This is a simple port of AMD AM79C874 PHY from old fec driver (arch/ppc/8xx_io) to PHY layer, previously sent to linuxppc-embedded mailing list for review. I don't have an AM79C874 based nic, so this email is also a request for testing :)
-- Aristeu
Index: testing/drivers/net/phy/Kconfig =================================================================== --- testing.orig/drivers/net/phy/Kconfig 2005-11-25 15:26:38.000000000 -0200 +++ testing/drivers/net/phy/Kconfig 2005-11-25 15:28:55.000000000 -0200 @@ -53,5 +53,11 @@ ---help--- Currently supports the cis8204 +config AMD_PHY + tristate "Drivers for the AMD PHYs" + depends on PHYLIB + ---help--- + Currenty supports AM79C874 + endmenu Index: testing/drivers/net/phy/Makefile =================================================================== --- testing.orig/drivers/net/phy/Makefile 2005-11-25 15:26:38.000000000 -0200 +++ testing/drivers/net/phy/Makefile 2005-11-25 15:26:56.000000000 -0200 @@ -8,3 +8,5 @@ obj-$(CONFIG_CICADA_PHY) += cicada.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o +obj-$(CONFIG_AMD_PHY) += amd.o + Index: testing/drivers/net/phy/amd.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ testing/drivers/net/phy/amd.c 2005-11-28 11:39:34.000000000 -0200 @@ -0,0 +1,71 @@ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/phy.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/uaccess.h> + +#define MII_AM79C874_MFR 16 /* Miscellaneous Features Register */ +#define MII_AM79C874_ICSR 17 /* Interrupt Control/Status Register */ +#define MII_AM79C874_DR 18 /* Diagnostic Register */ +#define MII_AM79C874_PMLR 19 /* Power Management & Loopback Register */ +#define MII_AM79C874_MCR 21 /* Mode Control Register */ +#define MII_AM79C874_DC 23 /* Disconnect Counter */ +#define MII_AM79C874_REC 24 /* Receiver Error Counter */ + +static int am79c874_ack_interrupt(struct phy_device *phy) +{ + int err; + + err = phy_read(phy, MII_AM79C874_ICSR); + + if (err < 0) + return err; + return 0; +} + +static int am79c874_config_intr(struct phy_device *phy) +{ + int err; + + if (phy->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phy, MII_AM79C874_ICSR, 0xff00); + else + err = phy_write(phy, MII_AM79C874_ICSR, 0); + + if (err < 0) + return err; + + return 0; +} + +static struct phy_driver am79c874 = { + .phy_id = 0x00022561, + .name = "AM79C874", + .phy_id_mask = 0x0fffffff, + .features = PHY_BASIC_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = am79c874_ack_interrupt, + .config_intr = am79c874_config_intr, + .driver = { .owner = THIS_MODULE,}, +}; + +static __init int am79c874_init(void) +{ + return phy_driver_register(&am79c874); +} + +static __exit void am79c874_exit(void) +{ + phy_driver_unregister(&am79c874); +} +module_init(am79c874_init); +module_exit(am79c874_exit); +