/* Open the interface. * The interface is opened whenever "ifconfig" actives it. */ static int emac_open(struct net_device *dev) { struct emac_board_info *db = netdev_priv(dev); int ret; if (netif_msg_ifup(db)) dev_dbg(db->dev, "enabling %s\n", dev->name); if (request_irq(dev->irq, &emac_interrupt, 0, dev->name, dev)) return -EAGAIN; /* Initialize EMAC board */ emac_reset(db); emac_init_device(dev); ret = emac_mdio_probe(dev); if (ret < 0) { free_irq(dev->irq, dev); netdev_err(dev, "cannot probe MDIO bus\n"); return ret; } phy_start(dev->phydev); netif_start_queue(dev); return 0; }
static int emac_resume(struct platform_device *dev) { struct net_device *ndev = platform_get_drvdata(dev); struct emac_board_info *db = netdev_priv(ndev); emac_reset(db); emac_init_device(ndev); netif_device_attach(ndev); return 0; }
/* Our watchdog timed out. Called by the networking layer */ static void emac_timeout(struct net_device *dev) { struct emac_board_info *db = netdev_priv(dev); unsigned long flags; if (netif_msg_timer(db)) dev_err(db->dev, "tx time out.\n"); /* Save previous register address */ spin_lock_irqsave(&db->lock, flags); netif_stop_queue(dev); emac_reset(db); emac_init_device(dev); /* We can accept TX packets again */ netif_trans_update(dev); netif_wake_queue(dev); /* Restore previous register address */ spin_unlock_irqrestore(&db->lock, flags); }
int eth_init() { cpu_flags_t flags; emac_reset(); emac_start(); event_initGeneric(&recv_wait); event_initGeneric(&send_wait); // Register interrupt vector IRQ_SAVE_DISABLE(flags); /* Disable all emac interrupts */ EMAC_IDR = 0xFFFFFFFF; #if CPU_ARM_AT91 // TODO: define sysirq_set... /* Set the vector. */ AIC_SVR(EMAC_ID) = emac_irqHandler; /* Initialize to edge triggered with defined priority. */ AIC_SMR(EMAC_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED; /* Clear pending interrupt */ AIC_ICCR = BV(EMAC_ID); /* Enable the system IRQ */ AIC_IECR = BV(EMAC_ID); #else sysirq_setHandler(INT_EMAC, emac_irqHandler); #endif /* Enable interrupts */ EMAC_IER = EMAC_RX_INTS | EMAC_TX_INTS; IRQ_RESTORE(flags); return 0; }
/* Search EMAC board, allocate space and register it */ static int emac_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct emac_board_info *db; struct net_device *ndev; int ret = 0; const char *mac_addr; ndev = alloc_etherdev(sizeof(struct emac_board_info)); if (!ndev) { dev_err(&pdev->dev, "could not allocate device.\n"); return -ENOMEM; } SET_NETDEV_DEV(ndev, &pdev->dev); db = netdev_priv(ndev); memset(db, 0, sizeof(*db)); db->dev = &pdev->dev; db->ndev = ndev; db->pdev = pdev; db->msg_enable = netif_msg_init(debug, EMAC_DEFAULT_MSG_ENABLE); spin_lock_init(&db->lock); db->membase = of_iomap(np, 0); if (!db->membase) { dev_err(&pdev->dev, "failed to remap registers\n"); ret = -ENOMEM; goto out; } /* fill in parameters for net-dev structure */ ndev->base_addr = (unsigned long)db->membase; ndev->irq = irq_of_parse_and_map(np, 0); if (ndev->irq == -ENXIO) { netdev_err(ndev, "No irq resource\n"); ret = ndev->irq; goto out_iounmap; } db->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(db->clk)) { ret = PTR_ERR(db->clk); goto out_iounmap; } ret = clk_prepare_enable(db->clk); if (ret) { dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret); goto out_iounmap; } ret = sunxi_sram_claim(&pdev->dev); if (ret) { dev_err(&pdev->dev, "Error couldn't map SRAM to device\n"); goto out_clk_disable_unprepare; } db->phy_node = of_parse_phandle(np, "phy", 0); if (!db->phy_node) { dev_err(&pdev->dev, "no associated PHY\n"); ret = -ENODEV; goto out_release_sram; } /* Read MAC-address from DT */ mac_addr = of_get_mac_address(np); if (mac_addr) memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); /* Check if the MAC address is valid, if not get a random one */ if (!is_valid_ether_addr(ndev->dev_addr)) { eth_hw_addr_random(ndev); dev_warn(&pdev->dev, "using random MAC address %pM\n", ndev->dev_addr); } db->emacrx_completed_flag = 1; emac_powerup(ndev); emac_reset(db); ndev->netdev_ops = &emac_netdev_ops; ndev->watchdog_timeo = msecs_to_jiffies(watchdog); ndev->ethtool_ops = &emac_ethtool_ops; platform_set_drvdata(pdev, ndev); /* Carrier starts down, phylib will bring it up */ netif_carrier_off(ndev); ret = register_netdev(ndev); if (ret) { dev_err(&pdev->dev, "Registering netdev failed!\n"); ret = -ENODEV; goto out_release_sram; } dev_info(&pdev->dev, "%s: at %p, IRQ %d MAC: %pM\n", ndev->name, db->membase, ndev->irq, ndev->dev_addr); return 0; out_release_sram: sunxi_sram_release(&pdev->dev); out_clk_disable_unprepare: clk_disable_unprepare(db->clk); out_iounmap: iounmap(db->membase); out: dev_err(db->dev, "not found (%d).\n", ret); free_netdev(ndev); return ret; }
/* Search EMAC board, allocate space and register it */ static int emac_probe(struct vmm_device *pdev, const struct vmm_devtree_nodeid *devid) { struct device_node *np = pdev->node; struct emac_board_info *db; struct net_device *ndev; int ret = 0; const char *mac_addr; virtual_addr_t reg_addr; ndev = alloc_etherdev(sizeof(struct emac_board_info)); if (!ndev) { dev_err(pdev, "%s: could not allocate device.\n", __func__); return -ENOMEM; } strlcpy(ndev->name, pdev->name, sizeof(ndev->name)); SET_NETDEV_DEV(ndev, pdev); db = netdev_priv(ndev); memset(db, 0, sizeof(*db)); db->ndev = ndev; db->pdev = pdev; spin_lock_init(&db->lock); if ((ret = vmm_devtree_request_regmap(np, ®_addr, 0, "Sun4i EMAC"))) { vmm_printf("%s: Failed to ioreamp\n", __func__); return -ENOMEM; } db->membase = (void *) reg_addr; /* fill in parameters for net-dev structure */ ndev->base_addr = (unsigned long)db->membase; ret = vmm_devtree_irq_get(np, &ndev->irq, 0); if (ret) { vmm_printf("%s: No irq resource\n", __func__); goto out; } db->clk = clk_get(pdev, NULL); if (IS_ERR(db->clk)) goto out; clk_prepare_enable(db->clk); db->phy_node = vmm_devtree_parse_phandle(np, "phy", 0); if (!db->phy_node) { dev_err(pdev, "%s: no associated PHY\n", __func__); ret = -ENODEV; goto out; } /* Read MAC-address from DT */ mac_addr = of_get_mac_address(np); if (mac_addr) memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); /* Check if the MAC address is valid, if not get a random one */ if (!is_valid_ether_addr(ndev->dev_addr)) { eth_hw_addr_random(ndev); dev_info(pdev, "using random MAC address: "); print_mac_address_fmt(ndev->dev_addr); } db->emacrx_completed_flag = 1; emac_powerup(ndev); emac_reset(db); ether_setup(ndev); ndev->netdev_ops = &emac_netdev_ops; ndev->watchdog_timeo = msecs_to_jiffies(watchdog); ndev->ethtool_ops = &emac_ethtool_ops; platform_set_drvdata(pdev, ndev); /* Carrier starts down, phylib will bring it up */ netif_carrier_off(ndev); ret = register_netdev(ndev); if (ret) { dev_err(pdev, "%s: Registering netdev failed!\n", __func__); ret = -ENODEV; goto out; } dev_info(pdev, "%s: at %p, IRQ %d MAC: ", ndev->name, db->membase, ndev->irq); print_mac_address_fmt(ndev->dev_addr); return 0; out: dev_err(pdev, "%s: not found (%d).\n", __func__, ret); free_netdev(ndev); return ret; }