mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 05:54:26 -04:00 
			
		
		
		
	Copy config and patches from kernel 5.10 to kernel 5.15 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
		
			
				
	
	
		
			296 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			296 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 5654ec78dd7e64b1e04777b24007344329e6a63b Mon Sep 17 00:00:00 2001
 | |
| From: Ansuel Smith <ansuelsmth@gmail.com>
 | |
| Date: Thu, 14 Oct 2021 00:39:11 +0200
 | |
| Subject: net: dsa: qca8k: rework rgmii delay logic and scan for cpu port 6
 | |
| 
 | |
| Future proof commit. This switch have 2 CPU ports and one valid
 | |
| configuration is first CPU port set to sgmii and second CPU port set to
 | |
| rgmii-id. The current implementation detects delay only for CPU port
 | |
| zero set to rgmii and doesn't count any delay set in a secondary CPU
 | |
| port. Drop the current delay scan function and move it to the sgmii
 | |
| parser function to generalize and implicitly add support for secondary
 | |
| CPU port set to rgmii-id. Introduce new logic where delay is enabled
 | |
| also with internal delay binding declared and rgmii set as PHY mode.
 | |
| 
 | |
| Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
 | |
| Signed-off-by: David S. Miller <davem@davemloft.net>
 | |
| ---
 | |
|  drivers/net/dsa/qca8k.c | 165 ++++++++++++++++++++++++------------------------
 | |
|  drivers/net/dsa/qca8k.h |  10 ++-
 | |
|  2 files changed, 89 insertions(+), 86 deletions(-)
 | |
| 
 | |
| --- a/drivers/net/dsa/qca8k.c
 | |
| +++ b/drivers/net/dsa/qca8k.c
 | |
| @@ -889,68 +889,6 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
 | |
|  }
 | |
|  
 | |
|  static int
 | |
| -qca8k_setup_of_rgmii_delay(struct qca8k_priv *priv)
 | |
| -{
 | |
| -	struct device_node *port_dn;
 | |
| -	phy_interface_t mode;
 | |
| -	struct dsa_port *dp;
 | |
| -	u32 val;
 | |
| -
 | |
| -	/* CPU port is already checked */
 | |
| -	dp = dsa_to_port(priv->ds, 0);
 | |
| -
 | |
| -	port_dn = dp->dn;
 | |
| -
 | |
| -	/* Check if port 0 is set to the correct type */
 | |
| -	of_get_phy_mode(port_dn, &mode);
 | |
| -	if (mode != PHY_INTERFACE_MODE_RGMII_ID &&
 | |
| -	    mode != PHY_INTERFACE_MODE_RGMII_RXID &&
 | |
| -	    mode != PHY_INTERFACE_MODE_RGMII_TXID) {
 | |
| -		return 0;
 | |
| -	}
 | |
| -
 | |
| -	switch (mode) {
 | |
| -	case PHY_INTERFACE_MODE_RGMII_ID:
 | |
| -	case PHY_INTERFACE_MODE_RGMII_RXID:
 | |
| -		if (of_property_read_u32(port_dn, "rx-internal-delay-ps", &val))
 | |
| -			val = 2;
 | |
| -		else
 | |
| -			/* Switch regs accept value in ns, convert ps to ns */
 | |
| -			val = val / 1000;
 | |
| -
 | |
| -		if (val > QCA8K_MAX_DELAY) {
 | |
| -			dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
 | |
| -			val = 3;
 | |
| -		}
 | |
| -
 | |
| -		priv->rgmii_rx_delay = val;
 | |
| -		/* Stop here if we need to check only for rx delay */
 | |
| -		if (mode != PHY_INTERFACE_MODE_RGMII_ID)
 | |
| -			break;
 | |
| -
 | |
| -		fallthrough;
 | |
| -	case PHY_INTERFACE_MODE_RGMII_TXID:
 | |
| -		if (of_property_read_u32(port_dn, "tx-internal-delay-ps", &val))
 | |
| -			val = 1;
 | |
| -		else
 | |
| -			/* Switch regs accept value in ns, convert ps to ns */
 | |
| -			val = val / 1000;
 | |
| -
 | |
| -		if (val > QCA8K_MAX_DELAY) {
 | |
| -			dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
 | |
| -			val = 3;
 | |
| -		}
 | |
| -
 | |
| -		priv->rgmii_tx_delay = val;
 | |
| -		break;
 | |
| -	default:
 | |
| -		return 0;
 | |
| -	}
 | |
| -
 | |
| -	return 0;
 | |
| -}
 | |
| -
 | |
| -static int
 | |
|  qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv)
 | |
|  {
 | |
|  	u32 mask = 0;
 | |
| @@ -996,19 +934,21 @@ static int qca8k_find_cpu_port(struct ds
 | |
|  static int
 | |
|  qca8k_parse_port_config(struct qca8k_priv *priv)
 | |
|  {
 | |
| +	int port, cpu_port_index = 0, ret;
 | |
|  	struct device_node *port_dn;
 | |
|  	phy_interface_t mode;
 | |
|  	struct dsa_port *dp;
 | |
| -	int port, ret;
 | |
| +	u32 delay;
 | |
|  
 | |
|  	/* We have 2 CPU port. Check them */
 | |
| -	for (port = 0; port < QCA8K_NUM_PORTS; port++) {
 | |
| +	for (port = 0; port < QCA8K_NUM_PORTS && cpu_port_index < QCA8K_NUM_CPU_PORTS; port++) {
 | |
|  		/* Skip every other port */
 | |
|  		if (port != 0 && port != 6)
 | |
|  			continue;
 | |
|  
 | |
|  		dp = dsa_to_port(priv->ds, port);
 | |
|  		port_dn = dp->dn;
 | |
| +		cpu_port_index++;
 | |
|  
 | |
|  		if (!of_device_is_available(port_dn))
 | |
|  			continue;
 | |
| @@ -1017,12 +957,54 @@ qca8k_parse_port_config(struct qca8k_pri
 | |
|  		if (ret)
 | |
|  			continue;
 | |
|  
 | |
| -		if (mode == PHY_INTERFACE_MODE_SGMII) {
 | |
| +		switch (mode) {
 | |
| +		case PHY_INTERFACE_MODE_RGMII:
 | |
| +		case PHY_INTERFACE_MODE_RGMII_ID:
 | |
| +		case PHY_INTERFACE_MODE_RGMII_TXID:
 | |
| +		case PHY_INTERFACE_MODE_RGMII_RXID:
 | |
| +			delay = 0;
 | |
| +
 | |
| +			if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay))
 | |
| +				/* Switch regs accept value in ns, convert ps to ns */
 | |
| +				delay = delay / 1000;
 | |
| +			else if (mode == PHY_INTERFACE_MODE_RGMII_ID ||
 | |
| +				 mode == PHY_INTERFACE_MODE_RGMII_TXID)
 | |
| +				delay = 1;
 | |
| +
 | |
| +			if (delay > QCA8K_MAX_DELAY) {
 | |
| +				dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
 | |
| +				delay = 3;
 | |
| +			}
 | |
| +
 | |
| +			priv->rgmii_tx_delay[cpu_port_index] = delay;
 | |
| +
 | |
| +			delay = 0;
 | |
| +
 | |
| +			if (!of_property_read_u32(port_dn, "rx-internal-delay-ps", &delay))
 | |
| +				/* Switch regs accept value in ns, convert ps to ns */
 | |
| +				delay = delay / 1000;
 | |
| +			else if (mode == PHY_INTERFACE_MODE_RGMII_ID ||
 | |
| +				 mode == PHY_INTERFACE_MODE_RGMII_RXID)
 | |
| +				delay = 2;
 | |
| +
 | |
| +			if (delay > QCA8K_MAX_DELAY) {
 | |
| +				dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
 | |
| +				delay = 3;
 | |
| +			}
 | |
| +
 | |
| +			priv->rgmii_rx_delay[cpu_port_index] = delay;
 | |
| +
 | |
| +			break;
 | |
| +		case PHY_INTERFACE_MODE_SGMII:
 | |
|  			if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge"))
 | |
|  				priv->sgmii_tx_clk_falling_edge = true;
 | |
|  
 | |
|  			if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge"))
 | |
|  				priv->sgmii_rx_clk_falling_edge = true;
 | |
| +
 | |
| +			break;
 | |
| +		default:
 | |
| +			continue;
 | |
|  		}
 | |
|  	}
 | |
|  
 | |
| @@ -1059,10 +1041,6 @@ qca8k_setup(struct dsa_switch *ds)
 | |
|  	if (ret)
 | |
|  		return ret;
 | |
|  
 | |
| -	ret = qca8k_setup_of_rgmii_delay(priv);
 | |
| -	if (ret)
 | |
| -		return ret;
 | |
| -
 | |
|  	ret = qca8k_setup_mac_pwr_sel(priv);
 | |
|  	if (ret)
 | |
|  		return ret;
 | |
| @@ -1229,8 +1207,8 @@ qca8k_phylink_mac_config(struct dsa_swit
 | |
|  			 const struct phylink_link_state *state)
 | |
|  {
 | |
|  	struct qca8k_priv *priv = ds->priv;
 | |
| -	u32 reg, val;
 | |
| -	int ret;
 | |
| +	int cpu_port_index, ret;
 | |
| +	u32 reg, val, delay;
 | |
|  
 | |
|  	switch (port) {
 | |
|  	case 0: /* 1st CPU port */
 | |
| @@ -1242,6 +1220,7 @@ qca8k_phylink_mac_config(struct dsa_swit
 | |
|  			return;
 | |
|  
 | |
|  		reg = QCA8K_REG_PORT0_PAD_CTRL;
 | |
| +		cpu_port_index = QCA8K_CPU_PORT0;
 | |
|  		break;
 | |
|  	case 1:
 | |
|  	case 2:
 | |
| @@ -1260,6 +1239,7 @@ qca8k_phylink_mac_config(struct dsa_swit
 | |
|  			return;
 | |
|  
 | |
|  		reg = QCA8K_REG_PORT6_PAD_CTRL;
 | |
| +		cpu_port_index = QCA8K_CPU_PORT6;
 | |
|  		break;
 | |
|  	default:
 | |
|  		dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
 | |
| @@ -1274,23 +1254,40 @@ qca8k_phylink_mac_config(struct dsa_swit
 | |
|  
 | |
|  	switch (state->interface) {
 | |
|  	case PHY_INTERFACE_MODE_RGMII:
 | |
| -		/* RGMII mode means no delay so don't enable the delay */
 | |
| -		qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
 | |
| -		break;
 | |
|  	case PHY_INTERFACE_MODE_RGMII_ID:
 | |
|  	case PHY_INTERFACE_MODE_RGMII_TXID:
 | |
|  	case PHY_INTERFACE_MODE_RGMII_RXID:
 | |
| -		/* RGMII_ID needs internal delay. This is enabled through
 | |
| -		 * PORT5_PAD_CTRL for all ports, rather than individual port
 | |
| -		 * registers
 | |
| +		val = QCA8K_PORT_PAD_RGMII_EN;
 | |
| +
 | |
| +		/* Delay can be declared in 3 different way.
 | |
| +		 * Mode to rgmii and internal-delay standard binding defined
 | |
| +		 * rgmii-id or rgmii-tx/rx phy mode set.
 | |
| +		 * The parse logic set a delay different than 0 only when one
 | |
| +		 * of the 3 different way is used. In all other case delay is
 | |
| +		 * not enabled. With ID or TX/RXID delay is enabled and set
 | |
| +		 * to the default and recommended value.
 | |
| +		 */
 | |
| +		if (priv->rgmii_tx_delay[cpu_port_index]) {
 | |
| +			delay = priv->rgmii_tx_delay[cpu_port_index];
 | |
| +
 | |
| +			val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) |
 | |
| +			       QCA8K_PORT_PAD_RGMII_TX_DELAY_EN;
 | |
| +		}
 | |
| +
 | |
| +		if (priv->rgmii_rx_delay[cpu_port_index]) {
 | |
| +			delay = priv->rgmii_rx_delay[cpu_port_index];
 | |
| +
 | |
| +			val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) |
 | |
| +			       QCA8K_PORT_PAD_RGMII_RX_DELAY_EN;
 | |
| +		}
 | |
| +
 | |
| +		/* Set RGMII delay based on the selected values */
 | |
| +		qca8k_write(priv, reg, val);
 | |
| +
 | |
| +		/* QCA8337 requires to set rgmii rx delay for all ports.
 | |
| +		 * This is enabled through PORT5_PAD_CTRL for all ports,
 | |
| +		 * rather than individual port registers.
 | |
|  		 */
 | |
| -		qca8k_write(priv, reg,
 | |
| -			    QCA8K_PORT_PAD_RGMII_EN |
 | |
| -			    QCA8K_PORT_PAD_RGMII_TX_DELAY(priv->rgmii_tx_delay) |
 | |
| -			    QCA8K_PORT_PAD_RGMII_RX_DELAY(priv->rgmii_rx_delay) |
 | |
| -			    QCA8K_PORT_PAD_RGMII_TX_DELAY_EN |
 | |
| -			    QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
 | |
| -		/* QCA8337 requires to set rgmii rx delay */
 | |
|  		if (priv->switch_id == QCA8K_ID_QCA8337)
 | |
|  			qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
 | |
|  				    QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
 | |
| --- a/drivers/net/dsa/qca8k.h
 | |
| +++ b/drivers/net/dsa/qca8k.h
 | |
| @@ -13,6 +13,7 @@
 | |
|  #include <linux/gpio.h>
 | |
|  
 | |
|  #define QCA8K_NUM_PORTS					7
 | |
| +#define QCA8K_NUM_CPU_PORTS				2
 | |
|  #define QCA8K_MAX_MTU					9000
 | |
|  
 | |
|  #define PHY_ID_QCA8327					0x004dd034
 | |
| @@ -255,13 +256,18 @@ struct qca8k_match_data {
 | |
|  	u8 id;
 | |
|  };
 | |
|  
 | |
| +enum {
 | |
| +	QCA8K_CPU_PORT0,
 | |
| +	QCA8K_CPU_PORT6,
 | |
| +};
 | |
| +
 | |
|  struct qca8k_priv {
 | |
|  	u8 switch_id;
 | |
|  	u8 switch_revision;
 | |
| -	u8 rgmii_tx_delay;
 | |
| -	u8 rgmii_rx_delay;
 | |
|  	bool sgmii_rx_clk_falling_edge;
 | |
|  	bool sgmii_tx_clk_falling_edge;
 | |
| +	u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
 | |
| +	u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
 | |
|  	bool legacy_phy_port_mapping;
 | |
|  	struct regmap *regmap;
 | |
|  	struct mii_bus *bus;
 |