1b050f2f1SRadu Pirea (NXP OSS) // SPDX-License-Identifier: GPL-2.0 2b050f2f1SRadu Pirea (NXP OSS) /* NXP C45 PHY driver 3b050f2f1SRadu Pirea (NXP OSS) * Copyright (C) 2021 NXP 4b050f2f1SRadu Pirea (NXP OSS) * Author: Radu Pirea <radu-nicolae.pirea@oss.nxp.com> 5b050f2f1SRadu Pirea (NXP OSS) */ 6b050f2f1SRadu Pirea (NXP OSS) 7b050f2f1SRadu Pirea (NXP OSS) #include <linux/delay.h> 8b050f2f1SRadu Pirea (NXP OSS) #include <linux/ethtool.h> 9b050f2f1SRadu Pirea (NXP OSS) #include <linux/ethtool_netlink.h> 10b050f2f1SRadu Pirea (NXP OSS) #include <linux/kernel.h> 11b050f2f1SRadu Pirea (NXP OSS) #include <linux/mii.h> 12b050f2f1SRadu Pirea (NXP OSS) #include <linux/module.h> 13b050f2f1SRadu Pirea (NXP OSS) #include <linux/phy.h> 14b050f2f1SRadu Pirea (NXP OSS) #include <linux/processor.h> 15b050f2f1SRadu Pirea (NXP OSS) #include <linux/property.h> 16b050f2f1SRadu Pirea (NXP OSS) 17b050f2f1SRadu Pirea (NXP OSS) #define PHY_ID_TJA_1103 0x001BB010 18b050f2f1SRadu Pirea (NXP OSS) 19b050f2f1SRadu Pirea (NXP OSS) #define PMAPMD_B100T1_PMAPMD_CTL 0x0834 20b050f2f1SRadu Pirea (NXP OSS) #define B100T1_PMAPMD_CONFIG_EN BIT(15) 21b050f2f1SRadu Pirea (NXP OSS) #define B100T1_PMAPMD_MASTER BIT(14) 22b050f2f1SRadu Pirea (NXP OSS) #define MASTER_MODE (B100T1_PMAPMD_CONFIG_EN | \ 23b050f2f1SRadu Pirea (NXP OSS) B100T1_PMAPMD_MASTER) 24b050f2f1SRadu Pirea (NXP OSS) #define SLAVE_MODE (B100T1_PMAPMD_CONFIG_EN) 25b050f2f1SRadu Pirea (NXP OSS) 26b050f2f1SRadu Pirea (NXP OSS) #define VEND1_DEVICE_CONTROL 0x0040 27b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_RESET BIT(15) 28b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14) 29b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_ALL_EN BIT(13) 30b050f2f1SRadu Pirea (NXP OSS) 31*b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_ACK 0x80A0 32*b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_EN 0x80A1 33*b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_STATUS 0x80A2 34*b2f0ca00SRadu Pirea (NXP OSS) #define PHY_IRQ_LINK_EVENT BIT(1) 35*b2f0ca00SRadu Pirea (NXP OSS) 36b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONTROL 0x8100 37b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_EN BIT(14) 38b050f2f1SRadu Pirea (NXP OSS) #define PHY_START_OP BIT(0) 39b050f2f1SRadu Pirea (NXP OSS) 40b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONFIG 0x8108 41b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_AUTO BIT(0) 42b050f2f1SRadu Pirea (NXP OSS) 43b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SIGNAL_QUALITY 0x8320 44b050f2f1SRadu Pirea (NXP OSS) #define SQI_VALID BIT(14) 45b050f2f1SRadu Pirea (NXP OSS) #define SQI_MASK GENMASK(2, 0) 46b050f2f1SRadu Pirea (NXP OSS) #define MAX_SQI SQI_MASK 47b050f2f1SRadu Pirea (NXP OSS) 48b050f2f1SRadu Pirea (NXP OSS) #define VEND1_CABLE_TEST 0x8330 49b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_ENABLE BIT(15) 50b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_START BIT(14) 51b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_VALID BIT(13) 52b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OK 0x00 53b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_SHORTED 0x01 54b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OPEN 0x02 55b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_UNKNOWN 0x07 56b050f2f1SRadu Pirea (NXP OSS) 57b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_CONTROL 0x8040 58b050f2f1SRadu Pirea (NXP OSS) #define PORT_CONTROL_EN BIT(14) 59b050f2f1SRadu Pirea (NXP OSS) 60b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_INFRA_CONTROL 0xAC00 61b050f2f1SRadu Pirea (NXP OSS) #define PORT_INFRA_CONTROL_EN BIT(14) 62b050f2f1SRadu Pirea (NXP OSS) 63b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RXID 0xAFCC 64b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TXID 0xAFCD 65b050f2f1SRadu Pirea (NXP OSS) #define ID_ENABLE BIT(15) 66b050f2f1SRadu Pirea (NXP OSS) 67b050f2f1SRadu Pirea (NXP OSS) #define VEND1_ABILITIES 0xAFC4 68b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ID_ABILITY BIT(15) 69b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ABILITY BIT(14) 70b050f2f1SRadu Pirea (NXP OSS) #define RMII_ABILITY BIT(10) 71b050f2f1SRadu Pirea (NXP OSS) #define REVMII_ABILITY BIT(9) 72b050f2f1SRadu Pirea (NXP OSS) #define MII_ABILITY BIT(8) 73b050f2f1SRadu Pirea (NXP OSS) #define SGMII_ABILITY BIT(0) 74b050f2f1SRadu Pirea (NXP OSS) 75b050f2f1SRadu Pirea (NXP OSS) #define VEND1_MII_BASIC_CONFIG 0xAFC6 76b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_REV BIT(8) 77b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_SGMII 0x9 78b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RGMII 0x7 79b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RMII 0x5 80b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_MII 0x4 81b050f2f1SRadu Pirea (NXP OSS) 82b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_COUNTER 0x8350 83b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_DROP_COUNTER 0x8352 84b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_LOSSES_AND_FAILURES 0x8353 85b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_GOOD_FRAME_CNT 0xA950 86b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_BAD_FRAME_CNT 0xA952 87b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_RXER_FRAME_CNT 0xA954 88b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_PREAMBLE_COUNT 0xAFCE 89b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_PREAMBLE_COUNT 0xAFCF 90b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_IPG_LENGTH 0xAFD0 91b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_IPG_LENGTH 0xAFD1 92b050f2f1SRadu Pirea (NXP OSS) #define COUNTER_EN BIT(15) 93b050f2f1SRadu Pirea (NXP OSS) 94b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS 8000U 95b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE div_u64(RGMII_PERIOD_PS, 360) 96b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS 1644U 97b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS 2260U 98b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS 2000U 99b050f2f1SRadu Pirea (NXP OSS) 100b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy { 101b050f2f1SRadu Pirea (NXP OSS) u32 tx_delay; 102b050f2f1SRadu Pirea (NXP OSS) u32 rx_delay; 103b050f2f1SRadu Pirea (NXP OSS) }; 104b050f2f1SRadu Pirea (NXP OSS) 105b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy_stats { 106b050f2f1SRadu Pirea (NXP OSS) const char *name; 107b050f2f1SRadu Pirea (NXP OSS) u8 mmd; 108b050f2f1SRadu Pirea (NXP OSS) u16 reg; 109b050f2f1SRadu Pirea (NXP OSS) u8 off; 110b050f2f1SRadu Pirea (NXP OSS) u16 mask; 111b050f2f1SRadu Pirea (NXP OSS) }; 112b050f2f1SRadu Pirea (NXP OSS) 113b050f2f1SRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats nxp_c45_hw_stats[] = { 114b050f2f1SRadu Pirea (NXP OSS) { "phy_symbol_error_cnt", MDIO_MMD_VEND1, 115b050f2f1SRadu Pirea (NXP OSS) VEND1_SYMBOL_ERROR_COUNTER, 0, GENMASK(15, 0) }, 116b050f2f1SRadu Pirea (NXP OSS) { "phy_link_status_drop_cnt", MDIO_MMD_VEND1, 117b050f2f1SRadu Pirea (NXP OSS) VEND1_LINK_DROP_COUNTER, 8, GENMASK(13, 8) }, 118b050f2f1SRadu Pirea (NXP OSS) { "phy_link_availability_drop_cnt", MDIO_MMD_VEND1, 119b050f2f1SRadu Pirea (NXP OSS) VEND1_LINK_DROP_COUNTER, 0, GENMASK(5, 0) }, 120b050f2f1SRadu Pirea (NXP OSS) { "phy_link_loss_cnt", MDIO_MMD_VEND1, 121b050f2f1SRadu Pirea (NXP OSS) VEND1_LINK_LOSSES_AND_FAILURES, 10, GENMASK(15, 10) }, 122b050f2f1SRadu Pirea (NXP OSS) { "phy_link_failure_cnt", MDIO_MMD_VEND1, 123b050f2f1SRadu Pirea (NXP OSS) VEND1_LINK_LOSSES_AND_FAILURES, 0, GENMASK(9, 0) }, 124b050f2f1SRadu Pirea (NXP OSS) { "r_good_frame_cnt", MDIO_MMD_VEND1, 125b050f2f1SRadu Pirea (NXP OSS) VEND1_R_GOOD_FRAME_CNT, 0, GENMASK(15, 0) }, 126b050f2f1SRadu Pirea (NXP OSS) { "r_bad_frame_cnt", MDIO_MMD_VEND1, 127b050f2f1SRadu Pirea (NXP OSS) VEND1_R_BAD_FRAME_CNT, 0, GENMASK(15, 0) }, 128b050f2f1SRadu Pirea (NXP OSS) { "r_rxer_frame_cnt", MDIO_MMD_VEND1, 129b050f2f1SRadu Pirea (NXP OSS) VEND1_R_RXER_FRAME_CNT, 0, GENMASK(15, 0) }, 130b050f2f1SRadu Pirea (NXP OSS) { "rx_preamble_count", MDIO_MMD_VEND1, 131b050f2f1SRadu Pirea (NXP OSS) VEND1_RX_PREAMBLE_COUNT, 0, GENMASK(5, 0) }, 132b050f2f1SRadu Pirea (NXP OSS) { "tx_preamble_count", MDIO_MMD_VEND1, 133b050f2f1SRadu Pirea (NXP OSS) VEND1_TX_PREAMBLE_COUNT, 0, GENMASK(5, 0) }, 134b050f2f1SRadu Pirea (NXP OSS) { "rx_ipg_length", MDIO_MMD_VEND1, 135b050f2f1SRadu Pirea (NXP OSS) VEND1_RX_IPG_LENGTH, 0, GENMASK(8, 0) }, 136b050f2f1SRadu Pirea (NXP OSS) { "tx_ipg_length", MDIO_MMD_VEND1, 137b050f2f1SRadu Pirea (NXP OSS) VEND1_TX_IPG_LENGTH, 0, GENMASK(8, 0) }, 138b050f2f1SRadu Pirea (NXP OSS) }; 139b050f2f1SRadu Pirea (NXP OSS) 140b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev) 141b050f2f1SRadu Pirea (NXP OSS) { 142b050f2f1SRadu Pirea (NXP OSS) return ARRAY_SIZE(nxp_c45_hw_stats); 143b050f2f1SRadu Pirea (NXP OSS) } 144b050f2f1SRadu Pirea (NXP OSS) 145b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data) 146b050f2f1SRadu Pirea (NXP OSS) { 147b050f2f1SRadu Pirea (NXP OSS) size_t i; 148b050f2f1SRadu Pirea (NXP OSS) 149b050f2f1SRadu Pirea (NXP OSS) for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) { 150b050f2f1SRadu Pirea (NXP OSS) strncpy(data + i * ETH_GSTRING_LEN, 151b050f2f1SRadu Pirea (NXP OSS) nxp_c45_hw_stats[i].name, ETH_GSTRING_LEN); 152b050f2f1SRadu Pirea (NXP OSS) } 153b050f2f1SRadu Pirea (NXP OSS) } 154b050f2f1SRadu Pirea (NXP OSS) 155b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev, 156b050f2f1SRadu Pirea (NXP OSS) struct ethtool_stats *stats, u64 *data) 157b050f2f1SRadu Pirea (NXP OSS) { 158b050f2f1SRadu Pirea (NXP OSS) size_t i; 159b050f2f1SRadu Pirea (NXP OSS) int ret; 160b050f2f1SRadu Pirea (NXP OSS) 161b050f2f1SRadu Pirea (NXP OSS) for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) { 162b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, nxp_c45_hw_stats[i].mmd, 163b050f2f1SRadu Pirea (NXP OSS) nxp_c45_hw_stats[i].reg); 164b050f2f1SRadu Pirea (NXP OSS) if (ret < 0) { 165b050f2f1SRadu Pirea (NXP OSS) data[i] = U64_MAX; 166b050f2f1SRadu Pirea (NXP OSS) } else { 167b050f2f1SRadu Pirea (NXP OSS) data[i] = ret & nxp_c45_hw_stats[i].mask; 168b050f2f1SRadu Pirea (NXP OSS) data[i] >>= nxp_c45_hw_stats[i].off; 169b050f2f1SRadu Pirea (NXP OSS) } 170b050f2f1SRadu Pirea (NXP OSS) } 171b050f2f1SRadu Pirea (NXP OSS) } 172b050f2f1SRadu Pirea (NXP OSS) 173b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev) 174b050f2f1SRadu Pirea (NXP OSS) { 175b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 176b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_GLOBAL_EN | 177b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_ALL_EN); 178b050f2f1SRadu Pirea (NXP OSS) usleep_range(400, 450); 179b050f2f1SRadu Pirea (NXP OSS) 180b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL, 181b050f2f1SRadu Pirea (NXP OSS) PORT_CONTROL_EN); 182b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 183b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_EN); 184b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL, 185b050f2f1SRadu Pirea (NXP OSS) PORT_INFRA_CONTROL_EN); 186b050f2f1SRadu Pirea (NXP OSS) 187b050f2f1SRadu Pirea (NXP OSS) return 0; 188b050f2f1SRadu Pirea (NXP OSS) } 189b050f2f1SRadu Pirea (NXP OSS) 190b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev) 191b050f2f1SRadu Pirea (NXP OSS) { 192b050f2f1SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 193b050f2f1SRadu Pirea (NXP OSS) PHY_START_OP); 194b050f2f1SRadu Pirea (NXP OSS) } 195b050f2f1SRadu Pirea (NXP OSS) 196*b2f0ca00SRadu Pirea (NXP OSS) static int nxp_c45_config_intr(struct phy_device *phydev) 197*b2f0ca00SRadu Pirea (NXP OSS) { 198*b2f0ca00SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 199*b2f0ca00SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 200*b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 201*b2f0ca00SRadu Pirea (NXP OSS) else 202*b2f0ca00SRadu Pirea (NXP OSS) return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 203*b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 204*b2f0ca00SRadu Pirea (NXP OSS) } 205*b2f0ca00SRadu Pirea (NXP OSS) 206*b2f0ca00SRadu Pirea (NXP OSS) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) 207*b2f0ca00SRadu Pirea (NXP OSS) { 208*b2f0ca00SRadu Pirea (NXP OSS) irqreturn_t ret = IRQ_NONE; 209*b2f0ca00SRadu Pirea (NXP OSS) int irq; 210*b2f0ca00SRadu Pirea (NXP OSS) 211*b2f0ca00SRadu Pirea (NXP OSS) irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS); 212*b2f0ca00SRadu Pirea (NXP OSS) if (irq & PHY_IRQ_LINK_EVENT) { 213*b2f0ca00SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK, 214*b2f0ca00SRadu Pirea (NXP OSS) PHY_IRQ_LINK_EVENT); 215*b2f0ca00SRadu Pirea (NXP OSS) phy_trigger_machine(phydev); 216*b2f0ca00SRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 217*b2f0ca00SRadu Pirea (NXP OSS) } 218*b2f0ca00SRadu Pirea (NXP OSS) 219*b2f0ca00SRadu Pirea (NXP OSS) return ret; 220*b2f0ca00SRadu Pirea (NXP OSS) } 221*b2f0ca00SRadu Pirea (NXP OSS) 222b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev) 223b050f2f1SRadu Pirea (NXP OSS) { 224b050f2f1SRadu Pirea (NXP OSS) int ret; 225b050f2f1SRadu Pirea (NXP OSS) 226b050f2f1SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 227b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_RESET); 228b050f2f1SRadu Pirea (NXP OSS) if (ret) 229b050f2f1SRadu Pirea (NXP OSS) return ret; 230b050f2f1SRadu Pirea (NXP OSS) 231b050f2f1SRadu Pirea (NXP OSS) return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 232b050f2f1SRadu Pirea (NXP OSS) VEND1_DEVICE_CONTROL, ret, 233b050f2f1SRadu Pirea (NXP OSS) !(ret & DEVICE_CONTROL_RESET), 20000, 234b050f2f1SRadu Pirea (NXP OSS) 240000, false); 235b050f2f1SRadu Pirea (NXP OSS) } 236b050f2f1SRadu Pirea (NXP OSS) 237b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev) 238b050f2f1SRadu Pirea (NXP OSS) { 239b050f2f1SRadu Pirea (NXP OSS) return phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST, 240b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE | CABLE_TEST_START); 241b050f2f1SRadu Pirea (NXP OSS) } 242b050f2f1SRadu Pirea (NXP OSS) 243b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev, 244b050f2f1SRadu Pirea (NXP OSS) bool *finished) 245b050f2f1SRadu Pirea (NXP OSS) { 246b050f2f1SRadu Pirea (NXP OSS) int ret; 247b050f2f1SRadu Pirea (NXP OSS) u8 cable_test_result; 248b050f2f1SRadu Pirea (NXP OSS) 249b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST); 250b050f2f1SRadu Pirea (NXP OSS) if (!(ret & CABLE_TEST_VALID)) { 251b050f2f1SRadu Pirea (NXP OSS) *finished = false; 252b050f2f1SRadu Pirea (NXP OSS) return 0; 253b050f2f1SRadu Pirea (NXP OSS) } 254b050f2f1SRadu Pirea (NXP OSS) 255b050f2f1SRadu Pirea (NXP OSS) *finished = true; 256b050f2f1SRadu Pirea (NXP OSS) cable_test_result = ret & GENMASK(2, 0); 257b050f2f1SRadu Pirea (NXP OSS) 258b050f2f1SRadu Pirea (NXP OSS) switch (cable_test_result) { 259b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OK: 260b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 261b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OK); 262b050f2f1SRadu Pirea (NXP OSS) break; 263b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_SHORTED: 264b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 265b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT); 266b050f2f1SRadu Pirea (NXP OSS) break; 267b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OPEN: 268b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 269b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OPEN); 270b050f2f1SRadu Pirea (NXP OSS) break; 271b050f2f1SRadu Pirea (NXP OSS) default: 272b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 273b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC); 274b050f2f1SRadu Pirea (NXP OSS) } 275b050f2f1SRadu Pirea (NXP OSS) 276b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST, 277b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE); 278b050f2f1SRadu Pirea (NXP OSS) 279b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 280b050f2f1SRadu Pirea (NXP OSS) } 281b050f2f1SRadu Pirea (NXP OSS) 282b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_setup_master_slave(struct phy_device *phydev) 283b050f2f1SRadu Pirea (NXP OSS) { 284b050f2f1SRadu Pirea (NXP OSS) switch (phydev->master_slave_set) { 285b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_MASTER_FORCE: 286b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_MASTER_PREFERRED: 287b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL, 288b050f2f1SRadu Pirea (NXP OSS) MASTER_MODE); 289b050f2f1SRadu Pirea (NXP OSS) break; 290b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_SLAVE_PREFERRED: 291b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_SLAVE_FORCE: 292b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL, 293b050f2f1SRadu Pirea (NXP OSS) SLAVE_MODE); 294b050f2f1SRadu Pirea (NXP OSS) break; 295b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_UNKNOWN: 296b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_UNSUPPORTED: 297b050f2f1SRadu Pirea (NXP OSS) return 0; 298b050f2f1SRadu Pirea (NXP OSS) default: 299b050f2f1SRadu Pirea (NXP OSS) phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 300b050f2f1SRadu Pirea (NXP OSS) return -EOPNOTSUPP; 301b050f2f1SRadu Pirea (NXP OSS) } 302b050f2f1SRadu Pirea (NXP OSS) 303b050f2f1SRadu Pirea (NXP OSS) return 0; 304b050f2f1SRadu Pirea (NXP OSS) } 305b050f2f1SRadu Pirea (NXP OSS) 306b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_read_master_slave(struct phy_device *phydev) 307b050f2f1SRadu Pirea (NXP OSS) { 308b050f2f1SRadu Pirea (NXP OSS) int reg; 309b050f2f1SRadu Pirea (NXP OSS) 310b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; 311b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; 312b050f2f1SRadu Pirea (NXP OSS) 313b050f2f1SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL); 314b050f2f1SRadu Pirea (NXP OSS) if (reg < 0) 315b050f2f1SRadu Pirea (NXP OSS) return reg; 316b050f2f1SRadu Pirea (NXP OSS) 317b050f2f1SRadu Pirea (NXP OSS) if (reg & B100T1_PMAPMD_MASTER) { 318b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; 319b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; 320b050f2f1SRadu Pirea (NXP OSS) } else { 321b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; 322b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; 323b050f2f1SRadu Pirea (NXP OSS) } 324b050f2f1SRadu Pirea (NXP OSS) 325b050f2f1SRadu Pirea (NXP OSS) return 0; 326b050f2f1SRadu Pirea (NXP OSS) } 327b050f2f1SRadu Pirea (NXP OSS) 328b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_aneg(struct phy_device *phydev) 329b050f2f1SRadu Pirea (NXP OSS) { 330b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_setup_master_slave(phydev); 331b050f2f1SRadu Pirea (NXP OSS) } 332b050f2f1SRadu Pirea (NXP OSS) 333b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_read_status(struct phy_device *phydev) 334b050f2f1SRadu Pirea (NXP OSS) { 335b050f2f1SRadu Pirea (NXP OSS) int ret; 336b050f2f1SRadu Pirea (NXP OSS) 337b050f2f1SRadu Pirea (NXP OSS) ret = genphy_c45_read_status(phydev); 338b050f2f1SRadu Pirea (NXP OSS) if (ret) 339b050f2f1SRadu Pirea (NXP OSS) return ret; 340b050f2f1SRadu Pirea (NXP OSS) 341b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_read_master_slave(phydev); 342b050f2f1SRadu Pirea (NXP OSS) if (ret) 343b050f2f1SRadu Pirea (NXP OSS) return ret; 344b050f2f1SRadu Pirea (NXP OSS) 345b050f2f1SRadu Pirea (NXP OSS) return 0; 346b050f2f1SRadu Pirea (NXP OSS) } 347b050f2f1SRadu Pirea (NXP OSS) 348b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev) 349b050f2f1SRadu Pirea (NXP OSS) { 350b050f2f1SRadu Pirea (NXP OSS) int reg; 351b050f2f1SRadu Pirea (NXP OSS) 352b050f2f1SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY); 353b050f2f1SRadu Pirea (NXP OSS) if (!(reg & SQI_VALID)) 354b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 355b050f2f1SRadu Pirea (NXP OSS) 356b050f2f1SRadu Pirea (NXP OSS) reg &= SQI_MASK; 357b050f2f1SRadu Pirea (NXP OSS) 358b050f2f1SRadu Pirea (NXP OSS) return reg; 359b050f2f1SRadu Pirea (NXP OSS) } 360b050f2f1SRadu Pirea (NXP OSS) 361b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev) 362b050f2f1SRadu Pirea (NXP OSS) { 363b050f2f1SRadu Pirea (NXP OSS) return MAX_SQI; 364b050f2f1SRadu Pirea (NXP OSS) } 365b050f2f1SRadu Pirea (NXP OSS) 366b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay) 367b050f2f1SRadu Pirea (NXP OSS) { 368b050f2f1SRadu Pirea (NXP OSS) if (delay < MIN_ID_PS) { 369b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS); 370b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 371b050f2f1SRadu Pirea (NXP OSS) } 372b050f2f1SRadu Pirea (NXP OSS) 373b050f2f1SRadu Pirea (NXP OSS) if (delay > MAX_ID_PS) { 374b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS); 375b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 376b050f2f1SRadu Pirea (NXP OSS) } 377b050f2f1SRadu Pirea (NXP OSS) 378b050f2f1SRadu Pirea (NXP OSS) return 0; 379b050f2f1SRadu Pirea (NXP OSS) } 380b050f2f1SRadu Pirea (NXP OSS) 381b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw) 382b050f2f1SRadu Pirea (NXP OSS) { 383b050f2f1SRadu Pirea (NXP OSS) /* The delay in degree phase is 73.8 + phase_offset_raw * 0.9. 384b050f2f1SRadu Pirea (NXP OSS) * To avoid floating point operations we'll multiply by 10 385b050f2f1SRadu Pirea (NXP OSS) * and get 1 decimal point precision. 386b050f2f1SRadu Pirea (NXP OSS) */ 387b050f2f1SRadu Pirea (NXP OSS) phase_offset_raw *= 10; 3886b3a6310SRadu Pirea (NXP OSS) phase_offset_raw -= 738; 389b050f2f1SRadu Pirea (NXP OSS) return div_u64(phase_offset_raw, 9); 390b050f2f1SRadu Pirea (NXP OSS) } 391b050f2f1SRadu Pirea (NXP OSS) 392b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev) 393b050f2f1SRadu Pirea (NXP OSS) { 394b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE); 395b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE); 396b050f2f1SRadu Pirea (NXP OSS) } 397b050f2f1SRadu Pirea (NXP OSS) 398b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev) 399b050f2f1SRadu Pirea (NXP OSS) { 400b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 401b050f2f1SRadu Pirea (NXP OSS) u64 tx_delay = priv->tx_delay; 402b050f2f1SRadu Pirea (NXP OSS) u64 rx_delay = priv->rx_delay; 403b050f2f1SRadu Pirea (NXP OSS) u64 degree; 404b050f2f1SRadu Pirea (NXP OSS) 405b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 406b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 407b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(tx_delay, PS_PER_DEGREE); 408b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 409b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 410b050f2f1SRadu Pirea (NXP OSS) } else { 411b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 412b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 413b050f2f1SRadu Pirea (NXP OSS) } 414b050f2f1SRadu Pirea (NXP OSS) 415b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 416b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 417b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(rx_delay, PS_PER_DEGREE); 418b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 419b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 420b050f2f1SRadu Pirea (NXP OSS) } else { 421b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 422b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 423b050f2f1SRadu Pirea (NXP OSS) } 424b050f2f1SRadu Pirea (NXP OSS) } 425b050f2f1SRadu Pirea (NXP OSS) 426b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev) 427b050f2f1SRadu Pirea (NXP OSS) { 428b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 429b050f2f1SRadu Pirea (NXP OSS) int ret; 430b050f2f1SRadu Pirea (NXP OSS) 431b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 432b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 433b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 434b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps", 435b050f2f1SRadu Pirea (NXP OSS) &priv->tx_delay); 436b050f2f1SRadu Pirea (NXP OSS) if (ret) 437b050f2f1SRadu Pirea (NXP OSS) priv->tx_delay = DEFAULT_ID_PS; 438b050f2f1SRadu Pirea (NXP OSS) 439b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->tx_delay); 440b050f2f1SRadu Pirea (NXP OSS) if (ret) { 441b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 442b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps invalid value\n"); 443b050f2f1SRadu Pirea (NXP OSS) return ret; 444b050f2f1SRadu Pirea (NXP OSS) } 445b050f2f1SRadu Pirea (NXP OSS) } 446b050f2f1SRadu Pirea (NXP OSS) 447b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 448b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 449b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 450b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps", 451b050f2f1SRadu Pirea (NXP OSS) &priv->rx_delay); 452b050f2f1SRadu Pirea (NXP OSS) if (ret) 453b050f2f1SRadu Pirea (NXP OSS) priv->rx_delay = DEFAULT_ID_PS; 454b050f2f1SRadu Pirea (NXP OSS) 455b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->rx_delay); 456b050f2f1SRadu Pirea (NXP OSS) if (ret) { 457b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 458b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps invalid value\n"); 459b050f2f1SRadu Pirea (NXP OSS) return ret; 460b050f2f1SRadu Pirea (NXP OSS) } 461b050f2f1SRadu Pirea (NXP OSS) } 462b050f2f1SRadu Pirea (NXP OSS) 463b050f2f1SRadu Pirea (NXP OSS) return 0; 464b050f2f1SRadu Pirea (NXP OSS) } 465b050f2f1SRadu Pirea (NXP OSS) 466b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev) 467b050f2f1SRadu Pirea (NXP OSS) { 468b050f2f1SRadu Pirea (NXP OSS) int ret; 469b050f2f1SRadu Pirea (NXP OSS) 470b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES); 471b050f2f1SRadu Pirea (NXP OSS) phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret); 472b050f2f1SRadu Pirea (NXP OSS) 473b050f2f1SRadu Pirea (NXP OSS) switch (phydev->interface) { 474b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII: 475b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ABILITY)) { 476b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii mode not supported\n"); 477b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 478b050f2f1SRadu Pirea (NXP OSS) } 479b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 480b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 481b050f2f1SRadu Pirea (NXP OSS) nxp_c45_disable_delays(phydev); 482b050f2f1SRadu Pirea (NXP OSS) break; 483b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_ID: 484b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_TXID: 485b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_RXID: 486b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ID_ABILITY)) { 487b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n"); 488b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 489b050f2f1SRadu Pirea (NXP OSS) } 490b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 491b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 492b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_get_delays(phydev); 493b050f2f1SRadu Pirea (NXP OSS) if (ret) 494b050f2f1SRadu Pirea (NXP OSS) return ret; 495b050f2f1SRadu Pirea (NXP OSS) 496b050f2f1SRadu Pirea (NXP OSS) nxp_c45_set_delays(phydev); 497b050f2f1SRadu Pirea (NXP OSS) break; 498b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_MII: 499b050f2f1SRadu Pirea (NXP OSS) if (!(ret & MII_ABILITY)) { 500b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "mii mode not supported\n"); 501b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 502b050f2f1SRadu Pirea (NXP OSS) } 503b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 504b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII); 505b050f2f1SRadu Pirea (NXP OSS) break; 506b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_REVMII: 507b050f2f1SRadu Pirea (NXP OSS) if (!(ret & REVMII_ABILITY)) { 508b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rev-mii mode not supported\n"); 509b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 510b050f2f1SRadu Pirea (NXP OSS) } 511b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 512b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII | MII_BASIC_CONFIG_REV); 513b050f2f1SRadu Pirea (NXP OSS) break; 514b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RMII: 515b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RMII_ABILITY)) { 516b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rmii mode not supported\n"); 517b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 518b050f2f1SRadu Pirea (NXP OSS) } 519b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 520b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RMII); 521b050f2f1SRadu Pirea (NXP OSS) break; 522b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_SGMII: 523b050f2f1SRadu Pirea (NXP OSS) if (!(ret & SGMII_ABILITY)) { 524b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "sgmii mode not supported\n"); 525b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 526b050f2f1SRadu Pirea (NXP OSS) } 527b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 528b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_SGMII); 529b050f2f1SRadu Pirea (NXP OSS) break; 530b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_INTERNAL: 531b050f2f1SRadu Pirea (NXP OSS) break; 532b050f2f1SRadu Pirea (NXP OSS) default: 533b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 534b050f2f1SRadu Pirea (NXP OSS) } 535b050f2f1SRadu Pirea (NXP OSS) 536b050f2f1SRadu Pirea (NXP OSS) return 0; 537b050f2f1SRadu Pirea (NXP OSS) } 538b050f2f1SRadu Pirea (NXP OSS) 539b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev) 540b050f2f1SRadu Pirea (NXP OSS) { 541b050f2f1SRadu Pirea (NXP OSS) int ret; 542b050f2f1SRadu Pirea (NXP OSS) 543b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_config_enable(phydev); 544b050f2f1SRadu Pirea (NXP OSS) if (ret) { 545b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "Failed to enable config\n"); 546b050f2f1SRadu Pirea (NXP OSS) return ret; 547b050f2f1SRadu Pirea (NXP OSS) } 548b050f2f1SRadu Pirea (NXP OSS) 549b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG, 550b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_AUTO); 551b050f2f1SRadu Pirea (NXP OSS) 552b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER, 553b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 554b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT, 555b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 556b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT, 557b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 558b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH, 559b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 560b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH, 561b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 562b050f2f1SRadu Pirea (NXP OSS) 563b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_set_phy_mode(phydev); 564b050f2f1SRadu Pirea (NXP OSS) if (ret) 565b050f2f1SRadu Pirea (NXP OSS) return ret; 566b050f2f1SRadu Pirea (NXP OSS) 567b050f2f1SRadu Pirea (NXP OSS) phydev->autoneg = AUTONEG_DISABLE; 568b050f2f1SRadu Pirea (NXP OSS) 569b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 570b050f2f1SRadu Pirea (NXP OSS) } 571b050f2f1SRadu Pirea (NXP OSS) 572b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev) 573b050f2f1SRadu Pirea (NXP OSS) { 574b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv; 575b050f2f1SRadu Pirea (NXP OSS) 576b050f2f1SRadu Pirea (NXP OSS) priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 577b050f2f1SRadu Pirea (NXP OSS) if (!priv) 578b050f2f1SRadu Pirea (NXP OSS) return -ENOMEM; 579b050f2f1SRadu Pirea (NXP OSS) 580b050f2f1SRadu Pirea (NXP OSS) phydev->priv = priv; 581b050f2f1SRadu Pirea (NXP OSS) 582b050f2f1SRadu Pirea (NXP OSS) return 0; 583b050f2f1SRadu Pirea (NXP OSS) } 584b050f2f1SRadu Pirea (NXP OSS) 585b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = { 586b050f2f1SRadu Pirea (NXP OSS) { 587b050f2f1SRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), 588b050f2f1SRadu Pirea (NXP OSS) .name = "NXP C45 TJA1103", 589b050f2f1SRadu Pirea (NXP OSS) .features = PHY_BASIC_T1_FEATURES, 590b050f2f1SRadu Pirea (NXP OSS) .probe = nxp_c45_probe, 591b050f2f1SRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset, 592b050f2f1SRadu Pirea (NXP OSS) .config_aneg = nxp_c45_config_aneg, 593b050f2f1SRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init, 594*b2f0ca00SRadu Pirea (NXP OSS) .config_intr = nxp_c45_config_intr, 595*b2f0ca00SRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt, 596b050f2f1SRadu Pirea (NXP OSS) .read_status = nxp_c45_read_status, 597b050f2f1SRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend, 598b050f2f1SRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume, 599b050f2f1SRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count, 600b050f2f1SRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings, 601b050f2f1SRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats, 602b050f2f1SRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start, 603b050f2f1SRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status, 604b050f2f1SRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback, 605b050f2f1SRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi, 606b050f2f1SRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max, 607b050f2f1SRadu Pirea (NXP OSS) }, 608b050f2f1SRadu Pirea (NXP OSS) }; 609b050f2f1SRadu Pirea (NXP OSS) 610b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver); 611b050f2f1SRadu Pirea (NXP OSS) 612b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = { 613b050f2f1SRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) }, 614b050f2f1SRadu Pirea (NXP OSS) { /*sentinel*/ }, 615b050f2f1SRadu Pirea (NXP OSS) }; 616b050f2f1SRadu Pirea (NXP OSS) 617b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl); 618b050f2f1SRadu Pirea (NXP OSS) 619b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>"); 620b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver"); 621b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2"); 622