xref: /openbmc/linux/drivers/net/phy/nxp-c45-tja11xx.c (revision 514def5dd33984e986e0a3afd2a369d8b4688d3f)
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>
16*514def5dSRadu Pirea (NXP OSS) #include <linux/ptp_classify.h>
17*514def5dSRadu Pirea (NXP OSS) #include <linux/ptp_clock_kernel.h>
18*514def5dSRadu 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) 
63*514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_ABILITIES		0x8046
64*514def5dSRadu Pirea (NXP OSS) #define PTP_ABILITY			BIT(3)
65*514def5dSRadu 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
82b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_REV		BIT(8)
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) 
100*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_LOAD_CTRL		0x1105
101*514def5dSRadu Pirea (NXP OSS) #define READ_LTC			BIT(2)
102*514def5dSRadu Pirea (NXP OSS) #define LOAD_LTC			BIT(0)
103*514def5dSRadu Pirea (NXP OSS) 
104*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_WR_NSEC_0		0x1106
105*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_WR_NSEC_1		0x1107
106*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_WR_SEC_0		0x1108
107*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_WR_SEC_1		0x1109
108*514def5dSRadu Pirea (NXP OSS) 
109*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_RD_NSEC_0		0x110A
110*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_RD_NSEC_1		0x110B
111*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_RD_SEC_0		0x110C
112*514def5dSRadu Pirea (NXP OSS) #define VEND1_LTC_RD_SEC_1		0x110D
113*514def5dSRadu Pirea (NXP OSS) 
114*514def5dSRadu Pirea (NXP OSS) #define VEND1_RATE_ADJ_SUBNS_0		0x110F
115*514def5dSRadu Pirea (NXP OSS) #define VEND1_RATE_ADJ_SUBNS_1		0x1110
116*514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_LD			BIT(15)
117*514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_DIR		BIT(14)
118*514def5dSRadu Pirea (NXP OSS) 
119*514def5dSRadu Pirea (NXP OSS) #define VEND1_HW_LTC_LOCK_CTRL		0x1115
120*514def5dSRadu Pirea (NXP OSS) #define HW_LTC_LOCK_EN			BIT(0)
121*514def5dSRadu Pirea (NXP OSS) 
122*514def5dSRadu Pirea (NXP OSS) #define VEND1_PTP_IRQ_EN		0x1131
123*514def5dSRadu Pirea (NXP OSS) #define VEND1_PTP_IRQ_STATUS		0x1132
124*514def5dSRadu Pirea (NXP OSS) #define PTP_IRQ_EGR_TS			BIT(0)
125*514def5dSRadu Pirea (NXP OSS) 
126*514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_TS_INSRT_CTRL		0x114D
127*514def5dSRadu Pirea (NXP OSS) #define RX_TS_INSRT_MODE2		0x02
128*514def5dSRadu Pirea (NXP OSS) 
129*514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_0		0x114E
130*514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_1_SEQ_ID	0x114F
131*514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_2_NSEC_15_0	0x1150
132*514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_3		0x1151
133*514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_CTRL		0x1154
134*514def5dSRadu Pirea (NXP OSS) 
135*514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_DOMAIN_NUMBER	GENMASK(7, 0)
136*514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_MSG_TYPE		GENMASK(11, 8)
137*514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_SEC_4_2		GENMASK(14, 2)
138*514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_TS_VALID		BIT(15)
139*514def5dSRadu Pirea (NXP OSS) 
140*514def5dSRadu Pirea (NXP OSS) #define RING_DATA_3_NSEC_29_16		GENMASK(13, 0)
141*514def5dSRadu Pirea (NXP OSS) #define RING_DATA_3_SEC_1_0		GENMASK(15, 14)
142*514def5dSRadu Pirea (NXP OSS) #define RING_DATA_5_SEC_16_5		GENMASK(15, 4)
143*514def5dSRadu Pirea (NXP OSS) #define RING_DONE			BIT(0)
144*514def5dSRadu Pirea (NXP OSS) 
145*514def5dSRadu Pirea (NXP OSS) #define TS_SEC_MASK			GENMASK(1, 0)
146*514def5dSRadu Pirea (NXP OSS) 
147*514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_ENABLES		0x8048
148*514def5dSRadu Pirea (NXP OSS) #define PTP_ENABLE			BIT(3)
149*514def5dSRadu Pirea (NXP OSS) 
150*514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_PTP_CONTROL		0x9000
151*514def5dSRadu Pirea (NXP OSS) #define PORT_PTP_CONTROL_BYPASS		BIT(11)
152*514def5dSRadu Pirea (NXP OSS) 
153*514def5dSRadu Pirea (NXP OSS) #define VEND1_PTP_CLK_PERIOD		0x1104
154*514def5dSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_100BT1		15ULL
155*514def5dSRadu Pirea (NXP OSS) 
156*514def5dSRadu Pirea (NXP OSS) #define VEND1_EVENT_MSG_FILT		0x1148
157*514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_ALL		0x0F
158*514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_NONE		0x00
159*514def5dSRadu Pirea (NXP OSS) 
160*514def5dSRadu Pirea (NXP OSS) #define VEND1_TX_PIPE_DLY_NS		0x1149
161*514def5dSRadu Pirea (NXP OSS) #define VEND1_TX_PIPEDLY_SUBNS		0x114A
162*514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_PIPE_DLY_NS		0x114B
163*514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_PIPEDLY_SUBNS		0x114C
164*514def5dSRadu Pirea (NXP OSS) 
165b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS			8000U
166b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE			div_u64(RGMII_PERIOD_PS, 360)
167b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS			1644U
168b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS			2260U
169b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS			2000U
170b050f2f1SRadu Pirea (NXP OSS) 
171*514def5dSRadu Pirea (NXP OSS) #define PPM_TO_SUBNS_INC(ppb)	div_u64(GENMASK(31, 0) * (ppb) * \
172*514def5dSRadu Pirea (NXP OSS) 					PTP_CLK_PERIOD_100BT1, NSEC_PER_SEC)
173*514def5dSRadu Pirea (NXP OSS) 
174*514def5dSRadu Pirea (NXP OSS) #define NXP_C45_SKB_CB(skb)	((struct nxp_c45_skb_cb *)(skb)->cb)
175*514def5dSRadu Pirea (NXP OSS) 
176*514def5dSRadu Pirea (NXP OSS) struct nxp_c45_skb_cb {
177*514def5dSRadu Pirea (NXP OSS) 	struct ptp_header *header;
178*514def5dSRadu Pirea (NXP OSS) 	unsigned int type;
179*514def5dSRadu Pirea (NXP OSS) };
180*514def5dSRadu Pirea (NXP OSS) 
181*514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts {
182*514def5dSRadu Pirea (NXP OSS) 	u32	nsec;
183*514def5dSRadu Pirea (NXP OSS) 	u32	sec;
184*514def5dSRadu Pirea (NXP OSS) 	u8	domain_number;
185*514def5dSRadu Pirea (NXP OSS) 	u16	sequence_id;
186*514def5dSRadu Pirea (NXP OSS) 	u8	msg_type;
187*514def5dSRadu Pirea (NXP OSS) };
188*514def5dSRadu Pirea (NXP OSS) 
189b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy {
190*514def5dSRadu Pirea (NXP OSS) 	struct phy_device *phydev;
191*514def5dSRadu Pirea (NXP OSS) 	struct mii_timestamper mii_ts;
192*514def5dSRadu Pirea (NXP OSS) 	struct ptp_clock *ptp_clock;
193*514def5dSRadu Pirea (NXP OSS) 	struct ptp_clock_info caps;
194*514def5dSRadu Pirea (NXP OSS) 	struct sk_buff_head tx_queue;
195*514def5dSRadu Pirea (NXP OSS) 	struct sk_buff_head rx_queue;
196*514def5dSRadu Pirea (NXP OSS) 	/* used to access the PTP registers atomic */
197*514def5dSRadu Pirea (NXP OSS) 	struct mutex ptp_lock;
198*514def5dSRadu Pirea (NXP OSS) 	int hwts_tx;
199*514def5dSRadu Pirea (NXP OSS) 	int hwts_rx;
200b050f2f1SRadu Pirea (NXP OSS) 	u32 tx_delay;
201b050f2f1SRadu Pirea (NXP OSS) 	u32 rx_delay;
202b050f2f1SRadu Pirea (NXP OSS) };
203b050f2f1SRadu Pirea (NXP OSS) 
204b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy_stats {
205b050f2f1SRadu Pirea (NXP OSS) 	const char	*name;
206b050f2f1SRadu Pirea (NXP OSS) 	u8		mmd;
207b050f2f1SRadu Pirea (NXP OSS) 	u16		reg;
208b050f2f1SRadu Pirea (NXP OSS) 	u8		off;
209b050f2f1SRadu Pirea (NXP OSS) 	u16		mask;
210b050f2f1SRadu Pirea (NXP OSS) };
211b050f2f1SRadu Pirea (NXP OSS) 
212*514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_poll_txts(struct phy_device *phydev)
213*514def5dSRadu Pirea (NXP OSS) {
214*514def5dSRadu Pirea (NXP OSS) 	return phydev->irq <= 0;
215*514def5dSRadu Pirea (NXP OSS) }
216*514def5dSRadu Pirea (NXP OSS) 
217*514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp,
218*514def5dSRadu Pirea (NXP OSS) 				   struct timespec64 *ts,
219*514def5dSRadu Pirea (NXP OSS) 				   struct ptp_system_timestamp *sts)
220*514def5dSRadu Pirea (NXP OSS) {
221*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
222*514def5dSRadu Pirea (NXP OSS) 
223*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_LOAD_CTRL,
224*514def5dSRadu Pirea (NXP OSS) 		      READ_LTC);
225*514def5dSRadu Pirea (NXP OSS) 	ts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
226*514def5dSRadu Pirea (NXP OSS) 				   VEND1_LTC_RD_NSEC_0);
227*514def5dSRadu Pirea (NXP OSS) 	ts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
228*514def5dSRadu Pirea (NXP OSS) 				    VEND1_LTC_RD_NSEC_1) << 16;
229*514def5dSRadu Pirea (NXP OSS) 	ts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
230*514def5dSRadu Pirea (NXP OSS) 				  VEND1_LTC_RD_SEC_0);
231*514def5dSRadu Pirea (NXP OSS) 	ts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
232*514def5dSRadu Pirea (NXP OSS) 				   VEND1_LTC_RD_SEC_1) << 16;
233*514def5dSRadu Pirea (NXP OSS) 
234*514def5dSRadu Pirea (NXP OSS) 	return 0;
235*514def5dSRadu Pirea (NXP OSS) }
236*514def5dSRadu Pirea (NXP OSS) 
237*514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp,
238*514def5dSRadu Pirea (NXP OSS) 				  struct timespec64 *ts,
239*514def5dSRadu Pirea (NXP OSS) 				  struct ptp_system_timestamp *sts)
240*514def5dSRadu Pirea (NXP OSS) {
241*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
242*514def5dSRadu Pirea (NXP OSS) 
243*514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
244*514def5dSRadu Pirea (NXP OSS) 	_nxp_c45_ptp_gettimex64(ptp, ts, sts);
245*514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
246*514def5dSRadu Pirea (NXP OSS) 
247*514def5dSRadu Pirea (NXP OSS) 	return 0;
248*514def5dSRadu Pirea (NXP OSS) }
249*514def5dSRadu Pirea (NXP OSS) 
250*514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_settime64(struct ptp_clock_info *ptp,
251*514def5dSRadu Pirea (NXP OSS) 				  const struct timespec64 *ts)
252*514def5dSRadu Pirea (NXP OSS) {
253*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
254*514def5dSRadu Pirea (NXP OSS) 
255*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_NSEC_0,
256*514def5dSRadu Pirea (NXP OSS) 		      ts->tv_nsec);
257*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_NSEC_1,
258*514def5dSRadu Pirea (NXP OSS) 		      ts->tv_nsec >> 16);
259*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_SEC_0,
260*514def5dSRadu Pirea (NXP OSS) 		      ts->tv_sec);
261*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_WR_SEC_1,
262*514def5dSRadu Pirea (NXP OSS) 		      ts->tv_sec >> 16);
263*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_LTC_LOAD_CTRL,
264*514def5dSRadu Pirea (NXP OSS) 		      LOAD_LTC);
265*514def5dSRadu Pirea (NXP OSS) 
266*514def5dSRadu Pirea (NXP OSS) 	return 0;
267*514def5dSRadu Pirea (NXP OSS) }
268*514def5dSRadu Pirea (NXP OSS) 
269*514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_settime64(struct ptp_clock_info *ptp,
270*514def5dSRadu Pirea (NXP OSS) 				 const struct timespec64 *ts)
271*514def5dSRadu Pirea (NXP OSS) {
272*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
273*514def5dSRadu Pirea (NXP OSS) 
274*514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
275*514def5dSRadu Pirea (NXP OSS) 	_nxp_c45_ptp_settime64(ptp, ts);
276*514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
277*514def5dSRadu Pirea (NXP OSS) 
278*514def5dSRadu Pirea (NXP OSS) 	return 0;
279*514def5dSRadu Pirea (NXP OSS) }
280*514def5dSRadu Pirea (NXP OSS) 
281*514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
282*514def5dSRadu Pirea (NXP OSS) {
283*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
284*514def5dSRadu Pirea (NXP OSS) 	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
285*514def5dSRadu Pirea (NXP OSS) 	u64 subns_inc_val;
286*514def5dSRadu Pirea (NXP OSS) 	bool inc;
287*514def5dSRadu Pirea (NXP OSS) 
288*514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
289*514def5dSRadu Pirea (NXP OSS) 	inc = ppb >= 0;
290*514def5dSRadu Pirea (NXP OSS) 	ppb = abs(ppb);
291*514def5dSRadu Pirea (NXP OSS) 
292*514def5dSRadu Pirea (NXP OSS) 	subns_inc_val = PPM_TO_SUBNS_INC(ppb);
293*514def5dSRadu Pirea (NXP OSS) 
294*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_RATE_ADJ_SUBNS_0,
295*514def5dSRadu Pirea (NXP OSS) 		      subns_inc_val);
296*514def5dSRadu Pirea (NXP OSS) 	subns_inc_val >>= 16;
297*514def5dSRadu Pirea (NXP OSS) 	subns_inc_val |= CLK_RATE_ADJ_LD;
298*514def5dSRadu Pirea (NXP OSS) 	if (inc)
299*514def5dSRadu Pirea (NXP OSS) 		subns_inc_val |= CLK_RATE_ADJ_DIR;
300*514def5dSRadu Pirea (NXP OSS) 
301*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_RATE_ADJ_SUBNS_1,
302*514def5dSRadu Pirea (NXP OSS) 		      subns_inc_val);
303*514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
304*514def5dSRadu Pirea (NXP OSS) 
305*514def5dSRadu Pirea (NXP OSS) 	return 0;
306*514def5dSRadu Pirea (NXP OSS) }
307*514def5dSRadu Pirea (NXP OSS) 
308*514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
309*514def5dSRadu Pirea (NXP OSS) {
310*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
311*514def5dSRadu Pirea (NXP OSS) 	struct timespec64 now, then;
312*514def5dSRadu Pirea (NXP OSS) 
313*514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
314*514def5dSRadu Pirea (NXP OSS) 	then = ns_to_timespec64(delta);
315*514def5dSRadu Pirea (NXP OSS) 	_nxp_c45_ptp_gettimex64(ptp, &now, NULL);
316*514def5dSRadu Pirea (NXP OSS) 	now = timespec64_add(now, then);
317*514def5dSRadu Pirea (NXP OSS) 	_nxp_c45_ptp_settime64(ptp, &now);
318*514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
319*514def5dSRadu Pirea (NXP OSS) 
320*514def5dSRadu Pirea (NXP OSS) 	return 0;
321*514def5dSRadu Pirea (NXP OSS) }
322*514def5dSRadu Pirea (NXP OSS) 
323*514def5dSRadu Pirea (NXP OSS) static void nxp_c45_reconstruct_ts(struct timespec64 *ts,
324*514def5dSRadu Pirea (NXP OSS) 				   struct nxp_c45_hwts *hwts)
325*514def5dSRadu Pirea (NXP OSS) {
326*514def5dSRadu Pirea (NXP OSS) 	ts->tv_nsec = hwts->nsec;
327*514def5dSRadu Pirea (NXP OSS) 	if ((ts->tv_sec & TS_SEC_MASK) < (hwts->sec & TS_SEC_MASK))
328*514def5dSRadu Pirea (NXP OSS) 		ts->tv_sec -= BIT(2);
329*514def5dSRadu Pirea (NXP OSS) 	ts->tv_sec &= ~TS_SEC_MASK;
330*514def5dSRadu Pirea (NXP OSS) 	ts->tv_sec |= hwts->sec & TS_SEC_MASK;
331*514def5dSRadu Pirea (NXP OSS) }
332*514def5dSRadu Pirea (NXP OSS) 
333*514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_match_ts(struct ptp_header *header,
334*514def5dSRadu Pirea (NXP OSS) 			     struct nxp_c45_hwts *hwts,
335*514def5dSRadu Pirea (NXP OSS) 			     unsigned int type)
336*514def5dSRadu Pirea (NXP OSS) {
337*514def5dSRadu Pirea (NXP OSS) 	return ntohs(header->sequence_id) == hwts->sequence_id &&
338*514def5dSRadu Pirea (NXP OSS) 	       ptp_get_msgtype(header, type) == hwts->msg_type &&
339*514def5dSRadu Pirea (NXP OSS) 	       header->domain_number  == hwts->domain_number;
340*514def5dSRadu Pirea (NXP OSS) }
341*514def5dSRadu Pirea (NXP OSS) 
342*514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv,
343*514def5dSRadu Pirea (NXP OSS) 			       struct nxp_c45_hwts *hwts)
344*514def5dSRadu Pirea (NXP OSS) {
345*514def5dSRadu Pirea (NXP OSS) 	bool valid;
346*514def5dSRadu Pirea (NXP OSS) 	u16 reg;
347*514def5dSRadu Pirea (NXP OSS) 
348*514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
349*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL,
350*514def5dSRadu Pirea (NXP OSS) 		      RING_DONE);
351*514def5dSRadu Pirea (NXP OSS) 	reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0);
352*514def5dSRadu Pirea (NXP OSS) 	valid = !!(reg & RING_DATA_0_TS_VALID);
353*514def5dSRadu Pirea (NXP OSS) 	if (!valid)
354*514def5dSRadu Pirea (NXP OSS) 		goto nxp_c45_get_hwtxts_out;
355*514def5dSRadu Pirea (NXP OSS) 
356*514def5dSRadu Pirea (NXP OSS) 	hwts->domain_number = reg;
357*514def5dSRadu Pirea (NXP OSS) 	hwts->msg_type = (reg & RING_DATA_0_MSG_TYPE) >> 8;
358*514def5dSRadu Pirea (NXP OSS) 	hwts->sec = (reg & RING_DATA_0_SEC_4_2) >> 10;
359*514def5dSRadu Pirea (NXP OSS) 	hwts->sequence_id = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
360*514def5dSRadu Pirea (NXP OSS) 					 VEND1_EGR_RING_DATA_1_SEQ_ID);
361*514def5dSRadu Pirea (NXP OSS) 	hwts->nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
362*514def5dSRadu Pirea (NXP OSS) 				  VEND1_EGR_RING_DATA_2_NSEC_15_0);
363*514def5dSRadu Pirea (NXP OSS) 	reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_3);
364*514def5dSRadu Pirea (NXP OSS) 	hwts->nsec |= (reg & RING_DATA_3_NSEC_29_16) << 16;
365*514def5dSRadu Pirea (NXP OSS) 	hwts->sec |= (reg & RING_DATA_3_SEC_1_0) >> 14;
366*514def5dSRadu Pirea (NXP OSS) 
367*514def5dSRadu Pirea (NXP OSS) nxp_c45_get_hwtxts_out:
368*514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
369*514def5dSRadu Pirea (NXP OSS) 	return valid;
370*514def5dSRadu Pirea (NXP OSS) }
371*514def5dSRadu Pirea (NXP OSS) 
372*514def5dSRadu Pirea (NXP OSS) static void nxp_c45_process_txts(struct nxp_c45_phy *priv,
373*514def5dSRadu Pirea (NXP OSS) 				 struct nxp_c45_hwts *txts)
374*514def5dSRadu Pirea (NXP OSS) {
375*514def5dSRadu Pirea (NXP OSS) 	struct sk_buff *skb, *tmp, *skb_match = NULL;
376*514def5dSRadu Pirea (NXP OSS) 	struct skb_shared_hwtstamps shhwtstamps;
377*514def5dSRadu Pirea (NXP OSS) 	struct timespec64 ts;
378*514def5dSRadu Pirea (NXP OSS) 	unsigned long flags;
379*514def5dSRadu Pirea (NXP OSS) 	bool ts_match;
380*514def5dSRadu Pirea (NXP OSS) 	s64 ts_ns;
381*514def5dSRadu Pirea (NXP OSS) 
382*514def5dSRadu Pirea (NXP OSS) 	spin_lock_irqsave(&priv->tx_queue.lock, flags);
383*514def5dSRadu Pirea (NXP OSS) 	skb_queue_walk_safe(&priv->tx_queue, skb, tmp) {
384*514def5dSRadu Pirea (NXP OSS) 		ts_match = nxp_c45_match_ts(NXP_C45_SKB_CB(skb)->header, txts,
385*514def5dSRadu Pirea (NXP OSS) 					    NXP_C45_SKB_CB(skb)->type);
386*514def5dSRadu Pirea (NXP OSS) 		if (!ts_match)
387*514def5dSRadu Pirea (NXP OSS) 			continue;
388*514def5dSRadu Pirea (NXP OSS) 		skb_match = skb;
389*514def5dSRadu Pirea (NXP OSS) 		__skb_unlink(skb, &priv->tx_queue);
390*514def5dSRadu Pirea (NXP OSS) 		break;
391*514def5dSRadu Pirea (NXP OSS) 	}
392*514def5dSRadu Pirea (NXP OSS) 	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
393*514def5dSRadu Pirea (NXP OSS) 
394*514def5dSRadu Pirea (NXP OSS) 	if (skb_match) {
395*514def5dSRadu Pirea (NXP OSS) 		nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL);
396*514def5dSRadu Pirea (NXP OSS) 		nxp_c45_reconstruct_ts(&ts, txts);
397*514def5dSRadu Pirea (NXP OSS) 		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
398*514def5dSRadu Pirea (NXP OSS) 		ts_ns = timespec64_to_ns(&ts);
399*514def5dSRadu Pirea (NXP OSS) 		shhwtstamps.hwtstamp = ns_to_ktime(ts_ns);
400*514def5dSRadu Pirea (NXP OSS) 		skb_complete_tx_timestamp(skb_match, &shhwtstamps);
401*514def5dSRadu Pirea (NXP OSS) 	} else {
402*514def5dSRadu Pirea (NXP OSS) 		phydev_warn(priv->phydev,
403*514def5dSRadu Pirea (NXP OSS) 			    "the tx timestamp doesn't match with any skb\n");
404*514def5dSRadu Pirea (NXP OSS) 	}
405*514def5dSRadu Pirea (NXP OSS) }
406*514def5dSRadu Pirea (NXP OSS) 
407*514def5dSRadu Pirea (NXP OSS) static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp)
408*514def5dSRadu Pirea (NXP OSS) {
409*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
410*514def5dSRadu Pirea (NXP OSS) 	bool poll_txts = nxp_c45_poll_txts(priv->phydev);
411*514def5dSRadu Pirea (NXP OSS) 	struct skb_shared_hwtstamps *shhwtstamps_rx;
412*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_hwts hwts;
413*514def5dSRadu Pirea (NXP OSS) 	bool reschedule = false;
414*514def5dSRadu Pirea (NXP OSS) 	struct timespec64 ts;
415*514def5dSRadu Pirea (NXP OSS) 	struct sk_buff *skb;
416*514def5dSRadu Pirea (NXP OSS) 	bool txts_valid;
417*514def5dSRadu Pirea (NXP OSS) 	u32 ts_raw;
418*514def5dSRadu Pirea (NXP OSS) 
419*514def5dSRadu Pirea (NXP OSS) 	while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) {
420*514def5dSRadu Pirea (NXP OSS) 		txts_valid = nxp_c45_get_hwtxts(priv, &hwts);
421*514def5dSRadu Pirea (NXP OSS) 		if (unlikely(!txts_valid)) {
422*514def5dSRadu Pirea (NXP OSS) 			/* Still more skbs in the queue */
423*514def5dSRadu Pirea (NXP OSS) 			reschedule = true;
424*514def5dSRadu Pirea (NXP OSS) 			break;
425*514def5dSRadu Pirea (NXP OSS) 		}
426*514def5dSRadu Pirea (NXP OSS) 
427*514def5dSRadu Pirea (NXP OSS) 		nxp_c45_process_txts(priv, &hwts);
428*514def5dSRadu Pirea (NXP OSS) 	}
429*514def5dSRadu Pirea (NXP OSS) 
430*514def5dSRadu Pirea (NXP OSS) 	nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL);
431*514def5dSRadu Pirea (NXP OSS) 	while ((skb = skb_dequeue(&priv->rx_queue)) != NULL) {
432*514def5dSRadu Pirea (NXP OSS) 		ts_raw = __be32_to_cpu(NXP_C45_SKB_CB(skb)->header->reserved2);
433*514def5dSRadu Pirea (NXP OSS) 		hwts.sec = ts_raw >> 30;
434*514def5dSRadu Pirea (NXP OSS) 		hwts.nsec = ts_raw & GENMASK(29, 0);
435*514def5dSRadu Pirea (NXP OSS) 		nxp_c45_reconstruct_ts(&ts, &hwts);
436*514def5dSRadu Pirea (NXP OSS) 		shhwtstamps_rx = skb_hwtstamps(skb);
437*514def5dSRadu Pirea (NXP OSS) 		shhwtstamps_rx->hwtstamp = ns_to_ktime(timespec64_to_ns(&ts));
438*514def5dSRadu Pirea (NXP OSS) 		NXP_C45_SKB_CB(skb)->header->reserved2 = 0;
439*514def5dSRadu Pirea (NXP OSS) 		netif_rx_ni(skb);
440*514def5dSRadu Pirea (NXP OSS) 	}
441*514def5dSRadu Pirea (NXP OSS) 
442*514def5dSRadu Pirea (NXP OSS) 	return reschedule ? 1 : -1;
443*514def5dSRadu Pirea (NXP OSS) }
444*514def5dSRadu Pirea (NXP OSS) 
445*514def5dSRadu Pirea (NXP OSS) static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv)
446*514def5dSRadu Pirea (NXP OSS) {
447*514def5dSRadu Pirea (NXP OSS) 	priv->caps = (struct ptp_clock_info) {
448*514def5dSRadu Pirea (NXP OSS) 		.owner		= THIS_MODULE,
449*514def5dSRadu Pirea (NXP OSS) 		.name		= "NXP C45 PHC",
450*514def5dSRadu Pirea (NXP OSS) 		.max_adj	= 16666666,
451*514def5dSRadu Pirea (NXP OSS) 		.adjfine	= nxp_c45_ptp_adjfine,
452*514def5dSRadu Pirea (NXP OSS) 		.adjtime	= nxp_c45_ptp_adjtime,
453*514def5dSRadu Pirea (NXP OSS) 		.gettimex64	= nxp_c45_ptp_gettimex64,
454*514def5dSRadu Pirea (NXP OSS) 		.settime64	= nxp_c45_ptp_settime64,
455*514def5dSRadu Pirea (NXP OSS) 		.do_aux_work	= nxp_c45_do_aux_work,
456*514def5dSRadu Pirea (NXP OSS) 	};
457*514def5dSRadu Pirea (NXP OSS) 
458*514def5dSRadu Pirea (NXP OSS) 	priv->ptp_clock = ptp_clock_register(&priv->caps,
459*514def5dSRadu Pirea (NXP OSS) 					     &priv->phydev->mdio.dev);
460*514def5dSRadu Pirea (NXP OSS) 
461*514def5dSRadu Pirea (NXP OSS) 	if (IS_ERR(priv->ptp_clock))
462*514def5dSRadu Pirea (NXP OSS) 		return PTR_ERR(priv->ptp_clock);
463*514def5dSRadu Pirea (NXP OSS) 
464*514def5dSRadu Pirea (NXP OSS) 	if (!priv->ptp_clock)
465*514def5dSRadu Pirea (NXP OSS) 		return -ENOMEM;
466*514def5dSRadu Pirea (NXP OSS) 
467*514def5dSRadu Pirea (NXP OSS) 	return 0;
468*514def5dSRadu Pirea (NXP OSS) }
469*514def5dSRadu Pirea (NXP OSS) 
470*514def5dSRadu Pirea (NXP OSS) static void nxp_c45_txtstamp(struct mii_timestamper *mii_ts,
471*514def5dSRadu Pirea (NXP OSS) 			     struct sk_buff *skb, int type)
472*514def5dSRadu Pirea (NXP OSS) {
473*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
474*514def5dSRadu Pirea (NXP OSS) 						mii_ts);
475*514def5dSRadu Pirea (NXP OSS) 
476*514def5dSRadu Pirea (NXP OSS) 	switch (priv->hwts_tx) {
477*514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_TX_ON:
478*514def5dSRadu Pirea (NXP OSS) 		NXP_C45_SKB_CB(skb)->type = type;
479*514def5dSRadu Pirea (NXP OSS) 		NXP_C45_SKB_CB(skb)->header = ptp_parse_header(skb, type);
480*514def5dSRadu Pirea (NXP OSS) 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
481*514def5dSRadu Pirea (NXP OSS) 		skb_queue_tail(&priv->tx_queue, skb);
482*514def5dSRadu Pirea (NXP OSS) 		if (nxp_c45_poll_txts(priv->phydev))
483*514def5dSRadu Pirea (NXP OSS) 			ptp_schedule_worker(priv->ptp_clock, 0);
484*514def5dSRadu Pirea (NXP OSS) 		break;
485*514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_TX_OFF:
486*514def5dSRadu Pirea (NXP OSS) 	default:
487*514def5dSRadu Pirea (NXP OSS) 		kfree_skb(skb);
488*514def5dSRadu Pirea (NXP OSS) 		break;
489*514def5dSRadu Pirea (NXP OSS) 	}
490*514def5dSRadu Pirea (NXP OSS) }
491*514def5dSRadu Pirea (NXP OSS) 
492*514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_rxtstamp(struct mii_timestamper *mii_ts,
493*514def5dSRadu Pirea (NXP OSS) 			     struct sk_buff *skb, int type)
494*514def5dSRadu Pirea (NXP OSS) {
495*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
496*514def5dSRadu Pirea (NXP OSS) 						mii_ts);
497*514def5dSRadu Pirea (NXP OSS) 	struct ptp_header *header = ptp_parse_header(skb, type);
498*514def5dSRadu Pirea (NXP OSS) 
499*514def5dSRadu Pirea (NXP OSS) 	if (!header)
500*514def5dSRadu Pirea (NXP OSS) 		return false;
501*514def5dSRadu Pirea (NXP OSS) 
502*514def5dSRadu Pirea (NXP OSS) 	if (!priv->hwts_rx)
503*514def5dSRadu Pirea (NXP OSS) 		return false;
504*514def5dSRadu Pirea (NXP OSS) 
505*514def5dSRadu Pirea (NXP OSS) 	NXP_C45_SKB_CB(skb)->header = header;
506*514def5dSRadu Pirea (NXP OSS) 	skb_queue_tail(&priv->rx_queue, skb);
507*514def5dSRadu Pirea (NXP OSS) 	ptp_schedule_worker(priv->ptp_clock, 0);
508*514def5dSRadu Pirea (NXP OSS) 
509*514def5dSRadu Pirea (NXP OSS) 	return true;
510*514def5dSRadu Pirea (NXP OSS) }
511*514def5dSRadu Pirea (NXP OSS) 
512*514def5dSRadu Pirea (NXP OSS) static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts,
513*514def5dSRadu Pirea (NXP OSS) 			    struct ifreq *ifreq)
514*514def5dSRadu Pirea (NXP OSS) {
515*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
516*514def5dSRadu Pirea (NXP OSS) 						mii_ts);
517*514def5dSRadu Pirea (NXP OSS) 	struct phy_device *phydev = priv->phydev;
518*514def5dSRadu Pirea (NXP OSS) 	struct hwtstamp_config cfg;
519*514def5dSRadu Pirea (NXP OSS) 
520*514def5dSRadu Pirea (NXP OSS) 	if (copy_from_user(&cfg, ifreq->ifr_data, sizeof(cfg)))
521*514def5dSRadu Pirea (NXP OSS) 		return -EFAULT;
522*514def5dSRadu Pirea (NXP OSS) 
523*514def5dSRadu Pirea (NXP OSS) 	if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ON)
524*514def5dSRadu Pirea (NXP OSS) 		return -ERANGE;
525*514def5dSRadu Pirea (NXP OSS) 
526*514def5dSRadu Pirea (NXP OSS) 	priv->hwts_tx = cfg.tx_type;
527*514def5dSRadu Pirea (NXP OSS) 
528*514def5dSRadu Pirea (NXP OSS) 	switch (cfg.rx_filter) {
529*514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_FILTER_NONE:
530*514def5dSRadu Pirea (NXP OSS) 		priv->hwts_rx = 0;
531*514def5dSRadu Pirea (NXP OSS) 		break;
532*514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
533*514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
534*514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
535*514def5dSRadu Pirea (NXP OSS) 		priv->hwts_rx = 1;
536*514def5dSRadu Pirea (NXP OSS) 		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
537*514def5dSRadu Pirea (NXP OSS) 		break;
538*514def5dSRadu Pirea (NXP OSS) 	default:
539*514def5dSRadu Pirea (NXP OSS) 		return -ERANGE;
540*514def5dSRadu Pirea (NXP OSS) 	}
541*514def5dSRadu Pirea (NXP OSS) 
542*514def5dSRadu Pirea (NXP OSS) 	if (priv->hwts_rx || priv->hwts_tx) {
543*514def5dSRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_EVENT_MSG_FILT,
544*514def5dSRadu Pirea (NXP OSS) 			      EVENT_MSG_FILT_ALL);
545*514def5dSRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
546*514def5dSRadu Pirea (NXP OSS) 				   VEND1_PORT_PTP_CONTROL,
547*514def5dSRadu Pirea (NXP OSS) 				   PORT_PTP_CONTROL_BYPASS);
548*514def5dSRadu Pirea (NXP OSS) 	} else {
549*514def5dSRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_EVENT_MSG_FILT,
550*514def5dSRadu Pirea (NXP OSS) 			      EVENT_MSG_FILT_NONE);
551*514def5dSRadu Pirea (NXP OSS) 		phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_PTP_CONTROL,
552*514def5dSRadu Pirea (NXP OSS) 				 PORT_PTP_CONTROL_BYPASS);
553*514def5dSRadu Pirea (NXP OSS) 	}
554*514def5dSRadu Pirea (NXP OSS) 
555*514def5dSRadu Pirea (NXP OSS) 	if (nxp_c45_poll_txts(priv->phydev))
556*514def5dSRadu Pirea (NXP OSS) 		goto nxp_c45_no_ptp_irq;
557*514def5dSRadu Pirea (NXP OSS) 
558*514def5dSRadu Pirea (NXP OSS) 	if (priv->hwts_tx)
559*514def5dSRadu Pirea (NXP OSS) 		phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
560*514def5dSRadu Pirea (NXP OSS) 				 VEND1_PTP_IRQ_EN, PTP_IRQ_EGR_TS);
561*514def5dSRadu Pirea (NXP OSS) 	else
562*514def5dSRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
563*514def5dSRadu Pirea (NXP OSS) 				   VEND1_PTP_IRQ_EN, PTP_IRQ_EGR_TS);
564*514def5dSRadu Pirea (NXP OSS) 
565*514def5dSRadu Pirea (NXP OSS) nxp_c45_no_ptp_irq:
566*514def5dSRadu Pirea (NXP OSS) 	return copy_to_user(ifreq->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
567*514def5dSRadu Pirea (NXP OSS) }
568*514def5dSRadu Pirea (NXP OSS) 
569*514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ts_info(struct mii_timestamper *mii_ts,
570*514def5dSRadu Pirea (NXP OSS) 			   struct ethtool_ts_info *ts_info)
571*514def5dSRadu Pirea (NXP OSS) {
572*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
573*514def5dSRadu Pirea (NXP OSS) 						mii_ts);
574*514def5dSRadu Pirea (NXP OSS) 
575*514def5dSRadu Pirea (NXP OSS) 	ts_info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
576*514def5dSRadu Pirea (NXP OSS) 			SOF_TIMESTAMPING_RX_HARDWARE |
577*514def5dSRadu Pirea (NXP OSS) 			SOF_TIMESTAMPING_RAW_HARDWARE;
578*514def5dSRadu Pirea (NXP OSS) 	ts_info->phc_index = ptp_clock_index(priv->ptp_clock);
579*514def5dSRadu Pirea (NXP OSS) 	ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
580*514def5dSRadu Pirea (NXP OSS) 	ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
581*514def5dSRadu Pirea (NXP OSS) 			(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
582*514def5dSRadu Pirea (NXP OSS) 			(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
583*514def5dSRadu Pirea (NXP OSS) 			(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT);
584*514def5dSRadu Pirea (NXP OSS) 
585*514def5dSRadu Pirea (NXP OSS) 	return 0;
586*514def5dSRadu Pirea (NXP OSS) }
587*514def5dSRadu Pirea (NXP OSS) 
588b050f2f1SRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats nxp_c45_hw_stats[] = {
589b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_symbol_error_cnt", MDIO_MMD_VEND1,
590b050f2f1SRadu Pirea (NXP OSS) 		VEND1_SYMBOL_ERROR_COUNTER, 0, GENMASK(15, 0) },
591b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_link_status_drop_cnt", MDIO_MMD_VEND1,
592b050f2f1SRadu Pirea (NXP OSS) 		VEND1_LINK_DROP_COUNTER, 8, GENMASK(13, 8) },
593b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_link_availability_drop_cnt", MDIO_MMD_VEND1,
594b050f2f1SRadu Pirea (NXP OSS) 		VEND1_LINK_DROP_COUNTER, 0, GENMASK(5, 0) },
595b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_link_loss_cnt", MDIO_MMD_VEND1,
596b050f2f1SRadu Pirea (NXP OSS) 		VEND1_LINK_LOSSES_AND_FAILURES, 10, GENMASK(15, 10) },
597b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_link_failure_cnt", MDIO_MMD_VEND1,
598b050f2f1SRadu Pirea (NXP OSS) 		VEND1_LINK_LOSSES_AND_FAILURES, 0, GENMASK(9, 0) },
599b050f2f1SRadu Pirea (NXP OSS) 	{ "r_good_frame_cnt", MDIO_MMD_VEND1,
600b050f2f1SRadu Pirea (NXP OSS) 		VEND1_R_GOOD_FRAME_CNT, 0, GENMASK(15, 0) },
601b050f2f1SRadu Pirea (NXP OSS) 	{ "r_bad_frame_cnt", MDIO_MMD_VEND1,
602b050f2f1SRadu Pirea (NXP OSS) 		VEND1_R_BAD_FRAME_CNT, 0, GENMASK(15, 0) },
603b050f2f1SRadu Pirea (NXP OSS) 	{ "r_rxer_frame_cnt", MDIO_MMD_VEND1,
604b050f2f1SRadu Pirea (NXP OSS) 		VEND1_R_RXER_FRAME_CNT, 0, GENMASK(15, 0) },
605b050f2f1SRadu Pirea (NXP OSS) 	{ "rx_preamble_count", MDIO_MMD_VEND1,
606b050f2f1SRadu Pirea (NXP OSS) 		VEND1_RX_PREAMBLE_COUNT, 0, GENMASK(5, 0) },
607b050f2f1SRadu Pirea (NXP OSS) 	{ "tx_preamble_count", MDIO_MMD_VEND1,
608b050f2f1SRadu Pirea (NXP OSS) 		VEND1_TX_PREAMBLE_COUNT, 0, GENMASK(5, 0) },
609b050f2f1SRadu Pirea (NXP OSS) 	{ "rx_ipg_length", MDIO_MMD_VEND1,
610b050f2f1SRadu Pirea (NXP OSS) 		VEND1_RX_IPG_LENGTH, 0, GENMASK(8, 0) },
611b050f2f1SRadu Pirea (NXP OSS) 	{ "tx_ipg_length", MDIO_MMD_VEND1,
612b050f2f1SRadu Pirea (NXP OSS) 		VEND1_TX_IPG_LENGTH, 0, GENMASK(8, 0) },
613b050f2f1SRadu Pirea (NXP OSS) };
614b050f2f1SRadu Pirea (NXP OSS) 
615b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev)
616b050f2f1SRadu Pirea (NXP OSS) {
617b050f2f1SRadu Pirea (NXP OSS) 	return ARRAY_SIZE(nxp_c45_hw_stats);
618b050f2f1SRadu Pirea (NXP OSS) }
619b050f2f1SRadu Pirea (NXP OSS) 
620b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data)
621b050f2f1SRadu Pirea (NXP OSS) {
622b050f2f1SRadu Pirea (NXP OSS) 	size_t i;
623b050f2f1SRadu Pirea (NXP OSS) 
624b050f2f1SRadu Pirea (NXP OSS) 	for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) {
625b050f2f1SRadu Pirea (NXP OSS) 		strncpy(data + i * ETH_GSTRING_LEN,
626b050f2f1SRadu Pirea (NXP OSS) 			nxp_c45_hw_stats[i].name, ETH_GSTRING_LEN);
627b050f2f1SRadu Pirea (NXP OSS) 	}
628b050f2f1SRadu Pirea (NXP OSS) }
629b050f2f1SRadu Pirea (NXP OSS) 
630b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev,
631b050f2f1SRadu Pirea (NXP OSS) 			      struct ethtool_stats *stats, u64 *data)
632b050f2f1SRadu Pirea (NXP OSS) {
633b050f2f1SRadu Pirea (NXP OSS) 	size_t i;
634b050f2f1SRadu Pirea (NXP OSS) 	int ret;
635b050f2f1SRadu Pirea (NXP OSS) 
636b050f2f1SRadu Pirea (NXP OSS) 	for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) {
637b050f2f1SRadu Pirea (NXP OSS) 		ret = phy_read_mmd(phydev, nxp_c45_hw_stats[i].mmd,
638b050f2f1SRadu Pirea (NXP OSS) 				   nxp_c45_hw_stats[i].reg);
639b050f2f1SRadu Pirea (NXP OSS) 		if (ret < 0) {
640b050f2f1SRadu Pirea (NXP OSS) 			data[i] = U64_MAX;
641b050f2f1SRadu Pirea (NXP OSS) 		} else {
642b050f2f1SRadu Pirea (NXP OSS) 			data[i] = ret & nxp_c45_hw_stats[i].mask;
643b050f2f1SRadu Pirea (NXP OSS) 			data[i] >>= nxp_c45_hw_stats[i].off;
644b050f2f1SRadu Pirea (NXP OSS) 		}
645b050f2f1SRadu Pirea (NXP OSS) 	}
646b050f2f1SRadu Pirea (NXP OSS) }
647b050f2f1SRadu Pirea (NXP OSS) 
648b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev)
649b050f2f1SRadu Pirea (NXP OSS) {
650b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
651b050f2f1SRadu Pirea (NXP OSS) 		      DEVICE_CONTROL_CONFIG_GLOBAL_EN |
652b050f2f1SRadu Pirea (NXP OSS) 		      DEVICE_CONTROL_CONFIG_ALL_EN);
653b050f2f1SRadu Pirea (NXP OSS) 	usleep_range(400, 450);
654b050f2f1SRadu Pirea (NXP OSS) 
655b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL,
656b050f2f1SRadu Pirea (NXP OSS) 		      PORT_CONTROL_EN);
657b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
658b050f2f1SRadu Pirea (NXP OSS) 		      PHY_CONFIG_EN);
659b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL,
660b050f2f1SRadu Pirea (NXP OSS) 		      PORT_INFRA_CONTROL_EN);
661b050f2f1SRadu Pirea (NXP OSS) 
662b050f2f1SRadu Pirea (NXP OSS) 	return 0;
663b050f2f1SRadu Pirea (NXP OSS) }
664b050f2f1SRadu Pirea (NXP OSS) 
665b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev)
666b050f2f1SRadu Pirea (NXP OSS) {
667b050f2f1SRadu Pirea (NXP OSS) 	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
668b050f2f1SRadu Pirea (NXP OSS) 				PHY_START_OP);
669b050f2f1SRadu Pirea (NXP OSS) }
670b050f2f1SRadu Pirea (NXP OSS) 
671b2f0ca00SRadu Pirea (NXP OSS) static int nxp_c45_config_intr(struct phy_device *phydev)
672b2f0ca00SRadu Pirea (NXP OSS) {
673b2f0ca00SRadu Pirea (NXP OSS) 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
674b2f0ca00SRadu Pirea (NXP OSS) 		return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
675b2f0ca00SRadu Pirea (NXP OSS) 					VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
676b2f0ca00SRadu Pirea (NXP OSS) 	else
677b2f0ca00SRadu Pirea (NXP OSS) 		return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
678b2f0ca00SRadu Pirea (NXP OSS) 					  VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
679b2f0ca00SRadu Pirea (NXP OSS) }
680b2f0ca00SRadu Pirea (NXP OSS) 
681b2f0ca00SRadu Pirea (NXP OSS) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev)
682b2f0ca00SRadu Pirea (NXP OSS) {
683*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = phydev->priv;
684b2f0ca00SRadu Pirea (NXP OSS) 	irqreturn_t ret = IRQ_NONE;
685*514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_hwts hwts;
686b2f0ca00SRadu Pirea (NXP OSS) 	int irq;
687b2f0ca00SRadu Pirea (NXP OSS) 
688b2f0ca00SRadu Pirea (NXP OSS) 	irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS);
689b2f0ca00SRadu Pirea (NXP OSS) 	if (irq & PHY_IRQ_LINK_EVENT) {
690b2f0ca00SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK,
691b2f0ca00SRadu Pirea (NXP OSS) 			      PHY_IRQ_LINK_EVENT);
692b2f0ca00SRadu Pirea (NXP OSS) 		phy_trigger_machine(phydev);
693b2f0ca00SRadu Pirea (NXP OSS) 		ret = IRQ_HANDLED;
694b2f0ca00SRadu Pirea (NXP OSS) 	}
695b2f0ca00SRadu Pirea (NXP OSS) 
696*514def5dSRadu Pirea (NXP OSS) 	/* There is no need for ACK.
697*514def5dSRadu Pirea (NXP OSS) 	 * The irq signal will be asserted until the EGR TS FIFO will be
698*514def5dSRadu Pirea (NXP OSS) 	 * emptied.
699*514def5dSRadu Pirea (NXP OSS) 	 */
700*514def5dSRadu Pirea (NXP OSS) 	irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_IRQ_STATUS);
701*514def5dSRadu Pirea (NXP OSS) 	if (irq & PTP_IRQ_EGR_TS) {
702*514def5dSRadu Pirea (NXP OSS) 		while (nxp_c45_get_hwtxts(priv, &hwts))
703*514def5dSRadu Pirea (NXP OSS) 			nxp_c45_process_txts(priv, &hwts);
704*514def5dSRadu Pirea (NXP OSS) 
705*514def5dSRadu Pirea (NXP OSS) 		ret = IRQ_HANDLED;
706*514def5dSRadu Pirea (NXP OSS) 	}
707*514def5dSRadu Pirea (NXP OSS) 
708b2f0ca00SRadu Pirea (NXP OSS) 	return ret;
709b2f0ca00SRadu Pirea (NXP OSS) }
710b2f0ca00SRadu Pirea (NXP OSS) 
711b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev)
712b050f2f1SRadu Pirea (NXP OSS) {
713b050f2f1SRadu Pirea (NXP OSS) 	int ret;
714b050f2f1SRadu Pirea (NXP OSS) 
715b050f2f1SRadu Pirea (NXP OSS) 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
716b050f2f1SRadu Pirea (NXP OSS) 			    DEVICE_CONTROL_RESET);
717b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
718b050f2f1SRadu Pirea (NXP OSS) 		return ret;
719b050f2f1SRadu Pirea (NXP OSS) 
720b050f2f1SRadu Pirea (NXP OSS) 	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
721b050f2f1SRadu Pirea (NXP OSS) 					 VEND1_DEVICE_CONTROL, ret,
722b050f2f1SRadu Pirea (NXP OSS) 					 !(ret & DEVICE_CONTROL_RESET), 20000,
723b050f2f1SRadu Pirea (NXP OSS) 					 240000, false);
724b050f2f1SRadu Pirea (NXP OSS) }
725b050f2f1SRadu Pirea (NXP OSS) 
726b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev)
727b050f2f1SRadu Pirea (NXP OSS) {
728b050f2f1SRadu Pirea (NXP OSS) 	return phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST,
729b050f2f1SRadu Pirea (NXP OSS) 			     CABLE_TEST_ENABLE | CABLE_TEST_START);
730b050f2f1SRadu Pirea (NXP OSS) }
731b050f2f1SRadu Pirea (NXP OSS) 
732b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev,
733b050f2f1SRadu Pirea (NXP OSS) 					 bool *finished)
734b050f2f1SRadu Pirea (NXP OSS) {
735b050f2f1SRadu Pirea (NXP OSS) 	int ret;
736b050f2f1SRadu Pirea (NXP OSS) 	u8 cable_test_result;
737b050f2f1SRadu Pirea (NXP OSS) 
738b050f2f1SRadu Pirea (NXP OSS) 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST);
739b050f2f1SRadu Pirea (NXP OSS) 	if (!(ret & CABLE_TEST_VALID)) {
740b050f2f1SRadu Pirea (NXP OSS) 		*finished = false;
741b050f2f1SRadu Pirea (NXP OSS) 		return 0;
742b050f2f1SRadu Pirea (NXP OSS) 	}
743b050f2f1SRadu Pirea (NXP OSS) 
744b050f2f1SRadu Pirea (NXP OSS) 	*finished = true;
745b050f2f1SRadu Pirea (NXP OSS) 	cable_test_result = ret & GENMASK(2, 0);
746b050f2f1SRadu Pirea (NXP OSS) 
747b050f2f1SRadu Pirea (NXP OSS) 	switch (cable_test_result) {
748b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_OK:
749b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
750b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_OK);
751b050f2f1SRadu Pirea (NXP OSS) 		break;
752b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_SHORTED:
753b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
754b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT);
755b050f2f1SRadu Pirea (NXP OSS) 		break;
756b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_OPEN:
757b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
758b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_OPEN);
759b050f2f1SRadu Pirea (NXP OSS) 		break;
760b050f2f1SRadu Pirea (NXP OSS) 	default:
761b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
762b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC);
763b050f2f1SRadu Pirea (NXP OSS) 	}
764b050f2f1SRadu Pirea (NXP OSS) 
765b050f2f1SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST,
766b050f2f1SRadu Pirea (NXP OSS) 			   CABLE_TEST_ENABLE);
767b050f2f1SRadu Pirea (NXP OSS) 
768b050f2f1SRadu Pirea (NXP OSS) 	return nxp_c45_start_op(phydev);
769b050f2f1SRadu Pirea (NXP OSS) }
770b050f2f1SRadu Pirea (NXP OSS) 
771b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_setup_master_slave(struct phy_device *phydev)
772b050f2f1SRadu Pirea (NXP OSS) {
773b050f2f1SRadu Pirea (NXP OSS) 	switch (phydev->master_slave_set) {
774b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_MASTER_FORCE:
775b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_MASTER_PREFERRED:
776b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL,
777b050f2f1SRadu Pirea (NXP OSS) 			      MASTER_MODE);
778b050f2f1SRadu Pirea (NXP OSS) 		break;
779b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_SLAVE_PREFERRED:
780b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_SLAVE_FORCE:
781b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL,
782b050f2f1SRadu Pirea (NXP OSS) 			      SLAVE_MODE);
783b050f2f1SRadu Pirea (NXP OSS) 		break;
784b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_UNKNOWN:
785b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_UNSUPPORTED:
786b050f2f1SRadu Pirea (NXP OSS) 		return 0;
787b050f2f1SRadu Pirea (NXP OSS) 	default:
788b050f2f1SRadu Pirea (NXP OSS) 		phydev_warn(phydev, "Unsupported Master/Slave mode\n");
789b050f2f1SRadu Pirea (NXP OSS) 		return -EOPNOTSUPP;
790b050f2f1SRadu Pirea (NXP OSS) 	}
791b050f2f1SRadu Pirea (NXP OSS) 
792b050f2f1SRadu Pirea (NXP OSS) 	return 0;
793b050f2f1SRadu Pirea (NXP OSS) }
794b050f2f1SRadu Pirea (NXP OSS) 
795b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_read_master_slave(struct phy_device *phydev)
796b050f2f1SRadu Pirea (NXP OSS) {
797b050f2f1SRadu Pirea (NXP OSS) 	int reg;
798b050f2f1SRadu Pirea (NXP OSS) 
799b050f2f1SRadu Pirea (NXP OSS) 	phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN;
800b050f2f1SRadu Pirea (NXP OSS) 	phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
801b050f2f1SRadu Pirea (NXP OSS) 
802b050f2f1SRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL);
803b050f2f1SRadu Pirea (NXP OSS) 	if (reg < 0)
804b050f2f1SRadu Pirea (NXP OSS) 		return reg;
805b050f2f1SRadu Pirea (NXP OSS) 
806b050f2f1SRadu Pirea (NXP OSS) 	if (reg & B100T1_PMAPMD_MASTER) {
807b050f2f1SRadu Pirea (NXP OSS) 		phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE;
808b050f2f1SRadu Pirea (NXP OSS) 		phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
809b050f2f1SRadu Pirea (NXP OSS) 	} else {
810b050f2f1SRadu Pirea (NXP OSS) 		phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE;
811b050f2f1SRadu Pirea (NXP OSS) 		phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
812b050f2f1SRadu Pirea (NXP OSS) 	}
813b050f2f1SRadu Pirea (NXP OSS) 
814b050f2f1SRadu Pirea (NXP OSS) 	return 0;
815b050f2f1SRadu Pirea (NXP OSS) }
816b050f2f1SRadu Pirea (NXP OSS) 
817b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_aneg(struct phy_device *phydev)
818b050f2f1SRadu Pirea (NXP OSS) {
819b050f2f1SRadu Pirea (NXP OSS) 	return nxp_c45_setup_master_slave(phydev);
820b050f2f1SRadu Pirea (NXP OSS) }
821b050f2f1SRadu Pirea (NXP OSS) 
822b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_read_status(struct phy_device *phydev)
823b050f2f1SRadu Pirea (NXP OSS) {
824b050f2f1SRadu Pirea (NXP OSS) 	int ret;
825b050f2f1SRadu Pirea (NXP OSS) 
826b050f2f1SRadu Pirea (NXP OSS) 	ret = genphy_c45_read_status(phydev);
827b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
828b050f2f1SRadu Pirea (NXP OSS) 		return ret;
829b050f2f1SRadu Pirea (NXP OSS) 
830b050f2f1SRadu Pirea (NXP OSS) 	ret = nxp_c45_read_master_slave(phydev);
831b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
832b050f2f1SRadu Pirea (NXP OSS) 		return ret;
833b050f2f1SRadu Pirea (NXP OSS) 
834b050f2f1SRadu Pirea (NXP OSS) 	return 0;
835b050f2f1SRadu Pirea (NXP OSS) }
836b050f2f1SRadu Pirea (NXP OSS) 
837b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev)
838b050f2f1SRadu Pirea (NXP OSS) {
839b050f2f1SRadu Pirea (NXP OSS) 	int reg;
840b050f2f1SRadu Pirea (NXP OSS) 
841b050f2f1SRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY);
842b050f2f1SRadu Pirea (NXP OSS) 	if (!(reg & SQI_VALID))
843b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
844b050f2f1SRadu Pirea (NXP OSS) 
845b050f2f1SRadu Pirea (NXP OSS) 	reg &= SQI_MASK;
846b050f2f1SRadu Pirea (NXP OSS) 
847b050f2f1SRadu Pirea (NXP OSS) 	return reg;
848b050f2f1SRadu Pirea (NXP OSS) }
849b050f2f1SRadu Pirea (NXP OSS) 
850b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev)
851b050f2f1SRadu Pirea (NXP OSS) {
852b050f2f1SRadu Pirea (NXP OSS) 	return MAX_SQI;
853b050f2f1SRadu Pirea (NXP OSS) }
854b050f2f1SRadu Pirea (NXP OSS) 
855b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay)
856b050f2f1SRadu Pirea (NXP OSS) {
857b050f2f1SRadu Pirea (NXP OSS) 	if (delay < MIN_ID_PS) {
858b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS);
859b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
860b050f2f1SRadu Pirea (NXP OSS) 	}
861b050f2f1SRadu Pirea (NXP OSS) 
862b050f2f1SRadu Pirea (NXP OSS) 	if (delay > MAX_ID_PS) {
863b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS);
864b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
865b050f2f1SRadu Pirea (NXP OSS) 	}
866b050f2f1SRadu Pirea (NXP OSS) 
867b050f2f1SRadu Pirea (NXP OSS) 	return 0;
868b050f2f1SRadu Pirea (NXP OSS) }
869b050f2f1SRadu Pirea (NXP OSS) 
870b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw)
871b050f2f1SRadu Pirea (NXP OSS) {
872b050f2f1SRadu Pirea (NXP OSS) 	/* The delay in degree phase is 73.8 + phase_offset_raw * 0.9.
873b050f2f1SRadu Pirea (NXP OSS) 	 * To avoid floating point operations we'll multiply by 10
874b050f2f1SRadu Pirea (NXP OSS) 	 * and get 1 decimal point precision.
875b050f2f1SRadu Pirea (NXP OSS) 	 */
876b050f2f1SRadu Pirea (NXP OSS) 	phase_offset_raw *= 10;
8776b3a6310SRadu Pirea (NXP OSS) 	phase_offset_raw -= 738;
878b050f2f1SRadu Pirea (NXP OSS) 	return div_u64(phase_offset_raw, 9);
879b050f2f1SRadu Pirea (NXP OSS) }
880b050f2f1SRadu Pirea (NXP OSS) 
881b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev)
882b050f2f1SRadu Pirea (NXP OSS) {
883b050f2f1SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE);
884b050f2f1SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE);
885b050f2f1SRadu Pirea (NXP OSS) }
886b050f2f1SRadu Pirea (NXP OSS) 
887b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev)
888b050f2f1SRadu Pirea (NXP OSS) {
889b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = phydev->priv;
890b050f2f1SRadu Pirea (NXP OSS) 	u64 tx_delay = priv->tx_delay;
891b050f2f1SRadu Pirea (NXP OSS) 	u64 rx_delay = priv->rx_delay;
892b050f2f1SRadu Pirea (NXP OSS) 	u64 degree;
893b050f2f1SRadu Pirea (NXP OSS) 
894b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
895b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
896b050f2f1SRadu Pirea (NXP OSS) 		degree = div_u64(tx_delay, PS_PER_DEGREE);
897b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
898b050f2f1SRadu Pirea (NXP OSS) 			      ID_ENABLE | nxp_c45_get_phase_shift(degree));
899b050f2f1SRadu Pirea (NXP OSS) 	} else {
900b050f2f1SRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
901b050f2f1SRadu Pirea (NXP OSS) 				   ID_ENABLE);
902b050f2f1SRadu Pirea (NXP OSS) 	}
903b050f2f1SRadu Pirea (NXP OSS) 
904b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
905b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
906b050f2f1SRadu Pirea (NXP OSS) 		degree = div_u64(rx_delay, PS_PER_DEGREE);
907b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
908b050f2f1SRadu Pirea (NXP OSS) 			      ID_ENABLE | nxp_c45_get_phase_shift(degree));
909b050f2f1SRadu Pirea (NXP OSS) 	} else {
910b050f2f1SRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
911b050f2f1SRadu Pirea (NXP OSS) 				   ID_ENABLE);
912b050f2f1SRadu Pirea (NXP OSS) 	}
913b050f2f1SRadu Pirea (NXP OSS) }
914b050f2f1SRadu Pirea (NXP OSS) 
915b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev)
916b050f2f1SRadu Pirea (NXP OSS) {
917b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = phydev->priv;
918b050f2f1SRadu Pirea (NXP OSS) 	int ret;
919b050f2f1SRadu Pirea (NXP OSS) 
920b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
921b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
922b050f2f1SRadu Pirea (NXP OSS) 		ret = device_property_read_u32(&phydev->mdio.dev,
923b050f2f1SRadu Pirea (NXP OSS) 					       "tx-internal-delay-ps",
924b050f2f1SRadu Pirea (NXP OSS) 					       &priv->tx_delay);
925b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
926b050f2f1SRadu Pirea (NXP OSS) 			priv->tx_delay = DEFAULT_ID_PS;
927b050f2f1SRadu Pirea (NXP OSS) 
928b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_check_delay(phydev, priv->tx_delay);
929b050f2f1SRadu Pirea (NXP OSS) 		if (ret) {
930b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev,
931b050f2f1SRadu Pirea (NXP OSS) 				   "tx-internal-delay-ps invalid value\n");
932b050f2f1SRadu Pirea (NXP OSS) 			return ret;
933b050f2f1SRadu Pirea (NXP OSS) 		}
934b050f2f1SRadu Pirea (NXP OSS) 	}
935b050f2f1SRadu Pirea (NXP OSS) 
936b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
937b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
938b050f2f1SRadu Pirea (NXP OSS) 		ret = device_property_read_u32(&phydev->mdio.dev,
939b050f2f1SRadu Pirea (NXP OSS) 					       "rx-internal-delay-ps",
940b050f2f1SRadu Pirea (NXP OSS) 					       &priv->rx_delay);
941b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
942b050f2f1SRadu Pirea (NXP OSS) 			priv->rx_delay = DEFAULT_ID_PS;
943b050f2f1SRadu Pirea (NXP OSS) 
944b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_check_delay(phydev, priv->rx_delay);
945b050f2f1SRadu Pirea (NXP OSS) 		if (ret) {
946b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev,
947b050f2f1SRadu Pirea (NXP OSS) 				   "rx-internal-delay-ps invalid value\n");
948b050f2f1SRadu Pirea (NXP OSS) 			return ret;
949b050f2f1SRadu Pirea (NXP OSS) 		}
950b050f2f1SRadu Pirea (NXP OSS) 	}
951b050f2f1SRadu Pirea (NXP OSS) 
952b050f2f1SRadu Pirea (NXP OSS) 	return 0;
953b050f2f1SRadu Pirea (NXP OSS) }
954b050f2f1SRadu Pirea (NXP OSS) 
955b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev)
956b050f2f1SRadu Pirea (NXP OSS) {
957b050f2f1SRadu Pirea (NXP OSS) 	int ret;
958b050f2f1SRadu Pirea (NXP OSS) 
959b050f2f1SRadu Pirea (NXP OSS) 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES);
960b050f2f1SRadu Pirea (NXP OSS) 	phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret);
961b050f2f1SRadu Pirea (NXP OSS) 
962b050f2f1SRadu Pirea (NXP OSS) 	switch (phydev->interface) {
963b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII:
964b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RGMII_ABILITY)) {
965b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rgmii mode not supported\n");
966b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
967b050f2f1SRadu Pirea (NXP OSS) 		}
968b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
969b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RGMII);
970b050f2f1SRadu Pirea (NXP OSS) 		nxp_c45_disable_delays(phydev);
971b050f2f1SRadu Pirea (NXP OSS) 		break;
972b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_ID:
973b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_TXID:
974b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_RXID:
975b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RGMII_ID_ABILITY)) {
976b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n");
977b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
978b050f2f1SRadu Pirea (NXP OSS) 		}
979b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
980b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RGMII);
981b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_get_delays(phydev);
982b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
983b050f2f1SRadu Pirea (NXP OSS) 			return ret;
984b050f2f1SRadu Pirea (NXP OSS) 
985b050f2f1SRadu Pirea (NXP OSS) 		nxp_c45_set_delays(phydev);
986b050f2f1SRadu Pirea (NXP OSS) 		break;
987b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_MII:
988b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & MII_ABILITY)) {
989b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "mii mode not supported\n");
990b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
991b050f2f1SRadu Pirea (NXP OSS) 		}
992b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
993b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_MII);
994b050f2f1SRadu Pirea (NXP OSS) 		break;
995b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_REVMII:
996b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & REVMII_ABILITY)) {
997b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rev-mii mode not supported\n");
998b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
999b050f2f1SRadu Pirea (NXP OSS) 		}
1000b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1001b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_MII | MII_BASIC_CONFIG_REV);
1002b050f2f1SRadu Pirea (NXP OSS) 		break;
1003b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RMII:
1004b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RMII_ABILITY)) {
1005b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rmii mode not supported\n");
1006b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
1007b050f2f1SRadu Pirea (NXP OSS) 		}
1008b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1009b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RMII);
1010b050f2f1SRadu Pirea (NXP OSS) 		break;
1011b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_SGMII:
1012b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & SGMII_ABILITY)) {
1013b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "sgmii mode not supported\n");
1014b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
1015b050f2f1SRadu Pirea (NXP OSS) 		}
1016b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1017b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_SGMII);
1018b050f2f1SRadu Pirea (NXP OSS) 		break;
1019b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_INTERNAL:
1020b050f2f1SRadu Pirea (NXP OSS) 		break;
1021b050f2f1SRadu Pirea (NXP OSS) 	default:
1022b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
1023b050f2f1SRadu Pirea (NXP OSS) 	}
1024b050f2f1SRadu Pirea (NXP OSS) 
1025b050f2f1SRadu Pirea (NXP OSS) 	return 0;
1026b050f2f1SRadu Pirea (NXP OSS) }
1027b050f2f1SRadu Pirea (NXP OSS) 
1028b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev)
1029b050f2f1SRadu Pirea (NXP OSS) {
1030b050f2f1SRadu Pirea (NXP OSS) 	int ret;
1031b050f2f1SRadu Pirea (NXP OSS) 
1032b050f2f1SRadu Pirea (NXP OSS) 	ret = nxp_c45_config_enable(phydev);
1033b050f2f1SRadu Pirea (NXP OSS) 	if (ret) {
1034b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "Failed to enable config\n");
1035b050f2f1SRadu Pirea (NXP OSS) 		return ret;
1036b050f2f1SRadu Pirea (NXP OSS) 	}
1037b050f2f1SRadu Pirea (NXP OSS) 
1038b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG,
1039b050f2f1SRadu Pirea (NXP OSS) 			 PHY_CONFIG_AUTO);
1040b050f2f1SRadu Pirea (NXP OSS) 
1041b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER,
1042b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
1043b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT,
1044b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
1045b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT,
1046b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
1047b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH,
1048b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
1049b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH,
1050b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
1051b050f2f1SRadu Pirea (NXP OSS) 
1052b050f2f1SRadu Pirea (NXP OSS) 	ret = nxp_c45_set_phy_mode(phydev);
1053b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
1054b050f2f1SRadu Pirea (NXP OSS) 		return ret;
1055b050f2f1SRadu Pirea (NXP OSS) 
1056b050f2f1SRadu Pirea (NXP OSS) 	phydev->autoneg = AUTONEG_DISABLE;
1057b050f2f1SRadu Pirea (NXP OSS) 
1058*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK_PERIOD,
1059*514def5dSRadu Pirea (NXP OSS) 		      PTP_CLK_PERIOD_100BT1);
1060*514def5dSRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_HW_LTC_LOCK_CTRL,
1061*514def5dSRadu Pirea (NXP OSS) 			   HW_LTC_LOCK_EN);
1062*514def5dSRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL,
1063*514def5dSRadu Pirea (NXP OSS) 		      RX_TS_INSRT_MODE2);
1064*514def5dSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES,
1065*514def5dSRadu Pirea (NXP OSS) 			 PTP_ENABLE);
1066*514def5dSRadu Pirea (NXP OSS) 
1067b050f2f1SRadu Pirea (NXP OSS) 	return nxp_c45_start_op(phydev);
1068b050f2f1SRadu Pirea (NXP OSS) }
1069b050f2f1SRadu Pirea (NXP OSS) 
1070b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev)
1071b050f2f1SRadu Pirea (NXP OSS) {
1072b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv;
1073*514def5dSRadu Pirea (NXP OSS) 	int ptp_ability;
1074*514def5dSRadu Pirea (NXP OSS) 	int ret = 0;
1075b050f2f1SRadu Pirea (NXP OSS) 
1076b050f2f1SRadu Pirea (NXP OSS) 	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
1077b050f2f1SRadu Pirea (NXP OSS) 	if (!priv)
1078b050f2f1SRadu Pirea (NXP OSS) 		return -ENOMEM;
1079b050f2f1SRadu Pirea (NXP OSS) 
1080*514def5dSRadu Pirea (NXP OSS) 	skb_queue_head_init(&priv->tx_queue);
1081*514def5dSRadu Pirea (NXP OSS) 	skb_queue_head_init(&priv->rx_queue);
1082*514def5dSRadu Pirea (NXP OSS) 
1083*514def5dSRadu Pirea (NXP OSS) 	priv->phydev = phydev;
1084*514def5dSRadu Pirea (NXP OSS) 
1085b050f2f1SRadu Pirea (NXP OSS) 	phydev->priv = priv;
1086b050f2f1SRadu Pirea (NXP OSS) 
1087*514def5dSRadu Pirea (NXP OSS) 	mutex_init(&priv->ptp_lock);
1088*514def5dSRadu Pirea (NXP OSS) 
1089*514def5dSRadu Pirea (NXP OSS) 	ptp_ability = phy_read_mmd(phydev, MDIO_MMD_VEND1,
1090*514def5dSRadu Pirea (NXP OSS) 				   VEND1_PORT_ABILITIES);
1091*514def5dSRadu Pirea (NXP OSS) 	ptp_ability = !!(ptp_ability & PTP_ABILITY);
1092*514def5dSRadu Pirea (NXP OSS) 	if (!ptp_ability) {
1093*514def5dSRadu Pirea (NXP OSS) 		phydev_info(phydev, "the phy does not support PTP");
1094*514def5dSRadu Pirea (NXP OSS) 		goto no_ptp_support;
1095*514def5dSRadu Pirea (NXP OSS) 	}
1096*514def5dSRadu Pirea (NXP OSS) 
1097*514def5dSRadu Pirea (NXP OSS) 	if (IS_ENABLED(CONFIG_PTP_1588_CLOCK) &&
1098*514def5dSRadu Pirea (NXP OSS) 	    IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) {
1099*514def5dSRadu Pirea (NXP OSS) 		priv->mii_ts.rxtstamp = nxp_c45_rxtstamp;
1100*514def5dSRadu Pirea (NXP OSS) 		priv->mii_ts.txtstamp = nxp_c45_txtstamp;
1101*514def5dSRadu Pirea (NXP OSS) 		priv->mii_ts.hwtstamp = nxp_c45_hwtstamp;
1102*514def5dSRadu Pirea (NXP OSS) 		priv->mii_ts.ts_info = nxp_c45_ts_info;
1103*514def5dSRadu Pirea (NXP OSS) 		phydev->mii_ts = &priv->mii_ts;
1104*514def5dSRadu Pirea (NXP OSS) 		ret = nxp_c45_init_ptp_clock(priv);
1105*514def5dSRadu Pirea (NXP OSS) 	} else {
1106*514def5dSRadu Pirea (NXP OSS) 		phydev_dbg(phydev, "PTP support not enabled even if the phy supports it");
1107*514def5dSRadu Pirea (NXP OSS) 	}
1108*514def5dSRadu Pirea (NXP OSS) 
1109*514def5dSRadu Pirea (NXP OSS) no_ptp_support:
1110*514def5dSRadu Pirea (NXP OSS) 
1111*514def5dSRadu Pirea (NXP OSS) 	return ret;
1112b050f2f1SRadu Pirea (NXP OSS) }
1113b050f2f1SRadu Pirea (NXP OSS) 
1114b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = {
1115b050f2f1SRadu Pirea (NXP OSS) 	{
1116b050f2f1SRadu Pirea (NXP OSS) 		PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
1117b050f2f1SRadu Pirea (NXP OSS) 		.name			= "NXP C45 TJA1103",
1118b050f2f1SRadu Pirea (NXP OSS) 		.features		= PHY_BASIC_T1_FEATURES,
1119b050f2f1SRadu Pirea (NXP OSS) 		.probe			= nxp_c45_probe,
1120b050f2f1SRadu Pirea (NXP OSS) 		.soft_reset		= nxp_c45_soft_reset,
1121b050f2f1SRadu Pirea (NXP OSS) 		.config_aneg		= nxp_c45_config_aneg,
1122b050f2f1SRadu Pirea (NXP OSS) 		.config_init		= nxp_c45_config_init,
1123b2f0ca00SRadu Pirea (NXP OSS) 		.config_intr		= nxp_c45_config_intr,
1124b2f0ca00SRadu Pirea (NXP OSS) 		.handle_interrupt	= nxp_c45_handle_interrupt,
1125b050f2f1SRadu Pirea (NXP OSS) 		.read_status		= nxp_c45_read_status,
1126b050f2f1SRadu Pirea (NXP OSS) 		.suspend		= genphy_c45_pma_suspend,
1127b050f2f1SRadu Pirea (NXP OSS) 		.resume			= genphy_c45_pma_resume,
1128b050f2f1SRadu Pirea (NXP OSS) 		.get_sset_count		= nxp_c45_get_sset_count,
1129b050f2f1SRadu Pirea (NXP OSS) 		.get_strings		= nxp_c45_get_strings,
1130b050f2f1SRadu Pirea (NXP OSS) 		.get_stats		= nxp_c45_get_stats,
1131b050f2f1SRadu Pirea (NXP OSS) 		.cable_test_start	= nxp_c45_cable_test_start,
1132b050f2f1SRadu Pirea (NXP OSS) 		.cable_test_get_status	= nxp_c45_cable_test_get_status,
1133b050f2f1SRadu Pirea (NXP OSS) 		.set_loopback		= genphy_c45_loopback,
1134b050f2f1SRadu Pirea (NXP OSS) 		.get_sqi		= nxp_c45_get_sqi,
1135b050f2f1SRadu Pirea (NXP OSS) 		.get_sqi_max		= nxp_c45_get_sqi_max,
1136b050f2f1SRadu Pirea (NXP OSS) 	},
1137b050f2f1SRadu Pirea (NXP OSS) };
1138b050f2f1SRadu Pirea (NXP OSS) 
1139b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver);
1140b050f2f1SRadu Pirea (NXP OSS) 
1141b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = {
1142b050f2f1SRadu Pirea (NXP OSS) 	{ PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) },
1143b050f2f1SRadu Pirea (NXP OSS) 	{ /*sentinel*/ },
1144b050f2f1SRadu Pirea (NXP OSS) };
1145b050f2f1SRadu Pirea (NXP OSS) 
1146b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl);
1147b050f2f1SRadu Pirea (NXP OSS) 
1148b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>");
1149b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver");
1150b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2");
1151