USB/PHY driver updates for 4.14-rc1

Here is the large USB and PHY driver update for 4.14-rc1.
 
 Not all that exciting, a few new PHY drivers, the usual mess of gadget
 driver updates and fixes, and of course, xhci updates to try to tame
 that beast.
 
 A number of usb-serial updates and other small fixes all over the USB
 driver tree are in here as well.  Full details are in the shortlog.
 
 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-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWa2Buw8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+yk0VQCeK9SbD3sNVE0NXnwBYPTptghtr1EAoKwg96LG
 e4TUNAUcKadcDHJ8S81i
 =zy8S
 -----END PGP SIGNATURE-----

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

Pull USB/PHY driver updates from Greg KH:
 "Here is the large USB and PHY driver update for 4.14-rc1.

  Not all that exciting, a few new PHY drivers, the usual mess of gadget
  driver updates and fixes, and of course, xhci updates to try to tame
  that beast.

  A number of usb-serial updates and other small fixes all over the USB
  driver tree are in here as well. Full details are in the shortlog.

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

* tag 'usb-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (171 commits)
  usbip: vhci-hcd: make vhci_hc_driver const
  usb: phy: Avoid unchecked dereference warning
  usb: imx21-hcd: make imx21_hc_driver const
  usb: host: make ehci_fsl_overrides const and __initconst
  dt-bindings: mt8173-mtu3: add generic compatible and rename file
  dt-bindings: mt8173-xhci: add generic compatible and rename file
  usb: xhci-mtk: add generic compatible string
  usbip: auto retry for concurrent attach
  USB: serial: option: simplify 3 D-Link device entries
  USB: serial: option: add support for D-Link DWM-157 C1
  usb: core: usbport: fix "BUG: key not in .data" when lockdep is enabled
  usb: chipidea: usb2: check memory allocation failure
  usb: Add device quirk for Logitech HD Pro Webcam C920-C
  usb: misc: lvstest: add entry to place port in compliance mode
  usb: xhci: Support enabling of compliance mode for xhci 1.1
  usb:xhci:Fix regression when ATI chipsets detected
  usb: quirks: add delay init quirk for Corsair Strafe RGB keyboard
  usb: gadget: make snd_pcm_hardware const
  usb: common: use of_property_read_bool()
  USB: core: constify vm_operations_struct
  ...
This commit is contained in:
Linus Torvalds 2017-09-05 10:26:01 -07:00
commit 1a3b85ea36
162 changed files with 2931 additions and 673 deletions

View File

@ -12,3 +12,6 @@ Description:
Ethernet over USB link
dev_addr - MAC address of device's end of this
Ethernet over USB link
class - USB interface class, default is 02 (hex)
subclass - USB interface subclass, default is 06 (hex)
protocol - USB interface protocol, default is 00 (hex)

View File

@ -45,3 +45,16 @@ Contact: Pratyush Anand <pratyush.anand@gmail.com>
Description:
Write to this node to issue "U3 exit" for Link Layer
Validation device. It is needed for TD.7.36.
What: /sys/bus/usb/devices/.../enable_compliance
Date: July 2017
Description:
Write to this node to set the port to compliance mode to test
with Link Layer Validation device. It is needed for TD.7.34.
What: /sys/bus/usb/devices/.../warm_reset
Date: July 2017
Description:
Write to this node to issue "Warm Reset" for Link Layer Validation
device. It may be needed to properly reset an xHCI 1.1 host port if
compliance mode needed to be explicitly enabled.

View File

@ -31,6 +31,7 @@ Required properties:
../interrupt-controller/interrupts.txt
Optional sub-nodes:
- phys : Contains a phandle to the USB PHY.
- regulators : Contains sub-nodes for each of the regulators supplied by
the device. The regulators are bound using their names listed below:

View File

