#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
+#include <linux/eeprom_93cx6.h>
#include <net/ax88796.h>
#define __ei_open ax_ei_open
#define __ei_close ax_ei_close
#define __ei_poll ax_ei_poll
+#define __ei_start_xmit ax_ei_start_xmit
#define __ei_tx_timeout ax_ei_tx_timeout
+#define __ei_get_stats ax_ei_get_stats
+#define __ei_set_multicast_list ax_ei_set_multicast_list
#define __ei_interrupt ax_ei_interrupt
#define ____alloc_ei_netdev ax__alloc_ei_netdev
#define __NS8390_init ax_NS8390_init
unsigned char running;
unsigned char resume_open;
+ unsigned int irqflags;
u32 reg_offsets[0x20];
};
static void ax_reset_8390(struct net_device *dev)
{
struct ei_device *ei_local = netdev_priv(dev);
+ struct ax_device *ax = to_ax_dev(dev);
unsigned long reset_start_time = jiffies;
void __iomem *addr = (void __iomem *)dev->base_addr;
if (ei_debug > 1)
- printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+ dev_dbg(&ax->dev->dev, "resetting the 8390 t=%ld\n", jiffies);
ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
/* This check _should_not_ be necessary, omit eventually. */
while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
if (jiffies - reset_start_time > 2*HZ/100) {
- printk(KERN_WARNING "%s: %s did not complete.\n",
- __FUNCTION__, dev->name);
+ dev_warn(&ax->dev->dev, "%s: %s did not complete.\n",
+ __func__, dev->name);
break;
}
}
int ring_page)
{
struct ei_device *ei_local = netdev_priv(dev);
+ struct ax_device *ax = to_ax_dev(dev);
void __iomem *nic_base = ei_local->mem;
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
- printk(KERN_EMERG "%s: DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n",
- dev->name, __FUNCTION__,
- ei_status.dmaing, ei_status.irqlock);
+ dev_err(&ax->dev->dev, "%s: DMAing conflict in %s "
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, __func__,
+ ei_status.dmaing, ei_status.irqlock);
return;
}
struct sk_buff *skb, int ring_offset)
{
struct ei_device *ei_local = netdev_priv(dev);
+ struct ax_device *ax = to_ax_dev(dev);
void __iomem *nic_base = ei_local->mem;
char *buf = skb->data;
if (ei_status.dmaing) {
- printk(KERN_EMERG "%s: DMAing conflict in ax_block_input "
+ dev_err(&ax->dev->dev,
+ "%s: DMAing conflict in %s "
"[DMAstat:%d][irqlock:%d].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
+ dev->name, __func__,
+ ei_status.dmaing, ei_status.irqlock);
return;
}
const unsigned char *buf, const int start_page)
{
struct ei_device *ei_local = netdev_priv(dev);
+ struct ax_device *ax = to_ax_dev(dev);
void __iomem *nic_base = ei_local->mem;
unsigned long dma_start;
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
- printk(KERN_EMERG "%s: DMAing conflict in %s."
+ dev_err(&ax->dev->dev, "%s: DMAing conflict in %s."
"[DMAstat:%d][irqlock:%d]\n",
- dev->name, __FUNCTION__,
+ dev->name, __func__,
ei_status.dmaing, ei_status.irqlock);
return;
}
while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
- printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+ dev_warn(&ax->dev->dev,
+ "%s: timeout waiting for Tx RDC.\n", dev->name);
ax_reset_8390(dev);
ax_NS8390_init(dev,1);
break;
{
if (phy_debug)
pr_debug("%s: dev %p, %04x, %04x, %d\n",
- __FUNCTION__, dev, phy_addr, reg, opc);
+ __func__, dev, phy_addr, reg, opc);
ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */
ax_mii_ei_outbits(dev, 1, 2); /* frame-start */
spin_unlock_irqrestore(&ei_local->page_lock, flags);
if (phy_debug)
- pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__,
+ pr_debug("%s: %04x.%04x => read %04x\n", __func__,
phy_addr, reg, result);
return result;
ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
{
struct ei_device *ei = (struct ei_device *) netdev_priv(dev);
+ struct ax_device *ax = to_ax_dev(dev);
unsigned long flags;
- printk(KERN_DEBUG "%s: %p, %04x, %04x %04x\n",
- __FUNCTION__, dev, phy_addr, reg, value);
+ dev_dbg(&ax->dev->dev, "%s: %p, %04x, %04x %04x\n",
+ __func__, dev, phy_addr, reg, value);
spin_lock_irqsave(&ei->page_lock, flags);
struct ei_device *ei_local = netdev_priv(dev);
int ret;
- dev_dbg(ax->dev, "%s: open\n", dev->name);
+ dev_dbg(&ax->dev->dev, "%s: open\n", dev->name);
- ret = request_irq(dev->irq, ax_ei_interrupt, 0, dev->name, dev);
+ ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
+ dev->name, dev);
if (ret)
return ret;
struct ax_device *ax = to_ax_dev(dev);
struct ei_device *ei_local = netdev_priv(dev);
- dev_dbg(ax->dev, "%s: close\n", dev->name);
+ dev_dbg(&ax->dev->dev, "%s: close\n", dev->name);
/* turn the phy off */
spin_lock_irqsave(&ax->mii_lock, flags);
mii_ethtool_gset(&ax->mii, cmd);
- spin_lock_irqsave(&ax->mii_lock, flags);
+ spin_unlock_irqrestore(&ax->mii_lock, flags);
return 0;
}
spin_lock_irqsave(&ax->mii_lock, flags);
rc = mii_ethtool_sset(&ax->mii, cmd);
- spin_lock_irqsave(&ax->mii_lock, flags);
+ spin_unlock_irqrestore(&ax->mii_lock, flags);
return rc;
}
.set_settings = ax_set_settings,
.nway_reset = ax_nway_reset,
.get_link = ax_get_link,
- .get_perm_addr = ethtool_op_get_perm_addr,
+};
+
+#ifdef CONFIG_AX88796_93CX6
+static void ax_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+ struct ei_device *ei_local = eeprom->data;
+ u8 reg = ei_inb(ei_local->mem + AX_MEMR);
+
+ eeprom->reg_data_in = reg & AX_MEMR_EEI;
+ eeprom->reg_data_out = reg & AX_MEMR_EEO; /* Input pin */
+ eeprom->reg_data_clock = reg & AX_MEMR_EECLK;
+ eeprom->reg_chip_select = reg & AX_MEMR_EECS;
+}
+
+static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+ struct ei_device *ei_local = eeprom->data;
+ u8 reg = ei_inb(ei_local->mem + AX_MEMR);
+
+ reg &= ~(AX_MEMR_EEI | AX_MEMR_EECLK | AX_MEMR_EECS);
+
+ if (eeprom->reg_data_in)
+ reg |= AX_MEMR_EEI;
+ if (eeprom->reg_data_clock)
+ reg |= AX_MEMR_EECLK;
+ if (eeprom->reg_chip_select)
+ reg |= AX_MEMR_EECS;
+
+ ei_outb(reg, ei_local->mem + AX_MEMR);
+ udelay(10);
+}
+#endif
+
+static const struct net_device_ops ax_netdev_ops = {
+ .ndo_open = ax_open,
+ .ndo_stop = ax_close,
+ .ndo_do_ioctl = ax_ioctl,
+
+ .ndo_start_xmit = ax_ei_start_xmit,
+ .ndo_tx_timeout = ax_ei_tx_timeout,
+ .ndo_get_stats = ax_ei_get_stats,
+ .ndo_set_multicast_list = ax_ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ax_ei_poll,
+#endif
};
/* setup code */
memcpy(dev->dev_addr, SA_prom, 6);
}
+#ifdef CONFIG_AX88796_93CX6
+ if (first_init && ax->plat->flags & AXFLG_HAS_93CX6) {
+ unsigned char mac_addr[6];
+ struct eeprom_93cx6 eeprom;
+
+ eeprom.data = ei_local;
+ eeprom.register_read = ax_eeprom_register_read;
+ eeprom.register_write = ax_eeprom_register_write;
+ eeprom.width = PCI_EEPROM_WIDTH_93C56;
+
+ eeprom_93cx6_multiread(&eeprom, 0,
+ (__le16 __force *)mac_addr,
+ sizeof(mac_addr) >> 1);
+
+ memcpy(dev->dev_addr, mac_addr, 6);
+ }
+#endif
if (ax->plat->wordlength == 2) {
/* We must set the 8390 for word mode. */
ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
/* load the mac-address from the device if this is the
* first time we've initialised */
- if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) {
- ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
- ei_local->mem + E8390_CMD); /* 0x61 */
+ if (first_init) {
+ if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
+ ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+ ei_local->mem + E8390_CMD); /* 0x61 */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ dev->dev_addr[i] =
+ ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
+ }
- for (i = 0 ; i < ETHER_ADDR_LEN ; i++)
- dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
+ if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
+ ax->plat->mac_addr)
+ memcpy(dev->dev_addr, ax->plat->mac_addr,
+ ETHER_ADDR_LEN);
}
ax_reset_8390(dev);
ei_status.get_8390_hdr = &ax_get_8390_hdr;
ei_status.priv = 0;
- dev->open = ax_open;
- dev->stop = ax_close;
- dev->do_ioctl = ax_ioctl;
+ dev->netdev_ops = &ax_netdev_ops;
dev->ethtool_ops = &ax_ethtool_ops;
ax->msg_enable = NETIF_MSG_LINK;
ax->mii.mdio_write = ax_phy_write;
ax->mii.dev = dev;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ax_ei_poll;
-#endif
ax_NS8390_init(dev, 0);
- if (first_init) {
- printk("AX88796: %dbit, irq %d, %lx, MAC: ",
- ei_status.word16 ? 16:8, dev->irq, dev->base_addr);
-
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- printk("%2.2x%c", dev->dev_addr[i],
- (i < (ETHER_ADDR_LEN-1) ? ':' : ' '));
-
- printk("\n");
- }
+ if (first_init)
+ dev_info(&ax->dev->dev, "%dbit, irq %d, %lx, MAC: %pM\n",
+ ei_status.word16 ? 16:8, dev->irq, dev->base_addr,
+ dev->dev_addr);
ret = register_netdev(dev);
if (ret)
struct ax_device *ax;
struct resource *res;
size_t size;
- int ret;
+ int ret = 0;
dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
if (dev == NULL)
/* find the platform resources */
- dev->irq = platform_get_irq(pdev, 0);
- if (dev->irq < 0) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res == NULL) {
dev_err(&pdev->dev, "no IRQ specified\n");
- ret = -ENXIO;
goto exit_mem;
}
+ dev->irq = res->start;
+ ax->irqflags = res->flags & IRQF_TRIGGER_MASK;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "no MEM specified\n");
}
ei_status.mem = ioremap(res->start, size);
- dev->base_addr = (long)ei_status.mem;
+ dev->base_addr = (unsigned long)ei_status.mem;
if (ei_status.mem == NULL) {
- dev_err(&pdev->dev, "Cannot ioremap area (%08zx,%08zx)\n",
- res->start, res->end);
+ dev_err(&pdev->dev, "Cannot ioremap area (%08llx,%08llx)\n",
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
ret = -ENXIO;
goto exit_req;
ax->map2 = ioremap(res->start, size);
if (ax->map2 == NULL) {
- dev_err(&pdev->dev, "cannot map reset register");
+ dev_err(&pdev->dev, "cannot map reset register\n");
ret = -ENXIO;
goto exit_mem2;
}
MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ax88796");