1 /* 2 * Vitesse PHY drivers 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of 7 * the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 17 * MA 02111-1307 USA 18 * 19 * Copyright 2010-2011 Freescale Semiconductor, Inc. 20 * author Andy Fleming 21 * 22 */ 23 #include <miiphy.h> 24 25 /* Cicada Auxiliary Control/Status Register */ 26 #define MIIM_CIS82xx_AUX_CONSTAT 0x1c 27 #define MIIM_CIS82xx_AUXCONSTAT_INIT 0x0004 28 #define MIIM_CIS82xx_AUXCONSTAT_DUPLEX 0x0020 29 #define MIIM_CIS82xx_AUXCONSTAT_SPEED 0x0018 30 #define MIIM_CIS82xx_AUXCONSTAT_GBIT 0x0010 31 #define MIIM_CIS82xx_AUXCONSTAT_100 0x0008 32 33 /* Cicada Extended Control Register 1 */ 34 #define MIIM_CIS82xx_EXT_CON1 0x17 35 #define MIIM_CIS8201_EXTCON1_INIT 0x0000 36 37 /* Cicada 8204 Extended PHY Control Register 1 */ 38 #define MIIM_CIS8204_EPHY_CON 0x17 39 #define MIIM_CIS8204_EPHYCON_INIT 0x0006 40 #define MIIM_CIS8204_EPHYCON_RGMII 0x1100 41 42 /* Cicada 8204 Serial LED Control Register */ 43 #define MIIM_CIS8204_SLED_CON 0x1b 44 #define MIIM_CIS8204_SLEDCON_INIT 0x1115 45 46 /* Vitesse VSC8601 Extended PHY Control Register 1 */ 47 #define MIIM_VSC8601_EPHY_CON 0x17 48 #define MIIM_VSC8601_EPHY_CON_INIT_SKEW 0x1120 49 #define MIIM_VSC8601_SKEW_CTRL 0x1c 50 51 #define PHY_EXT_PAGE_ACCESS 0x1f 52 53 /* CIS8201 */ 54 static int vitesse_config(struct phy_device *phydev) 55 { 56 /* Override PHY config settings */ 57 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, 58 MIIM_CIS82xx_AUXCONSTAT_INIT); 59 /* Set up the interface mode */ 60 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1, 61 MIIM_CIS8201_EXTCON1_INIT); 62 63 genphy_config_aneg(phydev); 64 65 return 0; 66 } 67 68 static int vitesse_parse_status(struct phy_device *phydev) 69 { 70 int speed; 71 int mii_reg; 72 73 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT); 74 75 if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX) 76 phydev->duplex = DUPLEX_FULL; 77 else 78 phydev->duplex = DUPLEX_HALF; 79 80 speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED; 81 switch (speed) { 82 case MIIM_CIS82xx_AUXCONSTAT_GBIT: 83 phydev->speed = SPEED_1000; 84 break; 85 case MIIM_CIS82xx_AUXCONSTAT_100: 86 phydev->speed = SPEED_100; 87 break; 88 default: 89 phydev->speed = SPEED_10; 90 break; 91 } 92 93 return 0; 94 } 95 96 static int vitesse_startup(struct phy_device *phydev) 97 { 98 genphy_update_link(phydev); 99 vitesse_parse_status(phydev); 100 101 return 0; 102 } 103 104 static int cis8204_config(struct phy_device *phydev) 105 { 106 /* Override PHY config settings */ 107 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, 108 MIIM_CIS82xx_AUXCONSTAT_INIT); 109 110 genphy_config_aneg(phydev); 111 112 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 113 (phydev->interface == PHY_INTERFACE_MODE_RGMII) || 114 (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) || 115 (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) 116 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, 117 MIIM_CIS8204_EPHYCON_INIT | 118 MIIM_CIS8204_EPHYCON_RGMII); 119 else 120 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, 121 MIIM_CIS8204_EPHYCON_INIT); 122 123 return 0; 124 } 125 126 /* Vitesse VSC8601 */ 127 int vsc8601_config(struct phy_device *phydev) 128 { 129 /* Configure some basic stuff */ 130 #ifdef CONFIG_SYS_VSC8601_SKEWFIX 131 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON, 132 MIIM_VSC8601_EPHY_CON_INIT_SKEW); 133 #if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX) 134 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1); 135 #define VSC8101_SKEW \ 136 ((CONFIG_SYS_VSC8601_SKEW_TX << 14) \ 137 | (CONFIG_SYS_VSC8601_SKEW_RX << 12)) 138 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL, 139 VSC8101_SKEW); 140 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); 141 #endif 142 #endif 143 144 genphy_config_aneg(phydev); 145 146 return 0; 147 } 148 149 static struct phy_driver VSC8211_driver = { 150 .name = "Vitesse VSC8211", 151 .uid = 0xfc4b0, 152 .mask = 0xffff0, 153 .features = PHY_GBIT_FEATURES, 154 .config = &vitesse_config, 155 .startup = &vitesse_startup, 156 .shutdown = &genphy_shutdown, 157 }; 158 159 static struct phy_driver VSC8221_driver = { 160 .name = "Vitesse VSC8221", 161 .uid = 0xfc550, 162 .mask = 0xffff0, 163 .features = PHY_GBIT_FEATURES, 164 .config = &genphy_config_aneg, 165 .startup = &vitesse_startup, 166 .shutdown = &genphy_shutdown, 167 }; 168 169 static struct phy_driver VSC8244_driver = { 170 .name = "Vitesse VSC8244", 171 .uid = 0xfc6c0, 172 .mask = 0xffff0, 173 .features = PHY_GBIT_FEATURES, 174 .config = &genphy_config_aneg, 175 .startup = &vitesse_startup, 176 .shutdown = &genphy_shutdown, 177 }; 178 179 static struct phy_driver VSC8234_driver = { 180 .name = "Vitesse VSC8234", 181 .uid = 0xfc620, 182 .mask = 0xffff0, 183 .features = PHY_GBIT_FEATURES, 184 .config = &genphy_config_aneg, 185 .startup = &vitesse_startup, 186 .shutdown = &genphy_shutdown, 187 }; 188 189 static struct phy_driver VSC8601_driver = { 190 .name = "Vitesse VSC8601", 191 .uid = 0x70420, 192 .mask = 0xffff0, 193 .features = PHY_GBIT_FEATURES, 194 .config = &vsc8601_config, 195 .startup = &vitesse_startup, 196 .shutdown = &genphy_shutdown, 197 }; 198 199 static struct phy_driver VSC8641_driver = { 200 .name = "Vitesse VSC8641", 201 .uid = 0x70430, 202 .mask = 0xffff0, 203 .features = PHY_GBIT_FEATURES, 204 .config = &genphy_config_aneg, 205 .startup = &vitesse_startup, 206 .shutdown = &genphy_shutdown, 207 }; 208 209 /* Vitesse bought Cicada, so we'll put these here */ 210 static struct phy_driver cis8201_driver = { 211 .name = "CIS8201", 212 .uid = 0xfc410, 213 .mask = 0xffff0, 214 .features = PHY_GBIT_FEATURES, 215 .config = &vitesse_config, 216 .startup = &vitesse_startup, 217 .shutdown = &genphy_shutdown, 218 }; 219 220 static struct phy_driver cis8204_driver = { 221 .name = "Cicada Cis8204", 222 .uid = 0xfc440, 223 .mask = 0xffff0, 224 .features = PHY_GBIT_FEATURES, 225 .config = &cis8204_config, 226 .startup = &vitesse_startup, 227 .shutdown = &genphy_shutdown, 228 }; 229 230 int phy_vitesse_init(void) 231 { 232 phy_register(&VSC8641_driver); 233 phy_register(&VSC8601_driver); 234 phy_register(&VSC8234_driver); 235 phy_register(&VSC8244_driver); 236 phy_register(&VSC8211_driver); 237 phy_register(&VSC8221_driver); 238 phy_register(&cis8201_driver); 239 phy_register(&cis8204_driver); 240 241 return 0; 242 } 243