xref: /openbmc/linux/drivers/net/phy/nxp-c45-tja11xx.c (revision 08e6547c8468863734a847154aee390f2a44befe)
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
21f1fe5dffSRadu Pirea (NXP OSS) #define PHY_ID_TJA_1120			0x001BB031
22b050f2f1SRadu Pirea (NXP OSS) 
23b050f2f1SRadu Pirea (NXP OSS) #define VEND1_DEVICE_CONTROL		0x0040
24b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_RESET		BIT(15)
25b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_GLOBAL_EN	BIT(14)
26b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_ALL_EN	BIT(13)
27b050f2f1SRadu Pirea (NXP OSS) 
28f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_DEVICE_CONFIG		0x0048
29f1fe5dffSRadu Pirea (NXP OSS) 
30f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_VEND1_EXT_TS_MODE	0x1012
31f1fe5dffSRadu Pirea (NXP OSS) 
32425c8348SRadu Pirea (NXP OSS) #define TJA1120_GLOBAL_INFRA_IRQ_ACK	0x2C08
33425c8348SRadu Pirea (NXP OSS) #define TJA1120_GLOBAL_INFRA_IRQ_EN	0x2C0A
34425c8348SRadu Pirea (NXP OSS) #define TJA1120_GLOBAL_INFRA_IRQ_STATUS	0x2C0C
35425c8348SRadu Pirea (NXP OSS) #define TJA1120_DEV_BOOT_DONE		BIT(1)
36425c8348SRadu Pirea (NXP OSS) 
37*08e6547cSRadu Pirea (NXP OSS) #define TJA1120_VEND1_PTP_TRIG_DATA_S	0x1070
38*08e6547cSRadu Pirea (NXP OSS) 
39bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_EGRESS_TS_DATA_S	0x9060
40bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_EGRESS_TS_END		0x9067
41bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_TS_VALID		BIT(0)
42bdb4c5b8SRadu Pirea (NXP OSS) #define TJA1120_MORE_TS			BIT(15)
43bdb4c5b8SRadu Pirea (NXP OSS) 
44b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_ACK		0x80A0
45b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_EN		0x80A1
46b2f0ca00SRadu Pirea (NXP OSS) #define VEND1_PHY_IRQ_STATUS		0x80A2
47b2f0ca00SRadu Pirea (NXP OSS) #define PHY_IRQ_LINK_EVENT		BIT(1)
48b2f0ca00SRadu Pirea (NXP OSS) 
49425c8348SRadu Pirea (NXP OSS) #define VEND1_ALWAYS_ACCESSIBLE		0x801F
50425c8348SRadu Pirea (NXP OSS) #define FUSA_PASS			BIT(4)
51425c8348SRadu Pirea (NXP OSS) 
52b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONTROL		0x8100
53b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_EN			BIT(14)
54b050f2f1SRadu Pirea (NXP OSS) #define PHY_START_OP			BIT(0)
55b050f2f1SRadu Pirea (NXP OSS) 
56b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONFIG		0x8108
57b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_AUTO			BIT(0)
58b050f2f1SRadu Pirea (NXP OSS) 
59b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SIGNAL_QUALITY		0x8320
60b050f2f1SRadu Pirea (NXP OSS) #define SQI_VALID			BIT(14)
61b050f2f1SRadu Pirea (NXP OSS) #define SQI_MASK			GENMASK(2, 0)
62b050f2f1SRadu Pirea (NXP OSS) #define MAX_SQI				SQI_MASK
63b050f2f1SRadu Pirea (NXP OSS) 
64b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_ENABLE		BIT(15)
65b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_START		BIT(14)
66b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OK			0x00
67b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_SHORTED		0x01
68b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OPEN			0x02
69b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_UNKNOWN		0x07
70b050f2f1SRadu Pirea (NXP OSS) 
71b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_CONTROL		0x8040
72b050f2f1SRadu Pirea (NXP OSS) #define PORT_CONTROL_EN			BIT(14)
73b050f2f1SRadu Pirea (NXP OSS) 
74514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_ABILITIES		0x8046
75514def5dSRadu Pirea (NXP OSS) #define PTP_ABILITY			BIT(3)
76514def5dSRadu Pirea (NXP OSS) 
77bdb4c5b8SRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_IRQ_EN		0x807A
78bdb4c5b8SRadu Pirea (NXP OSS) #define PTP_IRQS			BIT(3)
79bdb4c5b8SRadu Pirea (NXP OSS) 
80bdb4c5b8SRadu Pirea (NXP OSS) #define VEND1_PTP_IRQ_ACK		0x9008
81bdb4c5b8SRadu Pirea (NXP OSS) #define EGR_TS_IRQ			BIT(1)
82bdb4c5b8SRadu Pirea (NXP OSS) 
83b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_INFRA_CONTROL	0xAC00
84b050f2f1SRadu Pirea (NXP OSS) #define PORT_INFRA_CONTROL_EN		BIT(14)
85b050f2f1SRadu Pirea (NXP OSS) 
86b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RXID			0xAFCC
87b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TXID			0xAFCD
88b050f2f1SRadu Pirea (NXP OSS) #define ID_ENABLE			BIT(15)
89b050f2f1SRadu Pirea (NXP OSS) 
90b050f2f1SRadu Pirea (NXP OSS) #define VEND1_ABILITIES			0xAFC4
91b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ID_ABILITY		BIT(15)
92b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ABILITY			BIT(14)
93b050f2f1SRadu Pirea (NXP OSS) #define RMII_ABILITY			BIT(10)
94b050f2f1SRadu Pirea (NXP OSS) #define REVMII_ABILITY			BIT(9)
95b050f2f1SRadu Pirea (NXP OSS) #define MII_ABILITY			BIT(8)
96b050f2f1SRadu Pirea (NXP OSS) #define SGMII_ABILITY			BIT(0)
97b050f2f1SRadu Pirea (NXP OSS) 
98b050f2f1SRadu Pirea (NXP OSS) #define VEND1_MII_BASIC_CONFIG		0xAFC6
998ba57205SRadu Pirea (OSS) #define MII_BASIC_CONFIG_REV		BIT(4)
100b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_SGMII		0x9
101b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RGMII		0x7
102b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RMII		0x5
103b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_MII		0x4
104b050f2f1SRadu Pirea (NXP OSS) 
105f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_CNT_XTD	0x8351
106f1fe5dffSRadu Pirea (NXP OSS) #define EXTENDED_CNT_EN			BIT(15)
107f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_STATUS		0xAC80
108f1fe5dffSRadu Pirea (NXP OSS) #define MONITOR_RESET			BIT(15)
109f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_CONFIG		0xAC86
110f1fe5dffSRadu Pirea (NXP OSS) #define LOST_FRAMES_CNT_EN		BIT(9)
111f1fe5dffSRadu Pirea (NXP OSS) #define ALL_FRAMES_CNT_EN		BIT(8)
112f1fe5dffSRadu Pirea (NXP OSS) 
113b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_COUNTER	0x8350
114b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_DROP_COUNTER		0x8352
115b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_LOSSES_AND_FAILURES	0x8353
116b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_PREAMBLE_COUNT		0xAFCE
117b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_PREAMBLE_COUNT		0xAFCF
118b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_IPG_LENGTH		0xAFD0
119b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_IPG_LENGTH		0xAFD1
120b050f2f1SRadu Pirea (NXP OSS) #define COUNTER_EN			BIT(15)
121b050f2f1SRadu Pirea (NXP OSS) 
1227a71c8aaSRadu Pirea (NXP OSS) #define VEND1_PTP_CONFIG		0x1102
1237a71c8aaSRadu Pirea (NXP OSS) #define EXT_TRG_EDGE			BIT(1)
1247a71c8aaSRadu Pirea (NXP OSS) 
125b0b2247dSRadu Pirea (NXP OSS) #define TJA1120_SYNC_TRIG_FILTER	0x1010
126b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_RISE_TS		BIT(3)
127b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_FALLING_TS		BIT(2)
128b0b2247dSRadu Pirea (NXP OSS) 
129514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_LD			BIT(15)
130514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_DIR		BIT(14)
131514def5dSRadu Pirea (NXP OSS) 
132514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_TS_INSRT_CTRL		0x114D
1336c0c85daSRadu Pirea (NXP OSS) #define TJA1103_RX_TS_INSRT_MODE2	0x02
134514def5dSRadu Pirea (NXP OSS) 
135f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_CTRL	0x9012
136f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_EN		BIT(15)
137f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_TS_INSRT_MODE		BIT(4)
138f1fe5dffSRadu Pirea (NXP OSS) 
139514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_0		0x114E
140514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_CTRL		0x1154
141514def5dSRadu Pirea (NXP OSS) 
142514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_TS_VALID		BIT(15)
143514def5dSRadu Pirea (NXP OSS) 
144514def5dSRadu Pirea (NXP OSS) #define RING_DONE			BIT(0)
145514def5dSRadu Pirea (NXP OSS) 
146514def5dSRadu Pirea (NXP OSS) #define TS_SEC_MASK			GENMASK(1, 0)
147514def5dSRadu Pirea (NXP OSS) 
148514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_ENABLES		0x8048
149514def5dSRadu Pirea (NXP OSS) #define PTP_ENABLE			BIT(3)
150c552c110SRadu Pirea (NXP OSS) #define PHY_TEST_ENABLE			BIT(0)
151514def5dSRadu Pirea (NXP OSS) 
152514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_PTP_CONTROL		0x9000
153514def5dSRadu Pirea (NXP OSS) #define PORT_PTP_CONTROL_BYPASS		BIT(11)
154514def5dSRadu Pirea (NXP OSS) 
155514def5dSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_100BT1		15ULL
156f1fe5dffSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_1000BT1		8ULL
157514def5dSRadu Pirea (NXP OSS) 
158514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_ALL		0x0F
159514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_NONE		0x00
160514def5dSRadu Pirea (NXP OSS) 
1617a71c8aaSRadu Pirea (NXP OSS) #define VEND1_GPIO_FUNC_CONFIG_BASE	0x2C40
1627a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_EN			BIT(15)
1637a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_PTP			BIT(6)
1647a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PTP_TRIGGER		0x01
1657a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PPS_OUT		0x12
1667a71c8aaSRadu Pirea (NXP OSS) #define GPIO_DISABLE			0
1677a71c8aaSRadu Pirea (NXP OSS) #define GPIO_PPS_OUT_CFG		(GPIO_FUNC_EN | GPIO_FUNC_PTP | \
1687a71c8aaSRadu Pirea (NXP OSS) 	GPIO_SIGNAL_PPS_OUT)
1697a71c8aaSRadu Pirea (NXP OSS) #define GPIO_EXTTS_OUT_CFG		(GPIO_FUNC_EN | GPIO_FUNC_PTP | \
1707a71c8aaSRadu Pirea (NXP OSS) 	GPIO_SIGNAL_PTP_TRIGGER)
1717a71c8aaSRadu Pirea (NXP OSS) 
172b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS			8000U
173b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE			div_u64(RGMII_PERIOD_PS, 360)
174b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS			1644U
175b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS			2260U
176b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS			2000U
177b050f2f1SRadu Pirea (NXP OSS) 
1786c0c85daSRadu Pirea (NXP OSS) #define PPM_TO_SUBNS_INC(ppb, ptp_clk_period) div_u64(GENMASK_ULL(31, 0) * \
1796c0c85daSRadu Pirea (NXP OSS) 	(ppb) * (ptp_clk_period), NSEC_PER_SEC)
180514def5dSRadu Pirea (NXP OSS) 
181514def5dSRadu Pirea (NXP OSS) #define NXP_C45_SKB_CB(skb)	((struct nxp_c45_skb_cb *)(skb)->cb)
182514def5dSRadu Pirea (NXP OSS) 
183bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_phy;
184bdb4c5b8SRadu Pirea (NXP OSS) 
185514def5dSRadu Pirea (NXP OSS) struct nxp_c45_skb_cb {
186514def5dSRadu Pirea (NXP OSS) 	struct ptp_header *header;
187514def5dSRadu Pirea (NXP OSS) 	unsigned int type;
188514def5dSRadu Pirea (NXP OSS) };
189514def5dSRadu Pirea (NXP OSS) 
1906c0c85daSRadu Pirea (NXP OSS) #define NXP_C45_REG_FIELD(_reg, _devad, _offset, _size)	\
1916c0c85daSRadu Pirea (NXP OSS) 	((struct nxp_c45_reg_field) {			\
1926c0c85daSRadu Pirea (NXP OSS) 		.reg = _reg,				\
1936c0c85daSRadu Pirea (NXP OSS) 		.devad =  _devad,			\
1946c0c85daSRadu Pirea (NXP OSS) 		.offset = _offset,			\
1956c0c85daSRadu Pirea (NXP OSS) 		.size = _size,				\
1966c0c85daSRadu Pirea (NXP OSS) 	})
1976c0c85daSRadu Pirea (NXP OSS) 
1986c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field {
1996c0c85daSRadu Pirea (NXP OSS) 	u16 reg;
2006c0c85daSRadu Pirea (NXP OSS) 	u8 devad;
2016c0c85daSRadu Pirea (NXP OSS) 	u8 offset;
2026c0c85daSRadu Pirea (NXP OSS) 	u8 size;
2036c0c85daSRadu Pirea (NXP OSS) };
2046c0c85daSRadu Pirea (NXP OSS) 
205514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts {
206514def5dSRadu Pirea (NXP OSS) 	u32	nsec;
207514def5dSRadu Pirea (NXP OSS) 	u32	sec;
208514def5dSRadu Pirea (NXP OSS) 	u8	domain_number;
209514def5dSRadu Pirea (NXP OSS) 	u16	sequence_id;
210514def5dSRadu Pirea (NXP OSS) 	u8	msg_type;
211514def5dSRadu Pirea (NXP OSS) };
212514def5dSRadu Pirea (NXP OSS) 
2136c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap {
2146c0c85daSRadu Pirea (NXP OSS) 	/* PTP config regs. */
2156c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ptp_clk_period;
2166c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_event_msg_filt;
2176c0c85daSRadu Pirea (NXP OSS) 
2186c0c85daSRadu Pirea (NXP OSS) 	/* LTC bits and regs. */
2196c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field ltc_read;
2206c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field ltc_write;
2216c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field ltc_lock_ctrl;
2226c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ltc_wr_nsec_0;
2236c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ltc_wr_nsec_1;
2246c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ltc_wr_sec_0;
2256c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ltc_wr_sec_1;
2266c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ltc_rd_nsec_0;
2276c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ltc_rd_nsec_1;
2286c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ltc_rd_sec_0;
2296c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ltc_rd_sec_1;
2306c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_rate_adj_subns_0;
2316c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_rate_adj_subns_1;
2326c0c85daSRadu Pirea (NXP OSS) 
2336c0c85daSRadu Pirea (NXP OSS) 	/* External trigger reg fields. */
2346c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field irq_egr_ts_en;
2356c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field irq_egr_ts_status;
2366c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field domain_number;
2376c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field msg_type;
2386c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field sequence_id;
2396c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field sec_1_0;
2406c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field sec_4_2;
2416c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field nsec_15_0;
2426c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field nsec_29_16;
2436c0c85daSRadu Pirea (NXP OSS) 
2446c0c85daSRadu Pirea (NXP OSS) 	/* PPS and EXT Trigger bits and regs. */
2456c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field pps_enable;
2466c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field pps_polarity;
2476c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ext_trg_data_0;
2486c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ext_trg_data_1;
2496c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ext_trg_data_2;
2506c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ext_trg_data_3;
2516c0c85daSRadu Pirea (NXP OSS) 	u16 vend1_ext_trg_ctrl;
2526c0c85daSRadu Pirea (NXP OSS) 
2536c0c85daSRadu Pirea (NXP OSS) 	/* Cable test reg fields. */
2546c0c85daSRadu Pirea (NXP OSS) 	u16 cable_test;
2556c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field cable_test_valid;
2566c0c85daSRadu Pirea (NXP OSS) 	struct nxp_c45_reg_field cable_test_result;
2576c0c85daSRadu Pirea (NXP OSS) };
2586c0c85daSRadu Pirea (NXP OSS) 
2596c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_stats {
2606c0c85daSRadu Pirea (NXP OSS) 	const char	*name;
2616c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_reg_field counter;
2626c0c85daSRadu Pirea (NXP OSS) };
2636c0c85daSRadu Pirea (NXP OSS) 
2646c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data {
2656c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap;
2666c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_stats *stats;
2676c0c85daSRadu Pirea (NXP OSS) 	int n_stats;
2686c0c85daSRadu Pirea (NXP OSS) 	u8 ptp_clk_period;
269b0b2247dSRadu Pirea (NXP OSS) 	bool ext_ts_both_edges;
270bdb4c5b8SRadu Pirea (NXP OSS) 	bool ack_ptp_irq;
2716c0c85daSRadu Pirea (NXP OSS) 	void (*counters_enable)(struct phy_device *phydev);
272bdb4c5b8SRadu Pirea (NXP OSS) 	bool (*get_egressts)(struct nxp_c45_phy *priv,
273bdb4c5b8SRadu Pirea (NXP OSS) 			     struct nxp_c45_hwts *hwts);
274*08e6547cSRadu Pirea (NXP OSS) 	bool (*get_extts)(struct nxp_c45_phy *priv, struct timespec64 *extts);
2756c0c85daSRadu Pirea (NXP OSS) 	void (*ptp_init)(struct phy_device *phydev);
2766c0c85daSRadu Pirea (NXP OSS) 	void (*ptp_enable)(struct phy_device *phydev, bool enable);
277425c8348SRadu Pirea (NXP OSS) 	void (*nmi_handler)(struct phy_device *phydev,
278425c8348SRadu Pirea (NXP OSS) 			    irqreturn_t *irq_status);
2796c0c85daSRadu Pirea (NXP OSS) };
2806c0c85daSRadu Pirea (NXP OSS) 
281b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy {
2826c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *phy_data;
283514def5dSRadu Pirea (NXP OSS) 	struct phy_device *phydev;
284514def5dSRadu Pirea (NXP OSS) 	struct mii_timestamper mii_ts;
285514def5dSRadu Pirea (NXP OSS) 	struct ptp_clock *ptp_clock;
286514def5dSRadu Pirea (NXP OSS) 	struct ptp_clock_info caps;
287514def5dSRadu Pirea (NXP OSS) 	struct sk_buff_head tx_queue;
288514def5dSRadu Pirea (NXP OSS) 	struct sk_buff_head rx_queue;
289514def5dSRadu Pirea (NXP OSS) 	/* used to access the PTP registers atomic */
290514def5dSRadu Pirea (NXP OSS) 	struct mutex ptp_lock;
291514def5dSRadu Pirea (NXP OSS) 	int hwts_tx;
292514def5dSRadu Pirea (NXP OSS) 	int hwts_rx;
293b050f2f1SRadu Pirea (NXP OSS) 	u32 tx_delay;
294b050f2f1SRadu Pirea (NXP OSS) 	u32 rx_delay;
2957a71c8aaSRadu Pirea (NXP OSS) 	struct timespec64 extts_ts;
2967a71c8aaSRadu Pirea (NXP OSS) 	int extts_index;
2977a71c8aaSRadu Pirea (NXP OSS) 	bool extts;
298b050f2f1SRadu Pirea (NXP OSS) };
299b050f2f1SRadu Pirea (NXP OSS) 
3006c0c85daSRadu Pirea (NXP OSS) static const
3016c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data *nxp_c45_get_data(struct phy_device *phydev)
3026c0c85daSRadu Pirea (NXP OSS) {
3036c0c85daSRadu Pirea (NXP OSS) 	return phydev->drv->driver_data;
3046c0c85daSRadu Pirea (NXP OSS) }
3056c0c85daSRadu Pirea (NXP OSS) 
3066c0c85daSRadu Pirea (NXP OSS) static const
3076c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap *nxp_c45_get_regmap(struct phy_device *phydev)
3086c0c85daSRadu Pirea (NXP OSS) {
3096c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev);
3106c0c85daSRadu Pirea (NXP OSS) 
3116c0c85daSRadu Pirea (NXP OSS) 	return phy_data->regmap;
3126c0c85daSRadu Pirea (NXP OSS) }
3136c0c85daSRadu Pirea (NXP OSS) 
3146c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_read_reg_field(struct phy_device *phydev,
3156c0c85daSRadu Pirea (NXP OSS) 				  const struct nxp_c45_reg_field *reg_field)
3166c0c85daSRadu Pirea (NXP OSS) {
317b050f2f1SRadu Pirea (NXP OSS) 	u16 mask;
3186c0c85daSRadu Pirea (NXP OSS) 	int ret;
3196c0c85daSRadu Pirea (NXP OSS) 
3206c0c85daSRadu Pirea (NXP OSS) 	if (reg_field->size == 0) {
3216c0c85daSRadu Pirea (NXP OSS) 		phydev_err(phydev, "Trying to read a reg field of size 0.\n");
3226c0c85daSRadu Pirea (NXP OSS) 		return -EINVAL;
3236c0c85daSRadu Pirea (NXP OSS) 	}
3246c0c85daSRadu Pirea (NXP OSS) 
3256c0c85daSRadu Pirea (NXP OSS) 	ret = phy_read_mmd(phydev, reg_field->devad, reg_field->reg);
3266c0c85daSRadu Pirea (NXP OSS) 	if (ret < 0)
3276c0c85daSRadu Pirea (NXP OSS) 		return ret;
3286c0c85daSRadu Pirea (NXP OSS) 
3296c0c85daSRadu Pirea (NXP OSS) 	mask = reg_field->size == 1 ? BIT(reg_field->offset) :
3306c0c85daSRadu Pirea (NXP OSS) 		GENMASK(reg_field->offset + reg_field->size - 1,
3316c0c85daSRadu Pirea (NXP OSS) 			reg_field->offset);
3326c0c85daSRadu Pirea (NXP OSS) 	ret &= mask;
3336c0c85daSRadu Pirea (NXP OSS) 	ret >>= reg_field->offset;
3346c0c85daSRadu Pirea (NXP OSS) 
3356c0c85daSRadu Pirea (NXP OSS) 	return ret;
3366c0c85daSRadu Pirea (NXP OSS) }
3376c0c85daSRadu Pirea (NXP OSS) 
3386c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_write_reg_field(struct phy_device *phydev,
3396c0c85daSRadu Pirea (NXP OSS) 				   const struct nxp_c45_reg_field *reg_field,
3406c0c85daSRadu Pirea (NXP OSS) 				   u16 val)
3416c0c85daSRadu Pirea (NXP OSS) {
3426c0c85daSRadu Pirea (NXP OSS) 	u16 mask;
3436c0c85daSRadu Pirea (NXP OSS) 	u16 set;
3446c0c85daSRadu Pirea (NXP OSS) 
3456c0c85daSRadu Pirea (NXP OSS) 	if (reg_field->size == 0) {
3466c0c85daSRadu Pirea (NXP OSS) 		phydev_err(phydev, "Trying to write a reg field of size 0.\n");
3476c0c85daSRadu Pirea (NXP OSS) 		return -EINVAL;
3486c0c85daSRadu Pirea (NXP OSS) 	}
3496c0c85daSRadu Pirea (NXP OSS) 
3506c0c85daSRadu Pirea (NXP OSS) 	mask = reg_field->size == 1 ? BIT(reg_field->offset) :
3516c0c85daSRadu Pirea (NXP OSS) 		GENMASK(reg_field->offset + reg_field->size - 1,
3526c0c85daSRadu Pirea (NXP OSS) 			reg_field->offset);
3536c0c85daSRadu Pirea (NXP OSS) 	set = val << reg_field->offset;
3546c0c85daSRadu Pirea (NXP OSS) 
3556c0c85daSRadu Pirea (NXP OSS) 	return phy_modify_mmd_changed(phydev, reg_field->devad,
3566c0c85daSRadu Pirea (NXP OSS) 				      reg_field->reg, mask, set);
3576c0c85daSRadu Pirea (NXP OSS) }
3586c0c85daSRadu Pirea (NXP OSS) 
3596c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_set_reg_field(struct phy_device *phydev,
3606c0c85daSRadu Pirea (NXP OSS) 				 const struct nxp_c45_reg_field *reg_field)
3616c0c85daSRadu Pirea (NXP OSS) {
3626c0c85daSRadu Pirea (NXP OSS) 	if (reg_field->size != 1) {
3636c0c85daSRadu Pirea (NXP OSS) 		phydev_err(phydev, "Trying to set a reg field of size different than 1.\n");
3646c0c85daSRadu Pirea (NXP OSS) 		return -EINVAL;
3656c0c85daSRadu Pirea (NXP OSS) 	}
3666c0c85daSRadu Pirea (NXP OSS) 
3676c0c85daSRadu Pirea (NXP OSS) 	return nxp_c45_write_reg_field(phydev, reg_field, 1);
3686c0c85daSRadu Pirea (NXP OSS) }
3696c0c85daSRadu Pirea (NXP OSS) 
3706c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_clear_reg_field(struct phy_device *phydev,
3716c0c85daSRadu Pirea (NXP OSS) 				   const struct nxp_c45_reg_field *reg_field)
3726c0c85daSRadu Pirea (NXP OSS) {
3736c0c85daSRadu Pirea (NXP OSS) 	if (reg_field->size != 1) {
3746c0c85daSRadu Pirea (NXP OSS) 		phydev_err(phydev, "Trying to set a reg field of size different than 1.\n");
3756c0c85daSRadu Pirea (NXP OSS) 		return -EINVAL;
3766c0c85daSRadu Pirea (NXP OSS) 	}
3776c0c85daSRadu Pirea (NXP OSS) 
3786c0c85daSRadu Pirea (NXP OSS) 	return nxp_c45_write_reg_field(phydev, reg_field, 0);
3796c0c85daSRadu Pirea (NXP OSS) }
380b050f2f1SRadu Pirea (NXP OSS) 
381514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_poll_txts(struct phy_device *phydev)
382514def5dSRadu Pirea (NXP OSS) {
383514def5dSRadu Pirea (NXP OSS) 	return phydev->irq <= 0;
384514def5dSRadu Pirea (NXP OSS) }
385514def5dSRadu Pirea (NXP OSS) 
386514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp,
387514def5dSRadu Pirea (NXP OSS) 				   struct timespec64 *ts,
388514def5dSRadu Pirea (NXP OSS) 				   struct ptp_system_timestamp *sts)
389514def5dSRadu Pirea (NXP OSS) {
390514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
3916c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
392514def5dSRadu Pirea (NXP OSS) 
3936c0c85daSRadu Pirea (NXP OSS) 	nxp_c45_set_reg_field(priv->phydev, &regmap->ltc_read);
394514def5dSRadu Pirea (NXP OSS) 	ts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
3956c0c85daSRadu Pirea (NXP OSS) 				   regmap->vend1_ltc_rd_nsec_0);
396514def5dSRadu Pirea (NXP OSS) 	ts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
3976c0c85daSRadu Pirea (NXP OSS) 				    regmap->vend1_ltc_rd_nsec_1) << 16;
398514def5dSRadu Pirea (NXP OSS) 	ts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
3996c0c85daSRadu Pirea (NXP OSS) 				  regmap->vend1_ltc_rd_sec_0);
400514def5dSRadu Pirea (NXP OSS) 	ts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
4016c0c85daSRadu Pirea (NXP OSS) 				   regmap->vend1_ltc_rd_sec_1) << 16;
402514def5dSRadu Pirea (NXP OSS) 
403514def5dSRadu Pirea (NXP OSS) 	return 0;
404514def5dSRadu Pirea (NXP OSS) }
405514def5dSRadu Pirea (NXP OSS) 
406514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp,
407514def5dSRadu Pirea (NXP OSS) 				  struct timespec64 *ts,
408514def5dSRadu Pirea (NXP OSS) 				  struct ptp_system_timestamp *sts)
409514def5dSRadu Pirea (NXP OSS) {
410514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
411514def5dSRadu Pirea (NXP OSS) 
412514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
413514def5dSRadu Pirea (NXP OSS) 	_nxp_c45_ptp_gettimex64(ptp, ts, sts);
414514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
415514def5dSRadu Pirea (NXP OSS) 
416514def5dSRadu Pirea (NXP OSS) 	return 0;
417514def5dSRadu Pirea (NXP OSS) }
418514def5dSRadu Pirea (NXP OSS) 
419514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_settime64(struct ptp_clock_info *ptp,
420514def5dSRadu Pirea (NXP OSS) 				  const struct timespec64 *ts)
421514def5dSRadu Pirea (NXP OSS) {
422514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
4236c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
424514def5dSRadu Pirea (NXP OSS) 
4256c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_0,
426514def5dSRadu Pirea (NXP OSS) 		      ts->tv_nsec);
4276c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_1,
428514def5dSRadu Pirea (NXP OSS) 		      ts->tv_nsec >> 16);
4296c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_0,
430514def5dSRadu Pirea (NXP OSS) 		      ts->tv_sec);
4316c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_1,
432514def5dSRadu Pirea (NXP OSS) 		      ts->tv_sec >> 16);
4336c0c85daSRadu Pirea (NXP OSS) 	nxp_c45_set_reg_field(priv->phydev, &regmap->ltc_write);
434514def5dSRadu Pirea (NXP OSS) 
435514def5dSRadu Pirea (NXP OSS) 	return 0;
436514def5dSRadu Pirea (NXP OSS) }
437514def5dSRadu Pirea (NXP OSS) 
438514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_settime64(struct ptp_clock_info *ptp,
439514def5dSRadu Pirea (NXP OSS) 				 const struct timespec64 *ts)
440514def5dSRadu Pirea (NXP OSS) {
441514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
442514def5dSRadu Pirea (NXP OSS) 
443514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
444514def5dSRadu Pirea (NXP OSS) 	_nxp_c45_ptp_settime64(ptp, ts);
445514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
446514def5dSRadu Pirea (NXP OSS) 
447514def5dSRadu Pirea (NXP OSS) 	return 0;
448514def5dSRadu Pirea (NXP OSS) }
449514def5dSRadu Pirea (NXP OSS) 
450514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
451514def5dSRadu Pirea (NXP OSS) {
452514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
4536c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev);
4546c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = data->regmap;
455514def5dSRadu Pirea (NXP OSS) 	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
456514def5dSRadu Pirea (NXP OSS) 	u64 subns_inc_val;
457514def5dSRadu Pirea (NXP OSS) 	bool inc;
458514def5dSRadu Pirea (NXP OSS) 
459514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
460514def5dSRadu Pirea (NXP OSS) 	inc = ppb >= 0;
461514def5dSRadu Pirea (NXP OSS) 	ppb = abs(ppb);
462514def5dSRadu Pirea (NXP OSS) 
4636c0c85daSRadu Pirea (NXP OSS) 	subns_inc_val = PPM_TO_SUBNS_INC(ppb, data->ptp_clk_period);
464514def5dSRadu Pirea (NXP OSS) 
4656c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1,
4666c0c85daSRadu Pirea (NXP OSS) 		      regmap->vend1_rate_adj_subns_0,
467514def5dSRadu Pirea (NXP OSS) 		      subns_inc_val);
468514def5dSRadu Pirea (NXP OSS) 	subns_inc_val >>= 16;
469514def5dSRadu Pirea (NXP OSS) 	subns_inc_val |= CLK_RATE_ADJ_LD;
470514def5dSRadu Pirea (NXP OSS) 	if (inc)
471514def5dSRadu Pirea (NXP OSS) 		subns_inc_val |= CLK_RATE_ADJ_DIR;
472514def5dSRadu Pirea (NXP OSS) 
4736c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1,
4746c0c85daSRadu Pirea (NXP OSS) 		      regmap->vend1_rate_adj_subns_1,
475514def5dSRadu Pirea (NXP OSS) 		      subns_inc_val);
476514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
477514def5dSRadu Pirea (NXP OSS) 
478514def5dSRadu Pirea (NXP OSS) 	return 0;
479514def5dSRadu Pirea (NXP OSS) }
480514def5dSRadu Pirea (NXP OSS) 
481514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
482514def5dSRadu Pirea (NXP OSS) {
483514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
484514def5dSRadu Pirea (NXP OSS) 	struct timespec64 now, then;
485514def5dSRadu Pirea (NXP OSS) 
486514def5dSRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
487514def5dSRadu Pirea (NXP OSS) 	then = ns_to_timespec64(delta);
488514def5dSRadu Pirea (NXP OSS) 	_nxp_c45_ptp_gettimex64(ptp, &now, NULL);
489514def5dSRadu Pirea (NXP OSS) 	now = timespec64_add(now, then);
490514def5dSRadu Pirea (NXP OSS) 	_nxp_c45_ptp_settime64(ptp, &now);
491514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
492514def5dSRadu Pirea (NXP OSS) 
493514def5dSRadu Pirea (NXP OSS) 	return 0;
494514def5dSRadu Pirea (NXP OSS) }
495514def5dSRadu Pirea (NXP OSS) 
496514def5dSRadu Pirea (NXP OSS) static void nxp_c45_reconstruct_ts(struct timespec64 *ts,
497514def5dSRadu Pirea (NXP OSS) 				   struct nxp_c45_hwts *hwts)
498514def5dSRadu Pirea (NXP OSS) {
499514def5dSRadu Pirea (NXP OSS) 	ts->tv_nsec = hwts->nsec;
500514def5dSRadu Pirea (NXP OSS) 	if ((ts->tv_sec & TS_SEC_MASK) < (hwts->sec & TS_SEC_MASK))
501661fef56SVladimir Oltean 		ts->tv_sec -= TS_SEC_MASK + 1;
502514def5dSRadu Pirea (NXP OSS) 	ts->tv_sec &= ~TS_SEC_MASK;
503514def5dSRadu Pirea (NXP OSS) 	ts->tv_sec |= hwts->sec & TS_SEC_MASK;
504514def5dSRadu Pirea (NXP OSS) }
505514def5dSRadu Pirea (NXP OSS) 
506514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_match_ts(struct ptp_header *header,
507514def5dSRadu Pirea (NXP OSS) 			     struct nxp_c45_hwts *hwts,
508514def5dSRadu Pirea (NXP OSS) 			     unsigned int type)
509514def5dSRadu Pirea (NXP OSS) {
510514def5dSRadu Pirea (NXP OSS) 	return ntohs(header->sequence_id) == hwts->sequence_id &&
511514def5dSRadu Pirea (NXP OSS) 	       ptp_get_msgtype(header, type) == hwts->msg_type &&
512514def5dSRadu Pirea (NXP OSS) 	       header->domain_number  == hwts->domain_number;
513514def5dSRadu Pirea (NXP OSS) }
514514def5dSRadu Pirea (NXP OSS) 
515*08e6547cSRadu Pirea (NXP OSS) static bool nxp_c45_get_extts(struct nxp_c45_phy *priv,
5167a71c8aaSRadu Pirea (NXP OSS) 			      struct timespec64 *extts)
5177a71c8aaSRadu Pirea (NXP OSS) {
5186c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
5196c0c85daSRadu Pirea (NXP OSS) 
5207a71c8aaSRadu Pirea (NXP OSS) 	extts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
5216c0c85daSRadu Pirea (NXP OSS) 				      regmap->vend1_ext_trg_data_0);
5227a71c8aaSRadu Pirea (NXP OSS) 	extts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
5236c0c85daSRadu Pirea (NXP OSS) 				       regmap->vend1_ext_trg_data_1) << 16;
5247a71c8aaSRadu Pirea (NXP OSS) 	extts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
5256c0c85daSRadu Pirea (NXP OSS) 				     regmap->vend1_ext_trg_data_2);
5267a71c8aaSRadu Pirea (NXP OSS) 	extts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
5276c0c85daSRadu Pirea (NXP OSS) 				      regmap->vend1_ext_trg_data_3) << 16;
5286c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1,
5296c0c85daSRadu Pirea (NXP OSS) 		      regmap->vend1_ext_trg_ctrl, RING_DONE);
530*08e6547cSRadu Pirea (NXP OSS) 
531*08e6547cSRadu Pirea (NXP OSS) 	return true;
532*08e6547cSRadu Pirea (NXP OSS) }
533*08e6547cSRadu Pirea (NXP OSS) 
534*08e6547cSRadu Pirea (NXP OSS) static bool tja1120_extts_is_valid(struct phy_device *phydev)
535*08e6547cSRadu Pirea (NXP OSS) {
536*08e6547cSRadu Pirea (NXP OSS) 	bool valid;
537*08e6547cSRadu Pirea (NXP OSS) 	int reg;
538*08e6547cSRadu Pirea (NXP OSS) 
539*08e6547cSRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_VEND1,
540*08e6547cSRadu Pirea (NXP OSS) 			   TJA1120_VEND1_PTP_TRIG_DATA_S);
541*08e6547cSRadu Pirea (NXP OSS) 	valid = !!(reg & TJA1120_TS_VALID);
542*08e6547cSRadu Pirea (NXP OSS) 
543*08e6547cSRadu Pirea (NXP OSS) 	return valid;
544*08e6547cSRadu Pirea (NXP OSS) }
545*08e6547cSRadu Pirea (NXP OSS) 
546*08e6547cSRadu Pirea (NXP OSS) static bool tja1120_get_extts(struct nxp_c45_phy *priv,
547*08e6547cSRadu Pirea (NXP OSS) 			      struct timespec64 *extts)
548*08e6547cSRadu Pirea (NXP OSS) {
549*08e6547cSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
550*08e6547cSRadu Pirea (NXP OSS) 	struct phy_device *phydev = priv->phydev;
551*08e6547cSRadu Pirea (NXP OSS) 	bool more_ts;
552*08e6547cSRadu Pirea (NXP OSS) 	bool valid;
553*08e6547cSRadu Pirea (NXP OSS) 	u16 reg;
554*08e6547cSRadu Pirea (NXP OSS) 
555*08e6547cSRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_VEND1,
556*08e6547cSRadu Pirea (NXP OSS) 			   regmap->vend1_ext_trg_ctrl);
557*08e6547cSRadu Pirea (NXP OSS) 	more_ts = !!(reg & TJA1120_MORE_TS);
558*08e6547cSRadu Pirea (NXP OSS) 
559*08e6547cSRadu Pirea (NXP OSS) 	valid = tja1120_extts_is_valid(phydev);
560*08e6547cSRadu Pirea (NXP OSS) 	if (!valid) {
561*08e6547cSRadu Pirea (NXP OSS) 		if (!more_ts)
562*08e6547cSRadu Pirea (NXP OSS) 			goto tja1120_get_extts_out;
563*08e6547cSRadu Pirea (NXP OSS) 
564*08e6547cSRadu Pirea (NXP OSS) 		/* Bug workaround for TJA1120 engineering samples: move the new
565*08e6547cSRadu Pirea (NXP OSS) 		 * timestamp from the FIFO to the buffer.
566*08e6547cSRadu Pirea (NXP OSS) 		 */
567*08e6547cSRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1,
568*08e6547cSRadu Pirea (NXP OSS) 			      regmap->vend1_ext_trg_ctrl, RING_DONE);
569*08e6547cSRadu Pirea (NXP OSS) 		valid = tja1120_extts_is_valid(phydev);
570*08e6547cSRadu Pirea (NXP OSS) 		if (!valid)
571*08e6547cSRadu Pirea (NXP OSS) 			goto tja1120_get_extts_out;
572*08e6547cSRadu Pirea (NXP OSS) 	}
573*08e6547cSRadu Pirea (NXP OSS) 
574*08e6547cSRadu Pirea (NXP OSS) 	nxp_c45_get_extts(priv, extts);
575*08e6547cSRadu Pirea (NXP OSS) tja1120_get_extts_out:
576*08e6547cSRadu Pirea (NXP OSS) 	return valid;
5777a71c8aaSRadu Pirea (NXP OSS) }
5787a71c8aaSRadu Pirea (NXP OSS) 
579bdb4c5b8SRadu Pirea (NXP OSS) static void nxp_c45_read_egress_ts(struct nxp_c45_phy *priv,
580514def5dSRadu Pirea (NXP OSS) 				   struct nxp_c45_hwts *hwts)
581514def5dSRadu Pirea (NXP OSS) {
5826c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
5836c0c85daSRadu Pirea (NXP OSS) 	struct phy_device *phydev = priv->phydev;
584514def5dSRadu Pirea (NXP OSS) 
5856c0c85daSRadu Pirea (NXP OSS) 	hwts->domain_number =
5866c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_read_reg_field(phydev, &regmap->domain_number);
5876c0c85daSRadu Pirea (NXP OSS) 	hwts->msg_type =
5886c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_read_reg_field(phydev, &regmap->msg_type);
5896c0c85daSRadu Pirea (NXP OSS) 	hwts->sequence_id =
5906c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_read_reg_field(phydev, &regmap->sequence_id);
5916c0c85daSRadu Pirea (NXP OSS) 	hwts->nsec =
5926c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_read_reg_field(phydev, &regmap->nsec_15_0);
5936c0c85daSRadu Pirea (NXP OSS) 	hwts->nsec |=
5946c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_read_reg_field(phydev, &regmap->nsec_29_16) << 16;
5956c0c85daSRadu Pirea (NXP OSS) 	hwts->sec = nxp_c45_read_reg_field(phydev, &regmap->sec_1_0);
5966c0c85daSRadu Pirea (NXP OSS) 	hwts->sec |= nxp_c45_read_reg_field(phydev, &regmap->sec_4_2) << 2;
597bdb4c5b8SRadu Pirea (NXP OSS) }
598514def5dSRadu Pirea (NXP OSS) 
599bdb4c5b8SRadu Pirea (NXP OSS) static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv,
600bdb4c5b8SRadu Pirea (NXP OSS) 			       struct nxp_c45_hwts *hwts)
601bdb4c5b8SRadu Pirea (NXP OSS) {
602bdb4c5b8SRadu Pirea (NXP OSS) 	bool valid;
603bdb4c5b8SRadu Pirea (NXP OSS) 	u16 reg;
604bdb4c5b8SRadu Pirea (NXP OSS) 
605bdb4c5b8SRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
606bdb4c5b8SRadu Pirea (NXP OSS) 	phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL,
607bdb4c5b8SRadu Pirea (NXP OSS) 		      RING_DONE);
608bdb4c5b8SRadu Pirea (NXP OSS) 	reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0);
609bdb4c5b8SRadu Pirea (NXP OSS) 	valid = !!(reg & RING_DATA_0_TS_VALID);
610bdb4c5b8SRadu Pirea (NXP OSS) 	if (!valid)
611bdb4c5b8SRadu Pirea (NXP OSS) 		goto nxp_c45_get_hwtxts_out;
612bdb4c5b8SRadu Pirea (NXP OSS) 
613bdb4c5b8SRadu Pirea (NXP OSS) 	nxp_c45_read_egress_ts(priv, hwts);
614514def5dSRadu Pirea (NXP OSS) nxp_c45_get_hwtxts_out:
615514def5dSRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
616514def5dSRadu Pirea (NXP OSS) 	return valid;
617514def5dSRadu Pirea (NXP OSS) }
618514def5dSRadu Pirea (NXP OSS) 
619bdb4c5b8SRadu Pirea (NXP OSS) static bool tja1120_egress_ts_is_valid(struct phy_device *phydev)
620bdb4c5b8SRadu Pirea (NXP OSS) {
621bdb4c5b8SRadu Pirea (NXP OSS) 	bool valid;
622bdb4c5b8SRadu Pirea (NXP OSS) 	u16 reg;
623bdb4c5b8SRadu Pirea (NXP OSS) 
624bdb4c5b8SRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S);
625bdb4c5b8SRadu Pirea (NXP OSS) 	valid = !!(reg & TJA1120_TS_VALID);
626bdb4c5b8SRadu Pirea (NXP OSS) 
627bdb4c5b8SRadu Pirea (NXP OSS) 	return valid;
628bdb4c5b8SRadu Pirea (NXP OSS) }
629bdb4c5b8SRadu Pirea (NXP OSS) 
630bdb4c5b8SRadu Pirea (NXP OSS) static bool tja1120_get_hwtxts(struct nxp_c45_phy *priv,
631bdb4c5b8SRadu Pirea (NXP OSS) 			       struct nxp_c45_hwts *hwts)
632bdb4c5b8SRadu Pirea (NXP OSS) {
633bdb4c5b8SRadu Pirea (NXP OSS) 	struct phy_device *phydev = priv->phydev;
634bdb4c5b8SRadu Pirea (NXP OSS) 	bool more_ts;
635bdb4c5b8SRadu Pirea (NXP OSS) 	bool valid;
636bdb4c5b8SRadu Pirea (NXP OSS) 	u16 reg;
637bdb4c5b8SRadu Pirea (NXP OSS) 
638bdb4c5b8SRadu Pirea (NXP OSS) 	mutex_lock(&priv->ptp_lock);
639bdb4c5b8SRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_END);
640bdb4c5b8SRadu Pirea (NXP OSS) 	more_ts = !!(reg & TJA1120_MORE_TS);
641bdb4c5b8SRadu Pirea (NXP OSS) 	valid = tja1120_egress_ts_is_valid(phydev);
642bdb4c5b8SRadu Pirea (NXP OSS) 	if (!valid) {
643bdb4c5b8SRadu Pirea (NXP OSS) 		if (!more_ts)
644bdb4c5b8SRadu Pirea (NXP OSS) 			goto tja1120_get_hwtxts_out;
645bdb4c5b8SRadu Pirea (NXP OSS) 
646bdb4c5b8SRadu Pirea (NXP OSS) 		/* Bug workaround for TJA1120 engineering samples: move the
647bdb4c5b8SRadu Pirea (NXP OSS) 		 * new timestamp from the FIFO to the buffer.
648bdb4c5b8SRadu Pirea (NXP OSS) 		 */
649bdb4c5b8SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1,
650bdb4c5b8SRadu Pirea (NXP OSS) 			      TJA1120_EGRESS_TS_END, TJA1120_TS_VALID);
651bdb4c5b8SRadu Pirea (NXP OSS) 		valid = tja1120_egress_ts_is_valid(phydev);
652bdb4c5b8SRadu Pirea (NXP OSS) 		if (!valid)
653bdb4c5b8SRadu Pirea (NXP OSS) 			goto tja1120_get_hwtxts_out;
654bdb4c5b8SRadu Pirea (NXP OSS) 	}
655bdb4c5b8SRadu Pirea (NXP OSS) 	nxp_c45_read_egress_ts(priv, hwts);
656bdb4c5b8SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S,
657bdb4c5b8SRadu Pirea (NXP OSS) 			   TJA1120_TS_VALID);
658bdb4c5b8SRadu Pirea (NXP OSS) tja1120_get_hwtxts_out:
659bdb4c5b8SRadu Pirea (NXP OSS) 	mutex_unlock(&priv->ptp_lock);
660bdb4c5b8SRadu Pirea (NXP OSS) 	return valid;
661bdb4c5b8SRadu Pirea (NXP OSS) }
662bdb4c5b8SRadu Pirea (NXP OSS) 
663514def5dSRadu Pirea (NXP OSS) static void nxp_c45_process_txts(struct nxp_c45_phy *priv,
664514def5dSRadu Pirea (NXP OSS) 				 struct nxp_c45_hwts *txts)
665514def5dSRadu Pirea (NXP OSS) {
666514def5dSRadu Pirea (NXP OSS) 	struct sk_buff *skb, *tmp, *skb_match = NULL;
667514def5dSRadu Pirea (NXP OSS) 	struct skb_shared_hwtstamps shhwtstamps;
668514def5dSRadu Pirea (NXP OSS) 	struct timespec64 ts;
669514def5dSRadu Pirea (NXP OSS) 	unsigned long flags;
670514def5dSRadu Pirea (NXP OSS) 	bool ts_match;
671514def5dSRadu Pirea (NXP OSS) 	s64 ts_ns;
672514def5dSRadu Pirea (NXP OSS) 
673514def5dSRadu Pirea (NXP OSS) 	spin_lock_irqsave(&priv->tx_queue.lock, flags);
674514def5dSRadu Pirea (NXP OSS) 	skb_queue_walk_safe(&priv->tx_queue, skb, tmp) {
675514def5dSRadu Pirea (NXP OSS) 		ts_match = nxp_c45_match_ts(NXP_C45_SKB_CB(skb)->header, txts,
676514def5dSRadu Pirea (NXP OSS) 					    NXP_C45_SKB_CB(skb)->type);
677514def5dSRadu Pirea (NXP OSS) 		if (!ts_match)
678514def5dSRadu Pirea (NXP OSS) 			continue;
679514def5dSRadu Pirea (NXP OSS) 		skb_match = skb;
680514def5dSRadu Pirea (NXP OSS) 		__skb_unlink(skb, &priv->tx_queue);
681514def5dSRadu Pirea (NXP OSS) 		break;
682514def5dSRadu Pirea (NXP OSS) 	}
683514def5dSRadu Pirea (NXP OSS) 	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
684514def5dSRadu Pirea (NXP OSS) 
685514def5dSRadu Pirea (NXP OSS) 	if (skb_match) {
686514def5dSRadu Pirea (NXP OSS) 		nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL);
687514def5dSRadu Pirea (NXP OSS) 		nxp_c45_reconstruct_ts(&ts, txts);
688514def5dSRadu Pirea (NXP OSS) 		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
689514def5dSRadu Pirea (NXP OSS) 		ts_ns = timespec64_to_ns(&ts);
690514def5dSRadu Pirea (NXP OSS) 		shhwtstamps.hwtstamp = ns_to_ktime(ts_ns);
691514def5dSRadu Pirea (NXP OSS) 		skb_complete_tx_timestamp(skb_match, &shhwtstamps);
692514def5dSRadu Pirea (NXP OSS) 	} else {
693514def5dSRadu Pirea (NXP OSS) 		phydev_warn(priv->phydev,
694514def5dSRadu Pirea (NXP OSS) 			    "the tx timestamp doesn't match with any skb\n");
695514def5dSRadu Pirea (NXP OSS) 	}
696514def5dSRadu Pirea (NXP OSS) }
697514def5dSRadu Pirea (NXP OSS) 
698514def5dSRadu Pirea (NXP OSS) static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp)
699514def5dSRadu Pirea (NXP OSS) {
700514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
701bdb4c5b8SRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev);
702514def5dSRadu Pirea (NXP OSS) 	bool poll_txts = nxp_c45_poll_txts(priv->phydev);
703514def5dSRadu Pirea (NXP OSS) 	struct skb_shared_hwtstamps *shhwtstamps_rx;
7047a71c8aaSRadu Pirea (NXP OSS) 	struct ptp_clock_event event;
705514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_hwts hwts;
706514def5dSRadu Pirea (NXP OSS) 	bool reschedule = false;
707514def5dSRadu Pirea (NXP OSS) 	struct timespec64 ts;
708514def5dSRadu Pirea (NXP OSS) 	struct sk_buff *skb;
709*08e6547cSRadu Pirea (NXP OSS) 	bool ts_valid;
710514def5dSRadu Pirea (NXP OSS) 	u32 ts_raw;
711514def5dSRadu Pirea (NXP OSS) 
712514def5dSRadu Pirea (NXP OSS) 	while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) {
713*08e6547cSRadu Pirea (NXP OSS) 		ts_valid = data->get_egressts(priv, &hwts);
714*08e6547cSRadu Pirea (NXP OSS) 		if (unlikely(!ts_valid)) {
715514def5dSRadu Pirea (NXP OSS) 			/* Still more skbs in the queue */
716514def5dSRadu Pirea (NXP OSS) 			reschedule = true;
717514def5dSRadu Pirea (NXP OSS) 			break;
718514def5dSRadu Pirea (NXP OSS) 		}
719514def5dSRadu Pirea (NXP OSS) 
720514def5dSRadu Pirea (NXP OSS) 		nxp_c45_process_txts(priv, &hwts);
721514def5dSRadu Pirea (NXP OSS) 	}
722514def5dSRadu Pirea (NXP OSS) 
723514def5dSRadu Pirea (NXP OSS) 	while ((skb = skb_dequeue(&priv->rx_queue)) != NULL) {
724109258edSVladimir Oltean 		nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL);
725514def5dSRadu Pirea (NXP OSS) 		ts_raw = __be32_to_cpu(NXP_C45_SKB_CB(skb)->header->reserved2);
726514def5dSRadu Pirea (NXP OSS) 		hwts.sec = ts_raw >> 30;
727514def5dSRadu Pirea (NXP OSS) 		hwts.nsec = ts_raw & GENMASK(29, 0);
728514def5dSRadu Pirea (NXP OSS) 		nxp_c45_reconstruct_ts(&ts, &hwts);
729514def5dSRadu Pirea (NXP OSS) 		shhwtstamps_rx = skb_hwtstamps(skb);
730514def5dSRadu Pirea (NXP OSS) 		shhwtstamps_rx->hwtstamp = ns_to_ktime(timespec64_to_ns(&ts));
731514def5dSRadu Pirea (NXP OSS) 		NXP_C45_SKB_CB(skb)->header->reserved2 = 0;
732a3d73e15SSebastian Andrzej Siewior 		netif_rx(skb);
733514def5dSRadu Pirea (NXP OSS) 	}
734514def5dSRadu Pirea (NXP OSS) 
7357a71c8aaSRadu Pirea (NXP OSS) 	if (priv->extts) {
736*08e6547cSRadu Pirea (NXP OSS) 		ts_valid = data->get_extts(priv, &ts);
737*08e6547cSRadu Pirea (NXP OSS) 		if (ts_valid && timespec64_compare(&ts, &priv->extts_ts) != 0) {
7387a71c8aaSRadu Pirea (NXP OSS) 			priv->extts_ts = ts;
7397a71c8aaSRadu Pirea (NXP OSS) 			event.index = priv->extts_index;
7407a71c8aaSRadu Pirea (NXP OSS) 			event.type = PTP_CLOCK_EXTTS;
7417a71c8aaSRadu Pirea (NXP OSS) 			event.timestamp = ns_to_ktime(timespec64_to_ns(&ts));
7427a71c8aaSRadu Pirea (NXP OSS) 			ptp_clock_event(priv->ptp_clock, &event);
7437a71c8aaSRadu Pirea (NXP OSS) 		}
7447a71c8aaSRadu Pirea (NXP OSS) 		reschedule = true;
7457a71c8aaSRadu Pirea (NXP OSS) 	}
7467a71c8aaSRadu Pirea (NXP OSS) 
747514def5dSRadu Pirea (NXP OSS) 	return reschedule ? 1 : -1;
748514def5dSRadu Pirea (NXP OSS) }
749514def5dSRadu Pirea (NXP OSS) 
7507a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_gpio_config(struct nxp_c45_phy *priv,
7517a71c8aaSRadu Pirea (NXP OSS) 				int pin, u16 pin_cfg)
7527a71c8aaSRadu Pirea (NXP OSS) {
7537a71c8aaSRadu Pirea (NXP OSS) 	struct phy_device *phydev = priv->phydev;
7547a71c8aaSRadu Pirea (NXP OSS) 
7557a71c8aaSRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1,
7567a71c8aaSRadu Pirea (NXP OSS) 		      VEND1_GPIO_FUNC_CONFIG_BASE + pin, pin_cfg);
7577a71c8aaSRadu Pirea (NXP OSS) }
7587a71c8aaSRadu Pirea (NXP OSS) 
7597a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_perout_enable(struct nxp_c45_phy *priv,
7607a71c8aaSRadu Pirea (NXP OSS) 				 struct ptp_perout_request *perout, int on)
7617a71c8aaSRadu Pirea (NXP OSS) {
7626c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
7637a71c8aaSRadu Pirea (NXP OSS) 	struct phy_device *phydev = priv->phydev;
7647a71c8aaSRadu Pirea (NXP OSS) 	int pin;
7657a71c8aaSRadu Pirea (NXP OSS) 
7667a71c8aaSRadu Pirea (NXP OSS) 	if (perout->flags & ~PTP_PEROUT_PHASE)
7677a71c8aaSRadu Pirea (NXP OSS) 		return -EOPNOTSUPP;
7687a71c8aaSRadu Pirea (NXP OSS) 
7697a71c8aaSRadu Pirea (NXP OSS) 	pin = ptp_find_pin(priv->ptp_clock, PTP_PF_PEROUT, perout->index);
7707a71c8aaSRadu Pirea (NXP OSS) 	if (pin < 0)
7717a71c8aaSRadu Pirea (NXP OSS) 		return pin;
7727a71c8aaSRadu Pirea (NXP OSS) 
7737a71c8aaSRadu Pirea (NXP OSS) 	if (!on) {
7746c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_clear_reg_field(priv->phydev,
7756c0c85daSRadu Pirea (NXP OSS) 					&regmap->pps_enable);
7766c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_clear_reg_field(priv->phydev,
7776c0c85daSRadu Pirea (NXP OSS) 					&regmap->pps_polarity);
7787a71c8aaSRadu Pirea (NXP OSS) 
7797a71c8aaSRadu Pirea (NXP OSS) 		nxp_c45_gpio_config(priv, pin, GPIO_DISABLE);
7807a71c8aaSRadu Pirea (NXP OSS) 
7817a71c8aaSRadu Pirea (NXP OSS) 		return 0;
7827a71c8aaSRadu Pirea (NXP OSS) 	}
7837a71c8aaSRadu Pirea (NXP OSS) 
7847a71c8aaSRadu Pirea (NXP OSS) 	/* The PPS signal is fixed to 1 second and is always generated when the
7857a71c8aaSRadu Pirea (NXP OSS) 	 * seconds counter is incremented. The start time is not configurable.
7867a71c8aaSRadu Pirea (NXP OSS) 	 * If the clock is adjusted, the PPS signal is automatically readjusted.
7877a71c8aaSRadu Pirea (NXP OSS) 	 */
7887a71c8aaSRadu Pirea (NXP OSS) 	if (perout->period.sec != 1 || perout->period.nsec != 0) {
7897a71c8aaSRadu Pirea (NXP OSS) 		phydev_warn(phydev, "The period can be set only to 1 second.");
7907a71c8aaSRadu Pirea (NXP OSS) 		return -EINVAL;
7917a71c8aaSRadu Pirea (NXP OSS) 	}
7927a71c8aaSRadu Pirea (NXP OSS) 
7937a71c8aaSRadu Pirea (NXP OSS) 	if (!(perout->flags & PTP_PEROUT_PHASE)) {
7947a71c8aaSRadu Pirea (NXP OSS) 		if (perout->start.sec != 0 || perout->start.nsec != 0) {
7957a71c8aaSRadu Pirea (NXP OSS) 			phydev_warn(phydev, "The start time is not configurable. Should be set to 0 seconds and 0 nanoseconds.");
7967a71c8aaSRadu Pirea (NXP OSS) 			return -EINVAL;
7977a71c8aaSRadu Pirea (NXP OSS) 		}
7987a71c8aaSRadu Pirea (NXP OSS) 	} else {
7997a71c8aaSRadu Pirea (NXP OSS) 		if (perout->phase.nsec != 0 &&
8007a71c8aaSRadu Pirea (NXP OSS) 		    perout->phase.nsec != (NSEC_PER_SEC >> 1)) {
8017a71c8aaSRadu Pirea (NXP OSS) 			phydev_warn(phydev, "The phase can be set only to 0 or 500000000 nanoseconds.");
8027a71c8aaSRadu Pirea (NXP OSS) 			return -EINVAL;
8037a71c8aaSRadu Pirea (NXP OSS) 		}
8047a71c8aaSRadu Pirea (NXP OSS) 
8057a71c8aaSRadu Pirea (NXP OSS) 		if (perout->phase.nsec == 0)
8066c0c85daSRadu Pirea (NXP OSS) 			nxp_c45_clear_reg_field(priv->phydev,
8076c0c85daSRadu Pirea (NXP OSS) 						&regmap->pps_polarity);
8087a71c8aaSRadu Pirea (NXP OSS) 		else
8096c0c85daSRadu Pirea (NXP OSS) 			nxp_c45_set_reg_field(priv->phydev,
8106c0c85daSRadu Pirea (NXP OSS) 					      &regmap->pps_polarity);
8117a71c8aaSRadu Pirea (NXP OSS) 	}
8127a71c8aaSRadu Pirea (NXP OSS) 
8137a71c8aaSRadu Pirea (NXP OSS) 	nxp_c45_gpio_config(priv, pin, GPIO_PPS_OUT_CFG);
8147a71c8aaSRadu Pirea (NXP OSS) 
8156c0c85daSRadu Pirea (NXP OSS) 	nxp_c45_set_reg_field(priv->phydev, &regmap->pps_enable);
8167a71c8aaSRadu Pirea (NXP OSS) 
8177a71c8aaSRadu Pirea (NXP OSS) 	return 0;
8187a71c8aaSRadu Pirea (NXP OSS) }
8197a71c8aaSRadu Pirea (NXP OSS) 
820b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_or_falling(struct phy_device *phydev,
821b0b2247dSRadu Pirea (NXP OSS) 					  struct ptp_extts_request *extts)
822b0b2247dSRadu Pirea (NXP OSS) {
823b0b2247dSRadu Pirea (NXP OSS) 	if (extts->flags & PTP_RISING_EDGE)
824b0b2247dSRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
825b0b2247dSRadu Pirea (NXP OSS) 				   VEND1_PTP_CONFIG, EXT_TRG_EDGE);
826b0b2247dSRadu Pirea (NXP OSS) 
827b0b2247dSRadu Pirea (NXP OSS) 	if (extts->flags & PTP_FALLING_EDGE)
828b0b2247dSRadu Pirea (NXP OSS) 		phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
829b0b2247dSRadu Pirea (NXP OSS) 				 VEND1_PTP_CONFIG, EXT_TRG_EDGE);
830b0b2247dSRadu Pirea (NXP OSS) }
831b0b2247dSRadu Pirea (NXP OSS) 
832b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_and_falling(struct phy_device *phydev,
833b0b2247dSRadu Pirea (NXP OSS) 					   struct ptp_extts_request *extts)
834b0b2247dSRadu Pirea (NXP OSS) {
835b0b2247dSRadu Pirea (NXP OSS) 	/* PTP_EXTTS_REQUEST may have only the PTP_ENABLE_FEATURE flag set. In
836b0b2247dSRadu Pirea (NXP OSS) 	 * this case external ts will be enabled on rising edge.
837b0b2247dSRadu Pirea (NXP OSS) 	 */
838b0b2247dSRadu Pirea (NXP OSS) 	if (extts->flags & PTP_RISING_EDGE ||
839b0b2247dSRadu Pirea (NXP OSS) 	    extts->flags == PTP_ENABLE_FEATURE)
840b0b2247dSRadu Pirea (NXP OSS) 		phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
841b0b2247dSRadu Pirea (NXP OSS) 				 TJA1120_SYNC_TRIG_FILTER,
842b0b2247dSRadu Pirea (NXP OSS) 				 PTP_TRIG_RISE_TS);
843b0b2247dSRadu Pirea (NXP OSS) 	else
844b0b2247dSRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
845b0b2247dSRadu Pirea (NXP OSS) 				   TJA1120_SYNC_TRIG_FILTER,
846b0b2247dSRadu Pirea (NXP OSS) 				   PTP_TRIG_RISE_TS);
847b0b2247dSRadu Pirea (NXP OSS) 
848b0b2247dSRadu Pirea (NXP OSS) 	if (extts->flags & PTP_FALLING_EDGE)
849b0b2247dSRadu Pirea (NXP OSS) 		phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
850b0b2247dSRadu Pirea (NXP OSS) 				 TJA1120_SYNC_TRIG_FILTER,
851b0b2247dSRadu Pirea (NXP OSS) 				 PTP_TRIG_FALLING_TS);
852b0b2247dSRadu Pirea (NXP OSS) 	else
853b0b2247dSRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
854b0b2247dSRadu Pirea (NXP OSS) 				   TJA1120_SYNC_TRIG_FILTER,
855b0b2247dSRadu Pirea (NXP OSS) 				   PTP_TRIG_FALLING_TS);
856b0b2247dSRadu Pirea (NXP OSS) }
857b0b2247dSRadu Pirea (NXP OSS) 
8587a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_extts_enable(struct nxp_c45_phy *priv,
8597a71c8aaSRadu Pirea (NXP OSS) 				struct ptp_extts_request *extts, int on)
8607a71c8aaSRadu Pirea (NXP OSS) {
861b0b2247dSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev);
8627a71c8aaSRadu Pirea (NXP OSS) 	int pin;
8637a71c8aaSRadu Pirea (NXP OSS) 
8647a71c8aaSRadu Pirea (NXP OSS) 	if (extts->flags & ~(PTP_ENABLE_FEATURE |
8657a71c8aaSRadu Pirea (NXP OSS) 			      PTP_RISING_EDGE |
8667a71c8aaSRadu Pirea (NXP OSS) 			      PTP_FALLING_EDGE |
8677a71c8aaSRadu Pirea (NXP OSS) 			      PTP_STRICT_FLAGS))
8687a71c8aaSRadu Pirea (NXP OSS) 		return -EOPNOTSUPP;
8697a71c8aaSRadu Pirea (NXP OSS) 
8707a71c8aaSRadu Pirea (NXP OSS) 	/* Sampling on both edges is not supported */
8717a71c8aaSRadu Pirea (NXP OSS) 	if ((extts->flags & PTP_RISING_EDGE) &&
872b0b2247dSRadu Pirea (NXP OSS) 	    (extts->flags & PTP_FALLING_EDGE) &&
873b0b2247dSRadu Pirea (NXP OSS) 	    !data->ext_ts_both_edges)
8747a71c8aaSRadu Pirea (NXP OSS) 		return -EOPNOTSUPP;
8757a71c8aaSRadu Pirea (NXP OSS) 
8767a71c8aaSRadu Pirea (NXP OSS) 	pin = ptp_find_pin(priv->ptp_clock, PTP_PF_EXTTS, extts->index);
8777a71c8aaSRadu Pirea (NXP OSS) 	if (pin < 0)
8787a71c8aaSRadu Pirea (NXP OSS) 		return pin;
8797a71c8aaSRadu Pirea (NXP OSS) 
8807a71c8aaSRadu Pirea (NXP OSS) 	if (!on) {
8817a71c8aaSRadu Pirea (NXP OSS) 		nxp_c45_gpio_config(priv, pin, GPIO_DISABLE);
8827a71c8aaSRadu Pirea (NXP OSS) 		priv->extts = false;
8837a71c8aaSRadu Pirea (NXP OSS) 
8847a71c8aaSRadu Pirea (NXP OSS) 		return 0;
8857a71c8aaSRadu Pirea (NXP OSS) 	}
8867a71c8aaSRadu Pirea (NXP OSS) 
887b0b2247dSRadu Pirea (NXP OSS) 	if (data->ext_ts_both_edges)
888b0b2247dSRadu Pirea (NXP OSS) 		nxp_c45_set_rising_and_falling(priv->phydev, extts);
889b0b2247dSRadu Pirea (NXP OSS) 	else
890b0b2247dSRadu Pirea (NXP OSS) 		nxp_c45_set_rising_or_falling(priv->phydev, extts);
8917a71c8aaSRadu Pirea (NXP OSS) 
8927a71c8aaSRadu Pirea (NXP OSS) 	nxp_c45_gpio_config(priv, pin, GPIO_EXTTS_OUT_CFG);
8937a71c8aaSRadu Pirea (NXP OSS) 	priv->extts = true;
8947a71c8aaSRadu Pirea (NXP OSS) 	priv->extts_index = extts->index;
8957a71c8aaSRadu Pirea (NXP OSS) 	ptp_schedule_worker(priv->ptp_clock, 0);
8967a71c8aaSRadu Pirea (NXP OSS) 
8977a71c8aaSRadu Pirea (NXP OSS) 	return 0;
8987a71c8aaSRadu Pirea (NXP OSS) }
8997a71c8aaSRadu Pirea (NXP OSS) 
9007a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_enable(struct ptp_clock_info *ptp,
9017a71c8aaSRadu Pirea (NXP OSS) 			      struct ptp_clock_request *req, int on)
9027a71c8aaSRadu Pirea (NXP OSS) {
9037a71c8aaSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
9047a71c8aaSRadu Pirea (NXP OSS) 
9057a71c8aaSRadu Pirea (NXP OSS) 	switch (req->type) {
9067a71c8aaSRadu Pirea (NXP OSS) 	case PTP_CLK_REQ_EXTTS:
9077a71c8aaSRadu Pirea (NXP OSS) 		return nxp_c45_extts_enable(priv, &req->extts, on);
9087a71c8aaSRadu Pirea (NXP OSS) 	case PTP_CLK_REQ_PEROUT:
9097a71c8aaSRadu Pirea (NXP OSS) 		return nxp_c45_perout_enable(priv, &req->perout, on);
9107a71c8aaSRadu Pirea (NXP OSS) 	default:
9117a71c8aaSRadu Pirea (NXP OSS) 		return -EOPNOTSUPP;
9127a71c8aaSRadu Pirea (NXP OSS) 	}
9137a71c8aaSRadu Pirea (NXP OSS) }
9147a71c8aaSRadu Pirea (NXP OSS) 
9157a71c8aaSRadu Pirea (NXP OSS) static struct ptp_pin_desc nxp_c45_ptp_pins[] = {
9167a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio0", 0, PTP_PF_NONE},
9177a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio1", 1, PTP_PF_NONE},
9187a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio2", 2, PTP_PF_NONE},
9197a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio3", 3, PTP_PF_NONE},
9207a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio4", 4, PTP_PF_NONE},
9217a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio5", 5, PTP_PF_NONE},
9227a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio6", 6, PTP_PF_NONE},
9237a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio7", 7, PTP_PF_NONE},
9247a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio8", 8, PTP_PF_NONE},
9257a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio9", 9, PTP_PF_NONE},
9267a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio10", 10, PTP_PF_NONE},
9277a71c8aaSRadu Pirea (NXP OSS) 	{ "nxp_c45_gpio11", 11, PTP_PF_NONE},
9287a71c8aaSRadu Pirea (NXP OSS) };
9297a71c8aaSRadu Pirea (NXP OSS) 
9307a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
9317a71c8aaSRadu Pirea (NXP OSS) 				  enum ptp_pin_function func, unsigned int chan)
9327a71c8aaSRadu Pirea (NXP OSS) {
9337a71c8aaSRadu Pirea (NXP OSS) 	if (pin >= ARRAY_SIZE(nxp_c45_ptp_pins))
9347a71c8aaSRadu Pirea (NXP OSS) 		return -EINVAL;
9357a71c8aaSRadu Pirea (NXP OSS) 
9367a71c8aaSRadu Pirea (NXP OSS) 	switch (func) {
9377a71c8aaSRadu Pirea (NXP OSS) 	case PTP_PF_NONE:
9387a71c8aaSRadu Pirea (NXP OSS) 	case PTP_PF_PEROUT:
9397a71c8aaSRadu Pirea (NXP OSS) 	case PTP_PF_EXTTS:
9407a71c8aaSRadu Pirea (NXP OSS) 		break;
9417a71c8aaSRadu Pirea (NXP OSS) 	default:
9427a71c8aaSRadu Pirea (NXP OSS) 		return -EOPNOTSUPP;
9437a71c8aaSRadu Pirea (NXP OSS) 	}
9447a71c8aaSRadu Pirea (NXP OSS) 
9457a71c8aaSRadu Pirea (NXP OSS) 	return 0;
9467a71c8aaSRadu Pirea (NXP OSS) }
9477a71c8aaSRadu Pirea (NXP OSS) 
948514def5dSRadu Pirea (NXP OSS) static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv)
949514def5dSRadu Pirea (NXP OSS) {
950514def5dSRadu Pirea (NXP OSS) 	priv->caps = (struct ptp_clock_info) {
951514def5dSRadu Pirea (NXP OSS) 		.owner		= THIS_MODULE,
952514def5dSRadu Pirea (NXP OSS) 		.name		= "NXP C45 PHC",
953514def5dSRadu Pirea (NXP OSS) 		.max_adj	= 16666666,
954514def5dSRadu Pirea (NXP OSS) 		.adjfine	= nxp_c45_ptp_adjfine,
955514def5dSRadu Pirea (NXP OSS) 		.adjtime	= nxp_c45_ptp_adjtime,
956514def5dSRadu Pirea (NXP OSS) 		.gettimex64	= nxp_c45_ptp_gettimex64,
957514def5dSRadu Pirea (NXP OSS) 		.settime64	= nxp_c45_ptp_settime64,
9587a71c8aaSRadu Pirea (NXP OSS) 		.enable		= nxp_c45_ptp_enable,
9597a71c8aaSRadu Pirea (NXP OSS) 		.verify		= nxp_c45_ptp_verify_pin,
960514def5dSRadu Pirea (NXP OSS) 		.do_aux_work	= nxp_c45_do_aux_work,
9617a71c8aaSRadu Pirea (NXP OSS) 		.pin_config	= nxp_c45_ptp_pins,
9627a71c8aaSRadu Pirea (NXP OSS) 		.n_pins		= ARRAY_SIZE(nxp_c45_ptp_pins),
9637a71c8aaSRadu Pirea (NXP OSS) 		.n_ext_ts	= 1,
9647a71c8aaSRadu Pirea (NXP OSS) 		.n_per_out	= 1,
965514def5dSRadu Pirea (NXP OSS) 	};
966514def5dSRadu Pirea (NXP OSS) 
967514def5dSRadu Pirea (NXP OSS) 	priv->ptp_clock = ptp_clock_register(&priv->caps,
968514def5dSRadu Pirea (NXP OSS) 					     &priv->phydev->mdio.dev);
969514def5dSRadu Pirea (NXP OSS) 
970514def5dSRadu Pirea (NXP OSS) 	if (IS_ERR(priv->ptp_clock))
971514def5dSRadu Pirea (NXP OSS) 		return PTR_ERR(priv->ptp_clock);
972514def5dSRadu Pirea (NXP OSS) 
973514def5dSRadu Pirea (NXP OSS) 	if (!priv->ptp_clock)
974514def5dSRadu Pirea (NXP OSS) 		return -ENOMEM;
975514def5dSRadu Pirea (NXP OSS) 
976514def5dSRadu Pirea (NXP OSS) 	return 0;
977514def5dSRadu Pirea (NXP OSS) }
978514def5dSRadu Pirea (NXP OSS) 
979514def5dSRadu Pirea (NXP OSS) static void nxp_c45_txtstamp(struct mii_timestamper *mii_ts,
980514def5dSRadu Pirea (NXP OSS) 			     struct sk_buff *skb, int type)
981514def5dSRadu Pirea (NXP OSS) {
982514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
983514def5dSRadu Pirea (NXP OSS) 						mii_ts);
984514def5dSRadu Pirea (NXP OSS) 
985514def5dSRadu Pirea (NXP OSS) 	switch (priv->hwts_tx) {
986514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_TX_ON:
987514def5dSRadu Pirea (NXP OSS) 		NXP_C45_SKB_CB(skb)->type = type;
988514def5dSRadu Pirea (NXP OSS) 		NXP_C45_SKB_CB(skb)->header = ptp_parse_header(skb, type);
989514def5dSRadu Pirea (NXP OSS) 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
990514def5dSRadu Pirea (NXP OSS) 		skb_queue_tail(&priv->tx_queue, skb);
991514def5dSRadu Pirea (NXP OSS) 		if (nxp_c45_poll_txts(priv->phydev))
992514def5dSRadu Pirea (NXP OSS) 			ptp_schedule_worker(priv->ptp_clock, 0);
993514def5dSRadu Pirea (NXP OSS) 		break;
994514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_TX_OFF:
995514def5dSRadu Pirea (NXP OSS) 	default:
996514def5dSRadu Pirea (NXP OSS) 		kfree_skb(skb);
997514def5dSRadu Pirea (NXP OSS) 		break;
998514def5dSRadu Pirea (NXP OSS) 	}
999514def5dSRadu Pirea (NXP OSS) }
1000514def5dSRadu Pirea (NXP OSS) 
1001514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_rxtstamp(struct mii_timestamper *mii_ts,
1002514def5dSRadu Pirea (NXP OSS) 			     struct sk_buff *skb, int type)
1003514def5dSRadu Pirea (NXP OSS) {
1004514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
1005514def5dSRadu Pirea (NXP OSS) 						mii_ts);
1006514def5dSRadu Pirea (NXP OSS) 	struct ptp_header *header = ptp_parse_header(skb, type);
1007514def5dSRadu Pirea (NXP OSS) 
1008514def5dSRadu Pirea (NXP OSS) 	if (!header)
1009514def5dSRadu Pirea (NXP OSS) 		return false;
1010514def5dSRadu Pirea (NXP OSS) 
1011514def5dSRadu Pirea (NXP OSS) 	if (!priv->hwts_rx)
1012514def5dSRadu Pirea (NXP OSS) 		return false;
1013514def5dSRadu Pirea (NXP OSS) 
1014514def5dSRadu Pirea (NXP OSS) 	NXP_C45_SKB_CB(skb)->header = header;
1015514def5dSRadu Pirea (NXP OSS) 	skb_queue_tail(&priv->rx_queue, skb);
1016514def5dSRadu Pirea (NXP OSS) 	ptp_schedule_worker(priv->ptp_clock, 0);
1017514def5dSRadu Pirea (NXP OSS) 
1018514def5dSRadu Pirea (NXP OSS) 	return true;
1019514def5dSRadu Pirea (NXP OSS) }
1020514def5dSRadu Pirea (NXP OSS) 
1021514def5dSRadu Pirea (NXP OSS) static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts,
1022514def5dSRadu Pirea (NXP OSS) 			    struct ifreq *ifreq)
1023514def5dSRadu Pirea (NXP OSS) {
1024514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
1025514def5dSRadu Pirea (NXP OSS) 						mii_ts);
1026514def5dSRadu Pirea (NXP OSS) 	struct phy_device *phydev = priv->phydev;
10276c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *data;
1028514def5dSRadu Pirea (NXP OSS) 	struct hwtstamp_config cfg;
1029514def5dSRadu Pirea (NXP OSS) 
1030514def5dSRadu Pirea (NXP OSS) 	if (copy_from_user(&cfg, ifreq->ifr_data, sizeof(cfg)))
1031514def5dSRadu Pirea (NXP OSS) 		return -EFAULT;
1032514def5dSRadu Pirea (NXP OSS) 
1033514def5dSRadu Pirea (NXP OSS) 	if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ON)
1034514def5dSRadu Pirea (NXP OSS) 		return -ERANGE;
1035514def5dSRadu Pirea (NXP OSS) 
10366c0c85daSRadu Pirea (NXP OSS) 	data = nxp_c45_get_data(phydev);
1037514def5dSRadu Pirea (NXP OSS) 	priv->hwts_tx = cfg.tx_type;
1038514def5dSRadu Pirea (NXP OSS) 
1039514def5dSRadu Pirea (NXP OSS) 	switch (cfg.rx_filter) {
1040514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_FILTER_NONE:
1041514def5dSRadu Pirea (NXP OSS) 		priv->hwts_rx = 0;
1042514def5dSRadu Pirea (NXP OSS) 		break;
1043514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
1044514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
1045514def5dSRadu Pirea (NXP OSS) 	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
1046514def5dSRadu Pirea (NXP OSS) 		priv->hwts_rx = 1;
1047514def5dSRadu Pirea (NXP OSS) 		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
1048514def5dSRadu Pirea (NXP OSS) 		break;
1049514def5dSRadu Pirea (NXP OSS) 	default:
1050514def5dSRadu Pirea (NXP OSS) 		return -ERANGE;
1051514def5dSRadu Pirea (NXP OSS) 	}
1052514def5dSRadu Pirea (NXP OSS) 
1053514def5dSRadu Pirea (NXP OSS) 	if (priv->hwts_rx || priv->hwts_tx) {
10546c0c85daSRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1,
10556c0c85daSRadu Pirea (NXP OSS) 			      data->regmap->vend1_event_msg_filt,
1056514def5dSRadu Pirea (NXP OSS) 			      EVENT_MSG_FILT_ALL);
10576c0c85daSRadu Pirea (NXP OSS) 		data->ptp_enable(phydev, true);
1058514def5dSRadu Pirea (NXP OSS) 	} else {
10596c0c85daSRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1,
10606c0c85daSRadu Pirea (NXP OSS) 			      data->regmap->vend1_event_msg_filt,
1061514def5dSRadu Pirea (NXP OSS) 			      EVENT_MSG_FILT_NONE);
10626c0c85daSRadu Pirea (NXP OSS) 		data->ptp_enable(phydev, false);
1063514def5dSRadu Pirea (NXP OSS) 	}
1064514def5dSRadu Pirea (NXP OSS) 
1065514def5dSRadu Pirea (NXP OSS) 	if (nxp_c45_poll_txts(priv->phydev))
1066514def5dSRadu Pirea (NXP OSS) 		goto nxp_c45_no_ptp_irq;
1067514def5dSRadu Pirea (NXP OSS) 
1068514def5dSRadu Pirea (NXP OSS) 	if (priv->hwts_tx)
10696c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_set_reg_field(phydev, &data->regmap->irq_egr_ts_en);
1070514def5dSRadu Pirea (NXP OSS) 	else
10716c0c85daSRadu Pirea (NXP OSS) 		nxp_c45_clear_reg_field(phydev, &data->regmap->irq_egr_ts_en);
1072514def5dSRadu Pirea (NXP OSS) 
1073514def5dSRadu Pirea (NXP OSS) nxp_c45_no_ptp_irq:
1074514def5dSRadu Pirea (NXP OSS) 	return copy_to_user(ifreq->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
1075514def5dSRadu Pirea (NXP OSS) }
1076514def5dSRadu Pirea (NXP OSS) 
1077514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ts_info(struct mii_timestamper *mii_ts,
1078514def5dSRadu Pirea (NXP OSS) 			   struct ethtool_ts_info *ts_info)
1079514def5dSRadu Pirea (NXP OSS) {
1080514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
1081514def5dSRadu Pirea (NXP OSS) 						mii_ts);
1082514def5dSRadu Pirea (NXP OSS) 
1083514def5dSRadu Pirea (NXP OSS) 	ts_info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
1084514def5dSRadu Pirea (NXP OSS) 			SOF_TIMESTAMPING_RX_HARDWARE |
1085514def5dSRadu Pirea (NXP OSS) 			SOF_TIMESTAMPING_RAW_HARDWARE;
1086514def5dSRadu Pirea (NXP OSS) 	ts_info->phc_index = ptp_clock_index(priv->ptp_clock);
1087514def5dSRadu Pirea (NXP OSS) 	ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
1088514def5dSRadu Pirea (NXP OSS) 	ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
1089514def5dSRadu Pirea (NXP OSS) 			(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
1090514def5dSRadu Pirea (NXP OSS) 			(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
1091514def5dSRadu Pirea (NXP OSS) 			(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT);
1092514def5dSRadu Pirea (NXP OSS) 
1093514def5dSRadu Pirea (NXP OSS) 	return 0;
1094514def5dSRadu Pirea (NXP OSS) }
1095514def5dSRadu Pirea (NXP OSS) 
10966c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats common_hw_stats[] = {
10976c0c85daSRadu Pirea (NXP OSS) 	{ "phy_link_status_drop_cnt",
10986c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 8, 6), },
10996c0c85daSRadu Pirea (NXP OSS) 	{ "phy_link_availability_drop_cnt",
11006c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 0, 6), },
11016c0c85daSRadu Pirea (NXP OSS) 	{ "phy_link_loss_cnt",
11026c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 10, 6), },
11036c0c85daSRadu Pirea (NXP OSS) 	{ "phy_link_failure_cnt",
11046c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 0, 10), },
11056c0c85daSRadu Pirea (NXP OSS) 	{ "phy_symbol_error_cnt",
11066c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8350, MDIO_MMD_VEND1, 0, 16) },
11076c0c85daSRadu Pirea (NXP OSS) };
11086c0c85daSRadu Pirea (NXP OSS) 
11096c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1103_hw_stats[] = {
11106c0c85daSRadu Pirea (NXP OSS) 	{ "rx_preamble_count",
11116c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xAFCE, MDIO_MMD_VEND1, 0, 6), },
11126c0c85daSRadu Pirea (NXP OSS) 	{ "tx_preamble_count",
11136c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xAFCF, MDIO_MMD_VEND1, 0, 6), },
11146c0c85daSRadu Pirea (NXP OSS) 	{ "rx_ipg_length",
11156c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xAFD0, MDIO_MMD_VEND1, 0, 9), },
11166c0c85daSRadu Pirea (NXP OSS) 	{ "tx_ipg_length",
11176c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xAFD1, MDIO_MMD_VEND1, 0, 9), },
1118b050f2f1SRadu Pirea (NXP OSS) };
1119b050f2f1SRadu Pirea (NXP OSS) 
1120f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1120_hw_stats[] = {
1121f1fe5dffSRadu Pirea (NXP OSS) 	{ "phy_symbol_error_cnt_ext",
1122f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8351, MDIO_MMD_VEND1, 0, 14) },
1123f1fe5dffSRadu Pirea (NXP OSS) 	{ "tx_frames_xtd",
1124f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xACA1, MDIO_MMD_VEND1, 0, 8), },
1125f1fe5dffSRadu Pirea (NXP OSS) 	{ "tx_frames",
1126f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xACA0, MDIO_MMD_VEND1, 0, 16), },
1127f1fe5dffSRadu Pirea (NXP OSS) 	{ "rx_frames_xtd",
1128f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xACA3, MDIO_MMD_VEND1, 0, 8), },
1129f1fe5dffSRadu Pirea (NXP OSS) 	{ "rx_frames",
1130f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xACA2, MDIO_MMD_VEND1, 0, 16), },
1131f1fe5dffSRadu Pirea (NXP OSS) 	{ "tx_lost_frames_xtd",
1132f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xACA5, MDIO_MMD_VEND1, 0, 8), },
1133f1fe5dffSRadu Pirea (NXP OSS) 	{ "tx_lost_frames",
1134f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xACA4, MDIO_MMD_VEND1, 0, 16), },
1135f1fe5dffSRadu Pirea (NXP OSS) 	{ "rx_lost_frames_xtd",
1136f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xACA7, MDIO_MMD_VEND1, 0, 8), },
1137f1fe5dffSRadu Pirea (NXP OSS) 	{ "rx_lost_frames",
1138f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0xACA6, MDIO_MMD_VEND1, 0, 16), },
1139f1fe5dffSRadu Pirea (NXP OSS) };
1140f1fe5dffSRadu Pirea (NXP OSS) 
1141b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev)
1142b050f2f1SRadu Pirea (NXP OSS) {
11436c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev);
11446c0c85daSRadu Pirea (NXP OSS) 
11456c0c85daSRadu Pirea (NXP OSS) 	return ARRAY_SIZE(common_hw_stats) + (phy_data ? phy_data->n_stats : 0);
1146b050f2f1SRadu Pirea (NXP OSS) }
1147b050f2f1SRadu Pirea (NXP OSS) 
1148b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data)
1149b050f2f1SRadu Pirea (NXP OSS) {
11506c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev);
11516c0c85daSRadu Pirea (NXP OSS) 	size_t count = nxp_c45_get_sset_count(phydev);
11526c0c85daSRadu Pirea (NXP OSS) 	size_t idx;
1153b050f2f1SRadu Pirea (NXP OSS) 	size_t i;
1154b050f2f1SRadu Pirea (NXP OSS) 
11556c0c85daSRadu Pirea (NXP OSS) 	for (i = 0; i < count; i++) {
11566c0c85daSRadu Pirea (NXP OSS) 		if (i < ARRAY_SIZE(common_hw_stats)) {
11576c0c85daSRadu Pirea (NXP OSS) 			strscpy(data + i * ETH_GSTRING_LEN,
11586c0c85daSRadu Pirea (NXP OSS) 				common_hw_stats[i].name, ETH_GSTRING_LEN);
11596c0c85daSRadu Pirea (NXP OSS) 			continue;
11606c0c85daSRadu Pirea (NXP OSS) 		}
11616c0c85daSRadu Pirea (NXP OSS) 		idx = i - ARRAY_SIZE(common_hw_stats);
11626c0c85daSRadu Pirea (NXP OSS) 		strscpy(data + i * ETH_GSTRING_LEN,
11636c0c85daSRadu Pirea (NXP OSS) 			phy_data->stats[idx].name, ETH_GSTRING_LEN);
1164b050f2f1SRadu Pirea (NXP OSS) 	}
1165b050f2f1SRadu Pirea (NXP OSS) }
1166b050f2f1SRadu Pirea (NXP OSS) 
1167b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev,
1168b050f2f1SRadu Pirea (NXP OSS) 			      struct ethtool_stats *stats, u64 *data)
1169b050f2f1SRadu Pirea (NXP OSS) {
11706c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev);
11716c0c85daSRadu Pirea (NXP OSS) 	size_t count = nxp_c45_get_sset_count(phydev);
11726c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_reg_field *reg_field;
11736c0c85daSRadu Pirea (NXP OSS) 	size_t idx;
1174b050f2f1SRadu Pirea (NXP OSS) 	size_t i;
1175b050f2f1SRadu Pirea (NXP OSS) 	int ret;
1176b050f2f1SRadu Pirea (NXP OSS) 
11776c0c85daSRadu Pirea (NXP OSS) 	for (i = 0; i < count; i++) {
11786c0c85daSRadu Pirea (NXP OSS) 		if (i < ARRAY_SIZE(common_hw_stats)) {
11796c0c85daSRadu Pirea (NXP OSS) 			reg_field = &common_hw_stats[i].counter;
1180b050f2f1SRadu Pirea (NXP OSS) 		} else {
11816c0c85daSRadu Pirea (NXP OSS) 			idx = i - ARRAY_SIZE(common_hw_stats);
11826c0c85daSRadu Pirea (NXP OSS) 			reg_field = &phy_data->stats[idx].counter;
1183b050f2f1SRadu Pirea (NXP OSS) 		}
11846c0c85daSRadu Pirea (NXP OSS) 
11856c0c85daSRadu Pirea (NXP OSS) 		ret = nxp_c45_read_reg_field(phydev, reg_field);
11866c0c85daSRadu Pirea (NXP OSS) 		if (ret < 0)
11876c0c85daSRadu Pirea (NXP OSS) 			data[i] = U64_MAX;
11886c0c85daSRadu Pirea (NXP OSS) 		else
11896c0c85daSRadu Pirea (NXP OSS) 			data[i] = ret;
1190b050f2f1SRadu Pirea (NXP OSS) 	}
1191b050f2f1SRadu Pirea (NXP OSS) }
1192b050f2f1SRadu Pirea (NXP OSS) 
1193b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev)
1194b050f2f1SRadu Pirea (NXP OSS) {
1195b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
1196b050f2f1SRadu Pirea (NXP OSS) 		      DEVICE_CONTROL_CONFIG_GLOBAL_EN |
1197b050f2f1SRadu Pirea (NXP OSS) 		      DEVICE_CONTROL_CONFIG_ALL_EN);
1198b050f2f1SRadu Pirea (NXP OSS) 	usleep_range(400, 450);
1199b050f2f1SRadu Pirea (NXP OSS) 
1200b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL,
1201b050f2f1SRadu Pirea (NXP OSS) 		      PORT_CONTROL_EN);
1202b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
1203b050f2f1SRadu Pirea (NXP OSS) 		      PHY_CONFIG_EN);
1204b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL,
1205b050f2f1SRadu Pirea (NXP OSS) 		      PORT_INFRA_CONTROL_EN);
1206b050f2f1SRadu Pirea (NXP OSS) 
1207b050f2f1SRadu Pirea (NXP OSS) 	return 0;
1208b050f2f1SRadu Pirea (NXP OSS) }
1209b050f2f1SRadu Pirea (NXP OSS) 
1210b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev)
1211b050f2f1SRadu Pirea (NXP OSS) {
1212b050f2f1SRadu Pirea (NXP OSS) 	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
1213b050f2f1SRadu Pirea (NXP OSS) 				PHY_START_OP);
1214b050f2f1SRadu Pirea (NXP OSS) }
1215b050f2f1SRadu Pirea (NXP OSS) 
1216b2f0ca00SRadu Pirea (NXP OSS) static int nxp_c45_config_intr(struct phy_device *phydev)
1217b2f0ca00SRadu Pirea (NXP OSS) {
1218b2f0ca00SRadu Pirea (NXP OSS) 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
1219b2f0ca00SRadu Pirea (NXP OSS) 		return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1220b2f0ca00SRadu Pirea (NXP OSS) 					VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
1221b2f0ca00SRadu Pirea (NXP OSS) 	else
1222b2f0ca00SRadu Pirea (NXP OSS) 		return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1223b2f0ca00SRadu Pirea (NXP OSS) 					  VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
1224b2f0ca00SRadu Pirea (NXP OSS) }
1225b2f0ca00SRadu Pirea (NXP OSS) 
1226425c8348SRadu Pirea (NXP OSS) static int tja1103_config_intr(struct phy_device *phydev)
1227425c8348SRadu Pirea (NXP OSS) {
1228425c8348SRadu Pirea (NXP OSS) 	int ret;
1229425c8348SRadu Pirea (NXP OSS) 
1230425c8348SRadu Pirea (NXP OSS) 	/* We can't disable the FUSA IRQ for TJA1103, but we can clean it up. */
1231425c8348SRadu Pirea (NXP OSS) 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_ALWAYS_ACCESSIBLE,
1232425c8348SRadu Pirea (NXP OSS) 			    FUSA_PASS);
1233425c8348SRadu Pirea (NXP OSS) 	if (ret)
1234425c8348SRadu Pirea (NXP OSS) 		return ret;
1235425c8348SRadu Pirea (NXP OSS) 
1236425c8348SRadu Pirea (NXP OSS) 	return nxp_c45_config_intr(phydev);
1237425c8348SRadu Pirea (NXP OSS) }
1238425c8348SRadu Pirea (NXP OSS) 
1239425c8348SRadu Pirea (NXP OSS) static int tja1120_config_intr(struct phy_device *phydev)
1240425c8348SRadu Pirea (NXP OSS) {
1241425c8348SRadu Pirea (NXP OSS) 	int ret;
1242425c8348SRadu Pirea (NXP OSS) 
1243425c8348SRadu Pirea (NXP OSS) 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
1244425c8348SRadu Pirea (NXP OSS) 		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1245425c8348SRadu Pirea (NXP OSS) 				       TJA1120_GLOBAL_INFRA_IRQ_EN,
1246425c8348SRadu Pirea (NXP OSS) 				       TJA1120_DEV_BOOT_DONE);
1247425c8348SRadu Pirea (NXP OSS) 	else
1248425c8348SRadu Pirea (NXP OSS) 		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1249425c8348SRadu Pirea (NXP OSS) 					 TJA1120_GLOBAL_INFRA_IRQ_EN,
1250425c8348SRadu Pirea (NXP OSS) 					 TJA1120_DEV_BOOT_DONE);
1251425c8348SRadu Pirea (NXP OSS) 	if (ret)
1252425c8348SRadu Pirea (NXP OSS) 		return ret;
1253425c8348SRadu Pirea (NXP OSS) 
1254425c8348SRadu Pirea (NXP OSS) 	return nxp_c45_config_intr(phydev);
1255425c8348SRadu Pirea (NXP OSS) }
1256425c8348SRadu Pirea (NXP OSS) 
1257b2f0ca00SRadu Pirea (NXP OSS) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev)
1258b2f0ca00SRadu Pirea (NXP OSS) {
12596c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev);
1260514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = phydev->priv;
1261b2f0ca00SRadu Pirea (NXP OSS) 	irqreturn_t ret = IRQ_NONE;
1262514def5dSRadu Pirea (NXP OSS) 	struct nxp_c45_hwts hwts;
1263b2f0ca00SRadu Pirea (NXP OSS) 	int irq;
1264b2f0ca00SRadu Pirea (NXP OSS) 
1265b2f0ca00SRadu Pirea (NXP OSS) 	irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS);
1266b2f0ca00SRadu Pirea (NXP OSS) 	if (irq & PHY_IRQ_LINK_EVENT) {
1267b2f0ca00SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK,
1268b2f0ca00SRadu Pirea (NXP OSS) 			      PHY_IRQ_LINK_EVENT);
1269b2f0ca00SRadu Pirea (NXP OSS) 		phy_trigger_machine(phydev);
1270b2f0ca00SRadu Pirea (NXP OSS) 		ret = IRQ_HANDLED;
1271b2f0ca00SRadu Pirea (NXP OSS) 	}
1272b2f0ca00SRadu Pirea (NXP OSS) 
12736c0c85daSRadu Pirea (NXP OSS) 	irq = nxp_c45_read_reg_field(phydev, &data->regmap->irq_egr_ts_status);
12746c0c85daSRadu Pirea (NXP OSS) 	if (irq) {
1275bdb4c5b8SRadu Pirea (NXP OSS) 		/* If ack_ptp_irq is false, the IRQ bit is self-clear and will
1276bdb4c5b8SRadu Pirea (NXP OSS) 		 * be cleared when the EGR TS FIFO is empty. Otherwise, the
1277bdb4c5b8SRadu Pirea (NXP OSS) 		 * IRQ bit should be cleared before reading the timestamp,
1278bdb4c5b8SRadu Pirea (NXP OSS) 		 */
1279bdb4c5b8SRadu Pirea (NXP OSS) 		if (data->ack_ptp_irq)
1280bdb4c5b8SRadu Pirea (NXP OSS) 			phy_write_mmd(phydev, MDIO_MMD_VEND1,
1281bdb4c5b8SRadu Pirea (NXP OSS) 				      VEND1_PTP_IRQ_ACK, EGR_TS_IRQ);
1282bdb4c5b8SRadu Pirea (NXP OSS) 		while (data->get_egressts(priv, &hwts))
1283514def5dSRadu Pirea (NXP OSS) 			nxp_c45_process_txts(priv, &hwts);
1284514def5dSRadu Pirea (NXP OSS) 
1285514def5dSRadu Pirea (NXP OSS) 		ret = IRQ_HANDLED;
1286514def5dSRadu Pirea (NXP OSS) 	}
1287514def5dSRadu Pirea (NXP OSS) 
1288425c8348SRadu Pirea (NXP OSS) 	data->nmi_handler(phydev, &ret);
1289425c8348SRadu Pirea (NXP OSS) 
1290b2f0ca00SRadu Pirea (NXP OSS) 	return ret;
1291b2f0ca00SRadu Pirea (NXP OSS) }
1292b2f0ca00SRadu Pirea (NXP OSS) 
1293b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev)
1294b050f2f1SRadu Pirea (NXP OSS) {
1295b050f2f1SRadu Pirea (NXP OSS) 	int ret;
1296b050f2f1SRadu Pirea (NXP OSS) 
1297b050f2f1SRadu Pirea (NXP OSS) 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
1298b050f2f1SRadu Pirea (NXP OSS) 			    DEVICE_CONTROL_RESET);
1299b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
1300b050f2f1SRadu Pirea (NXP OSS) 		return ret;
1301b050f2f1SRadu Pirea (NXP OSS) 
1302b050f2f1SRadu Pirea (NXP OSS) 	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
1303b050f2f1SRadu Pirea (NXP OSS) 					 VEND1_DEVICE_CONTROL, ret,
1304b050f2f1SRadu Pirea (NXP OSS) 					 !(ret & DEVICE_CONTROL_RESET), 20000,
1305b050f2f1SRadu Pirea (NXP OSS) 					 240000, false);
1306b050f2f1SRadu Pirea (NXP OSS) }
1307b050f2f1SRadu Pirea (NXP OSS) 
1308b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev)
1309b050f2f1SRadu Pirea (NXP OSS) {
13106c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev);
13116c0c85daSRadu Pirea (NXP OSS) 
1312c552c110SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1313c552c110SRadu Pirea (NXP OSS) 			 VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE);
13146c0c85daSRadu Pirea (NXP OSS) 	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test,
1315b050f2f1SRadu Pirea (NXP OSS) 				CABLE_TEST_ENABLE | CABLE_TEST_START);
1316b050f2f1SRadu Pirea (NXP OSS) }
1317b050f2f1SRadu Pirea (NXP OSS) 
1318b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev,
1319b050f2f1SRadu Pirea (NXP OSS) 					 bool *finished)
1320b050f2f1SRadu Pirea (NXP OSS) {
13216c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev);
1322b050f2f1SRadu Pirea (NXP OSS) 	int ret;
1323b050f2f1SRadu Pirea (NXP OSS) 	u8 cable_test_result;
1324b050f2f1SRadu Pirea (NXP OSS) 
13256c0c85daSRadu Pirea (NXP OSS) 	ret = nxp_c45_read_reg_field(phydev, &regmap->cable_test_valid);
13266c0c85daSRadu Pirea (NXP OSS) 	if (!ret) {
1327b050f2f1SRadu Pirea (NXP OSS) 		*finished = false;
1328b050f2f1SRadu Pirea (NXP OSS) 		return 0;
1329b050f2f1SRadu Pirea (NXP OSS) 	}
1330b050f2f1SRadu Pirea (NXP OSS) 
1331b050f2f1SRadu Pirea (NXP OSS) 	*finished = true;
13326c0c85daSRadu Pirea (NXP OSS) 	cable_test_result = nxp_c45_read_reg_field(phydev,
13336c0c85daSRadu Pirea (NXP OSS) 						   &regmap->cable_test_result);
1334b050f2f1SRadu Pirea (NXP OSS) 
1335b050f2f1SRadu Pirea (NXP OSS) 	switch (cable_test_result) {
1336b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_OK:
1337b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
1338b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_OK);
1339b050f2f1SRadu Pirea (NXP OSS) 		break;
1340b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_SHORTED:
1341b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
1342b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT);
1343b050f2f1SRadu Pirea (NXP OSS) 		break;
1344b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_OPEN:
1345b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
1346b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_OPEN);
1347b050f2f1SRadu Pirea (NXP OSS) 		break;
1348b050f2f1SRadu Pirea (NXP OSS) 	default:
1349b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
1350b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC);
1351b050f2f1SRadu Pirea (NXP OSS) 	}
1352b050f2f1SRadu Pirea (NXP OSS) 
13536c0c85daSRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test,
1354b050f2f1SRadu Pirea (NXP OSS) 			   CABLE_TEST_ENABLE);
1355c552c110SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1356c552c110SRadu Pirea (NXP OSS) 			   VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE);
1357b050f2f1SRadu Pirea (NXP OSS) 
1358b050f2f1SRadu Pirea (NXP OSS) 	return nxp_c45_start_op(phydev);
1359b050f2f1SRadu Pirea (NXP OSS) }
1360b050f2f1SRadu Pirea (NXP OSS) 
1361b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev)
1362b050f2f1SRadu Pirea (NXP OSS) {
1363b050f2f1SRadu Pirea (NXP OSS) 	int reg;
1364b050f2f1SRadu Pirea (NXP OSS) 
1365b050f2f1SRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY);
1366b050f2f1SRadu Pirea (NXP OSS) 	if (!(reg & SQI_VALID))
1367b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
1368b050f2f1SRadu Pirea (NXP OSS) 
1369b050f2f1SRadu Pirea (NXP OSS) 	reg &= SQI_MASK;
1370b050f2f1SRadu Pirea (NXP OSS) 
1371b050f2f1SRadu Pirea (NXP OSS) 	return reg;
1372b050f2f1SRadu Pirea (NXP OSS) }
1373b050f2f1SRadu Pirea (NXP OSS) 
1374b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev)
1375b050f2f1SRadu Pirea (NXP OSS) {
1376b050f2f1SRadu Pirea (NXP OSS) 	return MAX_SQI;
1377b050f2f1SRadu Pirea (NXP OSS) }
1378b050f2f1SRadu Pirea (NXP OSS) 
1379b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay)
1380b050f2f1SRadu Pirea (NXP OSS) {
1381b050f2f1SRadu Pirea (NXP OSS) 	if (delay < MIN_ID_PS) {
1382b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS);
1383b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
1384b050f2f1SRadu Pirea (NXP OSS) 	}
1385b050f2f1SRadu Pirea (NXP OSS) 
1386b050f2f1SRadu Pirea (NXP OSS) 	if (delay > MAX_ID_PS) {
1387b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS);
1388b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
1389b050f2f1SRadu Pirea (NXP OSS) 	}
1390b050f2f1SRadu Pirea (NXP OSS) 
1391b050f2f1SRadu Pirea (NXP OSS) 	return 0;
1392b050f2f1SRadu Pirea (NXP OSS) }
1393b050f2f1SRadu Pirea (NXP OSS) 
13946c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_counters_enable(struct phy_device *phydev)
13956c0c85daSRadu Pirea (NXP OSS) {
13966c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev);
13976c0c85daSRadu Pirea (NXP OSS) 
13986c0c85daSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER,
13996c0c85daSRadu Pirea (NXP OSS) 			 COUNTER_EN);
14006c0c85daSRadu Pirea (NXP OSS) 
14016c0c85daSRadu Pirea (NXP OSS) 	data->counters_enable(phydev);
14026c0c85daSRadu Pirea (NXP OSS) }
14036c0c85daSRadu Pirea (NXP OSS) 
14046c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_ptp_init(struct phy_device *phydev)
14056c0c85daSRadu Pirea (NXP OSS) {
14066c0c85daSRadu Pirea (NXP OSS) 	const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev);
14076c0c85daSRadu Pirea (NXP OSS) 
14086c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1,
14096c0c85daSRadu Pirea (NXP OSS) 		      data->regmap->vend1_ptp_clk_period,
14106c0c85daSRadu Pirea (NXP OSS) 		      data->ptp_clk_period);
14116c0c85daSRadu Pirea (NXP OSS) 	nxp_c45_clear_reg_field(phydev, &data->regmap->ltc_lock_ctrl);
14126c0c85daSRadu Pirea (NXP OSS) 
14136c0c85daSRadu Pirea (NXP OSS) 	data->ptp_init(phydev);
14146c0c85daSRadu Pirea (NXP OSS) }
14156c0c85daSRadu Pirea (NXP OSS) 
1416b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw)
1417b050f2f1SRadu Pirea (NXP OSS) {
1418b050f2f1SRadu Pirea (NXP OSS) 	/* The delay in degree phase is 73.8 + phase_offset_raw * 0.9.
1419b050f2f1SRadu Pirea (NXP OSS) 	 * To avoid floating point operations we'll multiply by 10
1420b050f2f1SRadu Pirea (NXP OSS) 	 * and get 1 decimal point precision.
1421b050f2f1SRadu Pirea (NXP OSS) 	 */
1422b050f2f1SRadu Pirea (NXP OSS) 	phase_offset_raw *= 10;
14236b3a6310SRadu Pirea (NXP OSS) 	phase_offset_raw -= 738;
1424b050f2f1SRadu Pirea (NXP OSS) 	return div_u64(phase_offset_raw, 9);
1425b050f2f1SRadu Pirea (NXP OSS) }
1426b050f2f1SRadu Pirea (NXP OSS) 
1427b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev)
1428b050f2f1SRadu Pirea (NXP OSS) {
1429b050f2f1SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE);
1430b050f2f1SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE);
1431b050f2f1SRadu Pirea (NXP OSS) }
1432b050f2f1SRadu Pirea (NXP OSS) 
1433b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev)
1434b050f2f1SRadu Pirea (NXP OSS) {
1435b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = phydev->priv;
1436b050f2f1SRadu Pirea (NXP OSS) 	u64 tx_delay = priv->tx_delay;
1437b050f2f1SRadu Pirea (NXP OSS) 	u64 rx_delay = priv->rx_delay;
1438b050f2f1SRadu Pirea (NXP OSS) 	u64 degree;
1439b050f2f1SRadu Pirea (NXP OSS) 
1440b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
1441b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
1442b050f2f1SRadu Pirea (NXP OSS) 		degree = div_u64(tx_delay, PS_PER_DEGREE);
1443b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
1444b050f2f1SRadu Pirea (NXP OSS) 			      ID_ENABLE | nxp_c45_get_phase_shift(degree));
1445b050f2f1SRadu Pirea (NXP OSS) 	} else {
1446b050f2f1SRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
1447b050f2f1SRadu Pirea (NXP OSS) 				   ID_ENABLE);
1448b050f2f1SRadu Pirea (NXP OSS) 	}
1449b050f2f1SRadu Pirea (NXP OSS) 
1450b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
1451b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
1452b050f2f1SRadu Pirea (NXP OSS) 		degree = div_u64(rx_delay, PS_PER_DEGREE);
1453b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
1454b050f2f1SRadu Pirea (NXP OSS) 			      ID_ENABLE | nxp_c45_get_phase_shift(degree));
1455b050f2f1SRadu Pirea (NXP OSS) 	} else {
1456b050f2f1SRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
1457b050f2f1SRadu Pirea (NXP OSS) 				   ID_ENABLE);
1458b050f2f1SRadu Pirea (NXP OSS) 	}
1459b050f2f1SRadu Pirea (NXP OSS) }
1460b050f2f1SRadu Pirea (NXP OSS) 
1461b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev)
1462b050f2f1SRadu Pirea (NXP OSS) {
1463b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = phydev->priv;
1464b050f2f1SRadu Pirea (NXP OSS) 	int ret;
1465b050f2f1SRadu Pirea (NXP OSS) 
1466b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
1467b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
1468b050f2f1SRadu Pirea (NXP OSS) 		ret = device_property_read_u32(&phydev->mdio.dev,
1469b050f2f1SRadu Pirea (NXP OSS) 					       "tx-internal-delay-ps",
1470b050f2f1SRadu Pirea (NXP OSS) 					       &priv->tx_delay);
1471b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
1472b050f2f1SRadu Pirea (NXP OSS) 			priv->tx_delay = DEFAULT_ID_PS;
1473b050f2f1SRadu Pirea (NXP OSS) 
1474b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_check_delay(phydev, priv->tx_delay);
1475b050f2f1SRadu Pirea (NXP OSS) 		if (ret) {
1476b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev,
1477b050f2f1SRadu Pirea (NXP OSS) 				   "tx-internal-delay-ps invalid value\n");
1478b050f2f1SRadu Pirea (NXP OSS) 			return ret;
1479b050f2f1SRadu Pirea (NXP OSS) 		}
1480b050f2f1SRadu Pirea (NXP OSS) 	}
1481b050f2f1SRadu Pirea (NXP OSS) 
1482b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
1483b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
1484b050f2f1SRadu Pirea (NXP OSS) 		ret = device_property_read_u32(&phydev->mdio.dev,
1485b050f2f1SRadu Pirea (NXP OSS) 					       "rx-internal-delay-ps",
1486b050f2f1SRadu Pirea (NXP OSS) 					       &priv->rx_delay);
1487b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
1488b050f2f1SRadu Pirea (NXP OSS) 			priv->rx_delay = DEFAULT_ID_PS;
1489b050f2f1SRadu Pirea (NXP OSS) 
1490b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_check_delay(phydev, priv->rx_delay);
1491b050f2f1SRadu Pirea (NXP OSS) 		if (ret) {
1492b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev,
1493b050f2f1SRadu Pirea (NXP OSS) 				   "rx-internal-delay-ps invalid value\n");
1494b050f2f1SRadu Pirea (NXP OSS) 			return ret;
1495b050f2f1SRadu Pirea (NXP OSS) 		}
1496b050f2f1SRadu Pirea (NXP OSS) 	}
1497b050f2f1SRadu Pirea (NXP OSS) 
1498b050f2f1SRadu Pirea (NXP OSS) 	return 0;
1499b050f2f1SRadu Pirea (NXP OSS) }
1500b050f2f1SRadu Pirea (NXP OSS) 
1501b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev)
1502b050f2f1SRadu Pirea (NXP OSS) {
1503b050f2f1SRadu Pirea (NXP OSS) 	int ret;
1504b050f2f1SRadu Pirea (NXP OSS) 
1505b050f2f1SRadu Pirea (NXP OSS) 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES);
1506b050f2f1SRadu Pirea (NXP OSS) 	phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret);
1507b050f2f1SRadu Pirea (NXP OSS) 
1508b050f2f1SRadu Pirea (NXP OSS) 	switch (phydev->interface) {
1509b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII:
1510b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RGMII_ABILITY)) {
1511b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rgmii mode not supported\n");
1512b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
1513b050f2f1SRadu Pirea (NXP OSS) 		}
1514b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1515b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RGMII);
1516b050f2f1SRadu Pirea (NXP OSS) 		nxp_c45_disable_delays(phydev);
1517b050f2f1SRadu Pirea (NXP OSS) 		break;
1518b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_ID:
1519b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_TXID:
1520b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_RXID:
1521b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RGMII_ID_ABILITY)) {
1522b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n");
1523b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
1524b050f2f1SRadu Pirea (NXP OSS) 		}
1525b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1526b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RGMII);
1527b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_get_delays(phydev);
1528b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
1529b050f2f1SRadu Pirea (NXP OSS) 			return ret;
1530b050f2f1SRadu Pirea (NXP OSS) 
1531b050f2f1SRadu Pirea (NXP OSS) 		nxp_c45_set_delays(phydev);
1532b050f2f1SRadu Pirea (NXP OSS) 		break;
1533b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_MII:
1534b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & MII_ABILITY)) {
1535b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "mii mode not supported\n");
1536b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
1537b050f2f1SRadu Pirea (NXP OSS) 		}
1538b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1539b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_MII);
1540b050f2f1SRadu Pirea (NXP OSS) 		break;
1541b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_REVMII:
1542b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & REVMII_ABILITY)) {
1543b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rev-mii mode not supported\n");
1544b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
1545b050f2f1SRadu Pirea (NXP OSS) 		}
1546b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1547b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_MII | MII_BASIC_CONFIG_REV);
1548b050f2f1SRadu Pirea (NXP OSS) 		break;
1549b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RMII:
1550b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RMII_ABILITY)) {
1551b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rmii mode not supported\n");
1552b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
1553b050f2f1SRadu Pirea (NXP OSS) 		}
1554b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1555b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RMII);
1556b050f2f1SRadu Pirea (NXP OSS) 		break;
1557b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_SGMII:
1558b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & SGMII_ABILITY)) {
1559b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "sgmii mode not supported\n");
1560b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
1561b050f2f1SRadu Pirea (NXP OSS) 		}
1562b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1563b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_SGMII);
1564b050f2f1SRadu Pirea (NXP OSS) 		break;
1565b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_INTERNAL:
1566b050f2f1SRadu Pirea (NXP OSS) 		break;
1567b050f2f1SRadu Pirea (NXP OSS) 	default:
1568b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
1569b050f2f1SRadu Pirea (NXP OSS) 	}
1570b050f2f1SRadu Pirea (NXP OSS) 
1571b050f2f1SRadu Pirea (NXP OSS) 	return 0;
1572b050f2f1SRadu Pirea (NXP OSS) }
1573b050f2f1SRadu Pirea (NXP OSS) 
1574b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev)
1575b050f2f1SRadu Pirea (NXP OSS) {
1576b050f2f1SRadu Pirea (NXP OSS) 	int ret;
1577b050f2f1SRadu Pirea (NXP OSS) 
1578b050f2f1SRadu Pirea (NXP OSS) 	ret = nxp_c45_config_enable(phydev);
1579b050f2f1SRadu Pirea (NXP OSS) 	if (ret) {
1580b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "Failed to enable config\n");
1581b050f2f1SRadu Pirea (NXP OSS) 		return ret;
1582b050f2f1SRadu Pirea (NXP OSS) 	}
1583b050f2f1SRadu Pirea (NXP OSS) 
15840b5f0f29SVladimir Oltean 	/* Bug workaround for SJA1110 rev B: enable write access
15850b5f0f29SVladimir Oltean 	 * to MDIO_MMD_PMAPMD
15860b5f0f29SVladimir Oltean 	 */
15870b5f0f29SVladimir Oltean 	phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1);
15880b5f0f29SVladimir Oltean 	phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2);
15890b5f0f29SVladimir Oltean 
1590b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG,
1591b050f2f1SRadu Pirea (NXP OSS) 			 PHY_CONFIG_AUTO);
1592b050f2f1SRadu Pirea (NXP OSS) 
1593b050f2f1SRadu Pirea (NXP OSS) 	ret = nxp_c45_set_phy_mode(phydev);
1594b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
1595b050f2f1SRadu Pirea (NXP OSS) 		return ret;
1596b050f2f1SRadu Pirea (NXP OSS) 
1597b050f2f1SRadu Pirea (NXP OSS) 	phydev->autoneg = AUTONEG_DISABLE;
1598b050f2f1SRadu Pirea (NXP OSS) 
15996c0c85daSRadu Pirea (NXP OSS) 	nxp_c45_counters_enable(phydev);
16006c0c85daSRadu Pirea (NXP OSS) 	nxp_c45_ptp_init(phydev);
1601514def5dSRadu Pirea (NXP OSS) 
1602b050f2f1SRadu Pirea (NXP OSS) 	return nxp_c45_start_op(phydev);
1603b050f2f1SRadu Pirea (NXP OSS) }
1604b050f2f1SRadu Pirea (NXP OSS) 
1605369da333SRadu Pirea (NXP OSS) static int nxp_c45_get_features(struct phy_device *phydev)
1606369da333SRadu Pirea (NXP OSS) {
1607369da333SRadu Pirea (NXP OSS) 	linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported);
1608369da333SRadu Pirea (NXP OSS) 	linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported);
1609369da333SRadu Pirea (NXP OSS) 
1610369da333SRadu Pirea (NXP OSS) 	return genphy_c45_pma_read_abilities(phydev);
1611369da333SRadu Pirea (NXP OSS) }
1612369da333SRadu Pirea (NXP OSS) 
1613b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev)
1614b050f2f1SRadu Pirea (NXP OSS) {
1615b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv;
1616514def5dSRadu Pirea (NXP OSS) 	int ptp_ability;
1617514def5dSRadu Pirea (NXP OSS) 	int ret = 0;
1618b050f2f1SRadu Pirea (NXP OSS) 
1619b050f2f1SRadu Pirea (NXP OSS) 	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
1620b050f2f1SRadu Pirea (NXP OSS) 	if (!priv)
1621b050f2f1SRadu Pirea (NXP OSS) 		return -ENOMEM;
1622b050f2f1SRadu Pirea (NXP OSS) 
1623514def5dSRadu Pirea (NXP OSS) 	skb_queue_head_init(&priv->tx_queue);
1624514def5dSRadu Pirea (NXP OSS) 	skb_queue_head_init(&priv->rx_queue);
1625514def5dSRadu Pirea (NXP OSS) 
1626514def5dSRadu Pirea (NXP OSS) 	priv->phydev = phydev;
1627514def5dSRadu Pirea (NXP OSS) 
1628b050f2f1SRadu Pirea (NXP OSS) 	phydev->priv = priv;
1629b050f2f1SRadu Pirea (NXP OSS) 
1630514def5dSRadu Pirea (NXP OSS) 	mutex_init(&priv->ptp_lock);
1631514def5dSRadu Pirea (NXP OSS) 
1632514def5dSRadu Pirea (NXP OSS) 	ptp_ability = phy_read_mmd(phydev, MDIO_MMD_VEND1,
1633514def5dSRadu Pirea (NXP OSS) 				   VEND1_PORT_ABILITIES);
1634514def5dSRadu Pirea (NXP OSS) 	ptp_ability = !!(ptp_ability & PTP_ABILITY);
1635514def5dSRadu Pirea (NXP OSS) 	if (!ptp_ability) {
1636565c6d8cSVladimir Oltean 		phydev_dbg(phydev, "the phy does not support PTP");
1637514def5dSRadu Pirea (NXP OSS) 		goto no_ptp_support;
1638514def5dSRadu Pirea (NXP OSS) 	}
1639514def5dSRadu Pirea (NXP OSS) 
1640514def5dSRadu Pirea (NXP OSS) 	if (IS_ENABLED(CONFIG_PTP_1588_CLOCK) &&
1641514def5dSRadu Pirea (NXP OSS) 	    IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) {
1642514def5dSRadu Pirea (NXP OSS) 		priv->mii_ts.rxtstamp = nxp_c45_rxtstamp;
1643514def5dSRadu Pirea (NXP OSS) 		priv->mii_ts.txtstamp = nxp_c45_txtstamp;
1644514def5dSRadu Pirea (NXP OSS) 		priv->mii_ts.hwtstamp = nxp_c45_hwtstamp;
1645514def5dSRadu Pirea (NXP OSS) 		priv->mii_ts.ts_info = nxp_c45_ts_info;
1646514def5dSRadu Pirea (NXP OSS) 		phydev->mii_ts = &priv->mii_ts;
1647514def5dSRadu Pirea (NXP OSS) 		ret = nxp_c45_init_ptp_clock(priv);
1648514def5dSRadu Pirea (NXP OSS) 	} else {
1649514def5dSRadu Pirea (NXP OSS) 		phydev_dbg(phydev, "PTP support not enabled even if the phy supports it");
1650514def5dSRadu Pirea (NXP OSS) 	}
1651514def5dSRadu Pirea (NXP OSS) 
1652514def5dSRadu Pirea (NXP OSS) no_ptp_support:
1653514def5dSRadu Pirea (NXP OSS) 
1654514def5dSRadu Pirea (NXP OSS) 	return ret;
1655b050f2f1SRadu Pirea (NXP OSS) }
1656b050f2f1SRadu Pirea (NXP OSS) 
1657a4506722SRadu Pirea (OSS) static void nxp_c45_remove(struct phy_device *phydev)
1658a4506722SRadu Pirea (OSS) {
1659a4506722SRadu Pirea (OSS) 	struct nxp_c45_phy *priv = phydev->priv;
1660a4506722SRadu Pirea (OSS) 
1661a4506722SRadu Pirea (OSS) 	if (priv->ptp_clock)
1662a4506722SRadu Pirea (OSS) 		ptp_clock_unregister(priv->ptp_clock);
1663a4506722SRadu Pirea (OSS) 
1664a4506722SRadu Pirea (OSS) 	skb_queue_purge(&priv->tx_queue);
1665a4506722SRadu Pirea (OSS) 	skb_queue_purge(&priv->rx_queue);
1666a4506722SRadu Pirea (OSS) }
1667a4506722SRadu Pirea (OSS) 
16686c0c85daSRadu Pirea (NXP OSS) static void tja1103_counters_enable(struct phy_device *phydev)
16696c0c85daSRadu Pirea (NXP OSS) {
16706c0c85daSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT,
16716c0c85daSRadu Pirea (NXP OSS) 			 COUNTER_EN);
16726c0c85daSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT,
16736c0c85daSRadu Pirea (NXP OSS) 			 COUNTER_EN);
16746c0c85daSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH,
16756c0c85daSRadu Pirea (NXP OSS) 			 COUNTER_EN);
16766c0c85daSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH,
16776c0c85daSRadu Pirea (NXP OSS) 			 COUNTER_EN);
16786c0c85daSRadu Pirea (NXP OSS) }
16796c0c85daSRadu Pirea (NXP OSS) 
16806c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_init(struct phy_device *phydev)
16816c0c85daSRadu Pirea (NXP OSS) {
16826c0c85daSRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL,
16836c0c85daSRadu Pirea (NXP OSS) 		      TJA1103_RX_TS_INSRT_MODE2);
16846c0c85daSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES,
16856c0c85daSRadu Pirea (NXP OSS) 			 PTP_ENABLE);
16866c0c85daSRadu Pirea (NXP OSS) }
16876c0c85daSRadu Pirea (NXP OSS) 
16886c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_enable(struct phy_device *phydev, bool enable)
16896c0c85daSRadu Pirea (NXP OSS) {
16906c0c85daSRadu Pirea (NXP OSS) 	if (enable)
16916c0c85daSRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
16926c0c85daSRadu Pirea (NXP OSS) 				   VEND1_PORT_PTP_CONTROL,
16936c0c85daSRadu Pirea (NXP OSS) 				   PORT_PTP_CONTROL_BYPASS);
16946c0c85daSRadu Pirea (NXP OSS) 	else
16956c0c85daSRadu Pirea (NXP OSS) 		phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
16966c0c85daSRadu Pirea (NXP OSS) 				 VEND1_PORT_PTP_CONTROL,
16976c0c85daSRadu Pirea (NXP OSS) 				 PORT_PTP_CONTROL_BYPASS);
16986c0c85daSRadu Pirea (NXP OSS) }
16996c0c85daSRadu Pirea (NXP OSS) 
1700425c8348SRadu Pirea (NXP OSS) static void tja1103_nmi_handler(struct phy_device *phydev,
1701425c8348SRadu Pirea (NXP OSS) 				irqreturn_t *irq_status)
1702425c8348SRadu Pirea (NXP OSS) {
1703425c8348SRadu Pirea (NXP OSS) 	int ret;
1704425c8348SRadu Pirea (NXP OSS) 
1705425c8348SRadu Pirea (NXP OSS) 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1,
1706425c8348SRadu Pirea (NXP OSS) 			   VEND1_ALWAYS_ACCESSIBLE);
1707425c8348SRadu Pirea (NXP OSS) 	if (ret & FUSA_PASS) {
1708425c8348SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1,
1709425c8348SRadu Pirea (NXP OSS) 			      VEND1_ALWAYS_ACCESSIBLE,
1710425c8348SRadu Pirea (NXP OSS) 			      FUSA_PASS);
1711425c8348SRadu Pirea (NXP OSS) 		*irq_status = IRQ_HANDLED;
1712425c8348SRadu Pirea (NXP OSS) 	}
1713425c8348SRadu Pirea (NXP OSS) }
1714425c8348SRadu Pirea (NXP OSS) 
17156c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1103_regmap = {
17166c0c85daSRadu Pirea (NXP OSS) 	.vend1_ptp_clk_period	= 0x1104,
17176c0c85daSRadu Pirea (NXP OSS) 	.vend1_event_msg_filt	= 0x1148,
17186c0c85daSRadu Pirea (NXP OSS) 	.pps_enable		=
17196c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 3, 1),
17206c0c85daSRadu Pirea (NXP OSS) 	.pps_polarity		=
17216c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 2, 1),
17226c0c85daSRadu Pirea (NXP OSS) 	.ltc_lock_ctrl		=
17236c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1115, MDIO_MMD_VEND1, 0, 1),
17246c0c85daSRadu Pirea (NXP OSS) 	.ltc_read		=
17256c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 2, 1),
17266c0c85daSRadu Pirea (NXP OSS) 	.ltc_write		=
17276c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 0, 1),
17286c0c85daSRadu Pirea (NXP OSS) 	.vend1_ltc_wr_nsec_0	= 0x1106,
17296c0c85daSRadu Pirea (NXP OSS) 	.vend1_ltc_wr_nsec_1	= 0x1107,
17306c0c85daSRadu Pirea (NXP OSS) 	.vend1_ltc_wr_sec_0	= 0x1108,
17316c0c85daSRadu Pirea (NXP OSS) 	.vend1_ltc_wr_sec_1	= 0x1109,
17326c0c85daSRadu Pirea (NXP OSS) 	.vend1_ltc_rd_nsec_0	= 0x110A,
17336c0c85daSRadu Pirea (NXP OSS) 	.vend1_ltc_rd_nsec_1	= 0x110B,
17346c0c85daSRadu Pirea (NXP OSS) 	.vend1_ltc_rd_sec_0	= 0x110C,
17356c0c85daSRadu Pirea (NXP OSS) 	.vend1_ltc_rd_sec_1	= 0x110D,
17366c0c85daSRadu Pirea (NXP OSS) 	.vend1_rate_adj_subns_0	= 0x110F,
17376c0c85daSRadu Pirea (NXP OSS) 	.vend1_rate_adj_subns_1	= 0x1110,
17386c0c85daSRadu Pirea (NXP OSS) 	.irq_egr_ts_en		=
17396c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1131, MDIO_MMD_VEND1, 0, 1),
17406c0c85daSRadu Pirea (NXP OSS) 	.irq_egr_ts_status	=
17416c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1132, MDIO_MMD_VEND1, 0, 1),
17426c0c85daSRadu Pirea (NXP OSS) 	.domain_number		=
17436c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 0, 8),
17446c0c85daSRadu Pirea (NXP OSS) 	.msg_type		=
17456c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 8, 4),
17466c0c85daSRadu Pirea (NXP OSS) 	.sequence_id		=
17476c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x114F, MDIO_MMD_VEND1, 0, 16),
17486c0c85daSRadu Pirea (NXP OSS) 	.sec_1_0		=
17496c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 14, 2),
17506c0c85daSRadu Pirea (NXP OSS) 	.sec_4_2		=
17516c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 12, 3),
17526c0c85daSRadu Pirea (NXP OSS) 	.nsec_15_0		=
17536c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1150, MDIO_MMD_VEND1, 0, 16),
17546c0c85daSRadu Pirea (NXP OSS) 	.nsec_29_16		=
17556c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 0, 14),
17566c0c85daSRadu Pirea (NXP OSS) 	.vend1_ext_trg_data_0	= 0x1121,
17576c0c85daSRadu Pirea (NXP OSS) 	.vend1_ext_trg_data_1	= 0x1122,
17586c0c85daSRadu Pirea (NXP OSS) 	.vend1_ext_trg_data_2	= 0x1123,
17596c0c85daSRadu Pirea (NXP OSS) 	.vend1_ext_trg_data_3	= 0x1124,
17606c0c85daSRadu Pirea (NXP OSS) 	.vend1_ext_trg_ctrl	= 0x1126,
17616c0c85daSRadu Pirea (NXP OSS) 	.cable_test		= 0x8330,
17626c0c85daSRadu Pirea (NXP OSS) 	.cable_test_valid	=
17636c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 13, 1),
17646c0c85daSRadu Pirea (NXP OSS) 	.cable_test_result	=
17656c0c85daSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 0, 3),
17666c0c85daSRadu Pirea (NXP OSS) };
17676c0c85daSRadu Pirea (NXP OSS) 
17686c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1103_phy_data = {
17696c0c85daSRadu Pirea (NXP OSS) 	.regmap = &tja1103_regmap,
17706c0c85daSRadu Pirea (NXP OSS) 	.stats = tja1103_hw_stats,
17716c0c85daSRadu Pirea (NXP OSS) 	.n_stats = ARRAY_SIZE(tja1103_hw_stats),
17726c0c85daSRadu Pirea (NXP OSS) 	.ptp_clk_period = PTP_CLK_PERIOD_100BT1,
1773b0b2247dSRadu Pirea (NXP OSS) 	.ext_ts_both_edges = false,
1774bdb4c5b8SRadu Pirea (NXP OSS) 	.ack_ptp_irq = false,
17756c0c85daSRadu Pirea (NXP OSS) 	.counters_enable = tja1103_counters_enable,
1776bdb4c5b8SRadu Pirea (NXP OSS) 	.get_egressts = nxp_c45_get_hwtxts,
1777*08e6547cSRadu Pirea (NXP OSS) 	.get_extts = nxp_c45_get_extts,
17786c0c85daSRadu Pirea (NXP OSS) 	.ptp_init = tja1103_ptp_init,
17796c0c85daSRadu Pirea (NXP OSS) 	.ptp_enable = tja1103_ptp_enable,
1780425c8348SRadu Pirea (NXP OSS) 	.nmi_handler = tja1103_nmi_handler,
17816c0c85daSRadu Pirea (NXP OSS) };
17826c0c85daSRadu Pirea (NXP OSS) 
1783f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_counters_enable(struct phy_device *phydev)
1784f1fe5dffSRadu Pirea (NXP OSS) {
1785f1fe5dffSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_SYMBOL_ERROR_CNT_XTD,
1786f1fe5dffSRadu Pirea (NXP OSS) 			 EXTENDED_CNT_EN);
1787f1fe5dffSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_STATUS,
1788f1fe5dffSRadu Pirea (NXP OSS) 			 MONITOR_RESET);
1789f1fe5dffSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_CONFIG,
1790f1fe5dffSRadu Pirea (NXP OSS) 			 ALL_FRAMES_CNT_EN | LOST_FRAMES_CNT_EN);
1791f1fe5dffSRadu Pirea (NXP OSS) }
1792f1fe5dffSRadu Pirea (NXP OSS) 
1793f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_init(struct phy_device *phydev)
1794f1fe5dffSRadu Pirea (NXP OSS) {
1795f1fe5dffSRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_RX_TS_INSRT_CTRL,
1796f1fe5dffSRadu Pirea (NXP OSS) 		      TJA1120_RX_TS_INSRT_EN | TJA1120_TS_INSRT_MODE);
1797f1fe5dffSRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_VEND1_EXT_TS_MODE,
1798f1fe5dffSRadu Pirea (NXP OSS) 		      TJA1120_TS_INSRT_MODE);
1799f1fe5dffSRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONFIG,
1800f1fe5dffSRadu Pirea (NXP OSS) 			 PTP_ENABLE);
1801f1fe5dffSRadu Pirea (NXP OSS) }
1802f1fe5dffSRadu Pirea (NXP OSS) 
1803f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_enable(struct phy_device *phydev, bool enable)
1804f1fe5dffSRadu Pirea (NXP OSS) {
1805f1fe5dffSRadu Pirea (NXP OSS) 	if (enable)
1806f1fe5dffSRadu Pirea (NXP OSS) 		phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1807f1fe5dffSRadu Pirea (NXP OSS) 				 VEND1_PORT_FUNC_ENABLES,
1808f1fe5dffSRadu Pirea (NXP OSS) 				 PTP_ENABLE);
1809f1fe5dffSRadu Pirea (NXP OSS) 	else
1810f1fe5dffSRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1811f1fe5dffSRadu Pirea (NXP OSS) 				   VEND1_PORT_FUNC_ENABLES,
1812f1fe5dffSRadu Pirea (NXP OSS) 				   PTP_ENABLE);
1813f1fe5dffSRadu Pirea (NXP OSS) }
1814f1fe5dffSRadu Pirea (NXP OSS) 
1815425c8348SRadu Pirea (NXP OSS) static void tja1120_nmi_handler(struct phy_device *phydev,
1816425c8348SRadu Pirea (NXP OSS) 				irqreturn_t *irq_status)
1817425c8348SRadu Pirea (NXP OSS) {
1818425c8348SRadu Pirea (NXP OSS) 	int ret;
1819425c8348SRadu Pirea (NXP OSS) 
1820425c8348SRadu Pirea (NXP OSS) 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1,
1821425c8348SRadu Pirea (NXP OSS) 			   TJA1120_GLOBAL_INFRA_IRQ_STATUS);
1822425c8348SRadu Pirea (NXP OSS) 	if (ret & TJA1120_DEV_BOOT_DONE) {
1823425c8348SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1,
1824425c8348SRadu Pirea (NXP OSS) 			      TJA1120_GLOBAL_INFRA_IRQ_ACK,
1825425c8348SRadu Pirea (NXP OSS) 			      TJA1120_DEV_BOOT_DONE);
1826425c8348SRadu Pirea (NXP OSS) 		*irq_status = IRQ_HANDLED;
1827425c8348SRadu Pirea (NXP OSS) 	}
1828425c8348SRadu Pirea (NXP OSS) }
1829425c8348SRadu Pirea (NXP OSS) 
1830f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1120_regmap = {
1831f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ptp_clk_period	= 0x1020,
1832f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_event_msg_filt	= 0x9010,
1833f1fe5dffSRadu Pirea (NXP OSS) 	.pps_enable		=
1834f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 4, 1),
1835f1fe5dffSRadu Pirea (NXP OSS) 	.pps_polarity		=
1836f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 5, 1),
1837f1fe5dffSRadu Pirea (NXP OSS) 	.ltc_lock_ctrl		=
1838f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 2, 1),
1839f1fe5dffSRadu Pirea (NXP OSS) 	.ltc_read		=
1840f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 1, 1),
1841f1fe5dffSRadu Pirea (NXP OSS) 	.ltc_write		=
1842f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 2, 1),
1843f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ltc_wr_nsec_0	= 0x1040,
1844f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ltc_wr_nsec_1	= 0x1041,
1845f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ltc_wr_sec_0	= 0x1042,
1846f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ltc_wr_sec_1	= 0x1043,
1847f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ltc_rd_nsec_0	= 0x1048,
1848f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ltc_rd_nsec_1	= 0x1049,
1849f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ltc_rd_sec_0	= 0x104A,
1850f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ltc_rd_sec_1	= 0x104B,
1851f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_rate_adj_subns_0	= 0x1030,
1852f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_rate_adj_subns_1	= 0x1031,
1853f1fe5dffSRadu Pirea (NXP OSS) 	.irq_egr_ts_en		=
1854f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x900A, MDIO_MMD_VEND1, 1, 1),
1855f1fe5dffSRadu Pirea (NXP OSS) 	.irq_egr_ts_status	=
1856f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x900C, MDIO_MMD_VEND1, 1, 1),
1857f1fe5dffSRadu Pirea (NXP OSS) 	.domain_number		=
1858f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 8, 8),
1859f1fe5dffSRadu Pirea (NXP OSS) 	.msg_type		=
1860f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 4, 4),
1861f1fe5dffSRadu Pirea (NXP OSS) 	.sequence_id		=
1862f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x9062, MDIO_MMD_VEND1, 0, 16),
1863f1fe5dffSRadu Pirea (NXP OSS) 	.sec_1_0		=
1864f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 0, 2),
1865f1fe5dffSRadu Pirea (NXP OSS) 	.sec_4_2		=
1866f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 2, 3),
1867f1fe5dffSRadu Pirea (NXP OSS) 	.nsec_15_0		=
1868f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x9063, MDIO_MMD_VEND1, 0, 16),
1869f1fe5dffSRadu Pirea (NXP OSS) 	.nsec_29_16		=
1870f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x9064, MDIO_MMD_VEND1, 0, 14),
1871f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ext_trg_data_0	= 0x1071,
1872f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ext_trg_data_1	= 0x1072,
1873f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ext_trg_data_2	= 0x1073,
1874f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ext_trg_data_3	= 0x1074,
1875f1fe5dffSRadu Pirea (NXP OSS) 	.vend1_ext_trg_ctrl	= 0x1075,
1876f1fe5dffSRadu Pirea (NXP OSS) 	.cable_test		= 0x8360,
1877f1fe5dffSRadu Pirea (NXP OSS) 	.cable_test_valid	=
1878f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 15, 1),
1879f1fe5dffSRadu Pirea (NXP OSS) 	.cable_test_result	=
1880f1fe5dffSRadu Pirea (NXP OSS) 		NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 0, 3),
1881f1fe5dffSRadu Pirea (NXP OSS) };
1882f1fe5dffSRadu Pirea (NXP OSS) 
1883f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1120_phy_data = {
1884f1fe5dffSRadu Pirea (NXP OSS) 	.regmap = &tja1120_regmap,
1885f1fe5dffSRadu Pirea (NXP OSS) 	.stats = tja1120_hw_stats,
1886f1fe5dffSRadu Pirea (NXP OSS) 	.n_stats = ARRAY_SIZE(tja1120_hw_stats),
1887f1fe5dffSRadu Pirea (NXP OSS) 	.ptp_clk_period = PTP_CLK_PERIOD_1000BT1,
1888b0b2247dSRadu Pirea (NXP OSS) 	.ext_ts_both_edges = true,
1889bdb4c5b8SRadu Pirea (NXP OSS) 	.ack_ptp_irq = true,
1890f1fe5dffSRadu Pirea (NXP OSS) 	.counters_enable = tja1120_counters_enable,
1891bdb4c5b8SRadu Pirea (NXP OSS) 	.get_egressts = tja1120_get_hwtxts,
1892*08e6547cSRadu Pirea (NXP OSS) 	.get_extts = tja1120_get_extts,
1893f1fe5dffSRadu Pirea (NXP OSS) 	.ptp_init = tja1120_ptp_init,
1894f1fe5dffSRadu Pirea (NXP OSS) 	.ptp_enable = tja1120_ptp_enable,
1895425c8348SRadu Pirea (NXP OSS) 	.nmi_handler = tja1120_nmi_handler,
1896f1fe5dffSRadu Pirea (NXP OSS) };
1897f1fe5dffSRadu Pirea (NXP OSS) 
1898b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = {
1899b050f2f1SRadu Pirea (NXP OSS) 	{
1900b050f2f1SRadu Pirea (NXP OSS) 		PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
1901b050f2f1SRadu Pirea (NXP OSS) 		.name			= "NXP C45 TJA1103",
1902369da333SRadu Pirea (NXP OSS) 		.get_features		= nxp_c45_get_features,
19036c0c85daSRadu Pirea (NXP OSS) 		.driver_data		= &tja1103_phy_data,
1904b050f2f1SRadu Pirea (NXP OSS) 		.probe			= nxp_c45_probe,
1905b050f2f1SRadu Pirea (NXP OSS) 		.soft_reset		= nxp_c45_soft_reset,
1906ac0687e8SRadu Pirea (NXP OSS) 		.config_aneg		= genphy_c45_config_aneg,
1907b050f2f1SRadu Pirea (NXP OSS) 		.config_init		= nxp_c45_config_init,
1908425c8348SRadu Pirea (NXP OSS) 		.config_intr		= tja1103_config_intr,
1909b2f0ca00SRadu Pirea (NXP OSS) 		.handle_interrupt	= nxp_c45_handle_interrupt,
1910ac0687e8SRadu Pirea (NXP OSS) 		.read_status		= genphy_c45_read_status,
1911b050f2f1SRadu Pirea (NXP OSS) 		.suspend		= genphy_c45_pma_suspend,
1912b050f2f1SRadu Pirea (NXP OSS) 		.resume			= genphy_c45_pma_resume,
1913b050f2f1SRadu Pirea (NXP OSS) 		.get_sset_count		= nxp_c45_get_sset_count,
1914b050f2f1SRadu Pirea (NXP OSS) 		.get_strings		= nxp_c45_get_strings,
1915b050f2f1SRadu Pirea (NXP OSS) 		.get_stats		= nxp_c45_get_stats,
1916b050f2f1SRadu Pirea (NXP OSS) 		.cable_test_start	= nxp_c45_cable_test_start,
1917b050f2f1SRadu Pirea (NXP OSS) 		.cable_test_get_status	= nxp_c45_cable_test_get_status,
1918b050f2f1SRadu Pirea (NXP OSS) 		.set_loopback		= genphy_c45_loopback,
1919b050f2f1SRadu Pirea (NXP OSS) 		.get_sqi		= nxp_c45_get_sqi,
1920b050f2f1SRadu Pirea (NXP OSS) 		.get_sqi_max		= nxp_c45_get_sqi_max,
1921a4506722SRadu Pirea (OSS) 		.remove			= nxp_c45_remove,
1922b050f2f1SRadu Pirea (NXP OSS) 	},
1923f1fe5dffSRadu Pirea (NXP OSS) 	{
1924f1fe5dffSRadu Pirea (NXP OSS) 		PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120),
1925f1fe5dffSRadu Pirea (NXP OSS) 		.name			= "NXP C45 TJA1120",
1926f1fe5dffSRadu Pirea (NXP OSS) 		.get_features		= nxp_c45_get_features,
1927f1fe5dffSRadu Pirea (NXP OSS) 		.driver_data		= &tja1120_phy_data,
1928f1fe5dffSRadu Pirea (NXP OSS) 		.probe			= nxp_c45_probe,
1929f1fe5dffSRadu Pirea (NXP OSS) 		.soft_reset		= nxp_c45_soft_reset,
1930f1fe5dffSRadu Pirea (NXP OSS) 		.config_aneg		= genphy_c45_config_aneg,
1931f1fe5dffSRadu Pirea (NXP OSS) 		.config_init		= nxp_c45_config_init,
1932425c8348SRadu Pirea (NXP OSS) 		.config_intr		= tja1120_config_intr,
1933f1fe5dffSRadu Pirea (NXP OSS) 		.handle_interrupt	= nxp_c45_handle_interrupt,
1934f1fe5dffSRadu Pirea (NXP OSS) 		.read_status		= genphy_c45_read_status,
1935f1fe5dffSRadu Pirea (NXP OSS) 		.suspend		= genphy_c45_pma_suspend,
1936f1fe5dffSRadu Pirea (NXP OSS) 		.resume			= genphy_c45_pma_resume,
1937f1fe5dffSRadu Pirea (NXP OSS) 		.get_sset_count		= nxp_c45_get_sset_count,
1938f1fe5dffSRadu Pirea (NXP OSS) 		.get_strings		= nxp_c45_get_strings,
1939f1fe5dffSRadu Pirea (NXP OSS) 		.get_stats		= nxp_c45_get_stats,
1940f1fe5dffSRadu Pirea (NXP OSS) 		.cable_test_start	= nxp_c45_cable_test_start,
1941f1fe5dffSRadu Pirea (NXP OSS) 		.cable_test_get_status	= nxp_c45_cable_test_get_status,
1942f1fe5dffSRadu Pirea (NXP OSS) 		.set_loopback		= genphy_c45_loopback,
1943f1fe5dffSRadu Pirea (NXP OSS) 		.get_sqi		= nxp_c45_get_sqi,
1944f1fe5dffSRadu Pirea (NXP OSS) 		.get_sqi_max		= nxp_c45_get_sqi_max,
1945f1fe5dffSRadu Pirea (NXP OSS) 		.remove			= nxp_c45_remove,
1946f1fe5dffSRadu Pirea (NXP OSS) 	},
1947b050f2f1SRadu Pirea (NXP OSS) };
1948b050f2f1SRadu Pirea (NXP OSS) 
1949b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver);
1950b050f2f1SRadu Pirea (NXP OSS) 
1951b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = {
1952b050f2f1SRadu Pirea (NXP OSS) 	{ PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) },
1953f1fe5dffSRadu Pirea (NXP OSS) 	{ PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120) },
1954b050f2f1SRadu Pirea (NXP OSS) 	{ /*sentinel*/ },
1955b050f2f1SRadu Pirea (NXP OSS) };
1956b050f2f1SRadu Pirea (NXP OSS) 
1957b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl);
1958b050f2f1SRadu Pirea (NXP OSS) 
1959b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>");
1960b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver");
1961b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2");
1962