20
20
#include <linux/reset.h>
21
21
#include <linux/slab.h>
22
22
23
- #include <dt-bindings/phy/phy.h>
23
+ #include <dt-bindings/phy/phy-qcom-qmp .h>
24
24
25
25
#include "phy-qcom-qmp.h"
26
26
@@ -798,7 +798,23 @@ static const u8 qmp_dp_v5_voltage_swing_hbr_rbr[4][4] = {
798
798
799
799
struct qmp_combo ;
800
800
801
+ struct qmp_combo_offsets {
802
+ u16 com ;
803
+ u16 txa ;
804
+ u16 rxa ;
805
+ u16 txb ;
806
+ u16 rxb ;
807
+ u16 usb3_serdes ;
808
+ u16 usb3_pcs_misc ;
809
+ u16 usb3_pcs ;
810
+ u16 usb3_pcs_usb ;
811
+ u16 dp_serdes ;
812
+ u16 dp_dp_phy ;
813
+ };
814
+
801
815
struct qmp_phy_cfg {
816
+ const struct qmp_combo_offsets * offsets ;
817
+
802
818
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
803
819
const struct qmp_phy_init_tbl * serdes_tbl ;
804
820
int serdes_tbl_num ;
@@ -959,6 +975,20 @@ static const char * const sc7180_usb3phy_reset_l[] = {
959
975
"phy" ,
960
976
};
961
977
978
+ static const struct qmp_combo_offsets qmp_combo_offsets_v5 = {
979
+ .com = 0x0000 ,
980
+ .txa = 0x0400 ,
981
+ .rxa = 0x0600 ,
982
+ .txb = 0x0a00 ,
983
+ .rxb = 0x0c00 ,
984
+ .usb3_serdes = 0x1000 ,
985
+ .usb3_pcs_misc = 0x1200 ,
986
+ .usb3_pcs = 0x1400 ,
987
+ .usb3_pcs_usb = 0x1700 ,
988
+ .dp_serdes = 0x2000 ,
989
+ .dp_dp_phy = 0x2200 ,
990
+ };
991
+
962
992
static const struct qmp_phy_cfg sc7180_usb3dpphy_cfg = {
963
993
.serdes_tbl = qmp_v3_usb3_serdes_tbl ,
964
994
.serdes_tbl_num = ARRAY_SIZE (qmp_v3_usb3_serdes_tbl ),
@@ -1098,6 +1128,8 @@ static const struct qmp_phy_cfg sc8180x_usb3dpphy_cfg = {
1098
1128
};
1099
1129
1100
1130
static const struct qmp_phy_cfg sc8280xp_usb43dpphy_cfg = {
1131
+ .offsets = & qmp_combo_offsets_v5 ,
1132
+
1101
1133
.serdes_tbl = sc8280xp_usb43dp_serdes_tbl ,
1102
1134
.serdes_tbl_num = ARRAY_SIZE (sc8280xp_usb43dp_serdes_tbl ),
1103
1135
.tx_tbl = sc8280xp_usb43dp_tx_tbl ,
@@ -1138,7 +1170,6 @@ static const struct qmp_phy_cfg sc8280xp_usb43dpphy_cfg = {
1138
1170
.vreg_list = qmp_phy_vreg_l ,
1139
1171
.num_vregs = ARRAY_SIZE (qmp_phy_vreg_l ),
1140
1172
.regs = qmp_v4_usb3phy_regs_layout ,
1141
- .pcs_usb_offset = 0x300 ,
1142
1173
};
1143
1174
1144
1175
static const struct qmp_phy_cfg sm8250_usb3dpphy_cfg = {
@@ -2421,6 +2452,22 @@ static int phy_dp_clks_register(struct qmp_combo *qmp, struct device_node *np)
2421
2452
return 0 ;
2422
2453
}
2423
2454
2455
+ static struct clk_hw * qmp_combo_clk_hw_get (struct of_phandle_args * clkspec , void * data )
2456
+ {
2457
+ struct qmp_combo * qmp = data ;
2458
+
2459
+ switch (clkspec -> args [0 ]) {
2460
+ case QMP_USB43DP_USB3_PIPE_CLK :
2461
+ return & qmp -> pipe_clk_fixed .hw ;
2462
+ case QMP_USB43DP_DP_LINK_CLK :
2463
+ return & qmp -> dp_link_hw ;
2464
+ case QMP_USB43DP_DP_VCO_DIV_CLK :
2465
+ return & qmp -> dp_pixel_hw ;
2466
+ }
2467
+
2468
+ return ERR_PTR (- EINVAL );
2469
+ }
2470
+
2424
2471
static int qmp_combo_register_clocks (struct qmp_combo * qmp , struct device_node * usb_np ,
2425
2472
struct device_node * dp_np )
2426
2473
{
@@ -2434,6 +2481,15 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node *
2434
2481
if (ret )
2435
2482
return ret ;
2436
2483
2484
+ /*
2485
+ * Register a single provider for bindings without child nodes.
2486
+ */
2487
+ if (usb_np == qmp -> dev -> of_node )
2488
+ return devm_of_clk_add_hw_provider (qmp -> dev , qmp_combo_clk_hw_get , qmp );
2489
+
2490
+ /*
2491
+ * Register multiple providers for legacy bindings with child nodes.
2492
+ */
2437
2493
ret = of_clk_add_hw_provider (usb_np , of_clk_hw_simple_get ,
2438
2494
& qmp -> pipe_clk_fixed .hw );
2439
2495
if (ret )
@@ -2558,6 +2614,63 @@ static int qmp_combo_parse_dt_legacy(struct qmp_combo *qmp, struct device_node *
2558
2614
return 0 ;
2559
2615
}
2560
2616
2617
+ static int qmp_combo_parse_dt (struct qmp_combo * qmp )
2618
+ {
2619
+ struct platform_device * pdev = to_platform_device (qmp -> dev );
2620
+ const struct qmp_phy_cfg * cfg = qmp -> cfg ;
2621
+ const struct qmp_combo_offsets * offs = cfg -> offsets ;
2622
+ struct device * dev = qmp -> dev ;
2623
+ void __iomem * base ;
2624
+
2625
+ if (!offs )
2626
+ return - EINVAL ;
2627
+
2628
+ base = devm_platform_ioremap_resource (pdev , 0 );
2629
+ if (IS_ERR (base ))
2630
+ return PTR_ERR (base );
2631
+
2632
+ qmp -> com = base + offs -> com ;
2633
+ qmp -> tx = base + offs -> txa ;
2634
+ qmp -> rx = base + offs -> rxa ;
2635
+ qmp -> tx2 = base + offs -> txb ;
2636
+ qmp -> rx2 = base + offs -> rxb ;
2637
+
2638
+ qmp -> serdes = base + offs -> usb3_serdes ;
2639
+ qmp -> pcs_misc = base + offs -> usb3_pcs_misc ;
2640
+ qmp -> pcs = base + offs -> usb3_pcs ;
2641
+ qmp -> pcs_usb = base + offs -> usb3_pcs_usb ;
2642
+
2643
+ qmp -> dp_serdes = base + offs -> dp_serdes ;
2644
+ qmp -> dp_tx = base + offs -> txa ;
2645
+ qmp -> dp_tx2 = base + offs -> txb ;
2646
+ qmp -> dp_dp_phy = base + offs -> dp_dp_phy ;
2647
+
2648
+ qmp -> pipe_clk = devm_clk_get (dev , "usb3_pipe" );
2649
+ if (IS_ERR (qmp -> pipe_clk )) {
2650
+ return dev_err_probe (dev , PTR_ERR (qmp -> pipe_clk ),
2651
+ "failed to get usb3_pipe clock\n" );
2652
+ }
2653
+
2654
+ return 0 ;
2655
+ }
2656
+
2657
+ static struct phy * qmp_combo_phy_xlate (struct device * dev , struct of_phandle_args * args )
2658
+ {
2659
+ struct qmp_combo * qmp = dev_get_drvdata (dev );
2660
+
2661
+ if (args -> args_count == 0 )
2662
+ return ERR_PTR (- EINVAL );
2663
+
2664
+ switch (args -> args [0 ]) {
2665
+ case QMP_USB43DP_USB3_PHY :
2666
+ return qmp -> usb_phy ;
2667
+ case QMP_USB43DP_DP_PHY :
2668
+ return qmp -> dp_phy ;
2669
+ }
2670
+
2671
+ return ERR_PTR (- EINVAL );
2672
+ }
2673
+
2561
2674
static int qmp_combo_probe (struct platform_device * pdev )
2562
2675
{
2563
2676
struct qmp_combo * qmp ;
@@ -2590,17 +2703,22 @@ static int qmp_combo_probe(struct platform_device *pdev)
2590
2703
if (ret )
2591
2704
return ret ;
2592
2705
2706
+ /* Check for legacy binding with child nodes. */
2593
2707
usb_np = of_get_child_by_name (dev -> of_node , "usb3-phy" );
2594
- if (!usb_np )
2595
- return - EINVAL ;
2708
+ if (usb_np ) {
2709
+ dp_np = of_get_child_by_name (dev -> of_node , "dp-phy" );
2710
+ if (!dp_np ) {
2711
+ of_node_put (usb_np );
2712
+ return - EINVAL ;
2713
+ }
2596
2714
2597
- dp_np = of_get_child_by_name (dev -> of_node , "dp-phy" );
2598
- if (!dp_np ) {
2599
- of_node_put (usb_np );
2600
- return - EINVAL ;
2601
- }
2715
+ ret = qmp_combo_parse_dt_legacy (qmp , usb_np , dp_np );
2716
+ } else {
2717
+ usb_np = of_node_get (dev -> of_node );
2718
+ dp_np = of_node_get (dev -> of_node );
2602
2719
2603
- ret = qmp_combo_parse_dt_legacy (qmp , usb_np , dp_np );
2720
+ ret = qmp_combo_parse_dt (qmp );
2721
+ }
2604
2722
if (ret )
2605
2723
goto err_node_put ;
2606
2724
@@ -2636,7 +2754,12 @@ static int qmp_combo_probe(struct platform_device *pdev)
2636
2754
2637
2755
phy_set_drvdata (qmp -> dp_phy , qmp );
2638
2756
2639
- phy_provider = devm_of_phy_provider_register (dev , of_phy_simple_xlate );
2757
+ dev_set_drvdata (dev , qmp );
2758
+
2759
+ if (usb_np == dev -> of_node )
2760
+ phy_provider = devm_of_phy_provider_register (dev , qmp_combo_phy_xlate );
2761
+ else
2762
+ phy_provider = devm_of_phy_provider_register (dev , of_phy_simple_xlate );
2640
2763
2641
2764
of_node_put (usb_np );
2642
2765
of_node_put (dp_np );
0 commit comments