USB/PHY patches for 4.13-rc1

Here is the big patchset of USB and PHY driver updates for 4.13-rc1.
 
 On the PHY side, they decided to move files around to "make things
 easier" in their tree.  Hopefully that wasn't a mistake, but in
 linux-next testing, we haven't had any reported problems.
 
 There's the usual set of gadget and xhci and musb updates in here as
 well, along with a number of smaller updates for a raft of different USB
 drivers.  Full details in the shortlog, nothing really major.
 
 All of these have been in linux-next for a while with no reported
 issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWVpavQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ymJrgCgp8Pso8bs+bnIknUSQFSguWd3wM0AnA8X3NHf
 lrdCuqw+2oxGOQrecacz
 =5L4Q
 -----END PGP SIGNATURE-----

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

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

  On the PHY side, they decided to move files around to "make things
  easier" in their tree. Hopefully that wasn't a mistake, but in
  linux-next testing, we haven't had any reported problems.

  There's the usual set of gadget and xhci and musb updates in here as
  well, along with a number of smaller updates for a raft of different
  USB drivers. Full details in the shortlog, nothing really major.

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

* tag 'usb-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (173 commits)
  Add USB quirk for HVR-950q to avoid intermittent device resets
  USB hub_probe: rework ugly goto-into-compound-statement
  usb: host: ohci-pxa27x: Handle return value of clk_prepare_enable
  USB: serial: cp210x: add ID for CEL EM3588 USB ZigBee stick
  usbip: Fix uninitialized variable bug in vhci
  usb: core: read USB ports from DT in the usbport LED trigger driver
  dt-bindings: leds: document new trigger-sources property
  usb: typec: ucsi: Add ACPI driver
  usb: typec: Add support for UCSI interface
  usb: musb: compress return logic into one line
  USB: serial: propagate late probe errors
  USB: serial: refactor port endpoint setup
  usb: musb: tusb6010_omap: Convert to DMAengine API
  ARM: OMAP2+: DMA: Add slave map entries for 24xx external request lines
  usb: musb: tusb6010: Handle DMA TX completion in DMA callback as well
  usb: musb: tusb6010_omap: Allocate DMA channels upfront
  usb: musb: tusb6010_omap: Create new struct for DMA data/parameters
  usb: musb: tusb6010_omap: Use one musb_ep_select call in tusb_omap_dma_program
  usb: musb: tusb6010: Add MUSB_G_NO_SKB_RESERVE to quirks
  usb: musb: Add quirk to avoid skb reserve in gadget mode
  ...
This commit is contained in:
Linus Torvalds 2017-07-03 19:30:55 -07:00
commit 362f6729cb
245 changed files with 11054 additions and 4452 deletions

View File

@ -55,14 +55,6 @@ Description:
Indicates the maximum USB speed supported by this port.
Users:
What: /sys/class/udc/<udc>/maximum_speed
Date: June 2011
KernelVersion: 3.1
Contact: Felipe Balbi <balbi@kernel.org>
Description:
Indicates the maximum USB speed supported by this port.
Users:
What: /sys/class/udc/<udc>/soft_connect
Date: June 2011
KernelVersion: 3.1
@ -91,3 +83,11 @@ Description:
'configured', and 'suspended'; however not all USB Device
Controllers support reporting all states.
Users:
What: /sys/class/udc/<udc>/function
Date: June 2017
KernelVersion: 4.13
Contact: Felipe Balbi <balbi@kernel.org>
Description:
Prints out name of currently running USB Gadget Driver.
Users:

View File

@ -1,12 +1,14 @@
What: /config/usb-gadget/gadget/functions/uac1.name
Date: Sep 2014
KernelVersion: 3.18
Date: June 2017
KernelVersion: 4.14
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
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)
req_number - the number of pre-allocated request
for both capture and playback

View File

@ -0,0 +1,12 @@
What: /config/usb-gadget/gadget/functions/uac1_legacy.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

View File

@ -30,6 +30,21 @@ Description:
Valid values: source, sink
What: /sys/class/typec/<port>/port_type
Date: May 2017
Contact: Badhri Jagan Sridharan <Badhri@google.com>
Description:
Indicates the type of the port. This attribute can be used for
requesting a change in the port type. Port type change is
supported as a synchronous operation, so write(2) to the
attribute will not return until the operation has finished.
Valid values:
- source (The port will behave as source only DFP port)
- sink (The port will behave as sink only UFP port)
- dual (The port will behave as dual-role-data and
dual-role-power port)
What: /sys/class/typec/<port>/vconn_source
Date: April 2017
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>

View File

@ -1,4 +1,4 @@
Common leds properties.
* Common leds properties.
LED and flash LED devices provide the same basic functionality as current
regulators, but extended with LED and flash LED specific features like
@ -49,6 +49,22 @@ Optional properties for child nodes:
- panic-indicator : This property specifies that the LED should be used,
if at all possible, as a panic indicator.
- trigger-sources : List of devices which should be used as a source triggering
this LED activity. Some LEDs can be related to a specific
device and should somehow indicate its state. E.g. USB 2.0
LED may react to device(s) in a USB 2.0 port(s).
Another common example is switch or router with multiple
Ethernet ports each of them having its own LED assigned
(assuming they are not hardwired). In such cases this
property should contain phandle(s) of related source
device(s).
In many cases LED can be related to more than one device
(e.g. one USB LED vs. multiple USB ports). Each source
should be represented by a node in the device tree and be
referenced by a phandle and a set of phandle arguments. A
length of arguments should be specified by the
#trigger-source-cells property in the source node.
Required properties for flash LED child nodes:
- flash-max-microamp : Maximum flash LED supply current in microamperes.
- flash-max-timeout-us : Maximum timeout in microseconds after which the flash
@ -59,7 +75,17 @@ property can be omitted.
For controllers that have no configurable timeout the flash-max-timeout-us
property can be omitted.
Examples:
* Trigger source providers
Each trigger source should be represented by a device tree node. It may be e.g.
a USB port or an Ethernet device.
Required properties for trigger source:
- #trigger-source-cells : Number of cells in a source trigger. Typically 0 for
nodes of simple trigger sources (e.g. a specific USB
port).
* Examples
gpio-leds {
compatible = "gpio-leds";
@ -69,6 +95,11 @@ gpio-leds {
linux,default-trigger = "heartbeat";
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
};
usb {
gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port1>, <&ehci_port1>;
};
};
max77693-led {

View File

@ -3,9 +3,10 @@ Driver for Broadcom Northstar USB 3.0 PHY
Required properties:
- compatible: one of: "brcm,ns-ax-usb3-phy", "brcm,ns-bx-usb3-phy".
- reg: register mappings for DMP (Device Management Plugin) and ChipCommon B
MMI.
- reg-names: "dmp" and "ccb-mii"
- reg: address of MDIO bus device
- usb3-dmp-syscon: phandle to syscon with DMP (Device Management Plugin)
registers
- #phy-cells: must be 0
Initialization of USB 3.0 PHY depends on Northstar version. There are currently
three known series: Ax, Bx and Cx.
@ -15,9 +16,19 @@ Known B1: BCM4707 rev 6
Known C0: BCM47094 rev 0
Example:
usb3-phy {
compatible = "brcm,ns-ax-usb3-phy";
reg = <0x18105000 0x1000>, <0x18003000 0x1000>;
reg-names = "dmp", "ccb-mii";
#phy-cells = <0>;
mdio: mdio@0 {
reg = <0x0>;
#size-cells = <1>;
#address-cells = <0>;
usb3-phy@10 {
compatible = "brcm,ns-ax-usb3-phy";
reg = <0x10>;
usb3-dmp-syscon = <&usb3_dmp>;
#phy-cells = <0>;
};
};
usb3_dmp: syscon@18105000 {
reg = <0x18105000 0x1000>;
};

View File

@ -0,0 +1,30 @@
BROADCOM NORTHSTAR2 USB2 (DUAL ROLE DEVICE) PHY
Required properties:
- compatible: brcm,ns2-drd-phy
- reg: offset and length of the NS2 PHY related registers.
- reg-names
The below registers must be provided.
icfg - for DRD ICFG configurations
rst-ctrl - for DRD IDM reset
crmu-ctrl - for CRMU core vdd, PHY and PHY PLL reset
usb2-strap - for port over current polarity reversal
- #phy-cells: Must be 0. No args required.
- vbus-gpios: vbus gpio binding
- id-gpios: id gpio binding
Refer to phy/phy-bindings.txt for the generic PHY binding properties
Example:
usbdrd_phy: phy@66000960 {
#phy-cells = <0>;
compatible = "brcm,ns2-drd-phy";
reg = <0x66000960 0x24>,
<0x67012800 0x4>,
<0x6501d148 0x4>,
<0x664d0700 0x4>;
reg-names = "icfg", "rst-ctrl",
"crmu-ctrl", "usb2-strap";
id-gpios = <&gpio_g 30 0>;
vbus-gpios = <&gpio_g 31 0>;
};

View File

@ -7,12 +7,13 @@ Required properties:
"brcm,iproc-ns2-sata-phy"
"brcm,iproc-nsp-sata-phy"
"brcm,phy-sata3"
"brcm,iproc-sr-sata-phy"
- address-cells: should be 1
- size-cells: should be 0
- reg: register ranges for the PHY PCB interface
- reg-names: should be "phy" and "phy-ctrl"
The "phy-ctrl" registers are only required for
"brcm,iproc-ns2-sata-phy".
"brcm,iproc-ns2-sata-phy" and "brcm,iproc-sr-sata-phy".
Sub-nodes:
Each port's PHY should be represented as a sub-node.
@ -23,8 +24,8 @@ Sub-nodes required properties:
Sub-nodes optional properties:
- brcm,enable-ssc: use spread spectrum clocking (SSC) on this port
This property is not applicable for "brcm,iproc-ns2-sata-phy" and
"brcm,iproc-nsp-sata-phy".
This property is not applicable for "brcm,iproc-ns2-sata-phy",
"brcm,iproc-nsp-sata-phy" and "brcm,iproc-sr-sata-phy".
Example:
sata-phy@f0458100 {

View File

@ -0,0 +1,17 @@
* Amlogic Meson GXL and GXM USB2 PHY binding
Required properties:
- compatible: Should be "amlogic,meson-gxl-usb2-phy"
- reg: The base address and length of the registers
- #phys-cells: must be 0 (see phy-bindings.txt in this directory)
Optional properties:
- phy-supply: see phy-bindings.txt in this directory
Example:
usb2_phy0: phy@78000 {
compatible = "amlogic,meson-gxl-usb2-phy";
#phy-cells = <0>;
reg = <0x0 0x78000 0x0 0x20>;
};

View File

@ -1,7 +1,8 @@
* Amlogic Meson8b and GXBB USB2 PHY
* Amlogic Meson8, Meson8b and GXBB USB2 PHY
Required properties:
- compatible: Depending on the platform this should be one of:
"amlogic,meson8-usb2-phy"
"amlogic,meson8b-usb2-phy"
"amlogic,meson-gxbb-usb2-phy"
- reg: The base address and length of the registers

View File

@ -0,0 +1,40 @@
Motorola CPCAP PMIC USB PHY binding
Required properties:
compatible: Shall be either "motorola,cpcap-usb-phy" or
"motorola,mapphone-cpcap-usb-phy"
#phy-cells: Shall be 0
interrupts: CPCAP PMIC interrupts used by the USB PHY
interrupt-names: Interrupt names
io-channels: IIO ADC channels used by the USB PHY
io-channel-names: IIO ADC channel names
vusb-supply: Regulator for the PHY
Optional properties:
pinctrl: Optional alternate pin modes for the PHY
pinctrl-names: Names for optional pin modes
mode-gpios: Optional GPIOs for configuring alternate modes
Example:
cpcap_usb2_phy: phy {
compatible = "motorola,mapphone-cpcap-usb-phy";
pinctrl-0 = <&usb_gpio_mux_sel1 &usb_gpio_mux_sel2>;
pinctrl-1 = <&usb_ulpi_pins>;
pinctrl-2 = <&usb_utmi_pins>;
pinctrl-3 = <&uart3_pins>;
pinctrl-names = "default", "ulpi", "utmi", "uart";
#phy-cells = <0>;
interrupts-extended = <
&cpcap 15 0 &cpcap 14 0 &cpcap 28 0 &cpcap 19 0
&cpcap 18 0 &cpcap 17 0 &cpcap 16 0 &cpcap 49 0
&cpcap 48 1
>;
interrupt-names =
"id_ground", "id_float", "se0conn", "vbusvld",
"sessvld", "sessend", "se1", "dm", "dp";
mode-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH
&gpio1 0 GPIO_ACTIVE_HIGH>;
io-channels = <&cpcap_adc 2>, <&cpcap_adc 7>;
io-channel-names = "vbus", "id";
vusb-supply = <&vusb>;
};

View File

@ -2,6 +2,7 @@ ROCKCHIP USB2.0 PHY WITH INNO IP BLOCK
Required properties (phy (parent) node):
- compatible : should be one of the listed compatibles:
* "rockchip,rk3228-usb2phy"
* "rockchip,rk3328-usb2phy"
* "rockchip,rk3366-usb2phy"
* "rockchip,rk3399-usb2phy"

View File

@ -0,0 +1,46 @@
* Renesas R-Car generation 3 USB 3.0 PHY
This file provides information on what the device node for the R-Car generation
3 USB 3.0 PHY contains.
If you want to enable spread spectrum clock (ssc), you should use USB_EXTAL
instead of USB3_CLK. However, if you don't want to these features, you don't
need this driver.
Required properties:
- compatible: "renesas,r8a7795-usb3-phy" if the device is a part of an R8A7795
SoC.
"renesas,r8a7796-usb3-phy" if the device is a part of an R8A7796
SoC.
"renesas,rcar-gen3-usb3-phy" for a generic R-Car Gen3 compatible
device.
When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first
followed by the generic version.
- reg: offset and length of the USB 3.0 PHY register block.
- clocks: A list of phandles and clock-specifier pairs.
- clock-names: Name of the clocks.
- The funcional clock must be "usb3-if".
- The usb3's external clock must be "usb3s_clk".
- The usb2's external clock must be "usb_extal". If you want to use the ssc,
the clock-frequency must not be 0.
- #phy-cells: see phy-bindings.txt in the same directory, must be <0>.
Optional properties:
- renesas,ssc-range: Enable/disable spread spectrum clock (ssc) by using
the following values as u32:
- 0 (or the property doesn't exist): disable the ssc
- 4980: enable the ssc as -4980 ppm
- 4492: enable the ssc as -4492 ppm
- 4003: enable the ssc as -4003 ppm
Example (R-Car H3):
usb-phy@e65ee000 {
compatible = "renesas,r8a7795-usb3-phy",
"renesas,rcar-gen3-usb3-phy";
reg = <0 0xe65ee000 0 0x90>;
clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>, <&usb_extal>;
clock-names = "usb3-if", "usb3s_clk", "usb_extal";
};

View File

@ -45,6 +45,8 @@ Optional properties:
a free-running PHY clock.
- snps,dis-del-phy-power-chg-quirk: when set core will change PHY power
from P0 to P1/P2/P3 without delay.
- snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check
during HS transmit.
- snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
utmi_l1_suspend_n, false when asserts utmi_sleep_n
- snps,hird-threshold: HIRD threshold

View File

@ -0,0 +1,21 @@
Broadcom IPROC USB Device controller.
The device node is used for UDCs integrated into Broadcom's
iProc family (Northstar2, Cygnus) of SoCs'. The UDC is based
on Synopsys Designware Cores AHB Subsystem Device Controller
IP.
Required properties:
- compatible: Add the compatibility strings for supported platforms.
For Broadcom NS2 platform, add "brcm,ns2-udc","brcm,iproc-udc".
For Broadcom Cygnus platform, add "brcm,cygnus-udc", "brcm,iproc-udc".
- reg: Offset and length of UDC register set
- interrupts: description of interrupt line
- phys: phandle to phy node.
Example:
udc_dwc: usb@664e0000 {
compatible = "brcm,ns2-udc", "brcm,iproc-udc";
reg = <0x664e0000 0x2000>;
interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usbdrd_phy>;

View File

@ -10,6 +10,7 @@ Optional properties:
- big-endian-desc : boolean, set this for hcds with big-endian descriptors
- big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
- no-big-frame-no : boolean, set if frame_no lives in bits [15:0] of HCCA
- remote-wakeup-connected: remote wakeup is wired on the platform
- num-ports : u32, to override the detected port count
- clocks : a list of phandle + clock specifier pairs
- phys : phandle + phy specifier pair

View File

@ -0,0 +1,712 @@
===============================================================
Synopsys DesignWare Core SuperSpeed USB 3.0 Controller
===============================================================
:Author: Felipe Balbi <felipe.balbi@linux.intel.com>
:Date: April 2017
Introduction
============
The *Synopsys DesignWare Core SuperSpeed USB 3.0 Controller*
(hereinafter referred to as *DWC3*) is a USB SuperSpeed compliant
controller which can be configured in one of 4 ways:
1. Peripheral-only configuration
2. Host-only configuration
3. Dual-Role configuration
4. Hub configuration
Linux currently supports several versions of this controller. In all
likelyhood, the version in your SoC is already supported. At the time
of this writing, known tested versions range from 2.02a to 3.10a. As a
rule of thumb, anything above 2.02a should work reliably well.
Currently, we have many known users for this driver. In alphabetical
order:
1. Cavium
2. Intel Corporation
3. Qualcomm
4. Rockchip
5. ST
6. Samsung
7. Texas Instruments
8. Xilinx
Summary of Features
======================
For details about features supported by your version of DWC3, consult
your IP team and/or *Synopsys DesignWare Core SuperSpeed USB 3.0
Controller Databook*. Following is a list of features supported by the
driver at the time of this writing:
1. Up to 16 bidirectional endpoints (including the control
pipe - ep0)
2. Flexible endpoint configuration
3. Simultaneous IN and OUT transfer support
4. Scatter-list support
5. Up to 256 TRBs [#trb]_ per endpoint
6. Support for all transfer types (*Control*, *Bulk*,
*Interrupt*, and *Isochronous*)
7. SuperSpeed Bulk Streams
8. Link Power Management
9. Trace Events for debugging
10. DebugFS [#debugfs]_ interface
These features have all been exercised with many of the **in-tree**
gadget drivers. We have verified both *ConfigFS* [#configfs]_ and
legacy gadget drivers.
Driver Design
==============
The DWC3 driver sits on the *drivers/usb/dwc3/* directory. All files
related to this driver are in this one directory. This makes it easy
for new-comers to read the code and understand how it behaves.
Because of DWC3's configuration flexibility, the driver is a little
complex in some places but it should be rather straightforward to
understand.
The biggest part of the driver refers to the Gadget API.
Known Limitations
===================
Like any other HW, DWC3 has its own set of limitations. To avoid
constant questions about such problems, we decided to document them
here and have a single location to where we could point users.
OUT Transfer Size Requirements
---------------------------------
According to Synopsys Databook, all OUT transfer TRBs [#trb]_ must
have their *size* field set to a value which is integer divisible by
the endpoint's *wMaxPacketSize*. This means that *e.g.* in order to
receive a Mass Storage *CBW* [#cbw]_, req->length must either be set
to a value that's divisible by *wMaxPacketSize* (1024 on SuperSpeed,
512 on HighSpeed, etc), or DWC3 driver must add a Chained TRB pointing
to a throw-away buffer for the remaining length. Without this, OUT
transfers will **NOT** start.
Note that as of this writing, this won't be a problem because DWC3 is
fully capable of appending a chained TRB for the remaining length and
completely hide this detail from the gadget driver. It's still worth
mentioning because this seems to be the largest source of queries
about DWC3 and *non-working transfers*.
TRB Ring Size Limitation
-------------------------
We, currently, have a hard limit of 256 TRBs [#trb]_ per endpoint,
with the last TRB being a Link TRB [#link_trb]_ pointing back to the
first. This limit is arbitrary but it has the benefit of adding up to
exactly 4096 bytes, or 1 Page.
DWC3 driver will try its best to cope with more than 255 requests and,
for the most part, it should work normally. However this is not
something that has been exercised very frequently. If you experience
any problems, see section **Reporting Bugs** below.
Reporting Bugs
================
Whenever you encounter a problem with DWC3, first and foremost you
should make sure that:
1. You're running latest tag from `Linus' tree`_
2. You can reproduce the error without any out-of-tree changes
to DWC3
3. You have checked that it's not a fault on the host machine
After all these are verified, then here's how to capture enough
information so we can be of any help to you.
Required Information
---------------------
DWC3 relies exclusively on Trace Events for debugging. Everything is
exposed there, with some extra bits being exposed to DebugFS
[#debugfs]_.
In order to capture DWC3's Trace Events you should run the following
commands **before** plugging the USB cable to a host machine:
.. code-block:: sh
# mkdir -p /d
# mkdir -p /t
# mount -t debugfs none /d
# mount -t tracefs none /t
# echo 81920 > /t/buffer_size_kb
# echo 1 > /t/events/dwc3/enable
After this is done, you can connect your USB cable and reproduce the
problem. As soon as the fault is reproduced, make a copy of files
``trace`` and ``regdump``, like so:
.. code-block:: sh
# cp /t/trace /root/trace.txt
# cat /d/*dwc3*/regdump > /root/regdump.txt
Make sure to compress ``trace.txt`` and ``regdump.txt`` in a tarball
and email it to `me`_ with `linux-usb`_ in Cc. If you want to be extra
sure that I'll help you, write your subject line in the following
format:
**[BUG REPORT] usb: dwc3: Bug while doing XYZ**
On the email body, make sure to detail what you doing, which gadget
driver you were using, how to reproduce the problem, what SoC you're
using, which OS (and its version) was running on the Host machine.
With all this information, we should be able to understand what's
going on and be helpful to you.
Debugging
===========
First and foremost a disclaimer::
DISCLAIMER: The information available on DebugFS and/or TraceFS can
change at any time at any Major Linux Kernel Release. If writing
scripts, do **NOT** assume information to be available in the
current format.
With that out of the way, let's carry on.
If you're willing to debug your own problem, you deserve a round of
applause :-)
Anyway, there isn't much to say here other than Trace Events will be
really helpful in figuring out issues with DWC3. Also, access to
Synopsys Databook will be **really** valuable in this case.
A USB Sniffer can be helpful at times but it's not entirely required,
there's a lot that can be understood without looking at the wire.
Feel free to email `me`_ and Cc `linux-usb`_ if you need any help.
``DebugFS``
-------------
``DebugFS`` is very good for gathering snapshots of what's going on
with DWC3 and/or any endpoint.
On DWC3's ``DebugFS`` directory, you will find the following files and
directories:
``ep[0..15]{in,out}/``
``link_state``
``regdump``
``testmode``
``link_state``
``````````````
When read, ``link_state`` will print out one of ``U0``, ``U1``,
``U2``, ``U3``, ``SS.Disabled``, ``RX.Detect``, ``SS.Inactive``,
``Polling``, ``Recovery``, ``Hot Reset``, ``Compliance``,
``Loopback``, ``Reset``, ``Resume`` or ``UNKNOWN link state``.
This file can also be written to in order to force link to one of the
states above.
``regdump``
`````````````
File name is self-explanatory. When read, ``regdump`` will print out a
register dump of DWC3. Note that this file can be grepped to find the
information you want.
``testmode``
``````````````
When read, ``testmode`` will print out a name of one of the specified
USB 2.0 Testmodes (``test_j``, ``test_k``, ``test_se0_nak``,
``test_packet``, ``test_force_enable``) or the string ``no test`` in
case no tests are currently being executed.
In order to start any of these test modes, the same strings can be
written to the file and DWC3 will enter the requested test mode.
``ep[0..15]{in,out}``
``````````````````````
For each endpoint we expose one directory following the naming
convention ``ep$num$dir`` *(ep0in, ep0out, ep1in, ...)*. Inside each
of these directories you will find the following files:
``descriptor_fetch_queue``
``event_queue``
``rx_fifo_queue``
``rx_info_queue``
``rx_request_queue``
``transfer_type``
``trb_ring``
``tx_fifo_queue``
``tx_request_queue``
With access to Synopsys Databook, you can decode the information on
them.
``transfer_type``
~~~~~~~~~~~~~~~~~~
When read, ``transfer_type`` will print out one of ``control``,
``bulk``, ``interrupt`` or ``isochronous`` depending on what the
endpoint descriptor says. If the endpoint hasn't been enabled yet, it
will print ``--``.
``trb_ring``
~~~~~~~~~~~~~
When read, ``trb_ring`` will print out details about all TRBs on the
ring. It will also tell you where our enqueue and dequeue pointers are
located in the ring:
.. code-block:: sh
buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,512,normal,1,0,1,0,0,1 D
0000000000000000,0,UNKNOWN,0,0,0,0,0,0 E
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
00000000381ab000,0,link,0,0,0,0,0,1
Trace Events
-------------
DWC3 also provides several trace events which help us gathering
information about the behavior of the driver during runtime.
In order to use these events, you must enable ``CONFIG_FTRACE`` in
your kernel config.
For details about how enable DWC3 events, see section **Reporting
Bugs**.
The following subsections will give details about each Event Class and
each Event defined by DWC3.
MMIO
```````
It is sometimes useful to look at every MMIO access when looking for
bugs. Because of that, DWC3 offers two Trace Events (one for
dwc3_readl() and one for dwc3_writel()). ``TP_printk`` follows::
TP_printk("addr %p value %08x", __entry->base + __entry->offset,
__entry->value)
Interrupt Events
````````````````
Every IRQ event can be logged and decoded into a human readable
string. Because every event will be different, we don't give an
example other than the ``TP_printk`` format used::
TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__entry->event, __entry->ep0state))
Control Request
`````````````````
Every USB Control Request can be logged to the trace buffer. The
output format is::
TP_printk("%s", dwc3_decode_ctrl(__entry->bRequestType,
__entry->bRequest, __entry->wValue,
__entry->wIndex, __entry->wLength)
)
Note that Standard Control Requests will be decoded into
human-readable strings with their respective arguments. Class and
Vendor requests will be printed out a sequence of 8 bytes in hex
format.
Lifetime of a ``struct usb_request``
```````````````````````````````````````
The entire lifetime of a ``struct usb_request`` can be tracked on the
trace buffer. We have one event for each of allocation, free,
queueing, dequeueing, and giveback. Output format is::
TP_printk("%s: req %p length %u/%u %s%s%s ==> %d",
__get_str(name), __entry->req, __entry->actual, __entry->length,
__entry->zero ? "Z" : "z",
__entry->short_not_ok ? "S" : "s",
__entry->no_interrupt ? "i" : "I",
__entry->status
)
Generic Commands
````````````````````
We can log and decode every Generic Command with its completion
code. Format is::
TP_printk("cmd '%s' [%x] param %08x --> status: %s",
dwc3_gadget_generic_cmd_string(__entry->cmd),
__entry->cmd, __entry->param,
dwc3_gadget_generic_cmd_status_string(__entry->status)
)
Endpoint Commands
````````````````````
Endpoints commands can also be logged together with completion
code. Format is::
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
__get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->param0,
__entry->param1, __entry->param2,
dwc3_ep_cmd_status_string(__entry->cmd_status)
)
Lifetime of a ``TRB``
``````````````````````
A ``TRB`` Lifetime is simple. We are either preparing a ``TRB`` or
completing it. With these two events, we can see how a ``TRB`` changes
over time. Format is::
TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)",
__get_str(name), __entry->queued, __entry->allocated,
__entry->trb, __entry->bph, __entry->bpl,
({char *s;
int pcm = ((__entry->size >> 24) & 3) + 1;
switch (__entry->type) {
case USB_ENDPOINT_XFER_INT:
case USB_ENDPOINT_XFER_ISOC:
switch (pcm) {
case 1:
s = "1x ";
break;
case 2:
s = "2x ";
break;
case 3:
s = "3x ";
break;
}
default:
s = "";
} s; }),
DWC3_TRB_SIZE_LENGTH(__entry->size), __entry->ctrl,
__entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h',
__entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l',
__entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c',
__entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c',
dwc3_trb_type_string(DWC3_TRBCTL_TYPE(__entry->ctrl))
)
Lifetime of an Endpoint
```````````````````````
And endpoint's lifetime is summarized with enable and disable
operations, both of which can be traced. Format is::
TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c%c:%c:%c",
__get_str(name), __entry->maxpacket,
__entry->maxpacket_limit, __entry->max_streams,
__entry->maxburst, __entry->trb_enqueue,
__entry->trb_dequeue,
__entry->flags & DWC3_EP_ENABLED ? 'E' : 'e',
__entry->flags & DWC3_EP_STALL ? 'S' : 's',
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
__entry->flags & DWC3_EP_BUSY ? 'B' : 'b',
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
__entry->flags & DWC3_EP_MISSED_ISOC ? 'M' : 'm',
__entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
__entry->direction ? '<' : '>'
)
Structures, Methods and Definitions
====================================
.. kernel-doc:: drivers/usb/dwc3/core.h
:doc: main data structures
:internal:
.. kernel-doc:: drivers/usb/dwc3/gadget.h
:doc: gadget-only helpers
:internal:
.. kernel-doc:: drivers/usb/dwc3/gadget.c
:doc: gadget-side implementation
:internal:
.. kernel-doc:: drivers/usb/dwc3/core.c
:doc: core driver (probe, PM, etc)
:internal:
.. [#trb] Transfer Request Block
.. [#link_trb] Transfer Request Block pointing to another Transfer
Request Block.
.. [#debugfs] The Debug File System
.. [#configfs] The Config File System
.. [#cbw] Command Block Wrapper
.. _Linus' tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
.. _me: felipe.balbi@linux.intel.com
.. _linux-usb: linux-usb@vger.kernel.org

View File

@ -16,7 +16,10 @@ Linux USB API
persist
error-codes
writing_usb_driver
dwc3
writing_musb_glue_layer
typec
usb3-debug-port
.. only:: subproject and html

View File

@ -16,10 +16,11 @@ provided by gadgets.
13. RNDIS function
14. SERIAL function
15. SOURCESINK function
16. UAC1 function
16. UAC1 function (legacy implementation)
17. UAC2 function
18. UVC function
19. PRINTER function
20. UAC1 function (new API)
1. ACM function
@ -589,15 +590,16 @@ device: run the gadget
host: test-usb (tools/usb/testusb.c)
16. UAC1 function
16. UAC1 function (legacy implementation)
=================
The function is provided by usb_f_uac1.ko module.
The function is provided by usb_f_uac1_legacy.ko module.
Function-specific configfs interface
------------------------------------
The function name to use when creating the function directory is "uac1".
The function name to use when creating the function directory
is "uac1_legacy".
The uac1 function provides these attributes in its function directory:
audio_buf_size - audio buffer size
@ -772,3 +774,46 @@ host:
More advanced testing can be done with the prn_example
described in Documentation/usb/gadget-printer.txt.
20. UAC1 function (virtual ALSA card, using u_audio API)
=================
The function is provided by usb_f_uac1.ko module.
It will create a virtual ALSA card and the audio streams are simply
sinked to and sourced from it.
Function-specific configfs interface
------------------------------------
The function name to use when creating the function directory is "uac1".
The uac1 function provides these attributes in its function directory:
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)
req_number - the number of pre-allocated request for both capture
and playback
The attributes have sane default values.
Testing the UAC1 function
-------------------------
device: run the gadget
host: aplay -l # should list our USB Audio Gadget
This function does not require real hardware support, it just
sends a stream of audio data to/from the host. In order to
actually hear something at the device side, a command similar
to this must be used at the device side:
$ arecord -f dat -t wav -D hw:2,0 | aplay -D hw:0,0 &
e.g.:
$ arecord -f dat -t wav -D hw:CARD=UAC1Gadget,DEV=0 | \
aplay -D default:CARD=OdroidU3

View File

@ -1843,8 +1843,8 @@ F: drivers/i2c/busses/i2c-st.c
F: drivers/media/rc/st_rc.c
F: drivers/media/platform/sti/c8sectpfe/
F: drivers/mmc/host/sdhci-st.c
F: drivers/phy/phy-miphy28lp.c
F: drivers/phy/phy-stih407-usb.c
F: drivers/phy/st/phy-miphy28lp.c
F: drivers/phy/st/phy-stih407-usb.c
F: drivers/pinctrl/pinctrl-st.c
F: drivers/remoteproc/st_remoteproc.c
F: drivers/remoteproc/st_slim_rproc.c
@ -10840,11 +10840,11 @@ L: linux-iio@vger.kernel.org
S: Supported
F: drivers/iio/adc/rcar_gyro_adc.c
RENESAS USB2 PHY DRIVER
RENESAS USB PHY DRIVER
M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
L: linux-renesas-soc@vger.kernel.org
S: Maintained
F: drivers/phy/phy-rcar-gen3-usb2.c
F: drivers/phy/renesas/phy-rcar-gen3-usb*.c
RESET CONTROLLER FRAMEWORK
M: Philipp Zabel <p.zabel@pengutronix.de>
@ -11246,12 +11246,12 @@ L: linux-kernel@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/phy/samsung-phy.txt
F: Documentation/phy/samsung-usb2.txt
F: drivers/phy/phy-exynos4210-usb2.c
F: drivers/phy/phy-exynos4x12-usb2.c
F: drivers/phy/phy-exynos5250-usb2.c
F: drivers/phy/phy-s5pv210-usb2.c
F: drivers/phy/phy-samsung-usb2.c
F: drivers/phy/phy-samsung-usb2.h
F: drivers/phy/samsung/phy-exynos4210-usb2.c
F: drivers/phy/samsung/phy-exynos4x12-usb2.c
F: drivers/phy/samsung/phy-exynos5250-usb2.c
F: drivers/phy/samsung/phy-s5pv210-usb2.c
F: drivers/phy/samsung/phy-samsung-usb2.c
F: drivers/phy/samsung/phy-samsung-usb2.h
SERIAL DRIVERS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

View File

@ -249,6 +249,24 @@ static const struct dma_slave_map omap24xx_sdma_map[] = {
{ "omap_uart.2", "rx", SDMA_FILTER_PARAM(54) },
{ "omap_hsmmc.0", "tx", SDMA_FILTER_PARAM(61) },
{ "omap_hsmmc.0", "rx", SDMA_FILTER_PARAM(62) },
/* external DMA requests when tusb6010 is used */
{ "musb-tusb", "dmareq0", SDMA_FILTER_PARAM(2) },
{ "musb-tusb", "dmareq1", SDMA_FILTER_PARAM(3) },
{ "musb-tusb", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 only */
{ "musb-tusb", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 only */
{ "musb-tusb", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 only */
{ "musb-tusb", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 only */
};
static const struct dma_slave_map omap24xx_sdma_dt_map[] = {
/* external DMA requests when tusb6010 is used */
{ "musb-hdrc.1.auto", "dmareq0", SDMA_FILTER_PARAM(2) },
{ "musb-hdrc.1.auto", "dmareq1", SDMA_FILTER_PARAM(3) },
{ "musb-hdrc.1.auto", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 only */
{ "musb-hdrc.1.auto", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 only */
{ "musb-hdrc.1.auto", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 only */
{ "musb-hdrc.1.auto", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 only */
};
static const struct dma_slave_map omap3xxx_sdma_map[] = {
@ -346,6 +364,12 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
__func__);
return -ENODEV;
}
} else {
if (soc_is_omap24xx()) {
/* DMA slave map for drivers not yet converted to DT */
p.slave_map = omap24xx_sdma_dt_map;
p.slavecnt = ARRAY_SIZE(omap24xx_sdma_dt_map);
}
}
pdev = omap_device_build(name, 0, oh, &p, sizeof(p));

View File

@ -2884,3 +2884,19 @@ void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
else
dev->fwnode = fwnode;
}
/**
* device_set_of_node_from_dev - reuse device-tree node of another device
* @dev: device whose device-tree node is being set
* @dev2: device whose device-tree node is being reused
*
* Takes another reference to the new device-tree node after first dropping
* any reference held to the old node.
*/
void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
{
of_node_put(dev->of_node);
dev->of_node = of_node_get(dev2->of_node);
dev->of_node_reused = true;
}
EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);

View File

@ -23,6 +23,9 @@ int pinctrl_bind_pins(struct device *dev)
{
int ret;
if (dev->of_node_reused)
return 0;
dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);
if (!dev->pins)
return -ENOMEM;

View File

@ -916,12 +916,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
return NULL;
}
/* When the port_window is used, one frame must cover the window */
if (port_window) {
burst = port_window;
port_window_bytes = port_window * es_bytes[es];
}
/* Now allocate and setup the descriptor. */
d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC);
if (!d)
@ -931,6 +925,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->dev_addr = dev_addr;
d->es = es;
/* When the port_window is used, one frame must cover the window */
if (port_window) {
burst = port_window;
port_window_bytes = port_window * es_bytes[es];
d->ei = 1;
/*
* One frame covers the port_window and by configure
* the source frame index to be -1 * (port_window - 1)
* we instruct the sDMA that after a frame is processed
* it should move back to the start of the window.
*/
d->fi = -(port_window_bytes - 1);
}
d->ccr = c->ccr | CCR_SYNC_FRAME;
if (dir == DMA_DEV_TO_MEM) {
d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
@ -955,14 +964,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->ccr |= CCR_SRC_AMODE_POSTINC;
if (port_window) {
d->ccr |= CCR_DST_AMODE_DBLIDX;
d->ei = 1;
/*
* One frame covers the port_window and by configure
* the source frame index to be -1 * (port_window - 1)
* we instruct the sDMA that after a frame is processed
* it should move back to the start of the window.
*/
d->fi = -(port_window_bytes - 1);
if (port_window_bytes >= 64)
d->csdp |= CSDP_DST_BURST_64;
@ -1018,16 +1019,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
osg->addr = sg_dma_address(sgent);
osg->en = en;
osg->fn = sg_dma_len(sgent) / frame_bytes;
if (port_window && dir == DMA_DEV_TO_MEM) {
osg->ei = 1;
/*
* One frame covers the port_window and by configure
* the source frame index to be -1 * (port_window - 1)
* we instruct the sDMA that after a frame is processed
* it should move back to the start of the window.
*/
osg->fi = -(port_window_bytes - 1);
}
if (d->using_ll) {
osg->t2_desc = dma_pool_alloc(od->desc_pool, GFP_ATOMIC,

View File

@ -115,6 +115,7 @@ config EXTCON_PALMAS
config EXTCON_QCOM_SPMI_MISC
tristate "Qualcomm USB extcon support"
depends on ARCH_QCOM || COMPILE_TEST
help
Say Y here to enable SPMI PMIC based USB cable detection
support on Qualcomm PMICs such as PM8941.

View File

@ -1271,9 +1271,7 @@ static int arizona_extcon_get_micd_configs(struct device *dev,
goto out;
nconfs /= entries_per_config;
micd_configs = devm_kzalloc(dev,
nconfs * sizeof(struct arizona_micd_range),
micd_configs = devm_kcalloc(dev, nconfs, sizeof(*micd_configs),
GFP_KERNEL);
if (!micd_configs) {
ret = -ENOMEM;

View File

@ -94,8 +94,7 @@ static int int3496_probe(struct platform_device *pdev)
struct int3496_data *data;
int ret;
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
acpi_int3496_default_gpios);
ret = devm_acpi_dev_add_driver_gpios(dev, acpi_int3496_default_gpios);
if (ret) {
dev_err(dev, "can't add GPIO ACPI mapping\n");
return ret;
@ -169,8 +168,6 @@ static int int3496_remove(struct platform_device *pdev)
devm_free_irq(&pdev->dev, data->usb_id_irq, data);
cancel_delayed_work_sync(&data->work);
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev));
return 0;
}

View File

@ -964,12 +964,12 @@ EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
/**
* extcon_register_notifier_all() - Register a notifier block for all connectors
* @edev: the extcon device that has the external connecotr.
* @edev: the extcon device that has the external connector.
* @nb: a notifier block to be registered.
*
* This fucntion registers a notifier block in order to receive the state
* This function registers a notifier block in order to receive the state
* change of all supported external connectors from extcon device.
* And The second parameter given to the callback of nb (val) is
* And the second parameter given to the callback of nb (val) is
* the current state and third parameter is the edev pointer.
*
* Returns 0 if success or error number if fail
@ -1252,9 +1252,8 @@ int extcon_dev_register(struct extcon_dev *edev)
}
spin_lock_init(&edev->lock);
edev->nh = devm_kzalloc(&edev->dev,
sizeof(*edev->nh) * edev->max_supported, GFP_KERNEL);
edev->nh = devm_kcalloc(&edev->dev, edev->max_supported,
sizeof(*edev->nh), GFP_KERNEL);
if (!edev->nh) {
ret = -ENOMEM;
goto err_dev;

View File

@ -15,73 +15,6 @@ config GENERIC_PHY
phy users can obtain reference to the PHY. All the users of this
framework should select this config.
config PHY_BCM_NS_USB2
tristate "Broadcom Northstar USB 2.0 PHY Driver"
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on HAS_IOMEM && OF
select GENERIC_PHY
help
Enable this to support Broadcom USB 2.0 PHY connected to the USB
controller on Northstar family.
config PHY_BCM_NS_USB3
tristate "Broadcom Northstar USB 3.0 PHY Driver"
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on HAS_IOMEM && OF
select GENERIC_PHY
help
Enable this to support Broadcom USB 3.0 PHY connected to the USB
controller on Northstar family.
config PHY_BERLIN_USB
tristate "Marvell Berlin USB PHY Driver"
depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
select GENERIC_PHY
help
Enable this to support the USB PHY on Marvell Berlin SoCs.
config PHY_BERLIN_SATA
tristate "Marvell Berlin SATA PHY driver"
depends on ARCH_BERLIN && HAS_IOMEM && OF
select GENERIC_PHY
help
Enable this to support the SATA PHY on Marvell Berlin SoCs.
config ARMADA375_USBCLUSTER_PHY
def_bool y
depends on MACH_ARMADA_375 || COMPILE_TEST
depends on OF && HAS_IOMEM
select GENERIC_PHY
config PHY_DA8XX_USB
tristate "TI DA8xx USB PHY Driver"
depends on ARCH_DAVINCI_DA8XX
select GENERIC_PHY
select MFD_SYSCON
help
Enable this to support the USB PHY on DA8xx SoCs.
This driver controls both the USB 1.1 PHY and the USB 2.0 PHY.
config PHY_DM816X_USB
tristate "TI dm816x USB PHY driver"
depends on ARCH_OMAP2PLUS
depends on USB_SUPPORT
select GENERIC_PHY
select USB_PHY
help
Enable this for dm816x USB to work.
config PHY_EXYNOS_MIPI_VIDEO
tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
depends on HAS_IOMEM
depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
select GENERIC_PHY
default y if ARCH_S5PV210 || ARCH_EXYNOS
help
Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
and EXYNOS SoCs.
config PHY_LPC18XX_USB_OTG
tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
@ -93,146 +26,6 @@ config PHY_LPC18XX_USB_OTG
This driver is need for USB0 support on LPC18xx/43xx and takes
care of enabling and clock setup.
config PHY_PXA_28NM_HSIC
tristate "Marvell USB HSIC 28nm PHY Driver"
depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support Marvell USB HSIC PHY driver for Marvell
SoC. This driver will do the PHY initialization and shutdown.
The PHY driver will be used by Marvell ehci driver.
To compile this driver as a module, choose M here.
config PHY_PXA_28NM_USB2
tristate "Marvell USB 2.0 28nm PHY Driver"
depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support Marvell USB 2.0 PHY driver for Marvell
SoC. This driver will do the PHY initialization and shutdown.
The PHY driver will be used by Marvell udc/ehci/otg driver.
To compile this driver as a module, choose M here.
config PHY_MVEBU_SATA
def_bool y
depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
depends on OF
select GENERIC_PHY
config PHY_MIPHY28LP
tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407"
depends on ARCH_STI
select GENERIC_PHY
help
Enable this to support the miphy transceiver (for SATA/PCIE/USB3)
that is part of STMicroelectronics STiH407 SoC.
config PHY_RCAR_GEN2
tristate "Renesas R-Car generation 2 USB PHY driver"
depends on ARCH_RENESAS
depends on GENERIC_PHY
help
Support for USB PHY found on Renesas R-Car generation 2 SoCs.
config PHY_RCAR_GEN3_USB2
tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
depends on ARCH_RENESAS
depends on EXTCON
select GENERIC_PHY
help
Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs.
config OMAP_CONTROL_PHY
tristate "OMAP CONTROL PHY Driver"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
Enable this to add support for the PHY part present in the control
module. This driver has API to power on the USB2 PHY and to write to
the mailbox. The mailbox is present only in omap4 and the register to
power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
additional register to power on USB3 PHY/SATA PHY/PCIE PHY
(PIPE3 PHY).
config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS
depends on USB_SUPPORT
select GENERIC_PHY
select USB_PHY
select OMAP_CONTROL_PHY
depends on OMAP_OCP2SCP
help
Enable this to support the transceiver that is part of SOC. This
driver takes care of all the PHY functionality apart from comparator.
The USB OTG controller communicates with the comparator using this
driver.
config TI_PIPE3
tristate "TI PIPE3 PHY Driver"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
select GENERIC_PHY
select OMAP_CONTROL_PHY
depends on OMAP_OCP2SCP
help
Enable this to support the PIPE3 PHY that is part of TI SOCs. This
driver takes care of all the PHY functionality apart from comparator.
This driver interacts with the "OMAP Control PHY Driver" to power
on/off the PHY.
config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
depends on USB_SUPPORT
depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't 'y'
select GENERIC_PHY
select USB_PHY
help
Enable this to support the USB OTG transceiver on TWL4030
family chips (including the TWL5030 and TPS659x0 devices).
This transceiver supports high and full speed devices plus,
in host mode, low speed.
config PHY_EXYNOS_DP_VIDEO
tristate "EXYNOS SoC series Display Port PHY driver"
depends on OF
depends on ARCH_EXYNOS || COMPILE_TEST
default ARCH_EXYNOS
select GENERIC_PHY
help
Support for Display Port PHY found on Samsung EXYNOS SoCs.
config BCM_KONA_USB2_PHY
tristate "Broadcom Kona USB2 PHY Driver"
depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support the Broadcom Kona USB 2.0 PHY.
config PHY_EXYNOS5250_SATA
tristate "Exynos5250 Sata SerDes/PHY driver"
depends on SOC_EXYNOS5250
depends on HAS_IOMEM
depends on OF
select GENERIC_PHY
select I2C
select I2C_S3C2410
select MFD_SYSCON
help
Enable this to support SATA SerDes/Phy found on Samsung's
Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s,
SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
port to accept one SATA device.
config PHY_HIX5HD2_SATA
tristate "HIX5HD2 SATA PHY Driver"
depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
select GENERIC_PHY
select MFD_SYSCON
help
Support for SATA PHY on Hisilicon hix5hd2 Soc.
config PHY_MT65XX_USB3
tristate "Mediatek USB3.0 PHY Driver"
depends on ARCH_MEDIATEK && OF
@ -241,104 +34,6 @@ config PHY_MT65XX_USB3
Say 'Y' here to add support for Mediatek USB3.0 PHY driver,
it supports multiple usb2.0 and usb3.0 ports.
config PHY_HI6220_USB
tristate "hi6220 USB PHY support"
depends on (ARCH_HISI && ARM64) || COMPILE_TEST
select GENERIC_PHY
select MFD_SYSCON
help
Enable this to support the HISILICON HI6220 USB PHY.
To compile this driver as a module, choose M here.
config PHY_SUN4I_USB
tristate "Allwinner sunxi SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
depends on RESET_CONTROLLER
depends on EXTCON
depends on POWER_SUPPLY
depends on USB_SUPPORT
select GENERIC_PHY
select USB_COMMON
help
Enable this to support the transceiver that is part of Allwinner
sunxi SoCs.
This driver controls the entire USB PHY block, both the USB OTG
parts, as well as the 2 regular USB 2 host PHYs.
config PHY_SUN9I_USB
tristate "Allwinner sun9i SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
depends on RESET_CONTROLLER
depends on USB_SUPPORT
select USB_COMMON
select GENERIC_PHY
help
Enable this to support the transceiver that is part of Allwinner
sun9i SoCs.
This driver controls each individual USB 2 host PHY.
config PHY_SAMSUNG_USB2
tristate "Samsung USB 2.0 PHY driver"
depends on HAS_IOMEM
depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
select GENERIC_PHY
select MFD_SYSCON
default ARCH_EXYNOS
help
Enable this to support the Samsung USB 2.0 PHY driver for Samsung
SoCs. This driver provides the interface for USB 2.0 PHY. Support
for particular PHYs will be enabled based on the SoC type in addition
to this driver.
config PHY_S5PV210_USB2
bool "Support for S5PV210"
depends on PHY_SAMSUNG_USB2
depends on ARCH_S5PV210
help
Enable USB PHY support for S5PV210. This option requires that Samsung
USB 2.0 PHY driver is enabled and means that support for this
particular SoC is compiled in the driver. In case of S5PV210 two phys
are available - device and host.
config PHY_EXYNOS4210_USB2
bool
depends on PHY_SAMSUNG_USB2
default CPU_EXYNOS4210
config PHY_EXYNOS4X12_USB2
bool
depends on PHY_SAMSUNG_USB2
default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
config PHY_EXYNOS5250_USB2
bool
depends on PHY_SAMSUNG_USB2
default SOC_EXYNOS5250 || SOC_EXYNOS5420
config PHY_EXYNOS5_USBDRD
tristate "Exynos5 SoC series USB DRD PHY driver"
depends on ARCH_EXYNOS && OF
depends on HAS_IOMEM
depends on USB_DWC3_EXYNOS
select GENERIC_PHY
select MFD_SYSCON
default y
help
Enable USB DRD PHY support for Exynos 5 SoC series.
This driver provides PHY interface for USB 3.0 DRD controller
present on Exynos5 SoC series.
config PHY_EXYNOS_PCIE
bool "Exynos PCIe PHY driver"
depends on OF && (ARCH_EXYNOS || COMPILE_TEST)
select GENERIC_PHY
help
Enable PCIe PHY support for Exynos SoC series.
This driver provides PHY interface for Exynos PCIe controller.
config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver"
depends on MACH_PISTACHIO
@ -346,83 +41,6 @@ config PHY_PISTACHIO_USB
help
Enable this to support the USB2.0 PHY on the IMG Pistachio SoC.
config PHY_QCOM_APQ8064_SATA
tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
depends on ARCH_QCOM
depends on HAS_IOMEM
depends on OF
select GENERIC_PHY
config PHY_QCOM_IPQ806X_SATA
tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
depends on ARCH_QCOM
depends on HAS_IOMEM
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_ROCKCHIP_INNO_USB2
tristate "Rockchip INNO USB2PHY Driver"
depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
depends on COMMON_CLK
depends on EXTCON
depends on USB_SUPPORT
select GENERIC_PHY
select USB_COMMON
help
Support for Rockchip USB2.0 PHY with Innosilicon IP block.
config PHY_ROCKCHIP_EMMC
tristate "Rockchip EMMC PHY Driver"
depends on ARCH_ROCKCHIP && OF
select GENERIC_PHY
help
Enable this to support the Rockchip EMMC PHY.
config PHY_ROCKCHIP_DP
tristate "Rockchip Display Port PHY Driver"
depends on ARCH_ROCKCHIP && OF
select GENERIC_PHY
help
Enable this to support the Rockchip Display Port PHY.
config PHY_ROCKCHIP_PCIE
tristate "Rockchip PCIe PHY Driver"
depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
select GENERIC_PHY
select MFD_SYSCON
help
Enable this to support the Rockchip PCIe PHY.
config PHY_ROCKCHIP_TYPEC
tristate "Rockchip TYPEC PHY Driver"
depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
select EXTCON
select GENERIC_PHY
select RESET_CONTROLLER
help
Enable this to support the Rockchip USB TYPEC PHY.
config PHY_ST_SPEAR1310_MIPHY
tristate "ST SPEAR1310-MIPHY driver"
select GENERIC_PHY
depends on MACH_SPEAR1310 || COMPILE_TEST
help
Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
config PHY_ST_SPEAR1340_MIPHY
tristate "ST SPEAR1340-MIPHY driver"
select GENERIC_PHY
depends on MACH_SPEAR1340 || COMPILE_TEST
help
Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
config PHY_XGENE
tristate "APM X-Gene 15Gbps PHY support"
depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
@ -430,104 +48,18 @@ config PHY_XGENE
help
This option enables support for APM X-Gene SoC multi-purpose PHY.
config PHY_STIH407_USB
tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family"
depends on RESET_CONTROLLER
depends on ARCH_STI || COMPILE_TEST
select GENERIC_PHY
help
Enable this support to enable the picoPHY device used by USB2
and USB3 controllers on STMicroelectronics STiH407 SoC families.
config PHY_QCOM_QMP
tristate "Qualcomm QMP PHY Driver"
depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
select GENERIC_PHY
help
Enable this to support the QMP PHY transceiver that is used
with controllers such as PCIe, UFS, and USB on Qualcomm chips.
config PHY_QCOM_QUSB2
tristate "Qualcomm QUSB2 PHY Driver"
depends on OF && (ARCH_QCOM || COMPILE_TEST)
depends on NVMEM || !NVMEM
select GENERIC_PHY
help
Enable this to support the HighSpeed QUSB2 PHY transceiver for USB
controllers on Qualcomm chips. This driver supports the high-speed
PHY which is usually paired with either the ChipIdea or Synopsys DWC3
USB IPs on MSM SOCs.
config PHY_QCOM_UFS
tristate "Qualcomm UFS PHY driver"
depends on OF && ARCH_QCOM
select GENERIC_PHY
help
Support for UFS PHY on QCOM chipsets.
config PHY_QCOM_USB_HS
tristate "Qualcomm USB HS PHY module"
depends on USB_ULPI_BUS
depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
select GENERIC_PHY
help
Support for the USB high-speed ULPI compliant phy on Qualcomm
chipsets.
config PHY_QCOM_USB_HSIC
tristate "Qualcomm USB HSIC ULPI PHY module"
depends on USB_ULPI_BUS
select GENERIC_PHY
help
Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.
config PHY_TUSB1210
tristate "TI TUSB1210 ULPI PHY module"
depends on USB_ULPI_BUS
select GENERIC_PHY
help
Support for TI TUSB1210 USB ULPI PHY.
config PHY_BRCM_SATA
tristate "Broadcom SATA PHY driver"
depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST
depends on OF
select GENERIC_PHY
default ARCH_BCM_IPROC
help
Enable this to support the Broadcom SATA PHY.
If unsure, say N.
config PHY_CYGNUS_PCIE
tristate "Broadcom Cygnus PCIe PHY driver"
depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST)
select GENERIC_PHY
default ARCH_BCM_CYGNUS
help
Enable this to support the Broadcom Cygnus PCIe PHY.
If unsure, say N.
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig"
source "drivers/phy/hisilicon/Kconfig"
source "drivers/phy/marvell/Kconfig"
source "drivers/phy/motorola/Kconfig"
source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"
source "drivers/phy/st/Kconfig"
source "drivers/phy/tegra/Kconfig"
config PHY_NS2_PCIE
tristate "Broadcom Northstar2 PCIe PHY driver"
depends on OF && MDIO_BUS_MUX_BCM_IPROC
select GENERIC_PHY
default ARCH_BCM_IPROC
help
Enable this to support the Broadcom Northstar2 PCIe PHY.
If unsure, say N.
config PHY_MESON8B_USB2
tristate "Meson8b and GXBB USB2 PHY driver"
default ARCH_MESON
depends on OF && (ARCH_MESON || COMPILE_TEST)
depends on USB_SUPPORT
select USB_COMMON
select GENERIC_PHY
help
Enable this to support the Meson USB2 PHYs found in Meson8b
and GXBB SoCs.
If unsure, say N.
source "drivers/phy/ti/Kconfig"
endmenu

View File

@ -3,64 +3,21 @@
#
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o
obj-$(CONFIG_PHY_BCM_NS_USB3) += phy-bcm-ns-usb3.o
obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o
obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o
obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o
obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o
obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
phy-exynos-usb2-y += phy-samsung-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
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_EXYNOS_PCIE) += phy-exynos-pcie.o
obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.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
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o
obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o
obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
obj-$(CONFIG_ARCH_SUNXI) += allwinner/
obj-$(CONFIG_ARCH_MESON) += amlogic/
obj-$(CONFIG_ARCH_RENESAS) += renesas/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += broadcom/ \
hisilicon/ \
marvell/ \
motorola/ \
qualcomm/ \
samsung/ \
st/ \
ti/

View File

@ -0,0 +1,31 @@
#
# Phy drivers for Allwinner platforms
#
config PHY_SUN4I_USB
tristate "Allwinner sunxi SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
depends on RESET_CONTROLLER
depends on EXTCON
depends on POWER_SUPPLY
depends on USB_SUPPORT
select GENERIC_PHY
select USB_COMMON
help
Enable this to support the transceiver that is part of Allwinner
sunxi SoCs.
This driver controls the entire USB PHY block, both the USB OTG
parts, as well as the 2 regular USB 2 host PHYs.
config PHY_SUN9I_USB
tristate "Allwinner sun9i SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
depends on RESET_CONTROLLER
depends on USB_SUPPORT
select USB_COMMON
select GENERIC_PHY
help
Enable this to support the transceiver that is part of Allwinner
sun9i SoCs.
This driver controls each individual USB 2 host PHY.

View File

@ -0,0 +1,2 @@
obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o

View File

@ -0,0 +1,27 @@
#
# Phy drivers for Amlogic platforms
#
config PHY_MESON8B_USB2
tristate "Meson8, Meson8b and GXBB USB2 PHY driver"
default ARCH_MESON
depends on OF && (ARCH_MESON || COMPILE_TEST)
depends on USB_SUPPORT
select USB_COMMON
select GENERIC_PHY
help
Enable this to support the Meson USB2 PHYs found in Meson8,
Meson8b and GXBB SoCs.
If unsure, say N.
config PHY_MESON_GXL_USB2
tristate "Meson GXL and GXM USB2 PHY drivers"
default ARCH_MESON
depends on OF && (ARCH_MESON || COMPILE_TEST)
depends on USB_SUPPORT
select USB_COMMON
select GENERIC_PHY
select REGMAP_MMIO
help
Enable this to support the Meson USB2 PHYs found in Meson
GXL and GXM SoCs.
If unsure, say N.

View File

@ -0,0 +1,2 @@
obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
obj-$(CONFIG_PHY_MESON_GXL_USB2) += phy-meson-gxl-usb2.o

View File

@ -0,0 +1,273 @@
/*
* Meson GXL and GXM USB2 PHY driver
*
* Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/usb/of.h>
/* bits [31:27] are read-only */
#define U2P_R0 0x0
#define U2P_R0_BYPASS_SEL BIT(0)
#define U2P_R0_BYPASS_DM_EN BIT(1)
#define U2P_R0_BYPASS_DP_EN BIT(2)
#define U2P_R0_TXBITSTUFF_ENH BIT(3)
#define U2P_R0_TXBITSTUFF_EN BIT(4)
#define U2P_R0_DM_PULLDOWN BIT(5)
#define U2P_R0_DP_PULLDOWN BIT(6)
#define U2P_R0_DP_VBUS_VLD_EXT_SEL BIT(7)
#define U2P_R0_DP_VBUS_VLD_EXT BIT(8)
#define U2P_R0_ADP_PRB_EN BIT(9)
#define U2P_R0_ADP_DISCHARGE BIT(10)
#define U2P_R0_ADP_CHARGE BIT(11)
#define U2P_R0_DRV_VBUS BIT(12)
#define U2P_R0_ID_PULLUP BIT(13)
#define U2P_R0_LOOPBACK_EN_B BIT(14)
#define U2P_R0_OTG_DISABLE BIT(15)
#define U2P_R0_COMMON_ONN BIT(16)
#define U2P_R0_FSEL_MASK GENMASK(19, 17)
#define U2P_R0_REF_CLK_SEL_MASK GENMASK(21, 20)
#define U2P_R0_POWER_ON_RESET BIT(22)
#define U2P_R0_V_ATE_TEST_EN_B_MASK GENMASK(24, 23)
#define U2P_R0_ID_SET_ID_DQ BIT(25)
#define U2P_R0_ATE_RESET BIT(26)
#define U2P_R0_FSV_MINUS BIT(27)
#define U2P_R0_FSV_PLUS BIT(28)
#define U2P_R0_BYPASS_DM_DATA BIT(29)
#define U2P_R0_BYPASS_DP_DATA BIT(30)
#define U2P_R1 0x4
#define U2P_R1_BURN_IN_TEST BIT(0)
#define U2P_R1_ACA_ENABLE BIT(1)
#define U2P_R1_DCD_ENABLE BIT(2)
#define U2P_R1_VDAT_SRC_EN_B BIT(3)
#define U2P_R1_VDAT_DET_EN_B BIT(4)
#define U2P_R1_CHARGES_SEL BIT(5)
#define U2P_R1_TX_PREEMP_PULSE_TUNE BIT(6)
#define U2P_R1_TX_PREEMP_AMP_TUNE_MASK GENMASK(8, 7)
#define U2P_R1_TX_RES_TUNE_MASK GENMASK(10, 9)
#define U2P_R1_TX_RISE_TUNE_MASK GENMASK(12, 11)
#define U2P_R1_TX_VREF_TUNE_MASK GENMASK(16, 13)
#define U2P_R1_TX_FSLS_TUNE_MASK GENMASK(20, 17)
#define U2P_R1_TX_HSXV_TUNE_MASK GENMASK(22, 21)
#define U2P_R1_OTG_TUNE_MASK GENMASK(25, 23)
#define U2P_R1_SQRX_TUNE_MASK GENMASK(28, 26)
#define U2P_R1_COMP_DIS_TUNE_MASK GENMASK(31, 29)
/* bits [31:14] are read-only */
#define U2P_R2 0x8
#define U2P_R2_DATA_IN_MASK GENMASK(3, 0)
#define U2P_R2_DATA_IN_EN_MASK GENMASK(7, 4)
#define U2P_R2_ADDR_MASK GENMASK(11, 8)
#define U2P_R2_DATA_OUT_SEL BIT(12)
#define U2P_R2_CLK BIT(13)
#define U2P_R2_DATA_OUT_MASK GENMASK(17, 14)
#define U2P_R2_ACA_PIN_RANGE_C BIT(18)
#define U2P_R2_ACA_PIN_RANGE_B BIT(19)
#define U2P_R2_ACA_PIN_RANGE_A BIT(20)
#define U2P_R2_ACA_PIN_GND BIT(21)
#define U2P_R2_ACA_PIN_FLOAT BIT(22)
#define U2P_R2_CHARGE_DETECT BIT(23)
#define U2P_R2_DEVICE_SESSION_VALID BIT(24)
#define U2P_R2_ADP_PROBE BIT(25)
#define U2P_R2_ADP_SENSE BIT(26)
#define U2P_R2_SESSION_END BIT(27)
#define U2P_R2_VBUS_VALID BIT(28)
#define U2P_R2_B_VALID BIT(29)
#define U2P_R2_A_VALID BIT(30)
#define U2P_R2_ID_DIG BIT(31)
#define U2P_R3 0xc
#define RESET_COMPLETE_TIME 500
struct phy_meson_gxl_usb2_priv {
struct regmap *regmap;
enum phy_mode mode;
int is_enabled;
};
static const struct regmap_config phy_meson_gxl_usb2_regmap_conf = {
.reg_bits = 8,
.val_bits = 32,
.reg_stride = 4,
.max_register = U2P_R3,
};
static int phy_meson_gxl_usb2_reset(struct phy *phy)
{
struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
if (priv->is_enabled) {
/* reset the PHY and wait until settings are stabilized */
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
U2P_R0_POWER_ON_RESET);
udelay(RESET_COMPLETE_TIME);
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
0);
udelay(RESET_COMPLETE_TIME);
}
return 0;
}
static int phy_meson_gxl_usb2_set_mode(struct phy *phy, enum phy_mode mode)
{
struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
switch (mode) {
case PHY_MODE_USB_HOST:
case PHY_MODE_USB_OTG:
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
U2P_R0_DM_PULLDOWN);
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
U2P_R0_DP_PULLDOWN);
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, 0);
break;
case PHY_MODE_USB_DEVICE:
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
0);
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
0);
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP,
U2P_R0_ID_PULLUP);
break;
default:
return -EINVAL;
}
phy_meson_gxl_usb2_reset(phy);
priv->mode = mode;
return 0;
}
static int phy_meson_gxl_usb2_power_off(struct phy *phy)
{
struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
priv->is_enabled = 0;
/* power off the PHY by putting it into reset mode */
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
U2P_R0_POWER_ON_RESET);
return 0;
}
static int phy_meson_gxl_usb2_power_on(struct phy *phy)
{
struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
int ret;
priv->is_enabled = 1;
/* power on the PHY by taking it out of reset mode */
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0);
ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode);
if (ret) {
phy_meson_gxl_usb2_power_off(phy);
dev_err(&phy->dev, "Failed to initialize PHY with mode %d\n",
priv->mode);
return ret;
}
return 0;
}
static const struct phy_ops phy_meson_gxl_usb2_ops = {
.power_on = phy_meson_gxl_usb2_power_on,
.power_off = phy_meson_gxl_usb2_power_off,
.set_mode = phy_meson_gxl_usb2_set_mode,
.reset = phy_meson_gxl_usb2_reset,
.owner = THIS_MODULE,
};
static int phy_meson_gxl_usb2_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
struct resource *res;
struct phy_meson_gxl_usb2_priv *priv;
struct phy *phy;
void __iomem *base;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
platform_set_drvdata(pdev, priv);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
switch (of_usb_get_dr_mode_by_phy(dev->of_node, -1)) {
case USB_DR_MODE_PERIPHERAL:
priv->mode = PHY_MODE_USB_DEVICE;
break;
case USB_DR_MODE_OTG:
priv->mode = PHY_MODE_USB_OTG;
break;
case USB_DR_MODE_HOST:
default:
priv->mode = PHY_MODE_USB_HOST;
break;
}
priv->regmap = devm_regmap_init_mmio(dev, base,
&phy_meson_gxl_usb2_regmap_conf);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
phy = devm_phy_create(dev, NULL, &phy_meson_gxl_usb2_ops);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(phy);
}
phy_set_drvdata(phy, priv);
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 phy_meson_gxl_usb2_of_match[] = {
{ .compatible = "amlogic,meson-gxl-usb2-phy", },
{ },
};
MODULE_DEVICE_TABLE(of, phy_meson_gxl_usb2_of_match);
static struct platform_driver phy_meson_gxl_usb2_driver = {
.probe = phy_meson_gxl_usb2_probe,
.driver = {
.name = "phy-meson-gxl-usb2",
.of_match_table = phy_meson_gxl_usb2_of_match,
},
};
module_platform_driver(phy_meson_gxl_usb2_driver);
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
MODULE_DESCRIPTION("Meson GXL and GXM USB2 PHY driver");
MODULE_LICENSE("GPL v2");

View File

@ -1,5 +1,5 @@
/*
* Meson8b and GXBB USB2 PHY driver
* Meson8, Meson8b and GXBB USB2 PHY driver
*
* Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
*
@ -266,6 +266,7 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev)
}
static const struct of_device_id phy_meson8b_usb2_of_match[] = {
{ .compatible = "amlogic,meson8-usb2-phy", },
{ .compatible = "amlogic,meson8b-usb2-phy", },
{ .compatible = "amlogic,meson-gxbb-usb2-phy", },
{ },
@ -282,5 +283,5 @@ static struct platform_driver phy_meson8b_usb2_driver = {
module_platform_driver(phy_meson8b_usb2_driver);
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
MODULE_DESCRIPTION("Meson8b and GXBB USB2 PHY driver");
MODULE_DESCRIPTION("Meson8, Meson8b and GXBB USB2 PHY driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,69 @@
#
# Phy drivers for Broadcom platforms
#
config PHY_CYGNUS_PCIE
tristate "Broadcom Cygnus PCIe PHY driver"
depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST)
select GENERIC_PHY
default ARCH_BCM_CYGNUS
help
Enable this to support the Broadcom Cygnus PCIe PHY.
If unsure, say N.
config BCM_KONA_USB2_PHY
tristate "Broadcom Kona USB2 PHY Driver"
depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support the Broadcom Kona USB 2.0 PHY.
config PHY_BCM_NS_USB2
tristate "Broadcom Northstar USB 2.0 PHY Driver"
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on HAS_IOMEM && OF
select GENERIC_PHY
help
Enable this to support Broadcom USB 2.0 PHY connected to the USB
controller on Northstar family.
config PHY_BCM_NS_USB3
tristate "Broadcom Northstar USB 3.0 PHY Driver"
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on HAS_IOMEM && OF
select GENERIC_PHY
select MDIO_DEVICE
help
Enable this to support Broadcom USB 3.0 PHY connected to the USB
controller on Northstar family.
config PHY_NS2_PCIE
tristate "Broadcom Northstar2 PCIe PHY driver"
depends on OF && MDIO_BUS_MUX_BCM_IPROC
select GENERIC_PHY
default ARCH_BCM_IPROC
help
Enable this to support the Broadcom Northstar2 PCIe PHY.
If unsure, say N.
config PHY_NS2_USB_DRD
tristate "Broadcom Northstar2 USB DRD PHY support"
depends on OF && (ARCH_BCM_IPROC || COMPILE_TEST)
select GENERIC_PHY
select EXTCON
default ARCH_BCM_IPROC
help
Enable this to support the Broadcom Northstar2 USB DRD PHY.
This driver initializes the PHY in either HOST or DEVICE mode.
The host or device configuration is read from device tree.
If unsure, say N.
config PHY_BRCM_SATA
tristate "Broadcom SATA PHY driver"
depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST
depends on OF
select GENERIC_PHY
default ARCH_BCM_IPROC
help
Enable this to support the Broadcom SATA PHY.
If unsure, say N.

View File

@ -0,0 +1,7 @@
obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o
obj-$(CONFIG_PHY_BCM_NS_USB3) += phy-bcm-ns-usb3.o
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
obj-$(CONFIG_PHY_NS2_USB_DRD) += phy-bcm-ns2-usbdrd.o
obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o

View File

@ -16,7 +16,9 @@
#include <linux/bcma/bcma.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
@ -52,7 +54,10 @@ struct bcm_ns_usb3 {
enum bcm_ns_family family;
void __iomem *dmp;
void __iomem *ccb_mii;
struct mdio_device *mdiodev;
struct phy *phy;
int (*phy_write)(struct bcm_ns_usb3 *usb3, u16 reg, u16 value);
};
static const struct of_device_id bcm_ns_usb3_id_table[] = {
@ -68,63 +73,16 @@ static const struct of_device_id bcm_ns_usb3_id_table[] = {
};
MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);
static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
u32 mask, u32 value, unsigned long timeout)
{
unsigned long deadline = jiffies + timeout;
u32 val;
do {
val = readl(addr);
if ((val & mask) == value)
return 0;
cpu_relax();
udelay(10);
} while (!time_after_eq(jiffies, deadline));
dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
return -EBUSY;
}
static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3)
{
return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL,
0x0100, 0x0000,
usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
}
static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
u16 value)
{
u32 tmp = 0;
int err;
err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
if (err < 0) {
dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
return err;
}
/* TODO: Use a proper MDIO bus layer */
tmp |= 0x58020000; /* Magic value for MDIO PHY write */
tmp |= reg << 18;
tmp |= value;
writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
return 0;
return usb3->phy_write(usb3, reg, value);
}
static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
{
int err;
/* Enable MDIO. Setting MDCDIV as 26 */
writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
/* Wait for MDIO? */
udelay(2);
/* USB3 PLL Block */
err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
BCM_NS_USB3_PHY_PLL30_BLOCK);
@ -143,9 +101,6 @@ static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
/* Deaaserting PLL Reset */
bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0x8000);
/* Waiting MII Mgt interface idle */
bcm_ns_usb3_mii_mng_wait_idle(usb3);
/* Deasserting USB3 system reset */
writel(0, usb3->dmp + BCMA_RESET_CTL);
@ -169,9 +124,6 @@ static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
/* Enabling SSC */
bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
/* Waiting MII Mgt interface idle */
bcm_ns_usb3_mii_mng_wait_idle(usb3);
return 0;
}
@ -179,12 +131,6 @@ static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
{
int err;
/* Enable MDIO. Setting MDCDIV as 26 */
writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
/* Wait for MDIO? */
udelay(2);
/* PLL30 block */
err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
BCM_NS_USB3_PHY_PLL30_BLOCK);
@ -205,9 +151,6 @@ static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
/* Waiting MII Mgt interface idle */
bcm_ns_usb3_mii_mng_wait_idle(usb3);
/* Deasserting USB3 system reset */
writel(0, usb3->dmp + BCMA_RESET_CTL);
@ -242,6 +185,128 @@ static const struct phy_ops ops = {
.owner = THIS_MODULE,
};
/**************************************************
* MDIO driver code
**************************************************/
static int bcm_ns_usb3_mdiodev_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
u16 value)
{
struct mdio_device *mdiodev = usb3->mdiodev;
return mdiobus_write(mdiodev->bus, mdiodev->addr, reg, value);
}
static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev)
{
struct device *dev = &mdiodev->dev;
const struct of_device_id *of_id;
struct phy_provider *phy_provider;
struct device_node *syscon_np;
struct bcm_ns_usb3 *usb3;
struct resource res;
int err;
usb3 = devm_kzalloc(dev, sizeof(*usb3), GFP_KERNEL);
if (!usb3)
return -ENOMEM;
usb3->dev = dev;
usb3->mdiodev = mdiodev;
of_id = of_match_device(bcm_ns_usb3_id_table, dev);
if (!of_id)
return -EINVAL;
usb3->family = (enum bcm_ns_family)of_id->data;
syscon_np = of_parse_phandle(dev->of_node, "usb3-dmp-syscon", 0);
err = of_address_to_resource(syscon_np, 0, &res);
of_node_put(syscon_np);
if (err)
return err;
usb3->dmp = devm_ioremap_resource(dev, &res);
if (IS_ERR(usb3->dmp)) {
dev_err(dev, "Failed to map DMP regs\n");
return PTR_ERR(usb3->dmp);
}
usb3->phy_write = bcm_ns_usb3_mdiodev_phy_write;
usb3->phy = devm_phy_create(dev, NULL, &ops);
if (IS_ERR(usb3->phy)) {
dev_err(dev, "Failed to create PHY\n");
return PTR_ERR(usb3->phy);
}
phy_set_drvdata(usb3->phy, usb3);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static struct mdio_driver bcm_ns_usb3_mdio_driver = {
.mdiodrv = {
.driver = {
.name = "bcm_ns_mdio_usb3",
.of_match_table = bcm_ns_usb3_id_table,
},
},
.probe = bcm_ns_usb3_mdio_probe,
};
/**************************************************
* Platform driver code
**************************************************/
static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
u32 mask, u32 value, unsigned long timeout)
{
unsigned long deadline = jiffies + timeout;
u32 val;
do {
val = readl(addr);
if ((val & mask) == value)
return 0;
cpu_relax();
udelay(10);
} while (!time_after_eq(jiffies, deadline));
dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
return -EBUSY;
}
static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3)
{
return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL,
0x0100, 0x0000,
usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
}
static int bcm_ns_usb3_platform_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
u16 value)
{
u32 tmp = 0;
int err;
err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
if (err < 0) {
dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
return err;
}
/* TODO: Use a proper MDIO bus layer */
tmp |= 0x58020000; /* Magic value for MDIO PHY write */
tmp |= reg << 18;
tmp |= value;
writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
return bcm_ns_usb3_mii_mng_wait_idle(usb3);
}
static int bcm_ns_usb3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -275,6 +340,14 @@ static int bcm_ns_usb3_probe(struct platform_device *pdev)
return PTR_ERR(usb3->ccb_mii);
}
/* Enable MDIO. Setting MDCDIV as 26 */
writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
/* Wait for MDIO? */
udelay(2);
usb3->phy_write = bcm_ns_usb3_platform_phy_write;
usb3->phy = devm_phy_create(dev, NULL, &ops);
if (IS_ERR(usb3->phy)) {
dev_err(dev, "Failed to create PHY\n");
@ -298,6 +371,35 @@ static struct platform_driver bcm_ns_usb3_driver = {
.of_match_table = bcm_ns_usb3_id_table,
},
};
module_platform_driver(bcm_ns_usb3_driver);
static int __init bcm_ns_usb3_module_init(void)
{
int err;
/*
* For backward compatibility we register as MDIO and platform driver.
* After getting MDIO binding commonly used (e.g. switching all DT files
* to use it) we should deprecate the old binding and eventually drop
* support for it.
*/
err = mdio_driver_register(&bcm_ns_usb3_mdio_driver);
if (err)
return err;
err = platform_driver_register(&bcm_ns_usb3_driver);
if (err)
mdio_driver_unregister(&bcm_ns_usb3_mdio_driver);
return err;
}
module_init(bcm_ns_usb3_module_init);
static void __exit bcm_ns_usb3_module_exit(void)
{
platform_driver_unregister(&bcm_ns_usb3_driver);
mdio_driver_unregister(&bcm_ns_usb3_mdio_driver);
}
module_exit(bcm_ns_usb3_module_exit)
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,437 @@
/*
* Copyright (C) 2017 Broadcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/extcon.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/mfd/syscon.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/slab.h>
#include <linux/workqueue.h>
#define ICFG_DRD_AFE 0x0
#define ICFG_MISC_STAT 0x18
#define ICFG_DRD_P0CTL 0x1C
#define ICFG_STRAP_CTRL 0x20
#define ICFG_FSM_CTRL 0x24
#define ICFG_DEV_BIT BIT(2)
#define IDM_RST_BIT BIT(0)
#define AFE_CORERDY_VDDC BIT(18)
#define PHY_PLL_RESETB BIT(15)
#define PHY_RESETB BIT(14)
#define PHY_PLL_LOCK BIT(0)
#define DRD_DEV_MODE BIT(20)
#define OHCI_OVRCUR_POL BIT(11)
#define ICFG_OFF_MODE BIT(6)
#define PLL_LOCK_RETRY 1000
#define EVT_DEVICE 0
#define EVT_HOST 1
#define DRD_HOST_MODE (BIT(2) | BIT(3))
#define DRD_DEVICE_MODE (BIT(4) | BIT(5))
#define DRD_HOST_VAL 0x803
#define DRD_DEV_VAL 0x807
#define GPIO_DELAY 20
struct ns2_phy_data;
struct ns2_phy_driver {
void __iomem *icfgdrd_regs;
void __iomem *idmdrd_rst_ctrl;
void __iomem *crmu_usb2_ctrl;
void __iomem *usb2h_strap_reg;
struct ns2_phy_data *data;
struct extcon_dev *edev;
struct gpio_desc *vbus_gpiod;
struct gpio_desc *id_gpiod;
int id_irq;
int vbus_irq;
unsigned long debounce_jiffies;
struct delayed_work wq_extcon;
};
struct ns2_phy_data {
struct ns2_phy_driver *driver;
struct phy *phy;
int new_state;
};
static const unsigned int usb_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
EXTCON_NONE,
};
static inline int pll_lock_stat(u32 usb_reg, int reg_mask,
struct ns2_phy_driver *driver)
{
int retry = PLL_LOCK_RETRY;
u32 val;
do {
udelay(1);
val = readl(driver->icfgdrd_regs + usb_reg);
if (val & reg_mask)
return 0;
} while (--retry > 0);
return -EBUSY;
}
static int ns2_drd_phy_init(struct phy *phy)
{
struct ns2_phy_data *data = phy_get_drvdata(phy);
struct ns2_phy_driver *driver = data->driver;
u32 val;
val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
if (data->new_state == EVT_HOST) {
val &= ~DRD_DEVICE_MODE;
val |= DRD_HOST_MODE;
} else {
val &= ~DRD_HOST_MODE;
val |= DRD_DEVICE_MODE;
}
writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
return 0;
}
static int ns2_drd_phy_poweroff(struct phy *phy)
{
struct ns2_phy_data *data = phy_get_drvdata(phy);
struct ns2_phy_driver *driver = data->driver;
u32 val;
val = readl(driver->crmu_usb2_ctrl);
val &= ~AFE_CORERDY_VDDC;
writel(val, driver->crmu_usb2_ctrl);
val = readl(driver->crmu_usb2_ctrl);
val &= ~DRD_DEV_MODE;
writel(val, driver->crmu_usb2_ctrl);
/* Disable Host and Device Mode */
val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE | ICFG_OFF_MODE);
writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
return 0;
}
static int ns2_drd_phy_poweron(struct phy *phy)
{
struct ns2_phy_data *data = phy_get_drvdata(phy);
struct ns2_phy_driver *driver = data->driver;
u32 extcon_event = data->new_state;
int ret;
u32 val;
if (extcon_event == EVT_DEVICE) {
writel(DRD_DEV_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
val = readl(driver->idmdrd_rst_ctrl);
val &= ~IDM_RST_BIT;
writel(val, driver->idmdrd_rst_ctrl);
val = readl(driver->crmu_usb2_ctrl);
val |= (AFE_CORERDY_VDDC | DRD_DEV_MODE);
writel(val, driver->crmu_usb2_ctrl);
/* Bring PHY and PHY_PLL out of Reset */
val = readl(driver->crmu_usb2_ctrl);
val |= (PHY_PLL_RESETB | PHY_RESETB);
writel(val, driver->crmu_usb2_ctrl);
ret = pll_lock_stat(ICFG_MISC_STAT, PHY_PLL_LOCK, driver);
if (ret < 0) {
dev_err(&phy->dev, "Phy PLL lock failed\n");
return ret;
}
} else {
writel(DRD_HOST_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
val = readl(driver->crmu_usb2_ctrl);
val |= AFE_CORERDY_VDDC;
writel(val, driver->crmu_usb2_ctrl);
ret = pll_lock_stat(ICFG_MISC_STAT, PHY_PLL_LOCK, driver);
if (ret < 0) {
dev_err(&phy->dev, "Phy PLL lock failed\n");
return ret;
}
val = readl(driver->idmdrd_rst_ctrl);
val &= ~IDM_RST_BIT;
writel(val, driver->idmdrd_rst_ctrl);
/* port over current Polarity */
val = readl(driver->usb2h_strap_reg);
val |= OHCI_OVRCUR_POL;
writel(val, driver->usb2h_strap_reg);
}
return 0;
}
static void connect_change(struct ns2_phy_driver *driver)
{
u32 extcon_event;
u32 val;
extcon_event = driver->data->new_state;
val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
switch (extcon_event) {
case EVT_DEVICE:
val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE);
writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
val = (val & ~DRD_HOST_MODE) | DRD_DEVICE_MODE;
writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
val = readl(driver->icfgdrd_regs + ICFG_DRD_P0CTL);
val |= ICFG_DEV_BIT;
writel(val, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
break;
case EVT_HOST:
val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE);
writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
val = (val & ~DRD_DEVICE_MODE) | DRD_HOST_MODE;
writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
val = readl(driver->usb2h_strap_reg);
val |= OHCI_OVRCUR_POL;
writel(val, driver->usb2h_strap_reg);
val = readl(driver->icfgdrd_regs + ICFG_DRD_P0CTL);
val &= ~ICFG_DEV_BIT;
writel(val, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
break;
default:
pr_err("Invalid extcon event\n");
break;
}
}
static void extcon_work(struct work_struct *work)
{
struct ns2_phy_driver *driver;
int vbus;
int id;
driver = container_of(to_delayed_work(work),
struct ns2_phy_driver, wq_extcon);
id = gpiod_get_value_cansleep(driver->id_gpiod);
vbus = gpiod_get_value_cansleep(driver->vbus_gpiod);
if (!id && vbus) { /* Host connected */
extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, true);
pr_debug("Host cable connected\n");
driver->data->new_state = EVT_HOST;
connect_change(driver);
} else if (id && !vbus) { /* Disconnected */
extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, false);
extcon_set_cable_state_(driver->edev, EXTCON_USB, false);
pr_debug("Cable disconnected\n");
} else if (id && vbus) { /* Device connected */
extcon_set_cable_state_(driver->edev, EXTCON_USB, true);
pr_debug("Device cable connected\n");
driver->data->new_state = EVT_DEVICE;
connect_change(driver);
}
}
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{
struct ns2_phy_driver *driver = dev_id;
queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
driver->debounce_jiffies);
return IRQ_HANDLED;
}
static struct phy_ops ops = {
.init = ns2_drd_phy_init,
.power_on = ns2_drd_phy_poweron,
.power_off = ns2_drd_phy_poweroff,
.owner = THIS_MODULE,
};
static const struct of_device_id ns2_drd_phy_dt_ids[] = {
{ .compatible = "brcm,ns2-drd-phy", },
{ }
};
MODULE_DEVICE_TABLE(of, ns2_drd_phy_dt_ids);
static int ns2_drd_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct ns2_phy_driver *driver;
struct ns2_phy_data *data;
struct resource *res;
int ret;
u32 val;
driver = devm_kzalloc(dev, sizeof(struct ns2_phy_driver),
GFP_KERNEL);
if (!driver)
return -ENOMEM;
driver->data = devm_kzalloc(dev, sizeof(struct ns2_phy_data),
GFP_KERNEL);
if (!driver->data)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icfg");
driver->icfgdrd_regs = devm_ioremap_resource(dev, res);
if (IS_ERR(driver->icfgdrd_regs))
return PTR_ERR(driver->icfgdrd_regs);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rst-ctrl");
driver->idmdrd_rst_ctrl = devm_ioremap_resource(dev, res);
if (IS_ERR(driver->idmdrd_rst_ctrl))
return PTR_ERR(driver->idmdrd_rst_ctrl);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crmu-ctrl");
driver->crmu_usb2_ctrl = devm_ioremap_resource(dev, res);
if (IS_ERR(driver->crmu_usb2_ctrl))
return PTR_ERR(driver->crmu_usb2_ctrl);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb2-strap");
driver->usb2h_strap_reg = devm_ioremap_resource(dev, res);
if (IS_ERR(driver->usb2h_strap_reg))
return PTR_ERR(driver->usb2h_strap_reg);
/* create extcon */
driver->id_gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
if (IS_ERR(driver->id_gpiod)) {
dev_err(dev, "failed to get ID GPIO\n");
return PTR_ERR(driver->id_gpiod);
}
driver->vbus_gpiod = devm_gpiod_get(&pdev->dev, "vbus", GPIOD_IN);
if (IS_ERR(driver->vbus_gpiod)) {
dev_err(dev, "failed to get VBUS GPIO\n");
return PTR_ERR(driver->vbus_gpiod);
}
driver->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
if (IS_ERR(driver->edev)) {
dev_err(dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
ret = devm_extcon_dev_register(dev, driver->edev);
if (ret < 0) {
dev_err(dev, "failed to register extcon device\n");
return ret;
}
ret = gpiod_set_debounce(driver->id_gpiod, GPIO_DELAY * 1000);
if (ret < 0)
driver->debounce_jiffies = msecs_to_jiffies(GPIO_DELAY);
INIT_DELAYED_WORK(&driver->wq_extcon, extcon_work);
driver->id_irq = gpiod_to_irq(driver->id_gpiod);
if (driver->id_irq < 0) {
dev_err(dev, "failed to get ID IRQ\n");
return driver->id_irq;
}
driver->vbus_irq = gpiod_to_irq(driver->vbus_gpiod);
if (driver->vbus_irq < 0) {
dev_err(dev, "failed to get ID IRQ\n");
return driver->vbus_irq;
}
ret = devm_request_irq(dev, driver->id_irq, gpio_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"usb_id", driver);
if (ret < 0) {
dev_err(dev, "failed to request handler for ID IRQ\n");
return ret;
}
ret = devm_request_irq(dev, driver->vbus_irq, gpio_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"usb_vbus", driver);
if (ret < 0) {
dev_err(dev, "failed to request handler for VBUS IRQ\n");
return ret;
}
dev_set_drvdata(dev, driver);
/* Shutdown all ports. They can be powered up as required */
val = readl(driver->crmu_usb2_ctrl);
val &= ~(AFE_CORERDY_VDDC | PHY_RESETB);
writel(val, driver->crmu_usb2_ctrl);
data = driver->data;
data->phy = devm_phy_create(dev, dev->of_node, &ops);
if (IS_ERR(data->phy)) {
dev_err(dev, "Failed to create usb drd phy\n");
return PTR_ERR(data->phy);
}
data->driver = driver;
phy_set_drvdata(data->phy, data);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
dev_err(dev, "Failed to register as phy provider\n");
return PTR_ERR(phy_provider);
}
platform_set_drvdata(pdev, driver);
dev_info(dev, "Registered NS2 DRD Phy device\n");
queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
driver->debounce_jiffies);
return 0;
}
static struct platform_driver ns2_drd_phy_driver = {
.probe = ns2_drd_phy_probe,
.driver = {
.name = "bcm-ns2-usbphy",
.of_match_table = of_match_ptr(ns2_drd_phy_dt_ids),
},
};
module_platform_driver(ns2_drd_phy_driver);
MODULE_ALIAS("platform:bcm-ns2-drd-phy");
MODULE_AUTHOR("Broadcom");
MODULE_DESCRIPTION("Broadcom NS2 USB2 PHY driver");
MODULE_LICENSE("GPL v2");

View File

@ -46,6 +46,7 @@ enum brcm_sata_phy_version {
BRCM_SATA_PHY_STB_40NM,
BRCM_SATA_PHY_IPROC_NS2,
BRCM_SATA_PHY_IPROC_NSP,
BRCM_SATA_PHY_IPROC_SR,
};
struct brcm_sata_port {
@ -81,12 +82,17 @@ enum sata_phy_regs {
PLL_ACTRL2 = 0x8b,
PLL_ACTRL2_SELDIV_MASK = 0x1f,
PLL_ACTRL2_SELDIV_SHIFT = 9,
PLL_ACTRL6 = 0x86,
PLL1_REG_BANK = 0x060,
PLL1_ACTRL2 = 0x82,
PLL1_ACTRL3 = 0x83,
PLL1_ACTRL4 = 0x84,
TX_REG_BANK = 0x070,
TX_ACTRL0 = 0x80,
TX_ACTRL0_TXPOL_FLIP = BIT(6),
OOB_REG_BANK = 0x150,
OOB1_REG_BANK = 0x160,
OOB_CTRL1 = 0x80,
@ -347,6 +353,68 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port)
return 0;
}
/* SR PHY PLL0 registers */
#define SR_PLL0_ACTRL6_MAGIC 0xa
/* SR PHY PLL1 registers */
#define SR_PLL1_ACTRL2_MAGIC 0x32
#define SR_PLL1_ACTRL3_MAGIC 0x2
#define SR_PLL1_ACTRL4_MAGIC 0x3e8
static int brcm_sr_sata_init(struct brcm_sata_port *port)
{
struct brcm_sata_phy *priv = port->phy_priv;
struct device *dev = port->phy_priv->dev;
void __iomem *base = priv->phy_base;
unsigned int val, try;
/* Configure PHY PLL register bank 1 */
val = SR_PLL1_ACTRL2_MAGIC;
brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
val = SR_PLL1_ACTRL3_MAGIC;
brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
val = SR_PLL1_ACTRL4_MAGIC;
brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
/* Configure PHY PLL register bank 0 */
val = SR_PLL0_ACTRL6_MAGIC;
brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL6, 0x0, val);
/* Wait for PHY PLL lock by polling pll_lock bit */
try = 50;
do {
val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
BLOCK0_XGXSSTATUS);
if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
break;
msleep(20);
try--;
} while (try);
if ((val & BLOCK0_XGXSSTATUS_PLL_LOCK) == 0) {
/* PLL did not lock; give up */
dev_err(dev, "port%d PLL did not lock\n", port->portnum);
return -ETIMEDOUT;
}
/* Invert Tx polarity */
brcm_sata_phy_wr(base, TX_REG_BANK, TX_ACTRL0,
~TX_ACTRL0_TXPOL_FLIP, TX_ACTRL0_TXPOL_FLIP);
/* Configure OOB control to handle 100MHz reference clock */
val = ((0xc << OOB_CTRL1_BURST_MAX_SHIFT) |
(0x4 << OOB_CTRL1_BURST_MIN_SHIFT) |
(0x8 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT) |
(0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT));
brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
val = ((0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT) |
(0x2 << OOB_CTRL2_BURST_CNT_SHIFT) |
(0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT));
brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
return 0;
}
static int brcm_sata_phy_init(struct phy *phy)
{
int rc;
@ -363,6 +431,9 @@ static int brcm_sata_phy_init(struct phy *phy)
case BRCM_SATA_PHY_IPROC_NSP:
rc = brcm_nsp_sata_init(port);
break;
case BRCM_SATA_PHY_IPROC_SR:
rc = brcm_sr_sata_init(port);
break;
default:
rc = -ENODEV;
}
@ -384,6 +455,8 @@ static const struct of_device_id brcm_sata_phy_of_match[] = {
.data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
{ .compatible = "brcm,iproc-nsp-sata-phy",
.data = (void *)BRCM_SATA_PHY_IPROC_NSP },
{ .compatible = "brcm,iproc-sr-sata-phy",
.data = (void *)BRCM_SATA_PHY_IPROC_SR },
{},
};
MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);

View File

@ -0,0 +1,20 @@
#
# Phy drivers for Hisilicon platforms
#
config PHY_HI6220_USB
tristate "hi6220 USB PHY support"
depends on (ARCH_HISI && ARM64) || COMPILE_TEST
select GENERIC_PHY
select MFD_SYSCON
help
Enable this to support the HISILICON HI6220 USB PHY.
To compile this driver as a module, choose M here.
config PHY_HIX5HD2_SATA
tristate "HIX5HD2 SATA PHY Driver"
depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
select GENERIC_PHY
select MFD_SYSCON
help
Support for SATA PHY on Hisilicon hix5hd2 Soc.

View File

@ -0,0 +1,2 @@
obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o
obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o

View File

@ -0,0 +1,50 @@
#
# Phy drivers for Marvell platforms
#
config ARMADA375_USBCLUSTER_PHY
def_bool y
depends on MACH_ARMADA_375 || COMPILE_TEST
depends on OF && HAS_IOMEM
select GENERIC_PHY
config PHY_BERLIN_SATA
tristate "Marvell Berlin SATA PHY driver"
depends on ARCH_BERLIN && HAS_IOMEM && OF
select GENERIC_PHY
help
Enable this to support the SATA PHY on Marvell Berlin SoCs.
config PHY_BERLIN_USB
tristate "Marvell Berlin USB PHY Driver"
depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
select GENERIC_PHY
help
Enable this to support the USB PHY on Marvell Berlin SoCs.
config PHY_MVEBU_SATA
def_bool y
depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
depends on OF
select GENERIC_PHY
config PHY_PXA_28NM_HSIC
tristate "Marvell USB HSIC 28nm PHY Driver"
depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support Marvell USB HSIC PHY driver for Marvell
SoC. This driver will do the PHY initialization and shutdown.
The PHY driver will be used by Marvell ehci driver.
To compile this driver as a module, choose M here.
config PHY_PXA_28NM_USB2
tristate "Marvell USB 2.0 28nm PHY Driver"
depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support Marvell USB 2.0 PHY driver for Marvell
SoC. This driver will do the PHY initialization and shutdown.
The PHY driver will be used by Marvell udc/ehci/otg driver.
To compile this driver as a module, choose M here.

View File

@ -0,0 +1,6 @@
obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o

View File

@ -0,0 +1,12 @@
#
# Phy drivers for Motorola devices
#
config PHY_CPCAP_USB
tristate "CPCAP PMIC USB PHY driver"
depends on USB_SUPPORT && IIO
depends on USB_MUSB_HDRC || USB_MUSB_HDRC=n
select GENERIC_PHY
select USB_PHY
help
Enable this for USB to work on Motorola phones and tablets
such as Droid 4.

View File

@ -0,0 +1,5 @@
#
# Makefile for the phy drivers.
#
obj-$(CONFIG_PHY_CPCAP_USB) += phy-cpcap-usb.o

View File

@ -0,0 +1,676 @@
/*
* Motorola CPCAP PMIC USB PHY driver
* Copyright (C) 2017 Tony Lindgren <tony@atomide.com>
*
* Some parts based on earlier Motorola Linux kernel tree code in
* board-mapphone-usb.c and cpcap-usb-det.c:
* Copyright (C) 2007 - 2011 Motorola, 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 version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/atomic.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/iio/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/gpio/consumer.h>
#include <linux/mfd/motorola-cpcap.h>
#include <linux/phy/omap_usb.h>
#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
#include <linux/usb/musb.h>
/* CPCAP_REG_USBC1 register bits */
#define CPCAP_BIT_IDPULSE BIT(15)
#define CPCAP_BIT_ID100KPU BIT(14)
#define CPCAP_BIT_IDPUCNTRL BIT(13)
#define CPCAP_BIT_IDPU BIT(12)
#define CPCAP_BIT_IDPD BIT(11)
#define CPCAP_BIT_VBUSCHRGTMR3 BIT(10)
#define CPCAP_BIT_VBUSCHRGTMR2 BIT(9)
#define CPCAP_BIT_VBUSCHRGTMR1 BIT(8)
#define CPCAP_BIT_VBUSCHRGTMR0 BIT(7)
#define CPCAP_BIT_VBUSPU BIT(6)
#define CPCAP_BIT_VBUSPD BIT(5)
#define CPCAP_BIT_DMPD BIT(4)
#define CPCAP_BIT_DPPD BIT(3)
#define CPCAP_BIT_DM1K5PU BIT(2)
#define CPCAP_BIT_DP1K5PU BIT(1)
#define CPCAP_BIT_DP150KPU BIT(0)
/* CPCAP_REG_USBC2 register bits */
#define CPCAP_BIT_ZHSDRV1 BIT(15)
#define CPCAP_BIT_ZHSDRV0 BIT(14)
#define CPCAP_BIT_DPLLCLKREQ BIT(13)
#define CPCAP_BIT_SE0CONN BIT(12)
#define CPCAP_BIT_UARTTXTRI BIT(11)
#define CPCAP_BIT_UARTSWAP BIT(10)
#define CPCAP_BIT_UARTMUX1 BIT(9)
#define CPCAP_BIT_UARTMUX0 BIT(8)
#define CPCAP_BIT_ULPISTPLOW BIT(7)
#define CPCAP_BIT_TXENPOL BIT(6)
#define CPCAP_BIT_USBXCVREN BIT(5)
#define CPCAP_BIT_USBCNTRL BIT(4)
#define CPCAP_BIT_USBSUSPEND BIT(3)
#define CPCAP_BIT_EMUMODE2 BIT(2)
#define CPCAP_BIT_EMUMODE1 BIT(1)
#define CPCAP_BIT_EMUMODE0 BIT(0)
/* CPCAP_REG_USBC3 register bits */
#define CPCAP_BIT_SPARE_898_15 BIT(15)
#define CPCAP_BIT_IHSTX03 BIT(14)
#define CPCAP_BIT_IHSTX02 BIT(13)
#define CPCAP_BIT_IHSTX01 BIT(12)
#define CPCAP_BIT_IHSTX0 BIT(11)
#define CPCAP_BIT_IDPU_SPI BIT(10)
#define CPCAP_BIT_UNUSED_898_9 BIT(9)
#define CPCAP_BIT_VBUSSTBY_EN BIT(8)
#define CPCAP_BIT_VBUSEN_SPI BIT(7)
#define CPCAP_BIT_VBUSPU_SPI BIT(6)
#define CPCAP_BIT_VBUSPD_SPI BIT(5)
#define CPCAP_BIT_DMPD_SPI BIT(4)
#define CPCAP_BIT_DPPD_SPI BIT(3)
#define CPCAP_BIT_SUSPEND_SPI BIT(2)
#define CPCAP_BIT_PU_SPI BIT(1)
#define CPCAP_BIT_ULPI_SPI_SEL BIT(0)
struct cpcap_usb_ints_state {
bool id_ground;
bool id_float;
bool chrg_det;
bool rvrs_chrg;
bool vbusov;
bool chrg_se1b;
bool se0conn;
bool rvrs_mode;
bool chrgcurr1;
bool vbusvld;
bool sessvld;
bool sessend;
bool se1;
bool battdetb;
bool dm;
bool dp;
};
enum cpcap_gpio_mode {
CPCAP_DM_DP,
CPCAP_MDM_RX_TX,
CPCAP_UNKNOWN,
CPCAP_OTG_DM_DP,
};
struct cpcap_phy_ddata {
struct regmap *reg;
struct device *dev;
struct clk *refclk;
struct usb_phy phy;
struct delayed_work detect_work;
struct pinctrl *pins;
struct pinctrl_state *pins_ulpi;
struct pinctrl_state *pins_utmi;
struct pinctrl_state *pins_uart;
struct gpio_desc *gpio[2];
struct iio_channel *vbus;
struct iio_channel *id;
struct regulator *vusb;
atomic_t active;
};
static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
{
int error, value = 0;
error = iio_read_channel_processed(ddata->vbus, &value);
if (error >= 0)
return value > 3900 ? true : false;
dev_err(ddata->dev, "error reading VBUS: %i\n", error);
return false;
}
static int cpcap_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
{
otg->host = host;
if (!host)
otg->state = OTG_STATE_UNDEFINED;
return 0;
}
static int cpcap_usb_phy_set_peripheral(struct usb_otg *otg,
struct usb_gadget *gadget)
{
otg->gadget = gadget;
if (!gadget)
otg->state = OTG_STATE_UNDEFINED;
return 0;
}
static const struct phy_ops ops = {
.owner = THIS_MODULE,
};
static int cpcap_phy_get_ints_state(struct cpcap_phy_ddata *ddata,
struct cpcap_usb_ints_state *s)
{
int val, error;
error = regmap_read(ddata->reg, CPCAP_REG_INTS1, &val);
if (error)
return error;
s->id_ground = val & BIT(15);
s->id_float = val & BIT(14);
s->vbusov = val & BIT(11);
error = regmap_read(ddata->reg, CPCAP_REG_INTS2, &val);
if (error)
return error;
s->vbusvld = val & BIT(3);
s->sessvld = val & BIT(2);
s->sessend = val & BIT(1);
s->se1 = val & BIT(0);
error = regmap_read(ddata->reg, CPCAP_REG_INTS4, &val);
if (error)
return error;
s->dm = val & BIT(1);
s->dp = val & BIT(0);
return 0;
}
static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
static void cpcap_usb_detect(struct work_struct *work)
{
struct cpcap_phy_ddata *ddata;
struct cpcap_usb_ints_state s;
bool vbus = false;
int error;
ddata = container_of(work, struct cpcap_phy_ddata, detect_work.work);
error = cpcap_phy_get_ints_state(ddata, &s);
if (error)
return;
if (s.id_ground) {
dev_dbg(ddata->dev, "id ground, USB host mode\n");
error = cpcap_usb_set_usb_mode(ddata);
if (error)
goto out_err;
error = musb_mailbox(MUSB_ID_GROUND);
if (error)
goto out_err;
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
CPCAP_BIT_VBUSSTBY_EN,
CPCAP_BIT_VBUSSTBY_EN);
if (error)
goto out_err;
return;
}
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
CPCAP_BIT_VBUSSTBY_EN, 0);
if (error)
goto out_err;
vbus = cpcap_usb_vbus_valid(ddata);
if (vbus) {
/* Are we connected to a docking station with vbus? */
if (s.id_ground) {
dev_dbg(ddata->dev, "connected to a dock\n");
/* No VBUS needed with docks */
error = cpcap_usb_set_usb_mode(ddata);
if (error)
goto out_err;
error = musb_mailbox(MUSB_ID_GROUND);
if (error)
goto out_err;
return;
}
/* Otherwise assume we're connected to a USB host */
dev_dbg(ddata->dev, "connected to USB host\n");
error = cpcap_usb_set_usb_mode(ddata);
if (error)
goto out_err;
error = musb_mailbox(MUSB_VBUS_VALID);
if (error)
goto out_err;
return;
}
/* Default to debug UART mode */
error = cpcap_usb_set_uart_mode(ddata);
if (error)
goto out_err;
error = musb_mailbox(MUSB_VBUS_OFF);
if (error)
goto out_err;
dev_dbg(ddata->dev, "set UART mode\n");
return;
out_err:
dev_err(ddata->dev, "error setting cable state: %i\n", error);
}
static irqreturn_t cpcap_phy_irq_thread(int irq, void *data)
{
struct cpcap_phy_ddata *ddata = data;
if (!atomic_read(&ddata->active))
return IRQ_NONE;
schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
return IRQ_HANDLED;
}
static int cpcap_usb_init_irq(struct platform_device *pdev,
struct cpcap_phy_ddata *ddata,
const char *name)
{
int irq, error;
irq = platform_get_irq_byname(pdev, name);
if (!irq)
return -ENODEV;
error = devm_request_threaded_irq(ddata->dev, irq, NULL,
cpcap_phy_irq_thread,
IRQF_SHARED,
name, ddata);
if (error) {
dev_err(ddata->dev, "could not get irq %s: %i\n",
name, error);
return error;
}
return 0;
}
static const char * const cpcap_phy_irqs[] = {
/* REG_INT_0 */
"id_ground", "id_float",
/* REG_INT1 */
"se0conn", "vbusvld", "sessvld", "sessend", "se1",
/* REG_INT_3 */
"dm", "dp",
};
static int cpcap_usb_init_interrupts(struct platform_device *pdev,
struct cpcap_phy_ddata *ddata)
{
int i, error;
for (i = 0; i < ARRAY_SIZE(cpcap_phy_irqs); i++) {
error = cpcap_usb_init_irq(pdev, ddata, cpcap_phy_irqs[i]);
if (error)
return error;
}
return 0;
}
/*
* Optional pins and modes. At least Motorola mapphone devices
* are using two GPIOs and dynamic pinctrl to multiplex PHY pins
* to UART, ULPI or UTMI mode.
*/
static int cpcap_usb_gpio_set_mode(struct cpcap_phy_ddata *ddata,
enum cpcap_gpio_mode mode)
{
if (!ddata->gpio[0] || !ddata->gpio[1])
return 0;
gpiod_set_value(ddata->gpio[0], mode & 1);
gpiod_set_value(ddata->gpio[1], mode >> 1);
return 0;
}
static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
{
int error;
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
if (error)
goto out_err;
if (ddata->pins_uart) {
error = pinctrl_select_state(ddata->pins, ddata->pins_uart);
if (error)
goto out_err;
}
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
CPCAP_BIT_VBUSPD,
CPCAP_BIT_VBUSPD);
if (error)
goto out_err;
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
0xffff, CPCAP_BIT_UARTMUX0 |
CPCAP_BIT_EMUMODE0);
if (error)
goto out_err;
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3, 0x7fff,
CPCAP_BIT_IDPU_SPI);
if (error)
goto out_err;
return 0;
out_err:
dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
return error;
}
static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
{
int error;
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
if (error)
return error;
if (ddata->pins_utmi) {
error = pinctrl_select_state(ddata->pins, ddata->pins_utmi);
if (error) {
dev_err(ddata->dev, "could not set usb mode: %i\n",
error);
return error;
}
}
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
CPCAP_BIT_VBUSPD, 0);
if (error)
goto out_err;
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
CPCAP_BIT_USBXCVREN,
CPCAP_BIT_USBXCVREN);
if (error)
goto out_err;
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
CPCAP_BIT_PU_SPI |
CPCAP_BIT_DMPD_SPI |
CPCAP_BIT_DPPD_SPI |
CPCAP_BIT_SUSPEND_SPI |
CPCAP_BIT_ULPI_SPI_SEL, 0);
if (error)
goto out_err;
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
CPCAP_BIT_USBXCVREN,
CPCAP_BIT_USBXCVREN);
if (error)
goto out_err;
return 0;
out_err:
dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
return error;
}
static int cpcap_usb_init_optional_pins(struct cpcap_phy_ddata *ddata)
{
ddata->pins = devm_pinctrl_get(ddata->dev);
if (IS_ERR(ddata->pins)) {
dev_info(ddata->dev, "default pins not configured: %ld\n",
PTR_ERR(ddata->pins));
ddata->pins = NULL;
return 0;
}
ddata->pins_ulpi = pinctrl_lookup_state(ddata->pins, "ulpi");
if (IS_ERR(ddata->pins_ulpi)) {
dev_info(ddata->dev, "ulpi pins not configured\n");
ddata->pins_ulpi = NULL;
}
ddata->pins_utmi = pinctrl_lookup_state(ddata->pins, "utmi");
if (IS_ERR(ddata->pins_utmi)) {
dev_info(ddata->dev, "utmi pins not configured\n");
ddata->pins_utmi = NULL;
}
ddata->pins_uart = pinctrl_lookup_state(ddata->pins, "uart");
if (IS_ERR(ddata->pins_uart)) {
dev_info(ddata->dev, "uart pins not configured\n");
ddata->pins_uart = NULL;
}
if (ddata->pins_uart)
return pinctrl_select_state(ddata->pins, ddata->pins_uart);
return 0;
}
static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
{
int i;
for (i = 0; i < 2; i++) {
ddata->gpio[i] = devm_gpiod_get_index(ddata->dev, "mode",
i, GPIOD_OUT_HIGH);
if (IS_ERR(ddata->gpio[i])) {
dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
i, PTR_ERR(ddata->gpio[i]));
ddata->gpio[i] = NULL;
}
}
}
static int cpcap_usb_init_iio(struct cpcap_phy_ddata *ddata)
{
enum iio_chan_type type;
int error;
ddata->vbus = devm_iio_channel_get(ddata->dev, "vbus");
if (IS_ERR(ddata->vbus)) {
error = PTR_ERR(ddata->vbus);
goto out_err;
}
if (!ddata->vbus->indio_dev) {
error = -ENXIO;
goto out_err;
}
error = iio_get_channel_type(ddata->vbus, &type);
if (error < 0)
goto out_err;
if (type != IIO_VOLTAGE) {
error = -EINVAL;
goto out_err;
}
return 0;
out_err:
dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
error);
return error;
}
#ifdef CONFIG_OF
static const struct of_device_id cpcap_usb_phy_id_table[] = {
{
.compatible = "motorola,cpcap-usb-phy",
},
{
.compatible = "motorola,mapphone-cpcap-usb-phy",
},
{},
};
MODULE_DEVICE_TABLE(of, cpcap_usb_phy_id_table);
#endif
static int cpcap_usb_phy_probe(struct platform_device *pdev)
{
struct cpcap_phy_ddata *ddata;
struct phy *generic_phy;
struct phy_provider *phy_provider;
struct usb_otg *otg;
const struct of_device_id *of_id;
int error;
of_id = of_match_device(of_match_ptr(cpcap_usb_phy_id_table),
&pdev->dev);
if (!of_id)
return -EINVAL;
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
ddata->reg = dev_get_regmap(pdev->dev.parent, NULL);
if (!ddata->reg)
return -ENODEV;
otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
if (!otg)
return -ENOMEM;
ddata->dev = &pdev->dev;
ddata->phy.dev = ddata->dev;
ddata->phy.label = "cpcap_usb_phy";
ddata->phy.otg = otg;
ddata->phy.type = USB_PHY_TYPE_USB2;
otg->set_host = cpcap_usb_phy_set_host;
otg->set_peripheral = cpcap_usb_phy_set_peripheral;
otg->usb_phy = &ddata->phy;
INIT_DELAYED_WORK(&ddata->detect_work, cpcap_usb_detect);
platform_set_drvdata(pdev, ddata);
ddata->vusb = devm_regulator_get(&pdev->dev, "vusb");
if (IS_ERR(ddata->vusb))
return PTR_ERR(ddata->vusb);
error = regulator_enable(ddata->vusb);
if (error)
return error;
generic_phy = devm_phy_create(ddata->dev, NULL, &ops);
if (IS_ERR(generic_phy)) {
error = PTR_ERR(generic_phy);
return PTR_ERR(generic_phy);
}
phy_set_drvdata(generic_phy, ddata);
phy_provider = devm_of_phy_provider_register(ddata->dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
error = cpcap_usb_init_optional_pins(ddata);
if (error)
return error;
cpcap_usb_init_optional_gpios(ddata);
error = cpcap_usb_init_iio(ddata);
if (error)
return error;
error = cpcap_usb_init_interrupts(pdev, ddata);
if (error)
return error;
usb_add_phy_dev(&ddata->phy);
atomic_set(&ddata->active, 1);
schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
return 0;
}
static int cpcap_usb_phy_remove(struct platform_device *pdev)
{
struct cpcap_phy_ddata *ddata = platform_get_drvdata(pdev);
int error;
atomic_set(&ddata->active, 0);
error = cpcap_usb_set_uart_mode(ddata);
if (error)
dev_err(ddata->dev, "could not set UART mode\n");
error = musb_mailbox(MUSB_VBUS_OFF);
if (error)
dev_err(ddata->dev, "could not set mailbox\n");
usb_remove_phy(&ddata->phy);
cancel_delayed_work_sync(&ddata->detect_work);
clk_unprepare(ddata->refclk);
regulator_disable(ddata->vusb);
return 0;
}
static struct platform_driver cpcap_usb_phy_driver = {
.probe = cpcap_usb_phy_probe,
.remove = cpcap_usb_phy_remove,
.driver = {
.name = "cpcap-usb-phy",
.of_match_table = of_match_ptr(cpcap_usb_phy_id_table),
},
};
module_platform_driver(cpcap_usb_phy_driver);
MODULE_ALIAS("platform:cpcap_usb");
MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
MODULE_DESCRIPTION("CPCAP usb phy driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,58 @@
#
# Phy drivers for Qualcomm platforms
#
config PHY_QCOM_APQ8064_SATA
tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
depends on ARCH_QCOM
depends on HAS_IOMEM
depends on OF
select GENERIC_PHY
config PHY_QCOM_IPQ806X_SATA
tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
depends on ARCH_QCOM
depends on HAS_IOMEM
depends on OF
select GENERIC_PHY
config PHY_QCOM_QMP
tristate "Qualcomm QMP PHY Driver"
depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
select GENERIC_PHY
help
Enable this to support the QMP PHY transceiver that is used
with controllers such as PCIe, UFS, and USB on Qualcomm chips.
config PHY_QCOM_QUSB2
tristate "Qualcomm QUSB2 PHY Driver"
depends on OF && (ARCH_QCOM || COMPILE_TEST)
depends on NVMEM || !NVMEM
select GENERIC_PHY
help
Enable this to support the HighSpeed QUSB2 PHY transceiver for USB
controllers on Qualcomm chips. This driver supports the high-speed
PHY which is usually paired with either the ChipIdea or Synopsys DWC3
USB IPs on MSM SOCs.
config PHY_QCOM_UFS
tristate "Qualcomm UFS PHY driver"
depends on OF && ARCH_QCOM
select GENERIC_PHY
help
Support for UFS PHY on QCOM chipsets.
config PHY_QCOM_USB_HS
tristate "Qualcomm USB HS PHY module"
depends on USB_ULPI_BUS
depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
select GENERIC_PHY
help
Support for the USB high-speed ULPI compliant phy on Qualcomm
chipsets.
config PHY_QCOM_USB_HSIC
tristate "Qualcomm USB HSIC ULPI PHY module"
depends on USB_ULPI_BUS
select GENERIC_PHY
help
Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.

View File

@ -0,0 +1,9 @@
obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o
obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o

View File

@ -11,12 +11,11 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/reset.h>
#include <linux/extcon.h>
#include <linux/notifier.h>
#include "ulpi_phy.h"
#define ULPI_PWR_CLK_MNG_REG 0x88
# define ULPI_PWR_OTG_COMP_DISABLE BIT(0)

View File

@ -8,13 +8,12 @@
#include <linux/module.h>
#include <linux/ulpi/driver.h>
#include <linux/ulpi/regs.h>
#include <linux/phy/phy.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl-state.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include "ulpi_phy.h"
#define ULPI_HSIC_CFG 0x30
#define ULPI_HSIC_IO_CAL 0x33

View File

@ -0,0 +1,24 @@
#
# Phy drivers for Renesas platforms
#
config PHY_RCAR_GEN2
tristate "Renesas R-Car generation 2 USB PHY driver"
depends on ARCH_RENESAS
depends on GENERIC_PHY
help
Support for USB PHY found on Renesas R-Car generation 2 SoCs.
config PHY_RCAR_GEN3_USB2
tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
depends on ARCH_RENESAS
depends on EXTCON
select GENERIC_PHY
help
Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs.
config PHY_RCAR_GEN3_USB3
tristate "Renesas R-Car generation 3 USB 3.0 PHY driver"
depends on ARCH_RENESAS || COMPILE_TEST
select GENERIC_PHY
help
Support for USB 3.0 PHY found on Renesas R-Car generation 3 SoCs.

View File

@ -0,0 +1,3 @@
obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o
obj-$(CONFIG_PHY_RCAR_GEN3_USB3) += phy-rcar-gen3-usb3.o

View File

@ -0,0 +1,226 @@
/*
* Renesas R-Car Gen3 for USB3.0 PHY driver
*
* Copyright (C) 2017 Renesas Electronics Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#define USB30_CLKSET0 0x034
#define USB30_CLKSET1 0x036
#define USB30_SSC_SET 0x038
#define USB30_PHY_ENABLE 0x060
#define USB30_VBUS_EN 0x064
/* USB30_CLKSET0 */
#define CLKSET0_PRIVATE 0x05c0
#define CLKSET0_USB30_FSEL_USB_EXTAL 0x0002
/* USB30_CLKSET1 */
#define CLKSET1_USB30_PLL_MULTI_SHIFT 6
#define CLKSET1_USB30_PLL_MULTI_USB_EXTAL (0x64 << \
CLKSET1_USB30_PLL_MULTI_SHIFT)
#define CLKSET1_PHYRESET BIT(4) /* 1: reset */
#define CLKSET1_REF_CLKDIV BIT(3) /* 1: USB_EXTAL */
#define CLKSET1_PRIVATE_2_1 BIT(1) /* Write B'01 */
#define CLKSET1_REF_CLK_SEL BIT(0) /* 1: USB3S0_CLK_P */
/* USB30_SSC_SET */
#define SSC_SET_SSC_EN BIT(12)
#define SSC_SET_RANGE_SHIFT 9
#define SSC_SET_RANGE_4980 (0x0 << SSC_SET_RANGE_SHIFT)
#define SSC_SET_RANGE_4492 (0x1 << SSC_SET_RANGE_SHIFT)
#define SSC_SET_RANGE_4003 (0x2 << SSC_SET_RANGE_SHIFT)
/* USB30_PHY_ENABLE */
#define PHY_ENABLE_RESET_EN BIT(4)
/* USB30_VBUS_EN */
#define VBUS_EN_VBUS_EN BIT(1)
struct rcar_gen3_usb3 {
void __iomem *base;
struct phy *phy;
u32 ssc_range;
bool usb3s_clk;
bool usb_extal;
};
static void write_clkset1_for_usb_extal(struct rcar_gen3_usb3 *r, bool reset)
{
u16 val = CLKSET1_USB30_PLL_MULTI_USB_EXTAL |
CLKSET1_REF_CLKDIV | CLKSET1_PRIVATE_2_1;
if (reset)
val |= CLKSET1_PHYRESET;
writew(val, r->base + USB30_CLKSET1);
}
static void rcar_gen3_phy_usb3_enable_ssc(struct rcar_gen3_usb3 *r)
{
u16 val = SSC_SET_SSC_EN;
switch (r->ssc_range) {
case 4980:
val |= SSC_SET_RANGE_4980;
break;
case 4492:
val |= SSC_SET_RANGE_4492;
break;
case 4003:
val |= SSC_SET_RANGE_4003;
break;
default:
dev_err(&r->phy->dev, "%s: unsupported range (%x)\n", __func__,
r->ssc_range);
return;
}
writew(val, r->base + USB30_SSC_SET);
}
static void rcar_gen3_phy_usb3_select_usb_extal(struct rcar_gen3_usb3 *r)
{
write_clkset1_for_usb_extal(r, false);
if (r->ssc_range)
rcar_gen3_phy_usb3_enable_ssc(r);
writew(CLKSET0_PRIVATE | CLKSET0_USB30_FSEL_USB_EXTAL,
r->base + USB30_CLKSET0);
writew(PHY_ENABLE_RESET_EN, r->base + USB30_PHY_ENABLE);
write_clkset1_for_usb_extal(r, true);
usleep_range(10, 20);
write_clkset1_for_usb_extal(r, false);
}
static int rcar_gen3_phy_usb3_init(struct phy *p)
{
struct rcar_gen3_usb3 *r = phy_get_drvdata(p);
dev_vdbg(&r->phy->dev, "%s: enter (%d, %d, %d)\n", __func__,
r->usb3s_clk, r->usb_extal, r->ssc_range);
if (!r->usb3s_clk && r->usb_extal)
rcar_gen3_phy_usb3_select_usb_extal(r);
/* Enables VBUS detection anyway */
writew(VBUS_EN_VBUS_EN, r->base + USB30_VBUS_EN);
return 0;
}
static const struct phy_ops rcar_gen3_phy_usb3_ops = {
.init = rcar_gen3_phy_usb3_init,
.owner = THIS_MODULE,
};
static const struct of_device_id rcar_gen3_phy_usb3_match_table[] = {
{ .compatible = "renesas,rcar-gen3-usb3-phy" },
{ }
};
MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb3_match_table);
static int rcar_gen3_phy_usb3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rcar_gen3_usb3 *r;
struct phy_provider *provider;
struct resource *res;
int ret = 0;
struct clk *clk;
if (!dev->of_node) {
dev_err(dev, "This driver needs device tree\n");
return -EINVAL;
}
r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL);
if (!r)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
r->base = devm_ioremap_resource(dev, res);
if (IS_ERR(r->base))
return PTR_ERR(r->base);
clk = devm_clk_get(dev, "usb3s_clk");
if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
r->usb3s_clk = !!clk_get_rate(clk);
clk_disable_unprepare(clk);
}
clk = devm_clk_get(dev, "usb_extal");
if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
r->usb_extal = !!clk_get_rate(clk);
clk_disable_unprepare(clk);
}
if (!r->usb3s_clk && !r->usb_extal) {
dev_err(dev, "This driver needs usb3s_clk and/or usb_extal\n");
ret = -EINVAL;
goto error;
}
/*
* devm_phy_create() will call pm_runtime_enable(&phy->dev);
* And then, phy-core will manage runtime pm for this device.
*/
pm_runtime_enable(dev);
r->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb3_ops);
if (IS_ERR(r->phy)) {
dev_err(dev, "Failed to create USB3 PHY\n");
ret = PTR_ERR(r->phy);
goto error;
}
of_property_read_u32(dev->of_node, "renesas,ssc-range", &r->ssc_range);
platform_set_drvdata(pdev, r);
phy_set_drvdata(r->phy, r);
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(provider)) {
dev_err(dev, "Failed to register PHY provider\n");
ret = PTR_ERR(provider);
goto error;
}
return 0;
error:
pm_runtime_disable(dev);
return ret;
}
static int rcar_gen3_phy_usb3_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
return 0;
};
static struct platform_driver rcar_gen3_phy_usb3_driver = {
.driver = {
.name = "phy_rcar_gen3_usb3",
.of_match_table = rcar_gen3_phy_usb3_match_table,
},
.probe = rcar_gen3_phy_usb3_probe,
.remove = rcar_gen3_phy_usb3_remove,
};
module_platform_driver(rcar_gen3_phy_usb3_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 3.0 PHY");
MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");

View File

@ -0,0 +1,51 @@
#
# Phy drivers for Rockchip platforms
#
config PHY_ROCKCHIP_DP
tristate "Rockchip Display Port PHY Driver"
depends on ARCH_ROCKCHIP && OF
select GENERIC_PHY
help
Enable this to support the Rockchip Display Port PHY.
config PHY_ROCKCHIP_EMMC
tristate "Rockchip EMMC PHY Driver"
depends on ARCH_ROCKCHIP && OF
select GENERIC_PHY
help
Enable this to support the Rockchip EMMC PHY.
config PHY_ROCKCHIP_INNO_USB2
tristate "Rockchip INNO USB2PHY Driver"
depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
depends on COMMON_CLK
depends on EXTCON
depends on USB_SUPPORT
select GENERIC_PHY
select USB_COMMON
help
Support for Rockchip USB2.0 PHY with Innosilicon IP block.
config PHY_ROCKCHIP_PCIE
tristate "Rockchip PCIe PHY Driver"
depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
select GENERIC_PHY
select MFD_SYSCON
help
Enable this to support the Rockchip PCIe PHY.
config PHY_ROCKCHIP_TYPEC
tristate "Rockchip TYPEC PHY Driver"
depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
select EXTCON
select GENERIC_PHY
select RESET_CONTROLLER
help
Enable this to support the Rockchip USB TYPEC 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.

View File

@ -0,0 +1,6 @@
obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o
obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o

View File

@ -406,7 +406,8 @@ static int rockchip_usb2phy_init(struct phy *phy)
mutex_lock(&rport->mutex);
if (rport->port_id == USB2PHY_PORT_OTG) {
if (rport->mode != USB_DR_MODE_HOST) {
if (rport->mode != USB_DR_MODE_HOST &&
rport->mode != USB_DR_MODE_UNKNOWN) {
/* clear bvalid status and enable bvalid detect irq */
ret = property_enable(rphy,
&rport->port_cfg->bvalid_det_clr,
@ -421,7 +422,7 @@ static int rockchip_usb2phy_init(struct phy *phy)
goto out;
schedule_delayed_work(&rport->otg_sm_work,
OTG_SCHEDULE_DELAY);
OTG_SCHEDULE_DELAY * 3);
} else {
/* If OTG works in host only mode, do nothing. */
dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
@ -463,6 +464,9 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
if (ret)
return ret;
/* waiting for the utmi_clk to become stable */
usleep_range(1500, 2000);
rport->suspended = false;
return 0;
}
@ -493,7 +497,8 @@ static int rockchip_usb2phy_exit(struct phy *phy)
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
if (rport->port_id == USB2PHY_PORT_OTG &&
rport->mode != USB_DR_MODE_HOST) {
rport->mode != USB_DR_MODE_HOST &&
rport->mode != USB_DR_MODE_UNKNOWN) {
cancel_delayed_work_sync(&rport->otg_sm_work);
cancel_delayed_work_sync(&rport->chg_work);
} else if (rport->port_id == USB2PHY_PORT_HOST)
@ -970,7 +975,8 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
mutex_init(&rport->mutex);
rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
if (rport->mode == USB_DR_MODE_HOST) {
if (rport->mode == USB_DR_MODE_HOST ||
rport->mode == USB_DR_MODE_UNKNOWN) {
ret = 0;
goto out;
}
@ -1138,6 +1144,65 @@ disable_clks:
return ret;
}
static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
{
.reg = 0x760,
.num_ports = 2,
.clkout_ctl = { 0x0768, 4, 4, 1, 0 },
.port_cfgs = {
[USB2PHY_PORT_OTG] = {
.phy_sus = { 0x0760, 15, 0, 0, 0x1d1 },
.bvalid_det_en = { 0x0680, 3, 3, 0, 1 },
.bvalid_det_st = { 0x0690, 3, 3, 0, 1 },
.bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 },
.ls_det_en = { 0x0680, 2, 2, 0, 1 },
.ls_det_st = { 0x0690, 2, 2, 0, 1 },
.ls_det_clr = { 0x06a0, 2, 2, 0, 1 },
.utmi_bvalid = { 0x0480, 4, 4, 0, 1 },
.utmi_ls = { 0x0480, 3, 2, 0, 1 },
},
[USB2PHY_PORT_HOST] = {
.phy_sus = { 0x0764, 15, 0, 0, 0x1d1 },
.ls_det_en = { 0x0680, 4, 4, 0, 1 },
.ls_det_st = { 0x0690, 4, 4, 0, 1 },
.ls_det_clr = { 0x06a0, 4, 4, 0, 1 }
}
},
.chg_det = {
.opmode = { 0x0760, 3, 0, 5, 1 },
.cp_det = { 0x0884, 4, 4, 0, 1 },
.dcp_det = { 0x0884, 3, 3, 0, 1 },
.dp_det = { 0x0884, 5, 5, 0, 1 },
.idm_sink_en = { 0x0768, 8, 8, 0, 1 },
.idp_sink_en = { 0x0768, 7, 7, 0, 1 },
.idp_src_en = { 0x0768, 9, 9, 0, 1 },
.rdm_pdwn_en = { 0x0768, 10, 10, 0, 1 },
.vdm_src_en = { 0x0768, 12, 12, 0, 1 },
.vdp_src_en = { 0x0768, 11, 11, 0, 1 },
},
},
{
.reg = 0x800,
.num_ports = 2,
.clkout_ctl = { 0x0808, 4, 4, 1, 0 },
.port_cfgs = {
[USB2PHY_PORT_OTG] = {
.phy_sus = { 0x800, 15, 0, 0, 0x1d1 },
.ls_det_en = { 0x0684, 0, 0, 0, 1 },
.ls_det_st = { 0x0694, 0, 0, 0, 1 },
.ls_det_clr = { 0x06a4, 0, 0, 0, 1 }
},
[USB2PHY_PORT_HOST] = {
.phy_sus = { 0x804, 15, 0, 0, 0x1d1 },
.ls_det_en = { 0x0684, 1, 1, 0, 1 },
.ls_det_st = { 0x0694, 1, 1, 0, 1 },
.ls_det_clr = { 0x06a4, 1, 1, 0, 1 }
}
},
},
{ /* sentinel */ }
};
static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
{
.reg = 0x100,
@ -1263,6 +1328,7 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
};
static const struct of_device_id rockchip_usb2phy_dt_match[] = {
{ .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },

View File

@ -0,0 +1,95 @@
#
# Phy drivers for Samsung platforms
#
config PHY_EXYNOS_DP_VIDEO
tristate "EXYNOS SoC series Display Port PHY driver"
depends on OF
depends on ARCH_EXYNOS || COMPILE_TEST
default ARCH_EXYNOS
select GENERIC_PHY
help
Support for Display Port PHY found on Samsung EXYNOS SoCs.
config PHY_EXYNOS_MIPI_VIDEO
tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
depends on HAS_IOMEM
depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
select GENERIC_PHY
default y if ARCH_S5PV210 || ARCH_EXYNOS
help
Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
and EXYNOS SoCs.
config PHY_EXYNOS_PCIE
bool "Exynos PCIe PHY driver"
depends on OF && (ARCH_EXYNOS || COMPILE_TEST)
select GENERIC_PHY
help
Enable PCIe PHY support for Exynos SoC series.
This driver provides PHY interface for Exynos PCIe controller.
config PHY_SAMSUNG_USB2
tristate "Samsung USB 2.0 PHY driver"
depends on HAS_IOMEM
depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
select GENERIC_PHY
select MFD_SYSCON
default ARCH_EXYNOS
help
Enable this to support the Samsung USB 2.0 PHY driver for Samsung
SoCs. This driver provides the interface for USB 2.0 PHY. Support
for particular PHYs will be enabled based on the SoC type in addition
to this driver.
config PHY_EXYNOS4210_USB2
bool
depends on PHY_SAMSUNG_USB2
default CPU_EXYNOS4210
config PHY_EXYNOS4X12_USB2
bool
depends on PHY_SAMSUNG_USB2
default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
config PHY_EXYNOS5250_USB2
bool
depends on PHY_SAMSUNG_USB2
default SOC_EXYNOS5250 || SOC_EXYNOS5420
config PHY_S5PV210_USB2
bool "Support for S5PV210"
depends on PHY_SAMSUNG_USB2
depends on ARCH_S5PV210
help
Enable USB PHY support for S5PV210. This option requires that Samsung
USB 2.0 PHY driver is enabled and means that support for this
particular SoC is compiled in the driver. In case of S5PV210 two phys
are available - device and host.
config PHY_EXYNOS5_USBDRD
tristate "Exynos5 SoC series USB DRD PHY driver"
depends on ARCH_EXYNOS && OF
depends on HAS_IOMEM
depends on USB_DWC3_EXYNOS
select GENERIC_PHY
select MFD_SYSCON
default y
help
Enable USB DRD PHY support for Exynos 5 SoC series.
This driver provides PHY interface for USB 3.0 DRD controller
present on Exynos5 SoC series.
config PHY_EXYNOS5250_SATA
tristate "Exynos5250 Sata SerDes/PHY driver"
depends on SOC_EXYNOS5250
depends on HAS_IOMEM
depends on OF
select GENERIC_PHY
select I2C
select I2C_S3C2410
select MFD_SYSCON
help
Enable this to support SATA SerDes/Phy found on Samsung's
Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s,
SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
port to accept one SATA device.

View File

@ -0,0 +1,11 @@
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o
obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
phy-exynos-usb2-y += phy-samsung-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
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_EXYNOS5250_SATA) += phy-exynos5250-sata.o

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