Lines Matching +full:force +full:- +full:internal +full:- +full:phy

1 // SPDX-License-Identifier: GPL-2.0
2 /* Driver for the Texas Instruments DP83867 PHY
12 #include <linux/phy.h>
17 #include <linux/nvmem-consumer.h>
19 #include <dt-bindings/net/ti-dp83867.h>
102 /* PHY CTRL bits */
127 /* PHY STS bits */
211 struct net_device *ndev = phydev->attached_dev; in dp83867_set_wol()
218 if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST | in dp83867_set_wol()
223 if (wol->wolopts & WAKE_MAGIC) { in dp83867_set_wol()
224 mac = (const u8 *)ndev->dev_addr; in dp83867_set_wol()
227 return -EINVAL; in dp83867_set_wol()
241 if (wol->wolopts & WAKE_MAGICSECURE) { in dp83867_set_wol()
243 (wol->sopass[1] << 8) | wol->sopass[0]); in dp83867_set_wol()
245 (wol->sopass[3] << 8) | wol->sopass[2]); in dp83867_set_wol()
247 (wol->sopass[5] << 8) | wol->sopass[4]); in dp83867_set_wol()
254 if (wol->wolopts & WAKE_UCAST) in dp83867_set_wol()
259 if (wol->wolopts & WAKE_BCAST) in dp83867_set_wol()
279 wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC | in dp83867_get_wol()
281 wol->wolopts = 0; in dp83867_get_wol()
286 wol->wolopts |= WAKE_UCAST; in dp83867_get_wol()
289 wol->wolopts |= WAKE_BCAST; in dp83867_get_wol()
292 wol->wolopts |= WAKE_MAGIC; in dp83867_get_wol()
297 wol->sopass[0] = (sopass_val & 0xff); in dp83867_get_wol()
298 wol->sopass[1] = (sopass_val >> 8); in dp83867_get_wol()
302 wol->sopass[2] = (sopass_val & 0xff); in dp83867_get_wol()
303 wol->sopass[3] = (sopass_val >> 8); in dp83867_get_wol()
307 wol->sopass[4] = (sopass_val & 0xff); in dp83867_get_wol()
308 wol->sopass[5] = (sopass_val >> 8); in dp83867_get_wol()
310 wol->wolopts |= WAKE_MAGICSECURE; in dp83867_get_wol()
314 wol->wolopts = 0; in dp83867_get_wol()
321 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { in dp83867_config_intr()
388 phydev->duplex = DUPLEX_FULL; in dp83867_read_status()
390 phydev->duplex = DUPLEX_HALF; in dp83867_read_status()
393 phydev->speed = SPEED_1000; in dp83867_read_status()
395 phydev->speed = SPEED_100; in dp83867_read_status()
397 phydev->speed = SPEED_10; in dp83867_read_status()
427 return -EINVAL; in dp83867_get_downshift()
440 return -E2BIG; in dp83867_set_downshift()
462 return -EINVAL; in dp83867_set_downshift()
476 switch (tuna->id) { in dp83867_get_tunable()
480 return -EOPNOTSUPP; in dp83867_get_tunable()
487 switch (tuna->id) { in dp83867_set_tunable()
491 return -EOPNOTSUPP; in dp83867_set_tunable()
497 struct dp83867_private *dp83867 = phydev->priv; in dp83867_config_port_mirroring()
499 if (dp83867->port_mirroring == DP83867_PORT_MIRROING_EN) in dp83867_config_port_mirroring()
510 struct dp83867_private *dp83867 = phydev->priv; in dp83867_verify_rgmii_cfg()
515 if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { in dp83867_verify_rgmii_cfg()
526 "PHY has delays via pin strapping, but phy-mode = 'rgmii'\n" in dp83867_verify_rgmii_cfg()
527 "Should be 'rgmii-id' to use internal delays txskew:%x rxskew:%x\n", in dp83867_verify_rgmii_cfg()
531 /* RX delay *must* be specified if internal delay of RX is used. */ in dp83867_verify_rgmii_cfg()
532 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || in dp83867_verify_rgmii_cfg()
533 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) && in dp83867_verify_rgmii_cfg()
534 dp83867->rx_id_delay == DP83867_RGMII_RX_CLK_DELAY_INV) { in dp83867_verify_rgmii_cfg()
535 phydev_err(phydev, "ti,rx-internal-delay must be specified\n"); in dp83867_verify_rgmii_cfg()
536 return -EINVAL; in dp83867_verify_rgmii_cfg()
539 /* TX delay *must* be specified if internal delay of TX is used. */ in dp83867_verify_rgmii_cfg()
540 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || in dp83867_verify_rgmii_cfg()
541 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) && in dp83867_verify_rgmii_cfg()
542 dp83867->tx_id_delay == DP83867_RGMII_TX_CLK_DELAY_INV) { in dp83867_verify_rgmii_cfg()
543 phydev_err(phydev, "ti,tx-internal-delay must be specified\n"); in dp83867_verify_rgmii_cfg()
544 return -EINVAL; in dp83867_verify_rgmii_cfg()
553 struct dp83867_private *dp83867 = phydev->priv; in dp83867_of_init_io_impedance()
554 struct device *dev = &phydev->mdio.dev; in dp83867_of_init_io_impedance()
555 struct device_node *of_node = dev->of_node; in dp83867_of_init_io_impedance()
563 if (ret != -ENOENT && ret != -EOPNOTSUPP) in dp83867_of_init_io_impedance()
568 if (of_property_read_bool(of_node, "ti,max-output-impedance")) in dp83867_of_init_io_impedance()
569 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; in dp83867_of_init_io_impedance()
570 else if (of_property_read_bool(of_node, "ti,min-output-impedance")) in dp83867_of_init_io_impedance()
571 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN; in dp83867_of_init_io_impedance()
573 dp83867->io_impedance = -1; /* leave at default */ in dp83867_of_init_io_impedance()
589 return -ERANGE; in dp83867_of_init_io_impedance()
591 dp83867->io_impedance = val; in dp83867_of_init_io_impedance()
598 struct dp83867_private *dp83867 = phydev->priv; in dp83867_of_init()
599 struct device *dev = &phydev->mdio.dev; in dp83867_of_init()
600 struct device_node *of_node = dev->of_node; in dp83867_of_init()
604 return -ENODEV; in dp83867_of_init()
607 ret = of_property_read_u32(of_node, "ti,clk-output-sel", in dp83867_of_init()
608 &dp83867->clk_output_sel); in dp83867_of_init()
611 dp83867->set_clk_output = true; in dp83867_of_init()
615 if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK && in dp83867_of_init()
616 dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) { in dp83867_of_init()
617 phydev_err(phydev, "ti,clk-output-sel value %u out of range\n", in dp83867_of_init()
618 dp83867->clk_output_sel); in dp83867_of_init()
619 return -EINVAL; in dp83867_of_init()
627 dp83867->rxctrl_strap_quirk = of_property_read_bool(of_node, in dp83867_of_init()
628 "ti,dp83867-rxctrl-strap-quirk"); in dp83867_of_init()
630 dp83867->sgmii_ref_clk_en = of_property_read_bool(of_node, in dp83867_of_init()
631 "ti,sgmii-ref-clock-output-enable"); in dp83867_of_init()
633 dp83867->rx_id_delay = DP83867_RGMII_RX_CLK_DELAY_INV; in dp83867_of_init()
634 ret = of_property_read_u32(of_node, "ti,rx-internal-delay", in dp83867_of_init()
635 &dp83867->rx_id_delay); in dp83867_of_init()
636 if (!ret && dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) { in dp83867_of_init()
638 "ti,rx-internal-delay value of %u out of range\n", in dp83867_of_init()
639 dp83867->rx_id_delay); in dp83867_of_init()
640 return -EINVAL; in dp83867_of_init()
643 dp83867->tx_id_delay = DP83867_RGMII_TX_CLK_DELAY_INV; in dp83867_of_init()
644 ret = of_property_read_u32(of_node, "ti,tx-internal-delay", in dp83867_of_init()
645 &dp83867->tx_id_delay); in dp83867_of_init()
646 if (!ret && dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) { in dp83867_of_init()
648 "ti,tx-internal-delay value of %u out of range\n", in dp83867_of_init()
649 dp83867->tx_id_delay); in dp83867_of_init()
650 return -EINVAL; in dp83867_of_init()
653 if (of_property_read_bool(of_node, "enet-phy-lane-swap")) in dp83867_of_init()
654 dp83867->port_mirroring = DP83867_PORT_MIRROING_EN; in dp83867_of_init()
656 if (of_property_read_bool(of_node, "enet-phy-lane-no-swap")) in dp83867_of_init()
657 dp83867->port_mirroring = DP83867_PORT_MIRROING_DIS; in dp83867_of_init()
659 ret = of_property_read_u32(of_node, "ti,fifo-depth", in dp83867_of_init()
660 &dp83867->tx_fifo_depth); in dp83867_of_init()
662 ret = of_property_read_u32(of_node, "tx-fifo-depth", in dp83867_of_init()
663 &dp83867->tx_fifo_depth); in dp83867_of_init()
665 dp83867->tx_fifo_depth = in dp83867_of_init()
669 if (dp83867->tx_fifo_depth > DP83867_PHYCR_FIFO_DEPTH_MAX) { in dp83867_of_init()
670 phydev_err(phydev, "tx-fifo-depth value %u out of range\n", in dp83867_of_init()
671 dp83867->tx_fifo_depth); in dp83867_of_init()
672 return -EINVAL; in dp83867_of_init()
675 ret = of_property_read_u32(of_node, "rx-fifo-depth", in dp83867_of_init()
676 &dp83867->rx_fifo_depth); in dp83867_of_init()
678 dp83867->rx_fifo_depth = DP83867_PHYCR_FIFO_DEPTH_4_B_NIB; in dp83867_of_init()
680 if (dp83867->rx_fifo_depth > DP83867_PHYCR_FIFO_DEPTH_MAX) { in dp83867_of_init()
681 phydev_err(phydev, "rx-fifo-depth value %u out of range\n", in dp83867_of_init()
682 dp83867->rx_fifo_depth); in dp83867_of_init()
683 return -EINVAL; in dp83867_of_init()
691 struct dp83867_private *dp83867 = phydev->priv; in dp83867_of_init()
694 /* For non-OF device, the RX and TX ID values are either strapped in dp83867_of_init()
700 dp83867->rx_id_delay = delay & DP83867_RGMII_RX_CLK_DELAY_MAX; in dp83867_of_init()
701 dp83867->tx_id_delay = (delay >> DP83867_RGMII_TX_CLK_DELAY_SHIFT) & in dp83867_of_init()
704 /* Per datasheet, IO impedance is default to 50-ohm, so we set the in dp83867_of_init()
708 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN / 2; in dp83867_of_init()
710 /* For non-OF device, the RX and TX FIFO depths are taken from in dp83867_of_init()
714 dp83867->tx_fifo_depth = DP83867_PHYCR_FIFO_DEPTH_4_B_NIB; in dp83867_of_init()
715 dp83867->rx_fifo_depth = DP83867_PHYCR_FIFO_DEPTH_4_B_NIB; in dp83867_of_init()
723 /* Disable PHY Interrupts */ in dp83867_suspend()
725 phydev->interrupts = PHY_INTERRUPT_DISABLED; in dp83867_suspend()
734 /* Enable PHY Interrupts */ in dp83867_resume()
736 phydev->interrupts = PHY_INTERRUPT_ENABLED; in dp83867_resume()
749 dp83867 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83867), in dp83867_probe()
752 return -ENOMEM; in dp83867_probe()
754 phydev->priv = dp83867; in dp83867_probe()
761 struct dp83867_private *dp83867 = phydev->priv; in dp83867_config_init()
765 /* Force speed optimization for the PHY even if it strapped */ in dp83867_config_init()
776 if (dp83867->rxctrl_strap_quirk) in dp83867_config_init()
783 * be set to 0x2. This may causes the PHY link to be unstable - in dp83867_config_init()
795 phydev->interface == PHY_INTERFACE_MODE_SGMII) { in dp83867_config_init()
801 val |= (dp83867->tx_fifo_depth << in dp83867_config_init()
804 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { in dp83867_config_init()
806 val |= (dp83867->rx_fifo_depth << in dp83867_config_init()
823 * Such N/A mode enabled by mistake can put PHY IC in some in dp83867_config_init()
824 * internal testing mode and disable RGMII transmission. in dp83867_config_init()
838 /* If rgmii mode with no internal delay is selected, we do NOT use in dp83867_config_init()
839 * aligned mode as one might expect. Instead we use the PHY's default in dp83867_config_init()
841 * internal delay with a value of 7 (2.00 ns). in dp83867_config_init()
848 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) in dp83867_config_init()
851 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) in dp83867_config_init()
854 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) in dp83867_config_init()
860 if (dp83867->rx_id_delay != DP83867_RGMII_RX_CLK_DELAY_INV) in dp83867_config_init()
861 delay |= dp83867->rx_id_delay; in dp83867_config_init()
862 if (dp83867->tx_id_delay != DP83867_RGMII_TX_CLK_DELAY_INV) in dp83867_config_init()
863 delay |= dp83867->tx_id_delay << in dp83867_config_init()
871 if (dp83867->io_impedance >= 0) in dp83867_config_init()
874 dp83867->io_impedance); in dp83867_config_init()
876 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { in dp83867_config_init()
903 /* SGMII type is set to 4-wire mode by default. in dp83867_config_init()
905 * switch on 6-wire mode. in dp83867_config_init()
907 if (dp83867->sgmii_ref_clk_en) in dp83867_config_init()
917 if (dp83867->rxctrl_strap_quirk) in dp83867_config_init()
930 if (dp83867->port_mirroring != DP83867_PORT_MIRROING_KEEP) in dp83867_config_init()
934 if (dp83867->set_clk_output) { in dp83867_config_init()
937 if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) { in dp83867_config_init()
941 val = dp83867->clk_output_sel << in dp83867_config_init()
987 /* There is a limitation in DP83867 PHY device where SGMII AN is in dp83867_link_change_notify()
989 * PHY TPI is down and up again, SGMII AN is not triggered and in dp83867_link_change_notify()
990 * hence no new in-band message from PHY to MAC side SGMII. in dp83867_link_change_notify()
991 * This could cause an issue during power up, when PHY is up prior in dp83867_link_change_notify()
993 * SGMII wouldn`t receive new in-band message from TI PHY with in dp83867_link_change_notify()
995 * Thus, implemented a SW solution here to retrigger SGMII Auto-Neg in dp83867_link_change_notify()
998 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { in dp83867_link_change_notify()
1024 return -EINVAL; in dp83867_led_brightness_set()
1041 return -EINVAL; in dp83867_led_mode()
1067 return -EOPNOTSUPP; in dp83867_led_mode()
1198 MODULE_DESCRIPTION("Texas Instruments DP83867 PHY driver");