Newer
Older
(((crc ^ data) & 1) ? CRC32_POLY : 0);
/* only upper 6 bits (HASH_BITS) are used
* which point to specific bit in he hash registers
*/
hash = (crc >> (32 - HASH_BITS)) & 0x3f;
if (hash > 31) {
tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
tmp |= 1 << (hash - 32);
writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
} else {
tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
tmp |= 1 << hash;
writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
}
static int
fec_set_mac_address(struct net_device *dev, void *p)
struct fec_enet_private *fep = netdev_priv(dev);
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
fep->hwp + FEC_ADDR_LOW);
writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
fep->hwp + FEC_ADDR_HIGH);
static const struct net_device_ops fec_netdev_ops = {
.ndo_open = fec_enet_open,
.ndo_stop = fec_enet_close,
.ndo_start_xmit = fec_enet_start_xmit,
.ndo_set_multicast_list = set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = fec_timeout,
.ndo_set_mac_address = fec_set_mac_address,
.ndo_do_ioctl = fec_enet_ioctl,
/*
* XXX: We need to clean up on failure exits here.
*
* index is only used in legacy code
static int fec_enet_init(struct net_device *dev, int index)
{
struct fec_enet_private *fep = netdev_priv(dev);
/* Allocate memory for buffer descriptors. */
cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
GFP_KERNEL);
if (!cbd_base) {
printk("FEC: allocate descriptor memory failed?\n");
return -ENOMEM;
}
spin_lock_init(&fep->hw_lock);
/* Set the Ethernet address */
#ifdef CONFIG_M5272
#else
{
unsigned long l;
dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24);
dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16);
dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8);
dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0);
dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24);
dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16);
}
#endif
/* Set receive and transmit descriptor base. */
fep->rx_bd_base = cbd_base;
fep->tx_bd_base = cbd_base + RX_RING_SIZE;
/* The FEC Ethernet specific entries in the device structure */
dev->ethtool_ops = &fec_enet_ethtool_ops;
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
/* Initialize the receive buffer descriptors. */
bdp = fep->rx_bd_base;
for (i = 0; i < RX_RING_SIZE; i++) {
/* Initialize the BD for every fragment in the page. */
bdp->cbd_sc = 0;
bdp++;
}
/* Set the last buffer to wrap */
bdp--;
bdp->cbd_sc |= BD_SC_WRAP;
/* ...and the same for transmit */
bdp = fep->tx_bd_base;
for (i = 0; i < TX_RING_SIZE; i++) {
/* Initialize the BD for every fragment in the page. */
bdp->cbd_sc = 0;
bdp->cbd_bufaddr = 0;
bdp++;
}
/* Set the last buffer to wrap */
bdp--;
bdp->cbd_sc |= BD_SC_WRAP;
return 0;
}
/* This function is called to start or restart the FEC during a link
* change. This only happens when switching between half and full
* duplex.
*/
static void
fec_restart(struct net_device *dev, int duplex)
{
struct fec_enet_private *fep = netdev_priv(dev);
/* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL);
/* Clear any outstanding interrupt. */
writel(0xffc00000, fep->hwp + FEC_IEVENT);
/* Reset all multicast. */
writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
#ifndef CONFIG_M5272
writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
#endif
/* Set maximum receive buffer size. */
writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
/* Set receive and transmit descriptor base. */
writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE,
fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
fep->cur_rx = fep->rx_bd_base;
for (i = 0; i <= TX_RING_MOD_MASK; i++) {
if (fep->tx_skbuff[i]) {
dev_kfree_skb_any(fep->tx_skbuff[i]);
fep->tx_skbuff[i] = NULL;
}
}
/* MII enable / FD enable */
writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL);
writel(0x04, fep->hwp + FEC_X_CNTRL);
/* MII enable / No Rcv on Xmit */
writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL);
writel(0x0, fep->hwp + FEC_X_CNTRL);
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
#ifdef FEC_MIIGSK_ENR
if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
/* disable the gasket and wait */
writel(0, fep->hwp + FEC_MIIGSK_ENR);
while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
udelay(1);
/* configure the gasket: RMII, 50 MHz, no loopback, no echo */
writel(1, fep->hwp + FEC_MIIGSK_CFGR);
/* re-enable the gasket */
writel(2, fep->hwp + FEC_MIIGSK_ENR);
}
#endif
/* And last, enable the transmit and receive processing */
writel(2, fep->hwp + FEC_ECNTRL);
writel(0, fep->hwp + FEC_R_DES_ACTIVE);
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
}
static void
fec_stop(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
/* We cannot expect a graceful transmit stop without link !!! */
if (fep->link) {
writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */
udelay(10);
if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA))
printk("fec_stop : Graceful transmit stop did not complete !\n");
/* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL);
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
static int __devinit
fec_probe(struct platform_device *pdev)
{
struct fec_enet_private *fep;
struct fec_platform_data *pdata;
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
struct net_device *ndev;
int i, irq, ret = 0;
struct resource *r;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r)
return -ENXIO;
r = request_mem_region(r->start, resource_size(r), pdev->name);
if (!r)
return -EBUSY;
/* Init network device */
ndev = alloc_etherdev(sizeof(struct fec_enet_private));
if (!ndev)
return -ENOMEM;
SET_NETDEV_DEV(ndev, &pdev->dev);
/* setup board info structure */
fep = netdev_priv(ndev);
memset(fep, 0, sizeof(*fep));
ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r));
fep->pdev = pdev;
if (!ndev->base_addr) {
ret = -ENOMEM;
goto failed_ioremap;
}
platform_set_drvdata(pdev, ndev);
pdata = pdev->dev.platform_data;
if (pdata)
fep->phy_interface = pdata->phy;
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
/* This device has up to three irqs on some platforms */
for (i = 0; i < 3; i++) {
irq = platform_get_irq(pdev, i);
if (i && irq < 0)
break;
ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
if (ret) {
while (i >= 0) {
irq = platform_get_irq(pdev, i);
free_irq(irq, ndev);
i--;
}
goto failed_irq;
}
}
fep->clk = clk_get(&pdev->dev, "fec_clk");
if (IS_ERR(fep->clk)) {
ret = PTR_ERR(fep->clk);
goto failed_clk;
}
clk_enable(fep->clk);
ret = fec_enet_init(ndev, 0);
if (ret)
goto failed_init;
ret = fec_enet_mii_init(pdev);
if (ret)
goto failed_mii_init;
/* Carrier starts down, phylib will bring it up */
netif_carrier_off(ndev);
ret = register_netdev(ndev);
if (ret)
goto failed_register;
return 0;
failed_register:
fec_enet_mii_remove(fep);
failed_mii_init:
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
failed_init:
clk_disable(fep->clk);
clk_put(fep->clk);
failed_clk:
for (i = 0; i < 3; i++) {
irq = platform_get_irq(pdev, i);
if (irq > 0)
free_irq(irq, ndev);
}
failed_irq:
iounmap((void __iomem *)ndev->base_addr);
failed_ioremap:
free_netdev(ndev);
return ret;
}
static int __devexit
fec_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct fec_enet_private *fep = netdev_priv(ndev);
platform_set_drvdata(pdev, NULL);
fec_stop(ndev);
fec_enet_mii_remove(fep);
clk_disable(fep->clk);
clk_put(fep->clk);
iounmap((void __iomem *)ndev->base_addr);
unregister_netdev(ndev);
free_netdev(ndev);
return 0;
}
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep;
if (ndev) {
fep = netdev_priv(ndev);
if (netif_running(ndev))
fec_enet_close(ndev);
clk_disable(fep->clk);
}
return 0;
}
static int
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep;
fep = netdev_priv(ndev);
clk_enable(fep->clk);
if (netif_running(ndev))
fec_enet_open(ndev);
}
return 0;
}
static const struct dev_pm_ops fec_pm_ops = {
.suspend = fec_suspend,
.resume = fec_resume,
.freeze = fec_suspend,
.thaw = fec_resume,
.poweroff = fec_suspend,
.restore = fec_resume,
};
static struct platform_driver fec_driver = {
.driver = {
.name = "fec",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &fec_pm_ops,
#endif
.probe = fec_probe,
.remove = __devexit_p(fec_drv_remove),
};
static int __init
fec_enet_module_init(void)
{
printk(KERN_INFO "FEC Ethernet Driver\n");
return platform_driver_register(&fec_driver);
}
static void __exit
fec_enet_cleanup(void)
{
platform_driver_unregister(&fec_driver);
}
module_exit(fec_enet_cleanup);
module_init(fec_enet_module_init);
MODULE_LICENSE("GPL");