Commit cad2be29 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'phy-for-4.14_v2' of...

Merge tag 'phy-for-4.14_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next

Kishon writes:

phy: for 4.14

 *) Add USB PHY driver for Ralink SoC
 *) Make phy-mt65xx-usb3 driver support PCIe and SATA phy
 *) Add mediatek directory and rename phy-mt65xx-usb3 to phy-mtk-tphy.c
    since it now supports USB3.0, PCIe and SATA PHYs
 *) Make sun4i-usb-phy driver support USB PHYs for A83T SoC
 *) Make phy-qcom-qmp driver support USB PHYs for IPQ8074 SoC
 *) Make rockchip-inno-usb2 driver support usb2-phy for rv1108 SoC
 *) Minor fixes in phy drivers
Signed-off-by: default avatarKishon Vijay Abraham I <kishon@ti.com>
parents 34a00367 d9c51f4c
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): Required properties (controller (parent) node):
- compatible : should be one of - compatible : should be one of
"mediatek,mt2701-u3phy" "mediatek,generic-tphy-v1"
"mediatek,mt2712-u3phy" "mediatek,generic-tphy-v2"
"mediatek,mt8173-u3phy" "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 + - clocks : (deprecated, use port's clocks instead) a list of phandle +
clock-specifier pairs, one for each entry in clock-names clock-specifier pairs, one for each entry in clock-names
- clock-names : (deprecated, use port's one instead) must contain - clock-names : (deprecated, use port's one instead) must contain
...@@ -35,6 +40,8 @@ Required properties (port (child) node): ...@@ -35,6 +40,8 @@ Required properties (port (child) node):
cell after port phandle is phy type from: cell after port phandle is phy type from:
- PHY_TYPE_USB2 - PHY_TYPE_USB2
- PHY_TYPE_USB3 - PHY_TYPE_USB3
- PHY_TYPE_PCIE
- PHY_TYPE_SATA
Example: Example:
......
...@@ -6,6 +6,7 @@ Required properties (phy (parent) node): ...@@ -6,6 +6,7 @@ Required properties (phy (parent) node):
* "rockchip,rk3328-usb2phy" * "rockchip,rk3328-usb2phy"
* "rockchip,rk3366-usb2phy" * "rockchip,rk3366-usb2phy"
* "rockchip,rk3399-usb2phy" * "rockchip,rk3399-usb2phy"
* "rockchip,rv1108-usb2phy"
- reg : the address offset of grf for usb-phy configuration. - reg : the address offset of grf for usb-phy configuration.
- #clock-cells : should be 0. - #clock-cells : should be 0.
- clock-output-names : specify the 480m output clock name. - clock-output-names : specify the 480m output clock name.
...@@ -18,6 +19,10 @@ Optional properties: ...@@ -18,6 +19,10 @@ Optional properties:
usb-phy output 480m and xin24m. usb-phy output 480m and xin24m.
Refer to clk/clock-bindings.txt for generic clock Refer to clk/clock-bindings.txt for generic clock
consumer properties. 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. 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, 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. ...@@ -28,10 +33,14 @@ Required nodes : a sub-node is required for each port the phy provides.
Required properties (port (child) node): Required properties (port (child) node):
- #phy-cells : must be 0. See ./phy-bindings.txt for details. - #phy-cells : must be 0. See ./phy-bindings.txt for details.
- interrupts : specify an interrupt for each entry in interrupt-names. - 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-id" : for the otg id interrupt.
* "otg-bvalid" : for the otg vbus interrupt. * "otg-bvalid" : for the otg vbus interrupt.
* "linestate" : for the host/otg linestate 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: Optional properties:
- phy-supply : phandle to a regulator that provides power to VBUS. - phy-supply : phandle to a regulator that provides power to VBUS.
......
...@@ -6,6 +6,7 @@ controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB. ...@@ -6,6 +6,7 @@ controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
Required properties: Required properties:
- compatible: compatible list, contains: - 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-pcie-phy" for 14nm PCIe phy on msm8996,
"qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996. "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996.
...@@ -38,6 +39,8 @@ Required properties: ...@@ -38,6 +39,8 @@ Required properties:
"phy", "common", "cfg". "phy", "common", "cfg".
For "qcom,msm8996-qmp-usb3-phy" must contain For "qcom,msm8996-qmp-usb3-phy" must contain
"phy", "common". "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-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. - vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
...@@ -60,6 +63,13 @@ Required properties for child node: ...@@ -60,6 +63,13 @@ Required properties for child node:
one for each entry in clock-names. one for each entry in clock-names.
- clock-names: Must contain following for pcie and usb qmp phys: - clock-names: Must contain following for pcie and usb qmp phys:
"pipe<lane-number>" for pipe clock specific to each lane. "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, - resets: a list of phandles and reset controller specifier pairs,
one for each entry in reset-names. one for each entry in reset-names.
...@@ -96,6 +106,7 @@ Example: ...@@ -96,6 +106,7 @@ Example:
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
clock-names = "pipe0"; clock-names = "pipe0";
clock-output-names = "pcie_0_pipe_clk_src";
resets = <&gcc GCC_PCIE_0_PHY_BCR>; resets = <&gcc GCC_PCIE_0_PHY_BCR>;
reset-names = "lane0"; reset-names = "lane0";
}; };
......
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";
};
...@@ -9,6 +9,7 @@ Required properties: ...@@ -9,6 +9,7 @@ Required properties:
* allwinner,sun7i-a20-usb-phy * allwinner,sun7i-a20-usb-phy
* allwinner,sun8i-a23-usb-phy * allwinner,sun8i-a23-usb-phy
* allwinner,sun8i-a33-usb-phy * allwinner,sun8i-a33-usb-phy
* allwinner,sun8i-a83t-usb-phy
* allwinner,sun8i-h3-usb-phy * allwinner,sun8i-h3-usb-phy
* allwinner,sun8i-v3s-usb-phy * allwinner,sun8i-v3s-usb-phy
* allwinner,sun50i-a64-usb-phy * allwinner,sun50i-a64-usb-phy
...@@ -17,18 +18,22 @@ Required properties: ...@@ -17,18 +18,22 @@ Required properties:
* "phy_ctrl" * "phy_ctrl"
* "pmu0" for H3, V3s and A64 * "pmu0" for H3, V3s and A64
* "pmu1" * "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 - #phy-cells : from the generic phy bindings, must be 1
- clocks : phandle + clock specifier for the phy clocks - clocks : phandle + clock specifier for the phy clocks
- clock-names : - clock-names :
* "usb_phy" for sun4i, sun5i or sun7i * "usb_phy" for sun4i, sun5i or sun7i
* "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i * "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
* "usb0_phy", "usb1_phy" for sun8i * "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 - resets : a list of phandle + reset specifier pairs
- reset-names : - reset-names :
* "usb0_reset" * "usb0_reset"
* "usb1_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: Optional properties:
- usb0_id_det-gpios : gpio phandle for reading the otg id pin value - usb0_id_det-gpios : gpio phandle for reading the otg id pin value
...@@ -37,6 +42,7 @@ Optional properties: ...@@ -37,6 +42,7 @@ Optional properties:
- usb0_vbus-supply : regulator phandle for controller usb0 vbus - usb0_vbus-supply : regulator phandle for controller usb0 vbus
- usb1_vbus-supply : regulator phandle for controller usb1 vbus - usb1_vbus-supply : regulator phandle for controller usb1 vbus
- usb2_vbus-supply : regulator phandle for controller usb2 vbus - usb2_vbus-supply : regulator phandle for controller usb2 vbus
- usb3_vbus-supply : regulator phandle for controller usb3 vbus
Example: Example:
usbphy: phy@0x01c13400 { usbphy: phy@0x01c13400 {
......
...@@ -1570,7 +1570,7 @@ M: Chunfeng Yun <chunfeng.yun@mediatek.com> ...@@ -1570,7 +1570,7 @@ M: Chunfeng Yun <chunfeng.yun@mediatek.com>
L: linux-arm-kernel@lists.infradead.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) L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: drivers/phy/phy-mt65xx-usb3.c F: drivers/phy/mediatek/phy-mtk-tphy.c
ARM/MICREL KS8695 ARCHITECTURE ARM/MICREL KS8695 ARCHITECTURE
M: Greg Ungerer <gerg@uclinux.org> M: Greg Ungerer <gerg@uclinux.org>
......
...@@ -26,14 +26,6 @@ config PHY_LPC18XX_USB_OTG ...@@ -26,14 +26,6 @@ config PHY_LPC18XX_USB_OTG
This driver is need for USB0 support on LPC18xx/43xx and takes This driver is need for USB0 support on LPC18xx/43xx and takes
care of enabling and clock setup. 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 config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver" tristate "IMG Pistachio USB2.0 PHY driver"
depends on MACH_PISTACHIO depends on MACH_PISTACHIO
...@@ -53,8 +45,10 @@ source "drivers/phy/amlogic/Kconfig" ...@@ -53,8 +45,10 @@ source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig" source "drivers/phy/broadcom/Kconfig"
source "drivers/phy/hisilicon/Kconfig" source "drivers/phy/hisilicon/Kconfig"
source "drivers/phy/marvell/Kconfig" source "drivers/phy/marvell/Kconfig"
source "drivers/phy/mediatek/Kconfig"
source "drivers/phy/motorola/Kconfig" source "drivers/phy/motorola/Kconfig"
source "drivers/phy/qualcomm/Kconfig" source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/ralink/Kconfig"
source "drivers/phy/renesas/Kconfig" source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig" source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig" source "drivers/phy/samsung/Kconfig"
......
...@@ -4,12 +4,12 @@ ...@@ -4,12 +4,12 @@
obj-$(CONFIG_GENERIC_PHY) += phy-core.o obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.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_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_ARCH_SUNXI) += allwinner/ obj-$(CONFIG_ARCH_SUNXI) += allwinner/
obj-$(CONFIG_ARCH_MESON) += amlogic/ obj-$(CONFIG_ARCH_MESON) += amlogic/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_RENESAS) += renesas/ obj-$(CONFIG_ARCH_RENESAS) += renesas/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_ARCH_TEGRA) += tegra/
...@@ -18,6 +18,7 @@ obj-y += broadcom/ \ ...@@ -18,6 +18,7 @@ obj-y += broadcom/ \
marvell/ \ marvell/ \
motorola/ \ motorola/ \
qualcomm/ \ qualcomm/ \
ralink/ \
samsung/ \ samsung/ \
st/ \ st/ \
ti/ ti/
...@@ -87,6 +87,16 @@ ...@@ -87,6 +87,16 @@
#define PHY_DISCON_TH_SEL 0x2a #define PHY_DISCON_TH_SEL 0x2a
#define PHY_SQUELCH_DETECT 0x3c #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 #define MAX_PHYS 4
/* /*
...@@ -100,6 +110,7 @@ enum sun4i_usb_phy_type { ...@@ -100,6 +110,7 @@ enum sun4i_usb_phy_type {
sun4i_a10_phy, sun4i_a10_phy,
sun6i_a31_phy, sun6i_a31_phy,
sun8i_a33_phy, sun8i_a33_phy,
sun8i_a83t_phy,
sun8i_h3_phy, sun8i_h3_phy,
sun8i_v3s_phy, sun8i_v3s_phy,
sun50i_a64_phy, sun50i_a64_phy,
...@@ -107,6 +118,7 @@ enum sun4i_usb_phy_type { ...@@ -107,6 +118,7 @@ enum sun4i_usb_phy_type {
struct sun4i_usb_phy_cfg { struct sun4i_usb_phy_cfg {
int num_phys; int num_phys;
int hsic_index;
enum sun4i_usb_phy_type type; enum sun4i_usb_phy_type type;
u32 disc_thresh; u32 disc_thresh;
u8 phyctl_offset; u8 phyctl_offset;
...@@ -126,6 +138,7 @@ struct sun4i_usb_phy_data { ...@@ -126,6 +138,7 @@ struct sun4i_usb_phy_data {
struct regulator *vbus; struct regulator *vbus;
struct reset_control *reset; struct reset_control *reset;
struct clk *clk; struct clk *clk;
struct clk *clk2;
bool regulator_on; bool regulator_on;
int index; int index;
} phys[MAX_PHYS]; } phys[MAX_PHYS];
...@@ -232,6 +245,7 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, ...@@ -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) 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; u32 bits, reg_value;
if (!phy->pmu) if (!phy->pmu)
...@@ -240,6 +254,11 @@ static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable) ...@@ -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 | bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_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); reg_value = readl(phy->pmu);
if (enable) if (enable)
...@@ -261,27 +280,43 @@ static int sun4i_usb_phy_init(struct phy *_phy) ...@@ -261,27 +280,43 @@ static int sun4i_usb_phy_init(struct phy *_phy)
if (ret) if (ret)
return ret; return ret;
ret = reset_control_deassert(phy->reset); ret = clk_prepare_enable(phy->clk2);
if (ret) { if (ret) {
clk_disable_unprepare(phy->clk); clk_disable_unprepare(phy->clk);
return ret; return ret;
} }
if (phy->pmu && data->cfg->enable_pmu_unk1) { ret = reset_control_deassert(phy->reset);
val = readl(phy->pmu + REG_PMU_UNK1); if (ret) {
writel(val & ~2, phy->pmu + REG_PMU_UNK1); clk_disable_unprepare(phy->clk2);
clk_disable_unprepare(phy->clk);
return ret;
} }
/* Enable USB 45 Ohm resistor calibration */ if (data->cfg->type == sun8i_a83t_phy) {
if (phy->index == 0) if (phy->index == 0) {
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); 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 */ /* Enable USB 45 Ohm resistor calibration */
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); if (phy->index == 0)
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
/* Disconnect threshold adjustment */ /* Adjust PHY's magnitude and rate */
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
data->cfg->disc_thresh, 2);
/* Disconnect threshold adjustment */
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
data->cfg->disc_thresh, 2);
}
sun4i_usb_phy_passby(phy, 1); sun4i_usb_phy_passby(phy, 1);
...@@ -307,6 +342,13 @@ static int sun4i_usb_phy_exit(struct phy *_phy) ...@@ -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); struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
if (phy->index == 0) { 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 */ /* Disable pull-ups */
sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0); sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_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) ...@@ -315,6 +357,7 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
sun4i_usb_phy_passby(phy, 0); sun4i_usb_phy_passby(phy, 0);
reset_control_assert(phy->reset); reset_control_assert(phy->reset);
clk_disable_unprepare(phy->clk2);
clk_disable_unprepare(phy->clk); clk_disable_unprepare(phy->clk);
return 0; return 0;
...@@ -653,19 +696,25 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) ...@@ -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", data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
GPIOD_IN); 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); return PTR_ERR(data->id_det_gpio);
}
data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det", data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
GPIOD_IN); 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); return PTR_ERR(data->vbus_det_gpio);
}
if (of_find_property(np, "usb0_vbus_power-supply", NULL)) { if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
data->vbus_power_supply = devm_power_supply_get_by_phandle(dev, data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
"usb0_vbus_power-supply"); "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); return PTR_ERR(data->vbus_power_supply);
}
if (!data->vbus_power_supply) if (!data->vbus_power_supply)
return -EPROBE_DEFER; return -EPROBE_DEFER;
...@@ -674,8 +723,10 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) ...@@ -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->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
data->extcon = devm_extcon_dev_allocate(dev, sun4i_usb_phy0_cable); 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); return PTR_ERR(data->extcon);
}
ret = devm_extcon_dev_register(dev, data->extcon); ret = devm_extcon_dev_register(dev, data->extcon);
if (ret) { if (ret) {
...@@ -690,8 +741,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) ...@@ -690,8 +741,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
snprintf(name, sizeof(name), "usb%d_vbus", i); snprintf(name, sizeof(name), "usb%d_vbus", i);
phy->vbus = devm_regulator_get_optional(dev, name); phy->vbus = devm_regulator_get_optional(dev, name);
if (IS_ERR(phy->vbus)) { 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; return -EPROBE_DEFER;
}
phy->vbus = NULL; phy->vbus = NULL;
} }
...@@ -706,6 +762,17 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) ...@@ -706,6 +762,17 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy->clk); 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); snprintf(name, sizeof(name), "usb%d_reset", i);
phy->reset = devm_reset_control_get(dev, name); phy->reset = devm_reset_control_get(dev, name);
if (IS_ERR(phy->reset)) { if (IS_ERR(phy->reset)) {
...@@ -775,6 +842,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) ...@@ -775,6 +842,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy_provider); return PTR_ERR(phy_provider);
} }
dev_dbg(dev, "successfully loaded\n");
return 0; return 0;
} }
...@@ -832,6 +901,14 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { ...@@ -832,6 +901,14 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
.enable_pmu_unk1 = false, .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 = { static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
.num_phys = 4, .num_phys = 4,
.type = sun8i_h3_phy, .type = sun8i_h3_phy,
...@@ -868,6 +945,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = { ...@@ -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,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
{ .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg }, { .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
{ .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_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-h3-usb-phy", .data = &sun8i_h3_cfg },
{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg }, { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
{ .compatible = "allwinner,sun50i-a64-usb-phy", { .compatible = "allwinner,sun50i-a64-usb-phy",
......
...@@ -335,7 +335,7 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port) ...@@ -335,7 +335,7 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port)
/* Wait for pll_seq_done bit */ /* Wait for pll_seq_done bit */
try = 50; try = 50;
while (try--) { while (--try) {
val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK, val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
BLOCK0_XGXSSTATUS); BLOCK0_XGXSSTATUS);
if (val & BLOCK0_XGXSSTATUS_PLL_LOCK) if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
......
#
# 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.
#
# Makefile for the phy drivers.
#
obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */ #define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */
/* u2 phy bank */ /* u2 phy bank */
#define SSUSB_SIFSLV_V1_U2PHY_COM 0x000 #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_U3PHYD 0x000
#define SSUSB_SIFSLV_V1_U3PHYA 0x200 #define SSUSB_SIFSLV_V1_U3PHYA 0x200
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#define SSUSB_SIFSLV_V2_MISC 0x000 #define SSUSB_SIFSLV_V2_MISC 0x000
#define SSUSB_SIFSLV_V2_U2FREQ 0x100 #define SSUSB_SIFSLV_V2_U2FREQ 0x100
#define SSUSB_SIFSLV_V2_U2PHY_COM 0x300 #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_SPLLC 0x000
#define SSUSB_SIFSLV_V2_CHIP 0x100 #define SSUSB_SIFSLV_V2_CHIP 0x100
#define SSUSB_SIFSLV_V2_U3PHYD 0x200 #define SSUSB_SIFSLV_V2_U3PHYD 0x200
...@@ -99,6 +99,23 @@ ...@@ -99,6 +99,23 @@
#define P2C_RG_SESSEND BIT(4) #define P2C_RG_SESSEND BIT(4)
#define P2C_RG_AVALID BIT(2) #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 U3P_U3_PHYA_REG6 0x018
#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28) #define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28) #define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
...@@ -108,9 +125,40 @@ ...@@ -108,9 +125,40 @@
#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1) #define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
#define U3P_U3_PHYA_DA_REG0 0x100 #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 GENMASK(11, 10)
#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 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 U3P_U3_PHYD_LFPS1 0x00c
#define P3D_RG_FWAKE_TH GENMASK(21, 16) #define P3D_RG_FWAKE_TH GENMASK(21, 16)
#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16) #define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
...@@ -151,15 +199,74 @@ ...@@ -151,15 +199,74 @@
#define U3P_SR_COEF_DIVISOR 1000 #define U3P_SR_COEF_DIVISOR 1000
#define U3P_FM_DET_CYCLE_CNT 1024 #define U3P_FM_DET_CYCLE_CNT 1024
enum mt_phy_version { /* SATA register setting */
MT_PHY_V1 = 1, #define PHYD_CTRL_SIGNAL_MODE4 0x1c
MT_PHY_V2, /* 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 */ /* avoid RX sensitivity level degradation only for mt8173 */
bool avoid_rx_sen_degradation; bool avoid_rx_sen_degradation;
enum mt_phy_version version; enum mtk_phy_version version;
}; };
struct u2phy_banks { struct u2phy_banks {
...@@ -175,7 +282,7 @@ struct u3phy_banks { ...@@ -175,7 +282,7 @@ struct u3phy_banks {
void __iomem *phya; /* include u3phya_da */ void __iomem *phya; /* include u3phya_da */
}; };
struct mt65xx_phy_instance { struct mtk_phy_instance {
struct phy *phy; struct phy *phy;
void __iomem *port_base; void __iomem *port_base;
union { union {
...@@ -187,18 +294,18 @@ struct mt65xx_phy_instance { ...@@ -187,18 +294,18 @@ struct mt65xx_phy_instance {
u8 type; u8 type;
}; };
struct mt65xx_u3phy { struct mtk_tphy {
struct device *dev; struct device *dev;
void __iomem *sif_base; /* only shared sif */ void __iomem *sif_base; /* only shared sif */
/* deprecated, use @ref_clk instead in phy instance */ /* deprecated, use @ref_clk instead in phy instance */
struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */ struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
const struct mt65xx_phy_pdata *pdata; const struct mtk_phy_pdata *pdata;
struct mt65xx_phy_instance **phys; struct mtk_phy_instance **phys;
int nphys; int nphys;
}; };
static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
struct mt65xx_phy_instance *instance) struct mtk_phy_instance *instance)
{ {
struct u2phy_banks *u2_banks = &instance->u2_banks; struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *fmreg = u2_banks->fmreg; void __iomem *fmreg = u2_banks->fmreg;
...@@ -222,7 +329,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, ...@@ -222,7 +329,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
tmp = readl(fmreg + U3P_U2FREQ_FMCR0); tmp = readl(fmreg + U3P_U2FREQ_FMCR0);
tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL); tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL);
tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT); 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); tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1);
writel(tmp, fmreg + U3P_U2FREQ_FMCR0); writel(tmp, fmreg + U3P_U2FREQ_FMCR0);
...@@ -257,7 +364,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, ...@@ -257,7 +364,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
/* if FM detection fail, set default value */ /* if FM detection fail, set default value */
calibration_val = 4; 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); instance->index, fm_out, calibration_val);
/* set HS slew rate */ /* set HS slew rate */
...@@ -272,8 +379,8 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, ...@@ -272,8 +379,8 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
writel(tmp, com + U3P_USBPHYACR5); writel(tmp, com + U3P_USBPHYACR5);
} }
static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy, static void u3_phy_instance_init(struct mtk_tphy *tphy,
struct mt65xx_phy_instance *instance) struct mtk_phy_instance *instance)
{ {
struct u3phy_banks *u3_banks = &instance->u3_banks; struct u3phy_banks *u3_banks = &instance->u3_banks;
u32 tmp; u32 tmp;
...@@ -319,11 +426,11 @@ static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy, ...@@ -319,11 +426,11 @@ static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy,
tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10); tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2); 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, static void u2_phy_instance_init(struct mtk_tphy *tphy,
struct mt65xx_phy_instance *instance) struct mtk_phy_instance *instance)
{ {
struct u2phy_banks *u2_banks = &instance->u2_banks; struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *com = u2_banks->com; void __iomem *com = u2_banks->com;
...@@ -355,7 +462,7 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy, ...@@ -355,7 +462,7 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy,
writel(tmp, com + U3P_U2PHYACR4); writel(tmp, com + U3P_U2PHYACR4);
} }
if (u3phy->pdata->avoid_rx_sen_degradation) { if (tphy->pdata->avoid_rx_sen_degradation) {
if (!index) { if (!index) {
tmp = readl(com + U3P_USBPHYACR2); tmp = readl(com + U3P_USBPHYACR2);
tmp |= PA2_RG_SIF_U2PLL_FORCE_EN; tmp |= PA2_RG_SIF_U2PLL_FORCE_EN;
...@@ -381,11 +488,11 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy, ...@@ -381,11 +488,11 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy,
tmp |= PA6_RG_U2_SQTH_VAL(2); tmp |= PA6_RG_U2_SQTH_VAL(2);
writel(tmp, com + U3P_USBPHYACR6); 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, static void u2_phy_instance_power_on(struct mtk_tphy *tphy,
struct mt65xx_phy_instance *instance) struct mtk_phy_instance *instance)
{ {
struct u2phy_banks *u2_banks = &instance->u2_banks; struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *com = u2_banks->com; void __iomem *com = u2_banks->com;
...@@ -408,7 +515,7 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, ...@@ -408,7 +515,7 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
tmp &= ~P2C_RG_SESSEND; tmp &= ~P2C_RG_SESSEND;
writel(tmp, com + U3P_U2PHYDTM1); 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 = readl(com + U3D_U2PHYDCR0);
tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
writel(tmp, com + U3D_U2PHYDCR0); writel(tmp, com + U3D_U2PHYDCR0);
...@@ -417,11 +524,11 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, ...@@ -417,11 +524,11 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
writel(tmp, com + U3P_U2PHYDTM0); 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, static void u2_phy_instance_power_off(struct mtk_tphy *tphy,
struct mt65xx_phy_instance *instance) struct mtk_phy_instance *instance)
{ {
struct u2phy_banks *u2_banks = &instance->u2_banks; struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *com = u2_banks->com; void __iomem *com = u2_banks->com;
...@@ -449,24 +556,24 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy, ...@@ -449,24 +556,24 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
tmp |= P2C_RG_SESSEND; tmp |= P2C_RG_SESSEND;
writel(tmp, com + U3P_U2PHYDTM1); 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 = readl(com + U3D_U2PHYDCR0);
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
writel(tmp, com + U3D_U2PHYDCR0); 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, static void u2_phy_instance_exit(struct mtk_tphy *tphy,
struct mt65xx_phy_instance *instance) struct mtk_phy_instance *instance)
{ {
struct u2phy_banks *u2_banks = &instance->u2_banks; struct u2phy_banks *u2_banks = &instance->u2_banks;
void __iomem *com = u2_banks->com; void __iomem *com = u2_banks->com;
u32 index = instance->index; u32 index = instance->index;
u32 tmp; u32 tmp;
if (u3phy->pdata->avoid_rx_sen_degradation && index) { if (tphy->pdata->avoid_rx_sen_degradation && index) {
tmp = readl(com + U3D_U2PHYDCR0); tmp = readl(com + U3D_U2PHYDCR0);
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
writel(tmp, com + U3D_U2PHYDCR0); writel(tmp, com + U3D_U2PHYDCR0);
...@@ -477,109 +584,307 @@ static void phy_instance_exit(struct mt65xx_u3phy *u3phy, ...@@ -477,109 +584,307 @@ static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
} }
} }
static void phy_v1_banks_init(struct mt65xx_u3phy *u3phy, static void pcie_phy_instance_init(struct mtk_tphy *tphy,
struct mt65xx_phy_instance *instance) 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 u2phy_banks *u2_banks = &instance->u2_banks;
struct u3phy_banks *u3_banks = &instance->u3_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->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; u2_banks->com = instance->port_base + SSUSB_SIFSLV_V1_U2PHY_COM;
} else if (instance->type == PHY_TYPE_USB3) { break;
u3_banks->spllc = u3phy->sif_base + SSUSB_SIFSLV_V1_SPLLC; case PHY_TYPE_USB3:
case PHY_TYPE_PCIE:
u3_banks->spllc = tphy->sif_base + SSUSB_SIFSLV_V1_SPLLC;
u3_banks->chip = NULL; u3_banks->chip = NULL;
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD; u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD;
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA; 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, static void phy_v2_banks_init(struct mtk_tphy *tphy,
struct mt65xx_phy_instance *instance) struct mtk_phy_instance *instance)
{ {
struct u2phy_banks *u2_banks = &instance->u2_banks; struct u2phy_banks *u2_banks = &instance->u2_banks;
struct u3phy_banks *u3_banks = &instance->u3_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->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC;
u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ; u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ;
u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM; 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->spllc = instance->port_base + SSUSB_SIFSLV_V2_SPLLC;
u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP; u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP;
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD; u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD;
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V2_U3PHYA; 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 mtk_phy_instance *instance = phy_get_drvdata(phy);
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
int ret; int ret;
ret = clk_prepare_enable(u3phy->u3phya_ref); ret = clk_prepare_enable(tphy->u3phya_ref);
if (ret) { if (ret) {
dev_err(u3phy->dev, "failed to enable u3phya_ref\n"); dev_err(tphy->dev, "failed to enable u3phya_ref\n");
return ret; return ret;
} }
ret = clk_prepare_enable(instance->ref_clk); ret = clk_prepare_enable(instance->ref_clk);
if (ret) { if (ret) {
dev_err(u3phy->dev, "failed to enable ref_clk\n"); dev_err(tphy->dev, "failed to enable ref_clk\n");
return ret; return ret;
} }
if (instance->type == PHY_TYPE_USB2) switch (instance->type) {
phy_instance_init(u3phy, instance); case PHY_TYPE_USB2:
else u2_phy_instance_init(tphy, instance);
u3_phy_instance_init(u3phy, 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; 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 mtk_phy_instance *instance = phy_get_drvdata(phy);
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
if (instance->type == PHY_TYPE_USB2) { if (instance->type == PHY_TYPE_USB2) {
phy_instance_power_on(u3phy, instance); u2_phy_instance_power_on(tphy, instance);
hs_slew_rate_calibrate(u3phy, instance); hs_slew_rate_calibrate(tphy, instance);
} else if (instance->type == PHY_TYPE_PCIE) {
pcie_phy_instance_power_on(tphy, instance);
} }
return 0; return 0;
} }
static int mt65xx_phy_power_off(struct phy *phy) static int mtk_phy_power_off(struct phy *phy)
{ {
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); struct mtk_phy_instance *instance = phy_get_drvdata(phy);
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
if (instance->type == PHY_TYPE_USB2) if (instance->type == PHY_TYPE_USB2)
phy_instance_power_off(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; return 0;
} }
static int mt65xx_phy_exit(struct phy *phy) static int mtk_phy_exit(struct phy *phy)
{ {
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); struct mtk_phy_instance *instance = phy_get_drvdata(phy);
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
if (instance->type == PHY_TYPE_USB2) if (instance->type == PHY_TYPE_USB2)
phy_instance_exit(u3phy, instance); u2_phy_instance_exit(tphy, instance);
clk_disable_unprepare(instance->ref_clk); clk_disable_unprepare(instance->ref_clk);
clk_disable_unprepare(u3phy->u3phya_ref); clk_disable_unprepare(tphy->u3phya_ref);
return 0; 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 of_phandle_args *args)
{ {
struct mt65xx_u3phy *u3phy = dev_get_drvdata(dev); struct mtk_tphy *tphy = dev_get_drvdata(dev);
struct mt65xx_phy_instance *instance = NULL; struct mtk_phy_instance *instance = NULL;
struct device_node *phy_np = args->np; struct device_node *phy_np = args->np;
int index; int index;
...@@ -588,9 +893,9 @@ static struct phy *mt65xx_phy_xlate(struct device *dev, ...@@ -588,9 +893,9 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
for (index = 0; index < u3phy->nphys; index++) for (index = 0; index < tphy->nphys; index++)
if (phy_np == u3phy->phys[index]->phy->dev.of_node) { if (phy_np == tphy->phys[index]->phy->dev.of_node) {
instance = u3phy->phys[index]; instance = tphy->phys[index];
break; break;
} }
...@@ -601,15 +906,17 @@ static struct phy *mt65xx_phy_xlate(struct device *dev, ...@@ -601,15 +906,17 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
instance->type = args->args[0]; instance->type = args->args[0];
if (!(instance->type == PHY_TYPE_USB2 || 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); dev_err(dev, "unsupported device type: %d\n", instance->type);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
if (u3phy->pdata->version == MT_PHY_V1) { if (tphy->pdata->version == MTK_PHY_V1) {
phy_v1_banks_init(u3phy, instance); phy_v1_banks_init(tphy, instance);
} else if (u3phy->pdata->version == MT_PHY_V2) { } else if (tphy->pdata->version == MTK_PHY_V2) {
phy_v2_banks_init(u3phy, instance); phy_v2_banks_init(tphy, instance);
} else { } else {
dev_err(dev, "phy version is not supported\n"); dev_err(dev, "phy version is not supported\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -618,38 +925,40 @@ static struct phy *mt65xx_phy_xlate(struct device *dev, ...@@ -618,38 +925,40 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
return instance->phy; return instance->phy;
} }
static const struct phy_ops mt65xx_u3phy_ops = { static const struct phy_ops mtk_tphy_ops = {
.init = mt65xx_phy_init, .init = mtk_phy_init,
.exit = mt65xx_phy_exit, .exit = mtk_phy_exit,
.power_on = mt65xx_phy_power_on, .power_on = mtk_phy_power_on,
.power_off = mt65xx_phy_power_off, .power_off = mtk_phy_power_off,
.owner = THIS_MODULE, .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, .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, .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, .avoid_rx_sen_degradation = true,
.version = MT_PHY_V1, .version = MTK_PHY_V1,
}; };
static const struct of_device_id mt65xx_u3phy_id_table[] = { static const struct of_device_id mtk_tphy_id_table[] = {
{ .compatible = "mediatek,mt2701-u3phy", .data = &mt2701_pdata }, { .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata },
{ .compatible = "mediatek,mt2712-u3phy", .data = &mt2712_pdata }, { .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata },
{ .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_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; const struct of_device_id *match;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -657,50 +966,50 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev) ...@@ -657,50 +966,50 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
struct device_node *child_np; struct device_node *child_np;
struct phy_provider *provider; struct phy_provider *provider;
struct resource *sif_res; struct resource *sif_res;
struct mt65xx_u3phy *u3phy; struct mtk_tphy *tphy;
struct resource res; struct resource res;
int port, retval; 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) if (!match)
return -EINVAL; return -EINVAL;
u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL); tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL);
if (!u3phy) if (!tphy)
return -ENOMEM; return -ENOMEM;
u3phy->pdata = match->data; tphy->pdata = match->data;
u3phy->nphys = of_get_child_count(np); tphy->nphys = of_get_child_count(np);
u3phy->phys = devm_kcalloc(dev, u3phy->nphys, tphy->phys = devm_kcalloc(dev, tphy->nphys,
sizeof(*u3phy->phys), GFP_KERNEL); sizeof(*tphy->phys), GFP_KERNEL);
if (!u3phy->phys) if (!tphy->phys)
return -ENOMEM; return -ENOMEM;
u3phy->dev = dev; tphy->dev = dev;
platform_set_drvdata(pdev, u3phy); 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 */ /* get banks shared by multiple phys */
sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
u3phy->sif_base = devm_ioremap_resource(dev, sif_res); tphy->sif_base = devm_ioremap_resource(dev, sif_res);
if (IS_ERR(u3phy->sif_base)) { if (IS_ERR(tphy->sif_base)) {
dev_err(dev, "failed to remap sif regs\n"); 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 */ /* it's deprecated, make it optional for backward compatibility */
u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref"); tphy->u3phya_ref = devm_clk_get(dev, "u3phya_ref");
if (IS_ERR(u3phy->u3phya_ref)) { if (IS_ERR(tphy->u3phya_ref)) {
if (PTR_ERR(u3phy->u3phya_ref) == -EPROBE_DEFER) if (PTR_ERR(tphy->u3phya_ref) == -EPROBE_DEFER)
return -EPROBE_DEFER; return -EPROBE_DEFER;
u3phy->u3phya_ref = NULL; tphy->u3phya_ref = NULL;
} }
port = 0; port = 0;
for_each_child_of_node(np, child_np) { for_each_child_of_node(np, child_np) {
struct mt65xx_phy_instance *instance; struct mtk_phy_instance *instance;
struct phy *phy; struct phy *phy;
instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
...@@ -709,9 +1018,9 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev) ...@@ -709,9 +1018,9 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
goto put_child; 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)) { if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n"); dev_err(dev, "failed to create phy\n");
retval = PTR_ERR(phy); retval = PTR_ERR(phy);
...@@ -738,7 +1047,7 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev) ...@@ -738,7 +1047,7 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
port++; port++;
/* if deprecated clock is provided, ignore instance's one */ /* if deprecated clock is provided, ignore instance's one */
if (u3phy->u3phya_ref) if (tphy->u3phya_ref)
continue; continue;
instance->ref_clk = devm_clk_get(&phy->dev, "ref"); instance->ref_clk = devm_clk_get(&phy->dev, "ref");
...@@ -749,7 +1058,7 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev) ...@@ -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); return PTR_ERR_OR_ZERO(provider);
put_child: put_child:
...@@ -757,16 +1066,16 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev) ...@@ -757,16 +1066,16 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
return retval; return retval;
} }
static struct platform_driver mt65xx_u3phy_driver = { static struct platform_driver mtk_tphy_driver = {
.probe = mt65xx_u3phy_probe, .probe = mtk_tphy_probe,
.driver = { .driver = {
.name = "mt65xx-u3phy", .name = "mtk-tphy",
.of_match_table = mt65xx_u3phy_id_table, .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_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
MODULE_DESCRIPTION("mt65xx USB PHY driver"); MODULE_DESCRIPTION("MediaTek T-PHY driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -506,7 +506,7 @@ static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata) ...@@ -506,7 +506,7 @@ static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
if (IS_ERR(ddata->gpio[i])) { if (IS_ERR(ddata->gpio[i])) {
dev_info(ddata->dev, "no mode change GPIO%i: %li\n", dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
i, PTR_ERR(ddata->gpio[i])); i, PTR_ERR(ddata->gpio[i]));
ddata->gpio[i] = NULL; ddata->gpio[i] = NULL;
} }
} }
} }
......
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#define QSERDES_COM_PLL_RCTRL_MODE1 0x088 #define QSERDES_COM_PLL_RCTRL_MODE1 0x088
#define QSERDES_COM_PLL_CCTRL_MODE0 0x090 #define QSERDES_COM_PLL_CCTRL_MODE0 0x090
#define QSERDES_COM_PLL_CCTRL_MODE1 0x094 #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_SYSCLK_EN_SEL 0x0ac
#define QSERDES_COM_RESETSM_CNTRL 0x0b4 #define QSERDES_COM_RESETSM_CNTRL 0x0b4
#define QSERDES_COM_RESTRIM_CTRL 0x0bc #define QSERDES_COM_RESTRIM_CTRL 0x0bc
...@@ -143,6 +144,11 @@ ...@@ -143,6 +144,11 @@
#define QPHY_LOCK_DETECT_CONFIG3 0x88 #define QPHY_LOCK_DETECT_CONFIG3 0x88
#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0 #define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4 #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 */ /* QPHY_SW_RESET bit */
#define SW_RESET BIT(0) #define SW_RESET BIT(0)
...@@ -382,6 +388,85 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { ...@@ -382,6 +388,85 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08), 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 - per-PHY initialization config */
struct qmp_phy_cfg { struct qmp_phy_cfg {
/* phy-type - PCIE/UFS/USB */ /* phy-type - PCIE/UFS/USB */
...@@ -580,6 +665,42 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { ...@@ -580,6 +665,42 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
.mask_pcs_ready = PHYSTATUS, .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, static void qcom_qmp_phy_configure(void __iomem *base,
const unsigned int *regs, const unsigned int *regs,
const struct qmp_phy_init_tbl tbl[], const struct qmp_phy_init_tbl tbl[],
...@@ -654,8 +775,6 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) ...@@ -654,8 +775,6 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
if (ret) { if (ret) {
dev_err(qmp->dev, "%s reset deassert failed\n", dev_err(qmp->dev, "%s reset deassert failed\n",
qmp->cfg->reset_list[i]); qmp->cfg->reset_list[i]);
while (--i >= 0)
reset_control_assert(qmp->resets[i]);
goto err_rst; goto err_rst;
} }
} }
...@@ -684,7 +803,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) ...@@ -684,7 +803,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
if (ret) { if (ret) {
dev_err(qmp->dev, dev_err(qmp->dev,
"phy common block init timed-out\n"); "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) ...@@ -692,11 +811,11 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
return 0; return 0;
err_com_init: err_rst:
while (--i >= 0) while (--i >= 0)
reset_control_assert(qmp->resets[i]); reset_control_assert(qmp->resets[i]);
err_rst:
mutex_unlock(&qmp->phy_mutex); mutex_unlock(&qmp->phy_mutex);
return ret; return ret;
} }
...@@ -749,14 +868,13 @@ static int qcom_qmp_phy_init(struct phy *phy) ...@@ -749,14 +868,13 @@ static int qcom_qmp_phy_init(struct phy *phy)
if (ret) { if (ret) {
dev_err(qmp->dev, "failed to enable %s clk, err=%d\n", dev_err(qmp->dev, "failed to enable %s clk, err=%d\n",
qmp->cfg->clk_list[i], ret); qmp->cfg->clk_list[i], ret);
while (--i >= 0) goto err_clk;
clk_disable_unprepare(qmp->clks[i]);
} }
} }
ret = qcom_qmp_phy_com_init(qmp); ret = qcom_qmp_phy_com_init(qmp);
if (ret) if (ret)
goto err_com_init; goto err_clk;
if (cfg->has_lane_rst) { if (cfg->has_lane_rst) {
ret = reset_control_deassert(qphy->lane_rst); ret = reset_control_deassert(qphy->lane_rst);
...@@ -804,7 +922,7 @@ static int qcom_qmp_phy_init(struct phy *phy) ...@@ -804,7 +922,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
reset_control_assert(qphy->lane_rst); reset_control_assert(qphy->lane_rst);
err_lane_rst: err_lane_rst:
qcom_qmp_phy_com_exit(qmp); qcom_qmp_phy_com_exit(qmp);
err_com_init: err_clk:
while (--i >= 0) while (--i >= 0)
clk_disable_unprepare(qmp->clks[i]); clk_disable_unprepare(qmp->clks[i]);
...@@ -925,29 +1043,28 @@ static int qcom_qmp_phy_clk_init(struct device *dev) ...@@ -925,29 +1043,28 @@ static int qcom_qmp_phy_clk_init(struct device *dev)
* clk | +-------+ | +-----+ * 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_fixed_rate *fixed;
struct clk_init_data init = { }; struct clk_init_data init = { };
int ret;
switch (qmp->cfg->type) { if ((qmp->cfg->type != PHY_TYPE_USB3) &&
case PHY_TYPE_USB3: (qmp->cfg->type != PHY_TYPE_PCIE)) {
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:
/* not all phys register pipe clocks, so return success */ /* not all phys register pipe clocks, so return success */
return 0; 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); fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL);
if (!fixed) if (!fixed)
return -ENOMEM; return -ENOMEM;
init.name = name;
init.ops = &clk_fixed_rate_ops; init.ops = &clk_fixed_rate_ops;
/* controllers using QMP phys use 125MHz pipe clock interface */ /* 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[] = { ...@@ -1049,6 +1166,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
}, { }, {
.compatible = "qcom,msm8996-qmp-usb3-phy", .compatible = "qcom,msm8996-qmp-usb3-phy",
.data = &msm8996_usb3phy_cfg, .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) ...@@ -1122,7 +1242,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
* Register the pipe clock provided by phy. * Register the pipe clock provided by phy.
* See function description to see details of this pipe clock. * 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) { if (ret) {
dev_err(qmp->dev, dev_err(qmp->dev,
"failed to register pipe clock source\n"); "failed to register pipe clock source\n");
......
#
# 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.
obj-$(CONFIG_PHY_RALINK_USB) += phy-ralink-usb.o
/*
* 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 *) (RT_CLKCFG1_UPHY1_CLK_EN |
RT_CLKCFG1_UPHY0_CLK_EN)
},
{
.compatible = "mediatek,mt7620-usbphy",
.data = (void *) (MT7620_CLKCFG1_UPHY1_CLK_EN |
MT7620_CLKCFG1_UPHY0_CLK_EN)
},
{
.compatible = "mediatek,mt7628-usbphy",
.data = (void *) (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 = (u32) 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");
...@@ -172,6 +172,8 @@ struct rockchip_usb2phy_cfg { ...@@ -172,6 +172,8 @@ struct rockchip_usb2phy_cfg {
* @vbus_attached: otg device vbus status. * @vbus_attached: otg device vbus status.
* @bvalid_irq: IRQ number assigned for vbus valid rise detection. * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
* @ls_irq: IRQ number assigned for linestate 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. * @mutex: for register updating in sm_work.
* @chg_work: charge detect work. * @chg_work: charge detect work.
* @otg_sm_work: OTG state machine work. * @otg_sm_work: OTG state machine work.
...@@ -189,6 +191,7 @@ struct rockchip_usb2phy_port { ...@@ -189,6 +191,7 @@ struct rockchip_usb2phy_port {
bool vbus_attached; bool vbus_attached;
int bvalid_irq; int bvalid_irq;
int ls_irq; int ls_irq;
int otg_mux_irq;
struct mutex mutex; struct mutex mutex;
struct delayed_work chg_work; struct delayed_work chg_work;
struct delayed_work otg_sm_work; struct delayed_work otg_sm_work;
...@@ -202,6 +205,7 @@ struct rockchip_usb2phy_port { ...@@ -202,6 +205,7 @@ struct rockchip_usb2phy_port {
/** /**
* struct rockchip_usb2phy: usb2.0 phy driver data. * struct rockchip_usb2phy: usb2.0 phy driver data.
* @grf: General Register Files regmap. * @grf: General Register Files regmap.
* @usbgrf: USB General Register Files regmap.
* @clk: clock struct of phy input clk. * @clk: clock struct of phy input clk.
* @clk480m: clock struct of phy output clk. * @clk480m: clock struct of phy output clk.
* @clk_hw: clock struct of phy output clk management. * @clk_hw: clock struct of phy output clk management.
...@@ -216,6 +220,7 @@ struct rockchip_usb2phy_port { ...@@ -216,6 +220,7 @@ struct rockchip_usb2phy_port {
struct rockchip_usb2phy { struct rockchip_usb2phy {
struct device *dev; struct device *dev;
struct regmap *grf; struct regmap *grf;
struct regmap *usbgrf;
struct clk *clk; struct clk *clk;
struct clk *clk480m; struct clk *clk480m;
struct clk_hw clk480m_hw; struct clk_hw clk480m_hw;
...@@ -227,7 +232,12 @@ struct rockchip_usb2phy { ...@@ -227,7 +232,12 @@ struct rockchip_usb2phy {
struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; 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) const struct usb2phy_reg *reg, bool en)
{ {
unsigned int val, mask, tmp; unsigned int val, mask, tmp;
...@@ -236,17 +246,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy, ...@@ -236,17 +246,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy,
mask = GENMASK(reg->bitend, reg->bitstart); mask = GENMASK(reg->bitend, reg->bitstart);
val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); 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) const struct usb2phy_reg *reg)
{ {
int ret; int ret;
unsigned int tmp, orig; unsigned int tmp, orig;
unsigned int mask = GENMASK(reg->bitend, reg->bitstart); 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) if (ret)
return false; return false;
...@@ -258,11 +268,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) ...@@ -258,11 +268,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
{ {
struct rockchip_usb2phy *rphy = struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw); container_of(hw, struct rockchip_usb2phy, clk480m_hw);
struct regmap *base = get_reg_base(rphy);
int ret; int ret;
/* turn on 480m clk output if it is off */ /* turn on 480m clk output if it is off */
if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) { if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true); ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
if (ret) if (ret)
return ret; return ret;
...@@ -277,17 +288,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw) ...@@ -277,17 +288,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
{ {
struct rockchip_usb2phy *rphy = struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw); container_of(hw, struct rockchip_usb2phy, clk480m_hw);
struct regmap *base = get_reg_base(rphy);
/* turn off 480m clk output */ /* 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) static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
{ {
struct rockchip_usb2phy *rphy = struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw); 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 static unsigned long
...@@ -409,13 +422,13 @@ static int rockchip_usb2phy_init(struct phy *phy) ...@@ -409,13 +422,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
if (rport->mode != USB_DR_MODE_HOST && if (rport->mode != USB_DR_MODE_HOST &&
rport->mode != USB_DR_MODE_UNKNOWN) { rport->mode != USB_DR_MODE_UNKNOWN) {
/* clear bvalid status and enable bvalid detect irq */ /* clear bvalid status and enable bvalid detect irq */
ret = property_enable(rphy, ret = property_enable(rphy->grf,
&rport->port_cfg->bvalid_det_clr, &rport->port_cfg->bvalid_det_clr,
true); true);
if (ret) if (ret)
goto out; goto out;
ret = property_enable(rphy, ret = property_enable(rphy->grf,
&rport->port_cfg->bvalid_det_en, &rport->port_cfg->bvalid_det_en,
true); true);
if (ret) if (ret)
...@@ -429,11 +442,13 @@ static int rockchip_usb2phy_init(struct phy *phy) ...@@ -429,11 +442,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
} }
} else if (rport->port_id == USB2PHY_PORT_HOST) { } else if (rport->port_id == USB2PHY_PORT_HOST) {
/* clear linestate and enable linestate detect irq */ /* 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) if (ret)
goto out; 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) if (ret)
goto out; goto out;
...@@ -449,6 +464,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy) ...@@ -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_port *rport = phy_get_drvdata(phy);
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
int ret; int ret;
dev_dbg(&rport->phy->dev, "port power on\n"); dev_dbg(&rport->phy->dev, "port power on\n");
...@@ -460,7 +476,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy) ...@@ -460,7 +476,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
if (ret) if (ret)
return 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) if (ret)
return ret; return ret;
...@@ -475,6 +491,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy) ...@@ -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_port *rport = phy_get_drvdata(phy);
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
int ret; int ret;
dev_dbg(&rport->phy->dev, "port power off\n"); dev_dbg(&rport->phy->dev, "port power off\n");
...@@ -482,7 +499,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy) ...@@ -482,7 +499,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
if (rport->suspended) if (rport->suspended)
return 0; return 0;
ret = property_enable(rphy, &rport->port_cfg->phy_sus, true); ret = property_enable(base, &rport->port_cfg->phy_sus, true);
if (ret) if (ret)
return ret; return ret;
...@@ -526,11 +543,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) ...@@ -526,11 +543,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
bool vbus_attach, sch_work, notify_charger; bool vbus_attach, sch_work, notify_charger;
if (rport->utmi_avalid) if (rport->utmi_avalid)
vbus_attach = vbus_attach = property_enabled(rphy->grf,
property_enabled(rphy, &rport->port_cfg->utmi_avalid); &rport->port_cfg->utmi_avalid);
else else
vbus_attach = vbus_attach = property_enabled(rphy->grf,
property_enabled(rphy, &rport->port_cfg->utmi_bvalid); &rport->port_cfg->utmi_bvalid);
sch_work = false; sch_work = false;
notify_charger = false; notify_charger = false;
...@@ -650,22 +667,28 @@ static const char *chg_to_string(enum power_supply_type chg_type) ...@@ -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, static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
bool en) bool en)
{ {
property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); struct regmap *base = get_reg_base(rphy);
property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
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, static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
bool en) bool en)
{ {
property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en); struct regmap *base = get_reg_base(rphy);
property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
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, static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
bool en) bool en)
{ {
property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en); struct regmap *base = get_reg_base(rphy);
property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
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) #define CHG_DCD_POLL_TIME (100 * HZ / 1000)
...@@ -677,6 +700,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -677,6 +700,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
struct rockchip_usb2phy_port *rport = struct rockchip_usb2phy_port *rport =
container_of(work, struct rockchip_usb2phy_port, chg_work.work); container_of(work, struct rockchip_usb2phy_port, chg_work.work);
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
bool is_dcd, tmout, vout; bool is_dcd, tmout, vout;
unsigned long delay; unsigned long delay;
...@@ -687,7 +711,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -687,7 +711,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
if (!rport->suspended) if (!rport->suspended)
rockchip_usb2phy_power_off(rport->phy); rockchip_usb2phy_power_off(rport->phy);
/* put the controller in non-driving mode */ /* 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 */ /* Start DCD processing stage 1 */
rockchip_chg_enable_dcd(rphy, true); rockchip_chg_enable_dcd(rphy, true);
rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
...@@ -696,7 +720,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -696,7 +720,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
break; break;
case USB_CHG_STATE_WAIT_FOR_DCD: case USB_CHG_STATE_WAIT_FOR_DCD:
/* get data contact detection status */ /* 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; tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
/* stage 2 */ /* stage 2 */
if (is_dcd || tmout) { if (is_dcd || tmout) {
...@@ -713,7 +738,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -713,7 +738,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
} }
break; break;
case USB_CHG_STATE_DCD_DONE: 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); rockchip_chg_enable_primary_det(rphy, false);
if (vout) { if (vout) {
/* Voltage Source on DM, Probe on DP */ /* Voltage Source on DM, Probe on DP */
...@@ -734,7 +760,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -734,7 +760,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
} }
break; break;
case USB_CHG_STATE_PRIMARY_DONE: 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 */ /* Turn off voltage source */
rockchip_chg_enable_secondary_det(rphy, false); rockchip_chg_enable_secondary_det(rphy, false);
if (vout) if (vout)
...@@ -748,7 +775,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -748,7 +775,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
/* fall through */ /* fall through */
case USB_CHG_STATE_DETECTED: case USB_CHG_STATE_DETECTED:
/* put the controller in normal mode */ /* 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); rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
dev_info(&rport->phy->dev, "charger = %s\n", dev_info(&rport->phy->dev, "charger = %s\n",
chg_to_string(rphy->chg_type)); chg_to_string(rphy->chg_type));
...@@ -790,8 +817,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work) ...@@ -790,8 +817,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
if (ret < 0) if (ret < 0)
goto next_schedule; goto next_schedule;
ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
&uhd);
if (ret < 0) if (ret < 0)
goto next_schedule; goto next_schedule;
...@@ -845,8 +871,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work) ...@@ -845,8 +871,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
* activate the linestate detection to get the next device * activate the linestate detection to get the next device
* plug-in irq. * plug-in irq.
*/ */
property_enable(rphy, &rport->port_cfg->ls_det_clr, true); property_enable(rphy->grf, &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_en, true);
/* /*
* we don't need to rearm the delayed work when the phy port * 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) ...@@ -869,14 +895,14 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
struct rockchip_usb2phy_port *rport = data; struct rockchip_usb2phy_port *rport = data;
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); 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; return IRQ_NONE;
mutex_lock(&rport->mutex); mutex_lock(&rport->mutex);
/* disable linestate detect irq and clear its status */ /* disable linestate detect irq and clear its status */
property_enable(rphy, &rport->port_cfg->ls_det_en, false); property_enable(rphy->grf, &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_clr, true);
mutex_unlock(&rport->mutex); mutex_unlock(&rport->mutex);
...@@ -896,13 +922,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data) ...@@ -896,13 +922,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
struct rockchip_usb2phy_port *rport = data; struct rockchip_usb2phy_port *rport = data;
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); 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; return IRQ_NONE;
mutex_lock(&rport->mutex); mutex_lock(&rport->mutex);
/* clear bvalid detect irq pending status */ /* 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); mutex_unlock(&rport->mutex);
...@@ -911,6 +937,17 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data) ...@@ -911,6 +937,17 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
return IRQ_HANDLED; 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, static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
struct rockchip_usb2phy_port *rport, struct rockchip_usb2phy_port *rport,
struct device_node *child_np) struct device_node *child_np)
...@@ -987,20 +1024,43 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, ...@@ -987,20 +1024,43 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
rport->utmi_avalid = rport->utmi_avalid =
of_property_read_bool(child_np, "rockchip,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) { * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate
dev_err(rphy->dev, "no vbus valid irq provided\n"); * interrupts muxed together, so probe the otg-mux interrupt first,
ret = rport->bvalid_irq; * if not found, then look for the regular interrupts one by one.
goto out; */
} 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, ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq,
rockchip_usb2phy_bvalid_irq, NULL,
IRQF_ONESHOT, rockchip_usb2phy_bvalid_irq,
"rockchip_usb2phy_bvalid", rport); IRQF_ONESHOT,
if (ret) { "rockchip_usb2phy_bvalid",
dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n"); rport);
goto out; if (ret) {
dev_err(rphy->dev,
"failed to request otg-bvalid irq handle\n");
goto out;
}
} }
if (!IS_ERR(rphy->edev)) { if (!IS_ERR(rphy->edev)) {
...@@ -1045,6 +1105,16 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) ...@@ -1045,6 +1105,16 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (IS_ERR(rphy->grf)) if (IS_ERR(rphy->grf))
return PTR_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)) { if (of_property_read_u32(np, "reg", &reg)) {
dev_err(dev, "the reg property is not assigned in %s node\n", dev_err(dev, "the reg property is not assigned in %s node\n",
np->name); np->name);
...@@ -1327,11 +1397,54 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { ...@@ -1327,11 +1397,54 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
{ /* sentinel */ } { /* 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[] = { static const struct of_device_id rockchip_usb2phy_dt_match[] = {
{ .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs }, { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_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); MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);
......
...@@ -622,12 +622,11 @@ static int tcphy_get_mode(struct rockchip_typec_phy *tcphy) ...@@ -622,12 +622,11 @@ static int tcphy_get_mode(struct rockchip_typec_phy *tcphy)
struct extcon_dev *edev = tcphy->extcon; struct extcon_dev *edev = tcphy->extcon;
union extcon_property_value property; union extcon_property_value property;
unsigned int id; unsigned int id;
bool dfp, ufp, dp; bool ufp, dp;
u8 mode; u8 mode;
int ret; int ret;
ufp = extcon_get_state(edev, EXTCON_USB); ufp = extcon_get_state(edev, EXTCON_USB);
dfp = extcon_get_state(edev, EXTCON_USB_HOST);
dp = extcon_get_state(edev, EXTCON_DISP_DP); dp = extcon_get_state(edev, EXTCON_DISP_DP);
mode = MODE_DFP_USB; mode = MODE_DFP_USB;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -78,7 +79,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) ...@@ -78,7 +79,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
{ {
struct exynos_dp_video_phy *state; struct exynos_dp_video_phy *state;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct of_device_id *match;
struct phy_provider *phy_provider; struct phy_provider *phy_provider;
struct phy *phy; struct phy *phy;
...@@ -93,8 +93,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) ...@@ -93,8 +93,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
return PTR_ERR(state->regs); return PTR_ERR(state->regs);
} }
match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node); state->drvdata = of_device_get_match_data(dev);
state->drvdata = match->data;
phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops); phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops);
if (IS_ERR(phy)) { if (IS_ERR(phy)) {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -662,7 +663,6 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) ...@@ -662,7 +663,6 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
struct exynos5_usbdrd_phy *phy_drd; struct exynos5_usbdrd_phy *phy_drd;
struct phy_provider *phy_provider; struct phy_provider *phy_provider;
struct resource *res; struct resource *res;
const struct of_device_id *match;
const struct exynos5_usbdrd_phy_drvdata *drv_data; const struct exynos5_usbdrd_phy_drvdata *drv_data;
struct regmap *reg_pmu; struct regmap *reg_pmu;
u32 pmu_offset; u32 pmu_offset;
...@@ -681,9 +681,10 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) ...@@ -681,9 +681,10 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
if (IS_ERR(phy_drd->reg_phy)) if (IS_ERR(phy_drd->reg_phy))
return PTR_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; phy_drd->drv_data = drv_data;
ret = exynos5_usbdrd_phy_clk_handle(phy_drd); ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -142,7 +143,6 @@ MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match); ...@@ -142,7 +143,6 @@ MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
static int samsung_usb2_phy_probe(struct platform_device *pdev) static int samsung_usb2_phy_probe(struct platform_device *pdev)
{ {
const struct of_device_id *match;
const struct samsung_usb2_phy_config *cfg; const struct samsung_usb2_phy_config *cfg;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct phy_provider *phy_provider; struct phy_provider *phy_provider;
...@@ -155,12 +155,9 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev) ...@@ -155,12 +155,9 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node); cfg = of_device_get_match_data(dev);
if (!match) { if (!cfg)
dev_err(dev, "of_match_node() failed\n");
return -EINVAL; return -EINVAL;
}
cfg = match->data;
drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) + drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
cfg->num_phys * sizeof(struct samsung_usb2_phy_instance), cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),
......
...@@ -118,12 +118,12 @@ static struct pipe3_dpll_map dpll_map_usb[] = { ...@@ -118,12 +118,12 @@ static struct pipe3_dpll_map dpll_map_usb[] = {
}; };
static struct pipe3_dpll_map dpll_map_sata[] = { static struct pipe3_dpll_map dpll_map_sata[] = {
{12000000, {1000, 7, 4, 6, 0} }, /* 12 MHz */ {12000000, {625, 4, 4, 6, 0} }, /* 12 MHz */
{16800000, {714, 7, 4, 6, 0} }, /* 16.8 MHz */ {16800000, {625, 6, 4, 7, 0} }, /* 16.8 MHz */
{19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */ {19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */
{20000000, {600, 7, 4, 6, 0} }, /* 20 MHz */ {20000000, {750, 9, 4, 6, 0} }, /* 20 MHz */
{26000000, {461, 7, 4, 6, 0} }, /* 26 MHz */ {26000000, {750, 12, 4, 6, 0} }, /* 26 MHz */
{38400000, {312, 7, 4, 6, 0} }, /* 38.4 MHz */ {38400000, {625, 15, 4, 6, 0} }, /* 38.4 MHz */
{ }, /* Terminator */ { }, /* Terminator */
}; };
......
...@@ -185,7 +185,7 @@ struct twl4030_usb { ...@@ -185,7 +185,7 @@ struct twl4030_usb {
static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl, static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
u8 module, u8 data, u8 address) u8 module, u8 data, u8 address)
{ {
u8 check; u8 check = 0xFF;
if ((twl_i2c_write_u8(module, data, address) >= 0) && if ((twl_i2c_write_u8(module, data, address) >= 0) &&
(twl_i2c_read_u8(module, &check, address) >= 0) && (twl_i2c_read_u8(module, &check, address) >= 0) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment