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