Skip to content

Commit bda73d4

Browse files
committed
Merge branch 'Amiga-xsurf100'
Michael Schmitz says: ==================== New network driver for Amiga X-Surf 100 (m68k) [This is a resend of my v3 series which was based on the wrong version and tree. Only substantial change is to Asix AX99796B PHY driver.] This patch series adds support for the Individual Computers X-Surf 100 network card for m68k Amiga, a network adapter based on the AX88796 chip set. The driver was originally written for kernel version 3.19 by Michael Karcher (see CC:), and adapted to 4.16+ for submission to netdev by me. Questions regarding motivation for some of the changes are probably best directed at Michael Karcher. The driver has been tested by Adrian <glaubitz@physik.fu-berlin.de> who will send his Tested-by tag separately. A few changes to the ax88796 driver were required: - to read the MAC address, some setup of the ax99796 chip must be done, - attach to the MII bus only on device open to allow module unloading, - allow to supersede ax_block_input/ax_block_output by card-specific optimized code, - use an optional interrupt status callback to allow easier sharing of the card interrupt, - set IRQF_SHARED if platform IRQ resource is marked shareable The Asix Electronix PHY used on the X-Surf 100 is buggy, and causes the software reset to hang if the previous command sent to the PHY was also a soft reset. This bug requires addition of a PHY driver for Asix PHYs to provide a fixed .soft_reset function, included in this series. Some additional cleanup: - do not attempt to free IRQ in ax_remove (complements 82533ad), - clear platform drvdata on probe fail and module remove. Changes since v1: Raised in review by Andrew Lunn: - move MII code around to avoid need for forward declaration, - combine patches 2 and 7 to add cleanup in error path Changes since v2: - corrected authorship attribution to Michael Karcher Suggested by Geert Uytterhoeven: - use ei_local->reset_8390() instead of duplicating ax_reset_8390(), - use %pR to format struct resource pointers, - assign pdev and xs100 pointers in declaration, - don't split error messages, - change Kconfig logic to only require XSURF100 set on Amiga Suggested by Andrew Lunn: - add COMPILE_TEST to ax88796 Kconfig options, - use new Asix PHY driver for X-Surf 100 Suggested by Andrew Lunn/Finn Thain: - declare struct sk_buff in ax88796.h, - correct whitespace error in ax88796.h Changes since v3: - various checkpatch cleanup Andrew Lunn: - don't duplicate genphy_soft_reset in Asix PHY driver, just call genphy_soft_reset after writing zero to control register ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 32e4377 + 861928f commit bda73d4

File tree

8 files changed

+617
-95
lines changed

8 files changed

+617
-95
lines changed

drivers/net/ethernet/8390/Kconfig

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ config PCMCIA_AXNET
2929
called axnet_cs. If unsure, say N.
3030

3131
config AX88796
32-
tristate "ASIX AX88796 NE2000 clone support"
33-
depends on (ARM || MIPS || SUPERH)
32+
tristate "ASIX AX88796 NE2000 clone support" if !ZORRO
33+
depends on (ARM || MIPS || SUPERH || ZORRO || COMPILE_TEST)
3434
select CRC32
3535
select PHYLIB
3636
select MDIO_BITBANG
@@ -45,6 +45,19 @@ config AX88796_93CX6
4545
---help---
4646
Select this if your platform comes with an external 93CX6 eeprom.
4747

48+
config XSURF100
49+
tristate "Amiga XSurf 100 AX88796/NE2000 clone support"
50+
depends on ZORRO
51+
select AX88796
52+
select ASIX_PHY
53+
help
54+
This driver is for the Individual Computers X-Surf 100 Ethernet
55+
card (based on the Asix AX88796 chip). If you have such a card,
56+
say Y. Otherwise, say N.
57+
58+
To compile this driver as a module, choose M here: the module
59+
will be called xsurf100.
60+
4861
config HYDRA
4962
tristate "Hydra support"
5063
depends on ZORRO

drivers/net/ethernet/8390/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
1616
obj-$(CONFIG_STNIC) += stnic.o 8390.o
1717
obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
1818
obj-$(CONFIG_WD80x3) += wd.o 8390.o
19+
obj-$(CONFIG_XSURF100) += xsurf100.o
1920
obj-$(CONFIG_ZORRO8390) += zorro8390.o

drivers/net/ethernet/8390/ax88796.c

Lines changed: 135 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,21 @@ static void ax_reset_8390(struct net_device *dev)
163163
ei_outb(ENISR_RESET, addr + EN0_ISR); /* Ack intr. */
164164
}
165165

166+
/* Wrapper for __ei_interrupt for platforms that have a platform-specific
167+
* way to find out whether the interrupt request might be caused by
168+
* the ax88796 chip.
169+
*/
170+
static irqreturn_t ax_ei_interrupt_filtered(int irq, void *dev_id)
171+
{
172+
struct net_device *dev = dev_id;
173+
struct ax_device *ax = to_ax_dev(dev);
174+
struct platform_device *pdev = to_platform_device(dev->dev.parent);
175+
176+
if (!ax->plat->check_irq(pdev))
177+
return IRQ_NONE;
178+
179+
return ax_ei_interrupt(irq, dev_id);
180+
}
166181

167182
static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
168183
int ring_page)
@@ -387,15 +402,107 @@ static void ax_phy_switch(struct net_device *dev, int on)
387402
ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17));
388403
}
389404

405+
static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
406+
{
407+
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
408+
409+
if (level)
410+
ax->reg_memr |= AX_MEMR_MDC;
411+
else
412+
ax->reg_memr &= ~AX_MEMR_MDC;
413+
414+
ei_outb(ax->reg_memr, ax->addr_memr);
415+
}
416+
417+
static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
418+
{
419+
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
420+
421+
if (output)
422+
ax->reg_memr &= ~AX_MEMR_MDIR;
423+
else
424+
ax->reg_memr |= AX_MEMR_MDIR;
425+
426+
ei_outb(ax->reg_memr, ax->addr_memr);
427+
}
428+
429+
static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
430+
{
431+
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
432+
433+
if (value)
434+
ax->reg_memr |= AX_MEMR_MDO;
435+
else
436+
ax->reg_memr &= ~AX_MEMR_MDO;
437+
438+
ei_outb(ax->reg_memr, ax->addr_memr);
439+
}
440+
441+
static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
442+
{
443+
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
444+
int reg_memr = ei_inb(ax->addr_memr);
445+
446+
return reg_memr & AX_MEMR_MDI ? 1 : 0;
447+
}
448+
449+
static const struct mdiobb_ops bb_ops = {
450+
.owner = THIS_MODULE,
451+
.set_mdc = ax_bb_mdc,
452+
.set_mdio_dir = ax_bb_dir,
453+
.set_mdio_data = ax_bb_set_data,
454+
.get_mdio_data = ax_bb_get_data,
455+
};
456+
457+
static int ax_mii_init(struct net_device *dev)
458+
{
459+
struct platform_device *pdev = to_platform_device(dev->dev.parent);
460+
struct ei_device *ei_local = netdev_priv(dev);
461+
struct ax_device *ax = to_ax_dev(dev);
462+
int err;
463+
464+
ax->bb_ctrl.ops = &bb_ops;
465+
ax->addr_memr = ei_local->mem + AX_MEMR;
466+
ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
467+
if (!ax->mii_bus) {
468+
err = -ENOMEM;
469+
goto out;
470+
}
471+
472+
ax->mii_bus->name = "ax88796_mii_bus";
473+
ax->mii_bus->parent = dev->dev.parent;
474+
snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
475+
pdev->name, pdev->id);
476+
477+
err = mdiobus_register(ax->mii_bus);
478+
if (err)
479+
goto out_free_mdio_bitbang;
480+
481+
return 0;
482+
483+
out_free_mdio_bitbang:
484+
free_mdio_bitbang(ax->mii_bus);
485+
out:
486+
return err;
487+
}
488+
390489
static int ax_open(struct net_device *dev)
391490
{
392491
struct ax_device *ax = to_ax_dev(dev);
393492
int ret;
394493

395494
netdev_dbg(dev, "open\n");
396495

397-
ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
398-
dev->name, dev);
496+
ret = ax_mii_init(dev);
497+
if (ret)
498+
goto failed_mii;
499+
500+
if (ax->plat->check_irq)
501+
ret = request_irq(dev->irq, ax_ei_interrupt_filtered,
502+
ax->irqflags, dev->name, dev);
503+
else
504+
ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
505+
dev->name, dev);
399506
if (ret)
400507
goto failed_request_irq;
401508

@@ -421,6 +528,10 @@ static int ax_open(struct net_device *dev)
421528
ax_phy_switch(dev, 0);
422529
free_irq(dev->irq, dev);
423530
failed_request_irq:
531+
/* unregister mdiobus */
532+
mdiobus_unregister(ax->mii_bus);
533+
free_mdio_bitbang(ax->mii_bus);
534+
failed_mii:
424535
return ret;
425536
}
426537

@@ -440,6 +551,9 @@ static int ax_close(struct net_device *dev)
440551
phy_disconnect(dev->phydev);
441552

442553
free_irq(dev->irq, dev);
554+
555+
mdiobus_unregister(ax->mii_bus);
556+
free_mdio_bitbang(ax->mii_bus);
443557
return 0;
444558
}
445559

@@ -539,92 +653,8 @@ static const struct net_device_ops ax_netdev_ops = {
539653
#endif
540654
};
541655

542-
static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
543-
{
544-
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
545-
546-
if (level)
547-
ax->reg_memr |= AX_MEMR_MDC;
548-
else
549-
ax->reg_memr &= ~AX_MEMR_MDC;
550-
551-
ei_outb(ax->reg_memr, ax->addr_memr);
552-
}
553-
554-
static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
555-
{
556-
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
557-
558-
if (output)
559-
ax->reg_memr &= ~AX_MEMR_MDIR;
560-
else
561-
ax->reg_memr |= AX_MEMR_MDIR;
562-
563-
ei_outb(ax->reg_memr, ax->addr_memr);
564-
}
565-
566-
static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
567-
{
568-
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
569-
570-
if (value)
571-
ax->reg_memr |= AX_MEMR_MDO;
572-
else
573-
ax->reg_memr &= ~AX_MEMR_MDO;
574-
575-
ei_outb(ax->reg_memr, ax->addr_memr);
576-
}
577-
578-
static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
579-
{
580-
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
581-
int reg_memr = ei_inb(ax->addr_memr);
582-
583-
return reg_memr & AX_MEMR_MDI ? 1 : 0;
584-
}
585-
586-
static const struct mdiobb_ops bb_ops = {
587-
.owner = THIS_MODULE,
588-
.set_mdc = ax_bb_mdc,
589-
.set_mdio_dir = ax_bb_dir,
590-
.set_mdio_data = ax_bb_set_data,
591-
.get_mdio_data = ax_bb_get_data,
592-
};
593-
594656
/* setup code */
595657

596-
static int ax_mii_init(struct net_device *dev)
597-
{
598-
struct platform_device *pdev = to_platform_device(dev->dev.parent);
599-
struct ei_device *ei_local = netdev_priv(dev);
600-
struct ax_device *ax = to_ax_dev(dev);
601-
int err;
602-
603-
ax->bb_ctrl.ops = &bb_ops;
604-
ax->addr_memr = ei_local->mem + AX_MEMR;
605-
ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
606-
if (!ax->mii_bus) {
607-
err = -ENOMEM;
608-
goto out;
609-
}
610-
611-
ax->mii_bus->name = "ax88796_mii_bus";
612-
ax->mii_bus->parent = dev->dev.parent;
613-
snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
614-
pdev->name, pdev->id);
615-
616-
err = mdiobus_register(ax->mii_bus);
617-
if (err)
618-
goto out_free_mdio_bitbang;
619-
620-
return 0;
621-
622-
out_free_mdio_bitbang:
623-
free_mdio_bitbang(ax->mii_bus);
624-
out:
625-
return err;
626-
}
627-
628658
static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
629659
{
630660
void __iomem *ioaddr = ei_local->mem;
@@ -669,10 +699,16 @@ static int ax_init_dev(struct net_device *dev)
669699
if (ax->plat->flags & AXFLG_HAS_EEPROM) {
670700
unsigned char SA_prom[32];
671701

702+
ei_outb(6, ioaddr + EN0_RCNTLO);
703+
ei_outb(0, ioaddr + EN0_RCNTHI);
704+
ei_outb(0, ioaddr + EN0_RSARLO);
705+
ei_outb(0, ioaddr + EN0_RSARHI);
706+
ei_outb(E8390_RREAD + E8390_START, ioaddr + NE_CMD);
672707
for (i = 0; i < sizeof(SA_prom); i += 2) {
673708
SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
674709
SA_prom[i + 1] = ei_inb(ioaddr + NE_DATAPORT);
675710
}
711+
ei_outb(ENISR_RDC, ioaddr + EN0_ISR); /* Ack intr. */
676712

677713
if (ax->plat->wordlength == 2)
678714
for (i = 0; i < 16; i++)
@@ -741,18 +777,20 @@ static int ax_init_dev(struct net_device *dev)
741777
#endif
742778

743779
ei_local->reset_8390 = &ax_reset_8390;
744-
ei_local->block_input = &ax_block_input;
745-
ei_local->block_output = &ax_block_output;
780+
if (ax->plat->block_input)
781+
ei_local->block_input = ax->plat->block_input;
782+
else
783+
ei_local->block_input = &ax_block_input;
784+
if (ax->plat->block_output)
785+
ei_local->block_output = ax->plat->block_output;
786+
else
787+
ei_local->block_output = &ax_block_output;
746788
ei_local->get_8390_hdr = &ax_get_8390_hdr;
747789
ei_local->priv = 0;
748790

749791
dev->netdev_ops = &ax_netdev_ops;
750792
dev->ethtool_ops = &ax_ethtool_ops;
751793

752-
ret = ax_mii_init(dev);
753-
if (ret)
754-
goto err_out;
755-
756794
ax_NS8390_init(dev, 0);
757795

758796
ret = register_netdev(dev);
@@ -777,7 +815,6 @@ static int ax_remove(struct platform_device *pdev)
777815
struct resource *mem;
778816

779817
unregister_netdev(dev);
780-
free_irq(dev->irq, dev);
781818

782819
iounmap(ei_local->mem);
783820
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -789,6 +826,7 @@ static int ax_remove(struct platform_device *pdev)
789826
release_mem_region(mem->start, resource_size(mem));
790827
}
791828

829+
platform_set_drvdata(pdev, NULL);
792830
free_netdev(dev);
793831

794832
return 0;
@@ -835,6 +873,9 @@ static int ax_probe(struct platform_device *pdev)
835873
dev->irq = irq->start;
836874
ax->irqflags = irq->flags & IRQF_TRIGGER_MASK;
837875

876+
if (irq->flags & IORESOURCE_IRQ_SHAREABLE)
877+
ax->irqflags |= IRQF_SHARED;
878+
838879
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
839880
if (!mem) {
840881
dev_err(&pdev->dev, "no MEM specified\n");
@@ -919,6 +960,7 @@ static int ax_probe(struct platform_device *pdev)
919960
release_mem_region(mem->start, mem_size);
920961

921962
exit_mem:
963+
platform_set_drvdata(pdev, NULL);
922964
free_netdev(dev);
923965

924966
return ret;

0 commit comments

Comments
 (0)