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)
3708e6547cSRadu Pirea (NXP OSS) #define TJA1120_VEND1_PTP_TRIG_DATA_S 0x1070
3808e6547cSRadu 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)
59*68c6af72SRadu Pirea (NXP OSS) #define TJA1120_EPHY_RESETS 0x810A
60*68c6af72SRadu Pirea (NXP OSS) #define EPHY_PCS_RESET BIT(3)
61*68c6af72SRadu Pirea (NXP OSS)
62b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SIGNAL_QUALITY 0x8320
63b050f2f1SRadu Pirea (NXP OSS) #define SQI_VALID BIT(14)
64b050f2f1SRadu Pirea (NXP OSS) #define SQI_MASK GENMASK(2, 0)
65b050f2f1SRadu Pirea (NXP OSS) #define MAX_SQI SQI_MASK
66b050f2f1SRadu Pirea (NXP OSS)
67b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_ENABLE BIT(15)
68b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_START BIT(14)
69b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OK 0x00
70b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_SHORTED 0x01
71b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OPEN 0x02
72b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_UNKNOWN 0x07
73b050f2f1SRadu Pirea (NXP OSS)
74b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_CONTROL 0x8040
75b050f2f1SRadu Pirea (NXP OSS) #define PORT_CONTROL_EN BIT(14)
76b050f2f1SRadu Pirea (NXP OSS)
77514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_ABILITIES 0x8046
78514def5dSRadu Pirea (NXP OSS) #define PTP_ABILITY BIT(3)
79514def5dSRadu Pirea (NXP OSS)
80bdb4c5b8SRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_IRQ_EN 0x807A
81bdb4c5b8SRadu Pirea (NXP OSS) #define PTP_IRQS BIT(3)
82bdb4c5b8SRadu Pirea (NXP OSS)
83bdb4c5b8SRadu Pirea (NXP OSS) #define VEND1_PTP_IRQ_ACK 0x9008
84bdb4c5b8SRadu Pirea (NXP OSS) #define EGR_TS_IRQ BIT(1)
85bdb4c5b8SRadu Pirea (NXP OSS)
86b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_INFRA_CONTROL 0xAC00
87b050f2f1SRadu Pirea (NXP OSS) #define PORT_INFRA_CONTROL_EN BIT(14)
88b050f2f1SRadu Pirea (NXP OSS)
89b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RXID 0xAFCC
90b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TXID 0xAFCD
91b050f2f1SRadu Pirea (NXP OSS) #define ID_ENABLE BIT(15)
92b050f2f1SRadu Pirea (NXP OSS)
93b050f2f1SRadu Pirea (NXP OSS) #define VEND1_ABILITIES 0xAFC4
94b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ID_ABILITY BIT(15)
95b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ABILITY BIT(14)
96b050f2f1SRadu Pirea (NXP OSS) #define RMII_ABILITY BIT(10)
97b050f2f1SRadu Pirea (NXP OSS) #define REVMII_ABILITY BIT(9)
98b050f2f1SRadu Pirea (NXP OSS) #define MII_ABILITY BIT(8)
99b050f2f1SRadu Pirea (NXP OSS) #define SGMII_ABILITY BIT(0)
100b050f2f1SRadu Pirea (NXP OSS)
101b050f2f1SRadu Pirea (NXP OSS) #define VEND1_MII_BASIC_CONFIG 0xAFC6
1028ba57205SRadu Pirea (OSS) #define MII_BASIC_CONFIG_REV BIT(4)
103b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_SGMII 0x9
104b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RGMII 0x7
105b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RMII 0x5
106b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_MII 0x4
107b050f2f1SRadu Pirea (NXP OSS)
108f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_CNT_XTD 0x8351
109f1fe5dffSRadu Pirea (NXP OSS) #define EXTENDED_CNT_EN BIT(15)
110f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_STATUS 0xAC80
111f1fe5dffSRadu Pirea (NXP OSS) #define MONITOR_RESET BIT(15)
112f1fe5dffSRadu Pirea (NXP OSS) #define VEND1_MONITOR_CONFIG 0xAC86
113f1fe5dffSRadu Pirea (NXP OSS) #define LOST_FRAMES_CNT_EN BIT(9)
114f1fe5dffSRadu Pirea (NXP OSS) #define ALL_FRAMES_CNT_EN BIT(8)
115f1fe5dffSRadu Pirea (NXP OSS)
116b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_COUNTER 0x8350
117b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_DROP_COUNTER 0x8352
118b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_LOSSES_AND_FAILURES 0x8353
119b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_PREAMBLE_COUNT 0xAFCE
120b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_PREAMBLE_COUNT 0xAFCF
121b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_IPG_LENGTH 0xAFD0
122b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_IPG_LENGTH 0xAFD1
123b050f2f1SRadu Pirea (NXP OSS) #define COUNTER_EN BIT(15)
124b050f2f1SRadu Pirea (NXP OSS)
1257a71c8aaSRadu Pirea (NXP OSS) #define VEND1_PTP_CONFIG 0x1102
1267a71c8aaSRadu Pirea (NXP OSS) #define EXT_TRG_EDGE BIT(1)
1277a71c8aaSRadu Pirea (NXP OSS)
128b0b2247dSRadu Pirea (NXP OSS) #define TJA1120_SYNC_TRIG_FILTER 0x1010
129b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_RISE_TS BIT(3)
130b0b2247dSRadu Pirea (NXP OSS) #define PTP_TRIG_FALLING_TS BIT(2)
131b0b2247dSRadu Pirea (NXP OSS)
132514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_LD BIT(15)
133514def5dSRadu Pirea (NXP OSS) #define CLK_RATE_ADJ_DIR BIT(14)
134514def5dSRadu Pirea (NXP OSS)
135514def5dSRadu Pirea (NXP OSS) #define VEND1_RX_TS_INSRT_CTRL 0x114D
1366c0c85daSRadu Pirea (NXP OSS) #define TJA1103_RX_TS_INSRT_MODE2 0x02
137514def5dSRadu Pirea (NXP OSS)
138f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_CTRL 0x9012
139f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_RX_TS_INSRT_EN BIT(15)
140f1fe5dffSRadu Pirea (NXP OSS) #define TJA1120_TS_INSRT_MODE BIT(4)
141f1fe5dffSRadu Pirea (NXP OSS)
142514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_DATA_0 0x114E
143514def5dSRadu Pirea (NXP OSS) #define VEND1_EGR_RING_CTRL 0x1154
144514def5dSRadu Pirea (NXP OSS)
145514def5dSRadu Pirea (NXP OSS) #define RING_DATA_0_TS_VALID BIT(15)
146514def5dSRadu Pirea (NXP OSS)
147514def5dSRadu Pirea (NXP OSS) #define RING_DONE BIT(0)
148514def5dSRadu Pirea (NXP OSS)
149514def5dSRadu Pirea (NXP OSS) #define TS_SEC_MASK GENMASK(1, 0)
150514def5dSRadu Pirea (NXP OSS)
151514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_FUNC_ENABLES 0x8048
152514def5dSRadu Pirea (NXP OSS) #define PTP_ENABLE BIT(3)
153c552c110SRadu Pirea (NXP OSS) #define PHY_TEST_ENABLE BIT(0)
154514def5dSRadu Pirea (NXP OSS)
155514def5dSRadu Pirea (NXP OSS) #define VEND1_PORT_PTP_CONTROL 0x9000
156514def5dSRadu Pirea (NXP OSS) #define PORT_PTP_CONTROL_BYPASS BIT(11)
157514def5dSRadu Pirea (NXP OSS)
158514def5dSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_100BT1 15ULL
159f1fe5dffSRadu Pirea (NXP OSS) #define PTP_CLK_PERIOD_1000BT1 8ULL
160514def5dSRadu Pirea (NXP OSS)
161514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_ALL 0x0F
162514def5dSRadu Pirea (NXP OSS) #define EVENT_MSG_FILT_NONE 0x00
163514def5dSRadu Pirea (NXP OSS)
1647a71c8aaSRadu Pirea (NXP OSS) #define VEND1_GPIO_FUNC_CONFIG_BASE 0x2C40
1657a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_EN BIT(15)
1667a71c8aaSRadu Pirea (NXP OSS) #define GPIO_FUNC_PTP BIT(6)
1677a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PTP_TRIGGER 0x01
1687a71c8aaSRadu Pirea (NXP OSS) #define GPIO_SIGNAL_PPS_OUT 0x12
1697a71c8aaSRadu Pirea (NXP OSS) #define GPIO_DISABLE 0
1707a71c8aaSRadu Pirea (NXP OSS) #define GPIO_PPS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \
1717a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PPS_OUT)
1727a71c8aaSRadu Pirea (NXP OSS) #define GPIO_EXTTS_OUT_CFG (GPIO_FUNC_EN | GPIO_FUNC_PTP | \
1737a71c8aaSRadu Pirea (NXP OSS) GPIO_SIGNAL_PTP_TRIGGER)
1747a71c8aaSRadu Pirea (NXP OSS)
175b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS 8000U
176b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE div_u64(RGMII_PERIOD_PS, 360)
177b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS 1644U
178b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS 2260U
179b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS 2000U
180b050f2f1SRadu Pirea (NXP OSS)
1816c0c85daSRadu Pirea (NXP OSS) #define PPM_TO_SUBNS_INC(ppb, ptp_clk_period) div_u64(GENMASK_ULL(31, 0) * \
1826c0c85daSRadu Pirea (NXP OSS) (ppb) * (ptp_clk_period), NSEC_PER_SEC)
183514def5dSRadu Pirea (NXP OSS)
184514def5dSRadu Pirea (NXP OSS) #define NXP_C45_SKB_CB(skb) ((struct nxp_c45_skb_cb *)(skb)->cb)
185514def5dSRadu Pirea (NXP OSS)
186bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_phy;
187bdb4c5b8SRadu Pirea (NXP OSS)
188514def5dSRadu Pirea (NXP OSS) struct nxp_c45_skb_cb {
189514def5dSRadu Pirea (NXP OSS) struct ptp_header *header;
190514def5dSRadu Pirea (NXP OSS) unsigned int type;
191514def5dSRadu Pirea (NXP OSS) };
192514def5dSRadu Pirea (NXP OSS)
1936c0c85daSRadu Pirea (NXP OSS) #define NXP_C45_REG_FIELD(_reg, _devad, _offset, _size) \
1946c0c85daSRadu Pirea (NXP OSS) ((struct nxp_c45_reg_field) { \
1956c0c85daSRadu Pirea (NXP OSS) .reg = _reg, \
1966c0c85daSRadu Pirea (NXP OSS) .devad = _devad, \
1976c0c85daSRadu Pirea (NXP OSS) .offset = _offset, \
1986c0c85daSRadu Pirea (NXP OSS) .size = _size, \
1996c0c85daSRadu Pirea (NXP OSS) })
2006c0c85daSRadu Pirea (NXP OSS)
2016c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field {
2026c0c85daSRadu Pirea (NXP OSS) u16 reg;
2036c0c85daSRadu Pirea (NXP OSS) u8 devad;
2046c0c85daSRadu Pirea (NXP OSS) u8 offset;
2056c0c85daSRadu Pirea (NXP OSS) u8 size;
2066c0c85daSRadu Pirea (NXP OSS) };
2076c0c85daSRadu Pirea (NXP OSS)
208514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts {
209514def5dSRadu Pirea (NXP OSS) u32 nsec;
210514def5dSRadu Pirea (NXP OSS) u32 sec;
211514def5dSRadu Pirea (NXP OSS) u8 domain_number;
212514def5dSRadu Pirea (NXP OSS) u16 sequence_id;
213514def5dSRadu Pirea (NXP OSS) u8 msg_type;
214514def5dSRadu Pirea (NXP OSS) };
215514def5dSRadu Pirea (NXP OSS)
2166c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap {
2176c0c85daSRadu Pirea (NXP OSS) /* PTP config regs. */
2186c0c85daSRadu Pirea (NXP OSS) u16 vend1_ptp_clk_period;
2196c0c85daSRadu Pirea (NXP OSS) u16 vend1_event_msg_filt;
2206c0c85daSRadu Pirea (NXP OSS)
2216c0c85daSRadu Pirea (NXP OSS) /* LTC bits and regs. */
2226c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_read;
2236c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_write;
2246c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field ltc_lock_ctrl;
2256c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_nsec_0;
2266c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_nsec_1;
2276c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_sec_0;
2286c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_wr_sec_1;
2296c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_nsec_0;
2306c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_nsec_1;
2316c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_sec_0;
2326c0c85daSRadu Pirea (NXP OSS) u16 vend1_ltc_rd_sec_1;
2336c0c85daSRadu Pirea (NXP OSS) u16 vend1_rate_adj_subns_0;
2346c0c85daSRadu Pirea (NXP OSS) u16 vend1_rate_adj_subns_1;
2356c0c85daSRadu Pirea (NXP OSS)
2366c0c85daSRadu Pirea (NXP OSS) /* External trigger reg fields. */
2376c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field irq_egr_ts_en;
2386c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field irq_egr_ts_status;
2396c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field domain_number;
2406c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field msg_type;
2416c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sequence_id;
2426c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sec_1_0;
2436c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field sec_4_2;
2446c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field nsec_15_0;
2456c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field nsec_29_16;
2466c0c85daSRadu Pirea (NXP OSS)
2476c0c85daSRadu Pirea (NXP OSS) /* PPS and EXT Trigger bits and regs. */
2486c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field pps_enable;
2496c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field pps_polarity;
2506c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_0;
2516c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_1;
2526c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_2;
2536c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_data_3;
2546c0c85daSRadu Pirea (NXP OSS) u16 vend1_ext_trg_ctrl;
2556c0c85daSRadu Pirea (NXP OSS)
2566c0c85daSRadu Pirea (NXP OSS) /* Cable test reg fields. */
2576c0c85daSRadu Pirea (NXP OSS) u16 cable_test;
2586c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field cable_test_valid;
2596c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_reg_field cable_test_result;
2606c0c85daSRadu Pirea (NXP OSS) };
2616c0c85daSRadu Pirea (NXP OSS)
2626c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_stats {
2636c0c85daSRadu Pirea (NXP OSS) const char *name;
2646c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field counter;
2656c0c85daSRadu Pirea (NXP OSS) };
2666c0c85daSRadu Pirea (NXP OSS)
2676c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data {
2686c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap;
2696c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_stats *stats;
2706c0c85daSRadu Pirea (NXP OSS) int n_stats;
2716c0c85daSRadu Pirea (NXP OSS) u8 ptp_clk_period;
272b0b2247dSRadu Pirea (NXP OSS) bool ext_ts_both_edges;
273bdb4c5b8SRadu Pirea (NXP OSS) bool ack_ptp_irq;
2746c0c85daSRadu Pirea (NXP OSS) void (*counters_enable)(struct phy_device *phydev);
275bdb4c5b8SRadu Pirea (NXP OSS) bool (*get_egressts)(struct nxp_c45_phy *priv,
276bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts);
27708e6547cSRadu Pirea (NXP OSS) bool (*get_extts)(struct nxp_c45_phy *priv, struct timespec64 *extts);
2786c0c85daSRadu Pirea (NXP OSS) void (*ptp_init)(struct phy_device *phydev);
2796c0c85daSRadu Pirea (NXP OSS) void (*ptp_enable)(struct phy_device *phydev, bool enable);
280425c8348SRadu Pirea (NXP OSS) void (*nmi_handler)(struct phy_device *phydev,
281425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status);
2826c0c85daSRadu Pirea (NXP OSS) };
2836c0c85daSRadu Pirea (NXP OSS)
284b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy {
2856c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data;
286514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev;
287514def5dSRadu Pirea (NXP OSS) struct mii_timestamper mii_ts;
288514def5dSRadu Pirea (NXP OSS) struct ptp_clock *ptp_clock;
289514def5dSRadu Pirea (NXP OSS) struct ptp_clock_info caps;
290514def5dSRadu Pirea (NXP OSS) struct sk_buff_head tx_queue;
291514def5dSRadu Pirea (NXP OSS) struct sk_buff_head rx_queue;
292514def5dSRadu Pirea (NXP OSS) /* used to access the PTP registers atomic */
293514def5dSRadu Pirea (NXP OSS) struct mutex ptp_lock;
294514def5dSRadu Pirea (NXP OSS) int hwts_tx;
295514def5dSRadu Pirea (NXP OSS) int hwts_rx;
296b050f2f1SRadu Pirea (NXP OSS) u32 tx_delay;
297b050f2f1SRadu Pirea (NXP OSS) u32 rx_delay;
2987a71c8aaSRadu Pirea (NXP OSS) struct timespec64 extts_ts;
2997a71c8aaSRadu Pirea (NXP OSS) int extts_index;
3007a71c8aaSRadu Pirea (NXP OSS) bool extts;
301b050f2f1SRadu Pirea (NXP OSS) };
302b050f2f1SRadu Pirea (NXP OSS)
3036c0c85daSRadu Pirea (NXP OSS) static const
nxp_c45_get_data(struct phy_device * phydev)3046c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_phy_data *nxp_c45_get_data(struct phy_device *phydev)
3056c0c85daSRadu Pirea (NXP OSS) {
3066c0c85daSRadu Pirea (NXP OSS) return phydev->drv->driver_data;
3076c0c85daSRadu Pirea (NXP OSS) }
3086c0c85daSRadu Pirea (NXP OSS)
3096c0c85daSRadu Pirea (NXP OSS) static const
nxp_c45_get_regmap(struct phy_device * phydev)3106c0c85daSRadu Pirea (NXP OSS) struct nxp_c45_regmap *nxp_c45_get_regmap(struct phy_device *phydev)
3116c0c85daSRadu Pirea (NXP OSS) {
3126c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev);
3136c0c85daSRadu Pirea (NXP OSS)
3146c0c85daSRadu Pirea (NXP OSS) return phy_data->regmap;
3156c0c85daSRadu Pirea (NXP OSS) }
3166c0c85daSRadu Pirea (NXP OSS)
nxp_c45_read_reg_field(struct phy_device * phydev,const struct nxp_c45_reg_field * reg_field)3176c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_read_reg_field(struct phy_device *phydev,
3186c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field)
3196c0c85daSRadu Pirea (NXP OSS) {
320b050f2f1SRadu Pirea (NXP OSS) u16 mask;
3216c0c85daSRadu Pirea (NXP OSS) int ret;
3226c0c85daSRadu Pirea (NXP OSS)
3236c0c85daSRadu Pirea (NXP OSS) if (reg_field->size == 0) {
3246c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to read a reg field of size 0.\n");
3256c0c85daSRadu Pirea (NXP OSS) return -EINVAL;
3266c0c85daSRadu Pirea (NXP OSS) }
3276c0c85daSRadu Pirea (NXP OSS)
3286c0c85daSRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, reg_field->devad, reg_field->reg);
3296c0c85daSRadu Pirea (NXP OSS) if (ret < 0)
3306c0c85daSRadu Pirea (NXP OSS) return ret;
3316c0c85daSRadu Pirea (NXP OSS)
3326c0c85daSRadu Pirea (NXP OSS) mask = reg_field->size == 1 ? BIT(reg_field->offset) :
3336c0c85daSRadu Pirea (NXP OSS) GENMASK(reg_field->offset + reg_field->size - 1,
3346c0c85daSRadu Pirea (NXP OSS) reg_field->offset);
3356c0c85daSRadu Pirea (NXP OSS) ret &= mask;
3366c0c85daSRadu Pirea (NXP OSS) ret >>= reg_field->offset;
3376c0c85daSRadu Pirea (NXP OSS)
3386c0c85daSRadu Pirea (NXP OSS) return ret;
3396c0c85daSRadu Pirea (NXP OSS) }
3406c0c85daSRadu Pirea (NXP OSS)
nxp_c45_write_reg_field(struct phy_device * phydev,const struct nxp_c45_reg_field * reg_field,u16 val)3416c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_write_reg_field(struct phy_device *phydev,
3426c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field,
3436c0c85daSRadu Pirea (NXP OSS) u16 val)
3446c0c85daSRadu Pirea (NXP OSS) {
3456c0c85daSRadu Pirea (NXP OSS) u16 mask;
3466c0c85daSRadu Pirea (NXP OSS) u16 set;
3476c0c85daSRadu Pirea (NXP OSS)
3486c0c85daSRadu Pirea (NXP OSS) if (reg_field->size == 0) {
3496c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to write a reg field of size 0.\n");
3506c0c85daSRadu Pirea (NXP OSS) return -EINVAL;
3516c0c85daSRadu Pirea (NXP OSS) }
3526c0c85daSRadu Pirea (NXP OSS)
3536c0c85daSRadu Pirea (NXP OSS) mask = reg_field->size == 1 ? BIT(reg_field->offset) :
3546c0c85daSRadu Pirea (NXP OSS) GENMASK(reg_field->offset + reg_field->size - 1,
3556c0c85daSRadu Pirea (NXP OSS) reg_field->offset);
3566c0c85daSRadu Pirea (NXP OSS) set = val << reg_field->offset;
3576c0c85daSRadu Pirea (NXP OSS)
3586c0c85daSRadu Pirea (NXP OSS) return phy_modify_mmd_changed(phydev, reg_field->devad,
3596c0c85daSRadu Pirea (NXP OSS) reg_field->reg, mask, set);
3606c0c85daSRadu Pirea (NXP OSS) }
3616c0c85daSRadu Pirea (NXP OSS)
nxp_c45_set_reg_field(struct phy_device * phydev,const struct nxp_c45_reg_field * reg_field)3626c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_set_reg_field(struct phy_device *phydev,
3636c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field)
3646c0c85daSRadu Pirea (NXP OSS) {
3656c0c85daSRadu Pirea (NXP OSS) if (reg_field->size != 1) {
3666c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to set a reg field of size different than 1.\n");
3676c0c85daSRadu Pirea (NXP OSS) return -EINVAL;
3686c0c85daSRadu Pirea (NXP OSS) }
3696c0c85daSRadu Pirea (NXP OSS)
3706c0c85daSRadu Pirea (NXP OSS) return nxp_c45_write_reg_field(phydev, reg_field, 1);
3716c0c85daSRadu Pirea (NXP OSS) }
3726c0c85daSRadu Pirea (NXP OSS)
nxp_c45_clear_reg_field(struct phy_device * phydev,const struct nxp_c45_reg_field * reg_field)3736c0c85daSRadu Pirea (NXP OSS) static int nxp_c45_clear_reg_field(struct phy_device *phydev,
3746c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field)
3756c0c85daSRadu Pirea (NXP OSS) {
3766c0c85daSRadu Pirea (NXP OSS) if (reg_field->size != 1) {
3776c0c85daSRadu Pirea (NXP OSS) phydev_err(phydev, "Trying to set a reg field of size different than 1.\n");
3786c0c85daSRadu Pirea (NXP OSS) return -EINVAL;
3796c0c85daSRadu Pirea (NXP OSS) }
3806c0c85daSRadu Pirea (NXP OSS)
3816c0c85daSRadu Pirea (NXP OSS) return nxp_c45_write_reg_field(phydev, reg_field, 0);
3826c0c85daSRadu Pirea (NXP OSS) }
383b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_poll_txts(struct phy_device * phydev)384514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_poll_txts(struct phy_device *phydev)
385514def5dSRadu Pirea (NXP OSS) {
386514def5dSRadu Pirea (NXP OSS) return phydev->irq <= 0;
387514def5dSRadu Pirea (NXP OSS) }
388514def5dSRadu Pirea (NXP OSS)
_nxp_c45_ptp_gettimex64(struct ptp_clock_info * ptp,struct timespec64 * ts,struct ptp_system_timestamp * sts)389514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp,
390514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts,
391514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts)
392514def5dSRadu Pirea (NXP OSS) {
393514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
3946c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
395514def5dSRadu Pirea (NXP OSS)
3966c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->ltc_read);
397514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
3986c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_nsec_0);
399514def5dSRadu Pirea (NXP OSS) ts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
4006c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_nsec_1) << 16;
401514def5dSRadu Pirea (NXP OSS) ts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
4026c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_sec_0);
403514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
4046c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ltc_rd_sec_1) << 16;
405514def5dSRadu Pirea (NXP OSS)
406514def5dSRadu Pirea (NXP OSS) return 0;
407514def5dSRadu Pirea (NXP OSS) }
408514def5dSRadu Pirea (NXP OSS)
nxp_c45_ptp_gettimex64(struct ptp_clock_info * ptp,struct timespec64 * ts,struct ptp_system_timestamp * sts)409514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_gettimex64(struct ptp_clock_info *ptp,
410514def5dSRadu Pirea (NXP OSS) struct timespec64 *ts,
411514def5dSRadu Pirea (NXP OSS) struct ptp_system_timestamp *sts)
412514def5dSRadu Pirea (NXP OSS) {
413514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
414514def5dSRadu Pirea (NXP OSS)
415514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock);
416514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, ts, sts);
417514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock);
418514def5dSRadu Pirea (NXP OSS)
419514def5dSRadu Pirea (NXP OSS) return 0;
420514def5dSRadu Pirea (NXP OSS) }
421514def5dSRadu Pirea (NXP OSS)
_nxp_c45_ptp_settime64(struct ptp_clock_info * ptp,const struct timespec64 * ts)422514def5dSRadu Pirea (NXP OSS) static int _nxp_c45_ptp_settime64(struct ptp_clock_info *ptp,
423514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts)
424514def5dSRadu Pirea (NXP OSS) {
425514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
4266c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
427514def5dSRadu Pirea (NXP OSS)
4286c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_0,
429514def5dSRadu Pirea (NXP OSS) ts->tv_nsec);
4306c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_nsec_1,
431514def5dSRadu Pirea (NXP OSS) ts->tv_nsec >> 16);
4326c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_0,
433514def5dSRadu Pirea (NXP OSS) ts->tv_sec);
4346c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, regmap->vend1_ltc_wr_sec_1,
435514def5dSRadu Pirea (NXP OSS) ts->tv_sec >> 16);
4366c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->ltc_write);
437514def5dSRadu Pirea (NXP OSS)
438514def5dSRadu Pirea (NXP OSS) return 0;
439514def5dSRadu Pirea (NXP OSS) }
440514def5dSRadu Pirea (NXP OSS)
nxp_c45_ptp_settime64(struct ptp_clock_info * ptp,const struct timespec64 * ts)441514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_settime64(struct ptp_clock_info *ptp,
442514def5dSRadu Pirea (NXP OSS) const struct timespec64 *ts)
443514def5dSRadu Pirea (NXP OSS) {
444514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
445514def5dSRadu Pirea (NXP OSS)
446514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock);
447514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, ts);
448514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock);
449514def5dSRadu Pirea (NXP OSS)
450514def5dSRadu Pirea (NXP OSS) return 0;
451514def5dSRadu Pirea (NXP OSS) }
452514def5dSRadu Pirea (NXP OSS)
nxp_c45_ptp_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)453514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
454514def5dSRadu Pirea (NXP OSS) {
455514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
4566c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev);
4576c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = data->regmap;
458514def5dSRadu Pirea (NXP OSS) s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
459514def5dSRadu Pirea (NXP OSS) u64 subns_inc_val;
460514def5dSRadu Pirea (NXP OSS) bool inc;
461514def5dSRadu Pirea (NXP OSS)
462514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock);
463514def5dSRadu Pirea (NXP OSS) inc = ppb >= 0;
464514def5dSRadu Pirea (NXP OSS) ppb = abs(ppb);
465514def5dSRadu Pirea (NXP OSS)
4666c0c85daSRadu Pirea (NXP OSS) subns_inc_val = PPM_TO_SUBNS_INC(ppb, data->ptp_clk_period);
467514def5dSRadu Pirea (NXP OSS)
4686c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1,
4696c0c85daSRadu Pirea (NXP OSS) regmap->vend1_rate_adj_subns_0,
470514def5dSRadu Pirea (NXP OSS) subns_inc_val);
471514def5dSRadu Pirea (NXP OSS) subns_inc_val >>= 16;
472514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_LD;
473514def5dSRadu Pirea (NXP OSS) if (inc)
474514def5dSRadu Pirea (NXP OSS) subns_inc_val |= CLK_RATE_ADJ_DIR;
475514def5dSRadu Pirea (NXP OSS)
4766c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1,
4776c0c85daSRadu Pirea (NXP OSS) regmap->vend1_rate_adj_subns_1,
478514def5dSRadu Pirea (NXP OSS) subns_inc_val);
479514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock);
480514def5dSRadu Pirea (NXP OSS)
481514def5dSRadu Pirea (NXP OSS) return 0;
482514def5dSRadu Pirea (NXP OSS) }
483514def5dSRadu Pirea (NXP OSS)
nxp_c45_ptp_adjtime(struct ptp_clock_info * ptp,s64 delta)484514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
485514def5dSRadu Pirea (NXP OSS) {
486514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
487514def5dSRadu Pirea (NXP OSS) struct timespec64 now, then;
488514def5dSRadu Pirea (NXP OSS)
489514def5dSRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock);
490514def5dSRadu Pirea (NXP OSS) then = ns_to_timespec64(delta);
491514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_gettimex64(ptp, &now, NULL);
492514def5dSRadu Pirea (NXP OSS) now = timespec64_add(now, then);
493514def5dSRadu Pirea (NXP OSS) _nxp_c45_ptp_settime64(ptp, &now);
494514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock);
495514def5dSRadu Pirea (NXP OSS)
496514def5dSRadu Pirea (NXP OSS) return 0;
497514def5dSRadu Pirea (NXP OSS) }
498514def5dSRadu Pirea (NXP OSS)
nxp_c45_reconstruct_ts(struct timespec64 * ts,struct nxp_c45_hwts * hwts)499514def5dSRadu Pirea (NXP OSS) static void nxp_c45_reconstruct_ts(struct timespec64 *ts,
500514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts)
501514def5dSRadu Pirea (NXP OSS) {
502514def5dSRadu Pirea (NXP OSS) ts->tv_nsec = hwts->nsec;
503514def5dSRadu Pirea (NXP OSS) if ((ts->tv_sec & TS_SEC_MASK) < (hwts->sec & TS_SEC_MASK))
504661fef56SVladimir Oltean ts->tv_sec -= TS_SEC_MASK + 1;
505514def5dSRadu Pirea (NXP OSS) ts->tv_sec &= ~TS_SEC_MASK;
506514def5dSRadu Pirea (NXP OSS) ts->tv_sec |= hwts->sec & TS_SEC_MASK;
507514def5dSRadu Pirea (NXP OSS) }
508514def5dSRadu Pirea (NXP OSS)
nxp_c45_match_ts(struct ptp_header * header,struct nxp_c45_hwts * hwts,unsigned int type)509514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_match_ts(struct ptp_header *header,
510514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts,
511514def5dSRadu Pirea (NXP OSS) unsigned int type)
512514def5dSRadu Pirea (NXP OSS) {
513514def5dSRadu Pirea (NXP OSS) return ntohs(header->sequence_id) == hwts->sequence_id &&
514514def5dSRadu Pirea (NXP OSS) ptp_get_msgtype(header, type) == hwts->msg_type &&
515514def5dSRadu Pirea (NXP OSS) header->domain_number == hwts->domain_number;
516514def5dSRadu Pirea (NXP OSS) }
517514def5dSRadu Pirea (NXP OSS)
nxp_c45_get_extts(struct nxp_c45_phy * priv,struct timespec64 * extts)51808e6547cSRadu Pirea (NXP OSS) static bool nxp_c45_get_extts(struct nxp_c45_phy *priv,
5197a71c8aaSRadu Pirea (NXP OSS) struct timespec64 *extts)
5207a71c8aaSRadu Pirea (NXP OSS) {
5216c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
5226c0c85daSRadu Pirea (NXP OSS)
5237a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
5246c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_0);
5257a71c8aaSRadu Pirea (NXP OSS) extts->tv_nsec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
5266c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_1) << 16;
5277a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
5286c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_2);
5297a71c8aaSRadu Pirea (NXP OSS) extts->tv_sec |= phy_read_mmd(priv->phydev, MDIO_MMD_VEND1,
5306c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_data_3) << 16;
5316c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1,
5326c0c85daSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_ctrl, RING_DONE);
53308e6547cSRadu Pirea (NXP OSS)
53408e6547cSRadu Pirea (NXP OSS) return true;
53508e6547cSRadu Pirea (NXP OSS) }
53608e6547cSRadu Pirea (NXP OSS)
tja1120_extts_is_valid(struct phy_device * phydev)53708e6547cSRadu Pirea (NXP OSS) static bool tja1120_extts_is_valid(struct phy_device *phydev)
53808e6547cSRadu Pirea (NXP OSS) {
53908e6547cSRadu Pirea (NXP OSS) bool valid;
54008e6547cSRadu Pirea (NXP OSS) int reg;
54108e6547cSRadu Pirea (NXP OSS)
54208e6547cSRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1,
54308e6547cSRadu Pirea (NXP OSS) TJA1120_VEND1_PTP_TRIG_DATA_S);
54408e6547cSRadu Pirea (NXP OSS) valid = !!(reg & TJA1120_TS_VALID);
54508e6547cSRadu Pirea (NXP OSS)
54608e6547cSRadu Pirea (NXP OSS) return valid;
54708e6547cSRadu Pirea (NXP OSS) }
54808e6547cSRadu Pirea (NXP OSS)
tja1120_get_extts(struct nxp_c45_phy * priv,struct timespec64 * extts)54908e6547cSRadu Pirea (NXP OSS) static bool tja1120_get_extts(struct nxp_c45_phy *priv,
55008e6547cSRadu Pirea (NXP OSS) struct timespec64 *extts)
55108e6547cSRadu Pirea (NXP OSS) {
55208e6547cSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
55308e6547cSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev;
55408e6547cSRadu Pirea (NXP OSS) bool more_ts;
55508e6547cSRadu Pirea (NXP OSS) bool valid;
55608e6547cSRadu Pirea (NXP OSS) u16 reg;
55708e6547cSRadu Pirea (NXP OSS)
55808e6547cSRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1,
55908e6547cSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_ctrl);
56008e6547cSRadu Pirea (NXP OSS) more_ts = !!(reg & TJA1120_MORE_TS);
56108e6547cSRadu Pirea (NXP OSS)
56208e6547cSRadu Pirea (NXP OSS) valid = tja1120_extts_is_valid(phydev);
56308e6547cSRadu Pirea (NXP OSS) if (!valid) {
56408e6547cSRadu Pirea (NXP OSS) if (!more_ts)
56508e6547cSRadu Pirea (NXP OSS) goto tja1120_get_extts_out;
56608e6547cSRadu Pirea (NXP OSS)
56708e6547cSRadu Pirea (NXP OSS) /* Bug workaround for TJA1120 engineering samples: move the new
56808e6547cSRadu Pirea (NXP OSS) * timestamp from the FIFO to the buffer.
56908e6547cSRadu Pirea (NXP OSS) */
57008e6547cSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
57108e6547cSRadu Pirea (NXP OSS) regmap->vend1_ext_trg_ctrl, RING_DONE);
57208e6547cSRadu Pirea (NXP OSS) valid = tja1120_extts_is_valid(phydev);
57308e6547cSRadu Pirea (NXP OSS) if (!valid)
57408e6547cSRadu Pirea (NXP OSS) goto tja1120_get_extts_out;
57508e6547cSRadu Pirea (NXP OSS) }
57608e6547cSRadu Pirea (NXP OSS)
57708e6547cSRadu Pirea (NXP OSS) nxp_c45_get_extts(priv, extts);
57808e6547cSRadu Pirea (NXP OSS) tja1120_get_extts_out:
57908e6547cSRadu Pirea (NXP OSS) return valid;
5807a71c8aaSRadu Pirea (NXP OSS) }
5817a71c8aaSRadu Pirea (NXP OSS)
nxp_c45_read_egress_ts(struct nxp_c45_phy * priv,struct nxp_c45_hwts * hwts)582bdb4c5b8SRadu Pirea (NXP OSS) static void nxp_c45_read_egress_ts(struct nxp_c45_phy *priv,
583514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts)
584514def5dSRadu Pirea (NXP OSS) {
5856c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
5866c0c85daSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev;
587514def5dSRadu Pirea (NXP OSS)
5886c0c85daSRadu Pirea (NXP OSS) hwts->domain_number =
5896c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->domain_number);
5906c0c85daSRadu Pirea (NXP OSS) hwts->msg_type =
5916c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->msg_type);
5926c0c85daSRadu Pirea (NXP OSS) hwts->sequence_id =
5936c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->sequence_id);
5946c0c85daSRadu Pirea (NXP OSS) hwts->nsec =
5956c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->nsec_15_0);
5966c0c85daSRadu Pirea (NXP OSS) hwts->nsec |=
5976c0c85daSRadu Pirea (NXP OSS) nxp_c45_read_reg_field(phydev, ®map->nsec_29_16) << 16;
5986c0c85daSRadu Pirea (NXP OSS) hwts->sec = nxp_c45_read_reg_field(phydev, ®map->sec_1_0);
5996c0c85daSRadu Pirea (NXP OSS) hwts->sec |= nxp_c45_read_reg_field(phydev, ®map->sec_4_2) << 2;
600bdb4c5b8SRadu Pirea (NXP OSS) }
601514def5dSRadu Pirea (NXP OSS)
nxp_c45_get_hwtxts(struct nxp_c45_phy * priv,struct nxp_c45_hwts * hwts)602bdb4c5b8SRadu Pirea (NXP OSS) static bool nxp_c45_get_hwtxts(struct nxp_c45_phy *priv,
603bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts)
604bdb4c5b8SRadu Pirea (NXP OSS) {
605bdb4c5b8SRadu Pirea (NXP OSS) bool valid;
606bdb4c5b8SRadu Pirea (NXP OSS) u16 reg;
607bdb4c5b8SRadu Pirea (NXP OSS)
608bdb4c5b8SRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock);
609bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_CTRL,
610bdb4c5b8SRadu Pirea (NXP OSS) RING_DONE);
611bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(priv->phydev, MDIO_MMD_VEND1, VEND1_EGR_RING_DATA_0);
612bdb4c5b8SRadu Pirea (NXP OSS) valid = !!(reg & RING_DATA_0_TS_VALID);
613bdb4c5b8SRadu Pirea (NXP OSS) if (!valid)
614bdb4c5b8SRadu Pirea (NXP OSS) goto nxp_c45_get_hwtxts_out;
615bdb4c5b8SRadu Pirea (NXP OSS)
616bdb4c5b8SRadu Pirea (NXP OSS) nxp_c45_read_egress_ts(priv, hwts);
617514def5dSRadu Pirea (NXP OSS) nxp_c45_get_hwtxts_out:
618514def5dSRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock);
619514def5dSRadu Pirea (NXP OSS) return valid;
620514def5dSRadu Pirea (NXP OSS) }
621514def5dSRadu Pirea (NXP OSS)
tja1120_egress_ts_is_valid(struct phy_device * phydev)622bdb4c5b8SRadu Pirea (NXP OSS) static bool tja1120_egress_ts_is_valid(struct phy_device *phydev)
623bdb4c5b8SRadu Pirea (NXP OSS) {
624bdb4c5b8SRadu Pirea (NXP OSS) bool valid;
625bdb4c5b8SRadu Pirea (NXP OSS) u16 reg;
626bdb4c5b8SRadu Pirea (NXP OSS)
627bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S);
628bdb4c5b8SRadu Pirea (NXP OSS) valid = !!(reg & TJA1120_TS_VALID);
629bdb4c5b8SRadu Pirea (NXP OSS)
630bdb4c5b8SRadu Pirea (NXP OSS) return valid;
631bdb4c5b8SRadu Pirea (NXP OSS) }
632bdb4c5b8SRadu Pirea (NXP OSS)
tja1120_get_hwtxts(struct nxp_c45_phy * priv,struct nxp_c45_hwts * hwts)633bdb4c5b8SRadu Pirea (NXP OSS) static bool tja1120_get_hwtxts(struct nxp_c45_phy *priv,
634bdb4c5b8SRadu Pirea (NXP OSS) struct nxp_c45_hwts *hwts)
635bdb4c5b8SRadu Pirea (NXP OSS) {
636bdb4c5b8SRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev;
637bdb4c5b8SRadu Pirea (NXP OSS) bool more_ts;
638bdb4c5b8SRadu Pirea (NXP OSS) bool valid;
639bdb4c5b8SRadu Pirea (NXP OSS) u16 reg;
640bdb4c5b8SRadu Pirea (NXP OSS)
641bdb4c5b8SRadu Pirea (NXP OSS) mutex_lock(&priv->ptp_lock);
642bdb4c5b8SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_END);
643bdb4c5b8SRadu Pirea (NXP OSS) more_ts = !!(reg & TJA1120_MORE_TS);
644bdb4c5b8SRadu Pirea (NXP OSS) valid = tja1120_egress_ts_is_valid(phydev);
645bdb4c5b8SRadu Pirea (NXP OSS) if (!valid) {
646bdb4c5b8SRadu Pirea (NXP OSS) if (!more_ts)
647bdb4c5b8SRadu Pirea (NXP OSS) goto tja1120_get_hwtxts_out;
648bdb4c5b8SRadu Pirea (NXP OSS)
649bdb4c5b8SRadu Pirea (NXP OSS) /* Bug workaround for TJA1120 engineering samples: move the
650bdb4c5b8SRadu Pirea (NXP OSS) * new timestamp from the FIFO to the buffer.
651bdb4c5b8SRadu Pirea (NXP OSS) */
652bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
653bdb4c5b8SRadu Pirea (NXP OSS) TJA1120_EGRESS_TS_END, TJA1120_TS_VALID);
654bdb4c5b8SRadu Pirea (NXP OSS) valid = tja1120_egress_ts_is_valid(phydev);
655bdb4c5b8SRadu Pirea (NXP OSS) if (!valid)
656bdb4c5b8SRadu Pirea (NXP OSS) goto tja1120_get_hwtxts_out;
657bdb4c5b8SRadu Pirea (NXP OSS) }
658bdb4c5b8SRadu Pirea (NXP OSS) nxp_c45_read_egress_ts(priv, hwts);
659bdb4c5b8SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, TJA1120_EGRESS_TS_DATA_S,
660bdb4c5b8SRadu Pirea (NXP OSS) TJA1120_TS_VALID);
661bdb4c5b8SRadu Pirea (NXP OSS) tja1120_get_hwtxts_out:
662bdb4c5b8SRadu Pirea (NXP OSS) mutex_unlock(&priv->ptp_lock);
663bdb4c5b8SRadu Pirea (NXP OSS) return valid;
664bdb4c5b8SRadu Pirea (NXP OSS) }
665bdb4c5b8SRadu Pirea (NXP OSS)
nxp_c45_process_txts(struct nxp_c45_phy * priv,struct nxp_c45_hwts * txts)666514def5dSRadu Pirea (NXP OSS) static void nxp_c45_process_txts(struct nxp_c45_phy *priv,
667514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts *txts)
668514def5dSRadu Pirea (NXP OSS) {
669514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, *tmp, *skb_match = NULL;
670514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps shhwtstamps;
671514def5dSRadu Pirea (NXP OSS) struct timespec64 ts;
672514def5dSRadu Pirea (NXP OSS) unsigned long flags;
673514def5dSRadu Pirea (NXP OSS) bool ts_match;
674514def5dSRadu Pirea (NXP OSS) s64 ts_ns;
675514def5dSRadu Pirea (NXP OSS)
676514def5dSRadu Pirea (NXP OSS) spin_lock_irqsave(&priv->tx_queue.lock, flags);
677514def5dSRadu Pirea (NXP OSS) skb_queue_walk_safe(&priv->tx_queue, skb, tmp) {
678514def5dSRadu Pirea (NXP OSS) ts_match = nxp_c45_match_ts(NXP_C45_SKB_CB(skb)->header, txts,
679514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type);
680514def5dSRadu Pirea (NXP OSS) if (!ts_match)
681514def5dSRadu Pirea (NXP OSS) continue;
682514def5dSRadu Pirea (NXP OSS) skb_match = skb;
683514def5dSRadu Pirea (NXP OSS) __skb_unlink(skb, &priv->tx_queue);
684514def5dSRadu Pirea (NXP OSS) break;
685514def5dSRadu Pirea (NXP OSS) }
686514def5dSRadu Pirea (NXP OSS) spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
687514def5dSRadu Pirea (NXP OSS)
688514def5dSRadu Pirea (NXP OSS) if (skb_match) {
689514def5dSRadu Pirea (NXP OSS) nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL);
690514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, txts);
691514def5dSRadu Pirea (NXP OSS) memset(&shhwtstamps, 0, sizeof(shhwtstamps));
692514def5dSRadu Pirea (NXP OSS) ts_ns = timespec64_to_ns(&ts);
693514def5dSRadu Pirea (NXP OSS) shhwtstamps.hwtstamp = ns_to_ktime(ts_ns);
694514def5dSRadu Pirea (NXP OSS) skb_complete_tx_timestamp(skb_match, &shhwtstamps);
695514def5dSRadu Pirea (NXP OSS) } else {
696514def5dSRadu Pirea (NXP OSS) phydev_warn(priv->phydev,
697514def5dSRadu Pirea (NXP OSS) "the tx timestamp doesn't match with any skb\n");
698514def5dSRadu Pirea (NXP OSS) }
699514def5dSRadu Pirea (NXP OSS) }
700514def5dSRadu Pirea (NXP OSS)
nxp_c45_do_aux_work(struct ptp_clock_info * ptp)701514def5dSRadu Pirea (NXP OSS) static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp)
702514def5dSRadu Pirea (NXP OSS) {
703514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
704bdb4c5b8SRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev);
705514def5dSRadu Pirea (NXP OSS) bool poll_txts = nxp_c45_poll_txts(priv->phydev);
706514def5dSRadu Pirea (NXP OSS) struct skb_shared_hwtstamps *shhwtstamps_rx;
7077a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_event event;
708514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts;
709514def5dSRadu Pirea (NXP OSS) bool reschedule = false;
710514def5dSRadu Pirea (NXP OSS) struct timespec64 ts;
711514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb;
71208e6547cSRadu Pirea (NXP OSS) bool ts_valid;
713514def5dSRadu Pirea (NXP OSS) u32 ts_raw;
714514def5dSRadu Pirea (NXP OSS)
715514def5dSRadu Pirea (NXP OSS) while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) {
71608e6547cSRadu Pirea (NXP OSS) ts_valid = data->get_egressts(priv, &hwts);
71708e6547cSRadu Pirea (NXP OSS) if (unlikely(!ts_valid)) {
718514def5dSRadu Pirea (NXP OSS) /* Still more skbs in the queue */
719514def5dSRadu Pirea (NXP OSS) reschedule = true;
720514def5dSRadu Pirea (NXP OSS) break;
721514def5dSRadu Pirea (NXP OSS) }
722514def5dSRadu Pirea (NXP OSS)
723514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts);
724514def5dSRadu Pirea (NXP OSS) }
725514def5dSRadu Pirea (NXP OSS)
726514def5dSRadu Pirea (NXP OSS) while ((skb = skb_dequeue(&priv->rx_queue)) != NULL) {
727109258edSVladimir Oltean nxp_c45_ptp_gettimex64(&priv->caps, &ts, NULL);
728514def5dSRadu Pirea (NXP OSS) ts_raw = __be32_to_cpu(NXP_C45_SKB_CB(skb)->header->reserved2);
729514def5dSRadu Pirea (NXP OSS) hwts.sec = ts_raw >> 30;
730514def5dSRadu Pirea (NXP OSS) hwts.nsec = ts_raw & GENMASK(29, 0);
731514def5dSRadu Pirea (NXP OSS) nxp_c45_reconstruct_ts(&ts, &hwts);
732514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx = skb_hwtstamps(skb);
733514def5dSRadu Pirea (NXP OSS) shhwtstamps_rx->hwtstamp = ns_to_ktime(timespec64_to_ns(&ts));
734514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header->reserved2 = 0;
735a3d73e15SSebastian Andrzej Siewior netif_rx(skb);
736514def5dSRadu Pirea (NXP OSS) }
737514def5dSRadu Pirea (NXP OSS)
7387a71c8aaSRadu Pirea (NXP OSS) if (priv->extts) {
73908e6547cSRadu Pirea (NXP OSS) ts_valid = data->get_extts(priv, &ts);
74008e6547cSRadu Pirea (NXP OSS) if (ts_valid && timespec64_compare(&ts, &priv->extts_ts) != 0) {
7417a71c8aaSRadu Pirea (NXP OSS) priv->extts_ts = ts;
7427a71c8aaSRadu Pirea (NXP OSS) event.index = priv->extts_index;
7437a71c8aaSRadu Pirea (NXP OSS) event.type = PTP_CLOCK_EXTTS;
7447a71c8aaSRadu Pirea (NXP OSS) event.timestamp = ns_to_ktime(timespec64_to_ns(&ts));
7457a71c8aaSRadu Pirea (NXP OSS) ptp_clock_event(priv->ptp_clock, &event);
7467a71c8aaSRadu Pirea (NXP OSS) }
7477a71c8aaSRadu Pirea (NXP OSS) reschedule = true;
7487a71c8aaSRadu Pirea (NXP OSS) }
7497a71c8aaSRadu Pirea (NXP OSS)
750514def5dSRadu Pirea (NXP OSS) return reschedule ? 1 : -1;
751514def5dSRadu Pirea (NXP OSS) }
752514def5dSRadu Pirea (NXP OSS)
nxp_c45_gpio_config(struct nxp_c45_phy * priv,int pin,u16 pin_cfg)7537a71c8aaSRadu Pirea (NXP OSS) static void nxp_c45_gpio_config(struct nxp_c45_phy *priv,
7547a71c8aaSRadu Pirea (NXP OSS) int pin, u16 pin_cfg)
7557a71c8aaSRadu Pirea (NXP OSS) {
7567a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev;
7577a71c8aaSRadu Pirea (NXP OSS)
7587a71c8aaSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
7597a71c8aaSRadu Pirea (NXP OSS) VEND1_GPIO_FUNC_CONFIG_BASE + pin, pin_cfg);
7607a71c8aaSRadu Pirea (NXP OSS) }
7617a71c8aaSRadu Pirea (NXP OSS)
nxp_c45_perout_enable(struct nxp_c45_phy * priv,struct ptp_perout_request * perout,int on)7627a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_perout_enable(struct nxp_c45_phy *priv,
7637a71c8aaSRadu Pirea (NXP OSS) struct ptp_perout_request *perout, int on)
7647a71c8aaSRadu Pirea (NXP OSS) {
7656c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
7667a71c8aaSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev;
7677a71c8aaSRadu Pirea (NXP OSS) int pin;
7687a71c8aaSRadu Pirea (NXP OSS)
7697a71c8aaSRadu Pirea (NXP OSS) if (perout->flags & ~PTP_PEROUT_PHASE)
7707a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP;
7717a71c8aaSRadu Pirea (NXP OSS)
7727a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_PEROUT, perout->index);
7737a71c8aaSRadu Pirea (NXP OSS) if (pin < 0)
7747a71c8aaSRadu Pirea (NXP OSS) return pin;
7757a71c8aaSRadu Pirea (NXP OSS)
7767a71c8aaSRadu Pirea (NXP OSS) if (!on) {
7776c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev,
7786c0c85daSRadu Pirea (NXP OSS) ®map->pps_enable);
7796c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev,
7806c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity);
7817a71c8aaSRadu Pirea (NXP OSS)
7827a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE);
7837a71c8aaSRadu Pirea (NXP OSS)
7847a71c8aaSRadu Pirea (NXP OSS) return 0;
7857a71c8aaSRadu Pirea (NXP OSS) }
7867a71c8aaSRadu Pirea (NXP OSS)
7877a71c8aaSRadu Pirea (NXP OSS) /* The PPS signal is fixed to 1 second and is always generated when the
7887a71c8aaSRadu Pirea (NXP OSS) * seconds counter is incremented. The start time is not configurable.
7897a71c8aaSRadu Pirea (NXP OSS) * If the clock is adjusted, the PPS signal is automatically readjusted.
7907a71c8aaSRadu Pirea (NXP OSS) */
7917a71c8aaSRadu Pirea (NXP OSS) if (perout->period.sec != 1 || perout->period.nsec != 0) {
7927a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The period can be set only to 1 second.");
7937a71c8aaSRadu Pirea (NXP OSS) return -EINVAL;
7947a71c8aaSRadu Pirea (NXP OSS) }
7957a71c8aaSRadu Pirea (NXP OSS)
7967a71c8aaSRadu Pirea (NXP OSS) if (!(perout->flags & PTP_PEROUT_PHASE)) {
7977a71c8aaSRadu Pirea (NXP OSS) if (perout->start.sec != 0 || perout->start.nsec != 0) {
7987a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The start time is not configurable. Should be set to 0 seconds and 0 nanoseconds.");
7997a71c8aaSRadu Pirea (NXP OSS) return -EINVAL;
8007a71c8aaSRadu Pirea (NXP OSS) }
8017a71c8aaSRadu Pirea (NXP OSS) } else {
8027a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec != 0 &&
8037a71c8aaSRadu Pirea (NXP OSS) perout->phase.nsec != (NSEC_PER_SEC >> 1)) {
8047a71c8aaSRadu Pirea (NXP OSS) phydev_warn(phydev, "The phase can be set only to 0 or 500000000 nanoseconds.");
8057a71c8aaSRadu Pirea (NXP OSS) return -EINVAL;
8067a71c8aaSRadu Pirea (NXP OSS) }
8077a71c8aaSRadu Pirea (NXP OSS)
8087a71c8aaSRadu Pirea (NXP OSS) if (perout->phase.nsec == 0)
8096c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(priv->phydev,
8106c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity);
8117a71c8aaSRadu Pirea (NXP OSS) else
8126c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev,
8136c0c85daSRadu Pirea (NXP OSS) ®map->pps_polarity);
8147a71c8aaSRadu Pirea (NXP OSS) }
8157a71c8aaSRadu Pirea (NXP OSS)
8167a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_PPS_OUT_CFG);
8177a71c8aaSRadu Pirea (NXP OSS)
8186c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(priv->phydev, ®map->pps_enable);
8197a71c8aaSRadu Pirea (NXP OSS)
8207a71c8aaSRadu Pirea (NXP OSS) return 0;
8217a71c8aaSRadu Pirea (NXP OSS) }
8227a71c8aaSRadu Pirea (NXP OSS)
nxp_c45_set_rising_or_falling(struct phy_device * phydev,struct ptp_extts_request * extts)823b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_or_falling(struct phy_device *phydev,
824b0b2247dSRadu Pirea (NXP OSS) struct ptp_extts_request *extts)
825b0b2247dSRadu Pirea (NXP OSS) {
826b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE)
827b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
828b0b2247dSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE);
829b0b2247dSRadu Pirea (NXP OSS)
830b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE)
831b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
832b0b2247dSRadu Pirea (NXP OSS) VEND1_PTP_CONFIG, EXT_TRG_EDGE);
833b0b2247dSRadu Pirea (NXP OSS) }
834b0b2247dSRadu Pirea (NXP OSS)
nxp_c45_set_rising_and_falling(struct phy_device * phydev,struct ptp_extts_request * extts)835b0b2247dSRadu Pirea (NXP OSS) static void nxp_c45_set_rising_and_falling(struct phy_device *phydev,
836b0b2247dSRadu Pirea (NXP OSS) struct ptp_extts_request *extts)
837b0b2247dSRadu Pirea (NXP OSS) {
838b0b2247dSRadu Pirea (NXP OSS) /* PTP_EXTTS_REQUEST may have only the PTP_ENABLE_FEATURE flag set. In
839b0b2247dSRadu Pirea (NXP OSS) * this case external ts will be enabled on rising edge.
840b0b2247dSRadu Pirea (NXP OSS) */
841b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_RISING_EDGE ||
842b0b2247dSRadu Pirea (NXP OSS) extts->flags == PTP_ENABLE_FEATURE)
843b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
844b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER,
845b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_RISE_TS);
846b0b2247dSRadu Pirea (NXP OSS) else
847b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
848b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER,
849b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_RISE_TS);
850b0b2247dSRadu Pirea (NXP OSS)
851b0b2247dSRadu Pirea (NXP OSS) if (extts->flags & PTP_FALLING_EDGE)
852b0b2247dSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
853b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER,
854b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_FALLING_TS);
855b0b2247dSRadu Pirea (NXP OSS) else
856b0b2247dSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
857b0b2247dSRadu Pirea (NXP OSS) TJA1120_SYNC_TRIG_FILTER,
858b0b2247dSRadu Pirea (NXP OSS) PTP_TRIG_FALLING_TS);
859b0b2247dSRadu Pirea (NXP OSS) }
860b0b2247dSRadu Pirea (NXP OSS)
nxp_c45_extts_enable(struct nxp_c45_phy * priv,struct ptp_extts_request * extts,int on)8617a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_extts_enable(struct nxp_c45_phy *priv,
8627a71c8aaSRadu Pirea (NXP OSS) struct ptp_extts_request *extts, int on)
8637a71c8aaSRadu Pirea (NXP OSS) {
864b0b2247dSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(priv->phydev);
8657a71c8aaSRadu Pirea (NXP OSS) int pin;
8667a71c8aaSRadu Pirea (NXP OSS)
8677a71c8aaSRadu Pirea (NXP OSS) if (extts->flags & ~(PTP_ENABLE_FEATURE |
8687a71c8aaSRadu Pirea (NXP OSS) PTP_RISING_EDGE |
8697a71c8aaSRadu Pirea (NXP OSS) PTP_FALLING_EDGE |
8707a71c8aaSRadu Pirea (NXP OSS) PTP_STRICT_FLAGS))
8717a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP;
8727a71c8aaSRadu Pirea (NXP OSS)
8737a71c8aaSRadu Pirea (NXP OSS) /* Sampling on both edges is not supported */
8747a71c8aaSRadu Pirea (NXP OSS) if ((extts->flags & PTP_RISING_EDGE) &&
875b0b2247dSRadu Pirea (NXP OSS) (extts->flags & PTP_FALLING_EDGE) &&
876b0b2247dSRadu Pirea (NXP OSS) !data->ext_ts_both_edges)
8777a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP;
8787a71c8aaSRadu Pirea (NXP OSS)
8797a71c8aaSRadu Pirea (NXP OSS) pin = ptp_find_pin(priv->ptp_clock, PTP_PF_EXTTS, extts->index);
8807a71c8aaSRadu Pirea (NXP OSS) if (pin < 0)
8817a71c8aaSRadu Pirea (NXP OSS) return pin;
8827a71c8aaSRadu Pirea (NXP OSS)
8837a71c8aaSRadu Pirea (NXP OSS) if (!on) {
8847a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_DISABLE);
8857a71c8aaSRadu Pirea (NXP OSS) priv->extts = false;
8867a71c8aaSRadu Pirea (NXP OSS)
8877a71c8aaSRadu Pirea (NXP OSS) return 0;
8887a71c8aaSRadu Pirea (NXP OSS) }
8897a71c8aaSRadu Pirea (NXP OSS)
890b0b2247dSRadu Pirea (NXP OSS) if (data->ext_ts_both_edges)
891b0b2247dSRadu Pirea (NXP OSS) nxp_c45_set_rising_and_falling(priv->phydev, extts);
892b0b2247dSRadu Pirea (NXP OSS) else
893b0b2247dSRadu Pirea (NXP OSS) nxp_c45_set_rising_or_falling(priv->phydev, extts);
8947a71c8aaSRadu Pirea (NXP OSS)
8957a71c8aaSRadu Pirea (NXP OSS) nxp_c45_gpio_config(priv, pin, GPIO_EXTTS_OUT_CFG);
8967a71c8aaSRadu Pirea (NXP OSS) priv->extts = true;
8977a71c8aaSRadu Pirea (NXP OSS) priv->extts_index = extts->index;
8987a71c8aaSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0);
8997a71c8aaSRadu Pirea (NXP OSS)
9007a71c8aaSRadu Pirea (NXP OSS) return 0;
9017a71c8aaSRadu Pirea (NXP OSS) }
9027a71c8aaSRadu Pirea (NXP OSS)
nxp_c45_ptp_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * req,int on)9037a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_enable(struct ptp_clock_info *ptp,
9047a71c8aaSRadu Pirea (NXP OSS) struct ptp_clock_request *req, int on)
9057a71c8aaSRadu Pirea (NXP OSS) {
9067a71c8aaSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(ptp, struct nxp_c45_phy, caps);
9077a71c8aaSRadu Pirea (NXP OSS)
9087a71c8aaSRadu Pirea (NXP OSS) switch (req->type) {
9097a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_EXTTS:
9107a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_extts_enable(priv, &req->extts, on);
9117a71c8aaSRadu Pirea (NXP OSS) case PTP_CLK_REQ_PEROUT:
9127a71c8aaSRadu Pirea (NXP OSS) return nxp_c45_perout_enable(priv, &req->perout, on);
9137a71c8aaSRadu Pirea (NXP OSS) default:
9147a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP;
9157a71c8aaSRadu Pirea (NXP OSS) }
9167a71c8aaSRadu Pirea (NXP OSS) }
9177a71c8aaSRadu Pirea (NXP OSS)
9187a71c8aaSRadu Pirea (NXP OSS) static struct ptp_pin_desc nxp_c45_ptp_pins[] = {
9197a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio0", 0, PTP_PF_NONE},
9207a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio1", 1, PTP_PF_NONE},
9217a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio2", 2, PTP_PF_NONE},
9227a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio3", 3, PTP_PF_NONE},
9237a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio4", 4, PTP_PF_NONE},
9247a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio5", 5, PTP_PF_NONE},
9257a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio6", 6, PTP_PF_NONE},
9267a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio7", 7, PTP_PF_NONE},
9277a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio8", 8, PTP_PF_NONE},
9287a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio9", 9, PTP_PF_NONE},
9297a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio10", 10, PTP_PF_NONE},
9307a71c8aaSRadu Pirea (NXP OSS) { "nxp_c45_gpio11", 11, PTP_PF_NONE},
9317a71c8aaSRadu Pirea (NXP OSS) };
9327a71c8aaSRadu Pirea (NXP OSS)
nxp_c45_ptp_verify_pin(struct ptp_clock_info * ptp,unsigned int pin,enum ptp_pin_function func,unsigned int chan)9337a71c8aaSRadu Pirea (NXP OSS) static int nxp_c45_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
9347a71c8aaSRadu Pirea (NXP OSS) enum ptp_pin_function func, unsigned int chan)
9357a71c8aaSRadu Pirea (NXP OSS) {
9367a71c8aaSRadu Pirea (NXP OSS) if (pin >= ARRAY_SIZE(nxp_c45_ptp_pins))
9377a71c8aaSRadu Pirea (NXP OSS) return -EINVAL;
9387a71c8aaSRadu Pirea (NXP OSS)
9397a71c8aaSRadu Pirea (NXP OSS) switch (func) {
9407a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_NONE:
9417a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_PEROUT:
9427a71c8aaSRadu Pirea (NXP OSS) case PTP_PF_EXTTS:
9437a71c8aaSRadu Pirea (NXP OSS) break;
9447a71c8aaSRadu Pirea (NXP OSS) default:
9457a71c8aaSRadu Pirea (NXP OSS) return -EOPNOTSUPP;
9467a71c8aaSRadu Pirea (NXP OSS) }
9477a71c8aaSRadu Pirea (NXP OSS)
9487a71c8aaSRadu Pirea (NXP OSS) return 0;
9497a71c8aaSRadu Pirea (NXP OSS) }
9507a71c8aaSRadu Pirea (NXP OSS)
nxp_c45_init_ptp_clock(struct nxp_c45_phy * priv)951514def5dSRadu Pirea (NXP OSS) static int nxp_c45_init_ptp_clock(struct nxp_c45_phy *priv)
952514def5dSRadu Pirea (NXP OSS) {
953514def5dSRadu Pirea (NXP OSS) priv->caps = (struct ptp_clock_info) {
954514def5dSRadu Pirea (NXP OSS) .owner = THIS_MODULE,
955514def5dSRadu Pirea (NXP OSS) .name = "NXP C45 PHC",
956514def5dSRadu Pirea (NXP OSS) .max_adj = 16666666,
957514def5dSRadu Pirea (NXP OSS) .adjfine = nxp_c45_ptp_adjfine,
958514def5dSRadu Pirea (NXP OSS) .adjtime = nxp_c45_ptp_adjtime,
959514def5dSRadu Pirea (NXP OSS) .gettimex64 = nxp_c45_ptp_gettimex64,
960514def5dSRadu Pirea (NXP OSS) .settime64 = nxp_c45_ptp_settime64,
9617a71c8aaSRadu Pirea (NXP OSS) .enable = nxp_c45_ptp_enable,
9627a71c8aaSRadu Pirea (NXP OSS) .verify = nxp_c45_ptp_verify_pin,
963514def5dSRadu Pirea (NXP OSS) .do_aux_work = nxp_c45_do_aux_work,
9647a71c8aaSRadu Pirea (NXP OSS) .pin_config = nxp_c45_ptp_pins,
9657a71c8aaSRadu Pirea (NXP OSS) .n_pins = ARRAY_SIZE(nxp_c45_ptp_pins),
9667a71c8aaSRadu Pirea (NXP OSS) .n_ext_ts = 1,
9677a71c8aaSRadu Pirea (NXP OSS) .n_per_out = 1,
968514def5dSRadu Pirea (NXP OSS) };
969514def5dSRadu Pirea (NXP OSS)
970514def5dSRadu Pirea (NXP OSS) priv->ptp_clock = ptp_clock_register(&priv->caps,
971514def5dSRadu Pirea (NXP OSS) &priv->phydev->mdio.dev);
972514def5dSRadu Pirea (NXP OSS)
973514def5dSRadu Pirea (NXP OSS) if (IS_ERR(priv->ptp_clock))
974514def5dSRadu Pirea (NXP OSS) return PTR_ERR(priv->ptp_clock);
975514def5dSRadu Pirea (NXP OSS)
976514def5dSRadu Pirea (NXP OSS) if (!priv->ptp_clock)
977514def5dSRadu Pirea (NXP OSS) return -ENOMEM;
978514def5dSRadu Pirea (NXP OSS)
979514def5dSRadu Pirea (NXP OSS) return 0;
980514def5dSRadu Pirea (NXP OSS) }
981514def5dSRadu Pirea (NXP OSS)
nxp_c45_txtstamp(struct mii_timestamper * mii_ts,struct sk_buff * skb,int type)982514def5dSRadu Pirea (NXP OSS) static void nxp_c45_txtstamp(struct mii_timestamper *mii_ts,
983514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type)
984514def5dSRadu Pirea (NXP OSS) {
985514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
986514def5dSRadu Pirea (NXP OSS) mii_ts);
987514def5dSRadu Pirea (NXP OSS)
988514def5dSRadu Pirea (NXP OSS) switch (priv->hwts_tx) {
989514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_ON:
990514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->type = type;
991514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = ptp_parse_header(skb, type);
992514def5dSRadu Pirea (NXP OSS) skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
993514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->tx_queue, skb);
994514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev))
995514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0);
996514def5dSRadu Pirea (NXP OSS) break;
997514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_TX_OFF:
998514def5dSRadu Pirea (NXP OSS) default:
999514def5dSRadu Pirea (NXP OSS) kfree_skb(skb);
1000514def5dSRadu Pirea (NXP OSS) break;
1001514def5dSRadu Pirea (NXP OSS) }
1002514def5dSRadu Pirea (NXP OSS) }
1003514def5dSRadu Pirea (NXP OSS)
nxp_c45_rxtstamp(struct mii_timestamper * mii_ts,struct sk_buff * skb,int type)1004514def5dSRadu Pirea (NXP OSS) static bool nxp_c45_rxtstamp(struct mii_timestamper *mii_ts,
1005514def5dSRadu Pirea (NXP OSS) struct sk_buff *skb, int type)
1006514def5dSRadu Pirea (NXP OSS) {
1007514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
1008514def5dSRadu Pirea (NXP OSS) mii_ts);
1009514def5dSRadu Pirea (NXP OSS) struct ptp_header *header = ptp_parse_header(skb, type);
1010514def5dSRadu Pirea (NXP OSS)
1011514def5dSRadu Pirea (NXP OSS) if (!header)
1012514def5dSRadu Pirea (NXP OSS) return false;
1013514def5dSRadu Pirea (NXP OSS)
1014514def5dSRadu Pirea (NXP OSS) if (!priv->hwts_rx)
1015514def5dSRadu Pirea (NXP OSS) return false;
1016514def5dSRadu Pirea (NXP OSS)
1017514def5dSRadu Pirea (NXP OSS) NXP_C45_SKB_CB(skb)->header = header;
1018514def5dSRadu Pirea (NXP OSS) skb_queue_tail(&priv->rx_queue, skb);
1019514def5dSRadu Pirea (NXP OSS) ptp_schedule_worker(priv->ptp_clock, 0);
1020514def5dSRadu Pirea (NXP OSS)
1021514def5dSRadu Pirea (NXP OSS) return true;
1022514def5dSRadu Pirea (NXP OSS) }
1023514def5dSRadu Pirea (NXP OSS)
nxp_c45_hwtstamp(struct mii_timestamper * mii_ts,struct ifreq * ifreq)1024514def5dSRadu Pirea (NXP OSS) static int nxp_c45_hwtstamp(struct mii_timestamper *mii_ts,
1025514def5dSRadu Pirea (NXP OSS) struct ifreq *ifreq)
1026514def5dSRadu Pirea (NXP OSS) {
1027514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
1028514def5dSRadu Pirea (NXP OSS) mii_ts);
1029514def5dSRadu Pirea (NXP OSS) struct phy_device *phydev = priv->phydev;
10306c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data;
1031514def5dSRadu Pirea (NXP OSS) struct hwtstamp_config cfg;
1032514def5dSRadu Pirea (NXP OSS)
1033514def5dSRadu Pirea (NXP OSS) if (copy_from_user(&cfg, ifreq->ifr_data, sizeof(cfg)))
1034514def5dSRadu Pirea (NXP OSS) return -EFAULT;
1035514def5dSRadu Pirea (NXP OSS)
1036514def5dSRadu Pirea (NXP OSS) if (cfg.tx_type < 0 || cfg.tx_type > HWTSTAMP_TX_ON)
1037514def5dSRadu Pirea (NXP OSS) return -ERANGE;
1038514def5dSRadu Pirea (NXP OSS)
10396c0c85daSRadu Pirea (NXP OSS) data = nxp_c45_get_data(phydev);
1040514def5dSRadu Pirea (NXP OSS) priv->hwts_tx = cfg.tx_type;
1041514def5dSRadu Pirea (NXP OSS)
1042514def5dSRadu Pirea (NXP OSS) switch (cfg.rx_filter) {
1043514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_NONE:
1044514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 0;
1045514def5dSRadu Pirea (NXP OSS) break;
1046514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
1047514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
1048514def5dSRadu Pirea (NXP OSS) case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
1049514def5dSRadu Pirea (NXP OSS) priv->hwts_rx = 1;
1050514def5dSRadu Pirea (NXP OSS) cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
1051514def5dSRadu Pirea (NXP OSS) break;
1052514def5dSRadu Pirea (NXP OSS) default:
1053514def5dSRadu Pirea (NXP OSS) return -ERANGE;
1054514def5dSRadu Pirea (NXP OSS) }
1055514def5dSRadu Pirea (NXP OSS)
1056514def5dSRadu Pirea (NXP OSS) if (priv->hwts_rx || priv->hwts_tx) {
10576c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
10586c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_event_msg_filt,
1059514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_ALL);
10606c0c85daSRadu Pirea (NXP OSS) data->ptp_enable(phydev, true);
1061514def5dSRadu Pirea (NXP OSS) } else {
10626c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
10636c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_event_msg_filt,
1064514def5dSRadu Pirea (NXP OSS) EVENT_MSG_FILT_NONE);
10656c0c85daSRadu Pirea (NXP OSS) data->ptp_enable(phydev, false);
1066514def5dSRadu Pirea (NXP OSS) }
1067514def5dSRadu Pirea (NXP OSS)
1068514def5dSRadu Pirea (NXP OSS) if (nxp_c45_poll_txts(priv->phydev))
1069514def5dSRadu Pirea (NXP OSS) goto nxp_c45_no_ptp_irq;
1070514def5dSRadu Pirea (NXP OSS)
1071514def5dSRadu Pirea (NXP OSS) if (priv->hwts_tx)
10726c0c85daSRadu Pirea (NXP OSS) nxp_c45_set_reg_field(phydev, &data->regmap->irq_egr_ts_en);
1073514def5dSRadu Pirea (NXP OSS) else
10746c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(phydev, &data->regmap->irq_egr_ts_en);
1075514def5dSRadu Pirea (NXP OSS)
1076514def5dSRadu Pirea (NXP OSS) nxp_c45_no_ptp_irq:
1077514def5dSRadu Pirea (NXP OSS) return copy_to_user(ifreq->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
1078514def5dSRadu Pirea (NXP OSS) }
1079514def5dSRadu Pirea (NXP OSS)
nxp_c45_ts_info(struct mii_timestamper * mii_ts,struct ethtool_ts_info * ts_info)1080514def5dSRadu Pirea (NXP OSS) static int nxp_c45_ts_info(struct mii_timestamper *mii_ts,
1081514def5dSRadu Pirea (NXP OSS) struct ethtool_ts_info *ts_info)
1082514def5dSRadu Pirea (NXP OSS) {
1083514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = container_of(mii_ts, struct nxp_c45_phy,
1084514def5dSRadu Pirea (NXP OSS) mii_ts);
1085514def5dSRadu Pirea (NXP OSS)
1086514def5dSRadu Pirea (NXP OSS) ts_info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
1087514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RX_HARDWARE |
1088514def5dSRadu Pirea (NXP OSS) SOF_TIMESTAMPING_RAW_HARDWARE;
1089514def5dSRadu Pirea (NXP OSS) ts_info->phc_index = ptp_clock_index(priv->ptp_clock);
1090514def5dSRadu Pirea (NXP OSS) ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
1091514def5dSRadu Pirea (NXP OSS) ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
1092514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
1093514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
1094514def5dSRadu Pirea (NXP OSS) (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT);
1095514def5dSRadu Pirea (NXP OSS)
1096514def5dSRadu Pirea (NXP OSS) return 0;
1097514def5dSRadu Pirea (NXP OSS) }
1098514def5dSRadu Pirea (NXP OSS)
10996c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats common_hw_stats[] = {
11006c0c85daSRadu Pirea (NXP OSS) { "phy_link_status_drop_cnt",
11016c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 8, 6), },
11026c0c85daSRadu Pirea (NXP OSS) { "phy_link_availability_drop_cnt",
11036c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8352, MDIO_MMD_VEND1, 0, 6), },
11046c0c85daSRadu Pirea (NXP OSS) { "phy_link_loss_cnt",
11056c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 10, 6), },
11066c0c85daSRadu Pirea (NXP OSS) { "phy_link_failure_cnt",
11076c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8353, MDIO_MMD_VEND1, 0, 10), },
11086c0c85daSRadu Pirea (NXP OSS) { "phy_symbol_error_cnt",
11096c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8350, MDIO_MMD_VEND1, 0, 16) },
11106c0c85daSRadu Pirea (NXP OSS) };
11116c0c85daSRadu Pirea (NXP OSS)
11126c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1103_hw_stats[] = {
11136c0c85daSRadu Pirea (NXP OSS) { "rx_preamble_count",
11146c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFCE, MDIO_MMD_VEND1, 0, 6), },
11156c0c85daSRadu Pirea (NXP OSS) { "tx_preamble_count",
11166c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFCF, MDIO_MMD_VEND1, 0, 6), },
11176c0c85daSRadu Pirea (NXP OSS) { "rx_ipg_length",
11186c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFD0, MDIO_MMD_VEND1, 0, 9), },
11196c0c85daSRadu Pirea (NXP OSS) { "tx_ipg_length",
11206c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xAFD1, MDIO_MMD_VEND1, 0, 9), },
1121b050f2f1SRadu Pirea (NXP OSS) };
1122b050f2f1SRadu Pirea (NXP OSS)
1123f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats tja1120_hw_stats[] = {
1124f1fe5dffSRadu Pirea (NXP OSS) { "phy_symbol_error_cnt_ext",
1125f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8351, MDIO_MMD_VEND1, 0, 14) },
1126f1fe5dffSRadu Pirea (NXP OSS) { "tx_frames_xtd",
1127f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA1, MDIO_MMD_VEND1, 0, 8), },
1128f1fe5dffSRadu Pirea (NXP OSS) { "tx_frames",
1129f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA0, MDIO_MMD_VEND1, 0, 16), },
1130f1fe5dffSRadu Pirea (NXP OSS) { "rx_frames_xtd",
1131f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA3, MDIO_MMD_VEND1, 0, 8), },
1132f1fe5dffSRadu Pirea (NXP OSS) { "rx_frames",
1133f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA2, MDIO_MMD_VEND1, 0, 16), },
1134f1fe5dffSRadu Pirea (NXP OSS) { "tx_lost_frames_xtd",
1135f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA5, MDIO_MMD_VEND1, 0, 8), },
1136f1fe5dffSRadu Pirea (NXP OSS) { "tx_lost_frames",
1137f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA4, MDIO_MMD_VEND1, 0, 16), },
1138f1fe5dffSRadu Pirea (NXP OSS) { "rx_lost_frames_xtd",
1139f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA7, MDIO_MMD_VEND1, 0, 8), },
1140f1fe5dffSRadu Pirea (NXP OSS) { "rx_lost_frames",
1141f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0xACA6, MDIO_MMD_VEND1, 0, 16), },
1142f1fe5dffSRadu Pirea (NXP OSS) };
1143f1fe5dffSRadu Pirea (NXP OSS)
nxp_c45_get_sset_count(struct phy_device * phydev)1144b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev)
1145b050f2f1SRadu Pirea (NXP OSS) {
11466c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev);
11476c0c85daSRadu Pirea (NXP OSS)
11486c0c85daSRadu Pirea (NXP OSS) return ARRAY_SIZE(common_hw_stats) + (phy_data ? phy_data->n_stats : 0);
1149b050f2f1SRadu Pirea (NXP OSS) }
1150b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_get_strings(struct phy_device * phydev,u8 * data)1151b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data)
1152b050f2f1SRadu Pirea (NXP OSS) {
11536c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev);
11546c0c85daSRadu Pirea (NXP OSS) size_t count = nxp_c45_get_sset_count(phydev);
11556c0c85daSRadu Pirea (NXP OSS) size_t idx;
1156b050f2f1SRadu Pirea (NXP OSS) size_t i;
1157b050f2f1SRadu Pirea (NXP OSS)
11586c0c85daSRadu Pirea (NXP OSS) for (i = 0; i < count; i++) {
11596c0c85daSRadu Pirea (NXP OSS) if (i < ARRAY_SIZE(common_hw_stats)) {
11606c0c85daSRadu Pirea (NXP OSS) strscpy(data + i * ETH_GSTRING_LEN,
11616c0c85daSRadu Pirea (NXP OSS) common_hw_stats[i].name, ETH_GSTRING_LEN);
11626c0c85daSRadu Pirea (NXP OSS) continue;
11636c0c85daSRadu Pirea (NXP OSS) }
11646c0c85daSRadu Pirea (NXP OSS) idx = i - ARRAY_SIZE(common_hw_stats);
11656c0c85daSRadu Pirea (NXP OSS) strscpy(data + i * ETH_GSTRING_LEN,
11666c0c85daSRadu Pirea (NXP OSS) phy_data->stats[idx].name, ETH_GSTRING_LEN);
1167b050f2f1SRadu Pirea (NXP OSS) }
1168b050f2f1SRadu Pirea (NXP OSS) }
1169b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_get_stats(struct phy_device * phydev,struct ethtool_stats * stats,u64 * data)1170b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev,
1171b050f2f1SRadu Pirea (NXP OSS) struct ethtool_stats *stats, u64 *data)
1172b050f2f1SRadu Pirea (NXP OSS) {
11736c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *phy_data = nxp_c45_get_data(phydev);
11746c0c85daSRadu Pirea (NXP OSS) size_t count = nxp_c45_get_sset_count(phydev);
11756c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_reg_field *reg_field;
11766c0c85daSRadu Pirea (NXP OSS) size_t idx;
1177b050f2f1SRadu Pirea (NXP OSS) size_t i;
1178b050f2f1SRadu Pirea (NXP OSS) int ret;
1179b050f2f1SRadu Pirea (NXP OSS)
11806c0c85daSRadu Pirea (NXP OSS) for (i = 0; i < count; i++) {
11816c0c85daSRadu Pirea (NXP OSS) if (i < ARRAY_SIZE(common_hw_stats)) {
11826c0c85daSRadu Pirea (NXP OSS) reg_field = &common_hw_stats[i].counter;
1183b050f2f1SRadu Pirea (NXP OSS) } else {
11846c0c85daSRadu Pirea (NXP OSS) idx = i - ARRAY_SIZE(common_hw_stats);
11856c0c85daSRadu Pirea (NXP OSS) reg_field = &phy_data->stats[idx].counter;
1186b050f2f1SRadu Pirea (NXP OSS) }
11876c0c85daSRadu Pirea (NXP OSS)
11886c0c85daSRadu Pirea (NXP OSS) ret = nxp_c45_read_reg_field(phydev, reg_field);
11896c0c85daSRadu Pirea (NXP OSS) if (ret < 0)
11906c0c85daSRadu Pirea (NXP OSS) data[i] = U64_MAX;
11916c0c85daSRadu Pirea (NXP OSS) else
11926c0c85daSRadu Pirea (NXP OSS) data[i] = ret;
1193b050f2f1SRadu Pirea (NXP OSS) }
1194b050f2f1SRadu Pirea (NXP OSS) }
1195b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_config_enable(struct phy_device * phydev)1196b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev)
1197b050f2f1SRadu Pirea (NXP OSS) {
1198b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
1199b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_GLOBAL_EN |
1200b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_CONFIG_ALL_EN);
1201b050f2f1SRadu Pirea (NXP OSS) usleep_range(400, 450);
1202b050f2f1SRadu Pirea (NXP OSS)
1203b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL,
1204b050f2f1SRadu Pirea (NXP OSS) PORT_CONTROL_EN);
1205b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
1206b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_EN);
1207b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL,
1208b050f2f1SRadu Pirea (NXP OSS) PORT_INFRA_CONTROL_EN);
1209b050f2f1SRadu Pirea (NXP OSS)
1210b050f2f1SRadu Pirea (NXP OSS) return 0;
1211b050f2f1SRadu Pirea (NXP OSS) }
1212b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_start_op(struct phy_device * phydev)1213b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev)
1214b050f2f1SRadu Pirea (NXP OSS) {
1215b050f2f1SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
1216b050f2f1SRadu Pirea (NXP OSS) PHY_START_OP);
1217b050f2f1SRadu Pirea (NXP OSS) }
1218b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_config_intr(struct phy_device * phydev)1219b2f0ca00SRadu Pirea (NXP OSS) static int nxp_c45_config_intr(struct phy_device *phydev)
1220b2f0ca00SRadu Pirea (NXP OSS) {
1221b2f0ca00SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
1222b2f0ca00SRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1223b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
1224b2f0ca00SRadu Pirea (NXP OSS) else
1225b2f0ca00SRadu Pirea (NXP OSS) return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1226b2f0ca00SRadu Pirea (NXP OSS) VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
1227b2f0ca00SRadu Pirea (NXP OSS) }
1228b2f0ca00SRadu Pirea (NXP OSS)
tja1103_config_intr(struct phy_device * phydev)1229425c8348SRadu Pirea (NXP OSS) static int tja1103_config_intr(struct phy_device *phydev)
1230425c8348SRadu Pirea (NXP OSS) {
1231425c8348SRadu Pirea (NXP OSS) int ret;
1232425c8348SRadu Pirea (NXP OSS)
1233425c8348SRadu Pirea (NXP OSS) /* We can't disable the FUSA IRQ for TJA1103, but we can clean it up. */
1234425c8348SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_ALWAYS_ACCESSIBLE,
1235425c8348SRadu Pirea (NXP OSS) FUSA_PASS);
1236425c8348SRadu Pirea (NXP OSS) if (ret)
1237425c8348SRadu Pirea (NXP OSS) return ret;
1238425c8348SRadu Pirea (NXP OSS)
1239425c8348SRadu Pirea (NXP OSS) return nxp_c45_config_intr(phydev);
1240425c8348SRadu Pirea (NXP OSS) }
1241425c8348SRadu Pirea (NXP OSS)
tja1120_config_intr(struct phy_device * phydev)1242425c8348SRadu Pirea (NXP OSS) static int tja1120_config_intr(struct phy_device *phydev)
1243425c8348SRadu Pirea (NXP OSS) {
1244425c8348SRadu Pirea (NXP OSS) int ret;
1245425c8348SRadu Pirea (NXP OSS)
1246425c8348SRadu Pirea (NXP OSS) if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
1247425c8348SRadu Pirea (NXP OSS) ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1248425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_EN,
1249425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE);
1250425c8348SRadu Pirea (NXP OSS) else
1251425c8348SRadu Pirea (NXP OSS) ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1252425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_EN,
1253425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE);
1254425c8348SRadu Pirea (NXP OSS) if (ret)
1255425c8348SRadu Pirea (NXP OSS) return ret;
1256425c8348SRadu Pirea (NXP OSS)
1257425c8348SRadu Pirea (NXP OSS) return nxp_c45_config_intr(phydev);
1258425c8348SRadu Pirea (NXP OSS) }
1259425c8348SRadu Pirea (NXP OSS)
nxp_c45_handle_interrupt(struct phy_device * phydev)1260b2f0ca00SRadu Pirea (NXP OSS) static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev)
1261b2f0ca00SRadu Pirea (NXP OSS) {
12626c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev);
1263514def5dSRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv;
1264b2f0ca00SRadu Pirea (NXP OSS) irqreturn_t ret = IRQ_NONE;
1265514def5dSRadu Pirea (NXP OSS) struct nxp_c45_hwts hwts;
1266b2f0ca00SRadu Pirea (NXP OSS) int irq;
1267b2f0ca00SRadu Pirea (NXP OSS)
1268b2f0ca00SRadu Pirea (NXP OSS) irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS);
1269b2f0ca00SRadu Pirea (NXP OSS) if (irq & PHY_IRQ_LINK_EVENT) {
1270b2f0ca00SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK,
1271b2f0ca00SRadu Pirea (NXP OSS) PHY_IRQ_LINK_EVENT);
1272b2f0ca00SRadu Pirea (NXP OSS) phy_trigger_machine(phydev);
1273b2f0ca00SRadu Pirea (NXP OSS) ret = IRQ_HANDLED;
1274b2f0ca00SRadu Pirea (NXP OSS) }
1275b2f0ca00SRadu Pirea (NXP OSS)
12766c0c85daSRadu Pirea (NXP OSS) irq = nxp_c45_read_reg_field(phydev, &data->regmap->irq_egr_ts_status);
12776c0c85daSRadu Pirea (NXP OSS) if (irq) {
1278bdb4c5b8SRadu Pirea (NXP OSS) /* If ack_ptp_irq is false, the IRQ bit is self-clear and will
1279bdb4c5b8SRadu Pirea (NXP OSS) * be cleared when the EGR TS FIFO is empty. Otherwise, the
1280bdb4c5b8SRadu Pirea (NXP OSS) * IRQ bit should be cleared before reading the timestamp,
1281bdb4c5b8SRadu Pirea (NXP OSS) */
1282bdb4c5b8SRadu Pirea (NXP OSS) if (data->ack_ptp_irq)
1283bdb4c5b8SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
1284bdb4c5b8SRadu Pirea (NXP OSS) VEND1_PTP_IRQ_ACK, EGR_TS_IRQ);
1285bdb4c5b8SRadu Pirea (NXP OSS) while (data->get_egressts(priv, &hwts))
1286514def5dSRadu Pirea (NXP OSS) nxp_c45_process_txts(priv, &hwts);
1287514def5dSRadu Pirea (NXP OSS)
1288514def5dSRadu Pirea (NXP OSS) ret = IRQ_HANDLED;
1289514def5dSRadu Pirea (NXP OSS) }
1290514def5dSRadu Pirea (NXP OSS)
1291425c8348SRadu Pirea (NXP OSS) data->nmi_handler(phydev, &ret);
1292425c8348SRadu Pirea (NXP OSS)
1293b2f0ca00SRadu Pirea (NXP OSS) return ret;
1294b2f0ca00SRadu Pirea (NXP OSS) }
1295b2f0ca00SRadu Pirea (NXP OSS)
nxp_c45_soft_reset(struct phy_device * phydev)1296b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev)
1297b050f2f1SRadu Pirea (NXP OSS) {
1298b050f2f1SRadu Pirea (NXP OSS) int ret;
1299b050f2f1SRadu Pirea (NXP OSS)
1300b050f2f1SRadu Pirea (NXP OSS) ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
1301b050f2f1SRadu Pirea (NXP OSS) DEVICE_CONTROL_RESET);
1302b050f2f1SRadu Pirea (NXP OSS) if (ret)
1303b050f2f1SRadu Pirea (NXP OSS) return ret;
1304b050f2f1SRadu Pirea (NXP OSS)
1305b050f2f1SRadu Pirea (NXP OSS) return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
1306b050f2f1SRadu Pirea (NXP OSS) VEND1_DEVICE_CONTROL, ret,
1307b050f2f1SRadu Pirea (NXP OSS) !(ret & DEVICE_CONTROL_RESET), 20000,
1308b050f2f1SRadu Pirea (NXP OSS) 240000, false);
1309b050f2f1SRadu Pirea (NXP OSS) }
1310b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_cable_test_start(struct phy_device * phydev)1311b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev)
1312b050f2f1SRadu Pirea (NXP OSS) {
13136c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev);
13146c0c85daSRadu Pirea (NXP OSS)
1315c552c110SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1316c552c110SRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE);
13176c0c85daSRadu Pirea (NXP OSS) return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test,
1318b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE | CABLE_TEST_START);
1319b050f2f1SRadu Pirea (NXP OSS) }
1320b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_cable_test_get_status(struct phy_device * phydev,bool * finished)1321b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev,
1322b050f2f1SRadu Pirea (NXP OSS) bool *finished)
1323b050f2f1SRadu Pirea (NXP OSS) {
13246c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev);
1325b050f2f1SRadu Pirea (NXP OSS) int ret;
1326b050f2f1SRadu Pirea (NXP OSS) u8 cable_test_result;
1327b050f2f1SRadu Pirea (NXP OSS)
13286c0c85daSRadu Pirea (NXP OSS) ret = nxp_c45_read_reg_field(phydev, ®map->cable_test_valid);
13296c0c85daSRadu Pirea (NXP OSS) if (!ret) {
1330b050f2f1SRadu Pirea (NXP OSS) *finished = false;
1331b050f2f1SRadu Pirea (NXP OSS) return 0;
1332b050f2f1SRadu Pirea (NXP OSS) }
1333b050f2f1SRadu Pirea (NXP OSS)
1334b050f2f1SRadu Pirea (NXP OSS) *finished = true;
13356c0c85daSRadu Pirea (NXP OSS) cable_test_result = nxp_c45_read_reg_field(phydev,
13366c0c85daSRadu Pirea (NXP OSS) ®map->cable_test_result);
1337b050f2f1SRadu Pirea (NXP OSS)
1338b050f2f1SRadu Pirea (NXP OSS) switch (cable_test_result) {
1339b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OK:
1340b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
1341b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OK);
1342b050f2f1SRadu Pirea (NXP OSS) break;
1343b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_SHORTED:
1344b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
1345b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT);
1346b050f2f1SRadu Pirea (NXP OSS) break;
1347b050f2f1SRadu Pirea (NXP OSS) case CABLE_TEST_OPEN:
1348b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
1349b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_OPEN);
1350b050f2f1SRadu Pirea (NXP OSS) break;
1351b050f2f1SRadu Pirea (NXP OSS) default:
1352b050f2f1SRadu Pirea (NXP OSS) ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
1353b050f2f1SRadu Pirea (NXP OSS) ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC);
1354b050f2f1SRadu Pirea (NXP OSS) }
1355b050f2f1SRadu Pirea (NXP OSS)
13566c0c85daSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test,
1357b050f2f1SRadu Pirea (NXP OSS) CABLE_TEST_ENABLE);
1358c552c110SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1359c552c110SRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE);
1360b050f2f1SRadu Pirea (NXP OSS)
1361b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev);
1362b050f2f1SRadu Pirea (NXP OSS) }
1363b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_get_sqi(struct phy_device * phydev)1364b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev)
1365b050f2f1SRadu Pirea (NXP OSS) {
1366b050f2f1SRadu Pirea (NXP OSS) int reg;
1367b050f2f1SRadu Pirea (NXP OSS)
1368b050f2f1SRadu Pirea (NXP OSS) reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY);
1369b050f2f1SRadu Pirea (NXP OSS) if (!(reg & SQI_VALID))
1370b050f2f1SRadu Pirea (NXP OSS) return -EINVAL;
1371b050f2f1SRadu Pirea (NXP OSS)
1372b050f2f1SRadu Pirea (NXP OSS) reg &= SQI_MASK;
1373b050f2f1SRadu Pirea (NXP OSS)
1374b050f2f1SRadu Pirea (NXP OSS) return reg;
1375b050f2f1SRadu Pirea (NXP OSS) }
1376b050f2f1SRadu Pirea (NXP OSS)
tja1120_link_change_notify(struct phy_device * phydev)1377*68c6af72SRadu Pirea (NXP OSS) static void tja1120_link_change_notify(struct phy_device *phydev)
1378*68c6af72SRadu Pirea (NXP OSS) {
1379*68c6af72SRadu Pirea (NXP OSS) /* Bug workaround for TJA1120 enegineering samples: fix egress
1380*68c6af72SRadu Pirea (NXP OSS) * timestamps lost after link recovery.
1381*68c6af72SRadu Pirea (NXP OSS) */
1382*68c6af72SRadu Pirea (NXP OSS) if (phydev->state == PHY_NOLINK) {
1383*68c6af72SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1384*68c6af72SRadu Pirea (NXP OSS) TJA1120_EPHY_RESETS, EPHY_PCS_RESET);
1385*68c6af72SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1386*68c6af72SRadu Pirea (NXP OSS) TJA1120_EPHY_RESETS, EPHY_PCS_RESET);
1387*68c6af72SRadu Pirea (NXP OSS) }
1388*68c6af72SRadu Pirea (NXP OSS) }
1389*68c6af72SRadu Pirea (NXP OSS)
nxp_c45_get_sqi_max(struct phy_device * phydev)1390b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev)
1391b050f2f1SRadu Pirea (NXP OSS) {
1392b050f2f1SRadu Pirea (NXP OSS) return MAX_SQI;
1393b050f2f1SRadu Pirea (NXP OSS) }
1394b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_check_delay(struct phy_device * phydev,u32 delay)1395b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay)
1396b050f2f1SRadu Pirea (NXP OSS) {
1397b050f2f1SRadu Pirea (NXP OSS) if (delay < MIN_ID_PS) {
1398b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS);
1399b050f2f1SRadu Pirea (NXP OSS) return -EINVAL;
1400b050f2f1SRadu Pirea (NXP OSS) }
1401b050f2f1SRadu Pirea (NXP OSS)
1402b050f2f1SRadu Pirea (NXP OSS) if (delay > MAX_ID_PS) {
1403b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS);
1404b050f2f1SRadu Pirea (NXP OSS) return -EINVAL;
1405b050f2f1SRadu Pirea (NXP OSS) }
1406b050f2f1SRadu Pirea (NXP OSS)
1407b050f2f1SRadu Pirea (NXP OSS) return 0;
1408b050f2f1SRadu Pirea (NXP OSS) }
1409b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_counters_enable(struct phy_device * phydev)14106c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_counters_enable(struct phy_device *phydev)
14116c0c85daSRadu Pirea (NXP OSS) {
14126c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev);
14136c0c85daSRadu Pirea (NXP OSS)
14146c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER,
14156c0c85daSRadu Pirea (NXP OSS) COUNTER_EN);
14166c0c85daSRadu Pirea (NXP OSS)
14176c0c85daSRadu Pirea (NXP OSS) data->counters_enable(phydev);
14186c0c85daSRadu Pirea (NXP OSS) }
14196c0c85daSRadu Pirea (NXP OSS)
nxp_c45_ptp_init(struct phy_device * phydev)14206c0c85daSRadu Pirea (NXP OSS) static void nxp_c45_ptp_init(struct phy_device *phydev)
14216c0c85daSRadu Pirea (NXP OSS) {
14226c0c85daSRadu Pirea (NXP OSS) const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev);
14236c0c85daSRadu Pirea (NXP OSS)
14246c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
14256c0c85daSRadu Pirea (NXP OSS) data->regmap->vend1_ptp_clk_period,
14266c0c85daSRadu Pirea (NXP OSS) data->ptp_clk_period);
14276c0c85daSRadu Pirea (NXP OSS) nxp_c45_clear_reg_field(phydev, &data->regmap->ltc_lock_ctrl);
14286c0c85daSRadu Pirea (NXP OSS)
14296c0c85daSRadu Pirea (NXP OSS) data->ptp_init(phydev);
14306c0c85daSRadu Pirea (NXP OSS) }
14316c0c85daSRadu Pirea (NXP OSS)
nxp_c45_get_phase_shift(u64 phase_offset_raw)1432b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw)
1433b050f2f1SRadu Pirea (NXP OSS) {
1434b050f2f1SRadu Pirea (NXP OSS) /* The delay in degree phase is 73.8 + phase_offset_raw * 0.9.
1435b050f2f1SRadu Pirea (NXP OSS) * To avoid floating point operations we'll multiply by 10
1436b050f2f1SRadu Pirea (NXP OSS) * and get 1 decimal point precision.
1437b050f2f1SRadu Pirea (NXP OSS) */
1438b050f2f1SRadu Pirea (NXP OSS) phase_offset_raw *= 10;
14396b3a6310SRadu Pirea (NXP OSS) phase_offset_raw -= 738;
1440b050f2f1SRadu Pirea (NXP OSS) return div_u64(phase_offset_raw, 9);
1441b050f2f1SRadu Pirea (NXP OSS) }
1442b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_disable_delays(struct phy_device * phydev)1443b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev)
1444b050f2f1SRadu Pirea (NXP OSS) {
1445b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE);
1446b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE);
1447b050f2f1SRadu Pirea (NXP OSS) }
1448b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_set_delays(struct phy_device * phydev)1449b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev)
1450b050f2f1SRadu Pirea (NXP OSS) {
1451b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv;
1452b050f2f1SRadu Pirea (NXP OSS) u64 tx_delay = priv->tx_delay;
1453b050f2f1SRadu Pirea (NXP OSS) u64 rx_delay = priv->rx_delay;
1454b050f2f1SRadu Pirea (NXP OSS) u64 degree;
1455b050f2f1SRadu Pirea (NXP OSS)
1456b050f2f1SRadu Pirea (NXP OSS) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
1457b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
1458b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(tx_delay, PS_PER_DEGREE);
1459b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
1460b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree));
1461b050f2f1SRadu Pirea (NXP OSS) } else {
1462b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
1463b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE);
1464b050f2f1SRadu Pirea (NXP OSS) }
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_RXID) {
1468b050f2f1SRadu Pirea (NXP OSS) degree = div_u64(rx_delay, PS_PER_DEGREE);
1469b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
1470b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE | nxp_c45_get_phase_shift(degree));
1471b050f2f1SRadu Pirea (NXP OSS) } else {
1472b050f2f1SRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
1473b050f2f1SRadu Pirea (NXP OSS) ID_ENABLE);
1474b050f2f1SRadu Pirea (NXP OSS) }
1475b050f2f1SRadu Pirea (NXP OSS) }
1476b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_get_delays(struct phy_device * phydev)1477b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev)
1478b050f2f1SRadu Pirea (NXP OSS) {
1479b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv = phydev->priv;
1480b050f2f1SRadu Pirea (NXP OSS) int ret;
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_TXID) {
1484b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev,
1485b050f2f1SRadu Pirea (NXP OSS) "tx-internal-delay-ps",
1486b050f2f1SRadu Pirea (NXP OSS) &priv->tx_delay);
1487b050f2f1SRadu Pirea (NXP OSS) if (ret)
1488b050f2f1SRadu Pirea (NXP OSS) priv->tx_delay = DEFAULT_ID_PS;
1489b050f2f1SRadu Pirea (NXP OSS)
1490b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->tx_delay);
1491b050f2f1SRadu Pirea (NXP OSS) if (ret) {
1492b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev,
1493b050f2f1SRadu Pirea (NXP OSS) "tx-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) if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
1499b050f2f1SRadu Pirea (NXP OSS) phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
1500b050f2f1SRadu Pirea (NXP OSS) ret = device_property_read_u32(&phydev->mdio.dev,
1501b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps",
1502b050f2f1SRadu Pirea (NXP OSS) &priv->rx_delay);
1503b050f2f1SRadu Pirea (NXP OSS) if (ret)
1504b050f2f1SRadu Pirea (NXP OSS) priv->rx_delay = DEFAULT_ID_PS;
1505b050f2f1SRadu Pirea (NXP OSS)
1506b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_check_delay(phydev, priv->rx_delay);
1507b050f2f1SRadu Pirea (NXP OSS) if (ret) {
1508b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev,
1509b050f2f1SRadu Pirea (NXP OSS) "rx-internal-delay-ps invalid value\n");
1510b050f2f1SRadu Pirea (NXP OSS) return ret;
1511b050f2f1SRadu Pirea (NXP OSS) }
1512b050f2f1SRadu Pirea (NXP OSS) }
1513b050f2f1SRadu Pirea (NXP OSS)
1514b050f2f1SRadu Pirea (NXP OSS) return 0;
1515b050f2f1SRadu Pirea (NXP OSS) }
1516b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_set_phy_mode(struct phy_device * phydev)1517b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev)
1518b050f2f1SRadu Pirea (NXP OSS) {
1519b050f2f1SRadu Pirea (NXP OSS) int ret;
1520b050f2f1SRadu Pirea (NXP OSS)
1521b050f2f1SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES);
1522b050f2f1SRadu Pirea (NXP OSS) phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret);
1523b050f2f1SRadu Pirea (NXP OSS)
1524b050f2f1SRadu Pirea (NXP OSS) switch (phydev->interface) {
1525b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII:
1526b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ABILITY)) {
1527b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii mode not supported\n");
1528b050f2f1SRadu Pirea (NXP OSS) return -EINVAL;
1529b050f2f1SRadu Pirea (NXP OSS) }
1530b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1531b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII);
1532b050f2f1SRadu Pirea (NXP OSS) nxp_c45_disable_delays(phydev);
1533b050f2f1SRadu Pirea (NXP OSS) break;
1534b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_ID:
1535b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_TXID:
1536b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RGMII_RXID:
1537b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RGMII_ID_ABILITY)) {
1538b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n");
1539b050f2f1SRadu Pirea (NXP OSS) return -EINVAL;
1540b050f2f1SRadu Pirea (NXP OSS) }
1541b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1542b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RGMII);
1543b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_get_delays(phydev);
1544b050f2f1SRadu Pirea (NXP OSS) if (ret)
1545b050f2f1SRadu Pirea (NXP OSS) return ret;
1546b050f2f1SRadu Pirea (NXP OSS)
1547b050f2f1SRadu Pirea (NXP OSS) nxp_c45_set_delays(phydev);
1548b050f2f1SRadu Pirea (NXP OSS) break;
1549b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_MII:
1550b050f2f1SRadu Pirea (NXP OSS) if (!(ret & MII_ABILITY)) {
1551b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "mii 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_MII);
1556b050f2f1SRadu Pirea (NXP OSS) break;
1557b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_REVMII:
1558b050f2f1SRadu Pirea (NXP OSS) if (!(ret & REVMII_ABILITY)) {
1559b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rev-mii 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_MII | MII_BASIC_CONFIG_REV);
1564b050f2f1SRadu Pirea (NXP OSS) break;
1565b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_RMII:
1566b050f2f1SRadu Pirea (NXP OSS) if (!(ret & RMII_ABILITY)) {
1567b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "rmii mode not supported\n");
1568b050f2f1SRadu Pirea (NXP OSS) return -EINVAL;
1569b050f2f1SRadu Pirea (NXP OSS) }
1570b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1571b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_RMII);
1572b050f2f1SRadu Pirea (NXP OSS) break;
1573b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_SGMII:
1574b050f2f1SRadu Pirea (NXP OSS) if (!(ret & SGMII_ABILITY)) {
1575b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "sgmii mode not supported\n");
1576b050f2f1SRadu Pirea (NXP OSS) return -EINVAL;
1577b050f2f1SRadu Pirea (NXP OSS) }
1578b050f2f1SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
1579b050f2f1SRadu Pirea (NXP OSS) MII_BASIC_CONFIG_SGMII);
1580b050f2f1SRadu Pirea (NXP OSS) break;
1581b050f2f1SRadu Pirea (NXP OSS) case PHY_INTERFACE_MODE_INTERNAL:
1582b050f2f1SRadu Pirea (NXP OSS) break;
1583b050f2f1SRadu Pirea (NXP OSS) default:
1584b050f2f1SRadu Pirea (NXP OSS) return -EINVAL;
1585b050f2f1SRadu Pirea (NXP OSS) }
1586b050f2f1SRadu Pirea (NXP OSS)
1587b050f2f1SRadu Pirea (NXP OSS) return 0;
1588b050f2f1SRadu Pirea (NXP OSS) }
1589b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_config_init(struct phy_device * phydev)1590b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev)
1591b050f2f1SRadu Pirea (NXP OSS) {
1592b050f2f1SRadu Pirea (NXP OSS) int ret;
1593b050f2f1SRadu Pirea (NXP OSS)
1594b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_config_enable(phydev);
1595b050f2f1SRadu Pirea (NXP OSS) if (ret) {
1596b050f2f1SRadu Pirea (NXP OSS) phydev_err(phydev, "Failed to enable config\n");
1597b050f2f1SRadu Pirea (NXP OSS) return ret;
1598b050f2f1SRadu Pirea (NXP OSS) }
1599b050f2f1SRadu Pirea (NXP OSS)
16000b5f0f29SVladimir Oltean /* Bug workaround for SJA1110 rev B: enable write access
16010b5f0f29SVladimir Oltean * to MDIO_MMD_PMAPMD
16020b5f0f29SVladimir Oltean */
16030b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1);
16040b5f0f29SVladimir Oltean phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2);
16050b5f0f29SVladimir Oltean
1606b050f2f1SRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG,
1607b050f2f1SRadu Pirea (NXP OSS) PHY_CONFIG_AUTO);
1608b050f2f1SRadu Pirea (NXP OSS)
1609b050f2f1SRadu Pirea (NXP OSS) ret = nxp_c45_set_phy_mode(phydev);
1610b050f2f1SRadu Pirea (NXP OSS) if (ret)
1611b050f2f1SRadu Pirea (NXP OSS) return ret;
1612b050f2f1SRadu Pirea (NXP OSS)
1613b050f2f1SRadu Pirea (NXP OSS) phydev->autoneg = AUTONEG_DISABLE;
1614b050f2f1SRadu Pirea (NXP OSS)
16156c0c85daSRadu Pirea (NXP OSS) nxp_c45_counters_enable(phydev);
16166c0c85daSRadu Pirea (NXP OSS) nxp_c45_ptp_init(phydev);
1617514def5dSRadu Pirea (NXP OSS)
1618b050f2f1SRadu Pirea (NXP OSS) return nxp_c45_start_op(phydev);
1619b050f2f1SRadu Pirea (NXP OSS) }
1620b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_get_features(struct phy_device * phydev)1621369da333SRadu Pirea (NXP OSS) static int nxp_c45_get_features(struct phy_device *phydev)
1622369da333SRadu Pirea (NXP OSS) {
1623369da333SRadu Pirea (NXP OSS) linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported);
1624369da333SRadu Pirea (NXP OSS) linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported);
1625369da333SRadu Pirea (NXP OSS)
1626369da333SRadu Pirea (NXP OSS) return genphy_c45_pma_read_abilities(phydev);
1627369da333SRadu Pirea (NXP OSS) }
1628369da333SRadu Pirea (NXP OSS)
nxp_c45_probe(struct phy_device * phydev)1629b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev)
1630b050f2f1SRadu Pirea (NXP OSS) {
1631b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy *priv;
1632514def5dSRadu Pirea (NXP OSS) int ptp_ability;
1633514def5dSRadu Pirea (NXP OSS) int ret = 0;
1634b050f2f1SRadu Pirea (NXP OSS)
1635b050f2f1SRadu Pirea (NXP OSS) priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
1636b050f2f1SRadu Pirea (NXP OSS) if (!priv)
1637b050f2f1SRadu Pirea (NXP OSS) return -ENOMEM;
1638b050f2f1SRadu Pirea (NXP OSS)
1639514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->tx_queue);
1640514def5dSRadu Pirea (NXP OSS) skb_queue_head_init(&priv->rx_queue);
1641514def5dSRadu Pirea (NXP OSS)
1642514def5dSRadu Pirea (NXP OSS) priv->phydev = phydev;
1643514def5dSRadu Pirea (NXP OSS)
1644b050f2f1SRadu Pirea (NXP OSS) phydev->priv = priv;
1645b050f2f1SRadu Pirea (NXP OSS)
1646514def5dSRadu Pirea (NXP OSS) mutex_init(&priv->ptp_lock);
1647514def5dSRadu Pirea (NXP OSS)
1648514def5dSRadu Pirea (NXP OSS) ptp_ability = phy_read_mmd(phydev, MDIO_MMD_VEND1,
1649514def5dSRadu Pirea (NXP OSS) VEND1_PORT_ABILITIES);
1650514def5dSRadu Pirea (NXP OSS) ptp_ability = !!(ptp_ability & PTP_ABILITY);
1651514def5dSRadu Pirea (NXP OSS) if (!ptp_ability) {
1652565c6d8cSVladimir Oltean phydev_dbg(phydev, "the phy does not support PTP");
1653514def5dSRadu Pirea (NXP OSS) goto no_ptp_support;
1654514def5dSRadu Pirea (NXP OSS) }
1655514def5dSRadu Pirea (NXP OSS)
1656514def5dSRadu Pirea (NXP OSS) if (IS_ENABLED(CONFIG_PTP_1588_CLOCK) &&
1657514def5dSRadu Pirea (NXP OSS) IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) {
1658514def5dSRadu Pirea (NXP OSS) priv->mii_ts.rxtstamp = nxp_c45_rxtstamp;
1659514def5dSRadu Pirea (NXP OSS) priv->mii_ts.txtstamp = nxp_c45_txtstamp;
1660514def5dSRadu Pirea (NXP OSS) priv->mii_ts.hwtstamp = nxp_c45_hwtstamp;
1661514def5dSRadu Pirea (NXP OSS) priv->mii_ts.ts_info = nxp_c45_ts_info;
1662514def5dSRadu Pirea (NXP OSS) phydev->mii_ts = &priv->mii_ts;
1663514def5dSRadu Pirea (NXP OSS) ret = nxp_c45_init_ptp_clock(priv);
1664514def5dSRadu Pirea (NXP OSS) } else {
1665514def5dSRadu Pirea (NXP OSS) phydev_dbg(phydev, "PTP support not enabled even if the phy supports it");
1666514def5dSRadu Pirea (NXP OSS) }
1667514def5dSRadu Pirea (NXP OSS)
1668514def5dSRadu Pirea (NXP OSS) no_ptp_support:
1669514def5dSRadu Pirea (NXP OSS)
1670514def5dSRadu Pirea (NXP OSS) return ret;
1671b050f2f1SRadu Pirea (NXP OSS) }
1672b050f2f1SRadu Pirea (NXP OSS)
nxp_c45_remove(struct phy_device * phydev)1673a4506722SRadu Pirea (OSS) static void nxp_c45_remove(struct phy_device *phydev)
1674a4506722SRadu Pirea (OSS) {
1675a4506722SRadu Pirea (OSS) struct nxp_c45_phy *priv = phydev->priv;
1676a4506722SRadu Pirea (OSS)
1677a4506722SRadu Pirea (OSS) if (priv->ptp_clock)
1678a4506722SRadu Pirea (OSS) ptp_clock_unregister(priv->ptp_clock);
1679a4506722SRadu Pirea (OSS)
1680a4506722SRadu Pirea (OSS) skb_queue_purge(&priv->tx_queue);
1681a4506722SRadu Pirea (OSS) skb_queue_purge(&priv->rx_queue);
1682a4506722SRadu Pirea (OSS) }
1683a4506722SRadu Pirea (OSS)
tja1103_counters_enable(struct phy_device * phydev)16846c0c85daSRadu Pirea (NXP OSS) static void tja1103_counters_enable(struct phy_device *phydev)
16856c0c85daSRadu Pirea (NXP OSS) {
16866c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT,
16876c0c85daSRadu Pirea (NXP OSS) COUNTER_EN);
16886c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT,
16896c0c85daSRadu Pirea (NXP OSS) COUNTER_EN);
16906c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH,
16916c0c85daSRadu Pirea (NXP OSS) COUNTER_EN);
16926c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH,
16936c0c85daSRadu Pirea (NXP OSS) COUNTER_EN);
16946c0c85daSRadu Pirea (NXP OSS) }
16956c0c85daSRadu Pirea (NXP OSS)
tja1103_ptp_init(struct phy_device * phydev)16966c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_init(struct phy_device *phydev)
16976c0c85daSRadu Pirea (NXP OSS) {
16986c0c85daSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_TS_INSRT_CTRL,
16996c0c85daSRadu Pirea (NXP OSS) TJA1103_RX_TS_INSRT_MODE2);
17006c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_FUNC_ENABLES,
17016c0c85daSRadu Pirea (NXP OSS) PTP_ENABLE);
17026c0c85daSRadu Pirea (NXP OSS) }
17036c0c85daSRadu Pirea (NXP OSS)
tja1103_ptp_enable(struct phy_device * phydev,bool enable)17046c0c85daSRadu Pirea (NXP OSS) static void tja1103_ptp_enable(struct phy_device *phydev, bool enable)
17056c0c85daSRadu Pirea (NXP OSS) {
17066c0c85daSRadu Pirea (NXP OSS) if (enable)
17076c0c85daSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
17086c0c85daSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL,
17096c0c85daSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS);
17106c0c85daSRadu Pirea (NXP OSS) else
17116c0c85daSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
17126c0c85daSRadu Pirea (NXP OSS) VEND1_PORT_PTP_CONTROL,
17136c0c85daSRadu Pirea (NXP OSS) PORT_PTP_CONTROL_BYPASS);
17146c0c85daSRadu Pirea (NXP OSS) }
17156c0c85daSRadu Pirea (NXP OSS)
tja1103_nmi_handler(struct phy_device * phydev,irqreturn_t * irq_status)1716425c8348SRadu Pirea (NXP OSS) static void tja1103_nmi_handler(struct phy_device *phydev,
1717425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status)
1718425c8348SRadu Pirea (NXP OSS) {
1719425c8348SRadu Pirea (NXP OSS) int ret;
1720425c8348SRadu Pirea (NXP OSS)
1721425c8348SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1,
1722425c8348SRadu Pirea (NXP OSS) VEND1_ALWAYS_ACCESSIBLE);
1723425c8348SRadu Pirea (NXP OSS) if (ret & FUSA_PASS) {
1724425c8348SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
1725425c8348SRadu Pirea (NXP OSS) VEND1_ALWAYS_ACCESSIBLE,
1726425c8348SRadu Pirea (NXP OSS) FUSA_PASS);
1727425c8348SRadu Pirea (NXP OSS) *irq_status = IRQ_HANDLED;
1728425c8348SRadu Pirea (NXP OSS) }
1729425c8348SRadu Pirea (NXP OSS) }
1730425c8348SRadu Pirea (NXP OSS)
17316c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1103_regmap = {
17326c0c85daSRadu Pirea (NXP OSS) .vend1_ptp_clk_period = 0x1104,
17336c0c85daSRadu Pirea (NXP OSS) .vend1_event_msg_filt = 0x1148,
17346c0c85daSRadu Pirea (NXP OSS) .pps_enable =
17356c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 3, 1),
17366c0c85daSRadu Pirea (NXP OSS) .pps_polarity =
17376c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1102, MDIO_MMD_VEND1, 2, 1),
17386c0c85daSRadu Pirea (NXP OSS) .ltc_lock_ctrl =
17396c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1115, MDIO_MMD_VEND1, 0, 1),
17406c0c85daSRadu Pirea (NXP OSS) .ltc_read =
17416c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 2, 1),
17426c0c85daSRadu Pirea (NXP OSS) .ltc_write =
17436c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1105, MDIO_MMD_VEND1, 0, 1),
17446c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_0 = 0x1106,
17456c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_1 = 0x1107,
17466c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_0 = 0x1108,
17476c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_1 = 0x1109,
17486c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_0 = 0x110A,
17496c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_1 = 0x110B,
17506c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_0 = 0x110C,
17516c0c85daSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_1 = 0x110D,
17526c0c85daSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_0 = 0x110F,
17536c0c85daSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_1 = 0x1110,
17546c0c85daSRadu Pirea (NXP OSS) .irq_egr_ts_en =
17556c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1131, MDIO_MMD_VEND1, 0, 1),
17566c0c85daSRadu Pirea (NXP OSS) .irq_egr_ts_status =
17576c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1132, MDIO_MMD_VEND1, 0, 1),
17586c0c85daSRadu Pirea (NXP OSS) .domain_number =
17596c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 0, 8),
17606c0c85daSRadu Pirea (NXP OSS) .msg_type =
17616c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 8, 4),
17626c0c85daSRadu Pirea (NXP OSS) .sequence_id =
17636c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114F, MDIO_MMD_VEND1, 0, 16),
17646c0c85daSRadu Pirea (NXP OSS) .sec_1_0 =
17656c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 14, 2),
17666c0c85daSRadu Pirea (NXP OSS) .sec_4_2 =
17676c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x114E, MDIO_MMD_VEND1, 12, 3),
17686c0c85daSRadu Pirea (NXP OSS) .nsec_15_0 =
17696c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1150, MDIO_MMD_VEND1, 0, 16),
17706c0c85daSRadu Pirea (NXP OSS) .nsec_29_16 =
17716c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1151, MDIO_MMD_VEND1, 0, 14),
17726c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_0 = 0x1121,
17736c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_1 = 0x1122,
17746c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_2 = 0x1123,
17756c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_data_3 = 0x1124,
17766c0c85daSRadu Pirea (NXP OSS) .vend1_ext_trg_ctrl = 0x1126,
17776c0c85daSRadu Pirea (NXP OSS) .cable_test = 0x8330,
17786c0c85daSRadu Pirea (NXP OSS) .cable_test_valid =
17796c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 13, 1),
17806c0c85daSRadu Pirea (NXP OSS) .cable_test_result =
17816c0c85daSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8330, MDIO_MMD_VEND1, 0, 3),
17826c0c85daSRadu Pirea (NXP OSS) };
17836c0c85daSRadu Pirea (NXP OSS)
17846c0c85daSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1103_phy_data = {
17856c0c85daSRadu Pirea (NXP OSS) .regmap = &tja1103_regmap,
17866c0c85daSRadu Pirea (NXP OSS) .stats = tja1103_hw_stats,
17876c0c85daSRadu Pirea (NXP OSS) .n_stats = ARRAY_SIZE(tja1103_hw_stats),
17886c0c85daSRadu Pirea (NXP OSS) .ptp_clk_period = PTP_CLK_PERIOD_100BT1,
1789b0b2247dSRadu Pirea (NXP OSS) .ext_ts_both_edges = false,
1790bdb4c5b8SRadu Pirea (NXP OSS) .ack_ptp_irq = false,
17916c0c85daSRadu Pirea (NXP OSS) .counters_enable = tja1103_counters_enable,
1792bdb4c5b8SRadu Pirea (NXP OSS) .get_egressts = nxp_c45_get_hwtxts,
179308e6547cSRadu Pirea (NXP OSS) .get_extts = nxp_c45_get_extts,
17946c0c85daSRadu Pirea (NXP OSS) .ptp_init = tja1103_ptp_init,
17956c0c85daSRadu Pirea (NXP OSS) .ptp_enable = tja1103_ptp_enable,
1796425c8348SRadu Pirea (NXP OSS) .nmi_handler = tja1103_nmi_handler,
17976c0c85daSRadu Pirea (NXP OSS) };
17986c0c85daSRadu Pirea (NXP OSS)
tja1120_counters_enable(struct phy_device * phydev)1799f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_counters_enable(struct phy_device *phydev)
1800f1fe5dffSRadu Pirea (NXP OSS) {
1801f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_SYMBOL_ERROR_CNT_XTD,
1802f1fe5dffSRadu Pirea (NXP OSS) EXTENDED_CNT_EN);
1803f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_STATUS,
1804f1fe5dffSRadu Pirea (NXP OSS) MONITOR_RESET);
1805f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_MONITOR_CONFIG,
1806f1fe5dffSRadu Pirea (NXP OSS) ALL_FRAMES_CNT_EN | LOST_FRAMES_CNT_EN);
1807f1fe5dffSRadu Pirea (NXP OSS) }
1808f1fe5dffSRadu Pirea (NXP OSS)
tja1120_ptp_init(struct phy_device * phydev)1809f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_init(struct phy_device *phydev)
1810f1fe5dffSRadu Pirea (NXP OSS) {
1811f1fe5dffSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_RX_TS_INSRT_CTRL,
1812f1fe5dffSRadu Pirea (NXP OSS) TJA1120_RX_TS_INSRT_EN | TJA1120_TS_INSRT_MODE);
1813f1fe5dffSRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1, TJA1120_VEND1_EXT_TS_MODE,
1814f1fe5dffSRadu Pirea (NXP OSS) TJA1120_TS_INSRT_MODE);
1815f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONFIG,
1816f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE);
1817f1fe5dffSRadu Pirea (NXP OSS) }
1818f1fe5dffSRadu Pirea (NXP OSS)
tja1120_ptp_enable(struct phy_device * phydev,bool enable)1819f1fe5dffSRadu Pirea (NXP OSS) static void tja1120_ptp_enable(struct phy_device *phydev, bool enable)
1820f1fe5dffSRadu Pirea (NXP OSS) {
1821f1fe5dffSRadu Pirea (NXP OSS) if (enable)
1822f1fe5dffSRadu Pirea (NXP OSS) phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
1823f1fe5dffSRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES,
1824f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE);
1825f1fe5dffSRadu Pirea (NXP OSS) else
1826f1fe5dffSRadu Pirea (NXP OSS) phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
1827f1fe5dffSRadu Pirea (NXP OSS) VEND1_PORT_FUNC_ENABLES,
1828f1fe5dffSRadu Pirea (NXP OSS) PTP_ENABLE);
1829f1fe5dffSRadu Pirea (NXP OSS) }
1830f1fe5dffSRadu Pirea (NXP OSS)
tja1120_nmi_handler(struct phy_device * phydev,irqreturn_t * irq_status)1831425c8348SRadu Pirea (NXP OSS) static void tja1120_nmi_handler(struct phy_device *phydev,
1832425c8348SRadu Pirea (NXP OSS) irqreturn_t *irq_status)
1833425c8348SRadu Pirea (NXP OSS) {
1834425c8348SRadu Pirea (NXP OSS) int ret;
1835425c8348SRadu Pirea (NXP OSS)
1836425c8348SRadu Pirea (NXP OSS) ret = phy_read_mmd(phydev, MDIO_MMD_VEND1,
1837425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_STATUS);
1838425c8348SRadu Pirea (NXP OSS) if (ret & TJA1120_DEV_BOOT_DONE) {
1839425c8348SRadu Pirea (NXP OSS) phy_write_mmd(phydev, MDIO_MMD_VEND1,
1840425c8348SRadu Pirea (NXP OSS) TJA1120_GLOBAL_INFRA_IRQ_ACK,
1841425c8348SRadu Pirea (NXP OSS) TJA1120_DEV_BOOT_DONE);
1842425c8348SRadu Pirea (NXP OSS) *irq_status = IRQ_HANDLED;
1843425c8348SRadu Pirea (NXP OSS) }
1844425c8348SRadu Pirea (NXP OSS) }
1845425c8348SRadu Pirea (NXP OSS)
1846f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_regmap tja1120_regmap = {
1847f1fe5dffSRadu Pirea (NXP OSS) .vend1_ptp_clk_period = 0x1020,
1848f1fe5dffSRadu Pirea (NXP OSS) .vend1_event_msg_filt = 0x9010,
1849f1fe5dffSRadu Pirea (NXP OSS) .pps_enable =
1850f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 4, 1),
1851f1fe5dffSRadu Pirea (NXP OSS) .pps_polarity =
1852f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 5, 1),
1853f1fe5dffSRadu Pirea (NXP OSS) .ltc_lock_ctrl =
1854f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1006, MDIO_MMD_VEND1, 2, 1),
1855f1fe5dffSRadu Pirea (NXP OSS) .ltc_read =
1856f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 1, 1),
1857f1fe5dffSRadu Pirea (NXP OSS) .ltc_write =
1858f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x1000, MDIO_MMD_VEND1, 2, 1),
1859f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_0 = 0x1040,
1860f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_nsec_1 = 0x1041,
1861f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_0 = 0x1042,
1862f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_wr_sec_1 = 0x1043,
1863f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_0 = 0x1048,
1864f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_nsec_1 = 0x1049,
1865f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_0 = 0x104A,
1866f1fe5dffSRadu Pirea (NXP OSS) .vend1_ltc_rd_sec_1 = 0x104B,
1867f1fe5dffSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_0 = 0x1030,
1868f1fe5dffSRadu Pirea (NXP OSS) .vend1_rate_adj_subns_1 = 0x1031,
1869f1fe5dffSRadu Pirea (NXP OSS) .irq_egr_ts_en =
1870f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x900A, MDIO_MMD_VEND1, 1, 1),
1871f1fe5dffSRadu Pirea (NXP OSS) .irq_egr_ts_status =
1872f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x900C, MDIO_MMD_VEND1, 1, 1),
1873f1fe5dffSRadu Pirea (NXP OSS) .domain_number =
1874f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 8, 8),
1875f1fe5dffSRadu Pirea (NXP OSS) .msg_type =
1876f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9061, MDIO_MMD_VEND1, 4, 4),
1877f1fe5dffSRadu Pirea (NXP OSS) .sequence_id =
1878f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9062, MDIO_MMD_VEND1, 0, 16),
1879f1fe5dffSRadu Pirea (NXP OSS) .sec_1_0 =
1880f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 0, 2),
1881f1fe5dffSRadu Pirea (NXP OSS) .sec_4_2 =
1882f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9065, MDIO_MMD_VEND1, 2, 3),
1883f1fe5dffSRadu Pirea (NXP OSS) .nsec_15_0 =
1884f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9063, MDIO_MMD_VEND1, 0, 16),
1885f1fe5dffSRadu Pirea (NXP OSS) .nsec_29_16 =
1886f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x9064, MDIO_MMD_VEND1, 0, 14),
1887f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_0 = 0x1071,
1888f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_1 = 0x1072,
1889f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_2 = 0x1073,
1890f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_data_3 = 0x1074,
1891f1fe5dffSRadu Pirea (NXP OSS) .vend1_ext_trg_ctrl = 0x1075,
1892f1fe5dffSRadu Pirea (NXP OSS) .cable_test = 0x8360,
1893f1fe5dffSRadu Pirea (NXP OSS) .cable_test_valid =
1894f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 15, 1),
1895f1fe5dffSRadu Pirea (NXP OSS) .cable_test_result =
1896f1fe5dffSRadu Pirea (NXP OSS) NXP_C45_REG_FIELD(0x8361, MDIO_MMD_VEND1, 0, 3),
1897f1fe5dffSRadu Pirea (NXP OSS) };
1898f1fe5dffSRadu Pirea (NXP OSS)
1899f1fe5dffSRadu Pirea (NXP OSS) static const struct nxp_c45_phy_data tja1120_phy_data = {
1900f1fe5dffSRadu Pirea (NXP OSS) .regmap = &tja1120_regmap,
1901f1fe5dffSRadu Pirea (NXP OSS) .stats = tja1120_hw_stats,
1902f1fe5dffSRadu Pirea (NXP OSS) .n_stats = ARRAY_SIZE(tja1120_hw_stats),
1903f1fe5dffSRadu Pirea (NXP OSS) .ptp_clk_period = PTP_CLK_PERIOD_1000BT1,
1904b0b2247dSRadu Pirea (NXP OSS) .ext_ts_both_edges = true,
1905bdb4c5b8SRadu Pirea (NXP OSS) .ack_ptp_irq = true,
1906f1fe5dffSRadu Pirea (NXP OSS) .counters_enable = tja1120_counters_enable,
1907bdb4c5b8SRadu Pirea (NXP OSS) .get_egressts = tja1120_get_hwtxts,
190808e6547cSRadu Pirea (NXP OSS) .get_extts = tja1120_get_extts,
1909f1fe5dffSRadu Pirea (NXP OSS) .ptp_init = tja1120_ptp_init,
1910f1fe5dffSRadu Pirea (NXP OSS) .ptp_enable = tja1120_ptp_enable,
1911425c8348SRadu Pirea (NXP OSS) .nmi_handler = tja1120_nmi_handler,
1912f1fe5dffSRadu Pirea (NXP OSS) };
1913f1fe5dffSRadu Pirea (NXP OSS)
1914b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = {
1915b050f2f1SRadu Pirea (NXP OSS) {
1916b050f2f1SRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
1917b050f2f1SRadu Pirea (NXP OSS) .name = "NXP C45 TJA1103",
1918369da333SRadu Pirea (NXP OSS) .get_features = nxp_c45_get_features,
19196c0c85daSRadu Pirea (NXP OSS) .driver_data = &tja1103_phy_data,
1920b050f2f1SRadu Pirea (NXP OSS) .probe = nxp_c45_probe,
1921b050f2f1SRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset,
1922ac0687e8SRadu Pirea (NXP OSS) .config_aneg = genphy_c45_config_aneg,
1923b050f2f1SRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init,
1924425c8348SRadu Pirea (NXP OSS) .config_intr = tja1103_config_intr,
1925b2f0ca00SRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt,
1926ac0687e8SRadu Pirea (NXP OSS) .read_status = genphy_c45_read_status,
1927b050f2f1SRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend,
1928b050f2f1SRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume,
1929b050f2f1SRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count,
1930b050f2f1SRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings,
1931b050f2f1SRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats,
1932b050f2f1SRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start,
1933b050f2f1SRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status,
1934b050f2f1SRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback,
1935b050f2f1SRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi,
1936b050f2f1SRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max,
1937a4506722SRadu Pirea (OSS) .remove = nxp_c45_remove,
1938b050f2f1SRadu Pirea (NXP OSS) },
1939f1fe5dffSRadu Pirea (NXP OSS) {
1940f1fe5dffSRadu Pirea (NXP OSS) PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120),
1941f1fe5dffSRadu Pirea (NXP OSS) .name = "NXP C45 TJA1120",
1942f1fe5dffSRadu Pirea (NXP OSS) .get_features = nxp_c45_get_features,
1943f1fe5dffSRadu Pirea (NXP OSS) .driver_data = &tja1120_phy_data,
1944f1fe5dffSRadu Pirea (NXP OSS) .probe = nxp_c45_probe,
1945f1fe5dffSRadu Pirea (NXP OSS) .soft_reset = nxp_c45_soft_reset,
1946f1fe5dffSRadu Pirea (NXP OSS) .config_aneg = genphy_c45_config_aneg,
1947f1fe5dffSRadu Pirea (NXP OSS) .config_init = nxp_c45_config_init,
1948425c8348SRadu Pirea (NXP OSS) .config_intr = tja1120_config_intr,
1949f1fe5dffSRadu Pirea (NXP OSS) .handle_interrupt = nxp_c45_handle_interrupt,
1950f1fe5dffSRadu Pirea (NXP OSS) .read_status = genphy_c45_read_status,
1951*68c6af72SRadu Pirea (NXP OSS) .link_change_notify = tja1120_link_change_notify,
1952f1fe5dffSRadu Pirea (NXP OSS) .suspend = genphy_c45_pma_suspend,
1953f1fe5dffSRadu Pirea (NXP OSS) .resume = genphy_c45_pma_resume,
1954f1fe5dffSRadu Pirea (NXP OSS) .get_sset_count = nxp_c45_get_sset_count,
1955f1fe5dffSRadu Pirea (NXP OSS) .get_strings = nxp_c45_get_strings,
1956f1fe5dffSRadu Pirea (NXP OSS) .get_stats = nxp_c45_get_stats,
1957f1fe5dffSRadu Pirea (NXP OSS) .cable_test_start = nxp_c45_cable_test_start,
1958f1fe5dffSRadu Pirea (NXP OSS) .cable_test_get_status = nxp_c45_cable_test_get_status,
1959f1fe5dffSRadu Pirea (NXP OSS) .set_loopback = genphy_c45_loopback,
1960f1fe5dffSRadu Pirea (NXP OSS) .get_sqi = nxp_c45_get_sqi,
1961f1fe5dffSRadu Pirea (NXP OSS) .get_sqi_max = nxp_c45_get_sqi_max,
1962f1fe5dffSRadu Pirea (NXP OSS) .remove = nxp_c45_remove,
1963f1fe5dffSRadu Pirea (NXP OSS) },
1964b050f2f1SRadu Pirea (NXP OSS) };
1965b050f2f1SRadu Pirea (NXP OSS)
1966b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver);
1967b050f2f1SRadu Pirea (NXP OSS)
1968b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = {
1969b050f2f1SRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) },
1970f1fe5dffSRadu Pirea (NXP OSS) { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120) },
1971b050f2f1SRadu Pirea (NXP OSS) { /*sentinel*/ },
1972b050f2f1SRadu Pirea (NXP OSS) };
1973b050f2f1SRadu Pirea (NXP OSS)
1974b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl);
1975b050f2f1SRadu Pirea (NXP OSS)
1976b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>");
1977b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver");
1978b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2");
1979