diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-08 13:03:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-08 13:03:52 -0400 |
commit | 132d68d37d33f1d0b9c1f507c8b4d64c27ecec8a (patch) | |
tree | b3c05972e5579e1574873fe745fb1358c62a269c /drivers/phy/qualcomm/phy-qcom-qmp.c | |
parent | 80f232121b69cc69a31ccb2b38c1665d770b0710 (diff) | |
parent | 3515468a87a47781f6af818773650513ff14656a (diff) |
Merge tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY updates from Greg KH:
"Here is the big set of USB and PHY driver patches for 5.2-rc1
There is the usual set of:
- USB gadget updates
- PHY driver updates and additions
- USB serial driver updates and fixes
- typec updates and new chips supported
- mtu3 driver updates
- xhci driver updates
- other tiny driver updates
Nothing really interesting, just constant forward progress.
All of these have been in linux-next for a while with no reported
issues. The usb-gadget and usb-serial trees were merged a bit "late",
but both of them had been in linux-next before they got merged here
last Friday"
* tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (206 commits)
USB: serial: f81232: implement break control
USB: serial: f81232: add high baud rate support
USB: serial: f81232: clear overrun flag
USB: serial: f81232: fix interrupt worker not stop
usb: dwc3: Rename DWC3_DCTL_LPM_ERRATA
usb: dwc3: Fix default lpm_nyet_threshold value
usb: dwc3: debug: Print GET_STATUS(device) tracepoint
usb: dwc3: Do core validation early on probe
usb: dwc3: gadget: Set lpm_capable
usb: gadget: atmel: tie wake lock to running clock
usb: gadget: atmel: support USB suspend
usb: gadget: atmel_usba_udc: simplify setting of interrupt-enabled mask
dwc2: gadget: Fix completed transfer size calculation in DDMA
usb: dwc2: Set lpm mode parameters depend on HW configuration
usb: dwc2: Fix channel disable flow
usb: dwc2: Set actual frame number for completed ISOC transfer
usb: gadget: do not use __constant_cpu_to_le16
usb: dwc2: gadget: Increase descriptors count for ISOC's
usb: introduce usb_ep_type_string() function
usb: dwc3: move synchronize_irq() out of the spinlock protected block
...
Diffstat (limited to 'drivers/phy/qualcomm/phy-qcom-qmp.c')
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp.c | 222 |
1 files changed, 165 insertions, 57 deletions
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 08d6f6f7f039..cd91b4179b10 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c | |||
@@ -242,6 +242,88 @@ static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { | |||
242 | QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e), | 242 | QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e), |
243 | }; | 243 | }; |
244 | 244 | ||
245 | static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = { | ||
246 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), | ||
247 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), | ||
248 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x0f), | ||
249 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), | ||
250 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), | ||
251 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), | ||
252 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), | ||
253 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), | ||
254 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), | ||
255 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), | ||
256 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), | ||
257 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), | ||
258 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), | ||
259 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), | ||
260 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), | ||
261 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), | ||
262 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), | ||
263 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x03), | ||
264 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x55), | ||
265 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x55), | ||
266 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), | ||
267 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), | ||
268 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), | ||
269 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), | ||
270 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x08), | ||
271 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), | ||
272 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x34), | ||
273 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), | ||
274 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), | ||
275 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), | ||
276 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x07), | ||
277 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), | ||
278 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), | ||
279 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), | ||
280 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), | ||
281 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), | ||
282 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), | ||
283 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), | ||
284 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), | ||
285 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), | ||
286 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), | ||
287 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), | ||
288 | }; | ||
289 | |||
290 | static const struct qmp_phy_init_tbl msm8998_pcie_tx_tbl[] = { | ||
291 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), | ||
292 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), | ||
293 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), | ||
294 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), | ||
295 | }; | ||
296 | |||
297 | static const struct qmp_phy_init_tbl msm8998_pcie_rx_tbl[] = { | ||
298 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), | ||
299 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x1c), | ||
300 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), | ||
301 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0a), | ||
302 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), | ||
303 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), | ||
304 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), | ||
305 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), | ||
306 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), | ||
307 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x00), | ||
308 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), | ||
309 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), | ||
310 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), | ||
311 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), | ||
312 | }; | ||
313 | |||
314 | static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = { | ||
315 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), | ||
316 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), | ||
317 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), | ||
318 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), | ||
319 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), | ||
320 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), | ||
321 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), | ||
322 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), | ||
323 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x99), | ||
324 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), | ||
325 | }; | ||
326 | |||
245 | static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { | 327 | static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { |
246 | QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), | 328 | QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), |
247 | QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), | 329 | QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), |
@@ -897,6 +979,7 @@ struct qmp_phy { | |||
897 | * @init_count: phy common block initialization count | 979 | * @init_count: phy common block initialization count |
898 | * @phy_initialized: indicate if PHY has been initialized | 980 | * @phy_initialized: indicate if PHY has been initialized |
899 | * @mode: current PHY mode | 981 | * @mode: current PHY mode |
982 | * @ufs_reset: optional UFS PHY reset handle | ||
900 | */ | 983 | */ |
901 | struct qcom_qmp { | 984 | struct qcom_qmp { |
902 | struct device *dev; | 985 | struct device *dev; |
@@ -914,6 +997,8 @@ struct qcom_qmp { | |||
914 | int init_count; | 997 | int init_count; |
915 | bool phy_initialized; | 998 | bool phy_initialized; |
916 | enum phy_mode mode; | 999 | enum phy_mode mode; |
1000 | |||
1001 | struct reset_control *ufs_reset; | ||
917 | }; | 1002 | }; |
918 | 1003 | ||
919 | static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) | 1004 | static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) |
@@ -1146,6 +1231,31 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { | |||
1146 | .no_pcs_sw_reset = true, | 1231 | .no_pcs_sw_reset = true, |
1147 | }; | 1232 | }; |
1148 | 1233 | ||
1234 | static const struct qmp_phy_cfg msm8998_pciephy_cfg = { | ||
1235 | .type = PHY_TYPE_PCIE, | ||
1236 | .nlanes = 1, | ||
1237 | |||
1238 | .serdes_tbl = msm8998_pcie_serdes_tbl, | ||
1239 | .serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), | ||
1240 | .tx_tbl = msm8998_pcie_tx_tbl, | ||
1241 | .tx_tbl_num = ARRAY_SIZE(msm8998_pcie_tx_tbl), | ||
1242 | .rx_tbl = msm8998_pcie_rx_tbl, | ||
1243 | .rx_tbl_num = ARRAY_SIZE(msm8998_pcie_rx_tbl), | ||
1244 | .pcs_tbl = msm8998_pcie_pcs_tbl, | ||
1245 | .pcs_tbl_num = ARRAY_SIZE(msm8998_pcie_pcs_tbl), | ||
1246 | .clk_list = msm8996_phy_clk_l, | ||
1247 | .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), | ||
1248 | .reset_list = ipq8074_pciephy_reset_l, | ||
1249 | .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), | ||
1250 | .vreg_list = qmp_phy_vreg_l, | ||
1251 | .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), | ||
1252 | .regs = pciephy_regs_layout, | ||
1253 | |||
1254 | .start_ctrl = SERDES_START | PCS_START, | ||
1255 | .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, | ||
1256 | .mask_com_pcs_ready = PCS_READY, | ||
1257 | }; | ||
1258 | |||
1149 | static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { | 1259 | static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { |
1150 | .type = PHY_TYPE_USB3, | 1260 | .type = PHY_TYPE_USB3, |
1151 | .nlanes = 1, | 1261 | .nlanes = 1, |
@@ -1314,6 +1424,7 @@ static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp) | |||
1314 | return 0; | 1424 | return 0; |
1315 | } | 1425 | } |
1316 | 1426 | ||
1427 | reset_control_assert(qmp->ufs_reset); | ||
1317 | if (cfg->has_phy_com_ctrl) { | 1428 | if (cfg->has_phy_com_ctrl) { |
1318 | qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], | 1429 | qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], |
1319 | SERDES_START | PCS_START); | 1430 | SERDES_START | PCS_START); |
@@ -1335,8 +1446,7 @@ static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp) | |||
1335 | return 0; | 1446 | return 0; |
1336 | } | 1447 | } |
1337 | 1448 | ||
1338 | /* PHY Initialization */ | 1449 | static int qcom_qmp_phy_enable(struct phy *phy) |
1339 | static int qcom_qmp_phy_init(struct phy *phy) | ||
1340 | { | 1450 | { |
1341 | struct qmp_phy *qphy = phy_get_drvdata(phy); | 1451 | struct qmp_phy *qphy = phy_get_drvdata(phy); |
1342 | struct qcom_qmp *qmp = qphy->qmp; | 1452 | struct qcom_qmp *qmp = qphy->qmp; |
@@ -1351,6 +1461,33 @@ static int qcom_qmp_phy_init(struct phy *phy) | |||
1351 | 1461 | ||
1352 | dev_vdbg(qmp->dev, "Initializing QMP phy\n"); | 1462 | dev_vdbg(qmp->dev, "Initializing QMP phy\n"); |
1353 | 1463 | ||
1464 | if (cfg->no_pcs_sw_reset) { | ||
1465 | /* | ||
1466 | * Get UFS reset, which is delayed until now to avoid a | ||
1467 | * circular dependency where UFS needs its PHY, but the PHY | ||
1468 | * needs this UFS reset. | ||
1469 | */ | ||
1470 | if (!qmp->ufs_reset) { | ||
1471 | qmp->ufs_reset = | ||
1472 | devm_reset_control_get_exclusive(qmp->dev, | ||
1473 | "ufsphy"); | ||
1474 | |||
1475 | if (IS_ERR(qmp->ufs_reset)) { | ||
1476 | ret = PTR_ERR(qmp->ufs_reset); | ||
1477 | dev_err(qmp->dev, | ||
1478 | "failed to get UFS reset: %d\n", | ||
1479 | ret); | ||
1480 | |||
1481 | qmp->ufs_reset = NULL; | ||
1482 | return ret; | ||
1483 | } | ||
1484 | } | ||
1485 | |||
1486 | ret = reset_control_assert(qmp->ufs_reset); | ||
1487 | if (ret) | ||
1488 | goto err_lane_rst; | ||
1489 | } | ||
1490 | |||
1354 | ret = qcom_qmp_phy_com_init(qphy); | 1491 | ret = qcom_qmp_phy_com_init(qphy); |
1355 | if (ret) | 1492 | if (ret) |
1356 | return ret; | 1493 | return ret; |
@@ -1383,14 +1520,9 @@ static int qcom_qmp_phy_init(struct phy *phy) | |||
1383 | cfg->rx_tbl, cfg->rx_tbl_num); | 1520 | cfg->rx_tbl, cfg->rx_tbl_num); |
1384 | 1521 | ||
1385 | qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); | 1522 | qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); |
1386 | 1523 | ret = reset_control_deassert(qmp->ufs_reset); | |
1387 | /* | 1524 | if (ret) |
1388 | * UFS PHY requires the deassert of software reset before serdes start. | 1525 | goto err_lane_rst; |
1389 | * For UFS PHYs that do not have software reset control bits, defer | ||
1390 | * starting serdes until the power on callback. | ||
1391 | */ | ||
1392 | if ((cfg->type == PHY_TYPE_UFS) && cfg->no_pcs_sw_reset) | ||
1393 | goto out; | ||
1394 | 1526 | ||
1395 | /* | 1527 | /* |
1396 | * Pull out PHY from POWER DOWN state. | 1528 | * Pull out PHY from POWER DOWN state. |
@@ -1403,7 +1535,9 @@ static int qcom_qmp_phy_init(struct phy *phy) | |||
1403 | usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); | 1535 | usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); |
1404 | 1536 | ||
1405 | /* Pull PHY out of reset state */ | 1537 | /* Pull PHY out of reset state */ |
1406 | qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); | 1538 | if (!cfg->no_pcs_sw_reset) |
1539 | qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); | ||
1540 | |||
1407 | if (cfg->has_phy_dp_com_ctrl) | 1541 | if (cfg->has_phy_dp_com_ctrl) |
1408 | qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); | 1542 | qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); |
1409 | 1543 | ||
@@ -1420,11 +1554,10 @@ static int qcom_qmp_phy_init(struct phy *phy) | |||
1420 | goto err_pcs_ready; | 1554 | goto err_pcs_ready; |
1421 | } | 1555 | } |
1422 | qmp->phy_initialized = true; | 1556 | qmp->phy_initialized = true; |
1423 | 1557 | return 0; | |
1424 | out: | ||
1425 | return ret; | ||
1426 | 1558 | ||
1427 | err_pcs_ready: | 1559 | err_pcs_ready: |
1560 | reset_control_assert(qmp->ufs_reset); | ||
1428 | clk_disable_unprepare(qphy->pipe_clk); | 1561 | clk_disable_unprepare(qphy->pipe_clk); |
1429 | err_clk_enable: | 1562 | err_clk_enable: |
1430 | if (cfg->has_lane_rst) | 1563 | if (cfg->has_lane_rst) |
@@ -1435,7 +1568,7 @@ err_lane_rst: | |||
1435 | return ret; | 1568 | return ret; |
1436 | } | 1569 | } |
1437 | 1570 | ||
1438 | static int qcom_qmp_phy_exit(struct phy *phy) | 1571 | static int qcom_qmp_phy_disable(struct phy *phy) |
1439 | { | 1572 | { |
1440 | struct qmp_phy *qphy = phy_get_drvdata(phy); | 1573 | struct qmp_phy *qphy = phy_get_drvdata(phy); |
1441 | struct qcom_qmp *qmp = qphy->qmp; | 1574 | struct qcom_qmp *qmp = qphy->qmp; |
@@ -1463,44 +1596,6 @@ static int qcom_qmp_phy_exit(struct phy *phy) | |||
1463 | return 0; | 1596 | return 0; |
1464 | } | 1597 | } |
1465 | 1598 | ||
1466 | static int qcom_qmp_phy_poweron(struct phy *phy) | ||
1467 | { | ||
1468 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
1469 | struct qcom_qmp *qmp = qphy->qmp; | ||
1470 | const struct qmp_phy_cfg *cfg = qmp->cfg; | ||
1471 | void __iomem *pcs = qphy->pcs; | ||
1472 | void __iomem *status; | ||
1473 | unsigned int mask, val; | ||
1474 | int ret = 0; | ||
1475 | |||
1476 | if (cfg->type != PHY_TYPE_UFS) | ||
1477 | return 0; | ||
1478 | |||
1479 | /* | ||
1480 | * For UFS PHY that has not software reset control, serdes start | ||
1481 | * should only happen when UFS driver explicitly calls phy_power_on | ||
1482 | * after it deasserts software reset. | ||
1483 | */ | ||
1484 | if (cfg->no_pcs_sw_reset && !qmp->phy_initialized && | ||
1485 | (qmp->init_count != 0)) { | ||
1486 | /* start SerDes and Phy-Coding-Sublayer */ | ||
1487 | qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); | ||
1488 | |||
1489 | status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; | ||
1490 | mask = cfg->mask_pcs_ready; | ||
1491 | |||
1492 | ret = readl_poll_timeout(status, val, !(val & mask), 1, | ||
1493 | PHY_INIT_COMPLETE_TIMEOUT); | ||
1494 | if (ret) { | ||
1495 | dev_err(qmp->dev, "phy initialization timed-out\n"); | ||
1496 | return ret; | ||
1497 | } | ||
1498 | qmp->phy_initialized = true; | ||
1499 | } | ||
1500 | |||
1501 | return ret; | ||
1502 | } | ||
1503 | |||
1504 | static int qcom_qmp_phy_set_mode(struct phy *phy, | 1599 | static int qcom_qmp_phy_set_mode(struct phy *phy, |
1505 | enum phy_mode mode, int submode) | 1600 | enum phy_mode mode, int submode) |
1506 | { | 1601 | { |
@@ -1750,9 +1845,15 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) | |||
1750 | } | 1845 | } |
1751 | 1846 | ||
1752 | static const struct phy_ops qcom_qmp_phy_gen_ops = { | 1847 | static const struct phy_ops qcom_qmp_phy_gen_ops = { |
1753 | .init = qcom_qmp_phy_init, | 1848 | .init = qcom_qmp_phy_enable, |
1754 | .exit = qcom_qmp_phy_exit, | 1849 | .exit = qcom_qmp_phy_disable, |
1755 | .power_on = qcom_qmp_phy_poweron, | 1850 | .set_mode = qcom_qmp_phy_set_mode, |
1851 | .owner = THIS_MODULE, | ||
1852 | }; | ||
1853 | |||
1854 | static const struct phy_ops qcom_qmp_ufs_ops = { | ||
1855 | .power_on = qcom_qmp_phy_enable, | ||
1856 | .power_off = qcom_qmp_phy_disable, | ||
1756 | .set_mode = qcom_qmp_phy_set_mode, | 1857 | .set_mode = qcom_qmp_phy_set_mode, |
1757 | .owner = THIS_MODULE, | 1858 | .owner = THIS_MODULE, |
1758 | }; | 1859 | }; |
@@ -1763,6 +1864,7 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) | |||
1763 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | 1864 | struct qcom_qmp *qmp = dev_get_drvdata(dev); |
1764 | struct phy *generic_phy; | 1865 | struct phy *generic_phy; |
1765 | struct qmp_phy *qphy; | 1866 | struct qmp_phy *qphy; |
1867 | const struct phy_ops *ops = &qcom_qmp_phy_gen_ops; | ||
1766 | char prop_name[MAX_PROP_NAME]; | 1868 | char prop_name[MAX_PROP_NAME]; |
1767 | int ret; | 1869 | int ret; |
1768 | 1870 | ||
@@ -1849,7 +1951,10 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) | |||
1849 | } | 1951 | } |
1850 | } | 1952 | } |
1851 | 1953 | ||
1852 | generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_gen_ops); | 1954 | if (qmp->cfg->type == PHY_TYPE_UFS) |
1955 | ops = &qcom_qmp_ufs_ops; | ||
1956 | |||
1957 | generic_phy = devm_phy_create(dev, np, ops); | ||
1853 | if (IS_ERR(generic_phy)) { | 1958 | if (IS_ERR(generic_phy)) { |
1854 | ret = PTR_ERR(generic_phy); | 1959 | ret = PTR_ERR(generic_phy); |
1855 | dev_err(dev, "failed to create qphy %d\n", ret); | 1960 | dev_err(dev, "failed to create qphy %d\n", ret); |
@@ -1873,6 +1978,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { | |||
1873 | .compatible = "qcom,msm8996-qmp-usb3-phy", | 1978 | .compatible = "qcom,msm8996-qmp-usb3-phy", |
1874 | .data = &msm8996_usb3phy_cfg, | 1979 | .data = &msm8996_usb3phy_cfg, |
1875 | }, { | 1980 | }, { |
1981 | .compatible = "qcom,msm8998-qmp-pcie-phy", | ||
1982 | .data = &msm8998_pciephy_cfg, | ||
1983 | }, { | ||
1876 | .compatible = "qcom,msm8998-qmp-ufs-phy", | 1984 | .compatible = "qcom,msm8998-qmp-ufs-phy", |
1877 | .data = &sdm845_ufsphy_cfg, | 1985 | .data = &sdm845_ufsphy_cfg, |
1878 | }, { | 1986 | }, { |