Commit a09d042b authored by Aleksander Jan Bajkowski's avatar Aleksander Jan Bajkowski Committed by David S. Miller
Browse files

net: dsa: lantiq: allow to use all GPHYs on xRX300 and xRX330



This patch allows to use all PHYs on GRX300 and GRX330. The ARX300
has 3 and the GRX330 has 4 integrated PHYs connected to different
ports compared to VRX200. Each integrated PHY can work as single
Gigabit Ethernet PHY (GMII) or as double Fast Ethernet PHY (MII).

Allowed port configurations:

xRX200:
GMAC0: RGMII, MII, REVMII or RMII port
GMAC1: RGMII, MII, REVMII or RMII port
GMAC2: GPHY0 (GMII)
GMAC3: GPHY0 (MII)
GMAC4: GPHY1 (GMII)
GMAC5: GPHY1 (MII) or RGMII port

xRX300:
GMAC0: RGMII port
GMAC1: GPHY2 (GMII)
GMAC2: GPHY0 (GMII)
GMAC3: GPHY0 (MII)
GMAC4: GPHY1 (GMII)
GMAC5: GPHY1 (MII) or RGMII port

xRX330:
GMAC0: RGMII, GMII or RMII port
GMAC1: GPHY2 (GMII)
GMAC2: GPHY0 (GMII)
GMAC3: GPHY0 (MII) or GPHY3 (GMII)
GMAC4: GPHY1 (GMII)
GMAC5: GPHY1 (MII), RGMII or RMII port

Tested on D-Link DWR966 (xRX330) with OpenWRT.

Signed-off-by: default avatarAleksander Jan Bajkowski <olek2@wp.pl>
Acked-by: default avatarHauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 853b0df9
Loading
Loading
Loading
Loading
+113 −29
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Lantiq / Intel GSWIP switch driver for VRX200 SoCs
 * Lantiq / Intel GSWIP switch driver for VRX200, xRX300 and xRX330 SoCs
 *
 * Copyright (C) 2010 Lantiq Deutschland
 * Copyright (C) 2012 John Crispin <john@phrozen.org>
@@ -100,6 +100,7 @@
#define  GSWIP_MII_CFG_MODE_RMIIP	0x2
#define  GSWIP_MII_CFG_MODE_RMIIM	0x3
#define  GSWIP_MII_CFG_MODE_RGMII	0x4
#define  GSWIP_MII_CFG_MODE_GMII	0x9
#define  GSWIP_MII_CFG_MODE_MASK	0xf
#define  GSWIP_MII_CFG_RATE_M2P5	0x00
#define  GSWIP_MII_CFG_RATE_M25	0x10
@@ -220,6 +221,7 @@
struct gswip_hw_info {
	int max_ports;
	int cpu_port;
	const struct dsa_switch_ops *ops;
};

struct xway_gphy_match_data {
@@ -1384,12 +1386,42 @@ static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
	return 0;
}

static void gswip_phylink_validate(struct dsa_switch *ds, int port,
				   unsigned long *supported,
static void gswip_phylink_set_capab(unsigned long *supported,
				    struct phylink_link_state *state)
{
	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };

	/* Allow all the expected bits */
	phylink_set(mask, Autoneg);
	phylink_set_port_modes(mask);
	phylink_set(mask, Pause);
	phylink_set(mask, Asym_Pause);

	/* With the exclusion of MII, Reverse MII and Reduced MII, we
	 * support Gigabit, including Half duplex
	 */
	if (state->interface != PHY_INTERFACE_MODE_MII &&
	    state->interface != PHY_INTERFACE_MODE_REVMII &&
	    state->interface != PHY_INTERFACE_MODE_RMII) {
		phylink_set(mask, 1000baseT_Full);
		phylink_set(mask, 1000baseT_Half);
	}

	phylink_set(mask, 10baseT_Half);
	phylink_set(mask, 10baseT_Full);
	phylink_set(mask, 100baseT_Half);
	phylink_set(mask, 100baseT_Full);

	bitmap_and(supported, supported, mask,
		   __ETHTOOL_LINK_MODE_MASK_NBITS);
	bitmap_and(state->advertising, state->advertising, mask,
		   __ETHTOOL_LINK_MODE_MASK_NBITS);
}

static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port,
					  unsigned long *supported,
					  struct phylink_link_state *state)
{
	switch (port) {
	case 0:
	case 1:
@@ -1416,38 +1448,54 @@ static void gswip_phylink_validate(struct dsa_switch *ds, int port,
		return;
	}

	/* Allow all the expected bits */
	phylink_set(mask, Autoneg);
	phylink_set_port_modes(mask);
	phylink_set(mask, Pause);
	phylink_set(mask, Asym_Pause);
	gswip_phylink_set_capab(supported, state);

	/* With the exclusion of MII, Reverse MII and Reduced MII, we
	 * support Gigabit, including Half duplex
	 */
	if (state->interface != PHY_INTERFACE_MODE_MII &&
	    state->interface != PHY_INTERFACE_MODE_REVMII &&
	    state->interface != PHY_INTERFACE_MODE_RMII) {
		phylink_set(mask, 1000baseT_Full);
		phylink_set(mask, 1000baseT_Half);
	return;

unsupported:
	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
		phy_modes(state->interface), port);
}

