aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-12-26 20:01:18 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-12-26 20:01:18 -0500
commitdaf273350d96241752b00020940c07dc2cff2e0a (patch)
treec0a0557da09404455b6b4672fb9bd6f1147a8d16
parentf7dbd84fd49e487df68b3a95780c275d7da1891c (diff)
parent9955a7835bf376e12482583958b2661f501b868b (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.txt1
-rw-r--r--Documentation/devicetree/bindings/phy/phy-hi6220-usb.txt16
-rw-r--r--Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt39
-rw-r--r--Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt6
-rw-r--r--Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt1
-rw-r--r--Documentation/devicetree/bindings/phy/ti-phy.txt20
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/phy/Kconfig20
-rw-r--r--drivers/phy/Makefile2
-rw-r--r--drivers/phy/phy-berlin-usb.c3
-rw-r--r--drivers/phy/phy-brcmstb-sata.c47
-rw-r--r--drivers/phy/phy-hi6220-usb.c168
-rw-r--r--drivers/phy/phy-mt65xx-usb3.c106
-rw-r--r--drivers/phy/phy-omap-usb2.c94
-rw-r--r--drivers/phy/phy-rcar-gen3-usb2.c378
-rw-r--r--drivers/phy/phy-rockchip-usb.c287
-rw-r--r--drivers/phy/phy-sun4i-usb.c158
-rw-r--r--drivers/phy/phy-ti-pipe3.c302
-rw-r--r--include/linux/phy/omap_usb.h23
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
3Required properties: 3Required 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 @@
1Hisilicon hi6220 usb PHY
2-----------------------
3
4Required 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.
8Refer to phy/phy-bindings.txt for the generic PHY binding properties
9
10Example:
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
3This file provides information on what the device node for the R-Car generation
43 USB 2.0 PHY contains.
5
6Required 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
14Optional properties:
15To use a USB channel where USB 2.0 Host and HSUSB (USB 2.0 Peripheral) are
16combined, the device tree node should set HSUSB properties to reg and reg-names
17properties. This is because HSUSB has registers to select USB 2.0 host or
18peripheral 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
23Example (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 @@
1ROCKCHIP USB2 PHY 1ROCKCHIP USB2 PHY
2 2
3Required properties: 3Required 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:
21Optional Properties: 24Optional 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
25Example: 29Example:
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
32Required properties: 32Required 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
43Optional properties: 45Deprecated 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
49Recommended 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
47This is usually a subnode of ocp2scp to which it is connected. 53This is usually a subnode of ocp2scp to which it is connected.
48 54
49usb2phy@4a0ad080 { 55usb2phy@4a0ad080 {
@@ -77,14 +83,22 @@ Required properties:
77 * "div-clk" - apll clock 83 * "div-clk" - apll clock
78 84
79Optional properties: 85Optional 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
95Deprecated properties:
96 - ctrl-module : phandle of the control module used by PHY driver to power on
97 the PHY.
98
99Recommended 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
89This is usually a subnode of ocp2scp to which it is connected. 103This 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
8961F: drivers/net/ethernet/renesas/ 8961F: drivers/net/ethernet/renesas/
8962F: include/linux/sh_eth.h 8962F: include/linux/sh_eth.h
8963 8963
8964RENESAS USB2 PHY DRIVER
8965M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
8966L: linux-sh@vger.kernel.org
8967S: Maintained
8968F: drivers/phy/phy-rcar-gen3-usb2.c
8969
8964RESET CONTROLLER FRAMEWORK 8970RESET CONTROLLER FRAMEWORK
8965M: Philipp Zabel <p.zabel@pengutronix.de> 8971M: Philipp Zabel <p.zabel@pengutronix.de>
8966S: Maintained 8972S: 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
121config 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
121config OMAP_CONTROL_PHY 128config 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
225config 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
218config PHY_SUN4I_USB 234config 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
375config PHY_BRCMSTB_SATA 391config 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
384config PHY_CYGNUS_PCIE 400config 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
17obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o 17obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
18obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o 18obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o
19obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o 19obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
20obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o
20obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o 21obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
21obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o 22obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
22obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o 23obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
23obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o 24obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
24obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o 25obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
25obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o 26obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
27obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o
26obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o 28obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o
27obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o 29obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
28obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o 30obj-$(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
40enum brcm_sata_phy_version {
41 BRCM_SATA_PHY_28NM,
42 BRCM_SATA_PHY_40NM,
43};
36 44
37struct brcm_sata_port { 45struct brcm_sata_port {
38 int portnum; 46 int portnum;
@@ -44,11 +52,12 @@ struct brcm_sata_port {
44struct brcm_sata_phy { 52struct 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
51enum sata_mdio_phy_regs_28nm { 60enum 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 {
66static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port) 75static 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
73static void brcm_sata_mdio_wr(void __iomem *addr, u32 bank, u32 ofs, 90static 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
89static void brcm_sata_cfg_ssc_28nm(struct brcm_sata_port *port) 106static 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
125static const struct phy_ops phy_ops_28nm = { 142static 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
130static const struct of_device_id brcm_sata_phy_of_match[] = { 147static 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};
134MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match); 154MODULE_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
47struct hi6220_priv {
48 struct regmap *reg;
49 struct device *dev;
50};
51
52static 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
64static 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;
96out:
97 dev_err(priv->dev, "failed to setup phy ret: %d\n", ret);
98 return ret;
99}
100
101static 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
108static 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
115static struct phy_ops hi6220_phy_ops = {
116 .init = hi6220_phy_start,
117 .exit = hi6220_phy_exit,
118 .owner = THIS_MODULE,
119};
120
121static 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
151static const struct of_device_id hi6220_phy_of_match[] = {
152 {.compatible = "hisilicon,hi6220-usb-phy",},
153 { },
154};
155MODULE_DEVICE_TABLE(of, hi6220_phy_of_match);
156
157static 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};
164module_platform_driver(hi6220_phy_driver);
165
166MODULE_DESCRIPTION("HISILICON HI6220 USB PHY driver");
167MODULE_ALIAS("platform:hi6220-usb-phy");
168MODULE_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
114struct mt65xx_phy_instance { 137struct 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
152static 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
129static void phy_instance_init(struct mt65xx_u3phy *u3phy, 223static 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
102static 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
100static int omap_usb_power_off(struct phy *x) 122static 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
109static int omap_usb_power_on(struct phy *x) 129static 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
118static int omap_usb_init(struct phy *x) 136static int omap_usb_init(struct phy *x)
@@ -147,21 +165,38 @@ static const struct phy_ops ops = {
147static const struct usb_phy_data omap_usb2_data = { 165static 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
152static const struct usb_phy_data omap5_usb2_data = { 172static 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
157static const struct usb_phy_data dra7x_usb2_data = { 179static 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
186static 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
162static const struct usb_phy_data am437x_usb2_data = { 193static 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
167static const struct of_device_id omap_usb2_id_table[] = { 202static 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
91struct rcar_gen3_data {
92 void __iomem *base;
93 struct clk *clk;
94};
95
96struct rcar_gen3_chan {
97 struct rcar_gen3_data usb2;
98 struct rcar_gen3_data hsusb;
99 struct phy *phy;
100};
101
102static 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
115static 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
129static 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
142static 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
149static 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
156static 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
162static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
163{
164 return !!(readl(ch->usb2.base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
165}
166
167static 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
181static 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
201static 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
227static 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
236static 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
263static 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
279static 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
287static 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
304static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
305 { .compatible = "renesas,usb2-phy-r8a7795" },
306 { }
307};
308MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table);
309
310static 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
367static 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};
374module_platform_driver(rcar_gen3_phy_usb2_driver);
375
376MODULE_LICENSE("GPL v2");
377MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY");
378MODULE_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
41struct rockchip_usb_phys {
42 int reg;
43 const char *pll_name;
44};
45
46struct rockchip_usb_phy_pdata {
47 struct rockchip_usb_phys *phys;
48};
49
50struct rockchip_usb_phy_base {
51 struct device *dev;
52 struct regmap *reg_base;
53 const struct rockchip_usb_phy_pdata *pdata;
54};
55
39struct rockchip_usb_phy { 56struct 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
46static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, 66static 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
53static int rockchip_usb_phy_power_off(struct phy *_phy) 73static 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
79static 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); 89static 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
68static int rockchip_usb_phy_power_on(struct phy *_phy) 99static 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); 114static 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
121static 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
130static 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
87static const struct phy_ops ops = { 137static 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
93static int rockchip_usb_phy_probe(struct platform_device *pdev) 143static 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
154static 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", &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", &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
236err_devm_action:
237 of_clk_del_provider(child);
238err_clk_prov:
239 clk_unregister(rk_phy->clk480m);
240err_clk:
241 if (rk_phy->clk)
242 clk_put(rk_phy->clk);
243 return err;
244}
245
246static 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
254static 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
262static 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
271static 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);
146put_child:
147 of_node_put(child);
148 return err;
149} 310}
150 311
151static const struct of_device_id rockchip_usb_phy_dt_ids[] = { 312static 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
95enum sun4i_usb_phy_type {
96 sun4i_a10_phy,
97 sun8i_a33_phy,
98 sun8i_h3_phy,
99};
100
101struct 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
91struct sun4i_usb_phy_data { 109struct 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
696static 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
704static 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
712static 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
720static 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
728static 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
736static 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
744static 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
692static const struct of_device_id sun4i_usb_phy_of_match[] = { 751static 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};
701MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); 761MODULE_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
145static int ti_pipe3_power_off(struct phy *x) 161static 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
154static int ti_pipe3_power_on(struct phy *x) 179static 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
163static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy) 208static 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
309static const struct of_device_id ti_pipe3_id_table[]; 361static const struct of_device_id ti_pipe3_id_table[];
310 362
311static int ti_pipe3_probe(struct platform_device *pdev) 363static 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; 432static 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
509static 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); 539static 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
33enum 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
33struct omap_usb { 39struct 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
45struct usb_phy_data { 57struct 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)