xref: /openbmc/linux/drivers/net/phy/nxp-c45-tja11xx.c (revision 6b3a63100dedfa1f0887eb316110d5d7b0c51ed4)
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>
16b050f2f1SRadu Pirea (NXP OSS) 
17b050f2f1SRadu Pirea (NXP OSS) #define PHY_ID_TJA_1103			0x001BB010
18b050f2f1SRadu Pirea (NXP OSS) 
19b050f2f1SRadu Pirea (NXP OSS) #define PMAPMD_B100T1_PMAPMD_CTL	0x0834
20b050f2f1SRadu Pirea (NXP OSS) #define B100T1_PMAPMD_CONFIG_EN		BIT(15)
21b050f2f1SRadu Pirea (NXP OSS) #define B100T1_PMAPMD_MASTER		BIT(14)
22b050f2f1SRadu Pirea (NXP OSS) #define MASTER_MODE			(B100T1_PMAPMD_CONFIG_EN | \
23b050f2f1SRadu Pirea (NXP OSS) 					 B100T1_PMAPMD_MASTER)
24b050f2f1SRadu Pirea (NXP OSS) #define SLAVE_MODE			(B100T1_PMAPMD_CONFIG_EN)
25b050f2f1SRadu Pirea (NXP OSS) 
26b050f2f1SRadu Pirea (NXP OSS) #define VEND1_DEVICE_CONTROL		0x0040
27b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_RESET		BIT(15)
28b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_GLOBAL_EN	BIT(14)
29b050f2f1SRadu Pirea (NXP OSS) #define DEVICE_CONTROL_CONFIG_ALL_EN	BIT(13)
30b050f2f1SRadu Pirea (NXP OSS) 
31b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONTROL		0x8100
32b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_EN			BIT(14)
33b050f2f1SRadu Pirea (NXP OSS) #define PHY_START_OP			BIT(0)
34b050f2f1SRadu Pirea (NXP OSS) 
35b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PHY_CONFIG		0x8108
36b050f2f1SRadu Pirea (NXP OSS) #define PHY_CONFIG_AUTO			BIT(0)
37b050f2f1SRadu Pirea (NXP OSS) 
38b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SIGNAL_QUALITY		0x8320
39b050f2f1SRadu Pirea (NXP OSS) #define SQI_VALID			BIT(14)
40b050f2f1SRadu Pirea (NXP OSS) #define SQI_MASK			GENMASK(2, 0)
41b050f2f1SRadu Pirea (NXP OSS) #define MAX_SQI				SQI_MASK
42b050f2f1SRadu Pirea (NXP OSS) 
43b050f2f1SRadu Pirea (NXP OSS) #define VEND1_CABLE_TEST		0x8330
44b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_ENABLE		BIT(15)
45b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_START		BIT(14)
46b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_VALID		BIT(13)
47b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OK			0x00
48b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_SHORTED		0x01
49b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_OPEN			0x02
50b050f2f1SRadu Pirea (NXP OSS) #define CABLE_TEST_UNKNOWN		0x07
51b050f2f1SRadu Pirea (NXP OSS) 
52b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_CONTROL		0x8040
53b050f2f1SRadu Pirea (NXP OSS) #define PORT_CONTROL_EN			BIT(14)
54b050f2f1SRadu Pirea (NXP OSS) 
55b050f2f1SRadu Pirea (NXP OSS) #define VEND1_PORT_INFRA_CONTROL	0xAC00
56b050f2f1SRadu Pirea (NXP OSS) #define PORT_INFRA_CONTROL_EN		BIT(14)
57b050f2f1SRadu Pirea (NXP OSS) 
58b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RXID			0xAFCC
59b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TXID			0xAFCD
60b050f2f1SRadu Pirea (NXP OSS) #define ID_ENABLE			BIT(15)
61b050f2f1SRadu Pirea (NXP OSS) 
62b050f2f1SRadu Pirea (NXP OSS) #define VEND1_ABILITIES			0xAFC4
63b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ID_ABILITY		BIT(15)
64b050f2f1SRadu Pirea (NXP OSS) #define RGMII_ABILITY			BIT(14)
65b050f2f1SRadu Pirea (NXP OSS) #define RMII_ABILITY			BIT(10)
66b050f2f1SRadu Pirea (NXP OSS) #define REVMII_ABILITY			BIT(9)
67b050f2f1SRadu Pirea (NXP OSS) #define MII_ABILITY			BIT(8)
68b050f2f1SRadu Pirea (NXP OSS) #define SGMII_ABILITY			BIT(0)
69b050f2f1SRadu Pirea (NXP OSS) 
70b050f2f1SRadu Pirea (NXP OSS) #define VEND1_MII_BASIC_CONFIG		0xAFC6
71b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_REV		BIT(8)
72b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_SGMII		0x9
73b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RGMII		0x7
74b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_RMII		0x5
75b050f2f1SRadu Pirea (NXP OSS) #define MII_BASIC_CONFIG_MII		0x4
76b050f2f1SRadu Pirea (NXP OSS) 
77b050f2f1SRadu Pirea (NXP OSS) #define VEND1_SYMBOL_ERROR_COUNTER	0x8350
78b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_DROP_COUNTER		0x8352
79b050f2f1SRadu Pirea (NXP OSS) #define VEND1_LINK_LOSSES_AND_FAILURES	0x8353
80b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_GOOD_FRAME_CNT		0xA950
81b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_BAD_FRAME_CNT		0xA952
82b050f2f1SRadu Pirea (NXP OSS) #define VEND1_R_RXER_FRAME_CNT		0xA954
83b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_PREAMBLE_COUNT		0xAFCE
84b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_PREAMBLE_COUNT		0xAFCF
85b050f2f1SRadu Pirea (NXP OSS) #define VEND1_RX_IPG_LENGTH		0xAFD0
86b050f2f1SRadu Pirea (NXP OSS) #define VEND1_TX_IPG_LENGTH		0xAFD1
87b050f2f1SRadu Pirea (NXP OSS) #define COUNTER_EN			BIT(15)
88b050f2f1SRadu Pirea (NXP OSS) 
89b050f2f1SRadu Pirea (NXP OSS) #define RGMII_PERIOD_PS			8000U
90b050f2f1SRadu Pirea (NXP OSS) #define PS_PER_DEGREE			div_u64(RGMII_PERIOD_PS, 360)
91b050f2f1SRadu Pirea (NXP OSS) #define MIN_ID_PS			1644U
92b050f2f1SRadu Pirea (NXP OSS) #define MAX_ID_PS			2260U
93b050f2f1SRadu Pirea (NXP OSS) #define DEFAULT_ID_PS			2000U
94b050f2f1SRadu Pirea (NXP OSS) 
95b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy {
96b050f2f1SRadu Pirea (NXP OSS) 	u32 tx_delay;
97b050f2f1SRadu Pirea (NXP OSS) 	u32 rx_delay;
98b050f2f1SRadu Pirea (NXP OSS) };
99b050f2f1SRadu Pirea (NXP OSS) 
100b050f2f1SRadu Pirea (NXP OSS) struct nxp_c45_phy_stats {
101b050f2f1SRadu Pirea (NXP OSS) 	const char	*name;
102b050f2f1SRadu Pirea (NXP OSS) 	u8		mmd;
103b050f2f1SRadu Pirea (NXP OSS) 	u16		reg;
104b050f2f1SRadu Pirea (NXP OSS) 	u8		off;
105b050f2f1SRadu Pirea (NXP OSS) 	u16		mask;
106b050f2f1SRadu Pirea (NXP OSS) };
107b050f2f1SRadu Pirea (NXP OSS) 
108b050f2f1SRadu Pirea (NXP OSS) static const struct nxp_c45_phy_stats nxp_c45_hw_stats[] = {
109b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_symbol_error_cnt", MDIO_MMD_VEND1,
110b050f2f1SRadu Pirea (NXP OSS) 		VEND1_SYMBOL_ERROR_COUNTER, 0, GENMASK(15, 0) },
111b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_link_status_drop_cnt", MDIO_MMD_VEND1,
112b050f2f1SRadu Pirea (NXP OSS) 		VEND1_LINK_DROP_COUNTER, 8, GENMASK(13, 8) },
113b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_link_availability_drop_cnt", MDIO_MMD_VEND1,
114b050f2f1SRadu Pirea (NXP OSS) 		VEND1_LINK_DROP_COUNTER, 0, GENMASK(5, 0) },
115b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_link_loss_cnt", MDIO_MMD_VEND1,
116b050f2f1SRadu Pirea (NXP OSS) 		VEND1_LINK_LOSSES_AND_FAILURES, 10, GENMASK(15, 10) },
117b050f2f1SRadu Pirea (NXP OSS) 	{ "phy_link_failure_cnt", MDIO_MMD_VEND1,
118b050f2f1SRadu Pirea (NXP OSS) 		VEND1_LINK_LOSSES_AND_FAILURES, 0, GENMASK(9, 0) },
119b050f2f1SRadu Pirea (NXP OSS) 	{ "r_good_frame_cnt", MDIO_MMD_VEND1,
120b050f2f1SRadu Pirea (NXP OSS) 		VEND1_R_GOOD_FRAME_CNT, 0, GENMASK(15, 0) },
121b050f2f1SRadu Pirea (NXP OSS) 	{ "r_bad_frame_cnt", MDIO_MMD_VEND1,
122b050f2f1SRadu Pirea (NXP OSS) 		VEND1_R_BAD_FRAME_CNT, 0, GENMASK(15, 0) },
123b050f2f1SRadu Pirea (NXP OSS) 	{ "r_rxer_frame_cnt", MDIO_MMD_VEND1,
124b050f2f1SRadu Pirea (NXP OSS) 		VEND1_R_RXER_FRAME_CNT, 0, GENMASK(15, 0) },
125b050f2f1SRadu Pirea (NXP OSS) 	{ "rx_preamble_count", MDIO_MMD_VEND1,
126b050f2f1SRadu Pirea (NXP OSS) 		VEND1_RX_PREAMBLE_COUNT, 0, GENMASK(5, 0) },
127b050f2f1SRadu Pirea (NXP OSS) 	{ "tx_preamble_count", MDIO_MMD_VEND1,
128b050f2f1SRadu Pirea (NXP OSS) 		VEND1_TX_PREAMBLE_COUNT, 0, GENMASK(5, 0) },
129b050f2f1SRadu Pirea (NXP OSS) 	{ "rx_ipg_length", MDIO_MMD_VEND1,
130b050f2f1SRadu Pirea (NXP OSS) 		VEND1_RX_IPG_LENGTH, 0, GENMASK(8, 0) },
131b050f2f1SRadu Pirea (NXP OSS) 	{ "tx_ipg_length", MDIO_MMD_VEND1,
132b050f2f1SRadu Pirea (NXP OSS) 		VEND1_TX_IPG_LENGTH, 0, GENMASK(8, 0) },
133b050f2f1SRadu Pirea (NXP OSS) };
134b050f2f1SRadu Pirea (NXP OSS) 
135b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sset_count(struct phy_device *phydev)
136b050f2f1SRadu Pirea (NXP OSS) {
137b050f2f1SRadu Pirea (NXP OSS) 	return ARRAY_SIZE(nxp_c45_hw_stats);
138b050f2f1SRadu Pirea (NXP OSS) }
139b050f2f1SRadu Pirea (NXP OSS) 
140b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_strings(struct phy_device *phydev, u8 *data)
141b050f2f1SRadu Pirea (NXP OSS) {
142b050f2f1SRadu Pirea (NXP OSS) 	size_t i;
143b050f2f1SRadu Pirea (NXP OSS) 
144b050f2f1SRadu Pirea (NXP OSS) 	for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) {
145b050f2f1SRadu Pirea (NXP OSS) 		strncpy(data + i * ETH_GSTRING_LEN,
146b050f2f1SRadu Pirea (NXP OSS) 			nxp_c45_hw_stats[i].name, ETH_GSTRING_LEN);
147b050f2f1SRadu Pirea (NXP OSS) 	}
148b050f2f1SRadu Pirea (NXP OSS) }
149b050f2f1SRadu Pirea (NXP OSS) 
150b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_get_stats(struct phy_device *phydev,
151b050f2f1SRadu Pirea (NXP OSS) 			      struct ethtool_stats *stats, u64 *data)
152b050f2f1SRadu Pirea (NXP OSS) {
153b050f2f1SRadu Pirea (NXP OSS) 	size_t i;
154b050f2f1SRadu Pirea (NXP OSS) 	int ret;
155b050f2f1SRadu Pirea (NXP OSS) 
156b050f2f1SRadu Pirea (NXP OSS) 	for (i = 0; i < ARRAY_SIZE(nxp_c45_hw_stats); i++) {
157b050f2f1SRadu Pirea (NXP OSS) 		ret = phy_read_mmd(phydev, nxp_c45_hw_stats[i].mmd,
158b050f2f1SRadu Pirea (NXP OSS) 				   nxp_c45_hw_stats[i].reg);
159b050f2f1SRadu Pirea (NXP OSS) 		if (ret < 0) {
160b050f2f1SRadu Pirea (NXP OSS) 			data[i] = U64_MAX;
161b050f2f1SRadu Pirea (NXP OSS) 		} else {
162b050f2f1SRadu Pirea (NXP OSS) 			data[i] = ret & nxp_c45_hw_stats[i].mask;
163b050f2f1SRadu Pirea (NXP OSS) 			data[i] >>= nxp_c45_hw_stats[i].off;
164b050f2f1SRadu Pirea (NXP OSS) 		}
165b050f2f1SRadu Pirea (NXP OSS) 	}
166b050f2f1SRadu Pirea (NXP OSS) }
167b050f2f1SRadu Pirea (NXP OSS) 
168b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_enable(struct phy_device *phydev)
169b050f2f1SRadu Pirea (NXP OSS) {
170b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
171b050f2f1SRadu Pirea (NXP OSS) 		      DEVICE_CONTROL_CONFIG_GLOBAL_EN |
172b050f2f1SRadu Pirea (NXP OSS) 		      DEVICE_CONTROL_CONFIG_ALL_EN);
173b050f2f1SRadu Pirea (NXP OSS) 	usleep_range(400, 450);
174b050f2f1SRadu Pirea (NXP OSS) 
175b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_CONTROL,
176b050f2f1SRadu Pirea (NXP OSS) 		      PORT_CONTROL_EN);
177b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
178b050f2f1SRadu Pirea (NXP OSS) 		      PHY_CONFIG_EN);
179b050f2f1SRadu Pirea (NXP OSS) 	phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_INFRA_CONTROL,
180b050f2f1SRadu Pirea (NXP OSS) 		      PORT_INFRA_CONTROL_EN);
181b050f2f1SRadu Pirea (NXP OSS) 
182b050f2f1SRadu Pirea (NXP OSS) 	return 0;
183b050f2f1SRadu Pirea (NXP OSS) }
184b050f2f1SRadu Pirea (NXP OSS) 
185b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_start_op(struct phy_device *phydev)
186b050f2f1SRadu Pirea (NXP OSS) {
187b050f2f1SRadu Pirea (NXP OSS) 	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONTROL,
188b050f2f1SRadu Pirea (NXP OSS) 				PHY_START_OP);
189b050f2f1SRadu Pirea (NXP OSS) }
190b050f2f1SRadu Pirea (NXP OSS) 
191b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_soft_reset(struct phy_device *phydev)
192b050f2f1SRadu Pirea (NXP OSS) {
193b050f2f1SRadu Pirea (NXP OSS) 	int ret;
194b050f2f1SRadu Pirea (NXP OSS) 
195b050f2f1SRadu Pirea (NXP OSS) 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_CONTROL,
196b050f2f1SRadu Pirea (NXP OSS) 			    DEVICE_CONTROL_RESET);
197b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
198b050f2f1SRadu Pirea (NXP OSS) 		return ret;
199b050f2f1SRadu Pirea (NXP OSS) 
200b050f2f1SRadu Pirea (NXP OSS) 	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
201b050f2f1SRadu Pirea (NXP OSS) 					 VEND1_DEVICE_CONTROL, ret,
202b050f2f1SRadu Pirea (NXP OSS) 					 !(ret & DEVICE_CONTROL_RESET), 20000,
203b050f2f1SRadu Pirea (NXP OSS) 					 240000, false);
204b050f2f1SRadu Pirea (NXP OSS) }
205b050f2f1SRadu Pirea (NXP OSS) 
206b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_start(struct phy_device *phydev)
207b050f2f1SRadu Pirea (NXP OSS) {
208b050f2f1SRadu Pirea (NXP OSS) 	return phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST,
209b050f2f1SRadu Pirea (NXP OSS) 			     CABLE_TEST_ENABLE | CABLE_TEST_START);
210b050f2f1SRadu Pirea (NXP OSS) }
211b050f2f1SRadu Pirea (NXP OSS) 
212b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_cable_test_get_status(struct phy_device *phydev,
213b050f2f1SRadu Pirea (NXP OSS) 					 bool *finished)
214b050f2f1SRadu Pirea (NXP OSS) {
215b050f2f1SRadu Pirea (NXP OSS) 	int ret;
216b050f2f1SRadu Pirea (NXP OSS) 	u8 cable_test_result;
217b050f2f1SRadu Pirea (NXP OSS) 
218b050f2f1SRadu Pirea (NXP OSS) 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST);
219b050f2f1SRadu Pirea (NXP OSS) 	if (!(ret & CABLE_TEST_VALID)) {
220b050f2f1SRadu Pirea (NXP OSS) 		*finished = false;
221b050f2f1SRadu Pirea (NXP OSS) 		return 0;
222b050f2f1SRadu Pirea (NXP OSS) 	}
223b050f2f1SRadu Pirea (NXP OSS) 
224b050f2f1SRadu Pirea (NXP OSS) 	*finished = true;
225b050f2f1SRadu Pirea (NXP OSS) 	cable_test_result = ret & GENMASK(2, 0);
226b050f2f1SRadu Pirea (NXP OSS) 
227b050f2f1SRadu Pirea (NXP OSS) 	switch (cable_test_result) {
228b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_OK:
229b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
230b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_OK);
231b050f2f1SRadu Pirea (NXP OSS) 		break;
232b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_SHORTED:
233b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
234b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT);
235b050f2f1SRadu Pirea (NXP OSS) 		break;
236b050f2f1SRadu Pirea (NXP OSS) 	case CABLE_TEST_OPEN:
237b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
238b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_OPEN);
239b050f2f1SRadu Pirea (NXP OSS) 		break;
240b050f2f1SRadu Pirea (NXP OSS) 	default:
241b050f2f1SRadu Pirea (NXP OSS) 		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
242b050f2f1SRadu Pirea (NXP OSS) 					ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC);
243b050f2f1SRadu Pirea (NXP OSS) 	}
244b050f2f1SRadu Pirea (NXP OSS) 
245b050f2f1SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_CABLE_TEST,
246b050f2f1SRadu Pirea (NXP OSS) 			   CABLE_TEST_ENABLE);
247b050f2f1SRadu Pirea (NXP OSS) 
248b050f2f1SRadu Pirea (NXP OSS) 	return nxp_c45_start_op(phydev);
249b050f2f1SRadu Pirea (NXP OSS) }
250b050f2f1SRadu Pirea (NXP OSS) 
251b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_setup_master_slave(struct phy_device *phydev)
252b050f2f1SRadu Pirea (NXP OSS) {
253b050f2f1SRadu Pirea (NXP OSS) 	switch (phydev->master_slave_set) {
254b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_MASTER_FORCE:
255b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_MASTER_PREFERRED:
256b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL,
257b050f2f1SRadu Pirea (NXP OSS) 			      MASTER_MODE);
258b050f2f1SRadu Pirea (NXP OSS) 		break;
259b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_SLAVE_PREFERRED:
260b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_SLAVE_FORCE:
261b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL,
262b050f2f1SRadu Pirea (NXP OSS) 			      SLAVE_MODE);
263b050f2f1SRadu Pirea (NXP OSS) 		break;
264b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_UNKNOWN:
265b050f2f1SRadu Pirea (NXP OSS) 	case MASTER_SLAVE_CFG_UNSUPPORTED:
266b050f2f1SRadu Pirea (NXP OSS) 		return 0;
267b050f2f1SRadu Pirea (NXP OSS) 	default:
268b050f2f1SRadu Pirea (NXP OSS) 		phydev_warn(phydev, "Unsupported Master/Slave mode\n");
269b050f2f1SRadu Pirea (NXP OSS) 		return -EOPNOTSUPP;
270b050f2f1SRadu Pirea (NXP OSS) 	}
271b050f2f1SRadu Pirea (NXP OSS) 
272b050f2f1SRadu Pirea (NXP OSS) 	return 0;
273b050f2f1SRadu Pirea (NXP OSS) }
274b050f2f1SRadu Pirea (NXP OSS) 
275b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_read_master_slave(struct phy_device *phydev)
276b050f2f1SRadu Pirea (NXP OSS) {
277b050f2f1SRadu Pirea (NXP OSS) 	int reg;
278b050f2f1SRadu Pirea (NXP OSS) 
279b050f2f1SRadu Pirea (NXP OSS) 	phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN;
280b050f2f1SRadu Pirea (NXP OSS) 	phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
281b050f2f1SRadu Pirea (NXP OSS) 
282b050f2f1SRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL);
283b050f2f1SRadu Pirea (NXP OSS) 	if (reg < 0)
284b050f2f1SRadu Pirea (NXP OSS) 		return reg;
285b050f2f1SRadu Pirea (NXP OSS) 
286b050f2f1SRadu Pirea (NXP OSS) 	if (reg & B100T1_PMAPMD_MASTER) {
287b050f2f1SRadu Pirea (NXP OSS) 		phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE;
288b050f2f1SRadu Pirea (NXP OSS) 		phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
289b050f2f1SRadu Pirea (NXP OSS) 	} else {
290b050f2f1SRadu Pirea (NXP OSS) 		phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE;
291b050f2f1SRadu Pirea (NXP OSS) 		phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
292b050f2f1SRadu Pirea (NXP OSS) 	}
293b050f2f1SRadu Pirea (NXP OSS) 
294b050f2f1SRadu Pirea (NXP OSS) 	return 0;
295b050f2f1SRadu Pirea (NXP OSS) }
296b050f2f1SRadu Pirea (NXP OSS) 
297b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_aneg(struct phy_device *phydev)
298b050f2f1SRadu Pirea (NXP OSS) {
299b050f2f1SRadu Pirea (NXP OSS) 	return nxp_c45_setup_master_slave(phydev);
300b050f2f1SRadu Pirea (NXP OSS) }
301b050f2f1SRadu Pirea (NXP OSS) 
302b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_read_status(struct phy_device *phydev)
303b050f2f1SRadu Pirea (NXP OSS) {
304b050f2f1SRadu Pirea (NXP OSS) 	int ret;
305b050f2f1SRadu Pirea (NXP OSS) 
306b050f2f1SRadu Pirea (NXP OSS) 	ret = genphy_c45_read_status(phydev);
307b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
308b050f2f1SRadu Pirea (NXP OSS) 		return ret;
309b050f2f1SRadu Pirea (NXP OSS) 
310b050f2f1SRadu Pirea (NXP OSS) 	ret = nxp_c45_read_master_slave(phydev);
311b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
312b050f2f1SRadu Pirea (NXP OSS) 		return ret;
313b050f2f1SRadu Pirea (NXP OSS) 
314b050f2f1SRadu Pirea (NXP OSS) 	return 0;
315b050f2f1SRadu Pirea (NXP OSS) }
316b050f2f1SRadu Pirea (NXP OSS) 
317b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi(struct phy_device *phydev)
318b050f2f1SRadu Pirea (NXP OSS) {
319b050f2f1SRadu Pirea (NXP OSS) 	int reg;
320b050f2f1SRadu Pirea (NXP OSS) 
321b050f2f1SRadu Pirea (NXP OSS) 	reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_SIGNAL_QUALITY);
322b050f2f1SRadu Pirea (NXP OSS) 	if (!(reg & SQI_VALID))
323b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
324b050f2f1SRadu Pirea (NXP OSS) 
325b050f2f1SRadu Pirea (NXP OSS) 	reg &= SQI_MASK;
326b050f2f1SRadu Pirea (NXP OSS) 
327b050f2f1SRadu Pirea (NXP OSS) 	return reg;
328b050f2f1SRadu Pirea (NXP OSS) }
329b050f2f1SRadu Pirea (NXP OSS) 
330b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_sqi_max(struct phy_device *phydev)
331b050f2f1SRadu Pirea (NXP OSS) {
332b050f2f1SRadu Pirea (NXP OSS) 	return MAX_SQI;
333b050f2f1SRadu Pirea (NXP OSS) }
334b050f2f1SRadu Pirea (NXP OSS) 
335b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_check_delay(struct phy_device *phydev, u32 delay)
336b050f2f1SRadu Pirea (NXP OSS) {
337b050f2f1SRadu Pirea (NXP OSS) 	if (delay < MIN_ID_PS) {
338b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "delay value smaller than %u\n", MIN_ID_PS);
339b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
340b050f2f1SRadu Pirea (NXP OSS) 	}
341b050f2f1SRadu Pirea (NXP OSS) 
342b050f2f1SRadu Pirea (NXP OSS) 	if (delay > MAX_ID_PS) {
343b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "delay value higher than %u\n", MAX_ID_PS);
344b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
345b050f2f1SRadu Pirea (NXP OSS) 	}
346b050f2f1SRadu Pirea (NXP OSS) 
347b050f2f1SRadu Pirea (NXP OSS) 	return 0;
348b050f2f1SRadu Pirea (NXP OSS) }
349b050f2f1SRadu Pirea (NXP OSS) 
350b050f2f1SRadu Pirea (NXP OSS) static u64 nxp_c45_get_phase_shift(u64 phase_offset_raw)
351b050f2f1SRadu Pirea (NXP OSS) {
352b050f2f1SRadu Pirea (NXP OSS) 	/* The delay in degree phase is 73.8 + phase_offset_raw * 0.9.
353b050f2f1SRadu Pirea (NXP OSS) 	 * To avoid floating point operations we'll multiply by 10
354b050f2f1SRadu Pirea (NXP OSS) 	 * and get 1 decimal point precision.
355b050f2f1SRadu Pirea (NXP OSS) 	 */
356b050f2f1SRadu Pirea (NXP OSS) 	phase_offset_raw *= 10;
357*6b3a6310SRadu Pirea (NXP OSS) 	phase_offset_raw -= 738;
358b050f2f1SRadu Pirea (NXP OSS) 	return div_u64(phase_offset_raw, 9);
359b050f2f1SRadu Pirea (NXP OSS) }
360b050f2f1SRadu Pirea (NXP OSS) 
361b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_disable_delays(struct phy_device *phydev)
362b050f2f1SRadu Pirea (NXP OSS) {
363b050f2f1SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID, ID_ENABLE);
364b050f2f1SRadu Pirea (NXP OSS) 	phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID, ID_ENABLE);
365b050f2f1SRadu Pirea (NXP OSS) }
366b050f2f1SRadu Pirea (NXP OSS) 
367b050f2f1SRadu Pirea (NXP OSS) static void nxp_c45_set_delays(struct phy_device *phydev)
368b050f2f1SRadu Pirea (NXP OSS) {
369b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = phydev->priv;
370b050f2f1SRadu Pirea (NXP OSS) 	u64 tx_delay = priv->tx_delay;
371b050f2f1SRadu Pirea (NXP OSS) 	u64 rx_delay = priv->rx_delay;
372b050f2f1SRadu Pirea (NXP OSS) 	u64 degree;
373b050f2f1SRadu Pirea (NXP OSS) 
374b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
375b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
376b050f2f1SRadu Pirea (NXP OSS) 		degree = div_u64(tx_delay, PS_PER_DEGREE);
377b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
378b050f2f1SRadu Pirea (NXP OSS) 			      ID_ENABLE | nxp_c45_get_phase_shift(degree));
379b050f2f1SRadu Pirea (NXP OSS) 	} else {
380b050f2f1SRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TXID,
381b050f2f1SRadu Pirea (NXP OSS) 				   ID_ENABLE);
382b050f2f1SRadu Pirea (NXP OSS) 	}
383b050f2f1SRadu Pirea (NXP OSS) 
384b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
385b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
386b050f2f1SRadu Pirea (NXP OSS) 		degree = div_u64(rx_delay, PS_PER_DEGREE);
387b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
388b050f2f1SRadu Pirea (NXP OSS) 			      ID_ENABLE | nxp_c45_get_phase_shift(degree));
389b050f2f1SRadu Pirea (NXP OSS) 	} else {
390b050f2f1SRadu Pirea (NXP OSS) 		phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RXID,
391b050f2f1SRadu Pirea (NXP OSS) 				   ID_ENABLE);
392b050f2f1SRadu Pirea (NXP OSS) 	}
393b050f2f1SRadu Pirea (NXP OSS) }
394b050f2f1SRadu Pirea (NXP OSS) 
395b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_get_delays(struct phy_device *phydev)
396b050f2f1SRadu Pirea (NXP OSS) {
397b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv = phydev->priv;
398b050f2f1SRadu Pirea (NXP OSS) 	int ret;
399b050f2f1SRadu Pirea (NXP OSS) 
400b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
401b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
402b050f2f1SRadu Pirea (NXP OSS) 		ret = device_property_read_u32(&phydev->mdio.dev,
403b050f2f1SRadu Pirea (NXP OSS) 					       "tx-internal-delay-ps",
404b050f2f1SRadu Pirea (NXP OSS) 					       &priv->tx_delay);
405b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
406b050f2f1SRadu Pirea (NXP OSS) 			priv->tx_delay = DEFAULT_ID_PS;
407b050f2f1SRadu Pirea (NXP OSS) 
408b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_check_delay(phydev, priv->tx_delay);
409b050f2f1SRadu Pirea (NXP OSS) 		if (ret) {
410b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev,
411b050f2f1SRadu Pirea (NXP OSS) 				   "tx-internal-delay-ps invalid value\n");
412b050f2f1SRadu Pirea (NXP OSS) 			return ret;
413b050f2f1SRadu Pirea (NXP OSS) 		}
414b050f2f1SRadu Pirea (NXP OSS) 	}
415b050f2f1SRadu Pirea (NXP OSS) 
416b050f2f1SRadu Pirea (NXP OSS) 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
417b050f2f1SRadu Pirea (NXP OSS) 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
418b050f2f1SRadu Pirea (NXP OSS) 		ret = device_property_read_u32(&phydev->mdio.dev,
419b050f2f1SRadu Pirea (NXP OSS) 					       "rx-internal-delay-ps",
420b050f2f1SRadu Pirea (NXP OSS) 					       &priv->rx_delay);
421b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
422b050f2f1SRadu Pirea (NXP OSS) 			priv->rx_delay = DEFAULT_ID_PS;
423b050f2f1SRadu Pirea (NXP OSS) 
424b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_check_delay(phydev, priv->rx_delay);
425b050f2f1SRadu Pirea (NXP OSS) 		if (ret) {
426b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev,
427b050f2f1SRadu Pirea (NXP OSS) 				   "rx-internal-delay-ps invalid value\n");
428b050f2f1SRadu Pirea (NXP OSS) 			return ret;
429b050f2f1SRadu Pirea (NXP OSS) 		}
430b050f2f1SRadu Pirea (NXP OSS) 	}
431b050f2f1SRadu Pirea (NXP OSS) 
432b050f2f1SRadu Pirea (NXP OSS) 	return 0;
433b050f2f1SRadu Pirea (NXP OSS) }
434b050f2f1SRadu Pirea (NXP OSS) 
435b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_set_phy_mode(struct phy_device *phydev)
436b050f2f1SRadu Pirea (NXP OSS) {
437b050f2f1SRadu Pirea (NXP OSS) 	int ret;
438b050f2f1SRadu Pirea (NXP OSS) 
439b050f2f1SRadu Pirea (NXP OSS) 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_ABILITIES);
440b050f2f1SRadu Pirea (NXP OSS) 	phydev_dbg(phydev, "Clause 45 managed PHY abilities 0x%x\n", ret);
441b050f2f1SRadu Pirea (NXP OSS) 
442b050f2f1SRadu Pirea (NXP OSS) 	switch (phydev->interface) {
443b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII:
444b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RGMII_ABILITY)) {
445b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rgmii mode not supported\n");
446b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
447b050f2f1SRadu Pirea (NXP OSS) 		}
448b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
449b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RGMII);
450b050f2f1SRadu Pirea (NXP OSS) 		nxp_c45_disable_delays(phydev);
451b050f2f1SRadu Pirea (NXP OSS) 		break;
452b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_ID:
453b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_TXID:
454b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RGMII_RXID:
455b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RGMII_ID_ABILITY)) {
456b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rgmii-id, rgmii-txid, rgmii-rxid modes are not supported\n");
457b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
458b050f2f1SRadu Pirea (NXP OSS) 		}
459b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
460b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RGMII);
461b050f2f1SRadu Pirea (NXP OSS) 		ret = nxp_c45_get_delays(phydev);
462b050f2f1SRadu Pirea (NXP OSS) 		if (ret)
463b050f2f1SRadu Pirea (NXP OSS) 			return ret;
464b050f2f1SRadu Pirea (NXP OSS) 
465b050f2f1SRadu Pirea (NXP OSS) 		nxp_c45_set_delays(phydev);
466b050f2f1SRadu Pirea (NXP OSS) 		break;
467b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_MII:
468b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & MII_ABILITY)) {
469b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "mii mode not supported\n");
470b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
471b050f2f1SRadu Pirea (NXP OSS) 		}
472b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
473b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_MII);
474b050f2f1SRadu Pirea (NXP OSS) 		break;
475b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_REVMII:
476b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & REVMII_ABILITY)) {
477b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rev-mii mode not supported\n");
478b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
479b050f2f1SRadu Pirea (NXP OSS) 		}
480b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
481b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_MII | MII_BASIC_CONFIG_REV);
482b050f2f1SRadu Pirea (NXP OSS) 		break;
483b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_RMII:
484b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & RMII_ABILITY)) {
485b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "rmii mode not supported\n");
486b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
487b050f2f1SRadu Pirea (NXP OSS) 		}
488b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
489b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_RMII);
490b050f2f1SRadu Pirea (NXP OSS) 		break;
491b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_SGMII:
492b050f2f1SRadu Pirea (NXP OSS) 		if (!(ret & SGMII_ABILITY)) {
493b050f2f1SRadu Pirea (NXP OSS) 			phydev_err(phydev, "sgmii mode not supported\n");
494b050f2f1SRadu Pirea (NXP OSS) 			return -EINVAL;
495b050f2f1SRadu Pirea (NXP OSS) 		}
496b050f2f1SRadu Pirea (NXP OSS) 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_MII_BASIC_CONFIG,
497b050f2f1SRadu Pirea (NXP OSS) 			      MII_BASIC_CONFIG_SGMII);
498b050f2f1SRadu Pirea (NXP OSS) 		break;
499b050f2f1SRadu Pirea (NXP OSS) 	case PHY_INTERFACE_MODE_INTERNAL:
500b050f2f1SRadu Pirea (NXP OSS) 		break;
501b050f2f1SRadu Pirea (NXP OSS) 	default:
502b050f2f1SRadu Pirea (NXP OSS) 		return -EINVAL;
503b050f2f1SRadu Pirea (NXP OSS) 	}
504b050f2f1SRadu Pirea (NXP OSS) 
505b050f2f1SRadu Pirea (NXP OSS) 	return 0;
506b050f2f1SRadu Pirea (NXP OSS) }
507b050f2f1SRadu Pirea (NXP OSS) 
508b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_config_init(struct phy_device *phydev)
509b050f2f1SRadu Pirea (NXP OSS) {
510b050f2f1SRadu Pirea (NXP OSS) 	int ret;
511b050f2f1SRadu Pirea (NXP OSS) 
512b050f2f1SRadu Pirea (NXP OSS) 	ret = nxp_c45_config_enable(phydev);
513b050f2f1SRadu Pirea (NXP OSS) 	if (ret) {
514b050f2f1SRadu Pirea (NXP OSS) 		phydev_err(phydev, "Failed to enable config\n");
515b050f2f1SRadu Pirea (NXP OSS) 		return ret;
516b050f2f1SRadu Pirea (NXP OSS) 	}
517b050f2f1SRadu Pirea (NXP OSS) 
518b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG,
519b050f2f1SRadu Pirea (NXP OSS) 			 PHY_CONFIG_AUTO);
520b050f2f1SRadu Pirea (NXP OSS) 
521b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_LINK_DROP_COUNTER,
522b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
523b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_PREAMBLE_COUNT,
524b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
525b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_PREAMBLE_COUNT,
526b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
527b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_RX_IPG_LENGTH,
528b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
529b050f2f1SRadu Pirea (NXP OSS) 	phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_TX_IPG_LENGTH,
530b050f2f1SRadu Pirea (NXP OSS) 			 COUNTER_EN);
531b050f2f1SRadu Pirea (NXP OSS) 
532b050f2f1SRadu Pirea (NXP OSS) 	ret = nxp_c45_set_phy_mode(phydev);
533b050f2f1SRadu Pirea (NXP OSS) 	if (ret)
534b050f2f1SRadu Pirea (NXP OSS) 		return ret;
535b050f2f1SRadu Pirea (NXP OSS) 
536b050f2f1SRadu Pirea (NXP OSS) 	phydev->autoneg = AUTONEG_DISABLE;
537b050f2f1SRadu Pirea (NXP OSS) 
538b050f2f1SRadu Pirea (NXP OSS) 	return nxp_c45_start_op(phydev);
539b050f2f1SRadu Pirea (NXP OSS) }
540b050f2f1SRadu Pirea (NXP OSS) 
541b050f2f1SRadu Pirea (NXP OSS) static int nxp_c45_probe(struct phy_device *phydev)
542b050f2f1SRadu Pirea (NXP OSS) {
543b050f2f1SRadu Pirea (NXP OSS) 	struct nxp_c45_phy *priv;
544b050f2f1SRadu Pirea (NXP OSS) 
545b050f2f1SRadu Pirea (NXP OSS) 	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
546b050f2f1SRadu Pirea (NXP OSS) 	if (!priv)
547b050f2f1SRadu Pirea (NXP OSS) 		return -ENOMEM;
548b050f2f1SRadu Pirea (NXP OSS) 
549b050f2f1SRadu Pirea (NXP OSS) 	phydev->priv = priv;
550b050f2f1SRadu Pirea (NXP OSS) 
551b050f2f1SRadu Pirea (NXP OSS) 	return 0;
552b050f2f1SRadu Pirea (NXP OSS) }
553b050f2f1SRadu Pirea (NXP OSS) 
554b050f2f1SRadu Pirea (NXP OSS) static struct phy_driver nxp_c45_driver[] = {
555b050f2f1SRadu Pirea (NXP OSS) 	{
556b050f2f1SRadu Pirea (NXP OSS) 		PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
557b050f2f1SRadu Pirea (NXP OSS) 		.name			= "NXP C45 TJA1103",
558b050f2f1SRadu Pirea (NXP OSS) 		.features		= PHY_BASIC_T1_FEATURES,
559b050f2f1SRadu Pirea (NXP OSS) 		.probe			= nxp_c45_probe,
560b050f2f1SRadu Pirea (NXP OSS) 		.soft_reset		= nxp_c45_soft_reset,
561b050f2f1SRadu Pirea (NXP OSS) 		.config_aneg		= nxp_c45_config_aneg,
562b050f2f1SRadu Pirea (NXP OSS) 		.config_init		= nxp_c45_config_init,
563b050f2f1SRadu Pirea (NXP OSS) 		.read_status		= nxp_c45_read_status,
564b050f2f1SRadu Pirea (NXP OSS) 		.suspend		= genphy_c45_pma_suspend,
565b050f2f1SRadu Pirea (NXP OSS) 		.resume			= genphy_c45_pma_resume,
566b050f2f1SRadu Pirea (NXP OSS) 		.get_sset_count		= nxp_c45_get_sset_count,
567b050f2f1SRadu Pirea (NXP OSS) 		.get_strings		= nxp_c45_get_strings,
568b050f2f1SRadu Pirea (NXP OSS) 		.get_stats		= nxp_c45_get_stats,
569b050f2f1SRadu Pirea (NXP OSS) 		.cable_test_start	= nxp_c45_cable_test_start,
570b050f2f1SRadu Pirea (NXP OSS) 		.cable_test_get_status	= nxp_c45_cable_test_get_status,
571b050f2f1SRadu Pirea (NXP OSS) 		.set_loopback		= genphy_c45_loopback,
572b050f2f1SRadu Pirea (NXP OSS) 		.get_sqi		= nxp_c45_get_sqi,
573b050f2f1SRadu Pirea (NXP OSS) 		.get_sqi_max		= nxp_c45_get_sqi_max,
574b050f2f1SRadu Pirea (NXP OSS) 	},
575b050f2f1SRadu Pirea (NXP OSS) };
576b050f2f1SRadu Pirea (NXP OSS) 
577b050f2f1SRadu Pirea (NXP OSS) module_phy_driver(nxp_c45_driver);
578b050f2f1SRadu Pirea (NXP OSS) 
579b050f2f1SRadu Pirea (NXP OSS) static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = {
580b050f2f1SRadu Pirea (NXP OSS) 	{ PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) },
581b050f2f1SRadu Pirea (NXP OSS) 	{ /*sentinel*/ },
582b050f2f1SRadu Pirea (NXP OSS) };
583b050f2f1SRadu Pirea (NXP OSS) 
584b050f2f1SRadu Pirea (NXP OSS) MODULE_DEVICE_TABLE(mdio, nxp_c45_tbl);
585b050f2f1SRadu Pirea (NXP OSS) 
586b050f2f1SRadu Pirea (NXP OSS) MODULE_AUTHOR("Radu Pirea <radu-nicolae.pirea@oss.nxp.com>");
587b050f2f1SRadu Pirea (NXP OSS) MODULE_DESCRIPTION("NXP C45 PHY driver");
588b050f2f1SRadu Pirea (NXP OSS) MODULE_LICENSE("GPL v2");
589