	phylink_set(mask, 10baseT_Half);
	phylink_set(mask, 10baseT_Full);
	phylink_set(mask, 100baseT_Half);
	phylink_set(mask, 100baseT_Full);
static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port,
					  unsigned long *supported,
					  struct phylink_link_state *state)
{
	switch (port) {
	case 0:
		if (!phy_interface_mode_is_rgmii(state->interface) &&
		    state->interface != PHY_INTERFACE_MODE_GMII &&
		    state->interface != PHY_INTERFACE_MODE_RMII)
			goto unsupported;
		break;
	case 1:
	case 2:
	case 3:
	case 4:
		if (state->interface != PHY_INTERFACE_MODE_INTERNAL)
			goto unsupported;
		break;
	case 5:
		if (!phy_interface_mode_is_rgmii(state->interface) &&
		    state->interface != PHY_INTERFACE_MODE_INTERNAL &&
		    state->interface != PHY_INTERFACE_MODE_RMII)
			goto unsupported;
		break;
	default:
		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
		dev_err(ds->dev, "Unsupported port: %i\n", port);
		return;
	}

	gswip_phylink_set_capab(supported, state);

	bitmap_and(supported, supported, mask,
		   __ETHTOOL_LINK_MODE_MASK_NBITS);
	bitmap_and(state->advertising, state->advertising, mask,
		   __ETHTOOL_LINK_MODE_MASK_NBITS);
	return;

unsupported:
	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
		phy_modes(state->interface), port);
	return;
}

static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
@@ -1476,6 +1524,9 @@ static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
	case PHY_INTERFACE_MODE_RGMII_TXID:
		miicfg |= GSWIP_MII_CFG_MODE_RGMII;
		break;
	case PHY_INTERFACE_MODE_GMII:
		miicfg |= GSWIP_MII_CFG_MODE_GMII;
		break;
	default:
		dev_err(ds->dev,
			"Unsupported interface: %d\n", state->interface);
@@ -1588,7 +1639,31 @@ static int gswip_get_sset_count(struct dsa_switch *ds, int port, int sset)
	return ARRAY_SIZE(gswip_rmon_cnt);
}

static const struct dsa_switch_ops gswip_switch_ops = {
static const struct dsa_switch_ops gswip_xrx200_switch_ops = {
	.get_tag_protocol	= gswip_get_tag_protocol,
	.setup			= gswip_setup,
	.port_enable		= gswip_port_enable,
	.port_disable		= gswip_port_disable,
	.port_bridge_join	= gswip_port_bridge_join,
	.port_bridge_leave	= gswip_port_bridge_leave,
	.port_fast_age		= gswip_port_fast_age,
	.port_vlan_filtering	= gswip_port_vlan_filtering,
	.port_vlan_add		= gswip_port_vlan_add,
	.port_vlan_del		= gswip_port_vlan_del,
	.port_stp_state_set	= gswip_port_stp_state_set,
	.port_fdb_add		= gswip_port_fdb_add,
	.port_fdb_del		= gswip_port_fdb_del,
	.port_fdb_dump		= gswip_port_fdb_dump,
	.phylink_validate	= gswip_xrx200_phylink_validate,
	.phylink_mac_config	= gswip_phylink_mac_config,
	.phylink_mac_link_down	= gswip_phylink_mac_link_down,
	.phylink_mac_link_up	= gswip_phylink_mac_link_up,
	.get_strings		= gswip_get_strings,
	.get_ethtool_stats	= gswip_get_ethtool_stats,
	.get_sset_count		= gswip_get_sset_count,
};

static const struct dsa_switch_ops gswip_xrx300_switch_ops = {
	.get_tag_protocol	= gswip_get_tag_protocol,
	.setup			= gswip_setup,
	.port_enable		= gswip_port_enable,
@@ -1603,7 +1678,7 @@ static const struct dsa_switch_ops gswip_switch_ops = {
	.port_fdb_add		= gswip_port_fdb_add,
	.port_fdb_del		= gswip_port_fdb_del,
	.port_fdb_dump		= gswip_port_fdb_dump,
	.phylink_validate	= gswip_phylink_validate,
	.phylink_validate	= gswip_xrx300_phylink_validate,
	.phylink_mac_config	= gswip_phylink_mac_config,
	.phylink_mac_link_down	= gswip_phylink_mac_link_down,
	.phylink_mac_link_up	= gswip_phylink_mac_link_up,
@@ -1865,7 +1940,7 @@ static int gswip_probe(struct platform_device *pdev)
	priv->ds->dev = dev;
	priv->ds->num_ports = priv->hw_info->max_ports;
	priv->ds->priv = priv;
	priv->ds->ops = &gswip_switch_ops;
	priv->ds->ops = priv->hw_info->ops;
	priv->dev = dev;
	version = gswip_switch_r(priv, GSWIP_VERSION);

@@ -1946,10 +2021,19 @@ static int gswip_remove(struct platform_device *pdev)
static const struct gswip_hw_info gswip_xrx200 = {
	.max_ports = 7,
	.cpu_port = 6,
	.ops = &gswip_xrx200_switch_ops,
};

static const struct gswip_hw_info gswip_xrx300 = {
	.max_ports = 7,
	.cpu_port = 6,
	.ops = &gswip_xrx300_switch_ops,
};

static const struct of_device_id gswip_of_match[] = {
	{ .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 },
	{ .compatible = "lantiq,xrx300-gswip", .data = &gswip_xrx300 },
	{ .compatible = "lantiq,xrx330-gswip", .data = &gswip_xrx300 },
	{},
};
MODULE_DEVICE_TABLE(of, gswip_of_match);