diff options
Diffstat (limited to 'drivers/net/fec_imx.c')
-rw-r--r-- | drivers/net/fec_imx.c | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 5ef1d4359e..75a6596282 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -25,6 +25,22 @@ #include "fec_imx.h" +static int fec_set_promisc(struct eth_device *edev, bool enable) +{ + struct fec_priv *fec = (struct fec_priv *)edev->priv; + u32 rcntl; + + rcntl = readl(fec->regs + FEC_R_CNTRL); + + if (enable) + rcntl |= FEC_R_CNTRL_PROMISC; + else + rcntl &= ~FEC_R_CNTRL_PROMISC; + + writel(rcntl, fec->regs + FEC_R_CNTRL); + + return 0; +} /* * MII-interface related functions @@ -257,10 +273,15 @@ static int fec_init(struct eth_device *dev) */ writel(0x00000000, fec->regs + FEC_IMASK); + rcntl = readl(fec->regs + FEC_R_CNTRL); + + /* Keep promisc setting */ + rcntl &= FEC_R_CNTRL_PROMISC; + /* * Set FEC-Lite receive control register(R_CNTRL): */ - rcntl = FEC_R_CNTRL_MAX_FL(1518); + rcntl |= FEC_R_CNTRL_MAX_FL(1518); rcntl |= FEC_R_CNTRL_MII_MODE; /* @@ -320,6 +341,10 @@ static int fec_init(struct eth_device *dev) /* size of each buffer */ writel(FEC_MAX_PKT_SIZE, fec->regs + FEC_EMRBR); + /* set rx and tx buffer descriptor base address */ + writel(virt_to_phys(fec->tbd_base), fec->regs + FEC_ETDSR); + writel(virt_to_phys(fec->rbd_base), fec->regs + FEC_ERDSR); + return 0; } @@ -359,6 +384,8 @@ static int fec_open(struct eth_device *edev) if (fec->phy_init) fec->phy_init(edev->phydev); + fec_init(edev); + /* * Initialize RxBD/TxBD rings */ @@ -514,6 +541,7 @@ static int fec_recv(struct eth_device *dev) * Check if any critical events have happened */ ievent = readl(fec->regs + FEC_IEVENT); + ievent &= ~FEC_IEVENT_MII; writel(ievent, fec->regs + FEC_IEVENT); if (ievent & FEC_IEVENT_BABT) { @@ -561,7 +589,7 @@ static int fec_recv(struct eth_device *dev) * fixup and net_receive below would get * proper data */ - dma_sync_single_for_cpu((unsigned long)frame, + dma_sync_single_for_cpu(fec->dev, (unsigned long)frame, data_length, DMA_FROM_DEVICE); if (fec_is_imx28(fec)) @@ -573,7 +601,7 @@ static int fec_recv(struct eth_device *dev) */ len = data_length - 4; net_receive(dev, frame, len); - dma_sync_single_for_device((unsigned long)frame, + dma_sync_single_for_device(fec->dev, (unsigned long)frame, data_length, DMA_FROM_DEVICE); } @@ -624,25 +652,25 @@ static void fec_free_receive_packets(struct fec_priv *fec, int count, int size) } #ifdef CONFIG_OFDEVICE -static int fec_probe_dt(struct device_d *dev, struct fec_priv *fec) +static int fec_probe_dt(struct device *dev, struct fec_priv *fec) { struct device_node *mdiobus; int ret; - ret = of_get_phy_mode(dev->device_node); + ret = of_get_phy_mode(dev->of_node); if (ret < 0) fec->interface = PHY_INTERFACE_MODE_MII; else fec->interface = ret; - mdiobus = of_get_child_by_name(dev->device_node, "mdio"); + mdiobus = of_get_child_by_name(dev->of_node, "mdio"); if (mdiobus) - fec->miibus.dev.device_node = mdiobus; + fec->miibus.dev.of_node = mdiobus; return 0; } #else -static int fec_probe_dt(struct device_d *dev, struct fec_priv *fec) +static int fec_probe_dt(struct device *dev, struct fec_priv *fec) { return -ENODEV; } @@ -704,10 +732,10 @@ static int fec_clk_get(struct fec_priv *fec) { int i, err = 0; static const char *clk_names[ARRAY_SIZE(fec->clk)] = { - "ipg", "ahb", "ptp" + "ipg", "ahb", }; static const char *opt_clk_names[ARRAY_SIZE(fec->opt_clk)] = { - "enet_clk_ref", "enet_out", + "enet_clk_ref", "enet_out", "ptp" }; for (i = 0; i < ARRAY_SIZE(fec->clk); i++) { @@ -715,7 +743,7 @@ static int fec_clk_get(struct fec_priv *fec) if (IS_ERR(fec->clk[i])) { err = PTR_ERR(fec->clk[i]); fec_clk_put(fec); - break; + return err; } } @@ -729,7 +757,7 @@ static int fec_clk_get(struct fec_priv *fec) return err; } -static int fec_probe(struct device_d *dev) +static int fec_probe(struct device *dev) { struct resource *iores; struct fec_platform_data *pdata = (struct fec_platform_data *)dev->platform_data; @@ -738,14 +766,17 @@ static int fec_probe(struct device_d *dev) void *base; int ret; enum fec_type type; + void const *type_v; int phy_reset; u32 msec = 1, phy_post_delay = 0; u32 reg; - ret = dev_get_drvdata(dev, (const void **)&type); + ret = dev_get_drvdata(dev, &type_v); if (ret) return ret; + type = (uintptr_t)(type_v); + fec = xzalloc(sizeof(*fec)); fec->type = type; fec->dev = dev; @@ -758,6 +789,7 @@ static int fec_probe(struct device_d *dev) edev->halt = fec_halt; edev->get_ethaddr = fec_get_hwaddr; edev->set_ethaddr = fec_set_hwaddr; + edev->set_promisc = fec_set_promisc; edev->parent = dev; dma_set_mask(dev, DMA_BIT_MASK(32)); @@ -793,10 +825,11 @@ static int fec_probe(struct device_d *dev) goto release_res; } - phy_reset = of_get_named_gpio(dev->device_node, "phy-reset-gpios", 0); + phy_reset = of_get_named_gpio(dev->of_node, "phy-reset-gpios", 0); if (gpio_is_valid(phy_reset)) { - of_property_read_u32(dev->device_node, "phy-reset-duration", &msec); - of_property_read_u32(dev->device_node, "phy-reset-post-delay", + of_property_read_u32(dev->of_node, "phy-reset-duration", + &msec); + of_property_read_u32(dev->of_node, "phy-reset-post-delay", &phy_post_delay); /* valid reset duration should be less than 1s */ if (phy_post_delay > 1000) @@ -824,6 +857,8 @@ static int fec_probe(struct device_d *dev) if (ret) goto free_gpio; + fec_set_promisc(edev, false); + /* * reserve memory for both buffer descriptor chains at once * Datasheet forces the startaddress of each chain is 16 byte aligned @@ -835,14 +870,11 @@ static int fec_probe(struct device_d *dev) base += FEC_RBD_NUM * sizeof(struct buffer_descriptor); fec->tbd_base = base; - writel(virt_to_phys(fec->tbd_base), fec->regs + FEC_ETDSR); - writel(virt_to_phys(fec->rbd_base), fec->regs + FEC_ERDSR); - ret = fec_alloc_receive_packets(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE); if (ret < 0) goto free_xbd; - if (dev->device_node) { + if (dev->of_node) { ret = fec_probe_dt(dev, fec); fec->phy_addr = -1; } else if (pdata) { @@ -857,26 +889,24 @@ static int fec_probe(struct device_d *dev) if (ret) goto free_receive_packets; - fec_init(edev); - fec->miibus.read = fec_miibus_read; fec->miibus.write = fec_miibus_write; fec->miibus.priv = fec; fec->miibus.parent = dev; - ret = mdiobus_register(&fec->miibus); + ret = eth_register(edev); if (ret) goto free_receive_packets; - ret = eth_register(edev); + ret = mdiobus_register(&fec->miibus); if (ret) - goto unregister_mdio; + goto unregister_eth; return 0; -unregister_mdio: - mdiobus_unregister(&fec->miibus); +unregister_eth: + eth_unregister(edev); free_receive_packets: fec_free_receive_packets(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE); free_xbd: @@ -898,7 +928,7 @@ err_free: return ret; } -static void fec_remove(struct device_d *dev) +static void fec_remove(struct device *dev) { struct fec_priv *fec = dev->priv; @@ -922,12 +952,16 @@ static __maybe_unused struct of_device_id imx_fec_dt_ids[] = { .compatible = "fsl,imx6sx-fec", .data = (void *)FEC_TYPE_IMX6, }, { + .compatible = "fsl,imx8mp-fec", + .data = (void *)FEC_TYPE_IMX6, + }, { .compatible = "fsl,mvf600-fec", .data = (void *)FEC_TYPE_IMX6, }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx_fec_dt_ids); static struct platform_device_id imx_fec_ids[] = { { @@ -947,7 +981,7 @@ static struct platform_device_id imx_fec_ids[] = { /** * Driver description for registering */ -static struct driver_d fec_driver = { +static struct driver fec_driver = { .name = "fec_imx", .probe = fec_probe, .remove = fec_remove, |