| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2015 Microchip Technology |
|---|
| 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 |
|---|
| 6 | | - * as published by the Free Software Foundation; either version 2 |
|---|
| 7 | | - * of 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, see <http://www.gnu.org/licenses/>. |
|---|
| 16 | 4 | */ |
|---|
| 17 | 5 | #include <linux/kernel.h> |
|---|
| 18 | 6 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 88 | 76 | /* Save current page */ |
|---|
| 89 | 77 | save_page = phy_save_page(phydev); |
|---|
| 90 | 78 | if (save_page < 0) { |
|---|
| 91 | | - pr_warn("Failed to get current page\n"); |
|---|
| 79 | + phydev_warn(phydev, "Failed to get current page\n"); |
|---|
| 92 | 80 | goto err; |
|---|
| 93 | 81 | } |
|---|
| 94 | 82 | |
|---|
| .. | .. |
|---|
| 98 | 86 | ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_LOW_DATA, |
|---|
| 99 | 87 | (data & 0xFFFF)); |
|---|
| 100 | 88 | if (ret < 0) { |
|---|
| 101 | | - pr_warn("Failed to write TR low data\n"); |
|---|
| 89 | + phydev_warn(phydev, "Failed to write TR low data\n"); |
|---|
| 102 | 90 | goto err; |
|---|
| 103 | 91 | } |
|---|
| 104 | 92 | |
|---|
| 105 | 93 | ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_HIGH_DATA, |
|---|
| 106 | 94 | (data & 0x00FF0000) >> 16); |
|---|
| 107 | 95 | if (ret < 0) { |
|---|
| 108 | | - pr_warn("Failed to write TR high data\n"); |
|---|
| 96 | + phydev_warn(phydev, "Failed to write TR high data\n"); |
|---|
| 109 | 97 | goto err; |
|---|
| 110 | 98 | } |
|---|
| 111 | 99 | |
|---|
| .. | .. |
|---|
| 115 | 103 | |
|---|
| 116 | 104 | ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_CR, buf); |
|---|
| 117 | 105 | if (ret < 0) { |
|---|
| 118 | | - pr_warn("Failed to write data in reg\n"); |
|---|
| 106 | + phydev_warn(phydev, "Failed to write data in reg\n"); |
|---|
| 119 | 107 | goto err; |
|---|
| 120 | 108 | } |
|---|
| 121 | 109 | |
|---|
| 122 | 110 | usleep_range(1000, 2000);/* Wait for Data to be written */ |
|---|
| 123 | 111 | val = __phy_read(phydev, LAN88XX_EXT_PAGE_TR_CR); |
|---|
| 124 | 112 | if (!(val & 0x8000)) |
|---|
| 125 | | - pr_warn("TR Register[0x%X] configuration failed\n", regaddr); |
|---|
| 113 | + phydev_warn(phydev, "TR Register[0x%X] configuration failed\n", |
|---|
| 114 | + regaddr); |
|---|
| 126 | 115 | err: |
|---|
| 127 | 116 | return phy_restore_page(phydev, save_page, ret); |
|---|
| 128 | 117 | } |
|---|
| .. | .. |
|---|
| 137 | 126 | */ |
|---|
| 138 | 127 | err = lan88xx_TR_reg_set(phydev, 0x0F82, 0x12B00A); |
|---|
| 139 | 128 | if (err < 0) |
|---|
| 140 | | - pr_warn("Failed to Set Register[0x0F82]\n"); |
|---|
| 129 | + phydev_warn(phydev, "Failed to Set Register[0x0F82]\n"); |
|---|
| 141 | 130 | |
|---|
| 142 | 131 | /* Get access to Channel b'10, Node b'1101, Register 0x06. |
|---|
| 143 | 132 | * Write 24-bit value 0xD2C46F to register. Setting SSTrKf1000Slv, |
|---|
| .. | .. |
|---|
| 145 | 134 | */ |
|---|
| 146 | 135 | err = lan88xx_TR_reg_set(phydev, 0x168C, 0xD2C46F); |
|---|
| 147 | 136 | if (err < 0) |
|---|
| 148 | | - pr_warn("Failed to Set Register[0x168C]\n"); |
|---|
| 137 | + phydev_warn(phydev, "Failed to Set Register[0x168C]\n"); |
|---|
| 149 | 138 | |
|---|
| 150 | 139 | /* Get access to Channel b'10, Node b'1111, Register 0x11. |
|---|
| 151 | 140 | * Write 24-bit value 0x620 to register. Setting rem_upd_done_thresh |
|---|
| .. | .. |
|---|
| 153 | 142 | */ |
|---|
| 154 | 143 | err = lan88xx_TR_reg_set(phydev, 0x17A2, 0x620); |
|---|
| 155 | 144 | if (err < 0) |
|---|
| 156 | | - pr_warn("Failed to Set Register[0x17A2]\n"); |
|---|
| 145 | + phydev_warn(phydev, "Failed to Set Register[0x17A2]\n"); |
|---|
| 157 | 146 | |
|---|
| 158 | 147 | /* Get access to Channel b'10, Node b'1101, Register 0x10. |
|---|
| 159 | 148 | * Write 24-bit value 0xEEFFDD to register. Setting |
|---|
| .. | .. |
|---|
| 162 | 151 | */ |
|---|
| 163 | 152 | err = lan88xx_TR_reg_set(phydev, 0x16A0, 0xEEFFDD); |
|---|
| 164 | 153 | if (err < 0) |
|---|
| 165 | | - pr_warn("Failed to Set Register[0x16A0]\n"); |
|---|
| 154 | + phydev_warn(phydev, "Failed to Set Register[0x16A0]\n"); |
|---|
| 166 | 155 | |
|---|
| 167 | 156 | /* Get access to Channel b'10, Node b'1101, Register 0x13. |
|---|
| 168 | 157 | * Write 24-bit value 0x071448 to register. Setting |
|---|
| .. | .. |
|---|
| 170 | 159 | */ |
|---|
| 171 | 160 | err = lan88xx_TR_reg_set(phydev, 0x16A6, 0x071448); |
|---|
| 172 | 161 | if (err < 0) |
|---|
| 173 | | - pr_warn("Failed to Set Register[0x16A6]\n"); |
|---|
| 162 | + phydev_warn(phydev, "Failed to Set Register[0x16A6]\n"); |
|---|
| 174 | 163 | |
|---|
| 175 | 164 | /* Get access to Channel b'10, Node b'1101, Register 0x12. |
|---|
| 176 | 165 | * Write 24-bit value 0x13132F to register. Setting |
|---|
| .. | .. |
|---|
| 178 | 167 | */ |
|---|
| 179 | 168 | err = lan88xx_TR_reg_set(phydev, 0x16A4, 0x13132F); |
|---|
| 180 | 169 | if (err < 0) |
|---|
| 181 | | - pr_warn("Failed to Set Register[0x16A4]\n"); |
|---|
| 170 | + phydev_warn(phydev, "Failed to Set Register[0x16A4]\n"); |
|---|
| 182 | 171 | |
|---|
| 183 | 172 | /* Get access to Channel b'10, Node b'1101, Register 0x14. |
|---|
| 184 | 173 | * Write 24-bit value 0x0 to register. Setting eee_3level_delay, |
|---|
| .. | .. |
|---|
| 186 | 175 | */ |
|---|
| 187 | 176 | err = lan88xx_TR_reg_set(phydev, 0x16A8, 0x0); |
|---|
| 188 | 177 | if (err < 0) |
|---|
| 189 | | - pr_warn("Failed to Set Register[0x16A8]\n"); |
|---|
| 178 | + phydev_warn(phydev, "Failed to Set Register[0x16A8]\n"); |
|---|
| 190 | 179 | |
|---|
| 191 | 180 | /* Get access to Channel b'01, Node b'1111, Register 0x34. |
|---|
| 192 | 181 | * Write 24-bit value 0x91B06C to register. Setting |
|---|
| .. | .. |
|---|
| 195 | 184 | */ |
|---|
| 196 | 185 | err = lan88xx_TR_reg_set(phydev, 0x0FE8, 0x91B06C); |
|---|
| 197 | 186 | if (err < 0) |
|---|
| 198 | | - pr_warn("Failed to Set Register[0x0FE8]\n"); |
|---|
| 187 | + phydev_warn(phydev, "Failed to Set Register[0x0FE8]\n"); |
|---|
| 199 | 188 | |
|---|
| 200 | 189 | /* Get access to Channel b'01, Node b'1111, Register 0x3E. |
|---|
| 201 | 190 | * Write 24-bit value 0xC0A028 to register. Setting |
|---|
| .. | .. |
|---|
| 204 | 193 | */ |
|---|
| 205 | 194 | err = lan88xx_TR_reg_set(phydev, 0x0FFC, 0xC0A028); |
|---|
| 206 | 195 | if (err < 0) |
|---|
| 207 | | - pr_warn("Failed to Set Register[0x0FFC]\n"); |
|---|
| 196 | + phydev_warn(phydev, "Failed to Set Register[0x0FFC]\n"); |
|---|
| 208 | 197 | |
|---|
| 209 | 198 | /* Get access to Channel b'01, Node b'1111, Register 0x35. |
|---|
| 210 | 199 | * Write 24-bit value 0x041600 to register. Setting |
|---|
| .. | .. |
|---|
| 213 | 202 | */ |
|---|
| 214 | 203 | err = lan88xx_TR_reg_set(phydev, 0x0FEA, 0x041600); |
|---|
| 215 | 204 | if (err < 0) |
|---|
| 216 | | - pr_warn("Failed to Set Register[0x0FEA]\n"); |
|---|
| 205 | + phydev_warn(phydev, "Failed to Set Register[0x0FEA]\n"); |
|---|
| 217 | 206 | |
|---|
| 218 | 207 | /* Get access to Channel b'10, Node b'1101, Register 0x03. |
|---|
| 219 | 208 | * Write 24-bit value 0x000004 to register. Setting TrFreeze bits. |
|---|
| 220 | 209 | */ |
|---|
| 221 | 210 | err = lan88xx_TR_reg_set(phydev, 0x1686, 0x000004); |
|---|
| 222 | 211 | if (err < 0) |
|---|
| 223 | | - pr_warn("Failed to Set Register[0x1686]\n"); |
|---|
| 212 | + phydev_warn(phydev, "Failed to Set Register[0x1686]\n"); |
|---|
| 224 | 213 | } |
|---|
| 225 | 214 | |
|---|
| 226 | 215 | static int lan88xx_probe(struct phy_device *phydev) |
|---|
| .. | .. |
|---|
| 316 | 305 | { |
|---|
| 317 | 306 | int val; |
|---|
| 318 | 307 | |
|---|
| 319 | | - genphy_config_init(phydev); |
|---|
| 320 | 308 | /*Zerodetect delay enable */ |
|---|
| 321 | 309 | val = phy_read_mmd(phydev, MDIO_MMD_PCS, |
|---|
| 322 | 310 | PHY_ARDENNES_MMD_DEV_3_PHY_CFG); |
|---|
| .. | .. |
|---|
| 338 | 326 | return genphy_config_aneg(phydev); |
|---|
| 339 | 327 | } |
|---|
| 340 | 328 | |
|---|
| 329 | +static void lan88xx_link_change_notify(struct phy_device *phydev) |
|---|
| 330 | +{ |
|---|
| 331 | + int temp; |
|---|
| 332 | + |
|---|
| 333 | + /* At forced 100 F/H mode, chip may fail to set mode correctly |
|---|
| 334 | + * when cable is switched between long(~50+m) and short one. |
|---|
| 335 | + * As workaround, set to 10 before setting to 100 |
|---|
| 336 | + * at forced 100 F/H mode. |
|---|
| 337 | + */ |
|---|
| 338 | + if (!phydev->autoneg && phydev->speed == 100) { |
|---|
| 339 | + /* disable phy interrupt */ |
|---|
| 340 | + temp = phy_read(phydev, LAN88XX_INT_MASK); |
|---|
| 341 | + temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_; |
|---|
| 342 | + phy_write(phydev, LAN88XX_INT_MASK, temp); |
|---|
| 343 | + |
|---|
| 344 | + temp = phy_read(phydev, MII_BMCR); |
|---|
| 345 | + temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000); |
|---|
| 346 | + phy_write(phydev, MII_BMCR, temp); /* set to 10 first */ |
|---|
| 347 | + temp |= BMCR_SPEED100; |
|---|
| 348 | + phy_write(phydev, MII_BMCR, temp); /* set to 100 later */ |
|---|
| 349 | + |
|---|
| 350 | + /* clear pending interrupt generated while workaround */ |
|---|
| 351 | + temp = phy_read(phydev, LAN88XX_INT_STS); |
|---|
| 352 | + |
|---|
| 353 | + /* enable phy interrupt back */ |
|---|
| 354 | + temp = phy_read(phydev, LAN88XX_INT_MASK); |
|---|
| 355 | + temp |= LAN88XX_INT_MASK_MDINTPIN_EN_; |
|---|
| 356 | + phy_write(phydev, LAN88XX_INT_MASK, temp); |
|---|
| 357 | + } |
|---|
| 358 | +} |
|---|
| 359 | + |
|---|
| 341 | 360 | static struct phy_driver microchip_phy_driver[] = { |
|---|
| 342 | 361 | { |
|---|
| 343 | 362 | .phy_id = 0x0007c130, |
|---|
| 344 | 363 | .phy_id_mask = 0xfffffff0, |
|---|
| 345 | 364 | .name = "Microchip LAN88xx", |
|---|
| 346 | 365 | |
|---|
| 347 | | - .features = PHY_GBIT_FEATURES, |
|---|
| 348 | | - .flags = PHY_HAS_INTERRUPT, |
|---|
| 366 | + /* PHY_GBIT_FEATURES */ |
|---|
| 349 | 367 | |
|---|
| 350 | 368 | .probe = lan88xx_probe, |
|---|
| 351 | 369 | .remove = lan88xx_remove, |
|---|
| 352 | 370 | |
|---|
| 353 | 371 | .config_init = lan88xx_config_init, |
|---|
| 354 | 372 | .config_aneg = lan88xx_config_aneg, |
|---|
| 373 | + .link_change_notify = lan88xx_link_change_notify, |
|---|
| 355 | 374 | |
|---|
| 356 | 375 | .ack_interrupt = lan88xx_phy_ack_interrupt, |
|---|
| 357 | 376 | .config_intr = lan88xx_phy_config_intr, |
|---|