1
0
Fork 0

USB patches for 5.5-rc1

Here is the big set of USB patches for 5.5-rc1
 
 Lots of little things in here:
   - typec updates and additions
   - usb-serial drivers cleanups and fixes
   - misc USB drivers cleanups and fixes
   - gadget drivers new features and controllers added
   - usual xhci additions
   - other minor changes
 
 All of these have been in linux-next with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXd5+Iw8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ylA4wCbB3P206oHeHLBe9Eika3D8gM9/fMAn2oWlmpB
 Xh7wr30FGC02zU/KBpJ1
 =U5qC
 -----END PGP SIGNATURE-----

Merge tag 'usb-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB updates from Greg KH:
 "Here is the big set of USB patches for 5.5-rc1

  Lots of little things in here:
   - typec updates and additions
   - usb-serial drivers cleanups and fixes
   - misc USB drivers cleanups and fixes
   - gadget drivers new features and controllers added
   - usual xhci additions
   - other minor changes

  All of these have been in linux-next with no reported issues"

* tag 'usb-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (223 commits)
  usb: gadget: udc: gr_udc: create debugfs directory under usb root
  usb: gadget: atmel: create debugfs directory under usb root
  usb: musb: create debugfs directory under usb root
  usb: serial: Fix Kconfig indentation
  usb: misc: Fix Kconfig indentation
  usb: gadget: Fix Kconfig indentation
  usb: host: Fix Kconfig indentation
  usb: dwc3: Fix Kconfig indentation
  usb: gadget: configfs: Fix missing spin_lock_init()
  usb-storage: Disable UAS on JMicron SATA enclosure
  USB: documentation: flags on usb-storage versus UAS
  USB: uas: heed CAPACITY_HEURISTICS
  USB: uas: honor flag to avoid CAPACITY16
  usb: host: xhci-tegra: Correct phy enable sequence
  usb-serial: cp201x: support Mark-10 digital force gauge
  usb: chipidea: imx: pinctrl for HSIC is optional
  usb: chipidea: imx: refine the error handling for hsic
  usb: chipidea: imx: change hsic power regulator as optional
  usb: chipidea: imx: check data->usbmisc_data against NULL before access
  usb: chipidea: core: change vbus-regulator as optional
  ...
alistair/sunxi64-5.5-dsi
Linus Torvalds 2019-11-27 10:46:34 -08:00
commit 59274c7164
141 changed files with 7263 additions and 2873 deletions

View File

@ -5114,13 +5114,13 @@
Flags is a set of characters, each corresponding
to a common usb-storage quirk flag as follows:
a = SANE_SENSE (collect more than 18 bytes
of sense data);
of sense data, not on uas);
b = BAD_SENSE (don't collect more than 18
bytes of sense data);
bytes of sense data, not on uas);
c = FIX_CAPACITY (decrease the reported
device capacity by one sector);
d = NO_READ_DISC_INFO (don't use
READ_DISC_INFO command);
READ_DISC_INFO command, not on uas);
e = NO_READ_CAPACITY_16 (don't use
READ_CAPACITY_16 command);
f = NO_REPORT_OPCODES (don't use report opcodes
@ -5135,17 +5135,18 @@
j = NO_REPORT_LUNS (don't use report luns
command, uas only);
l = NOT_LOCKABLE (don't try to lock and
unlock ejectable media);
unlock ejectable media, not on uas);
m = MAX_SECTORS_64 (don't transfer more
than 64 sectors = 32 KB at a time);
than 64 sectors = 32 KB at a time,
not on uas);
n = INITIAL_READ10 (force a retry of the
initial READ(10) command);
initial READ(10) command, not on uas);
o = CAPACITY_OK (accept the capacity
reported by the device);
reported by the device, not on uas);
p = WRITE_CACHE (the device cache is ON
by default);
by default, not on uas);
r = IGNORE_RESIDUE (the device reports
bogus residue values);
bogus residue values, not on uas);
s = SINGLE_LUN (the device has only one
Logical Unit);
t = NO_ATA_1X (don't allow ATA(12) and ATA(16)
@ -5154,7 +5155,8 @@
w = NO_WP_DETECT (don't test whether the
medium is write-protected).
y = ALWAYS_SYNC (issue a SYNCHRONIZE_CACHE
even if the device claims no cache)
even if the device claims no cache,
not on uas)
Example: quirks=0419:aaf5:rl,0421:0433:rc
user_debug= [KNL,ARM]

View File

@ -8,6 +8,7 @@ Required Properties:
- "renesas,r8a7745-usb-dmac" (RZ/G1E)
- "renesas,r8a77470-usb-dmac" (RZ/G1C)
- "renesas,r8a774a1-usb-dmac" (RZ/G2M)
- "renesas,r8a774b1-usb-dmac" (RZ/G2N)
- "renesas,r8a774c0-usb-dmac" (RZ/G2E)
- "renesas,r8a7790-usb-dmac" (R-Car H2)
- "renesas,r8a7791-usb-dmac" (R-Car M2-W)

View File

@ -10,6 +10,8 @@ Required properties:
SoC.
"renesas,usb2-phy-r8a774a1" if the device is a part of an R8A774A1
SoC.
"renesas,usb2-phy-r8a774b1" if the device is a part of an R8A774B1
SoC.
"renesas,usb2-phy-r8a774c0" if the device is a part of an R8A774C0
SoC.
"renesas,usb2-phy-r8a7795" if the device is a part of an R8A7795

View File

@ -8,6 +8,8 @@ need this driver.
Required properties:
- compatible: "renesas,r8a774a1-usb3-phy" if the device is a part of an R8A774A1
SoC.
"renesas,r8a774b1-usb3-phy" if the device is a part of an R8A774B1
SoC.
"renesas,r8a7795-usb3-phy" if the device is a part of an R8A7795
SoC.

View File

@ -1,41 +0,0 @@
Renesas Electronics USB3.0 Peripheral driver
Required properties:
- compatible: Must contain one of the following:
- "renesas,r8a774a1-usb3-peri"
- "renesas,r8a774c0-usb3-peri"
- "renesas,r8a7795-usb3-peri"
- "renesas,r8a7796-usb3-peri"
- "renesas,r8a77965-usb3-peri"
- "renesas,r8a77990-usb3-peri"
- "renesas,rcar-gen3-usb3-peri" for a generic R-Car Gen3 or RZ/G2
compatible device
When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first
followed by the generic version.
- reg: Base address and length of the register for the USB3.0 Peripheral
- interrupts: Interrupt specifier for the USB3.0 Peripheral
- clocks: clock phandle and specifier pair
Optional properties:
- phys: phandle + phy specifier pair
- phy-names: must be "usb"
Example of R-Car H3 ES1.x:
usb3_peri0: usb@ee020000 {
compatible = "renesas,r8a7795-usb3-peri",
"renesas,rcar-gen3-usb3-peri";
reg = <0 0xee020000 0 0x400>;
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 328>;
};
usb3_peri1: usb@ee060000 {
compatible = "renesas,r8a7795-usb3-peri",
"renesas,rcar-gen3-usb3-peri";
reg = <0 0xee060000 0 0x400>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 327>;
};

View File

@ -0,0 +1,86 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/renesas,usb3-peri.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas USB 3.0 Peripheral controller
maintainers:
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
properties:
compatible:
items:
- enum:
- renesas,r8a774a1-usb3-peri # RZ/G2M
- renesas,r8a774b1-usb3-peri # RZ/G2N
- renesas,r8a774c0-usb3-peri # RZ/G2E
- renesas,r8a7795-usb3-peri # R-Car H3
- renesas,r8a7796-usb3-peri # R-Car M3-W
- renesas,r8a77965-usb3-peri # R-Car M3-N
- renesas,r8a77990-usb3-peri # R-Car E3
- const: renesas,rcar-gen3-usb3-peri
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
phys:
maxItems: 1
phy-names:
const: usb
power-domains:
maxItems: 1
resets:
maxItems: 1
usb-role-switch:
$ref: /schemas/types.yaml#/definitions/flag
description: Support role switch.
companion:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle of a companion.
port:
description: |
any connector to the data bus of this controller should be modelled
using the OF graph bindings specified, if the "usb-role-switch"
property is used.
required:
- compatible
- interrupts
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r8a774c0-cpg-mssr.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a774c0-sysc.h>
usb3_peri0: usb@ee020000 {
compatible = "renesas,r8a774c0-usb3-peri", "renesas,rcar-gen3-usb3-peri";
reg = <0 0xee020000 0 0x400>;
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 328>;
companion = <&xhci0>;
usb-role-switch;
port {
usb3_role_switch: endpoint {
remote-endpoint = <&hd3ss3220_ep>;
};
};
};

View File

@ -1,57 +0,0 @@
Renesas Electronics USBHS driver
Required properties:
- compatible: Must contain one or more of the following:
- "renesas,usbhs-r8a7743" for r8a7743 (RZ/G1M) compatible device
- "renesas,usbhs-r8a7744" for r8a7744 (RZ/G1N) compatible device
- "renesas,usbhs-r8a7745" for r8a7745 (RZ/G1E) compatible device
- "renesas,usbhs-r8a77470" for r8a77470 (RZ/G1C) compatible device
- "renesas,usbhs-r8a774a1" for r8a774a1 (RZ/G2M) compatible device
- "renesas,usbhs-r8a774c0" for r8a774c0 (RZ/G2E) compatible device
- "renesas,usbhs-r8a7790" for r8a7790 (R-Car H2) compatible device
- "renesas,usbhs-r8a7791" for r8a7791 (R-Car M2-W) compatible device
- "renesas,usbhs-r8a7792" for r8a7792 (R-Car V2H) compatible device
- "renesas,usbhs-r8a7793" for r8a7793 (R-Car M2-N) compatible device
- "renesas,usbhs-r8a7794" for r8a7794 (R-Car E2) compatible device
- "renesas,usbhs-r8a7795" for r8a7795 (R-Car H3) compatible device
- "renesas,usbhs-r8a7796" for r8a7796 (R-Car M3-W) compatible device
- "renesas,usbhs-r8a77965" for r8a77965 (R-Car M3-N) compatible device
- "renesas,usbhs-r8a77990" for r8a77990 (R-Car E3) compatible device
- "renesas,usbhs-r8a77995" for r8a77995 (R-Car D3) compatible device
- "renesas,usbhs-r7s72100" for r7s72100 (RZ/A1) compatible device
- "renesas,usbhs-r7s9210" for r7s9210 (RZ/A2) compatible device
- "renesas,rcar-gen2-usbhs" for R-Car Gen2 or RZ/G1 compatible devices
- "renesas,rcar-gen3-usbhs" for R-Car Gen3 or RZ/G2 compatible devices
- "renesas,rza1-usbhs" for RZ/A1 compatible device
- "renesas,rza2-usbhs" for RZ/A2 compatible device
When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first followed
by the generic version.
- reg: Base address and length of the register for the USBHS
- interrupts: Interrupt specifier for the USBHS
- clocks: A list of phandle + clock specifier pairs.
- In case of "renesas,rcar-gen3-usbhs", two clocks are required.
First clock should be peripheral and second one should be host.
- In case of except above, one clock is required. First clock
should be peripheral.
Optional properties:
- renesas,buswait: Integer to use BUSWAIT register
- renesas,enable-gpio: A gpio specifier to check GPIO determining if USB
function should be enabled
- phys: phandle + phy specifier pair
- phy-names: must be "usb"
- dmas: Must contain a list of references to DMA specifiers.
- dma-names : named "ch%d", where %d is the channel number ranging from zero
to the number of channels (DnFIFOs) minus one.
Example:
usbhs: usb@e6590000 {
compatible = "renesas,usbhs-r8a7790", "renesas,rcar-gen2-usbhs";
reg = <0 0xe6590000 0 0x100>;
interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp7_clks R8A7790_CLK_HSUSB>;
};

View File

@ -0,0 +1,126 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/renesas,usbhs.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas USBHS (HS-USB) controller
maintainers:
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
properties:
compatible:
oneOf:
- items:
- const: renesas,usbhs-r7s72100 # RZ/A1
- const: renesas,rza1-usbhs
- items:
- const: renesas,usbhs-r7s9210 # RZ/A2
- const: renesas,rza2-usbhs
- items:
- enum:
- renesas,usbhs-r8a7743 # RZ/G1M
- renesas,usbhs-r8a7744 # RZ/G1N
- renesas,usbhs-r8a7745 # RZ/G1E
- renesas,usbhs-r8a77470 # RZ/G1C
- renesas,usbhs-r8a7790 # R-Car H2
- renesas,usbhs-r8a7791 # R-Car M2-W
- renesas,usbhs-r8a7792 # R-Car V2H
- renesas,usbhs-r8a7793 # R-Car M2-N
- renesas,usbhs-r8a7794 # R-Car E2
- const: renesas,rcar-gen2-usbhs
- items:
- enum:
- renesas,usbhs-r8a774a1 # RZ/G2M
- renesas,usbhs-r8a774b1 # RZ/G2N
- renesas,usbhs-r8a774c0 # RZ/G2E
- renesas,usbhs-r8a7795 # R-Car H3
- renesas,usbhs-r8a7796 # R-Car M3-W
- renesas,usbhs-r8a77965 # R-Car M3-N
- renesas,usbhs-r8a77990 # R-Car E3
- renesas,usbhs-r8a77995 # R-Car D3
- const: renesas,rcar-gen3-usbhs
reg:
maxItems: 1
clocks:
minItems: 1
maxItems: 3
items:
- description: USB 2.0 host
- description: USB 2.0 peripheral
- description: USB 2.0 clock selector
interrupts:
maxItems: 1
renesas,buswait:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Integer to use BUSWAIT register.
renesas,enable-gpio:
description: |
gpio specifier to check GPIO determining if USB function should be
enabled.
phys:
maxItems: 1
items:
- description: phandle + phy specifier pair.
phy-names:
maxItems: 1
items:
- const: usb
dmas:
minItems: 2
maxItems: 4
dma-names:
minItems: 2
maxItems: 4
items:
- const: ch0
- const: ch1
- const: ch2
- const: ch3
dr_mode: true
power-domains:
maxItems: 1
resets:
minItems: 1
maxItems: 2
items:
- description: USB 2.0 host
- description: USB 2.0 peripheral
required:
- compatible
- reg
- clocks
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a7790-sysc.h>
usbhs: usb@e6590000 {
compatible = "renesas,usbhs-r8a7790", "renesas,rcar-gen2-usbhs";
reg = <0 0xe6590000 0 0x100>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 704>;
};

View File

@ -6,10 +6,39 @@ Required properties:
- interrupts : <a b> where a is the interrupt number and b represents an
encoding of the sense and level information for the interrupt.
Required sub-node:
- connector: The "usb-c-connector" attached to the tcpci chip, the bindings
of connector node are specified in
Documentation/devicetree/bindings/connector/usb-connector.txt
Example :
rt1711h@4e {
compatible = "richtek,rt1711h";
reg = <0x4e>;
interrupt-parent = <&gpio26>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
usb_con: connector {
compatible = "usb-c-connector";
label = "USB-C";
data-role = "dual";
power-role = "dual";
try-power-role = "sink";
source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
PDO_VAR(5000, 12000, 2000)>;
op-sink-microwatt = <10000000>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
usb_con_ss: endpoint {
remote-endpoint = <&usb3_data_ss>;
};
};
};
};
};

View File

@ -0,0 +1,38 @@
TI HD3SS3220 TypeC DRP Port Controller.
Required properties:
- compatible: Must be "ti,hd3ss3220".
- reg: I2C slave address, must be 0x47 or 0x67 based on ADDR pin.
- interrupts: An interrupt specifier.
Required sub-node:
- connector: The "usb-c-connector" attached to the hd3ss3220 chip. The
bindings of the connector node are specified in:
Documentation/devicetree/bindings/connector/usb-connector.txt
Example:
hd3ss3220@47 {
compatible = "ti,hd3ss3220";
reg = <0x47>;
interrupt-parent = <&gpio6>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
connector {
compatible = "usb-c-connector";
label = "USB-C";
data-role = "dual";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
hd3ss3220_ep: endpoint {
remote-endpoint = <&usb3_role_switch>;
};
};
};
};
};

View File

@ -0,0 +1,86 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: "http://devicetree.org/schemas/usb/ti,j721e-usb.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Bindings for the TI wrapper module for the Cadence USBSS-DRD controller
maintainers:
- Roger Quadros <rogerq@ti.com>
properties:
compatible:
items:
- const: ti,j721e-usb
reg:
description: module registers
power-domains:
description:
PM domain provider node and an args specifier containing
the USB device id value. See,
Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
clocks:
description: Clock phandles to usb2_refclk and lpm_clk
minItems: 2
maxItems: 2
clock-names:
items:
- const: ref
- const: lpm
ti,usb2-only:
description:
If present, it restricts the controller to USB2.0 mode of
operation. Must be present if USB3 PHY is not available
for USB.
type: boolean
ti,vbus-divider:
description:
Should be present if USB VBUS line is connected to the
VBUS pin of the SoC via a 1/3 voltage divider.
type: boolean
required:
- compatible
- reg
- power-domains
- clocks
- clock-names
examples:
- |
#include <dt-bindings/soc/ti,sci_pm_domain.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
cdns_usb@4104000 {
compatible = "ti,j721e-usb";
reg = <0x00 0x4104000 0x00 0x100>;
power-domains = <&k3_pds 288 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 288 15>, <&k3_clks 288 3>;
clock-names = "ref", "lpm";
assigned-clocks = <&k3_clks 288 15>; /* USB2_REFCLK */
assigned-clock-parents = <&k3_clks 288 16>; /* HFOSC0 */
#address-cells = <2>;
#size-cells = <2>;
usb@6000000 {
compatible = "cdns,usb3";
reg = <0x00 0x6000000 0x00 0x10000>,
<0x00 0x6010000 0x00 0x10000>,
<0x00 0x6020000 0x00 0x10000>;
reg-names = "otg", "xhci", "dev";
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
<GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, /* irq.6 */
<GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; /* otgirq.0 */
interrupt-names = "host",
"peripheral",
"otg";
maximum-speed = "super-speed";
dr_mode = "otg";
};
};

View File

@ -10,6 +10,7 @@ Required properties:
- "renesas,xhci-r8a7743" for r8a7743 SoC
- "renesas,xhci-r8a7744" for r8a7744 SoC
- "renesas,xhci-r8a774a1" for r8a774a1 SoC
- "renesas,xhci-r8a774b1" for r8a774b1 SoC
- "renesas,xhci-r8a774c0" for r8a774c0 SoC
- "renesas,xhci-r8a7790" for r8a7790 SoC
- "renesas,xhci-r8a7791" for r8a7791 SoC

View File

@ -7,11 +7,12 @@ Required properties :
- compatible : Should be "microchip,usb251xb" or one of the specific types:
"microchip,usb2512b", "microchip,usb2512bi", "microchip,usb2513b",
"microchip,usb2513bi", "microchip,usb2514b", "microchip,usb2514bi",
"microchip,usb2517", "microchip,usb2517i"
"microchip,usb2517", "microchip,usb2517i", "microchip,usb2422"
- reg : I2C address on the selected bus (default is <0x2C>)
Optional properties :
- reset-gpios : Should specify the gpio for hub reset
- vdd-supply : Should specify the phandle to the regulator supplying vdd
- skip-config : Skip Hub configuration, but only send the USB-Attach command
- vendor-id : Set USB Vendor ID of the hub (16 bit, default is 0x0424)
- product-id : Set USB Product ID of the hub (16 bit, default depends on type)

View File

@ -322,6 +322,25 @@ static void axp288_put_role_sw(void *data)
usb_role_switch_put(info->role_sw);
}
static int axp288_extcon_find_role_sw(struct axp288_extcon_info *info)
{
const struct software_node *swnode;
struct fwnode_handle *fwnode;
if (!x86_match_cpu(cherry_trail_cpu_ids))
return 0;
swnode = software_node_find_by_name(NULL, "intel-xhci-usb-sw");
if (!swnode)
return -EPROBE_DEFER;
fwnode = software_node_fwnode(swnode);
info->role_sw = usb_role_switch_find_by_fwnode(fwnode);
fwnode_handle_put(fwnode);
return info->role_sw ? 0 : -EPROBE_DEFER;
}
static int axp288_extcon_probe(struct platform_device *pdev)
{
struct axp288_extcon_info *info;
@ -343,9 +362,10 @@ static int axp288_extcon_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, info);
info->role_sw = usb_role_switch_get(dev);
if (IS_ERR(info->role_sw))
return PTR_ERR(info->role_sw);
ret = axp288_extcon_find_role_sw(info);
if (ret)
return ret;
if (info->role_sw) {
ret = devm_add_action_or_reset(dev, axp288_put_role_sw, info);
if (ret)
@ -440,26 +460,14 @@ static struct platform_driver axp288_extcon_driver = {
},
};
static struct device_connection axp288_extcon_role_sw_conn = {
.endpoint[0] = "axp288_extcon",
.endpoint[1] = "intel_xhci_usb_sw-role-switch",
.id = "usb-role-switch",
};
static int __init axp288_extcon_init(void)
{
if (x86_match_cpu(cherry_trail_cpu_ids))
device_connection_add(&axp288_extcon_role_sw_conn);
return platform_driver_register(&axp288_extcon_driver);
}
module_init(axp288_extcon_init);
static void __exit axp288_extcon_exit(void)
{
if (x86_match_cpu(cherry_trail_cpu_ids))
device_connection_remove(&axp288_extcon_role_sw_conn);
platform_driver_unregister(&axp288_extcon_driver);
}
module_exit(axp288_extcon_exit);

