Discussion:
[PATCH net-next 03/18] net: mvpp2: set the SMI PHY address when connecting to the PHY
Antoine Tenart
2017-07-24 13:48:33 UTC
Permalink
When connecting to the PHY, explicitly set the SMI PHY address in the
controller registers to configure a given port to be connected to the
selected PHY.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 1e592abc9067..6ffff929b22a 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -359,6 +359,8 @@
#define MVPP22_SMI_MISC_CFG_REG 0x1204
#define MVPP22_SMI_POLLING_EN BIT(10)

+#define MVPP22_SMI_PHY_ADDR(port) (0x120c + (port) * 0x4)
+
#define MVPP22_GMAC_BASE(port) (0x7000 + (port) * 0x1000 + 0xe00)

#define MVPP2_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff
@@ -5939,7 +5941,9 @@ static void mvpp21_get_mac_address(struct mvpp2_port *port, unsigned char *addr)

static int mvpp2_phy_connect(struct mvpp2_port *port)
{
+ struct mvpp2 *priv = port->priv;
struct phy_device *phy_dev;
+ u32 phy_addr;

phy_dev = of_phy_connect(port->dev, port->phy_node, mvpp2_link_event, 0,
port->phy_interface);
@@ -5954,6 +5958,16 @@ static int mvpp2_phy_connect(struct mvpp2_port *port)
port->duplex = 0;
port->speed = 0;

+ if (priv->hw_version != MVPP22)
+ return 0;
+
+ /* Set the SMI PHY address */
+ if (of_property_read_u32(port->phy_node, "reg", &phy_addr)) {
+ netdev_err(port->dev, "cannot find the PHY address\n");
+ return -EINVAL;
+ }
+
+ writel(phy_addr, priv->iface_base + MVPP22_SMI_PHY_ADDR(port->gop_id));
return 0;
}
--
2.13.3
Antoine Tenart
2017-07-24 13:48:32 UTC
Permalink
The macro defining the bit to toggle to bypass or not the
synchronization module is wrongly named. Writing 1 will disable bypass.
This patch s/MVPP22_CTRL4_SYNC_BYPASS/MVPP22_CTRL4_SYNC_BYPASS_DIS/.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index ee4ea195eb0b..1e592abc9067 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -339,7 +339,7 @@
#define MVPP22_GMAC_CTRL_4_REG 0x90
#define MVPP22_CTRL4_EXT_PIN_GMII_SEL BIT(0)
#define MVPP22_CTRL4_DP_CLK_SEL BIT(5)
-#define MVPP22_CTRL4_SYNC_BYPASS BIT(6)
+#define MVPP22_CTRL4_SYNC_BYPASS_DIS BIT(6)
#define MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE BIT(7)

/* Per-port XGMAC registers. PPv2.2 only, only for GOP port 0,
@@ -4195,7 +4195,7 @@ static void mvpp22_port_mii_set(struct mvpp2_port *port)
else
val &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL;
val &= ~MVPP22_CTRL4_DP_CLK_SEL;
- val |= MVPP22_CTRL4_SYNC_BYPASS;
+ val |= MVPP22_CTRL4_SYNC_BYPASS_DIS;
val |= MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
}
--
2.13.3
Antoine Tenart
2017-07-24 13:48:34 UTC
Permalink
This moves the mii configuration in the ndo_open path, to allow handling
different mii configurations later and to switch between these
configurations at runtime.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 6ffff929b22a..9d204ffb9b89 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -5862,6 +5862,7 @@ static void mvpp2_start_dev(struct mvpp2_port *port)
/* Enable interrupts on all CPUs */
mvpp2_interrupts_enable(port);

+ mvpp2_port_mii_set(port);
mvpp2_port_enable(port);
phy_start(ndev->phydev);
netif_tx_start_all_queues(port->dev);
@@ -6626,7 +6627,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,
goto err_free_stats;
}

- mvpp2_port_mii_set(port);
mvpp2_port_periodic_xon_disable(port);

if (priv->hw_version == MVPP21)
--
2.13.3
Antoine Tenart
2017-07-24 13:48:35 UTC
Permalink
This adds a routine to initialize the GMAC at the port level when using
a port. This wasn't done until this commit, and the mvpp2 driver was
relying on the bootloader/firmware initialization. This doesn't mean
everything is configured in the mvpp2 driver now, but it helps reducing
the gap.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 112 +++++++++++++++++++++++++++--------
1 file changed, 87 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 9d204ffb9b89..2573b0c27300 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -308,6 +308,7 @@
/* Per-port registers */
#define MVPP2_GMAC_CTRL_0_REG 0x0
#define MVPP2_GMAC_PORT_EN_MASK BIT(0)
+#define MVPP2_GMAC_PORT_TYPE_MASK BIT(1)
#define MVPP2_GMAC_MAX_RX_SIZE_OFFS 2
#define MVPP2_GMAC_MAX_RX_SIZE_MASK 0x7ffc
#define MVPP2_GMAC_MIB_CNTR_EN_MASK BIT(15)
@@ -319,16 +320,21 @@
#define MVPP2_GMAC_SA_LOW_OFFS 7
#define MVPP2_GMAC_CTRL_2_REG 0x8
#define MVPP2_GMAC_INBAND_AN_MASK BIT(0)
+#define MVPP2_GMAC_FLOW_CTRL_MASK GENMASK(2, 1)
#define MVPP2_GMAC_PCS_ENABLE_MASK BIT(3)
#define MVPP2_GMAC_PORT_RGMII_MASK BIT(4)
+#define MVPP2_GMAC_DISABLE_PADDING BIT(5)
#define MVPP2_GMAC_PORT_RESET_MASK BIT(6)
#define MVPP2_GMAC_AUTONEG_CONFIG 0xc
#define MVPP2_GMAC_FORCE_LINK_DOWN BIT(0)
#define MVPP2_GMAC_FORCE_LINK_PASS BIT(1)
+#define MVPP2_GMAC_IN_BAND_AUTONEG BIT(2)
+#define MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS BIT(3)
#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6)
#define MVPP2_GMAC_AN_SPEED_EN BIT(7)
#define MVPP2_GMAC_FC_ADV_EN BIT(9)
+#define MVPP2_GMAC_FLOW_CTRL_AUTONEG BIT(11)
#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
@@ -4173,6 +4179,84 @@ static void mvpp2_interrupts_unmask(void *arg)

/* Port configuration routines */

+static void mvpp2_port_mii_gmac_configure_mode(struct mvpp2_port *port)
+{
+ u32 val;
+
+ if (port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ val = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
+ val |= MVPP22_CTRL4_SYNC_BYPASS_DIS | MVPP22_CTRL4_DP_CLK_SEL |
+ MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+ val &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL;
+ writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ val |= MVPP2_GMAC_DISABLE_PADDING;
+ val &= ~MVPP2_GMAC_FLOW_CTRL_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+ } else if (port->phy_interface == PHY_INTERFACE_MODE_RGMII) {
+ val = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
+ val |= MVPP22_CTRL4_EXT_PIN_GMII_SEL |
+ MVPP22_CTRL4_SYNC_BYPASS_DIS |
+ MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+ val &= ~MVPP22_CTRL4_DP_CLK_SEL;
+ writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ val &= ~MVPP2_GMAC_DISABLE_PADDING;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+ }
+
+ /* The port is connected to a copper PHY */
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+ val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ val |= MVPP2_GMAC_IN_BAND_AUTONEG |
+ MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS |
+ MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_FLOW_CTRL_AUTONEG |
+ MVPP2_GMAC_AN_DUPLEX_EN;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+static void mvpp2_port_mii_gmac_configure(struct mvpp2_port *port)
+{
+ u32 val;
+
+ /* Force link down */
+ val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ val |= MVPP2_GMAC_FORCE_LINK_DOWN;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+
+ /* Set the GMAC in a reset state */
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ val |= MVPP2_GMAC_PORT_RESET_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ /* Configure the PCS and in-band AN */
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ if (port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ val |= MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PCS_ENABLE_MASK;
+ } else if (port->phy_interface == PHY_INTERFACE_MODE_RGMII) {
+ val |= MVPP2_GMAC_PORT_RGMII_MASK;
+ val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
+ }
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ mvpp2_port_mii_gmac_configure_mode(port);
+
+ /* Unset the GMAC reset state */
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ val &= ~MVPP2_GMAC_PORT_RESET_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ /* Stop forcing link down */
+ val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ val &= ~MVPP2_GMAC_FORCE_LINK_DOWN;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
static void mvpp22_port_mii_set(struct mvpp2_port *port)
{
u32 val;
@@ -4190,38 +4274,16 @@ static void mvpp22_port_mii_set(struct mvpp2_port *port)

writel(val, port->base + MVPP22_XLG_CTRL3_REG);
}
-
- val = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
- if (port->phy_interface == PHY_INTERFACE_MODE_RGMII)
- val |= MVPP22_CTRL4_EXT_PIN_GMII_SEL;
- else
- val &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL;
- val &= ~MVPP22_CTRL4_DP_CLK_SEL;
- val |= MVPP22_CTRL4_SYNC_BYPASS_DIS;
- val |= MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
- writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
}

static void mvpp2_port_mii_set(struct mvpp2_port *port)
{
- u32 val;
-
if (port->priv->hw_version == MVPP22)
mvpp22_port_mii_set(port);

- val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
-
- switch (port->phy_interface) {
- case PHY_INTERFACE_MODE_SGMII:
- val |= MVPP2_GMAC_INBAND_AN_MASK;
- break;
- case PHY_INTERFACE_MODE_RGMII:
- val |= MVPP2_GMAC_PORT_RGMII_MASK;
- default:
- val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
- }
-
- writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+ if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII)
+ mvpp2_port_mii_gmac_configure(port);
}

static void mvpp2_port_fc_adv_enable(struct mvpp2_port *port)
--
2.13.3
Antoine Tenart
2017-07-24 13:48:39 UTC
Permalink
This patch update the Marvell PPv2 driver to use named interrupts. A
compatibility path is kept to allow using device trees using the old dt
bindings. This change is needed as other interrupts will be used by the
PPv2 driver at some point.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index f6eb98d38ced..77eef2cc40a1 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -6789,10 +6789,20 @@ static int mvpp2_port_probe(struct platform_device *pdev,

port = netdev_priv(dev);

- port->irq = irq_of_parse_and_map(port_node, 0);
- if (port->irq <= 0) {
- err = -EINVAL;
- goto err_free_netdev;
+ if (of_get_property(port_node, "interrupt-names", NULL)) {
+ port->irq = of_irq_get_byname(port_node, "rx-shared");
+ if (port->irq <= 0) {
+ err = (port->irq == -EPROBE_DEFER) ?
+ -EPROBE_DEFER : -EINVAL;
+ goto err_free_netdev;
+ }
+ } else {
+ /* kept for dt compatibility */
+ port->irq = irq_of_parse_and_map(port_node, 0);
+ if (port->irq <= 0) {
+ err = -EINVAL;
+ goto err_free_netdev;
+ }
}

if (of_property_read_bool(port_node, "marvell,loopback"))
--
2.13.3
Sergei Shtylyov
2017-07-24 16:49:03 UTC
Permalink
Post by Antoine Tenart
This patch update the Marvell PPv2 driver to use named interrupts. A
compatibility path is kept to allow using device trees using the old dt
bindings. This change is needed as other interrupts will be used by the
PPv2 driver at some point.
---
drivers/net/ethernet/marvell/mvpp2.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index f6eb98d38ced..77eef2cc40a1 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -6789,10 +6789,20 @@ static int mvpp2_port_probe(struct platform_device *pdev,
port = netdev_priv(dev);
- port->irq = irq_of_parse_and_map(port_node, 0);
- if (port->irq <= 0) {
- err = -EINVAL;
- goto err_free_netdev;
+ if (of_get_property(port_node, "interrupt-names", NULL)) {
+ port->irq = of_irq_get_byname(port_node, "rx-shared");
+ if (port->irq <= 0) {
+ err = (port->irq == -EPROBE_DEFER) ?
+ -EPROBE_DEFER : -EINVAL;
Perhaps better:

err = port->irq ?: -EINVAL;
Post by Antoine Tenart
+ goto err_free_netdev;
+ }
+ } else {
+ /* kept for dt compatibility */
+ port->irq = irq_of_parse_and_map(port_node, 0);
+ if (port->irq <= 0) {
Note that irq_of_parse_and_map() returns *unsigned int*, so negative error
codes are not possible, 0 indicates bad IRQ.
Post by Antoine Tenart
+ err = -EINVAL;
+ goto err_free_netdev;
+ }
}
if (of_property_read_bool(port_node, "marvell,loopback"))
MBR, Sergei
Antoine Tenart
2017-07-25 08:45:58 UTC
Permalink
Hi Sergei,
Post by Sergei Shtylyov
Post by Antoine Tenart
+ if (of_get_property(port_node, "interrupt-names", NULL)) {
+ port->irq = of_irq_get_byname(port_node, "rx-shared");
+ if (port->irq <= 0) {
+ err = (port->irq == -EPROBE_DEFER) ?
+ -EPROBE_DEFER : -EINVAL;
err = port->irq ?: -EINVAL;
Sure.
Post by Sergei Shtylyov
Post by Antoine Tenart
+ goto err_free_netdev;
+ }
+ } else {
+ /* kept for dt compatibility */
+ port->irq = irq_of_parse_and_map(port_node, 0);
+ if (port->irq <= 0) {
Note that irq_of_parse_and_map() returns *unsigned int*, so negative
error codes are not possible, 0 indicates bad IRQ.
That right, I'll fix that!

Thanks,
Antoine
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Antoine Tenart
2017-07-24 13:48:42 UTC
Permalink
An interrupt-names property can be used in the PPv2 port description
bindings when more than a single interrupt (for rx) is used. Document
this new optional property.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
Documentation/devicetree/bindings/net/marvell-pp2.txt | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/marvell-pp2.txt b/Documentation/devicetree/bindings/net/marvell-pp2.txt
index 18ec66e51b0a..553aadceeeee 100644
--- a/Documentation/devicetree/bindings/net/marvell-pp2.txt
+++ b/Documentation/devicetree/bindings/net/marvell-pp2.txt
@@ -42,6 +42,9 @@ Optional properties (port):
- phy: a phandle to a phy node defining the PHY address (as the reg
property, a single integer).
- marvell,system-controller: a phandle to the system controller.
+- interrupt-names: if more than a single interrupt for rx is given, must
+ be the name associated to the interrupts listed. Valid
+ names are: "rx-shared", "link".

Example for marvell,armada-375-pp2:

@@ -82,18 +85,21 @@ cpm_ethernet: ***@0 {

eth0: eth0 {
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <0>;
gop-port-id = <0>;
};

eth1: eth1 {
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <1>;
gop-port-id = <2>;
};

eth2: eth2 {
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <2>;
gop-port-id = <3>;
};
--
2.13.3
Antoine Tenart
2017-07-24 13:48:43 UTC
Permalink
The PPv2 driver now uses named interrupts. Add the interrupt-names
property to the Ethernet ports to use this new functionality. This is
needed as other interrupt descriptions will be added to the Ethernet
ports at some point.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---

@Dave: Hi! This patch should go through the mvebu tree. Thanks!

arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 3 +++
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 3 +++
2 files changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
index 4c68605675a8..13763eefeb6e 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
@@ -70,6 +70,7 @@

cpm_eth0: eth0 {
interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <0>;
gop-port-id = <0>;
status = "disabled";
@@ -77,6 +78,7 @@

cpm_eth1: eth1 {
interrupts = <ICU_GRP_NSR 40 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <1>;
gop-port-id = <2>;
status = "disabled";
@@ -84,6 +86,7 @@

cpm_eth2: eth2 {
interrupts = <ICU_GRP_NSR 41 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <2>;
gop-port-id = <3>;
status = "disabled";
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
index 0dbb59811d00..0382cffef189 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
@@ -77,6 +77,7 @@

cps_eth0: eth0 {
interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <0>;
gop-port-id = <0>;
status = "disabled";
@@ -84,6 +85,7 @@

cps_eth1: eth1 {
interrupts = <ICU_GRP_NSR 40 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <1>;
gop-port-id = <2>;
status = "disabled";
@@ -91,6 +93,7 @@

cps_eth2: eth2 {
interrupts = <ICU_GRP_NSR 41 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared";
port-id = <2>;
gop-port-id = <3>;
status = "disabled";
--
2.13.3
Antoine Tenart
2017-07-24 13:48:46 UTC
Permalink
This patch enables the two GE/SFP ports. They are configured in 10GKR
mode by default. To do this the cpm_xdmio is enabled as well, and two
phy descriptions are added.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---

@Dave: Hi! This patch should go through the mvebu tree. Thanks!

arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts | 30 +++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
index abd39d1c1739..6cb4b000e1ac 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
@@ -127,6 +127,30 @@
};
};

+&cpm_xmdio {
+ status = "okay";
+
+ phy0: ethernet-***@0 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <0>;
+ };
+
+ phy1: ethernet-***@1 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <8>;
+ };
+};
+
+&cpm_ethernet {
+ status = "okay";
+};
+
+&cpm_eth0 {
+ status = "okay";
+ phy = <&phy0>;
+ phy-mode = "10gbase-kr";
+};
+
&cpm_sata0 {
/* CPM Lane 0 - U29 */
status = "okay";
@@ -154,6 +178,12 @@
status = "okay";
};

+&cps_eth0 {
+ status = "okay";
+ phy = <&phy1>;
+ phy-mode = "10gbase-kr";
+};
+
&cps_eth1 {
/* CPS Lane 0 - J5 (Gigabit RJ45) */
status = "okay";
--
2.13.3
Antoine Tenart
2017-07-24 13:48:40 UTC
Permalink
This patch adds the GoP link interrupt support for when a port isn't
connected to a PHY. Because of this the phylib callback is never called
and the link status management isn't done. This patch use the GoP link
interrupt in such cases to still have a minimal link management. Without
this patch ports not connected to a PHY cannot work.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 157 ++++++++++++++++++++++++++++++++++-
1 file changed, 154 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 77eef2cc40a1..33a7eb834855 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -339,16 +339,24 @@
#define MVPP2_GMAC_FLOW_CTRL_AUTONEG BIT(11)
#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
+#define MVPP2_GMAC_STATUS0 0x10
+#define MVPP2_GMAC_STATUS0_LINK_UP BIT(0)
#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
#define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6
#define MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK 0x1fc0
#define MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v) (((v) << 6) & \
MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
+#define MVPP22_GMAC_INT_STAT 0x20
+#define MVPP22_GMAC_INT_STAT_LINK BIT(1)
+#define MVPP22_GMAC_INT_MASK 0x24
+#define MVPP22_GMAC_INT_MASK_LINK_STAT BIT(1)
#define MVPP22_GMAC_CTRL_4_REG 0x90
#define MVPP22_CTRL4_EXT_PIN_GMII_SEL BIT(0)
#define MVPP22_CTRL4_DP_CLK_SEL BIT(5)
#define MVPP22_CTRL4_SYNC_BYPASS_DIS BIT(6)
#define MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE BIT(7)
+#define MVPP22_GMAC_INT_SUM_MASK 0xa4
+#define MVPP22_GMAC_INT_SUM_MASK_LINK_STAT BIT(1)

/* Per-port XGMAC registers. PPv2.2 only, only for GOP port 0,
* relative to port->base.
@@ -358,12 +366,19 @@
#define MVPP22_XLG_CTRL0_MAC_RESET_DIS BIT(1)
#define MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN BIT(7)
#define MVPP22_XLG_CTRL0_MIB_CNT_DIS BIT(14)
-
+#define MVPP22_XLG_STATUS 0x10c
+#define MVPP22_XLG_STATUS_LINK_UP BIT(0)
+#define MVPP22_XLG_INT_STAT 0x114
+#define MVPP22_XLG_INT_STAT_LINK BIT(1)
+#define MVPP22_XLG_INT_MASK 0x118
+#define MVPP22_XLG_INT_MASK_LINK BIT(1)
#define MVPP22_XLG_CTRL3_REG 0x11c
#define MVPP22_XLG_CTRL3_MACMODESELECT_MASK (7 << 13)
#define MVPP22_XLG_CTRL3_MACMODESELECT_GMAC (0 << 13)
#define MVPP22_XLG_CTRL3_MACMODESELECT_10G (1 << 13)
-
+#define MVPP22_XLG_EXT_INT_MASK 0x15c
+#define MVPP22_XLG_EXT_INT_MASK_XLG BIT(1)
+#define MVPP22_XLG_EXT_INT_MASK_GIG BIT(2)
#define MVPP22_XLG_CTRL4_REG 0x184
#define MVPP22_XLG_CTRL4_FWD_FC BIT(5)
#define MVPP22_XLG_CTRL4_FWD_PFC BIT(6)
@@ -814,6 +829,7 @@ struct mvpp2_port {
int gop_id;

int irq;
+ int link_irq;

struct mvpp2 *priv;

@@ -4330,6 +4346,63 @@ static int mvpp22_gop_init(struct mvpp2_port *port)
return -EINVAL;
}

+static void mvpp22_gop_unmask_irq(struct mvpp2_port *port)
+{
+ u32 val;
+
+ if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ /* Enable the GMAC link status irq for this port */
+ val = readl(port->base + MVPP22_GMAC_INT_SUM_MASK);
+ val |= MVPP22_GMAC_INT_SUM_MASK_LINK_STAT;
+ writel(val, port->base + MVPP22_GMAC_INT_SUM_MASK);
+ }
+
+ /* Enable the XLG/GIG irqs for this port */
+ val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
+ if (port->gop_id == 0 &&
+ port->phy_interface == PHY_INTERFACE_MODE_10GKR)
+ val |= MVPP22_XLG_EXT_INT_MASK_XLG;
+ else
+ val |= MVPP22_XLG_EXT_INT_MASK_GIG;
+ writel(val, port->base + MVPP22_XLG_EXT_INT_MASK);
+}
+
+static void mvpp22_gop_mask_irq(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
+ val &= ~(MVPP22_XLG_EXT_INT_MASK_XLG |
+ MVPP22_XLG_EXT_INT_MASK_GIG);
+ writel(val, port->base + MVPP22_XLG_EXT_INT_MASK);
+
+ if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ val = readl(port->base + MVPP22_GMAC_INT_SUM_MASK);
+ val &= ~MVPP22_GMAC_INT_SUM_MASK_LINK_STAT;
+ writel(val, port->base + MVPP22_GMAC_INT_SUM_MASK);
+ }
+}
+
+static void mvpp22_gop_setup_irq(struct mvpp2_port *port)
+{
+ u32 val;
+
+ if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ val = readl(port->base + MVPP22_GMAC_INT_MASK);
+ val |= MVPP22_GMAC_INT_MASK_LINK_STAT;
+ writel(val, port->base + MVPP22_GMAC_INT_MASK);
+ }
+
+ val = readl(port->base + MVPP22_XLG_INT_MASK);
+ val |= MVPP22_XLG_INT_MASK_LINK;
+ writel(val, port->base + MVPP22_XLG_INT_MASK);
+
+ mvpp22_gop_unmask_irq(port);
+}
+
static void mvpp2_port_mii_gmac_configure_mode(struct mvpp2_port *port)
{
u32 val;
@@ -5529,6 +5602,60 @@ static irqreturn_t mvpp2_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}

+/* Per-port interrupt for link status changes */
+static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
+{
+ struct mvpp2_port *port = (struct mvpp2_port *)dev_id;
+ struct net_device *dev = port->dev;
+ bool event = false, link = false;
+ u32 val;
+
+ mvpp22_gop_mask_irq(port);
+
+ if (port->gop_id == 0 &&
+ port->phy_interface == PHY_INTERFACE_MODE_10GKR) {
+ val = readl(port->base + MVPP22_XLG_INT_STAT);
+ if (val & MVPP22_XLG_INT_STAT_LINK) {
+ event = true;
+ val = readl(port->base + MVPP22_XLG_STATUS);
+ if (val & MVPP22_XLG_STATUS_LINK_UP)
+ link = true;
+ }
+ } else if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ val = readl(port->base + MVPP22_GMAC_INT_STAT);
+ if (val & MVPP22_GMAC_INT_STAT_LINK) {
+ event = true;
+ val = readl(port->base + MVPP2_GMAC_STATUS0);
+ if (val & MVPP2_GMAC_STATUS0_LINK_UP)
+ link = true;
+ }
+ }
+
+ if (!netif_running(dev) || !event)
+ goto handled;
+
+ if (link) {
+ mvpp2_interrupts_enable(port);
+
+ mvpp2_egress_enable(port);
+ mvpp2_ingress_enable(port);
+ netif_carrier_on(dev);
+ netif_tx_wake_all_queues(dev);
+ } else {
+ netif_tx_stop_all_queues(dev);
+ netif_carrier_off(dev);
+ mvpp2_ingress_disable(port);
+ mvpp2_egress_disable(port);
+
+ mvpp2_interrupts_disable(port);
+ }
+
+handled:
+ mvpp22_gop_unmask_irq(port);
+ return IRQ_HANDLED;
+}
+
/* Adjust link */
static void mvpp2_link_event(struct net_device *dev)
{
@@ -6221,6 +6348,7 @@ static void mvpp2_phy_disconnect(struct mvpp2_port *port)
static int mvpp2_open(struct net_device *dev)
{
struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2 *priv = port->priv;
unsigned char mac_bcast[ETH_ALEN] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int err;
@@ -6266,12 +6394,24 @@ static int mvpp2_open(struct net_device *dev)
goto err_cleanup_txqs;
}

+ if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq) {
+ err = request_irq(port->link_irq, mvpp2_link_status_isr, 0,
+ dev->name, port);
+ if (err) {
+ netdev_err(port->dev, "cannot request link IRQ %d\n",
+ port->link_irq);
+ goto err_free_irq;
+ }
+
+ mvpp22_gop_setup_irq(port);
+ }
+
/* In default link is down */
netif_carrier_off(port->dev);

err = mvpp2_phy_connect(port);
if (err < 0)
- goto err_free_irq;
+ goto err_free_link_irq;

/* Unmask interrupts on all CPUs */
on_each_cpu(mvpp2_interrupts_unmask, port, 1);
@@ -6280,6 +6420,8 @@ static int mvpp2_open(struct net_device *dev)

return 0;

+err_free_link_irq:
+ free_irq(port->link_irq, port);
err_free_irq:
free_irq(port->irq, port);
err_cleanup_txqs:
@@ -6796,6 +6938,15 @@ static int mvpp2_port_probe(struct platform_device *pdev,
-EPROBE_DEFER : -EINVAL;
goto err_free_netdev;
}
+
+ port->link_irq = of_irq_get_byname(port_node, "link");
+ if (port->link_irq == -EPROBE_DEFER) {
+ err = -EPROBE_DEFER;
+ goto err_free_irq;
+ }
+ if (port->link_irq <= 0)
+ /* the link irq is optional */
+ port->link_irq = 0;
} else {
/* kept for dt compatibility */
port->irq = irq_of_parse_and_map(port_node, 0);
--
2.13.3
Marcin Wojtas
2017-07-24 22:58:20 UTC
Permalink
Hi Antoine,

This patch requires also:

diff --git a/drivers/net/ethernet/marvell/mvpp2.c
b/drivers/net/ethernet/marvell/mvpp2.c
index 4694d4f..369819f 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -6625,6 +6625,7 @@ static int mvpp2_stop(struct net_device *dev)
{
struct mvpp2_port *port = netdev_priv(dev);
struct mvpp2_port_pcpu *port_pcpu;
+ struct mvpp2 *priv = port->priv;
int cpu;

mvpp2_stop_dev(port);
@@ -6633,6 +6634,10 @@ static int mvpp2_stop(struct net_device *dev)
/* Mask interrupts on all CPUs */
on_each_cpu(mvpp2_interrupts_mask, port, 1);

+ if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq) {
+ free_irq(port->link_irq, port);
+ }
+
free_irq(port->irq, port);
for_each_present_cpu(cpu) {
port_pcpu = per_cpu_ptr(port->pcpu, cpu);

Otherwise a sequence: ifconfig up/down/up results in faults.

Best regards,
Marcin
Post by Antoine Tenart
This patch adds the GoP link interrupt support for when a port isn't
connected to a PHY. Because of this the phylib callback is never called
and the link status management isn't done. This patch use the GoP link
interrupt in such cases to still have a minimal link management. Without
this patch ports not connected to a PHY cannot work.
---
drivers/net/ethernet/marvell/mvpp2.c | 157 ++++++++++++++++++++++++++++++++++-
1 file changed, 154 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 77eef2cc40a1..33a7eb834855 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -339,16 +339,24 @@
#define MVPP2_GMAC_FLOW_CTRL_AUTONEG BIT(11)
#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
+#define MVPP2_GMAC_STATUS0 0x10
+#define MVPP2_GMAC_STATUS0_LINK_UP BIT(0)
#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
#define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6
#define MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK 0x1fc0
#define MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v) (((v) << 6) & \
MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
+#define MVPP22_GMAC_INT_STAT 0x20
+#define MVPP22_GMAC_INT_STAT_LINK BIT(1)
+#define MVPP22_GMAC_INT_MASK 0x24
+#define MVPP22_GMAC_INT_MASK_LINK_STAT BIT(1)
#define MVPP22_GMAC_CTRL_4_REG 0x90
#define MVPP22_CTRL4_EXT_PIN_GMII_SEL BIT(0)
#define MVPP22_CTRL4_DP_CLK_SEL BIT(5)
#define MVPP22_CTRL4_SYNC_BYPASS_DIS BIT(6)
#define MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE BIT(7)
+#define MVPP22_GMAC_INT_SUM_MASK 0xa4
+#define MVPP22_GMAC_INT_SUM_MASK_LINK_STAT BIT(1)
/* Per-port XGMAC registers. PPv2.2 only, only for GOP port 0,
* relative to port->base.
@@ -358,12 +366,19 @@
#define MVPP22_XLG_CTRL0_MAC_RESET_DIS BIT(1)
#define MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN BIT(7)
#define MVPP22_XLG_CTRL0_MIB_CNT_DIS BIT(14)
-
+#define MVPP22_XLG_STATUS 0x10c
+#define MVPP22_XLG_STATUS_LINK_UP BIT(0)
+#define MVPP22_XLG_INT_STAT 0x114
+#define MVPP22_XLG_INT_STAT_LINK BIT(1)
+#define MVPP22_XLG_INT_MASK 0x118
+#define MVPP22_XLG_INT_MASK_LINK BIT(1)
#define MVPP22_XLG_CTRL3_REG 0x11c
#define MVPP22_XLG_CTRL3_MACMODESELECT_MASK (7 << 13)
#define MVPP22_XLG_CTRL3_MACMODESELECT_GMAC (0 << 13)
#define MVPP22_XLG_CTRL3_MACMODESELECT_10G (1 << 13)
-
+#define MVPP22_XLG_EXT_INT_MASK 0x15c
+#define MVPP22_XLG_EXT_INT_MASK_XLG BIT(1)
+#define MVPP22_XLG_EXT_INT_MASK_GIG BIT(2)
#define MVPP22_XLG_CTRL4_REG 0x184
#define MVPP22_XLG_CTRL4_FWD_FC BIT(5)
#define MVPP22_XLG_CTRL4_FWD_PFC BIT(6)
@@ -814,6 +829,7 @@ struct mvpp2_port {
int gop_id;
int irq;
+ int link_irq;
struct mvpp2 *priv;
@@ -4330,6 +4346,63 @@ static int mvpp22_gop_init(struct mvpp2_port *port)
return -EINVAL;
}
+static void mvpp22_gop_unmask_irq(struct mvpp2_port *port)
+{
+ u32 val;
+
+ if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ /* Enable the GMAC link status irq for this port */
+ val = readl(port->base + MVPP22_GMAC_INT_SUM_MASK);
+ val |= MVPP22_GMAC_INT_SUM_MASK_LINK_STAT;
+ writel(val, port->base + MVPP22_GMAC_INT_SUM_MASK);
+ }
+
+ /* Enable the XLG/GIG irqs for this port */
+ val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
+ if (port->gop_id == 0 &&
+ port->phy_interface == PHY_INTERFACE_MODE_10GKR)
+ val |= MVPP22_XLG_EXT_INT_MASK_XLG;
+ else
+ val |= MVPP22_XLG_EXT_INT_MASK_GIG;
+ writel(val, port->base + MVPP22_XLG_EXT_INT_MASK);
+}
+
+static void mvpp22_gop_mask_irq(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
+ val &= ~(MVPP22_XLG_EXT_INT_MASK_XLG |
+ MVPP22_XLG_EXT_INT_MASK_GIG);
+ writel(val, port->base + MVPP22_XLG_EXT_INT_MASK);
+
+ if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ val = readl(port->base + MVPP22_GMAC_INT_SUM_MASK);
+ val &= ~MVPP22_GMAC_INT_SUM_MASK_LINK_STAT;
+ writel(val, port->base + MVPP22_GMAC_INT_SUM_MASK);
+ }
+}
+
+static void mvpp22_gop_setup_irq(struct mvpp2_port *port)
+{
+ u32 val;
+
+ if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ val = readl(port->base + MVPP22_GMAC_INT_MASK);
+ val |= MVPP22_GMAC_INT_MASK_LINK_STAT;
+ writel(val, port->base + MVPP22_GMAC_INT_MASK);
+ }
+
+ val = readl(port->base + MVPP22_XLG_INT_MASK);
+ val |= MVPP22_XLG_INT_MASK_LINK;
+ writel(val, port->base + MVPP22_XLG_INT_MASK);
+
+ mvpp22_gop_unmask_irq(port);
+}
+
static void mvpp2_port_mii_gmac_configure_mode(struct mvpp2_port *port)
{
u32 val;
@@ -5529,6 +5602,60 @@ static irqreturn_t mvpp2_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+/* Per-port interrupt for link status changes */
+static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
+{
+ struct mvpp2_port *port = (struct mvpp2_port *)dev_id;
+ struct net_device *dev = port->dev;
+ bool event = false, link = false;
+ u32 val;
+
+ mvpp22_gop_mask_irq(port);
+
+ if (port->gop_id == 0 &&
+ port->phy_interface == PHY_INTERFACE_MODE_10GKR) {
+ val = readl(port->base + MVPP22_XLG_INT_STAT);
+ if (val & MVPP22_XLG_INT_STAT_LINK) {
+ event = true;
+ val = readl(port->base + MVPP22_XLG_STATUS);
+ if (val & MVPP22_XLG_STATUS_LINK_UP)
+ link = true;
+ }
+ } else if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ port->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ val = readl(port->base + MVPP22_GMAC_INT_STAT);
+ if (val & MVPP22_GMAC_INT_STAT_LINK) {
+ event = true;
+ val = readl(port->base + MVPP2_GMAC_STATUS0);
+ if (val & MVPP2_GMAC_STATUS0_LINK_UP)
+ link = true;
+ }
+ }
+
+ if (!netif_running(dev) || !event)
+ goto handled;
+
+ if (link) {
+ mvpp2_interrupts_enable(port);
+
+ mvpp2_egress_enable(port);
+ mvpp2_ingress_enable(port);
+ netif_carrier_on(dev);
+ netif_tx_wake_all_queues(dev);
+ } else {
+ netif_tx_stop_all_queues(dev);
+ netif_carrier_off(dev);
+ mvpp2_ingress_disable(port);
+ mvpp2_egress_disable(port);
+
+ mvpp2_interrupts_disable(port);
+ }
+
+ mvpp22_gop_unmask_irq(port);
+ return IRQ_HANDLED;
+}
+
/* Adjust link */
static void mvpp2_link_event(struct net_device *dev)
{
@@ -6221,6 +6348,7 @@ static void mvpp2_phy_disconnect(struct mvpp2_port *port)
static int mvpp2_open(struct net_device *dev)
{
struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2 *priv = port->priv;
unsigned char mac_bcast[ETH_ALEN] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int err;
@@ -6266,12 +6394,24 @@ static int mvpp2_open(struct net_device *dev)
goto err_cleanup_txqs;
}
+ if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq) {
+ err = request_irq(port->link_irq, mvpp2_link_status_isr, 0,
+ dev->name, port);
+ if (err) {
+ netdev_err(port->dev, "cannot request link IRQ %d\n",
+ port->link_irq);
+ goto err_free_irq;
+ }
+
+ mvpp22_gop_setup_irq(port);
+ }
+
/* In default link is down */
netif_carrier_off(port->dev);
err = mvpp2_phy_connect(port);
if (err < 0)
- goto err_free_irq;
+ goto err_free_link_irq;
/* Unmask interrupts on all CPUs */
on_each_cpu(mvpp2_interrupts_unmask, port, 1);
@@ -6280,6 +6420,8 @@ static int mvpp2_open(struct net_device *dev)
return 0;
+ free_irq(port->link_irq, port);
free_irq(port->irq, port);
@@ -6796,6 +6938,15 @@ static int mvpp2_port_probe(struct platform_device *pdev,
-EPROBE_DEFER : -EINVAL;
goto err_free_netdev;
}
+
+ port->link_irq = of_irq_get_byname(port_node, "link");
+ if (port->link_irq == -EPROBE_DEFER) {
+ err = -EPROBE_DEFER;
+ goto err_free_irq;
+ }
+ if (port->link_irq <= 0)
+ /* the link irq is optional */
+ port->link_irq = 0;
} else {
/* kept for dt compatibility */
port->irq = irq_of_parse_and_map(port_node, 0);
--
2.13.3
Antoine Tenart
2017-07-25 08:47:35 UTC
Permalink
Hi Marcin,
Post by Antoine Tenart
diff --git a/drivers/net/ethernet/marvell/mvpp2.c
b/drivers/net/ethernet/marvell/mvpp2.c
index 4694d4f..369819f 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -6625,6 +6625,7 @@ static int mvpp2_stop(struct net_device *dev)
{
struct mvpp2_port *port = netdev_priv(dev);
struct mvpp2_port_pcpu *port_pcpu;
+ struct mvpp2 *priv = port->priv;
int cpu;
mvpp2_stop_dev(port);
@@ -6633,6 +6634,10 @@ static int mvpp2_stop(struct net_device *dev)
/* Mask interrupts on all CPUs */
on_each_cpu(mvpp2_interrupts_mask, port, 1);
+ if (priv->hw_version == MVPP22 && !port->phy_node && port->link_irq) {
+ free_irq(port->link_irq, port);
+ }
+
free_irq(port->irq, port);
for_each_present_cpu(cpu) {
port_pcpu = per_cpu_ptr(port->pcpu, cpu);
Otherwise a sequence: ifconfig up/down/up results in faults.
You're right, thanks for the patch! I'll squash it in v2.

Thanks!
Antoine
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Thomas Petazzoni
2017-07-25 13:17:48 UTC
Permalink
Hello,
Post by Antoine Tenart
+
+ port->link_irq = of_irq_get_byname(port_node, "link");
+ if (port->link_irq == -EPROBE_DEFER) {
+ err = -EPROBE_DEFER;
+ goto err_free_irq;
+ }
+ if (port->link_irq <= 0)
+ /* the link irq is optional */
+ port->link_irq = 0;
You need to add the irq_dispose_mapping() call corresponding to this
of_irq_get_by_name() in the error path and in the remove path.

Best regards,

Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Antoine Tenart
2017-07-26 00:07:03 UTC
Permalink
Hi Thomas,
Post by Thomas Petazzoni
Post by Antoine Tenart
+
+ port->link_irq = of_irq_get_byname(port_node, "link");
+ if (port->link_irq == -EPROBE_DEFER) {
+ err = -EPROBE_DEFER;
+ goto err_free_irq;
+ }
+ if (port->link_irq <= 0)
+ /* the link irq is optional */
+ port->link_irq = 0;
You need to add the irq_dispose_mapping() call corresponding to this
of_irq_get_by_name() in the error path and in the remove path.
That's right. I'll fix that in v2.

Thanks!
Antoine
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Antoine Tenart
2017-07-24 13:48:31 UTC
Permalink
Cosmetic patch to use the same formatting rules on all register
definitions.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 88 ++++++++++++++++++------------------
1 file changed, 44 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 48d21c1e09f2..ee4ea195eb0b 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -187,18 +187,18 @@
#define MVPP2_MAX_ISR_RX_THRESHOLD 0xfffff0
#define MVPP21_ISR_RXQ_GROUP_REG(rxq) (0x5400 + 4 * (rxq))

-#define MVPP22_ISR_RXQ_GROUP_INDEX_REG 0x5400
+#define MVPP22_ISR_RXQ_GROUP_INDEX_REG 0x5400
#define MVPP22_ISR_RXQ_GROUP_INDEX_SUBGROUP_MASK 0xf
-#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_MASK 0x380
-#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET 7
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_MASK 0x380
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET 7

#define MVPP22_ISR_RXQ_GROUP_INDEX_SUBGROUP_MASK 0xf
-#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_MASK 0x380
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_MASK 0x380

-#define MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG 0x5404
-#define MVPP22_ISR_RXQ_SUB_GROUP_STARTQ_MASK 0x1f
-#define MVPP22_ISR_RXQ_SUB_GROUP_SIZE_MASK 0xf00
-#define MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET 8
+#define MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG 0x5404
+#define MVPP22_ISR_RXQ_SUB_GROUP_STARTQ_MASK 0x1f
+#define MVPP22_ISR_RXQ_SUB_GROUP_SIZE_MASK 0xf00
+#define MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET 8

#define MVPP2_ISR_ENABLE_REG(port) (0x5420 + 4 * (port))
#define MVPP2_ISR_ENABLE_INTERRUPT(mask) ((mask) & 0xffff)
@@ -265,7 +265,7 @@
#define MVPP2_BM_VIRT_RLS_REG 0x64c0
#define MVPP22_BM_ADDR_HIGH_RLS_REG 0x64c4
#define MVPP22_BM_ADDR_HIGH_PHYS_RLS_MASK 0xff
-#define MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK 0xff00
+#define MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK 0xff00
#define MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT 8

/* TX Scheduler registers */
@@ -307,57 +307,57 @@

/* Per-port registers */
#define MVPP2_GMAC_CTRL_0_REG 0x0
-#define MVPP2_GMAC_PORT_EN_MASK BIT(0)
-#define MVPP2_GMAC_MAX_RX_SIZE_OFFS 2
-#define MVPP2_GMAC_MAX_RX_SIZE_MASK 0x7ffc
-#define MVPP2_GMAC_MIB_CNTR_EN_MASK BIT(15)
+#define MVPP2_GMAC_PORT_EN_MASK BIT(0)
+#define MVPP2_GMAC_MAX_RX_SIZE_OFFS 2
+#define MVPP2_GMAC_MAX_RX_SIZE_MASK 0x7ffc
+#define MVPP2_GMAC_MIB_CNTR_EN_MASK BIT(15)
#define MVPP2_GMAC_CTRL_1_REG 0x4
-#define MVPP2_GMAC_PERIODIC_XON_EN_MASK BIT(1)
-#define MVPP2_GMAC_GMII_LB_EN_MASK BIT(5)
-#define MVPP2_GMAC_PCS_LB_EN_BIT 6
-#define MVPP2_GMAC_PCS_LB_EN_MASK BIT(6)
-#define MVPP2_GMAC_SA_LOW_OFFS 7
+#define MVPP2_GMAC_PERIODIC_XON_EN_MASK BIT(1)
+#define MVPP2_GMAC_GMII_LB_EN_MASK BIT(5)
+#define MVPP2_GMAC_PCS_LB_EN_BIT 6
+#define MVPP2_GMAC_PCS_LB_EN_MASK BIT(6)
+#define MVPP2_GMAC_SA_LOW_OFFS 7
#define MVPP2_GMAC_CTRL_2_REG 0x8
-#define MVPP2_GMAC_INBAND_AN_MASK BIT(0)
-#define MVPP2_GMAC_PCS_ENABLE_MASK BIT(3)
-#define MVPP2_GMAC_PORT_RGMII_MASK BIT(4)
-#define MVPP2_GMAC_PORT_RESET_MASK BIT(6)
+#define MVPP2_GMAC_INBAND_AN_MASK BIT(0)
+#define MVPP2_GMAC_PCS_ENABLE_MASK BIT(3)
+#define MVPP2_GMAC_PORT_RGMII_MASK BIT(4)
+#define MVPP2_GMAC_PORT_RESET_MASK BIT(6)
#define MVPP2_GMAC_AUTONEG_CONFIG 0xc
-#define MVPP2_GMAC_FORCE_LINK_DOWN BIT(0)
-#define MVPP2_GMAC_FORCE_LINK_PASS BIT(1)
-#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
-#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6)
-#define MVPP2_GMAC_AN_SPEED_EN BIT(7)
-#define MVPP2_GMAC_FC_ADV_EN BIT(9)
-#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
-#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
+#define MVPP2_GMAC_FORCE_LINK_DOWN BIT(0)
+#define MVPP2_GMAC_FORCE_LINK_PASS BIT(1)
+#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
+#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6)
+#define MVPP2_GMAC_AN_SPEED_EN BIT(7)
+#define MVPP2_GMAC_FC_ADV_EN BIT(9)
+#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
+#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
-#define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6
-#define MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK 0x1fc0
-#define MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v) (((v) << 6) & \
+#define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6
+#define MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK 0x1fc0
+#define MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v) (((v) << 6) & \
MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
#define MVPP22_GMAC_CTRL_4_REG 0x90
-#define MVPP22_CTRL4_EXT_PIN_GMII_SEL BIT(0)
-#define MVPP22_CTRL4_DP_CLK_SEL BIT(5)
-#define MVPP22_CTRL4_SYNC_BYPASS BIT(6)
-#define MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE BIT(7)
+#define MVPP22_CTRL4_EXT_PIN_GMII_SEL BIT(0)
+#define MVPP22_CTRL4_DP_CLK_SEL BIT(5)
+#define MVPP22_CTRL4_SYNC_BYPASS BIT(6)
+#define MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE BIT(7)

/* Per-port XGMAC registers. PPv2.2 only, only for GOP port 0,
* relative to port->base.
*/
#define MVPP22_XLG_CTRL0_REG 0x100
-#define MVPP22_XLG_CTRL0_PORT_EN BIT(0)
-#define MVPP22_XLG_CTRL0_MAC_RESET_DIS BIT(1)
-#define MVPP22_XLG_CTRL0_MIB_CNT_DIS BIT(14)
+#define MVPP22_XLG_CTRL0_PORT_EN BIT(0)
+#define MVPP22_XLG_CTRL0_MAC_RESET_DIS BIT(1)
+#define MVPP22_XLG_CTRL0_MIB_CNT_DIS BIT(14)

#define MVPP22_XLG_CTRL3_REG 0x11c
-#define MVPP22_XLG_CTRL3_MACMODESELECT_MASK (7 << 13)
-#define MVPP22_XLG_CTRL3_MACMODESELECT_GMAC (0 << 13)
-#define MVPP22_XLG_CTRL3_MACMODESELECT_10G (1 << 13)
+#define MVPP22_XLG_CTRL3_MACMODESELECT_MASK (7 << 13)
+#define MVPP22_XLG_CTRL3_MACMODESELECT_GMAC (0 << 13)
+#define MVPP22_XLG_CTRL3_MACMODESELECT_10G (1 << 13)

/* SMI registers. PPv2.2 only, relative to priv->iface_base. */
#define MVPP22_SMI_MISC_CFG_REG 0x1204
-#define MVPP22_SMI_POLLING_EN BIT(10)
+#define MVPP22_SMI_POLLING_EN BIT(10)

#define MVPP22_GMAC_BASE(port) (0x7000 + (port) * 0x1000 + 0xe00)
--
2.13.3
Antoine Tenart
2017-07-24 13:48:37 UTC
Permalink
This post might be inappropriate. Click to display it.
Antoine Tenart
2017-07-24 13:48:48 UTC
Permalink
This patch enables the SFP ports on the Armada 8040 DB as these ports
are now supported by the PPv2 driver (since the PHY is now optional).

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---

@Dave: Hi! This patch should go through the mvebu tree. Thanks!

arch/arm64/boot/dts/marvell/armada-8040-db.dts | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/marvell/armada-8040-db.dts b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
index 1e8f7242ed6f..83c7d8f2f710 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
@@ -136,6 +136,11 @@
status = "okay";
};

+&cpm_eth0 {
+ status = "okay";
+ phy-mode = "10gbase-kr";
+};
+
&cpm_eth2 {
status = "okay";
phy = <&phy1>;
@@ -179,6 +184,11 @@
status = "okay";
};

+&cps_eth0 {
+ status = "okay";
+ phy-mode = "10gbase-kr";
+};
+
&cps_eth1 {
status = "okay";
phy = <&phy0>;
--
2.13.3
Antoine Tenart
2017-07-24 13:48:38 UTC
Permalink
SFP ports do not necessarily need to have an Ethernet PHY between the
SoC and the actual physical port. However, the driver currently makes
the "phy" property mandatory, contrary to what is stated in the Device
Tree binding.

To allow handling the PPv2 controller on those boards, this patch makes
the PHY optional, and aligns the PPv2 driver on its device tree
documentation.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 948f5bd4ab18..f6eb98d38ced 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -6094,7 +6094,8 @@ static void mvpp2_start_dev(struct mvpp2_port *port)

mvpp2_port_mii_set(port);
mvpp2_port_enable(port);
- phy_start(ndev->phydev);
+ if (ndev->phydev)
+ phy_start(ndev->phydev);
netif_tx_start_all_queues(port->dev);
}

@@ -6118,7 +6119,8 @@ static void mvpp2_stop_dev(struct mvpp2_port *port)

mvpp2_egress_disable(port);
mvpp2_port_disable(port);
- phy_stop(ndev->phydev);
+ if (ndev->phydev)
+ phy_stop(ndev->phydev);
}

static int mvpp2_check_ringparam_valid(struct net_device *dev,
@@ -6176,6 +6178,10 @@ static int mvpp2_phy_connect(struct mvpp2_port *port)
struct phy_device *phy_dev;
u32 phy_addr;

+ /* No PHY is attached */
+ if (!port->phy_node)
+ return 0;
+
phy_dev = of_phy_connect(port->dev, port->phy_node, mvpp2_link_event, 0,
port->phy_interface);
if (!phy_dev) {
@@ -6206,6 +6212,9 @@ static void mvpp2_phy_disconnect(struct mvpp2_port *port)
{
struct net_device *ndev = port->dev;

+ if (!ndev->phydev)
+ return;
+
phy_disconnect(ndev->phydev);
}

@@ -6760,12 +6769,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,
return -ENOMEM;

phy_node = of_parse_phandle(port_node, "phy", 0);
- if (!phy_node) {
- dev_err(&pdev->dev, "missing phy\n");
- err = -ENODEV;
- goto err_free_netdev;
- }
-
phy_mode = of_get_phy_mode(port_node);
if (phy_mode < 0) {
dev_err(&pdev->dev, "incorrect phy mode\n");
--
2.13.3
Antoine Tenart
2017-07-24 13:48:47 UTC
Permalink
This patch enables the SFP port on the Armada 7040 DB as this port
is now supported by the PPv2 driver (since the PHY is now optional).

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---

@Dave: Hi! This patch should go through the mvebu tree. Thanks!

arch/arm64/boot/dts/marvell/armada-7040-db.dts | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
index 92c761c380d3..fa55e49e228e 100644
--- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
@@ -176,6 +176,11 @@
status = "okay";
};

+&cpm_eth0 {
+ status = "okay";
+ phy-mode = "10gbase-kr";
+};
+
&cpm_eth1 {
status = "okay";
phy = <&phy0>;
--
2.13.3
Antoine Tenart
2017-07-24 13:48:41 UTC
Permalink
This patch documents the new marvell,system-controller property used by
the Marvell ppv2 network driver.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
Documentation/devicetree/bindings/net/marvell-pp2.txt | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/net/marvell-pp2.txt b/Documentation/devicetree/bindings/net/marvell-pp2.txt
index 6b4956beff8c..18ec66e51b0a 100644
--- a/Documentation/devicetree/bindings/net/marvell-pp2.txt
+++ b/Documentation/devicetree/bindings/net/marvell-pp2.txt
@@ -41,6 +41,7 @@ Optional properties (port):
- marvell,loopback: port is loopback mode
- phy: a phandle to a phy node defining the PHY address (as the reg
property, a single integer).
+- marvell,system-controller: a phandle to the system controller.

Example for marvell,armada-375-pp2:
--
2.13.3
Antoine Tenart
2017-07-24 13:48:36 UTC
Permalink
This adds a routine to initialize the XLG MAC at the port level when
using a port and the XAUI/10GKR interface mode. This wasn't done until
this commit, and the mvpp2 driver was relying on the bootloader/firmware
initialization. This doesn't mean everything is configured in the mvpp2
driver now, but it helps reducing the gap.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 2573b0c27300..b3601561bbae 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -354,6 +354,7 @@
#define MVPP22_XLG_CTRL0_REG 0x100
#define MVPP22_XLG_CTRL0_PORT_EN BIT(0)
#define MVPP22_XLG_CTRL0_MAC_RESET_DIS BIT(1)
+#define MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN BIT(7)
#define MVPP22_XLG_CTRL0_MIB_CNT_DIS BIT(14)

#define MVPP22_XLG_CTRL3_REG 0x11c
@@ -361,6 +362,11 @@
#define MVPP22_XLG_CTRL3_MACMODESELECT_GMAC (0 << 13)
#define MVPP22_XLG_CTRL3_MACMODESELECT_10G (1 << 13)

+#define MVPP22_XLG_CTRL4_REG 0x184
+#define MVPP22_XLG_CTRL4_FWD_FC BIT(5)
+#define MVPP22_XLG_CTRL4_FWD_PFC BIT(6)
+#define MVPP22_XLG_CTRL4_MACMODSELECT_GMAC BIT(12)
+
/* SMI registers. PPv2.2 only, relative to priv->iface_base. */
#define MVPP22_SMI_MISC_CFG_REG 0x1204
#define MVPP22_SMI_POLLING_EN BIT(10)
@@ -4257,6 +4263,18 @@ static void mvpp2_port_mii_gmac_configure(struct mvpp2_port *port)
writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
}

+static void mvpp2_port_mii_xlg_configure(struct mvpp2_port *port)
+{
+ u32 val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ val |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+
+ val = readl(port->base + MVPP22_XLG_CTRL4_REG);
+ val &= ~MVPP22_XLG_CTRL4_MACMODSELECT_GMAC;
+ val |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC;
+ writel(val, port->base + MVPP22_XLG_CTRL4_REG);
+}
+
static void mvpp22_port_mii_set(struct mvpp2_port *port)
{
u32 val;
@@ -4284,6 +4302,8 @@ static void mvpp2_port_mii_set(struct mvpp2_port *port)
if (port->phy_interface == PHY_INTERFACE_MODE_RGMII ||
port->phy_interface == PHY_INTERFACE_MODE_SGMII)
mvpp2_port_mii_gmac_configure(port);
+ else if (port->phy_interface == PHY_INTERFACE_MODE_10GKR)
+ mvpp2_port_mii_xlg_configure(port);
}

static void mvpp2_port_fc_adv_enable(struct mvpp2_port *port)
--
2.13.3
Antoine Tenart
2017-07-24 13:48:45 UTC
Permalink
The network driver on Marvell SoC (7k/8k) needs to access some registers
in the system controller to configure its ports at runtime. This patch
adds a phandle reference to the syscon system controller node in the
ppv2 node.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---

@Dave: Hi! This patch should go through the mvebu tree. Thanks!

arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 1 +
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 1 +
2 files changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
index ebbdb3c97b7f..9278ba63b8ee 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
@@ -65,6 +65,7 @@
reg = <0x0 0x100000>, <0x129000 0xb000>;
clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>, <&cpm_clk 1 5>;
clock-names = "pp_clk", "gop_clk", "mg_clk";
+ marvell,system-controller = <&cpm_syscon0>;
status = "disabled";
dma-coherent;

diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
index a9ac5fc6def7..3515817b85f3 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
@@ -72,6 +72,7 @@
reg = <0x0 0x100000>, <0x129000 0xb000>;
clocks = <&cps_clk 1 3>, <&cps_clk 1 9>, <&cps_clk 1 5>;
clock-names = "pp_clk", "gop_clk", "mg_clk";
+ marvell,system-controller = <&cps_syscon0>;
status = "disabled";
dma-coherent;
--
2.13.3
Antoine Tenart
2017-07-24 13:48:44 UTC
Permalink
Ports interrupts are used by the PPv2 driver when no PHY is connected to
a port. This patch adds a description of these interrupts.

Signed-off-by: Antoine Tenart <***@free-electrons.com>
---

@Dave: Hi! This patch should go through the mvebu tree. Thanks!

arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 15 +++++++++------
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 15 +++++++++------
2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
index 13763eefeb6e..ebbdb3c97b7f 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
@@ -69,24 +69,27 @@
dma-coherent;

cpm_eth0: eth0 {
- interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "rx-shared";
+ interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>,
+ <ICU_GRP_NSR 129 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared", "link";
port-id = <0>;
gop-port-id = <0>;
status = "disabled";
};

cpm_eth1: eth1 {
- interrupts = <ICU_GRP_NSR 40 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "rx-shared";
+ interrupts = <ICU_GRP_NSR 40 IRQ_TYPE_LEVEL_HIGH>,
+ <ICU_GRP_NSR 128 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared", "link";
port-id = <1>;
gop-port-id = <2>;
status = "disabled";
};

cpm_eth2: eth2 {
- interrupts = <ICU_GRP_NSR 41 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "rx-shared";
+ interrupts = <ICU_GRP_NSR 41 IRQ_TYPE_LEVEL_HIGH>,
+ <ICU_GRP_NSR 127 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared", "link";
port-id = <2>;
gop-port-id = <3>;
status = "disabled";
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
index 0382cffef189..a9ac5fc6def7 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
@@ -76,24 +76,27 @@
dma-coherent;

cps_eth0: eth0 {
- interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "rx-shared";
+ interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>,
+ <ICU_GRP_NSR 129 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared", "link";
port-id = <0>;
gop-port-id = <0>;
status = "disabled";
};

cps_eth1: eth1 {
- interrupts = <ICU_GRP_NSR 40 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "rx-shared";
+ interrupts = <ICU_GRP_NSR 40 IRQ_TYPE_LEVEL_HIGH>,
+ <ICU_GRP_NSR 128 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared", "link";
port-id = <1>;
gop-port-id = <2>;
status = "disabled";
};

cps_eth2: eth2 {
- interrupts = <ICU_GRP_NSR 41 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "rx-shared";
+ interrupts = <ICU_GRP_NSR 41 IRQ_TYPE_LEVEL_HIGH>,
+ <ICU_GRP_NSR 127 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "rx-shared", "link";
port-id = <2>;
gop-port-id = <3>;
status = "disabled";
--
2.13.3
Sergei Shtylyov
2017-07-24 16:40:01 UTC
Permalink
Hello!
Post by Antoine Tenart
When connecting to the PHY, explicitly set the SMI PHY address in the
controller registers to configure a given port to be connected to the
selected PHY.
---
drivers/net/ethernet/marvell/mvpp2.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 1e592abc9067..6ffff929b22a 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
[...]
Post by Antoine Tenart
@@ -5954,6 +5958,16 @@ static int mvpp2_phy_connect(struct mvpp2_port *port)
port->duplex = 0;
port->speed = 0;
+ if (priv->hw_version != MVPP22)
+ return 0;
+
+ /* Set the SMI PHY address */
+ if (of_property_read_u32(port->phy_node, "reg", &phy_addr)) {
+ netdev_err(port->dev, "cannot find the PHY address\n");
+ return -EINVAL;
Wny not propagte the error from of_property_read_u32()?

[...]

MBR, Sergei
Antoine Tenart
2017-07-25 08:42:46 UTC
Permalink
Hi Sergei,
Post by Sergei Shtylyov
Post by Antoine Tenart
+ /* Set the SMI PHY address */
+ if (of_property_read_u32(port->phy_node, "reg", &phy_addr)) {
+ netdev_err(port->dev, "cannot find the PHY address\n");
+ return -EINVAL;
Wny not propagte the error from of_property_read_u32()?
I could do this, you're right.

Antoine
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Marcin Wojtas
2017-07-24 23:56:57 UTC
Permalink
Hi Antoine,

I stressed 10G interfaces with bidirectional traffic on A8040-DB, did
some up/down sequences and overall it seems stable (of course I needed
fix mentioned in patch 10/18). In a spare moment I'll give other
changes a scroll.

Best regards,
Marcin
Hi all,
This series aim two things: making the PPv2 driver less depending on
the firmware/bootloader initialization[1], and making the PPv2 driver
work when no Ethernet PHY is connected between a port and the physical
layer[2]. A few patches cleanup some small parts of the driver, and
newly supported interfaces are described in the device trees[3].
[1] The current implementation of the PPv2 driver relies on the
firmware/bootloader initialization to configure some parts, as the
Group of Ports (GoP) and the MACs (GMAC and/or XLG MAC --for 10G--).
The drawback is the kernel must be configured to match exactly what
the bootloader configures which is not convenient and is an issue
when using boards having an Ethernet port and an SFP port wired to
the same GoP port, as no dynamic configuration can be done.
This series adds the GoP and GMAC/XLG MAC initializations so that
the PPV2 does not have to rely on a previous initialization. One
part is still missing from this series, and that would be the
'comphy' which provides shared serdes PHYs and which must be
configured as well for a full kernel initialization to work. This
comphy support will be part of a following up series. (This
series was also tested with this 'comphy' support, as it's nearly
ready).
Patches 3-7, 11 and 14-15.
[2] While the documentation states the phy property in a port node is
optional, it is not in the current driver's implementation. This is
needed when no PHY is connected between a GoP port and the physical
layer (as for the two SFP ports on the 8040-db). One other feature
is missing to be able to use such ports: the port link interrupt
which allows not to rely on the phylib link event callback.
This series makes the phy optional in the PPv2 driver, and then adds
the support for the GoP port link interrupt to handle link status
changes on such ports.
Patches 8-10, 12-14.
[3] With the port link interrupt and optional PHY support, the two SFP
ports on the Marvell Armada 8040 DB can be described and used; as
well as the SFP port on the 7040 DB..
Cosmetic changes / fixes.
Patches 1, 2 and 16-18.
I intentionally grouped all these patches into one series, as we would
end up with series depending on each others (and I already did not
include all my patches in this one). If that's an issue for this series
to be reviewed/merged, I can easily split it into two series, with a
dependency of one on the other.
@Dave: Patches 13 to 18 should go through the mvebu tree, thanks :)
Thanks!
Antoine
net: mvpp2: unify register definitions coding style
net: mvpp2: fix the synchronization module bypass macro name
net: mvpp2: set the SMI PHY address when connecting to the PHY
net: mvpp2: move the mii configuration in the ndo_open path
net: mvpp2: initialize the GMAC when using a port
net: mvpp2: initialize the XLG MAC when using a port
net: mvpp2: initialize the GoP
net: mvpp2: make the phy optional
net: mvpp2: use named interrupts
net: mvpp2: use the GoP interrupt for link status changes
Documentation/bindings: net: marvell-pp2: add the system controller
Documentation/bindings: net: marvell-pp2: add the interrupt-names
arm64: dts: marvell: cp110: use named interrupts for the Ethernet
ports
arm64: dts: marvell: cp110: add PPv2 port interrupts
arm64: dts: marvell: add a reference to the sysctrl syscon in the ppv2
node
arm64: dts: marvell: mcbin: enable more networking ports
arm64: dts: marvell: 7040-db: enable the SFP port
arm64: dts: marvell: 8040-db: enable the SFP ports
.../devicetree/bindings/net/marvell-pp2.txt | 7 +
arch/arm64/boot/dts/marvell/armada-7040-db.dts | 5 +
arch/arm64/boot/dts/marvell/armada-8040-db.dts | 10 +
arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts | 30 ++
.../boot/dts/marvell/armada-cp110-master.dtsi | 13 +-
.../arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 13 +-
drivers/net/ethernet/marvell/mvpp2.c | 587 ++++++++++++++++++---
7 files changed, 575 insertions(+), 90 deletions(-)
--
2.13.3
Antoine Tenart
2017-07-25 08:48:39 UTC
Permalink
Hi Marcin,
Post by Marcin Wojtas
I stressed 10G interfaces with bidirectional traffic on A8040-DB, did
some up/down sequences and overall it seems stable (of course I needed
fix mentioned in patch 10/18). In a spare moment I'll give other
changes a scroll.
Thanks for testing! Can I had you Tested-by tag in v2?

Thanks,
Antoine
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Marcin Wojtas
2017-07-25 10:45:04 UTC
Permalink
Post by Antoine Tenart
Hi Marcin,
Post by Marcin Wojtas
I stressed 10G interfaces with bidirectional traffic on A8040-DB, did
some up/down sequences and overall it seems stable (of course I needed
fix mentioned in patch 10/18). In a spare moment I'll give other
changes a scroll.
Thanks for testing! Can I had you Tested-by tag in v2?
Sure.

Marcin
Loading...