USB/PHY patches for 4.11-rc1

Here is the big USB and PHY driver updates for 4.11-rc1.
 
 Nothing major, just the normal amount of churn in the usb gadget and dwc
 and xhci controllers, new device ids, new phy drivers, a new usb-serial
 driver, and a few other minor changes in different USB drivers.
 
 All have been in linux-next for a long time with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWK2lrg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ykh7ACffotTJvB/gwpuSIWh6qhA8KQ9mH8AnjlxMafv
 b5b3vfOXJ8/N0Go25VwI
 =7fqN
 -----END PGP SIGNATURE-----

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

Pull USB/PHY updates from Greg KH:
 "Here is the big USB and PHY driver updates for 4.11-rc1.

  Nothing major, just the normal amount of churn in the usb gadget and
  dwc and xhci controllers, new device ids, new phy drivers, a new
  usb-serial driver, and a few other minor changes in different USB
  drivers.

  All have been in linux-next for a long time with no reported issues"

* tag 'usb-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (265 commits)
  usb: cdc-wdm: remove logically dead code
  USB: serial: keyspan: drop header file
  USB: serial: io_edgeport: drop io-tables header file
  usb: musb: add code comment for clarification
  usb: misc: add USB251xB/xBi Hi-Speed Hub Controller Driver
  usb: misc: usbtest: remove redundant check on retval < 0
  USB: serial: upd78f0730: sort device ids
  USB: serial: upd78f0730: add ID for EVAL-ADXL362Z
  ohci-hub: fix typo in dbg_port macro
  usb: musb: dsps: Manage CPPI 4.1 DMA interrupt in DSPS
  usb: musb: tusb6010: Clean up tusb_omap_dma structure
  usb: musb: cppi_dma: Clean up cppi41_dma_controller structure
  usb: musb: cppi_dma: Clean up cppi structure
  usb: musb: cppi41: Detect aborted transfers in cppi41_dma_callback()
  usb: musb: dma: Add a DMA completion platform callback
  drivers: usb: usbip: Add missing break statement to switch
  usb: mtu3: remove redundant dev_err call in get_ssusb_rscs()
  USB: serial: mos7840: fix another NULL-deref at open
  USB: serial: console: clean up sanity checks
  USB: serial: console: fix uninitialised spinlock
  ...
This commit is contained in:
Linus Torvalds 2017-02-22 11:15:59 -08:00
commit 8ff546b801
193 changed files with 7821 additions and 4501 deletions

View file

@ -0,0 +1,39 @@
Broadcom USB3 phy binding for northstar plus SoC
The USB3 phy is internal to the SoC and is accessed using mdio interface.
Required mdio bus properties:
- reg: Should be 0x0 for SoC internal USB3 phy
- #address-cells: must be 1
- #size-cells: must be 0
Required USB3 PHY properties:
- compatible: should be "brcm,nsp-usb3-phy"
- reg: USB3 Phy address on SoC internal MDIO bus and it should be 0x10.
- usb3-ctrl-syscon: handler of syscon node defining physical address
of usb3 control register.
- #phy-cells: must be 0
Required usb3 control properties:
- compatible: should be "brcm,nsp-usb3-ctrl"
- reg: offset and length of the control registers
Example:
mdio@0 {
reg = <0x0>;
#address-cells = <1>;
#size-cells = <0>;
usb3_phy: usb-phy@10 {
compatible = "brcm,nsp-usb3-phy";
reg = <0x10>;
usb3-ctrl-syscon = <&usb3_ctrl>;
#phy-cells = <0>;
status = "disabled";
};
};
usb3_ctrl: syscon@104408 {
compatible = "brcm,nsp-usb3-ctrl", "syscon";
reg = <0x104408 0x3fc>;
};

View file

@ -0,0 +1,84 @@
Qualcomm's USB HS PHY
PROPERTIES
- compatible:
Usage: required
Value type: <string>
Definition: Should contain "qcom,usb-hs-phy" and more specifically one of the
following:
"qcom,usb-hs-phy-apq8064"
"qcom,usb-hs-phy-msm8916"
"qcom,usb-hs-phy-msm8974"
- #phy-cells:
Usage: required
Value type: <u32>
Definition: Should contain 0
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: Should contain clock specifier for the reference and sleep
clocks
- clock-names:
Usage: required
Value type: <stringlist>
Definition: Should contain "ref" and "sleep" for the reference and sleep
clocks respectively
- resets:
Usage: required
Value type: <prop-encoded-array>
Definition: Should contain the phy and POR resets
- reset-names:
Usage: required
Value type: <stringlist>
Definition: Should contain "phy" and "por" for the phy and POR resets
respectively
- v3p3-supply:
Usage: required
Value type: <phandle>
Definition: Should contain a reference to the 3.3V supply
- v1p8-supply:
Usage: required
Value type: <phandle>
Definition: Should contain a reference to the 1.8V supply
- extcon:
Usage: optional
Value type: <prop-encoded-array>
Definition: Should contain the vbus extcon
- qcom,init-seq:
Usage: optional
Value type: <u8 array>
Definition: Should contain a sequence of ULPI address and value pairs to
program into the ULPI_EXT_VENDOR_SPECIFIC area. This is related
to Device Mode Eye Diagram test. The addresses are offsets
from the ULPI_EXT_VENDOR_SPECIFIC address, for example,
<0x1 0x53> would mean "write the value 0x53 to address 0x81".
EXAMPLE
otg: usb-controller {
ulpi {
phy {
compatible = "qcom,usb-hs-phy-msm8974", "qcom,usb-hs-phy";
#phy-cells = <0>;
clocks = <&xo_board>, <&gcc GCC_USB2A_PHY_SLEEP_CLK>;
clock-names = "ref", "sleep";
resets = <&gcc GCC_USB2A_PHY_BCR>, <&otg 0>;
reset-names = "phy", "por";
v3p3-supply = <&pm8941_l24>;
v1p8-supply = <&pm8941_l6>;
extcon = <&smbb>;
qcom,init-seq = /bits/ 8 <0x1 0x63>;
};
};
};

View file

@ -0,0 +1,65 @@
Qualcomm's USB HSIC PHY
PROPERTIES
- compatible:
Usage: required
Value type: <string>
Definition: Should contain "qcom,usb-hsic-phy" and more specifically one of the
following:
"qcom,usb-hsic-phy-mdm9615"
"qcom,usb-hsic-phy-msm8974"
- #phy-cells:
Usage: required
Value type: <u32>
Definition: Should contain 0
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: Should contain clock specifier for phy, calibration and
a calibration sleep clock
- clock-names:
Usage: required
Value type: <stringlist>
Definition: Should contain "phy, "cal" and "cal_sleep"
- pinctrl-names:
Usage: required
Value type: <stringlist>
Definition: Should contain "init" and "default" in that order
- pinctrl-0:
Usage: required
Value type: <prop-encoded-array>
Definition: List of pinctrl settings to apply to keep HSIC pins in a glitch
free state
- pinctrl-1:
Usage: required
Value type: <prop-encoded-array>
Definition: List of pinctrl settings to apply to mux out the HSIC pins
EXAMPLE
usb-controller {
ulpi {
phy {
compatible = "qcom,usb-hsic-phy-msm8974",
"qcom,usb-hsic-phy";
#phy-cells = <0>;
pinctrl-names = "init", "default";
pinctrl-0 = <&hsic_sleep>;
pinctrl-1 = <&hsic_default>;
clocks = <&gcc GCC_USB_HSIC_CLK>,
<&gcc GCC_USB_HSIC_IO_CAL_CLK>,
<&gcc GCC_USB_HSIC_IO_CAL_SLEEP_CLK>;
clock-names = "phy", "cal", "cal_sleep";
assigned-clocks = <&gcc GCC_USB_HSIC_IO_CAL_CLK>;
assigned-clock-rates = <960000>;
};
};
};

View file

@ -10,6 +10,7 @@ Required properties:
* allwinner,sun8i-a23-usb-phy
* allwinner,sun8i-a33-usb-phy
* allwinner,sun8i-h3-usb-phy
* allwinner,sun8i-v3s-usb-phy
* allwinner,sun50i-a64-usb-phy
- reg : a list of offset + length pairs
- reg-names :

View file

@ -29,7 +29,6 @@ Optional properties:
- vdda-pll-max-microamp : specifies max. load that can be drawn from pll supply
- vddp-ref-clk-supply : phandle to UFS device ref_clk pad power supply
- vddp-ref-clk-max-microamp : specifies max. load that can be drawn from this supply
- vddp-ref-clk-always-on : specifies if this supply needs to be kept always on
Example:

View file

@ -2,8 +2,8 @@ Allwinner sun4i A10 musb DRC/OTG controller
-------------------------------------------
Required properties:
- compatible : "allwinner,sun4i-a10-musb", "allwinner,sun6i-a31-musb"
or "allwinner,sun8i-a33-musb"
- compatible : "allwinner,sun4i-a10-musb", "allwinner,sun6i-a31-musb",
"allwinner,sun8i-a33-musb" or "allwinner,sun8i-h3-musb"
- reg : mmio address range of the musb controller
- clocks : clock specifier for the musb controller ahb gate clock
- reset : reset specifier for the ahb reset (A31 and newer only)

View file

@ -20,10 +20,10 @@ See: Documentation/devicetree/bindings/reset/reset.txt
with 'reg' property
- pinctl-names : A pinctrl state named "default" must be defined
See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- pinctrl-0 : Pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- ranges : allows valid 1:1 translation between child's address space and
parent's address space

View file

@ -56,6 +56,10 @@ Optional properties:
- <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.
- in addition all properties from usb-xhci.txt from the current directory are
supported as well
This is usually a subnode to DWC3 glue to which it is connected.
dwc3@4a030000 {

View file

@ -7,7 +7,7 @@ Required properties:
- interrupts : one EHCI interrupt should be described here
- pinctrl-names : a pinctrl state named "default" must be defined
- pinctrl-0 : phandle referencing pin configuration of the USB controller
See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- clocks : phandle list of usb clocks
- clock-names : should be "ic" for interconnect clock and "clk48"
See: Documentation/devicetree/bindings/clock/clock-bindings.txt

View file

@ -10,7 +10,7 @@ Required properties:
- vusb33-supply : regulator of USB avdd3.3v
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : must contain "sys_ck" for clock of controller;
- clock-names : must contain "sys_ck" and "ref_ck" for clock of controller;
"wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are
depends on "mediatek,enable-wakeup"
- phys : a list of phandle + phy specifier pairs
@ -30,7 +30,7 @@ Optional properties:
"id_float" and "id_ground" are optinal which depends on
"mediatek,enable-manual-drd"
- pinctrl-0 : pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- maximum-speed : valid arguments are "super-speed", "high-speed" and
"full-speed"; refer to usb/generic.txt
@ -56,10 +56,10 @@ ssusb: usb@11271000 {
phys = <&phy_port0 PHY_TYPE_USB3>,
<&phy_port1 PHY_TYPE_USB2>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>,
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
<&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB1>;
clock-names = "sys_ck",
clock-names = "sys_ck", "ref_ck",
"wakeup_deb_p0",
"wakeup_deb_p1";
vusb33-supply = <&mt6397_vusb_reg>;
@ -79,8 +79,8 @@ ssusb: usb@11271000 {
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>;
clock-names = "sys_ck";
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
status = "disabled";
};

View file

@ -23,6 +23,7 @@ Required properties:
entry in clock-names
- clock-names : must contain
"sys_ck": for clock of xHCI MAC
"ref_ck": for reference clock of xHCI MAC
"wakeup_deb_p0": for USB wakeup debounce clock of port0
"wakeup_deb_p1": for USB wakeup debounce clock of port1
@ -37,7 +38,7 @@ Optional properties:
- usb3-lpm-capable : supports USB3.0 LPM
- pinctrl-names : a pinctrl state named "default" must be defined
- pinctrl-0 : pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Example:
usb30: usb@11270000 {
@ -47,10 +48,10 @@ usb30: usb@11270000 {
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>,
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
<&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB1>;
clock-names = "sys_ck",
clock-names = "sys_ck", "ref_ck",
"wakeup_deb_p0",
"wakeup_deb_p1";
phys = <&phy_port0 PHY_TYPE_USB3>,
@ -67,7 +68,7 @@ usb30: usb@11270000 {
In the case, xhci is added as subnode to mtu3. An example and the DT binding
details of mtu3 can be found in:
Documentation/devicetree/bindings/usb/mtu3.txt
Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
Required properties:
- compatible : should contain "mediatek,mt8173-xhci"
@ -82,6 +83,7 @@ Required properties:
entry in clock-names
- clock-names : must be
"sys_ck": for clock of xHCI MAC
"ref_ck": for reference clock of xHCI MAC
Optional properties:
- vbus-supply : reference to the VBUS regulator;
@ -94,8 +96,8 @@ usb30: usb@11270000 {
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>;
clock-names = "sys_ck";
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
usb3-lpm-capable;
};

View file

@ -18,7 +18,7 @@ A child node must exist to represent the core DWC3 IP block. The name of
the node is not important. The content of the node is defined in dwc3.txt.
Phy documentation is provided in the following places:
Documentation/devicetree/bindings/phy/qcom,dwc3-usb-phy.txt
Documentation/devicetree/bindings/phy/qcom-dwc3-usb-phy.txt
Example device nodes:

View file

@ -0,0 +1,20 @@
ULPI bus binding
----------------
Phys that are behind a ULPI connection can be described with the following
binding. The host controller shall have a "ulpi" named node as a child, and
that node shall have one enabled node underneath it representing the ulpi
device on the bus.
EXAMPLE
-------
usb {
compatible = "vendor,usb-controller";
ulpi {
phy {
compatible = "vendor,phy";
};
};
};

View file

@ -27,6 +27,7 @@ Required properties:
Optional properties:
- clocks: reference to a clock
- usb3-lpm-capable: determines if platform is USB3 LPM capable
- quirk-broken-port-ped: set if the controller has broken port disable mechanism
Example:
usb@f0931000 {

View file

@ -0,0 +1,83 @@
Microchip USB 2.0 Hi-Speed Hub Controller
The device node for the configuration of a Microchip USB251xB/xBi USB 2.0
Hi-Speed Controller.
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"
- hub-reset-gpios : Should specify the gpio for hub reset
Optional properties :
- reg : I2C address on the selected bus (default is <0x2C>)
- skip-config : Skip Hub configuration, but only send the USB-Attach command
- vendor-id : USB Vendor ID of the hub (16 bit, default is 0x0424)
- product-id : USB Product ID of the hub (16 bit, default depends on type)
- device-id : USB Device ID of the hub (16 bit, default is 0x0bb3)
- language-id : USB Language ID (16 bit, default is 0x0000)
- manufacturer : USB Manufacturer string (max 31 characters long)
- product : USB Product string (max 31 characters long)
- serial : USB Serial string (max 31 characters long)
- {bus,self}-powered : selects between self- and bus-powered operation (default
is self-powered)
- disable-hi-speed : disable USB Hi-Speed support
- {multi,single}-tt : selects between multi- and single-transaction-translator
(default is multi-tt)
- disable-eop : disable End of Packet generation in full-speed mode
- {ganged,individual}-sensing : select over-current sense type in self-powered
mode (default is individual)
- {ganged,individual}-port-switching : select port power switching mode
(default is individual)
- dynamic-power-switching : enable auto-switching from self- to bus-powered
operation if the local power source is removed or unavailable
- oc-delay-{100us,4ms,8ms,16ms} : set over current timer delay (default is 8ms)
- compound-device : indicated the hub is part of a compound device
- port-mapping-mode : enable port mapping mode
- string-support : enable string descriptor support (required for manufacturer,
product and serial string configuration)
- non-removable-ports : Should specify the ports which have a non-removable
device connected.
- sp-disabled-ports : Specifies the ports which will be self-power disabled
- bp-disabled-ports : Specifies the ports which will be bus-power disabled
- max-sp-power : Specifies the maximum current the hub consumes from an
upstream port when operating as self-powered hub including the power
consumption of a permanently attached peripheral if the hub is
configured as a compound device. The value is given in mA in a 0 - 500
range (default is 2).
- max-bp-power : Specifies the maximum current the hub consumes from an
upstream port when operating as bus-powered hub including the power
consumption of a permanently attached peripheral if the hub is
configured as a compound device. The value is given in mA in a 0 - 500
range (default is 100).
- max-sp-current : Specifies the maximum current the hub consumes from an
upstream port when operating as self-powered hub EXCLUDING the power
consumption of a permanently attached peripheral if the hub is
configured as a compound device. The value is given in mA in a 0 - 500
range (default is 2).
- max-bp-current : Specifies the maximum current the hub consumes from an
upstream port when operating as bus-powered hub EXCLUDING the power
consumption of a permanently attached peripheral if the hub is
configured as a compound device. The value is given in mA in a 0 - 500
range (default is 100).
- power-on-time : Specifies the time it takes from the time the host initiates
the power-on sequence to a port until the port has adequate power. The
value is given in ms in a 0 - 510 range (default is 100ms).
Examples:
usb2512b@2c {
compatible = "microchip,usb2512b";
hub-reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
};
usb2514b@2c {
compatible = "microchip,usb2514b";
reg = <0x2c>;
reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
vendor-id = /bits/ 16 <0x0000>;
product-id = /bits/ 16 <0x0000>;
string-support;
manufacturer = "Foo";
product = "Foo-Bar";
serial = "1234567890A";
};

View file

@ -632,6 +632,8 @@ The uac2 function provides these attributes in its function directory:
p_chmask - playback channel mask
p_srate - playback sampling rate
p_ssize - playback sample size (bytes)
req_number - the number of pre-allocated request for both capture
and playback
The attributes have sane default values.

View file

@ -8233,6 +8233,14 @@ F: drivers/media/platform/atmel/atmel-isc.c
F: drivers/media/platform/atmel/atmel-isc-regs.h
F: devicetree/bindings/media/atmel-isc.txt
MICROCHIP USB251XB DRIVER
M: Richard Leitner <richard.leitner@skidata.com>
L: linux-usb@vger.kernel.org
S: Maintained
F: drivers/usb/misc/usb251xb.c
F: include/linux/platform_data/usb251xb.h
F: Documentation/devicetree/bindings/usb/usb251xb.txt
MICROSOFT SURFACE PRO 3 BUTTON DRIVER
M: Chen Yu <yu.c.chen@intel.com>
L: platform-driver-x86@vger.kernel.org

View file

@ -728,9 +728,11 @@
<&phy_port1 PHY_TYPE_USB2>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>,
<&clk26m>,
<&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB1>;
clock-names = "sys_ck",
"ref_ck",
"wakeup_deb_p0",
"wakeup_deb_p1";
mediatek,syscon-wakeup = <&pericfg>;
@ -745,8 +747,8 @@
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>;
clock-names = "sys_ck";
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
status = "disabled";
};
};

View file

@ -79,14 +79,6 @@
#define QMGR_QUEUE_C(n) (0x2008 + (n) * 0x10)
#define QMGR_QUEUE_D(n) (0x200c + (n) * 0x10)
/* Glue layer specific */
/* USBSS / USB AM335x */
#define USBSS_IRQ_STATUS 0x28
#define USBSS_IRQ_ENABLER 0x2c
#define USBSS_IRQ_CLEARR 0x30
#define USBSS_IRQ_PD_COMP (1 << 2)
/* Packet Descriptor */
#define PD2_ZERO_LENGTH (1 << 19)
@ -294,14 +286,8 @@ static irqreturn_t cppi41_irq(int irq, void *data)
{
struct cppi41_dd *cdd = data;
struct cppi41_channel *c;
u32 status;
int i;
status = cppi_readl(cdd->usbss_mem + USBSS_IRQ_STATUS);
if (!(status & USBSS_IRQ_PD_COMP))
return IRQ_NONE;
cppi_writel(status, cdd->usbss_mem + USBSS_IRQ_STATUS);
for (i = QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE); i < QMGR_NUM_PEND;
i++) {
u32 val;
@ -618,6 +604,7 @@ static void cppi41_compute_td_desc(struct cppi41_desc *d)
static int cppi41_tear_down_chan(struct cppi41_channel *c)
{
struct dmaengine_result abort_result;
struct cppi41_dd *cdd = c->cdd;
struct cppi41_desc *td;
u32 reg;
@ -701,6 +688,12 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
c->td_seen = 0;
c->td_desc_seen = 0;
cppi_writel(0, c->gcr_reg);
/* Invoke the callback to do the necessary clean-up */
abort_result.result = DMA_TRANS_ABORTED;
dma_cookie_complete(&c->txd);
dmaengine_desc_get_callback_invoke(&c->txd, &abort_result);
return 0;
}
@ -1066,8 +1059,6 @@ static int cppi41_dma_probe(struct platform_device *pdev)
goto err_irq;
}
cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER);
ret = devm_request_irq(&pdev->dev, irq, glue_info->isr, IRQF_SHARED,
dev_name(dev), cdd);
if (ret)
@ -1091,7 +1082,6 @@ err_of:
dma_async_device_unregister(&cdd->ddev);
err_dma_reg:
err_irq:
cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
cleanup_chans(cdd);
err_chans:
deinit_cppi41(dev, cdd);
@ -1119,7 +1109,6 @@ static int cppi41_dma_remove(struct platform_device *pdev)
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&cdd->ddev);
cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
devm_free_irq(&pdev->dev, cdd->irq, cdd);
cleanup_chans(cdd);
deinit_cppi41(&pdev->dev, cdd);
@ -1138,7 +1127,6 @@ static int __maybe_unused cppi41_suspend(struct device *dev)
struct cppi41_dd *cdd = dev_get_drvdata(dev);
cdd->dma_tdfdq = cppi_readl(cdd->ctrl_mem + DMA_TDFDQ);
cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
disable_sched(cdd);
return 0;
@ -1164,8 +1152,6 @@ static int __maybe_unused cppi41_resume(struct device *dev)
cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE);
cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE);
cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER);
return 0;
}

View file

@ -225,6 +225,30 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
return tsize;
}
EXPORT_SYMBOL_GPL(of_device_get_modalias);
int of_device_request_module(struct device *dev)
{
char *str;
ssize_t size;
int ret;
size = of_device_get_modalias(dev, NULL, 0);
if (size < 0)
return size;
str = kmalloc(size + 1, GFP_KERNEL);
if (!str)
return -ENOMEM;
of_device_get_modalias(dev, str, size);
str[size] = '\0';
ret = request_module(str);
kfree(str);
return ret;
}
EXPORT_SYMBOL_GPL(of_device_request_module);
/**
* of_device_uevent - Display OF related uevent information
@ -287,3 +311,4 @@ int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
EXPORT_SYMBOL_GPL(of_device_uevent_modalias);

View file

@ -363,6 +363,7 @@ config PHY_ROCKCHIP_INNO_USB2
tristate "Rockchip INNO USB2PHY Driver"
depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
depends on COMMON_CLK
depends on EXTCON
depends on USB_SUPPORT
select GENERIC_PHY
select USB_COMMON
@ -437,6 +438,21 @@ config PHY_QCOM_UFS
help
Support for UFS PHY on QCOM chipsets.
config PHY_QCOM_USB_HS
tristate "Qualcomm USB HS PHY module"
depends on USB_ULPI_BUS
select GENERIC_PHY
help
Support for the USB high-speed ULPI compliant phy on Qualcomm
chipsets.
config PHY_QCOM_USB_HSIC
tristate "Qualcomm USB HSIC ULPI PHY module"
depends on USB_ULPI_BUS
select GENERIC_PHY
help
Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.
config PHY_TUSB1210
tristate "TI TUSB1210 ULPI PHY module"
depends on USB_ULPI_BUS
@ -486,4 +502,12 @@ config PHY_MESON8B_USB2
and GXBB SoCs.
If unsure, say N.
config PHY_NSP_USB3
tristate "Broadcom NorthStar plus USB3 PHY driver"
depends on OF && (ARCH_BCM_NSP || COMPILE_TEST)
select GENERIC_PHY
default ARCH_BCM_NSP
help
Enable this to support the Broadcom Northstar plus USB3 PHY.
If unsure, say N.
endmenu

View file

@ -52,6 +52,8 @@ obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
@ -59,3 +61,4 @@ obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
obj-$(CONFIG_PHY_NSP_USB3) += phy-bcm-nsp-usb3.o

View file

@ -114,7 +114,7 @@ static int cygnus_pcie_phy_power_off(struct phy *p)
return cygnus_pcie_power_config(phy, false);
}
static struct phy_ops cygnus_pcie_phy_ops = {
static const struct phy_ops cygnus_pcie_phy_ops = {
.power_on = cygnus_pcie_phy_power_on,
.power_off = cygnus_pcie_phy_power_off,
.owner = THIS_MODULE,

View file

@ -0,0 +1,177 @@
/*
* Copyright (C) 2016 Broadcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#define NSP_USB3_RST_CTRL_OFFSET 0x3f8
/* mdio reg access */
#define NSP_USB3_PHY_BASE_ADDR_REG 0x1f
#define NSP_USB3_PHY_PLL30_BLOCK 0x8000
#define NSP_USB3_PLL_CONTROL 0x01
#define NSP_USB3_PLLA_CONTROL0 0x0a
#define NSP_USB3_PLLA_CONTROL1 0x0b
#define NSP_USB3_PHY_TX_PMD_BLOCK 0x8040
#define NSP_USB3_TX_PMD_CONTROL1 0x01
#define NSP_USB3_PHY_PIPE_BLOCK 0x8060
#define NSP_USB3_LFPS_CMP 0x02
#define NSP_USB3_LFPS_DEGLITCH 0x03
struct nsp_usb3_phy {
struct regmap *usb3_ctrl;
struct phy *phy;
struct mdio_device *mdiodev;
};
static int nsp_usb3_phy_init(struct phy *phy)
{
struct nsp_usb3_phy *iphy = phy_get_drvdata(phy);
struct mii_bus *bus = iphy->mdiodev->bus;
int addr = iphy->mdiodev->addr;
u32 data;
int rc;
rc = regmap_read(iphy->usb3_ctrl, 0, &data);
if (rc)
return rc;
data |= 1;
rc = regmap_write(iphy->usb3_ctrl, 0, data);
if (rc)
return rc;
rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 1);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
NSP_USB3_PHY_PLL30_BLOCK);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x1000);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL0, 0x6400);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0xc000);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0x8000);
if (rc)
return rc;
rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 0);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x9000);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
NSP_USB3_PHY_PIPE_BLOCK);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_CMP, 0xf30d);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_DEGLITCH, 0x6302);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
NSP_USB3_PHY_TX_PMD_BLOCK);
if (rc)
return rc;
rc = mdiobus_write(bus, addr, NSP_USB3_TX_PMD_CONTROL1, 0x1003);
return rc;
}
static struct phy_ops nsp_usb3_phy_ops = {
.init = nsp_usb3_phy_init,
.owner = THIS_MODULE,
};
static int nsp_usb3_phy_probe(struct mdio_device *mdiodev)
{
struct device *dev = &mdiodev->dev;
struct phy_provider *provider;
struct nsp_usb3_phy *iphy;
iphy = devm_kzalloc(dev, sizeof(*iphy), GFP_KERNEL);
if (!iphy)
return -ENOMEM;
iphy->mdiodev = mdiodev;
iphy->usb3_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
"usb3-ctrl-syscon");
if (IS_ERR(iphy->usb3_ctrl))
return PTR_ERR(iphy->usb3_ctrl);
iphy->phy = devm_phy_create(dev, dev->of_node, &nsp_usb3_phy_ops);
if (IS_ERR(iphy->phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(iphy->phy);
}
phy_set_drvdata(iphy->phy, iphy);
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(provider)) {
dev_err(dev, "could not register PHY provider\n");
return PTR_ERR(provider);
}
return 0;
}
static const struct of_device_id nsp_usb3_phy_of_match[] = {
{.compatible = "brcm,nsp-usb3-phy",},
{ /* sentinel */ }
};
static struct mdio_driver nsp_usb3_phy_driver = {
.mdiodrv = {
.driver = {
.name = "nsp-usb3-phy",
.of_match_table = nsp_usb3_phy_of_match,
},
},
.probe = nsp_usb3_phy_probe,
};
mdio_module_driver(nsp_usb3_phy_driver);
MODULE_DESCRIPTION("Broadcom NSP USB3 PHY driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com");

View file

@ -112,7 +112,7 @@ static int hi6220_phy_exit(struct phy *phy)
return hi6220_phy_setup(priv, false);
}
static struct phy_ops hi6220_phy_ops = {
static const struct phy_ops hi6220_phy_ops = {
.init = hi6220_phy_start,
.exit = hi6220_phy_exit,
.owner = THIS_MODULE,

View file

@ -506,7 +506,7 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
return instance->phy;
}
static struct phy_ops mt65xx_u3phy_ops = {
static const struct phy_ops mt65xx_u3phy_ops = {
.init = mt65xx_phy_init,
.exit = mt65xx_phy_exit,
.power_on = mt65xx_phy_power_on,

View file

@ -77,7 +77,6 @@ struct ufs_qcom_phy_vreg {
int min_uV;
int max_uV;
bool enabled;
bool is_always_on;
};
struct ufs_qcom_phy {

View file

@ -132,27 +132,18 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev)
&ufs_qcom_phy_qmp_14nm_phy_ops, &phy_14nm_ops);
if (!generic_phy) {
dev_err(dev, "%s: ufs_qcom_phy_generic_probe() failed\n",
__func__);
err = -EIO;
goto out;
}
err = ufs_qcom_phy_init_clks(phy_common);
if (err) {
dev_err(phy_common->dev,
"%s: ufs_qcom_phy_init_clks() failed %d\n",
__func__, err);
if (err)
goto out;
}
err = ufs_qcom_phy_init_vregulators(phy_common);
if (err) {
dev_err(phy_common->dev,
"%s: ufs_qcom_phy_init_vregulators() failed %d\n",
__func__, err);
if (err)
goto out;
}
phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV;
phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV;

View file

@ -190,25 +190,17 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev)
&ufs_qcom_phy_qmp_20nm_phy_ops, &phy_20nm_ops);
if (!generic_phy) {
dev_err(dev, "%s: ufs_qcom_phy_generic_probe() failed\n",
__func__);
err = -EIO;
goto out;
}
err = ufs_qcom_phy_init_clks(phy_common);
if (err) {
dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n",
__func__, err);
if (err)
goto out;
}
err = ufs_qcom_phy_init_vregulators(phy_common);
if (err) {
dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n",
__func__, err);
if (err)
goto out;
}
ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common);

View file

