1 /* 2 * drivers/net/phy/smsc.c 3 * 4 * Driver for SMSC PHYs 5 * 6 * Author: Herbert Valerio Riedel 7 * 8 * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org> 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. 14 * 15 */ 16 17 #include <linux/config.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/mii.h> 21 #include <linux/ethtool.h> 22 #include <linux/phy.h> 23 #include <linux/netdevice.h> 24 25 #define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */ 26 #define MII_LAN83C185_IM 30 /* Interrupt Mask */ 27 28 #define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */ 29 #define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */ 30 #define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */ 31 #define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */ 32 #define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */ 33 #define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */ 34 #define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */ 35 36 #define MII_LAN83C185_ISF_INT_ALL (0x0e) 37 38 #define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \ 39 (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4) 40 41 42 static int lan83c185_config_intr(struct phy_device *phydev) 43 { 44 int rc = phy_write (phydev, MII_LAN83C185_IM, 45 ((PHY_INTERRUPT_ENABLED == phydev->interrupts) 46 ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS 47 : 0)); 48 49 return rc < 0 ? rc : 0; 50 } 51 52 static int lan83c185_ack_interrupt(struct phy_device *phydev) 53 { 54 int rc = phy_read (phydev, MII_LAN83C185_ISF); 55 56 return rc < 0 ? rc : 0; 57 } 58 59 static int lan83c185_config_init(struct phy_device *phydev) 60 { 61 return lan83c185_ack_interrupt (phydev); 62 } 63 64 65 static struct phy_driver lan83c185_driver = { 66 .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ 67 .phy_id_mask = 0xfffffff0, 68 .name = "SMSC LAN83C185", 69 70 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause 71 | SUPPORTED_Asym_Pause), 72 .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, 73 74 /* basic functions */ 75 .config_aneg = genphy_config_aneg, 76 .read_status = genphy_read_status, 77 .config_init = lan83c185_config_init, 78 79 /* IRQ related */ 80 .ack_interrupt = lan83c185_ack_interrupt, 81 .config_intr = lan83c185_config_intr, 82 83 .driver = { .owner = THIS_MODULE, } 84 }; 85 86 static int __init smsc_init(void) 87 { 88 return phy_driver_register (&lan83c185_driver); 89 } 90 91 static void __exit smsc_exit(void) 92 { 93 phy_driver_unregister (&lan83c185_driver); 94 } 95 96 MODULE_DESCRIPTION("SMSC PHY driver"); 97 MODULE_AUTHOR("Herbert Valerio Riedel"); 98 MODULE_LICENSE("GPL"); 99 100 module_init(smsc_init); 101 module_exit(smsc_exit); 102