Skip to content

Commit 04466ef

Browse files
Chunfeng Yunkishon
authored andcommitted
phy: phy-mt65xx-usb3: split SuperSpeed port into two ones
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 <[email protected]> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
1 parent 98cd83a commit 04466ef

File tree

1 file changed

+75
-74
lines changed

1 file changed

+75
-74
lines changed

drivers/phy/phy-mt65xx-usb3.c

Lines changed: 75 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@
3030
#define SSUSB_SIFSLV_SPLLC 0x0000
3131
#define SSUSB_SIFSLV_U2FREQ 0x0100
3232

33-
/* offsets of sub-segment in each port registers */
33+
/* offsets of banks in each u2phy registers */
3434
#define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000
35-
#define SSUSB_SIFSLV_U3PHYD_BASE 0x0100
36-
#define SSUSB_USB30_PHYA_SIV_B_BASE 0x0300
37-
#define SSUSB_SIFSLV_U3PHYA_DA_BASE 0x0400
35+
/* offsets of banks in each u3phy registers */
36+
#define SSUSB_SIFSLV_U3PHYD_BASE 0x0000
37+
#define SSUSB_SIFSLV_U3PHYA_BASE 0x0200
3838

3939
#define U3P_USBPHYACR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0000)
4040
#define PA0_RG_U2PLL_FORCE_ON BIT(15)
@@ -49,7 +49,6 @@
4949
#define PA5_RG_U2_HS_100U_U3_EN BIT(11)
5050

5151
#define U3P_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0018)
52-
#define PA6_RG_U2_ISO_EN BIT(31)
5352
#define PA6_RG_U2_BC11_SW_EN BIT(23)
5453
#define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20)
5554
#define PA6_RG_U2_SQTH GENMASK(3, 0)
@@ -91,18 +90,18 @@
9190
#define P2C_RG_SESSEND BIT(4)
9291
#define P2C_RG_AVALID BIT(2)
9392

94-
#define U3P_U3_PHYA_REG0 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0000)
93+
#define U3P_U3_PHYA_REG0 (SSUSB_SIFSLV_U3PHYA_BASE + 0x0000)
9594
#define P3A_RG_U3_VUSB10_ON BIT(5)
9695

97-
#define U3P_U3_PHYA_REG6 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0018)
96+
#define U3P_U3_PHYA_REG6 (SSUSB_SIFSLV_U3PHYA_BASE + 0x0018)
9897
#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
9998
#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
10099

101-
#define U3P_U3_PHYA_REG9 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0024)
100+
#define U3P_U3_PHYA_REG9 (SSUSB_SIFSLV_U3PHYA_BASE + 0x0024)
102101
#define P3A_RG_RX_DAC_MUX GENMASK(5, 1)
103102
#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
104103

105-
#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0000)
104+
#define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_BASE + 0x0100)
106105
#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
107106
#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
108107

@@ -160,7 +159,7 @@ struct mt65xx_phy_instance {
160159

161160
struct mt65xx_u3phy {
162161
struct device *dev;
163-
void __iomem *sif_base; /* include sif2, but exclude port's */
162+
void __iomem *sif_base; /* only shared sif */
164163
struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
165164
const struct mt65xx_phy_pdata *pdata;
166165
struct mt65xx_phy_instance **phys;
@@ -190,7 +189,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
190189
tmp = readl(sif_base + U3P_U2FREQ_FMCR0);
191190
tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL);
192191
tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT);
193-
tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index);
192+
tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1);
194193
writel(tmp, sif_base + U3P_U2FREQ_FMCR0);
195194

196195
/* enable frequency meter */
@@ -238,6 +237,56 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
238237
writel(tmp, instance->port_base + U3P_USBPHYACR5);
239238
}
240239