@ -189,12 +189,12 @@ int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common)
if (err)
goto out;
skip_txrx_clk:
err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_src",
&phy_common->ref_clk_src);
if (err)
goto out;
skip_txrx_clk:
/*
* "ref_clk_parent" is optional hence don't abort init if it's not
* found.
@ -210,25 +210,19 @@ out:
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks);
static int __ufs_qcom_phy_init_vreg(struct device *dev,
struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional)
static int ufs_qcom_phy_init_vreg(struct device *dev,
struct ufs_qcom_phy_vreg *vreg,
const char *name)
{
int err = 0;
char prop_name[MAX_PROP_NAME];
vreg->name = devm_kstrdup(dev, name, GFP_KERNEL);
if (!vreg->name) {
err = -ENOMEM;
goto out;
}
vreg->name = name;
vreg->reg = devm_regulator_get(dev, name);
if (IS_ERR(vreg->reg)) {
err = PTR_ERR(vreg->reg);
vreg->reg = NULL;
if (!optional)
dev_err(dev, "failed to get %s, %d\n", name, err);
dev_err(dev, "failed to get %s, %d\n", name, err);
goto out;
}
@ -248,9 +242,6 @@ static int __ufs_qcom_phy_init_vreg(struct device *dev,
}
err = 0;
}
snprintf(prop_name, MAX_PROP_NAME, "%s-always-on", name);
vreg->is_always_on = of_property_read_bool(dev->of_node,
prop_name);
}
if (!strcmp(name, "vdda-pll")) {
@ -265,17 +256,9 @@ static int __ufs_qcom_phy_init_vreg(struct device *dev,
}
out:
if (err)
kfree(vreg->name);
return err;
}
static int ufs_qcom_phy_init_vreg(struct device *dev,
struct ufs_qcom_phy_vreg *vreg, const char *name)
{
return __ufs_qcom_phy_init_vreg(dev, vreg, name, false);
}
int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common)
{
int err;
@ -291,9 +274,9 @@ int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common)
if (err)
goto out;
/* vddp-ref-clk-* properties are optional */
__ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk,
"vddp-ref-clk", true);
err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk,
"vddp-ref-clk");
out:
return err;
}
@ -416,7 +399,7 @@ static int ufs_qcom_phy_disable_vreg(struct device *dev,
{
int ret = 0;
if (!vreg || !vreg->enabled || vreg->is_always_on)
if (!vreg || !vreg->enabled)
goto out;
ret = regulator_disable(vreg->reg);

View file

@ -0,0 +1,296 @@
/**
* Copyright (C) 2016 Linaro Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/ulpi/driver.h>
#include <linux/ulpi/regs.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of_device.h>
#include <linux/reset.h>
#include <linux/extcon.h>
#include <linux/notifier.h>
#include "ulpi_phy.h"
#define ULPI_PWR_CLK_MNG_REG 0x88
# define ULPI_PWR_OTG_COMP_DISABLE BIT(0)
#define ULPI_MISC_A 0x96
# define ULPI_MISC_A_VBUSVLDEXTSEL BIT(1)
# define ULPI_MISC_A_VBUSVLDEXT BIT(0)
struct ulpi_seq {
u8 addr;
u8 val;
};
struct qcom_usb_hs_phy {
struct ulpi *ulpi;
struct phy *phy;
struct clk *ref_clk;
struct clk *sleep_clk;
struct regulator *v1p8;
struct regulator *v3p3;
struct reset_control *reset;
struct ulpi_seq *init_seq;
struct extcon_dev *vbus_edev;
struct notifier_block vbus_notify;
};
static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode)
{
struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
u8 addr;
int ret;
if (!uphy->vbus_edev) {
u8 val = 0;
switch (mode) {
case PHY_MODE_USB_OTG:
case PHY_MODE_USB_HOST:
val |= ULPI_INT_IDGRD;
case PHY_MODE_USB_DEVICE:
val |= ULPI_INT_SESS_VALID;
default:
break;
}
ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_RISE, val);
if (ret)
return ret;
ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_FALL, val);
} else {
switch (mode) {
case PHY_MODE_USB_OTG:
case PHY_MODE_USB_DEVICE:
addr = ULPI_SET(ULPI_MISC_A);
break;
case PHY_MODE_USB_HOST:
addr = ULPI_CLR(ULPI_MISC_A);
break;
default:
return -EINVAL;
}
ret = ulpi_write(uphy->ulpi, ULPI_SET(ULPI_PWR_CLK_MNG_REG),
ULPI_PWR_OTG_COMP_DISABLE);
if (ret)
return ret;
ret = ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXTSEL);
}
return ret;
}
static int
qcom_usb_hs_phy_vbus_notifier(struct notifier_block *nb, unsigned long event,
void *ptr)
{
struct qcom_usb_hs_phy *uphy;
u8 addr;
uphy = container_of(nb, struct qcom_usb_hs_phy, vbus_notify);
if (event)
addr = ULPI_SET(ULPI_MISC_A);
else
addr = ULPI_CLR(ULPI_MISC_A);
return ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXT);
}
static int qcom_usb_hs_phy_power_on(struct phy *phy)
{
struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
struct ulpi *ulpi = uphy->ulpi;
const struct ulpi_seq *seq;
int ret, state;
ret = clk_prepare_enable(uphy->ref_clk);
if (ret)
return ret;
ret = clk_prepare_enable(uphy->sleep_clk);
if (ret)
goto err_sleep;
ret = regulator_set_load(uphy->v1p8, 50000);
if (ret < 0)
goto err_1p8;
ret = regulator_enable(uphy->v1p8);
if (ret)
goto err_1p8;
ret = regulator_set_voltage_triplet(uphy->v3p3, 3050000, 3300000,
3300000);
if (ret)
goto err_3p3;
ret = regulator_set_load(uphy->v3p3, 50000);
if (ret < 0)
goto err_3p3;
ret = regulator_enable(uphy->v3p3);
if (ret)
goto err_3p3;
for (seq = uphy->init_seq; seq->addr; seq++) {
ret = ulpi_write(ulpi, ULPI_EXT_VENDOR_SPECIFIC + seq->addr,
seq->val);
if (ret)
goto err_ulpi;
}
if (uphy->reset) {
ret = reset_control_reset(uphy->reset);
if (ret)
goto err_ulpi;
}
if (uphy->vbus_edev) {
state = extcon_get_cable_state_(uphy->vbus_edev, EXTCON_USB);
/* setup initial state */
qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
uphy->vbus_edev);
ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB,
&uphy->vbus_notify);
if (ret)
goto err_ulpi;
}
return 0;
err_ulpi:
regulator_disable(uphy->v3p3);
err_3p3:
regulator_disable(uphy->v1p8);
err_1p8:
clk_disable_unprepare(uphy->sleep_clk);
err_sleep:
clk_disable_unprepare(uphy->ref_clk);
return ret;
}
static int qcom_usb_hs_phy_power_off(struct phy *phy)
{
int ret;
struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
if (uphy->vbus_edev) {
ret = extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB,
&uphy->vbus_notify);
if (ret)
return ret;
}
regulator_disable(uphy->v3p3);
regulator_disable(uphy->v1p8);
clk_disable_unprepare(uphy->sleep_clk);
clk_disable_unprepare(uphy->ref_clk);
return 0;
}
static const struct phy_ops qcom_usb_hs_phy_ops = {
.power_on = qcom_usb_hs_phy_power_on,
.power_off = qcom_usb_hs_phy_power_off,
.set_mode = qcom_usb_hs_phy_set_mode,
.owner = THIS_MODULE,
};
static int qcom_usb_hs_phy_probe(struct ulpi *ulpi)
{
struct qcom_usb_hs_phy *uphy;
struct phy_provider *p;
struct clk *clk;
struct regulator *reg;
struct reset_control *reset;
int size;
int ret;
uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
if (!uphy)
return -ENOMEM;
ulpi_set_drvdata(ulpi, uphy);
uphy->ulpi = ulpi;
size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq");
if (size < 0)
size = 0;
uphy->init_seq = devm_kmalloc_array(&ulpi->dev, (size / 2) + 1,
sizeof(*uphy->init_seq), GFP_KERNEL);
if (!uphy->init_seq)
return -ENOMEM;
ret = of_property_read_u8_array(ulpi->dev.of_node, "qcom,init-seq",
(u8 *)uphy->init_seq, size);
if (ret && size)
return ret;
/* NUL terminate */
uphy->init_seq[size / 2].addr = uphy->init_seq[size / 2].val = 0;
uphy->ref_clk = clk = devm_clk_get(&ulpi->dev, "ref");
if (IS_ERR(clk))
return PTR_ERR(clk);
uphy->sleep_clk = clk = devm_clk_get(&ulpi->dev, "sleep");
if (IS_ERR(clk))
return PTR_ERR(clk);
uphy->v1p8 = reg = devm_regulator_get(&ulpi->dev, "v1p8");
if (IS_ERR(reg))
return PTR_ERR(reg);
uphy->v3p3 = reg = devm_regulator_get(&ulpi->dev, "v3p3");
if (IS_ERR(reg))
return PTR_ERR(reg);
uphy->reset = reset = devm_reset_control_get(&ulpi->dev, "por");
if (IS_ERR(reset)) {
if (PTR_ERR(reset) == -EPROBE_DEFER)
return PTR_ERR(reset);
uphy->reset = NULL;
}
uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
&qcom_usb_hs_phy_ops);
if (IS_ERR(uphy->phy))
return PTR_ERR(uphy->phy);
uphy->vbus_edev = extcon_get_edev_by_phandle(&ulpi->dev, 0);
if (IS_ERR(uphy->vbus_edev)) {
if (PTR_ERR(uphy->vbus_edev) != -ENODEV)
return PTR_ERR(uphy->vbus_edev);
uphy->vbus_edev = NULL;
}
uphy->vbus_notify.notifier_call = qcom_usb_hs_phy_vbus_notifier;
phy_set_drvdata(uphy->phy, uphy);
p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(p);
}
static const struct of_device_id qcom_usb_hs_phy_match[] = {
{ .compatible = "qcom,usb-hs-phy", },
{ }
};
MODULE_DEVICE_TABLE(of, qcom_usb_hs_phy_match);
static struct ulpi_driver qcom_usb_hs_phy_driver = {
.probe = qcom_usb_hs_phy_probe,
.driver = {
.name = "qcom_usb_hs_phy",
.of_match_table = qcom_usb_hs_phy_match,
},
};
module_ulpi_driver(qcom_usb_hs_phy_driver);
MODULE_DESCRIPTION("Qualcomm USB HS phy");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,160 @@
/**
* Copyright (C) 2016 Linaro Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/ulpi/driver.h>
#include <linux/ulpi/regs.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl-state.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include "ulpi_phy.h"
#define ULPI_HSIC_CFG 0x30
#define ULPI_HSIC_IO_CAL 0x33
struct qcom_usb_hsic_phy {
struct ulpi *ulpi;
struct phy *phy;
struct pinctrl *pctl;
struct clk *phy_clk;
struct clk *cal_clk;
struct clk *cal_sleep_clk;
};
static int qcom_usb_hsic_phy_power_on(struct phy *phy)
{
struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
struct ulpi *ulpi = uphy->ulpi;
struct pinctrl_state *pins_default;
int ret;
ret = clk_prepare_enable(uphy->phy_clk);
if (ret)
return ret;
ret = clk_prepare_enable(uphy->cal_clk);
if (ret)
goto err_cal;
ret = clk_prepare_enable(uphy->cal_sleep_clk);
if (ret)
goto err_sleep;
/* Set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
ret = ulpi_write(ulpi, ULPI_HSIC_IO_CAL, 0xff);
if (ret)
goto err_ulpi;
/* Enable periodic IO calibration in HSIC_CFG register */
ret = ulpi_write(ulpi, ULPI_HSIC_CFG, 0xa8);
if (ret)
goto err_ulpi;
/* Configure pins for HSIC functionality */
pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT);
if (IS_ERR(pins_default))
return PTR_ERR(pins_default);
ret = pinctrl_select_state(uphy->pctl, pins_default);
if (ret)
goto err_ulpi;
/* Enable HSIC mode in HSIC_CFG register */
ret = ulpi_write(ulpi, ULPI_SET(ULPI_HSIC_CFG), 0x01);
if (ret)
goto err_ulpi;
/* Disable auto-resume */
ret = ulpi_write(ulpi, ULPI_CLR(ULPI_IFC_CTRL),
ULPI_IFC_CTRL_AUTORESUME);
if (ret)
goto err_ulpi;
return ret;
err_ulpi:
clk_disable_unprepare(uphy->cal_sleep_clk);
err_sleep:
clk_disable_unprepare(uphy->cal_clk);
err_cal:
clk_disable_unprepare(uphy->phy_clk);
return ret;
}
static int qcom_usb_hsic_phy_power_off(struct phy *phy)
{
struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
clk_disable_unprepare(uphy->cal_sleep_clk);
clk_disable_unprepare(uphy->cal_clk);
clk_disable_unprepare(uphy->phy_clk);
return 0;
}
static const struct phy_ops qcom_usb_hsic_phy_ops = {
.power_on = qcom_usb_hsic_phy_power_on,
.power_off = qcom_usb_hsic_phy_power_off,
.owner = THIS_MODULE,
};
static int qcom_usb_hsic_phy_probe(struct ulpi *ulpi)
{
struct qcom_usb_hsic_phy *uphy;
struct phy_provider *p;
struct clk *clk;
uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
if (!uphy)
return -ENOMEM;
ulpi_set_drvdata(ulpi, uphy);
uphy->ulpi = ulpi;
uphy->pctl = devm_pinctrl_get(&ulpi->dev);
if (IS_ERR(uphy->pctl))
return PTR_ERR(uphy->pctl);
uphy->phy_clk = clk = devm_clk_get(&ulpi->dev, "phy");
if (IS_ERR(clk))
return PTR_ERR(clk);
uphy->cal_clk = clk = devm_clk_get(&ulpi->dev, "cal");
if (IS_ERR(clk))
return PTR_ERR(clk);
uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
if (IS_ERR(clk))
return PTR_ERR(clk);
uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
&qcom_usb_hsic_phy_ops);
if (IS_ERR(uphy->phy))
return PTR_ERR(uphy->phy);
phy_set_drvdata(uphy->phy, uphy);
p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(p);
}
static const struct of_device_id qcom_usb_hsic_phy_match[] = {
{ .compatible = "qcom,usb-hsic-phy", },
{ }
};
MODULE_DEVICE_TABLE(of, qcom_usb_hsic_phy_match);
static struct ulpi_driver qcom_usb_hsic_phy_driver = {
.probe = qcom_usb_hsic_phy_probe,
.driver = {
.name = "qcom_usb_hsic_phy",
.of_match_table = qcom_usb_hsic_phy_match,
},
};
module_ulpi_driver(qcom_usb_hsic_phy_driver);
MODULE_DESCRIPTION("Qualcomm USB HSIC phy");
MODULE_LICENSE("GPL v2");

View file

@ -94,11 +94,11 @@ static void rcar_gen3_phy_usb2_work(struct work_struct *work)
work);
if (ch->extcon_host) {
extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, true);
extcon_set_cable_state_(ch->extcon, EXTCON_USB, false);
extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true);
extcon_set_state_sync(ch->extcon, EXTCON_USB, false);
} else {
extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, false);
extcon_set_cable_state_(ch->extcon, EXTCON_USB, true);
extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false);
extcon_set_state_sync(ch->extcon, EXTCON_USB, true);
}
}
@ -350,7 +350,7 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p)
return ret;
}
static struct phy_ops rcar_gen3_phy_usb2_ops = {
static const struct phy_ops rcar_gen3_phy_usb2_ops = {
.init = rcar_gen3_phy_usb2_init,
.exit = rcar_gen3_phy_usb2_exit,
.power_on = rcar_gen3_phy_usb2_power_on,

View file

@ -595,9 +595,14 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
if (rport->vbus_attached != vbus_attach) {
rport->vbus_attached = vbus_attach;
if (notify_charger && rphy->edev)
if (notify_charger && rphy->edev) {
extcon_set_cable_state_(rphy->edev,
cable, vbus_attach);
if (cable == EXTCON_CHG_USB_SDP)
extcon_set_state_sync(rphy->edev,
EXTCON_USB,
vbus_attach);
}
}
break;
case OTG_STATE_B_PERIPHERAL:

View file

@ -99,6 +99,7 @@ enum sun4i_usb_phy_type {
sun6i_a31_phy,
sun8i_a33_phy,
sun8i_h3_phy,
sun8i_v3s_phy,
sun50i_a64_phy,
};
@ -188,7 +189,8 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
spin_lock_irqsave(&phy_data->reg_lock, flags);
if (phy_data->cfg->type == sun8i_a33_phy ||
phy_data->cfg->type == sun50i_a64_phy) {
phy_data->cfg->type == sun50i_a64_phy ||
phy_data->cfg->type == sun8i_v3s_phy) {
/* A33 or A64 needs us to set phyctl to 0 explicitly */
writel(0, phyctl);
}
@ -534,7 +536,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
mutex_unlock(&phy0->mutex);
if (id_notify) {
extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST,
extcon_set_state_sync(data->extcon, EXTCON_USB_HOST,
!id_det);
/* When leaving host mode force end the session here */
if (force_session_end && id_det == 1) {
@ -547,7 +549,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
}
if (vbus_notify)
extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
extcon_set_state_sync(data->extcon, EXTCON_USB, vbus_det);
if (sun4i_usb_phy0_poll(data))
queue_delayed_work(system_wq, &data->detect, POLL_TIME);
@ -825,6 +827,15 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
.enable_pmu_unk1 = true,
};
static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
.num_phys = 1,
.type = sun8i_v3s_phy,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
.enable_pmu_unk1 = true,
};
static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
.num_phys = 2,
.type = sun50i_a64_phy,
@ -842,6 +853,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
{ .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
{ .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
{ .compatible = "allwinner,sun50i-a64-usb-phy",
.data = &sun50i_a64_cfg},
{ },

View file

@ -2,6 +2,7 @@ config USB_CHIPIDEA
tristate "ChipIdea Highspeed Dual Role Controller"
depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA
select EXTCON
select RESET_CONTROLLER
help
Say Y here if your system has a dual role high speed USB
controller based on ChipIdea silicon IP. It supports:
@ -38,4 +39,11 @@ config USB_CHIPIDEA_HOST
Say Y here to enable host controller functionality of the
ChipIdea driver.
config USB_CHIPIDEA_ULPI
bool "ChipIdea ULPI PHY support"
depends on USB_ULPI_BUS=y || USB_ULPI_BUS=USB_CHIPIDEA
help
Say Y here if you have a ULPI PHY attached to your ChipIdea
controller.
endif

View file

@ -4,6 +4,7 @@ ci_hdrc-y := core.o otg.o debug.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
ci_hdrc-$(CONFIG_USB_OTG_FSM) += otg_fsm.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_ULPI) += ulpi.o
# Glue/Bridge layers go here

View file

@ -18,6 +18,8 @@
#include <linux/usb.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg-fsm.h>
#include <linux/usb/otg.h>
#include <linux/ulpi/interface.h>
/******************************************************************************
* DEFINE
@ -52,6 +54,7 @@ enum ci_hw_regs {
OP_ENDPTLISTADDR,
OP_TTCTRL,
OP_BURSTSIZE,
OP_ULPI_VIEWPORT,
OP_PORTSC,
OP_DEVLC,
OP_OTGSC,
@ -187,6 +190,8 @@ struct hw_bank {
* @test_mode: the selected test mode
* @platdata: platform specific information supplied by parent device
* @vbus_active: is VBUS active
* @ulpi: pointer to ULPI device, if any
* @ulpi_ops: ULPI read/write ops for this device
* @phy: pointer to PHY, if any
* @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework
* @hcd: pointer to usb_hcd for ehci host driver
@ -236,6 +241,10 @@ struct ci_hdrc {
struct ci_hdrc_platform_data *platdata;
int vbus_active;
#ifdef CONFIG_USB_CHIPIDEA_ULPI
struct ulpi *ulpi;
struct ulpi_ops ulpi_ops;
#endif
struct phy *phy;
/* old usb_phy interface */
struct usb_phy *usb_phy;
@ -418,6 +427,16 @@ static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci)
#endif
}
#if IS_ENABLED(CONFIG_USB_CHIPIDEA_ULPI)
int ci_ulpi_init(struct ci_hdrc *ci);
void ci_ulpi_exit(struct ci_hdrc *ci);
int ci_ulpi_resume(struct ci_hdrc *ci);
#else
static inline int ci_ulpi_init(struct ci_hdrc *ci) { return 0; }
static inline void ci_ulpi_exit(struct ci_hdrc *ci) { }
static inline int ci_ulpi_resume(struct ci_hdrc *ci) { return 0; }
#endif
u32 hw_read_intr_enable(struct ci_hdrc *ci);
u32 hw_read_intr_status(struct ci_hdrc *ci);
@ -428,8 +447,7 @@ int hw_port_test_set(struct ci_hdrc *ci, u8 mode);
u8 hw_port_test_get(struct ci_hdrc *ci);
int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
u32 value, unsigned int timeout_ms);
void hw_phymode_configure(struct ci_hdrc *ci);
void ci_platform_configure(struct ci_hdrc *ci);

View file

@ -8,90 +8,292 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/usb/ulpi.h>
#include <linux/usb/gadget.h>
#include <linux/usb/chipidea.h>
#include <linux/clk.h>
#include <linux/reset.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/io.h>
#include <linux/reset-controller.h>
#include <linux/extcon.h>
#include <linux/of.h>
#include "ci.h"
#define MSM_USB_BASE (ci->hw_bank.abs)
#define HS_PHY_AHB_MODE 0x0098
static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
#define HS_PHY_GENCONFIG 0x009c
#define HS_PHY_TXFIFO_IDLE_FORCE_DIS BIT(4)
#define HS_PHY_GENCONFIG_2 0x00a0
#define HS_PHY_SESS_VLD_CTRL_EN BIT(7)
#define HS_PHY_ULPI_TX_PKT_EN_CLR_FIX BIT(19)
#define HSPHY_SESS_VLD_CTRL BIT(25)
/* Vendor base starts at 0x200 beyond CI base */
#define HS_PHY_CTRL 0x0040
#define HS_PHY_SEC_CTRL 0x0078
#define HS_PHY_DIG_CLAMP_N BIT(16)
#define HS_PHY_POR_ASSERT BIT(0)
struct ci_hdrc_msm {
struct platform_device *ci;
struct clk *core_clk;
struct clk *iface_clk;
struct clk *fs_clk;
struct ci_hdrc_platform_data pdata;
struct reset_controller_dev rcdev;
bool secondary_phy;
bool hsic;
void __iomem *base;
};
static int
ci_hdrc_msm_por_reset(struct reset_controller_dev *r, unsigned long id)
{
struct device *dev = ci->gadget.dev.parent;
struct ci_hdrc_msm *ci_msm = container_of(r, struct ci_hdrc_msm, rcdev);
void __iomem *addr = ci_msm->base;
u32 val;
if (id)
addr += HS_PHY_SEC_CTRL;
else
addr += HS_PHY_CTRL;
val = readl_relaxed(addr);
val |= HS_PHY_POR_ASSERT;
writel(val, addr);
/*
* wait for minimum 10 microseconds as suggested by manual.
* Use a slightly larger value since the exact value didn't
* work 100% of the time.
*/
udelay(12);
val &= ~HS_PHY_POR_ASSERT;
writel(val, addr);
return 0;
}
static const struct reset_control_ops ci_hdrc_msm_reset_ops = {
.reset = ci_hdrc_msm_por_reset,
};
static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
{
struct device *dev = ci->dev->parent;
struct ci_hdrc_msm *msm_ci = dev_get_drvdata(dev);
int ret;
switch (event) {
case CI_HDRC_CONTROLLER_RESET_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
writel(0, USB_AHBBURST);
hw_phymode_configure(ci);
if (msm_ci->secondary_phy) {
u32 val = readl_relaxed(msm_ci->base + HS_PHY_SEC_CTRL);
val |= HS_PHY_DIG_CLAMP_N;
writel_relaxed(val, msm_ci->base + HS_PHY_SEC_CTRL);
}
ret = phy_init(ci->phy);
if (ret)
return ret;
ret = phy_power_on(ci->phy);
if (ret) {
phy_exit(ci->phy);
return ret;
}
/* use AHB transactor, allow posted data writes */
writel(0x8, USB_AHBMODE);
usb_phy_init(ci->usb_phy);
hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
/* workaround for rx buffer collision issue */
hw_write_id_reg(ci, HS_PHY_GENCONFIG,
HS_PHY_TXFIFO_IDLE_FORCE_DIS, 0);
if (!msm_ci->hsic)
hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
HS_PHY_ULPI_TX_PKT_EN_CLR_FIX, 0);
if (!IS_ERR(ci->platdata->vbus_extcon.edev)) {
hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
HS_PHY_SESS_VLD_CTRL_EN,
HS_PHY_SESS_VLD_CTRL_EN);
hw_write(ci, OP_USBCMD, HSPHY_SESS_VLD_CTRL,
HSPHY_SESS_VLD_CTRL);
}
break;
case CI_HDRC_CONTROLLER_STOPPED_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
/*
* Put the phy in non-driving mode. Otherwise host
* may not detect soft-disconnection.
*/
usb_phy_notify_disconnect(ci->usb_phy, USB_SPEED_UNKNOWN);
phy_power_off(ci->phy);
phy_exit(ci->phy);
break;
default:
dev_dbg(dev, "unknown ci_hdrc event\n");
break;
}
}
static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
.name = "ci_hdrc_msm",
.capoffset = DEF_CAPOFFSET,
.flags = CI_HDRC_REGS_SHARED |
CI_HDRC_DISABLE_STREAMING,
.notify_event = ci_hdrc_msm_notify_event,
};
static int ci_hdrc_msm_probe(struct platform_device *pdev)
{
struct platform_device *plat_ci;
struct usb_phy *phy;
dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
/*
* OTG(PHY) driver takes care of PHY initialization, clock management,
* powering up VBUS, mapping of registers address space and power
* management.
*/
phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
if (IS_ERR(phy))
return PTR_ERR(phy);
ci_hdrc_msm_platdata.usb_phy = phy;
plat_ci = ci_hdrc_add_device(&pdev->dev,
pdev->resource, pdev->num_resources,
&ci_hdrc_msm_platdata);
if (IS_ERR(plat_ci)) {
dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
return PTR_ERR(plat_ci);
}
platform_set_drvdata(pdev, plat_ci);
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
}
static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci,
struct platform_device *pdev)
{
struct regmap *regmap;
struct device *dev = &pdev->dev;
struct of_phandle_args args;
u32 val;
int ret;
ret = of_parse_phandle_with_fixed_args(dev->of_node, "phy-select", 2, 0,
&args);
if (ret)
return 0;
regmap = syscon_node_to_regmap(args.np);
of_node_put(args.np);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
ret = regmap_write(regmap, args.args[0], args.args[1]);
if (ret)
return ret;
ci->secondary_phy = !!args.args[1];
if (ci->secondary_phy) {
val = readl_relaxed(ci->base + HS_PHY_SEC_CTRL);
val |= HS_PHY_DIG_CLAMP_N;
writel_relaxed(val, ci->base + HS_PHY_SEC_CTRL);
}
return 0;
}
static int ci_hdrc_msm_probe(struct platform_device *pdev)
{
struct ci_hdrc_msm *ci;
struct platform_device *plat_ci;
struct clk *clk;
struct reset_control *reset;
struct resource *res;
int ret;
struct device_node *ulpi_node, *phy_node;
dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL);
if (!ci)
return -ENOMEM;
platform_set_drvdata(pdev, ci);
ci->pdata.name = "ci_hdrc_msm";
ci->pdata.capoffset = DEF_CAPOFFSET;
ci->pdata.flags = CI_HDRC_REGS_SHARED | CI_HDRC_DISABLE_STREAMING |
CI_HDRC_OVERRIDE_AHB_BURST |
CI_HDRC_OVERRIDE_PHY_CONTROL;
ci->pdata.notify_event = ci_hdrc_msm_notify_event;
reset = devm_reset_control_get(&pdev->dev, "core");
if (IS_ERR(reset))
return PTR_ERR(reset);
ci->core_clk = clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(clk))
return PTR_ERR(clk);
ci->iface_clk = clk = devm_clk_get(&pdev->dev, "iface");
if (IS_ERR(clk))
return PTR_ERR(clk);
ci->fs_clk = clk = devm_clk_get(&pdev->dev, "fs");
if (IS_ERR(clk)) {
if (PTR_ERR(clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
ci->fs_clk = NULL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
ci->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ci->base))
return PTR_ERR(ci->base);
ci->rcdev.owner = THIS_MODULE;
ci->rcdev.ops = &ci_hdrc_msm_reset_ops;
ci->rcdev.of_node = pdev->dev.of_node;
ci->rcdev.nr_resets = 2;
ret = reset_controller_register(&ci->rcdev);
if (ret)
return ret;
ret = clk_prepare_enable(ci->fs_clk);
if (ret)
goto err_fs;
reset_control_assert(reset);
usleep_range(10000, 12000);
reset_control_deassert(reset);
clk_disable_unprepare(ci->fs_clk);
ret = clk_prepare_enable(ci->core_clk);
if (ret)
goto err_fs;
ret = clk_prepare_enable(ci->iface_clk);
if (ret)
goto err_iface;
ret = ci_hdrc_msm_mux_phy(ci, pdev);
if (ret)
goto err_mux;
ulpi_node = of_find_node_by_name(pdev->dev.of_node, "ulpi");
if (ulpi_node) {
phy_node = of_get_next_available_child(ulpi_node, NULL);
ci->hsic = of_device_is_compatible(phy_node, "qcom,usb-hsic-phy");
of_node_put(phy_node);
}
of_node_put(ulpi_node);
plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
pdev->num_resources, &ci->pdata);
if (IS_ERR(plat_ci)) {
ret = PTR_ERR(plat_ci);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
goto err_mux;
}
ci->ci = plat_ci;
pm_runtime_set_active(&pdev->dev);
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
err_mux:
clk_disable_unprepare(ci->iface_clk);
err_iface:
clk_disable_unprepare(ci->core_clk);
err_fs:
reset_controller_unregister(&ci->rcdev);
return ret;
}
static int ci_hdrc_msm_remove(struct platform_device *pdev)
{
struct platform_device *plat_ci = platform_get_drvdata(pdev);
struct ci_hdrc_msm *ci = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
ci_hdrc_remove_device(plat_ci);
ci_hdrc_remove_device(ci->ci);
clk_disable_unprepare(ci->iface_clk);
clk_disable_unprepare(ci->core_clk);
reset_controller_unregister(&ci->rcdev);
return 0;
}

View file

@ -74,10 +74,6 @@ static int ci_hdrc_usb2_probe(struct platform_device *pdev)
}
}
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
goto clk_err;
ci_pdata->name = dev_name(dev);
priv->ci_pdev = ci_hdrc_add_device(dev, pdev->resource,

View file

@ -62,7 +62,6 @@
#include <linux/usb/chipidea.h>
#include <linux/usb/of.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/regulator/consumer.h>
#include <linux/usb/ehci_def.h>
@ -86,6 +85,7 @@ static const u8 ci_regs_nolpm[] = {
[OP_ENDPTLISTADDR] = 0x18U,
[OP_TTCTRL] = 0x1CU,
[OP_BURSTSIZE] = 0x20U,
[OP_ULPI_VIEWPORT] = 0x30U,
[OP_PORTSC] = 0x44U,
[OP_DEVLC] = 0x84U,
[OP_OTGSC] = 0x64U,
@ -110,6 +110,7 @@ static const u8 ci_regs_lpm[] = {
[OP_ENDPTLISTADDR] = 0x18U,
[OP_TTCTRL] = 0x1CU,
[OP_BURSTSIZE] = 0x20U,
[OP_ULPI_VIEWPORT] = 0x30U,
[OP_PORTSC] = 0x44U,
[OP_DEVLC] = 0x84U,
[OP_OTGSC] = 0xC4U,
@ -285,7 +286,7 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
return 0;
}
static void hw_phymode_configure(struct ci_hdrc *ci)
void hw_phymode_configure(struct ci_hdrc *ci)
{
u32 portsc, lpm, sts = 0;
@ -325,6 +326,7 @@ static void hw_phymode_configure(struct ci_hdrc *ci)
hw_write(ci, OP_PORTSC, PORTSC_STS, PORTSC_STS);
}
}
EXPORT_SYMBOL_GPL(hw_phymode_configure);
/**
* _ci_usb_phy_init: initialize phy taking in account both phy and usb_phy
@ -361,6 +363,9 @@ static int _ci_usb_phy_init(struct ci_hdrc *ci)
*/
static void ci_usb_phy_exit(struct ci_hdrc *ci)
{
if (ci->platdata->flags & CI_HDRC_OVERRIDE_PHY_CONTROL)
return;
if (ci->phy) {
phy_power_off(ci->phy);
phy_exit(ci->phy);
@ -379,6 +384,9 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
{
int ret;
if (ci->platdata->flags & CI_HDRC_OVERRIDE_PHY_CONTROL)
return 0;
switch (ci->platdata->phy_mode) {
case USBPHY_INTERFACE_MODE_UTMI:
case USBPHY_INTERFACE_MODE_UTMIW:
@ -419,13 +427,21 @@ void ci_platform_configure(struct ci_hdrc *ci)
is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC;
is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC;
if (is_device_mode &&
(ci->platdata->flags & CI_HDRC_DISABLE_DEVICE_STREAMING))
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
if (is_device_mode) {
phy_set_mode(ci->phy, PHY_MODE_USB_DEVICE);
if (is_host_mode &&
(ci->platdata->flags & CI_HDRC_DISABLE_HOST_STREAMING))
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
if (ci->platdata->flags & CI_HDRC_DISABLE_DEVICE_STREAMING)
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS,
USBMODE_CI_SDIS);
}
if (is_host_mode) {
phy_set_mode(ci->phy, PHY_MODE_USB_HOST);
if (ci->platdata->flags & CI_HDRC_DISABLE_HOST_STREAMING)
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS,
USBMODE_CI_SDIS);
}
if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) {
if (ci->hw_bank.lpm)
@ -495,9 +511,12 @@ int hw_device_reset(struct ci_hdrc *ci)
return ret;
}
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
if (ci->platdata->notify_event) {
ret = ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_RESET_EVENT);
if (ret)
return ret;
}
/* USBMODE should be configured step by step */
hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
@ -516,38 +535,6 @@ int hw_device_reset(struct ci_hdrc *ci)
return 0;
}
/**
* hw_wait_reg: wait the register value
*
* Sometimes, it needs to wait register value before going on.
* Eg, when switch to device mode, the vbus value should be lower
* than OTGSC_BSV before connects to host.
*
* @ci: the controller
* @reg: register index
* @mask: mast bit
* @value: the bit value to wait
* @timeout_ms: timeout in millisecond
*
* This function returns an error code if timeout
*/
int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
u32 value, unsigned int timeout_ms)
{
unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms);
while (hw_read(ci, reg, mask) != value) {
if (time_after(jiffies, elapse)) {
dev_err(ci->dev, "timeout waiting for %08x in %d\n",
mask, reg);
return -ETIMEDOUT;
}
msleep(20);
}
return 0;
}
static irqreturn_t ci_irq(int irq, void *data)
{
struct ci_hdrc *ci = data;
@ -601,35 +588,14 @@ static irqreturn_t ci_irq(int irq, void *data)
return ret;
}
static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event,
void *ptr)
static int ci_cable_notifier(struct notifier_block *nb, unsigned long event,
void *ptr)
{
struct ci_hdrc_cable *vbus = container_of(nb, struct ci_hdrc_cable, nb);
struct ci_hdrc *ci = vbus->ci;
struct ci_hdrc_cable *cbl = container_of(nb, struct ci_hdrc_cable, nb);
struct ci_hdrc *ci = cbl->ci;
if (event)
vbus->state = true;
else
vbus->state = false;
vbus->changed = true;
ci_irq(ci->irq, ci);
return NOTIFY_DONE;
}
static int ci_id_notifier(struct notifier_block *nb, unsigned long event,
void *ptr)
{
struct ci_hdrc_cable *id = container_of(nb, struct ci_hdrc_cable, nb);
struct ci_hdrc *ci = id->ci;
if (event)
id->state = false;
else
id->state = true;
id->changed = true;
cbl->connected = event;
cbl->changed = true;
ci_irq(ci->irq, ci);
return NOTIFY_DONE;
@ -738,27 +704,27 @@ static int ci_get_platdata(struct device *dev,
}
cable = &platdata->vbus_extcon;
cable->nb.notifier_call = ci_vbus_notifier;
cable->nb.notifier_call = ci_cable_notifier;
cable->edev = ext_vbus;
if (!IS_ERR(ext_vbus)) {
ret = extcon_get_cable_state_(cable->edev, EXTCON_USB);
ret = extcon_get_state(cable->edev, EXTCON_USB);
if (ret)
cable->state = true;
cable->connected = true;
else
cable->state = false;
cable->connected = false;
}
cable = &platdata->id_extcon;
cable->nb.notifier_call = ci_id_notifier;
cable->nb.notifier_call = ci_cable_notifier;
cable->edev = ext_id;
if (!IS_ERR(ext_id)) {
ret = extcon_get_cable_state_(cable->edev, EXTCON_USB_HOST);
ret = extcon_get_state(cable->edev, EXTCON_USB_HOST);
if (ret)
cable->state = false;
cable->connected = true;
else
cable->state = true;
cable->connected = false;
}
return 0;
}
@ -771,8 +737,8 @@ static int ci_extcon_register(struct ci_hdrc *ci)
id = &ci->platdata->id_extcon;
id->ci = ci;
if (!IS_ERR(id->edev)) {
ret = extcon_register_notifier(id->edev, EXTCON_USB_HOST,
&id->nb);
ret = devm_extcon_register_notifier(ci->dev, id->edev,
EXTCON_USB_HOST, &id->nb);
if (ret < 0) {
dev_err(ci->dev, "register ID failed\n");
return ret;
@ -782,11 +748,9 @@ static int ci_extcon_register(struct ci_hdrc *ci)
vbus = &ci->platdata->vbus_extcon;
vbus->ci = ci;
if (!IS_ERR(vbus->edev)) {
ret = extcon_register_notifier(vbus->edev, EXTCON_USB,
&vbus->nb);
ret = devm_extcon_register_notifier(ci->dev, vbus->edev,
EXTCON_USB, &vbus->nb);
if (ret < 0) {
extcon_unregister_notifier(id->edev, EXTCON_USB_HOST,
&id->nb);
dev_err(ci->dev, "register VBUS failed\n");
return ret;
}
@ -795,20 +759,6 @@ static int ci_extcon_register(struct ci_hdrc *ci)
return 0;
}
static void ci_extcon_unregister(struct ci_hdrc *ci)
{
struct ci_hdrc_cable *cable;
cable = &ci->platdata->id_extcon;
if (!IS_ERR(cable->edev))
extcon_unregister_notifier(cable->edev, EXTCON_USB_HOST,
&cable->nb);
cable = &ci->platdata->vbus_extcon;
if (!IS_ERR(cable->edev))
extcon_unregister_notifier(cable->edev, EXTCON_USB, &cable->nb);
}
static DEFINE_IDA(ci_ida);
struct platform_device *ci_hdrc_add_device(struct device *dev,
@ -921,6 +871,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
CI_HDRC_IMX28_WRITE_FIX);
ci->supports_runtime_pm = !!(ci->platdata->flags &
CI_HDRC_SUPPORTS_RUNTIME_PM);
platform_set_drvdata(pdev, ci);
ret = hw_device_init(ci, base);
if (ret < 0) {
@ -928,6 +879,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}
ret = ci_ulpi_init(ci);
if (ret)
return ret;
if (ci->platdata->phy) {
ci->phy = ci->platdata->phy;
} else if (ci->platdata->usb_phy) {
@ -938,11 +893,15 @@ static int ci_hdrc_probe(struct platform_device *pdev)
/* if both generic PHY and USB PHY layers aren't enabled */
if (PTR_ERR(ci->phy) == -ENOSYS &&
PTR_ERR(ci->usb_phy) == -ENXIO)
return -ENXIO;
PTR_ERR(ci->usb_phy) == -ENXIO) {
ret = -ENXIO;
goto ulpi_exit;
}
if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy))
return -EPROBE_DEFER;
if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) {
ret = -EPROBE_DEFER;
goto ulpi_exit;
}
if (IS_ERR(ci->phy))
ci->phy = NULL;
@ -1027,7 +986,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
}
}
platform_set_drvdata(pdev, ci);
ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED,
ci->platdata->name, ci);
if (ret)
@ -1054,11 +1012,12 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (!ret)
return 0;
ci_extcon_unregister(ci);
stop:
ci_role_destroy(ci);
deinit_phy:
ci_usb_phy_exit(ci);
ulpi_exit:
ci_ulpi_exit(ci);
return ret;
}
@ -1074,10 +1033,10 @@ static int ci_hdrc_remove(struct platform_device *pdev)
}
dbg_remove_files(ci);
ci_extcon_unregister(ci);
ci_role_destroy(ci);
ci_hdrc_enter_lpm(ci, true);
ci_usb_phy_exit(ci);
ci_ulpi_exit(ci);
return 0;
}
@ -1125,6 +1084,7 @@ static void ci_controller_suspend(struct ci_hdrc *ci)
static int ci_controller_resume(struct device *dev)
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
int ret;
dev_dbg(dev, "at %s\n", __func__);
@ -1134,6 +1094,11 @@ static int ci_controller_resume(struct device *dev)
}
ci_hdrc_enter_lpm(ci, false);
ret = ci_ulpi_resume(ci);
if (ret)
return ret;
if (ci->usb_phy) {
usb_phy_set_suspend(ci->usb_phy, 0);
usb_phy_set_wakeup(ci->usb_phy, false);

View file

@ -90,6 +90,13 @@ static int ehci_ci_reset(struct usb_hcd *hcd)
ehci->need_io_watchdog = 0;
if (ci->platdata->notify_event) {
ret = ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_RESET_EVENT);
if (ret)
return ret;
}
ci_platform_configure(ci);
return ret;
@ -187,6 +194,9 @@ static void host_stop(struct ci_hdrc *ci)
struct usb_hcd *hcd = ci->hcd;
if (hcd) {
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_STOPPED_EVENT);
usb_remove_hcd(hcd);
ci->role = CI_ROLE_END;
synchronize_irq(ci->irq);

View file

@ -44,12 +44,15 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
else
val &= ~OTGSC_BSVIS;
cable->changed = false;
if (cable->state)
if (cable->connected)
val |= OTGSC_BSV;
else
val &= ~OTGSC_BSV;
if (cable->enabled)
val |= OTGSC_BSVIE;
else
val &= ~OTGSC_BSVIE;
}
cable = &ci->platdata->id_extcon;
@ -59,15 +62,18 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
else
val &= ~OTGSC_IDIS;
cable->changed = false;
if (cable->state)
val |= OTGSC_ID;
if (cable->connected)
val &= ~OTGSC_ID; /* host */
else
val &= ~OTGSC_ID;
val |= OTGSC_ID; /* device */
if (cable->enabled)
val |= OTGSC_IDIE;
else
val &= ~OTGSC_IDIE;
}
return val;
return val & mask;
}
/**
@ -77,6 +83,36 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
*/
void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data)
{
struct ci_hdrc_cable *cable;
cable = &ci->platdata->vbus_extcon;
if (!IS_ERR(cable->edev)) {
if (data & mask & OTGSC_BSVIS)
cable->changed = false;
/* Don't enable vbus interrupt if using external notifier */
if (data & mask & OTGSC_BSVIE) {
cable->enabled = true;
data &= ~OTGSC_BSVIE;
} else if (mask & OTGSC_BSVIE) {
cable->enabled = false;
}
}
cable = &ci->platdata->id_extcon;
if (!IS_ERR(cable->edev)) {
if (data & mask & OTGSC_IDIS)
cable->changed = false;
/* Don't enable id interrupt if using external notifier */
if (data & mask & OTGSC_IDIE) {
cable->enabled = true;
data &= ~OTGSC_IDIE;
} else if (mask & OTGSC_IDIE) {
cable->enabled = false;
}
}
hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data);
}
@ -98,13 +134,37 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
if (!ci->is_otg)
return;
if (hw_read_otgsc(ci, OTGSC_BSV))
if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active)
usb_gadget_vbus_connect(&ci->gadget);
else
else if (!hw_read_otgsc(ci, OTGSC_BSV) && ci->vbus_active)
usb_gadget_vbus_disconnect(&ci->gadget);
}
#define CI_VBUS_STABLE_TIMEOUT_MS 5000
/**
* When we switch to device mode, the vbus value should be lower
* than OTGSC_BSV before connecting to host.
*
* @ci: the controller
*
* This function returns an error code if timeout
*/
static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
{
unsigned long elapse = jiffies + msecs_to_jiffies(5000);
u32 mask = OTGSC_BSV;
while (hw_read_otgsc(ci, mask)) {
if (time_after(jiffies, elapse)) {
dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n",
mask);
return -ETIMEDOUT;
}
msleep(20);
}
return 0;
}
static void ci_handle_id_switch(struct ci_hdrc *ci)
{
enum ci_role role = ci_otg_role(ci);
@ -115,12 +175,21 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
ci_role_stop(ci);
if (role == CI_ROLE_GADGET)
/* wait vbus lower than OTGSC_BSV */
hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
CI_VBUS_STABLE_TIMEOUT_MS);
if (role == CI_ROLE_GADGET &&
IS_ERR(ci->platdata->vbus_extcon.edev))
/*
* Wait vbus lower than OTGSC_BSV before connecting
* to host. If connecting status is from an external
* connector instead of register, we don't need to
* care vbus on the board, since it will not affect
* external connector status.
*/
hw_wait_vbus_lower_bsv(ci);
ci_role_start(ci, role);
/* vbus change may have already occurred */
if (role == CI_ROLE_GADGET)
ci_handle_vbus_change(ci);
}
}
/**

View file

@ -1725,7 +1725,6 @@ static int ci_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
unsigned long flags;
int retval = -ENOMEM;
if (driver->disconnect == NULL)
@ -1752,7 +1751,6 @@ static int ci_udc_start(struct usb_gadget *gadget,
pm_runtime_get_sync(&ci->gadget.dev);
if (ci->vbus_active) {
spin_lock_irqsave(&ci->lock, flags);
hw_device_reset(ci);
} else {
usb_udc_vbus_handler(&ci->gadget, false);
@ -1761,7 +1759,6 @@ static int ci_udc_start(struct usb_gadget *gadget,
}
retval = hw_device_state(ci, ci->ep0out->qh.dma);
spin_unlock_irqrestore(&ci->lock, flags);
if (retval)
pm_runtime_put_sync(&ci->gadget.dev);
@ -1796,10 +1793,10 @@ static int ci_udc_stop(struct usb_gadget *gadget)
if (ci->vbus_active) {
hw_device_state(ci, 0);
spin_unlock_irqrestore(&ci->lock, flags);
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_STOPPED_EVENT);
spin_unlock_irqrestore(&ci->lock, flags);
_gadget_stop_activity(&ci->gadget);
spin_lock_irqsave(&ci->lock, flags);
pm_runtime_put(&ci->gadget.dev);

113
drivers/usb/chipidea/ulpi.c Normal file
View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2016 Linaro Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/device.h>
#include <linux/usb/chipidea.h>
#include <linux/ulpi/interface.h>
#include "ci.h"
#define ULPI_WAKEUP BIT(31)
#define ULPI_RUN BIT(30)
#define ULPI_WRITE BIT(29)
#define ULPI_SYNC_STATE BIT(27)
#define ULPI_ADDR(n) ((n) << 16)
#define ULPI_DATA(n) (n)
static int ci_ulpi_wait(struct ci_hdrc *ci, u32 mask)
{
unsigned long usec = 10000;
while (usec--) {
if (!hw_read(ci, OP_ULPI_VIEWPORT, mask))
return 0;
udelay(1);
}
return -ETIMEDOUT;
}
static int ci_ulpi_read(struct device *dev, u8 addr)
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
int ret;
hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
if (ret)
return ret;
hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_RUN | ULPI_ADDR(addr));
ret = ci_ulpi_wait(ci, ULPI_RUN);
if (ret)
return ret;
return hw_read(ci, OP_ULPI_VIEWPORT, GENMASK(15, 8)) >> 8;
}
static int ci_ulpi_write(struct device *dev, u8 addr, u8 val)
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
int ret;
hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
if (ret)
return ret;
hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff,
ULPI_RUN | ULPI_WRITE | ULPI_ADDR(addr) | val);
return ci_ulpi_wait(ci, ULPI_RUN);
}
int ci_ulpi_init(struct ci_hdrc *ci)
{
if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
return 0;
/*
* Set PORTSC correctly so we can read/write ULPI registers for
* identification purposes
*/
hw_phymode_configure(ci);
ci->ulpi_ops.read = ci_ulpi_read;
ci->ulpi_ops.write = ci_ulpi_write;
ci->ulpi = ulpi_register_interface(ci->dev, &ci->ulpi_ops);
if (IS_ERR(ci->ulpi))
dev_err(ci->dev, "failed to register ULPI interface");
return PTR_ERR_OR_ZERO(ci->ulpi);
}
void ci_ulpi_exit(struct ci_hdrc *ci)
{
if (ci->ulpi) {
ulpi_unregister_interface(ci->ulpi);
ci->ulpi = NULL;
}
}
int ci_ulpi_resume(struct ci_hdrc *ci)
{
int cnt = 100000;
while (cnt-- > 0) {
if (hw_read(ci, OP_ULPI_VIEWPORT, ULPI_SYNC_STATE))
return 0;
udelay(1);
}
return -ETIMEDOUT;
}

View file

@ -913,7 +913,6 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
struct serial_struct tmp;
memset(&tmp, 0, sizeof(tmp));
tmp.flags = ASYNC_LOW_LATENCY;
tmp.xmit_fifo_size = acm->writesize;
tmp.baud_base = le32_to_cpu(acm->line.dwDTERate);
tmp.close_delay = acm->port.close_delay / 10;

View file

@ -531,7 +531,7 @@ retry:
i++;
if (file->f_flags & O_NONBLOCK) {
if (!test_bit(WDM_READ, &desc->flags)) {
rv = cntr ? cntr : -EAGAIN;
rv = -EAGAIN;
goto err;
}
rv = 0;

View file

@ -16,6 +16,9 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/clk/clk-conf.h>
/* -------------------------------------------------------------------------- */
@ -39,6 +42,10 @@ static int ulpi_match(struct device *dev, struct device_driver *driver)
struct ulpi *ulpi = to_ulpi_dev(dev);
const struct ulpi_device_id *id;
/* Some ULPI devices don't have a vendor id so rely on OF match */
if (ulpi->id.vendor == 0)
return of_driver_match_device(dev, driver);
for (id = drv->id_table; id->vendor; id++)
if (id->vendor == ulpi->id.vendor &&
id->product == ulpi->id.product)
@ -50,6 +57,11 @@ static int ulpi_match(struct device *dev, struct device_driver *driver)
static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct ulpi *ulpi = to_ulpi_dev(dev);
int ret;
ret = of_device_uevent_modalias(dev, env);
if (ret != -ENODEV)
return ret;
if (add_uevent_var(env, "MODALIAS=ulpi:v%04xp%04x",
ulpi->id.vendor, ulpi->id.product))
@ -60,6 +72,11 @@ static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env)
static int ulpi_probe(struct device *dev)
{
struct ulpi_driver *drv = to_ulpi_driver(dev->driver);
int ret;
ret = of_clk_set_defaults(dev->of_node, false);
if (ret < 0)
return ret;
return drv->probe(to_ulpi_dev(dev));
}
@ -87,8 +104,13 @@ static struct bus_type ulpi_bus = {
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int len;
struct ulpi *ulpi = to_ulpi_dev(dev);
len = of_device_get_modalias(dev, buf, PAGE_SIZE - 1);
if (len != -ENODEV)
return len;
return sprintf(buf, "ulpi:v%04xp%04x\n",
ulpi->id.vendor, ulpi->id.product);
}
@ -153,23 +175,45 @@ EXPORT_SYMBOL_GPL(ulpi_unregister_driver);
/* -------------------------------------------------------------------------- */
static int ulpi_register(struct device *dev, struct ulpi *ulpi)
static int ulpi_of_register(struct ulpi *ulpi)
{
struct device_node *np = NULL, *child;
struct device *parent;
/* Find a ulpi bus underneath the parent or the grandparent */
parent = ulpi->dev.parent;
if (parent->of_node)
np = of_find_node_by_name(parent->of_node, "ulpi");
else if (parent->parent && parent->parent->of_node)
np = of_find_node_by_name(parent->parent->of_node, "ulpi");
if (!np)
return 0;
child = of_get_next_available_child(np, NULL);
of_node_put(np);
if (!child)
return -EINVAL;
ulpi->dev.of_node = child;
return 0;
}
static int ulpi_read_id(struct ulpi *ulpi)
{
int ret;
ulpi->dev.parent = dev; /* needed early for ops */
/* Test the interface */
ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa);
if (ret < 0)
return ret;
goto err;
ret = ulpi_read(ulpi, ULPI_SCRATCH);
if (ret < 0)
return ret;
if (ret != 0xaa)
return -ENODEV;
goto err;
ulpi->id.vendor = ulpi_read(ulpi, ULPI_VENDOR_ID_LOW);
ulpi->id.vendor |= ulpi_read(ulpi, ULPI_VENDOR_ID_HIGH) << 8;
@ -177,13 +221,35 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi)
ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW);
ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8;
/* Some ULPI devices don't have a vendor id so rely on OF match */
if (ulpi->id.vendor == 0)
goto err;
request_module("ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product);
return 0;
err:
of_device_request_module(&ulpi->dev);
return 0;
}
static int ulpi_register(struct device *dev, struct ulpi *ulpi)
{
int ret;
ulpi->dev.parent = dev; /* needed early for ops */
ulpi->dev.bus = &ulpi_bus;
ulpi->dev.type = &ulpi_dev_type;
dev_set_name(&ulpi->dev, "%s.ulpi", dev_name(dev));
ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev));
request_module("ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product);
ret = ulpi_of_register(ulpi);
if (ret)
return ret;
ret = ulpi_read_id(ulpi);
if (ret)
return ret;
ret = device_register(&ulpi->dev);
if (ret)
@ -234,6 +300,7 @@ EXPORT_SYMBOL_GPL(ulpi_register_interface);
*/
void ulpi_unregister_interface(struct ulpi *ulpi)
{
of_node_put(ulpi->dev.of_node);
device_unregister(&ulpi->dev);
}
EXPORT_SYMBOL_GPL(ulpi_unregister_interface);

View file

@ -134,42 +134,35 @@ enum snoop_when {
#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
/* Limit on the total amount of memory we can allocate for transfers */
static unsigned usbfs_memory_mb = 16;
static u32 usbfs_memory_mb = 16;
module_param(usbfs_memory_mb, uint, 0644);
MODULE_PARM_DESC(usbfs_memory_mb,
"maximum MB allowed for usbfs buffers (0 = no limit)");
/* Hard limit, necessary to avoid arithmetic overflow */
#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)
static atomic_t usbfs_memory_usage; /* Total memory currently allocated */
static atomic64_t usbfs_memory_usage; /* Total memory currently allocated */
/* Check whether it's okay to allocate more memory for a transfer */
static int usbfs_increase_memory_usage(unsigned amount)
static int usbfs_increase_memory_usage(u64 amount)
{
unsigned lim;
u64 lim;
/*
* Convert usbfs_memory_mb to bytes, avoiding overflows.
* 0 means use the hard limit (effectively unlimited).
*/
lim = ACCESS_ONCE(usbfs_memory_mb);
if (lim == 0 || lim > (USBFS_XFER_MAX >> 20))
lim = USBFS_XFER_MAX;
else
lim <<= 20;
lim <<= 20;
atomic_add(amount, &usbfs_memory_usage);
if (atomic_read(&usbfs_memory_usage) <= lim)
return 0;
atomic_sub(amount, &usbfs_memory_usage);
return -ENOMEM;
atomic64_add(amount, &usbfs_memory_usage);
if (lim > 0 && atomic64_read(&usbfs_memory_usage) > lim) {
atomic64_sub(amount, &usbfs_memory_usage);
return -ENOMEM;
}
return 0;
}
/* Memory for a transfer is being deallocated */
static void usbfs_decrease_memory_usage(unsigned amount)
static void usbfs_decrease_memory_usage(u64 amount)
{
atomic_sub(amount, &usbfs_memory_usage);
atomic64_sub(amount, &usbfs_memory_usage);
}
static int connected(struct usb_dev_state *ps)
@ -1191,7 +1184,7 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
return -EINVAL;
len1 = bulk.len;
if (len1 >= USBFS_XFER_MAX)
if (len1 >= (INT_MAX - sizeof(struct urb)))
return -EINVAL;
ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
if (ret)
@ -1584,10 +1577,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
return -EINVAL;
}
if (uurb->buffer_length >= USBFS_XFER_MAX) {
ret = -EINVAL;
goto error;
}
if (uurb->buffer_length > 0 &&
!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
uurb->buffer, uurb->buffer_length)) {

View file

@ -3017,6 +3017,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
}
usb_put_invalidate_rhdev(hcd);
hcd->flags = 0;
}
EXPORT_SYMBOL_GPL(usb_remove_hcd);

View file

@ -122,12 +122,11 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,
* This function sends a simple control message to a specified endpoint and
* waits for the message to complete, or timeout.
*
* Don't use this function from within an interrupt context, like a bottom half
* handler. If you need an asynchronous message, or need to send a message
* from within interrupt context, use usb_submit_urb().
* If a thread in your driver uses this call, make sure your disconnect()
* method can wait for it to complete. Since you don't have a handle on the
* URB used, you can't cancel the request.
* Don't use this function from within an interrupt context. If you need
* an asynchronous message, or need to send a message from within interrupt
* context, use usb_submit_urb(). If a thread in your driver uses this call,
* make sure your disconnect() method can wait for it to complete. Since you
* don't have a handle on the URB used, you can't cancel the request.
*
* Return: If successful, the number of bytes transferred. Otherwise, a negative
* error number.
@ -173,12 +172,11 @@ EXPORT_SYMBOL_GPL(usb_control_msg);
* This function sends a simple interrupt message to a specified endpoint and
* waits for the message to complete, or timeout.
*
* Don't use this function from within an interrupt context, like a bottom half
* handler. If you need an asynchronous message, or need to send a message
* from within interrupt context, use usb_submit_urb() If a thread in your
* driver uses this call, make sure your disconnect() method can wait for it to
* complete. Since you don't have a handle on the URB used, you can't cancel
* the request.
* Don't use this function from within an interrupt context. If you need
* an asynchronous message, or need to send a message from within interrupt
* context, use usb_submit_urb() If a thread in your driver uses this call,
* make sure your disconnect() method can wait for it to complete. Since you
* don't have a handle on the URB used, you can't cancel the request.
*
* Return:
* If successful, 0. Otherwise a negative error number. The number of actual
@ -207,12 +205,11 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);
* This function sends a simple bulk message to a specified endpoint
* and waits for the message to complete, or timeout.
*
* Don't use this function from within an interrupt context, like a bottom half
* handler. If you need an asynchronous message, or need to send a message
* from within interrupt context, use usb_submit_urb() If a thread in your
* driver uses this call, make sure your disconnect() method can wait for it to
* complete. Since you don't have a handle on the URB used, you can't cancel
* the request.
* Don't use this function from within an interrupt context. If you need
* an asynchronous message, or need to send a message from within interrupt
* context, use usb_submit_urb() If a thread in your driver uses this call,
* make sure your disconnect() method can wait for it to complete. Since you
* don't have a handle on the URB used, you can't cancel the request.
*
* Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT ioctl,
* users are forced to abuse this routine by using it to submit URBs for

View file

@ -104,7 +104,7 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
gr = &hsotg->gr_backup;
if (!gr->valid) {
dev_err(hsotg->dev, "%s: no global registers to restore\n",
__func__);
__func__);
return -EINVAL;
}
gr->valid = false;
@ -155,21 +155,21 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore)
ret = dwc2_restore_global_registers(hsotg);
if (ret) {
dev_err(hsotg->dev, "%s: failed to restore registers\n",
__func__);
__func__);
return ret;
}
if (dwc2_is_host_mode(hsotg)) {
ret = dwc2_restore_host_registers(hsotg);
if (ret) {
dev_err(hsotg->dev, "%s: failed to restore host registers\n",
__func__);
__func__);
return ret;
}
} else {
ret = dwc2_restore_device_registers(hsotg);
if (ret) {
dev_err(hsotg->dev, "%s: failed to restore device registers\n",
__func__);
__func__);
return ret;
}
}
@ -195,7 +195,7 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
ret = dwc2_backup_global_registers(hsotg);
if (ret) {
dev_err(hsotg->dev, "%s: failed to backup global registers\n",
__func__);
__func__);
return ret;
}
@ -203,14 +203,14 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
ret = dwc2_backup_host_registers(hsotg);
if (ret) {
dev_err(hsotg->dev, "%s: failed to backup host registers\n",
__func__);
__func__);
return ret;
}
} else {
ret = dwc2_backup_device_registers(hsotg);
if (ret) {
dev_err(hsotg->dev, "%s: failed to backup device registers\n",
__func__);
__func__);
return ret;
}
}
@ -313,7 +313,7 @@ static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg)
* Do core a soft reset of the core. Be careful with this because it
* resets all the internal state machines of the core.
*/
int dwc2_core_reset(struct dwc2_hsotg *hsotg)
int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
{
u32 greset;
int count = 0;
@ -369,7 +369,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
}
} while (!(greset & GRSTCTL_AHBIDLE));
if (wait_for_host_mode)
if (wait_for_host_mode && !skip_wait)
dwc2_wait_for_mode(hsotg, true);
return 0;
@ -455,7 +455,7 @@ void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
if (dwc2_iddig_filter_enabled(hsotg))
usleep_range(100000, 110000);
msleep(100);
}
/*
@ -500,7 +500,7 @@ int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg)
{
int retval;
retval = dwc2_core_reset(hsotg);
retval = dwc2_core_reset(hsotg, false);
if (retval)
return retval;
@ -541,7 +541,7 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
addr = hsotg->regs + HAINTMSK;
dev_dbg(hsotg->dev, "HAINTMSK @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr));
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
addr = hsotg->regs + HFLBADDR;
dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr));
@ -571,7 +571,7 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
addr = hsotg->regs + HCDMA(i);
dev_dbg(hsotg->dev, "HCDMA @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr));
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
addr = hsotg->regs + HCDMAB(i);
dev_dbg(hsotg->dev, "HCDMAB @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr));
@ -751,11 +751,6 @@ bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host)
return dwc2_force_mode(hsotg, host);
}
u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg)
{
return hsotg->params.otg_ver == 1 ? 0x0200 : 0x0103;
}
bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
{
if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
@ -793,7 +788,7 @@ void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg)
}
/* Returns the controller's GHWCFG2.OTG_MODE. */
unsigned dwc2_op_mode(struct dwc2_hsotg *hsotg)
unsigned int dwc2_op_mode(struct dwc2_hsotg *hsotg)
{
u32 ghwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
@ -804,7 +799,7 @@ unsigned dwc2_op_mode(struct dwc2_hsotg *hsotg)
/* Returns true if the controller is capable of DRD. */
bool dwc2_hw_is_otg(struct dwc2_hsotg *hsotg)
{
unsigned op_mode = dwc2_op_mode(hsotg);
unsigned int op_mode = dwc2_op_mode(hsotg);
return (op_mode == GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) ||
(op_mode == GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE) ||
@ -814,7 +809,7 @@ bool dwc2_hw_is_otg(struct dwc2_hsotg *hsotg)
/* Returns true if the controller is host-only. */
bool dwc2_hw_is_host(struct dwc2_hsotg *hsotg)
{
unsigned op_mode = dwc2_op_mode(hsotg);
unsigned int op_mode = dwc2_op_mode(hsotg);
return (op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_HOST) ||
(op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST);
@ -823,7 +818,7 @@ bool dwc2_hw_is_host(struct dwc2_hsotg *hsotg)
/* Returns true if the controller is device-only. */
bool dwc2_hw_is_device(struct dwc2_hsotg *hsotg)
{
unsigned op_mode = dwc2_op_mode(hsotg);
unsigned int op_mode = dwc2_op_mode(hsotg);
return (op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ||
(op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE);

View file

@ -127,6 +127,8 @@ static const char * const dwc2_hsotg_supply_names[] = {
"vusb_a", /* analog USB supply, 1.1V */
};
#define DWC2_NUM_SUPPLIES ARRAY_SIZE(dwc2_hsotg_supply_names)
/*
* EP0_MPS_LIMIT
*
@ -246,7 +248,8 @@ struct dwc2_hsotg_req {
void *saved_req_buf;
};
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
#define call_gadget(_hs, _entry) \
do { \
if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \
@ -271,13 +274,6 @@ enum dwc2_lx_state {
DWC2_L3, /* Off state */
};
/*
* Gadget periodic tx fifo sizes as used by legacy driver
* EP0 is not included
*/
#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 768, 768, 768, \
768, 0, 0, 0, 0, 0, 0, 0}
/* Gadget ep0 states */
enum dwc2_ep0_state {
DWC2_EP0_SETUP,
@ -295,9 +291,6 @@ enum dwc2_ep0_state {
* 1 - SRP Only capable
* 2 - No HNP/SRP capable (always available)
* Defaults to best available option (0, 1, then 2)
* @otg_ver: OTG version supported
* 0 - 1.3 (default)
* 1 - 2.0
* @host_dma: Specifies whether to use slave or DMA mode for accessing
* the data FIFOs. The driver will automatically detect the
* value for this parameter if none is specified.
@ -444,6 +437,11 @@ enum dwc2_ep0_state {
* in DWORDS with possible values from from
* 16-32768 (default: 256, 256, 256, 256, 768,
* 768, 768, 768, 0, 0, 0, 0, 0, 0, 0).
* @change_speed_quirk: Change speed configuration to DWC2_SPEED_PARAM_FULL
* while full&low speed device connect. And change speed
* back to DWC2_SPEED_PARAM_HIGH while device is gone.
* 0 - No (default)
* 1 - Yes
*
* The following parameters may be specified when starting the module. These
* parameters define how the DWC_otg controller should be configured. A
@ -452,63 +450,48 @@ enum dwc2_ep0_state {
* default described above.
*/
struct dwc2_core_params {
/*
* Don't add any non-int members here, this will break
* dwc2_set_all_params!
*/
int otg_cap;
u8 otg_cap;
#define DWC2_CAP_PARAM_HNP_SRP_CAPABLE 0
#define DWC2_CAP_PARAM_SRP_ONLY_CAPABLE 1
#define DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
int otg_ver;
int dma_desc_enable;
int dma_desc_fs_enable;
int speed;
#define DWC2_SPEED_PARAM_HIGH 0
#define DWC2_SPEED_PARAM_FULL 1
#define DWC2_SPEED_PARAM_LOW 2
int enable_dynamic_fifo;
int en_multiple_tx_fifo;
int host_rx_fifo_size;
int host_nperio_tx_fifo_size;
int host_perio_tx_fifo_size;
int max_transfer_size;
int max_packet_count;
int host_channels;
int phy_type;
u8 phy_type;
#define DWC2_PHY_TYPE_PARAM_FS 0
#define DWC2_PHY_TYPE_PARAM_UTMI 1
#define DWC2_PHY_TYPE_PARAM_ULPI 2
int phy_utmi_width;
int phy_ulpi_ddr;
int phy_ulpi_ext_vbus;
#define DWC2_PHY_ULPI_INTERNAL_VBUS 0
#define DWC2_PHY_ULPI_EXTERNAL_VBUS 1
u8 speed;
#define DWC2_SPEED_PARAM_HIGH 0
#define DWC2_SPEED_PARAM_FULL 1
#define DWC2_SPEED_PARAM_LOW 2
int i2c_enable;
int ulpi_fs_ls;
int host_support_fs_ls_low_power;
int host_ls_low_power_phy_clk;
#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
int ts_dline;
int reload_ctl;
int ahbcfg;
int uframe_sched;
int external_id_pin_ctl;
int hibernation;
/*
* The following parameters are *only* set via device
* properties and cannot be set directly in this structure.
*/
u8 phy_utmi_width;
bool phy_ulpi_ddr;
bool phy_ulpi_ext_vbus;
bool enable_dynamic_fifo;
bool en_multiple_tx_fifo;
bool i2c_enable;
bool ulpi_fs_ls;
bool ts_dline;
bool reload_ctl;
bool uframe_sched;
bool external_id_pin_ctl;
bool hibernation;
u16 max_packet_count;
u32 max_transfer_size;
u32 ahbcfg;
/* Host parameters */
bool host_dma;
bool dma_desc_enable;
bool dma_desc_fs_enable;
bool host_support_fs_ls_low_power;
bool host_ls_low_power_phy_clk;
u8 host_channels;
u16 host_rx_fifo_size;
u16 host_nperio_tx_fifo_size;
u16 host_perio_tx_fifo_size;
/* Gadget parameters */
bool g_dma;
@ -516,6 +499,8 @@ struct dwc2_core_params {
u32 g_rx_fifo_size;
u32 g_np_tx_fifo_size;
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
bool change_speed_quirk;
};
/**
@ -603,8 +588,8 @@ struct dwc2_hw_params {
#define DWC2_CTRL_BUFF_SIZE 8
/**
* struct dwc2_gregs_backup - Holds global registers state before entering partial
* power down
* struct dwc2_gregs_backup - Holds global registers state before
* entering partial power down
* @gotgctl: Backup of GOTGCTL register
* @gintmsk: Backup of GINTMSK register
* @gahbcfg: Backup of GAHBCFG register
@ -634,8 +619,8 @@ struct dwc2_gregs_backup {
};
/**
* struct dwc2_dregs_backup - Holds device registers state before entering partial
* power down
* struct dwc2_dregs_backup - Holds device registers state before
* entering partial power down
* @dcfg: Backup of DCFG register
* @dctl: Backup of DCTL register
* @daintmsk: Backup of DAINTMSK register
@ -664,8 +649,8 @@ struct dwc2_dregs_backup {
};
/**
* struct dwc2_hregs_backup - Holds host registers state before entering partial
* power down
* struct dwc2_hregs_backup - Holds host registers state before
* entering partial power down
* @hcfg: Backup of HCFG register
* @haintmsk: Backup of HAINTMSK register
* @hcintmsk: Backup of HCINTMSK register
@ -782,9 +767,10 @@ struct dwc2_hregs_backup {
* @gadget_enabled Peripheral mode sub-driver initialization indicator.
* @ll_hw_enabled Status of low-level hardware resources.
* @phy: The otg phy transceiver structure for phy control.
* @uphy: The otg phy transceiver structure for old USB phy control.
* @plat: The platform specific configuration data. This can be removed once
* all SoCs support usb transceiver.
* @uphy: The otg phy transceiver structure for old USB phy
* control.
* @plat: The platform specific configuration data. This can be
* removed once all SoCs support usb transceiver.
* @supplies: Definition of USB power supplies
* @phyif: PHY interface width
* @lock: Spinlock that protects all the driver data structures
@ -921,7 +907,7 @@ struct dwc2_hsotg {
struct phy *phy;
struct usb_phy *uphy;
struct dwc2_hsotg_plat *plat;
struct regulator_bulk_data supplies[ARRAY_SIZE(dwc2_hsotg_supply_names)];
struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
u32 phyif;
spinlock_t lock;
@ -947,6 +933,7 @@ struct dwc2_hsotg {
/* DWC OTG HW Release versions */
#define DWC2_CORE_REV_2_71a 0x4f54271a
#define DWC2_CORE_REV_2_90a 0x4f54290a
#define DWC2_CORE_REV_2_91a 0x4f54291a
#define DWC2_CORE_REV_2_92a 0x4f54292a
#define DWC2_CORE_REV_2_94a 0x4f54294a
#define DWC2_CORE_REV_3_00a 0x4f54300a
@ -1033,7 +1020,8 @@ struct dwc2_hsotg {
#endif
#endif /* CONFIG_USB_DWC2_HOST || CONFIG_USB_DWC2_DUAL_ROLE */
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
/* Gadget structures */
struct usb_gadget_driver *driver;
int fifo_mem;
@ -1101,37 +1089,37 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg *hsotg)
* The following functions support initialization of the core driver component
* and the DWC_otg controller
*/
extern int dwc2_core_reset(struct dwc2_hsotg *hsotg);
extern int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host);
void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg);
void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
extern bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg);
bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg);
/*
* Common core Functions.
* The following functions support managing the DWC_otg controller in either
* device or host mode.
*/
extern void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes);
extern void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num);
extern void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg);
void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes);
void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num);
void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg);
extern void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd);
extern void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd);
void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd);
void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd);
/* This function should be called on every hardware interrupt. */
extern irqreturn_t dwc2_handle_common_intr(int irq, void *dev);
irqreturn_t dwc2_handle_common_intr(int irq, void *dev);
/* The device ID match table */
extern const struct of_device_id dwc2_of_match_table[];
extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg);
extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg);
int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg);
int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg);
/* Parameters */
int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
@ -1145,7 +1133,7 @@ int dwc2_init_params(struct dwc2_hsotg *hsotg);
* are read in and cached so they always read directly from the
* GHWCFG2 register.
*/
unsigned dwc2_op_mode(struct dwc2_hsotg *hsotg);
unsigned int dwc2_op_mode(struct dwc2_hsotg *hsotg);
bool dwc2_hw_is_otg(struct dwc2_hsotg *hsotg);
bool dwc2_hw_is_host(struct dwc2_hsotg *hsotg);
bool dwc2_hw_is_device(struct dwc2_hsotg *hsotg);
@ -1157,6 +1145,7 @@ static inline int dwc2_is_host_mode(struct dwc2_hsotg *hsotg)
{
return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0;
}
static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
{
return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
@ -1165,29 +1154,28 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
/*
* Dump core registers and SPRAM
*/
extern void dwc2_dump_dev_registers(struct dwc2_hsotg *hsotg);
extern void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg);
extern void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg);
/*
* Return OTG version - either 1.3 or 2.0
*/
extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg);
void dwc2_dump_dev_registers(struct dwc2_hsotg *hsotg);
void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg);
void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg);
/* Gadget defines */
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
extern int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg);
extern int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2);
extern int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2);
extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
extern void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset);
extern void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg);
extern void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2);
extern int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg);
int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2);
int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2);
int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset);
void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg);
void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2);
int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
#define dwc2_is_device_connected(hsotg) (hsotg->connected)
int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg);
int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg);
int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
#else
static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
{ return 0; }
@ -1198,25 +1186,31 @@ static inline int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2)
static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{ return 0; }
static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset) {}
bool reset) {}
static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
int testmode)
int testmode)
{ return 0; }
#define dwc2_is_device_connected(hsotg) (0)
static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
{ return 0; }
#endif
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
extern int dwc2_hcd_get_future_frame_number(struct dwc2_hsotg *hsotg, int us);
extern void dwc2_hcd_connect(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force);
extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
int dwc2_hcd_get_future_frame_number(struct dwc2_hsotg *hsotg, int us);
void dwc2_hcd_connect(struct dwc2_hsotg *hsotg);
void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force);
void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg);
int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);
#else
@ -1229,7 +1223,7 @@ static inline void dwc2_hcd_connect(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force) {}
static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}
static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
{ return 0; }

View file

@ -159,9 +159,8 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
" ++OTG Interrupt: Session Request Success Status Change++\n");
gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
if (gotgctl & GOTGCTL_SESREQSCS) {
if (hsotg->params.phy_type ==
DWC2_PHY_TYPE_PARAM_FS
&& hsotg->params.i2c_enable > 0) {
if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
hsotg->params.i2c_enable) {
hsotg->srp_success = 1;
} else {
/* Clear Session Request */
@ -317,7 +316,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
hsotg->lx_state);
hsotg->lx_state);
if (dwc2_is_device_mode(hsotg)) {
if (hsotg->lx_state == DWC2_L2) {
@ -437,7 +436,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
/* Ignore suspend request before enumeration */
if (!dwc2_is_device_connected(hsotg)) {
dev_dbg(hsotg->dev,
"ignore suspend request before enumeration\n");
"ignore suspend request before enumeration\n");
return;
}
@ -445,7 +444,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
if (ret) {
if (ret != -ENOTSUPP)
dev_err(hsotg->dev,
"enter hibernation failed\n");
"enter hibernation failed\n");
goto skip_power_saving;
}

View file

@ -17,8 +17,8 @@
#include "core.h"
#ifdef CONFIG_DEBUG_FS
extern int dwc2_debugfs_init(struct dwc2_hsotg *);
extern void dwc2_debugfs_exit(struct dwc2_hsotg *);
int dwc2_debugfs_init(struct dwc2_hsotg *hsotg);
void dwc2_debugfs_exit(struct dwc2_hsotg *hsotg);
#else
static inline int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
{ return 0; }

View file

