summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig3
-rw-r--r--drivers/net/designware_eqos.c18
-rw-r--r--drivers/net/designware_eqos.h4
-rw-r--r--drivers/net/designware_stm32.c32
-rw-r--r--drivers/net/designware_tegra186.c45
-rw-r--r--drivers/net/fsl-fman.c128
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(&reg->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);