240+
static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy,
241+
struct mt65xx_phy_instance *instance)
242+
{
243+
void __iomem *port_base = instance->port_base;
244+
u32 tmp;
245+
246+
/* gating PCIe Analog XTAL clock */
247+
tmp = readl(u3phy->sif_base + U3P_XTALCTL3);
248+
tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD;
249+
writel(tmp, u3phy->sif_base + U3P_XTALCTL3);
250+
251+
/* gating XSQ */
252+
tmp = readl(port_base + U3P_U3PHYA_DA_REG0);
253+
tmp &= ~P3A_RG_XTAL_EXT_EN_U3;
254+
tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2);
255+
writel(tmp, port_base + U3P_U3PHYA_DA_REG0);
256+
257+
tmp = readl(port_base + U3P_U3_PHYA_REG9);
258+
tmp &= ~P3A_RG_RX_DAC_MUX;
259+
tmp |= P3A_RG_RX_DAC_MUX_VAL(4);
260+
writel(tmp, port_base + U3P_U3_PHYA_REG9);
261+
262+
tmp = readl(port_base + U3P_U3_PHYA_REG6);
263+
tmp &= ~P3A_RG_TX_EIDLE_CM;
264+
tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe);
265+
writel(tmp, port_base + U3P_U3_PHYA_REG6);
266+
267+
tmp = readl(port_base + U3P_PHYD_CDR1);
268+
tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1);
269+
tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3);
270+
writel(tmp, port_base + U3P_PHYD_CDR1);
271+
272+
tmp = readl(port_base + U3P_U3_PHYD_LFPS1);
273+
tmp &= ~P3D_RG_FWAKE_TH;
274+
tmp |= P3D_RG_FWAKE_TH_VAL(0x34);
275+
writel(tmp, port_base + U3P_U3_PHYD_LFPS1);
276+
277+
tmp = readl(port_base + U3P_U3_PHYD_RXDET1);
278+
tmp &= ~P3D_RG_RXDET_STB2_SET;
279+
tmp |= P3D_RG_RXDET_STB2_SET_VAL(0x10);
280+
writel(tmp, port_base + U3P_U3_PHYD_RXDET1);
281+
282+
tmp = readl(port_base + U3P_U3_PHYD_RXDET2);
283+
tmp &= ~P3D_RG_RXDET_STB2_SET_P3;
284+
tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
285+
writel(tmp, port_base + U3P_U3_PHYD_RXDET2);
286+
287+
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, instance->index);
288+
}
289+
241290
static void phy_instance_init(struct mt65xx_u3phy *u3phy,
242291
struct mt65xx_phy_instance *instance)
243292
{
@@ -287,41 +336,6 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy,
287336
tmp |= PA6_RG_U2_SQTH_VAL(2);
288337
writel(tmp, port_base + U3P_USBPHYACR6);
289338

290-
tmp = readl(port_base + U3P_U3PHYA_DA_REG0);
291-
tmp &= ~P3A_RG_XTAL_EXT_EN_U3;
292-
tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2);
293-
writel(tmp, port_base + U3P_U3PHYA_DA_REG0);
294-
295-
tmp = readl(port_base + U3P_U3_PHYA_REG9);
296-
tmp &= ~P3A_RG_RX_DAC_MUX;
297-
tmp |= P3A_RG_RX_DAC_MUX_VAL(4);
298-
writel(tmp, port_base + U3P_U3_PHYA_REG9);
299-
300-
tmp = readl(port_base + U3P_U3_PHYA_REG6);
301-
tmp &= ~P3A_RG_TX_EIDLE_CM;
302-
tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe);
303-
writel(tmp, port_base + U3P_U3_PHYA_REG6);
304-
305-
tmp = readl(port_base + U3P_PHYD_CDR1);
306-
tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1);
307-
tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3);
308-
writel(tmp, port_base + U3P_PHYD_CDR1);
309-
310-
tmp = readl(port_base + U3P_U3_PHYD_LFPS1);
311-
tmp &= ~P3D_RG_FWAKE_TH;
312-
tmp |= P3D_RG_FWAKE_TH_VAL(0x34);
313-
writel(tmp, port_base + U3P_U3_PHYD_LFPS1);
314-
315-
tmp = readl(port_base + U3P_U3_PHYD_RXDET1);
316-
tmp &= ~P3D_RG_RXDET_STB2_SET;
317-
tmp |= P3D_RG_RXDET_STB2_SET_VAL(0x10);
318-
writel(tmp, port_base + U3P_U3_PHYD_RXDET1);
319-
320-
tmp = readl(port_base + U3P_U3_PHYD_RXDET2);
321-
tmp &= ~P3D_RG_RXDET_STB2_SET_P3;
322-
tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
323-
writel(tmp, port_base + U3P_U3_PHYD_RXDET2);
324-
325339
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
326340
}
327341

