提交 e2987672 编写于 作者: L Linus Torvalds

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

Pull USB patches from Greg KH:
 "Here's the big pull request for the USB driver tree for 3.20-rc1.

  Nothing major happening here, just lots of gadget driver updates, new
  device ids, and a bunch of cleanups.

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

* tag 'usb-3.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (299 commits)
  usb: musb: fix device hotplug behind hub
  usb: dwc2: Fix a bug in reading the endpoint directions from reg.
  staging: emxx_udc: fix the build error
  usb: Retry port status check on resume to work around RH bugs
  Revert "usb: Reset USB-3 devices on USB-3 link bounce"
  uhci-hub: use HUB_CHAR_*
  usb: kconfig: replace PPC_OF with PPC
  ehci-pci: disable for Intel MID platforms (update)
  usb: gadget: Kconfig: use bool instead of boolean
  usb: musb: blackfin: remove incorrect __exit_p()
  USB: fix use-after-free bug in usb_hcd_unlink_urb()
  ehci-pci: disable for Intel MID platforms
  usb: host: pci_quirks: joing string literals
  USB: add flag for HCDs that can't receive wakeup requests (isp1760-hcd)
  USB: usbfs: allow URBs to be reaped after disconnection
  cdc-acm: kill unnecessary messages
  cdc-acm: add sanity checks
  usb: phy: phy-generic: Fix USB PHY gpio reset
  usb: dwc2: fix USB core dependencies
  usb: renesas_usbhs: fix NULL pointer dereference in dma_release_channel()
  ...