View File

@ -108,15 +108,7 @@ void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream)
void uvc_debugfs_init(void)
{
struct dentry *dir;
dir = debugfs_create_dir("uvcvideo", usb_debug_root);
if (IS_ERR_OR_NULL(dir)) {
uvc_printk(KERN_INFO, "Unable to create debugfs directory\n");
return;
}
uvc_debugfs_root_dir = dir;
uvc_debugfs_root_dir = debugfs_create_dir("uvcvideo", usb_debug_root);
}
void uvc_debugfs_cleanup(void)

View File

@ -614,7 +614,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
return PTR_ERR(channel->base);
/* call request_irq for OTG */
irq = platform_get_irq(pdev, 0);
irq = platform_get_irq_optional(pdev, 0);
if (irq >= 0) {
INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,

View File

@ -43,4 +43,14 @@ config USB_CDNS3_PCI_WRAP
If you choose to build this driver as module it will
be dynamically linked and module will be called cdns3-pci.ko
config USB_CDNS3_TI
tristate "Cadence USB3 support on TI platforms"
depends on ARCH_K3 || COMPILE_TEST
default USB_CDNS3
help
Say 'Y' or 'M' here if you are building for Texas Instruments
platforms that contain Cadence USB3 controller core.
e.g. J721e.
endif

View File

@ -14,3 +14,4 @@ endif
cdns3-$(CONFIG_USB_CDNS3_HOST) += host.o
obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o
obj-$(CONFIG_USB_CDNS3_TI) += cdns3-ti.o

View File

@ -0,0 +1,236 @@
// SPDX-License-Identifier: GPL-2.0
/**
* cdns3-ti.c - TI specific Glue layer for Cadence USB Controller
*
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
*/
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
/* USB Wrapper register offsets */
#define USBSS_PID 0x0
#define USBSS_W1 0x4
#define USBSS_STATIC_CONFIG 0x8
#define USBSS_PHY_TEST 0xc
#define USBSS_DEBUG_CTRL 0x10
#define USBSS_DEBUG_INFO 0x14
#define USBSS_DEBUG_LINK_STATE 0x18
#define USBSS_DEVICE_CTRL 0x1c
/* Wrapper 1 register bits */
#define USBSS_W1_PWRUP_RST BIT(0)
#define USBSS_W1_OVERCURRENT_SEL BIT(8)
#define USBSS_W1_MODESTRAP_SEL BIT(9)
#define USBSS_W1_OVERCURRENT BIT(16)
#define USBSS_W1_MODESTRAP_MASK GENMASK(18, 17)
#define USBSS_W1_MODESTRAP_SHIFT 17
#define USBSS_W1_USB2_ONLY BIT(19)
/* Static config register bits */
#define USBSS1_STATIC_PLL_REF_SEL_MASK GENMASK(8, 5)
#define USBSS1_STATIC_PLL_REF_SEL_SHIFT 5
#define USBSS1_STATIC_LOOPBACK_MODE_MASK GENMASK(4, 3)
#define USBSS1_STATIC_LOOPBACK_MODE_SHIFT 3
#define USBSS1_STATIC_VBUS_SEL_MASK GENMASK(2, 1)
#define USBSS1_STATIC_VBUS_SEL_SHIFT 1
#define USBSS1_STATIC_LANE_REVERSE BIT(0)
/* Modestrap modes */
enum modestrap_mode { USBSS_MODESTRAP_MODE_NONE,
USBSS_MODESTRAP_MODE_HOST,
USBSS_MODESTRAP_MODE_PERIPHERAL};
struct cdns_ti {
struct device *dev;
void __iomem *usbss;
int usb2_only:1;
int vbus_divider:1;
struct clk *usb2_refclk;
struct clk *lpm_clk;
};
static const int cdns_ti_rate_table[] = { /* in KHZ */
9600,
10000,
12000,
19200,
20000,
24000,
25000,
26000,
38400,
40000,
58000,
50000,
52000,
};
static inline u32 cdns_ti_readl(struct cdns_ti *data, u32 offset)
{
return readl(data->usbss + offset);
}
static inline void cdns_ti_writel(struct cdns_ti *data, u32 offset, u32 value)
{
writel(value, data->usbss + offset);
}
static int cdns_ti_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = pdev->dev.of_node;
struct cdns_ti *data;
int error;
u32 reg;
int rate_code, i;
unsigned long rate;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
platform_set_drvdata(pdev, data);
data->dev = dev;
data->usbss = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->usbss)) {
dev_err(dev, "can't map IOMEM resource\n");
return PTR_ERR(data->usbss);
}
data->usb2_refclk = devm_clk_get(dev, "ref");
if (IS_ERR(data->usb2_refclk)) {
dev_err(dev, "can't get usb2_refclk\n");
return PTR_ERR(data->usb2_refclk);
}
data->lpm_clk = devm_clk_get(dev, "lpm");
if (IS_ERR(data->lpm_clk)) {
dev_err(dev, "can't get lpm_clk\n");
return PTR_ERR(data->lpm_clk);
}
rate = clk_get_rate(data->usb2_refclk);
rate /= 1000; /* To KHz */
for (i = 0; i < ARRAY_SIZE(cdns_ti_rate_table); i++) {
if (cdns_ti_rate_table[i] == rate)
break;
}
if (i == ARRAY_SIZE(cdns_ti_rate_table)) {
dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
return -EINVAL;
}
rate_code = i;
pm_runtime_enable(dev);
error = pm_runtime_get_sync(dev);
if (error < 0) {
dev_err(dev, "pm_runtime_get_sync failed: %d\n", error);
goto err_get;
}
/* assert RESET */
reg = cdns_ti_readl(data, USBSS_W1);
reg &= ~USBSS_W1_PWRUP_RST;
cdns_ti_writel(data, USBSS_W1, reg);
/* set static config */
reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK;
reg |= rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT;
reg &= ~USBSS1_STATIC_VBUS_SEL_MASK;
data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
if (data->vbus_divider)
reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT;
cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg);
reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
/* set USB2_ONLY mode if requested */
reg = cdns_ti_readl(data, USBSS_W1);
data->usb2_only = device_property_read_bool(dev, "ti,usb2-only");
if (data->usb2_only)
reg |= USBSS_W1_USB2_ONLY;
/* set default modestrap */
reg |= USBSS_W1_MODESTRAP_SEL;
reg &= ~USBSS_W1_MODESTRAP_MASK;
reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT;
cdns_ti_writel(data, USBSS_W1, reg);
/* de-assert RESET */
reg |= USBSS_W1_PWRUP_RST;
cdns_ti_writel(data, USBSS_W1, reg);
error = of_platform_populate(node, NULL, NULL, dev);
if (error) {
dev_err(dev, "failed to create children: %d\n", error);
goto err;
}
return 0;
err:
pm_runtime_put_sync(data->dev);
err_get:
pm_runtime_disable(data->dev);
return error;
}
static int cdns_ti_remove_core(struct device *dev, void *c)
{
struct platform_device *pdev = to_platform_device(dev);
platform_device_unregister(pdev);
return 0;
}
static int cdns_ti_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
device_for_each_child(dev, NULL, cdns_ti_remove_core);
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
platform_set_drvdata(pdev, NULL);
return 0;
}
static const struct of_device_id cdns_ti_of_match[] = {
{ .compatible = "ti,j721e-usb", },
{},
};
MODULE_DEVICE_TABLE(of, cdns_ti_of_match);
static struct platform_driver cdns_ti_driver = {
.probe = cdns_ti_probe,
.remove = cdns_ti_remove,
.driver = {
.name = "cdns3-ti",
.of_match_table = cdns_ti_of_match,
},
};
module_platform_driver(cdns_ti_driver);
MODULE_ALIAS("platform:cdns3-ti");
MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Cadence USB3 TI Glue Layer");

View File

@ -274,11 +274,14 @@ static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event)
switch (event) {
case CI_HDRC_IMX_HSIC_ACTIVE_EVENT:
ret = pinctrl_select_state(data->pinctrl,
data->pinctrl_hsic_active);
if (ret)
dev_err(dev, "hsic_active select failed, err=%d\n",
ret);
if (data->pinctrl) {
ret = pinctrl_select_state(data->pinctrl,
data->pinctrl_hsic_active);
if (ret)
dev_err(dev,
"hsic_active select failed, err=%d\n",
ret);
}
break;
case CI_HDRC_IMX_HSIC_SUSPEND_EVENT:
ret = imx_usbmisc_hsic_set_connect(data->usbmisc_data);
@ -306,7 +309,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct pinctrl_state *pinctrl_hsic_idle;
of_id = of_match_device(ci_hdrc_imx_dt_ids, dev);
if (!of_id)
@ -330,12 +332,42 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
pdata.flags |= CI_HDRC_IMX_IS_HSIC;
data->usbmisc_data->hsic = 1;
data->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(data->pinctrl)) {
dev_err(dev, "pinctrl get failed, err=%ld\n",
if (PTR_ERR(data->pinctrl) == -ENODEV)
data->pinctrl = NULL;
else if (IS_ERR(data->pinctrl)) {
if (PTR_ERR(data->pinctrl) != -EPROBE_DEFER)
dev_err(dev, "pinctrl get failed, err=%ld\n",
PTR_ERR(data->pinctrl));
return PTR_ERR(data->pinctrl);
}
data->hsic_pad_regulator =
devm_regulator_get_optional(dev, "hsic");
if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) {
/* no pad regualator is needed */
data->hsic_pad_regulator = NULL;
} else if (IS_ERR(data->hsic_pad_regulator)) {
if (PTR_ERR(data->hsic_pad_regulator) != -EPROBE_DEFER)
dev_err(dev,
"Get HSIC pad regulator error: %ld\n",
PTR_ERR(data->hsic_pad_regulator));
return PTR_ERR(data->hsic_pad_regulator);
}
if (data->hsic_pad_regulator) {
ret = regulator_enable(data->hsic_pad_regulator);
if (ret) {
dev_err(dev,
"Failed to enable HSIC pad regulator\n");
return ret;
}
}
}
/* HSIC pinctrl handling */
if (data->pinctrl) {
struct pinctrl_state *pinctrl_hsic_idle;
pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle");
if (IS_ERR(pinctrl_hsic_idle)) {
dev_err(dev,
@ -358,27 +390,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
PTR_ERR(data->pinctrl_hsic_active));
return PTR_ERR(data->pinctrl_hsic_active);
}
data->hsic_pad_regulator = devm_regulator_get(dev, "hsic");
if (PTR_ERR(data->hsic_pad_regulator) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} else if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) {
/* no pad regualator is needed */
data->hsic_pad_regulator = NULL;
} else if (IS_ERR(data->hsic_pad_regulator)) {
dev_err(dev, "Get HSIC pad regulator error: %ld\n",
PTR_ERR(data->hsic_pad_regulator));
return PTR_ERR(data->hsic_pad_regulator);
}
if (data->hsic_pad_regulator) {
ret = regulator_enable(data->hsic_pad_regulator);
if (ret) {
dev_err(dev,
"Failed to enable HSIC pad regulator\n");
return ret;
}
}
}
if (pdata.flags & CI_HDRC_PMQOS)
@ -433,6 +444,16 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
goto err_clk;
}
if (data->usbmisc_data) {
if (!IS_ERR(pdata.id_extcon.edev) ||
of_property_read_bool(np, "usb-role-switch"))
data->usbmisc_data->ext_id = 1;
if (!IS_ERR(pdata.vbus_extcon.edev) ||
of_property_read_bool(np, "usb-role-switch"))
data->usbmisc_data->ext_vbus = 1;
}
ret = imx_usbmisc_init_post(data->usbmisc_data);
if (ret) {
dev_err(dev, "usbmisc post failed, ret=%d\n", ret);

View File

@ -22,6 +22,8 @@ struct imx_usbmisc_data {
unsigned int evdo:1; /* set external vbus divider option */
unsigned int ulpi:1; /* connected to an ULPI phy */
unsigned int hsic:1; /* HSIC controlller */
unsigned int ext_id:1; /* ID from exteranl event */
unsigned int ext_vbus:1; /* Vbus from exteranl event */
};
int imx_usbmisc_init(struct imx_usbmisc_data *data);

View File

@ -24,35 +24,23 @@ struct tegra_udc_soc_info {
unsigned long flags;
};
static const struct tegra_udc_soc_info tegra20_udc_soc_info = {
.flags = CI_HDRC_REQUIRES_ALIGNED_DMA,
};
static const struct tegra_udc_soc_info tegra30_udc_soc_info = {
.flags = CI_HDRC_REQUIRES_ALIGNED_DMA,
};
static const struct tegra_udc_soc_info tegra114_udc_soc_info = {
.flags = CI_HDRC_REQUIRES_ALIGNED_DMA,
};
static const struct tegra_udc_soc_info tegra124_udc_soc_info = {
static const struct tegra_udc_soc_info tegra_udc_soc_info = {
.flags = CI_HDRC_REQUIRES_ALIGNED_DMA,
};
static const struct of_device_id tegra_udc_of_match[] = {
{
.compatible = "nvidia,tegra20-udc",
.data = &tegra20_udc_soc_info,
.data = &tegra_udc_soc_info,
}, {
.compatible = "nvidia,tegra30-udc",
.data = &tegra30_udc_soc_info,
.data = &tegra_udc_soc_info,
}, {
.compatible = "nvidia,tegra114-udc",
.data = &tegra114_udc_soc_info,
.data = &tegra_udc_soc_info,
}, {
.compatible = "nvidia,tegra124-udc",
.data = &tegra124_udc_soc_info,
.data = &tegra_udc_soc_info,
}, {
/* sentinel */
}

View File

@ -683,7 +683,7 @@ static int ci_get_platdata(struct device *dev,
if (platdata->dr_mode != USB_DR_MODE_PERIPHERAL) {
/* Get the vbus regulator */
platdata->reg_vbus = devm_regulator_get(dev, "vbus");
platdata->reg_vbus = devm_regulator_get_optional(dev, "vbus");
if (PTR_ERR(platdata->reg_vbus) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} else if (PTR_ERR(platdata->reg_vbus) == -ENODEV) {

View File

@ -342,7 +342,7 @@ DEFINE_SHOW_ATTRIBUTE(ci_registers);
*/
void dbg_create_files(struct ci_hdrc *ci)
{
ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL);
ci->debugfs = debugfs_create_dir(dev_name(ci->dev), usb_debug_root);
debugfs_create_file("device", S_IRUGO, ci->debugfs, ci,
&ci_device_fops);

View File

@ -1524,42 +1524,53 @@ static const struct usb_ep_ops usb_ep_ops = {
/******************************************************************************
* GADGET block
*****************************************************************************/
/**
* ci_hdrc_gadget_connect: caller makes sure gadget driver is binded
*/
static void ci_hdrc_gadget_connect(struct usb_gadget *_gadget, int is_active)
{
struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
unsigned long flags;
if (is_active) {
pm_runtime_get_sync(&_gadget->dev);
hw_device_reset(ci);
spin_lock_irqsave(&ci->lock, flags);
if (ci->driver) {
hw_device_state(ci, ci->ep0out->qh.dma);
usb_gadget_set_state(_gadget, USB_STATE_POWERED);
usb_udc_vbus_handler(_gadget, true);
}
spin_unlock_irqrestore(&ci->lock, flags);
} else {
usb_udc_vbus_handler(_gadget, false);
if (ci->driver)
ci->driver->disconnect(&ci->gadget);
hw_device_state(ci, 0);
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_STOPPED_EVENT);
_gadget_stop_activity(&ci->gadget);
pm_runtime_put_sync(&_gadget->dev);
usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED);
}
}
static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
{
struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
unsigned long flags;
int gadget_ready = 0;
spin_lock_irqsave(&ci->lock, flags);
ci->vbus_active = is_active;
if (ci->driver)
gadget_ready = 1;
spin_unlock_irqrestore(&ci->lock, flags);
if (ci->usb_phy)
usb_phy_set_charger_state(ci->usb_phy, is_active ?
USB_CHARGER_PRESENT : USB_CHARGER_ABSENT);
if (gadget_ready) {
if (is_active) {
pm_runtime_get_sync(&_gadget->dev);
hw_device_reset(ci);
hw_device_state(ci, ci->ep0out->qh.dma);
usb_gadget_set_state(_gadget, USB_STATE_POWERED);
usb_udc_vbus_handler(_gadget, true);
} else {
usb_udc_vbus_handler(_gadget, false);
if (ci->driver)
ci->driver->disconnect(&ci->gadget);
hw_device_state(ci, 0);
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_STOPPED_EVENT);
_gadget_stop_activity(&ci->gadget);
pm_runtime_put_sync(&_gadget->dev);
usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED);
}
}
if (ci->driver)
ci_hdrc_gadget_connect(_gadget, is_active);
return 0;
}
@ -1612,7 +1623,7 @@ static int ci_udc_selfpowered(struct usb_gadget *_gadget, int is_on)
}
/* Change Data+ pullup status
* this func is used by usb_gadget_connect/disconnet
* this func is used by usb_gadget_connect/disconnect
*/
static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on)
{
@ -1785,18 +1796,10 @@ static int ci_udc_start(struct usb_gadget *gadget,
return retval;
}
pm_runtime_get_sync(&ci->gadget.dev);
if (ci->vbus_active) {
hw_device_reset(ci);
} else {
if (ci->vbus_active)
ci_hdrc_gadget_connect(gadget, 1);
else
usb_udc_vbus_handler(&ci->gadget, false);
pm_runtime_put_sync(&ci->gadget.dev);
return retval;
}
retval = hw_device_state(ci, ci->ep0out->qh.dma);
if (retval)
pm_runtime_put_sync(&ci->gadget.dev);
return retval;
}
@ -1826,6 +1829,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
unsigned long flags;
spin_lock_irqsave(&ci->lock, flags);
ci->driver = NULL;
if (ci->vbus_active) {
hw_device_state(ci, 0);
@ -1838,7 +1842,6 @@ static int ci_udc_stop(struct usb_gadget *gadget)
pm_runtime_put(&ci->gadget.dev);
}
ci->driver = NULL;
spin_unlock_irqrestore(&ci->lock, flags);
ci_udc_stop_for_otg_fsm(ci);

View File

@ -100,6 +100,9 @@
#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2)
#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3)
#define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
MX6_BM_ID_WAKEUP)
struct usbmisc_ops {
/* It's called once when probe a usb device */
int (*init)(struct imx_usbmisc_data *data);
@ -330,14 +333,25 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
return 0;
}
static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data)
{
u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS;
if (data->ext_id)
wakeup_setting &= ~MX6_BM_ID_WAKEUP;
if (data->ext_vbus)
wakeup_setting &= ~MX6_BM_VBUS_WAKEUP;
return wakeup_setting;
}
static int usbmisc_imx6q_set_wakeup
(struct imx_usbmisc_data *data, bool enabled)
{
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
unsigned long flags;
u32 val;
u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
int ret = 0;
if (data->index > 3)
@ -346,11 +360,12 @@ static int usbmisc_imx6q_set_wakeup
spin_lock_irqsave(&usbmisc->lock, flags);
val = readl(usbmisc->base + data->index * 4);
if (enabled) {
val |= wakeup_setting;
val &= ~MX6_USB_OTG_WAKEUP_BITS;
val |= usbmisc_wakeup_setting(data);
} else {
if (val & MX6_BM_WAKEUP_INTR)
pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
val &= ~wakeup_setting;
val &= ~MX6_USB_OTG_WAKEUP_BITS;
}
writel(val, usbmisc->base + data->index * 4);
spin_unlock_irqrestore(&usbmisc->lock, flags);
@ -547,17 +562,17 @@ static int usbmisc_imx7d_set_wakeup
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
unsigned long flags;
u32 val;
u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
spin_lock_irqsave(&usbmisc->lock, flags);
val = readl(usbmisc->base);
if (enabled) {
writel(val | wakeup_setting, usbmisc->base);
val &= ~MX6_USB_OTG_WAKEUP_BITS;
val |= usbmisc_wakeup_setting(data);
writel(val, usbmisc->base);
} else {
if (val & MX6_BM_WAKEUP_INTR)
dev_dbg(data->dev, "wakeup int\n");
writel(val & ~wakeup_setting, usbmisc->base);
writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base);
}
spin_unlock_irqrestore(&usbmisc->lock, flags);

View File

