Commit 213db493 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-for-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

usb: changes for v3.18 merge window

Quite big pull request this time. Audio and UVC gadgets
can now be used with our configfs-based binding. We have
three PHY drivers being removed because a new one has been
added using new PHY framework.

Gadget framework got a new ->reset callback preparing for
some other changes to come on next merge window.

A few new drivers came in as well; among those we have a
new UDC driver from Xilinx and two new glue layers for
DWC3 (ST and Qualcomm).

DWC3 also learned about tracepoints which will help debugging
quite a bit.

Other than that, a big series of non-critical fixes and
cleanups.

All patches have been on linux-next for quite a bit of time
and I boot tested these changes on platforms I have access
to and work with mainline.
Signed-of-by: default avatarFelipe Balbi <balbi@ti.com>
parents ce4df0b0 72a65a0d
What: /config/usb-gadget/gadget/functions/uac1.name
Date: Sep 2014
KernelVersion: 3.18
Description:
The attributes:
audio_buf_size - audio buffer size
fn_cap - capture pcm device file name
fn_cntl - control device file name
fn_play - playback pcm device file name
req_buf_size - ISO OUT endpoint request buffer size
req_count - ISO OUT endpoint request count
What: /config/usb-gadget/gadget/functions/uac2.name
Date: Sep 2014
KernelVersion: 3.18
Description:
The attributes:
c_chmask - capture channel mask
c_srate - capture sampling rate
c_ssize - capture sample size (bytes)
p_chmask - playback channel mask
p_srate - playback sampling rate
p_ssize - playback sample size (bytes)
Qualcomm DWC3 HS AND SS PHY CONTROLLER
--------------------------------------
DWC3 PHY nodes are defined to describe on-chip Synopsis Physical layer
controllers. Each DWC3 PHY controller should have its own node.
Required properties:
- compatible: should contain one of the following:
- "qcom,dwc3-hs-usb-phy" for High Speed Synopsis PHY controller
- "qcom,dwc3-ss-usb-phy" for Super Speed Synopsis PHY controller
- reg: offset and length of the DWC3 PHY controller register set
- #phy-cells: must be zero
- clocks: a list of phandles and clock-specifier pairs, one for each entry in
clock-names.
- clock-names: Should contain "ref" for the PHY reference clock
Optional clocks:
"xo" External reference clock
Example:
phy@100f8800 {
compatible = "qcom,dwc3-hs-usb-phy";
reg = <0x100f8800 0x30>;
clocks = <&gcc USB30_0_UTMI_CLK>;
clock-names = "ref";
#phy-cells = <0>;
status = "ok";
};
phy@100f8830 {
compatible = "qcom,dwc3-ss-usb-phy";
reg = <0x100f8830 0x30>;
clocks = <&gcc USB30_0_MASTER_CLK>;
clock-names = "ref";
#phy-cells = <0>;
status = "ok";
};
ST DWC3 glue logic
This file documents the parameters for the dwc3-st driver.
This driver controls the glue logic used to configure the dwc3 core on
STiH407 based platforms.
Required properties:
- compatible : must be "st,stih407-dwc3"
- reg : glue logic base address and USB syscfg ctrl register offset
- reg-names : should be "reg-glue" and "syscfg-reg"
- st,syscon : should be phandle to system configuration node which
encompasses the glue registers
- resets : list of phandle and reset specifier pairs. There should be two entries, one
for the powerdown and softreset lines of the usb3 IP
- reset-names : list of reset signal names. Names should be "powerdown" and "softreset"
See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
See: Documentation/devicetree/bindings/reset/reset.txt
- #address-cells, #size-cells : should be '1' if the device has sub-nodes
with 'reg' property
- pinctl-names : A pinctrl state named "default" must be defined
See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
- pinctrl-0 : Pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
- ranges : allows valid 1:1 translation between child's address space and
parent's address space
Sub-nodes:
The dwc3 core should be added as subnode to ST DWC3 glue as shown in the
example below. The DT binding details of dwc3 can be found in:
Documentation/devicetree/bindings/usb/dwc3.txt
NB: The dr_mode property described in [1] is NOT optional for this driver, as the default value
is "otg", which isn't supported by this SoC. Valid dr_mode values for dwc3-st are either "host"
or "device".
[1] Documentation/devicetree/bindings/usb/generic.txt
Example:
st_dwc3: dwc3@8f94000 {
status = "disabled";
compatible = "st,stih407-dwc3";
reg = <0x08f94000 0x1000>, <0x110 0x4>;
reg-names = "reg-glue", "syscfg-reg";
st,syscfg = <&syscfg_core>;
resets = <&powerdown STIH407_USB3_POWERDOWN>,
<&softreset STIH407_MIPHY2_SOFTRESET>;
reset-names = "powerdown",
"softreset";
#address-cells = <1>;
#size-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb3>;
ranges;
dwc3: dwc3@9900000 {
compatible = "snps,dwc3";
reg = <0x09900000 0x100000>;
interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>;
dr_mode = "host";
phys-names = "usb2-phy", "usb3-phy";
phys = <&usb2_picophy2>, <&phy_port2 MIPHY_TYPE_USB>;
};
};
......@@ -5,6 +5,7 @@ Required properties:
* "fsl,imx23-usbphy" for imx23 and imx28
* "fsl,imx6q-usbphy" for imx6dq and imx6dl
* "fsl,imx6sl-usbphy" for imx6sl
* "fsl,vf610-usbphy" for Vybrid vf610
* "fsl,imx6sx-usbphy" for imx6sx
"fsl,imx23-usbphy" is still a fallback for other strings
- reg: Should contain registers location and length
......
Qualcomm SuperSpeed DWC3 USB SoC controller
Required properties:
- compatible: should contain "qcom,dwc3"
- clocks: A list of phandle + clock-specifier pairs for the
clocks listed in clock-names
- clock-names: Should contain the following:
"core" Master/Core clock, have to be >= 125 MHz for SS
operation and >= 60MHz for HS operation
Optional clocks:
"iface" System bus AXI clock. Not present on all platforms
"sleep" Sleep clock, used when USB3 core goes into low
power mode (U3).
Required child node:
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
Example device nodes:
hs_phy: phy@100f8800 {
compatible = "qcom,dwc3-hs-usb-phy";
reg = <0x100f8800 0x30>;
clocks = <&gcc USB30_0_UTMI_CLK>;
clock-names = "ref";
#phy-cells = <0>;
status = "ok";
};
ss_phy: phy@100f8830 {
compatible = "qcom,dwc3-ss-usb-phy";
reg = <0x100f8830 0x30>;
clocks = <&gcc USB30_0_MASTER_CLK>;
clock-names = "ref";
#phy-cells = <0>;
status = "ok";
};
usb3_0: usb30@0 {
compatible = "qcom,dwc3";
#address-cells = <1>;
#size-cells = <1>;
clocks = <&gcc USB30_0_MASTER_CLK>;
clock-names = "core";
ranges;
status = "ok";
dwc3@10000000 {
compatible = "snps,dwc3";
reg = <0x10000000 0xcd00>;
interrupts = <0 205 0x4>;
phys = <&hs_phy>, <&ss_phy>;
phy-names = "usb2-phy", "usb3-phy";
tx-fifo-resize;
dr_mode = "host";
};
};
Renesas Electronics USBHS driver
Required properties:
- compatible: Must contain one of the following:
- "renesas,usbhs-r8a7790"
- "renesas,usbhs-r8a7791"
- reg: Base address and length of the register for the USBHS
- interrupts: Interrupt specifier for the USBHS
- clocks: A list of phandle + clock specifier pairs
Optional properties:
- renesas,buswait: Integer to use BUSWAIT register
- renesas,enable-gpio: A gpio specifier to check GPIO determining if USB
function should be enabled
- phys: phandle + phy specifier pair
- phy-names: must be "usb"
Example:
usbhs: usb@e6590000 {
compatible = "renesas,usbhs-r8a7790";
reg = <0 0xe6590000 0 0x100>;
interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp7_clks R8A7790_CLK_HSUSB>;
};
Xilinx USB2 device controller
Required properties:
- compatible : Should be "xlnx,usb2-device-4.00.a"
- reg : Physical base address and size of the USB2
device registers map.
- interrupts : Should contain single irq line of USB2 device
controller
- xlnx,has-builtin-dma : if DMA is included
Example:
axi-usb2-device@42e00000 {
compatible = "xlnx,usb2-device-4.00.a";
interrupts = <0x0 0x39 0x1>;
reg = <0x42e00000 0x10000>;
xlnx,has-builtin-dma;
};
......@@ -1398,6 +1398,7 @@ F: drivers/media/rc/st_rc.c
F: drivers/i2c/busses/i2c-st.c
F: drivers/tty/serial/st-asc.c
F: drivers/mmc/host/sdhci-st.c
F: drivers/usb/dwc3/dwc3-st.c
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
......@@ -9683,7 +9684,7 @@ USB WEBCAM GADGET
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-usb@vger.kernel.org
S: Maintained
F: drivers/usb/gadget/function/*uvc*.c
F: drivers/usb/gadget/function/*uvc*
F: drivers/usb/gadget/legacy/webcam.c
USB WIRELESS RNDIS DRIVER (rndis_wlan)
......
......@@ -80,6 +80,23 @@ config USB_DWC3_KEYSTONE
Support of USB2/3 functionality in TI Keystone2 platforms.
Say 'Y' or 'M' here if you have one such device
config USB_DWC3_ST
tristate "STMicroelectronics Platforms"
depends on ARCH_STI && OF
default USB_DWC3
help
STMicroelectronics SoCs with one DesignWare Core USB3 IP
inside (i.e. STiH407).
Say 'Y' or 'M' if you have one such device.
config USB_DWC3_QCOM
tristate "Qualcomm Platforms"
depends on ARCH_QCOM || COMPILE_TEST
default USB_DWC3
help
Recent Qualcomm SoCs ship with one DesignWare Core USB3 IP inside,
say 'Y' or 'M' if you have one such device.
comment "Debugging features"
config USB_DWC3_DEBUG
......
# define_trace.h needs to know how to find our header
CFLAGS_trace.o := -I$(src)
ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG
ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG
obj-$(CONFIG_USB_DWC3) += dwc3.o
dwc3-y := core.o
dwc3-y := core.o debug.o trace.o
ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
dwc3-y += host.o
......@@ -33,3 +36,5 @@ obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o
obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o
obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o
obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o
obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o
......@@ -186,10 +186,8 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
GFP_KERNEL);
if (!dwc->ev_buffs) {
dev_err(dwc->dev, "can't allocate event buffers array\n");
if (!dwc->ev_buffs)
return -ENOMEM;
}
for (i = 0; i < num; i++) {
struct dwc3_event_buffer *evt;
......@@ -639,10 +637,9 @@ static int dwc3_probe(struct platform_device *pdev)
void *mem;
mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
if (!mem) {
dev_err(dev, "not enough memory\n");
if (!mem)
return -ENOMEM;
}
dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
dwc->mem = mem;
dwc->dev = dev;
......
......@@ -33,6 +33,8 @@
#include <linux/phy/phy.h>
#define DWC3_MSG_MAX 500
/* Global constants */
#define DWC3_EP0_BOUNCE_SIZE 512
#define DWC3_ENDPOINTS_NUM 32
......@@ -938,7 +940,7 @@ int dwc3_gadget_get_link_state(struct dwc3 *dwc);
int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state);
int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
unsigned cmd, struct dwc3_gadget_ep_cmd_params *params);
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param);
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param);
#else
static inline int dwc3_gadget_init(struct dwc3 *dwc)
{ return 0; }
......
/**
* debug.c - DesignWare USB3 DRD Controller Debug/Trace Support
*
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Felipe Balbi <balbi@ti.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "debug.h"
void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...)
{
struct va_format vaf;
va_list args;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
trace(&vaf);
va_end(args);
}
......@@ -16,8 +16,206 @@
* GNU General Public License for more details.
*/
#ifndef __DWC3_DEBUG_H
#define __DWC3_DEBUG_H
#include "core.h"
/**
* dwc3_gadget_ep_cmd_string - returns endpoint command string
* @cmd: command code
*/
static inline const char *
dwc3_gadget_ep_cmd_string(u8 cmd)
{
switch (cmd) {
case DWC3_DEPCMD_DEPSTARTCFG:
return "Start New Configuration";
case DWC3_DEPCMD_ENDTRANSFER:
return "End Transfer";
case DWC3_DEPCMD_UPDATETRANSFER:
return "Update Transfer";
case DWC3_DEPCMD_STARTTRANSFER:
return "Start Transfer";
case DWC3_DEPCMD_CLEARSTALL:
return "Clear Stall";
case DWC3_DEPCMD_SETSTALL:
return "Set Stall";
case DWC3_DEPCMD_GETEPSTATE:
return "Get Endpoint State";
case DWC3_DEPCMD_SETTRANSFRESOURCE:
return "Set Endpoint Transfer Resource";
case DWC3_DEPCMD_SETEPCONFIG:
return "Set Endpoint Configuration";
default:
return "UNKNOWN command";
}
}
/**
* dwc3_gadget_generic_cmd_string - returns generic command string
* @cmd: command code
*/
static inline const char *
dwc3_gadget_generic_cmd_string(u8 cmd)
{
switch (cmd) {
case DWC3_DGCMD_SET_LMP:
return "Set LMP";
case DWC3_DGCMD_SET_PERIODIC_PAR:
return "Set Periodic Parameters";
case DWC3_DGCMD_XMIT_FUNCTION:
return "Transmit Function Wake Device Notification";
case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO:
return "Set Scratchpad Buffer Array Address Lo";
case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI:
return "Set Scratchpad Buffer Array Address Hi";
case DWC3_DGCMD_SELECTED_FIFO_FLUSH:
return "Selected FIFO Flush";
case DWC3_DGCMD_ALL_FIFO_FLUSH:
return "All FIFO Flush";
case DWC3_DGCMD_SET_ENDPOINT_NRDY:
return "Set Endpoint NRDY";
case DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK:
return "Run SoC Bus Loopback Test";
default:
return "UNKNOWN";
}
}
/**
* dwc3_gadget_link_string - returns link name
* @link_state: link state code
*/
static inline const char *
dwc3_gadget_link_string(enum dwc3_link_state link_state)
{
switch (link_state) {
case DWC3_LINK_STATE_U0:
return "U0";
case DWC3_LINK_STATE_U1:
return "U1";
case DWC3_LINK_STATE_U2:
return "U2";
case DWC3_LINK_STATE_U3:
return "U3";
case DWC3_LINK_STATE_SS_DIS:
return "SS.Disabled";
case DWC3_LINK_STATE_RX_DET:
return "RX.Detect";
case DWC3_LINK_STATE_SS_INACT:
return "SS.Inactive";
case DWC3_LINK_STATE_POLL:
return "Polling";
case DWC3_LINK_STATE_RECOV:
return "Recovery";
case DWC3_LINK_STATE_HRESET:
return "Hot Reset";
case DWC3_LINK_STATE_CMPLY:
return "Compliance";
case DWC3_LINK_STATE_LPBK:
return "Loopback";
case DWC3_LINK_STATE_RESET:
return "Reset";
case DWC3_LINK_STATE_RESUME:
return "Resume";
default:
return "UNKNOWN link state\n";
}
}
/**
* dwc3_gadget_event_string - returns event name
* @event: the event code
*/
static inline const char *dwc3_gadget_event_string(u8 event)
{
switch (event) {
case DWC3_DEVICE_EVENT_DISCONNECT:
return "Disconnect";
case DWC3_DEVICE_EVENT_RESET:
return "Reset";
case DWC3_DEVICE_EVENT_CONNECT_DONE:
return "Connection Done";
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
return "Link Status Change";
case DWC3_DEVICE_EVENT_WAKEUP:
return "WakeUp";
case DWC3_DEVICE_EVENT_EOPF:
return "End-Of-Frame";
case DWC3_DEVICE_EVENT_SOF:
return "Start-Of-Frame";
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
return "Erratic Error";
case DWC3_DEVICE_EVENT_CMD_CMPL:
return "Command Complete";
case DWC3_DEVICE_EVENT_OVERFLOW:
return "Overflow";
}
return "UNKNOWN";
}
/**
* dwc3_ep_event_string - returns event name
* @event: then event code
*/
static inline const char *dwc3_ep_event_string(u8 event)
{
switch (event) {
case DWC3_DEPEVT_XFERCOMPLETE:
return "Transfer Complete";
case DWC3_DEPEVT_XFERINPROGRESS:
return "Transfer In-Progress";
case DWC3_DEPEVT_XFERNOTREADY:
return "Transfer Not Ready";
case DWC3_DEPEVT_RXTXFIFOEVT:
return "FIFO";
case DWC3_DEPEVT_STREAMEVT:
return "Stream";
case DWC3_DEPEVT_EPCMDCMPLT:
return "Endpoint Command Complete";
}
return "UNKNOWN";
}
/**
* dwc3_gadget_event_type_string - return event name
* @event: the event code
*/
static inline const char *dwc3_gadget_event_type_string(u8 event)
{
switch (event) {
case DWC3_DEVICE_EVENT_DISCONNECT:
return "Disconnect";
case DWC3_DEVICE_EVENT_RESET:
return "Reset";
case DWC3_DEVICE_EVENT_CONNECT_DONE:
return "Connect Done";
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
return "Link Status Change";
case DWC3_DEVICE_EVENT_WAKEUP:
return "Wake-Up";
case DWC3_DEVICE_EVENT_HIBER_REQ:
return "Hibernation";
case DWC3_DEVICE_EVENT_EOPF:
return "End of Periodic Frame";
case DWC3_DEVICE_EVENT_SOF:
return "Start of Frame";
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
return "Erratic Error";
case DWC3_DEVICE_EVENT_CMD_CMPL:
return "Command Complete";
case DWC3_DEVICE_EVENT_OVERFLOW:
return "Overflow";
default:
return "UNKNOWN";
}
}
void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...);
#ifdef CONFIG_DEBUG_FS
extern int dwc3_debugfs_init(struct dwc3 *);
extern void dwc3_debugfs_exit(struct dwc3 *);
......@@ -27,4 +225,4 @@ static inline int dwc3_debugfs_init(struct dwc3 *d)
static inline void dwc3_debugfs_exit(struct dwc3 *d)
{ }
#endif
#endif /* __DWC3_DEBUG_H */
......@@ -113,10 +113,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
int ret;
exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
if (!exynos) {
dev_err(dev, "not enough memory\n");
if (!exynos)
return -ENOMEM;
}
/*
* Right now device-tree probed devices don't get dma_mask set.
......
......@@ -481,10 +481,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
}
omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
if (!omap) {
dev_err(dev, "not enough memory\n");
if (!omap)
return -ENOMEM;
}
platform_set_drvdata(pdev, omap);
......
......@@ -103,10 +103,8 @@ static int dwc3_pci_probe(struct pci_dev *pci,
struct device *dev = &pci->dev;
glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
if (!glue) {
dev_err(dev, "not enough memory\n");
if (!glue)
return -ENOMEM;
}
glue->dev = dev;
......
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
struct dwc3_qcom {
struct device *dev;
struct clk *core_clk;
struct clk *iface_clk;
struct clk *sleep_clk;
};
static int dwc3_qcom_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct dwc3_qcom *qdwc;
int ret;
qdwc = devm_kzalloc(&pdev->dev, sizeof(*qdwc), GFP_KERNEL);
if (!qdwc)
return -ENOMEM;
platform_set_drvdata(pdev, qdwc);
qdwc->dev = &pdev->dev;
qdwc->core_clk = devm_clk_get(qdwc->dev, "core");
if (IS_ERR(qdwc->core_clk)) {
dev_err(qdwc->dev, "failed to get core clock\n");
return PTR_ERR(qdwc->core_clk);
}
qdwc->iface_clk = devm_clk_get(qdwc->dev, "iface");
if (IS_ERR(qdwc->iface_clk)) {
dev_dbg(qdwc->dev, "failed to get optional iface clock\n");
qdwc->iface_clk = NULL;
}
qdwc->sleep_clk = devm_clk_get(qdwc->dev, "sleep");
if (IS_ERR(qdwc->sleep_clk)) {
dev_dbg(qdwc->dev, "failed to get optional sleep clock\n");
qdwc->sleep_clk = NULL;
}
ret = clk_prepare_enable(qdwc->core_clk);
if (ret) {
dev_err(qdwc->dev, "failed to enable core clock\n");
goto err_core;
}
ret = clk_prepare_enable(qdwc->iface_clk);
if (ret) {
dev_err(qdwc->dev, "failed to enable optional iface clock\n");
goto err_iface;
}
ret = clk_prepare_enable(qdwc->sleep_clk);
if (ret) {
dev_err(qdwc->dev, "failed to enable optional sleep clock\n");
goto err_sleep;
}
ret = of_platform_populate(node, NULL, NULL, qdwc->dev);
if (ret) {
dev_err(qdwc->dev, "failed to register core - %d\n", ret);
goto err_clks;
}
return 0;
err_clks:
clk_disable_unprepare(qdwc->sleep_clk);
err_sleep:
clk_disable_unprepare(qdwc->iface_clk);
err_iface:
clk_disable_unprepare(qdwc->core_clk);
err_core:
return ret;
}
static int dwc3_qcom_remove(struct platform_device *pdev)
{
struct dwc3_qcom *qdwc = platform_get_drvdata(pdev);
of_platform_depopulate(&pdev->dev);
clk_disable_unprepare(qdwc->sleep_clk);
clk_disable_unprepare(qdwc->iface_clk);
clk_disable_unprepare(qdwc->core_clk);
return 0;
}
static const struct of_device_id of_dwc3_match[] = {
{ .compatible = "qcom,dwc3" },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_dwc3_match);
static struct platform_driver dwc3_qcom_driver = {
.probe = dwc3_qcom_probe,
.remove = dwc3_qcom_remove,
.driver = {
.name = "qcom-dwc3",
.owner = THIS_MODULE,
.of_match_table = of_dwc3_match,
},
};
module_platform_driver(dwc3_qcom_driver);
MODULE_ALIAS("platform:qcom-dwc3");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 QCOM Glue Layer");
MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");
This diff is collapsed.
......@@ -31,6 +31,7 @@
#include <linux/usb/composite.h>
#include "core.h"
#include "debug.h"
#include "gadget.h"
#include "io.h"
......@@ -65,7 +66,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
dep = dwc->eps[epnum];
if (dep->flags & DWC3_EP_BUSY) {
dev_vdbg(dwc->dev, "%s: still busy\n", dep->name);
dwc3_trace(trace_dwc3_ep0, "%s still busy", dep->name);
return 0;
}
......@@ -88,7 +89,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
DWC3_DEPCMD_STARTTRANSFER, &params);
if (ret < 0) {
dev_dbg(dwc->dev, "failed to send STARTTRANSFER command\n");
dwc3_trace(trace_dwc3_ep0, "%s STARTTRANSFER failed",
dep->name);
return ret;
}
......@@ -153,7 +155,8 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
if (dwc->ep0state == EP0_STATUS_PHASE)
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
else
dev_dbg(dwc->dev, "too early for delayed status\n");
dwc3_trace(trace_dwc3_ep0,
"too early for delayed status");
return 0;
}
......@@ -217,7 +220,8 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
spin_lock_irqsave(&dwc->lock, flags);
if (!dep->endpoint.desc) {
dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
dwc3_trace(trace_dwc3_ep0,
"trying to queue request %p to disabled %s",
request, dep->name);
ret = -ESHUTDOWN;
goto out;
......@@ -229,7 +233,8 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
goto out;
}
dev_vdbg(dwc->dev, "queueing request %p to %s length %d, state '%s'\n",
dwc3_trace(trace_dwc3_ep0,
"queueing request %p to %s length %d state '%s'",
request, dep->name, request->length,
dwc3_ep0_state_string(dwc->ep0state));
......@@ -485,12 +490,13 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
addr = le16_to_cpu(ctrl->wValue);
if (addr > 127) {
dev_dbg(dwc->dev, "invalid device address %d\n", addr);
dwc3_trace(trace_dwc3_ep0, "invalid device address %d", addr);
return -EINVAL;
}
if (state == USB_STATE_CONFIGURED) {
dev_dbg(dwc->dev, "trying to set address when configured\n");
dwc3_trace(trace_dwc3_ep0,
"trying to set address when configured");
return -EINVAL;
}
......@@ -556,7 +562,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc->resize_fifos = true;
dev_dbg(dwc->dev, "resize fifos flag SET\n");
dwc3_trace(trace_dwc3_ep0, "resize FIFOs flag SET");
}
break;
......@@ -680,35 +686,35 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
switch (ctrl->bRequest) {
case USB_REQ_GET_STATUS:
dev_vdbg(dwc->dev, "USB_REQ_GET_STATUS\n");
dwc3_trace(trace_dwc3_ep0, "USB_REQ_GET_STATUS\n");
ret = dwc3_ep0_handle_status(dwc, ctrl);
break;
case USB_REQ_CLEAR_FEATURE:
dev_vdbg(dwc->dev, "USB_REQ_CLEAR_FEATURE\n");
dwc3_trace(trace_dwc3_ep0, "USB_REQ_CLEAR_FEATURE\n");
ret = dwc3_ep0_handle_feature(dwc, ctrl, 0);
break;
case USB_REQ_SET_FEATURE:
dev_vdbg(dwc->dev, "USB_REQ_SET_FEATURE\n");
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_FEATURE\n");
ret = dwc3_ep0_handle_feature(dwc, ctrl, 1);
break;
case USB_REQ_SET_ADDRESS:
dev_vdbg(dwc->dev, "USB_REQ_SET_ADDRESS\n");
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ADDRESS\n");
ret = dwc3_ep0_set_address(dwc, ctrl);
break;
case USB_REQ_SET_CONFIGURATION:
dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n");
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_CONFIGURATION\n");
ret = dwc3_ep0_set_config(dwc, ctrl);
break;
case USB_REQ_SET_SEL:
dev_vdbg(dwc->dev, "USB_REQ_SET_SEL\n");
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_SEL\n");
ret = dwc3_ep0_set_sel(dwc, ctrl);
break;
case USB_REQ_SET_ISOCH_DELAY:
dev_vdbg(dwc->dev, "USB_REQ_SET_ISOCH_DELAY\n");
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY\n");
ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
break;
default:
dev_vdbg(dwc->dev, "Forwarding to gadget driver\n");
dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver\n");
ret = dwc3_ep0_delegate_req(dwc, ctrl);
break;
}
......@@ -726,6 +732,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
if (!dwc->gadget_driver)
goto out;
trace_dwc3_ctrl_req(ctrl);
len = le16_to_cpu(ctrl->wLength);
if (!len) {
dwc->three_stage_setup = false;
......@@ -774,7 +782,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
status = DWC3_TRB_SIZE_TRBSTS(trb->size);
if (status == DWC3_TRBSTS_SETUP_PENDING) {
dev_dbg(dwc->dev, "Setup Pending received\n");
dwc3_trace(trace_dwc3_ep0, "Setup Pending received");
if (r)
dwc3_gadget_giveback(ep0, r, -ECONNRESET);
......@@ -834,7 +842,7 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
if (ret < 0) {
dev_dbg(dwc->dev, "Invalid Test #%d\n",
dwc3_trace(trace_dwc3_ep0, "Invalid Test #%d",
dwc->test_mode_nr);
dwc3_ep0_stall_and_restart(dwc);
return;
......@@ -843,7 +851,7 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
status = DWC3_TRB_SIZE_TRBSTS(trb->size);
if (status == DWC3_TRBSTS_SETUP_PENDING)
dev_dbg(dwc->dev, "Setup Pending received\n");
dwc3_trace(trace_dwc3_ep0, "Setup Pending received\n");
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
......@@ -860,17 +868,17 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
switch (dwc->ep0state) {
case EP0_SETUP_PHASE:
dev_vdbg(dwc->dev, "Inspecting Setup Bytes\n");
dwc3_trace(trace_dwc3_ep0, "Setup Phase");
dwc3_ep0_inspect_setup(dwc, event);
break;
case EP0_DATA_PHASE:
dev_vdbg(dwc->dev, "Data Phase\n");
dwc3_trace(trace_dwc3_ep0, "Data Phase");
dwc3_ep0_complete_data(dwc, event);
break;
case EP0_STATUS_PHASE:
dev_vdbg(dwc->dev, "Status Phase\n");
dwc3_trace(trace_dwc3_ep0, "Status Phase");
dwc3_ep0_complete_status(dwc, event);
break;
default:
......@@ -946,7 +954,7 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
{
if (dwc->resize_fifos) {
dev_dbg(dwc->dev, "starting to resize fifos\n");
dwc3_trace(trace_dwc3_ep0, "Resizing FIFOs");
dwc3_gadget_resize_tx_fifos(dwc);
dwc->resize_fifos = 0;
}
......@@ -987,7 +995,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
switch (event->status) {
case DEPEVT_STATUS_CONTROL_DATA:
dev_vdbg(dwc->dev, "Control Data\n");
dwc3_trace(trace_dwc3_ep0, "Control Data");
/*
* We already have a DATA transfer in the controller's cache,
......@@ -1001,7 +1009,8 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_expect_in != event->endpoint_number) {
struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in];
dev_vdbg(dwc->dev, "Wrong direction for Data phase\n");
dwc3_trace(trace_dwc3_ep0,
"Wrong direction for Data phase");
dwc3_ep0_end_control_data(dwc, dep);
dwc3_ep0_stall_and_restart(dwc);
return;
......@@ -1013,13 +1022,13 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
return;
dev_vdbg(dwc->dev, "Control Status\n");
dwc3_trace(trace_dwc3_ep0, "Control Status");
dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) {
WARN_ON_ONCE(event->endpoint_number != 1);
dev_vdbg(dwc->dev, "Mass Storage delayed status\n");
dwc3_trace(trace_dwc3_ep0, "Delayed Status");
return;
}
......@@ -1032,7 +1041,7 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc,
{
u8 epnum = event->endpoint_number;
dev_dbg(dwc->dev, "%s while ep%d%s in state '%s'\n",
dwc3_trace(trace_dwc3_ep0, "%s while ep%d%s in state '%s'",
dwc3_ep_event_string(event->endpoint_event),
epnum >> 1, (epnum & 1) ? "in" : "out",
dwc3_ep0_state_string(dwc->ep0state));
......
......@@ -30,6 +30,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include "debug.h"
#include "core.h"
#include "gadget.h"
#include "io.h"
......@@ -266,107 +267,19 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
req, dep->name, req->request.actual,
req->request.length, status);
trace_dwc3_gadget_giveback(req);
spin_unlock(&dwc->lock);
req->request.complete(&dep->endpoint, &req->request);
spin_lock(&dwc->lock);
}
static const char *dwc3_gadget_ep_cmd_string(u8 cmd)
{
switch (cmd) {
case DWC3_DEPCMD_DEPSTARTCFG:
return "Start New Configuration";
case DWC3_DEPCMD_ENDTRANSFER:
return "End Transfer";
case DWC3_DEPCMD_UPDATETRANSFER:
return "Update Transfer";
case DWC3_DEPCMD_STARTTRANSFER:
return "Start Transfer";
case DWC3_DEPCMD_CLEARSTALL:
return "Clear Stall";
case DWC3_DEPCMD_SETSTALL:
return "Set Stall";
case DWC3_DEPCMD_GETEPSTATE:
return "Get Endpoint State";
case DWC3_DEPCMD_SETTRANSFRESOURCE:
return "Set Endpoint Transfer Resource";
case DWC3_DEPCMD_SETEPCONFIG:
return "Set Endpoint Configuration";
default:
return "UNKNOWN command";
}
}
static const char *dwc3_gadget_generic_cmd_string(u8 cmd)
{
switch (cmd) {
case DWC3_DGCMD_SET_LMP:
return "Set LMP";
case DWC3_DGCMD_SET_PERIODIC_PAR:
return "Set Periodic Parameters";
case DWC3_DGCMD_XMIT_FUNCTION:
return "Transmit Function Wake Device Notification";
case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO:
return "Set Scratchpad Buffer Array Address Lo";
case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI:
return "Set Scratchpad Buffer Array Address Hi";
case DWC3_DGCMD_SELECTED_FIFO_FLUSH:
return "Selected FIFO Flush";
case DWC3_DGCMD_ALL_FIFO_FLUSH:
return "All FIFO Flush";
case DWC3_DGCMD_SET_ENDPOINT_NRDY:
return "Set Endpoint NRDY";
case DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK:
return "Run SoC Bus Loopback Test";
default:
return "UNKNOWN";
}
}
static const char *dwc3_gadget_link_string(enum dwc3_link_state link_state)
{
switch (link_state) {
case DWC3_LINK_STATE_U0:
return "U0";
case DWC3_LINK_STATE_U1:
return "U1";
case DWC3_LINK_STATE_U2:
return "U2";
case DWC3_LINK_STATE_U3:
return "U3";
case DWC3_LINK_STATE_SS_DIS:
return "SS.Disabled";
case DWC3_LINK_STATE_RX_DET:
return "RX.Detect";
case DWC3_LINK_STATE_SS_INACT:
return "SS.Inactive";
case DWC3_LINK_STATE_POLL:
return "Polling";
case DWC3_LINK_STATE_RECOV:
return "Recovery";
case DWC3_LINK_STATE_HRESET:
return "Hot Reset";
case DWC3_LINK_STATE_CMPLY:
return "Compliance";
case DWC3_LINK_STATE_LPBK:
return "Loopback";
case DWC3_LINK_STATE_RESET:
return "Reset";
case DWC3_LINK_STATE_RESUME:
return "Resume";
default:
return "UNKNOWN link state\n";
}
}
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param)
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
{
u32 timeout = 500;
u32 reg;
dev_vdbg(dwc->dev, "generic cmd '%s' [%d] param %08x\n",
dwc3_gadget_generic_cmd_string(cmd), cmd, param);
trace_dwc3_gadget_generic_cmd(cmd, param);
dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
......@@ -397,10 +310,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
u32 timeout = 500;
u32 reg;
dev_vdbg(dwc->dev, "%s: cmd '%s' [%d] params %08x %08x %08x\n",
dep->name,
dwc3_gadget_ep_cmd_string(cmd), cmd, params->param0,
params->param1, params->param2);
trace_dwc3_gadget_ep_cmd(dep, cmd, params);
dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0);
dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1);
......@@ -789,17 +699,16 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep,
{
struct dwc3_request *req;
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
req = kzalloc(sizeof(*req), gfp_flags);
if (!req) {
dev_err(dwc->dev, "not enough memory\n");
if (!req)
return NULL;
}
req->epnum = dep->number;
req->dep = dep;
trace_dwc3_alloc_request(req);
return &req->request;
}
......@@ -808,6 +717,7 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep,
{
struct dwc3_request *req = to_dwc3_request(request);
trace_dwc3_free_request(req);
kfree(req);
}
......@@ -889,6 +799,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
trb->ctrl |= DWC3_TRB_CTRL_HWO;
trace_dwc3_prepare_trb(dep, trb);
}
/*
......@@ -1235,6 +1147,7 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
dev_vdbg(dwc->dev, "queing request %p to %s length %d\n",
request, ep->name, request->length);
trace_dwc3_ep_queue(req);
ret = __dwc3_gadget_ep_queue(dep, req);
spin_unlock_irqrestore(&dwc->lock, flags);
......@@ -1254,6 +1167,8 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
unsigned long flags;
int ret = 0;
trace_dwc3_ep_dequeue(req);
spin_lock_irqsave(&dwc->lock, flags);
list_for_each_entry(r, &dep->request_list, list) {
......@@ -1744,11 +1659,8 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
u8 epnum = (i << 1) | (!!direction);
dep = kzalloc(sizeof(*dep), GFP_KERNEL);
if (!dep) {
dev_err(dwc->dev, "can't allocate endpoint %d\n",
epnum);
if (!dep)
return -ENOMEM;
}
dep->dwc = dwc;
dep->number = epnum;
......@@ -1847,6 +1759,8 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
unsigned int s_pkt = 0;
unsigned int trb_status;
trace_dwc3_complete_trb(dep, trb);
if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
/*
* We continue despite the error. There is not much we
......@@ -2021,9 +1935,6 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
if (!(dep->flags & DWC3_EP_ENABLED))
return;
dev_vdbg(dwc->dev, "%s: %s\n", dep->name,
dwc3_ep_event_string(event->endpoint_event));
if (epnum == 0 || epnum == 1) {
dwc3_ep0_interrupt(dwc, event);
return;
......@@ -2210,8 +2121,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
{
int reg;
dev_vdbg(dwc->dev, "%s\n", __func__);
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_INITU1ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
......@@ -2230,8 +2139,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
{
u32 reg;
dev_vdbg(dwc->dev, "%s\n", __func__);
/*
* WORKAROUND: DWC3 revisions <1.88a have an issue which
* would cause a missing Disconnect Event if there's a
......@@ -2316,8 +2223,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
u32 reg;
u8 speed;
dev_vdbg(dwc->dev, "%s\n", __func__);
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
speed = reg & DWC3_DSTS_CONNECTSPD;
dwc->speed = speed;
......@@ -2415,8 +2320,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
{
dev_vdbg(dwc->dev, "%s\n", __func__);
/*
* TODO take core out of low power mode when that's
* implemented.
......@@ -2521,10 +2424,6 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
break;
}
dev_vdbg(dwc->dev, "link change: %s [%d] -> %s [%d]\n",
dwc3_gadget_link_string(dwc->link_state),
dwc->link_state, dwc3_gadget_link_string(next), next);
dwc->link_state = next;
}
......@@ -2601,6 +2500,8 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
static void dwc3_process_event_entry(struct dwc3 *dwc,
const union dwc3_event *event)
{
trace_dwc3_event(event->raw);
/* Endpoint IRQ, handle it and return early */
if (event->type.is_devspec == 0) {
/* depevt */
......@@ -2754,7 +2655,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL);
if (!dwc->setup_buf) {
dev_err(dwc->dev, "failed to allocate setup buffer\n");
ret = -ENOMEM;
goto err2;
}
......
......@@ -103,60 +103,4 @@ static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3 *dwc, u8 number)
return DWC3_DEPCMD_GET_RSC_IDX(res_id);
}
/**
* dwc3_gadget_event_string - returns event name
* @event: the event code
*/
static inline const char *dwc3_gadget_event_string(u8 event)
{
switch (event) {
case DWC3_DEVICE_EVENT_DISCONNECT:
return "Disconnect";
case DWC3_DEVICE_EVENT_RESET:
return "Reset";
case DWC3_DEVICE_EVENT_CONNECT_DONE:
return "Connection Done";
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
return "Link Status Change";
case DWC3_DEVICE_EVENT_WAKEUP:
return "WakeUp";
case DWC3_DEVICE_EVENT_EOPF:
return "End-Of-Frame";
case DWC3_DEVICE_EVENT_SOF:
return "Start-Of-Frame";
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
return "Erratic Error";
case DWC3_DEVICE_EVENT_CMD_CMPL:
return "Command Complete";
case DWC3_DEVICE_EVENT_OVERFLOW:
return "Overflow";
}
return "UNKNOWN";
}
/**
* dwc3_ep_event_string - returns event name
* @event: then event code
*/
static inline const char *dwc3_ep_event_string(u8 event)
{
switch (event) {
case DWC3_DEPEVT_XFERCOMPLETE:
return "Transfer Complete";
case DWC3_DEPEVT_XFERINPROGRESS:
return "Transfer In-Progress";
case DWC3_DEPEVT_XFERNOTREADY:
return "Transfer Not Ready";
case DWC3_DEPEVT_RXTXFIFOEVT:
return "FIFO";
case DWC3_DEPEVT_STREAMEVT:
return "Stream";
case DWC3_DEPEVT_EPCMDCMPLT:
return "Endpoint Command Complete";
}
return "UNKNOWN";
}
#endif /* __DRIVERS_USB_DWC3_GADGET_H */
......@@ -20,27 +20,51 @@
#define __DRIVERS_USB_DWC3_IO_H
#include <linux/io.h>
#include "trace.h"
#include "debug.h"
#include "core.h"
static inline u32 dwc3_readl(void __iomem *base, u32 offset)
{
u32 offs = offset - DWC3_GLOBALS_REGS_START;
u32 value;
/*
* We requested the mem region starting from the Globals address
* space, see dwc3_probe in core.c.
* However, the offsets are given starting from xHCI address space.
*/
return readl(base + (offset - DWC3_GLOBALS_REGS_START));
value = readl(base + offs);
/*
* When tracing we want to make it easy to find the correct address on
* documentation, so we revert it back to the proper addresses, the
* same way they are described on SNPS documentation
*/
dwc3_trace(trace_dwc3_readl, "addr %p value %08x",
base - DWC3_GLOBALS_REGS_START + offset, value);
return value;
}
static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
{
u32 offs = offset - DWC3_GLOBALS_REGS_START;
/*
* We requested the mem region starting from the Globals address
* space, see dwc3_probe in core.c.
* However, the offsets are given starting from xHCI address space.
*/
writel(value, base + (offset - DWC3_GLOBALS_REGS_START));
writel(value, base + offs);
/*
* When tracing we want to make it easy to find the correct address on
* documentation, so we revert it back to the proper addresses, the
* same way they are described on SNPS documentation
*/
dwc3_trace(trace_dwc3_writel, "addr %p value %08x",
base - DWC3_GLOBALS_REGS_START + offset, value);
}
#endif /* __DRIVERS_USB_DWC3_IO_H */
/**
* trace.c - DesignWare USB3 DRD Controller Trace Support
*
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Felipe Balbi <balbi@ti.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define CREATE_TRACE_POINTS
#include "trace.h"
/**
* trace.h - DesignWare USB3 DRD Controller Trace Support
*
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Felipe Balbi <balbi@ti.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM dwc3
#if !defined(__DWC3_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define __DWC3_TRACE_H
#include <linux/types.h>
#include <linux/tracepoint.h>
#include <asm/byteorder.h>
#include "core.h"
#include "debug.h"
DECLARE_EVENT_CLASS(dwc3_log_msg,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf),
TP_STRUCT__entry(__dynamic_array(char, msg, DWC3_MSG_MAX)),
TP_fast_assign(
vsnprintf(__get_str(msg), DWC3_MSG_MAX, vaf->fmt, *vaf->va);
),
TP_printk("%s", __get_str(msg))
);
DEFINE_EVENT(dwc3_log_msg, dwc3_readl,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(dwc3_log_msg, dwc3_writel,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(dwc3_log_msg, dwc3_ep0,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DECLARE_EVENT_CLASS(dwc3_log_event,
TP_PROTO(u32 event),
TP_ARGS(event),
TP_STRUCT__entry(
__field(u32, event)
),
TP_fast_assign(
__entry->event = event;
),
TP_printk("event %08x\n", __entry->event)
);
DEFINE_EVENT(dwc3_log_event, dwc3_event,
TP_PROTO(u32 event),
TP_ARGS(event)
);
DECLARE_EVENT_CLASS(dwc3_log_ctrl,
TP_PROTO(struct usb_ctrlrequest *ctrl),
TP_ARGS(ctrl),
TP_STRUCT__entry(
__field(struct usb_ctrlrequest *, ctrl)
),
TP_fast_assign(
__entry->ctrl = ctrl;
),
TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d",
__entry->ctrl->bRequestType, __entry->ctrl->bRequest,
le16_to_cpu(__entry->ctrl->wValue), le16_to_cpu(__entry->ctrl->wIndex),
le16_to_cpu(__entry->ctrl->wLength)
)
);
DEFINE_EVENT(dwc3_log_ctrl, dwc3_ctrl_req,
TP_PROTO(struct usb_ctrlrequest *ctrl),
TP_ARGS(ctrl)
);
DECLARE_EVENT_CLASS(dwc3_log_request,
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req),
TP_STRUCT__entry(
__field(struct dwc3_request *, req)
),
TP_fast_assign(
__entry->req = req;
),
TP_printk("%s: req %p length %u/%u ==> %d",
__entry->req->dep->name, __entry->req,
__entry->req->request.actual, __entry->req->request.length,
__entry->req->request.status
)
);
DEFINE_EVENT(dwc3_log_request, dwc3_alloc_request,
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req)
);
DEFINE_EVENT(dwc3_log_request, dwc3_free_request,
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req)
);
DEFINE_EVENT(dwc3_log_request, dwc3_ep_queue,
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req)
);
DEFINE_EVENT(dwc3_log_request, dwc3_ep_dequeue,
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req)
);
DEFINE_EVENT(dwc3_log_request, dwc3_gadget_giveback,
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req)
);
DECLARE_EVENT_CLASS(dwc3_log_generic_cmd,
TP_PROTO(unsigned int cmd, u32 param),
TP_ARGS(cmd, param),
TP_STRUCT__entry(
__field(unsigned int, cmd)
__field(u32, param)
),
TP_fast_assign(
__entry->cmd = cmd;
__entry->param = param;
),
TP_printk("cmd '%s' [%d] param %08x\n",
dwc3_gadget_generic_cmd_string(__entry->cmd),
__entry->cmd, __entry->param
)
);
DEFINE_EVENT(dwc3_log_generic_cmd, dwc3_gadget_generic_cmd,
TP_PROTO(unsigned int cmd, u32 param),
TP_ARGS(cmd, param)
);
DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
TP_PROTO(struct dwc3_ep *dep, unsigned int cmd,
struct dwc3_gadget_ep_cmd_params *params),
TP_ARGS(dep, cmd, params),
TP_STRUCT__entry(
__field(struct dwc3_ep *, dep)
__field(unsigned int, cmd)
__field(struct dwc3_gadget_ep_cmd_params *, params)
),
TP_fast_assign(
__entry->dep = dep;
__entry->cmd = cmd;
__entry->params = params;
),
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x\n",
__entry->dep->name, dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->params->param0,
__entry->params->param1, __entry->params->param2
)
);
DEFINE_EVENT(dwc3_log_gadget_ep_cmd, dwc3_gadget_ep_cmd,
TP_PROTO(struct dwc3_ep *dep, unsigned int cmd,
struct dwc3_gadget_ep_cmd_params *params),
TP_ARGS(dep, cmd, params)
);
DECLARE_EVENT_CLASS(dwc3_log_trb,
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
TP_ARGS(dep, trb),
TP_STRUCT__entry(
__field(struct dwc3_ep *, dep)
__field(struct dwc3_trb *, trb)
),
TP_fast_assign(
__entry->dep = dep;
__entry->trb = trb;
),
TP_printk("%s: trb %p bph %08x bpl %08x size %08x ctrl %08x\n",
__entry->dep->name, __entry->trb, __entry->trb->bph,
__entry->trb->bpl, __entry->trb->size, __entry->trb->ctrl
)
);
DEFINE_EVENT(dwc3_log_trb, dwc3_prepare_trb,
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
TP_ARGS(dep, trb)
);
DEFINE_EVENT(dwc3_log_trb, dwc3_complete_trb,
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
TP_ARGS(dep, trb)
);
#endif /* __DWC3_TRACE_H */
/* this part has to be here */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>
......@@ -181,6 +181,15 @@ config USB_F_MASS_STORAGE
config USB_F_FS
tristate
config USB_F_UAC1
tristate
config USB_F_UAC2
tristate
config USB_F_UVC
tristate
choice
tristate "USB Gadget Drivers"
default USB_ETH
......
......@@ -3,7 +3,7 @@
#
subdir-ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
subdir-ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG
ccflags-y += -Idrivers/usb/gadget/udc
ccflags-y += -I$(srctree)/drivers/usb/gadget/udc
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y := usbstring.o config.o epautoconf.o
......
......@@ -2073,6 +2073,7 @@ static const struct usb_gadget_driver composite_driver_template = {
.unbind = composite_unbind,
.setup = composite_setup,
.reset = composite_disconnect,
.disconnect = composite_disconnect,
.suspend = composite_suspend,
......
......@@ -1450,6 +1450,7 @@ static const struct usb_gadget_driver configfs_driver_template = {
.unbind = configfs_composite_unbind,
.setup = composite_setup,
.reset = composite_disconnect,
.disconnect = composite_disconnect,
.max_speed = USB_SPEED_SUPER,
......
......@@ -2,8 +2,8 @@
# USB peripheral controller drivers
#
ccflags-y := -Idrivers/usb/gadget/
ccflags-y += -Idrivers/usb/gadget/udc/
ccflags-y := -I$(srctree)/drivers/usb/gadget/
ccflags-y += -I$(srctree)/drivers/usb/gadget/udc/
# USB Functions
usb_f_acm-y := f_acm.o
......@@ -32,3 +32,9 @@ usb_f_mass_storage-y := f_mass_storage.o storage_common.o
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
usb_f_fs-y := f_fs.o
obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
usb_f_uac1-y := f_uac1.o u_uac1.o
obj-$(CONFIG_USB_F_UAC1) += usb_f_uac1.o
usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o
usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o
obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o
......@@ -313,15 +313,15 @@ static void acm_complete_set_line_coding(struct usb_ep *ep,
struct usb_composite_dev *cdev = acm->port.func.config->cdev;
if (req->status != 0) {
DBG(cdev, "acm ttyGS%d completion, err %d\n",
acm->port_num, req->status);
dev_dbg(&cdev->gadget->dev, "acm ttyGS%d completion, err %d\n",
acm->port_num, req->status);
return;
}
/* normal completion */
if (req->actual != sizeof(acm->port_line_coding)) {
DBG(cdev, "acm ttyGS%d short resp, len %d\n",
acm->port_num, req->actual);
dev_dbg(&cdev->gadget->dev, "acm ttyGS%d short resp, len %d\n",
acm->port_num, req->actual);
usb_ep_set_halt(ep);
} else {
struct usb_cdc_line_coding *value = req->buf;
......@@ -397,14 +397,16 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
default:
invalid:
VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
w_value, w_index, w_length);
dev_vdbg(&cdev->gadget->dev,
"invalid control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
w_value, w_index, w_length);
}
/* respond with data transfer or status phase? */
if (value >= 0) {
DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
dev_dbg(&cdev->gadget->dev,
"acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
acm->port_num, ctrl->bRequestType, ctrl->bRequest,
w_value, w_index, w_length);
req->zero = 0;
......@@ -428,10 +430,12 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (intf == acm->ctrl_id) {
if (acm->notify->driver_data) {
VDBG(cdev, "reset acm control interface %d\n", intf);
dev_vdbg(&cdev->gadget->dev,
"reset acm control interface %d\n", intf);
usb_ep_disable(acm->notify);
} else {
VDBG(cdev, "init acm ctrl interface %d\n", intf);
dev_vdbg(&cdev->gadget->dev,
"init acm ctrl interface %d\n", intf);
if (config_ep_by_speed(cdev->gadget, f, acm->notify))
return -EINVAL;
}
......@@ -440,11 +444,13 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
} else if (intf == acm->data_id) {
if (acm->port.in->driver_data) {
DBG(cdev, "reset acm ttyGS%d\n", acm->port_num);
dev_dbg(&cdev->gadget->dev,
"reset acm ttyGS%d\n", acm->port_num);
gserial_disconnect(&acm->port);
}
if (!acm->port.in->desc || !acm->port.out->desc) {
DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
dev_dbg(&cdev->gadget->dev,
"activate acm ttyGS%d\n", acm->port_num);
if (config_ep_by_speed(cdev->gadget, f,
acm->port.in) ||
config_ep_by_speed(cdev->gadget, f,
......@@ -467,7 +473,7 @@ static void acm_disable(struct usb_function *f)
struct f_acm *acm = func_to_acm(f);
struct usb_composite_dev *cdev = f->config->cdev;
DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
dev_dbg(&cdev->gadget->dev, "acm ttyGS%d deactivated\n", acm->port_num);
gserial_disconnect(&acm->port);
usb_ep_disable(acm->notify);
acm->notify->driver_data = NULL;
......@@ -537,8 +543,8 @@ static int acm_notify_serial_state(struct f_acm *acm)
spin_lock(&acm->lock);
if (acm->notify_req) {
DBG(cdev, "acm ttyGS%d serial state %04x\n",
acm->port_num, acm->serial_state);
dev_dbg(&cdev->gadget->dev, "acm ttyGS%d serial state %04x\n",
acm->port_num, acm->serial_state);
status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
0, &acm->serial_state, sizeof(acm->serial_state));
} else {
......@@ -691,12 +697,13 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
if (status)
goto fail;
DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
acm->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
acm->port.in->name, acm->port.out->name,
acm->notify->name);
dev_dbg(&cdev->gadget->dev,
"acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
acm->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
acm->port.in->name, acm->port.out->name,
acm->notify->name);
return 0;
fail:
......
......@@ -1032,6 +1032,29 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
case FUNCTIONFS_ENDPOINT_REVMAP:
ret = epfile->ep->num;
break;
case FUNCTIONFS_ENDPOINT_DESC:
{
int desc_idx;
struct usb_endpoint_descriptor *desc;
switch (epfile->ffs->gadget->speed) {
case USB_SPEED_SUPER:
desc_idx = 2;
break;
case USB_SPEED_HIGH:
desc_idx = 1;
break;
default:
desc_idx = 0;
}
desc = epfile->ep->descs[desc_idx];
spin_unlock_irq(&epfile->ffs->eps_lock);
ret = copy_to_user((void *)value, desc, sizeof(*desc));
if (ret)
ret = -EFAULT;
return ret;
}
default:
ret = -ENOTTY;
}
......@@ -1534,7 +1557,10 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
epfile->ffs = ffs;
mutex_init(&epfile->mutex);
init_waitqueue_head(&epfile->wait);
sprintf(epfiles->name, "ep%u", i);
if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
sprintf(epfiles->name, "ep%02x", ffs->eps_addrmap[i]);
else
sprintf(epfiles->name, "ep%u", i);
if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile,
&ffs_epfile_operations,
&epfile->dentry))) {
......@@ -2083,10 +2109,12 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
break;
case FUNCTIONFS_DESCRIPTORS_MAGIC_V2:
flags = get_unaligned_le32(data + 8);
ffs->user_flags = flags;
if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
FUNCTIONFS_HAS_HS_DESC |
FUNCTIONFS_HAS_SS_DESC |
FUNCTIONFS_HAS_MS_OS_DESC)) {
FUNCTIONFS_HAS_MS_OS_DESC |
FUNCTIONFS_VIRTUAL_ADDR)) {
ret = -ENOSYS;
goto error;
}
......@@ -2346,7 +2374,8 @@ static void __ffs_event_add(struct ffs_data *ffs,
break;
default:
BUG();
WARN(1, "%d: unknown event, this should not happen\n", type);
return;
}
{
......@@ -2393,7 +2422,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
struct usb_endpoint_descriptor *ds = (void *)desc;
struct ffs_function *func = priv;
struct ffs_ep *ffs_ep;
unsigned ep_desc_id, idx;
unsigned ep_desc_id;
int idx;
static const char *speed_names[] = { "full", "high", "super" };
if (type != FFS_DESCRIPTOR)
......@@ -2441,7 +2471,13 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
} else {
struct usb_request *req;
struct usb_ep *ep;
u8 bEndpointAddress;
/*
* We back up bEndpointAddress because autoconfig overwrites
* it with physical endpoint address.
*/
bEndpointAddress = ds->bEndpointAddress;
pr_vdebug("autoconfig\n");
ep = usb_ep_autoconfig(func->gadget, ds);
if (unlikely(!ep))
......@@ -2456,6 +2492,12 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
ffs_ep->req = req;
func->eps_revmap[ds->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK] = idx + 1;
/*
* If we use virtual address mapping, we restore
* original bEndpointAddress value.
*/
if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
ds->bEndpointAddress = bEndpointAddress;
}
ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
......@@ -2900,6 +2942,8 @@ static int ffs_func_setup(struct usb_function *f,
ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex));
if (unlikely(ret < 0))
return ret;
if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
ret = func->ffs->eps_addrmap[ret];
break;
default:
......
......@@ -298,7 +298,8 @@ static void disable_loopback(struct f_loopback *loop)
struct usb_composite_dev *cdev;
cdev = loop->function.config->cdev;
disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL);
disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL, NULL,
NULL);
VDBG(cdev, "%s disabled\n", loop->function.name);
}
......
......@@ -566,22 +566,22 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
*pbusy = 1;
*state = BUF_STATE_BUSY;
spin_unlock_irq(&fsg->common->lock);
rc = usb_ep_queue(ep, req, GFP_KERNEL);
if (rc != 0) {
*pbusy = 0;
*state = BUF_STATE_EMPTY;
if (rc == 0)
return; /* All good, we're done */
/* We can't do much more than wait for a reset */
*pbusy = 0;
*state = BUF_STATE_EMPTY;
/*
* Note: currently the net2280 driver fails zero-length
* submissions if DMA is enabled.
*/
if (rc != -ESHUTDOWN &&
!(rc == -EOPNOTSUPP && req->length == 0))
WARNING(fsg, "error in submission: %s --> %d\n",
ep->name, rc);
}
/* We can't do much more than wait for a reset */
/*
* Note: currently the net2280 driver fails zero-length
* submissions if DMA is enabled.
*/
if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && req->length == 0))
WARNING(fsg, "error in submission: %s --> %d\n", ep->name, rc);
}
static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
......@@ -3665,4 +3665,3 @@ void fsg_config_from_params(struct fsg_config *cfg,
cfg->fsg_num_buffers = fsg_num_buffers;
}
EXPORT_SYMBOL_GPL(fsg_config_from_params);
......@@ -200,19 +200,22 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt != 0)
goto fail;
/* NOP */
DBG(cdev, "reset obex ttyGS%d control\n", obex->port_num);
dev_dbg(&cdev->gadget->dev,
"reset obex ttyGS%d control\n", obex->port_num);
} else if (intf == obex->data_id) {
if (alt > 1)
goto fail;
if (obex->port.in->driver_data) {
DBG(cdev, "reset obex ttyGS%d\n", obex->port_num);
dev_dbg(&cdev->gadget->dev,
"reset obex ttyGS%d\n", obex->port_num);
gserial_disconnect(&obex->port);
}
if (!obex->port.in->desc || !obex->port.out->desc) {
DBG(cdev, "init obex ttyGS%d\n", obex->port_num);
dev_dbg(&cdev->gadget->dev,
"init obex ttyGS%d\n", obex->port_num);
if (config_ep_by_speed(cdev->gadget, f,
obex->port.in) ||
config_ep_by_speed(cdev->gadget, f,
......@@ -224,7 +227,8 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
}
if (alt == 1) {
DBG(cdev, "activate obex ttyGS%d\n", obex->port_num);
dev_dbg(&cdev->gadget->dev,
"activate obex ttyGS%d\n", obex->port_num);
gserial_connect(&obex->port, obex->port_num);
}
......@@ -252,7 +256,7 @@ static void obex_disable(struct usb_function *f)
struct f_obex *obex = func_to_obex(f);
struct usb_composite_dev *cdev = f->config->cdev;
DBG(cdev, "obex ttyGS%d disable\n", obex->port_num);
dev_dbg(&cdev->gadget->dev, "obex ttyGS%d disable\n", obex->port_num);
gserial_disconnect(&obex->port);
}
......@@ -269,7 +273,8 @@ static void obex_connect(struct gserial *g)
status = usb_function_activate(&g->func);
if (status)
DBG(cdev, "obex ttyGS%d function activate --> %d\n",
dev_dbg(&cdev->gadget->dev,
"obex ttyGS%d function activate --> %d\n",
obex->port_num, status);
}
......@@ -284,7 +289,8 @@ static void obex_disconnect(struct gserial *g)
status = usb_function_deactivate(&g->func);
if (status)
DBG(cdev, "obex ttyGS%d function deactivate --> %d\n",
dev_dbg(&cdev->gadget->dev,
"obex ttyGS%d function deactivate --> %d\n",
obex->port_num, status);
}
......@@ -383,10 +389,10 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
obex->can_activate = true;
DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
obex->port_num,
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
obex->port.in->name, obex->port.out->name);
dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
obex->port_num,
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
obex->port.in->name, obex->port.out->name);
return 0;
......
......@@ -155,11 +155,13 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0, so this is an activation or a reset */
if (gser->port.in->driver_data) {
DBG(cdev, "reset generic ttyGS%d\n", gser->port_num);
dev_dbg(&cdev->gadget->dev,
"reset generic ttyGS%d\n", gser->port_num);
gserial_disconnect(&gser->port);
}
if (!gser->port.in->desc || !gser->port.out->desc) {
DBG(cdev, "activate generic ttyGS%d\n", gser->port_num);
dev_dbg(&cdev->gadget->dev,
"activate generic ttyGS%d\n", gser->port_num);
if (config_ep_by_speed(cdev->gadget, f, gser->port.in) ||
config_ep_by_speed(cdev->gadget, f, gser->port.out)) {
gser->port.in->desc = NULL;
......@@ -176,7 +178,8 @@ static void gser_disable(struct usb_function *f)
struct f_gser *gser = func_to_gser(f);
struct usb_composite_dev *cdev = f->config->cdev;
DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num);
dev_dbg(&cdev->gadget->dev,
"generic ttyGS%d deactivated\n", gser->port_num);
gserial_disconnect(&gser->port);
}
......@@ -239,11 +242,11 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f)
gser_ss_function);
if (status)
goto fail;
DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
gser->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
gser->port.in->name, gser->port.out->name);
dev_dbg(&cdev->gadget->dev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
gser->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
gser->port.in->name, gser->port.out->name);
return 0;
fail:
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -16,12 +16,13 @@
#include <linux/usb/composite.h>
#include <linux/usb/video.h>
int uvc_bind_config(struct usb_configuration *c,
const struct uvc_descriptor_header * const *fs_control,
const struct uvc_descriptor_header * const *hs_control,
const struct uvc_descriptor_header * const *fs_streaming,
const struct uvc_descriptor_header * const *hs_streaming,
const struct uvc_descriptor_header * const *ss_streaming);
#include "uvc.h"
void uvc_function_setup_continue(struct uvc_device *uvc);
void uvc_function_connect(struct uvc_device *uvc);
void uvc_function_disconnect(struct uvc_device *uvc);
#endif /* _F_UVC_H_ */
......@@ -10,6 +10,8 @@
#define GZERO_QLEN 32
#define GZERO_ISOC_INTERVAL 4
#define GZERO_ISOC_MAXPACKET 1024
#define GZERO_INT_INTERVAL 1 /* Default interrupt interval = 1 ms */
#define GZERO_INT_MAXPACKET 1024
struct usb_zero_options {
unsigned pattern;
......@@ -17,6 +19,10 @@ struct usb_zero_options {
unsigned isoc_maxpacket;
unsigned isoc_mult;
unsigned isoc_maxburst;
unsigned int_interval; /* In ms */
unsigned int_maxpacket;
unsigned int_mult;
unsigned int_maxburst;
unsigned bulk_buflen;
unsigned qlen;
};
......@@ -28,6 +34,10 @@ struct f_ss_opts {
unsigned isoc_maxpacket;
unsigned isoc_mult;
unsigned isoc_maxburst;
unsigned int_interval; /* In ms */
unsigned int_maxpacket;
unsigned int_mult;
unsigned int_maxburst;
unsigned bulk_buflen;
/*
......@@ -62,6 +72,7 @@ int lb_modinit(void);
void free_ep_req(struct usb_ep *ep, struct usb_request *req);
void disable_endpoints(struct usb_composite_dev *cdev,
struct usb_ep *in, struct usb_ep *out,
struct usb_ep *iso_in, struct usb_ep *iso_out);
struct usb_ep *iso_in, struct usb_ep *iso_out,
struct usb_ep *int_in, struct usb_ep *int_out);
#endif /* __G_ZERO_H */
......@@ -224,6 +224,8 @@ struct ffs_data {
void *ms_os_descs_ext_prop_name_avail;
void *ms_os_descs_ext_prop_data_avail;
unsigned user_flags;
u8 eps_addrmap[15];
unsigned short strings_count;
......
......@@ -55,11 +55,8 @@
* for a telephone or fax link. And ttyGS2 might be something that just
* needs a simple byte stream interface for some messaging protocol that
* is managed in userspace ... OBEX, PTP, and MTP have been mentioned.
*/
#define PREFIX "ttyGS"
/*
*
*
* gserial is the lifecycle interface, used by USB functions
* gs_port is the I/O nexus, used by the tty driver
* tty_struct links to the tty/filesystem framework
......@@ -385,9 +382,9 @@ __acquires(&port->port_lock)
list_del(&req->list);
req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0);
pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
port->port_num, len, *((u8 *)req->buf),
*((u8 *)req->buf+1), *((u8 *)req->buf+2));
pr_vdebug("ttyGS%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
port->port_num, len, *((u8 *)req->buf),
*((u8 *)req->buf+1), *((u8 *)req->buf+2));
/* Drop lock while we call out of driver; completions
* could be issued while we do so. Disconnection may
......@@ -503,13 +500,13 @@ static void gs_rx_push(unsigned long _port)
switch (req->status) {
case -ESHUTDOWN:
disconnect = true;
pr_vdebug(PREFIX "%d: shutdown\n", port->port_num);
pr_vdebug("ttyGS%d: shutdown\n", port->port_num);
break;
default:
/* presumably a transient fault */
pr_warning(PREFIX "%d: unexpected RX status %d\n",
port->port_num, req->status);
pr_warn("ttyGS%d: unexpected RX status %d\n",
port->port_num, req->status);
/* FALLTHROUGH */
case 0:
/* normal completion */
......@@ -537,9 +534,8 @@ static void gs_rx_push(unsigned long _port)
if (count != size) {
/* stop pushing; TTY layer can't handle more */
port->n_read += count;
pr_vdebug(PREFIX "%d: rx block %d/%d\n",
port->port_num,
count, req->actual);
pr_vdebug("ttyGS%d: rx block %d/%d\n",
port->port_num, count, req->actual);
break;
}
port->n_read = 0;
......@@ -569,7 +565,7 @@ static void gs_rx_push(unsigned long _port)
if (do_push)
tasklet_schedule(&port->push);
else
pr_warning(PREFIX "%d: RX not scheduled?\n",
pr_warn("ttyGS%d: RX not scheduled?\n",
port->port_num);
}
}
......@@ -985,7 +981,7 @@ static void gs_unthrottle(struct tty_struct *tty)
* read queue backs up enough we'll be NAKing OUT packets.
*/
tasklet_schedule(&port->push);
pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num);
pr_vdebug("ttyGS%d: unthrottle\n", port->port_num);
}
spin_unlock_irqrestore(&port->port_lock, flags);
}
......@@ -1295,7 +1291,7 @@ static int userial_init(void)
return -ENOMEM;
gs_tty_driver->driver_name = "g_serial";
gs_tty_driver->name = PREFIX;
gs_tty_driver->name = "ttyGS";
/* uses dynamically assigned dev_t values */
gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
......
......@@ -10,6 +10,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/delay.h>
......@@ -23,22 +24,6 @@
* This component encapsulates the ALSA devices for USB audio gadget
*/
#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
#define FILE_CONTROL "/dev/snd/controlC0"
static char *fn_play = FILE_PCM_PLAYBACK;
module_param(fn_play, charp, S_IRUGO);
MODULE_PARM_DESC(fn_play, "Playback PCM device file name");
static char *fn_cap = FILE_PCM_CAPTURE;
module_param(fn_cap, charp, S_IRUGO);
MODULE_PARM_DESC(fn_cap, "Capture PCM device file name");
static char *fn_cntl = FILE_CONTROL;
module_param(fn_cntl, charp, S_IRUGO);
MODULE_PARM_DESC(fn_cntl, "Control device file name");
/*-------------------------------------------------------------------------*/
/**
......@@ -167,7 +152,7 @@ static int playback_default_hw_params(struct gaudio_snd_dev *snd)
/**
* Playback audio buffer data by ALSA PCM device
*/
static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
{
struct gaudio_snd_dev *snd = &card->playback;
struct snd_pcm_substream *substream = snd->substream;
......@@ -202,12 +187,12 @@ static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
return 0;
}
static int u_audio_get_playback_channels(struct gaudio *card)
int u_audio_get_playback_channels(struct gaudio *card)
{
return card->playback.channels;
}
static int u_audio_get_playback_rate(struct gaudio *card)
int u_audio_get_playback_rate(struct gaudio *card)
{
return card->playback.rate;
}
......@@ -220,6 +205,13 @@ static int gaudio_open_snd_dev(struct gaudio *card)
{
struct snd_pcm_file *pcm_file;
struct gaudio_snd_dev *snd;
struct f_uac1_opts *opts;
char *fn_play, *fn_cap, *fn_cntl;
opts = container_of(card->func.fi, struct f_uac1_opts, func_inst);
fn_play = opts->fn_play;
fn_cap = opts->fn_cap;
fn_cntl = opts->fn_cntl;
if (!card)
return -ENODEV;
......@@ -293,7 +285,6 @@ static int gaudio_close_snd_dev(struct gaudio *gau)
return 0;
}
static struct gaudio *the_card;
/**
* gaudio_setup - setup ALSA interface and preparing for USB transfer
*
......@@ -301,15 +292,13 @@ static struct gaudio *the_card;
*
* Returns negative errno, or zero on success
*/
int __init gaudio_setup(struct gaudio *card)
int gaudio_setup(struct gaudio *card)
{
int ret;
ret = gaudio_open_snd_dev(card);
if (ret)
ERROR(card, "we need at least one control device\n");
else if (!the_card)
the_card = card;
return ret;
......@@ -320,11 +309,10 @@ int __init gaudio_setup(struct gaudio *card)
*
* This is called to free all resources allocated by @gaudio_setup().
*/
void gaudio_cleanup(void)
void gaudio_cleanup(struct gaudio *the_card)
{
if (the_card) {
gaudio_close_snd_dev(the_card);
the_card = NULL;
}
}
......@@ -23,6 +23,14 @@
#include "gadget_chips.h"
#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
#define FILE_CONTROL "/dev/snd/controlC0"
#define UAC1_OUT_EP_MAX_PACKET_SIZE 200
#define UAC1_REQ_COUNT 256
#define UAC1_AUDIO_BUF_SIZE 48000
/*
* This represents the USB side of an audio card device, managed by a USB
* function which provides control and stream interfaces.
......@@ -50,7 +58,28 @@ struct gaudio {
/* TODO */
};
struct f_uac1_opts {
struct usb_function_instance func_inst;
int req_buf_size;
int req_count;
int audio_buf_size;
char *fn_play;
char *fn_cap;
char *fn_cntl;
unsigned bound:1;
unsigned fn_play_alloc:1;
unsigned fn_cap_alloc:1;
unsigned fn_cntl_alloc:1;
struct gaudio *card;
struct mutex lock;
int refcnt;
};
int gaudio_setup(struct gaudio *card);
void gaudio_cleanup(void);
void gaudio_cleanup(struct gaudio *the_card);
size_t u_audio_playback(struct gaudio *card, void *buf, size_t count);
int u_audio_get_playback_channels(struct gaudio *card);
int u_audio_get_playback_rate(struct gaudio *card);
#endif /* __U_AUDIO_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment