diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-11-28 02:44:54 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-11-28 02:44:54 -0500 |
commit | cdefb95bfc0de9a60b91b748f15e65eddb4f116e (patch) | |
tree | 0d5ae76297cbe07a709cf773155ec982e16ac855 | |
parent | 0edbf9e55295585bbe9df61b646ca5bf80a8e1eb (diff) | |
parent | 5e253dfbdbea97ab3f462cdd75a6d1cae2292901 (diff) |
Merge tag 'phy-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next
Kishon writes:
phy: for 4.10
Merge contains:
*) Add new usb2 phy driver for Meson8b and GXBB
*) Remove phy drivers added for miphy365 and STiH415/6 (as support for
these SoCs are removed from the kernel)
*) Add a sysfs entry to facilitate usb role swap in rcar SoC
*) Add support for otg port in rk3399
*) misc fixes in various phy drivers and cleanups
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
23 files changed, 1042 insertions, 924 deletions
diff --git a/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2 b/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2 new file mode 100644 index 000000000000..6212697bbf6f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2 | |||
@@ -0,0 +1,15 @@ | |||
1 | What: /sys/devices/platform/<phy-name>/role | ||
2 | Date: October 2016 | ||
3 | KernelVersion: 4.10 | ||
4 | Contact: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> | ||
5 | Description: | ||
6 | This file can be read and write. | ||
7 | The file can show/change the phy mode for role swap of usb. | ||
8 | |||
9 | Write the following strings to change the mode: | ||
10 | "host" - switching mode from peripheral to host. | ||
11 | "peripheral" - switching mode from host to peripheral. | ||
12 | |||
13 | Read the file, then it shows the following strings: | ||
14 | "host" - The mode is host now. | ||
15 | "peripheral" - The mode is peripheral now. | ||
diff --git a/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt b/Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt index 9da5ea234154..5fa73b9d20f5 100644 --- a/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt +++ b/Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt | |||
@@ -1,4 +1,4 @@ | |||
1 | * Amlogic USB2 PHY | 1 | * Amlogic Meson8b and GXBB USB2 PHY |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: Depending on the platform this should be one of: | 4 | - compatible: Depending on the platform this should be one of: |
@@ -16,10 +16,10 @@ Optional properties: | |||
16 | 16 | ||
17 | Example: | 17 | Example: |
18 | 18 | ||
19 | usb0_phy: usb_phy@0 { | 19 | usb0_phy: usb-phy@c0000000 { |
20 | compatible = "amlogic,meson-gxbb-usb2-phy"; | 20 | compatible = "amlogic,meson-gxbb-usb2-phy"; |
21 | #phy-cells = <0>; | 21 | #phy-cells = <0>; |
22 | reg = <0x0 0x0 0x0 0x20>; | 22 | reg = <0x0 0xc0000000 0x0 0x20>; |
23 | resets = <&reset RESET_USB_OTG>; | 23 | resets = <&reset RESET_USB_OTG>; |
24 | clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>; | 24 | clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>; |
25 | clock-names = "usb_general", "usb"; | 25 | clock-names = "usb_general", "usb"; |
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index fe00f9134d51..e8eb7f225a88 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -129,16 +129,6 @@ config PHY_MIPHY28LP | |||
129 | Enable this to support the miphy transceiver (for SATA/PCIE/USB3) | 129 | Enable this to support the miphy transceiver (for SATA/PCIE/USB3) |
130 | that is part of STMicroelectronics STiH407 SoC. | 130 | that is part of STMicroelectronics STiH407 SoC. |
131 | 131 | ||
132 | config PHY_MIPHY365X | ||
133 | tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series" | ||
134 | depends on ARCH_STI | ||
135 | depends on HAS_IOMEM | ||
136 | depends on OF | ||
137 | select GENERIC_PHY | ||
138 | help | ||
139 | Enable this to support the miphy transceiver (for SATA/PCIE) | ||
140 | that is part of STMicroelectronics STiH41x SoC series. | ||
141 | |||
142 | config PHY_RCAR_GEN2 | 132 | config PHY_RCAR_GEN2 |
143 | tristate "Renesas R-Car generation 2 USB PHY driver" | 133 | tristate "Renesas R-Car generation 2 USB PHY driver" |
144 | depends on ARCH_RENESAS | 134 | depends on ARCH_RENESAS |
@@ -373,7 +363,9 @@ config PHY_ROCKCHIP_INNO_USB2 | |||
373 | tristate "Rockchip INNO USB2PHY Driver" | 363 | tristate "Rockchip INNO USB2PHY Driver" |
374 | depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF | 364 | depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF |
375 | depends on COMMON_CLK | 365 | depends on COMMON_CLK |
366 | depends on USB_SUPPORT | ||
376 | select GENERIC_PHY | 367 | select GENERIC_PHY |
368 | select USB_COMMON | ||
377 | help | 369 | help |
378 | Support for Rockchip USB2.0 PHY with Innosilicon IP block. | 370 | Support for Rockchip USB2.0 PHY with Innosilicon IP block. |
379 | 371 | ||
@@ -438,14 +430,6 @@ config PHY_STIH407_USB | |||
438 | Enable this support to enable the picoPHY device used by USB2 | 430 | Enable this support to enable the picoPHY device used by USB2 |
439 | and USB3 controllers on STMicroelectronics STiH407 SoC families. | 431 | and USB3 controllers on STMicroelectronics STiH407 SoC families. |
440 | 432 | ||
441 | config PHY_STIH41X_USB | ||
442 | tristate "STMicroelectronics USB2 PHY driver for STiH41x series" | ||
443 | depends on ARCH_STI | ||
444 | select GENERIC_PHY | ||
445 | help | ||
446 | Enable this to support the USB transceiver that is part of | ||
447 | STMicroelectronics STiH41x SoC series. | ||
448 | |||
449 | config PHY_QCOM_UFS | 433 | config PHY_QCOM_UFS |
450 | tristate "Qualcomm UFS PHY driver" | 434 | tristate "Qualcomm UFS PHY driver" |
451 | depends on OF && ARCH_QCOM | 435 | depends on OF && ARCH_QCOM |
@@ -489,4 +473,17 @@ config PHY_NS2_PCIE | |||
489 | help | 473 | help |
490 | Enable this to support the Broadcom Northstar2 PCIe PHY. | 474 | Enable this to support the Broadcom Northstar2 PCIe PHY. |
491 | If unsure, say N. | 475 | If unsure, say N. |
476 | |||
477 | config PHY_MESON8B_USB2 | ||
478 | tristate "Meson8b and GXBB USB2 PHY driver" | ||
479 | default ARCH_MESON | ||
480 | depends on OF && (ARCH_MESON || COMPILE_TEST) | ||
481 | depends on USB_SUPPORT | ||
482 | select USB_COMMON | ||
483 | select GENERIC_PHY | ||
484 | help | ||
485 | Enable this to support the Meson USB2 PHYs found in Meson8b | ||
486 | and GXBB SoCs. | ||
487 | If unsure, say N. | ||
488 | |||
492 | endmenu | 489 | endmenu |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index a534cf5be07d..65eb2f436a41 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -18,7 +18,6 @@ obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o | |||
18 | obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o | 18 | obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o |
19 | obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o | 19 | obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o |
20 | obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o | 20 | obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o |
21 | obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o | ||
22 | obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o | 21 | obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o |
23 | obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o | 22 | obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o |
24 | obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o | 23 | obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o |
@@ -50,7 +49,6 @@ obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o | |||
50 | obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o | 49 | obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o |
51 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o | 50 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o |
52 | obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o | 51 | obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o |
53 | obj-$(CONFIG_PHY_STIH41X_USB) += phy-stih41x-usb.o | ||
54 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o | 52 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o |
55 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o | 53 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o |
56 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o | 54 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o |
@@ -60,3 +58,4 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o | |||
60 | obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o | 58 | obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o |
61 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ | 59 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ |
62 | obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o | 60 | obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o |
61 | obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o | ||
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c index f84a33a1bdd9..2c7a57f2d595 100644 --- a/drivers/phy/phy-berlin-sata.c +++ b/drivers/phy/phy-berlin-sata.c | |||
@@ -85,7 +85,6 @@ static int phy_berlin_sata_power_on(struct phy *phy) | |||
85 | struct phy_berlin_desc *desc = phy_get_drvdata(phy); | 85 | struct phy_berlin_desc *desc = phy_get_drvdata(phy); |
86 | struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent); | 86 | struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent); |
87 | void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80); | 87 | void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80); |
88 | int ret = 0; | ||
89 | u32 regval; | 88 | u32 regval; |
90 | 89 | ||
91 | clk_prepare_enable(priv->clk); | 90 | clk_prepare_enable(priv->clk); |
@@ -130,7 +129,7 @@ static int phy_berlin_sata_power_on(struct phy *phy) | |||
130 | 129 | ||
131 | clk_disable_unprepare(priv->clk); | 130 | clk_disable_unprepare(priv->clk); |
132 | 131 | ||
133 | return ret; | 132 | return 0; |
134 | } | 133 | } |
135 | 134 | ||
136 | static int phy_berlin_sata_power_off(struct phy *phy) | 135 | static int phy_berlin_sata_power_off(struct phy *phy) |
diff --git a/drivers/phy/phy-brcm-sata.c b/drivers/phy/phy-brcm-sata.c index 8ffc44afdb75..ccbc3d994998 100644 --- a/drivers/phy/phy-brcm-sata.c +++ b/drivers/phy/phy-brcm-sata.c | |||
@@ -140,7 +140,7 @@ static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port) | |||
140 | default: | 140 | default: |
141 | dev_err(priv->dev, "invalid phy version\n"); | 141 | dev_err(priv->dev, "invalid phy version\n"); |
142 | break; | 142 | break; |
143 | }; | 143 | } |
144 | 144 | ||
145 | return priv->phy_base + (port->portnum * size); | 145 | return priv->phy_base + (port->portnum * size); |
146 | } | 146 | } |
@@ -157,7 +157,7 @@ static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port) | |||
157 | default: | 157 | default: |
158 | dev_err(priv->dev, "invalid phy version\n"); | 158 | dev_err(priv->dev, "invalid phy version\n"); |
159 | break; | 159 | break; |
160 | }; | 160 | } |
161 | 161 | ||
162 | return priv->ctrl_base + (port->portnum * size); | 162 | return priv->ctrl_base + (port->portnum * size); |
163 | } | 163 | } |
@@ -365,7 +365,7 @@ static int brcm_sata_phy_init(struct phy *phy) | |||
365 | break; | 365 | break; |
366 | default: | 366 | default: |
367 | rc = -ENODEV; | 367 | rc = -ENODEV; |
368 | }; | 368 | } |
369 | 369 | ||
370 | return rc; | 370 | return rc; |
371 | } | 371 | } |
diff --git a/drivers/phy/phy-da8xx-usb.c b/drivers/phy/phy-da8xx-usb.c index c85fb0b59729..1b82bff6330f 100644 --- a/drivers/phy/phy-da8xx-usb.c +++ b/drivers/phy/phy-da8xx-usb.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/regmap.h> | 24 | #include <linux/regmap.h> |
25 | 25 | ||
26 | #define PHY_INIT_BITS (CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN) | ||
27 | |||
26 | struct da8xx_usb_phy { | 28 | struct da8xx_usb_phy { |
27 | struct phy_provider *phy_provider; | 29 | struct phy_provider *phy_provider; |
28 | struct phy *usb11_phy; | 30 | struct phy *usb11_phy; |
@@ -208,6 +210,9 @@ static int da8xx_usb_phy_probe(struct platform_device *pdev) | |||
208 | dev_warn(dev, "Failed to create usb20 phy lookup\n"); | 210 | dev_warn(dev, "Failed to create usb20 phy lookup\n"); |
209 | } | 211 | } |
210 | 212 | ||
213 | regmap_write_bits(d_phy->regmap, CFGCHIP(2), | ||
214 | PHY_INIT_BITS, PHY_INIT_BITS); | ||
215 | |||
211 | return 0; | 216 | return 0; |
212 | } | 217 | } |
213 | 218 | ||
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index 8b851f718123..6bee04cc4d53 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c | |||
@@ -229,19 +229,6 @@ struct exynos_mipi_video_phy { | |||
229 | spinlock_t slock; | 229 | spinlock_t slock; |
230 | }; | 230 | }; |
231 | 231 | ||
232 | static inline int __is_running(const struct exynos_mipi_phy_desc *data, | ||
233 | struct exynos_mipi_video_phy *state) | ||
234 | { | ||
235 | u32 val; | ||
236 | int ret; | ||
237 | |||
238 | ret = regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val); | ||
239 | if (ret) | ||
240 | return 0; | ||
241 | |||
242 | return val & data->resetn_val; | ||
243 | } | ||
244 | |||
245 | static int __set_phy_state(const struct exynos_mipi_phy_desc *data, | 232 | static int __set_phy_state(const struct exynos_mipi_phy_desc *data, |
246 | struct exynos_mipi_video_phy *state, unsigned int on) | 233 | struct exynos_mipi_video_phy *state, unsigned int on) |
247 | { | 234 | { |
@@ -251,7 +238,7 @@ static int __set_phy_state(const struct exynos_mipi_phy_desc *data, | |||
251 | 238 | ||
252 | /* disable in PMU sysreg */ | 239 | /* disable in PMU sysreg */ |
253 | if (!on && data->coupled_phy_id >= 0 && | 240 | if (!on && data->coupled_phy_id >= 0 && |
254 | !__is_running(state->phys[data->coupled_phy_id].data, state)) { | 241 | state->phys[data->coupled_phy_id].phy->power_count == 0) { |
255 | regmap_read(state->regmaps[data->enable_map], data->enable_reg, | 242 | regmap_read(state->regmaps[data->enable_map], data->enable_reg, |
256 | &val); | 243 | &val); |
257 | val &= ~data->enable_val; | 244 | val &= ~data->enable_val; |
diff --git a/drivers/phy/phy-exynos4210-usb2.c b/drivers/phy/phy-exynos4210-usb2.c index f30bbb0fb3b2..1f50e1004828 100644 --- a/drivers/phy/phy-exynos4210-usb2.c +++ b/drivers/phy/phy-exynos4210-usb2.c | |||
@@ -141,7 +141,7 @@ static void exynos4210_isol(struct samsung_usb2_phy_instance *inst, bool on) | |||
141 | break; | 141 | break; |
142 | default: | 142 | default: |
143 | return; | 143 | return; |
144 | }; | 144 | } |
145 | 145 | ||
146 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); | 146 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); |
147 | } | 147 | } |
@@ -179,7 +179,7 @@ static void exynos4210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | |||
179 | rstbits = EXYNOS_4210_URSTCON_PHY1_P1P2 | | 179 | rstbits = EXYNOS_4210_URSTCON_PHY1_P1P2 | |
180 | EXYNOS_4210_URSTCON_HOST_LINK_P2; | 180 | EXYNOS_4210_URSTCON_HOST_LINK_P2; |
181 | break; | 181 | break; |
182 | }; | 182 | } |
183 | 183 | ||
184 | if (on) { | 184 | if (on) { |
185 | clk = readl(drv->reg_phy + EXYNOS_4210_UPHYCLK); | 185 | clk = readl(drv->reg_phy + EXYNOS_4210_UPHYCLK); |
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c index 765da90a536f..7f27a91acf87 100644 --- a/drivers/phy/phy-exynos4x12-usb2.c +++ b/drivers/phy/phy-exynos4x12-usb2.c | |||
@@ -187,7 +187,7 @@ static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on) | |||
187 | break; | 187 | break; |
188 | default: | 188 | default: |
189 | return; | 189 | return; |
190 | }; | 190 | } |
191 | 191 | ||
192 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); | 192 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); |
193 | } | 193 | } |
@@ -237,7 +237,7 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | |||
237 | rstbits = EXYNOS_4x12_URSTCON_HSIC1 | | 237 | rstbits = EXYNOS_4x12_URSTCON_HSIC1 | |
238 | EXYNOS_4x12_URSTCON_HOST_LINK_P1; | 238 | EXYNOS_4x12_URSTCON_HOST_LINK_P1; |
239 | break; | 239 | break; |
240 | }; | 240 | } |
241 | 241 | ||
242 | if (on) { | 242 | if (on) { |
243 | pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR); | 243 | pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR); |
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c index 2ed1735a076a..aad806272305 100644 --- a/drivers/phy/phy-exynos5250-usb2.c +++ b/drivers/phy/phy-exynos5250-usb2.c | |||
@@ -192,7 +192,7 @@ static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on) | |||
192 | break; | 192 | break; |
193 | default: | 193 | default: |
194 | return; | 194 | return; |
195 | }; | 195 | } |
196 | 196 | ||
197 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); | 197 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); |
198 | } | 198 | } |
diff --git a/drivers/phy/phy-meson8b-usb2.c b/drivers/phy/phy-meson8b-usb2.c new file mode 100644 index 000000000000..33c9f4ba157d --- /dev/null +++ b/drivers/phy/phy-meson8b-usb2.c | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * Meson8b and GXBB USB2 PHY driver | ||
3 | * | ||
4 | * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License | ||
11 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of_device.h> | ||
19 | #include <linux/reset.h> | ||
20 | #include <linux/phy/phy.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/usb/of.h> | ||
23 | |||
24 | #define REG_CONFIG 0x00 | ||
25 | #define REG_CONFIG_CLK_EN BIT(0) | ||
26 | #define REG_CONFIG_CLK_SEL_MASK GENMASK(3, 1) | ||
27 | #define REG_CONFIG_CLK_DIV_MASK GENMASK(10, 4) | ||
28 | #define REG_CONFIG_CLK_32k_ALTSEL BIT(15) | ||
29 | #define REG_CONFIG_TEST_TRIG BIT(31) | ||
30 | |||
31 | #define REG_CTRL 0x04 | ||
32 | #define REG_CTRL_SOFT_PRST BIT(0) | ||
33 | #define REG_CTRL_SOFT_HRESET BIT(1) | ||
34 | #define REG_CTRL_SS_SCALEDOWN_MODE_MASK GENMASK(3, 2) | ||
35 | #define REG_CTRL_CLK_DET_RST BIT(4) | ||
36 | #define REG_CTRL_INTR_SEL BIT(5) | ||
37 | #define REG_CTRL_CLK_DETECTED BIT(8) | ||
38 | #define REG_CTRL_SOF_SENT_RCVD_TGL BIT(9) | ||
39 | #define REG_CTRL_SOF_TOGGLE_OUT BIT(10) | ||
40 | #define REG_CTRL_POWER_ON_RESET BIT(15) | ||
41 | #define REG_CTRL_SLEEPM BIT(16) | ||
42 | #define REG_CTRL_TX_BITSTUFF_ENN_H BIT(17) | ||
43 | #define REG_CTRL_TX_BITSTUFF_ENN BIT(18) | ||
44 | #define REG_CTRL_COMMON_ON BIT(19) | ||
45 | #define REG_CTRL_REF_CLK_SEL_MASK GENMASK(21, 20) | ||
46 | #define REG_CTRL_REF_CLK_SEL_SHIFT 20 | ||
47 | #define REG_CTRL_FSEL_MASK GENMASK(24, 22) | ||
48 | #define REG_CTRL_FSEL_SHIFT 22 | ||
49 | #define REG_CTRL_PORT_RESET BIT(25) | ||
50 | #define REG_CTRL_THREAD_ID_MASK GENMASK(31, 26) | ||
51 | |||
52 | #define REG_ENDP_INTR 0x08 | ||
53 | |||
54 | /* bits [31:26], [24:21] and [15:3] seem to be read-only */ | ||
55 | #define REG_ADP_BC 0x0c | ||
56 | #define REG_ADP_BC_VBUS_VLD_EXT_SEL BIT(0) | ||
57 | #define REG_ADP_BC_VBUS_VLD_EXT BIT(1) | ||
58 | #define REG_ADP_BC_OTG_DISABLE BIT(2) | ||
59 | #define REG_ADP_BC_ID_PULLUP BIT(3) | ||
60 | #define REG_ADP_BC_DRV_VBUS BIT(4) | ||
61 | #define REG_ADP_BC_ADP_PRB_EN BIT(5) | ||
62 | #define REG_ADP_BC_ADP_DISCHARGE BIT(6) | ||
63 | #define REG_ADP_BC_ADP_CHARGE BIT(7) | ||
64 | #define REG_ADP_BC_SESS_END BIT(8) | ||
65 | #define REG_ADP_BC_DEVICE_SESS_VLD BIT(9) | ||
66 | #define REG_ADP_BC_B_VALID BIT(10) | ||
67 | #define REG_ADP_BC_A_VALID BIT(11) | ||
68 | #define REG_ADP_BC_ID_DIG BIT(12) | ||
69 | #define REG_ADP_BC_VBUS_VALID BIT(13) | ||
70 | #define REG_ADP_BC_ADP_PROBE BIT(14) | ||
71 | #define REG_ADP_BC_ADP_SENSE BIT(15) | ||
72 | #define REG_ADP_BC_ACA_ENABLE BIT(16) | ||
73 | #define REG_ADP_BC_DCD_ENABLE BIT(17) | ||
74 | #define REG_ADP_BC_VDAT_DET_EN_B BIT(18) | ||
75 | #define REG_ADP_BC_VDAT_SRC_EN_B BIT(19) | ||
76 | #define REG_ADP_BC_CHARGE_SEL BIT(20) | ||
77 | #define REG_ADP_BC_CHARGE_DETECT BIT(21) | ||
78 | #define REG_ADP_BC_ACA_PIN_RANGE_C BIT(22) | ||
79 | #define REG_ADP_BC_ACA_PIN_RANGE_B BIT(23) | ||
80 | #define REG_ADP_BC_ACA_PIN_RANGE_A BIT(24) | ||
81 | #define REG_ADP_BC_ACA_PIN_GND BIT(25) | ||
82 | #define REG_ADP_BC_ACA_PIN_FLOAT BIT(26) | ||
83 | |||
84 | #define REG_DBG_UART 0x14 | ||
85 | |||
86 | #define REG_TEST 0x18 | ||
87 | #define REG_TEST_DATA_IN_MASK GENMASK(3, 0) | ||
88 | #define REG_TEST_EN_MASK GENMASK(7, 4) | ||
89 | #define REG_TEST_ADDR_MASK GENMASK(11, 8) | ||
90 | #define REG_TEST_DATA_OUT_SEL BIT(12) | ||
91 | #define REG_TEST_CLK BIT(13) | ||
92 | #define REG_TEST_VA_TEST_EN_B_MASK GENMASK(15, 14) | ||
93 | #define REG_TEST_DATA_OUT_MASK GENMASK(19, 16) | ||
94 | #define REG_TEST_DISABLE_ID_PULLUP BIT(20) | ||
95 | |||
96 | #define REG_TUNE 0x1c | ||
97 | #define REG_TUNE_TX_RES_TUNE_MASK GENMASK(1, 0) | ||
98 | #define REG_TUNE_TX_HSXV_TUNE_MASK GENMASK(3, 2) | ||
99 | #define REG_TUNE_TX_VREF_TUNE_MASK GENMASK(7, 4) | ||
100 | #define REG_TUNE_TX_RISE_TUNE_MASK GENMASK(9, 8) | ||
101 | #define REG_TUNE_TX_PREEMP_PULSE_TUNE BIT(10) | ||
102 | #define REG_TUNE_TX_PREEMP_AMP_TUNE_MASK GENMASK(12, 11) | ||
103 | #define REG_TUNE_TX_FSLS_TUNE_MASK GENMASK(16, 13) | ||
104 | #define REG_TUNE_SQRX_TUNE_MASK GENMASK(19, 17) | ||
105 | #define REG_TUNE_OTG_TUNE GENMASK(22, 20) | ||
106 | #define REG_TUNE_COMP_DIS_TUNE GENMASK(25, 23) | ||
107 | #define REG_TUNE_HOST_DM_PULLDOWN BIT(26) | ||
108 | #define REG_TUNE_HOST_DP_PULLDOWN BIT(27) | ||
109 | |||
110 | #define RESET_COMPLETE_TIME 500 | ||
111 | #define ACA_ENABLE_COMPLETE_TIME 50 | ||
112 | |||
113 | struct phy_meson8b_usb2_priv { | ||
114 | void __iomem *regs; | ||
115 | enum usb_dr_mode dr_mode; | ||
116 | struct clk *clk_usb_general; | ||
117 | struct clk *clk_usb; | ||
118 | struct reset_control *reset; | ||
119 | }; | ||
120 | |||
121 | static u32 phy_meson8b_usb2_read(struct phy_meson8b_usb2_priv *phy_priv, | ||
122 | u32 reg) | ||
123 | { | ||
124 | return readl(phy_priv->regs + reg); | ||
125 | } | ||
126 | |||
127 | static void phy_meson8b_usb2_mask_bits(struct phy_meson8b_usb2_priv *phy_priv, | ||
128 | u32 reg, u32 mask, u32 value) | ||
129 | { | ||
130 | u32 data; | ||
131 | |||
132 | data = phy_meson8b_usb2_read(phy_priv, reg); | ||
133 | data &= ~mask; | ||
134 | data |= (value & mask); | ||
135 | |||
136 | writel(data, phy_priv->regs + reg); | ||
137 | } | ||
138 | |||
139 | static int phy_meson8b_usb2_power_on(struct phy *phy) | ||
140 | { | ||
141 | struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy); | ||
142 | int ret; | ||
143 | |||
144 | if (!IS_ERR_OR_NULL(priv->reset)) { | ||
145 | ret = reset_control_reset(priv->reset); | ||
146 | if (ret) { | ||
147 | dev_err(&phy->dev, "Failed to trigger USB reset\n"); | ||
148 | return ret; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | ret = clk_prepare_enable(priv->clk_usb_general); | ||
153 | if (ret) { | ||
154 | dev_err(&phy->dev, "Failed to enable USB general clock\n"); | ||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | ret = clk_prepare_enable(priv->clk_usb); | ||
159 | if (ret) { | ||
160 | dev_err(&phy->dev, "Failed to enable USB DDR clock\n"); | ||
161 | clk_disable_unprepare(priv->clk_usb_general); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | phy_meson8b_usb2_mask_bits(priv, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL, | ||
166 | REG_CONFIG_CLK_32k_ALTSEL); | ||
167 | |||
168 | phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK, | ||
169 | 0x2 << REG_CTRL_REF_CLK_SEL_SHIFT); | ||
170 | |||
171 | phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_FSEL_MASK, | ||
172 | 0x5 << REG_CTRL_FSEL_SHIFT); | ||
173 | |||
174 | /* reset the PHY */ | ||
175 | phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET, | ||
176 | REG_CTRL_POWER_ON_RESET); | ||
177 | udelay(RESET_COMPLETE_TIME); | ||
178 | phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0); | ||
179 | udelay(RESET_COMPLETE_TIME); | ||
180 | |||
181 | phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT, | ||
182 | REG_CTRL_SOF_TOGGLE_OUT); | ||
183 | |||
184 | if (priv->dr_mode == USB_DR_MODE_HOST) { | ||
185 | phy_meson8b_usb2_mask_bits(priv, REG_ADP_BC, | ||
186 | REG_ADP_BC_ACA_ENABLE, | ||
187 | REG_ADP_BC_ACA_ENABLE); | ||
188 | |||
189 | udelay(ACA_ENABLE_COMPLETE_TIME); | ||
190 | |||
191 | if (phy_meson8b_usb2_read(priv, REG_ADP_BC) & | ||
192 | REG_ADP_BC_ACA_PIN_FLOAT) { | ||
193 | dev_warn(&phy->dev, "USB ID detect failed!\n"); | ||
194 | clk_disable_unprepare(priv->clk_usb); | ||
195 | clk_disable_unprepare(priv->clk_usb_general); | ||
196 | return -EINVAL; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int phy_meson8b_usb2_power_off(struct phy *phy) | ||
204 | { | ||
205 | struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy); | ||
206 | |||
207 | clk_disable_unprepare(priv->clk_usb); | ||
208 | clk_disable_unprepare(priv->clk_usb_general); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static const struct phy_ops phy_meson8b_usb2_ops = { | ||
214 | .power_on = phy_meson8b_usb2_power_on, | ||
215 | .power_off = phy_meson8b_usb2_power_off, | ||
216 | .owner = THIS_MODULE, | ||
217 | }; | ||
218 | |||
219 | static int phy_meson8b_usb2_probe(struct platform_device *pdev) | ||
220 | { | ||
221 | struct phy_meson8b_usb2_priv *priv; | ||
222 | struct resource *res; | ||
223 | struct phy *phy; | ||
224 | struct phy_provider *phy_provider; | ||
225 | |||
226 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
227 | if (!priv) | ||
228 | return -ENOMEM; | ||
229 | |||
230 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
231 | priv->regs = devm_ioremap_resource(&pdev->dev, res); | ||
232 | if (IS_ERR(priv->regs)) | ||
233 | return PTR_ERR(priv->regs); | ||
234 | |||
235 | priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general"); | ||
236 | if (IS_ERR(priv->clk_usb_general)) | ||
237 | return PTR_ERR(priv->clk_usb_general); | ||
238 | |||
239 | priv->clk_usb = devm_clk_get(&pdev->dev, "usb"); | ||
240 | if (IS_ERR(priv->clk_usb)) | ||
241 | return PTR_ERR(priv->clk_usb); | ||
242 | |||
243 | priv->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL); | ||
244 | if (PTR_ERR(priv->reset) == -EPROBE_DEFER) | ||
245 | return PTR_ERR(priv->reset); | ||
246 | |||
247 | priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1); | ||
248 | if (priv->dr_mode == USB_DR_MODE_UNKNOWN) { | ||
249 | dev_err(&pdev->dev, | ||
250 | "missing dual role configuration of the controller\n"); | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops); | ||
255 | if (IS_ERR(phy)) { | ||
256 | dev_err(&pdev->dev, "failed to create PHY\n"); | ||
257 | return PTR_ERR(phy); | ||
258 | } | ||
259 | |||
260 | phy_set_drvdata(phy, priv); | ||
261 | |||
262 | phy_provider = | ||
263 | devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); | ||
264 | |||
265 | return PTR_ERR_OR_ZERO(phy_provider); | ||
266 | } | ||
267 | |||
268 | static const struct of_device_id phy_meson8b_usb2_of_match[] = { | ||
269 | { .compatible = "amlogic,meson8b-usb2-phy", }, | ||
270 | { .compatible = "amlogic,meson-gxbb-usb2-phy", }, | ||
271 | { }, | ||
272 | }; | ||
273 | MODULE_DEVICE_TABLE(of, phy_meson8b_usb2_of_match); | ||
274 | |||
275 | static struct platform_driver phy_meson8b_usb2_driver = { | ||
276 | .probe = phy_meson8b_usb2_probe, | ||
277 | .driver = { | ||
278 | .name = "phy-meson-usb2", | ||
279 | .of_match_table = phy_meson8b_usb2_of_match, | ||
280 | }, | ||
281 | }; | ||
282 | module_platform_driver(phy_meson8b_usb2_driver); | ||
283 | |||
284 | MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); | ||
285 | MODULE_DESCRIPTION("Meson8b and GXBB USB2 PHY driver"); | ||
286 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c deleted file mode 100644 index e661f3b36eaa..000000000000 --- a/drivers/phy/phy-miphy365x.c +++ /dev/null | |||
@@ -1,625 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics – All Rights Reserved | ||
3 | * | ||
4 | * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416). | ||
5 | * | ||
6 | * Authors: Alexandre Torgue <alexandre.torgue@st.com> | ||
7 | * Lee Jones <lee.jones@linaro.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2, as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_platform.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/phy/phy.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/mfd/syscon.h> | ||
26 | #include <linux/regmap.h> | ||
27 | |||
28 | #include <dt-bindings/phy/phy.h> | ||
29 | |||
30 | #define HFC_TIMEOUT 100 | ||
31 | |||
32 | #define SYSCFG_SELECT_SATA_MASK BIT(1) | ||
33 | #define SYSCFG_SELECT_SATA_POS 1 | ||
34 | |||
35 | /* MiPHY365x register definitions */ | ||
36 | #define RESET_REG 0x00 | ||
37 | #define RST_PLL BIT(1) | ||
38 | #define RST_PLL_CAL BIT(2) | ||
39 | #define RST_RX BIT(4) | ||
40 | #define RST_MACRO BIT(7) | ||
41 | |||
42 | #define STATUS_REG 0x01 | ||
43 | #define IDLL_RDY BIT(0) | ||
44 | #define PLL_RDY BIT(1) | ||
45 | #define DES_BIT_LOCK BIT(2) | ||
46 | #define DES_SYMBOL_LOCK BIT(3) | ||
47 | |||
48 | #define CTRL_REG 0x02 | ||
49 | #define TERM_EN BIT(0) | ||
50 | #define PCI_EN BIT(2) | ||
51 | #define DES_BIT_LOCK_EN BIT(3) | ||
52 | #define TX_POL BIT(5) | ||
53 | |||
54 | #define INT_CTRL_REG 0x03 | ||
55 | |||
56 | #define BOUNDARY1_REG 0x10 | ||
57 | #define SPDSEL_SEL BIT(0) | ||
58 | |||
59 | #define BOUNDARY3_REG 0x12 | ||
60 | #define TX_SPDSEL_GEN1_VAL 0 | ||
61 | #define TX_SPDSEL_GEN2_VAL 0x01 | ||
62 | #define TX_SPDSEL_GEN3_VAL 0x02 | ||
63 | #define RX_SPDSEL_GEN1_VAL 0 | ||
64 | #define RX_SPDSEL_GEN2_VAL (0x01 << 3) | ||
65 | #define RX_SPDSEL_GEN3_VAL (0x02 << 3) | ||
66 | |||
67 | #define PCIE_REG 0x16 | ||
68 | |||
69 | #define BUF_SEL_REG 0x20 | ||
70 | #define CONF_GEN_SEL_GEN3 0x02 | ||
71 | #define CONF_GEN_SEL_GEN2 0x01 | ||
72 | #define PD_VDDTFILTER BIT(4) | ||
73 | |||
74 | #define TXBUF1_REG 0x21 | ||
75 | #define SWING_VAL 0x04 | ||
76 | #define SWING_VAL_GEN1 0x03 | ||
77 | #define PREEMPH_VAL (0x3 << 5) | ||
78 | |||
79 | #define TXBUF2_REG 0x22 | ||
80 | #define TXSLEW_VAL 0x2 | ||
81 | #define TXSLEW_VAL_GEN1 0x4 | ||
82 | |||
83 | #define RXBUF_OFFSET_CTRL_REG 0x23 | ||
84 | |||
85 | #define RXBUF_REG 0x25 | ||
86 | #define SDTHRES_VAL 0x01 | ||
87 | #define EQ_ON3 (0x03 << 4) | ||
88 | #define EQ_ON1 (0x01 << 4) | ||
89 | |||
90 | #define COMP_CTRL1_REG 0x40 | ||
91 | #define START_COMSR BIT(0) | ||
92 | #define START_COMZC BIT(1) | ||
93 | #define COMSR_DONE BIT(2) | ||
94 | #define COMZC_DONE BIT(3) | ||
95 | #define COMP_AUTO_LOAD BIT(4) | ||
96 | |||
97 | #define COMP_CTRL2_REG 0x41 | ||
98 | #define COMP_2MHZ_RAT_GEN1 0x1e | ||
99 | #define COMP_2MHZ_RAT 0xf | ||
100 | |||
101 | #define COMP_CTRL3_REG 0x42 | ||
102 | #define COMSR_COMP_REF 0x33 | ||
103 | |||
104 | #define COMP_IDLL_REG 0x47 | ||
105 | #define COMZC_IDLL 0x2a | ||
106 | |||
107 | #define PLL_CTRL1_REG 0x50 | ||
108 | #define PLL_START_CAL BIT(0) | ||
109 | #define BUF_EN BIT(2) | ||
110 | #define SYNCHRO_TX BIT(3) | ||
111 | #define SSC_EN BIT(6) | ||
112 | #define CONFIG_PLL BIT(7) | ||
113 | |||
114 | #define PLL_CTRL2_REG 0x51 | ||
115 | #define BYPASS_PLL_CAL BIT(1) | ||
116 | |||
117 | #define PLL_RAT_REG 0x52 | ||
118 | |||
119 | #define PLL_SSC_STEP_MSB_REG 0x56 | ||
120 | #define PLL_SSC_STEP_MSB_VAL 0x03 | ||
121 | |||
122 | #define PLL_SSC_STEP_LSB_REG 0x57 | ||
123 | #define PLL_SSC_STEP_LSB_VAL 0x63 | ||
124 | |||
125 | #define PLL_SSC_PER_MSB_REG 0x58 | ||
126 | #define PLL_SSC_PER_MSB_VAL 0 | ||
127 | |||
128 | #define PLL_SSC_PER_LSB_REG 0x59 | ||
129 | #define PLL_SSC_PER_LSB_VAL 0xf1 | ||
130 | |||
131 | #define IDLL_TEST_REG 0x72 | ||
132 | #define START_CLK_HF BIT(6) | ||
133 | |||
134 | #define DES_BITLOCK_REG 0x86 | ||
135 | #define BIT_LOCK_LEVEL 0x01 | ||
136 | #define BIT_LOCK_CNT_512 (0x03 << 5) | ||
137 | |||
138 | struct miphy365x_phy { | ||
139 | struct phy *phy; | ||
140 | void __iomem *base; | ||
141 | bool pcie_tx_pol_inv; | ||
142 | bool sata_tx_pol_inv; | ||
143 | u32 sata_gen; | ||
144 | u32 ctrlreg; | ||
145 | u8 type; | ||
146 | }; | ||
147 | |||
148 | struct miphy365x_dev { | ||
149 | struct device *dev; | ||
150 | struct regmap *regmap; | ||
151 | struct mutex miphy_mutex; | ||
152 | struct miphy365x_phy **phys; | ||
153 | int nphys; | ||
154 | }; | ||
155 | |||
156 | /* | ||
157 | * These values are represented in Device tree. They are considered to be ABI | ||
158 | * and although they can be extended any existing values must not change. | ||
159 | */ | ||
160 | enum miphy_sata_gen { | ||
161 | SATA_GEN1 = 1, | ||
162 | SATA_GEN2, | ||
163 | SATA_GEN3 | ||
164 | }; | ||
165 | |||
166 | static u8 rx_tx_spd[] = { | ||
167 | 0, /* GEN0 doesn't exist. */ | ||
168 | TX_SPDSEL_GEN1_VAL | RX_SPDSEL_GEN1_VAL, | ||
169 | TX_SPDSEL_GEN2_VAL | RX_SPDSEL_GEN2_VAL, | ||
170 | TX_SPDSEL_GEN3_VAL | RX_SPDSEL_GEN3_VAL | ||
171 | }; | ||
172 | |||
173 | /* | ||
174 | * This function selects the system configuration, | ||
175 | * either two SATA, one SATA and one PCIe, or two PCIe lanes. | ||
176 | */ | ||
177 | static int miphy365x_set_path(struct miphy365x_phy *miphy_phy, | ||
178 | struct miphy365x_dev *miphy_dev) | ||
179 | { | ||
180 | bool sata = (miphy_phy->type == PHY_TYPE_SATA); | ||
181 | |||
182 | return regmap_update_bits(miphy_dev->regmap, | ||
183 | miphy_phy->ctrlreg, | ||
184 | SYSCFG_SELECT_SATA_MASK, | ||
185 | sata << SYSCFG_SELECT_SATA_POS); | ||
186 | } | ||
187 | |||
188 | static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy, | ||
189 | struct miphy365x_dev *miphy_dev) | ||
190 | { | ||
191 | u8 val; | ||
192 | |||
193 | if (miphy_phy->pcie_tx_pol_inv) { | ||
194 | /* Invert Tx polarity and clear pci_txdetect_pol bit */ | ||
195 | val = TERM_EN | PCI_EN | DES_BIT_LOCK_EN | TX_POL; | ||
196 | writeb_relaxed(val, miphy_phy->base + CTRL_REG); | ||
197 | writeb_relaxed(0x00, miphy_phy->base + PCIE_REG); | ||
198 | } | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static inline int miphy365x_hfc_not_rdy(struct miphy365x_phy *miphy_phy, | ||
204 | struct miphy365x_dev *miphy_dev) | ||
205 | { | ||
206 | unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT); | ||
207 | u8 mask = IDLL_RDY | PLL_RDY; | ||
208 | u8 regval; | ||
209 | |||
210 | do { | ||
211 | regval = readb_relaxed(miphy_phy->base + STATUS_REG); | ||
212 | if (!(regval & mask)) | ||
213 | return 0; | ||
214 | |||
215 | usleep_range(2000, 2500); | ||
216 | } while (time_before(jiffies, timeout)); | ||
217 | |||
218 | dev_err(miphy_dev->dev, "HFC ready timeout!\n"); | ||
219 | return -EBUSY; | ||
220 | } | ||
221 | |||
222 | static inline int miphy365x_rdy(struct miphy365x_phy *miphy_phy, | ||
223 | struct miphy365x_dev *miphy_dev) | ||
224 | { | ||
225 | unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT); | ||
226 | u8 mask = IDLL_RDY | PLL_RDY; | ||
227 | u8 regval; | ||
228 | |||
229 | do { | ||
230 | regval = readb_relaxed(miphy_phy->base + STATUS_REG); | ||
231 | if ((regval & mask) == mask) | ||
232 | return 0; | ||
233 | |||
234 | usleep_range(2000, 2500); | ||
235 | } while (time_before(jiffies, timeout)); | ||
236 | |||
237 | dev_err(miphy_dev->dev, "PHY not ready timeout!\n"); | ||
238 | return -EBUSY; | ||
239 | } | ||
240 | |||
241 | static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy, | ||
242 | struct miphy365x_dev *miphy_dev) | ||
243 | { | ||
244 | u8 val, mask; | ||
245 | |||
246 | if (miphy_phy->sata_gen == SATA_GEN1) | ||
247 | writeb_relaxed(COMP_2MHZ_RAT_GEN1, | ||
248 | miphy_phy->base + COMP_CTRL2_REG); | ||
249 | else | ||
250 | writeb_relaxed(COMP_2MHZ_RAT, | ||
251 | miphy_phy->base + COMP_CTRL2_REG); | ||
252 | |||
253 | if (miphy_phy->sata_gen != SATA_GEN3) { | ||
254 | writeb_relaxed(COMSR_COMP_REF, | ||
255 | miphy_phy->base + COMP_CTRL3_REG); | ||
256 | /* | ||
257 | * Force VCO current to value defined by address 0x5A | ||
258 | * and disable PCIe100Mref bit | ||
259 | * Enable auto load compensation for pll_i_bias | ||
260 | */ | ||
261 | writeb_relaxed(BYPASS_PLL_CAL, miphy_phy->base + PLL_CTRL2_REG); | ||
262 | writeb_relaxed(COMZC_IDLL, miphy_phy->base + COMP_IDLL_REG); | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Force restart compensation and enable auto load | ||
267 | * for Comzc_Tx, Comzc_Rx and Comsr on macro | ||
268 | */ | ||
269 | val = START_COMSR | START_COMZC | COMP_AUTO_LOAD; | ||
270 | writeb_relaxed(val, miphy_phy->base + COMP_CTRL1_REG); | ||
271 | |||
272 | mask = COMSR_DONE | COMZC_DONE; | ||
273 | while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask) != mask) | ||
274 | cpu_relax(); | ||
275 | } | ||
276 | |||
277 | static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy, | ||
278 | struct miphy365x_dev *miphy_dev) | ||
279 | { | ||
280 | u8 val; | ||
281 | |||
282 | /* | ||
283 | * SSC Settings. SSC will be enabled through Link | ||
284 | * SSC Ampl. = 0.4% | ||
285 | * SSC Freq = 31KHz | ||
286 | */ | ||
287 | writeb_relaxed(PLL_SSC_STEP_MSB_VAL, | ||
288 | miphy_phy->base + PLL_SSC_STEP_MSB_REG); | ||
289 | writeb_relaxed(PLL_SSC_STEP_LSB_VAL, | ||
290 | miphy_phy->base + PLL_SSC_STEP_LSB_REG); | ||
291 | writeb_relaxed(PLL_SSC_PER_MSB_VAL, | ||
292 | miphy_phy->base + PLL_SSC_PER_MSB_REG); | ||
293 | writeb_relaxed(PLL_SSC_PER_LSB_VAL, | ||
294 | miphy_phy->base + PLL_SSC_PER_LSB_REG); | ||
295 | |||
296 | /* SSC Settings complete */ | ||
297 | if (miphy_phy->sata_gen == SATA_GEN1) { | ||
298 | val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL; | ||
299 | writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG); | ||
300 | } else { | ||
301 | val = SSC_EN | PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL; | ||
302 | writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy, | ||
307 | struct miphy365x_dev *miphy_dev) | ||
308 | { | ||
309 | int ret; | ||
310 | u8 val; | ||
311 | |||
312 | /* | ||
313 | * Force PHY macro reset, PLL calibration reset, PLL reset | ||
314 | * and assert Deserializer Reset | ||
315 | */ | ||
316 | val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO; | ||
317 | writeb_relaxed(val, miphy_phy->base + RESET_REG); | ||
318 | |||
319 | if (miphy_phy->sata_tx_pol_inv) | ||
320 | writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG); | ||
321 | |||
322 | /* | ||
323 | * Force macro1 to use rx_lspd, tx_lspd | ||
324 | * Force Rx_Clock on first I-DLL phase | ||
325 | * Force Des in HP mode on macro, rx_lspd, tx_lspd for Gen2/3 | ||
326 | */ | ||
327 | writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG); | ||
328 | writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG); | ||
329 | val = rx_tx_spd[miphy_phy->sata_gen]; | ||
330 | writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG); | ||
331 | |||
332 | /* Wait for HFC_READY = 0 */ | ||
333 | ret = miphy365x_hfc_not_rdy(miphy_phy, miphy_dev); | ||
334 | if (ret) | ||
335 | return ret; | ||
336 | |||
337 | /* Compensation Recalibration */ | ||
338 | miphy365x_set_comp(miphy_phy, miphy_dev); | ||
339 | |||
340 | switch (miphy_phy->sata_gen) { | ||
341 | case SATA_GEN3: | ||
342 | /* | ||
343 | * TX Swing target 550-600mv peak to peak diff | ||
344 | * Tx Slew target 90-110ps rising/falling time | ||
345 | * Rx Eq ON3, Sigdet threshold SDTH1 | ||
346 | */ | ||
347 | val = PD_VDDTFILTER | CONF_GEN_SEL_GEN3; | ||
348 | writeb_relaxed(val, miphy_phy->base + BUF_SEL_REG); | ||
349 | val = SWING_VAL | PREEMPH_VAL; | ||
350 | writeb_relaxed(val, miphy_phy->base + TXBUF1_REG); | ||
351 | writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG); | ||
352 | writeb_relaxed(0x00, miphy_phy->base + RXBUF_OFFSET_CTRL_REG); | ||
353 | val = SDTHRES_VAL | EQ_ON3; | ||
354 | writeb_relaxed(val, miphy_phy->base + RXBUF_REG); | ||
355 | break; | ||
356 | case SATA_GEN2: | ||
357 | /* | ||
358 | * conf gen sel=0x1 to program Gen2 banked registers | ||
359 | * VDDT filter ON | ||
360 | * Tx Swing target 550-600mV peak-to-peak diff | ||
361 | * Tx Slew target 90-110 ps rising/falling time | ||
362 | * RX Equalization ON1, Sigdet threshold SDTH1 | ||
363 | */ | ||
364 | writeb_relaxed(CONF_GEN_SEL_GEN2, | ||
365 | miphy_phy->base + BUF_SEL_REG); | ||
366 | writeb_relaxed(SWING_VAL, miphy_phy->base + TXBUF1_REG); | ||
367 | writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG); | ||
368 | val = SDTHRES_VAL | EQ_ON1; | ||
369 | writeb_relaxed(val, miphy_phy->base + RXBUF_REG); | ||
370 | break; | ||
371 | case SATA_GEN1: | ||
372 | /* | ||
373 | * conf gen sel = 00b to program Gen1 banked registers | ||
374 | * VDDT filter ON | ||
375 | * Tx Swing target 500-550mV peak-to-peak diff | ||
376 | * Tx Slew target120-140 ps rising/falling time | ||
377 | */ | ||
378 | writeb_relaxed(PD_VDDTFILTER, miphy_phy->base + BUF_SEL_REG); | ||
379 | writeb_relaxed(SWING_VAL_GEN1, miphy_phy->base + TXBUF1_REG); | ||
380 | writeb_relaxed(TXSLEW_VAL_GEN1, miphy_phy->base + TXBUF2_REG); | ||
381 | break; | ||
382 | default: | ||
383 | break; | ||
384 | } | ||
385 | |||
386 | /* Force Macro1 in partial mode & release pll cal reset */ | ||
387 | writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG); | ||
388 | usleep_range(100, 150); | ||
389 | |||
390 | miphy365x_set_ssc(miphy_phy, miphy_dev); | ||
391 | |||
392 | /* Wait for phy_ready */ | ||
393 | ret = miphy365x_rdy(miphy_phy, miphy_dev); | ||
394 | if (ret) | ||
395 | return ret; | ||
396 | |||
397 | /* | ||
398 | * Enable macro1 to use rx_lspd & tx_lspd | ||
399 | * Release Rx_Clock on first I-DLL phase on macro1 | ||
400 | * Assert deserializer reset | ||
401 | * des_bit_lock_en is set | ||
402 | * bit lock detection strength | ||
403 | * Deassert deserializer reset | ||
404 | */ | ||
405 | writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG); | ||
406 | writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG); | ||
407 | writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG); | ||
408 | val = miphy_phy->sata_tx_pol_inv ? | ||
409 | (TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN; | ||
410 | writeb_relaxed(val, miphy_phy->base + CTRL_REG); | ||
411 | |||
412 | val = BIT_LOCK_CNT_512 | BIT_LOCK_LEVEL; | ||
413 | writeb_relaxed(val, miphy_phy->base + DES_BITLOCK_REG); | ||
414 | writeb_relaxed(0x00, miphy_phy->base + RESET_REG); | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static int miphy365x_init(struct phy *phy) | ||
420 | { | ||
421 | struct miphy365x_phy *miphy_phy = phy_get_drvdata(phy); | ||
422 | struct miphy365x_dev *miphy_dev = dev_get_drvdata(phy->dev.parent); | ||
423 | int ret = 0; | ||
424 | |||
425 | mutex_lock(&miphy_dev->miphy_mutex); | ||
426 | |||
427 | ret = miphy365x_set_path(miphy_phy, miphy_dev); | ||
428 | if (ret) { | ||
429 | mutex_unlock(&miphy_dev->miphy_mutex); | ||
430 | return ret; | ||
431 | } | ||
432 | |||
433 | /* Initialise Miphy for PCIe or SATA */ | ||
434 | if (miphy_phy->type == PHY_TYPE_PCIE) | ||
435 | ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev); | ||
436 | else | ||
437 | ret = miphy365x_init_sata_port(miphy_phy, miphy_dev); | ||
438 | |||
439 | mutex_unlock(&miphy_dev->miphy_mutex); | ||
440 | |||
441 | return ret; | ||
442 | } | ||
443 | |||
444 | static int miphy365x_get_addr(struct device *dev, | ||
445 | struct miphy365x_phy *miphy_phy, int index) | ||
446 | { | ||
447 | struct device_node *phynode = miphy_phy->phy->dev.of_node; | ||
448 | const char *name; | ||
449 | int type = miphy_phy->type; | ||
450 | int ret; | ||
451 | |||
452 | ret = of_property_read_string_index(phynode, "reg-names", index, &name); | ||
453 | if (ret) { | ||
454 | dev_err(dev, "no reg-names property not found\n"); | ||
455 | return ret; | ||
456 | } | ||
457 | |||
458 | if (!((!strncmp(name, "sata", 4) && type == PHY_TYPE_SATA) || | ||
459 | (!strncmp(name, "pcie", 4) && type == PHY_TYPE_PCIE))) | ||
460 | return 0; | ||
461 | |||
462 | miphy_phy->base = of_iomap(phynode, index); | ||
463 | if (!miphy_phy->base) { | ||
464 | dev_err(dev, "Failed to map %s\n", phynode->full_name); | ||
465 | return -EINVAL; | ||
466 | } | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static struct phy *miphy365x_xlate(struct device *dev, | ||
472 | struct of_phandle_args *args) | ||
473 | { | ||
474 | struct miphy365x_dev *miphy_dev = dev_get_drvdata(dev); | ||
475 | struct miphy365x_phy *miphy_phy = NULL; | ||
476 | struct device_node *phynode = args->np; | ||
477 | int ret, index; | ||
478 | |||
479 | if (args->args_count != 1) { | ||
480 | dev_err(dev, "Invalid number of cells in 'phy' property\n"); | ||
481 | return ERR_PTR(-EINVAL); | ||
482 | } | ||
483 | |||
484 | for (index = 0; index < miphy_dev->nphys; index++) | ||
485 | if (phynode == miphy_dev->phys[index]->phy->dev.of_node) { | ||
486 | miphy_phy = miphy_dev->phys[index]; | ||
487 | break; | ||
488 | } | ||
489 | |||
490 | if (!miphy_phy) { | ||
491 | dev_err(dev, "Failed to find appropriate phy\n"); | ||
492 | return ERR_PTR(-EINVAL); | ||
493 | } | ||
494 | |||
495 | miphy_phy->type = args->args[0]; | ||
496 | |||
497 | if (!(miphy_phy->type == PHY_TYPE_SATA || | ||
498 | miphy_phy->type == PHY_TYPE_PCIE)) { | ||
499 | dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type); | ||
500 | return ERR_PTR(-EINVAL); | ||
501 | } | ||
502 | |||
503 | /* Each port handles SATA and PCIE - third entry is always sysconf. */ | ||
504 | for (index = 0; index < 3; index++) { | ||
505 | ret = miphy365x_get_addr(dev, miphy_phy, index); | ||
506 | if (ret < 0) | ||
507 | return ERR_PTR(ret); | ||
508 | } | ||
509 | |||
510 | return miphy_phy->phy; | ||
511 | } | ||
512 | |||
513 | static const struct phy_ops miphy365x_ops = { | ||
514 | .init = miphy365x_init, | ||
515 | .owner = THIS_MODULE, | ||
516 | }; | ||
517 | |||
518 | static int miphy365x_of_probe(struct device_node *phynode, | ||
519 | struct miphy365x_phy *miphy_phy) | ||
520 | { | ||
521 | of_property_read_u32(phynode, "st,sata-gen", &miphy_phy->sata_gen); | ||
522 | if (!miphy_phy->sata_gen) | ||
523 | miphy_phy->sata_gen = SATA_GEN1; | ||
524 | |||
525 | miphy_phy->pcie_tx_pol_inv = | ||
526 | of_property_read_bool(phynode, "st,pcie-tx-pol-inv"); | ||
527 | |||
528 | miphy_phy->sata_tx_pol_inv = | ||
529 | of_property_read_bool(phynode, "st,sata-tx-pol-inv"); | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static int miphy365x_probe(struct platform_device *pdev) | ||
535 | { | ||
536 | struct device_node *child, *np = pdev->dev.of_node; | ||
537 | struct miphy365x_dev *miphy_dev; | ||
538 | struct phy_provider *provider; | ||
539 | struct phy *phy; | ||
540 | int ret, port = 0; | ||
541 | |||
542 | miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL); | ||
543 | if (!miphy_dev) | ||
544 | return -ENOMEM; | ||
545 | |||
546 | miphy_dev->nphys = of_get_child_count(np); | ||
547 | miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys, | ||
548 | sizeof(*miphy_dev->phys), GFP_KERNEL); | ||
549 | if (!miphy_dev->phys) | ||
550 | return -ENOMEM; | ||
551 | |||
552 | miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | ||
553 | if (IS_ERR(miphy_dev->regmap)) { | ||
554 | dev_err(miphy_dev->dev, "No syscfg phandle specified\n"); | ||
555 | return PTR_ERR(miphy_dev->regmap); | ||
556 | } | ||
557 | |||
558 | miphy_dev->dev = &pdev->dev; | ||
559 | |||
560 | dev_set_drvdata(&pdev->dev, miphy_dev); | ||
561 | |||
562 | mutex_init(&miphy_dev->miphy_mutex); | ||
563 | |||
564 | for_each_child_of_node(np, child) { | ||
565 | struct miphy365x_phy *miphy_phy; | ||
566 | |||
567 | miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy), | ||
568 | GFP_KERNEL); | ||
569 | if (!miphy_phy) { | ||
570 | ret = -ENOMEM; | ||
571 | goto put_child; | ||
572 | } | ||
573 | |||
574 | miphy_dev->phys[port] = miphy_phy; | ||
575 | |||
576 | phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops); | ||
577 | if (IS_ERR(phy)) { | ||
578 | dev_err(&pdev->dev, "failed to create PHY\n"); | ||
579 | ret = PTR_ERR(phy); | ||
580 | goto put_child; | ||
581 | } | ||
582 | |||
583 | miphy_dev->phys[port]->phy = phy; | ||
584 | |||
585 | ret = miphy365x_of_probe(child, miphy_phy); | ||
586 | if (ret) | ||
587 | goto put_child; | ||
588 | |||
589 | phy_set_drvdata(phy, miphy_dev->phys[port]); | ||
590 | |||
591 | port++; | ||
592 | /* sysconfig offsets are indexed from 1 */ | ||
593 | ret = of_property_read_u32_index(np, "st,syscfg", port, | ||
594 | &miphy_phy->ctrlreg); | ||
595 | if (ret) { | ||
596 | dev_err(&pdev->dev, "No sysconfig offset found\n"); | ||
597 | goto put_child; | ||
598 | } | ||
599 | } | ||
600 | |||
601 | provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate); | ||
602 | return PTR_ERR_OR_ZERO(provider); | ||
603 | put_child: | ||
604 | of_node_put(child); | ||
605 | return ret; | ||
606 | } | ||
607 | |||
608 | static const struct of_device_id miphy365x_of_match[] = { | ||
609 | { .compatible = "st,miphy365x-phy", }, | ||
610 | { }, | ||
611 | }; | ||
612 | MODULE_DEVICE_TABLE(of, miphy365x_of_match); | ||
613 | |||
614 | static struct platform_driver miphy365x_driver = { | ||
615 | .probe = miphy365x_probe, | ||
616 | .driver = { | ||
617 | .name = "miphy365x-phy", | ||
618 | .of_match_table = miphy365x_of_match, | ||
619 | } | ||
620 | }; | ||
621 | module_platform_driver(miphy365x_driver); | ||
622 | |||
623 | MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>"); | ||
624 | MODULE_DESCRIPTION("STMicroelectronics miphy365x driver"); | ||
625 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c index 3d97eadd247d..c63da1b955c1 100644 --- a/drivers/phy/phy-rcar-gen3-usb2.c +++ b/drivers/phy/phy-rcar-gen3-usb2.c | |||
@@ -70,6 +70,7 @@ | |||
70 | #define USB2_LINECTRL1_DP_RPD BIT(18) | 70 | #define USB2_LINECTRL1_DP_RPD BIT(18) |
71 | #define USB2_LINECTRL1_DMRPD_EN BIT(17) | 71 | #define USB2_LINECTRL1_DMRPD_EN BIT(17) |
72 | #define USB2_LINECTRL1_DM_RPD BIT(16) | 72 | #define USB2_LINECTRL1_DM_RPD BIT(16) |
73 | #define USB2_LINECTRL1_OPMODE_NODRV BIT(6) | ||
73 | 74 | ||
74 | /* ADPCTRL */ | 75 | /* ADPCTRL */ |
75 | #define USB2_ADPCTRL_OTGSESSVLD BIT(20) | 76 | #define USB2_ADPCTRL_OTGSESSVLD BIT(20) |
@@ -161,6 +162,43 @@ static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) | |||
161 | schedule_work(&ch->work); | 162 | schedule_work(&ch->work); |
162 | } | 163 | } |
163 | 164 | ||
165 | static void rcar_gen3_init_for_b_host(struct rcar_gen3_chan *ch) | ||
166 | { | ||
167 | void __iomem *usb2_base = ch->base; | ||
168 | u32 val; | ||
169 | |||
170 | val = readl(usb2_base + USB2_LINECTRL1); | ||
171 | writel(val | USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1); | ||
172 | |||
173 | rcar_gen3_set_linectrl(ch, 1, 1); | ||
174 | rcar_gen3_set_host_mode(ch, 1); | ||
175 | rcar_gen3_enable_vbus_ctrl(ch, 0); | ||
176 | |||
177 | val = readl(usb2_base + USB2_LINECTRL1); | ||
178 | writel(val & ~USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1); | ||
179 | } | ||
180 | |||
181 | static void rcar_gen3_init_for_a_peri(struct rcar_gen3_chan *ch) | ||
182 | { | ||
183 | rcar_gen3_set_linectrl(ch, 0, 1); | ||
184 | rcar_gen3_set_host_mode(ch, 0); | ||
185 | rcar_gen3_enable_vbus_ctrl(ch, 1); | ||
186 | } | ||
187 | |||
188 | static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch) | ||
189 | { | ||
190 | void __iomem *usb2_base = ch->base; | ||
191 | u32 val; | ||
192 | |||
193 | val = readl(usb2_base + USB2_OBINTEN); | ||
194 | writel(val & ~USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); | ||
195 | |||
196 | rcar_gen3_enable_vbus_ctrl(ch, 0); | ||
197 | rcar_gen3_init_for_host(ch); | ||
198 | |||
199 | writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); | ||
200 | } | ||
201 | |||
164 | static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) | 202 | static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) |
165 | { | 203 | { |
166 | return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); | 204 | return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); |
@@ -174,6 +212,65 @@ static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch) | |||
174 | rcar_gen3_init_for_peri(ch); | 212 | rcar_gen3_init_for_peri(ch); |
175 | } | 213 | } |
176 | 214 | ||
215 | static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch) | ||
216 | { | ||
217 | return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI); | ||
218 | } | ||
219 | |||
220 | static ssize_t role_store(struct device *dev, struct device_attribute *attr, | ||
221 | const char *buf, size_t count) | ||
222 | { | ||
223 | struct rcar_gen3_chan *ch = dev_get_drvdata(dev); | ||
224 | bool is_b_device, is_host, new_mode_is_host; | ||
225 | |||
226 | if (!ch->has_otg || !ch->phy->init_count) | ||
227 | return -EIO; | ||
228 | |||
229 | /* | ||
230 | * is_b_device: true is B-Device. false is A-Device. | ||
231 | * If {new_mode_}is_host: true is Host mode. false is Peripheral mode. | ||
232 | */ | ||
233 | is_b_device = rcar_gen3_check_id(ch); | ||
234 | is_host = rcar_gen3_is_host(ch); | ||
235 | if (!strncmp(buf, "host", strlen("host"))) | ||
236 | new_mode_is_host = true; | ||
237 | else if (!strncmp(buf, "peripheral", strlen("peripheral"))) | ||
238 | new_mode_is_host = false; | ||
239 | else | ||
240 | return -EINVAL; | ||
241 | |||
242 | /* If current and new mode is the same, this returns the error */ | ||
243 | if (is_host == new_mode_is_host) | ||
244 | return -EINVAL; | ||
245 | |||
246 | if (new_mode_is_host) { /* And is_host must be false */ | ||
247 | if (!is_b_device) /* A-Peripheral */ | ||
248 | rcar_gen3_init_from_a_peri_to_a_host(ch); | ||
249 | else /* B-Peripheral */ | ||
250 | rcar_gen3_init_for_b_host(ch); | ||
251 | } else { /* And is_host must be true */ | ||
252 | if (!is_b_device) /* A-Host */ | ||
253 | rcar_gen3_init_for_a_peri(ch); | ||
254 | else /* B-Host */ | ||
255 | rcar_gen3_init_for_peri(ch); | ||
256 | } | ||
257 | |||
258 | return count; | ||
259 | } | ||
260 | |||
261 | static ssize_t role_show(struct device *dev, struct device_attribute *attr, | ||
262 | char *buf) | ||
263 | { | ||
264 | struct rcar_gen3_chan *ch = dev_get_drvdata(dev); | ||
265 | |||
266 | if (!ch->has_otg || !ch->phy->init_count) | ||
267 | return -EIO; | ||
268 | |||
269 | return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" : | ||
270 | "peripheral"); | ||
271 | } | ||
272 | static DEVICE_ATTR_RW(role); | ||
273 | |||
177 | static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) | 274 | static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) |
178 | { | 275 | { |
179 | void __iomem *usb2_base = ch->base; | 276 | void __iomem *usb2_base = ch->base; |
@@ -351,21 +448,40 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) | |||
351 | channel->vbus = NULL; | 448 | channel->vbus = NULL; |
352 | } | 449 | } |
353 | 450 | ||
451 | platform_set_drvdata(pdev, channel); | ||
354 | phy_set_drvdata(channel->phy, channel); | 452 | phy_set_drvdata(channel->phy, channel); |
355 | 453 | ||
356 | provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | 454 | provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); |
357 | if (IS_ERR(provider)) | 455 | if (IS_ERR(provider)) { |
358 | dev_err(dev, "Failed to register PHY provider\n"); | 456 | dev_err(dev, "Failed to register PHY provider\n"); |
457 | } else if (channel->has_otg) { | ||
458 | int ret; | ||
459 | |||
460 | ret = device_create_file(dev, &dev_attr_role); | ||
461 | if (ret < 0) | ||
462 | return ret; | ||
463 | } | ||
359 | 464 | ||
360 | return PTR_ERR_OR_ZERO(provider); | 465 | return PTR_ERR_OR_ZERO(provider); |
361 | } | 466 | } |
362 | 467 | ||
468 | static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev) | ||
469 | { | ||
470 | struct rcar_gen3_chan *channel = platform_get_drvdata(pdev); | ||
471 | |||
472 | if (channel->has_otg) | ||
473 | device_remove_file(&pdev->dev, &dev_attr_role); | ||
474 | |||
475 | return 0; | ||
476 | }; | ||
477 | |||
363 | static struct platform_driver rcar_gen3_phy_usb2_driver = { | 478 | static struct platform_driver rcar_gen3_phy_usb2_driver = { |
364 | .driver = { | 479 | .driver = { |
365 | .name = "phy_rcar_gen3_usb2", | 480 | .name = "phy_rcar_gen3_usb2", |
366 | .of_match_table = rcar_gen3_phy_usb2_match_table, | 481 | .of_match_table = rcar_gen3_phy_usb2_match_table, |
367 | }, | 482 | }, |
368 | .probe = rcar_gen3_phy_usb2_probe, | 483 | .probe = rcar_gen3_phy_usb2_probe, |
484 | .remove = rcar_gen3_phy_usb2_remove, | ||
369 | }; | 485 | }; |
370 | module_platform_driver(rcar_gen3_phy_usb2_driver); | 486 | module_platform_driver(rcar_gen3_phy_usb2_driver); |
371 | 487 | ||
diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c index fd57345ffed2..f1b24f18e9b2 100644 --- a/drivers/phy/phy-rockchip-emmc.c +++ b/drivers/phy/phy-rockchip-emmc.c | |||
@@ -132,7 +132,7 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off) | |||
132 | default: | 132 | default: |
133 | ideal_rate = 200000000; | 133 | ideal_rate = 200000000; |
134 | break; | 134 | break; |
135 | }; | 135 | } |
136 | 136 | ||
137 | diff = (rate > ideal_rate) ? | 137 | diff = (rate > ideal_rate) ? |
138 | rate - ideal_rate : ideal_rate - rate; | 138 | rate - ideal_rate : ideal_rate - rate; |
diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c index ac203107b071..2f99ec95079c 100644 --- a/drivers/phy/phy-rockchip-inno-usb2.c +++ b/drivers/phy/phy-rockchip-inno-usb2.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/clk-provider.h> | 18 | #include <linux/clk-provider.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/extcon.h> | ||
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
22 | #include <linux/gpio/consumer.h> | 23 | #include <linux/gpio/consumer.h> |
@@ -30,11 +31,15 @@ | |||
30 | #include <linux/of_platform.h> | 31 | #include <linux/of_platform.h> |
31 | #include <linux/phy/phy.h> | 32 | #include <linux/phy/phy.h> |
32 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/power_supply.h> | ||
33 | #include <linux/regmap.h> | 35 | #include <linux/regmap.h> |
34 | #include <linux/mfd/syscon.h> | 36 | #include <linux/mfd/syscon.h> |
37 | #include <linux/usb/of.h> | ||
38 | #include <linux/usb/otg.h> | ||
35 | 39 | ||
36 | #define BIT_WRITEABLE_SHIFT 16 | 40 | #define BIT_WRITEABLE_SHIFT 16 |
37 | #define SCHEDULE_DELAY (60 * HZ) | 41 | #define SCHEDULE_DELAY (60 * HZ) |
42 | #define OTG_SCHEDULE_DELAY (2 * HZ) | ||
38 | 43 | ||
39 | enum rockchip_usb2phy_port_id { | 44 | enum rockchip_usb2phy_port_id { |
40 | USB2PHY_PORT_OTG, | 45 | USB2PHY_PORT_OTG, |
@@ -49,6 +54,37 @@ enum rockchip_usb2phy_host_state { | |||
49 | PHY_STATE_FS_LS_ONLINE = 4, | 54 | PHY_STATE_FS_LS_ONLINE = 4, |
50 | }; | 55 | }; |
51 | 56 | ||
57 | /** | ||
58 | * Different states involved in USB charger detection. | ||
59 | * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection | ||
60 | * process is not yet started. | ||
61 | * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact. | ||
62 | * USB_CHG_STATE_DCD_DONE Data pin contact is detected. | ||
63 | * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects | ||
64 | * between SDP and DCP/CDP). | ||
65 | * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects | ||
66 | * between DCP and CDP). | ||
67 | * USB_CHG_STATE_DETECTED USB charger type is determined. | ||
68 | */ | ||
69 | enum usb_chg_state { | ||
70 | USB_CHG_STATE_UNDEFINED = 0, | ||
71 | USB_CHG_STATE_WAIT_FOR_DCD, | ||
72 | USB_CHG_STATE_DCD_DONE, | ||
73 | USB_CHG_STATE_PRIMARY_DONE, | ||
74 | USB_CHG_STATE_SECONDARY_DONE, | ||
75 | USB_CHG_STATE_DETECTED, | ||
76 | }; | ||
77 | |||
78 | static const unsigned int rockchip_usb2phy_extcon_cable[] = { | ||
79 | EXTCON_USB, | ||
80 | EXTCON_USB_HOST, | ||
81 | EXTCON_CHG_USB_SDP, | ||
82 | EXTCON_CHG_USB_CDP, | ||
83 | EXTCON_CHG_USB_DCP, | ||
84 | EXTCON_CHG_USB_SLOW, | ||
85 | EXTCON_NONE, | ||
86 | }; | ||
87 | |||
52 | struct usb2phy_reg { | 88 | struct usb2phy_reg { |
53 | unsigned int offset; | 89 | unsigned int offset; |
54 | unsigned int bitend; | 90 | unsigned int bitend; |
@@ -58,19 +94,55 @@ struct usb2phy_reg { | |||
58 | }; | 94 | }; |
59 | 95 | ||
60 | /** | 96 | /** |
97 | * struct rockchip_chg_det_reg: usb charger detect registers | ||
98 | * @cp_det: charging port detected successfully. | ||
99 | * @dcp_det: dedicated charging port detected successfully. | ||
100 | * @dp_det: assert data pin connect successfully. | ||
101 | * @idm_sink_en: open dm sink curren. | ||
102 | * @idp_sink_en: open dp sink current. | ||
103 | * @idp_src_en: open dm source current. | ||
104 | * @rdm_pdwn_en: open dm pull down resistor. | ||
105 | * @vdm_src_en: open dm voltage source. | ||
106 | * @vdp_src_en: open dp voltage source. | ||
107 | * @opmode: utmi operational mode. | ||
108 | */ | ||
109 | struct rockchip_chg_det_reg { | ||
110 | struct usb2phy_reg cp_det; | ||
111 | struct usb2phy_reg dcp_det; | ||
112 | struct usb2phy_reg dp_det; | ||
113 | struct usb2phy_reg idm_sink_en; | ||
114 | struct usb2phy_reg idp_sink_en; | ||
115 | struct usb2phy_reg idp_src_en; | ||
116 | struct usb2phy_reg rdm_pdwn_en; | ||
117 | struct usb2phy_reg vdm_src_en; | ||
118 | struct usb2phy_reg vdp_src_en; | ||
119 | struct usb2phy_reg opmode; | ||
120 | }; | ||
121 | |||
122 | /** | ||
61 | * struct rockchip_usb2phy_port_cfg: usb-phy port configuration. | 123 | * struct rockchip_usb2phy_port_cfg: usb-phy port configuration. |
62 | * @phy_sus: phy suspend register. | 124 | * @phy_sus: phy suspend register. |
125 | * @bvalid_det_en: vbus valid rise detection enable register. | ||
126 | * @bvalid_det_st: vbus valid rise detection status register. | ||
127 | * @bvalid_det_clr: vbus valid rise detection clear register. | ||
63 | * @ls_det_en: linestate detection enable register. | 128 | * @ls_det_en: linestate detection enable register. |
64 | * @ls_det_st: linestate detection state register. | 129 | * @ls_det_st: linestate detection state register. |
65 | * @ls_det_clr: linestate detection clear register. | 130 | * @ls_det_clr: linestate detection clear register. |
131 | * @utmi_avalid: utmi vbus avalid status register. | ||
132 | * @utmi_bvalid: utmi vbus bvalid status register. | ||
66 | * @utmi_ls: utmi linestate state register. | 133 | * @utmi_ls: utmi linestate state register. |
67 | * @utmi_hstdet: utmi host disconnect register. | 134 | * @utmi_hstdet: utmi host disconnect register. |
68 | */ | 135 | */ |
69 | struct rockchip_usb2phy_port_cfg { | 136 | struct rockchip_usb2phy_port_cfg { |
70 | struct usb2phy_reg phy_sus; | 137 | struct usb2phy_reg phy_sus; |
138 | struct usb2phy_reg bvalid_det_en; | ||
139 | struct usb2phy_reg bvalid_det_st; | ||
140 | struct usb2phy_reg bvalid_det_clr; | ||
71 | struct usb2phy_reg ls_det_en; | 141 | struct usb2phy_reg ls_det_en; |
72 | struct usb2phy_reg ls_det_st; | 142 | struct usb2phy_reg ls_det_st; |
73 | struct usb2phy_reg ls_det_clr; | 143 | struct usb2phy_reg ls_det_clr; |
144 | struct usb2phy_reg utmi_avalid; | ||
145 | struct usb2phy_reg utmi_bvalid; | ||
74 | struct usb2phy_reg utmi_ls; | 146 | struct usb2phy_reg utmi_ls; |
75 | struct usb2phy_reg utmi_hstdet; | 147 | struct usb2phy_reg utmi_hstdet; |
76 | }; | 148 | }; |
@@ -80,31 +152,51 @@ struct rockchip_usb2phy_port_cfg { | |||
80 | * @reg: the address offset of grf for usb-phy config. | 152 | * @reg: the address offset of grf for usb-phy config. |
81 | * @num_ports: specify how many ports that the phy has. | 153 | * @num_ports: specify how many ports that the phy has. |
82 | * @clkout_ctl: keep on/turn off output clk of phy. | 154 | * @clkout_ctl: keep on/turn off output clk of phy. |
155 | * @chg_det: charger detection registers. | ||
83 | */ | 156 | */ |
84 | struct rockchip_usb2phy_cfg { | 157 | struct rockchip_usb2phy_cfg { |
85 | unsigned int reg; | 158 | unsigned int reg; |
86 | unsigned int num_ports; | 159 | unsigned int num_ports; |
87 | struct usb2phy_reg clkout_ctl; | 160 | struct usb2phy_reg clkout_ctl; |
88 | const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; | 161 | const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; |
162 | const struct rockchip_chg_det_reg chg_det; | ||
89 | }; | 163 | }; |
90 | 164 | ||
91 | /** | 165 | /** |
92 | * struct rockchip_usb2phy_port: usb-phy port data. | 166 | * struct rockchip_usb2phy_port: usb-phy port data. |
93 | * @port_id: flag for otg port or host port. | 167 | * @port_id: flag for otg port or host port. |
94 | * @suspended: phy suspended flag. | 168 | * @suspended: phy suspended flag. |
169 | * @utmi_avalid: utmi avalid status usage flag. | ||
170 | * true - use avalid to get vbus status | ||
171 | * flase - use bvalid to get vbus status | ||
172 | * @vbus_attached: otg device vbus status. | ||
173 | * @bvalid_irq: IRQ number assigned for vbus valid rise detection. | ||
95 | * @ls_irq: IRQ number assigned for linestate detection. | 174 | * @ls_irq: IRQ number assigned for linestate detection. |
96 | * @mutex: for register updating in sm_work. | 175 | * @mutex: for register updating in sm_work. |
97 | * @sm_work: OTG state machine work. | 176 | * @chg_work: charge detect work. |
177 | * @otg_sm_work: OTG state machine work. | ||
178 | * @sm_work: HOST state machine work. | ||
98 | * @phy_cfg: port register configuration, assigned by driver data. | 179 | * @phy_cfg: port register configuration, assigned by driver data. |
180 | * @event_nb: hold event notification callback. | ||
181 | * @state: define OTG enumeration states before device reset. | ||
182 | * @mode: the dr_mode of the controller. | ||
99 | */ | 183 | */ |
100 | struct rockchip_usb2phy_port { | 184 | struct rockchip_usb2phy_port { |
101 | struct phy *phy; | 185 | struct phy *phy; |
102 | unsigned int port_id; | 186 | unsigned int port_id; |
103 | bool suspended; | 187 | bool suspended; |
188 | bool utmi_avalid; | ||
189 | bool vbus_attached; | ||
190 | int bvalid_irq; | ||
104 | int ls_irq; | 191 | int ls_irq; |
105 | struct mutex mutex; | 192 | struct mutex mutex; |
193 | struct delayed_work chg_work; | ||
194 | struct delayed_work otg_sm_work; | ||
106 | struct delayed_work sm_work; | 195 | struct delayed_work sm_work; |
107 | const struct rockchip_usb2phy_port_cfg *port_cfg; | 196 | const struct rockchip_usb2phy_port_cfg *port_cfg; |
197 | struct notifier_block event_nb; | ||
198 | enum usb_otg_state state; | ||
199 | enum usb_dr_mode mode; | ||
108 | }; | 200 | }; |
109 | 201 | ||
110 | /** | 202 | /** |
@@ -113,6 +205,11 @@ struct rockchip_usb2phy_port { | |||
113 | * @clk: clock struct of phy input clk. | 205 | * @clk: clock struct of phy input clk. |
114 | * @clk480m: clock struct of phy output clk. | 206 | * @clk480m: clock struct of phy output clk. |
115 | * @clk_hw: clock struct of phy output clk management. | 207 | * @clk_hw: clock struct of phy output clk management. |
208 | * @chg_state: states involved in USB charger detection. | ||
209 | * @chg_type: USB charger types. | ||
210 | * @dcd_retries: The retry count used to track Data contact | ||
211 | * detection process. | ||
212 | * @edev: extcon device for notification registration | ||
116 | * @phy_cfg: phy register configuration, assigned by driver data. | 213 | * @phy_cfg: phy register configuration, assigned by driver data. |
117 | * @ports: phy port instance. | 214 | * @ports: phy port instance. |
118 | */ | 215 | */ |
@@ -122,6 +219,10 @@ struct rockchip_usb2phy { | |||
122 | struct clk *clk; | 219 | struct clk *clk; |
123 | struct clk *clk480m; | 220 | struct clk *clk480m; |
124 | struct clk_hw clk480m_hw; | 221 | struct clk_hw clk480m_hw; |
222 | enum usb_chg_state chg_state; | ||
223 | enum power_supply_type chg_type; | ||
224 | u8 dcd_retries; | ||
225 | struct extcon_dev *edev; | ||
125 | const struct rockchip_usb2phy_cfg *phy_cfg; | 226 | const struct rockchip_usb2phy_cfg *phy_cfg; |
126 | struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; | 227 | struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; |
127 | }; | 228 | }; |
@@ -153,7 +254,7 @@ static inline bool property_enabled(struct rockchip_usb2phy *rphy, | |||
153 | return tmp == reg->enable; | 254 | return tmp == reg->enable; |
154 | } | 255 | } |
155 | 256 | ||
156 | static int rockchip_usb2phy_clk480m_enable(struct clk_hw *hw) | 257 | static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) |
157 | { | 258 | { |
158 | struct rockchip_usb2phy *rphy = | 259 | struct rockchip_usb2phy *rphy = |
159 | container_of(hw, struct rockchip_usb2phy, clk480m_hw); | 260 | container_of(hw, struct rockchip_usb2phy, clk480m_hw); |
@@ -165,14 +266,14 @@ static int rockchip_usb2phy_clk480m_enable(struct clk_hw *hw) | |||
165 | if (ret) | 266 | if (ret) |
166 | return ret; | 267 | return ret; |
167 | 268 | ||
168 | /* waitting for the clk become stable */ | 269 | /* waiting for the clk become stable */ |
169 | mdelay(1); | 270 | usleep_range(1200, 1300); |
170 | } | 271 | } |
171 | 272 | ||
172 | return 0; | 273 | return 0; |
173 | } | 274 | } |
174 | 275 | ||
175 | static void rockchip_usb2phy_clk480m_disable(struct clk_hw *hw) | 276 | static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw) |
176 | { | 277 | { |
177 | struct rockchip_usb2phy *rphy = | 278 | struct rockchip_usb2phy *rphy = |
178 | container_of(hw, struct rockchip_usb2phy, clk480m_hw); | 279 | container_of(hw, struct rockchip_usb2phy, clk480m_hw); |
@@ -181,7 +282,7 @@ static void rockchip_usb2phy_clk480m_disable(struct clk_hw *hw) | |||
181 | property_enable(rphy, &rphy->phy_cfg->clkout_ctl, false); | 282 | property_enable(rphy, &rphy->phy_cfg->clkout_ctl, false); |
182 | } | 283 | } |
183 | 284 | ||
184 | static int rockchip_usb2phy_clk480m_enabled(struct clk_hw *hw) | 285 | static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw) |
185 | { | 286 | { |
186 | struct rockchip_usb2phy *rphy = | 287 | struct rockchip_usb2phy *rphy = |
187 | container_of(hw, struct rockchip_usb2phy, clk480m_hw); | 288 | container_of(hw, struct rockchip_usb2phy, clk480m_hw); |
@@ -197,9 +298,9 @@ rockchip_usb2phy_clk480m_recalc_rate(struct clk_hw *hw, | |||
197 | } | 298 | } |
198 | 299 | ||
199 | static const struct clk_ops rockchip_usb2phy_clkout_ops = { | 300 | static const struct clk_ops rockchip_usb2phy_clkout_ops = { |
200 | .enable = rockchip_usb2phy_clk480m_enable, | 301 | .prepare = rockchip_usb2phy_clk480m_prepare, |
201 | .disable = rockchip_usb2phy_clk480m_disable, | 302 | .unprepare = rockchip_usb2phy_clk480m_unprepare, |
202 | .is_enabled = rockchip_usb2phy_clk480m_enabled, | 303 | .is_prepared = rockchip_usb2phy_clk480m_prepared, |
203 | .recalc_rate = rockchip_usb2phy_clk480m_recalc_rate, | 304 | .recalc_rate = rockchip_usb2phy_clk480m_recalc_rate, |
204 | }; | 305 | }; |
205 | 306 | ||
@@ -263,33 +364,84 @@ err_ret: | |||
263 | return ret; | 364 | return ret; |
264 | } | 365 | } |
265 | 366 | ||
266 | static int rockchip_usb2phy_init(struct phy *phy) | 367 | static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy) |
267 | { | 368 | { |
268 | struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); | ||
269 | struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); | ||
270 | int ret; | 369 | int ret; |
370 | struct device_node *node = rphy->dev->of_node; | ||
371 | struct extcon_dev *edev; | ||
372 | |||
373 | if (of_property_read_bool(node, "extcon")) { | ||
374 | edev = extcon_get_edev_by_phandle(rphy->dev, 0); | ||
375 | if (IS_ERR(edev)) { | ||
376 | if (PTR_ERR(edev) != -EPROBE_DEFER) | ||
377 | dev_err(rphy->dev, "Invalid or missing extcon\n"); | ||
378 | return PTR_ERR(edev); | ||
379 | } | ||
380 | } else { | ||
381 | /* Initialize extcon device */ | ||
382 | edev = devm_extcon_dev_allocate(rphy->dev, | ||
383 | rockchip_usb2phy_extcon_cable); | ||
271 | 384 | ||
272 | if (rport->port_id == USB2PHY_PORT_HOST) { | 385 | if (IS_ERR(edev)) |
273 | /* clear linestate and enable linestate detect irq */ | 386 | return -ENOMEM; |
274 | mutex_lock(&rport->mutex); | ||
275 | 387 | ||
276 | ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true); | 388 | ret = devm_extcon_dev_register(rphy->dev, edev); |
277 | if (ret) { | 389 | if (ret) { |
278 | mutex_unlock(&rport->mutex); | 390 | dev_err(rphy->dev, "failed to register extcon device\n"); |
279 | return ret; | 391 | return ret; |
280 | } | 392 | } |
393 | } | ||
281 | 394 | ||
282 | ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true); | 395 | rphy->edev = edev; |
283 | if (ret) { | 396 | |
284 | mutex_unlock(&rport->mutex); | 397 | return 0; |
285 | return ret; | 398 | } |
399 | |||
400 | static int rockchip_usb2phy_init(struct phy *phy) | ||
401 | { | ||
402 | struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); | ||
403 | struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); | ||
404 | int ret = 0; | ||
405 | |||
406 | mutex_lock(&rport->mutex); | ||
407 | |||
408 | if (rport->port_id == USB2PHY_PORT_OTG) { | ||
409 | if (rport->mode != USB_DR_MODE_HOST) { | ||
410 | /* clear bvalid status and enable bvalid detect irq */ | ||
411 | ret = property_enable(rphy, | ||
412 | &rport->port_cfg->bvalid_det_clr, | ||
413 | true); | ||
414 | if (ret) | ||
415 | goto out; | ||
416 | |||
417 | ret = property_enable(rphy, | ||
418 | &rport->port_cfg->bvalid_det_en, | ||
419 | true); | ||
420 | if (ret) | ||
421 | goto out; | ||
422 | |||
423 | schedule_delayed_work(&rport->otg_sm_work, | ||
424 | OTG_SCHEDULE_DELAY); | ||
425 | } else { | ||
426 | /* If OTG works in host only mode, do nothing. */ | ||
427 | dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); | ||
286 | } | 428 | } |
429 | } else if (rport->port_id == USB2PHY_PORT_HOST) { | ||
430 | /* clear linestate and enable linestate detect irq */ | ||
431 | ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true); | ||
432 | if (ret) | ||
433 | goto out; | ||
434 | |||
435 | ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true); | ||
436 | if (ret) | ||
437 | goto out; | ||
287 | 438 | ||
288 | mutex_unlock(&rport->mutex); | ||
289 | schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); | 439 | schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); |
290 | } | 440 | } |
291 | 441 | ||
292 | return 0; | 442 | out: |
443 | mutex_unlock(&rport->mutex); | ||
444 | return ret; | ||
293 | } | 445 | } |
294 | 446 | ||
295 | static int rockchip_usb2phy_power_on(struct phy *phy) | 447 | static int rockchip_usb2phy_power_on(struct phy *phy) |
@@ -340,7 +492,11 @@ static int rockchip_usb2phy_exit(struct phy *phy) | |||
340 | { | 492 | { |
341 | struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); | 493 | struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); |
342 | 494 | ||
343 | if (rport->port_id == USB2PHY_PORT_HOST) | 495 | if (rport->port_id == USB2PHY_PORT_OTG && |
496 | rport->mode != USB_DR_MODE_HOST) { | ||
497 | cancel_delayed_work_sync(&rport->otg_sm_work); | ||
498 | cancel_delayed_work_sync(&rport->chg_work); | ||
499 | } else if (rport->port_id == USB2PHY_PORT_HOST) | ||
344 | cancel_delayed_work_sync(&rport->sm_work); | 500 | cancel_delayed_work_sync(&rport->sm_work); |
345 | 501 | ||
346 | return 0; | 502 | return 0; |
@@ -354,6 +510,249 @@ static const struct phy_ops rockchip_usb2phy_ops = { | |||
354 | .owner = THIS_MODULE, | 510 | .owner = THIS_MODULE, |
355 | }; | 511 | }; |
356 | 512 | ||
513 | static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) | ||
514 | { | ||
515 | struct rockchip_usb2phy_port *rport = | ||
516 | container_of(work, struct rockchip_usb2phy_port, | ||
517 | otg_sm_work.work); | ||
518 | struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); | ||
519 | static unsigned int cable; | ||
520 | unsigned long delay; | ||
521 | bool vbus_attach, sch_work, notify_charger; | ||
522 | |||
523 | if (rport->utmi_avalid) | ||
524 | vbus_attach = | ||
525 | property_enabled(rphy, &rport->port_cfg->utmi_avalid); | ||
526 | else | ||
527 | vbus_attach = | ||
528 | property_enabled(rphy, &rport->port_cfg->utmi_bvalid); | ||
529 | |||
530 | sch_work = false; | ||
531 | notify_charger = false; | ||
532 | delay = OTG_SCHEDULE_DELAY; | ||
533 | dev_dbg(&rport->phy->dev, "%s otg sm work\n", | ||
534 | usb_otg_state_string(rport->state)); | ||
535 | |||
536 | switch (rport->state) { | ||
537 | case OTG_STATE_UNDEFINED: | ||
538 | rport->state = OTG_STATE_B_IDLE; | ||
539 | if (!vbus_attach) | ||
540 | rockchip_usb2phy_power_off(rport->phy); | ||
541 | /* fall through */ | ||
542 | case OTG_STATE_B_IDLE: | ||
543 | if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) { | ||
544 | dev_dbg(&rport->phy->dev, "usb otg host connect\n"); | ||
545 | rport->state = OTG_STATE_A_HOST; | ||
546 | rockchip_usb2phy_power_on(rport->phy); | ||
547 | return; | ||
548 | } else if (vbus_attach) { | ||
549 | dev_dbg(&rport->phy->dev, "vbus_attach\n"); | ||
550 | switch (rphy->chg_state) { | ||
551 | case USB_CHG_STATE_UNDEFINED: | ||
552 | schedule_delayed_work(&rport->chg_work, 0); | ||
553 | return; | ||
554 | case USB_CHG_STATE_DETECTED: | ||
555 | switch (rphy->chg_type) { | ||
556 | case POWER_SUPPLY_TYPE_USB: | ||
557 | dev_dbg(&rport->phy->dev, | ||
558 | "sdp cable is connecetd\n"); | ||
559 | rockchip_usb2phy_power_on(rport->phy); | ||
560 | rport->state = OTG_STATE_B_PERIPHERAL; | ||
561 | notify_charger = true; | ||
562 | sch_work = true; | ||
563 | cable = EXTCON_CHG_USB_SDP; | ||
564 | break; | ||
565 | case POWER_SUPPLY_TYPE_USB_DCP: | ||
566 | dev_dbg(&rport->phy->dev, | ||
567 | "dcp cable is connecetd\n"); | ||
568 | rockchip_usb2phy_power_off(rport->phy); | ||
569 | notify_charger = true; | ||
570 | sch_work = true; | ||
571 | cable = EXTCON_CHG_USB_DCP; | ||
572 | break; | ||
573 | case POWER_SUPPLY_TYPE_USB_CDP: | ||
574 | dev_dbg(&rport->phy->dev, | ||
575 | "cdp cable is connecetd\n"); | ||
576 | rockchip_usb2phy_power_on(rport->phy); | ||
577 | rport->state = OTG_STATE_B_PERIPHERAL; | ||
578 | notify_charger = true; | ||
579 | sch_work = true; | ||
580 | cable = EXTCON_CHG_USB_CDP; | ||
581 | break; | ||
582 | default: | ||
583 | break; | ||
584 | } | ||
585 | break; | ||
586 | default: | ||
587 | break; | ||
588 | } | ||
589 | } else { | ||
590 | notify_charger = true; | ||
591 | rphy->chg_state = USB_CHG_STATE_UNDEFINED; | ||
592 | rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; | ||
593 | } | ||
594 | |||
595 | if (rport->vbus_attached != vbus_attach) { | ||
596 | rport->vbus_attached = vbus_attach; | ||
597 | |||
598 | if (notify_charger && rphy->edev) | ||
599 | extcon_set_cable_state_(rphy->edev, | ||
600 | cable, vbus_attach); | ||
601 | } | ||
602 | break; | ||
603 | case OTG_STATE_B_PERIPHERAL: | ||
604 | if (!vbus_attach) { | ||
605 | dev_dbg(&rport->phy->dev, "usb disconnect\n"); | ||
606 | rphy->chg_state = USB_CHG_STATE_UNDEFINED; | ||
607 | rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; | ||
608 | rport->state = OTG_STATE_B_IDLE; | ||
609 | delay = 0; | ||
610 | rockchip_usb2phy_power_off(rport->phy); | ||
611 | } | ||
612 | sch_work = true; | ||
613 | break; | ||
614 | case OTG_STATE_A_HOST: | ||
615 | if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) { | ||
616 | dev_dbg(&rport->phy->dev, "usb otg host disconnect\n"); | ||
617 | rport->state = OTG_STATE_B_IDLE; | ||
618 | rockchip_usb2phy_power_off(rport->phy); | ||
619 | } | ||
620 | break; | ||
621 | default: | ||
622 | break; | ||
623 | } | ||
624 | |||
625 | if (sch_work) | ||
626 | schedule_delayed_work(&rport->otg_sm_work, delay); | ||
627 | } | ||
628 | |||
629 | static const char *chg_to_string(enum power_supply_type chg_type) | ||
630 | { | ||
631 | switch (chg_type) { | ||
632 | case POWER_SUPPLY_TYPE_USB: | ||
633 | return "USB_SDP_CHARGER"; | ||
634 | case POWER_SUPPLY_TYPE_USB_DCP: | ||
635 | return "USB_DCP_CHARGER"; | ||
636 | case POWER_SUPPLY_TYPE_USB_CDP: | ||
637 | return "USB_CDP_CHARGER"; | ||
638 | default: | ||
639 | return "INVALID_CHARGER"; | ||
640 | } | ||
641 | } | ||
642 | |||
643 | static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy, | ||
644 | bool en) | ||
645 | { | ||
646 | property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); | ||
647 | property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en); | ||
648 | } | ||
649 | |||
650 | static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy, | ||
651 | bool en) | ||
652 | { | ||
653 | property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en); | ||
654 | property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en); | ||
655 | } | ||
656 | |||
657 | static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy, | ||
658 | bool en) | ||
659 | { | ||
660 | property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en); | ||
661 | property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en); | ||
662 | } | ||
663 | |||
664 | #define CHG_DCD_POLL_TIME (100 * HZ / 1000) | ||
665 | #define CHG_DCD_MAX_RETRIES 6 | ||
666 | #define CHG_PRIMARY_DET_TIME (40 * HZ / 1000) | ||
667 | #define CHG_SECONDARY_DET_TIME (40 * HZ / 1000) | ||
668 | static void rockchip_chg_detect_work(struct work_struct *work) | ||
669 | { | ||
670 | struct rockchip_usb2phy_port *rport = | ||
671 | container_of(work, struct rockchip_usb2phy_port, chg_work.work); | ||
672 | struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); | ||
673 | bool is_dcd, tmout, vout; | ||
674 | unsigned long delay; | ||
675 | |||
676 | dev_dbg(&rport->phy->dev, "chg detection work state = %d\n", | ||
677 | rphy->chg_state); | ||
678 | switch (rphy->chg_state) { | ||
679 | case USB_CHG_STATE_UNDEFINED: | ||
680 | if (!rport->suspended) | ||
681 | rockchip_usb2phy_power_off(rport->phy); | ||
682 | /* put the controller in non-driving mode */ | ||
683 | property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false); | ||
684 | /* Start DCD processing stage 1 */ | ||
685 | rockchip_chg_enable_dcd(rphy, true); | ||
686 | rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; | ||
687 | rphy->dcd_retries = 0; | ||
688 | delay = CHG_DCD_POLL_TIME; | ||
689 | break; | ||
690 | case USB_CHG_STATE_WAIT_FOR_DCD: | ||
691 | /* get data contact detection status */ | ||
692 | is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det); | ||
693 | tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES; | ||
694 | /* stage 2 */ | ||
695 | if (is_dcd || tmout) { | ||
696 | /* stage 4 */ | ||
697 | /* Turn off DCD circuitry */ | ||
698 | rockchip_chg_enable_dcd(rphy, false); | ||
699 | /* Voltage Source on DP, Probe on DM */ | ||
700 | rockchip_chg_enable_primary_det(rphy, true); | ||
701 | delay = CHG_PRIMARY_DET_TIME; | ||
702 | rphy->chg_state = USB_CHG_STATE_DCD_DONE; | ||
703 | } else { | ||
704 | /* stage 3 */ | ||
705 | delay = CHG_DCD_POLL_TIME; | ||
706 | } | ||
707 | break; | ||
708 | case USB_CHG_STATE_DCD_DONE: | ||
709 | vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det); | ||
710 | rockchip_chg_enable_primary_det(rphy, false); | ||
711 | if (vout) { | ||
712 | /* Voltage Source on DM, Probe on DP */ | ||
713 | rockchip_chg_enable_secondary_det(rphy, true); | ||
714 | delay = CHG_SECONDARY_DET_TIME; | ||
715 | rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE; | ||
716 | } else { | ||
717 | if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) { | ||
718 | /* floating charger found */ | ||
719 | rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; | ||
720 | rphy->chg_state = USB_CHG_STATE_DETECTED; | ||
721 | delay = 0; | ||
722 | } else { | ||
723 | rphy->chg_type = POWER_SUPPLY_TYPE_USB; | ||
724 | rphy->chg_state = USB_CHG_STATE_DETECTED; | ||
725 | delay = 0; | ||
726 | } | ||
727 | } | ||
728 | break; | ||
729 | case USB_CHG_STATE_PRIMARY_DONE: | ||
730 | vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det); | ||
731 | /* Turn off voltage source */ | ||
732 | rockchip_chg_enable_secondary_det(rphy, false); | ||
733 | if (vout) | ||
734 | rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; | ||
735 | else | ||
736 | rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; | ||
737 | /* fall through */ | ||
738 | case USB_CHG_STATE_SECONDARY_DONE: | ||
739 | rphy->chg_state = USB_CHG_STATE_DETECTED; | ||
740 | delay = 0; | ||
741 | /* fall through */ | ||
742 | case USB_CHG_STATE_DETECTED: | ||
743 | /* put the controller in normal mode */ | ||
744 | property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true); | ||
745 | rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); | ||
746 | dev_info(&rport->phy->dev, "charger = %s\n", | ||
747 | chg_to_string(rphy->chg_type)); | ||
748 | return; | ||
749 | default: | ||
750 | return; | ||
751 | } | ||
752 | |||
753 | schedule_delayed_work(&rport->chg_work, delay); | ||
754 | } | ||
755 | |||
357 | /* | 756 | /* |
358 | * The function manage host-phy port state and suspend/resume phy port | 757 | * The function manage host-phy port state and suspend/resume phy port |
359 | * to save power. | 758 | * to save power. |
@@ -485,6 +884,26 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data) | |||
485 | return IRQ_HANDLED; | 884 | return IRQ_HANDLED; |
486 | } | 885 | } |
487 | 886 | ||
887 | static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data) | ||
888 | { | ||
889 | struct rockchip_usb2phy_port *rport = data; | ||
890 | struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); | ||
891 | |||
892 | if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st)) | ||
893 | return IRQ_NONE; | ||
894 | |||
895 | mutex_lock(&rport->mutex); | ||
896 | |||
897 | /* clear bvalid detect irq pending status */ | ||
898 | property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true); | ||
899 | |||
900 | mutex_unlock(&rport->mutex); | ||
901 | |||
902 | rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); | ||
903 | |||
904 | return IRQ_HANDLED; | ||
905 | } | ||
906 | |||
488 | static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy, | 907 | static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy, |
489 | struct rockchip_usb2phy_port *rport, | 908 | struct rockchip_usb2phy_port *rport, |
490 | struct device_node *child_np) | 909 | struct device_node *child_np) |
@@ -509,13 +928,86 @@ static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy, | |||
509 | IRQF_ONESHOT, | 928 | IRQF_ONESHOT, |
510 | "rockchip_usb2phy", rport); | 929 | "rockchip_usb2phy", rport); |
511 | if (ret) { | 930 | if (ret) { |
512 | dev_err(rphy->dev, "failed to request irq handle\n"); | 931 | dev_err(rphy->dev, "failed to request linestate irq handle\n"); |
513 | return ret; | 932 | return ret; |
514 | } | 933 | } |
515 | 934 | ||
516 | return 0; | 935 | return 0; |
517 | } | 936 | } |
518 | 937 | ||
938 | static int rockchip_otg_event(struct notifier_block *nb, | ||
939 | unsigned long event, void *ptr) | ||
940 | { | ||
941 | struct rockchip_usb2phy_port *rport = | ||
942 | container_of(nb, struct rockchip_usb2phy_port, event_nb); | ||
943 | |||
944 | schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY); | ||
945 | |||
946 | return NOTIFY_DONE; | ||
947 | } | ||
948 | |||
949 | static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, | ||
950 | struct rockchip_usb2phy_port *rport, | ||
951 | struct device_node *child_np) | ||
952 | { | ||
953 | int ret; | ||
954 | |||
955 | rport->port_id = USB2PHY_PORT_OTG; | ||
956 | rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; | ||
957 | rport->state = OTG_STATE_UNDEFINED; | ||
958 | |||
959 | /* | ||
960 | * set suspended flag to true, but actually don't | ||
961 | * put phy in suspend mode, it aims to enable usb | ||
962 | * phy and clock in power_on() called by usb controller | ||
963 | * driver during probe. | ||
964 | */ | ||
965 | rport->suspended = true; | ||
966 | rport->vbus_attached = false; | ||
967 | |||
968 | mutex_init(&rport->mutex); | ||
969 | |||
970 | rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1); | ||
971 | if (rport->mode == USB_DR_MODE_HOST) { | ||
972 | ret = 0; | ||
973 | goto out; | ||
974 | } | ||
975 | |||
976 | INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work); | ||
977 | INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work); | ||
978 | |||
979 | rport->utmi_avalid = | ||
980 | of_property_read_bool(child_np, "rockchip,utmi-avalid"); | ||
981 | |||
982 | rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); | ||
983 | if (rport->bvalid_irq < 0) { | ||
984 | dev_err(rphy->dev, "no vbus valid irq provided\n"); | ||
985 | ret = rport->bvalid_irq; | ||
986 | goto out; | ||
987 | } | ||
988 | |||
989 | ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL, | ||
990 | rockchip_usb2phy_bvalid_irq, | ||
991 | IRQF_ONESHOT, | ||
992 | "rockchip_usb2phy_bvalid", rport); | ||
993 | if (ret) { | ||
994 | dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n"); | ||
995 | goto out; | ||
996 | } | ||
997 | |||
998 | if (!IS_ERR(rphy->edev)) { | ||
999 | rport->event_nb.notifier_call = rockchip_otg_event; | ||
1000 | |||
1001 | ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST, | ||
1002 | &rport->event_nb); | ||
1003 | if (ret) | ||
1004 | dev_err(rphy->dev, "register USB HOST notifier failed\n"); | ||
1005 | } | ||
1006 | |||
1007 | out: | ||
1008 | return ret; | ||
1009 | } | ||
1010 | |||
519 | static int rockchip_usb2phy_probe(struct platform_device *pdev) | 1011 | static int rockchip_usb2phy_probe(struct platform_device *pdev) |
520 | { | 1012 | { |
521 | struct device *dev = &pdev->dev; | 1013 | struct device *dev = &pdev->dev; |
@@ -553,8 +1045,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) | |||
553 | 1045 | ||
554 | rphy->dev = dev; | 1046 | rphy->dev = dev; |
555 | phy_cfgs = match->data; | 1047 | phy_cfgs = match->data; |
1048 | rphy->chg_state = USB_CHG_STATE_UNDEFINED; | ||
1049 | rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; | ||
556 | platform_set_drvdata(pdev, rphy); | 1050 | platform_set_drvdata(pdev, rphy); |
557 | 1051 | ||
1052 | ret = rockchip_usb2phy_extcon_register(rphy); | ||
1053 | if (ret) | ||
1054 | return ret; | ||
1055 | |||
558 | /* find out a proper config which can be matched with dt. */ | 1056 | /* find out a proper config which can be matched with dt. */ |
559 | index = 0; | 1057 | index = 0; |
560 | while (phy_cfgs[index].reg) { | 1058 | while (phy_cfgs[index].reg) { |
@@ -591,13 +1089,9 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) | |||
591 | struct rockchip_usb2phy_port *rport = &rphy->ports[index]; | 1089 | struct rockchip_usb2phy_port *rport = &rphy->ports[index]; |
592 | struct phy *phy; | 1090 | struct phy *phy; |
593 | 1091 | ||
594 | /* | 1092 | /* This driver aims to support both otg-port and host-port */ |
595 | * This driver aim to support both otg-port and host-port, | 1093 | if (of_node_cmp(child_np->name, "host-port") && |
596 | * but unfortunately, the otg part is not ready in current, | 1094 | of_node_cmp(child_np->name, "otg-port")) |
597 | * so this comments and below codes are interim, which should | ||
598 | * be changed after otg-port is supplied soon. | ||
599 | */ | ||
600 | if (of_node_cmp(child_np->name, "host-port")) | ||
601 | goto next_child; | 1095 | goto next_child; |
602 | 1096 | ||
603 | phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops); | 1097 | phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops); |
@@ -610,9 +1104,18 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) | |||
610 | rport->phy = phy; | 1104 | rport->phy = phy; |
611 | phy_set_drvdata(rport->phy, rport); | 1105 | phy_set_drvdata(rport->phy, rport); |
612 | 1106 | ||
613 | ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np); | 1107 | /* initialize otg/host port separately */ |
614 | if (ret) | 1108 | if (!of_node_cmp(child_np->name, "host-port")) { |
615 | goto put_child; | 1109 | ret = rockchip_usb2phy_host_port_init(rphy, rport, |
1110 | child_np); | ||
1111 | if (ret) | ||
1112 | goto put_child; | ||
1113 | } else { | ||
1114 | ret = rockchip_usb2phy_otg_port_init(rphy, rport, | ||
1115 | child_np); | ||
1116 | if (ret) | ||
1117 | goto put_child; | ||
1118 | } | ||
616 | 1119 | ||
617 | next_child: | 1120 | next_child: |
618 | /* to prevent out of boundary */ | 1121 | /* to prevent out of boundary */ |
@@ -654,10 +1157,18 @@ static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = { | |||
654 | 1157 | ||
655 | static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { | 1158 | static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { |
656 | { | 1159 | { |
657 | .reg = 0xe450, | 1160 | .reg = 0xe450, |
658 | .num_ports = 2, | 1161 | .num_ports = 2, |
659 | .clkout_ctl = { 0xe450, 4, 4, 1, 0 }, | 1162 | .clkout_ctl = { 0xe450, 4, 4, 1, 0 }, |
660 | .port_cfgs = { | 1163 | .port_cfgs = { |
1164 | [USB2PHY_PORT_OTG] = { | ||
1165 | .phy_sus = { 0xe454, 1, 0, 2, 1 }, | ||
1166 | .bvalid_det_en = { 0xe3c0, 3, 3, 0, 1 }, | ||
1167 | .bvalid_det_st = { 0xe3e0, 3, 3, 0, 1 }, | ||
1168 | .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 }, | ||
1169 | .utmi_avalid = { 0xe2ac, 7, 7, 0, 1 }, | ||
1170 | .utmi_bvalid = { 0xe2ac, 12, 12, 0, 1 }, | ||
1171 | }, | ||
661 | [USB2PHY_PORT_HOST] = { | 1172 | [USB2PHY_PORT_HOST] = { |
662 | .phy_sus = { 0xe458, 1, 0, 0x2, 0x1 }, | 1173 | .phy_sus = { 0xe458, 1, 0, 0x2, 0x1 }, |
663 | .ls_det_en = { 0xe3c0, 6, 6, 0, 1 }, | 1174 | .ls_det_en = { 0xe3c0, 6, 6, 0, 1 }, |
@@ -667,12 +1178,32 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { | |||
667 | .utmi_hstdet = { 0xe2ac, 23, 23, 0, 1 } | 1178 | .utmi_hstdet = { 0xe2ac, 23, 23, 0, 1 } |
668 | } | 1179 | } |
669 | }, | 1180 | }, |
1181 | .chg_det = { | ||
1182 | .opmode = { 0xe454, 3, 0, 5, 1 }, | ||
1183 | .cp_det = { 0xe2ac, 2, 2, 0, 1 }, | ||
1184 | .dcp_det = { 0xe2ac, 1, 1, 0, 1 }, | ||
1185 | .dp_det = { 0xe2ac, 0, 0, 0, 1 }, | ||
1186 | .idm_sink_en = { 0xe450, 8, 8, 0, 1 }, | ||
1187 | .idp_sink_en = { 0xe450, 7, 7, 0, 1 }, | ||
1188 | .idp_src_en = { 0xe450, 9, 9, 0, 1 }, | ||
1189 | .rdm_pdwn_en = { 0xe450, 10, 10, 0, 1 }, | ||
1190 | .vdm_src_en = { 0xe450, 12, 12, 0, 1 }, | ||
1191 | .vdp_src_en = { 0xe450, 11, 11, 0, 1 }, | ||
1192 | }, | ||
670 | }, | 1193 | }, |
671 | { | 1194 | { |
672 | .reg = 0xe460, | 1195 | .reg = 0xe460, |
673 | .num_ports = 2, | 1196 | .num_ports = 2, |
674 | .clkout_ctl = { 0xe460, 4, 4, 1, 0 }, | 1197 | .clkout_ctl = { 0xe460, 4, 4, 1, 0 }, |
675 | .port_cfgs = { | 1198 | .port_cfgs = { |
1199 | [USB2PHY_PORT_OTG] = { | ||
1200 | .phy_sus = { 0xe464, 1, 0, 2, 1 }, | ||
1201 | .bvalid_det_en = { 0xe3c0, 8, 8, 0, 1 }, | ||
1202 | .bvalid_det_st = { 0xe3e0, 8, 8, 0, 1 }, | ||
1203 | .bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 }, | ||
1204 | .utmi_avalid = { 0xe2ac, 10, 10, 0, 1 }, | ||
1205 | .utmi_bvalid = { 0xe2ac, 16, 16, 0, 1 }, | ||
1206 | }, | ||
676 | [USB2PHY_PORT_HOST] = { | 1207 | [USB2PHY_PORT_HOST] = { |
677 | .phy_sus = { 0xe468, 1, 0, 0x2, 0x1 }, | 1208 | .phy_sus = { 0xe468, 1, 0, 0x2, 0x1 }, |
678 | .ls_det_en = { 0xe3c0, 11, 11, 0, 1 }, | 1209 | .ls_det_en = { 0xe3c0, 11, 11, 0, 1 }, |
diff --git a/drivers/phy/phy-s5pv210-usb2.c b/drivers/phy/phy-s5pv210-usb2.c index 004d320767e4..f6f72339bbc3 100644 --- a/drivers/phy/phy-s5pv210-usb2.c +++ b/drivers/phy/phy-s5pv210-usb2.c | |||
@@ -103,7 +103,7 @@ static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on) | |||
103 | break; | 103 | break; |
104 | default: | 104 | default: |
105 | return; | 105 | return; |
106 | }; | 106 | } |
107 | 107 | ||
108 | regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET, | 108 | regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET, |
109 | mask, on ? 0 : mask); | 109 | mask, on ? 0 : mask); |
@@ -127,7 +127,7 @@ static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | |||
127 | rstbits = S5PV210_URSTCON_PHY1_ALL | | 127 | rstbits = S5PV210_URSTCON_PHY1_ALL | |
128 | S5PV210_URSTCON_HOST_LINK_ALL; | 128 | S5PV210_URSTCON_HOST_LINK_ALL; |
129 | break; | 129 | break; |
130 | }; | 130 | } |
131 | 131 | ||
132 | if (on) { | 132 | if (on) { |
133 | writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK); | 133 | writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK); |
diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c deleted file mode 100644 index 0ac74639ad02..000000000000 --- a/drivers/phy/phy-stih41x-usb.c +++ /dev/null | |||
@@ -1,188 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics | ||
3 | * | ||
4 | * STMicroelectronics PHY driver for STiH41x USB. | ||
5 | * | ||
6 | * Author: Maxime Coquelin <maxime.coquelin@st.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2, as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/phy/phy.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/mfd/syscon.h> | ||
24 | |||
25 | #define SYSCFG332 0x80 | ||
26 | #define SYSCFG2520 0x820 | ||
27 | |||
28 | /** | ||
29 | * struct stih41x_usb_cfg - SoC specific PHY register mapping | ||
30 | * @syscfg: Offset in syscfg registers bank | ||
31 | * @cfg_mask: Bits mask for PHY configuration | ||
32 | * @cfg: Static configuration value for PHY | ||
33 | * @oscok: Notify the PHY oscillator clock is ready | ||
34 | * Setting this bit enable the PHY | ||
35 | */ | ||
36 | struct stih41x_usb_cfg { | ||
37 | u32 syscfg; | ||
38 | u32 cfg_mask; | ||
39 | u32 cfg; | ||
40 | u32 oscok; | ||
41 | }; | ||
42 | |||
43 | /** | ||
44 | * struct stih41x_usb_phy - Private data for the PHY | ||
45 | * @dev: device for this controller | ||
46 | * @regmap: Syscfg registers bank in which PHY is configured | ||
47 | * @cfg: SoC specific PHY register mapping | ||
48 | * @clk: Oscillator used by the PHY | ||
49 | */ | ||
50 | struct stih41x_usb_phy { | ||
51 | struct device *dev; | ||
52 | struct regmap *regmap; | ||
53 | const struct stih41x_usb_cfg *cfg; | ||
54 | struct clk *clk; | ||
55 | }; | ||
56 | |||
57 | static struct stih41x_usb_cfg stih415_usb_phy_cfg = { | ||
58 | .syscfg = SYSCFG332, | ||
59 | .cfg_mask = 0x3f, | ||
60 | .cfg = 0x38, | ||
61 | .oscok = BIT(6), | ||
62 | }; | ||
63 | |||
64 | static struct stih41x_usb_cfg stih416_usb_phy_cfg = { | ||
65 | .syscfg = SYSCFG2520, | ||
66 | .cfg_mask = 0x33f, | ||
67 | .cfg = 0x238, | ||
68 | .oscok = BIT(6), | ||
69 | }; | ||
70 | |||
71 | static int stih41x_usb_phy_init(struct phy *phy) | ||
72 | { | ||
73 | struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); | ||
74 | |||
75 | return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, | ||
76 | phy_dev->cfg->cfg_mask, phy_dev->cfg->cfg); | ||
77 | } | ||
78 | |||
79 | static int stih41x_usb_phy_power_on(struct phy *phy) | ||
80 | { | ||
81 | struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); | ||
82 | int ret; | ||
83 | |||
84 | ret = clk_prepare_enable(phy_dev->clk); | ||
85 | if (ret) { | ||
86 | dev_err(phy_dev->dev, "Failed to enable osc_phy clock\n"); | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, | ||
91 | phy_dev->cfg->oscok, phy_dev->cfg->oscok); | ||
92 | if (ret) | ||
93 | clk_disable_unprepare(phy_dev->clk); | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | static int stih41x_usb_phy_power_off(struct phy *phy) | ||
99 | { | ||
100 | struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); | ||
101 | int ret; | ||
102 | |||
103 | ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, | ||
104 | phy_dev->cfg->oscok, 0); | ||
105 | if (ret) { | ||
106 | dev_err(phy_dev->dev, "Failed to clear oscok bit\n"); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | clk_disable_unprepare(phy_dev->clk); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static const struct phy_ops stih41x_usb_phy_ops = { | ||
116 | .init = stih41x_usb_phy_init, | ||
117 | .power_on = stih41x_usb_phy_power_on, | ||
118 | .power_off = stih41x_usb_phy_power_off, | ||
119 | .owner = THIS_MODULE, | ||
120 | }; | ||
121 | |||
122 | static const struct of_device_id stih41x_usb_phy_of_match[]; | ||
123 | |||
124 | static int stih41x_usb_phy_probe(struct platform_device *pdev) | ||
125 | { | ||
126 | struct device_node *np = pdev->dev.of_node; | ||
127 | const struct of_device_id *match; | ||
128 | struct stih41x_usb_phy *phy_dev; | ||
129 | struct device *dev = &pdev->dev; | ||
130 | struct phy_provider *phy_provider; | ||
131 | struct phy *phy; | ||
132 | |||
133 | phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); | ||
134 | if (!phy_dev) | ||
135 | return -ENOMEM; | ||
136 | |||
137 | match = of_match_device(stih41x_usb_phy_of_match, &pdev->dev); | ||
138 | if (!match) | ||
139 | return -ENODEV; | ||
140 | |||
141 | phy_dev->cfg = match->data; | ||
142 | |||
143 | phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | ||
144 | if (IS_ERR(phy_dev->regmap)) { | ||
145 | dev_err(dev, "No syscfg phandle specified\n"); | ||
146 | return PTR_ERR(phy_dev->regmap); | ||
147 | } | ||
148 | |||
149 | phy_dev->clk = devm_clk_get(dev, "osc_phy"); | ||
150 | if (IS_ERR(phy_dev->clk)) { | ||
151 | dev_err(dev, "osc_phy clk not found\n"); | ||
152 | return PTR_ERR(phy_dev->clk); | ||
153 | } | ||
154 | |||
155 | phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops); | ||
156 | |||
157 | if (IS_ERR(phy)) { | ||
158 | dev_err(dev, "failed to create phy\n"); | ||
159 | return PTR_ERR(phy); | ||
160 | } | ||
161 | |||
162 | phy_dev->dev = dev; | ||
163 | |||
164 | phy_set_drvdata(phy, phy_dev); | ||
165 | |||
166 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
167 | return PTR_ERR_OR_ZERO(phy_provider); | ||
168 | } | ||
169 | |||
170 | static const struct of_device_id stih41x_usb_phy_of_match[] = { | ||
171 | { .compatible = "st,stih415-usb-phy", .data = &stih415_usb_phy_cfg }, | ||
172 | { .compatible = "st,stih416-usb-phy", .data = &stih416_usb_phy_cfg }, | ||
173 | { /* sentinel */ }, | ||
174 | }; | ||
175 | MODULE_DEVICE_TABLE(of, stih41x_usb_phy_of_match); | ||
176 | |||
177 | static struct platform_driver stih41x_usb_phy_driver = { | ||
178 | .probe = stih41x_usb_phy_probe, | ||
179 | .driver = { | ||
180 | .name = "stih41x-usb-phy", | ||
181 | .of_match_table = stih41x_usb_phy_of_match, | ||
182 | } | ||
183 | }; | ||
184 | module_platform_driver(stih41x_usb_phy_driver); | ||
185 | |||
186 | MODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@st.com>"); | ||
187 | MODULE_DESCRIPTION("STMicroelectronics USB PHY driver for STiH41x series"); | ||
188 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index fec34f5213c4..bf28a0fdd569 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c | |||
@@ -436,25 +436,31 @@ static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode) | |||
436 | { | 436 | { |
437 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); | 437 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); |
438 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); | 438 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); |
439 | int new_mode; | ||
439 | 440 | ||
440 | if (phy->index != 0) | 441 | if (phy->index != 0) |
441 | return -EINVAL; | 442 | return -EINVAL; |
442 | 443 | ||
443 | switch (mode) { | 444 | switch (mode) { |
444 | case PHY_MODE_USB_HOST: | 445 | case PHY_MODE_USB_HOST: |
445 | data->dr_mode = USB_DR_MODE_HOST; | 446 | new_mode = USB_DR_MODE_HOST; |
446 | break; | 447 | break; |
447 | case PHY_MODE_USB_DEVICE: | 448 | case PHY_MODE_USB_DEVICE: |
448 | data->dr_mode = USB_DR_MODE_PERIPHERAL; | 449 | new_mode = USB_DR_MODE_PERIPHERAL; |
449 | break; | 450 | break; |
450 | case PHY_MODE_USB_OTG: | 451 | case PHY_MODE_USB_OTG: |
451 | data->dr_mode = USB_DR_MODE_OTG; | 452 | new_mode = USB_DR_MODE_OTG; |
452 | break; | 453 | break; |
453 | default: | 454 | default: |
454 | return -EINVAL; | 455 | return -EINVAL; |
455 | } | 456 | } |
456 | 457 | ||
457 | dev_info(&_phy->dev, "Changing dr_mode to %d\n", (int)data->dr_mode); | 458 | if (new_mode != data->dr_mode) { |
459 | dev_info(&_phy->dev, "Changing dr_mode to %d\n", new_mode); | ||
460 | data->dr_mode = new_mode; | ||
461 | } | ||
462 | |||
463 | data->id_det = -1; /* Force reprocessing of id */ | ||
458 | data->force_session_end = true; | 464 | data->force_session_end = true; |
459 | queue_delayed_work(system_wq, &data->detect, 0); | 465 | queue_delayed_work(system_wq, &data->detect, 0); |
460 | 466 | ||
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index bf46844dc387..9c84d32c6f60 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c | |||
@@ -537,10 +537,7 @@ static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy) | |||
537 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 537 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
538 | "pll_ctrl"); | 538 | "pll_ctrl"); |
539 | phy->pll_ctrl_base = devm_ioremap_resource(dev, res); | 539 | phy->pll_ctrl_base = devm_ioremap_resource(dev, res); |
540 | if (IS_ERR(phy->pll_ctrl_base)) | 540 | return PTR_ERR_OR_ZERO(phy->pll_ctrl_base); |
541 | return PTR_ERR(phy->pll_ctrl_base); | ||
542 | |||
543 | return 0; | ||
544 | } | 541 | } |
545 | 542 | ||
546 | static int ti_pipe3_probe(struct platform_device *pdev) | 543 | static int ti_pipe3_probe(struct platform_device *pdev) |
@@ -592,10 +589,7 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
592 | ti_pipe3_power_off(generic_phy); | 589 | ti_pipe3_power_off(generic_phy); |
593 | 590 | ||
594 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | 591 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); |
595 | if (IS_ERR(phy_provider)) | 592 | return PTR_ERR_OR_ZERO(phy_provider); |
596 | return PTR_ERR(phy_provider); | ||
597 | |||
598 | return 0; | ||
599 | } | 593 | } |
600 | 594 | ||
601 | static int ti_pipe3_remove(struct platform_device *pdev) | 595 | static int ti_pipe3_remove(struct platform_device *pdev) |
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 547ca7b3f098..2990b3965460 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c | |||
@@ -317,6 +317,9 @@ static enum musb_vbus_id_status | |||
317 | linkstat = MUSB_VBUS_OFF; | 317 | linkstat = MUSB_VBUS_OFF; |
318 | } | 318 | } |
319 | 319 | ||
320 | kobject_uevent(&twl->dev->kobj, linkstat == MUSB_VBUS_VALID | ||
321 | ? KOBJ_ONLINE : KOBJ_OFFLINE); | ||
322 | |||
320 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", | 323 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", |
321 | status, status, linkstat); | 324 | status, status, linkstat); |
322 | 325 | ||
diff --git a/drivers/phy/tegra/xusb-tegra124.c b/drivers/phy/tegra/xusb-tegra124.c index 119957249a51..c45cbedc6634 100644 --- a/drivers/phy/tegra/xusb-tegra124.c +++ b/drivers/phy/tegra/xusb-tegra124.c | |||
@@ -1483,7 +1483,6 @@ static int tegra124_usb3_port_enable(struct tegra_xusb_port *port) | |||
1483 | struct tegra_xusb_padctl *padctl = port->padctl; | 1483 | struct tegra_xusb_padctl *padctl = port->padctl; |
1484 | struct tegra_xusb_lane *lane = usb3->base.lane; | 1484 | struct tegra_xusb_lane *lane = usb3->base.lane; |
1485 | unsigned int index = port->index, offset; | 1485 | unsigned int index = port->index, offset; |
1486 | int ret = 0; | ||
1487 | u32 value; | 1486 | u32 value; |
1488 | 1487 | ||
1489 | value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); | 1488 | value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); |
@@ -1612,7 +1611,7 @@ static int tegra124_usb3_port_enable(struct tegra_xusb_port *port) | |||
1612 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index); | 1611 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index); |
1613 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | 1612 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); |
1614 | 1613 | ||
1615 | return ret; | 1614 | return 0; |
1616 | } | 1615 | } |
1617 | 1616 | ||
1618 | static void tegra124_usb3_port_disable(struct tegra_xusb_port *port) | 1617 | static void tegra124_usb3_port_disable(struct tegra_xusb_port *port) |
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 873424ab0e32..3cbcb2537657 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c | |||
@@ -561,10 +561,7 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2) | |||
561 | usb2->internal = of_property_read_bool(np, "nvidia,internal"); | 561 | usb2->internal = of_property_read_bool(np, "nvidia,internal"); |
562 | 562 | ||
563 | usb2->supply = devm_regulator_get(&port->dev, "vbus"); | 563 | usb2->supply = devm_regulator_get(&port->dev, "vbus"); |
564 | if (IS_ERR(usb2->supply)) | 564 | return PTR_ERR_OR_ZERO(usb2->supply); |
565 | return PTR_ERR(usb2->supply); | ||
566 | |||
567 | return 0; | ||
568 | } | 565 | } |
569 | 566 | ||
570 | static int tegra_xusb_add_usb2_port(struct tegra_xusb_padctl *padctl, | 567 | static int tegra_xusb_add_usb2_port(struct tegra_xusb_padctl *padctl, |
@@ -731,10 +728,7 @@ static int tegra_xusb_usb3_port_parse_dt(struct tegra_xusb_usb3_port *usb3) | |||
731 | usb3->internal = of_property_read_bool(np, "nvidia,internal"); | 728 | usb3->internal = of_property_read_bool(np, "nvidia,internal"); |
732 | 729 | ||
733 | usb3->supply = devm_regulator_get(&port->dev, "vbus"); | 730 | usb3->supply = devm_regulator_get(&port->dev, "vbus"); |
734 | if (IS_ERR(usb3->supply)) | 731 | return PTR_ERR_OR_ZERO(usb3->supply); |
735 | return PTR_ERR(usb3->supply); | ||
736 | |||
737 | return 0; | ||
738 | } | 732 | } |
739 | 733 | ||
740 | static int tegra_xusb_add_usb3_port(struct tegra_xusb_padctl *padctl, | 734 | static int tegra_xusb_add_usb3_port(struct tegra_xusb_padctl *padctl, |