@ -805,10 +805,10 @@ int usb_get_configuration(struct usb_device *dev)
{
struct device *ddev = &dev->dev;
int ncfg = dev->descriptor.bNumConfigurations;
int result = -ENOMEM;
unsigned int cfgno, length;
unsigned char *bigbuffer;
struct usb_config_descriptor *desc;
int result;
if (ncfg > USB_MAXCONFIG) {
dev_warn(ddev, "too many configurations: %d, "
@ -824,16 +824,16 @@ int usb_get_configuration(struct usb_device *dev)
length = ncfg * sizeof(struct usb_host_config);
dev->config = kzalloc(length, GFP_KERNEL);
if (!dev->config)
goto err2;
return -ENOMEM;
length = ncfg * sizeof(char *);
dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
if (!dev->rawdescriptors)
goto err2;
return -ENOMEM;
desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
if (!desc)
goto err2;
return -ENOMEM;
for (cfgno = 0; cfgno < ncfg; cfgno++) {
/* We grab just the first descriptor so we know how long
@ -895,9 +895,7 @@ int usb_get_configuration(struct usb_device *dev)
err:
kfree(desc);
dev->descriptor.bNumConfigurations = cfgno;
err2:
if (result == -ENOMEM)
dev_err(ddev, "out of memory\n");
return result;
}

View File

@ -764,8 +764,15 @@ static int claimintf(struct usb_dev_state *ps, unsigned int ifnum)
intf = usb_ifnum_to_if(dev, ifnum);
if (!intf)
err = -ENOENT;
else
else {
unsigned int old_suppress;
/* suppress uevents while claiming interface */
old_suppress = dev_get_uevent_suppress(&intf->dev);
dev_set_uevent_suppress(&intf->dev, 1);
err = usb_driver_claim_interface(&usbfs_driver, intf, ps);
dev_set_uevent_suppress(&intf->dev, old_suppress);
}
if (err == 0)
set_bit(ifnum, &ps->ifclaimed);
return err;
@ -785,7 +792,13 @@ static int releaseintf(struct usb_dev_state *ps, unsigned int ifnum)
if (!intf)
err = -ENOENT;
else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) {
unsigned int old_suppress;
/* suppress uevents while releasing interface */
old_suppress = dev_get_uevent_suppress(&intf->dev);
dev_set_uevent_suppress(&intf->dev, 1);
usb_driver_release_interface(&usbfs_driver, intf);
dev_set_uevent_suppress(&intf->dev, old_suppress);
err = 0;
}
return err;
@ -1550,10 +1563,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
uurb->buffer_length = le16_to_cpu(dr->wLength);
uurb->buffer += 8;
if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) {
is_in = 1;
is_in = true;
uurb->endpoint |= USB_DIR_IN;
} else {
is_in = 0;
is_in = false;
uurb->endpoint &= ~USB_DIR_IN;
}
if (is_in)

View File

@ -4930,6 +4930,91 @@ hub_power_remaining(struct usb_hub *hub)
return remaining;
}
static int descriptors_changed(struct usb_device *udev,
struct usb_device_descriptor *old_device_descriptor,
struct usb_host_bos *old_bos)
{
int changed = 0;
unsigned index;
unsigned serial_len = 0;
unsigned len;
unsigned old_length;
int length;
char *buf;
if (memcmp(&udev->descriptor, old_device_descriptor,
sizeof(*old_device_descriptor)) != 0)
return 1;
if ((old_bos && !udev->bos) || (!old_bos && udev->bos))
return 1;
if (udev->bos) {
len = le16_to_cpu(udev->bos->desc->wTotalLength);
if (len != le16_to_cpu(old_bos->desc->wTotalLength))
return 1;
if (memcmp(udev->bos->desc, old_bos->desc, len))
return 1;
}
/* Since the idVendor, idProduct, and bcdDevice values in the
* device descriptor haven't changed, we will assume the
* Manufacturer and Product strings haven't changed either.
* But the SerialNumber string could be different (e.g., a
* different flash card of the same brand).
*/
if (udev->serial)
serial_len = strlen(udev->serial) + 1;
len = serial_len;
for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
len = max(len, old_length);
}
buf = kmalloc(len, GFP_NOIO);
if (!buf)
/* assume the worst */
return 1;
for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf,
old_length);
if (length != old_length) {
dev_dbg(&udev->dev, "config index %d, error %d\n",
index, length);
changed = 1;
break;
}
if (memcmp(buf, udev->rawdescriptors[index], old_length)
!= 0) {
dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
index,
((struct usb_config_descriptor *) buf)->
bConfigurationValue);
changed = 1;
break;
}
}
if (!changed && serial_len) {
length = usb_string(udev, udev->descriptor.iSerialNumber,
buf, serial_len);
if (length + 1 != serial_len) {
dev_dbg(&udev->dev, "serial string error %d\n",
length);
changed = 1;
} else if (memcmp(buf, udev->serial, length) != 0) {
dev_dbg(&udev->dev, "serial string changed\n");
changed = 1;
}
}
kfree(buf);
return changed;
}
static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
u16 portchange)
{
@ -5167,7 +5252,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
{
struct usb_port *port_dev = hub->ports[port1 - 1];
struct usb_device *udev = port_dev->child;
struct usb_device_descriptor descriptor;
int status = -ENODEV;
int retval;
dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus,
portchange, portspeed(hub, portstatus));
@ -5188,7 +5275,30 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
udev->state != USB_STATE_NOTATTACHED) {
if (portstatus & USB_PORT_STAT_ENABLE) {
status = 0; /* Nothing to do */
/*
* USB-3 connections are initialized automatically by
* the hostcontroller hardware. Therefore check for
* changed device descriptors before resuscitating the
* device.
*/
descriptor = udev->descriptor;
retval = usb_get_device_descriptor(udev,
sizeof(udev->descriptor));
if (retval < 0) {
dev_dbg(&udev->dev,
"can't read device descriptor %d\n",
retval);
} else {
if (descriptors_changed(udev, &descriptor,
udev->bos)) {
dev_dbg(&udev->dev,
"device descriptor has changed\n");
/* for disconnect() calls */
udev->descriptor = descriptor;
} else {
status = 0; /* Nothing to do */
}
}
#ifdef CONFIG_PM
} else if (udev->state == USB_STATE_SUSPENDED &&
udev->persist_enabled) {
@ -5550,90 +5660,6 @@ void usb_hub_cleanup(void)
usb_deregister(&hub_driver);
} /* usb_hub_cleanup() */
static int descriptors_changed(struct usb_device *udev,
struct usb_device_descriptor *old_device_descriptor,
struct usb_host_bos *old_bos)
{
int changed = 0;
unsigned index;
unsigned serial_len = 0;
unsigned len;
unsigned old_length;
int length;
char *buf;
if (memcmp(&udev->descriptor, old_device_descriptor,
sizeof(*old_device_descriptor)) != 0)
return 1;
if ((old_bos && !udev->bos) || (!old_bos && udev->bos))
return 1;
if (udev->bos) {
len = le16_to_cpu(udev->bos->desc->wTotalLength);
if (len != le16_to_cpu(old_bos->desc->wTotalLength))
return 1;
if (memcmp(udev->bos->desc, old_bos->desc, len))
return 1;
}
/* Since the idVendor, idProduct, and bcdDevice values in the
* device descriptor haven't changed, we will assume the
* Manufacturer and Product strings haven't changed either.
* But the SerialNumber string could be different (e.g., a
* different flash card of the same brand).
*/
if (udev->serial)
serial_len = strlen(udev->serial) + 1;
len = serial_len;
for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
len = max(len, old_length);
}
buf = kmalloc(len, GFP_NOIO);
if (!buf)
/* assume the worst */
return 1;
for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf,
old_length);
if (length != old_length) {
dev_dbg(&udev->dev, "config index %d, error %d\n",
index, length);
changed = 1;
break;
}
if (memcmp(buf, udev->rawdescriptors[index], old_length)
!= 0) {
dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
index,
((struct usb_config_descriptor *) buf)->
bConfigurationValue);
changed = 1;
break;
}
}
if (!changed && serial_len) {
length = usb_string(udev, udev->descriptor.iSerialNumber,
buf, serial_len);
if (length + 1 != serial_len) {
dev_dbg(&udev->dev, "serial string error %d\n",
length);
changed = 1;
} else if (memcmp(buf, udev->serial, length) != 0) {
dev_dbg(&udev->dev, "serial string changed\n");
changed = 1;
}
}
kfree(buf);
return changed;
}
/**
* usb_reset_and_verify_device - perform a USB port reset to reinitialize a device
* @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
@ -5814,7 +5840,7 @@ re_enumerate_no_bos:
/**
* usb_reset_device - warn interface drivers and perform a USB port reset
* @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
* @udev: device to reset (not in NOTATTACHED state)
*
* Warns all drivers bound to registered interfaces (using their pre_reset
* method), performs the port reset, and then lets the drivers know that
@ -5842,8 +5868,7 @@ int usb_reset_device(struct usb_device *udev)
struct usb_host_config *config = udev->actconfig;
struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
if (udev->state == USB_STATE_NOTATTACHED ||
udev->state == USB_STATE_SUSPENDED) {
if (udev->state == USB_STATE_NOTATTACHED) {
dev_dbg(&udev->dev, "device reset not allowed in state %d\n",
udev->state);
return -EINVAL;

View File

@ -524,7 +524,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
greset |= GRSTCTL_CSFTRST;
dwc2_writel(hsotg, greset, GRSTCTL);
if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_CSFTRST, 50)) {
if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_CSFTRST, 10000)) {
dev_warn(hsotg->dev, "%s: HANG! Soft Reset timeout GRSTCTL GRSTCTL_CSFTRST\n",
__func__);
return -EBUSY;

View File

@ -134,7 +134,7 @@ struct dwc2_hsotg_req;
* @target_frame: Targeted frame num to setup next ISOC transfer
* @frame_overrun: Indicates SOF number overrun in DSTS
*
* This is the driver's state for each registered enpoint, allowing it
* This is the driver's state for each registered endpoint, allowing it
* to keep track of transactions that need doing. Each endpoint has a
* lock to protect the state, to try and avoid using an overall lock
* for the host controller as much as possible.

View File

@ -770,7 +770,7 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
int ret;
struct dentry *root;
root = debugfs_create_dir(dev_name(hsotg->dev), NULL);
root = debugfs_create_dir(dev_name(hsotg->dev), usb_debug_root);
hsotg->debug_root = root;
debugfs_create_file("params", 0444, root, hsotg, &params_fops);

View File

@ -97,24 +97,24 @@ config USB_DWC3_KEYSTONE
Say 'Y' or 'M' here if you have one such device
config USB_DWC3_MESON_G12A
tristate "Amlogic Meson G12A Platforms"
depends on OF && COMMON_CLK
depends on ARCH_MESON || COMPILE_TEST
default USB_DWC3
select USB_ROLE_SWITCH
tristate "Amlogic Meson G12A Platforms"
depends on OF && COMMON_CLK
depends on ARCH_MESON || COMPILE_TEST
default USB_DWC3
select USB_ROLE_SWITCH
select REGMAP_MMIO
help
Support USB2/3 functionality in Amlogic G12A platforms.
Say 'Y' or 'M' if you have one such device.
help
Support USB2/3 functionality in Amlogic G12A platforms.
Say 'Y' or 'M' if you have one such device.
config USB_DWC3_OF_SIMPLE
tristate "Generic OF Simple Glue Layer"
depends on OF && COMMON_CLK
default USB_DWC3
help
Support USB2/3 functionality in simple SoC integrations.
Currently supports Xilinx and Qualcomm DWC USB3 IP.
Say 'Y' or 'M' if you have one such device.
tristate "Generic OF Simple Glue Layer"
depends on OF && COMMON_CLK
default USB_DWC3
help
Support USB2/3 functionality in simple SoC integrations.
Currently supports Xilinx and Qualcomm DWC USB3 IP.
Say 'Y' or 'M' if you have one such device.
config USB_DWC3_ST
tristate "STMicroelectronics Platforms"

View File

@ -566,8 +566,11 @@ static int dwc3_core_ulpi_init(struct dwc3 *dwc)
*/
static int dwc3_phy_setup(struct dwc3 *dwc)
{
unsigned int hw_mode;
u32 reg;
hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
/*
@ -585,6 +588,14 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
if (dwc->revision > DWC3_REVISION_194A)
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
/*
* For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after
* power-on reset, and it can be set after core initialization, which is
* after device soft-reset during initialization.
*/
if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
if (dwc->u2ss_inp3_quirk)
reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
@ -668,6 +679,14 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
if (dwc->revision > DWC3_REVISION_194A)
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
/*
* For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after
* power-on reset, and it can be set after core initialization, which is
* after device soft-reset during initialization.
*/
if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
if (dwc->dis_u2_susphy_quirk)
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
@ -902,9 +921,12 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
*/
static int dwc3_core_init(struct dwc3 *dwc)
{
unsigned int hw_mode;
u32 reg;
int ret;
hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
/*
* Write Linux Version Code to our GUID register so it's easy to figure
* out which kernel version a bug was found.
@ -940,6 +962,21 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (ret)
goto err0a;
if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD &&
dwc->revision > DWC3_REVISION_194A) {
if (!dwc->dis_u3_susphy_quirk) {
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
}
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);
}
}
dwc3_core_setup_global_control(dwc);
dwc3_core_num_eps(dwc);

View File

@ -112,7 +112,7 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state)
case DWC3_LINK_STATE_RESUME:
return "Resume";
default:
return "UNKNOWN link state\n";
return "UNKNOWN link state";
}
}
@ -141,7 +141,7 @@ dwc3_gadget_hs_link_string(enum dwc3_link_state link_state)
case DWC3_LINK_STATE_RESUME:
return "Resume";
default:
return "UNKNOWN link state\n";
return "UNKNOWN link state";
}
}

View File

@ -916,7 +916,7 @@ void dwc3_debugfs_init(struct dwc3 *dwc)
dwc->regset->nregs = ARRAY_SIZE(dwc3_regs);
dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START;
root = debugfs_create_dir(dev_name(dwc->dev), NULL);
root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root);
dwc->root = root;
debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset);

View File

@ -110,12 +110,9 @@ err_resetc_put:
return ret;
}
static int dwc3_of_simple_remove(struct platform_device *pdev)
static void __dwc3_of_simple_teardown(struct dwc3_of_simple *simple)
{
struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
of_platform_depopulate(dev);
of_platform_depopulate(simple->dev);
clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
clk_bulk_put_all(simple->num_clocks, simple->clks);
@ -126,13 +123,27 @@ static int dwc3_of_simple_remove(struct platform_device *pdev)
reset_control_put(simple->resets);
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
pm_runtime_set_suspended(dev);
pm_runtime_disable(simple->dev);
pm_runtime_put_noidle(simple->dev);
pm_runtime_set_suspended(simple->dev);
}
static int dwc3_of_simple_remove(struct platform_device *pdev)
{
struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
__dwc3_of_simple_teardown(simple);
return 0;
}
static void dwc3_of_simple_shutdown(struct platform_device *pdev)
{
struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
__dwc3_of_simple_teardown(simple);
}
static int __maybe_unused dwc3_of_simple_runtime_suspend(struct device *dev)
{
struct dwc3_of_simple *simple = dev_get_drvdata(dev);
@ -190,6 +201,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
static struct platform_driver dwc3_of_simple_driver = {
.probe = dwc3_of_simple_probe,
.remove = dwc3_of_simple_remove,
.shutdown = dwc3_of_simple_shutdown,
.driver = {
.name = "dwc3-of-simple",
.of_match_table = of_dwc3_simple_match,

View File

@ -794,9 +794,9 @@ static int set_config(struct usb_composite_dev *cdev,
result = 0;
}
INFO(cdev, "%s config #%d: %s\n",
usb_speed_string(gadget->speed),
number, c ? c->label : "unconfigured");
DBG(cdev, "%s config #%d: %s\n",
usb_speed_string(gadget->speed),
number, c ? c->label : "unconfigured");
if (!c)
goto done;

View File

@ -1544,6 +1544,7 @@ static struct config_group *gadgets_make(
gi->composite.resume = NULL;
gi->composite.max_speed = USB_SPEED_SUPER;
spin_lock_init(&gi->spinlock);
mutex_init(&gi->lock);
INIT_LIST_HEAD(&gi->string_list);
INIT_LIST_HEAD(&gi->available_func);

View File

@ -771,6 +771,24 @@ static struct configfs_item_operations acm_item_ops = {
.release = acm_attr_release,
};
#ifdef CONFIG_U_SERIAL_CONSOLE
static ssize_t f_acm_console_store(struct config_item *item,
const char *page, size_t count)
{
return gserial_set_console(to_f_serial_opts(item)->port_num,
page, count);
}
static ssize_t f_acm_console_show(struct config_item *item, char *page)
{
return gserial_get_console(to_f_serial_opts(item)->port_num, page);
}
CONFIGFS_ATTR(f_acm_, console);
#endif /* CONFIG_U_SERIAL_CONSOLE */
static ssize_t f_acm_port_num_show(struct config_item *item, char *page)
{
return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
@ -779,6 +797,9 @@ static ssize_t f_acm_port_num_show(struct config_item *item, char *page)
CONFIGFS_ATTR_RO(f_acm_, port_num);
static struct configfs_attribute *acm_attrs[] = {
#ifdef CONFIG_U_SERIAL_CONSOLE
&f_acm_attr_console,
#endif
&f_acm_attr_port_num,
NULL,
};

View File

@ -432,7 +432,7 @@ static struct usb_function_instance *obex_alloc_inst(void)
return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = obex_free_inst;
ret = gserial_alloc_line(&opts->port_num);
ret = gserial_alloc_line_no_console(&opts->port_num);
if (ret) {
kfree(opts);
return ERR_PTR(ret);

View File

@ -266,6 +266,24 @@ static struct configfs_item_operations serial_item_ops = {
.release = serial_attr_release,
};
#ifdef CONFIG_U_SERIAL_CONSOLE
static ssize_t f_serial_console_store(struct config_item *item,
const char *page, size_t count)
{
return gserial_set_console(to_f_serial_opts(item)->port_num,
page, count);
}
static ssize_t f_serial_console_show(struct config_item *item, char *page)
{
return gserial_get_console(to_f_serial_opts(item)->port_num, page);
}
CONFIGFS_ATTR(f_serial_, console);
#endif /* CONFIG_U_SERIAL_CONSOLE */
static ssize_t f_serial_port_num_show(struct config_item *item, char *page)
{
return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
@ -274,6 +292,9 @@ static ssize_t f_serial_port_num_show(struct config_item *item, char *page)
CONFIGFS_ATTR_RO(f_serial_, port_num);
static struct configfs_attribute *acm_attrs[] = {
#ifdef CONFIG_U_SERIAL_CONSOLE
&f_serial_attr_console,
#endif
&f_serial_attr_port_num,
NULL,
};

View File

@ -846,7 +846,7 @@ static void uasp_set_alt(struct f_uas *fu)
fu->flags = USBG_IS_UAS;
if (gadget->speed == USB_SPEED_SUPER)
if (gadget->speed >= USB_SPEED_SUPER)
fu->flags |= USBG_USE_STREAMS;
config_ep_by_speed(gadget, f, fu->ep_in);
@ -2093,6 +2093,16 @@ static void tcm_delayed_set_alt(struct work_struct *wq)
usb_composite_setup_continue(fu->function.config->cdev);
}
static int tcm_get_alt(struct usb_function *f, unsigned intf)
{
if (intf == bot_intf_desc.bInterfaceNumber)
return USB_G_ALT_INT_BBB;
if (intf == uasp_intf_desc.bInterfaceNumber)
return USB_G_ALT_INT_UAS;
return -EOPNOTSUPP;
}
static int tcm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct f_uas *fu = to_f_uas(f);
@ -2300,6 +2310,7 @@ static struct usb_function *tcm_alloc(struct usb_function_instance *fi)
fu->function.bind = tcm_bind;
fu->function.unbind = tcm_unbind;
fu->function.set_alt = tcm_set_alt;
fu->function.get_alt = tcm_get_alt;
fu->function.setup = tcm_setup;
fu->function.disable = tcm_disable;
fu->function.free_func = tcm_free;

View File

@ -82,14 +82,13 @@
#define GS_CONSOLE_BUF_SIZE 8192
/* console info */
struct gscons_info {
struct gs_port *port;
struct task_struct *console_thread;
struct kfifo con_buf;
/* protect the buf and busy flag */
spinlock_t con_lock;
int req_busy;
struct usb_request *console_req;
struct gs_console {
struct console console;
struct work_struct work;
spinlock_t lock;
struct usb_request *req;
struct kfifo buf;
size_t missed;
};
/*
@ -101,8 +100,10 @@ struct gs_port {
spinlock_t port_lock; /* guard port_* access */
struct gserial *port_usb;
#ifdef CONFIG_U_SERIAL_CONSOLE
struct gs_console *console;
#endif
bool openclose; /* open/close in progress */
u8 port_num;
struct list_head read_pool;
@ -586,82 +587,45 @@ static int gs_open(struct tty_struct *tty, struct file *file)
{
int port_num = tty->index;
struct gs_port *port;
int status;
int status = 0;
do {
mutex_lock(&ports[port_num].lock);
port = ports[port_num].port;
if (!port)
status = -ENODEV;
else {
spin_lock_irq(&port->port_lock);
mutex_lock(&ports[port_num].lock);
port = ports[port_num].port;
if (!port) {
status = -ENODEV;
goto out;
}
/* already open? Great. */
if (port->port.count) {
status = 0;
port->port.count++;
/* currently opening/closing? wait ... */
} else if (port->openclose) {
status = -EBUSY;
/* ... else we do the work */
} else {
status = -EAGAIN;
port->openclose = true;
}
spin_unlock_irq(&port->port_lock);
}
mutex_unlock(&ports[port_num].lock);
switch (status) {
default:
/* fully handled */
return status;
case -EAGAIN:
/* must do the work */
break;
case -EBUSY:
/* wait for EAGAIN task to finish */
msleep(1);
/* REVISIT could have a waitchannel here, if
* concurrent open performance is important
*/
break;
}
} while (status != -EAGAIN);
/* Do the "real open" */
spin_lock_irq(&port->port_lock);
/* allocate circular buffer on first open */
if (!kfifo_initialized(&port->port_write_buf)) {
spin_unlock_irq(&port->port_lock);
/*
* portmaster's mutex still protects from simultaneous open(),
* and close() can't happen, yet.
*/
status = kfifo_alloc(&port->port_write_buf,
WRITE_BUF_SIZE, GFP_KERNEL);
spin_lock_irq(&port->port_lock);
if (status) {
pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n",
port->port_num, tty, file);
port->openclose = false;
goto exit_unlock_port;
port_num, tty, file);
goto out;
}
spin_lock_irq(&port->port_lock);
}
/* REVISIT if REMOVED (ports[].port NULL), abort the open
* to let rmmod work faster (but this way isn't wrong).
*/
/* REVISIT maybe wait for "carrier detect" */
/* already open? Great. */
if (port->port.count++)
goto exit_unlock_port;
tty->driver_data = port;
port->port.tty = tty;
port->port.count = 1;
port->openclose = false;
/* if connected, start the I/O stream */
if (port->port_usb) {
struct gserial *gser = port->port_usb;
@ -675,20 +639,21 @@ static int gs_open(struct tty_struct *tty, struct file *file)
pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
status = 0;
exit_unlock_port:
spin_unlock_irq(&port->port_lock);
out:
mutex_unlock(&ports[port_num].lock);
return status;
}
static int gs_writes_finished(struct gs_port *p)
static int gs_close_flush_done(struct gs_port *p)
{
int cond;
/* return true on disconnect or empty buffer */
/* return true on disconnect or empty buffer or if raced with open() */
spin_lock_irq(&p->port_lock);
cond = (p->port_usb == NULL) || !kfifo_len(&p->port_write_buf);
cond = p->port_usb == NULL || !kfifo_len(&p->port_write_buf) ||
p->port.count > 1;
spin_unlock_irq(&p->port_lock);
return cond;
@ -702,6 +667,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
spin_lock_irq(&port->port_lock);
if (port->port.count != 1) {
raced_with_open:
if (port->port.count == 0)
WARN_ON(1);
else
@ -711,12 +677,6 @@ static void gs_close(struct tty_struct *tty, struct file *file)
pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file);
/* mark port as closing but in use; we can drop port lock
* and sleep if necessary
*/
port->openclose = true;
port->port.count = 0;
gser = port->port_usb;
if (gser && gser->disconnect)
gser->disconnect(gser);
@ -727,9 +687,13 @@ static void gs_close(struct tty_struct *tty, struct file *file)
if (kfifo_len(&port->port_write_buf) > 0 && gser) {
spin_unlock_irq(&port->port_lock);
wait_event_interruptible_timeout(port->drain_wait,
gs_writes_finished(port),
gs_close_flush_done(port),
GS_CLOSE_TIMEOUT * HZ);
spin_lock_irq(&port->port_lock);
if (port->port.count != 1)
goto raced_with_open;
gser = port->port_usb;
}
@ -742,10 +706,9 @@ static void gs_close(struct tty_struct *tty, struct file *file)
else
kfifo_reset(&port->port_write_buf);
port->port.count = 0;
port->port.tty = NULL;
port->openclose = false;
pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
port->port_num, tty, file);
@ -889,36 +852,9 @@ static struct tty_driver *gs_tty_driver;
#ifdef CONFIG_U_SERIAL_CONSOLE
static struct gscons_info gscons_info;
static struct console gserial_cons;
static struct usb_request *gs_request_new(struct usb_ep *ep)
static void gs_console_complete_out(struct usb_ep *ep, struct usb_request *req)
{
struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (!req)
return NULL;
req->buf = kmalloc(ep->maxpacket, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
return NULL;
}
return req;
}
static void gs_request_free(struct usb_request *req, struct usb_ep *ep)
{
if (!req)
return;
kfree(req->buf);
usb_ep_free_request(ep, req);
}
static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
{
struct gscons_info *info = &gscons_info;
struct gs_console *cons = req->context;
switch (req->status) {
default:
@ -927,12 +863,12 @@ static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
/* fall through */
case 0:
/* normal completion */
spin_lock(&info->con_lock);
info->req_busy = 0;
spin_unlock(&info->con_lock);
wake_up_process(info->console_thread);
spin_lock(&cons->lock);
req->length = 0;
schedule_work(&cons->work);
spin_unlock(&cons->lock);
break;
case -ECONNRESET:
case -ESHUTDOWN:
/* disconnect */
pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
@ -940,190 +876,250 @@ static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
}
}
static int gs_console_connect(int port_num)
static void __gs_console_push(struct gs_console *cons)
{
struct gscons_info *info = &gscons_info;
struct gs_port *port;
struct usb_request *req = cons->req;
struct usb_ep *ep;
size_t size;
if (port_num != gserial_cons.index) {
pr_err("%s: port num [%d] is not support console\n",
__func__, port_num);
return -ENXIO;
if (!req)
return; /* disconnected */
if (req->length)
return; /* busy */
ep = cons->console.data;
size = kfifo_out(&cons->buf, req->buf, ep->maxpacket);
if (!size)
return;
if (cons->missed && ep->maxpacket >= 64) {
char buf[64];
size_t len;
len = sprintf(buf, "\n[missed %zu bytes]\n", cons->missed);
kfifo_in(&cons->buf, buf, len);
cons->missed = 0;
}
port = ports[port_num].port;
ep = port->port_usb->in;
if (!info->console_req) {
info->console_req = gs_request_new(ep);
if (!info->console_req)
return -ENOMEM;
info->console_req->complete = gs_complete_out;
}
info->port = port;
spin_lock(&info->con_lock);
info->req_busy = 0;
spin_unlock(&info->con_lock);
pr_vdebug("port[%d] console connect!\n", port_num);
return 0;
req->length = size;
if (usb_ep_queue(ep, req, GFP_ATOMIC))
req->length = 0;
}
static void gs_console_disconnect(struct usb_ep *ep)
static void gs_console_work(struct work_struct *work)
{
struct gscons_info *info = &gscons_info;
struct usb_request *req = info->console_req;
struct gs_console *cons = container_of(work, struct gs_console, work);
gs_request_free(req, ep);
info->console_req = NULL;
}
spin_lock_irq(&cons->lock);
static int gs_console_thread(void *data)
{
struct gscons_info *info = &gscons_info;
struct gs_port *port;
struct usb_request *req;
struct usb_ep *ep;
int xfer, ret, count, size;
__gs_console_push(cons);
do {
port = info->port;
set_current_state(TASK_INTERRUPTIBLE);
if (!port || !port->port_usb
|| !port->port_usb->in || !info->console_req)
goto sched;
req = info->console_req;
ep = port->port_usb->in;
spin_lock_irq(&info->con_lock);
count = kfifo_len(&info->con_buf);
size = ep->maxpacket;
if (count > 0 && !info->req_busy) {
set_current_state(TASK_RUNNING);
if (count < size)
size = count;
xfer = kfifo_out(&info->con_buf, req->buf, size);
req->length = xfer;
spin_unlock(&info->con_lock);
ret = usb_ep_queue(ep, req, GFP_ATOMIC);
spin_lock(&info->con_lock);
if (ret < 0)
info->req_busy = 0;
else
info->req_busy = 1;
spin_unlock_irq(&info->con_lock);
} else {
spin_unlock_irq(&info->con_lock);
sched:
if (kthread_should_stop()) {
set_current_state(TASK_RUNNING);
break;
}
schedule();
}
} while (1);
return 0;
}
static int gs_console_setup(struct console *co, char *options)
{
struct gscons_info *info = &gscons_info;
int status;
info->port = NULL;
info->console_req = NULL;
info->req_busy = 0;
spin_lock_init(&info->con_lock);
status = kfifo_alloc(&info->con_buf, GS_CONSOLE_BUF_SIZE, GFP_KERNEL);
if (status) {
pr_err("%s: allocate console buffer failed\n", __func__);
return status;
}
info->console_thread = kthread_create(gs_console_thread,
co, "gs_console");
if (IS_ERR(info->console_thread)) {
pr_err("%s: cannot create console thread\n", __func__);
kfifo_free(&info->con_buf);
return PTR_ERR(info->console_thread);
}
wake_up_process(info->console_thread);
return 0;
spin_unlock_irq(&cons->lock);
}
static void gs_console_write(struct console *co,
const char *buf, unsigned count)
{
struct gscons_info *info = &gscons_info;
struct gs_console *cons = container_of(co, struct gs_console, console);
unsigned long flags;
size_t n;
spin_lock_irqsave(&info->con_lock, flags);
kfifo_in(&info->con_buf, buf, count);
spin_unlock_irqrestore(&info->con_lock, flags);
spin_lock_irqsave(&cons->lock, flags);
wake_up_process(info->console_thread);
n = kfifo_in(&cons->buf, buf, count);
if (n < count)
cons->missed += count - n;
if (cons->req && !cons->req->length)
schedule_work(&cons->work);
spin_unlock_irqrestore(&cons->lock, flags);
}
static struct tty_driver *gs_console_device(struct console *co, int *index)
{
struct tty_driver **p = (struct tty_driver **)co->data;
if (!*p)
return NULL;
*index = co->index;
return *p;
return gs_tty_driver;
}
static struct console gserial_cons = {
.name = "ttyGS",
.write = gs_console_write,
.device = gs_console_device,
.setup = gs_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &gs_tty_driver,
};
static void gserial_console_init(void)
static int gs_console_connect(struct gs_port *port)
{
register_console(&gserial_cons);
struct gs_console *cons = port->console;
struct usb_request *req;
struct usb_ep *ep;
if (!cons)
return 0;
ep = port->port_usb->in;
req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
if (!req)
return -ENOMEM;
req->complete = gs_console_complete_out;
req->context = cons;
req->length = 0;
spin_lock(&cons->lock);
cons->req = req;
cons->console.data = ep;
spin_unlock(&cons->lock);
pr_debug("ttyGS%d: console connected!\n", port->port_num);
schedule_work(&cons->work);
return 0;
}
static void gserial_console_exit(void)
static void gs_console_disconnect(struct gs_port *port)
{
struct gscons_info *info = &gscons_info;
struct gs_console *cons = port->console;
struct usb_request *req;
struct usb_ep *ep;
unregister_console(&gserial_cons);
if (!IS_ERR_OR_NULL(info->console_thread))
kthread_stop(info->console_thread);
kfifo_free(&info->con_buf);
if (!cons)
return;
spin_lock(&cons->lock);
req = cons->req;
ep = cons->console.data;
cons->req = NULL;
spin_unlock(&cons->lock);
if (!req)
return;
usb_ep_dequeue(ep, req);
gs_free_req(ep, req);
}
static int gs_console_init(struct gs_port *port)
{
struct gs_console *cons;
int err;
if (port->console)
return 0;
cons = kzalloc(sizeof(*port->console), GFP_KERNEL);
if (!cons)
return -ENOMEM;
strcpy(cons->console.name, "ttyGS");
cons->console.write = gs_console_write;
cons->console.device = gs_console_device;
cons->console.flags = CON_PRINTBUFFER;
cons->console.index = port->port_num;
INIT_WORK(&cons->work, gs_console_work);
spin_lock_init(&cons->lock);
err = kfifo_alloc(&cons->buf, GS_CONSOLE_BUF_SIZE, GFP_KERNEL);
if (err) {
pr_err("ttyGS%d: allocate console buffer failed\n", port->port_num);
kfree(cons);
return err;
}
port->console = cons;
register_console(&cons->console);
spin_lock_irq(&port->port_lock);
if (port->port_usb)
gs_console_connect(port);
spin_unlock_irq(&port->port_lock);
return 0;
}
static void gs_console_exit(struct gs_port *port)
{
struct gs_console *cons = port->console;
if (!cons)
return;
unregister_console(&cons->console);
spin_lock_irq(&port->port_lock);
if (cons->req)
gs_console_disconnect(port);
spin_unlock_irq(&port->port_lock);
cancel_work_sync(&cons->work);
kfifo_free(&cons->buf);
kfree(cons);
port->console = NULL;
}
ssize_t gserial_set_console(unsigned char port_num, const char *page, size_t count)
{
struct gs_port *port;
bool enable;
int ret;
ret = strtobool(page, &enable);
if (ret)
return ret;
mutex_lock(&ports[port_num].lock);
port = ports[port_num].port;
if (WARN_ON(port == NULL)) {
ret = -ENXIO;
goto out;
}
if (enable)
ret = gs_console_init(port);
else
gs_console_exit(port);
out:
mutex_unlock(&ports[port_num].lock);
return ret < 0 ? ret : count;
}
EXPORT_SYMBOL_GPL(gserial_set_console);
ssize_t gserial_get_console(unsigned char port_num, char *page)
{
struct gs_port *port;
ssize_t ret;
mutex_lock(&ports[port_num].lock);
port = ports[port_num].port;
if (WARN_ON(port == NULL))
ret = -ENXIO;
else
ret = sprintf(page, "%u\n", !!port->console);
mutex_unlock(&ports[port_num].lock);
return ret;
}
EXPORT_SYMBOL_GPL(gserial_get_console);
#else
static int gs_console_connect(int port_num)
static int gs_console_connect(struct gs_port *port)
{
return 0;
}
static void gs_console_disconnect(struct usb_ep *ep)
static void gs_console_disconnect(struct gs_port *port)
{
}
static void gserial_console_init(void)
static int gs_console_init(struct gs_port *port)
{
return -ENOSYS;
}
static void gserial_console_exit(void)
static void gs_console_exit(struct gs_port *port)
{
}
@ -1172,8 +1168,9 @@ static int gs_closed(struct gs_port *port)
int cond;
spin_lock_irq(&port->port_lock);
cond = (port->port.count == 0) && !port->openclose;
cond = port->port.count == 0;
spin_unlock_irq(&port->port_lock);
return cond;
}
@ -1197,18 +1194,19 @@ void gserial_free_line(unsigned char port_num)
return;
}
port = ports[port_num].port;
gs_console_exit(port);
ports[port_num].port = NULL;
mutex_unlock(&ports[port_num].lock);
gserial_free_port(port);
tty_unregister_device(gs_tty_driver, port_num);
gserial_console_exit();
}
EXPORT_SYMBOL_GPL(gserial_free_line);
int gserial_alloc_line(unsigned char *line_num)
int gserial_alloc_line_no_console(unsigned char *line_num)
{
struct usb_cdc_line_coding coding;
struct gs_port *port;
struct device *tty_dev;
int ret;
int port_num;
@ -1231,24 +1229,35 @@ int gserial_alloc_line(unsigned char *line_num)
/* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
tty_dev = tty_port_register_device(&ports[port_num].port->port,
port = ports[port_num].port;
tty_dev = tty_port_register_device(&port->port,
gs_tty_driver, port_num, NULL);
if (IS_ERR(tty_dev)) {
struct gs_port *port;
pr_err("%s: failed to register tty for port %d, err %ld\n",
__func__, port_num, PTR_ERR(tty_dev));
ret = PTR_ERR(tty_dev);
port = ports[port_num].port;
mutex_lock(&ports[port_num].lock);
ports[port_num].port = NULL;
mutex_unlock(&ports[port_num].lock);
gserial_free_port(port);
goto err;
}
*line_num = port_num;
gserial_console_init();
err:
return ret;
}
EXPORT_SYMBOL_GPL(gserial_alloc_line_no_console);
int gserial_alloc_line(unsigned char *line_num)
{
int ret = gserial_alloc_line_no_console(line_num);
if (!ret && !*line_num)
gs_console_init(ports[*line_num].port);
return ret;
}
EXPORT_SYMBOL_GPL(gserial_alloc_line);
/**
@ -1327,7 +1336,7 @@ int gserial_connect(struct gserial *gser, u8 port_num)
gser->disconnect(gser);
}
status = gs_console_connect(port_num);
status = gs_console_connect(port);
spin_unlock_irqrestore(&port->port_lock, flags);
return status;
@ -1359,12 +1368,14 @@ void gserial_disconnect(struct gserial *gser)
/* tell the TTY glue not to do I/O here any more */
spin_lock_irqsave(&port->port_lock, flags);
gs_console_disconnect(port);
/* REVISIT as above: how best to track this? */
port->port_line_coding = gser->port_line_coding;
port->port_usb = NULL;
gser->ioport = NULL;
if (port->port.count > 0 || port->openclose) {
if (port->port.count > 0) {
wake_up_interruptible(&port->drain_wait);
if (port->port.tty)
tty_hangup(port->port.tty);
@ -1377,7 +1388,7 @@ void gserial_disconnect(struct gserial *gser)
/* finally, free any unused/unusable I/O buffers */
spin_lock_irqsave(&port->port_lock, flags);
if (port->port.count == 0 && !port->openclose)
if (port->port.count == 0)
kfifo_free(&port->port_write_buf);
gs_free_requests(gser->out, &port->read_pool, NULL);
gs_free_requests(gser->out, &port->read_queue, NULL);
@ -1386,7 +1397,6 @@ void gserial_disconnect(struct gserial *gser)
port->read_allocated = port->read_started =
port->write_allocated = port->write_started = 0;
gs_console_disconnect(gser->in);
spin_unlock_irqrestore(&port->port_lock, flags);
}
EXPORT_SYMBOL_GPL(gserial_disconnect);

View File

@ -54,9 +54,17 @@ struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
void gs_free_req(struct usb_ep *, struct usb_request *req);
/* management of individual TTY ports */
int gserial_alloc_line_no_console(unsigned char *port_line);
int gserial_alloc_line(unsigned char *port_line);
void gserial_free_line(unsigned char port_line);
#ifdef CONFIG_U_SERIAL_CONSOLE
ssize_t gserial_set_console(unsigned char port_num, const char *page, size_t count);
ssize_t gserial_get_console(unsigned char port_num, char *page);
#endif /* CONFIG_U_SERIAL_CONSOLE */
/* connect/disconnect is handled by individual functions */
int gserial_connect(struct gserial *, u8 port_num);
void gserial_disconnect(struct gserial *);

View File

@ -149,21 +149,21 @@ config USB_ETH_RNDIS
is given in comments found in that info file.
config USB_ETH_EEM
bool "Ethernet Emulation Model (EEM) support"
depends on USB_ETH
bool "Ethernet Emulation Model (EEM) support"
depends on USB_ETH
select USB_LIBCOMPOSITE
select USB_F_EEM
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.
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".
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"

View File

@ -105,7 +105,6 @@ static struct usb_function *f_msg;
*/
static int acm_ms_do_config(struct usb_configuration *c)
{
struct fsg_opts *opts;
int status;
if (gadget_is_otg(c->cdev->gadget)) {
@ -113,8 +112,6 @@ static int acm_ms_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
opts = fsg_opts_from_func_inst(fi_msg);
f_acm = usb_get_function(f_acm_inst);
if (IS_ERR(f_acm))
return PTR_ERR(f_acm);

View File

@ -105,7 +105,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
static int msg_do_config(struct usb_configuration *c)
{
struct fsg_opts *opts;
int ret;
if (gadget_is_otg(c->cdev->gadget)) {
@ -113,8 +112,6 @@ static int msg_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
opts = fsg_opts_from_func_inst(fi_msg);
f_msg = usb_get_function(fi_msg);
if (IS_ERR(f_msg))
return PTR_ERR(f_msg);

View File

@ -97,6 +97,36 @@ static unsigned n_ports = 1;
module_param(n_ports, uint, 0);
MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
static bool enable = true;
static int switch_gserial_enable(bool do_enable);
static int enable_set(const char *s, const struct kernel_param *kp)
{
bool do_enable;
int ret;
if (!s) /* called for no-arg enable == default */
return 0;
ret = strtobool(s, &do_enable);
if (ret || enable == do_enable)
return ret;
ret = switch_gserial_enable(do_enable);
if (!ret)
enable = do_enable;
return ret;
}
static const struct kernel_param_ops enable_ops = {
.set = enable_set,
.get = param_get_bool,
};
module_param_cb(enable, &enable_ops, &enable, 0644);
/*-------------------------------------------------------------------------*/
static struct usb_configuration serial_config_driver = {
@ -240,6 +270,19 @@ static struct usb_composite_driver gserial_driver = {
.unbind = gs_unbind,
};
static int switch_gserial_enable(bool do_enable)
{
if (!serial_config_driver.label)
/* init() was not called, yet */
return 0;
if (do_enable)
return usb_composite_probe(&gserial_driver);
usb_composite_unregister(&gserial_driver);
return 0;
}
static int __init init(void)
{
/* We *could* export two configs; that'd be much cleaner...
@ -266,12 +309,16 @@ static int __init init(void)
}
strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
if (!enable)
return 0;
return usb_composite_probe(&gserial_driver);
}
module_init(init);
static void __exit cleanup(void)
{
usb_composite_unregister(&gserial_driver);
if (enable)
usb_composite_unregister(&gserial_driver);
}
module_exit(cleanup);

View File

@ -120,10 +120,10 @@ config USB_FOTG210_UDC
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
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
@ -441,6 +441,17 @@ config USB_GADGET_XILINX
dynamically linked module called "udc-xilinx" and force all
gadget drivers to also be dynamically linked.
config USB_TEGRA_XUDC
tristate "NVIDIA Tegra Superspeed USB 3.0 Device Controller"
depends on ARCH_TEGRA || COMPILE_TEST
depends on PHY_TEGRA_XUSB
help
Enables NVIDIA Tegra USB 3.0 device mode controller driver.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "tegra_xudc" and force all
gadget drivers to also be dynamically linked.
source "drivers/usb/gadget/udc/aspeed-vhub/Kconfig"
#

View File

@ -24,6 +24,7 @@ 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_TEGRA_XUDC) += tegra-xudc.o
obj-$(CONFIG_USB_M66592) += m66592-udc.o
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
obj-$(CONFIG_USB_RENESAS_USB3) += renesas_usb3.o

View File

@ -1808,7 +1808,6 @@ static int at91udc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct at91_udc *udc;
int retval;
struct resource *res;
struct at91_ep *ep;
int i;
@ -1839,8 +1838,7 @@ static int at91udc_probe(struct platform_device *pdev)
ep->is_pingpong = 1;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
udc->udp_baseaddr = devm_ioremap_resource(dev, res);
udc->udp_baseaddr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(udc->udp_baseaddr))
return PTR_ERR(udc->udp_baseaddr);

View File

@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/ctype.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/delay.h>
@ -226,7 +227,7 @@ static void usba_init_debugfs(struct usba_udc *udc)
struct dentry *root;
struct resource *regs_resource;
root = debugfs_create_dir(udc->gadget.name, NULL);
root = debugfs_create_dir(udc->gadget.name, usb_debug_root);
udc->debugfs_root = root;
regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM,

View File

@ -2248,7 +2248,7 @@ static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc)
if (!IS_ENABLED(CONFIG_USB_GADGET_DEBUG_FS))
return;
root = debugfs_create_dir(udc->gadget.name, NULL);
root = debugfs_create_dir(udc->gadget.name, usb_debug_root);
udc->debugfs_root = root;
debugfs_create_file("usbd", 0400, root, udc, &bcm63xx_usbd_dbg_fops);
@ -2282,7 +2282,6 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct bcm63xx_usbd_platform_data *pd = dev_get_platdata(dev);
struct bcm63xx_udc *udc;
struct resource *res;
int rc = -ENOMEM, i, irq;
udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
@ -2298,13 +2297,11 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
udc->usbd_regs = devm_ioremap_resource(dev, res);
udc->usbd_regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(udc->usbd_regs))
return PTR_ERR(udc->usbd_regs);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
udc->iudma_regs = devm_ioremap_resource(dev, res);
udc->iudma_regs = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(udc->iudma_regs))
return PTR_ERR(udc->iudma_regs);

View File

@ -480,7 +480,6 @@ static void bdc_phy_exit(struct bdc *bdc)
static int bdc_probe(struct platform_device *pdev)
{
struct bdc *bdc;
struct resource *res;
int ret = -ENOMEM;
int irq;
u32 temp;
@ -508,8 +507,7 @@ static int bdc_probe(struct platform_device *pdev)
bdc->clk = clk;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bdc->regs = devm_ioremap_resource(dev, res);
bdc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bdc->regs)) {
dev_err(dev, "ioremap error\n");
return -ENOMEM;

View File

@ -195,7 +195,7 @@ static void handle_link_state_change(struct bdc *bdc, u32 uspc)
break;
case BDC_LINK_STATE_U0:
if (bdc->devstatus & REMOTE_WAKEUP_ISSUED) {
bdc->devstatus &= ~REMOTE_WAKEUP_ISSUED;
bdc->devstatus &= ~REMOTE_WAKEUP_ISSUED;
if (bdc->gadget.speed == USB_SPEED_SUPER) {
bdc_function_wake_fh(bdc, 0);
bdc->devstatus |= FUNC_WAKE_ISSUED;

View File

@ -1321,7 +1321,7 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
u32 this_sg;
bool next_sg;
to_host = usb_pipein(urb->pipe);
to_host = usb_urb_dir_in(urb);
rbuf = req->req.buf + req->req.actual;
if (!urb->num_sgs) {
@ -1409,7 +1409,7 @@ top:
/* FIXME update emulated data toggle too */
to_host = usb_pipein(urb->pipe);
to_host = usb_urb_dir_in(urb);
if (unlikely(len == 0))
is_short = 1;
else {
@ -1830,7 +1830,7 @@ restart:
/* find the gadget's ep for this request (if configured) */
address = usb_pipeendpoint (urb->pipe);
if (usb_pipein(urb->pipe))
if (usb_urb_dir_in(urb))
address |= USB_DIR_IN;
ep = find_endpoint(dum, address);
if (!ep) {
@ -2385,7 +2385,7 @@ static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb)
s = "?";
break;
} s; }),
ep, ep ? (usb_pipein(urb->pipe) ? "in" : "out") : "",
ep, ep ? (usb_urb_dir_in(urb) ? "in" : "out") : "",
({ char *s; \
switch (usb_pipetype(urb->pipe)) { \
case PIPE_CONTROL: \
@ -2725,7 +2725,7 @@ static struct platform_driver dummy_hcd_driver = {
};
/*-------------------------------------------------------------------------*/
#define MAX_NUM_UDC 2
#define MAX_NUM_UDC 32
static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];

View File

@ -333,8 +333,8 @@ struct qe_udc {
u32 resume_state; /* USB state to resume*/
u32 usb_state; /* USB current state */
u32 usb_next_state; /* USB next state */
u32 ep0_state; /* Enpoint zero state */
u32 ep0_dir; /* Enpoint zero direction: can be
u32 ep0_state; /* Endpoint zero state */
u32 ep0_dir; /* Endpoint zero direction: can be
USB_DIR_IN or USB_DIR_OUT*/
u32 usb_sof_count; /* SOF count */
u32 errors; /* USB ERRORs count */

View File

@ -1052,10 +1052,11 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep)
u32 bitmask;
struct ep_queue_head *qh;
ep = container_of(_ep, struct fsl_ep, ep);
if (!_ep || (!ep->ep.desc && ep_index(ep) != 0))
if (!_ep || _ep->desc || !(_ep->desc->bEndpointAddress&0xF))
return -ENODEV;
ep = container_of(_ep, struct fsl_ep, ep);
udc = (struct fsl_udc *)ep->udc;
if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
@ -1208,7 +1209,7 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
}
/* Change Data+ pullup status
* this func is used by usb_gadget_connect/disconnet
* this func is used by usb_gadget_connect/disconnect
*/
static int fsl_pullup(struct usb_gadget *gadget, int is_on)
{
@ -1595,14 +1596,13 @@ static int process_ep_req(struct fsl_udc *udc, int pipe,
struct fsl_req *curr_req)
{
struct ep_td_struct *curr_td;
int td_complete, actual, remaining_length, j, tmp;
int actual, remaining_length, j, tmp;
int status = 0;
int errors = 0;
struct ep_queue_head *curr_qh = &udc->ep_qh[pipe];
int direction = pipe % 2;
curr_td = curr_req->head;
td_complete = 0;
actual = curr_req->req.length;
for (j = 0; j < curr_req->dtd_count; j++) {
@ -1647,11 +1647,9 @@ static int process_ep_req(struct fsl_udc *udc, int pipe,
status = -EPROTO;
break;
} else {
td_complete++;
break;
}
} else {
td_complete++;
VDBG("dTD transmitted successful");
}

View File

@ -29,6 +29,7 @@
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/dma-mapping.h>
@ -208,7 +209,7 @@ static void gr_dfs_create(struct gr_udc *dev)
{
const char *name = "gr_udc_state";
dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), NULL);
dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), usb_debug_root);
debugfs_create_file(name, 0444, dev->dfs_root, dev, &gr_dfs_fops);
}
@ -2118,7 +2119,6 @@ static int gr_request_irq(struct gr_udc *dev, int irq)
static int gr_probe(struct platform_device *pdev)
{
struct gr_udc *dev;
struct resource *res;
struct gr_regs __iomem *regs;
int retval;
u32 status;
@ -2128,8 +2128,7 @@ static int gr_probe(struct platform_device *pdev)
return -ENOMEM;
dev->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev->dev, res);
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);

View File

@ -3000,7 +3000,6 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct lpc32xx_udc *udc;
int retval, i;
struct resource *res;
dma_addr_t dma_handle;
struct device_node *isp1301_node;
@ -3048,9 +3047,6 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
* IORESOURCE_IRQ, USB device interrupt number
* IORESOURCE_IRQ, USB transceiver interrupt number
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
spin_lock_init(&udc->lock);
@ -3061,7 +3057,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
return udc->udp_irq[i];
}
udc->udp_baseaddr = devm_ioremap_resource(dev, res);
udc->udp_baseaddr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(udc->udp_baseaddr)) {
dev_err(udc->dev, "IO map failure\n");
return PTR_ERR(udc->udp_baseaddr);

View File

@ -138,7 +138,7 @@ struct mv_u3d_op_regs {
u32 doorbell; /* doorbell register */
};
/* control enpoint enable registers */
/* control endpoint enable registers */
struct epxcr {
u32 epxoutcr0; /* ep out control 0 register */
u32 epxoutcr1; /* ep out control 1 register */

View File

@ -1519,7 +1519,6 @@ static void pch_udc_free_dma_chain(struct pch_udc_dev *dev,
td = phys_to_virt(addr);
addr2 = (dma_addr_t)td->next;
dma_pool_free(dev->data_requests, td, addr);
td->next = 0x00;
addr = addr2;
}
req->chain_len = 1;

View File

@ -2321,7 +2321,6 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
struct pxa25x_udc *dev = &memory;
int retval, irq;
u32 chiprev;
struct resource *res;
pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
@ -2367,8 +2366,7 @@ static int pxa25x_udc_probe(struct platform_device *pdev)
if (irq < 0)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->regs = devm_ioremap_resource(&pdev->dev, res);
dev->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dev->regs))
return PTR_ERR(dev->regs);

View File

@ -207,7 +207,7 @@ static void pxa_init_debugfs(struct pxa_udc *udc)
{
struct dentry *root;
root = debugfs_create_dir(udc->gadget.name, NULL);
root = debugfs_create_dir(udc->gadget.name, usb_debug_root);
udc->debugfs_root = root;
debugfs_create_file("udcstate", 0400, root, udc, &state_dbg_fops);
@ -2356,7 +2356,6 @@ MODULE_DEVICE_TABLE(of, udc_pxa_dt_ids);
*/
static int pxa_udc_probe(struct platform_device *pdev)
{
struct resource *regs;
struct pxa_udc *udc = &memory;
int retval = 0, gpio;
struct pxa2xx_udc_mach_info *mach = dev_get_platdata(&pdev->dev);
@ -2378,8 +2377,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
udc->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_ASIS);
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
udc->regs = devm_ioremap_resource(&pdev->dev, regs);
udc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(udc->regs))
return PTR_ERR(udc->regs);
udc->irq = platform_get_irq(pdev, 0);

View File

@ -1838,7 +1838,7 @@ static int r8a66597_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
char clk_name[8];
struct resource *res, *ires;
struct resource *ires;
int irq;
void __iomem *reg = NULL;
struct r8a66597 *r8a66597 = NULL;
@ -1846,8 +1846,7 @@ static int r8a66597_probe(struct platform_device *pdev)
int i;
unsigned long irq_trigger;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg = devm_ioremap_resource(&pdev->dev, res);
reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
return PTR_ERR(reg);

View File

@ -775,6 +775,18 @@ static void usb3_irq_epc_int_1_resume(struct renesas_usb3 *usb3)
usb3_transition_to_default_state(usb3, false);
}
static void usb3_irq_epc_int_1_suspend(struct renesas_usb3 *usb3)
{
usb3_disable_irq_1(usb3, USB_INT_1_B2_SPND);
if (usb3->gadget.speed != USB_SPEED_UNKNOWN &&
usb3->gadget.state != USB_STATE_NOTATTACHED) {
if (usb3->driver && usb3->driver->suspend)
usb3->driver->suspend(&usb3->gadget);
usb_gadget_set_state(&usb3->gadget, USB_STATE_SUSPENDED);
}
}
static void usb3_irq_epc_int_1_disable(struct renesas_usb3 *usb3)
{
usb3_stop_usb3_connection(usb3);
@ -860,6 +872,9 @@ static void usb3_irq_epc_int_1(struct renesas_usb3 *usb3, u32 int_sta_1)
if (int_sta_1 & USB_INT_1_B2_RSUM)
usb3_irq_epc_int_1_resume(usb3);
if (int_sta_1 & USB_INT_1_B2_SPND)
usb3_irq_epc_int_1_suspend(usb3);
if (int_sta_1 & USB_INT_1_SPEED)
usb3_irq_epc_int_1_speed(usb3);
@ -2536,7 +2551,7 @@ static const struct file_operations renesas_usb3_b_device_fops = {
static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3,
struct device *dev)
{
usb3->dentry = debugfs_create_dir(dev_name(dev), NULL);
usb3->dentry = debugfs_create_dir(dev_name(dev), usb_debug_root);
debugfs_create_file("b_device", 0644, usb3->dentry, usb3,
&renesas_usb3_b_device_fops);
@ -2733,7 +2748,6 @@ static struct usb_role_switch_desc renesas_usb3_role_switch_desc = {
static int renesas_usb3_probe(struct platform_device *pdev)
{
struct renesas_usb3 *usb3;
struct resource *res;
int irq, ret;
const struct renesas_usb3_priv *priv;
const struct soc_device_attribute *attr;
@ -2752,8 +2766,7 @@ static int renesas_usb3_probe(struct platform_device *pdev)
if (!usb3)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
usb3->reg = devm_ioremap_resource(&pdev->dev, res);
usb3->reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(usb3->reg))
return PTR_ERR(usb3->reg);

View File

@ -1263,7 +1263,6 @@ static const struct usb_gadget_ops s3c_hsudc_gadget_ops = {
static int s3c_hsudc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct s3c_hsudc *hsudc;
struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev);
int ret, i;
@ -1290,9 +1289,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
goto err_supplies;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hsudc->regs = devm_ioremap_resource(&pdev->dev, res);
hsudc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hsudc->regs)) {
ret = PTR_ERR(hsudc->regs);
goto err_res;

View File

@ -1978,7 +1978,8 @@ static int __init udc_init(void)
dprintk(DEBUG_NORMAL, "%s\n", gadget_name);
s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name,
usb_debug_root);
retval = platform_driver_register(&udc_driver_24x0);
if (retval)

File diff suppressed because it is too large Load Diff

View File

@ -38,9 +38,9 @@ config USB_XHCI_DBGCAP
before enabling this option. If unsure, say 'N'.
config USB_XHCI_PCI
tristate
depends on USB_PCI
default y
tristate
depends on USB_PCI
default y
config USB_XHCI_PLATFORM
tristate "Generic xHCI driver for a platform device"
@ -220,12 +220,12 @@ config USB_EHCI_HCD_ORION
Marvell PXA/MMP USB controller" for those.
config USB_EHCI_HCD_SPEAR
tristate "Support for ST SPEAr on-chip EHCI USB controller"
depends on USB_EHCI_HCD && PLAT_SPEAR
default y
---help---
Enables support for the on-chip EHCI controller on
ST SPEAr chips.
tristate "Support for ST SPEAr on-chip EHCI USB controller"
depends on USB_EHCI_HCD && PLAT_SPEAR
default y
---help---
Enables support for the on-chip EHCI controller on
ST SPEAr chips.
config USB_EHCI_HCD_STI
tristate "Support for ST STiHxxx on-chip EHCI USB controller"
@ -237,21 +237,21 @@ config USB_EHCI_HCD_STI
STMicroelectronics consumer electronics SoC's.
config USB_EHCI_HCD_AT91
tristate "Support for Atmel on-chip EHCI USB controller"
depends on USB_EHCI_HCD && ARCH_AT91
default y
---help---
Enables support for the on-chip EHCI controller on
Atmel chips.
tristate "Support for Atmel on-chip EHCI USB controller"
depends on USB_EHCI_HCD && ARCH_AT91
default y
---help---
Enables support for the on-chip EHCI controller on
Atmel chips.
config USB_EHCI_TEGRA
tristate "NVIDIA Tegra HCD support"
depends on ARCH_TEGRA
select USB_EHCI_ROOT_HUB_TT
select USB_TEGRA_PHY
help
This driver enables support for the internal USB Host Controllers
found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
tristate "NVIDIA Tegra HCD support"
depends on ARCH_TEGRA
select USB_EHCI_ROOT_HUB_TT
select USB_TEGRA_PHY
help
This driver enables support for the internal USB Host Controllers
found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
config USB_EHCI_HCD_PPC_OF
bool "EHCI support for PPC USB controller on OF platform bus"
@ -269,10 +269,10 @@ config USB_EHCI_SH
If you use the PCI EHCI controller, this option is not necessary.
config USB_EHCI_EXYNOS
tristate "EHCI support for Samsung S5P/EXYNOS SoC Series"
depends on ARCH_S5PV210 || ARCH_EXYNOS
help
Enable support for the Samsung Exynos SOC's on-chip EHCI controller.
tristate "EHCI support for Samsung S5P/EXYNOS SoC Series"
depends on ARCH_S5PV210 || ARCH_EXYNOS
help
Enable support for the Samsung Exynos SOC's on-chip EHCI controller.
config USB_EHCI_MV
tristate "EHCI support for Marvell PXA/MMP USB controller"
@ -409,12 +409,12 @@ config USB_OHCI_HCD_OMAP1
Enables support for the OHCI controller on OMAP1/2 chips.
config USB_OHCI_HCD_SPEAR
tristate "Support for ST SPEAr on-chip OHCI USB controller"
depends on USB_OHCI_HCD && PLAT_SPEAR
default y
---help---
Enables support for the on-chip OHCI controller on
ST SPEAr chips.
tristate "Support for ST SPEAr on-chip OHCI USB controller"
depends on USB_OHCI_HCD && PLAT_SPEAR
default y
---help---
Enables support for the on-chip OHCI controller on
ST SPEAr chips.
config USB_OHCI_HCD_STI
tristate "Support for ST STiHxxx on-chip OHCI USB controller"
@ -426,12 +426,12 @@ config USB_OHCI_HCD_STI
STMicroelectronics consumer electronics SoC's.
config USB_OHCI_HCD_S3C2410
tristate "OHCI support for Samsung S3C24xx/S3C64xx SoC series"
depends on USB_OHCI_HCD && (ARCH_S3C24XX || ARCH_S3C64XX)
default y
---help---
Enables support for the on-chip OHCI controller on
S3C24xx/S3C64xx chips.
tristate "OHCI support for Samsung S3C24xx/S3C64xx SoC series"
depends on USB_OHCI_HCD && (ARCH_S3C24XX || ARCH_S3C64XX)
default y
---help---
Enables support for the on-chip OHCI controller on
S3C24xx/S3C64xx chips.
config USB_OHCI_HCD_LPC32XX
tristate "Support for LPC on-chip OHCI USB controller"
@ -440,8 +440,8 @@ config USB_OHCI_HCD_LPC32XX
depends on USB_ISP1301
default y
---help---
Enables support for the on-chip OHCI controller on
NXP chips.
Enables support for the on-chip OHCI controller on
NXP chips.
config USB_OHCI_HCD_PXA27X
tristate "Support for PXA27X/PXA3XX on-chip OHCI USB controller"
@ -456,8 +456,8 @@ config USB_OHCI_HCD_AT91
depends on USB_OHCI_HCD && ARCH_AT91 && OF
default y
---help---
Enables support for the on-chip OHCI controller on
Atmel chips.
Enables support for the on-chip OHCI controller on
Atmel chips.
config USB_OHCI_HCD_OMAP3
tristate "OHCI support for OMAP3 and later chips"
@ -545,7 +545,7 @@ config USB_OHCI_EXYNOS
tristate "OHCI support for Samsung S5P/EXYNOS SoC Series"
depends on ARCH_S5PV210 || ARCH_EXYNOS
help
Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
config USB_CNS3XXX_OHCI
bool "Cavium CNS3XXX OHCI Module (DEPRECATED)"
@ -609,8 +609,8 @@ config USB_UHCI_PLATFORM
default y if (ARCH_VT8500 || ARCH_ASPEED)
config USB_UHCI_ASPEED
bool
default y if ARCH_ASPEED
bool
default y if ARCH_ASPEED
config USB_FHCI_HCD
tristate "Freescale QE USB Host Controller support"
@ -713,14 +713,14 @@ config USB_RENESAS_USBHS_HCD
module will be called renesas-usbhs.
config USB_IMX21_HCD
tristate "i.MX21 HCD support"
depends on ARM && ARCH_MXC
help
This driver enables support for the on-chip USB host in the
i.MX21 processor.
tristate "i.MX21 HCD support"
depends on ARM && ARCH_MXC
help
This driver enables support for the on-chip USB host in the
i.MX21 processor.
To compile this driver as a module, choose M here: the
module will be called "imx21-hcd".
To compile this driver as a module, choose M here: the
module will be called "imx21-hcd".
config USB_HCD_BCMA
tristate "BCMA usb host driver"

View File

@ -406,9 +406,12 @@ static int bcma_hcd_probe(struct bcma_device *core)
return -ENOMEM;
usb_dev->core = core;
if (core->dev.of_node)
if (core->dev.of_node) {
usb_dev->gpio_desc = devm_gpiod_get(&core->dev, "vcc",
GPIOD_OUT_HIGH);
if (IS_ERR(usb_dev->gpio_desc))
return PTR_ERR(usb_dev->gpio_desc);
}
switch (core->id.id) {
case BCMA_CORE_USB20_HOST:

View File

@ -5646,8 +5646,10 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
return retval;
failed_dis_clk:
if (!IS_ERR(fotg210->pclk))
if (!IS_ERR(fotg210->pclk)) {
clk_disable_unprepare(fotg210->pclk);
clk_put(fotg210->pclk);
}
failed_put_hcd:
usb_put_hcd(hcd);
fail_create_hcd:
@ -5665,8 +5667,10 @@ static int fotg210_hcd_remove(struct platform_device *pdev)
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
if (!IS_ERR(fotg210->pclk))
if (!IS_ERR(fotg210->pclk)) {
clk_disable_unprepare(fotg210->pclk);
clk_put(fotg210->pclk);
}
usb_remove_hcd(hcd);
usb_put_hcd(hcd);

View File

@ -419,7 +419,7 @@ static void create_debug_files(struct imx21 *imx21)
{
struct dentry *root;
root = debugfs_create_dir(dev_name(imx21->dev), NULL);
root = debugfs_create_dir(dev_name(imx21->dev), usb_debug_root);
imx21->debug_root = root;
debugfs_create_file("status", S_IRUGO, root, imx21, &debug_status_fops);

View File

@ -2627,7 +2627,7 @@ static int isp1362_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct isp1362_hcd *isp1362_hcd;
struct resource *addr, *data, *irq_res;
struct resource *data, *irq_res;
void __iomem *addr_reg;
void __iomem *data_reg;
int irq;
@ -2651,8 +2651,7 @@ static int isp1362_probe(struct platform_device *pdev)
irq = irq_res->start;
addr = platform_get_resource(pdev, IORESOURCE_MEM, 1);
addr_reg = devm_ioremap_resource(&pdev->dev, addr);
addr_reg = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(addr_reg))
return PTR_ERR(addr_reg);

View File

@ -115,7 +115,6 @@ static void at91_start_hc(struct platform_device *pdev)
static void at91_stop_hc(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct ohci_regs __iomem *regs = hcd->regs;
struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd);
dev_dbg(&pdev->dev, "stop\n");
@ -123,7 +122,7 @@ static void at91_stop_hc(struct platform_device *pdev)
/*
* Put the USB host controller into reset.
*/
writel(0, &regs->control);
usb_hcd_platform_shutdown(pdev);
/*
* Stop the USB clocks.
@ -628,6 +627,7 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
/* flush the writes */
(void) ohci_readl (ohci, &ohci->regs->control);
msleep(1);
at91_stop_clock(ohci_at91);
}
@ -642,8 +642,8 @@ ohci_hcd_at91_drv_resume(struct device *dev)
if (ohci_at91->wakeup)
disable_irq_wake(hcd->irq);
at91_start_clock(ohci_at91);
else
at91_start_clock(ohci_at91);
ohci_resume(hcd, false);

View File

@ -150,7 +150,7 @@ static void ohci_nxp_stop_hc(void)
static int ohci_hcd_nxp_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd = 0;
struct usb_hcd *hcd = NULL;
const struct hc_driver *driver = &ohci_nxp_hc_driver;
struct resource *res;
int ret = 0, irq;

View File

@ -676,12 +676,12 @@ static int oxu_hub_control(struct usb_hcd *hcd,
*/
/* Low level read/write registers functions */
static inline u32 oxu_readl(void *base, u32 reg)
static inline u32 oxu_readl(void __iomem *base, u32 reg)
{
return readl(base + reg);
}
static inline void oxu_writel(void *base, u32 reg, u32 val)
static inline void oxu_writel(void __iomem *base, u32 reg, u32 val)
{
writel(val, base + reg);
}
@ -4063,7 +4063,7 @@ static const struct hc_driver oxu_hc_driver = {
* Module stuff
*/
static void oxu_configuration(struct platform_device *pdev, void *base)
static void oxu_configuration(struct platform_device *pdev, void __iomem *base)
{
u32 tmp;
@ -4093,7 +4093,7 @@ static void oxu_configuration(struct platform_device *pdev, void *base)
oxu_writel(base, OXU_CHIPIRQEN_SET, OXU_USBSPHLPWUI | OXU_USBOTGLPWUI);
}
static int oxu_verify_id(struct platform_device *pdev, void *base)
static int oxu_verify_id(struct platform_device *pdev, void __iomem *base)
{
u32 id;
static const char * const bo[] = {
@ -4121,7 +4121,7 @@ static int oxu_verify_id(struct platform_device *pdev, void *base)
static const struct hc_driver oxu_hc_driver;
static struct usb_hcd *oxu_create(struct platform_device *pdev,
unsigned long memstart, unsigned long memlen,
void *base, int irq, int otg)
void __iomem *base, int irq, int otg)
{
struct device *dev = &pdev->dev;
@ -4158,7 +4158,7 @@ static struct usb_hcd *oxu_create(struct platform_device *pdev,
static int oxu_init(struct platform_device *pdev,
unsigned long memstart, unsigned long memlen,
void *base, int irq)
void __iomem *base, int irq)
{
struct oxu_info *info = platform_get_drvdata(pdev);
struct usb_hcd *hcd;
@ -4207,7 +4207,7 @@ error_create_otg:
static int oxu_drv_probe(struct platform_device *pdev)
{
struct resource *res;
void *base;
void __iomem *base;
unsigned long memstart, memlen;
int irq, ret;
struct oxu_info *info;

View File

@ -71,7 +71,7 @@ INT_MODULE_PARM(testing, 0);
/* Some boards misreport power switching/overcurrent*/
static bool distrust_firmware = true;
module_param(distrust_firmware, bool, 0);
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurrent"
"t setup");
static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
/*

View File

@ -48,6 +48,7 @@
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_XHCI 0x15e9
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI 0x15ec
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI 0x15f0
#define PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI 0x8a13
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
@ -212,7 +213,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI))
pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI))
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&

View File

@ -280,6 +280,9 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci)
return;
xhci_dbg(xhci, "// Ding dong!\n");
trace_xhci_ring_host_doorbell(0, DB_VALUE_HOST);
writel(DB_VALUE_HOST, &xhci->dba->doorbell[0]);
/* Flush PCI posted writes */
readl(&xhci->dba->doorbell[0]);
@ -401,6 +404,9 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING) ||
(ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT))
return;
trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id));
writel(DB_VALUE(ep_index, stream_id), db_addr);
/* The CPU has better things to do at this point than wait for a
* write-posting flush. It'll get there soon enough.
@ -651,10 +657,8 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
}
xhci_urb_free_priv(urb_priv);
usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock(&xhci->lock);
trace_xhci_urb_giveback(urb);
usb_hcd_giveback_urb(hcd, urb, status);
spin_lock(&xhci->lock);
}
static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
@ -2740,6 +2744,42 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
return 1;
}
/*
* Update Event Ring Dequeue Pointer:
* - When all events have finished
* - To avoid "Event Ring Full Error" condition
*/
static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
union xhci_trb *event_ring_deq)
{
u64 temp_64;
dma_addr_t deq;
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
/* If necessary, update the HW's version of the event ring deq ptr. */
if (event_ring_deq != xhci->event_ring->dequeue) {
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
xhci->event_ring->dequeue);
if (deq == 0)
xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n");
/*
* Per 4.9.4, Software writes to the ERDP register shall
* always advance the Event Ring Dequeue Pointer value.
*/
if ((temp_64 & (u64) ~ERST_PTR_MASK) ==
((u64) deq & (u64) ~ERST_PTR_MASK))
return;
/* Update HC event ring dequeue pointer */
temp_64 &= ERST_PTR_MASK;
temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
}
/* Clear the event handler busy flag (RW1C) */
temp_64 |= ERST_EHB;
xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
}
/*
* xHCI spec says we can get an interrupt, and if the HC has an error condition,
* we might get bad data out of the event ring. Section 4.10.2.7 has a list of
@ -2751,9 +2791,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
union xhci_trb *event_ring_deq;
irqreturn_t ret = IRQ_NONE;
unsigned long flags;
dma_addr_t deq;
u64 temp_64;
u32 status;
int event_loop = 0;
spin_lock_irqsave(&xhci->lock, flags);
/* Check if the xHC generated the interrupt, or the irq is shared */
@ -2807,24 +2847,14 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
/* FIXME this should be a delayed service routine
* that clears the EHB.
*/
while (xhci_handle_event(xhci) > 0) {}
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
/* If necessary, update the HW's version of the event ring deq ptr. */
if (event_ring_deq != xhci->event_ring->dequeue) {
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
xhci->event_ring->dequeue);
if (deq == 0)
xhci_warn(xhci, "WARN something wrong with SW event "
"ring dequeue ptr.\n");
/* Update HC event ring dequeue pointer */
temp_64 &= ERST_PTR_MASK;
temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
while (xhci_handle_event(xhci) > 0) {
if (event_loop++ < TRBS_PER_SEGMENT / 2)
continue;
xhci_update_erst_dequeue(xhci, event_ring_deq);
event_loop = 0;
}
/* Clear the event handler busy flag (RW1C); event ring is empty. */
temp_64 |= ERST_EHB;
xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
xhci_update_erst_dequeue(xhci, event_ring_deq);
ret = IRQ_HANDLED;
out:

View File

@ -42,19 +42,18 @@
#define XUSB_CFG_CSB_BASE_ADDR 0x800
/* FPCI mailbox registers */
#define XUSB_CFG_ARU_MBOX_CMD 0x0e4
/* XUSB_CFG_ARU_MBOX_CMD */
#define MBOX_DEST_FALC BIT(27)
#define MBOX_DEST_PME BIT(28)
#define MBOX_DEST_SMI BIT(29)
#define MBOX_DEST_XHCI BIT(30)
#define MBOX_INT_EN BIT(31)
#define XUSB_CFG_ARU_MBOX_DATA_IN 0x0e8
/* XUSB_CFG_ARU_MBOX_DATA_IN and XUSB_CFG_ARU_MBOX_DATA_OUT */
#define CMD_DATA_SHIFT 0
#define CMD_DATA_MASK 0xffffff
#define CMD_TYPE_SHIFT 24
#define CMD_TYPE_MASK 0xff
#define XUSB_CFG_ARU_MBOX_DATA_OUT 0x0ec
#define XUSB_CFG_ARU_MBOX_OWNER 0x0f0
/* XUSB_CFG_ARU_MBOX_OWNER */
#define MBOX_OWNER_NONE 0
#define MBOX_OWNER_FW 1
#define MBOX_OWNER_SW 2
@ -146,6 +145,13 @@ struct tegra_xusb_phy_type {
unsigned int num;
};
struct tega_xusb_mbox_regs {
u16 cmd;
u16 data_in;
u16 data_out;
u16 owner;
};
struct tegra_xusb_soc {
const char *firmware;
const char * const *supply_names;
@ -160,6 +166,8 @@ struct tegra_xusb_soc {
} usb2, ulpi, hsic, usb3;
} ports;
struct tega_xusb_mbox_regs mbox;
bool scale_ss_clock;
bool has_ipfs;
};
@ -395,15 +403,15 @@ static int tegra_xusb_mbox_send(struct tegra_xusb *tegra,
* ACK/NAK messages.
*/
if (!(msg->cmd == MBOX_CMD_ACK || msg->cmd == MBOX_CMD_NAK)) {
value = fpci_readl(tegra, XUSB_CFG_ARU_MBOX_OWNER);
value = fpci_readl(tegra, tegra->soc->mbox.owner);
if (value != MBOX_OWNER_NONE) {
dev_err(tegra->dev, "mailbox is busy\n");
return -EBUSY;
}
fpci_writel(tegra, MBOX_OWNER_SW, XUSB_CFG_ARU_MBOX_OWNER);
fpci_writel(tegra, MBOX_OWNER_SW, tegra->soc->mbox.owner);
value = fpci_readl(tegra, XUSB_CFG_ARU_MBOX_OWNER);
value = fpci_readl(tegra, tegra->soc->mbox.owner);
if (value != MBOX_OWNER_SW) {
dev_err(tegra->dev, "failed to acquire mailbox\n");
return -EBUSY;
@ -413,17 +421,17 @@ static int tegra_xusb_mbox_send(struct tegra_xusb *tegra,
}
value = tegra_xusb_mbox_pack(msg);
fpci_writel(tegra, value, XUSB_CFG_ARU_MBOX_DATA_IN);
fpci_writel(tegra, value, tegra->soc->mbox.data_in);
value = fpci_readl(tegra, XUSB_CFG_ARU_MBOX_CMD);
value = fpci_readl(tegra, tegra->soc->mbox.cmd);
value |= MBOX_INT_EN | MBOX_DEST_FALC;
fpci_writel(tegra, value, XUSB_CFG_ARU_MBOX_CMD);
fpci_writel(tegra, value, tegra->soc->mbox.cmd);
if (wait_for_idle) {
unsigned long timeout = jiffies + msecs_to_jiffies(250);
while (time_before(jiffies, timeout)) {
value = fpci_readl(tegra, XUSB_CFG_ARU_MBOX_OWNER);
value = fpci_readl(tegra, tegra->soc->mbox.owner);
if (value == MBOX_OWNER_NONE)
break;
@ -431,7 +439,7 @@ static int tegra_xusb_mbox_send(struct tegra_xusb *tegra,
}
if (time_after(jiffies, timeout))
value = fpci_readl(tegra, XUSB_CFG_ARU_MBOX_OWNER);
value = fpci_readl(tegra, tegra->soc->mbox.owner);
if (value != MBOX_OWNER_NONE)
return -ETIMEDOUT;
@ -598,16 +606,16 @@ static irqreturn_t tegra_xusb_mbox_thread(int irq, void *data)
mutex_lock(&tegra->lock);
value = fpci_readl(tegra, XUSB_CFG_ARU_MBOX_DATA_OUT);
value = fpci_readl(tegra, tegra->soc->mbox.data_out);
tegra_xusb_mbox_unpack(&msg, value);
value = fpci_readl(tegra, XUSB_CFG_ARU_MBOX_CMD);
value = fpci_readl(tegra, tegra->soc->mbox.cmd);
value &= ~MBOX_DEST_SMI;
fpci_writel(tegra, value, XUSB_CFG_ARU_MBOX_CMD);
fpci_writel(tegra, value, tegra->soc->mbox.cmd);
/* clear mailbox owner if no ACK/NAK is required */
if (!tegra_xusb_mbox_cmd_requires_ack(msg.cmd))
fpci_writel(tegra, MBOX_OWNER_NONE, XUSB_CFG_ARU_MBOX_OWNER);
fpci_writel(tegra, MBOX_OWNER_NONE, tegra->soc->mbox.owner);
tegra_xusb_mbox_handle(tegra, &msg);
@ -755,7 +763,6 @@ static int tegra_xusb_runtime_suspend(struct device *dev)
{
struct tegra_xusb *tegra = dev_get_drvdata(dev);
tegra_xusb_phy_disable(tegra);
regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies);
tegra_xusb_clk_disable(tegra);
@ -779,16 +786,8 @@ static int tegra_xusb_runtime_resume(struct device *dev)
goto disable_clk;
}
err = tegra_xusb_phy_enable(tegra);
if (err < 0) {
dev_err(dev, "failed to enable PHYs: %d\n", err);
goto disable_regulator;
}
return 0;
disable_regulator:
regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies);
disable_clk:
tegra_xusb_clk_disable(tegra);
return err;
@ -970,7 +969,7 @@ static int tegra_xusb_powerdomain_init(struct device *dev,
static int tegra_xusb_probe(struct platform_device *pdev)
{
struct tegra_xusb_mbox_msg msg;
struct resource *res, *regs;
struct resource *regs;
struct tegra_xusb *tegra;
struct xhci_hcd *xhci;
unsigned int i, j, k;
@ -992,14 +991,12 @@ static int tegra_xusb_probe(struct platform_device *pdev)
if (IS_ERR(tegra->regs))
return PTR_ERR(tegra->regs);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
tegra->fpci_base = devm_ioremap_resource(&pdev->dev, res);
tegra->fpci_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(tegra->fpci_base))
return PTR_ERR(tegra->fpci_base);
if (tegra->soc->has_ipfs) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res);
tegra->ipfs_base = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(tegra->ipfs_base))
return PTR_ERR(tegra->ipfs_base);
}
@ -1128,8 +1125,9 @@ static int tegra_xusb_probe(struct platform_device *pdev)
goto put_powerdomains;
}
for (i = 0; i < tegra->soc->num_supplies; i++)
tegra->supplies[i].supply = tegra->soc->supply_names[i];
regulator_bulk_set_supply_names(tegra->supplies,
tegra->soc->supply_names,
tegra->soc->num_supplies);
err = devm_regulator_bulk_get(&pdev->dev, tegra->soc->num_supplies,
tegra->supplies);
@ -1181,6 +1179,12 @@ static int tegra_xusb_probe(struct platform_device *pdev)
*/
platform_set_drvdata(pdev, tegra);
err = tegra_xusb_phy_enable(tegra);
if (err < 0) {
dev_err(&pdev->dev, "failed to enable PHYs: %d\n", err);
goto put_hcd;
}
pm_runtime_enable(&pdev->dev);
if (pm_runtime_enabled(&pdev->dev))
err = pm_runtime_get_sync(&pdev->dev);
@ -1189,7 +1193,7 @@ static int tegra_xusb_probe(struct platform_device *pdev)
if (err < 0) {
dev_err(&pdev->dev, "failed to enable device: %d\n", err);
goto disable_rpm;
goto disable_phy;
}
tegra_xusb_config(tegra, regs);
@ -1275,9 +1279,11 @@ remove_usb2:
put_rpm:
if (!pm_runtime_status_suspended(&pdev->dev))
tegra_xusb_runtime_suspend(&pdev->dev);
disable_rpm:
pm_runtime_disable(&pdev->dev);
put_hcd:
usb_put_hcd(tegra->hcd);
disable_phy:
tegra_xusb_phy_disable(tegra);
pm_runtime_disable(&pdev->dev);
put_powerdomains:
if (!of_property_read_bool(pdev->dev.of_node, "power-domains")) {
tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC);
@ -1314,6 +1320,8 @@ static int tegra_xusb_remove(struct platform_device *pdev)
tegra_xusb_powerdomain_remove(&pdev->dev, tegra);
}
tegra_xusb_phy_disable(tegra);
tegra_xusb_padctl_put(tegra->padctl);
return 0;
@ -1375,6 +1383,12 @@ static const struct tegra_xusb_soc tegra124_soc = {
},
.scale_ss_clock = true,
.has_ipfs = true,
.mbox = {
.cmd = 0xe4,
.data_in = 0xe8,
.data_out = 0xec,
.owner = 0xf0,
},
};
MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
@ -1407,6 +1421,12 @@ static const struct tegra_xusb_soc tegra210_soc = {
},
.scale_ss_clock = false,
.has_ipfs = true,
.mbox = {
.cmd = 0xe4,
.data_in = 0xe8,
.data_out = 0xec,
.owner = 0xf0,
},
};
MODULE_FIRMWARE("nvidia/tegra210/xusb.bin");
@ -1432,12 +1452,48 @@ static const struct tegra_xusb_soc tegra186_soc = {
},
.scale_ss_clock = false,
.has_ipfs = false,
.mbox = {
.cmd = 0xe4,
.data_in = 0xe8,
.data_out = 0xec,
.owner = 0xf0,
},
};
static const char * const tegra194_supply_names[] = {
};
static const struct tegra_xusb_phy_type tegra194_phy_types[] = {
{ .name = "usb3", .num = 4, },
{ .name = "usb2", .num = 4, },
};
static const struct tegra_xusb_soc tegra194_soc = {
.firmware = "nvidia/tegra194/xusb.bin",
.supply_names = tegra194_supply_names,
.num_supplies = ARRAY_SIZE(tegra194_supply_names),
.phy_types = tegra194_phy_types,
.num_types = ARRAY_SIZE(tegra194_phy_types),
.ports = {
.usb3 = { .offset = 0, .count = 4, },
.usb2 = { .offset = 4, .count = 4, },
},
.scale_ss_clock = false,
.has_ipfs = false,
.mbox = {
.cmd = 0x68,
.data_in = 0x6c,
.data_out = 0x70,
.owner = 0x74,
},
};
MODULE_FIRMWARE("nvidia/tegra194/xusb.bin");
static const struct of_device_id tegra_xusb_of_match[] = {
{ .compatible = "nvidia,tegra124-xusb", .data = &tegra124_soc },
{ .compatible = "nvidia,tegra210-xusb", .data = &tegra210_soc },
{ .compatible = "nvidia,tegra186-xusb", .data = &tegra186_soc },
{ .compatible = "nvidia,tegra194-xusb", .data = &tegra194_soc },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_xusb_of_match);

