Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Ansuel/907ac4b51923c006693011a088cb7231 to your computer and use it in GitHub Desktop.
Save Ansuel/907ac4b51923c006693011a088cb7231 to your computer and use it in GitHub Desktop.
From 42d1200ec0ea9f37c31d68207ab1b79e2d85012c Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Mon, 1 Mar 2021 12:17:15 +0100
Subject: [net-next PATCH v3 01/11] net: dsa: qca8k: add support for sgmii
falling edge
Add support for this in the qca8k driver. Also add support for SGMII
rx/tx clock falling edge. This is only present for pad0, pad5 and
pad6 have these bit reserved from Documentation. Add a comment that this
is hardcoded to PAD0 as qca8327/28/34/37 have an unique sgmii line and
setting falling in port0 applies to both configuration with sgmii used
for port0 or port6.
Signed-off-by: Matthew Hagan <mnhagan88@gmail.com>
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/net/dsa/qca8k.c | 25 +++++++++++++++++++++++++
drivers/net/dsa/qca8k.h | 3 +++
2 files changed, 28 insertions(+)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index a892b897cd0d..863eeac6eace 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -1172,6 +1172,7 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
const struct phylink_link_state *state)
{
struct qca8k_priv *priv = ds->priv;
+ struct dsa_port *dp;
u32 reg, val;
int ret;
@@ -1240,6 +1241,8 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
break;
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_1000BASEX:
+ dp = dsa_to_port(ds, port);
+
/* Enable SGMII on the port */
qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN);
@@ -1274,6 +1277,28 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
}
qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val);
+
+ /* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and
+ * falling edge is set writing in the PORT0 PAD reg
+ */
+ if (priv->switch_id == PHY_ID_QCA8327 ||
+ priv->switch_id == PHY_ID_QCA8337)
+ reg = QCA8K_REG_PORT0_PAD_CTRL;
+
+ val = 0;
+
+ /* SGMII Clock phase configuration */
+ if (of_property_read_bool(dp->dn, "qca,sgmii-rxclk-falling-edge"))
+ val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE;
+
+ if (of_property_read_bool(dp->dn, "qca,sgmii-txclk-falling-edge"))
+ val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE;
+
+ if (val)
+ ret = qca8k_rmw(priv, reg,
+ QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE |
+ QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE,
+ val);
break;
default:
dev_err(ds->dev, "xMII mode %s not supported for port %d\n",
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index fc7db94cc0c9..3fded69a6839 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -35,6 +35,9 @@
#define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8)
#define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8)
#define QCA8K_REG_PORT0_PAD_CTRL 0x004
+#define QCA8K_PORT0_PAD_CTRL_MAC06_EXCHG BIT(31)
+#define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19)
+#define QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE BIT(18)
#define QCA8K_REG_PORT5_PAD_CTRL 0x008
#define QCA8K_REG_PORT6_PAD_CTRL 0x00c
#define QCA8K_PORT_PAD_RGMII_EN BIT(26)
--
2.32.0
From 6be042ac44ce9373bf1efc8337d78a8272fd9e55 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Mon, 1 Mar 2021 12:19:56 +0100
Subject: [net-next PATCH v3 02/11] dt-bindings: net: dsa: qca8k: Add MAC swap
and clock phase properties
Add names and descriptions of additional PORT0_PAD_CTRL properties.
qca,sgmii-(rx|tx)clk-falling-edge are for setting the respective clock
phase to failling edge.
Signed-off-by: Matthew Hagan <mnhagan88@gmail.com>
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/qca8k.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
index 8c73f67c43ca..cc214e655442 100644
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -37,6 +37,10 @@ A CPU port node has the following optional node:
managed entity. See
Documentation/devicetree/bindings/net/fixed-link.txt
for details.
+- qca,sgmii-rxclk-falling-edge: Set the receive clock phase to falling edge.
+ Mostly used in qca8327 with CPU port 0 set to
+ sgmii.
+- qca,sgmii-txclk-falling-edge: Set the transmit clock phase to falling edge.
For QCA8K the 'fixed-link' sub-node supports only the following properties:
--
2.32.0
From 5026942f7092825e598618d0248a075cf6b57545 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Sun, 10 Oct 2021 02:18:25 +0200
Subject: [net-next PATCH v3 03/11] drivers: net: dsa: qca8k: add support for
cpu port 6
Currently CPU port is always hardcoded to port 0. This switch have 2 CPU
port. The original intention of this driver seems to be use the
mac06_exchange bit to swap MAC0 with MAC6 in the strange configuration
where device have connected only the CPU port 6. To skip the
introduction of a new binding, rework the driver to address the
secondary CPU port as primary and drop any reference of hardcoded port.
With configuration of mac06 exchange, just skip the definition of port0
and define the CPU port as a secondary. The driver will autoconfigure
the switch to use that as the primary CPU port.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/net/dsa/qca8k.c | 50 +++++++++++++++++++++++++++++------------
drivers/net/dsa/qca8k.h | 2 --
2 files changed, 36 insertions(+), 16 deletions(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 863eeac6eace..91334fa23183 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -977,17 +977,34 @@ qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv)
return ret;
}
+static int qca8k_find_cpu_port(struct dsa_switch *ds)
+{
+ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+
+ /* Find the connected cpu port. Valid port are 0 or 6 */
+ if (dsa_is_cpu_port(ds, 0))
+ return 0;
+
+ dev_dbg(priv->dev, "port 0 is not the CPU port. Checking port 6");
+
+ if (dsa_is_cpu_port(ds, 6))
+ return 6;
+
+ return -EINVAL;
+}
+
static int
qca8k_setup(struct dsa_switch *ds)
{
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ u8 cpu_port;
int ret, i;
u32 mask;
- /* Make sure that port 0 is the cpu port */
- if (!dsa_is_cpu_port(ds, 0)) {
- dev_err(priv->dev, "port 0 is not the CPU port");
- return -EINVAL;
+ cpu_port = qca8k_find_cpu_port(ds);
+ if (cpu_port < 0) {
+ dev_err(priv->dev, "No cpu port configured in both cpu port0 and port6");
+ return cpu_port;
}
mutex_init(&priv->reg_mutex);
@@ -1024,7 +1041,7 @@ qca8k_setup(struct dsa_switch *ds)
dev_warn(priv->dev, "mib init failed");
/* Enable QCA header mode on the cpu port */
- ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
+ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(cpu_port),
QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
if (ret) {
@@ -1046,10 +1063,10 @@ qca8k_setup(struct dsa_switch *ds)
/* Forward all unknown frames to CPU port for Linux processing */
ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
- BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
+ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
+ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
+ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
+ BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
if (ret)
return ret;
@@ -1057,7 +1074,7 @@ qca8k_setup(struct dsa_switch *ds)
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
/* CPU port gets connected to all user ports of the switch */
if (dsa_is_cpu_port(ds, i)) {
- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
+ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port),
QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds));
if (ret)
return ret;
@@ -1069,7 +1086,7 @@ qca8k_setup(struct dsa_switch *ds)
ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
QCA8K_PORT_LOOKUP_MEMBER,
- BIT(QCA8K_CPU_PORT));
+ BIT(cpu_port));
if (ret)
return ret;
@@ -1578,9 +1595,12 @@ static int
qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
{
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
- int port_mask = BIT(QCA8K_CPU_PORT);
+ int port_mask, cpu_port;
int i, ret;
+ cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
+ port_mask = BIT(cpu_port);
+
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
if (dsa_to_port(ds, i)->bridge_dev != br)
continue;
@@ -1607,7 +1627,9 @@ static void
qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
{
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
- int i;
+ int cpu_port, i;
+
+ cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
if (dsa_to_port(ds, i)->bridge_dev != br)
@@ -1624,7 +1646,7 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
* this port
*/
qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
- QCA8K_PORT_LOOKUP_MEMBER, BIT(QCA8K_CPU_PORT));
+ QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
}
static int
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index 3fded69a6839..5df0f0ef6526 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -24,8 +24,6 @@
#define QCA8K_NUM_FDB_RECORDS 2048
-#define QCA8K_CPU_PORT 0
-
#define QCA8K_PORT_VID_DEF 1
/* Global control registers */
--
2.32.0
From 40817ea988c242d473721ef1e5d1d4f429bbb42b Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Sun, 10 Oct 2021 02:36:26 +0200
Subject: [net-next PATCH v3 04/11] dt-bindings: net: dsa: qca8k: Document
support for CPU port 6
The switch now support CPU port to be set 6 instead of be hardcoded to
0. Document support for it and describe logic selection.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/qca8k.txt | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
index cc214e655442..aeb206556f54 100644
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -29,7 +29,11 @@ the mdio MASTER is used as communication.
Don't use mixed external and internal mdio-bus configurations, as this is
not supported by the hardware.
-The CPU port of this switch is always port 0.
+This switch support 2 CPU port. Normally and advised configuration is with
+CPU port set to port 0. It is also possible to set the CPU port to port 6
+if the device requires it. The driver will configure the switch to the defined
+port. With both CPU port declared the first CPU port is selected as primary
+and the secondary CPU ignored.
A CPU port node has the following optional node:
--
2.32.0
From 7158d0a777fca3d54088674daaeb1d58e2c907a6 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Tue, 11 May 2021 23:22:02 +0200
Subject: [net-next PATCH v3 05/11] net: dsa: qca8k: move rgmii delay detection
to phylink mac_config
Future proof commit. This switch have 2 CPU port and one valid
configuration is first CPU port set to sgmii and second CPU port set to
regmii-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 phylink
mac_config to generilize and implicitly add support for secondary CPU
port set to rgmii-id.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/net/dsa/qca8k.c | 121 +++++++++++++++-------------------------
drivers/net/dsa/qca8k.h | 2 -
2 files changed, 44 insertions(+), 79 deletions(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 91334fa23183..043980a5db7f 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -888,68 +888,6 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
return 0;
}
-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)
{
@@ -1019,10 +957,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;
@@ -1190,7 +1124,7 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
{
struct qca8k_priv *priv = ds->priv;
struct dsa_port *dp;
- u32 reg, val;
+ u32 reg, val, delay;
int ret;
switch (port) {
@@ -1241,17 +1175,50 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
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
+ dp = dsa_to_port(ds, port);
+ val = QCA8K_PORT_PAD_RGMII_EN;
+
+ if (state->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ state->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
+ if (of_property_read_u32(dp->dn, "tx-internal-delay-ps", &delay))
+ delay = 1;
+ else
+ /* Switch regs accept value in ns, convert ps to ns */
+ delay = delay / 1000;
+
+ 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;
+ }
+
+ val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) |
+ QCA8K_PORT_PAD_RGMII_TX_DELAY_EN;
+ }
+
+ if (state->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ state->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
+ if (of_property_read_u32(dp->dn, "rx-internal-delay-ps", &delay))
+ delay = 2;
+ else
+ /* Switch regs accept value in ns, convert ps to ns */
+ delay = delay / 1000;
+
+ 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;
+ }
+
+ 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);
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index 5df0f0ef6526..a790b27bc310 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -259,8 +259,6 @@ struct qca8k_match_data {
struct qca8k_priv {
u8 switch_id;
u8 switch_revision;
- u8 rgmii_tx_delay;
- u8 rgmii_rx_delay;
bool legacy_phy_port_mapping;
struct regmap *regmap;
struct mii_bus *bus;
--
2.32.0
From b47ee5dfc30c415a029bc9e83a7bb7882bde4dd7 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Mon, 13 Sep 2021 13:07:21 +0200
Subject: [net-next PATCH v3 06/11] net: dsa: qca8k: add explicit SGMII PLL
enable
Support enabling PLL on the SGMII CPU port. Some device require this
special configuration or no traffic is transmitted and the switch
doesn't work at all. A dedicated binding is added to the CPU node
port to apply the correct reg on mac config.
Fail to correctly configure sgmii with qca8327 switch and warn if pll is
used on qca8337 with a revision greater than 1.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/net/dsa/qca8k.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 043980a5db7f..b73b92ebd72e 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -1245,8 +1245,20 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
if (ret)
return;
- val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
- QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD;
+ val |= QCA8K_SGMII_EN_SD;
+
+ if (of_property_read_bool(dp->dn, "qca,sgmii-enable-pll")) {
+ if (priv->switch_id == QCA8K_ID_QCA8327) {
+ dev_err(priv->dev, "SGMII PLL should NOT be enabled for qca8327. Aborting enabling");
+ return;
+ }
+
+ if (priv->switch_revision < 2)
+ dev_warn(priv->dev, "SGMII PLL should NOT be enabled for qca8337 with revision 2 or more.");
+
+ val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
+ QCA8K_SGMII_EN_TX;
+ }
if (dsa_is_cpu_port(ds, port)) {
/* CPU port, we're talking to the CPU MAC, be a PHY */
--
2.32.0
From 3d174c77551c156f3089b6b8d07cb849ec1b6deb Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Mon, 13 Sep 2021 13:12:46 +0200
Subject: [net-next PATCH v3 07/11] dt-bindings: net: dsa: qca8k: Document
qca,sgmii-enable-pll
Document qca,sgmii-enable-pll binding used in the CPU nodes to
enable SGMII PLL on MAC config.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/qca8k.txt | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
index aeb206556f54..05a8ddfb5483 100644
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -45,6 +45,16 @@ A CPU port node has the following optional node:
Mostly used in qca8327 with CPU port 0 set to
sgmii.
- qca,sgmii-txclk-falling-edge: Set the transmit clock phase to falling edge.
+- qca,sgmii-enable-pll : For SGMII CPU port, explicitly enable PLL, TX and RX
+ chain along with Signal Detection.
+ This should NOT be enabled for qca8327. If enabled with
+ qca8327 the sgmii port won't correctly init and an err
+ is printed.
+ This can be required for qca8337 switch with revision 2.
+ A warning is displayed when used with revision greater
+ 2.
+ With CPU port set to sgmii and qca8337 it is advised
+ to set this unless a communication problem is observed.
For QCA8K the 'fixed-link' sub-node supports only the following properties:
--
2.32.0
From ac168b0da94a77299fda5c843d3aacbfd724e778 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Sun, 19 Sep 2021 14:13:54 +0200
Subject: [net-next PATCH v3 08/11] drivers: net: dsa: qca8k: add support for
pws config reg
Some qca8327 switch require to force the ignore of power on sel
strapping. Some switch require to set the led open drain mode in regs
instead of using strapping. While most of the device implements this
using the correct way using pin strapping, there are still some broken
device that require to be set using sw regs.
Introduce a new binding and support these special configuration.
As led open drain require to ignore pin strapping to work, the probe
fails with EINVAL error with incorrect configuration.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/net/dsa/qca8k.c | 39 +++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/qca8k.h | 6 ++++++
2 files changed, 45 insertions(+)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index b73b92ebd72e..3e2274cb82cd 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -931,6 +931,41 @@ static int qca8k_find_cpu_port(struct dsa_switch *ds)
return -EINVAL;
}
+static int
+qca8k_setup_of_pws_reg(struct qca8k_priv *priv)
+{
+ struct device_node *node = priv->dev->of_node;
+ u32 val = 0;
+ int ret;
+
+ /* QCA8327 require to set to the correct mode.
+ * His bigger brother QCA8328 have the 172 pin layout.
+ * Should be applied by default but we set this just to make sure.
+ */
+ if (priv->switch_id == QCA8K_ID_QCA8327) {
+ ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN,
+ QCA8327_PWS_PACKAGE148_EN);
+ if (ret)
+ return ret;
+ }
+
+ if (of_property_read_bool(node, "qca,ignore-power-on-sel"))
+ val |= QCA8K_PWS_POWER_ON_SEL;
+
+ if (of_property_read_bool(node, "qca,led-open-drain")) {
+ if (!(val & QCA8K_PWS_POWER_ON_SEL)) {
+ dev_err(priv->dev, "qca,led-open-drain require qca,ignore-power-on-sel to be set.");
+ return -EINVAL;
+ }
+
+ val |= QCA8K_PWS_LED_OPEN_EN_CSR;
+ }
+
+ return qca8k_rmw(priv, QCA8K_REG_PWS,
+ QCA8K_PWS_LED_OPEN_EN_CSR | QCA8K_PWS_POWER_ON_SEL,
+ val);
+}
+
static int
qca8k_setup(struct dsa_switch *ds)
{
@@ -957,6 +992,10 @@ qca8k_setup(struct dsa_switch *ds)
if (ret)
return ret;
+ ret = qca8k_setup_of_pws_reg(priv);
+ if (ret)
+ return ret;
+
ret = qca8k_setup_mac_pwr_sel(priv);
if (ret)
return ret;
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index a790b27bc310..535a4515e7b9 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -46,6 +46,12 @@
#define QCA8K_MAX_DELAY 3
#define QCA8K_PORT_PAD_SGMII_EN BIT(7)
#define QCA8K_REG_PWS 0x010
+#define QCA8K_PWS_POWER_ON_SEL BIT(31)
+/* This reg is only valid for QCA832x and toggle the package
+ * type from 176 pin (by default) to 148 pin used on QCA8327
+ */
+#define QCA8327_PWS_PACKAGE148_EN BIT(30)
+#define QCA8K_PWS_LED_OPEN_EN_CSR BIT(24)
#define QCA8K_PWS_SERDES_AEN_DIS BIT(7)
#define QCA8K_REG_MODULE_EN 0x030
#define QCA8K_MODULE_EN_MIB BIT(0)
--
2.32.0
From 218976ff96d5f64499616f2062e89cb52e0ed62f Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Sun, 19 Sep 2021 14:18:05 +0200
Subject: [net-next PATCH v3 09/11] dt-bindings: net: dsa: qca8k: document open
drain binding
Document new binding qca,power_on_sel used to enable Power-on-strapping
select reg and qca,led_open_drain to set led to open drain mode.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/qca8k.txt | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
index 05a8ddfb5483..71cd45818430 100644
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -13,6 +13,17 @@ Required properties:
Optional properties:
- reset-gpios: GPIO to be used to reset the whole device
+- qca,ignore-power-on-sel: Ignore power on pin strapping to configure led open
+ drain or eeprom presence. This is needed for broken
+ device that have wrong configuration or when the oem
+ decided to not use pin strapping and fallback to sw
+ regs.
+- qca,led-open-drain: Set leds to open-drain mode. This require the
+ qca,ignore-power-on-sel to be set or the driver will fail
+ to probe. This is needed if the oem doesn't use pin
+ strapping to set this mode and prefer to set it using sw
+ regs. The pin strapping related to led open drain mode is
+ the pin B68 for QCA832x and B49 for QCA833x
Subnodes:
--
2.32.0
From 88a59f6f870a1304c50e666584f4ba30a2f048bc Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Fri, 8 Oct 2021 01:50:49 +0200
Subject: [net-next PATCH v3 10/11] drivers: net: dsa: qca8k: add support for
QCA8328
QCA8328 switch is the bigger brother of the qca8327. Same regs different
chip. Change the function to set the correct pin layout and introduce a
new match_data to differentiate the 2 switch as they have the same ID
and their internal PHY have the same ID.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/net/dsa/qca8k.c | 19 ++++++++++++++++---
drivers/net/dsa/qca8k.h | 1 +
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 3e2274cb82cd..7c68c272ce3a 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -935,6 +935,7 @@ static int
qca8k_setup_of_pws_reg(struct qca8k_priv *priv)
{
struct device_node *node = priv->dev->of_node;
+ const struct qca8k_match_data *data;
u32 val = 0;
int ret;
@@ -943,8 +944,14 @@ qca8k_setup_of_pws_reg(struct qca8k_priv *priv)
* Should be applied by default but we set this just to make sure.
*/
if (priv->switch_id == QCA8K_ID_QCA8327) {
+ data = of_device_get_match_data(priv->dev);
+
+ /* Set the correct package of 148 pin for QCA8327 */
+ if (data->reduced_package)
+ val |= QCA8327_PWS_PACKAGE148_EN;
+
ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN,
- QCA8327_PWS_PACKAGE148_EN);
+ val);
if (ret)
return ret;
}
@@ -2018,7 +2025,12 @@ static int qca8k_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
qca8k_suspend, qca8k_resume);
-static const struct qca8k_match_data qca832x = {
+static const struct qca8k_match_data qca8327 = {
+ .id = QCA8K_ID_QCA8327,
+ .reduced_package = true,
+};
+
+static const struct qca8k_match_data qca8328 = {
.id = QCA8K_ID_QCA8327,
};
@@ -2027,7 +2039,8 @@ static const struct qca8k_match_data qca833x = {
};
static const struct of_device_id qca8k_of_match[] = {
- { .compatible = "qca,qca8327", .data = &qca832x },
+ { .compatible = "qca,qca8327", .data = &qca8327 },
+ { .compatible = "qca,qca8328", .data = &qca8328 },
{ .compatible = "qca,qca8334", .data = &qca833x },
{ .compatible = "qca,qca8337", .data = &qca833x },
{ /* sentinel */ },
diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h
index 535a4515e7b9..c032db5e0d41 100644
--- a/drivers/net/dsa/qca8k.h
+++ b/drivers/net/dsa/qca8k.h
@@ -260,6 +260,7 @@ struct ar8xxx_port_status {
struct qca8k_match_data {
u8 id;
+ bool reduced_package;
};
struct qca8k_priv {
--
2.32.0
From 8c4c3758d02fed47d6731050a04ec28f94492c1b Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Fri, 8 Oct 2021 01:52:42 +0200
Subject: [net-next PATCH v3 11/11] dt-bindings: net: dsa: qca8k: document
support for qca8328
QCA8328 is the bigger brother of qca8327. Document the new compatible
binding and add some information to understand the various switch
compatible.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/qca8k.txt | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
index 71cd45818430..e6b580d815c2 100644
--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
@@ -3,9 +3,10 @@
Required properties:
- compatible: should be one of:
- "qca,qca8327"
- "qca,qca8334"
- "qca,qca8337"
+ "qca,qca8328": referenced as AR8328(N)-AK1(A/B) QFN 176 pin package
+ "qca,qca8327": referenced as AR8327(N)-AL1A DR-QFN 148 pin package
+ "qca,qca8334": referenced as QCA8334-AL3C QFN 88 pin package
+ "qca,qca8337": referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package
- #size-cells: must be 0
- #address-cells: must be 1
--
2.32.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment