Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: David S. Miller <davem@davemloft.net>

+88 -38
+1 -1
Documentation/devicetree/bindings/net/brcm,bcmgenet.txt
··· 2 2 3 3 Required properties: 4 4 - compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2", 5 - "brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5". 5 + "brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5", "brcm,bcm2711-genet-v5". 6 6 - reg: address and length of the register set for the device 7 7 - interrupts and/or interrupts-extended: must be two cells, the first cell 8 8 is the general purpose interrupt line, while the second cell is the
+61 -15
drivers/net/ethernet/broadcom/genet/bcmgenet.c
··· 2576 2576 } 2577 2577 2578 2578 /* Init rDma */ 2579 - bcmgenet_rdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE); 2579 + bcmgenet_rdma_writel(priv, priv->dma_max_burst_length, 2580 + DMA_SCB_BURST_SIZE); 2580 2581 2581 2582 /* Initialize Rx queues */ 2582 2583 ret = bcmgenet_init_rx_queues(priv->dev); ··· 2590 2589 } 2591 2590 2592 2591 /* Init tDma */ 2593 - bcmgenet_tdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE); 2592 + bcmgenet_tdma_writel(priv, priv->dma_max_burst_length, 2593 + DMA_SCB_BURST_SIZE); 2594 2594 2595 2595 /* Initialize Tx queues */ 2596 2596 bcmgenet_init_tx_queues(priv->dev); ··· 3422 3420 params->words_per_bd); 3423 3421 } 3424 3422 3423 + struct bcmgenet_plat_data { 3424 + enum bcmgenet_version version; 3425 + u32 dma_max_burst_length; 3426 + }; 3427 + 3428 + static const struct bcmgenet_plat_data v1_plat_data = { 3429 + .version = GENET_V1, 3430 + .dma_max_burst_length = DMA_MAX_BURST_LENGTH, 3431 + }; 3432 + 3433 + static const struct bcmgenet_plat_data v2_plat_data = { 3434 + .version = GENET_V2, 3435 + .dma_max_burst_length = DMA_MAX_BURST_LENGTH, 3436 + }; 3437 + 3438 + static const struct bcmgenet_plat_data v3_plat_data = { 3439 + .version = GENET_V3, 3440 + .dma_max_burst_length = DMA_MAX_BURST_LENGTH, 3441 + }; 3442 + 3443 + static const struct bcmgenet_plat_data v4_plat_data = { 3444 + .version = GENET_V4, 3445 + .dma_max_burst_length = DMA_MAX_BURST_LENGTH, 3446 + }; 3447 + 3448 + static const struct bcmgenet_plat_data v5_plat_data = { 3449 + .version = GENET_V5, 3450 + .dma_max_burst_length = DMA_MAX_BURST_LENGTH, 3451 + }; 3452 + 3453 + static const struct bcmgenet_plat_data bcm2711_plat_data = { 3454 + .version = GENET_V5, 3455 + .dma_max_burst_length = 0x08, 3456 + }; 3457 + 3425 3458 static const struct of_device_id bcmgenet_match[] = { 3426 - { .compatible = "brcm,genet-v1", .data = (void *)GENET_V1 }, 3427 - { .compatible = "brcm,genet-v2", .data = (void *)GENET_V2 }, 3428 - { .compatible = "brcm,genet-v3", .data = (void *)GENET_V3 }, 3429 - { .compatible = "brcm,genet-v4", .data = (void *)GENET_V4 }, 3430 - { .compatible = "brcm,genet-v5", .data = (void *)GENET_V5 }, 3459 + { .compatible = "brcm,genet-v1", .data = &v1_plat_data }, 3460 + { .compatible = "brcm,genet-v2", .data = &v2_plat_data }, 3461 + { .compatible = "brcm,genet-v3", .data = &v3_plat_data }, 3462 + { .compatible = "brcm,genet-v4", .data = &v4_plat_data }, 3463 + { .compatible = "brcm,genet-v5", .data = &v5_plat_data }, 3464 + { .compatible = "brcm,bcm2711-genet-v5", .data = &bcm2711_plat_data }, 3431 3465 { }, 3432 3466 }; 3433 3467 MODULE_DEVICE_TABLE(of, bcmgenet_match); ··· 3473 3435 struct bcmgenet_platform_data *pd = pdev->dev.platform_data; 3474 3436 struct device_node *dn = pdev->dev.of_node; 3475 3437 const struct of_device_id *of_id = NULL; 3438 + const struct bcmgenet_plat_data *pdata; 3476 3439 struct bcmgenet_priv *priv; 3477 3440 struct net_device *dev; 3478 3441 const void *macaddr; ··· 3497 3458 3498 3459 priv = netdev_priv(dev); 3499 3460 priv->irq0 = platform_get_irq(pdev, 0); 3500 - priv->irq1 = platform_get_irq(pdev, 1); 3501 - priv->wol_irq = platform_get_irq(pdev, 2); 3502 - if (!priv->irq0 || !priv->irq1) { 3503 - dev_err(&pdev->dev, "can't find IRQs\n"); 3504 - err = -EINVAL; 3461 + if (priv->irq0 < 0) { 3462 + err = priv->irq0; 3505 3463 goto err; 3506 3464 } 3465 + priv->irq1 = platform_get_irq(pdev, 1); 3466 + if (priv->irq1 < 0) { 3467 + err = priv->irq1; 3468 + goto err; 3469 + } 3470 + priv->wol_irq = platform_get_irq_optional(pdev, 2); 3507 3471 3508 3472 if (dn) 3509 3473 macaddr = of_get_mac_address(dn); ··· 3555 3513 3556 3514 priv->dev = dev; 3557 3515 priv->pdev = pdev; 3558 - if (of_id) 3559 - priv->version = (enum bcmgenet_version)of_id->data; 3560 - else 3516 + if (of_id) { 3517 + pdata = of_id->data; 3518 + priv->version = pdata->version; 3519 + priv->dma_max_burst_length = pdata->dma_max_burst_length; 3520 + } else { 3561 3521 priv->version = pd->genet_version; 3522 + priv->dma_max_burst_length = DMA_MAX_BURST_LENGTH; 3523 + } 3562 3524 3563 3525 priv->clk = devm_clk_get(&priv->pdev->dev, "enet"); 3564 3526 if (IS_ERR(priv->clk)) {
+1
drivers/net/ethernet/broadcom/genet/bcmgenet.h
··· 664 664 bool crc_fwd_en; 665 665 666 666 unsigned int dma_rx_chk_bit; 667 + u32 dma_max_burst_length; 667 668 668 669 u32 msg_enable; 669 670
+25 -22
drivers/net/ethernet/broadcom/genet/bcmmii.c
··· 213 213 udelay(2); 214 214 } 215 215 216 - priv->ext_phy = !priv->internal_phy && 217 - (priv->phy_interface != PHY_INTERFACE_MODE_MOCA); 218 - 219 216 switch (priv->phy_interface) { 220 217 case PHY_INTERFACE_MODE_INTERNAL: 218 + phy_name = "internal PHY"; 219 + /* fall through */ 221 220 case PHY_INTERFACE_MODE_MOCA: 222 221 /* Irrespective of the actually configured PHY speed (100 or 223 222 * 1000) GENETv4 only has an internal GPHY so we will just end ··· 228 229 else 229 230 port_ctrl = PORT_MODE_INT_EPHY; 230 231 231 - bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL); 232 - 233 - if (priv->internal_phy) { 234 - phy_name = "internal PHY"; 235 - } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { 232 + if (!phy_name) { 236 233 phy_name = "MoCA"; 237 234 bcmgenet_moca_phy_setup(priv); 238 235 } ··· 237 242 case PHY_INTERFACE_MODE_MII: 238 243 phy_name = "external MII"; 239 244 phy_set_max_speed(phydev, SPEED_100); 240 - bcmgenet_sys_writel(priv, 241 - PORT_MODE_EXT_EPHY, SYS_PORT_CTRL); 242 - /* Restore the MII PHY after isolation */ 243 - if (bmcr >= 0) 244 - phy_write(phydev, MII_BMCR, bmcr); 245 + port_ctrl = PORT_MODE_EXT_EPHY; 245 246 break; 246 247 247 248 case PHY_INTERFACE_MODE_REVMII: ··· 252 261 port_ctrl = PORT_MODE_EXT_RVMII_50; 253 262 else 254 263 port_ctrl = PORT_MODE_EXT_RVMII_25; 255 - bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL); 256 264 break; 257 265 258 266 case PHY_INTERFACE_MODE_RGMII: 259 267 /* RGMII_NO_ID: TXC transitions at the same time as TXD 260 268 * (requires PCB or receiver-side delay) 261 - * RGMII: Add 2ns delay on TXC (90 degree shift) 262 269 * 263 270 * ID is implicitly disabled for 100Mbps (RG)MII operation. 264 271 */ 272 + phy_name = "external RGMII (no delay)"; 265 273 id_mode_dis = BIT(16); 266 - /* fall through */ 274 + port_ctrl = PORT_MODE_EXT_GPHY; 275 + break; 276 + 267 277 case PHY_INTERFACE_MODE_RGMII_TXID: 268 - if (id_mode_dis) 269 - phy_name = "external RGMII (no delay)"; 270 - else 271 - phy_name = "external RGMII (TX delay)"; 272 - bcmgenet_sys_writel(priv, 273 - PORT_MODE_EXT_GPHY, SYS_PORT_CTRL); 278 + /* RGMII_TXID: Add 2ns delay on TXC (90 degree shift) */ 279 + phy_name = "external RGMII (TX delay)"; 280 + port_ctrl = PORT_MODE_EXT_GPHY; 281 + break; 282 + 283 + case PHY_INTERFACE_MODE_RGMII_RXID: 284 + phy_name = "external RGMII (RX delay)"; 285 + port_ctrl = PORT_MODE_EXT_GPHY; 274 286 break; 275 287 default: 276 288 dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface); 277 289 return -EINVAL; 278 290 } 291 + 292 + bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL); 293 + 294 + /* Restore the MII PHY after isolation */ 295 + if (bmcr >= 0) 296 + phy_write(phydev, MII_BMCR, bmcr); 297 + 298 + priv->ext_phy = !priv->internal_phy && 299 + (priv->phy_interface != PHY_INTERFACE_MODE_MOCA); 279 300 280 301 /* This is an external PHY (xMII), so we need to enable the RGMII 281 302 * block for the interface to work