@ -1,13 +1,18 @@
mt65xx USB3.0 PHY binding
MediaTek T-PHY binding
--------------------------
This binding describes a usb3.0 phy for mt65xx platforms of Medaitek SoC.
T-phy controller supports physical layer functionality for a number of
controllers on MediaTek SoCs, such as, USB2.0, USB3.0, PCIe, and SATA.
Required properties (controller (parent) node):
- compatible : should be one of
"mediatek,mt2701-u3phy"
"mediatek,mt2712-u3phy"
"mediatek,mt8173-u3phy"
"mediatek,generic-tphy-v1"
"mediatek,generic-tphy-v2"
"mediatek,mt2701-u3phy" (deprecated)
"mediatek,mt2712-u3phy" (deprecated)
"mediatek,mt8173-u3phy";
make use of "mediatek,generic-tphy-v1" on mt2701 instead and
"mediatek,generic-tphy-v2" on mt2712 instead.
- clocks : (deprecated, use port's clocks instead) a list of phandle +
clock-specifier pairs, one for each entry in clock-names
- clock-names : (deprecated, use port's one instead) must contain
@ -35,6 +40,8 @@ Required properties (port (child) node):
cell after port phandle is phy type from:
- PHY_TYPE_USB2
- PHY_TYPE_USB3
- PHY_TYPE_PCIE
- PHY_TYPE_SATA
Example:

View File

@ -6,6 +6,7 @@ Required properties (phy (parent) node):
* "rockchip,rk3328-usb2phy"
* "rockchip,rk3366-usb2phy"
* "rockchip,rk3399-usb2phy"
* "rockchip,rv1108-usb2phy"
- reg : the address offset of grf for usb-phy configuration.
- #clock-cells : should be 0.
- clock-output-names : specify the 480m output clock name.
@ -18,6 +19,10 @@ Optional properties:
usb-phy output 480m and xin24m.
Refer to clk/clock-bindings.txt for generic clock
consumer properties.
- rockchip,usbgrf : phandle to the syscon managing the "usb general
register files". When set driver will request its
phandle as one companion-grf for some special SoCs
(e.g RV1108).
Required nodes : a sub-node is required for each port the phy provides.
The sub-node name is used to identify host or otg port,
@ -28,10 +33,14 @@ Required nodes : a sub-node is required for each port the phy provides.
Required properties (port (child) node):
- #phy-cells : must be 0. See ./phy-bindings.txt for details.
- interrupts : specify an interrupt for each entry in interrupt-names.
- interrupt-names : a list which shall be the following entries:
- interrupt-names : a list which should be one of the following cases:
Regular case:
* "otg-id" : for the otg id interrupt.
* "otg-bvalid" : for the otg vbus interrupt.
* "linestate" : for the host/otg linestate interrupt.
Some SoCs use one interrupt with the above muxed together, so for these
* "otg-mux" : otg-port interrupt, which mux otg-id/otg-bvalid/linestate
to one.
Optional properties:
- phy-supply : phandle to a regulator that provides power to VBUS.

View File

@ -6,6 +6,7 @@ controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
Required properties:
- compatible: compatible list, contains:
"qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074
"qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996,
"qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996.
@ -38,6 +39,8 @@ Required properties:
"phy", "common", "cfg".
For "qcom,msm8996-qmp-usb3-phy" must contain
"phy", "common".
For "qcom,ipq8074-qmp-pcie-phy" must contain:
"phy", "common".
- vdda-phy-supply: Phandle to a regulator supply to PHY core block.
- vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
@ -60,6 +63,13 @@ Required properties for child node:
one for each entry in clock-names.
- clock-names: Must contain following for pcie and usb qmp phys:
"pipe<lane-number>" for pipe clock specific to each lane.
- clock-output-names: Name of the PHY clock that will be the parent for
the above pipe clock.
For "qcom,ipq8074-qmp-pcie-phy":
- "pcie20_phy0_pipe_clk" Pipe Clock parent
(or)
"pcie20_phy1_pipe_clk"
- resets: a list of phandles and reset controller specifier pairs,
one for each entry in reset-names.
@ -96,6 +106,7 @@ Example:
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
clock-names = "pipe0";
clock-output-names = "pcie_0_pipe_clk_src";
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
reset-names = "lane0";
};

View File

@ -0,0 +1,23 @@
Mediatek/Ralink USB PHY
Required properties:
- compatible: "ralink,rt3352-usbphy"
"mediatek,mt7620-usbphy"
"mediatek,mt7628-usbphy"
- reg: required for "mediatek,mt7628-usbphy", unused otherwise
- #phy-cells: should be 0
- ralink,sysctl: a phandle to a ralink syscon register region
- resets: the two reset controllers for host and device
- reset-names: the names of the 2 reset controllers
Example:
usbphy: phy {
compatible = "mediatek,mt7628-usbphy";
reg = <0x10120000 0x1000>;
#phy-cells = <0>;
ralink,sysctl = <&sysc>;
resets = <&rstctrl 22 &rstctrl 25>;
reset-names = "host", "device";
};

View File

@ -9,6 +9,7 @@ Required properties:
* allwinner,sun7i-a20-usb-phy
* allwinner,sun8i-a23-usb-phy
* allwinner,sun8i-a33-usb-phy
* allwinner,sun8i-a83t-usb-phy
* allwinner,sun8i-h3-usb-phy
* allwinner,sun8i-v3s-usb-phy
* allwinner,sun50i-a64-usb-phy
@ -17,18 +18,22 @@ Required properties:
* "phy_ctrl"
* "pmu0" for H3, V3s and A64
* "pmu1"
* "pmu2" for sun4i, sun6i or sun7i
* "pmu2" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3
* "pmu3" for sun8i-h3
- #phy-cells : from the generic phy bindings, must be 1
- clocks : phandle + clock specifier for the phy clocks
- clock-names :
* "usb_phy" for sun4i, sun5i or sun7i
* "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
* "usb0_phy", "usb1_phy" for sun8i
* "usb0_phy", "usb1_phy", "usb2_phy" and "usb2_hsic_12M" for sun8i-a83t
* "usb0_phy", "usb1_phy", "usb2_phy" and "usb3_phy" for sun8i-h3
- resets : a list of phandle + reset specifier pairs
- reset-names :
* "usb0_reset"
* "usb1_reset"
* "usb2_reset" for sun4i, sun6i or sun7i
* "usb2_reset" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3
* "usb3_reset" for sun8i-h3
Optional properties:
- usb0_id_det-gpios : gpio phandle for reading the otg id pin value
@ -37,6 +42,7 @@ Optional properties:
- usb0_vbus-supply : regulator phandle for controller usb0 vbus
- usb1_vbus-supply : regulator phandle for controller usb1 vbus
- usb2_vbus-supply : regulator phandle for controller usb2 vbus
- usb3_vbus-supply : regulator phandle for controller usb3 vbus
Example:
usbphy: phy@0x01c13400 {

View File

@ -0,0 +1,29 @@
Broadcom USB Device Controller (BDC)
====================================
Required properties:
- compatible: must be one of:
"brcm,bdc-v0.16"
"brcm,bdc"
- reg: the base register address and length
- interrupts: the interrupt line for this controller
Optional properties:
On Broadcom STB platforms, these properties are required:
- phys: phandle to one or two USB PHY blocks
NOTE: Some SoC's have a single phy and some have
USB 2.0 and USB 3.0 phys
- clocks: phandle to the functional clock of this block
Example:
bdc@f0b02000 {
compatible = "brcm,bdc-v0.16";
reg = <0xf0b02000 0xfc4>;
interrupts = <0x0 0x60 0x0>;
phys = <&usbphy_0 0x0>;
clocks = <&sw_usbd>;
};

View File

@ -12,8 +12,21 @@ Required properties:
MPU.
- ranges: allows valid 1:1 translation between child's address space and
parent's address space.
- clocks: Clock IDs array as required by the controller.
- clock-names: names of clocks correseponding to IDs in the clock property.
SoC-specific Required Properties:
The following are mandatory properties for Keystone 2 66AK2HK, 66AK2L and 66AK2E
SoCs only:
- clocks: Clock ID for USB functional clock.
- clock-names: Must be "usb".
The following are mandatory properties for Keystone 2 66AK2G SoCs only:
- power-domains: Should contain a phandle to a PM domain provider node
and an args specifier containing the USB device id
value. This property is as per the binding,
Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
Sub-nodes:
The dwc3 core should be added as subnode to Keystone DWC3 glue.

View File

@ -11,7 +11,11 @@ into two parts.
------------------------------------------------------------------------
Required properties:
- compatible : should contain "mediatek,mt8173-xhci"
- compatible : should be "mediatek,<soc-model>-xhci", "mediatek,mtk-xhci",
soc-model is the name of SoC, such as mt8173, mt2712 etc, when using
"mediatek,mtk-xhci" compatible string, you need SoC specific ones in
addition, one of:
- "mediatek,mt8173-xhci"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for xHCI MAC and "ippc" for IP port control
- interrupts : interrupt used by the controller
@ -68,10 +72,14 @@ usb30: usb@11270000 {
In the case, xhci is added as subnode to mtu3. An example and the DT binding
details of mtu3 can be found in:
Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
Required properties:
- compatible : should contain "mediatek,mt8173-xhci"
- compatible : should be "mediatek,<soc-model>-xhci", "mediatek,mtk-xhci",
soc-model is the name of SoC, such as mt8173, mt2712 etc, when using
"mediatek,mtk-xhci" compatible string, you need SoC specific ones in
addition, one of:
- "mediatek,mt8173-xhci"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for xHCI MAC
- interrupts : interrupt used by the host controller

View File

@ -1,7 +1,11 @@
The device node for Mediatek USB3.0 DRD controller
Required properties:
- compatible : should be "mediatek,mt8173-mtu3"
- compatible : should be "mediatek,<soc-model>-mtu3", "mediatek,mtu3",
soc-model is the name of SoC, such as mt8173, mt2712 etc,
when using "mediatek,mtu3" compatible string, you need SoC specific
ones in addition, one of:
- "mediatek,mt8173-mtu3"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for device IP and "ippc" for IP port control
- interrupts : interrupt used by the device IP
@ -44,7 +48,7 @@ Optional properties:
Sub-nodes:
The xhci should be added as subnode to mtu3 as shown in the following example
if host mode is enabled. The DT binding details of xhci can be found in:
Documentation/devicetree/bindings/usb/mt8173-xhci.txt
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
Example:
ssusb: usb@11271000 {

View File

@ -3,20 +3,30 @@ Renesas Electronics USB3.0 Peripheral driver
Required properties:
- compatible: Must contain one of the following:
- "renesas,r8a7795-usb3-peri"
- "renesas,r8a7796-usb3-peri"
- "renesas,rcar-gen3-usb3-peri" 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: Base address and length of the register for the USB3.0 Peripheral
- interrupts: Interrupt specifier for the USB3.0 Peripheral
- clocks: clock phandle and specifier pair
Example:
Example of R-Car H3 ES1.x:
usb3_peri0: usb@ee020000 {
compatible = "renesas,r8a7795-usb3-peri";
compatible = "renesas,r8a7795-usb3-peri",
"renesas,rcar-gen3-usb3-peri";
reg = <0 0xee020000 0 0x400>;
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 328>;
};
usb3_peri1: usb@ee060000 {
compatible = "renesas,r8a7795-usb3-peri";
compatible = "renesas,r8a7795-usb3-peri",
"renesas,rcar-gen3-usb3-peri";
reg = <0 0xee060000 0 0x400>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 327>;

View File

@ -1570,7 +1570,7 @@ M: Chunfeng Yun <chunfeng.yun@mediatek.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/phy/phy-mt65xx-usb3.c
F: drivers/phy/mediatek/phy-mtk-tphy.c
ARM/MICREL KS8695 ARCHITECTURE
M: Greg Ungerer <gerg@uclinux.org>
@ -8475,6 +8475,14 @@ M: Sean Wang <sean.wang@mediatek.com>
S: Maintained
F: drivers/char/hw_random/mtk-rng.c
MEDIATEK USB3 DRD IP DRIVER
M: Chunfeng Yun <chunfeng.yun@mediatek.com>
L: linux-usb@vger.kernel.org (moderated for non-subscribers)
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/usb/mtu3/
MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
M: Peter Senna Tschudin <peter.senna@collabora.com>
M: Martin Donnelly <martin.donnelly@ge.com>

View File

@ -26,14 +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_MT65XX_USB3
tristate "Mediatek USB3.0 PHY Driver"
depends on ARCH_MEDIATEK && OF
select GENERIC_PHY
help
Say 'Y' here to add support for Mediatek USB3.0 PHY driver,
it supports multiple usb2.0 and usb3.0 ports.
config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver"
depends on MACH_PISTACHIO
@ -53,8 +45,10 @@ source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig"
source "drivers/phy/hisilicon/Kconfig"
source "drivers/phy/marvell/Kconfig"
source "drivers/phy/mediatek/Kconfig"
source "drivers/phy/motorola/Kconfig"
source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/ralink/Kconfig"
source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"

View File

@ -4,12 +4,12 @@
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_ARCH_SUNXI) += allwinner/
obj-$(CONFIG_ARCH_MESON) += amlogic/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_RENESAS) += renesas/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
@ -18,6 +18,7 @@ obj-y += broadcom/ \
marvell/ \
motorola/ \
qualcomm/ \
ralink/ \
samsung/ \
st/ \
ti/

View File

@ -87,6 +87,16 @@
#define PHY_DISCON_TH_SEL 0x2a
#define PHY_SQUELCH_DETECT 0x3c
/* A83T specific control bits for PHY0 */
#define PHY_CTL_VBUSVLDEXT BIT(5)
#define PHY_CTL_SIDDQ BIT(3)
/* A83T specific control bits for PHY2 HSIC */
#define SUNXI_EHCI_HS_FORCE BIT(20)
#define SUNXI_HSIC_CONNECT_DET BIT(17)
#define SUNXI_HSIC_CONNECT_INT BIT(16)
#define SUNXI_HSIC BIT(1)
#define MAX_PHYS 4
/*
@ -100,6 +110,7 @@ enum sun4i_usb_phy_type {
sun4i_a10_phy,
sun6i_a31_phy,
sun8i_a33_phy,
sun8i_a83t_phy,
sun8i_h3_phy,
sun8i_v3s_phy,
sun50i_a64_phy,
@ -107,6 +118,7 @@ enum sun4i_usb_phy_type {
struct sun4i_usb_phy_cfg {
int num_phys;
int hsic_index;
enum sun4i_usb_phy_type type;
u32 disc_thresh;
u8 phyctl_offset;
@ -126,6 +138,7 @@ struct sun4i_usb_phy_data {
struct regulator *vbus;
struct reset_control *reset;
struct clk *clk;
struct clk *clk2;
bool regulator_on;
int index;
} phys[MAX_PHYS];
@ -232,6 +245,7 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
{
struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
u32 bits, reg_value;
if (!phy->pmu)
@ -240,6 +254,11 @@ static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
/* A83T USB2 is HSIC */
if (phy_data->cfg->type == sun8i_a83t_phy && phy->index == 2)
bits |= SUNXI_EHCI_HS_FORCE | SUNXI_HSIC_CONNECT_INT |
SUNXI_HSIC;
reg_value = readl(phy->pmu);
if (enable)
@ -261,27 +280,43 @@ static int sun4i_usb_phy_init(struct phy *_phy)
if (ret)
return ret;
ret = reset_control_deassert(phy->reset);
ret = clk_prepare_enable(phy->clk2);
if (ret) {
clk_disable_unprepare(phy->clk);
return ret;
}
if (phy->pmu && data->cfg->enable_pmu_unk1) {
val = readl(phy->pmu + REG_PMU_UNK1);
writel(val & ~2, phy->pmu + REG_PMU_UNK1);
ret = reset_control_deassert(phy->reset);
if (ret) {
clk_disable_unprepare(phy->clk2);
clk_disable_unprepare(phy->clk);
return ret;
}
/* Enable USB 45 Ohm resistor calibration */
if (phy->index == 0)
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
if (data->cfg->type == sun8i_a83t_phy) {
if (phy->index == 0) {
val = readl(data->base + data->cfg->phyctl_offset);
val |= PHY_CTL_VBUSVLDEXT;
val &= ~PHY_CTL_SIDDQ;
writel(val, data->base + data->cfg->phyctl_offset);
}
} else {
if (phy->pmu && data->cfg->enable_pmu_unk1) {
val = readl(phy->pmu + REG_PMU_UNK1);
writel(val & ~2, phy->pmu + REG_PMU_UNK1);
}
/* Adjust PHY's magnitude and rate */
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
/* Enable USB 45 Ohm resistor calibration */
if (phy->index == 0)
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
/* Disconnect threshold adjustment */
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
data->cfg->disc_thresh, 2);
/* Adjust PHY's magnitude and rate */
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
/* Disconnect threshold adjustment */
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
data->cfg->disc_thresh, 2);
}
sun4i_usb_phy_passby(phy, 1);
@ -307,6 +342,13 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
if (phy->index == 0) {
if (data->cfg->type == sun8i_a83t_phy) {
void __iomem *phyctl = data->base +
data->cfg->phyctl_offset;
writel(readl(phyctl) | PHY_CTL_SIDDQ, phyctl);
}
/* Disable pull-ups */
sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
@ -315,6 +357,7 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
sun4i_usb_phy_passby(phy, 0);
reset_control_assert(phy->reset);
clk_disable_unprepare(phy->clk2);
clk_disable_unprepare(phy->clk);
return 0;
@ -653,19 +696,25 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
GPIOD_IN);
if (IS_ERR(data->id_det_gpio))
if (IS_ERR(data->id_det_gpio)) {
dev_err(dev, "Couldn't request ID GPIO\n");
return PTR_ERR(data->id_det_gpio);
}
data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
GPIOD_IN);
if (IS_ERR(data->vbus_det_gpio))
if (IS_ERR(data->vbus_det_gpio)) {
dev_err(dev, "Couldn't request VBUS detect GPIO\n");
return PTR_ERR(data->vbus_det_gpio);
}
if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
"usb0_vbus_power-supply");
if (IS_ERR(data->vbus_power_supply))
if (IS_ERR(data->vbus_power_supply)) {
dev_err(dev, "Couldn't get the VBUS power supply\n");
return PTR_ERR(data->vbus_power_supply);
}
if (!data->vbus_power_supply)
return -EPROBE_DEFER;
@ -674,8 +723,10 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
data->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
data->extcon = devm_extcon_dev_allocate(dev, sun4i_usb_phy0_cable);
if (IS_ERR(data->extcon))
if (IS_ERR(data->extcon)) {
dev_err(dev, "Couldn't allocate our extcon device\n");
return PTR_ERR(data->extcon);
}
ret = devm_extcon_dev_register(dev, data->extcon);
if (ret) {
@ -690,8 +741,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
snprintf(name, sizeof(name), "usb%d_vbus", i);
phy->vbus = devm_regulator_get_optional(dev, name);
if (IS_ERR(phy->vbus)) {
if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
if (PTR_ERR(phy->vbus) == -EPROBE_DEFER) {
dev_err(dev,
"Couldn't get regulator %s... Deferring probe\n",
name);
return -EPROBE_DEFER;
}
phy->vbus = NULL;
}
@ -706,6 +762,17 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy->clk);
}
/* The first PHY is always tied to OTG, and never HSIC */
if (data->cfg->hsic_index && i == data->cfg->hsic_index) {
/* HSIC needs secondary clock */
snprintf(name, sizeof(name), "usb%d_hsic_12M", i);
phy->clk2 = devm_clk_get(dev, name);
if (IS_ERR(phy->clk2)) {
dev_err(dev, "failed to get clock %s\n", name);
return PTR_ERR(phy->clk2);
}
}
snprintf(name, sizeof(name), "usb%d_reset", i);
phy->reset = devm_reset_control_get(dev, name);
if (IS_ERR(phy->reset)) {
@ -775,6 +842,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy_provider);
}
dev_dbg(dev, "successfully loaded\n");
return 0;
}
@ -832,6 +901,14 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
.enable_pmu_unk1 = false,
};
static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
.num_phys = 3,
.hsic_index = 2,
.type = sun8i_a83t_phy,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
};
static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
.num_phys = 4,
.type = sun8i_h3_phy,
@ -868,6 +945,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
{ .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
{ .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
{ .compatible = "allwinner,sun8i-a83t-usb-phy", .data = &sun8i_a83t_cfg },
{ .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
{ .compatible = "allwinner,sun50i-a64-usb-phy",

View File

@ -335,7 +335,7 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port)
/* Wait for pll_seq_done bit */
try = 50;
while (try--) {
while (--try) {
val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
BLOCK0_XGXSSTATUS);
if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)

View File

@ -0,0 +1,14 @@
#
# Phy drivers for Mediatek devices
#
config PHY_MTK_TPHY
tristate "MediaTek T-PHY Driver"
depends on ARCH_MEDIATEK && OF
select GENERIC_PHY
help
Say 'Y' here to add support for MediaTek T-PHY driver,
it supports multiple usb2.0, usb3.0 ports, PCIe and
SATA, and meanwhile supports two version T-PHY which have
different banks layout, the T-PHY with shared banks between
multi-ports is first version, otherwise is second veriosn,
so you can easily distinguish them by banks layout.

View File

@ -0,0 +1,5 @@
#
# Makefile for the phy drivers.
#
obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o

View File

@ -29,7 +29,7 @@
#define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */
/* u2 phy bank */
#define SSUSB_SIFSLV_V1_U2PHY_COM 0x000
/* u3 phy banks */
/* u3/pcie/sata phy banks */
#define SSUSB_SIFSLV_V1_U3PHYD 0x000
#define SSUSB_SIFSLV_V1_U3PHYA 0x200
@ -38,7 +38,7 @@
#define SSUSB_SIFSLV_V2_MISC 0x000
#define SSUSB_SIFSLV_V2_U2FREQ 0x100
#define SSUSB_SIFSLV_V2_U2PHY_COM 0x300
/* u3 phy banks */
/* u3/pcie/sata phy banks */
#define SSUSB_SIFSLV_V2_SPLLC 0x000
#define SSUSB_SIFSLV_V2_CHIP 0x100
#define SSUSB_SIFSLV_V2_U3PHYD 0x200
@ -99,6 +99,23 @@
#define P2C_RG_SESSEND BIT(4)
#define P2C_RG_AVALID BIT(2)
#define U3P_U3_CHIP_GPIO_CTLD 0x0c
#define P3C_REG_IP_SW_RST BIT(31)
#define P3C_MCU_BUS_CK_GATE_EN BIT(30)
#define P3C_FORCE_IP_SW_RST BIT(29)
#define U3P_U3_CHIP_GPIO_CTLE 0x10
#define P3C_RG_SWRST_U3_PHYD BIT(25)
#define P3C_RG_SWRST_U3_PHYD_FORCE_EN BIT(24)
#define U3P_U3_PHYA_REG0 0x000
#define P3A_RG_CLKDRV_OFF GENMASK(3, 2)
#define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2)
#define U3P_U3_PHYA_REG1 0x004
#define P3A_RG_CLKDRV_AMP GENMASK(31, 29)
#define P3A_RG_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29)
#define U3P_U3_PHYA_REG6 0x018
#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
@ -108,9 +125,40 @@
#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
#define U3P_U3_PHYA_DA_REG0 0x100
#define P3A_RG_XTAL_EXT_PE2H GENMASK(17, 16)
#define P3A_RG_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16)
#define P3A_RG_XTAL_EXT_PE1H GENMASK(13, 12)
#define P3A_RG_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12)
#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
#define U3P_U3_PHYA_DA_REG4 0x108
#define P3A_RG_PLL_DIVEN_PE2H GENMASK(21, 19)
#define P3A_RG_PLL_BC_PE2H GENMASK(7, 6)
#define P3A_RG_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6)
#define U3P_U3_PHYA_DA_REG5 0x10c
#define P3A_RG_PLL_BR_PE2H GENMASK(29, 28)
#define P3A_RG_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28)
#define P3A_RG_PLL_IC_PE2H GENMASK(15, 12)
#define P3A_RG_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12)
#define U3P_U3_PHYA_DA_REG6 0x110
#define P3A_RG_PLL_IR_PE2H GENMASK(19, 16)
#define P3A_RG_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16)
#define U3P_U3_PHYA_DA_REG7 0x114
#define P3A_RG_PLL_BP_PE2H GENMASK(19, 16)
#define P3A_RG_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16)
#define U3P_U3_PHYA_DA_REG20 0x13c
#define P3A_RG_PLL_DELTA1_PE2H GENMASK(31, 16)
#define P3A_RG_PLL_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16)
#define U3P_U3_PHYA_DA_REG25 0x148
#define P3A_RG_PLL_DELTA_PE2H GENMASK(15, 0)
#define P3A_RG_PLL_DELTA_PE2H_VAL(x) (0xffff & (x))
#define U3P_U3_PHYD_LFPS1 0x00c
#define P3D_RG_FWAKE_TH GENMASK(21, 16)
#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
@ -151,15 +199,74 @@
#define U3P_SR_COEF_DIVISOR 1000
#define U3P_FM_DET_CYCLE_CNT 1024
enum mt_phy_version {
MT_PHY_V1 = 1,
MT_PHY_V2,
/* SATA register setting */
#define PHYD_CTRL_SIGNAL_MODE4 0x1c
/* CDR Charge Pump P-path current adjustment */
#define RG_CDR_BICLTD1_GEN1_MSK GENMASK(23, 20)
#define RG_CDR_BICLTD1_GEN1_VAL(x) ((0xf & (x)) << 20)
#define RG_CDR_BICLTD0_GEN1_MSK GENMASK(11, 8)
#define RG_CDR_BICLTD0_GEN1_VAL(x) ((0xf & (x)) << 8)
#define PHYD_DESIGN_OPTION2 0x24
/* Symbol lock count selection */
#define RG_LOCK_CNT_SEL_MSK GENMASK(5, 4)
#define RG_LOCK_CNT_SEL_VAL(x) ((0x3 & (x)) << 4)
#define PHYD_DESIGN_OPTION9 0x40
/* COMWAK GAP width window */
#define RG_TG_MAX_MSK GENMASK(20, 16)
#define RG_TG_MAX_VAL(x) ((0x1f & (x)) << 16)
/* COMINIT GAP width window */
#define RG_T2_MAX_MSK GENMASK(13, 8)
#define RG_T2_MAX_VAL(x) ((0x3f & (x)) << 8)
/* COMWAK GAP width window */
#define RG_TG_MIN_MSK GENMASK(7, 5)
#define RG_TG_MIN_VAL(x) ((0x7 & (x)) << 5)
/* COMINIT GAP width window */
#define RG_T2_MIN_MSK GENMASK(4, 0)
#define RG_T2_MIN_VAL(x) (0x1f & (x))
#define ANA_RG_CTRL_SIGNAL1 0x4c
/* TX driver tail current control for 0dB de-empahsis mdoe for Gen1 speed */
#define RG_IDRV_0DB_GEN1_MSK GENMASK(13, 8)
#define RG_IDRV_0DB_GEN1_VAL(x) ((0x3f & (x)) << 8)
#define ANA_RG_CTRL_SIGNAL4 0x58
#define RG_CDR_BICLTR_GEN1_MSK GENMASK(23, 20)
#define RG_CDR_BICLTR_GEN1_VAL(x) ((0xf & (x)) << 20)
/* Loop filter R1 resistance adjustment for Gen1 speed */
#define RG_CDR_BR_GEN2_MSK GENMASK(10, 8)
#define RG_CDR_BR_GEN2_VAL(x) ((0x7 & (x)) << 8)
#define ANA_RG_CTRL_SIGNAL6 0x60
/* I-path capacitance adjustment for Gen1 */
#define RG_CDR_BC_GEN1_MSK GENMASK(28, 24)
#define RG_CDR_BC_GEN1_VAL(x) ((0x1f & (x)) << 24)
#define RG_CDR_BIRLTR_GEN1_MSK GENMASK(4, 0)
#define RG_CDR_BIRLTR_GEN1_VAL(x) (0x1f & (x))
#define ANA_EQ_EYE_CTRL_SIGNAL1 0x6c
/* RX Gen1 LEQ tuning step */
#define RG_EQ_DLEQ_LFI_GEN1_MSK GENMASK(11, 8)
#define RG_EQ_DLEQ_LFI_GEN1_VAL(x) ((0xf & (x)) << 8)
#define ANA_EQ_EYE_CTRL_SIGNAL4 0xd8
#define RG_CDR_BIRLTD0_GEN1_MSK GENMASK(20, 16)
#define RG_CDR_BIRLTD0_GEN1_VAL(x) ((0x1f & (x)) << 16)
#define ANA_EQ_EYE_CTRL_SIGNAL5 0xdc
#define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
enum mtk_phy_version {
MTK_PHY_V1 = 1,
MTK_PHY_V2,
};
struct mt65xx_phy_pdata {
struct mtk_phy_pdata {
/* avoid RX sensitivity level degradation only for mt8173 */
bool avoid_rx_sen_degradation;
enum mt_phy_version version;
enum mtk_phy_version version;
};
struct u2phy_banks {
@ -175,7 +282,7 @@ struct u3phy_banks {
void __iomem *phya; /* include u3phya_da */
};
struct mt65xx_phy_instance {
struct mtk_phy_instance {
struct phy *phy;
void __iomem *port_base;
union {
@ -187,18 +294,18 @@ struct mt65xx_phy_instance {
u8 type;
};
struct mt65xx_u3phy {
struct mtk_tphy {
struct device *dev;
void __iomem *sif_base; /* only shared sif */
/* deprecated, use @ref_clk instead in phy instance */
struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
const struct mt65xx_phy_pdata *pdata;
struct mt65xx_phy_instance **phys;
const struct mtk_phy_pdata *pdata;
struct mtk_phy_instance **phys;
int nphys;
};
static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
struct mt65xx_phy_instance *instance)
static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *fmreg = u2_banks->fmreg;
@ -222,7 +329,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
tmp = readl(fmreg + U3P_U2FREQ_FMCR0);
tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL);
tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT);
if (u3phy->pdata->version == MT_PHY_V1)
if (tphy->pdata->version == MTK_PHY_V1)
tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1);
writel(tmp, fmreg + U3P_U2FREQ_FMCR0);
@ -257,7 +364,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
/* if FM detection fail, set default value */
calibration_val = 4;
}
dev_dbg(u3phy->dev, "phy:%d, fm_out:%d, calib:%d\n",
dev_dbg(tphy->dev, "phy:%d, fm_out:%d, calib:%d\n",
instance->index, fm_out, calibration_val);
/* set HS slew rate */
@ -272,8 +379,8 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
writel(tmp, com + U3P_USBPHYACR5);
}
static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy,
struct mt65xx_phy_instance *instance)
static void u3_phy_instance_init(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u3phy_banks *u3_banks = &instance->u3_banks;
u32 tmp;
@ -319,11 +426,11 @@ static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy,
tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2);
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, instance->index);
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
}
static void phy_instance_init(struct mt65xx_u3phy *u3phy,
struct mt65xx_phy_instance *instance)
static void u2_phy_instance_init(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *com = u2_banks->com;
@ -355,7 +462,7 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy,
writel(tmp, com + U3P_U2PHYACR4);
}
if (u3phy->pdata->avoid_rx_sen_degradation) {
if (tphy->pdata->avoid_rx_sen_degradation) {
if (!index) {
tmp = readl(com + U3P_USBPHYACR2);
tmp |= PA2_RG_SIF_U2PLL_FORCE_EN;
@ -381,11 +488,11 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy,
tmp |= PA6_RG_U2_SQTH_VAL(2);
writel(tmp, com + U3P_USBPHYACR6);
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
}
static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
struct mt65xx_phy_instance *instance)
static void u2_phy_instance_power_on(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *com = u2_banks->com;
@ -408,7 +515,7 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
tmp &= ~P2C_RG_SESSEND;
writel(tmp, com + U3P_U2PHYDTM1);
if (u3phy->pdata->avoid_rx_sen_degradation && index) {
if (tphy->pdata->avoid_rx_sen_degradation && index) {
tmp = readl(com + U3D_U2PHYDCR0);
tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
writel(tmp, com + U3D_U2PHYDCR0);
@ -417,11 +524,11 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
writel(tmp, com + U3P_U2PHYDTM0);
}
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
}
static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
struct mt65xx_phy_instance *instance)
static void u2_phy_instance_power_off(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *com = u2_banks->com;
@ -449,24 +556,24 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
tmp |= P2C_RG_SESSEND;
writel(tmp, com + U3P_U2PHYDTM1);
if (u3phy->pdata->avoid_rx_sen_degradation && index) {
if (tphy->pdata->avoid_rx_sen_degradation && index) {
tmp = readl(com + U3D_U2PHYDCR0);
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
writel(tmp, com + U3D_U2PHYDCR0);
}
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
}
static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
struct mt65xx_phy_instance *instance)
static void u2_phy_instance_exit(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *com = u2_banks->com;
u32 index = instance->index;
u32 tmp;
if (u3phy->pdata->avoid_rx_sen_degradation && index) {
if (tphy->pdata->avoid_rx_sen_degradation && index) {
tmp = readl(com + U3D_U2PHYDCR0);
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
writel(tmp, com + U3D_U2PHYDCR0);
@ -477,109 +584,307 @@ static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
}
}
static void phy_v1_banks_init(struct mt65xx_u3phy *u3phy,
struct mt65xx_phy_instance *instance)
static void pcie_phy_instance_init(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u3phy_banks *u3_banks = &instance->u3_banks;
u32 tmp;
if (tphy->pdata->version != MTK_PHY_V1)
return;
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0);
tmp &= ~(P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H);
tmp |= P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | P3A_RG_XTAL_EXT_PE2H_VAL(0x2);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG0);
/* ref clk drive */
tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG1);
tmp &= ~P3A_RG_CLKDRV_AMP;
tmp |= P3A_RG_CLKDRV_AMP_VAL(0x4);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG1);
tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0);
tmp &= ~P3A_RG_CLKDRV_OFF;
tmp |= P3A_RG_CLKDRV_OFF_VAL(0x1);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0);
/* SSC delta -5000ppm */
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG20);
tmp &= ~P3A_RG_PLL_DELTA1_PE2H;
tmp |= P3A_RG_PLL_DELTA1_PE2H_VAL(0x3c);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG20);
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG25);
tmp &= ~P3A_RG_PLL_DELTA_PE2H;
tmp |= P3A_RG_PLL_DELTA_PE2H_VAL(0x36);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG25);
/* change pll BW 0.6M */
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG5);
tmp &= ~(P3A_RG_PLL_BR_PE2H | P3A_RG_PLL_IC_PE2H);
tmp |= P3A_RG_PLL_BR_PE2H_VAL(0x1) | P3A_RG_PLL_IC_PE2H_VAL(0x1);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG5);
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG4);
tmp &= ~(P3A_RG_PLL_DIVEN_PE2H | P3A_RG_PLL_BC_PE2H);
tmp |= P3A_RG_PLL_BC_PE2H_VAL(0x3);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG4);
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG6);
tmp &= ~P3A_RG_PLL_IR_PE2H;
tmp |= P3A_RG_PLL_IR_PE2H_VAL(0x2);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG6);
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG7);
tmp &= ~P3A_RG_PLL_BP_PE2H;
tmp |= P3A_RG_PLL_BP_PE2H_VAL(0xa);
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG7);
/* Tx Detect Rx Timing: 10us -> 5us */
tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET1);
tmp &= ~P3D_RG_RXDET_STB2_SET;
tmp |= P3D_RG_RXDET_STB2_SET_VAL(0x10);
writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET1);
tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET2);
tmp &= ~P3D_RG_RXDET_STB2_SET_P3;
tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2);
/* wait for PCIe subsys register to active */
usleep_range(2500, 3000);
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
}
static void pcie_phy_instance_power_on(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u3phy_banks *bank = &instance->u3_banks;
u32 tmp;
tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLD);
tmp &= ~(P3C_FORCE_IP_SW_RST | P3C_MCU_BUS_CK_GATE_EN |
P3C_REG_IP_SW_RST);
writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLD);
tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLE);
tmp &= ~(P3C_RG_SWRST_U3_PHYD_FORCE_EN | P3C_RG_SWRST_U3_PHYD);
writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLE);
}
static void pcie_phy_instance_power_off(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u3phy_banks *bank = &instance->u3_banks;
u32 tmp;
tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLD);
tmp |= P3C_FORCE_IP_SW_RST | P3C_REG_IP_SW_RST;
writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLD);
tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLE);
tmp |= P3C_RG_SWRST_U3_PHYD_FORCE_EN | P3C_RG_SWRST_U3_PHYD;
writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLE);
}
static void sata_phy_instance_init(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u3phy_banks *u3_banks = &instance->u3_banks;
void __iomem *phyd = u3_banks->phyd;
u32 tmp;
/* charge current adjustment */
tmp = readl(phyd + ANA_RG_CTRL_SIGNAL6);
tmp &= ~(RG_CDR_BIRLTR_GEN1_MSK | RG_CDR_BC_GEN1_MSK);
tmp |= RG_CDR_BIRLTR_GEN1_VAL(0x6) | RG_CDR_BC_GEN1_VAL(0x1a);
writel(tmp, phyd + ANA_RG_CTRL_SIGNAL6);
tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL4);
tmp &= ~RG_CDR_BIRLTD0_GEN1_MSK;
tmp |= RG_CDR_BIRLTD0_GEN1_VAL(0x18);
writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL4);
tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL5);
tmp &= ~RG_CDR_BIRLTD0_GEN3_MSK;
tmp |= RG_CDR_BIRLTD0_GEN3_VAL(0x06);
writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL5);
tmp = readl(phyd + ANA_RG_CTRL_SIGNAL4);
tmp &= ~(RG_CDR_BICLTR_GEN1_MSK | RG_CDR_BR_GEN2_MSK);
tmp |= RG_CDR_BICLTR_GEN1_VAL(0x0c) | RG_CDR_BR_GEN2_VAL(0x07);
writel(tmp, phyd + ANA_RG_CTRL_SIGNAL4);
tmp = readl(phyd + PHYD_CTRL_SIGNAL_MODE4);
tmp &= ~(RG_CDR_BICLTD0_GEN1_MSK | RG_CDR_BICLTD1_GEN1_MSK);
tmp |= RG_CDR_BICLTD0_GEN1_VAL(0x08) | RG_CDR_BICLTD1_GEN1_VAL(0x02);
writel(tmp, phyd + PHYD_CTRL_SIGNAL_MODE4);
tmp = readl(phyd + PHYD_DESIGN_OPTION2);
tmp &= ~RG_LOCK_CNT_SEL_MSK;
tmp |= RG_LOCK_CNT_SEL_VAL(0x02);
writel(tmp, phyd + PHYD_DESIGN_OPTION2);
tmp = readl(phyd + PHYD_DESIGN_OPTION9);
tmp &= ~(RG_T2_MIN_MSK | RG_TG_MIN_MSK |
RG_T2_MAX_MSK | RG_TG_MAX_MSK);
tmp |= RG_T2_MIN_VAL(0x12) | RG_TG_MIN_VAL(0x04) |
RG_T2_MAX_VAL(0x31) | RG_TG_MAX_VAL(0x0e);
writel(tmp, phyd + PHYD_DESIGN_OPTION9);
tmp = readl(phyd + ANA_RG_CTRL_SIGNAL1);
tmp &= ~RG_IDRV_0DB_GEN1_MSK;
tmp |= RG_IDRV_0DB_GEN1_VAL(0x20);
writel(tmp, phyd + ANA_RG_CTRL_SIGNAL1);
tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL1);
tmp &= ~RG_EQ_DLEQ_LFI_GEN1_MSK;
tmp |= RG_EQ_DLEQ_LFI_GEN1_VAL(0x03);
writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL1);
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
}
static void phy_v1_banks_init(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u2phy_banks *u2_banks = &instance->u2_banks;
struct u3phy_banks *u3_banks = &instance->u3_banks;
if (instance->type == PHY_TYPE_USB2) {
switch (instance->type) {
case PHY_TYPE_USB2:
u2_banks->misc = NULL;
u2_banks->fmreg = u3phy->sif_base + SSUSB_SIFSLV_V1_U2FREQ;
u2_banks->fmreg = tphy->sif_base + SSUSB_SIFSLV_V1_U2FREQ;
u2_banks->com = instance->port_base + SSUSB_SIFSLV_V1_U2PHY_COM;
} else if (instance->type == PHY_TYPE_USB3) {
u3_banks->spllc = u3phy->sif_base + SSUSB_SIFSLV_V1_SPLLC;
break;
case PHY_TYPE_USB3:
case PHY_TYPE_PCIE:
u3_banks->spllc = tphy->sif_base + SSUSB_SIFSLV_V1_SPLLC;
u3_banks->chip = NULL;
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD;
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA;
break;
case PHY_TYPE_SATA:
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD;
break;
default:
dev_err(tphy->dev, "incompatible PHY type\n");
return;
}
}
static void phy_v2_banks_init(struct mt65xx_u3phy *u3phy,
struct mt65xx_phy_instance *instance)
static void phy_v2_banks_init(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
struct u2phy_banks *u2_banks = &instance->u2_banks;
struct u3phy_banks *u3_banks = &instance->u3_banks;
if (instance->type == PHY_TYPE_USB2) {
switch (instance->type) {
case PHY_TYPE_USB2:
u2_banks->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC;
u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ;
u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM;
} else if (instance->type == PHY_TYPE_USB3) {
break;
case PHY_TYPE_USB3:
case PHY_TYPE_PCIE:
u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V2_SPLLC;
u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP;
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD;
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V2_U3PHYA;
break;
default:
dev_err(tphy->dev, "incompatible PHY type\n");
return;
}
}
static int mt65xx_phy_init(struct phy *phy)
static int mtk_phy_init(struct phy *phy)
{
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
int ret;
ret = clk_prepare_enable(u3phy->u3phya_ref);
ret = clk_prepare_enable(tphy->u3phya_ref);
if (ret) {
dev_err(u3phy->dev, "failed to enable u3phya_ref\n");
dev_err(tphy->dev, "failed to enable u3phya_ref\n");
return ret;
}
ret = clk_prepare_enable(instance->ref_clk);
if (ret) {
dev_err(u3phy->dev, "failed to enable ref_clk\n");
dev_err(tphy->dev, "failed to enable ref_clk\n");
return ret;
}
if (instance->type == PHY_TYPE_USB2)
phy_instance_init(u3phy, instance);
else
u3_phy_instance_init(u3phy, instance);
switch (instance->type) {
case PHY_TYPE_USB2:
u2_phy_instance_init(tphy, instance);
break;
case PHY_TYPE_USB3:
u3_phy_instance_init(tphy, instance);
break;
case PHY_TYPE_PCIE:
pcie_phy_instance_init(tphy, instance);
break;
case PHY_TYPE_SATA:
sata_phy_instance_init(tphy, instance);
break;
default:
dev_err(tphy->dev, "incompatible PHY type\n");
return -EINVAL;
}
return 0;
}
static int mt65xx_phy_power_on(struct phy *phy)
static int mtk_phy_power_on(struct phy *phy)
{
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
if (instance->type == PHY_TYPE_USB2) {
phy_instance_power_on(u3phy, instance);
hs_slew_rate_calibrate(u3phy, instance);
u2_phy_instance_power_on(tphy, instance);
hs_slew_rate_calibrate(tphy, instance);
} else if (instance->type == PHY_TYPE_PCIE) {
pcie_phy_instance_power_on(tphy, instance);
}
return 0;
}
static int mt65xx_phy_power_off(struct phy *phy)
{
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
if (instance->type == PHY_TYPE_USB2)
phy_instance_power_off(u3phy, instance);
return 0;
}
static int mt65xx_phy_exit(struct phy *phy)
static int mtk_phy_power_off(struct phy *phy)
{
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
if (instance->type == PHY_TYPE_USB2)
phy_instance_exit(u3phy, instance);
u2_phy_instance_power_off(tphy, instance);
else if (instance->type == PHY_TYPE_PCIE)
pcie_phy_instance_power_off(tphy, instance);
return 0;
}
static int mtk_phy_exit(struct phy *phy)
{
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
if (instance->type == PHY_TYPE_USB2)
u2_phy_instance_exit(tphy, instance);
clk_disable_unprepare(instance->ref_clk);
clk_disable_unprepare(u3phy->u3phya_ref);
clk_disable_unprepare(tphy->u3phya_ref);
return 0;
}
static struct phy *mt65xx_phy_xlate(struct device *dev,
static struct phy *mtk_phy_xlate(struct device *dev,
struct of_phandle_args *args)
{
struct mt65xx_u3phy *u3phy = dev_get_drvdata(dev);
struct mt65xx_phy_instance *instance = NULL;
struct mtk_tphy *tphy = dev_get_drvdata(dev);
struct mtk_phy_instance *instance = NULL;
struct device_node *phy_np = args->np;
int index;
@ -588,9 +893,9 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
return ERR_PTR(-EINVAL);
}
for (index = 0; index < u3phy->nphys; index++)
if (phy_np == u3phy->phys[index]->phy->dev.of_node) {
instance = u3phy->phys[index];
for (index = 0; index < tphy->nphys; index++)
if (phy_np == tphy->phys[index]->phy->dev.of_node) {
instance = tphy->phys[index];
break;
}
@ -601,15 +906,17 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
instance->type = args->args[0];
if (!(instance->type == PHY_TYPE_USB2 ||
instance->type == PHY_TYPE_USB3)) {
instance->type == PHY_TYPE_USB3 ||
instance->type == PHY_TYPE_PCIE ||
instance->type == PHY_TYPE_SATA)) {
dev_err(dev, "unsupported device type: %d\n", instance->type);
return ERR_PTR(-EINVAL);
}
if (u3phy->pdata->version == MT_PHY_V1) {
phy_v1_banks_init(u3phy, instance);
} else if (u3phy->pdata->version == MT_PHY_V2) {
phy_v2_banks_init(u3phy, instance);
if (tphy->pdata->version == MTK_PHY_V1) {
phy_v1_banks_init(tphy, instance);
} else if (tphy->pdata->version == MTK_PHY_V2) {
phy_v2_banks_init(tphy, instance);
} else {
dev_err(dev, "phy version is not supported\n");
return ERR_PTR(-EINVAL);
@ -618,38 +925,40 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
return instance->phy;
}
static const struct phy_ops mt65xx_u3phy_ops = {
.init = mt65xx_phy_init,
.exit = mt65xx_phy_exit,
.power_on = mt65xx_phy_power_on,
.power_off = mt65xx_phy_power_off,
static const struct phy_ops mtk_tphy_ops = {
.init = mtk_phy_init,
.exit = mtk_phy_exit,
.power_on = mtk_phy_power_on,
.power_off = mtk_phy_power_off,
.owner = THIS_MODULE,
};
static const struct mt65xx_phy_pdata mt2701_pdata = {
static const struct mtk_phy_pdata tphy_v1_pdata = {
.avoid_rx_sen_degradation = false,
.version = MT_PHY_V1,
.version = MTK_PHY_V1,
};
static const struct mt65xx_phy_pdata mt2712_pdata = {
static const struct mtk_phy_pdata tphy_v2_pdata = {
.avoid_rx_sen_degradation = false,
.version = MT_PHY_V2,
.version = MTK_PHY_V2,
};
static const struct mt65xx_phy_pdata mt8173_pdata = {
static const struct mtk_phy_pdata mt8173_pdata = {
.avoid_rx_sen_degradation = true,
.version = MT_PHY_V1,
.version = MTK_PHY_V1,
};
static const struct of_device_id mt65xx_u3phy_id_table[] = {
{ .compatible = "mediatek,mt2701-u3phy", .data = &mt2701_pdata },
{ .compatible = "mediatek,mt2712-u3phy", .data = &mt2712_pdata },
static const struct of_device_id mtk_tphy_id_table[] = {
{ .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata },
{ .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata },
{ .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata },
{ .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata },
{ .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata },
{ },
};
MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
MODULE_DEVICE_TABLE(of, mtk_tphy_id_table);
static int mt65xx_u3phy_probe(struct platform_device *pdev)
static int mtk_tphy_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct device *dev = &pdev->dev;
@ -657,50 +966,50 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
struct device_node *child_np;
struct phy_provider *provider;
struct resource *sif_res;
struct mt65xx_u3phy *u3phy;
struct mtk_tphy *tphy;
struct resource res;
int port, retval;
match = of_match_node(mt65xx_u3phy_id_table, pdev->dev.of_node);
match = of_match_node(mtk_tphy_id_table, pdev->dev.of_node);
if (!match)
return -EINVAL;
u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
if (!u3phy)
tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL);
if (!tphy)
return -ENOMEM;
u3phy->pdata = match->data;
u3phy->nphys = of_get_child_count(np);
u3phy->phys = devm_kcalloc(dev, u3phy->nphys,
sizeof(*u3phy->phys), GFP_KERNEL);
if (!u3phy->phys)
tphy->pdata = match->data;
tphy->nphys = of_get_child_count(np);
tphy->phys = devm_kcalloc(dev, tphy->nphys,
sizeof(*tphy->phys), GFP_KERNEL);
if (!tphy->phys)
return -ENOMEM;
u3phy->dev = dev;
platform_set_drvdata(pdev, u3phy);
tphy->dev = dev;
platform_set_drvdata(pdev, tphy);
if (u3phy->pdata->version == MT_PHY_V1) {
if (tphy->pdata->version == MTK_PHY_V1) {
/* get banks shared by multiple phys */
sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
u3phy->sif_base = devm_ioremap_resource(dev, sif_res);
if (IS_ERR(u3phy->sif_base)) {
tphy->sif_base = devm_ioremap_resource(dev, sif_res);
if (IS_ERR(tphy->sif_base)) {
dev_err(dev, "failed to remap sif regs\n");
return PTR_ERR(u3phy->sif_base);
return PTR_ERR(tphy->sif_base);
}
}
/* it's deprecated, make it optional for backward compatibility */
u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref");
if (IS_ERR(u3phy->u3phya_ref)) {
if (PTR_ERR(u3phy->u3phya_ref) == -EPROBE_DEFER)
tphy->u3phya_ref = devm_clk_get(dev, "u3phya_ref");
if (IS_ERR(tphy->u3phya_ref)) {
if (PTR_ERR(tphy->u3phya_ref) == -EPROBE_DEFER)
return -EPROBE_DEFER;
u3phy->u3phya_ref = NULL;
tphy->u3phya_ref = NULL;
}
port = 0;
for_each_child_of_node(np, child_np) {
struct mt65xx_phy_instance *instance;
struct mtk_phy_instance *instance;
struct phy *phy;
instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
@ -709,9 +1018,9 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
goto put_child;
}
u3phy->phys[port] = instance;
tphy->phys[port] = instance;
phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops);
phy = devm_phy_create(dev, child_np, &mtk_tphy_ops);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n");
retval = PTR_ERR(phy);
@ -738,7 +1047,7 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
port++;
/* if deprecated clock is provided, ignore instance's one */
if (u3phy->u3phya_ref)
if (tphy->u3phya_ref)
continue;
instance->ref_clk = devm_clk_get(&phy->dev, "ref");
@ -749,7 +1058,7 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
}
}
provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate);
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
return PTR_ERR_OR_ZERO(provider);
put_child:
@ -757,16 +1066,16 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
return retval;
}
static struct platform_driver mt65xx_u3phy_driver = {
.probe = mt65xx_u3phy_probe,
static struct platform_driver mtk_tphy_driver = {
.probe = mtk_tphy_probe,
.driver = {
.name = "mt65xx-u3phy",
.of_match_table = mt65xx_u3phy_id_table,
.name = "mtk-tphy",
.of_match_table = mtk_tphy_id_table,
},
};
module_platform_driver(mt65xx_u3phy_driver);
module_platform_driver(mtk_tphy_driver);
MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
MODULE_DESCRIPTION("mt65xx USB PHY driver");
MODULE_DESCRIPTION("MediaTek T-PHY driver");
MODULE_LICENSE("GPL v2");

View File

@ -506,7 +506,7 @@ static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
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;
ddata->gpio[i] = NULL;
}
}
}

View File

@ -59,6 +59,7 @@
#define QSERDES_COM_PLL_RCTRL_MODE1 0x088
#define QSERDES_COM_PLL_CCTRL_MODE0 0x090
#define QSERDES_COM_PLL_CCTRL_MODE1 0x094
#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x0a8
#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac
#define QSERDES_COM_RESETSM_CNTRL 0x0b4
#define QSERDES_COM_RESTRIM_CTRL 0x0bc
@ -143,6 +144,11 @@
#define QPHY_LOCK_DETECT_CONFIG3 0x88
#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
#define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8
#define QPHY_OSC_DTCT_ACTIONS 0x1AC
#define QPHY_RX_SIGDET_LVL 0x1D8
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
/* QPHY_SW_RESET bit */
#define SW_RESET BIT(0)
@ -382,6 +388,85 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08),
};
static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6),
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf),
QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0),
QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x1),
QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x20),
QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0xa),
QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0xa),
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xa),
QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x3),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x0),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0xD),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xD04),
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33),
QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x2),
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0xb),
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0),
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0xa),
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1),
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1),
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x2),
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x0),
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19),
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19),
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x7),
};
static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6),
QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2),
QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12),
};
static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb),
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4),
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x4),
};
static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x4),
QMP_PHY_INIT_CFG(QPHY_OSC_DTCT_ACTIONS, 0x0),
QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x40),
QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x0),
QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x40),
QMP_PHY_INIT_CFG(QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB, 0x0),
QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x40),
QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x73),
QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_LVL, 0x99),
QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M6DB_V0, 0x15),
QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0xe),
QMP_PHY_INIT_CFG_L(QPHY_SW_RESET, 0x0),
QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3),
};
/* struct qmp_phy_cfg - per-PHY initialization config */
struct qmp_phy_cfg {
/* phy-type - PCIE/UFS/USB */
@ -580,6 +665,42 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
.mask_pcs_ready = PHYSTATUS,
};
/* list of resets */
static const char * const ipq8074_pciephy_reset_l[] = {
"phy", "common",
};
static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
.type = PHY_TYPE_PCIE,
.nlanes = 1,
.serdes_tbl = ipq8074_pcie_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl),
.tx_tbl = ipq8074_pcie_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl),
.rx_tbl = ipq8074_pcie_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl),
.pcs_tbl = ipq8074_pcie_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl),
.clk_list = NULL,
.num_clks = 0,
.reset_list = ipq8074_pciephy_reset_l,
.num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
.vreg_list = NULL,
.num_vregs = 0,
.regs = pciephy_regs_layout,
.start_ctrl = SERDES_START | PCS_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.mask_pcs_ready = PHYSTATUS,
.has_phy_com_ctrl = false,
.has_lane_rst = false,
.has_pwrdn_delay = true,
.pwrdn_delay_min = 995, /* us */
.pwrdn_delay_max = 1005, /* us */
};
static void qcom_qmp_phy_configure(void __iomem *base,
const unsigned int *regs,
const struct qmp_phy_init_tbl tbl[],
@ -654,8 +775,6 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
if (ret) {
dev_err(qmp->dev, "%s reset deassert failed\n",
qmp->cfg->reset_list[i]);
while (--i >= 0)
reset_control_assert(qmp->resets[i]);
goto err_rst;
}
}
@ -684,7 +803,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
if (ret) {
dev_err(qmp->dev,
"phy common block init timed-out\n");
goto err_com_init;
goto err_rst;
}
}
@ -692,11 +811,11 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
return 0;
err_com_init:
err_rst:
while (--i >= 0)
reset_control_assert(qmp->resets[i]);
err_rst:
mutex_unlock(&qmp->phy_mutex);
return ret;
}
@ -749,14 +868,13 @@ static int qcom_qmp_phy_init(struct phy *phy)
if (ret) {
dev_err(qmp->dev, "failed to enable %s clk, err=%d\n",
qmp->cfg->clk_list[i], ret);
while (--i >= 0)
clk_disable_unprepare(qmp->clks[i]);
goto err_clk;
}
}
ret = qcom_qmp_phy_com_init(qmp);
if (ret)
goto err_com_init;
goto err_clk;
if (cfg->has_lane_rst) {
ret = reset_control_deassert(qphy->lane_rst);
@ -804,7 +922,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
reset_control_assert(qphy->lane_rst);
err_lane_rst:
qcom_qmp_phy_com_exit(qmp);
err_com_init:
err_clk:
while (--i >= 0)
clk_disable_unprepare(qmp->clks[i]);
@ -925,29 +1043,28 @@ static int qcom_qmp_phy_clk_init(struct device *dev)
* clk | +-------+ | +-----+
* +---------------+
*/
static int phy_pipe_clk_register(struct qcom_qmp *qmp, int id)
static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
{
char name[24];
struct clk_fixed_rate *fixed;
struct clk_init_data init = { };
int ret;
switch (qmp->cfg->type) {
case PHY_TYPE_USB3:
snprintf(name, sizeof(name), "usb3_phy_pipe_clk_src");
break;
case PHY_TYPE_PCIE:
snprintf(name, sizeof(name), "pcie_%d_pipe_clk_src", id);
break;
default:
if ((qmp->cfg->type != PHY_TYPE_USB3) &&
(qmp->cfg->type != PHY_TYPE_PCIE)) {
/* not all phys register pipe clocks, so return success */
return 0;
}
ret = of_property_read_string(np, "clock-output-names", &init.name);
if (ret) {
dev_err(qmp->dev, "%s: No clock-output-names\n", np->name);
return ret;
}
fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL);
if (!fixed)
return -ENOMEM;
init.name = name;
init.ops = &clk_fixed_rate_ops;
/* controllers using QMP phys use 125MHz pipe clock interface */
@ -1049,6 +1166,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
}, {
.compatible = "qcom,msm8996-qmp-usb3-phy",
.data = &msm8996_usb3phy_cfg,
}, {
.compatible = "qcom,ipq8074-qmp-pcie-phy",
.data = &ipq8074_pciephy_cfg,
},
{ },
};
@ -1122,7 +1242,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
* Register the pipe clock provided by phy.
* See function description to see details of this pipe clock.
*/
ret = phy_pipe_clk_register(qmp, id);
ret = phy_pipe_clk_register(qmp, child);
if (ret) {
dev_err(qmp->dev,
"failed to register pipe clock source\n");

View File

@ -0,0 +1,11 @@
#
# PHY drivers for Ralink platforms.
#
config PHY_RALINK_USB
tristate "Ralink USB PHY driver"
depends on RALINK || COMPILE_TEST
select GENERIC_PHY
select MFD_SYSCON
help
This option enables support for the Ralink USB PHY found inside
RT3352, MT7620, MT7628 and MT7688.

View File

@ -0,0 +1 @@
obj-$(CONFIG_PHY_RALINK_USB) += phy-ralink-usb.o

View File

@ -0,0 +1,249 @@
/*
* Copyright (C) 2017 John Crispin <john@phrozen.org>
*
* Based on code from
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_platform.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#define RT_SYSC_REG_SYSCFG1 0x014
#define RT_SYSC_REG_CLKCFG1 0x030
#define RT_SYSC_REG_USB_PHY_CFG 0x05c
#define OFS_U2_PHY_AC0 0x800
#define OFS_U2_PHY_AC1 0x804
#define OFS_U2_PHY_AC2 0x808
#define OFS_U2_PHY_ACR0 0x810
#define OFS_U2_PHY_ACR1 0x814
#define OFS_U2_PHY_ACR2 0x818
#define OFS_U2_PHY_ACR3 0x81C
#define OFS_U2_PHY_ACR4 0x820
#define OFS_U2_PHY_AMON0 0x824
#define OFS_U2_PHY_DCR0 0x860
#define OFS_U2_PHY_DCR1 0x864
#define OFS_U2_PHY_DTM0 0x868
#define OFS_U2_PHY_DTM1 0x86C
#define RT_RSTCTRL_UDEV BIT(25)
#define RT_RSTCTRL_UHST BIT(22)
#define RT_SYSCFG1_USB0_HOST_MODE BIT(10)
#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25)
#define MT7620_CLKCFG1_UPHY1_CLK_EN BIT(22)
#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20)
#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18)
#define USB_PHY_UTMI_8B60M BIT(1)
#define UDEV_WAKEUP BIT(0)
struct ralink_usb_phy {
struct reset_control *rstdev;
struct reset_control *rsthost;
u32 clk;
struct phy *phy;
void __iomem *base;
struct regmap *sysctl;
};
static void u2_phy_w32(struct ralink_usb_phy *phy, u32 val, u32 reg)
{
writel(val, phy->base + reg);
}
static u32 u2_phy_r32(struct ralink_usb_phy *phy, u32 reg)
{
return readl(phy->base + reg);
}
static void ralink_usb_phy_init(struct ralink_usb_phy *phy)
{
u2_phy_r32(phy, OFS_U2_PHY_AC2);
u2_phy_r32(phy, OFS_U2_PHY_ACR0);
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);
u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);
u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);
u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);
}
static int ralink_usb_phy_power_on(struct phy *_phy)
{
struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
u32 t;
/* enable the phy */
regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
phy->clk, phy->clk);
/* setup host mode */
regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1,
RT_SYSCFG1_USB0_HOST_MODE,
RT_SYSCFG1_USB0_HOST_MODE);
/* deassert the reset lines */
reset_control_deassert(phy->rsthost);
reset_control_deassert(phy->rstdev);
/*
* The SDK kernel had a delay of 100ms. however on device
* testing showed that 10ms is enough
*/
mdelay(10);
if (phy->base)
ralink_usb_phy_init(phy);
/* print some status info */
regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t);
dev_info(&phy->phy->dev, "remote usb device wakeup %s\n",
(t & UDEV_WAKEUP) ? ("enabled") : ("disabled"));
if (t & USB_PHY_UTMI_8B60M)
dev_info(&phy->phy->dev, "UTMI 8bit 60MHz\n");
else
dev_info(&phy->phy->dev, "UTMI 16bit 30MHz\n");
return 0;
}
static int ralink_usb_phy_power_off(struct phy *_phy)
{
struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
/* disable the phy */
regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
phy->clk, 0);
/* assert the reset lines */
reset_control_assert(phy->rstdev);
reset_control_assert(phy->rsthost);
return 0;
}
static struct phy_ops ralink_usb_phy_ops = {
.power_on = ralink_usb_phy_power_on,
.power_off = ralink_usb_phy_power_off,
.owner = THIS_MODULE,
};
static const struct of_device_id ralink_usb_phy_of_match[] = {
{
.compatible = "ralink,rt3352-usbphy",
.data = (void *)(uintptr_t)(RT_CLKCFG1_UPHY1_CLK_EN |
RT_CLKCFG1_UPHY0_CLK_EN)
},
{
.compatible = "mediatek,mt7620-usbphy",
.data = (void *)(uintptr_t)(MT7620_CLKCFG1_UPHY1_CLK_EN |
MT7620_CLKCFG1_UPHY0_CLK_EN)
},
{
.compatible = "mediatek,mt7628-usbphy",
.data = (void *)(uintptr_t)(MT7620_CLKCFG1_UPHY1_CLK_EN |
MT7620_CLKCFG1_UPHY0_CLK_EN) },
{ },
};
MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match);
static int ralink_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct phy_provider *phy_provider;
const struct of_device_id *match;
struct ralink_usb_phy *phy;
match = of_match_device(ralink_usb_phy_of_match, &pdev->dev);
if (!match)
return -ENODEV;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
phy->clk = (uintptr_t)match->data;
phy->base = NULL;
phy->sysctl = syscon_regmap_lookup_by_phandle(dev->of_node, "ralink,sysctl");
if (IS_ERR(phy->sysctl)) {
dev_err(dev, "failed to get sysctl registers\n");
return PTR_ERR(phy->sysctl);
}
/* The MT7628 and MT7688 require extra setup of PHY registers. */
if (of_device_is_compatible(dev->of_node, "mediatek,mt7628-usbphy")) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
phy->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(phy->base)) {
dev_err(dev, "failed to remap register memory\n");
return PTR_ERR(phy->base);
}
}
phy->rsthost = devm_reset_control_get(&pdev->dev, "host");
if (IS_ERR(phy->rsthost)) {
dev_err(dev, "host reset is missing\n");
return PTR_ERR(phy->rsthost);
}
phy->rstdev = devm_reset_control_get(&pdev->dev, "device");
if (IS_ERR(phy->rstdev)) {
dev_err(dev, "device reset is missing\n");
return PTR_ERR(phy->rstdev);
}
phy->phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops);
if (IS_ERR(phy->phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(phy->phy);
}
phy_set_drvdata(phy->phy, phy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static struct platform_driver ralink_usb_phy_driver = {
.probe = ralink_usb_phy_probe,
.driver = {
.of_match_table = ralink_usb_phy_of_match,
.name = "ralink-usb-phy",
}
};
module_platform_driver(ralink_usb_phy_driver);
MODULE_DESCRIPTION("Ralink USB phy driver");
MODULE_AUTHOR("John Crispin <john@phrozen.org>");
MODULE_LICENSE("GPL v2");

View File

@ -172,6 +172,8 @@ struct rockchip_usb2phy_cfg {
* @vbus_attached: otg device vbus status.
* @bvalid_irq: IRQ number assigned for vbus valid rise detection.
* @ls_irq: IRQ number assigned for linestate detection.
* @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate
* irqs to one irq in otg-port.
* @mutex: for register updating in sm_work.
* @chg_work: charge detect work.
* @otg_sm_work: OTG state machine work.
@ -189,6 +191,7 @@ struct rockchip_usb2phy_port {
bool vbus_attached;
int bvalid_irq;
int ls_irq;
int otg_mux_irq;
struct mutex mutex;
struct delayed_work chg_work;
struct delayed_work otg_sm_work;
@ -202,6 +205,7 @@ struct rockchip_usb2phy_port {
/**
* struct rockchip_usb2phy: usb2.0 phy driver data.
* @grf: General Register Files regmap.
* @usbgrf: USB General Register Files regmap.
* @clk: clock struct of phy input clk.
* @clk480m: clock struct of phy output clk.
* @clk_hw: clock struct of phy output clk management.
@ -216,6 +220,7 @@ struct rockchip_usb2phy_port {
struct rockchip_usb2phy {
struct device *dev;
struct regmap *grf;
struct regmap *usbgrf;
struct clk *clk;
struct clk *clk480m;
struct clk_hw clk480m_hw;
@ -227,7 +232,12 @@ struct rockchip_usb2phy {
struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
};
static inline int property_enable(struct rockchip_usb2phy *rphy,
static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
{
return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf;
}
static inline int property_enable(struct regmap *base,
const struct usb2phy_reg *reg, bool en)
{
unsigned int val, mask, tmp;
@ -236,17 +246,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy,
mask = GENMASK(reg->bitend, reg->bitstart);
val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
return regmap_write(rphy->grf, reg->offset, val);
return regmap_write(base, reg->offset, val);
}
static inline bool property_enabled(struct rockchip_usb2phy *rphy,
static inline bool property_enabled(struct regmap *base,
const struct usb2phy_reg *reg)
{
int ret;
unsigned int tmp, orig;
unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
ret = regmap_read(rphy->grf, reg->offset, &orig);
ret = regmap_read(base, reg->offset, &orig);
if (ret)
return false;
@ -258,11 +268,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
struct regmap *base = get_reg_base(rphy);
int ret;
/* turn on 480m clk output if it is off */
if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) {
ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true);
if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
if (ret)
return ret;
@ -277,17 +288,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
struct regmap *base = get_reg_base(rphy);
/* turn off 480m clk output */
property_enable(rphy, &rphy->phy_cfg->clkout_ctl, false);
property_enable(base, &rphy->phy_cfg->clkout_ctl, false);
}
static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
struct regmap *base = get_reg_base(rphy);
return property_enabled(rphy, &rphy->phy_cfg->clkout_ctl);
return property_enabled(base, &rphy->phy_cfg->clkout_ctl);
}
static unsigned long
@ -409,13 +422,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
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,
ret = property_enable(rphy->grf,
&rport->port_cfg->bvalid_det_clr,
true);
if (ret)
goto out;
ret = property_enable(rphy,
ret = property_enable(rphy->grf,
&rport->port_cfg->bvalid_det_en,
true);
if (ret)
@ -429,11 +442,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
}
} else if (rport->port_id == USB2PHY_PORT_HOST) {
/* clear linestate and enable linestate detect irq */
ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
ret = property_enable(rphy->grf,
&rport->port_cfg->ls_det_clr, true);
if (ret)
goto out;
ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
ret = property_enable(rphy->grf,
&rport->port_cfg->ls_det_en, true);
if (ret)
goto out;
@ -449,6 +464,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
{
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
int ret;
dev_dbg(&rport->phy->dev, "port power on\n");
@ -460,7 +476,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
if (ret)
return ret;
ret = property_enable(rphy, &rport->port_cfg->phy_sus, false);
ret = property_enable(base, &rport->port_cfg->phy_sus, false);
if (ret)
return ret;
@ -475,6 +491,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
{
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
int ret;
dev_dbg(&rport->phy->dev, "port power off\n");
@ -482,7 +499,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
if (rport->suspended)
return 0;
ret = property_enable(rphy, &rport->port_cfg->phy_sus, true);
ret = property_enable(base, &rport->port_cfg->phy_sus, true);
if (ret)
return ret;
@ -526,11 +543,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
bool vbus_attach, sch_work, notify_charger;
if (rport->utmi_avalid)
vbus_attach =
property_enabled(rphy, &rport->port_cfg->utmi_avalid);
vbus_attach = property_enabled(rphy->grf,
&rport->port_cfg->utmi_avalid);
else
vbus_attach =
property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
vbus_attach = property_enabled(rphy->grf,
&rport->port_cfg->utmi_bvalid);
sch_work = false;
notify_charger = false;
@ -650,22 +667,28 @@ static const char *chg_to_string(enum power_supply_type chg_type)
static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
bool en)
{
property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
struct regmap *base = get_reg_base(rphy);
property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en);
}
static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
bool en)
{
property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
struct regmap *base = get_reg_base(rphy);
property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en);
}
static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
bool en)
{
property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
struct regmap *base = get_reg_base(rphy);
property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en);
}
#define CHG_DCD_POLL_TIME (100 * HZ / 1000)
@ -677,6 +700,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
struct rockchip_usb2phy_port *rport =
container_of(work, struct rockchip_usb2phy_port, chg_work.work);
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
bool is_dcd, tmout, vout;
unsigned long delay;
@ -687,7 +711,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
if (!rport->suspended)
rockchip_usb2phy_power_off(rport->phy);
/* put the controller in non-driving mode */
property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false);
property_enable(base, &rphy->phy_cfg->chg_det.opmode, false);
/* Start DCD processing stage 1 */
rockchip_chg_enable_dcd(rphy, true);
rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
@ -696,7 +720,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
break;
case USB_CHG_STATE_WAIT_FOR_DCD:
/* get data contact detection status */
is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det);
is_dcd = property_enabled(rphy->grf,
&rphy->phy_cfg->chg_det.dp_det);
tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
/* stage 2 */
if (is_dcd || tmout) {
@ -713,7 +738,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
}
break;
case USB_CHG_STATE_DCD_DONE:
vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det);
vout = property_enabled(rphy->grf,
&rphy->phy_cfg->chg_det.cp_det);
rockchip_chg_enable_primary_det(rphy, false);
if (vout) {
/* Voltage Source on DM, Probe on DP */
@ -734,7 +760,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
}
break;
case USB_CHG_STATE_PRIMARY_DONE:
vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det);
vout = property_enabled(rphy->grf,
&rphy->phy_cfg->chg_det.dcp_det);
/* Turn off voltage source */
rockchip_chg_enable_secondary_det(rphy, false);
if (vout)
@ -748,7 +775,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
/* fall through */
case USB_CHG_STATE_DETECTED:
/* put the controller in normal mode */
property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true);
property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
dev_info(&rport->phy->dev, "charger = %s\n",
chg_to_string(rphy->chg_type));
@ -790,8 +817,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
if (ret < 0)
goto next_schedule;
ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset,
&uhd);
ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
if (ret < 0)
goto next_schedule;
@ -845,8 +871,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
* activate the linestate detection to get the next device
* plug-in irq.
*/
property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
property_enable(rphy, &rport->port_cfg->ls_det_en, true);
property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true);
/*
* we don't need to rearm the delayed work when the phy port
@ -869,14 +895,14 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
struct rockchip_usb2phy_port *rport = data;
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
if (!property_enabled(rphy, &rport->port_cfg->ls_det_st))
if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st))
return IRQ_NONE;
mutex_lock(&rport->mutex);
/* disable linestate detect irq and clear its status */
property_enable(rphy, &rport->port_cfg->ls_det_en, false);
property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false);
property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
mutex_unlock(&rport->mutex);
@ -896,13 +922,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
struct rockchip_usb2phy_port *rport = data;
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st))
if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st))
return IRQ_NONE;
mutex_lock(&rport->mutex);
/* clear bvalid detect irq pending status */
property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true);
property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true);
mutex_unlock(&rport->mutex);
@ -911,6 +937,17 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
return IRQ_HANDLED;
}
static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data)
{
struct rockchip_usb2phy_port *rport = data;
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
if (property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st))
return rockchip_usb2phy_bvalid_irq(irq, data);
else
return IRQ_NONE;
}
static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
struct rockchip_usb2phy_port *rport,
struct device_node *child_np)
@ -987,20 +1024,43 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
rport->utmi_avalid =
of_property_read_bool(child_np, "rockchip,utmi-avalid");
rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
if (rport->bvalid_irq < 0) {
dev_err(rphy->dev, "no vbus valid irq provided\n");
ret = rport->bvalid_irq;
goto out;
}
/*
* Some SoCs use one interrupt with otg-id/otg-bvalid/linestate
* interrupts muxed together, so probe the otg-mux interrupt first,
* if not found, then look for the regular interrupts one by one.
*/
rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux");
if (rport->otg_mux_irq > 0) {
ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq,
NULL,
rockchip_usb2phy_otg_mux_irq,
IRQF_ONESHOT,
"rockchip_usb2phy_otg",
rport);
if (ret) {
dev_err(rphy->dev,
"failed to request otg-mux irq handle\n");
goto out;
}
} else {
rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
if (rport->bvalid_irq < 0) {
dev_err(rphy->dev, "no vbus valid irq provided\n");
ret = rport->bvalid_irq;
goto out;
}
ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL,
rockchip_usb2phy_bvalid_irq,
IRQF_ONESHOT,
"rockchip_usb2phy_bvalid", rport);
if (ret) {
dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n");
goto out;
ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq,
NULL,
rockchip_usb2phy_bvalid_irq,
IRQF_ONESHOT,
"rockchip_usb2phy_bvalid",
rport);
if (ret) {
dev_err(rphy->dev,
"failed to request otg-bvalid irq handle\n");
goto out;
}
}
if (!IS_ERR(rphy->edev)) {
@ -1045,6 +1105,16 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (IS_ERR(rphy->grf))
return PTR_ERR(rphy->grf);
if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) {
rphy->usbgrf =
syscon_regmap_lookup_by_phandle(dev->of_node,
"rockchip,usbgrf");
if (IS_ERR(rphy->usbgrf))
return PTR_ERR(rphy->usbgrf);
} else {
rphy->usbgrf = NULL;
}
if (of_property_read_u32(np, "reg", &reg)) {
dev_err(dev, "the reg property is not assigned in %s node\n",
np->name);
@ -1327,11 +1397,54 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
{ /* sentinel */ }
};
static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = {
{
.reg = 0x100,
.num_ports = 2,
.clkout_ctl = { 0x108, 4, 4, 1, 0 },
.port_cfgs = {
[USB2PHY_PORT_OTG] = {
.phy_sus = { 0x0100, 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 = { 0x0804, 10, 10, 0, 1 },
.utmi_ls = { 0x0804, 13, 12, 0, 1 },
},
[USB2PHY_PORT_HOST] = {
.phy_sus = { 0x0104, 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 },
.utmi_ls = { 0x0804, 9, 8, 0, 1 },
.utmi_hstdet = { 0x0804, 7, 7, 0, 1 }
}
},
.chg_det = {
.opmode = { 0x0100, 3, 0, 5, 1 },
.cp_det = { 0x0804, 1, 1, 0, 1 },
.dcp_det = { 0x0804, 0, 0, 0, 1 },
.dp_det = { 0x0804, 2, 2, 0, 1 },
.idm_sink_en = { 0x0108, 8, 8, 0, 1 },
.idp_sink_en = { 0x0108, 7, 7, 0, 1 },
.idp_src_en = { 0x0108, 9, 9, 0, 1 },
.rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 },
.vdm_src_en = { 0x0108, 12, 12, 0, 1 },
.vdp_src_en = { 0x0108, 11, 11, 0, 1 },
},
},
{ /* sentinel */ }
};
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 },
{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
{}
};
MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);

View File

@ -622,12 +622,11 @@ static int tcphy_get_mode(struct rockchip_typec_phy *tcphy)
struct extcon_dev *edev = tcphy->extcon;
union extcon_property_value property;
unsigned int id;
bool dfp, ufp, dp;
bool ufp, dp;
u8 mode;
int ret;
ufp = extcon_get_state(edev, EXTCON_USB);
dfp = extcon_get_state(edev, EXTCON_USB_HOST);
dp = extcon_get_state(edev, EXTCON_DISP_DP);
mode = MODE_DFP_USB;

View File

@ -16,6 +16,7 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@ -78,7 +79,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
{
struct exynos_dp_video_phy *state;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
struct phy_provider *phy_provider;
struct phy *phy;
@ -93,8 +93,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
return PTR_ERR(state->regs);
}
match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node);
state->drvdata = match->data;
state->drvdata = of_device_get_match_data(dev);
phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops);
if (IS_ERR(phy)) {

View File

@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
@ -662,7 +663,6 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
struct exynos5_usbdrd_phy *phy_drd;
struct phy_provider *phy_provider;
struct resource *res;
const struct of_device_id *match;
const struct exynos5_usbdrd_phy_drvdata *drv_data;
struct regmap *reg_pmu;
u32 pmu_offset;
@ -681,9 +681,10 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
if (IS_ERR(phy_drd->reg_phy))
return PTR_ERR(phy_drd->reg_phy);
match = of_match_node(exynos5_usbdrd_phy_of_match, pdev->dev.of_node);
drv_data = of_device_get_match_data(dev);
if (!drv_data)
return -EINVAL;
drv_data = match->data;
phy_drd->drv_data = drv_data;
ret = exynos5_usbdrd_phy_clk_handle(phy_drd);

View File

@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
@ -142,7 +143,6 @@ MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
static int samsung_usb2_phy_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct samsung_usb2_phy_config *cfg;
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
@ -155,12 +155,9 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
return -EINVAL;
}
match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node);
if (!match) {
dev_err(dev, "of_match_node() failed\n");
cfg = of_device_get_match_data(dev);
if (!cfg)
return -EINVAL;
}
cfg = match->data;
drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),

View File

@ -118,12 +118,12 @@ static struct pipe3_dpll_map dpll_map_usb[] = {
};
static struct pipe3_dpll_map dpll_map_sata[] = {
{12000000, {1000, 7, 4, 6, 0} }, /* 12 MHz */
{16800000, {714, 7, 4, 6, 0} }, /* 16.8 MHz */
{12000000, {625, 4, 4, 6, 0} }, /* 12 MHz */
{16800000, {625, 6, 4, 7, 0} }, /* 16.8 MHz */
{19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */
{20000000, {600, 7, 4, 6, 0} }, /* 20 MHz */
{26000000, {461, 7, 4, 6, 0} }, /* 26 MHz */
{38400000, {312, 7, 4, 6, 0} }, /* 38.4 MHz */
{20000000, {750, 9, 4, 6, 0} }, /* 20 MHz */
{26000000, {750, 12, 4, 6, 0} }, /* 26 MHz */
{38400000, {625, 15, 4, 6, 0} }, /* 38.4 MHz */
{ }, /* Terminator */
};

View File

@ -185,7 +185,7 @@ struct twl4030_usb {
static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
u8 module, u8 data, u8 address)
{
u8 check;
u8 check = 0xFF;
if ((twl_i2c_write_u8(module, data, address) >= 0) &&
(twl_i2c_read_u8(module, &check, address) >= 0) &&

View File

@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
#include <linux/usb/phy.h>
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/auxadc.h>
@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
struct usb_phy *usb_phy;
struct notifier_block usb_notify;
};
static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
};
/* In milliamps */
static const unsigned int wm831x_usb_limits[] = {
0,
2,
100,
500,
900,
1500,
1800,
550,
};
static int wm831x_usb_limit_change(struct notifier_block *nb,
unsigned long limit, void *data)
{
struct wm831x_power *wm831x_power = container_of(nb,
struct wm831x_power,
usb_notify);
unsigned int i, best;
/* Find the highest supported limit */
best = 0;
for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
if (limit >= wm831x_usb_limits[i] &&
wm831x_usb_limits[best] < wm831x_usb_limits[i])
best = i;
}
dev_dbg(wm831x_power->wm831x->dev,
"Limiting USB current to %umA", wm831x_usb_limits[best]);
wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
WM831X_USB_ILIM_MASK, best);
return 0;
}
/*********************************************************************
* Battery properties
*********************************************************************/
@ -607,6 +647,33 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
power->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "phys", 0);
ret = PTR_ERR_OR_ZERO(power->usb_phy);
switch (ret) {
case 0:
power->usb_notify.notifier_call = wm831x_usb_limit_change;
ret = usb_register_notifier(power->usb_phy, &power->usb_notify);
if (ret) {
dev_err(&pdev->dev, "Failed to register notifier: %d\n",
ret);
goto err_bat_irq;
}
break;
case -EINVAL:
case -ENODEV:
/* ignore missing usb-phy, it's optional */
power->usb_phy = NULL;
ret = 0;
break;
default:
dev_err(&pdev->dev, "Failed to find USB phy: %d\n", ret);
/* fall-through */
case -EPROBE_DEFER:
goto err_bat_irq;
break;
}
return ret;
err_bat_irq:
@ -637,6 +704,11 @@ static int wm831x_power_remove(struct platform_device *pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
if (wm831x_power->usb_phy) {
usb_unregister_notifier(wm831x_power->usb_phy,
&wm831x_power->usb_notify);
}
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x,
platform_get_irq_byname(pdev,

View File

@ -43,7 +43,6 @@
#include "usbatm.h"
#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands, Simon Arlott"
#define DRIVER_VERSION "0.4"
#define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver"
static const char cxacru_driver_name[] = "cxacru";
@ -1380,4 +1379,3 @@ module_usb_driver(cxacru_usb_driver);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRIVER_VERSION);

View File

@ -40,8 +40,7 @@
#include "usbatm.h"
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
#define DRIVER_VERSION "1.10"
#define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION
#define DRIVER_DESC "Alcatel SpeedTouch USB driver"
static const char speedtch_driver_name[] = "speedtch";
@ -738,7 +737,7 @@ static int speedtch_post_reset(struct usb_interface *intf)
** USB **
**********/
static struct usb_device_id speedtch_usb_ids[] = {
static const struct usb_device_id speedtch_usb_ids[] = {
{USB_DEVICE(0x06b9, 0x4061)},
{}
};
@ -962,4 +961,3 @@ module_usb_driver(speedtch_usb_driver);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRIVER_VERSION);

View File

@ -2212,7 +2212,7 @@ static int uea_boot(struct uea_softc *sc)
ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
if (ret < 0) {
uea_err(INS_TO_USBDEV(sc),
"urb submition failed with error %d\n", ret);
"urb submission failed with error %d\n", ret);
goto err1;
}
@ -2522,7 +2522,7 @@ static struct attribute *attrs[] = {
&dev_attr_stat_firmid.attr,
NULL,
};
static struct attribute_group attr_grp = {
static const struct attribute_group attr_grp = {
.attrs = attrs,
};

View File

@ -93,8 +93,7 @@ static int usbatm_print_packet(struct usbatm_data *instance, const unsigned char
#endif
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
#define DRIVER_VERSION "1.10"
#define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION
#define DRIVER_DESC "Generic USB ATM/DSL I/O"
static const char usbatm_driver_name[] = "usbatm";
@ -174,7 +173,7 @@ static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __us
static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page);
static struct atmdev_ops usbatm_atm_devops = {
static const struct atmdev_ops usbatm_atm_devops = {
.dev_close = usbatm_atm_dev_close,
.open = usbatm_atm_open,
.close = usbatm_atm_close,
@ -1315,7 +1314,6 @@ module_exit(usbatm_usb_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRIVER_VERSION);
/************
** debug **

View File

@ -228,4 +228,3 @@ module_exit(xusbatm_exit);
MODULE_AUTHOR("Roman Kagan, Duncan Sands");
MODULE_DESCRIPTION("Driver for USB ADSL modems initialized in userspace");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");

View File

@ -305,7 +305,7 @@ static int c67x00_hcd_get_frame(struct usb_hcd *hcd)
return temp_val ? (temp_val - 1) : HOST_FRAME_MASK;
}
static struct hc_driver c67x00_hc_driver = {
static const struct hc_driver c67x00_hc_driver = {
.description = "c67x00-hcd",
.product_desc = "Cypress C67X00 Host Controller",
.hcd_priv_size = sizeof(struct c67x00_hcd),

View File

@ -15,3 +15,4 @@ obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_zevio.o
obj-$(CONFIG_USB_CHIPIDEA_PCI) += ci_hdrc_pci.o
obj-$(CONFIG_USB_CHIPIDEA_OF) += usbmisc_imx.o ci_hdrc_imx.o
obj-$(CONFIG_USB_CHIPIDEA_OF) += ci_hdrc_tegra.o

View File

@ -251,7 +251,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
if (ret)
goto err_mux;
ulpi_node = of_find_node_by_name(pdev->dev.of_node, "ulpi");
ulpi_node = of_find_node_by_name(of_node_get(pdev->dev.of_node), "ulpi");
if (ulpi_node) {
phy_node = of_get_next_available_child(ulpi_node, NULL);
ci->hsic = of_device_is_compatible(phy_node, "qcom,usb-hsic-phy");

View File

@ -170,5 +170,4 @@ module_pci_driver(ci_hdrc_pci_driver);
MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
MODULE_LICENSE("GPL");
MODULE_VERSION("June 2008");
MODULE_ALIAS("platform:ci13xxx_pci");

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2016, NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/reset.h>
#include <linux/usb/chipidea.h>
#include "ci.h"
struct tegra_udc {
struct ci_hdrc_platform_data data;
struct platform_device *dev;
struct usb_phy *phy;
struct clk *clk;
};
struct tegra_udc_soc_info {
unsigned long flags;
};
static const struct tegra_udc_soc_info tegra20_udc_soc_info = {
.flags = CI_HDRC_REQUIRES_ALIGNED_DMA,
};
static const struct tegra_udc_soc_info tegra30_udc_soc_info = {
.flags = 0,
};
static const struct tegra_udc_soc_info tegra114_udc_soc_info = {
.flags = 0,
};
static const struct tegra_udc_soc_info tegra124_udc_soc_info = {
.flags = 0,
};
static const struct of_device_id tegra_udc_of_match[] = {
{
.compatible = "nvidia,tegra20-udc",
.data = &tegra20_udc_soc_info,
}, {
.compatible = "nvidia,tegra30-udc",
.data = &tegra30_udc_soc_info,
}, {
.compatible = "nvidia,tegra114-udc",
.data = &tegra114_udc_soc_info,
}, {
.compatible = "nvidia,tegra124-udc",
.data = &tegra124_udc_soc_info,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(of, tegra_udc_of_match);
static int tegra_udc_probe(struct platform_device *pdev)
{
const struct tegra_udc_soc_info *soc;
struct tegra_udc *udc;
int err;
udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
if (!udc)
return -ENOMEM;
soc = of_device_get_match_data(&pdev->dev);
if (!soc) {
dev_err(&pdev->dev, "failed to match OF data\n");
return -EINVAL;
}
udc->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
if (IS_ERR(udc->phy)) {
err = PTR_ERR(udc->phy);
dev_err(&pdev->dev, "failed to get PHY: %d\n", err);
return err;
}
udc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(udc->clk)) {
err = PTR_ERR(udc->clk);
dev_err(&pdev->dev, "failed to get clock: %d\n", err);
return err;
}
err = clk_prepare_enable(udc->clk);
if (err < 0) {
dev_err(&pdev->dev, "failed to enable clock: %d\n", err);
return err;
}
/*
* Tegra's USB PHY driver doesn't implement optional phy_init()
* hook, so we have to power on UDC controller before ChipIdea
* driver initialization kicks in.
*/
usb_phy_set_suspend(udc->phy, 0);
/* setup and register ChipIdea HDRC device */
udc->data.name = "tegra-udc";
udc->data.flags = soc->flags;
udc->data.usb_phy = udc->phy;
udc->data.capoffset = DEF_CAPOFFSET;
udc->dev = ci_hdrc_add_device(&pdev->dev, pdev->resource,
pdev->num_resources, &udc->data);
if (IS_ERR(udc->dev)) {
err = PTR_ERR(udc->dev);
dev_err(&pdev->dev, "failed to add HDRC device: %d\n", err);
goto fail_power_off;
}
platform_set_drvdata(pdev, udc);
return 0;
fail_power_off:
usb_phy_set_suspend(udc->phy, 1);
clk_disable_unprepare(udc->clk);
return err;
}
static int tegra_udc_remove(struct platform_device *pdev)
{
struct tegra_udc *udc = platform_get_drvdata(pdev);
usb_phy_set_suspend(udc->phy, 1);
clk_disable_unprepare(udc->clk);
return 0;
}
static struct platform_driver tegra_udc_driver = {
.driver = {
.name = "tegra-udc",
.of_match_table = tegra_udc_of_match,
},
.probe = tegra_udc_probe,
.remove = tegra_udc_remove,
};
module_platform_driver(tegra_udc_driver);
MODULE_DESCRIPTION("NVIDIA Tegra USB device mode driver");
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
MODULE_ALIAS("platform:tegra-udc");
MODULE_LICENSE("GPL v2");

View File

@ -52,6 +52,8 @@ static int ci_hdrc_usb2_probe(struct platform_device *pdev)
if (!ci_pdata) {
ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
if (!ci_pdata)
return -ENOMEM;
*ci_pdata = ci_default_pdata; /* struct copy */
}

View File

@ -736,7 +736,7 @@ static int ci_extcon_register(struct ci_hdrc *ci)
id = &ci->platdata->id_extcon;
id->ci = ci;
if (!IS_ERR(id->edev)) {
if (!IS_ERR_OR_NULL(id->edev)) {
ret = devm_extcon_register_notifier(ci->dev, id->edev,
EXTCON_USB_HOST, &id->nb);
if (ret < 0) {
@ -747,7 +747,7 @@ static int ci_extcon_register(struct ci_hdrc *ci)
vbus = &ci->platdata->vbus_extcon;
vbus->ci = ci;
if (!IS_ERR(vbus->edev)) {
if (!IS_ERR_OR_NULL(vbus->edev)) {
ret = devm_extcon_register_notifier(ci->dev, vbus->edev,
EXTCON_USB, &vbus->nb);
if (ret < 0) {
@ -887,7 +887,7 @@ static struct attribute *ci_attrs[] = {
NULL,
};
static struct attribute_group ci_attr_group = {
static const struct attribute_group ci_attr_group = {
.attrs = ci_attrs,
};

View File

@ -193,7 +193,7 @@ static struct attribute *inputs_attrs[] = {
NULL,
};
static struct attribute_group inputs_attr_group = {
static const struct attribute_group inputs_attr_group = {
.name = "inputs",
.attrs = inputs_attrs,
};

View File

@ -944,7 +944,6 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
*/
static int isr_setup_status_phase(struct ci_hdrc *ci)
{
int retval;
struct ci_hw_ep *hwep;
/*
@ -960,9 +959,7 @@ static int isr_setup_status_phase(struct ci_hdrc *ci)
ci->status->context = ci;
ci->status->complete = isr_setup_status_complete;
retval = _ep_queue(&hwep->ep, ci->status, GFP_ATOMIC);
return retval;
return _ep_queue(&hwep->ep, ci->status, GFP_ATOMIC);
}
/**
@ -1899,6 +1896,9 @@ static int udc_start(struct ci_hdrc *ci)
ci->gadget.name = ci->platdata->name;
ci->gadget.otg_caps = otg_caps;
if (ci->platdata->flags & CI_HDRC_REQUIRES_ALIGNED_DMA)
ci->gadget.quirk_avoids_skb_reserve = 1;
if (ci->is_otg && (otg_caps->hnp_support || otg_caps->srp_support ||
otg_caps->adp_support))
ci->gadget.is_otg = 1;

View File

@ -26,10 +26,6 @@
#include <asm/unaligned.h>
#include <linux/usb/cdc-wdm.h>
/*
* Version Information
*/
#define DRIVER_VERSION "v0.03"
#define DRIVER_AUTHOR "Oliver Neukum"
#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"

View File

@ -1085,7 +1085,7 @@ static struct attribute *capability_attrs[] = {
NULL,
};
static struct attribute_group capability_attr_grp = {
static const struct attribute_group capability_attr_grp = {
.attrs = capability_attrs,
};
@ -1151,7 +1151,7 @@ static struct attribute *data_attrs[] = {
NULL,
};
static struct attribute_group data_attr_grp = {
static const struct attribute_group data_attr_grp = {
.attrs = data_attrs,
};

View File

@ -190,10 +190,7 @@ EXPORT_SYMBOL_GPL(of_usb_get_dr_mode_by_phy);
*/
bool of_usb_host_tpl_support(struct device_node *np)
{
if (of_find_property(np, "tpl-support", NULL))
return true;
return false;
return of_property_read_bool(np, "tpl-support");
}
EXPORT_SYMBOL_GPL(of_usb_host_tpl_support);
@ -227,8 +224,8 @@ int of_usb_update_otg_caps(struct device_node *np,
otg_caps->otg_rev = otg_rev;
break;
default:
pr_err("%s: unsupported otg-rev: 0x%x\n",
np->full_name, otg_rev);
pr_err("%pOF: unsupported otg-rev: 0x%x\n",
np, otg_rev);
return -EINVAL;
}
} else {
@ -240,11 +237,11 @@ int of_usb_update_otg_caps(struct device_node *np,
otg_caps->otg_rev = 0;
}
if (of_find_property(np, "hnp-disable", NULL))
if (of_property_read_bool(np, "hnp-disable"))
otg_caps->hnp_support = false;
if (of_find_property(np, "srp-disable", NULL))
if (of_property_read_bool(np, "srp-disable"))
otg_caps->srp_support = false;
if (of_find_property(np, "adp-disable", NULL) ||
if (of_property_read_bool(np, "adp-disable") ||
(otg_caps->otg_rev < 0x0200))
otg_caps->adp_support = false;

View File

@ -135,7 +135,7 @@ static void ulpi_dev_release(struct device *dev)
kfree(to_ulpi_dev(dev));
}
static struct device_type ulpi_dev_type = {
static const struct device_type ulpi_dev_type = {
.name = "ulpi_device",
.groups = ulpi_dev_attr_groups,
.release = ulpi_dev_release,

View File

@ -210,7 +210,7 @@ static void usbdev_vm_close(struct vm_area_struct *vma)
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
}
static struct vm_operations_struct usbdev_vm_ops = {
static const struct vm_operations_struct usbdev_vm_ops = {
.open = usbdev_vm_open,
.close = usbdev_vm_close
};
@ -623,6 +623,8 @@ static void async_completed(struct urb *urb)
if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
as->status != -ENOENT)
cancel_bulk_urbs(ps, as->bulk_addr);
wake_up(&ps->wait);
spin_unlock(&ps->lock);
if (signr) {
@ -630,8 +632,6 @@ static void async_completed(struct urb *urb)
put_pid(pid);
put_cred(cred);
}
wake_up(&ps->wait);
}
static void destroy_async(struct usb_dev_state *ps, struct list_head *list)

View File

@ -972,7 +972,7 @@ static struct attribute *usb_bus_attrs[] = {
NULL,
};
static struct attribute_group usb_bus_attr_group = {
static const struct attribute_group usb_bus_attr_group = {
.name = NULL, /* we want them in the same directory */
.attrs = usb_bus_attrs,
};

View File

@ -2614,7 +2614,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
#define SET_CONFIG_TRIES (2 * (use_both_schemes + 1))
#define USE_NEW_SCHEME(i) ((i) / 2 == (int)old_scheme_first)
#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
#define HUB_ROOT_RESET_TIME 60 /* times are in msec */
#define HUB_SHORT_RESET_TIME 10
#define HUB_BH_RESET_TIME 50
#define HUB_LONG_RESET_TIME 200
@ -4342,6 +4342,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
enum usb_device_speed oldspeed = udev->speed;
const char *speed;
int devnum = udev->devnum;
const char *driver_name;
/* root hub ports have a slightly longer reset period
* (from USB 2.0 spec, section 7.1.7.5)
@ -4409,11 +4410,23 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
else
speed = usb_speed_string(udev->speed);
/*
* The controller driver may be NULL if the controller device
* is the middle device between platform device and roothub.
* This middle device may not need a device driver due to
* all hardware control can be at platform device driver, this
* platform device is usually a dual-role USB controller device.
*/
if (udev->bus->controller->driver)
driver_name = udev->bus->controller->driver->name;
else
driver_name = udev->bus->sysdev->driver->name;
if (udev->speed < USB_SPEED_SUPER)
dev_info(&udev->dev,
"%s %s USB device number %d using %s\n",
(udev->config) ? "reset" : "new", speed,
devnum, udev->bus->controller->driver->name);
devnum, driver_name);
/* Set up TT records, if needed */
if (hdev->tt) {
@ -4545,7 +4558,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
"%s SuperSpeed%s USB device number %d using %s\n",
(udev->config) ? "reset" : "new",
(udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "",
devnum, udev->bus->controller->driver->name);
devnum, driver_name);
}
/* cope with hardware quirkiness:

View File

@ -149,8 +149,8 @@ static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data,
count = of_count_phandle_with_args(led_np, "trigger-sources",
"#trigger-source-cells");
if (count < 0) {
dev_warn(dev, "Failed to get trigger sources for %s\n",
led_np->full_name);
dev_warn(dev, "Failed to get trigger sources for %pOF\n",
led_np);
return false;
}
@ -205,6 +205,7 @@ static int usbport_trig_add_port(struct usbport_trig_data *usbport_data,
}
snprintf(port->port_name, len, "%s-port%d", hub_name, portnum);
sysfs_attr_init(&port->attr.attr);
port->attr.attr.name = port->port_name;
port->attr.attr.mode = S_IRUSR | S_IWUSR;
port->attr.show = usbport_trig_port_show;

View File

@ -57,8 +57,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Microsoft LifeCam-VX700 v2.0 */
{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech HD Pro Webcams C920 and C930e */
/* Logitech HD Pro Webcams C920, C920-C and C930e */
{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
{ USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
{ USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
/* Logitech ConferenceCam CC3000e */
@ -217,6 +218,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
/* Corsair Strafe RGB */
{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT },
/* Acer C120 LED Projector */
{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },

View File

@ -113,7 +113,7 @@ static ssize_t devspec_show(struct device *dev, struct device_attribute *attr,
{
struct device_node *of_node = dev->of_node;
return sprintf(buf, "%s\n", of_node_full_name(of_node));
return sprintf(buf, "%pOF\n", of_node);
}
static DEVICE_ATTR_RO(devspec);
#endif

View File

@ -4179,7 +4179,7 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
return ret;
}
static struct usb_ep_ops dwc2_hsotg_ep_ops = {
static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
.enable = dwc2_hsotg_ep_enable,
.disable = dwc2_hsotg_ep_disable,
.alloc_request = dwc2_hsotg_ep_alloc_request,

View File

@ -4388,6 +4388,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
spin_lock_irqsave(&hsotg->lock, flags);
if (dwc2_is_device_mode(hsotg))
goto unlock;
if (hsotg->lx_state != DWC2_L0)
goto unlock;
@ -4446,6 +4449,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
spin_lock_irqsave(&hsotg->lock, flags);
if (dwc2_is_device_mode(hsotg))
goto unlock;
if (hsotg->lx_state != DWC2_L2)
goto unlock;

View File

@ -15,7 +15,6 @@
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
@ -23,6 +22,7 @@
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
/* USBSS register offsets */
#define USBSS_REVISION 0x0000
@ -41,7 +41,6 @@
struct dwc3_keystone {
struct device *dev;
struct clk *clk;
void __iomem *usbss;
};
@ -106,17 +105,13 @@ static int kdwc3_probe(struct platform_device *pdev)
if (IS_ERR(kdwc->usbss))
return PTR_ERR(kdwc->usbss);
kdwc->clk = devm_clk_get(kdwc->dev, "usb");
if (IS_ERR(kdwc->clk)) {
dev_err(kdwc->dev, "unable to get usb clock\n");
return PTR_ERR(kdwc->clk);
}
pm_runtime_enable(kdwc->dev);
error = clk_prepare_enable(kdwc->clk);
error = pm_runtime_get_sync(kdwc->dev);
if (error < 0) {
dev_err(kdwc->dev, "unable to enable usb clock, error %d\n",
dev_err(kdwc->dev, "pm_runtime_get_sync failed, error %d\n",
error);
return error;
goto err_irq;
}
irq = platform_get_irq(pdev, 0);
@ -147,7 +142,8 @@ static int kdwc3_probe(struct platform_device *pdev)
err_core:
kdwc3_disable_irqs(kdwc);
err_irq:
clk_disable_unprepare(kdwc->clk);
pm_runtime_put_sync(kdwc->dev);
pm_runtime_disable(kdwc->dev);
return error;
}
@ -167,7 +163,9 @@ static int kdwc3_remove(struct platform_device *pdev)
kdwc3_disable_irqs(kdwc);
device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
clk_disable_unprepare(kdwc->clk);
pm_runtime_put_sync(kdwc->dev);
pm_runtime_disable(kdwc->dev);
platform_set_drvdata(pdev, NULL);
return 0;

View File

@ -25,7 +25,6 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
@ -96,7 +95,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, simple);
simple->dev = dev;
ret = dwc3_of_simple_clk_init(simple, of_clk_get_parent_count(np));
ret = dwc3_of_simple_clk_init(simple, of_count_phandle_with_args(np,
"clocks", "#clock-cells"));
if (ret)
return ret;

View File

@ -478,8 +478,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "missing IRQ resource\n");
return -EINVAL;
dev_err(dev, "missing IRQ resource: %d\n", irq);
return irq;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

View File

@ -345,7 +345,7 @@ static int dwc3_pci_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
static struct dev_pm_ops dwc3_pci_dev_pm_ops = {
static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_runtime_resume,
NULL)

View File

@ -130,7 +130,7 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
config U_SERIAL_CONSOLE
bool "Serial gadget console support"
depends on USB_G_SERIAL
depends on USB_U_SERIAL
help
It supports the serial gadget can be used as a console.

View File

@ -961,10 +961,9 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
/* In the meantime, endpoint got disabled or changed. */
ret = -ESHUTDOWN;
} else if (halt) {
/* Halt */
if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep))
usb_ep_set_halt(ep->ep);
ret = -EBADMSG;
ret = usb_ep_set_halt(ep->ep);
if (!ret)
ret = -EBADMSG;
} else if (unlikely(data_len == -EINVAL)) {
/*
* Sanity Check: even though data_len can't be used

View File

@ -44,6 +44,7 @@ struct f_hidg {
/* configuration */
unsigned char bInterfaceSubClass;
unsigned char bInterfaceProtocol;
unsigned char protocol;
unsigned short report_desc_length;
char *report_desc;
unsigned short report_length;
@ -527,7 +528,9 @@ static int hidg_setup(struct usb_function *f,
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_GET_PROTOCOL):
VDBG(cdev, "get_protocol\n");
goto stall;
length = min_t(unsigned int, length, 1);
((u8 *) req->buf)[0] = hidg->protocol;
goto respond;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
@ -539,6 +542,17 @@ static int hidg_setup(struct usb_function *f,
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_PROTOCOL):
VDBG(cdev, "set_protocol\n");
if (value > HID_REPORT_PROTOCOL)
goto stall;
length = 0;
/*
* We assume that programs implementing the Boot protocol
* are also compatible with the Report Protocol
*/
if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
hidg->protocol = value;
goto respond;
}
goto stall;
break;
@ -768,6 +782,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
/* set descriptor dynamic values */
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
hidg->protocol = HID_REPORT_PROTOCOL;
hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_ss_in_comp_desc.wBytesPerInterval =
cpu_to_le16(hidg->report_length);

View File

@ -98,6 +98,7 @@ struct f_midi {
DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *);
spinlock_t transmit_lock;
unsigned int in_last_port;
unsigned char free_ref;
struct gmidi_in_port in_ports_array[/* in_ports */];
};
@ -108,6 +109,7 @@ static inline struct f_midi *func_to_midi(struct usb_function *f)
}
static void f_midi_transmit(struct f_midi *midi);
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi);
DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
@ -163,6 +165,13 @@ static struct usb_endpoint_descriptor bulk_out_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_ss_ep_comp_descriptor bulk_out_ss_comp_desc = {
.bLength = sizeof(bulk_out_ss_comp_desc),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
};
/* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */
static struct usb_ms_endpoint_descriptor_16 ms_out_desc = {
/* .bLength = DYNAMIC */
@ -180,6 +189,13 @@ static struct usb_endpoint_descriptor bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_ss_ep_comp_descriptor bulk_in_ss_comp_desc = {
.bLength = sizeof(bulk_in_ss_comp_desc),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
};
/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */
static struct usb_ms_endpoint_descriptor_16 ms_in_desc = {
/* .bLength = DYNAMIC */
@ -755,13 +771,13 @@ static void f_midi_out_trigger(struct snd_rawmidi_substream *substream, int up)
clear_bit(substream->number, &midi->out_triggered);
}
static struct snd_rawmidi_ops gmidi_in_ops = {
static const struct snd_rawmidi_ops gmidi_in_ops = {
.open = f_midi_in_open,
.close = f_midi_in_close,
.trigger = f_midi_in_trigger,
};
static struct snd_rawmidi_ops gmidi_out_ops = {
static const struct snd_rawmidi_ops gmidi_out_ops = {
.open = f_midi_out_open,
.close = f_midi_out_close,
.trigger = f_midi_out_trigger
@ -818,6 +834,8 @@ static int f_midi_register_card(struct f_midi *midi)
SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_DUPLEX;
rmidi->private_data = midi;
rmidi->private_free = f_midi_rmidi_free;
midi->free_ref++;
/*
* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT.
@ -853,7 +871,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_midi *midi = func_to_midi(f);
struct usb_string *us;
int status, n, jack = 1, i = 0;
int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0;
midi->gadget = cdev->gadget;
tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
@ -895,7 +913,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
/* allocate temporary function list */
midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
midi_function = kcalloc((MAX_PORTS * 4) + 11, sizeof(*midi_function),
GFP_KERNEL);
if (!midi_function) {
status = -ENOMEM;
@ -985,6 +1003,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
ms_in_desc.bNumEmbMIDIJack = midi->out_ports;
/* ... and add them to the list */
endpoint_descriptor_index = i;
midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc;
midi_function[i++] = (struct usb_descriptor_header *) &ms_out_desc;
midi_function[i++] = (struct usb_descriptor_header *) &bulk_in_desc;
@ -1009,13 +1028,34 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
goto fail_f_midi;
}
if (gadget_is_superspeed(c->cdev->gadget)) {
bulk_in_desc.wMaxPacketSize = cpu_to_le16(1024);
bulk_out_desc.wMaxPacketSize = cpu_to_le16(1024);
i = endpoint_descriptor_index;
midi_function[i++] = (struct usb_descriptor_header *)
&bulk_out_desc;
midi_function[i++] = (struct usb_descriptor_header *)
&bulk_out_ss_comp_desc;
midi_function[i++] = (struct usb_descriptor_header *)
&ms_out_desc;
midi_function[i++] = (struct usb_descriptor_header *)
&bulk_in_desc;
midi_function[i++] = (struct usb_descriptor_header *)
&bulk_in_ss_comp_desc;
midi_function[i++] = (struct usb_descriptor_header *)
&ms_in_desc;
f->ss_descriptors = usb_copy_descriptors(midi_function);
if (!f->ss_descriptors)
goto fail_f_midi;
}
kfree(midi_function);
return 0;
fail_f_midi:
kfree(midi_function);
usb_free_descriptors(f->hs_descriptors);
usb_free_all_descriptors(f);
fail:
f_midi_unregister_card(midi);
fail_register:
@ -1197,14 +1237,21 @@ static void f_midi_free(struct usb_function *f)
midi = func_to_midi(f);
opts = container_of(f->fi, struct f_midi_opts, func_inst);
kfree(midi->id);
mutex_lock(&opts->lock);
kfifo_free(&midi->in_req_fifo);
kfree(midi);
--opts->refcnt;
if (!--midi->free_ref) {
kfree(midi->id);
kfifo_free(&midi->in_req_fifo);
kfree(midi);
--opts->refcnt;
}
mutex_unlock(&opts->lock);
}
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi)
{
f_midi_free(rmidi->private_data);
}
static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = f->config->cdev;
@ -1219,7 +1266,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
card = midi->card;
midi->card = NULL;
if (card)
snd_card_free(card);
snd_card_free_when_closed(card);
usb_free_all_descriptors(f);
}
@ -1263,6 +1310,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
midi->buflen = opts->buflen;
midi->qlen = opts->qlen;
midi->in_last_port = 0;
midi->free_ref = 1;
status = kfifo_alloc(&midi->in_req_fifo, midi->qlen, GFP_KERNEL);
if (status)

View File

@ -925,8 +925,6 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
*/
ncm->port.is_zlp_ok =
gadget_is_zlp_supported(cdev->gadget);
ncm->port.no_skb_reserve =
gadget_avoids_skb_reserve(cdev->gadget);
ncm->port.cdc_filter = DEFAULT_FILTER;
DBG(cdev, "activate ncm\n");
net = gether_connect(&ncm->port);

View File

@ -691,6 +691,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc;
}
rndis_iad_descriptor.bFunctionClass = rndis_opts->class;
rndis_iad_descriptor.bFunctionSubClass = rndis_opts->subclass;
rndis_iad_descriptor.bFunctionProtocol = rndis_opts->protocol;
/*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry,
@ -866,11 +870,23 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(rndis);
/* f_rndis_opts_ifname */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis);
/* f_rndis_opts_class */
USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, class);
/* f_rndis_opts_subclass */
USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, subclass);
/* f_rndis_opts_protocol */
USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, protocol);
static struct configfs_attribute *rndis_attrs[] = {
&rndis_opts_attr_dev_addr,
&rndis_opts_attr_host_addr,
&rndis_opts_attr_qmult,
&rndis_opts_attr_ifname,
&rndis_opts_attr_class,
&rndis_opts_attr_subclass,
&rndis_opts_attr_protocol,
NULL,
};
@ -916,6 +932,10 @@ static struct usb_function_instance *rndis_alloc_inst(void)
}
INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop);
opts->class = rndis_iad_descriptor.bFunctionClass;
opts->subclass = rndis_iad_descriptor.bFunctionSubClass;
opts->protocol = rndis_iad_descriptor.bFunctionProtocol;
descs[0] = &opts->rndis_os_desc;
names[0] = "rndis";
config_group_init_type_name(&opts->func_inst.group, "",

View File

@ -79,7 +79,7 @@ struct snd_uac_chip {
unsigned int p_framesize;
};
static struct snd_pcm_hardware uac_pcm_hardware = {
static const struct snd_pcm_hardware uac_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
| SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
@ -354,7 +354,7 @@ static int uac_pcm_null(struct snd_pcm_substream *substream)
return 0;
}
static struct snd_pcm_ops uac_pcm_ops = {
static const struct snd_pcm_ops uac_pcm_ops = {
.open = uac_pcm_open,
.close = uac_pcm_null,
.ioctl = snd_pcm_lib_ioctl,

View File

@ -1073,7 +1073,7 @@ struct net_device *gether_connect(struct gether *link)
if (result == 0) {
dev->zlp = link->is_zlp_ok;
dev->no_skb_reserve = link->no_skb_reserve;
dev->no_skb_reserve = gadget_avoids_skb_reserve(dev->gadget);
DBG(dev, "qlen %d\n", qlen(dev->gadget, dev->qmult));
dev->header_len = link->header_len;

View File

@ -64,7 +64,6 @@ struct gether {
struct usb_ep *out_ep;
bool is_zlp_ok;
bool no_skb_reserve;
u16 cdc_filter;

View File

@ -153,4 +153,39 @@ out: \
\
CONFIGFS_ATTR_RO(_f_##_opts_, ifname)
#define USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(_f_, _n_) \
static ssize_t _f_##_opts_##_n_##_show(struct config_item *item,\
char *page) \
{ \
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
mutex_lock(&opts->lock); \
ret = sprintf(page, "%02x\n", opts->_n_); \
mutex_unlock(&opts->lock); \
\
return ret; \
} \
\
static ssize_t _f_##_opts_##_n_##_store(struct config_item *item,\
const char *page, \
size_t len) \
{ \
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
u8 val; \
\
mutex_lock(&opts->lock); \
ret = sscanf(page, "%02hhx", &val); \
if (ret > 0) { \
opts->_n_ = val; \
ret = len; \
} \
mutex_unlock(&opts->lock); \
\
return ret; \
} \
\
CONFIGFS_ATTR(_f_##_opts_, _n_)
#endif /* __U_ETHER_CONFIGFS_H */

View File

@ -29,6 +29,10 @@ struct f_rndis_opts {
struct usb_os_desc rndis_os_desc;
char rndis_ext_compat_id[16];
u8 class;
u8 subclass;
u8 protocol;
/*
* Read/write access to configfs attributes is handled by configfs.
*

View File

@ -537,7 +537,7 @@ static void gs_rx_push(unsigned long _port)
}
/* push data to (open) tty */
if (req->actual) {
if (req->actual && tty) {
char *packet = req->buf;
unsigned size = req->actual;
unsigned n;

View File

@ -436,5 +436,4 @@ module_usb_composite_driver(webcam_driver);
MODULE_AUTHOR("Laurent Pinchart");
MODULE_DESCRIPTION("Webcam Video Gadget");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1.0");

View File

@ -1,6 +1,7 @@
config USB_BDC_UDC
tristate "Broadcom USB3.0 device controller IP driver(BDC)"
depends on USB_GADGET && HAS_DMA
default ARCH_BRCMSTB
help
BDC is Broadcom's USB3.0 device controller IP. If your SOC has a BDC IP

View File

@ -27,8 +27,8 @@
#include <linux/usb/gadget.h>
#include <asm/unaligned.h>
#define BRCM_BDC_NAME "bdc_usb3"
#define BRCM_BDC_DESC "BDC device controller driver"
#define BRCM_BDC_NAME "bdc"
#define BRCM_BDC_DESC "Broadcom USB Device Controller driver"
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
@ -83,14 +83,14 @@
#define BDC_DVCSA 0x50
#define BDC_DVCSB 0x54
#define BDC_EPSTS0(n) (0x60 + (n * 0x10))
#define BDC_EPSTS1(n) (0x64 + (n * 0x10))
#define BDC_EPSTS2(n) (0x68 + (n * 0x10))
#define BDC_EPSTS3(n) (0x6c + (n * 0x10))
#define BDC_EPSTS4(n) (0x70 + (n * 0x10))
#define BDC_EPSTS5(n) (0x74 + (n * 0x10))
#define BDC_EPSTS6(n) (0x78 + (n * 0x10))
#define BDC_EPSTS7(n) (0x7c + (n * 0x10))
#define BDC_EPSTS0 0x60
#define BDC_EPSTS1 0x64
#define BDC_EPSTS2 0x68
#define BDC_EPSTS3 0x6c
#define BDC_EPSTS4 0x70
#define BDC_EPSTS5 0x74
#define BDC_EPSTS6 0x78
#define BDC_EPSTS7 0x7c
#define BDC_SRRBAL(n) (0x200 + (n * 0x10))
#define BDC_SRRBAH(n) (0x204 + (n * 0x10))
#define BDC_SRRINT(n) (0x208 + (n * 0x10))
@ -413,6 +413,9 @@ struct bdc {
/* device lock */
spinlock_t lock;
/* generic phy */
struct phy **phys;
int num_phys;
/* num of endpoints for a particular instantiation of IP */
unsigned int num_eps;
/*
@ -454,6 +457,7 @@ struct bdc {
* Func Wake packet every 2.5 secs. Refer to USB3 spec section 8.5.6.4
*/
struct delayed_work func_wake_notify;
struct clk *clk;
};
static inline u32 bdc_readl(void __iomem *base, u32 offset)

View File

@ -24,9 +24,11 @@
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/moduleparam.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/clk.h>
#include "bdc.h"
#include "bdc_dbg.h"
@ -444,6 +446,43 @@ static int bdc_hw_init(struct bdc *bdc)
return 0;
}
static int bdc_phy_init(struct bdc *bdc)
{
int phy_num;
int ret;
for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
ret = phy_init(bdc->phys[phy_num]);
if (ret)
goto err_exit_phy;
ret = phy_power_on(bdc->phys[phy_num]);
if (ret) {
phy_exit(bdc->phys[phy_num]);
goto err_exit_phy;
}
}
return 0;
err_exit_phy:
while (--phy_num >= 0) {
phy_power_off(bdc->phys[phy_num]);
phy_exit(bdc->phys[phy_num]);
}
return ret;
}
static void bdc_phy_exit(struct bdc *bdc)
{
int phy_num;
for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
phy_power_off(bdc->phys[phy_num]);
phy_exit(bdc->phys[phy_num]);
}
}
static int bdc_probe(struct platform_device *pdev)
{
struct bdc *bdc;
@ -452,12 +491,29 @@ static int bdc_probe(struct platform_device *pdev)
int irq;
u32 temp;
struct device *dev = &pdev->dev;
struct clk *clk;
int phy_num;
dev_dbg(dev, "%s()\n", __func__);
clk = devm_clk_get(dev, "sw_usbd");
if (IS_ERR(clk)) {
dev_info(dev, "Clock not found in Device Tree\n");
clk = NULL;
}
ret = clk_prepare_enable(clk);
if (ret) {
dev_err(dev, "could not enable clock\n");
return ret;
}
bdc = devm_kzalloc(dev, sizeof(*bdc), GFP_KERNEL);
if (!bdc)
return -ENOMEM;
bdc->clk = clk;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bdc->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(bdc->regs)) {
@ -473,35 +529,66 @@ static int bdc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, bdc);
bdc->irq = irq;
bdc->dev = dev;
dev_dbg(bdc->dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq);
dev_dbg(dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq);
bdc->num_phys = of_count_phandle_with_args(dev->of_node,
"phys", "#phy-cells");
if (bdc->num_phys > 0) {
bdc->phys = devm_kcalloc(dev, bdc->num_phys,
sizeof(struct phy *), GFP_KERNEL);
if (!bdc->phys)
return -ENOMEM;
} else {
bdc->num_phys = 0;
}
dev_info(dev, "Using %d phy(s)\n", bdc->num_phys);
for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
bdc->phys[phy_num] = devm_of_phy_get_by_index(
dev, dev->of_node, phy_num);
if (IS_ERR(bdc->phys[phy_num])) {
ret = PTR_ERR(bdc->phys[phy_num]);
dev_err(bdc->dev,
"BDC phy specified but not found:%d\n", ret);
return ret;
}
}
ret = bdc_phy_init(bdc);
if (ret) {
dev_err(bdc->dev, "BDC phy init failure:%d\n", ret);
return ret;
}
temp = bdc_readl(bdc->regs, BDC_BDCCAP1);
if ((temp & BDC_P64) &&
!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
dev_dbg(bdc->dev, "Using 64-bit address\n");
dev_dbg(dev, "Using 64-bit address\n");
} else {
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(bdc->dev, "No suitable DMA config available, abort\n");
dev_err(dev,
"No suitable DMA config available, abort\n");
return -ENOTSUPP;
}
dev_dbg(bdc->dev, "Using 32-bit address\n");
dev_dbg(dev, "Using 32-bit address\n");
}
ret = bdc_hw_init(bdc);
if (ret) {
dev_err(bdc->dev, "BDC init failure:%d\n", ret);
return ret;
dev_err(dev, "BDC init failure:%d\n", ret);
goto phycleanup;
}
ret = bdc_udc_init(bdc);
if (ret) {
dev_err(bdc->dev, "BDC Gadget init failure:%d\n", ret);
dev_err(dev, "BDC Gadget init failure:%d\n", ret);
goto cleanup;
}
return 0;
cleanup:
bdc_hw_exit(bdc);
phycleanup:
bdc_phy_exit(bdc);
return ret;
}
@ -513,13 +600,56 @@ static int bdc_remove(struct platform_device *pdev)
dev_dbg(bdc->dev, "%s ()\n", __func__);
bdc_udc_exit(bdc);
bdc_hw_exit(bdc);
bdc_phy_exit(bdc);
clk_disable_unprepare(bdc->clk);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int bdc_suspend(struct device *dev)
{
struct bdc *bdc = dev_get_drvdata(dev);
clk_disable_unprepare(bdc->clk);
return 0;
}
static int bdc_resume(struct device *dev)
{
struct bdc *bdc = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(bdc->clk);
if (ret) {
dev_err(bdc->dev, "err enabling the clock\n");
return ret;
}
ret = bdc_reinit(bdc);
if (ret) {
dev_err(bdc->dev, "err in bdc reinit\n");
return ret;
}
return 0;
}
#endif /* CONFIG_PM_SLEEP */
static SIMPLE_DEV_PM_OPS(bdc_pm_ops, bdc_suspend,
bdc_resume);
static const struct of_device_id bdc_of_match[] = {
{ .compatible = "brcm,bdc-v0.16" },
{ .compatible = "brcm,bdc" },
{ /* sentinel */ }
};
static struct platform_driver bdc_driver = {
.driver = {
.name = BRCM_BDC_NAME,
.owner = THIS_MODULE,
.pm = &bdc_pm_ops,
.of_match_table = bdc_of_match,
},
.probe = bdc_probe,
.remove = bdc_remove,

View File

@ -40,28 +40,28 @@ void bdc_dump_epsts(struct bdc *bdc)
{
u32 temp;
temp = bdc_readl(bdc->regs, BDC_EPSTS0(0));
temp = bdc_readl(bdc->regs, BDC_EPSTS0);
dev_vdbg(bdc->dev, "BDC_EPSTS0:0x%08x\n", temp);
temp = bdc_readl(bdc->regs, BDC_EPSTS1(0));
temp = bdc_readl(bdc->regs, BDC_EPSTS1);
dev_vdbg(bdc->dev, "BDC_EPSTS1:0x%x\n", temp);
temp = bdc_readl(bdc->regs, BDC_EPSTS2(0));
temp = bdc_readl(bdc->regs, BDC_EPSTS2);
dev_vdbg(bdc->dev, "BDC_EPSTS2:0x%08x\n", temp);
temp = bdc_readl(bdc->regs, BDC_EPSTS3(0));
temp = bdc_readl(bdc->regs, BDC_EPSTS3);
dev_vdbg(bdc->dev, "BDC_EPSTS3:0x%08x\n", temp);
temp = bdc_readl(bdc->regs, BDC_EPSTS4(0));
temp = bdc_readl(bdc->regs, BDC_EPSTS4);
dev_vdbg(bdc->dev, "BDC_EPSTS4:0x%08x\n", temp);
temp = bdc_readl(bdc->regs, BDC_EPSTS5(0));
temp = bdc_readl(bdc->regs, BDC_EPSTS5);
dev_vdbg(bdc->dev, "BDC_EPSTS5:0x%08x\n", temp);
temp = bdc_readl(bdc->regs, BDC_EPSTS6(0));
temp = bdc_readl(bdc->regs, BDC_EPSTS6);
dev_vdbg(bdc->dev, "BDC_EPSTS6:0x%08x\n", temp);
temp = bdc_readl(bdc->regs, BDC_EPSTS7(0));
temp = bdc_readl(bdc->regs, BDC_EPSTS7);
dev_vdbg(bdc->dev, "BDC_EPSTS7:0x%08x\n", temp);
}

View File

@ -777,9 +777,9 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req)
*/
/* The current hw dequeue pointer */
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(0));
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0);
deq_ptr_64 = tmp_32;
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1(0));
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1);
deq_ptr_64 |= ((u64)tmp_32 << 32);
/* we have the dma addr of next bd that will be fetched by hardware */

View File

@ -249,6 +249,7 @@ void bdc_sr_uspc(struct bdc *bdc, struct bdc_sr *sreport)
disconn = true;
else if ((uspc & BDC_PCS) && !BDC_PST(uspc))
connected = true;
clear_flags |= BDC_PCC;
}
/* Change in VBus and VBus is present */
@ -259,16 +260,16 @@ void bdc_sr_uspc(struct bdc *bdc, struct bdc_sr *sreport)
bdc_softconn(bdc);
usb_gadget_set_state(&bdc->gadget, USB_STATE_POWERED);
}
clear_flags = BDC_VBC;
clear_flags |= BDC_VBC;
} else if ((uspc & BDC_PRS) || (uspc & BDC_PRC) || disconn) {
/* Hot reset, warm reset, 2.0 bus reset or disconn */
dev_dbg(bdc->dev, "Port reset or disconn\n");
bdc_uspc_disconnected(bdc, disconn);
clear_flags = BDC_PCC|BDC_PCS|BDC_PRS|BDC_PRC;
clear_flags |= BDC_PRC;
} else if ((uspc & BDC_PSC) && (uspc & BDC_PCS)) {
/* Change in Link state */
handle_link_state_change(bdc, uspc);
clear_flags = BDC_PSC|BDC_PCS;
clear_flags |= BDC_PSC;
}
/*

View File

@ -812,6 +812,8 @@ int usb_gadget_map_request_by_dev(struct device *dev,
dev_err(dev, "failed to map buffer\n");
return -EFAULT;
}
req->dma_mapped = 1;
}
return 0;
@ -836,9 +838,10 @@ void usb_gadget_unmap_request_by_dev(struct device *dev,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->num_mapped_sgs = 0;
} else {
} else if (req->dma_mapped) {
dma_unmap_single(dev, req->dma, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->dma_mapped = 0;
}
}
EXPORT_SYMBOL_GPL(usb_gadget_unmap_request_by_dev);
@ -1130,6 +1133,7 @@ static int check_pending_gadget_drivers(struct usb_udc *udc)
* @release: a gadget release function.
*
* Returns zero on success, negative errno otherwise.
* Calls the gadget release function in the latter case.
*/
int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
void (*release)(struct device *dev))
@ -1137,10 +1141,6 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
struct usb_udc *udc;
int ret = -ENOMEM;
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
if (!udc)
goto err1;
dev_set_name(&gadget->dev, "gadget");
INIT_WORK(&gadget->work, usb_gadget_state_work);
gadget->dev.parent = parent;
@ -1150,7 +1150,13 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
else
gadget->dev.release = usb_udc_nop_release;
ret = device_register(&gadget->dev);
device_initialize(&gadget->dev);
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
if (!udc)
goto err1;
ret = device_add(&gadget->dev);
if (ret)
goto err2;
@ -1197,10 +1203,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
device_del(&gadget->dev);
err2:
put_device(&gadget->dev);
kfree(udc);
err1:
put_device(&gadget->dev);
return ret;
}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);

View File

@ -2776,7 +2776,7 @@ static int __init init(void)
if (retval < 0) {
i--;
while (i >= 0)
platform_device_del(the_udc_pdev[i]);
platform_device_del(the_udc_pdev[i--]);
goto err_add_udc;
}
}

View File

@ -62,7 +62,7 @@ static const char *const ep_name[] = {
"ep3",
};
static struct usb_endpoint_descriptor qe_ep0_desc = {
static const struct usb_endpoint_descriptor qe_ep0_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

View File

@ -39,7 +39,6 @@
#include "mv_udc.h"
#define DRIVER_DESC "Marvell PXA USB Device Controller driver"
#define DRIVER_VERSION "8 Nov 2010"
#define ep_dir(ep) (((ep)->ep_num == 0) ? \
((ep)->udc->ep0_dir) : ((ep)->direction))
@ -2427,5 +2426,4 @@ module_platform_driver(udc_driver);
MODULE_ALIAS("platform:mv-udc");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");

View File

@ -8,6 +8,7 @@
* the Free Software Foundation; version 2 of the License.
*/
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
@ -20,6 +21,8 @@
#include <linux/pm_runtime.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@ -347,6 +350,7 @@ struct renesas_usb3 {
bool workaround_for_vbus;
bool extcon_host; /* check id and set EXTCON_USB_HOST */
bool extcon_usb; /* check vbus and set EXTCON_USB */
bool forced_b_device;
};
#define gadget_to_renesas_usb3(_gadget) \
@ -663,7 +667,9 @@ static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
spin_lock_irqsave(&usb3->lock, flags);
usb3_set_mode(usb3, host);
usb3_vbus_out(usb3, a_dev);
if (!host && a_dev) /* for A-Peripheral */
/* for A-Peripheral or forced B-device mode */
if ((!host && a_dev) ||
(usb3->workaround_for_vbus && usb3->forced_b_device))
usb3_connect(usb3);
spin_unlock_irqrestore(&usb3->lock, flags);
}
@ -677,7 +683,7 @@ static void usb3_check_id(struct renesas_usb3 *usb3)
{
usb3->extcon_host = usb3_is_a_device(usb3);
if (usb3->extcon_host)
if (usb3->extcon_host && !usb3->forced_b_device)
usb3_mode_config(usb3, true, true);
else
usb3_mode_config(usb3, false, false);
@ -2192,7 +2198,7 @@ static void renesas_usb3_ep_fifo_flush(struct usb_ep *_ep)
}
}
static struct usb_ep_ops renesas_usb3_ep_ops = {
static const struct usb_ep_ops renesas_usb3_ep_ops = {
.enable = renesas_usb3_ep_enable,
.disable = renesas_usb3_ep_disable,
@ -2283,6 +2289,9 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
if (!usb3->driver)
return -ENODEV;
if (usb3->forced_b_device)
return -EBUSY;
if (!strncmp(buf, "host", strlen("host")))
new_mode_is_host = true;
else if (!strncmp(buf, "peripheral", strlen("peripheral")))
@ -2310,6 +2319,70 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RW(role);
static int renesas_usb3_b_device_show(struct seq_file *s, void *unused)
{
struct renesas_usb3 *usb3 = s->private;
seq_printf(s, "%d\n", usb3->forced_b_device);
return 0;
}
static int renesas_usb3_b_device_open(struct inode *inode, struct file *file)
{
return single_open(file, renesas_usb3_b_device_show, inode->i_private);
}
static ssize_t renesas_usb3_b_device_write(struct file *file,
const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct renesas_usb3 *usb3 = s->private;
char buf[32];
if (!usb3->driver)
return -ENODEV;
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
if (!strncmp(buf, "1", 1))
usb3->forced_b_device = true;
else
usb3->forced_b_device = false;
/* Let this driver call usb3_connect() anyway */
usb3_check_id(usb3);
return count;
}
static const struct file_operations renesas_usb3_b_device_fops = {
.open = renesas_usb3_b_device_open,
.write = renesas_usb3_b_device_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3,
struct device *dev)
{
struct dentry *root, *file;
root = debugfs_create_dir(dev_name(dev), NULL);
if (IS_ERR_OR_NULL(root)) {
dev_info(dev, "%s: Can't create the root\n", __func__);
return;
}
file = debugfs_create_file("b_device", 0644, root, usb3,
&renesas_usb3_b_device_fops);
if (!file)
dev_info(dev, "%s: Can't create debugfs mode\n", __func__);
}
/*------- platform_driver ------------------------------------------------*/
static int renesas_usb3_remove(struct platform_device *pdev)
{
@ -2432,22 +2505,40 @@ static void renesas_usb3_init_ram(struct renesas_usb3 *usb3, struct device *dev,
}
}
static const struct renesas_usb3_priv renesas_usb3_priv_r8a7795 = {
static const struct renesas_usb3_priv renesas_usb3_priv_r8a7795_es1 = {
.ramsize_per_ramif = SZ_16K,
.num_ramif = 2,
.ramsize_per_pipe = SZ_4K,
.workaround_for_vbus = true,
};
static const struct renesas_usb3_priv renesas_usb3_priv_gen3 = {
.ramsize_per_ramif = SZ_16K,
.num_ramif = 4,
.ramsize_per_pipe = SZ_4K,
};
static const struct of_device_id usb3_of_match[] = {
{
.compatible = "renesas,r8a7795-usb3-peri",
.data = &renesas_usb3_priv_r8a7795,
.data = &renesas_usb3_priv_gen3,
},
{
.compatible = "renesas,rcar-gen3-usb3-peri",
.data = &renesas_usb3_priv_gen3,
},
{ },
};
MODULE_DEVICE_TABLE(of, usb3_of_match);
static const struct soc_device_attribute renesas_usb3_quirks_match[] = {
{
.soc_id = "r8a7795", .revision = "ES1.*",
.data = &renesas_usb3_priv_r8a7795_es1,
},
{ /* sentinel */ },
};
static const unsigned int renesas_usb3_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
@ -2461,15 +2552,23 @@ static int renesas_usb3_probe(struct platform_device *pdev)
const struct of_device_id *match;
int irq, ret;
const struct renesas_usb3_priv *priv;
const struct soc_device_attribute *attr;
match = of_match_node(usb3_of_match, pdev->dev.of_node);
if (!match)
return -ENODEV;
priv = match->data;
attr = soc_device_match(renesas_usb3_quirks_match);
if (attr)
priv = attr->data;
else
priv = match->data;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -ENODEV;
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
return irq;
}
usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL);
if (!usb3)
@ -2527,6 +2626,8 @@ static int renesas_usb3_probe(struct platform_device *pdev)
usb3->workaround_for_vbus = priv->workaround_for_vbus;
renesas_usb3_debugfs_init(usb3, &pdev->dev);
dev_info(&pdev->dev, "probed\n");
return 0;

View File

@ -51,7 +51,6 @@
#include "s3c2410_udc.h"
#define DRIVER_DESC "S3C2410 USB Device Controller Gadget"
#define DRIVER_VERSION "29 Apr 2007"
#define DRIVER_AUTHOR "Herbert Pötzl <herbert@13thfloor.at>, " \
"Arnaud Patard <arnaud.patard@rtp-net.org>"
@ -1996,7 +1995,7 @@ static int __init udc_init(void)
{
int retval;
dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
dprintk(DEBUG_NORMAL, "%s\n", gadget_name);
s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
if (IS_ERR(s3c2410_udc_debugfs_root)) {
@ -2027,5 +2026,4 @@ module_exit(udc_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");

View File

@ -642,7 +642,7 @@ static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port)
#define ehci_start_port_reset NULL
#endif /* CONFIG_USB_OTG */
static struct ehci_driver_overrides ehci_fsl_overrides __initdata = {
static const struct ehci_driver_overrides ehci_fsl_overrides __initconst = {
.extra_priv_size = sizeof(struct ehci_fsl),
.reset = ehci_fsl_setup,
};

View File

@ -130,8 +130,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "EHCI irq failed\n");
return -ENODEV;
dev_err(dev, "EHCI irq failed: %d\n", irq);
return irq;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

View File

@ -55,8 +55,8 @@ static struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)
return &dr_mode_data[i];
}
}
pr_warn("%s: Invalid 'dr_mode' property, fallback to host mode\n",
np->full_name);
pr_warn("%pOF: Invalid 'dr_mode' property, fallback to host mode\n",
np);
return &dr_mode_data[0]; /* mode not specified, use host */
}

View File

@ -614,7 +614,7 @@ static int wa_fill_descr(struct wahc *wa)
return result;
}
static struct hc_driver hwahc_hc_driver = {
static const struct hc_driver hwahc_hc_driver = {
.description = "hwa-hcd",
.product_desc = "Wireless USB HWA host controller",
.hcd_priv_size = sizeof(struct hwahc) - sizeof(struct usb_hcd),
@ -860,7 +860,7 @@ static void hwahc_disconnect(struct usb_interface *usb_iface)
usb_put_hcd(usb_hcd);
}
static struct usb_device_id hwahc_id_table[] = {
static const struct usb_device_id hwahc_id_table[] = {
/* Alereon 5310 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5310, 0xe0, 0x02, 0x01),
.driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC |

View File

@ -1779,7 +1779,7 @@ static void imx21_hc_stop(struct usb_hcd *hcd)
/* Driver glue */
/* =========================================== */
static struct hc_driver imx21_hc_driver = {
static const struct hc_driver imx21_hc_driver = {
.description = hcd_name,
.product_desc = "IMX21 USB Host Controller",
.hcd_priv_size = sizeof(struct imx21),
@ -1849,8 +1849,10 @@ static int imx21_probe(struct platform_device *pdev)
if (!res)
return -ENODEV;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -ENXIO;
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
return irq;
}
hcd = usb_create_hcd(&imx21_hc_driver,
&pdev->dev, dev_name(&pdev->dev));

View File

@ -1511,7 +1511,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
#endif
static struct hc_driver isp116x_hc_driver = {
static const struct hc_driver isp116x_hc_driver = {
.description = hcd_name,
.product_desc = "ISP116x Host Controller",
.hcd_priv_size = sizeof(struct isp116x),

View File

@ -2591,7 +2591,7 @@ static int isp1362_hc_start(struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
static struct hc_driver isp1362_hc_driver = {
static const struct hc_driver isp1362_hc_driver = {
.description = hcd_name,
.product_desc = "ISP1362 Host Controller",
.hcd_priv_size = sizeof(struct isp1362_hcd),

View File

@ -1811,7 +1811,7 @@ max3421_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
}
static struct hc_driver max3421_hcd_desc = {
static const struct hc_driver max3421_hcd_desc = {
.description = "max3421",
.product_desc = DRIVER_DESC,
.hcd_priv_size = sizeof(struct max3421_hcd),

View File

@ -142,29 +142,30 @@ static int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo)
pinfo->sb_type.gen = AMD_CHIPSET_SB700;
else if (rev >= 0x40 && rev <= 0x4f)
pinfo->sb_type.gen = AMD_CHIPSET_SB800;
}
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
0x145c, NULL);
if (pinfo->smbus_dev) {
pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN;
} else {
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
if (!pinfo->smbus_dev) {
pinfo->sb_type.gen = NOT_AMD_CHIPSET;
return 0;
if (pinfo->smbus_dev) {
rev = pinfo->smbus_dev->revision;
if (rev >= 0x11 && rev <= 0x14)
pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
else if (rev >= 0x15 && rev <= 0x18)
pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
else if (rev >= 0x39 && rev <= 0x3a)
pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
} else {
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
0x145c, NULL);
if (pinfo->smbus_dev) {
rev = pinfo->smbus_dev->revision;
pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN;
} else {
pinfo->sb_type.gen = NOT_AMD_CHIPSET;
return 0;
}
}
rev = pinfo->smbus_dev->revision;
if (rev >= 0x11 && rev <= 0x14)
pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
else if (rev >= 0x15 && rev <= 0x18)
pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
else if (rev >= 0x39 && rev <= 0x3a)
pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
}
pinfo->sb_type.rev = rev;
return 1;
}

View File

@ -2312,7 +2312,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
#define r8a66597_bus_resume NULL
#endif
static struct hc_driver r8a66597_hc_driver = {
static const struct hc_driver r8a66597_hc_driver = {
.description = hcd_name,
.hcd_priv_size = sizeof(struct r8a66597),
.irq = r8a66597_irq,

View File

@ -1554,7 +1554,7 @@ sl811h_start(struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
static struct hc_driver sl811h_hc_driver = {
static const struct hc_driver sl811h_hc_driver = {
.description = hcd_name,
.hcd_priv_size = sizeof(struct sl811),

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