phy-mt65xx-usb3.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. /*
  2. * Copyright (c) 2015 MediaTek Inc.
  3. * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
  4. *
  5. * This software is licensed under the terms of the GNU General Public
  6. * License version 2, as published by the Free Software Foundation, and
  7. * may be copied, distributed, and modified under those terms.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <dt-bindings/phy/phy.h>
  16. #include <linux/clk.h>
  17. #include <linux/delay.h>
  18. #include <linux/io.h>
  19. #include <linux/module.h>
  20. #include <linux/of_address.h>
  21. #include <linux/phy/phy.h>
  22. #include <linux/platform_device.h>
  23. /*
  24. * for sifslv2 register, but exclude port's;
  25. * relative to USB3_SIF2_BASE base address
  26. */
  27. #define SSUSB_SIFSLV_SPLLC 0x0000
  28. /* offsets of sub-segment in each port registers */
  29. #define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000
  30. #define SSUSB_SIFSLV_U3PHYD_BASE 0x0100
  31. #define SSUSB_USB30_PHYA_SIV_B_BASE 0x0300
  32. #define SSUSB_SIFSLV_U3PHYA_DA_BASE 0x0400
  33. #define U3P_USBPHYACR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0000)
  34. #define PA0_RG_U2PLL_FORCE_ON BIT(15)
  35. #define U3P_USBPHYACR2 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0008)
  36. #define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18)
  37. #define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014)
  38. #define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12)
  39. #define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12)
  40. #define PA5_RG_U2_HS_100U_U3_EN BIT(11)
  41. #define U3P_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0018)
  42. #define PA6_RG_U2_ISO_EN BIT(31)
  43. #define PA6_RG_U2_BC11_SW_EN BIT(23)
  44. #define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20)
  45. #define U3P_U2PHYACR4 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0020)
  46. #define P2C_RG_USB20_GPIO_CTL BIT(9)
  47. #define P2C_USB20_GPIO_MODE BIT(8)
  48. #define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
  49. #define U3D_U2PHYDCR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0060)
  50. #define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24)
  51. #define U3P_U2PHYDTM0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0068)
  52. #define P2C_FORCE_UART_EN BIT(26)
  53. #define P2C_FORCE_DATAIN BIT(23)
  54. #define P2C_FORCE_DM_PULLDOWN BIT(21)
  55. #define P2C_FORCE_DP_PULLDOWN BIT(20)
  56. #define P2C_FORCE_XCVRSEL BIT(19)
  57. #define P2C_FORCE_SUSPENDM BIT(18)
  58. #define P2C_FORCE_TERMSEL BIT(17)
  59. #define P2C_RG_DATAIN GENMASK(13, 10)
  60. #define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10)
  61. #define P2C_RG_DMPULLDOWN BIT(7)
  62. #define P2C_RG_DPPULLDOWN BIT(6)
  63. #define P2C_RG_XCVRSEL GENMASK(5, 4)
  64. #define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4)
  65. #define P2C_RG_SUSPENDM BIT(3)
  66. #define P2C_RG_TERMSEL BIT(2)
  67. #define P2C_DTM0_PART_MASK \
  68. (P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \
  69. P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \
  70. P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \
  71. P2C_RG_DPPULLDOWN | P2C_RG_TERMSEL)
  72. #define U3P_U2PHYDTM1 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x006C)
  73. #define P2C_RG_UART_EN BIT(16)
  74. #define P2C_RG_VBUSVALID BIT(5)
  75. #define P2C_RG_SESSEND BIT(4)
  76. #define P2C_RG_AVALID BIT(2)
  77. #define U3P_U3_PHYA_REG0 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0000)
  78. #define P3A_RG_U3_VUSB10_ON BIT(5)
  79. #define U3P_U3_PHYA_REG6 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0018)
  80. #define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
  81. #define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
  82. #define U3P_U3_PHYA_REG9 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0024)
  83. #define P3A_RG_RX_DAC_MUX GENMASK(5, 1)
  84. #define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
  85. #define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0000)
  86. #define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
  87. #define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
  88. #define U3P_PHYD_CDR1 (SSUSB_SIFSLV_U3PHYD_BASE + 0x005c)
  89. #define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24)
  90. #define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24)
  91. #define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8)
  92. #define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8)
  93. #define U3P_XTALCTL3 (SSUSB_SIFSLV_SPLLC + 0x0018)
  94. #define XC3_RG_U3_XTAL_RX_PWD BIT(9)
  95. #define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8)
  96. struct mt65xx_phy_instance {
  97. struct phy *phy;
  98. void __iomem *port_base;
  99. u32 index;
  100. u8 type;
  101. };
  102. struct mt65xx_u3phy {
  103. struct device *dev;
  104. void __iomem *sif_base; /* include sif2, but exclude port's */
  105. struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
  106. struct mt65xx_phy_instance **phys;
  107. int nphys;
  108. };
  109. static void phy_instance_init(struct mt65xx_u3phy *u3phy,
  110. struct mt65xx_phy_instance *instance)
  111. {
  112. void __iomem *port_base = instance->port_base;
  113. u32 index = instance->index;
  114. u32 tmp;
  115. /* switch to USB function. (system register, force ip into usb mode) */
  116. tmp = readl(port_base + U3P_U2PHYDTM0);
  117. tmp &= ~P2C_FORCE_UART_EN;
  118. tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0);
  119. writel(tmp, port_base + U3P_U2PHYDTM0);
  120. tmp = readl(port_base + U3P_U2PHYDTM1);
  121. tmp &= ~P2C_RG_UART_EN;
  122. writel(tmp, port_base + U3P_U2PHYDTM1);
  123. if (!index) {
  124. tmp = readl(port_base + U3P_U2PHYACR4);
  125. tmp &= ~P2C_U2_GPIO_CTR_MSK;
  126. writel(tmp, port_base + U3P_U2PHYACR4);
  127. tmp = readl(port_base + U3P_USBPHYACR2);
  128. tmp |= PA2_RG_SIF_U2PLL_FORCE_EN;
  129. writel(tmp, port_base + U3P_USBPHYACR2);
  130. tmp = readl(port_base + U3D_U2PHYDCR0);
  131. tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
  132. writel(tmp, port_base + U3D_U2PHYDCR0);
  133. } else {
  134. tmp = readl(port_base + U3D_U2PHYDCR0);
  135. tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
  136. writel(tmp, port_base + U3D_U2PHYDCR0);
  137. tmp = readl(port_base + U3P_U2PHYDTM0);
  138. tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
  139. writel(tmp, port_base + U3P_U2PHYDTM0);
  140. }
  141. /* DP/DM BC1.1 path Disable */
  142. tmp = readl(port_base + U3P_USBPHYACR6);
  143. tmp &= ~PA6_RG_U2_BC11_SW_EN;
  144. writel(tmp, port_base + U3P_USBPHYACR6);
  145. tmp = readl(port_base + U3P_U3PHYA_DA_REG0);
  146. tmp &= ~P3A_RG_XTAL_EXT_EN_U3;
  147. tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2);
  148. writel(tmp, port_base + U3P_U3PHYA_DA_REG0);
  149. tmp = readl(port_base + U3P_U3_PHYA_REG9);
  150. tmp &= ~P3A_RG_RX_DAC_MUX;
  151. tmp |= P3A_RG_RX_DAC_MUX_VAL(4);
  152. writel(tmp, port_base + U3P_U3_PHYA_REG9);
  153. tmp = readl(port_base + U3P_U3_PHYA_REG6);
  154. tmp &= ~P3A_RG_TX_EIDLE_CM;
  155. tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe);
  156. writel(tmp, port_base + U3P_U3_PHYA_REG6);
  157. tmp = readl(port_base + U3P_PHYD_CDR1);
  158. tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1);
  159. tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3);
  160. writel(tmp, port_base + U3P_PHYD_CDR1);
  161. dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
  162. }
  163. static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
  164. struct mt65xx_phy_instance *instance)
  165. {
  166. void __iomem *port_base = instance->port_base;
  167. u32 index = instance->index;
  168. u32 tmp;
  169. if (!index) {
  170. /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
  171. tmp = readl(port_base + U3P_U3_PHYA_REG0);
  172. tmp |= P3A_RG_U3_VUSB10_ON;
  173. writel(tmp, port_base + U3P_U3_PHYA_REG0);
  174. }
  175. /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */
  176. tmp = readl(port_base + U3P_U2PHYDTM0);
  177. tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL);
  178. tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK);
  179. writel(tmp, port_base + U3P_U2PHYDTM0);
  180. /* OTG Enable */
  181. tmp = readl(port_base + U3P_USBPHYACR6);
  182. tmp |= PA6_RG_U2_OTG_VBUSCMP_EN;
  183. writel(tmp, port_base + U3P_USBPHYACR6);
  184. if (!index) {
  185. tmp = readl(u3phy->sif_base + U3P_XTALCTL3);
  186. tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD;
  187. writel(tmp, u3phy->sif_base + U3P_XTALCTL3);
  188. /* [mt8173]disable Change 100uA current from SSUSB */
  189. tmp = readl(port_base + U3P_USBPHYACR5);
  190. tmp &= ~PA5_RG_U2_HS_100U_U3_EN;
  191. writel(tmp, port_base + U3P_USBPHYACR5);
  192. }
  193. tmp = readl(port_base + U3P_U2PHYDTM1);
  194. tmp |= P2C_RG_VBUSVALID | P2C_RG_AVALID;
  195. tmp &= ~P2C_RG_SESSEND;
  196. writel(tmp, port_base + U3P_U2PHYDTM1);
  197. /* USB 2.0 slew rate calibration */
  198. tmp = readl(port_base + U3P_USBPHYACR5);
  199. tmp &= ~PA5_RG_U2_HSTX_SRCTRL;
  200. tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4);
  201. writel(tmp, port_base + U3P_USBPHYACR5);
  202. if (index) {
  203. tmp = readl(port_base + U3D_U2PHYDCR0);
  204. tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
  205. writel(tmp, port_base + U3D_U2PHYDCR0);
  206. tmp = readl(port_base + U3P_U2PHYDTM0);
  207. tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
  208. writel(tmp, port_base + U3P_U2PHYDTM0);
  209. }
  210. dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
  211. }
  212. static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
  213. struct mt65xx_phy_instance *instance)
  214. {
  215. void __iomem *port_base = instance->port_base;
  216. u32 index = instance->index;
  217. u32 tmp;
  218. tmp = readl(port_base + U3P_U2PHYDTM0);
  219. tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN);
  220. tmp |= P2C_FORCE_SUSPENDM;
  221. writel(tmp, port_base + U3P_U2PHYDTM0);
  222. /* OTG Disable */
  223. tmp = readl(port_base + U3P_USBPHYACR6);
  224. tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN;
  225. writel(tmp, port_base + U3P_USBPHYACR6);
  226. if (!index) {
  227. /* (also disable)Change 100uA current switch to USB2.0 */
  228. tmp = readl(port_base + U3P_USBPHYACR5);
  229. tmp &= ~PA5_RG_U2_HS_100U_U3_EN;
  230. writel(tmp, port_base + U3P_USBPHYACR5);
  231. }
  232. /* let suspendm=0, set utmi into analog power down */
  233. tmp = readl(port_base + U3P_U2PHYDTM0);
  234. tmp &= ~P2C_RG_SUSPENDM;
  235. writel(tmp, port_base + U3P_U2PHYDTM0);
  236. udelay(1);
  237. tmp = readl(port_base + U3P_U2PHYDTM1);
  238. tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID);
  239. tmp |= P2C_RG_SESSEND;
  240. writel(tmp, port_base + U3P_U2PHYDTM1);
  241. if (!index) {
  242. tmp = readl(port_base + U3P_U3_PHYA_REG0);
  243. tmp &= ~P3A_RG_U3_VUSB10_ON;
  244. writel(tmp, port_base + U3P_U3_PHYA_REG0);
  245. } else {
  246. tmp = readl(port_base + U3D_U2PHYDCR0);
  247. tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
  248. writel(tmp, port_base + U3D_U2PHYDCR0);
  249. }
  250. dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
  251. }
  252. static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
  253. struct mt65xx_phy_instance *instance)
  254. {
  255. void __iomem *port_base = instance->port_base;
  256. u32 index = instance->index;
  257. u32 tmp;
  258. if (index) {
  259. tmp = readl(port_base + U3D_U2PHYDCR0);
  260. tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
  261. writel(tmp, port_base + U3D_U2PHYDCR0);
  262. tmp = readl(port_base + U3P_U2PHYDTM0);
  263. tmp &= ~P2C_FORCE_SUSPENDM;
  264. writel(tmp, port_base + U3P_U2PHYDTM0);
  265. }
  266. }
  267. static int mt65xx_phy_init(struct phy *phy)
  268. {
  269. struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
  270. struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
  271. int ret;
  272. ret = clk_prepare_enable(u3phy->u3phya_ref);
  273. if (ret) {
  274. dev_err(u3phy->dev, "failed to enable u3phya_ref\n");
  275. return ret;
  276. }
  277. phy_instance_init(u3phy, instance);
  278. return 0;
  279. }
  280. static int mt65xx_phy_power_on(struct phy *phy)
  281. {
  282. struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
  283. struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
  284. phy_instance_power_on(u3phy, instance);
  285. return 0;
  286. }
  287. static int mt65xx_phy_power_off(struct phy *phy)
  288. {
  289. struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
  290. struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
  291. phy_instance_power_off(u3phy, instance);
  292. return 0;
  293. }
  294. static int mt65xx_phy_exit(struct phy *phy)
  295. {
  296. struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
  297. struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
  298. phy_instance_exit(u3phy, instance);
  299. clk_disable_unprepare(u3phy->u3phya_ref);
  300. return 0;
  301. }
  302. static struct phy *mt65xx_phy_xlate(struct device *dev,
  303. struct of_phandle_args *args)
  304. {
  305. struct mt65xx_u3phy *u3phy = dev_get_drvdata(dev);
  306. struct mt65xx_phy_instance *instance = NULL;
  307. struct device_node *phy_np = args->np;
  308. int index;
  309. if (args->args_count != 1) {
  310. dev_err(dev, "invalid number of cells in 'phy' property\n");
  311. return ERR_PTR(-EINVAL);
  312. }
  313. for (index = 0; index < u3phy->nphys; index++)
  314. if (phy_np == u3phy->phys[index]->phy->dev.of_node) {
  315. instance = u3phy->phys[index];
  316. break;
  317. }
  318. if (!instance) {
  319. dev_err(dev, "failed to find appropriate phy\n");
  320. return ERR_PTR(-EINVAL);
  321. }
  322. instance->type = args->args[0];
  323. if (!(instance->type == PHY_TYPE_USB2 ||
  324. instance->type == PHY_TYPE_USB3)) {
  325. dev_err(dev, "unsupported device type: %d\n", instance->type);
  326. return ERR_PTR(-EINVAL);
  327. }
  328. return instance->phy;
  329. }
  330. static struct phy_ops mt65xx_u3phy_ops = {
  331. .init = mt65xx_phy_init,
  332. .exit = mt65xx_phy_exit,
  333. .power_on = mt65xx_phy_power_on,
  334. .power_off = mt65xx_phy_power_off,
  335. .owner = THIS_MODULE,
  336. };
  337. static int mt65xx_u3phy_probe(struct platform_device *pdev)
  338. {
  339. struct device *dev = &pdev->dev;
  340. struct device_node *np = dev->of_node;
  341. struct device_node *child_np;
  342. struct phy_provider *provider;
  343. struct resource *sif_res;
  344. struct mt65xx_u3phy *u3phy;
  345. struct resource res;
  346. int port, retval;
  347. u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
  348. if (!u3phy)
  349. return -ENOMEM;
  350. u3phy->nphys = of_get_child_count(np);
  351. u3phy->phys = devm_kcalloc(dev, u3phy->nphys,
  352. sizeof(*u3phy->phys), GFP_KERNEL);
  353. if (!u3phy->phys)
  354. return -ENOMEM;
  355. u3phy->dev = dev;
  356. platform_set_drvdata(pdev, u3phy);
  357. sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  358. u3phy->sif_base = devm_ioremap_resource(dev, sif_res);
  359. if (IS_ERR(u3phy->sif_base)) {
  360. dev_err(dev, "failed to remap sif regs\n");
  361. return PTR_ERR(u3phy->sif_base);
  362. }
  363. u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref");
  364. if (IS_ERR(u3phy->u3phya_ref)) {
  365. dev_err(dev, "error to get u3phya_ref\n");
  366. return PTR_ERR(u3phy->u3phya_ref);
  367. }
  368. port = 0;
  369. for_each_child_of_node(np, child_np) {
  370. struct mt65xx_phy_instance *instance;
  371. struct phy *phy;
  372. instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
  373. if (!instance) {
  374. retval = -ENOMEM;
  375. goto put_child;
  376. }
  377. u3phy->phys[port] = instance;
  378. phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops);
  379. if (IS_ERR(phy)) {
  380. dev_err(dev, "failed to create phy\n");
  381. retval = PTR_ERR(phy);
  382. goto put_child;
  383. }
  384. retval = of_address_to_resource(child_np, 0, &res);
  385. if (retval) {
  386. dev_err(dev, "failed to get address resource(id-%d)\n",
  387. port);
  388. goto put_child;
  389. }
  390. instance->port_base = devm_ioremap_resource(&phy->dev, &res);
  391. if (IS_ERR(instance->port_base)) {
  392. dev_err(dev, "failed to remap phy regs\n");
  393. retval = PTR_ERR(instance->port_base);
  394. goto put_child;
  395. }
  396. instance->phy = phy;
  397. instance->index = port;
  398. phy_set_drvdata(phy, instance);
  399. port++;
  400. }
  401. provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate);
  402. return PTR_ERR_OR_ZERO(provider);
  403. put_child:
  404. of_node_put(child_np);
  405. return retval;
  406. }
  407. static const struct of_device_id mt65xx_u3phy_id_table[] = {
  408. { .compatible = "mediatek,mt8173-u3phy", },
  409. { },
  410. };
  411. MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
  412. static struct platform_driver mt65xx_u3phy_driver = {
  413. .probe = mt65xx_u3phy_probe,
  414. .driver = {
  415. .name = "mt65xx-u3phy",
  416. .of_match_table = mt65xx_u3phy_id_table,
  417. },
  418. };
  419. module_platform_driver(mt65xx_u3phy_driver);
  420. MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
  421. MODULE_DESCRIPTION("mt65xx USB PHY driver");
  422. MODULE_LICENSE("GPL v2");