@ -137,7 +137,7 @@ static int state_show(struct seq_file *seq, void *v)
int idx;
seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n",
dwc2_readl(regs + DCFG),
dwc2_readl(regs + DCFG),
dwc2_readl(regs + DCTL),
dwc2_readl(regs + DSTS));
@ -338,23 +338,23 @@ static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg)
{
struct dentry *root;
struct dentry *file;
unsigned epidx;
unsigned int epidx;
root = hsotg->debug_root;
/* create general state file */
file = debugfs_create_file("state", S_IRUGO, root, hsotg, &state_fops);
file = debugfs_create_file("state", 0444, root, hsotg, &state_fops);
if (IS_ERR(file))
dev_err(hsotg->dev, "%s: failed to create state\n", __func__);
file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, hsotg,
&testmode_fops);
file = debugfs_create_file("testmode", 0644, root, hsotg,
&testmode_fops);
if (IS_ERR(file))
dev_err(hsotg->dev, "%s: failed to create testmode\n",
__func__);
__func__);
file = debugfs_create_file("fifo", S_IRUGO, root, hsotg, &fifo_fops);
file = debugfs_create_file("fifo", 0444, root, hsotg, &fifo_fops);
if (IS_ERR(file))
dev_err(hsotg->dev, "%s: failed to create fifo\n", __func__);
@ -364,8 +364,8 @@ static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg)
ep = hsotg->eps_out[epidx];
if (ep) {
file = debugfs_create_file(ep->name, S_IRUGO,
root, ep, &ep_fops);
file = debugfs_create_file(ep->name, 0444,
root, ep, &ep_fops);
if (IS_ERR(file))
dev_err(hsotg->dev, "failed to create %s debug file\n",
ep->name);
@ -377,8 +377,8 @@ static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg)
ep = hsotg->eps_in[epidx];
if (ep) {
file = debugfs_create_file(ep->name, S_IRUGO,
root, ep, &ep_fops);
file = debugfs_create_file(ep->name, 0444,
root, ep, &ep_fops);
if (IS_ERR(file))
dev_err(hsotg->dev, "failed to create %s debug file\n",
ep->name);
@ -725,6 +725,143 @@ static const struct debugfs_reg32 dwc2_regs[] = {
dump_register(HCDMAB(15)),
};
#define print_param(_seq, _ptr, _param) \
seq_printf((_seq), "%-30s: %d\n", #_param, (_ptr)->_param)
#define print_param_hex(_seq, _ptr, _param) \
seq_printf((_seq), "%-30s: 0x%x\n", #_param, (_ptr)->_param)
static int params_show(struct seq_file *seq, void *v)
{
struct dwc2_hsotg *hsotg = seq->private;
struct dwc2_core_params *p = &hsotg->params;
int i;
print_param(seq, p, otg_cap);
print_param(seq, p, dma_desc_enable);
print_param(seq, p, dma_desc_fs_enable);
print_param(seq, p, speed);
print_param(seq, p, enable_dynamic_fifo);
print_param(seq, p, en_multiple_tx_fifo);
print_param(seq, p, host_rx_fifo_size);
print_param(seq, p, host_nperio_tx_fifo_size);
print_param(seq, p, host_perio_tx_fifo_size);
print_param(seq, p, max_transfer_size);
print_param(seq, p, max_packet_count);
print_param(seq, p, host_channels);
print_param(seq, p, phy_type);
print_param(seq, p, phy_utmi_width);
print_param(seq, p, phy_ulpi_ddr);
print_param(seq, p, phy_ulpi_ext_vbus);
print_param(seq, p, i2c_enable);
print_param(seq, p, ulpi_fs_ls);
print_param(seq, p, host_support_fs_ls_low_power);
print_param(seq, p, host_ls_low_power_phy_clk);
print_param(seq, p, ts_dline);
print_param(seq, p, reload_ctl);
print_param_hex(seq, p, ahbcfg);
print_param(seq, p, uframe_sched);
print_param(seq, p, external_id_pin_ctl);
print_param(seq, p, hibernation);
print_param(seq, p, host_dma);
print_param(seq, p, g_dma);
print_param(seq, p, g_dma_desc);
print_param(seq, p, g_rx_fifo_size);
print_param(seq, p, g_np_tx_fifo_size);
for (i = 0; i < MAX_EPS_CHANNELS; i++) {
char str[32];
snprintf(str, 32, "g_tx_fifo_size[%d]", i);
seq_printf(seq, "%-30s: %d\n", str, p->g_tx_fifo_size[i]);
}
return 0;
}
static int params_open(struct inode *inode, struct file *file)
{
return single_open(file, params_show, inode->i_private);
}
static const struct file_operations params_fops = {
.owner = THIS_MODULE,
.open = params_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int hw_params_show(struct seq_file *seq, void *v)
{
struct dwc2_hsotg *hsotg = seq->private;
struct dwc2_hw_params *hw = &hsotg->hw_params;
print_param(seq, hw, op_mode);
print_param(seq, hw, arch);
print_param(seq, hw, dma_desc_enable);
print_param(seq, hw, enable_dynamic_fifo);
print_param(seq, hw, en_multiple_tx_fifo);
print_param(seq, hw, rx_fifo_size);
print_param(seq, hw, host_nperio_tx_fifo_size);
print_param(seq, hw, dev_nperio_tx_fifo_size);
print_param(seq, hw, host_perio_tx_fifo_size);
print_param(seq, hw, nperio_tx_q_depth);
print_param(seq, hw, host_perio_tx_q_depth);
print_param(seq, hw, dev_token_q_depth);
print_param(seq, hw, max_transfer_size);
print_param(seq, hw, max_packet_count);
print_param(seq, hw, host_channels);
print_param(seq, hw, hs_phy_type);
print_param(seq, hw, fs_phy_type);
print_param(seq, hw, i2c_enable);
print_param(seq, hw, num_dev_ep);
print_param(seq, hw, num_dev_perio_in_ep);
print_param(seq, hw, total_fifo_size);
print_param(seq, hw, power_optimized);
print_param(seq, hw, utmi_phy_data_width);
print_param_hex(seq, hw, snpsid);
print_param_hex(seq, hw, dev_ep_dirs);
return 0;
}
static int hw_params_open(struct inode *inode, struct file *file)
{
return single_open(file, hw_params_show, inode->i_private);
}
static const struct file_operations hw_params_fops = {
.owner = THIS_MODULE,
.open = hw_params_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int dr_mode_show(struct seq_file *seq, void *v)
{
struct dwc2_hsotg *hsotg = seq->private;
const char *dr_mode = "";
device_property_read_string(hsotg->dev, "dr_mode", &dr_mode);
seq_printf(seq, "%s\n", dr_mode);
return 0;
}
static int dr_mode_open(struct inode *inode, struct file *file)
{
return single_open(file, dr_mode_show, inode->i_private);
}
static const struct file_operations dr_mode_fops = {
.owner = THIS_MODULE,
.open = dr_mode_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
{
int ret;
@ -736,6 +873,25 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
goto err0;
}
file = debugfs_create_file("params", 0444,
hsotg->debug_root,
hsotg, &params_fops);
if (IS_ERR(file))
dev_err(hsotg->dev, "%s: failed to create params\n", __func__);
file = debugfs_create_file("hw_params", 0444,
hsotg->debug_root,
hsotg, &hw_params_fops);
if (IS_ERR(file))
dev_err(hsotg->dev, "%s: failed to create hw_params\n",
__func__);
file = debugfs_create_file("dr_mode", 0444,
hsotg->debug_root,
hsotg, &dr_mode_fops);
if (IS_ERR(file))
dev_err(hsotg->dev, "%s: failed to create dr_mode\n", __func__);
/* Add gadget debugfs nodes */
dwc2_hsotg_create_debug(hsotg);
@ -750,8 +906,8 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
hsotg->regset->nregs = ARRAY_SIZE(dwc2_regs);
hsotg->regset->base = hsotg->regs;
file = debugfs_create_regset32("regdump", S_IRUGO, hsotg->debug_root,
hsotg->regset);
file = debugfs_create_regset32("regdump", 0444, hsotg->debug_root,
hsotg->regset);
if (!file) {
ret = -ENOMEM;
goto err1;

View file

@ -171,7 +171,7 @@ static void dwc2_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
* request.
*/
static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
unsigned int ep, unsigned int dir_in,
unsigned int ep, unsigned int dir_in,
unsigned int en)
{
unsigned long flags;
@ -191,6 +191,99 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
local_irq_restore(flags);
}
/**
* dwc2_hsotg_tx_fifo_count - return count of TX FIFOs in device mode
*/
int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
{
if (hsotg->hw_params.en_multiple_tx_fifo)
/* In dedicated FIFO mode we need count of IN EPs */
return (dwc2_readl(hsotg->regs + GHWCFG4) &
GHWCFG4_NUM_IN_EPS_MASK) >> GHWCFG4_NUM_IN_EPS_SHIFT;
else
/* In shared FIFO mode we need count of Periodic IN EPs */
return hsotg->hw_params.num_dev_perio_in_ep;
}
/**
* dwc2_hsotg_ep_info_size - return Endpoint Info Control block size in DWORDs
*/
static int dwc2_hsotg_ep_info_size(struct dwc2_hsotg *hsotg)
{
int val = 0;
int i;
u32 ep_dirs;
/*
* Don't need additional space for ep info control registers in
* slave mode.
*/
if (!using_dma(hsotg)) {
dev_dbg(hsotg->dev, "Buffer DMA ep info size 0\n");
return 0;
}
/*
* Buffer DMA mode - 1 location per endpoit
* Descriptor DMA mode - 4 locations per endpoint
*/
ep_dirs = hsotg->hw_params.dev_ep_dirs;
for (i = 0; i <= hsotg->hw_params.num_dev_ep; i++) {
val += ep_dirs & 3 ? 1 : 2;
ep_dirs >>= 2;
}
if (using_desc_dma(hsotg))
val = val * 4;
return val;
}
/**
* dwc2_hsotg_tx_fifo_total_depth - return total FIFO depth available for
* device mode TX FIFOs
*/
int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
{
int ep_info_size;
int addr;
int tx_addr_max;
u32 np_tx_fifo_size;
np_tx_fifo_size = min_t(u32, hsotg->hw_params.dev_nperio_tx_fifo_size,
hsotg->params.g_np_tx_fifo_size);
/* Get Endpoint Info Control block size in DWORDs. */
ep_info_size = dwc2_hsotg_ep_info_size(hsotg);
tx_addr_max = hsotg->hw_params.total_fifo_size - ep_info_size;
addr = hsotg->params.g_rx_fifo_size + np_tx_fifo_size;
if (tx_addr_max <= addr)
return 0;
return tx_addr_max - addr;
}
/**
* dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode
* TX FIFOs
*/
int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
{
int tx_fifo_count;
int tx_fifo_depth;
tx_fifo_depth = dwc2_hsotg_tx_fifo_total_depth(hsotg);
tx_fifo_count = dwc2_hsotg_tx_fifo_count(hsotg);
if (!tx_fifo_count)
return tx_fifo_depth;
else
return tx_fifo_depth / tx_fifo_count;
}
/**
* dwc2_hsotg_init_fifo - initialise non-periodic FIFOs
* @hsotg: The device instance.
@ -241,6 +334,9 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
val = dwc2_readl(hsotg->regs + DPTXFSIZN(ep));
}
dwc2_writel(hsotg->hw_params.total_fifo_size |
addr << GDFIFOCFG_EPINFOBASE_SHIFT,
hsotg->regs + GDFIFOCFG);
/*
* according to p428 of the design guide, we need to ensure that
* all fifos are flushed before continuing
@ -277,11 +373,11 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
* Allocate a new USB request structure appropriate for the specified endpoint
*/
static struct usb_request *dwc2_hsotg_ep_alloc_request(struct usb_ep *ep,
gfp_t flags)
gfp_t flags)
{
struct dwc2_hsotg_req *req;
req = kzalloc(sizeof(struct dwc2_hsotg_req), flags);
req = kzalloc(sizeof(*req), flags);
if (!req)
return NULL;
@ -312,10 +408,11 @@ static inline int is_ep_periodic(struct dwc2_hsotg_ep *hs_ep)
* of a request to ensure the buffer is ready for access by the caller.
*/
static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_req *hs_req)
{
struct usb_request *req = &hs_req->req;
usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in);
}
@ -384,7 +481,7 @@ fail:
* This routine is only needed for PIO
*/
static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_req *hs_req)
{
bool periodic = is_ep_periodic(hs_ep);
@ -466,7 +563,7 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
max_transfer = hs_ep->ep.maxpacket * hs_ep->mc;
dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, max_transfer %d\n",
__func__, gnptxsts, can_write, to_write, max_transfer);
__func__, gnptxsts, can_write, to_write, max_transfer);
/*
* limit to 512 bytes of data, it seems at least on the non-periodic
@ -487,7 +584,7 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
/* it's needed only when we do not use dedicated fifos */
if (!hsotg->dedicated_fifos)
dwc2_hsotg_en_gsint(hsotg,
periodic ? GINTSTS_PTXFEMP :
periodic ? GINTSTS_PTXFEMP :
GINTSTS_NPTXFEMP);
}
@ -516,12 +613,12 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
/* it's needed only when we do not use dedicated fifos */
if (!hsotg->dedicated_fifos)
dwc2_hsotg_en_gsint(hsotg,
periodic ? GINTSTS_PTXFEMP :
periodic ? GINTSTS_PTXFEMP :
GINTSTS_NPTXFEMP);
}
dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n",
to_write, hs_req->req.length, can_write, buf_pos);
to_write, hs_req->req.length, can_write, buf_pos);
if (to_write <= 0)
return -ENOSPC;
@ -547,17 +644,17 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
* Return the maximum data that can be queued in one go on a given endpoint
* so that transfers that are too long can be split.
*/
static unsigned get_ep_limit(struct dwc2_hsotg_ep *hs_ep)
static unsigned int get_ep_limit(struct dwc2_hsotg_ep *hs_ep)
{
int index = hs_ep->index;
unsigned maxsize;
unsigned maxpkt;
unsigned int maxsize;
unsigned int maxpkt;
if (index != 0) {
maxsize = DXEPTSIZ_XFERSIZE_LIMIT + 1;
maxpkt = DXEPTSIZ_PKTCNT_LIMIT + 1;
} else {
maxsize = 64+64;
maxsize = 64 + 64;
if (hs_ep->dir_in)
maxpkt = DIEPTSIZ0_PKTCNT_LIMIT + 1;
else
@ -580,11 +677,11 @@ static unsigned get_ep_limit(struct dwc2_hsotg_ep *hs_ep)
}
/**
* dwc2_hsotg_read_frameno - read current frame number
* @hsotg: The device instance
*
* Return the current frame number
*/
* dwc2_hsotg_read_frameno - read current frame number
* @hsotg: The device instance
*
* Return the current frame number
*/
static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
{
u32 dsts;
@ -874,7 +971,7 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep)
* appropriately, and writing any data to the FIFOs.
*/
static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_req *hs_req,
bool continuing)
{
@ -885,9 +982,9 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
u32 epsize_reg;
u32 epsize;
u32 ctrl;
unsigned length;
unsigned packets;
unsigned maxreq;
unsigned int length;
unsigned int packets;
unsigned int maxreq;
unsigned int dma_reg;
if (index != 0) {
@ -966,7 +1063,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
if (dir_in && ureq->zero && !continuing) {
/* Test if zlp is actually required. */
if ((ureq->length >= hs_ep->ep.maxpacket) &&
!(ureq->length % hs_ep->ep.maxpacket))
!(ureq->length % hs_ep->ep.maxpacket))
hs_ep->send_zlp = 1;
}
@ -1070,7 +1167,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
/* check ep is enabled */
if (!(dwc2_readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA))
dev_dbg(hsotg->dev,
"ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n",
"ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n",
index, dwc2_readl(hsotg->regs + epctrl_reg));
dev_dbg(hsotg->dev, "%s: DXEPCTL=0x%08x\n",
@ -1093,7 +1190,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
* cleanup on completion.
*/
static int dwc2_hsotg_map_dma(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_ep *hs_ep,
struct usb_request *req)
{
int ret;
@ -1112,7 +1209,8 @@ dma_error:
}
static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req)
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_req *hs_req)
{
void *req_buf = hs_req->req.buf;
@ -1123,7 +1221,7 @@ static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
WARN_ON(hs_req->saved_req_buf);
dev_dbg(hsotg->dev, "%s: %s: buf=%p length=%d\n", __func__,
hs_ep->ep.name, req_buf, hs_req->req.length);
hs_ep->ep.name, req_buf, hs_req->req.length);
hs_req->req.buf = kmalloc(hs_req->req.length, GFP_ATOMIC);
if (!hs_req->req.buf) {
@ -1142,8 +1240,10 @@ static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
return 0;
}
static void dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req)
static void
dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_req *hs_req)
{
/* If dma is not being used or buffer was aligned */
if (!using_dma(hsotg) || !hs_req->saved_req_buf)
@ -1155,7 +1255,7 @@ static void dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
/* Copy data from bounce buffer on successful out transfer */
if (!hs_ep->dir_in && !hs_req->req.status)
memcpy(hs_req->saved_req_buf, hs_req->req.buf,
hs_req->req.actual);
hs_req->req.actual);
/* Free bounce buffer */
kfree(hs_req->req.buf);
@ -1224,7 +1324,7 @@ static int dwc2_gadget_set_ep0_desc_chain(struct dwc2_hsotg *hsotg,
}
static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
gfp_t gfp_flags)
gfp_t gfp_flags)
{
struct dwc2_hsotg_req *hs_req = our_req(req);
struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
@ -1239,7 +1339,7 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
/* Prevent new request submission when controller is suspended */
if (hs->lx_state == DWC2_L2) {
dev_dbg(hs->dev, "%s: don't submit request while suspended\n",
__func__);
__func__);
return -EAGAIN;
}
@ -1300,7 +1400,7 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
}
static int dwc2_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req,
gfp_t gfp_flags)
gfp_t gfp_flags)
{
struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hs = hs_ep->parent;
@ -1315,7 +1415,7 @@ static int dwc2_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req,
}
static void dwc2_hsotg_ep_free_request(struct usb_ep *ep,
struct usb_request *req)
struct usb_request *req)
{
struct dwc2_hsotg_req *hs_req = our_req(req);
@ -1331,7 +1431,7 @@ static void dwc2_hsotg_ep_free_request(struct usb_ep *ep,
* submitted that need cleaning up.
*/
static void dwc2_hsotg_complete_oursetup(struct usb_ep *ep,
struct usb_request *req)
struct usb_request *req)
{
struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hsotg = hs_ep->parent;
@ -1350,7 +1450,7 @@ static void dwc2_hsotg_complete_oursetup(struct usb_ep *ep,
* structure, or return NULL if it is not a valid endpoint.
*/
static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
u32 windex)
u32 windex)
{
struct dwc2_hsotg_ep *ep;
int dir = (windex & USB_DIR_IN) ? 1 : 0;
@ -1407,7 +1507,7 @@ int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
* an internal method of sending replies to certain control requests, etc.
*/
static int dwc2_hsotg_send_reply(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *ep,
struct dwc2_hsotg_ep *ep,
void *buff,
int length)
{
@ -1450,7 +1550,7 @@ static int dwc2_hsotg_send_reply(struct dwc2_hsotg *hsotg,
* @ctrl: USB control request
*/
static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
struct usb_ctrlrequest *ctrl)
{
struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
struct dwc2_hsotg_ep *ep;
@ -1466,8 +1566,11 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
reply = cpu_to_le16(0); /* bit 0 => self powered,
* bit 1 => remote wakeup */
/*
* bit 0 => self powered
* bit 1 => remote wakeup
*/
reply = cpu_to_le16(0);
break;
case USB_RECIP_INTERFACE:
@ -1555,7 +1658,7 @@ static void dwc2_gadget_start_next_request(struct dwc2_hsotg_ep *hs_ep)
* @ctrl: USB control request
*/
static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
struct usb_ctrlrequest *ctrl)
{
struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
struct dwc2_hsotg_req *hs_req;
@ -1640,9 +1743,8 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
}
/* If we have pending request, then start it */
if (!ep->req) {
if (!ep->req)
dwc2_gadget_start_next_request(ep);
}
}
break;
@ -1705,7 +1807,7 @@ static void dwc2_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
* gadget driver).
*/
static void dwc2_hsotg_process_control(struct dwc2_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
struct usb_ctrlrequest *ctrl)
{
struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
int ret = 0;
@ -1781,7 +1883,7 @@ static void dwc2_hsotg_process_control(struct dwc2_hsotg *hsotg,
* EP0 setup packets
*/
static void dwc2_hsotg_complete_setup(struct usb_ep *ep,
struct usb_request *req)
struct usb_request *req)
{
struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hsotg = hs_ep->parent;
@ -1839,7 +1941,7 @@ static void dwc2_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
}
static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep)
struct dwc2_hsotg_ep *hs_ep)
{
u32 ctrl;
u8 index = hs_ep->index;
@ -1885,11 +1987,10 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
* Note, expects the ep to already be locked as appropriate.
*/
static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_req *hs_req,
int result)
{
if (!hs_req) {
dev_dbg(hsotg->dev, "%s: nothing to complete?\n", __func__);
return;
@ -1935,9 +2036,8 @@ static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg,
* so be careful when doing this.
*/
if (!hs_ep->req && result >= 0) {
if (!hs_ep->req && result >= 0)
dwc2_gadget_start_next_request(hs_ep);
}
}
/*
@ -2068,13 +2168,12 @@ static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
int max_req;
int read_ptr;
if (!hs_req) {
u32 epctl = dwc2_readl(hsotg->regs + DOEPCTL(ep_idx));
int ptr;
dev_dbg(hsotg->dev,
"%s: FIFO %d bytes on ep%d but no req (DXEPCTl=0x%08x)\n",
"%s: FIFO %d bytes on ep%d but no req (DXEPCTl=0x%08x)\n",
__func__, size, ep_idx, epctl);
/* dump the data from the FIFO, we've nothing we can do */
@ -2134,7 +2233,7 @@ static void dwc2_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in)
}
static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg,
u32 epctl_reg)
u32 epctl_reg)
{
u32 ctrl;
@ -2191,7 +2290,7 @@ static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[epnum];
struct dwc2_hsotg_req *hs_req = hs_ep->req;
struct usb_request *req = &hs_req->req;
unsigned size_left = DXEPTSIZ_XFERSIZE_GET(epsize);
unsigned int size_left = DXEPTSIZ_XFERSIZE_GET(epsize);
int result = 0;
if (!hs_req) {
@ -2210,7 +2309,7 @@ static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
size_left = dwc2_gadget_get_xfersize_ddma(hs_ep);
if (using_dma(hsotg)) {
unsigned size_done;
unsigned int size_done;
/*
* Calculate the size of the transfer by checking how much
@ -2295,7 +2394,7 @@ static void dwc2_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
size >>= GRXSTS_BYTECNT_SHIFT;
dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n",
__func__, grxstsr, size, epnum);
__func__, grxstsr, size, epnum);
switch ((status & GRXSTS_PKTSTS_MASK) >> GRXSTS_PKTSTS_SHIFT) {
case GRXSTS_PKTSTS_GLOBALOUTNAK:
@ -2470,7 +2569,7 @@ static void dwc2_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
* make an attempt to write data into the FIFO.
*/
static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep)
struct dwc2_hsotg_ep *hs_ep)
{
struct dwc2_hsotg_req *hs_req = hs_ep->req;
@ -2481,7 +2580,7 @@ static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg,
*/
if (hs_ep->index != 0)
dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index,
hs_ep->dir_in, 0);
hs_ep->dir_in, 0);
return 0;
}
@ -2503,7 +2602,7 @@ static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg,
* call the relevant completion routines.
*/
static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep)
struct dwc2_hsotg_ep *hs_ep)
{
struct dwc2_hsotg_req *hs_req = hs_ep->req;
u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
@ -2531,7 +2630,7 @@ static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg,
ret = dwc2_hsotg_set_test_mode(hsotg, hsotg->test_mode);
if (ret < 0) {
dev_dbg(hsotg->dev, "Invalid Test #%d\n",
hsotg->test_mode);
hsotg->test_mode);
dwc2_hsotg_stall_ep0(hsotg);
return;
}
@ -2751,19 +2850,19 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep)
}
/**
* dwc2_gadget_handle_nak - handle NAK interrupt
* @hs_ep: The endpoint on which interrupt is asserted.
*
* This is starting point for ISOC-IN transfer, synchronization done with
* first IN token received from host while corresponding EP is disabled.
*
* Device does not know when first one token will arrive from host. On first
* token arrival HW generates 2 interrupts: 'in token received while FIFO empty'
* and 'NAK'. NAK interrupt for ISOC-IN means that token has arrived and ZLP was
* sent in response to that as there was no data in FIFO. SW is basing on this
* interrupt to obtain frame in which token has come and then based on the
* interval calculates next frame for transfer.
*/
* dwc2_gadget_handle_nak - handle NAK interrupt
* @hs_ep: The endpoint on which interrupt is asserted.
*
* This is starting point for ISOC-IN transfer, synchronization done with
* first IN token received from host while corresponding EP is disabled.
*
* Device does not know when first one token will arrive from host. On first
* token arrival HW generates 2 interrupts: 'in token received while FIFO empty'
* and 'NAK'. NAK interrupt for ISOC-IN means that token has arrived and ZLP was
* sent in response to that as there was no data in FIFO. SW is basing on this
* interrupt to obtain frame in which token has come and then based on the
* interval calculates next frame for transfer.
*/
static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)
{
struct dwc2_hsotg *hsotg = hs_ep->parent;
@ -2807,7 +2906,7 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)
* Process and clear any interrupt pending for an individual endpoint
*/
static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
int dir_in)
int dir_in)
{
struct dwc2_hsotg_ep *hs_ep = index_to_ep(hsotg, idx, dir_in);
u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx);
@ -2824,7 +2923,7 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
if (!hs_ep) {
dev_err(hsotg->dev, "%s:Interrupt for unconfigured ep%d(%s)\n",
__func__, idx, dir_in ? "in" : "out");
__func__, idx, dir_in ? "in" : "out");
return;
}
@ -3059,13 +3158,13 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg,
int result)
{
struct dwc2_hsotg_req *req, *treq;
unsigned size;
unsigned int size;
ep->req = NULL;
list_for_each_entry_safe(req, treq, &ep->queue, queue)
dwc2_hsotg_complete_request(hsotg, ep, req,
result);
result);
if (!hsotg->dedicated_fifos)
return;
@ -3084,7 +3183,7 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg,
*/
void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
{
unsigned ep;
unsigned int ep;
if (!hsotg->connected)
return;
@ -3095,10 +3194,10 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
if (hsotg->eps_in[ep])
kill_all_requests(hsotg, hsotg->eps_in[ep],
-ESHUTDOWN);
-ESHUTDOWN);
if (hsotg->eps_out[ep])
kill_all_requests(hsotg, hsotg->eps_out[ep],
-ESHUTDOWN);
-ESHUTDOWN);
}
call_gadget(hsotg, disconnect);
@ -3147,7 +3246,7 @@ static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
* Issue a soft reset to the core, and await the core finishing it.
*/
void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
bool is_usb_reset)
bool is_usb_reset)
{
u32 intmsk;
u32 val;
@ -3158,7 +3257,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
if (!is_usb_reset)
if (dwc2_core_reset(hsotg))
if (dwc2_core_reset(hsotg, true))
return;
/*
@ -3221,7 +3320,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
if (!using_desc_dma(hsotg))
intmsk |= GINTSTS_INCOMPL_SOIN | GINTSTS_INCOMPL_SOOUT;
if (hsotg->params.external_id_pin_ctl <= 0)
if (!hsotg->params.external_id_pin_ctl)
intmsk |= GINTSTS_CONIDSTSCHNG;
dwc2_writel(intmsk, hsotg->regs + GINTMSK);
@ -3462,7 +3561,6 @@ irq_retry:
}
if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
u32 connected = hsotg->connected;
@ -3601,7 +3699,7 @@ irq_retry:
*/
if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
goto irq_retry;
goto irq_retry;
spin_unlock(&hsotg->lock);
@ -3705,7 +3803,7 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
* This is called from the USB gadget code's usb_ep_enable().
*/
static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc)
const struct usb_endpoint_descriptor *desc)
{
struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
struct dwc2_hsotg *hsotg = hs_ep->parent;
@ -3827,12 +3925,13 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
if (dir_in && hsotg->dedicated_fifos) {
u32 fifo_index = 0;
u32 fifo_size = UINT_MAX;
size = hs_ep->ep.maxpacket*hs_ep->mc;
size = hs_ep->ep.maxpacket * hs_ep->mc;
for (i = 1; i < hsotg->num_of_eps; ++i) {
if (hsotg->fifo_map & (1<<i))
if (hsotg->fifo_map & (1 << i))
continue;
val = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
val = (val >> FIFOSIZE_DEPTH_SHIFT)*4;
val = (val >> FIFOSIZE_DEPTH_SHIFT) * 4;
if (val < size)
continue;
/* Search for smallest acceptable fifo */
@ -4033,23 +4132,22 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
epctl &= ~DXEPCTL_STALL;
xfertype = epctl & DXEPCTL_EPTYPE_MASK;
if (xfertype == DXEPCTL_EPTYPE_BULK ||
xfertype == DXEPCTL_EPTYPE_INTERRUPT)
epctl |= DXEPCTL_SETD0PID;
xfertype == DXEPCTL_EPTYPE_INTERRUPT)
epctl |= DXEPCTL_SETD0PID;
}
dwc2_writel(epctl, hs->regs + epreg);
} else {
epreg = DOEPCTL(index);
epctl = dwc2_readl(hs->regs + epreg);
if (value)
if (value) {
epctl |= DXEPCTL_STALL;
else {
} else {
epctl &= ~DXEPCTL_STALL;
xfertype = epctl & DXEPCTL_EPTYPE_MASK;
if (xfertype == DXEPCTL_EPTYPE_BULK ||
xfertype == DXEPCTL_EPTYPE_INTERRUPT)
epctl |= DXEPCTL_SETD0PID;
xfertype == DXEPCTL_EPTYPE_INTERRUPT)
epctl |= DXEPCTL_SETD0PID;
}
dwc2_writel(epctl, hs->regs + epreg);
}
@ -4090,7 +4188,7 @@ static struct usb_ep_ops dwc2_hsotg_ep_ops = {
};
/**
* dwc2_hsotg_init - initalize the usb core
* dwc2_hsotg_init - initialize the usb core
* @hsotg: The driver state
*/
static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg)
@ -4144,7 +4242,7 @@ static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg)
* to work.
*/
static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
struct usb_gadget_driver *driver)
{
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags;
@ -4267,7 +4365,7 @@ static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on)
unsigned long flags = 0;
dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on,
hsotg->op_state);
hsotg->op_state);
/* Don't modify pullup state while in host mode */
if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
@ -4329,7 +4427,7 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
*
* Report how much power the device may consume to the phy.
*/
static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
{
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
@ -4358,7 +4456,7 @@ static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = {
* direction information and other state that may be required.
*/
static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *hs_ep,
struct dwc2_hsotg_ep *hs_ep,
int epnum,
bool dir_in)
{
@ -4415,6 +4513,7 @@ static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg,
if (using_dma(hsotg)) {
u32 next = DXEPCTL_NEXTEP((epnum + 1) % 15);
if (dir_in)
dwc2_writel(next, hsotg->regs + DIEPCTL(epnum));
else
@ -4441,8 +4540,9 @@ static int dwc2_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
/* Add ep0 */
hsotg->num_of_eps++;
hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, sizeof(struct dwc2_hsotg_ep),
GFP_KERNEL);
hsotg->eps_in[0] = devm_kzalloc(hsotg->dev,
sizeof(struct dwc2_hsotg_ep),
GFP_KERNEL);
if (!hsotg->eps_in[0])
return -ENOMEM;
/* Same dwc2_hsotg_ep is used in both directions for ep0 */
@ -4521,7 +4621,6 @@ static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg)
idx, dwc2_readl(regs + DOEPCTL(idx)),
dwc2_readl(regs + DOEPTSIZ(idx)),
dwc2_readl(regs + DOEPDMA(idx)));
}
dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n",
@ -4576,7 +4675,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
}
ret = devm_request_irq(hsotg->dev, irq, dwc2_hsotg_irq, IRQF_SHARED,
dev_name(hsotg->dev), hsotg);
dev_name(hsotg->dev), hsotg);
if (ret < 0) {
dev_err(dev, "cannot claim IRQ for gadget\n");
return ret;
@ -4607,10 +4706,10 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
for (epnum = 0; epnum < hsotg->num_of_eps; epnum++) {
if (hsotg->eps_in[epnum])
dwc2_hsotg_initep(hsotg, hsotg->eps_in[epnum],
epnum, 1);
epnum, 1);
if (hsotg->eps_out[epnum])
dwc2_hsotg_initep(hsotg, hsotg->eps_out[epnum],
epnum, 0);
epnum, 0);
}
ret = usb_add_gadget_udc(dev, &hsotg->gadget);

View file