View File

@ -560,6 +560,32 @@ DEFINE_EVENT(xhci_log_portsc, xhci_hub_status_data,
TP_ARGS(portnum, portsc)
);
DECLARE_EVENT_CLASS(xhci_log_doorbell,
TP_PROTO(u32 slot, u32 doorbell),
TP_ARGS(slot, doorbell),
TP_STRUCT__entry(
__field(u32, slot)
__field(u32, doorbell)
),
TP_fast_assign(
__entry->slot = slot;
__entry->doorbell = doorbell;
),
TP_printk("Ring doorbell for %s",
xhci_decode_doorbell(__entry->slot, __entry->doorbell)
)
);
DEFINE_EVENT(xhci_log_doorbell, xhci_ring_ep_doorbell,
TP_PROTO(u32 slot, u32 doorbell),
TP_ARGS(slot, doorbell)
);
DEFINE_EVENT(xhci_log_doorbell, xhci_ring_host_doorbell,
TP_PROTO(u32 slot, u32 doorbell),
TP_ARGS(slot, doorbell)
);
DECLARE_EVENT_CLASS(xhci_dbc_log_request,
TP_PROTO(struct dbc_request *req),
TP_ARGS(req),

View File

@ -5301,7 +5301,8 @@ static const struct hc_driver xhci_hc_driver = {
* generic hardware linkage
*/
.irq = xhci_irq,
.flags = HCD_MEMORY | HCD_DMA | HCD_USB3 | HCD_SHARED,
.flags = HCD_MEMORY | HCD_DMA | HCD_USB3 | HCD_SHARED |
HCD_BH,
/*
* basic lifecycle operations

View File

@ -2580,6 +2580,35 @@ static inline const char *xhci_decode_portsc(u32 portsc)
return str;
}
static inline const char *xhci_decode_doorbell(u32 slot, u32 doorbell)
{
static char str[256];
u8 ep;
u16 stream;
int ret;
ep = (doorbell & 0xff);
stream = doorbell >> 16;
if (slot == 0) {
sprintf(str, "Command Ring %d", doorbell);
return str;
}
ret = sprintf(str, "Slot %d ", slot);
if (ep > 0 && ep < 32)
ret = sprintf(str + ret, "ep%d%s",
ep / 2,
ep % 2 ? "in" : "out");
else if (ep == 0 || ep < 248)
ret = sprintf(str + ret, "Reserved %d", ep);
else
ret = sprintf(str + ret, "Vendor Defined %d", ep);
if (stream)
ret = sprintf(str + ret, " Stream %d", stream);
return str;
}
static inline const char *xhci_ep_state_string(u8 state)
{
switch (state) {

View File

@ -566,7 +566,6 @@ static int
mts_scsi_queuecommand_lck(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
{
struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
int err = 0;
int res;
MTS_DEBUG_GOT_HERE();
@ -613,7 +612,7 @@ mts_scsi_queuecommand_lck(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback
}
out:
return err;
return 0;
}
static DEF_SCSI_QCMD(mts_scsi_queuecommand)

View File

@ -1032,8 +1032,6 @@ static int check_atl_transfer(struct usb_hcd *hcd, struct ptd *ptd,
urb->status = -EOVERFLOW;
else if (FROM_DW3_CERR(ptd->dw3))
urb->status = -EPIPE; /* Stall */
else if (ptd->dw3 & DW3_ERROR_BIT)
urb->status = -EPROTO; /* XactErr */
else
urb->status = -EPROTO; /* Unknown */
/*

View File

@ -181,8 +181,8 @@ config USB_TEST
including sample test device firmware and "how to use it".
config USB_EHSET_TEST_FIXTURE
tristate "USB EHSET Test Fixture driver"
help
tristate "USB EHSET Test Fixture driver"
help
Say Y here if you want to support the special test fixture device
used for the USB-IF Embedded Host High-Speed Electrical Test procedure.
@ -233,17 +233,17 @@ config USB_HUB_USB251XB
Say Y or M here if you need to configure such a device via SMBus.
config USB_HSIC_USB3503
tristate "USB3503 HSIC to USB20 Driver"
depends on I2C
select REGMAP_I2C
help
This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
tristate "USB3503 HSIC to USB20 Driver"
depends on I2C
select REGMAP_I2C
help
This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
config USB_HSIC_USB4604
tristate "USB4604 HSIC to USB20 Driver"
depends on I2C
help
This option enables support for SMSC USB4604 HSIC to USB 2.0 Driver.
tristate "USB4604 HSIC to USB20 Driver"
depends on I2C
help
This option enables support for SMSC USB4604 HSIC to USB 2.0 Driver.
config USB_LINK_LAYER_TEST
tristate "USB Link Layer Test driver"

View File

@ -164,7 +164,12 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd)
0,
pdata->msgdata, 2,
ACD_USB_TIMEOUT);
brightness = pdata->msgdata[1];
if (retval < 2) {
if (retval >= 0)
retval = -EMSGSIZE;
} else {
brightness = pdata->msgdata[1];
}
mutex_unlock(&pdata->sysfslock);
if (retval < 0)
@ -299,6 +304,7 @@ error:
if (pdata) {
if (pdata->urb) {
usb_kill_urb(pdata->urb);
cancel_delayed_work_sync(&pdata->work);
if (pdata->urbdata)
usb_free_coherent(pdata->udev, ACD_URB_BUFFER_LEN,
pdata->urbdata, pdata->urb->transfer_dma);

View File

@ -384,13 +384,17 @@ static int _chaoskey_fill(struct chaoskey *dev)
!dev->reading,
(started ? NAK_TIMEOUT : ALEA_FIRST_TIMEOUT) );
if (result < 0)
if (result < 0) {
usb_kill_urb(dev->urb);
goto out;
}
if (result == 0)
if (result == 0) {
result = -ETIMEDOUT;
else
usb_kill_urb(dev->urb);
} else {
result = dev->valid;
}
out:
/* Let the device go back to sleep eventually */
usb_autopm_put_interface(dev->interface);
@ -526,7 +530,21 @@ static int chaoskey_suspend(struct usb_interface *interface,
static int chaoskey_resume(struct usb_interface *interface)
{
struct chaoskey *dev;
struct usb_device *udev = interface_to_usbdev(interface);
usb_dbg(interface, "resume");
dev = usb_get_intfdata(interface);
/*
* We may have lost power.
* In that case the device that needs a long time
* for the first requests needs an extended timeout
* again
*/
if (le16_to_cpu(udev->descriptor.idVendor) == ALEA_VENDOR_ID)
dev->reads_started = false;
return 0;
}
#else

View File

@ -333,7 +333,8 @@ static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi)
*respond->result = -ESHUTDOWN;
*respond->value = 0;
complete(&respond->wait_completion);
} mutex_unlock(&ftdi->u132_lock);
}
mutex_unlock(&ftdi->u132_lock);
}
static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi)
@ -763,7 +764,8 @@ static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size)
struct u132_command *command = &ftdi->command[COMMAND_MASK &
i++];
total_size += 5 + command->follows;
} return total_size;
}
return total_size;
}
static int ftdi_elan_command_engine(struct usb_ftdi *ftdi)

