summaryrefslogtreecommitdiffstats
path: root/drivers/phy
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-21 00:12:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-21 00:12:25 -0400
commit19e36ad292ab24980db64a5ff17973d3118a8fb9 (patch)
tree175715409a689814e5cd425a98f2d2d47f82addf /drivers/phy
parente10abc629f38efd9b6936cf3612583cc846104d9 (diff)
parent60d5794fe5a50d02f4a0df84b45910a4dfa8b487 (diff)
Merge tag 'usb-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH: "Here's the big pull request for USB and PHY drivers for 4.7-rc1 Full details in the shortlog, but it's the normal major gadget driver updates, phy updates, new usbip code, as well as a bit of lots of other stuff. All have been in linux-next with no reported issues" * tag 'usb-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (164 commits) USB: serial: ti_usb_3410_5052: add MOXA UPORT 11x0 support USB: serial: fix minor-number allocation USB: serial: quatech2: fix use-after-free in probe error path USB: serial: mxuport: fix use-after-free in probe error path USB: serial: keyspan: fix debug and error messages USB: serial: keyspan: fix URB unlink USB: serial: keyspan: fix use-after-free in probe error path USB: serial: io_edgeport: fix memory leaks in probe error path USB: serial: io_edgeport: fix memory leaks in attach error path usb: Remove unnecessary space before operator ','. usb: Remove unnecessary space before open square bracket. USB: FHCI: avoid redundant condition usb: host: xhci-rcar: Avoid long wait in xhci_reset() usb/host/fotg210: remove dead code in create_sysfs_files usb: wusbcore: Do not initialise statics to 0. usb: wusbcore: Remove space before ',' and '(' . USB: serial: cp210x: clean up CRTSCTS flag code USB: serial: cp210x: get rid of magic numbers in CRTSCTS flag code USB: serial: cp210x: fix hardware flow-control disable USB: serial: option: add even more ZTE device ids ...
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/Kconfig33
-rw-r--r--drivers/phy/Makefile3
-rw-r--r--drivers/phy/phy-bcm-ns-usb2.c137
-rw-r--r--drivers/phy/phy-brcm-sata.c412
-rw-r--r--drivers/phy/phy-brcmstb-sata.c250
-rw-r--r--drivers/phy/phy-exynos-mipi-video.c321
-rw-r--r--drivers/phy/phy-mt65xx-usb3.c77
-rw-r--r--drivers/phy/phy-rcar-gen2.c1
-rw-r--r--drivers/phy/phy-rcar-gen3-usb2.c88
-rw-r--r--drivers/phy/phy-rockchip-usb.c2
10 files changed, 952 insertions, 372 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 27e5f6ee9a2a..b869b98835f4 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -15,6 +15,15 @@ config GENERIC_PHY
15 phy users can obtain reference to the PHY. All the users of this 15 phy users can obtain reference to the PHY. All the users of this
16 framework should select this config. 16 framework should select this config.
17 17
18config PHY_BCM_NS_USB2
19 tristate "Broadcom Northstar USB 2.0 PHY Driver"
20 depends on ARCH_BCM_IPROC || COMPILE_TEST
21 depends on HAS_IOMEM && OF
22 select GENERIC_PHY
23 help
24 Enable this to support Broadcom USB 2.0 PHY connected to the USB
25 controller on Northstar family.
26
18config PHY_BERLIN_USB 27config PHY_BERLIN_USB
19 tristate "Marvell Berlin USB PHY Driver" 28 tristate "Marvell Berlin USB PHY Driver"
20 depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF 29 depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
@@ -113,14 +122,15 @@ config PHY_MIPHY365X
113 122
114config PHY_RCAR_GEN2 123config PHY_RCAR_GEN2
115 tristate "Renesas R-Car generation 2 USB PHY driver" 124 tristate "Renesas R-Car generation 2 USB PHY driver"
116 depends on ARCH_SHMOBILE 125 depends on ARCH_RENESAS
117 depends on GENERIC_PHY 126 depends on GENERIC_PHY
118 help 127 help
119 Support for USB PHY found on Renesas R-Car generation 2 SoCs. 128 Support for USB PHY found on Renesas R-Car generation 2 SoCs.
120 129
121config PHY_RCAR_GEN3_USB2 130config PHY_RCAR_GEN3_USB2
122 tristate "Renesas R-Car generation 3 USB 2.0 PHY driver" 131 tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
123 depends on OF && ARCH_SHMOBILE 132 depends on ARCH_RENESAS
133 depends on EXTCON
124 select GENERIC_PHY 134 select GENERIC_PHY
125 help 135 help
126 Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs. 136 Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs.
@@ -218,9 +228,8 @@ config PHY_MT65XX_USB3
218 depends on ARCH_MEDIATEK && OF 228 depends on ARCH_MEDIATEK && OF
219 select GENERIC_PHY 229 select GENERIC_PHY
220 help 230 help
221 Say 'Y' here to add support for Mediatek USB3.0 PHY driver 231 Say 'Y' here to add support for Mediatek USB3.0 PHY driver,
222 for mt65xx SoCs. it supports two usb2.0 ports and 232 it supports multiple usb2.0 and usb3.0 ports.
223 one usb3.0 port.
224 233
225config PHY_HI6220_USB 234config PHY_HI6220_USB
226 tristate "hi6220 USB PHY support" 235 tristate "hi6220 USB PHY support"
@@ -250,7 +259,8 @@ config PHY_SUN9I_USB
250 tristate "Allwinner sun9i SoC USB PHY driver" 259 tristate "Allwinner sun9i SoC USB PHY driver"
251 depends on ARCH_SUNXI && HAS_IOMEM && OF 260 depends on ARCH_SUNXI && HAS_IOMEM && OF
252 depends on RESET_CONTROLLER 261 depends on RESET_CONTROLLER
253 depends on USB_COMMON 262 depends on USB_SUPPORT
263 select USB_COMMON
254 select GENERIC_PHY 264 select GENERIC_PHY
255 help 265 help
256 Enable this to support the transceiver that is part of Allwinner 266 Enable this to support the transceiver that is part of Allwinner
@@ -403,14 +413,15 @@ config PHY_TUSB1210
403 help 413 help
404 Support for TI TUSB1210 USB ULPI PHY. 414 Support for TI TUSB1210 USB ULPI PHY.
405 415
406config PHY_BRCMSTB_SATA 416config PHY_BRCM_SATA
407 tristate "Broadcom STB SATA PHY driver" 417 tristate "Broadcom SATA PHY driver"
408 depends on ARCH_BRCMSTB || BMIPS_GENERIC 418 depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST
409 depends on OF 419 depends on OF
410 select GENERIC_PHY 420 select GENERIC_PHY
421 default ARCH_BCM_IPROC
411 help 422 help
412 Enable this to support the SATA3 PHY on 28nm or 40nm Broadcom STB SoCs. 423 Enable this to support the Broadcom SATA PHY.
413 Likely useful only with CONFIG_SATA_BRCMSTB enabled. 424 If unsure, say N.
414 425
415config PHY_CYGNUS_PCIE 426config PHY_CYGNUS_PCIE
416 tristate "Broadcom Cygnus PCIe PHY driver" 427 tristate "Broadcom Cygnus PCIe PHY driver"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index d4f06e69fd9a..9c3e73ccabc4 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,6 +3,7 @@
3# 3#
4 4
5obj-$(CONFIG_GENERIC_PHY) += phy-core.o 5obj-$(CONFIG_GENERIC_PHY) += phy-core.o
6obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o
6obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o 7obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
7obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o 8obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
8obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o 9obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
@@ -49,7 +50,7 @@ obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
49obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o 50obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
50obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o 51obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
51obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o 52obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
52obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o 53obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o
53obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o 54obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
54obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o 55obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
55 56
diff --git a/drivers/phy/phy-bcm-ns-usb2.c b/drivers/phy/phy-bcm-ns-usb2.c
new file mode 100644
index 000000000000..95ab6b2a0de5
--- /dev/null
+++ b/drivers/phy/phy-bcm-ns-usb2.c
@@ -0,0 +1,137 @@
1/*
2 * Broadcom Northstar USB 2.0 PHY Driver
3 *
4 * Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/bcma/bcma.h>
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/module.h>
17#include <linux/of_address.h>
18#include <linux/of_platform.h>
19#include <linux/phy/phy.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22
23struct bcm_ns_usb2 {
24 struct device *dev;
25 struct clk *ref_clk;
26 struct phy *phy;
27 void __iomem *dmu;
28};
29
30static int bcm_ns_usb2_phy_init(struct phy *phy)
31{
32 struct bcm_ns_usb2 *usb2 = phy_get_drvdata(phy);
33 struct device *dev = usb2->dev;
34 void __iomem *dmu = usb2->dmu;
35 u32 ref_clk_rate, usb2ctl, usb_pll_ndiv, usb_pll_pdiv;
36 int err = 0;
37
38 err = clk_prepare_enable(usb2->ref_clk);
39 if (err < 0) {
40 dev_err(dev, "Failed to prepare ref clock: %d\n", err);
41 goto err_out;
42 }
43
44 ref_clk_rate = clk_get_rate(usb2->ref_clk);
45 if (!ref_clk_rate) {
46 dev_err(dev, "Failed to get ref clock rate\n");
47 err = -EINVAL;
48 goto err_clk_off;
49 }
50
51 usb2ctl = readl(dmu + BCMA_DMU_CRU_USB2_CONTROL);
52
53 if (usb2ctl & BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK) {
54 usb_pll_pdiv = usb2ctl;
55 usb_pll_pdiv &= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK;
56 usb_pll_pdiv >>= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT;
57 } else {
58 usb_pll_pdiv = 1 << 3;
59 }
60
61 /* Calculate ndiv based on a solid 1920 MHz that is for USB2 PHY */
62 usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
63
64 /* Unlock DMU PLL settings with some magic value */
65 writel(0x0000ea68, dmu + BCMA_DMU_CRU_CLKSET_KEY);
66
67 /* Write USB 2.0 PLL control setting */
68 usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
69 usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
70 writel(usb2ctl, dmu + BCMA_DMU_CRU_USB2_CONTROL);
71
72 /* Lock DMU PLL settings */
73 writel(0x00000000, dmu + BCMA_DMU_CRU_CLKSET_KEY);
74
75err_clk_off:
76 clk_disable_unprepare(usb2->ref_clk);
77err_out:
78 return err;
79}
80
81static const struct phy_ops ops = {
82 .init = bcm_ns_usb2_phy_init,
83 .owner = THIS_MODULE,
84};
85
86static int bcm_ns_usb2_probe(struct platform_device *pdev)
87{
88 struct device *dev = &pdev->dev;
89 struct bcm_ns_usb2 *usb2;
90 struct resource *res;
91 struct phy_provider *phy_provider;
92
93 usb2 = devm_kzalloc(&pdev->dev, sizeof(*usb2), GFP_KERNEL);
94 if (!usb2)
95 return -ENOMEM;
96 usb2->dev = dev;
97
98 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmu");
99 usb2->dmu = devm_ioremap_resource(dev, res);
100 if (IS_ERR(usb2->dmu)) {
101 dev_err(dev, "Failed to map DMU regs\n");
102 return PTR_ERR(usb2->dmu);
103 }
104
105 usb2->ref_clk = devm_clk_get(dev, "phy-ref-clk");
106 if (IS_ERR(usb2->ref_clk)) {
107 dev_err(dev, "Clock not defined\n");
108 return PTR_ERR(usb2->ref_clk);
109 }
110
111 usb2->phy = devm_phy_create(dev, NULL, &ops);
112 if (IS_ERR(dev))
113 return PTR_ERR(dev);
114
115 phy_set_drvdata(usb2->phy, usb2);
116 platform_set_drvdata(pdev, usb2);
117
118 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
119 return PTR_ERR_OR_ZERO(phy_provider);
120}
121
122static const struct of_device_id bcm_ns_usb2_id_table[] = {
123 { .compatible = "brcm,ns-usb2-phy", },
124 {},
125};
126MODULE_DEVICE_TABLE(of, bcm_ns_usb2_id_table);
127
128static struct platform_driver bcm_ns_usb2_driver = {
129 .probe = bcm_ns_usb2_probe,
130 .driver = {
131 .name = "bcm_ns_usb2",
132 .of_match_table = bcm_ns_usb2_id_table,
133 },
134};
135module_platform_driver(bcm_ns_usb2_driver);
136
137MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-brcm-sata.c b/drivers/phy/phy-brcm-sata.c
new file mode 100644
index 000000000000..6c4c5cb791ca
--- /dev/null
+++ b/drivers/phy/phy-brcm-sata.c
@@ -0,0 +1,412 @@
1/*
2 * Broadcom SATA3 AHCI Controller PHY Driver
3 *
4 * Copyright (C) 2016 Broadcom
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/delay.h>
18#include <linux/device.h>
19#include <linux/init.h>
20#include <linux/interrupt.h>
21#include <linux/io.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/of.h>
25#include <linux/phy/phy.h>
26#include <linux/platform_device.h>
27
28#define SATA_PCB_BANK_OFFSET 0x23c
29#define SATA_PCB_REG_OFFSET(ofs) ((ofs) * 4)
30
31#define MAX_PORTS 2
32
33/* Register offset between PHYs in PCB space */
34#define SATA_PCB_REG_28NM_SPACE_SIZE 0x1000
35
36/* The older SATA PHY registers duplicated per port registers within the map,
37 * rather than having a separate map per port.
38 */
39#define SATA_PCB_REG_40NM_SPACE_SIZE 0x10
40
41/* Register offset between PHYs in PHY control space */
42#define SATA_PHY_CTRL_REG_28NM_SPACE_SIZE 0x8
43
44enum brcm_sata_phy_version {
45 BRCM_SATA_PHY_STB_28NM,
46 BRCM_SATA_PHY_STB_40NM,
47 BRCM_SATA_PHY_IPROC_NS2,
48};
49
50struct brcm_sata_port {
51 int portnum;
52 struct phy *phy;
53 struct brcm_sata_phy *phy_priv;
54 bool ssc_en;
55};
56
57struct brcm_sata_phy {
58 struct device *dev;
59 void __iomem *phy_base;
60 void __iomem *ctrl_base;
61 enum brcm_sata_phy_version version;
62
63 struct brcm_sata_port phys[MAX_PORTS];
64};
65
66enum sata_phy_regs {
67 BLOCK0_REG_BANK = 0x000,
68 BLOCK0_XGXSSTATUS = 0x81,
69 BLOCK0_XGXSSTATUS_PLL_LOCK = BIT(12),
70 BLOCK0_SPARE = 0x8d,
71 BLOCK0_SPARE_OOB_CLK_SEL_MASK = 0x3,
72 BLOCK0_SPARE_OOB_CLK_SEL_REFBY2 = 0x1,
73
74 PLL_REG_BANK_0 = 0x050,
75 PLL_REG_BANK_0_PLLCONTROL_0 = 0x81,
76
77 PLL1_REG_BANK = 0x060,
78 PLL1_ACTRL2 = 0x82,
79 PLL1_ACTRL3 = 0x83,
80 PLL1_ACTRL4 = 0x84,
81
82 OOB_REG_BANK = 0x150,
83 OOB_CTRL1 = 0x80,
84 OOB_CTRL1_BURST_MAX_MASK = 0xf,
85 OOB_CTRL1_BURST_MAX_SHIFT = 12,
86 OOB_CTRL1_BURST_MIN_MASK = 0xf,
87 OOB_CTRL1_BURST_MIN_SHIFT = 8,
88 OOB_CTRL1_WAKE_IDLE_MAX_MASK = 0xf,
89 OOB_CTRL1_WAKE_IDLE_MAX_SHIFT = 4,
90 OOB_CTRL1_WAKE_IDLE_MIN_MASK = 0xf,
91 OOB_CTRL1_WAKE_IDLE_MIN_SHIFT = 0,
92 OOB_CTRL2 = 0x81,
93 OOB_CTRL2_SEL_ENA_SHIFT = 15,
94 OOB_CTRL2_SEL_ENA_RC_SHIFT = 14,
95 OOB_CTRL2_RESET_IDLE_MAX_MASK = 0x3f,
96 OOB_CTRL2_RESET_IDLE_MAX_SHIFT = 8,
97 OOB_CTRL2_BURST_CNT_MASK = 0x3,
98 OOB_CTRL2_BURST_CNT_SHIFT = 6,
99 OOB_CTRL2_RESET_IDLE_MIN_MASK = 0x3f,
100 OOB_CTRL2_RESET_IDLE_MIN_SHIFT = 0,
101
102 TXPMD_REG_BANK = 0x1a0,
103 TXPMD_CONTROL1 = 0x81,
104 TXPMD_CONTROL1_TX_SSC_EN_FRC = BIT(0),
105 TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL = BIT(1),
106 TXPMD_TX_FREQ_CTRL_CONTROL1 = 0x82,
107 TXPMD_TX_FREQ_CTRL_CONTROL2 = 0x83,
108 TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK = 0x3ff,
109 TXPMD_TX_FREQ_CTRL_CONTROL3 = 0x84,
110 TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK = 0x3ff,
111};
112
113enum sata_phy_ctrl_regs {
114 PHY_CTRL_1 = 0x0,
115 PHY_CTRL_1_RESET = BIT(0),
116};
117
118static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port)
119{
120 struct brcm_sata_phy *priv = port->phy_priv;
121 u32 size = 0;
122
123 switch (priv->version) {
124 case BRCM_SATA_PHY_STB_28NM:
125 case BRCM_SATA_PHY_IPROC_NS2:
126 size = SATA_PCB_REG_28NM_SPACE_SIZE;
127 break;
128 case BRCM_SATA_PHY_STB_40NM:
129 size = SATA_PCB_REG_40NM_SPACE_SIZE;
130 break;
131 default:
132 dev_err(priv->dev, "invalid phy version\n");
133 break;
134 };
135
136 return priv->phy_base + (port->portnum * size);
137}
138
139static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port)
140{
141 struct brcm_sata_phy *priv = port->phy_priv;
142 u32 size = 0;
143
144 switch (priv->version) {
145 case BRCM_SATA_PHY_IPROC_NS2:
146 size = SATA_PHY_CTRL_REG_28NM_SPACE_SIZE;
147 break;
148 default:
149 dev_err(priv->dev, "invalid phy version\n");
150 break;
151 };
152
153 return priv->ctrl_base + (port->portnum * size);
154}
155
156static void brcm_sata_phy_wr(void __iomem *pcb_base, u32 bank,
157 u32 ofs, u32 msk, u32 value)
158{
159 u32 tmp;
160
161 writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
162 tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
163 tmp = (tmp & msk) | value;
164 writel(tmp, pcb_base + SATA_PCB_REG_OFFSET(ofs));
165}
166
167static u32 brcm_sata_phy_rd(void __iomem *pcb_base, u32 bank, u32 ofs)
168{
169 writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
170 return readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
171}
172
173/* These defaults were characterized by H/W group */
174#define STB_FMIN_VAL_DEFAULT 0x3df
175#define STB_FMAX_VAL_DEFAULT 0x3df
176#define STB_FMAX_VAL_SSC 0x83
177
178static int brcm_stb_sata_init(struct brcm_sata_port *port)
179{
180 void __iomem *base = brcm_sata_pcb_base(port);
181 struct brcm_sata_phy *priv = port->phy_priv;
182 u32 tmp;
183
184 /* override the TX spread spectrum setting */
185 tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC;
186 brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
187
188 /* set fixed min freq */
189 brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
190 ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK,
191 STB_FMIN_VAL_DEFAULT);
192
193 /* set fixed max freq depending on SSC config */
194 if (port->ssc_en) {
195 dev_info(priv->dev, "enabling SSC on port%d\n", port->portnum);
196 tmp = STB_FMAX_VAL_SSC;
197 } else {
198 tmp = STB_FMAX_VAL_DEFAULT;
199 }
200
201 brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
202 ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
203
204 return 0;
205}
206
207/* NS2 SATA PLL1 defaults were characterized by H/W group */
208#define NS2_PLL1_ACTRL2_MAGIC 0x1df8
209#define NS2_PLL1_ACTRL3_MAGIC 0x2b00
210#define NS2_PLL1_ACTRL4_MAGIC 0x8824
211
212static int brcm_ns2_sata_init(struct brcm_sata_port *port)
213{
214 int try;
215 unsigned int val;
216 void __iomem *base = brcm_sata_pcb_base(port);
217 void __iomem *ctrl_base = brcm_sata_ctrl_base(port);
218 struct device *dev = port->phy_priv->dev;
219
220 /* Configure OOB control */
221 val = 0x0;
222 val |= (0xc << OOB_CTRL1_BURST_MAX_SHIFT);
223 val |= (0x4 << OOB_CTRL1_BURST_MIN_SHIFT);
224 val |= (0x9 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
225 val |= (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
226 brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
227 val = 0x0;
228 val |= (0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
229 val |= (0x2 << OOB_CTRL2_BURST_CNT_SHIFT);
230 val |= (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
231 brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
232
233 /* Configure PHY PLL register bank 1 */
234 val = NS2_PLL1_ACTRL2_MAGIC;
235 brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
236 val = NS2_PLL1_ACTRL3_MAGIC;
237 brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
238 val = NS2_PLL1_ACTRL4_MAGIC;
239 brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
240
241 /* Configure PHY BLOCK0 register bank */
242 /* Set oob_clk_sel to refclk/2 */
243 brcm_sata_phy_wr(base, BLOCK0_REG_BANK, BLOCK0_SPARE,
244 ~BLOCK0_SPARE_OOB_CLK_SEL_MASK,
245 BLOCK0_SPARE_OOB_CLK_SEL_REFBY2);
246
247 /* Strobe PHY reset using PHY control register */
248 writel(PHY_CTRL_1_RESET, ctrl_base + PHY_CTRL_1);
249 mdelay(1);
250 writel(0x0, ctrl_base + PHY_CTRL_1);
251 mdelay(1);
252
253 /* Wait for PHY PLL lock by polling pll_lock bit */
254 try = 50;
255 while (try) {
256 val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
257 BLOCK0_XGXSSTATUS);
258 if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
259 break;
260 msleep(20);
261 try--;
262 }
263 if (!try) {
264 /* PLL did not lock; give up */
265 dev_err(dev, "port%d PLL did not lock\n", port->portnum);
266 return -ETIMEDOUT;
267 }
268
269 dev_dbg(dev, "port%d initialized\n", port->portnum);
270
271 return 0;
272}
273
274static int brcm_sata_phy_init(struct phy *phy)
275{
276 int rc;
277 struct brcm_sata_port *port = phy_get_drvdata(phy);
278
279 switch (port->phy_priv->version) {
280 case BRCM_SATA_PHY_STB_28NM:
281 case BRCM_SATA_PHY_STB_40NM:
282 rc = brcm_stb_sata_init(port);
283 break;
284 case BRCM_SATA_PHY_IPROC_NS2:
285 rc = brcm_ns2_sata_init(port);
286 break;
287 default:
288 rc = -ENODEV;
289 };
290
291 return 0;
292}
293
294static const struct phy_ops phy_ops = {
295 .init = brcm_sata_phy_init,
296 .owner = THIS_MODULE,
297};
298
299static const struct of_device_id brcm_sata_phy_of_match[] = {
300 { .compatible = "brcm,bcm7445-sata-phy",
301 .data = (void *)BRCM_SATA_PHY_STB_28NM },
302 { .compatible = "brcm,bcm7425-sata-phy",
303 .data = (void *)BRCM_SATA_PHY_STB_40NM },
304 { .compatible = "brcm,iproc-ns2-sata-phy",
305 .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
306 {},
307};
308MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
309
310static int brcm_sata_phy_probe(struct platform_device *pdev)
311{
312 struct device *dev = &pdev->dev;
313 struct device_node *dn = dev->of_node, *child;
314 const struct of_device_id *of_id;
315 struct brcm_sata_phy *priv;
316 struct resource *res;
317 struct phy_provider *provider;
318 int ret, count = 0;
319
320 if (of_get_child_count(dn) == 0)
321 return -ENODEV;
322
323 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
324 if (!priv)
325 return -ENOMEM;
326 dev_set_drvdata(dev, priv);
327 priv->dev = dev;
328
329 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
330 priv->phy_base = devm_ioremap_resource(dev, res);
331 if (IS_ERR(priv->phy_base))
332 return PTR_ERR(priv->phy_base);
333
334 of_id = of_match_node(brcm_sata_phy_of_match, dn);
335 if (of_id)
336 priv->version = (enum brcm_sata_phy_version)of_id->data;
337 else
338 priv->version = BRCM_SATA_PHY_STB_28NM;
339
340 if (priv->version == BRCM_SATA_PHY_IPROC_NS2) {
341 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
342 "phy-ctrl");
343 priv->ctrl_base = devm_ioremap_resource(dev, res);
344 if (IS_ERR(priv->ctrl_base))
345 return PTR_ERR(priv->ctrl_base);
346 }
347
348 for_each_available_child_of_node(dn, child) {
349 unsigned int id;
350 struct brcm_sata_port *port;
351
352 if (of_property_read_u32(child, "reg", &id)) {
353 dev_err(dev, "missing reg property in node %s\n",
354 child->name);
355 ret = -EINVAL;
356 goto put_child;
357 }
358
359 if (id >= MAX_PORTS) {
360 dev_err(dev, "invalid reg: %u\n", id);
361 ret = -EINVAL;
362 goto put_child;
363 }
364 if (priv->phys[id].phy) {
365 dev_err(dev, "already registered port %u\n", id);
366 ret = -EINVAL;
367 goto put_child;
368 }
369
370 port = &priv->phys[id];
371 port->portnum = id;
372 port->phy_priv = priv;
373 port->phy = devm_phy_create(dev, child, &phy_ops);
374 port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
375 if (IS_ERR(port->phy)) {
376 dev_err(dev, "failed to create PHY\n");
377 ret = PTR_ERR(port->phy);
378 goto put_child;
379 }
380
381 phy_set_drvdata(port->phy, port);
382 count++;
383 }
384
385 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
386 if (IS_ERR(provider)) {
387 dev_err(dev, "could not register PHY provider\n");
388 return PTR_ERR(provider);
389 }
390
391 dev_info(dev, "registered %d port(s)\n", count);
392
393 return 0;
394put_child:
395 of_node_put(child);
396 return ret;
397}
398
399static struct platform_driver brcm_sata_phy_driver = {
400 .probe = brcm_sata_phy_probe,
401 .driver = {
402 .of_match_table = brcm_sata_phy_of_match,
403 .name = "brcm-sata-phy",
404 }
405};
406module_platform_driver(brcm_sata_phy_driver);
407
408MODULE_DESCRIPTION("Broadcom SATA PHY driver");
409MODULE_LICENSE("GPL");
410MODULE_AUTHOR("Marc Carino");
411MODULE_AUTHOR("Brian Norris");
412MODULE_ALIAS("platform:phy-brcm-sata");
diff --git a/drivers/phy/phy-brcmstb-sata.c b/drivers/phy/phy-brcmstb-sata.c
deleted file mode 100644
index a23172ff40e3..000000000000
--- a/drivers/phy/phy-brcmstb-sata.c
+++ /dev/null
@@ -1,250 +0,0 @@
1/*
2 * Broadcom SATA3 AHCI Controller PHY Driver
3 *
4 * Copyright © 2009-2015 Broadcom Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/device.h>
18#include <linux/init.h>
19#include <linux/interrupt.h>
20#include <linux/io.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/of.h>
24#include <linux/phy/phy.h>
25#include <linux/platform_device.h>
26
27#define SATA_MDIO_BANK_OFFSET 0x23c
28#define SATA_MDIO_REG_OFFSET(ofs) ((ofs) * 4)
29
30#define MAX_PORTS 2
31
32/* Register offset between PHYs in PCB space */
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};
44
45struct brcm_sata_port {
46 int portnum;
47 struct phy *phy;
48 struct brcm_sata_phy *phy_priv;
49 bool ssc_en;
50};
51
52struct brcm_sata_phy {
53 struct device *dev;
54 void __iomem *phy_base;
55 enum brcm_sata_phy_version version;
56
57 struct brcm_sata_port phys[MAX_PORTS];
58};
59
60enum sata_mdio_phy_regs {
61 PLL_REG_BANK_0 = 0x50,
62 PLL_REG_BANK_0_PLLCONTROL_0 = 0x81,
63
64 TXPMD_REG_BANK = 0x1a0,
65 TXPMD_CONTROL1 = 0x81,
66 TXPMD_CONTROL1_TX_SSC_EN_FRC = BIT(0),
67 TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL = BIT(1),
68 TXPMD_TX_FREQ_CTRL_CONTROL1 = 0x82,
69 TXPMD_TX_FREQ_CTRL_CONTROL2 = 0x83,
70 TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK = 0x3ff,
71 TXPMD_TX_FREQ_CTRL_CONTROL3 = 0x84,
72 TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK = 0x3ff,
73};
74
75static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port)
76{
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");
86
87 return priv->phy_base + (port->portnum * offset);
88}
89
90static void brcm_sata_mdio_wr(void __iomem *addr, u32 bank, u32 ofs,
91 u32 msk, u32 value)
92{
93 u32 tmp;
94
95 writel(bank, addr + SATA_MDIO_BANK_OFFSET);
96 tmp = readl(addr + SATA_MDIO_REG_OFFSET(ofs));
97 tmp = (tmp & msk) | value;
98 writel(tmp, addr + SATA_MDIO_REG_OFFSET(ofs));
99}
100
101/* These defaults were characterized by H/W group */
102#define FMIN_VAL_DEFAULT 0x3df
103#define FMAX_VAL_DEFAULT 0x3df
104#define FMAX_VAL_SSC 0x83
105
106static void brcm_sata_cfg_ssc(struct brcm_sata_port *port)
107{
108 void __iomem *base = brcm_sata_phy_base(port);
109 struct brcm_sata_phy *priv = port->phy_priv;
110 u32 tmp;
111
112 /* override the TX spread spectrum setting */
113 tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC;
114 brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
115
116 /* set fixed min freq */
117 brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
118 ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK,
119 FMIN_VAL_DEFAULT);
120
121 /* set fixed max freq depending on SSC config */
122 if (port->ssc_en) {
123 dev_info(priv->dev, "enabling SSC on port %d\n", port->portnum);
124 tmp = FMAX_VAL_SSC;
125 } else {
126 tmp = FMAX_VAL_DEFAULT;
127 }
128
129 brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
130 ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
131}
132
133static int brcm_sata_phy_init(struct phy *phy)
134{
135 struct brcm_sata_port *port = phy_get_drvdata(phy);
136
137 brcm_sata_cfg_ssc(port);
138
139 return 0;
140}
141
142static const struct phy_ops phy_ops = {
143 .init = brcm_sata_phy_init,
144 .owner = THIS_MODULE,
145};
146
147static const struct of_device_id brcm_sata_phy_of_match[] = {
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 },
152 {},
153};
154MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
155
156static int brcm_sata_phy_probe(struct platform_device *pdev)
157{
158 struct device *dev = &pdev->dev;
159 struct device_node *dn = dev->of_node, *child;
160 const struct of_device_id *of_id;
161 struct brcm_sata_phy *priv;
162 struct resource *res;
163 struct phy_provider *provider;
164 int ret, count = 0;
165
166 if (of_get_child_count(dn) == 0)
167 return -ENODEV;
168
169 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
170 if (!priv)
171 return -ENOMEM;
172 dev_set_drvdata(dev, priv);
173 priv->dev = dev;
174
175 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
176 priv->phy_base = devm_ioremap_resource(dev, res);
177 if (IS_ERR(priv->phy_base))
178 return PTR_ERR(priv->phy_base);
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
186 for_each_available_child_of_node(dn, child) {
187 unsigned int id;
188 struct brcm_sata_port *port;
189
190 if (of_property_read_u32(child, "reg", &id)) {
191 dev_err(dev, "missing reg property in node %s\n",
192 child->name);
193 ret = -EINVAL;
194 goto put_child;
195 }
196
197 if (id >= MAX_PORTS) {
198 dev_err(dev, "invalid reg: %u\n", id);
199 ret = -EINVAL;
200 goto put_child;
201 }
202 if (priv->phys[id].phy) {
203 dev_err(dev, "already registered port %u\n", id);
204 ret = -EINVAL;
205 goto put_child;
206 }
207
208 port = &priv->phys[id];
209 port->portnum = id;
210 port->phy_priv = priv;
211 port->phy = devm_phy_create(dev, child, &phy_ops);
212 port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
213 if (IS_ERR(port->phy)) {
214 dev_err(dev, "failed to create PHY\n");
215 ret = PTR_ERR(port->phy);
216 goto put_child;
217 }
218
219 phy_set_drvdata(port->phy, port);
220 count++;
221 }
222
223 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
224 if (IS_ERR(provider)) {
225 dev_err(dev, "could not register PHY provider\n");
226 return PTR_ERR(provider);
227 }
228
229 dev_info(dev, "registered %d port(s)\n", count);
230
231 return 0;
232put_child:
233 of_node_put(child);
234 return ret;
235}
236
237static struct platform_driver brcm_sata_phy_driver = {
238 .probe = brcm_sata_phy_probe,
239 .driver = {
240 .of_match_table = brcm_sata_phy_of_match,
241 .name = "brcmstb-sata-phy",
242 }
243};
244module_platform_driver(brcm_sata_phy_driver);
245
246MODULE_DESCRIPTION("Broadcom STB SATA PHY driver");
247MODULE_LICENSE("GPL");
248MODULE_AUTHOR("Marc Carino");
249MODULE_AUTHOR("Brian Norris");
250MODULE_ALIAS("platform:phy-brcmstb-sata");
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index 2a54caba93b4..cc093ebfda94 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver 2 * Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
3 * 3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd. 4 * Copyright (C) 2013,2016 Samsung Electronics Co., Ltd.
5 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> 5 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -13,96 +13,276 @@
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/mfd/syscon/exynos4-pmu.h> 15#include <linux/mfd/syscon/exynos4-pmu.h>
16#include <linux/mfd/syscon/exynos5-pmu.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/of.h> 18#include <linux/of.h>
18#include <linux/of_address.h> 19#include <linux/of_address.h>
20#include <linux/of_device.h>
19#include <linux/phy/phy.h> 21#include <linux/phy/phy.h>
20#include <linux/platform_device.h>
21#include <linux/regmap.h> 22#include <linux/regmap.h>
22#include <linux/spinlock.h> 23#include <linux/spinlock.h>
23#include <linux/mfd/syscon.h> 24#include <linux/mfd/syscon.h>
24 25
25/* MIPI_PHYn_CONTROL reg. offset (for base address from ioremap): n = 0..1 */
26#define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4)
27
28enum exynos_mipi_phy_id { 26enum exynos_mipi_phy_id {
27 EXYNOS_MIPI_PHY_ID_NONE = -1,
29 EXYNOS_MIPI_PHY_ID_CSIS0, 28 EXYNOS_MIPI_PHY_ID_CSIS0,
30 EXYNOS_MIPI_PHY_ID_DSIM0, 29 EXYNOS_MIPI_PHY_ID_DSIM0,
31 EXYNOS_MIPI_PHY_ID_CSIS1, 30 EXYNOS_MIPI_PHY_ID_CSIS1,
32 EXYNOS_MIPI_PHY_ID_DSIM1, 31 EXYNOS_MIPI_PHY_ID_DSIM1,
32 EXYNOS_MIPI_PHY_ID_CSIS2,
33 EXYNOS_MIPI_PHYS_NUM 33 EXYNOS_MIPI_PHYS_NUM
34}; 34};
35 35
36#define is_mipi_dsim_phy_id(id) \ 36enum exynos_mipi_phy_regmap_id {
37 ((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1) 37 EXYNOS_MIPI_REGMAP_PMU,
38 EXYNOS_MIPI_REGMAP_DISP,
39 EXYNOS_MIPI_REGMAP_CAM0,
40 EXYNOS_MIPI_REGMAP_CAM1,
41 EXYNOS_MIPI_REGMAPS_NUM
42};
43
44struct mipi_phy_device_desc {
45 int num_phys;
46 int num_regmaps;
47 const char *regmap_names[EXYNOS_MIPI_REGMAPS_NUM];
48 struct exynos_mipi_phy_desc {
49 enum exynos_mipi_phy_id coupled_phy_id;
50 u32 enable_val;
51 unsigned int enable_reg;
52 enum exynos_mipi_phy_regmap_id enable_map;
53 u32 resetn_val;
54 unsigned int resetn_reg;
55 enum exynos_mipi_phy_regmap_id resetn_map;
56 } phys[EXYNOS_MIPI_PHYS_NUM];
57};
58
59static const struct mipi_phy_device_desc s5pv210_mipi_phy = {
60 .num_regmaps = 1,
61 .regmap_names = {"syscon"},
62 .num_phys = 4,
63 .phys = {
64 {
65 /* EXYNOS_MIPI_PHY_ID_CSIS0 */
66 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
67 .enable_val = EXYNOS4_MIPI_PHY_ENABLE,
68 .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
69 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
70 .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
71 .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
72 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
73 }, {
74 /* EXYNOS_MIPI_PHY_ID_DSIM0 */
75 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
76 .enable_val = EXYNOS4_MIPI_PHY_ENABLE,
77 .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
78 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
79 .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
80 .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
81 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
82 }, {
83 /* EXYNOS_MIPI_PHY_ID_CSIS1 */
84 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1,
85 .enable_val = EXYNOS4_MIPI_PHY_ENABLE,
86 .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
87 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
88 .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
89 .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
90 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
91 }, {
92 /* EXYNOS_MIPI_PHY_ID_DSIM1 */
93 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1,
94 .enable_val = EXYNOS4_MIPI_PHY_ENABLE,
95 .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
96 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
97 .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
98 .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
99 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
100 },
101 },
102};
103
104static const struct mipi_phy_device_desc exynos5420_mipi_phy = {
105 .num_regmaps = 1,
106 .regmap_names = {"syscon"},
107 .num_phys = 5,
108 .phys = {
109 {
110 /* EXYNOS_MIPI_PHY_ID_CSIS0 */
111 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
112 .enable_val = EXYNOS5_PHY_ENABLE,
113 .enable_reg = EXYNOS5420_MIPI_PHY0_CONTROL,
114 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
115 .resetn_val = EXYNOS5_MIPI_PHY_S_RESETN,
116 .resetn_reg = EXYNOS5420_MIPI_PHY0_CONTROL,
117 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
118 }, {
119 /* EXYNOS_MIPI_PHY_ID_DSIM0 */
120 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
121 .enable_val = EXYNOS5_PHY_ENABLE,
122 .enable_reg = EXYNOS5420_MIPI_PHY0_CONTROL,
123 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
124 .resetn_val = EXYNOS5_MIPI_PHY_M_RESETN,
125 .resetn_reg = EXYNOS5420_MIPI_PHY0_CONTROL,
126 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
127 }, {
128 /* EXYNOS_MIPI_PHY_ID_CSIS1 */
129 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1,
130 .enable_val = EXYNOS5_PHY_ENABLE,
131 .enable_reg = EXYNOS5420_MIPI_PHY1_CONTROL,
132 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
133 .resetn_val = EXYNOS5_MIPI_PHY_S_RESETN,
134 .resetn_reg = EXYNOS5420_MIPI_PHY1_CONTROL,
135 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
136 }, {
137 /* EXYNOS_MIPI_PHY_ID_DSIM1 */
138 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1,
139 .enable_val = EXYNOS5_PHY_ENABLE,
140 .enable_reg = EXYNOS5420_MIPI_PHY1_CONTROL,
141 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
142 .resetn_val = EXYNOS5_MIPI_PHY_M_RESETN,
143 .resetn_reg = EXYNOS5420_MIPI_PHY1_CONTROL,
144 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
145 }, {
146 /* EXYNOS_MIPI_PHY_ID_CSIS2 */
147 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
148 .enable_val = EXYNOS5_PHY_ENABLE,
149 .enable_reg = EXYNOS5420_MIPI_PHY2_CONTROL,
150 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
151 .resetn_val = EXYNOS5_MIPI_PHY_S_RESETN,
152 .resetn_reg = EXYNOS5420_MIPI_PHY2_CONTROL,
153 .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
154 },
155 },
156};
157
158#define EXYNOS5433_SYSREG_DISP_MIPI_PHY 0x100C
159#define EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON 0x1014
160#define EXYNOS5433_SYSREG_CAM1_MIPI_DPHY_CON 0x1020
161
162static const struct mipi_phy_device_desc exynos5433_mipi_phy = {
163 .num_regmaps = 4,
164 .regmap_names = {
165 "samsung,pmu-syscon",
166 "samsung,disp-sysreg",
167 "samsung,cam0-sysreg",
168 "samsung,cam1-sysreg"
169 },
170 .num_phys = 5,
171 .phys = {
172 {
173 /* EXYNOS_MIPI_PHY_ID_CSIS0 */
174 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
175 .enable_val = EXYNOS5_PHY_ENABLE,
176 .enable_reg = EXYNOS5433_MIPI_PHY0_CONTROL,
177 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
178 .resetn_val = BIT(0),
179 .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON,
180 .resetn_map = EXYNOS_MIPI_REGMAP_CAM0,
181 }, {
182 /* EXYNOS_MIPI_PHY_ID_DSIM0 */
183 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
184 .enable_val = EXYNOS5_PHY_ENABLE,
185 .enable_reg = EXYNOS5433_MIPI_PHY0_CONTROL,
186 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
187 .resetn_val = BIT(0),
188 .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY,
189 .resetn_map = EXYNOS_MIPI_REGMAP_DISP,
190 }, {
191 /* EXYNOS_MIPI_PHY_ID_CSIS1 */
192 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
193 .enable_val = EXYNOS5_PHY_ENABLE,
194 .enable_reg = EXYNOS5433_MIPI_PHY1_CONTROL,
195 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
196 .resetn_val = BIT(1),
197 .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON,
198 .resetn_map = EXYNOS_MIPI_REGMAP_CAM0,
199 }, {
200 /* EXYNOS_MIPI_PHY_ID_DSIM1 */
201 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
202 .enable_val = EXYNOS5_PHY_ENABLE,
203 .enable_reg = EXYNOS5433_MIPI_PHY1_CONTROL,
204 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
205 .resetn_val = BIT(1),
206 .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY,
207 .resetn_map = EXYNOS_MIPI_REGMAP_DISP,
208 }, {
209 /* EXYNOS_MIPI_PHY_ID_CSIS2 */
210 .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
211 .enable_val = EXYNOS5_PHY_ENABLE,
212 .enable_reg = EXYNOS5433_MIPI_PHY2_CONTROL,
213 .enable_map = EXYNOS_MIPI_REGMAP_PMU,
214 .resetn_val = BIT(0),
215 .resetn_reg = EXYNOS5433_SYSREG_CAM1_MIPI_DPHY_CON,
216 .resetn_map = EXYNOS_MIPI_REGMAP_CAM1,
217 },
218 },
219};
38 220
39struct exynos_mipi_video_phy { 221struct exynos_mipi_video_phy {
222 struct regmap *regmaps[EXYNOS_MIPI_REGMAPS_NUM];
223 int num_phys;
40 struct video_phy_desc { 224 struct video_phy_desc {
41 struct phy *phy; 225 struct phy *phy;
42 unsigned int index; 226 unsigned int index;
227 const struct exynos_mipi_phy_desc *data;
43 } phys[EXYNOS_MIPI_PHYS_NUM]; 228 } phys[EXYNOS_MIPI_PHYS_NUM];
44 spinlock_t slock; 229 spinlock_t slock;
45 void __iomem *regs;
46 struct regmap *regmap;
47}; 230};
48 231
49static int __set_phy_state(struct exynos_mipi_video_phy *state, 232static inline int __is_running(const struct exynos_mipi_phy_desc *data,
50 enum exynos_mipi_phy_id id, unsigned int on) 233 struct exynos_mipi_video_phy *state)
51{ 234{
52 const unsigned int offset = EXYNOS4_MIPI_PHY_CONTROL(id / 2); 235 u32 val;
53 void __iomem *addr;
54 u32 val, reset;
55 236
56 if (is_mipi_dsim_phy_id(id)) 237 regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
57 reset = EXYNOS4_MIPI_PHY_MRESETN; 238 return val & data->resetn_val;
58 else 239}
59 reset = EXYNOS4_MIPI_PHY_SRESETN; 240
241static int __set_phy_state(const struct exynos_mipi_phy_desc *data,
242 struct exynos_mipi_video_phy *state, unsigned int on)
243{
244 u32 val;
60 245
61 spin_lock(&state->slock); 246 spin_lock(&state->slock);
62 247
63 if (!IS_ERR(state->regmap)) { 248 /* disable in PMU sysreg */
64 regmap_read(state->regmap, offset, &val); 249 if (!on && data->coupled_phy_id >= 0 &&
65 if (on) 250 !__is_running(state->phys[data->coupled_phy_id].data, state)) {
66 val |= reset; 251 regmap_read(state->regmaps[data->enable_map], data->enable_reg,
67 else 252 &val);
68 val &= ~reset; 253 val &= ~data->enable_val;
69 regmap_write(state->regmap, offset, val); 254 regmap_write(state->regmaps[data->enable_map], data->enable_reg,
70 if (on) 255 val);
71 val |= EXYNOS4_MIPI_PHY_ENABLE; 256 }
72 else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK)) 257
73 val &= ~EXYNOS4_MIPI_PHY_ENABLE; 258 /* PHY reset */
74 regmap_write(state->regmap, offset, val); 259 regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
75 } else { 260 val = on ? (val | data->resetn_val) : (val & ~data->resetn_val);
76 addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2); 261 regmap_write(state->regmaps[data->resetn_map], data->resetn_reg, val);
77 262
78 val = readl(addr); 263 /* enable in PMU sysreg */
79 if (on) 264 if (on) {
80 val |= reset; 265 regmap_read(state->regmaps[data->enable_map], data->enable_reg,
81 else 266 &val);
82 val &= ~reset; 267 val |= data->enable_val;
83 writel(val, addr); 268 regmap_write(state->regmaps[data->enable_map], data->enable_reg,
84 /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set */ 269 val);
85 if (on)
86 val |= EXYNOS4_MIPI_PHY_ENABLE;
87 else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK))
88 val &= ~EXYNOS4_MIPI_PHY_ENABLE;
89
90 writel(val, addr);
91 } 270 }
92 271
93 spin_unlock(&state->slock); 272 spin_unlock(&state->slock);
273
94 return 0; 274 return 0;
95} 275}
96 276
97#define to_mipi_video_phy(desc) \ 277#define to_mipi_video_phy(desc) \
98 container_of((desc), struct exynos_mipi_video_phy, phys[(desc)->index]); 278 container_of((desc), struct exynos_mipi_video_phy, phys[(desc)->index])
99 279
100static int exynos_mipi_video_phy_power_on(struct phy *phy) 280static int exynos_mipi_video_phy_power_on(struct phy *phy)
101{ 281{
102 struct video_phy_desc *phy_desc = phy_get_drvdata(phy); 282 struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
103 struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc); 283 struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
104 284
105 return __set_phy_state(state, phy_desc->index, 1); 285 return __set_phy_state(phy_desc->data, state, 1);
106} 286}
107 287
108static int exynos_mipi_video_phy_power_off(struct phy *phy) 288static int exynos_mipi_video_phy_power_off(struct phy *phy)
@@ -110,7 +290,7 @@ static int exynos_mipi_video_phy_power_off(struct phy *phy)
110 struct video_phy_desc *phy_desc = phy_get_drvdata(phy); 290 struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
111 struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc); 291 struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
112 292
113 return __set_phy_state(state, phy_desc->index, 0); 293 return __set_phy_state(phy_desc->data, state, 0);
114} 294}
115 295
116static struct phy *exynos_mipi_video_phy_xlate(struct device *dev, 296static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
@@ -118,7 +298,7 @@ static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
118{ 298{
119 struct exynos_mipi_video_phy *state = dev_get_drvdata(dev); 299 struct exynos_mipi_video_phy *state = dev_get_drvdata(dev);
120 300
121 if (WARN_ON(args->args[0] >= EXYNOS_MIPI_PHYS_NUM)) 301 if (WARN_ON(args->args[0] >= state->num_phys))
122 return ERR_PTR(-ENODEV); 302 return ERR_PTR(-ENODEV);
123 303
124 return state->phys[args->args[0]].phy; 304 return state->phys[args->args[0]].phy;
@@ -132,32 +312,33 @@ static const struct phy_ops exynos_mipi_video_phy_ops = {
132 312
133static int exynos_mipi_video_phy_probe(struct platform_device *pdev) 313static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
134{ 314{
315 const struct mipi_phy_device_desc *phy_dev;
135 struct exynos_mipi_video_phy *state; 316 struct exynos_mipi_video_phy *state;
136 struct device *dev = &pdev->dev; 317 struct device *dev = &pdev->dev;
318 struct device_node *np = dev->of_node;
137 struct phy_provider *phy_provider; 319 struct phy_provider *phy_provider;
138 unsigned int i; 320 unsigned int i;
139 321
322 phy_dev = of_device_get_match_data(dev);
323 if (!phy_dev)
324 return -ENODEV;
325
140 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); 326 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
141 if (!state) 327 if (!state)
142 return -ENOMEM; 328 return -ENOMEM;
143 329
144 state->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); 330 for (i = 0; i < phy_dev->num_regmaps; i++) {
145 if (IS_ERR(state->regmap)) { 331 state->regmaps[i] = syscon_regmap_lookup_by_phandle(np,
146 struct resource *res; 332 phy_dev->regmap_names[i]);
147 333 if (IS_ERR(state->regmaps[i]))
148 dev_info(dev, "regmap lookup failed: %ld\n", 334 return PTR_ERR(state->regmaps[i]);
149 PTR_ERR(state->regmap));
150
151 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
152 state->regs = devm_ioremap_resource(dev, res);
153 if (IS_ERR(state->regs))
154 return PTR_ERR(state->regs);
155 } 335 }
336 state->num_phys = phy_dev->num_phys;
337 spin_lock_init(&state->slock);
156 338
157 dev_set_drvdata(dev, state); 339 dev_set_drvdata(dev, state);
158 spin_lock_init(&state->slock);
159 340
160 for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { 341 for (i = 0; i < state->num_phys; i++) {
161 struct phy *phy = devm_phy_create(dev, NULL, 342 struct phy *phy = devm_phy_create(dev, NULL,
162 &exynos_mipi_video_phy_ops); 343 &exynos_mipi_video_phy_ops);
163 if (IS_ERR(phy)) { 344 if (IS_ERR(phy)) {
@@ -167,6 +348,7 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
167 348
168 state->phys[i].phy = phy; 349 state->phys[i].phy = phy;
169 state->phys[i].index = i; 350 state->phys[i].index = i;
351 state->phys[i].data = &phy_dev->phys[i];
170 phy_set_drvdata(phy, &state->phys[i]); 352 phy_set_drvdata(phy, &state->phys[i]);
171 } 353 }
172 354
@@ -177,8 +359,17 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
177} 359}
178 360
179static const struct of_device_id exynos_mipi_video_phy_of_match[] = { 361static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
180 { .compatible = "samsung,s5pv210-mipi-video-phy" }, 362 {
181 { }, 363 .compatible = "samsung,s5pv210-mipi-video-phy",
364 .data = &s5pv210_mipi_phy,
365 }, {
366 .compatible = "samsung,exynos5420-mipi-video-phy",
367 .data = &exynos5420_mipi_phy,
368 }, {
369 .compatible = "samsung,exynos5433-mipi-video-phy",
370 .data = &exynos5433_mipi_phy,
371 },
372 { /* sentinel */ },
182}; 373};
183MODULE_DEVICE_TABLE(of, exynos_mipi_video_phy_of_match); 374MODULE_DEVICE_TABLE(of, exynos_mipi_video_phy_of_match);
184 375
diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c
index c0e7b4b0cf5c..4d85e730ccab 100644
--- a/drivers/phy/phy-mt65xx-usb3.c
+++ b/drivers/phy/phy-mt65xx-usb3.c
@@ -134,6 +134,11 @@
134#define U3P_SR_COEF_DIVISOR 1000 134#define U3P_SR_COEF_DIVISOR 1000
135#define U3P_FM_DET_CYCLE_CNT 1024 135#define U3P_FM_DET_CYCLE_CNT 1024
136 136
137struct mt65xx_phy_pdata {
138 /* avoid RX sensitivity level degradation only for mt8173 */
139 bool avoid_rx_sen_degradation;
140};
141
137struct mt65xx_phy_instance { 142struct mt65xx_phy_instance {
138 struct phy *phy; 143 struct phy *phy;
139 void __iomem *port_base; 144 void __iomem *port_base;
@@ -145,6 +150,7 @@ struct mt65xx_u3phy {
145 struct device *dev; 150 struct device *dev;
146 void __iomem *sif_base; /* include sif2, but exclude port's */ 151 void __iomem *sif_base; /* include sif2, but exclude port's */
147 struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */ 152 struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
153 const struct mt65xx_phy_pdata *pdata;
148 struct mt65xx_phy_instance **phys; 154 struct mt65xx_phy_instance **phys;
149 int nphys; 155 int nphys;
150}; 156};
@@ -241,22 +247,26 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy,
241 tmp = readl(port_base + U3P_U2PHYACR4); 247 tmp = readl(port_base + U3P_U2PHYACR4);
242 tmp &= ~P2C_U2_GPIO_CTR_MSK; 248 tmp &= ~P2C_U2_GPIO_CTR_MSK;
243 writel(tmp, port_base + U3P_U2PHYACR4); 249 writel(tmp, port_base + U3P_U2PHYACR4);
250 }
244 251
245 tmp = readl(port_base + U3P_USBPHYACR2); 252 if (u3phy->pdata->avoid_rx_sen_degradation) {
246 tmp |= PA2_RG_SIF_U2PLL_FORCE_EN; 253 if (!index) {
247 writel(tmp, port_base + U3P_USBPHYACR2); 254 tmp = readl(port_base + U3P_USBPHYACR2);
248 255 tmp |= PA2_RG_SIF_U2PLL_FORCE_EN;
249 tmp = readl(port_base + U3D_U2PHYDCR0); 256 writel(tmp, port_base + U3P_USBPHYACR2);
250 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 257
251 writel(tmp, port_base + U3D_U2PHYDCR0); 258 tmp = readl(port_base + U3D_U2PHYDCR0);
252 } else { 259 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
253 tmp = readl(port_base + U3D_U2PHYDCR0); 260 writel(tmp, port_base + U3D_U2PHYDCR0);
254 tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; 261 } else {
255 writel(tmp, port_base + U3D_U2PHYDCR0); 262 tmp = readl(port_base + U3D_U2PHYDCR0);
256 263 tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
257 tmp = readl(port_base + U3P_U2PHYDTM0); 264 writel(tmp, port_base + U3D_U2PHYDCR0);
258 tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; 265
259 writel(tmp, port_base + U3P_U2PHYDTM0); 266 tmp = readl(port_base + U3P_U2PHYDTM0);
267 tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
268 writel(tmp, port_base + U3P_U2PHYDTM0);
269 }
260 } 270 }
261 271
262 tmp = readl(port_base + U3P_USBPHYACR6); 272 tmp = readl(port_base + U3P_USBPHYACR6);
@@ -318,7 +328,7 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
318 tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; 328 tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD;
319 writel(tmp, u3phy->sif_base + U3P_XTALCTL3); 329 writel(tmp, u3phy->sif_base + U3P_XTALCTL3);
320 330
321 /* [mt8173]switch 100uA current to SSUSB */ 331 /* switch 100uA current to SSUSB */
322 tmp = readl(port_base + U3P_USBPHYACR5); 332 tmp = readl(port_base + U3P_USBPHYACR5);
323 tmp |= PA5_RG_U2_HS_100U_U3_EN; 333 tmp |= PA5_RG_U2_HS_100U_U3_EN;
324 writel(tmp, port_base + U3P_USBPHYACR5); 334 writel(tmp, port_base + U3P_USBPHYACR5);
@@ -335,7 +345,7 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
335 tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4); 345 tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4);
336 writel(tmp, port_base + U3P_USBPHYACR5); 346 writel(tmp, port_base + U3P_USBPHYACR5);
337 347
338 if (index) { 348 if (u3phy->pdata->avoid_rx_sen_degradation && index) {
339 tmp = readl(port_base + U3D_U2PHYDCR0); 349 tmp = readl(port_base + U3D_U2PHYDCR0);
340 tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; 350 tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
341 writel(tmp, port_base + U3D_U2PHYDCR0); 351 writel(tmp, port_base + U3D_U2PHYDCR0);
@@ -386,7 +396,9 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
386 tmp = readl(port_base + U3P_U3_PHYA_REG0); 396 tmp = readl(port_base + U3P_U3_PHYA_REG0);
387 tmp &= ~P3A_RG_U3_VUSB10_ON; 397 tmp &= ~P3A_RG_U3_VUSB10_ON;
388 writel(tmp, port_base + U3P_U3_PHYA_REG0); 398 writel(tmp, port_base + U3P_U3_PHYA_REG0);
389 } else { 399 }
400
401 if (u3phy->pdata->avoid_rx_sen_degradation && index) {
390 tmp = readl(port_base + U3D_U2PHYDCR0); 402 tmp = readl(port_base + U3D_U2PHYDCR0);
391 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 403 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
392 writel(tmp, port_base + U3D_U2PHYDCR0); 404 writel(tmp, port_base + U3D_U2PHYDCR0);
@@ -402,7 +414,7 @@ static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
402 u32 index = instance->index; 414 u32 index = instance->index;
403 u32 tmp; 415 u32 tmp;
404 416
405 if (index) { 417 if (u3phy->pdata->avoid_rx_sen_degradation && index) {
406 tmp = readl(port_base + U3D_U2PHYDCR0); 418 tmp = readl(port_base + U3D_U2PHYDCR0);
407 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; 419 tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
408 writel(tmp, port_base + U3D_U2PHYDCR0); 420 writel(tmp, port_base + U3D_U2PHYDCR0);
@@ -502,8 +514,24 @@ static struct phy_ops mt65xx_u3phy_ops = {
502 .owner = THIS_MODULE, 514 .owner = THIS_MODULE,
503}; 515};
504 516
517static const struct mt65xx_phy_pdata mt2701_pdata = {
518 .avoid_rx_sen_degradation = false,
519};
520
521static const struct mt65xx_phy_pdata mt8173_pdata = {
522 .avoid_rx_sen_degradation = true,
523};
524
525static const struct of_device_id mt65xx_u3phy_id_table[] = {
526 { .compatible = "mediatek,mt2701-u3phy", .data = &mt2701_pdata },
527 { .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata },
528 { },
529};
530MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
531
505static int mt65xx_u3phy_probe(struct platform_device *pdev) 532static int mt65xx_u3phy_probe(struct platform_device *pdev)
506{ 533{
534 const struct of_device_id *match;
507 struct device *dev = &pdev->dev; 535 struct device *dev = &pdev->dev;
508 struct device_node *np = dev->of_node; 536 struct device_node *np = dev->of_node;
509 struct device_node *child_np; 537 struct device_node *child_np;
@@ -513,10 +541,15 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
513 struct resource res; 541 struct resource res;
514 int port, retval; 542 int port, retval;
515 543
544 match = of_match_node(mt65xx_u3phy_id_table, pdev->dev.of_node);
545 if (!match)
546 return -EINVAL;
547
516 u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL); 548 u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
517 if (!u3phy) 549 if (!u3phy)
518 return -ENOMEM; 550 return -ENOMEM;
519 551
552 u3phy->pdata = match->data;
520 u3phy->nphys = of_get_child_count(np); 553 u3phy->nphys = of_get_child_count(np);
521 u3phy->phys = devm_kcalloc(dev, u3phy->nphys, 554 u3phy->phys = devm_kcalloc(dev, u3phy->nphys,
522 sizeof(*u3phy->phys), GFP_KERNEL); 555 sizeof(*u3phy->phys), GFP_KERNEL);
@@ -587,12 +620,6 @@ put_child:
587 return retval; 620 return retval;
588} 621}
589 622
590static const struct of_device_id mt65xx_u3phy_id_table[] = {
591 { .compatible = "mediatek,mt8173-u3phy", },
592 { },
593};
594MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
595
596static struct platform_driver mt65xx_u3phy_driver = { 623static struct platform_driver mt65xx_u3phy_driver = {
597 .probe = mt65xx_u3phy_probe, 624 .probe = mt65xx_u3phy_probe,
598 .driver = { 625 .driver = {
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c
index c7a05996d5c1..97d4dd6ea924 100644
--- a/drivers/phy/phy-rcar-gen2.c
+++ b/drivers/phy/phy-rcar-gen2.c
@@ -195,6 +195,7 @@ static const struct of_device_id rcar_gen2_phy_match_table[] = {
195 { .compatible = "renesas,usb-phy-r8a7790" }, 195 { .compatible = "renesas,usb-phy-r8a7790" },
196 { .compatible = "renesas,usb-phy-r8a7791" }, 196 { .compatible = "renesas,usb-phy-r8a7791" },
197 { .compatible = "renesas,usb-phy-r8a7794" }, 197 { .compatible = "renesas,usb-phy-r8a7794" },
198 { .compatible = "renesas,rcar-gen2-usb-phy" },
198 { } 199 { }
199}; 200};
200MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table); 201MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c
index bc4f7dd821aa..76bb88f0700a 100644
--- a/drivers/phy/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/phy-rcar-gen3-usb2.c
@@ -12,6 +12,7 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15#include <linux/extcon.h>
15#include <linux/interrupt.h> 16#include <linux/interrupt.h>
16#include <linux/io.h> 17#include <linux/io.h>
17#include <linux/module.h> 18#include <linux/module.h>
@@ -19,6 +20,7 @@
19#include <linux/of_address.h> 20#include <linux/of_address.h>
20#include <linux/phy/phy.h> 21#include <linux/phy/phy.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/regulator/consumer.h>
22 24
23/******* USB2.0 Host registers (original offset is +0x200) *******/ 25/******* USB2.0 Host registers (original offset is +0x200) *******/
24#define USB2_INT_ENABLE 0x000 26#define USB2_INT_ENABLE 0x000
@@ -74,20 +76,17 @@
74#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */ 76#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */
75#define USB2_ADPCTRL_DRVVBUS BIT(4) 77#define USB2_ADPCTRL_DRVVBUS BIT(4)
76 78
77struct rcar_gen3_data {
78 void __iomem *base;
79 struct clk *clk;
80};
81
82struct rcar_gen3_chan { 79struct rcar_gen3_chan {
83 struct rcar_gen3_data usb2; 80 void __iomem *base;
81 struct extcon_dev *extcon;
84 struct phy *phy; 82 struct phy *phy;
83 struct regulator *vbus;
85 bool has_otg; 84 bool has_otg;
86}; 85};
87 86
88static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) 87static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
89{ 88{
90 void __iomem *usb2_base = ch->usb2.base; 89 void __iomem *usb2_base = ch->base;
91 u32 val = readl(usb2_base + USB2_COMMCTRL); 90 u32 val = readl(usb2_base + USB2_COMMCTRL);
92 91
93 dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, host); 92 dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, host);
@@ -100,7 +99,7 @@ static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
100 99
101static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) 100static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
102{ 101{
103 void __iomem *usb2_base = ch->usb2.base; 102 void __iomem *usb2_base = ch->base;
104 u32 val = readl(usb2_base + USB2_LINECTRL1); 103 u32 val = readl(usb2_base + USB2_LINECTRL1);
105 104
106 dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm); 105 dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm);
@@ -114,7 +113,7 @@ static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
114 113
115static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus) 114static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
116{ 115{
117 void __iomem *usb2_base = ch->usb2.base; 116 void __iomem *usb2_base = ch->base;
118 u32 val = readl(usb2_base + USB2_ADPCTRL); 117 u32 val = readl(usb2_base + USB2_ADPCTRL);
119 118
120 dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, vbus); 119 dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, vbus);
@@ -130,6 +129,9 @@ static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
130 rcar_gen3_set_linectrl(ch, 1, 1); 129 rcar_gen3_set_linectrl(ch, 1, 1);
131 rcar_gen3_set_host_mode(ch, 1); 130 rcar_gen3_set_host_mode(ch, 1);
132 rcar_gen3_enable_vbus_ctrl(ch, 1); 131 rcar_gen3_enable_vbus_ctrl(ch, 1);
132
133 extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, true);
134 extcon_set_cable_state_(ch->extcon, EXTCON_USB, false);
133} 135}
134 136
135static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) 137static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch)
@@ -137,17 +139,20 @@ static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch)
137 rcar_gen3_set_linectrl(ch, 0, 1); 139 rcar_gen3_set_linectrl(ch, 0, 1);
138 rcar_gen3_set_host_mode(ch, 0); 140 rcar_gen3_set_host_mode(ch, 0);
139 rcar_gen3_enable_vbus_ctrl(ch, 0); 141 rcar_gen3_enable_vbus_ctrl(ch, 0);
142
143 extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, false);
144 extcon_set_cable_state_(ch->extcon, EXTCON_USB, true);
140} 145}
141 146
142static bool rcar_gen3_check_vbus(struct rcar_gen3_chan *ch) 147static bool rcar_gen3_check_vbus(struct rcar_gen3_chan *ch)
143{ 148{
144 return !!(readl(ch->usb2.base + USB2_ADPCTRL) & 149 return !!(readl(ch->base + USB2_ADPCTRL) &
145 USB2_ADPCTRL_OTGSESSVLD); 150 USB2_ADPCTRL_OTGSESSVLD);
146} 151}
147 152
148static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) 153static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
149{ 154{
150 return !!(readl(ch->usb2.base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); 155 return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
151} 156}
152 157
153static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch) 158static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch)
@@ -166,7 +171,7 @@ static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch)
166 171
167static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) 172static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
168{ 173{
169 void __iomem *usb2_base = ch->usb2.base; 174 void __iomem *usb2_base = ch->base;
170 u32 val; 175 u32 val;
171 176
172 val = readl(usb2_base + USB2_VBCTRL); 177 val = readl(usb2_base + USB2_VBCTRL);
@@ -187,7 +192,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
187static int rcar_gen3_phy_usb2_init(struct phy *p) 192static int rcar_gen3_phy_usb2_init(struct phy *p)
188{ 193{
189 struct rcar_gen3_chan *channel = phy_get_drvdata(p); 194 struct rcar_gen3_chan *channel = phy_get_drvdata(p);
190 void __iomem *usb2_base = channel->usb2.base; 195 void __iomem *usb2_base = channel->base;
191 196
192 /* Initialize USB2 part */ 197 /* Initialize USB2 part */
193 writel(USB2_INT_ENABLE_INIT, usb2_base + USB2_INT_ENABLE); 198 writel(USB2_INT_ENABLE_INIT, usb2_base + USB2_INT_ENABLE);
@@ -205,7 +210,7 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p)
205{ 210{
206 struct rcar_gen3_chan *channel = phy_get_drvdata(p); 211 struct rcar_gen3_chan *channel = phy_get_drvdata(p);
207 212
208 writel(0, channel->usb2.base + USB2_INT_ENABLE); 213 writel(0, channel->base + USB2_INT_ENABLE);
209 214
210 return 0; 215 return 0;
211} 216}
@@ -213,8 +218,15 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p)
213static int rcar_gen3_phy_usb2_power_on(struct phy *p) 218static int rcar_gen3_phy_usb2_power_on(struct phy *p)
214{ 219{
215 struct rcar_gen3_chan *channel = phy_get_drvdata(p); 220 struct rcar_gen3_chan *channel = phy_get_drvdata(p);
216 void __iomem *usb2_base = channel->usb2.base; 221 void __iomem *usb2_base = channel->base;
217 u32 val; 222 u32 val;
223 int ret;
224
225 if (channel->vbus) {
226 ret = regulator_enable(channel->vbus);
227 if (ret)
228 return ret;
229 }
218 230
219 val = readl(usb2_base + USB2_USBCTR); 231 val = readl(usb2_base + USB2_USBCTR);
220 val |= USB2_USBCTR_PLL_RST; 232 val |= USB2_USBCTR_PLL_RST;
@@ -225,17 +237,29 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p)
225 return 0; 237 return 0;
226} 238}
227 239
240static int rcar_gen3_phy_usb2_power_off(struct phy *p)
241{
242 struct rcar_gen3_chan *channel = phy_get_drvdata(p);
243 int ret = 0;
244
245 if (channel->vbus)
246 ret = regulator_disable(channel->vbus);
247
248 return ret;
249}
250
228static struct phy_ops rcar_gen3_phy_usb2_ops = { 251static struct phy_ops rcar_gen3_phy_usb2_ops = {
229 .init = rcar_gen3_phy_usb2_init, 252 .init = rcar_gen3_phy_usb2_init,
230 .exit = rcar_gen3_phy_usb2_exit, 253 .exit = rcar_gen3_phy_usb2_exit,
231 .power_on = rcar_gen3_phy_usb2_power_on, 254 .power_on = rcar_gen3_phy_usb2_power_on,
255 .power_off = rcar_gen3_phy_usb2_power_off,
232 .owner = THIS_MODULE, 256 .owner = THIS_MODULE,
233}; 257};
234 258
235static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) 259static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
236{ 260{
237 struct rcar_gen3_chan *ch = _ch; 261 struct rcar_gen3_chan *ch = _ch;
238 void __iomem *usb2_base = ch->usb2.base; 262 void __iomem *usb2_base = ch->base;
239 u32 status = readl(usb2_base + USB2_OBINTSTA); 263 u32 status = readl(usb2_base + USB2_OBINTSTA);
240 irqreturn_t ret = IRQ_NONE; 264 irqreturn_t ret = IRQ_NONE;
241 265
@@ -251,10 +275,17 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
251 275
252static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = { 276static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
253 { .compatible = "renesas,usb2-phy-r8a7795" }, 277 { .compatible = "renesas,usb2-phy-r8a7795" },
278 { .compatible = "renesas,rcar-gen3-usb2-phy" },
254 { } 279 { }
255}; 280};
256MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table); 281MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table);
257 282
283static const unsigned int rcar_gen3_phy_cable[] = {
284 EXTCON_USB,
285 EXTCON_USB_HOST,
286 EXTCON_NONE,
287};
288
258static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) 289static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
259{ 290{
260 struct device *dev = &pdev->dev; 291 struct device *dev = &pdev->dev;
@@ -273,18 +304,30 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
273 return -ENOMEM; 304 return -ENOMEM;
274 305
275 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 306 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
276 channel->usb2.base = devm_ioremap_resource(dev, res); 307 channel->base = devm_ioremap_resource(dev, res);
277 if (IS_ERR(channel->usb2.base)) 308 if (IS_ERR(channel->base))
278 return PTR_ERR(channel->usb2.base); 309 return PTR_ERR(channel->base);
279 310
280 /* call request_irq for OTG */ 311 /* call request_irq for OTG */
281 irq = platform_get_irq(pdev, 0); 312 irq = platform_get_irq(pdev, 0);
282 if (irq >= 0) { 313 if (irq >= 0) {
314 int ret;
315
283 irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, 316 irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
284 IRQF_SHARED, dev_name(dev), channel); 317 IRQF_SHARED, dev_name(dev), channel);
285 if (irq < 0) 318 if (irq < 0)
286 dev_err(dev, "No irq handler (%d)\n", irq); 319 dev_err(dev, "No irq handler (%d)\n", irq);
287 channel->has_otg = true; 320 channel->has_otg = true;
321 channel->extcon = devm_extcon_dev_allocate(dev,
322 rcar_gen3_phy_cable);
323 if (IS_ERR(channel->extcon))
324 return PTR_ERR(channel->extcon);
325
326 ret = devm_extcon_dev_register(dev, channel->extcon);
327 if (ret < 0) {
328 dev_err(dev, "Failed to register extcon\n");
329 return ret;
330 }
288 } 331 }
289 332
290 /* devm_phy_create() will call pm_runtime_enable(dev); */ 333 /* devm_phy_create() will call pm_runtime_enable(dev); */
@@ -294,6 +337,13 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
294 return PTR_ERR(channel->phy); 337 return PTR_ERR(channel->phy);
295 } 338 }
296 339
340 channel->vbus = devm_regulator_get_optional(dev, "vbus");
341 if (IS_ERR(channel->vbus)) {
342 if (PTR_ERR(channel->vbus) == -EPROBE_DEFER)
343 return PTR_ERR(channel->vbus);
344 channel->vbus = NULL;
345 }
346
297 phy_set_drvdata(channel->phy, channel); 347 phy_set_drvdata(channel->phy, channel);
298 348
299 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 349 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index f62d899063a3..d60b149cff0f 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -216,7 +216,7 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
216 init.parent_names = &clk_name; 216 init.parent_names = &clk_name;
217 init.num_parents = 1; 217 init.num_parents = 1;
218 } else { 218 } else {
219 init.flags = CLK_IS_ROOT; 219 init.flags = 0;
220 init.parent_names = NULL; 220 init.parent_names = NULL;
221 init.num_parents = 0; 221 init.num_parents = 0;
222 } 222 }