diff --git a/arch/riscv/boot/dts/zhihe/a210-dev.dts b/arch/riscv/boot/dts/zhihe/a210-dev.dts index 7924f238b..cf4d714c3 100755 --- a/arch/riscv/boot/dts/zhihe/a210-dev.dts +++ b/arch/riscv/boot/dts/zhihe/a210-dev.dts @@ -990,11 +990,6 @@ &rp3x1 { pinctrl-names = "default"; pinctrl-0 = <&pcie_x1_pins>; - minipcie-1v5-pwren-gpios = <&aw9535_0 6 GPIO_ACTIVE_HIGH>; - minipcie-3v3-pwren-gpios = <&aw9535_0 7 GPIO_ACTIVE_HIGH>; - minipcie-perst-gpios = <&aw9535_0 15 GPIO_ACTIVE_HIGH>; - pcie-clk-en-gpios = <&aw9535_0 12 GPIO_ACTIVE_HIGH>; - pcie-clk-pwren-gpios = <&aw9535_1 13 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -1066,9 +1061,12 @@ wakeup-source; }; -&usb20_zhihe { - usb21-pwren-gpios = <&aw9535_1 8 GPIO_ACTIVE_HIGH>; - usb20-pwren-gpios = <&aw9535_1 9 GPIO_ACTIVE_HIGH>; +&usb2phy0 { + pwren-gpios = <&aw9535_1 8 GPIO_ACTIVE_HIGH>; +}; + +&usb2phy1 { + pwren-gpios = <&aw9535_1 9 GPIO_ACTIVE_HIGH>; }; &usb3 { @@ -1078,11 +1076,18 @@ }; &sata { - m2-sata-3v3-pwren-gpios = <&aw9535_0 14 GPIO_ACTIVE_HIGH>; - m2-sata-en-gpios = <&aw9535_0 9 GPIO_ACTIVE_HIGH>; - sata-clk-en-gpios = <&aw9535_0 12 GPIO_ACTIVE_HIGH>; - sata-clk-pwren-gpios = <&aw9535_1 13 GPIO_ACTIVE_HIGH>; - status = "disabled"; + status = "okay"; +}; + +&e16phy { + init-seq-select = "pcie_dmx1_rpx1_satax2"; + base-en-gpios = <&aw9535_0 12 GPIO_ACTIVE_HIGH>, // pcie-clk, sata-clk + <&aw9535_1 13 GPIO_ACTIVE_HIGH>; // pcie-clk-pwren, sata-clk-pwren + sata-en-gpios = <&aw9535_0 14 GPIO_ACTIVE_HIGH>, // m2-sata-3v3-pwren + <&aw9535_0 9 GPIO_ACTIVE_HIGH>; // m2-sata-en + pcie-en-gpios = <&aw9535_0 6 GPIO_ACTIVE_HIGH>, // minipcie-1v5-pwren + <&aw9535_0 7 GPIO_ACTIVE_HIGH>, // minipcie-3v3-pwren + <&aw9535_0 15 GPIO_ACTIVE_HIGH>; // minipcie-perst }; &mipi0_csi0 { diff --git a/arch/riscv/boot/dts/zhihe/a210-evb.dts b/arch/riscv/boot/dts/zhihe/a210-evb.dts index f500ed132..1ec1489db 100644 --- a/arch/riscv/boot/dts/zhihe/a210-evb.dts +++ b/arch/riscv/boot/dts/zhihe/a210-evb.dts @@ -1305,13 +1305,6 @@ clock-frequency = <400000>; }; -&dm3x4 { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_x4_pins>; - num-lanes = <1>; - status = "okay"; -}; - &uart2 { pinctrl-names = "default"; pinctrl-0 = <&uart2_pins>; @@ -1468,9 +1461,20 @@ &rp3x1 { pinctrl-names = "default"; pinctrl-0 = <&pcie_x1_pins>; + status = "disabled"; +}; + +&dm3x4 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_x4_pins>; + num-lanes = <1>; status = "okay"; }; +&e16phy { + init-seq-select = "pcie_dmx1_rpx1_satax2"; +}; + /* expansion IO: i2c2-0 Conflict with: sata_p0 diff --git a/arch/riscv/boot/dts/zhihe/a210-platform-evb.dtsi b/arch/riscv/boot/dts/zhihe/a210-platform-evb.dtsi index 37f0bd1f6..138130f80 100644 --- a/arch/riscv/boot/dts/zhihe/a210-platform-evb.dtsi +++ b/arch/riscv/boot/dts/zhihe/a210-platform-evb.dtsi @@ -78,10 +78,6 @@ status = "okay"; }; -&i2c0 { - status = "disabled"; -}; - &i2c1 { status = "disabled"; }; diff --git a/arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi b/arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi index 847a397b8..48394a427 100755 --- a/arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi +++ b/arch/riscv/boot/dts/zhihe/a210-soc-peri.dtsi @@ -1414,44 +1414,66 @@ }; }; - usb20_zhihe: usb20_zhihe@08300000 { - compatible = "zhihe,usb20"; - reg = <0x00 0x8300000 0x0 0x2000>; - reg-names = "usb20-blk-sysreg"; - resets = <&rst USB_USB20_BLK_USB0_PHY_PON_RESET>, - <&rst USB_USB20_BLK_USB1_PHY_PON_RESET>; - reset-names = "usb0-phy-rst", "usb1-phy-rst"; + usb2phy0: phy@08300000 { + compatible = "zhihe,a210-usb2-phy"; + reg = <0x00 0x8300000 0x0 0x001000>; #address-cells = <2>; #size-cells = <2>; - ranges; + reg-names = "usb20-blk-sysreg"; + resets = <&rst USB_USB20_BLK_USB0_PHY_PON_RESET>; + reset-names = "usb-phy-rst"; + #phy-cells = <0>; + power-domains = <&power_usb>; + }; - usb2_0: dwc2@8200000 { - compatible = "zhihe,p100-usb"; - reg = <0x00 0x8200000 0x0 0x40000>; - interrupt-parent = <&intc>; - interrupts = <181>; - reg-shift = <2>; - reg-io-width = <4>; - maximum-speed = "high-speed"; - dr_mode = "host"; - power-domains = <&power_usb>; - // iommus = <&iommu DEVID_DIE0_USB2_0>; - snps,need-phy-for-wake; - }; + usb2phy1: phy@08301000 { + compatible = "zhihe,a210-usb2-phy"; + reg = <0x00 0x8301000 0x0 0x001000>; + #address-cells = <2>; + #size-cells = <2>; + reg-names = "usb20-blk-sysreg"; + resets = <&rst USB_USB20_BLK_USB1_PHY_PON_RESET>; + reset-names = "usb-phy-rst"; + #phy-cells = <0>; + power-domains = <&power_usb>; + }; - usb2_1: dwc2@8240000 { - compatible = "zhihe,p100-usb"; - reg = <0x00 0x8240000 0x0 0x40000>; - interrupt-parent = <&intc>; - interrupts = <182>; - reg-shift = <2>; - reg-io-width = <4>; - maximum-speed = "high-speed"; - dr_mode = "host"; - power-domains = <&power_usb>; - // iommus = <&iommu DEVID_DIE0_USB2_1>; - snps,need-phy-for-wake; - }; + usb2_0: dwc2@8200000 { + compatible = "zhihe,a210-usb", "snps,dwc2"; + reg = <0x00 0x8200000 0x0 0x40000>; + interrupt-parent = <&intc>; + interrupts = <181>; + reg-shift = <2>; + reg-io-width = <4>; + g-np-tx-fifo-size = <16>; + g-rx-fifo-size = <275>; + g-tx-fifo-size = <256 128 128 64 64 32>; + maximum-speed = "high-speed"; + dr_mode = "host"; + power-domains = <&power_usb>; + // iommus = <&iommu DEVID_DIE0_USB2_0>; + snps,need-phy-for-wake; + phys = <&usb2phy0>; + phy-names = "usb"; + }; + + usb2_1: dwc2@8240000 { + compatible = "zhihe,a210-usb", "snps,dwc2"; + reg = <0x00 0x8240000 0x0 0x40000>; + interrupt-parent = <&intc>; + interrupts = <182>; + reg-shift = <2>; + reg-io-width = <4>; + g-np-tx-fifo-size = <16>; + g-rx-fifo-size = <275>; + g-tx-fifo-size = <256 128 128 64 64 32>; + maximum-speed = "high-speed"; + dr_mode = "host"; + power-domains = <&power_usb>; + // iommus = <&iommu DEVID_DIE0_USB2_1>; + snps,need-phy-for-wake; + phys = <&usb2phy1>; + phy-names = "usb"; }; audio_pdm0: audio_pdm0@0002008000 { @@ -1603,22 +1625,22 @@ <0x108 0x00000011>, <0x048 0x00010001>; /* PCIE_DMx2,SATA_x2 */ - init-seq-pcie_dmx2_sata_x2 = /bits/ 32 <0x000 0x00110001>, + init-seq-pcie_dmx2_satax2 = /bits/ 32 <0x000 0x00110001>, <0x004 0x00001100>, <0x008 0x00002200>, <0x108 0x00000011>, <0x048 0x00010001>; /* PCIE_DMx1,PCIE_RPx1,SATA_x2 */ - init-seq-pcie_dmx1_rpx1_sata_x2 = /bits/ 32 <0x000 0x00110101>, + init-seq-pcie_dmx1_rpx1_satax2 = /bits/ 32 <0x000 0x00110101>, <0x004 0x00001100>, <0x008 0x00002200>, <0x108 0x00000011>, <0x048 0x00010001>; - init-seq-select = "pcie_dmx1_rpx1_sata_x2"; + init-seq-select = "pcie_dmx4"; }; dm3x4: pcie@b000000 { - compatible = "zh,p100-pcie"; + compatible = "zhihe,a210-pcie"; reg = <0x00 0x0b000000 0x0 0x800000>, <0x18 0x00000000 0x0 0x200000>, <0x00 0x0A004000 0x0 0x001000>; @@ -1631,7 +1653,6 @@ ranges = <0x81000000 0x18 0x00200000 0x18 0x00200000 0x0 0x600000>, <0x82000000 0x00 0x40100000 0x00 0x40100000 0x0 0x800000>, <0xc3000000 0x18 0x00300000 0x18 0x00300000 0x0 0x800000>; - num-lanes = <4>; interrupts = <139>,<140>,<141>,<142>,<143>; interrupt-names = "msi","inta","intb","intc","intd"; interrupt-parent = <&intc>; @@ -1640,7 +1661,6 @@ <0x0 0x0 0x0 0x2 &intc 141>, <0x0 0x0 0x0 0x3 &intc 142>, <0x0 0x0 0x0 0x4 &intc 143>; - zh,max-link-speed = <3>; 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>, @@ -1650,15 +1670,16 @@ //iommus = <&iommu DEVID_DIE0_PCIE_0>; phys = <&e16phy>; phy-names = "pcie-phy"; + num-lanes = <4>; + max-link-speed = <3>; }; rp3x1: pcie@b800000 { - compatible = "zh,p100-pcie"; + compatible = "zhihe,a210-pcie"; reg = <0x00 0x0b800000 0x0 0x800000>, <0x1E 0x00000000 0x0 0x20000>, - <0x00 0x0A005000 0x0 0x001000>, - <0x00 0x0A180000 0x0 0x001000>; - reg-names = "dbi","config","pcie_sysreg","phy_sysreg"; + <0x00 0x0A005000 0x0 0x001000>; + reg-names = "dbi","config","pcie_sysreg"; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; @@ -1667,7 +1688,6 @@ ranges = <0x81000000 0x1E 0x00200000 0x1E 0x00200000 0x0 0x600000>, <0x82000000 0x00 0x50100000 0x00 0x50100000 0x0 0x800000>, <0xc3000000 0x1E 0x00300000 0x1E 0x00300000 0x0 0x800000>; - num-lanes = <1>; interrupts = <158>,<159>,<160>,<161>,<162>; interrupt-names = "msi","inta","intb","intc","intd"; interrupt-parent = <&intc>; @@ -1676,7 +1696,6 @@ <0x0 0x0 0x0 0x2 &intc 160>, <0x0 0x0 0x0 0x3 &intc 161>, <0x0 0x0 0x0 0x4 &intc 162>; - zh,max-link-speed = <3>; 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>, @@ -1686,6 +1705,8 @@ //iommus = <&iommu DEVID_DIE0_PCIE_1>; phys = <&e16phy>; phy-names = "pcie-phy"; + num-lanes = <1>; + max-link-speed = <3>; }; mbox_920: mbox@0000310000 { @@ -2059,7 +2080,7 @@ }; bmu4: usb-bmu@0008024000 { - compatible = "zhihe,p100-usb-bmu"; + compatible = "zhihe,a210-usb-bmu"; reg = <0x00 0x08024000 0x0 0x400>; zhihe,bm-num = <1>; zhihe,bm-name ="bmu_usb"; diff --git a/arch/riscv/configs/a210_evb_defconfig b/arch/riscv/configs/a210_evb_defconfig index 7cb7b821c..dc8f7a139 100644 --- a/arch/riscv/configs/a210_evb_defconfig +++ b/arch/riscv/configs/a210_evb_defconfig @@ -339,26 +339,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 @@ -463,6 +450,7 @@ CONFIG_PWM=y CONFIG_PWM_THEAD=y CONFIG_PHY_DW_DPHY=y CONFIG_PHY_ZHIHE_SNPS_PCIE3=m +CONFIG_PHY_ZHIHE_SNPS_USB2=m CONFIG_NVMEM_XUANTIE_TH1520_EFUSE=y CONFIG_NVMEM_ZH_EFUSE=y CONFIG_TEE=m diff --git a/drivers/pci/controller/dwc/pcie-zh.c b/drivers/pci/controller/dwc/pcie-zh.c index 910a661fe..ced97ca87 100644 --- a/drivers/pci/controller/dwc/pcie-zh.c +++ b/drivers/pci/controller/dwc/pcie-zh.c @@ -1,14 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 /* - * PCIe RC driver for zh P100 + * PCIe RC driver for A210 * - * Copyright (C) 2025 zh computing, Inc. + * Copyright (C) 2025 zhihe computing, Inc. * - * Author: Ya.Huang */ #include #include -#include #include #include #include @@ -19,12 +17,23 @@ #include #include #include -#include #include "pcie-designware.h" -#define PCIE_GEN3X4_CTRL_REG 0x00000000 -#define PCIE_GEN3X4_DBG_INFO_REG0 0x00000430 +#define APP_PCIE_GEN3X4_CTRL_REG 0x000 +#define DEVICE_TYPE_EP 0 +#define DEVICE_TYPE_RP BIT(2) +#define DEVICE_TYPE_SYSREG BIT(4) +#define APP_LTSSM_ENABLE BIT(8) +#define APP_DEVICE_TYPE_MASK GENMASK(3, 0) + +#define APP_PCIE_GEN3X4_LINK_STS_REG 0x034 +#define RDLH_LINK_UP BIT(0) +#define SMLH_LINK_UP BIT(4) +#define SMLH_LTSM_STATE_MASK GENMASK(25, 20) +#define SMLH_LTSM_S_L0 BIT(20) | BIT(24) + +#define APP_PCIE_GEN3X4_DBG_INFO_REG0 0x430 #define PCIE_EXTENDED_REG0 0x00000154 #define PCIE_EXTENDED_REG1 0x00000158 @@ -43,21 +52,12 @@ #define DEVICE_CONTROL_DEVICE_STATUS 0x00000078 #define LINK_CONTROL2_LINK_STATUS2_REG 0x000000a0 -#define LINK_UP_IS_OK 0x11 - struct zhihe_pcie { - struct dw_pcie pci; - enum dw_pcie_device_mode mode; - void __iomem *cfg_base; - struct gpio_desc *pcie_bat_en; - struct gpio_desc *pcie_3v3_en; - struct gpio_desc *pcie_12v_en; - struct gpio_desc *pcie_clk_en; - struct gpio_desc *minipcie_1v5_pwren; - struct gpio_desc *minipcie_3v3_pwren; - struct gpio_desc *minipcie_perst; - struct gpio_desc *pcie_clk_pwren; - struct phy *phy; + struct dw_pcie pci; + enum dw_pcie_device_mode mode; + void __iomem *app_base; + struct phy *phy; + u32 cap_base; }; #define to_zhihe_pcie(x) (struct zhihe_pcie*)dev_get_drvdata((x)->dev) @@ -66,51 +66,88 @@ struct zhihe_pcie_of_data { enum dw_pcie_device_mode mode; }; -static inline int zhihe_pcie_cfg_readl(struct zhihe_pcie *pcie, u32 reg) +static void pcie_update_bits(void __iomem *base, u32 ofs, u32 mask, u32 val) { - return readl(pcie->cfg_base + reg); + u32 old; + + old = readl(base + ofs); + val = (old & ~mask) | (val & mask); + + if (val != old) + writel(val, base + ofs); } -static inline void zhihe_pcie_cfg_writel(struct zhihe_pcie *pcie, - u32 reg, u32 val) +static inline int pcie_app_rd(struct zhihe_pcie *pcie, u32 reg) { - writel(val, pcie->cfg_base + reg); + return readl(pcie->app_base + reg); } -static void __maybe_unused zhihe_pcie_ltssm_enable(struct dw_pcie *pci) +static inline void pcie_app_wr(struct zhihe_pcie *pcie, u32 reg, u32 val) { - struct zhihe_pcie *pcie = to_zhihe_pcie(pci); - writel(0x1114, pcie->cfg_base + PCIE_GEN3X4_CTRL_REG); + writel(val, pcie->app_base + reg); } -static void __maybe_unused zhihe_pcie_ltssm_disable(struct dw_pcie *pci) +static void pcie_app_wr_mask(struct zhihe_pcie *pcie, u32 ofs, + u32 mask, u32 val) { - struct zhihe_pcie *pcie = to_zhihe_pcie(pci); - writel(0x1014, pcie->cfg_base + PCIE_GEN3X4_CTRL_REG); + pcie_update_bits(pcie->app_base, ofs, mask, val); } -static void zhihe_pcie_wait_linkup(struct zhihe_pcie *pcie) +static void __maybe_unused pcie_dump_mmio(struct device *dev, void __iomem *start, + unsigned int bytes) { - u32 ltssm_stat = 0; - unsigned long cnt = 0; - unsigned int TIME_OUT_CNT = 20; - unsigned int DELAY_MS = 50; + unsigned int b, w, o, offset = 0; + unsigned char linebuf[38]; + + for (b = 0; b < bytes;) { + for (w = 0, o = 0; b < bytes && w < 4; w++) { + o += scnprintf(linebuf + o, sizeof(linebuf) - o, + "%08x ", readl(start + b)); + b += sizeof(u32); + } + dev_info(dev, "%03x: %s\n", offset, linebuf); + offset += w * sizeof(u32); + } +} + +static void zhihe_pcie_set_device_type(struct zhihe_pcie *pcie, u32 type) +{ + pcie_app_wr_mask(pcie, APP_PCIE_GEN3X4_CTRL_REG, + DEVICE_TYPE_SYSREG | APP_DEVICE_TYPE_MASK, + DEVICE_TYPE_SYSREG | type); +} + +static void zhihe_pcie_ltssm_enable(struct zhihe_pcie *pcie) +{ + pcie_app_wr_mask(pcie, APP_PCIE_GEN3X4_CTRL_REG, APP_LTSSM_ENABLE, APP_LTSSM_ENABLE); +} + +static void zhihe_pcie_ltssm_disable(struct zhihe_pcie *pcie) +{ + pcie_app_wr_mask(pcie, APP_PCIE_GEN3X4_CTRL_REG, APP_LTSSM_ENABLE, 0); +} + +static int zhihe_pcie_wait_linkup(struct zhihe_pcie *pcie) +{ + u32 ltssm_stat; + int count = 20; do { - mdelay(DELAY_MS); - ltssm_stat = zhihe_pcie_cfg_readl(pcie, \ - PCIE_GEN3X4_DBG_INFO_REG0); - ltssm_stat &= 0x3f; - if (ltssm_stat == LINK_UP_IS_OK) { + ltssm_stat = pcie_app_rd(pcie, APP_PCIE_GEN3X4_LINK_STS_REG); + if (ltssm_stat && (SMLH_LTSM_S_L0 | SMLH_LINK_UP | RDLH_LINK_UP)) { dev_info(pcie->pci.dev, "ltssm:link up ok!\n"); break; } - if (cnt > TIME_OUT_CNT) { - dev_err(pcie->pci.dev, "ltssm_stat = 0x%x,link up fail!\n",ltssm_stat); - break; - } - cnt++; - } while (ltssm_stat != LINK_UP_IS_OK); + mdelay(50); + } while (count--); + + if (count < 0) { + dev_err(pcie->pci.dev, "ltssm_stat = 0x%x,link up fail!\n",ltssm_stat); + pcie_dump_mmio(pcie->pci.dev, pcie->app_base, 0x490); + return -ETIMEDOUT; + } + + return 0; } @@ -126,60 +163,11 @@ static int zhihe_pcie_get_resources(struct platform_device *pdev, } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie_sysreg"); - pcie->cfg_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pcie->cfg_base)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->cfg_base), + pcie->app_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pcie->app_base)) + return dev_err_probe(&pdev->dev, PTR_ERR(pcie->app_base), "Failed to get pcie_sysreg resource"); - /* Get GPIO descriptors for PCIe power control */ - pcie->pcie_bat_en = devm_gpiod_get_optional(&pdev->dev, - "pcie-bat-en", GPIOD_OUT_LOW); - if (IS_ERR(pcie->pcie_bat_en)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->pcie_bat_en), - "Failed to get pcie-bat-en GPIO"); - - pcie->pcie_3v3_en = devm_gpiod_get_optional(&pdev->dev, - "pcie-3v3-en", GPIOD_OUT_LOW); - if (IS_ERR(pcie->pcie_3v3_en)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->pcie_3v3_en), - "Failed to get pcie-3v3-en GPIO"); - - pcie->pcie_12v_en = devm_gpiod_get_optional(&pdev->dev, - "pcie-12v-en", GPIOD_OUT_LOW); - if (IS_ERR(pcie->pcie_12v_en)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->pcie_12v_en), - "Failed to get pcie-12v-en GPIO"); - - pcie->pcie_clk_en = devm_gpiod_get_optional(&pdev->dev, - "pcie-clk-en", GPIOD_OUT_LOW); - if (IS_ERR(pcie->pcie_clk_en)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->pcie_clk_en), - "Failed to get pcie-clk-en GPIO"); - - pcie->minipcie_1v5_pwren = devm_gpiod_get_optional(&pdev->dev, - "minipcie-1v5-pwren", GPIOD_OUT_LOW); - if (IS_ERR(pcie->minipcie_1v5_pwren)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->minipcie_1v5_pwren), - "Failed to get minipcie-1v5-pwren GPIO"); - - pcie->minipcie_3v3_pwren = devm_gpiod_get_optional(&pdev->dev, - "minipcie-3v3-pwren", GPIOD_OUT_LOW); - if (IS_ERR(pcie->minipcie_3v3_pwren)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->minipcie_3v3_pwren), - "Failed to get minipcie-3v3-pwren GPIO"); - - pcie->minipcie_perst = devm_gpiod_get_optional(&pdev->dev, - "minipcie-perst", GPIOD_OUT_LOW); - if (IS_ERR(pcie->minipcie_perst)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->minipcie_perst), - "Failed to get minipcie-perst GPIO"); - - pcie->pcie_clk_pwren = devm_gpiod_get_optional(&pdev->dev, - "pcie-clk-pwren", GPIOD_OUT_LOW); - if (IS_ERR(pcie->pcie_clk_pwren)) - return dev_err_probe(&pdev->dev, PTR_ERR(pcie->pcie_clk_pwren), - "Failed to get pcie-clk-pwren GPIO"); - return 0; } @@ -194,9 +182,15 @@ static int __maybe_unused zhihe_pcie_phy_init(struct zhihe_pcie *pcie) "missing PHY\n"); ret = phy_init(pcie->phy); - if (ret < 0) + if (ret) return ret; + ret = phy_set_mode_ext(pcie->phy, PHY_MODE_PCIE, pcie->mode); + if (ret) { + phy_exit(pcie->phy); + return ret; + } + ret = phy_power_on(pcie->phy); if (ret) phy_exit(pcie->phy); @@ -210,102 +204,79 @@ static void __maybe_unused zhihe_pcie_phy_deinit(struct zhihe_pcie *pcie) phy_power_off(pcie->phy); } +static int zhihe_pcie_start_link(struct dw_pcie *pci) +{ + struct zhihe_pcie *pcie = to_zhihe_pcie(pci); + zhihe_pcie_ltssm_enable(pcie); + return zhihe_pcie_wait_linkup(pcie); +} + static void zhihe_pcie_stop_link(struct dw_pcie *pci) { - zhihe_pcie_ltssm_disable(pci); + struct zhihe_pcie *pcie = to_zhihe_pcie(pci); + zhihe_pcie_ltssm_disable(pcie); } static const struct dw_pcie_ops dw_pcie_ops = { + .start_link = zhihe_pcie_start_link, .stop_link = zhihe_pcie_stop_link, }; -static int zhihe_pcie_ipctrl_init(struct dw_pcie_rp *pp) +static int zhihe_pcie_host_init(struct dw_pcie_rp *pp) { u32 val; struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct zhihe_pcie *pcie = to_zhihe_pcie(pci); + int ret = zhihe_pcie_phy_init(pcie); + if (ret) + return ret; + /*disable ltssm*/ - zhihe_pcie_ltssm_disable(pci); + zhihe_pcie_ltssm_disable(pcie); + /* Set RP mode */ + zhihe_pcie_set_device_type(pcie, DEVICE_TYPE_RP); + + if (!pcie->cap_base) + pcie->cap_base = dw_pcie_find_capability(&pcie->pci, PCI_CAP_ID_EXP); + + /* Disable BARs for inbound access */ + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0); + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0); + + /* Configure Max lane width from DT */ + dw_pcie_dbi_ro_wr_en(pci); + val = dw_pcie_readl_dbi(pci, pcie->cap_base + PCI_EXP_LNKCAP); + val &= ~PCI_EXP_LNKCAP_MLW; + val |= (pci->num_lanes << PCI_EXP_LNKSTA_NLW_SHIFT); + dw_pcie_writel_dbi(pci, pcie->cap_base + PCI_EXP_LNKCAP, val); + dw_pcie_dbi_ro_wr_dis(pci); val = dw_pcie_readl_dbi(pci, PCIE_PORT_LANE_SKEW); val &= ~PORT_LANE_SKEW_INSERT_MASK; - if(pci->num_lanes == 4) { - val |= BIT(27) | BIT(28); - } + if (pci->num_lanes < 4) + val |= BIT(6); dw_pcie_writel_dbi(pci, PCIE_PORT_LANE_SKEW, val); + val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); + val |= GEN3_RELATED_OFF_EQ_PHASE_2_3; + dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, 0xc020071); - /*ip ctrl cfg*/ - dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS); // 0x2000 - dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, GEN3_RELATED_OFF_EQ_PHASE_2_3 | BIT(11) | GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS); //0x2a00 - dw_pcie_writel_dbi(pci, PCIE_EXTENDED_REG0, 0x21614536); - dw_pcie_writel_dbi(pci, PCIE_EXTENDED_REG1, 0x6337451); - dw_pcie_writel_dbi(pci, PCIE_EXTENDED_REG2, 0x8553824); - dw_pcie_writel_dbi(pci, PCIE_EXTENDED_REG3, 0x47373650); - dw_pcie_writel_dbi(pci, GEN3_EQ_FB_MODE_DIR_CHANGE_OFF, 0x0); - dw_pcie_writel_dbi(pci, DEVICE_CONTROL_DEVICE_STATUS, 0x2130); - /*cfg Gen3*/ - val = dw_pcie_readl_dbi(pci, LINK_CONTROL2_LINK_STATUS2_REG); - val &= 0xfffffff0; - val |= 0x3; - dw_pcie_writel_dbi(pci, LINK_CONTROL2_LINK_STATUS2_REG, val); - - /*config space setup*/ - dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, 0); - dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_1, 0); - - dw_pcie_writel_dbi(pci, TRGT_MAP_CTRL_OFF, 0x40); - dw_pcie_writel_dbi(pci, SEC_STAT_IO_LIMIT_IO_BASE_REG, 0x4f40); - dw_pcie_writel_dbi(pci, IO_LIMIT_UPPER_IO_BASE_UPPER_REG, 0x0); - dw_pcie_writel_dbi(pci, MEM_LIMIT_MEM_BASE_REG, 0xc91fc800); - dw_pcie_writel_dbi(pci, PREF_MEM_LIMIT_PREF_MEM_BASE_REG, 0xfff0); - dw_pcie_writel_dbi(pci, PREF_BASE_UPPER_REG, 0x0); - dw_pcie_writel_dbi(pci, PREF_LIMIT_UPPER_REG, 0x0); - dw_pcie_writel_dbi(pci, TYPE1_STATUS_COMMAND_REG, 0x100007); - /*enable ltssm*/ - zhihe_pcie_ltssm_enable(pci); - zhihe_pcie_wait_linkup(pcie); return 0; } static const struct dw_pcie_host_ops zhihe_pcie_host_ops = { - .host_init = zhihe_pcie_ipctrl_init, + .host_init = zhihe_pcie_host_init, }; -static int zhihe_add_pcie_port(struct zhihe_pcie *pcie, - struct platform_device *pdev) +static int zhihe_add_pcie_port(struct zhihe_pcie *pcie, struct platform_device *pdev) { struct dw_pcie *pci = &pcie->pci; struct dw_pcie_rp *pp = &pci->pp; struct device *dev = &pdev->dev; int ret; - if (pcie->pcie_bat_en) - gpiod_set_value(pcie->pcie_bat_en, 1); - - if (pcie->pcie_3v3_en) - gpiod_set_value(pcie->pcie_3v3_en, 1); - - if (pcie->pcie_12v_en) - gpiod_set_value(pcie->pcie_12v_en, 1); - - if (pcie->pcie_clk_en) - gpiod_set_value(pcie->pcie_clk_en, 1); - - if (pcie->minipcie_1v5_pwren) - gpiod_set_value(pcie->minipcie_1v5_pwren, 1); - - if (pcie->minipcie_3v3_pwren) - gpiod_set_value(pcie->minipcie_3v3_pwren, 1); - - if (pcie->minipcie_perst) - gpiod_set_value(pcie->minipcie_perst, 1); - - if (pcie->pcie_clk_pwren) - gpiod_set_value(pcie->pcie_clk_pwren, 1); - pp->irq = platform_get_irq(pdev, 0); if (pp->irq < 0) return pp->irq; @@ -353,10 +324,6 @@ static int zhihe_pcie_probe(struct platform_device *pdev) if (ret) return ret; - ret = zhihe_pcie_phy_init(pcie); - if (ret) - return ret; - switch (pcie->mode) { case DW_PCIE_RC_TYPE: ret = zhihe_add_pcie_port(pcie, pdev); @@ -380,7 +347,6 @@ static int zhihe_pcie_remove(struct platform_device *pdev) dw_pcie_host_deinit(&pcie->pci.pp); - return 0; } @@ -390,7 +356,7 @@ static const struct zhihe_pcie_of_data zhihe_pcie_rc_of_data = { static const struct of_device_id zhihe_pcie_of_match[] = { { - .compatible = "zh,p100-pcie", + .compatible = "zhihe,a210-pcie", .data = &zhihe_pcie_rc_of_data, }, {}, @@ -406,4 +372,6 @@ static struct platform_driver zhihe_pcie_driver = { .remove = zhihe_pcie_remove, }; module_platform_driver(zhihe_pcie_driver); + +MODULE_DEVICE_TABLE(of, zhihe_pcie_of_match); MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 876746442..bc452e057 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -99,6 +99,6 @@ source "drivers/phy/tegra/Kconfig" source "drivers/phy/ti/Kconfig" source "drivers/phy/intel/Kconfig" source "drivers/phy/xilinx/Kconfig" -source "drivers/phy/synopsys/Kconfig" +source "drivers/phy/zhihe/Kconfig" endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 5c9317bb2..184231584 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -37,4 +37,4 @@ obj-y += allwinner/ \ tegra/ \ ti/ \ xilinx/ \ - synopsys/ + zhihe/ diff --git a/drivers/phy/synopsys/Makefile b/drivers/phy/synopsys/Makefile deleted file mode 100644 index 63cba317b..000000000 --- a/drivers/phy/synopsys/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# 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/Kconfig b/drivers/phy/zhihe/Kconfig similarity index 64% rename from drivers/phy/synopsys/Kconfig rename to drivers/phy/zhihe/Kconfig index 6294933f5..1995045fd 100644 --- a/drivers/phy/synopsys/Kconfig +++ b/drivers/phy/zhihe/Kconfig @@ -17,3 +17,13 @@ config PHY_ZHIHE_SNPS_PCIE3 select MFD_SYSCON help Enable this to support the ZHIHE snps PCIe3 PHY. + +config PHY_ZHIHE_SNPS_USB2 + tristate "Zhihe Snps USB2.0 PHY Driver" + depends on (ARCH_ZHIHE && OF) || COMPILE_TEST + depends on HAS_IOMEM + select GENERIC_PHY + help + Enable this to support the ZHIHE Snps USB 2.0 PHY. + This driver provides PHY support for the USB 2.0 controllers + on ZHIHE platforms. diff --git a/drivers/phy/zhihe/Makefile b/drivers/phy/zhihe/Makefile new file mode 100644 index 000000000..cb0f95665 --- /dev/null +++ b/drivers/phy/zhihe/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_PHY_DW_DPHY) += phy-zhihe-snps-mipidsi.o +obj-$(CONFIG_PHY_ZHIHE_SNPS_PCIE3) += phy-zhihe-snps-e16phy.o +obj-$(CONFIG_PHY_ZHIHE_SNPS_USB2) += phy-zhihe-snps-usb2.o diff --git a/drivers/phy/synopsys/phy-dw-e16.c b/drivers/phy/zhihe/phy-zhihe-snps-e16phy.c similarity index 78% rename from drivers/phy/synopsys/phy-dw-e16.c rename to drivers/phy/zhihe/phy-zhihe-snps-e16phy.c index 9e604876a..8f0e2b238 100644 --- a/drivers/phy/synopsys/phy-dw-e16.c +++ b/drivers/phy/zhihe/phy-zhihe-snps-e16phy.c @@ -18,6 +18,7 @@ #include #include #include +#include /* Registers definition for ZHIHE A210 */ #define E16PHY_GLB_CTRL_REG 0x00000000 @@ -75,14 +76,16 @@ struct zhihe_e16phy_priv { int num_clks; struct e16phy_seq *init_seq; int num_init_seq; + struct gpio_descs *base_en; + struct gpio_descs *sata_en; + struct gpio_descs *pcie_en; }; static void e16phy_dump_mmio(struct device *dev, void __iomem *start, unsigned int bytes) { - unsigned int b, w, o; + unsigned int b, w, o, offset = 0; unsigned char linebuf[38]; - int offset = 0; for (b = 0; b < bytes;) { for (w = 0, o = 0; b < bytes && w < 4; w++) { @@ -91,7 +94,7 @@ static void e16phy_dump_mmio(struct device *dev, void __iomem *start, b += sizeof(u32); } dev_info(dev, "%03x: %s\n", offset, linebuf); - offset += b; + offset += w * sizeof(u32); } } @@ -158,9 +161,42 @@ static int zhihe_e16phy_exit(struct phy *phy) return 0; } +static void zhihe_e16phy_gpio_set_value(struct gpio_descs *gpios, int val) +{ + if (!gpios) + return; + for (int i = 0; i < gpios->ndescs; i++) + gpiod_set_value(gpios->desc[i], val); +} + +static int zhihe_e16phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct zhihe_e16phy_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; + zhihe_e16phy_gpio_set_value(priv->base_en, 1); + zhihe_e16phy_gpio_set_value(priv->sata_en, 1); + break; + case PHY_MODE_PCIE: + priv->mode = PHY_MODE_PCIE; + zhihe_e16phy_gpio_set_value(priv->base_en, 1); + zhihe_e16phy_gpio_set_value(priv->pcie_en, 1); + break; + default: + dev_err(&phy->dev, "%s, invalid mode\n", __func__); + return -EINVAL; + } + + return 0; +} + static const struct phy_ops zhihe_e16phy_ops = { .init = zhihe_e16phy_init, .exit = zhihe_e16phy_exit, + .set_mode = zhihe_e16phy_set_mode, .owner = THIS_MODULE, }; @@ -230,8 +266,24 @@ static int zhihe_e16phy_probe(struct platform_device *pdev) return ret; } - dev_info(dev, "using init sequence: %s (%d entries)\n", - mode_name, priv->num_init_seq); + /* Get base-en-gpios property */ + priv->base_en = devm_gpiod_get_array_optional(&pdev->dev, + "base-en", GPIOD_OUT_LOW); + if (IS_ERR(priv->base_en)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->base_en), + "Failed to get base-en GPIO"); + + priv->pcie_en = devm_gpiod_get_array_optional(&pdev->dev, + "pcie-en", GPIOD_OUT_LOW); + if (IS_ERR(priv->pcie_en)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->pcie_en), + "Failed to get pcie-en GPIO"); + + priv->sata_en = devm_gpiod_get_array_optional(&pdev->dev, + "sata-en", GPIOD_OUT_LOW); + if (IS_ERR(priv->sata_en)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->sata_en), + "Failed to get sata-en GPIO"); dev_set_drvdata(dev, priv); phy_set_drvdata(priv->phy, priv); diff --git a/drivers/phy/synopsys/phy-dw-mipi-dphy.c b/drivers/phy/zhihe/phy-zhihe-snps-mipidsi.c similarity index 100% rename from drivers/phy/synopsys/phy-dw-mipi-dphy.c rename to drivers/phy/zhihe/phy-zhihe-snps-mipidsi.c diff --git a/drivers/phy/zhihe/phy-zhihe-snps-usb2.c b/drivers/phy/zhihe/phy-zhihe-snps-usb2.c new file mode 100644 index 000000000..3d88868bf --- /dev/null +++ b/drivers/phy/zhihe/phy-zhihe-snps-usb2.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * phy-zhihe-snps-femto-v2.c - ZHIHE USB 2.0 PHY driver + * + * Based on PHY operations from dwc2-zhihe.c + * + * Copyright (C) 2025, Anonymous + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* USB20 BLK SYSREG registers */ +#define PHY_ANA_CFG 0x0 +#define PHY_CFG 0x4 + +/* Bit fields */ +#define PHY_DM_PULLDOWN BIT(1) +#define PHY_DP_PULLDOWN BIT(0) + + +/* USB2.0 PHY TxVRefTune Mask */ +#define USB20_PHY_TXVREFTUNE_MASK 0x1E0000 +#define HS_DV_VOLTAGE_LEVEL_POS_16_PER (0xB << 17) + +struct zhihe_usb2_phy { + struct device *dev; + struct phy *phy; + void __iomem *base; + struct reset_control *phy_rst; + struct gpio_desc *pwren; +}; + +static int zhihe_usb2_phy_init(struct phy *phy) +{ + struct zhihe_usb2_phy *zhphy = phy_get_drvdata(phy); + int val; + + /* Set PHY power enable */ + if (zhphy->pwren) + gpiod_set_value(zhphy->pwren, 1); + + /* Deassert PHY reset */ + reset_control_assert(zhphy->phy_rst); + + /* Pull-up the PHY reset */ + val = readl(zhphy->base + PHY_CFG); + val |= PHY_DM_PULLDOWN | PHY_DP_PULLDOWN; + writel(val, zhphy->base + PHY_CFG); + + /* Configure PHY analog - Set TxVRefTune */ + val = readl(zhphy->base + PHY_ANA_CFG); + val &= ~USB20_PHY_TXVREFTUNE_MASK; + val |= HS_DV_VOLTAGE_LEVEL_POS_16_PER; + writel(val, zhphy->base + PHY_ANA_CFG); + + /* Assert PHY reset to complete initialization */ + reset_control_deassert(zhphy->phy_rst); + + return 0; +} + +static int zhihe_usb2_phy_exit(struct phy *phy) +{ + struct zhihe_usb2_phy *zhphy = phy_get_drvdata(phy); + + /* Assert reset to power down PHY */ + reset_control_assert(zhphy->phy_rst); + /* Set PHY power disable */ + if (zhphy->pwren) + gpiod_set_value(zhphy->pwren, 0); + + return 0; +} + +static const struct phy_ops zhihe_usb2_phy_ops = { + .init = zhihe_usb2_phy_init, + .exit = zhihe_usb2_phy_exit, + .owner = THIS_MODULE, +}; + +static int zhihe_usb2_phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct zhihe_usb2_phy *zhphy; + struct phy_provider *phy_provider; + struct phy *generic_phy; + + zhphy = devm_kzalloc(dev, sizeof(*zhphy), GFP_KERNEL); + if (!zhphy) + return -ENOMEM; + + zhphy->dev = dev; + + /* Get USB20 BLK SYSREG base address */ + zhphy->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(zhphy->base)) + return PTR_ERR(zhphy->base); + + /* Get PHY reset control */ + zhphy->phy_rst = devm_reset_control_get_shared(dev, "usb-phy-rst"); + if (IS_ERR(zhphy->phy_rst)) { + dev_err(dev, "failed to get usb-phy-rst: %ld\n", + PTR_ERR(zhphy->phy_rst)); + return PTR_ERR(zhphy->phy_rst); + } + zhphy->pwren = devm_gpiod_get_optional(&pdev->dev, + "pwren", GPIOD_OUT_LOW); + if (IS_ERR(zhphy->pwren)) { + dev_err(&pdev->dev, "Failed to get pwren GPIO\n"); + return PTR_ERR(zhphy->pwren); + } + + /* Create PHY */ + generic_phy = devm_phy_create(dev, NULL, &zhihe_usb2_phy_ops); + if (IS_ERR(generic_phy)) { + dev_err(dev, "failed to create phy: %ld\n", PTR_ERR(generic_phy)); + return PTR_ERR(generic_phy); + } + + zhphy->phy = generic_phy; + dev_set_drvdata(dev, zhphy); + phy_set_drvdata(generic_phy, zhphy); + + /* Register PHY provider */ + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) { + dev_err(dev, "failed to register phy provider: %ld\n", + PTR_ERR(phy_provider)); + return PTR_ERR(phy_provider); + } + + return 0; +} + +static const struct of_device_id zhihe_usb2_phy_of_match[] = { + { .compatible = "zhihe,a210-usb2-phy", }, + { } +}; +MODULE_DEVICE_TABLE(of, zhihe_usb2_phy_of_match); + +static struct platform_driver zhihe_usb2_phy_driver = { + .probe = zhihe_usb2_phy_probe, + .driver = { + .name = "phy-zhihe-snps-femtophy", + .of_match_table = zhihe_usb2_phy_of_match, + }, +}; + +module_platform_driver(zhihe_usb2_phy_driver); + +MODULE_DESCRIPTION("ZHIHE USB 2.0 PHY driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Zhu Guangzhao "); diff --git a/drivers/soc/zhihe/a210-bmu.c b/drivers/soc/zhihe/a210-bmu.c index 1b6e824ce..f9eb4edc7 100644 --- a/drivers/soc/zhihe/a210-bmu.c +++ b/drivers/soc/zhihe/a210-bmu.c @@ -990,7 +990,7 @@ static const struct of_device_id a210_bmu_dt_ids[] = { .data = &bmu3_para_data[BMU_PCIE], }, { - .compatible = "zhihe,p100-usb-bmu", + .compatible = "zhihe,a210-usb-bmu", .data = &bmu3_para_data[BMU_USB], }, { diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig index bca5a1fa1..c13171936 100644 --- a/drivers/usb/dwc2/Kconfig +++ b/drivers/usb/dwc2/Kconfig @@ -1,14 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -config USB_DWC2_ZHIHE - tristate "Zhihe DWC2 Platform" - depends on ARCH_ZHIHE || COMPILE_TEST - default USB_DWC2 - help - Support Zhihe platform with DesignWare Core USB2 IP. - Only the host mode is currently supported. - Say 'Y' or 'M' here if you have one such device. - config USB_DWC2 tristate "DesignWare USB2 DRD Core Support" depends on HAS_DMA diff --git a/drivers/usb/dwc2/Makefile b/drivers/usb/dwc2/Makefile index fc5e5d059..2bcd6945d 100644 --- a/drivers/usb/dwc2/Makefile +++ b/drivers/usb/dwc2/Makefile @@ -19,8 +19,6 @@ ifneq ($(CONFIG_DEBUG_FS),) dwc2-y += debugfs.o endif -obj-$(CONFIG_USB_DWC2_ZHIHE) += dwc2-zhihe.o - # NOTE: The previous s3c-hsotg peripheral mode only driver has been moved to # this location and renamed gadget.c. When building for dynamically linked # modules, dwc2.ko will get built for host mode, peripheral mode, and dual-role diff --git a/drivers/usb/dwc2/dwc2-zhihe.c b/drivers/usb/dwc2/dwc2-zhihe.c deleted file mode 100644 index d314d2553..000000000 --- a/drivers/usb/dwc2/dwc2-zhihe.c +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dwc2-zhihe.c - ZHIHE platform specific glue layer for DWC2 - * - * Inspired by dwc3-zhihe.c and dwc2-platform.c - * - * Copyright (C) 2025, Anonymous - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core.h" -#include "hcd.h" - -/* USB20 BLK SYSREG registers */ -#define USB20_PHY_ANA_CFG 0x0 -#define USB20_PHY_CFG 0x4 -#define USB21_PHY_ANA_CFG 0x1000 -#define USB21_PHY_CFG 0x1004 - -/* Bit fields */ -/* USB20_PHY_CFG */ -#define USB0_PHY_DM_PULLDOWN BIT(1) -#define USB0_PHY_DP_PULLDOWN BIT(0) - -/* USB21_PHY_CFG */ -#define USB1_PHY_DM_PULLDOWN BIT(3) -#define USB1_PHY_DP_PULLDOWN BIT(2) - -/* USB2.0 PHY TxVRefTune Mask */ -#define USB20_PHY_TXVREFTUNE_MASK 0x1E0000 -#define HS_DV_VOLTAGE_LEVEL_POS_16_PER (0xB << 17) - -struct dwc2_zhihe { - struct device *dev; - void __iomem *usb20_blk_sysreg; - struct reset_control *usb0_phy_rst; - struct reset_control *usb1_phy_rst; - struct gpio_desc *usb20_pwren; - struct gpio_desc *usb21_pwren; -}; - -static int dwc2_zhihe_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct dwc2_zhihe *zhihe; - int ret, val; - - if (!np) { - dev_err(dev, "device node not found\n"); - return -ENODEV; - } - - zhihe = devm_kzalloc(dev, sizeof(*zhihe), GFP_KERNEL); - if (!zhihe) - return -ENOMEM; - - platform_set_drvdata(pdev, zhihe); - zhihe->dev = dev; - - /* Get USB20 system registers */ - struct resource *res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "usb20-blk-sysreg"); - if (!res) { - dev_err(dev, "failed to get resource - %ld\n", PTR_ERR(res)); - return PTR_ERR(res); - } - - zhihe->usb20_blk_sysreg = devm_ioremap_resource(dev, res); - if (IS_ERR(zhihe->usb20_blk_sysreg)) { - dev_err(dev, "failed to get iomem - %ld\n", PTR_ERR(zhihe->usb20_blk_sysreg)); - return PTR_ERR(zhihe->usb20_blk_sysreg); - } - - zhihe->usb0_phy_rst = devm_reset_control_get_shared(&pdev->dev, "usb0-phy-rst"); - if (IS_ERR(zhihe->usb0_phy_rst)) - return PTR_ERR(zhihe->usb0_phy_rst); - - zhihe->usb1_phy_rst = devm_reset_control_get_shared(&pdev->dev, "usb1-phy-rst"); - if (IS_ERR(zhihe->usb1_phy_rst)) - return PTR_ERR(zhihe->usb1_phy_rst); - - /* Pull-up the PHY reset */ - val = readl(zhihe->usb20_blk_sysreg + USB20_PHY_CFG); - val |= USB0_PHY_DM_PULLDOWN | USB0_PHY_DP_PULLDOWN; - writel(val, zhihe->usb20_blk_sysreg + USB20_PHY_CFG); - - val = readl(zhihe->usb20_blk_sysreg + USB21_PHY_CFG); - val |= USB1_PHY_DM_PULLDOWN | USB1_PHY_DP_PULLDOWN; - writel(val, zhihe->usb20_blk_sysreg + USB21_PHY_CFG); - - reset_control_deassert(zhihe->usb0_phy_rst); - reset_control_deassert(zhihe->usb1_phy_rst); - - val = readl(zhihe->usb20_blk_sysreg + USB20_PHY_ANA_CFG); - val &= ~USB20_PHY_TXVREFTUNE_MASK; - val |= HS_DV_VOLTAGE_LEVEL_POS_16_PER; - writel(val, zhihe->usb20_blk_sysreg + USB20_PHY_ANA_CFG); - - val = readl(zhihe->usb20_blk_sysreg + USB21_PHY_ANA_CFG); - val &= ~USB20_PHY_TXVREFTUNE_MASK; - val |= HS_DV_VOLTAGE_LEVEL_POS_16_PER; - writel(val, zhihe->usb20_blk_sysreg + USB21_PHY_ANA_CFG); - - reset_control_assert(zhihe->usb0_phy_rst); - reset_control_assert(zhihe->usb1_phy_rst); - - /* Populate child nodes (dwc2 controllers) */ - ret = of_platform_populate(np, NULL, NULL, dev); - if (ret) { - dev_err(dev, "failed to populate child nodes: %d\n", ret); - return ret; - } - - zhihe->usb20_pwren = devm_gpiod_get_optional(&pdev->dev, - "usb20-pwren", - GPIOD_OUT_LOW); - if (IS_ERR(zhihe->usb20_pwren)) { - dev_err(&pdev->dev, "Failed to get usb20-pwren GPIO\n"); - return PTR_ERR(zhihe->usb20_pwren); - } - - zhihe->usb21_pwren = devm_gpiod_get_optional(&pdev->dev, - "usb21-pwren", - GPIOD_OUT_LOW); - if (IS_ERR(zhihe->usb21_pwren)) { - dev_err(&pdev->dev, "Failed to get usb21-pwren GPIO\n"); - return PTR_ERR(zhihe->usb21_pwren); - } - - if (zhihe->usb20_pwren) - gpiod_set_value(zhihe->usb20_pwren, 1); - - if (zhihe->usb21_pwren) - gpiod_set_value(zhihe->usb21_pwren, 1); - - dev_info(dev, "ZHIHE DWC2 glue layer initialized\n"); - return 0; -} - -static int dwc2_zhihe_remove(struct platform_device *pdev) -{ - struct dwc2_zhihe *zhihe = platform_get_drvdata(pdev); - - of_platform_depopulate(zhihe->dev); - return 0; -} - -static const struct of_device_id dwc2_zhihe_of_match[] = { - { .compatible = "zhihe,usb20" }, - { }, -}; -MODULE_DEVICE_TABLE(of, dwc2_zhihe_of_match); - -static struct platform_driver dwc2_zhihe_driver = { - .probe = dwc2_zhihe_probe, - .remove = dwc2_zhihe_remove, - .driver = { - .name = "dwc2-zhihe", - .of_match_table = dwc2_zhihe_of_match, - }, -}; - -module_platform_driver(dwc2_zhihe_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("ZHIHE DWC2 Glue Layer"); -MODULE_AUTHOR("Anonymous "); diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 5f25a9efa..d7a2d4d53 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -136,13 +136,18 @@ static void dwc2_set_zhihe_params(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *p = &hsotg->params; - p->phy_utmi_width = 8; - /* Use INCR4 burst length to prevent AHB ERROR during long-term USB storage operations */ - p->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT; - /* Configure FIFO sizes for stable bulk transfers */ - p->host_rx_fifo_size = 1024; - p->host_nperio_tx_fifo_size = 1024; - p->host_perio_tx_fifo_size = 1024; + p->otg_caps.hnp_support = false; + p->otg_caps.srp_support = false; + p->host_rx_fifo_size = 525; + p->host_nperio_tx_fifo_size = 128; + p->host_perio_tx_fifo_size = 256; + p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << + GAHBCFG_HBSTLEN_SHIFT; + p->power_down = DWC2_POWER_DOWN_PARAM_NONE; + p->lpm = false; + p->lpm_clock_gating = false; + p->besl = false; + p->hird_threshold_en = false; } static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg) @@ -293,7 +298,7 @@ const struct of_device_id dwc2_of_match_table[] = { { .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params }, { .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params }, { .compatible = "snps,dwc2" }, - { .compatible = "zhihe,p100-usb", .data = dwc2_set_zhihe_params }, + { .compatible = "zhihe,a210-usb", .data = dwc2_set_zhihe_params }, { .compatible = "samsung,s3c6400-hsotg", .data = dwc2_set_s3c6400_params }, { .compatible = "amlogic,meson8-usb",