@@ -332,13 +346,6 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
332346
u32 index = instance->index;
333347
u32 tmp;
334348

335-
if (!index) {
336-
/* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
337-
tmp = readl(port_base + U3P_U3_PHYA_REG0);
338-
tmp |= P3A_RG_U3_VUSB10_ON;
339-
writel(tmp, port_base + U3P_U3_PHYA_REG0);
340-
}
341-
342349
/* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */
343350
tmp = readl(port_base + U3P_U2PHYDTM0);
344351
tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL);
@@ -351,10 +358,6 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
351358
writel(tmp, port_base + U3P_USBPHYACR6);
352359

353360
if (!index) {
354-
tmp = readl(u3phy->sif_base + U3P_XTALCTL3);
355-
tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD;
356-
writel(tmp, u3phy->sif_base + U3P_XTALCTL3);
357-
358361
/* switch 100uA current to SSUSB */
359362
tmp = readl(port_base + U3P_USBPHYACR5);
360363
tmp |= PA5_RG_U2_HS_100U_U3_EN;
@@ -366,12 +369,6 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
366369
tmp &= ~P2C_RG_SESSEND;
367370
writel(tmp, port_base + U3P_U2PHYDTM1);
368371

369-
/* USB 2.0 slew rate calibration */
370-
tmp = readl(port_base + U3P_USBPHYACR5);
371-
tmp &= ~PA5_RG_U2_HSTX_SRCTRL;
372-
tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4);
373-
writel(tmp, port_base + U3P_USBPHYACR5);
374-
375372
if (u3phy->pdata->avoid_rx_sen_degradation && index) {
376373
tmp = readl(port_base + U3D_U2PHYDCR0);
377374
tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
@@ -419,12 +416,6 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
419416
tmp |= P2C_RG_SESSEND;
420417
writel(tmp, port_base + U3P_U2PHYDTM1);
421418

422-
if (!index) {
423-
tmp = readl(port_base + U3P_U3_PHYA_REG0);
424-
tmp &= ~P3A_RG_U3_VUSB10_ON;
425-
writel(tmp, port_base + U3P_U3_PHYA_REG0);
426-
}
427-
428419
if (u3phy->pdata->avoid_rx_sen_degradation && index) {
429420
tmp = readl(port_base + U3D_U2PHYDCR0);
430421
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
@@ -464,7 +455,11 @@ static int mt65xx_phy_init(struct phy *phy)
464455
return ret;
465456
}
466457

467-
phy_instance_init(u3phy, instance);
458+
if (instance->type == PHY_TYPE_USB2)
459+
phy_instance_init(u3phy, instance);
460+
else
461+
u3_phy_instance_init(u3phy, instance);
462+
468463
return 0;
469464
}
470465

@@ -473,8 +468,10 @@ static int mt65xx_phy_power_on(struct phy *phy)
473468
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
474469
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
475470

476-
phy_instance_power_on(u3phy, instance);
477-
hs_slew_rate_calibrate(u3phy, instance);
471+
if (instance->type == PHY_TYPE_USB2) {
472+
phy_instance_power_on(u3phy, instance);
473+
hs_slew_rate_calibrate(u3phy, instance);
474+
}
478475
return 0;
479476
}
480477

@@ -483,7 +480,9 @@ static int mt65xx_phy_power_off(struct phy *phy)
483480
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
484481
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
485482

486-
phy_instance_power_off(u3phy, instance);
483+
if (instance->type == PHY_TYPE_USB2)
484+
phy_instance_power_off(u3phy, instance);
485+
487486
return 0;
488487
}
489488

@@ -492,7 +491,9 @@ static int mt65xx_phy_exit(struct phy *phy)
492491
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
493492
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
494493

495-
phy_instance_exit(u3phy, instance);
494+
if (instance->type == PHY_TYPE_USB2)
495+
phy_instance_exit(u3phy, instance);
496+
496497
clk_disable_unprepare(u3phy->u3phya_ref);
497498
return 0;
498499
}

0 commit comments

Comments
 (0)