View File

@ -56,11 +56,10 @@ static const struct usb_device_id idmouse_table[] = {
#define FTIP_SCROLL 0x24
#define ftip_command(dev, command, value, index) \
usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), command, \
usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), command, \
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000)
MODULE_DEVICE_TABLE(usb, idmouse_table);
static DEFINE_MUTEX(open_disc_mutex);
/* structure to hold all of our device specific stuff */
struct usb_idmouse {
@ -158,8 +157,8 @@ static int idmouse_create_image(struct usb_idmouse *dev)
/* loop over a blocking bulk read to get data from the device */
while (bytes_read < IMGSIZE) {
result = usb_bulk_msg (dev->udev,
usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr),
result = usb_bulk_msg(dev->udev,
usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
dev->bulk_in_buffer + bytes_read,
dev->bulk_in_size, &bulk_read, 5000);
if (result < 0) {
@ -223,21 +222,17 @@ static int idmouse_open(struct inode *inode, struct file *file)
int result;
/* get the interface from minor number and driver information */
interface = usb_find_interface (&idmouse_driver, iminor (inode));
interface = usb_find_interface(&idmouse_driver, iminor(inode));
if (!interface)
return -ENODEV;
mutex_lock(&open_disc_mutex);
/* get the device information block from the interface */
dev = usb_get_intfdata(interface);
if (!dev) {
mutex_unlock(&open_disc_mutex);
if (!dev)
return -ENODEV;
}
/* lock this device */
mutex_lock(&dev->lock);
mutex_unlock(&open_disc_mutex);
/* check if already open */
if (dev->open) {
@ -251,7 +246,7 @@ static int idmouse_open(struct inode *inode, struct file *file)
result = usb_autopm_get_interface(interface);
if (result)
goto error;
result = idmouse_create_image (dev);
result = idmouse_create_image(dev);
usb_autopm_put_interface(interface);
if (result)
goto error;
@ -280,27 +275,17 @@ static int idmouse_release(struct inode *inode, struct file *file)
if (dev == NULL)
return -ENODEV;
mutex_lock(&open_disc_mutex);
/* lock our device */
mutex_lock(&dev->lock);
/* are we really open? */
if (dev->open <= 0) {
mutex_unlock(&dev->lock);
mutex_unlock(&open_disc_mutex);
return -ENODEV;
}
--dev->open;
if (!dev->present) {
/* the device was unplugged before the file was released */
mutex_unlock(&dev->lock);
mutex_unlock(&open_disc_mutex);
idmouse_delete(dev);
} else {
mutex_unlock(&dev->lock);
mutex_unlock(&open_disc_mutex);
}
return 0;
}
@ -379,7 +364,6 @@ static int idmouse_probe(struct usb_interface *interface,
if (result) {
/* something prevented us from registering this device */
dev_err(&interface->dev, "Unable to allocate minor number.\n");
usb_set_intfdata(interface, NULL);
idmouse_delete(dev);
return result;
}
@ -392,19 +376,13 @@ static int idmouse_probe(struct usb_interface *interface,
static void idmouse_disconnect(struct usb_interface *interface)
{
struct usb_idmouse *dev;
/* get device structure */
dev = usb_get_intfdata(interface);
struct usb_idmouse *dev = usb_get_intfdata(interface);
/* give back our minor */
usb_deregister_dev(interface, &idmouse_class);
mutex_lock(&open_disc_mutex);
usb_set_intfdata(interface, NULL);
/* lock the device */
mutex_lock(&dev->lock);
mutex_unlock(&open_disc_mutex);
/* prevent device read, write and ioctl */
dev->present = 0;

View File

@ -157,19 +157,19 @@ MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms");
#define LEGO_USB_TOWER_REQUEST_GET_VERSION 0xFD
struct tower_reset_reply {
__le16 size; /* little-endian */
__le16 size;
__u8 err_code;
__u8 spare;
} __attribute__ ((packed));
};
struct tower_get_version_reply {
__le16 size; /* little-endian */
__le16 size;
__u8 err_code;
__u8 spare;
__u8 major;
__u8 minor;
__le16 build_no; /* little-endian */
} __attribute__ ((packed));
__le16 build_no;
};
/* table of devices that work with this driver */
@ -178,7 +178,7 @@ static const struct usb_device_id tower_table[] = {
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, tower_table);
MODULE_DEVICE_TABLE(usb, tower_table);
#define LEGO_USB_TOWER_MINOR_BASE 160
@ -186,13 +186,13 @@ MODULE_DEVICE_TABLE (usb, tower_table);
/* Structure to hold all of our device specific stuff */
struct lego_usb_tower {
struct mutex lock; /* locks this structure */
struct usb_device* udev; /* save off the usb device pointer */
struct usb_device *udev; /* save off the usb device pointer */
unsigned char minor; /* the starting minor number for this device */
int open_count; /* number of times this port has been opened */
unsigned long disconnected:1;
char* read_buffer;
char *read_buffer;
size_t read_buffer_length; /* this much came in */
size_t read_packet_length; /* this much will be returned on read */
spinlock_t read_buffer_lock;
@ -202,16 +202,15 @@ struct lego_usb_tower {
wait_queue_head_t read_wait;
wait_queue_head_t write_wait;
char* interrupt_in_buffer;
struct usb_endpoint_descriptor* interrupt_in_endpoint;
struct urb* interrupt_in_urb;
char *interrupt_in_buffer;
struct usb_endpoint_descriptor *interrupt_in_endpoint;
struct urb *interrupt_in_urb;
int interrupt_in_interval;
int interrupt_in_running;
int interrupt_in_done;
char* interrupt_out_buffer;
struct usb_endpoint_descriptor* interrupt_out_endpoint;
struct urb* interrupt_out_urb;
char *interrupt_out_buffer;
struct usb_endpoint_descriptor *interrupt_out_endpoint;
struct urb *interrupt_out_urb;
int interrupt_out_interval;
int interrupt_out_busy;
@ -219,21 +218,20 @@ struct lego_usb_tower {
/* local function prototypes */
static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos);
static ssize_t tower_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
static inline void tower_delete (struct lego_usb_tower *dev);
static int tower_open (struct inode *inode, struct file *file);
static int tower_release (struct inode *inode, struct file *file);
static __poll_t tower_poll (struct file *file, poll_table *wait);
static loff_t tower_llseek (struct file *file, loff_t off, int whence);
static ssize_t tower_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
static ssize_t tower_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
static inline void tower_delete(struct lego_usb_tower *dev);
static int tower_open(struct inode *inode, struct file *file);
static int tower_release(struct inode *inode, struct file *file);
static __poll_t tower_poll(struct file *file, poll_table *wait);
static loff_t tower_llseek(struct file *file, loff_t off, int whence);
static void tower_abort_transfers (struct lego_usb_tower *dev);
static void tower_check_for_read_packet (struct lego_usb_tower *dev);
static void tower_interrupt_in_callback (struct urb *urb);
static void tower_interrupt_out_callback (struct urb *urb);
static void tower_check_for_read_packet(struct lego_usb_tower *dev);
static void tower_interrupt_in_callback(struct urb *urb);
static void tower_interrupt_out_callback(struct urb *urb);
static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id);
static void tower_disconnect (struct usb_interface *interface);
static int tower_probe(struct usb_interface *interface, const struct usb_device_id *id);
static void tower_disconnect(struct usb_interface *interface);
/* file operations needed when we register this driver */
@ -288,23 +286,23 @@ static inline void lego_usb_tower_debug_data(struct device *dev,
/**
* tower_delete
*/
static inline void tower_delete (struct lego_usb_tower *dev)
static inline void tower_delete(struct lego_usb_tower *dev)
{
/* free data structures */
usb_free_urb(dev->interrupt_in_urb);
usb_free_urb(dev->interrupt_out_urb);
kfree (dev->read_buffer);
kfree (dev->interrupt_in_buffer);
kfree (dev->interrupt_out_buffer);
kfree(dev->read_buffer);
kfree(dev->interrupt_in_buffer);
kfree(dev->interrupt_out_buffer);
usb_put_dev(dev->udev);
kfree (dev);
kfree(dev);
}
/**
* tower_open
*/
static int tower_open (struct inode *inode, struct file *file)
static int tower_open(struct inode *inode, struct file *file)
{
struct lego_usb_tower *dev = NULL;
int subminor;
@ -314,7 +312,6 @@ static int tower_open (struct inode *inode, struct file *file)
int result;
reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL);
if (!reset_reply) {
retval = -ENOMEM;
goto exit;
@ -323,8 +320,7 @@ static int tower_open (struct inode *inode, struct file *file)
nonseekable_open(inode, file);
subminor = iminor(inode);
interface = usb_find_interface (&tower_driver, subminor);
interface = usb_find_interface(&tower_driver, subminor);
if (!interface) {
pr_err("error, can't find device for minor %d\n", subminor);
retval = -ENODEV;
@ -351,15 +347,15 @@ static int tower_open (struct inode *inode, struct file *file)
}
/* reset the tower */
result = usb_control_msg (dev->udev,
usb_rcvctrlpipe(dev->udev, 0),
LEGO_USB_TOWER_REQUEST_RESET,
USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
0,
0,
reset_reply,
sizeof(*reset_reply),
1000);
result = usb_control_msg(dev->udev,
usb_rcvctrlpipe(dev->udev, 0),
LEGO_USB_TOWER_REQUEST_RESET,
USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
0,
0,
reset_reply,
sizeof(*reset_reply),
1000);
if (result < 0) {
dev_err(&dev->udev->dev,
"LEGO USB Tower reset control request failed\n");
@ -370,24 +366,22 @@ static int tower_open (struct inode *inode, struct file *file)
/* initialize in direction */
dev->read_buffer_length = 0;
dev->read_packet_length = 0;
usb_fill_int_urb (dev->interrupt_in_urb,
dev->udev,
usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress),
dev->interrupt_in_buffer,
usb_endpoint_maxp(dev->interrupt_in_endpoint),
tower_interrupt_in_callback,
dev,
dev->interrupt_in_interval);
usb_fill_int_urb(dev->interrupt_in_urb,
dev->udev,
usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress),
dev->interrupt_in_buffer,
usb_endpoint_maxp(dev->interrupt_in_endpoint),
tower_interrupt_in_callback,
dev,
dev->interrupt_in_interval);
dev->interrupt_in_running = 1;
dev->interrupt_in_done = 0;
mb();
retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL);
retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
if (retval) {
dev_err(&dev->udev->dev,
"Couldn't submit interrupt_in_urb %d\n", retval);
dev->interrupt_in_running = 0;
goto unlock_exit;
}
@ -407,13 +401,12 @@ exit:
/**
* tower_release
*/
static int tower_release (struct inode *inode, struct file *file)
static int tower_release(struct inode *inode, struct file *file)
{
struct lego_usb_tower *dev;
int retval = 0;
dev = file->private_data;
if (dev == NULL) {
retval = -ENODEV;
goto exit;
@ -421,56 +414,32 @@ static int tower_release (struct inode *inode, struct file *file)
mutex_lock(&dev->lock);
if (dev->open_count != 1) {
dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n",
__func__);
retval = -ENODEV;
goto unlock_exit;
}
if (dev->disconnected) {
/* the device was unplugged before the file was released */
/* unlock here as tower_delete frees dev */
mutex_unlock(&dev->lock);
tower_delete (dev);
tower_delete(dev);
goto exit;
}
/* wait until write transfer is finished */
if (dev->interrupt_out_busy) {
wait_event_interruptible_timeout (dev->write_wait, !dev->interrupt_out_busy, 2 * HZ);
wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy,
2 * HZ);
}
tower_abort_transfers (dev);
/* shutdown transfers */
usb_kill_urb(dev->interrupt_in_urb);
usb_kill_urb(dev->interrupt_out_urb);
dev->open_count = 0;
unlock_exit:
mutex_unlock(&dev->lock);
exit:
return retval;
}
/**
* tower_abort_transfers
* aborts transfers and frees associated data structures
*/
static void tower_abort_transfers (struct lego_usb_tower *dev)
{
if (dev == NULL)
return;
/* shutdown transfer */
if (dev->interrupt_in_running) {
dev->interrupt_in_running = 0;
mb();
usb_kill_urb(dev->interrupt_in_urb);
}
if (dev->interrupt_out_busy)
usb_kill_urb(dev->interrupt_out_urb);
}
/**
* tower_check_for_read_packet
*
@ -479,23 +448,23 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
* until it has been there unchanged for at least
* dev->packet_timeout_jiffies, or until the buffer is full.
*/
static void tower_check_for_read_packet (struct lego_usb_tower *dev)
static void tower_check_for_read_packet(struct lego_usb_tower *dev)
{
spin_lock_irq (&dev->read_buffer_lock);
spin_lock_irq(&dev->read_buffer_lock);
if (!packet_timeout
|| time_after(jiffies, dev->read_last_arrival + dev->packet_timeout_jiffies)
|| dev->read_buffer_length == read_buffer_size) {
dev->read_packet_length = dev->read_buffer_length;
}
dev->interrupt_in_done = 0;
spin_unlock_irq (&dev->read_buffer_lock);
spin_unlock_irq(&dev->read_buffer_lock);
}
/**
* tower_poll
*/
static __poll_t tower_poll (struct file *file, poll_table *wait)
static __poll_t tower_poll(struct file *file, poll_table *wait)
{
struct lego_usb_tower *dev;
__poll_t mask = 0;
@ -509,12 +478,10 @@ static __poll_t tower_poll (struct file *file, poll_table *wait)
poll_wait(file, &dev->write_wait, wait);
tower_check_for_read_packet(dev);
if (dev->read_packet_length > 0) {
if (dev->read_packet_length > 0)
mask |= EPOLLIN | EPOLLRDNORM;
}
if (!dev->interrupt_out_busy) {
if (!dev->interrupt_out_busy)
mask |= EPOLLOUT | EPOLLWRNORM;
}
return mask;
}
@ -523,7 +490,7 @@ static __poll_t tower_poll (struct file *file, poll_table *wait)
/**
* tower_llseek
*/
static loff_t tower_llseek (struct file *file, loff_t off, int whence)
static loff_t tower_llseek(struct file *file, loff_t off, int whence)
{
return -ESPIPE; /* unseekable */
}
@ -532,7 +499,7 @@ static loff_t tower_llseek (struct file *file, loff_t off, int whence)
/**
* tower_read
*/
static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos)
static ssize_t tower_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct lego_usb_tower *dev;
size_t bytes_to_read;
@ -551,7 +518,6 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
/* verify that the device wasn't unplugged */
if (dev->disconnected) {
retval = -ENODEV;
pr_err("No device or device unplugged %d\n", retval);
goto unlock_exit;
}
@ -561,21 +527,19 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
goto unlock_exit;
}
if (read_timeout) {
if (read_timeout)
timeout = jiffies + msecs_to_jiffies(read_timeout);
}
/* wait for data */
tower_check_for_read_packet (dev);
tower_check_for_read_packet(dev);
while (dev->read_packet_length == 0) {
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
goto unlock_exit;
}
retval = wait_event_interruptible_timeout(dev->read_wait, dev->interrupt_in_done, dev->packet_timeout_jiffies);
if (retval < 0) {
if (retval < 0)
goto unlock_exit;
}
/* reset read timeout during read or write activity */
if (read_timeout
@ -583,28 +547,27 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
timeout = jiffies + msecs_to_jiffies(read_timeout);
}
/* check for read timeout */
if (read_timeout && time_after (jiffies, timeout)) {
if (read_timeout && time_after(jiffies, timeout)) {
retval = -ETIMEDOUT;
goto unlock_exit;
}
tower_check_for_read_packet (dev);
tower_check_for_read_packet(dev);
}
/* copy the data from read_buffer into userspace */
bytes_to_read = min(count, dev->read_packet_length);
if (copy_to_user (buffer, dev->read_buffer, bytes_to_read)) {
if (copy_to_user(buffer, dev->read_buffer, bytes_to_read)) {
retval = -EFAULT;
goto unlock_exit;
}
spin_lock_irq (&dev->read_buffer_lock);
spin_lock_irq(&dev->read_buffer_lock);
dev->read_buffer_length -= bytes_to_read;
dev->read_packet_length -= bytes_to_read;
for (i=0; i<dev->read_buffer_length; i++) {
for (i = 0; i < dev->read_buffer_length; i++)
dev->read_buffer[i] = dev->read_buffer[i+bytes_to_read];
}
spin_unlock_irq (&dev->read_buffer_lock);
spin_unlock_irq(&dev->read_buffer_lock);
retval = bytes_to_read;
@ -620,7 +583,7 @@ exit:
/**
* tower_write
*/
static ssize_t tower_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
static ssize_t tower_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct lego_usb_tower *dev;
size_t bytes_to_write;
@ -637,7 +600,6 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
/* verify that the device wasn't unplugged */
if (dev->disconnected) {
retval = -ENODEV;
pr_err("No device or device unplugged %d\n", retval);
goto unlock_exit;
}
@ -653,10 +615,10 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
retval = -EAGAIN;
goto unlock_exit;
}
retval = wait_event_interruptible (dev->write_wait, !dev->interrupt_out_busy);
if (retval) {
retval = wait_event_interruptible(dev->write_wait,
!dev->interrupt_out_busy);
if (retval)
goto unlock_exit;
}
}
/* write the data into interrupt_out_buffer from userspace */
@ -664,7 +626,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
dev_dbg(&dev->udev->dev, "%s: count = %zd, bytes_to_write = %zd\n",
__func__, count, bytes_to_write);
if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
retval = -EFAULT;
goto unlock_exit;
}
@ -682,7 +644,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
dev->interrupt_out_busy = 1;
wmb();
retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL);
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
if (retval) {
dev->interrupt_out_busy = 0;
dev_err(&dev->udev->dev,
@ -703,7 +665,7 @@ exit:
/**
* tower_interrupt_in_callback
*/
static void tower_interrupt_in_callback (struct urb *urb)
static void tower_interrupt_in_callback(struct urb *urb)
{
struct lego_usb_tower *dev = urb->context;
int status = urb->status;
@ -729,9 +691,9 @@ static void tower_interrupt_in_callback (struct urb *urb)
if (urb->actual_length > 0) {
spin_lock_irqsave(&dev->read_buffer_lock, flags);
if (dev->read_buffer_length + urb->actual_length < read_buffer_size) {
memcpy (dev->read_buffer + dev->read_buffer_length,
dev->interrupt_in_buffer,
urb->actual_length);
memcpy(dev->read_buffer + dev->read_buffer_length,
dev->interrupt_in_buffer,
urb->actual_length);
dev->read_buffer_length += urb->actual_length;
dev->read_last_arrival = jiffies;
dev_dbg(&dev->udev->dev, "%s: received %d bytes\n",
@ -744,25 +706,21 @@ static void tower_interrupt_in_callback (struct urb *urb)
}
resubmit:
/* resubmit if we're still running */
if (dev->interrupt_in_running) {
retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC);
if (retval)
dev_err(&dev->udev->dev,
"%s: usb_submit_urb failed (%d)\n",
__func__, retval);
retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
if (retval) {
dev_err(&dev->udev->dev, "%s: usb_submit_urb failed (%d)\n",
__func__, retval);
}
exit:
dev->interrupt_in_done = 1;
wake_up_interruptible (&dev->read_wait);
wake_up_interruptible(&dev->read_wait);
}
/**
* tower_interrupt_out_callback
*/
static void tower_interrupt_out_callback (struct urb *urb)
static void tower_interrupt_out_callback(struct urb *urb)
{
struct lego_usb_tower *dev = urb->context;
int status = urb->status;
@ -790,48 +748,27 @@ static void tower_interrupt_out_callback (struct urb *urb)
* Called by the usb core when a new device is connected that it thinks
* this driver might be interested in.
*/
static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id)
static int tower_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct device *idev = &interface->dev;
struct usb_device *udev = interface_to_usbdev(interface);
struct lego_usb_tower *dev = NULL;
struct lego_usb_tower *dev;
struct tower_get_version_reply *get_version_reply = NULL;
int retval = -ENOMEM;
int result;
/* allocate memory for our device state and initialize it */
dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL);
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
goto exit;
mutex_init(&dev->lock);
dev->udev = usb_get_dev(udev);
dev->open_count = 0;
dev->disconnected = 0;
dev->read_buffer = NULL;
dev->read_buffer_length = 0;
dev->read_packet_length = 0;
spin_lock_init (&dev->read_buffer_lock);
spin_lock_init(&dev->read_buffer_lock);
dev->packet_timeout_jiffies = msecs_to_jiffies(packet_timeout);
dev->read_last_arrival = jiffies;
init_waitqueue_head (&dev->read_wait);
init_waitqueue_head (&dev->write_wait);
dev->interrupt_in_buffer = NULL;
dev->interrupt_in_endpoint = NULL;
dev->interrupt_in_urb = NULL;
dev->interrupt_in_running = 0;
dev->interrupt_in_done = 0;
dev->interrupt_out_buffer = NULL;
dev->interrupt_out_endpoint = NULL;
dev->interrupt_out_urb = NULL;
dev->interrupt_out_busy = 0;
init_waitqueue_head(&dev->read_wait);
init_waitqueue_head(&dev->write_wait);
result = usb_find_common_endpoints_reverse(interface->cur_altsetting,
NULL, NULL,
@ -843,16 +780,16 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
goto error;
}
dev->read_buffer = kmalloc (read_buffer_size, GFP_KERNEL);
dev->read_buffer = kmalloc(read_buffer_size, GFP_KERNEL);
if (!dev->read_buffer)
goto error;
dev->interrupt_in_buffer = kmalloc (usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL);
dev->interrupt_in_buffer = kmalloc(usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL);
if (!dev->interrupt_in_buffer)
goto error;
dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->interrupt_in_urb)
goto error;
dev->interrupt_out_buffer = kmalloc (write_buffer_size, GFP_KERNEL);
dev->interrupt_out_buffer = kmalloc(write_buffer_size, GFP_KERNEL);
if (!dev->interrupt_out_buffer)
goto error;
dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
@ -862,22 +799,21 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL);
if (!get_version_reply) {
retval = -ENOMEM;
goto error;
}
/* get the firmware version and log it */
result = usb_control_msg (udev,
usb_rcvctrlpipe(udev, 0),
LEGO_USB_TOWER_REQUEST_GET_VERSION,
USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
0,
0,
get_version_reply,
sizeof(*get_version_reply),
1000);
result = usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0),
LEGO_USB_TOWER_REQUEST_GET_VERSION,
USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
0,
0,
get_version_reply,
sizeof(*get_version_reply),
1000);
if (result != sizeof(*get_version_reply)) {
if (result >= 0)
result = -EIO;
@ -892,10 +828,9 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
le16_to_cpu(get_version_reply->build_no));
/* we can register the device now, as it is ready */
usb_set_intfdata (interface, dev);
retval = usb_register_dev (interface, &tower_class);
usb_set_intfdata(interface, dev);
retval = usb_register_dev(interface, &tower_class);
if (retval) {
/* something prevented us from registering this driver */
dev_err(idev, "Not able to get a minor for this device.\n");
@ -924,17 +859,17 @@ error:
*
* Called by the usb core when the device is removed from the system.
*/
static void tower_disconnect (struct usb_interface *interface)
static void tower_disconnect(struct usb_interface *interface)
{
struct lego_usb_tower *dev;
int minor;
dev = usb_get_intfdata (interface);
dev = usb_get_intfdata(interface);
minor = dev->minor;
/* give back our minor and prevent further open() */
usb_deregister_dev (interface, &tower_class);
usb_deregister_dev(interface, &tower_class);
/* stop I/O */
usb_poison_urb(dev->interrupt_in_urb);
@ -945,7 +880,7 @@ static void tower_disconnect (struct usb_interface *interface)
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
mutex_unlock(&dev->lock);
tower_delete (dev);
tower_delete(dev);
} else {
dev->disconnected = 1;
/* wake up pollers */
@ -962,6 +897,4 @@ module_usb_driver(tower_driver);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif

View File

@ -4,7 +4,7 @@ config USB_SISUSBVGA
tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
depends on (USB_MUSB_HDRC || USB_EHCI_HCD)
select FONT_SUPPORT if USB_SISUSBVGA_CON
---help---
---help---
Say Y here if you intend to attach a USB2VGA dongle based on a
Net2280 and a SiS315 chip.

View File

@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/nls.h>
#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
/* Internal Register Set Addresses & Default Values acc. to DS00001692C */
@ -26,10 +27,6 @@
#define USB251XB_ADDR_PRODUCT_ID_LSB 0x02
#define USB251XB_ADDR_PRODUCT_ID_MSB 0x03
#define USB251XB_DEF_PRODUCT_ID_12 0x2512 /* USB2512B/12Bi */
#define USB251XB_DEF_PRODUCT_ID_13 0x2513 /* USB2513B/13Bi */
#define USB251XB_DEF_PRODUCT_ID_14 0x2514 /* USB2514B/14Bi */
#define USB251XB_DEF_PRODUCT_ID_17 0x2517 /* USB2517/17i */
#define USB251XB_ADDR_DEVICE_ID_LSB 0x04
#define USB251XB_ADDR_DEVICE_ID_MSB 0x05
@ -74,7 +71,6 @@
#define USB251XB_ADDR_PRODUCT_STRING_LEN 0x14
#define USB251XB_ADDR_PRODUCT_STRING 0x54
#define USB251XB_DEF_PRODUCT_STRING "USB251xB/xBi/7i"
#define USB251XB_ADDR_SERIAL_STRING_LEN 0x15
#define USB251XB_ADDR_SERIAL_STRING 0x92
@ -116,6 +112,7 @@
struct usb251xb {
struct device *dev;
struct i2c_client *i2c;
struct regulator *vdd;
u8 skip_config;
struct gpio_desc *gpio_reset;
u16 vendor_id;
@ -159,6 +156,14 @@ struct usb251xb_data {
char product_str[USB251XB_STRING_BUFSIZE / 2]; /* ASCII string */
};
static const struct usb251xb_data usb2422_data = {
.product_id = 0x2422,
.port_cnt = 2,
.led_support = false,
.bat_support = true,
.product_str = "USB2422",
};
static const struct usb251xb_data usb2512b_data = {
.product_id = 0x2512,
.port_cnt = 2,
@ -261,20 +266,19 @@ static int usb251x_check_gpio_chip(struct usb251xb *hub)
}
#endif
static void usb251xb_reset(struct usb251xb *hub, int state)
static void usb251xb_reset(struct usb251xb *hub)
{
if (!hub->gpio_reset)
return;
i2c_lock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT);
gpiod_set_value_cansleep(hub->gpio_reset, state);
gpiod_set_value_cansleep(hub->gpio_reset, 1);
usleep_range(1, 10); /* >=1us RESET_N asserted */
gpiod_set_value_cansleep(hub->gpio_reset, 0);
/* wait for hub recovery/stabilization */
if (!state)
usleep_range(500, 750); /* >=500us at power on */
else
usleep_range(1, 10); /* >=1us at power down */
usleep_range(500, 750); /* >=500us after RESET_N deasserted */
i2c_unlock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT);
}
@ -292,7 +296,7 @@ static int usb251xb_connect(struct usb251xb *hub)
i2c_wb[0] = 0x01;
i2c_wb[1] = USB251XB_STATUS_COMMAND_ATTACH;
usb251xb_reset(hub, 0);
usb251xb_reset(hub);
err = i2c_smbus_write_i2c_block_data(hub->i2c,
USB251XB_ADDR_STATUS_COMMAND, 2, i2c_wb);
@ -342,7 +346,7 @@ static int usb251xb_connect(struct usb251xb *hub)
i2c_wb[USB251XB_ADDR_PORT_MAP_7] = hub->port_map7;
i2c_wb[USB251XB_ADDR_STATUS_COMMAND] = USB251XB_STATUS_COMMAND_ATTACH;
usb251xb_reset(hub, 0);
usb251xb_reset(hub);
/* write registers */
for (i = 0; i < (USB251XB_I2C_REG_SZ / USB251XB_I2C_WRITE_SZ); i++) {
@ -420,6 +424,10 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
return err;
}
hub->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(hub->vdd))
return PTR_ERR(hub->vdd);
if (of_property_read_u16_array(np, "vendor-id", &hub->vendor_id, 1))
hub->vendor_id = USB251XB_DEF_VENDOR_ID;
@ -593,6 +601,9 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
static const struct of_device_id usb251xb_of_match[] = {
{
.compatible = "microchip,usb2422",
.data = &usb2422_data,
}, {
.compatible = "microchip,usb2512b",
.data = &usb2512b_data,
}, {
@ -665,6 +676,10 @@ static int usb251xb_probe(struct usb251xb *hub)
if (err)
return err;
err = regulator_enable(hub->vdd);
if (err)
return err;
err = usb251xb_connect(hub);
if (err) {
dev_err(dev, "Failed to connect hub (%d)\n", err);
@ -692,7 +707,31 @@ static int usb251xb_i2c_probe(struct i2c_client *i2c,
return usb251xb_probe(hub);
}
static int __maybe_unused usb251xb_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct usb251xb *hub = i2c_get_clientdata(client);
return regulator_disable(hub->vdd);
}
static int __maybe_unused usb251xb_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct usb251xb *hub = i2c_get_clientdata(client);
int err;
err = regulator_enable(hub->vdd);
if (err)
return err;
return usb251xb_connect(hub);
}
static SIMPLE_DEV_PM_OPS(usb251xb_pm_ops, usb251xb_suspend, usb251xb_resume);
static const struct i2c_device_id usb251xb_id[] = {
{ "usb2422", 0 },
{ "usb2512b", 0 },
{ "usb2512bi", 0 },
{ "usb2513b", 0 },
@ -709,6 +748,7 @@ static struct i2c_driver usb251xb_i2c_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(usb251xb_of_match),
.pm = &usb251xb_pm_ops,
},
.probe = usb251xb_i2c_probe,
.id_table = usb251xb_id,

View File

@ -153,6 +153,15 @@ static void ep0_stall_set(struct mtu3_ep *mep0, bool set, u32 pktrdy)
set ? "SEND" : "CLEAR", decode_ep0_state(mtu));
}
static void ep0_do_status_stage(struct mtu3 *mtu)
{
void __iomem *mbase = mtu->mac_base;
u32 value;
value = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS;
mtu3_writel(mbase, U3D_EP0CSR, value | EP0_SETUPPKTRDY | EP0_DATAEND);
}
static int ep0_queue(struct mtu3_ep *mep0, struct mtu3_request *mreq);
static void ep0_dummy_complete(struct usb_ep *ep, struct usb_request *req)
@ -297,8 +306,7 @@ static int handle_test_mode(struct mtu3 *mtu, struct usb_ctrlrequest *setup)
ep0_load_test_packet(mtu);
/* send status before entering test mode. */
value = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS;
mtu3_writel(mbase, U3D_EP0CSR, value | EP0_SETUPPKTRDY | EP0_DATAEND);
ep0_do_status_stage(mtu);
/* wait for ACK status sent by host */
readl_poll_timeout_atomic(mbase + U3D_EP0CSR, value,
@ -632,7 +640,6 @@ __acquires(mtu->lock)
{
struct usb_ctrlrequest setup;
struct mtu3_request *mreq;
void __iomem *mbase = mtu->mac_base;
int handled = 0;
ep0_read_setup(mtu, &setup);
@ -664,14 +671,19 @@ finish:
if (mtu->test_mode) {
; /* nothing to do */
} else if (handled == USB_GADGET_DELAYED_STATUS) {
/* handle the delay STATUS phase till receive ep_queue on ep0 */
mtu->delayed_status = true;
mreq = next_ep0_request(mtu);
if (mreq) {
/* already asked us to continue delayed status */
ep0_do_status_stage(mtu);
ep0_req_giveback(mtu, &mreq->request);
} else {
/* do delayed STATUS stage till receive ep0_queue */
mtu->delayed_status = true;
}
} else if (le16_to_cpu(setup.wLength) == 0) { /* no data stage */
mtu3_writel(mbase, U3D_EP0CSR,
(mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS)
| EP0_SETUPPKTRDY | EP0_DATAEND);
ep0_do_status_stage(mtu);
/* complete zlp request directly */
mreq = next_ep0_request(mtu);
if (mreq && !mreq->request.length)
@ -802,12 +814,9 @@ static int ep0_queue(struct mtu3_ep *mep, struct mtu3_request *mreq)
}
if (mtu->delayed_status) {
u32 csr;
mtu->delayed_status = false;
csr = mtu3_readl(mtu->mac_base, U3D_EP0CSR) & EP0_W1C_BITS;
csr |= EP0_SETUPPKTRDY | EP0_DATAEND;
mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr);
ep0_do_status_stage(mtu);
/* needn't giveback the request for handling delay STATUS */
return 0;
}

View File

@ -2431,14 +2431,12 @@ static int musb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int irq = platform_get_irq_byname(pdev, "mc");
struct resource *iomem;
void __iomem *base;
if (irq <= 0)
return -ENODEV;
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, iomem);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);

