Pārlūkot izejas kodu

drivers: net: dwc_eth_qos: Add GMAC support for Dubhe

Signed-off-by: Wei Liang Lim <weiliang.lim@starfivetech.com>
Wei Liang Lim 7 mēneši atpakaļ
vecāks
revīzija
569779ec17

+ 57 - 0
arch/riscv/dts/dubhe.dtsi

@@ -33,6 +33,28 @@
 				interrupt-controller;
 			};
 		};
+
+		cpu@1 {
+			compatible = "starfive,dubhe", "riscv";
+			d-cache-block-size = <64>;
+			d-cache-sets = <128>;
+			d-cache-size = <65536>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <512>;
+			i-cache-size = <65536>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv48";
+			reg = <0x1>;
+			riscv,isa = "rv64imafdcbhnv";
+			tlb-split;
+			cpu1_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+			};
+		};
 	};
 
 	soc {
@@ -98,5 +120,40 @@
 			clocks = <&pbus_clk>;
 			status = "disabled";
 		};
+
+		stmmac_axi_setup: stmmac-axi-config {
+			snps,wr_osr_lmt = <0xf>;
+			snps,rd_osr_lmt = <0xf>;
+			snps,blen = <256 128 64 32 0 0 0>;
+		};
+
+		gmac0: gmac0@10100000 {
+			compatible = "starfive,dubhe-eqos-5.20";
+			reg = <0x0 0x10100000 0x0 0x10000>;
+			clock-names = "gtx",
+				"tx",
+				"ptp_ref",
+				"stmmaceth",
+				"pclk",
+				"gtxc";
+			interrupt-parent = <&plic0>;
+			interrupts = <8>, <11>, <12> ;
+			interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
+			max-frame-size = <1500>;
+			phy-mode = "rgmii-id";
+			snps,multicast-filter-bins = <64>;
+			snps,perfect-filter-entries = <128>;
+			rx-fifo-depth = <2048>;
+			tx-fifo-depth = <2048>;
+			snps,fixed-burst;
+			snps,no-pbl-x8;
+			snps,force_thresh_dma_mode;
+			snps,axi-config = <&stmmac_axi_setup>;
+			snps,tso;
+			snps,en-tx-lpi-clockgating;
+			snps,txpbl = <4>;
+			snps,rxpbl = <4>;
+			status = "disabled";
+		};		
 	};
 };

+ 36 - 6
arch/riscv/dts/dubhe_fpga.dts

@@ -27,6 +27,41 @@
 	};
 
 	soc {
+		fpga_2p5mhz_clk: fpga_2p5mhz_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <2500000>;
+		};
+
+		fpga_50mhz_clk: fpga_50mhz_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <50000000>;
+		};
+	};
+};
+
+&gmac0 {
+	status = "okay";
+	phy-mode = "rgmii-id";
+	// clk_csr = <3>;
+	// max-speed = <10>;
+	phy-handle = <&ethernet_phy0>;
+	clocks = <&fpga_2p5mhz_clk>,
+		 <&fpga_2p5mhz_clk>,
+		 <&fpga_2p5mhz_clk>,
+		 <&fpga_50mhz_clk>,
+		 <&fpga_50mhz_clk>,
+		 <&fpga_2p5mhz_clk>;
+
+	mdio0 {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		ethernet_phy0: ethernet-phy@0 {
+			reg = <0>;
+			max-speed = <10>;
+		};
 	};
 };
 
@@ -149,12 +184,7 @@
 
 		qspi_ubootproper_opensbi_blob: blob-ext@2 {
 			filename = "u-boot.itb";
-			offset = <0x22000>;
-		};
-
-		qspi_kernel_blob: blob-ext@3 {
-			filename = "kernel.itb";
-			offset = <0x400000>;
+			offset = <0x42000>;
 		};
 	};
 };

+ 1 - 1
board/starfive/dubhe_fpga/Kconfig

@@ -15,7 +15,7 @@ config SYS_SOC
 config SYS_CONFIG_NAME
 	default "starfive-dubhe-fpga"
 
-config SYS_TEXT_BASE
+config TEXT_BASE
 	default 0x83000000 if SPL
 	default 0x80000000 if !RISCV_SMODE
 	default 0x80200000 if RISCV_SMODE

+ 17 - 2
configs/starfive_dubhe_fpga_defconfig

@@ -48,5 +48,20 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MMC=y
 CONFIG_MMC_SPI=y
 CONFIG_SPL_MMC_SUPPORT=y
