|
@@ -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
|
|
|
|
|
|
{ }
|
|
|
};
|