1 /* 2 * drivers/net/phy/lxt.c 3 * 4 * Driver for Intel LXT PHYs 5 * 6 * Author: Andy Fleming 7 * 8 * Copyright (c) 2004 Freescale Semiconductor, Inc. 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 #include <linux/kernel.h> 17 #include <linux/string.h> 18 #include <linux/errno.h> 19 #include <linux/unistd.h> 20 #include <linux/slab.h> 21 #include <linux/interrupt.h> 22 #include <linux/init.h> 23 #include <linux/delay.h> 24 #include <linux/netdevice.h> 25 #include <linux/etherdevice.h> 26 #include <linux/skbuff.h> 27 #include <linux/spinlock.h> 28 #include <linux/mm.h> 29 #include <linux/module.h> 30 #include <linux/mii.h> 31 #include <linux/ethtool.h> 32 #include <linux/phy.h> 33 34 #include <asm/io.h> 35 #include <asm/irq.h> 36 #include <asm/uaccess.h> 37 38 /* The Level one LXT970 is used by many boards */ 39 40 #define MII_LXT970_IER 17 /* Interrupt Enable Register */ 41 42 #define MII_LXT970_IER_IEN 0x0002 43 44 #define MII_LXT970_ISR 18 /* Interrupt Status Register */ 45 46 #define MII_LXT970_CONFIG 19 /* Configuration Register */ 47 48 /* ------------------------------------------------------------------------- */ 49 /* The Level one LXT971 is used on some of my custom boards */ 50 51 /* register definitions for the 971 */ 52 #define MII_LXT971_IER 18 /* Interrupt Enable Register */ 53 #define MII_LXT971_IER_IEN 0x00f2 54 55 #define MII_LXT971_ISR 19 /* Interrupt Status Register */ 56 57 58 MODULE_DESCRIPTION("Intel LXT PHY driver"); 59 MODULE_AUTHOR("Andy Fleming"); 60 MODULE_LICENSE("GPL"); 61 62 static int lxt970_ack_interrupt(struct phy_device *phydev) 63 { 64 int err; 65 66 err = phy_read(phydev, MII_BMSR); 67 68 if (err < 0) 69 return err; 70 71 err = phy_read(phydev, MII_LXT970_ISR); 72 73 if (err < 0) 74 return err; 75 76 return 0; 77 } 78 79 static int lxt970_config_intr(struct phy_device *phydev) 80 { 81 int err; 82 83 if(phydev->interrupts == PHY_INTERRUPT_ENABLED) 84 err = phy_write(phydev, MII_LXT970_IER, MII_LXT970_IER_IEN); 85 else 86 err = phy_write(phydev, MII_LXT970_IER, 0); 87 88 return err; 89 } 90 91 static int lxt970_config_init(struct phy_device *phydev) 92 { 93 int err; 94 95 err = phy_write(phydev, MII_LXT970_CONFIG, 0); 96 97 return err; 98 } 99 100 101 static int lxt971_ack_interrupt(struct phy_device *phydev) 102 { 103 int err = phy_read(phydev, MII_LXT971_ISR); 104 105 if (err < 0) 106 return err; 107 108 return 0; 109 } 110 111 static int lxt971_config_intr(struct phy_device *phydev) 112 { 113 int err; 114 115 if(phydev->interrupts == PHY_INTERRUPT_ENABLED) 116 err = phy_write(phydev, MII_LXT971_IER, MII_LXT971_IER_IEN); 117 else 118 err = phy_write(phydev, MII_LXT971_IER, 0); 119 120 return err; 121 } 122 123 static struct phy_driver lxt970_driver = { 124 .phy_id = 0x78100000, 125 .name = "LXT970", 126 .phy_id_mask = 0xfffffff0, 127 .features = PHY_BASIC_FEATURES, 128 .flags = PHY_HAS_INTERRUPT, 129 .config_init = lxt970_config_init, 130 .config_aneg = genphy_config_aneg, 131 .read_status = genphy_read_status, 132 .ack_interrupt = lxt970_ack_interrupt, 133 .config_intr = lxt970_config_intr, 134 .driver = { .owner = THIS_MODULE,}, 135 }; 136 137 static struct phy_driver lxt971_driver = { 138 .phy_id = 0x001378e0, 139 .name = "LXT971", 140 .phy_id_mask = 0xfffffff0, 141 .features = PHY_BASIC_FEATURES, 142 .flags = PHY_HAS_INTERRUPT, 143 .config_aneg = genphy_config_aneg, 144 .read_status = genphy_read_status, 145 .ack_interrupt = lxt971_ack_interrupt, 146 .config_intr = lxt971_config_intr, 147 .driver = { .owner = THIS_MODULE,}, 148 }; 149 150 static int __init lxt_init(void) 151 { 152 int ret; 153 154 ret = phy_driver_register(&lxt970_driver); 155 if (ret) 156 goto err1; 157 158 ret = phy_driver_register(&lxt971_driver); 159 if (ret) 160 goto err2; 161 return 0; 162 163 err2: 164 phy_driver_unregister(&lxt970_driver); 165 err1: 166 return ret; 167 } 168 169 static void __exit lxt_exit(void) 170 { 171 phy_driver_unregister(&lxt970_driver); 172 phy_driver_unregister(&lxt971_driver); 173 } 174 175 module_init(lxt_init); 176 module_exit(lxt_exit); 177