Merge branch '2023-08-15-add-SGMII-support-for-TI-j7200' into next

To quote the author:
This series adds support for SGMII mode to the CPSW driver to enable the
functionality on TI's J7200 SoC.

Supporting SGMII mode also requires changes to the WIZ driver which acts
as a wrapper for the SerDes used by the CPSW MAC to transmit data to the
Ethernet PHY daughtercard mounted on the I2C GPIO Expander 2 connector
on the J7200 EVM.

Powering on and resetting the Ethernet PHY requires MDIO support which
is added to the CPSW driver.

For supporting DMA transactions from the MAIN CPSW instance to the A72
Host on J7200 SoC, the corresponding PSI-L endpoint information is added
for the J721E SoC, which is applicable to J7200 SoC as well.

The SGMII daughtercard used for testing SGMII mode has TI's DP83869 PHY.
Thus, enable the config for DP83869 driver functionality. Also, enable
GPIO HOG config.
diff --git a/configs/j7200_evm_a72_defconfig b/configs/j7200_evm_a72_defconfig
index ad8492a..ba5914d 100644
--- a/configs/j7200_evm_a72_defconfig
+++ b/configs/j7200_evm_a72_defconfig
@@ -114,6 +114,7 @@
 CONFIG_FASTBOOT_FLASH_MMC_DEV=0
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_TI_SCI_PROTOCOL=y
+CONFIG_GPIO_HOG=y
 CONFIG_DA8XX_GPIO=y
 CONFIG_DM_PCA953X=y
 CONFIG_DM_I2C=y
@@ -146,6 +147,7 @@
 CONFIG_SPI_FLASH_MTD=y
 CONFIG_MULTIPLEXER=y
 CONFIG_MUX_MMIO=y
+CONFIG_PHY_TI_DP83869=y
 CONFIG_PHY_FIXED=y
 CONFIG_TI_AM65_CPSW_NUSS=y
 CONFIG_PHY=y
diff --git a/drivers/dma/ti/k3-psil-j721e.c b/drivers/dma/ti/k3-psil-j721e.c
index 105ffd9..8e57e86 100644
--- a/drivers/dma/ti/k3-psil-j721e.c
+++ b/drivers/dma/ti/k3-psil-j721e.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- *  Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
+ *  Copyright (C) 2019-2023 Texas Instruments Incorporated - https://www.ti.com
  *  Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
  */
 
@@ -21,13 +21,15 @@
 
 /* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
 static struct psil_ep j721e_src_ep_map[] = {
-	/* CPSW0 */
+	/* MCU_CPSW0 */
 	PSIL_ETHERNET(0x7000),
