diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-12-26 20:01:18 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-12-26 20:01:18 -0500 |
commit | daf273350d96241752b00020940c07dc2cff2e0a (patch) | |
tree | c0a0557da09404455b6b4672fb9bd6f1147a8d16 | |
parent | f7dbd84fd49e487df68b3a95780c275d7da1891c (diff) | |
parent | 9955a7835bf376e12482583958b2661f501b868b (diff) |
Merge tag 'phy-for-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next
Kishon writes:
phy: for 4.5
*) new PHY driver for hi6220 usb and rcar gen3 usb2
*) deprecate phy-omap-control driver. phy-omap-control driver was added
when there was no proper infrastructure for doing control module
initialization. The phy-omap-control driver is not an 'actual' PHY
driver and it was just a hack to do PHY related control module
initialization. Now with SYSCON framework in the kernel, control
module setttings can be done using APIs provided by syscon.
*) usbphy-internal pll creates the needed 480MHz and is also a
supply-clock back to the core clock-controller in Rockchip SoCs.
This is now modeled as a real clock.
*) calibrate mt65xx usb3 PHY for better eye diagram and receiver
sensitivity.
*) Miscellaneous cleanups.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r-- | Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/phy-hi6220-usb.txt | 16 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt | 39 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 6 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/ti-phy.txt | 20 | ||||
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | drivers/phy/Kconfig | 20 | ||||
-rw-r--r-- | drivers/phy/Makefile | 2 | ||||
-rw-r--r-- | drivers/phy/phy-berlin-usb.c | 3 | ||||
-rw-r--r-- | drivers/phy/phy-brcmstb-sata.c | 47 | ||||
-rw-r--r-- | drivers/phy/phy-hi6220-usb.c | 168 | ||||
-rw-r--r-- | drivers/phy/phy-mt65xx-usb3.c | 106 | ||||
-rw-r--r-- | drivers/phy/phy-omap-usb2.c | 94 | ||||
-rw-r--r-- | drivers/phy/phy-rcar-gen3-usb2.c | 378 | ||||
-rw-r--r-- | drivers/phy/phy-rockchip-usb.c | 287 | ||||
-rw-r--r-- | drivers/phy/phy-sun4i-usb.c | 158 | ||||
-rw-r--r-- | drivers/phy/phy-ti-pipe3.c | 302 | ||||
-rw-r--r-- | include/linux/phy/omap_usb.h | 23 |
19 files changed, 1439 insertions, 238 deletions
diff --git a/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt b/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt index 7f81ef90146a..d87ab7c127b8 100644 --- a/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt +++ b/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: should be one or more of | 4 | - compatible: should be one or more of |
5 | "brcm,bcm7425-sata-phy" | ||
5 | "brcm,bcm7445-sata-phy" | 6 | "brcm,bcm7445-sata-phy" |
6 | "brcm,phy-sata3" | 7 | "brcm,phy-sata3" |
7 | - address-cells: should be 1 | 8 | - address-cells: should be 1 |
diff --git a/Documentation/devicetree/bindings/phy/phy-hi6220-usb.txt b/Documentation/devicetree/bindings/phy/phy-hi6220-usb.txt new file mode 100644 index 000000000000..f17a56e2152f --- /dev/null +++ b/Documentation/devicetree/bindings/phy/phy-hi6220-usb.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | Hisilicon hi6220 usb PHY | ||
2 | ----------------------- | ||
3 | |||
4 | Required properties: | ||
5 | - compatible: should be "hisilicon,hi6220-usb-phy" | ||
6 | - #phy-cells: must be 0 | ||
7 | - hisilicon,peripheral-syscon: phandle of syscon used to control phy. | ||
8 | Refer to phy/phy-bindings.txt for the generic PHY binding properties | ||
9 | |||
10 | Example: | ||
11 | usb_phy: usbphy { | ||
12 | compatible = "hisilicon,hi6220-usb-phy"; | ||
13 | #phy-cells = <0>; | ||
14 | phy-supply = <&fixed_5v_hub>; | ||
15 | hisilicon,peripheral-syscon = <&sys_ctrl>; | ||
16 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt new file mode 100644 index 000000000000..2390e4e9c84c --- /dev/null +++ b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt | |||
@@ -0,0 +1,39 @@ | |||
1 | * Renesas R-Car generation 3 USB 2.0 PHY | ||
2 | |||
3 | This file provides information on what the device node for the R-Car generation | ||
4 | 3 USB 2.0 PHY contains. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: "renesas,usb2-phy-r8a7795" if the device is a part of an R8A7795 | ||
8 | SoC. | ||
9 | - reg: offset and length of the partial USB 2.0 Host register block. | ||
10 | - reg-names: must be "usb2_host". | ||
11 | - clocks: clock phandle and specifier pair(s). | ||
12 | - #phy-cells: see phy-bindings.txt in the same directory, must be <0>. | ||
13 | |||
14 | Optional properties: | ||
15 | To use a USB channel where USB 2.0 Host and HSUSB (USB 2.0 Peripheral) are | ||
16 | combined, the device tree node should set HSUSB properties to reg and reg-names | ||
17 | properties. This is because HSUSB has registers to select USB 2.0 host or | ||
18 | peripheral at that channel: | ||
19 | - reg: offset and length of the partial HSUSB register block. | ||
20 | - reg-names: must be "hsusb". | ||
21 | - interrupts: interrupt specifier for the PHY. | ||
22 | |||
23 | Example (R-Car H3): | ||
24 | |||
25 | usb-phy@ee080200 { | ||
26 | compatible = "renesas,usb2-phy-r8a7795"; | ||
27 | reg = <0 0xee080200 0 0x700>, <0 0xe6590100 0 0x100>; | ||
28 | reg-names = "usb2_host", "hsusb"; | ||
29 | interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; | ||
30 | clocks = <&mstp7_clks R8A7795_CLK_EHCI0>, | ||
31 | <&mstp7_clks R8A7795_CLK_HSUSB>; | ||
32 | }; | ||
33 | |||
34 | usb-phy@ee0a0200 { | ||
35 | compatible = "renesas,usb2-phy-r8a7795"; | ||
36 | reg = <0 0xee0a0200 0 0x700>; | ||
37 | reg-names = "usb2_host"; | ||
38 | clocks = <&mstp7_clks R8A7795_CLK_EHCI0>; | ||
39 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt index 826454ac43bb..68498d560354 100644 --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | |||
@@ -1,7 +1,10 @@ | |||
1 | ROCKCHIP USB2 PHY | 1 | ROCKCHIP USB2 PHY |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: rockchip,rk3288-usb-phy | 4 | - compatible: matching the soc type, one of |
5 | "rockchip,rk3066a-usb-phy" | ||
6 | "rockchip,rk3188-usb-phy" | ||
7 | "rockchip,rk3288-usb-phy" | ||
5 | - rockchip,grf : phandle to the syscon managing the "general | 8 | - rockchip,grf : phandle to the syscon managing the "general |
6 | register files" | 9 | register files" |
7 | - #address-cells: should be 1 | 10 | - #address-cells: should be 1 |
@@ -21,6 +24,7 @@ required properties: | |||
21 | Optional Properties: | 24 | Optional Properties: |
22 | - clocks : phandle + clock specifier for the phy clocks | 25 | - clocks : phandle + clock specifier for the phy clocks |
23 | - clock-names: string, clock name, must be "phyclk" | 26 | - clock-names: string, clock name, must be "phyclk" |
27 | - #clock-cells: for users of the phy-pll, should be 0 | ||
24 | 28 | ||
25 | Example: | 29 | Example: |
26 | 30 | ||
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt index 0cebf7454517..95736d77fbb7 100644 --- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt | |||
@@ -9,6 +9,7 @@ Required properties: | |||
9 | * allwinner,sun7i-a20-usb-phy | 9 | * allwinner,sun7i-a20-usb-phy |
10 | * allwinner,sun8i-a23-usb-phy | 10 | * allwinner,sun8i-a23-usb-phy |
11 | * allwinner,sun8i-a33-usb-phy | 11 | * allwinner,sun8i-a33-usb-phy |
12 | * allwinner,sun8i-h3-usb-phy | ||
12 | - reg : a list of offset + length pairs | 13 | - reg : a list of offset + length pairs |
13 | - reg-names : | 14 | - reg-names : |
14 | * "phy_ctrl" | 15 | * "phy_ctrl" |
diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt index 9cf9446eaf2e..a3b394587874 100644 --- a/Documentation/devicetree/bindings/phy/ti-phy.txt +++ b/Documentation/devicetree/bindings/phy/ti-phy.txt | |||
@@ -31,6 +31,8 @@ OMAP USB2 PHY | |||
31 | 31 | ||
32 | Required properties: | 32 | Required properties: |
33 | - compatible: Should be "ti,omap-usb2" | 33 | - compatible: Should be "ti,omap-usb2" |
34 | Should be "ti,dra7x-usb2-phy2" for the 2nd instance of USB2 PHY | ||
35 | in DRA7x | ||
34 | - reg : Address and length of the register set for the device. | 36 | - reg : Address and length of the register set for the device. |
35 | - #phy-cells: determine the number of cells that should be given in the | 37 | - #phy-cells: determine the number of cells that should be given in the |
36 | phandle while referencing this phy. | 38 | phandle while referencing this phy. |
@@ -40,10 +42,14 @@ Required properties: | |||
40 | * "wkupclk" - wakeup clock. | 42 | * "wkupclk" - wakeup clock. |
41 | * "refclk" - reference clock (optional). | 43 | * "refclk" - reference clock (optional). |
42 | 44 | ||
43 | Optional properties: | 45 | Deprecated properties: |
44 | - ctrl-module : phandle of the control module used by PHY driver to power on | 46 | - ctrl-module : phandle of the control module used by PHY driver to power on |
45 | the PHY. | 47 | the PHY. |
46 | 48 | ||
49 | Recommended properies: | ||
50 | - syscon-phy-power : phandle/offset pair. Phandle to the system control | ||
51 | module and the register offset to power on/off the PHY. | ||
52 | |||
47 | This is usually a subnode of ocp2scp to which it is connected. | 53 | This is usually a subnode of ocp2scp to which it is connected. |
48 | 54 | ||
49 | usb2phy@4a0ad080 { | 55 | usb2phy@4a0ad080 { |
@@ -77,14 +83,22 @@ Required properties: | |||
77 | * "div-clk" - apll clock | 83 | * "div-clk" - apll clock |
78 | 84 | ||
79 | Optional properties: | 85 | Optional properties: |
80 | - ctrl-module : phandle of the control module used by PHY driver to power on | ||
81 | the PHY. | ||
82 | - id: If there are multiple instance of the same type, in order to | 86 | - id: If there are multiple instance of the same type, in order to |
83 | differentiate between each instance "id" can be used (e.g., multi-lane PCIe | 87 | differentiate between each instance "id" can be used (e.g., multi-lane PCIe |
84 | PHY). If "id" is not provided, it is set to default value of '1'. | 88 | PHY). If "id" is not provided, it is set to default value of '1'. |
85 | - syscon-pllreset: Handle to system control region that contains the | 89 | - syscon-pllreset: Handle to system control region that contains the |
86 | CTRL_CORE_SMA_SW_0 register and register offset to the CTRL_CORE_SMA_SW_0 | 90 | CTRL_CORE_SMA_SW_0 register and register offset to the CTRL_CORE_SMA_SW_0 |
87 | register that contains the SATA_PLL_SOFT_RESET bit. Only valid for sata_phy. | 91 | register that contains the SATA_PLL_SOFT_RESET bit. Only valid for sata_phy. |
92 | - syscon-pcs : phandle/offset pair. Phandle to the system control module and the | ||
93 | register offset to write the PCS delay value. | ||
94 | |||
95 | Deprecated properties: | ||
96 | - ctrl-module : phandle of the control module used by PHY driver to power on | ||
97 | the PHY. | ||
98 | |||
99 | Recommended properies: | ||
100 | - syscon-phy-power : phandle/offset pair. Phandle to the system control | ||
101 | module and the register offset to power on/off the PHY. | ||
88 | 102 | ||
89 | This is usually a subnode of ocp2scp to which it is connected. | 103 | This is usually a subnode of ocp2scp to which it is connected. |
90 | 104 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 233f83464814..f18cd5e41221 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8961,6 +8961,12 @@ L: linux-sh@vger.kernel.org | |||
8961 | F: drivers/net/ethernet/renesas/ | 8961 | F: drivers/net/ethernet/renesas/ |
8962 | F: include/linux/sh_eth.h | 8962 | F: include/linux/sh_eth.h |
8963 | 8963 | ||
8964 | RENESAS USB2 PHY DRIVER | ||
8965 | M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> | ||
8966 | L: linux-sh@vger.kernel.org | ||
8967 | S: Maintained | ||
8968 | F: drivers/phy/phy-rcar-gen3-usb2.c | ||
8969 | |||
8964 | RESET CONTROLLER FRAMEWORK | 8970 | RESET CONTROLLER FRAMEWORK |
8965 | M: Philipp Zabel <p.zabel@pengutronix.de> | 8971 | M: Philipp Zabel <p.zabel@pengutronix.de> |
8966 | S: Maintained | 8972 | S: Maintained |
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 03cb3ea2d2c0..e7e117d5dbbe 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -118,6 +118,13 @@ config PHY_RCAR_GEN2 | |||
118 | help | 118 | help |
119 | Support for USB PHY found on Renesas R-Car generation 2 SoCs. | 119 | Support for USB PHY found on Renesas R-Car generation 2 SoCs. |
120 | 120 | ||
121 | config PHY_RCAR_GEN3_USB2 | ||
122 | tristate "Renesas R-Car generation 3 USB 2.0 PHY driver" | ||
123 | depends on OF && ARCH_SHMOBILE | ||
124 | select GENERIC_PHY | ||
125 | help | ||
126 | Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs. | ||
127 | |||
121 | config OMAP_CONTROL_PHY | 128 | config OMAP_CONTROL_PHY |
122 | tristate "OMAP CONTROL PHY Driver" | 129 | tristate "OMAP CONTROL PHY Driver" |
123 | depends on ARCH_OMAP2PLUS || COMPILE_TEST | 130 | depends on ARCH_OMAP2PLUS || COMPILE_TEST |
@@ -215,6 +222,15 @@ config PHY_MT65XX_USB3 | |||
215 | for mt65xx SoCs. it supports two usb2.0 ports and | 222 | for mt65xx SoCs. it supports two usb2.0 ports and |
216 | one usb3.0 port. | 223 | one usb3.0 port. |
217 | 224 | ||
225 | config PHY_HI6220_USB | ||
226 | tristate "hi6220 USB PHY support" | ||
227 | select GENERIC_PHY | ||
228 | select MFD_SYSCON | ||
229 | help | ||
230 | Enable this to support the HISILICON HI6220 USB PHY. | ||
231 | |||
232 | To compile this driver as a module, choose M here. | ||
233 | |||
218 | config PHY_SUN4I_USB | 234 | config PHY_SUN4I_USB |
219 | tristate "Allwinner sunxi SoC USB PHY driver" | 235 | tristate "Allwinner sunxi SoC USB PHY driver" |
220 | depends on ARCH_SUNXI && HAS_IOMEM && OF | 236 | depends on ARCH_SUNXI && HAS_IOMEM && OF |
@@ -374,11 +390,11 @@ config PHY_TUSB1210 | |||
374 | 390 | ||
375 | config PHY_BRCMSTB_SATA | 391 | config PHY_BRCMSTB_SATA |
376 | tristate "Broadcom STB SATA PHY driver" | 392 | tristate "Broadcom STB SATA PHY driver" |
377 | depends on ARCH_BRCMSTB | 393 | depends on ARCH_BRCMSTB || BMIPS_GENERIC |
378 | depends on OF | 394 | depends on OF |
379 | select GENERIC_PHY | 395 | select GENERIC_PHY |
380 | help | 396 | help |
381 | Enable this to support the SATA3 PHY on 28nm Broadcom STB SoCs. | 397 | Enable this to support the SATA3 PHY on 28nm or 40nm Broadcom STB SoCs. |
382 | Likely useful only with CONFIG_SATA_BRCMSTB enabled. | 398 | Likely useful only with CONFIG_SATA_BRCMSTB enabled. |
383 | 399 | ||
384 | config PHY_CYGNUS_PCIE | 400 | config PHY_CYGNUS_PCIE |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 075db1a81aa5..c80f09df3bb8 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -17,12 +17,14 @@ obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o | |||
17 | obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o | 17 | obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o |
18 | obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o | 18 | obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o |
19 | obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o | 19 | obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o |
20 | obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o | ||
20 | obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o | 21 | obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o |
21 | obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o | 22 | obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o |
22 | obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o | 23 | obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o |
23 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o | 24 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o |
24 | obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o | 25 | obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o |
25 | obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o | 26 | obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o |
27 | obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o | ||
26 | obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o | 28 | obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o |
27 | obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o | 29 | obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o |
28 | obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o | 30 | obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o |
diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index 797ba17c404f..2017751ede26 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c | |||
@@ -9,11 +9,9 @@ | |||
9 | * warranty of any kind, whether express or implied. | 9 | * warranty of any kind, whether express or implied. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/io.h> | 12 | #include <linux/io.h> |
14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
15 | #include <linux/of_device.h> | 14 | #include <linux/of_device.h> |
16 | #include <linux/of_gpio.h> | ||
17 | #include <linux/phy/phy.h> | 15 | #include <linux/phy/phy.h> |
18 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
19 | #include <linux/reset.h> | 17 | #include <linux/reset.h> |
@@ -195,7 +193,6 @@ static int phy_berlin_usb_probe(struct platform_device *pdev) | |||
195 | return PTR_ERR(phy); | 193 | return PTR_ERR(phy); |
196 | } | 194 | } |
197 | 195 | ||
198 | platform_set_drvdata(pdev, priv); | ||
199 | phy_set_drvdata(phy, priv); | 196 | phy_set_drvdata(phy, priv); |
200 | 197 | ||
201 | phy_provider = | 198 | phy_provider = |
diff --git a/drivers/phy/phy-brcmstb-sata.c b/drivers/phy/phy-brcmstb-sata.c index cd9dba820566..a23172ff40e3 100644 --- a/drivers/phy/phy-brcmstb-sata.c +++ b/drivers/phy/phy-brcmstb-sata.c | |||
@@ -26,13 +26,21 @@ | |||
26 | 26 | ||
27 | #define SATA_MDIO_BANK_OFFSET 0x23c | 27 | #define SATA_MDIO_BANK_OFFSET 0x23c |
28 | #define SATA_MDIO_REG_OFFSET(ofs) ((ofs) * 4) | 28 | #define SATA_MDIO_REG_OFFSET(ofs) ((ofs) * 4) |
29 | #define SATA_MDIO_REG_SPACE_SIZE 0x1000 | ||
30 | #define SATA_MDIO_REG_LENGTH 0x1f00 | ||
31 | 29 | ||
32 | #define MAX_PORTS 2 | 30 | #define MAX_PORTS 2 |
33 | 31 | ||
34 | /* Register offset between PHYs in PCB space */ | 32 | /* Register offset between PHYs in PCB space */ |
35 | #define SATA_MDIO_REG_SPACE_SIZE 0x1000 | 33 | #define SATA_MDIO_REG_28NM_SPACE_SIZE 0x1000 |
34 | |||
35 | /* The older SATA PHY registers duplicated per port registers within the map, | ||
36 | * rather than having a separate map per port. | ||
37 | */ | ||
38 | #define SATA_MDIO_REG_40NM_SPACE_SIZE 0x10 | ||
39 | |||
40 | enum brcm_sata_phy_version { | ||
41 | BRCM_SATA_PHY_28NM, | ||
42 | BRCM_SATA_PHY_40NM, | ||
43 | }; | ||
36 | 44 | ||
37 | struct brcm_sata_port { | 45 | struct brcm_sata_port { |
38 | int portnum; | 46 | int portnum; |
@@ -44,11 +52,12 @@ struct brcm_sata_port { | |||
44 | struct brcm_sata_phy { | 52 | struct brcm_sata_phy { |
45 | struct device *dev; | 53 | struct device *dev; |
46 | void __iomem *phy_base; | 54 | void __iomem *phy_base; |
55 | enum brcm_sata_phy_version version; | ||
47 | 56 | ||
48 | struct brcm_sata_port phys[MAX_PORTS]; | 57 | struct brcm_sata_port phys[MAX_PORTS]; |
49 | }; | 58 | }; |
50 | 59 | ||
51 | enum sata_mdio_phy_regs_28nm { | 60 | enum sata_mdio_phy_regs { |
52 | PLL_REG_BANK_0 = 0x50, | 61 | PLL_REG_BANK_0 = 0x50, |
53 | PLL_REG_BANK_0_PLLCONTROL_0 = 0x81, | 62 | PLL_REG_BANK_0_PLLCONTROL_0 = 0x81, |
54 | 63 | ||
@@ -66,8 +75,16 @@ enum sata_mdio_phy_regs_28nm { | |||
66 | static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port) | 75 | static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port) |
67 | { | 76 | { |
68 | struct brcm_sata_phy *priv = port->phy_priv; | 77 | struct brcm_sata_phy *priv = port->phy_priv; |
78 | u32 offset = 0; | ||
79 | |||
80 | if (priv->version == BRCM_SATA_PHY_28NM) | ||
81 | offset = SATA_MDIO_REG_28NM_SPACE_SIZE; | ||
82 | else if (priv->version == BRCM_SATA_PHY_40NM) | ||
83 | offset = SATA_MDIO_REG_40NM_SPACE_SIZE; | ||
84 | else | ||
85 | dev_err(priv->dev, "invalid phy version\n"); | ||
69 | 86 | ||
70 | return priv->phy_base + (port->portnum * SATA_MDIO_REG_SPACE_SIZE); | 87 | return priv->phy_base + (port->portnum * offset); |
71 | } | 88 | } |
72 | 89 | ||
73 | static void brcm_sata_mdio_wr(void __iomem *addr, u32 bank, u32 ofs, | 90 | static void brcm_sata_mdio_wr(void __iomem *addr, u32 bank, u32 ofs, |
@@ -86,7 +103,7 @@ static void brcm_sata_mdio_wr(void __iomem *addr, u32 bank, u32 ofs, | |||
86 | #define FMAX_VAL_DEFAULT 0x3df | 103 | #define FMAX_VAL_DEFAULT 0x3df |
87 | #define FMAX_VAL_SSC 0x83 | 104 | #define FMAX_VAL_SSC 0x83 |
88 | 105 | ||
89 | static void brcm_sata_cfg_ssc_28nm(struct brcm_sata_port *port) | 106 | static void brcm_sata_cfg_ssc(struct brcm_sata_port *port) |
90 | { | 107 | { |
91 | void __iomem *base = brcm_sata_phy_base(port); | 108 | void __iomem *base = brcm_sata_phy_base(port); |
92 | struct brcm_sata_phy *priv = port->phy_priv; | 109 | struct brcm_sata_phy *priv = port->phy_priv; |
@@ -117,18 +134,21 @@ static int brcm_sata_phy_init(struct phy *phy) | |||
117 | { | 134 | { |
118 | struct brcm_sata_port *port = phy_get_drvdata(phy); | 135 | struct brcm_sata_port *port = phy_get_drvdata(phy); |
119 | 136 | ||
120 | brcm_sata_cfg_ssc_28nm(port); | 137 | brcm_sata_cfg_ssc(port); |
121 | 138 | ||
122 | return 0; | 139 | return 0; |
123 | } | 140 | } |
124 | 141 | ||
125 | static const struct phy_ops phy_ops_28nm = { | 142 | static const struct phy_ops phy_ops = { |
126 | .init = brcm_sata_phy_init, | 143 | .init = brcm_sata_phy_init, |
127 | .owner = THIS_MODULE, | 144 | .owner = THIS_MODULE, |
128 | }; | 145 | }; |
129 | 146 | ||
130 | static const struct of_device_id brcm_sata_phy_of_match[] = { | 147 | static const struct of_device_id brcm_sata_phy_of_match[] = { |
131 | { .compatible = "brcm,bcm7445-sata-phy" }, | 148 | { .compatible = "brcm,bcm7445-sata-phy", |
149 | .data = (void *)BRCM_SATA_PHY_28NM }, | ||
150 | { .compatible = "brcm,bcm7425-sata-phy", | ||
151 | .data = (void *)BRCM_SATA_PHY_40NM }, | ||
132 | {}, | 152 | {}, |
133 | }; | 153 | }; |
134 | MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match); | 154 | MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match); |
@@ -137,6 +157,7 @@ static int brcm_sata_phy_probe(struct platform_device *pdev) | |||
137 | { | 157 | { |
138 | struct device *dev = &pdev->dev; | 158 | struct device *dev = &pdev->dev; |
139 | struct device_node *dn = dev->of_node, *child; | 159 | struct device_node *dn = dev->of_node, *child; |
160 | const struct of_device_id *of_id; | ||
140 | struct brcm_sata_phy *priv; | 161 | struct brcm_sata_phy *priv; |
141 | struct resource *res; | 162 | struct resource *res; |
142 | struct phy_provider *provider; | 163 | struct phy_provider *provider; |
@@ -156,6 +177,12 @@ static int brcm_sata_phy_probe(struct platform_device *pdev) | |||
156 | if (IS_ERR(priv->phy_base)) | 177 | if (IS_ERR(priv->phy_base)) |
157 | return PTR_ERR(priv->phy_base); | 178 | return PTR_ERR(priv->phy_base); |
158 | 179 | ||
180 | of_id = of_match_node(brcm_sata_phy_of_match, dn); | ||
181 | if (of_id) | ||
182 | priv->version = (enum brcm_sata_phy_version)of_id->data; | ||
183 | else | ||
184 | priv->version = BRCM_SATA_PHY_28NM; | ||
185 | |||
159 | for_each_available_child_of_node(dn, child) { | 186 | for_each_available_child_of_node(dn, child) { |
160 | unsigned int id; | 187 | unsigned int id; |
161 | struct brcm_sata_port *port; | 188 | struct brcm_sata_port *port; |
@@ -181,7 +208,7 @@ static int brcm_sata_phy_probe(struct platform_device *pdev) | |||
181 | port = &priv->phys[id]; | 208 | port = &priv->phys[id]; |
182 | port->portnum = id; | 209 | port->portnum = id; |
183 | port->phy_priv = priv; | 210 | port->phy_priv = priv; |
184 | port->phy = devm_phy_create(dev, child, &phy_ops_28nm); | 211 | port->phy = devm_phy_create(dev, child, &phy_ops); |
185 | port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc"); | 212 | port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc"); |
186 | if (IS_ERR(port->phy)) { | 213 | if (IS_ERR(port->phy)) { |
187 | dev_err(dev, "failed to create PHY\n"); | 214 | dev_err(dev, "failed to create PHY\n"); |
diff --git a/drivers/phy/phy-hi6220-usb.c b/drivers/phy/phy-hi6220-usb.c new file mode 100644 index 000000000000..b2141cbd4cf6 --- /dev/null +++ b/drivers/phy/phy-hi6220-usb.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Linaro Ltd. | ||
3 | * Copyright (c) 2015 Hisilicon Limited. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/mfd/syscon.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/phy/phy.h> | ||
15 | #include <linux/regmap.h> | ||
16 | |||
17 | #define SC_PERIPH_CTRL4 0x00c | ||
18 | |||
19 | #define CTRL4_PICO_SIDDQ BIT(6) | ||
20 | #define CTRL4_PICO_OGDISABLE BIT(8) | ||
21 | #define CTRL4_PICO_VBUSVLDEXT BIT(10) | ||
22 | #define CTRL4_PICO_VBUSVLDEXTSEL BIT(11) | ||
23 | #define CTRL4_OTG_PHY_SEL BIT(21) | ||
24 | |||
25 | #define SC_PERIPH_CTRL5 0x010 | ||
26 | |||
27 | #define CTRL5_USBOTG_RES_SEL BIT(3) | ||
28 | #define CTRL5_PICOPHY_ACAENB BIT(4) | ||
29 | #define CTRL5_PICOPHY_BC_MODE BIT(5) | ||
30 | #define CTRL5_PICOPHY_CHRGSEL BIT(6) | ||
31 | #define CTRL5_PICOPHY_VDATSRCEND BIT(7) | ||
32 | #define CTRL5_PICOPHY_VDATDETENB BIT(8) | ||
33 | #define CTRL5_PICOPHY_DCDENB BIT(9) | ||
34 | #define CTRL5_PICOPHY_IDDIG BIT(10) | ||
35 | |||
36 | #define SC_PERIPH_CTRL8 0x018 | ||
37 | #define SC_PERIPH_RSTEN0 0x300 | ||
38 | #define SC_PERIPH_RSTDIS0 0x304 | ||
39 | |||
40 | #define RST0_USBOTG_BUS BIT(4) | ||
41 | #define RST0_POR_PICOPHY BIT(5) | ||
42 | #define RST0_USBOTG BIT(6) | ||
43 | #define RST0_USBOTG_32K BIT(7) | ||
44 | |||
45 | #define EYE_PATTERN_PARA 0x7053348c | ||
46 | |||
47 | struct hi6220_priv { | ||
48 | struct regmap *reg; | ||
49 | struct device *dev; | ||
50 | }; | ||
51 | |||
52 | static void hi6220_phy_init(struct hi6220_priv *priv) | ||
53 | { | ||
54 | struct regmap *reg = priv->reg; | ||
55 | u32 val, mask; | ||
56 | |||
57 | val = RST0_USBOTG_BUS | RST0_POR_PICOPHY | | ||
58 | RST0_USBOTG | RST0_USBOTG_32K; | ||
59 | mask = val; | ||
60 | regmap_update_bits(reg, SC_PERIPH_RSTEN0, mask, val); | ||
61 | regmap_update_bits(reg, SC_PERIPH_RSTDIS0, mask, val); | ||
62 | } | ||
63 | |||
64 | static int hi6220_phy_setup(struct hi6220_priv *priv, bool on) | ||
65 | { | ||
66 | struct regmap *reg = priv->reg; | ||
67 | u32 val, mask; | ||
68 | int ret; | ||
69 | |||
70 | if (on) { | ||
71 | val = CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB; | ||
72 | mask = val | CTRL5_PICOPHY_BC_MODE; | ||
73 | ret = regmap_update_bits(reg, SC_PERIPH_CTRL5, mask, val); | ||
74 | if (ret) | ||
75 | goto out; | ||
76 | |||
77 | val = CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL | | ||
78 | CTRL4_OTG_PHY_SEL; | ||
79 | mask = val | CTRL4_PICO_SIDDQ | CTRL4_PICO_OGDISABLE; | ||
80 | ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val); | ||
81 | if (ret) | ||
82 | goto out; | ||
83 | |||
84 | ret = regmap_write(reg, SC_PERIPH_CTRL8, EYE_PATTERN_PARA); | ||
85 | if (ret) | ||
86 | goto out; | ||
87 | } else { | ||
88 | val = CTRL4_PICO_SIDDQ; | ||
89 | mask = val; | ||
90 | ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val); | ||
91 | if (ret) | ||
92 | goto out; | ||
93 | } | ||
94 | |||
95 | return 0; | ||
96 | out: | ||
97 | dev_err(priv->dev, "failed to setup phy ret: %d\n", ret); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | static int hi6220_phy_start(struct phy *phy) | ||
102 | { | ||
103 | struct hi6220_priv *priv = phy_get_drvdata(phy); | ||
104 | |||
105 | return hi6220_phy_setup(priv, true); | ||
106 | } | ||
107 | |||
108 | static int hi6220_phy_exit(struct phy *phy) | ||
109 | { | ||
110 | struct hi6220_priv *priv = phy_get_drvdata(phy); | ||
111 | |||
112 | return hi6220_phy_setup(priv, false); | ||
113 | } | ||
114 | |||
115 | static struct phy_ops hi6220_phy_ops = { | ||
116 | .init = hi6220_phy_start, | ||
117 | .exit = hi6220_phy_exit, | ||
118 | .owner = THIS_MODULE, | ||
119 | }; | ||
120 | |||
121 | static int hi6220_phy_probe(struct platform_device *pdev) | ||
122 | { | ||
123 | struct phy_provider *phy_provider; | ||
124 | struct device *dev = &pdev->dev; | ||
125 | struct phy *phy; | ||
126 | struct hi6220_priv *priv; | ||
127 | |||
128 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
129 | if (!priv) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | priv->dev = dev; | ||
133 | priv->reg = syscon_regmap_lookup_by_phandle(dev->of_node, | ||
134 | "hisilicon,peripheral-syscon"); | ||
135 | if (IS_ERR(priv->reg)) { | ||
136 | dev_err(dev, "no hisilicon,peripheral-syscon\n"); | ||
137 | return PTR_ERR(priv->reg); | ||
138 | } | ||
139 | |||
140 | hi6220_phy_init(priv); | ||
141 | |||
142 | phy = devm_phy_create(dev, NULL, &hi6220_phy_ops); | ||
143 | if (IS_ERR(phy)) | ||
144 | return PTR_ERR(phy); | ||
145 | |||
146 | phy_set_drvdata(phy, priv); | ||
147 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
148 | return PTR_ERR_OR_ZERO(phy_provider); | ||
149 | } | ||
150 | |||
151 | static const struct of_device_id hi6220_phy_of_match[] = { | ||
152 | {.compatible = "hisilicon,hi6220-usb-phy",}, | ||
153 | { }, | ||
154 | }; | ||
155 | MODULE_DEVICE_TABLE(of, hi6220_phy_of_match); | ||
156 | |||
157 | static struct platform_driver hi6220_phy_driver = { | ||
158 | .probe = hi6220_phy_probe, | ||
159 | .driver = { | ||
160 | .name = "hi6220-usb-phy", | ||
161 | .of_match_table = hi6220_phy_of_match, | ||
162 | } | ||
163 | }; | ||
164 | module_platform_driver(hi6220_phy_driver); | ||
165 | |||
166 | MODULE_DESCRIPTION("HISILICON HI6220 USB PHY driver"); | ||
167 | MODULE_ALIAS("platform:hi6220-usb-phy"); | ||
168 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c index e427c3b788ff..c0e7b4b0cf5c 100644 --- a/drivers/phy/phy-mt65xx-usb3.c +++ b/drivers/phy/phy-mt65xx-usb3.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/iopoll.h> | ||
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
22 | #include <linux/phy/phy.h> | 23 | #include <linux/phy/phy.h> |
@@ -27,6 +28,7 @@ | |||
27 | * relative to USB3_SIF2_BASE base address | 28 | * relative to USB3_SIF2_BASE base address |
28 | */ | 29 | */ |
29 | #define SSUSB_SIFSLV_SPLLC 0x0000 | 30 | #define SSUSB_SIFSLV_SPLLC 0x0000 |
31 | #define SSUSB_SIFSLV_U2FREQ 0x0100 | ||
30 | 32 | ||
31 | /* offsets of sub-segment in each port registers */ | 33 | /* offsets of sub-segment in each port registers */ |
32 | #define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000 | 34 | #define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000 |
@@ -41,6 +43,7 @@ | |||
41 | #define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) | 43 | #define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) |
42 | 44 | ||
43 | #define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014) | 45 | #define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014) |
46 | #define PA5_RG_U2_HSTX_SRCAL_EN BIT(15) | ||
44 | #define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) | 47 | #define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) |
45 | #define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) | 48 | #define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) |
46 | #define PA5_RG_U2_HS_100U_U3_EN BIT(11) | 49 | #define PA5_RG_U2_HS_100U_U3_EN BIT(11) |
@@ -49,6 +52,8 @@ | |||
49 | #define PA6_RG_U2_ISO_EN BIT(31) | 52 | #define PA6_RG_U2_ISO_EN BIT(31) |
50 | #define PA6_RG_U2_BC11_SW_EN BIT(23) | 53 | #define PA6_RG_U2_BC11_SW_EN BIT(23) |
51 | #define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20) | 54 | #define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20) |
55 | #define PA6_RG_U2_SQTH GENMASK(3, 0) | ||
56 | #define PA6_RG_U2_SQTH_VAL(x) (0xf & (x)) | ||
52 | 57 | ||
53 | #define U3P_U2PHYACR4 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0020) | 58 | #define U3P_U2PHYACR4 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0020) |
54 | #define P2C_RG_USB20_GPIO_CTL BIT(9) | 59 | #define P2C_RG_USB20_GPIO_CTL BIT(9) |
@@ -111,6 +116,24 @@ | |||
111 | #define XC3_RG_U3_XTAL_RX_PWD BIT(9) | 116 | #define XC3_RG_U3_XTAL_RX_PWD BIT(9) |
112 | #define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8) | 117 | #define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8) |
113 | 118 | ||
119 | #define U3P_U2FREQ_FMCR0 (SSUSB_SIFSLV_U2FREQ + 0x00) | ||
120 | #define P2F_RG_MONCLK_SEL GENMASK(27, 26) | ||
121 | #define P2F_RG_MONCLK_SEL_VAL(x) ((0x3 & (x)) << 26) | ||
122 | #define P2F_RG_FREQDET_EN BIT(24) | ||
123 | #define P2F_RG_CYCLECNT GENMASK(23, 0) | ||
124 | #define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x)) | ||
125 | |||
126 | #define U3P_U2FREQ_VALUE (SSUSB_SIFSLV_U2FREQ + 0x0c) | ||
127 | |||
128 | #define U3P_U2FREQ_FMMONR1 (SSUSB_SIFSLV_U2FREQ + 0x10) | ||
129 | #define P2F_USB_FM_VALID BIT(0) | ||
130 | #define P2F_RG_FRCK_EN BIT(8) | ||
131 | |||
132 | #define U3P_REF_CLK 26 /* MHZ */ | ||
133 | #define U3P_SLEW_RATE_COEF 28 | ||
134 | #define U3P_SR_COEF_DIVISOR 1000 | ||
135 | #define U3P_FM_DET_CYCLE_CNT 1024 | ||
136 | |||
114 | struct mt65xx_phy_instance { | 137 | struct mt65xx_phy_instance { |
115 | struct phy *phy; | 138 | struct phy *phy; |
116 | void __iomem *port_base; | 139 | void __iomem *port_base; |
@@ -126,6 +149,77 @@ struct mt65xx_u3phy { | |||
126 | int nphys; | 149 | int nphys; |
127 | }; | 150 | }; |
128 | 151 | ||
152 | static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, | ||
153 | struct mt65xx_phy_instance *instance) | ||
154 | { | ||
155 | void __iomem *sif_base = u3phy->sif_base; | ||
156 | int calibration_val; | ||
157 | int fm_out; | ||
158 | u32 tmp; | ||
159 | |||
160 | /* enable USB ring oscillator */ | ||
161 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | ||
162 | tmp |= PA5_RG_U2_HSTX_SRCAL_EN; | ||
163 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | ||
164 | udelay(1); | ||
165 | |||
166 | /*enable free run clock */ | ||
167 | tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); | ||
168 | tmp |= P2F_RG_FRCK_EN; | ||
169 | writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); | ||
170 | |||
171 | /* set cycle count as 1024, and select u2 channel */ | ||
172 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | ||
173 | tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL); | ||
174 | tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT); | ||
175 | tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index); | ||
176 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | ||
177 | |||
178 | /* enable frequency meter */ | ||
179 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | ||
180 | tmp |= P2F_RG_FREQDET_EN; | ||
181 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | ||
182 | |||
183 | /* ignore return value */ | ||
184 | readl_poll_timeout(sif_base + U3P_U2FREQ_FMMONR1, tmp, | ||
185 | (tmp & P2F_USB_FM_VALID), 10, 200); | ||
186 | |||
187 | fm_out = readl(sif_base + U3P_U2FREQ_VALUE); | ||
188 | |||
189 | /* disable frequency meter */ | ||
190 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | ||
191 | tmp &= ~P2F_RG_FREQDET_EN; | ||
192 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | ||
193 | |||
194 | /*disable free run clock */ | ||
195 | tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); | ||
196 | tmp &= ~P2F_RG_FRCK_EN; | ||
197 | writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); | ||
198 | |||
199 | if (fm_out) { | ||
200 | /* ( 1024 / FM_OUT ) x reference clock frequency x 0.028 */ | ||
201 | tmp = U3P_FM_DET_CYCLE_CNT * U3P_REF_CLK * U3P_SLEW_RATE_COEF; | ||
202 | tmp /= fm_out; | ||
203 | calibration_val = DIV_ROUND_CLOSEST(tmp, U3P_SR_COEF_DIVISOR); | ||
204 | } else { | ||
205 | /* if FM detection fail, set default value */ | ||
206 | calibration_val = 4; | ||
207 | } | ||
208 | dev_dbg(u3phy->dev, "phy:%d, fm_out:%d, calib:%d\n", | ||
209 | instance->index, fm_out, calibration_val); | ||
210 | |||
211 | /* set HS slew rate */ | ||
212 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | ||
213 | tmp &= ~PA5_RG_U2_HSTX_SRCTRL; | ||
214 | tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(calibration_val); | ||
215 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | ||
216 | |||
217 | /* disable USB ring oscillator */ | ||
218 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | ||
219 | tmp &= ~PA5_RG_U2_HSTX_SRCAL_EN; | ||
220 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | ||
221 | } | ||
222 | |||
129 | static void phy_instance_init(struct mt65xx_u3phy *u3phy, | 223 | static void phy_instance_init(struct mt65xx_u3phy *u3phy, |
130 | struct mt65xx_phy_instance *instance) | 224 | struct mt65xx_phy_instance *instance) |
131 | { | 225 | { |
@@ -165,9 +259,10 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy, | |||
165 | writel(tmp, port_base + U3P_U2PHYDTM0); | 259 | writel(tmp, port_base + U3P_U2PHYDTM0); |
166 | } | 260 | } |
167 | 261 | ||
168 | /* DP/DM BC1.1 path Disable */ | ||
169 | tmp = readl(port_base + U3P_USBPHYACR6); | 262 | tmp = readl(port_base + U3P_USBPHYACR6); |
170 | tmp &= ~PA6_RG_U2_BC11_SW_EN; | 263 | tmp &= ~PA6_RG_U2_BC11_SW_EN; /* DP/DM BC1.1 path Disable */ |
264 | tmp &= ~PA6_RG_U2_SQTH; | ||
265 | tmp |= PA6_RG_U2_SQTH_VAL(2); | ||
171 | writel(tmp, port_base + U3P_USBPHYACR6); | 266 | writel(tmp, port_base + U3P_USBPHYACR6); |
172 | 267 | ||
173 | tmp = readl(port_base + U3P_U3PHYA_DA_REG0); | 268 | tmp = readl(port_base + U3P_U3PHYA_DA_REG0); |
@@ -223,9 +318,9 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, | |||
223 | tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; | 318 | tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; |
224 | writel(tmp, u3phy->sif_base + U3P_XTALCTL3); | 319 | writel(tmp, u3phy->sif_base + U3P_XTALCTL3); |
225 | 320 | ||
226 | /* [mt8173]disable Change 100uA current from SSUSB */ | 321 | /* [mt8173]switch 100uA current to SSUSB */ |
227 | tmp = readl(port_base + U3P_USBPHYACR5); | 322 | tmp = readl(port_base + U3P_USBPHYACR5); |
228 | tmp &= ~PA5_RG_U2_HS_100U_U3_EN; | 323 | tmp |= PA5_RG_U2_HS_100U_U3_EN; |
229 | writel(tmp, port_base + U3P_USBPHYACR5); | 324 | writel(tmp, port_base + U3P_USBPHYACR5); |
230 | } | 325 | } |
231 | 326 | ||
@@ -270,7 +365,7 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy, | |||
270 | writel(tmp, port_base + U3P_USBPHYACR6); | 365 | writel(tmp, port_base + U3P_USBPHYACR6); |
271 | 366 | ||
272 | if (!index) { | 367 | if (!index) { |
273 | /* (also disable)Change 100uA current switch to USB2.0 */ | 368 | /* switch 100uA current back to USB2.0 */ |
274 | tmp = readl(port_base + U3P_USBPHYACR5); | 369 | tmp = readl(port_base + U3P_USBPHYACR5); |
275 | tmp &= ~PA5_RG_U2_HS_100U_U3_EN; | 370 | tmp &= ~PA5_RG_U2_HS_100U_U3_EN; |
276 | writel(tmp, port_base + U3P_USBPHYACR5); | 371 | writel(tmp, port_base + U3P_USBPHYACR5); |
@@ -340,6 +435,7 @@ static int mt65xx_phy_power_on(struct phy *phy) | |||
340 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); | 435 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); |
341 | 436 | ||
342 | phy_instance_power_on(u3phy, instance); | 437 | phy_instance_power_on(u3phy, instance); |
438 | hs_slew_rate_calibrate(u3phy, instance); | ||
343 | return 0; | 439 | return 0; |
344 | } | 440 | } |
345 | 441 | ||
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index 0fe80589ffbe..c134989052f5 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/phy/omap_control_phy.h> | 30 | #include <linux/phy/omap_control_phy.h> |
31 | #include <linux/phy/phy.h> | 31 | #include <linux/phy/phy.h> |
32 | #include <linux/mfd/syscon.h> | ||
33 | #include <linux/regmap.h> | ||
32 | #include <linux/of_platform.h> | 34 | #include <linux/of_platform.h> |
33 | 35 | ||
34 | #define USB2PHY_DISCON_BYP_LATCH (1 << 31) | 36 | #define USB2PHY_DISCON_BYP_LATCH (1 << 31) |
@@ -97,22 +99,38 @@ static int omap_usb_set_peripheral(struct usb_otg *otg, | |||
97 | return 0; | 99 | return 0; |
98 | } | 100 | } |
99 | 101 | ||
102 | static int omap_usb_phy_power(struct omap_usb *phy, int on) | ||
103 | { | ||
104 | u32 val; | ||
105 | int ret; | ||
106 | |||
107 | if (!phy->syscon_phy_power) { | ||
108 | omap_control_phy_power(phy->control_dev, on); | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | if (on) | ||
113 | val = phy->power_on; | ||
114 | else | ||
115 | val = phy->power_off; | ||
116 | |||
117 | ret = regmap_update_bits(phy->syscon_phy_power, phy->power_reg, | ||
118 | phy->mask, val); | ||
119 | return ret; | ||
120 | } | ||
121 | |||
100 | static int omap_usb_power_off(struct phy *x) | 122 | static int omap_usb_power_off(struct phy *x) |
101 | { | 123 | { |
102 | struct omap_usb *phy = phy_get_drvdata(x); | 124 | struct omap_usb *phy = phy_get_drvdata(x); |
103 | 125 | ||
104 | omap_control_phy_power(phy->control_dev, 0); | 126 | return omap_usb_phy_power(phy, false); |
105 | |||
106 | return 0; | ||
107 | } | 127 | } |
108 | 128 | ||
109 | static int omap_usb_power_on(struct phy *x) | 129 | static int omap_usb_power_on(struct phy *x) |
110 | { | 130 | { |
111 | struct omap_usb *phy = phy_get_drvdata(x); | 131 | struct omap_usb *phy = phy_get_drvdata(x); |
112 | 132 | ||
113 | omap_control_phy_power(phy->control_dev, 1); | 133 | return omap_usb_phy_power(phy, true); |
114 | |||
115 | return 0; | ||
116 | } | 134 | } |
117 | 135 | ||
118 | static int omap_usb_init(struct phy *x) | 136 | static int omap_usb_init(struct phy *x) |
@@ -147,21 +165,38 @@ static const struct phy_ops ops = { | |||
147 | static const struct usb_phy_data omap_usb2_data = { | 165 | static const struct usb_phy_data omap_usb2_data = { |
148 | .label = "omap_usb2", | 166 | .label = "omap_usb2", |
149 | .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS, | 167 | .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS, |
168 | .mask = OMAP_DEV_PHY_PD, | ||
169 | .power_off = OMAP_DEV_PHY_PD, | ||
150 | }; | 170 | }; |
151 | 171 | ||
152 | static const struct usb_phy_data omap5_usb2_data = { | 172 | static const struct usb_phy_data omap5_usb2_data = { |
153 | .label = "omap5_usb2", | 173 | .label = "omap5_usb2", |
154 | .flags = 0, | 174 | .flags = 0, |
175 | .mask = OMAP_DEV_PHY_PD, | ||
176 | .power_off = OMAP_DEV_PHY_PD, | ||
155 | }; | 177 | }; |
156 | 178 | ||
157 | static const struct usb_phy_data dra7x_usb2_data = { | 179 | static const struct usb_phy_data dra7x_usb2_data = { |
158 | .label = "dra7x_usb2", | 180 | .label = "dra7x_usb2", |
159 | .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT, | 181 | .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT, |
182 | .mask = OMAP_DEV_PHY_PD, | ||
183 | .power_off = OMAP_DEV_PHY_PD, | ||
184 | }; | ||
185 | |||
186 | static const struct usb_phy_data dra7x_usb2_phy2_data = { | ||
187 | .label = "dra7x_usb2_phy2", | ||
188 | .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT, | ||
189 | .mask = OMAP_USB2_PHY_PD, | ||
190 | .power_off = OMAP_USB2_PHY_PD, | ||
160 | }; | 191 | }; |
161 | 192 | ||
162 | static const struct usb_phy_data am437x_usb2_data = { | 193 | static const struct usb_phy_data am437x_usb2_data = { |
163 | .label = "am437x_usb2", | 194 | .label = "am437x_usb2", |
164 | .flags = 0, | 195 | .flags = 0, |
196 | .mask = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD | | ||
197 | AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN, | ||
198 | .power_on = AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN, | ||
199 | .power_off = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD, | ||
165 | }; | 200 | }; |
166 | 201 | ||
167 | static const struct of_device_id omap_usb2_id_table[] = { | 202 | static const struct of_device_id omap_usb2_id_table[] = { |
@@ -178,6 +213,10 @@ static const struct of_device_id omap_usb2_id_table[] = { | |||
178 | .data = &dra7x_usb2_data, | 213 | .data = &dra7x_usb2_data, |
179 | }, | 214 | }, |
180 | { | 215 | { |
216 | .compatible = "ti,dra7x-usb2-phy2", | ||
217 | .data = &dra7x_usb2_phy2_data, | ||
218 | }, | ||
219 | { | ||
181 | .compatible = "ti,am437x-usb2", | 220 | .compatible = "ti,am437x-usb2", |
182 | .data = &am437x_usb2_data, | 221 | .data = &am437x_usb2_data, |
183 | }, | 222 | }, |
@@ -219,6 +258,9 @@ static int omap_usb2_probe(struct platform_device *pdev) | |||
219 | phy->phy.label = phy_data->label; | 258 | phy->phy.label = phy_data->label; |
220 | phy->phy.otg = otg; | 259 | phy->phy.otg = otg; |
221 | phy->phy.type = USB_PHY_TYPE_USB2; | 260 | phy->phy.type = USB_PHY_TYPE_USB2; |
261 | phy->mask = phy_data->mask; | ||
262 | phy->power_on = phy_data->power_on; | ||
263 | phy->power_off = phy_data->power_off; | ||
222 | 264 | ||
223 | if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) { | 265 | if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) { |
224 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 266 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -228,21 +270,36 @@ static int omap_usb2_probe(struct platform_device *pdev) | |||
228 | phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT; | 270 | phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT; |
229 | } | 271 | } |
230 | 272 | ||
231 | control_node = of_parse_phandle(node, "ctrl-module", 0); | 273 | phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node, |
232 | if (!control_node) { | 274 | "syscon-phy-power"); |
233 | dev_err(&pdev->dev, "Failed to get control device phandle\n"); | 275 | if (IS_ERR(phy->syscon_phy_power)) { |
234 | return -EINVAL; | 276 | dev_dbg(&pdev->dev, |
235 | } | 277 | "can't get syscon-phy-power, using control device\n"); |
278 | phy->syscon_phy_power = NULL; | ||
279 | |||
280 | control_node = of_parse_phandle(node, "ctrl-module", 0); | ||
281 | if (!control_node) { | ||
282 | dev_err(&pdev->dev, | ||
283 | "Failed to get control device phandle\n"); | ||
284 | return -EINVAL; | ||
285 | } | ||
236 | 286 | ||
237 | control_pdev = of_find_device_by_node(control_node); | 287 | control_pdev = of_find_device_by_node(control_node); |
238 | if (!control_pdev) { | 288 | if (!control_pdev) { |
239 | dev_err(&pdev->dev, "Failed to get control device\n"); | 289 | dev_err(&pdev->dev, "Failed to get control device\n"); |
240 | return -EINVAL; | 290 | return -EINVAL; |
291 | } | ||
292 | phy->control_dev = &control_pdev->dev; | ||
293 | } else { | ||
294 | if (of_property_read_u32_index(node, | ||
295 | "syscon-phy-power", 1, | ||
296 | &phy->power_reg)) { | ||
297 | dev_err(&pdev->dev, | ||
298 | "couldn't get power reg. offset\n"); | ||
299 | return -EINVAL; | ||
300 | } | ||
241 | } | 301 | } |
242 | 302 | ||
243 | phy->control_dev = &control_pdev->dev; | ||
244 | omap_control_phy_power(phy->control_dev, 0); | ||
245 | |||
246 | otg->set_host = omap_usb_set_host; | 303 | otg->set_host = omap_usb_set_host; |
247 | otg->set_peripheral = omap_usb_set_peripheral; | 304 | otg->set_peripheral = omap_usb_set_peripheral; |
248 | if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS) | 305 | if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS) |
@@ -261,6 +318,7 @@ static int omap_usb2_probe(struct platform_device *pdev) | |||
261 | } | 318 | } |
262 | 319 | ||
263 | phy_set_drvdata(generic_phy, phy); | 320 | phy_set_drvdata(generic_phy, phy); |
321 | omap_usb_power_off(generic_phy); | ||
264 | 322 | ||
265 | phy_provider = devm_of_phy_provider_register(phy->dev, | 323 | phy_provider = devm_of_phy_provider_register(phy->dev, |
266 | of_phy_simple_xlate); | 324 | of_phy_simple_xlate); |
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c new file mode 100644 index 000000000000..ef332ef4abc7 --- /dev/null +++ b/drivers/phy/phy-rcar-gen3-usb2.c | |||
@@ -0,0 +1,378 @@ | |||
1 | /* | ||
2 | * Renesas R-Car Gen3 for USB2.0 PHY driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Renesas Electronics Corporation | ||
5 | * | ||
6 | * This is based on the phy-rcar-gen2 driver: | ||
7 | * Copyright (C) 2014 Renesas Solutions Corp. | ||
8 | * Copyright (C) 2014 Cogent Embedded, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/phy/phy.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | /******* USB2.0 Host registers (original offset is +0x200) *******/ | ||
24 | #define USB2_INT_ENABLE 0x000 | ||
25 | #define USB2_USBCTR 0x00c | ||
26 | #define USB2_SPD_RSM_TIMSET 0x10c | ||
27 | #define USB2_OC_TIMSET 0x110 | ||
28 | #define USB2_COMMCTRL 0x600 | ||
29 | #define USB2_OBINTSTA 0x604 | ||
30 | #define USB2_OBINTEN 0x608 | ||
31 | #define USB2_VBCTRL 0x60c | ||
32 | #define USB2_LINECTRL1 0x610 | ||
33 | #define USB2_ADPCTRL 0x630 | ||
34 | |||
35 | /* INT_ENABLE */ | ||
36 | #define USB2_INT_ENABLE_UCOM_INTEN BIT(3) | ||
37 | #define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) | ||
38 | #define USB2_INT_ENABLE_USBH_INTA_EN BIT(1) | ||
39 | #define USB2_INT_ENABLE_INIT (USB2_INT_ENABLE_UCOM_INTEN | \ | ||
40 | USB2_INT_ENABLE_USBH_INTB_EN | \ | ||
41 | USB2_INT_ENABLE_USBH_INTA_EN) | ||
42 | |||
43 | /* USBCTR */ | ||
44 | #define USB2_USBCTR_DIRPD BIT(2) | ||
45 | #define USB2_USBCTR_PLL_RST BIT(1) | ||
46 | |||
47 | /* SPD_RSM_TIMSET */ | ||
48 | #define USB2_SPD_RSM_TIMSET_INIT 0x014e029b | ||
49 | |||
50 | /* OC_TIMSET */ | ||
51 | #define USB2_OC_TIMSET_INIT 0x000209ab | ||
52 | |||
53 | /* COMMCTRL */ | ||
54 | #define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */ | ||
55 | |||
56 | /* OBINTSTA and OBINTEN */ | ||
57 | #define USB2_OBINT_SESSVLDCHG BIT(12) | ||
58 | #define USB2_OBINT_IDDIGCHG BIT(11) | ||
59 | #define USB2_OBINT_BITS (USB2_OBINT_SESSVLDCHG | \ | ||
60 | USB2_OBINT_IDDIGCHG) | ||
61 | |||
62 | /* VBCTRL */ | ||
63 | #define USB2_VBCTRL_DRVVBUSSEL BIT(8) | ||
64 | |||
65 | /* LINECTRL1 */ | ||
66 | #define USB2_LINECTRL1_DPRPD_EN BIT(19) | ||
67 | #define USB2_LINECTRL1_DP_RPD BIT(18) | ||
68 | #define USB2_LINECTRL1_DMRPD_EN BIT(17) | ||
69 | #define USB2_LINECTRL1_DM_RPD BIT(16) | ||
70 | |||
71 | /* ADPCTRL */ | ||
72 | #define USB2_ADPCTRL_OTGSESSVLD BIT(20) | ||
73 | #define USB2_ADPCTRL_IDDIG BIT(19) | ||
74 | #define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */ | ||
75 | #define USB2_ADPCTRL_DRVVBUS BIT(4) | ||
76 | |||
77 | /******* HSUSB registers (original offset is +0x100) *******/ | ||
78 | #define HSUSB_LPSTS 0x02 | ||
79 | #define HSUSB_UGCTRL2 0x84 | ||
80 | |||
81 | /* Low Power Status register (LPSTS) */ | ||
82 | #define HSUSB_LPSTS_SUSPM 0x4000 | ||
83 | |||
84 | /* USB General control register 2 (UGCTRL2) */ | ||
85 | #define HSUSB_UGCTRL2_MASK 0x00000031 /* bit[31:6] should be 0 */ | ||
86 | #define HSUSB_UGCTRL2_USB0SEL 0x00000030 | ||
87 | #define HSUSB_UGCTRL2_USB0SEL_HOST 0x00000010 | ||
88 | #define HSUSB_UGCTRL2_USB0SEL_HS_USB 0x00000020 | ||
89 | #define HSUSB_UGCTRL2_USB0SEL_OTG 0x00000030 | ||
90 | |||
91 | struct rcar_gen3_data { | ||
92 | void __iomem *base; | ||
93 | struct clk *clk; | ||
94 | }; | ||
95 | |||
96 | struct rcar_gen3_chan { | ||
97 | struct rcar_gen3_data usb2; | ||
98 | struct rcar_gen3_data hsusb; | ||
99 | struct phy *phy; | ||
100 | }; | ||
101 | |||
102 | static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) | ||
103 | { | ||
104 | void __iomem *usb2_base = ch->usb2.base; | ||
105 | u32 val = readl(usb2_base + USB2_COMMCTRL); | ||
106 | |||
107 | dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, host); | ||
108 | if (host) | ||
109 | val &= ~USB2_COMMCTRL_OTG_PERI; | ||
110 | else | ||
111 | val |= USB2_COMMCTRL_OTG_PERI; | ||
112 | writel(val, usb2_base + USB2_COMMCTRL); | ||
113 | } | ||
114 | |||
115 | static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) | ||
116 | { | ||
117 | void __iomem *usb2_base = ch->usb2.base; | ||
118 | u32 val = readl(usb2_base + USB2_LINECTRL1); | ||
119 | |||
120 | dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm); | ||
121 | val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD); | ||
122 | if (dp) | ||
123 | val |= USB2_LINECTRL1_DP_RPD; | ||
124 | if (dm) | ||
125 | val |= USB2_LINECTRL1_DM_RPD; | ||
126 | writel(val, usb2_base + USB2_LINECTRL1); | ||
127 | } | ||
128 | |||
129 | static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus) | ||
130 | { | ||
131 | void __iomem *usb2_base = ch->usb2.base; | ||
132 | u32 val = readl(usb2_base + USB2_ADPCTRL); | ||
133 | |||
134 | dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, vbus); | ||
135 | if (vbus) | ||
136 | val |= USB2_ADPCTRL_DRVVBUS; | ||
137 | else | ||
138 | val &= ~USB2_ADPCTRL_DRVVBUS; | ||
139 | writel(val, usb2_base + USB2_ADPCTRL); | ||
140 | } | ||
141 | |||
142 | static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) | ||
143 | { | ||
144 | rcar_gen3_set_linectrl(ch, 1, 1); | ||
145 | rcar_gen3_set_host_mode(ch, 1); | ||
146 | rcar_gen3_enable_vbus_ctrl(ch, 1); | ||
147 | } | ||
148 | |||
149 | static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) | ||
150 | { | ||
151 | rcar_gen3_set_linectrl(ch, 0, 1); | ||
152 | rcar_gen3_set_host_mode(ch, 0); | ||
153 | rcar_gen3_enable_vbus_ctrl(ch, 0); | ||
154 | } | ||
155 | |||
156 | static bool rcar_gen3_check_vbus(struct rcar_gen3_chan *ch) | ||
157 | { | ||
158 | return !!(readl(ch->usb2.base + USB2_ADPCTRL) & | ||
159 | USB2_ADPCTRL_OTGSESSVLD); | ||
160 | } | ||
161 | |||
162 | static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) | ||
163 | { | ||
164 | return !!(readl(ch->usb2.base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); | ||
165 | } | ||
166 | |||
167 | static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch) | ||
168 | { | ||
169 | bool is_host = true; | ||
170 | |||
171 | /* B-device? */ | ||
172 | if (rcar_gen3_check_id(ch) && rcar_gen3_check_vbus(ch)) | ||
173 | is_host = false; | ||
174 | |||
175 | if (is_host) | ||
176 | rcar_gen3_init_for_host(ch); | ||
177 | else | ||
178 | rcar_gen3_init_for_peri(ch); | ||
179 | } | ||
180 | |||
181 | static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) | ||
182 | { | ||
183 | void __iomem *usb2_base = ch->usb2.base; | ||
184 | u32 val; | ||
185 | |||
186 | val = readl(usb2_base + USB2_VBCTRL); | ||
187 | writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); | ||
188 | writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); | ||
189 | val = readl(usb2_base + USB2_OBINTEN); | ||
190 | writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); | ||
191 | val = readl(usb2_base + USB2_ADPCTRL); | ||
192 | writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); | ||
193 | val = readl(usb2_base + USB2_LINECTRL1); | ||
194 | rcar_gen3_set_linectrl(ch, 0, 0); | ||
195 | writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN, | ||
196 | usb2_base + USB2_LINECTRL1); | ||
197 | |||
198 | rcar_gen3_device_recognition(ch); | ||
199 | } | ||
200 | |||
201 | static int rcar_gen3_phy_usb2_init(struct phy *p) | ||
202 | { | ||
203 | struct rcar_gen3_chan *channel = phy_get_drvdata(p); | ||
204 | void __iomem *usb2_base = channel->usb2.base; | ||
205 | void __iomem *hsusb_base = channel->hsusb.base; | ||
206 | u32 val; | ||
207 | |||
208 | /* Initialize USB2 part */ | ||
209 | writel(USB2_INT_ENABLE_INIT, usb2_base + USB2_INT_ENABLE); | ||
210 | writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET); | ||
211 | writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); | ||
212 | |||
213 | /* Initialize HSUSB part */ | ||
214 | if (hsusb_base) { | ||
215 | val = readl(hsusb_base + HSUSB_UGCTRL2); | ||
216 | val = (val & ~HSUSB_UGCTRL2_USB0SEL) | | ||
217 | HSUSB_UGCTRL2_USB0SEL_OTG; | ||
218 | writel(val & HSUSB_UGCTRL2_MASK, hsusb_base + HSUSB_UGCTRL2); | ||
219 | |||
220 | /* Initialize otg part */ | ||
221 | rcar_gen3_init_otg(channel); | ||
222 | } | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int rcar_gen3_phy_usb2_exit(struct phy *p) | ||
228 | { | ||
229 | struct rcar_gen3_chan *channel = phy_get_drvdata(p); | ||
230 | |||
231 | writel(0, channel->usb2.base + USB2_INT_ENABLE); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int rcar_gen3_phy_usb2_power_on(struct phy *p) | ||
237 | { | ||
238 | struct rcar_gen3_chan *channel = phy_get_drvdata(p); | ||
239 | void __iomem *usb2_base = channel->usb2.base; | ||
240 | void __iomem *hsusb_base = channel->hsusb.base; | ||
241 | u32 val; | ||
242 | |||
243 | val = readl(usb2_base + USB2_USBCTR); | ||
244 | val |= USB2_USBCTR_PLL_RST; | ||
245 | writel(val, usb2_base + USB2_USBCTR); | ||
246 | val &= ~USB2_USBCTR_PLL_RST; | ||
247 | writel(val, usb2_base + USB2_USBCTR); | ||
248 | |||
249 | /* | ||
250 | * TODO: To reduce power consuming, this driver should set the SUSPM | ||
251 | * after the PHY detects ID pin as peripheral. | ||
252 | */ | ||
253 | if (hsusb_base) { | ||
254 | /* Power on HSUSB PHY */ | ||
255 | val = readw(hsusb_base + HSUSB_LPSTS); | ||
256 | val |= HSUSB_LPSTS_SUSPM; | ||
257 | writew(val, hsusb_base + HSUSB_LPSTS); | ||
258 | } | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int rcar_gen3_phy_usb2_power_off(struct phy *p) | ||
264 | { | ||
265 | struct rcar_gen3_chan *channel = phy_get_drvdata(p); | ||
266 | void __iomem *hsusb_base = channel->hsusb.base; | ||
267 | u32 val; | ||
268 | |||
269 | if (hsusb_base) { | ||
270 | /* Power off HSUSB PHY */ | ||
271 | val = readw(hsusb_base + HSUSB_LPSTS); | ||
272 | val &= ~HSUSB_LPSTS_SUSPM; | ||
273 | writew(val, hsusb_base + HSUSB_LPSTS); | ||
274 | } | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static struct phy_ops rcar_gen3_phy_usb2_ops = { | ||
280 | .init = rcar_gen3_phy_usb2_init, | ||
281 | .exit = rcar_gen3_phy_usb2_exit, | ||
282 | .power_on = rcar_gen3_phy_usb2_power_on, | ||
283 | .power_off = rcar_gen3_phy_usb2_power_off, | ||
284 | .owner = THIS_MODULE, | ||
285 | }; | ||
286 | |||
287 | static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) | ||
288 | { | ||
289 | struct rcar_gen3_chan *ch = _ch; | ||
290 | void __iomem *usb2_base = ch->usb2.base; | ||
291 | u32 status = readl(usb2_base + USB2_OBINTSTA); | ||
292 | irqreturn_t ret = IRQ_NONE; | ||
293 | |||
294 | if (status & USB2_OBINT_BITS) { | ||
295 | dev_vdbg(&ch->phy->dev, "%s: %08x\n", __func__, status); | ||
296 | writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); | ||
297 | rcar_gen3_device_recognition(ch); | ||
298 | ret = IRQ_HANDLED; | ||
299 | } | ||
300 | |||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = { | ||
305 | { .compatible = "renesas,usb2-phy-r8a7795" }, | ||
306 | { } | ||
307 | }; | ||
308 | MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table); | ||
309 | |||
310 | static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) | ||
311 | { | ||
312 | struct device *dev = &pdev->dev; | ||
313 | struct rcar_gen3_chan *channel; | ||
314 | struct phy_provider *provider; | ||
315 | struct resource *res; | ||
316 | |||
317 | if (!dev->of_node) { | ||
318 | dev_err(dev, "This driver needs device tree\n"); | ||
319 | return -EINVAL; | ||
320 | } | ||
321 | |||
322 | channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL); | ||
323 | if (!channel) | ||
324 | return -ENOMEM; | ||
325 | |||
326 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb2_host"); | ||
327 | channel->usb2.base = devm_ioremap_resource(dev, res); | ||
328 | if (IS_ERR(channel->usb2.base)) | ||
329 | return PTR_ERR(channel->usb2.base); | ||
330 | |||
331 | /* "hsusb" memory resource is optional */ | ||
332 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hsusb"); | ||
333 | |||
334 | /* To avoid error message by devm_ioremap_resource() */ | ||
335 | if (res) { | ||
336 | int irq; | ||
337 | |||
338 | channel->hsusb.base = devm_ioremap_resource(dev, res); | ||
339 | if (IS_ERR(channel->hsusb.base)) | ||
340 | channel->hsusb.base = NULL; | ||
341 | /* call request_irq for OTG */ | ||
342 | irq = platform_get_irq(pdev, 0); | ||
343 | if (irq >= 0) | ||
344 | irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, | ||
345 | IRQF_SHARED, dev_name(dev), | ||
346 | channel); | ||
347 | if (irq < 0) | ||
348 | dev_err(dev, "No irq handler (%d)\n", irq); | ||
349 | } | ||
350 | |||
351 | /* devm_phy_create() will call pm_runtime_enable(dev); */ | ||
352 | channel->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb2_ops); | ||
353 | if (IS_ERR(channel->phy)) { | ||
354 | dev_err(dev, "Failed to create USB2 PHY\n"); | ||
355 | return PTR_ERR(channel->phy); | ||
356 | } | ||
357 | |||
358 | phy_set_drvdata(channel->phy, channel); | ||
359 | |||
360 | provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
361 | if (IS_ERR(provider)) | ||
362 | dev_err(dev, "Failed to register PHY provider\n"); | ||
363 | |||
364 | return PTR_ERR_OR_ZERO(provider); | ||
365 | } | ||
366 | |||
367 | static struct platform_driver rcar_gen3_phy_usb2_driver = { | ||
368 | .driver = { | ||
369 | .name = "phy_rcar_gen3_usb2", | ||
370 | .of_match_table = rcar_gen3_phy_usb2_match_table, | ||
371 | }, | ||
372 | .probe = rcar_gen3_phy_usb2_probe, | ||
373 | }; | ||
374 | module_platform_driver(rcar_gen3_phy_usb2_driver); | ||
375 | |||
376 | MODULE_LICENSE("GPL v2"); | ||
377 | MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY"); | ||
378 | MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>"); | ||
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c index 62c43c435194..33a80eba1cb4 100644 --- a/drivers/phy/phy-rockchip-usb.c +++ b/drivers/phy/phy-rockchip-usb.c | |||
@@ -15,12 +15,14 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/clk-provider.h> | ||
18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
19 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
23 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
25 | #include <linux/of_platform.h> | ||
24 | #include <linux/phy/phy.h> | 26 | #include <linux/phy/phy.h> |
25 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
26 | #include <linux/regulator/consumer.h> | 28 | #include <linux/regulator/consumer.h> |
@@ -36,120 +38,281 @@ | |||
36 | #define SIDDQ_ON BIT(13) | 38 | #define SIDDQ_ON BIT(13) |
37 | #define SIDDQ_OFF (0 << 13) | 39 | #define SIDDQ_OFF (0 << 13) |
38 | 40 | ||
41 | struct rockchip_usb_phys { | ||
42 | int reg; | ||
43 | const char *pll_name; | ||
44 | }; | ||
45 | |||
46 | struct rockchip_usb_phy_pdata { | ||
47 | struct rockchip_usb_phys *phys; | ||
48 | }; | ||
49 | |||
50 | struct rockchip_usb_phy_base { | ||
51 | struct device *dev; | ||
52 | struct regmap *reg_base; | ||
53 | const struct rockchip_usb_phy_pdata *pdata; | ||
54 | }; | ||
55 | |||
39 | struct rockchip_usb_phy { | 56 | struct rockchip_usb_phy { |
57 | struct rockchip_usb_phy_base *base; | ||
58 | struct device_node *np; | ||
40 | unsigned int reg_offset; | 59 | unsigned int reg_offset; |
41 | struct regmap *reg_base; | ||
42 | struct clk *clk; | 60 | struct clk *clk; |
61 | struct clk *clk480m; | ||
62 | struct clk_hw clk480m_hw; | ||
43 | struct phy *phy; | 63 | struct phy *phy; |
44 | }; | 64 | }; |
45 | 65 | ||
46 | static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, | 66 | static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, |
47 | bool siddq) | 67 | bool siddq) |
48 | { | 68 | { |
49 | return regmap_write(phy->reg_base, phy->reg_offset, | 69 | return regmap_write(phy->base->reg_base, phy->reg_offset, |
50 | SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF)); | 70 | SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF)); |
51 | } | 71 | } |
52 | 72 | ||
53 | static int rockchip_usb_phy_power_off(struct phy *_phy) | 73 | static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw, |
74 | unsigned long parent_rate) | ||
54 | { | 75 | { |
55 | struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); | 76 | return 480000000; |
56 | int ret = 0; | 77 | } |
78 | |||
79 | static void rockchip_usb_phy480m_disable(struct clk_hw *hw) | ||
80 | { | ||
81 | struct rockchip_usb_phy *phy = container_of(hw, | ||
82 | struct rockchip_usb_phy, | ||
83 | clk480m_hw); | ||
57 | 84 | ||
58 | /* Power down usb phy analog blocks by set siddq 1 */ | 85 | /* Power down usb phy analog blocks by set siddq 1 */ |
59 | ret = rockchip_usb_phy_power(phy, 1); | 86 | rockchip_usb_phy_power(phy, 1); |
60 | if (ret) | 87 | } |
61 | return ret; | ||
62 | 88 | ||
63 | clk_disable_unprepare(phy->clk); | 89 | static int rockchip_usb_phy480m_enable(struct clk_hw *hw) |
90 | { | ||
91 | struct rockchip_usb_phy *phy = container_of(hw, | ||
92 | struct rockchip_usb_phy, | ||
93 | clk480m_hw); | ||
64 | 94 | ||
65 | return 0; | 95 | /* Power up usb phy analog blocks by set siddq 0 */ |
96 | return rockchip_usb_phy_power(phy, 0); | ||
66 | } | 97 | } |
67 | 98 | ||
68 | static int rockchip_usb_phy_power_on(struct phy *_phy) | 99 | static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw) |
69 | { | 100 | { |
70 | struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); | 101 | struct rockchip_usb_phy *phy = container_of(hw, |
71 | int ret = 0; | 102 | struct rockchip_usb_phy, |
103 | clk480m_hw); | ||
104 | int ret; | ||
105 | u32 val; | ||
72 | 106 | ||
73 | ret = clk_prepare_enable(phy->clk); | 107 | ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val); |
74 | if (ret) | 108 | if (ret < 0) |
75 | return ret; | 109 | return ret; |
76 | 110 | ||
77 | /* Power up usb phy analog blocks by set siddq 0 */ | 111 | return (val & SIDDQ_ON) ? 0 : 1; |
78 | ret = rockchip_usb_phy_power(phy, 0); | 112 | } |
79 | if (ret) { | 113 | |
80 | clk_disable_unprepare(phy->clk); | 114 | static const struct clk_ops rockchip_usb_phy480m_ops = { |
81 | return ret; | 115 | .enable = rockchip_usb_phy480m_enable, |
82 | } | 116 | .disable = rockchip_usb_phy480m_disable, |
117 | .is_enabled = rockchip_usb_phy480m_is_enabled, | ||
118 | .recalc_rate = rockchip_usb_phy480m_recalc_rate, | ||
119 | }; | ||
120 | |||
121 | static int rockchip_usb_phy_power_off(struct phy *_phy) | ||
122 | { | ||
123 | struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); | ||
124 | |||
125 | clk_disable_unprepare(phy->clk480m); | ||
83 | 126 | ||
84 | return 0; | 127 | return 0; |
85 | } | 128 | } |
86 | 129 | ||
130 | static int rockchip_usb_phy_power_on(struct phy *_phy) | ||
131 | { | ||
132 | struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); | ||
133 | |||
134 | return clk_prepare_enable(phy->clk480m); | ||
135 | } | ||
136 | |||
87 | static const struct phy_ops ops = { | 137 | static const struct phy_ops ops = { |
88 | .power_on = rockchip_usb_phy_power_on, | 138 | .power_on = rockchip_usb_phy_power_on, |
89 | .power_off = rockchip_usb_phy_power_off, | 139 | .power_off = rockchip_usb_phy_power_off, |
90 | .owner = THIS_MODULE, | 140 | .owner = THIS_MODULE, |
91 | }; | 141 | }; |
92 | 142 | ||
93 | static int rockchip_usb_phy_probe(struct platform_device *pdev) | 143 | static void rockchip_usb_phy_action(void *data) |
144 | { | ||
145 | struct rockchip_usb_phy *rk_phy = data; | ||
146 | |||
147 | of_clk_del_provider(rk_phy->np); | ||
148 | clk_unregister(rk_phy->clk480m); | ||
149 | |||
150 | if (rk_phy->clk) | ||
151 | clk_put(rk_phy->clk); | ||
152 | } | ||
153 | |||
154 | static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base, | ||
155 | struct device_node *child) | ||
94 | { | 156 | { |
95 | struct device *dev = &pdev->dev; | ||
96 | struct rockchip_usb_phy *rk_phy; | 157 | struct rockchip_usb_phy *rk_phy; |
97 | struct phy_provider *phy_provider; | ||
98 | struct device_node *child; | ||
99 | struct regmap *grf; | ||
100 | unsigned int reg_offset; | 158 | unsigned int reg_offset; |
101 | int err; | 159 | const char *clk_name; |
160 | struct clk_init_data init; | ||
161 | int err, i; | ||
102 | 162 | ||
103 | grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); | 163 | rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL); |
104 | if (IS_ERR(grf)) { | 164 | if (!rk_phy) |
105 | dev_err(&pdev->dev, "Missing rockchip,grf property\n"); | 165 | return -ENOMEM; |
106 | return PTR_ERR(grf); | 166 | |
167 | rk_phy->base = base; | ||
168 | rk_phy->np = child; | ||
169 | |||
170 | if (of_property_read_u32(child, "reg", ®_offset)) { | ||
171 | dev_err(base->dev, "missing reg property in node %s\n", | ||
172 | child->name); | ||
173 | return -EINVAL; | ||
107 | } | 174 | } |
108 | 175 | ||
109 | for_each_available_child_of_node(dev->of_node, child) { | 176 | rk_phy->reg_offset = reg_offset; |
110 | rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL); | 177 | |
111 | if (!rk_phy) { | 178 | rk_phy->clk = of_clk_get_by_name(child, "phyclk"); |
112 | err = -ENOMEM; | 179 | if (IS_ERR(rk_phy->clk)) |
113 | goto put_child; | 180 | rk_phy->clk = NULL; |
114 | } | ||
115 | 181 | ||
116 | if (of_property_read_u32(child, "reg", ®_offset)) { | 182 | i = 0; |
117 | dev_err(dev, "missing reg property in node %s\n", | 183 | init.name = NULL; |
118 | child->name); | 184 | while (base->pdata->phys[i].reg) { |
119 | err = -EINVAL; | 185 | if (base->pdata->phys[i].reg == reg_offset) { |
120 | goto put_child; | 186 | init.name = base->pdata->phys[i].pll_name; |
187 | break; | ||
121 | } | 188 | } |
189 | i++; | ||
190 | } | ||
122 | 191 | ||
123 | rk_phy->reg_offset = reg_offset; | 192 | if (!init.name) { |
124 | rk_phy->reg_base = grf; | 193 | dev_err(base->dev, "phy data not found\n"); |
194 | return -EINVAL; | ||
195 | } | ||
125 | 196 | ||
126 | rk_phy->clk = of_clk_get_by_name(child, "phyclk"); | 197 | if (rk_phy->clk) { |
127 | if (IS_ERR(rk_phy->clk)) | 198 | clk_name = __clk_get_name(rk_phy->clk); |
128 | rk_phy->clk = NULL; | 199 | init.flags = 0; |
200 | init.parent_names = &clk_name; | ||
201 | init.num_parents = 1; | ||
202 | } else { | ||
203 | init.flags = CLK_IS_ROOT; | ||
204 | init.parent_names = NULL; | ||
205 | init.num_parents = 0; | ||
206 | } | ||
129 | 207 | ||
130 | rk_phy->phy = devm_phy_create(dev, child, &ops); | 208 | init.ops = &rockchip_usb_phy480m_ops; |
131 | if (IS_ERR(rk_phy->phy)) { | 209 | rk_phy->clk480m_hw.init = &init; |
132 | dev_err(dev, "failed to create PHY\n"); | ||
133 | err = PTR_ERR(rk_phy->phy); | ||
134 | goto put_child; | ||
135 | } | ||
136 | phy_set_drvdata(rk_phy->phy, rk_phy); | ||
137 | 210 | ||
138 | /* only power up usb phy when it use, so disable it when init*/ | 211 | rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw); |
139 | err = rockchip_usb_phy_power(rk_phy, 1); | 212 | if (IS_ERR(rk_phy->clk480m)) { |
140 | if (err) | 213 | err = PTR_ERR(rk_phy->clk480m); |
141 | goto put_child; | 214 | goto err_clk; |
215 | } | ||
216 | |||
217 | err = of_clk_add_provider(child, of_clk_src_simple_get, | ||
218 | rk_phy->clk480m); | ||
219 | if (err < 0) | ||
220 | goto err_clk_prov; | ||
221 | |||
222 | err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy); | ||
223 | if (err) | ||
224 | goto err_devm_action; | ||
225 | |||
226 | rk_phy->phy = devm_phy_create(base->dev, child, &ops); | ||
227 | if (IS_ERR(rk_phy->phy)) { | ||
228 | dev_err(base->dev, "failed to create PHY\n"); | ||
229 | return PTR_ERR(rk_phy->phy); | ||
230 | } | ||
231 | phy_set_drvdata(rk_phy->phy, rk_phy); | ||
232 | |||
233 | /* only power up usb phy when it use, so disable it when init*/ | ||
234 | return rockchip_usb_phy_power(rk_phy, 1); | ||
235 | |||
236 | err_devm_action: | ||
237 | of_clk_del_provider(child); | ||
238 | err_clk_prov: | ||
239 | clk_unregister(rk_phy->clk480m); | ||
240 | err_clk: | ||
241 | if (rk_phy->clk) | ||
242 | clk_put(rk_phy->clk); | ||
243 | return err; | ||
244 | } | ||
245 | |||
246 | static const struct rockchip_usb_phy_pdata rk3066a_pdata = { | ||
247 | .phys = (struct rockchip_usb_phys[]){ | ||
248 | { .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" }, | ||
249 | { .reg = 0x188, .pll_name = "sclk_otgphy1_480m" }, | ||
250 | { /* sentinel */ } | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static const struct rockchip_usb_phy_pdata rk3188_pdata = { | ||
255 | .phys = (struct rockchip_usb_phys[]){ | ||
256 | { .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" }, | ||
257 | { .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" }, | ||
258 | { /* sentinel */ } | ||
259 | }, | ||
260 | }; | ||
261 | |||
262 | static const struct rockchip_usb_phy_pdata rk3288_pdata = { | ||
263 | .phys = (struct rockchip_usb_phys[]){ | ||
264 | { .reg = 0x320, .pll_name = "sclk_otgphy0_480m" }, | ||
265 | { .reg = 0x334, .pll_name = "sclk_otgphy1_480m" }, | ||
266 | { .reg = 0x348, .pll_name = "sclk_otgphy2_480m" }, | ||
267 | { /* sentinel */ } | ||
268 | }, | ||
269 | }; | ||
270 | |||
271 | static int rockchip_usb_phy_probe(struct platform_device *pdev) | ||
272 | { | ||
273 | struct device *dev = &pdev->dev; | ||
274 | struct rockchip_usb_phy_base *phy_base; | ||
275 | struct phy_provider *phy_provider; | ||
276 | const struct of_device_id *match; | ||
277 | struct device_node *child; | ||
278 | int err; | ||
279 | |||
280 | phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL); | ||
281 | if (!phy_base) | ||
282 | return -ENOMEM; | ||
283 | |||
284 | match = of_match_device(dev->driver->of_match_table, dev); | ||
285 | if (!match || !match->data) { | ||
286 | dev_err(dev, "missing phy data\n"); | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
290 | phy_base->pdata = match->data; | ||
291 | |||
292 | phy_base->dev = dev; | ||
293 | phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node, | ||
294 | "rockchip,grf"); | ||
295 | if (IS_ERR(phy_base->reg_base)) { | ||
296 | dev_err(&pdev->dev, "Missing rockchip,grf property\n"); | ||
297 | return PTR_ERR(phy_base->reg_base); | ||
298 | } | ||
299 | |||
300 | for_each_available_child_of_node(dev->of_node, child) { | ||
301 | err = rockchip_usb_phy_init(phy_base, child); | ||
302 | if (err) { | ||
303 | of_node_put(child); | ||
304 | return err; | ||
305 | } | ||
142 | } | 306 | } |
143 | 307 | ||
144 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | 308 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); |
145 | return PTR_ERR_OR_ZERO(phy_provider); | 309 | return PTR_ERR_OR_ZERO(phy_provider); |
146 | put_child: | ||
147 | of_node_put(child); | ||
148 | return err; | ||
149 | } | 310 | } |
150 | 311 | ||
151 | static const struct of_device_id rockchip_usb_phy_dt_ids[] = { | 312 | static const struct of_device_id rockchip_usb_phy_dt_ids[] = { |
152 | { .compatible = "rockchip,rk3288-usb-phy" }, | 313 | { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata }, |
314 | { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata }, | ||
315 | { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata }, | ||
153 | {} | 316 | {} |
154 | }; | 317 | }; |
155 | 318 | ||
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index b12964b70625..bae54f7a1f48 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/of.h> | 33 | #include <linux/of.h> |
34 | #include <linux/of_address.h> | 34 | #include <linux/of_address.h> |
35 | #include <linux/of_device.h> | ||
35 | #include <linux/of_gpio.h> | 36 | #include <linux/of_gpio.h> |
36 | #include <linux/phy/phy.h> | 37 | #include <linux/phy/phy.h> |
37 | #include <linux/phy/phy-sun4i-usb.h> | 38 | #include <linux/phy/phy-sun4i-usb.h> |
@@ -46,6 +47,9 @@ | |||
46 | #define REG_PHYBIST 0x08 | 47 | #define REG_PHYBIST 0x08 |
47 | #define REG_PHYTUNE 0x0c | 48 | #define REG_PHYTUNE 0x0c |
48 | #define REG_PHYCTL_A33 0x10 | 49 | #define REG_PHYCTL_A33 0x10 |
50 | #define REG_PHY_UNK_H3 0x20 | ||
51 | |||
52 | #define REG_PMU_UNK_H3 0x10 | ||
49 | 53 | ||
50 | #define PHYCTL_DATA BIT(7) | 54 | #define PHYCTL_DATA BIT(7) |
51 | 55 | ||
@@ -79,7 +83,7 @@ | |||
79 | #define PHY_DISCON_TH_SEL 0x2a | 83 | #define PHY_DISCON_TH_SEL 0x2a |
80 | #define PHY_SQUELCH_DETECT 0x3c | 84 | #define PHY_SQUELCH_DETECT 0x3c |
81 | 85 | ||
82 | #define MAX_PHYS 3 | 86 | #define MAX_PHYS 4 |
83 | 87 | ||
84 | /* | 88 | /* |
85 | * Note do not raise the debounce time, we must report Vusb high within 100ms | 89 | * Note do not raise the debounce time, we must report Vusb high within 100ms |
@@ -88,12 +92,24 @@ | |||
88 | #define DEBOUNCE_TIME msecs_to_jiffies(50) | 92 | #define DEBOUNCE_TIME msecs_to_jiffies(50) |
89 | #define POLL_TIME msecs_to_jiffies(250) | 93 | #define POLL_TIME msecs_to_jiffies(250) |
90 | 94 | ||
95 | enum sun4i_usb_phy_type { | ||
96 | sun4i_a10_phy, | ||
97 | sun8i_a33_phy, | ||
98 | sun8i_h3_phy, | ||
99 | }; | ||
100 | |||
101 | struct sun4i_usb_phy_cfg { | ||
102 | int num_phys; | ||
103 | enum sun4i_usb_phy_type type; | ||
104 | u32 disc_thresh; | ||
105 | u8 phyctl_offset; | ||
106 | bool dedicated_clocks; | ||
107 | }; | ||
108 | |||
91 | struct sun4i_usb_phy_data { | 109 | struct sun4i_usb_phy_data { |
92 | void __iomem *base; | 110 | void __iomem *base; |
111 | const struct sun4i_usb_phy_cfg *cfg; | ||
93 | struct mutex mutex; | 112 | struct mutex mutex; |
94 | int num_phys; | ||
95 | u32 disc_thresh; | ||
96 | bool has_a33_phyctl; | ||
97 | struct sun4i_usb_phy { | 113 | struct sun4i_usb_phy { |
98 | struct phy *phy; | 114 | struct phy *phy; |
99 | void __iomem *pmu; | 115 | void __iomem *pmu; |
@@ -159,17 +175,14 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, | |||
159 | { | 175 | { |
160 | struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy); | 176 | struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy); |
161 | u32 temp, usbc_bit = BIT(phy->index * 2); | 177 | u32 temp, usbc_bit = BIT(phy->index * 2); |
162 | void *phyctl; | 178 | void *phyctl = phy_data->base + phy_data->cfg->phyctl_offset; |
163 | int i; | 179 | int i; |
164 | 180 | ||
165 | mutex_lock(&phy_data->mutex); | 181 | mutex_lock(&phy_data->mutex); |
166 | 182 | ||
167 | if (phy_data->has_a33_phyctl) { | 183 | if (phy_data->cfg->type == sun8i_a33_phy) { |
168 | phyctl = phy_data->base + REG_PHYCTL_A33; | ||
169 | /* A33 needs us to set phyctl to 0 explicitly */ | 184 | /* A33 needs us to set phyctl to 0 explicitly */ |
170 | writel(0, phyctl); | 185 | writel(0, phyctl); |
171 | } else { | ||
172 | phyctl = phy_data->base + REG_PHYCTL_A10; | ||
173 | } | 186 | } |
174 | 187 | ||
175 | for (i = 0; i < len; i++) { | 188 | for (i = 0; i < len; i++) { |
@@ -230,6 +243,7 @@ static int sun4i_usb_phy_init(struct phy *_phy) | |||
230 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); | 243 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); |
231 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); | 244 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); |
232 | int ret; | 245 | int ret; |
246 | u32 val; | ||
233 | 247 | ||
234 | ret = clk_prepare_enable(phy->clk); | 248 | ret = clk_prepare_enable(phy->clk); |
235 | if (ret) | 249 | if (ret) |
@@ -241,15 +255,26 @@ static int sun4i_usb_phy_init(struct phy *_phy) | |||
241 | return ret; | 255 | return ret; |
242 | } | 256 | } |
243 | 257 | ||
244 | /* Enable USB 45 Ohm resistor calibration */ | 258 | if (data->cfg->type == sun8i_h3_phy) { |
245 | if (phy->index == 0) | 259 | if (phy->index == 0) { |
246 | sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); | 260 | val = readl(data->base + REG_PHY_UNK_H3); |
261 | writel(val & ~1, data->base + REG_PHY_UNK_H3); | ||
262 | } | ||
247 | 263 | ||
248 | /* Adjust PHY's magnitude and rate */ | 264 | val = readl(phy->pmu + REG_PMU_UNK_H3); |
249 | sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); | 265 | writel(val & ~2, phy->pmu + REG_PMU_UNK_H3); |
266 | } else { | ||
267 | /* Enable USB 45 Ohm resistor calibration */ | ||
268 | if (phy->index == 0) | ||
269 | sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); | ||
250 | 270 | ||
251 | /* Disconnect threshold adjustment */ | 271 | /* Adjust PHY's magnitude and rate */ |
252 | sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->disc_thresh, 2); | 272 | sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); |
273 | |||
274 | /* Disconnect threshold adjustment */ | ||
275 | sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, | ||
276 | data->cfg->disc_thresh, 2); | ||
277 | } | ||
253 | 278 | ||
254 | sun4i_usb_phy_passby(phy, 1); | 279 | sun4i_usb_phy_passby(phy, 1); |
255 | 280 | ||
@@ -476,7 +501,7 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev, | |||
476 | { | 501 | { |
477 | struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); | 502 | struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); |
478 | 503 | ||
479 | if (args->args[0] >= data->num_phys) | 504 | if (args->args[0] >= data->cfg->num_phys) |
480 | return ERR_PTR(-ENODEV); | 505 | return ERR_PTR(-ENODEV); |
481 | 506 | ||
482 | return data->phys[args->args[0]].phy; | 507 | return data->phys[args->args[0]].phy; |
@@ -511,7 +536,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
511 | struct device *dev = &pdev->dev; | 536 | struct device *dev = &pdev->dev; |
512 | struct device_node *np = dev->of_node; | 537 | struct device_node *np = dev->of_node; |
513 | struct phy_provider *phy_provider; | 538 | struct phy_provider *phy_provider; |
514 | bool dedicated_clocks; | ||
515 | struct resource *res; | 539 | struct resource *res; |
516 | int i, ret; | 540 | int i, ret; |
517 | 541 | ||
@@ -522,29 +546,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
522 | mutex_init(&data->mutex); | 546 | mutex_init(&data->mutex); |
523 | INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan); | 547 | INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan); |
524 | dev_set_drvdata(dev, data); | 548 | dev_set_drvdata(dev, data); |
525 | 549 | data->cfg = of_device_get_match_data(dev); | |
526 | if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || | 550 | if (!data->cfg) |
527 | of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") || | 551 | return -EINVAL; |
528 | of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) | ||
529 | data->num_phys = 2; | ||
530 | else | ||
531 | data->num_phys = 3; | ||
532 | |||
533 | if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || | ||
534 | of_device_is_compatible(np, "allwinner,sun7i-a20-usb-phy")) | ||
535 | data->disc_thresh = 2; | ||
536 | else | ||
537 | data->disc_thresh = 3; | ||
538 | |||
539 | if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") || | ||
540 | of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") || | ||
541 | of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) | ||
542 | dedicated_clocks = true; | ||
543 | else | ||
544 | dedicated_clocks = false; | ||
545 | |||
546 | if (of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) | ||
547 | data->has_a33_phyctl = true; | ||
548 | 552 | ||
549 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); | 553 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); |
550 | data->base = devm_ioremap_resource(dev, res); | 554 | data->base = devm_ioremap_resource(dev, res); |
@@ -590,7 +594,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
590 | } | 594 | } |
591 | } | 595 | } |
592 | 596 | ||
593 | for (i = 0; i < data->num_phys; i++) { | 597 | for (i = 0; i < data->cfg->num_phys; i++) { |
594 | struct sun4i_usb_phy *phy = data->phys + i; | 598 | struct sun4i_usb_phy *phy = data->phys + i; |
595 | char name[16]; | 599 | char name[16]; |
596 | 600 | ||
@@ -602,7 +606,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
602 | phy->vbus = NULL; | 606 | phy->vbus = NULL; |
603 | } | 607 | } |
604 | 608 | ||
605 | if (dedicated_clocks) | 609 | if (data->cfg->dedicated_clocks) |
606 | snprintf(name, sizeof(name), "usb%d_phy", i); | 610 | snprintf(name, sizeof(name), "usb%d_phy", i); |
607 | else | 611 | else |
608 | strlcpy(name, "usb_phy", sizeof(name)); | 612 | strlcpy(name, "usb_phy", sizeof(name)); |
@@ -689,13 +693,69 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
689 | return 0; | 693 | return 0; |
690 | } | 694 | } |
691 | 695 | ||
696 | static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { | ||
697 | .num_phys = 3, | ||
698 | .type = sun4i_a10_phy, | ||
699 | .disc_thresh = 3, | ||
700 | .phyctl_offset = REG_PHYCTL_A10, | ||
701 | .dedicated_clocks = false, | ||
702 | }; | ||
703 | |||
704 | static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { | ||
705 | .num_phys = 2, | ||
706 | .type = sun4i_a10_phy, | ||
707 | .disc_thresh = 2, | ||
708 | .phyctl_offset = REG_PHYCTL_A10, | ||
709 | .dedicated_clocks = false, | ||
710 | }; | ||
711 | |||
712 | static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { | ||
713 | .num_phys = 3, | ||
714 | .type = sun4i_a10_phy, | ||
715 | .disc_thresh = 3, | ||
716 | .phyctl_offset = REG_PHYCTL_A10, | ||
717 | .dedicated_clocks = true, | ||
718 | }; | ||
719 | |||
720 | static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { | ||
721 | .num_phys = 3, | ||
722 | .type = sun4i_a10_phy, | ||
723 | .disc_thresh = 2, | ||
724 | .phyctl_offset = REG_PHYCTL_A10, | ||
725 | .dedicated_clocks = false, | ||
726 | }; | ||
727 | |||
728 | static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { | ||
729 | .num_phys = 2, | ||
730 | .type = sun4i_a10_phy, | ||
731 | .disc_thresh = 3, | ||
732 | .phyctl_offset = REG_PHYCTL_A10, | ||
733 | .dedicated_clocks = true, | ||
734 | }; | ||
735 | |||
736 | static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { | ||
737 | .num_phys = 2, | ||
738 | .type = sun8i_a33_phy, | ||
739 | .disc_thresh = 3, | ||
740 | .phyctl_offset = REG_PHYCTL_A33, | ||
741 | .dedicated_clocks = true, | ||
742 | }; | ||
743 | |||
744 | static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { | ||
745 | .num_phys = 4, | ||
746 | .type = sun8i_h3_phy, | ||
747 | .disc_thresh = 3, | ||
748 | .dedicated_clocks = true, | ||
749 | }; | ||
750 | |||
692 | static const struct of_device_id sun4i_usb_phy_of_match[] = { | 751 | static const struct of_device_id sun4i_usb_phy_of_match[] = { |
693 | { .compatible = "allwinner,sun4i-a10-usb-phy" }, | 752 | { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, |
694 | { .compatible = "allwinner,sun5i-a13-usb-phy" }, | 753 | { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, |
695 | { .compatible = "allwinner,sun6i-a31-usb-phy" }, | 754 | { .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg }, |
696 | { .compatible = "allwinner,sun7i-a20-usb-phy" }, | 755 | { .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg }, |
697 | { .compatible = "allwinner,sun8i-a23-usb-phy" }, | 756 | { .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg }, |
698 | { .compatible = "allwinner,sun8i-a33-usb-phy" }, | 757 | { .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg }, |
758 | { .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg }, | ||
699 | { }, | 759 | { }, |
700 | }; | 760 | }; |
701 | MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); | 761 | MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); |
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 93bc1120af12..0a477d24cf76 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c | |||
@@ -56,6 +56,18 @@ | |||
56 | 56 | ||
57 | #define SATA_PLL_SOFT_RESET BIT(18) | 57 | #define SATA_PLL_SOFT_RESET BIT(18) |
58 | 58 | ||
59 | #define PIPE3_PHY_PWRCTL_CLK_CMD_MASK 0x003FC000 | ||
60 | #define PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 14 | ||
61 | |||
62 | #define PIPE3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000 | ||
63 | #define PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT 22 | ||
64 | |||
65 | #define PIPE3_PHY_TX_RX_POWERON 0x3 | ||
66 | #define PIPE3_PHY_TX_RX_POWEROFF 0x0 | ||
67 | |||
68 | #define PCIE_PCS_MASK 0xFF0000 | ||
69 | #define PCIE_PCS_DELAY_COUNT_SHIFT 0x10 | ||
70 | |||
59 | /* | 71 | /* |
60 | * This is an Empirical value that works, need to confirm the actual | 72 | * This is an Empirical value that works, need to confirm the actual |
61 | * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status | 73 | * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status |
@@ -86,8 +98,12 @@ struct ti_pipe3 { | |||
86 | struct clk *refclk; | 98 | struct clk *refclk; |
87 | struct clk *div_clk; | 99 | struct clk *div_clk; |
88 | struct pipe3_dpll_map *dpll_map; | 100 | struct pipe3_dpll_map *dpll_map; |
101 | struct regmap *phy_power_syscon; /* ctrl. reg. acces */ | ||
102 | struct regmap *pcs_syscon; /* ctrl. reg. acces */ | ||
89 | struct regmap *dpll_reset_syscon; /* ctrl. reg. acces */ | 103 | struct regmap *dpll_reset_syscon; /* ctrl. reg. acces */ |
90 | unsigned int dpll_reset_reg; /* reg. index within syscon */ | 104 | unsigned int dpll_reset_reg; /* reg. index within syscon */ |
105 | unsigned int power_reg; /* power reg. index within syscon */ | ||
106 | unsigned int pcie_pcs_reg; /* pcs reg. index in syscon */ | ||
91 | bool sata_refclk_enabled; | 107 | bool sata_refclk_enabled; |
92 | }; | 108 | }; |
93 | 109 | ||
@@ -144,20 +160,49 @@ static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy); | |||
144 | 160 | ||
145 | static int ti_pipe3_power_off(struct phy *x) | 161 | static int ti_pipe3_power_off(struct phy *x) |
146 | { | 162 | { |
163 | u32 val; | ||
164 | int ret; | ||
147 | struct ti_pipe3 *phy = phy_get_drvdata(x); | 165 | struct ti_pipe3 *phy = phy_get_drvdata(x); |
148 | 166 | ||
149 | omap_control_phy_power(phy->control_dev, 0); | 167 | if (!phy->phy_power_syscon) { |
168 | omap_control_phy_power(phy->control_dev, 0); | ||
169 | return 0; | ||
170 | } | ||
150 | 171 | ||
151 | return 0; | 172 | val = PIPE3_PHY_TX_RX_POWEROFF << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT; |
173 | |||
174 | ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg, | ||
175 | PIPE3_PHY_PWRCTL_CLK_CMD_MASK, val); | ||
176 | return ret; | ||
152 | } | 177 | } |
153 | 178 | ||
154 | static int ti_pipe3_power_on(struct phy *x) | 179 | static int ti_pipe3_power_on(struct phy *x) |
155 | { | 180 | { |
181 | u32 val; | ||
182 | u32 mask; | ||
183 | int ret; | ||
184 | unsigned long rate; | ||
156 | struct ti_pipe3 *phy = phy_get_drvdata(x); | 185 | struct ti_pipe3 *phy = phy_get_drvdata(x); |
157 | 186 | ||
158 | omap_control_phy_power(phy->control_dev, 1); | 187 | if (!phy->phy_power_syscon) { |
188 | omap_control_phy_power(phy->control_dev, 1); | ||
189 | return 0; | ||
190 | } | ||
159 | 191 | ||
160 | return 0; | 192 | rate = clk_get_rate(phy->sys_clk); |
193 | if (!rate) { | ||
194 | dev_err(phy->dev, "Invalid clock rate\n"); | ||
195 | return -EINVAL; | ||
196 | } | ||
197 | rate = rate / 1000000; | ||
198 | mask = OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK | | ||
199 | OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK; | ||
200 | val = PIPE3_PHY_TX_RX_POWERON << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT; | ||
201 | val |= rate << OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT; | ||
202 | |||
203 | ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg, | ||
204 | mask, val); | ||
205 | return ret; | ||
161 | } | 206 | } |
162 | 207 | ||
163 | static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy) | 208 | static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy) |
@@ -229,8 +274,15 @@ static int ti_pipe3_init(struct phy *x) | |||
229 | * 18-1804. | 274 | * 18-1804. |
230 | */ | 275 | */ |
231 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) { | 276 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) { |
232 | omap_control_pcie_pcs(phy->control_dev, 0x96); | 277 | if (!phy->pcs_syscon) { |
233 | return 0; | 278 | omap_control_pcie_pcs(phy->control_dev, 0x96); |
279 | return 0; | ||
280 | } | ||
281 | |||
282 | val = 0x96 << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT; | ||
283 | ret = regmap_update_bits(phy->pcs_syscon, phy->pcie_pcs_reg, | ||
284 | PCIE_PCS_MASK, val); | ||
285 | return ret; | ||
234 | } | 286 | } |
235 | 287 | ||
236 | /* Bring it out of IDLE if it is IDLE */ | 288 | /* Bring it out of IDLE if it is IDLE */ |
@@ -308,51 +360,15 @@ static const struct phy_ops ops = { | |||
308 | 360 | ||
309 | static const struct of_device_id ti_pipe3_id_table[]; | 361 | static const struct of_device_id ti_pipe3_id_table[]; |
310 | 362 | ||
311 | static int ti_pipe3_probe(struct platform_device *pdev) | 363 | static int ti_pipe3_get_clk(struct ti_pipe3 *phy) |
312 | { | 364 | { |
313 | struct ti_pipe3 *phy; | ||
314 | struct phy *generic_phy; | ||
315 | struct phy_provider *phy_provider; | ||
316 | struct resource *res; | ||
317 | struct device_node *node = pdev->dev.of_node; | ||
318 | struct device_node *control_node; | ||
319 | struct platform_device *control_pdev; | ||
320 | const struct of_device_id *match; | ||
321 | struct clk *clk; | 365 | struct clk *clk; |
366 | struct device *dev = phy->dev; | ||
367 | struct device_node *node = dev->of_node; | ||
322 | 368 | ||
323 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); | 369 | phy->refclk = devm_clk_get(dev, "refclk"); |
324 | if (!phy) | ||
325 | return -ENOMEM; | ||
326 | |||
327 | phy->dev = &pdev->dev; | ||
328 | |||
329 | if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { | ||
330 | match = of_match_device(ti_pipe3_id_table, &pdev->dev); | ||
331 | if (!match) | ||
332 | return -EINVAL; | ||
333 | |||
334 | phy->dpll_map = (struct pipe3_dpll_map *)match->data; | ||
335 | if (!phy->dpll_map) { | ||
336 | dev_err(&pdev->dev, "no DPLL data\n"); | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | |||
340 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
341 | "pll_ctrl"); | ||
342 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); | ||
343 | if (IS_ERR(phy->pll_ctrl_base)) | ||
344 | return PTR_ERR(phy->pll_ctrl_base); | ||
345 | |||
346 | phy->sys_clk = devm_clk_get(phy->dev, "sysclk"); | ||
347 | if (IS_ERR(phy->sys_clk)) { | ||
348 | dev_err(&pdev->dev, "unable to get sysclk\n"); | ||
349 | return -EINVAL; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | phy->refclk = devm_clk_get(phy->dev, "refclk"); | ||
354 | if (IS_ERR(phy->refclk)) { | 370 | if (IS_ERR(phy->refclk)) { |
355 | dev_err(&pdev->dev, "unable to get refclk\n"); | 371 | dev_err(dev, "unable to get refclk\n"); |
356 | /* older DTBs have missing refclk in SATA PHY | 372 | /* older DTBs have missing refclk in SATA PHY |
357 | * so don't bail out in case of SATA PHY. | 373 | * so don't bail out in case of SATA PHY. |
358 | */ | 374 | */ |
@@ -361,80 +377,194 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
361 | } | 377 | } |
362 | 378 | ||
363 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { | 379 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { |
364 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); | 380 | phy->wkupclk = devm_clk_get(dev, "wkupclk"); |
365 | if (IS_ERR(phy->wkupclk)) { | 381 | if (IS_ERR(phy->wkupclk)) { |
366 | dev_err(&pdev->dev, "unable to get wkupclk\n"); | 382 | dev_err(dev, "unable to get wkupclk\n"); |
367 | return PTR_ERR(phy->wkupclk); | 383 | return PTR_ERR(phy->wkupclk); |
368 | } | 384 | } |
369 | } else { | 385 | } else { |
370 | phy->wkupclk = ERR_PTR(-ENODEV); | 386 | phy->wkupclk = ERR_PTR(-ENODEV); |
371 | phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(node, | 387 | } |
372 | "syscon-pllreset"); | 388 | |
373 | if (IS_ERR(phy->dpll_reset_syscon)) { | 389 | if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie") || |
374 | dev_info(&pdev->dev, | 390 | phy->phy_power_syscon) { |
375 | "can't get syscon-pllreset, sata dpll won't idle\n"); | 391 | phy->sys_clk = devm_clk_get(dev, "sysclk"); |
376 | phy->dpll_reset_syscon = NULL; | 392 | if (IS_ERR(phy->sys_clk)) { |
377 | } else { | 393 | dev_err(dev, "unable to get sysclk\n"); |
378 | if (of_property_read_u32_index(node, | 394 | return -EINVAL; |
379 | "syscon-pllreset", 1, | ||
380 | &phy->dpll_reset_reg)) { | ||
381 | dev_err(&pdev->dev, | ||
382 | "couldn't get pllreset reg. offset\n"); | ||
383 | return -EINVAL; | ||
384 | } | ||
385 | } | 395 | } |
386 | } | 396 | } |
387 | 397 | ||
388 | if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { | 398 | if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { |
389 | 399 | clk = devm_clk_get(dev, "dpll_ref"); | |
390 | clk = devm_clk_get(phy->dev, "dpll_ref"); | ||
391 | if (IS_ERR(clk)) { | 400 | if (IS_ERR(clk)) { |
392 | dev_err(&pdev->dev, "unable to get dpll ref clk\n"); | 401 | dev_err(dev, "unable to get dpll ref clk\n"); |
393 | return PTR_ERR(clk); | 402 | return PTR_ERR(clk); |
394 | } | 403 | } |
395 | clk_set_rate(clk, 1500000000); | 404 | clk_set_rate(clk, 1500000000); |
396 | 405 | ||
397 | clk = devm_clk_get(phy->dev, "dpll_ref_m2"); | 406 | clk = devm_clk_get(dev, "dpll_ref_m2"); |
398 | if (IS_ERR(clk)) { | 407 | if (IS_ERR(clk)) { |
399 | dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n"); | 408 | dev_err(dev, "unable to get dpll ref m2 clk\n"); |
400 | return PTR_ERR(clk); | 409 | return PTR_ERR(clk); |
401 | } | 410 | } |
402 | clk_set_rate(clk, 100000000); | 411 | clk_set_rate(clk, 100000000); |
403 | 412 | ||
404 | clk = devm_clk_get(phy->dev, "phy-div"); | 413 | clk = devm_clk_get(dev, "phy-div"); |
405 | if (IS_ERR(clk)) { | 414 | if (IS_ERR(clk)) { |
406 | dev_err(&pdev->dev, "unable to get phy-div clk\n"); | 415 | dev_err(dev, "unable to get phy-div clk\n"); |
407 | return PTR_ERR(clk); | 416 | return PTR_ERR(clk); |
408 | } | 417 | } |
409 | clk_set_rate(clk, 100000000); | 418 | clk_set_rate(clk, 100000000); |
410 | 419 | ||
411 | phy->div_clk = devm_clk_get(phy->dev, "div-clk"); | 420 | phy->div_clk = devm_clk_get(dev, "div-clk"); |
412 | if (IS_ERR(phy->div_clk)) { | 421 | if (IS_ERR(phy->div_clk)) { |
413 | dev_err(&pdev->dev, "unable to get div-clk\n"); | 422 | dev_err(dev, "unable to get div-clk\n"); |
414 | return PTR_ERR(phy->div_clk); | 423 | return PTR_ERR(phy->div_clk); |
415 | } | 424 | } |
416 | } else { | 425 | } else { |
417 | phy->div_clk = ERR_PTR(-ENODEV); | 426 | phy->div_clk = ERR_PTR(-ENODEV); |
418 | } | 427 | } |
419 | 428 | ||
420 | control_node = of_parse_phandle(node, "ctrl-module", 0); | 429 | return 0; |
421 | if (!control_node) { | 430 | } |
422 | dev_err(&pdev->dev, "Failed to get control device phandle\n"); | 431 | |
423 | return -EINVAL; | 432 | static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy) |
433 | { | ||
434 | struct device *dev = phy->dev; | ||
435 | struct device_node *node = dev->of_node; | ||
436 | struct device_node *control_node; | ||
437 | struct platform_device *control_pdev; | ||
438 | |||
439 | phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node, | ||
440 | "syscon-phy-power"); | ||
441 | if (IS_ERR(phy->phy_power_syscon)) { | ||
442 | dev_dbg(dev, | ||
443 | "can't get syscon-phy-power, using control device\n"); | ||
444 | phy->phy_power_syscon = NULL; | ||
445 | } else { | ||
446 | if (of_property_read_u32_index(node, | ||
447 | "syscon-phy-power", 1, | ||
448 | &phy->power_reg)) { | ||
449 | dev_err(dev, "couldn't get power reg. offset\n"); | ||
450 | return -EINVAL; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | if (!phy->phy_power_syscon) { | ||
455 | control_node = of_parse_phandle(node, "ctrl-module", 0); | ||
456 | if (!control_node) { | ||
457 | dev_err(dev, "Failed to get control device phandle\n"); | ||
458 | return -EINVAL; | ||
459 | } | ||
460 | |||
461 | control_pdev = of_find_device_by_node(control_node); | ||
462 | if (!control_pdev) { | ||
463 | dev_err(dev, "Failed to get control device\n"); | ||
464 | return -EINVAL; | ||
465 | } | ||
466 | |||
467 | phy->control_dev = &control_pdev->dev; | ||
468 | } | ||
469 | |||
470 | if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { | ||
471 | phy->pcs_syscon = syscon_regmap_lookup_by_phandle(node, | ||
472 | "syscon-pcs"); | ||
473 | if (IS_ERR(phy->pcs_syscon)) { | ||
474 | dev_dbg(dev, | ||
475 | "can't get syscon-pcs, using omap control\n"); | ||
476 | phy->pcs_syscon = NULL; | ||
477 | } else { | ||
478 | if (of_property_read_u32_index(node, | ||
479 | "syscon-pcs", 1, | ||
480 | &phy->pcie_pcs_reg)) { | ||
481 | dev_err(dev, | ||
482 | "couldn't get pcie pcs reg. offset\n"); | ||
483 | return -EINVAL; | ||
484 | } | ||
485 | } | ||
486 | } | ||
487 | |||
488 | if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) { | ||
489 | phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(node, | ||
490 | "syscon-pllreset"); | ||
491 | if (IS_ERR(phy->dpll_reset_syscon)) { | ||
492 | dev_info(dev, | ||
493 | "can't get syscon-pllreset, sata dpll won't idle\n"); | ||
494 | phy->dpll_reset_syscon = NULL; | ||
495 | } else { | ||
496 | if (of_property_read_u32_index(node, | ||
497 | "syscon-pllreset", 1, | ||
498 | &phy->dpll_reset_reg)) { | ||
499 | dev_err(dev, | ||
500 | "couldn't get pllreset reg. offset\n"); | ||
501 | return -EINVAL; | ||
502 | } | ||
503 | } | ||
424 | } | 504 | } |
425 | 505 | ||
426 | control_pdev = of_find_device_by_node(control_node); | 506 | return 0; |
427 | if (!control_pdev) { | 507 | } |
428 | dev_err(&pdev->dev, "Failed to get control device\n"); | 508 | |
509 | static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy) | ||
510 | { | ||
511 | struct resource *res; | ||
512 | const struct of_device_id *match; | ||
513 | struct device *dev = phy->dev; | ||
514 | struct device_node *node = dev->of_node; | ||
515 | struct platform_device *pdev = to_platform_device(dev); | ||
516 | |||
517 | if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) | ||
518 | return 0; | ||
519 | |||
520 | match = of_match_device(ti_pipe3_id_table, dev); | ||
521 | if (!match) | ||
522 | return -EINVAL; | ||
523 | |||
524 | phy->dpll_map = (struct pipe3_dpll_map *)match->data; | ||
525 | if (!phy->dpll_map) { | ||
526 | dev_err(dev, "no DPLL data\n"); | ||
429 | return -EINVAL; | 527 | return -EINVAL; |
430 | } | 528 | } |
431 | 529 | ||
432 | phy->control_dev = &control_pdev->dev; | 530 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
531 | "pll_ctrl"); | ||
532 | phy->pll_ctrl_base = devm_ioremap_resource(dev, res); | ||
533 | if (IS_ERR(phy->pll_ctrl_base)) | ||
534 | return PTR_ERR(phy->pll_ctrl_base); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
433 | 538 | ||
434 | omap_control_phy_power(phy->control_dev, 0); | 539 | static int ti_pipe3_probe(struct platform_device *pdev) |
540 | { | ||
541 | struct ti_pipe3 *phy; | ||
542 | struct phy *generic_phy; | ||
543 | struct phy_provider *phy_provider; | ||
544 | struct device_node *node = pdev->dev.of_node; | ||
545 | struct device *dev = &pdev->dev; | ||
546 | int ret; | ||
547 | |||
548 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); | ||
549 | if (!phy) | ||
550 | return -ENOMEM; | ||
551 | |||
552 | phy->dev = dev; | ||
553 | |||
554 | ret = ti_pipe3_get_pll_base(phy); | ||
555 | if (ret) | ||
556 | return ret; | ||
557 | |||
558 | ret = ti_pipe3_get_sysctrl(phy); | ||
559 | if (ret) | ||
560 | return ret; | ||
561 | |||
562 | ret = ti_pipe3_get_clk(phy); | ||
563 | if (ret) | ||
564 | return ret; | ||
435 | 565 | ||
436 | platform_set_drvdata(pdev, phy); | 566 | platform_set_drvdata(pdev, phy); |
437 | pm_runtime_enable(phy->dev); | 567 | pm_runtime_enable(dev); |
438 | 568 | ||
439 | /* | 569 | /* |
440 | * Prevent auto-disable of refclk for SATA PHY due to Errata i783 | 570 | * Prevent auto-disable of refclk for SATA PHY due to Errata i783 |
@@ -446,13 +576,15 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
446 | } | 576 | } |
447 | } | 577 | } |
448 | 578 | ||
449 | generic_phy = devm_phy_create(phy->dev, NULL, &ops); | 579 | generic_phy = devm_phy_create(dev, NULL, &ops); |
450 | if (IS_ERR(generic_phy)) | 580 | if (IS_ERR(generic_phy)) |
451 | return PTR_ERR(generic_phy); | 581 | return PTR_ERR(generic_phy); |
452 | 582 | ||
453 | phy_set_drvdata(generic_phy, phy); | 583 | phy_set_drvdata(generic_phy, phy); |
454 | phy_provider = devm_of_phy_provider_register(phy->dev, | 584 | |
455 | of_phy_simple_xlate); | 585 | ti_pipe3_power_off(generic_phy); |
586 | |||
587 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
456 | if (IS_ERR(phy_provider)) | 588 | if (IS_ERR(phy_provider)) |
457 | return PTR_ERR(phy_provider); | 589 | return PTR_ERR(phy_provider); |
458 | 590 | ||
diff --git a/include/linux/phy/omap_usb.h b/include/linux/phy/omap_usb.h index dc2c541a619b..2e5fb870efa9 100644 --- a/include/linux/phy/omap_usb.h +++ b/include/linux/phy/omap_usb.h | |||
@@ -30,6 +30,12 @@ struct usb_dpll_params { | |||
30 | u32 mf; | 30 | u32 mf; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | enum omap_usb_phy_type { | ||
34 | TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */ | ||
35 | TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */ | ||
36 | TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */ | ||
37 | }; | ||
38 | |||
33 | struct omap_usb { | 39 | struct omap_usb { |
34 | struct usb_phy phy; | 40 | struct usb_phy phy; |
35 | struct phy_companion *comparator; | 41 | struct phy_companion *comparator; |
@@ -40,11 +46,20 @@ struct omap_usb { | |||
40 | struct clk *wkupclk; | 46 | struct clk *wkupclk; |
41 | struct clk *optclk; | 47 | struct clk *optclk; |
42 | u8 flags; | 48 | u8 flags; |
49 | enum omap_usb_phy_type type; | ||
50 | struct regmap *syscon_phy_power; /* ctrl. reg. acces */ | ||
51 | unsigned int power_reg; /* power reg. index within syscon */ | ||
52 | u32 mask; | ||
53 | u32 power_on; | ||
54 | u32 power_off; | ||
43 | }; | 55 | }; |
44 | 56 | ||
45 | struct usb_phy_data { | 57 | struct usb_phy_data { |
46 | const char *label; | 58 | const char *label; |
47 | u8 flags; | 59 | u8 flags; |
60 | u32 mask; | ||
61 | u32 power_on; | ||
62 | u32 power_off; | ||
48 | }; | 63 | }; |
49 | 64 | ||
50 | /* Driver Flags */ | 65 | /* Driver Flags */ |
@@ -52,6 +67,14 @@ struct usb_phy_data { | |||
52 | #define OMAP_USB2_HAS_SET_VBUS (1 << 1) | 67 | #define OMAP_USB2_HAS_SET_VBUS (1 << 1) |
53 | #define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT (1 << 2) | 68 | #define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT (1 << 2) |
54 | 69 | ||
70 | #define OMAP_DEV_PHY_PD BIT(0) | ||
71 | #define OMAP_USB2_PHY_PD BIT(28) | ||
72 | |||
73 | #define AM437X_USB2_PHY_PD BIT(0) | ||
74 | #define AM437X_USB2_OTG_PD BIT(1) | ||
75 | #define AM437X_USB2_OTGVDET_EN BIT(19) | ||
76 | #define AM437X_USB2_OTGSESSEND_EN BIT(20) | ||
77 | |||
55 | #define phy_to_omapusb(x) container_of((x), struct omap_usb, phy) | 78 | #define phy_to_omapusb(x) container_of((x), struct omap_usb, phy) |
56 | 79 | ||
57 | #if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE) | 80 | #if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE) |