Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.17-rc7 572 lines 16 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2 3#include <linux/clk.h> 4#include <linux/err.h> 5#include <linux/io.h> 6#include <linux/module.h> 7#include <linux/of_device.h> 8#include <linux/phy/phy.h> 9#include <linux/platform_device.h> 10#include <linux/delay.h> 11#include <linux/regmap.h> 12#include <linux/mfd/syscon.h> 13 14/* USB QSCRATCH Hardware registers */ 15#define QSCRATCH_GENERAL_CFG (0x08) 16#define HSUSB_PHY_CTRL_REG (0x10) 17 18/* PHY_CTRL_REG */ 19#define HSUSB_CTRL_DMSEHV_CLAMP BIT(24) 20#define HSUSB_CTRL_USB2_SUSPEND BIT(23) 21#define HSUSB_CTRL_UTMI_CLK_EN BIT(21) 22#define HSUSB_CTRL_UTMI_OTG_VBUS_VALID BIT(20) 23#define HSUSB_CTRL_USE_CLKCORE BIT(18) 24#define HSUSB_CTRL_DPSEHV_CLAMP BIT(17) 25#define HSUSB_CTRL_COMMONONN BIT(11) 26#define HSUSB_CTRL_ID_HV_CLAMP BIT(9) 27#define HSUSB_CTRL_OTGSESSVLD_CLAMP BIT(8) 28#define HSUSB_CTRL_CLAMP_EN BIT(7) 29#define HSUSB_CTRL_RETENABLEN BIT(1) 30#define HSUSB_CTRL_POR BIT(0) 31 32/* QSCRATCH_GENERAL_CFG */ 33#define HSUSB_GCFG_XHCI_REV BIT(2) 34 35/* USB QSCRATCH Hardware registers */ 36#define SSUSB_PHY_CTRL_REG (0x00) 37#define SSUSB_PHY_PARAM_CTRL_1 (0x04) 38#define SSUSB_PHY_PARAM_CTRL_2 (0x08) 39#define CR_PROTOCOL_DATA_IN_REG (0x0c) 40#define CR_PROTOCOL_DATA_OUT_REG (0x10) 41#define CR_PROTOCOL_CAP_ADDR_REG (0x14) 42#define CR_PROTOCOL_CAP_DATA_REG (0x18) 43#define CR_PROTOCOL_READ_REG (0x1c) 44#define CR_PROTOCOL_WRITE_REG (0x20) 45 46/* PHY_CTRL_REG */ 47#define SSUSB_CTRL_REF_USE_PAD BIT(28) 48#define SSUSB_CTRL_TEST_POWERDOWN BIT(27) 49#define SSUSB_CTRL_LANE0_PWR_PRESENT BIT(24) 50#define SSUSB_CTRL_SS_PHY_EN BIT(8) 51#define SSUSB_CTRL_SS_PHY_RESET BIT(7) 52 53/* SSPHY control registers - Does this need 0x30? */ 54#define SSPHY_CTRL_RX_OVRD_IN_HI(lane) (0x1006 + 0x100 * (lane)) 55#define SSPHY_CTRL_TX_OVRD_DRV_LO(lane) (0x1002 + 0x100 * (lane)) 56 57/* SSPHY SoC version specific values */ 58#define SSPHY_RX_EQ_VALUE 4 /* Override value for rx_eq */ 59/* Override value for transmit preemphasis */ 60#define SSPHY_TX_DEEMPH_3_5DB 23 61/* Override value for mpll */ 62#define SSPHY_MPLL_VALUE 0 63 64/* QSCRATCH PHY_PARAM_CTRL1 fields */ 65#define PHY_PARAM_CTRL1_TX_FULL_SWING_MASK GENMASK(26, 19) 66#define PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK GENMASK(19, 13) 67#define PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK GENMASK(13, 7) 68#define PHY_PARAM_CTRL1_LOS_BIAS_MASK GENMASK(7, 2) 69 70#define PHY_PARAM_CTRL1_MASK \ 71 (PHY_PARAM_CTRL1_TX_FULL_SWING_MASK | \ 72 PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK | \ 73 PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK | \ 74 PHY_PARAM_CTRL1_LOS_BIAS_MASK) 75 76#define PHY_PARAM_CTRL1_TX_FULL_SWING(x) \ 77 (((x) << 20) & PHY_PARAM_CTRL1_TX_FULL_SWING_MASK) 78#define PHY_PARAM_CTRL1_TX_DEEMPH_6DB(x) \ 79 (((x) << 14) & PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK) 80#define PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB(x) \ 81 (((x) << 8) & PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK) 82#define PHY_PARAM_CTRL1_LOS_BIAS(x) \ 83 (((x) << 3) & PHY_PARAM_CTRL1_LOS_BIAS_MASK) 84 85/* RX OVRD IN HI bits */ 86#define RX_OVRD_IN_HI_RX_RESET_OVRD BIT(13) 87#define RX_OVRD_IN_HI_RX_RX_RESET BIT(12) 88#define RX_OVRD_IN_HI_RX_EQ_OVRD BIT(11) 89#define RX_OVRD_IN_HI_RX_EQ_MASK GENMASK(10, 7) 90#define RX_OVRD_IN_HI_RX_EQ(x) ((x) << 8) 91#define RX_OVRD_IN_HI_RX_EQ_EN_OVRD BIT(7) 92#define RX_OVRD_IN_HI_RX_EQ_EN BIT(6) 93#define RX_OVRD_IN_HI_RX_LOS_FILTER_OVRD BIT(5) 94#define RX_OVRD_IN_HI_RX_LOS_FILTER_MASK GENMASK(4, 2) 95#define RX_OVRD_IN_HI_RX_RATE_OVRD BIT(2) 96#define RX_OVRD_IN_HI_RX_RATE_MASK GENMASK(2, 0) 97 98/* TX OVRD DRV LO register bits */ 99#define TX_OVRD_DRV_LO_AMPLITUDE_MASK GENMASK(6, 0) 100#define TX_OVRD_DRV_LO_PREEMPH_MASK GENMASK(13, 6) 101#define TX_OVRD_DRV_LO_PREEMPH(x) ((x) << 7) 102#define TX_OVRD_DRV_LO_EN BIT(14) 103 104/* MPLL bits */ 105#define SSPHY_MPLL_MASK GENMASK(8, 5) 106#define SSPHY_MPLL(x) ((x) << 5) 107 108/* SS CAP register bits */ 109#define SS_CR_CAP_ADDR_REG BIT(0) 110#define SS_CR_CAP_DATA_REG BIT(0) 111#define SS_CR_READ_REG BIT(0) 112#define SS_CR_WRITE_REG BIT(0) 113 114struct usb_phy { 115 void __iomem *base; 116 struct device *dev; 117 struct clk *xo_clk; 118 struct clk *ref_clk; 119 u32 rx_eq; 120 u32 tx_deamp_3_5db; 121 u32 mpll; 122}; 123 124struct phy_drvdata { 125 struct phy_ops ops; 126 u32 clk_rate; 127}; 128 129/** 130 * usb_phy_write_readback() - Write register and read back masked value to 131 * confirm it is written 132 * 133 * @phy_dwc3: QCOM DWC3 phy context 134 * @offset: register offset. 135 * @mask: register bitmask specifying what should be updated 136 * @val: value to write. 137 */ 138static inline void usb_phy_write_readback(struct usb_phy *phy_dwc3, 139 u32 offset, 140 const u32 mask, u32 val) 141{ 142 u32 write_val, tmp = readl(phy_dwc3->base + offset); 143 144 tmp &= ~mask; /* retain other bits */ 145 write_val = tmp | val; 146 147 writel(write_val, phy_dwc3->base + offset); 148 149 /* Read back to see if val was written */ 150 tmp = readl(phy_dwc3->base + offset); 151 tmp &= mask; /* clear other bits */ 152 153 if (tmp != val) 154 dev_err(phy_dwc3->dev, "write: %x to QSCRATCH: %x FAILED\n", val, offset); 155} 156 157static int wait_for_latch(void __iomem *addr) 158{ 159 u32 retry = 10; 160 161 while (true) { 162 if (!readl(addr)) 163 break; 164 165 if (--retry == 0) 166 return -ETIMEDOUT; 167 168 usleep_range(10, 20); 169 } 170 171 return 0; 172} 173 174/** 175 * usb_ss_write_phycreg() - Write SSPHY register 176 * 177 * @phy_dwc3: QCOM DWC3 phy context 178 * @addr: SSPHY address to write. 179 * @val: value to write. 180 */ 181static int usb_ss_write_phycreg(struct usb_phy *phy_dwc3, 182 u32 addr, u32 val) 183{ 184 int ret; 185 186 writel(addr, phy_dwc3->base + CR_PROTOCOL_DATA_IN_REG); 187 writel(SS_CR_CAP_ADDR_REG, 188 phy_dwc3->base + CR_PROTOCOL_CAP_ADDR_REG); 189 190 ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_CAP_ADDR_REG); 191 if (ret) 192 goto err_wait; 193 194 writel(val, phy_dwc3->base + CR_PROTOCOL_DATA_IN_REG); 195 writel(SS_CR_CAP_DATA_REG, 196 phy_dwc3->base + CR_PROTOCOL_CAP_DATA_REG); 197 198 ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_CAP_DATA_REG); 199 if (ret) 200 goto err_wait; 201 202 writel(SS_CR_WRITE_REG, phy_dwc3->base + CR_PROTOCOL_WRITE_REG); 203 204 ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_WRITE_REG); 205 206err_wait: 207 if (ret) 208 dev_err(phy_dwc3->dev, "timeout waiting for latch\n"); 209 return ret; 210} 211 212/** 213 * usb_ss_read_phycreg() - Read SSPHY register. 214 * 215 * @phy_dwc3: QCOM DWC3 phy context 216 * @addr: SSPHY address to read. 217 * @val: pointer in which read is store. 218 */ 219static int usb_ss_read_phycreg(struct usb_phy *phy_dwc3, 220 u32 addr, u32 *val) 221{ 222 int ret; 223 224 writel(addr, phy_dwc3->base + CR_PROTOCOL_DATA_IN_REG); 225 writel(SS_CR_CAP_ADDR_REG, 226 phy_dwc3->base + CR_PROTOCOL_CAP_ADDR_REG); 227 228 ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_CAP_ADDR_REG); 229 if (ret) 230 goto err_wait; 231 232 /* 233 * Due to hardware bug, first read of SSPHY register might be 234 * incorrect. Hence as workaround, SW should perform SSPHY register 235 * read twice, but use only second read and ignore first read. 236 */ 237 writel(SS_CR_READ_REG, phy_dwc3->base + CR_PROTOCOL_READ_REG); 238 239 ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_READ_REG); 240 if (ret) 241 goto err_wait; 242 243 /* throwaway read */ 244 readl(phy_dwc3->base + CR_PROTOCOL_DATA_OUT_REG); 245 246 writel(SS_CR_READ_REG, phy_dwc3->base + CR_PROTOCOL_READ_REG); 247 248 ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_READ_REG); 249 if (ret) 250 goto err_wait; 251 252 *val = readl(phy_dwc3->base + CR_PROTOCOL_DATA_OUT_REG); 253 254err_wait: 255 return ret; 256} 257 258static int qcom_ipq806x_usb_hs_phy_init(struct phy *phy) 259{ 260 struct usb_phy *phy_dwc3 = phy_get_drvdata(phy); 261 int ret; 262 u32 val; 263 264 ret = clk_prepare_enable(phy_dwc3->xo_clk); 265 if (ret) 266 return ret; 267 268 ret = clk_prepare_enable(phy_dwc3->ref_clk); 269 if (ret) { 270 clk_disable_unprepare(phy_dwc3->xo_clk); 271 return ret; 272 } 273 274 /* 275 * HSPHY Initialization: Enable UTMI clock, select 19.2MHz fsel 276 * enable clamping, and disable RETENTION (power-on default is ENABLED) 277 */ 278 val = HSUSB_CTRL_DPSEHV_CLAMP | HSUSB_CTRL_DMSEHV_CLAMP | 279 HSUSB_CTRL_RETENABLEN | HSUSB_CTRL_COMMONONN | 280 HSUSB_CTRL_OTGSESSVLD_CLAMP | HSUSB_CTRL_ID_HV_CLAMP | 281 HSUSB_CTRL_UTMI_OTG_VBUS_VALID | HSUSB_CTRL_UTMI_CLK_EN | 282 HSUSB_CTRL_CLAMP_EN | 0x70; 283 284 /* use core clock if external reference is not present */ 285 if (!phy_dwc3->xo_clk) 286 val |= HSUSB_CTRL_USE_CLKCORE; 287 288 writel(val, phy_dwc3->base + HSUSB_PHY_CTRL_REG); 289 usleep_range(2000, 2200); 290 291 /* Disable (bypass) VBUS and ID filters */ 292 writel(HSUSB_GCFG_XHCI_REV, phy_dwc3->base + QSCRATCH_GENERAL_CFG); 293 294 return 0; 295} 296 297static int qcom_ipq806x_usb_hs_phy_exit(struct phy *phy) 298{ 299 struct usb_phy *phy_dwc3 = phy_get_drvdata(phy); 300 301 clk_disable_unprepare(phy_dwc3->ref_clk); 302 clk_disable_unprepare(phy_dwc3->xo_clk); 303 304 return 0; 305} 306 307static int qcom_ipq806x_usb_ss_phy_init(struct phy *phy) 308{ 309 struct usb_phy *phy_dwc3 = phy_get_drvdata(phy); 310 int ret; 311 u32 data; 312 313 ret = clk_prepare_enable(phy_dwc3->xo_clk); 314 if (ret) 315 return ret; 316 317 ret = clk_prepare_enable(phy_dwc3->ref_clk); 318 if (ret) { 319 clk_disable_unprepare(phy_dwc3->xo_clk); 320 return ret; 321 } 322 323 /* reset phy */ 324 data = readl(phy_dwc3->base + SSUSB_PHY_CTRL_REG); 325 writel(data | SSUSB_CTRL_SS_PHY_RESET, 326 phy_dwc3->base + SSUSB_PHY_CTRL_REG); 327 usleep_range(2000, 2200); 328 writel(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); 329 330 /* clear REF_PAD if we don't have XO clk */ 331 if (!phy_dwc3->xo_clk) 332 data &= ~SSUSB_CTRL_REF_USE_PAD; 333 else 334 data |= SSUSB_CTRL_REF_USE_PAD; 335 336 writel(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); 337 338 /* wait for ref clk to become stable, this can take up to 30ms */ 339 msleep(30); 340 341 data |= SSUSB_CTRL_SS_PHY_EN | SSUSB_CTRL_LANE0_PWR_PRESENT; 342 writel(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); 343 344 /* 345 * WORKAROUND: There is SSPHY suspend bug due to which USB enumerates 346 * in HS mode instead of SS mode. Workaround it by asserting 347 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode 348 */ 349 ret = usb_ss_read_phycreg(phy_dwc3, 0x102D, &data); 350 if (ret) 351 goto err_phy_trans; 352 353 data |= (1 << 7); 354 ret = usb_ss_write_phycreg(phy_dwc3, 0x102D, data); 355 if (ret) 356 goto err_phy_trans; 357 358 ret = usb_ss_read_phycreg(phy_dwc3, 0x1010, &data); 359 if (ret) 360 goto err_phy_trans; 361 362 data &= ~0xff0; 363 data |= 0x20; 364 ret = usb_ss_write_phycreg(phy_dwc3, 0x1010, data); 365 if (ret) 366 goto err_phy_trans; 367 368 /* 369 * Fix RX Equalization setting as follows 370 * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 371 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 372 * LANE0.RX_OVRD_IN_HI.RX_EQ set based on SoC version 373 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 374 */ 375 ret = usb_ss_read_phycreg(phy_dwc3, SSPHY_CTRL_RX_OVRD_IN_HI(0), &data); 376 if (ret) 377 goto err_phy_trans; 378 379 data &= ~RX_OVRD_IN_HI_RX_EQ_EN; 380 data |= RX_OVRD_IN_HI_RX_EQ_EN_OVRD; 381 data &= ~RX_OVRD_IN_HI_RX_EQ_MASK; 382 data |= RX_OVRD_IN_HI_RX_EQ(phy_dwc3->rx_eq); 383 data |= RX_OVRD_IN_HI_RX_EQ_OVRD; 384 ret = usb_ss_write_phycreg(phy_dwc3, 385 SSPHY_CTRL_RX_OVRD_IN_HI(0), data); 386 if (ret) 387 goto err_phy_trans; 388 389 /* 390 * Set EQ and TX launch amplitudes as follows 391 * LANE0.TX_OVRD_DRV_LO.PREEMPH set based on SoC version 392 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 110 393 * LANE0.TX_OVRD_DRV_LO.EN set to 1. 394 */ 395 ret = usb_ss_read_phycreg(phy_dwc3, 396 SSPHY_CTRL_TX_OVRD_DRV_LO(0), &data); 397 if (ret) 398 goto err_phy_trans; 399 400 data &= ~TX_OVRD_DRV_LO_PREEMPH_MASK; 401 data |= TX_OVRD_DRV_LO_PREEMPH(phy_dwc3->tx_deamp_3_5db); 402 data &= ~TX_OVRD_DRV_LO_AMPLITUDE_MASK; 403 data |= 0x6E; 404 data |= TX_OVRD_DRV_LO_EN; 405 ret = usb_ss_write_phycreg(phy_dwc3, 406 SSPHY_CTRL_TX_OVRD_DRV_LO(0), data); 407 if (ret) 408 goto err_phy_trans; 409 410 data = 0; 411 data &= ~SSPHY_MPLL_MASK; 412 data |= SSPHY_MPLL(phy_dwc3->mpll); 413 usb_ss_write_phycreg(phy_dwc3, 0x30, data); 414 415 /* 416 * Set the QSCRATCH PHY_PARAM_CTRL1 parameters as follows 417 * TX_FULL_SWING [26:20] amplitude to 110 418 * TX_DEEMPH_6DB [19:14] to 32 419 * TX_DEEMPH_3_5DB [13:8] set based on SoC version 420 * LOS_BIAS [7:3] to 9 421 */ 422 data = readl(phy_dwc3->base + SSUSB_PHY_PARAM_CTRL_1); 423 424 data &= ~PHY_PARAM_CTRL1_MASK; 425 426 data |= PHY_PARAM_CTRL1_TX_FULL_SWING(0x6e) | 427 PHY_PARAM_CTRL1_TX_DEEMPH_6DB(0x20) | 428 PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB(phy_dwc3->tx_deamp_3_5db) | 429 PHY_PARAM_CTRL1_LOS_BIAS(0x9); 430 431 usb_phy_write_readback(phy_dwc3, SSUSB_PHY_PARAM_CTRL_1, 432 PHY_PARAM_CTRL1_MASK, data); 433 434err_phy_trans: 435 return ret; 436} 437 438static int qcom_ipq806x_usb_ss_phy_exit(struct phy *phy) 439{ 440 struct usb_phy *phy_dwc3 = phy_get_drvdata(phy); 441 442 /* Sequence to put SSPHY in low power state: 443 * 1. Clear REF_PHY_EN in PHY_CTRL_REG 444 * 2. Clear REF_USE_PAD in PHY_CTRL_REG 445 * 3. Set TEST_POWERED_DOWN in PHY_CTRL_REG to enable PHY retention 446 */ 447 usb_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, 448 SSUSB_CTRL_SS_PHY_EN, 0x0); 449 usb_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, 450 SSUSB_CTRL_REF_USE_PAD, 0x0); 451 usb_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, 452 SSUSB_CTRL_TEST_POWERDOWN, 0x0); 453 454 clk_disable_unprepare(phy_dwc3->ref_clk); 455 clk_disable_unprepare(phy_dwc3->xo_clk); 456 457 return 0; 458} 459 460static const struct phy_drvdata qcom_ipq806x_usb_hs_drvdata = { 461 .ops = { 462 .init = qcom_ipq806x_usb_hs_phy_init, 463 .exit = qcom_ipq806x_usb_hs_phy_exit, 464 .owner = THIS_MODULE, 465 }, 466 .clk_rate = 60000000, 467}; 468 469static const struct phy_drvdata qcom_ipq806x_usb_ss_drvdata = { 470 .ops = { 471 .init = qcom_ipq806x_usb_ss_phy_init, 472 .exit = qcom_ipq806x_usb_ss_phy_exit, 473 .owner = THIS_MODULE, 474 }, 475 .clk_rate = 125000000, 476}; 477 478static const struct of_device_id qcom_ipq806x_usb_phy_table[] = { 479 { .compatible = "qcom,ipq806x-usb-phy-hs", 480 .data = &qcom_ipq806x_usb_hs_drvdata }, 481 { .compatible = "qcom,ipq806x-usb-phy-ss", 482 .data = &qcom_ipq806x_usb_ss_drvdata }, 483 { /* Sentinel */ } 484}; 485MODULE_DEVICE_TABLE(of, qcom_ipq806x_usb_phy_table); 486 487static int qcom_ipq806x_usb_phy_probe(struct platform_device *pdev) 488{ 489 struct resource *res; 490 resource_size_t size; 491 struct phy *generic_phy; 492 struct usb_phy *phy_dwc3; 493 const struct phy_drvdata *data; 494 struct phy_provider *phy_provider; 495 496 phy_dwc3 = devm_kzalloc(&pdev->dev, sizeof(*phy_dwc3), GFP_KERNEL); 497 if (!phy_dwc3) 498 return -ENOMEM; 499 500 data = of_device_get_match_data(&pdev->dev); 501 502 phy_dwc3->dev = &pdev->dev; 503 504 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 505 if (!res) 506 return -EINVAL; 507 size = resource_size(res); 508 phy_dwc3->base = devm_ioremap(phy_dwc3->dev, res->start, size); 509 510 if (!phy_dwc3->base) { 511 dev_err(phy_dwc3->dev, "failed to map reg\n"); 512 return -ENOMEM; 513 } 514 515 phy_dwc3->ref_clk = devm_clk_get(phy_dwc3->dev, "ref"); 516 if (IS_ERR(phy_dwc3->ref_clk)) { 517 dev_dbg(phy_dwc3->dev, "cannot get reference clock\n"); 518 return PTR_ERR(phy_dwc3->ref_clk); 519 } 520 521 clk_set_rate(phy_dwc3->ref_clk, data->clk_rate); 522 523 phy_dwc3->xo_clk = devm_clk_get(phy_dwc3->dev, "xo"); 524 if (IS_ERR(phy_dwc3->xo_clk)) { 525 dev_dbg(phy_dwc3->dev, "cannot get TCXO clock\n"); 526 phy_dwc3->xo_clk = NULL; 527 } 528 529 /* Parse device node to probe HSIO settings */ 530 if (device_property_read_u32(&pdev->dev, "qcom,rx-eq", 531 &phy_dwc3->rx_eq)) 532 phy_dwc3->rx_eq = SSPHY_RX_EQ_VALUE; 533 534 if (device_property_read_u32(&pdev->dev, "qcom,tx-deamp_3_5db", 535 &phy_dwc3->tx_deamp_3_5db)) 536 phy_dwc3->tx_deamp_3_5db = SSPHY_TX_DEEMPH_3_5DB; 537 538 if (device_property_read_u32(&pdev->dev, "qcom,mpll", &phy_dwc3->mpll)) 539 phy_dwc3->mpll = SSPHY_MPLL_VALUE; 540 541 generic_phy = devm_phy_create(phy_dwc3->dev, pdev->dev.of_node, &data->ops); 542 543 if (IS_ERR(generic_phy)) 544 return PTR_ERR(generic_phy); 545 546 phy_set_drvdata(generic_phy, phy_dwc3); 547 platform_set_drvdata(pdev, phy_dwc3); 548 549 phy_provider = devm_of_phy_provider_register(phy_dwc3->dev, 550 of_phy_simple_xlate); 551 552 if (IS_ERR(phy_provider)) 553 return PTR_ERR(phy_provider); 554 555 return 0; 556} 557 558static struct platform_driver qcom_ipq806x_usb_phy_driver = { 559 .probe = qcom_ipq806x_usb_phy_probe, 560 .driver = { 561 .name = "qcom-ipq806x-usb-phy", 562 .of_match_table = qcom_ipq806x_usb_phy_table, 563 }, 564}; 565 566module_platform_driver(qcom_ipq806x_usb_phy_driver); 567 568MODULE_ALIAS("platform:phy-qcom-ipq806x-usb"); 569MODULE_LICENSE("GPL v2"); 570MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>"); 571MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>"); 572MODULE_DESCRIPTION("DesignWare USB3 QCOM PHY driver");