927 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Driver for the Texas Instruments DP83869 PHY3 * Copyright (C) 2019 Texas Instruments Inc.4 */5 6#include <linux/ethtool.h>7#include <linux/etherdevice.h>8#include <linux/kernel.h>9#include <linux/mii.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/phy.h>13#include <linux/delay.h>14#include <linux/bitfield.h>15 16#include <dt-bindings/net/ti-dp83869.h>17 18#define DP83869_PHY_ID 0x2000a0f119#define DP83561_PHY_ID 0x2000a1a420#define DP83869_DEVADDR 0x1f21 22#define MII_DP83869_PHYCTRL 0x1023#define MII_DP83869_MICR 0x1224#define MII_DP83869_ISR 0x1325#define DP83869_CFG2 0x1426#define DP83869_CTRL 0x1f27#define DP83869_CFG4 0x1e28 29/* Extended Registers */30#define DP83869_GEN_CFG3 0x003131#define DP83869_RGMIICTL 0x003232#define DP83869_STRAP_STS1 0x006e33#define DP83869_RGMIIDCTL 0x008634#define DP83869_RXFCFG 0x013435#define DP83869_RXFPMD1 0x013636#define DP83869_RXFPMD2 0x013737#define DP83869_RXFPMD3 0x013838#define DP83869_RXFSOP1 0x013939#define DP83869_RXFSOP2 0x013A40#define DP83869_RXFSOP3 0x013B41#define DP83869_IO_MUX_CFG 0x017042#define DP83869_OP_MODE 0x01df43#define DP83869_FX_CTRL 0x0c0044 45#define DP83869_SW_RESET BIT(15)46#define DP83869_SW_RESTART BIT(14)47 48/* MICR Interrupt bits */49#define MII_DP83869_MICR_AN_ERR_INT_EN BIT(15)50#define MII_DP83869_MICR_SPEED_CHNG_INT_EN BIT(14)51#define MII_DP83869_MICR_DUP_MODE_CHNG_INT_EN BIT(13)52#define MII_DP83869_MICR_PAGE_RXD_INT_EN BIT(12)53#define MII_DP83869_MICR_AUTONEG_COMP_INT_EN BIT(11)54#define MII_DP83869_MICR_LINK_STS_CHNG_INT_EN BIT(10)55#define MII_DP83869_MICR_FALSE_CARRIER_INT_EN BIT(8)56#define MII_DP83869_MICR_SLEEP_MODE_CHNG_INT_EN BIT(4)57#define MII_DP83869_MICR_WOL_INT_EN BIT(3)58#define MII_DP83869_MICR_XGMII_ERR_INT_EN BIT(2)59#define MII_DP83869_MICR_POL_CHNG_INT_EN BIT(1)60#define MII_DP83869_MICR_JABBER_INT_EN BIT(0)61 62#define MII_DP83869_BMCR_DEFAULT (BMCR_ANENABLE | \63 BMCR_FULLDPLX | \64 BMCR_SPEED1000)65 66#define MII_DP83869_FIBER_ADVERTISE (ADVERTISED_FIBRE | \67 ADVERTISED_Pause | \68 ADVERTISED_Asym_Pause)69 70/* This is the same bit mask as the BMCR so re-use the BMCR default */71#define DP83869_FX_CTRL_DEFAULT MII_DP83869_BMCR_DEFAULT72 73/* CFG1 bits */74#define DP83869_CFG1_DEFAULT (ADVERTISE_1000HALF | \75 ADVERTISE_1000FULL | \76 CTL1000_AS_MASTER)77 78/* RGMIICTL bits */79#define DP83869_RGMII_TX_CLK_DELAY_EN BIT(1)80#define DP83869_RGMII_RX_CLK_DELAY_EN BIT(0)81 82/* RGMIIDCTL */83#define DP83869_RGMII_CLK_DELAY_SHIFT 484#define DP83869_CLK_DELAY_DEF 785 86/* STRAP_STS1 bits */87#define DP83869_STRAP_OP_MODE_MASK GENMASK(2, 0)88#define DP83869_STRAP_STS1_RESERVED BIT(11)89#define DP83869_STRAP_MIRROR_ENABLED BIT(12)90 91/* PHYCTRL bits */92#define DP83869_RX_FIFO_SHIFT 1293#define DP83869_TX_FIFO_SHIFT 1494 95/* PHY_CTRL lower bytes 0x48 are declared as reserved */96#define DP83869_PHY_CTRL_DEFAULT 0x4897#define DP83869_PHYCR_FIFO_DEPTH_MASK GENMASK(15, 12)98#define DP83869_PHYCR_RESERVED_MASK BIT(11)99 100/* IO_MUX_CFG bits */101#define DP83869_IO_MUX_CFG_IO_IMPEDANCE_CTRL 0x1f102 103#define DP83869_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0104#define DP83869_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f105#define DP83869_IO_MUX_CFG_CLK_O_SEL_MASK (0x1f << 8)106#define DP83869_IO_MUX_CFG_CLK_O_SEL_SHIFT 8107 108/* CFG3 bits */109#define DP83869_CFG3_PORT_MIRROR_EN BIT(0)110 111/* CFG4 bits */112#define DP83869_INT_OE BIT(7)113 114/* OP MODE */115#define DP83869_OP_MODE_MII BIT(5)116#define DP83869_SGMII_RGMII_BRIDGE BIT(6)117 118/* RXFCFG bits*/119#define DP83869_WOL_MAGIC_EN BIT(0)120#define DP83869_WOL_PATTERN_EN BIT(1)121#define DP83869_WOL_BCAST_EN BIT(2)122#define DP83869_WOL_UCAST_EN BIT(4)123#define DP83869_WOL_SEC_EN BIT(5)124#define DP83869_WOL_ENH_MAC BIT(7)125 126/* CFG2 bits */127#define DP83869_DOWNSHIFT_EN (BIT(8) | BIT(9))128#define DP83869_DOWNSHIFT_ATTEMPT_MASK (BIT(10) | BIT(11))129#define DP83869_DOWNSHIFT_1_COUNT_VAL 0130#define DP83869_DOWNSHIFT_2_COUNT_VAL 1131#define DP83869_DOWNSHIFT_4_COUNT_VAL 2132#define DP83869_DOWNSHIFT_8_COUNT_VAL 3133#define DP83869_DOWNSHIFT_1_COUNT 1134#define DP83869_DOWNSHIFT_2_COUNT 2135#define DP83869_DOWNSHIFT_4_COUNT 4136#define DP83869_DOWNSHIFT_8_COUNT 8137 138enum {139 DP83869_PORT_MIRRORING_KEEP,140 DP83869_PORT_MIRRORING_EN,141 DP83869_PORT_MIRRORING_DIS,142};143 144struct dp83869_private {145 int tx_fifo_depth;146 int rx_fifo_depth;147 s32 rx_int_delay;148 s32 tx_int_delay;149 int io_impedance;150 int port_mirroring;151 bool rxctrl_strap_quirk;152 int clk_output_sel;153 int mode;154};155 156static int dp83869_read_status(struct phy_device *phydev)157{158 struct dp83869_private *dp83869 = phydev->priv;159 int ret;160 161 ret = genphy_read_status(phydev);162 if (ret)163 return ret;164 165 if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) {166 if (phydev->link) {167 if (dp83869->mode == DP83869_RGMII_100_BASE)168 phydev->speed = SPEED_100;169 } else {170 phydev->speed = SPEED_UNKNOWN;171 phydev->duplex = DUPLEX_UNKNOWN;172 }173 }174 175 return 0;176}177 178static int dp83869_ack_interrupt(struct phy_device *phydev)179{180 int err = phy_read(phydev, MII_DP83869_ISR);181 182 if (err < 0)183 return err;184 185 return 0;186}187 188static int dp83869_config_intr(struct phy_device *phydev)189{190 int micr_status = 0, err;191 192 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {193 err = dp83869_ack_interrupt(phydev);194 if (err)195 return err;196 197 micr_status = phy_read(phydev, MII_DP83869_MICR);198 if (micr_status < 0)199 return micr_status;200 201 micr_status |=202 (MII_DP83869_MICR_AN_ERR_INT_EN |203 MII_DP83869_MICR_SPEED_CHNG_INT_EN |204 MII_DP83869_MICR_AUTONEG_COMP_INT_EN |205 MII_DP83869_MICR_LINK_STS_CHNG_INT_EN |206 MII_DP83869_MICR_DUP_MODE_CHNG_INT_EN |207 MII_DP83869_MICR_SLEEP_MODE_CHNG_INT_EN);208 209 err = phy_write(phydev, MII_DP83869_MICR, micr_status);210 } else {211 err = phy_write(phydev, MII_DP83869_MICR, micr_status);212 if (err)213 return err;214 215 err = dp83869_ack_interrupt(phydev);216 }217 218 return err;219}220 221static irqreturn_t dp83869_handle_interrupt(struct phy_device *phydev)222{223 int irq_status, irq_enabled;224 225 irq_status = phy_read(phydev, MII_DP83869_ISR);226 if (irq_status < 0) {227 phy_error(phydev);228 return IRQ_NONE;229 }230 231 irq_enabled = phy_read(phydev, MII_DP83869_MICR);232 if (irq_enabled < 0) {233 phy_error(phydev);234 return IRQ_NONE;235 }236 237 if (!(irq_status & irq_enabled))238 return IRQ_NONE;239 240 phy_trigger_machine(phydev);241 242 return IRQ_HANDLED;243}244 245static int dp83869_set_wol(struct phy_device *phydev,246 struct ethtool_wolinfo *wol)247{248 struct net_device *ndev = phydev->attached_dev;249 int val_rxcfg, val_micr;250 const u8 *mac;251 int ret;252 253 val_rxcfg = phy_read_mmd(phydev, DP83869_DEVADDR, DP83869_RXFCFG);254 if (val_rxcfg < 0)255 return val_rxcfg;256 257 val_micr = phy_read(phydev, MII_DP83869_MICR);258 if (val_micr < 0)259 return val_micr;260 261 if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |262 WAKE_BCAST)) {263 val_rxcfg |= DP83869_WOL_ENH_MAC;264 val_micr |= MII_DP83869_MICR_WOL_INT_EN;265 266 if (wol->wolopts & WAKE_MAGIC ||267 wol->wolopts & WAKE_MAGICSECURE) {268 mac = (const u8 *)ndev->dev_addr;269 270 if (!is_valid_ether_addr(mac))271 return -EINVAL;272 273 ret = phy_write_mmd(phydev, DP83869_DEVADDR,274 DP83869_RXFPMD1,275 mac[1] << 8 | mac[0]);276 if (ret)277 return ret;278 279 ret = phy_write_mmd(phydev, DP83869_DEVADDR,280 DP83869_RXFPMD2,281 mac[3] << 8 | mac[2]);282 if (ret)283 return ret;284 285 ret = phy_write_mmd(phydev, DP83869_DEVADDR,286 DP83869_RXFPMD3,287 mac[5] << 8 | mac[4]);288 if (ret)289 return ret;290 291 val_rxcfg |= DP83869_WOL_MAGIC_EN;292 } else {293 val_rxcfg &= ~DP83869_WOL_MAGIC_EN;294 }295 296 if (wol->wolopts & WAKE_MAGICSECURE) {297 ret = phy_write_mmd(phydev, DP83869_DEVADDR,298 DP83869_RXFSOP1,299 (wol->sopass[1] << 8) | wol->sopass[0]);300 if (ret)301 return ret;302 303 ret = phy_write_mmd(phydev, DP83869_DEVADDR,304 DP83869_RXFSOP2,305 (wol->sopass[3] << 8) | wol->sopass[2]);306 if (ret)307 return ret;308 ret = phy_write_mmd(phydev, DP83869_DEVADDR,309 DP83869_RXFSOP3,310 (wol->sopass[5] << 8) | wol->sopass[4]);311 if (ret)312 return ret;313 314 val_rxcfg |= DP83869_WOL_SEC_EN;315 } else {316 val_rxcfg &= ~DP83869_WOL_SEC_EN;317 }318 319 if (wol->wolopts & WAKE_UCAST)320 val_rxcfg |= DP83869_WOL_UCAST_EN;321 else322 val_rxcfg &= ~DP83869_WOL_UCAST_EN;323 324 if (wol->wolopts & WAKE_BCAST)325 val_rxcfg |= DP83869_WOL_BCAST_EN;326 else327 val_rxcfg &= ~DP83869_WOL_BCAST_EN;328 } else {329 val_rxcfg &= ~DP83869_WOL_ENH_MAC;330 val_micr &= ~MII_DP83869_MICR_WOL_INT_EN;331 }332 333 ret = phy_write_mmd(phydev, DP83869_DEVADDR, DP83869_RXFCFG, val_rxcfg);334 if (ret)335 return ret;336 337 return phy_write(phydev, MII_DP83869_MICR, val_micr);338}339 340static void dp83869_get_wol(struct phy_device *phydev,341 struct ethtool_wolinfo *wol)342{343 int value, sopass_val;344 345 wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC |346 WAKE_MAGICSECURE);347 wol->wolopts = 0;348 349 value = phy_read_mmd(phydev, DP83869_DEVADDR, DP83869_RXFCFG);350 if (value < 0) {351 phydev_err(phydev, "Failed to read RX CFG\n");352 return;353 }354 355 if (value & DP83869_WOL_UCAST_EN)356 wol->wolopts |= WAKE_UCAST;357 358 if (value & DP83869_WOL_BCAST_EN)359 wol->wolopts |= WAKE_BCAST;360 361 if (value & DP83869_WOL_MAGIC_EN)362 wol->wolopts |= WAKE_MAGIC;363 364 if (value & DP83869_WOL_SEC_EN) {365 sopass_val = phy_read_mmd(phydev, DP83869_DEVADDR,366 DP83869_RXFSOP1);367 if (sopass_val < 0) {368 phydev_err(phydev, "Failed to read RX SOP 1\n");369 return;370 }371 372 wol->sopass[0] = (sopass_val & 0xff);373 wol->sopass[1] = (sopass_val >> 8);374 375 sopass_val = phy_read_mmd(phydev, DP83869_DEVADDR,376 DP83869_RXFSOP2);377 if (sopass_val < 0) {378 phydev_err(phydev, "Failed to read RX SOP 2\n");379 return;380 }381 382 wol->sopass[2] = (sopass_val & 0xff);383 wol->sopass[3] = (sopass_val >> 8);384 385 sopass_val = phy_read_mmd(phydev, DP83869_DEVADDR,386 DP83869_RXFSOP3);387 if (sopass_val < 0) {388 phydev_err(phydev, "Failed to read RX SOP 3\n");389 return;390 }391 392 wol->sopass[4] = (sopass_val & 0xff);393 wol->sopass[5] = (sopass_val >> 8);394 395 wol->wolopts |= WAKE_MAGICSECURE;396 }397 398 if (!(value & DP83869_WOL_ENH_MAC))399 wol->wolopts = 0;400}401 402static int dp83869_get_downshift(struct phy_device *phydev, u8 *data)403{404 int val, cnt, enable, count;405 406 val = phy_read(phydev, DP83869_CFG2);407 if (val < 0)408 return val;409 410 enable = FIELD_GET(DP83869_DOWNSHIFT_EN, val);411 cnt = FIELD_GET(DP83869_DOWNSHIFT_ATTEMPT_MASK, val);412 413 switch (cnt) {414 case DP83869_DOWNSHIFT_1_COUNT_VAL:415 count = DP83869_DOWNSHIFT_1_COUNT;416 break;417 case DP83869_DOWNSHIFT_2_COUNT_VAL:418 count = DP83869_DOWNSHIFT_2_COUNT;419 break;420 case DP83869_DOWNSHIFT_4_COUNT_VAL:421 count = DP83869_DOWNSHIFT_4_COUNT;422 break;423 case DP83869_DOWNSHIFT_8_COUNT_VAL:424 count = DP83869_DOWNSHIFT_8_COUNT;425 break;426 default:427 return -EINVAL;428 }429 430 *data = enable ? count : DOWNSHIFT_DEV_DISABLE;431 432 return 0;433}434 435static int dp83869_set_downshift(struct phy_device *phydev, u8 cnt)436{437 int val, count;438 439 if (cnt > DP83869_DOWNSHIFT_8_COUNT)440 return -EINVAL;441 442 if (!cnt)443 return phy_clear_bits(phydev, DP83869_CFG2,444 DP83869_DOWNSHIFT_EN);445 446 switch (cnt) {447 case DP83869_DOWNSHIFT_1_COUNT:448 count = DP83869_DOWNSHIFT_1_COUNT_VAL;449 break;450 case DP83869_DOWNSHIFT_2_COUNT:451 count = DP83869_DOWNSHIFT_2_COUNT_VAL;452 break;453 case DP83869_DOWNSHIFT_4_COUNT:454 count = DP83869_DOWNSHIFT_4_COUNT_VAL;455 break;456 case DP83869_DOWNSHIFT_8_COUNT:457 count = DP83869_DOWNSHIFT_8_COUNT_VAL;458 break;459 default:460 phydev_err(phydev,461 "Downshift count must be 1, 2, 4 or 8\n");462 return -EINVAL;463 }464 465 val = DP83869_DOWNSHIFT_EN;466 val |= FIELD_PREP(DP83869_DOWNSHIFT_ATTEMPT_MASK, count);467 468 return phy_modify(phydev, DP83869_CFG2,469 DP83869_DOWNSHIFT_EN | DP83869_DOWNSHIFT_ATTEMPT_MASK,470 val);471}472 473static int dp83869_get_tunable(struct phy_device *phydev,474 struct ethtool_tunable *tuna, void *data)475{476 switch (tuna->id) {477 case ETHTOOL_PHY_DOWNSHIFT:478 return dp83869_get_downshift(phydev, data);479 default:480 return -EOPNOTSUPP;481 }482}483 484static int dp83869_set_tunable(struct phy_device *phydev,485 struct ethtool_tunable *tuna, const void *data)486{487 switch (tuna->id) {488 case ETHTOOL_PHY_DOWNSHIFT:489 return dp83869_set_downshift(phydev, *(const u8 *)data);490 default:491 return -EOPNOTSUPP;492 }493}494 495static int dp83869_config_port_mirroring(struct phy_device *phydev)496{497 struct dp83869_private *dp83869 = phydev->priv;498 499 if (dp83869->port_mirroring == DP83869_PORT_MIRRORING_EN)500 return phy_set_bits_mmd(phydev, DP83869_DEVADDR,501 DP83869_GEN_CFG3,502 DP83869_CFG3_PORT_MIRROR_EN);503 else504 return phy_clear_bits_mmd(phydev, DP83869_DEVADDR,505 DP83869_GEN_CFG3,506 DP83869_CFG3_PORT_MIRROR_EN);507}508 509static int dp83869_set_strapped_mode(struct phy_device *phydev)510{511 struct dp83869_private *dp83869 = phydev->priv;512 int val;513 514 val = phy_read_mmd(phydev, DP83869_DEVADDR, DP83869_STRAP_STS1);515 if (val < 0)516 return val;517 518 dp83869->mode = val & DP83869_STRAP_OP_MODE_MASK;519 520 return 0;521}522 523#if IS_ENABLED(CONFIG_OF_MDIO)524static const int dp83869_internal_delay[] = {250, 500, 750, 1000, 1250, 1500,525 1750, 2000, 2250, 2500, 2750, 3000,526 3250, 3500, 3750, 4000};527 528static int dp83869_of_init(struct phy_device *phydev)529{530 struct dp83869_private *dp83869 = phydev->priv;531 struct device *dev = &phydev->mdio.dev;532 struct device_node *of_node = dev->of_node;533 int delay_size = ARRAY_SIZE(dp83869_internal_delay);534 int ret;535 536 if (!of_node)537 return -ENODEV;538 539 dp83869->io_impedance = -EINVAL;540 541 /* Optional configuration */542 ret = of_property_read_u32(of_node, "ti,clk-output-sel",543 &dp83869->clk_output_sel);544 if (ret || dp83869->clk_output_sel > DP83869_CLK_O_SEL_REF_CLK)545 dp83869->clk_output_sel = DP83869_CLK_O_SEL_REF_CLK;546 547 ret = of_property_read_u32(of_node, "ti,op-mode", &dp83869->mode);548 if (ret == 0) {549 if (dp83869->mode < DP83869_RGMII_COPPER_ETHERNET ||550 dp83869->mode > DP83869_SGMII_COPPER_ETHERNET)551 return -EINVAL;552 } else {553 ret = dp83869_set_strapped_mode(phydev);554 if (ret)555 return ret;556 }557 558 if (of_property_read_bool(of_node, "ti,max-output-impedance"))559 dp83869->io_impedance = DP83869_IO_MUX_CFG_IO_IMPEDANCE_MAX;560 else if (of_property_read_bool(of_node, "ti,min-output-impedance"))561 dp83869->io_impedance = DP83869_IO_MUX_CFG_IO_IMPEDANCE_MIN;562 563 if (of_property_read_bool(of_node, "enet-phy-lane-swap")) {564 dp83869->port_mirroring = DP83869_PORT_MIRRORING_EN;565 } else {566 /* If the lane swap is not in the DT then check the straps */567 ret = phy_read_mmd(phydev, DP83869_DEVADDR, DP83869_STRAP_STS1);568 if (ret < 0)569 return ret;570 571 if (ret & DP83869_STRAP_MIRROR_ENABLED)572 dp83869->port_mirroring = DP83869_PORT_MIRRORING_EN;573 else574 dp83869->port_mirroring = DP83869_PORT_MIRRORING_DIS;575 576 ret = 0;577 }578 579 if (of_property_read_u32(of_node, "rx-fifo-depth",580 &dp83869->rx_fifo_depth))581 dp83869->rx_fifo_depth = DP83869_PHYCR_FIFO_DEPTH_4_B_NIB;582 583 if (of_property_read_u32(of_node, "tx-fifo-depth",584 &dp83869->tx_fifo_depth))585 dp83869->tx_fifo_depth = DP83869_PHYCR_FIFO_DEPTH_4_B_NIB;586 587 dp83869->rx_int_delay = phy_get_internal_delay(phydev, dev,588 &dp83869_internal_delay[0],589 delay_size, true);590 if (dp83869->rx_int_delay < 0)591 dp83869->rx_int_delay = DP83869_CLK_DELAY_DEF;592 593 dp83869->tx_int_delay = phy_get_internal_delay(phydev, dev,594 &dp83869_internal_delay[0],595 delay_size, false);596 if (dp83869->tx_int_delay < 0)597 dp83869->tx_int_delay = DP83869_CLK_DELAY_DEF;598 599 return ret;600}601#else602static int dp83869_of_init(struct phy_device *phydev)603{604 return dp83869_set_strapped_mode(phydev);605}606#endif /* CONFIG_OF_MDIO */607 608static int dp83869_configure_rgmii(struct phy_device *phydev,609 struct dp83869_private *dp83869)610{611 int ret = 0, val;612 613 if (phy_interface_is_rgmii(phydev)) {614 val = phy_read(phydev, MII_DP83869_PHYCTRL);615 if (val < 0)616 return val;617 618 val &= ~DP83869_PHYCR_FIFO_DEPTH_MASK;619 val |= (dp83869->tx_fifo_depth << DP83869_TX_FIFO_SHIFT);620 val |= (dp83869->rx_fifo_depth << DP83869_RX_FIFO_SHIFT);621 622 ret = phy_write(phydev, MII_DP83869_PHYCTRL, val);623 if (ret)624 return ret;625 }626 627 if (dp83869->io_impedance >= 0)628 ret = phy_modify_mmd(phydev, DP83869_DEVADDR,629 DP83869_IO_MUX_CFG,630 DP83869_IO_MUX_CFG_IO_IMPEDANCE_CTRL,631 dp83869->io_impedance &632 DP83869_IO_MUX_CFG_IO_IMPEDANCE_CTRL);633 634 return ret;635}636 637static int dp83869_configure_fiber(struct phy_device *phydev,638 struct dp83869_private *dp83869)639{640 int bmcr;641 int ret;642 643 /* Only allow advertising what this PHY supports */644 linkmode_and(phydev->advertising, phydev->advertising,645 phydev->supported);646 647 linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);648 649 if (dp83869->mode == DP83869_RGMII_1000_BASE) {650 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,651 phydev->supported);652 } else {653 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,654 phydev->supported);655 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,656 phydev->supported);657 658 /* Auto neg is not supported in 100base FX mode */659 bmcr = phy_read(phydev, MII_BMCR);660 if (bmcr < 0)661 return bmcr;662 663 phydev->autoneg = AUTONEG_DISABLE;664 linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);665 linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->advertising);666 667 if (bmcr & BMCR_ANENABLE) {668 ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);669 if (ret < 0)670 return ret;671 }672 }673 674 /* Update advertising from supported */675 linkmode_or(phydev->advertising, phydev->advertising,676 phydev->supported);677 678 return 0;679}680 681static int dp83869_configure_mode(struct phy_device *phydev,682 struct dp83869_private *dp83869)683{684 int phy_ctrl_val;685 int ret;686 687 if (dp83869->mode < DP83869_RGMII_COPPER_ETHERNET ||688 dp83869->mode > DP83869_SGMII_COPPER_ETHERNET)689 return -EINVAL;690 691 /* Below init sequence for each operational mode is defined in692 * section 9.4.8 of the datasheet.693 */694 phy_ctrl_val = dp83869->mode;695 if (phydev->interface == PHY_INTERFACE_MODE_MII) {696 if (dp83869->mode == DP83869_100M_MEDIA_CONVERT ||697 dp83869->mode == DP83869_RGMII_100_BASE ||698 dp83869->mode == DP83869_RGMII_COPPER_ETHERNET) {699 phy_ctrl_val |= DP83869_OP_MODE_MII;700 } else {701 phydev_err(phydev, "selected op-mode is not valid with MII mode\n");702 return -EINVAL;703 }704 }705 706 ret = phy_write_mmd(phydev, DP83869_DEVADDR, DP83869_OP_MODE,707 phy_ctrl_val);708 if (ret)709 return ret;710 711 ret = phy_write(phydev, MII_BMCR, MII_DP83869_BMCR_DEFAULT);712 if (ret)713 return ret;714 715 phy_ctrl_val = (dp83869->rx_fifo_depth << DP83869_RX_FIFO_SHIFT |716 dp83869->tx_fifo_depth << DP83869_TX_FIFO_SHIFT |717 DP83869_PHY_CTRL_DEFAULT);718 719 switch (dp83869->mode) {720 case DP83869_RGMII_COPPER_ETHERNET:721 ret = phy_write(phydev, MII_DP83869_PHYCTRL,722 phy_ctrl_val);723 if (ret)724 return ret;725 726 ret = phy_write(phydev, MII_CTRL1000, DP83869_CFG1_DEFAULT);727 if (ret)728 return ret;729 730 ret = dp83869_configure_rgmii(phydev, dp83869);731 if (ret)732 return ret;733 break;734 case DP83869_RGMII_SGMII_BRIDGE:735 ret = phy_modify_mmd(phydev, DP83869_DEVADDR, DP83869_OP_MODE,736 DP83869_SGMII_RGMII_BRIDGE,737 DP83869_SGMII_RGMII_BRIDGE);738 if (ret)739 return ret;740 741 ret = phy_write_mmd(phydev, DP83869_DEVADDR,742 DP83869_FX_CTRL, DP83869_FX_CTRL_DEFAULT);743 if (ret)744 return ret;745 746 break;747 case DP83869_1000M_MEDIA_CONVERT:748 ret = phy_write(phydev, MII_DP83869_PHYCTRL,749 phy_ctrl_val);750 if (ret)751 return ret;752 753 ret = phy_write_mmd(phydev, DP83869_DEVADDR,754 DP83869_FX_CTRL, DP83869_FX_CTRL_DEFAULT);755 if (ret)756 return ret;757 break;758 case DP83869_100M_MEDIA_CONVERT:759 ret = phy_write(phydev, MII_DP83869_PHYCTRL,760 phy_ctrl_val);761 if (ret)762 return ret;763 break;764 case DP83869_SGMII_COPPER_ETHERNET:765 ret = phy_write(phydev, MII_DP83869_PHYCTRL,766 phy_ctrl_val);767 if (ret)768 return ret;769 770 ret = phy_write(phydev, MII_CTRL1000, DP83869_CFG1_DEFAULT);771 if (ret)772 return ret;773 774 ret = phy_write_mmd(phydev, DP83869_DEVADDR,775 DP83869_FX_CTRL, DP83869_FX_CTRL_DEFAULT);776 if (ret)777 return ret;778 779 break;780 case DP83869_RGMII_1000_BASE:781 case DP83869_RGMII_100_BASE:782 ret = dp83869_configure_fiber(phydev, dp83869);783 break;784 default:785 return -EINVAL;786 }787 788 return ret;789}790 791static int dp83869_config_init(struct phy_device *phydev)792{793 struct dp83869_private *dp83869 = phydev->priv;794 int ret, val;795 796 /* Force speed optimization for the PHY even if it strapped */797 ret = phy_modify(phydev, DP83869_CFG2, DP83869_DOWNSHIFT_EN,798 DP83869_DOWNSHIFT_EN);799 if (ret)800 return ret;801 802 ret = dp83869_configure_mode(phydev, dp83869);803 if (ret)804 return ret;805 806 /* Enable Interrupt output INT_OE in CFG4 register */807 if (phy_interrupt_is_valid(phydev)) {808 val = phy_read(phydev, DP83869_CFG4);809 val |= DP83869_INT_OE;810 phy_write(phydev, DP83869_CFG4, val);811 }812 813 if (dp83869->port_mirroring != DP83869_PORT_MIRRORING_KEEP)814 dp83869_config_port_mirroring(phydev);815 816 /* Clock output selection if muxing property is set */817 if (dp83869->clk_output_sel != DP83869_CLK_O_SEL_REF_CLK)818 ret = phy_modify_mmd(phydev,819 DP83869_DEVADDR, DP83869_IO_MUX_CFG,820 DP83869_IO_MUX_CFG_CLK_O_SEL_MASK,821 dp83869->clk_output_sel <<822 DP83869_IO_MUX_CFG_CLK_O_SEL_SHIFT);823 824 if (phy_interface_is_rgmii(phydev)) {825 ret = phy_write_mmd(phydev, DP83869_DEVADDR, DP83869_RGMIIDCTL,826 dp83869->rx_int_delay |827 dp83869->tx_int_delay << DP83869_RGMII_CLK_DELAY_SHIFT);828 if (ret)829 return ret;830 831 val = phy_read_mmd(phydev, DP83869_DEVADDR, DP83869_RGMIICTL);832 val |= (DP83869_RGMII_TX_CLK_DELAY_EN |833 DP83869_RGMII_RX_CLK_DELAY_EN);834 835 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)836 val &= ~(DP83869_RGMII_TX_CLK_DELAY_EN |837 DP83869_RGMII_RX_CLK_DELAY_EN);838 839 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)840 val &= ~DP83869_RGMII_TX_CLK_DELAY_EN;841 842 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)843 val &= ~DP83869_RGMII_RX_CLK_DELAY_EN;844 845 ret = phy_write_mmd(phydev, DP83869_DEVADDR, DP83869_RGMIICTL,846 val);847 }848 849 return ret;850}851 852static int dp83869_probe(struct phy_device *phydev)853{854 struct dp83869_private *dp83869;855 int ret;856 857 dp83869 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83869),858 GFP_KERNEL);859 if (!dp83869)860 return -ENOMEM;861 862 phydev->priv = dp83869;863 864 ret = dp83869_of_init(phydev);865 if (ret)866 return ret;867 868 if (dp83869->mode == DP83869_RGMII_100_BASE ||869 dp83869->mode == DP83869_RGMII_1000_BASE)870 phydev->port = PORT_FIBRE;871 872 return dp83869_config_init(phydev);873}874 875static int dp83869_phy_reset(struct phy_device *phydev)876{877 int ret;878 879 ret = phy_write(phydev, DP83869_CTRL, DP83869_SW_RESET);880 if (ret < 0)881 return ret;882 883 usleep_range(10, 20);884 885 /* Global sw reset sets all registers to default.886 * Need to set the registers in the PHY to the right config.887 */888 return dp83869_config_init(phydev);889}890 891 892#define DP83869_PHY_DRIVER(_id, _name) \893{ \894 PHY_ID_MATCH_MODEL(_id), \895 .name = (_name), \896 .probe = dp83869_probe, \897 .config_init = dp83869_config_init, \898 .soft_reset = dp83869_phy_reset, \899 .config_intr = dp83869_config_intr, \900 .handle_interrupt = dp83869_handle_interrupt, \901 .read_status = dp83869_read_status, \902 .get_tunable = dp83869_get_tunable, \903 .set_tunable = dp83869_set_tunable, \904 .get_wol = dp83869_get_wol, \905 .set_wol = dp83869_set_wol, \906 .suspend = genphy_suspend, \907 .resume = genphy_resume, \908}909 910static struct phy_driver dp83869_driver[] = {911 DP83869_PHY_DRIVER(DP83869_PHY_ID, "TI DP83869"),912 DP83869_PHY_DRIVER(DP83561_PHY_ID, "TI DP83561-SP"),913 914};915module_phy_driver(dp83869_driver);916 917static struct mdio_device_id __maybe_unused dp83869_tbl[] = {918 { PHY_ID_MATCH_MODEL(DP83869_PHY_ID) },919 { PHY_ID_MATCH_MODEL(DP83561_PHY_ID) },920 { }921};922MODULE_DEVICE_TABLE(mdio, dp83869_tbl);923 924MODULE_DESCRIPTION("Texas Instruments DP83869 PHY driver");925MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");926MODULE_LICENSE("GPL v2");927