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