^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Analog Devices Industrial Ethernet PHYs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2019 Analog Devices Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/bitfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define PHY_ID_ADIN1200 0x0283bc20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define PHY_ID_ADIN1300 0x0283bc30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define ADIN1300_MII_EXT_REG_PTR 0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define ADIN1300_MII_EXT_REG_DATA 0x0011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define ADIN1300_PHY_CTRL1 0x0012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define ADIN1300_AUTO_MDI_EN BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define ADIN1300_MAN_MDIX_EN BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define ADIN1300_RX_ERR_CNT 0x0014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define ADIN1300_PHY_CTRL_STATUS2 0x0015
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define ADIN1300_NRG_PD_EN BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define ADIN1300_NRG_PD_TX_EN BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ADIN1300_NRG_PD_STATUS BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define ADIN1300_PHY_CTRL2 0x0016
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define ADIN1300_DOWNSPEED_AN_100_EN BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define ADIN1300_DOWNSPEED_AN_10_EN BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define ADIN1300_GROUP_MDIO_EN BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define ADIN1300_DOWNSPEEDS_EN \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) (ADIN1300_DOWNSPEED_AN_100_EN | ADIN1300_DOWNSPEED_AN_10_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define ADIN1300_PHY_CTRL3 0x0017
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define ADIN1300_LINKING_EN BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define ADIN1300_DOWNSPEED_RETRIES_MSK GENMASK(12, 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define ADIN1300_INT_MASK_REG 0x0018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define ADIN1300_INT_MDIO_SYNC_EN BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define ADIN1300_INT_ANEG_STAT_CHNG_EN BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define ADIN1300_INT_ANEG_PAGE_RX_EN BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define ADIN1300_INT_IDLE_ERR_CNT_EN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define ADIN1300_INT_MAC_FIFO_OU_EN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define ADIN1300_INT_RX_STAT_CHNG_EN BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define ADIN1300_INT_LINK_STAT_CHNG_EN BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define ADIN1300_INT_SPEED_CHNG_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define ADIN1300_INT_HW_IRQ_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define ADIN1300_INT_MASK_EN \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) (ADIN1300_INT_LINK_STAT_CHNG_EN | ADIN1300_INT_HW_IRQ_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define ADIN1300_INT_STATUS_REG 0x0019
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define ADIN1300_PHY_STATUS1 0x001a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define ADIN1300_PAIR_01_SWAP BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* EEE register addresses, accessible via Clause 22 access using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * ADIN1300_MII_EXT_REG_PTR & ADIN1300_MII_EXT_REG_DATA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * The bit-fields are the same as specified by IEEE for EEE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define ADIN1300_EEE_CAP_REG 0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define ADIN1300_EEE_ADV_REG 0x8001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define ADIN1300_EEE_LPABLE_REG 0x8002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define ADIN1300_CLOCK_STOP_REG 0x9400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define ADIN1300_LPI_WAKE_ERR_CNT_REG 0xa000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define ADIN1300_GE_SOFT_RESET_REG 0xff0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define ADIN1300_GE_SOFT_RESET BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define ADIN1300_GE_RGMII_CFG_REG 0xff23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define ADIN1300_GE_RGMII_RX_SEL(x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) FIELD_PREP(ADIN1300_GE_RGMII_RX_MSK, x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define ADIN1300_GE_RGMII_GTX_MSK GENMASK(5, 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define ADIN1300_GE_RGMII_GTX_SEL(x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) FIELD_PREP(ADIN1300_GE_RGMII_GTX_MSK, x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define ADIN1300_GE_RGMII_RXID_EN BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define ADIN1300_GE_RGMII_TXID_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define ADIN1300_GE_RGMII_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* RGMII internal delay settings for rx and tx for ADIN1300 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define ADIN1300_RGMII_1_60_NS 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define ADIN1300_RGMII_1_80_NS 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define ADIN1300_RGMII_2_00_NS 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define ADIN1300_RGMII_2_20_NS 0x0006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define ADIN1300_RGMII_2_40_NS 0x0007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define ADIN1300_GE_RMII_CFG_REG 0xff24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define ADIN1300_GE_RMII_FIFO_DEPTH_MSK GENMASK(6, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define ADIN1300_GE_RMII_FIFO_DEPTH_SEL(x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) FIELD_PREP(ADIN1300_GE_RMII_FIFO_DEPTH_MSK, x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define ADIN1300_GE_RMII_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* RMII fifo depth values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define ADIN1300_RMII_4_BITS 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define ADIN1300_RMII_8_BITS 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define ADIN1300_RMII_12_BITS 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define ADIN1300_RMII_16_BITS 0x0003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define ADIN1300_RMII_20_BITS 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define ADIN1300_RMII_24_BITS 0x0005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * struct adin_cfg_reg_map - map a config value to aregister value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @cfg: value in device configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @reg: value in the register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct adin_cfg_reg_map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static const struct adin_cfg_reg_map adin_rgmii_delays[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { 1600, ADIN1300_RGMII_1_60_NS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { 1800, ADIN1300_RGMII_1_80_NS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { 2000, ADIN1300_RGMII_2_00_NS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { 2200, ADIN1300_RGMII_2_20_NS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { 2400, ADIN1300_RGMII_2_40_NS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const struct adin_cfg_reg_map adin_rmii_fifo_depths[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { 4, ADIN1300_RMII_4_BITS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { 8, ADIN1300_RMII_8_BITS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { 12, ADIN1300_RMII_12_BITS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { 16, ADIN1300_RMII_16_BITS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { 20, ADIN1300_RMII_20_BITS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { 24, ADIN1300_RMII_24_BITS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * struct adin_clause45_mmd_map - map to convert Clause 45 regs to Clause 22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * @devad: device address used in Clause 45 access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * @cl45_regnum: register address defined by Clause 45
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * @adin_regnum: equivalent register address accessible via Clause 22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct adin_clause45_mmd_map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int devad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u16 cl45_regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u16 adin_regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static const struct adin_clause45_mmd_map adin_clause45_mmd_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE, ADIN1300_EEE_CAP_REG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { MDIO_MMD_AN, MDIO_AN_EEE_LPABLE, ADIN1300_EEE_LPABLE_REG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) { MDIO_MMD_AN, MDIO_AN_EEE_ADV, ADIN1300_EEE_ADV_REG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { MDIO_MMD_PCS, MDIO_CTRL1, ADIN1300_CLOCK_STOP_REG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { MDIO_MMD_PCS, MDIO_PCS_EEE_WK_ERR, ADIN1300_LPI_WAKE_ERR_CNT_REG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct adin_hw_stat {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) const char *string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u16 reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u16 reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static const struct adin_hw_stat adin_hw_stats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { "total_frames_checked_count", 0x940A, 0x940B }, /* hi + lo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) { "length_error_frames_count", 0x940C },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { "alignment_error_frames_count", 0x940D },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { "symbol_error_count", 0x940E },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { "oversized_frames_count", 0x940F },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) { "undersized_frames_count", 0x9410 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) { "odd_nibble_frames_count", 0x9411 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) { "odd_preamble_packet_count", 0x9412 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) { "dribble_bits_frames_count", 0x9413 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) { "false_carrier_events_count", 0x9414 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * struct adin_priv - ADIN PHY driver private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @stats: statistic counters for the PHY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct adin_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u64 stats[ARRAY_SIZE(adin_hw_stats)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static int adin_lookup_reg_value(const struct adin_cfg_reg_map *tbl, int cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) for (i = 0; tbl[i].cfg; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (tbl[i].cfg == cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return tbl[i].reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static u32 adin_get_reg_value(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) const char *prop_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) const struct adin_cfg_reg_map *tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u32 dflt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct device *dev = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (device_property_read_u32(dev, prop_name, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return dflt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) rc = adin_lookup_reg_value(tbl, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) phydev_warn(phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) "Unsupported value %u for %s using default (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) val, prop_name, dflt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return dflt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int adin_config_rgmii_mode(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!phy_interface_is_rgmii(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ADIN1300_GE_RGMII_CFG_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ADIN1300_GE_RGMII_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_GE_RGMII_CFG_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) reg |= ADIN1300_GE_RGMII_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) reg |= ADIN1300_GE_RGMII_RXID_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) val = adin_get_reg_value(phydev, "adi,rx-internal-delay-ps",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) adin_rgmii_delays,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ADIN1300_RGMII_2_00_NS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) reg &= ~ADIN1300_GE_RGMII_RX_MSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) reg |= ADIN1300_GE_RGMII_RX_SEL(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) reg &= ~ADIN1300_GE_RGMII_RXID_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) reg |= ADIN1300_GE_RGMII_TXID_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) val = adin_get_reg_value(phydev, "adi,tx-internal-delay-ps",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) adin_rgmii_delays,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ADIN1300_RGMII_2_00_NS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) reg &= ~ADIN1300_GE_RGMII_GTX_MSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) reg |= ADIN1300_GE_RGMII_GTX_SEL(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) reg &= ~ADIN1300_GE_RGMII_TXID_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return phy_write_mmd(phydev, MDIO_MMD_VEND1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ADIN1300_GE_RGMII_CFG_REG, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int adin_config_rmii_mode(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (phydev->interface != PHY_INTERFACE_MODE_RMII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) ADIN1300_GE_RMII_CFG_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ADIN1300_GE_RMII_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_GE_RMII_CFG_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) reg |= ADIN1300_GE_RMII_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) val = adin_get_reg_value(phydev, "adi,fifo-depth-bits",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) adin_rmii_fifo_depths,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ADIN1300_RMII_8_BITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) reg &= ~ADIN1300_GE_RMII_FIFO_DEPTH_MSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) reg |= ADIN1300_GE_RMII_FIFO_DEPTH_SEL(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return phy_write_mmd(phydev, MDIO_MMD_VEND1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ADIN1300_GE_RMII_CFG_REG, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static int adin_get_downshift(struct phy_device *phydev, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int val, cnt, enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) val = phy_read(phydev, ADIN1300_PHY_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) cnt = phy_read(phydev, ADIN1300_PHY_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (cnt < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) enable = FIELD_GET(ADIN1300_DOWNSPEEDS_EN, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) cnt = FIELD_GET(ADIN1300_DOWNSPEED_RETRIES_MSK, cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *data = (enable && cnt) ? cnt : DOWNSHIFT_DEV_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int adin_set_downshift(struct phy_device *phydev, u8 cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (cnt == DOWNSHIFT_DEV_DISABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return phy_clear_bits(phydev, ADIN1300_PHY_CTRL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ADIN1300_DOWNSPEEDS_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (cnt > 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) val = FIELD_PREP(ADIN1300_DOWNSPEED_RETRIES_MSK, cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) val |= ADIN1300_LINKING_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) rc = phy_modify(phydev, ADIN1300_PHY_CTRL3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ADIN1300_LINKING_EN | ADIN1300_DOWNSPEED_RETRIES_MSK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return phy_set_bits(phydev, ADIN1300_PHY_CTRL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ADIN1300_DOWNSPEEDS_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static int adin_get_edpd(struct phy_device *phydev, u16 *tx_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) val = phy_read(phydev, ADIN1300_PHY_CTRL_STATUS2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (ADIN1300_NRG_PD_EN & val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (val & ADIN1300_NRG_PD_TX_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* default is 1 second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) *tx_interval = ETHTOOL_PHY_EDPD_DFLT_TX_MSECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) *tx_interval = ETHTOOL_PHY_EDPD_NO_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) *tx_interval = ETHTOOL_PHY_EDPD_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return 0;
^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) static int adin_set_edpd(struct phy_device *phydev, u16 tx_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (tx_interval == ETHTOOL_PHY_EDPD_DISABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return phy_clear_bits(phydev, ADIN1300_PHY_CTRL_STATUS2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) (ADIN1300_NRG_PD_EN | ADIN1300_NRG_PD_TX_EN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) val = ADIN1300_NRG_PD_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) switch (tx_interval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case 1000: /* 1 second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) val |= ADIN1300_NRG_PD_TX_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) case ETHTOOL_PHY_EDPD_NO_TX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return phy_modify(phydev, ADIN1300_PHY_CTRL_STATUS2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) (ADIN1300_NRG_PD_EN | ADIN1300_NRG_PD_TX_EN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int adin_get_tunable(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct ethtool_tunable *tuna, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) switch (tuna->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case ETHTOOL_PHY_DOWNSHIFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return adin_get_downshift(phydev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) case ETHTOOL_PHY_EDPD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return adin_get_edpd(phydev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int adin_set_tunable(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct ethtool_tunable *tuna, const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) switch (tuna->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) case ETHTOOL_PHY_DOWNSHIFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return adin_set_downshift(phydev, *(const u8 *)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) case ETHTOOL_PHY_EDPD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return adin_set_edpd(phydev, *(const u16 *)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static int adin_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) rc = adin_config_rgmii_mode(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) rc = adin_config_rmii_mode(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) rc = adin_set_downshift(phydev, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) rc = adin_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) phydev_dbg(phydev, "PHY is using mode '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) phy_modes(phydev->interface));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return 0;
^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 adin_phy_ack_intr(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /* Clear pending interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) int rc = phy_read(phydev, ADIN1300_INT_STATUS_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return rc < 0 ? rc : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static int adin_phy_config_intr(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return phy_set_bits(phydev, ADIN1300_INT_MASK_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ADIN1300_INT_MASK_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return phy_clear_bits(phydev, ADIN1300_INT_MASK_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ADIN1300_INT_MASK_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static int adin_cl45_to_adin_reg(struct phy_device *phydev, int devad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) u16 cl45_regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) const struct adin_clause45_mmd_map *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (devad == MDIO_MMD_VEND1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return cl45_regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) for (i = 0; i < ARRAY_SIZE(adin_clause45_mmd_map); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) m = &adin_clause45_mmd_map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (m->devad == devad && m->cl45_regnum == cl45_regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return m->adin_regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) phydev_err(phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) "No translation available for devad: %d reg: %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) devad, cl45_regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int adin_read_mmd(struct phy_device *phydev, int devad, u16 regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct mii_bus *bus = phydev->mdio.bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int phy_addr = phydev->mdio.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int adin_regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) adin_regnum = adin_cl45_to_adin_reg(phydev, devad, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (adin_regnum < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return adin_regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) err = __mdiobus_write(bus, phy_addr, ADIN1300_MII_EXT_REG_PTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) adin_regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return __mdiobus_read(bus, phy_addr, ADIN1300_MII_EXT_REG_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static int adin_write_mmd(struct phy_device *phydev, int devad, u16 regnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct mii_bus *bus = phydev->mdio.bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) int phy_addr = phydev->mdio.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) int adin_regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) adin_regnum = adin_cl45_to_adin_reg(phydev, devad, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (adin_regnum < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return adin_regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) err = __mdiobus_write(bus, phy_addr, ADIN1300_MII_EXT_REG_PTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) adin_regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return __mdiobus_write(bus, phy_addr, ADIN1300_MII_EXT_REG_DATA, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static int adin_config_mdix(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) bool auto_en, mdix_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) mdix_en = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) auto_en = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) switch (phydev->mdix_ctrl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) case ETH_TP_MDI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) case ETH_TP_MDI_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) mdix_en = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case ETH_TP_MDI_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) auto_en = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) reg = phy_read(phydev, ADIN1300_PHY_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (mdix_en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) reg |= ADIN1300_MAN_MDIX_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) reg &= ~ADIN1300_MAN_MDIX_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (auto_en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) reg |= ADIN1300_AUTO_MDI_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) reg &= ~ADIN1300_AUTO_MDI_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return phy_write(phydev, ADIN1300_PHY_CTRL1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static int adin_config_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) ret = adin_config_mdix(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return genphy_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static int adin_mdix_update(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) bool auto_en, mdix_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) bool swapped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) reg = phy_read(phydev, ADIN1300_PHY_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) auto_en = !!(reg & ADIN1300_AUTO_MDI_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) mdix_en = !!(reg & ADIN1300_MAN_MDIX_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* If MDI/MDIX is forced, just read it from the control reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (!auto_en) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (mdix_en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) phydev->mdix = ETH_TP_MDI_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) phydev->mdix = ETH_TP_MDI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * Otherwise, we need to deduce it from the PHY status2 reg.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * When Auto-MDI is enabled, the ADIN1300_MAN_MDIX_EN bit implies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * a preference for MDIX when it is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) reg = phy_read(phydev, ADIN1300_PHY_STATUS1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) swapped = !!(reg & ADIN1300_PAIR_01_SWAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (mdix_en != swapped)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) phydev->mdix = ETH_TP_MDI_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) phydev->mdix = ETH_TP_MDI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) static int adin_read_status(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) {
^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) ret = adin_mdix_update(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return genphy_read_status(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static int adin_soft_reset(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /* The reset bit is self-clearing, set it and wait */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) rc = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) ADIN1300_GE_SOFT_RESET_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ADIN1300_GE_SOFT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* If we get a read error something may be wrong */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) rc = phy_read_mmd(phydev, MDIO_MMD_VEND1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ADIN1300_GE_SOFT_RESET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return rc < 0 ? rc : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static int adin_get_sset_count(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return ARRAY_SIZE(adin_hw_stats);
^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) static void adin_get_strings(struct phy_device *phydev, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) for (i = 0; i < ARRAY_SIZE(adin_hw_stats); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) strlcpy(&data[i * ETH_GSTRING_LEN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) adin_hw_stats[i].string, ETH_GSTRING_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static int adin_read_mmd_stat_regs(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) const struct adin_hw_stat *stat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, stat->reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) *val = (ret & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (stat->reg2 == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, stat->reg2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (ret < 0)
^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) *val <<= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) *val |= (ret & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static u64 adin_get_stat(struct phy_device *phydev, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) const struct adin_hw_stat *stat = &adin_hw_stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct adin_priv *priv = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (stat->reg1 > 0x1f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ret = adin_read_mmd_stat_regs(phydev, stat, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return (u64)(~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ret = phy_read(phydev, stat->reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return (u64)(~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) val = (ret & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) priv->stats[i] += val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return priv->stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static void adin_get_stats(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct ethtool_stats *stats, u64 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) /* latch copies of all the frame-checker counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) rc = phy_read(phydev, ADIN1300_RX_ERR_CNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) for (i = 0; i < ARRAY_SIZE(adin_hw_stats); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) data[i] = adin_get_stat(phydev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) static int adin_probe(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct device *dev = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct adin_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) phydev->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static struct phy_driver adin_driver[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) PHY_ID_MATCH_MODEL(PHY_ID_ADIN1200),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) .name = "ADIN1200",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .probe = adin_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .config_init = adin_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) .soft_reset = adin_soft_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .config_aneg = adin_config_aneg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) .read_status = adin_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .get_tunable = adin_get_tunable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .set_tunable = adin_set_tunable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) .ack_interrupt = adin_phy_ack_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .config_intr = adin_phy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .get_sset_count = adin_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .get_strings = adin_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) .get_stats = adin_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) .read_mmd = adin_read_mmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) .write_mmd = adin_write_mmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) PHY_ID_MATCH_MODEL(PHY_ID_ADIN1300),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .name = "ADIN1300",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .probe = adin_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) .config_init = adin_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .soft_reset = adin_soft_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) .config_aneg = adin_config_aneg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) .read_status = adin_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .get_tunable = adin_get_tunable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .set_tunable = adin_set_tunable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .ack_interrupt = adin_phy_ack_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) .config_intr = adin_phy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .get_sset_count = adin_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .get_strings = adin_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .get_stats = adin_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .read_mmd = adin_read_mmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .write_mmd = adin_write_mmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) module_phy_driver(adin_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static struct mdio_device_id __maybe_unused adin_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1200) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1300) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) MODULE_DEVICE_TABLE(mdio, adin_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) MODULE_DESCRIPTION("Analog Devices Industrial Ethernet PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) MODULE_LICENSE("GPL");