1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * MediaTek USB3.1 gen2 xsphy Driver 4 * 5 * Copyright (c) 2018 MediaTek Inc. 6 * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> 7 * 8 */ 9 10 #include <dt-bindings/phy/phy.h> 11 #include <linux/clk.h> 12 #include <linux/delay.h> 13 #include <linux/iopoll.h> 14 #include <linux/mfd/syscon.h> 15 #include <linux/module.h> 16 #include <linux/of_address.h> 17 #include <linux/phy/phy.h> 18 #include <linux/platform_device.h> 19 #include <linux/regmap.h> 20 21 #include "phy-mtk-io.h" 22 23 /* u2 phy banks */ 24 #define SSUSB_SIFSLV_MISC 0x000 25 #define SSUSB_SIFSLV_U2FREQ 0x100 26 #define SSUSB_SIFSLV_U2PHY_COM 0x300 27 28 /* u3 phy shared banks */ 29 #define SSPXTP_SIFSLV_DIG_GLB 0x000 30 #define SSPXTP_SIFSLV_PHYA_GLB 0x100 31 32 /* u3 phy banks */ 33 #define SSPXTP_SIFSLV_DIG_LN_TOP 0x000 34 #define SSPXTP_SIFSLV_DIG_LN_TX0 0x100 35 #define SSPXTP_SIFSLV_DIG_LN_RX0 0x200 36 #define SSPXTP_SIFSLV_DIG_LN_DAIF 0x300 37 #define SSPXTP_SIFSLV_PHYA_LN 0x400 38 39 #define XSP_U2FREQ_FMCR0 ((SSUSB_SIFSLV_U2FREQ) + 0x00) 40 #define P2F_RG_FREQDET_EN BIT(24) 41 #define P2F_RG_CYCLECNT GENMASK(23, 0) 42 43 #define XSP_U2FREQ_MMONR0 ((SSUSB_SIFSLV_U2FREQ) + 0x0c) 44 45 #define XSP_U2FREQ_FMMONR1 ((SSUSB_SIFSLV_U2FREQ) + 0x10) 46 #define P2F_RG_FRCK_EN BIT(8) 47 #define P2F_USB_FM_VALID BIT(0) 48 49 #define XSP_USBPHYACR0 ((SSUSB_SIFSLV_U2PHY_COM) + 0x00) 50 #define P2A0_RG_INTR_EN BIT(5) 51 52 #define XSP_USBPHYACR1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x04) 53 #define P2A1_RG_INTR_CAL GENMASK(23, 19) 54 #define P2A1_RG_VRT_SEL GENMASK(14, 12) 55 #define P2A1_RG_TERM_SEL GENMASK(10, 8) 56 57 #define XSP_USBPHYACR5 ((SSUSB_SIFSLV_U2PHY_COM) + 0x014) 58 #define P2A5_RG_HSTX_SRCAL_EN BIT(15) 59 #define P2A5_RG_HSTX_SRCTRL GENMASK(14, 12) 60 61 #define XSP_USBPHYACR6 ((SSUSB_SIFSLV_U2PHY_COM) + 0x018) 62 #define P2A6_RG_BC11_SW_EN BIT(23) 63 #define P2A6_RG_OTG_VBUSCMP_EN BIT(20) 64 65 #define XSP_U2PHYDTM1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x06C) 66 #define P2D_FORCE_IDDIG BIT(9) 67 #define P2D_RG_VBUSVALID BIT(5) 68 #define P2D_RG_SESSEND BIT(4) 69 #define P2D_RG_AVALID BIT(2) 70 #define P2D_RG_IDDIG BIT(1) 71 72 #define SSPXTP_PHYA_GLB_00 ((SSPXTP_SIFSLV_PHYA_GLB) + 0x00) 73 #define RG_XTP_GLB_BIAS_INTR_CTRL GENMASK(21, 16) 74 75 #define SSPXTP_PHYA_LN_04 ((SSPXTP_SIFSLV_PHYA_LN) + 0x04) 76 #define RG_XTP_LN0_TX_IMPSEL GENMASK(4, 0) 77 78 #define SSPXTP_PHYA_LN_14 ((SSPXTP_SIFSLV_PHYA_LN) + 0x014) 79 #define RG_XTP_LN0_RX_IMPSEL GENMASK(4, 0) 80 81 #define XSP_REF_CLK 26 /* MHZ */ 82 #define XSP_SLEW_RATE_COEF 17 83 #define XSP_SR_COEF_DIVISOR 1000 84 #define XSP_FM_DET_CYCLE_CNT 1024 85 86 /* PHY switch between pcie/usb3/sgmii */ 87 #define USB_PHY_SWITCH_CTRL 0x0 88 #define RG_PHY_SW_TYPE GENMASK(3, 0) 89 #define RG_PHY_SW_PCIE 0x0 90 #define RG_PHY_SW_USB3 0x1 91 #define RG_PHY_SW_SGMII 0x2 92 93 struct xsphy_instance { 94 struct phy *phy; 95 void __iomem *port_base; 96 struct clk *ref_clk; /* reference clock of anolog phy */ 97 u32 index; 98 u32 type; 99 struct regmap *type_sw; 100 u32 type_sw_reg; 101 u32 type_sw_index; 102 /* only for HQA test */ 103 int efuse_intr; 104 int efuse_tx_imp; 105 int efuse_rx_imp; 106 /* u2 eye diagram */ 107 int eye_src; 108 int eye_vrt; 109 int eye_term; 110 }; 111 112 struct mtk_xsphy { 113 struct device *dev; 114 void __iomem *glb_base; /* only shared u3 sif */ 115 struct xsphy_instance **phys; 116 int nphys; 117 int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ 118 int src_coef; /* coefficient for slew rate calibrate */ 119 }; 120 121 static void u2_phy_slew_rate_calibrate(struct mtk_xsphy *xsphy, 122 struct xsphy_instance *inst) 123 { 124 void __iomem *pbase = inst->port_base; 125 int calib_val; 126 int fm_out; 127 u32 tmp; 128 129 /* use force value */ 130 if (inst->eye_src) 131 return; 132 133 /* enable USB ring oscillator */ 134 mtk_phy_set_bits(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCAL_EN); 135 udelay(1); /* wait clock stable */ 136 137 /* enable free run clock */ 138 mtk_phy_set_bits(pbase + XSP_U2FREQ_FMMONR1, P2F_RG_FRCK_EN); 139 140 /* set cycle count as 1024 */ 141 mtk_phy_update_field(pbase + XSP_U2FREQ_FMCR0, P2F_RG_CYCLECNT, 142 XSP_FM_DET_CYCLE_CNT); 143 144 /* enable frequency meter */ 145 mtk_phy_set_bits(pbase + XSP_U2FREQ_FMCR0, P2F_RG_FREQDET_EN); 146 147 /* ignore return value */ 148 readl_poll_timeout(pbase + XSP_U2FREQ_FMMONR1, tmp, 149 (tmp & P2F_USB_FM_VALID), 10, 200); 150 151 fm_out = readl(pbase + XSP_U2FREQ_MMONR0); 152 153 /* disable frequency meter */ 154 mtk_phy_clear_bits(pbase + XSP_U2FREQ_FMCR0, P2F_RG_FREQDET_EN); 155 156 /* disable free run clock */ 157 mtk_phy_clear_bits(pbase + XSP_U2FREQ_FMMONR1, P2F_RG_FRCK_EN); 158 159 if (fm_out) { 160 /* (1024 / FM_OUT) x reference clock frequency x coefficient */ 161 tmp = xsphy->src_ref_clk * xsphy->src_coef; 162 tmp = (tmp * XSP_FM_DET_CYCLE_CNT) / fm_out; 163 calib_val = DIV_ROUND_CLOSEST(tmp, XSP_SR_COEF_DIVISOR); 164 } else { 165 /* if FM detection fail, set default value */ 166 calib_val = 3; 167 } 168 dev_dbg(xsphy->dev, "phy.%d, fm_out:%d, calib:%d (clk:%d, coef:%d)\n", 169 inst->index, fm_out, calib_val, 170 xsphy->src_ref_clk, xsphy->src_coef); 171 172 /* set HS slew rate */ 173 mtk_phy_update_field(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL, calib_val); 174 175 /* disable USB ring oscillator */ 176 mtk_phy_clear_bits(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCAL_EN); 177 } 178 179 static void u2_phy_instance_init(struct mtk_xsphy *xsphy, 180 struct xsphy_instance *inst) 181 { 182 void __iomem *pbase = inst->port_base; 183 184 /* DP/DM BC1.1 path Disable */ 185 mtk_phy_clear_bits(pbase + XSP_USBPHYACR6, P2A6_RG_BC11_SW_EN); 186 187 mtk_phy_set_bits(pbase + XSP_USBPHYACR0, P2A0_RG_INTR_EN); 188 } 189 190 static void u2_phy_instance_power_on(struct mtk_xsphy *xsphy, 191 struct xsphy_instance *inst) 192 { 193 void __iomem *pbase = inst->port_base; 194 u32 index = inst->index; 195 196 mtk_phy_set_bits(pbase + XSP_USBPHYACR6, P2A6_RG_OTG_VBUSCMP_EN); 197 198 mtk_phy_update_bits(pbase + XSP_U2PHYDTM1, 199 P2D_RG_VBUSVALID | P2D_RG_AVALID | P2D_RG_SESSEND, 200 P2D_RG_VBUSVALID | P2D_RG_AVALID); 201 202 dev_dbg(xsphy->dev, "%s(%d)\n", __func__, index); 203 } 204 205 static void u2_phy_instance_power_off(struct mtk_xsphy *xsphy, 206 struct xsphy_instance *inst) 207 { 208 void __iomem *pbase = inst->port_base; 209 u32 index = inst->index; 210 211 mtk_phy_clear_bits(pbase + XSP_USBPHYACR6, P2A6_RG_OTG_VBUSCMP_EN); 212 213 mtk_phy_update_bits(pbase + XSP_U2PHYDTM1, 214 P2D_RG_VBUSVALID | P2D_RG_AVALID | P2D_RG_SESSEND, 215 P2D_RG_SESSEND); 216 217 dev_dbg(xsphy->dev, "%s(%d)\n", __func__, index); 218 } 219 220 static void u2_phy_instance_set_mode(struct mtk_xsphy *xsphy, 221 struct xsphy_instance *inst, 222 enum phy_mode mode) 223 { 224 u32 tmp; 225 226 tmp = readl(inst->port_base + XSP_U2PHYDTM1); 227 switch (mode) { 228 case PHY_MODE_USB_DEVICE: 229 tmp |= P2D_FORCE_IDDIG | P2D_RG_IDDIG; 230 break; 231 case PHY_MODE_USB_HOST: 232 tmp |= P2D_FORCE_IDDIG; 233 tmp &= ~P2D_RG_IDDIG; 234 break; 235 case PHY_MODE_USB_OTG: 236 tmp &= ~(P2D_FORCE_IDDIG | P2D_RG_IDDIG); 237 break; 238 default: 239 return; 240 } 241 writel(tmp, inst->port_base + XSP_U2PHYDTM1); 242 } 243 244 static void phy_parse_property(struct mtk_xsphy *xsphy, 245 struct xsphy_instance *inst) 246 { 247 struct device *dev = &inst->phy->dev; 248 249 switch (inst->type) { 250 case PHY_TYPE_USB2: 251 device_property_read_u32(dev, "mediatek,efuse-intr", 252 &inst->efuse_intr); 253 device_property_read_u32(dev, "mediatek,eye-src", 254 &inst->eye_src); 255 device_property_read_u32(dev, "mediatek,eye-vrt", 256 &inst->eye_vrt); 257 device_property_read_u32(dev, "mediatek,eye-term", 258 &inst->eye_term); 259 dev_dbg(dev, "intr:%d, src:%d, vrt:%d, term:%d\n", 260 inst->efuse_intr, inst->eye_src, 261 inst->eye_vrt, inst->eye_term); 262 break; 263 case PHY_TYPE_USB3: 264 device_property_read_u32(dev, "mediatek,efuse-intr", 265 &inst->efuse_intr); 266 device_property_read_u32(dev, "mediatek,efuse-tx-imp", 267 &inst->efuse_tx_imp); 268 device_property_read_u32(dev, "mediatek,efuse-rx-imp", 269 &inst->efuse_rx_imp); 270 dev_dbg(dev, "intr:%d, tx-imp:%d, rx-imp:%d\n", 271 inst->efuse_intr, inst->efuse_tx_imp, 272 inst->efuse_rx_imp); 273 break; 274 case PHY_TYPE_PCIE: 275 case PHY_TYPE_SGMII: 276 /* nothing to do */ 277 break; 278 default: 279 dev_err(xsphy->dev, "incompatible phy type\n"); 280 return; 281 } 282 } 283 284 static void u2_phy_props_set(struct mtk_xsphy *xsphy, 285 struct xsphy_instance *inst) 286 { 287 void __iomem *pbase = inst->port_base; 288 289 if (inst->efuse_intr) 290 mtk_phy_update_field(pbase + XSP_USBPHYACR1, P2A1_RG_INTR_CAL, 291 inst->efuse_intr); 292 293 if (inst->eye_src) 294 mtk_phy_update_field(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL, 295 inst->eye_src); 296 297 if (inst->eye_vrt) 298 mtk_phy_update_field(pbase + XSP_USBPHYACR1, P2A1_RG_VRT_SEL, 299 inst->eye_vrt); 300 301 if (inst->eye_term) 302 mtk_phy_update_field(pbase + XSP_USBPHYACR1, P2A1_RG_TERM_SEL, 303 inst->eye_term); 304 } 305 306 static void u3_phy_props_set(struct mtk_xsphy *xsphy, 307 struct xsphy_instance *inst) 308 { 309 void __iomem *pbase = inst->port_base; 310 311 if (inst->efuse_intr) 312 mtk_phy_update_field(xsphy->glb_base + SSPXTP_PHYA_GLB_00, 313 RG_XTP_GLB_BIAS_INTR_CTRL, inst->efuse_intr); 314 315 if (inst->efuse_tx_imp) 316 mtk_phy_update_field(pbase + SSPXTP_PHYA_LN_04, 317 RG_XTP_LN0_TX_IMPSEL, inst->efuse_tx_imp); 318 319 if (inst->efuse_rx_imp) 320 mtk_phy_update_field(pbase + SSPXTP_PHYA_LN_14, 321 RG_XTP_LN0_RX_IMPSEL, inst->efuse_rx_imp); 322 } 323 324 /* type switch for usb3/pcie/sgmii */ 325 static int phy_type_syscon_get(struct xsphy_instance *instance, 326 struct device_node *dn) 327 { 328 struct of_phandle_args args; 329 int ret; 330 331 /* type switch function is optional */ 332 if (!of_property_present(dn, "mediatek,syscon-type")) 333 return 0; 334 335 ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type", 336 2, 0, &args); 337 if (ret) 338 return ret; 339 340 instance->type_sw_reg = args.args[0]; 341 instance->type_sw_index = args.args[1] & 0x3; /* <=3 */ 342 instance->type_sw = syscon_node_to_regmap(args.np); 343 of_node_put(args.np); 344 dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n", 345 instance->type_sw_reg, instance->type_sw_index); 346 347 return PTR_ERR_OR_ZERO(instance->type_sw); 348 } 349 350 static int phy_type_set(struct xsphy_instance *instance) 351 { 352 int type; 353 u32 offset; 354 355 if (!instance->type_sw) 356 return 0; 357 358 switch (instance->type) { 359 case PHY_TYPE_USB3: 360 type = RG_PHY_SW_USB3; 361 break; 362 case PHY_TYPE_PCIE: 363 type = RG_PHY_SW_PCIE; 364 break; 365 case PHY_TYPE_SGMII: 366 type = RG_PHY_SW_SGMII; 367 break; 368 case PHY_TYPE_USB2: 369 default: 370 return 0; 371 } 372 373 offset = instance->type_sw_index * BITS_PER_BYTE; 374 regmap_update_bits(instance->type_sw, instance->type_sw_reg, 375 RG_PHY_SW_TYPE << offset, type << offset); 376 377 return 0; 378 } 379 380 static int mtk_phy_init(struct phy *phy) 381 { 382 struct xsphy_instance *inst = phy_get_drvdata(phy); 383 struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); 384 int ret; 385 386 ret = clk_prepare_enable(inst->ref_clk); 387 if (ret) { 388 dev_err(xsphy->dev, "failed to enable ref_clk\n"); 389 return ret; 390 } 391 392 switch (inst->type) { 393 case PHY_TYPE_USB2: 394 u2_phy_instance_init(xsphy, inst); 395 u2_phy_props_set(xsphy, inst); 396 break; 397 case PHY_TYPE_USB3: 398 u3_phy_props_set(xsphy, inst); 399 break; 400 case PHY_TYPE_PCIE: 401 case PHY_TYPE_SGMII: 402 /* nothing to do, only used to set type */ 403 break; 404 default: 405 dev_err(xsphy->dev, "incompatible phy type\n"); 406 clk_disable_unprepare(inst->ref_clk); 407 return -EINVAL; 408 } 409 410 return 0; 411 } 412 413 static int mtk_phy_power_on(struct phy *phy) 414 { 415 struct xsphy_instance *inst = phy_get_drvdata(phy); 416 struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); 417 418 if (inst->type == PHY_TYPE_USB2) { 419 u2_phy_instance_power_on(xsphy, inst); 420 u2_phy_slew_rate_calibrate(xsphy, inst); 421 } 422 423 return 0; 424 } 425 426 static int mtk_phy_power_off(struct phy *phy) 427 { 428 struct xsphy_instance *inst = phy_get_drvdata(phy); 429 struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); 430 431 if (inst->type == PHY_TYPE_USB2) 432 u2_phy_instance_power_off(xsphy, inst); 433 434 return 0; 435 } 436 437 static int mtk_phy_exit(struct phy *phy) 438 { 439 struct xsphy_instance *inst = phy_get_drvdata(phy); 440 441 clk_disable_unprepare(inst->ref_clk); 442 return 0; 443 } 444 445 static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) 446 { 447 struct xsphy_instance *inst = phy_get_drvdata(phy); 448 struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); 449 450 if (inst->type == PHY_TYPE_USB2) 451 u2_phy_instance_set_mode(xsphy, inst, mode); 452 453 return 0; 454 } 455 456 static struct phy *mtk_phy_xlate(struct device *dev, 457 const struct of_phandle_args *args) 458 { 459 struct mtk_xsphy *xsphy = dev_get_drvdata(dev); 460 struct xsphy_instance *inst = NULL; 461 struct device_node *phy_np = args->np; 462 int index; 463 464 if (args->args_count != 1) { 465 dev_err(dev, "invalid number of cells in 'phy' property\n"); 466 return ERR_PTR(-EINVAL); 467 } 468 469 for (index = 0; index < xsphy->nphys; index++) 470 if (phy_np == xsphy->phys[index]->phy->dev.of_node) { 471 inst = xsphy->phys[index]; 472 break; 473 } 474 475 if (!inst) { 476 dev_err(dev, "failed to find appropriate phy\n"); 477 return ERR_PTR(-EINVAL); 478 } 479 480 inst->type = args->args[0]; 481 if (!(inst->type == PHY_TYPE_USB2 || 482 inst->type == PHY_TYPE_USB3 || 483 inst->type == PHY_TYPE_PCIE || 484 inst->type == PHY_TYPE_SGMII)) { 485 dev_err(dev, "unsupported phy type: %d\n", inst->type); 486 return ERR_PTR(-EINVAL); 487 } 488 489 phy_parse_property(xsphy, inst); 490 phy_type_set(inst); 491 492 return inst->phy; 493 } 494 495 static const struct phy_ops mtk_xsphy_ops = { 496 .init = mtk_phy_init, 497 .exit = mtk_phy_exit, 498 .power_on = mtk_phy_power_on, 499 .power_off = mtk_phy_power_off, 500 .set_mode = mtk_phy_set_mode, 501 .owner = THIS_MODULE, 502 }; 503 504 static const struct of_device_id mtk_xsphy_id_table[] = { 505 { .compatible = "mediatek,xsphy", }, 506 { }, 507 }; 508 MODULE_DEVICE_TABLE(of, mtk_xsphy_id_table); 509 510 static int mtk_xsphy_probe(struct platform_device *pdev) 511 { 512 struct device *dev = &pdev->dev; 513 struct device_node *np = dev->of_node; 514 struct phy_provider *provider; 515 struct resource *glb_res; 516 struct mtk_xsphy *xsphy; 517 struct resource res; 518 int port; 519 520 xsphy = devm_kzalloc(dev, sizeof(*xsphy), GFP_KERNEL); 521 if (!xsphy) 522 return -ENOMEM; 523 524 xsphy->nphys = of_get_child_count(np); 525 xsphy->phys = devm_kcalloc(dev, xsphy->nphys, 526 sizeof(*xsphy->phys), GFP_KERNEL); 527 if (!xsphy->phys) 528 return -ENOMEM; 529 530 xsphy->dev = dev; 531 platform_set_drvdata(pdev, xsphy); 532 533 glb_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 534 /* optional, may not exist if no u3 phys */ 535 if (glb_res) { 536 /* get banks shared by multiple u3 phys */ 537 xsphy->glb_base = devm_ioremap_resource(dev, glb_res); 538 if (IS_ERR(xsphy->glb_base)) { 539 dev_err(dev, "failed to remap glb regs\n"); 540 return PTR_ERR(xsphy->glb_base); 541 } 542 } 543 544 xsphy->src_ref_clk = XSP_REF_CLK; 545 xsphy->src_coef = XSP_SLEW_RATE_COEF; 546 /* update parameters of slew rate calibrate if exist */ 547 device_property_read_u32(dev, "mediatek,src-ref-clk-mhz", 548 &xsphy->src_ref_clk); 549 device_property_read_u32(dev, "mediatek,src-coef", &xsphy->src_coef); 550 551 port = 0; 552 for_each_child_of_node_scoped(np, child_np) { 553 struct xsphy_instance *inst; 554 struct phy *phy; 555 int retval; 556 557 inst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL); 558 if (!inst) 559 return -ENOMEM; 560 561 xsphy->phys[port] = inst; 562 563 phy = devm_phy_create(dev, child_np, &mtk_xsphy_ops); 564 if (IS_ERR(phy)) { 565 dev_err(dev, "failed to create phy\n"); 566 return PTR_ERR(phy); 567 } 568 569 retval = of_address_to_resource(child_np, 0, &res); 570 if (retval) { 571 dev_err(dev, "failed to get address resource(id-%d)\n", 572 port); 573 return retval; 574 } 575 576 inst->port_base = devm_ioremap_resource(&phy->dev, &res); 577 if (IS_ERR(inst->port_base)) { 578 dev_err(dev, "failed to remap phy regs\n"); 579 return PTR_ERR(inst->port_base); 580 } 581 582 inst->phy = phy; 583 inst->index = port; 584 phy_set_drvdata(phy, inst); 585 port++; 586 587 inst->ref_clk = devm_clk_get(&phy->dev, "ref"); 588 if (IS_ERR(inst->ref_clk)) { 589 dev_err(dev, "failed to get ref_clk(id-%d)\n", port); 590 return PTR_ERR(inst->ref_clk); 591 } 592 593 retval = phy_type_syscon_get(inst, child_np); 594 if (retval) 595 return retval; 596 } 597 598 provider = devm_of_phy_provider_register(dev, mtk_phy_xlate); 599 return PTR_ERR_OR_ZERO(provider); 600 } 601 602 static struct platform_driver mtk_xsphy_driver = { 603 .probe = mtk_xsphy_probe, 604 .driver = { 605 .name = "mtk-xsphy", 606 .of_match_table = mtk_xsphy_id_table, 607 }, 608 }; 609 610 module_platform_driver(mtk_xsphy_driver); 611 612 MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>"); 613 MODULE_DESCRIPTION("MediaTek USB XS-PHY driver"); 614 MODULE_LICENSE("GPL v2"); 615