1 /* 2 * drivers/net/phy/et1011c.c 3 * 4 * Driver for LSI ET1011C PHYs 5 * 6 * Author: Chaithrika U S 7 * 8 * Copyright (c) 2008 Texas Instruments 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 #include <linux/io.h> 34 #include <linux/uaccess.h> 35 #include <asm/irq.h> 36 37 #define ET1011C_STATUS_REG (0x1A) 38 #define ET1011C_CONFIG_REG (0x16) 39 #define ET1011C_SPEED_MASK (0x0300) 40 #define ET1011C_GIGABIT_SPEED (0x0200) 41 #define ET1011C_TX_FIFO_MASK (0x3000) 42 #define ET1011C_TX_FIFO_DEPTH_8 (0x0000) 43 #define ET1011C_TX_FIFO_DEPTH_16 (0x1000) 44 #define ET1011C_INTERFACE_MASK (0x0007) 45 #define ET1011C_GMII_INTERFACE (0x0002) 46 #define ET1011C_SYS_CLK_EN (0x01 << 4) 47 48 49 MODULE_DESCRIPTION("LSI ET1011C PHY driver"); 50 MODULE_AUTHOR("Chaithrika U S"); 51 MODULE_LICENSE("GPL"); 52 53 static int et1011c_config_aneg(struct phy_device *phydev) 54 { 55 int ctl = 0; 56 ctl = phy_read(phydev, MII_BMCR); 57 if (ctl < 0) 58 return ctl; 59 ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | 60 BMCR_ANENABLE); 61 /* First clear the PHY */ 62 phy_write(phydev, MII_BMCR, ctl | BMCR_RESET); 63 64 return genphy_config_aneg(phydev); 65 } 66 67 static int et1011c_read_status(struct phy_device *phydev) 68 { 69 int ret; 70 u32 val; 71 static int speed; 72 ret = genphy_read_status(phydev); 73 74 if (speed != phydev->speed) { 75 speed = phydev->speed; 76 val = phy_read(phydev, ET1011C_STATUS_REG); 77 if ((val & ET1011C_SPEED_MASK) == 78 ET1011C_GIGABIT_SPEED) { 79 val = phy_read(phydev, ET1011C_CONFIG_REG); 80 val &= ~ET1011C_TX_FIFO_MASK; 81 phy_write(phydev, ET1011C_CONFIG_REG, val\ 82 | ET1011C_GMII_INTERFACE\ 83 | ET1011C_SYS_CLK_EN\ 84 | ET1011C_TX_FIFO_DEPTH_16); 85 86 } 87 } 88 return ret; 89 } 90 91 static struct phy_driver et1011c_driver = { 92 .phy_id = 0x0282f014, 93 .name = "ET1011C", 94 .phy_id_mask = 0xfffffff0, 95 .features = (PHY_BASIC_FEATURES | SUPPORTED_1000baseT_Full), 96 .flags = PHY_POLL, 97 .config_aneg = et1011c_config_aneg, 98 .read_status = et1011c_read_status, 99 .driver = { .owner = THIS_MODULE,}, 100 }; 101 102 static int __init et1011c_init(void) 103 { 104 return phy_driver_register(&et1011c_driver); 105 } 106 107 static void __exit et1011c_exit(void) 108 { 109 phy_driver_unregister(&et1011c_driver); 110 } 111 112 module_init(et1011c_init); 113 module_exit(et1011c_exit); 114