@ -42,6 +42,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/io.h>
@ -54,6 +55,8 @@
#include "core.h"
#include "hcd.h"
static void dwc2_port_resume(struct dwc2_hsotg *hsotg);
/*
* =========================================================================
* Host Core Layer Functions
@ -79,9 +82,9 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
/* Enable the interrupts in the GINTMSK */
intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT;
if (hsotg->params.host_dma <= 0)
if (!hsotg->params.host_dma)
intmsk |= GINTSTS_RXFLVL;
if (hsotg->params.external_id_pin_ctl <= 0)
if (!hsotg->params.external_id_pin_ctl)
intmsk |= GINTSTS_CONIDSTSCHNG;
intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP |
@ -100,7 +103,7 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
hsotg->params.ulpi_fs_ls > 0) ||
hsotg->params.ulpi_fs_ls) ||
hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
/* Full speed PHY */
val = HCFG_FSLSPCLKSEL_48_MHZ;
@ -152,7 +155,7 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
if (dwc2_is_host_mode(hsotg))
dwc2_init_fs_ls_pclk_sel(hsotg);
if (hsotg->params.i2c_enable > 0) {
if (hsotg->params.i2c_enable) {
dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");
/* Program GUSBCFG.OtgUtmiFsSel to I2C */
@ -195,7 +198,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
dev_dbg(hsotg->dev, "HS ULPI PHY selected\n");
usbcfg |= GUSBCFG_ULPI_UTMI_SEL;
usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
if (hsotg->params.phy_ulpi_ddr > 0)
if (hsotg->params.phy_ulpi_ddr)
usbcfg |= GUSBCFG_DDRSEL;
break;
case DWC2_PHY_TYPE_PARAM_UTMI:
@ -246,7 +249,7 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
hsotg->params.ulpi_fs_ls > 0) {
hsotg->params.ulpi_fs_ls) {
dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg |= GUSBCFG_ULPI_FS_LS;
@ -290,17 +293,17 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
hsotg->params.host_dma,
hsotg->params.dma_desc_enable);
if (hsotg->params.host_dma > 0) {
if (hsotg->params.dma_desc_enable > 0)
if (hsotg->params.host_dma) {
if (hsotg->params.dma_desc_enable)
dev_dbg(hsotg->dev, "Using Descriptor DMA mode\n");
else
dev_dbg(hsotg->dev, "Using Buffer DMA mode\n");
} else {
dev_dbg(hsotg->dev, "Using Slave mode\n");
hsotg->params.dma_desc_enable = 0;
hsotg->params.dma_desc_enable = false;
}
if (hsotg->params.host_dma > 0)
if (hsotg->params.host_dma)
ahbcfg |= GAHBCFG_DMA_EN;
dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
@ -491,9 +494,10 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n",
dwc2_readl(hsotg->regs + HPTXFSIZ));
if (hsotg->params.en_multiple_tx_fifo > 0 &&
hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) {
if (hsotg->params.en_multiple_tx_fifo &&
hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_91a) {
/*
* This feature was implemented in 2.91a version
* Global DFIFOCFG calculation for Host mode -
* include RxFIFO, NPTXFIFO and HPTXFIFO
*/
@ -771,7 +775,7 @@ static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg,
* For Descriptor DMA mode core halts the channel on AHB error.
* Interrupt is not required.
*/
if (hsotg->params.dma_desc_enable <= 0) {
if (!hsotg->params.dma_desc_enable) {
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "desc DMA disabled\n");
hcintmsk |= HCINTMSK_AHBERR;
@ -804,7 +808,7 @@ static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg,
{
u32 intmsk;
if (hsotg->params.host_dma > 0) {
if (hsotg->params.host_dma) {
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "DMA enabled\n");
dwc2_hc_enable_dma_ints(hsotg, chan);
@ -1024,7 +1028,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
/* No need to set the bit in DDMA for disabling the channel */
/* TODO check it everywhere channel is disabled */
if (hsotg->params.dma_desc_enable <= 0) {
if (!hsotg->params.dma_desc_enable) {
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "desc DMA disabled\n");
hcchar |= HCCHAR_CHENA;
@ -1034,7 +1038,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
}
hcchar |= HCCHAR_CHDIS;
if (hsotg->params.host_dma <= 0) {
if (!hsotg->params.host_dma) {
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "DMA not enabled\n");
hcchar |= HCCHAR_CHENA;
@ -1380,7 +1384,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
dev_vdbg(hsotg->dev, "%s()\n", __func__);
if (chan->do_ping) {
if (hsotg->params.host_dma <= 0) {
if (!hsotg->params.host_dma) {
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "ping, no DMA\n");
dwc2_hc_do_ping(hsotg, chan);
@ -1508,7 +1512,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
TSIZ_SC_MC_PID_SHIFT);
}
if (hsotg->params.host_dma > 0) {
if (hsotg->params.host_dma) {
dwc2_writel((u32)chan->xfer_dma,
hsotg->regs + HCDMA(chan->hc_num));
if (dbg_hc(chan))
@ -1551,7 +1555,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
chan->xfer_started = 1;
chan->requests++;
if (hsotg->params.host_dma <= 0 &&
if (!hsotg->params.host_dma &&
!chan->ep_is_in && chan->xfer_len > 0)
/* Load OUT packet into the appropriate Tx FIFO */
dwc2_hc_write_packet(hsotg, chan);
@ -1834,7 +1838,7 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
u32 hcchar;
int i;
if (hsotg->params.host_dma <= 0) {
if (!hsotg->params.host_dma) {
/* Flush out any channel requests in slave mode */
for (i = 0; i < num_channels; i++) {
channel = hsotg->hc_ptr_array[i];
@ -1870,7 +1874,7 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
channel->qh = NULL;
}
/* All channels have been freed, mark them available */
if (hsotg->params.uframe_sched > 0) {
if (hsotg->params.uframe_sched) {
hsotg->available_host_channels =
hsotg->params.host_channels;
} else {
@ -2107,7 +2111,7 @@ static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg,
* Free the QTD and clean up the associated QH. Leave the QH in the
* schedule if it has any remaining QTDs.
*/
if (hsotg->params.dma_desc_enable <= 0) {
if (!hsotg->params.dma_desc_enable) {
u8 in_process = urb_qtd->in_process;
dwc2_hcd_qtd_unlink_and_free(hsotg, urb_qtd, qh);
@ -2150,7 +2154,7 @@ static int dwc2_hcd_endpoint_disable(struct dwc2_hsotg *hsotg,
}
spin_unlock_irqrestore(&hsotg->lock, flags);
usleep_range(20000, 40000);
msleep(20);
spin_lock_irqsave(&hsotg->lock, flags);
qh = ep->hcpriv;
if (!qh) {
@ -2215,13 +2219,12 @@ static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
/* Set ULPI External VBUS bit if needed */
usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV;
if (hsotg->params.phy_ulpi_ext_vbus ==
DWC2_PHY_ULPI_EXTERNAL_VBUS)
if (hsotg->params.phy_ulpi_ext_vbus)
usbcfg |= GUSBCFG_ULPI_EXT_VBUS_DRV;
/* Set external TS Dline pulsing bit if needed */
usbcfg &= ~GUSBCFG_TERMSELDLPULSE;
if (hsotg->params.ts_dline > 0)
if (hsotg->params.ts_dline)
usbcfg |= GUSBCFG_TERMSELDLPULSE;
dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
@ -2260,10 +2263,7 @@ static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
/* Program the GOTGCTL register */
otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
otgctl &= ~GOTGCTL_OTGVER;
if (hsotg->params.otg_ver > 0)
otgctl |= GOTGCTL_OTGVER;
dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->params.otg_ver);
/* Clear the SRP success bit for FS-I2c */
hsotg->srp_success = 0;
@ -2319,13 +2319,13 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
* runtime. This bit needs to be programmed during initial configuration
* and its value must not be changed during runtime.
*/
if (hsotg->params.reload_ctl > 0) {
if (hsotg->params.reload_ctl) {
hfir = dwc2_readl(hsotg->regs + HFIR);
hfir |= HFIR_RLDCTRL;
dwc2_writel(hfir, hsotg->regs + HFIR);
}
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
u32 op_mode = hsotg->hw_params.op_mode;
if (hsotg->hw_params.snpsid < DWC2_CORE_REV_2_90a ||
@ -2337,7 +2337,7 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
"Hardware does not support descriptor DMA mode -\n");
dev_err(hsotg->dev,
"falling back to buffer DMA mode.\n");
hsotg->params.dma_desc_enable = 0;
hsotg->params.dma_desc_enable = false;
} else {
hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg |= HCFG_DESCDMA;
@ -2363,7 +2363,7 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
otgctl &= ~GOTGCTL_HSTSETHNPEN;
dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
if (hsotg->params.dma_desc_enable <= 0) {
if (!hsotg->params.dma_desc_enable) {
int num_channels, i;
u32 hcchar;
@ -2430,7 +2430,7 @@ static void dwc2_hcd_reinit(struct dwc2_hsotg *hsotg)
hsotg->flags.d32 = 0;
hsotg->non_periodic_qh_ptr = &hsotg->non_periodic_sched_active;
if (hsotg->params.uframe_sched > 0) {
if (hsotg->params.uframe_sched) {
hsotg->available_host_channels =
hsotg->params.host_channels;
} else {
@ -2488,7 +2488,7 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
chan->do_ping = 0;
chan->ep_is_in = 0;
chan->data_pid_start = DWC2_HC_PID_SETUP;
if (hsotg->params.host_dma > 0)
if (hsotg->params.host_dma)
chan->xfer_dma = urb->setup_dma;
else
chan->xfer_buf = urb->setup_packet;
@ -2515,7 +2515,7 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
chan->do_ping = 0;
chan->data_pid_start = DWC2_HC_PID_DATA1;
chan->xfer_len = 0;
if (hsotg->params.host_dma > 0)
if (hsotg->params.host_dma)
chan->xfer_dma = hsotg->status_buf_dma;
else
chan->xfer_buf = hsotg->status_buf;
@ -2533,13 +2533,13 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
case USB_ENDPOINT_XFER_ISOC:
chan->ep_type = USB_ENDPOINT_XFER_ISOC;
if (hsotg->params.dma_desc_enable > 0)
if (hsotg->params.dma_desc_enable)
break;
frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
frame_desc->status = 0;
if (hsotg->params.host_dma > 0) {
if (hsotg->params.host_dma) {
chan->xfer_dma = urb->dma;
chan->xfer_dma += frame_desc->offset +
qtd->isoc_split_offset;
@ -2577,7 +2577,7 @@ static void dwc2_free_dma_aligned_buffer(struct urb *urb)
return;
temp = container_of(urb->transfer_buffer,
struct dma_aligned_buffer, data);
struct dma_aligned_buffer, data);
if (usb_urb_dir_in(urb))
memcpy(temp->old_xfer_buffer, temp->data,
@ -2621,7 +2621,7 @@ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
}
static int dwc2_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags)
gfp_t mem_flags)
{
int ret;
@ -2718,10 +2718,10 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
chan->multi_count = 1;
if (urb->actual_length > urb->length &&
!dwc2_hcd_is_pipe_in(&urb->pipe_info))
!dwc2_hcd_is_pipe_in(&urb->pipe_info))
urb->actual_length = urb->length;
if (hsotg->params.host_dma > 0)
if (hsotg->params.host_dma)
chan->xfer_dma = urb->dma + urb->actual_length;
else
chan->xfer_buf = (u8 *)urb->buf + urb->actual_length;
@ -2746,7 +2746,7 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
*/
chan->multi_count = dwc2_hb_mult(qh->maxp);
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
chan->desc_list_addr = qh->desc_list_dma;
chan->desc_list_sz = qh->desc_list_sz;
}
@ -2783,7 +2783,7 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
while (qh_ptr != &hsotg->periodic_sched_ready) {
if (list_empty(&hsotg->free_hc_list))
break;
if (hsotg->params.uframe_sched > 0) {
if (hsotg->params.uframe_sched) {
if (hsotg->available_host_channels <= 1)
break;
hsotg->available_host_channels--;
@ -2810,14 +2810,14 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
num_channels = hsotg->params.host_channels;
qh_ptr = hsotg->non_periodic_sched_inactive.next;
while (qh_ptr != &hsotg->non_periodic_sched_inactive) {
if (hsotg->params.uframe_sched <= 0 &&
if (!hsotg->params.uframe_sched &&
hsotg->non_periodic_channels >= num_channels -
hsotg->periodic_channels)
break;
if (list_empty(&hsotg->free_hc_list))
break;
qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
if (hsotg->params.uframe_sched > 0) {
if (hsotg->params.uframe_sched) {
if (hsotg->available_host_channels < 1)
break;
hsotg->available_host_channels--;
@ -2839,7 +2839,7 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
else
ret_val = DWC2_TRANSACTION_ALL;
if (hsotg->params.uframe_sched <= 0)
if (!hsotg->params.uframe_sched)
hsotg->non_periodic_channels++;
}
@ -2878,8 +2878,8 @@ static int dwc2_queue_transaction(struct dwc2_hsotg *hsotg,
list_move_tail(&chan->split_order_list_entry,
&hsotg->split_order);
if (hsotg->params.host_dma > 0) {
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.host_dma) {
if (hsotg->params.dma_desc_enable) {
if (!chan->xfer_started ||
chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
dwc2_hcd_start_xfer_ddma(hsotg, chan->qh);
@ -2967,7 +2967,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
if (qspcavail == 0) {
no_queue_space = 1;
no_queue_space = true;
break;
}
@ -2988,15 +2988,15 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
* The flag prevents any halts to get into the request queue in
* the middle of multiple high-bandwidth packets getting queued.
*/
if (hsotg->params.host_dma <= 0 &&
qh->channel->multi_count > 1)
if (!hsotg->params.host_dma &&
qh->channel->multi_count > 1)
hsotg->queuing_high_bandwidth = 1;
fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
TXSTS_FSPCAVAIL_SHIFT;
status = dwc2_queue_transaction(hsotg, qh->channel, fspcavail);
if (status < 0) {
no_fifo_space = 1;
no_fifo_space = true;
break;
}
@ -3007,7 +3007,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
* controller automatically handles multiple packets for
* high-bandwidth transfers.
*/
if (hsotg->params.host_dma > 0 || status == 0 ||
if (hsotg->params.host_dma || status == 0 ||
qh->channel->requests == qh->channel->multi_count) {
qh_ptr = qh_ptr->next;
/*
@ -3024,7 +3024,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
exit:
if (no_queue_space || no_fifo_space ||
(hsotg->params.host_dma <= 0 &&
(!hsotg->params.host_dma &&
!list_empty(&hsotg->periodic_sched_assigned))) {
/*
* May need to queue more transactions as the request
@ -3045,7 +3045,7 @@ exit:
* now. This function is called from interrupt
* handlers to queue more transactions as transfer
* states change.
*/
*/
gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
if (gintmsk & GINTSTS_PTXFEMP) {
gintmsk &= ~GINTSTS_PTXFEMP;
@ -3104,7 +3104,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg)
tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
if (hsotg->params.host_dma <= 0 && qspcavail == 0) {
if (!hsotg->params.host_dma && qspcavail == 0) {
no_queue_space = 1;
break;
}
@ -3137,7 +3137,7 @@ next:
hsotg->non_periodic_qh_ptr->next;
} while (hsotg->non_periodic_qh_ptr != orig_qh_ptr);
if (hsotg->params.host_dma <= 0) {
if (!hsotg->params.host_dma) {
tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT;
@ -3235,12 +3235,25 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
if (gotgctl & GOTGCTL_CONID_B) {
/* Wait for switch to device mode */
dev_dbg(hsotg->dev, "connId B\n");
if (hsotg->bus_suspended) {
dev_info(hsotg->dev,
"Do port resume before switching to device mode\n");
dwc2_port_resume(hsotg);
}
while (!dwc2_is_device_mode(hsotg)) {
dev_info(hsotg->dev,
"Waiting for Peripheral Mode, Mode=%s\n",
dwc2_is_host_mode(hsotg) ? "Host" :
"Peripheral");
usleep_range(20000, 40000);
msleep(20);
/*
* Sometimes the initial GOTGCTRL read is wrong, so
* check it again and jump to host mode if that was
* the case.
*/
gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
if (!(gotgctl & GOTGCTL_CONID_B))
goto host;
if (++count > 250)
break;
}
@ -3255,13 +3268,14 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_hsotg_core_connect(hsotg);
} else {
host:
/* A-Device connector (Host Mode) */
dev_dbg(hsotg->dev, "connId A\n");
while (!dwc2_is_host_mode(hsotg)) {
dev_info(hsotg->dev, "Waiting for Host Mode, Mode=%s\n",
dwc2_is_host_mode(hsotg) ?
"Host" : "Peripheral");
usleep_range(20000, 40000);
msleep(20);
if (++count > 250)
break;
}
@ -3296,7 +3310,7 @@ static void dwc2_wakeup_detected(unsigned long data)
dwc2_readl(hsotg->regs + HPRT0));
dwc2_hcd_rem_wakeup(hsotg);
hsotg->bus_suspended = 0;
hsotg->bus_suspended = false;
/* Change to L0 state */
hsotg->lx_state = DWC2_L0;
@ -3332,7 +3346,7 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
hprt0 |= HPRT0_SUSP;
dwc2_writel(hprt0, hsotg->regs + HPRT0);
hsotg->bus_suspended = 1;
hsotg->bus_suspended = true;
/*
* If hibernation is supported, Phy clock will be suspended
@ -3354,7 +3368,7 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
spin_unlock_irqrestore(&hsotg->lock, flags);
usleep_range(200000, 250000);
msleep(200);
} else {
spin_unlock_irqrestore(&hsotg->lock, flags);
}
@ -3378,7 +3392,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
pcgctl &= ~PCGCTL_STOPPCLK;
dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
spin_unlock_irqrestore(&hsotg->lock, flags);
usleep_range(20000, 40000);
msleep(20);
spin_lock_irqsave(&hsotg->lock, flags);
}
@ -3394,7 +3408,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
dwc2_writel(hprt0, hsotg->regs + HPRT0);
hsotg->bus_suspended = 0;
hsotg->bus_suspended = false;
spin_unlock_irqrestore(&hsotg->lock, flags);
}
@ -3614,7 +3628,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
u32 hcfg;
dev_info(hsotg->dev, "Enabling descriptor DMA mode\n");
hsotg->params.dma_desc_enable = 1;
hsotg->params.dma_desc_enable = true;
hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg |= HCFG_DESCDMA;
dwc2_writel(hcfg, hsotg->regs + HCFG);
@ -3691,7 +3705,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
}
/* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
usleep_range(50000, 70000);
msleep(50);
hprt0 &= ~HPRT0_RST;
dwc2_writel(hprt0, hsotg->regs + HPRT0);
hsotg->lx_state = DWC2_L0; /* Now back to On state */
@ -4047,7 +4061,7 @@ static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd)
{
struct wrapper_priv_data *p;
p = (struct wrapper_priv_data *) &hcd->hcd_priv;
p = (struct wrapper_priv_data *)&hcd->hcd_priv;
return p->hsotg;
}
@ -4082,7 +4096,7 @@ struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context,
*ttport = urb->dev->ttport;
dwc_tt = urb->dev->tt->hcpriv;
if (dwc_tt == NULL) {
if (!dwc_tt) {
size_t bitmap_size;
/*
@ -4096,7 +4110,7 @@ struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context,
dwc_tt = kzalloc(sizeof(*dwc_tt) + bitmap_size,
mem_flags);
if (dwc_tt == NULL)
if (!dwc_tt)
return NULL;
dwc_tt->usb_tt = urb->dev->tt;
@ -4123,7 +4137,7 @@ struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context,
void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg, struct dwc2_tt *dwc_tt)
{
/* Model kfree and make put of NULL a no-op */
if (dwc_tt == NULL)
if (!dwc_tt)
return;
WARN_ON(dwc_tt->refcount < 1);
@ -4206,7 +4220,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
usb_pipein(urb->pipe) ? "IN" : "OUT", status,
urb->actual_length);
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
for (i = 0; i < urb->number_of_packets; ++i) {
@ -4587,7 +4600,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
dwc2_dump_urb_info(hcd, urb, "urb_enqueue");
}
if (ep == NULL)
if (!ep)
return -EINVAL;
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS ||
@ -4657,7 +4670,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
urb->iso_frame_desc[i].length);
urb->hcpriv = dwc2_urb;
qh = (struct dwc2_qh *) ep->hcpriv;
qh = (struct dwc2_qh *)ep->hcpriv;
/* Create QH for the endpoint if it doesn't exist */
if (!qh) {
qh = dwc2_hcd_qh_create(hsotg, dwc2_urb, mem_flags);
@ -4712,7 +4725,7 @@ fail1:
dwc2_hcd_qh_unlink(hsotg, qh);
/* Free each QTD in the QH's QTD list */
list_for_each_entry_safe(qtd2, qtd2_tmp, &qh->qtd_list,
qtd_list_entry)
qtd_list_entry)
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh);
dwc2_hcd_qh_free(hsotg, qh);
}
@ -4860,6 +4873,61 @@ static void _dwc2_hcd_clear_tt_buffer_complete(struct usb_hcd *hcd,
spin_unlock_irqrestore(&hsotg->lock, flags);
}
/*
* HPRT0_SPD_HIGH_SPEED: high speed
* HPRT0_SPD_FULL_SPEED: full speed
*/
static void dwc2_change_bus_speed(struct usb_hcd *hcd, int speed)
{
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
if (hsotg->params.speed == speed)
return;
hsotg->params.speed = speed;
queue_work(hsotg->wq_otg, &hsotg->wf_otg);
}
static void dwc2_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
{
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
if (!hsotg->params.change_speed_quirk)
return;
/*
* On removal, set speed to default high-speed.
*/
if (udev->parent && udev->parent->speed > USB_SPEED_UNKNOWN &&
udev->parent->speed < USB_SPEED_HIGH) {
dev_info(hsotg->dev, "Set speed to default high-speed\n");
dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED);
}
}
static int dwc2_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
{
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
if (!hsotg->params.change_speed_quirk)
return 0;
if (udev->speed == USB_SPEED_HIGH) {
dev_info(hsotg->dev, "Set speed to high-speed\n");
dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED);
} else if ((udev->speed == USB_SPEED_FULL ||
udev->speed == USB_SPEED_LOW)) {
/*
* Change speed setting to full-speed if there's
* a full-speed or low-speed device plugged in.
*/
dev_info(hsotg->dev, "Set speed to full-speed\n");
dwc2_change_bus_speed(hcd, HPRT0_SPD_FULL_SPEED);
}
return 0;
}
static struct hc_driver dwc2_hc_driver = {
.description = "dwc2_hsotg",
.product_desc = "DWC OTG Controller",
@ -4911,7 +4979,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg)
for (i = 0; i < MAX_EPS_CHANNELS; i++) {
struct dwc2_host_chan *chan = hsotg->hc_ptr_array[i];
if (chan != NULL) {
if (chan) {
dev_dbg(hsotg->dev, "HCD Free channel #%i, chan=%p\n",
i, chan);
hsotg->hc_ptr_array[i] = NULL;
@ -4919,7 +4987,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg)
}
}
if (hsotg->params.host_dma > 0) {
if (hsotg->params.host_dma) {
if (hsotg->status_buf) {
dma_free_coherent(hsotg->dev, DWC2_HCD_STATUS_BUF_SIZE,
hsotg->status_buf,
@ -4967,8 +5035,10 @@ static void dwc2_hcd_release(struct dwc2_hsotg *hsotg)
* USB bus with the core and calls the hc_driver->start() function. It returns
* a negative error on failure.
*/
int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
{
struct platform_device *pdev = to_platform_device(hsotg->dev);
struct resource *res;
struct usb_hcd *hcd;
struct dwc2_host_chan *channel;
u32 hcfg;
@ -4999,32 +5069,41 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
hsotg->last_frame_num = HFNUM_MAX_FRNUM;
/* Check if the bus driver or platform code has setup a dma_mask */
if (hsotg->params.host_dma > 0 &&
hsotg->dev->dma_mask == NULL) {
if (hsotg->params.host_dma &&
!hsotg->dev->dma_mask) {
dev_warn(hsotg->dev,
"dma_mask not set, disabling DMA\n");
hsotg->params.host_dma = 0;
hsotg->params.dma_desc_enable = 0;
hsotg->params.host_dma = false;
hsotg->params.dma_desc_enable = false;
}
/* Set device flags indicating whether the HCD supports DMA */
if (hsotg->params.host_dma > 0) {
if (hsotg->params.host_dma) {
if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0)
dev_warn(hsotg->dev, "can't set DMA mask\n");
if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0)
dev_warn(hsotg->dev, "can't set coherent DMA mask\n");
}
if (hsotg->params.change_speed_quirk) {
dwc2_hc_driver.free_dev = dwc2_free_dev;
dwc2_hc_driver.reset_device = dwc2_reset_device;
}
hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev));
if (!hcd)
goto error1;
if (hsotg->params.host_dma <= 0)
if (!hsotg->params.host_dma)
hcd->self.uses_dma = 0;
hcd->has_tt = 1;
((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
((struct wrapper_priv_data *)&hcd->hcd_priv)->hsotg = hsotg;
hsotg->priv = hcd;
/*
@ -5072,7 +5151,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
for (i = 0; i < num_channels; i++) {
channel = kzalloc(sizeof(*channel), GFP_KERNEL);
if (channel == NULL)
if (!channel)
goto error3;
channel->hc_num = i;
INIT_LIST_HEAD(&channel->split_order_list_entry);
@ -5091,7 +5170,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* done after usb_add_hcd since that function allocates the DMA buffer
* pool.
*/
if (hsotg->params.host_dma > 0)
if (hsotg->params.host_dma)
hsotg->status_buf = dma_alloc_coherent(hsotg->dev,
DWC2_HCD_STATUS_BUF_SIZE,
&hsotg->status_buf_dma, GFP_KERNEL);
@ -5121,8 +5200,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* Disable descriptor dma mode since it will not be
* usable.
*/
hsotg->params.dma_desc_enable = 0;
hsotg->params.dma_desc_fs_enable = 0;
hsotg->params.dma_desc_enable = false;
hsotg->params.dma_desc_fs_enable = false;
}
hsotg->desc_hsisoc_cache = kmem_cache_create("dwc2-hsisoc-desc",
@ -5138,8 +5217,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* Disable descriptor dma mode since it will not be
* usable.
*/
hsotg->params.dma_desc_enable = 0;
hsotg->params.dma_desc_fs_enable = 0;
hsotg->params.dma_desc_enable = false;
hsotg->params.dma_desc_fs_enable = false;
}
}
@ -5164,7 +5243,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* allocates the DMA buffer pool, registers the USB bus, requests the
* IRQ line, and calls hcd_start method.
*/
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
retval = usb_add_hcd(hcd, hsotg->irq, IRQF_SHARED);
if (retval < 0)
goto error4;

View file

@ -521,29 +521,29 @@ static inline u8 dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info *pipe)
return !dwc2_hcd_is_pipe_in(pipe);
}
extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq);
extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg);
int dwc2_hcd_init(struct dwc2_hsotg *hsotg);
void dwc2_hcd_remove(struct dwc2_hsotg *hsotg);
/* Transaction Execution Functions */
extern enum dwc2_transaction_type dwc2_hcd_select_transactions(
enum dwc2_transaction_type dwc2_hcd_select_transactions(
struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
enum dwc2_transaction_type tr_type);
void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
enum dwc2_transaction_type tr_type);
/* Schedule Queue Functions */
/* Implemented in hcd_queue.c */
extern struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
struct dwc2_hcd_urb *urb,
struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
struct dwc2_hcd_urb *urb,
gfp_t mem_flags);
extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
extern void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
int sched_csplit);
void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
int sched_csplit);
extern void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb);
extern int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
struct dwc2_qh *qh);
void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb);
int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
struct dwc2_qh *qh);
/* Unlinks and frees a QTD */
static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
@ -556,15 +556,15 @@ static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
}
/* Descriptor DMA support functions */
extern void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh);
extern void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan, int chnum,
void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh);
void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan, int chnum,
enum dwc2_halt_status halt_status);
extern int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
gfp_t mem_flags);
extern void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
gfp_t mem_flags);
void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
/* Check if QH is non-periodic */
#define dwc2_qh_is_non_per(_qh_ptr_) \
@ -732,8 +732,8 @@ static inline u16 dwc2_hcd_get_ep_bandwidth(struct dwc2_hsotg *hsotg,
return qh->host_us;
}
extern void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan, int chnum,
void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan, int chnum,
struct dwc2_qtd *qtd);
/* HCD Core API */
@ -746,14 +746,14 @@ extern void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
* Returns IRQ_HANDLED if interrupt is handled
* Return IRQ_NONE if interrupt is not handled
*/
extern irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg);
irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg);
/**
* dwc2_hcd_stop() - Halts the DWC_otg host mode operation
*
* @hsotg: The DWC2 HCD
*/
extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
/**
* dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host,
@ -761,7 +761,7 @@ extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
*
* @hsotg: The DWC2 HCD
*/
extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
/**
* dwc2_hcd_dump_state() - Dumps hsotg state
@ -771,7 +771,7 @@ extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
* NOTE: This function will be removed once the peripheral controller code
* is integrated and the driver is stable
*/
extern void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg);
void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg);
/**
* dwc2_hcd_dump_frrem() - Dumps the average frame remaining at SOF
@ -784,7 +784,7 @@ extern void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg);
* NOTE: This function will be removed once the peripheral controller code
* is integrated and the driver is stable
*/
extern void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg);
void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg);
/* URB interface */
@ -793,15 +793,15 @@ extern void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg);
#define URB_SEND_ZERO_PACKET 0x2
/* Host driver callbacks */
extern struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg,
void *context, gfp_t mem_flags,
int *ttport);
struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg,
void *context, gfp_t mem_flags,
int *ttport);
extern void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg,
struct dwc2_tt *dwc_tt);
extern int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context);
extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
int status);
void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg,
struct dwc2_tt *dwc_tt);
int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context);
void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
int status);
#ifdef DEBUG
/*

View file

@ -89,8 +89,8 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
{
struct kmem_cache *desc_cache;
if (qh->ep_type == USB_ENDPOINT_XFER_ISOC
&& qh->dev_speed == USB_SPEED_HIGH)
if (qh->ep_type == USB_ENDPOINT_XFER_ISOC &&
qh->dev_speed == USB_SPEED_HIGH)
desc_cache = hsotg->desc_hsisoc_cache;
else
desc_cache = hsotg->desc_gen_cache;
@ -106,7 +106,7 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
qh->desc_list_sz,
DMA_TO_DEVICE);
qh->n_bytes = kzalloc(sizeof(u32) * dwc2_max_desc_num(qh), flags);
qh->n_bytes = kcalloc(dwc2_max_desc_num(qh), sizeof(u32), flags);
if (!qh->n_bytes) {
dma_unmap_single(hsotg->dev, qh->desc_list_dma,
qh->desc_list_sz,
@ -123,8 +123,8 @@ static void dwc2_desc_list_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{
struct kmem_cache *desc_cache;
if (qh->ep_type == USB_ENDPOINT_XFER_ISOC
&& qh->dev_speed == USB_SPEED_HIGH)
if (qh->ep_type == USB_ENDPOINT_XFER_ISOC &&
qh->dev_speed == USB_SPEED_HIGH)
desc_cache = hsotg->desc_hsisoc_cache;
else
desc_cache = hsotg->desc_gen_cache;
@ -175,7 +175,6 @@ static void dwc2_frame_list_free(struct dwc2_hsotg *hsotg)
hsotg->frame_list = NULL;
spin_unlock_irqrestore(&hsotg->lock, flags);
}
static void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en)
@ -297,7 +296,7 @@ static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan = qh->channel;
if (dwc2_qh_is_non_per(qh)) {
if (hsotg->params.uframe_sched > 0)
if (hsotg->params.uframe_sched)
hsotg->available_host_channels++;
else
hsotg->non_periodic_channels--;
@ -404,7 +403,7 @@ void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC ||
qh->ep_type == USB_ENDPOINT_XFER_INT) &&
(hsotg->params.uframe_sched > 0 ||
(hsotg->params.uframe_sched ||
!hsotg->periodic_channels) && hsotg->frame_list) {
dwc2_per_sched_disable(hsotg);
dwc2_frame_list_free(hsotg);
@ -570,7 +569,7 @@ static void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
#endif
dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma +
qh->desc_list_dma +
(idx * sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE);
@ -776,7 +775,7 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
n_desc - 1,
&qh->desc_list[n_desc - 1]);
dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma +
qh->desc_list_dma +
((n_desc - 1) *
sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_dma_desc),
@ -816,7 +815,7 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
dev_vdbg(hsotg->dev, "set A bit in desc 0 (%p)\n",
&qh->desc_list[0]);
dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma,
qh->desc_list_dma,
sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE);
}
@ -1064,7 +1063,7 @@ stop_scan:
}
static int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan,
struct dwc2_host_chan *chan,
struct dwc2_qtd *qtd,
struct dwc2_dma_desc *dma_desc,
enum dwc2_halt_status halt_status,

View file

@ -60,7 +60,7 @@ static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg)
if (expected != curr_frame_number)
dwc2_sch_vdbg(hsotg, "MISSED SOF %04x != %04x\n",
expected, curr_frame_number);
expected, curr_frame_number);
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
if (hsotg->frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
@ -163,7 +163,7 @@ static void dwc2_sof_intr(struct dwc2_hsotg *hsotg)
* (micro)frame
*/
list_move_tail(&qh->qh_list_entry,
&hsotg->periodic_sched_ready);
&hsotg->periodic_sched_ready);
}
}
tr_type = dwc2_hcd_select_transactions(hsotg);
@ -297,8 +297,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
HCFG_FSLSPCLKSEL_SHIFT;
if (prtspd == HPRT0_SPD_LOW_SPEED &&
params->host_ls_low_power_phy_clk ==
DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) {
params->host_ls_low_power_phy_clk) {
/* 6 MHZ */
dev_vdbg(hsotg->dev,
"FS_PHY programming HCFG to 6 MHz\n");
@ -398,7 +397,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
if (hsotg->params.dma_desc_fs_enable) {
u32 hcfg;
hsotg->params.dma_desc_enable = 0;
hsotg->params.dma_desc_enable = false;
hsotg->new_connection = false;
hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg &= ~HCFG_DESCDMA;
@ -442,7 +441,7 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg,
count = (hctsiz & TSIZ_XFERSIZE_MASK) >>
TSIZ_XFERSIZE_SHIFT;
length = chan->xfer_len - count;
if (short_read != NULL)
if (short_read)
*short_read = (count != 0);
} else if (chan->qh->do_split) {
length = qtd->ssplit_out_xfer_count;
@ -604,7 +603,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
/* Skip whole frame */
if (chan->qh->do_split &&
chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in &&
hsotg->params.host_dma > 0) {
hsotg->params.host_dma) {
qtd->complete_split = 0;
qtd->isoc_split_offset = 0;
}
@ -743,7 +742,7 @@ cleanup:
dwc2_hc_cleanup(hsotg, chan);
list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
if (hsotg->params.uframe_sched > 0) {
if (hsotg->params.uframe_sched) {
hsotg->available_host_channels++;
} else {
switch (chan->ep_type) {
@ -789,7 +788,7 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "%s()\n", __func__);
if (hsotg->params.host_dma > 0) {
if (hsotg->params.host_dma) {
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "DMA enabled\n");
dwc2_release_channel(hsotg, chan, qtd, halt_status);
@ -823,7 +822,7 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
* processed.
*/
list_move_tail(&chan->qh->qh_list_entry,
&hsotg->periodic_sched_assigned);
&hsotg->periodic_sched_assigned);
/*
* Make sure the Periodic Tx FIFO Empty interrupt is
@ -979,7 +978,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, halt_status);
if (pipe_type == USB_ENDPOINT_XFER_ISOC)
/* Do not disable the interrupt, just clear it */
@ -990,7 +989,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
/* Handle xfer complete on CSPLIT */
if (chan->qh->do_split) {
if (chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in &&
hsotg->params.host_dma > 0) {
hsotg->params.host_dma) {
if (qtd->complete_split &&
dwc2_xfercomp_isoc_split_in(hsotg, chan, chnum,
qtd))
@ -1078,7 +1077,8 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
dev_vdbg(hsotg->dev, " Isochronous transfer complete\n");
if (qtd->isoc_split_pos == DWC2_HCSPLT_XACTPOS_ALL)
halt_status = dwc2_update_isoc_urb_state(hsotg, chan,
chnum, qtd, DWC2_HC_XFER_COMPLETE);
chnum, qtd,
DWC2_HC_XFER_COMPLETE);
dwc2_complete_periodic_xfer(hsotg, chan, chnum, qtd,
halt_status);
break;
@ -1102,7 +1102,7 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg,
dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: STALL Received--\n",
chnum);
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
DWC2_HC_XFER_STALL);
goto handle_stall_done;
@ -1212,7 +1212,7 @@ static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg,
switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
case USB_ENDPOINT_XFER_CONTROL:
case USB_ENDPOINT_XFER_BULK:
if (hsotg->params.host_dma > 0 && chan->ep_is_in) {
if (hsotg->params.host_dma && chan->ep_is_in) {
/*
* NAK interrupts are enabled on bulk/control IN
* transfers in DMA mode for the sole purpose of
@ -1358,7 +1358,7 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
*/
if (chan->do_split && chan->complete_split) {
if (chan->ep_is_in && chan->ep_type == USB_ENDPOINT_XFER_ISOC &&
hsotg->params.host_dma > 0) {
hsotg->params.host_dma) {
qtd->complete_split = 0;
qtd->isoc_split_offset = 0;
qtd->isoc_frame_index++;
@ -1379,7 +1379,7 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh = chan->qh;
bool past_end;
if (hsotg->params.uframe_sched <= 0) {
if (!hsotg->params.uframe_sched) {
int frnum = dwc2_hcd_get_frame_number(hsotg);
/* Don't have num_hs_transfers; simple logic */
@ -1389,22 +1389,27 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
int end_frnum;
/*
* Figure out the end frame based on schedule.
*
* We don't want to go on trying again and again
* forever. Let's stop when we've done all the
* transfers that were scheduled.
*
* We're going to be comparing start_active_frame
* and next_active_frame, both of which are 1
* before the time the packet goes on the wire,
* so that cancels out. Basically if had 1
* transfer and we saw 1 NYET then we're done.
* We're getting a NYET here so if next >=
* (start + num_transfers) we're done. The
* complexity is that for all but ISOC_OUT we
* skip one slot.
*/
* Figure out the end frame based on
* schedule.
*
* We don't want to go on trying again
* and again forever. Let's stop when
* we've done all the transfers that
* were scheduled.
*
* We're going to be comparing
* start_active_frame and
* next_active_frame, both of which
* are 1 before the time the packet
* goes on the wire, so that cancels
* out. Basically if had 1 transfer
* and we saw 1 NYET then we're done.
* We're getting a NYET here so if
* next >= (start + num_transfers)
* we're done. The complexity is that
* for all but ISOC_OUT we skip one
* slot.
*/
end_frnum = dwc2_frame_num_inc(
qh->start_active_frame,
qh->num_hs_transfers);
@ -1472,7 +1477,7 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg,
dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
DWC2_HC_XFER_BABBLE_ERR);
goto disable_int;
@ -1577,7 +1582,7 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg,
dev_err(hsotg->dev, " Interval: %d\n", urb->interval);
/* Core halts the channel for Descriptor DMA mode */
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
DWC2_HC_XFER_AHB_ERR);
goto handle_ahberr_done;
@ -1609,7 +1614,7 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg,
dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
if (hsotg->params.dma_desc_enable > 0) {
if (hsotg->params.dma_desc_enable) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
DWC2_HC_XFER_XACT_ERR);
goto handle_xacterr_done;
@ -1620,7 +1625,6 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg,
case USB_ENDPOINT_XFER_BULK:
qtd->error_count++;
if (!chan->qh->ping_state) {
dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb,
qtd, DWC2_HC_XFER_XACT_ERR);
dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
@ -1645,7 +1649,7 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg,
enum dwc2_halt_status halt_status;
halt_status = dwc2_update_isoc_urb_state(hsotg, chan,
chnum, qtd, DWC2_HC_XFER_XACT_ERR);
chnum, qtd, DWC2_HC_XFER_XACT_ERR);
dwc2_halt_channel(hsotg, chan, qtd, halt_status);
}
break;
@ -1803,8 +1807,8 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE ||
(chan->halt_status == DWC2_HC_XFER_AHB_ERR &&
hsotg->params.dma_desc_enable <= 0)) {
if (hsotg->params.dma_desc_enable > 0)
!hsotg->params.dma_desc_enable)) {
if (hsotg->params.dma_desc_enable)
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
chan->halt_status);
else
@ -1835,7 +1839,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
} else if (chan->hcint & HCINTMSK_STALL) {
dwc2_hc_stall_intr(hsotg, chan, chnum, qtd);
} else if ((chan->hcint & HCINTMSK_XACTERR) &&
hsotg->params.dma_desc_enable <= 0) {
!hsotg->params.dma_desc_enable) {
if (out_nak_enh) {
if (chan->hcint &
(HCINTMSK_NYET | HCINTMSK_NAK | HCINTMSK_ACK)) {
@ -1855,10 +1859,10 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
*/
dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
} else if ((chan->hcint & HCINTMSK_XCS_XACT) &&
hsotg->params.dma_desc_enable > 0) {
hsotg->params.dma_desc_enable) {
dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
} else if ((chan->hcint & HCINTMSK_AHBERR) &&
hsotg->params.dma_desc_enable > 0) {
hsotg->params.dma_desc_enable) {
dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd);
} else if (chan->hcint & HCINTMSK_BBLERR) {
dwc2_hc_babble_intr(hsotg, chan, chnum, qtd);
@ -1951,7 +1955,7 @@ static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg,
dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: Channel Halted--\n",
chnum);
if (hsotg->params.host_dma > 0) {
if (hsotg->params.host_dma) {
dwc2_hc_chhltd_intr_dma(hsotg, chan, chnum, qtd);
} else {
if (!dwc2_halt_status_ok(hsotg, chan, chnum, qtd))
@ -1970,7 +1974,7 @@ static bool dwc2_check_qtd_still_ok(struct dwc2_qtd *qtd, struct dwc2_qh *qh)
{
struct dwc2_qtd *cur_head;
if (qh == NULL)
if (!qh)
return false;
cur_head = list_first_entry(&qh->qtd_list, struct dwc2_qtd,
@ -2028,7 +2032,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
* interrupt unmasked
*/
WARN_ON(hcint != HCINTMSK_CHHLTD);
if (hsotg->params.dma_desc_enable > 0)
if (hsotg->params.dma_desc_enable)
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
chan->halt_status);
else
@ -2056,7 +2060,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
qtd = list_first_entry(&chan->qh->qtd_list, struct dwc2_qtd,
qtd_list_entry);
if (hsotg->params.host_dma <= 0) {
if (!hsotg->params.host_dma) {
if ((hcint & HCINTMSK_CHHLTD) && hcint != HCINTMSK_CHHLTD)
hcint &= ~HCINTMSK_CHHLTD;
}

View file

@ -76,14 +76,13 @@ static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg)
int num_channels;
num_channels = hsotg->params.host_channels;
if (hsotg->periodic_channels + hsotg->non_periodic_channels <
num_channels
&& hsotg->periodic_channels < num_channels - 1) {
if ((hsotg->periodic_channels + hsotg->non_periodic_channels <
num_channels) && (hsotg->periodic_channels < num_channels - 1)) {
status = 0;
} else {
dev_dbg(hsotg->dev,
"%s: Total channels: %d, Periodic: %d, "
"Non-periodic: %d\n", __func__, num_channels,
"%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
__func__, num_channels,
hsotg->periodic_channels, hsotg->non_periodic_channels);
status = -ENOSPC;
}
@ -485,7 +484,6 @@ static void pmap_print(unsigned long *map, int bits_per_period,
}
}
struct dwc2_qh_print_data {
struct dwc2_hsotg *hsotg;
struct dwc2_qh *qh;
@ -558,7 +556,6 @@ static void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg,
DWC2_HS_SCHEDULE_UFRAMES, "uFrame", "us",
dwc2_qh_print, &print_data);
}
return;
}
#else
static inline void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg,
@ -587,7 +584,7 @@ static int dwc2_ls_pmap_schedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
unsigned long *map = dwc2_get_ls_map(hsotg, qh);
int slice;
if (map == NULL)
if (!map)
return -EINVAL;
/*
@ -626,7 +623,7 @@ static void dwc2_ls_pmap_unschedule(struct dwc2_hsotg *hsotg,
unsigned long *map = dwc2_get_ls_map(hsotg, qh);
/* Schedule should have failed, so no worries about no error code */
if (map == NULL)
if (!map)
return;
pmap_unschedule(map, DWC2_LS_PERIODIC_SLICES_PER_FRAME,
@ -1107,7 +1104,7 @@ static void dwc2_pick_first_frame(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
next_active_frame = earliest_frame;
/* Get the "no microframe schduler" out of the way... */
if (hsotg->params.uframe_sched <= 0) {
if (!hsotg->params.uframe_sched) {
if (qh->do_split)
/* Splits are active at microframe 0 minus 1 */
next_active_frame |= 0x7;
@ -1182,7 +1179,7 @@ exit:
qh->start_active_frame = next_active_frame;
dwc2_sch_vdbg(hsotg, "QH=%p First fn=%04x nxt=%04x\n",
qh, frame_number, qh->next_active_frame);
qh, frame_number, qh->next_active_frame);
}
/**
@ -1200,7 +1197,7 @@ static int dwc2_do_reserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{
int status;
if (hsotg->params.uframe_sched > 0) {
if (hsotg->params.uframe_sched) {
status = dwc2_uframe_schedule(hsotg, qh);
} else {
status = dwc2_periodic_channel_available(hsotg);
@ -1221,7 +1218,7 @@ static int dwc2_do_reserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
return status;
}
if (hsotg->params.uframe_sched <= 0)
if (!hsotg->params.uframe_sched)
/* Reserve periodic channel */
hsotg->periodic_channels++;
@ -1257,7 +1254,7 @@ static void dwc2_do_unreserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
/* Update claimed usecs per (micro)frame */
hsotg->periodic_usecs -= qh->host_us;
if (hsotg->params.uframe_sched > 0) {
if (hsotg->params.uframe_sched) {
dwc2_uframe_unschedule(hsotg, qh);
} else {
/* Release periodic channel reservation */
@ -1394,7 +1391,7 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
qh->unreserve_pending = 0;
if (hsotg->params.dma_desc_enable > 0)
if (hsotg->params.dma_desc_enable)
/* Don't rely on SOF and start in ready schedule */
list_add_tail(&qh->qh_list_entry, &hsotg->periodic_sched_ready);
else
@ -1501,7 +1498,6 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
device_ns += dwc_tt->usb_tt->think_time;
qh->device_us = NS_TO_US(device_ns);
qh->device_interval = urb->interval;
qh->host_interval = urb->interval * (do_split ? 8 : 1);
@ -1587,7 +1583,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
* Return: Pointer to the newly allocated QH, or NULL on error
*/
struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
struct dwc2_hcd_urb *urb,
struct dwc2_hcd_urb *urb,
gfp_t mem_flags)
{
struct dwc2_qh *qh;
@ -1602,7 +1598,7 @@ struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
dwc2_qh_init(hsotg, qh, urb, mem_flags);
if (hsotg->params.dma_desc_enable > 0 &&
if (hsotg->params.dma_desc_enable &&
dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) {
dwc2_hcd_qh_free(hsotg, qh);
return NULL;
@ -1714,7 +1710,7 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
dwc2_deschedule_periodic(hsotg, qh);
hsotg->periodic_qh_count--;
if (!hsotg->periodic_qh_count &&
hsotg->params.dma_desc_enable <= 0) {
!hsotg->params.dma_desc_enable) {
intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
intr_mask &= ~GINTSTS_SOF;
dwc2_writel(intr_mask, hsotg->regs + GINTMSK);
@ -1741,7 +1737,7 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
* Return: number missed by (or 0 if we didn't miss).
*/
static int dwc2_next_for_periodic_split(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh, u16 frame_number)
struct dwc2_qh *qh, u16 frame_number)
{
u16 old_frame = qh->next_active_frame;
u16 prev_frame_number = dwc2_frame_num_dec(frame_number, 1);
@ -1804,7 +1800,7 @@ static int dwc2_next_for_periodic_split(struct dwc2_hsotg *hsotg,
* Return: number missed by (or 0 if we didn't miss).
*/
static int dwc2_next_periodic_start(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh, u16 frame_number)
struct dwc2_qh *qh, u16 frame_number)
{
int missed = 0;
u16 interval = qh->host_interval;
@ -1926,7 +1922,7 @@ void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
missed = dwc2_next_periodic_start(hsotg, qh, frame_number);
dwc2_sch_vdbg(hsotg,
"QH=%p next(%d) fn=%04x, sch=%04x=>%04x (%+d) miss=%d %s\n",
"QH=%p next(%d) fn=%04x, sch=%04x=>%04x (%+d) miss=%d %s\n",
qh, sched_next_periodic_split, frame_number, old_frame,
qh->next_active_frame,
dwc2_frame_num_dec(qh->next_active_frame, old_frame),

View file

@ -40,37 +40,37 @@
#define HSOTG_REG(x) (x)
#define GOTGCTL HSOTG_REG(0x000)
#define GOTGCTL_CHIRPEN (1 << 27)
#define GOTGCTL_CHIRPEN BIT(27)
#define GOTGCTL_MULT_VALID_BC_MASK (0x1f << 22)
#define GOTGCTL_MULT_VALID_BC_SHIFT 22
#define GOTGCTL_OTGVER (1 << 20)
#define GOTGCTL_BSESVLD (1 << 19)
#define GOTGCTL_ASESVLD (1 << 18)
#define GOTGCTL_DBNC_SHORT (1 << 17)
#define GOTGCTL_CONID_B (1 << 16)
#define GOTGCTL_DBNCE_FLTR_BYPASS (1 << 15)
#define GOTGCTL_DEVHNPEN (1 << 11)
#define GOTGCTL_HSTSETHNPEN (1 << 10)
#define GOTGCTL_HNPREQ (1 << 9)
#define GOTGCTL_HSTNEGSCS (1 << 8)
#define GOTGCTL_SESREQ (1 << 1)
#define GOTGCTL_SESREQSCS (1 << 0)
#define GOTGCTL_OTGVER BIT(20)
#define GOTGCTL_BSESVLD BIT(19)
#define GOTGCTL_ASESVLD BIT(18)
#define GOTGCTL_DBNC_SHORT BIT(17)
#define GOTGCTL_CONID_B BIT(16)
#define GOTGCTL_DBNCE_FLTR_BYPASS BIT(15)
#define GOTGCTL_DEVHNPEN BIT(11)
#define GOTGCTL_HSTSETHNPEN BIT(10)
#define GOTGCTL_HNPREQ BIT(9)
#define GOTGCTL_HSTNEGSCS BIT(8)
#define GOTGCTL_SESREQ BIT(1)
#define GOTGCTL_SESREQSCS BIT(0)
#define GOTGINT HSOTG_REG(0x004)
#define GOTGINT_DBNCE_DONE (1 << 19)
#define GOTGINT_A_DEV_TOUT_CHG (1 << 18)
#define GOTGINT_HST_NEG_DET (1 << 17)
#define GOTGINT_HST_NEG_SUC_STS_CHNG (1 << 9)
#define GOTGINT_SES_REQ_SUC_STS_CHNG (1 << 8)
#define GOTGINT_SES_END_DET (1 << 2)
#define GOTGINT_DBNCE_DONE BIT(19)
#define GOTGINT_A_DEV_TOUT_CHG BIT(18)
#define GOTGINT_HST_NEG_DET BIT(17)
#define GOTGINT_HST_NEG_SUC_STS_CHNG BIT(9)
#define GOTGINT_SES_REQ_SUC_STS_CHNG BIT(8)
#define GOTGINT_SES_END_DET BIT(2)
#define GAHBCFG HSOTG_REG(0x008)
#define GAHBCFG_AHB_SINGLE (1 << 23)
#define GAHBCFG_NOTI_ALL_DMA_WRIT (1 << 22)
#define GAHBCFG_REM_MEM_SUPP (1 << 21)
#define GAHBCFG_P_TXF_EMP_LVL (1 << 8)
#define GAHBCFG_NP_TXF_EMP_LVL (1 << 7)
#define GAHBCFG_DMA_EN (1 << 5)
#define GAHBCFG_AHB_SINGLE BIT(23)
#define GAHBCFG_NOTI_ALL_DMA_WRIT BIT(22)
#define GAHBCFG_REM_MEM_SUPP BIT(21)
#define GAHBCFG_P_TXF_EMP_LVL BIT(8)
#define GAHBCFG_NP_TXF_EMP_LVL BIT(7)
#define GAHBCFG_DMA_EN BIT(5)
#define GAHBCFG_HBSTLEN_MASK (0xf << 1)
#define GAHBCFG_HBSTLEN_SHIFT 1
#define GAHBCFG_HBSTLEN_SINGLE 0
@ -78,38 +78,38 @@
#define GAHBCFG_HBSTLEN_INCR4 3
#define GAHBCFG_HBSTLEN_INCR8 5
#define GAHBCFG_HBSTLEN_INCR16 7
#define GAHBCFG_GLBL_INTR_EN (1 << 0)
#define GAHBCFG_GLBL_INTR_EN BIT(0)
#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \
GAHBCFG_NP_TXF_EMP_LVL | \
GAHBCFG_DMA_EN | \
GAHBCFG_GLBL_INTR_EN)
#define GUSBCFG HSOTG_REG(0x00C)
#define GUSBCFG_FORCEDEVMODE (1 << 30)
#define GUSBCFG_FORCEHOSTMODE (1 << 29)
#define GUSBCFG_TXENDDELAY (1 << 28)
#define GUSBCFG_ICTRAFFICPULLREMOVE (1 << 27)
#define GUSBCFG_ICUSBCAP (1 << 26)
#define GUSBCFG_ULPI_INT_PROT_DIS (1 << 25)
#define GUSBCFG_INDICATORPASSTHROUGH (1 << 24)
#define GUSBCFG_INDICATORCOMPLEMENT (1 << 23)
#define GUSBCFG_TERMSELDLPULSE (1 << 22)
#define GUSBCFG_ULPI_INT_VBUS_IND (1 << 21)
#define GUSBCFG_ULPI_EXT_VBUS_DRV (1 << 20)
#define GUSBCFG_ULPI_CLK_SUSP_M (1 << 19)
#define GUSBCFG_ULPI_AUTO_RES (1 << 18)
#define GUSBCFG_ULPI_FS_LS (1 << 17)
#define GUSBCFG_OTG_UTMI_FS_SEL (1 << 16)
#define GUSBCFG_PHY_LP_CLK_SEL (1 << 15)
#define GUSBCFG_FORCEDEVMODE BIT(30)
#define GUSBCFG_FORCEHOSTMODE BIT(29)
#define GUSBCFG_TXENDDELAY BIT(28)
#define GUSBCFG_ICTRAFFICPULLREMOVE BIT(27)
#define GUSBCFG_ICUSBCAP BIT(26)
#define GUSBCFG_ULPI_INT_PROT_DIS BIT(25)
#define GUSBCFG_INDICATORPASSTHROUGH BIT(24)
#define GUSBCFG_INDICATORCOMPLEMENT BIT(23)
#define GUSBCFG_TERMSELDLPULSE BIT(22)
#define GUSBCFG_ULPI_INT_VBUS_IND BIT(21)
#define GUSBCFG_ULPI_EXT_VBUS_DRV BIT(20)
#define GUSBCFG_ULPI_CLK_SUSP_M BIT(19)
#define GUSBCFG_ULPI_AUTO_RES BIT(18)
#define GUSBCFG_ULPI_FS_LS BIT(17)
#define GUSBCFG_OTG_UTMI_FS_SEL BIT(16)
#define GUSBCFG_PHY_LP_CLK_SEL BIT(15)
#define GUSBCFG_USBTRDTIM_MASK (0xf << 10)
#define GUSBCFG_USBTRDTIM_SHIFT 10
#define GUSBCFG_HNPCAP (1 << 9)
#define GUSBCFG_SRPCAP (1 << 8)
#define GUSBCFG_DDRSEL (1 << 7)
#define GUSBCFG_PHYSEL (1 << 6)
#define GUSBCFG_FSINTF (1 << 5)
#define GUSBCFG_ULPI_UTMI_SEL (1 << 4)
#define GUSBCFG_PHYIF16 (1 << 3)
#define GUSBCFG_HNPCAP BIT(9)
#define GUSBCFG_SRPCAP BIT(8)
#define GUSBCFG_DDRSEL BIT(7)
#define GUSBCFG_PHYSEL BIT(6)
#define GUSBCFG_FSINTF BIT(5)
#define GUSBCFG_ULPI_UTMI_SEL BIT(4)
#define GUSBCFG_PHYIF16 BIT(3)
#define GUSBCFG_PHYIF8 (0 << 3)
#define GUSBCFG_TOUTCAL_MASK (0x7 << 0)
#define GUSBCFG_TOUTCAL_SHIFT 0
@ -117,54 +117,54 @@
#define GUSBCFG_TOUTCAL(_x) ((_x) << 0)
#define GRSTCTL HSOTG_REG(0x010)
#define GRSTCTL_AHBIDLE (1 << 31)
#define GRSTCTL_DMAREQ (1 << 30)
#define GRSTCTL_AHBIDLE BIT(31)
#define GRSTCTL_DMAREQ BIT(30)
#define GRSTCTL_TXFNUM_MASK (0x1f << 6)
#define GRSTCTL_TXFNUM_SHIFT 6
#define GRSTCTL_TXFNUM_LIMIT 0x1f
#define GRSTCTL_TXFNUM(_x) ((_x) << 6)
#define GRSTCTL_TXFFLSH (1 << 5)
#define GRSTCTL_RXFFLSH (1 << 4)
#define GRSTCTL_IN_TKNQ_FLSH (1 << 3)
#define GRSTCTL_FRMCNTRRST (1 << 2)
#define GRSTCTL_HSFTRST (1 << 1)
#define GRSTCTL_CSFTRST (1 << 0)
#define GRSTCTL_TXFFLSH BIT(5)
#define GRSTCTL_RXFFLSH BIT(4)
#define GRSTCTL_IN_TKNQ_FLSH BIT(3)
#define GRSTCTL_FRMCNTRRST BIT(2)
#define GRSTCTL_HSFTRST BIT(1)
#define GRSTCTL_CSFTRST BIT(0)
#define GINTSTS HSOTG_REG(0x014)
#define GINTMSK HSOTG_REG(0x018)
#define GINTSTS_WKUPINT (1 << 31)
#define GINTSTS_SESSREQINT (1 << 30)
#define GINTSTS_DISCONNINT (1 << 29)
#define GINTSTS_CONIDSTSCHNG (1 << 28)
#define GINTSTS_LPMTRANRCVD (1 << 27)
#define GINTSTS_PTXFEMP (1 << 26)
#define GINTSTS_HCHINT (1 << 25)
#define GINTSTS_PRTINT (1 << 24)
#define GINTSTS_RESETDET (1 << 23)
#define GINTSTS_FET_SUSP (1 << 22)
#define GINTSTS_INCOMPL_IP (1 << 21)
#define GINTSTS_INCOMPL_SOOUT (1 << 21)
#define GINTSTS_INCOMPL_SOIN (1 << 20)
#define GINTSTS_OEPINT (1 << 19)
#define GINTSTS_IEPINT (1 << 18)
#define GINTSTS_EPMIS (1 << 17)
#define GINTSTS_RESTOREDONE (1 << 16)
#define GINTSTS_EOPF (1 << 15)
#define GINTSTS_ISOUTDROP (1 << 14)
#define GINTSTS_ENUMDONE (1 << 13)
#define GINTSTS_USBRST (1 << 12)
#define GINTSTS_USBSUSP (1 << 11)
#define GINTSTS_ERLYSUSP (1 << 10)
#define GINTSTS_I2CINT (1 << 9)
#define GINTSTS_ULPI_CK_INT (1 << 8)
#define GINTSTS_GOUTNAKEFF (1 << 7)
#define GINTSTS_GINNAKEFF (1 << 6)
#define GINTSTS_NPTXFEMP (1 << 5)
#define GINTSTS_RXFLVL (1 << 4)
#define GINTSTS_SOF (1 << 3)
#define GINTSTS_OTGINT (1 << 2)
#define GINTSTS_MODEMIS (1 << 1)
#define GINTSTS_CURMODE_HOST (1 << 0)
#define GINTSTS_WKUPINT BIT(31)
#define GINTSTS_SESSREQINT BIT(30)
#define GINTSTS_DISCONNINT BIT(29)
#define GINTSTS_CONIDSTSCHNG BIT(28)
#define GINTSTS_LPMTRANRCVD BIT(27)
#define GINTSTS_PTXFEMP BIT(26)
#define GINTSTS_HCHINT BIT(25)
#define GINTSTS_PRTINT BIT(24)
#define GINTSTS_RESETDET BIT(23)
#define GINTSTS_FET_SUSP BIT(22)
#define GINTSTS_INCOMPL_IP BIT(21)
#define GINTSTS_INCOMPL_SOOUT BIT(21)
#define GINTSTS_INCOMPL_SOIN BIT(20)
#define GINTSTS_OEPINT BIT(19)
#define GINTSTS_IEPINT BIT(18)
#define GINTSTS_EPMIS BIT(17)
#define GINTSTS_RESTOREDONE BIT(16)
#define GINTSTS_EOPF BIT(15)
#define GINTSTS_ISOUTDROP BIT(14)
#define GINTSTS_ENUMDONE BIT(13)
#define GINTSTS_USBRST BIT(12)
#define GINTSTS_USBSUSP BIT(11)
#define GINTSTS_ERLYSUSP BIT(10)
#define GINTSTS_I2CINT BIT(9)
#define GINTSTS_ULPI_CK_INT BIT(8)
#define GINTSTS_GOUTNAKEFF BIT(7)
#define GINTSTS_GINNAKEFF BIT(6)
#define GINTSTS_NPTXFEMP BIT(5)
#define GINTSTS_RXFLVL BIT(4)
#define GINTSTS_SOF BIT(3)
#define GINTSTS_OTGINT BIT(2)
#define GINTSTS_MODEMIS BIT(1)
#define GINTSTS_CURMODE_HOST BIT(0)
#define GRXSTSR HSOTG_REG(0x01C)
#define GRXSTSP HSOTG_REG(0x020)
@ -208,14 +208,14 @@
#define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v) (((_v) >> 0) & 0xffff)
#define GI2CCTL HSOTG_REG(0x0030)
#define GI2CCTL_BSYDNE (1 << 31)
#define GI2CCTL_RW (1 << 30)
#define GI2CCTL_I2CDATSE0 (1 << 28)
#define GI2CCTL_BSYDNE BIT(31)
#define GI2CCTL_RW BIT(30)
#define GI2CCTL_I2CDATSE0 BIT(28)
#define GI2CCTL_I2CDEVADDR_MASK (0x3 << 26)
#define GI2CCTL_I2CDEVADDR_SHIFT 26
#define GI2CCTL_I2CSUSPCTL (1 << 25)
#define GI2CCTL_ACK (1 << 24)
#define GI2CCTL_I2CEN (1 << 23)
#define GI2CCTL_I2CSUSPCTL BIT(25)
#define GI2CCTL_ACK BIT(24)
#define GI2CCTL_I2CEN BIT(23)
#define GI2CCTL_ADDR_MASK (0x7f << 16)
#define GI2CCTL_ADDR_SHIFT 16
#define GI2CCTL_REGADDR_MASK (0xff << 8)
@ -230,16 +230,16 @@
#define GHWCFG1 HSOTG_REG(0x0044)
#define GHWCFG2 HSOTG_REG(0x0048)
#define GHWCFG2_OTG_ENABLE_IC_USB (1 << 31)
#define GHWCFG2_OTG_ENABLE_IC_USB BIT(31)
#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1f << 26)
#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT 26
#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24)
#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT 24
#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22)
#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT 22
#define GHWCFG2_MULTI_PROC_INT (1 << 20)
#define GHWCFG2_DYNAMIC_FIFO (1 << 19)
#define GHWCFG2_PERIO_EP_SUPPORTED (1 << 18)
#define GHWCFG2_MULTI_PROC_INT BIT(20)
#define GHWCFG2_DYNAMIC_FIFO BIT(19)
#define GHWCFG2_PERIO_EP_SUPPORTED BIT(18)
#define GHWCFG2_NUM_HOST_CHAN_MASK (0xf << 14)
#define GHWCFG2_NUM_HOST_CHAN_SHIFT 14
#define GHWCFG2_NUM_DEV_EP_MASK (0xf << 10)
@ -256,7 +256,7 @@
#define GHWCFG2_HS_PHY_TYPE_UTMI 1
#define GHWCFG2_HS_PHY_TYPE_ULPI 2
#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
#define GHWCFG2_POINT2POINT (1 << 5)
#define GHWCFG2_POINT2POINT BIT(5)
#define GHWCFG2_ARCHITECTURE_MASK (0x3 << 3)
#define GHWCFG2_ARCHITECTURE_SHIFT 3
#define GHWCFG2_SLAVE_ONLY_ARCH 0
@ -276,32 +276,32 @@
#define GHWCFG3 HSOTG_REG(0x004c)
#define GHWCFG3_DFIFO_DEPTH_MASK (0xffff << 16)
#define GHWCFG3_DFIFO_DEPTH_SHIFT 16
#define GHWCFG3_OTG_LPM_EN (1 << 15)
#define GHWCFG3_BC_SUPPORT (1 << 14)
#define GHWCFG3_OTG_ENABLE_HSIC (1 << 13)
#define GHWCFG3_ADP_SUPP (1 << 12)
#define GHWCFG3_SYNCH_RESET_TYPE (1 << 11)
#define GHWCFG3_OPTIONAL_FEATURES (1 << 10)
#define GHWCFG3_VENDOR_CTRL_IF (1 << 9)
#define GHWCFG3_I2C (1 << 8)
#define GHWCFG3_OTG_FUNC (1 << 7)
#define GHWCFG3_OTG_LPM_EN BIT(15)
#define GHWCFG3_BC_SUPPORT BIT(14)
#define GHWCFG3_OTG_ENABLE_HSIC BIT(13)
#define GHWCFG3_ADP_SUPP BIT(12)
#define GHWCFG3_SYNCH_RESET_TYPE BIT(11)
#define GHWCFG3_OPTIONAL_FEATURES BIT(10)
#define GHWCFG3_VENDOR_CTRL_IF BIT(9)
#define GHWCFG3_I2C BIT(8)
#define GHWCFG3_OTG_FUNC BIT(7)
#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4)
#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT 4
#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xf << 0)
#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT 0
#define GHWCFG4 HSOTG_REG(0x0050)
#define GHWCFG4_DESC_DMA_DYN (1 << 31)
#define GHWCFG4_DESC_DMA (1 << 30)
#define GHWCFG4_DESC_DMA_DYN BIT(31)
#define GHWCFG4_DESC_DMA BIT(30)
#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
#define GHWCFG4_NUM_IN_EPS_SHIFT 26
#define GHWCFG4_DED_FIFO_EN (1 << 25)
#define GHWCFG4_DED_FIFO_EN BIT(25)
#define GHWCFG4_DED_FIFO_SHIFT 25
#define GHWCFG4_SESSION_END_FILT_EN (1 << 24)
#define GHWCFG4_B_VALID_FILT_EN (1 << 23)
#define GHWCFG4_A_VALID_FILT_EN (1 << 22)
#define GHWCFG4_VBUS_VALID_FILT_EN (1 << 21)
#define GHWCFG4_IDDIG_FILT_EN (1 << 20)
#define GHWCFG4_SESSION_END_FILT_EN BIT(24)
#define GHWCFG4_B_VALID_FILT_EN BIT(23)
#define GHWCFG4_A_VALID_FILT_EN BIT(22)
#define GHWCFG4_VBUS_VALID_FILT_EN BIT(21)
#define GHWCFG4_IDDIG_FILT_EN BIT(20)
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xf << 16)
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14)
@ -309,64 +309,64 @@
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2
#define GHWCFG4_XHIBER (1 << 7)
#define GHWCFG4_HIBER (1 << 6)
#define GHWCFG4_MIN_AHB_FREQ (1 << 5)
#define GHWCFG4_POWER_OPTIMIZ (1 << 4)
#define GHWCFG4_XHIBER BIT(7)
#define GHWCFG4_HIBER BIT(6)
#define GHWCFG4_MIN_AHB_FREQ BIT(5)
#define GHWCFG4_POWER_OPTIMIZ BIT(4)
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xf << 0)
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0
#define GLPMCFG HSOTG_REG(0x0054)
#define GLPMCFG_INV_SEL_HSIC (1 << 31)
#define GLPMCFG_HSIC_CONNECT (1 << 30)
#define GLPMCFG_INV_SEL_HSIC BIT(31)
#define GLPMCFG_HSIC_CONNECT BIT(30)
#define GLPMCFG_RETRY_COUNT_STS_MASK (0x7 << 25)
#define GLPMCFG_RETRY_COUNT_STS_SHIFT 25
#define GLPMCFG_SEND_LPM (1 << 24)
#define GLPMCFG_SEND_LPM BIT(24)
#define GLPMCFG_RETRY_COUNT_MASK (0x7 << 21)
#define GLPMCFG_RETRY_COUNT_SHIFT 21
#define GLPMCFG_LPM_CHAN_INDEX_MASK (0xf << 17)
#define GLPMCFG_LPM_CHAN_INDEX_SHIFT 17
#define GLPMCFG_SLEEP_STATE_RESUMEOK (1 << 16)
#define GLPMCFG_PRT_SLEEP_STS (1 << 15)
#define GLPMCFG_SLEEP_STATE_RESUMEOK BIT(16)
#define GLPMCFG_PRT_SLEEP_STS BIT(15)
#define GLPMCFG_LPM_RESP_MASK (0x3 << 13)
#define GLPMCFG_LPM_RESP_SHIFT 13
#define GLPMCFG_HIRD_THRES_MASK (0x1f << 8)
#define GLPMCFG_HIRD_THRES_SHIFT 8
#define GLPMCFG_HIRD_THRES_EN (0x10 << 8)
#define GLPMCFG_EN_UTMI_SLEEP (1 << 7)
#define GLPMCFG_REM_WKUP_EN (1 << 6)
#define GLPMCFG_EN_UTMI_SLEEP BIT(7)
#define GLPMCFG_REM_WKUP_EN BIT(6)
#define GLPMCFG_HIRD_MASK (0xf << 2)
#define GLPMCFG_HIRD_SHIFT 2
#define GLPMCFG_APPL_RESP (1 << 1)
#define GLPMCFG_LPM_CAP_EN (1 << 0)
#define GLPMCFG_APPL_RESP BIT(1)
#define GLPMCFG_LPM_CAP_EN BIT(0)
#define GPWRDN HSOTG_REG(0x0058)
#define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24)
#define GPWRDN_MULT_VAL_ID_BC_SHIFT 24
#define GPWRDN_ADP_INT (1 << 23)
#define GPWRDN_BSESSVLD (1 << 22)
#define GPWRDN_IDSTS (1 << 21)
#define GPWRDN_ADP_INT BIT(23)
#define GPWRDN_BSESSVLD BIT(22)
#define GPWRDN_IDSTS BIT(21)
#define GPWRDN_LINESTATE_MASK (0x3 << 19)
#define GPWRDN_LINESTATE_SHIFT 19
#define GPWRDN_STS_CHGINT_MSK (1 << 18)
#define GPWRDN_STS_CHGINT (1 << 17)
#define GPWRDN_SRP_DET_MSK (1 << 16)
#define GPWRDN_SRP_DET (1 << 15)
#define GPWRDN_CONNECT_DET_MSK (1 << 14)
#define GPWRDN_CONNECT_DET (1 << 13)
#define GPWRDN_DISCONN_DET_MSK (1 << 12)
#define GPWRDN_DISCONN_DET (1 << 11)
#define GPWRDN_RST_DET_MSK (1 << 10)
#define GPWRDN_RST_DET (1 << 9)
#define GPWRDN_LNSTSCHG_MSK (1 << 8)
#define GPWRDN_LNSTSCHG (1 << 7)
#define GPWRDN_DIS_VBUS (1 << 6)
#define GPWRDN_PWRDNSWTCH (1 << 5)
#define GPWRDN_PWRDNRSTN (1 << 4)
#define GPWRDN_PWRDNCLMP (1 << 3)
#define GPWRDN_RESTORE (1 << 2)
#define GPWRDN_PMUACTV (1 << 1)
#define GPWRDN_PMUINTSEL (1 << 0)
#define GPWRDN_STS_CHGINT_MSK BIT(18)
#define GPWRDN_STS_CHGINT BIT(17)
#define GPWRDN_SRP_DET_MSK BIT(16)
#define GPWRDN_SRP_DET BIT(15)
#define GPWRDN_CONNECT_DET_MSK BIT(14)
#define GPWRDN_CONNECT_DET BIT(13)
#define GPWRDN_DISCONN_DET_MSK BIT(12)
#define GPWRDN_DISCONN_DET BIT(11)
#define GPWRDN_RST_DET_MSK BIT(10)
#define GPWRDN_RST_DET BIT(9)
#define GPWRDN_LNSTSCHG_MSK BIT(8)
#define GPWRDN_LNSTSCHG BIT(7)
#define GPWRDN_DIS_VBUS BIT(6)
#define GPWRDN_PWRDNSWTCH BIT(5)
#define GPWRDN_PWRDNRSTN BIT(4)
#define GPWRDN_PWRDNCLMP BIT(3)
#define GPWRDN_RESTORE BIT(2)
#define GPWRDN_PMUACTV BIT(1)
#define GPWRDN_PMUINTSEL BIT(0)
#define GDFIFOCFG HSOTG_REG(0x005c)
#define GDFIFOCFG_EPINFOBASE_MASK (0xffff << 16)
@ -377,16 +377,16 @@
#define ADPCTL HSOTG_REG(0x0060)
#define ADPCTL_AR_MASK (0x3 << 27)
#define ADPCTL_AR_SHIFT 27
#define ADPCTL_ADP_TMOUT_INT_MSK (1 << 26)
#define ADPCTL_ADP_SNS_INT_MSK (1 << 25)
#define ADPCTL_ADP_PRB_INT_MSK (1 << 24)
#define ADPCTL_ADP_TMOUT_INT (1 << 23)
#define ADPCTL_ADP_SNS_INT (1 << 22)
#define ADPCTL_ADP_PRB_INT (1 << 21)
#define ADPCTL_ADPENA (1 << 20)
#define ADPCTL_ADPRES (1 << 19)
#define ADPCTL_ENASNS (1 << 18)
#define ADPCTL_ENAPRB (1 << 17)
#define ADPCTL_ADP_TMOUT_INT_MSK BIT(26)
#define ADPCTL_ADP_SNS_INT_MSK BIT(25)
#define ADPCTL_ADP_PRB_INT_MSK BIT(24)
#define ADPCTL_ADP_TMOUT_INT BIT(23)
#define ADPCTL_ADP_SNS_INT BIT(22)
#define ADPCTL_ADP_PRB_INT BIT(21)
#define ADPCTL_ADPENA BIT(20)
#define ADPCTL_ADPRES BIT(19)
#define ADPCTL_ENASNS BIT(18)
#define ADPCTL_ENAPRB BIT(17)
#define ADPCTL_RTIM_MASK (0x7ff << 6)
#define ADPCTL_RTIM_SHIFT 6
#define ADPCTL_PRB_PER_MASK (0x3 << 4)
@ -412,7 +412,7 @@
/* Device mode registers */
#define DCFG HSOTG_REG(0x800)
#define DCFG_DESCDMA_EN (1 << 23)
#define DCFG_DESCDMA_EN BIT(23)
#define DCFG_EPMISCNT_MASK (0x1f << 18)
#define DCFG_EPMISCNT_SHIFT 18
#define DCFG_EPMISCNT_LIMIT 0x1f
@ -425,7 +425,7 @@
#define DCFG_DEVADDR_SHIFT 4
#define DCFG_DEVADDR_LIMIT 0x7f
#define DCFG_DEVADDR(_x) ((_x) << 4)
#define DCFG_NZ_STS_OUT_HSHK (1 << 2)
#define DCFG_NZ_STS_OUT_HSHK BIT(2)
#define DCFG_DEVSPD_MASK (0x3 << 0)
#define DCFG_DEVSPD_SHIFT 0
#define DCFG_DEVSPD_HS 0
@ -434,54 +434,54 @@
#define DCFG_DEVSPD_FS48 3
#define DCTL HSOTG_REG(0x804)
#define DCTL_PWRONPRGDONE (1 << 11)
#define DCTL_CGOUTNAK (1 << 10)
#define DCTL_SGOUTNAK (1 << 9)
#define DCTL_CGNPINNAK (1 << 8)
#define DCTL_SGNPINNAK (1 << 7)
#define DCTL_PWRONPRGDONE BIT(11)
#define DCTL_CGOUTNAK BIT(10)
#define DCTL_SGOUTNAK BIT(9)
#define DCTL_CGNPINNAK BIT(8)
#define DCTL_SGNPINNAK BIT(7)
#define DCTL_TSTCTL_MASK (0x7 << 4)
#define DCTL_TSTCTL_SHIFT 4
#define DCTL_GOUTNAKSTS (1 << 3)
#define DCTL_GNPINNAKSTS (1 << 2)
#define DCTL_SFTDISCON (1 << 1)
#define DCTL_RMTWKUPSIG (1 << 0)
#define DCTL_GOUTNAKSTS BIT(3)
#define DCTL_GNPINNAKSTS BIT(2)
#define DCTL_SFTDISCON BIT(1)
#define DCTL_RMTWKUPSIG BIT(0)
#define DSTS HSOTG_REG(0x808)
#define DSTS_SOFFN_MASK (0x3fff << 8)
#define DSTS_SOFFN_SHIFT 8
#define DSTS_SOFFN_LIMIT 0x3fff
#define DSTS_SOFFN(_x) ((_x) << 8)
#define DSTS_ERRATICERR (1 << 3)
#define DSTS_ERRATICERR BIT(3)
#define DSTS_ENUMSPD_MASK (0x3 << 1)
#define DSTS_ENUMSPD_SHIFT 1
#define DSTS_ENUMSPD_HS 0
#define DSTS_ENUMSPD_FS 1
#define DSTS_ENUMSPD_LS 2
#define DSTS_ENUMSPD_FS48 3
#define DSTS_SUSPSTS (1 << 0)
#define DSTS_SUSPSTS BIT(0)
#define DIEPMSK HSOTG_REG(0x810)
#define DIEPMSK_NAKMSK (1 << 13)
#define DIEPMSK_BNAININTRMSK (1 << 9)
#define DIEPMSK_TXFIFOUNDRNMSK (1 << 8)
#define DIEPMSK_TXFIFOEMPTY (1 << 7)
#define DIEPMSK_INEPNAKEFFMSK (1 << 6)
#define DIEPMSK_INTKNEPMISMSK (1 << 5)
#define DIEPMSK_INTKNTXFEMPMSK (1 << 4)
#define DIEPMSK_TIMEOUTMSK (1 << 3)
#define DIEPMSK_AHBERRMSK (1 << 2)
#define DIEPMSK_EPDISBLDMSK (1 << 1)
#define DIEPMSK_XFERCOMPLMSK (1 << 0)
#define DIEPMSK_NAKMSK BIT(13)
#define DIEPMSK_BNAININTRMSK BIT(9)
#define DIEPMSK_TXFIFOUNDRNMSK BIT(8)
#define DIEPMSK_TXFIFOEMPTY BIT(7)
#define DIEPMSK_INEPNAKEFFMSK BIT(6)
#define DIEPMSK_INTKNEPMISMSK BIT(5)
#define DIEPMSK_INTKNTXFEMPMSK BIT(4)
#define DIEPMSK_TIMEOUTMSK BIT(3)
#define DIEPMSK_AHBERRMSK BIT(2)
#define DIEPMSK_EPDISBLDMSK BIT(1)
#define DIEPMSK_XFERCOMPLMSK BIT(0)
#define DOEPMSK HSOTG_REG(0x814)
#define DOEPMSK_BNAMSK (1 << 9)
#define DOEPMSK_BACK2BACKSETUP (1 << 6)
#define DOEPMSK_STSPHSERCVDMSK (1 << 5)
#define DOEPMSK_OUTTKNEPDISMSK (1 << 4)
#define DOEPMSK_SETUPMSK (1 << 3)
#define DOEPMSK_AHBERRMSK (1 << 2)
#define DOEPMSK_EPDISBLDMSK (1 << 1)
#define DOEPMSK_XFERCOMPLMSK (1 << 0)
#define DOEPMSK_BNAMSK BIT(9)
#define DOEPMSK_BACK2BACKSETUP BIT(6)
#define DOEPMSK_STSPHSERCVDMSK BIT(5)
#define DOEPMSK_OUTTKNEPDISMSK BIT(4)
#define DOEPMSK_SETUPMSK BIT(3)
#define DOEPMSK_AHBERRMSK BIT(2)
#define DOEPMSK_EPDISBLDMSK BIT(1)
#define DOEPMSK_XFERCOMPLMSK BIT(0)
#define DAINT HSOTG_REG(0x818)
#define DAINTMSK HSOTG_REG(0x81C)
@ -516,30 +516,30 @@
#define D0EPCTL_MPS_16 2
#define D0EPCTL_MPS_8 3
#define DXEPCTL_EPENA (1 << 31)
#define DXEPCTL_EPDIS (1 << 30)
#define DXEPCTL_SETD1PID (1 << 29)
#define DXEPCTL_SETODDFR (1 << 29)
#define DXEPCTL_SETD0PID (1 << 28)
#define DXEPCTL_SETEVENFR (1 << 28)
#define DXEPCTL_SNAK (1 << 27)
#define DXEPCTL_CNAK (1 << 26)
#define DXEPCTL_EPENA BIT(31)
#define DXEPCTL_EPDIS BIT(30)
#define DXEPCTL_SETD1PID BIT(29)
#define DXEPCTL_SETODDFR BIT(29)
#define DXEPCTL_SETD0PID BIT(28)
#define DXEPCTL_SETEVENFR BIT(28)
#define DXEPCTL_SNAK BIT(27)
#define DXEPCTL_CNAK BIT(26)
#define DXEPCTL_TXFNUM_MASK (0xf << 22)
#define DXEPCTL_TXFNUM_SHIFT 22
#define DXEPCTL_TXFNUM_LIMIT 0xf
#define DXEPCTL_TXFNUM(_x) ((_x) << 22)
#define DXEPCTL_STALL (1 << 21)
#define DXEPCTL_SNP (1 << 20)
#define DXEPCTL_STALL BIT(21)
#define DXEPCTL_SNP BIT(20)
#define DXEPCTL_EPTYPE_MASK (0x3 << 18)
#define DXEPCTL_EPTYPE_CONTROL (0x0 << 18)
#define DXEPCTL_EPTYPE_ISO (0x1 << 18)
#define DXEPCTL_EPTYPE_BULK (0x2 << 18)
#define DXEPCTL_EPTYPE_INTERRUPT (0x3 << 18)
#define DXEPCTL_NAKSTS (1 << 17)
#define DXEPCTL_DPID (1 << 16)
#define DXEPCTL_EOFRNUM (1 << 16)
#define DXEPCTL_USBACTEP (1 << 15)
#define DXEPCTL_NAKSTS BIT(17)
#define DXEPCTL_DPID BIT(16)
#define DXEPCTL_EOFRNUM BIT(16)
#define DXEPCTL_USBACTEP BIT(15)
#define DXEPCTL_NEXTEP_MASK (0xf << 11)
#define DXEPCTL_NEXTEP_SHIFT 11
#define DXEPCTL_NEXTEP_LIMIT 0xf
@ -551,26 +551,26 @@
#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
#define DXEPINT_SETUP_RCVD (1 << 15)
#define DXEPINT_NYETINTRPT (1 << 14)
#define DXEPINT_NAKINTRPT (1 << 13)
#define DXEPINT_BBLEERRINTRPT (1 << 12)
#define DXEPINT_PKTDRPSTS (1 << 11)
#define DXEPINT_BNAINTR (1 << 9)
#define DXEPINT_TXFIFOUNDRN (1 << 8)
#define DXEPINT_OUTPKTERR (1 << 8)
#define DXEPINT_TXFEMP (1 << 7)
#define DXEPINT_INEPNAKEFF (1 << 6)
#define DXEPINT_BACK2BACKSETUP (1 << 6)
#define DXEPINT_INTKNEPMIS (1 << 5)
#define DXEPINT_STSPHSERCVD (1 << 5)
#define DXEPINT_INTKNTXFEMP (1 << 4)
#define DXEPINT_OUTTKNEPDIS (1 << 4)
#define DXEPINT_TIMEOUT (1 << 3)
#define DXEPINT_SETUP (1 << 3)
#define DXEPINT_AHBERR (1 << 2)
#define DXEPINT_EPDISBLD (1 << 1)
#define DXEPINT_XFERCOMPL (1 << 0)
#define DXEPINT_SETUP_RCVD BIT(15)
#define DXEPINT_NYETINTRPT BIT(14)
#define DXEPINT_NAKINTRPT BIT(13)
#define DXEPINT_BBLEERRINTRPT BIT(12)
#define DXEPINT_PKTDRPSTS BIT(11)
#define DXEPINT_BNAINTR BIT(9)
#define DXEPINT_TXFIFOUNDRN BIT(8)
#define DXEPINT_OUTPKTERR BIT(8)
#define DXEPINT_TXFEMP BIT(7)
#define DXEPINT_INEPNAKEFF BIT(6)
#define DXEPINT_BACK2BACKSETUP BIT(6)
#define DXEPINT_INTKNEPMIS BIT(5)
#define DXEPINT_STSPHSERCVD BIT(5)
#define DXEPINT_INTKNTXFEMP BIT(4)
#define DXEPINT_OUTTKNEPDIS BIT(4)
#define DXEPINT_TIMEOUT BIT(3)
#define DXEPINT_SETUP BIT(3)
#define DXEPINT_AHBERR BIT(2)
#define DXEPINT_EPDISBLD BIT(1)
#define DXEPINT_XFERCOMPL BIT(0)
#define DIEPTSIZ0 HSOTG_REG(0x910)
#define DIEPTSIZ0_PKTCNT_MASK (0x3 << 19)
@ -587,7 +587,7 @@
#define DOEPTSIZ0_SUPCNT_SHIFT 29
#define DOEPTSIZ0_SUPCNT_LIMIT 0x3
#define DOEPTSIZ0_SUPCNT(_x) ((_x) << 29)
#define DOEPTSIZ0_PKTCNT (1 << 19)
#define DOEPTSIZ0_PKTCNT BIT(19)
#define DOEPTSIZ0_XFERSIZE_MASK (0x7f << 0)
#define DOEPTSIZ0_XFERSIZE_SHIFT 0
@ -614,55 +614,55 @@
#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20))
#define PCGCTL HSOTG_REG(0x0e00)
#define PCGCTL_IF_DEV_MODE (1 << 31)
#define PCGCTL_IF_DEV_MODE BIT(31)
#define PCGCTL_P2HD_PRT_SPD_MASK (0x3 << 29)
#define PCGCTL_P2HD_PRT_SPD_SHIFT 29
#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK (0x3 << 27)
#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT 27
#define PCGCTL_MAC_DEV_ADDR_MASK (0x7f << 20)
#define PCGCTL_MAC_DEV_ADDR_SHIFT 20
#define PCGCTL_MAX_TERMSEL (1 << 19)
#define PCGCTL_MAX_TERMSEL BIT(19)
#define PCGCTL_MAX_XCVRSELECT_MASK (0x3 << 17)
#define PCGCTL_MAX_XCVRSELECT_SHIFT 17
#define PCGCTL_PORT_POWER (1 << 16)
#define PCGCTL_PORT_POWER BIT(16)
#define PCGCTL_PRT_CLK_SEL_MASK (0x3 << 14)
#define PCGCTL_PRT_CLK_SEL_SHIFT 14
#define PCGCTL_ESS_REG_RESTORED (1 << 13)
#define PCGCTL_EXTND_HIBER_SWITCH (1 << 12)
#define PCGCTL_EXTND_HIBER_PWRCLMP (1 << 11)
#define PCGCTL_ENBL_EXTND_HIBER (1 << 10)
#define PCGCTL_RESTOREMODE (1 << 9)
#define PCGCTL_RESETAFTSUSP (1 << 8)
#define PCGCTL_DEEP_SLEEP (1 << 7)
#define PCGCTL_PHY_IN_SLEEP (1 << 6)
#define PCGCTL_ENBL_SLEEP_GATING (1 << 5)
#define PCGCTL_RSTPDWNMODULE (1 << 3)
#define PCGCTL_PWRCLMP (1 << 2)
#define PCGCTL_GATEHCLK (1 << 1)
#define PCGCTL_STOPPCLK (1 << 0)
#define PCGCTL_ESS_REG_RESTORED BIT(13)
#define PCGCTL_EXTND_HIBER_SWITCH BIT(12)
#define PCGCTL_EXTND_HIBER_PWRCLMP BIT(11)
#define PCGCTL_ENBL_EXTND_HIBER BIT(10)
#define PCGCTL_RESTOREMODE BIT(9)
#define PCGCTL_RESETAFTSUSP BIT(8)
#define PCGCTL_DEEP_SLEEP BIT(7)
#define PCGCTL_PHY_IN_SLEEP BIT(6)
#define PCGCTL_ENBL_SLEEP_GATING BIT(5)
#define PCGCTL_RSTPDWNMODULE BIT(3)
#define PCGCTL_PWRCLMP BIT(2)
#define PCGCTL_GATEHCLK BIT(1)
#define PCGCTL_STOPPCLK BIT(0)
#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000))
/* Host Mode Registers */
#define HCFG HSOTG_REG(0x0400)
#define HCFG_MODECHTIMEN (1 << 31)
#define HCFG_PERSCHEDENA (1 << 26)
#define HCFG_MODECHTIMEN BIT(31)
#define HCFG_PERSCHEDENA BIT(26)
#define HCFG_FRLISTEN_MASK (0x3 << 24)
#define HCFG_FRLISTEN_SHIFT 24
#define HCFG_FRLISTEN_8 (0 << 24)
#define FRLISTEN_8_SIZE 8
#define HCFG_FRLISTEN_16 (1 << 24)
#define HCFG_FRLISTEN_16 BIT(24)
#define FRLISTEN_16_SIZE 16
#define HCFG_FRLISTEN_32 (2 << 24)
#define FRLISTEN_32_SIZE 32
#define HCFG_FRLISTEN_64 (3 << 24)
#define FRLISTEN_64_SIZE 64
#define HCFG_DESCDMA (1 << 23)
#define HCFG_DESCDMA BIT(23)
#define HCFG_RESVALID_MASK (0xff << 8)
#define HCFG_RESVALID_SHIFT 8
#define HCFG_ENA32KHZ (1 << 7)
#define HCFG_FSLSSUPP (1 << 2)
#define HCFG_ENA32KHZ BIT(7)
#define HCFG_FSLSSUPP BIT(2)
#define HCFG_FSLSPCLKSEL_MASK (0x3 << 0)
#define HCFG_FSLSPCLKSEL_SHIFT 0
#define HCFG_FSLSPCLKSEL_30_60_MHZ 0
@ -672,7 +672,7 @@
#define HFIR HSOTG_REG(0x0404)
#define HFIR_FRINT_MASK (0xffff << 0)
#define HFIR_FRINT_SHIFT 0
#define HFIR_RLDCTRL (1 << 16)
#define HFIR_RLDCTRL BIT(16)
#define HFNUM HSOTG_REG(0x0408)
#define HFNUM_FRREM_MASK (0xffff << 16)
@ -682,12 +682,12 @@
#define HFNUM_MAX_FRNUM 0x3fff
#define HPTXSTS HSOTG_REG(0x0410)
#define TXSTS_QTOP_ODD (1 << 31)
#define TXSTS_QTOP_ODD BIT(31)
#define TXSTS_QTOP_CHNEP_MASK (0xf << 27)
#define TXSTS_QTOP_CHNEP_SHIFT 27
#define TXSTS_QTOP_TOKEN_MASK (0x3 << 25)
#define TXSTS_QTOP_TOKEN_SHIFT 25
#define TXSTS_QTOP_TERMINATE (1 << 24)
#define TXSTS_QTOP_TERMINATE BIT(24)
#define TXSTS_QSPCAVAIL_MASK (0xff << 16)
#define TXSTS_QSPCAVAIL_SHIFT 16
#define TXSTS_FSPCAVAIL_MASK (0xffff << 0)
@ -705,39 +705,39 @@
#define HPRT0_SPD_LOW_SPEED 2
#define HPRT0_TSTCTL_MASK (0xf << 13)
#define HPRT0_TSTCTL_SHIFT 13
#define HPRT0_PWR (1 << 12)
#define HPRT0_PWR BIT(12)
#define HPRT0_LNSTS_MASK (0x3 << 10)
#define HPRT0_LNSTS_SHIFT 10
#define HPRT0_RST (1 << 8)
#define HPRT0_SUSP (1 << 7)
#define HPRT0_RES (1 << 6)
#define HPRT0_OVRCURRCHG (1 << 5)
#define HPRT0_OVRCURRACT (1 << 4)
#define HPRT0_ENACHG (1 << 3)
#define HPRT0_ENA (1 << 2)
#define HPRT0_CONNDET (1 << 1)
#define HPRT0_CONNSTS (1 << 0)
#define HPRT0_RST BIT(8)
#define HPRT0_SUSP BIT(7)
#define HPRT0_RES BIT(6)
#define HPRT0_OVRCURRCHG BIT(5)
#define HPRT0_OVRCURRACT BIT(4)
#define HPRT0_ENACHG BIT(3)
#define HPRT0_ENA BIT(2)
#define HPRT0_CONNDET BIT(1)
#define HPRT0_CONNSTS BIT(0)
#define HCCHAR(_ch) HSOTG_REG(0x0500 + 0x20 * (_ch))
#define HCCHAR_CHENA (1 << 31)
#define HCCHAR_CHDIS (1 << 30)
#define HCCHAR_ODDFRM (1 << 29)
#define HCCHAR_CHENA BIT(31)
#define HCCHAR_CHDIS BIT(30)
#define HCCHAR_ODDFRM BIT(29)
#define HCCHAR_DEVADDR_MASK (0x7f << 22)
#define HCCHAR_DEVADDR_SHIFT 22
#define HCCHAR_MULTICNT_MASK (0x3 << 20)
#define HCCHAR_MULTICNT_SHIFT 20
#define HCCHAR_EPTYPE_MASK (0x3 << 18)
#define HCCHAR_EPTYPE_SHIFT 18
#define HCCHAR_LSPDDEV (1 << 17)
#define HCCHAR_EPDIR (1 << 15)
#define HCCHAR_LSPDDEV BIT(17)
#define HCCHAR_EPDIR BIT(15)
#define HCCHAR_EPNUM_MASK (0xf << 11)
#define HCCHAR_EPNUM_SHIFT 11
#define HCCHAR_MPS_MASK (0x7ff << 0)
#define HCCHAR_MPS_SHIFT 0
#define HCSPLT(_ch) HSOTG_REG(0x0504 + 0x20 * (_ch))
#define HCSPLT_SPLTENA (1 << 31)
#define HCSPLT_COMPSPLT (1 << 16)
#define HCSPLT_SPLTENA BIT(31)
#define HCSPLT_COMPSPLT BIT(16)
#define HCSPLT_XACTPOS_MASK (0x3 << 14)
#define HCSPLT_XACTPOS_SHIFT 14
#define HCSPLT_XACTPOS_MID 0
@ -752,23 +752,23 @@
#define HCINT(_ch) HSOTG_REG(0x0508 + 0x20 * (_ch))
#define HCINTMSK(_ch) HSOTG_REG(0x050c + 0x20 * (_ch))
#define HCINTMSK_RESERVED14_31 (0x3ffff << 14)
#define HCINTMSK_FRM_LIST_ROLL (1 << 13)
#define HCINTMSK_XCS_XACT (1 << 12)
#define HCINTMSK_BNA (1 << 11)
#define HCINTMSK_DATATGLERR (1 << 10)
#define HCINTMSK_FRMOVRUN (1 << 9)
#define HCINTMSK_BBLERR (1 << 8)
#define HCINTMSK_XACTERR (1 << 7)
#define HCINTMSK_NYET (1 << 6)
#define HCINTMSK_ACK (1 << 5)
#define HCINTMSK_NAK (1 << 4)
#define HCINTMSK_STALL (1 << 3)
#define HCINTMSK_AHBERR (1 << 2)
#define HCINTMSK_CHHLTD (1 << 1)
#define HCINTMSK_XFERCOMPL (1 << 0)
#define HCINTMSK_FRM_LIST_ROLL BIT(13)
#define HCINTMSK_XCS_XACT BIT(12)
#define HCINTMSK_BNA BIT(11)
#define HCINTMSK_DATATGLERR BIT(10)
#define HCINTMSK_FRMOVRUN BIT(9)
#define HCINTMSK_BBLERR BIT(8)
#define HCINTMSK_XACTERR BIT(7)
#define HCINTMSK_NYET BIT(6)
#define HCINTMSK_ACK BIT(5)
#define HCINTMSK_NAK BIT(4)
#define HCINTMSK_STALL BIT(3)
#define HCINTMSK_AHBERR BIT(2)
#define HCINTMSK_CHHLTD BIT(1)
#define HCINTMSK_XFERCOMPL BIT(0)
#define HCTSIZ(_ch) HSOTG_REG(0x0510 + 0x20 * (_ch))
#define TSIZ_DOPNG (1 << 31)
#define TSIZ_DOPNG BIT(31)
#define TSIZ_SC_MC_PID_MASK (0x3 << 29)
#define TSIZ_SC_MC_PID_SHIFT 29
#define TSIZ_SC_MC_PID_DATA0 0
@ -808,14 +808,14 @@ struct dwc2_dma_desc {
/* Host Mode DMA descriptor status quadlet */
#define HOST_DMA_A (1 << 31)
#define HOST_DMA_A BIT(31)
#define HOST_DMA_STS_MASK (0x3 << 28)
#define HOST_DMA_STS_SHIFT 28
#define HOST_DMA_STS_PKTERR (1 << 28)
#define HOST_DMA_EOL (1 << 26)
#define HOST_DMA_IOC (1 << 25)
#define HOST_DMA_SUP (1 << 24)
#define HOST_DMA_ALT_QTD (1 << 23)
#define HOST_DMA_STS_PKTERR BIT(28)
#define HOST_DMA_EOL BIT(26)
#define HOST_DMA_IOC BIT(25)
#define HOST_DMA_SUP BIT(24)
#define HOST_DMA_ALT_QTD BIT(23)
#define HOST_DMA_QTD_OFFSET_MASK (0x3f << 17)
#define HOST_DMA_QTD_OFFSET_SHIFT 17
#define HOST_DMA_ISOC_NBYTES_MASK (0xfff << 0)
@ -837,11 +837,11 @@ struct dwc2_dma_desc {
#define DEV_DMA_STS_SUCC 0
#define DEV_DMA_STS_BUFF_FLUSH 1
#define DEV_DMA_STS_BUFF_ERR 3
#define DEV_DMA_L (1 << 27)
#define DEV_DMA_SHORT (1 << 26)
#define DEV_DMA_IOC (1 << 25)
#define DEV_DMA_SR (1 << 24)
#define DEV_DMA_MTRF (1 << 23)
#define DEV_DMA_L BIT(27)
#define DEV_DMA_SHORT BIT(26)
#define DEV_DMA_IOC BIT(25)
#define DEV_DMA_SR BIT(24)
#define DEV_DMA_MTRF BIT(23)
#define DEV_DMA_ISOC_PID_MASK (0x3 << 23)
#define DEV_DMA_ISOC_PID_SHIFT 23
#define DEV_DMA_ISOC_PID_DATA0 0

File diff suppressed because it is too large Load diff

View file

@ -87,7 +87,7 @@ static void dwc2_pci_remove(struct pci_dev *pci)
}
static int dwc2_pci_probe(struct pci_dev *pci,
const struct pci_device_id *id)
const struct pci_device_id *id)
{
struct resource res[2];
struct platform_device *dwc2;

View file

@ -111,7 +111,7 @@ static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg)
if (mode != hsotg->dr_mode) {
dev_warn(hsotg->dev,
"Configuration mismatch. dr_mode forced to %s\n",
"Configuration mismatch. dr_mode forced to %s\n",
mode == USB_DR_MODE_HOST ? "host" : "device");
hsotg->dr_mode = mode;
@ -136,11 +136,11 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
return ret;
}
if (hsotg->uphy)
if (hsotg->uphy) {
ret = usb_phy_init(hsotg->uphy);
else if (hsotg->plat && hsotg->plat->phy_init)
} else if (hsotg->plat && hsotg->plat->phy_init) {
ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
else {
} else {
ret = phy_power_on(hsotg->phy);
if (ret == 0)
ret = phy_init(hsotg->phy);
@ -170,11 +170,11 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
struct platform_device *pdev = to_platform_device(hsotg->dev);
int ret = 0;
if (hsotg->uphy)
if (hsotg->uphy) {
usb_phy_shutdown(hsotg->uphy);
else if (hsotg->plat && hsotg->plat->phy_exit)
} else if (hsotg->plat && hsotg->plat->phy_exit) {
ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
else {
} else {
ret = phy_exit(hsotg->phy);
if (ret == 0)
ret = phy_power_off(hsotg->phy);
@ -445,7 +445,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
}
if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
retval = dwc2_hcd_init(hsotg, hsotg->irq);
retval = dwc2_hcd_init(hsotg);
if (retval) {
if (hsotg->gadget_enabled)
dwc2_hsotg_remove(hsotg);

View file

@ -40,6 +40,7 @@
/* Global constants */
#define DWC3_PULL_UP_TIMEOUT 500 /* ms */
#define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */
#define DWC3_BOUNCE_SIZE 1024 /* size of a superspeed bulk */
#define DWC3_EP0_BOUNCE_SIZE 512
#define DWC3_ENDPOINTS_NUM 32
#define DWC3_XHCI_RESOURCES_NUM 2
@ -724,6 +725,7 @@ struct dwc3_hwparams {
* @epnum: endpoint number to which this request refers
* @trb: pointer to struct dwc3_trb
* @trb_dma: DMA address of @trb
* @unaligned: true for OUT endpoints with length not divisible by maxp
* @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped
* @queued: true when request has been queued to HW
@ -740,6 +742,7 @@ struct dwc3_request {
struct dwc3_trb *trb;
dma_addr_t trb_dma;
unsigned unaligned:1;
unsigned direction:1;
unsigned mapped:1;
unsigned started:1;
@ -857,12 +860,14 @@ struct dwc3_scratchpad_array {
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
struct dwc3_trb *ep0_trb;
void *bounce;
void *ep0_bounce;
void *zlp_buf;
void *scratchbuf;
u8 *setup_buf;
dma_addr_t ctrl_req_addr;
dma_addr_t ep0_trb_addr;
dma_addr_t bounce_addr;
dma_addr_t ep0_bounce_addr;
dma_addr_t scratch_addr;
struct dwc3_request ep0_usb_req;

View file

@ -128,10 +128,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
clk_prepare_enable(exynos->clk);
exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
if (IS_ERR(exynos->susp_clk)) {
dev_info(dev, "no suspend clk specified\n");
if (IS_ERR(exynos->susp_clk))
exynos->susp_clk = NULL;
}
clk_prepare_enable(exynos->susp_clk);
if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
@ -290,7 +288,6 @@ static struct platform_driver dwc3_exynos_driver = {
module_platform_driver(dwc3_exynos_driver);
MODULE_ALIAS("platform:exynos-dwc3");
MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");

View file

@ -426,20 +426,20 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
}
omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
ret = extcon_register_notifier(edev, EXTCON_USB,
&omap->vbus_nb);
ret = devm_extcon_register_notifier(omap->dev, edev,
EXTCON_USB, &omap->vbus_nb);
if (ret < 0)
dev_vdbg(omap->dev, "failed to register notifier for USB\n");
omap->id_nb.notifier_call = dwc3_omap_id_notifier;
ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
&omap->id_nb);
ret = devm_extcon_register_notifier(omap->dev, edev,
EXTCON_USB_HOST, &omap->id_nb);
if (ret < 0)
dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
if (extcon_get_cable_state_(edev, EXTCON_USB) == true)
if (extcon_get_state(edev, EXTCON_USB) == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == true)
if (extcon_get_state(edev, EXTCON_USB_HOST) == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
omap->edev = edev;
@ -528,17 +528,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)
ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) {
dev_err(&pdev->dev, "failed to create dwc3 core\n");
goto err2;
goto err1;
}
dwc3_omap_enable_irqs(omap);
enable_irq(omap->irq);
return 0;
err2:
extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
err1:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
@ -550,8 +546,6 @@ static int dwc3_omap_remove(struct platform_device *pdev)
{
struct dwc3_omap *omap = platform_get_drvdata(pdev);
extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
dwc3_omap_disable_irqs(omap);
disable_irq(omap->irq);
of_platform_depopulate(omap->dev);

View file

@ -1123,7 +1123,21 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) {
struct dwc3_ep *dep = dwc->eps[0];
WARN_ON_ONCE(event->endpoint_number != 1);
/*
* We should handle the delay STATUS phase here if the
* request for handling delay STATUS has been queued
* into the list.
*/
if (!list_empty(&dep->pending_list)) {
dwc->delayed_status = false;
usb_gadget_set_state(&dwc->gadget,
USB_STATE_CONFIGURED);
dwc3_ep0_do_control_status(dwc, event);
}
return;
}

View file

@ -833,29 +833,14 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep,
static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep);
/**
* dwc3_prepare_one_trb - setup one TRB from one request
* @dep: endpoint for which this request is prepared
* @req: dwc3_request pointer
*/
static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
struct dwc3_request *req, dma_addr_t dma,
unsigned length, unsigned chain, unsigned node)
static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
dma_addr_t dma, unsigned length, unsigned chain, unsigned node,
unsigned stream_id, unsigned short_not_ok, unsigned no_interrupt)
{
struct dwc3_trb *trb;
struct dwc3 *dwc = dep->dwc;
struct usb_gadget *gadget = &dwc->gadget;
enum usb_device_speed speed = gadget->speed;
trb = &dep->trb_pool[dep->trb_enqueue];
if (!req->trb) {
dwc3_gadget_move_started_request(req);
req->trb = trb;
req->trb_dma = dwc3_trb_dma_offset(dep, trb);
dep->queued_requests++;
}
dwc3_ep_inc_enq(dep);
trb->size = DWC3_TRB_SIZE_LENGTH(length);
@ -900,11 +885,11 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
if (usb_endpoint_dir_out(dep->endpoint.desc)) {
trb->ctrl |= DWC3_TRB_CTRL_CSP;
if (req->request.short_not_ok)
if (short_not_ok)
trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
}
if ((!req->request.no_interrupt && !chain) ||
if ((!no_interrupt && !chain) ||
(dwc3_calc_trbs_left(dep) == 0))
trb->ctrl |= DWC3_TRB_CTRL_IOC;
@ -912,13 +897,43 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
trb->ctrl |= DWC3_TRB_CTRL_CHN;
if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable)
trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(stream_id);
trb->ctrl |= DWC3_TRB_CTRL_HWO;
trace_dwc3_prepare_trb(dep, trb);
}
/**
* dwc3_prepare_one_trb - setup one TRB from one request
* @dep: endpoint for which this request is prepared
* @req: dwc3_request pointer
* @chain: should this TRB be chained to the next?
* @node: only for isochronous endpoints. First TRB needs different type.
*/
static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
struct dwc3_request *req, unsigned chain, unsigned node)
{
struct dwc3_trb *trb;
unsigned length = req->request.length;
unsigned stream_id = req->request.stream_id;
unsigned short_not_ok = req->request.short_not_ok;
unsigned no_interrupt = req->request.no_interrupt;
dma_addr_t dma = req->request.dma;
trb = &dep->trb_pool[dep->trb_enqueue];
if (!req->trb) {
dwc3_gadget_move_started_request(req);
req->trb = trb;
req->trb_dma = dwc3_trb_dma_offset(dep, trb);
dep->queued_requests++;
}
__dwc3_prepare_one_trb(dep, trb, dma, length, chain, node,
stream_id, short_not_ok, no_interrupt);
}
/**
* dwc3_ep_prev_trb() - Returns the previous TRB in the ring
* @dep: The endpoint with the TRB ring
@ -974,21 +989,36 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
{
struct scatterlist *sg = req->sg;
struct scatterlist *s;
unsigned int length;
dma_addr_t dma;
int i;
for_each_sg(sg, s, req->num_pending_sgs, i) {
unsigned int length = req->request.length;
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
unsigned int rem = length % maxp;
unsigned chain = true;
length = sg_dma_len(s);
dma = sg_dma_address(s);
if (sg_is_last(s))
chain = false;
dwc3_prepare_one_trb(dep, req, dma, length,
chain, i);
if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {
struct dwc3 *dwc = dep->dwc;
struct dwc3_trb *trb;
req->unaligned = true;
/* prepare normal TRB */
dwc3_prepare_one_trb(dep, req, true, i);
/* Now prepare one extra TRB to align transfer size */
trb = &dep->trb_pool[dep->trb_enqueue];
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr,
maxp - rem, false, 0,
req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
} else {
dwc3_prepare_one_trb(dep, req, chain, i);
}
if (!dwc3_calc_trbs_left(dep))
break;
@ -998,14 +1028,28 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
struct dwc3_request *req)
{
unsigned int length;
dma_addr_t dma;
unsigned int length = req->request.length;
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
unsigned int rem = length % maxp;
dma = req->request.dma;
length = req->request.length;
if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) {
struct dwc3 *dwc = dep->dwc;
struct dwc3_trb *trb;
dwc3_prepare_one_trb(dep, req, dma, length,
false, 0);
req->unaligned = true;
/* prepare normal TRB */
dwc3_prepare_one_trb(dep, req, true, 0);
/* Now prepare one extra TRB to align transfer size */
trb = &dep->trb_pool[dep->trb_enqueue];
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem,
false, 0, req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
} else {
dwc3_prepare_one_trb(dep, req, false, 0);
}
}
/*
@ -1335,6 +1379,9 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
unsigned transfer_in_flight;
unsigned started;
if (dep->flags & DWC3_EP_STALL)
return 0;
if (dep->number > 1)
trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
else
@ -1356,6 +1403,8 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
else
dep->flags |= DWC3_EP_STALL;
} else {
if (!(dep->flags & DWC3_EP_STALL))
return 0;
ret = dwc3_send_clear_stall_ep_cmd(dep);
if (ret)
@ -1918,6 +1967,44 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
dep->endpoint.ops = &dwc3_gadget_ep0_ops;
if (!epnum)
dwc->gadget.ep0 = &dep->endpoint;
} else if (direction) {
int mdwidth;
int size;
int ret;
int num;
mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
/* MDWIDTH is represented in bits, we need it in bytes */
mdwidth /= 8;
size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(i));
size = DWC3_GTXFIFOSIZ_TXFDEF(size);
/* FIFO Depth is in MDWDITH bytes. Multiply */
size *= mdwidth;
num = size / 1024;
if (num == 0)
num = 1;
/*
* FIFO sizes account an extra MDWIDTH * (num + 1) bytes for
* internal overhead. We don't really know how these are used,
* but documentation say it exists.
*/
size -= mdwidth * (num + 1);
size /= num;
usb_ep_set_maxpacket_limit(&dep->endpoint, size);
dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list,
&dwc->gadget.ep_list);
ret = dwc3_alloc_trb_pool(dep);
if (ret)
return ret;
} else {
int ret;
@ -2029,6 +2116,16 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO))
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
/*
* If we're dealing with unaligned size OUT transfer, we will be left
* with one TRB pending in the ring. We need to manually clear HWO bit
* from that TRB.
*/
if (req->unaligned && (trb->ctrl & DWC3_TRB_CTRL_HWO)) {
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
return 1;
}
if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
return 1;
@ -2118,6 +2215,13 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
event, status, chain);
}
if (req->unaligned) {
trb = &dep->trb_pool[dep->trb_dequeue];
ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
event, status, false);
req->unaligned = false;
}
req->request.actual = length - req->remaining;
if ((req->request.actual < length) && req->num_pending_sgs)
@ -3019,6 +3123,13 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err4;
}
dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE,
&dwc->bounce_addr, GFP_KERNEL);
if (!dwc->bounce) {
ret = -ENOMEM;
goto err5;
}
init_completion(&dwc->ep0_in_setup);
dwc->gadget.ops = &dwc3_gadget_ops;
@ -3049,12 +3160,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
dwc->gadget.max_speed = dwc->maximum_speed;
/*
* Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
* on ep out.
*/
dwc->gadget.quirk_ep_out_aligned_size = true;
/*
* REVISIT: Here we should clear all pending IRQs to be
* sure we're starting from a well known location.
@ -3062,15 +3167,18 @@ int dwc3_gadget_init(struct dwc3 *dwc)
ret = dwc3_gadget_init_endpoints(dwc);
if (ret)
goto err5;
goto err6;
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to register udc\n");
goto err5;
goto err6;
}
return 0;
err6:
dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
dwc->bounce_addr);
err5:
kfree(dwc->zlp_buf);
@ -3103,6 +3211,8 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dwc3_gadget_free_endpoints(dwc);
dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
dwc->bounce_addr);
dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE,
dwc->ep0_bounce, dwc->ep0_bounce_addr);

View file

@ -54,11 +54,12 @@ out:
int dwc3_host_init(struct dwc3 *dwc)
{
struct property_entry props[2];
struct property_entry props[3];
struct platform_device *xhci;
int ret, irq;
struct resource *res;
struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
int prop_idx = 0;
irq = dwc3_host_get_irq(dwc);
if (irq < 0)
@ -97,8 +98,22 @@ int dwc3_host_init(struct dwc3 *dwc)
memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
if (dwc->usb3_lpm_capable) {
props[0].name = "usb3-lpm-capable";
if (dwc->usb3_lpm_capable)
props[prop_idx++].name = "usb3-lpm-capable";
/**
* WORKAROUND: dwc3 revisions <=3.00a have a limitation
* where Port Disable command doesn't work.
*
* The suggested workaround is that we avoid Port Disable
* completely.
*
* This following flag tells XHCI to do just that.
*/
if (dwc->revision <= DWC3_REVISION_300A)
props[prop_idx++].name = "quirk-broken-port-ped";
if (prop_idx) {
ret = platform_device_add_properties(xhci, props);
if (ret) {
dev_err(dwc->dev, "failed to add properties to xHCI\n");

View file

@ -580,7 +580,6 @@ try_again:
USB_DEBUG_DEVNUM);
goto err;
}
devnum = USB_DEBUG_DEVNUM;
dbgp_printk("debug device renamed to 127\n");
}

