author | Vishal Mahaveer <vishalm@ti.com> | |
Wed, 6 May 2015 21:48:23 +0000 (16:48 -0500) | ||
committer | Vishal Mahaveer <vishalm@ti.com> | |
Wed, 6 May 2015 21:48:23 +0000 (16:48 -0500) |
* 'ti-linux-3.14.y' of git://git.ti.com/ti-linux-kernel/ti-linux-kernel: (218 commits)
Linux 3.14.41
nosave: consolidate __nosave_{begin,end} in <asm/sections.h>
fs: take i_mutex during prepare_binprm for set[ug]id executables
driver core: bus: Goto appropriate labels on failure in bus_add_device
memstick: mspro_block: add missing curly braces
C6x: time: Ensure consistency in __init
crypto: omap-aes - Fix support for unequal lengths
wl18xx: show rx_frames_per_rates as an array as it really is
lib: memzero_explicit: use barrier instead of OPTIMIZER_HIDE_VAR
e1000: add dummy allocator to fix race condition between mtu change and netpoll
ksoftirqd: Enable IRQs and call cond_resched() before poking RCU
RCU pathwalk breakage when running into a symlink overmounting something
drm/i915: cope with large i2c transfers
drm/radeon: fix doublescan modes (v2)
i2c: core: Export bus recovery functions
IB/mlx4: Fix WQE LSO segment calculation
IB/core: don't disallow registering region starting at 0x0
IB/core: disallow registering 0-sized memory region
stk1160: Make sure current buffer is released
mvsas: fix panic on expander attached SATA devices
...
Change-Id: I0155e17495c9013dfcc57ca6d6401b3b648c1efe
Signed-off-by: Vishal Mahaveer <vishalm@ti.com>
Linux 3.14.41
nosave: consolidate __nosave_{begin,end} in <asm/sections.h>
fs: take i_mutex during prepare_binprm for set[ug]id executables
driver core: bus: Goto appropriate labels on failure in bus_add_device
memstick: mspro_block: add missing curly braces
C6x: time: Ensure consistency in __init
crypto: omap-aes - Fix support for unequal lengths
wl18xx: show rx_frames_per_rates as an array as it really is
lib: memzero_explicit: use barrier instead of OPTIMIZER_HIDE_VAR
e1000: add dummy allocator to fix race condition between mtu change and netpoll
ksoftirqd: Enable IRQs and call cond_resched() before poking RCU
RCU pathwalk breakage when running into a symlink overmounting something
drm/i915: cope with large i2c transfers
drm/radeon: fix doublescan modes (v2)
i2c: core: Export bus recovery functions
IB/mlx4: Fix WQE LSO segment calculation
IB/core: don't disallow registering region starting at 0x0
IB/core: disallow registering 0-sized memory region
stk1160: Make sure current buffer is released
mvsas: fix panic on expander attached SATA devices
...
Change-Id: I0155e17495c9013dfcc57ca6d6401b3b648c1efe
Signed-off-by: Vishal Mahaveer <vishalm@ti.com>
325 files changed:
diff --git a/Documentation/devicetree/bindings/extcon/extcon-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-GPIO based EXTCON
-
-EXTCON GPIO
------------
-
-Required Properties:
- - compatible: should be:
- * "linux,extcon-gpio"
- - gpios: specifies the gpio pin used.
- - cable-name: Name of the cable used.
-
-Optional Properties:
- - debounce: Debounce time for GPIO IRQ in ms
-
-
-Eg:
-
- extcon1: am43_usbid_extcon1 {
- compatible = "linux,extcon-gpio";
- gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>;
- debounce = <20>;
- cable-name = "USB-HOST";
- };
diff --git a/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt
--- /dev/null
@@ -0,0 +1,18 @@
+USB GPIO Extcon device
+
+This is a virtual device used to generate USB cable states from the USB ID pin
+connected to a GPIO pin.
+
+Required properties:
+- compatible: Should be "linux,extcon-usb-gpio"
+- id-gpio: gpio for USB ID pin. See gpio binding.
+
+Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below:
+ extcon_usb1 {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
+ }
+
+ &omap_dwc3_1 {
+ extcon = <&extcon_usb1>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index 471366d6a1291846852e24cb0b03fec0e5fa8b23..cd7f0454e13a9227ad512228e9c12bc76e2c7c07 100644 (file)
- phys: from the *Generic PHY* bindings
- phy-names: from the *Generic PHY* bindings
- tx-fifo-resize: determines if the FIFO *has* to be reallocated.
+ - snps,disable_scramble_quirk: true when SW should disable data scrambling.
+ Only really useful for FPGA builds.
+ - snps,has-lpm-erratum: true when DWC3 was configured with LPM Erratum enabled
+ - snps,lpm-nyet-threshold: LPM NYET threshold
+ - snps,u2exit_lfps_quirk: set if we want to enable u2exit lfps quirk
+ - snps,u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
+ - snps,req_p1p2p3_quirk: when set, the core will always request for
+ P1/P2/P3 transition sequence.
+ - snps,del_p1p2p3_quirk: when set core will delay P1/P2/P3 until a certain
+ amount of 8B10B errors occur.
+ - snps,del_phy_power_chg_quirk: when set core will delay PHY power change
+ from P0 to P1/P2/P3.
+ - snps,lfps_filter_quirk: when set core will filter LFPS reception.
+ - snps,rx_detect_poll_quirk: when set core will disable a 400us delay to start
+ Polling LFPS after RX.Detect.
+ - snps,tx_de_emphasis_quirk: when set core will set Tx de-emphasis value.
+ - snps,tx_de_emphasis: the value driven to the PHY is controlled by the
+ LTSSM during USB3 Compliance mode.
+ - snps,dis_u3_susphy_quirk: when set core will disable USB3 suspend phy.
+ - snps,dis_u2_susphy_quirk: when set core will disable USB2 suspend phy.
+ - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
+ utmi_l1_suspend_n, false when asserts utmi_sleep_n
+ - snps,hird-threshold: HIRD threshold
This is usually a subnode to DWC3 glue to which it is connected.
diff --git a/Makefile b/Makefile
index 070e0ebb92313f81e651d475900ca63b25e6e63e..7a60d4a1301cab8c4ca3416dc39d0da3a8b15316 100644 (file)
--- a/Makefile
+++ b/Makefile
VERSION = 3
PATCHLEVEL = 14
-SUBLEVEL = 40
+SUBLEVEL = 41
EXTRAVERSION =
NAME = Remembering Coco
index 73654f516baf45984e8f98a5e06f764330c08a8f..19e56a3db11b8648ed263fafa9d59917f83287a4 100644 (file)
maximum-speed = "high-speed";
dr_mode = "otg";
status = "disabled";
+ snps,dis_u3_susphy_quirk;
+ snps,dis_u2_susphy_quirk;
};
};
maximum-speed = "high-speed";
dr_mode = "otg";
status = "disabled";
+ snps,dis_u3_susphy_quirk;
+ snps,dis_u2_susphy_quirk;
};
};
index 8783f2a747b82203c2284a3d05d4d105383d0986..f336ad4e1b16f94d3ef3e570caf74d6170a75a26 100644 (file)
usb2_phy2_pins: usb2_phy2_pins {
pinctrl-single,pins = <
- 0x2c0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x2c4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
>;
};
};
index 187fd46b7b5ef018c2985e7db5298784338f0507..355117cbbf4ac9ff3d10f6bc581462a1a845a598 100644 (file)
uart2: serial@12200 {
compatible = "ns16550a";
- reg = <0x12000 0x100>;
+ reg = <0x12200 0x100>;
reg-shift = <2>;
interrupts = <9>;
clocks = <&core_clk 0>;
uart3: serial@12300 {
compatible = "ns16550a";
- reg = <0x12100 0x100>;
+ reg = <0x12300 0x100>;
reg-shift = <2>;
interrupts = <10>;
clocks = <&core_clk 0>;
index 0120eee4bc3883d09aa177d367a49f2bebb0dbc4..46503feafec65416ecf2864a9099d08996b29d9f 100644 (file)
};
};
- extcon1: dra7x_usbid_extcon1 {
- compatible = "linux,extcon-gpio";
- gpios = <&pcf_gpio_21 1 GPIO_ACTIVE_LOW>;
- cable-name = "USB-HOST";
+ extcon_usb1: extcon_usb1 {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpios = <&pcf_gpio_21 1 GPIO_ACTIVE_HIGH>;
};
- extcon2: dra7x_usbid_extcon2 {
- compatible = "linux,extcon-gpio";
- gpios = <&pcf_gpio_21 2 GPIO_ACTIVE_LOW>;
- cable-name = "USB-HOST";
+ extcon_usb2: extcon_usb2 {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpios = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>;
};
evm_3v3_sd: fixedregulator-sd {
};
&omap_dwc3_1 {
- extcon = <&extcon1>;
+ extcon = <&extcon_usb1>;
};
&omap_dwc3_2 {
- extcon = <&extcon2>;
+ extcon = <&extcon_usb2>;
};
&usb1 {
- dr_mode = "peripheral";
+ dr_mode = "otg";
};
&usb2 {
index 2b8bdd4524ea467973129c7de6b2fa7b24bdca5a..7a5ae4a45cd7d8740eb7492ed472359809b3591a 100644 (file)
tx-fifo-resize;
maximum-speed = "super-speed";
dr_mode = "otg";
+ snps,dis_u3_susphy_quirk;
+ snps,dis_u2_susphy_quirk;
};
};
tx-fifo-resize;
maximum-speed = "high-speed";
dr_mode = "otg";
+ snps,dis_u3_susphy_quirk;
+ snps,dis_u2_susphy_quirk;
};
};
tx-fifo-resize;
maximum-speed = "high-speed";
dr_mode = "otg";
+ snps,dis_u3_susphy_quirk;
+ snps,dis_u2_susphy_quirk;
};
};
index 8df717398f2381c845ac91e85c280576c0c2f496..dbf2981382043af3157a4f6acb70a9de9878f851 100644 (file)
};
};
- extcon1: dra7x_usbid_extcon1 {
- compatible = "linux,extcon-gpio";
- gpios = <&pcf_gpio_21 1 GPIO_ACTIVE_LOW>;
- cable-name = "USB-HOST";
+ extcon_usb1: extcon_usb1 {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpios = <&pcf_gpio_21 1 GPIO_ACTIVE_HIGH>;
};
- extcon2: dra7x_usbid_extcon2 {
- compatible = "linux,extcon-gpio";
- gpios = <&pcf_gpio_21 2 GPIO_ACTIVE_LOW>;
- cable-name = "USB-HOST";
+ extcon_usb2: extcon_usb2 {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpios = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>;
};
evm_3v3_sd: fixedregulator-sd {
};
&omap_dwc3_1 {
- extcon = <&extcon1>;
+ extcon = <&extcon_usb1>;
};
&omap_dwc3_2 {
- extcon = <&extcon2>;
+ extcon = <&extcon_usb2>;
};
&usb2_phy1 {
index f4b46d39b9cfb12756050a992262367ce575f90b..051b7269e639911210b631e544b026324e4e7d5d 100644 (file)
the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
/* When the program starts, a1 contains a pointer to a function to be
registered with atexit, as per the SVR4 ABI. A value of 0 means we
index 7bc66682687efa4f240a5557618278d38c39e4b1..dcbe17f5e5f8054ee7fd1e796197eb88d78e97a8 100644 (file)
#include <mach/gpio-samsung.h>
#define GLENFARCLAS_PMIC_IRQ_BASE IRQ_BOARD_START
+#define BANFF_PMIC_IRQ_BASE (IRQ_BOARD_START + 64)
#define PCA935X_GPIO_BASE GPIO_BOARD_START
#define CODEC_GPIO_BASE (GPIO_BOARD_START + 8)
index 3df3c372ee1f9aa1f1685913e2b00ba123339513..66b95c46649756ff8d509d9df6f68650f4c1810c 100644 (file)
static struct wm831x_pdata crag_pmic_pdata = {
.wm831x_num = 1,
+ .irq_base = BANFF_PMIC_IRQ_BASE,
.gpio_base = BANFF_PMIC_GPIO_BASE,
.soft_shutdown = true,
index 6d20b7d162d834da4f9364e340e81d6014ec566a..a268a9af0c2d8f2c5ac62581181e123a3a912330 100644 (file)
$(call if_changed,vdsosym)
# Assembly rules for the .S files
-$(obj-vdso): %.o: %.S
+$(obj-vdso): %.o: %.S FORCE
$(call if_changed_dep,vdsoas)
# Actual build commands
diff --git a/arch/c6x/kernel/time.c b/arch/c6x/kernel/time.c
index 356ee84cad95aef68e6e9aca6f88b42e0eb931ec..04845aaf59858f81feebeeca6c45096b48c313d8 100644 (file)
--- a/arch/c6x/kernel/time.c
+++ b/arch/c6x/kernel/time.c
return (tsc * sched_clock_multiplier) >> SCHED_CLOCK_SHIFT;
}
-void time_init(void)
+void __init time_init(void)
{
u64 tmp = (u64)NSEC_PER_SEC << SCHED_CLOCK_SHIFT;
diff --git a/arch/mips/include/asm/suspend.h b/arch/mips/include/asm/suspend.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_SUSPEND_H
-#define __ASM_SUSPEND_H
-
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
-#endif /* __ASM_SUSPEND_H */
diff --git a/arch/mips/power/cpu.c b/arch/mips/power/cpu.c
index 521e5963df05f4f67038f52dd3b321851fa0e551..2129e67723ff38b6a1ef8fea8401886a063c8402 100644 (file)
--- a/arch/mips/power/cpu.c
+++ b/arch/mips/power/cpu.c
* Author: Hu Hongbing <huhb@lemote.com>
* Wu Zhangjin <wuzhangjin@gmail.com>
*/
-#include <asm/suspend.h>
+#include <asm/sections.h>
#include <asm/fpu.h>
#include <asm/dsp.h>
index 32a7c828f073be90c228756e3e0712c8ea6c195e..e7567c8a9e79659ac1420375d77c12623a630188 100644 (file)
END(swsusp_arch_suspend)
LEAF(swsusp_arch_resume)
+ /* Avoid TLB mismatch during and after kernel resume */
+ jal local_flush_tlb_all
PTR_L t0, restore_pblist
0:
PTR_L t1, PBE_ADDRESS(t0) /* source */
bne t1, t3, 1b
PTR_L t0, PBE_NEXT(t0)
bnez t0, 0b
- jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */
PTR_LA t0, saved_regs
PTR_L ra, PT_R31(t0)
PTR_L sp, PT_R29(t0)
index 2912b8787aa46b4b28b0e84a2e5c068afc2f5ea2..3eb36cea324c13a9f65e7695905f66c575954286 100644 (file)
};
/* These are used to index the cache_type_info array. */
-#define CACHE_TYPE_UNIFIED 0
-#define CACHE_TYPE_INSTRUCTION 1
-#define CACHE_TYPE_DATA 2
+#define CACHE_TYPE_UNIFIED 0 /* cache-size, cache-block-size, etc. */
+#define CACHE_TYPE_UNIFIED_D 1 /* d-cache-size, d-cache-block-size, etc */
+#define CACHE_TYPE_INSTRUCTION 2
+#define CACHE_TYPE_DATA 3
static const struct cache_type_info cache_type_info[] = {
+ {
+ /* Embedded systems that use cache-size, cache-block-size,
+ * etc. for the Unified (typically L2) cache. */
+ .name = "Unified",
+ .size_prop = "cache-size",
+ .line_size_props = { "cache-line-size",
+ "cache-block-size", },
+ .nr_sets_prop = "cache-sets",
+ },
{
/* PowerPC Processor binding says the [di]-cache-*
* must be equal on unified caches, so just use
{
struct cache *iter;
- if (cache->type == CACHE_TYPE_UNIFIED)
+ if (cache->type == CACHE_TYPE_UNIFIED ||
+ cache->type == CACHE_TYPE_UNIFIED_D)
return cache;
list_for_each_entry(iter, &cache_list, list)
return of_get_property(np, "cache-unified", NULL);
}
-static struct cache *cache_do_one_devnode_unified(struct device_node *node,
- int level)
+/*
+ * Unified caches can have two different sets of tags. Most embedded
+ * use cache-size, etc. for the unified cache size, but open firmware systems
+ * use d-cache-size, etc. Check on initialization for which type we have, and
+ * return the appropriate structure type. Assume it's embedded if it isn't
+ * open firmware. If it's yet a 3rd type, then there will be missing entries
+ * in /sys/devices/system/cpu/cpu0/cache/index2/, and this code will need
+ * to be extended further.
+ */
+static int cache_is_unified_d(const struct device_node *np)
{
- struct cache *cache;
+ return of_get_property(np,
+ cache_type_info[CACHE_TYPE_UNIFIED_D].size_prop, NULL) ?
+ CACHE_TYPE_UNIFIED_D : CACHE_TYPE_UNIFIED;
+}
+/*
+ */
+static struct cache *cache_do_one_devnode_unified(struct device_node *node, int level)
+{
pr_debug("creating L%d ucache for %s\n", level, node->full_name);
- cache = new_cache(CACHE_TYPE_UNIFIED, level, node);
-
- return cache;
+ return new_cache(cache_is_unified_d(node), level, node);
}
static struct cache *cache_do_one_devnode_split(struct device_node *node,
index 0167d53da30cbbbb1e61c8cdb8768db35e4b3e7a..a531154cc0f3a43f06edbba75e3207ab92b105d5 100644 (file)
#include <linux/mm.h>
#include <asm/page.h>
-
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
+#include <asm/sections.h>
/*
* pfn_is_nosave - check if given pfn is in the 'nosave' section
index 2396dda282cdef0ed5c11c6ab7c3f4f479d0ac04..ead55351b2542accc663c496be8592b9c3942b08 100644 (file)
sp = regs->gpr[1];
perf_callchain_store(entry, next_ip);
- for (;;) {
+ while (entry->nr < PERF_MAX_STACK_DEPTH) {
fp = (unsigned long __user *) sp;
if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp))
return;
index 2b90ff8a93bea7542fee7d89f99d3439bf9e0d13..59ef76c5f4f4a4eb5340323a17435bfde19bfc38 100644 (file)
io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
- for (i = 0; i < npages; i++, uaddr += tbl->it_page_shift)
+ for (i = 0; i < npages; i++, uaddr += (1 << tbl->it_page_shift))
io_pte[i] = base_pte | (__pa(uaddr) & CBE_IOPTE_RPN_Mask);
mb();
index a7a7537ce1e7e415460199098a609b8732de1175..d3236c9e226b87b98323add039a9901df23bcaeb 100644 (file)
#include <asm/ipl.h>
#include <asm/cio.h>
#include <asm/pci.h>
+#include <asm/sections.h>
#include "entry.h"
-/*
- * References to section boundaries
- */
-extern const void __nosave_begin, __nosave_end;
-
/*
* The restore of the saved pages in an hibernation image will set
* the change and referenced bits in the storage key for each page.
{
unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end));
+ unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1;
+ unsigned long stext_pfn = PFN_DOWN(__pa(&_stext));
/* Always save lowcore pages (LC protection might be enabled). */
if (pfn <= LC_PAGES)
if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn)
return 1;
/* Skip memory holes and read-only pages (NSS, DCSS, ...). */
+ if (pfn >= stext_pfn && pfn <= eshared_pfn)
+ return ipl_info.type == IPL_TYPE_NSS ? 1 : 0;
if (tprot(PFN_PHYS(pfn)))
return 1;
return 0;
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 75beea632a10ee7c1bba185d344831e11ec684c5..3588f2f37986af5df448d7e6c97f4885d822329c 100644 (file)
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
for (n = mem->count - 1; n > 0 ; n--)
memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
+ memset(&mem->vm[0], 0, sizeof(mem->vm[0]));
mem->vm[0].cpus_total = cpus;
mem->vm[0].cpus_configured = cpus;
mem->vm[0].cpus_standby = 0;
index 1b6199740e98ab7e554f1676d615983f451e56a7..7a99e6af637284d3061a96a274f375f2189f2eb2 100644 (file)
#include <asm-generic/sections.h>
-extern long __nosave_begin, __nosave_end;
extern long __machvec_start, __machvec_end;
extern char __uncached_start, __uncached_end;
extern char __start_eh_frame[], __stop_eh_frame[];
index 42b0b8ce699a94b295e9ec311de1141531275a14..17bd2e167e07edd934dfe9957c43712b21401c55 100644 (file)
#include <asm/hibernate.h>
#include <asm/visasm.h>
#include <asm/page.h>
+#include <asm/sections.h>
#include <asm/tlb.h>
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
struct saved_context saved_context;
/*
index 4dcd34ae194cdc54b772a246706ffa5d7460b3f0..77b522694e744b07c4d49b807ebd4c3551ab0bdd 100644 (file)
/* Defined in hibernate_asm.S */
extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist);
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
extern struct pbe *restore_pblist;
#endif
index d75ef8b6cb5618f28cb2ed0db4192910fcf056e2..9969ec374abb345abcad9ffd5742f155fae36d37 100644 (file)
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
+#include <asm/sections.h>
#include <asm/suspend.h>
#include "mach/pm.h"
index 1da25a5f96f92486c8971856123fa000fdc3abc0..3ba047cbcf5bb342b606990722b039903d7cd491 100644 (file)
:: "a" (eax), "c" (ecx));
}
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+ trace_hardirqs_on();
+ /* "mwait %eax, %ecx;" */
+ asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
+ :: "a" (eax), "c" (ecx));
+}
+
/*
* This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
* which can obviate IPI to trigger checking of need_resched.
index 3fb8d95ab8b5ea3635ddb1f0d9f9c12e3a348285..1a1ff42094a7b238fb0002d135d4177bb22b427b 100644 (file)
#include <asm/fpu-internal.h>
#include <asm/debugreg.h>
#include <asm/nmi.h>
+#include <asm/mwait.h>
/*
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
default_idle();
}
+/*
+ * Intel Core2 and older machines prefer MWAIT over HALT for C1.
+ * We can't rely on cpuidle installing MWAIT, because it will not load
+ * on systems that support only C1 -- so the boot default must be MWAIT.
+ *
+ * Some AMD machines are the opposite, they depend on using HALT.
+ *
+ * So for default C1, which is used during boot until cpuidle loads,
+ * use MWAIT-C1 on Intel HW that has it, else use HALT.
+ */
+static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
+{
+ if (c->x86_vendor != X86_VENDOR_INTEL)
+ return 0;
+
+ if (!cpu_has(c, X86_FEATURE_MWAIT))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * MONITOR/MWAIT with no hints, used for default default C1 state.
+ * This invokes MWAIT with interrutps enabled and no flags,
+ * which is backwards compatible with the original MWAIT implementation.
+ */
+
+static void mwait_idle(void)
+{
+ if (!current_set_polling_and_test()) {
+ if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) {
+ mb();
+ clflush((void *)¤t_thread_info()->flags);
+ mb();
+ }
+
+ __monitor((void *)¤t_thread_info()->flags, 0, 0);
+ if (!need_resched())
+ __sti_mwait(0, 0);
+ else
+ local_irq_enable();
+ } else
+ local_irq_enable();
+ current_clr_polling();
+}
+
void select_idle_routine(const struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
/* E400: APIC timer interrupt does not wake up CPU from C1e */
pr_info("using AMD E400 aware idle routine\n");
x86_idle = amd_e400_idle;
+ } else if (prefer_mwait_c1_over_halt(c)) {
+ pr_info("using mwait in idle threads\n");
+ x86_idle = mwait_idle;
} else
x86_idle = default_idle;
}
index 7d28c885d2385b85c133add5b51176eea8b52af7..291226b952a997f55d3a0be723f15cb9b9b1ab92 100644 (file)
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/mmzone.h>
+#include <asm/sections.h>
/* Defined in hibernate_asm_32.S */
extern int restore_image(void);
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
/* Pointer to the temporary resume page tables */
pgd_t *resume_pg_dir;
index 304fca20d96ee3e1540d7045a9e0e25118c240b0..2276238fde6fb670362d9993b86fb238f84a0b03 100644 (file)
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/mtrr.h>
+#include <asm/sections.h>
#include <asm/suspend.h>
-/* References to section boundaries */
-extern __visible const void __nosave_begin, __nosave_end;
-
/* Defined in hibernate_asm_64.S */
extern asmlinkage int restore_image(void);
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index c87ae7c6e5f94636ab576a649ada006b4fb376dc..8879361e477e4de8d32f6aa8fdf6a9d91ee04557 100644 (file)
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
source "fs/Kconfig.binfmt"
+config XTFPGA_LCD
+ bool "Enable XTFPGA LCD driver"
+ depends on XTENSA_PLATFORM_XTFPGA
+ default n
+ help
+ There's a 2x16 LCD on most of XTFPGA boards, kernel may output
+ progress messages there during bootup/shutdown. It may be useful
+ during board bringup.
+
+ If unsure, say N.
+
+config XTFPGA_LCD_BASE_ADDR
+ hex "XTFPGA LCD base address"
+ depends on XTFPGA_LCD
+ default "0x0d0c0000"
+ help
+ Base address of the LCD controller inside KIO region.
+ Different boards from XTFPGA family have LCD controller at different
+ addresses. Please consult prototyping user guide for your board for
+ the correct address. Wrong address here may lead to hardware lockup.
+
+config XTFPGA_LCD_8BIT_ACCESS
+ bool "Use 8-bit access to XTFPGA LCD"
+ depends on XTFPGA_LCD
+ default n
+ help
+ LCD may be connected with 4- or 8-bit interface, 8-bit access may
+ only be used with 8-bit interface. Please consult prototyping user
+ guide for your board for the correct interface width.
+
endmenu
source "net/Kconfig"
index 50084f7c01c825958a3d583bede8d23ed4f5793e..b54fa1bd7f7e9dde2b5bb358afedada439a250bf 100644 (file)
__SYSCALL(324, sys_name_to_handle_at, 5)
#define __NR_open_by_handle_at 325
__SYSCALL(325, sys_open_by_handle_at, 3)
-#define __NR_sync_file_range 326
+#define __NR_sync_file_range2 326
__SYSCALL(326, sys_sync_file_range2, 6)
#define __NR_perf_event_open 327
__SYSCALL(327, sys_perf_event_open, 5)
index d05f8feeb8d7e16312367e58f52f9d93a175e0cc..17b1ef3232e4833349c2f64ed19e08dede454b52 100644 (file)
{
struct iss_net_private *lp = (struct iss_net_private *)priv;
- spin_lock(&lp->lock);
iss_net_poll();
+ spin_lock(&lp->lock);
mod_timer(&lp->timer, jiffies + lp->timer_val);
spin_unlock(&lp->lock);
}
struct iss_net_private *lp = netdev_priv(dev);
int err;
- spin_lock(&lp->lock);
+ spin_lock_bh(&lp->lock);
err = lp->tp.open(lp);
if (err < 0)
while ((err = iss_net_rx(dev)) > 0)
;
- spin_lock(&opened_lock);
+ spin_unlock_bh(&lp->lock);
+ spin_lock_bh(&opened_lock);
list_add(&lp->opened_list, &opened);
- spin_unlock(&opened_lock);
+ spin_unlock_bh(&opened_lock);
+ spin_lock_bh(&lp->lock);
init_timer(&lp->timer);
lp->timer_val = ISS_NET_TIMER_VALUE;
mod_timer(&lp->timer, jiffies + lp->timer_val);
out:
- spin_unlock(&lp->lock);
+ spin_unlock_bh(&lp->lock);
return err;
}
{
struct iss_net_private *lp = netdev_priv(dev);
netif_stop_queue(dev);
- spin_lock(&lp->lock);
+ spin_lock_bh(&lp->lock);
spin_lock(&opened_lock);
list_del(&opened);
lp->tp.close(lp);
- spin_unlock(&lp->lock);
+ spin_unlock_bh(&lp->lock);
return 0;
}
static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct iss_net_private *lp = netdev_priv(dev);
- unsigned long flags;
int len;
netif_stop_queue(dev);
- spin_lock_irqsave(&lp->lock, flags);
+ spin_lock_bh(&lp->lock);
len = lp->tp.write(lp, &skb);
pr_err("%s: %s failed(%d)\n", dev->name, __func__, len);
}
- spin_unlock_irqrestore(&lp->lock, flags);
+ spin_unlock_bh(&lp->lock);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
if (!is_valid_ether_addr(hwaddr->sa_data))
return -EADDRNOTAVAIL;
- spin_lock(&lp->lock);
+ spin_lock_bh(&lp->lock);
memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
- spin_unlock(&lp->lock);
+ spin_unlock_bh(&lp->lock);
return 0;
}
*lp = (struct iss_net_private) {
.device_list = LIST_HEAD_INIT(lp->device_list),
.opened_list = LIST_HEAD_INIT(lp->opened_list),
- .lock = __SPIN_LOCK_UNLOCKED(lp.lock),
.dev = dev,
.index = index,
- };
+ };
+ spin_lock_init(&lp->lock);
/*
* If this name ends up conflicting with an existing registered
* netdevice, that is OK, register_netdev{,ice}() will notice this
index b9ae206340cd51012775e22af3391d3839be985e..7839d38b2337885862df5470e06452ea4efce211 100644 (file)
#
# Note 2! The CFLAGS definitions are in the main makefile...
-obj-y = setup.o lcd.o
+obj-y += setup.o
+obj-$(CONFIG_XTFPGA_LCD) += lcd.o
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
index aeb316b7ff8838f9bcff5d8f29202bac7043823c..e8cc86fbba0977e4b1a1bea298c34f51181d14b7 100644 (file)
/* UART */
#define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020)
-/* LCD instruction and data addresses. */
-#define LCD_INSTR_ADDR ((char *)IOADDR(0x0D040000))
-#define LCD_DATA_ADDR ((char *)IOADDR(0x0D040004))
/* Misc. */
#define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000)
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h
index 0e435645af5a1ed2043944b6d6fa46647a7a3d86..4c8541ed11396e52bd570cb2cbd0d7bda1782f00 100644 (file)
#ifndef __XTENSA_XTAVNET_LCD_H
#define __XTENSA_XTAVNET_LCD_H
+#ifdef CONFIG_XTFPGA_LCD
/* Display string STR at position POS on the LCD. */
void lcd_disp_at_pos(char *str, unsigned char pos);
/* Shift the contents of the LCD display left or right. */
void lcd_shiftleft(void);
void lcd_shiftright(void);
+#else
+static inline void lcd_disp_at_pos(char *str, unsigned char pos)
+{
+}
+
+static inline void lcd_shiftleft(void)
+{
+}
+
+static inline void lcd_shiftright(void)
+{
+}
+#endif
+
#endif
index 2872301598df266ffe2822f9eb782b0e23b7156c..4dc0c1b43f4bfd917a65fc04b225a790d0fdfeaa 100644 (file)
/*
- * Driver for the LCD display on the Tensilica LX60 Board.
+ * Driver for the LCD display on the Tensilica XTFPGA board family.
+ * http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001, 2006 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
*/
-/*
- *
- * FIXME: this code is from the examples from the LX60 user guide.
- *
- * The lcd_pause function does busy waiting, which is probably not
- * great. Maybe the code could be changed to use kernel timers, or
- * change the hardware to not need to wait.
- */
-
+#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <platform/hardware.h>
#include <platform/lcd.h>
-#include <linux/delay.h>
-#define LCD_PAUSE_ITERATIONS 4000
+/* LCD instruction and data addresses. */
+#define LCD_INSTR_ADDR ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR))
+#define LCD_DATA_ADDR (LCD_INSTR_ADDR + 4)
+
#define LCD_CLEAR 0x1
#define LCD_DISPLAY_ON 0xc
/* 8bit and 2 lines display */
#define LCD_DISPLAY_MODE8BIT 0x38
+#define LCD_DISPLAY_MODE4BIT 0x28
#define LCD_DISPLAY_POS 0x80
#define LCD_SHIFT_LEFT 0x18
#define LCD_SHIFT_RIGHT 0x1c
+static void lcd_put_byte(u8 *addr, u8 data)
+{
+#ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS
+ ACCESS_ONCE(*addr) = data;
+#else
+ ACCESS_ONCE(*addr) = data & 0xf0;
+ ACCESS_ONCE(*addr) = (data << 4) & 0xf0;
+#endif
+}
+
static int __init lcd_init(void)
{
- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
mdelay(5);
- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
udelay(200);
- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
+ udelay(50);
+#ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS
+ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT;
+ udelay(50);
+ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT);
udelay(50);
- *LCD_INSTR_ADDR = LCD_DISPLAY_ON;
+#endif
+ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON);
udelay(50);
- *LCD_INSTR_ADDR = LCD_CLEAR;
+ lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR);
mdelay(10);
lcd_disp_at_pos("XTENSA LINUX", 0);
return 0;
void lcd_disp_at_pos(char *str, unsigned char pos)
{
- *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos;
+ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos);
udelay(100);
while (*str != 0) {
- *LCD_DATA_ADDR = *str;
+ lcd_put_byte(LCD_DATA_ADDR, *str);
udelay(200);
str++;
}
void lcd_shiftleft(void)
{
- *LCD_INSTR_ADDR = LCD_SHIFT_LEFT;
+ lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT);
udelay(50);
}
void lcd_shiftright(void)
{
- *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT;
+ lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT);
udelay(50);
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 666beea3bf1c41e2d37d14ec95f72441b3864acf..9498c3d575d40b3fe1e33716d30f97d07b290fe3 100644 (file)
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
struct acpi_device_physical_node *pn;
bool offline = true;
- mutex_lock(&adev->physical_node_lock);
+ /*
+ * acpi_container_offline() calls this for all of the container's
+ * children under the container's physical_node_lock lock.
+ */
+ mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING);
list_for_each_entry(pn, &adev->physical_node_list, node)
if (device_supports_offline(pn->dev) && !pn->dev->offline) {
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 45d0fa78981c2cb1b383298a92498c2f47f426c2..12b39dc2ad5c8e679b7dc23291866a54bb6f73bd 100644 (file)
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
goto out_put;
error = device_add_groups(dev, bus->dev_groups);
if (error)
- goto out_groups;
+ goto out_id;
error = sysfs_create_link(&bus->p->devices_kset->kobj,
&dev->kobj, dev_name(dev));
if (error)
- goto out_id;
+ goto out_groups;
error = sysfs_create_link(&dev->kobj,
&dev->bus->p->subsys.kobj, "subsystem");
if (error)
index 5afe556a70f838a5d3d94952b42480e66883febe..26b03e1254ef7ebfc996675085154ed248e4e343 100644 (file)
/* Atheros AR3011 with sflash firmware*/
{ USB_DEVICE(0x0489, 0xE027) },
{ USB_DEVICE(0x0489, 0xE03D) },
+ { USB_DEVICE(0x04F2, 0xAFF1) },
{ USB_DEVICE(0x0930, 0x0215) },
{ USB_DEVICE(0x0CF3, 0x3002) },
{ USB_DEVICE(0x0CF3, 0xE019) },
index 03b331798e16adc6123dcf02c7974b2d04d83393..9eb1669962efe7f76f5a484b2a3a48bf228b7cc3 100644 (file)
/* Atheros 3011 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
index 0996a3a398550f36acdfc2320d70e64075e2afe5..a9dd21aff6bbd73e1ba478e27f8859ff6f70083e 100644 (file)
mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK;
cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
- if (rcg->mnd_width && f->n)
+ if (rcg->mnd_width && f->n && (f->m != f->n))
cfg |= CFG_MODE_DUAL_EDGE;
ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask,
cfg);
index c0a7d77235105472d225d6f528c81e675866fd3c..a90af1780cf2a437f391490b50e4d8913ef3cd70 100644 (file)
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
rst_ctlr.of_node = np;
- rst_ctlr.nr_resets = clk_num * 32;
+ rst_ctlr.nr_resets = periph_banks * 32;
reset_controller_register(&rst_ctlr);
}
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index be56e8ac95e6e3d6240ec1039739f0efbaba74e1..6121375b248a6b550bf9deec9f5e8f3f148f6bc3 100644 (file)
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
comment "Extcon Device Drivers"
+config EXTCON_ADC_JACK
+ tristate "ADC Jack extcon support"
+ depends on IIO
+ help
+ Say Y here to enable extcon device driver based on ADC values.
+
+config EXTCON_ARIZONA
+ tristate "Wolfson Arizona EXTCON support"
+ depends on MFD_ARIZONA && INPUT && SND_SOC
+ help
+ Say Y here to enable support for external accessory detection
+ with Wolfson Arizona devices. These are audio CODECs with
+ advanced audio accessory detection support.
+
config EXTCON_GPIO
tristate "GPIO extcon support"
depends on GPIOLIB
Say Y here to enable GPIO based extcon support. Note that GPIO
extcon supports single state per extcon instance.
-config EXTCON_ADC_JACK
- tristate "ADC Jack extcon support"
- depends on IIO
- help
- Say Y here to enable extcon device driver based on ADC values.
-
config EXTCON_MAX14577
tristate "MAX14577 EXTCON Support"
depends on MFD_MAX14577
Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory
detector and switch.
-config EXTCON_ARIZONA
- tristate "Wolfson Arizona EXTCON support"
- depends on MFD_ARIZONA && INPUT && SND_SOC
- help
- Say Y here to enable support for external accessory detection
- with Wolfson Arizona devices. These are audio CODECs with
- advanced audio accessory detection support.
-
config EXTCON_PALMAS
tristate "Palmas USB EXTCON support"
depends on MFD_PALMAS
Say Y here to enable support for USB peripheral and USB host
detection by palmas usb.
+config EXTCON_USB_GPIO
+ tristate "USB GPIO extcon support"
+ depends on GPIOLIB
+ help
+ Say Y here to enable GPIO based USB cable detection extcon support.
+ Used typically if GPIO is used for USB ID pin detection.
+
endif # MULTISTATE_SWITCH
index bf7861ec090607b881fc3b75d4113c69f10bd2c4..72aa5933d48e1c51e539bc1be2c671d526fd87e0 100644 (file)
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
-#
+
# Makefile for external connector class (extcon) devices
#
obj-$(CONFIG_EXTCON) += extcon-class.o
-obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
+obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
+obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o
-obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o
+obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o
index e23f1c2e505366dd24cb2ff6037f31074f7331ff..d860229e4de1455a31c0700aa5667d0b3d6a679d 100644 (file)
* @chan: iio channel being queried.
*/
struct adc_jack_data {
- struct extcon_dev edev;
+ struct extcon_dev *edev;
const char **cable_names;
int num_cables;
ret = iio_read_channel_raw(data->chan, &adc_val);
if (ret < 0) {
- dev_err(&data->edev.dev, "read channel() error: %d\n", ret);
+ dev_err(&data->edev->dev, "read channel() error: %d\n", ret);
return;
}
}
/* if no def has met, it means state = 0 (no cables attached) */
- extcon_set_state(&data->edev, state);
+ extcon_set_state(data->edev, state);
}
static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
if (!data)
return -ENOMEM;
- data->edev.name = pdata->name;
-
if (!pdata->cable_names) {
- err = -EINVAL;
dev_err(&pdev->dev, "error: cable_names not defined.\n");
- goto out;
+ return -EINVAL;
}
- data->edev.dev.parent = &pdev->dev;
- data->edev.supported_cable = pdata->cable_names;
+ data->edev = devm_extcon_dev_allocate(&pdev->dev, pdata->cable_names);
+ if (IS_ERR(data->edev)) {
+ dev_err(&pdev->dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
+ }
+ data->edev->name = pdata->name;
/* Check the length of array and set num_cables */
- for (i = 0; data->edev.supported_cable[i]; i++)
+ for (i = 0; data->edev->supported_cable[i]; i++)
;
if (i == 0 || i > SUPPORTED_CABLE_MAX) {
- err = -EINVAL;
dev_err(&pdev->dev, "error: pdata->cable_names size = %d\n",
i - 1);
- goto out;
+ return -EINVAL;
}
data->num_cables = i;
if (!pdata->adc_conditions ||
!pdata->adc_conditions[0].state) {
- err = -EINVAL;
dev_err(&pdev->dev, "error: adc_conditions not defined.\n");
- goto out;
+ return -EINVAL;
}
data->adc_conditions = pdata->adc_conditions;
data->num_conditions = i;
data->chan = iio_channel_get(&pdev->dev, pdata->consumer_channel);
- if (IS_ERR(data->chan)) {
- err = PTR_ERR(data->chan);
- goto out;
- }
+ if (IS_ERR(data->chan))
+ return PTR_ERR(data->chan);
data->handling_delay = msecs_to_jiffies(pdata->handling_delay_ms);
platform_set_drvdata(pdev, data);
- err = extcon_dev_register(&data->edev);
+ err = devm_extcon_dev_register(&pdev->dev, data->edev);
if (err)
- goto out;
+ return err;
data->irq = platform_get_irq(pdev, 0);
if (!data->irq) {
dev_err(&pdev->dev, "platform_get_irq failed\n");
- err = -ENODEV;
- goto err_irq;
+ return -ENODEV;
}
err = request_any_context_irq(data->irq, adc_jack_irq_thread,
if (err < 0) {
dev_err(&pdev->dev, "error: irq %d\n", data->irq);
- goto err_irq;
+ return err;
}
return 0;
-
-err_irq:
- extcon_dev_unregister(&data->edev);
-out:
- return err;
}
static int adc_jack_remove(struct platform_device *pdev)
free_irq(data->irq, data);
cancel_work_sync(&data->handler.work);
- extcon_dev_unregister(&data->edev);
return 0;
}
index 98a14f6143a7087accee9c5d2b127c99c300b81d..64f7df916dfec441fe12e7065a830c57473682e1 100644 (file)
int hpdet_ip;
- struct extcon_dev edev;
+ struct extcon_dev *edev;
};
static const struct arizona_micd_config micd_default_modes[] = {
}
/* If the cable was removed while measuring ignore the result */
- ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL);
+ ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL);
if (ret < 0) {
dev_err(arizona->dev, "Failed to check cable state: %d\n",
ret);
else
report = ARIZONA_CABLE_HEADPHONE;
- ret = extcon_set_cable_state_(&info->edev, report, true);
+ ret = extcon_set_cable_state_(info->edev, report, true);
if (ret != 0)
dev_err(arizona->dev, "Failed to report HP/line: %d\n",
ret);
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
/* Just report headphone */
- ret = extcon_update_state(&info->edev,
+ ret = extcon_update_state(info->edev,
1 << ARIZONA_CABLE_HEADPHONE,
1 << ARIZONA_CABLE_HEADPHONE);
if (ret != 0)
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
/* Just report headphone */
- ret = extcon_update_state(&info->edev,
+ ret = extcon_update_state(info->edev,
1 << ARIZONA_CABLE_HEADPHONE,
1 << ARIZONA_CABLE_HEADPHONE);
if (ret != 0)
mutex_lock(&info->lock);
/* If the cable was removed while measuring ignore the result */
- ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL);
+ ret = extcon_get_cable_state_(info->edev, ARIZONA_CABLE_MECHANICAL);
if (ret < 0) {
dev_err(arizona->dev, "Failed to check cable state: %d\n",
ret);
if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
arizona_identify_headphone(info);
- ret = extcon_update_state(&info->edev,
+ ret = extcon_update_state(info->edev,
1 << ARIZONA_CABLE_MICROPHONE,
1 << ARIZONA_CABLE_MICROPHONE);
if (info->last_jackdet == present) {
dev_dbg(arizona->dev, "Detected jack\n");
- ret = extcon_set_cable_state_(&info->edev,
+ ret = extcon_set_cable_state_(info->edev,
ARIZONA_CABLE_MECHANICAL, true);
if (ret != 0)
info->micd_ranges[i].key, 0);
input_sync(info->input);
- ret = extcon_update_state(&info->edev, 0xffffffff, 0);
+ ret = extcon_update_state(info->edev, 0xffffffff, 0);
if (ret != 0)
dev_err(arizona->dev, "Removal report failed: %d\n",
ret);
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info) {
dev_err(&pdev->dev, "Failed to allocate memory\n");
- ret = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
info->micvdd = devm_regulator_get(arizona->dev, "MICVDD");
if (IS_ERR(info->micvdd)) {
ret = PTR_ERR(info->micvdd);
dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
- goto err;
+ return ret;
}
mutex_init(&info->lock);
break;
}
- info->edev.name = "Headset Jack";
- info->edev.dev.parent = arizona->dev;
- info->edev.supported_cable = arizona_cable;
+ info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable);
+ if (IS_ERR(info->edev)) {
+ dev_err(&pdev->dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
+ }
+ info->edev->name = "Headset Jack";
- ret = extcon_dev_register(&info->edev);
+ ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret < 0) {
dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
ret);
- goto err;
+ return ret;
}
info->input = devm_input_allocate_device(&pdev->dev);
err_input:
err_register:
pm_runtime_disable(&pdev->dev);
- extcon_dev_unregister(&info->edev);
-err:
return ret;
}
regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
ARIZONA_JD1_ENA, 0);
arizona_clk32k_disable(arizona);
- extcon_dev_unregister(&info->edev);
return 0;
}
index 7ab21aa6eaa15fa362829c9ee72fa6be3269bc53..4c2f2c543bb753cfeb9c871e222615af3168d60d 100644 (file)
{
}
+/*
+ * extcon_dev_allocate() - Allocate the memory of extcon device.
+ * @supported_cable: Array of supported cable names ending with NULL.
+ * If supported_cable is NULL, cable name related APIs
+ * are disabled.
+ *
+ * This function allocates the memory for extcon device without allocating
+ * memory in each extcon provider driver and initialize default setting for
+ * extcon device.
+ *
+ * Return the pointer of extcon device if success or ERR_PTR(err) if fail
+ */
+struct extcon_dev *extcon_dev_allocate(const char **supported_cable)
+{
+ struct extcon_dev *edev;
+
+ edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+ if (!edev)
+ return ERR_PTR(-ENOMEM);
+
+ edev->max_supported = 0;
+ edev->supported_cable = supported_cable;
+
+ return edev;
+}
+
+/*
+ * extcon_dev_free() - Free the memory of extcon device.
+ * @edev: the extcon device to free
+ */
+void extcon_dev_free(struct extcon_dev *edev)
+{
+ kfree(edev);
+}
+EXPORT_SYMBOL_GPL(extcon_dev_free);
+
+static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
+{
+ struct extcon_dev **r = res;
+
+ if (WARN_ON(!r || !*r))
+ return 0;
+
+ return *r == data;
+}
+
+static void devm_extcon_dev_release(struct device *dev, void *res)
+{
+ extcon_dev_free(*(struct extcon_dev **)res);
+}
+
+/**
+ * devm_extcon_dev_allocate - Allocate managed extcon device
+ * @dev: device owning the extcon device being created
+ * @supported_cable: Array of supported cable names ending with NULL.
+ * If supported_cable is NULL, cable name related APIs
+ * are disabled.
+ *
+ * This function manages automatically the memory of extcon device using device
+ * resource management and simplify the control of freeing the memory of extcon
+ * device.
+ *
+ * Returns the pointer memory of allocated extcon_dev if success
+ * or ERR_PTR(err) if fail
+ */
+struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
+ const char **supported_cable)
+{
+ struct extcon_dev **ptr, *edev;
+
+ ptr = devres_alloc(devm_extcon_dev_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ edev = extcon_dev_allocate(supported_cable);
+ if (IS_ERR(edev)) {
+ devres_free(ptr);
+ return edev;
+ }
+
+ edev->dev.parent = dev;
+
+ *ptr = edev;
+ devres_add(dev, ptr);
+
+ return edev;
+}
+EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate);
+
+void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev)
+{
+ WARN_ON(devres_release(dev, devm_extcon_dev_release,
+ devm_extcon_dev_match, edev));
+}
+EXPORT_SYMBOL_GPL(devm_extcon_dev_free);
+
/**
* extcon_dev_register() - Register a new extcon device
* @edev : the new extcon device (should be allocated before calling)
}
EXPORT_SYMBOL_GPL(extcon_dev_unregister);
+static void devm_extcon_dev_unreg(struct device *dev, void *res)
+{
+ extcon_dev_unregister(*(struct extcon_dev **)res);
+}
+
+/**
+ * devm_extcon_dev_register() - Resource-managed extcon_dev_register()
+ * @dev: device to allocate extcon device
+ * @edev: the new extcon device to register
+ *
+ * Managed extcon_dev_register() function. If extcon device is attached with
+ * this function, that extcon device is automatically unregistered on driver
+ * detach. Internally this function calls extcon_dev_register() function.
+ * To get more information, refer that function.
+ *
+ * If extcon device is registered with this function and the device needs to be
+ * unregistered separately, devm_extcon_dev_unregister() should be used.
+ *
+ * Returns 0 if success or negaive error number if failure.
+ */
+int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev)
+{
+ struct extcon_dev **ptr;
+ int ret;
+
+ ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ ret = extcon_dev_register(edev);
+ if (ret) {
+ devres_free(ptr);
+ return ret;
+ }
+
+ *ptr = edev;
+ devres_add(dev, ptr);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devm_extcon_dev_register);
+
+/**
+ * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister()
+ * @dev: device the extcon belongs to
+ * @edev: the extcon device to unregister
+ *
+ * Unregister extcon device that is registered with devm_extcon_dev_register()
+ * function.
+ */
+void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev)
+{
+ WARN_ON(devres_release(dev, devm_extcon_dev_unreg,
+ devm_extcon_dev_match, edev));
+}
+EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
+
#ifdef CONFIG_OF
/*
* extcon_get_edev_by_phandle - Get the extcon device from devicetree
index 4d192a8239da9d5a4a77ac0041a610e6e6eb0b34..c73c5818a7dda37850b923fc2ee5a43fa8d6f37c 100644 (file)
*
*/
-#include <linux/extcon.h>
-#include <linux/extcon/extcon-gpio.h>
-#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/extcon.h>
+#include <linux/extcon/extcon-gpio.h>
struct gpio_extcon_data {
- struct extcon_dev edev;
- struct gpio_desc *gpiod;
+ struct extcon_dev *edev;
+ unsigned gpio;
+ bool gpio_active_low;
const char *state_on;
const char *state_off;
int irq;
struct delayed_work work;
unsigned long debounce_jiffies;
bool check_on_resume;
- const char *cable_name[1];
};
static void gpio_extcon_work(struct work_struct *work)
container_of(to_delayed_work(work), struct gpio_extcon_data,
work);
- state = gpiod_get_value_cansleep(data->gpiod);
- extcon_set_state(&data->edev, state);
+ state = gpio_get_value(data->gpio);
+ if (data->gpio_active_low)
+ state = !state;
+ extcon_set_state(data->edev, state);
}
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
{
- struct gpio_extcon_data *extcon_data =
- container_of(edev, struct gpio_extcon_data, edev);
+ struct device *dev = edev->dev.parent;
+ struct gpio_extcon_data *extcon_data = dev_get_drvdata(dev);
const char *state;
+
if (extcon_get_state(edev))
state = extcon_data->state_on;
else
static int gpio_extcon_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct gpio_extcon_data *extcon_data;
int ret;
- unsigned int irq_flags;
- unsigned int debounce = 0;
+
+ if (!pdata)
+ return -EBUSY;
+ if (!pdata->irq_flags) {
+ dev_err(&pdev->dev, "IRQ flag is not specified.\n");
+ return -EINVAL;
+ }
extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data),
GFP_KERNEL);
if (!extcon_data)
return -ENOMEM;
- if (np) {
- int irq;
-
- extcon_data->gpiod = devm_gpiod_get(&pdev->dev, NULL);
- if (IS_ERR(extcon_data->gpiod))
- return PTR_ERR(extcon_data->gpiod);
-
- extcon_data->edev.name = np->name;
- extcon_data->edev.dev.parent = &pdev->dev;
- of_property_read_u32(np, "debounce", &debounce);
- irq = gpiod_to_irq(extcon_data->gpiod);
- irq_flags = irq_get_trigger_type(irq);
- of_property_read_string_index(np, "cable-name", 0,
- extcon_data->cable_name);
- extcon_data->edev.supported_cable = extcon_data->cable_name;
- } else {
- if (!pdata)
- return -EBUSY;
-
- if (!pdata->irq_flags) {
- dev_err(&pdev->dev, "IRQ flag is not specified.\n");
- return -EINVAL;
- }
-
- extcon_data->edev.name = pdata->name;
- extcon_data->edev.dev.parent = &pdev->dev;
- extcon_data->state_on = pdata->state_on;
- extcon_data->state_off = pdata->state_off;
- extcon_data->check_on_resume = pdata->check_on_resume;
- if (pdata->state_on && pdata->state_off)
- extcon_data->edev.print_state = extcon_gpio_print_state;
-
- extcon_data->gpiod = gpio_to_desc(pdata->gpio);
- ret = devm_gpio_request_one(&pdev->dev, pdata->gpio,
- GPIOF_DIR_IN, pdev->name);
- if (ret < 0)
- return ret;
- irq_flags = pdata->irq_flags;
- debounce = pdata->debounce;
+ extcon_data->edev = devm_extcon_dev_allocate(&pdev->dev, NULL);
+ if (IS_ERR(extcon_data->edev)) {
+ dev_err(&pdev->dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
}
+ extcon_data->edev->name = pdata->name;
+
+ extcon_data->gpio = pdata->gpio;
+ extcon_data->gpio_active_low = pdata->gpio_active_low;
+ extcon_data->state_on = pdata->state_on;
+ extcon_data->state_off = pdata->state_off;
+ extcon_data->check_on_resume = pdata->check_on_resume;
+ if (pdata->state_on && pdata->state_off)
+ extcon_data->edev->print_state = extcon_gpio_print_state;
+
+ ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN,
+ pdev->name);
+ if (ret < 0)
+ return ret;
- if (debounce) {
- ret = gpiod_set_debounce(extcon_data->gpiod,
- debounce * 1000);
+ if (pdata->debounce) {
+ ret = gpio_set_debounce(extcon_data->gpio,
+ pdata->debounce * 1000);
if (ret < 0)
extcon_data->debounce_jiffies =
- msecs_to_jiffies(debounce);
+ msecs_to_jiffies(pdata->debounce);
}
- ret = extcon_dev_register(&extcon_data->edev);
+ ret = devm_extcon_dev_register(&pdev->dev, extcon_data->edev);
if (ret < 0)
return ret;
INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work);
- extcon_data->irq = gpiod_to_irq(extcon_data->gpiod);
- if (extcon_data->irq < 0) {
- ret = extcon_data->irq;
- goto err;
- }
+ extcon_data->irq = gpio_to_irq(extcon_data->gpio);
+ if (extcon_data->irq < 0)
+ return extcon_data->irq;
ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler,
- irq_flags, pdev->name,
+ pdata->irq_flags, pdev->name,
extcon_data);
if (ret < 0)
- goto err;
+ return ret;
platform_set_drvdata(pdev, extcon_data);
/* Perform initial detection */
gpio_extcon_work(&extcon_data->work.work);
return 0;
-
-err:
- extcon_dev_unregister(&extcon_data->edev);
-
- return ret;
}
static int gpio_extcon_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&extcon_data->work);
free_irq(extcon_data->irq, extcon_data);
- extcon_dev_unregister(&extcon_data->edev);
return 0;
}
SET_SYSTEM_SLEEP_PM_OPS(NULL, gpio_extcon_resume)
};
-static struct of_device_id of_extcon_gpio_match_tbl[] = {
- { .compatible = "linux,extcon-gpio", },
- { /* end */ }
-};
-
static struct platform_driver gpio_extcon_driver = {
.probe = gpio_extcon_probe,
.remove = gpio_extcon_remove,
.name = "extcon-gpio",
.owner = THIS_MODULE,
.pm = &gpio_extcon_pm_ops,
- .of_match_table = of_extcon_gpio_match_tbl,
},
};
index 5c948c9625d25c1d76489c6f5b6ffbe6eade9cc3..12f5a91ed8c4bd58eaa48e07c7d67742502e8aa1 100644 (file)
}
/* Initialize extcon device */
- info->edev = devm_kzalloc(&pdev->dev, sizeof(*info->edev), GFP_KERNEL);
- if (!info->edev) {
+ info->edev = devm_extcon_dev_allocate(&pdev->dev,
+ max14577_extcon_cable);
+ if (IS_ERR(info->edev)) {
dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
return -ENOMEM;
}
info->edev->name = DEV_NAME;
- info->edev->supported_cable = max14577_extcon_cable;
- ret = extcon_dev_register(info->edev);
+
+ ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret) {
dev_err(&pdev->dev, "failed to register extcon device\n");
return ret;
MAX14577_REG_DEVICEID, &id);
if (ret < 0) {
dev_err(&pdev->dev, "failed to read revision number\n");
- goto err_extcon;
+ return ret;
}
dev_info(info->dev, "device ID : 0x%x\n", id);
delay_jiffies);
return ret;
-
-err_extcon:
- extcon_dev_unregister(info->edev);
- return ret;
}
static int max14577_muic_remove(struct platform_device *pdev)
struct max14577_muic_info *info = platform_get_drvdata(pdev);
cancel_work_sync(&info->irq_work);
- extcon_dev_unregister(info->edev);
return 0;
}
index 4657a91acf56c311551727de122400fb35d09fac..40a1730744ebea5a26492ed9d322b69360b8a48f 100644 (file)
}
/* Initialize extcon device */
- info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
- GFP_KERNEL);
- if (!info->edev) {
+ info->edev = devm_extcon_dev_allocate(&pdev->dev,
+ max77693_extcon_cable);
+ if (IS_ERR(info->edev)) {
dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
ret = -ENOMEM;
goto err_irq;
}
info->edev->name = DEV_NAME;
- info->edev->dev.parent = &pdev->dev;
- info->edev->supported_cable = max77693_extcon_cable;
- ret = extcon_dev_register(info->edev);
+
+ ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret) {
dev_err(&pdev->dev, "failed to register extcon device\n");
goto err_irq;
}
-
/* Initialize MUIC register by using platform data or default data */
if (pdata && pdata->muic_data) {
init_data = pdata->muic_data->init_data;
MAX77693_MUIC_REG_ID, &id);
if (ret < 0) {
dev_err(&pdev->dev, "failed to read revision number\n");
- goto err_extcon;
+ goto err_irq;
}
dev_info(info->dev, "device ID : 0x%x\n", id);
return ret;
-err_extcon:
- extcon_dev_unregister(info->edev);
err_irq:
while (--i >= 0)
free_irq(muic_irqs[i].virq, info);
free_irq(muic_irqs[i].virq, info);
cancel_work_sync(&info->irq_work);
input_unregister_device(info->dock);
- extcon_dev_unregister(info->edev);
return 0;
}
index 5e1b88cecb76a5eb036e8407f02c2b71a388d7c9..1f906e1b0720ee7ef3d56eebd81189c076b3a4d3 100644 (file)
}
/* External connector */
- info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
- GFP_KERNEL);
- if (!info->edev) {
+ info->edev = devm_extcon_dev_allocate(&pdev->dev, max8997_extcon_cable);
+ if (IS_ERR(info->edev)) {
dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
ret = -ENOMEM;
goto err_irq;
}
info->edev->name = DEV_NAME;
- info->edev->dev.parent = &pdev->dev;
- info->edev->supported_cable = max8997_extcon_cable;
- ret = extcon_dev_register(info->edev);
+
+ ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret) {
dev_err(&pdev->dev, "failed to register extcon device\n");
goto err_irq;
free_irq(muic_irqs[i].virq, info);
cancel_work_sync(&info->irq_work);
- extcon_dev_unregister(info->edev);
-
return 0;
}
index 51dee215ba8167b85e0b39b08db45acbf6bd6d8e..ae73950903c537586e9e381499eb181afdb8619f 100644 (file)
if (vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS) {
if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) {
palmas_usb->linkstat = PALMAS_USB_STATE_VBUS;
- extcon_set_cable_state(&palmas_usb->edev, "USB", true);
+ extcon_set_cable_state(palmas_usb->edev, "USB", true);
dev_info(palmas_usb->dev, "USB cable is attached\n");
} else {
dev_dbg(palmas_usb->dev,
} else if (!(vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS)) {
if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) {
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
- extcon_set_cable_state(&palmas_usb->edev, "USB", false);
+ extcon_set_cable_state(palmas_usb->edev, "USB", false);
dev_info(palmas_usb->dev, "USB cable is detached\n");
} else {
dev_dbg(palmas_usb->dev,
PALMAS_USB_ID_INT_LATCH_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
palmas_usb->linkstat = PALMAS_USB_STATE_ID;
- extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true);
+ extcon_set_cable_state(palmas_usb->edev, "USB-HOST", true);
dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
} else if ((set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) &&
(id_src & PALMAS_USB_ID_INT_SRC_ID_FLOAT)) {
PALMAS_USB_ID_INT_LATCH_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
- extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
+ extcon_set_cable_state(palmas_usb->edev, "USB-HOST", false);
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
} else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) &&
(!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) {
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
- extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
+ extcon_set_cable_state(palmas_usb->edev, "USB-HOST", false);
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
} else if ((palmas_usb->linkstat == PALMAS_USB_STATE_DISCONNECT) &&
(id_src & PALMAS_USB_ID_INT_SRC_ID_GND)) {
palmas_usb->linkstat = PALMAS_USB_STATE_ID;
- extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true);
+ extcon_set_cable_state(palmas_usb->edev, "USB-HOST", true);
dev_info(palmas_usb->dev, " USB-HOST cable is attached\n");
}
platform_set_drvdata(pdev, palmas_usb);
- palmas_usb->edev.supported_cable = palmas_extcon_cable;
- palmas_usb->edev.dev.parent = palmas_usb->dev;
- palmas_usb->edev.name = kstrdup(node->name, GFP_KERNEL);
- palmas_usb->edev.mutually_exclusive = mutually_exclusive;
+ palmas_usb->edev = devm_extcon_dev_allocate(&pdev->dev,
+ palmas_extcon_cable);
+ if (IS_ERR(palmas_usb->edev)) {
+ dev_err(&pdev->dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
+ }
+ palmas_usb->edev->name = kstrdup(node->name, GFP_KERNEL);
+ palmas_usb->edev->mutually_exclusive = mutually_exclusive;
- status = extcon_dev_register(&palmas_usb->edev);
+ status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
if (status) {
dev_err(&pdev->dev, "failed to register extcon device\n");
- kfree(palmas_usb->edev.name);
+ kfree(palmas_usb->edev->name);
return status;
}
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->id_irq, status);
- goto fail_extcon;
+ kfree(palmas_usb->edev->name);
+ return status;
}
}
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->vbus_irq, status);
- goto fail_extcon;
+ kfree(palmas_usb->edev->name);
+ return status;
}
}
palmas_enable_irq(palmas_usb);
device_set_wakeup_capable(&pdev->dev, true);
return 0;
-
-fail_extcon:
- extcon_dev_unregister(&palmas_usb->edev);
- kfree(palmas_usb->edev.name);
-
- return status;
}
static int palmas_usb_remove(struct platform_device *pdev)
{
struct palmas_usb *palmas_usb = platform_get_drvdata(pdev);
- extcon_dev_unregister(&palmas_usb->edev);
- kfree(palmas_usb->edev.name);
+ kfree(palmas_usb->edev->name);
return 0;
}
palmas_usb_resume)
};
-static struct of_device_id of_palmas_match_tbl[] = {
+static const struct of_device_id of_palmas_match_tbl[] = {
{ .compatible = "ti,palmas-usb", },
{ .compatible = "ti,palmas-usb-vid", },
{ .compatible = "ti,twl6035-usb", },
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
--- /dev/null
@@ -0,0 +1,316 @@
+/**
+ * drivers/extcon/extcon-usb-gpio.c - USB GPIO extcon driver
+ *
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Roger Quadros <rogerq@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/extcon.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
+
+struct usb_extcon_info {
+ struct device *dev;
+ struct extcon_dev *edev;
+
+ struct gpio_desc *id_gpiod;
+ struct gpio_desc *vbus_gpiod;
+ int id_irq;
+ int vbus_irq;
+
+ unsigned long debounce_jiffies;
+ struct delayed_work wq_detcable;
+};
+
+/* List of detectable cables */
+enum {
+ EXTCON_CABLE_USB = 0,
+ EXTCON_CABLE_USB_HOST,
+
+ EXTCON_CABLE_END,
+};
+
+static const char *usb_extcon_cable[] = {
+ [EXTCON_CABLE_USB] = "USB",
+ [EXTCON_CABLE_USB_HOST] = "USB-HOST",
+ NULL,
+};
+
+/*
+ * "USB" = VBUS and "USB-HOST" = !ID, so we have:
+ *
+ * State | ID | VBUS
+ * ----------------------------------------
+ * [1] USB | H | H
+ * [2] none | H | L
+ * [3] USB & USB-HOST | L | H
+ * [4] USB-HOST | L | L
+ *
+ * In case we have only one of these signals:
+ * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1.
+ * - ID only - we want to distinguish between [1] and [4], so VBUS = ID.
+ */
+
+static void usb_extcon_detect_cable(struct work_struct *work)
+{
+ int id;
+ int vbus;
+ struct usb_extcon_info *info = container_of(to_delayed_work(work),
+ struct usb_extcon_info,
+ wq_detcable);
+
+ /* check ID and VBUS and update cable state */
+
+ id = info->id_gpiod ?
+ gpiod_get_value_cansleep(info->id_gpiod) : 1;
+
+ vbus = info->vbus_gpiod ?
+ gpiod_get_value_cansleep(info->vbus_gpiod) : id;
+
+ /* at first we clean states which are no longer active */
+ if (id)
+ extcon_set_cable_state(info->edev,
+ usb_extcon_cable[EXTCON_CABLE_USB_HOST], false);
+ if (!vbus)
+ extcon_set_cable_state(info->edev,
+ usb_extcon_cable[EXTCON_CABLE_USB], false);
+
+ if (!id)
+ extcon_set_cable_state(info->edev,
+ usb_extcon_cable[EXTCON_CABLE_USB_HOST], true);
+ if (vbus)
+ extcon_set_cable_state(info->edev,
+ usb_extcon_cable[EXTCON_CABLE_USB], true);
+}
+
+static irqreturn_t usb_irq_handler(int irq, void *dev_id)
+{
+ struct usb_extcon_info *info = dev_id;
+
+ queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
+ info->debounce_jiffies);
+
+ return IRQ_HANDLED;
+}
+
+static int usb_extcon_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct usb_extcon_info *info;
+ u32 debounce;
+ int ret;
+
+ if (!np)
+ return -EINVAL;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = dev;
+
+ ret = of_property_read_u32(np, "debounce", &debounce);
+ if (ret < 0)
+ debounce = USB_GPIO_DEBOUNCE_MS;
+
+ info->id_gpiod = devm_gpiod_get(&pdev->dev, "id");
+ info->vbus_gpiod = devm_gpiod_get(&pdev->dev, "vbus");
+
+ if (IS_ERR(info->id_gpiod))
+ info->id_gpiod = NULL;
+
+ if (IS_ERR(info->vbus_gpiod))
+ info->vbus_gpiod = NULL;
+
+ if (!info->id_gpiod && !info->vbus_gpiod) {
+ dev_err(dev, "failed to get gpios\n");
+ return -ENODEV;
+ }
+
+ info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
+ if (IS_ERR(info->edev)) {
+ dev_err(dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
+ }
+
+ ret = devm_extcon_dev_register(dev, info->edev);
+ if (ret < 0) {
+ dev_err(dev, "failed to register extcon device\n");
+ return ret;
+ }
+
+ if (info->id_gpiod)
+ ret = gpiod_set_debounce(info->id_gpiod, debounce * 1000);
+ if (!ret && info->vbus_gpiod) {
+ ret = gpiod_set_debounce(info->vbus_gpiod, debounce * 1000);
+ if (ret < 0 && info->id_gpiod)
+ gpiod_set_debounce(info->vbus_gpiod, 0);
+ }
+ if (ret < 0)
+ info->debounce_jiffies = msecs_to_jiffies(debounce);
+
+ INIT_DELAYED_WORK(&info->wq_detcable, usb_extcon_detect_cable);
+
+ if (info->id_gpiod) {
+ info->id_irq = gpiod_to_irq(info->id_gpiod);
+ if (info->id_irq < 0) {
+ dev_err(dev, "failed to get ID IRQ\n");
+ return info->id_irq;
+ }
+ ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+ usb_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ pdev->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for ID IRQ\n");
+ return ret;
+ }
+ }
+ if (info->vbus_gpiod) {
+ info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
+ if (info->vbus_irq < 0) {
+ dev_err(dev, "failed to get VBUS IRQ\n");
+ return info->vbus_irq;
+ }
+ ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+ usb_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ pdev->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for VBUS IRQ\n");
+ return ret;
+ }
+ }
+
+ platform_set_drvdata(pdev, info);
+ device_init_wakeup(dev, 1);
+
+ /* Perform initial detection */
+ usb_extcon_detect_cable(&info->wq_detcable.work);
+
+ return 0;
+}
+
+static int usb_extcon_remove(struct platform_device *pdev)
+{
+ struct usb_extcon_info *info = platform_get_drvdata(pdev);
+
+ cancel_delayed_work_sync(&info->wq_detcable);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int usb_extcon_suspend(struct device *dev)
+{
+ struct usb_extcon_info *info = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (device_may_wakeup(dev)) {
+ if (info->id_gpiod) {
+ ret = enable_irq_wake(info->id_irq);
+ if (ret)
+ return ret;
+ }
+ if (info->vbus_gpiod) {
+ ret = enable_irq_wake(info->vbus_irq);
+ if (ret)
+ goto err;
+ }
+ }
+
+ /*
+ * We don't want to process any IRQs after this point
+ * as GPIOs used behind I2C subsystem might not be
+ * accessible until resume completes. So disable IRQ.
+ */
+ if (info->id_gpiod)
+ disable_irq(info->id_irq);
+ if (info->vbus_gpiod)
+ disable_irq(info->vbus_irq);
+
+ return ret;
+
+err:
+ if (info->id_gpiod)
+ disable_irq_wake(info->id_irq);
+ return ret;
+}
+
+static int usb_extcon_resume(struct device *dev)
+{
+ struct usb_extcon_info *info = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (device_may_wakeup(dev)) {
+ if (info->id_gpiod) {
+ ret = disable_irq_wake(info->id_irq);
+ if (ret)
+ return ret;
+ }
+ if (info->vbus_gpiod) {
+ ret = disable_irq_wake(info->vbus_irq);
+ if (ret)
+ goto err;
+ }
+ }
+
+ if (info->id_gpiod)
+ enable_irq(info->id_irq);
+ if (info->vbus_gpiod)
+ enable_irq(info->vbus_irq);
+
+ return ret;
+
+err:
+ if (info->id_gpiod)
+ enable_irq_wake(info->id_irq);
+ return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(usb_extcon_pm_ops,
+ usb_extcon_suspend, usb_extcon_resume);
+
+static struct of_device_id usb_extcon_dt_match[] = {
+ { .compatible = "linux,extcon-usb-gpio", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, usb_extcon_dt_match);
+
+static struct platform_driver usb_extcon_driver = {
+ .probe = usb_extcon_probe,
+ .remove = usb_extcon_remove,
+ .driver = {
+ .name = "extcon-usb-gpio",
+ .pm = &usb_extcon_pm_ops,
+ .of_match_table = usb_extcon_dt_match,
+ },
+};
+
+module_platform_driver(usb_extcon_driver);
+
+MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
+MODULE_DESCRIPTION("USB GPIO extcon driver");
+MODULE_LICENSE("GPL v2");
index 3b1fd1ce460f258fb0151550f5cb30b1260b4e62..e9d8cf6c2f79cb6b96f5dae0f94f0cf77c286733 100644 (file)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mvebu_gpio_chip *mvchip = gc->private;
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache &= ~mask;
- writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+ ct->mask_cache_priv &= ~mask;
+
+ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip));
irq_gc_unlock(gc);
}
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mvebu_gpio_chip *mvchip = gc->private;
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache |= mask;
- writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+ ct->mask_cache_priv |= mask;
+ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip));
irq_gc_unlock(gc);
}
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mvebu_gpio_chip *mvchip = gc->private;
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache &= ~mask;
- writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+ ct->mask_cache_priv &= ~mask;
+ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip));
irq_gc_unlock(gc);
}
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mvebu_gpio_chip *mvchip = gc->private;
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
- gc->mask_cache |= mask;
- writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+ ct->mask_cache_priv |= mask;
+ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip));
irq_gc_unlock(gc);
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 430536b65951bed47014519ed49127b8cb939555..f6fdda1d3825a6a35a96b1cf9d7c3bad0b6f8079 100644 (file)
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
* that the GPIO was actually requested.
*/
-static int _gpiod_get_raw_value(const struct gpio_desc *desc)
+static bool _gpiod_get_raw_value(const struct gpio_desc *desc)
{
struct gpio_chip *chip;
- int value;
+ bool value;
int offset;
chip = desc->chip;
offset = gpio_chip_hwgpio(desc);
- value = chip->get ? chip->get(chip, offset) : 0;
+ value = chip->get ? chip->get(chip, offset) : false;
trace_gpio_value(desc_to_gpio(desc), 1, value);
return value;
}
* @desc: gpio descriptor whose state need to be set.
* @value: Non-zero for setting it HIGH otherise it will set to LOW.
*/
-static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)
+static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value)
{
int err = 0;
struct gpio_chip *chip = desc->chip;
* @desc: gpio descriptor whose state need to be set.
* @value: Non-zero for setting it HIGH otherise it will set to LOW.
*/
-static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)
+static void _gpio_set_open_source_value(struct gpio_desc *desc, bool value)
{
int err = 0;
struct gpio_chip *chip = desc->chip;
__func__, err);
}
-static void _gpiod_set_raw_value(struct gpio_desc *desc, int value)
+static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value)
{
struct gpio_chip *chip;
index 0c83b3dab58c0142743e46cc4d88c5784f812e3d..5b38bf819b7b64b57cc6123d8af095421bfcb657 100644 (file)
#define GMBUS_CYCLE_INDEX (2<<25)
#define GMBUS_CYCLE_STOP (4<<25)
#define GMBUS_BYTE_COUNT_SHIFT 16
+#define GMBUS_BYTE_COUNT_MAX 256U
#define GMBUS_SLAVE_INDEX_SHIFT 8
#define GMBUS_SLAVE_ADDR_SHIFT 1
#define GMBUS_SLAVE_READ (1<<0)
index d33b61d0dd3331b6bd073806d0482b19aeb0eb08..1d02970ed395bf793b71aa6ac815b7b2300341b0 100644 (file)
}
static int
-gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
- u32 gmbus1_index)
+gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
+ unsigned short addr, u8 *buf, unsigned int len,
+ u32 gmbus1_index)
{
int reg_offset = dev_priv->gpio_mmio_base;
- u16 len = msg->len;
- u8 *buf = msg->buf;
I915_WRITE(GMBUS1 + reg_offset,
gmbus1_index |
GMBUS_CYCLE_WAIT |
(len << GMBUS_BYTE_COUNT_SHIFT) |
- (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
+ (addr << GMBUS_SLAVE_ADDR_SHIFT) |
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
while (len) {
int ret;
}
static int
-gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
+gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
+ u32 gmbus1_index)
{
- int reg_offset = dev_priv->gpio_mmio_base;
- u16 len = msg->len;
u8 *buf = msg->buf;
+ unsigned int rx_size = msg->len;
+ unsigned int len;
+ int ret;
+
+ do {
+ len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+
+ ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
+ buf, len, gmbus1_index);
+ if (ret)
+ return ret;
+
+ rx_size -= len;
+ buf += len;
+ } while (rx_size != 0);
+
+ return 0;
+}
+
+static int
+gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
+ unsigned short addr, u8 *buf, unsigned int len)
+{
+ int reg_offset = dev_priv->gpio_mmio_base;
+ unsigned int chunk_size = len;
u32 val, loop;
val = loop = 0;
I915_WRITE(GMBUS3 + reg_offset, val);
I915_WRITE(GMBUS1 + reg_offset,
GMBUS_CYCLE_WAIT |
- (msg->len << GMBUS_BYTE_COUNT_SHIFT) |
- (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
+ (chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
+ (addr << GMBUS_SLAVE_ADDR_SHIFT) |
GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
while (len) {
int ret;
if (ret)
return ret;
}
+
+ return 0;
+}
+
+static int
+gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
+{
+ u8 *buf = msg->buf;
+ unsigned int tx_size = msg->len;
+ unsigned int len;
+ int ret;
+
+ do {
+ len = min(tx_size, GMBUS_BYTE_COUNT_MAX);
+
+ ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len);
+ if (ret)
+ return ret;
+
+ buf += len;
+ tx_size -= len;
+ } while (tx_size != 0);
+
return 0;
}
index 461df93e825edf81e98d22683cfbf4fe7b4404aa..4f32b34f48d43b83bd62dcf2d5ddf951dab2875f 100644 (file)
A3XX_INT0_CP_AHB_ERROR_HALT | \
A3XX_INT0_UCHE_OOB_ACCESS)
-static struct platform_device *a3xx_pdev;
-
static void a3xx_me_init(struct msm_gpu *gpu)
{
struct msm_ringbuffer *ring = gpu->rb;
ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
#endif
- put_device(&a3xx_gpu->pdev->dev);
kfree(a3xx_gpu);
}
struct a3xx_gpu *a3xx_gpu = NULL;
struct adreno_gpu *adreno_gpu;
struct msm_gpu *gpu;
- struct platform_device *pdev = a3xx_pdev;
+ struct msm_drm_private *priv = dev->dev_private;
+ struct platform_device *pdev = priv->gpu_pdev;
struct adreno_platform_config *config;
int ret;
adreno_gpu = &a3xx_gpu->base;
gpu = &adreno_gpu->base;
- get_device(&pdev->dev);
a3xx_gpu->pdev = pdev;
gpu->fast_rate = config->fast_rate;
# include <mach/kgsl.h>
#endif
-static int a3xx_probe(struct platform_device *pdev)
+static void set_gpu_pdev(struct drm_device *dev,
+ struct platform_device *pdev)
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ priv->gpu_pdev = pdev;
+}
+
+static int a3xx_bind(struct device *dev, struct device *master, void *data)
{
static struct adreno_platform_config config = {};
#ifdef CONFIG_OF
- struct device_node *child, *node = pdev->dev.of_node;
+ struct device_node *child, *node = dev->of_node;
u32 val;
int ret;
ret = of_property_read_u32(node, "qcom,chipid", &val);
if (ret) {
- dev_err(&pdev->dev, "could not find chipid: %d\n", ret);
+ dev_err(dev, "could not find chipid: %d\n", ret);
return ret;
}
for_each_child_of_node(child, pwrlvl) {
ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
if (ret) {
- dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret);
+ dev_err(dev, "could not find gpu-freq: %d\n", ret);
return ret;
}
config.fast_rate = max(config.fast_rate, val);
}
if (!config.fast_rate) {
- dev_err(&pdev->dev, "could not find clk rates\n");
+ dev_err(dev, "could not find clk rates\n");
return -ENXIO;
}
#else
- struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
+ struct kgsl_device_platform_data *pdata = dev->platform_data;
uint32_t version = socinfo_get_version();
if (cpu_is_apq8064ab()) {
config.fast_rate = 450000000;
config.bus_scale_table = pdata->bus_scale_table;
# endif
#endif
- pdev->dev.platform_data = &config;
- a3xx_pdev = pdev;
+ dev->platform_data = &config;
+ set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
return 0;
}
+static void a3xx_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ set_gpu_pdev(dev_get_drvdata(master), NULL);
+}
+
+static const struct component_ops a3xx_ops = {
+ .bind = a3xx_bind,
+ .unbind = a3xx_unbind,
+};
+
+static int a3xx_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &a3xx_ops);
+}
+
static int a3xx_remove(struct platform_device *pdev)
{
- a3xx_pdev = NULL;
+ component_del(&pdev->dev, &a3xx_ops);
return 0;
}
{ .compatible = "qcom,kgsl-3d0" },
{}
};
-MODULE_DEVICE_TABLE(of, dt_match);
static struct platform_driver a3xx_driver = {
.probe = a3xx_probe,
index 6f1588aa9071f8db8642dcb8b32e46642381b38d..8a04a1d206cd50bcdc57f8277f0696c230c7749b 100644 (file)
#include "hdmi.h"
-static struct platform_device *hdmi_pdev;
-
void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
{
uint32_t ctrl = 0;
{
struct hdmi *hdmi = NULL;
struct msm_drm_private *priv = dev->dev_private;
- struct platform_device *pdev = hdmi_pdev;
+ struct platform_device *pdev = priv->hdmi_pdev;
struct hdmi_platform_config *config;
int i, ret;
kref_init(&hdmi->refcount);
- get_device(&pdev->dev);
-
hdmi->dev = dev;
hdmi->pdev = pdev;
hdmi->config = config;
#include <linux/of_gpio.h>
-static int hdmi_dev_probe(struct platform_device *pdev)
+static void set_hdmi_pdev(struct drm_device *dev,
+ struct platform_device *pdev)
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ priv->hdmi_pdev = pdev;
+}
+
+static int hdmi_bind(struct device *dev, struct device *master, void *data)
{
static struct hdmi_platform_config config = {};
#ifdef CONFIG_OF
- struct device_node *of_node = pdev->dev.of_node;
+ struct device_node *of_node = dev->of_node;
int get_gpio(const char *name)
{
int gpio = of_get_named_gpio(of_node, name, 0);
if (gpio < 0) {
- dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n",
+ dev_err(dev, "failed to get gpio: %s (%d)\n",
name, gpio);
gpio = -1;
}
config.mux_sel_gpio = -1;
}
#endif
- pdev->dev.platform_data = &config;
- hdmi_pdev = pdev;
+ dev->platform_data = &config;
+ set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev));
return 0;
}
+static void hdmi_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ set_hdmi_pdev(dev_get_drvdata(master), NULL);
+}
+
+static const struct component_ops hdmi_ops = {
+ .bind = hdmi_bind,
+ .unbind = hdmi_unbind,
+};
+
+static int hdmi_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &hdmi_ops);
+}
+
static int hdmi_dev_remove(struct platform_device *pdev)
{
- hdmi_pdev = NULL;
+ component_del(&pdev->dev, &hdmi_ops);
return 0;
}
{ .compatible = "qcom,hdmi-tx" },
{}
};
-MODULE_DEVICE_TABLE(of, dt_match);
static struct platform_driver hdmi_driver = {
.probe = hdmi_dev_probe,
index e6adafc7eff3177b789395f6bc81f4ab62042e11..e79cfd0b2b04592097fb11dbee8b2fb2a4d6b021 100644 (file)
MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
module_param(vram, charp, 0);
+/*
+ * Util/helpers:
+ */
+
void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
const char *dbgname)
{
priv->vram.paddr, &attrs);
}
+ component_unbind_all(dev->dev, dev);
+
dev->dev_private = NULL;
kfree(priv);
struct msm_kms *kms;
int ret;
+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(dev->dev, "failed to allocate private data\n");
(uint32_t)(priv->vram.paddr + size));
}
+ platform_set_drvdata(pdev, dev);
+
+ /* Bind all our sub-components: */
+ ret = component_bind_all(dev->dev, dev);
+ if (ret)
+ return ret;
+
switch (get_mdp_ver(pdev)) {
case 4:
kms = mdp4_kms_init(dev);
goto fail;
}
- platform_set_drvdata(pdev, dev);
-
#ifdef CONFIG_DRM_MSM_FBDEV
priv->fbdev = msm_fbdev_init(dev);
#endif
SET_SYSTEM_SLEEP_PM_OPS(msm_pm_suspend, msm_pm_resume)
};
+/*
+ * Componentized driver support:
+ */
+
+#ifdef CONFIG_OF
+/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx
+ * (or probably any other).. so probably some room for some helpers
+ */
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+static int msm_drm_add_components(struct device *master, struct master *m)
+{
+ struct device_node *np = master->of_node;
+ unsigned i;
+ int ret;
+
+ for (i = 0; ; i++) {
+ struct device_node *node;
+
+ node = of_parse_phandle(np, "connectors", i);
+ if (!node)
+ break;
+
+ ret = component_master_add_child(m, compare_of, node);
+ of_node_put(node);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+#else
+static int compare_dev(struct device *dev, void *data)
+{
+ return dev == data;
+}
+
+static int msm_drm_add_components(struct device *master, struct master *m)
+{
+ /* For non-DT case, it kinda sucks. We don't actually have a way
+ * to know whether or not we are waiting for certain devices (or if
+ * they are simply not present). But for non-DT we only need to
+ * care about apq8064/apq8060/etc (all mdp4/a3xx):
+ */
+ static const char *devnames[] = {
+ "hdmi_msm.0", "kgsl-3d0.0",
+ };
+ int i;
+
+ DBG("Adding components..");
+
+ for (i = 0; i < ARRAY_SIZE(devnames); i++) {
+ struct device *dev;
+ int ret;
+
+ dev = bus_find_device_by_name(&platform_bus_type,
+ NULL, devnames[i]);
+ if (!dev) {
+ dev_info(master, "still waiting for %s\n", devnames[i]);
+ return -EPROBE_DEFER;
+ }
+
+ ret = component_master_add_child(m, compare_dev, dev);
+ if (ret) {
+ DBG("could not add child: %d", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static int msm_drm_bind(struct device *dev)
+{
+ return drm_platform_init(&msm_driver, to_platform_device(dev));
+}
+
+static void msm_drm_unbind(struct device *dev)
+{
+ drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
+}
+
+static const struct component_master_ops msm_drm_ops = {
+ .add_components = msm_drm_add_components,
+ .bind = msm_drm_bind,
+ .unbind = msm_drm_unbind,
+};
+
/*
* Platform driver:
*/
static int msm_pdev_probe(struct platform_device *pdev)
{
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- return drm_platform_init(&msm_driver, pdev);
+ return component_master_add(&pdev->dev, &msm_drm_ops);
}
static int msm_pdev_remove(struct platform_device *pdev)
{
- drm_put_dev(platform_get_drvdata(pdev));
+ component_master_del(&pdev->dev, &msm_drm_ops);
return 0;
}
index 3d63269c5b29c51e69bc0dfe7714dddae71e4fee..9d10ee0b5aacf9d234de220e93a49fbea786a503 100644 (file)
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/module.h>
+#include <linux/component.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
struct msm_kms *kms;
+ /* subordinate devices, if present: */
+ struct platform_device *hdmi_pdev, *gpu_pdev;
+
/* when we have more than one 'msm_gpu' these need to be an array: */
struct msm_gpu *gpu;
struct msm_file_private *lastctx;
index 663394f0c166b82e06ded3b151f712363c7b084f..0db3e208f02ab2ab6bf3e86859e915852a7f1d9f 100644 (file)
misc |= ATOM_COMPOSITESYNC;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
misc |= ATOM_INTERLACE;
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
misc |= ATOM_DOUBLE_CLOCK_MODE;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
args.ucCRTC = radeon_crtc->crtc_id;
misc |= ATOM_COMPOSITESYNC;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
misc |= ATOM_INTERLACE;
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
misc |= ATOM_DOUBLE_CLOCK_MODE;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
args.ucCRTC = radeon_crtc->crtc_id;
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index e99e71a6ea59a44e5181b650aaa89156cdb193d2..356f22f90a05fad4cab48a8a4bd72f1e7bf03158 100644 (file)
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
GFP_KERNEL);
if (!open_info) {
err = -ENOMEM;
- goto error0;
+ goto error_gpadl;
}
init_completion(&open_info->waitevent);
if (userdatalen > MAX_USER_DEFINED_BYTES) {
err = -EINVAL;
- goto error0;
+ goto error_gpadl;
}
if (userdatalen)
list_del(&open_info->msglistentry);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+error_gpadl:
+ vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
+
error0:
free_pages((unsigned long)out,
get_order(send_ringbuffer_size + recv_ringbuffer_size));
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 5fb80b8962a2ad7d8e78dcee01df68cb639d3602..43fe15a0e5cc8486f544eadfa4b968c737a24e26 100644 (file)
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
adap->bus_recovery_info->set_scl(adap, 1);
return i2c_generic_recovery(adap);
}
+EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery);
int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
{
return ret;
}
+EXPORT_SYMBOL_GPL(i2c_generic_gpio_recovery);
int i2c_recover_bus(struct i2c_adapter *adap)
{
dev_dbg(&adap->dev, "Trying i2c bus recovery\n");
return adap->bus_recovery_info->recover_bus(adap);
}
+EXPORT_SYMBOL_GPL(i2c_recover_bus);
static int i2c_device_probe(struct device *dev)
{
index 055ebebc07ddb1ba19375aead10a7f138812c41d..c1fef27010d45203ef0f87334227ef7535b5d345 100644 (file)
if (dmasync)
dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
+ if (!size)
+ return ERR_PTR(-EINVAL);
+
/*
* If the combination of the addr and size requested for this memory
* region causes an integer overflow, return error.
*/
- if ((PAGE_ALIGN(addr + size) <= size) ||
- (PAGE_ALIGN(addr + size) <= addr))
+ if (((addr + size) < addr) ||
+ PAGE_ALIGN(addr + size) < (addr + size))
return ERR_PTR(-EINVAL);
if (!can_do_mlock())
index d8f4d1fe849430ceb40eab47470d5af033884694..8d7cd98c9671a7567eb3921eb637ef746442e4df 100644 (file)
memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
- *lso_hdr_sz = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
- wr->wr.ud.hlen);
+ *lso_hdr_sz = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen);
*lso_seg_len = halign;
return 0;
}
index 0b75b5764f31514f2486d1398501eb10d4953be0..cfc5a2e6dcce185cd609b309c6f6003daf8ec402 100644 (file)
return PSMOUSE_FULL_PACKET;
}
+/*
+ * This writes the reg_07 value again to the hardware at the end of every
+ * set_rate call because the register loses its value. reg_07 allows setting
+ * absolute mode on v4 hardware
+ */
+static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse,
+ unsigned int rate)
+{
+ struct elantech_data *etd = psmouse->private;
+
+ etd->original_set_rate(psmouse, rate);
+ if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+ psmouse_err(psmouse, "restoring reg_07 failed\n");
+}
+
/*
* Put the touchpad into absolute mode
*/
* Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons
* Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons
* Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons
+ * Asus TP500LN 0x381f17 10, 14, 0e clickpad
+ * Asus X750JN 0x381f17 10, 14, 0e clickpad
* Asus UX31 0x361f00 20, 15, 0e clickpad
* Asus UX32VD 0x361f02 00, 15, 0e clickpad
* Avatar AVIU-145A2 0x361f00 ? clickpad
goto init_fail;
}
+ if (etd->fw_version == 0x381f17) {
+ etd->original_set_rate = psmouse->set_rate;
+ psmouse->set_rate = elantech_set_rate_restore_reg_07;
+ }
+
if (elantech_set_input_params(psmouse)) {
psmouse_err(psmouse, "failed to query touchpad range.\n");
goto init_fail;
index 9e0e2a1f340d52817fc18bf79d849bed6d340932..59263a3a86674cdc7a2db74c56736f37defd2c1d 100644 (file)
struct finger_pos mt[ETP_MAX_FINGERS];
unsigned char parity[256];
int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param);
+ void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate);
};
#ifdef CONFIG_MOUSE_PS2_ELANTECH
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 4a8d19d0a5a4ab34a241ca912ec0951246b6941a..5a4cda24e30242a23eb5b2ba0ce3fa246d7d319b 100644 (file)
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
switch (r) {
/* async */
+ case -EINPROGRESS:
case -EBUSY:
wait_for_completion(&ctx->restart);
reinit_completion(&ctx->restart);
- /* fall through*/
- case -EINPROGRESS:
ctx->req = NULL;
ctx->cc_sector++;
continue;
struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx);
struct crypt_config *cc = io->cc;
- if (error == -EINPROGRESS) {
- complete(&ctx->restart);
+ if (error == -EINPROGRESS)
return;
- }
if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
if (!atomic_dec_and_test(&ctx->cc_pending))
- return;
+ goto done;
if (bio_data_dir(io->base_bio) == READ)
kcryptd_crypt_read_done(io);
else
kcryptd_crypt_write_io_submit(io, 1);
+done:
+ if (!completion_done(&ctx->restart))
+ complete(&ctx->restart);
}
static void kcryptd_crypt(struct work_struct *work)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 407a99e46f6993a770c21fdfff1972b7f64063b6..683e685ed6973f06d091cd47932a4c8161bc4de8 100644 (file)
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
/*
* remaps the bio to the target device. we separate two flows.
- * power 2 flow and a general flow for the sake of perfromance
+ * power 2 flow and a general flow for the sake of performance
*/
static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
sector_t sector, sector_t *sector_offset)
split = bio;
}
+ sector = bio->bi_iter.bi_sector;
zone = find_zone(mddev->private, §or);
tmp_dev = map_sector(mddev, zone, sector, §or);
split->bi_bdev = tmp_dev->bdev;
index 37bc00f418f1db47272238d90830ed2a7ac1f872..7596537becf770656db11ce1612080089d38ccc8 100644 (file)
if (mutex_lock_interruptible(&dev->v4l_lock))
return -ERESTARTSYS;
+ /*
+ * Once URBs are cancelled, the URB complete handler
+ * won't be running. This is required to safely release the
+ * current buffer (dev->isoc_ctl.buf).
+ */
stk1160_cancel_isoc(dev);
/*
stk1160_info("buffer [%p/%d] aborted\n",
buf, buf->vb.v4l2_buf.index);
}
- /* It's important to clear current buffer */
- dev->isoc_ctl.buf = NULL;
+
+ /* It's important to release the current buffer */
+ if (dev->isoc_ctl.buf) {
+ buf = dev->isoc_ctl.buf;
+ dev->isoc_ctl.buf = NULL;
+
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ stk1160_info("buffer [%p/%d] aborted\n",
+ buf, buf->vb.v4l2_buf.index);
+ }
spin_unlock_irqrestore(&dev->buf_lock, flags);
}
index fc145d202c46907cf1ed40572068fcf3d21441c1..922a750640e8684f9ddda9ca7a20bec44832b5b3 100644 (file)
if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
if (msb->data_dir == READ) {
- for (cnt = 0; cnt < msb->current_seg; cnt++)
+ for (cnt = 0; cnt < msb->current_seg; cnt++) {
t_len += msb->req_sg[cnt].length
/ msb->page_size;
t_len += msb->current_page - 1;
t_len *= msb->page_size;
+ }
}
} else
t_len = blk_rq_bytes(msb->block_req);
index 6f27d9a1be3b7ff3294e0549bc7fef308a9a1b85..21841fe25ad381fbcca4e56df31046f749a715d3 100644 (file)
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
second_is_newer = !second_is_newer;
} else {
dbg_bld("PEB %d CRC is OK", pnum);
- bitflips = !!err;
+ bitflips |= !!err;
}
mutex_unlock(&ubi->buf_mutex);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 8ca49f2043e4b8a7fe41109129de5760995b59d4..4cbbd55311336f544b49be4ce4b08d5d525b4afb 100644 (file)
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
/* Validate the request */
err = -EINVAL;
if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
- req.bytes < 0 || req.lnum >= vol->usable_leb_size)
+ req.bytes < 0 || req.bytes > vol->usable_leb_size)
break;
err = get_exclusive(desc);
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 0e11671dadc48c129c3f9cd669c8cf7c9ec5bf70..930cf2c77abb14a386610a56de9c7eabed6b9598 100644 (file)
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
* during re-size.
*/
ubi_move_aeb_to_list(av, aeb, &ai->erase);
- vol->eba_tbl[aeb->lnum] = aeb->pnum;
+ else
+ vol->eba_tbl[aeb->lnum] = aeb->pnum;
}
}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 68b924ec222e0f7fef1e868b6e0381582df4aee3..c6b0b078ab99364c01c8e41af28ea784f74ead8c 100644 (file)
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
int cancel)
{
int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
- int vol_id = -1, uninitialized_var(lnum);
+ int vol_id = -1, lnum = -1;
#ifdef CONFIG_MTD_UBI_FASTMAP
int anchor = wrk->anchor;
#endif
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 46e6544ed1b7f5c1ba9367dd1dfe444d725cd0e3..b655fe4f4c2e7e0d19beb8d4479ab698853515bb 100644 (file)
static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
+static void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
+{
+}
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int cleaned_count);
msleep(1);
/* e1000_down has a dependency on max_frame_size */
hw->max_frame_size = max_frame;
- if (netif_running(netdev))
+ if (netif_running(netdev)) {
+ /* prevent buffers from being reallocated */
+ adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers;
e1000_down(adapter);
+ }
/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index f583167691595f14f82f707da0359958a335668d..66c92a16da2939d869fd3758ffc933612d06e31d 100644 (file)
{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
{RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
+ {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
{RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
{RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
{RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
{RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
{RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
{RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+ {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */
{RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
{RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/
{RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/
index 7f1669cdea090ed6895b8eaabf0ab7f74054d9c4..779dc2b2ca7591077e18494a4eaa3c82ed8f846d 100644 (file)
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u");
WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u");
-WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(rx_rate, rx_frames_per_rates, 50);
WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate,
AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE);
index f7381dd69009a150e1901a876494d225e0267f5e..1bce4325e86bba78bc808fb95eea3738bb9a6663 100644 (file)
#include "wlcore.h"
-int wl1271_format_buffer(char __user *userbuf, size_t count,
- loff_t *ppos, char *fmt, ...);
+__printf(4, 5) int wl1271_format_buffer(char __user *userbuf, size_t count,
+ loff_t *ppos, char *fmt, ...);
int wl1271_debugfs_init(struct wl1271 *wl);
void wl1271_debugfs_exit(struct wl1271 *wl);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 16078a3129bff3b56ac3ac423e7f39fcd7f9d47b..78a58232b6c130169cb6d6cf7666c0da0b0ae547 100644 (file)
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
* of_device_make_bus_id - Use the device node data to assign a unique name
* @dev: pointer to device structure that is linked to a device tree node
*
- * This routine will first try using either the dcr-reg or the reg property
- * value to derive a unique name. As a last resort it will use the node
- * name followed by a unique number.
+ * This routine will first try using the translated bus address to
+ * derive a unique name. If it cannot, then it will prepend names from
+ * parent nodes until a unique name can be derived.
*/
void of_device_make_bus_id(struct device *dev)
{
- static atomic_t bus_no_reg_magic;
struct device_node *node = dev->of_node;
const __be32 *reg;
u64 addr;
- const __be32 *addrp;
- int magic;
#ifdef CONFIG_PPC_DCR
/*
}
#endif /* CONFIG_PPC_DCR */
- /*
- * For MMIO, get the physical address
- */
- reg = of_get_property(node, "reg", NULL);
- if (reg) {
- if (of_can_translate_address(node)) {
- addr = of_translate_address(node, reg);
- } else {
- addrp = of_get_address(node, 0, NULL, NULL);
- if (addrp)
- addr = of_read_number(addrp, 1);
- else
- addr = OF_BAD_ADDR;
- }
- if (addr != OF_BAD_ADDR) {
- dev_set_name(dev, "%llx.%s",
- (unsigned long long)addr, node->name);
+ /* Construct the name, using parent nodes if necessary to ensure uniqueness */
+ while (node->parent) {
+ /*
+ * If the address can be translated, then that is as much
+ * uniqueness as we need. Make it the first component and return
+ */
+ reg = of_get_property(node, "reg", NULL);
+ if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) {
+ dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s",
+ (unsigned long long)addr, node->name,
+ dev_name(dev));
return;
}
- }
- /*
- * No BusID, use the node name and add a globally incremented
- * counter (and pray...)
- */
- magic = atomic_add_return(1, &bus_no_reg_magic);
- dev_set_name(dev, "%s.%d", node->name, magic - 1);
+ /* format arguments only used if dev_name() resolves to NULL */
+ dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s",
+ strrchr(node->full_name, '/') + 1, dev_name(dev));
+ node = node->parent;
+ }
}
/**
index 5786792b9c8cd6cfd44749bbf55568f923604e9b..25c463946376b9b4dd38fc80c73279a35ab6f908 100644 (file)
static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
{
- struct usb_phy *phy = otg->phy;
-
otg->host = host;
if (!host)
- phy->state = OTG_STATE_UNDEFINED;
+ otg->state = OTG_STATE_UNDEFINED;
return 0;
}
static int omap_usb_set_peripheral(struct usb_otg *otg,
struct usb_gadget *gadget)
{
- struct usb_phy *phy = otg->phy;
-
otg->gadget = gadget;
if (!gadget)
- phy->state = OTG_STATE_UNDEFINED;
+ otg->state = OTG_STATE_UNDEFINED;
return 0;
}
index aaac3594f83bed78004e6b125eeb2010c9ea017d..0a5dc0d0242e7f724c98724c2664cb1dee0d79a1 100644 (file)
otg->gadget = gadget;
if (!gadget)
- otg->phy->state = OTG_STATE_UNDEFINED;
+ otg->state = OTG_STATE_UNDEFINED;
return 0;
}
otg->host = host;
if (!host)
- otg->phy->state = OTG_STATE_UNDEFINED;
+ otg->state = OTG_STATE_UNDEFINED;
return 0;
}
index 7297df2ebf503771d080a3467869819d72921b08..2d9d1985adc1ce89fb6f4c3e56559e8e419df25d 100644 (file)
/* Power supply */
initialize_power_supply_data(data);
- power_supply_register(&compal_device->dev, &data->psy);
+ err = power_supply_register(&compal_device->dev, &data->psy);
+ if (err < 0)
+ goto remove;
platform_set_drvdata(pdev, data);
index ed49b50b220b3ed6541c5b6f82079e1d0373e8f7..72da2a6c22db953b1c9c95a84fc27a9007580891 100644 (file)
pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop);
pchg->battery.get_property = lp8788_battery_get_property;
- if (power_supply_register(&pdev->dev, &pchg->battery))
+ if (power_supply_register(&pdev->dev, &pchg->battery)) {
+ power_supply_unregister(&pchg->charger);
return -EPERM;
+ }
return 0;
}
index 7ef445a6cfa6d824f297c39ad0b93555126fd82e..cf907609ec49eea0ddff12a23e44afe05b02434c 100644 (file)
{
struct twl4030_madc_battery *twl4030_madc_bat;
struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data;
+ int ret = 0;
twl4030_madc_bat = kzalloc(sizeof(*twl4030_madc_bat), GFP_KERNEL);
if (!twl4030_madc_bat)
twl4030_madc_bat->pdata = pdata;
platform_set_drvdata(pdev, twl4030_madc_bat);
- power_supply_register(&pdev->dev, &twl4030_madc_bat->psy);
+ ret = power_supply_register(&pdev->dev, &twl4030_madc_bat->psy);
+ if (ret < 0)
+ kfree(twl4030_madc_bat);
- return 0;
+ return ret;
}
static int twl4030_madc_battery_remove(struct platform_device *pdev)
index 65180e15de6ebfb6797cff83cab776a0e5e8e314..50c75e1fbf8a0e17e6b6bc4f8a5f1e7e725b7b7b 100644 (file)
while (!bfa_raw_sem_get(bar)) {
if (--n <= 0)
return BFA_STATUS_BADFLASH;
- udelay(10000);
+ mdelay(10);
}
return BFA_STATUS_OK;
}
index 6c1f223a8e1d335fa7c86a374e470e666e848906..4c0b8b4e1d407489afbff23876fecb40283c9e50 100644 (file)
static int mvs_task_prep_ata(struct mvs_info *mvi,
struct mvs_task_exec_info *tei)
{
- struct sas_ha_struct *sha = mvi->sas;
struct sas_task *task = tei->task;
struct domain_device *dev = task->dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_cmd_hdr *hdr = tei->hdr;
struct asd_sas_port *sas_port = dev->port;
- struct sas_phy *sphy = dev->phy;
- struct asd_sas_phy *sas_phy = sha->sas_phy[sphy->number];
struct mvs_slot_info *slot;
void *buf_prd;
u32 tag = tei->tag, hdr_tag;
slot->tx = mvi->tx_prod;
del_q = TXQ_MODE_I | tag |
(TXQ_CMD_STP << TXQ_CMD_SHIFT) |
- (MVS_PHY_ID << TXQ_PHY_SHIFT) |
+ ((sas_port->phy_mask & TXQ_PHY_MASK) << TXQ_PHY_SHIFT) |
(mvi_dev->taskfileset << TXQ_SRS_SHIFT);
mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q);
index 86b05151fdab3906353a3c55f54abdbe283b8c2d..97892f258043f4ba04998b1f4d6b72e36ffca239 100644 (file)
if (bounce_sgl[j].length == PAGE_SIZE) {
/* full..move to next entry */
sg_kunmap_atomic(bounce_addr);
+ bounce_addr = 0;
j++;
+ }
- /* if we need to use another bounce buffer */
- if (srclen || i != orig_sgl_count - 1)
- bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+ /* if we need to use another bounce buffer */
+ if (srclen && bounce_addr == 0)
+ bounce_addr = sg_kmap_atomic(bounce_sgl, j);
- } else if (srclen == 0 && i == orig_sgl_count - 1) {
- /* unmap the last bounce that is < PAGE_SIZE */
- sg_kunmap_atomic(bounce_addr);
- }
}
sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
}
+ if (bounce_addr)
+ sg_kunmap_atomic(bounce_addr);
+
local_irq_restore(flags);
return total_copied;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index d7c6e36021e884727f9bd0a7fc858d83824d441a..2fe5b61d886a71b792f4a74a12e3b7c0ab3e2a3b 100644 (file)
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
k_tmp->len = u_tmp->len;
total += k_tmp->len;
- if (total > bufsiz) {
+ /* Check total length of transfers. Also check each
+ * transfer length to avoid arithmetic overflow.
+ */
+ if (total > bufsiz || k_tmp->len > bufsiz) {
status = -EMSGSIZE;
goto done;
}
index 41eff7d64cb8878bd4a7a42acbf1a13c9f141b70..b199f1e21d0e67fbf7df63118843ea2c8e0dc396 100644 (file)
struct se_device *se_dev = cmd->se_dev;
struct fd_dev *dev = FD_DEV(se_dev);
struct file *prot_fd = dev->fd_prot_file;
- struct scatterlist *sg;
loff_t pos = (cmd->t_task_lba * se_dev->prot_length);
unsigned char *buf;
- u32 prot_size, len, size;
- int rc, ret = 1, i;
+ u32 prot_size;
+ int rc, ret = 1;
prot_size = (cmd->data_length / se_dev->dev_attrib.block_size) *
se_dev->prot_length;
if (!is_write) {
- fd_prot->prot_buf = vzalloc(prot_size);
+ fd_prot->prot_buf = kzalloc(prot_size, GFP_KERNEL);
if (!fd_prot->prot_buf) {
pr_err("Unable to allocate fd_prot->prot_buf\n");
return -ENOMEM;
}
buf = fd_prot->prot_buf;
- fd_prot->prot_sg_nents = cmd->t_prot_nents;
- fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist) *
- fd_prot->prot_sg_nents, GFP_KERNEL);
+ fd_prot->prot_sg_nents = 1;
+ fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist),
+ GFP_KERNEL);
if (!fd_prot->prot_sg) {
pr_err("Unable to allocate fd_prot->prot_sg\n");
- vfree(fd_prot->prot_buf);
+ kfree(fd_prot->prot_buf);
return -ENOMEM;
}
- size = prot_size;
-
- for_each_sg(fd_prot->prot_sg, sg, fd_prot->prot_sg_nents, i) {
-
- len = min_t(u32, PAGE_SIZE, size);
- sg_set_buf(sg, buf, len);
- size -= len;
- buf += len;
- }
+ sg_init_table(fd_prot->prot_sg, fd_prot->prot_sg_nents);
+ sg_set_buf(fd_prot->prot_sg, buf, prot_size);
}
if (is_write) {
if (is_write || ret < 0) {
kfree(fd_prot->prot_sg);
- vfree(fd_prot->prot_buf);
+ kfree(fd_prot->prot_buf);
}
return ret;
0, fd_prot.prot_sg, 0);
if (rc) {
kfree(fd_prot.prot_sg);
- vfree(fd_prot.prot_buf);
+ kfree(fd_prot.prot_buf);
return rc;
}
kfree(fd_prot.prot_sg);
- vfree(fd_prot.prot_buf);
+ kfree(fd_prot.prot_buf);
}
} else {
memset(&fd_prot, 0, sizeof(struct fd_prot));
0, fd_prot.prot_sg, 0);
if (rc) {
kfree(fd_prot.prot_sg);
- vfree(fd_prot.prot_buf);
+ kfree(fd_prot.prot_buf);
return rc;
}
}
if (ret < 0) {
kfree(fd_prot.prot_sg);
- vfree(fd_prot.prot_buf);
+ kfree(fd_prot.prot_buf);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
index 68511e83486b98cea87a2fbe8e21839495870b6d..f89b24a09b19b969e7f9b521fc5e52efdb821928 100644 (file)
@@ -314,7 +314,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
return 0;
}
-static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd)
+static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success)
{
unsigned char *buf, *addr;
struct scatterlist *sg;
cmd->data_direction);
}
-static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
+static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
{
struct se_device *dev = cmd->se_dev;
return TCM_NO_SENSE;
}
-static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
+static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success)
{
struct se_device *dev = cmd->se_dev;
struct scatterlist *write_sg = NULL, *sg;
/*
* Handle early failure in transport_generic_request_failure(),
- * which will not have taken ->caw_mutex yet..
+ * which will not have taken ->caw_sem yet..
*/
- if (!cmd->t_data_sg || !cmd->t_bidi_data_sg)
+ if (!success && (!cmd->t_data_sg || !cmd->t_bidi_data_sg))
return TCM_NO_SENSE;
+ /*
+ * Handle special case for zero-length COMPARE_AND_WRITE
+ */
+ if (!cmd->data_length)
+ goto out;
/*
* Immediately exit + release dev->caw_sem if command has already
* been failed with a non-zero SCSI status.
index 9e54c0fe718da9bfaf3152cab5f6e4ade58a93ab..6fc38903046c7ef42fa6cefc0bdbb24a1ac564d5 100644 (file)
transport_complete_task_attr(cmd);
/*
* Handle special case for COMPARE_AND_WRITE failure, where the
- * callback is expected to drop the per device ->caw_mutex.
+ * callback is expected to drop the per device ->caw_sem.
*/
if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
cmd->transport_complete_callback)
- cmd->transport_complete_callback(cmd);
+ cmd->transport_complete_callback(cmd, false);
switch (sense_reason) {
case TCM_NON_EXISTENT_LUN:
if (cmd->transport_complete_callback) {
sense_reason_t rc;
- rc = cmd->transport_complete_callback(cmd);
+ rc = cmd->transport_complete_callback(cmd, true);
if (!rc && !(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE_POST)) {
+ if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
+ !cmd->data_length)
+ goto queue_rsp;
+
return;
} else if (rc) {
ret = transport_send_check_condition_and_sense(cmd,
}
}
+queue_rsp:
switch (cmd->data_direction) {
case DMA_FROM_DEVICE:
spin_lock(&cmd->se_lun->lun_sep_lock);
static inline void transport_free_pages(struct se_cmd *cmd)
{
if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) {
+ /*
+ * Release special case READ buffer payload required for
+ * SG_TO_MEM_NOALLOC to function with COMPARE_AND_WRITE
+ */
+ if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) {
+ transport_free_sgl(cmd->t_bidi_data_sg,
+ cmd->t_bidi_data_nents);
+ cmd->t_bidi_data_sg = NULL;
+ cmd->t_bidi_data_nents = 0;
+ }
transport_reset_sgl_orig(cmd);
return;
}
transport_generic_new_cmd(struct se_cmd *cmd)
{
int ret = 0;
+ bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
/*
* Determine is the TCM fabric module has already allocated physical
*/
if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) &&
cmd->data_length) {
- bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
if ((cmd->se_cmd_flags & SCF_BIDI) ||
(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)) {
cmd->data_length, zero_flag);
if (ret < 0)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ } else if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
+ cmd->data_length) {
+ /*
+ * Special case for COMPARE_AND_WRITE with fabrics
+ * using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC.
+ */
+ u32 caw_length = cmd->t_task_nolb *
+ cmd->se_dev->dev_attrib.block_size;
+
+ ret = target_alloc_sgl(&cmd->t_bidi_data_sg,
+ &cmd->t_bidi_data_nents,
+ caw_length, zero_flag);
+ if (ret < 0)
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
/*
* If this command is not a write we can execute it right here,
index 231ddf10545664512513e71a91e7ccecc95b05d1..61e47e4399874cba505c1476d1521f5bc14cd0ce 100644 (file)
struct pm_qos_request pm_qos_request;
struct work_struct qos_work;
struct uart_8250_dma omap8250_dma;
+ spinlock_t rx_dma_lock;
};
static u32 uart_read(struct uart_8250_port *up, u32 reg)
static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
{
+ struct omap8250_priv *priv = p->port.private_data;
struct uart_8250_dma *dma = p->dma;
struct tty_port *tty_port = &p->port.state->port;
struct dma_tx_state state;
int count;
+ unsigned long flags;
dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
dma->rx_size, DMA_FROM_DEVICE);
+ spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
+ if (!dma->rx_running)
+ goto unlock;
+
dma->rx_running = 0;
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
dmaengine_terminate_all(dma->rxchan);
tty_insert_flip_string(tty_port, dma->rx_buf, count);
p->port.icount.rx += count;
+unlock:
+ spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+
if (!error)
omap_8250_rx_dma(p, 0);
__dma_rx_do_complete(param, false);
}
+static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
+{
+ struct omap8250_priv *priv = p->port.private_data;
+ struct uart_8250_dma *dma = p->dma;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
+ if (!dma->rx_running) {
+ spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+ return;
+ }
+
+ dmaengine_pause(dma->rxchan);
+
+ spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+
+ __dma_rx_do_complete(p, true);
+}
+
static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
{
+ struct omap8250_priv *priv = p->port.private_data;
struct uart_8250_dma *dma = p->dma;
+ int err = 0;
struct dma_async_tx_descriptor *desc;
+ unsigned long flags;
switch (iir & 0x3f) {
case UART_IIR_RLSI:
/* 8250_core handles errors and break interrupts */
- if (dma->rx_running) {
- dmaengine_pause(dma->rxchan);
- __dma_rx_do_complete(p, true);
- }
+ omap_8250_rx_dma_flush(p);
return -EIO;
case UART_IIR_RX_TIMEOUT:
/*
* If RCVR FIFO trigger level was not reached, complete the
* transfer and let 8250_core copy the remaining data.
*/
- if (dma->rx_running) {
- dmaengine_pause(dma->rxchan);
- __dma_rx_do_complete(p, true);
- }
+ omap_8250_rx_dma_flush(p);
return -ETIMEDOUT;
case UART_IIR_RDI:
/*
* the DMA won't do anything soon so we have to cancel the DMA
* transfer and purge the FIFO manually.
*/
- if (dma->rx_running) {
- dmaengine_pause(dma->rxchan);
- __dma_rx_do_complete(p, true);
- }
+ omap_8250_rx_dma_flush(p);
return -ETIMEDOUT;
default:
break;
}
+ spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
if (dma->rx_running)
- return 0;
+ goto out;
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
dma->rx_size, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EBUSY;
+ if (!desc) {
+ err = -EBUSY;
+ goto out;
+ }
dma->rx_running = 1;
desc->callback = __dma_rx_complete;
dma->rx_size, DMA_FROM_DEVICE);
dma_async_issue_pending(dma->rxchan);
- return 0;
+out:
+ spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+ return err;
}
static int omap_8250_tx_dma(struct uart_8250_port *p);
priv->latency);
INIT_WORK(&priv->qos_work, omap8250_uart_qos_work);
+ spin_lock_init(&priv->rx_dma_lock);
+
device_init_wakeup(&pdev->dev, true);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4d80716c600da679f52e9ee6d621d325782fc76c..1bc1e1b2ff46d027f9f97d64e1edeb09fbf422d1 100644 (file)
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
config USB_COMMON
tristate
default y
- depends on USB || USB_GADGET
-
-config DRD_LIB
- tristate "DRD Library support"
- default y
- depends on USB && USB_GADGET
- ---help---
- This option adds DRD Library support for Universal Serial Bus (USB).
- DRD Library faciliatets the Role switching by HOST and DEVICE roles,
- If your hardware has a Dual Role Device.
-
- The DRD Library uses USB core API's to start/stop HOST controllers,
- UDC API's to start/stop DEVICE controllers, ther by enabling to
- switch roles between HOST and Device modes.
-
- Say N if unsure.
+ depends on USB || USB_GADGET || USB_OTG
config USB_ARCH_HAS_HCD
def_bool y
source "drivers/usb/gadget/Kconfig"
+config USB_LED_TRIG
+ bool "USB LED Triggers"
+ depends on LEDS_CLASS && USB_COMMON && LEDS_TRIGGERS
+ help
+ This option adds LED triggers for USB host and/or gadget activity.
+
+ Say Y here if you are working on a system with led-class supported
+ LEDs and you want to use them as activity indicators for USB host or
+ gadget.
+
endif # USB_SUPPORT
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 932a61e30a6dd3c0f03e0ac85de898061ada52ef..de62c4e69a2b76ea7b0d8532bc08ee3bf88cdcdc 100644 (file)
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/
obj-$(CONFIG_USB_GADGET) += gadget/
-obj-$(CONFIG_USB_COMMON) += usb-common.o
-obj-$(CONFIG_DRD_LIB) += drd-lib.o
+obj-$(CONFIG_USB_COMMON) += common/
+obj-$(CONFIG_USB_OTG) += common/
index a8ac6c16dac92832f79cd4d978f5af85b70b94dd..6d216cb293dbdeb47ef31239da450ee1f0772c95 100644 (file)
hcd->has_tt = 1;
hcd->power_budget = ci->platdata->power_budget;
- hcd->phy = ci->transceiver;
+ hcd->usb_phy = ci->transceiver;
ehci = hcd_to_ehci(hcd);
ehci->caps = ci->hw_bank.cap;
index 86b1fd6737492dcd765bcdcee82400a336cec05d..014020710d43e23c342f3bdbf41d36e1c4d68e4d 100644 (file)
static int ci_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver);
-static int ci_udc_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver);
+static int ci_udc_stop(struct usb_gadget *gadget);
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
/**
* ci_udc_stop: unregister a gadget driver
*/
-static int ci_udc_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int ci_udc_stop(struct usb_gadget *gadget)
{
struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
unsigned long flags;
index a051a7a2b1bd534a93fd459da7c553e0a5af4dfa..a81f9dd7ee97db06a86c18b813defea0b207099c 100644 (file)
case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
dev_dbg(&desc->intf->dev,
"NOTIFY_RESPONSE_AVAILABLE received: index %d len %d",
- dr->wIndex, dr->wLength);
+ le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength));
break;
case USB_CDC_NOTIFY_NETWORK_CONNECTION:
clear_bit(WDM_POLL_RUNNING, &desc->flags);
dev_err(&desc->intf->dev,
"unknown notification %d received: index %d len %d\n",
- dr->bNotificationType, dr->wIndex, dr->wLength);
+ dr->bNotificationType,
+ le16_to_cpu(dr->wIndex),
+ le16_to_cpu(dr->wLength));
goto exit;
}
USB_RECIP_INTERFACE);
req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
req->wValue = 0;
- req->wIndex = desc->inum;
+ req->wIndex = desc->inum; /* already converted */
req->wLength = cpu_to_le16(count);
set_bit(WDM_IN_USE, &desc->flags);
desc->outbuf = buf;
rv = usb_translate_errors(rv);
} else {
dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
- req->wIndex);
+ le16_to_cpu(req->wIndex));
}
out:
usb_autopm_put_interface(desc->intf);
@@ -820,7 +822,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
desc->irq->wValue = 0;
- desc->irq->wIndex = desc->inum;
+ desc->irq->wIndex = desc->inum; /* already converted */
desc->irq->wLength = cpu_to_le16(desc->wMaxCommand);
usb_fill_control_urb(
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the usb common parts.
+#
+
+obj-$(CONFIG_USB_COMMON) += usb-common.o
+usb-common-y += common.o
+usb-common-$(CONFIG_USB_LED_TRIG) += led.o
+
+usbotg-y := usb-otg.o usb-otg-fsm.o
+obj-$(CONFIG_USB_OTG) += usbotg.o
similarity index 90%
rename from drivers/usb/usb-common.c
rename to drivers/usb/common/common.c
index d771870a819e52ff23220490c80de43697c508f2..d4c328e6b1c808ef16e62bede2f8970d11efa0b1 100644 (file)
rename from drivers/usb/usb-common.c
rename to drivers/usb/common/common.c
index d771870a819e52ff23220490c80de43697c508f2..d4c328e6b1c808ef16e62bede2f8970d11efa0b1 100644 (file)
--- a/drivers/usb/usb-common.c
}
EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed);
+/**
+ * of_usb_host_tpl_support - to get if Targeted Peripheral List is supported
+ * for given targeted hosts (non-PC hosts)
+ * @np: Pointer to the given device_node
+ *
+ * The function gets if the targeted hosts support TPL or not
+ */
+bool of_usb_host_tpl_support(struct device_node *np)
+{
+ if (of_find_property(np, "tpl-support", NULL))
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(of_usb_host_tpl_support);
#endif
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/common/led.c b/drivers/usb/common/led.c
--- /dev/null
+++ b/drivers/usb/common/led.c
@@ -0,0 +1,57 @@
+/*
+ * LED Triggers for USB Activity
+ *
+ * Copyright 2014 Michal Sojka <sojka@merica.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/usb.h>
+
+#define BLINK_DELAY 30
+
+static unsigned long usb_blink_delay = BLINK_DELAY;
+
+DEFINE_LED_TRIGGER(ledtrig_usb_gadget);
+DEFINE_LED_TRIGGER(ledtrig_usb_host);
+
+void usb_led_activity(enum usb_led_event ev)
+{
+ struct led_trigger *trig = NULL;
+
+ switch (ev) {
+ case USB_LED_EVENT_GADGET:
+ trig = ledtrig_usb_gadget;
+ break;
+ case USB_LED_EVENT_HOST:
+ trig = ledtrig_usb_host;
+ break;
+ }
+ /* led_trigger_blink_oneshot() handles trig == NULL gracefully */
+ led_trigger_blink_oneshot(trig, &usb_blink_delay, &usb_blink_delay, 0);
+}
+EXPORT_SYMBOL_GPL(usb_led_activity);
+
+
+static int __init ledtrig_usb_init(void)
+{
+ led_trigger_register_simple("usb-gadget", &ledtrig_usb_gadget);
+ led_trigger_register_simple("usb-host", &ledtrig_usb_host);
+ return 0;
+}
+
+static void __exit ledtrig_usb_exit(void)
+{
+ led_trigger_unregister_simple(ledtrig_usb_gadget);
+ led_trigger_unregister_simple(ledtrig_usb_host);
+}
+
+module_init(ledtrig_usb_init);
+module_exit(ledtrig_usb_exit);
similarity index 94%
rename from drivers/usb/phy/phy-fsm-usb.c
rename to drivers/usb/common/usb-otg-fsm.c
index 7aa314ef4a8ade13bac4ba73b41645d1b522dd84..c43ac377f0c949a6a5168b8e7bf3c31386a3a0da 100644 (file)
rename from drivers/usb/phy/phy-fsm-usb.c
rename to drivers/usb/common/usb-otg-fsm.c
index 7aa314ef4a8ade13bac4ba73b41645d1b522dd84..c43ac377f0c949a6a5168b8e7bf3c31386a3a0da 100644 (file)
#include <linux/usb/otg.h>
#include <linux/usb/otg-fsm.h>
+#undef VDBG
+
+#ifdef VERBOSE
+#define VDBG(fmt, args...) pr_debug("[%s] " fmt , \
+ __func__, ## args)
+#else
+#define VDBG(stuff...) do {} while (0)
+#endif
+
/* Change USB protocol when there is a protocol change */
static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
{
return 0;
}
-static int state_changed;
-
/* Called when leaving a state. Do state clean up jobs here */
static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
{
@@ -123,11 +130,11 @@ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
/* Called when entering a state */
static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
{
- state_changed = 1;
- if (fsm->otg->phy->state == new_state)
+ fsm->state_changed = 1;
+ if (fsm->otg->state == new_state)
return 0;
VDBG("Set state: %s\n", usb_otg_state_string(new_state));
- otg_leave_state(fsm, fsm->otg->phy->state);
+ otg_leave_state(fsm, fsm->otg->state);
switch (new_state) {
case OTG_STATE_B_IDLE:
otg_drv_vbus(fsm, 0);
otg_loc_conn(fsm, 0);
otg_loc_sof(fsm, 1);
otg_set_protocol(fsm, PROTO_HOST);
- usb_bus_start_enum(fsm->otg->host,
- fsm->otg->host->otg_port);
+ if (fsm->ops->start_enum) {
+ fsm->ops->start_enum(fsm->otg->host,
+ fsm->otg->host->otg_port);
+ }
break;
case OTG_STATE_A_IDLE:
otg_drv_vbus(fsm, 0);
break;
}
- fsm->otg->phy->state = new_state;
+ fsm->otg->state = new_state;
return 0;
}
mutex_lock(&fsm->lock);
- state = fsm->otg->phy->state;
- state_changed = 0;
+ state = fsm->otg->state;
+ fsm->state_changed = 0;
/* State machine state change judgement */
switch (state) {
}
mutex_unlock(&fsm->lock);
- VDBG("quit statemachine, changed = %d\n", state_changed);
- return state_changed;
+ VDBG("quit statemachine, changed = %d\n", fsm->state_changed);
+ return fsm->state_changed;
}
diff --git a/drivers/usb/common/usb-otg.c b/drivers/usb/common/usb-otg.c
--- /dev/null
@@ -0,0 +1,924 @@
+/**
+ * drivers/usb/common/usb-otg.c - USB OTG core
+ *
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Roger Quadros <rogerq@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/list.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/phy.h> /* enum usb_otg_state */
+#include <linux/usb/gadget.h>
+#include <linux/workqueue.h>
+
+#include "usb-otg.h"
+
+/* to link timer with callback data */
+struct otg_timer {
+ struct hrtimer timer;
+ ktime_t timeout;
+ /* callback data */
+ int *timeout_bit;
+ struct otg_data *otgd;
+};
+
+struct otg_hcd {
+ struct usb_hcd *hcd;
+ unsigned int irqnum;
+ unsigned long irqflags;
+ struct otg_hcd_ops *ops;
+};
+
+struct otg_data {
+ struct device *dev; /* HCD & GCD's parent device */
+
+ bool drd_only; /* Dual-role only, no OTG features */
+ struct otg_fsm fsm;
+ /* HCD, GCD and usb_otg_state are present in otg_fsm->otg
+ * HCD is bus_to_hcd(fsm->otg->host)
+ * GCD is fsm->otg->gadget
+ */
+ struct otg_fsm_ops fsm_ops; /* private copy for override */
+ struct usb_otg otg; /* allocator for fsm->otg */
+
+ struct otg_hcd primary_hcd;
+ struct otg_hcd shared_hcd;
+
+ struct otg_gadget_ops *gadget_ops; /* interface to gadget f/w */
+
+ /* saved hooks to OTG device */
+ int (*start_host)(struct otg_fsm *fsm, int on);
+ int (*start_gadget)(struct otg_fsm *fsm, int on);
+
+ struct list_head list;
+
+ struct work_struct work; /* OTG FSM work */
+ struct workqueue_struct *wq;
+
+ struct otg_timer timers[NUM_OTG_FSM_TIMERS];
+
+ bool fsm_running;
+ /* use otg->fsm.lock for serializing access */
+};
+
+/* OTG device list */
+static LIST_HEAD(otg_list);
+static DEFINE_MUTEX(otg_list_mutex);
+
+static int usb_otg_hcd_is_primary_hcd(struct usb_hcd *hcd)
+{
+ if (!hcd->primary_hcd)
+ return 1;
+ return hcd == hcd->primary_hcd;
+}
+
+/**
+ * check if device is in our OTG list and return
+ * otg_data, else NULL.
+ *
+ * otg_list_mutex must be held.
+ */
+static struct otg_data *usb_otg_device_get_otgd(struct device *parent_dev)
+{
+ struct otg_data *otgd;
+
+ list_for_each_entry(otgd, &otg_list, list) {
+ if (otgd->dev == parent_dev)
+ return otgd;
+ }
+
+ return NULL;
+}
+
+/**
+ * timer callback to set timeout bit and kick FSM
+ */
+static enum hrtimer_restart set_tmout(struct hrtimer *data)
+{
+ struct otg_timer *otgtimer;
+
+ otgtimer = container_of(data, struct otg_timer, timer);
+ if (otgtimer->timeout_bit)
+ *otgtimer->timeout_bit = 1;
+
+ usb_otg_sync_inputs(&otgtimer->otgd->fsm);
+
+ return HRTIMER_NORESTART;
+}
+
+/**
+ * Initialize one OTG timer with callback, timeout and timeout bit
+ */
+static void otg_timer_init(enum otg_fsm_timer id, struct otg_data *otgd,
+ enum hrtimer_restart (*callback)(struct hrtimer *),
+ unsigned long expires_ms,
+ int *timeout_bit)
+{
+ struct otg_timer *otgtimer = &otgd->timers[id];
+ struct hrtimer *timer = &otgtimer->timer;
+
+ otgtimer->timeout = ms_to_ktime(expires_ms);
+ hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ timer->function = callback;
+
+ otgtimer->timeout_bit = timeout_bit;
+ otgtimer->otgd = otgd;
+}
+
+/**
+ * Initialize standard OTG timers
+ */
+static void usb_otg_init_timers(struct otg_data *otgd)
+{
+ struct otg_fsm *fsm = &otgd->fsm;
+
+ otg_timer_init(A_WAIT_VRISE, otgd, set_tmout, TA_WAIT_VRISE, &fsm->a_wait_vrise_tmout);
+ otg_timer_init(A_WAIT_VFALL, otgd, set_tmout, TA_WAIT_VFALL, &fsm->a_wait_vfall_tmout);
+ otg_timer_init(A_WAIT_BCON, otgd, set_tmout, TA_WAIT_BCON, &fsm->a_wait_bcon_tmout);
+ otg_timer_init(A_AIDL_BDIS, otgd, set_tmout, TA_AIDL_BDIS, &fsm->a_aidl_bdis_tmout);
+ otg_timer_init(A_BIDL_ADIS, otgd, set_tmout, TA_BIDL_ADIS, &fsm->a_bidl_adis_tmout);
+ otg_timer_init(B_ASE0_BRST, otgd, set_tmout, TB_ASE0_BRST, &fsm->b_ase0_brst_tmout);
+
+ otg_timer_init(B_SE0_SRP, otgd, set_tmout, TB_SE0_SRP, &fsm->b_se0_srp);
+ otg_timer_init(B_SRP_FAIL, otgd, set_tmout, TB_SRP_FAIL, &fsm->b_srp_done);
+
+ otg_timer_init(A_WAIT_ENUM, otgd, set_tmout, TB_SRP_FAIL, NULL);
+}
+
+/**
+ * OTG FSM ops function to add timer
+ */
+static void usb_otg_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer id)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+ struct otg_timer *otgtimer = &otgd->timers[id];
+ struct hrtimer *timer = &otgtimer->timer;
+
+ if (!otgd->fsm_running)
+ return;
+
+ /* if timer is already active, exit */
+ if (hrtimer_active(timer)) {
+ dev_err(otgd->dev, "otg: timer %d is already running\n", id);
+ return;
+ }
+
+ hrtimer_start(timer, otgtimer->timeout, HRTIMER_MODE_REL);
+}
+
+/**
+ * OTG FSM ops function to delete timer
+ */
+static void usb_otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer id)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+ struct hrtimer *timer = &otgd->timers[id].timer;
+
+ hrtimer_cancel(timer);
+}
+
+/**
+ * OTG FSM ops function to start/stop host
+ */
+static int usb_otg_start_host(struct otg_fsm *fsm, int on)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+ struct otg_hcd_ops *hcd_ops;
+
+ dev_dbg(otgd->dev, "otg: %s %d\n", __func__, on);
+ if (!fsm->otg->host) {
+ WARN_ONCE(1, "otg: fsm running without host\n");
+ return 0;
+ }
+
+ if (on) {
+ /* OTG device operations */
+ if (otgd->start_host)
+ otgd->start_host(fsm, on);
+
+ /* start host */
+ hcd_ops = otgd->primary_hcd.ops;
+ hcd_ops->add(otgd->primary_hcd.hcd, otgd->primary_hcd.irqnum,
+ otgd->primary_hcd.irqflags);
+ if (otgd->shared_hcd.hcd) {
+ hcd_ops = otgd->shared_hcd.ops;
+ hcd_ops->add(otgd->shared_hcd.hcd,
+ otgd->shared_hcd.irqnum,
+ otgd->shared_hcd.irqflags);
+ }
+ } else {
+ /* stop host */
+ if (otgd->shared_hcd.hcd) {
+ hcd_ops = otgd->shared_hcd.ops;
+ hcd_ops->remove(otgd->shared_hcd.hcd);
+ }
+ hcd_ops = otgd->primary_hcd.ops;
+ hcd_ops->remove(otgd->primary_hcd.hcd);
+
+ /* OTG device operations */
+ if (otgd->start_host)
+ otgd->start_host(fsm, on);
+ }
+
+ return 0;
+}
+
+/**
+ * OTG FSM ops function to start/stop gadget
+ */
+static int usb_otg_start_gadget(struct otg_fsm *fsm, int on)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+ struct usb_gadget *gadget = fsm->otg->gadget;
+
+ dev_dbg(otgd->dev, "otg: %s %d\n", __func__, on);
+ if (!gadget) {
+ WARN_ONCE(1, "otg: fsm running without gadget\n");
+ return 0;
+ }
+
+ if (on) {
+ /* OTG device operations */
+ if (otgd->start_gadget)
+ otgd->start_gadget(fsm, on);
+
+ otgd->gadget_ops->start(fsm->otg->gadget);
+ } else {
+ otgd->gadget_ops->stop(fsm->otg->gadget);
+
+ /* OTG device operations */
+ if (otgd->start_gadget)
+ otgd->start_gadget(fsm, on);
+
+ }
+
+ return 0;
+}
+
+/* Change USB protocol when there is a protocol change */
+static int drd_set_protocol(struct otg_fsm *fsm, int protocol)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+ int ret = 0;
+
+ if (fsm->protocol != protocol) {
+ dev_dbg(otgd->dev, "otg: changing role fsm->protocol= %d; new protocol= %d\n",
+ fsm->protocol, protocol);
+ /* stop old protocol */
+ if (fsm->protocol == PROTO_HOST)
+ ret = otg_start_host(fsm, 0);
+ else if (fsm->protocol == PROTO_GADGET)
+ ret = otg_start_gadget(fsm, 0);
+ if (ret)
+ return ret;
+
+ /* start new protocol */
+ if (protocol == PROTO_HOST)
+ ret = otg_start_host(fsm, 1);
+ else if (protocol == PROTO_GADGET)
+ ret = otg_start_gadget(fsm, 1);
+ if (ret)
+ return ret;
+
+ fsm->protocol = protocol;
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Called when entering a DRD state */
+static void drd_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+
+ if (fsm->otg->state == new_state)
+ return;
+
+ fsm->state_changed = 1;
+ dev_dbg(otgd->dev, "otg: set state: %s\n",
+ usb_otg_state_string(new_state));
+ switch (new_state) {
+ case OTG_STATE_B_IDLE:
+ drd_set_protocol(fsm, PROTO_UNDEF);
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ drd_set_protocol(fsm, PROTO_GADGET);
+ break;
+ case OTG_STATE_A_HOST:
+ drd_set_protocol(fsm, PROTO_HOST);
+ break;
+ case OTG_STATE_UNDEFINED:
+ case OTG_STATE_B_SRP_INIT:
+ case OTG_STATE_B_WAIT_ACON:
+ case OTG_STATE_B_HOST:
+ case OTG_STATE_A_IDLE:
+ case OTG_STATE_A_WAIT_VRISE:
+ case OTG_STATE_A_WAIT_BCON:
+ case OTG_STATE_A_SUSPEND:
+ case OTG_STATE_A_PERIPHERAL:
+ case OTG_STATE_A_WAIT_VFALL:
+ case OTG_STATE_A_VBUS_ERR:
+ default:
+ dev_warn(otgd->dev, "%s: otg: invalid state: %s\n",
+ __func__, usb_otg_state_string(new_state));
+ break;
+ }
+
+ fsm->otg->state = new_state;
+}
+
+/**
+ * DRD state change judgement
+ *
+ * For DRD we're only interested in some of the OTG states
+ * i.e. OTG_STATE_B_IDLE: both peripheral and host are stopped
+ * OTG_STATE_B_PERIPHERAL: peripheral active
+ * OTG_STATE_A_HOST: host active
+ * we're only interested in the following inputs
+ * fsm->id, fsm->vbus
+ */
+static int drd_statemachine(struct otg_fsm *fsm)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+ enum usb_otg_state state;
+
+ mutex_lock(&fsm->lock);
+
+ state = fsm->otg->state;
+
+ switch (state) {
+ case OTG_STATE_UNDEFINED:
+ if (!fsm->id)
+ drd_set_state(fsm, OTG_STATE_A_HOST);
+ else if (fsm->id && fsm->vbus)
+ drd_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+ else
+ drd_set_state(fsm, OTG_STATE_B_IDLE);
+ break;
+ case OTG_STATE_B_IDLE:
+ if (!fsm->id)
+ drd_set_state(fsm, OTG_STATE_A_HOST);
+ else if (fsm->vbus)
+ drd_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ if (!fsm->id)
+ drd_set_state(fsm, OTG_STATE_A_HOST);
+ else if (!fsm->vbus)
+ drd_set_state(fsm, OTG_STATE_B_IDLE);
+ break;
+ case OTG_STATE_A_HOST:
+ if (fsm->id && fsm->vbus)
+ drd_set_state(fsm, OTG_STATE_B_PERIPHERAL);
+ else if (fsm->id && !fsm->vbus)
+ drd_set_state(fsm, OTG_STATE_B_IDLE);
+ break;
+
+ /* invalid states for DRD */
+ case OTG_STATE_B_SRP_INIT:
+ case OTG_STATE_B_WAIT_ACON:
+ case OTG_STATE_B_HOST:
+ case OTG_STATE_A_IDLE:
+ case OTG_STATE_A_WAIT_VRISE:
+ case OTG_STATE_A_WAIT_BCON:
+ case OTG_STATE_A_SUSPEND:
+ case OTG_STATE_A_PERIPHERAL:
+ case OTG_STATE_A_WAIT_VFALL:
+ case OTG_STATE_A_VBUS_ERR:
+ dev_err(otgd->dev, "%s: otg: invalid usb-drd state: %s\n",
+ __func__, usb_otg_state_string(state));
+ drd_set_state(fsm, OTG_STATE_UNDEFINED);
+ break;
+ }
+
+ mutex_unlock(&fsm->lock);
+ dev_dbg(otgd->dev, "otg: quit statemachine, changed %d\n",
+ fsm->state_changed);
+
+ return fsm->state_changed;
+}
+
+/**
+ * OTG FSM/DRD work function
+ */
+static void usb_otg_work(struct work_struct *work)
+{
+ struct otg_data *otgd = container_of(work, struct otg_data, work);
+
+ /* OTG state machine */
+ if (!otgd->drd_only) {
+ otg_statemachine(&otgd->fsm);
+ return;
+ }
+
+ /* DRD state machine */
+ drd_statemachine(&otgd->fsm);
+}
+
+/**
+ * usb_otg_register() - Register the OTG device to OTG core
+ * @parent_device: parent device of Host & Gadget controllers.
+ * @otg_fsm_ops: otg state machine ops.
+ * @drd_only: dual-role only. no OTG features.
+ *
+ * Register parent device that contains both HCD and GCD into
+ * the USB OTG core. HCD and GCD will be prevented from starting
+ * till both are available for use.
+ *
+ * Return: struct otg_fsm * if success, NULL if error.
+ */
+struct otg_fsm *usb_otg_register(struct device *parent_dev,
+ struct otg_fsm_ops *fsm_ops,
+ bool drd_only)
+{
+ struct otg_data *otgd;
+ int ret = 0;
+
+ if (!parent_dev || !fsm_ops)
+ return ERR_PTR(-EINVAL);
+
+ /* already in list? */
+ mutex_lock(&otg_list_mutex);
+ if (usb_otg_device_get_otgd(parent_dev)) {
+ dev_err(parent_dev, "otg: %s: device already in otg list\n",
+ __func__);
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ /* allocate and add to list */
+ otgd = kzalloc(sizeof(*otgd), GFP_KERNEL);
+ if (!otgd) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ otgd->dev = parent_dev;
+ INIT_WORK(&otgd->work, usb_otg_work);
+ otgd->wq = create_singlethread_workqueue("usb_otg");
+ if (!otgd->wq) {
+ dev_err(parent_dev, "otg: %s: can't create workqueue\n",
+ __func__);
+ ret = -ENODEV;
+ goto err_wq;
+ }
+
+ otgd->drd_only = drd_only;
+ /* For DRD mode we don't need OTG timers */
+ if (!drd_only) {
+ usb_otg_init_timers(otgd);
+
+ /* FIXME: we ignore caller's timer ops */
+ otgd->fsm_ops.add_timer = usb_otg_add_timer;
+ otgd->fsm_ops.del_timer = usb_otg_del_timer;
+ }
+
+ /* save original start host/gadget ops */
+ otgd->start_host = fsm_ops->start_host;
+ otgd->start_gadget = fsm_ops->start_gadget;
+ /* create copy of original ops */
+ otgd->fsm_ops = *fsm_ops;
+ /* override ops */
+ otgd->fsm_ops.start_host = usb_otg_start_host;
+ otgd->fsm_ops.start_gadget = usb_otg_start_gadget;
+ /* set otg ops */
+ otgd->fsm.ops = &otgd->fsm_ops;
+ otgd->fsm.otg = &otgd->otg;
+
+ mutex_init(&otgd->fsm.lock);
+
+ list_add_tail(&otgd->list, &otg_list);
+ mutex_unlock(&otg_list_mutex);
+ return &otgd->fsm;
+
+err_wq:
+ kfree(otgd);
+unlock:
+ mutex_unlock(&otg_list_mutex);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(usb_otg_register);
+
+/**
+ * usb_otg_unregister() - Unregister the OTG device from USB OTG core
+ * @parent_device: parent device of Host & Gadget controllers.
+ *
+ * Unregister parent OTG deviced from USB OTG core.
+ * Prevents unregistering till both Host and Gadget controllers
+ * have unregistered from the OTG core.
+ *
+ * Return: 0 on success, error value otherwise.
+ */
+int usb_otg_unregister(struct device *parent_dev)
+{
+ struct otg_data *otgd;
+
+ mutex_lock(&otg_list_mutex);
+ otgd = usb_otg_device_get_otgd(parent_dev);
+ if (!otgd) {
+ dev_err(parent_dev, "otg: %s: device not in otg list\n",
+ __func__);
+ mutex_unlock(&otg_list_mutex);
+ return -EINVAL;
+ }
+
+ /* prevent unregister till both host & gadget have unregistered */
+ if (otgd->fsm.otg->host || otgd->fsm.otg->gadget) {
+ dev_err(parent_dev, "otg: %s: host/gadget still registered\n",
+ __func__);
+ return -EBUSY;
+ }
+
+ /* OTG FSM is halted when host/gadget unregistered */
+ destroy_workqueue(otgd->wq);
+
+ /* remove from otg list */
+ list_del(&otgd->list);
+ kfree(otgd);
+ mutex_unlock(&otg_list_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_unregister);
+
+/**
+ * start/kick the OTG FSM if we can
+ * fsm->lock must be held
+ */
+static void usb_otg_start_fsm(struct otg_fsm *fsm)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+
+ if (otgd->fsm_running)
+ goto kick_fsm;
+
+ if (!fsm->otg->host) {
+ dev_info(otgd->dev, "otg: can't start till host registers\n");
+ return;
+ }
+
+ if (!fsm->otg->gadget) {
+ dev_info(otgd->dev, "otg: can't start till gadget registers\n");
+ return;
+ }
+
+ otgd->fsm_running = true;
+kick_fsm:
+ queue_work(otgd->wq, &otgd->work);
+}
+
+/**
+ * stop the OTG FSM. Stops Host & Gadget controllers as well.
+ * fsm->lock must be held
+ */
+static void usb_otg_stop_fsm(struct otg_fsm *fsm)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+ int i;
+
+ if (!otgd->fsm_running)
+ return;
+
+ /* no more new events queued */
+ otgd->fsm_running = false;
+
+ /* Stop state machine / timers */
+ if (!otgd->drd_only) {
+ for (i = 0; i < ARRAY_SIZE(otgd->timers); i++)
+ hrtimer_cancel(&otgd->timers[i].timer);
+ }
+
+ flush_workqueue(otgd->wq);
+ fsm->otg->state = OTG_STATE_UNDEFINED;
+
+ /* stop host/gadget immediately */
+ if (fsm->protocol == PROTO_HOST)
+ otg_start_host(fsm, 0);
+ else if (fsm->protocol == PROTO_GADGET)
+ otg_start_gadget(fsm, 0);
+ fsm->protocol = PROTO_UNDEF;
+}
+
+/**
+ * usb_otg_sync_inputs - Sync OTG inputs with the OTG state machine
+ * @fsm: OTG FSM instance
+ *
+ * Used by the OTG driver to update the inputs to the OTG
+ * state machine.
+ *
+ * Can be called in IRQ context.
+ */
+void usb_otg_sync_inputs(struct otg_fsm *fsm)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+
+ /* Don't kick FSM till it has started */
+ if (!otgd->fsm_running)
+ return;
+
+ /* Kick FSM */
+ queue_work(otgd->wq, &otgd->work);
+}
+EXPORT_SYMBOL_GPL(usb_otg_sync_inputs);
+
+/**
+ * usb_otg_kick_fsm - Kick the OTG state machine
+ * @hcd_gcd_device: Host/Gadget controller device
+ *
+ * Used by USB host/device stack to sync OTG related
+ * events to the OTG state machine.
+ * e.g. change in host_bus->b_hnp_enable, gadget->b_hnp_enable
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_kick_fsm(struct device *hcd_gcd_device)
+{
+ struct otg_data *otgd;
+
+ mutex_lock(&otg_list_mutex);
+ otgd = usb_otg_device_get_otgd(hcd_gcd_device->parent);
+ if (!otgd) {
+ dev_err(hcd_gcd_device, "otg: %s: invalid host/gadget device\n",
+ __func__);
+ mutex_unlock(&otg_list_mutex);
+ return -ENODEV;
+ }
+
+ mutex_unlock(&otg_list_mutex);
+ usb_otg_sync_inputs(&otgd->fsm);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_kick_fsm);
+
+/**
+ * usb_otg_register_hcd - Register Host controller to OTG core
+ * @hcd: Host controller device
+ * @irqnum: interrupt number
+ * @irqflags: interrupt flags
+ * @ops: HCD ops to add/remove the HCD
+ *
+ * This is used by the USB Host stack to register the Host controller
+ * to the OTG core. Host controller must not be started by the
+ * caller as it is left upto the OTG state machine to do so.
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
+ unsigned long irqflags, struct otg_hcd_ops *ops)
+{
+ struct otg_data *otgd;
+ struct device *otg_dev = hcd->self.controller->parent;
+
+ mutex_lock(&otg_list_mutex);
+ otgd = usb_otg_device_get_otgd(otg_dev);
+ if (!otgd) {
+ dev_dbg(otg_dev, "otg: %s: device not registered to otg core\n",
+ __func__);
+ mutex_unlock(&otg_list_mutex);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&otg_list_mutex);
+ /* HCD will be started by OTG fsm when needed */
+ mutex_lock(&otgd->fsm.lock);
+ if (otgd->primary_hcd.hcd) {
+ /* probably a shared HCD ? */
+ if (usb_otg_hcd_is_primary_hcd(hcd)) {
+ dev_err(otg_dev, "otg: primary host already registered\n");
+ goto err;
+ }
+
+ if (hcd->shared_hcd == otgd->primary_hcd.hcd) {
+ if (otgd->shared_hcd.hcd) {
+ dev_err(otg_dev, "otg: shared host already registered\n");
+ goto err;
+ }
+
+ otgd->shared_hcd.hcd = hcd;
+ otgd->shared_hcd.irqnum = irqnum;
+ otgd->shared_hcd.irqflags = irqflags;
+ otgd->shared_hcd.ops = ops;
+ dev_info(otg_dev, "otg: shared host %s registered\n",
+ dev_name(hcd->self.controller));
+ } else {
+ dev_err(otg_dev, "otg: invalid shared host %s\n",
+ dev_name(hcd->self.controller));
+ goto err;
+ }
+ } else {
+ if (!usb_otg_hcd_is_primary_hcd(hcd)) {
+ dev_err(otg_dev, "otg: primary host must be registered first\n");
+ goto err;
+ }
+
+ otgd->primary_hcd.hcd = hcd;
+ otgd->primary_hcd.irqnum = irqnum;
+ otgd->primary_hcd.irqflags = irqflags;
+ otgd->primary_hcd.ops = ops;
+ dev_info(otg_dev, "otg: primary host %s registered\n",
+ dev_name(hcd->self.controller));
+
+ }
+
+ /*
+ * we're ready only if we have shared HCD
+ * or we don't need shared HCD.
+ */
+ if (otgd->shared_hcd.hcd || !otgd->primary_hcd.hcd->shared_hcd) {
+ otgd->fsm.otg->host = hcd_to_bus(hcd);
+ /* FIXME: set bus->otg_port if this is true OTG port with HNP */
+
+ /* start FSM */
+ usb_otg_start_fsm(&otgd->fsm);
+ } else {
+ dev_dbg(otg_dev, "otg: can't start till shared host registers\n");
+ }
+
+ mutex_unlock(&otgd->fsm.lock);
+
+ return 0;
+
+err:
+ mutex_unlock(&otgd->fsm.lock);
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(usb_otg_register_hcd);
+
+/**
+ * usb_otg_unregister_hcd - Unregister Host controller from OTG core
+ * @hcd: Host controller device
+ *
+ * This is used by the USB Host stack to unregister the Host controller
+ * from the OTG core. Ensures that Host controller is not running
+ * on successful return.
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_unregister_hcd(struct usb_hcd *hcd)
+{
+ struct otg_data *otgd;
+ struct usb_bus *bus = hcd_to_bus(hcd);
+ struct device *otg_dev = bus->controller->parent;
+
+ mutex_lock(&otg_list_mutex);
+ otgd = usb_otg_device_get_otgd(otg_dev);
+ if (!otgd) {
+ dev_err(otg_dev, "otg: %s: device not registered to otg core\n",
+ __func__);
+ mutex_unlock(&otg_list_mutex);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&otg_list_mutex);
+
+ mutex_lock(&otgd->fsm.lock);
+ if (hcd == otgd->primary_hcd.hcd) {
+ otgd->primary_hcd.hcd = NULL;
+ dev_info(otg_dev, "otg: primary host %s unregistered\n",
+ dev_name(bus->controller));
+ } else if (hcd == otgd->shared_hcd.hcd) {
+ otgd->shared_hcd.hcd = NULL;
+ dev_info(otg_dev, "otg: shared host %s unregistered\n",
+ dev_name(bus->controller));
+ } else {
+ dev_err(otg_dev, "otg: host %s wasn't registered with otg\n",
+ dev_name(bus->controller));
+ mutex_unlock(&otgd->fsm.lock);
+ return -EINVAL;
+ }
+
+ /* stop FSM & Host */
+ usb_otg_stop_fsm(&otgd->fsm);
+ otgd->fsm.otg->host = NULL;
+
+ mutex_unlock(&otgd->fsm.lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_unregister_hcd);
+
+/**
+ * usb_otg_register_gadget - Register Gadget controller to OTG core
+ * @gadget: Gadget controller
+ *
+ * This is used by the USB Gadget stack to register the Gadget controller
+ * to the OTG core. Gadget controller must not be started by the
+ * caller as it is left upto the OTG state machine to do so.
+ *
+ * Gadget core must call this only when all resources required for
+ * gadget controller to run are available.
+ * i.e. gadget function driver is available.
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_register_gadget(struct usb_gadget *gadget,
+ struct otg_gadget_ops *ops)
+{
+ struct otg_data *otgd;
+ struct device *otg_dev = gadget->dev.parent;
+
+ mutex_lock(&otg_list_mutex);
+ otgd = usb_otg_device_get_otgd(otg_dev);
+ if (!otgd) {
+ dev_err(otg_dev, "otg: %s: device not registered to otg core\n",
+ __func__);
+ mutex_unlock(&otg_list_mutex);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&otg_list_mutex);
+
+ mutex_lock(&otgd->fsm.lock);
+ if (otgd->fsm.otg->gadget) {
+ dev_err(otg_dev, "otg: gadget already registered with otg\n");
+ mutex_unlock(&otgd->fsm.lock);
+ return -EINVAL;
+ }
+
+ otgd->fsm.otg->gadget = gadget;
+ otgd->gadget_ops = ops;
+ dev_info(otg_dev, "otg: gadget %s registered\n",
+ dev_name(&gadget->dev));
+
+ /* start FSM */
+ usb_otg_start_fsm(&otgd->fsm);
+ mutex_unlock(&otgd->fsm.lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_register_gadget);
+
+/**
+ * usb_otg_unregister_gadget - Unregister Gadget controller from OTG core
+ * @gadget: Gadget controller
+ *
+ * This is used by the USB Gadget stack to unregister the Gadget controller
+ * from the OTG core. Ensures that Gadget controller is not running
+ * on successful return.
+ *
+ * Returns: 0 on success, error value otherwise.
+ */
+int usb_otg_unregister_gadget(struct usb_gadget *gadget)
+{
+ struct otg_data *otgd;
+ struct device *otg_dev = gadget->dev.parent;
+
+ mutex_lock(&otg_list_mutex);
+ otgd = usb_otg_device_get_otgd(otg_dev);
+ if (!otgd) {
+ dev_err(otg_dev, "otg: %s: device not registered to otg core\n",
+ __func__);
+ mutex_unlock(&otg_list_mutex);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&otg_list_mutex);
+
+ mutex_lock(&otgd->fsm.lock);
+ if (otgd->fsm.otg->gadget != gadget) {
+ dev_err(otg_dev, "otg: gadget %s wasn't registered with otg\n",
+ dev_name(&gadget->dev));
+ mutex_unlock(&otgd->fsm.lock);
+ return -EINVAL;
+ }
+
+ /* Stop FSM & gadget */
+ usb_otg_stop_fsm(&otgd->fsm);
+ otgd->fsm.otg->gadget = NULL;
+ mutex_unlock(&otgd->fsm.lock);
+
+ dev_info(otg_dev, "otg: gadget %s unregistered\n",
+ dev_name(&gadget->dev));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_unregister_gadget);
+
+/**
+ * usb_otg_fsm_to_dev - Get OTG controller device from struct otg_fsm
+ * @fsm: otg_fsm data structure
+ *
+ * This is used by the OTG controller driver to get it's device node
+ * from any of the otg_fsm->ops.
+ */
+struct device *usb_otg_fsm_to_dev(struct otg_fsm *fsm)
+{
+ struct otg_data *otgd = container_of(fsm, struct otg_data, fsm);
+
+ return otgd->dev;
+}
+EXPORT_SYMBOL_GPL(usb_otg_fsm_to_dev);
diff --git a/drivers/usb/common/usb-otg.h b/drivers/usb/common/usb-otg.h
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+ * drivers/usb/common/usb-otg.h - USB OTG core local header
+ *
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Roger Quadros <rogerq@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRIVERS_USB_COMMON_USB_OTG_H
+#define __DRIVERS_USB_COMMON_USB_OTG_H
+
+/*
+ * A-DEVICE timing constants
+ */
+
+/* Wait for VBUS Rise */
+#define TA_WAIT_VRISE (100) /* a_wait_vrise: section 7.1.2
+ * a_wait_vrise_tmr: section 7.4.5.1
+ * TA_VBUS_RISE <= 100ms, section 4.4
+ * Table 4-1: Electrical Characteristics
+ * ->DC Electrical Timing
+ */
+/* Wait for VBUS Fall */
+#define TA_WAIT_VFALL (1000) /* a_wait_vfall: section 7.1.7
+ * a_wait_vfall_tmr: section: 7.4.5.2
+ */
+/* Wait for B-Connect */
+#define TA_WAIT_BCON (10000) /* a_wait_bcon: section 7.1.3
+ * TA_WAIT_BCON: should be between 1100
+ * and 30000 ms, section 5.5, Table 5-1
+ */
+/* A-Idle to B-Disconnect */
+#define TA_AIDL_BDIS (5000) /* a_suspend min 200 ms, section 5.2.1
+ * TA_AIDL_BDIS: section 5.5, Table 5-1
+ */
+/* B-Idle to A-Disconnect */
+#define TA_BIDL_ADIS (500) /* TA_BIDL_ADIS: section 5.2.1
+ * 500ms is used for B switch to host
+ * for safe
+ */
+
+/*
+ * B-device timing constants
+ */
+
+/* Data-Line Pulse Time*/
+#define TB_DATA_PLS (10) /* b_srp_init,continue 5~10ms
+ * section:5.1.3
+ */
+/* SRP Fail Time */
+#define TB_SRP_FAIL (6000) /* b_srp_init,fail time 5~6s
+ * section:5.1.6
+ */
+/* A-SE0 to B-Reset */
+#define TB_ASE0_BRST (155) /* minimum 155 ms, section:5.3.1 */
+/* SE0 Time Before SRP */
+#define TB_SE0_SRP (1000) /* b_idle,minimum 1s, section:5.1.2 */
+/* SSEND time before SRP */
+#define TB_SSEND_SRP (1500) /* minimum 1.5 sec, section:5.1.2 */
+
+#define TB_SESS_VLD (1000)
+
+#endif /* __DRIVERS_USB_COMMON_USB_OTG_H */
index fed7f68d025d1174e9e6882c3cba59a94de8220d..bcae4db11cdd8c0651f53da9fdc3567eee9750da 100644 (file)
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
external hubs. OTG hosts are allowed to reduce hardware
and software costs by not supporting external hubs. So
are "Embedded Hosts" that don't offer OTG support.
-
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index ee6c5562d296e13168b4b4f836cc729ed4343fe9..21532abcf7cc9ad9d403d43bfd667e4d348803c5 100644 (file)
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/phy.h>
+#include <linux/usb/otg.h>
#include "usb.h"
usbmon_urb_complete(&hcd->self, urb, status);
usb_anchor_suspend_wakeups(anchor);
usb_unanchor_urb(urb);
+ if (likely(status == 0))
+ usb_led_activity(USB_LED_EVENT_HOST);
/* pass ownership to the completion handler */
urb->status = status;
* buffers of consistent memory, register the bus, request the IRQ line,
* and call the driver's reset() and start() routines.
*/
-int usb_add_hcd(struct usb_hcd *hcd,
- unsigned int irqnum, unsigned long irqflags)
+static int usb_otg_add_hcd(struct usb_hcd *hcd,
+ unsigned int irqnum, unsigned long irqflags)
{
int retval;
struct usb_device *rhdev;
- if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->phy) {
+ if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) {
struct usb_phy *phy = usb_get_phy_dev(hcd->self.controller, 0);
if (IS_ERR(phy)) {
usb_put_phy(phy);
return retval;
}
- hcd->phy = phy;
+ hcd->usb_phy = phy;
hcd->remove_phy = 1;
}
}
err_register_bus:
hcd_buffer_destroy(hcd);
err_remove_phy:
- if (hcd->remove_phy && hcd->phy) {
- usb_phy_shutdown(hcd->phy);
- usb_put_phy(hcd->phy);
- hcd->phy = NULL;
+ if (hcd->remove_phy && hcd->usb_phy) {
+ usb_phy_shutdown(hcd->usb_phy);
+ usb_put_phy(hcd->usb_phy);
+ hcd->usb_phy = NULL;
}
return retval;
}
-EXPORT_SYMBOL_GPL(usb_add_hcd);
/**
- * usb_remove_hcd - shutdown processing for generic HCDs
+ * usb_otg_remove_hcd - shutdown processing for generic HCDs
* @hcd: the usb_hcd structure to remove
* Context: !in_interrupt()
*
* Disconnects the root hub, then reverses the effects of usb_add_hcd(),
* invoking the HCD's stop() method.
*/
-void usb_remove_hcd(struct usb_hcd *hcd)
+static void usb_otg_remove_hcd(struct usb_hcd *hcd)
{
struct usb_device *rhdev = hcd->self.root_hub;
usb_put_dev(hcd->self.root_hub);
usb_deregister_bus(&hcd->self);
hcd_buffer_destroy(hcd);
- if (hcd->remove_phy && hcd->phy) {
- usb_phy_shutdown(hcd->phy);
- usb_put_phy(hcd->phy);
- hcd->phy = NULL;
+ if (hcd->remove_phy && hcd->usb_phy) {
+ usb_phy_shutdown(hcd->usb_phy);
+ usb_put_phy(hcd->usb_phy);
+ hcd->usb_phy = NULL;
}
}
+
+static struct otg_hcd_ops otg_hcd_intf = {
+ .add = usb_otg_add_hcd,
+ .remove = usb_otg_remove_hcd,
+};
+
+/**
+ * usb_add_hcd - finish generic HCD structure initialization and register
+ * @hcd: the usb_hcd structure to initialize
+ * @irqnum: Interrupt line to allocate
+ * @irqflags: Interrupt type flags
+ *
+ * Finish the remaining parts of generic HCD initialization: allocate the
+ * buffers of consistent memory, register the bus, request the IRQ line,
+ * and call the driver's reset() and start() routines.
+ * If it is an OTG device then it only registers the HCD with OTG core.
+ *
+ */
+int usb_add_hcd(struct usb_hcd *hcd,
+ unsigned int irqnum, unsigned long irqflags)
+{
+ /* If OTG device, OTG core takes care of adding HCD */
+ if (usb_otg_register_hcd(hcd, irqnum, irqflags, &otg_hcd_intf))
+ return usb_otg_add_hcd(hcd, irqnum, irqflags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_add_hcd);
+
+/**
+ * usb_remove_hcd - shutdown processing for generic HCDs
+ * @hcd: the usb_hcd structure to remove
+ * Context: !in_interrupt()
+ *
+ * Disconnects the root hub, then reverses the effects of usb_add_hcd(),
+ * invoking the HCD's stop() method.
+ * If it is an OTG device then it unregisters the HCD from OTG core
+ * as well.
+ */
+void usb_remove_hcd(struct usb_hcd *hcd)
+{
+ /* If OTG device, OTG core takes care of stopping HCD */
+ if (usb_otg_unregister_hcd(hcd))
+ usb_otg_remove_hcd(hcd);
+}
EXPORT_SYMBOL_GPL(usb_remove_hcd);
void
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c7a2245a84b55bc5d48e28e13bb15998c156955d..47d8dafe9d9f789781285a0f83072724c8b5dcb2 100644 (file)
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
"can't set HNP mode: %d\n",
err);
bus->b_hnp_enable = 0;
+ } else {
+ /* notify OTG fsm about a_set_b_hnp_enable */
+ usb_otg_kick_fsm(udev->bus->controller);
}
}
}
dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
port1, status);
} else {
- /* drive resume for at least 20 msec */
+ /* drive resume for USB_RESUME_TIMEOUT msec */
dev_dbg(&udev->dev, "usb %sresume\n",
(PMSG_IS_AUTO(msg) ? "auto-" : ""));
- msleep(25);
+ msleep(USB_RESUME_TIMEOUT);
/* Virtual root hubs can trigger on GET_PORT_STATUS to
* stop resume signaling. Then finish the resume
*/
if (!hdev->parent) {
delay = HUB_ROOT_RESET_TIME;
- if (port1 == hdev->bus->otg_port)
+ if (port1 == hdev->bus->otg_port) {
hdev->bus->b_hnp_enable = 0;
+#ifdef CONFIG_USB_OTG
+ /* notify OTG fsm about a_set_b_hnp_enable change */
+ usb_otg_kick_fsm(hdev->bus->controller);
+#endif
+ }
}
/* Some low speed devices have problems with the quick delay, so */
if (retval)
goto fail;
- if (hcd->phy && !hdev->parent)
- usb_phy_notify_connect(hcd->phy, udev->speed);
+ if (hcd->usb_phy && !hdev->parent)
+ usb_phy_notify_connect(hcd->usb_phy, udev->speed);
/*
* Some superspeed devices have finished the link training process
/* Disconnect any existing devices under this port */
if (udev) {
- if (hcd->phy && !hdev->parent &&
+ if (hcd->usb_phy && !hdev->parent &&
!(portstatus & USB_PORT_STAT_CONNECTION))
- usb_phy_notify_disconnect(hcd->phy, udev->speed);
+ usb_phy_notify_disconnect(hcd->usb_phy, udev->speed);
usb_disconnect(&hub->ports[port1 - 1]->child);
}
clear_bit(port1, hub->change_bits);
diff --git a/drivers/usb/drd-lib.c b/drivers/usb/drd-lib.c
--- a/drivers/usb/drd-lib.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/**
- * drd-lib.c - USB DRD library functions
- *
- * Copyright (C) 2014 Texas Instruments
- * Author: George Cherian <george.cherian@ti.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 of
- * the License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-#include <linux/usb/hcd.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/drd.h>
-
-/**
- * struct usb_drd - describes one dual role device
- * @host - the HOST controller device of this drd
- * @gadget - the gadget of drd
- * @parent - the device to the actual controller
- * @list - for use by the drd lib
- * @state - specifies the current state
- *
- * This represents the internal data structure which is used by the UDC-class
- * to hold information about udc driver and gadget together.
-*/
-struct usb_drd {
- struct usb_drd_host *host;
- struct usb_drd_gadget *gadget;
- struct device *parent;
- struct list_head list;
- unsigned int state;
-};
-
-static LIST_HEAD(drd_list);
-static DEFINE_SPINLOCK(drd_lock);
-
-static struct usb_drd *usb_drd_get_dev(struct device *parent)
-{
- struct usb_drd *drd;
-
- spin_lock(&drd_lock);
- list_for_each_entry(drd, &drd_list, list)
- if (drd->parent == parent)
- goto out;
- drd = NULL;
-out:
- spin_unlock(&drd_lock);
-
- return drd;
-}
-
-int usb_drd_get_state(struct device *parent)
-{
- struct usb_drd *drd;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- return drd->state;
-}
-EXPORT_SYMBOL_GPL(usb_drd_get_state);
-
-int usb_drd_release(struct device *parent)
-{
- struct usb_drd *drd;
- int ret;
-
- spin_lock(&drd_lock);
- list_for_each_entry(drd, &drd_list, list) {
- if (drd->parent == parent) {
- kfree(drd);
- ret = 0;
- goto out;
- }
- }
- ret = -ENODEV;
-out:
- spin_unlock(&drd_lock);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(usb_drd_release);
-
-int usb_drd_add(struct device *parent)
-{
- struct usb_drd *drd;
-
- drd = kzalloc(sizeof(*drd), GFP_KERNEL);
- if (!drd)
- return -ENOMEM;
-
- spin_lock(&drd_lock);
- drd->parent = parent;
- list_add_tail(&drd->list, &drd_list);
- drd->state = DRD_UNREGISTERED;
-
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_add);
-
-int usb_drd_register_hcd(struct device *parent, struct usb_drd_host *host)
-{
- struct usb_drd *drd;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- spin_lock(&drd_lock);
- drd->host = host;
- drd->state |= DRD_HOST_REGISTERED | DRD_HOST_ACTIVE;
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_register_hcd);
-
-int usb_drd_unregister_hcd(struct device *parent)
-{
- struct usb_drd *drd;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- spin_lock(&drd_lock);
- drd->state &= ~(DRD_HOST_REGISTERED | DRD_HOST_ACTIVE);
- spin_unlock(&drd_lock);
- kfree(drd->host);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_unregister_hcd);
-
-int usb_drd_start_hcd(struct device *parent)
-{
- struct usb_drd *drd;
- struct usb_drd_setup *setup;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- if (WARN_ON(!(drd->state & DRD_HOST_REGISTERED)))
- return -EINVAL;
-
- setup = drd->host->host_setup;
- if (setup && setup->ll_start)
- setup->ll_start(setup->data);
-
- usb_add_hcd(drd->host->main_hcd,
- drd->host->hcd_irq, IRQF_SHARED);
- if (drd->host->shared_hcd)
- usb_add_hcd(drd->host->shared_hcd,
- drd->host->hcd_irq, IRQF_SHARED);
-
- spin_lock(&drd_lock);
- drd->state |= DRD_HOST_ACTIVE;
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_start_hcd);
-
-int usb_drd_stop_hcd(struct device *parent)
-{
- struct usb_drd *drd;
- struct usb_drd_setup *setup;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- if (WARN_ON(!(drd->state & DRD_HOST_REGISTERED)))
- return -EINVAL;
-
- setup = drd->host->host_setup;
- if (setup && setup->ll_stop)
- setup->ll_stop(setup->data);
- if (drd->host->shared_hcd)
- usb_remove_hcd(drd->host->shared_hcd);
-
- usb_remove_hcd(drd->host->main_hcd);
-
- spin_lock(&drd_lock);
- drd->state = drd->state & ~DRD_HOST_ACTIVE;
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_stop_hcd);
-
-int usb_drd_register_udc(struct device *parent, struct usb_drd_gadget *gadget)
-{
- struct usb_drd *drd;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- spin_lock(&drd_lock);
- drd->gadget = gadget;
- drd->state |= DRD_DEVICE_REGISTERED;
- if (drd->gadget->g_driver)
- drd->state |= DRD_DEVICE_ACTIVE;
-
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_register_udc);
-
-int usb_drd_register_udc_driver(struct device *parent,
- struct usb_gadget_driver *driver)
-{
- struct usb_drd *drd;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- spin_lock(&drd_lock);
- drd->gadget->g_driver = driver;
- drd->state |= DRD_DEVICE_ACTIVE;
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_register_udc_driver);
-
-int usb_drd_unregister_udc(struct device *parent)
-{
- struct usb_drd *drd;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- spin_lock(&drd_lock);
- drd->state &= ~(DRD_DEVICE_REGISTERED | DRD_DEVICE_ACTIVE);
- spin_unlock(&drd_lock);
- kfree(drd->gadget->gadget_setup);
- kfree(drd->gadget);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_unregister_udc);
-
-int usb_drd_unregister_udc_driver(struct device *parent)
-{
- struct usb_drd *drd;
- struct usb_drd_gadget *drd_gadget;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
- drd_gadget = drd->gadget;
-
- spin_lock(&drd_lock);
- drd->state &= ~DRD_DEVICE_ACTIVE;
- drd_gadget->g_driver = NULL;
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_unregister_udc_driver);
-
-int usb_drd_start_udc(struct device *parent)
-{
- struct usb_drd *drd;
- struct usb_drd_gadget *drd_gadget;
- struct usb_drd_setup *setup;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- if (WARN_ON(!(drd->state & DRD_DEVICE_REGISTERED)))
- return -EINVAL;
-
- drd_gadget = drd->gadget;
- setup = drd_gadget->gadget_setup;
-
- if (setup && setup->ll_start)
- setup->ll_start(setup->data);
-
- usb_add_gadget_udc_release(parent, drd_gadget->gadget,
- setup->ll_release);
- spin_lock(&drd_lock);
- drd->state |= DRD_DEVICE_ACTIVE;
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_start_udc);
-
-int usb_drd_stop_udc(struct device *parent)
-{
- struct usb_drd *drd;
- struct usb_drd_gadget *drd_gadget;
- struct usb_drd_setup *setup;
-
- drd = usb_drd_get_dev(parent);
- if (!drd)
- return -ENODEV;
-
- if (WARN_ON(!(drd->state & DRD_DEVICE_REGISTERED)))
- return -EINVAL;
-
- drd_gadget = drd->gadget;
- setup = drd_gadget->gadget_setup;
- if (setup && setup->ll_stop)
- setup->ll_stop(setup->data);
-
- usb_del_gadget_udc(drd_gadget->gadget);
-
- spin_lock(&drd_lock);
- drd->state = drd->state & ~DRD_DEVICE_ACTIVE;
- spin_unlock(&drd_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_drd_stop_udc);
-
-MODULE_DESCRIPTION("USB-DRD Library");
-MODULE_AUTHOR("George Cherian <george.cherian@ti.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 4d918ed8d343394bcc92cea19e4e025a9f7c7c5c..0f9980088c083628c44cc3f13a8e4248f1a0dcce 100644 (file)
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
writel(0, hsotg->regs + PCGCTL);
- usleep_range(20000, 40000);
+ msleep(USB_RESUME_TIMEOUT);
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 |= HPRT0_RES;
index bc1bce1e1144fa89b9684b13d4505f4db19beaaa..10ac3e72482ea52e8924533ad9ed93490eac9e46 100644 (file)
dwc3-y += host.o
endif
-ifneq ($(CONFIG_USB_DWC3_DUAL_ROLE),)
- dwc3-y += otg.o
-endif
-
ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
dwc3-y += gadget.o ep0.o
endif
index 717ff4e47f0eb887766043d25ff9833e9364ec5d..2ada5769020a63dd5cb832ba049a6b540a29bb8a 100644 (file)
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
reg |= DWC3_GCTL_PRTCAPDIR(mode);
+ dwc->current_mode = mode;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}
}
}
-int dwc3_core_gadget_helper(struct dwc3 *dwc)
-{
- return dwc3_event_buffers_setup(dwc);
-}
-
static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
{
if (!dwc->has_hibernation)
parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
}
+/**
+ * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
+ * @dwc: Pointer to our controller context structure
+ */
+static void dwc3_phy_setup(struct dwc3 *dwc)
+{
+ u32 reg;
+
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+
+ /*
+ * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
+ * to '0' during coreConsultant configuration. So default value
+ * will be '0' when the core is reset. Application needs to set it
+ * to '1' after the core initialization is completed.
+ */
+ if (dwc->revision > DWC3_REVISION_194A)
+ reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+
+ if (dwc->u2ss_inp3_quirk)
+ reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
+
+ if (dwc->req_p1p2p3_quirk)
+ reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
+
+ if (dwc->del_p1p2p3_quirk)
+ reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
+
+ if (dwc->del_phy_power_chg_quirk)
+ reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
+
+ if (dwc->lfps_filter_quirk)
+ reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
+
+ if (dwc->rx_detect_poll_quirk)
+ reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
+
+ if (dwc->tx_de_emphasis_quirk)
+ reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
+
+ if (dwc->dis_u3_susphy_quirk)
+ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+
+ dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+
+ mdelay(100);
+
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+
+ /*
+ * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
+ * '0' during coreConsultant configuration. So default value will
+ * be '0' when the core is reset. Application needs to set it to
+ * '1' after the core initialization is completed.
+ */
+ if (dwc->revision > DWC3_REVISION_194A)
+ reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+
+ if (dwc->dis_u2_susphy_quirk)
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+
+ mdelay(100);
+}
+
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
- reg &= ~DWC3_GCTL_DISSCRAMBLE;
switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
dev_dbg(dwc->dev, "No power optimization available\n");
}
+ /* check if current dwc3 is on simulation board */
+ if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
+ dev_dbg(dwc->dev, "it is on FPGA board\n");
+ dwc->is_fpga = true;
+ }
+
+ WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga,
+ "disable_scramble cannot be used on non-FPGA builds\n");
+
+ if (dwc->disable_scramble_quirk && dwc->is_fpga)
+ reg |= DWC3_GCTL_DISSCRAMBLE;
+ else
+ reg &= ~DWC3_GCTL_DISSCRAMBLE;
+
+ if (dwc->u2exit_lfps_quirk)
+ reg |= DWC3_GCTL_U2EXIT_LFPS;
+
/*
* WORKAROUND: DWC3 revisions <1.90a have a bug
* where the device can fail to connect at SuperSpeed
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+ dwc3_phy_setup(dwc);
+
ret = dwc3_alloc_scratch_buffers(dwc);
if (ret)
goto err1;
return 0;
}
+/* Get OTG events and sync it to OTG fsm */
+static void dwc3_otg_fsm_sync(struct dwc3 *dwc)
+{
+ u32 reg;
+ int id, vbus;
+
+ reg = dwc3_readl(dwc->regs, DWC3_OSTS);
+ dev_dbg(dwc->dev, "otgstatus 0x%x\n", reg);
+
+ id = !!(reg & DWC3_OSTS_CONIDSTS);
+ vbus = !!(reg & DWC3_OSTS_BSESVLD);
+
+ if (id != dwc->fsm->id || vbus != dwc->fsm->vbus) {
+ dev_dbg(dwc->dev, "id %d vbus %d\n", id, vbus);
+ dwc->fsm->id = id;
+ dwc->fsm->vbus = vbus;
+ usb_otg_sync_inputs(dwc->fsm);
+ }
+}
+
+static irqreturn_t dwc3_otg_thread_irq(int irq, void *_dwc)
+{
+ struct dwc3 *dwc = _dwc;
+ unsigned long flags;
+ irqreturn_t ret = IRQ_NONE;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+ dwc3_otg_fsm_sync(dwc);
+ /* unmask interrupts */
+ dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ return ret;
+}
+
+static irqreturn_t dwc3_otg_irq(int irq, void *_dwc)
+{
+ struct dwc3 *dwc = _dwc;
+ irqreturn_t ret = IRQ_NONE;
+ u32 reg;
+
+ spin_lock(&dwc->lock);
+
+ reg = dwc3_readl(dwc->regs, DWC3_OEVT);
+ if (reg) {
+ dwc3_writel(dwc->regs, DWC3_OEVT, reg);
+ /* mask interrupts till processed */
+ dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN);
+ dwc3_writel(dwc->regs, DWC3_OEVTEN, 0);
+ ret = IRQ_WAKE_THREAD;
+ }
+
+ spin_unlock(&dwc->lock);
+
+ return ret;
+}
+
+/* --------------------- Dual-Role management ------------------------------- */
+
+static void dwc3_drd_fsm_sync(struct dwc3 *dwc)
+{
+ int id, vbus;
+
+ /* get ID */
+ id = extcon_get_cable_state(dwc->edev, "USB-HOST");
+ /* Host means ID == 0 */
+ id = !id;
+
+ /* get VBUS */
+ vbus = extcon_get_cable_state(dwc->edev, "USB");
+ dev_dbg(dwc->dev, "id %d vbus %d\n", id, vbus);
+
+ dwc->fsm->id = id;
+ dwc->fsm->vbus = vbus;
+ usb_otg_sync_inputs(dwc->fsm);
+}
+
+static int dwc3_drd_start_host(struct otg_fsm *fsm, int on)
+{
+ struct device *dev = usb_otg_fsm_to_dev(fsm);
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ u32 reg;
+
+ dev_dbg(dwc->dev, "%s: %d\n", __func__, on);
+ if (dwc->edev) {
+ if (on)
+ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
+
+ return 0;
+ }
+
+ /* switch OTG core */
+ if (on) {
+ /* OCTL.PeriMode = 0 */
+ reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+ reg &= ~DWC3_OCTL_PERIMODE;
+ dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+ /* unconditionally turn on VBUS */
+ reg |= DWC3_OCTL_PRTPWRCTL;
+ dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+ } else {
+ /* turn off VBUS */
+ reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+ reg &= ~DWC3_OCTL_PRTPWRCTL;
+ dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+ /* OCTL.PeriMode = 1 */
+ reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+ reg |= DWC3_OCTL_PERIMODE;
+ dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+ }
+
+ return 0;
+}
+
+static int dwc3_drd_start_gadget(struct otg_fsm *fsm, int on)
+{
+ struct device *dev = usb_otg_fsm_to_dev(fsm);
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ u32 reg;
+
+ dev_dbg(dwc->dev, "%s: %d\n", __func__, on);
+ if (on)
+ dwc3_event_buffers_setup(dwc);
+
+ if (dwc->edev) {
+ if (on)
+ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+
+ return 0;
+ }
+
+ /* switch OTG core */
+ if (on) {
+ /* OCTL.PeriMode = 1 */
+ reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+ reg |= DWC3_OCTL_PERIMODE;
+ dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+ /* GUSB2PHYCFG0.SusPHY = 1 */
+ if (!dwc->dis_u2_susphy_quirk) {
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+ reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+ }
+ } else {
+ /* GUSB2PHYCFG0.SusPHY=0 */
+ if (!dwc->dis_u2_susphy_quirk) {
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+ }
+ /* OCTL.PeriMode = 1 */
+ reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+ reg |= DWC3_OCTL_PERIMODE;
+ dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+ }
+
+ return 0;
+}
+
+static struct otg_fsm_ops dwc3_drd_ops = {
+ .start_host = dwc3_drd_start_host,
+ .start_gadget = dwc3_drd_start_gadget,
+};
+
+static int dwc3_drd_notifier(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct dwc3 *dwc = container_of(nb, struct dwc3, otg_nb);
+
+ dwc3_drd_fsm_sync(dwc);
+
+ return NOTIFY_DONE;
+}
+
+static int dwc3_drd_init(struct dwc3 *dwc)
+{
+ int ret, id, vbus;
+ int irq;
+ u32 reg;
+ struct dwc3_hwparams *parms = &dwc->hwparams;
+
+ /* If extcon device is not present we rely on OTG core for ID event */
+ if (!dwc->edev) {
+ dev_dbg(dwc->dev, "No extcon device found for OTG mode\n");
+ goto try_otg_core;
+ }
+
+ dwc->otg_nb.notifier_call = dwc3_drd_notifier;
+ ret = extcon_register_notifier(dwc->edev, &dwc->otg_nb);
+ if (ret < 0) {
+ dev_err(dwc->dev, "Couldn't register USB cable notifier\n");
+ return -ENODEV;
+ }
+
+ /* sanity check id & vbus states */
+ id = extcon_get_cable_state(dwc->edev, "USB-HOST");
+ vbus = extcon_get_cable_state(dwc->edev, "USB");
+ if (id < 0 || vbus < 0) {
+ dev_err(dwc->dev, "Invalid USB cable state. id %d, vbus %d\n",
+ id, vbus);
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ /* register parent as OTG device with USB core */
+ dwc->fsm = usb_otg_register(dwc->dev, &dwc3_drd_ops, true);
+ if (IS_ERR(dwc->fsm)) {
+ dev_err(dwc->dev, "Failed to register with OTG core\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ dwc3_drd_fsm_sync(dwc);
+
+ return 0;
+
+fail:
+ extcon_unregister_notifier(dwc->edev, &dwc->otg_nb);
+
+ return ret;
+
+try_otg_core:
+ /* get OTG capabilities */
+ dwc->otg_has_hnp_rsp = !!(parms->hwparams6 & DWC3_GHWPARAMS6_HNPSUPPORT);
+ dwc->otg_has_srp = !!(parms->hwparams6 & DWC3_GHWPARAMS6_SRPSUPPORT);
+ dwc->otg_has_adp = !!(parms->hwparams6 & DWC3_GHWPARAMS6_ADPSUPPORT);
+ dwc->otg_has_bc = !!(parms->hwparams6 & DWC3_GHWPARAMS6_BCSUPPORT);
+ dwc->otg_has_otg3 = !!(parms->hwparams6 & DWC3_GHWPARAMS6_OTG3SUPPORT);
+
+ dev_dbg(dwc->dev, "otg v%s - srp: %d, hnp/rsp:%d, adp:%d, bc:%d\n",
+ dwc->otg_has_otg3 ? "3.0":"2.0",
+ dwc->otg_has_srp, dwc->otg_has_hnp_rsp,
+ dwc->otg_has_adp, dwc->otg_has_bc);
+
+
+ /* Some SoCs have OTG events in a separate IRQ, try that first */
+ irq = dwc->otg_irq;
+ if (!irq)
+ irq = dwc->gadget_irq;
+ if (!irq) {
+ dev_err(dwc->dev, "failed to get irq for OTG\n");
+ return -ENODEV;
+ }
+
+ /* register parent as OTG device with USB core */
+ dwc->fsm = usb_otg_register(dwc->dev, &dwc3_drd_ops, true);
+ if (IS_ERR(dwc->fsm)) {
+ dev_err(dwc->dev, "Failed to register with OTG core\n");
+ return -ENODEV;
+ }
+
+ /* disable all irqs */
+ dwc3_writel(dwc->regs, DWC3_OEVTEN, 0);
+ /* clear all events */
+ dwc3_writel(dwc->regs, DWC3_OEVT, ~0);
+
+ ret = request_threaded_irq(irq, dwc3_otg_irq, dwc3_otg_thread_irq,
+ IRQF_SHARED, "dwc3-otg", dwc);
+ if (ret) {
+ dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+ irq, ret);
+ ret = -ENODEV;
+ goto error;
+ }
+
+ /* we need to set OTG to get events from OTG core */
+ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
+ /* GUSB2PHYCFG0.SusPHY=0 */
+ if (!dwc->dis_u2_susphy_quirk) {
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+ }
+
+ /* Initialize OTG registers */
+ /*
+ * Prevent host/device reset from resetting OTG core.
+ * If we don't do this then xhci_reset (USBCMD.HCRST) will reset
+ * the signal outputs sent to the PHY, the OTG FSM logic of the
+ * core and also the resets to the VBUS filters inside the core.
+ */
+ reg = DWC3_OCFG_SFTRSTMASK;
+ dwc3_writel(dwc->regs, DWC3_OCFG, reg);
+ /* Enable ID event interrupt */
+ dwc3_writel(dwc->regs, DWC3_OEVTEN, DWC3_OEVTEN_CONIDSTSCHNGEN |
+ DWC3_OEVTEN_BDEVVBUSCHNGE |
+ DWC3_OEVTEN_BDEVSESSVLDDETEN);
+ /* OCTL.PeriMode = 1 */
+ dwc3_writel(dwc->regs, DWC3_OCTL, DWC3_OCTL_PERIMODE);
+
+ dwc3_otg_fsm_sync(dwc);
+ usb_otg_sync_inputs(dwc->fsm);
+
+ return 0;
+
+error:
+ usb_otg_unregister(dwc->dev);
+
+ return ret;
+}
+
+static void dwc3_drd_exit(struct dwc3 *dwc)
+{
+ usb_otg_unregister(dwc->dev);
+ extcon_unregister_notifier(dwc->edev, &dwc->otg_nb);
+}
+
+/* -------------------------------------------------------------------------- */
+
static int dwc3_core_init_mode(struct dwc3 *dwc)
{
struct device *dev = dwc->dev;
}
break;
case USB_DR_MODE_OTG:
- dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
- ret = dwc3_otg_init(dwc);
+ ret = dwc3_drd_init(dwc);
+ if (ret) {
+ dev_err(dev, "failed to initialize drd\n");
+ return ret;
+ }
+
+ ret = dwc3_host_init(dwc);
+ if (ret) {
+ dev_err(dev, "failed to initialize host\n");
+ return ret;
+ }
+
+ ret = dwc3_gadget_init(dwc);
if (ret) {
- dev_err(dev, "failed to initialize otg\n");
+ dev_err(dev, "failed to initialize gadget\n");
return ret;
}
break;
case USB_DR_MODE_OTG:
dwc3_host_exit(dwc);
dwc3_gadget_exit(dwc);
+ dwc3_drd_exit(dwc);
break;
default:
/* do nothing */
struct device_node *node = dev->of_node;
struct resource *res;
struct dwc3 *dwc;
+ u8 lpm_nyet_threshold;
+ u8 tx_de_emphasis;
+ u8 hird_threshold;
int ret;
dwc->regs = regs;
dwc->regs_size = resource_size(res);
+ /* default to highest possible threshold */
+ lpm_nyet_threshold = 0xff;
+
+ /* default to -3.5dB de-emphasis */
+ tx_de_emphasis = 1;
+
+ /*
+ * default to assert utmi_sleep_n and use maximum allowed HIRD
+ * threshold value of 0b1100
+ */
+ hird_threshold = 12;
+
if (node) {
- dwc->maximum_speed = of_usb_get_maximum_speed(node);
+ if (of_property_read_bool(node, "extcon"))
+ dwc->edev = extcon_get_edev_by_phandle(dev, 0);
+ else if (of_property_read_bool(dev->parent->of_node, "extcon"))
+ dwc->edev = extcon_get_edev_by_phandle(dev->parent, 0);
+
+ if (IS_ERR(dwc->edev)) {
+ dev_vdbg(dev, "couldn't get extcon device\n");
+ return -EPROBE_DEFER;
+ }
- dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
+ dwc->maximum_speed = of_usb_get_maximum_speed(node);
+ dwc->has_lpm_erratum = of_property_read_bool(node,
+ "snps,has-lpm-erratum");
+ of_property_read_u8(node, "snps,lpm-nyet-threshold",
+ &lpm_nyet_threshold);
+ dwc->is_utmi_l1_suspend = of_property_read_bool(node,
+ "snps,is-utmi-l1-suspend");
+ of_property_read_u8(node, "snps,hird-threshold",
+ &hird_threshold);
+
+ dwc->needs_fifo_resize = of_property_read_bool(node,
+ "tx-fifo-resize");
dwc->dr_mode = of_usb_get_dr_mode(node);
+
+ dwc->disable_scramble_quirk = of_property_read_bool(node,
+ "snps,disable_scramble_quirk");
+ dwc->u2exit_lfps_quirk = of_property_read_bool(node,
+ "snps,u2exit_lfps_quirk");
+ dwc->u2ss_inp3_quirk = of_property_read_bool(node,
+ "snps,u2ss_inp3_quirk");
+ dwc->req_p1p2p3_quirk = of_property_read_bool(node,
+ "snps,req_p1p2p3_quirk");
+ dwc->del_p1p2p3_quirk = of_property_read_bool(node,
+ "snps,del_p1p2p3_quirk");
+ dwc->del_phy_power_chg_quirk = of_property_read_bool(node,
+ "snps,del_phy_power_chg_quirk");
+ dwc->lfps_filter_quirk = of_property_read_bool(node,
+ "snps,lfps_filter_quirk");
+ dwc->rx_detect_poll_quirk = of_property_read_bool(node,
+ "snps,rx_detect_poll_quirk");
+ dwc->dis_u3_susphy_quirk = of_property_read_bool(node,
+ "snps,dis_u3_susphy_quirk");
+ dwc->dis_u2_susphy_quirk = of_property_read_bool(node,
+ "snps,dis_u2_susphy_quirk");
+
+ dwc->tx_de_emphasis_quirk = of_property_read_bool(node,
+ "snps,tx_de_emphasis_quirk");
+ of_property_read_u8(node, "snps,tx_de_emphasis",
+ &tx_de_emphasis);
} else if (pdata) {
+ if (pdata->extcon) {
+ dwc->edev = extcon_get_extcon_dev(pdata->extcon);
+ if (!dwc->edev) {
+ dev_vdbg(dev, "couldn't get extcon device\n");
+ return -EPROBE_DEFER;
+ }
+ }
dwc->maximum_speed = pdata->maximum_speed;
+ dwc->has_lpm_erratum = pdata->has_lpm_erratum;
+ if (pdata->lpm_nyet_threshold)
+ lpm_nyet_threshold = pdata->lpm_nyet_threshold;
+ dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend;
+ if (pdata->hird_threshold)
+ hird_threshold = pdata->hird_threshold;
dwc->needs_fifo_resize = pdata->tx_fifo_resize;
dwc->dr_mode = pdata->dr_mode;
+
+ dwc->disable_scramble_quirk = pdata->disable_scramble_quirk;
+ dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk;
+ dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk;
+ dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk;
+ dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk;
+ dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk;
+ dwc->lfps_filter_quirk = pdata->lfps_filter_quirk;
+ dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk;
+ dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk;
+ dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk;
+
+ dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk;
+ if (pdata->tx_de_emphasis)
+ tx_de_emphasis = pdata->tx_de_emphasis;
}
/* default to superspeed if no maximum_speed passed */
if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
dwc->maximum_speed = USB_SPEED_SUPER;
+ dwc->lpm_nyet_threshold = lpm_nyet_threshold;
+ dwc->tx_de_emphasis = tx_de_emphasis;
+
+ dwc->hird_threshold = hird_threshold
+ | (dwc->is_utmi_l1_suspend << 4);
+
ret = dwc3_core_get_phy(dwc);
if (ret)
goto err0;
spin_lock_irqsave(&dwc->lock, flags);
+ /* Save OTG state only if we're really using it */
+ if (dwc->current_mode == DWC3_GCTL_PRTCAP_OTG) {
+ dwc->ocfg = dwc3_readl(dwc->regs, DWC3_OCFG);
+ dwc->octl = dwc3_readl(dwc->regs, DWC3_OCTL);
+ dwc->oevt = dwc3_readl(dwc->regs, DWC3_OEVT);
+ dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN);
+ }
+
switch (dwc->dr_mode) {
- case USB_DR_MODE_OTG:
- dwc3_otg_suspend(dwc);
case USB_DR_MODE_PERIPHERAL:
+ case USB_DR_MODE_OTG:
dwc3_gadget_suspend(dwc);
/* FALLTHROUGH */
case USB_DR_MODE_HOST:
dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
dwc3_event_buffers_setup(dwc);
+ /* Restore OTG state only if we're really using it */
+ if (dwc->current_mode == DWC3_GCTL_PRTCAP_OTG) {
+ dwc3_writel(dwc->regs, DWC3_OCFG, dwc->ocfg);
+ dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl);
+ dwc3_writel(dwc->regs, DWC3_OEVT, dwc->oevt);
+ dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
+ }
+
switch (dwc->dr_mode) {
- case USB_DR_MODE_OTG:
- dwc3_otg_resume(dwc);
case USB_DR_MODE_PERIPHERAL:
+ case USB_DR_MODE_OTG:
dwc3_gadget_resume(dwc);
/* FALLTHROUGH */
case USB_DR_MODE_HOST:
index 9bc15d1c09904766710c3a1f649dd5eed6f04149..f3fa0b875ccd5e7f80623d39128eb6f44f79c95a 100644 (file)
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
+#include <linux/usb/otg-fsm.h>
#include <linux/phy/phy.h>
+#include <linux/extcon.h>
/* Global constants */
#define DWC3_EP0_BOUNCE_SIZE 512
#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4)
#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3)
#define DWC3_GCTL_DISSCRAMBLE (1 << 3)
+#define DWC3_GCTL_U2EXIT_LFPS (1 << 2)
#define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1)
#define DWC3_GCTL_DSBLCLKGTNG (1 << 0)
+/* Global Status Register */
+#define DWC3_GSTS_OTG_IP (1 << 10)
+#define DWC3_GSTS_BC_IP (1 << 9)
+#define DWC3_GSTS_ADP_IP (1 << 8)
+#define DWC3_GSTS_HOST_IP (1 << 7)
+#define DWC3_GSTS_DEVICE_IP (1 << 6)
+#define DWC3_GSTS_CSR_TIMEOUT (1 << 5)
+#define DWC3_GSTS_BUS_ERR_ADDR_VLD (1 << 4)
+
/* Global USB2 PHY Configuration Register */
#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31)
#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6)
/* Global USB3 PIPE Control Register */
#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31)
+#define DWC3_GUSB3PIPECTL_U2SSINP3OK (1 << 29)
+#define DWC3_GUSB3PIPECTL_REQP1P2P3 (1 << 24)
+#define DWC3_GUSB3PIPECTL_DEP1P2P3(n) ((n) << 19)
+#define DWC3_GUSB3PIPECTL_DEP1P2P3_MASK DWC3_GUSB3PIPECTL_DEP1P2P3(7)
+#define DWC3_GUSB3PIPECTL_DEP1P2P3_EN DWC3_GUSB3PIPECTL_DEP1P2P3(1)
+#define DWC3_GUSB3PIPECTL_DEPOCHANGE (1 << 18)
#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17)
+#define DWC3_GUSB3PIPECTL_LFPSFILT (1 << 9)
+#define DWC3_GUSB3PIPECTL_RX_DETOPOLL (1 << 8)
+#define DWC3_GUSB3PIPECTL_TX_DEEPH_MASK DWC3_GUSB3PIPECTL_TX_DEEPH(3)
+#define DWC3_GUSB3PIPECTL_TX_DEEPH(n) ((n) << 1)
/* Global TX Fifo Size Register */
#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
#define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) & (0x0f << 13)) >> 13)
#define DWC3_MAX_HIBER_SCRATCHBUFS 15
+/* Global HWPARAMS6 Register */
+#define DWC3_GHWPARAMS6_BCSUPPORT (1 << 14)
+#define DWC3_GHWPARAMS6_OTG3SUPPORT (1 << 13)
+#define DWC3_GHWPARAMS6_ADPSUPPORT (1 << 12)
+#define DWC3_GHWPARAMS6_HNPSUPPORT (1 << 11)
+#define DWC3_GHWPARAMS6_SRPSUPPORT (1 << 10)
+#define DWC3_GHWPARAMS6_EN_FPGA (1 << 7)
+
/* Global FIFO Space Register */
#define DWC3_GDBGFIFOSPACE_TXFIFO (0 << 5)
#define DWC3_GDBGFIFOSPACE_RXFIFO (1 << 5)
#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6))
/* These apply for core versions 1.94a and later */
-#define DWC3_DCTL_KEEP_CONNECT (1 << 19)
-#define DWC3_DCTL_L1_HIBER_EN (1 << 18)
-#define DWC3_DCTL_CRS (1 << 17)
-#define DWC3_DCTL_CSS (1 << 16)
+#define DWC3_DCTL_LPM_ERRATA_MASK DWC3_DCTL_LPM_ERRATA(0xf)
+#define DWC3_DCTL_LPM_ERRATA(n) ((n) << 20)
-#define DWC3_DCTL_INITU2ENA (1 << 12)
-#define DWC3_DCTL_ACCEPTU2ENA (1 << 11)
-#define DWC3_DCTL_INITU1ENA (1 << 10)
-#define DWC3_DCTL_ACCEPTU1ENA (1 << 9)
-#define DWC3_DCTL_TSTCTRL_MASK (0xf << 1)
+#define DWC3_DCTL_KEEP_CONNECT (1 << 19)
+#define DWC3_DCTL_L1_HIBER_EN (1 << 18)
+#define DWC3_DCTL_CRS (1 << 17)
+#define DWC3_DCTL_CSS (1 << 16)
+
+#define DWC3_DCTL_INITU2ENA (1 << 12)
+#define DWC3_DCTL_ACCEPTU2ENA (1 << 11)
+#define DWC3_DCTL_INITU1ENA (1 << 10)
+#define DWC3_DCTL_ACCEPTU1ENA (1 << 9)
+#define DWC3_DCTL_TSTCTRL_MASK (0xf << 1)
#define DWC3_DCTL_ULSTCHNGREQ_MASK (0x0f << 5)
#define DWC3_DCTL_ULSTCHNGREQ(n) (((n) << 5) & DWC3_DCTL_ULSTCHNGREQ_MASK)
#define DWC3_DEPCMD_TYPE_INTR 3
/* OTG Configuration Register */
-#define DWC3_OCFG_DISPWRCUTTOFF (1 << 5)
-#define DWC3_OCFG_HIBDISMASK (1 << 4)
-#define DWC3_OCFG_SFTRSTMASK (1 << 3)
-#define DWC3_OCFG_OTGVERSION (1 << 2)
-#define DWC3_OCFG_HNPCAP (1 << 1)
-#define DWC3_OCFG_SRPCAP (1 << 0)
+#define DWC3_OCFG_DISPWRCUTTOFF (1 << 5)
+#define DWC3_OCFG_HIBDISMASK (1 << 4)
+#define DWC3_OCFG_SFTRSTMASK (1 << 3)
+#define DWC3_OCFG_OTGVERSION (1 << 2)
+#define DWC3_OCFG_HNPCAP (1 << 1)
+#define DWC3_OCFG_SRPCAP (1 << 0)
/* OTG CTL Register */
-#define DWC3_OCTL_OTG3GOERR (1 << 7)
-#define DWC3_OCTL_PERIMODE (1 << 6)
-#define DWC3_OCTL_PRTPWRCTL (1 << 5)
-#define DWC3_OCTL_HNPREQ (1 << 4)
-#define DWC3_OCTL_SESREQ (1 << 3)
-#define DWC3_OCTL_TERMSELIDPULSE (1 << 2)
-#define DWC3_OCTL_DEVSETHNPEN (1 << 1)
-#define DWC3_OCTL_HOSTSETHNPEN (1 << 0)
+#define DWC3_OCTL_OTG3GOERR (1 << 7)
+#define DWC3_OCTL_PERIMODE (1 << 6)
+#define DWC3_OCTL_PRTPWRCTL (1 << 5)
+#define DWC3_OCTL_HNPREQ (1 << 4)
+#define DWC3_OCTL_SESREQ (1 << 3)
+#define DWC3_OCTL_TERMSELIDPULSE (1 << 2)
+#define DWC3_OCTL_DEVSETHNPEN (1 << 1)
+#define DWC3_OCTL_HSTSETHNPEN (1 << 0)
/* OTG Event Register */
-#define DWC3_OEVT_DEVICEMODE (1 << 31)
-#define DWC3_OEVT_XHCIRUNSTPSET (1 << 27)
-#define DWC3_OEVT_DEVRUNSTPSET (1 << 26)
-#define DWC3_OEVT_HIBENTRY (1 << 25)
-#define DWC3_OEVT_IDSTSCHNG (1 << 24)
-#define DWC3_OEVT_HRRCONFNOTIF (1 << 23)
-#define DWC3_OEVT_HRRINITNOTIF (1 << 22)
-#define DWC3_OEVT_ADEVIDLE (1 << 21)
-#define DWC3_OEVT_ADEVBHOSTEND (1 << 20)
-#define DWC3_OEVT_ADEVHOST (1 << 19)
-#define DWC3_OEVT_ADEVHNPCHNG (1 << 18)
-#define DWC3_OEVT_ADEVSRPDET (1 << 17)
-#define DWC3_OEVT_ADEVSESSENDDET (1 << 16)
-#define DWC3_OEVT_BDEVBHOSTEND (1 << 11)
-#define DWC3_OEVT_BDEVHNPCHNG (1 << 10)
-#define DWC3_OEVT_BDEVSESSVLDDET (1 << 9)
-#define DWC3_OEVT_BDEVVBUSCHNG (1 << 8)
-#define DWC3_OEVT_BSESSVLD (1 << 3)
-#define DWC3_OEVT_HOSTNEGSTS (1 << 2)
-#define DWC3_OEVT_SESSREQSTS (1 << 1)
-#define DWC3_OEVT_ERR (1 << 0)
+#define DWC3_OEVT_DEVICEMODE (1 << 31)
+#define DWC3_OEVT_XHCIRUNSTPSET (1 << 27)
+#define DWC3_OEVT_DEVRUNSTPSET (1 << 26)
+#define DWC3_OEVT_HIBENTRY (1 << 25)
+#define DWC3_OEVT_CONIDSTSCHNG (1 << 24)
+#define DWC3_OEVT_HRRCONFNOTIF (1 << 23)
+#define DWC3_OEVT_HRRINITNOTIF (1 << 22)
+#define DWC3_OEVT_ADEVIDLE (1 << 21)
+#define DWC3_OEVT_ADEVBHOSTEND (1 << 20)
+#define DWC3_OEVT_ADEVHOST (1 << 19)
+#define DWC3_OEVT_ADEVHNPCHNG (1 << 18)
+#define DWC3_OEVT_ADEVSRPDET (1 << 17)
+#define DWC3_OEVT_ADEVSESSENDDET (1 << 16)
+#define DWC3_OEVT_BDEVBHOSTEND (1 << 11)
+#define DWC3_OEVT_BDEVHNPCHNG (1 << 10)
+#define DWC3_OEVT_BDEVSESSVLDDET (1 << 9)
+#define DWC3_OEVT_BDEVVBUSCHNG (1 << 8)
+#define DWC3_OEVT_BSESSVLD (1 << 3)
+#define DWC3_OEVT_HSTNEGSTS (1 << 2)
+#define DWC3_OEVT_SESREQSTS (1 << 1)
+#define DWC3_OEVT_ERROR (1 << 0)
/* OTG Event Enable Register */
-#define DWC3_OEVTEN_XHCIRUNSTPSETEN (1 << 27)
-#define DWC3_OEVTEN_DEVRUNSTPSETEN (1 << 26)
-#define DWC3_OEVTEN_HIBENTRYEN (1 << 25)
-#define DWC3_OEVTEN_CONIDSTSCHNGEN (1 << 24)
-#define DWC3_OEVTEN_HRRCONFNOTIFEN (1 << 23)
-#define DWC3_OEVTEN_HRRINITNOTIFEN (1 << 22)
-#define DWC3_OEVTEN_ADEVIDLEEN (1 << 21)
-#define DWC3_OEVTEN_ADEVBHOSTENDEN (1 << 20)
-#define DWC3_OEVTEN_ADEVHOSTEN (1 << 19)
-#define DWC3_OEVTEN_ADEVHNPCHNGEN (1 << 18)
-#define DWC3_OEVTEN_ADEVSRPDETEN (1 << 17)
-#define DWC3_OEVTEN_ADEVSESSENDDETEN (1 << 16)
-#define DWC3_OEVTEN_BDEVHOSTENDEN (1 << 11)
-#define DWC3_OEVTEN_BDEVHNPCHNGEN (1 << 10)
-#define DWC3_OEVTEN_BDEVSESSVLDDETEN (1 << 9)
-#define DWC3_OEVTEN_BDEVVBUSCHNGEVNTEN (1 << 8)
+#define DWC3_OEVTEN_XHCIRUNSTPSETEN (1 << 27)
+#define DWC3_OEVTEN_DEVRUNSTPSETEN (1 << 26)
+#define DWC3_OEVTEN_HIBENTRYEN (1 << 25)
+#define DWC3_OEVTEN_CONIDSTSCHNGEN (1 << 24)
+#define DWC3_OEVTEN_HRRCONFNOTIFEN (1 << 23)
+#define DWC3_OEVTEN_HRRINITNOTIFEN (1 << 22)
+#define DWC3_OEVTEN_ADEVIDLEEN (1 << 21)
+#define DWC3_OEVTEN_ADEVBHOSTENDEN (1 << 20)
+#define DWC3_OEVTEN_ADEVHOSTEN (1 << 19)
+#define DWC3_OEVTEN_ADEVHNPCHNGEN (1 << 18)
+#define DWC3_OEVTEN_ADEVSRPDETEN (1 << 17)
+#define DWC3_OEVTEN_ADEVSESSENDDETEN (1 << 16)
+#define DWC3_OEVTEN_BDEVHOSTENDEN (1 << 11)
+#define DWC3_OEVTEN_BDEVHNPCHNGEN (1 << 10)
+#define DWC3_OEVTEN_BDEVSESSVLDDETEN (1 << 9)
+#define DWC3_OEVTEN_BDEVVBUSCHNGE (1 << 8)
/* OTG Status Register */
-#define DWC3_OSTS_DEVRUNSTP (1 << 13)
-#define DWC3_OSTS_XHCIRUNSTP (1 << 12)
-#define DWC3_OSTS_PERIPHERALSTATE (1 << 4)
-#define DWC3_OSTS_XHCIPORTPOWER (1 << 3)
-#define DWC3_OSTS_BSESVLD (1 << 2)
-#define DWC3_OSTS_VBUSVLD (1 << 1)
-#define DWC3_OSTS_CONIDSTS (1 << 0)
+#define DWC3_OSTS_DEVRUNSTP (1 << 13)
+#define DWC3_OSTS_XHCIRUNSTP (1 << 12)
+#define DWC3_OSTS_PERIPHERALSTATE (1 << 4)
+#define DWC3_OSTS_XHCIPRTPOWER (1 << 3)
+#define DWC3_OSTS_BSESVLD (1 << 2)
+#define DWC3_OSTS_VBUSVLD (1 << 1)
+#define DWC3_OSTS_CONIDSTS (1 << 0)
/* Structures */
__le64 dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
};
-struct dwc3_gadget {
- struct usb_gadget gadget;
- struct dwc3 *dwc;
-};
-
/**
* struct dwc3 - representation of our controller
* @ctrl_req: usb control request which is used for ep0
* @gadget_driver: pointer to the gadget driver
* @regs: base address for our registers
* @regs_size: address space size
+ * @oevten: otg interrupt enable mask copy
+ * @current_mode: current mode of operation written to PRTCAPDIR
* @nr_scratch: number of scratch buffers
* @num_event_buffers: calculated number of event buffers
* @u1u2: only used on revisions <1.83a for workaround
* @regset: debugfs pointer to regdump file
* @test_mode: true when we're entering a USB test mode
* @test_mode_nr: test feature selector
+ * @lpm_nyet_threshold: LPM NYET response threshold
+ * @hird_threshold: HIRD threshold
* @delayed_status: true when gadget driver asks for delayed status
* @ep0_bounced: true when we used bounce buffer
* @ep0_expect_in: true when we expect a DATA IN transfer
* @has_hibernation: true when dwc3 was configured with Hibernation
+ * @has_lpm_erratum: true when core was configured with LPM Erratum. Note that
+ * there's now way for software to detect this in runtime.
+ * @is_utmi_l1_suspend: the core asserts output signal
+ * 0 - utmi_sleep_n
+ * 1 - utmi_l1_suspend_n
* @is_selfpowered: true when we are selfpowered
+ * @is_fpga: true when we are using the FPGA board
* @needs_fifo_resize: not all users might want fifo resizing, flag it
* @pullups_connected: true when Run/Stop bit is set
* @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
* @start_config_issued: true when StartConfig command has been issued
* @three_stage_setup: set if we perform a three phase setup
+ * @disable_scramble_quirk: set if we enable the disable scramble quirk
+ * @u2exit_lfps_quirk: set if we enable u2exit lfps quirk
+ * @u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
+ * @req_p1p2p3_quirk: set if we enable request p1p2p3 quirk
+ * @del_p1p2p3_quirk: set if we enable delay p1p2p3 quirk
+ * @del_phy_power_chg_quirk: set if we enable delay phy power change quirk
+ * @lfps_filter_quirk: set if we enable LFPS filter quirk
+ * @rx_detect_poll_quirk: set if we enable rx_detect to polling lfps quirk
+ * @dis_u3_susphy_quirk: set if we disable usb3 suspend phy
+ * @dis_u2_susphy_quirk: set if we disable usb2 suspend phy
+ * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk
+ * @tx_de_emphasis: Tx de-emphasis value
+ * 0 - -6dB de-emphasis
+ * 1 - -3.5dB de-emphasis
+ * 2 - No de-emphasis
+ * 3 - Reserved
+ * @otg_has_srp: set if otg core supports SRP
+ * @otg_has_hnp_rsp: set if otg core supports HNP/RSP
+ * @otg_has_adp: set if otg core supports ADP
+ * @otg_has_bc: set if otg core supports BC
+ * @otg_has_otg3: set if otg core supports OTG v3.0
*/
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
struct dwc3_event_buffer **ev_buffs;
struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];
- struct dwc3_gadget *dwc_gadget;
+ struct usb_gadget gadget;
struct usb_gadget_driver *gadget_driver;
struct usb_phy *usb2_phy;
struct phy *usb2_generic_phy;
struct phy *usb3_generic_phy;
+ struct extcon_dev *edev; /* USB cable events ID & VBUS */
+ struct notifier_block otg_nb; /* notifier for USB cable events */
+ struct otg_fsm *fsm;
+
void __iomem *regs;
size_t regs_size;
u32 octl;
u32 oevt;
u32 oevten;
- u32 osts;
+ u32 current_mode;
u32 nr_scratch;
u32 num_event_buffers;
u32 u1u2;
u32 maximum_speed;
u32 revision;
- u32 iddig;
#define DWC3_REVISION_173A 0x5533173a
#define DWC3_REVISION_175A 0x5533175a
u8 test_mode;
u8 test_mode_nr;
+ u8 lpm_nyet_threshold;
+ u8 hird_threshold;
unsigned delayed_status:1;
unsigned ep0_bounced:1;
unsigned ep0_expect_in:1;
unsigned has_hibernation:1;
+ unsigned has_lpm_erratum:1;
+ unsigned is_utmi_l1_suspend:1;
unsigned is_selfpowered:1;
+ unsigned is_fpga:1;
unsigned needs_fifo_resize:1;
unsigned pullups_connected:1;
unsigned resize_fifos:1;
unsigned setup_packet_pending:1;
unsigned start_config_issued:1;
unsigned three_stage_setup:1;
+
+ unsigned disable_scramble_quirk:1;
+ unsigned u2exit_lfps_quirk:1;
+ unsigned u2ss_inp3_quirk:1;
+ unsigned req_p1p2p3_quirk:1;
+ unsigned del_p1p2p3_quirk:1;
+ unsigned del_phy_power_chg_quirk:1;
+ unsigned lfps_filter_quirk:1;
+ unsigned rx_detect_poll_quirk:1;
+ unsigned dis_u3_susphy_quirk:1;
+ unsigned dis_u2_susphy_quirk:1;
+
+ unsigned tx_de_emphasis_quirk:1;
+ unsigned tx_de_emphasis:2;
+
+ unsigned otg_has_srp:1;
+ unsigned otg_has_hnp_rsp:1;
+ unsigned otg_has_adp:1;
+ unsigned otg_has_bc:1;
+ unsigned otg_has_otg3:1;
};
/* -------------------------------------------------------------------------- */
/* prototypes */
void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
-int dwc3_core_gadget_helper(struct dwc3 *dwc);
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_host_init(struct dwc3 *dwc);
{ return 0; }
#endif
-#if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
-int dwc3_otg_init(struct dwc3 *dwc);
-void dwc3_otg_exit(struct dwc3 *dwc);
-void dwc3_otg_suspend(struct dwc3 *dwc);
-void dwc3_otg_resume(struct dwc3 *dwc);
-#else
-static inline int dwc3_otg_init(struct dwc3 *dwc)
-{ return 0; }
-static inline void dwc3_otg_exit(struct dwc3 *dwc)
-{ }
-static inline void dwc3_otg_suspend(struct dwc3 *dwc)
-{ }
-static inline void dwc3_otg_resume(struct dwc3 *dwc)
-{ }
-#endif
-
/* power management interface */
#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
int dwc3_gadget_suspend(struct dwc3 *dwc);
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 7b349ad045e5938b0a41936d7691dea4c90e4739..dbf3d332f2adb836ce1fe16aa79788745f29b5d3 100644 (file)
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
req->request.actual = 0;
req->request.status = -EINPROGRESS;
direction = !dwc->ep0_expect_in;
dwc->delayed_status = false;
- usb_gadget_set_state(&dwc_gadget->gadget, USB_STATE_CONFIGURED);
+ usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED);
if (dwc->ep0state == EP0_STATUS_PHASE)
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
struct usb_ctrlrequest *ctrl, int set)
{
struct dwc3_ep *dep;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
u32 recip;
u32 wValue;
u32 wIndex;
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
recip = ctrl->bRequestType & USB_RECIP_MASK;
- state = dwc_gadget->gadget.state;
+ state = dwc->gadget.state;
switch (recip) {
case USB_RECIP_DEVICE:
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
- enum usb_device_state state = dwc_gadget->gadget.state;
+ enum usb_device_state state = dwc->gadget.state;
u32 addr;
u32 reg;
@@ -517,28 +514,26 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
if (addr)
- usb_gadget_set_state(&dwc_gadget->gadget, USB_STATE_ADDRESS);
+ usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
else
- usb_gadget_set_state(&dwc_gadget->gadget, USB_STATE_DEFAULT);
+ usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
return 0;
}
static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
int ret;
spin_unlock(&dwc->lock);
- ret = dwc->gadget_driver->setup(&dwc_gadget->gadget, ctrl);
+ ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl);
spin_lock(&dwc->lock);
return ret;
}
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
- enum usb_device_state state = dwc_gadget->gadget.state;
+ enum usb_device_state state = dwc->gadget.state;
u32 cfg;
int ret;
u32 reg;
* to change the state on the next usb_ep_queue()
*/
if (ret == 0)
- usb_gadget_set_state(&dwc_gadget->gadget,
+ usb_gadget_set_state(&dwc->gadget,
USB_STATE_CONFIGURED);
/*
case USB_STATE_CONFIGURED:
ret = dwc3_ep0_delegate_req(dwc, ctrl);
if (!cfg && !ret)
- usb_gadget_set_state(&dwc_gadget->gadget,
+ usb_gadget_set_state(&dwc->gadget,
USB_STATE_ADDRESS);
break;
default:
static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
struct dwc3_ep *dep;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
- enum usb_device_state state = dwc_gadget->gadget.state;
+ enum usb_device_state state = dwc->gadget.state;
u16 wLength;
u16 wValue;
struct dwc3_ep *dep, struct dwc3_request *req)
{
int ret;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
req->direction = !!dep->number;
u32 transfer_size;
u32 maxpacket;
- ret = usb_gadget_map_request(&dwc_gadget->gadget, &req->request,
+ ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
if (ret) {
dev_dbg(dwc->dev, "failed to map request\n");
dwc->ep0_bounce_addr, transfer_size,
DWC3_TRBCTL_CONTROL_DATA);
} else {
- ret = usb_gadget_map_request(&dwc_gadget->gadget, &req->request,
+ ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
if (ret) {
dev_dbg(dwc->dev, "failed to map request\n");
index 70708395c79a26f15ca52d567484572ed3b4e132..45c3f9762e3fe9f5788c66a7b9635bb3462f3103 100644 (file)
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include <linux/usb/drd.h>
#include "core.h"
#include "gadget.h"
int status)
{
struct dwc3 *dwc = dep->dwc;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
int i;
if (req->queued) {
if (dwc->ep0_bounced && dep->number == 0)
dwc->ep0_bounced = false;
else
- usb_gadget_unmap_request(&dwc_gadget->gadget, &req->request,
+ usb_gadget_unmap_request(&dwc->gadget, &req->request,
req->direction);
dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
bool ignore)
{
struct dwc3_gadget_ep_cmd_params params;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
memset(¶ms, 0x00, sizeof(params));
| DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc));
/* Burst size is only needed in SuperSpeed mode */
- if (dwc_gadget->gadget.speed == USB_SPEED_SUPER) {
+ if (dwc->gadget.speed == USB_SPEED_SUPER) {
u32 burst = dep->endpoint.maxburst - 1;
params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst);
struct dwc3_gadget_ep_cmd_params params;
struct dwc3_request *req;
struct dwc3 *dwc = dep->dwc;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
int ret;
u32 cmd;
* here and stop, unmap, free and del each of the linked
* requests instead of what we do now.
*/
- usb_gadget_unmap_request(&dwc_gadget->gadget, &req->request,
+ usb_gadget_unmap_request(&dwc->gadget, &req->request,
req->direction);
list_del(&req->list);
return ret;
static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
int ret;
req->request.actual = 0;
@@ -1137,7 +1132,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
* This will also avoid Host cancelling URBs due to too
* many NAKs.
*/
- ret = usb_gadget_map_request(&dwc_gadget->gadget, &req->request,
+ ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->direction);
if (ret)
return ret;
static int dwc3_gadget_get_frame(struct usb_gadget *g)
{
- struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(g);
- struct dwc3 *dwc = dwc_gadget->dwc;
+ struct dwc3 *dwc = gadget_to_dwc(g);
u32 reg;
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
static int dwc3_gadget_wakeup(struct usb_gadget *g)
{
- struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(g);
- struct dwc3 *dwc = dwc_gadget->dwc;
+ struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long timeout;
unsigned long flags;
static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
int is_selfpowered)
{
- struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(g);
- struct dwc3 *dwc = dwc_gadget->dwc;
+ struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags;
spin_lock_irqsave(&dwc->lock, flags);
static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
{
- struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(g);
- struct dwc3 *dwc = dwc_gadget->dwc;
+ struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags;
int ret;
static int dwc3_gadget_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
- struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(g);
- struct dwc3 *dwc = dwc_gadget->dwc;
+ struct dwc3 *dwc = gadget_to_dwc(g);
struct dwc3_ep *dep;
unsigned long flags;
int ret = 0;
if (dwc->gadget_driver) {
dev_err(dwc->dev, "%s is already bound to %s\n",
- dwc_gadget->gadget.name,
+ dwc->gadget.name,
dwc->gadget_driver->driver.name);
ret = -EBUSY;
goto err1;
return ret;
}
-static int dwc3_gadget_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int dwc3_gadget_stop(struct usb_gadget *g)
{
- struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(g);
- struct dwc3 *dwc = dwc_gadget->dwc;
+ struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags;
int irq;
u8 num, u32 direction)
{
struct dwc3_ep *dep;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
u8 i;
for (i = 0; i < num; i++) {
dep->endpoint.maxburst = 1;
dep->endpoint.ops = &dwc3_gadget_ep0_ops;
if (!epnum)
- dwc_gadget->gadget.ep0 = &dep->endpoint;
+ dwc->gadget.ep0 = &dep->endpoint;
} else {
int ret;
dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list,
- &dwc_gadget->gadget.ep_list);
+ &dwc->gadget.ep_list);
ret = dwc3_alloc_trb_pool(dep);
if (ret)
static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
{
int ret;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
- INIT_LIST_HEAD(&dwc_gadget->gadget.ep_list);
+ INIT_LIST_HEAD(&dwc->gadget.ep_list);
ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
if (ret < 0) {
}
kfree(dep);
- dwc->eps[epnum] = NULL;
}
}
static void dwc3_disconnect_gadget(struct dwc3 *dwc)
{
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
-
if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
spin_unlock(&dwc->lock);
- dwc->gadget_driver->disconnect(&dwc_gadget->gadget);
+ dwc->gadget_driver->disconnect(&dwc->gadget);
spin_lock(&dwc->lock);
}
}
static void dwc3_suspend_gadget(struct dwc3 *dwc)
{
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
-
if (dwc->gadget_driver && dwc->gadget_driver->suspend) {
spin_unlock(&dwc->lock);
- dwc->gadget_driver->suspend(&dwc_gadget->gadget);
+ dwc->gadget_driver->suspend(&dwc->gadget);
spin_lock(&dwc->lock);
}
}
static void dwc3_resume_gadget(struct dwc3 *dwc)
{
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
-
if (dwc->gadget_driver && dwc->gadget_driver->resume) {
spin_unlock(&dwc->lock);
- dwc->gadget_driver->resume(&dwc_gadget->gadget);
+ dwc->gadget_driver->resume(&dwc->gadget);
spin_lock(&dwc->lock);
}
}
static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
{
int reg;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
dev_vdbg(dwc->dev, "%s\n", __func__);
dwc3_disconnect_gadget(dwc);
dwc->start_config_issued = false;
- dwc_gadget->gadget.speed = USB_SPEED_UNKNOWN;
+ dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->setup_packet_pending = false;
}
static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
{
u32 reg;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
dev_vdbg(dwc->dev, "%s\n", __func__);
}
/* after reset -> Default State */
- usb_gadget_set_state(&dwc_gadget->gadget, USB_STATE_DEFAULT);
+ usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
- if (dwc_gadget->gadget.speed != USB_SPEED_UNKNOWN)
+ if (dwc->gadget.speed != USB_SPEED_UNKNOWN)
dwc3_disconnect_gadget(dwc);
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
int ret;
u32 reg;
u8 speed;
dwc3_gadget_reset_interrupt(dwc);
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
- dwc_gadget->gadget.ep0->maxpacket = 512;
- dwc_gadget->gadget.speed = USB_SPEED_SUPER;
+ dwc->gadget.ep0->maxpacket = 512;
+ dwc->gadget.speed = USB_SPEED_SUPER;
break;
case DWC3_DCFG_HIGHSPEED:
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
- dwc_gadget->gadget.ep0->maxpacket = 64;
- dwc_gadget->gadget.speed = USB_SPEED_HIGH;
+ dwc->gadget.ep0->maxpacket = 64;
+ dwc->gadget.speed = USB_SPEED_HIGH;
break;
case DWC3_DCFG_FULLSPEED2:
case DWC3_DCFG_FULLSPEED1:
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
- dwc_gadget->gadget.ep0->maxpacket = 64;
- dwc_gadget->gadget.speed = USB_SPEED_FULL;
+ dwc->gadget.ep0->maxpacket = 64;
+ dwc->gadget.speed = USB_SPEED_FULL;
break;
case DWC3_DCFG_LOWSPEED:
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8);
- dwc_gadget->gadget.ep0->maxpacket = 8;
- dwc_gadget->gadget.speed = USB_SPEED_LOW;
+ dwc->gadget.ep0->maxpacket = 8;
+ dwc->gadget.speed = USB_SPEED_LOW;
break;
}
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
+ reg |= DWC3_DCTL_HIRD_THRES(dwc->hird_threshold);
+
/*
- * TODO: This should be configurable. For now using
- * maximum allowed HIRD threshold value of 0b1100
+ * When dwc3 revisions >= 2.40a, LPM Erratum is enabled and
+ * DCFG.LPMCap is set, core responses with an ACK and the
+ * BESL value in the LPM token is less than or equal to LPM
+ * NYET threshold.
*/
- reg |= DWC3_DCTL_HIRD_THRES(12);
+ WARN_ONCE(dwc->revision < DWC3_REVISION_240A
+ && dwc->has_lpm_erratum,
+ "LPM Erratum not available on dwc3 revisisions < 2.40a\n");
+
+ if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
+ reg |= DWC3_DCTL_LPM_ERRATA(dwc->lpm_nyet_threshold);
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
} else {
static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
{
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
-
dev_vdbg(dwc->dev, "%s\n", __func__);
/*
* implemented.
*/
- dwc->gadget_driver->resume(&dwc_gadget->gadget);
+ dwc->gadget_driver->resume(&dwc->gadget);
}
static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
return ret;
}
-static void dwc3_gadget_release(struct device *dev)
-{
- struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev);
- struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(gadget);
- struct dwc3 *dwc = dwc_gadget->dwc;
-
- dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
- dwc3_gadget_free_endpoints(dwc);
- dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
- dwc->ep0_bounce, dwc->ep0_bounce_addr);
- kfree(dwc->setup_buf);
- dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
- dwc->ep0_trb, dwc->ep0_trb_addr);
- dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
- dwc->ctrl_req, dwc->ctrl_req_addr);
- usb_drd_unregister_udc(dwc->dev);
- kfree(dwc_gadget);
-}
-
-static int dwc3_gadget_setup(void *data)
-{
- struct dwc3 *dwc = data;
- struct dwc3_gadget *dwc_gadget;
- struct usb_drd_gadget *drd_gadget;
- struct usb_drd_setup *gadget_setup;
- int ret;
-
- drd_gadget = kzalloc(sizeof(*drd_gadget), GFP_KERNEL);
- if (!drd_gadget) {
- ret = -ENOMEM;
- goto err1;
- }
-
- gadget_setup = kzalloc(sizeof(*gadget_setup), GFP_KERNEL);
- if (!gadget_setup) {
- ret = -ENOMEM;
- goto err2;
- }
-
- dwc_gadget = kzalloc(sizeof(*dwc_gadget), GFP_KERNEL);
- if (!dwc_gadget) {
- ret = -ENOMEM;
- goto err3;
- }
-
- drd_gadget->g_driver = dwc->gadget_driver;
-
- /*
- * Pass the DWC3 specific routines for
- * switching roles to the drd library
- */
- gadget_setup->ll_start = NULL;
- gadget_setup->ll_stop = NULL;
- gadget_setup->ll_release = dwc3_gadget_release;
- gadget_setup->data = (void *)dwc;
- drd_gadget->gadget_setup = gadget_setup;
-
- dwc_gadget->gadget.ops = &dwc3_gadget_ops;
- dwc_gadget->gadget.max_speed = USB_SPEED_SUPER;
- dwc_gadget->gadget.speed = USB_SPEED_UNKNOWN;
- dwc_gadget->gadget.sg_supported = true;
- dwc_gadget->gadget.name = "dwc3-gadget";
- dwc_gadget->dwc = dwc;
- drd_gadget->gadget = &dwc_gadget->gadget;
-
- /*
- * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
- * on ep out.
- */
- dwc_gadget->gadget.quirk_ep_out_aligned_size = true;
- dwc->dwc_gadget = dwc_gadget;
- usb_drd_register_udc(dwc->dev, drd_gadget);
-
- return 0;
-
-err3:
- kfree(gadget_setup);
-err2:
- kfree(drd_gadget);
-err1:
- return ret;
-}
-
/**
* dwc3_gadget_init - Initializes gadget related registers
* @dwc: pointer to our controller context structure
goto err3;
}
- ret = dwc3_gadget_setup(dwc);
- if (ret)
- goto err3;
+ dwc->gadget.ops = &dwc3_gadget_ops;
+ dwc->gadget.max_speed = USB_SPEED_SUPER;
+ dwc->gadget.speed = USB_SPEED_UNKNOWN;
+ dwc->gadget.sg_supported = true;
+ dwc->gadget.name = "dwc3-gadget";
+
+ /*
+ * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
+ * on ep out.
+ */
+ dwc->gadget.quirk_ep_out_aligned_size = true;
/*
* REVISIT: Here we should clear all pending IRQs to be
if (ret)
goto err4;
- ret = usb_add_gadget_udc_release(dwc->dev, &dwc->dwc_gadget->gadget,
- dwc3_gadget_release);
+ ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to register udc\n");
goto err4;
return 0;
err4:
- usb_drd_unregister_udc(dwc->dev);
dwc3_gadget_free_endpoints(dwc);
dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
dwc->ep0_bounce, dwc->ep0_bounce_addr);
void dwc3_gadget_exit(struct dwc3 *dwc)
{
- struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
+ usb_del_gadget_udc(&dwc->gadget);
+ dwc3_gadget_free_endpoints(dwc);
- if (usb_drd_get_state(dwc->dev) & DRD_DEVICE_REGISTERED) {
- usb_del_gadget_udc(&dwc_gadget->gadget);
-
- dwc3_gadget_free_endpoints(dwc);
-
- dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
- dwc->ep0_bounce, dwc->ep0_bounce_addr);
+ dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
+ dwc->ep0_bounce, dwc->ep0_bounce_addr);
- kfree(dwc->setup_buf);
+ kfree(dwc->setup_buf);
- dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
- dwc->ep0_trb, dwc->ep0_trb_addr);
+ dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+ dwc->ep0_trb, dwc->ep0_trb_addr);
- dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
- dwc->ctrl_req, dwc->ctrl_req_addr);
- }
+ dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
+ dwc->ctrl_req, dwc->ctrl_req_addr);
}
int dwc3_gadget_suspend(struct dwc3 *dwc)
{
+ if (!dwc->gadget_driver)
+ return 0;
+
if (dwc->pullups_connected) {
dwc3_gadget_disable_irq(dwc);
dwc3_gadget_run_stop(dwc, false, true);
dwc->pullups_connected = true;
}
- if (dwc->eps[0] && dwc->eps[1]) {
- __dwc3_gadget_ep_disable(dwc->eps[0]);
- __dwc3_gadget_ep_disable(dwc->eps[1]);
- }
+ __dwc3_gadget_ep_disable(dwc->eps[0]);
+ __dwc3_gadget_ep_disable(dwc->eps[1]);
dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
struct dwc3_ep *dep;
int ret;
- if (dwc->eps[0] && dwc->eps[1]) {
- /* Start with SuperSpeed Default */
- dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
+ if (!dwc->gadget_driver)
+ return 0;
- dep = dwc->eps[0];
- ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc,
- NULL, false);
- if (ret)
- goto err0;
+ /* Start with SuperSpeed Default */
+ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
- dep = dwc->eps[1];
- ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc,
- NULL, false);
- if (ret)
- goto err1;
+ dep = dwc->eps[0];
+ ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+ if (ret)
+ goto err0;
- /* begin to receive SETUP packets */
- dwc->ep0state = EP0_SETUP_PHASE;
- dwc3_ep0_out_start(dwc);
+ dep = dwc->eps[1];
+ ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+ if (ret)
+ goto err1;
- dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
+ /* begin to receive SETUP packets */
+ dwc->ep0state = EP0_SETUP_PHASE;
+ dwc3_ep0_out_start(dwc);
- if (dwc->pullups_connected) {
- dwc3_gadget_enable_irq(dwc);
- dwc3_gadget_run_stop(dwc, true, false);
- }
+ dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
+
+ if (dwc->pullups_connected) {
+ dwc3_gadget_enable_irq(dwc);
+ dwc3_gadget_run_stop(dwc, true, false);
}
+
return 0;
err1:
index 1dfd9381aeb306b25e5a700c1f7f77a675e95d36..9b68577105ee2ea5baf8c69dcdc28edc2d58f43c 100644 (file)
struct dwc3;
#define to_dwc3_ep(ep) (container_of(ep, struct dwc3_ep, endpoint))
#define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget))
-#define gadget_to_dwc_gadget(g) (container_of(g, struct dwc3_gadget, gadget))
/* DEPCFG parameter 1 */
#define DWC3_DEPCFG_INT_NUM(n) ((n) << 0)
index 257b5b56e6d54f699212eaa106b6ca66b21bfdbe..dcb8ca08459892a3979a56c83addce299aef13c0 100644 (file)
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
#ifdef CONFIG_DWC3_HOST_USB3_LPM_ENABLE
pdata.usb3_lpm_capable = 1;
#endif
- pdata.usb_drd_support = 1;
- pdata.usb_needs_lhc_reset = 1;
ret = platform_device_add_data(xhci, &pdata, sizeof(pdata));
if (ret) {
diff --git a/drivers/usb/dwc3/otg.c b/drivers/usb/dwc3/otg.c
--- a/drivers/usb/dwc3/otg.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * otg.c - DesignWare USB3 DRD Controller OTG
- *
- * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
- *
- * Authors: George Cherian <george.cherian@ti.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 of
- * the License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-
-#include <linux/usb/drd.h>
-#include "core.h"
-#include "io.h"
-
-#define DWC3_GSTS_OTG_IP (1 << 10)
-#define DWC3_OSTS_A_IDLE 0x0
-
-static irqreturn_t dwc3_otg_interrupt(int irq , void *_dwc)
-{
- struct dwc3 *dwc = _dwc;
- u32 reg;
-
- spin_lock(&dwc->lock);
- reg = dwc3_readl(dwc->regs, DWC3_GSTS);
- if (reg & DWC3_GSTS_OTG_IP) {
- reg = dwc3_readl(dwc->regs, DWC3_OEVT);
- dev_vdbg(dwc->dev, "OTG Interrupt %x\n", reg);
- dwc3_writel(dwc->regs, DWC3_OEVT, reg);
- spin_unlock(&dwc->lock);
- return IRQ_WAKE_THREAD;
- }
-
- spin_unlock(&dwc->lock);
- return IRQ_NONE;
-}
-
-static irqreturn_t dwc3_otg_thread_interrupt(int irq, void *_dwc)
-{
- struct dwc3 *dwc = _dwc;
- u32 reg = dwc3_readl(dwc->regs, DWC3_OSTS);
-
- dev_vdbg(dwc->dev, "OTG thread interrupt, OSTS 0x04%x, prev iddig %d\n",
- reg, dwc->iddig);
-
- if ((reg & DWC3_OSTS_CONIDSTS) == dwc->iddig)
- goto out;
- else
- dwc->iddig = reg & DWC3_OSTS_CONIDSTS;
-
- if ((reg & DWC3_OSTS_CONIDSTS)) {
- usb_drd_stop_hcd(dwc->dev);
- dwc3_writel(dwc->regs, DWC3_OCFG, DWC3_OCFG_SFTRSTMASK);
- dwc3_writel(dwc->regs, DWC3_OCTL,
- DWC3_OCTL_SESREQ | DWC3_OCTL_PERIMODE);
- if (usb_drd_get_state(dwc->dev) & DRD_DEVICE_REGISTERED) {
- usb_drd_start_udc(dwc->dev);
- } else {
- dwc3_core_gadget_helper(dwc);
- dwc3_gadget_init(dwc);
- }
- dwc3_writel(dwc->regs, DWC3_OEVTEN,
- DWC3_OEVTEN_CONIDSTSCHNGEN);
- } else if (!(reg & DWC3_OSTS_CONIDSTS)) {
- usb_drd_stop_udc(dwc->dev);
- dwc3_writel(dwc->regs, DWC3_OCFG,
- DWC3_OCFG_DISPWRCUTTOFF | DWC3_OCFG_SFTRSTMASK);
- dwc3_writel(dwc->regs, DWC3_OCTL, DWC3_OCTL_PRTPWRCTL);
- if (usb_drd_get_state(dwc->dev) & DRD_HOST_REGISTERED)
- usb_drd_start_hcd(dwc->dev);
- else
- dwc3_host_init(dwc);
-
- dwc3_writel(dwc->regs, DWC3_OEVTEN,
- DWC3_OEVTEN_CONIDSTSCHNGEN);
- }
-
-out:
- return IRQ_HANDLED;
-}
-
-int dwc3_otg_init(struct dwc3 *dwc)
-{
- u32 reg, ret;
-
- usb_drd_add(dwc->dev);
- dwc3_writel(dwc->regs, DWC3_OEVT, 0xFFFF);
- if (dwc->otg_irq > 0) {
- ret = devm_request_threaded_irq(dwc->dev, dwc->otg_irq,
- dwc3_otg_interrupt,
- dwc3_otg_thread_interrupt,
- IRQF_SHARED, "dwc3-otg", dwc);
- } else {
- WARN(1, "Trying to request invalid otg_irq");
- return -ENODEV;
- }
-
- dwc3_writel(dwc->regs, DWC3_OEVTEN, DWC3_OEVTEN_CONIDSTSCHNGEN);
- dwc3_writel(dwc->regs, DWC3_OCTL, DWC3_OCTL_PERIMODE);
-
- reg = dwc3_readl(dwc->regs, DWC3_OSTS);
- if ((reg & DWC3_OSTS_CONIDSTS)) {
- dev_vdbg(dwc->dev, "Gadget init\n");
- dwc3_writel(dwc->regs, DWC3_OCFG, DWC3_OCFG_SFTRSTMASK);
- dwc3_writel(dwc->regs, DWC3_OCTL,
- DWC3_OCTL_SESREQ | DWC3_OCTL_PERIMODE);
- dwc3_gadget_init(dwc);
- dwc3_writel(dwc->regs, DWC3_OEVTEN,
- DWC3_OEVTEN_CONIDSTSCHNGEN);
-
- } else if (!(reg & DWC3_OSTS_CONIDSTS)) {
- unsigned wait = 100;
-
- dev_vdbg(dwc->dev, "Host init\n");
- dwc3_writel(dwc->regs, DWC3_OCFG,
- DWC3_OCFG_DISPWRCUTTOFF | DWC3_OCFG_SFTRSTMASK);
- /*
- * We need 2 seperate writes to OCTL register.
- * First to set to HOST mode and then to enable the PORT power
- * If written in single shot devices never get detected at
- * boot time. This is because the OTG internal state machine
- * disables Port power when it enters A_IDLE.
- * Based on experiments, it needs almost 50ms to transition to
- * A_IDLE.
- */
- dwc3_writel(dwc->regs, DWC3_OCTL, 0x0);
- do {
- u32 reg;
-
- reg = ((dwc3_readl(dwc->regs, DWC3_OSTS) >> 8) & 0xf);
- if (reg == DWC3_OSTS_A_IDLE)
- break;
- wait--;
- usleep_range(1000, 2000);
- } while (wait);
-
- if (!wait) {
- dev_err(dwc->dev, "Timedout while waiting transition to A_IDLE\n");
- return -ETIMEDOUT;
- }
-
- dwc3_writel(dwc->regs, DWC3_OCTL, DWC3_OCTL_PRTPWRCTL);
- dwc3_host_init(dwc);
- dwc3_writel(dwc->regs, DWC3_OEVTEN,
- DWC3_OEVTEN_CONIDSTSCHNGEN);
- }
-
- dwc->iddig = reg & DWC3_OSTS_CONIDSTS;
-
- return 0;
-}
-
-void dwc3_otg_suspend(struct dwc3 *dwc)
-{
- dwc->ocfg = dwc3_readl(dwc->regs, DWC3_OCFG);
- dwc->octl = dwc3_readl(dwc->regs, DWC3_OCTL);
- dwc->oevt = dwc3_readl(dwc->regs, DWC3_OEVT);
- dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN);
- dwc->osts = dwc3_readl(dwc->regs, DWC3_OSTS);
-}
-
-void dwc3_otg_resume(struct dwc3 *dwc)
-{
- dwc3_writel(dwc->regs, DWC3_OCFG, dwc->ocfg);
- dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl);
- dwc3_writel(dwc->regs, DWC3_OEVT, dwc->oevt);
- dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
- dwc3_writel(dwc->regs, DWC3_OSTS, dwc->osts);
-}
index 7db34f00b89ab8fec3b0e1ef9b372e3c853c7eaf..117edd099f5fd338e38af80a872174aae1edd368 100644 (file)
enum usb_device_speed maximum_speed;
enum usb_dr_mode dr_mode;
bool tx_fifo_resize;
+
+ unsigned is_utmi_l1_suspend:1;
+ u8 hird_threshold;
+
+ u8 lpm_nyet_threshold;
+
+ unsigned disable_scramble_quirk:1;
+ unsigned has_lpm_erratum:1;
+ unsigned u2exit_lfps_quirk:1;
+ unsigned u2ss_inp3_quirk:1;
+ unsigned req_p1p2p3_quirk:1;
+ unsigned del_p1p2p3_quirk:1;
+ unsigned del_phy_power_chg_quirk:1;
+ unsigned lfps_filter_quirk:1;
+ unsigned rx_detect_poll_quirk:1;
+ unsigned dis_u3_susphy_quirk:1;
+ unsigned dis_u2_susphy_quirk:1;
+
+ unsigned tx_de_emphasis_quirk:1;
+ unsigned tx_de_emphasis:2;
+
+ const char *extcon; /* extcon name for USB cable events ID/VBUS */
};
index fd13ef0a96c9c2611182940a5a028d67bef8df33..5c822afb6d70fc1ae2b8308678b1c0a400d70d23 100644 (file)
a module parameter as well.
If unsure, say 2.
-#
-# USB Peripheral Controller Support
-#
-# The order here is alphabetical, except that integrated controllers go
-# before discrete ones so they will be the initial/default value:
-# - integrated/SOC controllers first
-# - licensed IP used in both SOC and discrete versions
-# - discrete ones (including all PCI-only controllers)
-# - debug/dummy gadget+hcd is last.
-#
-menu "USB Peripheral Controller"
-
-#
-# Integrated controllers
-#
-
-config USB_AT91
- tristate "Atmel AT91 USB Device Port"
- depends on ARCH_AT91
- help
- Many Atmel AT91 processors (such as the AT91RM2000) have a
- full speed USB Device Port with support for five configurable
- endpoints (plus endpoint zero).
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "at91_udc" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_LPC32XX
- tristate "LPC32XX USB Peripheral Controller"
- depends on ARCH_LPC32XX
- select USB_ISP1301
- help
- This option selects the USB device controller in the LPC32xx SoC.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "lpc32xx_udc" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_ATMEL_USBA
- tristate "Atmel USBA"
- depends on AVR32 || ARCH_AT91
- help
- USBA is the integrated high-speed USB Device controller on
- the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
-
-config USB_BCM63XX_UDC
- tristate "Broadcom BCM63xx Peripheral Controller"
- depends on BCM63XX
- help
- Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
- high speed USB Device Port with support for four fixed endpoints
- (plus endpoint zero).
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "bcm63xx_udc".
-
-config USB_FSL_USB2
- tristate "Freescale Highspeed USB DR Peripheral Controller"
- depends on FSL_SOC || ARCH_MXC
- select USB_FSL_MPH_DR_OF if OF
- help
- Some of Freescale PowerPC and i.MX processors have a High Speed
- Dual-Role(DR) USB controller, which supports device mode.
-
- The number of programmable endpoints is different through
- SOC revisions.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "fsl_usb2_udc" and force
- all gadget drivers to also be dynamically linked.
-
-config USB_FUSB300
- tristate "Faraday FUSB300 USB Peripheral Controller"
- depends on !PHYS_ADDR_T_64BIT && HAS_DMA
- help
- Faraday usb device controller FUSB300 driver
-
-config USB_FOTG210_UDC
- depends on HAS_DMA
- tristate "Faraday FOTG210 USB Peripheral Controller"
- help
- Faraday USB2.0 OTG controller which can be configured as
- high speed or full speed USB device. This driver supppors
- Bulk Transfer so far.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "fotg210_udc".
-
-config USB_GR_UDC
- tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
- depends on HAS_DMA
- help
- Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
- VHDL IP core library.
-
-config USB_OMAP
- tristate "OMAP USB Device Controller"
- depends on ARCH_OMAP1
- select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
- help
- Many Texas Instruments OMAP processors have flexible full
- speed USB device controllers, with support for up to 30
- endpoints (plus endpoint zero). This driver supports the
- controller in the OMAP 1611, and should work with controllers
- in other OMAP processors too, given minor tweaks.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "omap_udc" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_PXA25X
- tristate "PXA 25x or IXP 4xx"
- depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
- help
- Intel's PXA 25x series XScale ARM-5TE processors include
- an integrated full speed USB 1.1 device controller. The
- controller in the IXP 4xx series is register-compatible.
-
- It has fifteen fixed-function endpoints, as well as endpoint
- zero (for control transfers).
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "pxa25x_udc" and force all
- gadget drivers to also be dynamically linked.
-
-# if there's only one gadget driver, using only two bulk endpoints,
-# don't waste memory for the other endpoints
-config USB_PXA25X_SMALL
- depends on USB_PXA25X
- bool
- default n if USB_ETH_RNDIS
- default y if USB_ZERO
- default y if USB_ETH
- default y if USB_G_SERIAL
-
-config USB_R8A66597
- tristate "Renesas R8A66597 USB Peripheral Controller"
- depends on HAS_DMA
- help
- R8A66597 is a discrete USB host and peripheral controller chip that
- supports both full and high speed USB 2.0 data transfers.
- It has nine configurable endpoints, and endpoint zero.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "r8a66597_udc" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_RENESAS_USBHS_UDC
- tristate 'Renesas USBHS controller'
- depends on USB_RENESAS_USBHS
- help
- Renesas USBHS is a discrete USB host and peripheral controller chip
- that supports both full and high speed USB 2.0 data transfers.
- It has nine or more configurable endpoints, and endpoint zero.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "renesas_usbhs" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_PXA27X
- tristate "PXA 27x"
- help
- Intel's PXA 27x series XScale ARM v5TE processors include
- an integrated full speed USB 1.1 device controller.
-
- It has up to 23 endpoints, as well as endpoint zero (for
- control transfers).
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "pxa27x_udc" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_S3C_HSOTG
- depends on ARM
- tristate "Designware/S3C HS/OtG USB Device controller"
- help
- The Designware USB2.0 high-speed gadget controller
- integrated into many SoCs.
-
-config USB_S3C2410
- tristate "S3C2410 USB Device Controller"
- depends on ARCH_S3C24XX
- help
- Samsung's S3C2410 is an ARM-4 processor with an integrated
- full speed USB 1.1 device controller. It has 4 configurable
- endpoints, as well as endpoint zero (for control transfers).
-
- This driver has been tested on the S3C2410, S3C2412, and
- S3C2440 processors.
-
-config USB_S3C2410_DEBUG
- boolean "S3C2410 udc debug messages"
- depends on USB_S3C2410
-
-config USB_S3C_HSUDC
- tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
- depends on ARCH_S3C24XX
- help
- Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
- integrated with dual speed USB 2.0 device controller. It has
- 8 endpoints, as well as endpoint zero.
-
- This driver has been tested on S3C2416 and S3C2450 processors.
-
-config USB_MV_UDC
- tristate "Marvell USB2.0 Device Controller"
- depends on HAS_DMA
- help
- Marvell Socs (including PXA and MMP series) include a high speed
- USB2.0 OTG controller, which can be configured as high speed or
- full speed USB peripheral.
-
-config USB_MV_U3D
- depends on HAS_DMA
- tristate "MARVELL PXA2128 USB 3.0 controller"
- help
- MARVELL PXA2128 Processor series include a super speed USB3.0 device
- controller, which support super speed USB peripheral.
-
-#
-# Controllers available in both integrated and discrete versions
-#
-
-config USB_M66592
- tristate "Renesas M66592 USB Peripheral Controller"
- help
- M66592 is a discrete USB peripheral controller chip that
- supports both full and high speed USB 2.0 data transfers.
- It has seven configurable endpoints, and endpoint zero.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "m66592_udc" and force all
- gadget drivers to also be dynamically linked.
-
-#
-# Controllers available only in discrete form (and all PCI controllers)
-#
-
-config USB_AMD5536UDC
- tristate "AMD5536 UDC"
- depends on PCI
- help
- The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
- It is a USB Highspeed DMA capable USB device controller. Beside ep0
- it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
- The UDC port supports OTG operation, and may be used as a host port
- if it's not being used to implement peripheral or OTG roles.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "amd5536udc" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_FSL_QE
- tristate "Freescale QE/CPM USB Device Controller"
- depends on FSL_SOC && (QUICC_ENGINE || CPM)
- help
- Some of Freescale PowerPC processors have a Full Speed
- QE/CPM2 USB controller, which support device mode with 4
- programmable endpoints. This driver supports the
- controller in the MPC8360 and MPC8272, and should work with
- controllers having QE or CPM2, given minor tweaks.
-
- Set CONFIG_USB_GADGET to "m" to build this driver as a
- dynamically linked module called "fsl_qe_udc".
-
-config USB_NET2272
- tristate "PLX NET2272"
- help
- PLX NET2272 is a USB peripheral controller which supports
- both full and high speed USB 2.0 data transfers.
-
- It has three configurable endpoints, as well as endpoint zero
- (for control transfer).
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "net2272" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_NET2272_DMA
- boolean "Support external DMA controller"
- depends on USB_NET2272 && HAS_DMA
- help
- The NET2272 part can optionally support an external DMA
- controller, but your board has to have support in the
- driver itself.
-
- If unsure, say "N" here. The driver works fine in PIO mode.
-
-config USB_NET2280
- tristate "NetChip 228x"
- depends on PCI
- help
- NetChip 2280 / 2282 is a PCI based USB peripheral controller which
- supports both full and high speed USB 2.0 data transfers.
-
- It has six configurable endpoints, as well as endpoint zero
- (for control transfers) and several endpoints with dedicated
- functions.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "net2280" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_GOKU
- tristate "Toshiba TC86C001 'Goku-S'"
- depends on PCI
- help
- The Toshiba TC86C001 is a PCI device which includes controllers
- for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
-
- The device controller has three configurable (bulk or interrupt)
- endpoints, plus endpoint zero (for control transfers).
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "goku_udc" and to force all
- gadget drivers to also be dynamically linked.
-
-config USB_EG20T
- tristate "Intel QUARK X1000/EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
- depends on PCI
- help
- This is a USB device driver for EG20T PCH.
- EG20T PCH is the platform controller hub that is used in Intel's
- general embedded platform. EG20T PCH has USB device interface.
- Using this interface, it is able to access system devices connected
- to USB device.
- This driver enables USB device function.
- USB device is a USB peripheral controller which
- supports both full and high speed USB 2.0 data transfers.
- This driver supports both control transfer and bulk transfer modes.
- This driver dose not support interrupt transfer or isochronous
- transfer modes.
-
- This driver also can be used for LAPIS Semiconductor's ML7213 which is
- for IVI(In-Vehicle Infotainment) use.
- ML7831 is for general purpose use.
- ML7213/ML7831 is companion chip for Intel Atom E6xx series.
- ML7213/ML7831 is completely compatible for Intel EG20T PCH.
-
- This driver can be used with Intel's Quark X1000 SOC platform
-#
-# LAST -- dummy/emulated controller
-#
-
-config USB_DUMMY_HCD
- tristate "Dummy HCD (DEVELOPMENT)"
- depends on USB=y || (USB=m && USB_GADGET=m)
- help
- This host controller driver emulates USB, looping all data transfer
- requests back to a USB "gadget driver" in the same host. The host
- side is the master; the gadget side is the slave. Gadget drivers
- can be high, full, or low speed; and they have access to endpoints
- like those from NET2280, PXA2xx, or SA1100 hardware.
-
- This may help in some stages of creating a driver to embed in a
- Linux device, since it lets you debug several parts of the gadget
- driver without its hardware or drivers being involved.
-
- Since such a gadget side driver needs to interoperate with a host
- side Linux-USB device driver, this may help to debug both sides
- of a USB protocol stack.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "dummy_hcd" and force all
- gadget drivers to also be dynamically linked.
-
-# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears
-# first and will be selected by default.
-
-endmenu
+source "drivers/usb/gadget/udc/Kconfig"
#
# USB Gadget Drivers
implemented in kernel space (for instance Ethernet, serial or
mass storage) and other are implemented in user space.
-config USB_ZERO
- tristate "Gadget Zero (DEVELOPMENT)"
- select USB_LIBCOMPOSITE
- select USB_F_SS_LB
- help
- Gadget Zero is a two-configuration device. It either sinks and
- sources bulk data; or it loops back a configurable number of
- transfers. It also implements control requests, for "chapter 9"
- conformance. The driver needs only two bulk-capable endpoints, so
- it can work on top of most device-side usb controllers. It's
- useful for testing, and is also a working example showing how
- USB "gadget drivers" can be written.
-
- Make this be the first driver you try using on top of any new
- USB peripheral controller driver. Then you can use host-side
- test software, like the "usbtest" driver, to put your hardware
- and its driver through a basic set of functional tests.
-
- Gadget Zero also works with the host-side "usb-skeleton" driver,
- and with many kinds of host-side test software. You may need
- to tweak product and vendor IDs before host software knows about
- this device, and arrange to select an appropriate configuration.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_zero".
-
-config USB_ZERO_HNPTEST
- boolean "HNP Test Device"
- depends on USB_ZERO && USB_OTG
- help
- You can configure this device to enumerate using the device
- identifiers of the USB-OTG test device. That means that when
- this gadget connects to another OTG device, with this one using
- the "B-Peripheral" role, that device will use HNP to let this
- one serve as the USB host instead (in the "B-Host" role).
-
-config USB_AUDIO
- tristate "Audio Gadget"
- depends on SND
- select USB_LIBCOMPOSITE
- select SND_PCM
- help
- This Gadget Audio driver is compatible with USB Audio Class
- specification 2.0. It implements 1 AudioControl interface,
- 1 AudioStreaming Interface each for USB-OUT and USB-IN.
- Number of channels, sample rate and sample size can be
- specified as module parameters.
- This driver doesn't expect any real Audio codec to be present
- on the device - the audio streams are simply sinked to and
- sourced from a virtual ALSA sound card created. The user-space
- application may choose to do whatever it wants with the data
- received from the USB Host and choose to provide whatever it
- wants as audio data to the USB Host.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_audio".
-
-config GADGET_UAC1
- bool "UAC 1.0 (Legacy)"
- depends on USB_AUDIO
- help
- If you instead want older UAC Spec-1.0 driver that also has audio
- paths hardwired to the Audio codec chip on-board and doesn't work
- without one.
-
-config USB_ETH
- tristate "Ethernet Gadget (with CDC Ethernet support)"
- depends on NET
- select USB_LIBCOMPOSITE
- select USB_U_ETHER
- select USB_F_ECM
- select USB_F_SUBSET
- select CRC32
- help
- This driver implements Ethernet style communication, in one of
- several ways:
-
- - The "Communication Device Class" (CDC) Ethernet Control Model.
- That protocol is often avoided with pure Ethernet adapters, in
- favor of simpler vendor-specific hardware, but is widely
- supported by firmware for smart network devices.
-
- - On hardware can't implement that protocol, a simple CDC subset
- is used, placing fewer demands on USB.
-
- - CDC Ethernet Emulation Model (EEM) is a newer standard that has
- a simpler interface that can be used by more USB hardware.
-
- RNDIS support is an additional option, more demanding than than
- subset.
-
- Within the USB device, this gadget driver exposes a network device
- "usbX", where X depends on what other networking devices you have.
- Treat it like a two-node Ethernet link: host, and gadget.
-
- The Linux-USB host-side "usbnet" driver interoperates with this
- driver, so that deep I/O queues can be supported. On 2.4 kernels,
- use "CDCEther" instead, if you're using the CDC option. That CDC
- mode should also interoperate with standard CDC Ethernet class
- drivers on other host operating systems.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_ether".
-
-config USB_ETH_RNDIS
- bool "RNDIS support"
- depends on USB_ETH
- select USB_LIBCOMPOSITE
- select USB_F_RNDIS
- default y
- help
- Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
- and Microsoft provides redistributable binary RNDIS drivers for
- older versions of Windows.
-
- If you say "y" here, the Ethernet gadget driver will try to provide
- a second device configuration, supporting RNDIS to talk to such
- Microsoft USB hosts.
-
- To make MS-Windows work with this, use Documentation/usb/linux.inf
- as the "driver info file". For versions of MS-Windows older than
- XP, you'll need to download drivers from Microsoft's website; a URL
- is given in comments found in that info file.
-
-config USB_ETH_EEM
- bool "Ethernet Emulation Model (EEM) support"
- depends on USB_ETH
- select USB_LIBCOMPOSITE
- select USB_F_EEM
- default n
- help
- CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
- and therefore can be supported by more hardware. Technically ECM and
- EEM are designed for different applications. The ECM model extends
- the network interface to the target (e.g. a USB cable modem), and the
- EEM model is for mobile devices to communicate with hosts using
- ethernet over USB. For Linux gadgets, however, the interface with
- the host is the same (a usbX device), so the differences are minimal.
-
- If you say "y" here, the Ethernet gadget driver will use the EEM
- protocol rather than ECM. If unsure, say "n".
-
-config USB_G_NCM
- tristate "Network Control Model (NCM) support"
- depends on NET
- select USB_LIBCOMPOSITE
- select USB_U_ETHER
- select USB_F_NCM
- select CRC32
- help
- This driver implements USB CDC NCM subclass standard. NCM is
- an advanced protocol for Ethernet encapsulation, allows grouping
- of several ethernet frames into one USB transfer and different
- alignment possibilities.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_ncm".
-
-config USB_GADGETFS
- tristate "Gadget Filesystem"
- help
- This driver provides a filesystem based API that lets user mode
- programs implement a single-configuration USB device, including
- endpoint I/O and control requests that don't relate to enumeration.
- All endpoints, transfer speeds, and transfer types supported by
- the hardware are available, through read() and write() calls.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "gadgetfs".
-
-config USB_FUNCTIONFS
- tristate "Function Filesystem"
- select USB_LIBCOMPOSITE
- select USB_F_FS
- select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
- help
- The Function Filesystem (FunctionFS) lets one create USB
- composite functions in user space in the same way GadgetFS
- lets one create USB gadgets in user space. This allows creation
- of composite gadgets such that some of the functions are
- implemented in kernel space (for instance Ethernet, serial or
- mass storage) and other are implemented in user space.
-
- If you say "y" or "m" here you will be able what kind of
- configurations the gadget will provide.
-
- Say "y" to link the driver statically, or "m" to build
- a dynamically linked module called "g_ffs".
-
-config USB_FUNCTIONFS_ETH
- bool "Include configuration with CDC ECM (Ethernet)"
- depends on USB_FUNCTIONFS && NET
- select USB_U_ETHER
- select USB_F_ECM
- select USB_F_SUBSET
- help
- Include a configuration with CDC ECM function (Ethernet) and the
- Function Filesystem.
-
-config USB_FUNCTIONFS_RNDIS
- bool "Include configuration with RNDIS (Ethernet)"
- depends on USB_FUNCTIONFS && NET
- select USB_U_ETHER
- select USB_F_RNDIS
- help
- Include a configuration with RNDIS function (Ethernet) and the Filesystem.
-
-config USB_FUNCTIONFS_GENERIC
- bool "Include 'pure' configuration"
- depends on USB_FUNCTIONFS
- help
- Include a configuration with the Function Filesystem alone with
- no Ethernet interface.
-
-config USB_MASS_STORAGE
- tristate "Mass Storage Gadget"
- depends on BLOCK
- select USB_LIBCOMPOSITE
- select USB_F_MASS_STORAGE
- help
- The Mass Storage Gadget acts as a USB Mass Storage disk drive.
- As its storage repository it can use a regular file or a block
- device (in much the same way as the "loop" device driver),
- specified as a module parameter or sysfs option.
-
- This driver is a replacement for now removed File-backed
- Storage Gadget (g_file_storage).
-
- Say "y" to link the driver statically, or "m" to build
- a dynamically linked module called "g_mass_storage".
-
-config USB_GADGET_TARGET
- tristate "USB Gadget Target Fabric Module"
- depends on TARGET_CORE
- select USB_LIBCOMPOSITE
- help
- This fabric is an USB gadget. Two USB protocols are supported that is
- BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
- advertised on alternative interface 0 (primary) and UAS is on
- alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
- UAS utilizes the USB 3.0 feature called streams support.
-
-config USB_G_SERIAL
- tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
- depends on TTY
- select USB_U_SERIAL
- select USB_F_ACM
- select USB_F_SERIAL
- select USB_F_OBEX
- select USB_LIBCOMPOSITE
- help
- The Serial Gadget talks to the Linux-USB generic serial driver.
- This driver supports a CDC-ACM module option, which can be used
- to interoperate with MS-Windows hosts or with the Linux-USB
- "cdc-acm" driver.
-
- This driver also supports a CDC-OBEX option. You will need a
- user space OBEX server talking to /dev/ttyGS*, since the kernel
- itself doesn't implement the OBEX protocol.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_serial".
-
- For more information, see Documentation/usb/gadget_serial.txt
- which includes instructions and a "driver info file" needed to
- make MS-Windows work with CDC ACM.
-
-config USB_MIDI_GADGET
- tristate "MIDI Gadget"
- depends on SND
- select USB_LIBCOMPOSITE
- select SND_RAWMIDI
- help
- The MIDI Gadget acts as a USB Audio device, with one MIDI
- input and one MIDI output. These MIDI jacks appear as
- a sound "card" in the ALSA sound system. Other MIDI
- connections can then be made on the gadget system, using
- ALSA's aconnect utility etc.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_midi".
-
-config USB_G_PRINTER
- tristate "Printer Gadget"
- select USB_LIBCOMPOSITE
- help
- The Printer Gadget channels data between the USB host and a
- userspace program driving the print engine. The user space
- program reads and writes the device file /dev/g_printer to
- receive or send printer data. It can use ioctl calls to
- the device file to get or set printer status.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_printer".
-
- For more information, see Documentation/usb/gadget_printer.txt
- which includes sample code for accessing the device file.
-
-if TTY
-
-config USB_CDC_COMPOSITE
- tristate "CDC Composite Device (Ethernet and ACM)"
- depends on NET
- select USB_LIBCOMPOSITE
- select USB_U_SERIAL
- select USB_U_ETHER
- select USB_F_ACM
- select USB_F_ECM
- help
- This driver provides two functions in one configuration:
- a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
-
- This driver requires four bulk and two interrupt endpoints,
- plus the ability to handle altsettings. Not all peripheral
- controllers are that capable.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module.
-
-config USB_G_NOKIA
- tristate "Nokia composite gadget"
- depends on PHONET
- select USB_LIBCOMPOSITE
- select USB_U_SERIAL
- select USB_U_ETHER
- select USB_F_ACM
- select USB_F_OBEX
- select USB_F_PHONET
- select USB_F_ECM
- help
- The Nokia composite gadget provides support for acm, obex
- and phonet in only one composite gadget driver.
-
- It's only really useful for N900 hardware. If you're building
- a kernel for N900, say Y or M here. If unsure, say N.
-
-config USB_G_ACM_MS
- tristate "CDC Composite Device (ACM and mass storage)"
- depends on BLOCK
- select USB_LIBCOMPOSITE
- select USB_U_SERIAL
- select USB_F_ACM
- select USB_F_MASS_STORAGE
- help
- This driver provides two functions in one configuration:
- a mass storage, and a CDC ACM (serial port) link.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_acm_ms".
-
-config USB_G_MULTI
- tristate "Multifunction Composite Gadget"
- depends on BLOCK && NET
- select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
- select USB_LIBCOMPOSITE
- select USB_U_SERIAL
- select USB_U_ETHER
- select USB_F_ACM
- select USB_F_MASS_STORAGE
- help
- The Multifunction Composite Gadget provides Ethernet (RNDIS
- and/or CDC Ethernet), mass storage and ACM serial link
- interfaces.
-
- You will be asked to choose which of the two configurations is
- to be available in the gadget. At least one configuration must
- be chosen to make the gadget usable. Selecting more than one
- configuration will prevent Windows from automatically detecting
- the gadget as a composite gadget, so an INF file will be needed to
- use the gadget.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_multi".
-
-config USB_G_MULTI_RNDIS
- bool "RNDIS + CDC Serial + Storage configuration"
- depends on USB_G_MULTI
- select USB_F_RNDIS
- default y
- help
- This option enables a configuration with RNDIS, CDC Serial and
- Mass Storage functions available in the Multifunction Composite
- Gadget. This is the configuration dedicated for Windows since RNDIS
- is Microsoft's protocol.
-
- If unsure, say "y".
-
-config USB_G_MULTI_CDC
- bool "CDC Ethernet + CDC Serial + Storage configuration"
- depends on USB_G_MULTI
- default n
- select USB_F_ECM
- help
- This option enables a configuration with CDC Ethernet (ECM), CDC
- Serial and Mass Storage functions available in the Multifunction
- Composite Gadget.
-
- If unsure, say "y".
-
-endif # TTY
-
-config USB_G_HID
- tristate "HID Gadget"
- select USB_LIBCOMPOSITE
- help
- The HID gadget driver provides generic emulation of USB
- Human Interface Devices (HID).
-
- For more information, see Documentation/usb/gadget_hid.txt which
- includes sample code for accessing the device files.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_hid".
-
-# Standalone / single function gadgets
-config USB_G_DBGP
- tristate "EHCI Debug Device Gadget"
- depends on TTY
- select USB_LIBCOMPOSITE
- help
- This gadget emulates an EHCI Debug device. This is useful when you want
- to interact with an EHCI Debug Port.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_dbgp".
-
-if USB_G_DBGP
-choice
- prompt "EHCI Debug Device mode"
- default USB_G_DBGP_SERIAL
-
-config USB_G_DBGP_PRINTK
- depends on USB_G_DBGP
- bool "printk"
- help
- Directly printk() received data. No interaction.
-
-config USB_G_DBGP_SERIAL
- depends on USB_G_DBGP
- select USB_U_SERIAL
- bool "serial"
- help
- Userland can interact using /dev/ttyGSxxx.
-endchoice
-endif
-
-# put drivers that need isochronous transfer support (for audio
-# or video class gadget drivers), or specific hardware, here.
-config USB_G_WEBCAM
- tristate "USB Webcam Gadget"
- depends on VIDEO_DEV
- select USB_LIBCOMPOSITE
- select VIDEOBUF2_VMALLOC
- help
- The Webcam Gadget acts as a composite USB Audio and Video Class
- device. It provides a userspace API to process UVC control requests
- and stream video data to the host.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_webcam".
+source "drivers/usb/gadget/legacy/Kconfig"
endchoice
index 5f150bc1b4bc92c720d3dff8e6ec9a3d7cb3d967..a186afeaa7001f3f81abb4f95d9edd3099477867 100644 (file)
#
# USB peripheral controller drivers
#
-ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG
+subdir-ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
+subdir-ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG
+ccflags-y += -I$(PWD)/drivers/usb/gadget/udc
-obj-$(CONFIG_USB_GADGET) += udc-core.o
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y := usbstring.o config.o epautoconf.o
libcomposite-y += composite.o functions.o configfs.o u_f.o
-obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
-obj-$(CONFIG_USB_NET2272) += net2272.o
-obj-$(CONFIG_USB_NET2280) += net2280.o
-obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o
-obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o
-obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
-obj-$(CONFIG_USB_GOKU) += goku_udc.o
-obj-$(CONFIG_USB_OMAP) += omap_udc.o
-obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
-obj-$(CONFIG_USB_AT91) += at91_udc.o
-obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
-obj-$(CONFIG_USB_BCM63XX_UDC) += bcm63xx_udc.o
-obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
-fsl_usb2_udc-y := fsl_udc_core.o
-fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
-obj-$(CONFIG_USB_M66592) += m66592-udc.o
-obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
-obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
-obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o
-obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o
-obj-$(CONFIG_USB_LPC32XX) += lpc32xx_udc.o
-obj-$(CONFIG_USB_EG20T) += pch_udc.o
-obj-$(CONFIG_USB_MV_UDC) += mv_udc.o
-mv_udc-y := mv_udc_core.o
-obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
-obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o
-obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
-obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
-# USB Functions
-usb_f_acm-y := f_acm.o
-obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o
-usb_f_ss_lb-y := f_loopback.o f_sourcesink.o
-obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o
-obj-$(CONFIG_USB_U_SERIAL) += u_serial.o
-usb_f_serial-y := f_serial.o
-obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o
-usb_f_obex-y := f_obex.o
-obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o
-obj-$(CONFIG_USB_U_ETHER) += u_ether.o
-usb_f_ncm-y := f_ncm.o
-obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o
-usb_f_ecm-y := f_ecm.o
-obj-$(CONFIG_USB_F_ECM) += usb_f_ecm.o
-usb_f_phonet-y := f_phonet.o
-obj-$(CONFIG_USB_F_PHONET) += usb_f_phonet.o
-usb_f_eem-y := f_eem.o
-obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o
-usb_f_ecm_subset-y := f_subset.o
-obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o
-usb_f_rndis-y := f_rndis.o rndis.o
-obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o
-usb_f_mass_storage-y := f_mass_storage.o storage_common.o
-obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
-usb_f_fs-y := f_fs.o
-obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
-
-#
-# USB gadget drivers
-#
-g_zero-y := zero.o
-g_audio-y := audio.o
-g_ether-y := ether.o
-g_serial-y := serial.o
-g_midi-y := gmidi.o
-gadgetfs-y := inode.o
-g_mass_storage-y := mass_storage.o
-g_printer-y := printer.o
-g_cdc-y := cdc2.o
-g_multi-y := multi.o
-g_hid-y := hid.o
-g_dbgp-y := dbgp.o
-g_nokia-y := nokia.o
-g_webcam-y := webcam.o
-g_ncm-y := ncm.o
-g_acm_ms-y := acm_ms.o
-g_tcm_usb_gadget-y := tcm_usb_gadget.o
-
-obj-$(CONFIG_USB_ZERO) += g_zero.o
-obj-$(CONFIG_USB_AUDIO) += g_audio.o
-obj-$(CONFIG_USB_ETH) += g_ether.o
-obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
-obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
-obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
-obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
-obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
-obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
-obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
-obj-$(CONFIG_USB_G_HID) += g_hid.o
-obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o
-obj-$(CONFIG_USB_G_MULTI) += g_multi.o
-obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
-obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
-obj-$(CONFIG_USB_G_NCM) += g_ncm.o
-obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
-obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
+obj-$(CONFIG_USB_GADGET) += udc/ function/ legacy/
index 042c66b71df8a2c831370667e819585a04774621..b89b543cdd087e5532042407f4fe7a4ae9bdd77a 100644 (file)
usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
- usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
+ usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT);
/*
* The Superspeed USB Capability descriptor shall be implemented by all
index 2ddcd635ca2abccb9b559adeb4dd2a74c26a0d06..44d6e505e9a261c4d72768e0825a49e771e442e5 100644 (file)
ret = -EBUSY;
goto err;
}
- ret = udc_attach_driver(name, &gi->composite.gadget_driver);
+ ret = usb_udc_attach_driver(name, &gi->composite.gadget_driver);
if (ret)
goto err;
gi->udc_name = name;
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
--- /dev/null
@@ -0,0 +1,34 @@
+#
+# USB peripheral controller drivers
+#
+
+ccflags-y := -I$(PWD)/drivers/usb/gadget/
+ccflags-y += -I$(PWD)/drivers/usb/gadget/udc/
+
+# USB Functions
+usb_f_acm-y := f_acm.o
+obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o
+usb_f_ss_lb-y := f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o
+obj-$(CONFIG_USB_U_SERIAL) += u_serial.o
+usb_f_serial-y := f_serial.o
+obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o
+usb_f_obex-y := f_obex.o
+obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o
+obj-$(CONFIG_USB_U_ETHER) += u_ether.o
+usb_f_ncm-y := f_ncm.o
+obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o
+usb_f_ecm-y := f_ecm.o
+obj-$(CONFIG_USB_F_ECM) += usb_f_ecm.o
+usb_f_phonet-y := f_phonet.o
+obj-$(CONFIG_USB_F_PHONET) += usb_f_phonet.o
+usb_f_eem-y := f_eem.o
+obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o
+usb_f_ecm_subset-y := f_subset.o
+obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o
+usb_f_rndis-y := f_rndis.o rndis.o
+obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o
+usb_f_mass_storage-y := f_mass_storage.o storage_common.o
+obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
+usb_f_fs-y := f_fs.o
+obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
similarity index 100%
rename from drivers/usb/gadget/f_acm.c
rename to drivers/usb/gadget/function/f_acm.c
rename from drivers/usb/gadget/f_acm.c
rename to drivers/usb/gadget/function/f_acm.c
similarity index 100%
rename from drivers/usb/gadget/f_ecm.c
rename to drivers/usb/gadget/function/f_ecm.c
rename from drivers/usb/gadget/f_ecm.c
rename to drivers/usb/gadget/function/f_ecm.c
similarity index 100%
rename from drivers/usb/gadget/f_eem.c
rename to drivers/usb/gadget/function/f_eem.c
rename from drivers/usb/gadget/f_eem.c
rename to drivers/usb/gadget/function/f_eem.c
similarity index 99%
rename from drivers/usb/gadget/f_fs.c
rename to drivers/usb/gadget/function/f_fs.c
index 5b46a7a84962361be4013694266ff23eb7dbdd07..8e862d2cc545f5b725dfcb33070d46d81852e9f6 100644 (file)
rename from drivers/usb/gadget/f_fs.c
rename to drivers/usb/gadget/function/f_fs.c
index 5b46a7a84962361be4013694266ff23eb7dbdd07..8e862d2cc545f5b725dfcb33070d46d81852e9f6 100644 (file)
existing = _ffs_find_dev(name);
if (existing)
return -EBUSY;
-
+
dev->name = name;
return 0;
ffs_dev = ffs_data->private_data;
if (ffs_dev)
ffs_dev->mounted = false;
-
+
if (ffs_dev->ffs_release_dev_callback)
ffs_dev->ffs_release_dev_callback(ffs_dev);
similarity index 100%
rename from drivers/usb/gadget/f_hid.c
rename to drivers/usb/gadget/function/f_hid.c
rename from drivers/usb/gadget/f_hid.c
rename to drivers/usb/gadget/function/f_hid.c
similarity index 100%
rename from drivers/usb/gadget/f_loopback.c
rename to drivers/usb/gadget/function/f_loopback.c
rename from drivers/usb/gadget/f_loopback.c
rename to drivers/usb/gadget/function/f_loopback.c
similarity index 99%
rename from drivers/usb/gadget/f_mass_storage.c
rename to drivers/usb/gadget/function/f_mass_storage.c
index b963939088606e7e9252ec1f55d42ff9fdd1dcd3..07f4c0485f0f74299813657629892541debff461 100644 (file)
rename from drivers/usb/gadget/f_mass_storage.c
rename to drivers/usb/gadget/function/f_mass_storage.c
index b963939088606e7e9252ec1f55d42ff9fdd1dcd3..07f4c0485f0f74299813657629892541debff461 100644 (file)
cfg->fsg_num_buffers = fsg_num_buffers;
}
EXPORT_SYMBOL_GPL(fsg_config_from_params);
-
similarity index 100%
rename from drivers/usb/gadget/f_mass_storage.h
rename to drivers/usb/gadget/function/f_mass_storage.h
rename from drivers/usb/gadget/f_mass_storage.h
rename to drivers/usb/gadget/function/f_mass_storage.h
similarity index 99%
rename from drivers/usb/gadget/f_midi.c
rename to drivers/usb/gadget/function/f_midi.c
index 36d4bb23087f4743a9309783ab80b7d3c4d31d18..ff8a6a321cf2aee5eb4a81a3d2327690e49156dc 100644 (file)
rename from drivers/usb/gadget/f_midi.c
rename to drivers/usb/gadget/function/f_midi.c
index 36d4bb23087f4743a9309783ab80b7d3c4d31d18..ff8a6a321cf2aee5eb4a81a3d2327690e49156dc 100644 (file)
fail:
return status;
}
-
similarity index 100%
rename from drivers/usb/gadget/f_ncm.c
rename to drivers/usb/gadget/function/f_ncm.c
rename from drivers/usb/gadget/f_ncm.c
rename to drivers/usb/gadget/function/f_ncm.c
similarity index 100%
rename from drivers/usb/gadget/f_obex.c
rename to drivers/usb/gadget/function/f_obex.c
rename from drivers/usb/gadget/f_obex.c
rename to drivers/usb/gadget/function/f_obex.c
similarity index 100%
rename from drivers/usb/gadget/f_phonet.c
rename to drivers/usb/gadget/function/f_phonet.c
rename from drivers/usb/gadget/f_phonet.c
rename to drivers/usb/gadget/function/f_phonet.c
similarity index 100%
rename from drivers/usb/gadget/f_rndis.c
rename to drivers/usb/gadget/function/f_rndis.c
rename from drivers/usb/gadget/f_rndis.c
rename to drivers/usb/gadget/function/f_rndis.c
similarity index 100%
rename from drivers/usb/gadget/f_serial.c
rename to drivers/usb/gadget/function/f_serial.c
rename from drivers/usb/gadget/f_serial.c
rename to drivers/usb/gadget/function/f_serial.c
similarity index 100%
rename from drivers/usb/gadget/f_sourcesink.c
rename to drivers/usb/gadget/function/f_sourcesink.c
rename from drivers/usb/gadget/f_sourcesink.c
rename to drivers/usb/gadget/function/f_sourcesink.c
similarity index 100%
rename from drivers/usb/gadget/f_subset.c
rename to drivers/usb/gadget/function/f_subset.c
rename from drivers/usb/gadget/f_subset.c
rename to drivers/usb/gadget/function/f_subset.c
similarity index 100%
rename from drivers/usb/gadget/f_uac1.c
rename to drivers/usb/gadget/function/f_uac1.c
rename from drivers/usb/gadget/f_uac1.c
rename to drivers/usb/gadget/function/f_uac1.c
similarity index 100%
rename from drivers/usb/gadget/f_uac2.c
rename to drivers/usb/gadget/function/f_uac2.c
rename from drivers/usb/gadget/f_uac2.c
rename to drivers/usb/gadget/function/f_uac2.c
similarity index 99%
rename from drivers/usb/gadget/f_uvc.c
rename to drivers/usb/gadget/function/f_uvc.c
index e2a1f50bd93c4b7740c6592d5446c965ec107b04..3717086121825ac6a3da709792571c9c54d68481 100644 (file)
rename from drivers/usb/gadget/f_uvc.c
rename to drivers/usb/gadget/function/f_uvc.c
index e2a1f50bd93c4b7740c6592d5446c965ec107b04..3717086121825ac6a3da709792571c9c54d68481 100644 (file)
module_param_named(trace, uvc_gadget_trace_param, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(trace, "Trace level bitmask");
-
similarity index 99%
rename from drivers/usb/gadget/f_uvc.h
rename to drivers/usb/gadget/function/f_uvc.h
index ec52752f7326d2d422be5e8ea054bb4932f113dc..ecee3e9242a9ef664ff875ece3deab9d71091416 100644 (file)
rename from drivers/usb/gadget/f_uvc.h
rename to drivers/usb/gadget/function/f_uvc.h
index ec52752f7326d2d422be5e8ea054bb4932f113dc..ecee3e9242a9ef664ff875ece3deab9d71091416 100644 (file)
const struct uvc_descriptor_header * const *ss_streaming);
#endif /* _F_UVC_H_ */
-
similarity index 100%
rename from drivers/usb/gadget/g_zero.h
rename to drivers/usb/gadget/function/g_zero.h
rename from drivers/usb/gadget/g_zero.h
rename to drivers/usb/gadget/function/g_zero.h
similarity index 100%
rename from drivers/usb/gadget/ndis.h
rename to drivers/usb/gadget/function/ndis.h
rename from drivers/usb/gadget/ndis.h
rename to drivers/usb/gadget/function/ndis.h
similarity index 99%
rename from drivers/usb/gadget/rndis.c
rename to drivers/usb/gadget/function/rndis.c
index 95d2324f69778faf8d7cf8fbd64f553f6f8b4105..9ec7e228587d7f7cf12e3e4d77f2ec9468b836da 100644 (file)
rename from drivers/usb/gadget/rndis.c
rename to drivers/usb/gadget/function/rndis.c
index 95d2324f69778faf8d7cf8fbd64f553f6f8b4105..9ec7e228587d7f7cf12e3e4d77f2ec9468b836da 100644 (file)
}
#endif
}
-
similarity index 100%
rename from drivers/usb/gadget/rndis.h
rename to drivers/usb/gadget/function/rndis.h
rename from drivers/usb/gadget/rndis.h
rename to drivers/usb/gadget/function/rndis.h
similarity index 100%
rename from drivers/usb/gadget/storage_common.c
rename to drivers/usb/gadget/function/storage_common.c
rename from drivers/usb/gadget/storage_common.c
rename to drivers/usb/gadget/function/storage_common.c
similarity index 100%
rename from drivers/usb/gadget/storage_common.h
rename to drivers/usb/gadget/function/storage_common.h
rename from drivers/usb/gadget/storage_common.h
rename to drivers/usb/gadget/function/storage_common.h
similarity index 100%
rename from drivers/usb/gadget/u_ecm.h
rename to drivers/usb/gadget/function/u_ecm.h
rename from drivers/usb/gadget/u_ecm.h
rename to drivers/usb/gadget/function/u_ecm.h
similarity index 100%
rename from drivers/usb/gadget/u_eem.h
rename to drivers/usb/gadget/function/u_eem.h
rename from drivers/usb/gadget/u_eem.h
rename to drivers/usb/gadget/function/u_eem.h
similarity index 100%
rename from drivers/usb/gadget/u_ether.c
rename to drivers/usb/gadget/function/u_ether.c
rename from drivers/usb/gadget/u_ether.c
rename to drivers/usb/gadget/function/u_ether.c
similarity index 100%
rename from drivers/usb/gadget/u_ether.h
rename to drivers/usb/gadget/function/u_ether.h
rename from drivers/usb/gadget/u_ether.h
rename to drivers/usb/gadget/function/u_ether.h
similarity index 100%
rename from drivers/usb/gadget/u_ether_configfs.h
rename to drivers/usb/gadget/function/u_ether_configfs.h
rename from drivers/usb/gadget/u_ether_configfs.h
rename to drivers/usb/gadget/function/u_ether_configfs.h
similarity index 100%
rename from drivers/usb/gadget/u_fs.h
rename to drivers/usb/gadget/function/u_fs.h
rename from drivers/usb/gadget/u_fs.h
rename to drivers/usb/gadget/function/u_fs.h
similarity index 100%
rename from drivers/usb/gadget/u_gether.h
rename to drivers/usb/gadget/function/u_gether.h
rename from drivers/usb/gadget/u_gether.h
rename to drivers/usb/gadget/function/u_gether.h
similarity index 100%
rename from drivers/usb/gadget/u_ncm.h
rename to drivers/usb/gadget/function/u_ncm.h
rename from drivers/usb/gadget/u_ncm.h
rename to drivers/usb/gadget/function/u_ncm.h
similarity index 100%
rename from drivers/usb/gadget/u_phonet.h
rename to drivers/usb/gadget/function/u_phonet.h
rename from drivers/usb/gadget/u_phonet.h
rename to drivers/usb/gadget/function/u_phonet.h
similarity index 100%
rename from drivers/usb/gadget/u_rndis.h
rename to drivers/usb/gadget/function/u_rndis.h
rename from drivers/usb/gadget/u_rndis.h
rename to drivers/usb/gadget/function/u_rndis.h
similarity index 100%
rename from drivers/usb/gadget/u_serial.c
rename to drivers/usb/gadget/function/u_serial.c
rename from drivers/usb/gadget/u_serial.c
rename to drivers/usb/gadget/function/u_serial.c
similarity index 100%
rename from drivers/usb/gadget/u_serial.h
rename to drivers/usb/gadget/function/u_serial.h
rename from drivers/usb/gadget/u_serial.h
rename to drivers/usb/gadget/function/u_serial.h
similarity index 99%
rename from drivers/usb/gadget/u_uac1.c
rename to drivers/usb/gadget/function/u_uac1.c
index 7a55fea43430551b9f7d83d11cebe02a351ccf44..d07af5f37727c98d6410052edbed0f99588f1c65 100644 (file)
rename from drivers/usb/gadget/u_uac1.c
rename to drivers/usb/gadget/function/u_uac1.c
index 7a55fea43430551b9f7d83d11cebe02a351ccf44..d07af5f37727c98d6410052edbed0f99588f1c65 100644 (file)
the_card = NULL;
}
}
-
similarity index 100%
rename from drivers/usb/gadget/u_uac1.h
rename to drivers/usb/gadget/function/u_uac1.h
rename from drivers/usb/gadget/u_uac1.h
rename to drivers/usb/gadget/function/u_uac1.h
similarity index 99%
rename from drivers/usb/gadget/uvc.h
rename to drivers/usb/gadget/function/uvc.h
index 7a9111de80542b0877f9cef36a1f788353b4e2ab..ce6a406f0c967229dedab43888ad307ca93f88a9 100644 (file)
rename from drivers/usb/gadget/uvc.h
rename to drivers/usb/gadget/function/uvc.h
index 7a9111de80542b0877f9cef36a1f788353b4e2ab..ce6a406f0c967229dedab43888ad307ca93f88a9 100644 (file)
--- a/drivers/usb/gadget/uvc.h
#endif /* __KERNEL__ */
#endif /* _UVC_GADGET_H_ */
-
similarity index 99%
rename from drivers/usb/gadget/uvc_queue.c
rename to drivers/usb/gadget/function/uvc_queue.c
index 1c29bc954db9f02f1954073861629e2b9be74c4d..57ff9d77c5412e5829f0ac38299733f705768ebe 100644 (file)
rename from drivers/usb/gadget/uvc_queue.c
rename to drivers/usb/gadget/function/uvc_queue.c
index 1c29bc954db9f02f1954073861629e2b9be74c4d..57ff9d77c5412e5829f0ac38299733f705768ebe 100644 (file)
return buf;
}
-
similarity index 99%
rename from drivers/usb/gadget/uvc_queue.h
rename to drivers/usb/gadget/function/uvc_queue.h
index 8e76ce982f1eadb525b2045e8c7549c6255a723d..28080734b1847b83ab25c9fe96cf265ece91d5f5 100644 (file)
rename from drivers/usb/gadget/uvc_queue.h
rename to drivers/usb/gadget/function/uvc_queue.h
index 8e76ce982f1eadb525b2045e8c7549c6255a723d..28080734b1847b83ab25c9fe96cf265ece91d5f5 100644 (file)
#endif /* __KERNEL__ */
#endif /* _UVC_QUEUE_H_ */
-
similarity index 99%
rename from drivers/usb/gadget/uvc_v4l2.c
rename to drivers/usb/gadget/function/uvc_v4l2.c
index ad48e81155e2c0c838f0092e2da671a7bdaddf5f..d0c1bca41f50092e312c584e562128ffb9f60680 100644 (file)
rename from drivers/usb/gadget/uvc_v4l2.c
rename to drivers/usb/gadget/function/uvc_v4l2.c
index ad48e81155e2c0c838f0092e2da671a7bdaddf5f..d0c1bca41f50092e312c584e562128ffb9f60680 100644 (file)
.get_unmapped_area = uvc_v4l2_get_unmapped_area,
#endif
};
-
similarity index 99%
rename from drivers/usb/gadget/uvc_video.c
rename to drivers/usb/gadget/function/uvc_video.c
index 71e896d4c5ae481d189e582609d8cb456a8187c3..9ce6118bfd55f3176ebb2a89c3ff20719ff3725d 100644 (file)
rename from drivers/usb/gadget/uvc_video.c
rename to drivers/usb/gadget/function/uvc_video.c
index 71e896d4c5ae481d189e582609d8cb456a8187c3..9ce6118bfd55f3176ebb2a89c3ff20719ff3725d 100644 (file)
uvc_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT);
return 0;
}
-
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
--- /dev/null
@@ -0,0 +1,475 @@
+#
+# USB Gadget support on a system involves
+# (a) a peripheral controller, and
+# (b) the gadget driver using it.
+#
+# NOTE: Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+# - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+# - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+# - Some systems have both kinds of controllers.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
+
+config USB_ZERO
+ tristate "Gadget Zero (DEVELOPMENT)"
+ select USB_LIBCOMPOSITE
+ select USB_F_SS_LB
+ help
+ Gadget Zero is a two-configuration device. It either sinks and
+ sources bulk data; or it loops back a configurable number of
+ transfers. It also implements control requests, for "chapter 9"
+ conformance. The driver needs only two bulk-capable endpoints, so
+ it can work on top of most device-side usb controllers. It's
+ useful for testing, and is also a working example showing how
+ USB "gadget drivers" can be written.
+
+ Make this be the first driver you try using on top of any new
+ USB peripheral controller driver. Then you can use host-side
+ test software, like the "usbtest" driver, to put your hardware
+ and its driver through a basic set of functional tests.
+
+ Gadget Zero also works with the host-side "usb-skeleton" driver,
+ and with many kinds of host-side test software. You may need
+ to tweak product and vendor IDs before host software knows about
+ this device, and arrange to select an appropriate configuration.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_zero".
+
+config USB_ZERO_HNPTEST
+ boolean "HNP Test Device"
+ depends on USB_ZERO && USB_OTG
+ help
+ You can configure this device to enumerate using the device
+ identifiers of the USB-OTG test device. That means that when
+ this gadget connects to another OTG device, with this one using
+ the "B-Peripheral" role, that device will use HNP to let this
+ one serve as the USB host instead (in the "B-Host" role).
+
+config USB_AUDIO
+ tristate "Audio Gadget"
+ depends on SND
+ select USB_LIBCOMPOSITE
+ select SND_PCM
+ help
+ This Gadget Audio driver is compatible with USB Audio Class
+ specification 2.0. It implements 1 AudioControl interface,
+ 1 AudioStreaming Interface each for USB-OUT and USB-IN.
+ Number of channels, sample rate and sample size can be
+ specified as module parameters.
+ This driver doesn't expect any real Audio codec to be present
+ on the device - the audio streams are simply sinked to and
+ sourced from a virtual ALSA sound card created. The user-space
+ application may choose to do whatever it wants with the data
+ received from the USB Host and choose to provide whatever it
+ wants as audio data to the USB Host.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_audio".
+
+config GADGET_UAC1
+ bool "UAC 1.0 (Legacy)"
+ depends on USB_AUDIO
+ help
+ If you instead want older UAC Spec-1.0 driver that also has audio
+ paths hardwired to the Audio codec chip on-board and doesn't work
+ without one.
+
+config USB_ETH
+ tristate "Ethernet Gadget (with CDC Ethernet support)"
+ depends on NET
+ select USB_LIBCOMPOSITE
+ select USB_U_ETHER
+ select USB_F_ECM
+ select USB_F_SUBSET
+ select CRC32
+ help
+ This driver implements Ethernet style communication, in one of
+ several ways:
+
+ - The "Communication Device Class" (CDC) Ethernet Control Model.
+ That protocol is often avoided with pure Ethernet adapters, in
+ favor of simpler vendor-specific hardware, but is widely
+ supported by firmware for smart network devices.
+
+ - On hardware can't implement that protocol, a simple CDC subset
+ is used, placing fewer demands on USB.
+
+ - CDC Ethernet Emulation Model (EEM) is a newer standard that has
+ a simpler interface that can be used by more USB hardware.
+
+ RNDIS support is an additional option, more demanding than than
+ subset.
+
+ Within the USB device, this gadget driver exposes a network device
+ "usbX", where X depends on what other networking devices you have.
+ Treat it like a two-node Ethernet link: host, and gadget.
+
+ The Linux-USB host-side "usbnet" driver interoperates with this
+ driver, so that deep I/O queues can be supported. On 2.4 kernels,
+ use "CDCEther" instead, if you're using the CDC option. That CDC
+ mode should also interoperate with standard CDC Ethernet class
+ drivers on other host operating systems.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_ether".
+
+config USB_ETH_RNDIS
+ bool "RNDIS support"
+ depends on USB_ETH
+ select USB_LIBCOMPOSITE
+ select USB_F_RNDIS
+ default y
+ help
+ Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
+ and Microsoft provides redistributable binary RNDIS drivers for
+ older versions of Windows.
+
+ If you say "y" here, the Ethernet gadget driver will try to provide
+ a second device configuration, supporting RNDIS to talk to such
+ Microsoft USB hosts.
+
+ To make MS-Windows work with this, use Documentation/usb/linux.inf
+ as the "driver info file". For versions of MS-Windows older than
+ XP, you'll need to download drivers from Microsoft's website; a URL
+ is given in comments found in that info file.
+
+config USB_ETH_EEM
+ bool "Ethernet Emulation Model (EEM) support"
+ depends on USB_ETH
+ select USB_LIBCOMPOSITE
+ select USB_F_EEM
+ default n
+ help
+ CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
+ and therefore can be supported by more hardware. Technically ECM and
+ EEM are designed for different applications. The ECM model extends
+ the network interface to the target (e.g. a USB cable modem), and the
+ EEM model is for mobile devices to communicate with hosts using
+ ethernet over USB. For Linux gadgets, however, the interface with
+ the host is the same (a usbX device), so the differences are minimal.
+
+ If you say "y" here, the Ethernet gadget driver will use the EEM
+ protocol rather than ECM. If unsure, say "n".
+
+config USB_G_NCM
+ tristate "Network Control Model (NCM) support"
+ depends on NET
+ select USB_LIBCOMPOSITE
+ select USB_U_ETHER
+ select USB_F_NCM
+ select CRC32
+ help
+ This driver implements USB CDC NCM subclass standard. NCM is
+ an advanced protocol for Ethernet encapsulation, allows grouping
+ of several ethernet frames into one USB transfer and different
+ alignment possibilities.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_ncm".
+
+config USB_GADGETFS
+ tristate "Gadget Filesystem"
+ help
+ This driver provides a filesystem based API that lets user mode
+ programs implement a single-configuration USB device, including
+ endpoint I/O and control requests that don't relate to enumeration.
+ All endpoints, transfer speeds, and transfer types supported by
+ the hardware are available, through read() and write() calls.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "gadgetfs".
+
+config USB_FUNCTIONFS
+ tristate "Function Filesystem"
+ select USB_LIBCOMPOSITE
+ select USB_F_FS
+ select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
+ help
+ The Function Filesystem (FunctionFS) lets one create USB
+ composite functions in user space in the same way GadgetFS
+ lets one create USB gadgets in user space. This allows creation
+ of composite gadgets such that some of the functions are
+ implemented in kernel space (for instance Ethernet, serial or
+ mass storage) and other are implemented in user space.
+
+ If you say "y" or "m" here you will be able what kind of
+ configurations the gadget will provide.
+
+ Say "y" to link the driver statically, or "m" to build
+ a dynamically linked module called "g_ffs".
+
+config USB_FUNCTIONFS_ETH
+ bool "Include configuration with CDC ECM (Ethernet)"
+ depends on USB_FUNCTIONFS && NET
+ select USB_U_ETHER
+ select USB_F_ECM
+ select USB_F_SUBSET
+ help
+ Include a configuration with CDC ECM function (Ethernet) and the
+ Function Filesystem.
+
+config USB_FUNCTIONFS_RNDIS
+ bool "Include configuration with RNDIS (Ethernet)"
+ depends on USB_FUNCTIONFS && NET
+ select USB_U_ETHER
+ select USB_F_RNDIS
+ help
+ Include a configuration with RNDIS function (Ethernet) and the Filesystem.
+
+config USB_FUNCTIONFS_GENERIC
+ bool "Include 'pure' configuration"
+ depends on USB_FUNCTIONFS
+ help
+ Include a configuration with the Function Filesystem alone with
+ no Ethernet interface.
+
+config USB_MASS_STORAGE
+ tristate "Mass Storage Gadget"
+ depends on BLOCK
+ select USB_LIBCOMPOSITE
+ select USB_F_MASS_STORAGE
+ help
+ The Mass Storage Gadget acts as a USB Mass Storage disk drive.
+ As its storage repository it can use a regular file or a block
+ device (in much the same way as the "loop" device driver),
+ specified as a module parameter or sysfs option.
+
+ This driver is a replacement for now removed File-backed
+ Storage Gadget (g_file_storage).
+
+ Say "y" to link the driver statically, or "m" to build
+ a dynamically linked module called "g_mass_storage".
+
+config USB_GADGET_TARGET
+ tristate "USB Gadget Target Fabric Module"
+ depends on TARGET_CORE
+ select USB_LIBCOMPOSITE
+ help
+ This fabric is an USB gadget. Two USB protocols are supported that is
+ BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
+ advertised on alternative interface 0 (primary) and UAS is on
+ alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
+ UAS utilizes the USB 3.0 feature called streams support.
+
+config USB_G_SERIAL
+ tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
+ depends on TTY
+ select USB_U_SERIAL
+ select USB_F_ACM
+ select USB_F_SERIAL
+ select USB_F_OBEX
+ select USB_LIBCOMPOSITE
+ help
+ The Serial Gadget talks to the Linux-USB generic serial driver.
+ This driver supports a CDC-ACM module option, which can be used
+ to interoperate with MS-Windows hosts or with the Linux-USB
+ "cdc-acm" driver.
+
+ This driver also supports a CDC-OBEX option. You will need a
+ user space OBEX server talking to /dev/ttyGS*, since the kernel
+ itself doesn't implement the OBEX protocol.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_serial".
+
+ For more information, see Documentation/usb/gadget_serial.txt
+ which includes instructions and a "driver info file" needed to
+ make MS-Windows work with CDC ACM.
+
+config USB_MIDI_GADGET
+ tristate "MIDI Gadget"
+ depends on SND
+ select USB_LIBCOMPOSITE
+ select SND_RAWMIDI
+ help
+ The MIDI Gadget acts as a USB Audio device, with one MIDI
+ input and one MIDI output. These MIDI jacks appear as
+ a sound "card" in the ALSA sound system. Other MIDI
+ connections can then be made on the gadget system, using
+ ALSA's aconnect utility etc.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_midi".
+
+config USB_G_PRINTER
+ tristate "Printer Gadget"
+ select USB_LIBCOMPOSITE
+ help
+ The Printer Gadget channels data between the USB host and a
+ userspace program driving the print engine. The user space
+ program reads and writes the device file /dev/g_printer to
+ receive or send printer data. It can use ioctl calls to
+ the device file to get or set printer status.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_printer".
+
+ For more information, see Documentation/usb/gadget_printer.txt
+ which includes sample code for accessing the device file.
+
+if TTY
+
+config USB_CDC_COMPOSITE
+ tristate "CDC Composite Device (Ethernet and ACM)"
+ depends on NET
+ select USB_LIBCOMPOSITE
+ select USB_U_SERIAL
+ select USB_U_ETHER
+ select USB_F_ACM
+ select USB_F_ECM
+ help
+ This driver provides two functions in one configuration:
+ a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
+
+ This driver requires four bulk and two interrupt endpoints,
+ plus the ability to handle altsettings. Not all peripheral
+ controllers are that capable.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module.
+
+config USB_G_NOKIA
+ tristate "Nokia composite gadget"
+ depends on PHONET
+ select USB_LIBCOMPOSITE
+ select USB_U_SERIAL
+ select USB_U_ETHER
+ select USB_F_ACM
+ select USB_F_OBEX
+ select USB_F_PHONET
+ select USB_F_ECM
+ help
+ The Nokia composite gadget provides support for acm, obex
+ and phonet in only one composite gadget driver.
+
+ It's only really useful for N900 hardware. If you're building
+ a kernel for N900, say Y or M here. If unsure, say N.
+
+config USB_G_ACM_MS
+ tristate "CDC Composite Device (ACM and mass storage)"
+ depends on BLOCK
+ select USB_LIBCOMPOSITE
+ select USB_U_SERIAL
+ select USB_F_ACM
+ select USB_F_MASS_STORAGE
+ help
+ This driver provides two functions in one configuration:
+ a mass storage, and a CDC ACM (serial port) link.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_acm_ms".
+
+config USB_G_MULTI
+ tristate "Multifunction Composite Gadget"
+ depends on BLOCK && NET
+ select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
+ select USB_LIBCOMPOSITE
+ select USB_U_SERIAL
+ select USB_U_ETHER
+ select USB_F_ACM
+ select USB_F_MASS_STORAGE
+ help
+ The Multifunction Composite Gadget provides Ethernet (RNDIS
+ and/or CDC Ethernet), mass storage and ACM serial link
+ interfaces.
+
+ You will be asked to choose which of the two configurations is
+ to be available in the gadget. At least one configuration must
+ be chosen to make the gadget usable. Selecting more than one
+ configuration will prevent Windows from automatically detecting
+ the gadget as a composite gadget, so an INF file will be needed to
+ use the gadget.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_multi".
+
+config USB_G_MULTI_RNDIS
+ bool "RNDIS + CDC Serial + Storage configuration"
+ depends on USB_G_MULTI
+ select USB_F_RNDIS
+ default y
+ help
+ This option enables a configuration with RNDIS, CDC Serial and
+ Mass Storage functions available in the Multifunction Composite
+ Gadget. This is the configuration dedicated for Windows since RNDIS
+ is Microsoft's protocol.
+
+ If unsure, say "y".
+
+config USB_G_MULTI_CDC
+ bool "CDC Ethernet + CDC Serial + Storage configuration"
+ depends on USB_G_MULTI
+ default n
+ select USB_F_ECM
+ help
+ This option enables a configuration with CDC Ethernet (ECM), CDC
+ Serial and Mass Storage functions available in the Multifunction
+ Composite Gadget.
+
+ If unsure, say "y".
+
+endif # TTY
+
+config USB_G_HID
+ tristate "HID Gadget"
+ select USB_LIBCOMPOSITE
+ help
+ The HID gadget driver provides generic emulation of USB
+ Human Interface Devices (HID).
+
+ For more information, see Documentation/usb/gadget_hid.txt which
+ includes sample code for accessing the device files.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_hid".
+
+# Standalone / single function gadgets
+config USB_G_DBGP
+ tristate "EHCI Debug Device Gadget"
+ depends on TTY
+ select USB_LIBCOMPOSITE
+ help
+ This gadget emulates an EHCI Debug device. This is useful when you want
+ to interact with an EHCI Debug Port.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_dbgp".
+
+if USB_G_DBGP
+choice
+ prompt "EHCI Debug Device mode"
+ default USB_G_DBGP_SERIAL
+
+config USB_G_DBGP_PRINTK
+ depends on USB_G_DBGP
+ bool "printk"
+ help
+ Directly printk() received data. No interaction.
+
+config USB_G_DBGP_SERIAL
+ depends on USB_G_DBGP
+ select USB_U_SERIAL
+ bool "serial"
+ help
+ Userland can interact using /dev/ttyGSxxx.
+endchoice
+endif
+
+# put drivers that need isochronous transfer support (for audio
+# or video class gadget drivers), or specific hardware, here.
+config USB_G_WEBCAM
+ tristate "USB Webcam Gadget"
+ depends on VIDEO_DEV
+ select USB_LIBCOMPOSITE
+ select VIDEOBUF2_VMALLOC
+ help
+ The Webcam Gadget acts as a composite USB Audio and Video Class
+ device. It provides a userspace API to process UVC control requests
+ and stream video data to the host.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "g_webcam".
diff --git a/drivers/usb/gadget/legacy/Makefile b/drivers/usb/gadget/legacy/Makefile
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# USB gadget drivers
+#
+
+ccflags-y := -I$(PWD)/drivers/usb/gadget/
+ccflags-y += -I$(PWD)/drivers/usb/gadget/udc/
+ccflags-y += -I$(PWD)/drivers/usb/gadget/function/
+
+g_zero-y := zero.o
+g_audio-y := audio.o
+g_ether-y := ether.o
+g_serial-y := serial.o
+g_midi-y := gmidi.o
+gadgetfs-y := inode.o
+g_mass_storage-y := mass_storage.o
+g_printer-y := printer.o
+g_cdc-y := cdc2.o
+g_multi-y := multi.o
+g_hid-y := hid.o
+g_dbgp-y := dbgp.o
+g_nokia-y := nokia.o
+g_webcam-y := webcam.o
+g_ncm-y := ncm.o
+g_acm_ms-y := acm_ms.o
+g_tcm_usb_gadget-y := tcm_usb_gadget.o
+
+obj-$(CONFIG_USB_ZERO) += g_zero.o
+obj-$(CONFIG_USB_AUDIO) += g_audio.o
+obj-$(CONFIG_USB_ETH) += g_ether.o
+obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
+obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
+obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
+obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
+obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
+obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
+obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
+obj-$(CONFIG_USB_G_HID) += g_hid.o
+obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o
+obj-$(CONFIG_USB_G_MULTI) += g_multi.o
+obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
+obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
+obj-$(CONFIG_USB_G_NCM) += g_ncm.o
+obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
+obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
similarity index 100%
rename from drivers/usb/gadget/acm_ms.c
rename to drivers/usb/gadget/legacy/acm_ms.c
rename from drivers/usb/gadget/acm_ms.c
rename to drivers/usb/gadget/legacy/acm_ms.c
similarity index 99%
rename from drivers/usb/gadget/audio.c
rename to drivers/usb/gadget/legacy/audio.c
index 231b0efe8fdc12704f596e84c7fbab8f86e9aee7..c8877baa13835c51a00f831f3f948e7c31dc38ad 100644 (file)
rename from drivers/usb/gadget/audio.c
rename to drivers/usb/gadget/legacy/audio.c
index 231b0efe8fdc12704f596e84c7fbab8f86e9aee7..c8877baa13835c51a00f831f3f948e7c31dc38ad 100644 (file)
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Bryan Wu <cooloney@kernel.org>");
MODULE_LICENSE("GPL");
-
similarity index 100%
rename from drivers/usb/gadget/cdc2.c
rename to drivers/usb/gadget/legacy/cdc2.c
rename from drivers/usb/gadget/cdc2.c
rename to drivers/usb/gadget/legacy/cdc2.c
similarity index 100%
rename from drivers/usb/gadget/dbgp.c
rename to drivers/usb/gadget/legacy/dbgp.c
rename from drivers/usb/gadget/dbgp.c
rename to drivers/usb/gadget/legacy/dbgp.c
similarity index 100%
rename from drivers/usb/gadget/ether.c
rename to drivers/usb/gadget/legacy/ether.c
rename from drivers/usb/gadget/ether.c
rename to drivers/usb/gadget/legacy/ether.c
similarity index 99%
rename from drivers/usb/gadget/g_ffs.c
rename to drivers/usb/gadget/legacy/g_ffs.c
index fe12e6a2744896a08f9cb55039c45824756f9f52..087aca0e9dac71c56e81f2a2ed5169d5eddf6968 100644 (file)
rename from drivers/usb/gadget/g_ffs.c
rename to drivers/usb/gadget/legacy/g_ffs.c
index fe12e6a2744896a08f9cb55039c45824756f9f52..087aca0e9dac71c56e81f2a2ed5169d5eddf6968 100644 (file)
{
if (!try_module_get(THIS_MODULE))
return ERR_PTR(-ENODEV);
-
+
return 0;
}
}
/*
- * The caller of this function takes ffs_lock
+ * The caller of this function takes ffs_lock
*/
static int functionfs_ready_callback(struct ffs_data *ffs)
{
ret = usb_composite_probe(&gfs_driver);
if (unlikely(ret < 0))
gfs_registered = false;
-
+
return ret;
}
/*
- * The caller of this function takes ffs_lock
+ * The caller of this function takes ffs_lock
*/
static void functionfs_closed_callback(struct ffs_data *ffs)
{
similarity index 99%
rename from drivers/usb/gadget/gmidi.c
rename to drivers/usb/gadget/legacy/gmidi.c
index e879e2c9f461bb73463608fe8d4c90a6333e8cd8..2710f2982f3fc63c400e8c351489cd44325373bb 100644 (file)
rename from drivers/usb/gadget/gmidi.c
rename to drivers/usb/gadget/legacy/gmidi.c
index e879e2c9f461bb73463608fe8d4c90a6333e8cd8..2710f2982f3fc63c400e8c351489cd44325373bb 100644 (file)
usb_composite_unregister(&midi_driver);
}
module_exit(midi_cleanup);
-
similarity index 100%
rename from drivers/usb/gadget/hid.c
rename to drivers/usb/gadget/legacy/hid.c
rename from drivers/usb/gadget/hid.c
rename to drivers/usb/gadget/legacy/hid.c
similarity index 99%
rename from drivers/usb/gadget/inode.c
rename to drivers/usb/gadget/legacy/inode.c
index 66ce5f9b3b06e94e50214181c47d8c19f57d527c..bc86ba30f59b6110ef0cd21ae30679d49db1b45c 100644 (file)
rename from drivers/usb/gadget/inode.c
rename to drivers/usb/gadget/legacy/inode.c
index 66ce5f9b3b06e94e50214181c47d8c19f57d527c..bc86ba30f59b6110ef0cd21ae30679d49db1b45c 100644 (file)
unregister_filesystem (&gadgetfs_type);
}
module_exit (cleanup);
-
similarity index 100%
rename from drivers/usb/gadget/mass_storage.c
rename to drivers/usb/gadget/legacy/mass_storage.c
rename from drivers/usb/gadget/mass_storage.c
rename to drivers/usb/gadget/legacy/mass_storage.c
similarity index 100%
rename from drivers/usb/gadget/multi.c
rename to drivers/usb/gadget/legacy/multi.c
rename from drivers/usb/gadget/multi.c
rename to drivers/usb/gadget/legacy/multi.c
similarity index 100%
rename from drivers/usb/gadget/ncm.c
rename to drivers/usb/gadget/legacy/ncm.c
rename from drivers/usb/gadget/ncm.c
rename to drivers/usb/gadget/legacy/ncm.c
similarity index 100%
rename from drivers/usb/gadget/nokia.c
rename to drivers/usb/gadget/legacy/nokia.c
rename from drivers/usb/gadget/nokia.c
rename to drivers/usb/gadget/legacy/nokia.c
similarity index 100%
rename from drivers/usb/gadget/printer.c
rename to drivers/usb/gadget/legacy/printer.c
rename from drivers/usb/gadget/printer.c
rename to drivers/usb/gadget/legacy/printer.c
similarity index 100%
rename from drivers/usb/gadget/serial.c
rename to drivers/usb/gadget/legacy/serial.c
rename from drivers/usb/gadget/serial.c
rename to drivers/usb/gadget/legacy/serial.c
similarity index 100%
rename from drivers/usb/gadget/tcm_usb_gadget.c
rename to drivers/usb/gadget/legacy/tcm_usb_gadget.c
rename from drivers/usb/gadget/tcm_usb_gadget.c
rename to drivers/usb/gadget/legacy/tcm_usb_gadget.c
similarity index 100%
rename from drivers/usb/gadget/tcm_usb_gadget.h
rename to drivers/usb/gadget/legacy/tcm_usb_gadget.h
rename from drivers/usb/gadget/tcm_usb_gadget.h
rename to drivers/usb/gadget/legacy/tcm_usb_gadget.h
similarity index 99%
rename from drivers/usb/gadget/webcam.c
rename to drivers/usb/gadget/legacy/webcam.c
index 8cef1e658c2908c749735ab311d55456b334f279..9ad285777bbd5aa5c34273933aa1f5646425a62d 100644 (file)
rename from drivers/usb/gadget/webcam.c
rename to drivers/usb/gadget/legacy/webcam.c
index 8cef1e658c2908c749735ab311d55456b334f279..9ad285777bbd5aa5c34273933aa1f5646425a62d 100644 (file)
MODULE_DESCRIPTION("Webcam Video Gadget");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1.0");
-
similarity index 100%
rename from drivers/usb/gadget/zero.c
rename to drivers/usb/gadget/legacy/zero.c
rename from drivers/usb/gadget/zero.c
rename to drivers/usb/gadget/legacy/zero.c
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
--- /dev/null
@@ -0,0 +1,385 @@
+#
+# USB Gadget support on a system involves
+# (a) a peripheral controller, and
+# (b) the gadget driver using it.
+#
+# NOTE: Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+# - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+# - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+# - Some systems have both kinds of controllers.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
+
+#
+# USB Peripheral Controller Support
+#
+# The order here is alphabetical, except that integrated controllers go
+# before discrete ones so they will be the initial/default value:
+# - integrated/SOC controllers first
+# - licensed IP used in both SOC and discrete versions
+# - discrete ones (including all PCI-only controllers)
+# - debug/dummy gadget+hcd is last.
+#
+menu "USB Peripheral Controller"
+
+#
+# Integrated controllers
+#
+
+config USB_AT91
+ tristate "Atmel AT91 USB Device Port"
+ depends on ARCH_AT91
+ help
+ Many Atmel AT91 processors (such as the AT91RM2000) have a
+ full speed USB Device Port with support for five configurable
+ endpoints (plus endpoint zero).
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "at91_udc" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_LPC32XX
+ tristate "LPC32XX USB Peripheral Controller"
+ depends on ARCH_LPC32XX && I2C
+ select USB_ISP1301
+ help
+ This option selects the USB device controller in the LPC32xx SoC.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "lpc32xx_udc" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_ATMEL_USBA
+ tristate "Atmel USBA"
+ depends on AVR32 || ARCH_AT91
+ help
+ USBA is the integrated high-speed USB Device controller on
+ the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
+
+config USB_BCM63XX_UDC
+ tristate "Broadcom BCM63xx Peripheral Controller"
+ depends on BCM63XX
+ help
+ Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
+ high speed USB Device Port with support for four fixed endpoints
+ (plus endpoint zero).
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "bcm63xx_udc".
+
+config USB_FSL_USB2
+ tristate "Freescale Highspeed USB DR Peripheral Controller"
+ depends on FSL_SOC || ARCH_MXC
+ select USB_FSL_MPH_DR_OF if OF
+ help
+ Some of Freescale PowerPC and i.MX processors have a High Speed
+ Dual-Role(DR) USB controller, which supports device mode.
+
+ The number of programmable endpoints is different through
+ SOC revisions.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "fsl_usb2_udc" and force
+ all gadget drivers to also be dynamically linked.
+
+config USB_FUSB300
+ tristate "Faraday FUSB300 USB Peripheral Controller"
+ depends on !PHYS_ADDR_T_64BIT && HAS_DMA
+ help
+ Faraday usb device controller FUSB300 driver
+
+config USB_FOTG210_UDC
+ depends on HAS_DMA
+ tristate "Faraday FOTG210 USB Peripheral Controller"
+ help
+ Faraday USB2.0 OTG controller which can be configured as
+ high speed or full speed USB device. This driver supppors
+ Bulk Transfer so far.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "fotg210_udc".
+
+config USB_GR_UDC
+ tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
+ depends on HAS_DMA
+ help
+ Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
+ VHDL IP core library.
+
+config USB_OMAP
+ tristate "OMAP USB Device Controller"
+ depends on ARCH_OMAP1
+ depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
+ help
+ Many Texas Instruments OMAP processors have flexible full
+ speed USB device controllers, with support for up to 30
+ endpoints (plus endpoint zero). This driver supports the
+ controller in the OMAP 1611, and should work with controllers
+ in other OMAP processors too, given minor tweaks.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "omap_udc" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_PXA25X
+ tristate "PXA 25x or IXP 4xx"
+ depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
+ help
+ Intel's PXA 25x series XScale ARM-5TE processors include
+ an integrated full speed USB 1.1 device controller. The
+ controller in the IXP 4xx series is register-compatible.
+
+ It has fifteen fixed-function endpoints, as well as endpoint
+ zero (for control transfers).
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "pxa25x_udc" and force all
+ gadget drivers to also be dynamically linked.
+
+# if there's only one gadget driver, using only two bulk endpoints,
+# don't waste memory for the other endpoints
+config USB_PXA25X_SMALL
+ depends on USB_PXA25X
+ bool
+ default n if USB_ETH_RNDIS
+ default y if USB_ZERO
+ default y if USB_ETH
+ default y if USB_G_SERIAL
+
+config USB_R8A66597
+ tristate "Renesas R8A66597 USB Peripheral Controller"
+ depends on HAS_DMA
+ help
+ R8A66597 is a discrete USB host and peripheral controller chip that
+ supports both full and high speed USB 2.0 data transfers.
+ It has nine configurable endpoints, and endpoint zero.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "r8a66597_udc" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_RENESAS_USBHS_UDC
+ tristate 'Renesas USBHS controller'
+ depends on USB_RENESAS_USBHS
+ help
+ Renesas USBHS is a discrete USB host and peripheral controller chip
+ that supports both full and high speed USB 2.0 data transfers.
+ It has nine or more configurable endpoints, and endpoint zero.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "renesas_usbhs" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_PXA27X
+ tristate "PXA 27x"
+ help
+ Intel's PXA 27x series XScale ARM v5TE processors include
+ an integrated full speed USB 1.1 device controller.
+
+ It has up to 23 endpoints, as well as endpoint zero (for
+ control transfers).
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "pxa27x_udc" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_S3C2410
+ tristate "S3C2410 USB Device Controller"
+ depends on ARCH_S3C24XX
+ help
+ Samsung's S3C2410 is an ARM-4 processor with an integrated
+ full speed USB 1.1 device controller. It has 4 configurable
+ endpoints, as well as endpoint zero (for control transfers).
+
+ This driver has been tested on the S3C2410, S3C2412, and
+ S3C2440 processors.
+
+config USB_S3C2410_DEBUG
+ boolean "S3C2410 udc debug messages"
+ depends on USB_S3C2410
+
+config USB_S3C_HSUDC
+ tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
+ depends on ARCH_S3C24XX
+ help
+ Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
+ integrated with dual speed USB 2.0 device controller. It has
+ 8 endpoints, as well as endpoint zero.
+
+ This driver has been tested on S3C2416 and S3C2450 processors.
+
+config USB_MV_UDC
+ tristate "Marvell USB2.0 Device Controller"
+ depends on HAS_DMA
+ help
+ Marvell Socs (including PXA and MMP series) include a high speed
+ USB2.0 OTG controller, which can be configured as high speed or
+ full speed USB peripheral.
+
+config USB_MV_U3D
+ depends on HAS_DMA
+ tristate "MARVELL PXA2128 USB 3.0 controller"
+ help
+ MARVELL PXA2128 Processor series include a super speed USB3.0 device
+ controller, which support super speed USB peripheral.
+
+#
+# Controllers available in both integrated and discrete versions
+#
+
+config USB_M66592
+ tristate "Renesas M66592 USB Peripheral Controller"
+ help
+ M66592 is a discrete USB peripheral controller chip that
+ supports both full and high speed USB 2.0 data transfers.
+ It has seven configurable endpoints, and endpoint zero.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "m66592_udc" and force all
+ gadget drivers to also be dynamically linked.
+
+#
+# Controllers available only in discrete form (and all PCI controllers)
+#
+
+config USB_AMD5536UDC
+ tristate "AMD5536 UDC"
+ depends on PCI
+ help
+ The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
+ It is a USB Highspeed DMA capable USB device controller. Beside ep0
+ it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
+ The UDC port supports OTG operation, and may be used as a host port
+ if it's not being used to implement peripheral or OTG roles.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "amd5536udc" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_FSL_QE
+ tristate "Freescale QE/CPM USB Device Controller"
+ depends on FSL_SOC && (QUICC_ENGINE || CPM)
+ help
+ Some of Freescale PowerPC processors have a Full Speed
+ QE/CPM2 USB controller, which support device mode with 4
+ programmable endpoints. This driver supports the
+ controller in the MPC8360 and MPC8272, and should work with
+ controllers having QE or CPM2, given minor tweaks.
+
+ Set CONFIG_USB_GADGET to "m" to build this driver as a
+ dynamically linked module called "fsl_qe_udc".
+
+config USB_NET2272
+ tristate "PLX NET2272"
+ help
+ PLX NET2272 is a USB peripheral controller which supports
+ both full and high speed USB 2.0 data transfers.
+
+ It has three configurable endpoints, as well as endpoint zero
+ (for control transfer).
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "net2272" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_NET2272_DMA
+ boolean "Support external DMA controller"
+ depends on USB_NET2272 && HAS_DMA
+ help
+ The NET2272 part can optionally support an external DMA
+ controller, but your board has to have support in the
+ driver itself.
+
+ If unsure, say "N" here. The driver works fine in PIO mode.
+
+config USB_NET2280
+ tristate "NetChip 228x / PLX USB338x"
+ depends on PCI
+ help
+ NetChip 2280 / 2282 is a PCI based USB peripheral controller which
+ supports both full and high speed USB 2.0 data transfers.
+
+ It has six configurable endpoints, as well as endpoint zero
+ (for control transfers) and several endpoints with dedicated
+ functions.
+
+ PLX 3380 / 3382 is a PCIe based USB peripheral controller which
+ supports full, high speed USB 2.0 and super speed USB 3.0
+ data transfers.
+
+ It has eight configurable endpoints, as well as endpoint zero
+ (for control transfers) and several endpoints with dedicated
+ functions.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "net2280" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_GOKU
+ tristate "Toshiba TC86C001 'Goku-S'"
+ depends on PCI
+ help
+ The Toshiba TC86C001 is a PCI device which includes controllers
+ for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
+
+ The device controller has three configurable (bulk or interrupt)
+ endpoints, plus endpoint zero (for control transfers).
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "goku_udc" and to force all
+ gadget drivers to also be dynamically linked.
+
+config USB_EG20T
+ tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
+ depends on PCI
+ help
+ This is a USB device driver for EG20T PCH.
+ EG20T PCH is the platform controller hub that is used in Intel's
+ general embedded platform. EG20T PCH has USB device interface.
+ Using this interface, it is able to access system devices connected
+ to USB device.
+ This driver enables USB device function.
+ USB device is a USB peripheral controller which
+ supports both full and high speed USB 2.0 data transfers.
+ This driver supports both control transfer and bulk transfer modes.
+ This driver dose not support interrupt transfer or isochronous
+ transfer modes.
+
+ This driver also can be used for LAPIS Semiconductor's ML7213 which is
+ for IVI(In-Vehicle Infotainment) use.
+ ML7831 is for general purpose use.
+ ML7213/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7213/ML7831 is completely compatible for Intel EG20T PCH.
+
+#
+# LAST -- dummy/emulated controller
+#
+
+config USB_DUMMY_HCD
+ tristate "Dummy HCD (DEVELOPMENT)"
+ depends on USB=y || (USB=m && USB_GADGET=m)
+ help
+ This host controller driver emulates USB, looping all data transfer
+ requests back to a USB "gadget driver" in the same host. The host
+ side is the master; the gadget side is the slave. Gadget drivers
+ can be high, full, or low speed; and they have access to endpoints
+ like those from NET2280, PXA2xx, or SA1100 hardware.
+
+ This may help in some stages of creating a driver to embed in a
+ Linux device, since it lets you debug several parts of the gadget
+ driver without its hardware or drivers being involved.
+
+ Since such a gadget side driver needs to interoperate with a host
+ side Linux-USB device driver, this may help to debug both sides
+ of a USB protocol stack.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "dummy_hcd" and force all
+ gadget drivers to also be dynamically linked.
+
+# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears
+# first and will be selected by default.
+
+endmenu
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# USB peripheral controller drivers
+#
+obj-$(CONFIG_USB_GADGET) += udc-core.o
+obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
+obj-$(CONFIG_USB_NET2272) += net2272.o
+obj-$(CONFIG_USB_NET2280) += net2280.o
+obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o
+obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o
+obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
+obj-$(CONFIG_USB_GOKU) += goku_udc.o
+obj-$(CONFIG_USB_OMAP) += omap_udc.o
+obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
+obj-$(CONFIG_USB_AT91) += at91_udc.o
+obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
+obj-$(CONFIG_USB_BCM63XX_UDC) += bcm63xx_udc.o
+obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
+fsl_usb2_udc-y := fsl_udc_core.o
+fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
+obj-$(CONFIG_USB_M66592) += m66592-udc.o
+obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
+obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
+obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o
+obj-$(CONFIG_USB_LPC32XX) += lpc32xx_udc.o
+obj-$(CONFIG_USB_EG20T) += pch_udc.o
+obj-$(CONFIG_USB_MV_UDC) += mv_udc.o
+mv_udc-y := mv_udc_core.o
+obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
+obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o
+obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
+obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
similarity index 99%
rename from drivers/usb/gadget/amd5536udc.c
rename to drivers/usb/gadget/udc/amd5536udc.c
index 41b062eb4de075077d01d9ee9a293e10906cdefd..ad13f2159c7c4495de859e8e0011434b00a725c4 100644 (file)
rename from drivers/usb/gadget/amd5536udc.c
rename to drivers/usb/gadget/udc/amd5536udc.c
index 41b062eb4de075077d01d9ee9a293e10906cdefd..ad13f2159c7c4495de859e8e0011434b00a725c4 100644 (file)
static int amd5536_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int amd5536_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
-/* gadget operations */
+static int amd5536_udc_stop(struct usb_gadget *g);
+
static const struct usb_gadget_ops udc_ops = {
.wakeup = udc_wakeup,
.get_frame = udc_get_frame,
}
/* Called by gadget driver to unregister itself */
-static int amd5536_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int amd5536_udc_stop(struct usb_gadget *g)
{
struct udc *dev = to_amd5536_udc(g);
unsigned long flags;
MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
MODULE_AUTHOR("Thomas Dahlmann");
MODULE_LICENSE("GPL");
-
similarity index 100%
rename from drivers/usb/gadget/amd5536udc.h
rename to drivers/usb/gadget/udc/amd5536udc.h
rename from drivers/usb/gadget/amd5536udc.h
rename to drivers/usb/gadget/udc/amd5536udc.h
similarity index 99%
rename from drivers/usb/gadget/at91_udc.c
rename to drivers/usb/gadget/udc/at91_udc.c
index 1926925a52a9958b0d5066b86a89b42ce0b6ac25..a0779fd308949b9cb0c4f0f13dd1318699cca25a 100644 (file)
rename from drivers/usb/gadget/at91_udc.c
rename to drivers/usb/gadget/udc/at91_udc.c
index 1926925a52a9958b0d5066b86a89b42ce0b6ac25..a0779fd308949b9cb0c4f0f13dd1318699cca25a 100644 (file)
static int at91_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver);
-static int at91_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver);
+static int at91_stop(struct usb_gadget *gadget);
+
static const struct usb_gadget_ops at91_udc_ops = {
.get_frame = at91_get_frame,
.wakeup = at91_wakeup,
return 0;
}
-static int at91_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int at91_stop(struct usb_gadget *gadget)
{
struct at91_udc *udc;
unsigned long flags;
similarity index 99%
rename from drivers/usb/gadget/at91_udc.h
rename to drivers/usb/gadget/udc/at91_udc.h
index 01752466338164e898b48a511078c5b2252b15a7..7e9ac66fbd8ca5596685194a0e255f64d4e4316e 100644 (file)
rename from drivers/usb/gadget/at91_udc.h
rename to drivers/usb/gadget/udc/at91_udc.h
index 01752466338164e898b48a511078c5b2252b15a7..7e9ac66fbd8ca5596685194a0e255f64d4e4316e 100644 (file)
#define DBG(stuff...) pr_debug("udc: " stuff)
#endif
-
similarity index 99%
rename from drivers/usb/gadget/atmel_usba_udc.c
rename to drivers/usb/gadget/udc/atmel_usba_udc.c
index c371656082fa7980f74c36e633668bdf1478f629..3a04d3f6b939bf65400537ed1084daefa07524c2 100644 (file)
rename from drivers/usb/gadget/atmel_usba_udc.c
rename to drivers/usb/gadget/udc/atmel_usba_udc.c
index c371656082fa7980f74c36e633668bdf1478f629..3a04d3f6b939bf65400537ed1084daefa07524c2 100644 (file)
static int atmel_usba_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver);
-static int atmel_usba_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver);
+static int atmel_usba_stop(struct usb_gadget *gadget);
+
static const struct usb_gadget_ops usba_udc_ops = {
.get_frame = usba_udc_get_frame,
.wakeup = usba_udc_wakeup,
return 0;
}
-static int atmel_usba_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int atmel_usba_stop(struct usb_gadget *gadget)
{
struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
unsigned long flags;
similarity index 100%
rename from drivers/usb/gadget/atmel_usba_udc.h
rename to drivers/usb/gadget/udc/atmel_usba_udc.h
rename from drivers/usb/gadget/atmel_usba_udc.h
rename to drivers/usb/gadget/udc/atmel_usba_udc.h
similarity index 99%
rename from drivers/usb/gadget/bcm63xx_udc.c
rename to drivers/usb/gadget/udc/bcm63xx_udc.c
index e969eb809a853dbb38093a0f5d3d39f57f931bb7..f97a3acd1790f4b2615fedc75824e0cc09c059e2 100644 (file)
rename from drivers/usb/gadget/bcm63xx_udc.c
rename to drivers/usb/gadget/udc/bcm63xx_udc.c
index e969eb809a853dbb38093a0f5d3d39f57f931bb7..f97a3acd1790f4b2615fedc75824e0cc09c059e2 100644 (file)
* @gadget: USB slave device.
* @driver: Driver for USB slave devices.
*/
-static int bcm63xx_udc_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int bcm63xx_udc_stop(struct usb_gadget *gadget)
{
struct bcm63xx_udc *udc = gadget_to_udc(gadget);
unsigned long flags;
similarity index 99%
rename from drivers/usb/gadget/dummy_hcd.c
rename to drivers/usb/gadget/udc/dummy_hcd.c
index 8c06430dcc476d78ba4ba389e22fe0c9b2f3efde..65ed3aebdfe2a142b79883ae4c0d40255705f4fa 100644 (file)
rename from drivers/usb/gadget/dummy_hcd.c
rename to drivers/usb/gadget/udc/dummy_hcd.c
index 8c06430dcc476d78ba4ba389e22fe0c9b2f3efde..65ed3aebdfe2a142b79883ae4c0d40255705f4fa 100644 (file)
static int dummy_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int dummy_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
+static int dummy_udc_stop(struct usb_gadget *g);
static const struct usb_gadget_ops dummy_ops = {
.get_frame = dummy_g_get_frame,
return 0;
}
-static int dummy_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int dummy_udc_stop(struct usb_gadget *g)
{
struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g);
struct dummy *dum = dum_hcd->dum;
similarity index 99%
rename from drivers/usb/gadget/fotg210-udc.c
rename to drivers/usb/gadget/udc/fotg210-udc.c
index e143d69f601798f1e94ac1a39cdac71744e5fe6f..b165f4f1267ed7bfe5da32e92875da24e98aee08 100644 (file)
rename from drivers/usb/gadget/fotg210-udc.c
rename to drivers/usb/gadget/udc/fotg210-udc.c
index e143d69f601798f1e94ac1a39cdac71744e5fe6f..b165f4f1267ed7bfe5da32e92875da24e98aee08 100644 (file)
iowrite32(value, fotg210->reg + FOTG210_DMISGR0);
}
-static int fotg210_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int fotg210_udc_stop(struct usb_gadget *g)
{
struct fotg210_udc *fotg210 = gadget_to_fotg210(g);
unsigned long flags;
similarity index 100%
rename from drivers/usb/gadget/fotg210.h
rename to drivers/usb/gadget/udc/fotg210.h
rename from drivers/usb/gadget/fotg210.h
rename to drivers/usb/gadget/udc/fotg210.h
similarity index 100%
rename from drivers/usb/gadget/fsl_mxc_udc.c
rename to drivers/usb/gadget/udc/fsl_mxc_udc.c
rename from drivers/usb/gadget/fsl_mxc_udc.c
rename to drivers/usb/gadget/udc/fsl_mxc_udc.c
similarity index 99%
rename from drivers/usb/gadget/fsl_qe_udc.c
rename to drivers/usb/gadget/udc/fsl_qe_udc.c
index ad548333516700401d1707e9b8981eced7bdde54..4b465f26d648b70d2f1ac87d9d615d927cef90ac 100644 (file)
rename from drivers/usb/gadget/fsl_qe_udc.c
rename to drivers/usb/gadget/udc/fsl_qe_udc.c
index ad548333516700401d1707e9b8981eced7bdde54..4b465f26d648b70d2f1ac87d9d615d927cef90ac 100644 (file)
static int fsl_qe_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver);
-static int fsl_qe_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver);
+static int fsl_qe_stop(struct usb_gadget *gadget);
/* defined in usb_gadget.h */
static const struct usb_gadget_ops qe_gadget_ops = {
return 0;
}
-static int fsl_qe_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int fsl_qe_stop(struct usb_gadget *gadget)
{
struct qe_udc *udc;
struct qe_ep *loop_ep;
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_LICENSE("GPL");
-
similarity index 100%
rename from drivers/usb/gadget/fsl_qe_udc.h
rename to drivers/usb/gadget/udc/fsl_qe_udc.h
rename from drivers/usb/gadget/fsl_qe_udc.h
rename to drivers/usb/gadget/udc/fsl_qe_udc.h
similarity index 99%
rename from drivers/usb/gadget/fsl_udc_core.c
rename to drivers/usb/gadget/udc/fsl_udc_core.c
index 68843f081377f884ff4f2d426c8518d39e0990cf..9c4d574a3dc1eb129051b9e34d9c3ab26f5cac00 100644 (file)
rename from drivers/usb/gadget/fsl_udc_core.c
rename to drivers/usb/gadget/udc/fsl_udc_core.c
index 68843f081377f884ff4f2d426c8518d39e0990cf..9c4d574a3dc1eb129051b9e34d9c3ab26f5cac00 100644 (file)
static int fsl_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int fsl_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
-/* defined in gadget.h */
+static int fsl_udc_stop(struct usb_gadget *g);
+
static const struct usb_gadget_ops fsl_gadget_ops = {
.get_frame = fsl_get_frame,
.wakeup = fsl_wakeup,
}
/* Disconnect from gadget driver */
-static int fsl_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int fsl_udc_stop(struct usb_gadget *g)
{
struct fsl_ep *loop_ep;
unsigned long flags;
similarity index 100%
rename from drivers/usb/gadget/fsl_usb2_udc.h
rename to drivers/usb/gadget/udc/fsl_usb2_udc.h
rename from drivers/usb/gadget/fsl_usb2_udc.h
rename to drivers/usb/gadget/udc/fsl_usb2_udc.h
similarity index 99%
rename from drivers/usb/gadget/fusb300_udc.c
rename to drivers/usb/gadget/udc/fusb300_udc.c
index 3deb4e9380717386aca6c8638e25f6514d6ec60e..2c22b1a68bcf51f0c0ad3c63cd59b902a28be7be 100644 (file)
rename from drivers/usb/gadget/fusb300_udc.c
rename to drivers/usb/gadget/udc/fusb300_udc.c
index 3deb4e9380717386aca6c8638e25f6514d6ec60e..2c22b1a68bcf51f0c0ad3c63cd59b902a28be7be 100644 (file)
return 0;
}
-static int fusb300_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int fusb300_udc_stop(struct usb_gadget *g)
{
struct fusb300 *fusb300 = to_fusb300(g);
similarity index 100%
rename from drivers/usb/gadget/fusb300_udc.h
rename to drivers/usb/gadget/udc/fusb300_udc.h
rename from drivers/usb/gadget/fusb300_udc.h
rename to drivers/usb/gadget/udc/fusb300_udc.h
similarity index 100%
rename from drivers/usb/gadget/gadget_chips.h
rename to drivers/usb/gadget/udc/gadget_chips.h
rename from drivers/usb/gadget/gadget_chips.h
rename to drivers/usb/gadget/udc/gadget_chips.h
similarity index 99%
rename from drivers/usb/gadget/goku_udc.c
rename to drivers/usb/gadget/udc/goku_udc.c
index 6c85839e15adb8936c80cc8a449cca9981a166ba..e88cd9345fa41b9f71c94e5f672c3d069e54a9d3 100644 (file)
rename from drivers/usb/gadget/goku_udc.c
rename to drivers/usb/gadget/udc/goku_udc.c
index 6c85839e15adb8936c80cc8a449cca9981a166ba..e88cd9345fa41b9f71c94e5f672c3d069e54a9d3 100644 (file)
static int goku_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int goku_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
+static int goku_udc_stop(struct usb_gadget *g);
static const struct usb_gadget_ops goku_ops = {
.get_frame = goku_get_frame,
udc_enable(dev);
}
-static int goku_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int goku_udc_stop(struct usb_gadget *g)
{
struct goku_udc *dev = to_goku_udc(g);
unsigned long flags;
similarity index 99%
rename from drivers/usb/gadget/goku_udc.h
rename to drivers/usb/gadget/udc/goku_udc.h
index 86d2adafe149a1ccfb811584f1284ce331e34ab5..1ebb6353d65a6b0823be16169d8b74e67927f5da 100644 (file)
rename from drivers/usb/gadget/goku_udc.h
rename to drivers/usb/gadget/udc/goku_udc.h
index 86d2adafe149a1ccfb811584f1284ce331e34ab5..1ebb6353d65a6b0823be16169d8b74e67927f5da 100644 (file)
xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
xprintk(dev , KERN_INFO , fmt , ## args)
-
similarity index 99%
rename from drivers/usb/gadget/gr_udc.c
rename to drivers/usb/gadget/udc/gr_udc.c
index 25e039bd512cf3f66390098d83429f6a1feb4306..b0d6d6163373851074472b40ee25354edeae26ec 100644 (file)
rename from drivers/usb/gadget/gr_udc.c
rename to drivers/usb/gadget/udc/gr_udc.c
index 25e039bd512cf3f66390098d83429f6a1feb4306..b0d6d6163373851074472b40ee25354edeae26ec 100644 (file)
return 0;
}
-static int gr_udc_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int gr_udc_stop(struct usb_gadget *gadget)
{
struct gr_udc *dev = to_gr_udc(gadget);
unsigned long flags;
similarity index 100%
rename from drivers/usb/gadget/gr_udc.h
rename to drivers/usb/gadget/udc/gr_udc.h
rename from drivers/usb/gadget/gr_udc.h
rename to drivers/usb/gadget/udc/gr_udc.h
similarity index 99%
rename from drivers/usb/gadget/lpc32xx_udc.c
rename to drivers/usb/gadget/udc/lpc32xx_udc.c
index a139894c600fc6a5f022d78e37f1d15ce0bc2934..be8df266003eede306293c6569fcdc90812ee4a8 100644 (file)
rename from drivers/usb/gadget/lpc32xx_udc.c
rename to drivers/usb/gadget/udc/lpc32xx_udc.c
index a139894c600fc6a5f022d78e37f1d15ce0bc2934..be8df266003eede306293c6569fcdc90812ee4a8 100644 (file)
}
static int lpc32xx_start(struct usb_gadget *, struct usb_gadget_driver *);
-static int lpc32xx_stop(struct usb_gadget *, struct usb_gadget_driver *);
+static int lpc32xx_stop(struct usb_gadget *);
static const struct usb_gadget_ops lpc32xx_udc_ops = {
.get_frame = lpc32xx_get_frame,
return 0;
}
-static int lpc32xx_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int lpc32xx_stop(struct usb_gadget *gadget)
{
int i;
struct lpc32xx_udc *udc = to_udc(gadget);
similarity index 99%
rename from drivers/usb/gadget/m66592-udc.c
rename to drivers/usb/gadget/udc/m66592-udc.c
index 0d17174b86f8bbec733541270cc886ddf74c1d5e..114ef78d2097a3635d2b80a5511fccf95674b0dc 100644 (file)
rename from drivers/usb/gadget/m66592-udc.c
rename to drivers/usb/gadget/udc/m66592-udc.c
index 0d17174b86f8bbec733541270cc886ddf74c1d5e..114ef78d2097a3635d2b80a5511fccf95674b0dc 100644 (file)
return 0;
}
-static int m66592_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int m66592_udc_stop(struct usb_gadget *g)
{
struct m66592 *m66592 = to_m66592(g);
similarity index 99%
rename from drivers/usb/gadget/m66592-udc.h
rename to drivers/usb/gadget/udc/m66592-udc.h
index 96d49d7bfb6b8fd64b45d9fe8673f490c6491b43..9585d900584d761bf6e340f80c012dc0ebec83a0 100644 (file)
rename from drivers/usb/gadget/m66592-udc.h
rename to drivers/usb/gadget/udc/m66592-udc.h
index 96d49d7bfb6b8fd64b45d9fe8673f490c6491b43..9585d900584d761bf6e340f80c012dc0ebec83a0 100644 (file)
}
#endif /* ifndef __M66592_UDC_H__ */
-
-
similarity index 100%
rename from drivers/usb/gadget/mv_u3d.h
rename to drivers/usb/gadget/udc/mv_u3d.h
rename from drivers/usb/gadget/mv_u3d.h
rename to drivers/usb/gadget/udc/mv_u3d.h
similarity index 99%
rename from drivers/usb/gadget/mv_u3d_core.c
rename to drivers/usb/gadget/udc/mv_u3d_core.c
index 16248711c152d86386131e91783b30691766b743..5e286e7e7aad9ab4a60b0b515ecb355fcc17ccb6 100644 (file)
rename from drivers/usb/gadget/mv_u3d_core.c
rename to drivers/usb/gadget/udc/mv_u3d_core.c
index 16248711c152d86386131e91783b30691766b743..5e286e7e7aad9ab4a60b0b515ecb355fcc17ccb6 100644 (file)
return 0;
}
-static int mv_u3d_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int mv_u3d_stop(struct usb_gadget *g)
{
struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
similarity index 100%
rename from drivers/usb/gadget/mv_udc.h
rename to drivers/usb/gadget/udc/mv_udc.h
rename from drivers/usb/gadget/mv_udc.h
rename to drivers/usb/gadget/udc/mv_udc.h
similarity index 99%
rename from drivers/usb/gadget/mv_udc_core.c
rename to drivers/usb/gadget/udc/mv_udc_core.c
index fcff3a571b45da76ff466bcb76bbe219d9d25e53..85faa3d34e131eb24b284d2f9553a42c4100b3da 100644 (file)
rename from drivers/usb/gadget/mv_udc_core.c
rename to drivers/usb/gadget/udc/mv_udc_core.c
index fcff3a571b45da76ff466bcb76bbe219d9d25e53..85faa3d34e131eb24b284d2f9553a42c4100b3da 100644 (file)
}
static int mv_udc_start(struct usb_gadget *, struct usb_gadget_driver *);
-static int mv_udc_stop(struct usb_gadget *, struct usb_gadget_driver *);
+static int mv_udc_stop(struct usb_gadget *);
/* device controller usb_gadget_ops structure */
static const struct usb_gadget_ops mv_ops = {
return 0;
}
-static int mv_udc_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int mv_udc_stop(struct usb_gadget *gadget)
{
struct mv_udc *udc;
unsigned long flags;
similarity index 99%
rename from drivers/usb/gadget/net2272.c
rename to drivers/usb/gadget/udc/net2272.c
index ca15405583e20bf1ad58b89e749ca293a013dfc8..d1181bc0d3193aa800e62e6b02eec27facfa6725 100644 (file)
rename from drivers/usb/gadget/net2272.c
rename to drivers/usb/gadget/udc/net2272.c
index ca15405583e20bf1ad58b89e749ca293a013dfc8..d1181bc0d3193aa800e62e6b02eec27facfa6725 100644 (file)
static int net2272_start(struct usb_gadget *_gadget,
struct usb_gadget_driver *driver);
-static int net2272_stop(struct usb_gadget *_gadget,
- struct usb_gadget_driver *driver);
+static int net2272_stop(struct usb_gadget *_gadget);
static const struct usb_gadget_ops net2272_ops = {
.get_frame = net2272_get_frame,
net2272_usb_reinit(dev);
}
-static int net2272_stop(struct usb_gadget *_gadget,
- struct usb_gadget_driver *driver)
+static int net2272_stop(struct usb_gadget *_gadget)
{
struct net2272 *dev;
unsigned long flags;
similarity index 100%
rename from drivers/usb/gadget/net2272.h
rename to drivers/usb/gadget/udc/net2272.h
rename from drivers/usb/gadget/net2272.h
rename to drivers/usb/gadget/udc/net2272.h
similarity index 99%
rename from drivers/usb/gadget/net2280.c
rename to drivers/usb/gadget/udc/net2280.c
index 300b3a71383b95fbd732245613593cc2a2704620..548ebd15f57dff81e0fa2a3bb45342259fec0797 100644 (file)
rename from drivers/usb/gadget/net2280.c
rename to drivers/usb/gadget/udc/net2280.c
index 300b3a71383b95fbd732245613593cc2a2704620..548ebd15f57dff81e0fa2a3bb45342259fec0797 100644 (file)
static int net2280_start(struct usb_gadget *_gadget,
struct usb_gadget_driver *driver);
-static int net2280_stop(struct usb_gadget *_gadget,
- struct usb_gadget_driver *driver);
+static int net2280_stop(struct usb_gadget *_gadget);
static const struct usb_gadget_ops net2280_ops = {
.get_frame = net2280_get_frame,
usb_reinit (dev);
}
-static int net2280_stop(struct usb_gadget *_gadget,
- struct usb_gadget_driver *driver)
+static int net2280_stop(struct usb_gadget *_gadget)
{
struct net2280 *dev;
unsigned long flags;
similarity index 100%
rename from drivers/usb/gadget/net2280.h
rename to drivers/usb/gadget/udc/net2280.h
rename from drivers/usb/gadget/net2280.h
rename to drivers/usb/gadget/udc/net2280.h
similarity index 99%
rename from drivers/usb/gadget/omap_udc.c
rename to drivers/usb/gadget/udc/omap_udc.c
index 2ae4f6d69f74fa946f325d6436ae2774c551a230..a971594b38e60d7c02715e470ee83942a9ed6f4f 100644 (file)
rename from drivers/usb/gadget/omap_udc.c
rename to drivers/usb/gadget/udc/omap_udc.c
index 2ae4f6d69f74fa946f325d6436ae2774c551a230..a971594b38e60d7c02715e470ee83942a9ed6f4f 100644 (file)
static int omap_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int omap_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
+static int omap_udc_stop(struct usb_gadget *g);
static const struct usb_gadget_ops omap_gadget_ops = {
.get_frame = omap_get_frame,
return status;
}
-static int omap_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int omap_udc_stop(struct usb_gadget *g)
{
unsigned long flags;
int status = -ENODEV;
similarity index 99%
rename from drivers/usb/gadget/omap_udc.h
rename to drivers/usb/gadget/udc/omap_udc.h
index cfadeb5fc5deba66ac66e7a2228812f08fcd5261..52b7bbd6534134732069895b8cfaaa7294227df7 100644 (file)
rename from drivers/usb/gadget/omap_udc.h
rename to drivers/usb/gadget/udc/omap_udc.h
index cfadeb5fc5deba66ac66e7a2228812f08fcd5261..52b7bbd6534134732069895b8cfaaa7294227df7 100644 (file)
#define HMC_1510 ((omap_readl(MOD_CONF_CTRL_0) >> 1) & 0x3f)
#define HMC_1610 (omap_readl(OTG_SYSCON_2) & 0x3f)
#define HMC (cpu_is_omap15xx() ? HMC_1510 : HMC_1610)
-
similarity index 99%
rename from drivers/usb/gadget/pch_udc.c
rename to drivers/usb/gadget/udc/pch_udc.c
index 460d953c91b6c9b540d2af185b3f2664ea39613b..6075b60b6786919719305d3c6b9d785833e6c5e2 100644 (file)
rename from drivers/usb/gadget/pch_udc.c
rename to drivers/usb/gadget/udc/pch_udc.c
index 460d953c91b6c9b540d2af185b3f2664ea39613b..6075b60b6786919719305d3c6b9d785833e6c5e2 100644 (file)
static int pch_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int pch_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
+static int pch_udc_stop(struct usb_gadget *g);
+
static const struct usb_gadget_ops pch_udc_ops = {
.get_frame = pch_udc_pcd_get_frame,
.wakeup = pch_udc_pcd_wakeup,
return 0;
}
-static int pch_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int pch_udc_stop(struct usb_gadget *g)
{
struct pch_udc_dev *dev = to_pch_udc(g);
similarity index 99%
rename from drivers/usb/gadget/pxa25x_udc.c
rename to drivers/usb/gadget/udc/pxa25x_udc.c
index 9984437d295209512d4d1696d02e1fb57874a6c3..0d3e4e0c7d943f02adf0ce1638de923b6aed57c1 100644 (file)
rename from drivers/usb/gadget/pxa25x_udc.c
rename to drivers/usb/gadget/udc/pxa25x_udc.c
index 9984437d295209512d4d1696d02e1fb57874a6c3..0d3e4e0c7d943f02adf0ce1638de923b6aed57c1 100644 (file)
static int pxa25x_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int pxa25x_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
+static int pxa25x_udc_stop(struct usb_gadget *g);
static const struct usb_gadget_ops pxa25x_udc_ops = {
.get_frame = pxa25x_udc_get_frame,
udc_reinit(dev);
}
-static int pxa25x_udc_stop(struct usb_gadget*g,
- struct usb_gadget_driver *driver)
+static int pxa25x_udc_stop(struct usb_gadget*g)
{
struct pxa25x_udc *dev = to_pxa25x(g);
similarity index 100%
rename from drivers/usb/gadget/pxa25x_udc.h
rename to drivers/usb/gadget/udc/pxa25x_udc.h
rename from drivers/usb/gadget/pxa25x_udc.h
rename to drivers/usb/gadget/udc/pxa25x_udc.h
similarity index 99%
rename from drivers/usb/gadget/pxa27x_udc.c
rename to drivers/usb/gadget/udc/pxa27x_udc.c
index cdf4d678be9638c1edaa230760b487740a5f0bf6..322faf54d98bc5d932acc8288f21d98d7460d8f6 100644 (file)
rename from drivers/usb/gadget/pxa27x_udc.c
rename to drivers/usb/gadget/udc/pxa27x_udc.c
index cdf4d678be9638c1edaa230760b487740a5f0bf6..322faf54d98bc5d932acc8288f21d98d7460d8f6 100644 (file)
static int pxa27x_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int pxa27x_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
+static int pxa27x_udc_stop(struct usb_gadget *g);
static const struct usb_gadget_ops pxa_udc_ops = {
.get_frame = pxa_udc_get_frame,
@@ -1859,8 +1858,7 @@ static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
*
* Returns 0 if no error, -ENODEV, -EINVAL otherwise
*/
-static int pxa27x_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int pxa27x_udc_stop(struct usb_gadget *g)
{
struct pxa_udc *udc = to_pxa(g);
similarity index 100%
rename from drivers/usb/gadget/pxa27x_udc.h
rename to drivers/usb/gadget/udc/pxa27x_udc.h
rename from drivers/usb/gadget/pxa27x_udc.h
rename to drivers/usb/gadget/udc/pxa27x_udc.h
similarity index 99%
rename from drivers/usb/gadget/r8a66597-udc.c
rename to drivers/usb/gadget/udc/r8a66597-udc.c
index b698a490cc7d78e345a4a518af3c39238c8cb5af..6e4b7e8ecb6b40869ed6974239dcf94ce17dad27 100644 (file)
rename from drivers/usb/gadget/r8a66597-udc.c
rename to drivers/usb/gadget/udc/r8a66597-udc.c
index b698a490cc7d78e345a4a518af3c39238c8cb5af..6e4b7e8ecb6b40869ed6974239dcf94ce17dad27 100644 (file)
return 0;
}
-static int r8a66597_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int r8a66597_stop(struct usb_gadget *gadget)
{
struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
unsigned long flags;
similarity index 99%
rename from drivers/usb/gadget/r8a66597-udc.h
rename to drivers/usb/gadget/udc/r8a66597-udc.h
index 45c4b2df1785d0de45bbd19669b351abaf85fd55..d00099a101f76780da3017dc212a853ef94c7c20 100644 (file)
rename from drivers/usb/gadget/r8a66597-udc.h
rename to drivers/usb/gadget/udc/r8a66597-udc.h
index 45c4b2df1785d0de45bbd19669b351abaf85fd55..d00099a101f76780da3017dc212a853ef94c7c20 100644 (file)
disable_pipe_irq(r8a66597, pipenum, NRDYENB)
#endif /* __R8A66597_H__ */
-
similarity index 99%
rename from drivers/usb/gadget/s3c-hsudc.c
rename to drivers/usb/gadget/udc/s3c-hsudc.c
index ea4bbfe72ec0ba1ef0ff111fd1f982b2db981565..c0b55147bfa639de6f097b8a1ffc9ae176d65409 100644 (file)
rename from drivers/usb/gadget/s3c-hsudc.c
rename to drivers/usb/gadget/udc/s3c-hsudc.c
index ea4bbfe72ec0ba1ef0ff111fd1f982b2db981565..c0b55147bfa639de6f097b8a1ffc9ae176d65409 100644 (file)
return ret;
}
-static int s3c_hsudc_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int s3c_hsudc_stop(struct usb_gadget *gadget)
{
struct s3c_hsudc *hsudc = to_hsudc(gadget);
unsigned long flags;
similarity index 99%
rename from drivers/usb/gadget/s3c2410_udc.c
rename to drivers/usb/gadget/udc/s3c2410_udc.c
index 7987aa049fab2ba62781dcca616bb2917cfe56e2..d89d5601effa6856ced79e85f43489d8c8a758e2 100644 (file)
rename from drivers/usb/gadget/s3c2410_udc.c
rename to drivers/usb/gadget/udc/s3c2410_udc.c
index 7987aa049fab2ba62781dcca616bb2917cfe56e2..d89d5601effa6856ced79e85f43489d8c8a758e2 100644 (file)
static int s3c2410_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int s3c2410_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
+static int s3c2410_udc_stop(struct usb_gadget *g);
static const struct usb_gadget_ops s3c2410_ops = {
.get_frame = s3c2410_udc_get_frame,
return 0;
}
-static int s3c2410_udc_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int s3c2410_udc_stop(struct usb_gadget *g)
{
struct s3c2410_udc *udc = to_s3c2410(g);
similarity index 100%
rename from drivers/usb/gadget/s3c2410_udc.h
rename to drivers/usb/gadget/udc/s3c2410_udc.h
rename from drivers/usb/gadget/s3c2410_udc.h
rename to drivers/usb/gadget/udc/s3c2410_udc.h
similarity index 75%
rename from drivers/usb/gadget/udc-core.c
rename to drivers/usb/gadget/udc/udc-core.c
index 38913eac6e7c9c731eecb90a5f4efbd27f200998..154eca7dbb5e331250ad6bbc0681d0e8cb273334 100644 (file)
rename from drivers/usb/gadget/udc-core.c
rename to drivers/usb/gadget/udc/udc-core.c
index 38913eac6e7c9c731eecb90a5f4efbd27f200998..154eca7dbb5e331250ad6bbc0681d0e8cb273334 100644 (file)
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
/**
* struct usb_udc - describes one usb device controller
* @dev - the child device to the actual controller
* @gadget - the gadget. For use by the class code
* @list - for use by the udc class driver
+ * @is_otg - we're registered with OTG core and it takes care of UDC start/stop
*
* This represents the internal data structure which is used by the UDC-class
* to hold information about udc driver and gadget together.
struct usb_gadget *gadget;
struct device dev;
struct list_head list;
+ bool is_otg;
};
static struct class *udc_class;
/* ------------------------------------------------------------------------- */
+/**
+ * usb_gadget_giveback_request - give the request back to the gadget layer
+ * Context: in_interrupt()
+ *
+ * This is called by device controller drivers in order to return the
+ * completed request back to the gadget layer.
+ */
+void usb_gadget_giveback_request(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ if (likely(req->status == 0))
+ usb_led_activity(USB_LED_EVENT_GADGET);
+
+ req->complete(ep, req);
+}
+EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
+
+/* ------------------------------------------------------------------------- */
+
static void usb_gadget_state_work(struct work_struct *work)
{
struct usb_gadget *gadget = work_to_gadget(work);
+ struct usb_udc *udc = NULL;
- sysfs_notify(&gadget->dev.kobj, NULL, "state");
+ mutex_lock(&udc_lock);
+ list_for_each_entry(udc, &udc_list, list)
+ if (udc->gadget == gadget)
+ goto found;
+ mutex_unlock(&udc_lock);
+
+ return;
+
+found:
+ mutex_unlock(&udc_lock);
+
+ sysfs_notify(&udc->dev.kobj, NULL, "state");
}
void usb_gadget_set_state(struct usb_gadget *gadget,
/* ------------------------------------------------------------------------- */
+/**
+ * usb_gadget_udc_reset - notifies the udc core that bus reset occurs
+ * @gadget: The gadget which bus reset occurs
+ * @driver: The gadget driver we want to notify
+ *
+ * If the udc driver has bus reset handler, it needs to call this when the bus
+ * reset occurs, it notifies the gadget driver that the bus reset occurs as
+ * well as updates gadget state.
+ */
+void usb_gadget_udc_reset(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
+{
+ driver->reset(gadget);
+ usb_gadget_set_state(gadget, USB_STATE_DEFAULT);
+}
+EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
+
/**
* usb_gadget_udc_start - tells usb device controller to start up
- * @gadget: The gadget we want to get started
- * @driver: The driver we want to bind to @gadget
+ * @udc: The UDC to be started
*
* This call is issued by the UDC Class driver when it's about
* to register a gadget driver to the device controller, before
*
* Returns zero on success, else negative errno.
*/
-static inline int usb_gadget_udc_start(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static inline int usb_gadget_udc_start(struct usb_udc *udc)
{
- return gadget->ops->udc_start(gadget, driver);
+ dev_dbg(&udc->dev, "%s\n", __func__);
+ return udc->gadget->ops->udc_start(udc->gadget, udc->driver);
}
/**
* far as powering off UDC completely and disable its data
* line pullups.
*/
-static inline void usb_gadget_udc_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static inline void usb_gadget_udc_stop(struct usb_udc *udc)
{
- gadget->ops->udc_stop(gadget, driver);
+ dev_dbg(&udc->dev, "%s\n", __func__);
+ udc->gadget->ops->udc_stop(udc->gadget);
+}
+
+/**
+ * usb_gadget_start - start the usb gadget controller and connect to bus
+ * @gadget: the gadget device to start
+ *
+ * This is external API for use by OTG core.
+ *
+ * Start the usb device controller and connect to bus (enable pull).
+ */
+static int usb_gadget_start(struct usb_gadget *gadget)
+{
+ int ret;
+ struct usb_udc *udc = NULL;
+
+ dev_dbg(&gadget->dev, "%s\n", __func__);
+ mutex_lock(&udc_lock);
+ list_for_each_entry(udc, &udc_list, list)
+ if (udc->gadget == gadget)
+ goto found;
+
+ dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
+ __func__);
+ mutex_unlock(&udc_lock);
+ return -EINVAL;
+
+found:
+ ret = usb_gadget_udc_start(udc);
+ if (ret)
+ dev_err(&udc->dev, "USB Device Controller didn't start: %d\n",
+ ret);
+ else
+ usb_gadget_connect(udc->gadget);
+
+ mutex_unlock(&udc_lock);
+
+ return ret;
+}
+
+/**
+ * usb_gadget_stop - disconnect from bus and stop the usb gadget
+ * @gadget: The gadget device we want to stop
+ *
+ * This is external API for use by OTG core.
+ *
+ * Disconnect from the bus (disable pull) and stop the
+ * gadget controller.
+ */
+static int usb_gadget_stop(struct usb_gadget *gadget)
+{
+ struct usb_udc *udc = NULL;
+
+ dev_dbg(&gadget->dev, "%s\n", __func__);
+ mutex_lock(&udc_lock);
+ list_for_each_entry(udc, &udc_list, list)
+ if (udc->gadget == gadget)
+ goto found;
+
+ dev_err(gadget->dev.parent, "%s: gadget not registered.\n",
+ __func__);
+ mutex_unlock(&udc_lock);
+ return -EINVAL;
+
+found:
+ usb_gadget_disconnect(udc->gadget);
+ udc->driver->disconnect(udc->gadget);
+ usb_gadget_udc_stop(udc);
+ mutex_unlock(&udc_lock);
+
+ return 0;
}
/**
}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
+/* udc_lock must be held */
static void usb_gadget_remove_driver(struct usb_udc *udc)
{
dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
- udc->gadget->name);
+ udc->driver->function);
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
- usb_gadget_disconnect(udc->gadget);
- udc->driver->disconnect(udc->gadget);
+ /* If OTG, the otg core ensures UDC is stopped on unregister */
+ if (udc->is_otg) {
+ mutex_unlock(&udc_lock);
+ usb_otg_unregister_gadget(udc->gadget);
+ mutex_lock(&udc_lock);
+ } else {
+ usb_gadget_disconnect(udc->gadget);
+ udc->driver->disconnect(udc->gadget);
+ usb_gadget_udc_stop(udc);
+ }
+
udc->driver->unbind(udc->gadget);
- usb_gadget_udc_stop(udc->gadget, NULL);
udc->driver = NULL;
udc->dev.driver = NULL;
dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
list_del(&udc->list);
- mutex_unlock(&udc_lock);
if (udc->driver)
usb_gadget_remove_driver(udc);
+ mutex_unlock(&udc_lock);
+
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
flush_work(&gadget->work);
device_unregister(&udc->dev);
/* ------------------------------------------------------------------------- */
+static struct otg_gadget_ops otg_gadget_intf = {
+ .start = usb_gadget_start,
+ .stop = usb_gadget_stop,
+};
+
+/* udc_lock must be held */
static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
{
int ret;
@@ -346,12 +483,19 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
ret = driver->bind(udc->gadget, driver);
if (ret)
goto err1;
- ret = usb_gadget_udc_start(udc->gadget, driver);
- if (ret) {
- driver->unbind(udc->gadget);
- goto err1;
+
+ /* If OTG, the otg core starts the UDC when needed */
+ mutex_unlock(&udc_lock);
+ udc->is_otg = !usb_otg_register_gadget(udc->gadget, &otg_gadget_intf);
+ mutex_lock(&udc_lock);
+ if (!udc->is_otg) {
+ ret = usb_gadget_udc_start(udc);
+ if (ret) {
+ driver->unbind(udc->gadget);
+ goto err1;
+ }
+ usb_gadget_connect(udc->gadget);
}
- usb_gadget_connect(udc->gadget);
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
return 0;
return ret;
}
-int udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
+int usb_udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
{
struct usb_udc *udc = NULL;
int ret = -ENODEV;
mutex_unlock(&udc_lock);
return ret;
}
-EXPORT_SYMBOL_GPL(udc_attach_driver);
+EXPORT_SYMBOL_GPL(usb_udc_attach_driver);
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
{
return -EOPNOTSUPP;
}
+ /* In OTG mode we don't support softconnect, but b_bus_req */
+ if (udc->is_otg) {
+ dev_err(dev, "soft-connect not supported in OTG mode\n");
+ return -EOPNOTSUPP;
+ }
+
if (sysfs_streq(buf, "connect")) {
- usb_gadget_udc_start(udc->gadget, udc->driver);
+ usb_gadget_udc_start(udc);
usb_gadget_connect(udc->gadget);
} else if (sysfs_streq(buf, "disconnect")) {
usb_gadget_disconnect(udc->gadget);
- usb_gadget_udc_stop(udc->gadget, udc->driver);
+ udc->driver->disconnect(udc->gadget);
+ usb_gadget_udc_stop(udc);
} else {
dev_err(dev, "unsupported command '%s'\n", buf);
return -EINVAL;
static USB_UDC_ATTR(b_hnp_enable);
static USB_UDC_ATTR(a_hnp_support);
static USB_UDC_ATTR(a_alt_hnp_support);
+static USB_UDC_ATTR(is_selfpowered);
static struct attribute *usb_udc_attrs[] = {
&dev_attr_srp.attr,
&dev_attr_b_hnp_enable.attr,
&dev_attr_a_hnp_support.attr,
&dev_attr_a_alt_hnp_support.attr,
+ &dev_attr_is_selfpowered.attr,
NULL,
};
index 748631bb9ae3fc0c643c5f3743e1b5ca4c7cc9ff..27954f67949dc009ad76bbf6825b7a5a5ba91ec0 100644 (file)
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
if USB_XHCI_HCD
+config USB_XHCI_PCI
+ tristate
+ depends on PCI
+ default y
+
config USB_XHCI_PLATFORM
tristate
index b59ca3c9415d00f429827e08f8a2e150a7676594..2d80a3c767e827bf1490ef5c1fa82b43d3375643 100644 (file)
xhci-hcd-y := xhci.o xhci-mem.o
xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
xhci-hcd-y += xhci-trace.o
-xhci-hcd-$(CONFIG_PCI) += xhci-pci.o
-ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
- xhci-hcd-y += xhci-plat.o
+xhci-plat-hcd-y := xhci-plat.o
ifneq ($(CONFIG_USB_XHCI_MVEBU), )
- xhci-hcd-y += xhci-mvebu.o
+ xhci-plat-hcd-y += xhci-mvebu.o
endif
ifneq ($(CONFIG_USB_XHCI_RCAR), )
- xhci-hcd-y += xhci-rcar.o
-endif
+ xhci-plat-hcd-y += xhci-rcar.o
endif
obj-$(CONFIG_USB_WHCI_HCD) += whci/
obj-$(CONFIG_PCI) += pci-quirks.o
+obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
+obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
+
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
index cf2734b532a7ab288d24dd13fd79db364490a748..4bdcd3439d4777976effabc3b739e1736809dfbf 100644 (file)
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
+ hcd->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n",
- hcd, ehci, hcd->phy);
+ hcd, ehci, hcd->usb_phy);
- if (!IS_ERR_OR_NULL(hcd->phy)) {
- retval = otg_set_host(hcd->phy->otg,
+ if (!IS_ERR_OR_NULL(hcd->usb_phy)) {
+ retval = otg_set_host(hcd->usb_phy->otg,
&ehci_to_hcd(ehci)->self);
if (retval) {
- usb_put_phy(hcd->phy);
+ usb_put_phy(hcd->usb_phy);
goto err2;
}
} else {
{
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
- if (!IS_ERR_OR_NULL(hcd->phy)) {
- otg_set_host(hcd->phy->otg, NULL);
- usb_put_phy(hcd->phy);
+ if (!IS_ERR_OR_NULL(hcd->usb_phy)) {
+ otg_set_host(hcd->usb_phy->otg, NULL);
+ usb_put_phy(hcd->usb_phy);
}
usb_remove_hcd(hcd);
index 7d6f64c447bf0971558cb2f7f9c10ab9f06e3971..28a5b488eb3020efc42e42485622039fdab91f1d 100644 (file)
#ifdef CONFIG_USB_OTG
if ((hcd->self.otg_port == (wIndex + 1))
&& hcd->self.b_hnp_enable) {
- otg_start_hnp(hcd->phy->otg);
+ otg_start_hnp(hcd->usb_phy->otg);
break;
}
#endif
index f341651d6f6ce6e4ae67a2d53ab2cab3aefeb81e..fea9b159e917d9d065bc26aaffb530127119603c 100644 (file)
goto put_hcd;
}
- hcd->phy = phy;
+ hcd->usb_phy = phy;
device_init_wakeup(&pdev->dev, 1);
/*
* OTG device parent of HCD takes care of putting
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
- otg_set_host(hcd->phy->otg, NULL);
+ otg_set_host(hcd->usb_phy->otg, NULL);
/* FIXME: need to call usb_remove_hcd() here? */
index 633dbea28f300e3562151fe3a251432dc48f34db..7cc7357c07a6332f266ace29c4ebc4073ea64237 100644 (file)
if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
/* Resume completed, re-enable disconnect detection */
tegra->port_resuming = 0;
- tegra_usb_phy_postresume(hcd->phy);
+ tegra_usb_phy_postresume(hcd->usb_phy);
}
}
goto done;
/* Disable disconnect detection during port resume */
- tegra_usb_phy_preresume(hcd->phy);
+ tegra_usb_phy_preresume(hcd->usb_phy);
ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
err = PTR_ERR(u_phy);
goto cleanup_clk_en;
}
- hcd->phy = u_phy;
+ hcd->usb_phy = u_phy;
tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
"nvidia,needs-double-reset");
ehci->caps = hcd->regs + 0x100;
ehci->has_hostpc = soc_config->has_hostpc;
- err = usb_phy_init(hcd->phy);
+ err = usb_phy_init(hcd->usb_phy);
if (err) {
dev_err(&pdev->dev, "Failed to initialize phy\n");
goto cleanup_clk_en;
}
u_phy->otg->host = hcd_to_bus(hcd);
- err = usb_phy_set_suspend(hcd->phy, 0);
+ err = usb_phy_set_suspend(hcd->usb_phy, 0);
if (err) {
dev_err(&pdev->dev, "Failed to power on the phy\n");
goto cleanup_phy;
cleanup_otg_set_host:
otg_set_host(u_phy->otg, NULL);
cleanup_phy:
- usb_phy_shutdown(hcd->phy);
+ usb_phy_shutdown(hcd->usb_phy);
cleanup_clk_en:
clk_disable_unprepare(tegra->clk);
cleanup_hcd_create:
struct tegra_ehci_hcd *tegra =
(struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
- otg_set_host(hcd->phy->otg, NULL);
+ otg_set_host(hcd->usb_phy->otg, NULL);
- usb_phy_shutdown(hcd->phy);
+ usb_phy_shutdown(hcd->usb_phy);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
index 98a89d16cc3e8f8e117b325620e36517e45ab523..8aa4ba0a0c695b8b188f47105dc0c109f2437b09 100644 (file)
/* resume signaling for 20 msec */
fotg210_writel(fotg210, temp | PORT_RESUME, status_reg);
fotg210->reset_done[wIndex] = jiffies
- + msecs_to_jiffies(20);
+ + msecs_to_jiffies(USB_RESUME_TIMEOUT);
break;
case USB_PORT_FEAT_C_SUSPEND:
clear_bit(wIndex, &fotg210->port_c_suspend);
index ba9499060f639c3bff934d4868ca71cfd6948bb4..3e3926aa584e00e50aca8c1b63387d6629c55662 100644 (file)
if ((temp & PORT_PE) == 0)
goto error;
- /* resume signaling for 20 msec */
fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
fusbh200->reset_done[wIndex] = jiffies
- + msecs_to_jiffies(20);
+ + msecs_to_jiffies(USB_RESUME_TIMEOUT);
break;
case USB_PORT_FEAT_C_SUSPEND:
clear_bit(wIndex, &fusbh200->port_c_suspend);
index 240e792c81a7b5e7a3c60406b7faf16bd01f743a..b62298fe0be80a2e3e68c5c9a0a9e2b50f9a78b7 100644 (file)
spin_unlock_irq(&isp116x->lock);
hcd->state = HC_STATE_RESUMING;
- msleep(20);
+ msleep(USB_RESUME_TIMEOUT);
/* Go operational */
spin_lock_irq(&isp116x->lock);
index c923cafcaca76bc5fa7cf918fd3e62e43b7caff9..4629dd7db728c21b120721d427ce9b2c39ba2c9f 100644 (file)
unsigned long flags;
u32 l;
- otg_start_hnp(hcd->phy->otg);
+ otg_start_hnp(hcd->usb_phy->otg);
local_irq_save(flags);
- hcd->phy->state = OTG_STATE_A_SUSPEND;
+ hcd->usb_phy->otg.state = OTG_STATE_A_SUSPEND;
writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]);
l = omap_readl(OTG_CTRL);
l &= ~OTG_A_BUSREQ;
#ifdef CONFIG_USB_OTG
if (need_transceiver) {
- hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!IS_ERR_OR_NULL(hcd->phy)) {
- int status = otg_set_host(hcd->phy->otg,
+ hcd->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(hcd->usb_phy)) {
+ int status = otg_set_host(hcd->usb_phy->otg,
&ohci_to_hcd(ohci)->self);
dev_dbg(hcd->self.controller, "init %s phy, status %d\n",
- hcd->phy->label, status);
+ hcd->usb_phy->label, status);
if (status) {
- usb_put_phy(hcd->phy);
+ usb_put_phy(hcd->usb_phy);
return status;
}
} else {
dev_dbg(hcd->self.controller, "stopping USB Controller\n");
usb_remove_hcd(hcd);
omap_ohci_clock_power(0);
- if (!IS_ERR_OR_NULL(hcd->phy)) {
- (void) otg_set_host(hcd->phy->otg, 0);
- usb_put_phy(hcd->phy);
+ if (!IS_ERR_OR_NULL(hcd->usb_phy)) {
+ (void) otg_set_host(hcd->usb_phy->otg, 0);
+ usb_put_phy(hcd->usb_phy);
}
if (machine_is_omap_osk())
gpio_free(9);
index 110b4b9ebeaa1f047056b29faf6f76d9a0808ff9..f130bb2f7bbea000272ef50c1cf62fea32eee04c 100644 (file)
rh->port &= ~USB_PORT_STAT_SUSPEND;
rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
- msleep(50);
+ msleep(USB_RESUME_TIMEOUT);
r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
}
index a517151867af33a0d62f57ed9674c1a0e6777654..0f53cc8c8ecf03eb1408fc2f9dfe2db21483f4af 100644 (file)
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
mod_timer(&sl811->timer, jiffies
- + msecs_to_jiffies(20));
+ + msecs_to_jiffies(USB_RESUME_TIMEOUT));
break;
case USB_PORT_FEAT_POWER:
port_power(sl811, 0);
index 93e17b12fb3304b0191f36b3eb2f2b6eef334132..98c66d88ebde2c58c0cbecfa79861d82d6474ad0 100644 (file)
/* Port received a wakeup request */
set_bit(port, &uhci->resuming_ports);
uhci->ports_timeout = jiffies +
- msecs_to_jiffies(25);
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
usb_hcd_start_port_resume(
&uhci_to_hcd(uhci)->self, port);
uhci_finish_suspend(uhci, port, port_addr);
/* USB v2.0 7.1.7.5 */
- uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
+ uhci->ports_timeout = jiffies +
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
break;
case USB_PORT_FEAT_POWER:
/* UHCI has no power switching */
index eb009a457fb537f6c6674d097e852de0501e98dc..bb89175ca6e5dd5e9669076ee3f5ddbde05c638e 100644 (file)
trace(&vaf);
va_end(args);
}
+EXPORT_SYMBOL_GPL(xhci_dbg_trace);
index 6d906932538f1a2244efb4f3b1dfd46b45b0a376..11f16cbaa4fdbd77b1b81ab115025da078cf55af 100644 (file)
static const char hcd_name[] = "xhci_hcd";
+static struct hc_driver __read_mostly xhci_pci_hc_driver;
+
+static int xhci_pci_setup(struct usb_hcd *hcd);
+
+static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
+ .extra_priv_size = sizeof(struct xhci_hcd),
+ .reset = xhci_pci_setup,
+};
+
/* called after powerup, by probe or system-pm "wakeup" */
static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)
{
if (!retval)
return retval;
- kfree(xhci);
return retval;
}
/* USB 2.0 roothub is stored in the PCI device now. */
hcd = dev_get_drvdata(&dev->dev);
xhci = hcd_to_xhci(hcd);
+ xhci->main_hcd = hcd;
xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev,
pci_name(dev), hcd);
if (!xhci->shared_hcd) {
goto dealloc_usb2_hcd;
}
- /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset)
- * is called by usb_add_hcd().
- */
- *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
-
retval = usb_add_hcd(xhci->shared_hcd, dev->irq,
IRQF_SHARED);
if (retval)
/* Workaround for spurious wakeups at shutdown with HSW */
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
pci_set_power_state(dev, PCI_D3hot);
-
- kfree(xhci);
}
#ifdef CONFIG_PM
* Systems with the TI redriver that loses port status change events
* need to have the registers polled during D3, so avoid D3cold.
*/
- if (xhci_compliance_mode_recovery_timer_quirk_check())
+ if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
pdev->no_d3cold = true;
return xhci_suspend(xhci, do_wakeup);
}
#endif /* CONFIG_PM */
-static const struct hc_driver xhci_pci_hc_driver = {
- .description = hcd_name,
- .product_desc = "xHCI Host Controller",
- .hcd_priv_size = sizeof(struct xhci_hcd *),
-
- /*
- * generic hardware linkage
- */
- .irq = xhci_irq,
- .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED,
-
- /*
- * basic lifecycle operations
- */
- .reset = xhci_pci_setup,
- .start = xhci_run,
-#ifdef CONFIG_PM
- .pci_suspend = xhci_pci_suspend,
- .pci_resume = xhci_pci_resume,
-#endif
- .stop = xhci_stop,
- .shutdown = xhci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = xhci_urb_enqueue,
- .urb_dequeue = xhci_urb_dequeue,
- .alloc_dev = xhci_alloc_dev,
- .free_dev = xhci_free_dev,
- .alloc_streams = xhci_alloc_streams,
- .free_streams = xhci_free_streams,
- .add_endpoint = xhci_add_endpoint,
- .drop_endpoint = xhci_drop_endpoint,
- .endpoint_reset = xhci_endpoint_reset,
- .check_bandwidth = xhci_check_bandwidth,
- .reset_bandwidth = xhci_reset_bandwidth,
- .address_device = xhci_address_device,
- .enable_device = xhci_enable_device,
- .update_hub_device = xhci_update_hub_device,
- .reset_device = xhci_discover_or_reset_device,
-
- /*
- * scheduling support
- */
- .get_frame_number = xhci_get_frame,
-
- /* Root hub support */
- .hub_control = xhci_hub_control,
- .hub_status_data = xhci_hub_status_data,
- .bus_suspend = xhci_bus_suspend,
- .bus_resume = xhci_bus_resume,
- /*
- * call back when device connected and addressed
- */
- .update_device = xhci_update_device,
- .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm,
- .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
- .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
- .find_raw_port_number = xhci_find_raw_port_number,
-};
-
/*-------------------------------------------------------------------------*/
/* PCI driver selection metadata; PCI hotplugging uses this */
#endif
};
-int __init xhci_register_pci(void)
+static int __init xhci_pci_init(void)
{
+ xhci_init_driver(&xhci_pci_hc_driver, &xhci_pci_overrides);
+#ifdef CONFIG_PM
+ xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
+ xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
+#endif
return pci_register_driver(&xhci_pci_driver);
}
+module_init(xhci_pci_init);
-void xhci_unregister_pci(void)
+static void __exit xhci_pci_exit(void)
{
pci_unregister_driver(&xhci_pci_driver);
}
+module_exit(xhci_pci_exit);
+
+MODULE_DESCRIPTION("xHCI PCI Host Controller Driver");
+MODULE_LICENSE("GPL");
index 8b084554542ef67cba6f9eb1b25422fb2046b25b..72f5be7bd2e11b39e58cda0b6e3963b18b91ff72 100644 (file)
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/drd.h>
#include <linux/usb/xhci_pdriver.h>
#include "xhci.h"
#include "xhci-mvebu.h"
#include "xhci-rcar.h"
-static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
-{
- struct usb_xhci_pdata *pdata = dev_get_platdata(dev);
+static struct hc_driver __read_mostly xhci_plat_hc_driver;
- if (pdata->usb_drd_support)
- xhci->quirks |= XHCI_DRD_SUPPORT;
+static int xhci_plat_setup(struct usb_hcd *hcd);
+static int xhci_plat_start(struct usb_hcd *hcd);
+
+static const struct xhci_driver_overrides xhci_plat_overrides __initconst = {
+ .extra_priv_size = sizeof(struct xhci_hcd),
+ .reset = xhci_plat_setup,
+ .start = xhci_plat_start,
+};
- if (pdata->usb_needs_lhc_reset)
- xhci->quirks |= XHCI_NEEDS_LHC_RESET;
+static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
/*
* As of now platform drivers don't provide MSI support so we ensure
* here that the generic code does not try to make a pci_dev from our
return xhci_run(hcd);
}
-static const struct hc_driver xhci_plat_xhci_driver = {
- .description = "xhci-hcd",
- .product_desc = "xHCI Host Controller",
- .hcd_priv_size = sizeof(struct xhci_hcd *),
-
- /*
- * generic hardware linkage
- */
- .irq = xhci_irq,
- .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED,
-
- /*
- * basic lifecycle operations
- */
- .reset = xhci_plat_setup,
- .start = xhci_plat_start,
- .stop = xhci_stop,
- .shutdown = xhci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = xhci_urb_enqueue,
- .urb_dequeue = xhci_urb_dequeue,
- .alloc_dev = xhci_alloc_dev,
- .free_dev = xhci_free_dev,
- .alloc_streams = xhci_alloc_streams,
- .free_streams = xhci_free_streams,
- .add_endpoint = xhci_add_endpoint,
- .drop_endpoint = xhci_drop_endpoint,
- .endpoint_reset = xhci_endpoint_reset,
- .check_bandwidth = xhci_check_bandwidth,
- .reset_bandwidth = xhci_reset_bandwidth,
- .address_device = xhci_address_device,
- .enable_device = xhci_enable_device,
- .update_hub_device = xhci_update_hub_device,
- .reset_device = xhci_discover_or_reset_device,
-
- /*
- * scheduling support
- */
- .get_frame_number = xhci_get_frame,
-
- /* Root hub support */
- .hub_control = xhci_hub_control,
- .hub_status_data = xhci_hub_status_data,
- .bus_suspend = xhci_bus_suspend,
- .bus_resume = xhci_bus_resume,
-
- .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
- .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
-};
-
static int xhci_plat_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct resource *res;
struct usb_hcd *hcd;
struct clk *clk;
- struct usb_drd_host *drd_host;
int ret;
int irq;
if (usb_disabled())
return -ENODEV;
- driver = &xhci_plat_xhci_driver;
+ driver = &xhci_plat_hc_driver;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
goto put_hcd;
}
- ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (ret)
- goto disable_clk;
-
device_wakeup_enable(hcd->self.controller);
- /* USB 2.0 roothub is stored in the platform_device now. */
- hcd = platform_get_drvdata(pdev);
xhci = hcd_to_xhci(hcd);
xhci->clk = clk;
+ xhci->main_hcd = hcd;
xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev,
dev_name(&pdev->dev), hcd);
if (!xhci->shared_hcd) {
ret = -ENOMEM;
- goto dealloc_usb2_hcd;
+ goto disable_clk;
}
if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
(pdata && pdata->usb3_lpm_capable))
xhci->quirks |= XHCI_LPM_SUPPORT;
- /*
- * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)
- * is called by usb_add_hcd().
- */
- *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
xhci->shared_hcd->can_do_streams = 1;
- ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+ ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret)
goto put_usb3_hcd;
- drd_host = kzalloc(sizeof(*drd_host), GFP_KERNEL);
- if (!drd_host)
- return -ENOMEM;
-
- drd_host->main_hcd = xhci->main_hcd;
- drd_host->shared_hcd = xhci->shared_hcd;
- drd_host->hcd_irq = irq;
- drd_host->host_setup = NULL;
-
- usb_drd_register_hcd(pdev->dev.parent, drd_host);
+ ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+ if (ret)
+ goto dealloc_usb2_hcd;
return 0;
-put_usb3_hcd:
- usb_put_hcd(xhci->shared_hcd);
-
dealloc_usb2_hcd:
usb_remove_hcd(hcd);
+put_usb3_hcd:
+ usb_put_hcd(xhci->shared_hcd);
+
disable_clk:
if (!IS_ERR(clk))
clk_disable_unprepare(clk);
struct clk *clk = xhci->clk;
usb_remove_hcd(xhci->shared_hcd);
- usb_put_hcd(xhci->shared_hcd);
-
usb_remove_hcd(hcd);
+
+ usb_put_hcd(xhci->shared_hcd);
if (!IS_ERR(clk))
clk_disable_unprepare(clk);
usb_put_hcd(hcd);
- usb_drd_unregister_hcd(dev->dev.parent);
- kfree(xhci);
return 0;
}
* reconsider this when xhci_plat_suspend enlarges its scope, e.g.,
* also applies to runtime suspend.
*/
-
- if (usb_drd_get_state(dev->parent) & DRD_HOST_ACTIVE)
- return xhci_suspend(xhci, device_may_wakeup(dev));
-
- return 0;
+ return xhci_suspend(xhci, device_may_wakeup(dev));
}
static int xhci_plat_resume(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- if (usb_drd_get_state(dev->parent) & DRD_HOST_ACTIVE)
- return xhci_resume(xhci, 0);
-
- return 0;
+ return xhci_resume(xhci, 0);
}
static const struct dev_pm_ops xhci_plat_pm_ops = {
};
MODULE_ALIAS("platform:xhci-hcd");
-int xhci_register_plat(void)
+static int __init xhci_plat_init(void)
{
+ xhci_init_driver(&xhci_plat_hc_driver, &xhci_plat_overrides);
return platform_driver_register(&usb_xhci_driver);
}
+module_init(xhci_plat_init);
-void xhci_unregister_plat(void)
+static void __exit xhci_plat_exit(void)
{
platform_driver_unregister(&usb_xhci_driver);
}
+module_exit(xhci_plat_exit);
+
+MODULE_DESCRIPTION("xHCI Platform Host Controller Driver");
+MODULE_LICENSE("GPL");
index 5856eee924b1fbbae2509f34f815bfc3ce0bb621..4867cae860ed261ebf8b47708f7f6abdaec56728 100644 (file)
} else {
xhci_dbg(xhci, "resume HS port %d\n", port_id);
bus_state->resume_done[faked_port_index] = jiffies +
- msecs_to_jiffies(20);
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
set_bit(faked_port_index, &bus_state->resuming_ports);
mod_timer(&hcd->rh_timer,
bus_state->resume_done[faked_port_index]);
{
int reserved_trbs = xhci->cmd_ring_reserved_trbs;
int ret;
- if (xhci->xhc_state & XHCI_STATE_DYING)
+
+ if (xhci->xhc_state) {
+ xhci_dbg(xhci, "xHCI dying or halted, can't queue_command\n");
return -ESHUTDOWN;
+ }
if (!command_must_succeed)
reserved_trbs++;
index 7cf30c83dcf3af899c3663f739d15bb3ed25e45a..367b630bdb3c0376e065bea040971784f8c39d81 100644 (file)
#define CREATE_TRACE_POINTS
#include "xhci-trace.h"
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(xhci_dbg_quirks);
index 8285330252888de0b032f13a927961540ca145ae..397c0dddafcc1641a1f5ff3a817361ad900b238c 100644 (file)
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Reset the HC");
command = readl(&xhci->op_regs->command);
- command |= (xhci->quirks & XHCI_NEEDS_LHC_RESET) ? CMD_LRESET : CMD_RESET;
+ command |= CMD_RESET;
writel(command, &xhci->op_regs->command);
ret = xhci_handshake(xhci, &xhci->op_regs->command,
- (xhci->quirks & XHCI_NEEDS_LHC_RESET) ? CMD_LRESET : CMD_RESET,
- 0, 10 * 1000 * 1000);
+ CMD_RESET, 0, 10 * 1000 * 1000);
if (ret)
return ret;
* Systems:
* Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820
*/
-bool xhci_compliance_mode_recovery_timer_quirk_check(void)
+static bool xhci_compliance_mode_recovery_timer_quirk_check(void)
{
const char *dmi_product_name, *dmi_sys_vendor;
"Finished xhci_run for USB2 roothub");
return 0;
}
+EXPORT_SYMBOL_GPL(xhci_run);
static void xhci_only_stop_hcd(struct usb_hcd *hcd)
{
spin_lock_irq(&xhci->lock);
xhci_halt(xhci);
-
- /* The shared_hcd is going to be deallocated shortly (the USB core only
- * calls this function when allocation fails in usb_add_hcd(), or
- * usb_remove_hcd() is called). So we need to unset xHCI's pointer.
- */
- if (!(xhci->quirks & XHCI_DRD_SUPPORT))
- xhci->shared_hcd = NULL;
spin_unlock_irq(&xhci->lock);
}
struct usb_hcd *hcd = xhci_to_hcd(xhci);
u32 command;
+ if (!hcd->state)
+ return 0;
+
if (hcd->state != HC_STATE_SUSPENDED ||
xhci->shared_hcd->state != HC_STATE_SUSPENDED)
return -EINVAL;
return rc;
}
+EXPORT_SYMBOL_GPL(xhci_suspend);
/*
* start xHC (not bus-specific)
int retval = 0;
bool comp_timer_running = false;
+ if (!hcd->state)
+ return 0;
+
/* Wait a bit if either of the roothubs need to settle from the
* transition into bus suspend.
*/
return retval;
}
+EXPORT_SYMBOL_GPL(xhci_resume);
#endif /* CONFIG_PM */
/*-------------------------------------------------------------------------*/
struct xhci_hcd *xhci;
struct device *dev = hcd->self.controller;
int retval;
- bool allocated = false;
/* Accept arbitrarily long scatter-gather lists */
hcd->self.sg_tablesize = ~0;
hcd->self.no_stop_on_short = 1;
if (usb_hcd_is_primary_hcd(hcd)) {
- if (*((struct xhci_hcd **)hcd->hcd_priv) == NULL) {
- xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL);
- if (!xhci)
- return -ENOMEM;
- *((struct xhci_hcd **)hcd->hcd_priv) = xhci;
- allocated = true;
- } else {
- xhci = *((struct xhci_hcd **)hcd->hcd_priv);
- }
- xhci->main_hcd = hcd;
+ xhci = hcd_to_xhci(hcd);
/* Mark the first roothub as being USB 2.0.
* The xHCI driver will register the USB 3.0 roothub.
*/
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
if (retval)
- goto error;
+ return retval;
xhci_dbg(xhci, "Resetting HCD\n");
/* Reset the internal HC memory state and registers. */
retval = xhci_reset(xhci);
if (retval)
- goto error;
+ return retval;
xhci_dbg(xhci, "Reset complete\n");
/* Set dma_mask and coherent_dma_mask to 64-bits,
/* Initialize HCD and host controller data structures. */
retval = xhci_init(hcd);
if (retval)
- goto error;
+ return retval;
xhci_dbg(xhci, "Called HCD init\n");
return 0;
-error:
- if (allocated) {
- *((struct xhci_hcd **)hcd->hcd_priv) = NULL;
- kfree(xhci);
+}
+EXPORT_SYMBOL_GPL(xhci_gen_setup);
+
+static const struct hc_driver xhci_hc_driver = {
+ .description = "xhci-hcd",
+ .product_desc = "xHCI Host Controller",
+ .hcd_priv_size = sizeof(struct xhci_hcd *),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = xhci_irq,
+ .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED,
+
+ /*
+ * basic lifecycle operations
+ */
+ .reset = NULL, /* set in xhci_init_driver() */
+ .start = xhci_run,
+ .stop = xhci_stop,
+ .shutdown = xhci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = xhci_urb_enqueue,
+ .urb_dequeue = xhci_urb_dequeue,
+ .alloc_dev = xhci_alloc_dev,
+ .free_dev = xhci_free_dev,
+ .alloc_streams = xhci_alloc_streams,
+ .free_streams = xhci_free_streams,
+ .add_endpoint = xhci_add_endpoint,
+ .drop_endpoint = xhci_drop_endpoint,
+ .endpoint_reset = xhci_endpoint_reset,
+ .check_bandwidth = xhci_check_bandwidth,
+ .reset_bandwidth = xhci_reset_bandwidth,
+ .address_device = xhci_address_device,
+ .enable_device = xhci_enable_device,
+ .update_hub_device = xhci_update_hub_device,
+ .reset_device = xhci_discover_or_reset_device,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = xhci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_control = xhci_hub_control,
+ .hub_status_data = xhci_hub_status_data,
+ .bus_suspend = xhci_bus_suspend,
+ .bus_resume = xhci_bus_resume,
+
+ /*
+ * call back when device connected and addressed
+ */
+ .update_device = xhci_update_device,
+ .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm,
+ .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
+ .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
+ .find_raw_port_number = xhci_find_raw_port_number,
+};
+
+void xhci_init_driver(struct hc_driver *drv,
+ const struct xhci_driver_overrides *over)
+{
+ BUG_ON(!over);
+
+ /* Copy the generic table to drv then apply the overrides */
+ *drv = xhci_hc_driver;
+
+ if (over) {
+ drv->hcd_priv_size += over->extra_priv_size;
+ if (over->reset)
+ drv->reset = over->reset;
+ if (over->start)
+ drv->start = over->start;
}
- return retval;
}
+EXPORT_SYMBOL_GPL(xhci_init_driver);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
static int __init xhci_hcd_init(void)
{
- int retval;
-
- retval = xhci_register_pci();
- if (retval < 0) {
- pr_debug("Problem registering PCI driver.\n");
- return retval;
- }
- retval = xhci_register_plat();
- if (retval < 0) {
- pr_debug("Problem registering platform driver.\n");
- goto unreg_pci;
- }
/*
* Check the compiler generated sizes of structures that must be laid
* out in specific ways for hardware access.
/* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
return 0;
-unreg_pci:
- xhci_unregister_pci();
- return retval;
}
module_init(xhci_hcd_init);
-
-static void __exit xhci_hcd_cleanup(void)
-{
- xhci_unregister_pci();
- xhci_unregister_plat();
-}
-module_exit(xhci_hcd_cleanup);
index ada24600f2cfaf4bb0d28dd277462a581adeffc6..870f4cccd986527cc93f6a9926f8c02420326b79 100644 (file)
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
#define XHCI_SPURIOUS_WAKEUP (1 << 18)
/* For controllers with a broken beyond repair streams implementation */
#define XHCI_BROKEN_STREAMS (1 << 19)
-#define XHCI_DRD_SUPPORT (1 << 20)
-#define XHCI_NEEDS_LHC_RESET (1 << 21)
unsigned int num_active_eps;
unsigned int limit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */
#define COMP_MODE_RCVRY_MSECS 2000
};
+/* Platform specific overrides to generic XHCI hc_driver ops */
+struct xhci_driver_overrides {
+ size_t extra_priv_size;
+ int (*reset)(struct usb_hcd *hcd);
+ int (*start)(struct usb_hcd *hcd);
+};
+
/* convert between an HCD pointer and the corresponding EHCI_HCD */
static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd)
{
- return *((struct xhci_hcd **) (hcd->hcd_priv));
+ struct usb_hcd *primary_hcd;
+
+ if (usb_hcd_is_primary_hcd(hcd))
+ primary_hcd = hcd;
+ else
+ primary_hcd = hcd->primary_hcd;
+
+ return (struct xhci_hcd *) (primary_hcd->hcd_priv);
}
static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
void xhci_free_command(struct xhci_hcd *xhci,
struct xhci_command *command);
-#ifdef CONFIG_PCI
-/* xHCI PCI glue */
-int xhci_register_pci(void);
-void xhci_unregister_pci(void);
-#else
-static inline int xhci_register_pci(void) { return 0; }
-static inline void xhci_unregister_pci(void) {}
-#endif
-
-#if IS_ENABLED(CONFIG_USB_XHCI_PLATFORM)
-int xhci_register_plat(void);
-void xhci_unregister_plat(void);
-#else
-static inline int xhci_register_plat(void)
-{ return 0; }
-static inline void xhci_unregister_plat(void)
-{ }
-#endif
-
/* xHCI host controller glue */
typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
void xhci_stop(struct usb_hcd *hcd);
void xhci_shutdown(struct usb_hcd *hcd);
int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
+void xhci_init_driver(struct hc_driver *drv,
+ const struct xhci_driver_overrides *over);
#ifdef CONFIG_PM
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
@@ -1893,7 +1888,4 @@ struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci,
struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index);
-/* xHCI quirks */
-bool xhci_compliance_mode_recovery_timer_quirk_check(void);
-
#endif /* __LINUX_XHCI_HCD_H */
index 0a34dd8595554f4ddc4d543d6817f986a272d049..aef4a46399ce80577dfae6164838265c7a3f35de 100644 (file)
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_WAIT_BCON:
devctl &= ~MUSB_DEVCTL_SESSION;
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE) {
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb);
} else {
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
}
break;
case OTG_STATE_A_WAIT_VFALL:
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG,
MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT);
break;
if (devctl & MUSB_DEVCTL_BDEVICE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
else
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
break;
default:
break;
/* Never idle if active, or when VBUS timeout is not set as host */
if (musb->is_active || (musb->a_wait_bcon == 0 &&
- musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+ musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
del_timer(&otg_workaround);
last_timer = jiffies;
return;
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&otg_workaround, timeout);
}
* devctl.
*/
musb->int_usb &= ~MUSB_INTR_VBUSERROR;
- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
WARNING("VBUS error workaround (delay coming)\n");
} else if (drvvbus) {
MUSB_HST_MODE(musb);
otg->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
portstate(musb->port1_status |= USB_PORT_STAT_POWER);
del_timer(&otg_workaround);
} else {
musb->is_active = 0;
MUSB_DEV_MODE(musb);
otg->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
}
/* NOTE: this must complete power-on within 100 ms. */
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;
}
/* Poll for ID change */
- if (musb->xceiv->state == OTG_STATE_B_IDLE)
+ if (musb->xceiv->otg->state == OTG_STATE_B_IDLE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
spin_unlock_irqrestore(&musb->lock, flags);
index d40d5f0b5528b6a117e722e26f51a3a268839487..a241a14e255f35b3cce468af269c8bf6c158c60c 100644 (file)
}
/* Start sampling ID pin, when plug is removed from MUSB */
- if ((musb->xceiv->state == OTG_STATE_B_IDLE
- || musb->xceiv->state == OTG_STATE_A_WAIT_BCON) ||
+ if ((musb->xceiv->otg->state == OTG_STATE_B_IDLE
+ || musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON) ||
(musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb))) {
mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
musb->a_wait_bcon = TIMER_DELAY;
static u8 toggle;
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_IDLE:
case OTG_STATE_A_WAIT_BCON:
/* Start a new session */
if (!(val & MUSB_DEVCTL_BDEVICE)) {
gpio_set_value(musb->config->gpio_vrsel, 1);
- musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
} else {
gpio_set_value(musb->config->gpio_vrsel, 0);
/* Ignore VBUSERROR and SUSPEND IRQ */
val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR;
musb_writeb(musb->mregs, MUSB_INTRUSB, val);
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
}
mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
break;
if (!(val & MUSB_DEVCTL_BDEVICE)) {
gpio_set_value(musb->config->gpio_vrsel, 1);
- musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
} else {
gpio_set_value(musb->config->gpio_vrsel, 0);
break;
default:
dev_dbg(musb->controller, "%s state not handled\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
break;
}
spin_unlock_irqrestore(&musb->lock, flags);
dev_dbg(musb->controller, "state is %s\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
static void bfin_musb_enable(struct musb *musb)
dev_dbg(musb->controller, "VBUS %s, devctl %02x "
/* otg %3x conf %08x prcm %08x */ "\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
musb_readb(musb->mregs, MUSB_DEVCTL));
}
index 058775e647adab9b1e977f560b31a2f767143524..527c7fe60ece743575312e5ace6e50cfbb319efa 100644 (file)
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_WAIT_BCON:
devctl &= ~MUSB_DEVCTL_SESSION;
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE) {
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb);
} else {
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
}
break;
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
break;
}
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
musb_writel(musb->ctrl_base, DA8XX_USB_INTR_SRC_SET_REG,
MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT);
break;
if (devctl & MUSB_DEVCTL_BDEVICE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
else
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
break;
default:
break;
/* Never idle if active, or when VBUS timeout is not set as host */
if (musb->is_active || (musb->a_wait_bcon == 0 &&
- musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+ musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
del_timer(&otg_workaround);
last_timer = jiffies;
return;
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&otg_workaround, timeout);
}
* devctl.
*/
musb->int_usb &= ~MUSB_INTR_VBUSERROR;
- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
WARNING("VBUS error workaround (delay coming)\n");
} else if (drvvbus) {
MUSB_HST_MODE(musb);
otg->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
portstate(musb->port1_status |= USB_PORT_STAT_POWER);
del_timer(&otg_workaround);
} else {
musb->is_active = 0;
MUSB_DEV_MODE(musb);
otg->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
}
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;
musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
/* Poll for ID change */
- if (musb->xceiv->state == OTG_STATE_B_IDLE)
+ if (musb->xceiv->otg->state == OTG_STATE_B_IDLE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
spin_unlock_irqrestore(&musb->lock, flags);
index de8492b06e467b0bf8f2fd7cd45715b7b38e8d9e..c9b3fdb1bb8b2fe40cee13e8291bc65d0c83d211 100644 (file)
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_WAIT_VFALL:
/* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL
* seems to mis-handle session "start" otherwise (or in our
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
break;
}
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG,
MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT);
break;
if (devctl & MUSB_DEVCTL_BDEVICE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
else
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
break;
default:
break;
* to stop registering in devctl.
*/
musb->int_usb &= ~MUSB_INTR_VBUSERROR;
- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
WARNING("VBUS error workaround (delay coming)\n");
} else if (drvvbus) {
MUSB_HST_MODE(musb);
otg->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
portstate(musb->port1_status |= USB_PORT_STAT_POWER);
del_timer(&otg_workaround);
} else {
musb->is_active = 0;
MUSB_DEV_MODE(musb);
otg->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
}
davinci_musb_source_power(musb, drvvbus, 0);
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
err ? " ERROR" : "",
devctl);
retval = IRQ_HANDLED;
musb_writel(tibase, DAVINCI_USB_EOI_REG, 0);
/* poll for ID change */
- if (musb->xceiv->state == OTG_STATE_B_IDLE)
+ if (musb->xceiv->otg->state == OTG_STATE_B_IDLE)
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
spin_unlock_irqrestore(&musb->lock, flags);
index 85f725743a8540d931fece78d731aa0716a40b8e..5114d2f6beb49667e3b31d2e2ee5de62d3ed2cd1 100644 (file)
unsigned long flags;
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_B_WAIT_ACON:
dev_dbg(musb->controller, "HNP: b_wait_acon timeout; back to b_peripheral\n");
musb_g_disconnect(musb);
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
musb->is_active = 0;
break;
case OTG_STATE_A_SUSPEND:
case OTG_STATE_A_WAIT_BCON:
dev_dbg(musb->controller, "HNP: %s timeout\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
musb_platform_set_vbus(musb, 0);
- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
break;
default:
dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
spin_unlock_irqrestore(&musb->lock, flags);
}
u8 reg;
dev_dbg(musb->controller, "HNP: stop from %s\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_PERIPHERAL:
musb_g_disconnect(musb);
dev_dbg(musb->controller, "HNP: back to %s\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
break;
case OTG_STATE_B_HOST:
dev_dbg(musb->controller, "HNP: Disabling HR\n");
if (hcd)
hcd->self.is_b_host = 0;
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
MUSB_DEV_MODE(musb);
reg = musb_readb(mbase, MUSB_POWER);
reg |= MUSB_POWER_SUSPENDM;
break;
default:
dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
/*
*/
if (int_usb & MUSB_INTR_RESUME) {
handled = IRQ_HANDLED;
- dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state));
+ dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->otg->state));
if (devctl & MUSB_DEVCTL_HM) {
void __iomem *mbase = musb->mregs;
u8 power;
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_SUSPEND:
/* remote wakeup? later, GetPortStatus
* will stop RESUME signaling
+ msecs_to_jiffies(20);
musb->need_finish_resume = 1;
- musb->xceiv->state = OTG_STATE_A_HOST;
+ musb->xceiv->otg->state = OTG_STATE_A_HOST;
musb->is_active = 1;
musb_host_resume_root_hub(musb);
break;
case OTG_STATE_B_WAIT_ACON:
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
musb->is_active = 1;
MUSB_DEV_MODE(musb);
break;
default:
WARNING("bogus %s RESUME (%s)\n",
"host",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
} else {
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_SUSPEND:
/* possibly DISCONNECT is upcoming */
- musb->xceiv->state = OTG_STATE_A_HOST;
+ musb->xceiv->otg->state = OTG_STATE_A_HOST;
musb_host_resume_root_hub(musb);
break;
case OTG_STATE_B_WAIT_ACON:
default:
WARNING("bogus %s RESUME (%s)\n",
"peripheral",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
}
}
}
dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
/* IRQ arrives from ID pin sense or (later, if VBUS power
* is removed) SRP. responses are time critical:
*/
musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
musb->ep0_stage = MUSB_EP0_START;
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
musb_platform_set_vbus(musb, 1);
* REVISIT: do delays from lots of DEBUG_KERNEL checks
* make trouble here, keeping VBUS < 4.4V ?
*/
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_HOST:
/* recovery is dicey once we've gotten past the
* initial stages of enumeration, but if VBUS
dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller,
"VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
devctl,
({ char *s;
switch (devctl & MUSB_DEVCTL_VBUS) {
if (int_usb & MUSB_INTR_SUSPEND) {
dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
- usb_otg_state_string(musb->xceiv->state), devctl);
+ usb_otg_state_string(musb->xceiv->otg->state), devctl);
handled = IRQ_HANDLED;
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_PERIPHERAL:
/* We also come here if the cable is removed, since
* this silicon doesn't report ID-no-longer-grounded.
musb_g_suspend(musb);
musb->is_active = musb->g.b_hnp_enable;
if (musb->is_active) {
- musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+ musb->xceiv->otg->state = OTG_STATE_B_WAIT_ACON;
dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
mod_timer(&musb->otg_timer, jiffies
+ msecs_to_jiffies(
+ msecs_to_jiffies(musb->a_wait_bcon));
break;
case OTG_STATE_A_HOST:
- musb->xceiv->state = OTG_STATE_A_SUSPEND;
+ musb->xceiv->otg->state = OTG_STATE_A_SUSPEND;
musb->is_active = musb->hcd->self.b_hnp_enable;
break;
case OTG_STATE_B_HOST:
musb->port1_status |= USB_PORT_STAT_LOW_SPEED;
/* indicate new connection to OTG machine */
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_B_PERIPHERAL:
if (int_usb & MUSB_INTR_SUSPEND) {
dev_dbg(musb->controller, "HNP: SUSPEND+CONNECT, now b_host\n");
case OTG_STATE_B_WAIT_ACON:
dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n");
b_host:
- musb->xceiv->state = OTG_STATE_B_HOST;
+ musb->xceiv->otg->state = OTG_STATE_B_HOST;
if (musb->hcd)
musb->hcd->self.is_b_host = 1;
del_timer(&musb->otg_timer);
default:
if ((devctl & MUSB_DEVCTL_VBUS)
== (3 << MUSB_DEVCTL_VBUS_SHIFT)) {
- musb->xceiv->state = OTG_STATE_A_HOST;
+ musb->xceiv->otg->state = OTG_STATE_A_HOST;
if (hcd)
hcd->self.is_b_host = 0;
}
musb_host_poke_root_hub(musb);
dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
- usb_otg_state_string(musb->xceiv->state), devctl);
+ usb_otg_state_string(musb->xceiv->otg->state), devctl);
}
if (int_usb & MUSB_INTR_DISCONNECT) {
dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
MUSB_MODE(musb), devctl);
handled = IRQ_HANDLED;
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_HOST:
case OTG_STATE_A_SUSPEND:
musb_host_resume_root_hub(musb);
musb_root_disconnect(musb);
if (musb->hcd)
musb->hcd->self.is_b_host = 0;
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
MUSB_DEV_MODE(musb);
musb_g_disconnect(musb);
break;
break;
default:
WARNING("unhandled DISCONNECT transition (%s)\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
break;
}
}
}
} else {
dev_dbg(musb->controller, "BUS RESET as %s\n",
- usb_otg_state_string(musb->xceiv->state));
- switch (musb->xceiv->state) {
+ usb_otg_state_string(musb->xceiv->otg->state));
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_SUSPEND:
musb_g_reset(musb);
/* FALLTHROUGH */
case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */
/* never use invalid T(a_wait_bcon) */
dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
TA_WAIT_BCON(musb));
mod_timer(&musb->otg_timer, jiffies
+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
break;
case OTG_STATE_B_WAIT_ACON:
dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
- usb_otg_state_string(musb->xceiv->state));
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ usb_otg_state_string(musb->xceiv->otg->state));
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
musb_g_reset(musb);
break;
case OTG_STATE_B_IDLE:
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
/* FALLTHROUGH */
case OTG_STATE_B_PERIPHERAL:
musb_g_reset(musb);
break;
default:
dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
}
}
int ret = -EINVAL;
spin_lock_irqsave(&musb->lock, flags);
- ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state));
+ ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->otg->state));
spin_unlock_irqrestore(&musb->lock, flags);
return ret;
spin_lock_irqsave(&musb->lock, flags);
/* force T(a_wait_bcon) to be zero/unlimited *OR* valid */
musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ;
- if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON)
+ if (musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON)
musb->is_active = 0;
musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
spin_unlock_irqrestore(&musb->lock, flags);
{
struct musb *musb = container_of(data, struct musb, irq_work);
- if (musb->xceiv->state != musb->xceiv_old_state) {
- musb->xceiv_old_state = musb->xceiv->state;
+ if (musb->xceiv->otg->state != musb->xceiv_old_state) {
+ musb->xceiv_old_state = musb->xceiv->otg->state;
sysfs_notify(&musb->controller->kobj, NULL, "mode");
}
}
if (musb->xceiv->otg->default_a) {
MUSB_HST_MODE(musb);
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
} else {
MUSB_DEV_MODE(musb);
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
}
switch (musb->port_mode) {
index d6c4617a51d3e1a460c4257f69eb9692efaade85..0ca6011a17e9dd868022764f7a66a186ac2e7df9 100644 (file)
/* Never idle if active, or when VBUS timeout is not set as host */
if (musb->is_active || (musb->a_wait_bcon == 0 &&
- musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+ musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
del_timer(&glue->timer);
glue->last_timer = jiffies;
return;
glue->last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&glue->timer, timeout);
}
*/
devctl = dsps_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_WAIT_BCON:
dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
skip_session = 1;
case OTG_STATE_A_IDLE:
case OTG_STATE_B_IDLE:
if (devctl & MUSB_DEVCTL_BDEVICE) {
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb);
} else {
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
}
if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
break;
case OTG_STATE_A_WAIT_VFALL:
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
dsps_writel(musb->ctrl_base, wrp->coreintr_set,
MUSB_INTR_VBUSERROR << wrp->usb_shift);
break;
* devctl.
*/
musb->int_usb &= ~MUSB_INTR_VBUSERROR;
- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&glue->timer,
jiffies + wrp->poll_seconds * HZ);
WARNING("VBUS error workaround (delay coming)\n");
} else if (drvvbus) {
MUSB_HST_MODE(musb);
musb->xceiv->otg->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
del_timer(&glue->timer);
} else {
musb->is_active = 0;
MUSB_DEV_MODE(musb);
musb->xceiv->otg->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
}
/* NOTE: this must complete power-on within 100 ms. */
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;
ret |= musb_interrupt(musb);
/* Poll for ID change in OTG port mode */
- if (musb->xceiv->state == OTG_STATE_B_IDLE &&
+ if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
out:
dsps_writel(mbase, wrp->mode, glue->context.mode);
dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
- if (musb->xceiv->state == OTG_STATE_B_IDLE &&
+ if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
index d4aa779339f1c8ed9af9573d1eb92f80ee22f3c0..9e94fb0350ad704ae23f0aa7888c5ab5e48ca1c9 100644 (file)
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_B_PERIPHERAL:
/* NOTE: OTG state machine doesn't include B_SUSPENDED;
* that's part of the standard usb 1.1 state machine, and
goto done;
default:
dev_dbg(musb->controller, "Unhandled wake: %s\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
goto done;
}
static int musb_gadget_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
-static int musb_gadget_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver);
+static int musb_gadget_stop(struct usb_gadget *g);
static const struct usb_gadget_ops musb_gadget_operations = {
.get_frame = musb_gadget_get_frame,
MUSB_DEV_MODE(musb);
musb->xceiv->otg->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
/* this "gadget" abstracts/virtualizes the controller */
musb->g.name = musb_driver_name;
musb->is_active = 1;
otg_set_peripheral(otg, &musb->g);
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
spin_unlock_irqrestore(&musb->lock, flags);
musb_start(musb);
@@ -1925,8 +1924,7 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
*
* @param driver the gadget driver to unregister
*/
-static int musb_gadget_stop(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+static int musb_gadget_stop(struct usb_gadget *g)
{
struct musb *musb = gadget_to_musb(g);
unsigned long flags;
(void) musb_gadget_vbus_draw(&musb->g, 0);
- musb->xceiv->state = OTG_STATE_UNDEFINED;
- stop_activity(musb, driver);
+ musb->xceiv->otg->state = OTG_STATE_UNDEFINED;
+ stop_activity(musb, NULL);
otg_set_peripheral(musb->xceiv->otg, NULL);
dev_dbg(musb->controller, "unregistering driver %s\n",
- driver ? driver->function : "(removed)");
+ musb->gadget_driver->function);
musb->is_active = 0;
musb->gadget_driver = NULL;
void musb_g_resume(struct musb *musb)
{
musb->is_suspended = 0;
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_B_IDLE:
break;
case OTG_STATE_B_WAIT_ACON:
break;
default:
WARNING("unhandled RESUME transition (%s)\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
}
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "devctl %02x\n", devctl);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_B_IDLE:
if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
break;
case OTG_STATE_B_PERIPHERAL:
musb->is_suspended = 1;
* A_PERIPHERAL may need care too
*/
WARNING("unhandled SUSPEND transition (%s)\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
}
spin_lock(&musb->lock);
}
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
default:
dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
- usb_otg_state_string(musb->xceiv->state));
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ usb_otg_state_string(musb->xceiv->otg->state));
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
break;
case OTG_STATE_A_PERIPHERAL:
- musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
MUSB_HST_MODE(musb);
break;
case OTG_STATE_B_WAIT_ACON:
case OTG_STATE_B_HOST:
case OTG_STATE_B_PERIPHERAL:
case OTG_STATE_B_IDLE:
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
break;
case OTG_STATE_B_SRP_INIT:
break;
* In that case, do not rely on devctl for setting
* peripheral mode.
*/
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
musb->g.is_a_peripheral = 0;
} else if (devctl & MUSB_DEVCTL_BDEVICE) {
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
musb->g.is_a_peripheral = 0;
} else {
- musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_A_PERIPHERAL;
musb->g.is_a_peripheral = 1;
}
index 85a6c1dd14d4a70d0e5a9d81f6724fb3222e37a3..409ddd954047adb3c4dcdc75ae40efdd3c2765be 100644 (file)
if (!is_host_active(musb))
return 0;
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_SUSPEND:
return 0;
case OTG_STATE_A_WAIT_VRISE:
*/
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
- musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
break;
default:
break;
if (musb->is_active) {
WARNING("trying to suspend as %s while active\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
return -EBUSY;
} else
return 0;
MUSB_HST_MODE(musb);
musb->xceiv->otg->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
otg_set_host(musb->xceiv->otg, &hcd->self);
hcd->self.otg_port = 1;
index e2d2d8c9891bc1f7a4cf5f8a16048d58a3d4c630..a133bd8c5dc7f310fbcdc90d1f6adce0e28b068a 100644 (file)
musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
usb_hcd_poll_rh_status(musb->hcd);
/* NOTE: it might really be A_WAIT_BCON ... */
- musb->xceiv->state = OTG_STATE_A_HOST;
+ musb->xceiv->otg->state = OTG_STATE_A_HOST;
spin_unlock_irqrestore(&musb->lock, flags);
}
dev_dbg(musb->controller, "Root port suspended, power %02x\n", power);
musb->port1_status |= USB_PORT_STAT_SUSPEND;
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_HOST:
- musb->xceiv->state = OTG_STATE_A_SUSPEND;
+ musb->xceiv->otg->state = OTG_STATE_A_SUSPEND;
musb->is_active = otg->host->b_hnp_enable;
if (musb->is_active)
mod_timer(&musb->otg_timer, jiffies
musb_platform_try_idle(musb, 0);
break;
case OTG_STATE_B_HOST:
- musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+ musb->xceiv->otg->state = OTG_STATE_B_WAIT_ACON;
musb->is_active = otg->host->b_hnp_enable;
musb_platform_try_idle(musb, 0);
break;
default:
dev_dbg(musb->controller, "bogus rh suspend? %s\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
} else if (power & MUSB_POWER_SUSPENDM) {
power &= ~MUSB_POWER_SUSPENDM;
u8 power;
void __iomem *mbase = musb->mregs;
- if (musb->xceiv->state == OTG_STATE_B_IDLE) {
+ if (musb->xceiv->otg->state == OTG_STATE_B_IDLE) {
dev_dbg(musb->controller, "HNP: Returning from HNP; no hub reset from b_idle\n");
musb->port1_status &= ~USB_PORT_STAT_RESET;
return;
usb_hcd_poll_rh_status(musb->hcd);
musb->is_active = 0;
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_SUSPEND:
if (otg->host->b_hnp_enable) {
- musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
+ musb->xceiv->otg->state = OTG_STATE_A_PERIPHERAL;
musb->g.is_a_peripheral = 1;
break;
}
/* FALLTHROUGH */
case OTG_STATE_A_HOST:
- musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
musb->is_active = 0;
break;
case OTG_STATE_A_WAIT_VFALL:
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
break;
default:
dev_dbg(musb->controller, "host disconnect (%s)\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
}
index d369bf1f3936cba910de97a4859c27174dbed8a5..d1b08349f056307b25996a64b8a0fc71f823405f 100644 (file)
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_WAIT_BCON:
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE) {
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb);
} else {
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
}
break;
musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
usb_hcd_poll_rh_status(musb->hcd);
/* NOTE: it might really be A_WAIT_BCON ... */
- musb->xceiv->state = OTG_STATE_A_HOST;
+ musb->xceiv->otg->state = OTG_STATE_A_HOST;
}
break;
case OTG_STATE_A_HOST:
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE)
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
else
- musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
default:
break;
}
/* Never idle if active, or when VBUS timeout is not set as host */
if (musb->is_active || ((musb->a_wait_bcon == 0)
- && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
+ && (musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON))) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
del_timer(&musb_idle_timer);
last_timer = jiffies;
return;
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
(unsigned long)jiffies_to_msecs(timeout - jiffies));
mod_timer(&musb_idle_timer, timeout);
}
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (is_on) {
- if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+ if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
int loops = 100;
/* start the session */
devctl |= MUSB_DEVCTL_SESSION;
} else {
musb->is_active = 1;
otg->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
devctl |= MUSB_DEVCTL_SESSION;
MUSB_HST_MODE(musb);
}
*/
otg->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
devctl &= ~MUSB_DEVCTL_SESSION;
MUSB_DEV_MODE(musb);
dev_dbg(musb->controller, "VBUS %s, devctl %02x "
/* otg %3x conf %08x prcm %08x */ "\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
musb_readb(musb->mregs, MUSB_DEVCTL));
}
dev_dbg(dev, "ID GND\n");
otg->default_a = true;
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
musb->xceiv->last_event = USB_EVENT_ID;
if (musb->gadget_driver) {
pm_runtime_get_sync(dev);
dev_dbg(dev, "VBUS Connect\n");
otg->default_a = false;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
musb->xceiv->last_event = USB_EVENT_VBUS;
if (musb->gadget_driver)
pm_runtime_get_sync(dev);
index 159ef4be1ef250203e32a4c57a4a336b0ebaec43..df4513e151a5ae6f0202d30e94a282c1d13afbb3 100644 (file)
spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_WAIT_BCON:
if ((musb->a_wait_bcon != 0)
&& (musb->idle_timeout == 0
|| time_after(jiffies, musb->idle_timeout))) {
dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
}
/* FALLTHROUGH */
case OTG_STATE_A_IDLE:
/* Never idle if active, or when VBUS timeout is not set as host */
if (musb->is_active || ((musb->a_wait_bcon == 0)
- && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
+ && (musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON))) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- usb_otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->otg->state));
del_timer(&musb_idle_timer);
last_timer = jiffies;
return;
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
(unsigned long)jiffies_to_msecs(timeout - jiffies));
mod_timer(&musb_idle_timer, timeout);
}
if (is_on) {
timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
otg->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
devctl |= MUSB_DEVCTL_SESSION;
conf |= TUSB_DEV_CONF_USB_HOST_MODE;
/* If ID pin is grounded, we want to be a_idle */
otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT);
if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) {
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_WAIT_VRISE:
case OTG_STATE_A_WAIT_BCON:
- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
break;
case OTG_STATE_A_WAIT_VFALL:
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
break;
default:
- musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
}
musb->is_active = 0;
otg->default_a = 1;
} else {
musb->is_active = 0;
otg->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb);
}
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
dev_dbg(musb->controller, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
musb_readb(musb->mregs, MUSB_DEVCTL),
musb_readl(tbase, TUSB_DEV_OTG_STAT),
conf, prcm);
if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) {
dev_dbg(musb->controller, "Forcing disconnect (no interrupt)\n");
- if (musb->xceiv->state != OTG_STATE_B_IDLE) {
+ if (musb->xceiv->otg->state != OTG_STATE_B_IDLE) {
/* INTR_DISCONNECT can hide... */
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
musb->int_usb |= MUSB_INTR_DISCONNECT;
}
musb->is_active = 0;
}
dev_dbg(musb->controller, "vbus change, %s, otg %03x\n",
- usb_otg_state_string(musb->xceiv->state), otg_stat);
+ usb_otg_state_string(musb->xceiv->otg->state), otg_stat);
idle_timeout = jiffies + (1 * HZ);
schedule_work(&musb->irq_work);
} else /* A-dev state machine */ {
dev_dbg(musb->controller, "vbus change, %s, otg %03x\n",
- usb_otg_state_string(musb->xceiv->state), otg_stat);
+ usb_otg_state_string(musb->xceiv->otg->state), otg_stat);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_IDLE:
dev_dbg(musb->controller, "Got SRP, turning on VBUS\n");
musb_platform_set_vbus(musb, 1);
u8 devctl;
dev_dbg(musb->controller, "%s timer, %03x\n",
- usb_otg_state_string(musb->xceiv->state), otg_stat);
+ usb_otg_state_string(musb->xceiv->otg->state), otg_stat);
- switch (musb->xceiv->state) {
+ switch (musb->xceiv->otg->state) {
case OTG_STATE_A_WAIT_VRISE:
/* VBUS has probably been valid for a while now,
* but may well have bounced out of range a bit
dev_dbg(musb->controller, "devctl %02x\n", devctl);
break;
}
- musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
musb->is_active = 0;
idle_timeout = jiffies
+ msecs_to_jiffies(musb->a_wait_bcon);
index f202e50884615cb50fb9259f43cbc54099d403a8..71231bcbd17868a4c33a333277af802085cf880e 100644 (file)
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
if (is_on) {
- if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+ if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
/* start the session */
devctl |= MUSB_DEVCTL_SESSION;
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
} else {
musb->is_active = 1;
musb->xceiv->otg->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
devctl |= MUSB_DEVCTL_SESSION;
MUSB_HST_MODE(musb);
}
mdelay(200);
dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
- usb_otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->otg->state),
musb_readb(musb->mregs, MUSB_DEVCTL));
}
struct musb *musb = container_of(nb, struct musb, nb);
dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
- event, usb_otg_state_string(musb->xceiv->state));
+ event, usb_otg_state_string(musb->xceiv->otg->state));
switch (event) {
case UX500_MUSB_ID:
if (is_host_active(musb))
ux500_musb_set_vbus(musb, 0);
else
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
break;
default:
dev_dbg(musb->controller, "ID float\n");
index ec531a48d24034aba8a1626ddc0832c58c9a290f..b7b4410bbf5b5ec70e8e958889a5123f63b204c5 100644 (file)
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
config USB_PHY
def_bool n
-config USB_OTG_FSM
- tristate "USB 2.0 OTG FSM implementation"
- depends on USB
- select USB_OTG
- select USB_PHY
- help
- Implements OTG Final State Machine as specified in On-The-Go
- and Embedded Host Supplement to the USB Revision 2.0 Specification.
-
#
# USB Transceiver Drivers
#
index f8fa719a31b9b9b8a86454b11a632992ceda7048..068f35da291dee5f570984f208b8bf1586c59f56 100644 (file)
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
#
obj-$(CONFIG_USB_PHY) += phy.o
obj-$(CONFIG_OF) += of.o
-obj-$(CONFIG_USB_OTG_FSM) += phy-fsm-usb.o
# transceiver drivers, keep the list sorted
index 11ab2c45e46220ac98a9dc829fd88cecde51aa70..2d5250143ce14a8ef8968220f463526b125a6fa9 100644 (file)
if (event != UX500_MUSB_RIDB)
event = UX500_MUSB_NONE;
/* Fallback to default B_IDLE as nothing is connected. */
- ab->phy.state = OTG_STATE_B_IDLE;
+ ab->phy.otg->state = OTG_STATE_B_IDLE;
break;
case USB_LINK_ACA_RID_C_NM_9540:
* Fallback to default B_IDLE as nothing
* is connected
*/
- ab->phy.state = OTG_STATE_B_IDLE;
+ ab->phy.otg->state = OTG_STATE_B_IDLE;
break;
case USB_LINK_ACA_RID_C_NM_8540:
* Fallback to default B_IDLE as nothing
* is connected
*/
- ab->phy.state = OTG_STATE_B_IDLE;
+ ab->phy.otg->state = OTG_STATE_B_IDLE;
break;
case USB_LINK_ACA_RID_C_NM_8505:
if (event != UX500_MUSB_RIDB)
event = UX500_MUSB_NONE;
/* Fallback to default B_IDLE as nothing is connected */
- ab->phy.state = OTG_STATE_B_IDLE;
+ ab->phy.otg->state = OTG_STATE_B_IDLE;
break;
case USB_LINK_ACA_RID_C_NM_8500:
ab->phy.label = "ab8500";
ab->phy.set_suspend = ab8500_usb_set_suspend;
ab->phy.set_power = ab8500_usb_set_power;
- ab->phy.state = OTG_STATE_UNDEFINED;
+ ab->phy.otg->state = OTG_STATE_UNDEFINED;
otg->phy = &ab->phy;
otg->set_host = ab8500_usb_set_host;
index 2b0f968d932537d10d165584c855eb7c769508cb..6732865afc765d2ed7b605f9d02ce24f148b89c0 100644 (file)
/* Mini-A cable connected */
struct otg_fsm *fsm = &otg_dev->fsm;
- otg->phy->state = OTG_STATE_UNDEFINED;
+ otg.state = OTG_STATE_UNDEFINED;
fsm->protocol = PROTO_UNDEF;
}
}
{
if (!fsl_otg_dev)
return -ENODEV;
- if (phy->state == OTG_STATE_B_PERIPHERAL)
+ if (phy->otg.state == OTG_STATE_B_PERIPHERAL)
pr_info("FSL OTG: Draw %d mA\n", mA);
return 0;
{
struct fsl_otg *otg_dev;
- if (!otg || otg->phy->state != OTG_STATE_B_IDLE)
+ if (!otg || otg.state != OTG_STATE_B_IDLE)
return -ENODEV;
otg_dev = container_of(otg->phy, struct fsl_otg, phy);
.start_host = fsl_otg_start_host,
.start_gadget = fsl_otg_start_gadget,
+
+ .start_enum = usb_bus_start_enum,
};
/* Initialize the global variable fsl_otg_dev and request IRQ for OTG */
* Also: record initial state of ID pin
*/
if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) {
- p_otg->phy.state = OTG_STATE_UNDEFINED;
+ p_otg->phy->otg.state = OTG_STATE_UNDEFINED;
p_otg->fsm.id = 1;
} else {
- p_otg->phy.state = OTG_STATE_A_IDLE;
+ p_otg->phy->otg.state = OTG_STATE_A_IDLE;
p_otg->fsm.id = 0;
}
index 7594e5069ae59d2f621054ff7f6cd7331022f5a2..280a3458ff6bdb1157ba45bdd9e55f65c1467593 100644 (file)
}
otg->gadget = gadget;
- otg->phy->state = OTG_STATE_B_IDLE;
+ otg->state = OTG_STATE_B_IDLE;
return 0;
}
nop->phy.dev = nop->dev;
nop->phy.label = "nop-xceiv";
nop->phy.set_suspend = nop_set_suspend;
- nop->phy.state = OTG_STATE_UNDEFINED;
nop->phy.type = type;
+ nop->phy.otg->state = OTG_STATE_UNDEFINED;
nop->phy.otg->phy = &nop->phy;
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
index 69462e09d014e7dc15dd5f3f7ad20dd43a9f55bd..a4e88a28199a0a9d2b9bc7595fb0aaa8918c4a8e 100644 (file)
if (vbus) {
status = USB_EVENT_VBUS;
- gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
+ gpio_vbus->phy.otg->state = OTG_STATE_B_PERIPHERAL;
gpio_vbus->phy.last_event = status;
usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);
usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
status = USB_EVENT_NONE;
- gpio_vbus->phy.state = OTG_STATE_B_IDLE;
+ gpio_vbus->phy.otg->state = OTG_STATE_B_IDLE;
gpio_vbus->phy.last_event = status;
atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
set_vbus_draw(gpio_vbus, 0);
usb_gadget_vbus_disconnect(otg->gadget);
- otg->phy->state = OTG_STATE_UNDEFINED;
+ otg->state = OTG_STATE_UNDEFINED;
otg->gadget = NULL;
return 0;
gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);
- if (phy->state == OTG_STATE_B_PERIPHERAL)
+ if (phy->otg->state == OTG_STATE_B_PERIPHERAL)
set_vbus_draw(gpio_vbus, mA);
return 0;
}
gpio_vbus->phy.dev = gpio_vbus->dev;
gpio_vbus->phy.set_power = gpio_vbus_set_power;
gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend;
- gpio_vbus->phy.state = OTG_STATE_UNDEFINED;
+ gpio_vbus->phy.otg->state = OTG_STATE_UNDEFINED;
gpio_vbus->phy.otg->phy = &gpio_vbus->phy;
gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral;
index 69e49be8866bc00a974ba324718aef15996494b3..5f4ba6aca502dd30c2675491133040731abbec09 100644 (file)
static inline const char *state_name(struct isp1301 *isp)
{
- return usb_otg_state_string(isp->phy.state);
+ return usb_otg_state_string(isp->phy.otg->state);
}
/*-------------------------------------------------------------------------*/
static void power_down(struct isp1301 *isp)
{
- isp->phy.state = OTG_STATE_UNDEFINED;
+ isp->phy.otg->state = OTG_STATE_UNDEFINED;
// isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);
{
u32 l;
- if (isp->phy.state == OTG_STATE_A_IDLE)
+ if (isp->phy.otg->state == OTG_STATE_A_IDLE)
return;
isp->phy.otg->default_a = 1;
isp->phy.otg->gadget->is_a_peripheral = 1;
gadget_suspend(isp);
}
- isp->phy.state = OTG_STATE_A_IDLE;
+ isp->phy.otg->state = OTG_STATE_A_IDLE;
l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
omap_writel(l, OTG_CTRL);
isp->last_otg_ctrl = l;
{
u32 l;
- if (isp->phy.state == OTG_STATE_B_IDLE)
+ if (isp->phy.otg->state == OTG_STATE_B_IDLE)
return;
isp->phy.otg->default_a = 0;
isp->phy.otg->gadget->is_a_peripheral = 0;
gadget_suspend(isp);
}
- isp->phy.state = OTG_STATE_B_IDLE;
+ isp->phy.otg->state = OTG_STATE_B_IDLE;
l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
omap_writel(l, OTG_CTRL);
isp->last_otg_ctrl = l;
default:
break;
}
- if (isp->phy.state == state && !extra)
+ if (isp->phy.otg->state == state && !extra)
return;
pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
usb_otg_state_string(state), fsm, state_name(isp),
if (int_src & INTR_SESS_VLD)
otg_ctrl |= OTG_ASESSVLD;
- else if (isp->phy.state == OTG_STATE_A_WAIT_VFALL) {
+ else if (isp->phy.otg->state == OTG_STATE_A_WAIT_VFALL) {
a_idle(isp, "vfall");
otg_ctrl &= ~OTG_CTRL_BITS;
}
if (int_src & INTR_VBUS_VLD)
otg_ctrl |= OTG_VBUSVLD;
if (int_src & INTR_ID_GND) { /* default-A */
- if (isp->phy.state == OTG_STATE_B_IDLE
- || isp->phy.state
+ if (isp->phy.otg->state == OTG_STATE_B_IDLE
+ || isp->phy.otg->state
== OTG_STATE_UNDEFINED) {
a_idle(isp, "init");
return;
}
} else { /* default-B */
otg_ctrl |= OTG_ID;
- if (isp->phy.state == OTG_STATE_A_IDLE
- || isp->phy.state == OTG_STATE_UNDEFINED) {
+ if (isp->phy.otg->state == OTG_STATE_A_IDLE
+ || isp->phy.otg->state == OTG_STATE_UNDEFINED) {
b_idle(isp, "init");
return;
}
isp->last_otg_ctrl = otg_ctrl;
otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS;
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_B_IDLE:
case OTG_STATE_B_PERIPHERAL:
case OTG_STATE_B_SRP_INIT:
if (!(otg_ctrl & OTG_PULLUP)) {
// if (otg_ctrl & OTG_B_HNPEN) {
if (isp->phy.otg->gadget->b_hnp_enable) {
- isp->phy.state = OTG_STATE_B_WAIT_ACON;
+ isp->phy.otg->state = OTG_STATE_B_WAIT_ACON;
pr_debug(" --> b_wait_acon\n");
}
goto pulldown;
if (!(isp->phy.otg->host))
otg_ctrl &= ~OTG_DRV_VBUS;
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_A_SUSPEND:
if (otg_ctrl & OTG_DRV_VBUS) {
set |= OTG1_VBUS_DRV;
/* FALLTHROUGH */
case OTG_STATE_A_VBUS_ERR:
- isp->phy.state = OTG_STATE_A_WAIT_VFALL;
+ isp->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
pr_debug(" --> a_wait_vfall\n");
/* FALLTHROUGH */
case OTG_STATE_A_WAIT_VFALL:
break;
case OTG_STATE_A_IDLE:
if (otg_ctrl & OTG_DRV_VBUS) {
- isp->phy.state = OTG_STATE_A_WAIT_VRISE;
+ isp->phy.otg->state = OTG_STATE_A_WAIT_VRISE;
pr_debug(" --> a_wait_vrise\n");
}
/* FALLTHROUGH */
if (otg_change & OTG_PULLUP) {
u32 l;
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_B_IDLE:
if (clr & OTG1_DP_PULLUP)
break;
- isp->phy.state = OTG_STATE_B_PERIPHERAL;
+ isp->phy.otg->state = OTG_STATE_B_PERIPHERAL;
pr_debug(" --> b_peripheral\n");
break;
case OTG_STATE_A_SUSPEND:
if (clr & OTG1_DP_PULLUP)
break;
- isp->phy.state = OTG_STATE_A_PERIPHERAL;
+ isp->phy.otg->state = OTG_STATE_A_PERIPHERAL;
pr_debug(" --> a_peripheral\n");
break;
default:
* remote wakeup (SRP, normal) using their own timer
* to give "check cable and A-device" messages.
*/
- if (isp->phy.state == OTG_STATE_B_SRP_INIT)
+ if (isp->phy.otg->state == OTG_STATE_B_SRP_INIT)
b_idle(isp, "srp_timeout");
omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC);
omap_writel(otg_ctrl, OTG_CTRL);
/* subset of b_peripheral()... */
- isp->phy.state = OTG_STATE_B_PERIPHERAL;
+ isp->phy.otg->state = OTG_STATE_B_PERIPHERAL;
pr_debug(" --> b_peripheral\n");
omap_writew(B_HNP_FAIL, OTG_IRQ_SRC);
state_name(isp), omap_readl(OTG_CTRL));
isp1301_defer_work(isp, WORK_UPDATE_OTG);
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_A_IDLE:
if (!otg->host)
break;
otg_ctrl |= OTG_BUSDROP;
otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
omap_writel(otg_ctrl, OTG_CTRL);
- isp->phy.state = OTG_STATE_A_WAIT_VFALL;
+ isp->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC);
ret = IRQ_HANDLED;
otg_ctrl |= OTG_BUSDROP;
otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS;
omap_writel(otg_ctrl, OTG_CTRL);
- isp->phy.state = OTG_STATE_A_VBUS_ERR;
+ isp->phy.otg->state = OTG_STATE_A_VBUS_ERR;
omap_writew(A_VBUS_ERR, OTG_IRQ_SRC);
ret = IRQ_HANDLED;
/* role is peripheral */
if (otg_ctrl & OTG_DRIVER_SEL) {
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_A_IDLE:
b_idle(isp, __func__);
break;
}
if (otg->host) {
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_B_WAIT_ACON:
- isp->phy.state = OTG_STATE_B_HOST;
+ isp->phy.otg->state = OTG_STATE_B_HOST;
pr_debug(" --> b_host\n");
kick = 1;
break;
case OTG_STATE_A_WAIT_BCON:
- isp->phy.state = OTG_STATE_A_HOST;
+ isp->phy.otg->state = OTG_STATE_A_HOST;
pr_debug(" --> a_host\n");
break;
case OTG_STATE_A_PERIPHERAL:
- isp->phy.state = OTG_STATE_A_WAIT_BCON;
+ isp->phy.otg->state = OTG_STATE_A_WAIT_BCON;
pr_debug(" --> a_wait_bcon\n");
break;
default:
/* UDC driver just set OTG_BSESSVLD */
isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
- isp->phy.state = OTG_STATE_B_PERIPHERAL;
+ isp->phy.otg->state = OTG_STATE_B_PERIPHERAL;
pr_debug(" --> b_peripheral\n");
dump_regs(isp, "2periph");
#endif
{
struct usb_otg *otg = isp->phy.otg;
u8 isp_stat, isp_bstat;
- enum usb_otg_state state = isp->phy.state;
+ enum usb_otg_state state = isp->phy.otg->state;
if (stat & INTR_BDIS_ACON)
pr_debug("OTG: BDIS_ACON, %s\n", state_name(isp));
* when HNP is used.
*/
if (isp_stat & INTR_VBUS_VLD)
- isp->phy.state = OTG_STATE_A_HOST;
+ isp->phy.otg->state = OTG_STATE_A_HOST;
break;
case OTG_STATE_A_WAIT_VFALL:
if (!(isp_stat & INTR_SESS_VLD))
break;
default:
if (!(isp_stat & INTR_VBUS_VLD))
- isp->phy.state = OTG_STATE_A_VBUS_ERR;
+ isp->phy.otg->state = OTG_STATE_A_VBUS_ERR;
break;
}
isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
if (otg->default_a) {
switch (state) {
default:
- isp->phy.state = OTG_STATE_A_WAIT_VFALL;
+ isp->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
break;
case OTG_STATE_A_WAIT_VFALL:
state = OTG_STATE_A_IDLE;
host_suspend(isp);
isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1,
MC1_BDIS_ACON_EN);
- isp->phy.state = OTG_STATE_B_IDLE;
+ isp->phy.otg->state = OTG_STATE_B_IDLE;
l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
l &= ~OTG_CTRL_BITS;
omap_writel(l, OTG_CTRL);
}
isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_B_PERIPHERAL:
case OTG_STATE_B_WAIT_ACON:
case OTG_STATE_B_HOST:
}
}
- if (state != isp->phy.state)
+ if (state != isp->phy.otg->state)
pr_debug(" isp, %s -> %s\n",
usb_otg_state_string(state), state_name(isp));
* skip A_WAIT_VRISE; hc transitions invisibly
* skip A_WAIT_BCON; same.
*/
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_A_WAIT_BCON:
case OTG_STATE_A_WAIT_VRISE:
- isp->phy.state = OTG_STATE_A_HOST;
+ isp->phy.otg->state = OTG_STATE_A_HOST;
pr_debug(" --> a_host\n");
otg_ctrl = omap_readl(OTG_CTRL);
otg_ctrl |= OTG_A_BUSREQ;
omap_writel(otg_ctrl, OTG_CTRL);
break;
case OTG_STATE_B_WAIT_ACON:
- isp->phy.state = OTG_STATE_B_HOST;
+ isp->phy.otg->state = OTG_STATE_B_HOST;
pr_debug(" --> b_host (acon)\n");
break;
case OTG_STATE_B_HOST:
}
power_up(isp);
- isp->phy.state = OTG_STATE_B_IDLE;
+ isp->phy.otg->state = OTG_STATE_B_IDLE;
if (machine_is_omap_h2() || machine_is_omap_h3())
isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
{
if (!the_transceiver)
return -ENODEV;
- if (dev->state == OTG_STATE_B_PERIPHERAL)
+ if (dev->otg->state == OTG_STATE_B_PERIPHERAL)
enable_vbus_draw(the_transceiver, mA);
return 0;
}
struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy);
u32 otg_ctrl;
- if (isp != the_transceiver || isp->phy.state != OTG_STATE_B_IDLE)
+ if (isp != the_transceiver || isp->phy.otg->state != OTG_STATE_B_IDLE)
return -ENODEV;
otg_ctrl = omap_readl(OTG_CTRL);
otg_ctrl |= OTG_B_BUSREQ;
otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK;
omap_writel(otg_ctrl, OTG_CTRL);
- isp->phy.state = OTG_STATE_B_SRP_INIT;
+ isp->phy.otg->state = OTG_STATE_B_SRP_INIT;
pr_debug("otg: SRP, %s ... %06x\n", state_name(isp),
omap_readl(OTG_CTRL));
/* We want hardware to manage most HNP protocol timings.
* So do this part as early as possible...
*/
- switch (isp->phy.state) {
+ switch (isp->phy.otg->state) {
case OTG_STATE_B_HOST:
- isp->phy.state = OTG_STATE_B_PERIPHERAL;
+ isp->phy.otg->state = OTG_STATE_B_PERIPHERAL;
/* caller will suspend next */
break;
case OTG_STATE_A_HOST:
index 4f88174aede5ace7cabb2c0202cf00863a075466..8586da5aa8d9dfd60f6552dd2e7bb004646d3181 100644 (file)
}
if (!host) {
- if (otg->phy->state == OTG_STATE_A_HOST) {
+ if (otg->state == OTG_STATE_A_HOST) {
pm_runtime_get_sync(otg->phy->dev);
msm_otg_start_host(otg->phy, 0);
otg->host = NULL;
- otg->phy->state = OTG_STATE_UNDEFINED;
+ otg->state = OTG_STATE_UNDEFINED;
schedule_work(&motg->sm_work);
} else {
otg->host = NULL;
}
if (!gadget) {
- if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
+ if (otg->state == OTG_STATE_B_PERIPHERAL) {
pm_runtime_get_sync(otg->phy->dev);
msm_otg_start_peripheral(otg->phy, 0);
otg->gadget = NULL;
- otg->phy->state = OTG_STATE_UNDEFINED;
+ otg->state = OTG_STATE_UNDEFINED;
schedule_work(&motg->sm_work);
} else {
otg->gadget = NULL;
struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
struct usb_otg *otg = motg->phy.otg;
- switch (otg->phy->state) {
+ switch (otg->state) {
case OTG_STATE_UNDEFINED:
dev_dbg(otg->phy->dev, "OTG_STATE_UNDEFINED state\n");
msm_otg_reset(otg->phy);
msm_otg_init_sm(motg);
- otg->phy->state = OTG_STATE_B_IDLE;
+ otg->state = OTG_STATE_B_IDLE;
/* FALL THROUGH */
case OTG_STATE_B_IDLE:
dev_dbg(otg->phy->dev, "OTG_STATE_B_IDLE state\n");
/* disable BSV bit */
writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
msm_otg_start_host(otg->phy, 1);
- otg->phy->state = OTG_STATE_A_HOST;
+ otg->state = OTG_STATE_A_HOST;
} else if (test_bit(B_SESS_VLD, &motg->inputs)) {
switch (motg->chg_state) {
case USB_CHG_STATE_UNDEFINED:
msm_otg_notify_charger(motg,
IDEV_CHG_MAX);
msm_otg_start_peripheral(otg->phy, 1);
- otg->phy->state
+ otg->state
= OTG_STATE_B_PERIPHERAL;
break;
case USB_SDP_CHARGER:
msm_otg_notify_charger(motg, IUNIT);
msm_otg_start_peripheral(otg->phy, 1);
- otg->phy->state
+ otg->state
= OTG_STATE_B_PERIPHERAL;
break;
default:
motg->chg_state = USB_CHG_STATE_UNDEFINED;
motg->chg_type = USB_INVALID_CHARGER;
}
- pm_runtime_put_sync(otg->phy->dev);
+
+ if (otg->state == OTG_STATE_B_IDLE)
+ pm_runtime_put_sync(otg->phy->dev);
break;
case OTG_STATE_B_PERIPHERAL:
dev_dbg(otg->phy->dev, "OTG_STATE_B_PERIPHERAL state\n");
msm_otg_start_peripheral(otg->phy, 0);
motg->chg_state = USB_CHG_STATE_UNDEFINED;
motg->chg_type = USB_INVALID_CHARGER;
- otg->phy->state = OTG_STATE_B_IDLE;
+ otg->state = OTG_STATE_B_IDLE;
msm_otg_reset(otg->phy);
schedule_work(w);
}
dev_dbg(otg->phy->dev, "OTG_STATE_A_HOST state\n");
if (test_bit(ID, &motg->inputs)) {
msm_otg_start_host(otg->phy, 0);
- otg->phy->state = OTG_STATE_B_IDLE;
+ otg->state = OTG_STATE_B_IDLE;
msm_otg_reset(otg->phy);
schedule_work(w);
}
struct msm_otg *motg = s->private;
struct usb_otg *otg = motg->phy.otg;
- switch (otg->phy->state) {
+ switch (otg->state) {
case OTG_STATE_A_HOST:
seq_puts(s, "host\n");
break;
switch (req_mode) {
case USB_DR_MODE_UNKNOWN:
- switch (otg->phy->state) {
+ switch (otg->state) {
case OTG_STATE_A_HOST:
case OTG_STATE_B_PERIPHERAL:
set_bit(ID, &motg->inputs);
}
break;
case USB_DR_MODE_PERIPHERAL:
- switch (otg->phy->state) {
+ switch (otg->state) {
case OTG_STATE_B_IDLE:
case OTG_STATE_A_HOST:
set_bit(ID, &motg->inputs);
}
break;
case USB_DR_MODE_HOST:
- switch (otg->phy->state) {
+ switch (otg->state) {
case OTG_STATE_B_IDLE:
case OTG_STATE_B_PERIPHERAL:
clear_bit(ID, &motg->inputs);
* This 1 sec delay also prevents entering into LPM immediately
* after asynchronous interrupt.
*/
- if (otg->phy->state != OTG_STATE_UNDEFINED)
+ if (otg->state != OTG_STATE_UNDEFINED)
pm_schedule_suspend(dev, 1000);
return -EAGAIN;
index 7d80c54f0ac66924c2d228944c1fcbf23f45eb5e..11c5fbe345741f53c5a92094b609ef0d7bc13825 100644 (file)
static void mv_otg_update_state(struct mv_otg *mvotg)
{
struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
- struct usb_phy *phy = &mvotg->phy;
- int old_state = phy->state;
+ int old_state = mvotg->phy.otg->state;
switch (old_state) {
case OTG_STATE_UNDEFINED:
- phy->state = OTG_STATE_B_IDLE;
+ mvotg->phy.otg->state = OTG_STATE_B_IDLE;
/* FALL THROUGH */
case OTG_STATE_B_IDLE:
if (otg_ctrl->id == 0)
- phy->state = OTG_STATE_A_IDLE;
+ mvotg->phy.otg->state = OTG_STATE_A_IDLE;
else if (otg_ctrl->b_sess_vld)
- phy->state = OTG_STATE_B_PERIPHERAL;
+ mvotg->phy.otg->state = OTG_STATE_B_PERIPHERAL;
break;
case OTG_STATE_B_PERIPHERAL:
if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0)
- phy->state = OTG_STATE_B_IDLE;
+ mvotg->phy.otg->state = OTG_STATE_B_IDLE;
break;
case OTG_STATE_A_IDLE:
if (otg_ctrl->id)
- phy->state = OTG_STATE_B_IDLE;
+ mvotg->phy.otg->state = OTG_STATE_B_IDLE;
else if (!(otg_ctrl->a_bus_drop) &&
(otg_ctrl->a_bus_req || otg_ctrl->a_srp_det))
- phy->state = OTG_STATE_A_WAIT_VRISE;
+ mvotg->phy.otg->state = OTG_STATE_A_WAIT_VRISE;
break;
case OTG_STATE_A_WAIT_VRISE:
if (otg_ctrl->a_vbus_vld)
- phy->state = OTG_STATE_A_WAIT_BCON;
+ mvotg->phy.otg->state = OTG_STATE_A_WAIT_BCON;
break;
case OTG_STATE_A_WAIT_BCON:
if (otg_ctrl->id || otg_ctrl->a_bus_drop
|| otg_ctrl->a_wait_bcon_timeout) {
mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
- phy->state = OTG_STATE_A_WAIT_VFALL;
+ mvotg->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
otg_ctrl->a_bus_req = 0;
} else if (!otg_ctrl->a_vbus_vld) {
mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
- phy->state = OTG_STATE_A_VBUS_ERR;
+ mvotg->phy.otg->state = OTG_STATE_A_VBUS_ERR;
} else if (otg_ctrl->b_conn) {
mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
- phy->state = OTG_STATE_A_HOST;
+ mvotg->phy.otg->state = OTG_STATE_A_HOST;
}
break;
case OTG_STATE_A_HOST:
if (otg_ctrl->id || !otg_ctrl->b_conn
|| otg_ctrl->a_bus_drop)
- phy->state = OTG_STATE_A_WAIT_BCON;
+ mvotg->phy.otg->state = OTG_STATE_A_WAIT_BCON;
else if (!otg_ctrl->a_vbus_vld)
- phy->state = OTG_STATE_A_VBUS_ERR;
+ mvotg->phy.otg->state = OTG_STATE_A_VBUS_ERR;
break;
case OTG_STATE_A_WAIT_VFALL:
if (otg_ctrl->id
|| (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld)
|| otg_ctrl->a_bus_req)
- phy->state = OTG_STATE_A_IDLE;
+ mvotg->phy.otg->state = OTG_STATE_A_IDLE;
break;
case OTG_STATE_A_VBUS_ERR:
if (otg_ctrl->id || otg_ctrl->a_clr_err
|| otg_ctrl->a_bus_drop) {
otg_ctrl->a_clr_err = 0;
- phy->state = OTG_STATE_A_WAIT_VFALL;
+ mvotg->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
}
break;
default:
run:
/* work queue is single thread, or we need spin_lock to protect */
phy = &mvotg->phy;
- otg = phy->otg;
- old_state = phy->state;
+ otg = mvotg->phy.otg;
+ old_state = otg->state;
if (!mvotg->active)
return;
mv_otg_update_inputs(mvotg);
mv_otg_update_state(mvotg);
- if (old_state != phy->state) {
+ if (old_state != mvotg->phy.otg->state) {
dev_info(&mvotg->pdev->dev, "change from state %s to %s\n",
state_string[old_state],
- state_string[phy->state]);
+ state_string[mvotg->phy.otg->state]);
- switch (phy->state) {
+ switch (mvotg->phy.otg->state) {
case OTG_STATE_B_IDLE:
otg->default_a = 0;
if (old_state == OTG_STATE_B_PERIPHERAL)
return -1;
/* We will use this interface to change to A device */
- if (mvotg->phy.state != OTG_STATE_B_IDLE
- && mvotg->phy.state != OTG_STATE_A_IDLE)
+ if (mvotg->phy.otg->state != OTG_STATE_B_IDLE
+ && mvotg->phy.otg->state != OTG_STATE_A_IDLE)
return -1;
/* The clock may disabled and we need to set irq for ID detected */
mvotg->phy.dev = &pdev->dev;
mvotg->phy.otg = otg;
mvotg->phy.label = driver_name;
- mvotg->phy.state = OTG_STATE_UNDEFINED;
otg->phy = &mvotg->phy;
+ otg->state = OTG_STATE_UNDEFINED;
otg->set_host = mv_otg_set_host;
otg->set_peripheral = mv_otg_set_peripheral;
otg->set_vbus = mv_otg_set_vbus;
{
struct mv_otg *mvotg = platform_get_drvdata(pdev);
- if (mvotg->phy.state != OTG_STATE_B_IDLE) {
+ if (mvotg->phy.otg->state != OTG_STATE_B_IDLE) {
dev_info(&pdev->dev,
"OTG state is not B_IDLE, it is %d!\n",
- mvotg->phy.state);
+ mvotg->phy.otg->state);
return -EAGAIN;
}
index cc61ee44b911dfa5a0b2842a827b5ebfed285f20..04ece535c2f829ce8925b4077e6476c6c06e47db 100644 (file)
reg = retu_read(rdev, TAHVO_REG_IDSR);
if (reg & TAHVO_STAT_VBUS) {
- switch (tu->phy.state) {
+ switch (tu->phy.otg->state) {
case OTG_STATE_B_IDLE:
/* Enable the gadget driver */
if (tu->phy.otg->gadget)
usb_gadget_vbus_connect(tu->phy.otg->gadget);
- tu->phy.state = OTG_STATE_B_PERIPHERAL;
+ tu->phy.otg->state = OTG_STATE_B_PERIPHERAL;
break;
case OTG_STATE_A_IDLE:
/*
* Session is now valid assuming the USB hub is driving
* Vbus.
*/
- tu->phy.state = OTG_STATE_A_HOST;
+ tu->phy.otg->state = OTG_STATE_A_HOST;
break;
default:
break;
}
dev_info(&tu->pt_dev->dev, "USB cable connected\n");
} else {
- switch (tu->phy.state) {
+ switch (tu->phy.otg->state) {
case OTG_STATE_B_PERIPHERAL:
if (tu->phy.otg->gadget)
usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
- tu->phy.state = OTG_STATE_B_IDLE;
+ tu->phy.otg->state = OTG_STATE_B_IDLE;
break;
case OTG_STATE_A_HOST:
- tu->phy.state = OTG_STATE_A_IDLE;
+ tu->phy.otg->state = OTG_STATE_A_IDLE;
break;
default:
break;
/* Power up the transceiver in USB host mode */
retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND |
USBR_MASTER_SW2 | USBR_MASTER_SW1);
- tu->phy.state = OTG_STATE_A_IDLE;
+ tu->phy.otg->state = OTG_STATE_A_IDLE;
check_vbus_state(tu);
}
static void tahvo_usb_stop_host(struct tahvo_usb *tu)
{
- tu->phy.state = OTG_STATE_A_IDLE;
+ tu->phy.otg->state = OTG_STATE_A_IDLE;
}
static void tahvo_usb_become_peripheral(struct tahvo_usb *tu)
/* Power up transceiver and set it in USB peripheral mode */
retu_write(rdev, TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT |
USBR_NSUSPEND | USBR_SLAVE_SW);
- tu->phy.state = OTG_STATE_B_IDLE;
+ tu->phy.otg->state = OTG_STATE_B_IDLE;
check_vbus_state(tu);
}
{
if (tu->phy.otg->gadget)
usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
- tu->phy.state = OTG_STATE_B_IDLE;
+ tu->phy.otg->state = OTG_STATE_B_IDLE;
}
static void tahvo_usb_power_off(struct tahvo_usb *tu)
/* Power off transceiver */
retu_write(rdev, TAHVO_REG_USBR, 0);
- tu->phy.state = OTG_STATE_UNDEFINED;
+ tu->phy.otg->state = OTG_STATE_UNDEFINED;
}
static int tahvo_usb_set_suspend(struct usb_phy *dev, int suspend)
/* Create OTG interface */
tahvo_usb_power_off(tu);
tu->phy.dev = &pdev->dev;
- tu->phy.state = OTG_STATE_UNDEFINED;
+ tu->phy.otg->state = OTG_STATE_UNDEFINED;
tu->phy.label = DRIVER_NAME;
tu->phy.set_suspend = tahvo_usb_set_suspend;
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index fd0d7f122ace3a8e42115f17a1bcf0ef2d1af065..1abe16acc8284d338c2eed95d5c1f46df7ac2847 100644 (file)
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
{
- return res == match_data;
+ struct usb_phy **phy = res;
+
+ return *phy == match_data;
}
/**
index 458f3766bef1c2385a17e0e6a30b39739367e3c5..2335380891e863fc9da8ecf77bae7d0c6c2630b5 100644 (file)
return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD);
}
-static int usbhsg_gadget_stop(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
+static int usbhsg_gadget_stop(struct usb_gadget *gadget)
{
struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index f4d7b2fc9ffbc19a336d8abe2095e7cf990da52c..78f46089a0778fbc3b7b549962c5896c2a72c795 100644 (file)
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
int elf_prot = 0, elf_flags;
unsigned long k, vaddr;
+ unsigned long total_size = 0;
if (elf_ppnt->p_type != PT_LOAD)
continue;
#else
load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
#endif
+ total_size = total_mapping_size(elf_phdata,
+ loc->elf_ex.e_phnum);
+ if (!total_size) {
+ error = -EINVAL;
+ goto out_free_dentry;
+ }
}
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
- elf_prot, elf_flags, 0);
+ elf_prot, elf_flags, total_size);
if (BAD_ADDR(error)) {
send_sig(SIGKILL, current, 0);
retval = IS_ERR((void *)error) ?
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d2f1c011d73ab3025e3056585b0ce7568be1747a..794d7c6ea9ee4c4105acc0a2c2dfbd63d9bf19d9 100644 (file)
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
return -ENOSPC;
}
- if (btrfs_test_opt(root, DISCARD))
- ret = btrfs_discard_extent(root, start, len, NULL);
-
if (pin)
pin_down_extent(root, cache, start, len, 1);
else {
+ if (btrfs_test_opt(root, DISCARD))
+ ret = btrfs_discard_extent(root, start, len, NULL);
btrfs_add_free_space(cache, start, len);
btrfs_update_reserved_bytes(cache, len, RESERVE_FREE);
}
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0b72006aecbece81402764a23808ec4e8e33f35e..3e16042338e497de38ee1ba2530ebdf6d0c59c63 100644 (file)
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
if (src == dst)
return -EINVAL;
+ if (len == 0)
+ return 0;
+
btrfs_double_lock(src, loff, dst, dst_loff, len);
ret = extent_same_check_offsets(src, loff, len);
@@ -3226,6 +3229,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
if (off + len == src->i_size)
len = ALIGN(src->i_size, bs) - off;
+ if (len == 0) {
+ ret = 0;
+ goto out_unlock;
+ }
+
/* verify the end result is block aligned */
if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) ||
!IS_ALIGNED(destoff, bs))
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index ad8328d797ea9910c21f0ecd5db6051d347a4571..488e987c337495276c74868bc25b796293bea8be 100644 (file)
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
/*
* Check if the attribute is in a supported namespace.
*
- * This applied after the check for the synthetic attributes in the system
+ * This is applied after the check for the synthetic attributes in the system
* namespace.
*/
-static bool btrfs_is_valid_xattr(const char *name)
+static int btrfs_is_valid_xattr(const char *name)
{
- return !strncmp(name, XATTR_SECURITY_PREFIX,
- XATTR_SECURITY_PREFIX_LEN) ||
- !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
- !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
- !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) ||
- !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN);
+ int len = strlen(name);
+ int prefixlen = 0;
+
+ if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ XATTR_SECURITY_PREFIX_LEN))
+ prefixlen = XATTR_SECURITY_PREFIX_LEN;
+ else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+ prefixlen = XATTR_SYSTEM_PREFIX_LEN;
+ else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+ prefixlen = XATTR_TRUSTED_PREFIX_LEN;
+ else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+ prefixlen = XATTR_USER_PREFIX_LEN;
+ else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
+ prefixlen = XATTR_BTRFS_PREFIX_LEN;
+ else
+ return -EOPNOTSUPP;
+
+ /*
+ * The name cannot consist of just prefix
+ */
+ if (len <= prefixlen)
+ return -EINVAL;
+
+ return 0;
}
ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
+ int ret;
+
/*
* If this is a request for a synthetic attribute in the system.*
* namespace use the generic infrastructure to resolve a handler
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
return generic_getxattr(dentry, name, buffer, size);
- if (!btrfs_is_valid_xattr(name))
- return -EOPNOTSUPP;
+ ret = btrfs_is_valid_xattr(name);
+ if (ret)
+ return ret;
return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
}
size_t size, int flags)
{
struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+ int ret;
/*
* The permission on security.* and system.* is not checked
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
return generic_setxattr(dentry, name, value, size, flags);
- if (!btrfs_is_valid_xattr(name))
- return -EOPNOTSUPP;
+ ret = btrfs_is_valid_xattr(name);
+ if (ret)
+ return ret;
if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
return btrfs_set_prop(dentry->d_inode, name,
int btrfs_removexattr(struct dentry *dentry, const char *name)
{
struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+ int ret;
/*
* The permission on security.* and system.* is not checked
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
return generic_removexattr(dentry, name);
- if (!btrfs_is_valid_xattr(name))
- return -EOPNOTSUPP;
+ ret = btrfs_is_valid_xattr(name);
+ if (ret)
+ return ret;
if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
return btrfs_set_prop(dentry->d_inode, name,
diff --git a/fs/exec.c b/fs/exec.c
index ea4449d0536a7c79e36605d2512eba3b7d15541e..05f1942d7edba5e4086562c7beea27389b4d99ca 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
spin_unlock(&p->fs->lock);
}
+static void bprm_fill_uid(struct linux_binprm *bprm)
+{
+ struct inode *inode;
+ unsigned int mode;
+ kuid_t uid;
+ kgid_t gid;
+
+ /* clear any previous set[ug]id data from a previous binary */
+ bprm->cred->euid = current_euid();
+ bprm->cred->egid = current_egid();
+
+ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
+ return;
+
+ if (current->no_new_privs)
+ return;
+
+ inode = file_inode(bprm->file);
+ mode = ACCESS_ONCE(inode->i_mode);
+ if (!(mode & (S_ISUID|S_ISGID)))
+ return;
+
+ /* Be careful if suid/sgid is set */
+ mutex_lock(&inode->i_mutex);
+
+ /* reload atomically mode/uid/gid now that lock held */
+ mode = inode->i_mode;
+ uid = inode->i_uid;
+ gid = inode->i_gid;
+ mutex_unlock(&inode->i_mutex);
+
+ /* We ignore suid/sgid if there are no mappings for them in the ns */
+ if (!kuid_has_mapping(bprm->cred->user_ns, uid) ||
+ !kgid_has_mapping(bprm->cred->user_ns, gid))
+ return;
+
+ if (mode & S_ISUID) {
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+ bprm->cred->euid = uid;
+ }
+
+ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+ bprm->cred->egid = gid;
+ }
+}
+
/*
* Fill the binprm structure from the inode.
* Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
*/
int prepare_binprm(struct linux_binprm *bprm)
{
- struct inode *inode = file_inode(bprm->file);
- umode_t mode = inode->i_mode;
int retval;
-
- /* clear any previous set[ug]id data from a previous binary */
- bprm->cred->euid = current_euid();
- bprm->cred->egid = current_egid();
-
- if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
- !current->no_new_privs &&
- kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) &&
- kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) {
- /* Set-uid? */
- if (mode & S_ISUID) {
- bprm->per_clear |= PER_CLEAR_ON_SETID;
- bprm->cred->euid = inode->i_uid;
- }
-
- /* Set-gid? */
- /*
- * If setgid is set but no group execute bit then this
- * is a candidate for mandatory locking, not a setgid
- * executable.
- */
- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
- bprm->per_clear |= PER_CLEAR_ON_SETID;
- bprm->cred->egid = inode->i_gid;
- }
- }
+ bprm_fill_uid(bprm);
/* fill in binprm security blob */
retval = security_bprm_set_creds(bprm);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 2dcbfb6245d8c4b689e55f288fbb63b0fadce35d..bc7e37bc0c5b21647d490acb7850b1f135a48164 100644 (file)
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
struct inode *inode)
{
struct inode *dir = dentry->d_parent->d_inode;
- struct buffer_head *bh;
+ struct buffer_head *bh = NULL;
struct ext4_dir_entry_2 *de;
struct ext4_dir_entry_tail *t;
struct super_block *sb;
return retval;
if (retval == 1) {
retval = 0;
- return retval;
+ goto out;
}
}
if (is_dx(dir)) {
retval = ext4_dx_add_entry(handle, dentry, inode);
if (!retval || (retval != ERR_BAD_DX_DIR))
- return retval;
+ goto out;
ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
dx_fallback++;
ext4_mark_inode_dirty(handle, dir);
return PTR_ERR(bh);
retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
- if (retval != -ENOSPC) {
- brelse(bh);
- return retval;
- }
+ if (retval != -ENOSPC)
+ goto out;
if (blocks == 1 && !dx_fallback &&
- EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
- return make_indexed_dir(handle, dentry, inode, bh);
+ EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+ retval = make_indexed_dir(handle, dentry, inode, bh);
+ bh = NULL; /* make_indexed_dir releases bh */
+ goto out;
+ }
brelse(bh);
}
bh = ext4_append(handle, dir, &block);
}
retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
+out:
brelse(bh);
if (retval == 0)
ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY);
diff --git a/fs/namei.c b/fs/namei.c
index 0dd72c8e65fd45a8423f4135bbafc1ef717516f6..ccb8000f3459995e6cb750d98d1ed3bcacbffcf1 100644 (file)
--- a/fs/namei.c
+++ b/fs/namei.c
if (should_follow_link(path->dentry, follow)) {
if (nd->flags & LOOKUP_RCU) {
- if (unlikely(unlazy_walk(nd, path->dentry))) {
+ if (unlikely(nd->path.mnt != path->mnt ||
+ unlazy_walk(nd, path->dentry))) {
err = -ECHILD;
goto out_err;
}
if (should_follow_link(path->dentry, !symlink_ok)) {
if (nd->flags & LOOKUP_RCU) {
- if (unlikely(unlazy_walk(nd, path->dentry))) {
+ if (unlikely(nd->path.mnt != path->mnt ||
+ unlazy_walk(nd, path->dentry))) {
error = -ECHILD;
goto out;
}
diff --git a/fs/open.c b/fs/open.c
index 2ed7325f713ec325a0059c59b9768ef16b7dbdc9..17679f2b2f1ca4c24171cc87523ac36bb4711e73 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
uid = make_kuid(current_user_ns(), user);
gid = make_kgid(current_user_ns(), group);
+retry_deleg:
newattrs.ia_valid = ATTR_CTIME;
if (user != (uid_t) -1) {
if (!uid_valid(uid))
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
-retry_deleg:
mutex_lock(&inode->i_mutex);
error = security_path_chown(path, uid, gid);
if (!error)
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 68a3ada689c900b90b26af4ec61377cd8405472f..8fc12f80b6161f2e53e045cee3302b99249361ab 100644 (file)
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
typedef s32 acpi_native_int;
typedef u32 acpi_size;
+
+#ifdef ACPI_32BIT_PHYSICAL_ADDRESS
+
+/*
+ * OSPMs can define this to shrink the size of the structures for 32-bit
+ * none PAE environment. ASL compiler may always define this to generate
+ * 32-bit OSPM compliant tables.
+ */
typedef u32 acpi_io_address;
typedef u32 acpi_physical_address;
+#else /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
+/*
+ * It is reported that, after some calculations, the physical addresses can
+ * wrap over the 32-bit boundary on 32-bit PAE environment.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=87971
+ */
+typedef u64 acpi_io_address;
+typedef u64 acpi_physical_address;
+
+#endif /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
#define ACPI_MAX_PTR ACPI_UINT32_MAX
#define ACPI_SIZE_MAX ACPI_UINT32_MAX
index b402eb67af83fd5496669eec6e8ed6fe2d168f58..579912c7156c78ac2a286c3cbeed380f545b6633 100644 (file)
#define ACPI_LARGE_NAMESPACE_NODE
#define ACPI_DATA_TABLE_DISASSEMBLY
#define ACPI_SINGLE_THREADED
+#define ACPI_32BIT_PHYSICAL_ADDRESS
#endif
/* acpi_exec configuration. Multithreaded with full AML debugger */
index f1a24b5c3b906ef91804bca4f6f56b4158d93aca..b58fd667f87bc7c7b093c3cac1d293d78d89ec4d 100644 (file)
/* References to section boundaries */
+#include <linux/compiler.h>
+
/*
* Usage guidelines:
* _text, _data: architecture specific, don't use them in arch-independent code
/* Start and end of .ctors section - used for constructor calls. */
extern char __ctors_start[], __ctors_end[];
+extern __visible const void __nosave_begin, __nosave_end;
+
/* function descriptor handling (if any). Override
* in asm/sections.h */
#ifndef dereference_function_descriptor
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index f488145bb2d40460ac58add4624e8648af685e3f..36f49c405dfb334bf03db9d6f886e6b6fa2d3667 100644 (file)
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
*/
extern int extcon_dev_register(struct extcon_dev *edev);
extern void extcon_dev_unregister(struct extcon_dev *edev);
+extern int devm_extcon_dev_register(struct device *dev,
+ struct extcon_dev *edev);
+extern void devm_extcon_dev_unregister(struct device *dev,
+ struct extcon_dev *edev);
extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
+/*
+ * Following APIs control the memory of extcon device.
+ */
+extern struct extcon_dev *extcon_dev_allocate(const char **cables);
+extern void extcon_dev_free(struct extcon_dev *edev);
+extern struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
+ const char **cables);
+extern void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev);
+
/*
* get/set/update_state access the 32b encoded state value, which represents
* states of all possible cables of the multistate port. For example, if one
static inline void extcon_dev_unregister(struct extcon_dev *edev) { }
+static inline int devm_extcon_dev_register(struct device *dev,
+ struct extcon_dev *edev)
+{
+ return -EINVAL;
+}
+
+static inline void devm_extcon_dev_unregister(struct device *dev,
+ struct extcon_dev *edev) { }
+
+static inline struct extcon_dev *extcon_dev_allocate(const char **cables)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void extcon_dev_free(struct extcon_dev *edev) { }
+
+static inline struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
+ const char **cables)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void devm_extcon_dev_free(struct extcon_dev *edev) { }
+
static inline u32 extcon_get_state(struct extcon_dev *edev)
{
return 0;
index 0b17ad43fbfcefd062b3902dd615e1af45f6b245..8900fdf511c6acf91f71c67894f32c26cb7fbfbd 100644 (file)
* @irq_flags: IRQ Flags (e.g., IRQF_TRIGGER_LOW).
* @state_on: print_state is overriden with state_on if attached.
* If NULL, default method of extcon class is used.
- * @state_off: print_state is overriden with state_off if detached.
+ * @state_off: print_state is overriden with state_on if detached.
* If NUll, default method of extcon class is used.
- * @check_on_resume: Boolean describing whether to check the state of gpio
- * while resuming from sleep.
*
* Note that in order for state_on or state_off to be valid, both state_on
* and state_off should be not NULL. If at least one of them is NULL,
index 7e29be8862aa1e4759046b4df2451f0f5e878dcf..3bf65c056771b1157751042ade3a9ae0b8d7f001 100644 (file)
struct palmas *palmas;
struct device *dev;
- struct extcon_dev edev;
+ struct extcon_dev *edev;
int id_otg_irq;
int id_irq;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index ad8f85908a565f0a2be0e1362fcfa16aa560ab2f..ab3133797ff7180231826043dfcc505b3a07cc1e 100644 (file)
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags,
int node);
+struct sk_buff *__build_skb(void *data, unsigned int frag_size);
struct sk_buff *build_skb(void *data, unsigned int frag_size);
static inline struct sk_buff *alloc_skb(unsigned int size,
gfp_t priority)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 7f6eb859873e4a24bcb5ebf30bf8b4485e61a622..d8834a79e545c229e5ea4686d6f9407b0092e9e7 100644 (file)
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
#define USB_MAXINTERFACES 32
#define USB_MAXIADS (USB_MAXINTERFACES/2)
+/*
+ * USB Resume Timer: Every Host controller driver should drive the resume
+ * signalling on the bus for the amount of time defined by this macro.
+ *
+ * That way we will have a 'stable' behavior among all HCDs supported by Linux.
+ *
+ * Note that the USB Specification states we should drive resume for *at least*
+ * 20 ms, but it doesn't give an upper bound. This creates two possible
+ * situations which we want to avoid:
+ *
+ * (a) sometimes an msleep(20) might expire slightly before 20 ms, which causes
+ * us to fail USB Electrical Tests, thus failing Certification
+ *
+ * (b) Some (many) devices actually need more than 20 ms of resume signalling,
+ * and while we can argue that's against the USB Specification, we don't have
+ * control over which devices a certification laboratory will be using for
+ * certification. If CertLab uses a device which was tested against Windows and
+ * that happens to have relaxed resume signalling rules, we might fall into
+ * situations where we fail interoperability and electrical tests.
+ *
+ * In order to avoid both conditions, we're using a 40 ms resume timeout, which
+ * should cope with both LPJ calibration errors and devices not following every
+ * detail of the USB Specification.
+ */
+#define USB_RESUME_TIMEOUT 40 /* ms */
+
/**
* struct usb_interface_cache - long-term representation of a device interface
* @num_altsetting: number of altsettings defined.
/* debugfs stuff */
extern struct dentry *usb_debug_root;
+/* LED triggers */
+enum usb_led_event {
+ USB_LED_EVENT_HOST = 0,
+ USB_LED_EVENT_GADGET = 1,
+};
+
+#ifdef CONFIG_USB_LED_TRIG
+extern void usb_led_activity(enum usb_led_event ev);
+#else
+static inline void usb_led_activity(enum usb_led_event ev) {}
+#endif
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/usb/drd.h b/include/linux/usb/drd.h
--- a/include/linux/usb/drd.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/hcd.h>
-
-struct usb_drd_setup {
- int (*ll_start)(void *);
- int (*ll_stop)(void *);
- void (*ll_release)(struct device *);
- void *data;
-};
-
-struct usb_drd_host {
- struct usb_hcd *main_hcd;
- struct usb_hcd *shared_hcd;
- int hcd_irq;
- struct usb_drd_setup *host_setup;
-};
-
-struct usb_drd_gadget {
- struct usb_gadget_driver *g_driver;
- struct usb_gadget *gadget;
- struct usb_drd_setup *gadget_setup;
-};
-
-#define DRD_UNREGISTERED 0x0
-#define DRD_DEVICE_REGISTERED 0x1
-#define DRD_HOST_REGISTERED 0x2
-#define DRD_HOST_ACTIVE 0x4
-#define DRD_DEVICE_ACTIVE 0x8
-
-#if IS_ENABLED(CONFIG_DRD_LIB)
-int usb_drd_release(struct device *parent);
-int usb_drd_add(struct device *parent);
-int usb_drd_register_udc(struct device *parent,
- struct usb_drd_gadget *gadget);
-int usb_drd_register_udc_driver(struct device *parent,
- struct usb_gadget_driver *driver);
-int usb_drd_unregister_udc(struct device *parent);
-int usb_drd_unregister_udc_driver(struct device *parent);
-int usb_drd_register_hcd(struct device *parent,
- struct usb_drd_host *host);
-int usb_drd_unregister_hcd(struct device *parent);
-int usb_drd_start_hcd(struct device *parent);
-int usb_drd_stop_hcd(struct device *parent);
-int usb_drd_start_udc(struct device *parent);
-int usb_drd_stop_udc(struct device *parent);
-int usb_drd_get_state(struct device *parent);
-#else
-static inline int usb_drd_release(struct device *parent)
-{ return 0; }
-static inline int usb_drd_add(struct device *parent)
-{ return 0; }
-static inline int usb_drd_register_udc(struct device *parent,
- struct usb_drd_gadget *gadget)
-{ return 0; }
-static inline int usb_drd_register_udc_driver(struct device *parent,
- struct usb_gadget_driver *driver)
-{ return 0; }
-static inline int usb_drd_unregister_udc(struct device *parent,
- struct usb_drd_gadget *gadget)
-{ return 0; }
-static inline int usb_drd_unregister_udc_driver(struct device *parent)
-{ return 0; }
-static inline int usb_drd_register_hcd(struct device *parent,
- struct usb_drd_host *host)
-{ return 0; }
-static inline int usb_drd_unregister_hcd(struct device *parent)
-{ return 0; }
-static inline int usb_drd_stop_hcd(struct device *parent)
-{ return 0; }
-static inline int usb_drd_start_udc(struct device *parent)
-{ return 0; }
-static inline int usb_drd_stop_udc(struct device *parent)
-{ return 0; }
-static inline int usb_drd_get_state(struct device *parent)
-{ return 0; }
-#endif
index c3a61853cd1306f7a34cdc9b26a9e08b39c49ce2..b2828cbcecb63fa3ad124e11d11e5277a9393d53 100644 (file)
void (*get_config_params)(struct usb_dcd_config_params *);
int (*udc_start)(struct usb_gadget *,
struct usb_gadget_driver *);
- int (*udc_stop)(struct usb_gadget *,
- struct usb_gadget_driver *);
+ int (*udc_stop)(struct usb_gadget *);
};
/**
* enabled HNP support.
* @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
* MaxPacketSize.
+ * @is_selfpowered: if the gadget is self-powered.
*
* Gadgets have a mostly-portable "gadget driver" implementing device
* functions, handling all usb configurations and interfaces. Gadget
unsigned a_hnp_support:1;
unsigned a_alt_hnp_support:1;
unsigned quirk_ep_out_aligned_size:1;
+ unsigned is_selfpowered:1;
};
#define work_to_gadget(w) (container_of((w), struct usb_gadget, work))
* Called in a context that permits sleeping.
* @suspend: Invoked on USB suspend. May be called in_interrupt.
* @resume: Invoked on USB resume. May be called in_interrupt.
+ * @reset: Invoked on USB bus reset. It is mandatory for all gadget drivers
+ * and should be called in_interrupt.
* @driver: Driver model state for this driver.
*
* Devices are disabled till a gadget driver successfully bind()s, which
void (*disconnect)(struct usb_gadget *);
void (*suspend)(struct usb_gadget *);
void (*resume)(struct usb_gadget *);
+ void (*reset)(struct usb_gadget *);
/* FIXME support safe rmmod */
struct device_driver driver;
};
+/*-------------------------------------------------------------------------*/
+
+/**
+ * struct otg_gadget_ops - Interface between OTG core and gadget
+ *
+ * Provided by the gadget core to allow the OTG core to start/stop the gadget
+ *
+ * @start: function to start the gadget
+ * @stop: function to stop the gadget
+ */
+struct otg_gadget_ops {
+ int (*start)(struct usb_gadget *gadget);
+ int (*stop)(struct usb_gadget *gadget);
+};
/*-------------------------------------------------------------------------*/
struct usb_gadget *gadget, void (*release)(struct device *dev));
extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
extern void usb_del_gadget_udc(struct usb_gadget *gadget);
-extern int udc_attach_driver(const char *name,
+extern int usb_udc_attach_driver(const char *name,
struct usb_gadget_driver *driver);
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
+/* utility to tell udc core that the bus reset occurs */
+extern void usb_gadget_udc_reset(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
+
+/*-------------------------------------------------------------------------*/
+
+/* utility to give requests back to the gadget layer */
+
+extern void usb_gadget_giveback_request(struct usb_ep *ep,
+ struct usb_request *req);
+
+
+/*-------------------------------------------------------------------------*/
+
/* utility wrapping a simple endpoint selection policy */
extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
index 52598bdce2babbb62417335ff78dbc05dfbdb6e4..2ca8c79ec1f19bef04e261ad67f375f0f85720e2 100644 (file)
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
* OTG and some Host controllers need software interaction with phys;
* other external phys should be software-transparent
*/
- struct usb_phy *phy;
+ struct usb_phy *usb_phy;
/* Flags that need to be manipulated atomically because they can
* change while the host controller is running. Always use
int (*find_raw_port_number)(struct usb_hcd *, int);
};
+/**
+ * struct otg_hcd_ops - Interface between OTG core and HCD
+ *
+ * Provided by the HCD core to allow the OTG core to start/stop the HCD
+ *
+ * @add: function to add the HCD
+ * @remove: function to remove the HCD
+ */
+struct otg_hcd_ops {
+ int (*add)(struct usb_hcd *hcd,
+ unsigned int irqnum, unsigned long irqflags);
+ void (*remove)(struct usb_hcd *hcd);
+};
+
static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
{
return hcd->driver->flags & HCD_BH;
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h
index 8c38aa26b3bb6dba5a1ef37b6104d701cc03fcdb..cfe0528cdbb1048dd87e3d2910f2eaec454d3607 100644 (file)
--- a/include/linux/usb/of.h
+++ b/include/linux/usb/of.h
#if IS_ENABLED(CONFIG_OF)
enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np);
enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np);
+bool of_usb_host_tpl_support(struct device_node *np);
#else
static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
{
{
return USB_SPEED_UNKNOWN;
}
+static inline bool of_usb_host_tpl_support(struct device_node *np)
+{
+ return false;
+}
#endif
#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT)
index b6ba1bfb86f2aa7cfb348bc2e704e48c34796b1b..cbe94e9d159e0f99567b145e489e731e655ba2de 100644 (file)
#include <linux/mutex.h>
#include <linux/errno.h>
-#undef VERBOSE
-
-#ifdef VERBOSE
-#define VDBG(fmt, args...) pr_debug("[%s] " fmt , \
- __func__, ## args)
-#else
-#define VDBG(stuff...) do {} while (0)
-#endif
-
-#ifdef VERBOSE
-#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__)
-#else
-#define MPC_LOC do {} while (0)
-#endif
-
#define PROTO_UNDEF (0)
#define PROTO_HOST (1)
#define PROTO_GADGET (2)
NUM_OTG_FSM_TIMERS,
};
-/* OTG state machine according to the OTG spec */
+/**
+ * struct otg_fsm - OTG state machine according to the OTG spec
+ *
+ * DRD mode hardware Inputs
+ *
+ * @id: TRUE for B-device, FALSE for A-device.
+ * @vbus: VBUS voltage in regulation.
+ *
+ * OTG hardware Inputs
+ *
+ * Common inputs for A and B device
+ * @id: TRUE for B-device, FALSE for A-device.
+ * @adp_change: TRUE when current ADP measurement (n) value, compared to the
+ * ADP measurement taken at n-2, differs by more than CADP_THR
+ * @power_up: TRUE when the OTG device first powers up its USB system and
+ * ADP measurement taken if ADP capable
+ *
+ * A-Device state inputs
+ * @a_srp_det: TRUE if the A-device detects SRP
+ * @a_vbus_vld: TRUE when VBUS voltage is in regulation
+ * @b_conn: TRUE if the A-device detects connection from the B-device
+ * @a_bus_resume: TRUE when the B-device detects that the A-device is signaling
+ * a resume (K state)
+ * B-Device state inputs
+ * @a_bus_suspend: TRUE when the B-device detects that the A-device has put
+ * the bus into suspend
+ * @a_conn: TRUE if the B-device detects a connection from the A-device
+ * @b_se0_srp: TRUE when the line has been at SE0 for more than the minimum
+ * time before generating SRP
+ * @b_ssend_srp: TRUE when the VBUS has been below VOTG_SESS_VLD for more than
+ * the minimum time before generating SRP
+ * @b_sess_vld: TRUE when the B-device detects that the voltage on VBUS is
+ * above VOTG_SESS_VLD
+ * @test_device: TRUE when the B-device switches to B-Host and detects an
+ * OTG test device.
+ * FIXME: This must be set by host/hub driver
+ *
+ * Application inputs (A-Device)
+ * @a_bus_drop: TRUE when A-device application needs to power down the bus
+ * @a_bus_req: TRUE when A-device application wants to use the bus.
+ * FALSE to suspend the bus
+ *
+ * Application inputs (B-Device)
+ * @b_bus_req: TRUE during the time that the Application running on the
+ * B-device wants to use the bus
+ *
+ * Auxilary inputs (OTG v1.3 only. Obsolete now.)
+ * @a_sess_vld: TRUE if the A-device detects that VBUS is above VA_SESS_VLD
+ * @b_bus_suspend: TRUE when the A-device detects that the B-device has put
+ * the bus into suspend
+ * @b_bus_resume: TRUE when the A-device detects that the B-device is
+ * signaling a resume on the bus
+ *
+ * OTG Output status. Read only for users. updated by otg_ops() helpers
+ *
+ * Outputs for Both A and B device
+ * @drv_vbus: TRUE when A-device is driving VBUS
+ * @loc_conn: TRUE when the local device has signaled that it is
+ * connected to the bus
+ * @loc_sof: TRUE when the local device is generating activity on the bus
+ * @adp_prb: TRUE when the local device is in process of doing ADP probing
+ *
+ * Outputs for B-device state
+ * @adp_sns: TRUE when the B-device is in the process of carrying out
+ * ADP sensing
+ * @data_pulse: TRUE when the B-device is performing data line pulsing
+ *
+ * Internal Variables
+ *
+ * a_set_b_hnp_en: TRUE when the A-device has successfully set the b_hnp_enable
+ * bit in the B-device.
+ * Unused as OTG fsm uses otg->host->b_hnp_enable instead
+ * b_srp_done: TRUE when the B-device has completed initiating SRP
+ * b_hnp_enable: TRUE when the B-device has accepted the SetFeature
+ * (b_hnp_enable) B-device.
+ * Unused as OTG fsm uses otg->gadget->b_hnp_enable instead
+ * a_clr_err: Asserted (by application ?) to clear a_vbus_err due to an
+ * overcurrent condition and causes the A-device to transition
+ * to a_wait_vfall
+ */
struct otg_fsm {
/* Input */
- int id;
+ int id; /* DRD + OTG */
+ int vbus; /* DRD only */
int adp_change;
int power_up;
- int test_device;
- int a_bus_drop;
- int a_bus_req;
int a_srp_det;
int a_vbus_vld;
int b_conn;
int a_bus_resume;
int a_bus_suspend;
int a_conn;
- int b_bus_req;
int b_se0_srp;
int b_ssend_srp;
int b_sess_vld;
+ int test_device;
+ int a_bus_drop;
+ int a_bus_req;
+ int b_bus_req;
+
/* Auxilary inputs */
int a_sess_vld;
int b_bus_resume;
int b_bus_suspend;
/* Output */
- int data_pulse;
int drv_vbus;
int loc_conn;
int loc_sof;
int adp_prb;
int adp_sns;
+ int data_pulse;
/* Internal variables */
int a_set_b_hnp_en;
int b_hnp_enable;
int a_clr_err;
- /* Informative variables */
+ /* Informative variables. All unused as of now */
int a_bus_drop_inf;
int a_bus_req_inf;
int a_clr_err_inf;
/* Current usb protocol used: 0:undefine; 1:host; 2:client */
int protocol;
struct mutex lock;
+ bool state_changed;
};
struct otg_fsm_ops {
void (*del_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer);
int (*start_host)(struct otg_fsm *fsm, int on);
int (*start_gadget)(struct otg_fsm *fsm, int on);
+ int (*start_enum)(struct usb_bus *bus, unsigned port_num);
};
index 154332b7c8c0d165bd94806c818f666e16e5c9d4..489f76074c341111642c0903f9b6d792be41ed67 100644 (file)
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
#ifndef __LINUX_USB_OTG_H
#define __LINUX_USB_OTG_H
+#include <linux/device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg-fsm.h>
#include <linux/usb/phy.h>
struct usb_otg {
struct usb_bus *host;
struct usb_gadget *gadget;
+ enum usb_otg_state state;
+
+/*------------- deprecated interface -----------------------------*/
/* bind/unbind the host controller */
int (*set_host)(struct usb_otg *otg, struct usb_bus *host);
/* start or continue HNP role switch */
int (*start_hnp)(struct usb_otg *otg);
-
+/*---------------------------------------------------------------*/
};
extern const char *usb_otg_state_string(enum usb_otg_state state);
+enum usb_dr_mode {
+ USB_DR_MODE_UNKNOWN,
+ USB_DR_MODE_HOST,
+ USB_DR_MODE_PERIPHERAL,
+ USB_DR_MODE_OTG,
+};
+
+#if IS_ENABLED(CONFIG_USB_OTG)
+struct otg_fsm *usb_otg_register(struct device *parent_dev,
+ struct otg_fsm_ops *fsm_ops, bool drd_only);
+int usb_otg_unregister(struct device *parent_dev);
+int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
+ unsigned long irqflags, struct otg_hcd_ops *ops);
+int usb_otg_unregister_hcd(struct usb_hcd *hcd);
+int usb_otg_register_gadget(struct usb_gadget *gadget,
+ struct otg_gadget_ops *ops);
+int usb_otg_unregister_gadget(struct usb_gadget *gadget);
+void usb_otg_sync_inputs(struct otg_fsm *fsm);
+int usb_otg_kick_fsm(struct device *hcd_gcd_device);
+bool usb_otg_gadget_can_start(struct usb_gadget *gadget);
+struct device *usb_otg_fsm_to_dev(struct otg_fsm *fsm);
+
+#else /* CONFIG_USB_OTG */
+
+static inline struct otg_fsm *usb_otg_register(struct device *parent_dev,
+ struct otg_fsm_ops *fsm_ops,
+ bool drd_only)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline int usb_otg_unregister(struct device *parent_dev)
+{
+ return -ENOSYS;
+}
+
+static inline int usb_otg_register_hcd(struct usb_hcd *hcd, unsigned int irqnum,
+ unsigned long irqflags,
+ struct otg_hcd_ops *ops)
+{
+ return -ENOSYS;
+}
+
+static inline int usb_otg_unregister_hcd(struct usb_hcd *hcd)
+{
+ return -ENOSYS;
+}
+
+static inline int usb_otg_register_gadget(struct usb_gadget *gadget,
+ struct otg_gadget_ops *ops)
+{
+ return -ENOSYS;
+}
+
+static inline int usb_otg_unregister_gadget(struct usb_gadget *gadget)
+{
+ return -ENOSYS;
+}
+
+static inline void usb_otg_sync_inputs(struct otg_fsm *fsm)
+{
+}
+
+static inline int usb_otg_kick_fsm(struct device *hcd_gcd_device)
+{
+ return -ENOSYS;
+}
+
+static inline bool usb_otg_gadget_can_start(struct usb_gadget *gadget)
+{
+ return true;
+}
+
+static inline struct device *usb_otg_fsm_to_dev(struct otg_fsm *fsm)
+{
+ return NULL;
+}
+
+#endif /* CONFIG_USB_OTG */
+
+
+/*------------- deprecated interface -----------------------------*/
/* Context: can sleep */
static inline int
otg_start_hnp(struct usb_otg *otg)
/* for OTG controller drivers (and maybe other stuff) */
extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
-enum usb_dr_mode {
- USB_DR_MODE_UNKNOWN,
- USB_DR_MODE_HOST,
- USB_DR_MODE_PERIPHERAL,
- USB_DR_MODE_OTG,
-};
+/*---------------------------------------------------------------*/
#endif /* __LINUX_USB_OTG_H */
index 6c0b1c513db72ce9632396223ed99aca20ff3efb..5b23a3a3bea3ec203baf60d10f4e1048c815470d 100644 (file)
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
unsigned int flags;
enum usb_phy_type type;
- enum usb_otg_state state;
enum usb_phy_events last_event;
struct usb_otg *otg;
index 8ef732155623b0a6e9fd7eda09190697ec29da5a..376654b5b0f79603799567871110b0eb4ee2ebe3 100644 (file)
*/
struct usb_xhci_pdata {
unsigned usb3_lpm_capable:1;
- unsigned usb_drd_support:1;
- unsigned usb_needs_lhc_reset:1;
};
#endif /* __USB_CORE_XHCI_PDRIVER_H */
index 349325404add6c532b7cbf018d8510e00e1c0914..e4b9e011d2a195a8e79d228066417d92bd5f7098 100644 (file)
sense_reason_t (*execute_cmd)(struct se_cmd *);
sense_reason_t (*execute_rw)(struct se_cmd *, struct scatterlist *,
u32, enum dma_data_direction);
- sense_reason_t (*transport_complete_callback)(struct se_cmd *);
+ sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool);
unsigned char *t_task_cdb;
unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE];
diff --git a/kernel/irq/dummychip.c b/kernel/irq/dummychip.c
index 988dc58e8847f6ebdbcd78348d9f527a9e4f2dfe..2feb6feca0cc96dff8514c45750542386db5ec53 100644 (file)
--- a/kernel/irq/dummychip.c
+++ b/kernel/irq/dummychip.c
.irq_ack = noop,
.irq_mask = noop,
.irq_unmask = noop,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
};
EXPORT_SYMBOL_GPL(dummy_irq_chip);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 1f4bcb3cc21cee5bcfd1b4e13a77eeff2af23a2b..be9760f8284a41dcab57a6510a980effe41d2233 100644 (file)
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
static int ptrace_resume(struct task_struct *child, long request,
unsigned long data)
{
+ bool need_siglock;
+
if (!valid_signal(data))
return -EIO;
user_disable_single_step(child);
}
+ /*
+ * Change ->exit_code and ->state under siglock to avoid the race
+ * with wait_task_stopped() in between; a non-zero ->exit_code will
+ * wrongly look like another report from tracee.
+ *
+ * Note that we need siglock even if ->exit_code == data and/or this
+ * status was not reported yet, the new status must not be cleared by
+ * wait_task_stopped() after resume.
+ *
+ * If data == 0 we do not care if wait_task_stopped() reports the old
+ * status and clears the code too; this can't race with the tracee, it
+ * takes siglock after resume.
+ */
+ need_siglock = data && !thread_group_empty(current);
+ if (need_siglock)
+ spin_lock_irq(&child->sighand->siglock);
child->exit_code = data;
wake_up_state(child, __TASK_TRACED);
+ if (need_siglock)
+ spin_unlock_irq(&child->sighand->siglock);
return 0;
}
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 490fcbb1dc5b41727408d28e17ae145754c2c051..93be750348c86f5bda390f66615d42c2298a9950 100644 (file)
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
* in the task stack here.
*/
__do_softirq();
- rcu_note_context_switch(cpu);
local_irq_enable();
cond_resched();
+
+ preempt_disable();
+ rcu_note_context_switch(cpu);
+ preempt_enable();
+
return;
}
local_irq_enable();
diff --git a/kernel/time.c b/kernel/time.c
index 3eb322e518a31d06eedd0b25e4b5d766c36c0a5e..c8cc0a4e3badd35b6a0461cb5d3ff8371bc127ef 100644 (file)
--- a/kernel/time.c
+++ b/kernel/time.c
{
return (unsigned long)nsecs_to_jiffies64(n);
}
+EXPORT_SYMBOL_GPL(nsecs_to_jiffies);
/*
* Add two timespec values and do a safety check for overflow.
index 774a0807fe811b103d4b80d33b284ef48ecd7fc4..da41de9dc319aefbf3969e959030fb3a1f55e41c 100644 (file)
static __always_inline int trace_recursive_lock(void)
{
- unsigned int val = this_cpu_read(current_context);
+ unsigned int val = __this_cpu_read(current_context);
int bit;
if (in_interrupt()) {
return 1;
val |= (1 << bit);
- this_cpu_write(current_context, val);
+ __this_cpu_write(current_context, val);
return 0;
}
static __always_inline void trace_recursive_unlock(void)
{
- unsigned int val = this_cpu_read(current_context);
+ unsigned int val = __this_cpu_read(current_context);
- val--;
- val &= this_cpu_read(current_context);
- this_cpu_write(current_context, val);
+ val &= val & (val - 1);
+ __this_cpu_write(current_context, val);
}
#else
diff --git a/lib/string.c b/lib/string.c
index 43d0781daf4703d94be9fd988bd6054f49cdeca4..cb9ea218155780cc6ba2dab7676f72f6c4ff17a0 100644 (file)
--- a/lib/string.c
+++ b/lib/string.c
void memzero_explicit(void *s, size_t count)
{
memset(s, 0, count);
- OPTIMIZER_HIDE_VAR(s);
+ barrier();
}
EXPORT_SYMBOL(memzero_explicit);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e2b1bba6988269fb32e7e6b26903031de3242236..69ec61abfb37aee9ab8f6ba2f752189ccc7ff094 100644 (file)
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
EXPORT_SYMBOL(__alloc_skb);
/**
- * build_skb - build a network buffer
+ * __build_skb - build a network buffer
* @data: data buffer provided by caller
- * @frag_size: size of fragment, or 0 if head was kmalloced
+ * @frag_size: size of data, or 0 if head was kmalloced
*
* Allocate a new &sk_buff. Caller provides space holding head and
* skb_shared_info. @data must have been allocated by kmalloc() only if
- * @frag_size is 0, otherwise data should come from the page allocator.
+ * @frag_size is 0, otherwise data should come from the page allocator
+ * or vmalloc()
* The return is the new skb buffer.
* On a failure the return is %NULL, and @data is not freed.
* Notes :
* before giving packet to stack.
* RX rings only contains data buffers, not full skbs.
*/
-struct sk_buff *build_skb(void *data, unsigned int frag_size)
+struct sk_buff *__build_skb(void *data, unsigned int frag_size)
{
struct skb_shared_info *shinfo;
struct sk_buff *skb;
memset(skb, 0, offsetof(struct sk_buff, tail));
skb->truesize = SKB_TRUESIZE(size);
- skb->head_frag = frag_size != 0;
atomic_set(&skb->users, 1);
skb->head = data;
skb->data = data;
return skb;
}
+
+/* build_skb() is wrapper over __build_skb(), that specifically
+ * takes care of skb->head and skb->pfmemalloc
+ * This means that if @frag_size is not zero, then @data must be backed
+ * by a page fragment, not kmalloc() or vmalloc()
+ */
+struct sk_buff *build_skb(void *data, unsigned int frag_size)
+{
+ struct sk_buff *skb = __build_skb(data, frag_size);
+
+ if (skb && frag_size) {
+ skb->head_frag = 1;
+ if (virt_to_head_page(data)->pfmemalloc)
+ skb->pfmemalloc = 1;
+ }
+ return skb;
+}
EXPORT_SYMBOL(build_skb);
struct netdev_alloc_cache {
gfp_t gfp = gfp_mask;
if (order)
- gfp |= __GFP_COMP | __GFP_NOWARN;
+ gfp |= __GFP_COMP | __GFP_NOWARN |
+ __GFP_NOMEMALLOC;
nc->frag.page = alloc_pages(gfp, order);
if (likely(nc->frag.page))
break;
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index ecb34b5ea42ff6db2944ed649e6e26db2824164f..57075c4508f719a183ebe47beef7ed2b9c1ce1df 100644 (file)
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
struct rtable *rt; /* Route we use */
struct ip_options *opt = &(IPCB(skb)->opt);
+ if (unlikely(skb->sk))
+ goto drop;
+
if (skb_warn_if_lro(skb))
goto drop;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 8c70c73da34750200d12e617f5fa7f236000d5bc..a68cd7100349274de28efe45dad94a1400ce6822 100644 (file)
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
}
}
-/* Send a fin. The caller locks the socket for us. This cannot be
- * allowed to fail queueing a FIN frame under any circumstances.
+/* We allow to exceed memory limits for FIN packets to expedite
+ * connection tear down and (memory) recovery.
+ * Otherwise tcp_send_fin() could be tempted to either delay FIN
+ * or even be forced to close flow without any FIN.
+ */
+static void sk_forced_wmem_schedule(struct sock *sk, int size)
+{
+ int amt, status;
+
+ if (size <= sk->sk_forward_alloc)
+ return;
+ amt = sk_mem_pages(size);
+ sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
+ sk_memory_allocated_add(sk, amt, &status);
+}
+
+/* Send a FIN. The caller locks the socket for us.
+ * We should try to send a FIN packet really hard, but eventually give up.
*/
void tcp_send_fin(struct sock *sk)
{
+ struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk);
struct tcp_sock *tp = tcp_sk(sk);
- struct sk_buff *skb = tcp_write_queue_tail(sk);
- int mss_now;
- /* Optimization, tack on the FIN if we have a queue of
- * unsent frames. But be careful about outgoing SACKS
- * and IP options.
+ /* Optimization, tack on the FIN if we have one skb in write queue and
+ * this skb was not yet sent, or we are under memory pressure.
+ * Note: in the latter case, FIN packet will be sent after a timeout,
+ * as TCP stack thinks it has already been transmitted.
*/
- mss_now = tcp_current_mss(sk);
-
- if (tcp_send_head(sk) != NULL) {
- TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN;
- TCP_SKB_CB(skb)->end_seq++;
+ if (tskb && (tcp_send_head(sk) || sk_under_memory_pressure(sk))) {
+coalesce:
+ TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN;
+ TCP_SKB_CB(tskb)->end_seq++;
tp->write_seq++;
+ if (!tcp_send_head(sk)) {
+ /* This means tskb was already sent.
+ * Pretend we included the FIN on previous transmit.
+ * We need to set tp->snd_nxt to the value it would have
+ * if FIN had been sent. This is because retransmit path
+ * does not change tp->snd_nxt.
+ */
+ tp->snd_nxt++;
+ return;
+ }
} else {
- /* Socket is locked, keep trying until memory is available. */
- for (;;) {
- skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
- if (skb)
- break;
- yield();
+ skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation);
+ if (unlikely(!skb)) {
+ if (tskb)
+ goto coalesce;
+ return;
}
+ skb_reserve(skb, MAX_TCP_HEADER);
+ sk_forced_wmem_schedule(sk, skb->truesize);
/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
tcp_init_nondata_skb(skb, tp->write_seq,
TCPHDR_ACK | TCPHDR_FIN);
tcp_queue_skb(sk, skb);
}
- __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF);
+ __tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF);
}
/* We get here when a process closes a file descriptor (either due to
index 1d52506bda14145795b52940e41fa5d5fe3bdd9b..a0b0ea949192ef8aefa5ec76bcbbd51736628f76 100644 (file)
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
if (data == NULL)
return NULL;
- skb = build_skb(data, size);
+ skb = __build_skb(data, size);
if (skb == NULL)
vfree(data);
- else {
- skb->head_frag = 0;
+ else
skb->destructor = netlink_skb_destructor;
- }
return skb;
}
index 2ca9f2e93139e125925c096f3e6163c3e2cd1c87..53745f4c2bf59f136ed664edd4276d8ccf5cfa63 100644 (file)
struct snd_emu10k1 *emu = entry->private_data;
u32 value;
u32 value2;
- unsigned long flags;
u32 rate;
if (emu->card_capabilities->emu_model) {
- spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_read(emu, 0x38, &value);
- spin_unlock_irqrestore(&emu->emu_lock, flags);
if ((value & 0x1) == 0) {
- spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_read(emu, 0x2a, &value);
snd_emu1010_fpga_read(emu, 0x2b, &value2);
- spin_unlock_irqrestore(&emu->emu_lock, flags);
rate = 0x1770000 / (((value << 5) | value2)+1);
snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
} else {
snd_iprintf(buffer, "ADAT Unlocked\n");
}
- spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_read(emu, 0x20, &value);
- spin_unlock_irqrestore(&emu->emu_lock, flags);
if ((value & 0x4) == 0) {
- spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_read(emu, 0x28, &value);
snd_emu1010_fpga_read(emu, 0x29, &value2);
- spin_unlock_irqrestore(&emu->emu_lock, flags);
rate = 0x1770000 / (((value << 5) | value2)+1);
snd_iprintf(buffer, "SPDIF Locked : %d\n", rate);
} else {
{
struct snd_emu10k1 *emu = entry->private_data;
u32 value;
- unsigned long flags;
int i;
snd_iprintf(buffer, "EMU1010 Registers:\n\n");
for(i = 0; i < 0x40; i+=1) {
- spin_lock_irqsave(&emu->emu_lock, flags);
snd_emu1010_fpga_read(emu, i, &value);
- spin_unlock_irqrestore(&emu->emu_lock, flags);
snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f);
}
}
index 7ccad190a9d66508d7b28ac07afa1b6e12a7ddc6..90368eac505a36fce6f90d10b843d0bad7f1ce61 100644 (file)
CONFIG_USB_TEST=m
# CONFIG_USB_DEBUG is not set
+#USB OTG
+CONFIG_USB_OTG=y
+
#USB MUSB support
CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_MUSB_OMAP2PLUS=m
CONFIG_MTD_M25P80=m
#EXTCON
-CONFIG_EXTCON_GPIO=y
+CONFIG_EXTCON_USB_GPIO=y
# Networking
CONFIG_NF_CONNTRACK=y
index dcc665228c71fd09f7b39c2486063d98f7176445..deb3569ab004ffc8904121695773ffd02d239140 100644 (file)
switch (type_len) {
case KBUFFER_TYPE_PADDING:
*length = read_4(kbuf, data);
- data += *length;
break;
case KBUFFER_TYPE_TIME_EXTEND:
index d1b3a361e526d83d1ce011819d917e6f9c256f81..4039854560d0d5dffe32150562a6f11b2791033f 100644 (file)
CC = $(CROSS_COMPILE)gcc
-BUILD_OUTPUT := $(PWD)
+BUILD_OUTPUT := $(CURDIR)
PREFIX := /usr
DESTDIR :=
+ifeq ("$(origin O)", "command line")
+ BUILD_OUTPUT := $(O)
+endif
+
turbostat : turbostat.c
CFLAGS += -Wall
CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"'
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 66112533b1e9cfac421ce3a6b9f4d9be72fea9a3..eed250e9c21895cd924a7852fba2b16427216204 100644 (file)
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
ghc->generation = slots->generation;
ghc->len = len;
ghc->memslot = gfn_to_memslot(kvm, start_gfn);
- ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
- if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
+ ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, NULL);
+ if (!kvm_is_error_hva(ghc->hva) && nr_pages_needed <= 1) {
ghc->hva += offset;
} else {
/*