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 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 #include <miiphy.h> 10 11 /* Cicada Auxiliary Control/Status Register */ 12 #define MIIM_CIS82xx_AUX_CONSTAT 0x1c 13 #define MIIM_CIS82xx_AUXCONSTAT_INIT 0x0004 14 #define MIIM_CIS82xx_AUXCONSTAT_DUPLEX 0x0020 15 #define MIIM_CIS82xx_AUXCONSTAT_SPEED 0x0018 16 #define MIIM_CIS82xx_AUXCONSTAT_GBIT 0x0010 17 #define MIIM_CIS82xx_AUXCONSTAT_100 0x0008 18 19 /* Cicada Extended Control Register 1 */ 20 #define MIIM_CIS82xx_EXT_CON1 0x17 21 #define MIIM_CIS8201_EXTCON1_INIT 0x0000 22 23 /* Cicada 8204 Extended PHY Control Register 1 */ 24 #define MIIM_CIS8204_EPHY_CON 0x17 25 #define MIIM_CIS8204_EPHYCON_INIT 0x0006 26 #define MIIM_CIS8204_EPHYCON_RGMII 0x1100 27 28 /* Cicada 8204 Serial LED Control Register */ 29 #define MIIM_CIS8204_SLED_CON 0x1b 30 #define MIIM_CIS8204_SLEDCON_INIT 0x1115 31 32 /* Vitesse VSC8601 Extended PHY Control Register 1 */ 33 #define MIIM_VSC8601_EPHY_CON 0x17 34 #define MIIM_VSC8601_EPHY_CON_INIT_SKEW 0x1120 35 #define MIIM_VSC8601_SKEW_CTRL 0x1c 36 37 #define PHY_EXT_PAGE_ACCESS 0x1f 38 #define PHY_EXT_PAGE_ACCESS_GENERAL 0x10 39 #define PHY_EXT_PAGE_ACCESS_EXTENDED3 0x3 40 41 /* Vitesse VSC8574 control register */ 42 #define MIIM_VSC8574_MAC_SERDES_CON 0x10 43 #define MIIM_VSC8574_MAC_SERDES_ANEG 0x80 44 #define MIIM_VSC8574_GENERAL18 0x12 45 #define MIIM_VSC8574_GENERAL19 0x13 46 47 /* Vitesse VSC8574 gerenal purpose register 18 */ 48 #define MIIM_VSC8574_18G_SGMII 0x80f0 49 #define MIIM_VSC8574_18G_QSGMII 0x80e0 50 #define MIIM_VSC8574_18G_CMDSTAT 0x8000 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 static 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 int vsc8574_config(struct phy_device *phydev) 149 { 150 u32 val; 151 /* configure regiser 19G for MAC */ 152 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 153 PHY_EXT_PAGE_ACCESS_GENERAL); 154 155 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19); 156 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) { 157 /* set bit 15:14 to '01' for QSGMII mode */ 158 val = (val & 0x3fff) | (1 << 14); 159 phy_write(phydev, MDIO_DEVAD_NONE, 160 MIIM_VSC8574_GENERAL19, val); 161 /* Enable 4 ports MAC QSGMII */ 162 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18, 163 MIIM_VSC8574_18G_QSGMII); 164 } else { 165 /* set bit 15:14 to '00' for SGMII mode */ 166 val = val & 0x3fff; 167 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19, val); 168 /* Enable 4 ports MAC SGMII */ 169 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18, 170 MIIM_VSC8574_18G_SGMII); 171 } 172 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18); 173 /* When bit 15 is cleared the command has completed */ 174 while (val & MIIM_VSC8574_18G_CMDSTAT) 175 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18); 176 177 /* Enable Serdes Auto-negotiation */ 178 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 179 PHY_EXT_PAGE_ACCESS_EXTENDED3); 180 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON); 181 val = val | MIIM_VSC8574_MAC_SERDES_ANEG; 182 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON, val); 183 184 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); 185 186 genphy_config_aneg(phydev); 187 188 return 0; 189 } 190 191 static struct phy_driver VSC8211_driver = { 192 .name = "Vitesse VSC8211", 193 .uid = 0xfc4b0, 194 .mask = 0xffff0, 195 .features = PHY_GBIT_FEATURES, 196 .config = &vitesse_config, 197 .startup = &vitesse_startup, 198 .shutdown = &genphy_shutdown, 199 }; 200 201 static struct phy_driver VSC8221_driver = { 202 .name = "Vitesse VSC8221", 203 .uid = 0xfc550, 204 .mask = 0xffff0, 205 .features = PHY_GBIT_FEATURES, 206 .config = &genphy_config_aneg, 207 .startup = &vitesse_startup, 208 .shutdown = &genphy_shutdown, 209 }; 210 211 static struct phy_driver VSC8244_driver = { 212 .name = "Vitesse VSC8244", 213 .uid = 0xfc6c0, 214 .mask = 0xffff0, 215 .features = PHY_GBIT_FEATURES, 216 .config = &genphy_config_aneg, 217 .startup = &vitesse_startup, 218 .shutdown = &genphy_shutdown, 219 }; 220 221 static struct phy_driver VSC8234_driver = { 222 .name = "Vitesse VSC8234", 223 .uid = 0xfc620, 224 .mask = 0xffff0, 225 .features = PHY_GBIT_FEATURES, 226 .config = &genphy_config_aneg, 227 .startup = &vitesse_startup, 228 .shutdown = &genphy_shutdown, 229 }; 230 231 static struct phy_driver VSC8574_driver = { 232 .name = "Vitesse VSC8574", 233 .uid = 0x704a0, 234 .mask = 0xffff0, 235 .features = PHY_GBIT_FEATURES, 236 .config = &vsc8574_config, 237 .startup = &vitesse_startup, 238 .shutdown = &genphy_shutdown, 239 }; 240 241 static struct phy_driver VSC8601_driver = { 242 .name = "Vitesse VSC8601", 243 .uid = 0x70420, 244 .mask = 0xffff0, 245 .features = PHY_GBIT_FEATURES, 246 .config = &vsc8601_config, 247 .startup = &vitesse_startup, 248 .shutdown = &genphy_shutdown, 249 }; 250 251 static struct phy_driver VSC8641_driver = { 252 .name = "Vitesse VSC8641", 253 .uid = 0x70430, 254 .mask = 0xffff0, 255 .features = PHY_GBIT_FEATURES, 256 .config = &genphy_config_aneg, 257 .startup = &vitesse_startup, 258 .shutdown = &genphy_shutdown, 259 }; 260 261 static struct phy_driver VSC8662_driver = { 262 .name = "Vitesse VSC8662", 263 .uid = 0x70660, 264 .mask = 0xffff0, 265 .features = PHY_GBIT_FEATURES, 266 .config = &genphy_config_aneg, 267 .startup = &vitesse_startup, 268 .shutdown = &genphy_shutdown, 269 }; 270 271 /* Vitesse bought Cicada, so we'll put these here */ 272 static struct phy_driver cis8201_driver = { 273 .name = "CIS8201", 274 .uid = 0xfc410, 275 .mask = 0xffff0, 276 .features = PHY_GBIT_FEATURES, 277 .config = &vitesse_config, 278 .startup = &vitesse_startup, 279 .shutdown = &genphy_shutdown, 280 }; 281 282 static struct phy_driver cis8204_driver = { 283 .name = "Cicada Cis8204", 284 .uid = 0xfc440, 285 .mask = 0xffff0, 286 .features = PHY_GBIT_FEATURES, 287 .config = &cis8204_config, 288 .startup = &vitesse_startup, 289 .shutdown = &genphy_shutdown, 290 }; 291 292 int phy_vitesse_init(void) 293 { 294 phy_register(&VSC8641_driver); 295 phy_register(&VSC8601_driver); 296 phy_register(&VSC8234_driver); 297 phy_register(&VSC8244_driver); 298 phy_register(&VSC8211_driver); 299 phy_register(&VSC8221_driver); 300 phy_register(&VSC8574_driver); 301 phy_register(&VSC8662_driver); 302 phy_register(&cis8201_driver); 303 phy_register(&cis8204_driver); 304 305 return 0; 306 } 307