From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
To: "David S. Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>
Cc: "Marek Behún" <kabel@kernel.org>, "Felix Fietkau" <nbd@nbd.name>,
"John Crispin" <john@phrozen.org>,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org,
"Mark Lee" <Mark-MC.Lee@mediatek.com>,
"Matthias Brugger" <matthias.bgg@gmail.com>,
netdev@vger.kernel.org, "Paolo Abeni" <pabeni@redhat.com>,
"Sean Wang" <sean.wang@mediatek.com>,
"Eric Dumazet" <edumazet@google.com>
Subject: [PATCH net-next 11/12] net: mtk_eth_soc: convert code structure to suit split PCS support
Date: Wed, 18 May 2022 15:55:22 +0100 [thread overview]
Message-ID: <E1nrL58-00AM5d-U9@rmk-PC.armlinux.org.uk> (raw)
In-Reply-To: <YoUIX+BN/ZbyXzTT@shell.armlinux.org.uk>
Provide a mtk_pcs structure which encapsulates everything that the PCS
functions need (the regmap and ana_rgc3 offset), and use this in the
PCS functions. Provide shim functions to convert from the existing
"mtk_sgmii_*" interface to the converted PCS functions.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 15 ++-
drivers/net/ethernet/mediatek/mtk_sgmii.c | 123 +++++++++++---------
2 files changed, 79 insertions(+), 59 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 1ad5c26f01fb..8bf2d53cbec8 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -869,16 +869,23 @@ struct mtk_soc_data {
/* currently no SoC has more than 2 macs */
#define MTK_MAX_DEVS 2
-/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
- * characteristics
+/* struct mtk_pcs - This structure holds each sgmii regmap and associated
+ * data
* @regmap: The register map pointing at the range used to setup
* SGMII modes
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
*/
+struct mtk_pcs {
+ struct regmap *regmap;
+ u32 ana_rgc3;
+};
+/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
+ * characteristics
+ * @pcs Array of individual PCS structures
+ */
struct mtk_sgmii {
- struct regmap *regmap[MTK_MAX_DEVS];
- u32 ana_rgc3;
+ struct mtk_pcs pcs[MTK_MAX_DEVS];
};
/* struct mtk_eth - This is the main datasructure for holding the state
diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 4defc1ca41b6..7f257f492926 100644
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -9,90 +9,71 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
+#include <linux/phylink.h>
#include <linux/regmap.h>
#include "mtk_eth_soc.h"
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
-{
- struct device_node *np;
- int i;
-
- ss->ana_rgc3 = ana_rgc3;
-
- for (i = 0; i < MTK_MAX_DEVS; i++) {
- np = of_parse_phandle(r, "mediatek,sgmiisys", i);
- if (!np)
- break;
-
- ss->regmap[i] = syscon_node_to_regmap(np);
- of_node_put(np);
- if (IS_ERR(ss->regmap[i]))
- return PTR_ERR(ss->regmap[i]);
- }
-
- return 0;
-}
-
/* For SGMII interface mode */
-static int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
+static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
{
unsigned int val;
- if (!ss->regmap[id])
+ if (!mpcs->regmap)
return -EINVAL;
/* Setup the link timer and QPHY power up inside SGMIISYS */
- regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
SGMII_LINK_TIMER_DEFAULT);
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val |= SGMII_REMOTE_FAULT_DIS;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
+
}
/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
* fixed speed.
*/
-static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
- phy_interface_t interface)
+static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
+ phy_interface_t interface)
{
unsigned int val;
- if (!ss->regmap[id])
+ if (!mpcs->regmap)
return -EINVAL;
- regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
val &= ~RG_PHY_SPEED_MASK;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
val |= RG_PHY_SPEED_3_125G;
- regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
/* Disable SGMII AN */
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val &= ~SGMII_AN_ENABLE;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
/* Set the speed etc but leave the duplex unchanged */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK;
val |= SGMII_SPEED_1000;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
/* Release PHYA power down state */
- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
}
@@ -100,44 +81,76 @@ static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode,
phy_interface_t interface)
{
+ struct mtk_pcs *mpcs = &ss->pcs[id];
int err = 0;
/* Setup SGMIISYS with the determined property */
if (interface != PHY_INTERFACE_MODE_SGMII)
- err = mtk_sgmii_setup_mode_force(ss, id, interface);
+ err = mtk_pcs_setup_mode_force(mpcs, interface);
else if (phylink_autoneg_inband(mode))
- err = mtk_sgmii_setup_mode_an(ss, id);
+ err = mtk_pcs_setup_mode_an(mpcs);
return err;
}
-/* For 1000BASE-X and 2500BASE-X interface modes */
-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
+static void mtk_pcs_restart_an(struct mtk_pcs *mpcs)
+{
+ unsigned int val;
+
+ if (!mpcs->regmap)
+ return;
+
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
+ val |= SGMII_AN_RESTART;
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+}
+
+static void mtk_pcs_link_up(struct mtk_pcs *mpcs, int speed, int duplex)
{
unsigned int val;
/* SGMII force duplex setting */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val &= ~SGMII_DUPLEX_FULL;
if (duplex == DUPLEX_FULL)
val |= SGMII_DUPLEX_FULL;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+}
+
+/* For 1000BASE-X and 2500BASE-X interface modes */
+void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
+{
+ mtk_pcs_link_up(&ss->pcs[id], speed, duplex);
+}
+
+int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+{
+ struct device_node *np;
+ int i;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ np = of_parse_phandle(r, "mediatek,sgmiisys", i);
+ if (!np)
+ break;
+
+ ss->pcs[i].ana_rgc3 = ana_rgc3;
+ ss->pcs[i].regmap = syscon_node_to_regmap(np);
+ of_node_put(np);
+ if (IS_ERR(ss->pcs[i].regmap))
+ return PTR_ERR(ss->pcs[i].regmap);
+ }
+
+ return 0;
}
void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
{
- struct mtk_sgmii *ss = eth->sgmii;
- unsigned int val, sid;
+ unsigned int sid;
/* Decide how GMAC and SGMIISYS be mapped */
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
0 : mac_id;
- if (!ss->regmap[sid])
- return;
-
- regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val);
- val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val);
+ mtk_pcs_restart_an(ð->sgmii->pcs[sid]);
}
--
2.30.2
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
WARNING: multiple messages have this Message-ID (diff)
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
To: "David S. Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>
Cc: "Marek Behún" <kabel@kernel.org>, "Felix Fietkau" <nbd@nbd.name>,
"John Crispin" <john@phrozen.org>,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org,
"Mark Lee" <Mark-MC.Lee@mediatek.com>,
"Matthias Brugger" <matthias.bgg@gmail.com>,
netdev@vger.kernel.org, "Paolo Abeni" <pabeni@redhat.com>,
"Sean Wang" <sean.wang@mediatek.com>,
"Eric Dumazet" <edumazet@google.com>
Subject: [PATCH net-next 11/12] net: mtk_eth_soc: convert code structure to suit split PCS support
Date: Wed, 18 May 2022 15:55:22 +0100 [thread overview]
Message-ID: <E1nrL58-00AM5d-U9@rmk-PC.armlinux.org.uk> (raw)
In-Reply-To: <YoUIX+BN/ZbyXzTT@shell.armlinux.org.uk>
Provide a mtk_pcs structure which encapsulates everything that the PCS
functions need (the regmap and ana_rgc3 offset), and use this in the
PCS functions. Provide shim functions to convert from the existing
"mtk_sgmii_*" interface to the converted PCS functions.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 15 ++-
drivers/net/ethernet/mediatek/mtk_sgmii.c | 123 +++++++++++---------
2 files changed, 79 insertions(+), 59 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 1ad5c26f01fb..8bf2d53cbec8 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -869,16 +869,23 @@ struct mtk_soc_data {
/* currently no SoC has more than 2 macs */
#define MTK_MAX_DEVS 2
-/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
- * characteristics
+/* struct mtk_pcs - This structure holds each sgmii regmap and associated
+ * data
* @regmap: The register map pointing at the range used to setup
* SGMII modes
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
*/
+struct mtk_pcs {
+ struct regmap *regmap;
+ u32 ana_rgc3;
+};
+/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
+ * characteristics
+ * @pcs Array of individual PCS structures
+ */
struct mtk_sgmii {
- struct regmap *regmap[MTK_MAX_DEVS];
- u32 ana_rgc3;
+ struct mtk_pcs pcs[MTK_MAX_DEVS];
};
/* struct mtk_eth - This is the main datasructure for holding the state
diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 4defc1ca41b6..7f257f492926 100644
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -9,90 +9,71 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
+#include <linux/phylink.h>
#include <linux/regmap.h>
#include "mtk_eth_soc.h"
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
-{
- struct device_node *np;
- int i;
-
- ss->ana_rgc3 = ana_rgc3;
-
- for (i = 0; i < MTK_MAX_DEVS; i++) {
- np = of_parse_phandle(r, "mediatek,sgmiisys", i);
- if (!np)
- break;
-
- ss->regmap[i] = syscon_node_to_regmap(np);
- of_node_put(np);
- if (IS_ERR(ss->regmap[i]))
- return PTR_ERR(ss->regmap[i]);
- }
-
- return 0;
-}
-
/* For SGMII interface mode */
-static int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
+static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
{
unsigned int val;
- if (!ss->regmap[id])
+ if (!mpcs->regmap)
return -EINVAL;
/* Setup the link timer and QPHY power up inside SGMIISYS */
- regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
SGMII_LINK_TIMER_DEFAULT);
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val |= SGMII_REMOTE_FAULT_DIS;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
+
}
/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
* fixed speed.
*/
-static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
- phy_interface_t interface)
+static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
+ phy_interface_t interface)
{
unsigned int val;
- if (!ss->regmap[id])
+ if (!mpcs->regmap)
return -EINVAL;
- regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
val &= ~RG_PHY_SPEED_MASK;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
val |= RG_PHY_SPEED_3_125G;
- regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
/* Disable SGMII AN */
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val &= ~SGMII_AN_ENABLE;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
/* Set the speed etc but leave the duplex unchanged */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK;
val |= SGMII_SPEED_1000;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
/* Release PHYA power down state */
- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
}
@@ -100,44 +81,76 @@ static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode,
phy_interface_t interface)
{
+ struct mtk_pcs *mpcs = &ss->pcs[id];
int err = 0;
/* Setup SGMIISYS with the determined property */
if (interface != PHY_INTERFACE_MODE_SGMII)
- err = mtk_sgmii_setup_mode_force(ss, id, interface);
+ err = mtk_pcs_setup_mode_force(mpcs, interface);
else if (phylink_autoneg_inband(mode))
- err = mtk_sgmii_setup_mode_an(ss, id);
+ err = mtk_pcs_setup_mode_an(mpcs);
return err;
}
-/* For 1000BASE-X and 2500BASE-X interface modes */
-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
+static void mtk_pcs_restart_an(struct mtk_pcs *mpcs)
+{
+ unsigned int val;
+
+ if (!mpcs->regmap)
+ return;
+
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
+ val |= SGMII_AN_RESTART;
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+}
+
+static void mtk_pcs_link_up(struct mtk_pcs *mpcs, int speed, int duplex)
{
unsigned int val;
/* SGMII force duplex setting */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val &= ~SGMII_DUPLEX_FULL;
if (duplex == DUPLEX_FULL)
val |= SGMII_DUPLEX_FULL;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+}
+
+/* For 1000BASE-X and 2500BASE-X interface modes */
+void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
+{
+ mtk_pcs_link_up(&ss->pcs[id], speed, duplex);
+}
+
+int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+{
+ struct device_node *np;
+ int i;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ np = of_parse_phandle(r, "mediatek,sgmiisys", i);
+ if (!np)
+ break;
+
+ ss->pcs[i].ana_rgc3 = ana_rgc3;
+ ss->pcs[i].regmap = syscon_node_to_regmap(np);
+ of_node_put(np);
+ if (IS_ERR(ss->pcs[i].regmap))
+ return PTR_ERR(ss->pcs[i].regmap);
+ }
+
+ return 0;
}
void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
{
- struct mtk_sgmii *ss = eth->sgmii;
- unsigned int val, sid;
+ unsigned int sid;
/* Decide how GMAC and SGMIISYS be mapped */
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
0 : mac_id;
- if (!ss->regmap[sid])
- return;
-
- regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val);
- val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val);
+ mtk_pcs_restart_an(ð->sgmii->pcs[sid]);
}
--
2.30.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
To: "David S. Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>
Cc: "Marek Behún" <kabel@kernel.org>, "Felix Fietkau" <nbd@nbd.name>,
"John Crispin" <john@phrozen.org>,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org,
"Mark Lee" <Mark-MC.Lee@mediatek.com>,
"Matthias Brugger" <matthias.bgg@gmail.com>,
netdev@vger.kernel.org, "Paolo Abeni" <pabeni@redhat.com>,
"Sean Wang" <sean.wang@mediatek.com>,
"Eric Dumazet" <edumazet@google.com>
Subject: [PATCH net-next 11/12] net: mtk_eth_soc: convert code structure to suit split PCS support
Date: Wed, 18 May 2022 15:55:22 +0100 [thread overview]
Message-ID: <E1nrL58-00AM5d-U9@rmk-PC.armlinux.org.uk> (raw)
In-Reply-To: <YoUIX+BN/ZbyXzTT@shell.armlinux.org.uk>
Provide a mtk_pcs structure which encapsulates everything that the PCS
functions need (the regmap and ana_rgc3 offset), and use this in the
PCS functions. Provide shim functions to convert from the existing
"mtk_sgmii_*" interface to the converted PCS functions.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 15 ++-
drivers/net/ethernet/mediatek/mtk_sgmii.c | 123 +++++++++++---------
2 files changed, 79 insertions(+), 59 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 1ad5c26f01fb..8bf2d53cbec8 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -869,16 +869,23 @@ struct mtk_soc_data {
/* currently no SoC has more than 2 macs */
#define MTK_MAX_DEVS 2
-/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
- * characteristics
+/* struct mtk_pcs - This structure holds each sgmii regmap and associated
+ * data
* @regmap: The register map pointing at the range used to setup
* SGMII modes
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
*/
+struct mtk_pcs {
+ struct regmap *regmap;
+ u32 ana_rgc3;
+};
+/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
+ * characteristics
+ * @pcs Array of individual PCS structures
+ */
struct mtk_sgmii {
- struct regmap *regmap[MTK_MAX_DEVS];
- u32 ana_rgc3;
+ struct mtk_pcs pcs[MTK_MAX_DEVS];
};
/* struct mtk_eth - This is the main datasructure for holding the state
diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 4defc1ca41b6..7f257f492926 100644
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -9,90 +9,71 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
+#include <linux/phylink.h>
#include <linux/regmap.h>
#include "mtk_eth_soc.h"
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
-{
- struct device_node *np;
- int i;
-
- ss->ana_rgc3 = ana_rgc3;
-
- for (i = 0; i < MTK_MAX_DEVS; i++) {
- np = of_parse_phandle(r, "mediatek,sgmiisys", i);
- if (!np)
- break;
-
- ss->regmap[i] = syscon_node_to_regmap(np);
- of_node_put(np);
- if (IS_ERR(ss->regmap[i]))
- return PTR_ERR(ss->regmap[i]);
- }
-
- return 0;
-}
-
/* For SGMII interface mode */
-static int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
+static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
{
unsigned int val;
- if (!ss->regmap[id])
+ if (!mpcs->regmap)
return -EINVAL;
/* Setup the link timer and QPHY power up inside SGMIISYS */
- regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
SGMII_LINK_TIMER_DEFAULT);
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val |= SGMII_REMOTE_FAULT_DIS;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
+
}
/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
* fixed speed.
*/
-static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
- phy_interface_t interface)
+static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
+ phy_interface_t interface)
{
unsigned int val;
- if (!ss->regmap[id])
+ if (!mpcs->regmap)
return -EINVAL;
- regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
val &= ~RG_PHY_SPEED_MASK;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
val |= RG_PHY_SPEED_3_125G;
- regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
/* Disable SGMII AN */
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val &= ~SGMII_AN_ENABLE;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
/* Set the speed etc but leave the duplex unchanged */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK;
val |= SGMII_SPEED_1000;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
/* Release PHYA power down state */
- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
}
@@ -100,44 +81,76 @@ static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode,
phy_interface_t interface)
{
+ struct mtk_pcs *mpcs = &ss->pcs[id];
int err = 0;
/* Setup SGMIISYS with the determined property */
if (interface != PHY_INTERFACE_MODE_SGMII)
- err = mtk_sgmii_setup_mode_force(ss, id, interface);
+ err = mtk_pcs_setup_mode_force(mpcs, interface);
else if (phylink_autoneg_inband(mode))
- err = mtk_sgmii_setup_mode_an(ss, id);
+ err = mtk_pcs_setup_mode_an(mpcs);
return err;
}
-/* For 1000BASE-X and 2500BASE-X interface modes */
-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
+static void mtk_pcs_restart_an(struct mtk_pcs *mpcs)
+{
+ unsigned int val;
+
+ if (!mpcs->regmap)
+ return;
+
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
+ val |= SGMII_AN_RESTART;
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+}
+
+static void mtk_pcs_link_up(struct mtk_pcs *mpcs, int speed, int duplex)
{
unsigned int val;
/* SGMII force duplex setting */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val &= ~SGMII_DUPLEX_FULL;
if (duplex == DUPLEX_FULL)
val |= SGMII_DUPLEX_FULL;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+}
+
+/* For 1000BASE-X and 2500BASE-X interface modes */
+void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
+{
+ mtk_pcs_link_up(&ss->pcs[id], speed, duplex);
+}
+
+int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+{
+ struct device_node *np;
+ int i;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ np = of_parse_phandle(r, "mediatek,sgmiisys", i);
+ if (!np)
+ break;
+
+ ss->pcs[i].ana_rgc3 = ana_rgc3;
+ ss->pcs[i].regmap = syscon_node_to_regmap(np);
+ of_node_put(np);
+ if (IS_ERR(ss->pcs[i].regmap))
+ return PTR_ERR(ss->pcs[i].regmap);
+ }
+
+ return 0;
}
void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
{
- struct mtk_sgmii *ss = eth->sgmii;
- unsigned int val, sid;
+ unsigned int sid;
/* Decide how GMAC and SGMIISYS be mapped */
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
0 : mac_id;
- if (!ss->regmap[sid])
- return;
-
- regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val);
- val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val);
+ mtk_pcs_restart_an(ð->sgmii->pcs[sid]);
}
--
2.30.2
next prev parent reply other threads:[~2022-05-18 14:59 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-18 14:53 [PATCH net-next 00/12] mtk_eth_soc phylink updates Russell King (Oracle)
2022-05-18 14:53 ` Russell King (Oracle)
2022-05-18 14:53 ` Russell King (Oracle)
2022-05-18 14:54 ` [PATCH net-next 01/12] net: mtk_eth_soc: remove unused mac->mode Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` [PATCH net-next 02/12] net: mtk_eth_soc: remove unused sgmii flags Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` [PATCH net-next 03/12] net: mtk_eth_soc: add mask and update PCS speed definitions Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` [PATCH net-next 04/12] net: mtk_eth_soc: correct 802.3z speed setting Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` [PATCH net-next 05/12] net: mtk_eth_soc: correct 802.3z duplex setting Russell King
2022-05-18 14:54 ` Russell King
2022-05-18 14:54 ` Russell King
2022-05-18 14:54 ` [PATCH net-next 06/12] net: mtk_eth_soc: stop passing phylink state to sgmii setup Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:54 ` Russell King (Oracle)
2022-05-18 14:55 ` [PATCH net-next 07/12] net: mtk_eth_soc: provide mtk_sgmii_config() Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` [PATCH net-next 08/12] net: mtk_eth_soc: add fixme comment for state->speed use Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` [PATCH net-next 09/12] net: mtk_eth_soc: move MAC_MCR setting to mac_finish() Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` [PATCH net-next 10/12] net: mtk_eth_soc: move restoration of SYSCFG0 " Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle) [this message]
2022-05-18 14:55 ` [PATCH net-next 11/12] net: mtk_eth_soc: convert code structure to suit split PCS support Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` [PATCH net-next 12/12] net: mtk_eth_soc: partially convert to phylink_pcs Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 14:55 ` Russell King (Oracle)
2022-05-18 15:40 ` [PATCH net-next 00/12] mtk_eth_soc phylink updates Marek Behún
2022-05-18 15:40 ` Marek Behún
2022-05-18 15:40 ` Marek Behún
2022-05-20 1:20 ` patchwork-bot+netdevbpf
2022-05-20 1:20 ` patchwork-bot+netdevbpf
2022-05-20 1:20 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=E1nrL58-00AM5d-U9@rmk-PC.armlinux.org.uk \
--to=rmk+kernel@armlinux.org.uk \
--cc=Mark-MC.Lee@mediatek.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=john@phrozen.org \
--cc=kabel@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=matthias.bgg@gmail.com \
--cc=nbd@nbd.name \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sean.wang@mediatek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.