-
-
+CONFIG_SYS_LOAD_ADDR=0x84000000
+CONFIG_SPL_BSS_START_ADDR=0x80300000
+CONFIG_SPL_BSS_MAX_SIZE=0x00100000
+CONFIG_SPL_MAX_SIZE=0x00200000
+CONFIG_SYS_MALLOC_LEN=0x00100000
+CONFIG_SYS_BOOTM_LEN=0x04000000
+CONFIG_SYS_SPL_MALLOC_START=0x80400000
+CONFIG_SYS_SPL_MALLOC_SIZE=0x00100000
+CONFIG_SPL_STACK=0x80600000
+CONFIG_SYS_SDRAM_BASE=0x80000000
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80600000
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_PHY_MARVELL=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_STARFIVE=y
+CONFIG_DM_GPIO=y

+ 310 - 0
drivers/net/dwc_eth_qos.c

@@ -346,6 +346,57 @@ err:
 #endif
 }
 
+static int eqos_start_clks_jh7110(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	int ret;
+
+	ret = clk_enable(&eqos->clk_slave_bus);
+	if (ret < 0) {
+		pr_err("clk_enable(clk_slave_bus) failed: %d", ret);
+		goto err;
+	}
+
+	ret = clk_enable(&eqos->clk_master_bus);
+	if (ret < 0) {
+		pr_err("clk_enable(clk_master_bus) failed: %d", ret);
+		goto err_disable_clk_slave_bus;
+	}
+
+	ret = clk_enable(&eqos->clk_ck);
+	if (ret < 0) {
+		pr_err("clk_enable(clk_ck) failed: %d", ret);
+		goto err_disable_clk_master_bus;
+	}
+
+	ret = clk_enable(&eqos->clk_ptp_ref);
+	if (ret < 0) {
+		pr_err("clk_enable(clk_ptp_ref) failed: %d", ret);
+		goto err_disable_clk_gtx;
+	}
+
+	ret = clk_enable(&eqos->clk_tx);
+	if (ret < 0) {
+		pr_err("clk_enable(clk_tx) failed: %d", ret);
+		goto err_disable_clk_ptp_ref;
+	}
+
+	debug("%s: OK\n", __func__);
+	return 0;
+
+err_disable_clk_ptp_ref:
+	clk_disable(&eqos->clk_ptp_ref);
+err_disable_clk_gtx:
+	clk_disable(&eqos->clk_rx);
+err_disable_clk_master_bus:
+	clk_disable(&eqos->clk_master_bus);
+err_disable_clk_slave_bus:
+	clk_disable(&eqos->clk_slave_bus);
+err:
+	debug("%s: FAILED: %d\n", __func__, ret);
+	return ret;
+}
+
 static int eqos_stop_clks_tegra186(struct udevice *dev)
 {
 #ifdef CONFIG_CLK
@@ -380,6 +431,20 @@ static int eqos_stop_clks_stm32(struct udevice *dev)
 	return 0;
 }
 
+static int eqos_stop_clks_jh7110(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+
+	clk_disable(&eqos->clk_tx);
+	clk_disable(&eqos->clk_ptp_ref);
+	clk_disable(&eqos->clk_ck);
+	clk_disable(&eqos->clk_master_bus);
+	clk_disable(&eqos->clk_slave_bus);
+
+	debug("%s: OK\n", __func__);
+	return 0;
+}
+
 static int eqos_start_resets_tegra186(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -419,6 +484,29 @@ static int eqos_start_resets_tegra186(struct udevice *dev)
 	return 0;
 }
 
+#if 0
+static int eqos_start_resets_jh7110(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	int ret;
+
+	ret = reset_deassert_bulk(&eqos->reset_bulk);
+	if (ret < 0) {
+		pr_err("reset_deassert() failed: %d", ret);
+		return ret;
+	}
+
+	ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1);
+	if (ret < 0) {
+		pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret);
+		return ret;
+	}
+
+	debug("%s: OK\n", __func__);
+	return 0;
+}
+#endif
+
 static int eqos_stop_resets_tegra186(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -429,6 +517,16 @@ static int eqos_stop_resets_tegra186(struct udevice *dev)
 	return 0;
 }
 
+static int eqos_stop_resets_jh7110(struct udevice *dev)
+{
+//	struct eqos_priv *eqos = dev_get_priv(dev);
+
+//	reset_assert_bulk(&eqos->reset_bulk);
+//	dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
+
+	return 0;
+}
+
 static int eqos_calibrate_pads_tegra186(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -503,6 +601,16 @@ static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
 #endif
 }
 
+static ulong eqos_get_tick_clk_rate_jh7110(struct udevice *dev)
+{
+	return 4000000;
+}
+
+__weak int jh7110_eqos_txclk_set_rate(unsigned long rate)
+{
+	return 0;
+}
+
 static int eqos_set_full_duplex(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -599,6 +707,36 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev)
 	return 0;
 }
 