What: /config/usb-gadget/gadget/functions/uvc.name
Date: Dec 2014
KernelVersion: 3.20
Description: UVC function directory
streaming_maxburst - 0..15 (ss only)
streaming_maxpacket - 1..1023 (fs), 1..3072 (hs/ss)
streaming_interval - 1..16
What: /config/usb-gadget/gadget/functions/uvc.name/control
Date: Dec 2014
KernelVersion: 3.20
Description: Control descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/class
Date: Dec 2014
KernelVersion: 3.20
Description: Class descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/class/ss
Date: Dec 2014
KernelVersion: 3.20
Description: Super speed control class descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/class/fs
Date: Dec 2014
KernelVersion: 3.20
Description: Full speed control class descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/terminal
Date: Dec 2014
KernelVersion: 3.20
Description: Terminal descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/terminal/output
Date: Dec 2014
KernelVersion: 3.20
Description: Output terminal descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/terminal/output/default
Date: Dec 2014
KernelVersion: 3.20
Description: Default output terminal descriptors
All attributes read only:
iTerminal - index of string descriptor
bSourceID - id of the terminal to which this terminal
is connected
bAssocTerminal - id of the input terminal to which this output
terminal is associated
wTerminalType - terminal type
bTerminalID - a non-zero id of this terminal
What: /config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera
Date: Dec 2014
KernelVersion: 3.20
Description: Camera terminal descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera/default
Date: Dec 2014
KernelVersion: 3.20
Description: Default camera terminal descriptors
All attributes read only:
bmControls - bitmap specifying which controls are
supported for the video stream
wOcularFocalLength - the value of Locular
wObjectiveFocalLengthMax- the value of Lmin
wObjectiveFocalLengthMin- the value of Lmax
iTerminal - index of string descriptor
bAssocTerminal - id of the output terminal to which
this terminal is connected
wTerminalType - terminal type
bTerminalID - a non-zero id of this terminal
What: /config/usb-gadget/gadget/functions/uvc.name/control/processing
Date: Dec 2014
KernelVersion: 3.20
Description: Processing unit descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/processing/default
Date: Dec 2014
KernelVersion: 3.20
Description: Default processing unit descriptors
All attributes read only:
iProcessing - index of string descriptor
bmControls - bitmap specifying which controls are
supported for the video stream
wMaxMultiplier - maximum digital magnification x100
bSourceID - id of the terminal to which this unit is
connected
bUnitID - a non-zero id of this unit
What: /config/usb-gadget/gadget/functions/uvc.name/control/header
Date: Dec 2014
KernelVersion: 3.20
Description: Control header descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/control/header/name
Date: Dec 2014
KernelVersion: 3.20
Description: Specific control header descriptors
dwClockFrequency
bcdUVC
What: /config/usb-gadget/gadget/functions/uvc.name/streaming
Date: Dec 2014
KernelVersion: 3.20
Description: Streaming descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/class
Date: Dec 2014
KernelVersion: 3.20
Description: Streaming class descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/class/ss
Date: Dec 2014
KernelVersion: 3.20
Description: Super speed streaming class descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/class/hs
Date: Dec 2014
KernelVersion: 3.20
Description: High speed streaming class descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/class/fs
Date: Dec 2014
KernelVersion: 3.20
Description: Full speed streaming class descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/color_matching
Date: Dec 2014
KernelVersion: 3.20
Description: Color matching descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/color_matching/default
Date: Dec 2014
KernelVersion: 3.20
Description: Default color matching descriptors
All attributes read only:
bMatrixCoefficients - matrix used to compute luma and
chroma values from the color primaries
bTransferCharacteristics- optoelectronic transfer
characteristic of the source picutre,
also called the gamma function
bColorPrimaries - color primaries and the reference
white
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg
Date: Dec 2014
KernelVersion: 3.20
Description: MJPEG format descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name
Date: Dec 2014
KernelVersion: 3.20
Description: Specific MJPEG format descriptors
All attributes read only,
except bmaControls and bDefaultFrameIndex:
bmaControls - this format's data for bmaControls in
the streaming header
bmInterfaceFlags - specifies interlace information,
read-only
bAspectRatioY - the X dimension of the picture aspect
ratio, read-only
bAspectRatioX - the Y dimension of the picture aspect
ratio, read-only
bmFlags - characteristics of this format,
read-only
bDefaultFrameIndex - optimum frame index for this stream
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name/name
Date: Dec 2014
KernelVersion: 3.20
Description: Specific MJPEG frame descriptors
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
dwDefaultFrameInterval - the frame interval the device would
like to use as default
dwMaxVideoFrameBufferSize- the maximum number of bytes the
compressor will produce for a video
frame or still image
dwMaxBitRate - the maximum bit rate at the shortest
frame interval in bps
dwMinBitRate - the minimum bit rate at the longest
frame interval in bps
wHeight - height of decoded bitmap frame in px
wWidth - width of decoded bitmam frame in px
bmCapabilities - still image support, fixed frame-rate
support
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed
Date: Dec 2014
KernelVersion: 3.20
Description: Uncompressed format descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name
Date: Dec 2014
KernelVersion: 3.20
Description: Specific uncompressed format descriptors
bmaControls - this format's data for bmaControls in
the streaming header
bmInterfaceFlags - specifies interlace information,
read-only
bAspectRatioY - the X dimension of the picture aspect
ratio, read-only
bAspectRatioX - the Y dimension of the picture aspect
ratio, read-only
bDefaultFrameIndex - optimum frame index for this stream
bBitsPerPixel - number of bits per pixel used to
specify color in the decoded video
frame
guidFormat - globally unique id used to identify
stream-encoding format
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name/name
Date: Dec 2014
KernelVersion: 3.20
Description: Specific uncompressed frame descriptors
dwFrameInterval - indicates how frame interval can be
programmed; a number of values
separated by newline can be specified
dwDefaultFrameInterval - the frame interval the device would
like to use as default
dwMaxVideoFrameBufferSize- the maximum number of bytes the
compressor will produce for a video
frame or still image
dwMaxBitRate - the maximum bit rate at the shortest
frame interval in bps
dwMinBitRate - the minimum bit rate at the longest
frame interval in bps
wHeight - height of decoded bitmap frame in px
wWidth - width of decoded bitmam frame in px
bmCapabilities - still image support, fixed frame-rate
support
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/header
Date: Dec 2014
KernelVersion: 3.20
Description: Streaming header descriptors
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/header/name
Date: Dec 2014
KernelVersion: 3.20
Description: Specific streaming header descriptors
All attributes read only:
bTriggerUsage - how the host software will respond to
a hardware trigger interrupt event
bTriggerSupport - flag specifying if hardware
triggering is supported
bStillCaptureMethod - method of still image caputre
supported
bTerminalLink - id of the output terminal to which
the video endpoint of this interface
is connected
bmInfo - capabilities of this video streaming
interface
......@@ -26,6 +26,7 @@ Required properties (port (child) node):
filled in "reg". It can also contain the offset of the system configuration
registers used as glue-logic to setup the device for SATA/PCIe or USB3
devices.
- st,syscfg : Offset of the parent configuration register.
- resets : phandle to the parent reset controller.
- reset-names : Associated name must be "miphy-sw-rst".
......@@ -54,18 +55,12 @@ example:
phy_port0: port@9b22000 {
reg = <0x9b22000 0xff>,
<0x9b09000 0xff>,
<0x9b04000 0xff>,
<0x114 0x4>, /* sysctrl MiPHY cntrl */
<0x818 0x4>, /* sysctrl MiPHY status*/
<0xe0 0x4>, /* sysctrl PCIe */
<0xec 0x4>; /* sysctrl SATA */
<0x9b04000 0xff>;
reg-names = "sata-up",
"pcie-up",
"pipew",
"miphy-ctrl-glue",
"miphy-status-glue",
"pcie-glue",
"sata-glue";
"pipew";
st,syscfg = <0x114 0x818 0xe0 0xec>;
#phy-cells = <1>;
st,osc-rdy;
reset-names = "miphy-sw-rst";
......@@ -75,18 +70,13 @@ example:
phy_port1: port@9b2a000 {
reg = <0x9b2a000 0xff>,
<0x9b19000 0xff>,
<0x9b14000 0xff>,
<0x118 0x4>,
<0x81c 0x4>,
<0xe4 0x4>,
<0xf0 0x4>;
<0x9b14000 0xff>;
reg-names = "sata-up",
"pcie-up",
"pipew",
"miphy-ctrl-glue",
"miphy-status-glue",
"pcie-glue",
"sata-glue";
"pipew";
st,syscfg = <0x118 0x81c 0xe4 0xf0>;
#phy-cells = <1>;
st,osc-force-ext;
reset-names = "miphy-sw-rst";
......@@ -95,13 +85,12 @@ example:
phy_port2: port@8f95000 {
reg = <0x8f95000 0xff>,
<0x8f90000 0xff>,
<0x11c 0x4>,
<0x820 0x4>;
<0x8f90000 0xff>;
reg-names = "pipew",
"usb3-up",
"miphy-ctrl-glue",
"miphy-status-glue";
"usb3-up";
st,syscfg = <0x11c 0x820>;
#phy-cells = <1>;
reset-names = "miphy-sw-rst";
resets = <&softreset STIH407_MIPHY2_SOFTRESET>;
......@@ -125,4 +114,4 @@ example:
Macro definitions for the supported miphy configuration can be found in:
include/dt-bindings/phy/phy-miphy28lp.h
include/dt-bindings/phy/phy.h
ROCKCHIP USB2 PHY
Required properties:
- compatible: rockchip,rk3288-usb-phy
- rockchip,grf : phandle to the syscon managing the "general
register files"
- #address-cells: should be 1
- #size-cells: should be 0
Sub-nodes:
Each PHY should be represented as a sub-node.
Sub-nodes
required properties:
- #phy-cells: should be 0
- reg: PHY configure reg address offset in GRF
"0x320" - for PHY attach to OTG controller
"0x334" - for PHY attach to HOST0 controller
"0x348" - for PHY attach to HOST1 controller
Optional Properties:
- clocks : phandle + clock specifier for the phy clocks
- clock-names: string, clock name, must be "phyclk"
Example:
usbphy: phy {
compatible = "rockchip,rk3288-usb-phy";
rockchip,grf = <&grf>;
#address-cells = <1>;
#size-cells = <0>;
usbphy0: usb-phy0 {
#phy-cells = <0>;
reg = <0x320>;
};
};
......@@ -3,8 +3,8 @@ Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY
Required properties:
- compatible : should be "samsung,s5pv210-mipi-video-phy";
- reg : offset and length of the MIPI DPHY register set;
- #phy-cells : from the generic phy bindings, must be 1;
- syscon - phandle to the PMU system controller;
For "samsung,s5pv210-mipi-video-phy" compatible PHYs the second cell in
the PHY specifier identifies the PHY and its meaning is as follows:
......
......@@ -51,7 +51,10 @@ usb1: gadget@fffa4000 {
Atmel High-Speed USB device controller
Required properties:
- compatible: Should be "atmel,at91sam9rl-udc"
- compatible: Should be one of the following
"at91sam9rl-udc"
"at91sam9g45-udc"
"sama5d3-udc"
- reg: Address and length of the register set for the device
- interrupts: Should contain usba interrupt
- ep childnode: To specify the number of endpoints and their properties.
......
......@@ -20,6 +20,10 @@ Optional properties:
Refer to phy/phy-bindings.txt for generic phy consumer properties
- dr_mode: shall be one of "host", "peripheral" and "otg"
Refer to usb/generic.txt
- g-use-dma: enable dma usage in gadget driver.
- g-rx-fifo-size: size of rx fifo size in gadget mode.
- g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
Example:
......
......@@ -14,6 +14,8 @@ Optional properties:
function should be enabled
- phys: phandle + phy specifier pair
- phy-names: must be "usb"
- dmas: Must contain a list of references to DMA specifiers.
- dma-names : Must contain a list of DMA names, "tx" or "rx".
Example:
usbhs: usb@e6590000 {
......
......@@ -12,6 +12,7 @@ Optional properties:
- big-endian-regs : boolean, set this for hcds with big-endian registers
- big-endian-desc : boolean, set this for hcds with big-endian descriptors
- big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
- needs-reset-on-resume : boolean, set this to force EHCI reset after resume
- clocks : a list of phandle + clock specifier pairs
- phys : phandle + phy specifier pair
- phy-names : "usb"
......
......@@ -13,10 +13,15 @@ Optional properties:
- clock-frequency: the clock frequency (in Hz) that the PHY clock must
be configured to.
- vcc-supply: phandle to the regulator that provides RESET to the PHY.
- vcc-supply: phandle to the regulator that provides power to the PHY.
- reset-gpios: Should specify the GPIO for reset.
- vbus-detect-gpio: should specify the GPIO detecting a VBus insertion
(see Documentation/devicetree/bindings/gpio/gpio.txt)
- vbus-regulator : should specifiy the regulator supplying current drawn from
the VBus line (see Documentation/devicetree/bindings/regulator/regulator.txt).
Example:
hsusb1_phy {
......@@ -26,8 +31,11 @@ Example:
clock-names = "main_clk";
vcc-supply = <&hsusb1_vcc_regulator>;
reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
vbus-detect-gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>;
vbus-regulator = <&vbus_regulator>;
};
hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator
and expects that clock to be configured to 19.2MHz by the NOP PHY driver.
hsusb1_vcc_regulator provides power to the PHY and GPIO 7 controls RESET.
GPIO 13 detects VBus insertion, and accordingly notifies the vbus-regulator.
此差异已折叠。
......@@ -236,8 +236,12 @@ I: If#= 0 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=serial
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
You must explicitly load the usbserial driver with parameters to
configure it to recognize the gadget serial device, like this:
You must load the usbserial driver and explicitly set its parameters
to configure it to recognize the gadget serial device, like this:
echo 0x0525 0xA4A6 >/sys/bus/usb-serial/drivers/generic/new_id
The legacy way is to use module parameters:
modprobe usbserial vendor=0x0525 product=0xA4A6
......
......@@ -72,7 +72,7 @@ to listen on a single bus, otherwise, to listen on all buses, type:
# cat /sys/kernel/debug/usb/usbmon/0u > /tmp/1.mon.out
This process will be reading until killed. Naturally, the output can be
This process will read until it is killed. Naturally, the output can be
redirected to a desirable location. This is preferred, because it is going
to be quite long.
......
......@@ -3048,7 +3048,7 @@ S: Maintained
F: drivers/platform/x86/dell-wmi.c
DESIGNWARE USB2 DRD IP DRIVER
M: Paul Zimmerman <paulz@synopsys.com>
M: John Youn <johnyoun@synopsys.com>
L: linux-usb@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
......
......@@ -77,7 +77,7 @@ static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
static int octeon2_usb_clock_start_cnt;
static void octeon2_usb_clocks_start(void)
static void octeon2_usb_clocks_start(struct device *dev)
{
u64 div;
union cvmx_uctlx_if_ena if_ena;
......@@ -86,6 +86,8 @@ static void octeon2_usb_clocks_start(void)
union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
int i;
unsigned long io_clk_64_to_ns;
u32 clock_rate = 12000000;
bool is_crystal_clock = false;
mutex_lock(&octeon2_usb_clocks_mutex);
......@@ -96,6 +98,28 @@ static void octeon2_usb_clocks_start(void)
io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate();
if (dev->of_node) {
struct device_node *uctl_node;
const char *clock_type;
uctl_node = of_get_parent(dev->of_node);
if (!uctl_node) {
dev_err(dev, "No UCTL device node\n");
goto exit;
}
i = of_property_read_u32(uctl_node,
"refclk-frequency", &clock_rate);
if (i) {
dev_err(dev, "No UCTL \"refclk-frequency\"\n");
goto exit;
}
i = of_property_read_string(uctl_node,
"refclk-type", &clock_type);
if (!i && strcmp("crystal", clock_type) == 0)
is_crystal_clock = true;
}
/*
* Step 1: Wait for voltages stable. That surely happened
* before starting the kernel.
......@@ -126,9 +150,22 @@ static void octeon2_usb_clocks_start(void)
cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
/* 3b */
/* 12MHz crystal. */
clk_rst_ctl.s.p_refclk_sel = 0;
clk_rst_ctl.s.p_refclk_div = 0;
clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1;
switch (clock_rate) {
default:
pr_err("Invalid UCTL clock rate of %u, using 12000000 instead\n",
clock_rate);
/* Fall through */
case 12000000:
clk_rst_ctl.s.p_refclk_div = 0;
break;
case 24000000:
clk_rst_ctl.s.p_refclk_div = 1;
break;
case 48000000:
clk_rst_ctl.s.p_refclk_div = 2;
break;
}
cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
/* 3c */
......@@ -259,7 +296,7 @@ static void octeon2_usb_clocks_stop(void)
static int octeon_ehci_power_on(struct platform_device *pdev)
{
octeon2_usb_clocks_start();
octeon2_usb_clocks_start(&pdev->dev);
return 0;
}
......@@ -273,15 +310,16 @@ static struct usb_ehci_pdata octeon_ehci_pdata = {
#ifdef __BIG_ENDIAN
.big_endian_mmio = 1,
#endif
.dma_mask_64 = 1,
.power_on = octeon_ehci_power_on,
.power_off = octeon_ehci_power_off,
};
static void __init octeon_ehci_hw_start(void)
static void __init octeon_ehci_hw_start(struct device *dev)
{
union cvmx_uctlx_ehci_ctl ehci_ctl;
octeon2_usb_clocks_start();
octeon2_usb_clocks_start(dev);
ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
/* Use 64-bit addressing. */
......@@ -294,64 +332,30 @@ static void __init octeon_ehci_hw_start(void)
octeon2_usb_clocks_stop();
}
static u64 octeon_ehci_dma_mask = DMA_BIT_MASK(64);
static int __init octeon_ehci_device_init(void)
{
struct platform_device *pd;
struct device_node *ehci_node;
int ret = 0;
struct resource usb_resources[] = {
{
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_IRQ,
}
};
/* Only Octeon2 has ehci/ohci */
if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
ehci_node = of_find_node_by_name(NULL, "ehci");
if (!ehci_node)
return 0;
if (octeon_is_simulation() || usb_disabled())
return 0; /* No USB in the simulator. */
pd = platform_device_alloc("ehci-platform", 0);
if (!pd) {
ret = -ENOMEM;
goto out;
}
usb_resources[0].start = 0x00016F0000000000ULL;
usb_resources[0].end = usb_resources[0].start + 0x100;
usb_resources[1].start = OCTEON_IRQ_USB0;
usb_resources[1].end = OCTEON_IRQ_USB0;
ret = platform_device_add_resources(pd, usb_resources,
ARRAY_SIZE(usb_resources));
if (ret)
goto fail;
pd = of_find_device_by_node(ehci_node);
if (!pd)
return 0;
pd->dev.dma_mask = &octeon_ehci_dma_mask;
pd->dev.platform_data = &octeon_ehci_pdata;
octeon_ehci_hw_start();
octeon_ehci_hw_start(&pd->dev);
ret = platform_device_add(pd);
if (ret)
goto fail;
return ret;
fail:
platform_device_put(pd);
out:
return ret;
}
device_initcall(octeon_ehci_device_init);
static int octeon_ohci_power_on(struct platform_device *pdev)
{
octeon2_usb_clocks_start();
octeon2_usb_clocks_start(&pdev->dev);
return 0;
}
......@@ -369,11 +373,11 @@ static struct usb_ohci_pdata octeon_ohci_pdata = {
.power_off = octeon_ohci_power_off,
};
static void __init octeon_ohci_hw_start(void)
static void __init octeon_ohci_hw_start(struct device *dev)
{
union cvmx_uctlx_ohci_ctl ohci_ctl;
octeon2_usb_clocks_start();
octeon2_usb_clocks_start(dev);
ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0));
ohci_ctl.s.l2c_addr_msb = 0;
......@@ -387,57 +391,27 @@ static void __init octeon_ohci_hw_start(void)
static int __init octeon_ohci_device_init(void)
{
struct platform_device *pd;
struct device_node *ohci_node;
int ret = 0;
struct resource usb_resources[] = {
{
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_IRQ,
}
};
/* Only Octeon2 has ehci/ohci */
if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
ohci_node = of_find_node_by_name(NULL, "ohci");
if (!ohci_node)
return 0;
if (octeon_is_simulation() || usb_disabled())
return 0; /* No USB in the simulator. */
pd = platform_device_alloc("ohci-platform", 0);
if (!pd) {
ret = -ENOMEM;
goto out;
}
usb_resources[0].start = 0x00016F0000000400ULL;
usb_resources[0].end = usb_resources[0].start + 0x100;
usb_resources[1].start = OCTEON_IRQ_USB0;
usb_resources[1].end = OCTEON_IRQ_USB0;
ret = platform_device_add_resources(pd, usb_resources,
ARRAY_SIZE(usb_resources));
if (ret)
goto fail;
pd = of_find_device_by_node(ohci_node);
if (!pd)
return 0;
pd->dev.platform_data = &octeon_ohci_pdata;
octeon_ohci_hw_start();
ret = platform_device_add(pd);
if (ret)
goto fail;
octeon_ohci_hw_start(&pd->dev);
return ret;
fail:
platform_device_put(pd);
out:
return ret;
}
device_initcall(octeon_ohci_device_init);
#endif /* CONFIG_USB */
static struct of_device_id __initdata octeon_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "cavium,octeon-6335-uctl", },
......
......@@ -239,6 +239,13 @@ config PHY_QCOM_IPQ806X_SATA
depends on OF
select GENERIC_PHY
config PHY_ROCKCHIP_USB
tristate "Rockchip USB2 PHY Driver"
depends on ARCH_ROCKCHIP && OF
select GENERIC_PHY
help
Enable this to support the Rockchip USB 2.0 PHY.
config PHY_ST_SPEAR1310_MIPHY
tristate "ST SPEAR1310-MIPHY driver"
select GENERIC_PHY
......
......@@ -28,6 +28,7 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
......
......@@ -118,8 +118,8 @@ static int armada375_usb_phy_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
usb_cluster_base = devm_ioremap_resource(&pdev->dev, res);
if (!usb_cluster_base)
return -ENOMEM;
if (IS_ERR(usb_cluster_base))
return PTR_ERR(usb_cluster_base);
phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops);
if (IS_ERR(phy)) {
......
......@@ -12,19 +12,18 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon/exynos4-pmu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
#include <linux/mfd/syscon.h>
/* MIPI_PHYn_CONTROL register offset: n = 0..1 */
/* MIPI_PHYn_CONTROL reg. offset (for base address from ioremap): n = 0..1 */
#define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4)
#define EXYNOS_MIPI_PHY_ENABLE (1 << 0)
#define EXYNOS_MIPI_PHY_SRESETN (1 << 1)
#define EXYNOS_MIPI_PHY_MRESETN (1 << 2)
#define EXYNOS_MIPI_PHY_RESET_MASK (3 << 1)
enum exynos_mipi_phy_id {
EXYNOS_MIPI_PHY_ID_CSIS0,
......@@ -38,43 +37,62 @@ enum exynos_mipi_phy_id {
((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1)
struct exynos_mipi_video_phy {
spinlock_t slock;
struct video_phy_desc {
struct phy *phy;
unsigned int index;
} phys[EXYNOS_MIPI_PHYS_NUM];
spinlock_t slock;
void __iomem *regs;
struct mutex mutex;
struct regmap *regmap;
};
static int __set_phy_state(struct exynos_mipi_video_phy *state,
enum exynos_mipi_phy_id id, unsigned int on)
{
const unsigned int offset = EXYNOS4_MIPI_PHY_CONTROL(id / 2);
void __iomem *addr;
u32 reg, reset;
addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2);
u32 val, reset;
if (is_mipi_dsim_phy_id(id))
reset = EXYNOS_MIPI_PHY_MRESETN;
else
reset = EXYNOS_MIPI_PHY_SRESETN;
spin_lock(&state->slock);
reg = readl(addr);
if (on)
reg |= reset;
reset = EXYNOS4_MIPI_PHY_MRESETN;
else
reg &= ~reset;
writel(reg, addr);
/* Clear ENABLE bit only if MRESETN, SRESETN bits are not set. */
if (on)
reg |= EXYNOS_MIPI_PHY_ENABLE;
else if (!(reg & EXYNOS_MIPI_PHY_RESET_MASK))
reg &= ~EXYNOS_MIPI_PHY_ENABLE;
reset = EXYNOS4_MIPI_PHY_SRESETN;
if (state->regmap) {
mutex_lock(&state->mutex);
regmap_read(state->regmap, offset, &val);
if (on)
val |= reset;
else
val &= ~reset;
regmap_write(state->regmap, offset, val);
if (on)
val |= EXYNOS4_MIPI_PHY_ENABLE;
else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK))
val &= ~EXYNOS4_MIPI_PHY_ENABLE;
regmap_write(state->regmap, offset, val);
mutex_unlock(&state->mutex);
} else {
addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2);
spin_lock(&state->slock);
val = readl(addr);
if (on)
val |= reset;
else
val &= ~reset;
writel(val, addr);
/* Clear ENABLE bit only if MRESETN, SRESETN bits are not set */
if (on)
val |= EXYNOS4_MIPI_PHY_ENABLE;
else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK))
val &= ~EXYNOS4_MIPI_PHY_ENABLE;
writel(val, addr);
spin_unlock(&state->slock);
}
writel(reg, addr);
spin_unlock(&state->slock);
return 0;
}
......@@ -118,7 +136,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
{
struct exynos_mipi_video_phy *state;
struct device *dev = &pdev->dev;
struct resource *res;
struct phy_provider *phy_provider;
unsigned int i;
......@@ -126,14 +143,22 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
if (!state)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
state->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
if (IS_ERR(state->regmap)) {
struct resource *res;
state->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(state->regs))
return PTR_ERR(state->regs);
dev_info(dev, "regmap lookup failed: %ld\n",
PTR_ERR(state->regmap));
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
state->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(state->regs))
return PTR_ERR(state->regs);
}
dev_set_drvdata(dev, state);
spin_lock_init(&state->slock);
mutex_init(&state->mutex);
for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
struct phy *phy = devm_phy_create(dev, NULL,
......
......@@ -194,6 +194,14 @@
#define MIPHY_SATA_BANK_NB 3
#define MIPHY_PCIE_BANK_NB 2
enum {
SYSCFG_CTRL,
SYSCFG_STATUS,
SYSCFG_PCI,
SYSCFG_SATA,
SYSCFG_REG_MAX,
};
struct miphy28lp_phy {
struct phy *phy;
struct miphy28lp_dev *phydev;
......@@ -211,10 +219,7 @@ struct miphy28lp_phy {
u32 sata_gen;
/* Sysconfig registers offsets needed to configure the device */
u32 syscfg_miphy_ctrl;
u32 syscfg_miphy_status;
u32 syscfg_pci;
u32 syscfg_sata;
u32 syscfg_reg[SYSCFG_REG_MAX];
u8 type;
};
......@@ -834,12 +839,12 @@ static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
if (!miphy_phy->osc_rdy)
return 0;
if (!miphy_phy->syscfg_miphy_status)
if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])
return -EINVAL;
do {
regmap_read(miphy_dev->regmap, miphy_phy->syscfg_miphy_status,
&val);
regmap_read(miphy_dev->regmap,
miphy_phy->syscfg_reg[SYSCFG_STATUS], &val);
if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
cpu_relax();
......@@ -888,7 +893,7 @@ static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)
int err;
struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
if (!miphy_phy->syscfg_miphy_ctrl)
if (!miphy_phy->syscfg_reg[SYSCFG_CTRL])
return -EINVAL;
err = reset_control_assert(miphy_phy->miphy_rst);
......@@ -900,7 +905,8 @@ static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)
if (miphy_phy->osc_force_ext)
miphy_val |= MIPHY_OSC_FORCE_EXT;
regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_miphy_ctrl,
regmap_update_bits(miphy_dev->regmap,
miphy_phy->syscfg_reg[SYSCFG_CTRL],
MIPHY_CTRL_MASK, miphy_val);
err = reset_control_deassert(miphy_phy->miphy_rst);
......@@ -917,8 +923,9 @@ static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)
struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
int err, sata_conf = SATA_CTRL_SELECT_SATA;
if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci)
|| (!miphy_phy->base))
if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||
(!miphy_phy->syscfg_reg[SYSCFG_PCI]) ||
(!miphy_phy->base))
return -EINVAL;
dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base);
......@@ -926,10 +933,11 @@ static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)
/* Configure the glue-logic */
sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE);
regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata,
regmap_update_bits(miphy_dev->regmap,
miphy_phy->syscfg_reg[SYSCFG_SATA],
SATA_CTRL_MASK, sata_conf);
regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci,
regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],
PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
/* MiPHY path and clocking init */
......@@ -951,17 +959,19 @@ static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy)
struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
int err;
if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci)
if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||
(!miphy_phy->syscfg_reg[SYSCFG_PCI])
|| (!miphy_phy->base) || (!miphy_phy->pipebase))
return -EINVAL;
dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base);
/* Configure the glue-logic */
regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata,
regmap_update_bits(miphy_dev->regmap,
miphy_phy->syscfg_reg[SYSCFG_SATA],
SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci,
regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],
PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL);
/* MiPHY path and clocking init */
......@@ -1156,7 +1166,8 @@ static int miphy28lp_probe_resets(struct device_node *node,
static int miphy28lp_of_probe(struct device_node *np,
struct miphy28lp_phy *miphy_phy)
{
struct resource res;
int i;
u32 ctrlreg;
miphy_phy->osc_force_ext =
of_property_read_bool(np, "st,osc-force-ext");
......@@ -1175,18 +1186,10 @@ static int miphy28lp_of_probe(struct device_node *np,
if (!miphy_phy->sata_gen)
miphy_phy->sata_gen = SATA_GEN1;
if (!miphy28lp_get_resource_byname(np, "miphy-ctrl-glue", &res))
miphy_phy->syscfg_miphy_ctrl = res.start;
if (!miphy28lp_get_resource_byname(np, "miphy-status-glue", &res))
miphy_phy->syscfg_miphy_status = res.start;
if (!miphy28lp_get_resource_byname(np, "pcie-glue", &res))
miphy_phy->syscfg_pci = res.start;
if (!miphy28lp_get_resource_byname(np, "sata-glue", &res))
miphy_phy->syscfg_sata = res.start;
for (i = 0; i < SYSCFG_REG_MAX; i++) {
if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg))
miphy_phy->syscfg_reg[i] = ctrlreg;
}
return 0;
}
......
/*
* Rockchip usb PHY driver
*
* Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com>
* Copyright (C) 2014 ROCKCHIP, Inc.
*
* 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; either version 2 of the License.
*
* 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/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
/*
* The higher 16-bit of this register is used for write protection
* only if BIT(13 + 16) set to 1 the BIT(13) can be written.
*/
#define SIDDQ_WRITE_ENA BIT(29)
#define SIDDQ_ON BIT(13)
#define SIDDQ_OFF (0 << 13)
struct rockchip_usb_phy {
unsigned int reg_offset;
struct regmap *reg_base;
struct clk *clk;
struct phy *phy;
};
static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
bool siddq)
{
return regmap_write(phy->reg_base, phy->reg_offset,
SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
}
static int rockchip_usb_phy_power_off(struct phy *_phy)
{
struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
int ret = 0;
/* Power down usb phy analog blocks by set siddq 1 */
ret = rockchip_usb_phy_power(phy, 1);
if (ret)
return ret;
clk_disable_unprepare(phy->clk);
if (ret)
return ret;
return 0;
}
static int rockchip_usb_phy_power_on(struct phy *_phy)
{
struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
int ret = 0;
ret = clk_prepare_enable(phy->clk);
if (ret)
return ret;
/* Power up usb phy analog blocks by set siddq 0 */
ret = rockchip_usb_phy_power(phy, 0);
if (ret)
return ret;
return 0;
}
static struct phy_ops ops = {
.power_on = rockchip_usb_phy_power_on,
.power_off = rockchip_usb_phy_power_off,
.owner = THIS_MODULE,
};
static int rockchip_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rockchip_usb_phy *rk_phy;
struct phy_provider *phy_provider;
struct device_node *child;
struct regmap *grf;
unsigned int reg_offset;
grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
if (IS_ERR(grf)) {
dev_err(&pdev->dev, "Missing rockchip,grf property\n");
return PTR_ERR(grf);
}
for_each_available_child_of_node(dev->of_node, child) {
rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
if (!rk_phy)
return -ENOMEM;
if (of_property_read_u32(child, "reg", &reg_offset)) {
dev_err(dev, "missing reg property in node %s\n",
child->name);
return -EINVAL;
}
rk_phy->reg_offset = reg_offset;
rk_phy->reg_base = grf;
rk_phy->clk = of_clk_get_by_name(child, "phyclk");
if (IS_ERR(rk_phy->clk))
rk_phy->clk = NULL;
rk_phy->phy = devm_phy_create(dev, child, &ops);
if (IS_ERR(rk_phy->phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(rk_phy->phy);
}
phy_set_drvdata(rk_phy->phy, rk_phy);
}
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
{ .compatible = "rockchip,rk3288-usb-phy" },
{}
};
MODULE_DEVICE_TABLE(of, rockchip_usb_phy_dt_ids);
static struct platform_driver rockchip_usb_driver = {
.probe = rockchip_usb_phy_probe,
.driver = {
.name = "rockchip-usb-phy",
.owner = THIS_MODULE,
.of_match_table = rockchip_usb_phy_dt_ids,
},
};
module_platform_driver(rockchip_usb_driver);
MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
MODULE_LICENSE("GPL v2");
......@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/phy/omap_control_phy.h>
#include <linux/of_platform.h>
#include <linux/spinlock.h>
#define PLL_STATUS 0x00000004
#define PLL_GO 0x00000008
......@@ -82,6 +83,10 @@ struct ti_pipe3 {
struct clk *refclk;
struct clk *div_clk;
struct pipe3_dpll_map *dpll_map;
bool enabled;
spinlock_t lock; /* serialize clock enable/disable */
/* the below flag is needed specifically for SATA */
bool refclk_enabled;
};
static struct pipe3_dpll_map dpll_map_usb[] = {
......@@ -307,6 +312,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
return -ENOMEM;
phy->dev = &pdev->dev;
spin_lock_init(&phy->lock);
if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
match = of_match_device(of_match_ptr(ti_pipe3_id_table),
......@@ -333,21 +339,24 @@ static int ti_pipe3_probe(struct platform_device *pdev)
}
}
phy->refclk = devm_clk_get(phy->dev, "refclk");
if (IS_ERR(phy->refclk)) {
dev_err(&pdev->dev, "unable to get refclk\n");
/* older DTBs have missing refclk in SATA PHY
* so don't bail out in case of SATA PHY.
*/
if (!of_device_is_compatible(node, "ti,phy-pipe3-sata"))
return PTR_ERR(phy->refclk);
}
if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
if (IS_ERR(phy->wkupclk)) {
dev_err(&pdev->dev, "unable to get wkupclk\n");
return PTR_ERR(phy->wkupclk);
}
phy->refclk = devm_clk_get(phy->dev, "refclk");
if (IS_ERR(phy->refclk)) {
dev_err(&pdev->dev, "unable to get refclk\n");
return PTR_ERR(phy->refclk);
}
} else {
phy->wkupclk = ERR_PTR(-ENODEV);
phy->refclk = ERR_PTR(-ENODEV);
}
if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
......@@ -426,33 +435,42 @@ static int ti_pipe3_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
static int ti_pipe3_runtime_suspend(struct device *dev)
static int ti_pipe3_enable_refclk(struct ti_pipe3 *phy)
{
struct ti_pipe3 *phy = dev_get_drvdata(dev);
if (!IS_ERR(phy->refclk) && !phy->refclk_enabled) {
int ret;
if (!IS_ERR(phy->wkupclk))
clk_disable_unprepare(phy->wkupclk);
ret = clk_prepare_enable(phy->refclk);
if (ret) {
dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
return ret;
}
phy->refclk_enabled = true;
}
return 0;
}
static void ti_pipe3_disable_refclk(struct ti_pipe3 *phy)
{
if (!IS_ERR(phy->refclk))
clk_disable_unprepare(phy->refclk);
if (!IS_ERR(phy->div_clk))
clk_disable_unprepare(phy->div_clk);
return 0;
phy->refclk_enabled = false;
}
static int ti_pipe3_runtime_resume(struct device *dev)
static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
{
u32 ret = 0;
struct ti_pipe3 *phy = dev_get_drvdata(dev);
int ret = 0;
unsigned long flags;
if (!IS_ERR(phy->refclk)) {
ret = clk_prepare_enable(phy->refclk);
if (ret) {
dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
goto err1;
}
}
spin_lock_irqsave(&phy->lock, flags);
if (phy->enabled)
goto err1;
ret = ti_pipe3_enable_refclk(phy);
if (ret)
goto err1;
if (!IS_ERR(phy->wkupclk)) {
ret = clk_prepare_enable(phy->wkupclk);
......@@ -469,6 +487,9 @@ static int ti_pipe3_runtime_resume(struct device *dev)
goto err3;
}
}
phy->enabled = true;
spin_unlock_irqrestore(&phy->lock, flags);
return 0;
err3:
......@@ -479,20 +500,80 @@ static int ti_pipe3_runtime_resume(struct device *dev)
if (!IS_ERR(phy->refclk))
clk_disable_unprepare(phy->refclk);
ti_pipe3_disable_refclk(phy);
err1:
spin_unlock_irqrestore(&phy->lock, flags);
return ret;
}
static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy)
{
unsigned long flags;
spin_lock_irqsave(&phy->lock, flags);
if (!phy->enabled) {
spin_unlock_irqrestore(&phy->lock, flags);
return;
}
if (!IS_ERR(phy->wkupclk))
clk_disable_unprepare(phy->wkupclk);
/* Don't disable refclk for SATA PHY due to Errata i783 */
if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
ti_pipe3_disable_refclk(phy);
if (!IS_ERR(phy->div_clk))
clk_disable_unprepare(phy->div_clk);
phy->enabled = false;
spin_unlock_irqrestore(&phy->lock, flags);
}
static int ti_pipe3_runtime_suspend(struct device *dev)
{
struct ti_pipe3 *phy = dev_get_drvdata(dev);
ti_pipe3_disable_clocks(phy);
return 0;
}
static int ti_pipe3_runtime_resume(struct device *dev)
{
struct ti_pipe3 *phy = dev_get_drvdata(dev);
int ret = 0;
ret = ti_pipe3_enable_clocks(phy);
return ret;
}
static int ti_pipe3_suspend(struct device *dev)
{
struct ti_pipe3 *phy = dev_get_drvdata(dev);
ti_pipe3_disable_clocks(phy);
return 0;
}
static int ti_pipe3_resume(struct device *dev)
{
struct ti_pipe3 *phy = dev_get_drvdata(dev);
int ret;
ret = ti_pipe3_enable_clocks(phy);
if (ret)
return ret;
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return 0;
}
#endif
static const struct dev_pm_ops ti_pipe3_pm_ops = {
SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend,
ti_pipe3_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume)
};
#define DEV_PM_OPS (&ti_pipe3_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif
#ifdef CONFIG_OF
static const struct of_device_id ti_pipe3_id_table[] = {
{
......@@ -520,7 +601,7 @@ static struct platform_driver ti_pipe3_driver = {
.remove = ti_pipe3_remove,
.driver = {
.name = "ti-pipe3",
.pm = DEV_PM_OPS,
.pm = &ti_pipe3_pm_ops,
.of_match_table = of_match_ptr(ti_pipe3_id_table),
},
};
......
......@@ -1608,7 +1608,7 @@ static int std_req_get_status(struct nbu2ss_udc *udc)
switch (recipient) {
case USB_RECIP_DEVICE:
if (udc->ctrl.wIndex == 0x0000) {
if (udc->self_powered)
if (udc->gadget.is_selfpowered)
status_data |= (1 << USB_DEVICE_SELF_POWERED);
if (udc->remote_wakeup)
......@@ -3117,7 +3117,7 @@ static int nbu2ss_gad_wakeup(struct usb_gadget *pgadget)
static int nbu2ss_gad_set_selfpowered(struct usb_gadget *pgadget,
int is_selfpowered)
{
struct nbu2ss_udc *udc;
struct nbu2ss_udc *udc;
unsigned long flags;
/* INFO("=== %s()\n", __func__); */
......@@ -3130,7 +3130,7 @@ static int nbu2ss_gad_set_selfpowered(struct usb_gadget *pgadget,
udc = container_of(pgadget, struct nbu2ss_udc, gadget);
spin_lock_irqsave(&udc->lock, flags);
udc->self_powered = (is_selfpowered != 0);
pgadget->is_selfpowered = (is_selfpowered != 0);
spin_unlock_irqrestore(&udc->lock, flags);
return 0;
......@@ -3308,7 +3308,7 @@ static int __init nbu2ss_drv_contest_init(
spin_lock_init(&udc->lock);
udc->dev = &pdev->dev;
udc->self_powered = 1;
udc->gadget.is_selfpowered = 1;
udc->devstate = USB_STATE_NOTATTACHED;
udc->pdev = pdev;
udc->mA = 0;
......
......@@ -624,7 +624,6 @@ struct nbu2ss_udc {
unsigned linux_suspended:1;
unsigned linux_resume:1;
unsigned usb_suspended:1;
unsigned self_powered:1;
unsigned remote_wakeup:1;
unsigned udc_enabled:1;
......
......@@ -104,6 +104,8 @@ source "drivers/usb/dwc2/Kconfig"
source "drivers/usb/chipidea/Kconfig"
source "drivers/usb/isp1760/Kconfig"
comment "USB port drivers"
if USB
......
......@@ -8,6 +8,7 @@ obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_DWC3) += dwc3/
obj-$(CONFIG_USB_DWC2) += dwc2/
obj-$(CONFIG_USB_ISP1760) += isp1760/
obj-$(CONFIG_USB_MON) += mon/
......@@ -23,7 +24,6 @@ obj-$(CONFIG_USB_ISP1362_HCD) += host/
obj-$(CONFIG_USB_U132_HCD) += host/
obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_HWA_HCD) += host/
obj-$(CONFIG_USB_ISP1760_HCD) += host/
obj-$(CONFIG_USB_IMX21_HCD) += host/
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
obj-$(CONFIG_USB_FUSBH200_HCD) += host/
......
......@@ -111,6 +111,9 @@ static void ci_hdrc_pci_remove(struct pci_dev *pdev)
* PCI device structure
*
* Check "pci.h" for details
*
* Note: ehci-pci driver may try to probe the device first. You have to add an
* ID to the bypass_pci_id_table in ehci-pci driver to prevent this.
*/
static const struct pci_device_id ci_hdrc_pci_id_table[] = {
{
......
......@@ -819,8 +819,8 @@ __acquires(hwep->lock)
}
if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
/* Assume that device is bus powered for now. */
*(u16 *)req->buf = ci->remote_wakeup << 1;
*(u16 *)req->buf = (ci->remote_wakeup << 1) |
ci->gadget.is_selfpowered;
} else if ((setup->bRequestType & USB_RECIP_MASK) \
== USB_RECIP_ENDPOINT) {
dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
......@@ -1520,6 +1520,19 @@ static int ci_udc_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
return -ENOTSUPP;
}
static int ci_udc_selfpowered(struct usb_gadget *_gadget, int is_on)
{
struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
struct ci_hw_ep *hwep = ci->ep0in;
unsigned long flags;
spin_lock_irqsave(hwep->lock, flags);
_gadget->is_selfpowered = (is_on != 0);
spin_unlock_irqrestore(hwep->lock, flags);
return 0;
}
/* Change Data+ pullup status
* this func is used by usb_gadget_connect/disconnet
*/
......@@ -1549,6 +1562,7 @@ static int ci_udc_stop(struct usb_gadget *gadget);
static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci_udc_vbus_session,
.wakeup = ci_udc_wakeup,
.set_selfpowered = ci_udc_selfpowered,
.pullup = ci_udc_pullup,
.vbus_draw = ci_udc_vbus_draw,
.udc_start = ci_udc_start,
......
......@@ -1091,6 +1091,7 @@ static int acm_probe(struct usb_interface *intf,
unsigned long quirks;
int num_rx_buf;
int i;
unsigned int elength = 0;
int combined_interfaces = 0;
struct device *tty_dev;
int rv = -ENOMEM;
......@@ -1136,9 +1137,12 @@ static int acm_probe(struct usb_interface *intf,
dev_err(&intf->dev, "skipping garbage\n");
goto next_desc;
}
elength = buffer[0];
switch (buffer[2]) {
case USB_CDC_UNION_TYPE: /* we've found it */
if (elength < sizeof(struct usb_cdc_union_desc))
goto next_desc;
if (union_header) {
dev_err(&intf->dev, "More than one "
"union descriptor, skipping ...\n");
......@@ -1147,29 +1151,36 @@ static int acm_probe(struct usb_interface *intf,
union_header = (struct usb_cdc_union_desc *)buffer;
break;
case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/
if (elength < sizeof(struct usb_cdc_country_functional_desc))
goto next_desc;
cfd = (struct usb_cdc_country_functional_desc *)buffer;
break;
case USB_CDC_HEADER_TYPE: /* maybe check version */
break; /* for now we ignore it */
case USB_CDC_ACM_TYPE:
if (elength < 4)
goto next_desc;
ac_management_function = buffer[3];
break;
case USB_CDC_CALL_MANAGEMENT_TYPE:
if (elength < 5)
goto next_desc;
call_management_function = buffer[3];
call_interface_num = buffer[4];
break;
default:
/* there are LOTS more CDC descriptors that
/*
* there are LOTS more CDC descriptors that
* could legitimately be found here.
*/
dev_dbg(&intf->dev, "Ignoring descriptor: "
"type %02x, length %d\n",
buffer[2], buffer[0]);
"type %02x, length %ud\n",
buffer[2], elength);
break;
}
next_desc:
buflen -= buffer[0];
buffer += buffer[0];
buflen -= elength;
buffer += elength;
}
if (!union_header) {
......@@ -1287,10 +1298,8 @@ static int acm_probe(struct usb_interface *intf,
dev_dbg(&intf->dev, "interfaces are valid\n");
acm = kzalloc(sizeof(struct acm), GFP_KERNEL);
if (acm == NULL) {
dev_err(&intf->dev, "out of memory (acm kzalloc)\n");
if (acm == NULL)
goto alloc_fail;
}
minor = acm_alloc_minor(acm);
if (minor == ACM_TTY_MINORS) {
......@@ -1329,42 +1338,32 @@ static int acm_probe(struct usb_interface *intf,
acm->quirks = quirks;
buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
dev_err(&intf->dev, "out of memory (ctrl buffer alloc)\n");
if (!buf)
goto alloc_fail2;
}
acm->ctrl_buffer = buf;
if (acm_write_buffers_alloc(acm) < 0) {
dev_err(&intf->dev, "out of memory (write buffer alloc)\n");
if (acm_write_buffers_alloc(acm) < 0)
goto alloc_fail4;
}
acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->ctrlurb) {
dev_err(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
if (!acm->ctrlurb)
goto alloc_fail5;
}
for (i = 0; i < num_rx_buf; i++) {
struct acm_rb *rb = &(acm->read_buffers[i]);
struct urb *urb;
rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL,
&rb->dma);
if (!rb->base) {
dev_err(&intf->dev, "out of memory "
"(read bufs usb_alloc_coherent)\n");
if (!rb->base)
goto alloc_fail6;
}
rb->index = i;
rb->instance = acm;
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
dev_err(&intf->dev,
"out of memory (read urbs usb_alloc_urb)\n");
if (!urb)
goto alloc_fail6;
}
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
urb->transfer_dma = rb->dma;
if (acm->is_int_ep) {
......@@ -1389,11 +1388,8 @@ static int acm_probe(struct usb_interface *intf,
struct acm_wb *snd = &(acm->wb[i]);
snd->urb = usb_alloc_urb(0, GFP_KERNEL);
if (snd->urb == NULL) {
dev_err(&intf->dev,
"out of memory (write urbs usb_alloc_urb)\n");
if (snd->urb == NULL)
goto alloc_fail7;
}
if (usb_endpoint_xfer_int(epwrite))
usb_fill_int_urb(snd->urb, usb_dev,
......
......@@ -22,17 +22,25 @@
*/
/* FIXME tune these based on pool statistics ... */
static const size_t pool_max[HCD_BUFFER_POOLS] = {
/* platforms without dma-friendly caches might need to
* prevent cacheline sharing...
*/
32,
128,
512,
PAGE_SIZE / 2
/* bigger --> allocate pages */
static size_t pool_max[HCD_BUFFER_POOLS] = {
32, 128, 512, 2048,
};
void __init usb_init_pool_max(void)
{
/*
* The pool_max values must never be smaller than
* ARCH_KMALLOC_MINALIGN.
*/
if (ARCH_KMALLOC_MINALIGN <= 32)
; /* Original value is okay */
else if (ARCH_KMALLOC_MINALIGN <= 64)
pool_max[0] = 64;
else if (ARCH_KMALLOC_MINALIGN <= 128)
pool_max[0] = 0; /* Don't use this pool */
else
BUILD_BUG(); /* We don't allow this */
}
/* SETUP primitives */
......
......@@ -1689,7 +1689,7 @@ static struct async *reap_as(struct usb_dev_state *ps)
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
as = async_getcompleted(ps);
if (as)
if (as || !connected(ps))
break;
if (signal_pending(current))
break;
......@@ -1712,7 +1712,7 @@ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)
}
if (signal_pending(current))
return -EINTR;
return -EIO;
return -ENODEV;
}
static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
......@@ -1721,10 +1721,11 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
struct async *as;
as = async_getcompleted(ps);
retval = -EAGAIN;
if (as) {
retval = processcompl(as, (void __user * __user *)arg);
free_async(as);
} else {
retval = (connected(ps) ? -EAGAIN : -ENODEV);
}
return retval;
}
......@@ -1854,7 +1855,7 @@ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)
}
if (signal_pending(current))
return -EINTR;
return -EIO;
return -ENODEV;
}
static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *arg)
......@@ -1862,11 +1863,12 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar
int retval;
struct async *as;
retval = -EAGAIN;
as = async_getcompleted(ps);
if (as) {
retval = processcompl_compat(as, (void __user * __user *)arg);
free_async(as);
} else {
retval = (connected(ps) ? -EAGAIN : -ENODEV);
}
return retval;
}
......@@ -2038,7 +2040,8 @@ static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg)
{
__u32 caps;
caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM;
caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM |
USBDEVFS_CAP_REAP_AFTER_DISCONNECT;
if (!ps->dev->bus->no_stop_on_short)
caps |= USBDEVFS_CAP_BULK_CONTINUATION;
if (ps->dev->bus->sg_tablesize)
......@@ -2138,6 +2141,32 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
return -EPERM;
usb_lock_device(dev);
/* Reap operations are allowed even after disconnection */
switch (cmd) {
case USBDEVFS_REAPURB:
snoop(&dev->dev, "%s: REAPURB\n", __func__);
ret = proc_reapurb(ps, p);
goto done;
case USBDEVFS_REAPURBNDELAY:
snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__);
ret = proc_reapurbnonblock(ps, p);
goto done;
#ifdef CONFIG_COMPAT
case USBDEVFS_REAPURB32:
snoop(&dev->dev, "%s: REAPURB32\n", __func__);
ret = proc_reapurb_compat(ps, p);
goto done;
case USBDEVFS_REAPURBNDELAY32:
snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__);
ret = proc_reapurbnonblock_compat(ps, p);
goto done;
#endif
}
if (!connected(ps)) {
usb_unlock_device(dev);
return -ENODEV;
......@@ -2231,16 +2260,6 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
inode->i_mtime = CURRENT_TIME;
break;
case USBDEVFS_REAPURB32:
snoop(&dev->dev, "%s: REAPURB32\n", __func__);
ret = proc_reapurb_compat(ps, p);
break;
case USBDEVFS_REAPURBNDELAY32:
snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__);
ret = proc_reapurbnonblock_compat(ps, p);
break;
case USBDEVFS_IOCTL32:
snoop(&dev->dev, "%s: IOCTL32\n", __func__);
ret = proc_ioctl_compat(ps, ptr_to_compat(p));
......@@ -2252,16 +2271,6 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
ret = proc_unlinkurb(ps, p);
break;
case USBDEVFS_REAPURB:
snoop(&dev->dev, "%s: REAPURB\n", __func__);
ret = proc_reapurb(ps, p);
break;
case USBDEVFS_REAPURBNDELAY:
snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__);
ret = proc_reapurbnonblock(ps, p);
break;
case USBDEVFS_DISCSIGNAL:
snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__);
ret = proc_disconnectsignal(ps, p);
......@@ -2304,6 +2313,8 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
ret = proc_free_streams(ps, p);
break;
}
done:
usb_unlock_device(dev);
if (ret >= 0)
inode->i_atime = CURRENT_TIME;
......
......@@ -275,21 +275,6 @@ static int usb_unbind_device(struct device *dev)
return 0;
}
/*
* Cancel any pending scheduled resets
*
* [see usb_queue_reset_device()]
*
* Called after unconfiguring / when releasing interfaces. See
* comments in __usb_queue_reset_device() regarding
* udev->reset_running.
*/
static void usb_cancel_queued_reset(struct usb_interface *iface)
{
if (iface->reset_running == 0)
cancel_work_sync(&iface->reset_ws);
}
/* called from driver core with dev locked */
static int usb_probe_interface(struct device *dev)
{
......@@ -380,7 +365,6 @@ static int usb_probe_interface(struct device *dev)
usb_set_intfdata(intf, NULL);
intf->needs_remote_wakeup = 0;
intf->condition = USB_INTERFACE_UNBOUND;
usb_cancel_queued_reset(intf);
/* If the LPM disable succeeded, balance the ref counts. */
if (!lpm_disable_error)
......@@ -425,7 +409,6 @@ static int usb_unbind_interface(struct device *dev)
usb_disable_interface(udev, intf, false);
driver->disconnect(intf);
usb_cancel_queued_reset(intf);
/* Free streams */
for (i = 0, j = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
......@@ -1797,6 +1780,18 @@ static int autosuspend_check(struct usb_device *udev)
dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
return -EOPNOTSUPP;
}
/*
* If the device is a direct child of the root hub and the HCD
* doesn't handle wakeup requests, don't allow autosuspend when
* wakeup is needed.
*/
if (w && udev->parent == udev->bus->root_hub &&
bus_to_hcd(udev->bus)->cant_recv_wakeups) {
dev_dbg(&udev->dev, "HCD doesn't handle wakeup requests\n");
return -EOPNOTSUPP;
}
udev->do_remote_wakeup = w;
return 0;
}
......
......@@ -1618,6 +1618,7 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status)
int usb_hcd_unlink_urb (struct urb *urb, int status)
{
struct usb_hcd *hcd;
struct usb_device *udev = urb->dev;
int retval = -EIDRM;
unsigned long flags;
......@@ -1629,20 +1630,19 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
spin_lock_irqsave(&hcd_urb_unlink_lock, flags);
if (atomic_read(&urb->use_count) > 0) {
retval = 0;
usb_get_dev(urb->dev);
usb_get_dev(udev);
}
spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags);
if (retval == 0) {
hcd = bus_to_hcd(urb->dev->bus);
retval = unlink1(hcd, urb, status);
usb_put_dev(urb->dev);
if (retval == 0)
retval = -EINPROGRESS;
else if (retval != -EIDRM && retval != -EBUSY)
dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n",
urb, retval);
usb_put_dev(udev);
}
if (retval == 0)
retval = -EINPROGRESS;
else if (retval != -EIDRM && retval != -EBUSY)
dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n",
urb, retval);
return retval;
}
......
......@@ -2896,10 +2896,12 @@ static int port_is_suspended(struct usb_hub *hub, unsigned portstatus)
*/
static int check_port_resume_type(struct usb_device *udev,
struct usb_hub *hub, int port1,
int status, unsigned portchange, unsigned portstatus)
int status, u16 portchange, u16 portstatus)
{
struct usb_port *port_dev = hub->ports[port1 - 1];
int retries = 3;
retry:
/* Is a warm reset needed to recover the connection? */
if (status == 0 && udev->reset_resume
&& hub_port_warm_reset_required(hub, port1, portstatus)) {
......@@ -2907,10 +2909,17 @@ static int check_port_resume_type(struct usb_device *udev,
}
/* Is the device still present? */
else if (status || port_is_suspended(hub, portstatus) ||
!port_is_power_on(hub, portstatus) ||
!(portstatus & USB_PORT_STAT_CONNECTION)) {
!port_is_power_on(hub, portstatus)) {
if (status >= 0)
status = -ENODEV;
} else if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
if (retries--) {
usleep_range(200, 300);
status = hub_port_status(hub, port1, &portstatus,
&portchange);
goto retry;
}
status = -ENODEV;
}
/* Can't do a normal resume if the port isn't enabled,
......@@ -4643,9 +4652,13 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
test_bit(port1, hub->removed_bits)) {
/* maybe switch power back on (e.g. root hub was reset) */
/*
* maybe switch power back on (e.g. root hub was reset)
* but only if the port isn't owned by someone else.
*/
if (hub_is_port_power_switchable(hub)
&& !port_is_power_on(hub, portstatus))
&& !port_is_power_on(hub, portstatus)
&& !port_dev->port_owner)
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
if (portstatus & USB_PORT_STAT_ENABLE)
......@@ -4870,7 +4883,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
static void port_event(struct usb_hub *hub, int port1)
__must_hold(&port_dev->status_lock)
{
int connect_change, reset_device = 0;
int connect_change;
struct usb_port *port_dev = hub->ports[port1 - 1];
struct usb_device *udev = port_dev->child;
struct usb_device *hdev = hub->hdev;
......@@ -4958,30 +4971,14 @@ static void port_event(struct usb_hub *hub, int port1)
if (hub_port_reset(hub, port1, NULL,
HUB_BH_RESET_TIME, true) < 0)
hub_port_disable(hub, port1, 1);
} else
reset_device = 1;
}
/*
* On disconnect USB3 protocol ports transit from U0 to
* SS.Inactive to Rx.Detect. If this happens a warm-
* reset is not needed, but a (re)connect may happen
* before hub_wq runs and sees the disconnect, and the
* device may be an unknown state.
*
* If the port went through SS.Inactive without hub_wq
* seeing it the C_LINK_STATE change flag will be set,
* and we reset the dev to put it in a known state.
*/
if (reset_device || (udev && hub_is_superspeed(hub->hdev)
&& (portchange & USB_PORT_STAT_C_LINK_STATE)
&& (portstatus & USB_PORT_STAT_CONNECTION))) {
usb_unlock_port(port_dev);
usb_lock_device(udev);
usb_reset_device(udev);
usb_unlock_device(udev);
usb_lock_port(port_dev);
connect_change = 0;
} else {
usb_unlock_port(port_dev);
usb_lock_device(udev);
usb_reset_device(udev);
usb_unlock_device(udev);
usb_lock_port(port_dev);
connect_change = 0;
}
}
if (connect_change)
......@@ -5577,26 +5574,19 @@ EXPORT_SYMBOL_GPL(usb_reset_device);
* possible; depending on how the driver attached to each interface
* handles ->pre_reset(), the second reset might happen or not.
*
* - If a driver is unbound and it had a pending reset, the reset will
* be cancelled.
*
* - This function can be called during .probe() or .disconnect()
* times. On return from .disconnect(), any pending resets will be
* cancelled.
*
* There is no no need to lock/unlock the @reset_ws as schedule_work()
* does its own.
* - If the reset is delayed so long that the interface is unbound from
* its driver, the reset will be skipped.
*
* NOTE: We don't do any reference count tracking because it is not
* needed. The lifecycle of the work_struct is tied to the
* usb_interface. Before destroying the interface we cancel the
* work_struct, so the fact that work_struct is queued and or
* running means the interface (and thus, the device) exist and
* are referenced.
* - This function can be called during .probe(). It can also be called
* during .disconnect(), but doing so is pointless because the reset
* will not occur. If you really want to reset the device during
* .disconnect(), call usb_reset_device() directly -- but watch out
* for nested unbinding issues!
*/
void usb_queue_reset_device(struct usb_interface *iface)
{
schedule_work(&iface->reset_ws);
if (schedule_work(&iface->reset_ws))
usb_get_intf(iface);
}
EXPORT_SYMBOL_GPL(usb_queue_reset_device);
......
......@@ -1551,6 +1551,7 @@ static void usb_release_interface(struct device *dev)
altsetting_to_usb_interface_cache(intf->altsetting);
kref_put(&intfc->ref, usb_release_interface_cache);
usb_put_dev(interface_to_usbdev(intf));
kfree(intf);
}
......@@ -1626,24 +1627,6 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
/*
* Internal function to queue a device reset
*
* This is initialized into the workstruct in 'struct
* usb_device->reset_ws' that is launched by
* message.c:usb_set_configuration() when initializing each 'struct
* usb_interface'.
*
* It is safe to get the USB device without reference counts because
* the life cycle of @iface is bound to the life cycle of @udev. Then,
* this function will be ran only if @iface is alive (and before
* freeing it any scheduled instances of it will have been cancelled).
*
* We need to set a flag (usb_dev->reset_running) because when we call
* the reset, the interfaces might be unbound. The current interface
* cannot try to remove the queued work as it would cause a deadlock
* (you cannot remove your work from within your executing
* workqueue). This flag lets it know, so that
* usb_cancel_queued_reset() doesn't try to do it.
*
* See usb_queue_reset_device() for more details
*/
static void __usb_queue_reset_device(struct work_struct *ws)
......@@ -1655,11 +1638,10 @@ static void __usb_queue_reset_device(struct work_struct *ws)
rc = usb_lock_device_for_reset(udev, iface);
if (rc >= 0) {
iface->reset_running = 1;
usb_reset_device(udev);
iface->reset_running = 0;
usb_unlock_device(udev);
}
usb_put_intf(iface); /* Undo _get_ in usb_queue_reset_device() */
}
......@@ -1854,6 +1836,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
dev_set_name(&intf->dev, "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath,
configuration, alt->desc.bInterfaceNumber);
usb_get_dev(dev);
}
kfree(new_interfaces);
......
......@@ -1049,6 +1049,7 @@ static int __init usb_init(void)
pr_info("%s: USB support disabled\n", usbcore_name);
return 0;
}
usb_init_pool_max();
retval = usb_debugfs_init();
if (retval)
......
......@@ -23,7 +23,7 @@ choice
config USB_DWC2_HOST
bool "Host only mode"
depends on USB
depends on USB=y || (USB_DWC2=m && USB)
help
The Designware USB2.0 high-speed host controller
integrated into many SoCs. Select this option if you want the
......@@ -42,7 +42,7 @@ config USB_DWC2_PERIPHERAL
config USB_DWC2_DUAL_ROLE
bool "Dual Role mode"
depends on (USB=y || USB=USB_DWC2) && (USB_GADGET=y || USB_GADGET=USB_DWC2)
depends on (USB=y && USB_GADGET=y) || (USB_DWC2=m && USB && USB_GADGET)
help
Select this option if you want the driver to work in a dual-role
mode. In this mode both host and gadget features are enabled, and
......
......@@ -462,7 +462,7 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
dwc2_enable_common_interrupts(hsotg);
/*
* Do device or host intialization based on mode during PCD and
* Do device or host initialization based on mode during PCD and
* HCD initialization
*/
if (dwc2_is_host_mode(hsotg)) {
......
......@@ -108,7 +108,7 @@ struct s3c_hsotg_req;
* @halted: Set if the endpoint has been halted.
* @periodic: Set if this is a periodic ep, such as Interrupt
* @isochronous: Set if this is a isochronous ep
* @sent_zlp: Set if we've sent a zero-length packet.
* @send_zlp: Set if we need to send a zero-length packet.
* @total_data: The total number of data bytes done.
* @fifo_size: The size of the FIFO (for periodic IN endpoints)
* @fifo_load: The amount of data loaded into the FIFO (periodic IN)
......@@ -149,7 +149,7 @@ struct s3c_hsotg_ep {
unsigned int halted:1;
unsigned int periodic:1;
unsigned int isochronous:1;
unsigned int sent_zlp:1;
unsigned int send_zlp:1;
char name[10];
};
......@@ -158,14 +158,12 @@ struct s3c_hsotg_ep {
* struct s3c_hsotg_req - data transfer request
* @req: The USB gadget request
* @queue: The list of requests for the endpoint this is queued for.
* @in_progress: Has already had size/packets written to core
* @mapped: DMA buffer for this request has been mapped via dma_map_single().
* @saved_req_buf: variable to save req.buf when bounce buffers are used.
*/
struct s3c_hsotg_req {
struct usb_request req;
struct list_head queue;
unsigned char in_progress;
unsigned char mapped;
void *saved_req_buf;
};
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
......@@ -193,6 +191,22 @@ 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,
DWC2_EP0_DATA_IN,
DWC2_EP0_DATA_OUT,
DWC2_EP0_STATUS_IN,
DWC2_EP0_STATUS_OUT,
};
/**
* struct dwc2_core_params - Parameters for configuring the core
*
......@@ -381,7 +395,7 @@ struct dwc2_core_params {
* @power_optimized Are power optimizations enabled?
* @num_dev_ep Number of device endpoints available
* @num_dev_perio_in_ep Number of device periodic IN endpoints
* avaialable
* available
* @dev_token_q_depth Device Mode IN Token Sequence Learning Queue
* Depth
* 0 to 30
......@@ -434,6 +448,9 @@ struct dwc2_hw_params {
u32 snpsid;
};
/* Size of control and EP0 buffers */
#define DWC2_CTRL_BUFF_SIZE 8
/**
* struct dwc2_hsotg - Holds the state of the driver, including the non-periodic
* and periodic schedules
......@@ -552,14 +569,20 @@ struct dwc2_hw_params {
* @num_of_eps: Number of available EPs (excluding EP0)
* @debug_root: Root directrory for debugfs.
* @debug_file: Main status file for debugfs.
* @debug_testmode: Testmode status file for debugfs.
* @debug_fifo: FIFO status file for debugfs.
* @ep0_reply: Request used for ep0 reply.
* @ep0_buff: Buffer for EP0 reply data, if needed.
* @ctrl_buff: Buffer for EP0 control requests.
* @ctrl_req: Request for EP0 control packets.
* @setup: NAK management for EP0 SETUP
* @ep0_state: EP0 control transfers state
* @test_mode: USB test mode requested by the host
* @last_rst: Time of last reset
* @eps: The endpoints being supplied to the gadget framework
* @g_using_dma: Indicate if dma usage is enabled
* @g_rx_fifo_sz: Contains rx fifo size value
* @g_np_g_tx_fifo_sz: Contains Non-Periodic tx fifo size value
* @g_tx_fifo_sz: Contains tx fifo size value per endpoints
*/
struct dwc2_hsotg {
struct device *dev;
......@@ -591,6 +614,7 @@ struct dwc2_hsotg {
struct dentry *debug_root;
struct dentry *debug_file;
struct dentry *debug_testmode;
struct dentry *debug_fifo;
/* DWC OTG HW Release versions */
......@@ -684,15 +708,21 @@ struct dwc2_hsotg {
struct usb_request *ep0_reply;
struct usb_request *ctrl_req;
u8 ep0_buff[8];
u8 ctrl_buff[8];
void *ep0_buff;
void *ctrl_buff;
enum dwc2_ep0_state ep0_state;
u8 test_mode;
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
unsigned int setup:1;
unsigned long last_rst;
struct s3c_hsotg_ep *eps;
struct s3c_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
struct s3c_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
u32 g_using_dma;
u32 g_rx_fifo_sz;
u32 g_np_g_tx_fifo_sz;
u32 g_tx_fifo_sz[MAX_EPS_CHANNELS];
#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
};
......@@ -969,7 +999,8 @@ extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg);
extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2);
extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2);
extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2);
extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset);
extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg);
extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2);
#else
......@@ -981,7 +1012,8 @@ static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2)
{ return 0; }
static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{ return 0; }
static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2) {}
static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset) {}
static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
#endif
......
此差异已折叠。
此差异已折叠。
......@@ -294,6 +294,7 @@
#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_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)
......@@ -541,6 +542,7 @@
#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
#define DXEPINT_SETUP_RCVD (1 << 15)
#define DXEPINT_INEPNAKEFF (1 << 6)
#define DXEPINT_BACK2BACKSETUP (1 << 6)
#define DXEPINT_INTKNEPMIS (1 << 5)
......
此差异已折叠。
......@@ -104,12 +104,6 @@ config USB_DWC3_DEBUG
help
Say Y here to enable debugging messages on DWC3 Driver.
config USB_DWC3_VERBOSE
bool "Enable Verbose Debugging Messages"
depends on USB_DWC3_DEBUG
help
Say Y here to enable verbose debugging messages on DWC3 Driver.
config DWC3_HOST_USB3_LPM_ENABLE
bool "Enable USB3 LPM Capability"
depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
......
......@@ -2,7 +2,6 @@
CFLAGS_trace.o := -I$(src)
ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG
ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG
obj-$(CONFIG_USB_DWC3) += dwc3.o
......
......@@ -345,7 +345,7 @@ static void dwc3_core_num_eps(struct dwc3 *dwc)
dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints",
dwc->num_in_eps, dwc->num_out_eps);
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册