From 8cf766e6cf733ec0b8dcb8d2339d35a54921cc2c Mon Sep 17 00:00:00 2001 From: hongyi Date: Sun, 4 Jan 2026 12:22:11 +0800 Subject: [PATCH] Release develop 260104 --- arch/riscv/boot/dts/zhihe/a210-evb.dts | 6 +- .../boot/dts/zhihe/a210-platform-evb.dtsi | 48 ++-- arch/riscv/boot/dts/zhihe/a210-soc-core.dtsi | 14 +- arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi | 33 +-- arch/riscv/configs/a210_evb_defconfig | 16 +- drivers/ata/libahci.c | 12 + drivers/ata/libata-core.c | 1 + drivers/pci/controller/dwc/pcie-zh.c | 68 +----- drivers/phy/synopsys/Kconfig | 9 + drivers/phy/synopsys/Makefile | 1 + drivers/phy/synopsys/phy-dw-e16.c | 231 ++++++++++++++++++ 11 files changed, 314 insertions(+), 125 deletions(-) create mode 100644 drivers/phy/synopsys/phy-dw-e16.c diff --git a/arch/riscv/boot/dts/zhihe/a210-evb.dts b/arch/riscv/boot/dts/zhihe/a210-evb.dts index 84ce5f7c1..a22077f9c 100644 --- a/arch/riscv/boot/dts/zhihe/a210-evb.dts +++ b/arch/riscv/boot/dts/zhihe/a210-evb.dts @@ -353,7 +353,7 @@ }; sata_p1_pins: sata_p1-0 { sata_p1-pins { - pins = "GPIO0_14", "GPIO0_15", "GPIO0_16", "GPIO0_17", "GPIO0_18"; + pins = "GPIO0_14", "GPIO0_15", "GPIO0_16", "GPIO0_17", "GPIO1_5"; // DEVSLP, MP_SWITCH, CP_DET, CP_POD, ACT_LED function = "sata_p1"; bias-disable; drive-strength = <7>; @@ -396,7 +396,7 @@ }; sata_p0_pins: sata_p0-0 { sata_p0-pins { - pins = "GPIO0_19", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23"; + pins = "GPIO0_19", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23"; // DEVSLP, MP_SWITCH, CP_DET, CP_POD, ACT_LED function = "sata_p0"; bias-disable; drive-strength = <7>; @@ -493,7 +493,7 @@ }; pcie_x1_pins: pcie_x1-1 { pcie_x1-pins { - pins = "GPIO0_24", "GPIO0_25", "GPIO0_26", "GPIO0_27"; + pins = "GPIO0_24", "GPIO0_25", "GPIO0_26", "GPIO0_27"; // BTN_RSTN, LKREQN, PERSTN, WAKEN function = "pcie_x1"; bias-disable; drive-strength = <7>; diff --git a/arch/riscv/boot/dts/zhihe/a210-platform-evb.dtsi b/arch/riscv/boot/dts/zhihe/a210-platform-evb.dtsi index 0e67fa250..b35477fdf 100644 --- a/arch/riscv/boot/dts/zhihe/a210-platform-evb.dtsi +++ b/arch/riscv/boot/dts/zhihe/a210-platform-evb.dtsi @@ -3,33 +3,33 @@ // status = "disabled"; }; -// &c908_1 { -// status = "disabled"; -// }; +&c908_1 { + status = "disabled"; +}; -// &c908_2 { -// status = "disabled"; -// }; +&c908_2 { + status = "disabled"; +}; -// &c908_3 { -// status = "disabled"; -// }; +&c908_3 { + status = "disabled"; +}; -// &c920_4 { -// status = "disabled"; -// }; +&c920_4 { + status = "disabled"; +}; -// &c920_5 { -// status = "disabled"; -// }; +&c920_5 { + status = "disabled"; +}; -// &c920_6 { -// status = "disabled"; -// }; +&c920_6 { + status = "disabled"; +}; -// &c920_7 { -// status = "disabled"; -// }; +&c920_7 { + status = "disabled"; +}; &uart0 { status = "disabled"; @@ -79,6 +79,10 @@ status = "disabled"; }; +&i2c0 { + status = "disabled"; +}; + &i2c1 { status = "disabled"; }; @@ -181,7 +185,7 @@ }; &dm3x4 { - status = "okay"; + status = "disabled"; }; &rp3x1 { diff --git a/arch/riscv/boot/dts/zhihe/a210-soc-core.dtsi b/arch/riscv/boot/dts/zhihe/a210-soc-core.dtsi index 85ec1f998..dfd0f21f0 100644 --- a/arch/riscv/boot/dts/zhihe/a210-soc-core.dtsi +++ b/arch/riscv/boot/dts/zhihe/a210-soc-core.dtsi @@ -741,11 +741,10 @@ power-domains = <&power_top>; #power-domain-cells = <0>; id = ; - clocks = <&clk_pcie E16PHY_PCLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_AUX_CLK_EN>, + clocks = <&clk_pcie PCIE_DM_GEN3X4_AUX_CLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_SLV_ACLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_MST_ACLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_PCLK_EN>; - resets = <&rst PCIE_E16PHY_PHY_RST>, <&rst PCIE_E16PHY_APBS_PRST>, - <&rst PCIE_DM_GEN3X4_APBS_PRST>, <&rst PCIE_DM_GEN3X4_POWER_UP_RST>; + resets = <&rst PCIE_DM_GEN3X4_APBS_PRST>, <&rst PCIE_DM_GEN3X4_POWER_UP_RST>; iopmps = <&device_pcie_0_iopmp>; }; power_pcie1:power_pcie1 { @@ -754,11 +753,10 @@ power-domains = <&power_top>; #power-domain-cells = <0>; id = ; - clocks = <&clk_pcie E16PHY_PCLK_EN>, <&clk_pcie PCIE_RP_GEN3X1_AUX_CLK_EN>, + clocks = <&clk_pcie PCIE_RP_GEN3X1_AUX_CLK_EN>, <&clk_pcie PCIE_RP_GEN3X1_SLV_ACLK_EN>, <&clk_pcie PCIE_RP_GEN3X1_MST_ACLK_EN>, <&clk_pcie PCIE_RP_GEN3X1_PCLK_EN>; - resets = <&rst PCIE_E16PHY_PHY_RST>, <&rst PCIE_E16PHY_APBS_PRST>, - <&rst PCIE_RP_GEN3X1_APBS_PRST>, <&rst PCIE_RP_GEN3X1_POWER_UP_RST>; + resets = <&rst PCIE_RP_GEN3X1_APBS_PRST>, <&rst PCIE_RP_GEN3X1_POWER_UP_RST>; iopmps = <&device_pcie_1_iopmp>; }; power_sata:power_sata { @@ -767,9 +765,9 @@ power-domains = <&power_top>; #power-domain-cells = <0>; id = ; - clocks = <&clk_pcie E16PHY_PCLK_EN>, <&clk_pcie SATA_GEN3X2_ACLK_EN>, <&clk_pcie SATA_PMALIVE_CLK_EN>, + clocks = <&clk_pcie SATA_GEN3X2_ACLK_EN>, <&clk_pcie SATA_PMALIVE_CLK_EN>, <&clk_pcie SATA_RXOOB0_CLK_EN>, <&clk_pcie SATA_RXOOB1_CLK_EN>; - resets = <&rst PCIE_E16PHY_PHY_RST>, <&rst PCIE_E16PHY_APBS_PRST>, <&rst PCIE_SATA_ARESET>, + resets = <&rst PCIE_SATA_ARESET>, <&rst PCIE_SATA_RST_PMALIVE>, <&rst PCIE_SATA_RST_ASIC0>, <&rst PCIE_SATA_RST_ASIC1>, <&rst PCIE_SATA_RST_RXOOB0>, <&rst PCIE_SATA_RST_RXOOB1>; iopmps = <&device_sata_0_iopmp>; diff --git a/arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi b/arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi index edb192d03..57fc23a92 100755 --- a/arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi +++ b/arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi @@ -1678,21 +1678,22 @@ status = "okay"; }; - pcie_phy: pcie-phy@32f00000 { - compatible = "fsl,imx8mp-pcie-phy"; - reg = <0x00 0x0A180000 0x0 0x001000>; - power-domains = <&power_pcie0>; + pcie_phy: pcie-phy@a1800000 { + compatible = "zhihe,a210-pcie-phy"; + reg = <0x00 0xa180000 0x0 0x001000>; #phy-cells = <0>; - status = "disabled"; + clocks = <&clk_pcie E16PHY_PCLK_EN>; + clock-names = "e16phy_clk"; + resets = <&rst PCIE_E16PHY_PHY_RST>,<&rst PCIE_E16PHY_APBS_PRST>; + reset-names = "apb", "phy"; }; dm3x4: pcie@b000000 { compatible = "zh,p100-pcie"; reg = <0x00 0x0b000000 0x0 0x800000>, <0x18 0x00000000 0x0 0x200000>, - <0x00 0x0A004000 0x0 0x001000>, - <0x00 0x0A180000 0x0 0x001000>; - reg-names = "dbi","config","pcie_sysreg","phy_sysreg"; + <0x00 0x0A004000 0x0 0x001000>; + reg-names = "dbi","config","pcie_sysreg"; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; @@ -1711,16 +1712,12 @@ <0x0 0x0 0x0 0x3 &intc 142>, <0x0 0x0 0x0 0x4 &intc 143>; zh,max-link-speed = <3>; - clocks = <&clk_pcie E16PHY_PCLK_EN>, - <&clk_pcie PCIE_DM_GEN3X4_AUX_CLK_EN>, + clocks = <&clk_pcie PCIE_DM_GEN3X4_AUX_CLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_SLV_ACLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_MST_ACLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_PCLK_EN>; - clock-names = "e16phy_clk","gen3x4_aux_clk","gen3x4_slv_clk","gen3x4_mst_clk","gen3x4_pclk"; + clock-names = "gen3x4_aux_clk","gen3x4_slv_clk","gen3x4_mst_clk","gen3x4_pclk"; power-domains = <&power_pcie0>; - resets = <&rst PCIE_E16PHY_PHY_RST>, - <&rst PCIE_E16PHY_APBS_PRST>; - reset-names = "pcie-rst", "pcie-prst"; //iommus = <&pcie_dfmu_iommu DEVID_DIE0_PCIE_0>; phys = <&pcie_phy>; phy-names = "pcie-phy"; @@ -1805,10 +1802,10 @@ clocks = <&clk_pcie SATA_PMALIVE_CLK_EN>, <&clk_pcie SATA_RXOOB0_CLK_EN>, <&clk_pcie SATA_GEN3X2_ACLK_EN>; - clock-names = "pmalive", "rxoob", "aclk"; + clock-names = "pmalive", "rxoob", "aclk"; // sata_pmalive_clk, sata_rxoob0_clk, sata_gen3x2_aclk power-domains = <&power_sata>; //iommus = <&iommu DEVID_DIE0_SATA_0>; - ports-implemented = <3>; + ports-implemented = <1>; status = "okay"; sata0: sata-port@0 { @@ -1816,6 +1813,8 @@ hba-port-cap = ; snps,tx-ts-max = <16>; snps,rx-ts-max = <16>; + phys = <&pcie_phy>; + phy-names = "sata-phy"; }; sata1: sata-port@1 { @@ -1823,6 +1822,8 @@ hba-port-cap = ; snps,tx-ts-max = <16>; snps,rx-ts-max = <16>; + phys = <&pcie_phy>; + phy-names = "sata-phy"; }; }; diff --git a/arch/riscv/configs/a210_evb_defconfig b/arch/riscv/configs/a210_evb_defconfig index 1ad61f15d..6ec726a03 100644 --- a/arch/riscv/configs/a210_evb_defconfig +++ b/arch/riscv/configs/a210_evb_defconfig @@ -131,6 +131,8 @@ CONFIG_TH1520_DSMART_CARD=y CONFIG_IO_EVENT_WRAPER=y CONFIG_EEPROM_AT24=y CONFIG_BLK_DEV_SD=m +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y CONFIG_ATA=m CONFIG_AHCI_DWC=m CONFIG_MD=y @@ -339,26 +341,13 @@ CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_MEDIA_TUNER_XC4000 is not set # CONFIG_MEDIA_TUNER_XC5000 is not set CONFIG_DRM=y -CONFIG_DRM_MIPI_DSI=y -CONFIG_DRM_KMS_HELPER=y -CONFIG_DRM_FBDEV_EMULATION=y -CONFIG_DRM_FBDEV_OVERALLOC=100 CONFIG_DRM_LOAD_EDID_FIRMWARE=y -CONFIG_DRM_DISPLAY_HELPER=m -CONFIG_DRM_DISPLAY_DP_HELPER=y -CONFIG_DRM_DISPLAY_HDCP_HELPER=y -CONFIG_DRM_DISPLAY_HDMI_HELPER=y CONFIG_DRM_DP_AUX_CHARDEV=y -CONFIG_DRM_PANEL=y CONFIG_DRM_PANEL_SIMPLE=m CONFIG_DRM_PANEL_ILITEK_ILI9881C=m CONFIG_DRM_PANEL_JADARD_JD9365DA_H3=y CONFIG_DRM_PANEL_LT8911=y -CONFIG_DRM_BRIDGE=y -CONFIG_DRM_PANEL_BRIDGE=y -CONFIG_DRM_DW_HDMI=m CONFIG_DRM_VERISILICON=m -CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y CONFIG_VERISILICON_DW_DP_P100=y CONFIG_ZHIHE_AUXDISP=y CONFIG_FB=y @@ -462,6 +451,7 @@ CONFIG_IIO_SW_DEVICE=y CONFIG_PWM=y CONFIG_PWM_THEAD=y CONFIG_PHY_DW_DPHY=y +CONFIG_PHY_ZHIHE_SNPS_PCIE3=m CONFIG_NVMEM_XUANTIE_TH1520_EFUSE=y CONFIG_NVMEM_ZH_EFUSE=y CONFIG_TEE=m diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index f1263364f..1b5e700c5 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -659,7 +659,10 @@ static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) int offset = ahci_scr_offset(link->ap, sc_reg); if (offset) { + // dma_mb(); *val = readl(port_mmio + offset); + // dev_info(link->ap->dev, "------------------------------------ahci_scr_read: offset 0x%x, val=0x%08x\n", offset, *val); + // dma_mb(); return 0; } return -EINVAL; @@ -671,7 +674,10 @@ static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) int offset = ahci_scr_offset(link->ap, sc_reg); if (offset) { + // dev_info(link->ap->dev, "------------------------------------ahci_scr_write: offset 0x%x, val 0x%08x\n", offset, val); + // dma_mb(); writel(val, port_mmio + offset); + // dma_mb(); return 0; } return -EINVAL; @@ -683,10 +689,14 @@ void ahci_start_engine(struct ata_port *ap) u32 tmp; /* start DMA */ + dma_mb(); tmp = readl(port_mmio + PORT_CMD); tmp |= PORT_CMD_START; writel(tmp, port_mmio + PORT_CMD); + // dma_mb(); readl(port_mmio + PORT_CMD); /* flush */ + // dma_mb(); + // dev_info(ap->dev, "------------------------------------ahci_start_engine\n"); } EXPORT_SYMBOL_GPL(ahci_start_engine); @@ -709,6 +719,7 @@ int ahci_stop_engine(struct ata_port *ap) return -EIO; } + // dma_mb(); tmp = readl(port_mmio + PORT_CMD); /* check if the HBA is idle */ @@ -728,6 +739,7 @@ int ahci_stop_engine(struct ata_port *ap) /* setting HBA to idle */ tmp &= ~PORT_CMD_START; writel(tmp, port_mmio + PORT_CMD); + // dma_mb(); /* wait for engine to stop. This could be as long as 500 msec */ tmp = ata_wait_register(ap, port_mmio + PORT_CMD, diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d8cc1e27a..d7e955686 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4790,6 +4790,7 @@ static void fill_result_tf(struct ata_queued_cmd *qc) qc->result_tf.flags = qc->tf.flags; ap->ops->qc_fill_rtf(qc); + // dma_mb(); } static void ata_verify_xfer(struct ata_queued_cmd *qc) diff --git a/drivers/pci/controller/dwc/pcie-zh.c b/drivers/pci/controller/dwc/pcie-zh.c index 9c254ebd4..acea28e52 100644 --- a/drivers/pci/controller/dwc/pcie-zh.c +++ b/drivers/pci/controller/dwc/pcie-zh.c @@ -30,11 +30,6 @@ #define PCIE_GEN3X4_CTRL_REG 0x00000000 #define PCIE_GEN3X4_DBG_INFO_REG0 0x00000430 -#define E16PHY_GLB_CTRL_REG 0x00000000 -#define E16PHY_SRC_SEL_REG 0x00000004 -#define E16PHY_PROTLCOL_REG 0x00000008 -#define E16PHY_RES_RTURN_REG 0x00000048 - #define PCIE_EXTENDED_REG0 0x00000154 #define PCIE_EXTENDED_REG1 0x00000158 #define PCIE_EXTENDED_REG2 0x0000015c @@ -59,9 +54,6 @@ struct zhihe_pcie { enum dw_pcie_device_mode mode; unsigned int ip_type; void __iomem *cfg_base; - void __iomem *phy_base; - struct reset_control *pcie_rst; - struct reset_control *pcie_prst; struct gpio_desc *pcie_bat_en; struct gpio_desc *pcie_3v3_en; struct gpio_desc *pcie_12v_en; @@ -91,18 +83,6 @@ static inline void zhihe_pcie_cfg_writel(struct zhihe_pcie *pcie, writel(val, pcie->cfg_base + reg); } -static inline int zhihe_pcie_readl_phy(struct zhihe_pcie *pcie, - u32 reg) -{ - return readl(pcie->phy_base + reg); -} - -static inline void zhihe_pcie_writel_phy(struct zhihe_pcie *pcie, - u32 reg, u32 val) -{ - writel(val, pcie->phy_base + reg); -} - static void __maybe_unused zhihe_pcie_ltssm_enable(struct dw_pcie *pci) { struct zhihe_pcie *pcie = to_zhihe_pcie(pci); @@ -144,7 +124,6 @@ static int zhihe_pcie_get_resources(struct platform_device *pdev, struct zhihe_pcie *pcie) { struct resource *res; - static void __iomem *ep16phy_base; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -163,29 +142,6 @@ static int zhihe_pcie_get_resources(struct platform_device *pdev, return dev_err_probe(&pdev->dev, PTR_ERR(pcie->cfg_base), "Failed to get pcie_sysreg resource"); - if (pcie->ip_type == PCIE_X4_TYPE) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_sysreg"); - pcie->phy_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pcie->phy_base)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->phy_base), - "Failed to get phy_sysreg resource"); - ep16phy_base = pcie->phy_base; - } - - if (pcie->ip_type == PCIE_X1_TYPE) - pcie->phy_base = ep16phy_base; - - if (pcie->ip_type == PCIE_X4_TYPE) { - pcie->pcie_rst = devm_reset_control_get_shared(&pdev->dev, "pcie-rst"); - if(IS_ERR(pcie->pcie_rst)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->pcie_rst), - "Failed to get pcie-rst reset"); - pcie->pcie_prst = devm_reset_control_get_shared(&pdev->dev, "pcie-prst"); - if(IS_ERR(pcie->pcie_prst)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->pcie_prst), - "Failed to get pcie-prst reset"); - } - /* Get GPIO descriptors for PCIe power control */ pcie->pcie_bat_en = devm_gpiod_get_optional(&pdev->dev, "pcie-bat-en", GPIOD_OUT_LOW); @@ -251,6 +207,7 @@ static int __maybe_unused zhihe_pcie_phy_init(struct zhihe_pcie *pcie) ret = phy_init(pcie->phy); if (ret < 0) return ret; + dev_info(dev, "phy_init======================================================\n"); ret = phy_power_on(pcie->phy); if (ret) @@ -267,8 +224,6 @@ static void __maybe_unused zhihe_pcie_phy_deinit(struct zhihe_pcie *pcie) static void zhihe_pcie_stop_link(struct dw_pcie *pci) { - struct zhihe_pcie *zhihe_pcie = dev_get_drvdata(pci->dev); - zhihe_pcie_ltssm_disable(pci); } @@ -285,18 +240,7 @@ static int zhihe_pcie_ipctrl_init(struct dw_pcie_rp *pp) /*disable ltssm*/ zhihe_pcie_ltssm_disable(pci); /*enable rp && sata*/ - if (pcie->ip_type == PCIE_X1_TYPE) { - zhihe_pcie_writel_phy(pcie, E16PHY_GLB_CTRL_REG, 0x110101); - zhihe_pcie_writel_phy(pcie, E16PHY_SRC_SEL_REG, 0x1100); - zhihe_pcie_writel_phy(pcie, E16PHY_PROTLCOL_REG, 0x2200); - } - /*phy deassert*/ - if (pcie->ip_type == PCIE_X4_TYPE) { - reset_control_deassert(pcie->pcie_rst); - reset_control_deassert(pcie->pcie_prst); - } - /*resistor tune request && res_ack_in*/ - zhihe_pcie_writel_phy(pcie, E16PHY_RES_RTURN_REG, 0x10001); + if (pcie->ip_type == PCIE_X4_TYPE) { /*cfg x4 lane*/ dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, 0x70120); @@ -428,9 +372,9 @@ static int zhihe_pcie_probe(struct platform_device *pdev) if (ret) return ret; - // ret = zhihe_pcie_phy_init(pcie); - // if (ret) - // return ret; + ret = zhihe_pcie_phy_init(pcie); + if (ret) + return ret; switch (pcie->mode) { case DW_PCIE_RC_TYPE: @@ -455,8 +399,6 @@ static int zhihe_pcie_remove(struct platform_device *pdev) dw_pcie_host_deinit(&pcie->pci.pp); - reset_control_assert(pcie->pcie_rst); - reset_control_assert(pcie->pcie_prst); return 0; } diff --git a/drivers/phy/synopsys/Kconfig b/drivers/phy/synopsys/Kconfig index f55fc284c..6294933f5 100644 --- a/drivers/phy/synopsys/Kconfig +++ b/drivers/phy/synopsys/Kconfig @@ -8,3 +8,12 @@ config PHY_DW_DPHY help Choose this option if you have DesignWare D-PHY in your system. If M is selected, the module will be called dw-dphy. + +config PHY_ZHIHE_SNPS_PCIE3 + tristate "Zhihe Snps PCIe3 PHY Driver" + depends on (ARCH_ZHIHE && OF) || COMPILE_TEST + depends on HAS_IOMEM + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the ZHIHE snps PCIe3 PHY. diff --git a/drivers/phy/synopsys/Makefile b/drivers/phy/synopsys/Makefile index d6e25ea66..63cba317b 100644 --- a/drivers/phy/synopsys/Makefile +++ b/drivers/phy/synopsys/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_PHY_DW_DPHY) += phy-dw-mipi-dphy.o +obj-$(CONFIG_PHY_ZHIHE_SNPS_PCIE3) += phy-dw-e16.o diff --git a/drivers/phy/synopsys/phy-dw-e16.c b/drivers/phy/synopsys/phy-dw-e16.c new file mode 100644 index 000000000..45213d553 --- /dev/null +++ b/drivers/phy/synopsys/phy-dw-e16.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip PCIE3.0 phy driver + * + * Copyright (C) 2022 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register for A210 */ +#define E16PHY_GLB_CTRL_REG 0x00000000 +#define E16PHY_SRC_SEL_REG 0x00000004 +#define E16PHY_PROTLCOL_REG 0x00000008 +#define E16PHY_RES_RTURN_REG 0x00000048 + +/* Register for RK3568 */ +#define GRF_PCIE30PHY_CON1 0x4 +#define GRF_PCIE30PHY_CON6 0x18 +#define GRF_PCIE30PHY_CON9 0x24 +#define GRF_PCIE30PHY_DA_OCM (BIT(15) | BIT(31)) +#define GRF_PCIE30PHY_STATUS0 0x80 +#define GRF_PCIE30PHY_WR_EN (0xf << 16) +#define SRAM_INIT_DONE(reg) (reg & BIT(14)) + +#define RK3568_BIFURCATION_LANE_0_1 BIT(0) + +/* Register for RK3588 */ +#define PHP_GRF_PCIESEL_CON 0x100 +#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0 +#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904 +#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04 +#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0)) + +#define RK3588_BIFURCATION_LANE_0_1 BIT(0) +#define RK3588_BIFURCATION_LANE_2_3 BIT(1) +#define RK3588_LANE_AGGREGATION BIT(2) + +struct zhihe_p3phy_ops; + +struct zhihe_p3phy_priv { + const struct zhihe_p3phy_ops *ops; + void __iomem *mmio; + /* mode: RC, EP */ + int mode; + /* pcie30_phymode: Aggregation, Bifurcation */ + int pcie30_phymode; + struct reset_control *apb_rst; + struct reset_control *phy_rst; + struct phy *phy; + struct clk_bulk_data *clks; + int num_clks; + int num_lanes; + u32 lanes[4]; +}; + +struct zhihe_p3phy_ops { + int (*phy_init)(struct zhihe_p3phy_priv *priv); +}; + +static int zhihe_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct zhihe_p3phy_priv *priv = phy_get_drvdata(phy); + + /* Actually We don't care EP/RC mode, but just record it */ + switch (mode) { + case PHY_MODE_SATA: + priv->mode = PHY_MODE_SATA; + break; + default: + dev_err(&phy->dev, "%s, invalid mode, submode %d\n", __func__, submode); + return -EINVAL; + } + + return 0; +} + +static int zhihe_p3phy_a210_init(struct zhihe_p3phy_priv *priv) +{ + int ret = 0; + + // dev_info(&priv->phy->dev, "%s mmio=%px\n", __func__, priv->mmio); + writel(0x00110101, priv->mmio + 0); + writel(0x00001100, priv->mmio + 4); + writel(0x00002200, priv->mmio + 8); + writel(0x00000011, priv->mmio + 108); + writel(0x00010001, priv->mmio + 48); + // dma_mb(); + + return ret; +} + +static const struct zhihe_p3phy_ops a210_ops = { + .phy_init = zhihe_p3phy_a210_init, +}; + +static int rochchip_p3phy_init(struct phy *phy) +{ + struct zhihe_p3phy_priv *priv = phy_get_drvdata(phy); + int ret; + + ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); + if (ret) { + dev_err(&priv->phy->dev, "failed to enable PCIe bulk clks %d\n", ret); + return ret; + } + udelay(10); + reset_control_assert(priv->apb_rst); + reset_control_assert(priv->phy_rst); + if (priv->ops->phy_init) { + ret = priv->ops->phy_init(priv); + if (ret) { + clk_bulk_disable_unprepare(priv->num_clks, priv->clks); + reset_control_assert(priv->apb_rst); + return ret; + } + } + // reset_control_deassert(priv->apb_rst); + udelay(1); + reset_control_deassert(priv->phy_rst); + + return ret; +} + +static int rochchip_p3phy_exit(struct phy *phy) +{ + struct zhihe_p3phy_priv *priv = phy_get_drvdata(phy); + + clk_bulk_disable_unprepare(priv->num_clks, priv->clks); + reset_control_assert(priv->phy_rst); + reset_control_assert(priv->apb_rst); + + return 0; +} + +static const struct phy_ops rochchip_p3phy_ops = { + .init = rochchip_p3phy_init, + .exit = rochchip_p3phy_exit, + .set_mode = zhihe_p3phy_set_mode, + .owner = THIS_MODULE, +}; + +static int zhihe_p3phy_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct zhihe_p3phy_priv *priv; + struct resource *res; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->mmio)) { + ret = PTR_ERR(priv->mmio); + return ret; + } + dev_info(&pdev->dev, + "E16PHY mapped: phys=%pa, virt=%px, size=%zu\n", + &res->start, priv->mmio, (size_t)resource_size(res)); + + priv->ops = of_device_get_match_data(&pdev->dev); + if (!priv->ops) { + dev_err(dev, "no of match data provided\n"); + return -EINVAL; + } + + priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops); + if (IS_ERR(priv->phy)) { + dev_err(dev, "failed to create combphy\n"); + return PTR_ERR(priv->phy); + } + + priv->apb_rst = devm_reset_control_get_shared(dev, "apb"); + if (IS_ERR(priv->apb_rst)) { + return dev_err_probe(dev, PTR_ERR(priv->apb_rst), + "failed to get apb rst control\n"); + } + if (!priv->apb_rst) + dev_info(dev, "no apb reset control specified\n"); + + priv->phy_rst = devm_reset_control_get_shared(dev, "phy"); + if (IS_ERR(priv->phy_rst)) { + return dev_err_probe(dev, PTR_ERR(priv->phy_rst), + "failed to get phy rst control\n"); + } + if (!priv->phy_rst) + dev_info(dev, "no phy reset control specified\n"); + + priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); + if (priv->num_clks < 1) + return -ENODEV; + + dev_info(dev, "num_clks = %d\n", priv->num_clks); + dev_set_drvdata(dev, priv); + phy_set_drvdata(priv->phy, priv); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id zhihe_p3phy_of_match[] = { + { .compatible = "zhihe,a210-pcie-phy", .data = &a210_ops }, + { }, +}; +MODULE_DEVICE_TABLE(of, zhihe_p3phy_of_match); + +static struct platform_driver zhihe_p3phy_driver = { + .probe = zhihe_p3phy_probe, + .driver = { + .name = "zhihe-snps-pcie3-phy", + .of_match_table = zhihe_p3phy_of_match, + }, +}; +module_platform_driver(zhihe_p3phy_driver); +MODULE_DESCRIPTION("Zhihe Synopsys PCIe 3.0 PHY driver"); +MODULE_LICENSE("GPL");