xref: /openbmc/linux/drivers/net/phy/nxp-c45-tja11xx.c (revision 8ba572052a4b8fe5b205854d27e54e3486049b71)
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