[RESEND PATCH 2/6] phy: phy-mt65xx-usb3: split SuperSpeed port into two ones

2017-01-17 Thread Chunfeng Yun
Currently usb3 port in fact includes two sub-ports, but it is not
flexible for some cases, such as following one:
usb3 port0 includes u2port0 and u3port0;
usb2 port0 includes u2port1;
If wants to support only HS, we can use u2port0 or u2port1, when
select u2port0, u3port0 is not needed;
If wants to support SS, we can compound u2port0 and u3port0,
or u2port1 and u3port0, if select latter one, u2port0 is not needed.

So it's more flexible to split usb3 port into two ones and also try
best to save power by disabling unnecessary ports.

Signed-off-by: Chunfeng Yun 
---
 drivers/phy/phy-mt65xx-usb3.c |  124 -
 1 file changed, 61 insertions(+), 63 deletions(-)

diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c
index fc9a4f0..c187a3b 100644
--- a/drivers/phy/phy-mt65xx-usb3.c
+++ b/drivers/phy/phy-mt65xx-usb3.c
@@ -30,11 +30,11 @@
 #define SSUSB_SIFSLV_SPLLC 0x
 #define SSUSB_SIFSLV_U2FREQ0x0100
 
-/* offsets of sub-segment in each port registers */
+/* offsets of banks in each u2phy registers */
 #define SSUSB_SIFSLV_U2PHY_COM_BASE0x
-#define SSUSB_SIFSLV_U3PHYD_BASE   0x0100
-#define SSUSB_USB30_PHYA_SIV_B_BASE0x0300
-#define SSUSB_SIFSLV_U3PHYA_DA_BASE0x0400
+/* offsets of banks in each u3phy registers */
+#define SSUSB_SIFSLV_U3PHYD_BASE   0x
+#define SSUSB_SIFSLV_U3PHYA_BASE   0x0200
 
 #define U3P_USBPHYACR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x)
 #define PA0_RG_U2PLL_FORCE_ON  BIT(15)
@@ -49,7 +49,6 @@
 #define PA5_RG_U2_HS_100U_U3_ENBIT(11)
 
 #define U3P_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0018)
-#define PA6_RG_U2_ISO_EN   BIT(31)
 #define PA6_RG_U2_BC11_SW_EN   BIT(23)
 #define PA6_RG_U2_OTG_VBUSCMP_EN   BIT(20)
 #define PA6_RG_U2_SQTH GENMASK(3, 0)
@@ -91,18 +90,18 @@
 #define P2C_RG_SESSEND BIT(4)
 #define P2C_RG_AVALID  BIT(2)
 
-#define U3P_U3_PHYA_REG0   (SSUSB_USB30_PHYA_SIV_B_BASE + 0x)
+#define U3P_U3_PHYA_REG0   (SSUSB_SIFSLV_U3PHYA_BASE + 0x)
 #define P3A_RG_U3_VUSB10_ONBIT(5)
 
-#define U3P_U3_PHYA_REG6   (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0018)
+#define U3P_U3_PHYA_REG6   (SSUSB_SIFSLV_U3PHYA_BASE + 0x0018)
 #define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
 #define P3A_RG_TX_EIDLE_CM_VAL(x)  ((0xf & (x)) << 28)
 
-#define U3P_U3_PHYA_REG9   (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0024)
+#define U3P_U3_PHYA_REG9   (SSUSB_SIFSLV_U3PHYA_BASE + 0x0024)
 #define P3A_RG_RX_DAC_MUX  GENMASK(5, 1)
 #define P3A_RG_RX_DAC_MUX_VAL(x)   ((0x1f & (x)) << 1)
 
-#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x)
+#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_BASE + 0x0100)
 #define P3A_RG_XTAL_EXT_EN_U3  GENMASK(11, 10)
 #define P3A_RG_XTAL_EXT_EN_U3_VAL(x)   ((0x3 & (x)) << 10)
 
