diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-09-01 12:30:18 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-09-01 12:30:18 -0700 |
| commit | 8a26eb4b4e0e04efc8676c3317d997e175851e33 (patch) | |
| tree | 9e53954c91a0ab13ab608a5e8cf5a2754c07b70b | |
| parent | bc995c6ce883ca8dd77a5094a9f7e2937fa16535 (diff) | |
| download | patches-8a26eb4b4e0e04efc8676c3317d997e175851e33.tar.gz | |
new patches
23 files changed, 6473 insertions, 0 deletions
diff --git a/driver-core/driver-core-platform-use-drv-driver.bus-instead-of-assuming-platform_bus_type.patch b/driver-core/driver-core-platform-use-drv-driver.bus-instead-of-assuming-platform_bus_type.patch new file mode 100644 index 00000000000000..4bc68e72d53471 --- /dev/null +++ b/driver-core/driver-core-platform-use-drv-driver.bus-instead-of-assuming-platform_bus_type.patch @@ -0,0 +1,41 @@ +From ppannuto@codeaurora.org Wed Sep 1 11:48:10 2010 +From: Patrick Pannuto <ppannuto@codeaurora.org> +To: linux-kernel@vger.kernel.org +Cc: ppannuto@codeaurora.org, linux-arm-msm@vger.kernel.org, + Greg Kroah-Hartman <gregkh@suse.de>, + Magnus Damm <damm@opensource.se>, Paul Mundt <lethal@linux-sh.org>, + =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>, + "Rafael J. Wysocki" <rjw@sisk.pl> +Subject: driver core: platform: Use drv->driver.bus instead of assuming platform_bus_type +Date: Fri, 6 Aug 2010 17:12:41 -0700 +Message-Id: <1281139962-20538-1-git-send-email-ppannuto@codeaurora.org> + +In theory (although not *yet* in practice), a driver being passed +to platform_driver_probe might have driver.bus set to something +other than platform_bus_type. Locking drv->driver.bus is always +correct. + +Signed-off-by: Patrick Pannuto <ppannuto@codeaurora.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/base/platform.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -488,12 +488,12 @@ int __init_or_module platform_driver_pro + * if the probe was successful, and make sure any forced probes of + * new devices fail. + */ +- spin_lock(&platform_bus_type.p->klist_drivers.k_lock); ++ spin_lock(&drv->driver.bus->p->klist_drivers.k_lock); + drv->probe = NULL; + if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) + retval = -ENODEV; + drv->driver.probe = platform_drv_probe_fail; +- spin_unlock(&platform_bus_type.p->klist_drivers.k_lock); ++ spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); + + if (code != retval) + platform_driver_unregister(drv); diff --git a/driver-core/dynamic-debug-initialize-dynamic-debug-earlier-via-arch_initcall.patch b/driver-core/dynamic-debug-initialize-dynamic-debug-earlier-via-arch_initcall.patch new file mode 100644 index 00000000000000..51f501bd2ed7e1 --- /dev/null +++ b/driver-core/dynamic-debug-initialize-dynamic-debug-earlier-via-arch_initcall.patch @@ -0,0 +1,111 @@ +From trenn@suse.de Wed Sep 1 11:46:30 2010 +From: Thomas Renninger <trenn@suse.de> +To: penberg@cs.helsinki.fi, jbaron@redhat.com, greg@kroah.com +Cc: trenn@suse.de, linux-acpi@vger.kernel.org, greg@kroah.com +Subject: Dynamic Debug: Initialize dynamic debug earlier via arch_initcall +Date: Fri, 6 Aug 2010 16:11:03 +0200 +Message-Id: <1281103864-18860-4-git-send-email-trenn@suse.de> + +Having the ddebug_query= boot parameter it makes sense to set up +dynamic debug as soon as possible. + +I expect sysfs files cannot be set up via an arch_initcall, because +this one is even before fs_initcall. Therefore I splitted the +dynamic_debug_init function into an early one and a later one providing +/sys/../dynamic_debug/control file. + +Possibly dynamic_debug can be initialized even earlier, not sure whether +this still makes sense then. I picked up arch_initcall as it covers +quite a lot already. + +Dynamic debug needs to allocate memory, therefore it's not easily possible to +set it up even before the command line gets parsed. +Therefore the boot param query string is stored in a temp string which is +applied when dynamic debug gets set up. + +This has been tested with ddebug_query="file ec.c +p" +and I could retrieve pr_debug() messages early at boot during ACPI setup: +ACPI: EC: Look up EC in DSDT +ACPI: EC: ---> status = 0x08 +ACPI: EC: transaction start +ACPI: EC: <--- command = 0x80 +ACPI: EC: ~~~> interrupt +ACPI: EC: ---> status = 0x08 +ACPI: EC: <--- data = 0xa4 +... +ACPI: Interpreter enabled +ACPI: (supports S0 S3 S4 S5) +ACPI: Using IOAPIC for interrupt routing +ACPI: EC: ---> status = 0x00 +ACPI: EC: transaction start +ACPI: EC: <--- command = 0x80 + + +Signed-off-by: Thomas Renninger <trenn@suse.de> +Acked-by: jbaron@redhat.com +Acked-by: Pekka Enberg <penberg@cs.helsinki.fi> +CC: linux-acpi@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + lib/dynamic_debug.c | 33 +++++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +--- a/lib/dynamic_debug.c ++++ b/lib/dynamic_debug.c +@@ -748,13 +748,14 @@ static void ddebug_remove_all_tables(voi + mutex_unlock(&ddebug_lock); + } + +-static int __init dynamic_debug_init(void) ++static __initdata int ddebug_init_success; ++ ++static int __init dynamic_debug_init_debugfs(void) + { + struct dentry *dir, *file; +- struct _ddebug *iter, *iter_start; +- const char *modname = NULL; +- int ret = 0; +- int n = 0; ++ ++ if (!ddebug_init_success) ++ return -ENODEV; + + dir = debugfs_create_dir("dynamic_debug", NULL); + if (!dir) +@@ -765,6 +766,16 @@ static int __init dynamic_debug_init(voi + debugfs_remove(dir); + return -ENOMEM; + } ++ return 0; ++} ++ ++static int __init dynamic_debug_init(void) ++{ ++ struct _ddebug *iter, *iter_start; ++ const char *modname = NULL; ++ int ret = 0; ++ int n = 0; ++ + if (__start___verbose != __stop___verbose) { + iter = __start___verbose; + modname = iter->modname; +@@ -795,11 +806,13 @@ static int __init dynamic_debug_init(voi + } + + out_free: +- if (ret) { ++ if (ret) + ddebug_remove_all_tables(); +- debugfs_remove(dir); +- debugfs_remove(file); +- } ++ else ++ ddebug_init_success = 1; + return 0; + } +-module_init(dynamic_debug_init); ++/* Allow early initialization for boot messages via boot param */ ++arch_initcall(dynamic_debug_init); ++/* Debugfs setup must be done later */ ++module_init(dynamic_debug_init_debugfs); diff --git a/driver-core/dynamic-debug-introduce-ddebug_query-boot-parameter.patch b/driver-core/dynamic-debug-introduce-ddebug_query-boot-parameter.patch new file mode 100644 index 00000000000000..c79b1436a0ad3c --- /dev/null +++ b/driver-core/dynamic-debug-introduce-ddebug_query-boot-parameter.patch @@ -0,0 +1,134 @@ +From trenn@suse.de Wed Sep 1 11:46:15 2010 +From: Thomas Renninger <trenn@suse.de> +To: penberg@cs.helsinki.fi, jbaron@redhat.com, greg@kroah.com +Cc: trenn@suse.de, greg@kroah.com +Subject: Dynamic Debug: Introduce ddebug_query= boot parameter +Date: Fri, 6 Aug 2010 16:11:02 +0200 +Message-Id: <1281103864-18860-3-git-send-email-trenn@suse.de> + +Dynamic debug lacks the ability to enable debug messages at boot time. +One could patch initramfs or service startup scripts to write to +/sys/../dynamic_debug/control, but this sucks. + +This patch makes it possible to pass a query in the same format one can +write to /sys/../dynamic_debug/control via boot param. +When dynamic debug gets initialized, this query will automatically be +applied. + + +Signed-off-by: Thomas Renninger <trenn@suse.de> +Acked-by: jbaron@redhat.com +Acked-by: Pekka Enberg <penberg@cs.helsinki.fi> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + Documentation/dynamic-debug-howto.txt | 22 +++++++++++++++++++++- + Documentation/kernel-parameters.txt | 7 ++++++- + lib/dynamic_debug.c | 25 +++++++++++++++++++++++++ + 3 files changed, 52 insertions(+), 2 deletions(-) + +--- a/Documentation/dynamic-debug-howto.txt ++++ b/Documentation/dynamic-debug-howto.txt +@@ -24,7 +24,7 @@ Dynamic debug has even more useful featu + read to display the complete list of known debug statements, to help guide you + + Controlling dynamic debug Behaviour +-=============================== ++=================================== + + The behaviour of pr_debug()/dev_debug()s are controlled via writing to a + control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs +@@ -212,6 +212,26 @@ Note the regexp ^[-+=][scp]+$ matches a + Note also that there is no convenient syntax to remove all + the flags at once, you need to use "-psc". + ++ ++Debug messages during boot process ++================================== ++ ++To be able to activate debug messages during the boot process, ++even before userspace and debugfs exists, use the boot parameter: ++ddebug_query="QUERY" ++ ++QUERY follows the syntax described above, but must not exceed 1023 ++characters. The enablement of debug messages is done as an arch_initcall. ++Thus you can enable debug messages in all code processed after this ++arch_initcall via this boot parameter. ++On an x86 system for example ACPI enablement is a subsys_initcall and ++ddebug_query="file ec.c +p" ++will show early Embedded Controller transactions during ACPI setup if ++your machine (typically a laptop) has an Embedded Controller. ++PCI (or other devices) initialization also is a hot candidate for using ++this boot parameter for debugging purposes. ++ ++ + Examples + ======== + +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -43,10 +43,11 @@ parameter is applicable: + AVR32 AVR32 architecture is enabled. + AX25 Appropriate AX.25 support is enabled. + BLACKFIN Blackfin architecture is enabled. +- DRM Direct Rendering Management support is enabled. + EDD BIOS Enhanced Disk Drive Services (EDD) is enabled + EFI EFI Partitioning (GPT) is enabled + EIDE EIDE/ATAPI support is enabled. ++ DRM Direct Rendering Management support is enabled. ++ DYNAMIC_DEBUG Build in debug messages and enable them at runtime + FB The frame buffer device is enabled. + GCOV GCOV profiling is enabled. + HW Appropriate hardware is enabled. +@@ -570,6 +571,10 @@ and is between 256 and 4096 characters. + Format: <port#>,<type> + See also Documentation/input/joystick-parport.txt + ++ ddebug_query= [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot ++ time. See Documentation/dynamic-debug-howto.txt for ++ details. ++ + debug [KNL] Enable kernel debugging (events log level). + + debug_locks_verbose= +--- a/lib/dynamic_debug.c ++++ b/lib/dynamic_debug.c +@@ -450,6 +450,19 @@ static int ddebug_exec_query(char *query + return 0; + } + ++static __initdata char ddebug_setup_string[1024]; ++static __init int ddebug_setup_query(char *str) ++{ ++ if (strlen(str) >= 1024) { ++ pr_warning("ddebug boot param string too large\n"); ++ return 0; ++ } ++ strcpy(ddebug_setup_string, str); ++ return 1; ++} ++ ++__setup("ddebug_query=", ddebug_setup_query); ++ + /* + * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the + * command text from userspace, parses and executes it. +@@ -769,6 +782,18 @@ static int __init dynamic_debug_init(voi + } + ret = ddebug_add_module(iter_start, n, modname); + } ++ ++ /* ddebug_query boot param got passed -> set it up */ ++ if (ddebug_setup_string[0] != '\0') { ++ ret = ddebug_exec_query(ddebug_setup_string); ++ if (ret) ++ pr_warning("Invalid ddebug boot param %s", ++ ddebug_setup_string); ++ else ++ pr_info("ddebug initialized with string %s", ++ ddebug_setup_string); ++ } ++ + out_free: + if (ret) { + ddebug_remove_all_tables(); diff --git a/driver-core/dynamic-debug-introduce-global-fake-module-param-module.ddebug.patch b/driver-core/dynamic-debug-introduce-global-fake-module-param-module.ddebug.patch new file mode 100644 index 00000000000000..9e8f4adde4c9dc --- /dev/null +++ b/driver-core/dynamic-debug-introduce-global-fake-module-param-module.ddebug.patch @@ -0,0 +1,172 @@ +From trenn@suse.de Wed Sep 1 11:46:46 2010 +From: Thomas Renninger <trenn@suse.de> +To: penberg@cs.helsinki.fi, jbaron@redhat.com, greg@kroah.com +Cc: trenn@suse.de, greg@kroah.com +Subject: Dynamic Debug: Introduce global fake module param module.ddebug +Date: Fri, 6 Aug 2010 16:11:04 +0200 +Message-Id: <1281103864-18860-5-git-send-email-trenn@suse.de> + +Dynamic Debug allows enabling of pr_debug or KERN_DEBUG messages at runtime. +This is controlled via /sys/kernel/debug/dynamic_debug/control. +One major drawback is that the whole initialization of a module cannot be +tracked, because ddebug is only aware of debug strings of loaded modules. +But this is the most interesting part... + +This patch introduces a fake module parameter module.ddebug(not shown in +/sys/module/*/parameters, thus it does not use any resources/memory). + +If a module passes ddebug as a module parameter (e.g. via module.ddebug +kernel boot param or via "modprobe module ddebug"), all debug strings of this +module get activated by issuing "module module_name +p" internally +(not via sysfs) when the module gets loaded. + +Possible enhancements for the future if ddebug might get extended with +further flags: +module.ddebug=flags +Then module.ddebug="p" would be the same as module.ddebug, but if there +is a "x" ddebug flag added, one could pass: +module.ddebug="xp" +which would result in such a dynamic debug query: +module module_name +xp + +Modules must not use "ddebug" as module parameter or it will get ignored. +If it's tried, a warning will show up at module load time that it will get +ignored (this is the only part which got added late and is compile tested only). + +Tested with (additional added pr_debug messages): +options hp-wmi ddebug +in modprobe.conf +-> works and pr_debug messages issued at module initialization time show +up. Also "p" flag gets set for the whole hp-wmi module: +grep hp-wmi /sys/../dynamic_debug/control + +Signed-off-by: Thomas Renninger <trenn@suse.de> +Acked-by: Jason Baron <jbaron@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + Documentation/dynamic-debug-howto.txt | 28 +++++++++++++++++++++++++++- + include/linux/dynamic_debug.h | 5 +++++ + kernel/params.c | 17 ++++++++++++++++- + lib/dynamic_debug.c | 2 +- + 4 files changed, 49 insertions(+), 3 deletions(-) + +--- a/Documentation/dynamic-debug-howto.txt ++++ b/Documentation/dynamic-debug-howto.txt +@@ -213,7 +213,7 @@ Note also that there is no convenient sy + the flags at once, you need to use "-psc". + + +-Debug messages during boot process ++Debug Messages during Boot Process + ================================== + + To be able to activate debug messages during the boot process, +@@ -232,6 +232,32 @@ PCI (or other devices) initialization al + this boot parameter for debugging purposes. + + ++Debug Messages at Module Initialization Time ++============================================ ++ ++Enabling debug messages inside a module is only possible if the module itself ++is loaded already. If you unload a module, the dynamic debug flags associated ++to its debug messages are lost. ++Therefore, enabling debug messages that get processed at module initialization ++time through the <debugfs>/dynamic_debug/control interface is not possible. ++Instead, a "ddebug" module paramter can be passed: ++ ++ - via kernel boot parameter: ++ module.ddebug ++ ++ - as an ordinary module parameter via modprobe ++ modprobe module ddebug ++ ++ - or the parameter can be used permanently via modprobe.conf(.local) ++ options module ddebug ++ ++The ddebug option is not implemented as an ordinary module parameter and thus ++will not show up in /sys/module/module_name/parameters/ddebug ++The settings can get reverted through the sysfs interface again when the ++module got loaded as soon as debug messages are not needed anymore: ++echo "module module_name -p" > <debugfs>/dynamic_debug/control ++as described in the "Command Language Reference" chapter above. ++ + Examples + ======== + +--- a/include/linux/dynamic_debug.h ++++ b/include/linux/dynamic_debug.h +@@ -41,6 +41,7 @@ int ddebug_add_module(struct _ddebug *ta + + #if defined(CONFIG_DYNAMIC_DEBUG) + extern int ddebug_remove_module(const char *mod_name); ++extern int ddebug_exec_query(char *query_string); + + #define __dynamic_dbg_enabled(dd) ({ \ + int __ret = 0; \ +@@ -77,6 +78,10 @@ static inline int ddebug_remove_module(c + { + return 0; + } ++static inline int ddebug_exec_query(char *query_string) ++{ ++ return 0; ++} + + #define dynamic_pr_debug(fmt, ...) \ + do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0) +--- a/kernel/params.c ++++ b/kernel/params.c +@@ -24,6 +24,7 @@ + #include <linux/err.h> + #include <linux/slab.h> + #include <linux/ctype.h> ++#include <linux/dynamic_debug.h> + + #if 0 + #define DEBUGP printk +@@ -175,10 +176,17 @@ int parse_args(const char *name, + unsigned num, + int (*unknown)(char *param, char *val)) + { +- char *param, *val; ++ char *param, *val, ddebug[1024]; ++ int i; + + DEBUGP("Parsing ARGS: %s\n", args); + ++ for (i = 0; i < num; i++) { ++ if (parameq("ddebug", params[i].name)) ++ pr_warning("Module %s uses reserved keyword *ddebug* as" ++ "parameter which will get ignored\n", name); ++ } ++ + /* Chew leading spaces */ + args = skip_spaces(args); + +@@ -187,6 +195,13 @@ int parse_args(const char *name, + int irq_was_disabled; + + args = next_arg(args, ¶m, &val); ++ ++ if (parameq(param, "ddebug")) { ++ snprintf(ddebug, "module %s +p", name, 1024); ++ ddebug_exec_query(ddebug); ++ continue; ++ } ++ + irq_was_disabled = irqs_disabled(); + ret = parse_one(param, val, params, num, unknown); + if (irq_was_disabled && !irqs_disabled()) { +--- a/lib/dynamic_debug.c ++++ b/lib/dynamic_debug.c +@@ -429,7 +429,7 @@ static int ddebug_parse_flags(const char + return 0; + } + +-static int ddebug_exec_query(char *query_string) ++int ddebug_exec_query(char *query_string) + { + unsigned int flags = 0, mask = 0; + struct ddebug_query query; diff --git a/driver-core/dynamic-debug-split-out-query-string-parsing-setup-from-proc_write.patch b/driver-core/dynamic-debug-split-out-query-string-parsing-setup-from-proc_write.patch new file mode 100644 index 00000000000000..4c9cea2ac17b7f --- /dev/null +++ b/driver-core/dynamic-debug-split-out-query-string-parsing-setup-from-proc_write.patch @@ -0,0 +1,86 @@ +From trenn@suse.de Wed Sep 1 11:46:00 2010 +From: Thomas Renninger <trenn@suse.de> +To: penberg@cs.helsinki.fi, jbaron@redhat.com, greg@kroah.com +Cc: trenn@suse.de, greg@kroah.com +Subject: Dynamic Debug: Split out query string parsing/setup from proc_write +Date: Fri, 6 Aug 2010 16:11:01 +0200 +Message-Id: <1281103864-18860-2-git-send-email-trenn@suse.de> + +The parsing and applying of dynamic debug strings is not only useful for +/sys/../dynamic_debug/control write access, but can also be used for +boot parameter parsing. +The boot parameter is introduced in a follow up patch. + +Signed-off-by: Thomas Renninger <trenn@suse.de> +Acked-by: jbaron@redhat.com +Acked-by: Pekka Enberg <penberg@cs.helsinki.fi> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + lib/dynamic_debug.c | 40 +++++++++++++++++++++++++--------------- + 1 file changed, 25 insertions(+), 15 deletions(-) + +--- a/lib/dynamic_debug.c ++++ b/lib/dynamic_debug.c +@@ -429,6 +429,27 @@ static int ddebug_parse_flags(const char + return 0; + } + ++static int ddebug_exec_query(char *query_string) ++{ ++ unsigned int flags = 0, mask = 0; ++ struct ddebug_query query; ++#define MAXWORDS 9 ++ int nwords; ++ char *words[MAXWORDS]; ++ ++ nwords = ddebug_tokenize(query_string, words, MAXWORDS); ++ if (nwords <= 0) ++ return -EINVAL; ++ if (ddebug_parse_query(words, nwords-1, &query)) ++ return -EINVAL; ++ if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) ++ return -EINVAL; ++ ++ /* actually go and implement the change */ ++ ddebug_change(&query, flags, mask); ++ return 0; ++} ++ + /* + * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the + * command text from userspace, parses and executes it. +@@ -436,12 +457,8 @@ static int ddebug_parse_flags(const char + static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) + { +- unsigned int flags = 0, mask = 0; +- struct ddebug_query query; +-#define MAXWORDS 9 +- int nwords; +- char *words[MAXWORDS]; + char tmpbuf[256]; ++ int ret; + + if (len == 0) + return 0; +@@ -455,16 +472,9 @@ static ssize_t ddebug_proc_write(struct + printk(KERN_INFO "%s: read %d bytes from userspace\n", + __func__, (int)len); + +- nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS); +- if (nwords <= 0) +- return -EINVAL; +- if (ddebug_parse_query(words, nwords-1, &query)) +- return -EINVAL; +- if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) +- return -EINVAL; +- +- /* actually go and implement the change */ +- ddebug_change(&query, flags, mask); ++ ret = ddebug_exec_query(tmpbuf); ++ if (ret) ++ return ret; + + *offp += len; + return len; @@ -8,6 +8,11 @@ gregkh/gkh-version.patch ################################# # Driver core patches for 2.6.36 ################################# +driver-core/dynamic-debug-split-out-query-string-parsing-setup-from-proc_write.patch +driver-core/dynamic-debug-introduce-ddebug_query-boot-parameter.patch +driver-core/dynamic-debug-initialize-dynamic-debug-earlier-via-arch_initcall.patch +driver-core/dynamic-debug-introduce-global-fake-module-param-module.ddebug.patch +driver-core/driver-core-platform-use-drv-driver.bus-instead-of-assuming-platform_bus_type.patch ################################# # TTY patches for 2.6.36 @@ -21,6 +26,17 @@ gregkh/gkh-version.patch ################################# # Staging patches for 2.6.36 ################################# +staging.current/staging-hv-fix-missing-functions-for-net_device_ops.patch +staging.current/staging-hv-fixed-bounce-kmap-problem-by-using-correct-index.patch +staging.current/staging-hv-fixed-the-value-of-the-64bit-hole-inside-ring-buffer.patch +staging.current/staging-hv-increased-storvsc-ringbuffer-and-max_io_requests.patch +staging.current/staging-spectra-needs-linux-slab.h.patch +staging.current/staging-comedi-das08_cs.c-fix-io_req_t-conversion.patch +staging.current/staging-rt2870sta-add-more-device-ids-from-vendor-drivers.patch +staging.current/staging-zram-free-device-memory-when-init-fails.patch +staging.current/staging-spectra-depend-on-x86_mrst.patch +staging.current/staging-octeon-depends-on-netdevices.patch +staging.current/staging-wlan-ng-explicitly-set-some-fields-in-cfg80211-interface.patch ##################################################################### @@ -42,8 +58,15 @@ gregkh/gkh-version.patch ################################### # USB stuff for after 2.6.36 is out ################################### +usb/usb-add-intel-langwell-usb-otg-transceiver-driver.patch +usb/usb-langwell-usb-client-driver-code-cleanup.patch +usb/usb-langwell-usb-client-endpoint-initialization.patch +usb/usb-langwell-usb-client-phy-low-power-mode-setting.patch +usb/usb-langwell-usb-client-remote-wakeup-support.patch +usb/usb-langwell-usb-client-driver-memory-handling.patch # staging stuff for next is now in the staging-next tree on git.kernel.org + diff --git a/staging.current/staging-comedi-das08_cs.c-fix-io_req_t-conversion.patch b/staging.current/staging-comedi-das08_cs.c-fix-io_req_t-conversion.patch new file mode 100644 index 00000000000000..653de3b493263f --- /dev/null +++ b/staging.current/staging-comedi-das08_cs.c-fix-io_req_t-conversion.patch @@ -0,0 +1,32 @@ +From andreas@infernal.debian.net Mon Aug 30 16:53:01 2010 +From: Andreas Bombe <aeb@debian.org> +To: linux-kernel@vger.kernel.org +Cc: Dominik Brodowski <linux@dominikbrodowski.net>, + Greg Kroah-Hartman <gregkh@suse.de>, devel@driverdev.osuosl.org, + Andreas Bombe <aeb@debian.org> +Subject: staging: comedi das08_cs.c: Fix io_req_t conversion +Date: Sat, 14 Aug 2010 03:24:22 +0200 +Message-Id: <1281749062-9907-1-git-send-email-aeb@debian.org> + +Commit 90abdc3b9 converted all PCMCIA users away from io_req_t. In +das08_cs.c the converted IO lines mask setting was added but the old +line using the now inexistent p_dev->io was not removed. + +Signed-off-by: Andreas Bombe <aeb@debian.org> +Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/comedi/drivers/das08_cs.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/staging/comedi/drivers/das08_cs.c ++++ b/drivers/staging/comedi/drivers/das08_cs.c +@@ -222,7 +222,6 @@ static int das08_pcmcia_config_loop(stru + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); +- p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; + if (io->nwin > 1) { diff --git a/staging.current/staging-hv-fix-missing-functions-for-net_device_ops.patch b/staging.current/staging-hv-fix-missing-functions-for-net_device_ops.patch new file mode 100644 index 00000000000000..61aad0560c5414 --- /dev/null +++ b/staging.current/staging-hv-fix-missing-functions-for-net_device_ops.patch @@ -0,0 +1,40 @@ +From devel-bounces@linuxdriverproject.org Tue Aug 3 12:16:38 2010 +From: Haiyang Zhang <haiyangz@microsoft.com> +Subject: staging: hv: Fix missing functions for net_device_ops +Date: Tue, 3 Aug 2010 19:15:31 +0000 +Message-ID: <1FB5E1D5CA062146B38059374562DF728380C37B@TK5EX14MBXC126.redmond.corp.microsoft.com> + +From: Haiyang Zhang <haiyangz@microsoft.com> + +Fix missing functions for net_device_ops. +It's a bug when porting the drivers from 2.6.27 to 2.6.32. In 2.6.27, +the default functions for Ethernet, like eth_change_mtu(), were assigned +by ether_setup(). But in 2.6.32, these function pointers moved to +net_device_ops structure and no longer be assigned in ether_setup(). So +we need to set these functions in our driver code. It will ensure the +MTU won't be set beyond 1500. Otherwise, this can cause an error on the +server side, because the HyperV linux driver doesn't support jumbo frame +yet. + +Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> +Signed-off-by: Hank Janssen <hjanssen@microsoft.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/staging/hv/netvsc_drv.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/staging/hv/netvsc_drv.c ++++ b/drivers/staging/hv/netvsc_drv.c +@@ -327,6 +327,9 @@ static const struct net_device_ops devic + .ndo_stop = netvsc_close, + .ndo_start_xmit = netvsc_start_xmit, + .ndo_set_multicast_list = netvsc_set_multicast_list, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_set_mac_address = eth_mac_addr, + }; + + static int netvsc_probe(struct device *device) diff --git a/staging.current/staging-hv-fixed-bounce-kmap-problem-by-using-correct-index.patch b/staging.current/staging-hv-fixed-bounce-kmap-problem-by-using-correct-index.patch new file mode 100644 index 00000000000000..c04ed93606d1eb --- /dev/null +++ b/staging.current/staging-hv-fixed-bounce-kmap-problem-by-using-correct-index.patch @@ -0,0 +1,43 @@ +From devel-bounces@linuxdriverproject.org Thu Aug 5 12:30:40 2010 +From: Hank Janssen <hjanssen@microsoft.com> +Subject: staging: hv: Fixed bounce kmap problem by using correct index +Date: Thu, 5 Aug 2010 19:29:44 +0000 +Message-ID: <8AFC7968D54FB448A30D8F38F259C56223FEC87F@TK5EX14MBXC114.redmond.corp.microsoft.com> +Cc: Haiyang Zhang <haiyangz@microsoft.com>, "'gregkh@suse.de'" <gregkh@suse.de> + +From: Hank Janssen <hjanssen@microsoft.com> + +Fixed bounce offset kmap problem by using correct index. +The symptom of the problem is that in some NAS appliances this problem +represents Itself by a unresponsive VM under a load with many clients writing +small files. + +Signed-off-by:Hank Janssen <hjanssen@microsoft.com> +Signed-off-by:Haiyang Zhang <haiyangz@microsoft.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/hv/storvsc_drv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/staging/hv/storvsc_drv.c ++++ b/drivers/staging/hv/storvsc_drv.c +@@ -495,7 +495,7 @@ static unsigned int copy_to_bounce_buffe + + /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */ + +- if (j == 0) ++ if (bounce_addr == 0) + bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0); + + while (srclen) { +@@ -556,7 +556,7 @@ static unsigned int copy_from_bounce_buf + destlen = orig_sgl[i].length; + /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */ + +- if (j == 0) ++ if (bounce_addr == 0) + bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0); + + while (destlen) { diff --git a/staging.current/staging-hv-fixed-the-value-of-the-64bit-hole-inside-ring-buffer.patch b/staging.current/staging-hv-fixed-the-value-of-the-64bit-hole-inside-ring-buffer.patch new file mode 100644 index 00000000000000..a5ce955c5b5f35 --- /dev/null +++ b/staging.current/staging-hv-fixed-the-value-of-the-64bit-hole-inside-ring-buffer.patch @@ -0,0 +1,43 @@ +From hjanssen@microsoft.com Thu Aug 5 12:30:06 2010 +From: Hank Janssen <hjanssen@microsoft.com> +Cc: Haiyang Zhang <haiyangz@microsoft.com>, + "'gregkh@suse.de'" <gregkh@suse.de> +Subject: staging: hv: Fixed the value of the 64bit-hole inside ring buffer +Date: Thu, 5 Aug 2010 19:30:01 +0000 +Message-ID: <8AFC7968D54FB448A30D8F38F259C56223FEC892@TK5EX14MBXC114.redmond.corp.microsoft.com> + +From: Haiyang Zhang <haiyangz@microsoft.com> + +Fixed the value of the 64bit-hole inside ring buffer, this +caused a problem on Hyper-V when running checked Windows builds. + +Checked builds of Windows are used internally and given to external +system integrators at times. They are builds that for example that all +elements in a structure follow the definition of that Structure. The bug +this fixed was for a field that we did not fill in at all (Because we do +Not use it on the Linux side), and the checked build of windows gives +errors on it internally to the Windows logs. + +This fixes that error. + +Signed-off-by:Hank Janssen <hjanssen@microsoft.com> +Signed-off-by:Haiyang Zhang <haiyangz@microsoft.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/hv/ring_buffer.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/staging/hv/ring_buffer.c ++++ b/drivers/staging/hv/ring_buffer.c +@@ -193,8 +193,7 @@ Description: + static inline u64 + GetRingBufferIndices(struct hv_ring_buffer_info *RingInfo) + { +- return ((u64)RingInfo->RingBuffer->WriteIndex << 32) +- || RingInfo->RingBuffer->ReadIndex; ++ return (u64)RingInfo->RingBuffer->WriteIndex << 32; + } + + diff --git a/staging.current/staging-hv-increased-storvsc-ringbuffer-and-max_io_requests.patch b/staging.current/staging-hv-increased-storvsc-ringbuffer-and-max_io_requests.patch new file mode 100644 index 00000000000000..6404960843bca3 --- /dev/null +++ b/staging.current/staging-hv-increased-storvsc-ringbuffer-and-max_io_requests.patch @@ -0,0 +1,47 @@ +From devel-bounces@linuxdriverproject.org Thu Aug 5 12:34:01 2010 +From: Hank Janssen <hjanssen@microsoft.com> +Subject: staging: hv: Increased storvsc ringbuffer and max_io_requests +Date: Thu, 5 Aug 2010 19:30:31 +0000 +Message-ID: <8AFC7968D54FB448A30D8F38F259C56223FEC89F@TK5EX14MBXC114.redmond.corp.microsoft.com> +Cc: Haiyang Zhang <haiyangz@microsoft.com>, "'gregkh@suse.de'" <gregkh@suse.de> + +From: Hank Janssen <hjanssen@microsoft.com> + +Increased storvsc ringbuffer and max_io_requests. This now more +closely mimics the numbers on Hyper-V. And will allow more IO requests +to take place for the SCSI driver. + +Max_IO is set to double from what it was before, Hyper-V allows it and +we have had appliance builder requests to see if it was a problem to +increase the number. + +Ringbuffer size for storvsc is now increased because I have seen A few buffer +problems on extremely busy systems. They were Set pretty low before. +And since max_io_requests is increased I Really needed to increase the buffer +as well. + + +Signed-off-by:Hank Janssen <hjanssen@microsoft.com> +Signed-off-by:Haiyang Zhang <haiyangz@microsoft.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/hv/storvsc_api.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/staging/hv/storvsc_api.h ++++ b/drivers/staging/hv/storvsc_api.h +@@ -28,10 +28,10 @@ + #include "vmbus_api.h" + + /* Defines */ +-#define STORVSC_RING_BUFFER_SIZE (10*PAGE_SIZE) ++#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) + #define BLKVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) + +-#define STORVSC_MAX_IO_REQUESTS 64 ++#define STORVSC_MAX_IO_REQUESTS 128 + + /* + * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In diff --git a/staging.current/staging-octeon-depends-on-netdevices.patch b/staging.current/staging-octeon-depends-on-netdevices.patch new file mode 100644 index 00000000000000..d6a4db3a8bf8f4 --- /dev/null +++ b/staging.current/staging-octeon-depends-on-netdevices.patch @@ -0,0 +1,37 @@ +From randy.dunlap@oracle.com Mon Aug 30 16:56:54 2010 +Date: Tue, 24 Aug 2010 14:09:40 -0700 +From: Randy Dunlap <randy.dunlap@oracle.com> +To: devel@driverdev.osuosl.org +Cc: gregkh@suse.de, support@caviumnetworks.com, + Arnaud Lacombe <lacombar@gmail.com> +Subject: Staging: octeon: depends on NETDEVICES +Message-Id: <20100824140940.57369e83.randy.dunlap@oracle.com> + +From: Randy Dunlap <randy.dunlap@oracle.com> + +OCTEON_ETHERNET should depend on NETDEVICES. + +Fixes this kconfig warning: + +warning: (NET_DSA && NET && EXPERIMENTAL && NETDEVICES && !S390 || ... +|| OCTEON_ETHERNET && STAGING && !STAGING_EXCLUDE_BUILD && CPU_CAVIUM_OCTEON) selects PHYLIB which has unmet direct dependencies (!S390 && NETDEVICES) + +Reported-by: Arnaud Lacombe <lacombar@gmail.com> +Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> +Cc: support@caviumnetworks.com +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/octeon/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/octeon/Kconfig ++++ b/drivers/staging/octeon/Kconfig +@@ -1,6 +1,6 @@ + config OCTEON_ETHERNET + tristate "Cavium Networks Octeon Ethernet support" +- depends on CPU_CAVIUM_OCTEON ++ depends on CPU_CAVIUM_OCTEON && NETDEVICES + select PHYLIB + select MDIO_OCTEON + help diff --git a/staging.current/staging-rt2870sta-add-more-device-ids-from-vendor-drivers.patch b/staging.current/staging-rt2870sta-add-more-device-ids-from-vendor-drivers.patch new file mode 100644 index 00000000000000..fe3e6208e6b814 --- /dev/null +++ b/staging.current/staging-rt2870sta-add-more-device-ids-from-vendor-drivers.patch @@ -0,0 +1,112 @@ +From ben@decadent.org.uk Mon Aug 30 16:53:26 2010 +Date: Sun, 29 Aug 2010 02:13:11 +0100 +From: Ben Hutchings <ben@decadent.org.uk> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: devel@driverdev.osuosl.org +Subject: Staging: rt2870sta: Add more device IDs from vendor drivers +Message-ID: <20100829011311.GU5063@decadent.org.uk> + +Taken from DPO_RT3070_LinuxSTA_V2.3.0.4_20100604.tar.bz2 and +2010_0709_RT2870_Linux_STA_v2.4.0.1.tar.bz2, with duplicates removed. + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/rt2860/usb_main_dev.c | 41 ++++++++++++++++++++++++++++++++-- + 1 file changed, 39 insertions(+), 2 deletions(-) + +--- a/drivers/staging/rt2860/usb_main_dev.c ++++ b/drivers/staging/rt2860/usb_main_dev.c +@@ -44,6 +44,7 @@ struct usb_device_id rtusb_usb_id[] = { + {USB_DEVICE(0x07B8, 0x2870)}, /* AboCom */ + {USB_DEVICE(0x07B8, 0x2770)}, /* AboCom */ + {USB_DEVICE(0x0DF6, 0x0039)}, /* Sitecom 2770 */ ++ {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom 2770 */ + {USB_DEVICE(0x083A, 0x7512)}, /* Arcadyan 2770 */ + {USB_DEVICE(0x0789, 0x0162)}, /* Logitec 2870 */ + {USB_DEVICE(0x0789, 0x0163)}, /* Logitec 2870 */ +@@ -95,7 +96,8 @@ struct usb_device_id rtusb_usb_id[] = { + {USB_DEVICE(0x050d, 0x815c)}, + {USB_DEVICE(0x1482, 0x3C09)}, /* Abocom */ + {USB_DEVICE(0x14B2, 0x3C09)}, /* Alpha */ +- {USB_DEVICE(0x04E8, 0x2018)}, /* samsung */ ++ {USB_DEVICE(0x04E8, 0x2018)}, /* samsung linkstick2 */ ++ {USB_DEVICE(0x1690, 0x0740)}, /* Askey */ + {USB_DEVICE(0x5A57, 0x0280)}, /* Zinwell */ + {USB_DEVICE(0x5A57, 0x0282)}, /* Zinwell */ + {USB_DEVICE(0x7392, 0x7718)}, +@@ -105,21 +107,34 @@ struct usb_device_id rtusb_usb_id[] = { + {USB_DEVICE(0x1737, 0x0071)}, /* Linksys WUSB600N */ + {USB_DEVICE(0x0411, 0x00e8)}, /* Buffalo WLI-UC-G300N */ + {USB_DEVICE(0x050d, 0x815c)}, /* Belkin F5D8053 */ ++ {USB_DEVICE(0x100D, 0x9031)}, /* Motorola 2770 */ + #endif /* RT2870 // */ + #ifdef RT3070 + {USB_DEVICE(0x148F, 0x3070)}, /* Ralink 3070 */ + {USB_DEVICE(0x148F, 0x3071)}, /* Ralink 3071 */ + {USB_DEVICE(0x148F, 0x3072)}, /* Ralink 3072 */ + {USB_DEVICE(0x0DB0, 0x3820)}, /* Ralink 3070 */ ++ {USB_DEVICE(0x0DB0, 0x871C)}, /* Ralink 3070 */ ++ {USB_DEVICE(0x0DB0, 0x822C)}, /* Ralink 3070 */ ++ {USB_DEVICE(0x0DB0, 0x871B)}, /* Ralink 3070 */ ++ {USB_DEVICE(0x0DB0, 0x822B)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DF6, 0x003E)}, /* Sitecom 3070 */ + {USB_DEVICE(0x0DF6, 0x0042)}, /* Sitecom 3072 */ ++ {USB_DEVICE(0x0DF6, 0x0048)}, /* Sitecom 3070 */ ++ {USB_DEVICE(0x0DF6, 0x0047)}, /* Sitecom 3071 */ + {USB_DEVICE(0x14B2, 0x3C12)}, /* AL 3070 */ + {USB_DEVICE(0x18C5, 0x0012)}, /* Corega 3070 */ + {USB_DEVICE(0x083A, 0x7511)}, /* Arcadyan 3070 */ ++ {USB_DEVICE(0x083A, 0xA701)}, /* SMC 3070 */ ++ {USB_DEVICE(0x083A, 0xA702)}, /* SMC 3072 */ + {USB_DEVICE(0x1740, 0x9703)}, /* EnGenius 3070 */ + {USB_DEVICE(0x1740, 0x9705)}, /* EnGenius 3071 */ + {USB_DEVICE(0x1740, 0x9706)}, /* EnGenius 3072 */ ++ {USB_DEVICE(0x1740, 0x9707)}, /* EnGenius 3070 */ ++ {USB_DEVICE(0x1740, 0x9708)}, /* EnGenius 3071 */ ++ {USB_DEVICE(0x1740, 0x9709)}, /* EnGenius 3072 */ + {USB_DEVICE(0x13D3, 0x3273)}, /* AzureWave 3070 */ ++ {USB_DEVICE(0x13D3, 0x3305)}, /* AzureWave 3070*/ + {USB_DEVICE(0x1044, 0x800D)}, /* Gigabyte GN-WB32L 3070 */ + {USB_DEVICE(0x2019, 0xAB25)}, /* Planex Communications, Inc. RT3070 */ + {USB_DEVICE(0x07B8, 0x3070)}, /* AboCom 3070 */ +@@ -132,14 +147,36 @@ struct usb_device_id rtusb_usb_id[] = { + {USB_DEVICE(0x07D1, 0x3C0D)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C0E)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C0F)}, /* D-Link 3070 */ ++ {USB_DEVICE(0x07D1, 0x3C16)}, /* D-Link 3070 */ ++ {USB_DEVICE(0x07D1, 0x3C17)}, /* D-Link 8070 */ + {USB_DEVICE(0x1D4D, 0x000C)}, /* Pegatron Corporation 3070 */ + {USB_DEVICE(0x1D4D, 0x000E)}, /* Pegatron Corporation 3070 */ + {USB_DEVICE(0x5A57, 0x5257)}, /* Zinwell 3070 */ + {USB_DEVICE(0x5A57, 0x0283)}, /* Zinwell 3072 */ + {USB_DEVICE(0x04BB, 0x0945)}, /* I-O DATA 3072 */ ++ {USB_DEVICE(0x04BB, 0x0947)}, /* I-O DATA 3070 */ ++ {USB_DEVICE(0x04BB, 0x0948)}, /* I-O DATA 3072 */ + {USB_DEVICE(0x203D, 0x1480)}, /* Encore 3070 */ ++ {USB_DEVICE(0x20B8, 0x8888)}, /* PARA INDUSTRIAL 3070 */ ++ {USB_DEVICE(0x0B05, 0x1784)}, /* Asus 3072 */ ++ {USB_DEVICE(0x203D, 0x14A9)}, /* Encore 3070*/ ++ {USB_DEVICE(0x0DB0, 0x899A)}, /* MSI 3070*/ ++ {USB_DEVICE(0x0DB0, 0x3870)}, /* MSI 3070*/ ++ {USB_DEVICE(0x0DB0, 0x870A)}, /* MSI 3070*/ ++ {USB_DEVICE(0x0DB0, 0x6899)}, /* MSI 3070 */ ++ {USB_DEVICE(0x0DB0, 0x3822)}, /* MSI 3070 */ ++ {USB_DEVICE(0x0DB0, 0x3871)}, /* MSI 3070 */ ++ {USB_DEVICE(0x0DB0, 0x871A)}, /* MSI 3070 */ ++ {USB_DEVICE(0x0DB0, 0x822A)}, /* MSI 3070 */ ++ {USB_DEVICE(0x0DB0, 0x3821)}, /* Ralink 3070 */ ++ {USB_DEVICE(0x0DB0, 0x821A)}, /* Ralink 3070 */ ++ {USB_DEVICE(0x083A, 0xA703)}, /* IO-MAGIC */ ++ {USB_DEVICE(0x13D3, 0x3307)}, /* Azurewave */ ++ {USB_DEVICE(0x13D3, 0x3321)}, /* Azurewave */ ++ {USB_DEVICE(0x07FA, 0x7712)}, /* Edimax */ ++ {USB_DEVICE(0x0789, 0x0166)}, /* Edimax */ ++ {USB_DEVICE(0x148F, 0x2070)}, /* Edimax */ + #endif /* RT3070 // */ +- {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom WL-608 */ + {USB_DEVICE(0x1737, 0x0077)}, /* Linksys WUSB54GC-EU v3 */ + {USB_DEVICE(0x2001, 0x3C09)}, /* D-Link */ + {USB_DEVICE(0x2001, 0x3C0A)}, /* D-Link 3072 */ diff --git a/staging.current/staging-spectra-depend-on-x86_mrst.patch b/staging.current/staging-spectra-depend-on-x86_mrst.patch new file mode 100644 index 00000000000000..02a2eeeb2d9b69 --- /dev/null +++ b/staging.current/staging-spectra-depend-on-x86_mrst.patch @@ -0,0 +1,29 @@ +From jeffm@suse.com Mon Aug 30 16:56:28 2010 +Message-ID: <4C73EF6A.5050603@suse.com> +Date: Tue, 24 Aug 2010 12:12:26 -0400 +From: Jeff Mahoney <jeffm@suse.com> +To: Greg Kroah-Hartman <GregKH@suse.de> +Subject: Staging: spectra: depend on X86_MRST + +lld_nand fails to build on arches without virt_to_bus. Since this driver +is specifically for hardware enablment on Moorestown, this patch adds +Moorestown MID support as a dependency. + +Signed-off-by: Jeff Mahoney <jeffm@suse.com> +Cc: David Woodhouse <dwmw2@infradead.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/spectra/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/staging/spectra/Kconfig ++++ b/drivers/staging/spectra/Kconfig +@@ -2,6 +2,7 @@ + menuconfig SPECTRA + tristate "Denali Spectra Flash Translation Layer" + depends on BLOCK ++ depends on X86_MRST + default n + ---help--- + Enable the FTL pseudo-filesystem used with the NAND Flash diff --git a/staging.current/staging-spectra-needs-linux-slab.h.patch b/staging.current/staging-spectra-needs-linux-slab.h.patch new file mode 100644 index 00000000000000..07ad0c9d4d10ba --- /dev/null +++ b/staging.current/staging-spectra-needs-linux-slab.h.patch @@ -0,0 +1,36 @@ +From geert@linux-m68k.org Mon Aug 30 16:52:22 2010 +Date: Mon, 30 Aug 2010 08:57:49 +0200 (CEST) +From: Geert Uytterhoeven <geert@linux-m68k.org> +To: Greg Kroah-Hartman <gregkh@suse.de> +Subject: staging: spectra needs <linux/slab.h> +Message-ID: <alpine.DEB.2.00.1008300856010.28212@ayla.of.borg> + +On one of my m68k test builds I get: + +drivers/staging/spectra/ffsport.c: In function ‘ioctl_read_page_data’: +drivers/staging/spectra/ffsport.c:196: error: implicit declaration of function ‘kmalloc’ +drivers/staging/spectra/ffsport.c:196: warning: assignment makes pointer from integer without a cast +drivers/staging/spectra/ffsport.c:212: error: implicit declaration of function ‘kfree’ +drivers/staging/spectra/ffsport.c: In function ‘ioctl_write_page_data’: +drivers/staging/spectra/ffsport.c:229: warning: assignment makes pointer from integer without a cast +drivers/staging/spectra/ffsport.c: In function ‘SBD_setup_device’: +drivers/staging/spectra/ffsport.c:637: warning: assignment makes pointer from integer without a cast + +Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> +Acked-by: Pekka Enberg <penberg@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/spectra/ffsport.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/staging/spectra/ffsport.c ++++ b/drivers/staging/spectra/ffsport.c +@@ -28,6 +28,7 @@ + #include <linux/log2.h> + #include <linux/init.h> + #include <linux/smp_lock.h> ++#include <linux/slab.h> + + /**** Helper functions used for Div, Remainder operation on u64 ****/ + diff --git a/staging.current/staging-wlan-ng-explicitly-set-some-fields-in-cfg80211-interface.patch b/staging.current/staging-wlan-ng-explicitly-set-some-fields-in-cfg80211-interface.patch new file mode 100644 index 00000000000000..c7b993b4235089 --- /dev/null +++ b/staging.current/staging-wlan-ng-explicitly-set-some-fields-in-cfg80211-interface.patch @@ -0,0 +1,39 @@ +From karllinuxtest.relton@ntlworld.com Wed Sep 1 11:36:50 2010 +Subject: Staging: wlan-ng: Explicitly set some fields in cfg80211 interface +From: Karl Relton <karllinuxtest.relton@ntlworld.com> +To: Greg KH <greg@kroah.com> +Cc: linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org +Date: Wed, 11 Aug 2010 18:16:08 +0100 +Message-ID: <1281546968.2010.5.camel@dellpc> + + +The cfg80211 api has introduced a few new fields. Rather than assume +what cfg80211 api does by default, set these explicitly. + +Signed-off-by: Karl Relton <karllinuxtest.relton@ntlworld.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/staging/wlan-ng/cfg80211.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/staging/wlan-ng/cfg80211.c ++++ b/drivers/staging/wlan-ng/cfg80211.c +@@ -219,6 +219,7 @@ int prism2_get_key(struct wiphy *wiphy, + return -ENOENT; + params.key_len = len; + params.key = wlandev->wep_keys[key_index]; ++ params.seq_len = 0; + + callback(cookie, ¶ms); + +@@ -735,6 +736,8 @@ struct wiphy *wlan_create_wiphy(struct d + priv->band.n_channels = ARRAY_SIZE(prism2_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(prism2_rates); ++ priv->band.band = IEEE80211_BAND_2GHZ; ++ priv->band.ht_cap.ht_supported = false; + wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + set_wiphy_dev(wiphy, dev); diff --git a/staging.current/staging-zram-free-device-memory-when-init-fails.patch b/staging.current/staging-zram-free-device-memory-when-init-fails.patch new file mode 100644 index 00000000000000..8e908e6fb76fa0 --- /dev/null +++ b/staging.current/staging-zram-free-device-memory-when-init-fails.patch @@ -0,0 +1,26 @@ +From linux-next-owner@vger.kernel.org Mon Aug 30 16:55:05 2010 +Date: Sat, 28 Aug 2010 10:09:05 +0300 +From: Shahar Havivi <shaharh@redhat.com> +To: linux-next@vger.kernel.org +Cc: linux-kernel@vger.kernel.org, greg@kroah.com +Subject: Staging: zram: free device memory when init fails +Message-ID: <20100828070901.GA31943@redhat.com> +Content-Disposition: inline + +Signed-off-by: Shahar Havivi <shaharh@redhat.com> +Cc: Nitin Gupta <ngupta@vflare.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/zram/zram_drv.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/staging/zram/zram_drv.c ++++ b/drivers/staging/zram/zram_drv.c +@@ -769,6 +769,7 @@ static int __init zram_init(void) + free_devices: + while (dev_id) + destroy_device(&devices[--dev_id]); ++ kfree(devices); + unregister: + unregister_blkdev(zram_major, "zram"); + out: diff --git a/usb/usb-add-intel-langwell-usb-otg-transceiver-driver.patch b/usb/usb-add-intel-langwell-usb-otg-transceiver-driver.patch new file mode 100644 index 00000000000000..e9d2c754b5bb75 --- /dev/null +++ b/usb/usb-add-intel-langwell-usb-otg-transceiver-driver.patch @@ -0,0 +1,2613 @@ +From linux-usb-owner@vger.kernel.org Wed Sep 1 11:39:27 2010 +From: Hao Wu <hao.wu@intel.com> +Subject: usb: Add Intel Langwell USB OTG Transceiver Driver +To: linux-usb@vger.kernel.org +Date: Thu, 05 Aug 2010 14:17:28 +0100 +Message-ID: <20100805131726.12473.94642.stgit@localhost.localdomain> + +From: Hao Wu <hao.wu@intel.com> + +This adds support for the USB transceiver driver in the Langwell chipset used +on the Intel MID platforms. It folds up the original patch set which includes +basic support for the device, PHY low power mode (Please notice that there is +a limitation, after we drive VBus down, 2ms delay is required from SCU FW to +sync up OTGSC register with USBCFG register), software timers (the hardware +timers do not work in low power mode), HNP, SRP. + + +Signed-off-by: Hao Wu <hao.wu@intel.com> +Signed-off-by: Alek Du <alek.du@intel.com> +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/otg/Kconfig | 14 + drivers/usb/otg/Makefile | 1 + drivers/usb/otg/langwell_otg.c | 2408 +++++++++++++++++++++++++++++++++++++++ + include/linux/usb/langwell_otg.h | 139 ++ + 4 files changed, 2562 insertions(+) + +--- a/drivers/usb/otg/Kconfig ++++ b/drivers/usb/otg/Kconfig +@@ -67,4 +67,18 @@ config NOP_USB_XCEIV + built-in with usb ip or which are autonomous and doesn't require any + phy programming such as ISP1x04 etc. + ++config USB_LANGWELL_OTG ++ tristate "Intel Langwell USB OTG dual-role support" ++ depends on USB && X86_MRST ++ select USB_OTG ++ select USB_OTG_UTILS ++ help ++ Say Y here if you want to build Intel Langwell USB OTG ++ transciever driver in kernel. This driver implements role ++ switch between EHCI host driver and Langwell USB OTG ++ client driver. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called langwell_otg. ++ + endif # USB || OTG +--- a/drivers/usb/otg/Makefile ++++ b/drivers/usb/otg/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o + obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o + obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o + obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o ++obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o + obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o + obj-$(CONFIG_USB_ULPI) += ulpi.o + +--- /dev/null ++++ b/drivers/usb/otg/langwell_otg.c +@@ -0,0 +1,2408 @@ ++/* ++ * Intel Langwell USB OTG transceiver driver ++ * Copyright (C) 2008 - 2009, Intel Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope 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 St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++/* This driver helps to switch Langwell OTG controller function between host ++ * and peripheral. It works with EHCI driver and Langwell client controller ++ * driver together. ++ */ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/pci.h> ++#include <linux/errno.h> ++#include <linux/interrupt.h> ++#include <linux/kernel.h> ++#include <linux/device.h> ++#include <linux/moduleparam.h> ++#include <linux/usb/ch9.h> ++#include <linux/usb/gadget.h> ++#include <linux/usb.h> ++#include <linux/usb/otg.h> ++#include <linux/usb/hcd.h> ++#include <linux/notifier.h> ++#include <linux/delay.h> ++#include <asm/intel_scu_ipc.h> ++ ++#include <linux/usb/langwell_otg.h> ++ ++#define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" ++#define DRIVER_VERSION "3.0.0.32L.0003" ++ ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>"); ++MODULE_VERSION(DRIVER_VERSION); ++MODULE_LICENSE("GPL"); ++ ++static const char driver_name[] = "langwell_otg"; ++ ++static int langwell_otg_probe(struct pci_dev *pdev, ++ const struct pci_device_id *id); ++static void langwell_otg_remove(struct pci_dev *pdev); ++static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); ++static int langwell_otg_resume(struct pci_dev *pdev); ++ ++static int langwell_otg_set_host(struct otg_transceiver *otg, ++ struct usb_bus *host); ++static int langwell_otg_set_peripheral(struct otg_transceiver *otg, ++ struct usb_gadget *gadget); ++static int langwell_otg_start_srp(struct otg_transceiver *otg); ++ ++static const struct pci_device_id pci_ids[] = {{ ++ .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), ++ .class_mask = ~0, ++ .vendor = 0x8086, ++ .device = 0x0811, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++}, { /* end: all zeroes */ } ++}; ++ ++static struct pci_driver otg_pci_driver = { ++ .name = (char *) driver_name, ++ .id_table = pci_ids, ++ ++ .probe = langwell_otg_probe, ++ .remove = langwell_otg_remove, ++ ++ .suspend = langwell_otg_suspend, ++ .resume = langwell_otg_resume, ++}; ++ ++static const char *state_string(enum usb_otg_state state) ++{ ++ switch (state) { ++ case OTG_STATE_A_IDLE: ++ return "a_idle"; ++ case OTG_STATE_A_WAIT_VRISE: ++ return "a_wait_vrise"; ++ case OTG_STATE_A_WAIT_BCON: ++ return "a_wait_bcon"; ++ case OTG_STATE_A_HOST: ++ return "a_host"; ++ case OTG_STATE_A_SUSPEND: ++ return "a_suspend"; ++ case OTG_STATE_A_PERIPHERAL: ++ return "a_peripheral"; ++ case OTG_STATE_A_WAIT_VFALL: ++ return "a_wait_vfall"; ++ case OTG_STATE_A_VBUS_ERR: ++ return "a_vbus_err"; ++ case OTG_STATE_B_IDLE: ++ return "b_idle"; ++ case OTG_STATE_B_SRP_INIT: ++ return "b_srp_init"; ++ case OTG_STATE_B_PERIPHERAL: ++ return "b_peripheral"; ++ case OTG_STATE_B_WAIT_ACON: ++ return "b_wait_acon"; ++ case OTG_STATE_B_HOST: ++ return "b_host"; ++ default: ++ return "UNDEFINED"; ++ } ++} ++ ++/* HSM timers */ ++static inline struct langwell_otg_timer *otg_timer_initializer ++(void (*function)(unsigned long), unsigned long expires, unsigned long data) ++{ ++ struct langwell_otg_timer *timer; ++ timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); ++ if (timer == NULL) ++ return timer; ++ ++ timer->function = function; ++ timer->expires = expires; ++ timer->data = data; ++ return timer; ++} ++ ++static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr, ++ *b_se0_srp_tmr, *b_srp_init_tmr; ++ ++static struct list_head active_timers; ++ ++static struct langwell_otg *the_transceiver; ++ ++/* host/client notify transceiver when event affects HNP state */ ++void langwell_update_transceiver(void) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ ++ dev_dbg(lnw->dev, "transceiver is updated\n"); ++ ++ if (!lnw->qwork) ++ return ; ++ ++ queue_work(lnw->qwork, &lnw->work); ++} ++EXPORT_SYMBOL(langwell_update_transceiver); ++ ++static int langwell_otg_set_host(struct otg_transceiver *otg, ++ struct usb_bus *host) ++{ ++ otg->host = host; ++ ++ return 0; ++} ++ ++static int langwell_otg_set_peripheral(struct otg_transceiver *otg, ++ struct usb_gadget *gadget) ++{ ++ otg->gadget = gadget; ++ ++ return 0; ++} ++ ++static int langwell_otg_set_power(struct otg_transceiver *otg, ++ unsigned mA) ++{ ++ return 0; ++} ++ ++/* A-device drives vbus, controlled through PMIC CHRGCNTL register*/ ++static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ u8 r; ++ ++ dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off"); ++ ++ /* FIXME: surely we should cache this on the first read. If not use ++ readv to avoid two transactions */ ++ if (intel_scu_ipc_ioread8(0x00, &r) < 0) { ++ dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2"); ++ return -EBUSY; ++ } ++ if ((r & 0x03) != 0x02) { ++ dev_dbg(lnw->dev, "not NEC PMIC attached\n"); ++ return -EBUSY; ++ } ++ ++ if (intel_scu_ipc_ioread8(0x20, &r) < 0) { ++ dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2"); ++ return -EBUSY; ++ } ++ ++ if ((r & 0x20) == 0) { ++ dev_dbg(lnw->dev, "no battery attached\n"); ++ return -EBUSY; ++ } ++ ++ /* Workaround for battery attachment issue */ ++ if (r == 0x34) { ++ dev_dbg(lnw->dev, "no battery attached on SH\n"); ++ return -EBUSY; ++ } ++ ++ dev_dbg(lnw->dev, "battery attached. 2 reg = %x\n", r); ++ ++ /* workaround: FW detect writing 0x20/0xc0 to d4 event. ++ * this is only for NEC PMIC. ++ */ ++ ++ if (intel_scu_ipc_iowrite8(0xD4, enabled ? 0x20 : 0xC0)) ++ dev_dbg(lnw->dev, "Failed to write PMIC.\n"); ++ ++ dev_dbg(lnw->dev, "%s --->\n", __func__); ++ ++ return 0; ++} ++ ++/* charge vbus or discharge vbus through a resistor to ground */ ++static void langwell_otg_chrg_vbus(int on) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ u32 val; ++ ++ val = readl(lnw->iotg.base + CI_OTGSC); ++ ++ if (on) ++ writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, ++ lnw->iotg.base + CI_OTGSC); ++ else ++ writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, ++ lnw->iotg.base + CI_OTGSC); ++} ++ ++/* Start SRP */ ++static int langwell_otg_start_srp(struct otg_transceiver *otg) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ u32 val; ++ ++ dev_dbg(lnw->dev, "%s --->\n", __func__); ++ ++ val = readl(iotg->base + CI_OTGSC); ++ ++ writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, ++ iotg->base + CI_OTGSC); ++ ++ /* Check if the data plus is finished or not */ ++ msleep(8); ++ val = readl(iotg->base + CI_OTGSC); ++ if (val & (OTGSC_HADP | OTGSC_DP)) ++ dev_dbg(lnw->dev, "DataLine SRP Error\n"); ++ ++ /* Disable interrupt - b_sess_vld */ ++ val = readl(iotg->base + CI_OTGSC); ++ val &= (~(OTGSC_BSVIE | OTGSC_BSEIE)); ++ writel(val, iotg->base + CI_OTGSC); ++ ++ /* Start VBus SRP, drive vbus to generate VBus pulse */ ++ iotg->otg.set_vbus(&iotg->otg, true); ++ msleep(15); ++ iotg->otg.set_vbus(&iotg->otg, false); ++ ++ /* Enable interrupt - b_sess_vld*/ ++ val = readl(iotg->base + CI_OTGSC); ++ dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val); ++ ++ val |= (OTGSC_BSVIE | OTGSC_BSEIE); ++ writel(val, iotg->base + CI_OTGSC); ++ ++ /* If Vbus is valid, then update the hsm */ ++ if (val & OTGSC_BSV) { ++ dev_dbg(lnw->dev, "no b_sess_vld interrupt\n"); ++ ++ lnw->iotg.hsm.b_sess_vld = 1; ++ langwell_update_transceiver(); ++ } ++ ++ dev_dbg(lnw->dev, "%s <---\n", __func__); ++ return 0; ++} ++ ++/* stop SOF via bus_suspend */ ++static void langwell_otg_loc_sof(int on) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct usb_hcd *hcd; ++ int err; ++ ++ dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume"); ++ ++ hcd = bus_to_hcd(lnw->iotg.otg.host); ++ if (on) ++ err = hcd->driver->bus_resume(hcd); ++ else ++ err = hcd->driver->bus_suspend(hcd); ++ ++ if (err) ++ dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err); ++ ++ dev_dbg(lnw->dev, "%s <---\n", __func__); ++} ++ ++static int langwell_otg_check_otgsc(void) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ u32 otgsc, usbcfg; ++ ++ dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n"); ++ ++ otgsc = readl(lnw->iotg.base + CI_OTGSC); ++ usbcfg = readl(lnw->usbcfg); ++ ++ dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n", ++ otgsc, usbcfg); ++ dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); ++ dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n", ++ !!(usbcfg & USBCFG_VBUSVAL)); ++ dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); ++ dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n", ++ !!(usbcfg & USBCFG_AVALID)); ++ dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); ++ dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n", ++ !!(usbcfg & USBCFG_BVALID)); ++ dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); ++ dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n", ++ !!(usbcfg & USBCFG_SESEND)); ++ ++ /* Check USBCFG VBusValid/AValid/BValid/SessEnd */ ++ if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) { ++ dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); ++ goto err; ++ } ++ if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) { ++ dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n"); ++ goto err; ++ } ++ if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) { ++ dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n"); ++ goto err; ++ } ++ if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) { ++ dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); ++ goto err; ++ } ++ ++ dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n"); ++ ++ return 0; ++ ++err: ++ dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n"); ++ return -EPIPE; ++} ++ ++ ++static void langwell_otg_phy_low_power(int on) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ u8 val, phcd; ++ int retval; ++ ++ dev_dbg(lnw->dev, "%s ---> %s mode\n", ++ __func__, on ? "Low power" : "Normal"); ++ ++ phcd = 0x40; ++ ++ val = readb(iotg->base + CI_HOSTPC1 + 2); ++ ++ if (on) { ++ /* Due to hardware issue, after set PHCD, sync will failed ++ * between USBCFG and OTGSC, so before set PHCD, check if ++ * sync is in process now. If the answer is "yes", then do ++ * not touch PHCD bit */ ++ retval = langwell_otg_check_otgsc(); ++ if (retval) { ++ dev_dbg(lnw->dev, "Skip PHCD programming..\n"); ++ return ; ++ } ++ ++ writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2); ++ } else ++ writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2); ++ ++ dev_dbg(lnw->dev, "%s <--- done\n", __func__); ++} ++ ++/* After drv vbus, add 2 ms delay to set PHCD */ ++static void langwell_otg_phy_low_power_wait(int on) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ ++ dev_dbg(lnw->dev, "add 2ms delay before programing PHCD\n"); ++ ++ mdelay(2); ++ langwell_otg_phy_low_power(on); ++} ++ ++/* Enable/Disable OTG interrupt */ ++static void langwell_otg_intr(int on) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ u32 val; ++ ++ dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); ++ ++ val = readl(iotg->base + CI_OTGSC); ++ ++ /* OTGSC_INT_MASK doesn't contains 1msInt */ ++ if (on) { ++ val = val | (OTGSC_INT_MASK); ++ writel(val, iotg->base + CI_OTGSC); ++ } else { ++ val = val & ~(OTGSC_INT_MASK); ++ writel(val, iotg->base + CI_OTGSC); ++ } ++ ++ dev_dbg(lnw->dev, "%s <---\n", __func__); ++} ++ ++/* set HAAR: Hardware Assist Auto-Reset */ ++static void langwell_otg_HAAR(int on) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ u32 val; ++ ++ dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); ++ ++ val = readl(iotg->base + CI_OTGSC); ++ if (on) ++ writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, ++ iotg->base + CI_OTGSC); ++ else ++ writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, ++ iotg->base + CI_OTGSC); ++ ++ dev_dbg(lnw->dev, "%s <---\n", __func__); ++} ++ ++/* set HABA: Hardware Assist B-Disconnect to A-Connect */ ++static void langwell_otg_HABA(int on) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ u32 val; ++ ++ dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); ++ ++ val = readl(iotg->base + CI_OTGSC); ++ if (on) ++ writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, ++ iotg->base + CI_OTGSC); ++ else ++ writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, ++ iotg->base + CI_OTGSC); ++ ++ dev_dbg(lnw->dev, "%s <---\n", __func__); ++} ++ ++static int langwell_otg_check_se0_srp(int on) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ int delay_time = TB_SE0_SRP * 10; ++ u32 val; ++ ++ dev_dbg(lnw->dev, "%s --->\n", __func__); ++ ++ do { ++ udelay(100); ++ if (!delay_time--) ++ break; ++ val = readl(lnw->iotg.base + CI_PORTSC1); ++ val &= PORTSC_LS; ++ } while (!val); ++ ++ dev_dbg(lnw->dev, "%s <---\n", __func__); ++ return val; ++} ++ ++/* The timeout callback function to set time out bit */ ++static void set_tmout(unsigned long indicator) ++{ ++ *(int *)indicator = 1; ++} ++ ++void langwell_otg_nsf_msg(unsigned long indicator) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ ++ switch (indicator) { ++ case 2: ++ case 4: ++ case 6: ++ case 7: ++ dev_warn(lnw->dev, ++ "OTG:NSF-%lu - deivce not responding\n", indicator); ++ break; ++ case 3: ++ dev_warn(lnw->dev, ++ "OTG:NSF-%lu - deivce not supported\n", indicator); ++ break; ++ default: ++ dev_warn(lnw->dev, "Do not have this kind of NSF\n"); ++ break; ++ } ++} ++ ++/* Initialize timers */ ++static int langwell_otg_init_timers(struct otg_hsm *hsm) ++{ ++ /* HSM used timers */ ++ a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, ++ (unsigned long)&hsm->a_wait_vrise_tmout); ++ if (a_wait_vrise_tmr == NULL) ++ return -ENOMEM; ++ a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, ++ (unsigned long)&hsm->a_aidl_bdis_tmout); ++ if (a_aidl_bdis_tmr == NULL) ++ return -ENOMEM; ++ b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, ++ (unsigned long)&hsm->b_se0_srp); ++ if (b_se0_srp_tmr == NULL) ++ return -ENOMEM; ++ b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT, ++ (unsigned long)&hsm->b_srp_init_tmout); ++ if (b_srp_init_tmr == NULL) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++/* Free timers */ ++static void langwell_otg_free_timers(void) ++{ ++ kfree(a_wait_vrise_tmr); ++ kfree(a_aidl_bdis_tmr); ++ kfree(b_se0_srp_tmr); ++ kfree(b_srp_init_tmr); ++} ++ ++/* The timeout callback function to set time out bit */ ++static void langwell_otg_timer_fn(unsigned long indicator) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ ++ *(int *)indicator = 1; ++ ++ dev_dbg(lnw->dev, "kernel timer - timeout\n"); ++ ++ langwell_update_transceiver(); ++} ++ ++/* kernel timer used instead of HW based interrupt */ ++static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ unsigned long j = jiffies; ++ unsigned long data, time; ++ ++ switch (timers) { ++ case TA_WAIT_VRISE_TMR: ++ iotg->hsm.a_wait_vrise_tmout = 0; ++ data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout; ++ time = TA_WAIT_VRISE; ++ break; ++ case TA_WAIT_BCON_TMR: ++ iotg->hsm.a_wait_bcon_tmout = 0; ++ data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout; ++ time = TA_WAIT_BCON; ++ break; ++ case TA_AIDL_BDIS_TMR: ++ iotg->hsm.a_aidl_bdis_tmout = 0; ++ data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout; ++ time = TA_AIDL_BDIS; ++ break; ++ case TB_ASE0_BRST_TMR: ++ iotg->hsm.b_ase0_brst_tmout = 0; ++ data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout; ++ time = TB_ASE0_BRST; ++ break; ++ case TB_SRP_INIT_TMR: ++ iotg->hsm.b_srp_init_tmout = 0; ++ data = (unsigned long)&iotg->hsm.b_srp_init_tmout; ++ time = TB_SRP_INIT; ++ break; ++ case TB_SRP_FAIL_TMR: ++ iotg->hsm.b_srp_fail_tmout = 0; ++ data = (unsigned long)&iotg->hsm.b_srp_fail_tmout; ++ time = TB_SRP_FAIL; ++ break; ++ case TB_BUS_SUSPEND_TMR: ++ iotg->hsm.b_bus_suspend_tmout = 0; ++ data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout; ++ time = TB_BUS_SUSPEND; ++ break; ++ default: ++ dev_dbg(lnw->dev, "unkown timer, cannot enable it\n"); ++ return; ++ } ++ ++ lnw->hsm_timer.data = data; ++ lnw->hsm_timer.function = langwell_otg_timer_fn; ++ lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */ ++ ++ add_timer(&lnw->hsm_timer); ++ ++ dev_dbg(lnw->dev, "add timer successfully\n"); ++} ++ ++/* Add timer to timer list */ ++static void langwell_otg_add_timer(void *gtimer) ++{ ++ struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; ++ struct langwell_otg_timer *tmp_timer; ++ struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg; ++ u32 val32; ++ ++ /* Check if the timer is already in the active list, ++ * if so update timer count ++ */ ++ list_for_each_entry(tmp_timer, &active_timers, list) ++ if (tmp_timer == timer) { ++ timer->count = timer->expires; ++ return; ++ } ++ timer->count = timer->expires; ++ ++ if (list_empty(&active_timers)) { ++ val32 = readl(iotg->base + CI_OTGSC); ++ writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC); ++ } ++ ++ list_add_tail(&timer->list, &active_timers); ++} ++ ++/* Remove timer from the timer list; clear timeout status */ ++static void langwell_otg_del_timer(void *gtimer) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; ++ struct langwell_otg_timer *tmp_timer, *del_tmp; ++ u32 val32; ++ ++ list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) ++ if (tmp_timer == timer) ++ list_del(&timer->list); ++ ++ if (list_empty(&active_timers)) { ++ val32 = readl(lnw->iotg.base + CI_OTGSC); ++ writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC); ++ } ++} ++ ++/* Reduce timer count by 1, and find timeout conditions.*/ ++static int langwell_otg_tick_timer(u32 *int_sts) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct langwell_otg_timer *tmp_timer, *del_tmp; ++ int expired = 0; ++ ++ list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { ++ tmp_timer->count--; ++ /* check if timer expires */ ++ if (!tmp_timer->count) { ++ list_del(&tmp_timer->list); ++ tmp_timer->function(tmp_timer->data); ++ expired = 1; ++ } ++ } ++ ++ if (list_empty(&active_timers)) { ++ dev_dbg(lnw->dev, "tick timer: disable 1ms int\n"); ++ *int_sts = *int_sts & ~OTGSC_1MSE; ++ } ++ return expired; ++} ++ ++static void reset_otg(void) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ int delay_time = 1000; ++ u32 val; ++ ++ dev_dbg(lnw->dev, "reseting OTG controller ...\n"); ++ val = readl(lnw->iotg.base + CI_USBCMD); ++ writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD); ++ do { ++ udelay(100); ++ if (!delay_time--) ++ dev_dbg(lnw->dev, "reset timeout\n"); ++ val = readl(lnw->iotg.base + CI_USBCMD); ++ val &= USBCMD_RST; ++ } while (val != 0); ++ dev_dbg(lnw->dev, "reset done.\n"); ++} ++ ++static void set_host_mode(void) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ u32 val; ++ ++ reset_otg(); ++ val = readl(lnw->iotg.base + CI_USBMODE); ++ val = (val & (~USBMODE_CM)) | USBMODE_HOST; ++ writel(val, lnw->iotg.base + CI_USBMODE); ++} ++ ++static void set_client_mode(void) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ u32 val; ++ ++ reset_otg(); ++ val = readl(lnw->iotg.base + CI_USBMODE); ++ val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; ++ writel(val, lnw->iotg.base + CI_USBMODE); ++} ++ ++static void init_hsm(void) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ u32 val32; ++ ++ /* read OTGSC after reset */ ++ val32 = readl(lnw->iotg.base + CI_OTGSC); ++ dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32); ++ ++ /* set init state */ ++ if (val32 & OTGSC_ID) { ++ iotg->hsm.id = 1; ++ iotg->otg.default_a = 0; ++ set_client_mode(); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ } else { ++ iotg->hsm.id = 0; ++ iotg->otg.default_a = 1; ++ set_host_mode(); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ } ++ ++ /* set session indicator */ ++ if (val32 & OTGSC_BSE) ++ iotg->hsm.b_sess_end = 1; ++ if (val32 & OTGSC_BSV) ++ iotg->hsm.b_sess_vld = 1; ++ if (val32 & OTGSC_ASV) ++ iotg->hsm.a_sess_vld = 1; ++ if (val32 & OTGSC_AVV) ++ iotg->hsm.a_vbus_vld = 1; ++ ++ /* defautly power the bus */ ++ iotg->hsm.a_bus_req = 1; ++ iotg->hsm.a_bus_drop = 0; ++ /* defautly don't request bus as B device */ ++ iotg->hsm.b_bus_req = 0; ++ /* no system error */ ++ iotg->hsm.a_clr_err = 0; ++ ++ langwell_otg_phy_low_power_wait(1); ++} ++ ++static void update_hsm(void) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ u32 val32; ++ ++ /* read OTGSC */ ++ val32 = readl(lnw->iotg.base + CI_OTGSC); ++ dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); ++ ++ iotg->hsm.id = !!(val32 & OTGSC_ID); ++ iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE); ++ iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); ++ iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); ++ iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); ++} ++ ++static irqreturn_t otg_dummy_irq(int irq, void *_dev) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ void __iomem *reg_base = _dev; ++ u32 val; ++ u32 int_mask = 0; ++ ++ val = readl(reg_base + CI_USBMODE); ++ if ((val & USBMODE_CM) != USBMODE_DEVICE) ++ return IRQ_NONE; ++ ++ val = readl(reg_base + CI_USBSTS); ++ int_mask = val & INTR_DUMMY_MASK; ++ ++ if (int_mask == 0) ++ return IRQ_NONE; ++ ++ /* clear hsm.b_conn here since host driver can't detect it ++ * otg_dummy_irq called means B-disconnect happened. ++ */ ++ if (lnw->iotg.hsm.b_conn) { ++ lnw->iotg.hsm.b_conn = 0; ++ if (spin_trylock(&lnw->wq_lock)) { ++ langwell_update_transceiver(); ++ spin_unlock(&lnw->wq_lock); ++ } ++ } ++ ++ /* Clear interrupts */ ++ writel(int_mask, reg_base + CI_USBSTS); ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t otg_irq(int irq, void *_dev) ++{ ++ struct langwell_otg *lnw = _dev; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ u32 int_sts, int_en; ++ u32 int_mask = 0; ++ int flag = 0; ++ ++ int_sts = readl(lnw->iotg.base + CI_OTGSC); ++ int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; ++ int_mask = int_sts & int_en; ++ if (int_mask == 0) ++ return IRQ_NONE; ++ ++ if (int_mask & OTGSC_IDIS) { ++ dev_dbg(lnw->dev, "%s: id change int\n", __func__); ++ iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; ++ dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id); ++ flag = 1; ++ } ++ if (int_mask & OTGSC_DPIS) { ++ dev_dbg(lnw->dev, "%s: data pulse int\n", __func__); ++ iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; ++ dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det); ++ flag = 1; ++ } ++ if (int_mask & OTGSC_BSEIS) { ++ dev_dbg(lnw->dev, "%s: b session end int\n", __func__); ++ iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; ++ dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end); ++ flag = 1; ++ } ++ if (int_mask & OTGSC_BSVIS) { ++ dev_dbg(lnw->dev, "%s: b session valid int\n", __func__); ++ iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; ++ dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end); ++ flag = 1; ++ } ++ if (int_mask & OTGSC_ASVIS) { ++ dev_dbg(lnw->dev, "%s: a session valid int\n", __func__); ++ iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; ++ dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld); ++ flag = 1; ++ } ++ if (int_mask & OTGSC_AVVIS) { ++ dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__); ++ iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; ++ dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld); ++ flag = 1; ++ } ++ ++ if (int_mask & OTGSC_1MSS) { ++ /* need to schedule otg_work if any timer is expired */ ++ if (langwell_otg_tick_timer(&int_sts)) ++ flag = 1; ++ } ++ ++ writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, ++ lnw->iotg.base + CI_OTGSC); ++ if (flag) ++ langwell_update_transceiver(); ++ ++ return IRQ_HANDLED; ++} ++ ++static int langwell_otg_iotg_notify(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = data; ++ int flag = 0; ++ ++ if (iotg == NULL) ++ return NOTIFY_BAD; ++ ++ if (lnw == NULL) ++ return NOTIFY_BAD; ++ ++ switch (action) { ++ case MID_OTG_NOTIFY_CONNECT: ++ dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n"); ++ if (iotg->otg.default_a == 1) ++ iotg->hsm.b_conn = 1; ++ else ++ iotg->hsm.a_conn = 1; ++ flag = 1; ++ break; ++ case MID_OTG_NOTIFY_DISCONN: ++ dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n"); ++ if (iotg->otg.default_a == 1) ++ iotg->hsm.b_conn = 0; ++ else ++ iotg->hsm.a_conn = 0; ++ flag = 1; ++ break; ++ case MID_OTG_NOTIFY_HSUSPEND: ++ dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n"); ++ if (iotg->otg.default_a == 1) ++ iotg->hsm.a_suspend_req = 1; ++ else ++ iotg->hsm.b_bus_req = 0; ++ flag = 1; ++ break; ++ case MID_OTG_NOTIFY_HRESUME: ++ dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n"); ++ if (iotg->otg.default_a == 1) ++ iotg->hsm.b_bus_resume = 1; ++ flag = 1; ++ break; ++ case MID_OTG_NOTIFY_CSUSPEND: ++ dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n"); ++ if (iotg->otg.default_a == 1) { ++ if (iotg->hsm.b_bus_suspend_vld == 2) { ++ iotg->hsm.b_bus_suspend = 1; ++ iotg->hsm.b_bus_suspend_vld = 0; ++ flag = 1; ++ } else { ++ iotg->hsm.b_bus_suspend_vld++; ++ flag = 0; ++ } ++ } else { ++ if (iotg->hsm.a_bus_suspend == 0) { ++ iotg->hsm.a_bus_suspend = 1; ++ flag = 1; ++ } ++ } ++ break; ++ case MID_OTG_NOTIFY_CRESUME: ++ dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n"); ++ if (iotg->otg.default_a == 0) ++ iotg->hsm.a_bus_suspend = 0; ++ flag = 0; ++ break; ++ case MID_OTG_NOTIFY_HOSTADD: ++ dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n"); ++ flag = 1; ++ break; ++ case MID_OTG_NOTIFY_HOSTREMOVE: ++ dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n"); ++ flag = 1; ++ break; ++ case MID_OTG_NOTIFY_CLIENTADD: ++ dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n"); ++ flag = 1; ++ break; ++ case MID_OTG_NOTIFY_CLIENTREMOVE: ++ dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n"); ++ flag = 1; ++ break; ++ default: ++ dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n"); ++ return NOTIFY_DONE; ++ } ++ ++ if (flag) ++ langwell_update_transceiver(); ++ ++ return NOTIFY_OK; ++} ++ ++static void langwell_otg_work(struct work_struct *work) ++{ ++ struct langwell_otg *lnw; ++ struct intel_mid_otg_xceiv *iotg; ++ int retval; ++ struct pci_dev *pdev; ++ ++ lnw = container_of(work, struct langwell_otg, work); ++ iotg = &lnw->iotg; ++ pdev = to_pci_dev(lnw->dev); ++ ++ dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, ++ state_string(iotg->otg.state)); ++ ++ switch (iotg->otg.state) { ++ case OTG_STATE_UNDEFINED: ++ case OTG_STATE_B_IDLE: ++ if (!iotg->hsm.id) { ++ langwell_otg_del_timer(b_srp_init_tmr); ++ del_timer_sync(&lnw->hsm_timer); ++ ++ iotg->otg.default_a = 1; ++ iotg->hsm.a_srp_det = 0; ++ ++ langwell_otg_chrg_vbus(0); ++ set_host_mode(); ++ langwell_otg_phy_low_power(1); ++ ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ langwell_update_transceiver(); ++ } else if (iotg->hsm.b_sess_vld) { ++ langwell_otg_del_timer(b_srp_init_tmr); ++ del_timer_sync(&lnw->hsm_timer); ++ iotg->hsm.b_sess_end = 0; ++ iotg->hsm.a_bus_suspend = 0; ++ langwell_otg_chrg_vbus(0); ++ ++ if (lnw->iotg.start_peripheral) { ++ lnw->iotg.start_peripheral(&lnw->iotg); ++ iotg->otg.state = OTG_STATE_B_PERIPHERAL; ++ } else ++ dev_dbg(lnw->dev, "client driver not loaded\n"); ++ ++ } else if (iotg->hsm.b_srp_init_tmout) { ++ iotg->hsm.b_srp_init_tmout = 0; ++ dev_warn(lnw->dev, "SRP init timeout\n"); ++ } else if (iotg->hsm.b_srp_fail_tmout) { ++ iotg->hsm.b_srp_fail_tmout = 0; ++ iotg->hsm.b_bus_req = 0; ++ ++ /* No silence failure */ ++ langwell_otg_nsf_msg(6); ++ } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) { ++ del_timer_sync(&lnw->hsm_timer); ++ /* workaround for b_se0_srp detection */ ++ retval = langwell_otg_check_se0_srp(0); ++ if (retval) { ++ iotg->hsm.b_bus_req = 0; ++ dev_dbg(lnw->dev, "LS isn't SE0, try later\n"); ++ } else { ++ /* clear the PHCD before start srp */ ++ langwell_otg_phy_low_power(0); ++ ++ /* Start SRP */ ++ langwell_otg_add_timer(b_srp_init_tmr); ++ iotg->otg.start_srp(&iotg->otg); ++ langwell_otg_del_timer(b_srp_init_tmr); ++ langwell_otg_add_ktimer(TB_SRP_FAIL_TMR); ++ ++ /* reset PHY low power mode here */ ++ langwell_otg_phy_low_power_wait(1); ++ } ++ } ++ break; ++ case OTG_STATE_B_SRP_INIT: ++ if (!iotg->hsm.id) { ++ iotg->otg.default_a = 1; ++ iotg->hsm.a_srp_det = 0; ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ langwell_otg_chrg_vbus(0); ++ set_host_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ langwell_update_transceiver(); ++ } else if (iotg->hsm.b_sess_vld) { ++ langwell_otg_chrg_vbus(0); ++ if (lnw->iotg.start_peripheral) { ++ lnw->iotg.start_peripheral(&lnw->iotg); ++ iotg->otg.state = OTG_STATE_B_PERIPHERAL; ++ } else ++ dev_dbg(lnw->dev, "client driver not loaded\n"); ++ } ++ break; ++ case OTG_STATE_B_PERIPHERAL: ++ if (!iotg->hsm.id) { ++ iotg->otg.default_a = 1; ++ iotg->hsm.a_srp_det = 0; ++ ++ langwell_otg_chrg_vbus(0); ++ ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver has been removed.\n"); ++ ++ set_host_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ langwell_update_transceiver(); ++ } else if (!iotg->hsm.b_sess_vld) { ++ iotg->hsm.b_hnp_enable = 0; ++ ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver has been removed.\n"); ++ ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ } else if (iotg->hsm.b_bus_req && iotg->otg.gadget && ++ iotg->otg.gadget->b_hnp_enable && ++ iotg->hsm.a_bus_suspend) { ++ ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver has been removed.\n"); ++ ++ langwell_otg_HAAR(1); ++ iotg->hsm.a_conn = 0; ++ ++ if (lnw->iotg.start_host) { ++ lnw->iotg.start_host(&lnw->iotg); ++ iotg->otg.state = OTG_STATE_B_WAIT_ACON; ++ } else ++ dev_dbg(lnw->dev, ++ "host driver not loaded.\n"); ++ ++ iotg->hsm.a_bus_resume = 0; ++ langwell_otg_add_ktimer(TB_ASE0_BRST_TMR); ++ } ++ break; ++ ++ case OTG_STATE_B_WAIT_ACON: ++ if (!iotg->hsm.id) { ++ /* delete hsm timer for b_ase0_brst_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ iotg->otg.default_a = 1; ++ iotg->hsm.a_srp_det = 0; ++ ++ langwell_otg_chrg_vbus(0); ++ ++ langwell_otg_HAAR(0); ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ set_host_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ langwell_update_transceiver(); ++ } else if (!iotg->hsm.b_sess_vld) { ++ /* delete hsm timer for b_ase0_brst_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ iotg->hsm.b_hnp_enable = 0; ++ iotg->hsm.b_bus_req = 0; ++ ++ langwell_otg_chrg_vbus(0); ++ langwell_otg_HAAR(0); ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ set_client_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ } else if (iotg->hsm.a_conn) { ++ /* delete hsm timer for b_ase0_brst_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ langwell_otg_HAAR(0); ++ iotg->otg.state = OTG_STATE_B_HOST; ++ langwell_update_transceiver(); ++ } else if (iotg->hsm.a_bus_resume || ++ iotg->hsm.b_ase0_brst_tmout) { ++ /* delete hsm timer for b_ase0_brst_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ langwell_otg_HAAR(0); ++ langwell_otg_nsf_msg(7); ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ iotg->hsm.a_bus_suspend = 0; ++ iotg->hsm.b_bus_req = 0; ++ ++ if (lnw->iotg.start_peripheral) ++ lnw->iotg.start_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver not loaded.\n"); ++ ++ iotg->otg.state = OTG_STATE_B_PERIPHERAL; ++ } ++ break; ++ ++ case OTG_STATE_B_HOST: ++ if (!iotg->hsm.id) { ++ iotg->otg.default_a = 1; ++ iotg->hsm.a_srp_det = 0; ++ ++ langwell_otg_chrg_vbus(0); ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ set_host_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ langwell_update_transceiver(); ++ } else if (!iotg->hsm.b_sess_vld) { ++ iotg->hsm.b_hnp_enable = 0; ++ iotg->hsm.b_bus_req = 0; ++ ++ langwell_otg_chrg_vbus(0); ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ set_client_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ } else if ((!iotg->hsm.b_bus_req) || ++ (!iotg->hsm.a_conn)) { ++ iotg->hsm.b_bus_req = 0; ++ langwell_otg_loc_sof(0); ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ iotg->hsm.a_bus_suspend = 0; ++ ++ if (lnw->iotg.start_peripheral) ++ lnw->iotg.start_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver not loaded.\n"); ++ ++ iotg->otg.state = OTG_STATE_B_PERIPHERAL; ++ } ++ break; ++ ++ case OTG_STATE_A_IDLE: ++ iotg->otg.default_a = 1; ++ if (iotg->hsm.id) { ++ iotg->otg.default_a = 0; ++ iotg->hsm.b_bus_req = 0; ++ iotg->hsm.vbus_srp_up = 0; ++ ++ langwell_otg_chrg_vbus(0); ++ set_client_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ langwell_update_transceiver(); ++ } else if (!iotg->hsm.a_bus_drop && ++ (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) { ++ langwell_otg_phy_low_power(0); ++ ++ /* Turn on VBus */ ++ iotg->otg.set_vbus(&iotg->otg, true); ++ ++ iotg->hsm.vbus_srp_up = 0; ++ iotg->hsm.a_wait_vrise_tmout = 0; ++ langwell_otg_add_timer(a_wait_vrise_tmr); ++ iotg->otg.state = OTG_STATE_A_WAIT_VRISE; ++ langwell_update_transceiver(); ++ } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) { ++ iotg->hsm.vbus_srp_up = 1; ++ } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) { ++ msleep(10); ++ langwell_otg_phy_low_power(0); ++ ++ /* Turn on VBus */ ++ iotg->otg.set_vbus(&iotg->otg, true); ++ iotg->hsm.a_srp_det = 1; ++ iotg->hsm.vbus_srp_up = 0; ++ iotg->hsm.a_wait_vrise_tmout = 0; ++ langwell_otg_add_timer(a_wait_vrise_tmr); ++ iotg->otg.state = OTG_STATE_A_WAIT_VRISE; ++ langwell_update_transceiver(); ++ } else if (!iotg->hsm.a_sess_vld && ++ !iotg->hsm.vbus_srp_up) { ++ langwell_otg_phy_low_power(1); ++ } ++ break; ++ case OTG_STATE_A_WAIT_VRISE: ++ if (iotg->hsm.id) { ++ langwell_otg_del_timer(a_wait_vrise_tmr); ++ iotg->hsm.b_bus_req = 0; ++ iotg->otg.default_a = 0; ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ set_client_mode(); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ } else if (iotg->hsm.a_vbus_vld) { ++ langwell_otg_del_timer(a_wait_vrise_tmr); ++ iotg->hsm.b_conn = 0; ++ if (lnw->iotg.start_host) ++ lnw->iotg.start_host(&lnw->iotg); ++ else { ++ dev_dbg(lnw->dev, "host driver not loaded.\n"); ++ break; ++ } ++ ++ langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); ++ iotg->otg.state = OTG_STATE_A_WAIT_BCON; ++ } else if (iotg->hsm.a_wait_vrise_tmout) { ++ iotg->hsm.b_conn = 0; ++ if (iotg->hsm.a_vbus_vld) { ++ if (lnw->iotg.start_host) ++ lnw->iotg.start_host(&lnw->iotg); ++ else { ++ dev_dbg(lnw->dev, ++ "host driver not loaded.\n"); ++ break; ++ } ++ langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); ++ iotg->otg.state = OTG_STATE_A_WAIT_BCON; ++ } else { ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_A_VBUS_ERR; ++ } ++ } ++ break; ++ case OTG_STATE_A_WAIT_BCON: ++ if (iotg->hsm.id) { ++ /* delete hsm timer for a_wait_bcon_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ iotg->otg.default_a = 0; ++ iotg->hsm.b_bus_req = 0; ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ set_client_mode(); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ langwell_update_transceiver(); ++ } else if (!iotg->hsm.a_vbus_vld) { ++ /* delete hsm timer for a_wait_bcon_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_A_VBUS_ERR; ++ } else if (iotg->hsm.a_bus_drop || ++ (iotg->hsm.a_wait_bcon_tmout && ++ !iotg->hsm.a_bus_req)) { ++ /* delete hsm timer for a_wait_bcon_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_WAIT_VFALL; ++ } else if (iotg->hsm.b_conn) { ++ /* delete hsm timer for a_wait_bcon_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ iotg->hsm.a_suspend_req = 0; ++ iotg->otg.state = OTG_STATE_A_HOST; ++ if (iotg->hsm.a_srp_det && iotg->otg.host && ++ !iotg->otg.host->b_hnp_enable) { ++ /* SRP capable peripheral-only device */ ++ iotg->hsm.a_bus_req = 1; ++ iotg->hsm.a_srp_det = 0; ++ } else if (!iotg->hsm.a_bus_req && iotg->otg.host && ++ iotg->otg.host->b_hnp_enable) { ++ /* It is not safe enough to do a fast ++ * transistion from A_WAIT_BCON to ++ * A_SUSPEND */ ++ msleep(10000); ++ if (iotg->hsm.a_bus_req) ++ break; ++ ++ if (request_irq(pdev->irq, ++ otg_dummy_irq, IRQF_SHARED, ++ driver_name, iotg->base) != 0) { ++ dev_dbg(lnw->dev, ++ "request interrupt %d fail\n", ++ pdev->irq); ++ } ++ ++ langwell_otg_HABA(1); ++ iotg->hsm.b_bus_resume = 0; ++ iotg->hsm.a_aidl_bdis_tmout = 0; ++ ++ langwell_otg_loc_sof(0); ++ /* clear PHCD to enable HW timer */ ++ langwell_otg_phy_low_power(0); ++ langwell_otg_add_timer(a_aidl_bdis_tmr); ++ iotg->otg.state = OTG_STATE_A_SUSPEND; ++ } else if (!iotg->hsm.a_bus_req && iotg->otg.host && ++ !iotg->otg.host->b_hnp_enable) { ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_WAIT_VFALL; ++ } ++ } ++ break; ++ case OTG_STATE_A_HOST: ++ if (iotg->hsm.id) { ++ iotg->otg.default_a = 0; ++ iotg->hsm.b_bus_req = 0; ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ set_client_mode(); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ langwell_update_transceiver(); ++ } else if (iotg->hsm.a_bus_drop || ++ (iotg->otg.host && ++ !iotg->otg.host->b_hnp_enable && ++ !iotg->hsm.a_bus_req)) { ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_WAIT_VFALL; ++ } else if (!iotg->hsm.a_vbus_vld) { ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_A_VBUS_ERR; ++ } else if (iotg->otg.host && ++ iotg->otg.host->b_hnp_enable && ++ !iotg->hsm.a_bus_req) { ++ /* Set HABA to enable hardware assistance to signal ++ * A-connect after receiver B-disconnect. Hardware ++ * will then set client mode and enable URE, SLE and ++ * PCE after the assistance. otg_dummy_irq is used to ++ * clean these ints when client driver is not resumed. ++ */ ++ if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, ++ driver_name, iotg->base) != 0) { ++ dev_dbg(lnw->dev, ++ "request interrupt %d failed\n", ++ pdev->irq); ++ } ++ ++ /* set HABA */ ++ langwell_otg_HABA(1); ++ iotg->hsm.b_bus_resume = 0; ++ iotg->hsm.a_aidl_bdis_tmout = 0; ++ langwell_otg_loc_sof(0); ++ /* clear PHCD to enable HW timer */ ++ langwell_otg_phy_low_power(0); ++ langwell_otg_add_timer(a_aidl_bdis_tmr); ++ iotg->otg.state = OTG_STATE_A_SUSPEND; ++ } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) { ++ langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); ++ iotg->otg.state = OTG_STATE_A_WAIT_BCON; ++ } ++ break; ++ case OTG_STATE_A_SUSPEND: ++ if (iotg->hsm.id) { ++ langwell_otg_del_timer(a_aidl_bdis_tmr); ++ langwell_otg_HABA(0); ++ free_irq(pdev->irq, iotg->base); ++ iotg->otg.default_a = 0; ++ iotg->hsm.b_bus_req = 0; ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ set_client_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ langwell_update_transceiver(); ++ } else if (iotg->hsm.a_bus_req || ++ iotg->hsm.b_bus_resume) { ++ langwell_otg_del_timer(a_aidl_bdis_tmr); ++ langwell_otg_HABA(0); ++ free_irq(pdev->irq, iotg->base); ++ iotg->hsm.a_suspend_req = 0; ++ langwell_otg_loc_sof(1); ++ iotg->otg.state = OTG_STATE_A_HOST; ++ } else if (iotg->hsm.a_aidl_bdis_tmout || ++ iotg->hsm.a_bus_drop) { ++ langwell_otg_del_timer(a_aidl_bdis_tmr); ++ langwell_otg_HABA(0); ++ free_irq(pdev->irq, iotg->base); ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_WAIT_VFALL; ++ } else if (!iotg->hsm.b_conn && iotg->otg.host && ++ iotg->otg.host->b_hnp_enable) { ++ langwell_otg_del_timer(a_aidl_bdis_tmr); ++ langwell_otg_HABA(0); ++ free_irq(pdev->irq, iotg->base); ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ iotg->hsm.b_bus_suspend = 0; ++ iotg->hsm.b_bus_suspend_vld = 0; ++ ++ /* msleep(200); */ ++ if (lnw->iotg.start_peripheral) ++ lnw->iotg.start_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver not loaded.\n"); ++ ++ langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR); ++ iotg->otg.state = OTG_STATE_A_PERIPHERAL; ++ break; ++ } else if (!iotg->hsm.a_vbus_vld) { ++ langwell_otg_del_timer(a_aidl_bdis_tmr); ++ langwell_otg_HABA(0); ++ free_irq(pdev->irq, iotg->base); ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_A_VBUS_ERR; ++ } ++ break; ++ case OTG_STATE_A_PERIPHERAL: ++ if (iotg->hsm.id) { ++ /* delete hsm timer for b_bus_suspend_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ iotg->otg.default_a = 0; ++ iotg->hsm.b_bus_req = 0; ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ set_client_mode(); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ langwell_update_transceiver(); ++ } else if (!iotg->hsm.a_vbus_vld) { ++ /* delete hsm timer for b_bus_suspend_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ langwell_otg_phy_low_power_wait(1); ++ iotg->otg.state = OTG_STATE_A_VBUS_ERR; ++ } else if (iotg->hsm.a_bus_drop) { ++ /* delete hsm timer for b_bus_suspend_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver has been removed.\n"); ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_WAIT_VFALL; ++ } else if (iotg->hsm.b_bus_suspend) { ++ /* delete hsm timer for b_bus_suspend_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver has been removed.\n"); ++ ++ if (lnw->iotg.start_host) ++ lnw->iotg.start_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver not loaded.\n"); ++ langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); ++ iotg->otg.state = OTG_STATE_A_WAIT_BCON; ++ } else if (iotg->hsm.b_bus_suspend_tmout) { ++ u32 val; ++ val = readl(lnw->iotg.base + CI_PORTSC1); ++ if (!(val & PORTSC_SUSP)) ++ break; ++ ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "client driver has been removed.\n"); ++ ++ if (lnw->iotg.start_host) ++ lnw->iotg.start_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, ++ "host driver not loaded.\n"); ++ langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); ++ iotg->otg.state = OTG_STATE_A_WAIT_BCON; ++ } ++ break; ++ case OTG_STATE_A_VBUS_ERR: ++ if (iotg->hsm.id) { ++ iotg->otg.default_a = 0; ++ iotg->hsm.a_clr_err = 0; ++ iotg->hsm.a_srp_det = 0; ++ set_client_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ langwell_update_transceiver(); ++ } else if (iotg->hsm.a_clr_err) { ++ iotg->hsm.a_clr_err = 0; ++ iotg->hsm.a_srp_det = 0; ++ reset_otg(); ++ init_hsm(); ++ if (iotg->otg.state == OTG_STATE_A_IDLE) ++ langwell_update_transceiver(); ++ } else { ++ /* FW will clear PHCD bit when any VBus ++ * event detected. Reset PHCD to 1 again */ ++ langwell_otg_phy_low_power(1); ++ } ++ break; ++ case OTG_STATE_A_WAIT_VFALL: ++ if (iotg->hsm.id) { ++ iotg->otg.default_a = 0; ++ set_client_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ langwell_update_transceiver(); ++ } else if (iotg->hsm.a_bus_req) { ++ ++ /* Turn on VBus */ ++ iotg->otg.set_vbus(&iotg->otg, true); ++ iotg->hsm.a_wait_vrise_tmout = 0; ++ langwell_otg_add_timer(a_wait_vrise_tmr); ++ iotg->otg.state = OTG_STATE_A_WAIT_VRISE; ++ } else if (!iotg->hsm.a_sess_vld) { ++ iotg->hsm.a_srp_det = 0; ++ set_host_mode(); ++ langwell_otg_phy_low_power(1); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ } ++ break; ++ default: ++ ; ++ } ++ ++ dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, ++ state_string(iotg->otg.state)); ++} ++ ++static ssize_t ++show_registers(struct device *_dev, struct device_attribute *attr, char *buf) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ char *next; ++ unsigned size, t; ++ ++ next = buf; ++ size = PAGE_SIZE; ++ ++ t = scnprintf(next, size, ++ "\n" ++ "USBCMD = 0x%08x\n" ++ "USBSTS = 0x%08x\n" ++ "USBINTR = 0x%08x\n" ++ "ASYNCLISTADDR = 0x%08x\n" ++ "PORTSC1 = 0x%08x\n" ++ "HOSTPC1 = 0x%08x\n" ++ "OTGSC = 0x%08x\n" ++ "USBMODE = 0x%08x\n", ++ readl(lnw->iotg.base + 0x30), ++ readl(lnw->iotg.base + 0x34), ++ readl(lnw->iotg.base + 0x38), ++ readl(lnw->iotg.base + 0x48), ++ readl(lnw->iotg.base + 0x74), ++ readl(lnw->iotg.base + 0xb4), ++ readl(lnw->iotg.base + 0xf4), ++ readl(lnw->iotg.base + 0xf8) ++ ); ++ size -= t; ++ next += t; ++ ++ return PAGE_SIZE - size; ++} ++static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); ++ ++static ssize_t ++show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ char *next; ++ unsigned size, t; ++ ++ next = buf; ++ size = PAGE_SIZE; ++ ++ if (iotg->otg.host) ++ iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable; ++ ++ if (iotg->otg.gadget) ++ iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable; ++ ++ t = scnprintf(next, size, ++ "\n" ++ "current state = %s\n" ++ "a_bus_resume = \t%d\n" ++ "a_bus_suspend = \t%d\n" ++ "a_conn = \t%d\n" ++ "a_sess_vld = \t%d\n" ++ "a_srp_det = \t%d\n" ++ "a_vbus_vld = \t%d\n" ++ "b_bus_resume = \t%d\n" ++ "b_bus_suspend = \t%d\n" ++ "b_conn = \t%d\n" ++ "b_se0_srp = \t%d\n" ++ "b_sess_end = \t%d\n" ++ "b_sess_vld = \t%d\n" ++ "id = \t%d\n" ++ "a_set_b_hnp_en = \t%d\n" ++ "b_srp_done = \t%d\n" ++ "b_hnp_enable = \t%d\n" ++ "a_wait_vrise_tmout = \t%d\n" ++ "a_wait_bcon_tmout = \t%d\n" ++ "a_aidl_bdis_tmout = \t%d\n" ++ "b_ase0_brst_tmout = \t%d\n" ++ "a_bus_drop = \t%d\n" ++ "a_bus_req = \t%d\n" ++ "a_clr_err = \t%d\n" ++ "a_suspend_req = \t%d\n" ++ "b_bus_req = \t%d\n" ++ "b_bus_suspend_tmout = \t%d\n" ++ "b_bus_suspend_vld = \t%d\n", ++ state_string(iotg->otg.state), ++ iotg->hsm.a_bus_resume, ++ iotg->hsm.a_bus_suspend, ++ iotg->hsm.a_conn, ++ iotg->hsm.a_sess_vld, ++ iotg->hsm.a_srp_det, ++ iotg->hsm.a_vbus_vld, ++ iotg->hsm.b_bus_resume, ++ iotg->hsm.b_bus_suspend, ++ iotg->hsm.b_conn, ++ iotg->hsm.b_se0_srp, ++ iotg->hsm.b_sess_end, ++ iotg->hsm.b_sess_vld, ++ iotg->hsm.id, ++ iotg->hsm.a_set_b_hnp_en, ++ iotg->hsm.b_srp_done, ++ iotg->hsm.b_hnp_enable, ++ iotg->hsm.a_wait_vrise_tmout, ++ iotg->hsm.a_wait_bcon_tmout, ++ iotg->hsm.a_aidl_bdis_tmout, ++ iotg->hsm.b_ase0_brst_tmout, ++ iotg->hsm.a_bus_drop, ++ iotg->hsm.a_bus_req, ++ iotg->hsm.a_clr_err, ++ iotg->hsm.a_suspend_req, ++ iotg->hsm.b_bus_req, ++ iotg->hsm.b_bus_suspend_tmout, ++ iotg->hsm.b_bus_suspend_vld ++ ); ++ size -= t; ++ next += t; ++ ++ return PAGE_SIZE - size; ++} ++static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); ++ ++static ssize_t ++get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ char *next; ++ unsigned size, t; ++ ++ next = buf; ++ size = PAGE_SIZE; ++ ++ t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req); ++ size -= t; ++ next += t; ++ ++ return PAGE_SIZE - size; ++} ++ ++static ssize_t ++set_a_bus_req(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ ++ if (!iotg->otg.default_a) ++ return -1; ++ if (count > 2) ++ return -1; ++ ++ if (buf[0] == '0') { ++ iotg->hsm.a_bus_req = 0; ++ dev_dbg(lnw->dev, "User request: a_bus_req = 0\n"); ++ } else if (buf[0] == '1') { ++ /* If a_bus_drop is TRUE, a_bus_req can't be set */ ++ if (iotg->hsm.a_bus_drop) ++ return -1; ++ iotg->hsm.a_bus_req = 1; ++ dev_dbg(lnw->dev, "User request: a_bus_req = 1\n"); ++ } ++ if (spin_trylock(&lnw->wq_lock)) { ++ langwell_update_transceiver(); ++ spin_unlock(&lnw->wq_lock); ++ } ++ return count; ++} ++static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req); ++ ++static ssize_t ++get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ char *next; ++ unsigned size, t; ++ ++ next = buf; ++ size = PAGE_SIZE; ++ ++ t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop); ++ size -= t; ++ next += t; ++ ++ return PAGE_SIZE - size; ++} ++ ++static ssize_t ++set_a_bus_drop(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ ++ if (!iotg->otg.default_a) ++ return -1; ++ if (count > 2) ++ return -1; ++ ++ if (buf[0] == '0') { ++ iotg->hsm.a_bus_drop = 0; ++ dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n"); ++ } else if (buf[0] == '1') { ++ iotg->hsm.a_bus_drop = 1; ++ iotg->hsm.a_bus_req = 0; ++ dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n"); ++ dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n"); ++ } ++ if (spin_trylock(&lnw->wq_lock)) { ++ langwell_update_transceiver(); ++ spin_unlock(&lnw->wq_lock); ++ } ++ return count; ++} ++static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO, ++ get_a_bus_drop, set_a_bus_drop); ++ ++static ssize_t ++get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ char *next; ++ unsigned size, t; ++ ++ next = buf; ++ size = PAGE_SIZE; ++ ++ t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req); ++ size -= t; ++ next += t; ++ ++ return PAGE_SIZE - size; ++} ++ ++static ssize_t ++set_b_bus_req(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ ++ if (iotg->otg.default_a) ++ return -1; ++ ++ if (count > 2) ++ return -1; ++ ++ if (buf[0] == '0') { ++ iotg->hsm.b_bus_req = 0; ++ dev_dbg(lnw->dev, "User request: b_bus_req = 0\n"); ++ } else if (buf[0] == '1') { ++ iotg->hsm.b_bus_req = 1; ++ dev_dbg(lnw->dev, "User request: b_bus_req = 1\n"); ++ } ++ if (spin_trylock(&lnw->wq_lock)) { ++ langwell_update_transceiver(); ++ spin_unlock(&lnw->wq_lock); ++ } ++ return count; ++} ++static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req); ++ ++static ssize_t ++set_a_clr_err(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ ++ if (!iotg->otg.default_a) ++ return -1; ++ if (count > 2) ++ return -1; ++ ++ if (buf[0] == '1') { ++ iotg->hsm.a_clr_err = 1; ++ dev_dbg(lnw->dev, "User request: a_clr_err = 1\n"); ++ } ++ if (spin_trylock(&lnw->wq_lock)) { ++ langwell_update_transceiver(); ++ spin_unlock(&lnw->wq_lock); ++ } ++ return count; ++} ++static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err); ++ ++static struct attribute *inputs_attrs[] = { ++ &dev_attr_a_bus_req.attr, ++ &dev_attr_a_bus_drop.attr, ++ &dev_attr_b_bus_req.attr, ++ &dev_attr_a_clr_err.attr, ++ NULL, ++}; ++ ++static struct attribute_group debug_dev_attr_group = { ++ .name = "inputs", ++ .attrs = inputs_attrs, ++}; ++ ++static int langwell_otg_probe(struct pci_dev *pdev, ++ const struct pci_device_id *id) ++{ ++ unsigned long resource, len; ++ void __iomem *base = NULL; ++ int retval; ++ u32 val32; ++ struct langwell_otg *lnw; ++ char qname[] = "langwell_otg_queue"; ++ ++ retval = 0; ++ dev_dbg(&pdev->dev, "\notg controller is detected.\n"); ++ if (pci_enable_device(pdev) < 0) { ++ retval = -ENODEV; ++ goto done; ++ } ++ ++ lnw = kzalloc(sizeof *lnw, GFP_KERNEL); ++ if (lnw == NULL) { ++ retval = -ENOMEM; ++ goto done; ++ } ++ the_transceiver = lnw; ++ ++ /* control register: BAR 0 */ ++ resource = pci_resource_start(pdev, 0); ++ len = pci_resource_len(pdev, 0); ++ if (!request_mem_region(resource, len, driver_name)) { ++ retval = -EBUSY; ++ goto err; ++ } ++ lnw->region = 1; ++ ++ base = ioremap_nocache(resource, len); ++ if (base == NULL) { ++ retval = -EFAULT; ++ goto err; ++ } ++ lnw->iotg.base = base; ++ ++ if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) { ++ retval = -EBUSY; ++ goto err; ++ } ++ lnw->cfg_region = 1; ++ ++ /* For the SCCB.USBCFG register */ ++ base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN); ++ if (base == NULL) { ++ retval = -EFAULT; ++ goto err; ++ } ++ lnw->usbcfg = base; ++ ++ if (!pdev->irq) { ++ dev_dbg(&pdev->dev, "No IRQ.\n"); ++ retval = -ENODEV; ++ goto err; ++ } ++ ++ lnw->qwork = create_singlethread_workqueue(qname); ++ if (!lnw->qwork) { ++ dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname); ++ retval = -ENOMEM; ++ goto err; ++ } ++ INIT_WORK(&lnw->work, langwell_otg_work); ++ ++ /* OTG common part */ ++ lnw->dev = &pdev->dev; ++ lnw->iotg.otg.dev = lnw->dev; ++ lnw->iotg.otg.label = driver_name; ++ lnw->iotg.otg.set_host = langwell_otg_set_host; ++ lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral; ++ lnw->iotg.otg.set_power = langwell_otg_set_power; ++ lnw->iotg.otg.set_vbus = langwell_otg_set_vbus; ++ lnw->iotg.otg.start_srp = langwell_otg_start_srp; ++ lnw->iotg.otg.state = OTG_STATE_UNDEFINED; ++ ++ if (otg_set_transceiver(&lnw->iotg.otg)) { ++ dev_dbg(lnw->dev, "can't set transceiver\n"); ++ retval = -EBUSY; ++ goto err; ++ } ++ ++ reset_otg(); ++ init_hsm(); ++ ++ spin_lock_init(&lnw->lock); ++ spin_lock_init(&lnw->wq_lock); ++ INIT_LIST_HEAD(&active_timers); ++ retval = langwell_otg_init_timers(&lnw->iotg.hsm); ++ if (retval) { ++ dev_dbg(&pdev->dev, "Failed to init timers\n"); ++ goto err; ++ } ++ ++ init_timer(&lnw->hsm_timer); ++ ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier); ++ ++ lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify; ++ ++ retval = intel_mid_otg_register_notifier(&lnw->iotg, ++ &lnw->iotg_notifier); ++ if (retval) { ++ dev_dbg(lnw->dev, "Failed to register notifier\n"); ++ goto err; ++ } ++ ++ if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, ++ driver_name, lnw) != 0) { ++ dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq); ++ retval = -EBUSY; ++ goto err; ++ } ++ ++ /* enable OTGSC int */ ++ val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | ++ OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; ++ writel(val32, lnw->iotg.base + CI_OTGSC); ++ ++ retval = device_create_file(&pdev->dev, &dev_attr_registers); ++ if (retval < 0) { ++ dev_dbg(lnw->dev, ++ "Can't register sysfs attribute: %d\n", retval); ++ goto err; ++ } ++ ++ retval = device_create_file(&pdev->dev, &dev_attr_hsm); ++ if (retval < 0) { ++ dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval); ++ goto err; ++ } ++ ++ retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); ++ if (retval < 0) { ++ dev_dbg(lnw->dev, ++ "Can't register sysfs attr group: %d\n", retval); ++ goto err; ++ } ++ ++ if (lnw->iotg.otg.state == OTG_STATE_A_IDLE) ++ langwell_update_transceiver(); ++ ++ return 0; ++ ++err: ++ if (the_transceiver) ++ langwell_otg_remove(pdev); ++done: ++ return retval; ++} ++ ++static void langwell_otg_remove(struct pci_dev *pdev) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ ++ if (lnw->qwork) { ++ flush_workqueue(lnw->qwork); ++ destroy_workqueue(lnw->qwork); ++ } ++ intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier); ++ langwell_otg_free_timers(); ++ ++ /* disable OTGSC interrupt as OTGSC doesn't change in reset */ ++ writel(0, lnw->iotg.base + CI_OTGSC); ++ ++ if (pdev->irq) ++ free_irq(pdev->irq, lnw); ++ if (lnw->usbcfg) ++ iounmap(lnw->usbcfg); ++ if (lnw->cfg_region) ++ release_mem_region(USBCFG_ADDR, USBCFG_LEN); ++ if (lnw->iotg.base) ++ iounmap(lnw->iotg.base); ++ if (lnw->region) ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++ otg_set_transceiver(NULL); ++ pci_disable_device(pdev); ++ sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); ++ device_remove_file(&pdev->dev, &dev_attr_hsm); ++ device_remove_file(&pdev->dev, &dev_attr_registers); ++ kfree(lnw); ++ lnw = NULL; ++} ++ ++static void transceiver_suspend(struct pci_dev *pdev) ++{ ++ pci_save_state(pdev); ++ pci_set_power_state(pdev, PCI_D3hot); ++ langwell_otg_phy_low_power(1); ++} ++ ++static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ struct intel_mid_otg_xceiv *iotg = &lnw->iotg; ++ int ret = 0; ++ ++ /* Disbale OTG interrupts */ ++ langwell_otg_intr(0); ++ ++ if (pdev->irq) ++ free_irq(pdev->irq, lnw); ++ ++ /* Prevent more otg_work */ ++ flush_workqueue(lnw->qwork); ++ destroy_workqueue(lnw->qwork); ++ lnw->qwork = NULL; ++ ++ /* start actions */ ++ switch (iotg->otg.state) { ++ case OTG_STATE_A_WAIT_VFALL: ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ case OTG_STATE_A_IDLE: ++ case OTG_STATE_B_IDLE: ++ case OTG_STATE_A_VBUS_ERR: ++ transceiver_suspend(pdev); ++ break; ++ case OTG_STATE_A_WAIT_VRISE: ++ langwell_otg_del_timer(a_wait_vrise_tmr); ++ iotg->hsm.a_srp_det = 0; ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ transceiver_suspend(pdev); ++ break; ++ case OTG_STATE_A_WAIT_BCON: ++ del_timer_sync(&lnw->hsm_timer); ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(&pdev->dev, "host driver has been removed.\n"); ++ ++ iotg->hsm.a_srp_det = 0; ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ transceiver_suspend(pdev); ++ break; ++ case OTG_STATE_A_HOST: ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(&pdev->dev, "host driver has been removed.\n"); ++ ++ iotg->hsm.a_srp_det = 0; ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ transceiver_suspend(pdev); ++ break; ++ case OTG_STATE_A_SUSPEND: ++ langwell_otg_del_timer(a_aidl_bdis_tmr); ++ langwell_otg_HABA(0); ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(lnw->dev, "host driver has been removed.\n"); ++ iotg->hsm.a_srp_det = 0; ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ transceiver_suspend(pdev); ++ break; ++ case OTG_STATE_A_PERIPHERAL: ++ del_timer_sync(&lnw->hsm_timer); ++ ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(&pdev->dev, ++ "client driver has been removed.\n"); ++ iotg->hsm.a_srp_det = 0; ++ ++ /* Turn off VBus */ ++ iotg->otg.set_vbus(&iotg->otg, false); ++ iotg->otg.state = OTG_STATE_A_IDLE; ++ transceiver_suspend(pdev); ++ break; ++ case OTG_STATE_B_HOST: ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(&pdev->dev, "host driver has been removed.\n"); ++ iotg->hsm.b_bus_req = 0; ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ transceiver_suspend(pdev); ++ break; ++ case OTG_STATE_B_PERIPHERAL: ++ if (lnw->iotg.stop_peripheral) ++ lnw->iotg.stop_peripheral(&lnw->iotg); ++ else ++ dev_dbg(&pdev->dev, ++ "client driver has been removed.\n"); ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ transceiver_suspend(pdev); ++ break; ++ case OTG_STATE_B_WAIT_ACON: ++ /* delete hsm timer for b_ase0_brst_tmr */ ++ del_timer_sync(&lnw->hsm_timer); ++ ++ langwell_otg_HAAR(0); ++ ++ if (lnw->iotg.stop_host) ++ lnw->iotg.stop_host(&lnw->iotg); ++ else ++ dev_dbg(&pdev->dev, "host driver has been removed.\n"); ++ iotg->hsm.b_bus_req = 0; ++ iotg->otg.state = OTG_STATE_B_IDLE; ++ transceiver_suspend(pdev); ++ break; ++ default: ++ dev_dbg(lnw->dev, "error state before suspend\n"); ++ break; ++ } ++ ++ return ret; ++} ++ ++static void transceiver_resume(struct pci_dev *pdev) ++{ ++ pci_restore_state(pdev); ++ pci_set_power_state(pdev, PCI_D0); ++} ++ ++static int langwell_otg_resume(struct pci_dev *pdev) ++{ ++ struct langwell_otg *lnw = the_transceiver; ++ int ret = 0; ++ ++ transceiver_resume(pdev); ++ ++ lnw->qwork = create_singlethread_workqueue("langwell_otg_queue"); ++ if (!lnw->qwork) { ++ dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen"); ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, ++ driver_name, lnw) != 0) { ++ dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq); ++ ret = -EBUSY; ++ goto error; ++ } ++ ++ /* enable OTG interrupts */ ++ langwell_otg_intr(1); ++ ++ update_hsm(); ++ ++ langwell_update_transceiver(); ++ ++ return ret; ++error: ++ langwell_otg_intr(0); ++ transceiver_suspend(pdev); ++ return ret; ++} ++ ++static int __init langwell_otg_init(void) ++{ ++ return pci_register_driver(&otg_pci_driver); ++} ++module_init(langwell_otg_init); ++ ++static void __exit langwell_otg_cleanup(void) ++{ ++ pci_unregister_driver(&otg_pci_driver); ++} ++module_exit(langwell_otg_cleanup); +--- /dev/null ++++ b/include/linux/usb/langwell_otg.h +@@ -0,0 +1,139 @@ ++/* ++ * Intel Langwell USB OTG transceiver driver ++ * Copyright (C) 2008, Intel Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope 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 St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++ ++#ifndef __LANGWELL_OTG_H ++#define __LANGWELL_OTG_H ++ ++#include <linux/usb/intel_mid_otg.h> ++ ++#define CI_USBCMD 0x30 ++# define USBCMD_RST BIT(1) ++# define USBCMD_RS BIT(0) ++#define CI_USBSTS 0x34 ++# define USBSTS_SLI BIT(8) ++# define USBSTS_URI BIT(6) ++# define USBSTS_PCI BIT(2) ++#define CI_PORTSC1 0x74 ++# define PORTSC_PP BIT(12) ++# define PORTSC_LS (BIT(11) | BIT(10)) ++# define PORTSC_SUSP BIT(7) ++# define PORTSC_CCS BIT(0) ++#define CI_HOSTPC1 0xb4 ++# define HOSTPC1_PHCD BIT(22) ++#define CI_OTGSC 0xf4 ++# define OTGSC_DPIE BIT(30) ++# define OTGSC_1MSE BIT(29) ++# define OTGSC_BSEIE BIT(28) ++# define OTGSC_BSVIE BIT(27) ++# define OTGSC_ASVIE BIT(26) ++# define OTGSC_AVVIE BIT(25) ++# define OTGSC_IDIE BIT(24) ++# define OTGSC_DPIS BIT(22) ++# define OTGSC_1MSS BIT(21) ++# define OTGSC_BSEIS BIT(20) ++# define OTGSC_BSVIS BIT(19) ++# define OTGSC_ASVIS BIT(18) ++# define OTGSC_AVVIS BIT(17) ++# define OTGSC_IDIS BIT(16) ++# define OTGSC_DPS BIT(14) ++# define OTGSC_1MST BIT(13) ++# define OTGSC_BSE BIT(12) ++# define OTGSC_BSV BIT(11) ++# define OTGSC_ASV BIT(10) ++# define OTGSC_AVV BIT(9) ++# define OTGSC_ID BIT(8) ++# define OTGSC_HABA BIT(7) ++# define OTGSC_HADP BIT(6) ++# define OTGSC_IDPU BIT(5) ++# define OTGSC_DP BIT(4) ++# define OTGSC_OT BIT(3) ++# define OTGSC_HAAR BIT(2) ++# define OTGSC_VC BIT(1) ++# define OTGSC_VD BIT(0) ++# define OTGSC_INTEN_MASK (0x7f << 24) ++# define OTGSC_INT_MASK (0x5f << 24) ++# define OTGSC_INTSTS_MASK (0x7f << 16) ++#define CI_USBMODE 0xf8 ++# define USBMODE_CM (BIT(1) | BIT(0)) ++# define USBMODE_IDLE 0 ++# define USBMODE_DEVICE 0x2 ++# define USBMODE_HOST 0x3 ++#define USBCFG_ADDR 0xff10801c ++#define USBCFG_LEN 4 ++# define USBCFG_VBUSVAL BIT(14) ++# define USBCFG_AVALID BIT(13) ++# define USBCFG_BVALID BIT(12) ++# define USBCFG_SESEND BIT(11) ++ ++#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI) ++ ++enum langwell_otg_timer_type { ++ TA_WAIT_VRISE_TMR, ++ TA_WAIT_BCON_TMR, ++ TA_AIDL_BDIS_TMR, ++ TB_ASE0_BRST_TMR, ++ TB_SE0_SRP_TMR, ++ TB_SRP_INIT_TMR, ++ TB_SRP_FAIL_TMR, ++ TB_BUS_SUSPEND_TMR ++}; ++ ++#define TA_WAIT_VRISE 100 ++#define TA_WAIT_BCON 30000 ++#define TA_AIDL_BDIS 15000 ++#define TB_ASE0_BRST 5000 ++#define TB_SE0_SRP 2 ++#define TB_SRP_INIT 100 ++#define TB_SRP_FAIL 5500 ++#define TB_BUS_SUSPEND 500 ++ ++struct langwell_otg_timer { ++ unsigned long expires; /* Number of count increase to timeout */ ++ unsigned long count; /* Tick counter */ ++ void (*function)(unsigned long); /* Timeout function */ ++ unsigned long data; /* Data passed to function */ ++ struct list_head list; ++}; ++ ++struct langwell_otg { ++ struct intel_mid_otg_xceiv iotg; ++ struct device *dev; ++ ++ void __iomem *usbcfg; /* SCCBUSB config Reg */ ++ ++ unsigned region; ++ unsigned cfg_region; ++ ++ struct work_struct work; ++ struct workqueue_struct *qwork; ++ struct timer_list hsm_timer; ++ ++ spinlock_t lock; ++ spinlock_t wq_lock; ++ ++ struct notifier_block iotg_notifier; ++}; ++ ++static inline ++struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg) ++{ ++ return container_of(iotg, struct langwell_otg, iotg); ++} ++ ++#endif /* __LANGWELL_OTG_H__ */ diff --git a/usb/usb-langwell-usb-client-driver-code-cleanup.patch b/usb/usb-langwell-usb-client-driver-code-cleanup.patch new file mode 100644 index 00000000000000..6c62a054b2db70 --- /dev/null +++ b/usb/usb-langwell-usb-client-driver-code-cleanup.patch @@ -0,0 +1,2133 @@ +From linux-usb-owner@vger.kernel.org Wed Sep 1 11:41:05 2010 +From: JiebingLi <jiebing.li@intel.com> +Subject: USB: langwell: USB Client driver code cleanup +To: linux-usb@vger.kernel.org +Date: Thu, 05 Aug 2010 14:17:54 +0100 +Message-ID: <20100805131753.12473.56494.stgit@localhost.localdomain> + +From: JiebingLi <jiebing.li@intel.com> + +Code cleanup by using standard debugging API's and USB inline functions + +Signed-off-by: JiebingLi <jiebing.li@intel.com> +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/langwell_udc.c | 738 +++++++++++++++++++------------------- + 1 file changed, 375 insertions(+), 363 deletions(-) + +--- a/drivers/usb/gadget/langwell_udc.c ++++ b/drivers/usb/gadget/langwell_udc.c +@@ -19,7 +19,7 @@ + + + /* #undef DEBUG */ +-/* #undef VERBOSE */ ++/* #undef VERBOSE_DEBUG */ + + #if defined(CONFIG_USB_LANGWELL_OTG) + #define OTG_TRANSCEIVER +@@ -77,141 +77,110 @@ langwell_ep0_desc = { + /*-------------------------------------------------------------------------*/ + /* debugging */ + +-#ifdef DEBUG +-#define DBG(dev, fmt, args...) \ +- pr_debug("%s %s: " fmt , driver_name, \ +- pci_name(dev->pdev), ## 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...) \ +- pr_err("%s %s: " fmt , driver_name, \ +- pci_name(dev->pdev), ## args) +- +-#define WARNING(dev, fmt, args...) \ +- pr_warning("%s %s: " fmt , driver_name, \ +- pci_name(dev->pdev), ## args) +- +-#define INFO(dev, fmt, args...) \ +- pr_info("%s %s: " fmt , driver_name, \ +- pci_name(dev->pdev), ## args) +- +- +-#ifdef VERBOSE ++#ifdef VERBOSE_DEBUG + static inline void print_all_registers(struct langwell_udc *dev) + { + int i; + + /* Capability Registers */ +- printk(KERN_DEBUG "Capability Registers (offset: " +- "0x%04x, length: 0x%08x)\n", +- CAP_REG_OFFSET, +- (u32)sizeof(struct langwell_cap_regs)); +- printk(KERN_DEBUG "caplength=0x%02x\n", ++ dev_dbg(&dev->pdev->dev, ++ "Capability Registers (offset: 0x%04x, length: 0x%08x)\n", ++ CAP_REG_OFFSET, (u32)sizeof(struct langwell_cap_regs)); ++ dev_dbg(&dev->pdev->dev, "caplength=0x%02x\n", + readb(&dev->cap_regs->caplength)); +- printk(KERN_DEBUG "hciversion=0x%04x\n", ++ dev_dbg(&dev->pdev->dev, "hciversion=0x%04x\n", + readw(&dev->cap_regs->hciversion)); +- printk(KERN_DEBUG "hcsparams=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "hcsparams=0x%08x\n", + readl(&dev->cap_regs->hcsparams)); +- printk(KERN_DEBUG "hccparams=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "hccparams=0x%08x\n", + readl(&dev->cap_regs->hccparams)); +- printk(KERN_DEBUG "dciversion=0x%04x\n", ++ dev_dbg(&dev->pdev->dev, "dciversion=0x%04x\n", + readw(&dev->cap_regs->dciversion)); +- printk(KERN_DEBUG "dccparams=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "dccparams=0x%08x\n", + readl(&dev->cap_regs->dccparams)); + + /* Operational Registers */ +- printk(KERN_DEBUG "Operational Registers (offset: " +- "0x%04x, length: 0x%08x)\n", +- OP_REG_OFFSET, +- (u32)sizeof(struct langwell_op_regs)); +- printk(KERN_DEBUG "extsts=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, ++ "Operational Registers (offset: 0x%04x, length: 0x%08x)\n", ++ OP_REG_OFFSET, (u32)sizeof(struct langwell_op_regs)); ++ dev_dbg(&dev->pdev->dev, "extsts=0x%08x\n", + readl(&dev->op_regs->extsts)); +- printk(KERN_DEBUG "extintr=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "extintr=0x%08x\n", + readl(&dev->op_regs->extintr)); +- printk(KERN_DEBUG "usbcmd=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "usbcmd=0x%08x\n", + readl(&dev->op_regs->usbcmd)); +- printk(KERN_DEBUG "usbsts=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "usbsts=0x%08x\n", + readl(&dev->op_regs->usbsts)); +- printk(KERN_DEBUG "usbintr=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "usbintr=0x%08x\n", + readl(&dev->op_regs->usbintr)); +- printk(KERN_DEBUG "frindex=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "frindex=0x%08x\n", + readl(&dev->op_regs->frindex)); +- printk(KERN_DEBUG "ctrldssegment=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "ctrldssegment=0x%08x\n", + readl(&dev->op_regs->ctrldssegment)); +- printk(KERN_DEBUG "deviceaddr=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "deviceaddr=0x%08x\n", + readl(&dev->op_regs->deviceaddr)); +- printk(KERN_DEBUG "endpointlistaddr=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endpointlistaddr=0x%08x\n", + readl(&dev->op_regs->endpointlistaddr)); +- printk(KERN_DEBUG "ttctrl=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "ttctrl=0x%08x\n", + readl(&dev->op_regs->ttctrl)); +- printk(KERN_DEBUG "burstsize=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "burstsize=0x%08x\n", + readl(&dev->op_regs->burstsize)); +- printk(KERN_DEBUG "txfilltuning=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "txfilltuning=0x%08x\n", + readl(&dev->op_regs->txfilltuning)); +- printk(KERN_DEBUG "txttfilltuning=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "txttfilltuning=0x%08x\n", + readl(&dev->op_regs->txttfilltuning)); +- printk(KERN_DEBUG "ic_usb=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "ic_usb=0x%08x\n", + readl(&dev->op_regs->ic_usb)); +- printk(KERN_DEBUG "ulpi_viewport=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "ulpi_viewport=0x%08x\n", + readl(&dev->op_regs->ulpi_viewport)); +- printk(KERN_DEBUG "configflag=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "configflag=0x%08x\n", + readl(&dev->op_regs->configflag)); +- printk(KERN_DEBUG "portsc1=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "portsc1=0x%08x\n", + readl(&dev->op_regs->portsc1)); +- printk(KERN_DEBUG "devlc=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "devlc=0x%08x\n", + readl(&dev->op_regs->devlc)); +- printk(KERN_DEBUG "otgsc=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "otgsc=0x%08x\n", + readl(&dev->op_regs->otgsc)); +- printk(KERN_DEBUG "usbmode=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "usbmode=0x%08x\n", + readl(&dev->op_regs->usbmode)); +- printk(KERN_DEBUG "endptnak=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endptnak=0x%08x\n", + readl(&dev->op_regs->endptnak)); +- printk(KERN_DEBUG "endptnaken=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endptnaken=0x%08x\n", + readl(&dev->op_regs->endptnaken)); +- printk(KERN_DEBUG "endptsetupstat=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endptsetupstat=0x%08x\n", + readl(&dev->op_regs->endptsetupstat)); +- printk(KERN_DEBUG "endptprime=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endptprime=0x%08x\n", + readl(&dev->op_regs->endptprime)); +- printk(KERN_DEBUG "endptflush=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endptflush=0x%08x\n", + readl(&dev->op_regs->endptflush)); +- printk(KERN_DEBUG "endptstat=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endptstat=0x%08x\n", + readl(&dev->op_regs->endptstat)); +- printk(KERN_DEBUG "endptcomplete=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endptcomplete=0x%08x\n", + readl(&dev->op_regs->endptcomplete)); + + for (i = 0; i < dev->ep_max / 2; i++) { +- printk(KERN_DEBUG "endptctrl[%d]=0x%08x\n", ++ dev_dbg(&dev->pdev->dev, "endptctrl[%d]=0x%08x\n", + i, readl(&dev->op_regs->endptctrl[i])); + } + } +-#endif /* VERBOSE */ ++#else ++ ++#define print_all_registers(dev) do { } while (0) ++ ++#endif /* VERBOSE_DEBUG */ + + + /*-------------------------------------------------------------------------*/ + +-#define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out") ++#define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \ ++ USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc))) + +-#define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \ +- USB_DIR_IN) : ((ep)->desc->bEndpointAddress \ +- & USB_DIR_IN) == USB_DIR_IN) ++#define DIR_STRING(ep) (is_in(ep) ? "in" : "out") + + +-#ifdef DEBUG +-static char *type_string(u8 bmAttributes) ++static char *type_string(const struct usb_endpoint_descriptor *desc) + { +- switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) { ++ switch (usb_endpoint_type(desc)) { + case USB_ENDPOINT_XFER_BULK: + return "bulk"; + case USB_ENDPOINT_XFER_ISOC: +@@ -222,7 +191,6 @@ static char *type_string(u8 bmAttributes + + return "control"; + } +-#endif + + + /* configure endpoint control registers */ +@@ -233,7 +201,7 @@ static void ep_reset(struct langwell_ep + u32 endptctrl; + + dev = ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); + if (is_in) { /* TX */ +@@ -250,7 +218,7 @@ static void ep_reset(struct langwell_ep + + writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -260,7 +228,7 @@ static void ep0_reset(struct langwell_ud + struct langwell_ep *ep; + int i; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* ep0 in and out */ + for (i = 0; i < 2; i++) { +@@ -283,7 +251,7 @@ static void ep0_reset(struct langwell_ud + ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL); + } + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return; + } + +@@ -305,7 +273,7 @@ static int langwell_ep_enable(struct usb + + ep = container_of(_ep, struct langwell_ep, ep); + dev = ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (!_ep || !desc || ep->desc + || desc->bDescriptorType != USB_DT_ENDPOINT) +@@ -326,7 +294,7 @@ static int langwell_ep_enable(struct usb + * sanity check type, direction, address, and then + * initialize the endpoint capabilities fields in dQH + */ +- switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { ++ switch (usb_endpoint_type(desc)) { + case USB_ENDPOINT_XFER_CONTROL: + ios = 1; + break; +@@ -395,24 +363,24 @@ static int langwell_ep_enable(struct usb + ep->ep.maxpacket = max; + ep->desc = desc; + ep->stopped = 0; +- ep->ep_num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; ++ ep->ep_num = usb_endpoint_num(desc); + + /* ep_type */ +- ep->ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; ++ ep->ep_type = usb_endpoint_type(desc); + + /* configure endpoint control registers */ + ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type); + +- DBG(dev, "enabled %s (ep%d%s-%s), max %04x\n", ++ dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n", + _ep->name, + ep->ep_num, +- DIR_STRING(desc->bEndpointAddress), +- type_string(desc->bmAttributes), ++ DIR_STRING(ep), ++ type_string(desc), + max); + + spin_unlock_irqrestore(&dev->lock, flags); + done: +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return retval; + } + +@@ -428,7 +396,7 @@ static void done(struct langwell_ep *ep, + struct langwell_dtd *curr_dtd, *next_dtd; + int i; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* remove the req from ep->queue */ + list_del_init(&req->queue); +@@ -448,7 +416,8 @@ static void done(struct langwell_ep *ep, + } + + if (req->mapped) { +- dma_unmap_single(&dev->pdev->dev, req->req.dma, req->req.length, ++ dma_unmap_single(&dev->pdev->dev, ++ req->req.dma, req->req.length, + is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); + req->req.dma = DMA_ADDR_INVALID; + req->mapped = 0; +@@ -458,9 +427,10 @@ static void done(struct langwell_ep *ep, + is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + + if (status != -ESHUTDOWN) +- DBG(dev, "complete %s, req %p, stat %d, len %u/%u\n", +- ep->ep.name, &req->req, status, +- req->req.actual, req->req.length); ++ dev_dbg(&dev->pdev->dev, ++ "complete %s, req %p, stat %d, len %u/%u\n", ++ ep->ep.name, &req->req, status, ++ req->req.actual, req->req.length); + + /* don't modify queue heads during completion callback */ + ep->stopped = 1; +@@ -473,7 +443,7 @@ static void done(struct langwell_ep *ep, + spin_lock(&dev->lock); + ep->stopped = stopped; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -511,7 +481,7 @@ static int langwell_ep_disable(struct us + + ep = container_of(_ep, struct langwell_ep, ep); + dev = ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (!_ep || !ep->desc) + return -EINVAL; +@@ -535,8 +505,8 @@ static int langwell_ep_disable(struct us + + spin_unlock_irqrestore(&dev->lock, flags); + +- DBG(dev, "disabled %s\n", _ep->name); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "disabled %s\n", _ep->name); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + + return 0; + } +@@ -555,7 +525,7 @@ static struct usb_request *langwell_allo + + ep = container_of(_ep, struct langwell_ep, ep); + dev = ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + req = kzalloc(sizeof(*req), gfp_flags); + if (!req) +@@ -564,8 +534,8 @@ static struct usb_request *langwell_allo + req->req.dma = DMA_ADDR_INVALID; + INIT_LIST_HEAD(&req->queue); + +- VDBG(dev, "alloc request for %s\n", _ep->name); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "alloc request for %s\n", _ep->name); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return &req->req; + } + +@@ -580,7 +550,7 @@ static void langwell_free_request(struct + + ep = container_of(_ep, struct langwell_ep, ep); + dev = ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (!_ep || !_req) + return; +@@ -591,8 +561,8 @@ static void langwell_free_request(struct + if (_req) + kfree(req); + +- VDBG(dev, "free request for %s\n", _ep->name); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "free request for %s\n", _ep->name); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -608,23 +578,24 @@ static int queue_dtd(struct langwell_ep + struct langwell_udc *dev; + + dev = ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + i = ep->ep_num * 2 + is_in(ep); + dqh = &dev->ep_dqh[i]; + + if (ep->ep_num) +- VDBG(dev, "%s\n", ep->name); ++ dev_vdbg(&dev->pdev->dev, "%s\n", ep->name); + else + /* ep0 */ +- VDBG(dev, "%s-%s\n", ep->name, is_in(ep) ? "in" : "out"); ++ dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep)); + +- VDBG(dev, "ep_dqh[%d] addr: 0x%08x\n", i, (u32)&(dev->ep_dqh[i])); ++ dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%08x\n", ++ i, (u32)&(dev->ep_dqh[i])); + + bit_mask = is_in(ep) ? + (1 << (ep->ep_num + 16)) : (1 << (ep->ep_num)); + +- VDBG(dev, "bit_mask = 0x%08x\n", bit_mask); ++ dev_vdbg(&dev->pdev->dev, "bit_mask = 0x%08x\n", bit_mask); + + /* check if the pipe is empty */ + if (!(list_empty(&ep->queue))) { +@@ -665,14 +636,17 @@ static int queue_dtd(struct langwell_ep + /* clear active and halt bit */ + dtd_status = (u8) ~(DTD_STS_ACTIVE | DTD_STS_HALTED); + dqh->dtd_status &= dtd_status; +- VDBG(dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status); ++ dev_vdbg(&dev->pdev->dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status); ++ ++ /* ensure that updates to the dQH will occure before priming */ ++ wmb(); + + /* write 1 to endptprime register to PRIME endpoint */ + bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << ep->ep_num); +- VDBG(dev, "endprime bit_mask = 0x%08x\n", bit_mask); ++ dev_vdbg(&dev->pdev->dev, "endprime bit_mask = 0x%08x\n", bit_mask); + writel(bit_mask, &dev->op_regs->endptprime); + out: +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -687,7 +661,7 @@ static struct langwell_dtd *build_dtd(st + int i; + + dev = req->ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* the maximum transfer length, up to 16k bytes */ + *length = min(req->req.length - req->req.actual, +@@ -708,7 +682,7 @@ static struct langwell_dtd *build_dtd(st + + /* fill in total bytes with transfer size */ + dtd->dtd_total = cpu_to_le16(*length); +- VDBG(dev, "dtd->dtd_total = %d\n", dtd->dtd_total); ++ dev_vdbg(&dev->pdev->dev, "dtd->dtd_total = %d\n", dtd->dtd_total); + + /* set is_last flag if req->req.zero is set or not */ + if (req->req.zero) { +@@ -722,7 +696,7 @@ static struct langwell_dtd *build_dtd(st + *is_last = 0; + + if (*is_last == 0) +- VDBG(dev, "multi-dtd request!\n"); ++ dev_vdbg(&dev->pdev->dev, "multi-dtd request!\n"); + + /* set interrupt on complete bit for the last dTD */ + if (*is_last && !req->req.no_interrupt) +@@ -733,10 +707,12 @@ static struct langwell_dtd *build_dtd(st + + /* set the active bit of status field to 1 */ + dtd->dtd_status = DTD_STS_ACTIVE; +- VDBG(dev, "dtd->dtd_status = 0x%02x\n", dtd->dtd_status); ++ dev_vdbg(&dev->pdev->dev, "dtd->dtd_status = 0x%02x\n", ++ dtd->dtd_status); + +- VDBG(dev, "length = %d, dma addr= 0x%08x\n", *length, (int)*dma); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "length = %d, dma addr= 0x%08x\n", ++ *length, (int)*dma); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return dtd; + } + +@@ -751,7 +727,7 @@ static int req_to_dtd(struct langwell_re + dma_addr_t dma; + + dev = req->ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + do { + dtd = build_dtd(req, &count, &dma, &is_last); + if (dtd == NULL) +@@ -773,7 +749,7 @@ static int req_to_dtd(struct langwell_re + + req->tail = dtd; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -803,9 +779,9 @@ static int langwell_ep_queue(struct usb_ + + dev = ep->dev; + req->ep = ep; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + +- if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { ++ if (usb_endpoint_xfer_isoc(ep->desc)) { + if (req->req.length > ep->ep.maxpacket) + return -EMSGSIZE; + is_iso = 1; +@@ -818,7 +794,7 @@ static int langwell_ep_queue(struct usb_ + if (_req->dma == DMA_ADDR_INVALID) { + /* WORKAROUND: WARN_ON(size == 0) */ + if (_req->length == 0) { +- VDBG(dev, "req->length: 0->1\n"); ++ dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n"); + zlflag = 1; + _req->length++; + } +@@ -827,24 +803,25 @@ static int langwell_ep_queue(struct usb_ + _req->buf, _req->length, + is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + if (zlflag && (_req->length == 1)) { +- VDBG(dev, "req->length: 1->0\n"); ++ dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n"); + zlflag = 0; + _req->length = 0; + } + + req->mapped = 1; +- VDBG(dev, "req->mapped = 1\n"); ++ dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n"); + } else { + dma_sync_single_for_device(&dev->pdev->dev, + _req->dma, _req->length, + is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + req->mapped = 0; +- VDBG(dev, "req->mapped = 0\n"); ++ dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n"); + } + +- DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08llx\n", +- _ep->name, +- _req, _req->length, _req->buf, (unsigned long long)_req->dma); ++ dev_dbg(&dev->pdev->dev, ++ "%s queue req %p, len %u, buf %p, dma 0x%08x\n", ++ _ep->name, ++ _req, _req->length, _req->buf, (int)_req->dma); + + _req->status = -EINPROGRESS; + _req->actual = 0; +@@ -866,12 +843,12 @@ static int langwell_ep_queue(struct usb_ + + if (likely(req != NULL)) { + list_add_tail(&req->queue, &ep->queue); +- VDBG(dev, "list_add_tail() \n"); ++ dev_vdbg(&dev->pdev->dev, "list_add_tail()\n"); + } + + spin_unlock_irqrestore(&dev->lock, flags); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -888,7 +865,7 @@ static int langwell_ep_dequeue(struct us + + ep = container_of(_ep, struct langwell_ep, ep); + dev = ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (!_ep || !ep->desc || !_req) + return -EINVAL; +@@ -924,7 +901,7 @@ static int langwell_ep_dequeue(struct us + + /* queue head may be partially complete. */ + if (ep->queue.next == &req->queue) { +- DBG(dev, "unlink (%s) dma\n", _ep->name); ++ dev_dbg(&dev->pdev->dev, "unlink (%s) dma\n", _ep->name); + _req->status = -ECONNRESET; + langwell_ep_fifo_flush(&ep->ep); + +@@ -963,7 +940,7 @@ done: + ep->stopped = stopped; + spin_unlock_irqrestore(&dev->lock, flags); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return retval; + } + +@@ -976,7 +953,7 @@ static void ep_set_halt(struct langwell_ + u32 endptctrl = 0; + int ep_num; + struct langwell_udc *dev = ep->dev; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + ep_num = ep->ep_num; + endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); +@@ -1001,7 +978,7 @@ static void ep_set_halt(struct langwell_ + + writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -1016,7 +993,7 @@ static int langwell_ep_set_halt(struct u + ep = container_of(_ep, struct langwell_ep, ep); + dev = ep->dev; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (!_ep || !ep->desc) + return -EINVAL; +@@ -1024,8 +1001,7 @@ static int langwell_ep_set_halt(struct u + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) + return -ESHUTDOWN; + +- if (ep->desc && (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) +- == USB_ENDPOINT_XFER_ISOC) ++ if (usb_endpoint_xfer_isoc(ep->desc)) + return -EOPNOTSUPP; + + spin_lock_irqsave(&dev->lock, flags); +@@ -1036,7 +1012,7 @@ static int langwell_ep_set_halt(struct u + */ + if (!list_empty(&ep->queue) && is_in(ep) && value) { + /* IN endpoint FIFO holds bytes */ +- DBG(dev, "%s FIFO holds bytes\n", _ep->name); ++ dev_dbg(&dev->pdev->dev, "%s FIFO holds bytes\n", _ep->name); + retval = -EAGAIN; + goto done; + } +@@ -1050,8 +1026,9 @@ static int langwell_ep_set_halt(struct u + } + done: + spin_unlock_irqrestore(&dev->lock, flags); +- DBG(dev, "%s %s halt\n", _ep->name, value ? "set" : "clear"); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "%s %s halt\n", ++ _ep->name, value ? "set" : "clear"); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return retval; + } + +@@ -1065,12 +1042,12 @@ static int langwell_ep_set_wedge(struct + ep = container_of(_ep, struct langwell_ep, ep); + dev = ep->dev; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (!_ep || !ep->desc) + return -EINVAL; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return usb_ep_set_halt(_ep); + } + +@@ -1086,15 +1063,16 @@ static void langwell_ep_fifo_flush(struc + ep = container_of(_ep, struct langwell_ep, ep); + dev = ep->dev; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (!_ep || !ep->desc) { +- VDBG(dev, "ep or ep->desc is NULL\n"); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n"); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return; + } + +- VDBG(dev, "%s-%s fifo flush\n", _ep->name, is_in(ep) ? "in" : "out"); ++ dev_vdbg(&dev->pdev->dev, "%s-%s fifo flush\n", ++ _ep->name, DIR_STRING(ep)); + + /* flush endpoint buffer */ + if (ep->ep_num == 0) +@@ -1110,14 +1088,14 @@ static void langwell_ep_fifo_flush(struc + writel(flush_bit, &dev->op_regs->endptflush); + while (readl(&dev->op_regs->endptflush)) { + if (time_after(jiffies, timeout)) { +- ERROR(dev, "ep flush timeout\n"); ++ dev_err(&dev->pdev->dev, "ep flush timeout\n"); + goto done; + } + cpu_relax(); + } + } while (readl(&dev->op_regs->endptstat) & flush_bit); + done: +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -1167,11 +1145,11 @@ static int langwell_get_frame(struct usb + return -ENODEV; + + dev = container_of(_gadget, struct langwell_udc, gadget); +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + retval = readl(&dev->op_regs->frindex) & FRINDEX_MASK; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return retval; + } + +@@ -1180,18 +1158,20 @@ static int langwell_get_frame(struct usb + static int langwell_wakeup(struct usb_gadget *_gadget) + { + struct langwell_udc *dev; +- u32 portsc1, devlc; +- unsigned long flags; ++ u32 portsc1, devlc; ++ unsigned long flags; + + if (!_gadget) + return 0; + + dev = container_of(_gadget, struct langwell_udc, gadget); +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + +- /* Remote Wakeup feature not enabled by host */ +- if (!dev->remote_wakeup) ++ /* remote wakeup feature not enabled by host */ ++ if (!dev->remote_wakeup) { ++ dev_info(&dev->pdev->dev, "remote wakeup is disabled\n"); + return -ENOTSUPP; ++ } + + spin_lock_irqsave(&dev->lock, flags); + +@@ -1215,13 +1195,12 @@ static int langwell_wakeup(struct usb_ga + + /* exit PHY low power suspend */ + devlc = readl(&dev->op_regs->devlc); +- VDBG(dev, "devlc = 0x%08x\n", devlc); + devlc &= ~LPM_PHCD; + writel(devlc, &dev->op_regs->devlc); + + spin_unlock_irqrestore(&dev->lock, flags); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -1231,16 +1210,17 @@ static int langwell_vbus_session(struct + { + struct langwell_udc *dev; + unsigned long flags; +- u32 usbcmd; ++ u32 usbcmd; + + if (!_gadget) + return -ENODEV; + + dev = container_of(_gadget, struct langwell_udc, gadget); +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + spin_lock_irqsave(&dev->lock, flags); +- VDBG(dev, "VBUS status: %s\n", is_active ? "on" : "off"); ++ dev_vdbg(&dev->pdev->dev, "VBUS status: %s\n", ++ is_active ? "on" : "off"); + + dev->vbus_active = (is_active != 0); + if (dev->driver && dev->softconnected && dev->vbus_active) { +@@ -1255,7 +1235,7 @@ static int langwell_vbus_session(struct + + spin_unlock_irqrestore(&dev->lock, flags); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -1269,15 +1249,15 @@ static int langwell_vbus_draw(struct usb + return -ENODEV; + + dev = container_of(_gadget, struct langwell_udc, gadget); +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (dev->transceiver) { +- VDBG(dev, "otg_set_power\n"); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "otg_set_power\n"); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return otg_set_power(dev->transceiver, mA); + } + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return -ENOTSUPP; + } + +@@ -1286,15 +1266,15 @@ static int langwell_vbus_draw(struct usb + static int langwell_pullup(struct usb_gadget *_gadget, int is_on) + { + struct langwell_udc *dev; +- u32 usbcmd; +- unsigned long flags; ++ u32 usbcmd; ++ unsigned long flags; + + if (!_gadget) + return -ENODEV; + + dev = container_of(_gadget, struct langwell_udc, gadget); + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + spin_lock_irqsave(&dev->lock, flags); + dev->softconnected = (is_on != 0); +@@ -1310,7 +1290,7 @@ static int langwell_pullup(struct usb_ga + } + spin_unlock_irqrestore(&dev->lock, flags); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -1351,7 +1331,7 @@ static int langwell_udc_reset(struct lan + if (!dev) + return -EINVAL; + +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* set controller to stop state */ + usbcmd = readl(&dev->op_regs->usbcmd); +@@ -1367,7 +1347,7 @@ static int langwell_udc_reset(struct lan + timeout = jiffies + RESET_TIMEOUT; + while (readl(&dev->op_regs->usbcmd) & CMD_RST) { + if (time_after(jiffies, timeout)) { +- ERROR(dev, "device reset timeout\n"); ++ dev_err(&dev->pdev->dev, "device reset timeout\n"); + return -ETIMEDOUT; + } + cpu_relax(); +@@ -1382,7 +1362,7 @@ static int langwell_udc_reset(struct lan + + writel(usbmode, &dev->op_regs->usbmode); + usbmode = readl(&dev->op_regs->usbmode); +- VDBG(dev, "usbmode=0x%08x\n", usbmode); ++ dev_vdbg(&dev->pdev->dev, "usbmode=0x%08x\n", usbmode); + + /* Write-Clear setup status */ + writel(0, &dev->op_regs->usbsts); +@@ -1400,10 +1380,11 @@ static int langwell_udc_reset(struct lan + endpointlistaddr &= ENDPOINTLISTADDR_MASK; + writel(endpointlistaddr, &dev->op_regs->endpointlistaddr); + +- VDBG(dev, "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n", +- dev->ep_dqh, endpointlistaddr, +- readl(&dev->op_regs->endpointlistaddr)); +- DBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, ++ "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n", ++ dev->ep_dqh, endpointlistaddr, ++ readl(&dev->op_regs->endpointlistaddr)); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -1415,7 +1396,7 @@ static int eps_reinit(struct langwell_ud + char name[14]; + int i; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* initialize ep0 */ + ep = &dev->ep[0]; +@@ -1453,7 +1434,7 @@ static int eps_reinit(struct langwell_ud + ep->dqh = &dev->ep_dqh[i]; + } + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -1462,7 +1443,7 @@ static int eps_reinit(struct langwell_ud + static void langwell_udc_start(struct langwell_udc *dev) + { + u32 usbintr, usbcmd; +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* enable interrupts */ + usbintr = INTR_ULPIE /* ULPI */ +@@ -1485,7 +1466,7 @@ static void langwell_udc_start(struct la + usbcmd |= CMD_RUNSTOP; + writel(usbcmd, &dev->op_regs->usbcmd); + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return; + } + +@@ -1495,7 +1476,7 @@ static void langwell_udc_stop(struct lan + { + u32 usbcmd; + +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* disable all interrupts */ + writel(0, &dev->op_regs->usbintr); +@@ -1508,7 +1489,7 @@ static void langwell_udc_stop(struct lan + usbcmd &= ~CMD_RUNSTOP; + writel(usbcmd, &dev->op_regs->usbcmd); + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return; + } + +@@ -1518,7 +1499,7 @@ static void stop_activity(struct langwel + struct usb_gadget_driver *driver) + { + struct langwell_ep *ep; +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + nuke(&dev->ep[0], -ESHUTDOWN); + +@@ -1533,7 +1514,7 @@ static void stop_activity(struct langwel + spin_lock(&dev->lock); + } + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -1659,13 +1640,15 @@ static ssize_t show_langwell_udc(struct + "Over-current Change: %s\n" + "Port Enable/Disable Change: %s\n" + "Port Enabled/Disabled: %s\n" +- "Current Connect Status: %s\n\n", ++ "Current Connect Status: %s\n" ++ "LPM Suspend Status: %s\n\n", + (tmp_reg & PORTS_PR) ? "Reset" : "Not Reset", + (tmp_reg & PORTS_SUSP) ? "Suspend " : "Not Suspend", + (tmp_reg & PORTS_OCC) ? "Detected" : "No", + (tmp_reg & PORTS_PEC) ? "Changed" : "Not Changed", + (tmp_reg & PORTS_PE) ? "Enable" : "Not Correct", +- (tmp_reg & PORTS_CCS) ? "Attached" : "Not Attached"); ++ (tmp_reg & PORTS_CCS) ? "Attached" : "Not Attached", ++ (tmp_reg & PORTS_SLP) ? "LPM L1" : "LPM L0"); + size -= t; + next += t; + +@@ -1676,7 +1659,7 @@ static ssize_t show_langwell_udc(struct + "Serial Transceiver : %d\n" + "Port Speed: %s\n" + "Port Force Full Speed Connenct: %s\n" +- "PHY Low Power Suspend Clock Disable: %s\n" ++ "PHY Low Power Suspend Clock: %s\n" + "BmAttributes: %d\n\n", + LPM_PTS(tmp_reg), + (tmp_reg & LPM_STS) ? 1 : 0, +@@ -1816,7 +1799,7 @@ int usb_gadget_register_driver(struct us + if (!dev) + return -ENODEV; + +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (dev->driver) + return -EBUSY; +@@ -1832,7 +1815,7 @@ int usb_gadget_register_driver(struct us + + retval = driver->bind(&dev->gadget); + if (retval) { +- DBG(dev, "bind to driver %s --> %d\n", ++ dev_dbg(&dev->pdev->dev, "bind to driver %s --> %d\n", + driver->driver.name, retval); + dev->driver = NULL; + dev->gadget.dev.driver = NULL; +@@ -1851,13 +1834,13 @@ int usb_gadget_register_driver(struct us + if (dev->got_irq) + langwell_udc_start(dev); + +- VDBG(dev, "After langwell_udc_start(), print all registers:\n"); +-#ifdef VERBOSE ++ dev_vdbg(&dev->pdev->dev, ++ "After langwell_udc_start(), print all registers:\n"); + print_all_registers(dev); +-#endif + +- INFO(dev, "register driver: %s\n", driver->driver.name); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_info(&dev->pdev->dev, "register driver: %s\n", ++ driver->driver.name); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + + err_unbind: +@@ -1865,7 +1848,7 @@ err_unbind: + dev->gadget.dev.driver = NULL; + dev->driver = NULL; + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return retval; + } + EXPORT_SYMBOL(usb_gadget_register_driver); +@@ -1880,7 +1863,7 @@ int usb_gadget_unregister_driver(struct + if (!dev) + return -ENODEV; + +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (unlikely(!driver || !driver->bind || !driver->unbind)) + return -EINVAL; +@@ -1910,8 +1893,9 @@ int usb_gadget_unregister_driver(struct + + device_remove_file(&dev->pdev->dev, &dev_attr_function); + +- INFO(dev, "unregistered driver '%s'\n", driver->driver.name); +- DBG(dev, "<--- %s()\n", __func__); ++ dev_info(&dev->pdev->dev, "unregistered driver '%s'\n", ++ driver->driver.name); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + EXPORT_SYMBOL(usb_gadget_unregister_driver); +@@ -1930,7 +1914,7 @@ static void setup_tripwire(struct langwe + unsigned long timeout; + struct langwell_dqh *dqh; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* ep0 OUT dQH */ + dqh = &dev->ep_dqh[EP_DIR_OUT]; +@@ -1943,7 +1927,7 @@ static void setup_tripwire(struct langwe + timeout = jiffies + SETUPSTAT_TIMEOUT; + while (readl(&dev->op_regs->endptsetupstat)) { + if (time_after(jiffies, timeout)) { +- ERROR(dev, "setup_tripwire timeout\n"); ++ dev_err(&dev->pdev->dev, "setup_tripwire timeout\n"); + break; + } + cpu_relax(); +@@ -1963,7 +1947,7 @@ static void setup_tripwire(struct langwe + usbcmd = readl(&dev->op_regs->usbcmd); + writel(usbcmd & ~CMD_SUTW, &dev->op_regs->usbcmd); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -1972,7 +1956,7 @@ static void ep0_stall(struct langwell_ud + { + u32 endptctrl; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* set TX and RX to stall */ + endptctrl = readl(&dev->op_regs->endptctrl[0]); +@@ -1983,7 +1967,7 @@ static void ep0_stall(struct langwell_ud + dev->ep0_state = WAIT_FOR_SETUP; + dev->ep0_dir = USB_DIR_OUT; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -1994,7 +1978,7 @@ static int prime_status_phase(struct lan + struct langwell_ep *ep; + int status = 0; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (dir == EP_DIR_IN) + dev->ep0_dir = USB_DIR_IN; +@@ -2019,11 +2003,11 @@ static int prime_status_phase(struct lan + return -ENOMEM; + + if (status) +- ERROR(dev, "can't queue ep0 status request\n"); ++ dev_err(&dev->pdev->dev, "can't queue ep0 status request\n"); + + list_add_tail(&req->queue, &ep->queue); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return status; + } + +@@ -2032,11 +2016,11 @@ static int prime_status_phase(struct lan + static void set_address(struct langwell_udc *dev, u16 value, + u16 index, u16 length) + { +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* save the new address to device struct */ + dev->dev_addr = (u8) value; +- VDBG(dev, "dev->dev_addr = %d\n", dev->dev_addr); ++ dev_vdbg(&dev->pdev->dev, "dev->dev_addr = %d\n", dev->dev_addr); + + /* update usb state */ + dev->usb_state = USB_STATE_ADDRESS; +@@ -2045,7 +2029,7 @@ static void set_address(struct langwell_ + if (prime_status_phase(dev, EP_DIR_IN)) + ep0_stall(dev); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -2054,7 +2038,7 @@ static struct langwell_ep *get_ep_by_win + u16 wIndex) + { + struct langwell_ep *ep; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) + return &dev->ep[0]; +@@ -2073,7 +2057,7 @@ static struct langwell_ep *get_ep_by_win + return ep; + } + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return NULL; + } + +@@ -2085,7 +2069,7 @@ static int ep_is_stall(struct langwell_e + u32 endptctrl; + int retval; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + endptctrl = readl(&dev->op_regs->endptctrl[ep->ep_num]); + if (is_in(ep)) +@@ -2093,7 +2077,7 @@ static int ep_is_stall(struct langwell_e + else + retval = endptctrl & EPCTRL_RXS ? 1 : 0; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return retval; + } + +@@ -2107,7 +2091,7 @@ static void get_status(struct langwell_u + u16 status_data = 0; /* 16 bits cpu view status data */ + int status = 0; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + ep = &dev->ep[0]; + +@@ -2129,6 +2113,8 @@ static void get_status(struct langwell_u + status_data = ep_is_stall(epn) << USB_ENDPOINT_HALT; + } + ++ dev_dbg(&dev->pdev->dev, "get status data: 0x%04x\n", status_data); ++ + dev->ep0_dir = USB_DIR_IN; + + /* borrow the per device status_req */ +@@ -2150,18 +2136,19 @@ static void get_status(struct langwell_u + goto stall; + + if (status) { +- ERROR(dev, "response error on GET_STATUS request\n"); ++ dev_err(&dev->pdev->dev, ++ "response error on GET_STATUS request\n"); + goto stall; + } + + list_add_tail(&req->queue, &ep->queue); + dev->ep0_state = DATA_STATE_XMIT; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return; + stall: + ep0_stall(dev); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -2173,12 +2160,12 @@ static void handle_setup_packet(struct l + u16 wIndex = le16_to_cpu(setup->wIndex); + u16 wLength = le16_to_cpu(setup->wLength); + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* ep0 fifo flush */ + nuke(&dev->ep[0], -ESHUTDOWN); + +- DBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", ++ dev_dbg(&dev->pdev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", + setup->bRequestType, setup->bRequest, + wValue, wIndex, wLength); + +@@ -2197,7 +2184,7 @@ static void handle_setup_packet(struct l + /* We process some stardard setup requests here */ + switch (setup->bRequest) { + case USB_REQ_GET_STATUS: +- DBG(dev, "SETUP: USB_REQ_GET_STATUS\n"); ++ dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_GET_STATUS\n"); + /* get status, DATA and STATUS phase */ + if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK)) + != (USB_DIR_IN | USB_TYPE_STANDARD)) +@@ -2206,7 +2193,7 @@ static void handle_setup_packet(struct l + goto end; + + case USB_REQ_SET_ADDRESS: +- DBG(dev, "SETUP: USB_REQ_SET_ADDRESS\n"); ++ dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_SET_ADDRESS\n"); + /* STATUS phase */ + if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD + | USB_RECIP_DEVICE)) +@@ -2220,9 +2207,11 @@ static void handle_setup_packet(struct l + { + int rc = -EOPNOTSUPP; + if (setup->bRequest == USB_REQ_SET_FEATURE) +- DBG(dev, "SETUP: USB_REQ_SET_FEATURE\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_SET_FEATURE\n"); + else if (setup->bRequest == USB_REQ_CLEAR_FEATURE) +- DBG(dev, "SETUP: USB_REQ_CLEAR_FEATURE\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_CLEAR_FEATURE\n"); + + if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) + == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) { +@@ -2240,8 +2229,8 @@ static void handle_setup_packet(struct l + + spin_unlock(&dev->lock); + rc = langwell_ep_set_halt(&epn->ep, +- (setup->bRequest == USB_REQ_SET_FEATURE) +- ? 1 : 0); ++ (setup->bRequest == USB_REQ_SET_FEATURE) ++ ? 1 : 0); + spin_lock(&dev->lock); + + } else if ((setup->bRequestType & (USB_RECIP_MASK +@@ -2274,31 +2263,38 @@ static void handle_setup_packet(struct l + } + + case USB_REQ_GET_DESCRIPTOR: +- DBG(dev, "SETUP: USB_REQ_GET_DESCRIPTOR\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_GET_DESCRIPTOR\n"); + goto delegate; + + case USB_REQ_SET_DESCRIPTOR: +- DBG(dev, "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n"); + goto delegate; + + case USB_REQ_GET_CONFIGURATION: +- DBG(dev, "SETUP: USB_REQ_GET_CONFIGURATION\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_GET_CONFIGURATION\n"); + goto delegate; + + case USB_REQ_SET_CONFIGURATION: +- DBG(dev, "SETUP: USB_REQ_SET_CONFIGURATION\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_SET_CONFIGURATION\n"); + goto delegate; + + case USB_REQ_GET_INTERFACE: +- DBG(dev, "SETUP: USB_REQ_GET_INTERFACE\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_GET_INTERFACE\n"); + goto delegate; + + case USB_REQ_SET_INTERFACE: +- DBG(dev, "SETUP: USB_REQ_SET_INTERFACE\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_SET_INTERFACE\n"); + goto delegate; + + case USB_REQ_SYNCH_FRAME: +- DBG(dev, "SETUP: USB_REQ_SYNCH_FRAME unsupported\n"); ++ dev_dbg(&dev->pdev->dev, ++ "SETUP: USB_REQ_SYNCH_FRAME unsupported\n"); + goto delegate; + + default: +@@ -2310,7 +2306,8 @@ delegate: + /* DATA phase from gadget, STATUS phase from udc */ + dev->ep0_dir = (setup->bRequestType & USB_DIR_IN) + ? USB_DIR_IN : USB_DIR_OUT; +- VDBG(dev, "dev->ep0_dir = 0x%x, wLength = %d\n", ++ dev_vdbg(&dev->pdev->dev, ++ "dev->ep0_dir = 0x%x, wLength = %d\n", + dev->ep0_dir, wLength); + spin_unlock(&dev->lock); + if (dev->driver->setup(&dev->gadget, +@@ -2322,7 +2319,8 @@ delegate: + } else { + /* no DATA phase, IN STATUS phase from gadget */ + dev->ep0_dir = USB_DIR_IN; +- VDBG(dev, "dev->ep0_dir = 0x%x, wLength = %d\n", ++ dev_vdbg(&dev->pdev->dev, ++ "dev->ep0_dir = 0x%x, wLength = %d\n", + dev->ep0_dir, wLength); + spin_unlock(&dev->lock); + if (dev->driver->setup(&dev->gadget, +@@ -2334,7 +2332,7 @@ delegate: + break; + } + end: +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return; + } + +@@ -2359,7 +2357,7 @@ static int process_ep_req(struct langwel + td_complete = 0; + actual = curr_req->req.length; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + for (i = 0; i < curr_req->dtd_count; i++) { + remaining_length = le16_to_cpu(curr_dtd->dtd_total); +@@ -2372,10 +2370,12 @@ static int process_ep_req(struct langwel + /* transfers completed successfully */ + if (!remaining_length) { + td_complete++; +- VDBG(dev, "dTD transmitted successfully\n"); ++ dev_vdbg(&dev->pdev->dev, ++ "dTD transmitted successfully\n"); + } else { + if (dir) { +- VDBG(dev, "TX dTD remains data\n"); ++ dev_vdbg(&dev->pdev->dev, ++ "TX dTD remains data\n"); + retval = -EPROTO; + break; + +@@ -2387,27 +2387,32 @@ static int process_ep_req(struct langwel + } else { + /* transfers completed with errors */ + if (dtd_status & DTD_STS_ACTIVE) { +- DBG(dev, "request not completed\n"); ++ dev_dbg(&dev->pdev->dev, ++ "dTD status ACTIVE dQH[%d]\n", index); + retval = 1; + return retval; + } else if (dtd_status & DTD_STS_HALTED) { +- ERROR(dev, "dTD error %08x dQH[%d]\n", +- dtd_status, index); ++ dev_err(&dev->pdev->dev, ++ "dTD error %08x dQH[%d]\n", ++ dtd_status, index); + /* clear the errors and halt condition */ + curr_dqh->dtd_status = 0; + retval = -EPIPE; + break; + } else if (dtd_status & DTD_STS_DBE) { +- DBG(dev, "data buffer (overflow) error\n"); ++ dev_dbg(&dev->pdev->dev, ++ "data buffer (overflow) error\n"); + retval = -EPROTO; + break; + } else if (dtd_status & DTD_STS_TRE) { +- DBG(dev, "transaction(ISO) error\n"); ++ dev_dbg(&dev->pdev->dev, ++ "transaction(ISO) error\n"); + retval = -EILSEQ; + break; + } else +- ERROR(dev, "unknown error (0x%x)!\n", +- dtd_status); ++ dev_err(&dev->pdev->dev, ++ "unknown error (0x%x)!\n", ++ dtd_status); + } + + if (i != curr_req->dtd_count - 1) +@@ -2420,7 +2425,7 @@ static int process_ep_req(struct langwel + + curr_req->req.actual = actual; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -2430,7 +2435,7 @@ static void ep0_req_complete(struct lang + struct langwell_ep *ep0, struct langwell_request *req) + { + u32 new_addr; +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (dev->usb_state == USB_STATE_ADDRESS) { + /* set the new address */ +@@ -2438,7 +2443,7 @@ static void ep0_req_complete(struct lang + writel(new_addr << USBADR_SHIFT, &dev->op_regs->deviceaddr); + + new_addr = USBADR(readl(&dev->op_regs->deviceaddr)); +- VDBG(dev, "new_addr = %d\n", new_addr); ++ dev_vdbg(&dev->pdev->dev, "new_addr = %d\n", new_addr); + } + + done(ep0, req, 0); +@@ -2458,14 +2463,14 @@ static void ep0_req_complete(struct lang + dev->ep0_state = WAIT_FOR_SETUP; + break; + case WAIT_FOR_SETUP: +- ERROR(dev, "unexpect ep0 packets\n"); ++ dev_err(&dev->pdev->dev, "unexpect ep0 packets\n"); + break; + default: + ep0_stall(dev); + break; + } + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -2477,16 +2482,17 @@ static void handle_trans_complete(struct + struct langwell_ep *epn; + struct langwell_request *curr_req, *temp_req; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + complete_bits = readl(&dev->op_regs->endptcomplete); +- VDBG(dev, "endptcomplete register: 0x%08x\n", complete_bits); ++ dev_vdbg(&dev->pdev->dev, "endptcomplete register: 0x%08x\n", ++ complete_bits); + + /* Write-Clear the bits in endptcomplete register */ + writel(complete_bits, &dev->op_regs->endptcomplete); + + if (!complete_bits) { +- DBG(dev, "complete_bits = 0\n"); ++ dev_dbg(&dev->pdev->dev, "complete_bits = 0\n"); + goto done; + } + +@@ -2506,23 +2512,25 @@ static void handle_trans_complete(struct + epn = &dev->ep[i]; + + if (epn->name == NULL) { +- WARNING(dev, "invalid endpoint\n"); ++ dev_warn(&dev->pdev->dev, "invalid endpoint\n"); + continue; + } + + if (i < 2) + /* ep0 in and out */ +- DBG(dev, "%s-%s transfer completed\n", ++ dev_dbg(&dev->pdev->dev, "%s-%s transfer completed\n", + epn->name, + is_in(epn) ? "in" : "out"); + else +- DBG(dev, "%s transfer completed\n", epn->name); ++ dev_dbg(&dev->pdev->dev, "%s transfer completed\n", ++ epn->name); + + /* process the req queue until an uncomplete request */ + list_for_each_entry_safe(curr_req, temp_req, + &epn->queue, queue) { + status = process_ep_req(dev, i, curr_req); +- VDBG(dev, "%s req status: %d\n", epn->name, status); ++ dev_vdbg(&dev->pdev->dev, "%s req status: %d\n", ++ epn->name, status); + + if (status) + break; +@@ -2540,7 +2548,7 @@ static void handle_trans_complete(struct + } + } + done: +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return; + } + +@@ -2551,14 +2559,14 @@ static void handle_port_change(struct la + u32 portsc1, devlc; + u32 speed; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (dev->bus_reset) + dev->bus_reset = 0; + + portsc1 = readl(&dev->op_regs->portsc1); + devlc = readl(&dev->op_regs->devlc); +- VDBG(dev, "portsc1 = 0x%08x, devlc = 0x%08x\n", ++ dev_vdbg(&dev->pdev->dev, "portsc1 = 0x%08x, devlc = 0x%08x\n", + portsc1, devlc); + + /* bus reset is finished */ +@@ -2579,25 +2587,22 @@ static void handle_port_change(struct la + dev->gadget.speed = USB_SPEED_UNKNOWN; + break; + } +- VDBG(dev, "speed = %d, dev->gadget.speed = %d\n", ++ dev_vdbg(&dev->pdev->dev, ++ "speed = %d, dev->gadget.speed = %d\n", + speed, dev->gadget.speed); + } + + /* LPM L0 to L1 */ + if (dev->lpm && dev->lpm_state == LPM_L0) + if (portsc1 & PORTS_SUSP && portsc1 & PORTS_SLP) { +- INFO(dev, "LPM L0 to L1\n"); +- dev->lpm_state = LPM_L1; ++ dev_info(&dev->pdev->dev, "LPM L0 to L1\n"); ++ dev->lpm_state = LPM_L1; + } + + /* LPM L1 to L0, force resume or remote wakeup finished */ + if (dev->lpm && dev->lpm_state == LPM_L1) + if (!(portsc1 & PORTS_SUSP)) { +- if (portsc1 & PORTS_SLP) +- INFO(dev, "LPM L1 to L0, force resume\n"); +- else +- INFO(dev, "LPM L1 to L0, remote wakeup\n"); +- ++ dev_info(&dev->pdev->dev, "LPM L1 to L0\n"); + dev->lpm_state = LPM_L0; + } + +@@ -2605,7 +2610,7 @@ static void handle_port_change(struct la + if (!dev->resume_state) + dev->usb_state = USB_STATE_DEFAULT; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -2617,7 +2622,7 @@ static void handle_usb_reset(struct lang + endptcomplete; + unsigned long timeout; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* Write-Clear the device address */ + deviceaddr = readl(&dev->op_regs->deviceaddr); +@@ -2651,7 +2656,7 @@ static void handle_usb_reset(struct lang + timeout = jiffies + PRIME_TIMEOUT; + while (readl(&dev->op_regs->endptprime)) { + if (time_after(jiffies, timeout)) { +- ERROR(dev, "USB reset timeout\n"); ++ dev_err(&dev->pdev->dev, "USB reset timeout\n"); + break; + } + cpu_relax(); +@@ -2661,7 +2666,7 @@ static void handle_usb_reset(struct lang + writel((u32) ~0, &dev->op_regs->endptflush); + + if (readl(&dev->op_regs->portsc1) & PORTS_PR) { +- VDBG(dev, "USB bus reset\n"); ++ dev_vdbg(&dev->pdev->dev, "USB bus reset\n"); + /* bus is reseting */ + dev->bus_reset = 1; + +@@ -2669,7 +2674,7 @@ static void handle_usb_reset(struct lang + stop_activity(dev, dev->driver); + dev->usb_state = USB_STATE_DEFAULT; + } else { +- VDBG(dev, "device controller reset\n"); ++ dev_vdbg(&dev->pdev->dev, "device controller reset\n"); + /* controller reset */ + langwell_udc_reset(dev); + +@@ -2691,7 +2696,7 @@ static void handle_usb_reset(struct lang + dev->lotg->hsm.b_hnp_enable = 0; + #endif + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -2699,7 +2704,7 @@ static void handle_usb_reset(struct lang + static void handle_bus_suspend(struct langwell_udc *dev) + { + u32 devlc; +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + dev->resume_state = dev->usb_state; + dev->usb_state = USB_STATE_SUSPENDED; +@@ -2733,31 +2738,30 @@ static void handle_bus_suspend(struct la + spin_unlock(&dev->lock); + dev->driver->suspend(&dev->gadget); + spin_lock(&dev->lock); +- DBG(dev, "suspend %s\n", dev->driver->driver.name); ++ dev_dbg(&dev->pdev->dev, "suspend %s\n", ++ dev->driver->driver.name); + } + } + + /* enter PHY low power suspend */ + devlc = readl(&dev->op_regs->devlc); +- VDBG(dev, "devlc = 0x%08x\n", devlc); + devlc |= LPM_PHCD; + writel(devlc, &dev->op_regs->devlc); + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + + static void handle_bus_resume(struct langwell_udc *dev) + { + u32 devlc; +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + dev->usb_state = dev->resume_state; + dev->resume_state = 0; + + /* exit PHY low power suspend */ + devlc = readl(&dev->op_regs->devlc); +- VDBG(dev, "devlc = 0x%08x\n", devlc); + devlc &= ~LPM_PHCD; + writel(devlc, &dev->op_regs->devlc); + +@@ -2772,11 +2776,12 @@ static void handle_bus_resume(struct lan + spin_unlock(&dev->lock); + dev->driver->resume(&dev->gadget); + spin_lock(&dev->lock); +- DBG(dev, "resume %s\n", dev->driver->driver.name); ++ dev_dbg(&dev->pdev->dev, "resume %s\n", ++ dev->driver->driver.name); + } + } + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + +@@ -2789,11 +2794,11 @@ static irqreturn_t langwell_irq(int irq, + irq_sts, + portsc1; + +- VDBG(dev, "---> %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); + + if (dev->stopped) { +- VDBG(dev, "handle IRQ_NONE\n"); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n"); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return IRQ_NONE; + } + +@@ -2806,12 +2811,13 @@ static irqreturn_t langwell_irq(int irq, + usbintr = readl(&dev->op_regs->usbintr); + + irq_sts = usbsts & usbintr; +- VDBG(dev, "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n", ++ dev_vdbg(&dev->pdev->dev, ++ "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n", + usbsts, usbintr, irq_sts); + + if (!irq_sts) { +- VDBG(dev, "handle IRQ_NONE\n"); +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n"); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + spin_unlock(&dev->lock); + return IRQ_NONE; + } +@@ -2827,12 +2833,13 @@ static irqreturn_t langwell_irq(int irq, + + /* USB interrupt */ + if (irq_sts & STS_UI) { +- VDBG(dev, "USB interrupt\n"); ++ dev_vdbg(&dev->pdev->dev, "USB interrupt\n"); + + /* setup packet received from ep0 */ + if (readl(&dev->op_regs->endptsetupstat) + & EP0SETUPSTAT_MASK) { +- VDBG(dev, "USB SETUP packet received interrupt\n"); ++ dev_vdbg(&dev->pdev->dev, ++ "USB SETUP packet received interrupt\n"); + /* setup tripwire semaphone */ + setup_tripwire(dev); + handle_setup_packet(dev, &dev->local_setup_buff); +@@ -2840,7 +2847,8 @@ static irqreturn_t langwell_irq(int irq, + + /* USB transfer completion */ + if (readl(&dev->op_regs->endptcomplete)) { +- VDBG(dev, "USB transfer completion interrupt\n"); ++ dev_vdbg(&dev->pdev->dev, ++ "USB transfer completion interrupt\n"); + handle_trans_complete(dev); + } + } +@@ -2848,36 +2856,36 @@ static irqreturn_t langwell_irq(int irq, + /* SOF received interrupt (for ISO transfer) */ + if (irq_sts & STS_SRI) { + /* FIXME */ +- /* VDBG(dev, "SOF received interrupt\n"); */ ++ /* dev_vdbg(&dev->pdev->dev, "SOF received interrupt\n"); */ + } + + /* port change detect interrupt */ + if (irq_sts & STS_PCI) { +- VDBG(dev, "port change detect interrupt\n"); ++ dev_vdbg(&dev->pdev->dev, "port change detect interrupt\n"); + handle_port_change(dev); + } + + /* suspend interrrupt */ + if (irq_sts & STS_SLI) { +- VDBG(dev, "suspend interrupt\n"); ++ dev_vdbg(&dev->pdev->dev, "suspend interrupt\n"); + handle_bus_suspend(dev); + } + + /* USB reset interrupt */ + if (irq_sts & STS_URI) { +- VDBG(dev, "USB reset interrupt\n"); ++ dev_vdbg(&dev->pdev->dev, "USB reset interrupt\n"); + handle_usb_reset(dev); + } + + /* USB error or system error interrupt */ + if (irq_sts & (STS_UEI | STS_SEI)) { + /* FIXME */ +- WARNING(dev, "error IRQ, irq_sts: %x\n", irq_sts); ++ dev_warn(&dev->pdev->dev, "error IRQ, irq_sts: %x\n", irq_sts); + } + + spin_unlock(&dev->lock); + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return IRQ_HANDLED; + } + +@@ -2889,11 +2897,11 @@ static void gadget_release(struct device + { + struct langwell_udc *dev = the_controller; + +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + complete(dev->done); + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + kfree(dev); + } + +@@ -2906,7 +2914,7 @@ static void langwell_udc_remove(struct p + DECLARE_COMPLETION(done); + + BUG_ON(dev->driver); +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + dev->done = &done; + +@@ -2949,8 +2957,8 @@ static void langwell_udc_remove(struct p + + dev->cap_regs = NULL; + +- INFO(dev, "unbind\n"); +- DBG(dev, "<--- %s()\n", __func__); ++ dev_info(&dev->pdev->dev, "unbind\n"); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + + device_unregister(&dev->gadget.dev); + device_remove_file(&pdev->dev, &dev_attr_langwell_udc); +@@ -2997,7 +3005,7 @@ static int langwell_udc_probe(struct pci + spin_lock_init(&dev->lock); + + dev->pdev = pdev; +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + #ifdef OTG_TRANSCEIVER + /* PCI device is already enabled by otg_transceiver driver */ +@@ -3022,7 +3030,7 @@ static int langwell_udc_probe(struct pci + resource = pci_resource_start(pdev, 0); + len = pci_resource_len(pdev, 0); + if (!request_mem_region(resource, len, driver_name)) { +- ERROR(dev, "controller already in use\n"); ++ dev_err(&dev->pdev->dev, "controller already in use\n"); + retval = -EBUSY; + goto error; + } +@@ -3031,33 +3039,35 @@ static int langwell_udc_probe(struct pci + base = ioremap_nocache(resource, len); + #endif + if (base == NULL) { +- ERROR(dev, "can't map memory\n"); ++ dev_err(&dev->pdev->dev, "can't map memory\n"); + retval = -EFAULT; + goto error; + } + + dev->cap_regs = (struct langwell_cap_regs __iomem *) base; +- VDBG(dev, "dev->cap_regs: %p\n", dev->cap_regs); ++ dev_vdbg(&dev->pdev->dev, "dev->cap_regs: %p\n", dev->cap_regs); + dev->op_regs = (struct langwell_op_regs __iomem *) + (base + OP_REG_OFFSET); +- VDBG(dev, "dev->op_regs: %p\n", dev->op_regs); ++ dev_vdbg(&dev->pdev->dev, "dev->op_regs: %p\n", dev->op_regs); + + /* irq setup after old hardware is cleaned up */ + if (!pdev->irq) { +- ERROR(dev, "No IRQ. Check PCI setup!\n"); ++ dev_err(&dev->pdev->dev, "No IRQ. Check PCI setup!\n"); + retval = -ENODEV; + goto error; + } + + #ifndef OTG_TRANSCEIVER +- INFO(dev, "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n", ++ dev_info(&dev->pdev->dev, ++ "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n", + pdev->irq, resource, len, base); + /* enables bus-mastering for device dev */ + pci_set_master(pdev); + + if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, + driver_name, dev) != 0) { +- ERROR(dev, "request interrupt %d failed\n", pdev->irq); ++ dev_err(&dev->pdev->dev, ++ "request interrupt %d failed\n", pdev->irq); + retval = -EBUSY; + goto error; + } +@@ -3071,32 +3081,34 @@ static int langwell_udc_probe(struct pci + dev->lpm = (readl(&dev->cap_regs->hccparams) & HCC_LEN) ? 1 : 0; + dev->dciversion = readw(&dev->cap_regs->dciversion); + dev->devcap = (readl(&dev->cap_regs->dccparams) & DEVCAP) ? 1 : 0; +- VDBG(dev, "dev->lpm: %d\n", dev->lpm); +- VDBG(dev, "dev->dciversion: 0x%04x\n", dev->dciversion); +- VDBG(dev, "dccparams: 0x%08x\n", readl(&dev->cap_regs->dccparams)); +- VDBG(dev, "dev->devcap: %d\n", dev->devcap); ++ dev_vdbg(&dev->pdev->dev, "dev->lpm: %d\n", dev->lpm); ++ dev_vdbg(&dev->pdev->dev, "dev->dciversion: 0x%04x\n", ++ dev->dciversion); ++ dev_vdbg(&dev->pdev->dev, "dccparams: 0x%08x\n", ++ readl(&dev->cap_regs->dccparams)); ++ dev_vdbg(&dev->pdev->dev, "dev->devcap: %d\n", dev->devcap); + if (!dev->devcap) { +- ERROR(dev, "can't support device mode\n"); ++ dev_err(&dev->pdev->dev, "can't support device mode\n"); + retval = -ENODEV; + goto error; + } + + /* a pair of endpoints (out/in) for each address */ + dev->ep_max = DEN(readl(&dev->cap_regs->dccparams)) * 2; +- VDBG(dev, "dev->ep_max: %d\n", dev->ep_max); ++ dev_vdbg(&dev->pdev->dev, "dev->ep_max: %d\n", dev->ep_max); + + /* allocate endpoints memory */ + dev->ep = kzalloc(sizeof(struct langwell_ep) * dev->ep_max, + GFP_KERNEL); + if (!dev->ep) { +- ERROR(dev, "allocate endpoints memory failed\n"); ++ dev_err(&dev->pdev->dev, "allocate endpoints memory failed\n"); + retval = -ENOMEM; + goto error; + } + + /* allocate device dQH memory */ + size = dev->ep_max * sizeof(struct langwell_dqh); +- VDBG(dev, "orig size = %d\n", size); ++ dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size); + if (size < DQH_ALIGNMENT) + size = DQH_ALIGNMENT; + else if ((size % DQH_ALIGNMENT) != 0) { +@@ -3106,17 +3118,18 @@ static int langwell_udc_probe(struct pci + dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size, + &dev->ep_dqh_dma, GFP_KERNEL); + if (!dev->ep_dqh) { +- ERROR(dev, "allocate dQH memory failed\n"); ++ dev_err(&dev->pdev->dev, "allocate dQH memory failed\n"); + retval = -ENOMEM; + goto error; + } + dev->ep_dqh_size = size; +- VDBG(dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); ++ dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); + + /* initialize ep0 status request structure */ + dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL); + if (!dev->status_req) { +- ERROR(dev, "allocate status_req memory failed\n"); ++ dev_err(&dev->pdev->dev, ++ "allocate status_req memory failed\n"); + retval = -ENOMEM; + goto error; + } +@@ -3174,18 +3187,20 @@ static int langwell_udc_probe(struct pci + } + + /* done */ +- INFO(dev, "%s\n", driver_desc); +- INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base); +- INFO(dev, "Driver version: " DRIVER_VERSION "\n"); +- INFO(dev, "Support (max) %d endpoints\n", dev->ep_max); +- INFO(dev, "Device interface version: 0x%04x\n", dev->dciversion); +- INFO(dev, "Controller mode: %s\n", dev->devcap ? "Device" : "Host"); +- INFO(dev, "Support USB LPM: %s\n", dev->lpm ? "Yes" : "No"); ++ dev_info(&dev->pdev->dev, "%s\n", driver_desc); ++ dev_info(&dev->pdev->dev, "irq %d, pci mem %p\n", pdev->irq, base); ++ dev_info(&dev->pdev->dev, "Driver version: " DRIVER_VERSION "\n"); ++ dev_info(&dev->pdev->dev, "Support (max) %d endpoints\n", dev->ep_max); ++ dev_info(&dev->pdev->dev, "Device interface version: 0x%04x\n", ++ dev->dciversion); ++ dev_info(&dev->pdev->dev, "Controller mode: %s\n", ++ dev->devcap ? "Device" : "Host"); ++ dev_info(&dev->pdev->dev, "Support USB LPM: %s\n", ++ dev->lpm ? "Yes" : "No"); + +- VDBG(dev, "After langwell_udc_probe(), print all registers:\n"); +-#ifdef VERBOSE ++ dev_vdbg(&dev->pdev->dev, ++ "After langwell_udc_probe(), print all registers:\n"); + print_all_registers(dev); +-#endif + + the_controller = dev; + +@@ -3197,12 +3212,12 @@ static int langwell_udc_probe(struct pci + if (retval) + goto error; + +- VDBG(dev, "<--- %s()\n", __func__); ++ dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + + error: + if (dev) { +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + langwell_udc_remove(pdev); + } + +@@ -3216,7 +3231,7 @@ static int langwell_udc_suspend(struct p + struct langwell_udc *dev = the_controller; + u32 devlc; + +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* disable interrupt and set controller to stop state */ + langwell_udc_stop(dev); +@@ -3226,7 +3241,6 @@ static int langwell_udc_suspend(struct p + free_irq(pdev->irq, dev); + dev->got_irq = 0; + +- + /* save PCI state */ + pci_save_state(pdev); + +@@ -3235,11 +3249,10 @@ static int langwell_udc_suspend(struct p + + /* enter PHY low power suspend */ + devlc = readl(&dev->op_regs->devlc); +- VDBG(dev, "devlc = 0x%08x\n", devlc); + devlc |= LPM_PHCD; + writel(devlc, &dev->op_regs->devlc); + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -3250,11 +3263,10 @@ static int langwell_udc_resume(struct pc + struct langwell_udc *dev = the_controller; + u32 devlc; + +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* exit PHY low power suspend */ + devlc = readl(&dev->op_regs->devlc); +- VDBG(dev, "devlc = 0x%08x\n", devlc); + devlc &= ~LPM_PHCD; + writel(devlc, &dev->op_regs->devlc); + +@@ -3265,10 +3277,11 @@ static int langwell_udc_resume(struct pc + pci_restore_state(pdev); + + /* enable IRQ handler */ +- if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, driver_name, dev) +- != 0) { +- ERROR(dev, "request interrupt %d failed\n", pdev->irq); +- return -1; ++ if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, ++ driver_name, dev) != 0) { ++ dev_err(&dev->pdev->dev, "request interrupt %d failed\n", ++ pdev->irq); ++ return -EBUSY; + } + dev->got_irq = 1; + +@@ -3290,7 +3303,7 @@ static int langwell_udc_resume(struct pc + dev->ep0_state = WAIT_FOR_SETUP; + dev->ep0_dir = USB_DIR_OUT; + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + } + +@@ -3301,15 +3314,15 @@ static void langwell_udc_shutdown(struct + struct langwell_udc *dev = the_controller; + u32 usbmode; + +- DBG(dev, "---> %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* reset controller mode to IDLE */ + usbmode = readl(&dev->op_regs->usbmode); +- DBG(dev, "usbmode = 0x%08x\n", usbmode); ++ dev_dbg(&dev->pdev->dev, "usbmode = 0x%08x\n", usbmode); + usbmode &= (~3 | MODE_IDLE); + writel(usbmode, &dev->op_regs->usbmode); + +- DBG(dev, "<--- %s()\n", __func__); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } + + /*-------------------------------------------------------------------------*/ +@@ -3324,7 +3337,6 @@ static const struct pci_device_id pci_id + }, { /* end: all zeroes */ } + }; + +- + MODULE_DEVICE_TABLE(pci, pci_ids); + + +@@ -3343,12 +3355,6 @@ static struct pci_driver langwell_pci_dr + }; + + +-MODULE_DESCRIPTION(DRIVER_DESC); +-MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>"); +-MODULE_VERSION(DRIVER_VERSION); +-MODULE_LICENSE("GPL"); +- +- + static int __init init(void) + { + #ifdef OTG_TRANSCEIVER +@@ -3370,3 +3376,9 @@ static void __exit cleanup(void) + } + module_exit(cleanup); + ++ ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>"); ++MODULE_VERSION(DRIVER_VERSION); ++MODULE_LICENSE("GPL"); ++ diff --git a/usb/usb-langwell-usb-client-driver-memory-handling.patch b/usb/usb-langwell-usb-client-driver-memory-handling.patch new file mode 100644 index 00000000000000..f3deec1c90d205 --- /dev/null +++ b/usb/usb-langwell-usb-client-driver-memory-handling.patch @@ -0,0 +1,223 @@ +From linux-usb-owner@vger.kernel.org Wed Sep 1 11:44:09 2010 +From: JiebingLi <jiebing.li@intel.com> +Subject: USB: langwell: USB Client driver memory handling +To: linux-usb@vger.kernel.org +Date: Thu, 05 Aug 2010 14:18:29 +0100 +Message-ID: <20100805131828.12473.14313.stgit@localhost.localdomain> + +From: JiebingLi <jiebing.li@intel.com> + +SRAM Memory handling for USB client function + +Signed-off-by: JiebingLi <jiebing.li@intel.com> +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + + drivers/usb/gadget/langwell_udc.c | 113 ++++++++++++++++++++++++++++++++++++-- + drivers/usb/gadget/langwell_udc.h | 12 ++-- + 2 files changed, 115 insertions(+), 10 deletions(-) + + +--- a/drivers/usb/gadget/langwell_udc.c ++++ b/drivers/usb/gadget/langwell_udc.c +@@ -2988,6 +2988,50 @@ static void gadget_release(struct device + } + + ++/* enable SRAM caching if SRAM detected */ ++static void sram_init(struct langwell_udc *dev) ++{ ++ struct pci_dev *pdev = dev->pdev; ++ ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); ++ ++ dev->sram_addr = pci_resource_start(pdev, 1); ++ dev->sram_size = pci_resource_len(pdev, 1); ++ dev_info(&dev->pdev->dev, "Found private SRAM at %x size:%x\n", ++ dev->sram_addr, dev->sram_size); ++ dev->got_sram = 1; ++ ++ if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) { ++ dev_warn(&dev->pdev->dev, "SRAM request failed\n"); ++ dev->got_sram = 0; ++ } else if (!dma_declare_coherent_memory(&pdev->dev, dev->sram_addr, ++ dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP)) { ++ dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n"); ++ pci_release_region(pdev, 1); ++ dev->got_sram = 0; ++ } ++ ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); ++} ++ ++ ++/* release SRAM caching */ ++static void sram_deinit(struct langwell_udc *dev) ++{ ++ struct pci_dev *pdev = dev->pdev; ++ ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); ++ ++ dma_release_declared_memory(&pdev->dev); ++ pci_release_region(pdev, 1); ++ ++ dev->got_sram = 0; ++ ++ dev_info(&dev->pdev->dev, "release SRAM caching\n"); ++ dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); ++} ++ ++ + /* tear down the binding between this driver and the pci device */ + static void langwell_udc_remove(struct pci_dev *pdev) + { +@@ -3000,19 +3044,25 @@ static void langwell_udc_remove(struct p + + dev->done = &done; + +- /* free memory allocated in probe */ ++#ifndef OTG_TRANSCEIVER ++ /* free dTD dma_pool and dQH */ + if (dev->dtd_pool) + dma_pool_destroy(dev->dtd_pool); + ++ if (dev->ep_dqh) ++ dma_free_coherent(&pdev->dev, dev->ep_dqh_size, ++ dev->ep_dqh, dev->ep_dqh_dma); ++ ++ /* release SRAM caching */ ++ if (dev->has_sram && dev->got_sram) ++ sram_deinit(dev); ++#endif ++ + if (dev->status_req) { + kfree(dev->status_req->req.buf); + kfree(dev->status_req); + } + +- if (dev->ep_dqh) +- dma_free_coherent(&pdev->dev, dev->ep_dqh_size, +- dev->ep_dqh, dev->ep_dqh_dma); +- + kfree(dev->ep); + + /* diable IRQ handler */ +@@ -3140,7 +3190,15 @@ static int langwell_udc_probe(struct pci + goto error; + } + ++ dev->has_sram = 1; ++ dev->got_sram = 0; ++ dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram); ++ + #ifndef OTG_TRANSCEIVER ++ /* enable SRAM caching if detected */ ++ if (dev->has_sram && !dev->got_sram) ++ sram_init(dev); ++ + dev_info(&dev->pdev->dev, + "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n", + pdev->irq, resource, len, base); +@@ -3335,6 +3393,18 @@ static int langwell_udc_suspend(struct p + /* save PCI state */ + pci_save_state(pdev); + ++ /* free dTD dma_pool and dQH */ ++ if (dev->dtd_pool) ++ dma_pool_destroy(dev->dtd_pool); ++ ++ if (dev->ep_dqh) ++ dma_free_coherent(&pdev->dev, dev->ep_dqh_size, ++ dev->ep_dqh, dev->ep_dqh_dma); ++ ++ /* release SRAM caching */ ++ if (dev->has_sram && dev->got_sram) ++ sram_deinit(dev); ++ + /* set device power state */ + pci_set_power_state(pdev, PCI_D3hot); + +@@ -3351,6 +3421,7 @@ static int langwell_udc_suspend(struct p + static int langwell_udc_resume(struct pci_dev *pdev) + { + struct langwell_udc *dev = the_controller; ++ size_t size; + + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + +@@ -3361,6 +3432,38 @@ static int langwell_udc_resume(struct pc + /* set device D0 power state */ + pci_set_power_state(pdev, PCI_D0); + ++ /* enable SRAM caching if detected */ ++ if (dev->has_sram && !dev->got_sram) ++ sram_init(dev); ++ ++ /* allocate device dQH memory */ ++ size = dev->ep_max * sizeof(struct langwell_dqh); ++ dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size); ++ if (size < DQH_ALIGNMENT) ++ size = DQH_ALIGNMENT; ++ else if ((size % DQH_ALIGNMENT) != 0) { ++ size += DQH_ALIGNMENT + 1; ++ size &= ~(DQH_ALIGNMENT - 1); ++ } ++ dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size, ++ &dev->ep_dqh_dma, GFP_KERNEL); ++ if (!dev->ep_dqh) { ++ dev_err(&dev->pdev->dev, "allocate dQH memory failed\n"); ++ return -ENOMEM; ++ } ++ dev->ep_dqh_size = size; ++ dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); ++ ++ /* create dTD dma_pool resource */ ++ dev->dtd_pool = dma_pool_create("langwell_dtd", ++ &dev->pdev->dev, ++ sizeof(struct langwell_dtd), ++ DTD_ALIGNMENT, ++ DMA_BOUNDARY); ++ ++ if (!dev->dtd_pool) ++ return -ENOMEM; ++ + /* restore PCI state */ + pci_restore_state(pdev); + +--- a/drivers/usb/gadget/langwell_udc.h ++++ b/drivers/usb/gadget/langwell_udc.h +@@ -18,11 +18,7 @@ + */ + + #include <linux/usb/langwell_udc.h> +- +-#if defined(CONFIG_USB_LANGWELL_OTG) + #include <linux/usb/langwell_otg.h> +-#endif +- + + /*-------------------------------------------------------------------------*/ + +@@ -199,7 +195,9 @@ struct langwell_udc { + vbus_active:1, + suspended:1, + stopped:1, +- lpm:1; /* LPM capability */ ++ lpm:1, /* LPM capability */ ++ has_sram:1, /* SRAM caching */ ++ got_sram:1; + + /* pci state used to access those endpoints */ + struct pci_dev *pdev; +@@ -225,6 +223,10 @@ struct langwell_udc { + /* make sure release() is done */ + struct completion *done; + ++ /* for private SRAM caching */ ++ unsigned int sram_addr; ++ unsigned int sram_size; ++ + /* device status data for get_status request */ + u16 dev_status; + }; diff --git a/usb/usb-langwell-usb-client-endpoint-initialization.patch b/usb/usb-langwell-usb-client-endpoint-initialization.patch new file mode 100644 index 00000000000000..0bfea9f422d4ce --- /dev/null +++ b/usb/usb-langwell-usb-client-endpoint-initialization.patch @@ -0,0 +1,84 @@ +From linux-usb-owner@vger.kernel.org Wed Sep 1 11:41:36 2010 +From: JiebingLi <jiebing.li@intel.com> +Subject: USB: langwell: USB Client Endpoint initialization +To: linux-usb@vger.kernel.org +Date: Thu, 05 Aug 2010 14:18:05 +0100 +Message-ID: <20100805131802.12473.31336.stgit@localhost.localdomain> + +From: JiebingLi <jiebing.li@intel.com> + +Endpoint software structure initialization + +Signed-off-by: JiebingLi <jiebing.li@intel.com> +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + + drivers/usb/gadget/langwell_udc.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + + +--- a/drivers/usb/gadget/langwell_udc.c ++++ b/drivers/usb/gadget/langwell_udc.c +@@ -242,11 +242,13 @@ static void ep0_reset(struct langwell_ud + ep->dqh->dqh_ios = 1; + ep->dqh->dqh_mpl = EP0_MAX_PKT_SIZE; + +- /* FIXME: enable ep0-in HW zero length termination select */ ++ /* enable ep0-in HW zero length termination select */ + if (is_in(ep)) + ep->dqh->dqh_zlt = 0; + ep->dqh->dqh_mult = 0; + ++ ep->dqh->dtd_next = DTD_TERM; ++ + /* configure ep0 control registers */ + ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL); + } +@@ -268,7 +270,7 @@ static int langwell_ep_enable(struct usb + struct langwell_ep *ep; + u16 max = 0; + unsigned long flags; +- int retval = 0; ++ int i, retval = 0; + unsigned char zlt, ios = 0, mult = 0; + + ep = container_of(_ep, struct langwell_ep, ep); +@@ -354,12 +356,6 @@ static int langwell_ep_enable(struct usb + + spin_lock_irqsave(&dev->lock, flags); + +- /* configure endpoint capabilities in dQH */ +- ep->dqh->dqh_ios = ios; +- ep->dqh->dqh_mpl = cpu_to_le16(max); +- ep->dqh->dqh_zlt = zlt; +- ep->dqh->dqh_mult = mult; +- + ep->ep.maxpacket = max; + ep->desc = desc; + ep->stopped = 0; +@@ -371,6 +367,15 @@ static int langwell_ep_enable(struct usb + /* configure endpoint control registers */ + ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type); + ++ /* configure endpoint capabilities in dQH */ ++ i = ep->ep_num * 2 + is_in(ep); ++ ep->dqh = &dev->ep_dqh[i]; ++ ep->dqh->dqh_ios = ios; ++ ep->dqh->dqh_mpl = cpu_to_le16(max); ++ ep->dqh->dqh_zlt = zlt; ++ ep->dqh->dqh_mult = mult; ++ ep->dqh->dtd_next = DTD_TERM; ++ + dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n", + _ep->name, + ep->ep_num, +@@ -1430,8 +1435,6 @@ static int eps_reinit(struct langwell_ud + + INIT_LIST_HEAD(&ep->queue); + list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); +- +- ep->dqh = &dev->ep_dqh[i]; + } + + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); diff --git a/usb/usb-langwell-usb-client-phy-low-power-mode-setting.patch b/usb/usb-langwell-usb-client-phy-low-power-mode-setting.patch new file mode 100644 index 00000000000000..b186e55fdba77d --- /dev/null +++ b/usb/usb-langwell-usb-client-phy-low-power-mode-setting.patch @@ -0,0 +1,209 @@ +From linux-usb-owner@vger.kernel.org Wed Sep 1 11:41:55 2010 +From: JiebingLi <jiebing.li@intel.com> +Subject: USB: langwell: USB Client PHY low power mode setting +To: linux-usb@vger.kernel.org +Date: Thu, 05 Aug 2010 14:18:13 +0100 +Message-ID: <20100805131811.12473.42609.stgit@localhost.localdomain> + +From: JiebingLi <jiebing.li@intel.com> + +PHY low power mode setting with a static function + +Signed-off-by: JiebingLi <jiebing.li@intel.com> +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + + drivers/usb/gadget/langwell_udc.c | 92 ++++++++++++++++++++++++-------------- + 1 file changed, 60 insertions(+), 32 deletions(-) + + +--- a/drivers/usb/gadget/langwell_udc.c ++++ b/drivers/usb/gadget/langwell_udc.c +@@ -1159,11 +1159,37 @@ static int langwell_get_frame(struct usb + } + + ++/* enter or exit PHY low power state */ ++static void langwell_phy_low_power(struct langwell_udc *dev, bool flag) ++{ ++ u32 devlc; ++ u8 devlc_byte2; ++ dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); ++ ++ devlc = readl(&dev->op_regs->devlc); ++ dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc); ++ ++ if (flag) ++ devlc |= LPM_PHCD; ++ else ++ devlc &= ~LPM_PHCD; ++ ++ /* FIXME: workaround for Langwell A1/A2/A3 sighting */ ++ devlc_byte2 = (devlc >> 16) & 0xff; ++ writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2); ++ ++ devlc = readl(&dev->op_regs->devlc); ++ dev_vdbg(&dev->pdev->dev, ++ "%s PHY low power suspend, devlc = 0x%08x\n", ++ flag ? "enter" : "exit", devlc); ++} ++ ++ + /* tries to wake up the host connected to this gadget */ + static int langwell_wakeup(struct usb_gadget *_gadget) + { + struct langwell_udc *dev; +- u32 portsc1, devlc; ++ u32 portsc1; + unsigned long flags; + + if (!_gadget) +@@ -1186,22 +1212,19 @@ static int langwell_wakeup(struct usb_ga + return 0; + } + +- /* LPM L1 to L0, remote wakeup */ +- if (dev->lpm && dev->lpm_state == LPM_L1) { +- portsc1 |= PORTS_SLP; +- writel(portsc1, &dev->op_regs->portsc1); +- } +- +- /* force port resume */ +- if (dev->usb_state == USB_STATE_SUSPENDED) { +- portsc1 |= PORTS_FPR; +- writel(portsc1, &dev->op_regs->portsc1); +- } ++ /* LPM L1 to L0 or legacy remote wakeup */ ++ if (dev->lpm && dev->lpm_state == LPM_L1) ++ dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n"); ++ else ++ dev_info(&dev->pdev->dev, "device remote wakeup\n"); + + /* exit PHY low power suspend */ +- devlc = readl(&dev->op_regs->devlc); +- devlc &= ~LPM_PHCD; +- writel(devlc, &dev->op_regs->devlc); ++ if (dev->pdev->device != 0x0829) ++ langwell_phy_low_power(dev, 0); ++ ++ /* force port resume */ ++ portsc1 |= PORTS_FPR; ++ writel(portsc1, &dev->op_regs->portsc1); + + spin_unlock_irqrestore(&dev->lock, flags); + +@@ -1331,6 +1354,7 @@ static const struct usb_gadget_ops langw + static int langwell_udc_reset(struct langwell_udc *dev) + { + u32 usbcmd, usbmode, devlc, endpointlistaddr; ++ u8 devlc_byte0, devlc_byte2; + unsigned long timeout; + + if (!dev) +@@ -1375,9 +1399,17 @@ static int langwell_udc_reset(struct lan + /* if support USB LPM, ACK all LPM token */ + if (dev->lpm) { + devlc = readl(&dev->op_regs->devlc); ++ dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc); ++ /* FIXME: workaround for Langwell A1/A2/A3 sighting */ + devlc &= ~LPM_STL; /* don't STALL LPM token */ + devlc &= ~LPM_NYT_ACK; /* ACK LPM token */ +- writel(devlc, &dev->op_regs->devlc); ++ devlc_byte0 = devlc & 0xff; ++ devlc_byte2 = (devlc >> 16) & 0xff; ++ writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc); ++ writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2); ++ devlc = readl(&dev->op_regs->devlc); ++ dev_vdbg(&dev->pdev->dev, ++ "ACK LPM token, devlc = 0x%08x\n", devlc); + } + + /* fill endpointlistaddr register */ +@@ -1871,6 +1903,10 @@ int usb_gadget_unregister_driver(struct + if (unlikely(!driver || !driver->bind || !driver->unbind)) + return -EINVAL; + ++ /* exit PHY low power suspend */ ++ if (dev->pdev->device != 0x0829) ++ langwell_phy_low_power(dev, 0); ++ + /* unbind OTG transceiver */ + if (dev->transceiver) + (void)otg_set_peripheral(dev->transceiver, 0); +@@ -2706,7 +2742,6 @@ static void handle_usb_reset(struct lang + /* USB bus suspend/resume interrupt */ + static void handle_bus_suspend(struct langwell_udc *dev) + { +- u32 devlc; + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + dev->resume_state = dev->usb_state; +@@ -2747,9 +2782,8 @@ static void handle_bus_suspend(struct la + } + + /* enter PHY low power suspend */ +- devlc = readl(&dev->op_regs->devlc); +- devlc |= LPM_PHCD; +- writel(devlc, &dev->op_regs->devlc); ++ if (dev->pdev->device != 0x0829) ++ langwell_phy_low_power(dev, 0); + + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + } +@@ -2757,16 +2791,14 @@ static void handle_bus_suspend(struct la + + static void handle_bus_resume(struct langwell_udc *dev) + { +- u32 devlc; + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + dev->usb_state = dev->resume_state; + dev->resume_state = 0; + + /* exit PHY low power suspend */ +- devlc = readl(&dev->op_regs->devlc); +- devlc &= ~LPM_PHCD; +- writel(devlc, &dev->op_regs->devlc); ++ if (dev->pdev->device != 0x0829) ++ langwell_phy_low_power(dev, 0); + + #ifdef OTG_TRANSCEIVER + if (dev->lotg->otg.default_a == 0) +@@ -3232,7 +3264,6 @@ error: + static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) + { + struct langwell_udc *dev = the_controller; +- u32 devlc; + + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + +@@ -3251,9 +3282,8 @@ static int langwell_udc_suspend(struct p + pci_set_power_state(pdev, PCI_D3hot); + + /* enter PHY low power suspend */ +- devlc = readl(&dev->op_regs->devlc); +- devlc |= LPM_PHCD; +- writel(devlc, &dev->op_regs->devlc); ++ if (dev->pdev->device != 0x0829) ++ langwell_phy_low_power(dev, 1); + + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; +@@ -3264,14 +3294,12 @@ static int langwell_udc_suspend(struct p + static int langwell_udc_resume(struct pci_dev *pdev) + { + struct langwell_udc *dev = the_controller; +- u32 devlc; + + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + /* exit PHY low power suspend */ +- devlc = readl(&dev->op_regs->devlc); +- devlc &= ~LPM_PHCD; +- writel(devlc, &dev->op_regs->devlc); ++ if (dev->pdev->device != 0x0829) ++ langwell_phy_low_power(dev, 0); + + /* set device D0 power state */ + pci_set_power_state(pdev, PCI_D0); diff --git a/usb/usb-langwell-usb-client-remote-wakeup-support.patch b/usb/usb-langwell-usb-client-remote-wakeup-support.patch new file mode 100644 index 00000000000000..ab7037c06f0cf2 --- /dev/null +++ b/usb/usb-langwell-usb-client-remote-wakeup-support.patch @@ -0,0 +1,160 @@ +From linux-usb-owner@vger.kernel.org Wed Sep 1 11:42:33 2010 +From: JiebingLi <jiebing.li@intel.com> +Subject: USB: langwell: USB Client Remote Wakeup Support +To: linux-usb@vger.kernel.org +Date: Thu, 05 Aug 2010 14:18:21 +0100 +Message-ID: <20100805131819.12473.6939.stgit@localhost.localdomain> + +From: JiebingLi <jiebing.li@intel.com> + +Remote wakeup support in client driver. Made non-debug only this time. + +Signed-off-by: JiebingLi <jiebing.li@intel.com> +Signed-off-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + + drivers/usb/gadget/langwell_udc.c | 67 +++++++++++++++++++++++++++++++++++--- + drivers/usb/gadget/langwell_udc.h | 3 + + 2 files changed, 65 insertions(+), 5 deletions(-) + + +--- a/drivers/usb/gadget/langwell_udc.c ++++ b/drivers/usb/gadget/langwell_udc.c +@@ -1815,6 +1815,36 @@ static ssize_t show_langwell_udc(struct + static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL); + + ++/* device "remote_wakeup" sysfs attribute file */ ++static ssize_t store_remote_wakeup(struct device *_dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct langwell_udc *dev = the_controller; ++ unsigned long flags; ++ ssize_t rc = count; ++ ++ if (count > 2) ++ return -EINVAL; ++ ++ if (count > 0 && buf[count-1] == '\n') ++ ((char *) buf)[count-1] = 0; ++ ++ if (buf[0] != '1') ++ return -EINVAL; ++ ++ /* force remote wakeup enabled in case gadget driver doesn't support */ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->remote_wakeup = 1; ++ dev->dev_status |= (1 << USB_DEVICE_REMOTE_WAKEUP); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ langwell_wakeup(&dev->gadget); ++ ++ return rc; ++} ++static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup); ++ ++ + /*-------------------------------------------------------------------------*/ + + /* +@@ -2136,8 +2166,7 @@ static void get_status(struct langwell_u + + if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) { + /* get device status */ +- status_data = 1 << USB_DEVICE_SELF_POWERED; +- status_data |= dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP; ++ status_data = dev->dev_status; + } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) { + /* get interface status */ + status_data = 0; +@@ -2275,6 +2304,22 @@ static void handle_setup_packet(struct l + } else if ((setup->bRequestType & (USB_RECIP_MASK + | USB_TYPE_MASK)) == (USB_RECIP_DEVICE + | USB_TYPE_STANDARD)) { ++ rc = 0; ++ switch (wValue) { ++ case USB_DEVICE_REMOTE_WAKEUP: ++ if (setup->bRequest == USB_REQ_SET_FEATURE) { ++ dev->remote_wakeup = 1; ++ dev->dev_status |= (1 << wValue); ++ } else { ++ dev->remote_wakeup = 0; ++ dev->dev_status &= ~(1 << wValue); ++ } ++ break; ++ default: ++ rc = -EOPNOTSUPP; ++ break; ++ } ++ + if (!gadget_is_otg(&dev->gadget)) + break; + else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) { +@@ -2290,7 +2335,6 @@ static void handle_setup_packet(struct l + dev->gadget.a_alt_hnp_support = 1; + else + break; +- rc = 0; + } else + break; + +@@ -2678,7 +2722,10 @@ static void handle_usb_reset(struct lang + + dev->ep0_dir = USB_DIR_OUT; + dev->ep0_state = WAIT_FOR_SETUP; +- dev->remote_wakeup = 0; /* default to 0 on reset */ ++ ++ /* remote wakeup reset to 0 when the device is reset */ ++ dev->remote_wakeup = 0; ++ dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; + dev->gadget.b_hnp_enable = 0; + dev->gadget.a_hnp_support = 0; + dev->gadget.a_alt_hnp_support = 0; +@@ -2997,6 +3044,7 @@ static void langwell_udc_remove(struct p + + device_unregister(&dev->gadget.dev); + device_remove_file(&pdev->dev, &dev_attr_langwell_udc); ++ device_remove_file(&pdev->dev, &dev_attr_remote_wakeup); + + #ifndef OTG_TRANSCEIVER + pci_set_drvdata(pdev, NULL); +@@ -3177,7 +3225,10 @@ static int langwell_udc_probe(struct pci + dev->resume_state = USB_STATE_NOTATTACHED; + dev->usb_state = USB_STATE_POWERED; + dev->ep0_dir = USB_DIR_OUT; +- dev->remote_wakeup = 0; /* default to 0 on reset */ ++ ++ /* remote wakeup reset to 0 when the device is reset */ ++ dev->remote_wakeup = 0; ++ dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; + + #ifndef OTG_TRANSCEIVER + /* reset device controller */ +@@ -3247,9 +3298,15 @@ static int langwell_udc_probe(struct pci + if (retval) + goto error; + ++ retval = device_create_file(&pdev->dev, &dev_attr_remote_wakeup); ++ if (retval) ++ goto error_attr1; ++ + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; + ++error_attr1: ++ device_remove_file(&pdev->dev, &dev_attr_langwell_udc); + error: + if (dev) { + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); +--- a/drivers/usb/gadget/langwell_udc.h ++++ b/drivers/usb/gadget/langwell_udc.h +@@ -224,5 +224,8 @@ struct langwell_udc { + + /* make sure release() is done */ + struct completion *done; ++ ++ /* device status data for get_status request */ ++ u16 dev_status; + }; + |