View File

@ -325,7 +325,7 @@ void musb_init_debugfs(struct musb *musb)
{
struct dentry *root;
root = debugfs_create_dir(dev_name(musb->controller), NULL);
root = debugfs_create_dir(dev_name(musb->controller), usb_debug_root);
musb->debugfs_root = root;
debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops);

View File

@ -411,7 +411,7 @@ static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue)
char buf[128];
sprintf(buf, "%s.dsps", dev_name(musb->controller));
root = debugfs_create_dir(buf, NULL);
root = debugfs_create_dir(buf, usb_debug_root);
glue->dbgfs_root = root;
glue->regset.regs = dsps_musb_regs;

View File

@ -1085,7 +1085,6 @@ static int musb_gadget_disable(struct usb_ep *ep)
u8 epnum;
struct musb_ep *musb_ep;
void __iomem *epio;
int status = 0;
musb_ep = to_musb_ep(ep);
musb = musb_ep->musb;
@ -1118,7 +1117,7 @@ static int musb_gadget_disable(struct usb_ep *ep)
musb_dbg(musb, "%s", musb_ep->end_point.name);
return status;
return 0;
}
/*
@ -1316,7 +1315,7 @@ done:
}
/*
* Set or clear the halt bit of an endpoint. A halted enpoint won't tx/rx any
* Set or clear the halt bit of an endpoint. A halted endpoint won't tx/rx any
* data but will queue requests.
*
* exported to ep0 code

Some files were not shown because too many files have changed in this diff Show More