View file

@ -1230,7 +1230,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
desc = epfile->ep->descs[desc_idx];
spin_unlock_irq(&epfile->ffs->eps_lock);
ret = copy_to_user((void *)value, desc, sizeof(*desc));
ret = copy_to_user((void *)value, desc, desc->bLength);
if (ret)
ret = -EFAULT;
return ret;
@ -2101,7 +2101,7 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
case FFS_ENDPOINT:
d = (void *)desc;
helper->eps_count++;
if (helper->eps_count >= 15)
if (helper->eps_count >= FFS_MAX_EPS_COUNT)
return -EINVAL;
/* Check if descriptors for any speed were already parsed */
if (!helper->ffs->eps_count && !helper->ffs->interfaces_count)

View file

@ -50,12 +50,12 @@ struct f_hidg {
/* recv report */
struct list_head completed_out_req;
spinlock_t spinlock;
spinlock_t read_spinlock;
wait_queue_head_t read_queue;
unsigned int qlen;
/* send report */
struct mutex lock;
spinlock_t write_spinlock;
bool write_pending;
wait_queue_head_t write_queue;
struct usb_request *req;
@ -258,28 +258,35 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
spin_lock_irqsave(&hidg->spinlock, flags);
spin_lock_irqsave(&hidg->read_spinlock, flags);
#define READ_COND (!list_empty(&hidg->completed_out_req))
/* wait for at least one buffer to complete */
while (!READ_COND) {
spin_unlock_irqrestore(&hidg->spinlock, flags);
spin_unlock_irqrestore(&hidg->read_spinlock, flags);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible(hidg->read_queue, READ_COND))
return -ERESTARTSYS;
spin_lock_irqsave(&hidg->spinlock, flags);
spin_lock_irqsave(&hidg->read_spinlock, flags);
}
/* pick the first one */
list = list_first_entry(&hidg->completed_out_req,
struct f_hidg_req_list, list);
/*
* Remove this from list to protect it from beign free()
* while host disables our function
*/
list_del(&list->list);
req = list->req;
count = min_t(unsigned int, count, req->actual - list->pos);
spin_unlock_irqrestore(&hidg->spinlock, flags);
spin_unlock_irqrestore(&hidg->read_spinlock, flags);
/* copy to user outside spinlock */
count -= copy_to_user(buffer, req->buf + list->pos, count);
@ -292,15 +299,20 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
* call, taking into account its current read position.
*/
if (list->pos == req->actual) {
spin_lock_irqsave(&hidg->spinlock, flags);
list_del(&list->list);
kfree(list);
spin_unlock_irqrestore(&hidg->spinlock, flags);
req->length = hidg->report_length;
ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL);
if (ret < 0)
if (ret < 0) {
free_ep_req(hidg->out_ep, req);
return ret;
}
} else {
spin_lock_irqsave(&hidg->read_spinlock, flags);
list_add(&list->list, &hidg->completed_out_req);
spin_unlock_irqrestore(&hidg->read_spinlock, flags);
wake_up(&hidg->read_queue);
}
return count;
@ -309,13 +321,16 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_hidg *hidg = (struct f_hidg *)ep->driver_data;
unsigned long flags;
if (req->status != 0) {
ERROR(hidg->func.config->cdev,
"End Point Request ERROR: %d\n", req->status);
}
spin_lock_irqsave(&hidg->write_spinlock, flags);
hidg->write_pending = 0;
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
wake_up(&hidg->write_queue);
}
@ -323,18 +338,20 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
size_t count, loff_t *offp)
{
struct f_hidg *hidg = file->private_data;
struct usb_request *req;
unsigned long flags;
ssize_t status = -ENOMEM;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
mutex_lock(&hidg->lock);
spin_lock_irqsave(&hidg->write_spinlock, flags);
#define WRITE_COND (!hidg->write_pending)
try_again:
/* write queue */
while (!WRITE_COND) {
mutex_unlock(&hidg->lock);
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
@ -342,37 +359,59 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
hidg->write_queue, WRITE_COND))
return -ERESTARTSYS;
mutex_lock(&hidg->lock);
spin_lock_irqsave(&hidg->write_spinlock, flags);
}
hidg->write_pending = 1;
req = hidg->req;
count = min_t(unsigned, count, hidg->report_length);
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
status = copy_from_user(hidg->req->buf, buffer, count);
if (status != 0) {
ERROR(hidg->func.config->cdev,
"copy_from_user error\n");
mutex_unlock(&hidg->lock);
return -EINVAL;
status = -EINVAL;
goto release_write_pending;
}
hidg->req->status = 0;
hidg->req->zero = 0;
hidg->req->length = count;
hidg->req->complete = f_hidg_req_complete;
hidg->req->context = hidg;
hidg->write_pending = 1;
spin_lock_irqsave(&hidg->write_spinlock, flags);
/* we our function has been disabled by host */
if (!hidg->req) {
free_ep_req(hidg->in_ep, hidg->req);
/*
* TODO
* Should we fail with error here?
*/
goto try_again;
}
req->status = 0;
req->zero = 0;
req->length = count;
req->complete = f_hidg_req_complete;
req->context = hidg;
status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
if (status < 0) {
ERROR(hidg->func.config->cdev,
"usb_ep_queue error on int endpoint %zd\n", status);
hidg->write_pending = 0;
wake_up(&hidg->write_queue);
goto release_write_pending_unlocked;
} else {
status = count;
}
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
mutex_unlock(&hidg->lock);
return status;
release_write_pending:
spin_lock_irqsave(&hidg->write_spinlock, flags);
release_write_pending_unlocked:
hidg->write_pending = 0;
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
wake_up(&hidg->write_queue);
return status;
}
@ -425,20 +464,36 @@ static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep,
static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_hidg *hidg = (struct f_hidg *) req->context;
struct usb_composite_dev *cdev = hidg->func.config->cdev;
struct f_hidg_req_list *req_list;
unsigned long flags;
req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
if (!req_list)
switch (req->status) {
case 0:
req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
if (!req_list) {
ERROR(cdev, "Unable to allocate mem for req_list\n");
goto free_req;
}
req_list->req = req;
spin_lock_irqsave(&hidg->read_spinlock, flags);
list_add_tail(&req_list->list, &hidg->completed_out_req);
spin_unlock_irqrestore(&hidg->read_spinlock, flags);
wake_up(&hidg->read_queue);
break;
default:
ERROR(cdev, "Set report failed %d\n", req->status);
/* FALLTHROUGH */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
free_req:
free_ep_req(ep, req);
return;
req_list->req = req;
spin_lock_irqsave(&hidg->spinlock, flags);
list_add_tail(&req_list->list, &hidg->completed_out_req);
spin_unlock_irqrestore(&hidg->spinlock, flags);
wake_up(&hidg->read_queue);
}
}
static int hidg_setup(struct usb_function *f,
@ -544,20 +599,35 @@ static void hidg_disable(struct usb_function *f)
{
struct f_hidg *hidg = func_to_hidg(f);
struct f_hidg_req_list *list, *next;
unsigned long flags;
usb_ep_disable(hidg->in_ep);
usb_ep_disable(hidg->out_ep);
spin_lock_irqsave(&hidg->read_spinlock, flags);
list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
free_ep_req(hidg->out_ep, list->req);
list_del(&list->list);
kfree(list);
}
spin_unlock_irqrestore(&hidg->read_spinlock, flags);
spin_lock_irqsave(&hidg->write_spinlock, flags);
if (!hidg->write_pending) {
free_ep_req(hidg->in_ep, hidg->req);
hidg->write_pending = 1;
}
hidg->req = NULL;
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
}
static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = f->config->cdev;
struct f_hidg *hidg = func_to_hidg(f);
struct usb_request *req_in = NULL;
unsigned long flags;
int i, status = 0;
VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
@ -578,6 +648,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
goto fail;
}
hidg->in_ep->driver_data = hidg;
req_in = hidg_alloc_ep_req(hidg->in_ep, hidg->report_length);
if (!req_in) {
status = -ENOMEM;
goto disable_ep_in;
}
}
@ -589,12 +665,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
hidg->out_ep);
if (status) {
ERROR(cdev, "config_ep_by_speed FAILED!\n");
goto fail;
goto free_req_in;
}
status = usb_ep_enable(hidg->out_ep);
if (status < 0) {
ERROR(cdev, "Enable OUT endpoint FAILED!\n");
goto fail;
goto free_req_in;
}
hidg->out_ep->driver_data = hidg;
@ -610,17 +686,37 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
req->context = hidg;
status = usb_ep_queue(hidg->out_ep, req,
GFP_ATOMIC);
if (status)
if (status) {
ERROR(cdev, "%s queue req --> %d\n",
hidg->out_ep->name, status);
free_ep_req(hidg->out_ep, req);
}
} else {
usb_ep_disable(hidg->out_ep);
status = -ENOMEM;
goto fail;
goto disable_out_ep;
}
}
}
if (hidg->in_ep != NULL) {
spin_lock_irqsave(&hidg->write_spinlock, flags);
hidg->req = req_in;
hidg->write_pending = 0;
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
wake_up(&hidg->write_queue);
}
return 0;
disable_out_ep:
usb_ep_disable(hidg->out_ep);
free_req_in:
if (req_in)
free_ep_req(hidg->in_ep, req_in);
disable_ep_in:
if (hidg->in_ep)
usb_ep_disable(hidg->in_ep);
fail:
return status;
}
@ -669,12 +765,6 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
hidg->out_ep = ep;
/* preallocate request and buffer */
status = -ENOMEM;
hidg->req = alloc_ep_req(hidg->in_ep, hidg->report_length);
if (!hidg->req)
goto fail;
/* set descriptor dynamic values */
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
@ -711,8 +801,10 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
if (status)
goto fail;
mutex_init(&hidg->lock);
spin_lock_init(&hidg->spinlock);
spin_lock_init(&hidg->write_spinlock);
hidg->write_pending = 1;
hidg->req = NULL;
spin_lock_init(&hidg->read_spinlock);
init_waitqueue_head(&hidg->write_queue);
init_waitqueue_head(&hidg->read_queue);
INIT_LIST_HEAD(&hidg->completed_out_req);
@ -976,10 +1068,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
device_destroy(hidg_class, MKDEV(major, hidg->minor));
cdev_del(&hidg->cdev);
/* disable/free request and end point */
usb_ep_disable(hidg->in_ep);
free_ep_req(hidg->in_ep, hidg->req);
usb_free_all_descriptors(f);
}

