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>
This commit is contained in:
commit
90bc72b13c
|
@ -2,7 +2,7 @@
|
|||
|
||||
Required properties:
|
||||
- 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
|
||||
- interrupts and/or interrupts-extended: must be two cells, the first cell
|
||||
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)
|
|||
}
|
||||
|
||||
/* 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 */
|
||||
ret = bcmgenet_init_rx_queues(priv->dev);
|
||||
|
@ -2589,7 +2590,8 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
|
|||
}
|
||||
|
||||
/* 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 */
|
||||
bcmgenet_init_tx_queues(priv->dev);
|
||||
|
@ -3420,12 +3422,48 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
|
|||
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[] = {
|
||||
{ .compatible = "brcm,genet-v1", .data = (void *)GENET_V1 },
|
||||
{ .compatible = "brcm,genet-v2", .data = (void *)GENET_V2 },
|
||||
{ .compatible = "brcm,genet-v3", .data = (void *)GENET_V3 },
|
||||
{ .compatible = "brcm,genet-v4", .data = (void *)GENET_V4 },
|
||||
{ .compatible = "brcm,genet-v5", .data = (void *)GENET_V5 },
|
||||
{ .compatible = "brcm,genet-v1", .data = &v1_plat_data },
|
||||
{ .compatible = "brcm,genet-v2", .data = &v2_plat_data },
|
||||
{ .compatible = "brcm,genet-v3", .data = &v3_plat_data },
|
||||
{ .compatible = "brcm,genet-v4", .data = &v4_plat_data },
|
||||
{ .compatible = "brcm,genet-v5", .data = &v5_plat_data },
|
||||
{ .compatible = "brcm,bcm2711-genet-v5", .data = &bcm2711_plat_data },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcmgenet_match);
|
||||
|
@ -3435,6 +3473,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
struct bcmgenet_platform_data *pd = pdev->dev.platform_data;
|
||||
struct device_node *dn = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id = NULL;
|
||||
const struct bcmgenet_plat_data *pdata;
|
||||
struct bcmgenet_priv *priv;
|
||||
struct net_device *dev;
|
||||
const void *macaddr;
|
||||
|
@ -3458,13 +3497,16 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
|
||||
priv = netdev_priv(dev);
|
||||
priv->irq0 = platform_get_irq(pdev, 0);
|
||||
priv->irq1 = platform_get_irq(pdev, 1);
|
||||
priv->wol_irq = platform_get_irq(pdev, 2);
|
||||
if (!priv->irq0 || !priv->irq1) {
|
||||
dev_err(&pdev->dev, "can't find IRQs\n");
|
||||
err = -EINVAL;
|
||||
if (priv->irq0 < 0) {
|
||||
err = priv->irq0;
|
||||
goto err;
|
||||
}
|
||||
priv->irq1 = platform_get_irq(pdev, 1);
|
||||
if (priv->irq1 < 0) {
|
||||
err = priv->irq1;
|
||||
goto err;
|
||||
}
|
||||
priv->wol_irq = platform_get_irq_optional(pdev, 2);
|
||||
|
||||
if (dn)
|
||||
macaddr = of_get_mac_address(dn);
|
||||
|
@ -3513,10 +3555,14 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
|
||||
priv->dev = dev;
|
||||
priv->pdev = pdev;
|
||||
if (of_id)
|
||||
priv->version = (enum bcmgenet_version)of_id->data;
|
||||
else
|
||||
if (of_id) {
|
||||
pdata = of_id->data;
|
||||
priv->version = pdata->version;
|
||||
priv->dma_max_burst_length = pdata->dma_max_burst_length;
|
||||
} else {
|
||||
priv->version = pd->genet_version;
|
||||
priv->dma_max_burst_length = DMA_MAX_BURST_LENGTH;
|
||||
}
|
||||
|
||||
priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
|
||||
if (IS_ERR(priv->clk)) {
|
||||
|
|
|
@ -664,6 +664,7 @@ struct bcmgenet_priv {
|
|||
bool crc_fwd_en;
|
||||
|
||||
unsigned int dma_rx_chk_bit;
|
||||
u32 dma_max_burst_length;
|
||||
|
||||
u32 msg_enable;
|
||||
|
||||
|
|
|
@ -213,11 +213,10 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
|
|||
udelay(2);
|
||||
}
|
||||
|
||||
priv->ext_phy = !priv->internal_phy &&
|
||||
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
|
||||
|
||||
switch (priv->phy_interface) {
|
||||
case PHY_INTERFACE_MODE_INTERNAL:
|
||||
phy_name = "internal PHY";
|
||||
/* fall through */
|
||||
case PHY_INTERFACE_MODE_MOCA:
|
||||
/* Irrespective of the actually configured PHY speed (100 or
|
||||
* 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)
|
|||
else
|
||||
port_ctrl = PORT_MODE_INT_EPHY;
|
||||
|
||||
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
|
||||
|
||||
if (priv->internal_phy) {
|
||||
phy_name = "internal PHY";
|
||||
} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
|
||||
if (!phy_name) {
|
||||
phy_name = "MoCA";
|
||||
bcmgenet_moca_phy_setup(priv);
|
||||
}
|
||||
|
@ -242,11 +237,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
|
|||
case PHY_INTERFACE_MODE_MII:
|
||||
phy_name = "external MII";
|
||||
phy_set_max_speed(phydev, SPEED_100);
|
||||
bcmgenet_sys_writel(priv,
|
||||
PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
|
||||
/* Restore the MII PHY after isolation */
|
||||
if (bmcr >= 0)
|
||||
phy_write(phydev, MII_BMCR, bmcr);
|
||||
port_ctrl = PORT_MODE_EXT_EPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_REVMII:
|
||||
|
@ -261,31 +252,43 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
|
|||
port_ctrl = PORT_MODE_EXT_RVMII_50;
|
||||
else
|
||||
port_ctrl = PORT_MODE_EXT_RVMII_25;
|
||||
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
/* RGMII_NO_ID: TXC transitions at the same time as TXD
|
||||
* (requires PCB or receiver-side delay)
|
||||
* RGMII: Add 2ns delay on TXC (90 degree shift)
|
||||
*
|
||||
* ID is implicitly disabled for 100Mbps (RG)MII operation.
|
||||
*/
|
||||
phy_name = "external RGMII (no delay)";
|
||||
id_mode_dis = BIT(16);
|
||||
/* fall through */
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
if (id_mode_dis)
|
||||
phy_name = "external RGMII (no delay)";
|
||||
else
|
||||
phy_name = "external RGMII (TX delay)";
|
||||
bcmgenet_sys_writel(priv,
|
||||
PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
|
||||
/* RGMII_TXID: Add 2ns delay on TXC (90 degree shift) */
|
||||
phy_name = "external RGMII (TX delay)";
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
phy_name = "external RGMII (RX delay)";
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
default:
|
||||
dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
|
||||
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
|
||||
* block for the interface to work
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue