36
36
#define EXYNOS5_FSEL_26MHZ 0x6
37
37
#define EXYNOS5_FSEL_50MHZ 0x7
38
38
39
+ /* USB 3.2 DRD 4nm PHY link controller registers */
40
+ #define EXYNOS2200_DRD_CLKRST 0x0c
41
+ #define EXYNOS2200_CLKRST_LINK_PCLK_SEL BIT(1)
42
+
43
+ #define EXYNOS2200_DRD_UTMI 0x10
44
+ #define EXYNOS2200_UTMI_FORCE_VBUSVALID BIT(1)
45
+ #define EXYNOS2200_UTMI_FORCE_BVALID BIT(0)
46
+
47
+ #define EXYNOS2200_DRD_HSP_MISC 0x114
48
+ #define HSP_MISC_SET_REQ_IN2 BIT(4)
49
+ #define HSP_MISC_RES_TUNE GENMASK(1, 0)
50
+ #define RES_TUNE_PHY1_PHY2 0x1
51
+ #define RES_TUNE_PHY1 0x2
52
+ #define RES_TUNE_PHY2 0x3
53
+
39
54
/* Exynos5: USB 3.0 DRD PHY registers */
40
55
#define EXYNOS5_DRD_LINKSYSTEM 0x04
41
56
#define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27)
@@ -431,6 +446,7 @@ struct exynos5_usbdrd_phy_drvdata {
431
446
* @clks: clocks for register access
432
447
* @core_clks: core clocks for phy (ref, pipe3, utmi+, ITP, etc. as required)
433
448
* @drv_data: pointer to SoC level driver data structure
449
+ * @hs_phy: pointer to non-Samsung IP high-speed phy controller
434
450
* @phy_mutex: mutex protecting phy_init/exit & TCPC callbacks
435
451
* @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
436
452
* instances each with its 'phy' and 'phy_cfg'.
@@ -448,6 +464,7 @@ struct exynos5_usbdrd_phy {
448
464
struct clk_bulk_data * clks ;
449
465
struct clk_bulk_data * core_clks ;
450
466
const struct exynos5_usbdrd_phy_drvdata * drv_data ;
467
+ struct phy * hs_phy ;
451
468
struct mutex phy_mutex ;
452
469
struct phy_usb_instance {
453
470
struct phy * phy ;
@@ -1285,6 +1302,149 @@ static const struct phy_ops exynos7870_usbdrd_phy_ops = {
1285
1302
.owner = THIS_MODULE ,
1286
1303
};
1287
1304
1305
+ static void exynos2200_usbdrd_utmi_init (struct exynos5_usbdrd_phy * phy_drd )
1306
+ {
1307
+ /* Configure non-Samsung IP PHY, responsible for UTMI */
1308
+ phy_init (phy_drd -> hs_phy );
1309
+ }
1310
+
1311
+ static void exynos2200_usbdrd_link_init (struct exynos5_usbdrd_phy * phy_drd )
1312
+ {
1313
+ void __iomem * regs_base = phy_drd -> reg_phy ;
1314
+ u32 reg ;
1315
+
1316
+ /*
1317
+ * Disable HWACG (hardware auto clock gating control). This will force
1318
+ * QACTIVE signal in Q-Channel interface to HIGH level, to make sure
1319
+ * the PHY clock is not gated by the hardware.
1320
+ */
1321
+ reg = readl (regs_base + EXYNOS850_DRD_LINKCTRL );
1322
+ reg |= LINKCTRL_FORCE_QACT ;
1323
+ writel (reg , regs_base + EXYNOS850_DRD_LINKCTRL );
1324
+
1325
+ /* De-assert link reset */
1326
+ reg = readl (regs_base + EXYNOS2200_DRD_CLKRST );
1327
+ reg &= ~CLKRST_LINK_SW_RST ;
1328
+ writel (reg , regs_base + EXYNOS2200_DRD_CLKRST );
1329
+
1330
+ /* Set link VBUS Valid */
1331
+ reg = readl (regs_base + EXYNOS2200_DRD_UTMI );
1332
+ reg |= EXYNOS2200_UTMI_FORCE_BVALID | EXYNOS2200_UTMI_FORCE_VBUSVALID ;
1333
+ writel (reg , regs_base + EXYNOS2200_DRD_UTMI );
1334
+ }
1335
+
1336
+ static void
1337
+ exynos2200_usbdrd_link_attach_detach_pipe3_phy (struct phy_usb_instance * inst )
1338
+ {
1339
+ struct exynos5_usbdrd_phy * phy_drd = to_usbdrd_phy (inst );
1340
+ void __iomem * regs_base = phy_drd -> reg_phy ;
1341
+ u32 reg ;
1342
+
1343
+ reg = readl (regs_base + EXYNOS850_DRD_LINKCTRL );
1344
+ if (inst -> phy_cfg -> id == EXYNOS5_DRDPHY_UTMI ) {
1345
+ /* force pipe3 signal for link */
1346
+ reg &= ~LINKCTRL_FORCE_PHYSTATUS ;
1347
+ reg |= LINKCTRL_FORCE_PIPE_EN | LINKCTRL_FORCE_RXELECIDLE ;
1348
+ } else {
1349
+ /* disable forcing pipe interface */
1350
+ reg &= ~LINKCTRL_FORCE_PIPE_EN ;
1351
+ }
1352
+ writel (reg , regs_base + EXYNOS850_DRD_LINKCTRL );
1353
+
1354
+ reg = readl (regs_base + EXYNOS2200_DRD_HSP_MISC );
1355
+ if (inst -> phy_cfg -> id == EXYNOS5_DRDPHY_UTMI ) {
1356
+ /* calibrate only eUSB phy */
1357
+ reg |= FIELD_PREP (HSP_MISC_RES_TUNE , RES_TUNE_PHY1 );
1358
+ reg |= HSP_MISC_SET_REQ_IN2 ;
1359
+ } else {
1360
+ /* calibrate for dual phy */
1361
+ reg |= FIELD_PREP (HSP_MISC_RES_TUNE , RES_TUNE_PHY1_PHY2 );
1362
+ reg &= ~HSP_MISC_SET_REQ_IN2 ;
1363
+ }
1364
+ writel (reg , regs_base + EXYNOS2200_DRD_HSP_MISC );
1365
+
1366
+ reg = readl (regs_base + EXYNOS2200_DRD_CLKRST );
1367
+ if (inst -> phy_cfg -> id == EXYNOS5_DRDPHY_UTMI )
1368
+ reg &= ~EXYNOS2200_CLKRST_LINK_PCLK_SEL ;
1369
+ else
1370
+ reg |= EXYNOS2200_CLKRST_LINK_PCLK_SEL ;
1371
+
1372
+ writel (reg , regs_base + EXYNOS2200_DRD_CLKRST );
1373
+ }
1374
+
1375
+ static int exynos2200_usbdrd_phy_init (struct phy * phy )
1376
+ {
1377
+ struct phy_usb_instance * inst = phy_get_drvdata (phy );
1378
+ struct exynos5_usbdrd_phy * phy_drd = to_usbdrd_phy (inst );
1379
+ int ret ;
1380
+
1381
+ if (inst -> phy_cfg -> id == EXYNOS5_DRDPHY_UTMI ) {
1382
+ /* Power-on PHY ... */
1383
+ ret = regulator_bulk_enable (phy_drd -> drv_data -> n_regulators ,
1384
+ phy_drd -> regulators );
1385
+ if (ret ) {
1386
+ dev_err (phy_drd -> dev ,
1387
+ "Failed to enable PHY regulator(s)\n" );
1388
+ return ret ;
1389
+ }
1390
+ }
1391
+ /*
1392
+ * ... and ungate power via PMU. Without this here, we get an SError
1393
+ * trying to access PMA registers
1394
+ */
1395
+ exynos5_usbdrd_phy_isol (inst , false);
1396
+
1397
+ ret = clk_bulk_prepare_enable (phy_drd -> drv_data -> n_clks , phy_drd -> clks );
1398
+ if (ret )
1399
+ return ret ;
1400
+
1401
+ /* Set up the link controller */
1402
+ exynos2200_usbdrd_link_init (phy_drd );
1403
+
1404
+ /* UTMI or PIPE3 link preparation */
1405
+ exynos2200_usbdrd_link_attach_detach_pipe3_phy (inst );
1406
+
1407
+ /* UTMI or PIPE3 specific init */
1408
+ inst -> phy_cfg -> phy_init (phy_drd );
1409
+
1410
+ clk_bulk_disable_unprepare (phy_drd -> drv_data -> n_clks , phy_drd -> clks );
1411
+
1412
+ return 0 ;
1413
+ }
1414
+
1415
+ static int exynos2200_usbdrd_phy_exit (struct phy * phy )
1416
+ {
1417
+ struct phy_usb_instance * inst = phy_get_drvdata (phy );
1418
+ struct exynos5_usbdrd_phy * phy_drd = to_usbdrd_phy (inst );
1419
+ void __iomem * regs_base = phy_drd -> reg_phy ;
1420
+ u32 reg ;
1421
+ int ret ;
1422
+
1423
+ ret = clk_bulk_prepare_enable (phy_drd -> drv_data -> n_clks , phy_drd -> clks );
1424
+ if (ret )
1425
+ return ret ;
1426
+
1427
+ reg = readl (regs_base + EXYNOS2200_DRD_UTMI );
1428
+ reg &= ~(EXYNOS2200_UTMI_FORCE_BVALID | EXYNOS2200_UTMI_FORCE_VBUSVALID );
1429
+ writel (reg , regs_base + EXYNOS2200_DRD_UTMI );
1430
+
1431
+ reg = readl (regs_base + EXYNOS2200_DRD_CLKRST );
1432
+ reg |= CLKRST_LINK_SW_RST ;
1433
+ writel (reg , regs_base + EXYNOS2200_DRD_CLKRST );
1434
+
1435
+ clk_bulk_disable_unprepare (phy_drd -> drv_data -> n_clks , phy_drd -> clks );
1436
+
1437
+ exynos5_usbdrd_phy_isol (inst , true);
1438
+ return regulator_bulk_disable (phy_drd -> drv_data -> n_regulators ,
1439
+ phy_drd -> regulators );
1440
+ }
1441
+
1442
+ static const struct phy_ops exynos2200_usbdrd_phy_ops = {
1443
+ .init = exynos2200_usbdrd_phy_init ,
1444
+ .exit = exynos2200_usbdrd_phy_exit ,
1445
+ .owner = THIS_MODULE ,
1446
+ };
1447
+
1288
1448
static void
1289
1449
exynos5_usbdrd_usb_v3p1_pipe_override (struct exynos5_usbdrd_phy * phy_drd )
1290
1450
{
@@ -1594,27 +1754,37 @@ static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
1594
1754
return dev_err_probe (phy_drd -> dev , ret ,
1595
1755
"failed to get phy core clock(s)\n" );
1596
1756
1597
- ref_clk = NULL ;
1598
- for (int i = 0 ; i < phy_drd -> drv_data -> n_core_clks ; ++ i ) {
1599
- if (!strcmp (phy_drd -> core_clks [i ].id , "ref" )) {
1600
- ref_clk = phy_drd -> core_clks [i ].clk ;
1601
- break ;
1757
+ if (phy_drd -> drv_data -> n_core_clks ) {
1758
+ ref_clk = NULL ;
1759
+ for (int i = 0 ; i < phy_drd -> drv_data -> n_core_clks ; ++ i ) {
1760
+ if (!strcmp (phy_drd -> core_clks [i ].id , "ref" )) {
1761
+ ref_clk = phy_drd -> core_clks [i ].clk ;
1762
+ break ;
1763
+ }
1602
1764
}
1603
- }
1604
- if (!ref_clk )
1605
- return dev_err_probe (phy_drd -> dev , - ENODEV ,
1606
- "failed to find phy reference clock\n" );
1765
+ if (!ref_clk )
1766
+ return dev_err_probe (phy_drd -> dev , - ENODEV ,
1767
+ "failed to find phy reference clock\n" );
1607
1768
1608
- ref_rate = clk_get_rate (ref_clk );
1609
- ret = exynos5_rate_to_clk (ref_rate , & phy_drd -> extrefclk );
1610
- if (ret )
1611
- return dev_err_probe (phy_drd -> dev , ret ,
1612
- "clock rate (%ld) not supported\n" ,
1613
- ref_rate );
1769
+ ref_rate = clk_get_rate (ref_clk );
1770
+ ret = exynos5_rate_to_clk (ref_rate , & phy_drd -> extrefclk );
1771
+ if (ret )
1772
+ return dev_err_probe (phy_drd -> dev , ret ,
1773
+ "clock rate (%ld) not supported\n" ,
1774
+ ref_rate );
1775
+ }
1614
1776
1615
1777
return 0 ;
1616
1778
}
1617
1779
1780
+ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos2200 [] = {
1781
+ {
1782
+ .id = EXYNOS5_DRDPHY_UTMI ,
1783
+ .phy_isol = exynos5_usbdrd_phy_isol ,
1784
+ .phy_init = exynos2200_usbdrd_utmi_init ,
1785
+ },
1786
+ };
1787
+
1618
1788
static int exynos5_usbdrd_orien_sw_set (struct typec_switch_dev * sw ,
1619
1789
enum typec_orientation orientation )
1620
1790
{
@@ -1767,6 +1937,19 @@ static const char * const exynos5_regulator_names[] = {
1767
1937
"vbus" , "vbus-boost" ,
1768
1938
};
1769
1939
1940
+ static const struct exynos5_usbdrd_phy_drvdata exynos2200_usb32drd_phy = {
1941
+ .phy_cfg = phy_cfg_exynos2200 ,
1942
+ .phy_ops = & exynos2200_usbdrd_phy_ops ,
1943
+ .pmu_offset_usbdrd0_phy = EXYNOS2200_PHY_CTRL_USB20 ,
1944
+ .clk_names = exynos5_clk_names ,
1945
+ .n_clks = ARRAY_SIZE (exynos5_clk_names ),
1946
+ /* clocks and regulators are specific to the underlying PHY blocks */
1947
+ .core_clk_names = NULL ,
1948
+ .n_core_clks = 0 ,
1949
+ .regulator_names = NULL ,
1950
+ .n_regulators = 0 ,
1951
+ };
1952
+
1770
1953
static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
1771
1954
.phy_cfg = phy_cfg_exynos5 ,
1772
1955
.phy_ops = & exynos5_usbdrd_phy_ops ,
@@ -2024,6 +2207,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
2024
2207
{
2025
2208
.compatible = "google,gs101-usb31drd-phy" ,
2026
2209
.data = & gs101_usbd31rd_phy
2210
+ }, {
2211
+ .compatible = "samsung,exynos2200-usb32drd-phy" ,
2212
+ .data = & exynos2200_usb32drd_phy ,
2027
2213
}, {
2028
2214
.compatible = "samsung,exynos5250-usbdrd-phy" ,
2029
2215
.data = & exynos5250_usbdrd_phy
@@ -2099,6 +2285,17 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
2099
2285
return PTR_ERR (phy_drd -> reg_phy );
2100
2286
}
2101
2287
2288
+ /*
2289
+ * USB32DRD 4nm controller implements Synopsys eUSB2.0 PHY
2290
+ * and Synopsys SS/USBDP COMBOPHY, managed by external code.
2291
+ */
2292
+ if (of_property_present (dev -> of_node , "phy-names" )) {
2293
+ phy_drd -> hs_phy = devm_of_phy_get (dev , dev -> of_node , "hs" );
2294
+ if (IS_ERR (phy_drd -> hs_phy ))
2295
+ return dev_err_probe (dev , PTR_ERR (phy_drd -> hs_phy ),
2296
+ "failed to get hs_phy\n" );
2297
+ }
2298
+
2102
2299
ret = exynos5_usbdrd_phy_clk_handle (phy_drd );
2103
2300
if (ret )
2104
2301
return ret ;
0 commit comments