/* * Theory of operation * * The Au1000 MACs use a simple rx and tx descriptor ring scheme. * There are four receive and four transmit descriptors. These * descriptors are not in memory; rather, they are just a set of * hardware registers. * * Since the Au1000 has a coherent data cache, the receive and * transmit buffers are allocated from the KSEG0 segment. The * hardware registers, however, are still mapped at KSEG1 to * make sure there's no out-of-order writes, and that all writes * complete immediately.
*/
/* * board-specific configurations * * PHY detection algorithm * * If phy_static_config is undefined, the PHY setup is * autodetected: * * mii_probe() first searches the current MAC's MII bus for a PHY, * selecting the first (or last, if phy_search_highest_addr is * defined) PHY address not already claimed by another netdev. * * If nothing was found that way when searching for the 2nd ethernet * controller's PHY and phy1_search_mac0 is defined, then * the first MII bus is searched as well for an unclaimed PHY; this is * needed in case of a dual-PHY accessible only through the MAC0's MII * bus. * * Finally, if no PHY is found, then the corresponding ethernet * controller is not registered to the network subsystem.
*/
/* autodetection defaults: phy1_search_mac0 */
/* static PHY setup * * most boards PHY setup should be detectable properly with the * autodetection algorithm in mii_probe(), but in some cases (e.g. if * you have a switch attached, or want to use the PHY's interrupt * notification capabilities) you can provide a static PHY * configuration here * * IRQs may only be set, if a PHY address was configured * If a PHY address is given, also a bus id is required to be set * * ps: make sure the used irqs are configured properly in the board * specific irq-map
*/ staticvoid au1000_enable_mac(struct net_device *dev, int force_reset)
{ unsignedlong flags; struct au1000_private *aup = netdev_priv(dev);
/* find the first (lowest address) PHY * on the current MAC's MII bus
*/ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) if (mdiobus_get_phy(aup->mii_bus, phy_addr)) {
phydev = mdiobus_get_phy(aup->mii_bus, phy_addr); if (!aup->phy_search_highest_addr) /* break out with first one found */ break;
}
if (aup->phy1_search_mac0) { /* try harder to find a PHY */ if (!phydev && (aup->mac_id == 1)) { /* no PHY found, maybe we have a dual PHY? */
dev_info(&dev->dev, ": no PHY found on MAC1, " "let's see if it's attached to MAC0...\n");
/* find the first (lowest address) non-attached * PHY on the MAC0 MII bus
*/ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { struct phy_device *const tmp_phydev =
mdiobus_get_phy(aup->mii_bus,
phy_addr);
if (aup->mac_id == 1) break;
/* no PHY here... */ if (!tmp_phydev) continue;
/* already claimed by MAC0 */ if (tmp_phydev->attached_dev) continue;
phydev = tmp_phydev; break; /* found it */
}
}
}
if (!phydev) {
netdev_err(dev, "no PHY found\n"); return -1;
}
/* now we are supposed to have a proper phydev, to attach to... */
BUG_ON(phydev->attached_dev);
/* * Buffer allocation/deallocation routines. The buffer descriptor returned * has the virtual and dma address of a buffer suitable for * both, receive and transmit operations.
*/ staticstruct db_dest *au1000_GetFreeDB(struct au1000_private *aup)
{ struct db_dest *pDB;
pDB = aup->pDBfree;
aup->tx_full = 0; for (i = 0; i < NUM_RX_DMA; i++) { /* reset control bits */
aup->rx_dma_ring[i]->buff_stat &= ~0xf;
} for (i = 0; i < NUM_TX_DMA; i++) { /* reset control bits */
aup->tx_dma_ring[i]->buff_stat &= ~0xf;
}
/* * Setup the receive and transmit "rings". These pointers are the addresses * of the rx and tx MAC DMA registers so they are fixed by the hardware -- * these are not descriptors sitting in memory.
*/ staticvoid
au1000_setup_hw_rings(struct au1000_private *aup, void __iomem *tx_base)
{ int i;
for (i = 0; i < NUM_RX_DMA; i++) {
aup->rx_dma_ring[i] = (struct rx_dma *)
(tx_base + 0x100 + sizeof(struct rx_dma) * i);
} for (i = 0; i < NUM_TX_DMA; i++) {
aup->tx_dma_ring[i] = (struct tx_dma *)
(tx_base + sizeof(struct tx_dma) * i);
}
}
/* * Initialize the interface. * * When the device powers up, the clocks are disabled and the * mac is in reset state. When the interface is closed, we * do the same -- reset the device and disable the clocks to * conserve power. Thus, whenever au1000_init() is called, * the device should already be in reset state.
*/ staticint au1000_init(struct net_device *dev)
{ struct au1000_private *aup = netdev_priv(dev); unsignedlong flags; int i;
u32 control;
netif_dbg(aup, hw, dev, "au1000_init\n");
/* bring the device out of reset */
au1000_enable_mac(dev, 1);
if (status & TX_FRAME_ABORTED) { if (!dev->phydev || (DUPLEX_FULL == dev->phydev->duplex)) { if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) { /* any other tx errors are only valid * in half duplex mode
*/
ps->tx_errors++;
ps->tx_aborted_errors++;
}
} else {
ps->tx_errors++;
ps->tx_aborted_errors++; if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER))
ps->tx_carrier_errors++;
}
}
}
/* * Called from the interrupt service routine to acknowledge * the TX DONE bits. This is a must if the irq is setup as * edge triggered.
*/ staticvoid au1000_tx_ack(struct net_device *dev)
{ struct au1000_private *aup = netdev_priv(dev); struct tx_dma *ptxd;
/* * The Tx ring has been full longer than the watchdog timeout * value. The transmitter must be hung?
*/ staticvoid au1000_tx_timeout(struct net_device *dev, unsignedint txqueue)
{
netdev_err(dev, "au1000_tx_timeout: dev=%p\n", dev);
au1000_reset_mac(dev);
au1000_init(dev);
netif_trans_update(dev); /* prevent tx timeout */
netif_wake_queue(dev);
}
base = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!base) {
dev_err(&pdev->dev, "failed to retrieve base register\n");
err = -ENODEV; goto out;
}
macen = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!macen) {
dev_err(&pdev->dev, "failed to retrieve MAC Enable register\n");
err = -ENODEV; goto out;
}
macdma = platform_get_resource(pdev, IORESOURCE_MEM, 2); if (!macdma) {
dev_err(&pdev->dev, "failed to retrieve MACDMA registers\n");
err = -ENODEV; goto out;
}
if (!request_mem_region(base->start, resource_size(base),
pdev->name)) {
dev_err(&pdev->dev, "failed to request memory region for base registers\n");
err = -ENXIO; goto out;
}
if (!request_mem_region(macen->start, resource_size(macen),
pdev->name)) {
dev_err(&pdev->dev, "failed to request memory region for MAC enable register\n");
err = -ENXIO; goto err_request;
}
if (!request_mem_region(macdma->start, resource_size(macdma),
pdev->name)) {
dev_err(&pdev->dev, "failed to request MACDMA memory region\n");
err = -ENXIO; goto err_macdma;
}
dev = alloc_etherdev(sizeof(struct au1000_private)); if (!dev) {
err = -ENOMEM; goto err_alloc;
}
/* Allocate the data buffers * Snooping works fine with eth on all au1xxx
*/
aup->vaddr = dma_alloc_coherent(&pdev->dev, MAX_BUF_SIZE *
(NUM_TX_BUFFS + NUM_RX_BUFFS),
&aup->dma_addr, 0); if (!aup->vaddr) {
dev_err(&pdev->dev, "failed to allocate data buffers\n");
err = -ENOMEM; goto err_vaddr;
}
/* aup->mac is the base address of the MAC's registers */
aup->mac = (struct mac_reg *)
ioremap(base->start, resource_size(base)); if (!aup->mac) {
dev_err(&pdev->dev, "failed to ioremap MAC registers\n");
err = -ENXIO; goto err_remap1;
}
/* Setup some variables for quick register address access */
aup->enable = (u32 *)ioremap(macen->start,
resource_size(macen)); if (!aup->enable) {
dev_err(&pdev->dev, "failed to ioremap MAC enable register\n");
err = -ENXIO; goto err_remap2;
}
aup->mac_id = pdev->id;
aup->macdma = ioremap(macdma->start, resource_size(macdma)); if (!aup->macdma) {
dev_err(&pdev->dev, "failed to ioremap MACDMA registers\n");
err = -ENXIO; goto err_remap3;
}
au1000_setup_hw_rings(aup, aup->macdma);
writel(0, aup->enable);
aup->mac_enabled = 0;
pd = dev_get_platdata(&pdev->dev); if (!pd) {
dev_info(&pdev->dev, "no platform_data passed," " PHY search on MAC0\n");
aup->phy1_search_mac0 = 1;
} else { if (is_valid_ether_addr(pd->mac)) {
eth_hw_addr_set(dev, pd->mac);
} else { /* Set a random MAC since no valid provided by platform_data. */
eth_hw_addr_random(dev);
}
/* if known, set corresponding PHY IRQs */ if (aup->phy_static_config) if (aup->phy_irq && aup->phy_busid == aup->mac_id)
aup->mii_bus->irq[aup->phy_addr] = aup->phy_irq;
err = mdiobus_register(aup->mii_bus); if (err) {
dev_err(&pdev->dev, "failed to register MDIO bus\n"); goto err_mdiobus_reg;
}
err = au1000_mii_probe(dev); if (err != 0) goto err_out;
pDBfree = NULL; /* setup the data buffer descriptors and attach a buffer to each one */
pDB = aup->db; for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
pDB->pnext = pDBfree;
pDBfree = pDB;
pDB->vaddr = aup->vaddr + MAX_BUF_SIZE * i;
pDB->dma_addr = aup->dma_addr + MAX_BUF_SIZE * i;
pDB++;
}
aup->pDBfree = pDBfree;
err = -ENODEV; for (i = 0; i < NUM_RX_DMA; i++) {
pDB = au1000_GetFreeDB(aup); if (!pDB) goto err_out;
/* * The boot code uses the ethernet controller, so reset it to start * fresh. au1000_init() expects that the device is in reset state.
*/
au1000_reset_mac(dev);
err = register_netdev(dev); if (err) {
netdev_err(dev, "Cannot register net device, aborting.\n"); goto err_out;
}
netdev_info(dev, "Au1xx0 Ethernet found at 0x%lx, irq %d\n",
(unsignedlong)base->start, irq);
return 0;
err_out: if (aup->mii_bus)
mdiobus_unregister(aup->mii_bus);
/* here we should have a valid dev plus aup-> register addresses * so we can reset the mac properly.
*/
au1000_reset_mac(dev);
for (i = 0; i < NUM_RX_DMA; i++) { if (aup->rx_db_inuse[i])
au1000_ReleaseDB(aup, aup->rx_db_inuse[i]);
} for (i = 0; i < NUM_TX_DMA; i++) { if (aup->tx_db_inuse[i])
au1000_ReleaseDB(aup, aup->tx_db_inuse[i]);
}
err_mdiobus_reg:
mdiobus_free(aup->mii_bus);
err_mdiobus_alloc:
iounmap(aup->macdma);
err_remap3:
iounmap(aup->enable);
err_remap2:
iounmap(aup->mac);
err_remap1:
dma_free_coherent(&pdev->dev, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
aup->vaddr, aup->dma_addr);
err_vaddr:
free_netdev(dev);
err_alloc:
release_mem_region(macdma->start, resource_size(macdma));
err_macdma:
release_mem_region(macen->start, resource_size(macen));
err_request:
release_mem_region(base->start, resource_size(base));
out: return err;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.