Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.29-rc2 195 lines 5.0 kB view raw
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 * Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@smsc.com 16 * 17 */ 18 19#include <linux/kernel.h> 20#include <linux/module.h> 21#include <linux/mii.h> 22#include <linux/ethtool.h> 23#include <linux/phy.h> 24#include <linux/netdevice.h> 25 26#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */ 27#define MII_LAN83C185_IM 30 /* Interrupt Mask */ 28 29#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */ 30#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */ 31#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */ 32#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */ 33#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */ 34#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */ 35#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */ 36 37#define MII_LAN83C185_ISF_INT_ALL (0x0e) 38 39#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \ 40 (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4) 41 42 43static int smsc_phy_config_intr(struct phy_device *phydev) 44{ 45 int rc = phy_write (phydev, MII_LAN83C185_IM, 46 ((PHY_INTERRUPT_ENABLED == phydev->interrupts) 47 ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS 48 : 0)); 49 50 return rc < 0 ? rc : 0; 51} 52 53static int smsc_phy_ack_interrupt(struct phy_device *phydev) 54{ 55 int rc = phy_read (phydev, MII_LAN83C185_ISF); 56 57 return rc < 0 ? rc : 0; 58} 59 60static int smsc_phy_config_init(struct phy_device *phydev) 61{ 62 return smsc_phy_ack_interrupt (phydev); 63} 64 65 66static struct phy_driver lan83c185_driver = { 67 .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ 68 .phy_id_mask = 0xfffffff0, 69 .name = "SMSC LAN83C185", 70 71 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause 72 | SUPPORTED_Asym_Pause), 73 .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, 74 75 /* basic functions */ 76 .config_aneg = genphy_config_aneg, 77 .read_status = genphy_read_status, 78 .config_init = smsc_phy_config_init, 79 80 /* IRQ related */ 81 .ack_interrupt = smsc_phy_ack_interrupt, 82 .config_intr = smsc_phy_config_intr, 83 84 .driver = { .owner = THIS_MODULE, } 85}; 86 87static struct phy_driver lan8187_driver = { 88 .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */ 89 .phy_id_mask = 0xfffffff0, 90 .name = "SMSC LAN8187", 91 92 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause 93 | SUPPORTED_Asym_Pause), 94 .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, 95 96 /* basic functions */ 97 .config_aneg = genphy_config_aneg, 98 .read_status = genphy_read_status, 99 .config_init = smsc_phy_config_init, 100 101 /* IRQ related */ 102 .ack_interrupt = smsc_phy_ack_interrupt, 103 .config_intr = smsc_phy_config_intr, 104 105 .driver = { .owner = THIS_MODULE, } 106}; 107 108static struct phy_driver lan8700_driver = { 109 .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */ 110 .phy_id_mask = 0xfffffff0, 111 .name = "SMSC LAN8700", 112 113 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause 114 | SUPPORTED_Asym_Pause), 115 .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, 116 117 /* basic functions */ 118 .config_aneg = genphy_config_aneg, 119 .read_status = genphy_read_status, 120 .config_init = smsc_phy_config_init, 121 122 /* IRQ related */ 123 .ack_interrupt = smsc_phy_ack_interrupt, 124 .config_intr = smsc_phy_config_intr, 125 126 .driver = { .owner = THIS_MODULE, } 127}; 128 129static struct phy_driver lan911x_int_driver = { 130 .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */ 131 .phy_id_mask = 0xfffffff0, 132 .name = "SMSC LAN911x Internal PHY", 133 134 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause 135 | SUPPORTED_Asym_Pause), 136 .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, 137 138 /* basic functions */ 139 .config_aneg = genphy_config_aneg, 140 .read_status = genphy_read_status, 141 .config_init = smsc_phy_config_init, 142 143 /* IRQ related */ 144 .ack_interrupt = smsc_phy_ack_interrupt, 145 .config_intr = smsc_phy_config_intr, 146 147 .driver = { .owner = THIS_MODULE, } 148}; 149 150static int __init smsc_init(void) 151{ 152 int ret; 153 154 ret = phy_driver_register (&lan83c185_driver); 155 if (ret) 156 goto err1; 157 158 ret = phy_driver_register (&lan8187_driver); 159 if (ret) 160 goto err2; 161 162 ret = phy_driver_register (&lan8700_driver); 163 if (ret) 164 goto err3; 165 166 ret = phy_driver_register (&lan911x_int_driver); 167 if (ret) 168 goto err4; 169 170 return 0; 171 172err4: 173 phy_driver_unregister (&lan8700_driver); 174err3: 175 phy_driver_unregister (&lan8187_driver); 176err2: 177 phy_driver_unregister (&lan83c185_driver); 178err1: 179 return ret; 180} 181 182static void __exit smsc_exit(void) 183{ 184 phy_driver_unregister (&lan911x_int_driver); 185 phy_driver_unregister (&lan8700_driver); 186 phy_driver_unregister (&lan8187_driver); 187 phy_driver_unregister (&lan83c185_driver); 188} 189 190MODULE_DESCRIPTION("SMSC PHY driver"); 191MODULE_AUTHOR("Herbert Valerio Riedel"); 192MODULE_LICENSE("GPL"); 193 194module_init(smsc_init); 195module_exit(smsc_exit);