View file

@ -49,7 +49,6 @@
#include "u_printer.h"
#define PNP_STRING_LEN 1024
#define PRINTER_MINORS 4
#define GET_DEVICE_ID 0
#define GET_PORT_STATUS 1
@ -907,8 +906,7 @@ static bool gprinter_req_match(struct usb_function *f,
switch (ctrl->bRequest) {
case GET_DEVICE_ID:
w_index >>= 8;
if (w_length <= PNP_STRING_LEN &&
(USB_DIR_IN & ctrl->bRequestType))
if (USB_DIR_IN & ctrl->bRequestType)
break;
return false;
case GET_PORT_STATUS:
@ -937,6 +935,7 @@ static int printer_func_setup(struct usb_function *f,
struct printer_dev *dev = func_to_printer(f);
struct usb_composite_dev *cdev = f->config->cdev;
struct usb_request *req = cdev->req;
u8 *buf = req->buf;
int value = -EOPNOTSUPP;
u16 wIndex = le16_to_cpu(ctrl->wIndex);
u16 wValue = le16_to_cpu(ctrl->wValue);
@ -953,10 +952,16 @@ static int printer_func_setup(struct usb_function *f,
if ((wIndex>>8) != dev->interface)
break;
value = (dev->pnp_string[0] << 8) | dev->pnp_string[1];
memcpy(req->buf, dev->pnp_string, value);
if (!dev->pnp_string) {
value = 0;
break;
}
value = strlen(dev->pnp_string);
buf[0] = (value >> 8) & 0xFF;
buf[1] = value & 0xFF;
memcpy(buf + 2, dev->pnp_string, value);
DBG(dev, "1284 PNP String: %x %s\n", value,
&dev->pnp_string[2]);
dev->pnp_string);
break;
case GET_PORT_STATUS: /* Get Port Status */
@ -964,7 +969,7 @@ static int printer_func_setup(struct usb_function *f,
if (wIndex != dev->interface)
break;
*(u8 *)req->buf = dev->printer_status;
buf[0] = dev->printer_status;
value = min_t(u16, wLength, 1);
break;
@ -1157,10 +1162,21 @@ static ssize_t f_printer_opts_pnp_string_show(struct config_item *item,
char *page)
{
struct f_printer_opts *opts = to_f_printer_opts(item);
int result;
int result = 0;
mutex_lock(&opts->lock);
result = strlcpy(page, opts->pnp_string + 2, PNP_STRING_LEN - 2);
if (!opts->pnp_string)
goto unlock;
result = strlcpy(page, opts->pnp_string, PAGE_SIZE);
if (result >= PAGE_SIZE) {
result = PAGE_SIZE;
} else if (page[result - 1] != '\n' && result + 1 < PAGE_SIZE) {
page[result++] = '\n';
page[result] = '\0';
}
unlock:
mutex_unlock(&opts->lock);
return result;
@ -1170,13 +1186,24 @@ static ssize_t f_printer_opts_pnp_string_store(struct config_item *item,
const char *page, size_t len)
{
struct f_printer_opts *opts = to_f_printer_opts(item);
int result, l;
char *new_pnp;
int result;
mutex_lock(&opts->lock);
result = strlcpy(opts->pnp_string + 2, page, PNP_STRING_LEN - 2);
l = strlen(opts->pnp_string + 2) + 2;
opts->pnp_string[0] = (l >> 8) & 0xFF;
opts->pnp_string[1] = l & 0xFF;
new_pnp = kstrndup(page, len, GFP_KERNEL);
if (!new_pnp) {
result = -ENOMEM;
goto unlock;
}
if (opts->pnp_string_allocated)
kfree(opts->pnp_string);
opts->pnp_string_allocated = true;
opts->pnp_string = new_pnp;
result = len;
unlock:
mutex_unlock(&opts->lock);
return result;
@ -1270,6 +1297,8 @@ static void gprinter_free_inst(struct usb_function_instance *f)
mutex_unlock(&printer_ida_lock);
if (opts->pnp_string_allocated)
kfree(opts->pnp_string);
kfree(opts);
}

View file

@ -22,9 +22,6 @@
#include "u_uac2.h"
/* Keep everyone on toes */
#define USB_XFERS 2
/*
* The driver implements a simple UAC_2 topology.
* USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
@ -78,7 +75,7 @@ struct uac2_rtd_params {
size_t period_size;
unsigned max_psize;
struct uac2_req ureq[USB_XFERS];
struct uac2_req *ureq;
spinlock_t lock;
};
@ -269,6 +266,8 @@ static int
uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
struct audio_dev *agdev = uac2_to_agdev(uac2);
struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev);
struct uac2_rtd_params *prm;
unsigned long flags;
int err = 0;
@ -300,7 +299,7 @@ uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
/* Clear buffer after Play stops */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
memset(prm->rbuf, 0, prm->max_psize * USB_XFERS);
memset(prm->rbuf, 0, prm->max_psize * uac2_opts->req_number);
return err;
}
@ -943,6 +942,8 @@ static inline void
free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
{
struct snd_uac2_chip *uac2 = prm->uac2;
struct audio_dev *agdev = uac2_to_agdev(uac2);
struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev);
int i;
if (!prm->ep_enabled)
@ -950,7 +951,7 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
prm->ep_enabled = false;
for (i = 0; i < USB_XFERS; i++) {
for (i = 0; i < uac2_opts->req_number; i++) {
if (prm->ureq[i].req) {
usb_ep_dequeue(ep, prm->ureq[i].req);
usb_ep_free_request(ep, prm->ureq[i].req);
@ -1095,31 +1096,47 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm = &agdev->uac2.c_prm;
prm->max_psize = hs_epout_desc.wMaxPacketSize;
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req),
GFP_KERNEL);
if (!prm->ureq) {
ret = -ENOMEM;
goto err_free_descs;
}
prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL);
if (!prm->rbuf) {
prm->max_psize = 0;
ret = -ENOMEM;
goto err_free_descs;
}
prm = &agdev->uac2.p_prm;
prm->max_psize = hs_epin_desc.wMaxPacketSize;
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req),
GFP_KERNEL);
if (!prm->ureq) {
ret = -ENOMEM;
goto err_free_descs;
}
prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL);
if (!prm->rbuf) {
prm->max_psize = 0;
goto err;
ret = -ENOMEM;
goto err_no_memory;
}
ret = alsa_uac2_init(agdev);
if (ret)
goto err;
goto err_no_memory;
return 0;
err:
err_no_memory:
kfree(agdev->uac2.p_prm.ureq);
kfree(agdev->uac2.c_prm.ureq);
kfree(agdev->uac2.p_prm.rbuf);
kfree(agdev->uac2.c_prm.rbuf);
err_free_descs:
usb_free_all_descriptors(fn);
return -EINVAL;
return ret;
}
static int
@ -1127,6 +1144,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = fn->config->cdev;
struct audio_dev *agdev = func_to_agdev(fn);
struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev);
struct snd_uac2_chip *uac2 = &agdev->uac2;
struct usb_gadget *gadget = cdev->gadget;
struct device *dev = &uac2->pdev.dev;
@ -1157,7 +1175,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
agdev->as_out_alt = alt;
req_len = prm->max_psize;
} else if (intf == agdev->as_in_intf) {
struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev);
unsigned int factor, rate;
struct usb_endpoint_descriptor *ep_desc;
@ -1203,7 +1220,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
prm->ep_enabled = true;
usb_ep_enable(ep);
for (i = 0; i < USB_XFERS; i++) {
for (i = 0; i < opts->req_number; i++) {
if (!prm->ureq[i].req) {
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req == NULL)
@ -1487,6 +1504,7 @@ UAC2_ATTRIBUTE(p_ssize);
UAC2_ATTRIBUTE(c_chmask);
UAC2_ATTRIBUTE(c_srate);
UAC2_ATTRIBUTE(c_ssize);
UAC2_ATTRIBUTE(req_number);
static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_p_chmask,
@ -1495,6 +1513,7 @@ static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_c_chmask,
&f_uac2_opts_attr_c_srate,
&f_uac2_opts_attr_c_ssize,
&f_uac2_opts_attr_req_number,
NULL,
};
@ -1532,6 +1551,7 @@ static struct usb_function_instance *afunc_alloc_inst(void)
opts->c_chmask = UAC2_DEF_CCHMASK;
opts->c_srate = UAC2_DEF_CSRATE;
opts->c_ssize = UAC2_DEF_CSSIZE;
opts->req_number = UAC2_DEF_REQ_NUM;
return &opts->func_inst;
}
@ -1560,6 +1580,7 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
prm = &agdev->uac2.c_prm;
kfree(prm->rbuf);
kfree(prm->ureq);
usb_free_all_descriptors(f);
}

