]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/smc91x.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / drivers / net / smc91x.c
index 0a47bad4afeb4e88d8bf5038d01b305375218269..734bf1e82c4fb2b3a6e3867181fdb5fffd3136c4 100644 (file)
@@ -1619,7 +1619,7 @@ smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        strncpy(info->driver, CARDNAME, sizeof(info->driver));
        strncpy(info->version, version, sizeof(info->version));
-       strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
+       strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
 }
 
 static int smc_ethtool_nwayreset(struct net_device *dev)
@@ -1648,6 +1648,117 @@ static void smc_ethtool_setmsglevel(struct net_device *dev, u32 level)
        lp->msg_enable = level;
 }
 
+static int smc_write_eeprom_word(struct net_device *dev, u16 addr, u16 word)
+{
+       u16 ctl;
+       struct smc_local *lp = netdev_priv(dev);
+       void __iomem *ioaddr = lp->base;
+
+       spin_lock_irq(&lp->lock);
+       /* load word into GP register */
+       SMC_SELECT_BANK(lp, 1);
+       SMC_SET_GP(lp, word);
+       /* set the address to put the data in EEPROM */
+       SMC_SELECT_BANK(lp, 2);
+       SMC_SET_PTR(lp, addr);
+       /* tell it to write */
+       SMC_SELECT_BANK(lp, 1);
+       ctl = SMC_GET_CTL(lp);
+       SMC_SET_CTL(lp, ctl | (CTL_EEPROM_SELECT | CTL_STORE));
+       /* wait for it to finish */
+       do {
+               udelay(1);
+       } while (SMC_GET_CTL(lp) & CTL_STORE);
+       /* clean up */
+       SMC_SET_CTL(lp, ctl);
+       SMC_SELECT_BANK(lp, 2);
+       spin_unlock_irq(&lp->lock);
+       return 0;
+}
+
+static int smc_read_eeprom_word(struct net_device *dev, u16 addr, u16 *word)
+{
+       u16 ctl;
+       struct smc_local *lp = netdev_priv(dev);
+       void __iomem *ioaddr = lp->base;
+
+       spin_lock_irq(&lp->lock);
+       /* set the EEPROM address to get the data from */
+       SMC_SELECT_BANK(lp, 2);
+       SMC_SET_PTR(lp, addr | PTR_READ);
+       /* tell it to load */
+       SMC_SELECT_BANK(lp, 1);
+       SMC_SET_GP(lp, 0xffff); /* init to known */
+       ctl = SMC_GET_CTL(lp);
+       SMC_SET_CTL(lp, ctl | (CTL_EEPROM_SELECT | CTL_RELOAD));
+       /* wait for it to finish */
+       do {
+               udelay(1);
+       } while (SMC_GET_CTL(lp) & CTL_RELOAD);
+       /* read word from GP register */
+       *word = SMC_GET_GP(lp);
+       /* clean up */
+       SMC_SET_CTL(lp, ctl);
+       SMC_SELECT_BANK(lp, 2);
+       spin_unlock_irq(&lp->lock);
+       return 0;
+}
+
+static int smc_ethtool_geteeprom_len(struct net_device *dev)
+{
+       return 0x23 * 2;
+}
+
+static int smc_ethtool_geteeprom(struct net_device *dev,
+               struct ethtool_eeprom *eeprom, u8 *data)
+{
+       int i;
+       int imax;
+
+       DBG(1, "Reading %d bytes at %d(0x%x)\n",
+               eeprom->len, eeprom->offset, eeprom->offset);
+       imax = smc_ethtool_geteeprom_len(dev);
+       for (i = 0; i < eeprom->len; i += 2) {
+               int ret;
+               u16 wbuf;
+               int offset = i + eeprom->offset;
+               if (offset > imax)
+                       break;
+               ret = smc_read_eeprom_word(dev, offset >> 1, &wbuf);
+               if (ret != 0)
+                       return ret;
+               DBG(2, "Read 0x%x from 0x%x\n", wbuf, offset >> 1);
+               data[i] = (wbuf >> 8) & 0xff;
+               data[i+1] = wbuf & 0xff;
+       }
+       return 0;
+}
+
+static int smc_ethtool_seteeprom(struct net_device *dev,
+               struct ethtool_eeprom *eeprom, u8 *data)
+{
+       int i;
+       int imax;
+
+       DBG(1, "Writing %d bytes to %d(0x%x)\n",
+                       eeprom->len, eeprom->offset, eeprom->offset);
+       imax = smc_ethtool_geteeprom_len(dev);
+       for (i = 0; i < eeprom->len; i += 2) {
+               int ret;
+               u16 wbuf;
+               int offset = i + eeprom->offset;
+               if (offset > imax)
+                       break;
+               wbuf = (data[i] << 8) | data[i + 1];
+               DBG(2, "Writing 0x%x to 0x%x\n", wbuf, offset >> 1);
+               ret = smc_write_eeprom_word(dev, offset >> 1, wbuf);
+               if (ret != 0)
+                       return ret;
+       }
+       return 0;
+}
+
+
 static const struct ethtool_ops smc_ethtool_ops = {
        .get_settings   = smc_ethtool_getsettings,
        .set_settings   = smc_ethtool_setsettings,
@@ -1657,8 +1768,22 @@ static const struct ethtool_ops smc_ethtool_ops = {
        .set_msglevel   = smc_ethtool_setmsglevel,
        .nway_reset     = smc_ethtool_nwayreset,
        .get_link       = ethtool_op_get_link,
-//     .get_eeprom     = smc_ethtool_geteeprom,
-//     .set_eeprom     = smc_ethtool_seteeprom,
+       .get_eeprom_len = smc_ethtool_geteeprom_len,
+       .get_eeprom     = smc_ethtool_geteeprom,
+       .set_eeprom     = smc_ethtool_seteeprom,
+};
+
+static const struct net_device_ops smc_netdev_ops = {
+       .ndo_open               = smc_open,
+       .ndo_stop               = smc_close,
+       .ndo_start_xmit         = smc_hard_start_xmit,
+       .ndo_tx_timeout         = smc_timeout,
+       .ndo_set_multicast_list = smc_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = smc_poll_controller,
+#endif
 };
 
 /*
@@ -1870,16 +1995,9 @@ static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
        /* Fill in the fields of the device structure with ethernet values. */
        ether_setup(dev);
 
-       dev->open = smc_open;
-       dev->stop = smc_close;
-       dev->hard_start_xmit = smc_hard_start_xmit;
-       dev->tx_timeout = smc_timeout;
        dev->watchdog_timeo = msecs_to_jiffies(watchdog);
-       dev->set_multicast_list = smc_set_multicast_list;
+       dev->netdev_ops = &smc_netdev_ops;
        dev->ethtool_ops = &smc_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = smc_poll_controller;
-#endif
 
        tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev);
        INIT_WORK(&lp->phy_configure, smc_phy_configure);