summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei Liang Lim <weiliang.lim@starfivetech.com>2023-10-19 09:36:18 +0300
committerWei Liang Lim <weiliang.lim@starfivetech.com>2023-10-19 09:46:14 +0300
commit569779ec17583d0237e72815299921aec677a84e (patch)
treefe02ed95b99d126587c614ab9de724ecbb97c7e0
parent82942334532223a0e7eefa5a659bcd5454c661ca (diff)
downloadu-boot-569779ec17583d0237e72815299921aec677a84e.tar.xz
drivers: net: dwc_eth_qos: Add GMAC support for Dubhe
Signed-off-by: Wei Liang Lim <weiliang.lim@starfivetech.com>
-rw-r--r--arch/riscv/dts/dubhe.dtsi57
-rw-r--r--arch/riscv/dts/dubhe_fpga.dts42
-rw-r--r--board/starfive/dubhe_fpga/Kconfig2
-rw-r--r--configs/starfive_dubhe_fpga_defconfig19
-rw-r--r--drivers/net/dwc_eth_qos.c310
-rw-r--r--drivers/net/dwc_eth_qos.h4
-rw-r--r--include/configs/starfive-dubhe-fpga.h11
7 files changed, 425 insertions, 20 deletions
diff --git a/arch/riscv/dts/dubhe.dtsi b/arch/riscv/dts/dubhe.dtsi
index f689389c73..3ce659e1e7 100644
--- a/arch/riscv/dts/dubhe.dtsi
+++ b/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";
+ };
};
};
diff --git a/arch/riscv/dts/dubhe_fpga.dts b/arch/riscv/dts/dubhe_fpga.dts
index 56cd3d2a03..5a04f9b6d3 100644
--- a/arch/riscv/dts/dubhe_fpga.dts
+++ b/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>;
};
};
}; \ No newline at end of file
diff --git a/board/starfive/dubhe_fpga/Kconfig b/board/starfive/dubhe_fpga/Kconfig
index 99fe0e8508..6ffeb1a62f 100644
--- a/board/starfive/dubhe_fpga/Kconfig
+++ b/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
diff --git a/configs/starfive_dubhe_fpga_defconfig b/configs/starfive_dubhe_fpga_defconfig
index 519d2c8c04..01864bf666 100644
--- a/configs/starfive_dubhe_fpga_defconfig
+++ b/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
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 1e92bd9ca9..a0ba471365 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/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
{ }
};
diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
index a6b719af80..cb2cc74dfd 100644
--- a/drivers/net/dwc_eth_qos.h
+++ b/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
diff --git a/include/configs/starfive-dubhe-fpga.h b/include/configs/starfive-dubhe-fpga.h
index 86e94ba2fc..e59322ef51 100644
--- a/include/configs/starfive-dubhe-fpga.h
+++ b/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 */