View file

@ -913,9 +913,16 @@ EXPORT_SYMBOL_GPL(gether_set_dev_addr);
int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len)
{
struct eth_dev *dev;
int ret;
dev = netdev_priv(net);
return get_ether_addr_str(dev->dev_mac, dev_addr, len);
ret = get_ether_addr_str(dev->dev_mac, dev_addr, len);
if (ret + 1 < len) {
dev_addr[ret++] = '\n';
dev_addr[ret] = '\0';
}
return ret;
}
EXPORT_SYMBOL_GPL(gether_get_dev_addr);
@ -935,9 +942,16 @@ EXPORT_SYMBOL_GPL(gether_set_host_addr);
int gether_get_host_addr(struct net_device *net, char *host_addr, int len)
{
struct eth_dev *dev;
int ret;
dev = netdev_priv(net);
return get_ether_addr_str(dev->host_mac, host_addr, len);
ret = get_ether_addr_str(dev->host_mac, host_addr, len);
if (ret + 1 < len) {
host_addr[ret++] = '\n';
host_addr[ret] = '\0';
}
return ret;
}
EXPORT_SYMBOL_GPL(gether_get_host_addr);
@ -984,10 +998,12 @@ EXPORT_SYMBOL_GPL(gether_get_qmult);
int gether_get_ifname(struct net_device *net, char *name, int len)
{
int ret;
rtnl_lock();
strlcpy(name, netdev_name(net), len);
ret = snprintf(name, len, "%s\n", netdev_name(net));
rtnl_unlock();
return strlen(name);
return ret < len ? ret : len;
}
EXPORT_SYMBOL_GPL(gether_get_ifname);

View file

@ -108,7 +108,7 @@
mutex_lock(&opts->lock); \
qmult = gether_get_qmult(opts->net); \
mutex_unlock(&opts->lock); \
return sprintf(page, "%d", qmult); \
return sprintf(page, "%d\n", qmult); \
} \
\
static ssize_t _f_##_opts_qmult_store(struct config_item *item, \

View file

@ -247,7 +247,8 @@ struct ffs_data {
unsigned user_flags;
u8 eps_addrmap[15];
#define FFS_MAX_EPS_COUNT 31
u8 eps_addrmap[FFS_MAX_EPS_COUNT];
unsigned short strings_count;
unsigned short interfaces_count;

View file

@ -18,12 +18,11 @@
#include <linux/usb/composite.h>
#define PNP_STRING_LEN 1024
struct f_printer_opts {
struct usb_function_instance func_inst;
int minor;
char pnp_string[PNP_STRING_LEN];
char *pnp_string;
bool pnp_string_allocated;
unsigned q_len;
/*

View file

@ -24,6 +24,7 @@
#define UAC2_DEF_CCHMASK 0x3
#define UAC2_DEF_CSRATE 64000
#define UAC2_DEF_CSSIZE 2
#define UAC2_DEF_REQ_NUM 2
struct f_uac2_opts {
struct usb_function_instance func_inst;
@ -33,6 +34,7 @@ struct f_uac2_opts {
int c_chmask;
int c_srate;
int c_ssize;
int req_number;
bool bound;
struct mutex lock;

View file

@ -229,6 +229,7 @@ static int audio_bind(struct usb_composite_dev *cdev)
uac2_opts->c_chmask = c_chmask;
uac2_opts->c_srate = c_srate;
uac2_opts->c_ssize = c_ssize;
uac2_opts->req_number = UAC2_DEF_REQ_NUM;
#else
uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst);
uac1_opts->fn_play = fn_play;

View file

@ -88,8 +88,8 @@ static const struct usb_descriptor_header *otg_desc[2];
static char product_desc [40] = DRIVER_DESC;
static char serial_num [40] = "1";
static char pnp_string[PNP_STRING_LEN] =
"XXMFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;";
static char *pnp_string =
"MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;";
/* static strings, in UTF-8 */
static struct usb_string strings [] = {
@ -143,23 +143,29 @@ static int printer_do_config(struct usb_configuration *c)
static int printer_bind(struct usb_composite_dev *cdev)
{
struct f_printer_opts *opts;
int ret, len;
int ret;
fi_printer = usb_get_function_instance("printer");
if (IS_ERR(fi_printer))
return PTR_ERR(fi_printer);
if (iPNPstring)
strlcpy(&pnp_string[2], iPNPstring, PNP_STRING_LEN - 2);
len = strlen(pnp_string);
pnp_string[0] = (len >> 8) & 0xFF;
pnp_string[1] = len & 0xFF;
opts = container_of(fi_printer, struct f_printer_opts, func_inst);
opts->minor = 0;
memcpy(opts->pnp_string, pnp_string, PNP_STRING_LEN);
opts->q_len = QLEN;
if (iPNPstring) {
opts->pnp_string = kstrdup(iPNPstring, GFP_KERNEL);
if (!opts->pnp_string) {
ret = -ENOMEM;
goto fail_put_func_inst;
}
opts->pnp_string_allocated = true;
/*
* we don't free this memory in case of error
* as printer cleanup func will do this for us
*/
} else {
opts->pnp_string = pnp_string;
}
ret = usb_string_ids_tab(cdev, strings);
if (ret < 0)

View file

@ -60,6 +60,20 @@ config USB_ATMEL_USBA
USBA is the integrated high-speed USB Device controller on
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
The fifo_mode parameter is used to select endpoint allocation mode.
fifo_mode = 0 is used to let the driver autoconfigure the endpoints.
In this case 2 banks are allocated for isochronous endpoints and
only one bank is allocated for the rest of the endpoints.
fifo_mode = 1 is a generic maximum fifo size (1024 bytes) configuration
allowing the usage of ep1 - ep6
fifo_mode = 2 is a generic performance maximum fifo size (1024 bytes)
configuration allowing the usage of ep1 - ep3
fifo_mode = 3 is a balanced performance configuration allowing the
the usage of ep1 - ep8
config USB_BCM63XX_UDC
tristate "Broadcom BCM63xx Peripheral Controller"
depends on BCM63XX

View file

@ -20,6 +20,7 @@
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/ctype.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/atmel_usba_udc.h>
@ -318,6 +319,91 @@ static inline void usba_cleanup_debugfs(struct usba_udc *udc)
}
#endif
static ushort fifo_mode;
/* "modprobe ... fifo_mode=1" etc */
module_param(fifo_mode, ushort, 0x0);
MODULE_PARM_DESC(fifo_mode, "Endpoint configuration mode");
/* mode 0 - uses autoconfig */
/* mode 1 - fits in 8KB, generic max fifo configuration */
static struct usba_fifo_cfg mode_1_cfg[] = {
{ .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, },
{ .hw_ep_num = 1, .fifo_size = 1024, .nr_banks = 2, },
{ .hw_ep_num = 2, .fifo_size = 1024, .nr_banks = 1, },
{ .hw_ep_num = 3, .fifo_size = 1024, .nr_banks = 1, },
{ .hw_ep_num = 4, .fifo_size = 1024, .nr_banks = 1, },
{ .hw_ep_num = 5, .fifo_size = 1024, .nr_banks = 1, },
{ .hw_ep_num = 6, .fifo_size = 1024, .nr_banks = 1, },
};
/* mode 2 - fits in 8KB, performance max fifo configuration */
static struct usba_fifo_cfg mode_2_cfg[] = {
{ .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, },
{ .hw_ep_num = 1, .fifo_size = 1024, .nr_banks = 3, },
{ .hw_ep_num = 2, .fifo_size = 1024, .nr_banks = 2, },
{ .hw_ep_num = 3, .fifo_size = 1024, .nr_banks = 2, },
};
/* mode 3 - fits in 8KB, mixed fifo configuration */
static struct usba_fifo_cfg mode_3_cfg[] = {
{ .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, },
{ .hw_ep_num = 1, .fifo_size = 1024, .nr_banks = 2, },
{ .hw_ep_num = 2, .fifo_size = 512, .nr_banks = 2, },
{ .hw_ep_num = 3, .fifo_size = 512, .nr_banks = 2, },
{ .hw_ep_num = 4, .fifo_size = 512, .nr_banks = 2, },
{ .hw_ep_num = 5, .fifo_size = 512, .nr_banks = 2, },
{ .hw_ep_num = 6, .fifo_size = 512, .nr_banks = 2, },
};
/* mode 4 - fits in 8KB, custom fifo configuration */
static struct usba_fifo_cfg mode_4_cfg[] = {
{ .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, },
{ .hw_ep_num = 1, .fifo_size = 512, .nr_banks = 2, },
{ .hw_ep_num = 2, .fifo_size = 512, .nr_banks = 2, },
{ .hw_ep_num = 3, .fifo_size = 8, .nr_banks = 2, },
{ .hw_ep_num = 4, .fifo_size = 512, .nr_banks = 2, },
{ .hw_ep_num = 5, .fifo_size = 512, .nr_banks = 2, },
{ .hw_ep_num = 6, .fifo_size = 16, .nr_banks = 2, },
{ .hw_ep_num = 7, .fifo_size = 8, .nr_banks = 2, },
{ .hw_ep_num = 8, .fifo_size = 8, .nr_banks = 2, },
};
/* Add additional configurations here */
int usba_config_fifo_table(struct usba_udc *udc)
{
int n;
switch (fifo_mode) {
default:
fifo_mode = 0;
case 0:
udc->fifo_cfg = NULL;
n = 0;
break;
case 1:
udc->fifo_cfg = mode_1_cfg;
n = ARRAY_SIZE(mode_1_cfg);
break;
case 2:
udc->fifo_cfg = mode_2_cfg;
n = ARRAY_SIZE(mode_2_cfg);
break;
case 3:
udc->fifo_cfg = mode_3_cfg;
n = ARRAY_SIZE(mode_3_cfg);
break;
case 4:
udc->fifo_cfg = mode_4_cfg;
n = ARRAY_SIZE(mode_4_cfg);
break;
}
DBG(DBG_HW, "Setup fifo_mode %d\n", fifo_mode);
return n;
}
static inline u32 usba_int_enb_get(struct usba_udc *udc)
{
return udc->int_enb_cache;
@ -543,24 +629,17 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
ep->is_isoc = 0;
ep->is_in = 0;
if (maxpacket <= 8)
ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
else
/* LSB is bit 1, not 0 */
ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3);
DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n",
DBG(DBG_ERR, "%s: EPT_CFG = 0x%lx (maxpacket = %lu)\n",
ep->ep.name, ept_cfg, maxpacket);
if (usb_endpoint_dir_in(desc)) {
ep->is_in = 1;
ept_cfg |= USBA_EPT_DIR_IN;
ep->ept_cfg |= USBA_EPT_DIR_IN;
}
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL);
ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
ep->ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL);
break;
case USB_ENDPOINT_XFER_ISOC:
if (!ep->can_isoc) {
@ -578,24 +657,15 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
return -EINVAL;
ep->is_isoc = 1;
ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO);
ep->ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO);
ep->ept_cfg |= USBA_BF(NB_TRANS, nr_trans);
/*
* Do triple-buffering on high-bandwidth iso endpoints.
*/
if (nr_trans > 1 && ep->nr_banks == 3)
ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE);
else
ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
ept_cfg |= USBA_BF(NB_TRANS, nr_trans);
break;
case USB_ENDPOINT_XFER_BULK:
ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK);
ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
ep->ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK);
break;
case USB_ENDPOINT_XFER_INT:
ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT);
ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
ep->ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT);
break;
}
@ -604,7 +674,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
ep->ep.desc = desc;
ep->ep.maxpacket = maxpacket;
usba_ep_writel(ep, CFG, ept_cfg);
usba_ep_writel(ep, CFG, ep->ept_cfg);
usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
if (ep->can_dma) {
@ -1006,12 +1076,81 @@ static int atmel_usba_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver);
static int atmel_usba_stop(struct usb_gadget *gadget);
static struct usb_ep *atmel_usba_match_ep(
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp
)
{
struct usb_ep *_ep;
struct usba_ep *ep;
/* Look at endpoints until an unclaimed one looks usable */
list_for_each_entry(_ep, &gadget->ep_list, ep_list) {
if (usb_gadget_ep_match_desc(gadget, _ep, desc, ep_comp))
goto found_ep;
}
/* Fail */
return NULL;
found_ep:
if (fifo_mode == 0) {
/* Optimize hw fifo size based on ep type and other info */
ep = to_usba_ep(_ep);
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
break;
case USB_ENDPOINT_XFER_ISOC:
ep->fifo_size = 1024;
ep->nr_banks = 2;
break;
case USB_ENDPOINT_XFER_BULK:
ep->fifo_size = 512;
ep->nr_banks = 1;
break;
case USB_ENDPOINT_XFER_INT:
if (desc->wMaxPacketSize == 0)
ep->fifo_size =
roundup_pow_of_two(_ep->maxpacket_limit);
else
ep->fifo_size =
roundup_pow_of_two(le16_to_cpu(desc->wMaxPacketSize));
ep->nr_banks = 1;
break;
}
/* It might be a little bit late to set this */
usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
/* Generate ept_cfg basd on FIFO size and number of banks */
if (ep->fifo_size <= 8)
ep->ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
else
/* LSB is bit 1, not 0 */
ep->ept_cfg =
USBA_BF(EPT_SIZE, fls(ep->fifo_size - 1) - 3);
ep->ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks);
ep->udc->configured_ep++;
}
return _ep;
}
static const struct usb_gadget_ops usba_udc_ops = {
.get_frame = usba_udc_get_frame,
.wakeup = usba_udc_wakeup,
.set_selfpowered = usba_udc_set_selfpowered,
.udc_start = atmel_usba_start,
.udc_stop = atmel_usba_stop,
.match_ep = atmel_usba_match_ep,
};
static struct usb_endpoint_descriptor usba_ep0_desc = {
@ -1678,7 +1817,8 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
}
if (status & USBA_END_OF_RESET) {
struct usba_ep *ep0;
struct usba_ep *ep0, *ep;
int i, n;
usba_writel(udc, INT_CLR, USBA_END_OF_RESET);
generate_bias_pulse(udc);
@ -1717,6 +1857,16 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED))
dev_dbg(&udc->pdev->dev,
"ODD: EP0 configuration is invalid!\n");
/* Preallocate other endpoints */
n = fifo_mode ? udc->num_ep : udc->configured_ep;
for (i = 1; i < n; i++) {
ep = &udc->usba_ep[i];
usba_ep_writel(ep, CFG, ep->ept_cfg);
if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED))
dev_dbg(&udc->pdev->dev,
"ODD: EP%d configuration is invalid!\n", i);
}
}
spin_unlock(&udc->lock);
@ -1864,6 +2014,9 @@ static int atmel_usba_stop(struct usb_gadget *gadget)
if (gpio_is_valid(udc->vbus_pin))
disable_irq(gpio_to_irq(udc->vbus_pin));
if (fifo_mode == 0)
udc->configured_ep = 1;
usba_stop(udc);
udc->driver = NULL;
@ -1931,9 +2084,13 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
&flags);
udc->vbus_pin_inverted = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
pp = NULL;
while ((pp = of_get_next_child(np, pp)))
udc->num_ep++;
if (fifo_mode == 0) {
pp = NULL;
while ((pp = of_get_next_child(np, pp)))
udc->num_ep++;
udc->configured_ep = 1;
} else
udc->num_ep = usba_config_fifo_table(udc);
eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep,
GFP_KERNEL);
@ -1946,7 +2103,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
pp = NULL;
i = 0;
while ((pp = of_get_next_child(np, pp))) {
while ((pp = of_get_next_child(np, pp)) && i < udc->num_ep) {
ep = &eps[i];
ret = of_property_read_u32(pp, "reg", &val);
@ -1954,21 +2111,21 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
dev_err(&pdev->dev, "of_probe: reg error(%d)\n", ret);
goto err;
}
ep->index = val;
ep->index = fifo_mode ? udc->fifo_cfg[i].hw_ep_num : val;
ret = of_property_read_u32(pp, "atmel,fifo-size", &val);
if (ret) {
dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret);
goto err;
}
ep->fifo_size = val;
ep->fifo_size = fifo_mode ? udc->fifo_cfg[i].fifo_size : val;
ret = of_property_read_u32(pp, "atmel,nb-banks", &val);
if (ret) {
dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret);
goto err;
}
ep->nr_banks = val;
ep->nr_banks = fifo_mode ? udc->fifo_cfg[i].nr_banks : val;
ep->can_dma = of_property_read_bool(pp, "atmel,can-dma");
ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
@ -2000,6 +2157,21 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
if (fifo_mode != 0) {
/*
* Generate ept_cfg based on FIFO size and
* banks number
*/
if (ep->fifo_size <= 8)
ep->ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
else
/* LSB is bit 1, not 0 */
ep->ept_cfg =
USBA_BF(EPT_SIZE, fls(ep->fifo_size - 1) - 3);
ep->ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks);
}
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);

View file

@ -275,6 +275,12 @@ struct usba_dma_desc {
u32 ctrl;
};
struct usba_fifo_cfg {
u8 hw_ep_num;
u16 fifo_size;
u8 nr_banks;
};
struct usba_ep {
int state;
void __iomem *ep_regs;
@ -293,7 +299,7 @@ struct usba_ep {
unsigned int can_isoc:1;
unsigned int is_isoc:1;
unsigned int is_in:1;
unsigned long ept_cfg;
#ifdef CONFIG_USB_GADGET_DEBUG_FS
u32 last_dma_status;
struct dentry *debugfs_dir;
@ -338,6 +344,8 @@ struct usba_udc {
int vbus_pin;
int vbus_pin_inverted;
int num_ep;
int configured_ep;
struct usba_fifo_cfg *fifo_cfg;
struct clk *pclk;
struct clk *hclk;
struct usba_ep *usba_ep;

View file

@ -1080,6 +1080,24 @@ static void usb_udc_nop_release(struct device *dev)
dev_vdbg(dev, "%s\n", __func__);
}
/* should be called with udc_lock held */
static int check_pending_gadget_drivers(struct usb_udc *udc)
{
struct usb_gadget_driver *driver;
int ret = 0;
list_for_each_entry(driver, &gadget_driver_pending_list, pending)
if (!driver->udc_name || strcmp(driver->udc_name,
dev_name(&udc->dev)) == 0) {
ret = udc_bind_to_driver(udc, driver);
if (ret != -EPROBE_DEFER)
list_del(&driver->pending);
break;
}
return ret;
}
/**
* usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
* @parent: the parent device to this udc. Usually the controller driver's
@ -1093,7 +1111,6 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
void (*release)(struct device *dev))
{
struct usb_udc *udc;
struct usb_gadget_driver *driver;
int ret = -ENOMEM;
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
@ -1136,17 +1153,9 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
udc->vbus = true;
/* pick up one of pending gadget drivers */
list_for_each_entry(driver, &gadget_driver_pending_list, pending) {
if (!driver->udc_name || strcmp(driver->udc_name,
dev_name(&udc->dev)) == 0) {
ret = udc_bind_to_driver(udc, driver);
if (ret != -EPROBE_DEFER)
list_del(&driver->pending);
if (ret)
goto err5;
break;
}
}
ret = check_pending_gadget_drivers(udc);
if (ret)
goto err5;
mutex_unlock(&udc_lock);
@ -1356,14 +1365,22 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return -EINVAL;
mutex_lock(&udc_lock);
list_for_each_entry(udc, &udc_list, list)
list_for_each_entry(udc, &udc_list, list) {
if (udc->driver == driver) {
usb_gadget_remove_driver(udc);
usb_gadget_set_state(udc->gadget,
USB_STATE_NOTATTACHED);
USB_STATE_NOTATTACHED);
/* Maybe there is someone waiting for this UDC? */
check_pending_gadget_drivers(udc);
/*
* For now we ignore bind errors as probably it's
* not a valid reason to fail other's gadget unbind
*/
ret = 0;
break;
}
}
if (ret) {
list_del(&driver->pending);

View file

@ -527,7 +527,7 @@ static void fotg210_ep_fifo_flush(struct usb_ep *_ep)
{
}
static struct usb_ep_ops fotg210_ep_ops = {
static const struct usb_ep_ops fotg210_ep_ops = {
.enable = fotg210_ep_enable,
.disable = fotg210_ep_disable,
@ -1058,7 +1058,7 @@ static int fotg210_udc_stop(struct usb_gadget *g)
return 0;
}
static struct usb_gadget_ops fotg210_gadget_ops = {
static const struct usb_gadget_ops fotg210_gadget_ops = {
.udc_start = fotg210_udc_start,
.udc_stop = fotg210_udc_stop,
};

View file

@ -1847,7 +1847,7 @@ out:
return status;
}
static struct usb_ep_ops qe_ep_ops = {
static const struct usb_ep_ops qe_ep_ops = {
.enable = qe_ep_enable,
.disable = qe_ep_disable,

View file

@ -1118,7 +1118,7 @@ static void fsl_ep_fifo_flush(struct usb_ep *_ep)
} while (fsl_readl(&dr_regs->endptstatus) & bits);
}
static struct usb_ep_ops fsl_ep_ops = {
static const struct usb_ep_ops fsl_ep_ops = {
.enable = fsl_ep_enable,
.disable = fsl_ep_disable,
@ -1248,6 +1248,12 @@ static const struct usb_gadget_ops fsl_gadget_ops = {
.udc_stop = fsl_udc_stop,
};
/*
* Empty complete function used by this driver to fill in the req->complete
* field when creating a request since the complete field is mandatory.
*/
static void fsl_noop_complete(struct usb_ep *ep, struct usb_request *req) { }
/* Set protocol stall on ep0, protocol stall will automatically be cleared
on new transaction */
static void ep0stall(struct fsl_udc *udc)
@ -1282,7 +1288,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
req->req.length = 0;
req->req.status = -EINPROGRESS;
req->req.actual = 0;
req->req.complete = NULL;
req->req.complete = fsl_noop_complete;
req->dtd_count = 0;
ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
@ -1365,7 +1371,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
req->req.length = 2;
req->req.status = -EINPROGRESS;
req->req.actual = 0;
req->req.complete = NULL;
req->req.complete = fsl_noop_complete;
req->dtd_count = 0;
ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));

View file

@ -518,7 +518,7 @@ static void fusb300_fifo_flush(struct usb_ep *_ep)
{
}
static struct usb_ep_ops fusb300_ep_ops = {
static const struct usb_ep_ops fusb300_ep_ops = {
.enable = fusb300_enable,
.disable = fusb300_disable,

View file

@ -968,7 +968,7 @@ static void goku_fifo_flush(struct usb_ep *_ep)
command(regs, COMMAND_FIFO_CLEAR, ep->num);
}
static struct usb_ep_ops goku_ep_ops = {
static const struct usb_ep_ops goku_ep_ops = {
.enable = goku_ep_enable,
.disable = goku_ep_disable,

View file

@ -1841,7 +1841,7 @@ static void gr_fifo_flush(struct usb_ep *_ep)
spin_unlock(&ep->dev->lock);
}
static struct usb_ep_ops gr_ep_ops = {
static const struct usb_ep_ops gr_ep_ops = {
.enable = gr_ep_enable,
.disable = gr_ep_disable,

View file

@ -1436,7 +1436,7 @@ static void m66592_fifo_flush(struct usb_ep *_ep)
spin_unlock_irqrestore(&ep->m66592->lock, flags);
}
static struct usb_ep_ops m66592_ep_ops = {
static const struct usb_ep_ops m66592_ep_ops = {
.enable = m66592_enable,
.disable = m66592_disable,

View file

@ -995,7 +995,7 @@ static int mv_u3d_ep_set_wedge(struct usb_ep *_ep)
return mv_u3d_ep_set_halt_wedge(_ep, 1, 1);
}
static struct usb_ep_ops mv_u3d_ep_ops = {
static const struct usb_ep_ops mv_u3d_ep_ops = {
.enable = mv_u3d_ep_enable,
.disable = mv_u3d_ep_disable,

View file

@ -946,7 +946,7 @@ static int mv_ep_set_wedge(struct usb_ep *_ep)
return mv_ep_set_halt_wedge(_ep, 1, 1);
}
static struct usb_ep_ops mv_ep_ops = {
static const struct usb_ep_ops mv_ep_ops = {
.enable = mv_ep_enable,
.disable = mv_ep_disable,

View file

@ -181,7 +181,7 @@ static void net2272_dequeue_all(struct net2272_ep *);
static int net2272_kick_dma(struct net2272_ep *, struct net2272_request *);
static int net2272_fifo_status(struct usb_ep *);
static struct usb_ep_ops net2272_ep_ops;
static const struct usb_ep_ops net2272_ep_ops;
/*---------------------------------------------------------------------------*/
@ -1067,7 +1067,7 @@ net2272_fifo_flush(struct usb_ep *_ep)
net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
}
static struct usb_ep_ops net2272_ep_ops = {
static const struct usb_ep_ops net2272_ep_ops = {
.enable = net2272_enable,
.disable = net2272_disable,

View file

@ -1112,7 +1112,7 @@ done:
return status;
}
static struct usb_ep_ops omap_ep_ops = {
static const struct usb_ep_ops omap_ep_ops = {
.enable = omap_ep_enable,
.disable = omap_ep_disable,

View file

@ -1473,7 +1473,7 @@ static int pxa_ep_disable(struct usb_ep *_ep)
return 0;
}
static struct usb_ep_ops pxa_ep_ops = {
static const struct usb_ep_ops pxa_ep_ops = {
.enable = pxa_ep_enable,
.disable = pxa_ep_disable,

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