@@ -148,7 +147,7 @@ struct mt65xx_phy_instance {
 
 struct mt65xx_u3phy {
struct device *dev;
-   void __iomem *sif_base; /* include sif2, but exclude port's */
+   void __iomem *sif_base; /* only shared sif */
struct clk *u2ref_clk;  /* reference clock of u2 analog phy */
struct clk *u3ref_clk;  /* reference clock of u3 analog phy */
const struct mt65xx_phy_pdata *pdata;
@@ -179,7 +178,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy 
*u3phy,
tmp = readl(sif_base + U3P_U2FREQ_FMCR0);
tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL);
tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT);
-   tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index);
+   tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1);
writel(tmp, sif_base + U3P_U2FREQ_FMCR0);
 
/* enable frequency meter */
@@ -227,6 +226,41 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy 
*u3phy,
writel(tmp, instance->port_base + U3P_USBPHYACR5);
 }
 
+static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy,
+   struct mt65xx_phy_instance *instance)
+{
+   void __iomem *port_base = instance->port_base;
+   u32 tmp;
+
+   /* gating PCIe Analog XTAL clock */
+   tmp = readl(u3phy->sif_base + U3P_XTALCTL3);
+   tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD;
+   writel(tmp, u3phy->sif_base + U3P_XTALCTL3);
+
+   /* gating XSQ */
+   tmp = readl(port_base + U3P_U3PHYA_DA_REG0);
+   tmp &= ~P3A_RG_XTAL_EXT_EN_U3;
+   tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2);
+   writel(tmp, port_base + U3P_U3PHYA_DA_REG0);
+
+   tmp = readl(port_base + U3P_U3_PHYA_REG9);
+   tmp &= ~P3A_RG_RX_DAC_MUX;
+   tmp |= P3A_RG_RX_DAC_MUX_VAL(4);
+   writel(tmp, port_base + U3P_U3_PHYA_REG9);
+
+   tmp = readl(port_base + U3P_U3_PHYA_REG6);
+   tmp &= ~P3A_RG_TX_EIDLE_CM;
+   tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe);
+   writel(tmp, port_base + U3P_U3_PHYA_REG6);
+
+   tmp = 

[RESEND PATCH 2/6] phy: phy-mt65xx-usb3: split SuperSpeed port into two ones

2017-01-17 Thread Chunfeng Yun
Currently usb3 port in fact includes two sub-ports, but it is not
flexible for some cases, such as following one:
usb3 port0 includes u2port0 and u3port0;
usb2 port0 includes u2port1;
If wants to support only HS, we can use u2port0 or u2port1, when
select u2port0, u3port0 is not needed;
If wants to support SS, we can compound u2port0 and u3port0,
or u2port1 and u3port0, if select latter one, u2port0 is not needed.

So it's more flexible to split usb3 port into two ones and also try
best to save power by disabling unnecessary ports.

Signed-off-by: Chunfeng Yun 
---
 drivers/phy/phy-mt65xx-usb3.c |  124 -
 1 file changed, 61 insertions(+), 63 deletions(-)

diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c
index fc9a4f0..c187a3b 100644
--- a/drivers/phy/phy-mt65xx-usb3.c
+++ b/drivers/phy/phy-mt65xx-usb3.c
@@ -30,11 +30,11 @@
 #define SSUSB_SIFSLV_SPLLC 0x
 #define SSUSB_SIFSLV_U2FREQ0x0100
 
-/* offsets of sub-segment in each port registers */
+/* offsets of banks in each u2phy registers */
 #define SSUSB_SIFSLV_U2PHY_COM_BASE0x
-#define SSUSB_SIFSLV_U3PHYD_BASE   0x0100
-#define SSUSB_USB30_PHYA_SIV_B_BASE0x0300
-#define SSUSB_SIFSLV_U3PHYA_DA_BASE0x0400
+/* offsets of banks in each u3phy registers */
+#define SSUSB_SIFSLV_U3PHYD_BASE   0x
+#define SSUSB_SIFSLV_U3PHYA_BASE   0x0200
 
 #define U3P_USBPHYACR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x)
 #define PA0_RG_U2PLL_FORCE_ON  BIT(15)
