Commit 3adffc76 authored by David S. Miller's avatar David S. Miller

Merge branch 'lantiq-xrx300-xrx330'

Aleksander Jan Bajkowski says:

====================
net: dsa: lantiq: add support for xRX300 and xRX330

Changed since v3:
	* fixed last compilation warning

Changed since v2:
	* fixed compilation warnings
	* removed example bindings for xrx330
	* patches has been refactored due to upstream changes

Changed since v1:
	* gswip_mii_mask_cfg() can now change port 3 on xRX330
	* changed alowed modes on port 0 and 5 for xRX300 and xRX330
	* moved common part of phylink validation into gswip_phylink_set_capab()
	* verify the compatible string against the hardware
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 853b0df9 ee83d824
...@@ -5,6 +5,10 @@ Required properties for GSWIP core: ...@@ -5,6 +5,10 @@ Required properties for GSWIP core:
- compatible : "lantiq,xrx200-gswip" for the embedded GSWIP in the - compatible : "lantiq,xrx200-gswip" for the embedded GSWIP in the
xRX200 SoC xRX200 SoC
"lantiq,xrx300-gswip" for the embedded GSWIP in the
xRX300 SoC
"lantiq,xrx330-gswip" for the embedded GSWIP in the
xRX330 SoC
- reg : memory range of the GSWIP core registers - reg : memory range of the GSWIP core registers
: memory range of the GSWIP MDIO registers : memory range of the GSWIP MDIO registers
: memory range of the GSWIP MII registers : memory range of the GSWIP MII registers
......
// SPDX-License-Identifier: GPL-2.0 // 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) 2010 Lantiq Deutschland
* Copyright (C) 2012 John Crispin <john@phrozen.org> * Copyright (C) 2012 John Crispin <john@phrozen.org>
...@@ -100,6 +100,7 @@ ...@@ -100,6 +100,7 @@
#define GSWIP_MII_CFG_MODE_RMIIP 0x2 #define GSWIP_MII_CFG_MODE_RMIIP 0x2
#define GSWIP_MII_CFG_MODE_RMIIM 0x3 #define GSWIP_MII_CFG_MODE_RMIIM 0x3
#define GSWIP_MII_CFG_MODE_RGMII 0x4 #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_MODE_MASK 0xf
#define GSWIP_MII_CFG_RATE_M2P5 0x00 #define GSWIP_MII_CFG_RATE_M2P5 0x00
#define GSWIP_MII_CFG_RATE_M25 0x10 #define GSWIP_MII_CFG_RATE_M25 0x10
...@@ -220,6 +221,7 @@ ...@@ -220,6 +221,7 @@
struct gswip_hw_info { struct gswip_hw_info {
int max_ports; int max_ports;
int cpu_port; int cpu_port;
const struct dsa_switch_ops *ops;
}; };
struct xway_gphy_match_data { struct xway_gphy_match_data {
...@@ -1384,12 +1386,42 @@ static int gswip_port_fdb_dump(struct dsa_switch *ds, int port, ...@@ -1384,12 +1386,42 @@ static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
return 0; return 0;
} }
static void gswip_phylink_validate(struct dsa_switch *ds, int port, static void gswip_phylink_set_capab(unsigned long *supported,
unsigned long *supported, struct phylink_link_state *state)
struct phylink_link_state *state)
{ {
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; __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) { switch (port) {
case 0: case 0:
case 1: case 1:
...@@ -1416,38 +1448,54 @@ static void gswip_phylink_validate(struct dsa_switch *ds, int port, ...@@ -1416,38 +1448,54 @@ static void gswip_phylink_validate(struct dsa_switch *ds, int port,
return; return;
} }
/* Allow all the expected bits */ gswip_phylink_set_capab(supported, state);
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 return;
* support Gigabit, including Half duplex
*/ unsupported:
if (state->interface != PHY_INTERFACE_MODE_MII && bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
state->interface != PHY_INTERFACE_MODE_REVMII && dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
state->interface != PHY_INTERFACE_MODE_RMII) { phy_modes(state->interface), port);
phylink_set(mask, 1000baseT_Full); }
phylink_set(mask, 1000baseT_Half);
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;
} }
phylink_set(mask, 10baseT_Half); gswip_phylink_set_capab(supported, state);
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);
return; return;
unsupported: unsupported:
bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
dev_err(ds->dev, "Unsupported interface '%s' for port %d\n", dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
phy_modes(state->interface), port); phy_modes(state->interface), port);
return;
} }
static void gswip_phylink_mac_config(struct dsa_switch *ds, int port, 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, ...@@ -1476,6 +1524,9 @@ static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_RGMII_TXID:
miicfg |= GSWIP_MII_CFG_MODE_RGMII; miicfg |= GSWIP_MII_CFG_MODE_RGMII;
break; break;
case PHY_INTERFACE_MODE_GMII:
miicfg |= GSWIP_MII_CFG_MODE_GMII;
break;
default: default:
dev_err(ds->dev, dev_err(ds->dev,
"Unsupported interface: %d\n", state->interface); "Unsupported interface: %d\n", state->interface);
...@@ -1588,7 +1639,7 @@ static int gswip_get_sset_count(struct dsa_switch *ds, int port, int sset) ...@@ -1588,7 +1639,7 @@ static int gswip_get_sset_count(struct dsa_switch *ds, int port, int sset)
return ARRAY_SIZE(gswip_rmon_cnt); 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, .get_tag_protocol = gswip_get_tag_protocol,
.setup = gswip_setup, .setup = gswip_setup,
.port_enable = gswip_port_enable, .port_enable = gswip_port_enable,
...@@ -1603,7 +1654,31 @@ static const struct dsa_switch_ops gswip_switch_ops = { ...@@ -1603,7 +1654,31 @@ static const struct dsa_switch_ops gswip_switch_ops = {
.port_fdb_add = gswip_port_fdb_add, .port_fdb_add = gswip_port_fdb_add,
.port_fdb_del = gswip_port_fdb_del, .port_fdb_del = gswip_port_fdb_del,
.port_fdb_dump = gswip_port_fdb_dump, .port_fdb_dump = gswip_port_fdb_dump,
.phylink_validate = gswip_phylink_validate, .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,
.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_xrx300_phylink_validate,
.phylink_mac_config = gswip_phylink_mac_config, .phylink_mac_config = gswip_phylink_mac_config,
.phylink_mac_link_down = gswip_phylink_mac_link_down, .phylink_mac_link_down = gswip_phylink_mac_link_down,
.phylink_mac_link_up = gswip_phylink_mac_link_up, .phylink_mac_link_up = gswip_phylink_mac_link_up,
...@@ -1832,7 +1907,7 @@ static int gswip_gphy_fw_list(struct gswip_priv *priv, ...@@ -1832,7 +1907,7 @@ static int gswip_gphy_fw_list(struct gswip_priv *priv,
static int gswip_probe(struct platform_device *pdev) static int gswip_probe(struct platform_device *pdev)
{ {
struct gswip_priv *priv; struct gswip_priv *priv;
struct device_node *mdio_np, *gphy_fw_np; struct device_node *np, *mdio_np, *gphy_fw_np;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int err; int err;
int i; int i;
...@@ -1865,10 +1940,28 @@ static int gswip_probe(struct platform_device *pdev) ...@@ -1865,10 +1940,28 @@ static int gswip_probe(struct platform_device *pdev)
priv->ds->dev = dev; priv->ds->dev = dev;
priv->ds->num_ports = priv->hw_info->max_ports; priv->ds->num_ports = priv->hw_info->max_ports;
priv->ds->priv = priv; priv->ds->priv = priv;
priv->ds->ops = &gswip_switch_ops; priv->ds->ops = priv->hw_info->ops;
priv->dev = dev; priv->dev = dev;
version = gswip_switch_r(priv, GSWIP_VERSION); version = gswip_switch_r(priv, GSWIP_VERSION);
np = dev->of_node;
switch (version) {
case GSWIP_VERSION_2_0:
case GSWIP_VERSION_2_1:
if (!of_device_is_compatible(np, "lantiq,xrx200-gswip"))
return -EINVAL;
break;
case GSWIP_VERSION_2_2:
case GSWIP_VERSION_2_2_ETC:
if (!of_device_is_compatible(np, "lantiq,xrx300-gswip") &&
!of_device_is_compatible(np, "lantiq,xrx330-gswip"))
return -EINVAL;
break;
default:
dev_err(dev, "unknown GSWIP version: 0x%x", version);
return -ENOENT;
}
/* bring up the mdio bus */ /* bring up the mdio bus */
gphy_fw_np = of_get_compatible_child(dev->of_node, "lantiq,gphy-fw"); gphy_fw_np = of_get_compatible_child(dev->of_node, "lantiq,gphy-fw");
if (gphy_fw_np) { if (gphy_fw_np) {
...@@ -1946,10 +2039,19 @@ static int gswip_remove(struct platform_device *pdev) ...@@ -1946,10 +2039,19 @@ static int gswip_remove(struct platform_device *pdev)
static const struct gswip_hw_info gswip_xrx200 = { static const struct gswip_hw_info gswip_xrx200 = {
.max_ports = 7, .max_ports = 7,
.cpu_port = 6, .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[] = { static const struct of_device_id gswip_of_match[] = {
{ .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 }, { .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); MODULE_DEVICE_TABLE(of, gswip_of_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment