Commit 90bc72b1 authored by David S. Miller's avatar David S. Miller

Merge branch 'ARM-Enable-GENET-support-for-RPi-4'

Stefan Wahren says:

====================
ARM: Enable GENET support for RPi 4

Raspberry Pi 4 uses the broadcom genet chip in version five.
This chip has a dma controller integrated. Up to now the maximal
burst size was hard-coded to 0x10. But it turns out that Raspberry Pi 4
does only work with the smaller maximal burst size of 0x8.

Additionally the patch series has some IRQ retrieval improvements and
adds support for a missing PHY mode.

This series based on Matthias Brugger's V1 series [1].

[1] - https://patchwork.kernel.org/cover/11186193/

Changes in V5:
- address Doug's comment

Changes in V4:
- rebased on current net-next
- remove RGMII_ID support
- remove fixes tag from patch 1
- add Florian's suggestions to patch 5

Changes in V3:
- introduce SoC-specific compatibles for GENET (incl. dt-binding)
- use platform_get_irq_optional for optional IRQ
- remove Fixes tag from IRQ error handling change
- move most of MDIO stuff to bcm2711.dtsi

Changes in V2:
- add 2 fixes for IRQ retrieval
- add support for missing PHY modes
- declare PHY mode RGMII RXID based on the default settings
- add alias to allow firmware append the MAC address
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2eea1fa8 da388022
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Required properties: Required properties:
- compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2", - compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2",
"brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5". "brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5", "brcm,bcm2711-genet-v5".
- reg: address and length of the register set for the device - reg: address and length of the register set for the device
- interrupts and/or interrupts-extended: must be two cells, the first cell - interrupts and/or interrupts-extended: must be two cells, the first cell
is the general purpose interrupt line, while the second cell is the is the general purpose interrupt line, while the second cell is the
......
...@@ -2576,7 +2576,8 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv) ...@@ -2576,7 +2576,8 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
} }
/* Init rDma */ /* Init rDma */
bcmgenet_rdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE); bcmgenet_rdma_writel(priv, priv->dma_max_burst_length,
DMA_SCB_BURST_SIZE);
/* Initialize Rx queues */ /* Initialize Rx queues */
ret = bcmgenet_init_rx_queues(priv->dev); ret = bcmgenet_init_rx_queues(priv->dev);
...@@ -2589,7 +2590,8 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv) ...@@ -2589,7 +2590,8 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
} }
/* Init tDma */ /* Init tDma */
bcmgenet_tdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE); bcmgenet_tdma_writel(priv, priv->dma_max_burst_length,
DMA_SCB_BURST_SIZE);
/* Initialize Tx queues */ /* Initialize Tx queues */
bcmgenet_init_tx_queues(priv->dev); bcmgenet_init_tx_queues(priv->dev);
...@@ -3420,12 +3422,48 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv) ...@@ -3420,12 +3422,48 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
params->words_per_bd); params->words_per_bd);
} }
struct bcmgenet_plat_data {
enum bcmgenet_version version;
u32 dma_max_burst_length;
};
static const struct bcmgenet_plat_data v1_plat_data = {
.version = GENET_V1,
.dma_max_burst_length = DMA_MAX_BURST_LENGTH,
};
static const struct bcmgenet_plat_data v2_plat_data = {
.version = GENET_V2,
.dma_max_burst_length = DMA_MAX_BURST_LENGTH,
};
static const struct bcmgenet_plat_data v3_plat_data = {
.version = GENET_V3,
.dma_max_burst_length = DMA_MAX_BURST_LENGTH,
};
static const struct bcmgenet_plat_data v4_plat_data = {
.version = GENET_V4,
.dma_max_burst_length = DMA_MAX_BURST_LENGTH,
};
static const struct bcmgenet_plat_data v5_plat_data = {
.version = GENET_V5,
.dma_max_burst_length = DMA_MAX_BURST_LENGTH,
};
static const struct bcmgenet_plat_data bcm2711_plat_data = {
.version = GENET_V5,
.dma_max_burst_length = 0x08,
};
static const struct of_device_id bcmgenet_match[] = { static const struct of_device_id bcmgenet_match[] = {
{ .compatible = "brcm,genet-v1", .data = (void *)GENET_V1 }, { .compatible = "brcm,genet-v1", .data = &v1_plat_data },
{ .compatible = "brcm,genet-v2", .data = (void *)GENET_V2 }, { .compatible = "brcm,genet-v2", .data = &v2_plat_data },
{ .compatible = "brcm,genet-v3", .data = (void *)GENET_V3 }, { .compatible = "brcm,genet-v3", .data = &v3_plat_data },
{ .compatible = "brcm,genet-v4", .data = (void *)GENET_V4 }, { .compatible = "brcm,genet-v4", .data = &v4_plat_data },
{ .compatible = "brcm,genet-v5", .data = (void *)GENET_V5 }, { .compatible = "brcm,genet-v5", .data = &v5_plat_data },
{ .compatible = "brcm,bcm2711-genet-v5", .data = &bcm2711_plat_data },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, bcmgenet_match); MODULE_DEVICE_TABLE(of, bcmgenet_match);
...@@ -3435,6 +3473,7 @@ static int bcmgenet_probe(struct platform_device *pdev) ...@@ -3435,6 +3473,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
struct bcmgenet_platform_data *pd = pdev->dev.platform_data; struct bcmgenet_platform_data *pd = pdev->dev.platform_data;
struct device_node *dn = pdev->dev.of_node; struct device_node *dn = pdev->dev.of_node;
const struct of_device_id *of_id = NULL; const struct of_device_id *of_id = NULL;
const struct bcmgenet_plat_data *pdata;
struct bcmgenet_priv *priv; struct bcmgenet_priv *priv;
struct net_device *dev; struct net_device *dev;
const void *macaddr; const void *macaddr;
...@@ -3458,13 +3497,16 @@ static int bcmgenet_probe(struct platform_device *pdev) ...@@ -3458,13 +3497,16 @@ static int bcmgenet_probe(struct platform_device *pdev)
priv = netdev_priv(dev); priv = netdev_priv(dev);
priv->irq0 = platform_get_irq(pdev, 0); priv->irq0 = platform_get_irq(pdev, 0);
if (priv->irq0 < 0) {
err = priv->irq0;
goto err;
}
priv->irq1 = platform_get_irq(pdev, 1); priv->irq1 = platform_get_irq(pdev, 1);
priv->wol_irq = platform_get_irq(pdev, 2); if (priv->irq1 < 0) {
if (!priv->irq0 || !priv->irq1) { err = priv->irq1;
dev_err(&pdev->dev, "can't find IRQs\n");
err = -EINVAL;
goto err; goto err;
} }
priv->wol_irq = platform_get_irq_optional(pdev, 2);
if (dn) if (dn)
macaddr = of_get_mac_address(dn); macaddr = of_get_mac_address(dn);
...@@ -3513,10 +3555,14 @@ static int bcmgenet_probe(struct platform_device *pdev) ...@@ -3513,10 +3555,14 @@ static int bcmgenet_probe(struct platform_device *pdev)
priv->dev = dev; priv->dev = dev;
priv->pdev = pdev; priv->pdev = pdev;
if (of_id) if (of_id) {
priv->version = (enum bcmgenet_version)of_id->data; pdata = of_id->data;
else priv->version = pdata->version;
priv->dma_max_burst_length = pdata->dma_max_burst_length;
} else {
priv->version = pd->genet_version; priv->version = pd->genet_version;
priv->dma_max_burst_length = DMA_MAX_BURST_LENGTH;
}
priv->clk = devm_clk_get(&priv->pdev->dev, "enet"); priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
if (IS_ERR(priv->clk)) { if (IS_ERR(priv->clk)) {
......
...@@ -664,6 +664,7 @@ struct bcmgenet_priv { ...@@ -664,6 +664,7 @@ struct bcmgenet_priv {
bool crc_fwd_en; bool crc_fwd_en;
unsigned int dma_rx_chk_bit; unsigned int dma_rx_chk_bit;
u32 dma_max_burst_length;
u32 msg_enable; u32 msg_enable;
......
...@@ -213,11 +213,10 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) ...@@ -213,11 +213,10 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
udelay(2); udelay(2);
} }
priv->ext_phy = !priv->internal_phy &&
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
switch (priv->phy_interface) { switch (priv->phy_interface) {
case PHY_INTERFACE_MODE_INTERNAL: case PHY_INTERFACE_MODE_INTERNAL:
phy_name = "internal PHY";
/* fall through */
case PHY_INTERFACE_MODE_MOCA: case PHY_INTERFACE_MODE_MOCA:
/* Irrespective of the actually configured PHY speed (100 or /* Irrespective of the actually configured PHY speed (100 or
* 1000) GENETv4 only has an internal GPHY so we will just end * 1000) GENETv4 only has an internal GPHY so we will just end
...@@ -229,11 +228,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) ...@@ -229,11 +228,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
else else
port_ctrl = PORT_MODE_INT_EPHY; port_ctrl = PORT_MODE_INT_EPHY;
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL); if (!phy_name) {
if (priv->internal_phy) {
phy_name = "internal PHY";
} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
phy_name = "MoCA"; phy_name = "MoCA";
bcmgenet_moca_phy_setup(priv); bcmgenet_moca_phy_setup(priv);
} }
...@@ -242,11 +237,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) ...@@ -242,11 +237,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_MII:
phy_name = "external MII"; phy_name = "external MII";
phy_set_max_speed(phydev, SPEED_100); phy_set_max_speed(phydev, SPEED_100);
bcmgenet_sys_writel(priv, port_ctrl = PORT_MODE_EXT_EPHY;
PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
/* Restore the MII PHY after isolation */
if (bmcr >= 0)
phy_write(phydev, MII_BMCR, bmcr);
break; break;
case PHY_INTERFACE_MODE_REVMII: case PHY_INTERFACE_MODE_REVMII:
...@@ -261,31 +252,43 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) ...@@ -261,31 +252,43 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
port_ctrl = PORT_MODE_EXT_RVMII_50; port_ctrl = PORT_MODE_EXT_RVMII_50;
else else
port_ctrl = PORT_MODE_EXT_RVMII_25; port_ctrl = PORT_MODE_EXT_RVMII_25;
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
break; break;
case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII:
/* RGMII_NO_ID: TXC transitions at the same time as TXD /* RGMII_NO_ID: TXC transitions at the same time as TXD
* (requires PCB or receiver-side delay) * (requires PCB or receiver-side delay)
* RGMII: Add 2ns delay on TXC (90 degree shift)
* *
* ID is implicitly disabled for 100Mbps (RG)MII operation. * ID is implicitly disabled for 100Mbps (RG)MII operation.
*/ */
phy_name = "external RGMII (no delay)";
id_mode_dis = BIT(16); id_mode_dis = BIT(16);
/* fall through */ port_ctrl = PORT_MODE_EXT_GPHY;
break;
case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_RGMII_TXID:
if (id_mode_dis) /* RGMII_TXID: Add 2ns delay on TXC (90 degree shift) */
phy_name = "external RGMII (no delay)"; phy_name = "external RGMII (TX delay)";
else port_ctrl = PORT_MODE_EXT_GPHY;
phy_name = "external RGMII (TX delay)"; break;
bcmgenet_sys_writel(priv,
PORT_MODE_EXT_GPHY, SYS_PORT_CTRL); case PHY_INTERFACE_MODE_RGMII_RXID:
phy_name = "external RGMII (RX delay)";
port_ctrl = PORT_MODE_EXT_GPHY;
break; break;
default: default:
dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface); dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
return -EINVAL; return -EINVAL;
} }
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
/* Restore the MII PHY after isolation */
if (bmcr >= 0)
phy_write(phydev, MII_BMCR, bmcr);
priv->ext_phy = !priv->internal_phy &&
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
/* This is an external PHY (xMII), so we need to enable the RGMII /* This is an external PHY (xMII), so we need to enable the RGMII
* block for the interface to work * block for the interface to work
*/ */
......
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