1 /* 2 * drivers/net/phy/micrel.c 3 * 4 * Driver for Micrel PHYs 5 * 6 * Author: David J. Choi 7 * 8 * Copyright (c) 2010-2013 Micrel, Inc. 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 * Support : Micrel Phys: 16 * Giga phys: ksz9021, ksz9031 17 * 100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041 18 * ksz8021, ksz8031, ksz8051, 19 * ksz8081, ksz8091, 20 * ksz8061, 21 * Switch : ksz8873, ksz886x 22 */ 23 24 #include <linux/kernel.h> 25 #include <linux/module.h> 26 #include <linux/phy.h> 27 #include <linux/micrel_phy.h> 28 #include <linux/of.h> 29 #include <linux/clk.h> 30 31 /* Operation Mode Strap Override */ 32 #define MII_KSZPHY_OMSO 0x16 33 #define KSZPHY_OMSO_B_CAST_OFF (1 << 9) 34 #define KSZPHY_OMSO_RMII_OVERRIDE (1 << 1) 35 #define KSZPHY_OMSO_MII_OVERRIDE (1 << 0) 36 37 /* general Interrupt control/status reg in vendor specific block. */ 38 #define MII_KSZPHY_INTCS 0x1B 39 #define KSZPHY_INTCS_JABBER (1 << 15) 40 #define KSZPHY_INTCS_RECEIVE_ERR (1 << 14) 41 #define KSZPHY_INTCS_PAGE_RECEIVE (1 << 13) 42 #define KSZPHY_INTCS_PARELLEL (1 << 12) 43 #define KSZPHY_INTCS_LINK_PARTNER_ACK (1 << 11) 44 #define KSZPHY_INTCS_LINK_DOWN (1 << 10) 45 #define KSZPHY_INTCS_REMOTE_FAULT (1 << 9) 46 #define KSZPHY_INTCS_LINK_UP (1 << 8) 47 #define KSZPHY_INTCS_ALL (KSZPHY_INTCS_LINK_UP |\ 48 KSZPHY_INTCS_LINK_DOWN) 49 50 /* general PHY control reg in vendor specific block. */ 51 #define MII_KSZPHY_CTRL 0x1F 52 /* bitmap of PHY register to set interrupt mode */ 53 #define KSZPHY_CTRL_INT_ACTIVE_HIGH (1 << 9) 54 #define KSZ9021_CTRL_INT_ACTIVE_HIGH (1 << 14) 55 #define KS8737_CTRL_INT_ACTIVE_HIGH (1 << 14) 56 #define KSZ8051_RMII_50MHZ_CLK (1 << 7) 57 58 /* Write/read to/from extended registers */ 59 #define MII_KSZPHY_EXTREG 0x0b 60 #define KSZPHY_EXTREG_WRITE 0x8000 61 62 #define MII_KSZPHY_EXTREG_WRITE 0x0c 63 #define MII_KSZPHY_EXTREG_READ 0x0d 64 65 /* Extended registers */ 66 #define MII_KSZPHY_CLK_CONTROL_PAD_SKEW 0x104 67 #define MII_KSZPHY_RX_DATA_PAD_SKEW 0x105 68 #define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106 69 70 #define PS_TO_REG 200 71 72 static int ksz_config_flags(struct phy_device *phydev) 73 { 74 int regval; 75 76 if (phydev->dev_flags & (MICREL_PHY_50MHZ_CLK | MICREL_PHY_25MHZ_CLK)) { 77 regval = phy_read(phydev, MII_KSZPHY_CTRL); 78 if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) 79 regval |= KSZ8051_RMII_50MHZ_CLK; 80 else 81 regval &= ~KSZ8051_RMII_50MHZ_CLK; 82 return phy_write(phydev, MII_KSZPHY_CTRL, regval); 83 } 84 return 0; 85 } 86 87 static int kszphy_extended_write(struct phy_device *phydev, 88 u32 regnum, u16 val) 89 { 90 phy_write(phydev, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | regnum); 91 return phy_write(phydev, MII_KSZPHY_EXTREG_WRITE, val); 92 } 93 94 static int kszphy_extended_read(struct phy_device *phydev, 95 u32 regnum) 96 { 97 phy_write(phydev, MII_KSZPHY_EXTREG, regnum); 98 return phy_read(phydev, MII_KSZPHY_EXTREG_READ); 99 } 100 101 static int kszphy_ack_interrupt(struct phy_device *phydev) 102 { 103 /* bit[7..0] int status, which is a read and clear register. */ 104 int rc; 105 106 rc = phy_read(phydev, MII_KSZPHY_INTCS); 107 108 return (rc < 0) ? rc : 0; 109 } 110 111 static int kszphy_set_interrupt(struct phy_device *phydev) 112 { 113 int temp; 114 temp = (PHY_INTERRUPT_ENABLED == phydev->interrupts) ? 115 KSZPHY_INTCS_ALL : 0; 116 return phy_write(phydev, MII_KSZPHY_INTCS, temp); 117 } 118 119 static int kszphy_config_intr(struct phy_device *phydev) 120 { 121 int temp, rc; 122 123 /* set the interrupt pin active low */ 124 temp = phy_read(phydev, MII_KSZPHY_CTRL); 125 temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH; 126 phy_write(phydev, MII_KSZPHY_CTRL, temp); 127 rc = kszphy_set_interrupt(phydev); 128 return rc < 0 ? rc : 0; 129 } 130 131 static int ksz9021_config_intr(struct phy_device *phydev) 132 { 133 int temp, rc; 134 135 /* set the interrupt pin active low */ 136 temp = phy_read(phydev, MII_KSZPHY_CTRL); 137 temp &= ~KSZ9021_CTRL_INT_ACTIVE_HIGH; 138 phy_write(phydev, MII_KSZPHY_CTRL, temp); 139 rc = kszphy_set_interrupt(phydev); 140 return rc < 0 ? rc : 0; 141 } 142 143 static int ks8737_config_intr(struct phy_device *phydev) 144 { 145 int temp, rc; 146 147 /* set the interrupt pin active low */ 148 temp = phy_read(phydev, MII_KSZPHY_CTRL); 149 temp &= ~KS8737_CTRL_INT_ACTIVE_HIGH; 150 phy_write(phydev, MII_KSZPHY_CTRL, temp); 151 rc = kszphy_set_interrupt(phydev); 152 return rc < 0 ? rc : 0; 153 } 154 155 static int kszphy_setup_led(struct phy_device *phydev, 156 unsigned int reg, unsigned int shift) 157 { 158 159 struct device *dev = &phydev->dev; 160 struct device_node *of_node = dev->of_node; 161 int rc, temp; 162 u32 val; 163 164 if (!of_node && dev->parent->of_node) 165 of_node = dev->parent->of_node; 166 167 if (of_property_read_u32(of_node, "micrel,led-mode", &val)) 168 return 0; 169 170 temp = phy_read(phydev, reg); 171 if (temp < 0) 172 return temp; 173 174 temp &= ~(3 << shift); 175 temp |= val << shift; 176 rc = phy_write(phydev, reg, temp); 177 178 return rc < 0 ? rc : 0; 179 } 180 181 static int kszphy_config_init(struct phy_device *phydev) 182 { 183 return 0; 184 } 185 186 static int kszphy_config_init_led8041(struct phy_device *phydev) 187 { 188 /* single led control, register 0x1e bits 15..14 */ 189 return kszphy_setup_led(phydev, 0x1e, 14); 190 } 191 192 static int ksz8021_config_init(struct phy_device *phydev) 193 { 194 const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE; 195 int rc; 196 197 rc = kszphy_setup_led(phydev, 0x1f, 4); 198 if (rc) 199 dev_err(&phydev->dev, "failed to set led mode\n"); 200 201 phy_write(phydev, MII_KSZPHY_OMSO, val); 202 rc = ksz_config_flags(phydev); 203 return rc < 0 ? rc : 0; 204 } 205 206 static int ks8051_config_init(struct phy_device *phydev) 207 { 208 int rc; 209 210 rc = kszphy_setup_led(phydev, 0x1f, 4); 211 if (rc) 212 dev_err(&phydev->dev, "failed to set led mode\n"); 213 214 rc = ksz_config_flags(phydev); 215 return rc < 0 ? rc : 0; 216 } 217 218 static int ksz9021_load_values_from_of(struct phy_device *phydev, 219 struct device_node *of_node, u16 reg, 220 char *field1, char *field2, 221 char *field3, char *field4) 222 { 223 int val1 = -1; 224 int val2 = -2; 225 int val3 = -3; 226 int val4 = -4; 227 int newval; 228 int matches = 0; 229 230 if (!of_property_read_u32(of_node, field1, &val1)) 231 matches++; 232 233 if (!of_property_read_u32(of_node, field2, &val2)) 234 matches++; 235 236 if (!of_property_read_u32(of_node, field3, &val3)) 237 matches++; 238 239 if (!of_property_read_u32(of_node, field4, &val4)) 240 matches++; 241 242 if (!matches) 243 return 0; 244 245 if (matches < 4) 246 newval = kszphy_extended_read(phydev, reg); 247 else 248 newval = 0; 249 250 if (val1 != -1) 251 newval = ((newval & 0xfff0) | ((val1 / PS_TO_REG) & 0xf) << 0); 252 253 if (val2 != -2) 254 newval = ((newval & 0xff0f) | ((val2 / PS_TO_REG) & 0xf) << 4); 255 256 if (val3 != -3) 257 newval = ((newval & 0xf0ff) | ((val3 / PS_TO_REG) & 0xf) << 8); 258 259 if (val4 != -4) 260 newval = ((newval & 0x0fff) | ((val4 / PS_TO_REG) & 0xf) << 12); 261 262 return kszphy_extended_write(phydev, reg, newval); 263 } 264 265 static int ksz9021_config_init(struct phy_device *phydev) 266 { 267 struct device *dev = &phydev->dev; 268 struct device_node *of_node = dev->of_node; 269 270 if (!of_node && dev->parent->of_node) 271 of_node = dev->parent->of_node; 272 273 if (of_node) { 274 ksz9021_load_values_from_of(phydev, of_node, 275 MII_KSZPHY_CLK_CONTROL_PAD_SKEW, 276 "txen-skew-ps", "txc-skew-ps", 277 "rxdv-skew-ps", "rxc-skew-ps"); 278 ksz9021_load_values_from_of(phydev, of_node, 279 MII_KSZPHY_RX_DATA_PAD_SKEW, 280 "rxd0-skew-ps", "rxd1-skew-ps", 281 "rxd2-skew-ps", "rxd3-skew-ps"); 282 ksz9021_load_values_from_of(phydev, of_node, 283 MII_KSZPHY_TX_DATA_PAD_SKEW, 284 "txd0-skew-ps", "txd1-skew-ps", 285 "txd2-skew-ps", "txd3-skew-ps"); 286 } 287 return 0; 288 } 289 290 #define MII_KSZ9031RN_MMD_CTRL_REG 0x0d 291 #define MII_KSZ9031RN_MMD_REGDATA_REG 0x0e 292 #define OP_DATA 1 293 #define KSZ9031_PS_TO_REG 60 294 295 /* Extended registers */ 296 #define MII_KSZ9031RN_CONTROL_PAD_SKEW 4 297 #define MII_KSZ9031RN_RX_DATA_PAD_SKEW 5 298 #define MII_KSZ9031RN_TX_DATA_PAD_SKEW 6 299 #define MII_KSZ9031RN_CLK_PAD_SKEW 8 300 301 static int ksz9031_extended_write(struct phy_device *phydev, 302 u8 mode, u32 dev_addr, u32 regnum, u16 val) 303 { 304 phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr); 305 phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum); 306 phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr); 307 return phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, val); 308 } 309 310 static int ksz9031_extended_read(struct phy_device *phydev, 311 u8 mode, u32 dev_addr, u32 regnum) 312 { 313 phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr); 314 phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum); 315 phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr); 316 return phy_read(phydev, MII_KSZ9031RN_MMD_REGDATA_REG); 317 } 318 319 static int ksz9031_of_load_skew_values(struct phy_device *phydev, 320 struct device_node *of_node, 321 u16 reg, size_t field_sz, 322 char *field[], u8 numfields) 323 { 324 int val[4] = {-1, -2, -3, -4}; 325 int matches = 0; 326 u16 mask; 327 u16 maxval; 328 u16 newval; 329 int i; 330 331 for (i = 0; i < numfields; i++) 332 if (!of_property_read_u32(of_node, field[i], val + i)) 333 matches++; 334 335 if (!matches) 336 return 0; 337 338 if (matches < numfields) 339 newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg); 340 else 341 newval = 0; 342 343 maxval = (field_sz == 4) ? 0xf : 0x1f; 344 for (i = 0; i < numfields; i++) 345 if (val[i] != -(i + 1)) { 346 mask = 0xffff; 347 mask ^= maxval << (field_sz * i); 348 newval = (newval & mask) | 349 (((val[i] / KSZ9031_PS_TO_REG) & maxval) 350 << (field_sz * i)); 351 } 352 353 return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval); 354 } 355 356 static int ksz9031_config_init(struct phy_device *phydev) 357 { 358 struct device *dev = &phydev->dev; 359 struct device_node *of_node = dev->of_node; 360 char *clk_skews[2] = {"rxc-skew-ps", "txc-skew-ps"}; 361 char *rx_data_skews[4] = { 362 "rxd0-skew-ps", "rxd1-skew-ps", 363 "rxd2-skew-ps", "rxd3-skew-ps" 364 }; 365 char *tx_data_skews[4] = { 366 "txd0-skew-ps", "txd1-skew-ps", 367 "txd2-skew-ps", "txd3-skew-ps" 368 }; 369 char *control_skews[2] = {"txen-skew-ps", "rxdv-skew-ps"}; 370 371 if (!of_node && dev->parent->of_node) 372 of_node = dev->parent->of_node; 373 374 if (of_node) { 375 ksz9031_of_load_skew_values(phydev, of_node, 376 MII_KSZ9031RN_CLK_PAD_SKEW, 5, 377 clk_skews, 2); 378 379 ksz9031_of_load_skew_values(phydev, of_node, 380 MII_KSZ9031RN_CONTROL_PAD_SKEW, 4, 381 control_skews, 2); 382 383 ksz9031_of_load_skew_values(phydev, of_node, 384 MII_KSZ9031RN_RX_DATA_PAD_SKEW, 4, 385 rx_data_skews, 4); 386 387 ksz9031_of_load_skew_values(phydev, of_node, 388 MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4, 389 tx_data_skews, 4); 390 } 391 return 0; 392 } 393 394 #define KSZ8873MLL_GLOBAL_CONTROL_4 0x06 395 #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX (1 << 6) 396 #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED (1 << 4) 397 static int ksz8873mll_read_status(struct phy_device *phydev) 398 { 399 int regval; 400 401 /* dummy read */ 402 regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4); 403 404 regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4); 405 406 if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX) 407 phydev->duplex = DUPLEX_HALF; 408 else 409 phydev->duplex = DUPLEX_FULL; 410 411 if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED) 412 phydev->speed = SPEED_10; 413 else 414 phydev->speed = SPEED_100; 415 416 phydev->link = 1; 417 phydev->pause = phydev->asym_pause = 0; 418 419 return 0; 420 } 421 422 static int ksz8873mll_config_aneg(struct phy_device *phydev) 423 { 424 return 0; 425 } 426 427 /* This routine returns -1 as an indication to the caller that the 428 * Micrel ksz9021 10/100/1000 PHY does not support standard IEEE 429 * MMD extended PHY registers. 430 */ 431 static int 432 ksz9021_rd_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum, 433 int regnum) 434 { 435 return -1; 436 } 437 438 /* This routine does nothing since the Micrel ksz9021 does not support 439 * standard IEEE MMD extended PHY registers. 440 */ 441 static void 442 ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum, 443 int regnum, u32 val) 444 { 445 } 446 447 static int ksz8021_probe(struct phy_device *phydev) 448 { 449 struct clk *clk; 450 451 clk = devm_clk_get(&phydev->dev, "rmii-ref"); 452 if (!IS_ERR(clk)) { 453 unsigned long rate = clk_get_rate(clk); 454 455 if (rate > 24500000 && rate < 25500000) { 456 phydev->dev_flags |= MICREL_PHY_25MHZ_CLK; 457 } else if (rate > 49500000 && rate < 50500000) { 458 phydev->dev_flags |= MICREL_PHY_50MHZ_CLK; 459 } else { 460 dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate); 461 return -EINVAL; 462 } 463 } 464 465 return 0; 466 } 467 468 static struct phy_driver ksphy_driver[] = { 469 { 470 .phy_id = PHY_ID_KS8737, 471 .phy_id_mask = 0x00fffff0, 472 .name = "Micrel KS8737", 473 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), 474 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 475 .config_init = kszphy_config_init, 476 .config_aneg = genphy_config_aneg, 477 .read_status = genphy_read_status, 478 .ack_interrupt = kszphy_ack_interrupt, 479 .config_intr = ks8737_config_intr, 480 .suspend = genphy_suspend, 481 .resume = genphy_resume, 482 .driver = { .owner = THIS_MODULE,}, 483 }, { 484 .phy_id = PHY_ID_KSZ8021, 485 .phy_id_mask = 0x00ffffff, 486 .name = "Micrel KSZ8021 or KSZ8031", 487 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | 488 SUPPORTED_Asym_Pause), 489 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 490 .probe = ksz8021_probe, 491 .config_init = ksz8021_config_init, 492 .config_aneg = genphy_config_aneg, 493 .read_status = genphy_read_status, 494 .ack_interrupt = kszphy_ack_interrupt, 495 .config_intr = kszphy_config_intr, 496 .suspend = genphy_suspend, 497 .resume = genphy_resume, 498 .driver = { .owner = THIS_MODULE,}, 499 }, { 500 .phy_id = PHY_ID_KSZ8031, 501 .phy_id_mask = 0x00ffffff, 502 .name = "Micrel KSZ8031", 503 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause | 504 SUPPORTED_Asym_Pause), 505 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 506 .probe = ksz8021_probe, 507 .config_init = ksz8021_config_init, 508 .config_aneg = genphy_config_aneg, 509 .read_status = genphy_read_status, 510 .ack_interrupt = kszphy_ack_interrupt, 511 .config_intr = kszphy_config_intr, 512 .suspend = genphy_suspend, 513 .resume = genphy_resume, 514 .driver = { .owner = THIS_MODULE,}, 515 }, { 516 .phy_id = PHY_ID_KSZ8041, 517 .phy_id_mask = 0x00fffff0, 518 .name = "Micrel KSZ8041", 519 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause 520 | SUPPORTED_Asym_Pause), 521 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 522 .config_init = kszphy_config_init_led8041, 523 .config_aneg = genphy_config_aneg, 524 .read_status = genphy_read_status, 525 .ack_interrupt = kszphy_ack_interrupt, 526 .config_intr = kszphy_config_intr, 527 .suspend = genphy_suspend, 528 .resume = genphy_resume, 529 .driver = { .owner = THIS_MODULE,}, 530 }, { 531 .phy_id = PHY_ID_KSZ8041RNLI, 532 .phy_id_mask = 0x00fffff0, 533 .name = "Micrel KSZ8041RNLI", 534 .features = PHY_BASIC_FEATURES | 535 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 536 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 537 .config_init = kszphy_config_init_led8041, 538 .config_aneg = genphy_config_aneg, 539 .read_status = genphy_read_status, 540 .ack_interrupt = kszphy_ack_interrupt, 541 .config_intr = kszphy_config_intr, 542 .suspend = genphy_suspend, 543 .resume = genphy_resume, 544 .driver = { .owner = THIS_MODULE,}, 545 }, { 546 .phy_id = PHY_ID_KSZ8051, 547 .phy_id_mask = 0x00fffff0, 548 .name = "Micrel KSZ8051", 549 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause 550 | SUPPORTED_Asym_Pause), 551 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 552 .config_init = ks8051_config_init, 553 .config_aneg = genphy_config_aneg, 554 .read_status = genphy_read_status, 555 .ack_interrupt = kszphy_ack_interrupt, 556 .config_intr = kszphy_config_intr, 557 .suspend = genphy_suspend, 558 .resume = genphy_resume, 559 .driver = { .owner = THIS_MODULE,}, 560 }, { 561 .phy_id = PHY_ID_KSZ8001, 562 .name = "Micrel KSZ8001 or KS8721", 563 .phy_id_mask = 0x00ffffff, 564 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), 565 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 566 .config_init = kszphy_config_init_led8041, 567 .config_aneg = genphy_config_aneg, 568 .read_status = genphy_read_status, 569 .ack_interrupt = kszphy_ack_interrupt, 570 .config_intr = kszphy_config_intr, 571 .suspend = genphy_suspend, 572 .resume = genphy_resume, 573 .driver = { .owner = THIS_MODULE,}, 574 }, { 575 .phy_id = PHY_ID_KSZ8081, 576 .name = "Micrel KSZ8081 or KSZ8091", 577 .phy_id_mask = 0x00fffff0, 578 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), 579 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 580 .config_init = kszphy_config_init, 581 .config_aneg = genphy_config_aneg, 582 .read_status = genphy_read_status, 583 .ack_interrupt = kszphy_ack_interrupt, 584 .config_intr = kszphy_config_intr, 585 .suspend = genphy_suspend, 586 .resume = genphy_resume, 587 .driver = { .owner = THIS_MODULE,}, 588 }, { 589 .phy_id = PHY_ID_KSZ8061, 590 .name = "Micrel KSZ8061", 591 .phy_id_mask = 0x00fffff0, 592 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), 593 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 594 .config_init = kszphy_config_init, 595 .config_aneg = genphy_config_aneg, 596 .read_status = genphy_read_status, 597 .ack_interrupt = kszphy_ack_interrupt, 598 .config_intr = kszphy_config_intr, 599 .suspend = genphy_suspend, 600 .resume = genphy_resume, 601 .driver = { .owner = THIS_MODULE,}, 602 }, { 603 .phy_id = PHY_ID_KSZ9021, 604 .phy_id_mask = 0x000ffffe, 605 .name = "Micrel KSZ9021 Gigabit PHY", 606 .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), 607 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 608 .config_init = ksz9021_config_init, 609 .config_aneg = genphy_config_aneg, 610 .read_status = genphy_read_status, 611 .ack_interrupt = kszphy_ack_interrupt, 612 .config_intr = ksz9021_config_intr, 613 .suspend = genphy_suspend, 614 .resume = genphy_resume, 615 .read_mmd_indirect = ksz9021_rd_mmd_phyreg, 616 .write_mmd_indirect = ksz9021_wr_mmd_phyreg, 617 .driver = { .owner = THIS_MODULE, }, 618 }, { 619 .phy_id = PHY_ID_KSZ9031, 620 .phy_id_mask = 0x00fffff0, 621 .name = "Micrel KSZ9031 Gigabit PHY", 622 .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), 623 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 624 .config_init = ksz9031_config_init, 625 .config_aneg = genphy_config_aneg, 626 .read_status = genphy_read_status, 627 .ack_interrupt = kszphy_ack_interrupt, 628 .config_intr = ksz9021_config_intr, 629 .suspend = genphy_suspend, 630 .resume = genphy_resume, 631 .driver = { .owner = THIS_MODULE, }, 632 }, { 633 .phy_id = PHY_ID_KSZ8873MLL, 634 .phy_id_mask = 0x00fffff0, 635 .name = "Micrel KSZ8873MLL Switch", 636 .features = (SUPPORTED_Pause | SUPPORTED_Asym_Pause), 637 .flags = PHY_HAS_MAGICANEG, 638 .config_init = kszphy_config_init, 639 .config_aneg = ksz8873mll_config_aneg, 640 .read_status = ksz8873mll_read_status, 641 .suspend = genphy_suspend, 642 .resume = genphy_resume, 643 .driver = { .owner = THIS_MODULE, }, 644 }, { 645 .phy_id = PHY_ID_KSZ886X, 646 .phy_id_mask = 0x00fffff0, 647 .name = "Micrel KSZ886X Switch", 648 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), 649 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 650 .config_init = kszphy_config_init, 651 .config_aneg = genphy_config_aneg, 652 .read_status = genphy_read_status, 653 .suspend = genphy_suspend, 654 .resume = genphy_resume, 655 .driver = { .owner = THIS_MODULE, }, 656 } }; 657 658 static int __init ksphy_init(void) 659 { 660 return phy_drivers_register(ksphy_driver, 661 ARRAY_SIZE(ksphy_driver)); 662 } 663 664 static void __exit ksphy_exit(void) 665 { 666 phy_drivers_unregister(ksphy_driver, 667 ARRAY_SIZE(ksphy_driver)); 668 } 669 670 module_init(ksphy_init); 671 module_exit(ksphy_exit); 672 673 MODULE_DESCRIPTION("Micrel PHY driver"); 674 MODULE_AUTHOR("David J. Choi"); 675 MODULE_LICENSE("GPL"); 676 677 static struct mdio_device_id __maybe_unused micrel_tbl[] = { 678 { PHY_ID_KSZ9021, 0x000ffffe }, 679 { PHY_ID_KSZ9031, 0x00fffff0 }, 680 { PHY_ID_KSZ8001, 0x00ffffff }, 681 { PHY_ID_KS8737, 0x00fffff0 }, 682 { PHY_ID_KSZ8021, 0x00ffffff }, 683 { PHY_ID_KSZ8031, 0x00ffffff }, 684 { PHY_ID_KSZ8041, 0x00fffff0 }, 685 { PHY_ID_KSZ8051, 0x00fffff0 }, 686 { PHY_ID_KSZ8061, 0x00fffff0 }, 687 { PHY_ID_KSZ8081, 0x00fffff0 }, 688 { PHY_ID_KSZ8873MLL, 0x00fffff0 }, 689 { PHY_ID_KSZ886X, 0x00fffff0 }, 690 { } 691 }; 692 693 MODULE_DEVICE_TABLE(mdio, micrel_tbl); 694