On 16/11/2022 14:01, Abel Vesa wrote:
> Add the SM8550 both g4 and g3 configurations. In addition, there is a
> new "lane shared" table that needs to be configured for g4, along with
> the No-CSR list of resets.
>
> Co-developed-by: Neil Armstrong <neil.armstrong@linaro.org>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 354 +++++++++++++++++++++++
> 1 file changed, 354 insertions(+)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
> index 47cccc4b35b2..87c7c20dfc8d 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
[skipped tables]
> @@ -1473,6 +1701,8 @@ struct qmp_pcie_offsets {
> struct qmp_phy_cfg_tbls {
> const struct qmp_phy_init_tbl *serdes;
> int serdes_num;
> + const struct qmp_phy_init_tbl *ln_shrd_serdes;
> + int ln_shrd_serdes_num;
> const struct qmp_phy_init_tbl *tx;
> int tx_num;
> const struct qmp_phy_init_tbl *rx;
> @@ -1510,6 +1740,9 @@ struct qmp_phy_cfg {
> /* resets to be requested */
> const char * const *reset_list;
> int num_resets;
> + /* no CSR resets to be requested */
> + const char * const *nocsr_reset_list;
> + int num_nocsr_resets;
Is there any difference between 'no CSR' resets and the plain ones? Can
we handle them in a single array instead?
> /* regulators to be requested */
> const char * const *vreg_list;
> int num_vregs;
> @@ -1523,6 +1756,9 @@ struct qmp_phy_cfg {
>
> bool skip_start_delay;
>
> + /* true, if PHY has lane shared serdes table */
> + bool has_ln_shrd_serdes_tbl;
s/shrd/shared/g ? I think it's easier to read and to understand.
> +
> /* QMP PHY pipe clock interface rate */
> unsigned long pipe_clock_rate;
> };
> @@ -1534,6 +1770,7 @@ struct qmp_pcie {
> bool tcsr_4ln_config;
>
> void __iomem *serdes;
> + void __iomem *ln_shrd_serdes;
> void __iomem *pcs;
> void __iomem *pcs_misc;
> void __iomem *tx;
> @@ -1548,6 +1785,7 @@ struct qmp_pcie {
> int num_pipe_clks;
>
> struct reset_control_bulk_data *resets;
> + struct reset_control_bulk_data *nocsr_resets;
> struct regulator_bulk_data *vregs;
>
> struct phy *phy;
> @@ -1595,11 +1833,19 @@ static const char * const sdm845_pciephy_clk_l[] = {
> "aux", "cfg_ahb", "ref", "refgen",
> };
>
> +static const char * const sm8550_pciephy_clk_l[] = {
> + "aux", "aux_phy", "cfg_ahb", "ref", "refgen",
> +};
> +
> /* list of regulators */
> static const char * const qmp_phy_vreg_l[] = {
> "vdda-phy", "vdda-pll",
> };
>
> +static const char * const sm8550_qmp_phy_vreg_l[] = {
> + "vdda-phy", "vdda-pll", "vdda-qref",
> +};
> +
> /* list of resets */
> static const char * const ipq8074_pciephy_reset_l[] = {
> "phy", "common",
> @@ -1609,6 +1855,10 @@ static const char * const sdm845_pciephy_reset_l[] = {
> "phy",
> };
>
> +static const char * const sm8550_pciephy_nocsr_reset_l[] = {
> + "pcie_1_nocsr_com_phy_reset",
> +};
> +
> static const struct qmp_pcie_offsets qmp_pcie_offsets_v5 = {
> .serdes = 0,
> .pcs = 0x0200,
> @@ -2084,6 +2334,65 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = {
> .phy_status = PHYSTATUS_4_20,
> };
>
> +static const struct qmp_phy_cfg sm8550_qmp_gen3x2_pciephy_cfg = {
> + .lanes = 2,
> +
> + .tbls = {
> + .serdes = sm8550_qmp_gen3x2_pcie_serdes_tbl,
> + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl),
> + .tx = sm8550_qmp_gen3x2_pcie_tx_tbl,
> + .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl),
> + .rx = sm8550_qmp_gen3x2_pcie_rx_tbl,
> + .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl),
> + .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl,
> + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl),
> + .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl,
> + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl),
> + },
> + .clk_list = sdm845_pciephy_clk_l,
> + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
> + .reset_list = sdm845_pciephy_reset_l,
> + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
> + .vreg_list = qmp_phy_vreg_l,
> + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
> + .regs = sm8250_pcie_regs_layout,
> +
> + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
> + .phy_status = PHYSTATUS,
> +};
> +
> +static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = {
> + .lanes = 2,
> +
> + .tbls = {
> + .serdes = sm8550_qmp_gen4x2_pcie_serdes_tbl,
> + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_serdes_tbl),
> + .ln_shrd_serdes = sm8550_qmp_gen4x2_pcie_serdes_ln_shrd_tbl,
> + .ln_shrd_serdes_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_serdes_ln_shrd_tbl),
> + .tx = sm8550_qmp_gen4x2_pcie_tx_tbl,
> + .tx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_tx_tbl),
> + .rx = sm8550_qmp_gen4x2_pcie_rx_tbl,
> + .rx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_rx_tbl),
> + .pcs = sm8550_qmp_gen4x2_pcie_pcs_tbl,
> + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_tbl),
> + .pcs_misc = sm8550_qmp_gen4x2_pcie_pcs_misc_tbl,
> + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_misc_tbl),
> + },
> + .clk_list = sm8550_pciephy_clk_l,
> + .num_clks = ARRAY_SIZE(sm8550_pciephy_clk_l),
> + .reset_list = sdm845_pciephy_reset_l,
> + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
> + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
> + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
> + .vreg_list = sm8550_qmp_phy_vreg_l,
> + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
> + .regs = sm8250_pcie_regs_layout,
> +
> + .has_ln_shrd_serdes_tbl = true,
> + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
> + .phy_status = PHYSTATUS_4_20,
> +};
> +
> static void qmp_pcie_configure_lane(void __iomem *base,
> const struct qmp_phy_init_tbl tbl[],
> int num,
> @@ -2132,6 +2441,7 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
> {
> const struct qmp_phy_cfg *cfg = qmp->cfg;
> void __iomem *serdes = qmp->serdes;
> + void __iomem *ln_shrd_serdes = qmp->ln_shrd_serdes;
> void __iomem *tx = qmp->tx;
> void __iomem *rx = qmp->rx;
> void __iomem *tx2 = qmp->tx2;
> @@ -2159,6 +2469,10 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
> qmp_pcie_configure(serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num);
> qmp_pcie_init_port_b(qmp, tbls);
> }
> +
> + if (cfg->has_ln_shrd_serdes_tbl)
> + qmp_pcie_configure(ln_shrd_serdes, tbls->ln_shrd_serdes,
> + tbls->ln_shrd_serdes_num);
> }
>
> static int qmp_pcie_init(struct phy *phy)
> @@ -2179,6 +2493,14 @@ static int qmp_pcie_init(struct phy *phy)
> goto err_disable_regulators;
> }
>
> + if (qmp->nocsr_resets) {
> + ret = reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_resets);
> + if (ret) {
> + dev_err(qmp->dev, "no-csr reset assert failed\n");
> + goto err_disable_regulators;
> + }
> + }
> +
> usleep_range(200, 300);
>
> ret = reset_control_bulk_deassert(cfg->num_resets, qmp->resets);
> @@ -2240,6 +2562,14 @@ static int qmp_pcie_power_on(struct phy *phy)
> if (ret)
> return ret;
>
> + if (qmp->nocsr_resets) {
> + ret = reset_control_bulk_deassert(cfg->num_nocsr_resets, qmp->nocsr_resets);
> + if (ret) {
> + dev_err(qmp->dev, "no-csr reset deassert failed\n");
> + goto err_disable_pipe_clk;
> + }
> + }
> +
> /* Pull PHY out of reset state */
> qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
>
> @@ -2373,6 +2703,21 @@ static int qmp_pcie_reset_init(struct qmp_pcie *qmp)
> if (ret)
> return dev_err_probe(dev, ret, "failed to get resets\n");
>
> + if (cfg->nocsr_reset_list) {
> + qmp->nocsr_resets = devm_kcalloc(dev, cfg->num_nocsr_resets,
> + sizeof(*qmp->nocsr_resets), GFP_KERNEL);
> + if (!qmp->nocsr_resets)
> + return -ENOMEM;
> +
> + for (i = 0; i < cfg->num_nocsr_resets; i++)
> + qmp->nocsr_resets[i].id = cfg->nocsr_reset_list[i];
> +
> + ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_nocsr_resets,
> + qmp->nocsr_resets);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to get no CSR resets\n");
> + }
> +
> return 0;
> }
>
> @@ -2502,6 +2847,9 @@ static int qmp_pcie_parse_dt_legacy(struct qmp_pcie *qmp, struct device_node *np
> return PTR_ERR(qmp->rx2);
>
> qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
> +
> + if (cfg->has_ln_shrd_serdes_tbl)
> + qmp->ln_shrd_serdes = devm_of_iomap(dev, np, 6, NULL);
I think we also need to check the returned value. Also, I think we can
drop the conditional check here. we don't have to validate the DT, so if
the reg is present in DT, then it's present. If not, it's not required.
> } else {
> qmp->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
> }
> @@ -2729,6 +3077,12 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
> }, {
> .compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy",
> .data = &sm8450_qmp_gen4x2_pciephy_cfg,
> + }, {
> + .compatible = "qcom,sm8550-qmp-gen3x2-pcie-phy",
> + .data = &sm8550_qmp_gen3x2_pciephy_cfg,
> + }, {
> + .compatible = "qcom,sm8550-qmp-gen4x2-pcie-phy",
> + .data = &sm8550_qmp_gen4x2_pciephy_cfg,
> },
> { },
> };
On 23-01-01 22:15:55, Dmitry Baryshkov wrote:
> On 16/11/2022 14:01, Abel Vesa wrote:
> > Add the SM8550 both g4 and g3 configurations. In addition, there is a
> > new "lane shared" table that needs to be configured for g4, along with
> > the No-CSR list of resets.
> >
> > Co-developed-by: Neil Armstrong <neil.armstrong@linaro.org>
> > Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> > Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
> > ---
> > drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 354 +++++++++++++++++++++++
> > 1 file changed, 354 insertions(+)
> >
> > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
> > index 47cccc4b35b2..87c7c20dfc8d 100644
> > --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
> > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
>
> [skipped tables]
>
> > @@ -1473,6 +1701,8 @@ struct qmp_pcie_offsets {
> > struct qmp_phy_cfg_tbls {
> > const struct qmp_phy_init_tbl *serdes;
> > int serdes_num;
> > + const struct qmp_phy_init_tbl *ln_shrd_serdes;
> > + int ln_shrd_serdes_num;
> > const struct qmp_phy_init_tbl *tx;
> > int tx_num;
> > const struct qmp_phy_init_tbl *rx;
> > @@ -1510,6 +1740,9 @@ struct qmp_phy_cfg {
> > /* resets to be requested */
> > const char * const *reset_list;
> > int num_resets;
> > + /* no CSR resets to be requested */
> > + const char * const *nocsr_reset_list;
> > + int num_nocsr_resets;
>
> Is there any difference between 'no CSR' resets and the plain ones? Can we
> handle them in a single array instead?
Yes, on power on, only the 'No CSR' are necessary to be deasserted.
So we need to differentiate between 'No CSR' and the rest.
>
> > /* regulators to be requested */
> > const char * const *vreg_list;
> > int num_vregs;
> > @@ -1523,6 +1756,9 @@ struct qmp_phy_cfg {
> > bool skip_start_delay;
> > + /* true, if PHY has lane shared serdes table */
> > + bool has_ln_shrd_serdes_tbl;
>
> s/shrd/shared/g ? I think it's easier to read and to understand.
Sure. Will do.
>
> > +
> > /* QMP PHY pipe clock interface rate */
> > unsigned long pipe_clock_rate;
> > };
> > @@ -1534,6 +1770,7 @@ struct qmp_pcie {
> > bool tcsr_4ln_config;
> > void __iomem *serdes;
> > + void __iomem *ln_shrd_serdes;
> > void __iomem *pcs;
> > void __iomem *pcs_misc;
> > void __iomem *tx;
> > @@ -1548,6 +1785,7 @@ struct qmp_pcie {
> > int num_pipe_clks;
> > struct reset_control_bulk_data *resets;
> > + struct reset_control_bulk_data *nocsr_resets;
> > struct regulator_bulk_data *vregs;
> > struct phy *phy;
> > @@ -1595,11 +1833,19 @@ static const char * const sdm845_pciephy_clk_l[] = {
> > "aux", "cfg_ahb", "ref", "refgen",
> > };
> > +static const char * const sm8550_pciephy_clk_l[] = {
> > + "aux", "aux_phy", "cfg_ahb", "ref", "refgen",
> > +};
> > +
> > /* list of regulators */
> > static const char * const qmp_phy_vreg_l[] = {
> > "vdda-phy", "vdda-pll",
> > };
> > +static const char * const sm8550_qmp_phy_vreg_l[] = {
> > + "vdda-phy", "vdda-pll", "vdda-qref",
> > +};
> > +
> > /* list of resets */
> > static const char * const ipq8074_pciephy_reset_l[] = {
> > "phy", "common",
> > @@ -1609,6 +1855,10 @@ static const char * const sdm845_pciephy_reset_l[] = {
> > "phy",
> > };
> > +static const char * const sm8550_pciephy_nocsr_reset_l[] = {
> > + "pcie_1_nocsr_com_phy_reset",
> > +};
> > +
> > static const struct qmp_pcie_offsets qmp_pcie_offsets_v5 = {
> > .serdes = 0,
> > .pcs = 0x0200,
> > @@ -2084,6 +2334,65 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = {
> > .phy_status = PHYSTATUS_4_20,
> > };
> > +static const struct qmp_phy_cfg sm8550_qmp_gen3x2_pciephy_cfg = {
> > + .lanes = 2,
> > +
> > + .tbls = {
> > + .serdes = sm8550_qmp_gen3x2_pcie_serdes_tbl,
> > + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl),
> > + .tx = sm8550_qmp_gen3x2_pcie_tx_tbl,
> > + .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl),
> > + .rx = sm8550_qmp_gen3x2_pcie_rx_tbl,
> > + .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl),
> > + .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl,
> > + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl),
> > + .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl,
> > + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl),
> > + },
> > + .clk_list = sdm845_pciephy_clk_l,
> > + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
> > + .reset_list = sdm845_pciephy_reset_l,
> > + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
> > + .vreg_list = qmp_phy_vreg_l,
> > + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
> > + .regs = sm8250_pcie_regs_layout,
> > +
> > + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
> > + .phy_status = PHYSTATUS,
> > +};
> > +
> > +static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = {
> > + .lanes = 2,
> > +
> > + .tbls = {
> > + .serdes = sm8550_qmp_gen4x2_pcie_serdes_tbl,
> > + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_serdes_tbl),
> > + .ln_shrd_serdes = sm8550_qmp_gen4x2_pcie_serdes_ln_shrd_tbl,
> > + .ln_shrd_serdes_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_serdes_ln_shrd_tbl),
> > + .tx = sm8550_qmp_gen4x2_pcie_tx_tbl,
> > + .tx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_tx_tbl),
> > + .rx = sm8550_qmp_gen4x2_pcie_rx_tbl,
> > + .rx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_rx_tbl),
> > + .pcs = sm8550_qmp_gen4x2_pcie_pcs_tbl,
> > + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_tbl),
> > + .pcs_misc = sm8550_qmp_gen4x2_pcie_pcs_misc_tbl,
> > + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_misc_tbl),
> > + },
> > + .clk_list = sm8550_pciephy_clk_l,
> > + .num_clks = ARRAY_SIZE(sm8550_pciephy_clk_l),
> > + .reset_list = sdm845_pciephy_reset_l,
> > + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
> > + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
> > + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
> > + .vreg_list = sm8550_qmp_phy_vreg_l,
> > + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
> > + .regs = sm8250_pcie_regs_layout,
> > +
> > + .has_ln_shrd_serdes_tbl = true,
> > + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
> > + .phy_status = PHYSTATUS_4_20,
> > +};
> > +
> > static void qmp_pcie_configure_lane(void __iomem *base,
> > const struct qmp_phy_init_tbl tbl[],
> > int num,
> > @@ -2132,6 +2441,7 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
> > {
> > const struct qmp_phy_cfg *cfg = qmp->cfg;
> > void __iomem *serdes = qmp->serdes;
> > + void __iomem *ln_shrd_serdes = qmp->ln_shrd_serdes;
> > void __iomem *tx = qmp->tx;
> > void __iomem *rx = qmp->rx;
> > void __iomem *tx2 = qmp->tx2;
> > @@ -2159,6 +2469,10 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
> > qmp_pcie_configure(serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num);
> > qmp_pcie_init_port_b(qmp, tbls);
> > }
> > +
> > + if (cfg->has_ln_shrd_serdes_tbl)
> > + qmp_pcie_configure(ln_shrd_serdes, tbls->ln_shrd_serdes,
> > + tbls->ln_shrd_serdes_num);
> > }
> > static int qmp_pcie_init(struct phy *phy)
> > @@ -2179,6 +2493,14 @@ static int qmp_pcie_init(struct phy *phy)
> > goto err_disable_regulators;
> > }
> > + if (qmp->nocsr_resets) {
> > + ret = reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_resets);
> > + if (ret) {
> > + dev_err(qmp->dev, "no-csr reset assert failed\n");
> > + goto err_disable_regulators;
> > + }
> > + }
> > +
> > usleep_range(200, 300);
> > ret = reset_control_bulk_deassert(cfg->num_resets, qmp->resets);
> > @@ -2240,6 +2562,14 @@ static int qmp_pcie_power_on(struct phy *phy)
> > if (ret)
> > return ret;
> > + if (qmp->nocsr_resets) {
> > + ret = reset_control_bulk_deassert(cfg->num_nocsr_resets, qmp->nocsr_resets);
> > + if (ret) {
> > + dev_err(qmp->dev, "no-csr reset deassert failed\n");
> > + goto err_disable_pipe_clk;
> > + }
> > + }
> > +
> > /* Pull PHY out of reset state */
> > qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
> > @@ -2373,6 +2703,21 @@ static int qmp_pcie_reset_init(struct qmp_pcie *qmp)
> > if (ret)
> > return dev_err_probe(dev, ret, "failed to get resets\n");
> > + if (cfg->nocsr_reset_list) {
> > + qmp->nocsr_resets = devm_kcalloc(dev, cfg->num_nocsr_resets,
> > + sizeof(*qmp->nocsr_resets), GFP_KERNEL);
> > + if (!qmp->nocsr_resets)
> > + return -ENOMEM;
> > +
> > + for (i = 0; i < cfg->num_nocsr_resets; i++)
> > + qmp->nocsr_resets[i].id = cfg->nocsr_reset_list[i];
> > +
> > + ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_nocsr_resets,
> > + qmp->nocsr_resets);
> > + if (ret)
> > + return dev_err_probe(dev, ret, "failed to get no CSR resets\n");
> > + }
> > +
> > return 0;
> > }
> > @@ -2502,6 +2847,9 @@ static int qmp_pcie_parse_dt_legacy(struct qmp_pcie *qmp, struct device_node *np
> > return PTR_ERR(qmp->rx2);
> > qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
> > +
> > + if (cfg->has_ln_shrd_serdes_tbl)
> > + qmp->ln_shrd_serdes = devm_of_iomap(dev, np, 6, NULL);
>
> I think we also need to check the returned value. Also, I think we can drop
> the conditional check here. we don't have to validate the DT, so if the reg
> is present in DT, then it's present. If not, it's not required.
Yeah, but I was trying to make sure that if there is a new type of reg
for some upcomming SoC, we don't take that as ln_shrd. That's why the check
was added.
I'll add the returned value check though.
>
> > } else {
> > qmp->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
> > }
> > @@ -2729,6 +3077,12 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
> > }, {
> > .compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy",
> > .data = &sm8450_qmp_gen4x2_pciephy_cfg,
> > + }, {
> > + .compatible = "qcom,sm8550-qmp-gen3x2-pcie-phy",
> > + .data = &sm8550_qmp_gen3x2_pciephy_cfg,
> > + }, {
> > + .compatible = "qcom,sm8550-qmp-gen4x2-pcie-phy",
> > + .data = &sm8550_qmp_gen4x2_pciephy_cfg,
> > },
> > { },
> > };
>
> --
> With best wishes
> Dmitry
>
@@ -1460,6 +1460,234 @@ static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl[] =
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x08),
};
+static const struct qmp_phy_init_tbl sm8550_qmp_gen3x2_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x93),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x42),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_ADDITIONAL_MISC_3, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen3x2_pcie_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_TX_LANE_MODE_1, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V6_TX_LANE_MODE_4, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_TX_PI_QEC_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x18),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen3x2_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_GM_CAL, 0x11),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH, 0xbf),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH2, 0xbf),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH3, 0xb7),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH4, 0xea),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_LOW, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH, 0x5c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH2, 0x9c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH3, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH4, 0x89),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_LOW, 0xdc),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH, 0x94),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH2, 0x5b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH3, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH4, 0x89),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_TX_ADAPT_POST_THRESH, 0xf0),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FO_GAIN, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SO_GAIN, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIDGET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_IDAC_TSETTLE_LOW, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_CAL_TRIM, 0x08),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen3x2_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_REFGEN_REQ_CONFIG1, 0x05),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_RX_SIGDET_LVL, 0x77),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_RATE_SLEW_CNTRL1, 0x0b),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_EQ_CONFIG2, 0x0f),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_PCS_TX_RX_CONFIG, 0x8c),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen3x2_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2, 0x1d),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x26),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_POST_DIV_MUX, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x46),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MISC_1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MODE, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_serdes_ln_shrd_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_Q_EN_RATES, 0xe),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B4, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B6, 0x64),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_RX, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_3, 0x51),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_TRAN_DRVR_EMP_EN, 0x34),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET, 0x7c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0xb3),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B2, 0x58),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B4, 0x26),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B6, 0xee),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B0, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B1, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B2, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B3, 0xdf),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x78),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_G3S2_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_COM_ELECIDLE_DLY_SEL, 0x25),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG4, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG5, 0x22),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG1, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG2, 0x02),
+};
+
+static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_OSC_DTCT_ATCIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG1, 0x16),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG5, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG1, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG3, 0x28),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_TX_RX_CONFIG, 0xc0),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_POWER_STATE_CONFIG2, 0x1d),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG5, 0x0f),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_FOM_EQ_CONFIG5, 0xf2),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5, 0xf2),
+};
+
struct qmp_pcie_offsets {
u16 serdes;
u16 pcs;
@@ -1473,6 +1701,8 @@ struct qmp_pcie_offsets {
struct qmp_phy_cfg_tbls {
const struct qmp_phy_init_tbl *serdes;
int serdes_num;
+ const struct qmp_phy_init_tbl *ln_shrd_serdes;
+ int ln_shrd_serdes_num;
const struct qmp_phy_init_tbl *tx;
int tx_num;
const struct qmp_phy_init_tbl *rx;
@@ -1510,6 +1740,9 @@ struct qmp_phy_cfg {
/* resets to be requested */
const char * const *reset_list;
int num_resets;
+ /* no CSR resets to be requested */
+ const char * const *nocsr_reset_list;
+ int num_nocsr_resets;
/* regulators to be requested */
const char * const *vreg_list;
int num_vregs;
@@ -1523,6 +1756,9 @@ struct qmp_phy_cfg {
bool skip_start_delay;
+ /* true, if PHY has lane shared serdes table */
+ bool has_ln_shrd_serdes_tbl;
+
/* QMP PHY pipe clock interface rate */
unsigned long pipe_clock_rate;
};
@@ -1534,6 +1770,7 @@ struct qmp_pcie {
bool tcsr_4ln_config;
void __iomem *serdes;
+ void __iomem *ln_shrd_serdes;
void __iomem *pcs;
void __iomem *pcs_misc;
void __iomem *tx;
@@ -1548,6 +1785,7 @@ struct qmp_pcie {
int num_pipe_clks;
struct reset_control_bulk_data *resets;
+ struct reset_control_bulk_data *nocsr_resets;
struct regulator_bulk_data *vregs;
struct phy *phy;
@@ -1595,11 +1833,19 @@ static const char * const sdm845_pciephy_clk_l[] = {
"aux", "cfg_ahb", "ref", "refgen",
};
+static const char * const sm8550_pciephy_clk_l[] = {
+ "aux", "aux_phy", "cfg_ahb", "ref", "refgen",
+};
+
/* list of regulators */
static const char * const qmp_phy_vreg_l[] = {
"vdda-phy", "vdda-pll",
};
+static const char * const sm8550_qmp_phy_vreg_l[] = {
+ "vdda-phy", "vdda-pll", "vdda-qref",
+};
+
/* list of resets */
static const char * const ipq8074_pciephy_reset_l[] = {
"phy", "common",
@@ -1609,6 +1855,10 @@ static const char * const sdm845_pciephy_reset_l[] = {
"phy",
};
+static const char * const sm8550_pciephy_nocsr_reset_l[] = {
+ "pcie_1_nocsr_com_phy_reset",
+};
+
static const struct qmp_pcie_offsets qmp_pcie_offsets_v5 = {
.serdes = 0,
.pcs = 0x0200,
@@ -2084,6 +2334,65 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = {
.phy_status = PHYSTATUS_4_20,
};
+static const struct qmp_phy_cfg sm8550_qmp_gen3x2_pciephy_cfg = {
+ .lanes = 2,
+
+ .tbls = {
+ .serdes = sm8550_qmp_gen3x2_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl),
+ .tx = sm8550_qmp_gen3x2_pcie_tx_tbl,
+ .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl),
+ .rx = sm8550_qmp_gen3x2_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl),
+ .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl),
+ .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl),
+ },
+ .clk_list = sdm845_pciephy_clk_l,
+ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = sm8250_pcie_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS,
+};
+
+static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = {
+ .lanes = 2,
+
+ .tbls = {
+ .serdes = sm8550_qmp_gen4x2_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_serdes_tbl),
+ .ln_shrd_serdes = sm8550_qmp_gen4x2_pcie_serdes_ln_shrd_tbl,
+ .ln_shrd_serdes_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_serdes_ln_shrd_tbl),
+ .tx = sm8550_qmp_gen4x2_pcie_tx_tbl,
+ .tx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_tx_tbl),
+ .rx = sm8550_qmp_gen4x2_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_rx_tbl),
+ .pcs = sm8550_qmp_gen4x2_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_tbl),
+ .pcs_misc = sm8550_qmp_gen4x2_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_misc_tbl),
+ },
+ .clk_list = sm8550_pciephy_clk_l,
+ .num_clks = ARRAY_SIZE(sm8550_pciephy_clk_l),
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
+ .vreg_list = sm8550_qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
+ .regs = sm8250_pcie_regs_layout,
+
+ .has_ln_shrd_serdes_tbl = true,
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS_4_20,
+};
+
static void qmp_pcie_configure_lane(void __iomem *base,
const struct qmp_phy_init_tbl tbl[],
int num,
@@ -2132,6 +2441,7 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *serdes = qmp->serdes;
+ void __iomem *ln_shrd_serdes = qmp->ln_shrd_serdes;
void __iomem *tx = qmp->tx;
void __iomem *rx = qmp->rx;
void __iomem *tx2 = qmp->tx2;
@@ -2159,6 +2469,10 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
qmp_pcie_configure(serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num);
qmp_pcie_init_port_b(qmp, tbls);
}
+
+ if (cfg->has_ln_shrd_serdes_tbl)
+ qmp_pcie_configure(ln_shrd_serdes, tbls->ln_shrd_serdes,
+ tbls->ln_shrd_serdes_num);
}
static int qmp_pcie_init(struct phy *phy)
@@ -2179,6 +2493,14 @@ static int qmp_pcie_init(struct phy *phy)
goto err_disable_regulators;
}
+ if (qmp->nocsr_resets) {
+ ret = reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_resets);
+ if (ret) {
+ dev_err(qmp->dev, "no-csr reset assert failed\n");
+ goto err_disable_regulators;
+ }
+ }
+
usleep_range(200, 300);
ret = reset_control_bulk_deassert(cfg->num_resets, qmp->resets);
@@ -2240,6 +2562,14 @@ static int qmp_pcie_power_on(struct phy *phy)
if (ret)
return ret;
+ if (qmp->nocsr_resets) {
+ ret = reset_control_bulk_deassert(cfg->num_nocsr_resets, qmp->nocsr_resets);
+ if (ret) {
+ dev_err(qmp->dev, "no-csr reset deassert failed\n");
+ goto err_disable_pipe_clk;
+ }
+ }
+
/* Pull PHY out of reset state */
qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
@@ -2373,6 +2703,21 @@ static int qmp_pcie_reset_init(struct qmp_pcie *qmp)
if (ret)
return dev_err_probe(dev, ret, "failed to get resets\n");
+ if (cfg->nocsr_reset_list) {
+ qmp->nocsr_resets = devm_kcalloc(dev, cfg->num_nocsr_resets,
+ sizeof(*qmp->nocsr_resets), GFP_KERNEL);
+ if (!qmp->nocsr_resets)
+ return -ENOMEM;
+
+ for (i = 0; i < cfg->num_nocsr_resets; i++)
+ qmp->nocsr_resets[i].id = cfg->nocsr_reset_list[i];
+
+ ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_nocsr_resets,
+ qmp->nocsr_resets);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get no CSR resets\n");
+ }
+
return 0;
}
@@ -2502,6 +2847,9 @@ static int qmp_pcie_parse_dt_legacy(struct qmp_pcie *qmp, struct device_node *np
return PTR_ERR(qmp->rx2);
qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
+
+ if (cfg->has_ln_shrd_serdes_tbl)
+ qmp->ln_shrd_serdes = devm_of_iomap(dev, np, 6, NULL);
} else {
qmp->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
}
@@ -2729,6 +3077,12 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy",
.data = &sm8450_qmp_gen4x2_pciephy_cfg,
+ }, {
+ .compatible = "qcom,sm8550-qmp-gen3x2-pcie-phy",
+ .data = &sm8550_qmp_gen3x2_pciephy_cfg,
+ }, {
+ .compatible = "qcom,sm8550-qmp-gen4x2-pcie-phy",
+ .data = &sm8550_qmp_gen4x2_pciephy_cfg,
},
{ },
};