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