summaryrefslogtreecommitdiffstats
path: root/drivers/net/fec_imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fec_imx.c')
-rw-r--r--drivers/net/fec_imx.c92
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,