2022-10-19 15:50:22

by Daniel Golle

[permalink] [raw]
Subject: [PATCH 1/2] phy: phy-mtk-tphy: Add PCIe 2 lane efuse support

From: Zhanyong Wang <[email protected]>

Add PCIe 2 lane efuse support in tphy driver.

Signed-off-by: Jie Yang <[email protected]>
Signed-off-by: Zhanyong Wang <[email protected]>
Signed-off-by: Daniel Golle <[email protected]>
---
drivers/phy/mediatek/phy-mtk-tphy.c | 112 ++++++++++++++++++++++++++++
1 file changed, 112 insertions(+)

diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
index e906a82791bdaa..b0c9834efec7ef 100644
--- a/drivers/phy/mediatek/phy-mtk-tphy.c
+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
@@ -43,6 +43,15 @@
#define SSUSB_SIFSLV_V2_U3PHYD 0x200
#define SSUSB_SIFSLV_V2_U3PHYA 0x400

+/* version V4 sub-banks offset base address */
+/* pcie phy banks */
+#define SSUSB_SIFSLV_V4_SPLLC 0x000
+#define SSUSB_SIFSLV_V4_CHIP 0x100
+#define SSUSB_SIFSLV_V4_U3PHYD 0x900
+#define SSUSB_SIFSLV_V4_U3PHYA 0xb00
+
+#define SSUSB_LN1_OFFSET 0x10000
+
#define U3P_MISC_REG1 0x04
#define MR1_EFUSE_AUTO_LOAD_DIS BIT(6)

@@ -268,6 +277,7 @@ enum mtk_phy_version {
MTK_PHY_V1 = 1,
MTK_PHY_V2,
MTK_PHY_V3,
+ MTK_PHY_V4,
};

struct mtk_phy_pdata {
@@ -317,6 +327,9 @@ struct mtk_phy_instance {
u32 efuse_intr;
u32 efuse_tx_imp;
u32 efuse_rx_imp;
+ u32 efuse_intr_ln1;
+ u32 efuse_tx_imp_ln1;
+ u32 efuse_rx_imp_ln1;
int eye_src;
int eye_vrt;
int eye_term;
@@ -760,6 +773,36 @@ static void phy_v2_banks_init(struct mtk_tphy *tphy,
}
}

+static void phy_v4_banks_init(struct mtk_tphy *tphy,
+ struct mtk_phy_instance *instance)
+{
+ struct u2phy_banks *u2_banks = &instance->u2_banks;
+ struct u3phy_banks *u3_banks = &instance->u3_banks;
+
+ switch (instance->type) {
+ case PHY_TYPE_USB2:
+ u2_banks->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC;
+ u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ;
+ u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM;
+ break;
+ case PHY_TYPE_USB3:
+ u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V2_SPLLC;
+ u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP;
+ u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD;
+ u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V2_U3PHYA;
+ break;
+ case PHY_TYPE_PCIE:
+ u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V4_SPLLC;
+ u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V4_CHIP;
+ u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V4_U3PHYD;
+ u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V4_U3PHYA;
+ break;
+ default:
+ dev_err(tphy->dev, "incompatible PHY type\n");
+ return;
+ }
+}
+
static void phy_parse_property(struct mtk_tphy *tphy,
struct mtk_phy_instance *instance)
{
@@ -951,6 +994,40 @@ static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instanc

dev_dbg(dev, "u3 efuse - intr %x, rx_imp %x, tx_imp %x\n",
instance->efuse_intr, instance->efuse_rx_imp,instance->efuse_tx_imp);
+
+ if (tphy->pdata->version != MTK_PHY_V4)
+ break;
+
+ ret = nvmem_cell_read_variable_le_u32(dev, "intr_ln1", &instance->efuse_intr_ln1);
+ if (ret) {
+ dev_err(dev, "fail to get u3 lane1 intr efuse, %d\n", ret);
+ break;
+ }
+
+ ret = nvmem_cell_read_variable_le_u32(dev, "rx_imp_ln1", &instance->efuse_rx_imp_ln1);
+ if (ret) {
+ dev_err(dev, "fail to get u3 lane1 rx_imp efuse, %d\n", ret);
+ break;
+ }
+
+ ret = nvmem_cell_read_variable_le_u32(dev, "tx_imp_ln1", &instance->efuse_tx_imp_ln1);
+ if (ret) {
+ dev_err(dev, "fail to get u3 lane1 tx_imp efuse, %d\n", ret);
+ break;
+ }
+
+ /* no efuse, ignore it */
+ if (!instance->efuse_intr_ln1 &&
+ !instance->efuse_rx_imp_ln1 &&
+ !instance->efuse_tx_imp_ln1) {
+ dev_warn(dev, "no u3 lane1 efuse, but dts enable it\n");
+ instance->efuse_sw_en = 0;
+ break;
+ }
+
+ dev_info(dev, "u3 lane1 efuse - intr %x, rx_imp %x, tx_imp %x\n",
+ instance->efuse_intr_ln1, instance->efuse_rx_imp_ln1,
+ instance->efuse_tx_imp_ln1);
break;
default:
dev_err(dev, "no sw efuse for type %d\n", instance->type);
@@ -990,6 +1067,31 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)

mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0, P3A_RG_IEXT_INTR,
instance->efuse_intr);
+ if (instance->type == PHY_TYPE_USB3 || (
+ !instance->efuse_intr_ln1 &&
+ !instance->efuse_rx_imp_ln1 &&
+ !instance->efuse_tx_imp_ln1))
+ break;
+
+ mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_RSV,
+ P3D_RG_EFUSE_AUTO_LOAD_DIS);
+
+ mtk_phy_update_field(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_IMPCAL0,
+ P3D_RG_TX_IMPEL, instance->efuse_tx_imp_ln1);
+ mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_IMPCAL0,
+ P3D_RG_FORCE_TX_IMPEL);
+
+ mtk_phy_update_field(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_IMPCAL1,
+ P3D_RG_RX_IMPEL, instance->efuse_rx_imp_ln1);
+ mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_IMPCAL1,
+ P3D_RG_FORCE_RX_IMPEL);
+
+ mtk_phy_update_field(u3_banks->phya + SSUSB_LN1_OFFSET + U3P_U3_PHYA_REG0,
+ P3A_RG_IEXT_INTR, instance->efuse_intr_ln1);
+
+ dev_info(dev, "%s set LN1 efuse, tx_imp %x, rx_imp %x intr %x\n",
+ __func__, instance->efuse_tx_imp_ln1,
+ instance->efuse_rx_imp_ln1, instance->efuse_intr_ln1);
break;
default:
dev_warn(dev, "no sw efuse for type %d\n", instance->type);
@@ -1129,6 +1231,9 @@ static struct phy *mtk_phy_xlate(struct device *dev,
case MTK_PHY_V3:
phy_v2_banks_init(tphy, instance);
break;
+ case MTK_PHY_V4:
+ phy_v4_banks_init(tphy, instance);
+ break;
default:
dev_err(dev, "phy version is not supported\n");
return ERR_PTR(-EINVAL);
@@ -1169,6 +1274,12 @@ static const struct mtk_phy_pdata tphy_v3_pdata = {
.version = MTK_PHY_V3,
};

+static const struct mtk_phy_pdata tphy_v4_pdata = {
+ .avoid_rx_sen_degradation = false,
+ .sw_efuse_supported = true,
+ .version = MTK_PHY_V4,
+};
+
static const struct mtk_phy_pdata mt8173_pdata = {
.avoid_rx_sen_degradation = true,
.version = MTK_PHY_V1,
@@ -1188,6 +1299,7 @@ static const struct of_device_id mtk_tphy_id_table[] = {
{ .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata },
{ .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata },
{ .compatible = "mediatek,generic-tphy-v3", .data = &tphy_v3_pdata },
+ { .compatible = "mediatek,generic-tphy-v4", .data = &tphy_v4_pdata },
{ },
};
MODULE_DEVICE_TABLE(of, mtk_tphy_id_table);
--
2.37.3


2022-10-19 16:07:04

by Daniel Golle

[permalink] [raw]
Subject: [PATCH 2/2] dt-bindings: phy: mediatek: tphy: add compatible for tphy-v4

V4 can be found in MT7986 and MT7981 SoCs, it supports PCIe with two
lanes.

Signed-off-by: Daniel Golle <[email protected]>
---
Documentation/devicetree/bindings/phy/mediatek,tphy.yaml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
index 5613cc5106e32f..851e3dda7b638b 100644
--- a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
+++ b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
@@ -89,6 +89,11 @@ properties:
- mediatek,mt8188-tphy
- mediatek,mt8195-tphy
- const: mediatek,generic-tphy-v3
+ - items:
+ - enum:
+ - mediatek,mt7981-tphy
+ - mediatek,mt7986-tphy
+ - const: mediatek,generic-tphy-v4
- const: mediatek,mt2701-u3phy
deprecated: true
- const: mediatek,mt2712-u3phy
@@ -99,7 +104,7 @@ properties:
description:
Register shared by multiple ports, exclude port's private register.
It is needed for T-PHY V1, such as mt2701 and mt8173, but not for
- T-PHY V2/V3, such as mt2712.
+ T-PHY V2/V3/V4, such as mt2712.
maxItems: 1

"#address-cells":
--
2.37.3

2022-10-21 02:41:54

by Sam Shih

[permalink] [raw]
Subject: Re: [PATCH 1/2] phy: phy-mtk-tphy: Add PCIe 2 lane efuse support

Hi Daniel,

The only difference between V2 and V4 tphy drivers is that V4 provides
2 channel efuse loading support.

MT7981 and MT7986 SoC support the 'autoload' feature to automatically
load PCIE 2nd lane efuse values into hardware, and this feature is
enabled on all MT7986 chips on the production line.

So I think we can directly use tphy V2 driver instead of tphy V4 for
MT7986 and MT7981 SoCs.


Best Regards,
Sam Shih


On Wed, 2022-10-19 at 16:37 +0100, Daniel Golle wrote:
> From: Zhanyong Wang <[email protected]>
>
> Add PCIe 2 lane efuse support in tphy driver.
>
> Signed-off-by: Jie Yang <[email protected]>
> Signed-off-by: Zhanyong Wang <[email protected]>
> Signed-off-by: Daniel Golle <[email protected]>
> ---
> drivers/phy/mediatek/phy-mtk-tphy.c | 112
> ++++++++++++++++++++++++++++
> 1 file changed, 112 insertions(+)
>
> diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c
> b/drivers/phy/mediatek/phy-mtk-tphy.c
> index e906a82791bdaa..b0c9834efec7ef 100644
> --- a/drivers/phy/mediatek/phy-mtk-tphy.c
> +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
> @@ -43,6 +43,15 @@
> #define SSUSB_SIFSLV_V2_U3PHYD 0x200
> #define SSUSB_SIFSLV_V2_U3PHYA 0x400
>
> +/* version V4 sub-banks offset base address */
> +/* pcie phy banks */
> +#define SSUSB_SIFSLV_V4_SPLLC 0x000
> +#define SSUSB_SIFSLV_V4_CHIP 0x100
> +#define SSUSB_SIFSLV_V4_U3PHYD 0x900
> +#define SSUSB_SIFSLV_V4_U3PHYA 0xb00
> +
> +#define SSUSB_LN1_OFFSET 0x10000
> +
> #define U3P_MISC_REG1 0x04
> #define MR1_EFUSE_AUTO_LOAD_DIS BIT(6)
>
> @@ -268,6 +277,7 @@ enum mtk_phy_version {
> MTK_PHY_V1 = 1,
> MTK_PHY_V2,
> MTK_PHY_V3,
> + MTK_PHY_V4,
> };
>
> struct mtk_phy_pdata {
> @@ -317,6 +327,9 @@ struct mtk_phy_instance {
> u32 efuse_intr;
> u32 efuse_tx_imp;
> u32 efuse_rx_imp;
> + u32 efuse_intr_ln1;
> + u32 efuse_tx_imp_ln1;
> + u32 efuse_rx_imp_ln1;
> int eye_src;
> int eye_vrt;
> int eye_term;
> @@ -760,6 +773,36 @@ static void phy_v2_banks_init(struct mtk_tphy
> *tphy,
> }
> }
>
> +static void phy_v4_banks_init(struct mtk_tphy *tphy,
> + struct mtk_phy_instance *instance)
> +{
> + struct u2phy_banks *u2_banks = &instance->u2_banks;
> + struct u3phy_banks *u3_banks = &instance->u3_banks;
> +
> + switch (instance->type) {
> + case PHY_TYPE_USB2:
> + u2_banks->misc = instance->port_base +
> SSUSB_SIFSLV_V2_MISC;
> + u2_banks->fmreg = instance->port_base +
> SSUSB_SIFSLV_V2_U2FREQ;
> + u2_banks->com = instance->port_base +
> SSUSB_SIFSLV_V2_U2PHY_COM;
> + break;
> + case PHY_TYPE_USB3:
> + u3_banks->spllc = instance->port_base +
> SSUSB_SIFSLV_V2_SPLLC;
> + u3_banks->chip = instance->port_base +
> SSUSB_SIFSLV_V2_CHIP;
> + u3_banks->phyd = instance->port_base +
> SSUSB_SIFSLV_V2_U3PHYD;
> + u3_banks->phya = instance->port_base +
> SSUSB_SIFSLV_V2_U3PHYA;
> + break;
> + case PHY_TYPE_PCIE:
> + u3_banks->spllc = instance->port_base +
> SSUSB_SIFSLV_V4_SPLLC;
> + u3_banks->chip = instance->port_base +
> SSUSB_SIFSLV_V4_CHIP;
> + u3_banks->phyd = instance->port_base +
> SSUSB_SIFSLV_V4_U3PHYD;
> + u3_banks->phya = instance->port_base +
> SSUSB_SIFSLV_V4_U3PHYA;
> + break;
> + default:
> + dev_err(tphy->dev, "incompatible PHY type\n");
> + return;
> + }
> +}
> +
> static void phy_parse_property(struct mtk_tphy *tphy,
> struct mtk_phy_instance *instance)
> {
> @@ -951,6 +994,40 @@ static int phy_efuse_get(struct mtk_tphy *tphy,
> struct mtk_phy_instance *instanc
>
> dev_dbg(dev, "u3 efuse - intr %x, rx_imp %x, tx_imp
> %x\n",
> instance->efuse_intr, instance-
> >efuse_rx_imp,instance->efuse_tx_imp);
> +
> + if (tphy->pdata->version != MTK_PHY_V4)
> + break;
> +
> + ret = nvmem_cell_read_variable_le_u32(dev, "intr_ln1",
> &instance->efuse_intr_ln1);
> + if (ret) {
> + dev_err(dev, "fail to get u3 lane1 intr efuse,
> %d\n", ret);
> + break;
> + }
> +
> + ret = nvmem_cell_read_variable_le_u32(dev,
> "rx_imp_ln1", &instance->efuse_rx_imp_ln1);
> + if (ret) {
> + dev_err(dev, "fail to get u3 lane1 rx_imp
> efuse, %d\n", ret);
> + break;
> + }
> +
> + ret = nvmem_cell_read_variable_le_u32(dev,
> "tx_imp_ln1", &instance->efuse_tx_imp_ln1);
> + if (ret) {
> + dev_err(dev, "fail to get u3 lane1 tx_imp
> efuse, %d\n", ret);
> + break;
> + }
> +
> + /* no efuse, ignore it */
> + if (!instance->efuse_intr_ln1 &&
> + !instance->efuse_rx_imp_ln1 &&
> + !instance->efuse_tx_imp_ln1) {
> + dev_warn(dev, "no u3 lane1 efuse, but dts
> enable it\n");
> + instance->efuse_sw_en = 0;
> + break;
> + }
> +
> + dev_info(dev, "u3 lane1 efuse - intr %x, rx_imp %x,
> tx_imp %x\n",
> + instance->efuse_intr_ln1, instance-
> >efuse_rx_imp_ln1,
> + instance->efuse_tx_imp_ln1);
> break;
> default:
> dev_err(dev, "no sw efuse for type %d\n", instance-
> >type);
> @@ -990,6 +1067,31 @@ static void phy_efuse_set(struct
> mtk_phy_instance *instance)
>
> mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0,
> P3A_RG_IEXT_INTR,
> instance->efuse_intr);
> + if (instance->type == PHY_TYPE_USB3 || (
> + !instance->efuse_intr_ln1 &&
> + !instance->efuse_rx_imp_ln1 &&
> + !instance->efuse_tx_imp_ln1))
> + break;
> +
> + mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET +
> U3P_U3_PHYD_RSV,
> + P3D_RG_EFUSE_AUTO_LOAD_DIS);
> +
> + mtk_phy_update_field(u3_banks->phyd + SSUSB_LN1_OFFSET
> + U3P_U3_PHYD_IMPCAL0,
> + P3D_RG_TX_IMPEL, instance-
> >efuse_tx_imp_ln1);
> + mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET +
> U3P_U3_PHYD_IMPCAL0,
> + P3D_RG_FORCE_TX_IMPEL);
> +
> + mtk_phy_update_field(u3_banks->phyd + SSUSB_LN1_OFFSET
> + U3P_U3_PHYD_IMPCAL1,
> + P3D_RG_RX_IMPEL, instance-
> >efuse_rx_imp_ln1);
> + mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET +
> U3P_U3_PHYD_IMPCAL1,
> + P3D_RG_FORCE_RX_IMPEL);
> +
> + mtk_phy_update_field(u3_banks->phya + SSUSB_LN1_OFFSET
> + U3P_U3_PHYA_REG0,
> + P3A_RG_IEXT_INTR, instance-
> >efuse_intr_ln1);
> +
> + dev_info(dev, "%s set LN1 efuse, tx_imp %x, rx_imp %x
> intr %x\n",
> + __func__, instance->efuse_tx_imp_ln1,
> + instance->efuse_rx_imp_ln1, instance-
> >efuse_intr_ln1);
> break;
> default:
> dev_warn(dev, "no sw efuse for type %d\n", instance-
> >type);
> @@ -1129,6 +1231,9 @@ static struct phy *mtk_phy_xlate(struct device
> *dev,
> case MTK_PHY_V3:
> phy_v2_banks_init(tphy, instance);
> break;
> + case MTK_PHY_V4:
> + phy_v4_banks_init(tphy, instance);
> + break;
> default:
> dev_err(dev, "phy version is not supported\n");
> return ERR_PTR(-EINVAL);
> @@ -1169,6 +1274,12 @@ static const struct mtk_phy_pdata
> tphy_v3_pdata = {
> .version = MTK_PHY_V3,
> };
>
> +static const struct mtk_phy_pdata tphy_v4_pdata = {
> + .avoid_rx_sen_degradation = false,
> + .sw_efuse_supported = true,
> + .version = MTK_PHY_V4,
> +};
> +
> static const struct mtk_phy_pdata mt8173_pdata = {
> .avoid_rx_sen_degradation = true,
> .version = MTK_PHY_V1,
> @@ -1188,6 +1299,7 @@ static const struct of_device_id
> mtk_tphy_id_table[] = {
> { .compatible = "mediatek,generic-tphy-v1", .data =
> &tphy_v1_pdata },
> { .compatible = "mediatek,generic-tphy-v2", .data =
> &tphy_v2_pdata },
> { .compatible = "mediatek,generic-tphy-v3", .data =
> &tphy_v3_pdata },
> + { .compatible = "mediatek,generic-tphy-v4", .data =
> &tphy_v4_pdata },
> { },
> };
> MODULE_DEVICE_TABLE(of, mtk_tphy_id_table);
> --
> 2.37.3
>
>

2022-10-21 02:46:17

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH 2/2] dt-bindings: phy: mediatek: tphy: add compatible for tphy-v4

On Wed, 19 Oct 2022 16:38:14 +0100, Daniel Golle wrote:
> V4 can be found in MT7986 and MT7981 SoCs, it supports PCIe with two
> lanes.
>
> Signed-off-by: Daniel Golle <[email protected]>
> ---
> Documentation/devicetree/bindings/phy/mediatek,tphy.yaml | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>

Reviewed-by: Rob Herring <[email protected]>

2022-10-21 06:49:12

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH 2/2] dt-bindings: phy: mediatek: tphy: add compatible for tphy-v4

On Wed, 2022-10-19 at 16:38 +0100, Daniel Golle wrote:
> V4 can be found in MT7986 and MT7981 SoCs, it supports PCIe with two
> lanes.
NAK.

mt7981/mt7986 shall use "mediatek,generic-tphy-v2" instead.

Thanks a lot

>
> Signed-off-by: Daniel Golle <[email protected]>
> ---
> Documentation/devicetree/bindings/phy/mediatek,tphy.yaml | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
> b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
> index 5613cc5106e32f..851e3dda7b638b 100644
> --- a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
> +++ b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
> @@ -89,6 +89,11 @@ properties:
> - mediatek,mt8188-tphy
> - mediatek,mt8195-tphy
> - const: mediatek,generic-tphy-v3
> + - items:
> + - enum:
> + - mediatek,mt7981-tphy
> + - mediatek,mt7986-tphy
> + - const: mediatek,generic-tphy-v4
> - const: mediatek,mt2701-u3phy
> deprecated: true
> - const: mediatek,mt2712-u3phy
> @@ -99,7 +104,7 @@ properties:
> description:
> Register shared by multiple ports, exclude port's private
> register.
> It is needed for T-PHY V1, such as mt2701 and mt8173, but not
> for
> - T-PHY V2/V3, such as mt2712.
> + T-PHY V2/V3/V4, such as mt2712.
> maxItems: 1
>
> "#address-cells":

2022-10-21 06:58:06

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH 1/2] phy: phy-mtk-tphy: Add PCIe 2 lane efuse support

On Wed, 2022-10-19 at 16:37 +0100, Daniel Golle wrote:
> From: Zhanyong Wang <[email protected]>
>
> Add PCIe 2 lane efuse support in tphy driver.
>
> Signed-off-by: Jie Yang <[email protected]>
> Signed-off-by: Zhanyong Wang <[email protected]>
> Signed-off-by: Daniel Golle <[email protected]>
> ---
> drivers/phy/mediatek/phy-mtk-tphy.c | 112
> ++++++++++++++++++++++++++++
> 1 file changed, 112 insertions(+)
>
> diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c
> b/drivers/phy/mediatek/phy-mtk-tphy.c
> index e906a82791bdaa..b0c9834efec7ef 100644
> --- a/drivers/phy/mediatek/phy-mtk-tphy.c
> +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
> @@ -43,6 +43,15 @@
> #define SSUSB_SIFSLV_V2_U3PHYD 0x200
> #define SSUSB_SIFSLV_V2_U3PHYA 0x400
>
> +/* version V4 sub-banks offset base address */
> +/* pcie phy banks */
> +#define SSUSB_SIFSLV_V4_SPLLC 0x000
> +#define SSUSB_SIFSLV_V4_CHIP 0x100
> +#define SSUSB_SIFSLV_V4_U3PHYD 0x900
> +#define SSUSB_SIFSLV_V4_U3PHYA 0xb00
> +
> +#define SSUSB_LN1_OFFSET 0x10000
> +
> #define U3P_MISC_REG1 0x04
> #define MR1_EFUSE_AUTO_LOAD_DIS BIT(6)
>
> @@ -268,6 +277,7 @@ enum mtk_phy_version {
> MTK_PHY_V1 = 1,
> MTK_PHY_V2,
> MTK_PHY_V3,
> + MTK_PHY_V4,
> };
>
> struct mtk_phy_pdata {
> @@ -317,6 +327,9 @@ struct mtk_phy_instance {
> u32 efuse_intr;
> u32 efuse_tx_imp;
> u32 efuse_rx_imp;
> + u32 efuse_intr_ln1;
> + u32 efuse_tx_imp_ln1;
> + u32 efuse_rx_imp_ln1;
> int eye_src;
> int eye_vrt;
> int eye_term;
> @@ -760,6 +773,36 @@ static void phy_v2_banks_init(struct mtk_tphy
> *tphy,
> }
> }
>
> +static void phy_v4_banks_init(struct mtk_tphy *tphy,
> + struct mtk_phy_instance *instance)
> +{
> + struct u2phy_banks *u2_banks = &instance->u2_banks;
> + struct u3phy_banks *u3_banks = &instance->u3_banks;
> +
> + switch (instance->type) {
> + case PHY_TYPE_USB2:
> + u2_banks->misc = instance->port_base +
> SSUSB_SIFSLV_V2_MISC;
> + u2_banks->fmreg = instance->port_base +
> SSUSB_SIFSLV_V2_U2FREQ;
> + u2_banks->com = instance->port_base +
> SSUSB_SIFSLV_V2_U2PHY_COM;
> + break;
> + case PHY_TYPE_USB3:
> + u3_banks->spllc = instance->port_base +
> SSUSB_SIFSLV_V2_SPLLC;
> + u3_banks->chip = instance->port_base +
> SSUSB_SIFSLV_V2_CHIP;
> + u3_banks->phyd = instance->port_base +
> SSUSB_SIFSLV_V2_U3PHYD;
> + u3_banks->phya = instance->port_base +
> SSUSB_SIFSLV_V2_U3PHYA;
> + break;
> + case PHY_TYPE_PCIE:
> + u3_banks->spllc = instance->port_base +
> SSUSB_SIFSLV_V4_SPLLC;
> + u3_banks->chip = instance->port_base +
> SSUSB_SIFSLV_V4_CHIP;
> + u3_banks->phyd = instance->port_base +
> SSUSB_SIFSLV_V4_U3PHYD;
> + u3_banks->phya = instance->port_base +
> SSUSB_SIFSLV_V4_U3PHYA;
> + break;
> + default:
> + dev_err(tphy->dev, "incompatible PHY type\n");
> + return;
> + }
> +}
> +
> static void phy_parse_property(struct mtk_tphy *tphy,
> struct mtk_phy_instance *instance)
> {
> @@ -951,6 +994,40 @@ static int phy_efuse_get(struct mtk_tphy *tphy,
> struct mtk_phy_instance *instanc
>
> dev_dbg(dev, "u3 efuse - intr %x, rx_imp %x, tx_imp
> %x\n",
> instance->efuse_intr, instance-
> >efuse_rx_imp,instance->efuse_tx_imp);
> +
> + if (tphy->pdata->version != MTK_PHY_V4)
> + break;
> +
> + ret = nvmem_cell_read_variable_le_u32(dev, "intr_ln1",
> &instance->efuse_intr_ln1);
> + if (ret) {
> + dev_err(dev, "fail to get u3 lane1 intr efuse,
> %d\n", ret);
> + break;
> + }
> +
> + ret = nvmem_cell_read_variable_le_u32(dev,
> "rx_imp_ln1", &instance->efuse_rx_imp_ln1);
> + if (ret) {
> + dev_err(dev, "fail to get u3 lane1 rx_imp
> efuse, %d\n", ret);
> + break;
> + }
> +
> + ret = nvmem_cell_read_variable_le_u32(dev,
> "tx_imp_ln1", &instance->efuse_tx_imp_ln1);
> + if (ret) {
> + dev_err(dev, "fail to get u3 lane1 tx_imp
> efuse, %d\n", ret);
> + break;
> + }
> +
> + /* no efuse, ignore it */
> + if (!instance->efuse_intr_ln1 &&
> + !instance->efuse_rx_imp_ln1 &&
> + !instance->efuse_tx_imp_ln1) {
> + dev_warn(dev, "no u3 lane1 efuse, but dts
> enable it\n");
> + instance->efuse_sw_en = 0;
> + break;
> + }
> +
> + dev_info(dev, "u3 lane1 efuse - intr %x, rx_imp %x,
> tx_imp %x\n",
> + instance->efuse_intr_ln1, instance-
> >efuse_rx_imp_ln1,
> + instance->efuse_tx_imp_ln1);
> break;
> default:
> dev_err(dev, "no sw efuse for type %d\n", instance-
> >type);
> @@ -990,6 +1067,31 @@ static void phy_efuse_set(struct
> mtk_phy_instance *instance)
>
> mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0,
> P3A_RG_IEXT_INTR,
> instance->efuse_intr);
> + if (instance->type == PHY_TYPE_USB3 || (
> + !instance->efuse_intr_ln1 &&
> + !instance->efuse_rx_imp_ln1 &&
> + !instance->efuse_tx_imp_ln1))
> + break;
> +
> + mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET +
> U3P_U3_PHYD_RSV,
> + P3D_RG_EFUSE_AUTO_LOAD_DIS);
> +
> + mtk_phy_update_field(u3_banks->phyd + SSUSB_LN1_OFFSET
> + U3P_U3_PHYD_IMPCAL0,
> + P3D_RG_TX_IMPEL, instance-
> >efuse_tx_imp_ln1);
> + mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET +
> U3P_U3_PHYD_IMPCAL0,
> + P3D_RG_FORCE_TX_IMPEL);
> +
> + mtk_phy_update_field(u3_banks->phyd + SSUSB_LN1_OFFSET
> + U3P_U3_PHYD_IMPCAL1,
> + P3D_RG_RX_IMPEL, instance-
> >efuse_rx_imp_ln1);
> + mtk_phy_set_bits(u3_banks->phyd + SSUSB_LN1_OFFSET +
> U3P_U3_PHYD_IMPCAL1,
> + P3D_RG_FORCE_RX_IMPEL);
> +
> + mtk_phy_update_field(u3_banks->phya + SSUSB_LN1_OFFSET
> + U3P_U3_PHYA_REG0,
> + P3A_RG_IEXT_INTR, instance-
> >efuse_intr_ln1);
> +
> + dev_info(dev, "%s set LN1 efuse, tx_imp %x, rx_imp %x
> intr %x\n",
> + __func__, instance->efuse_tx_imp_ln1,
> + instance->efuse_rx_imp_ln1, instance-
> >efuse_intr_ln1);
> break;
> default:
> dev_warn(dev, "no sw efuse for type %d\n", instance-
> >type);
> @@ -1129,6 +1231,9 @@ static struct phy *mtk_phy_xlate(struct device
> *dev,
> case MTK_PHY_V3:
> phy_v2_banks_init(tphy, instance);
> break;
> + case MTK_PHY_V4:
> + phy_v4_banks_init(tphy, instance);
> + break;
> default:
> dev_err(dev, "phy version is not supported\n");
> return ERR_PTR(-EINVAL);
> @@ -1169,6 +1274,12 @@ static const struct mtk_phy_pdata
> tphy_v3_pdata = {
> .version = MTK_PHY_V3,
> };
>
> +static const struct mtk_phy_pdata tphy_v4_pdata = {
> + .avoid_rx_sen_degradation = false,
> + .sw_efuse_supported = true,
> + .version = MTK_PHY_V4,
> +};

Please try to use hardware efuse autoload way for this case first,
there is no hardware issue, so I don't think we need use software way.

As Sam said, the hardware ip used on 7981/7986 is MTK_PHY_V2;

Thanks a lot

> +
> static const struct mtk_phy_pdata mt8173_pdata = {
> .avoid_rx_sen_degradation = true,
> .version = MTK_PHY_V1,
> @@ -1188,6 +1299,7 @@ static const struct of_device_id
> mtk_tphy_id_table[] = {
> { .compatible = "mediatek,generic-tphy-v1", .data =
> &tphy_v1_pdata },
> { .compatible = "mediatek,generic-tphy-v2", .data =
> &tphy_v2_pdata },
> { .compatible = "mediatek,generic-tphy-v3", .data =
> &tphy_v3_pdata },
> + { .compatible = "mediatek,generic-tphy-v4", .data =
> &tphy_v4_pdata },
> { },
> };
> MODULE_DEVICE_TABLE(of, mtk_tphy_id_table);