struct dma_descriptor *b = &(r->desc_b);
/* allocate a new skb for next time receive */
- new_skb = dev_alloc_skb(PKT_BUF_SZ + 2);
+ new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
if (!new_skb) {
printk(KERN_NOTICE DRV_NAME
": init: low on mem - packet dropped\n");
goto init_error;
}
- skb_reserve(new_skb, 2);
+ skb_reserve(new_skb, NET_IP_ALIGN);
r->skb = new_skb;
/*
* MII operations
*/
/* Wait until the previous MDC/MDIO transaction has completed */
-static void mdio_poll(void)
+static void bfin_mdio_poll(void)
{
int timeout_cnt = MAX_TIMEOUT_CNT;
}
/* Read an off-chip register in a PHY through the MDC/MDIO port */
-static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
{
- mdio_poll();
+ bfin_mdio_poll();
/* read mode */
bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
SET_REGAD((u16) regnum) |
STABUSY);
- mdio_poll();
+ bfin_mdio_poll();
return (int) bfin_read_EMAC_STADAT();
}
/* Write an off-chip register in a PHY through the MDC/MDIO port */
-static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
- u16 value)
+static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+ u16 value)
{
- mdio_poll();
+ bfin_mdio_poll();
bfin_write_EMAC_STADAT((u32) value);
STAOP |
STABUSY);
- mdio_poll();
+ bfin_mdio_poll();
return 0;
}
-static int mdiobus_reset(struct mii_bus *bus)
+static int bfin_mdiobus_reset(struct mii_bus *bus)
{
return 0;
}
/* search for connect PHY device */
for (i = 0; i < PHY_MAX_ADDR; i++) {
- struct phy_device *const tmp_phydev = lp->mii_bus.phy_map[i];
+ struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
if (!tmp_phydev)
continue; /* no PHY here... */
}
#if defined(CONFIG_BFIN_MAC_RMII)
- phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0,
- PHY_INTERFACE_MODE_RMII);
+ phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
+ 0, PHY_INTERFACE_MODE_RMII);
#else
- phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
+ 0, PHY_INTERFACE_MODE_MII);
#endif
if (IS_ERR(phydev)) {
printk(KERN_INFO "%s: attached PHY driver [%s] "
"(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)"
"@sclk=%dMHz)\n",
- DRV_NAME, phydev->drv->name, phydev->dev.bus_id, phydev->irq,
+ DRV_NAME, phydev->drv->name, dev_name(&phydev->dev), phydev->irq,
MDC_CLK, mdc_div, sclk/1000000);
return 0;
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
strcpy(info->fw_version, "N/A");
- strcpy(info->bus_info, dev->dev.bus_id);
+ strcpy(info->bus_info, dev_name(&dev->dev));
}
-static struct ethtool_ops bfin_mac_ethtool_ops = {
+static const struct ethtool_ops bfin_mac_ethtool_ops = {
.get_settings = bfin_mac_ethtool_getsettings,
.set_settings = bfin_mac_ethtool_setsettings,
.get_link = ethtool_op_get_link,
{
int timeout_cnt = MAX_TIMEOUT_CNT;
- if (tx_list_head->status.status_word != 0
- && current_tx_ptr != tx_list_head) {
+ if (tx_list_head->status.status_word != 0 &&
+ current_tx_ptr != tx_list_head) {
goto adjust_head; /* released something, just return; */
}
*/
if (current_tx_ptr->next->next == tx_list_head) {
while (tx_list_head->status.status_word == 0) {
- mdelay(1);
- if (tx_list_head->status.status_word != 0
- || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) {
+ udelay(10);
+ if (tx_list_head->status.status_word != 0 ||
+ !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) {
goto adjust_head;
}
if (timeout_cnt-- < 0) {
": no sk_buff in a transmitted frame!\n");
}
tx_list_head = tx_list_head->next;
- } while (tx_list_head->status.status_word != 0
- && current_tx_ptr != tx_list_head);
+ } while (tx_list_head->status.status_word != 0 &&
+ current_tx_ptr != tx_list_head);
return;
}
struct net_device *dev)
{
u16 *data;
-
+ u32 data_align = (unsigned long)(skb->data) & 0x3;
current_tx_ptr->skb = skb;
- if (ANOMALY_05000285) {
- /*
- * TXDWA feature is not avaible to older revision < 0.3 silicon
- * of BF537
- *
- * Only if data buffer is ODD WORD alignment, we do not
- * need to memcpy
- */
- u32 data_align = (u32)(skb->data) & 0x3;
- if (data_align == 0x2) {
- /* move skb->data to current_tx_ptr payload */
- data = (u16 *)(skb->data) - 1;
- *data = (u16)(skb->len);
- current_tx_ptr->desc_a.start_addr = (u32)data;
- /* this is important! */
- blackfin_dcache_flush_range((u32)data,
- (u32)((u8 *)data + skb->len + 4));
- } else {
- *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
- memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
- skb->len);
- current_tx_ptr->desc_a.start_addr =
- (u32)current_tx_ptr->packet;
- if (current_tx_ptr->status.status_word != 0)
- current_tx_ptr->status.status_word = 0;
- blackfin_dcache_flush_range(
- (u32)current_tx_ptr->packet,
- (u32)(current_tx_ptr->packet + skb->len + 2));
- }
+ if (data_align == 0x2) {
+ /* move skb->data to current_tx_ptr payload */
+ data = (u16 *)(skb->data) - 1;
+ *data = (u16)(skb->len);
+ current_tx_ptr->desc_a.start_addr = (u32)data;
+ /* this is important! */
+ blackfin_dcache_flush_range((u32)data,
+ (u32)((u8 *)data + skb->len + 4));
} else {
- /*
- * TXDWA feature is avaible to revision < 0.3 silicon of
- * BF537 and always avaible to BF52x
- */
- u32 data_align = (u32)(skb->data) & 0x3;
- if (data_align == 0x0) {
- u16 sysctl = bfin_read_EMAC_SYSCTL();
- sysctl |= TXDWA;
- bfin_write_EMAC_SYSCTL(sysctl);
-
- /* move skb->data to current_tx_ptr payload */
- data = (u16 *)(skb->data) - 2;
- *data = (u16)(skb->len);
- current_tx_ptr->desc_a.start_addr = (u32)data;
- /* this is important! */
- blackfin_dcache_flush_range(
- (u32)data,
- (u32)((u8 *)data + skb->len + 4));
- } else if (data_align == 0x2) {
- u16 sysctl = bfin_read_EMAC_SYSCTL();
- sysctl &= ~TXDWA;
- bfin_write_EMAC_SYSCTL(sysctl);
-
- /* move skb->data to current_tx_ptr payload */
- data = (u16 *)(skb->data) - 1;
- *data = (u16)(skb->len);
- current_tx_ptr->desc_a.start_addr = (u32)data;
- /* this is important! */
- blackfin_dcache_flush_range(
- (u32)data,
- (u32)((u8 *)data + skb->len + 4));
- } else {
- u16 sysctl = bfin_read_EMAC_SYSCTL();
- sysctl &= ~TXDWA;
- bfin_write_EMAC_SYSCTL(sysctl);
-
- *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
- memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
- skb->len);
- current_tx_ptr->desc_a.start_addr =
- (u32)current_tx_ptr->packet;
- if (current_tx_ptr->status.status_word != 0)
- current_tx_ptr->status.status_word = 0;
- blackfin_dcache_flush_range(
- (u32)current_tx_ptr->packet,
- (u32)(current_tx_ptr->packet + skb->len + 2));
- }
+ *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
+ memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
+ skb->len);
+ current_tx_ptr->desc_a.start_addr =
+ (u32)current_tx_ptr->packet;
+ if (current_tx_ptr->status.status_word != 0)
+ current_tx_ptr->status.status_word = 0;
+ blackfin_dcache_flush_range(
+ (u32)current_tx_ptr->packet,
+ (u32)(current_tx_ptr->packet + skb->len + 2));
}
+ /* make sure the internal data buffers in the core are drained
+ * so that the DMA descriptors are completely written when the
+ * DMA engine goes to fetch them below
+ */
+ SSYNC();
+
/* enable this packet's dma */
current_tx_ptr->desc_a.config |= DMAEN;
/* tx dma is running, just return */
- if (bfin_read_DMA2_IRQ_STATUS() & 0x08)
+ if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)
goto out;
/* tx dma is not running */
dev->trans_start = jiffies;
dev->stats.tx_packets++;
dev->stats.tx_bytes += (skb->len);
- return 0;
+ return NETDEV_TX_OK;
}
static void bfin_mac_rx(struct net_device *dev)
/* allocate a new skb for next time receive */
skb = current_rx_ptr->skb;
- new_skb = dev_alloc_skb(PKT_BUF_SZ + 2);
+ new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
if (!new_skb) {
printk(KERN_NOTICE DRV_NAME
": rx: low on mem - packet dropped\n");
goto out;
}
/* reserve 2 bytes for RXDWA padding */
- skb_reserve(new_skb, 2);
+ skb_reserve(new_skb, NET_IP_ALIGN);
current_rx_ptr->skb = new_skb;
current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2;
blackfin_dcache_invalidate_range((unsigned long)skb->head,
(unsigned long)skb->tail);
- dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, dev);
#if defined(BFIN_MAC_CSUM_OFFLOAD)
skb->csum = current_rx_ptr->status.ip_payload_csum;
{
u32 opmode;
- pr_debug("%s: %s\n", DRV_NAME, __FUNCTION__);
+ pr_debug("%s: %s\n", DRV_NAME, __func__);
/* Set RX DMA */
bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a));
bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);
/* Wait MII done */
- mdio_poll();
+ bfin_mdio_poll();
/* We enable only RX here */
/* ASTP : Enable Automatic Pad Stripping
/* Our watchdog timed out. Called by the networking layer */
static void bfin_mac_timeout(struct net_device *dev)
{
- pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+ pr_debug("%s: %s\n", dev->name, __func__);
bfin_mac_disable();
{
struct bfin_mac_local *lp = netdev_priv(dev);
int retval;
- pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+ pr_debug("%s: %s\n", dev->name, __func__);
/*
* Check that the address is valid. If its not, refuse
}
/*
- *
* this makes the board clean up everything that it can
* and not talk to the outside world. Caused by
* an 'ifconfig ethX down'
static int bfin_mac_close(struct net_device *dev)
{
struct bfin_mac_local *lp = netdev_priv(dev);
- pr_debug("%s: %s\n", dev->name, __FUNCTION__);
+ pr_debug("%s: %s\n", dev->name, __func__);
netif_stop_queue(dev);
netif_carrier_off(dev);
return 0;
}
+static const struct net_device_ops bfin_mac_netdev_ops = {
+ .ndo_open = bfin_mac_open,
+ .ndo_stop = bfin_mac_close,
+ .ndo_start_xmit = bfin_mac_hard_start_xmit,
+ .ndo_set_mac_address = bfin_mac_set_mac_address,
+ .ndo_tx_timeout = bfin_mac_timeout,
+ .ndo_set_multicast_list = bfin_mac_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = bfin_mac_poll,
+#endif
+};
+
static int __devinit bfin_mac_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct bfin_mac_local *lp;
- int rc, i;
+ struct platform_device *pd;
+ int rc;
ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
if (!ndev) {
goto out_err_probe_mac;
}
- /* set the GPIO pins to Ethernet mode */
- rc = peripheral_request_list(pin_req, DRV_NAME);
- if (rc) {
- dev_err(&pdev->dev, "Requesting peripherals failed!\n");
- rc = -EFAULT;
- goto out_err_setup_pin_mux;
- }
/*
* Is it valid? (Did bootloader initialize it?)
setup_mac_addr(ndev->dev_addr);
- /* MDIO bus initial */
- lp->mii_bus.priv = ndev;
- lp->mii_bus.read = mdiobus_read;
- lp->mii_bus.write = mdiobus_write;
- lp->mii_bus.reset = mdiobus_reset;
- lp->mii_bus.name = "bfin_mac_mdio";
- snprintf(lp->mii_bus.id, MII_BUS_ID_SIZE, "0");
- lp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
- for (i = 0; i < PHY_MAX_ADDR; ++i)
- lp->mii_bus.irq[i] = PHY_POLL;
-
- rc = mdiobus_register(&lp->mii_bus);
- if (rc) {
- dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
- goto out_err_mdiobus_register;
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n");
+ rc = -ENODEV;
+ goto out_err_probe_mac;
}
+ pd = pdev->dev.platform_data;
+ lp->mii_bus = platform_get_drvdata(pd);
+ lp->mii_bus->priv = ndev;
rc = mii_probe(ndev);
if (rc) {
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(ndev);
- ndev->open = bfin_mac_open;
- ndev->stop = bfin_mac_close;
- ndev->hard_start_xmit = bfin_mac_hard_start_xmit;
- ndev->set_mac_address = bfin_mac_set_mac_address;
- ndev->tx_timeout = bfin_mac_timeout;
- ndev->set_multicast_list = bfin_mac_set_multicast_list;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- ndev->poll_controller = bfin_mac_poll;
-#endif
+ ndev->netdev_ops = &bfin_mac_netdev_ops;
ndev->ethtool_ops = &bfin_mac_ethtool_ops;
spin_lock_init(&lp->lock);
/* now, enable interrupts */
/* register irq handler */
rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
- IRQF_DISABLED | IRQF_SHARED, "EMAC_RX", ndev);
+ IRQF_DISABLED, "EMAC_RX", ndev);
if (rc) {
dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
rc = -EBUSY;
free_irq(IRQ_MAC_RX, ndev);
out_err_request_irq:
out_err_mii_probe:
- mdiobus_unregister(&lp->mii_bus);
-out_err_mdiobus_register:
+ mdiobus_unregister(lp->mii_bus);
+ mdiobus_free(lp->mii_bus);
peripheral_free_list(pin_req);
-out_err_setup_pin_mux:
out_err_probe_mac:
platform_set_drvdata(pdev, NULL);
free_netdev(ndev);
platform_set_drvdata(pdev, NULL);
- mdiobus_unregister(&lp->mii_bus);
+ lp->mii_bus->priv = NULL;
unregister_netdev(ndev);
#define bfin_mac_resume NULL
#endif /* CONFIG_PM */
+static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
+{
+ struct mii_bus *miibus;
+ int rc, i;
+
+ /*
+ * We are setting up a network card,
+ * so set the GPIO pins to Ethernet mode
+ */
+ rc = peripheral_request_list(pin_req, DRV_NAME);
+ if (rc) {
+ dev_err(&pdev->dev, "Requesting peripherals failed!\n");
+ return rc;
+ }
+
+ rc = -ENOMEM;
+ miibus = mdiobus_alloc();
+ if (miibus == NULL)
+ goto out_err_alloc;
+ miibus->read = bfin_mdiobus_read;
+ miibus->write = bfin_mdiobus_write;
+ miibus->reset = bfin_mdiobus_reset;
+
+ miibus->parent = &pdev->dev;
+ miibus->name = "bfin_mii_bus";
+ snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
+ miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ if (miibus->irq == NULL)
+ goto out_err_alloc;
+ for (i = 0; i < PHY_MAX_ADDR; ++i)
+ miibus->irq[i] = PHY_POLL;
+
+ rc = mdiobus_register(miibus);
+ if (rc) {
+ dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
+ goto out_err_mdiobus_register;
+ }
+
+ platform_set_drvdata(pdev, miibus);
+ return 0;
+
+out_err_mdiobus_register:
+ mdiobus_free(miibus);
+out_err_alloc:
+ peripheral_free_list(pin_req);
+
+ return rc;
+}
+
+static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
+{
+ struct mii_bus *miibus = platform_get_drvdata(pdev);
+ platform_set_drvdata(pdev, NULL);
+ mdiobus_unregister(miibus);
+ mdiobus_free(miibus);
+ peripheral_free_list(pin_req);
+ return 0;
+}
+
+static struct platform_driver bfin_mii_bus_driver = {
+ .probe = bfin_mii_bus_probe,
+ .remove = __devexit_p(bfin_mii_bus_remove),
+ .driver = {
+ .name = "bfin_mii_bus",
+ .owner = THIS_MODULE,
+ },
+};
+
static struct platform_driver bfin_mac_driver = {
.probe = bfin_mac_probe,
.remove = __devexit_p(bfin_mac_remove),
static int __init bfin_mac_init(void)
{
- return platform_driver_register(&bfin_mac_driver);
+ int ret;
+ ret = platform_driver_register(&bfin_mii_bus_driver);
+ if (!ret)
+ return platform_driver_register(&bfin_mac_driver);
+ return -ENODEV;
}
module_init(bfin_mac_init);
static void __exit bfin_mac_cleanup(void)
{
platform_driver_unregister(&bfin_mac_driver);
+ platform_driver_unregister(&bfin_mii_bus_driver);
}
module_exit(bfin_mac_cleanup);