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/interrupt.h> 21 #include <linux/init.h> 22 #include <linux/delay.h> 23 #include <linux/netdevice.h> 24 #include <linux/etherdevice.h> 25 #include <linux/skbuff.h> 26 #include <linux/spinlock.h> 27 #include <linux/mm.h> 28 #include <linux/module.h> 29 #include <linux/mii.h> 30 #include <linux/ethtool.h> 31 #include <linux/phy.h> 32 #include <linux/io.h> 33 #include <linux/uaccess.h> 34 #include <asm/irq.h> 35 36 #define ET1011C_STATUS_REG (0x1A) 37 #define ET1011C_CONFIG_REG (0x16) 38 #define ET1011C_SPEED_MASK (0x0300) 39 #define ET1011C_GIGABIT_SPEED (0x0200) 40 #define ET1011C_TX_FIFO_MASK (0x3000) 41 #define ET1011C_TX_FIFO_DEPTH_8 (0x0000) 42 #define ET1011C_TX_FIFO_DEPTH_16 (0x1000) 43 #define ET1011C_INTERFACE_MASK (0x0007) 44 #define ET1011C_GMII_INTERFACE (0x0002) 45 #define ET1011C_SYS_CLK_EN (0x01 << 4) 46 47 48 MODULE_DESCRIPTION("LSI ET1011C PHY driver"); 49 MODULE_AUTHOR("Chaithrika U S"); 50 MODULE_LICENSE("GPL"); 51 52 static int et1011c_config_aneg(struct phy_device *phydev) 53 { 54 int ctl = 0; 55 ctl = phy_read(phydev, MII_BMCR); 56 if (ctl < 0) 57 return ctl; 58 ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | 59 BMCR_ANENABLE); 60 /* First clear the PHY */ 61 phy_write(phydev, MII_BMCR, ctl | BMCR_RESET); 62 63 return genphy_config_aneg(phydev); 64 } 65 66 static int et1011c_read_status(struct phy_device *phydev) 67 { 68 int ret; 69 u32 val; 70 static int speed; 71 ret = genphy_read_status(phydev); 72 73 if (speed != phydev->speed) { 74 speed = phydev->speed; 75 val = phy_read(phydev, ET1011C_STATUS_REG); 76 if ((val & ET1011C_SPEED_MASK) == 77 ET1011C_GIGABIT_SPEED) { 78 val = phy_read(phydev, ET1011C_CONFIG_REG); 79 val &= ~ET1011C_TX_FIFO_MASK; 80 phy_write(phydev, ET1011C_CONFIG_REG, val\ 81 | ET1011C_GMII_INTERFACE\ 82 | ET1011C_SYS_CLK_EN\ 83 | ET1011C_TX_FIFO_DEPTH_16); 84 85 } 86 } 87 return ret; 88 } 89 90 static struct phy_driver et1011c_driver = { 91 .phy_id = 0x0282f014, 92 .name = "ET1011C", 93 .phy_id_mask = 0xfffffff0, 94 .features = (PHY_BASIC_FEATURES | SUPPORTED_1000baseT_Full), 95 .flags = PHY_POLL, 96 .config_aneg = et1011c_config_aneg, 97 .read_status = et1011c_read_status, 98 .driver = { .owner = THIS_MODULE,}, 99 }; 100 101 static int __init et1011c_init(void) 102 { 103 return phy_driver_register(&et1011c_driver); 104 } 105 106 static void __exit et1011c_exit(void) 107 { 108 phy_driver_unregister(&et1011c_driver); 109 } 110 111 module_init(et1011c_init); 112 module_exit(et1011c_exit); 113 114 static struct mdio_device_id __maybe_unused et1011c_tbl[] = { 115 { 0x0282f014, 0xfffffff0 }, 116 { } 117 }; 118 119 MODULE_DEVICE_TABLE(mdio, et1011c_tbl); 120