static void __lpc_eth_init(struct netdata_local *pldat) { u32 tmp; /* Disable controller and reset */ tmp = readl(LPC_ENET_COMMAND(pldat->net_base)); tmp &= ~LPC_COMMAND_RXENABLE | LPC_COMMAND_TXENABLE; writel(tmp, LPC_ENET_COMMAND(pldat->net_base)); tmp = readl(LPC_ENET_MAC1(pldat->net_base)); tmp &= ~LPC_MAC1_RECV_ENABLE; writel(tmp, LPC_ENET_MAC1(pldat->net_base)); /* Initial MAC setup */ writel(LPC_MAC1_PASS_ALL_RX_FRAMES, LPC_ENET_MAC1(pldat->net_base)); writel((LPC_MAC2_PAD_CRC_ENABLE | LPC_MAC2_CRC_ENABLE), LPC_ENET_MAC2(pldat->net_base)); writel(ENET_MAXF_SIZE, LPC_ENET_MAXF(pldat->net_base)); /* Collision window, gap */ writel((LPC_CLRT_LOAD_RETRY_MAX(0xF) | LPC_CLRT_LOAD_COLLISION_WINDOW(0x37)), LPC_ENET_CLRT(pldat->net_base)); writel(LPC_IPGR_LOAD_PART2(0x12), LPC_ENET_IPGR(pldat->net_base)); if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) writel(LPC_COMMAND_PASSRUNTFRAME, LPC_ENET_COMMAND(pldat->net_base)); else { writel((LPC_COMMAND_PASSRUNTFRAME | LPC_COMMAND_RMII), LPC_ENET_COMMAND(pldat->net_base)); writel(LPC_SUPP_RESET_RMII, LPC_ENET_SUPP(pldat->net_base)); } __lpc_params_setup(pldat); /* Setup TX and RX descriptors */ __lpc_txrx_desc_setup(pldat); /* Setup packet filtering */ writel((LPC_RXFLTRW_ACCEPTUBROADCAST | LPC_RXFLTRW_ACCEPTPERFECT), LPC_ENET_RXFILTER_CTRL(pldat->net_base)); /* Get the next TX buffer output index */ pldat->num_used_tx_buffs = 0; pldat->last_tx_idx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base)); /* Clear and enable interrupts */ writel(0xFFFF, LPC_ENET_INTCLEAR(pldat->net_base)); smp_wmb(); lpc_eth_enable_int(pldat->net_base); /* Enable controller */ tmp = readl(LPC_ENET_COMMAND(pldat->net_base)); tmp |= LPC_COMMAND_RXENABLE | LPC_COMMAND_TXENABLE; writel(tmp, LPC_ENET_COMMAND(pldat->net_base)); tmp = readl(LPC_ENET_MAC1(pldat->net_base)); tmp |= LPC_MAC1_RECV_ENABLE; writel(tmp, LPC_ENET_MAC1(pldat->net_base)); }
static int lpc_mii_init(struct netdata_local *pldat) { int err = -ENXIO, i; pldat->mii_bus = mdiobus_alloc(); if (!pldat->mii_bus) { err = -ENOMEM; goto err_out; } /* Setup MII mode */ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) writel(LPC_COMMAND_PASSRUNTFRAME, LPC_ENET_COMMAND(pldat->net_base)); else { writel((LPC_COMMAND_PASSRUNTFRAME | LPC_COMMAND_RMII), LPC_ENET_COMMAND(pldat->net_base)); writel(LPC_SUPP_RESET_RMII, LPC_ENET_SUPP(pldat->net_base)); } pldat->mii_bus->name = "lpc_mii_bus"; pldat->mii_bus->read = &lpc_mdio_read; pldat->mii_bus->write = &lpc_mdio_write; pldat->mii_bus->reset = &lpc_mdio_reset; snprintf(pldat->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", pldat->pdev->name, pldat->pdev->id); pldat->mii_bus->priv = pldat; pldat->mii_bus->parent = &pldat->pdev->dev; pldat->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); if (!pldat->mii_bus->irq) { err = -ENOMEM; goto err_out_1; } for (i = 0; i < PHY_MAX_ADDR; i++) pldat->mii_bus->irq[i] = PHY_POLL; platform_set_drvdata(pldat->pdev, pldat->mii_bus); if (mdiobus_register(pldat->mii_bus)) goto err_out_free_mdio_irq; if (lpc_mii_probe(pldat->ndev) != 0) goto err_out_unregister_bus; return 0; err_out_unregister_bus: mdiobus_unregister(pldat->mii_bus); err_out_free_mdio_irq: kfree(pldat->mii_bus->irq); err_out_1: mdiobus_free(pldat->mii_bus); err_out: return err; }
static int lpc_mii_probe(struct net_device *ndev) { struct netdata_local *pldat = netdev_priv(ndev); struct phy_device *phydev = phy_find_first(pldat->mii_bus); if (!phydev) { netdev_err(ndev, "no PHY found\n"); return -ENODEV; } /* Attach to the PHY */ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) netdev_info(ndev, "using MII interface\n"); else netdev_info(ndev, "using RMII interface\n"); phydev = phy_connect(ndev, dev_name(&phydev->dev), &lpc_handle_link_change, lpc_phy_interface_mode(&pldat->pdev->dev)); if (IS_ERR(phydev)) { netdev_err(ndev, "Could not attach to PHY\n"); return PTR_ERR(phydev); } /* mask with MAC supported features */ phydev->supported &= PHY_BASIC_FEATURES; phydev->advertising = phydev->supported; pldat->link = 0; pldat->speed = 0; pldat->duplex = -1; pldat->phy_dev = phydev; netdev_info(ndev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; }