|
72 | 72 | #define PHY_ID_VSC8572 0x000704d0
|
73 | 73 | #define PHY_ID_VSC8574 0x000704a0
|
74 | 74 | #define PHY_ID_VSC8601 0x00070420
|
| 75 | +#define PHY_ID_VSC7385 0x00070450 |
| 76 | +#define PHY_ID_VSC7388 0x00070480 |
| 77 | +#define PHY_ID_VSC7395 0x00070550 |
| 78 | +#define PHY_ID_VSC7398 0x00070580 |
75 | 79 | #define PHY_ID_VSC8662 0x00070660
|
76 | 80 | #define PHY_ID_VSC8221 0x000fc550
|
77 | 81 | #define PHY_ID_VSC8211 0x000fc4b0
|
@@ -116,6 +120,137 @@ static int vsc824x_config_init(struct phy_device *phydev)
|
116 | 120 | return err;
|
117 | 121 | }
|
118 | 122 |
|
| 123 | +#define VSC73XX_EXT_PAGE_ACCESS 0x1f |
| 124 | + |
| 125 | +static int vsc73xx_read_page(struct phy_device *phydev) |
| 126 | +{ |
| 127 | + return __phy_read(phydev, VSC73XX_EXT_PAGE_ACCESS); |
| 128 | +} |
| 129 | + |
| 130 | +static int vsc73xx_write_page(struct phy_device *phydev, int page) |
| 131 | +{ |
| 132 | + return __phy_write(phydev, VSC73XX_EXT_PAGE_ACCESS, page); |
| 133 | +} |
| 134 | + |
| 135 | +static void vsc73xx_config_init(struct phy_device *phydev) |
| 136 | +{ |
| 137 | + /* Receiver init */ |
| 138 | + phy_write(phydev, 0x1f, 0x2a30); |
| 139 | + phy_modify(phydev, 0x0c, 0x0300, 0x0200); |
| 140 | + phy_write(phydev, 0x1f, 0x0000); |
| 141 | + |
| 142 | + /* Config LEDs 0x61 */ |
| 143 | + phy_modify(phydev, MII_TPISTATUS, 0xff00, 0x0061); |
| 144 | +} |
| 145 | + |
| 146 | +static int vsc738x_config_init(struct phy_device *phydev) |
| 147 | +{ |
| 148 | + u16 rev; |
| 149 | + /* This magic sequence appear in the application note |
| 150 | + * "VSC7385/7388 PHY Configuration". |
| 151 | + * |
| 152 | + * Maybe one day we will get to know what it all means. |
| 153 | + */ |
| 154 | + phy_write(phydev, 0x1f, 0x2a30); |
| 155 | + phy_modify(phydev, 0x08, 0x0200, 0x0200); |
| 156 | + phy_write(phydev, 0x1f, 0x52b5); |
| 157 | + phy_write(phydev, 0x10, 0xb68a); |
| 158 | + phy_modify(phydev, 0x12, 0xff07, 0x0003); |
| 159 | + phy_modify(phydev, 0x11, 0x00ff, 0x00a2); |
| 160 | + phy_write(phydev, 0x10, 0x968a); |
| 161 | + phy_write(phydev, 0x1f, 0x2a30); |
| 162 | + phy_modify(phydev, 0x08, 0x0200, 0x0000); |
| 163 | + phy_write(phydev, 0x1f, 0x0000); |
| 164 | + |
| 165 | + /* Read revision */ |
| 166 | + rev = phy_read(phydev, MII_PHYSID2); |
| 167 | + rev &= 0x0f; |
| 168 | + |
| 169 | + /* Special quirk for revision 0 */ |
| 170 | + if (rev == 0) { |
| 171 | + phy_write(phydev, 0x1f, 0x2a30); |
| 172 | + phy_modify(phydev, 0x08, 0x0200, 0x0200); |
| 173 | + phy_write(phydev, 0x1f, 0x52b5); |
| 174 | + phy_write(phydev, 0x12, 0x0000); |
| 175 | + phy_write(phydev, 0x11, 0x0689); |
| 176 | + phy_write(phydev, 0x10, 0x8f92); |
| 177 | + phy_write(phydev, 0x1f, 0x52b5); |
| 178 | + phy_write(phydev, 0x12, 0x0000); |
| 179 | + phy_write(phydev, 0x11, 0x0e35); |
| 180 | + phy_write(phydev, 0x10, 0x9786); |
| 181 | + phy_write(phydev, 0x1f, 0x2a30); |
| 182 | + phy_modify(phydev, 0x08, 0x0200, 0x0000); |
| 183 | + phy_write(phydev, 0x17, 0xff80); |
| 184 | + phy_write(phydev, 0x17, 0x0000); |
| 185 | + } |
| 186 | + |
| 187 | + phy_write(phydev, 0x1f, 0x0000); |
| 188 | + phy_write(phydev, 0x12, 0x0048); |
| 189 | + |
| 190 | + if (rev == 0) { |
| 191 | + phy_write(phydev, 0x1f, 0x2a30); |
| 192 | + phy_write(phydev, 0x14, 0x6600); |
| 193 | + phy_write(phydev, 0x1f, 0x0000); |
| 194 | + phy_write(phydev, 0x18, 0xa24e); |
| 195 | + } else { |
| 196 | + phy_write(phydev, 0x1f, 0x2a30); |
| 197 | + phy_modify(phydev, 0x16, 0x0fc0, 0x0240); |
| 198 | + phy_modify(phydev, 0x14, 0x6000, 0x4000); |
| 199 | + /* bits 14-15 in extended register 0x14 controls DACG amplitude |
| 200 | + * 6 = -8%, 2 is hardware default |
| 201 | + */ |
| 202 | + phy_write(phydev, 0x1f, 0x0001); |
| 203 | + phy_modify(phydev, 0x14, 0xe000, 0x6000); |
| 204 | + phy_write(phydev, 0x1f, 0x0000); |
| 205 | + } |
| 206 | + |
| 207 | + vsc73xx_config_init(phydev); |
| 208 | + |
| 209 | + return genphy_config_init(phydev); |
| 210 | +} |
| 211 | + |
| 212 | +static int vsc739x_config_init(struct phy_device *phydev) |
| 213 | +{ |
| 214 | + /* This magic sequence appears in the VSC7395 SparX-G5e application |
| 215 | + * note "VSC7395/VSC7398 PHY Configuration" |
| 216 | + * |
| 217 | + * Maybe one day we will get to know what it all means. |
| 218 | + */ |
| 219 | + phy_write(phydev, 0x1f, 0x2a30); |
| 220 | + phy_modify(phydev, 0x08, 0x0200, 0x0200); |
| 221 | + phy_write(phydev, 0x1f, 0x52b5); |
| 222 | + phy_write(phydev, 0x10, 0xb68a); |
| 223 | + phy_modify(phydev, 0x12, 0xff07, 0x0003); |
| 224 | + phy_modify(phydev, 0x11, 0x00ff, 0x00a2); |
| 225 | + phy_write(phydev, 0x10, 0x968a); |
| 226 | + phy_write(phydev, 0x1f, 0x2a30); |
| 227 | + phy_modify(phydev, 0x08, 0x0200, 0x0000); |
| 228 | + phy_write(phydev, 0x1f, 0x0000); |
| 229 | + |
| 230 | + phy_write(phydev, 0x1f, 0x0000); |
| 231 | + phy_write(phydev, 0x12, 0x0048); |
| 232 | + phy_write(phydev, 0x1f, 0x2a30); |
| 233 | + phy_modify(phydev, 0x16, 0x0fc0, 0x0240); |
| 234 | + phy_modify(phydev, 0x14, 0x6000, 0x4000); |
| 235 | + phy_write(phydev, 0x1f, 0x0001); |
| 236 | + phy_modify(phydev, 0x14, 0xe000, 0x6000); |
| 237 | + phy_write(phydev, 0x1f, 0x0000); |
| 238 | + |
| 239 | + vsc73xx_config_init(phydev); |
| 240 | + |
| 241 | + return genphy_config_init(phydev); |
| 242 | +} |
| 243 | + |
| 244 | +static int vsc73xx_config_aneg(struct phy_device *phydev) |
| 245 | +{ |
| 246 | + /* The VSC73xx switches does not like to be instructed to |
| 247 | + * do autonegotiation in any way, it prefers that you just go |
| 248 | + * with the power-on/reset defaults. Writing some registers will |
| 249 | + * just make autonegotiation permanently fail. |
| 250 | + */ |
| 251 | + return 0; |
| 252 | +} |
| 253 | + |
119 | 254 | /* This adds a skew for both TX and RX clocks, so the skew should only be
|
120 | 255 | * applied to "rgmii-id" interfaces. It may not work as expected
|
121 | 256 | * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */
|
@@ -318,6 +453,42 @@ static struct phy_driver vsc82xx_driver[] = {
|
318 | 453 | .config_init = &vsc8601_config_init,
|
319 | 454 | .ack_interrupt = &vsc824x_ack_interrupt,
|
320 | 455 | .config_intr = &vsc82xx_config_intr,
|
| 456 | +}, { |
| 457 | + .phy_id = PHY_ID_VSC7385, |
| 458 | + .name = "Vitesse VSC7385", |
| 459 | + .phy_id_mask = 0x000ffff0, |
| 460 | + .features = PHY_GBIT_FEATURES, |
| 461 | + .config_init = vsc738x_config_init, |
| 462 | + .config_aneg = vsc73xx_config_aneg, |
| 463 | + .read_page = vsc73xx_read_page, |
| 464 | + .write_page = vsc73xx_write_page, |
| 465 | +}, { |
| 466 | + .phy_id = PHY_ID_VSC7388, |
| 467 | + .name = "Vitesse VSC7388", |
| 468 | + .phy_id_mask = 0x000ffff0, |
| 469 | + .features = PHY_GBIT_FEATURES, |
| 470 | + .config_init = vsc738x_config_init, |
| 471 | + .config_aneg = vsc73xx_config_aneg, |
| 472 | + .read_page = vsc73xx_read_page, |
| 473 | + .write_page = vsc73xx_write_page, |
| 474 | +}, { |
| 475 | + .phy_id = PHY_ID_VSC7395, |
| 476 | + .name = "Vitesse VSC7395", |
| 477 | + .phy_id_mask = 0x000ffff0, |
| 478 | + .features = PHY_GBIT_FEATURES, |
| 479 | + .config_init = vsc739x_config_init, |
| 480 | + .config_aneg = vsc73xx_config_aneg, |
| 481 | + .read_page = vsc73xx_read_page, |
| 482 | + .write_page = vsc73xx_write_page, |
| 483 | +}, { |
| 484 | + .phy_id = PHY_ID_VSC7398, |
| 485 | + .name = "Vitesse VSC7398", |
| 486 | + .phy_id_mask = 0x000ffff0, |
| 487 | + .features = PHY_GBIT_FEATURES, |
| 488 | + .config_init = vsc739x_config_init, |
| 489 | + .config_aneg = vsc73xx_config_aneg, |
| 490 | + .read_page = vsc73xx_read_page, |
| 491 | + .write_page = vsc73xx_write_page, |
321 | 492 | }, {
|
322 | 493 | .phy_id = PHY_ID_VSC8662,
|
323 | 494 | .name = "Vitesse VSC8662",
|
@@ -358,6 +529,10 @@ static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
|
358 | 529 | { PHY_ID_VSC8514, 0x000ffff0 },
|
359 | 530 | { PHY_ID_VSC8572, 0x000ffff0 },
|
360 | 531 | { PHY_ID_VSC8574, 0x000ffff0 },
|
| 532 | + { PHY_ID_VSC7385, 0x000ffff0 }, |
| 533 | + { PHY_ID_VSC7388, 0x000ffff0 }, |
| 534 | + { PHY_ID_VSC7395, 0x000ffff0 }, |
| 535 | + { PHY_ID_VSC7398, 0x000ffff0 }, |
361 | 536 | { PHY_ID_VSC8662, 0x000ffff0 },
|
362 | 537 | { PHY_ID_VSC8221, 0x000ffff0 },
|
363 | 538 | { PHY_ID_VSC8211, 0x000ffff0 },
|
|
0 commit comments