diff options
Diffstat (limited to 'drivers/phy/phy-mt65xx-usb3.c')
-rw-r--r-- | drivers/phy/phy-mt65xx-usb3.c | 77 |
1 files changed, 52 insertions, 25 deletions
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 | ||
137 | struct mt65xx_phy_pdata { | ||
138 | /* avoid RX sensitivity level degradation only for mt8173 */ | ||
139 | bool avoid_rx_sen_degradation; | ||
140 | }; | ||
141 | |||
137 | struct mt65xx_phy_instance { | 142 | struct 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 | ||
517 | static const struct mt65xx_phy_pdata mt2701_pdata = { | ||
518 | .avoid_rx_sen_degradation = false, | ||
519 | }; | ||
520 | |||
521 | static const struct mt65xx_phy_pdata mt8173_pdata = { | ||
522 | .avoid_rx_sen_degradation = true, | ||
523 | }; | ||
524 | |||
525 | static 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 | }; | ||
530 | MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table); | ||
531 | |||
505 | static int mt65xx_u3phy_probe(struct platform_device *pdev) | 532 | static 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 | ||
590 | static const struct of_device_id mt65xx_u3phy_id_table[] = { | ||
591 | { .compatible = "mediatek,mt8173-u3phy", }, | ||
592 | { }, | ||
593 | }; | ||
594 | MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table); | ||
595 | |||
596 | static struct platform_driver mt65xx_u3phy_driver = { | 623 | static struct platform_driver mt65xx_u3phy_driver = { |
597 | .probe = mt65xx_u3phy_probe, | 624 | .probe = mt65xx_u3phy_probe, |
598 | .driver = { | 625 | .driver = { |