mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2025-12-10 06:24:40 +01:00
Add a new microchipsw target aimed add supporting Microchip switch SoC-s. Start by supporting LAN969x SoC-s as the first subtarget. Signed-off-by: Robert Marko <robert.marko@sartura.hr>
227 lines
7.9 KiB
Diff
227 lines
7.9 KiB
Diff
From 9a6d927f8d9386fcabe4b93aa1bf16a0796e69fb Mon Sep 17 00:00:00 2001
|
|
From: Daniel Machon <daniel.machon@microchip.com>
|
|
Date: Fri, 4 Oct 2024 15:19:34 +0200
|
|
Subject: [PATCH 36/82] net: sparx5: add ops to match data
|
|
|
|
Add new struct sparx5_ops, containing functions that needs to be
|
|
different as the implementation differs on Sparx5 and lan969x. Initially
|
|
we add functions for checking the port type (2g5, 5g, 10g or 25g) based
|
|
on the port number. Update the code to use the ops instead of the
|
|
platform specific functions.
|
|
|
|
Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
|
|
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
|
Signed-off-by: Daniel Machon <daniel.machon@microchip.com>
|
|
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
---
|
|
.../ethernet/microchip/sparx5/sparx5_main.c | 8 +++++
|
|
.../ethernet/microchip/sparx5/sparx5_main.h | 8 +++++
|
|
.../ethernet/microchip/sparx5/sparx5_port.c | 34 +++++++++++--------
|
|
.../ethernet/microchip/sparx5/sparx5_port.h | 12 ++++---
|
|
4 files changed, 44 insertions(+), 18 deletions(-)
|
|
|
|
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
|
|
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
|
|
@@ -982,12 +982,20 @@ static const struct sparx5_consts sparx5
|
|
.tod_pin = 4,
|
|
};
|
|
|
|
+static const struct sparx5_ops sparx5_ops = {
|
|
+ .is_port_2g5 = &sparx5_port_is_2g5,
|
|
+ .is_port_5g = &sparx5_port_is_5g,
|
|
+ .is_port_10g = &sparx5_port_is_10g,
|
|
+ .is_port_25g = &sparx5_port_is_25g,
|
|
+};
|
|
+
|
|
static const struct sparx5_match_data sparx5_desc = {
|
|
.iomap = sparx5_main_iomap,
|
|
.iomap_size = ARRAY_SIZE(sparx5_main_iomap),
|
|
.ioranges = 3,
|
|
.regs = &sparx5_regs,
|
|
.consts = &sparx5_consts,
|
|
+ .ops = &sparx5_ops,
|
|
};
|
|
|
|
static const struct of_device_id mchp_sparx5_match[] = {
|
|
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
|
|
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
|
|
@@ -258,6 +258,13 @@ struct sparx5_consts {
|
|
u32 tod_pin; /* PTP TOD pin */
|
|
};
|
|
|
|
+struct sparx5_ops {
|
|
+ bool (*is_port_2g5)(int portno);
|
|
+ bool (*is_port_5g)(int portno);
|
|
+ bool (*is_port_10g)(int portno);
|
|
+ bool (*is_port_25g)(int portno);
|
|
+};
|
|
+
|
|
struct sparx5_main_io_resource {
|
|
enum sparx5_target id;
|
|
phys_addr_t offset;
|
|
@@ -267,6 +274,7 @@ struct sparx5_main_io_resource {
|
|
struct sparx5_match_data {
|
|
const struct sparx5_regs *regs;
|
|
const struct sparx5_consts *consts;
|
|
+ const struct sparx5_ops *ops;
|
|
const struct sparx5_main_io_resource *iomap;
|
|
int ioranges;
|
|
int iomap_size;
|
|
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
|
|
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
|
|
@@ -213,11 +213,13 @@ static int sparx5_port_verify_speed(stru
|
|
struct sparx5_port *port,
|
|
struct sparx5_port_config *conf)
|
|
{
|
|
- if ((sparx5_port_is_2g5(port->portno) &&
|
|
+ const struct sparx5_ops *ops = sparx5->data->ops;
|
|
+
|
|
+ if ((ops->is_port_2g5(port->portno) &&
|
|
conf->speed > SPEED_2500) ||
|
|
- (sparx5_port_is_5g(port->portno) &&
|
|
+ (ops->is_port_5g(port->portno) &&
|
|
conf->speed > SPEED_5000) ||
|
|
- (sparx5_port_is_10g(port->portno) &&
|
|
+ (ops->is_port_10g(port->portno) &&
|
|
conf->speed > SPEED_10000))
|
|
return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
|
|
|
|
@@ -226,14 +228,14 @@ static int sparx5_port_verify_speed(stru
|
|
return -EINVAL;
|
|
case PHY_INTERFACE_MODE_1000BASEX:
|
|
if (conf->speed != SPEED_1000 ||
|
|
- sparx5_port_is_2g5(port->portno))
|
|
+ ops->is_port_2g5(port->portno))
|
|
return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
|
|
- if (sparx5_port_is_2g5(port->portno))
|
|
+ if (ops->is_port_2g5(port->portno))
|
|
return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
|
|
break;
|
|
case PHY_INTERFACE_MODE_2500BASEX:
|
|
if (conf->speed != SPEED_2500 ||
|
|
- sparx5_port_is_2g5(port->portno))
|
|
+ ops->is_port_2g5(port->portno))
|
|
return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
|
|
break;
|
|
case PHY_INTERFACE_MODE_QSGMII:
|
|
@@ -320,6 +322,7 @@ static int sparx5_port_disable(struct sp
|
|
u32 dev = high_spd_dev ?
|
|
sparx5_to_high_dev(sparx5, port->portno) : TARGET_DEV2G5;
|
|
void __iomem *devinst = spx5_inst_get(sparx5, dev, tinst);
|
|
+ const struct sparx5_ops *ops = sparx5->data->ops;
|
|
u32 spd = port->conf.speed;
|
|
u32 spd_prm;
|
|
int err;
|
|
@@ -436,7 +439,7 @@ static int sparx5_port_disable(struct sp
|
|
pcsinst,
|
|
PCS10G_BR_PCS_CFG(0));
|
|
|
|
- if (sparx5_port_is_25g(port->portno))
|
|
+ if (ops->is_port_25g(port->portno))
|
|
/* Disable 25G PCS */
|
|
spx5_rmw(DEV25G_PCS25G_CFG_PCS25G_ENA_SET(0),
|
|
DEV25G_PCS25G_CFG_PCS25G_ENA,
|
|
@@ -561,6 +564,7 @@ static int sparx5_port_max_tags_set(stru
|
|
u32 dev = sparx5_to_high_dev(sparx5, port->portno);
|
|
u32 tinst = sparx5_port_dev_index(sparx5, port->portno);
|
|
void __iomem *inst = spx5_inst_get(sparx5, dev, tinst);
|
|
+ const struct sparx5_ops *ops = sparx5->data->ops;
|
|
u32 etype;
|
|
|
|
etype = (vlan_type == SPX5_VLAN_PORT_TYPE_S_CUSTOM ?
|
|
@@ -575,7 +579,7 @@ static int sparx5_port_max_tags_set(stru
|
|
sparx5,
|
|
DEV2G5_MAC_TAGS_CFG(port->portno));
|
|
|
|
- if (sparx5_port_is_2g5(port->portno))
|
|
+ if (ops->is_port_2g5(port->portno))
|
|
return 0;
|
|
|
|
spx5_inst_rmw(DEV10G_MAC_TAGS_CFG_TAG_ID_SET(etype) |
|
|
@@ -844,18 +848,19 @@ static int sparx5_port_pcs_high_set(stru
|
|
static void sparx5_dev_switch(struct sparx5 *sparx5, int port, bool hsd)
|
|
{
|
|
int bt_indx = BIT(sparx5_port_dev_index(sparx5, port));
|
|
+ const struct sparx5_ops *ops = sparx5->data->ops;
|
|
|
|
- if (sparx5_port_is_5g(port)) {
|
|
+ if (ops->is_port_5g(port)) {
|
|
spx5_rmw(hsd ? 0 : bt_indx,
|
|
bt_indx,
|
|
sparx5,
|
|
PORT_CONF_DEV5G_MODES);
|
|
- } else if (sparx5_port_is_10g(port)) {
|
|
+ } else if (ops->is_port_10g(port)) {
|
|
spx5_rmw(hsd ? 0 : bt_indx,
|
|
bt_indx,
|
|
sparx5,
|
|
PORT_CONF_DEV10G_MODES);
|
|
- } else if (sparx5_port_is_25g(port)) {
|
|
+ } else if (ops->is_port_25g(port)) {
|
|
spx5_rmw(hsd ? 0 : bt_indx,
|
|
bt_indx,
|
|
sparx5,
|
|
@@ -1016,6 +1021,7 @@ int sparx5_port_init(struct sparx5 *spar
|
|
{
|
|
u32 pause_start = sparx5_wm_enc(6 * (ETH_MAXLEN / SPX5_BUFFER_CELL_SZ));
|
|
u32 atop = sparx5_wm_enc(20 * (ETH_MAXLEN / SPX5_BUFFER_CELL_SZ));
|
|
+ const struct sparx5_ops *ops = sparx5->data->ops;
|
|
u32 devhigh = sparx5_to_high_dev(sparx5, port->portno);
|
|
u32 pix = sparx5_port_dev_index(sparx5, port->portno);
|
|
u32 pcs = sparx5_to_pcs_dev(sparx5, port->portno);
|
|
@@ -1082,7 +1088,7 @@ int sparx5_port_init(struct sparx5 *spar
|
|
if (err)
|
|
return err;
|
|
|
|
- if (!sparx5_port_is_2g5(port->portno))
|
|
+ if (!ops->is_port_2g5(port->portno))
|
|
/* Enable shadow device */
|
|
spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV10G_SHADOW_ENA_SET(1),
|
|
DSM_DEV_TX_STOP_WM_CFG_DEV10G_SHADOW_ENA,
|
|
@@ -1105,7 +1111,7 @@ int sparx5_port_init(struct sparx5 *spar
|
|
sparx5,
|
|
DEV2G5_MAC_IFG_CFG(port->portno));
|
|
|
|
- if (sparx5_port_is_2g5(port->portno))
|
|
+ if (ops->is_port_2g5(port->portno))
|
|
return 0; /* Low speed device only - return */
|
|
|
|
/* Now setup the high speed device */
|
|
@@ -1128,7 +1134,7 @@ int sparx5_port_init(struct sparx5 *spar
|
|
pcsinst,
|
|
PCS10G_BR_PCS_SD_CFG(0));
|
|
|
|
- if (sparx5_port_is_25g(port->portno)) {
|
|
+ if (ops->is_port_25g(port->portno)) {
|
|
/* Handle Signal Detect in 25G PCS */
|
|
spx5_wr(DEV25G_PCS25G_SD_CFG_SD_POL_SET(sd_pol) |
|
|
DEV25G_PCS25G_SD_CFG_SD_SEL_SET(sd_sel) |
|
|
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
|
|
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
|
|
@@ -42,18 +42,22 @@ static inline bool sparx5_port_is_25g(in
|
|
|
|
static inline u32 sparx5_to_high_dev(struct sparx5 *sparx5, int port)
|
|
{
|
|
- if (sparx5_port_is_5g(port))
|
|
+ const struct sparx5_ops *ops = sparx5->data->ops;
|
|
+
|
|
+ if (ops->is_port_5g(port))
|
|
return TARGET_DEV5G;
|
|
- if (sparx5_port_is_10g(port))
|
|
+ if (ops->is_port_10g(port))
|
|
return TARGET_DEV10G;
|
|
return TARGET_DEV25G;
|
|
}
|
|
|
|
static inline u32 sparx5_to_pcs_dev(struct sparx5 *sparx5, int port)
|
|
{
|
|
- if (sparx5_port_is_5g(port))
|
|
+ const struct sparx5_ops *ops = sparx5->data->ops;
|
|
+
|
|
+ if (ops->is_port_5g(port))
|
|
return TARGET_PCS5G_BR;
|
|
- if (sparx5_port_is_10g(port))
|
|
+ if (ops->is_port_10g(port))
|
|
return TARGET_PCS10G_BR;
|
|
return TARGET_PCS25G_BR;
|
|
}
|