Example #1
0
File: bgmac.c Project: 7799/linux
static int bgmac_stop(struct net_device *net_dev)
{
	struct bgmac *bgmac = netdev_priv(net_dev);

	netif_carrier_off(net_dev);

	phy_stop(bgmac->phy_dev);

	napi_disable(&bgmac->napi);
	bgmac_chip_intrs_off(bgmac);
	free_irq(bgmac->core->irq, net_dev);

	bgmac_chip_reset(bgmac);

	return 0;
}
Example #2
0
static irqreturn_t bgmac_interrupt(int irq, void *dev_id)
{
	struct bgmac *bgmac = netdev_priv(dev_id);

	u32 int_status = bgmac_read(bgmac, BGMAC_INT_STATUS);
	int_status &= bgmac->int_mask;

	if (!int_status)
		return IRQ_NONE;

	int_status &= ~(BGMAC_IS_TX0 | BGMAC_IS_RX);
	if (int_status)
		bgmac_err(bgmac, "Unknown IRQs: 0x%08X\n", int_status);

	/* Disable new interrupts until handling existing ones */
	bgmac_chip_intrs_off(bgmac);

	napi_schedule(&bgmac->napi);

	return IRQ_HANDLED;
}
Example #3
0
int bgmac_enet_suspend(struct bgmac *bgmac)
{
	if (!netif_running(bgmac->net_dev))
		return 0;

	phy_stop(bgmac->net_dev->phydev);

	netif_stop_queue(bgmac->net_dev);

	napi_disable(&bgmac->napi);

	netif_tx_lock(bgmac->net_dev);
	netif_device_detach(bgmac->net_dev);
	netif_tx_unlock(bgmac->net_dev);

	bgmac_chip_intrs_off(bgmac);
	bgmac_chip_reset(bgmac);
	bgmac_dma_cleanup(bgmac);

	return 0;
}
Example #4
0
File: bgmac.c Project: 7799/linux
static irqreturn_t bgmac_interrupt(int irq, void *dev_id)
{
	struct bgmac *bgmac = netdev_priv(dev_id);

	u32 int_status = bgmac_read(bgmac, BGMAC_INT_STATUS);
	int_status &= bgmac->int_mask;

	if (!int_status)
		return IRQ_NONE;

	/* Ack */
	bgmac_write(bgmac, BGMAC_INT_STATUS, int_status);

	/* Disable new interrupts until handling existing ones */
	bgmac_chip_intrs_off(bgmac);

	bgmac->int_status = int_status;

	napi_schedule(&bgmac->napi);

	return IRQ_HANDLED;
}
Example #5
0
int bgmac_phy_connect_direct(struct bgmac *bgmac)
{
	struct fixed_phy_status fphy_status = {
		.link = 1,
		.speed = SPEED_1000,
		.duplex = DUPLEX_FULL,
	};
	struct phy_device *phy_dev;
	int err;

	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
	if (!phy_dev || IS_ERR(phy_dev)) {
		dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
		return -ENODEV;
	}

	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
				 PHY_INTERFACE_MODE_MII);
	if (err) {
		dev_err(bgmac->dev, "Connecting PHY failed\n");
		return err;
	}

	return err;
}
EXPORT_SYMBOL_GPL(bgmac_phy_connect_direct);

struct bgmac *bgmac_alloc(struct device *dev)
{
	struct net_device *net_dev;
	struct bgmac *bgmac;

	/* Allocation and references */
	net_dev = devm_alloc_etherdev(dev, sizeof(*bgmac));
	if (!net_dev)
		return NULL;

	net_dev->netdev_ops = &bgmac_netdev_ops;
	net_dev->ethtool_ops = &bgmac_ethtool_ops;

	bgmac = netdev_priv(net_dev);
	bgmac->dev = dev;
	bgmac->net_dev = net_dev;

	return bgmac;
}
EXPORT_SYMBOL_GPL(bgmac_alloc);

int bgmac_enet_probe(struct bgmac *bgmac)
{
	struct net_device *net_dev = bgmac->net_dev;
	int err;

	bgmac_chip_intrs_off(bgmac);

	net_dev->irq = bgmac->irq;
	SET_NETDEV_DEV(net_dev, bgmac->dev);
	dev_set_drvdata(bgmac->dev, bgmac);

	if (!is_valid_ether_addr(net_dev->dev_addr)) {
		dev_err(bgmac->dev, "Invalid MAC addr: %pM\n",
			net_dev->dev_addr);
		eth_hw_addr_random(net_dev);
		dev_warn(bgmac->dev, "Using random MAC: %pM\n",
			 net_dev->dev_addr);
	}

	/* This (reset &) enable is not preset in specs or reference driver but
	 * Broadcom does it in arch PCI code when enabling fake PCI device.
	 */
	bgmac_clk_enable(bgmac, 0);

	/* This seems to be fixing IRQ by assigning OOB #6 to the core */
	if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) {
		if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
			bgmac_idm_write(bgmac, BCMA_OOB_SEL_OUT_A30, 0x86);
	}

	bgmac_chip_reset(bgmac);

	err = bgmac_dma_alloc(bgmac);
	if (err) {
		dev_err(bgmac->dev, "Unable to alloc memory for DMA\n");
		goto err_out;
	}

	bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
	if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0)
		bgmac->int_mask &= ~BGMAC_IS_TX_MASK;

	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);

	err = bgmac_phy_connect(bgmac);
	if (err) {
		dev_err(bgmac->dev, "Cannot connect to phy\n");
		goto err_dma_free;
	}

	net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
	net_dev->hw_features = net_dev->features;
	net_dev->vlan_features = net_dev->features;

	err = register_netdev(bgmac->net_dev);
	if (err) {
		dev_err(bgmac->dev, "Cannot register net device\n");
		goto err_phy_disconnect;
	}

	netif_carrier_off(net_dev);

	return 0;

err_phy_disconnect:
	phy_disconnect(net_dev->phydev);
err_dma_free:
	bgmac_dma_free(bgmac);
err_out:

	return err;
}
EXPORT_SYMBOL_GPL(bgmac_enet_probe);

void bgmac_enet_remove(struct bgmac *bgmac)
{
	unregister_netdev(bgmac->net_dev);
	phy_disconnect(bgmac->net_dev->phydev);
	netif_napi_del(&bgmac->napi);
	bgmac_dma_free(bgmac);
	free_netdev(bgmac->net_dev);
}