Skip to content

Commit 83a0bbe

Browse files
jhovoldvinodkoul
authored andcommitted
phy: qcom-qmp-combo: add support for updated sc8280xp binding
Add support for the new SC8280XP binding. Note that the binding does not try to describe every register subregion and instead the driver holds the corresponding offsets. Also note that (possibly) unlike on earlier platforms, the TX registers are used by both the USB and DP implementation. Reviewed-by: Dmitry Baryshkov <[email protected]> Signed-off-by: Johan Hovold <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 133836a commit 83a0bbe

File tree

1 file changed

+134
-11
lines changed

1 file changed

+134
-11
lines changed

drivers/phy/qualcomm/phy-qcom-qmp-combo.c

Lines changed: 134 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <linux/reset.h>
2121
#include <linux/slab.h>
2222

23-
#include <dt-bindings/phy/phy.h>
23+
#include <dt-bindings/phy/phy-qcom-qmp.h>
2424

2525
#include "phy-qcom-qmp.h"
2626

@@ -798,7 +798,23 @@ static const u8 qmp_dp_v5_voltage_swing_hbr_rbr[4][4] = {
798798

799799
struct qmp_combo;
800800

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+
801815
struct qmp_phy_cfg {
816+
const struct qmp_combo_offsets *offsets;
817+
802818
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
803819
const struct qmp_phy_init_tbl *serdes_tbl;
804820
int serdes_tbl_num;
@@ -959,6 +975,20 @@ static const char * const sc7180_usb3phy_reset_l[] = {
959975
"phy",
960976
};
961977

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+
962992
static const struct qmp_phy_cfg sc7180_usb3dpphy_cfg = {
963993
.serdes_tbl = qmp_v3_usb3_serdes_tbl,
964994
.serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
@@ -1098,6 +1128,8 @@ static const struct qmp_phy_cfg sc8180x_usb3dpphy_cfg = {
10981128
};
10991129

11001130
static const struct qmp_phy_cfg sc8280xp_usb43dpphy_cfg = {
1131+
.offsets = &qmp_combo_offsets_v5,
1132+
11011133
.serdes_tbl = sc8280xp_usb43dp_serdes_tbl,
11021134
.serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb43dp_serdes_tbl),
11031135
.tx_tbl = sc8280xp_usb43dp_tx_tbl,
@@ -1138,7 +1170,6 @@ static const struct qmp_phy_cfg sc8280xp_usb43dpphy_cfg = {
11381170
.vreg_list = qmp_phy_vreg_l,
11391171
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
11401172
.regs = qmp_v4_usb3phy_regs_layout,
1141-
.pcs_usb_offset = 0x300,
11421173
};
11431174

11441175
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)
24212452
return 0;
24222453
}
24232454

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+
24242471
static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node *usb_np,
24252472
struct device_node *dp_np)
24262473
{
@@ -2434,6 +2481,15 @@ static int qmp_combo_register_clocks(struct qmp_combo *qmp, struct device_node *
24342481
if (ret)
24352482
return ret;
24362483

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+
*/
24372493
ret = of_clk_add_hw_provider(usb_np, of_clk_hw_simple_get,
24382494
&qmp->pipe_clk_fixed.hw);
24392495
if (ret)
@@ -2558,6 +2614,63 @@ static int qmp_combo_parse_dt_legacy(struct qmp_combo *qmp, struct device_node *
25582614
return 0;
25592615
}
25602616

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+
25612674
static int qmp_combo_probe(struct platform_device *pdev)
25622675
{
25632676
struct qmp_combo *qmp;
@@ -2590,17 +2703,22 @@ static int qmp_combo_probe(struct platform_device *pdev)
25902703
if (ret)
25912704
return ret;
25922705

2706+
/* Check for legacy binding with child nodes. */
25932707
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+
}
25962714

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);
26022719

2603-
ret = qmp_combo_parse_dt_legacy(qmp, usb_np, dp_np);
2720+
ret = qmp_combo_parse_dt(qmp);
2721+
}
26042722
if (ret)
26052723
goto err_node_put;
26062724

@@ -2636,7 +2754,12 @@ static int qmp_combo_probe(struct platform_device *pdev)
26362754

26372755
phy_set_drvdata(qmp->dp_phy, qmp);
26382756

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);
26402763

26412764
of_node_put(usb_np);
26422765
of_node_put(dp_np);

0 commit comments

Comments
 (0)