@@ -49,7 +49,6 @@
 #define PA5_RG_U2_HS_100U_U3_ENBIT(11)
 
 #define U3P_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0018)
-#define PA6_RG_U2_ISO_EN   BIT(31)
 #define PA6_RG_U2_BC11_SW_EN   BIT(23)
 #define PA6_RG_U2_OTG_VBUSCMP_EN   BIT(20)
 #define PA6_RG_U2_SQTH GENMASK(3, 0)
@@ -91,18 +90,18 @@
 #define P2C_RG_SESSEND BIT(4)
 #define P2C_RG_AVALID  BIT(2)
 
-#define U3P_U3_PHYA_REG0   (SSUSB_USB30_PHYA_SIV_B_BASE + 0x)
+#define U3P_U3_PHYA_REG0   (SSUSB_SIFSLV_U3PHYA_BASE + 0x)
 #define P3A_RG_U3_VUSB10_ONBIT(5)
 
-#define U3P_U3_PHYA_REG6   (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0018)
+#define U3P_U3_PHYA_REG6   (SSUSB_SIFSLV_U3PHYA_BASE + 0x0018)
 #define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
 #define P3A_RG_TX_EIDLE_CM_VAL(x)  ((0xf & (x)) << 28)
 
-#define U3P_U3_PHYA_REG9   (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0024)
+#define U3P_U3_PHYA_REG9   (SSUSB_SIFSLV_U3PHYA_BASE + 0x0024)
 #define P3A_RG_RX_DAC_MUX  GENMASK(5, 1)
 #define P3A_RG_RX_DAC_MUX_VAL(x)   ((0x1f & (x)) << 1)
 
-#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x)
+#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_BASE + 0x0100)
 #define P3A_RG_XTAL_EXT_EN_U3  GENMASK(11, 10)
 #define P3A_RG_XTAL_EXT_EN_U3_VAL(x)   ((0x3 & (x)) << 10)
 
@@ -148,7 +147,7 @@ struct mt65xx_phy_instance {
 
 struct mt65xx_u3phy {
struct device *dev;
-   void __iomem *sif_base; /* include sif2, but exclude port's */
+   void __iomem *sif_base; /* only shared sif */
struct clk *u2ref_clk;  /* reference clock of u2 analog phy */
struct clk *u3ref_clk;  /* reference clock of u3 analog phy */
const struct mt65xx_phy_pdata *pdata;
@@ -179,7 +178,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy 
*u3phy,
tmp = readl(sif_base + U3P_U2FREQ_FMCR0);
tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL);
tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT);
-   tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index);
+   tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1);
writel(tmp, sif_base + U3P_U2FREQ_FMCR0);
 
/* enable frequency meter */
@@ -227,6 +226,41 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy 
*u3phy,
writel(tmp, instance->port_base + U3P_USBPHYACR5);
 }
 
+static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy,
+   struct mt65xx_phy_instance *instance)
+{
+   void __iomem *port_base = instance->port_base;
+   u32 tmp;
+
+   /* gating PCIe Analog XTAL clock */
+   tmp = readl(u3phy->sif_base + U3P_XTALCTL3);
+   tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD;
+   writel(tmp, u3phy->sif_base + U3P_XTALCTL3);
+
+   /* gating XSQ */
+   tmp = readl(port_base + U3P_U3PHYA_DA_REG0);
+   tmp &= ~P3A_RG_XTAL_EXT_EN_U3;
+   tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2);
+   writel(tmp, port_base + U3P_U3PHYA_DA_REG0);
+
+   tmp = readl(port_base + U3P_U3_PHYA_REG9);
+   tmp &= ~P3A_RG_RX_DAC_MUX;
+   tmp |= P3A_RG_RX_DAC_MUX_VAL(4);
+   writel(tmp, port_base + U3P_U3_PHYA_REG9);
+
+   tmp = readl(port_base + U3P_U3_PHYA_REG6);
+   tmp &= ~P3A_RG_TX_EIDLE_CM;
+   tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe);
+   writel(tmp, port_base + U3P_U3_PHYA_REG6);
+
+   tmp = readl(port_base +