+	/* MAIN_CPSW0 */
+	PSIL_ETHERNET(0x4a00),
 };
 
 /* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */
 static struct psil_ep j721e_dst_ep_map[] = {
-	/* CPSW0 */
+	/* MCU_CPSW0 */
 	PSIL_ETHERNET(0xf000),
 	PSIL_ETHERNET(0xf001),
 	PSIL_ETHERNET(0xf002),
@@ -36,6 +38,15 @@
 	PSIL_ETHERNET(0xf005),
 	PSIL_ETHERNET(0xf006),
 	PSIL_ETHERNET(0xf007),
+	/* MAIN_CPSW0 */
+	PSIL_ETHERNET(0xca00),
+	PSIL_ETHERNET(0xca01),
+	PSIL_ETHERNET(0xca02),
+	PSIL_ETHERNET(0xca03),
+	PSIL_ETHERNET(0xca04),
+	PSIL_ETHERNET(0xca05),
+	PSIL_ETHERNET(0xca06),
+	PSIL_ETHERNET(0xca07),
 };
 
 struct psil_ep_map j721e_ep_map = {
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
index 51a8167..f4e5809 100644
--- a/drivers/net/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <malloc.h>
 #include <asm/cache.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <clk.h>
@@ -26,6 +27,7 @@
 #include <soc.h>
 #include <syscon.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/soc/ti/ti-udma.h>
 
 #include "cpsw_mdio.h"
@@ -57,6 +59,12 @@
 #define AM65_CPSW_PN_REG_SA_L			0x308
 #define AM65_CPSW_PN_REG_SA_H			0x30c
 
+#define AM65_CPSW_SGMII_CONTROL_REG             0x010
+#define AM65_CPSW_SGMII_MR_ADV_ABILITY_REG      0x018
+#define AM65_CPSW_SGMII_CONTROL_MR_AN_ENABLE    BIT(0)
+
+#define ADVERTISE_SGMII				0x1
+
 #define AM65_CPSW_ALE_CTL_REG			0x8
 #define AM65_CPSW_ALE_CTL_REG_ENABLE		BIT(31)
 #define AM65_CPSW_ALE_CTL_REG_RESET_TBL		BIT(30)
@@ -90,8 +98,11 @@
 
 #define AM65_CPSW_CPPI_PKT_TYPE			0x7
 
+#define DEFAULT_GPIO_RESET_DELAY		10
+
 struct am65_cpsw_port {
 	fdt_addr_t	port_base;
+	fdt_addr_t	port_sgmii_base;
 	fdt_addr_t	macsl_base;
 	bool		disabled;
 	u32		mac_control;
@@ -113,6 +124,10 @@
 	struct mii_dev		*bus;
 	u32			bus_freq;
 
+	struct gpio_desc	mdio_gpio_reset;
+	u32			reset_delay_us;
+	u32			reset_post_delay_us;
+
 	struct dma		dma_tx;
 	struct dma		dma_rx;
 	u32			rx_next;
@@ -204,6 +219,8 @@
 			mac_control |= AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX;
 		if (phy->speed == 100)
 			mac_control |= AM65_CPSW_MACSL_CTL_REG_IFCTL_A;
+		if (phy->interface == PHY_INTERFACE_MODE_SGMII)
+			mac_control |= AM65_CPSW_MACSL_CTL_EXT_EN;
 	}
 
 	if (mac_control == port->mac_control)
@@ -229,6 +246,7 @@
 #define AM65_GMII_SEL_MODE_MII		0
 #define AM65_GMII_SEL_MODE_RMII		1
 #define AM65_GMII_SEL_MODE_RGMII	2
+#define AM65_GMII_SEL_MODE_SGMII	3
 
 #define AM65_GMII_SEL_RGMII_IDMODE	BIT(4)
 
@@ -280,6 +298,10 @@
 		rgmii_id = true;
 		break;
 
+	case PHY_INTERFACE_MODE_SGMII:
+		mode = AM65_GMII_SEL_MODE_SGMII;
+		break;
+
 	default:
 		dev_warn(dev,
 			 "Unsupported PHY mode: %u. Defaulting to MII.\n",
@@ -420,6 +442,13 @@
 		goto err_dis_rx;
 	}
 
+	if (priv->phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+		writel(ADVERTISE_SGMII,
+		       port->port_sgmii_base + AM65_CPSW_SGMII_MR_ADV_ABILITY_REG);
+		writel(AM65_CPSW_SGMII_CONTROL_MR_AN_ENABLE,
+		       port->port_sgmii_base + AM65_CPSW_SGMII_CONTROL_REG);
+	}
+
 	ret = phy_startup(priv->phydev);
 	if (ret) {
 		dev_err(dev, "phy_startup failed\n");
@@ -658,6 +687,16 @@
 	if (!priv->has_phy || cpsw_common->bus)
 		return 0;
 
+	if (IS_ENABLED(CONFIG_DM_GPIO)) {
+		if (dm_gpio_is_valid(&cpsw_common->mdio_gpio_reset)) {
+			dm_gpio_set_value(&cpsw_common->mdio_gpio_reset, 1);
+			udelay(cpsw_common->reset_delay_us);
+			dm_gpio_set_value(&cpsw_common->mdio_gpio_reset, 0);
+			if (cpsw_common->reset_post_delay_us > 0)
+				udelay(cpsw_common->reset_post_delay_us);
+		}
+	}
+
 	ret = am65_cpsw_mdio_setup(dev);
 	if (ret)
 		return ret;
@@ -797,7 +836,7 @@
 static int am65_cpsw_probe_nuss(struct udevice *dev)
 {
 	struct am65_cpsw_common *cpsw_common = dev_get_priv(dev);
-	ofnode ports_np, node;
+	ofnode ports_np, node, mdio_np;
 	int ret, i;
 	struct udevice *port_dev;
 
@@ -824,6 +863,24 @@
 				AM65_CPSW_CPSW_NU_ALE_BASE;
 	cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE;
 
+	if (IS_ENABLED(CONFIG_DM_GPIO)) {
+		/* get bus level PHY reset GPIO details */
+		mdio_np = dev_read_subnode(dev, "mdio");
+		if (!ofnode_valid(mdio_np)) {
+			ret = -ENOENT;
+			goto out;
+		}
+
+		cpsw_common->reset_delay_us = ofnode_read_u32_default(mdio_np, "reset-delay-us",
+								      DEFAULT_GPIO_RESET_DELAY);
+		cpsw_common->reset_post_delay_us = ofnode_read_u32_default(mdio_np,
+									   "reset-post-delay-us",
+									   0);
+		ret = gpio_request_by_name_nodev(mdio_np, "reset-gpios", 0,
+						 &cpsw_common->mdio_gpio_reset,
+						 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+	}
+
 	ports_np = dev_read_subnode(dev, "ethernet-ports");
 	if (!ofnode_valid(ports_np)) {
 		ret = -ENOENT;
@@ -872,6 +929,8 @@
 		port->port_base = cpsw_common->cpsw_base +
 				  AM65_CPSW_CPSW_NU_PORTS_OFFSET +
 				  (i * AM65_CPSW_CPSW_NU_PORTS_OFFSET);
+		port->port_sgmii_base = cpsw_common->ss_base +
+					(i * AM65_CPSW_SGMII_BASE);
 		port->macsl_base = port->port_base +
 				   AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET;
 	}
diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 34314d0..7261339 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -585,12 +585,20 @@
 
 static int wiz_phy_fullrt_div(struct wiz *wiz, int lane)
 {
-	if (wiz->type != AM64_WIZ_10G)
+	switch (wiz->type) {
+	case AM64_WIZ_10G:
+		if (wiz->lane_phy_type[lane] == PHY_TYPE_PCIE)
+			return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1);
+		break;
+
+	case J721E_WIZ_16G:
+	case J721E_WIZ_10G:
+		if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII)
+			return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2);
+		break;
+	default:
 		return 0;
-
-	if (wiz->lane_phy_type[lane] == PHY_TYPE_PCIE)
-		return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1);
-
+	}
 	return 0;
 }
 
@@ -706,7 +714,8 @@
 	int i;
 
 	for (i = 0; i < num_lanes; i++) {
-		if (wiz->lane_phy_type[i] == PHY_TYPE_QSGMII) {
+		if (wiz->lane_phy_type[i] == PHY_TYPE_SGMII ||
+		    wiz->lane_phy_type[i] == PHY_TYPE_QSGMII) {
 			ret = regmap_field_write(wiz->p_mac_div_sel0[i], 1);
 			if (ret)
 				return ret;