diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 3 | ||||
-rw-r--r-- | drivers/net/designware_eqos.c | 18 | ||||
-rw-r--r-- | drivers/net/designware_eqos.h | 4 | ||||
-rw-r--r-- | drivers/net/designware_stm32.c | 32 | ||||
-rw-r--r-- | drivers/net/designware_tegra186.c | 45 | ||||
-rw-r--r-- | drivers/net/fsl-fman.c | 128 |
6 files changed, 110 insertions, 120 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 62e522a302..5823320b03 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -90,8 +90,9 @@ endif config DRIVER_NET_DESIGNWARE_EQOS bool "Designware Designware Ethernet QoS support" depends on HAS_DMA + depends on COMMON_CLK + depends on OFTREE select PHYLIB - select OFTREE help This option enables support for the Synopsys Designware Ethernet Quality-of-Service (GMAC4). diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c index a49239e057..da67adf9a0 100644 --- a/drivers/net/designware_eqos.c +++ b/drivers/net/designware_eqos.c @@ -204,7 +204,7 @@ static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg) ret = eqos_mdio_wait_idle(eqos); if (ret) { - eqos_err(eqos, "MDIO not idle at entry\n"); + dev_err(&bus->dev, "MDIO not idle at entry\n"); return ret; } @@ -222,7 +222,7 @@ static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg) ret = eqos_mdio_wait_idle(eqos); if (ret) { - eqos_err(eqos, "MDIO read didn't complete\n"); + dev_err(&bus->dev, "MDIO read didn't complete\n"); return ret; } @@ -237,7 +237,7 @@ static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val) ret = eqos_mdio_wait_idle(eqos); if (ret) { - eqos_err(eqos, "MDIO not idle at entry\n"); + dev_err(&bus->dev, "MDIO not idle at entry\n"); return ret; } @@ -256,7 +256,7 @@ static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val) ret = eqos_mdio_wait_idle(eqos); if (ret) { - eqos_err(eqos, "MDIO read didn't complete\n"); + dev_err(&bus->dev, "MDIO read didn't complete\n"); return ret; } @@ -365,7 +365,7 @@ static int phy_resume(struct phy_device *phydev) return 0; } -int eqos_start(struct eth_device *edev) +static int eqos_start(struct eth_device *edev) { struct eqos *eqos = edev->priv; u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; @@ -611,7 +611,7 @@ int eqos_start(struct eth_device *edev) return 0; } -void eqos_stop(struct eth_device *edev) +static void eqos_stop(struct eth_device *edev) { struct eqos *eqos = edev->priv; int i; @@ -841,10 +841,10 @@ int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv) dev->priv = edev->priv = eqos; edev->parent = dev; - edev->open = ops->start; + edev->open = eqos_start; edev->send = eqos_send; edev->recv = eqos_recv; - edev->halt = ops->stop; + edev->halt = eqos_stop; edev->get_ethaddr = ops->get_ethaddr; edev->set_ethaddr = ops->set_ethaddr; @@ -869,6 +869,8 @@ void eqos_remove(struct device_d *dev) { struct eqos *eqos = dev->priv; + eth_unregister(&eqos->netdev); + mdiobus_unregister(&eqos->miibus); dma_free(phys_to_virt(eqos->rx_descs[0].des0)); diff --git a/drivers/net/designware_eqos.h b/drivers/net/designware_eqos.h index 969a524c0a..f794195db4 100644 --- a/drivers/net/designware_eqos.h +++ b/drivers/net/designware_eqos.h @@ -11,8 +11,6 @@ struct eth_device; struct eqos_ops { int (*init)(struct device_d *dev, struct eqos *priv); - int (*start)(struct eth_device *edev); - void (*stop)(struct eth_device *edev); int (*get_ethaddr)(struct eth_device *dev, unsigned char *mac); int (*set_ethaddr)(struct eth_device *edev, const unsigned char *mac); void (*adjust_link)(struct eth_device *edev); @@ -73,8 +71,6 @@ int eqos_reset(struct eqos *priv); int eqos_get_ethaddr(struct eth_device *edev, unsigned char *mac); int eqos_set_ethaddr(struct eth_device *edev, const unsigned char *mac); -int eqos_start(struct eth_device *edev); -void eqos_stop(struct eth_device *edev); void eqos_adjust_link(struct eth_device *edev); #define eqos_dbg(eqos, ...) dev_dbg(&eqos->netdev.dev, __VA_ARGS__) diff --git a/drivers/net/designware_stm32.c b/drivers/net/designware_stm32.c index 5b087ad5a3..4c682a5dac 100644 --- a/drivers/net/designware_stm32.c +++ b/drivers/net/designware_stm32.c @@ -164,16 +164,6 @@ static int eqos_init_stm32(struct device_d *dev, struct eqos *eqos) dev_dbg(dev, "No phy clock provided. Continuing without.\n"); } - return 0; - -} - -static int eqos_start_stm32(struct eth_device *edev) -{ - struct eqos *eqos = edev->priv; - struct eqos_stm32 *priv = to_stm32(eqos); - int ret; - ret = clk_bulk_enable(priv->num_clks, priv->clks); if (ret < 0) { eqos_err(eqos, "clk_bulk_enable() failed: %s\n", @@ -181,34 +171,13 @@ static int eqos_start_stm32(struct eth_device *edev) return ret; } - udelay(10); - - ret = eqos_start(edev); - if (ret) - goto err_stop_clks; - return 0; - -err_stop_clks: - clk_bulk_disable(priv->num_clks, priv->clks); - - return ret; -} - -static void eqos_stop_stm32(struct eth_device *edev) -{ - struct eqos_stm32 *priv = to_stm32(edev->priv); - - clk_bulk_disable(priv->num_clks, priv->clks); } -// todo split! static struct eqos_ops stm32_ops = { .init = eqos_init_stm32, .get_ethaddr = eqos_get_ethaddr, .set_ethaddr = eqos_set_ethaddr, - .start = eqos_start_stm32, - .stop = eqos_stop_stm32, .adjust_link = eqos_adjust_link, .get_csr_clk_rate = eqos_get_csr_clk_rate_stm32, @@ -228,6 +197,7 @@ static void eqos_remove_stm32(struct device_d *dev) eqos_remove(dev); + clk_bulk_disable(priv->num_clks, priv->clks); clk_bulk_put(priv->num_clks, priv->clks); } diff --git a/drivers/net/designware_tegra186.c b/drivers/net/designware_tegra186.c index 58484d4095..20521db1c7 100644 --- a/drivers/net/designware_tegra186.c +++ b/drivers/net/designware_tegra186.c @@ -230,29 +230,16 @@ static int eqos_init_tegra186(struct device_d *dev, struct eqos *eqos) priv->clks = xmemdup(tegra186_clks, sizeof(tegra186_clks)); priv->num_clks = ARRAY_SIZE(tegra186_clks); - return 0; - -release_res: - reset_control_put(priv->rst); - return ret; -} - -static int eqos_start_tegra186(struct eth_device *edev) -{ - struct eqos *eqos = edev->priv; - struct eqos_tegra186 *priv = to_tegra186(eqos); - int ret; - ret = clk_bulk_enable(priv->num_clks, priv->clks); if (ret < 0) { eqos_err(eqos, "clk_bulk_enable() failed: %s\n", strerror(-ret)); - return ret; + goto release_res; } ret = eqos_clks_set_rate_tegra186(priv); if (ret < 0) { eqos_err(eqos, "clks_set_rate() failed: %s\n", strerror(-ret)); - goto err; + goto err_stop_clks; } eqos_reset_tegra186(priv, false); @@ -261,30 +248,14 @@ static int eqos_start_tegra186(struct eth_device *edev) goto err_stop_clks; } - udelay(10); - - ret = eqos_start(edev); - if (ret) - goto err_stop_resets; - return 0; -err_stop_resets: - eqos_reset_tegra186(priv, true); err_stop_clks: clk_bulk_disable(priv->num_clks, priv->clks); -err: - return ret; -} - - -static void eqos_stop_tegra186(struct eth_device *edev) -{ - struct eqos_tegra186 *priv = to_tegra186(edev->priv); - - eqos_reset_tegra186(priv, true); +release_res: + reset_control_put(priv->rst); - clk_bulk_disable(priv->num_clks, priv->clks); + return ret; } static void eqos_adjust_link_tegra186(struct eth_device *edev) @@ -306,8 +277,6 @@ static const struct eqos_ops tegra186_ops = { .init = eqos_init_tegra186, .get_ethaddr = eqos_get_ethaddr, .set_ethaddr = eqos_set_ethaddr_tegra186, - .start = eqos_start_tegra186, - .stop = eqos_stop_tegra186, .adjust_link = eqos_adjust_link_tegra186, .get_csr_clk_rate = eqos_get_csr_clk_rate_tegra186, @@ -327,6 +296,10 @@ static void eqos_remove_tegra186(struct device_d *dev) eqos_remove(dev); + eqos_reset_tegra186(priv, true); + + clk_bulk_disable(priv->num_clks, priv->clks); + clk_bulk_put(priv->num_clks, priv->clks); gpio_free(priv->phy_reset_gpio); diff --git a/drivers/net/fsl-fman.c b/drivers/net/fsl-fman.c index 4e6bb2ecfd..1aae58e494 100644 --- a/drivers/net/fsl-fman.c +++ b/drivers/net/fsl-fman.c @@ -104,11 +104,11 @@ struct fm_eth { struct device_d *dev; struct fm_port_global_pram *rx_pram; /* Rx parameter table */ struct fm_port_global_pram *tx_pram; /* Tx parameter table */ - void *rx_bd_ring; /* Rx BD ring base */ - void *cur_rxbd; /* current Rx BD */ + struct fm_port_bd *rx_bd_ring; /* Rx BD ring base */ + int cur_rxbd_idx; /* current Rx BD index */ void *rx_buf; /* Rx buffer base */ - void *tx_bd_ring; /* Tx BD ring base */ - void *cur_txbd; /* current Tx BD */ + struct fm_port_bd *tx_bd_ring; /* Tx BD ring base */ + int cur_txbd_idx; /* current Tx BD index */ struct memac *regs; }; @@ -628,12 +628,13 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) /* save them to fm_eth */ fm_eth->rx_bd_ring = rx_bd_ring_base; - fm_eth->cur_rxbd = rx_bd_ring_base; + fm_eth->cur_rxbd_idx = 0; fm_eth->rx_buf = rx_buf_pool; /* init Rx BDs ring */ - rxbd = rx_bd_ring_base; for (i = 0; i < RX_BD_RING_SIZE; i++) { + rxbd = &fm_eth->rx_bd_ring[i]; + muram_writew(&rxbd->status, RxBD_EMPTY); muram_writew(&rxbd->len, 0); buf_hi = upper_32_bits(virt_to_phys(rx_buf_pool + @@ -644,7 +645,6 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) MAX_RXBUF_LEN, DMA_FROM_DEVICE); muram_writew(&rxbd->buf_ptr_hi, (u16)buf_hi); out_be32(&rxbd->buf_ptr_lo, buf_lo); - rxbd++; } /* set the Rx queue descriptor */ @@ -702,16 +702,16 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) * TX_BD_RING_SIZE); /* save it to fm_eth */ fm_eth->tx_bd_ring = tx_bd_ring_base; - fm_eth->cur_txbd = tx_bd_ring_base; + fm_eth->cur_txbd_idx = 0; /* init Tx BDs ring */ - txbd = tx_bd_ring_base; for (i = 0; i < TX_BD_RING_SIZE; i++) { + txbd = &fm_eth->tx_bd_ring[i]; + muram_writew(&txbd->status, TxBD_LAST); muram_writew(&txbd->len, 0); muram_writew(&txbd->buf_ptr_hi, 0); out_be32(&txbd->buf_ptr_lo, 0); - txbd++; } /* set the Tx queue decriptor */ @@ -834,13 +834,12 @@ static int fm_eth_send(struct eth_device *edev, void *buf, int len) { struct fm_eth *fm_eth = to_fm_eth(edev); struct fm_port_global_pram *pram; - struct fm_port_bd *txbd, *txbd_base; - u16 offset_in; - int i; + struct fm_port_bd *txbd; + int i, ret; dma_addr_t dma; pram = fm_eth->tx_pram; - txbd = fm_eth->cur_txbd; + txbd = &fm_eth->tx_bd_ring[fm_eth->cur_txbd_idx]; /* find one empty TxBD */ for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) { @@ -862,41 +861,35 @@ static int fm_eth_send(struct eth_device *edev, void *buf, int len) muram_writew(&txbd->len, len); muram_writew(&txbd->status, TxBD_READY | TxBD_LAST); + /* advance the TxBD */ + fm_eth->cur_txbd_idx = (fm_eth->cur_txbd_idx + 1) % TX_BD_RING_SIZE; + /* update TxQD, let RISC to send the packet */ - offset_in = muram_readw(&pram->txqd.offset_in); - offset_in += sizeof(struct fm_port_bd); - if (offset_in >= muram_readw(&pram->txqd.bd_ring_size)) - offset_in = 0; - muram_writew(&pram->txqd.offset_in, offset_in); + muram_writew(&pram->txqd.offset_in, + fm_eth->cur_txbd_idx * sizeof(struct fm_port_bd)); /* wait for buffer to be transmitted */ + ret = 0; for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) { udelay(10); if (i > 0x10000) { dev_err(&edev->dev, "Tx error, txbd->status = 0x%x\n", muram_readw(&txbd->status)); - return -EIO; + ret = -EIO; + break; } } dma_unmap_single(fm_eth->dev, dma, len, DMA_TO_DEVICE); - /* advance the TxBD */ - txbd++; - txbd_base = fm_eth->tx_bd_ring; - if (txbd >= (txbd_base + TX_BD_RING_SIZE)) - txbd = txbd_base; - /* update current txbd */ - fm_eth->cur_txbd = (void *)txbd; - - return 0; + return ret; } static int fm_eth_recv(struct eth_device *edev) { struct fm_eth *fm_eth = to_fm_eth(edev); struct fm_port_global_pram *pram; - struct fm_port_bd *rxbd, *rxbd_base; + struct fm_port_bd *rxbd; u16 status, len; u32 buf_lo, buf_hi; u8 *data; @@ -904,10 +897,14 @@ static int fm_eth_recv(struct eth_device *edev) int ret = 1; pram = fm_eth->rx_pram; - rxbd = fm_eth->cur_rxbd; - status = muram_readw(&rxbd->status); - while (!(status & RxBD_EMPTY)) { + while (1) { + rxbd = &fm_eth->rx_bd_ring[fm_eth->cur_rxbd_idx]; + + status = muram_readw(&rxbd->status); + if (status & RxBD_EMPTY) + break; + if (!(status & RxBD_ERROR)) { buf_hi = muram_readw(&rxbd->buf_ptr_hi); buf_lo = in_be32(&rxbd->buf_ptr_lo); @@ -933,12 +930,7 @@ static int fm_eth_recv(struct eth_device *edev) muram_writew(&rxbd->len, 0); /* advance RxBD */ - rxbd++; - rxbd_base = fm_eth->rx_bd_ring; - if (rxbd >= (rxbd_base + RX_BD_RING_SIZE)) - rxbd = rxbd_base; - /* read next status */ - status = muram_readw(&rxbd->status); + fm_eth->cur_rxbd_idx = (fm_eth->cur_rxbd_idx + 1) % RX_BD_RING_SIZE; /* update RxQD */ offset_out = muram_readw(&pram->rxqd.offset_out); @@ -947,7 +939,6 @@ static int fm_eth_recv(struct eth_device *edev) offset_out = 0; muram_writew(&pram->rxqd.offset_out, offset_out); } - fm_eth->cur_rxbd = rxbd; return ret; } @@ -1175,6 +1166,8 @@ static int fsl_fman_memac_probe(struct device_d *dev) /* alloc the FMan ethernet private struct */ fm_eth = xzalloc(sizeof(*fm_eth)); + dev->priv = fm_eth; + fm_eth->dev = dev; ret = fsl_fman_memac_port_bind(fm_eth, FMAN_PORT_TYPE_TX); @@ -1216,6 +1209,13 @@ static int fsl_fman_memac_probe(struct device_d *dev) return 0; } +static void fsl_fman_memac_remove(struct device_d *dev) +{ + struct fm_eth *fm_eth = dev->priv; + + fm_eth_halt(&fm_eth->edev); +} + static int fsl_fman_muram_probe(struct device_d *dev) { struct resource *iores; @@ -1274,6 +1274,7 @@ static struct of_device_id fsl_fman_memac_dt_ids[] = { static struct driver_d fman_memac_driver = { .name = "fsl-fman-memac", .probe = fsl_fman_memac_probe, + .remove = fsl_fman_memac_remove, .of_compatible = DRV_OF_COMPAT(fsl_fman_memac_dt_ids), }; @@ -1303,6 +1304,7 @@ static int fsl_fman_probe(struct device_d *dev) return PTR_ERR(iores); reg = IOMEM(iores->start); + dev->priv = reg; ret = of_platform_populate(dev->device_node, NULL, dev); if (ret) @@ -1320,6 +1322,13 @@ static int fsl_fman_probe(struct device_d *dev) return 0; } +static void fsl_fman_remove(struct device_d *dev) +{ + struct ccsr_fman *reg = dev->priv; + + setbits_be32(®->fm_fpm.fmrstc, FMFP_RSTC_RFM); +} + static struct of_device_id fsl_fman_dt_ids[] = { { .compatible = "fsl,fman", @@ -1330,6 +1339,45 @@ static struct of_device_id fsl_fman_dt_ids[] = { static struct driver_d fman_driver = { .name = "fsl-fman", .probe = fsl_fman_probe, + .remove = fsl_fman_remove, .of_compatible = DRV_OF_COMPAT(fsl_fman_dt_ids), }; device_platform_driver(fman_driver); + +static int fman_of_fixup(struct device_node *root, void *context) +{ + struct device_node *fman, *fman_bb; + struct device_node *child, *child_bb; + + fman_bb = of_find_compatible_node(NULL, NULL, "fsl,fman"); + fman = of_find_compatible_node(root, NULL, "fsl,fman"); + + /* + * The dts files in the Linux tree have all network interfaces + * enabled. Disable the ones that are disabled under barebox + * as well. + */ + for_each_child_of_node(fman, child) { + if (!of_device_is_compatible(child, "fsl,fman-memac")) + continue; + + child_bb = of_get_child_by_name(fman_bb, child->name); + if (!child_bb) + continue; + + if (of_device_is_available(child_bb)) + of_device_enable(child); + else + of_device_disable(child); + } + + return 0; +} + +static int fman_register_of_fixup(void) +{ + of_register_fixup(fman_of_fixup, NULL); + + return 0; +} +late_initcall(fman_register_of_fixup); |