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> 16514def5dSRadu Pirea (NXP OSS) #include <linux/ptp_classify.h> 17514def5dSRadu Pirea (NXP OSS) #include <linux/ptp_clock_kernel.h> 18514def5dSRadu Pirea (NXP OSS) #include <linux/net_tstamp.h> 19b050f2f1SRadu Pirea (NXP OSS) 20b050f2f1SRadu Pirea (NXP OSS) #define PHY_ID_TJA_1103 0x001BB010 21b050f2f1SRadu Pirea (NXP OSS) 22b050f2f1SRadu Pirea (NXP OSS) #define PMAPMD_B100T1_PMAPMD_CTL 0x0834 23b050f2f1SRadu Pirea (NXP OSS) #define B100T1_PMAPMD_CONFIG_EN BIT(15) 24b050f2f1SRadu Pirea (NXP OSS) #define B100T1_PMAPMD_MASTER BIT(14) 25b050f2f1SRadu Pirea (NXP OSS) #define MASTER_MODE (B100T1_PMAPMD_CONFIG_EN | \ 26b050f2f1SRadu Pirea (NXP OSS) B100T1_PMAPMD_MASTER) 27b050f2f1SRadu Pirea (NXP OSS) #define SLAVE_MODE (B100T1_PMAPMD_CONFIG_EN) 28b050f2f1SRadu Pirea (NXP OSS) 29b050f2f1SRadu Pirea (NXP OSS) #define VEND1_DEVICE_CONTROL 0x0040 30b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_RESET BIT(15) 31b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14) 32b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_ALL_EN BIT(13) 33b050f2f1SRadu Pirea (NXP OSS) 34b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_ACK 0x80A0 35b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_EN 0x80A1 36b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_STATUS 0x80A2 37b2f0ca00SRadu Pirea (NXP OSS) #define PHY_IRQ_LINK_EVENT BIT(1) 38b2f0ca00SRadu Pirea (NXP OSS) 39b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONTROL 0x8100 40b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_EN BIT(14) 41b050f2f1SRadu Pirea (NXP OSS) #define PHY_START_OP BIT(0) 42b050f2f1SRadu Pirea (NXP OSS) 43b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONFIG 0x8108 44b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_AUTO BIT(0) 45b050f2f1SRadu Pirea (NXP OSS) 46b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SIGNAL_QUALITY 0x8320 47b050f2f1SRadu Pirea (NXP OSS) #define SQI_VALID BIT(14) 48b050f2f1SRadu Pirea (NXP OSS) #define SQI_MASK GENMASK(2, 0) 49b050f2f1SRadu Pirea (NXP OSS) #define MAX_SQI SQI_MASK 50b050f2f1SRadu Pirea (NXP OSS) 51b050f2f1SRadu Pirea (NXP OSS) #define VEND1_CABLE_TEST 0x8330 52b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_ENABLE BIT(15) 53b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_START BIT(14) 54b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_VALID BIT(13) 55b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OK 0x00 56b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_SHORTED 0x01 57b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OPEN 0x02 58b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_UNKNOWN 0x07 59b050f2f1SRadu Pirea (NXP OSS) 60b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_CONTROL 0x8040 61b050f2f1SRadu Pirea (NXP OSS) #define PORT_CONTROL_EN BIT(14) 62b050f2f1SRadu Pirea (NXP OSS) 63514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_ABILITIES 0x8046 64514def5dSRadu Pirea (NXP OSS) #define PTP_ABILITY BIT(3) 65514def5dSRadu Pirea (NXP OSS) 66b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_INFRA_CONTROL 0xAC00 67b050f2f1SRadu Pirea (NXP OSS) #define PORT_INFRA_CONTROL_EN BIT(14) 68b050f2f1SRadu Pirea (NXP OSS) 69b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RXID 0xAFCC 70b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TXID 0xAFCD 71b050f2f1SRadu Pirea (NXP OSS) #define ID_ENABLE BIT(15) 72b050f2f1SRadu Pirea (NXP OSS) 73b050f2f1SRadu Pirea (NXP OSS) #define VEND1_ABILITIES 0xAFC4 74b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ID_ABILITY BIT(15) 75b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ABILITY BIT(14) 76b050f2f1SRadu Pirea (NXP OSS) #define RMII_ABILITY BIT(10) 77b050f2f1SRadu Pirea (NXP OSS) #define REVMII_ABILITY BIT(9) 78b050f2f1SRadu Pirea (NXP OSS) #define MII_ABILITY BIT(8) 79b050f2f1SRadu Pirea (NXP OSS) #define SGMII_ABILITY BIT(0) 80b050f2f1SRadu Pirea (NXP OSS) 81b050f2f1SRadu Pirea (NXP OSS) #define VEND1_MII_BASIC_CONFIG 0xAFC6 82*8ba57205SRadu Pirea (OSS) #define MII_BASIC_CONFIG_REV BIT(4) 83b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_SGMII 0x9 84b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RGMII 0x7 85b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RMII 0x5 86b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_MII 0x4 87b050f2f1SRadu Pirea (NXP OSS) 88b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_COUNTER 0x8350 89b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_DROP_COUNTER 0x8352 90b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_LOSSES_AND_FAILURES 0x8353 91b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_GOOD_FRAME_CNT 0xA950 92b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_BAD_FRAME_CNT 0xA952 93b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_RXER_FRAME_CNT 0xA954 94b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_PREAMBLE_COUNT 0xAFCE 95b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_PREAMBLE_COUNT 0xAFCF 96b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_IPG_LENGTH 0xAFD0 97b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_IPG_LENGTH 0xAFD1 98b050f2f1SRadu Pirea (NXP OSS) #define COUNTER_EN BIT(15) 99b050f2f1SRadu Pirea (NXP OSS) 1007a71c8aaSRadu Pirea (NXP OSS) #define VEND1_PTP_CONFIG 0x1102 1017a71c8aaSRadu Pirea (NXP OSS) #define EXT_TRG_EDGE BIT(1) 1027a71c8aaSRadu Pirea (NXP OSS) #define PPS_OUT_POL BIT(2) 1037a71c8aaSRadu Pirea (NXP OSS) #define PPS_OUT_EN BIT(3) 1047a71c8aaSRadu Pirea (NXP OSS) 105514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_LOAD_CTRL 0x1105 106514def5dSRadu Pirea (NXP OSS) #define READ_LTC BIT(2) 107514def5dSRadu Pirea (NXP OSS) #define LOAD_LTC BIT(0) 108514def5dSRadu Pirea (NXP OSS) 109514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_WR_NSEC_0 0x1106 110514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_WR_NSEC_1 0x1107 111514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_WR_SEC_0 0x1108 112514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_WR_SEC_1 0x1109 113514def5dSRadu Pirea (NXP OSS) 114514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_RD_NSEC_0 0x110A 115514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_RD_NSEC_1 0x110B 116514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_RD_SEC_0 0x110C 117514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_RD_SEC_1 0x110D 118514def5dSRadu Pirea (NXP OSS) 119514def5dSRadu Pirea (NXP OSS) #define VEND1_RATE_ADJ_SUBNS_0 0x110F 120514def5dSRadu Pirea (NXP OSS) #define VEND1_RATE_ADJ_SUBNS_1 0x1110 121514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_LD BIT(15) 122514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_DIR BIT(14) 123514def5dSRadu Pirea (NXP OSS) 124514def5dSRadu Pirea (NXP OSS) #define VEND1_HW_LTC_LOCK_CTRL 0x1115 125514def5dSRadu Pirea (NXP OSS) #define HW_LTC_LOCK_EN BIT(0) 126514def5dSRadu Pirea (NXP OSS) 127514def5dSRadu Pirea (NXP OSS) #define VEND1_PTP_IRQ_EN 0x1131 128514def5dSRadu Pirea (NXP OSS) #define VEND1_PTP_IRQ_STATUS 0x1132 129514def5dSRadu Pirea (NXP OSS) #define PTP_IRQ_EGR_TS BIT(0) 130514def5dSRadu Pirea (NXP OSS) 131514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_TS_INSRT_CTRL 0x114D 132514def5dSRadu Pirea (NXP OSS) #define RX_TS_INSRT_MODE2 0x02 133514def5dSRadu Pirea (NXP OSS) 134514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_0 0x114E 135514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_1_SEQ_ID 0x114F 136514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_2_NSEC_15_0 0x1150 137514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_3 0x1151 138514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_CTRL 0x1154 139514def5dSRadu Pirea (NXP OSS) 1407a71c8aaSRadu Pirea (NXP OSS) #define VEND1_EXT_TRG_TS_DATA_0 0x1121 1417a71c8aaSRadu Pirea (NXP OSS) #define VEND1_EXT_TRG_TS_DATA_1 0x1122 1427a71c8aaSRadu Pirea (NXP OSS) #define VEND1_EXT_TRG_TS_DATA_2 0x1123 1437a71c8aaSRadu Pirea (NXP OSS) #define VEND1_EXT_TRG_TS_DATA_3 0x1124 1447a71c8aaSRadu Pirea (NXP OSS) #define VEND1_EXT_TRG_TS_DATA_4 0x1125 1457a71c8aaSRadu Pirea (NXP OSS) #define VEND1_EXT_TRG_TS_CTRL 0x1126 1467a71c8aaSRadu Pirea (NXP OSS) 147514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_DOMAIN_NUMBER GENMASK(7, 0) 148514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_MSG_TYPE GENMASK(11, 8) 149514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_SEC_4_2 GENMASK(14, 2) 150514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_TS_VALID BIT(15) 151514def5dSRadu Pirea (NXP OSS) 152514def5dSRadu Pirea (NXP OSS) #define RING_DATA_3_NSEC_29_16 GENMASK(13, 0) 153514def5dSRadu Pirea (NXP OSS) #define RING_DATA_3_SEC_1_0 GENMASK(15, 14) 154514def5dSRadu Pirea (NXP OSS) #define RING_DATA_5_SEC_16_5 GENMASK(15, 4) 155514def5dSRadu Pirea (NXP OSS) #define RING_DONE BIT(0) 156514def5dSRadu Pirea (NXP OSS) 157514def5dSRadu Pirea (NXP OSS) #define TS_SEC_MASK GENMASK(1, 0) 158514def5dSRadu Pirea (NXP OSS) 159514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_ENABLES 0x8048 160514def5dSRadu Pirea (NXP OSS) #define PTP_ENABLE BIT(3) 161514def5dSRadu Pirea (NXP OSS) 162514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_PTP_CONTROL 0x9000 163514def5dSRadu Pirea (NXP OSS) #define PORT_PTP_CONTROL_BYPASS BIT(11) 164514def5dSRadu Pirea (NXP OSS) 165514def5dSRadu Pirea (NXP OSS) #define VEND1_PTP_CLK_PERIOD 0x1104 166514def5dSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_100BT1 15ULL 167514def5dSRadu Pirea (NXP OSS) 168514def5dSRadu Pirea (NXP OSS) #define VEND1_EVENT_MSG_FILT 0x1148 169514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_ALL 0x0F 170514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_NONE 0x00 171514def5dSRadu Pirea (NXP OSS) 172514def5dSRadu Pirea (NXP OSS) #define VEND1_TX_PIPE_DLY_NS 0x1149 173514def5dSRadu Pirea (NXP OSS) #define VEND1_TX_PIPEDLY_SUBNS 0x114A 174514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_PIPE_DLY_NS 0x114B 175514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_PIPEDLY_SUBNS 0x114C 176514def5dSRadu Pirea (NXP OSS) 1777a71c8aaSRadu Pirea (NXP OSS) #define VEND1_GPIO_FUNC_CONFIG_BASE 0x2C40 1787a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_EN BIT(15) 1797a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_PTP BIT(6) 1807a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PTP_TRIGGER 0x01 1817a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PPS_OUT 0x12 1827a71c8aaSRadu Pirea (NXP OSS) #define GPIO_DISABLE 0 1837a71c8aaSRadu Pirea (NXP OSS) #define GPIO_PPS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \ 1847a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PPS_OUT) 1857a71c8aaSRadu Pirea (NXP OSS) #define GPIO_EXTTS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \ 1867a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PTP_TRIGGER) 1877a71c8aaSRadu Pirea (NXP OSS) 188b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS 8000U 189b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE div_u64(RGMII_PERIOD_PS, 360) 190b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS 1644U 191b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS 2260U 192b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS 2000U 193b050f2f1SRadu Pirea (NXP OSS) 194514def5dSRadu Pirea (NXP OSS) #define PPM_TO_SUBNS_INC(ppb) div_u64(GENMASK(31, 0) * (ppb) * \ 195514def5dSRadu Pirea (NXP OSS) PTP_CLK_PERIOD_100BT1, NSEC_PER_SEC) 196514def5dSRadu Pirea (NXP OSS) 197514def5dSRadu Pirea (NXP OSS) #define NXP_C45_SKB_CB(skb) ((struct nxp_c45_skb_cb *)(skb)->cb) 198514def5dSRadu Pirea (NXP OSS) 199514def5dSRadu Pirea (NXP OSS) struct nxp_c45_skb_cb { 200514def5dSRadu Pirea (NXP OSS) struct ptp_header *header; 201514def5dSRadu Pirea (NXP OSS) unsigned int type; 202514def5dSRadu Pirea (NXP OSS) }; 203514def5dSRadu Pirea (NXP OSS) 204514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts { 205514def5dSRadu Pirea (NXP OSS) u32 nsec; 206514def5dSRadu Pirea (NXP OSS) u32 sec; 207514def5dSRadu Pirea (NXP OSS) u8 domain_number; 208514def5dSRadu Pirea (NXP OSS) u16 sequence_id; 209514def5dSRadu Pirea (NXP OSS) u8 msg_type; 210514def5dSRadu Pirea (NXP OSS) }; 211514def5dSRadu Pirea (NXP OSS) 212b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy { 213514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev; 214514def5dSRadu Pirea (NXP OSS) struct mii_timestamper mii_ts; 215514def5dSRadu Pirea (NXP OSS) struct ptp_clock *ptp_clock; 216514def5dSRadu Pirea (NXP OSS) struct ptp_clock_info caps; 217514def5dSRadu Pirea (NXP OSS) struct sk_buff_head tx_queue; 218514def5dSRadu Pirea (NXP OSS) struct sk_buff_head rx_queue; 219514def5dSRadu Pirea (NXP OSS) /* used to access the PTP registers atomic */ 220514def5dSRadu Pirea (NXP OSS) struct mutex ptp_lock; 221514def5dSRadu Pirea (NXP OSS) int hwts_tx; 222514def5dSRadu Pirea (NXP OSS) int hwts_rx; 223b050f2f1SRadu Pirea (NXP OSS) u32 tx_delay; 224b050f2f1SRadu Pirea (NXP OSS) u32 rx_delay; 2257a71c8aaSRadu Pirea (NXP OSS) struct timespec64 extts_ts; 2267a71c8aaSRadu Pirea (NXP OSS) int extts_index; 2277a71c8aaSRadu Pirea (NXP OSS) bool extts; 228b050f2f1SRadu Pirea (NXP OSS) }; 229b050f2f1SRadu Pirea (NXP OSS) 230b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy_stats { 231b050f2f1SRadu Pirea (NXP OSS) const char *name; 232b050f2f1SRadu Pirea (NXP OSS) u8 mmd; 233b050f2f1SRadu Pirea (NXP OSS) u16 reg; 234b050f2f1SRadu Pirea (NXP OSS) u8 off; 235b050f2f1SRadu Pirea (NXP OSS) u16 mask; 236b050f2f1SRadu Pirea (NXP OSS) }; 237b050f2f1SRadu Pirea (NXP OSS) 238514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_poll_txts(struct phy_device *phydev) 239514def5dSRadu Pirea (NXP OSS) { 240514def5dSRadu Pirea (NXP OSS) return phydev->irq <= 0; 241514def5dSRadu Pirea (NXP OSS) } 242514def5dSRadu Pirea (NXP OSS) 243514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, 244514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts, 245514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts) 246514def5dSRadu Pirea (NXP OSS) { 247514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 248514def5dSRadu Pirea (NXP OSS) 249514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_LOAD_CTRL, 250514def5dSRadu Pirea (NXP OSS) READ_LTC); 251514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 252514def5dSRadu Pirea (NXP OSS) VEND1_LTC_RD_NSEC_0); 253514def5dSRadu Pirea (NXP OSS) ts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 254514def5dSRadu Pirea (NXP OSS) VEND1_LTC_RD_NSEC_1) << 16; 255514def5dSRadu Pirea (NXP OSS) ts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 256514def5dSRadu Pirea (NXP OSS) VEND1_LTC_RD_SEC_0); 257514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 258514def5dSRadu Pirea (NXP OSS) VEND1_LTC_RD_SEC_1) << 16; 259514def5dSRadu Pirea (NXP OSS) 260514def5dSRadu Pirea (NXP OSS) return 0; 261514def5dSRadu Pirea (NXP OSS) } 262514def5dSRadu Pirea (NXP OSS) 263514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp, 264514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts, 265514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts) 266514def5dSRadu Pirea (NXP OSS) { 267514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 268514def5dSRadu Pirea (NXP OSS) 269514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 270514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, ts, sts); 271514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 272514def5dSRadu Pirea (NXP OSS) 273514def5dSRadu Pirea (NXP OSS) return 0; 274514def5dSRadu Pirea (NXP OSS) } 275514def5dSRadu Pirea (NXP OSS) 276514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, 277514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts) 278514def5dSRadu Pirea (NXP OSS) { 279514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 280514def5dSRadu Pirea (NXP OSS) 281514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_NSEC_0, 282514def5dSRadu Pirea (NXP OSS) ts->tv_nsec); 283514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_NSEC_1, 284514def5dSRadu Pirea (NXP OSS) ts->tv_nsec >> 16); 285514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_SEC_0, 286514def5dSRadu Pirea (NXP OSS) ts->tv_sec); 287514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_SEC_1, 288514def5dSRadu Pirea (NXP OSS) ts->tv_sec >> 16); 289514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_LOAD_CTRL, 290514def5dSRadu Pirea (NXP OSS) LOAD_LTC); 291514def5dSRadu Pirea (NXP OSS) 292514def5dSRadu Pirea (NXP OSS) return 0; 293514def5dSRadu Pirea (NXP OSS) } 294514def5dSRadu Pirea (NXP OSS) 295514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_settime64(struct ptp_clock_info *ptp, 296514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts) 297514def5dSRadu Pirea (NXP OSS) { 298514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 299514def5dSRadu Pirea (NXP OSS) 300514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 301514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, ts); 302514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 303514def5dSRadu Pirea (NXP OSS) 304514def5dSRadu Pirea (NXP OSS) return 0; 305514def5dSRadu Pirea (NXP OSS) } 306514def5dSRadu Pirea (NXP OSS) 307514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 308514def5dSRadu Pirea (NXP OSS) { 309514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 310514def5dSRadu Pirea (NXP OSS) s32 ppb = scaled_ppm_to_ppb(scaled_ppm); 311514def5dSRadu Pirea (NXP OSS) u64 subns_inc_val; 312514def5dSRadu Pirea (NXP OSS) bool inc; 313514def5dSRadu Pirea (NXP OSS) 314514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 315514def5dSRadu Pirea (NXP OSS) inc = ppb >= 0; 316514def5dSRadu Pirea (NXP OSS) ppb = abs(ppb); 317514def5dSRadu Pirea (NXP OSS) 318514def5dSRadu Pirea (NXP OSS) subns_inc_val = PPM_TO_SUBNS_INC(ppb); 319514def5dSRadu Pirea (NXP OSS) 320514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_RATE_ADJ_SUBNS_0, 321514def5dSRadu Pirea (NXP OSS) subns_inc_val); 322514def5dSRadu Pirea (NXP OSS) subns_inc_val >>= 16; 323514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_LD; 324514def5dSRadu Pirea (NXP OSS) if (inc) 325514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_DIR; 326514def5dSRadu Pirea (NXP OSS) 327514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_RATE_ADJ_SUBNS_1, 328514def5dSRadu Pirea (NXP OSS) subns_inc_val); 329514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 330514def5dSRadu Pirea (NXP OSS) 331514def5dSRadu Pirea (NXP OSS) return 0; 332514def5dSRadu Pirea (NXP OSS) } 333514def5dSRadu Pirea (NXP OSS) 334514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) 335514def5dSRadu Pirea (NXP OSS) { 336514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 337514def5dSRadu Pirea (NXP OSS) struct timespec64 now, then; 338514def5dSRadu Pirea (NXP OSS) 339514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 340514def5dSRadu Pirea (NXP OSS) then = ns_to_timespec64(delta); 341514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, &now, NULL); 342514def5dSRadu Pirea (NXP OSS) now = timespec64_add(now, then); 343514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, &now); 344514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 345514def5dSRadu Pirea (NXP OSS) 346514def5dSRadu Pirea (NXP OSS) return 0; 347514def5dSRadu Pirea (NXP OSS) } 348514def5dSRadu Pirea (NXP OSS) 349514def5dSRadu Pirea (NXP OSS) static void nxp_c45_reconstruct_ts(struct timespec64 *ts, 350514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 351514def5dSRadu Pirea (NXP OSS) { 352514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = hwts->nsec; 353514def5dSRadu Pirea (NXP OSS) if ((ts->tv_sec & TS_SEC_MASK) < (hwts->sec & TS_SEC_MASK)) 354661fef56SVladimir Oltean ts->tv_sec -= TS_SEC_MASK + 1; 355514def5dSRadu Pirea (NXP OSS) ts->tv_sec &= ~TS_SEC_MASK; 356514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= hwts->sec & TS_SEC_MASK; 357514def5dSRadu Pirea (NXP OSS) } 358514def5dSRadu Pirea (NXP OSS) 359514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_match_ts(struct ptp_header *header, 360514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts, 361514def5dSRadu Pirea (NXP OSS) unsigned int type) 362514def5dSRadu Pirea (NXP OSS) { 363514def5dSRadu Pirea (NXP OSS) return ntohs(header->sequence_id) == hwts->sequence_id && 364514def5dSRadu Pirea (NXP OSS) ptp_get_msgtype(header, type) == hwts->msg_type && 365514def5dSRadu Pirea (NXP OSS) header->domain_number == hwts->domain_number; 366514def5dSRadu Pirea (NXP OSS) } 367514def5dSRadu Pirea (NXP OSS) 3687a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_get_extts(struct nxp_c45_phy *priv, 3697a71c8aaSRadu Pirea (NXP OSS) struct timespec64 *extts) 3707a71c8aaSRadu Pirea (NXP OSS) { 3717a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3727a71c8aaSRadu Pirea (NXP OSS) VEND1_EXT_TRG_TS_DATA_0); 3737a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3747a71c8aaSRadu Pirea (NXP OSS) VEND1_EXT_TRG_TS_DATA_1) << 16; 3757a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3767a71c8aaSRadu Pirea (NXP OSS) VEND1_EXT_TRG_TS_DATA_2); 3777a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 3787a71c8aaSRadu Pirea (NXP OSS) VEND1_EXT_TRG_TS_DATA_3) << 16; 3797a71c8aaSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EXT_TRG_TS_CTRL, 3807a71c8aaSRadu Pirea (NXP OSS) RING_DONE); 3817a71c8aaSRadu Pirea (NXP OSS) } 3827a71c8aaSRadu Pirea (NXP OSS) 383514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv, 384514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts) 385514def5dSRadu Pirea (NXP OSS) { 386514def5dSRadu Pirea (NXP OSS) bool valid; 387514def5dSRadu Pirea (NXP OSS) u16 reg; 388514def5dSRadu Pirea (NXP OSS) 389514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock); 390514def5dSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL, 391514def5dSRadu Pirea (NXP OSS) RING_DONE); 392514def5dSRadu Pirea (NXP OSS) reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0); 393514def5dSRadu Pirea (NXP OSS) valid = !!(reg & RING_DATA_0_TS_VALID); 394514def5dSRadu Pirea (NXP OSS) if (!valid) 395514def5dSRadu Pirea (NXP OSS) goto nxp_c45_get_hwtxts_out; 396514def5dSRadu Pirea (NXP OSS) 397514def5dSRadu Pirea (NXP OSS) hwts->domain_number = reg; 398514def5dSRadu Pirea (NXP OSS) hwts->msg_type = (reg & RING_DATA_0_MSG_TYPE) >> 8; 399514def5dSRadu Pirea (NXP OSS) hwts->sec = (reg & RING_DATA_0_SEC_4_2) >> 10; 400514def5dSRadu Pirea (NXP OSS) hwts->sequence_id = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 401514def5dSRadu Pirea (NXP OSS) VEND1_EGR_RING_DATA_1_SEQ_ID); 402514def5dSRadu Pirea (NXP OSS) hwts->nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, 403514def5dSRadu Pirea (NXP OSS) VEND1_EGR_RING_DATA_2_NSEC_15_0); 404514def5dSRadu Pirea (NXP OSS) reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_3); 405514def5dSRadu Pirea (NXP OSS) hwts->nsec |= (reg & RING_DATA_3_NSEC_29_16) << 16; 406514def5dSRadu Pirea (NXP OSS) hwts->sec |= (reg & RING_DATA_3_SEC_1_0) >> 14; 407514def5dSRadu Pirea (NXP OSS) 408514def5dSRadu Pirea (NXP OSS) nxp_c45_get_hwtxts_out: 409514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock); 410514def5dSRadu Pirea (NXP OSS) return valid; 411514def5dSRadu Pirea (NXP OSS) } 412514def5dSRadu Pirea (NXP OSS) 413514def5dSRadu Pirea (NXP OSS) static void nxp_c45_process_txts(struct nxp_c45_phy *priv, 414514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *txts) 415514def5dSRadu Pirea (NXP OSS) { 416514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, *tmp, *skb_match = NULL; 417514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps shhwtstamps; 418514def5dSRadu Pirea (NXP OSS) struct timespec64 ts; 419514def5dSRadu Pirea (NXP OSS) unsigned long flags; 420514def5dSRadu Pirea (NXP OSS) bool ts_match; 421514def5dSRadu Pirea (NXP OSS) s64 ts_ns; 422514def5dSRadu Pirea (NXP OSS) 423514def5dSRadu Pirea (NXP OSS) spin_lock_irqsave(&priv->tx_queue.lock, flags); 424514def5dSRadu Pirea (NXP OSS) skb_queue_walk_safe(&priv->tx_queue, skb, tmp) { 425514def5dSRadu Pirea (NXP OSS) ts_match = nxp_c45_match_ts(NXP_C45_SKB_CB(skb)->header, txts, 426514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type); 427514def5dSRadu Pirea (NXP OSS) if (!ts_match) 428514def5dSRadu Pirea (NXP OSS) continue; 429514def5dSRadu Pirea (NXP OSS) skb_match = skb; 430514def5dSRadu Pirea (NXP OSS) __skb_unlink(skb, &priv->tx_queue); 431514def5dSRadu Pirea (NXP OSS) break; 432514def5dSRadu Pirea (NXP OSS) } 433514def5dSRadu Pirea (NXP OSS) spin_unlock_irqrestore(&priv->tx_queue.lock, flags); 434514def5dSRadu Pirea (NXP OSS) 435514def5dSRadu Pirea (NXP OSS) if (skb_match) { 436514def5dSRadu Pirea (NXP OSS) nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL); 437514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, txts); 438514def5dSRadu Pirea (NXP OSS) memset(&shhwtstamps, 0, sizeof(shhwtstamps)); 439514def5dSRadu Pirea (NXP OSS) ts_ns = timespec64_to_ns(&ts); 440514def5dSRadu Pirea (NXP OSS) shhwtstamps.hwtstamp = ns_to_ktime(ts_ns); 441514def5dSRadu Pirea (NXP OSS) skb_complete_tx_timestamp(skb_match, &shhwtstamps); 442514def5dSRadu Pirea (NXP OSS) } else { 443514def5dSRadu Pirea (NXP OSS) phydev_warn(priv->phydev, 444514def5dSRadu Pirea (NXP OSS) "the tx timestamp doesn't match with any skb\n"); 445514def5dSRadu Pirea (NXP OSS) } 446514def5dSRadu Pirea (NXP OSS) } 447514def5dSRadu Pirea (NXP OSS) 448514def5dSRadu Pirea (NXP OSS) static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp) 449514def5dSRadu Pirea (NXP OSS) { 450514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 451514def5dSRadu Pirea (NXP OSS) bool poll_txts = nxp_c45_poll_txts(priv->phydev); 452514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps *shhwtstamps_rx; 4537a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_event event; 454514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts; 455514def5dSRadu Pirea (NXP OSS) bool reschedule = false; 456514def5dSRadu Pirea (NXP OSS) struct timespec64 ts; 457514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb; 458514def5dSRadu Pirea (NXP OSS) bool txts_valid; 459514def5dSRadu Pirea (NXP OSS) u32 ts_raw; 460514def5dSRadu Pirea (NXP OSS) 461514def5dSRadu Pirea (NXP OSS) while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) { 462514def5dSRadu Pirea (NXP OSS) txts_valid = nxp_c45_get_hwtxts(priv, &hwts); 463514def5dSRadu Pirea (NXP OSS) if (unlikely(!txts_valid)) { 464514def5dSRadu Pirea (NXP OSS) /* Still more skbs in the queue */ 465514def5dSRadu Pirea (NXP OSS) reschedule = true; 466514def5dSRadu Pirea (NXP OSS) break; 467514def5dSRadu Pirea (NXP OSS) } 468514def5dSRadu Pirea (NXP OSS) 469514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts); 470514def5dSRadu Pirea (NXP OSS) } 471514def5dSRadu Pirea (NXP OSS) 472514def5dSRadu Pirea (NXP OSS) while ((skb = skb_dequeue(&priv->rx_queue)) != NULL) { 473109258edSVladimir Oltean nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL); 474514def5dSRadu Pirea (NXP OSS) ts_raw = __be32_to_cpu(NXP_C45_SKB_CB(skb)->header->reserved2); 475514def5dSRadu Pirea (NXP OSS) hwts.sec = ts_raw >> 30; 476514def5dSRadu Pirea (NXP OSS) hwts.nsec = ts_raw & GENMASK(29, 0); 477514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, &hwts); 478514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx = skb_hwtstamps(skb); 479514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx->hwtstamp = ns_to_ktime(timespec64_to_ns(&ts)); 480514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header->reserved2 = 0; 481a3d73e15SSebastian Andrzej Siewior netif_rx(skb); 482514def5dSRadu Pirea (NXP OSS) } 483514def5dSRadu Pirea (NXP OSS) 4847a71c8aaSRadu Pirea (NXP OSS) if (priv->extts) { 4857a71c8aaSRadu Pirea (NXP OSS) nxp_c45_get_extts(priv, &ts); 4867a71c8aaSRadu Pirea (NXP OSS) if (timespec64_compare(&ts, &priv->extts_ts) != 0) { 4877a71c8aaSRadu Pirea (NXP OSS) priv->extts_ts = ts; 4887a71c8aaSRadu Pirea (NXP OSS) event.index = priv->extts_index; 4897a71c8aaSRadu Pirea (NXP OSS) event.type = PTP_CLOCK_EXTTS; 4907a71c8aaSRadu Pirea (NXP OSS) event.timestamp = ns_to_ktime(timespec64_to_ns(&ts)); 4917a71c8aaSRadu Pirea (NXP OSS) ptp_clock_event(priv->ptp_clock, &event); 4927a71c8aaSRadu Pirea (NXP OSS) } 4937a71c8aaSRadu Pirea (NXP OSS) reschedule = true; 4947a71c8aaSRadu Pirea (NXP OSS) } 4957a71c8aaSRadu Pirea (NXP OSS) 496514def5dSRadu Pirea (NXP OSS) return reschedule ? 1 : -1; 497514def5dSRadu Pirea (NXP OSS) } 498514def5dSRadu Pirea (NXP OSS) 4997a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_gpio_config(struct nxp_c45_phy *priv, 5007a71c8aaSRadu Pirea (NXP OSS) int pin, u16 pin_cfg) 5017a71c8aaSRadu Pirea (NXP OSS) { 5027a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 5037a71c8aaSRadu Pirea (NXP OSS) 5047a71c8aaSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, 5057a71c8aaSRadu Pirea (NXP OSS) VEND1_GPIO_FUNC_CONFIG_BASE + pin, pin_cfg); 5067a71c8aaSRadu Pirea (NXP OSS) } 5077a71c8aaSRadu Pirea (NXP OSS) 5087a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_perout_enable(struct nxp_c45_phy *priv, 5097a71c8aaSRadu Pirea (NXP OSS) struct ptp_perout_request *perout, int on) 5107a71c8aaSRadu Pirea (NXP OSS) { 5117a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 5127a71c8aaSRadu Pirea (NXP OSS) int pin; 5137a71c8aaSRadu Pirea (NXP OSS) 5147a71c8aaSRadu Pirea (NXP OSS) if (perout->flags & ~PTP_PEROUT_PHASE) 5157a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 5167a71c8aaSRadu Pirea (NXP OSS) 5177a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_PEROUT, perout->index); 5187a71c8aaSRadu Pirea (NXP OSS) if (pin < 0) 5197a71c8aaSRadu Pirea (NXP OSS) return pin; 5207a71c8aaSRadu Pirea (NXP OSS) 5217a71c8aaSRadu Pirea (NXP OSS) if (!on) { 5227a71c8aaSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CONFIG, 5237a71c8aaSRadu Pirea (NXP OSS) PPS_OUT_EN); 5247a71c8aaSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CONFIG, 5257a71c8aaSRadu Pirea (NXP OSS) PPS_OUT_POL); 5267a71c8aaSRadu Pirea (NXP OSS) 5277a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); 5287a71c8aaSRadu Pirea (NXP OSS) 5297a71c8aaSRadu Pirea (NXP OSS) return 0; 5307a71c8aaSRadu Pirea (NXP OSS) } 5317a71c8aaSRadu Pirea (NXP OSS) 5327a71c8aaSRadu Pirea (NXP OSS) /* The PPS signal is fixed to 1 second and is always generated when the 5337a71c8aaSRadu Pirea (NXP OSS) * seconds counter is incremented. The start time is not configurable. 5347a71c8aaSRadu Pirea (NXP OSS) * If the clock is adjusted, the PPS signal is automatically readjusted. 5357a71c8aaSRadu Pirea (NXP OSS) */ 5367a71c8aaSRadu Pirea (NXP OSS) if (perout->period.sec != 1 || perout->period.nsec != 0) { 5377a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The period can be set only to 1 second."); 5387a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 5397a71c8aaSRadu Pirea (NXP OSS) } 5407a71c8aaSRadu Pirea (NXP OSS) 5417a71c8aaSRadu Pirea (NXP OSS) if (!(perout->flags & PTP_PEROUT_PHASE)) { 5427a71c8aaSRadu Pirea (NXP OSS) if (perout->start.sec != 0 || perout->start.nsec != 0) { 5437a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The start time is not configurable. Should be set to 0 seconds and 0 nanoseconds."); 5447a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 5457a71c8aaSRadu Pirea (NXP OSS) } 5467a71c8aaSRadu Pirea (NXP OSS) } else { 5477a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec != 0 && 5487a71c8aaSRadu Pirea (NXP OSS) perout->phase.nsec != (NSEC_PER_SEC >> 1)) { 5497a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The phase can be set only to 0 or 500000000 nanoseconds."); 5507a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 5517a71c8aaSRadu Pirea (NXP OSS) } 5527a71c8aaSRadu Pirea (NXP OSS) 5537a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec == 0) 5547a71c8aaSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 5557a71c8aaSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, PPS_OUT_POL); 5567a71c8aaSRadu Pirea (NXP OSS) else 5577a71c8aaSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 5587a71c8aaSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, PPS_OUT_POL); 5597a71c8aaSRadu Pirea (NXP OSS) } 5607a71c8aaSRadu Pirea (NXP OSS) 5617a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_PPS_OUT_CFG); 5627a71c8aaSRadu Pirea (NXP OSS) 5637a71c8aaSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CONFIG, PPS_OUT_EN); 5647a71c8aaSRadu Pirea (NXP OSS) 5657a71c8aaSRadu Pirea (NXP OSS) return 0; 5667a71c8aaSRadu Pirea (NXP OSS) } 5677a71c8aaSRadu Pirea (NXP OSS) 5687a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_extts_enable(struct nxp_c45_phy *priv, 5697a71c8aaSRadu Pirea (NXP OSS) struct ptp_extts_request *extts, int on) 5707a71c8aaSRadu Pirea (NXP OSS) { 5717a71c8aaSRadu Pirea (NXP OSS) int pin; 5727a71c8aaSRadu Pirea (NXP OSS) 5737a71c8aaSRadu Pirea (NXP OSS) if (extts->flags & ~(PTP_ENABLE_FEATURE | 5747a71c8aaSRadu Pirea (NXP OSS) PTP_RISING_EDGE | 5757a71c8aaSRadu Pirea (NXP OSS) PTP_FALLING_EDGE | 5767a71c8aaSRadu Pirea (NXP OSS) PTP_STRICT_FLAGS)) 5777a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 5787a71c8aaSRadu Pirea (NXP OSS) 5797a71c8aaSRadu Pirea (NXP OSS) /* Sampling on both edges is not supported */ 5807a71c8aaSRadu Pirea (NXP OSS) if ((extts->flags & PTP_RISING_EDGE) && 5817a71c8aaSRadu Pirea (NXP OSS) (extts->flags & PTP_FALLING_EDGE)) 5827a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 5837a71c8aaSRadu Pirea (NXP OSS) 5847a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_EXTTS, extts->index); 5857a71c8aaSRadu Pirea (NXP OSS) if (pin < 0) 5867a71c8aaSRadu Pirea (NXP OSS) return pin; 5877a71c8aaSRadu Pirea (NXP OSS) 5887a71c8aaSRadu Pirea (NXP OSS) if (!on) { 5897a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE); 5907a71c8aaSRadu Pirea (NXP OSS) priv->extts = false; 5917a71c8aaSRadu Pirea (NXP OSS) 5927a71c8aaSRadu Pirea (NXP OSS) return 0; 5937a71c8aaSRadu Pirea (NXP OSS) } 5947a71c8aaSRadu Pirea (NXP OSS) 5957a71c8aaSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE) 5967a71c8aaSRadu Pirea (NXP OSS) phy_clear_bits_mmd(priv->phydev, MDIO_MMD_VEND1, 5977a71c8aaSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE); 5987a71c8aaSRadu Pirea (NXP OSS) 5997a71c8aaSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE) 6007a71c8aaSRadu Pirea (NXP OSS) phy_set_bits_mmd(priv->phydev, MDIO_MMD_VEND1, 6017a71c8aaSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE); 6027a71c8aaSRadu Pirea (NXP OSS) 6037a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_EXTTS_OUT_CFG); 6047a71c8aaSRadu Pirea (NXP OSS) priv->extts = true; 6057a71c8aaSRadu Pirea (NXP OSS) priv->extts_index = extts->index; 6067a71c8aaSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 6077a71c8aaSRadu Pirea (NXP OSS) 6087a71c8aaSRadu Pirea (NXP OSS) return 0; 6097a71c8aaSRadu Pirea (NXP OSS) } 6107a71c8aaSRadu Pirea (NXP OSS) 6117a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_enable(struct ptp_clock_info *ptp, 6127a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_request *req, int on) 6137a71c8aaSRadu Pirea (NXP OSS) { 6147a71c8aaSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps); 6157a71c8aaSRadu Pirea (NXP OSS) 6167a71c8aaSRadu Pirea (NXP OSS) switch (req->type) { 6177a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_EXTTS: 6187a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_extts_enable(priv, &req->extts, on); 6197a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_PEROUT: 6207a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_perout_enable(priv, &req->perout, on); 6217a71c8aaSRadu Pirea (NXP OSS) default: 6227a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 6237a71c8aaSRadu Pirea (NXP OSS) } 6247a71c8aaSRadu Pirea (NXP OSS) } 6257a71c8aaSRadu Pirea (NXP OSS) 6267a71c8aaSRadu Pirea (NXP OSS) static struct ptp_pin_desc nxp_c45_ptp_pins[] = { 6277a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio0", 0, PTP_PF_NONE}, 6287a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio1", 1, PTP_PF_NONE}, 6297a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio2", 2, PTP_PF_NONE}, 6307a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio3", 3, PTP_PF_NONE}, 6317a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio4", 4, PTP_PF_NONE}, 6327a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio5", 5, PTP_PF_NONE}, 6337a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio6", 6, PTP_PF_NONE}, 6347a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio7", 7, PTP_PF_NONE}, 6357a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio8", 8, PTP_PF_NONE}, 6367a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio9", 9, PTP_PF_NONE}, 6377a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio10", 10, PTP_PF_NONE}, 6387a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio11", 11, PTP_PF_NONE}, 6397a71c8aaSRadu Pirea (NXP OSS) }; 6407a71c8aaSRadu Pirea (NXP OSS) 6417a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, 6427a71c8aaSRadu Pirea (NXP OSS) enum ptp_pin_function func, unsigned int chan) 6437a71c8aaSRadu Pirea (NXP OSS) { 6447a71c8aaSRadu Pirea (NXP OSS) if (pin >= ARRAY_SIZE(nxp_c45_ptp_pins)) 6457a71c8aaSRadu Pirea (NXP OSS) return -EINVAL; 6467a71c8aaSRadu Pirea (NXP OSS) 6477a71c8aaSRadu Pirea (NXP OSS) switch (func) { 6487a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_NONE: 6497a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_PEROUT: 6507a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_EXTTS: 6517a71c8aaSRadu Pirea (NXP OSS) break; 6527a71c8aaSRadu Pirea (NXP OSS) default: 6537a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP; 6547a71c8aaSRadu Pirea (NXP OSS) } 6557a71c8aaSRadu Pirea (NXP OSS) 6567a71c8aaSRadu Pirea (NXP OSS) return 0; 6577a71c8aaSRadu Pirea (NXP OSS) } 6587a71c8aaSRadu Pirea (NXP OSS) 659514def5dSRadu Pirea (NXP OSS) static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv) 660514def5dSRadu Pirea (NXP OSS) { 661514def5dSRadu Pirea (NXP OSS) priv->caps = (struct ptp_clock_info) { 662514def5dSRadu Pirea (NXP OSS) .owner = THIS_MODULE, 663514def5dSRadu Pirea (NXP OSS) .name = "NXP C45 PHC", 664514def5dSRadu Pirea (NXP OSS) .max_adj = 16666666, 665514def5dSRadu Pirea (NXP OSS) .adjfine = nxp_c45_ptp_adjfine, 666514def5dSRadu Pirea (NXP OSS) .adjtime = nxp_c45_ptp_adjtime, 667514def5dSRadu Pirea (NXP OSS) .gettimex64 = nxp_c45_ptp_gettimex64, 668514def5dSRadu Pirea (NXP OSS) .settime64 = nxp_c45_ptp_settime64, 6697a71c8aaSRadu Pirea (NXP OSS) .enable = nxp_c45_ptp_enable, 6707a71c8aaSRadu Pirea (NXP OSS) .verify = nxp_c45_ptp_verify_pin, 671514def5dSRadu Pirea (NXP OSS) .do_aux_work = nxp_c45_do_aux_work, 6727a71c8aaSRadu Pirea (NXP OSS) .pin_config = nxp_c45_ptp_pins, 6737a71c8aaSRadu Pirea (NXP OSS) .n_pins = ARRAY_SIZE(nxp_c45_ptp_pins), 6747a71c8aaSRadu Pirea (NXP OSS) .n_ext_ts = 1, 6757a71c8aaSRadu Pirea (NXP OSS) .n_per_out = 1, 676514def5dSRadu Pirea (NXP OSS) }; 677514def5dSRadu Pirea (NXP OSS) 678514def5dSRadu Pirea (NXP OSS) priv->ptp_clock = ptp_clock_register(&priv->caps, 679514def5dSRadu Pirea (NXP OSS) &priv->phydev->mdio.dev); 680514def5dSRadu Pirea (NXP OSS) 681514def5dSRadu Pirea (NXP OSS) if (IS_ERR(priv->ptp_clock)) 682514def5dSRadu Pirea (NXP OSS) return PTR_ERR(priv->ptp_clock); 683514def5dSRadu Pirea (NXP OSS) 684514def5dSRadu Pirea (NXP OSS) if (!priv->ptp_clock) 685514def5dSRadu Pirea (NXP OSS) return -ENOMEM; 686514def5dSRadu Pirea (NXP OSS) 687514def5dSRadu Pirea (NXP OSS) return 0; 688514def5dSRadu Pirea (NXP OSS) } 689514def5dSRadu Pirea (NXP OSS) 690514def5dSRadu Pirea (NXP OSS) static void nxp_c45_txtstamp(struct mii_timestamper *mii_ts, 691514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type) 692514def5dSRadu Pirea (NXP OSS) { 693514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 694514def5dSRadu Pirea (NXP OSS) mii_ts); 695514def5dSRadu Pirea (NXP OSS) 696514def5dSRadu Pirea (NXP OSS) switch (priv->hwts_tx) { 697514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_ON: 698514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type = type; 699514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = ptp_parse_header(skb, type); 700514def5dSRadu Pirea (NXP OSS) skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 701514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->tx_queue, skb); 702514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev)) 703514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 704514def5dSRadu Pirea (NXP OSS) break; 705514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_OFF: 706514def5dSRadu Pirea (NXP OSS) default: 707514def5dSRadu Pirea (NXP OSS) kfree_skb(skb); 708514def5dSRadu Pirea (NXP OSS) break; 709514def5dSRadu Pirea (NXP OSS) } 710514def5dSRadu Pirea (NXP OSS) } 711514def5dSRadu Pirea (NXP OSS) 712514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_rxtstamp(struct mii_timestamper *mii_ts, 713514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type) 714514def5dSRadu Pirea (NXP OSS) { 715514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 716514def5dSRadu Pirea (NXP OSS) mii_ts); 717514def5dSRadu Pirea (NXP OSS) struct ptp_header *header = ptp_parse_header(skb, type); 718514def5dSRadu Pirea (NXP OSS) 719514def5dSRadu Pirea (NXP OSS) if (!header) 720514def5dSRadu Pirea (NXP OSS) return false; 721514def5dSRadu Pirea (NXP OSS) 722514def5dSRadu Pirea (NXP OSS) if (!priv->hwts_rx) 723514def5dSRadu Pirea (NXP OSS) return false; 724514def5dSRadu Pirea (NXP OSS) 725514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = header; 726514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->rx_queue, skb); 727514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0); 728514def5dSRadu Pirea (NXP OSS) 729514def5dSRadu Pirea (NXP OSS) return true; 730514def5dSRadu Pirea (NXP OSS) } 731514def5dSRadu Pirea (NXP OSS) 732514def5dSRadu Pirea (NXP OSS) static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts, 733514def5dSRadu Pirea (NXP OSS) struct ifreq *ifreq) 734514def5dSRadu Pirea (NXP OSS) { 735514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 736514def5dSRadu Pirea (NXP OSS) mii_ts); 737514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev; 738514def5dSRadu Pirea (NXP OSS) struct hwtstamp_config cfg; 739514def5dSRadu Pirea (NXP OSS) 740514def5dSRadu Pirea (NXP OSS) if (copy_from_user(&cfg, ifreq->ifr_data, sizeof(cfg))) 741514def5dSRadu Pirea (NXP OSS) return -EFAULT; 742514def5dSRadu Pirea (NXP OSS) 743514def5dSRadu Pirea (NXP OSS) if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ON) 744514def5dSRadu Pirea (NXP OSS) return -ERANGE; 745514def5dSRadu Pirea (NXP OSS) 746514def5dSRadu Pirea (NXP OSS) priv->hwts_tx = cfg.tx_type; 747514def5dSRadu Pirea (NXP OSS) 748514def5dSRadu Pirea (NXP OSS) switch (cfg.rx_filter) { 749514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_NONE: 750514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 0; 751514def5dSRadu Pirea (NXP OSS) break; 752514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 753514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 754514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 755514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 1; 756514def5dSRadu Pirea (NXP OSS) cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; 757514def5dSRadu Pirea (NXP OSS) break; 758514def5dSRadu Pirea (NXP OSS) default: 759514def5dSRadu Pirea (NXP OSS) return -ERANGE; 760514def5dSRadu Pirea (NXP OSS) } 761514def5dSRadu Pirea (NXP OSS) 762514def5dSRadu Pirea (NXP OSS) if (priv->hwts_rx || priv->hwts_tx) { 763514def5dSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_EVENT_MSG_FILT, 764514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_ALL); 765514def5dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 766514def5dSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL, 767514def5dSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS); 768514def5dSRadu Pirea (NXP OSS) } else { 769514def5dSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_EVENT_MSG_FILT, 770514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_NONE); 771514def5dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_PTP_CONTROL, 772514def5dSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS); 773514def5dSRadu Pirea (NXP OSS) } 774514def5dSRadu Pirea (NXP OSS) 775514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev)) 776514def5dSRadu Pirea (NXP OSS) goto nxp_c45_no_ptp_irq; 777514def5dSRadu Pirea (NXP OSS) 778514def5dSRadu Pirea (NXP OSS) if (priv->hwts_tx) 779514def5dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 780514def5dSRadu Pirea (NXP OSS) VEND1_PTP_IRQ_EN, PTP_IRQ_EGR_TS); 781514def5dSRadu Pirea (NXP OSS) else 782514def5dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 783514def5dSRadu Pirea (NXP OSS) VEND1_PTP_IRQ_EN, PTP_IRQ_EGR_TS); 784514def5dSRadu Pirea (NXP OSS) 785514def5dSRadu Pirea (NXP OSS) nxp_c45_no_ptp_irq: 786514def5dSRadu Pirea (NXP OSS) return copy_to_user(ifreq->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 787514def5dSRadu Pirea (NXP OSS) } 788514def5dSRadu Pirea (NXP OSS) 789514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ts_info(struct mii_timestamper *mii_ts, 790514def5dSRadu Pirea (NXP OSS) struct ethtool_ts_info *ts_info) 791514def5dSRadu Pirea (NXP OSS) { 792514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy, 793514def5dSRadu Pirea (NXP OSS) mii_ts); 794514def5dSRadu Pirea (NXP OSS) 795514def5dSRadu Pirea (NXP OSS) ts_info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | 796514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RX_HARDWARE | 797514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RAW_HARDWARE; 798514def5dSRadu Pirea (NXP OSS) ts_info->phc_index = ptp_clock_index(priv->ptp_clock); 799514def5dSRadu Pirea (NXP OSS) ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); 800514def5dSRadu Pirea (NXP OSS) ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | 801514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | 802514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | 803514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT); 804514def5dSRadu Pirea (NXP OSS) 805514def5dSRadu Pirea (NXP OSS) return 0; 806514def5dSRadu Pirea (NXP OSS) } 807514def5dSRadu Pirea (NXP OSS) 808b050f2f1SRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats nxp_c45_hw_stats[] = { 809b050f2f1SRadu Pirea (NXP OSS) { "phy_symbol_error_cnt", MDIO_MMD_VEND1, 810b050f2f1SRadu Pirea (NXP OSS) VEND1_SYMBOL_ERROR_COUNTER, 0, GENMASK(15, 0) }, 811b050f2f1SRadu Pirea (NXP OSS) { "phy_link_status_drop_cnt", MDIO_MMD_VEND1, 812b050f2f1SRadu Pirea (NXP OSS) VEND1_LINK_DROP_COUNTER, 8, GENMASK(13, 8) }, 813b050f2f1SRadu Pirea (NXP OSS) { "phy_link_availability_drop_cnt", MDIO_MMD_VEND1, 814b050f2f1SRadu Pirea (NXP OSS) VEND1_LINK_DROP_COUNTER, 0, GENMASK(5, 0) }, 815b050f2f1SRadu Pirea (NXP OSS) { "phy_link_loss_cnt", MDIO_MMD_VEND1, 816b050f2f1SRadu Pirea (NXP OSS) VEND1_LINK_LOSSES_AND_FAILURES, 10, GENMASK(15, 10) }, 817b050f2f1SRadu Pirea (NXP OSS) { "phy_link_failure_cnt", MDIO_MMD_VEND1, 818b050f2f1SRadu Pirea (NXP OSS) VEND1_LINK_LOSSES_AND_FAILURES, 0, GENMASK(9, 0) }, 819b050f2f1SRadu Pirea (NXP OSS) { "r_good_frame_cnt", MDIO_MMD_VEND1, 820b050f2f1SRadu Pirea (NXP OSS) VEND1_R_GOOD_FRAME_CNT, 0, GENMASK(15, 0) }, 821b050f2f1SRadu Pirea (NXP OSS) { "r_bad_frame_cnt", MDIO_MMD_VEND1, 822b050f2f1SRadu Pirea (NXP OSS) VEND1_R_BAD_FRAME_CNT, 0, GENMASK(15, 0) }, 823b050f2f1SRadu Pirea (NXP OSS) { "r_rxer_frame_cnt", MDIO_MMD_VEND1, 824b050f2f1SRadu Pirea (NXP OSS) VEND1_R_RXER_FRAME_CNT, 0, GENMASK(15, 0) }, 825b050f2f1SRadu Pirea (NXP OSS) { "rx_preamble_count", MDIO_MMD_VEND1, 826b050f2f1SRadu Pirea (NXP OSS) VEND1_RX_PREAMBLE_COUNT, 0, GENMASK(5, 0) }, 827b050f2f1SRadu Pirea (NXP OSS) { "tx_preamble_count", MDIO_MMD_VEND1, 828b050f2f1SRadu Pirea (NXP OSS) VEND1_TX_PREAMBLE_COUNT, 0, GENMASK(5, 0) }, 829b050f2f1SRadu Pirea (NXP OSS) { "rx_ipg_length", MDIO_MMD_VEND1, 830b050f2f1SRadu Pirea (NXP OSS) VEND1_RX_IPG_LENGTH, 0, GENMASK(8, 0) }, 831b050f2f1SRadu Pirea (NXP OSS) { "tx_ipg_length", MDIO_MMD_VEND1, 832b050f2f1SRadu Pirea (NXP OSS) VEND1_TX_IPG_LENGTH, 0, GENMASK(8, 0) }, 833b050f2f1SRadu Pirea (NXP OSS) }; 834b050f2f1SRadu Pirea (NXP OSS) 835b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev) 836b050f2f1SRadu Pirea (NXP OSS) { 837b050f2f1SRadu Pirea (NXP OSS) return ARRAY_SIZE(nxp_c45_hw_stats); 838b050f2f1SRadu Pirea (NXP OSS) } 839b050f2f1SRadu Pirea (NXP OSS) 840b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data) 841b050f2f1SRadu Pirea (NXP OSS) { 842b050f2f1SRadu Pirea (NXP OSS) size_t i; 843b050f2f1SRadu Pirea (NXP OSS) 844b050f2f1SRadu Pirea (NXP OSS) for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) { 845b050f2f1SRadu Pirea (NXP OSS) strncpy(data + i * ETH_GSTRING_LEN, 846b050f2f1SRadu Pirea (NXP OSS) nxp_c45_hw_stats[i].name, ETH_GSTRING_LEN); 847b050f2f1SRadu Pirea (NXP OSS) } 848b050f2f1SRadu Pirea (NXP OSS) } 849b050f2f1SRadu Pirea (NXP OSS) 850b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev, 851b050f2f1SRadu Pirea (NXP OSS) struct ethtool_stats *stats, u64 *data) 852b050f2f1SRadu Pirea (NXP OSS) { 853b050f2f1SRadu Pirea (NXP OSS) size_t i; 854b050f2f1SRadu Pirea (NXP OSS) int ret; 855b050f2f1SRadu Pirea (NXP OSS) 856b050f2f1SRadu Pirea (NXP OSS) for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) { 857b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, nxp_c45_hw_stats[i].mmd, 858b050f2f1SRadu Pirea (NXP OSS) nxp_c45_hw_stats[i].reg); 859b050f2f1SRadu Pirea (NXP OSS) if (ret < 0) { 860b050f2f1SRadu Pirea (NXP OSS) data[i] = U64_MAX; 861b050f2f1SRadu Pirea (NXP OSS) } else { 862b050f2f1SRadu Pirea (NXP OSS) data[i] = ret & nxp_c45_hw_stats[i].mask; 863b050f2f1SRadu Pirea (NXP OSS) data[i] >>= nxp_c45_hw_stats[i].off; 864b050f2f1SRadu Pirea (NXP OSS) } 865b050f2f1SRadu Pirea (NXP OSS) } 866b050f2f1SRadu Pirea (NXP OSS) } 867b050f2f1SRadu Pirea (NXP OSS) 868b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev) 869b050f2f1SRadu Pirea (NXP OSS) { 870b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 871b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_GLOBAL_EN | 872b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_ALL_EN); 873b050f2f1SRadu Pirea (NXP OSS) usleep_range(400, 450); 874b050f2f1SRadu Pirea (NXP OSS) 875b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL, 876b050f2f1SRadu Pirea (NXP OSS) PORT_CONTROL_EN); 877b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 878b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_EN); 879b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL, 880b050f2f1SRadu Pirea (NXP OSS) PORT_INFRA_CONTROL_EN); 881b050f2f1SRadu Pirea (NXP OSS) 882b050f2f1SRadu Pirea (NXP OSS) return 0; 883b050f2f1SRadu Pirea (NXP OSS) } 884b050f2f1SRadu Pirea (NXP OSS) 885b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev) 886b050f2f1SRadu Pirea (NXP OSS) { 887b050f2f1SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL, 888b050f2f1SRadu Pirea (NXP OSS) PHY_START_OP); 889b050f2f1SRadu Pirea (NXP OSS) } 890b050f2f1SRadu Pirea (NXP OSS) 891b2f0ca00SRadu Pirea (NXP OSS) static int nxp_c45_config_intr(struct phy_device *phydev) 892b2f0ca00SRadu Pirea (NXP OSS) { 893b2f0ca00SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 894b2f0ca00SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, 895b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 896b2f0ca00SRadu Pirea (NXP OSS) else 897b2f0ca00SRadu Pirea (NXP OSS) return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 898b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT); 899b2f0ca00SRadu Pirea (NXP OSS) } 900b2f0ca00SRadu Pirea (NXP OSS) 901b2f0ca00SRadu Pirea (NXP OSS) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev) 902b2f0ca00SRadu Pirea (NXP OSS) { 903514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 904b2f0ca00SRadu Pirea (NXP OSS) irqreturn_t ret = IRQ_NONE; 905514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts; 906b2f0ca00SRadu Pirea (NXP OSS) int irq; 907b2f0ca00SRadu Pirea (NXP OSS) 908b2f0ca00SRadu Pirea (NXP OSS) irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS); 909b2f0ca00SRadu Pirea (NXP OSS) if (irq & PHY_IRQ_LINK_EVENT) { 910b2f0ca00SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK, 911b2f0ca00SRadu Pirea (NXP OSS) PHY_IRQ_LINK_EVENT); 912b2f0ca00SRadu Pirea (NXP OSS) phy_trigger_machine(phydev); 913b2f0ca00SRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 914b2f0ca00SRadu Pirea (NXP OSS) } 915b2f0ca00SRadu Pirea (NXP OSS) 916514def5dSRadu Pirea (NXP OSS) /* There is no need for ACK. 917514def5dSRadu Pirea (NXP OSS) * The irq signal will be asserted until the EGR TS FIFO will be 918514def5dSRadu Pirea (NXP OSS) * emptied. 919514def5dSRadu Pirea (NXP OSS) */ 920514def5dSRadu Pirea (NXP OSS) irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_IRQ_STATUS); 921514def5dSRadu Pirea (NXP OSS) if (irq & PTP_IRQ_EGR_TS) { 922514def5dSRadu Pirea (NXP OSS) while (nxp_c45_get_hwtxts(priv, &hwts)) 923514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts); 924514def5dSRadu Pirea (NXP OSS) 925514def5dSRadu Pirea (NXP OSS) ret = IRQ_HANDLED; 926514def5dSRadu Pirea (NXP OSS) } 927514def5dSRadu Pirea (NXP OSS) 928b2f0ca00SRadu Pirea (NXP OSS) return ret; 929b2f0ca00SRadu Pirea (NXP OSS) } 930b2f0ca00SRadu Pirea (NXP OSS) 931b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev) 932b050f2f1SRadu Pirea (NXP OSS) { 933b050f2f1SRadu Pirea (NXP OSS) int ret; 934b050f2f1SRadu Pirea (NXP OSS) 935b050f2f1SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL, 936b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_RESET); 937b050f2f1SRadu Pirea (NXP OSS) if (ret) 938b050f2f1SRadu Pirea (NXP OSS) return ret; 939b050f2f1SRadu Pirea (NXP OSS) 940b050f2f1SRadu Pirea (NXP OSS) return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 941b050f2f1SRadu Pirea (NXP OSS) VEND1_DEVICE_CONTROL, ret, 942b050f2f1SRadu Pirea (NXP OSS) !(ret & DEVICE_CONTROL_RESET), 20000, 943b050f2f1SRadu Pirea (NXP OSS) 240000, false); 944b050f2f1SRadu Pirea (NXP OSS) } 945b050f2f1SRadu Pirea (NXP OSS) 946b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev) 947b050f2f1SRadu Pirea (NXP OSS) { 948b050f2f1SRadu Pirea (NXP OSS) return phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST, 949b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE | CABLE_TEST_START); 950b050f2f1SRadu Pirea (NXP OSS) } 951b050f2f1SRadu Pirea (NXP OSS) 952b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev, 953b050f2f1SRadu Pirea (NXP OSS) bool *finished) 954b050f2f1SRadu Pirea (NXP OSS) { 955b050f2f1SRadu Pirea (NXP OSS) int ret; 956b050f2f1SRadu Pirea (NXP OSS) u8 cable_test_result; 957b050f2f1SRadu Pirea (NXP OSS) 958b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST); 959b050f2f1SRadu Pirea (NXP OSS) if (!(ret & CABLE_TEST_VALID)) { 960b050f2f1SRadu Pirea (NXP OSS) *finished = false; 961b050f2f1SRadu Pirea (NXP OSS) return 0; 962b050f2f1SRadu Pirea (NXP OSS) } 963b050f2f1SRadu Pirea (NXP OSS) 964b050f2f1SRadu Pirea (NXP OSS) *finished = true; 965b050f2f1SRadu Pirea (NXP OSS) cable_test_result = ret & GENMASK(2, 0); 966b050f2f1SRadu Pirea (NXP OSS) 967b050f2f1SRadu Pirea (NXP OSS) switch (cable_test_result) { 968b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OK: 969b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 970b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OK); 971b050f2f1SRadu Pirea (NXP OSS) break; 972b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_SHORTED: 973b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 974b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT); 975b050f2f1SRadu Pirea (NXP OSS) break; 976b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OPEN: 977b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 978b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OPEN); 979b050f2f1SRadu Pirea (NXP OSS) break; 980b050f2f1SRadu Pirea (NXP OSS) default: 981b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 982b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC); 983b050f2f1SRadu Pirea (NXP OSS) } 984b050f2f1SRadu Pirea (NXP OSS) 985b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST, 986b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE); 987b050f2f1SRadu Pirea (NXP OSS) 988b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 989b050f2f1SRadu Pirea (NXP OSS) } 990b050f2f1SRadu Pirea (NXP OSS) 991b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_setup_master_slave(struct phy_device *phydev) 992b050f2f1SRadu Pirea (NXP OSS) { 993b050f2f1SRadu Pirea (NXP OSS) switch (phydev->master_slave_set) { 994b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_MASTER_FORCE: 995b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_MASTER_PREFERRED: 996b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL, 997b050f2f1SRadu Pirea (NXP OSS) MASTER_MODE); 998b050f2f1SRadu Pirea (NXP OSS) break; 999b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_SLAVE_PREFERRED: 1000b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_SLAVE_FORCE: 1001b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL, 1002b050f2f1SRadu Pirea (NXP OSS) SLAVE_MODE); 1003b050f2f1SRadu Pirea (NXP OSS) break; 1004b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_UNKNOWN: 1005b050f2f1SRadu Pirea (NXP OSS) case MASTER_SLAVE_CFG_UNSUPPORTED: 1006b050f2f1SRadu Pirea (NXP OSS) return 0; 1007b050f2f1SRadu Pirea (NXP OSS) default: 1008b050f2f1SRadu Pirea (NXP OSS) phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 1009b050f2f1SRadu Pirea (NXP OSS) return -EOPNOTSUPP; 1010b050f2f1SRadu Pirea (NXP OSS) } 1011b050f2f1SRadu Pirea (NXP OSS) 1012b050f2f1SRadu Pirea (NXP OSS) return 0; 1013b050f2f1SRadu Pirea (NXP OSS) } 1014b050f2f1SRadu Pirea (NXP OSS) 1015b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_read_master_slave(struct phy_device *phydev) 1016b050f2f1SRadu Pirea (NXP OSS) { 1017b050f2f1SRadu Pirea (NXP OSS) int reg; 1018b050f2f1SRadu Pirea (NXP OSS) 1019b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; 1020b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; 1021b050f2f1SRadu Pirea (NXP OSS) 1022b050f2f1SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL); 1023b050f2f1SRadu Pirea (NXP OSS) if (reg < 0) 1024b050f2f1SRadu Pirea (NXP OSS) return reg; 1025b050f2f1SRadu Pirea (NXP OSS) 1026b050f2f1SRadu Pirea (NXP OSS) if (reg & B100T1_PMAPMD_MASTER) { 1027b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; 1028b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; 1029b050f2f1SRadu Pirea (NXP OSS) } else { 1030b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; 1031b050f2f1SRadu Pirea (NXP OSS) phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; 1032b050f2f1SRadu Pirea (NXP OSS) } 1033b050f2f1SRadu Pirea (NXP OSS) 1034b050f2f1SRadu Pirea (NXP OSS) return 0; 1035b050f2f1SRadu Pirea (NXP OSS) } 1036b050f2f1SRadu Pirea (NXP OSS) 1037b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_aneg(struct phy_device *phydev) 1038b050f2f1SRadu Pirea (NXP OSS) { 1039b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_setup_master_slave(phydev); 1040b050f2f1SRadu Pirea (NXP OSS) } 1041b050f2f1SRadu Pirea (NXP OSS) 1042b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_read_status(struct phy_device *phydev) 1043b050f2f1SRadu Pirea (NXP OSS) { 1044b050f2f1SRadu Pirea (NXP OSS) int ret; 1045b050f2f1SRadu Pirea (NXP OSS) 1046b050f2f1SRadu Pirea (NXP OSS) ret = genphy_c45_read_status(phydev); 1047b050f2f1SRadu Pirea (NXP OSS) if (ret) 1048b050f2f1SRadu Pirea (NXP OSS) return ret; 1049b050f2f1SRadu Pirea (NXP OSS) 1050b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_read_master_slave(phydev); 1051b050f2f1SRadu Pirea (NXP OSS) if (ret) 1052b050f2f1SRadu Pirea (NXP OSS) return ret; 1053b050f2f1SRadu Pirea (NXP OSS) 1054b050f2f1SRadu Pirea (NXP OSS) return 0; 1055b050f2f1SRadu Pirea (NXP OSS) } 1056b050f2f1SRadu Pirea (NXP OSS) 1057b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev) 1058b050f2f1SRadu Pirea (NXP OSS) { 1059b050f2f1SRadu Pirea (NXP OSS) int reg; 1060b050f2f1SRadu Pirea (NXP OSS) 1061b050f2f1SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY); 1062b050f2f1SRadu Pirea (NXP OSS) if (!(reg & SQI_VALID)) 1063b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1064b050f2f1SRadu Pirea (NXP OSS) 1065b050f2f1SRadu Pirea (NXP OSS) reg &= SQI_MASK; 1066b050f2f1SRadu Pirea (NXP OSS) 1067b050f2f1SRadu Pirea (NXP OSS) return reg; 1068b050f2f1SRadu Pirea (NXP OSS) } 1069b050f2f1SRadu Pirea (NXP OSS) 1070b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev) 1071b050f2f1SRadu Pirea (NXP OSS) { 1072b050f2f1SRadu Pirea (NXP OSS) return MAX_SQI; 1073b050f2f1SRadu Pirea (NXP OSS) } 1074b050f2f1SRadu Pirea (NXP OSS) 1075b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay) 1076b050f2f1SRadu Pirea (NXP OSS) { 1077b050f2f1SRadu Pirea (NXP OSS) if (delay < MIN_ID_PS) { 1078b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS); 1079b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1080b050f2f1SRadu Pirea (NXP OSS) } 1081b050f2f1SRadu Pirea (NXP OSS) 1082b050f2f1SRadu Pirea (NXP OSS) if (delay > MAX_ID_PS) { 1083b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS); 1084b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1085b050f2f1SRadu Pirea (NXP OSS) } 1086b050f2f1SRadu Pirea (NXP OSS) 1087b050f2f1SRadu Pirea (NXP OSS) return 0; 1088b050f2f1SRadu Pirea (NXP OSS) } 1089b050f2f1SRadu Pirea (NXP OSS) 1090b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw) 1091b050f2f1SRadu Pirea (NXP OSS) { 1092b050f2f1SRadu Pirea (NXP OSS) /* The delay in degree phase is 73.8 + phase_offset_raw * 0.9. 1093b050f2f1SRadu Pirea (NXP OSS) * To avoid floating point operations we'll multiply by 10 1094b050f2f1SRadu Pirea (NXP OSS) * and get 1 decimal point precision. 1095b050f2f1SRadu Pirea (NXP OSS) */ 1096b050f2f1SRadu Pirea (NXP OSS) phase_offset_raw *= 10; 10976b3a6310SRadu Pirea (NXP OSS) phase_offset_raw -= 738; 1098b050f2f1SRadu Pirea (NXP OSS) return div_u64(phase_offset_raw, 9); 1099b050f2f1SRadu Pirea (NXP OSS) } 1100b050f2f1SRadu Pirea (NXP OSS) 1101b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev) 1102b050f2f1SRadu Pirea (NXP OSS) { 1103b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE); 1104b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE); 1105b050f2f1SRadu Pirea (NXP OSS) } 1106b050f2f1SRadu Pirea (NXP OSS) 1107b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev) 1108b050f2f1SRadu Pirea (NXP OSS) { 1109b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1110b050f2f1SRadu Pirea (NXP OSS) u64 tx_delay = priv->tx_delay; 1111b050f2f1SRadu Pirea (NXP OSS) u64 rx_delay = priv->rx_delay; 1112b050f2f1SRadu Pirea (NXP OSS) u64 degree; 1113b050f2f1SRadu Pirea (NXP OSS) 1114b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1115b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 1116b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(tx_delay, PS_PER_DEGREE); 1117b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 1118b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 1119b050f2f1SRadu Pirea (NXP OSS) } else { 1120b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, 1121b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 1122b050f2f1SRadu Pirea (NXP OSS) } 1123b050f2f1SRadu Pirea (NXP OSS) 1124b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1125b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 1126b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(rx_delay, PS_PER_DEGREE); 1127b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 1128b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree)); 1129b050f2f1SRadu Pirea (NXP OSS) } else { 1130b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, 1131b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE); 1132b050f2f1SRadu Pirea (NXP OSS) } 1133b050f2f1SRadu Pirea (NXP OSS) } 1134b050f2f1SRadu Pirea (NXP OSS) 1135b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev) 1136b050f2f1SRadu Pirea (NXP OSS) { 1137b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv; 1138b050f2f1SRadu Pirea (NXP OSS) int ret; 1139b050f2f1SRadu Pirea (NXP OSS) 1140b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1141b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 1142b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 1143b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps", 1144b050f2f1SRadu Pirea (NXP OSS) &priv->tx_delay); 1145b050f2f1SRadu Pirea (NXP OSS) if (ret) 1146b050f2f1SRadu Pirea (NXP OSS) priv->tx_delay = DEFAULT_ID_PS; 1147b050f2f1SRadu Pirea (NXP OSS) 1148b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->tx_delay); 1149b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1150b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 1151b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps invalid value\n"); 1152b050f2f1SRadu Pirea (NXP OSS) return ret; 1153b050f2f1SRadu Pirea (NXP OSS) } 1154b050f2f1SRadu Pirea (NXP OSS) } 1155b050f2f1SRadu Pirea (NXP OSS) 1156b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 1157b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 1158b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev, 1159b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps", 1160b050f2f1SRadu Pirea (NXP OSS) &priv->rx_delay); 1161b050f2f1SRadu Pirea (NXP OSS) if (ret) 1162b050f2f1SRadu Pirea (NXP OSS) priv->rx_delay = DEFAULT_ID_PS; 1163b050f2f1SRadu Pirea (NXP OSS) 1164b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->rx_delay); 1165b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1166b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, 1167b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps invalid value\n"); 1168b050f2f1SRadu Pirea (NXP OSS) return ret; 1169b050f2f1SRadu Pirea (NXP OSS) } 1170b050f2f1SRadu Pirea (NXP OSS) } 1171b050f2f1SRadu Pirea (NXP OSS) 1172b050f2f1SRadu Pirea (NXP OSS) return 0; 1173b050f2f1SRadu Pirea (NXP OSS) } 1174b050f2f1SRadu Pirea (NXP OSS) 1175b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev) 1176b050f2f1SRadu Pirea (NXP OSS) { 1177b050f2f1SRadu Pirea (NXP OSS) int ret; 1178b050f2f1SRadu Pirea (NXP OSS) 1179b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES); 1180b050f2f1SRadu Pirea (NXP OSS) phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret); 1181b050f2f1SRadu Pirea (NXP OSS) 1182b050f2f1SRadu Pirea (NXP OSS) switch (phydev->interface) { 1183b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII: 1184b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ABILITY)) { 1185b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii mode not supported\n"); 1186b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1187b050f2f1SRadu Pirea (NXP OSS) } 1188b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1189b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 1190b050f2f1SRadu Pirea (NXP OSS) nxp_c45_disable_delays(phydev); 1191b050f2f1SRadu Pirea (NXP OSS) break; 1192b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_ID: 1193b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_TXID: 1194b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_RXID: 1195b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ID_ABILITY)) { 1196b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n"); 1197b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1198b050f2f1SRadu Pirea (NXP OSS) } 1199b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1200b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII); 1201b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_get_delays(phydev); 1202b050f2f1SRadu Pirea (NXP OSS) if (ret) 1203b050f2f1SRadu Pirea (NXP OSS) return ret; 1204b050f2f1SRadu Pirea (NXP OSS) 1205b050f2f1SRadu Pirea (NXP OSS) nxp_c45_set_delays(phydev); 1206b050f2f1SRadu Pirea (NXP OSS) break; 1207b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_MII: 1208b050f2f1SRadu Pirea (NXP OSS) if (!(ret & MII_ABILITY)) { 1209b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "mii mode not supported\n"); 1210b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1211b050f2f1SRadu Pirea (NXP OSS) } 1212b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1213b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII); 1214b050f2f1SRadu Pirea (NXP OSS) break; 1215b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_REVMII: 1216b050f2f1SRadu Pirea (NXP OSS) if (!(ret & REVMII_ABILITY)) { 1217b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rev-mii mode not supported\n"); 1218b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1219b050f2f1SRadu Pirea (NXP OSS) } 1220b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1221b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_MII | MII_BASIC_CONFIG_REV); 1222b050f2f1SRadu Pirea (NXP OSS) break; 1223b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RMII: 1224b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RMII_ABILITY)) { 1225b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rmii mode not supported\n"); 1226b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1227b050f2f1SRadu Pirea (NXP OSS) } 1228b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1229b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RMII); 1230b050f2f1SRadu Pirea (NXP OSS) break; 1231b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_SGMII: 1232b050f2f1SRadu Pirea (NXP OSS) if (!(ret & SGMII_ABILITY)) { 1233b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "sgmii mode not supported\n"); 1234b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1235b050f2f1SRadu Pirea (NXP OSS) } 1236b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG, 1237b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_SGMII); 1238b050f2f1SRadu Pirea (NXP OSS) break; 1239b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_INTERNAL: 1240b050f2f1SRadu Pirea (NXP OSS) break; 1241b050f2f1SRadu Pirea (NXP OSS) default: 1242b050f2f1SRadu Pirea (NXP OSS) return -EINVAL; 1243b050f2f1SRadu Pirea (NXP OSS) } 1244b050f2f1SRadu Pirea (NXP OSS) 1245b050f2f1SRadu Pirea (NXP OSS) return 0; 1246b050f2f1SRadu Pirea (NXP OSS) } 1247b050f2f1SRadu Pirea (NXP OSS) 1248b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev) 1249b050f2f1SRadu Pirea (NXP OSS) { 1250b050f2f1SRadu Pirea (NXP OSS) int ret; 1251b050f2f1SRadu Pirea (NXP OSS) 1252b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_config_enable(phydev); 1253b050f2f1SRadu Pirea (NXP OSS) if (ret) { 1254b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "Failed to enable config\n"); 1255b050f2f1SRadu Pirea (NXP OSS) return ret; 1256b050f2f1SRadu Pirea (NXP OSS) } 1257b050f2f1SRadu Pirea (NXP OSS) 12580b5f0f29SVladimir Oltean /* Bug workaround for SJA1110 rev B: enable write access 12590b5f0f29SVladimir Oltean * to MDIO_MMD_PMAPMD 12600b5f0f29SVladimir Oltean */ 12610b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1); 12620b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2); 12630b5f0f29SVladimir Oltean 1264b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG, 1265b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_AUTO); 1266b050f2f1SRadu Pirea (NXP OSS) 1267b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER, 1268b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 1269b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT, 1270b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 1271b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT, 1272b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 1273b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH, 1274b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 1275b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH, 1276b050f2f1SRadu Pirea (NXP OSS) COUNTER_EN); 1277b050f2f1SRadu Pirea (NXP OSS) 1278b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_set_phy_mode(phydev); 1279b050f2f1SRadu Pirea (NXP OSS) if (ret) 1280b050f2f1SRadu Pirea (NXP OSS) return ret; 1281b050f2f1SRadu Pirea (NXP OSS) 1282b050f2f1SRadu Pirea (NXP OSS) phydev->autoneg = AUTONEG_DISABLE; 1283b050f2f1SRadu Pirea (NXP OSS) 1284514def5dSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK_PERIOD, 1285514def5dSRadu Pirea (NXP OSS) PTP_CLK_PERIOD_100BT1); 1286514def5dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_HW_LTC_LOCK_CTRL, 1287514def5dSRadu Pirea (NXP OSS) HW_LTC_LOCK_EN); 1288514def5dSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL, 1289514def5dSRadu Pirea (NXP OSS) RX_TS_INSRT_MODE2); 1290514def5dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES, 1291514def5dSRadu Pirea (NXP OSS) PTP_ENABLE); 1292514def5dSRadu Pirea (NXP OSS) 1293b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev); 1294b050f2f1SRadu Pirea (NXP OSS) } 1295b050f2f1SRadu Pirea (NXP OSS) 1296b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev) 1297b050f2f1SRadu Pirea (NXP OSS) { 1298b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv; 1299514def5dSRadu Pirea (NXP OSS) int ptp_ability; 1300514def5dSRadu Pirea (NXP OSS) int ret = 0; 1301b050f2f1SRadu Pirea (NXP OSS) 1302b050f2f1SRadu Pirea (NXP OSS) priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 1303b050f2f1SRadu Pirea (NXP OSS) if (!priv) 1304b050f2f1SRadu Pirea (NXP OSS) return -ENOMEM; 1305b050f2f1SRadu Pirea (NXP OSS) 1306514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->tx_queue); 1307514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->rx_queue); 1308514def5dSRadu Pirea (NXP OSS) 1309514def5dSRadu Pirea (NXP OSS) priv->phydev = phydev; 1310514def5dSRadu Pirea (NXP OSS) 1311b050f2f1SRadu Pirea (NXP OSS) phydev->priv = priv; 1312b050f2f1SRadu Pirea (NXP OSS) 1313514def5dSRadu Pirea (NXP OSS) mutex_init(&priv->ptp_lock); 1314514def5dSRadu Pirea (NXP OSS) 1315514def5dSRadu Pirea (NXP OSS) ptp_ability = phy_read_mmd(phydev, MDIO_MMD_VEND1, 1316514def5dSRadu Pirea (NXP OSS) VEND1_PORT_ABILITIES); 1317514def5dSRadu Pirea (NXP OSS) ptp_ability = !!(ptp_ability & PTP_ABILITY); 1318514def5dSRadu Pirea (NXP OSS) if (!ptp_ability) { 1319565c6d8cSVladimir Oltean phydev_dbg(phydev, "the phy does not support PTP"); 1320514def5dSRadu Pirea (NXP OSS) goto no_ptp_support; 1321514def5dSRadu Pirea (NXP OSS) } 1322514def5dSRadu Pirea (NXP OSS) 1323514def5dSRadu Pirea (NXP OSS) if (IS_ENABLED(CONFIG_PTP_1588_CLOCK) && 1324514def5dSRadu Pirea (NXP OSS) IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) { 1325514def5dSRadu Pirea (NXP OSS) priv->mii_ts.rxtstamp = nxp_c45_rxtstamp; 1326514def5dSRadu Pirea (NXP OSS) priv->mii_ts.txtstamp = nxp_c45_txtstamp; 1327514def5dSRadu Pirea (NXP OSS) priv->mii_ts.hwtstamp = nxp_c45_hwtstamp; 1328514def5dSRadu Pirea (NXP OSS) priv->mii_ts.ts_info = nxp_c45_ts_info; 1329514def5dSRadu Pirea (NXP OSS) phydev->mii_ts = &priv->mii_ts; 1330514def5dSRadu Pirea (NXP OSS) ret = nxp_c45_init_ptp_clock(priv); 1331514def5dSRadu Pirea (NXP OSS) } else { 1332514def5dSRadu Pirea (NXP OSS) phydev_dbg(phydev, "PTP support not enabled even if the phy supports it"); 1333514def5dSRadu Pirea (NXP OSS) } 1334514def5dSRadu Pirea (NXP OSS) 1335514def5dSRadu Pirea (NXP OSS) no_ptp_support: 1336514def5dSRadu Pirea (NXP OSS) 1337514def5dSRadu Pirea (NXP OSS) return ret; 1338b050f2f1SRadu Pirea (NXP OSS) } 1339b050f2f1SRadu Pirea (NXP OSS) 1340b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = { 1341b050f2f1SRadu Pirea (NXP OSS) { 1342b050f2f1SRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), 1343b050f2f1SRadu Pirea (NXP OSS) .name = "NXP C45 TJA1103", 1344b050f2f1SRadu Pirea (NXP OSS) .features = PHY_BASIC_T1_FEATURES, 1345b050f2f1SRadu Pirea (NXP OSS) .probe = nxp_c45_probe, 1346b050f2f1SRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset, 1347b050f2f1SRadu Pirea (NXP OSS) .config_aneg = nxp_c45_config_aneg, 1348b050f2f1SRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init, 1349b2f0ca00SRadu Pirea (NXP OSS) .config_intr = nxp_c45_config_intr, 1350b2f0ca00SRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt, 1351b050f2f1SRadu Pirea (NXP OSS) .read_status = nxp_c45_read_status, 1352b050f2f1SRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend, 1353b050f2f1SRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume, 1354b050f2f1SRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count, 1355b050f2f1SRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings, 1356b050f2f1SRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats, 1357b050f2f1SRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start, 1358b050f2f1SRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status, 1359b050f2f1SRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback, 1360b050f2f1SRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi, 1361b050f2f1SRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max, 1362b050f2f1SRadu Pirea (NXP OSS) }, 1363b050f2f1SRadu Pirea (NXP OSS) }; 1364b050f2f1SRadu Pirea (NXP OSS) 1365b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver); 1366b050f2f1SRadu Pirea (NXP OSS) 1367b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = { 1368b050f2f1SRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) }, 1369b050f2f1SRadu Pirea (NXP OSS) { /*sentinel*/ }, 1370b050f2f1SRadu Pirea (NXP OSS) }; 1371b050f2f1SRadu Pirea (NXP OSS) 1372b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl); 1373b050f2f1SRadu Pirea (NXP OSS) 1374b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>"); 1375b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver"); 1376b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2"); 1377