+static int eqos_set_tx_clk_speed_jh7110(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	ulong rate;
+	int ret;
+
+	switch (eqos->phy->speed) {
+	case SPEED_1000:
+		rate = 125 * 1000 * 1000;
+		break;
+	case SPEED_100:
+		rate = 25 * 1000 * 1000;
+		break;
+	case SPEED_10:
+		rate = 2.5 * 1000 * 1000;
+		break;
+	default:
+		pr_err("invalid speed %d", eqos->phy->speed);
+		return -EINVAL;
+	}
+
+	ret = jh7110_eqos_txclk_set_rate(rate);
+	if (ret < 0) {
+		pr_err("jh7110 (tx_clk, %lu) failed: %d", rate, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int eqos_adjust_link(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1484,11 +1622,103 @@ err_probe:
 	return ret;
 }
 
+static int eqos_probe_resources_jh7110(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	phy_interface_t interface;
+	int ret;
+
+	interface = eqos->config->interface(dev);
+
+	if (interface == PHY_INTERFACE_MODE_NA) {
+		pr_err("Invalid PHY interface\n");
+		return -EINVAL;
+	}
+
+#if 0
+	ret = reset_get_bulk(dev, &eqos->reset_bulk);
+	if (ret) {
+		pr_err("Can't get reset: %d\n", ret);
+		return ret;
+	}
+
+	ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
+				   &eqos->phy_reset_gpio,
+				   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+	if (ret) {
+		pr_err("gpio_request_by_name(phy reset) failed: %d", ret);
+		goto err_free_reset_eqos;
+	}
+#endif
+	ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
+	if (ret) {
+		pr_err("clk_get_by_name(master_bus) failed: %d", ret);
+		goto err_free_gpio_phy_reset;
+	}
+
+	ret = clk_get_by_name(dev, "pclk", &eqos->clk_slave_bus);
+	if (ret) {
+		pr_err("clk_get_by_name(slave_bus) failed: %d", ret);
+		goto err_free_clk_master_bus;
+	}
+
+	ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref);
+	if (ret) {
+		pr_err("clk_get_by_name(ptp_ref) failed: %d", ret);
+		goto err_free_clk_slave_bus;
+		return ret;
+	}
+
+	ret = clk_get_by_name(dev, "gtx", &eqos->clk_ck);
+	if (ret) {
+		pr_err("clk_get_by_name(gtx) failed: %d", ret);
+		goto err_free_clk_ptp_ref;
+	}
+
+	ret = clk_get_by_name(dev, "tx", &eqos->clk_tx);
+	if (ret) {
+		pr_err("clk_get_by_name(tx) failed: %d", ret);
+		goto err_free_clk_gtx;
+	}
+
+	debug("%s: OK\n", __func__);
+	return 0;
+
+err_free_clk_gtx:
+	clk_free(&eqos->clk_ck);
+err_free_clk_ptp_ref:
+	clk_free(&eqos->clk_ptp_ref);
+err_free_clk_slave_bus:
+	clk_free(&eqos->clk_slave_bus);
+err_free_clk_master_bus:
+	clk_free(&eqos->clk_master_bus);
+err_free_gpio_phy_reset:
+	dm_gpio_free(dev, &eqos->phy_reset_gpio);
+err_free_reset_eqos:
+	reset_free(&eqos->reset_ctl);
+
+	return ret;
+}
+
 static phy_interface_t eqos_get_interface_tegra186(const struct udevice *dev)
 {
 	return PHY_INTERFACE_MODE_MII;
 }
 
+static phy_interface_t eqos_get_interface_jh7110(struct udevice *dev)
+{
+	const char *phy_mode;
+	phy_interface_t interface = PHY_INTERFACE_MODE_NA;
+
+	debug("%s(dev=%p):\n", __func__, dev);
+
+	phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", NULL);
+	if (phy_mode)
+		interface = dev_read_phy_mode(dev);
+
+	return interface;
+}
+
 static int eqos_remove_resources_tegra186(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1527,6 +1757,22 @@ static int eqos_remove_resources_stm32(struct udevice *dev)
 	return 0;
 }
 
+static int eqos_remove_resources_jh7110(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+
+	clk_free(&eqos->clk_tx);
+	clk_free(&eqos->clk_ptp_ref);
+	clk_free(&eqos->clk_ck);
+	clk_free(&eqos->clk_slave_bus);
+	clk_free(&eqos->clk_master_bus);
+	dm_gpio_free(dev, &eqos->phy_reset_gpio);
+	reset_free(&eqos->reset_ctl);
+
+	debug("%s: OK\n", __func__);
+	return 0;
+}
+
 static int eqos_probe(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1699,6 +1945,64 @@ static const struct eqos_config __maybe_unused eqos_stm32_config = {
 	.ops = &eqos_stm32_ops
 };
 
+static struct eqos_ops eqos_dubhe_ops = {
+	.eqos_inval_desc = eqos_inval_desc_generic,
+	.eqos_flush_desc = eqos_flush_desc_generic,
+	.eqos_inval_buffer = eqos_inval_buffer_generic,
+	.eqos_flush_buffer = eqos_flush_buffer_generic,
+	.eqos_probe_resources = eqos_probe_resources_jh7110,
+	.eqos_remove_resources = eqos_null_ops,
+	.eqos_stop_resets = eqos_null_ops,
+	.eqos_start_resets = eqos_null_ops,
+	.eqos_stop_clks = eqos_null_ops,
+	.eqos_start_clks = eqos_null_ops,
+	.eqos_calibrate_pads = eqos_null_ops,
+	.eqos_disable_calibration = eqos_null_ops,	
+	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_jh7110,
+	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_jh7110
+};
+
+#if 0
+static struct eqos_ops eqos_jh7110_ops = {
+	.eqos_inval_desc = eqos_inval_desc_generic,
+	.eqos_flush_desc = eqos_flush_desc_generic,
+	.eqos_inval_buffer = eqos_inval_buffer_generic,
+	.eqos_flush_buffer = eqos_flush_buffer_generic,
+	.eqos_probe_resources = eqos_probe_resources_jh7110,
+	.eqos_remove_resources = eqos_remove_resources_jh7110,
+	.eqos_stop_resets = eqos_stop_resets_jh7110,
+	.eqos_start_resets = eqos_start_resets_jh7110,
+	.eqos_stop_clks = eqos_stop_clks_jh7110,
+	.eqos_start_clks = eqos_start_clks_jh7110,
+	.eqos_calibrate_pads = eqos_null_ops,
+	.eqos_disable_calibration = eqos_null_ops,
+	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_jh7110,
+	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_jh7110
+};
+
+struct eqos_config __maybe_unused eqos_jh7110_config = {
+	.reg_access_always_ok = false,
+	.mdio_wait = 10,
+	.swr_wait = 50,
+	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
+	.axi_bus_width = EQOS_AXI_WIDTH_64,
+	.interface = eqos_get_interface_jh7110,
+	.ops = &eqos_jh7110_ops
+};
+#endif
+
+struct eqos_config __maybe_unused eqos_dubhe_config = {
+	.reg_access_always_ok = false,
+	.mdio_wait = 10,
+	.swr_wait = 50,
+	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
+	.axi_bus_width = EQOS_AXI_WIDTH_64,
+	.interface = eqos_get_interface_jh7110,
+	.ops = &eqos_dubhe_ops
+};
+
 static const struct udevice_id eqos_ids[] = {
 #if IS_ENABLED(CONFIG_DWC_ETH_QOS_TEGRA186)
 	{
@@ -1726,11 +2030,17 @@ static const struct udevice_id eqos_ids[] = {
 	},
 #endif
 #if IS_ENABLED(CONFIG_DWC_ETH_QOS_STARFIVE)
+#if 0
 	{
 		.compatible = "starfive,jh7110-dwmac",
 		.data = (ulong)&eqos_jh7110_config
 	},
 #endif
+	{
+		.compatible = "starfive,dubhe-eqos-5.20",
+		.data = (ulong)&eqos_dubhe_config
+	},
+#endif
 
 	{ }
 };

+ 4 - 0
drivers/net/dwc_eth_qos.h

@@ -83,7 +83,11 @@ struct eqos_mac_regs {
 #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT			16
 #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT			8
 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35			2
+#if CONFIG_IS_ENABLED(STARFIVE_JH7110)
+#define EQOS_MAC_MDIO_ADDRESS_CR_250_300		9
+#else
 #define EQOS_MAC_MDIO_ADDRESS_CR_250_300		5
+#endif
 #define EQOS_MAC_MDIO_ADDRESS_SKAP			BIT(4)
 #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT			2
 #define EQOS_MAC_MDIO_ADDRESS_GOC_READ			3

+ 0 - 11
include/configs/starfive-dubhe-fpga.h

@@ -1,16 +1,5 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#define CONFIG_SPL_MAX_SIZE		0x00200000
-#define CONFIG_SPL_BSS_START_ADDR	0x80300000
-#define CONFIG_SPL_BSS_MAX_SIZE		0x00100000
-#define CONFIG_SYS_SPL_MALLOC_START	0x80400000
-#define CONFIG_SYS_SPL_MALLOC_SIZE	0x00100000
-#define CONFIG_SPL_STACK		0x80600000
 
-#define CONFIG_SYS_SDRAM_BASE		0x80000000
-#define CONFIG_SYS_INIT_SP_ADDR		0x80600000
-#define CONFIG_SYS_LOAD_ADDR		0x84000000
-#define CONFIG_SYS_MALLOC_LEN		0x00100000
-#define CONFIG_SYS_BOOTM_LEN		0x04000000
 #endif /* __CONFIG_H */