Linux Audio

Check our new training course

Buildroot integration, development and maintenance

Need a Buildroot system for your embedded project?
Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Marvell 88Q2XXX automotive 100BASE-T1/1000BASE-T1 PHY driver
 
 
 
 
  4 */
  5#include <linux/ethtool_netlink.h>
  6#include <linux/marvell_phy.h>
  7#include <linux/phy.h>
 
 
 
 
 
  8
  9#define MDIO_MMD_AN_MV_STAT			32769
 10#define MDIO_MMD_AN_MV_STAT_ANEG		0x0100
 11#define MDIO_MMD_AN_MV_STAT_LOCAL_RX		0x1000
 12#define MDIO_MMD_AN_MV_STAT_REMOTE_RX		0x2000
 13#define MDIO_MMD_AN_MV_STAT_LOCAL_MASTER	0x4000
 14#define MDIO_MMD_AN_MV_STAT_MS_CONF_FAULT	0x8000
 15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 16#define MDIO_MMD_PCS_MV_100BT1_STAT1			33032
 17#define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR	0x00FF
 18#define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER		0x0100
 19#define MDIO_MMD_PCS_MV_100BT1_STAT1_LINK		0x0200
 20#define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX		0x1000
 21#define MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX		0x2000
 22#define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_MASTER	0x4000
 23
 24#define MDIO_MMD_PCS_MV_100BT1_STAT2		33033
 25#define MDIO_MMD_PCS_MV_100BT1_STAT2_JABBER	0x0001
 26#define MDIO_MMD_PCS_MV_100BT1_STAT2_POL	0x0002
 27#define MDIO_MMD_PCS_MV_100BT1_STAT2_LINK	0x0004
 28#define MDIO_MMD_PCS_MV_100BT1_STAT2_ANGE	0x0008
 29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 30static int mv88q2xxx_soft_reset(struct phy_device *phydev)
 31{
 32	int ret;
 33	int val;
 34
 35	ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
 36			    MDIO_PCS_1000BT1_CTRL, MDIO_PCS_1000BT1_CTRL_RESET);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 37	if (ret < 0)
 38		return ret;
 39
 40	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
 41					 MDIO_PCS_1000BT1_CTRL, val,
 42					 !(val & MDIO_PCS_1000BT1_CTRL_RESET),
 43					 50000, 600000, true);
 
 
 
 
 
 44}
 45
 46static int mv88q2xxx_read_link_gbit(struct phy_device *phydev)
 47{
 48	int ret;
 49	bool link = false;
 50
 51	/* Read vendor specific Auto-Negotiation status register to get local
 52	 * and remote receiver status according to software initialization
 53	 * guide.
 
 54	 */
 55	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT);
 56	if (ret < 0) {
 57		return ret;
 58	} else if ((ret & MDIO_MMD_AN_MV_STAT_LOCAL_RX) &&
 59		   (ret & MDIO_MMD_AN_MV_STAT_REMOTE_RX)) {
 
 60		/* The link state is latched low so that momentary link
 61		 * drops can be detected. Do not double-read the status
 62		 * in polling mode to detect such short link drops except
 63		 * the link was already down.
 64		 */
 65		if (!phy_polling_mode(phydev) || !phydev->link) {
 66			ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_STAT);
 
 67			if (ret < 0)
 68				return ret;
 69			else if (ret & MDIO_PCS_1000BT1_STAT_LINK)
 70				link = true;
 71		}
 72
 73		if (!link) {
 74			ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_STAT);
 
 75			if (ret < 0)
 76				return ret;
 77			else if (ret & MDIO_PCS_1000BT1_STAT_LINK)
 78				link = true;
 79		}
 80	}
 81
 82	phydev->link = link;
 83
 84	return 0;
 85}
 86
 87static int mv88q2xxx_read_link_100m(struct phy_device *phydev)
 88{
 89	int ret;
 90
 91	/* The link state is latched low so that momentary link
 92	 * drops can be detected. Do not double-read the status
 93	 * in polling mode to detect such short link drops except
 94	 * the link was already down. In case we are not polling,
 95	 * we always read the realtime status.
 96	 */
 97	if (!phy_polling_mode(phydev) || !phydev->link) {
 98		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_100BT1_STAT1);
 
 
 
 
 
 
 
 
 
 
 
 
 99		if (ret < 0)
100			return ret;
101		else if (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK)
102			goto out;
103	}
104
105	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_100BT1_STAT1);
106	if (ret < 0)
107		return ret;
108
109out:
110	/* Check if we have link and if the remote and local receiver are ok */
111	if ((ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK) &&
112	    (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX) &&
113	    (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX))
114		phydev->link = true;
115	else
116		phydev->link = false;
117
118	return 0;
119}
120
121static int mv88q2xxx_read_link(struct phy_device *phydev)
122{
123	int ret;
124
125	/* The 88Q2XXX PHYs do not have the PMA/PMD status register available,
126	 * therefore we need to read the link status from the vendor specific
127	 * registers depending on the speed.
128	 */
 
129	if (phydev->speed == SPEED_1000)
130		ret = mv88q2xxx_read_link_gbit(phydev);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131	else
132		ret = mv88q2xxx_read_link_100m(phydev);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
134	return ret;
135}
136
137static int mv88q2xxx_read_status(struct phy_device *phydev)
138{
139	int ret;
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141	ret = mv88q2xxx_read_link(phydev);
142	if (ret < 0)
143		return ret;
144
145	return genphy_c45_read_pma(phydev);
146}
147
148static int mv88q2xxx_get_features(struct phy_device *phydev)
149{
150	int ret;
151
152	ret = genphy_c45_pma_read_abilities(phydev);
153	if (ret)
154		return ret;
155
156	/* We need to read the baset1 extended abilities manually because the
157	 * PHY does not signalize it has the extended abilities register
158	 * available.
159	 */
160	ret = genphy_c45_pma_baset1_read_abilities(phydev);
161	if (ret)
162		return ret;
163
164	/* The PHY signalizes it supports autonegotiation. Unfortunately, so
165	 * far it was not possible to get a link even when following the init
166	 * sequence provided by Marvell. Disable it for now until a proper
167	 * workaround is found or a new PHY revision is released.
168	 */
169	linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
170
171	return 0;
172}
173
174static int mv88q2xxx_config_aneg(struct phy_device *phydev)
175{
176	int ret;
177
178	ret = genphy_c45_config_aneg(phydev);
179	if (ret)
180		return ret;
181
182	return mv88q2xxx_soft_reset(phydev);
183}
184
185static int mv88q2xxx_config_init(struct phy_device *phydev)
186{
187	int ret;
188
189	/* The 88Q2XXX PHYs do have the extended ability register available, but
190	 * register MDIO_PMA_EXTABLE where they should signalize it does not
191	 * work according to specification. Therefore, we force it here.
192	 */
193	phydev->pma_extable = MDIO_PMA_EXTABLE_BT1;
194
195	/* Read the current PHY configuration */
196	ret = genphy_c45_read_pma(phydev);
197	if (ret)
198		return ret;
 
 
 
199
200	return mv88q2xxx_config_aneg(phydev);
201}
202
203static int mv88q2xxxx_get_sqi(struct phy_device *phydev)
204{
205	int ret;
206
207	if (phydev->speed == SPEED_100) {
208		/* Read the SQI from the vendor specific receiver status
209		 * register
210		 */
211		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 0x8230);
 
212		if (ret < 0)
213			return ret;
214
215		ret = ret >> 12;
216	} else {
217		/* Read from vendor specific registers, they are not documented
218		 * but can be found in the Software Initialization Guide. Only
219		 * revisions >= A0 are supported.
220		 */
221		ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, 0xFC5D, 0x00FF, 0x00AC);
222		if (ret < 0)
223			return ret;
224
225		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 0xfc88);
226		if (ret < 0)
227			return ret;
228	}
229
230	return ret & 0x0F;
231}
232
233static int mv88q2xxxx_get_sqi_max(struct phy_device *phydev)
234{
235	return 15;
236}
237
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238static struct phy_driver mv88q2xxx_driver[] = {
239	{
240		.phy_id			= MARVELL_PHY_ID_88Q2110,
241		.phy_id_mask		= MARVELL_PHY_ID_MASK,
242		.name			= "mv88q2110",
243		.get_features		= mv88q2xxx_get_features,
244		.config_aneg		= mv88q2xxx_config_aneg,
245		.config_init		= mv88q2xxx_config_init,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246		.read_status		= mv88q2xxx_read_status,
247		.soft_reset		= mv88q2xxx_soft_reset,
 
 
248		.set_loopback		= genphy_c45_loopback,
249		.get_sqi		= mv88q2xxxx_get_sqi,
250		.get_sqi_max		= mv88q2xxxx_get_sqi_max,
 
 
 
 
251	},
252};
253
254module_phy_driver(mv88q2xxx_driver);
255
256static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = {
257	{ MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK },
 
258	{ /*sentinel*/ }
259};
260MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl);
261
262MODULE_DESCRIPTION("Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet PHY driver");
263MODULE_LICENSE("GPL");
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Marvell 88Q2XXX automotive 100BASE-T1/1000BASE-T1 PHY driver
  4 *
  5 * Derived from Marvell Q222x API
  6 *
  7 * Copyright (C) 2024 Liebherr-Electronics and Drives GmbH
  8 */
  9#include <linux/ethtool_netlink.h>
 10#include <linux/marvell_phy.h>
 11#include <linux/phy.h>
 12#include <linux/hwmon.h>
 13
 14#define PHY_ID_88Q2220_REVB0	(MARVELL_PHY_ID_88Q2220 | 0x1)
 15#define PHY_ID_88Q2220_REVB1	(MARVELL_PHY_ID_88Q2220 | 0x2)
 16#define PHY_ID_88Q2220_REVB2	(MARVELL_PHY_ID_88Q2220 | 0x3)
 17
 18#define MDIO_MMD_AN_MV_STAT			32769
 19#define MDIO_MMD_AN_MV_STAT_ANEG		0x0100
 20#define MDIO_MMD_AN_MV_STAT_LOCAL_RX		0x1000
 21#define MDIO_MMD_AN_MV_STAT_REMOTE_RX		0x2000
 22#define MDIO_MMD_AN_MV_STAT_LOCAL_MASTER	0x4000
 23#define MDIO_MMD_AN_MV_STAT_MS_CONF_FAULT	0x8000
 24
 25#define MDIO_MMD_AN_MV_STAT2			32794
 26#define MDIO_MMD_AN_MV_STAT2_AN_RESOLVED	0x0800
 27#define MDIO_MMD_AN_MV_STAT2_100BT1		0x2000
 28#define MDIO_MMD_AN_MV_STAT2_1000BT1		0x4000
 29
 30#define MDIO_MMD_PCS_MV_INT_EN			32784
 31#define MDIO_MMD_PCS_MV_INT_EN_LINK_UP		0x0040
 32#define MDIO_MMD_PCS_MV_INT_EN_LINK_DOWN	0x0080
 33#define MDIO_MMD_PCS_MV_INT_EN_100BT1		0x1000
 34
 35#define MDIO_MMD_PCS_MV_GPIO_INT_STAT			32785
 36#define MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_UP		0x0040
 37#define MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_DOWN		0x0080
 38#define MDIO_MMD_PCS_MV_GPIO_INT_STAT_100BT1_GEN	0x1000
 39
 40#define MDIO_MMD_PCS_MV_GPIO_INT_CTRL			32787
 41#define MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS		0x0800
 42
 43#define MDIO_MMD_PCS_MV_TEMP_SENSOR1			32833
 44#define MDIO_MMD_PCS_MV_TEMP_SENSOR1_RAW_INT		0x0001
 45#define MDIO_MMD_PCS_MV_TEMP_SENSOR1_INT		0x0040
 46#define MDIO_MMD_PCS_MV_TEMP_SENSOR1_INT_EN		0x0080
 47
 48#define MDIO_MMD_PCS_MV_TEMP_SENSOR2			32834
 49#define MDIO_MMD_PCS_MV_TEMP_SENSOR2_DIS_MASK		0xc000
 50
 51#define MDIO_MMD_PCS_MV_TEMP_SENSOR3			32835
 52#define MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK	0xff00
 53#define MDIO_MMD_PCS_MV_TEMP_SENSOR3_MASK		0x00ff
 54
 55#define MDIO_MMD_PCS_MV_100BT1_STAT1			33032
 56#define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR		0x00ff
 57#define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER		0x0100
 58#define MDIO_MMD_PCS_MV_100BT1_STAT1_LINK		0x0200
 59#define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX		0x1000
 60#define MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX		0x2000
 61#define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_MASTER	0x4000
 62
 63#define MDIO_MMD_PCS_MV_100BT1_STAT2		33033
 64#define MDIO_MMD_PCS_MV_100BT1_STAT2_JABBER	0x0001
 65#define MDIO_MMD_PCS_MV_100BT1_STAT2_POL	0x0002
 66#define MDIO_MMD_PCS_MV_100BT1_STAT2_LINK	0x0004
 67#define MDIO_MMD_PCS_MV_100BT1_STAT2_ANGE	0x0008
 68
 69#define MDIO_MMD_PCS_MV_100BT1_INT_EN			33042
 70#define MDIO_MMD_PCS_MV_100BT1_INT_EN_LINKEVENT		0x0400
 71
 72#define MDIO_MMD_PCS_MV_COPPER_INT_STAT			33043
 73#define MDIO_MMD_PCS_MV_COPPER_INT_STAT_LINKEVENT	0x0400
 74
 75#define MDIO_MMD_PCS_MV_RX_STAT			33328
 76
 77#define MDIO_MMD_PCS_MV_TDR_RESET			65226
 78#define MDIO_MMD_PCS_MV_TDR_RESET_TDR_RST		0x1000
 79
 80#define MDIO_MMD_PCS_MV_TDR_OFF_SHORT_CABLE		65241
 81
 82#define MDIO_MMD_PCS_MV_TDR_OFF_LONG_CABLE		65242
 83
 84#define MDIO_MMD_PCS_MV_TDR_STATUS			65245
 85#define MDIO_MMD_PCS_MV_TDR_STATUS_MASK			0x0003
 86#define MDIO_MMD_PCS_MV_TDR_STATUS_OFF			0x0001
 87#define MDIO_MMD_PCS_MV_TDR_STATUS_ON			0x0002
 88#define MDIO_MMD_PCS_MV_TDR_STATUS_DIST_MASK		0xff00
 89#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_MASK	0x00f0
 90#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_SHORT	0x0030
 91#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OPEN	0x00e0
 92#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OK		0x0070
 93#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_IN_PROGR	0x0080
 94#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_NOISE	0x0050
 95
 96#define MDIO_MMD_PCS_MV_TDR_OFF_CUTOFF			65246
 97
 98struct mv88q2xxx_priv {
 99	bool enable_temp;
100};
101
102struct mmd_val {
103	int devad;
104	u32 regnum;
105	u16 val;
106};
107
108static const struct mmd_val mv88q2110_init_seq0[] = {
109	{ MDIO_MMD_PCS, 0xffe4, 0x07b5 },
110	{ MDIO_MMD_PCS, 0xffe4, 0x06b6 },
111};
112
113static const struct mmd_val mv88q2110_init_seq1[] = {
114	{ MDIO_MMD_PCS, 0xffde, 0x402f },
115	{ MDIO_MMD_PCS, 0xfe34, 0x4040 },
116	{ MDIO_MMD_PCS, 0xfe2a, 0x3c1d },
117	{ MDIO_MMD_PCS, 0xfe34, 0x0040 },
118	{ MDIO_MMD_AN, 0x8032, 0x0064 },
119	{ MDIO_MMD_AN, 0x8031, 0x0a01 },
120	{ MDIO_MMD_AN, 0x8031, 0x0c01 },
121	{ MDIO_MMD_PCS, 0xffdb, 0x0010 },
122};
123
124static const struct mmd_val mv88q222x_revb0_init_seq0[] = {
125	{ MDIO_MMD_PCS, 0x8033, 0x6801 },
126	{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
127	{ MDIO_MMD_PMAPMD, MDIO_CTRL1,
128	  MDIO_CTRL1_LPOWER | MDIO_PMA_CTRL1_SPEED1000 },
129	{ MDIO_MMD_PCS, 0xfe1b, 0x48 },
130	{ MDIO_MMD_PCS, 0xffe4, 0x6b6 },
131	{ MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0 },
132	{ MDIO_MMD_PCS, MDIO_CTRL1, 0x0 },
133};
134
135static const struct mmd_val mv88q222x_revb0_init_seq1[] = {
136	{ MDIO_MMD_PCS, 0xfe79, 0x0 },
137	{ MDIO_MMD_PCS, 0xfe07, 0x125a },
138	{ MDIO_MMD_PCS, 0xfe09, 0x1288 },
139	{ MDIO_MMD_PCS, 0xfe08, 0x2588 },
140	{ MDIO_MMD_PCS, 0xfe11, 0x1105 },
141	{ MDIO_MMD_PCS, 0xfe72, 0x042c },
142	{ MDIO_MMD_PCS, 0xfbba, 0xcb2 },
143	{ MDIO_MMD_PCS, 0xfbbb, 0xc4a },
144	{ MDIO_MMD_AN, 0x8032, 0x2020 },
145	{ MDIO_MMD_AN, 0x8031, 0xa28 },
146	{ MDIO_MMD_AN, 0x8031, 0xc28 },
147	{ MDIO_MMD_PCS, 0xffdb, 0xfc10 },
148	{ MDIO_MMD_PCS, 0xfe1b, 0x58 },
149	{ MDIO_MMD_PCS, 0xfe79, 0x4 },
150	{ MDIO_MMD_PCS, 0xfe5f, 0xe8 },
151	{ MDIO_MMD_PCS, 0xfe05, 0x755c },
152};
153
154static const struct mmd_val mv88q222x_revb1_init_seq0[] = {
155	{ MDIO_MMD_PCS, 0xffe4, 0x0007 },
156	{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
157	{ MDIO_MMD_PCS, 0xffe3, 0x7000 },
158	{ MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0840 },
159};
160
161static const struct mmd_val mv88q222x_revb2_init_seq0[] = {
162	{ MDIO_MMD_PCS, 0xffe4, 0x0007 },
163	{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
164	{ MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0840 },
165};
166
167static const struct mmd_val mv88q222x_revb1_revb2_init_seq1[] = {
168	{ MDIO_MMD_PCS, 0xfe07, 0x125a },
169	{ MDIO_MMD_PCS, 0xfe09, 0x1288 },
170	{ MDIO_MMD_PCS, 0xfe08, 0x2588 },
171	{ MDIO_MMD_PCS, 0xfe72, 0x042c },
172	{ MDIO_MMD_PCS, 0xffe4, 0x0071 },
173	{ MDIO_MMD_PCS, 0xffe4, 0x0001 },
174	{ MDIO_MMD_PCS, 0xfe1b, 0x0048 },
175	{ MDIO_MMD_PMAPMD, 0x0000, 0x0000 },
176	{ MDIO_MMD_PCS, 0x0000, 0x0000 },
177	{ MDIO_MMD_PCS, 0xffdb, 0xfc10 },
178	{ MDIO_MMD_PCS, 0xfe1b, 0x58 },
179	{ MDIO_MMD_PCS, 0xfcad, 0x030c },
180	{ MDIO_MMD_PCS, 0x8032, 0x6001 },
181	{ MDIO_MMD_PCS, 0xfdff, 0x05a5 },
182	{ MDIO_MMD_PCS, 0xfdec, 0xdbaf },
183	{ MDIO_MMD_PCS, 0xfcab, 0x1054 },
184	{ MDIO_MMD_PCS, 0xfcac, 0x1483 },
185	{ MDIO_MMD_PCS, 0x8033, 0xc801 },
186	{ MDIO_MMD_AN, 0x8032, 0x2020 },
187	{ MDIO_MMD_AN, 0x8031, 0xa28 },
188	{ MDIO_MMD_AN, 0x8031, 0xc28 },
189	{ MDIO_MMD_PCS, 0xfbba, 0x0cb2 },
190	{ MDIO_MMD_PCS, 0xfbbb, 0x0c4a },
191	{ MDIO_MMD_PCS, 0xfe5f, 0xe8 },
192	{ MDIO_MMD_PCS, 0xfe05, 0x755c },
193	{ MDIO_MMD_PCS, 0xfa20, 0x002a },
194	{ MDIO_MMD_PCS, 0xfe11, 0x1105 },
195};
196
197static int mv88q2xxx_write_mmd_vals(struct phy_device *phydev,
198				    const struct mmd_val *vals, size_t len)
199{
200	int ret;
201
202	for (; len; vals++, len--) {
203		ret = phy_write_mmd(phydev, vals->devad, vals->regnum,
204				    vals->val);
205		if (ret < 0)
206			return ret;
207	}
208
209	return 0;
210}
211
212static int mv88q2xxx_soft_reset(struct phy_device *phydev)
213{
214	int ret;
215	int val;
216
217	/* Enable RESET of DCL */
218	if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000) {
219		ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x48);
220		if (ret < 0)
221			return ret;
222	}
223
224	ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_CTRL,
225			    MDIO_PCS_1000BT1_CTRL_RESET);
226	if (ret < 0)
227		return ret;
228
229	ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
230					MDIO_PCS_1000BT1_CTRL, val,
231					!(val & MDIO_PCS_1000BT1_CTRL_RESET),
232					50000, 600000, true);
233	if (ret < 0)
234		return ret;
235
236	ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xffe4, 0xc);
237	if (ret < 0)
238		return ret;
239
240	/* Disable RESET of DCL */
241	if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000)
242		return phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x58);
243
244	return 0;
245}
246
247static int mv88q2xxx_read_link_gbit(struct phy_device *phydev)
248{
249	int ret;
250	bool link = false;
251
252	/* Read vendor specific Auto-Negotiation status register to get local
253	 * and remote receiver status according to software initialization
254	 * guide. However, when not in polling mode the local and remote
255	 * receiver status are not evaluated due to the Marvell 88Q2xxx APIs.
256	 */
257	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT);
258	if (ret < 0) {
259		return ret;
260	} else if (((ret & MDIO_MMD_AN_MV_STAT_LOCAL_RX) &&
261		   (ret & MDIO_MMD_AN_MV_STAT_REMOTE_RX)) ||
262		   !phy_polling_mode(phydev)) {
263		/* The link state is latched low so that momentary link
264		 * drops can be detected. Do not double-read the status
265		 * in polling mode to detect such short link drops except
266		 * the link was already down.
267		 */
268		if (!phy_polling_mode(phydev) || !phydev->link) {
269			ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
270					   MDIO_PCS_1000BT1_STAT);
271			if (ret < 0)
272				return ret;
273			else if (ret & MDIO_PCS_1000BT1_STAT_LINK)
274				link = true;
275		}
276
277		if (!link) {
278			ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
279					   MDIO_PCS_1000BT1_STAT);
280			if (ret < 0)
281				return ret;
282			else if (ret & MDIO_PCS_1000BT1_STAT_LINK)
283				link = true;
284		}
285	}
286
287	phydev->link = link;
288
289	return 0;
290}
291
292static int mv88q2xxx_read_link_100m(struct phy_device *phydev)
293{
294	int ret;
295
296	/* The link state is latched low so that momentary link
297	 * drops can be detected. Do not double-read the status
298	 * in polling mode to detect such short link drops except
299	 * the link was already down. In case we are not polling,
300	 * we always read the realtime status.
301	 */
302	if (!phy_polling_mode(phydev)) {
303		phydev->link = false;
304		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
305				   MDIO_MMD_PCS_MV_100BT1_STAT2);
306		if (ret < 0)
307			return ret;
308
309		if (ret & MDIO_MMD_PCS_MV_100BT1_STAT2_LINK)
310			phydev->link = true;
311
312		return 0;
313	} else if (!phydev->link) {
314		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
315				   MDIO_MMD_PCS_MV_100BT1_STAT1);
316		if (ret < 0)
317			return ret;
318		else if (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK)
319			goto out;
320	}
321
322	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_100BT1_STAT1);
323	if (ret < 0)
324		return ret;
325
326out:
327	/* Check if we have link and if the remote and local receiver are ok */
328	if ((ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK) &&
329	    (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX) &&
330	    (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX))
331		phydev->link = true;
332	else
333		phydev->link = false;
334
335	return 0;
336}
337
338static int mv88q2xxx_read_link(struct phy_device *phydev)
339{
 
 
340	/* The 88Q2XXX PHYs do not have the PMA/PMD status register available,
341	 * therefore we need to read the link status from the vendor specific
342	 * registers depending on the speed.
343	 */
344
345	if (phydev->speed == SPEED_1000)
346		return mv88q2xxx_read_link_gbit(phydev);
347	else if (phydev->speed == SPEED_100)
348		return mv88q2xxx_read_link_100m(phydev);
349
350	phydev->link = false;
351	return 0;
352}
353
354static int mv88q2xxx_read_master_slave_state(struct phy_device *phydev)
355{
356	int ret;
357
358	phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
359	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT);
360	if (ret < 0)
361		return ret;
362
363	if (ret & MDIO_MMD_AN_MV_STAT_LOCAL_MASTER)
364		phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
365	else
366		phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
367
368	return 0;
369}
370
371static int mv88q2xxx_read_aneg_speed(struct phy_device *phydev)
372{
373	int ret;
374
375	phydev->speed = SPEED_UNKNOWN;
376	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT2);
377	if (ret < 0)
378		return ret;
379
380	if (!(ret & MDIO_MMD_AN_MV_STAT2_AN_RESOLVED))
381		return 0;
382
383	if (ret & MDIO_MMD_AN_MV_STAT2_100BT1)
384		phydev->speed = SPEED_100;
385	else if (ret & MDIO_MMD_AN_MV_STAT2_1000BT1)
386		phydev->speed = SPEED_1000;
387
388	return 0;
389}
390
391static int mv88q2xxx_read_status(struct phy_device *phydev)
392{
393	int ret;
394
395	if (phydev->autoneg == AUTONEG_ENABLE) {
396		/* We have to get the negotiated speed first, otherwise we are
397		 * not able to read the link.
398		 */
399		ret = mv88q2xxx_read_aneg_speed(phydev);
400		if (ret < 0)
401			return ret;
402
403		ret = mv88q2xxx_read_link(phydev);
404		if (ret < 0)
405			return ret;
406
407		ret = genphy_c45_read_lpa(phydev);
408		if (ret < 0)
409			return ret;
410
411		ret = genphy_c45_baset1_read_status(phydev);
412		if (ret < 0)
413			return ret;
414
415		ret = mv88q2xxx_read_master_slave_state(phydev);
416		if (ret < 0)
417			return ret;
418
419		phy_resolve_aneg_linkmode(phydev);
420
421		return 0;
422	}
423
424	ret = mv88q2xxx_read_link(phydev);
425	if (ret < 0)
426		return ret;
427
428	return genphy_c45_read_pma(phydev);
429}
430
431static int mv88q2xxx_get_features(struct phy_device *phydev)
432{
433	int ret;
434
435	ret = genphy_c45_pma_read_abilities(phydev);
436	if (ret)
437		return ret;
438
439	/* We need to read the baset1 extended abilities manually because the
440	 * PHY does not signalize it has the extended abilities register
441	 * available.
442	 */
443	ret = genphy_c45_pma_baset1_read_abilities(phydev);
444	if (ret)
445		return ret;
446
 
 
 
 
 
 
 
447	return 0;
448}
449
450static int mv88q2xxx_config_aneg(struct phy_device *phydev)
451{
452	int ret;
453
454	ret = genphy_c45_config_aneg(phydev);
455	if (ret)
456		return ret;
457
458	return phydev->drv->soft_reset(phydev);
459}
460
461static int mv88q2xxx_config_init(struct phy_device *phydev)
462{
 
 
463	/* The 88Q2XXX PHYs do have the extended ability register available, but
464	 * register MDIO_PMA_EXTABLE where they should signalize it does not
465	 * work according to specification. Therefore, we force it here.
466	 */
467	phydev->pma_extable = MDIO_PMA_EXTABLE_BT1;
468
469	/* Configure interrupt with default settings, output is driven low for
470	 * active interrupt and high for inactive.
471	 */
472	if (phy_interrupt_is_valid(phydev))
473		return phy_set_bits_mmd(phydev, MDIO_MMD_PCS,
474					MDIO_MMD_PCS_MV_GPIO_INT_CTRL,
475					MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS);
476
477	return 0;
478}
479
480static int mv88q2xxx_get_sqi(struct phy_device *phydev)
481{
482	int ret;
483
484	if (phydev->speed == SPEED_100) {
485		/* Read the SQI from the vendor specific receiver status
486		 * register
487		 */
488		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
489				   MDIO_MMD_PCS_MV_RX_STAT);
490		if (ret < 0)
491			return ret;
492
493		ret = ret >> 12;
494	} else {
495		/* Read from vendor specific registers, they are not documented
496		 * but can be found in the Software Initialization Guide. Only
497		 * revisions >= A0 are supported.
498		 */
499		ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, 0xfc5d, 0xff, 0xac);
500		if (ret < 0)
501			return ret;
502
503		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 0xfc88);
504		if (ret < 0)
505			return ret;
506	}
507
508	return ret & 0x0f;
509}
510
511static int mv88q2xxx_get_sqi_max(struct phy_device *phydev)
512{
513	return 15;
514}
515
516static int mv88q2xxx_config_intr(struct phy_device *phydev)
517{
518	int ret;
519
520	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
521		/* Enable interrupts for 1000BASE-T1 link up and down events
522		 * and enable general interrupts for 100BASE-T1.
523		 */
524		ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
525				    MDIO_MMD_PCS_MV_INT_EN,
526				    MDIO_MMD_PCS_MV_INT_EN_LINK_UP |
527				    MDIO_MMD_PCS_MV_INT_EN_LINK_DOWN |
528				    MDIO_MMD_PCS_MV_INT_EN_100BT1);
529		if (ret < 0)
530			return ret;
531
532		/* Enable interrupts for 100BASE-T1 link events */
533		return phy_write_mmd(phydev, MDIO_MMD_PCS,
534				     MDIO_MMD_PCS_MV_100BT1_INT_EN,
535				     MDIO_MMD_PCS_MV_100BT1_INT_EN_LINKEVENT);
536	} else {
537		ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
538				    MDIO_MMD_PCS_MV_INT_EN, 0);
539		if (ret < 0)
540			return ret;
541
542		return phy_write_mmd(phydev, MDIO_MMD_PCS,
543				     MDIO_MMD_PCS_MV_100BT1_INT_EN, 0);
544	}
545}
546
547static irqreturn_t mv88q2xxx_handle_interrupt(struct phy_device *phydev)
548{
549	bool trigger_machine = false;
550	int irq;
551
552	/* Before we can acknowledge the 100BT1 general interrupt, that is in
553	 * the 1000BT1 interrupt status register, we have to acknowledge any
554	 * interrupts that are related to it. Therefore we read first the 100BT1
555	 * interrupt status register, followed by reading the 1000BT1 interrupt
556	 * status register.
557	 */
558
559	irq = phy_read_mmd(phydev, MDIO_MMD_PCS,
560			   MDIO_MMD_PCS_MV_COPPER_INT_STAT);
561	if (irq < 0) {
562		phy_error(phydev);
563		return IRQ_NONE;
564	}
565
566	/* Check link status for 100BT1 */
567	if (irq & MDIO_MMD_PCS_MV_COPPER_INT_STAT_LINKEVENT)
568		trigger_machine = true;
569
570	irq = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_GPIO_INT_STAT);
571	if (irq < 0) {
572		phy_error(phydev);
573		return IRQ_NONE;
574	}
575
576	/* Check link status for 1000BT1 */
577	if ((irq & MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_UP) ||
578	    (irq & MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_DOWN))
579		trigger_machine = true;
580
581	if (!trigger_machine)
582		return IRQ_NONE;
583
584	phy_trigger_machine(phydev);
585
586	return IRQ_HANDLED;
587}
588
589static int mv88q2xxx_suspend(struct phy_device *phydev)
590{
591	int ret;
592
593	/* Disable PHY interrupts */
594	if (phy_interrupt_is_valid(phydev)) {
595		phydev->interrupts = PHY_INTERRUPT_DISABLED;
596		ret = mv88q2xxx_config_intr(phydev);
597		if (ret)
598			return ret;
599	}
600
601	return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1,
602				MDIO_CTRL1_LPOWER);
603}
604
605static int mv88q2xxx_resume(struct phy_device *phydev)
606{
607	int ret;
608
609	/* Enable PHY interrupts */
610	if (phy_interrupt_is_valid(phydev)) {
611		phydev->interrupts = PHY_INTERRUPT_ENABLED;
612		ret = mv88q2xxx_config_intr(phydev);
613		if (ret)
614			return ret;
615	}
616
617	return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1,
618				  MDIO_CTRL1_LPOWER);
619}
620
621#if IS_ENABLED(CONFIG_HWMON)
622static const struct hwmon_channel_info * const mv88q2xxx_hwmon_info[] = {
623	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_ALARM),
624	NULL
625};
626
627static umode_t mv88q2xxx_hwmon_is_visible(const void *data,
628					  enum hwmon_sensor_types type,
629					  u32 attr, int channel)
630{
631	switch (attr) {
632	case hwmon_temp_input:
633		return 0444;
634	case hwmon_temp_max:
635		return 0644;
636	case hwmon_temp_alarm:
637		return 0444;
638	default:
639		return 0;
640	}
641}
642
643static int mv88q2xxx_hwmon_read(struct device *dev,
644				enum hwmon_sensor_types type,
645				u32 attr, int channel, long *val)
646{
647	struct phy_device *phydev = dev_get_drvdata(dev);
648	int ret;
649
650	switch (attr) {
651	case hwmon_temp_input:
652		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
653				   MDIO_MMD_PCS_MV_TEMP_SENSOR3);
654		if (ret < 0)
655			return ret;
656
657		ret = FIELD_GET(MDIO_MMD_PCS_MV_TEMP_SENSOR3_MASK, ret);
658		*val = (ret - 75) * 1000;
659		return 0;
660	case hwmon_temp_max:
661		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
662				   MDIO_MMD_PCS_MV_TEMP_SENSOR3);
663		if (ret < 0)
664			return ret;
665
666		ret = FIELD_GET(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK,
667				ret);
668		*val = (ret - 75) * 1000;
669		return 0;
670	case hwmon_temp_alarm:
671		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
672				   MDIO_MMD_PCS_MV_TEMP_SENSOR1);
673		if (ret < 0)
674			return ret;
675
676		*val = !!(ret & MDIO_MMD_PCS_MV_TEMP_SENSOR1_RAW_INT);
677		return 0;
678	default:
679		return -EOPNOTSUPP;
680	}
681}
682
683static int mv88q2xxx_hwmon_write(struct device *dev,
684				 enum hwmon_sensor_types type, u32 attr,
685				 int channel, long val)
686{
687	struct phy_device *phydev = dev_get_drvdata(dev);
688
689	switch (attr) {
690	case hwmon_temp_max:
691		clamp_val(val, -75000, 180000);
692		val = (val / 1000) + 75;
693		val = FIELD_PREP(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK,
694				 val);
695		return phy_modify_mmd(phydev, MDIO_MMD_PCS,
696				      MDIO_MMD_PCS_MV_TEMP_SENSOR3,
697				      MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK,
698				      val);
699	default:
700		return -EOPNOTSUPP;
701	}
702}
703
704static const struct hwmon_ops mv88q2xxx_hwmon_hwmon_ops = {
705	.is_visible = mv88q2xxx_hwmon_is_visible,
706	.read = mv88q2xxx_hwmon_read,
707	.write = mv88q2xxx_hwmon_write,
708};
709
710static const struct hwmon_chip_info mv88q2xxx_hwmon_chip_info = {
711	.ops = &mv88q2xxx_hwmon_hwmon_ops,
712	.info = mv88q2xxx_hwmon_info,
713};
714
715static int mv88q2xxx_hwmon_probe(struct phy_device *phydev)
716{
717	struct mv88q2xxx_priv *priv = phydev->priv;
718	struct device *dev = &phydev->mdio.dev;
719	struct device *hwmon;
720	char *hwmon_name;
721
722	priv->enable_temp = true;
723	hwmon_name = devm_hwmon_sanitize_name(dev, dev_name(dev));
724	if (IS_ERR(hwmon_name))
725		return PTR_ERR(hwmon_name);
726
727	hwmon = devm_hwmon_device_register_with_info(dev,
728						     hwmon_name,
729						     phydev,
730						     &mv88q2xxx_hwmon_chip_info,
731						     NULL);
732
733	return PTR_ERR_OR_ZERO(hwmon);
734}
735
736#else
737static int mv88q2xxx_hwmon_probe(struct phy_device *phydev)
738{
739	return 0;
740}
741#endif
742
743static int mv88q2xxx_probe(struct phy_device *phydev)
744{
745	struct mv88q2xxx_priv *priv;
746
747	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
748	if (!priv)
749		return -ENOMEM;
750
751	phydev->priv = priv;
752
753	return mv88q2xxx_hwmon_probe(phydev);
754}
755
756static int mv88q2110_config_init(struct phy_device *phydev)
757{
758	int ret;
759
760	ret = mv88q2xxx_write_mmd_vals(phydev, mv88q2110_init_seq0,
761				       ARRAY_SIZE(mv88q2110_init_seq0));
762	if (ret < 0)
763		return ret;
764
765	usleep_range(5000, 10000);
766
767	ret = mv88q2xxx_write_mmd_vals(phydev, mv88q2110_init_seq1,
768				       ARRAY_SIZE(mv88q2110_init_seq1));
769	if (ret < 0)
770		return ret;
771
772	return mv88q2xxx_config_init(phydev);
773}
774
775static int mv88q222x_revb0_config_init(struct phy_device *phydev)
776{
777	int ret;
778
779	ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb0_init_seq0,
780				       ARRAY_SIZE(mv88q222x_revb0_init_seq0));
781	if (ret < 0)
782		return ret;
783
784	usleep_range(5000, 10000);
785
786	ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb0_init_seq1,
787				       ARRAY_SIZE(mv88q222x_revb0_init_seq1));
788	if (ret < 0)
789		return ret;
790
791	return mv88q2xxx_config_init(phydev);
792}
793
794static int mv88q222x_revb1_revb2_config_init(struct phy_device *phydev)
795{
796	bool is_rev_b1 = phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] == PHY_ID_88Q2220_REVB1;
797	int ret;
798
799	if (is_rev_b1)
800		ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb1_init_seq0,
801					       ARRAY_SIZE(mv88q222x_revb1_init_seq0));
802	else
803		ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb2_init_seq0,
804					       ARRAY_SIZE(mv88q222x_revb2_init_seq0));
805	if (ret < 0)
806		return ret;
807
808	usleep_range(3000, 5000);
809
810	ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb1_revb2_init_seq1,
811				       ARRAY_SIZE(mv88q222x_revb1_revb2_init_seq1));
812	if (ret < 0)
813		return ret;
814
815	return mv88q2xxx_config_init(phydev);
816}
817
818static int mv88q222x_config_init(struct phy_device *phydev)
819{
820	struct mv88q2xxx_priv *priv = phydev->priv;
821	int ret;
822
823	/* Enable temperature sense */
824	if (priv->enable_temp) {
825		ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
826				     MDIO_MMD_PCS_MV_TEMP_SENSOR2,
827				     MDIO_MMD_PCS_MV_TEMP_SENSOR2_DIS_MASK, 0);
828		if (ret < 0)
829			return ret;
830	}
831
832	if (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] == PHY_ID_88Q2220_REVB0)
833		return mv88q222x_revb0_config_init(phydev);
834	else
835		return mv88q222x_revb1_revb2_config_init(phydev);
836}
837
838static int mv88q222x_cable_test_start(struct phy_device *phydev)
839{
840	int ret;
841
842	ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
843			    MDIO_MMD_PCS_MV_TDR_OFF_CUTOFF, 0x0058);
844	if (ret < 0)
845		return ret;
846
847	ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
848			    MDIO_MMD_PCS_MV_TDR_OFF_LONG_CABLE, 0x00eb);
849	if (ret < 0)
850		return ret;
851
852	ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
853			    MDIO_MMD_PCS_MV_TDR_OFF_SHORT_CABLE, 0x010e);
854	if (ret < 0)
855		return ret;
856
857	ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_RESET,
858			    0x0d90);
859	if (ret < 0)
860		return ret;
861
862	ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS,
863			    MDIO_MMD_PCS_MV_TDR_STATUS_ON);
864	if (ret < 0)
865		return ret;
866
867	/* According to the Marvell API the test is finished within 500 ms */
868	msleep(500);
869
870	return 0;
871}
872
873static int mv88q222x_cable_test_get_status(struct phy_device *phydev,
874					   bool *finished)
875{
876	int ret, status;
877	u32 dist;
878
879	status = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS);
880	if (status < 0)
881		return status;
882
883	ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_RESET,
884			    MDIO_MMD_PCS_MV_TDR_RESET_TDR_RST | 0xd90);
885	if (ret < 0)
886		return ret;
887
888	/* Test could not be finished */
889	if (FIELD_GET(MDIO_MMD_PCS_MV_TDR_STATUS_MASK, status) !=
890	    MDIO_MMD_PCS_MV_TDR_STATUS_OFF)
891		return -ETIMEDOUT;
892
893	*finished = true;
894	/* Fault length reported in meters, convert to centimeters */
895	dist = FIELD_GET(MDIO_MMD_PCS_MV_TDR_STATUS_DIST_MASK, status) * 100;
896	switch (status & MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_MASK) {
897	case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OPEN:
898		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
899					ETHTOOL_A_CABLE_RESULT_CODE_OPEN);
900		ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A,
901					      dist);
902		break;
903	case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_SHORT:
904		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
905					ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT);
906		ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A,
907					      dist);
908		break;
909	case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OK:
910		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
911					ETHTOOL_A_CABLE_RESULT_CODE_OK);
912		break;
913	default:
914		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
915					ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC);
916	}
917
918	return 0;
919}
920
921static struct phy_driver mv88q2xxx_driver[] = {
922	{
923		.phy_id			= MARVELL_PHY_ID_88Q2110,
924		.phy_id_mask		= MARVELL_PHY_ID_MASK,
925		.name			= "mv88q2110",
926		.get_features		= mv88q2xxx_get_features,
927		.config_aneg		= mv88q2xxx_config_aneg,
928		.config_init		= mv88q2110_config_init,
929		.read_status		= mv88q2xxx_read_status,
930		.soft_reset		= mv88q2xxx_soft_reset,
931		.set_loopback		= genphy_c45_loopback,
932		.get_sqi		= mv88q2xxx_get_sqi,
933		.get_sqi_max		= mv88q2xxx_get_sqi_max,
934	},
935	{
936		.phy_id			= MARVELL_PHY_ID_88Q2220,
937		.phy_id_mask		= MARVELL_PHY_ID_MASK,
938		.name			= "mv88q2220",
939		.flags			= PHY_POLL_CABLE_TEST,
940		.probe			= mv88q2xxx_probe,
941		.get_features		= mv88q2xxx_get_features,
942		.config_aneg		= mv88q2xxx_config_aneg,
943		.aneg_done		= genphy_c45_aneg_done,
944		.config_init		= mv88q222x_config_init,
945		.read_status		= mv88q2xxx_read_status,
946		.soft_reset		= mv88q2xxx_soft_reset,
947		.config_intr		= mv88q2xxx_config_intr,
948		.handle_interrupt	= mv88q2xxx_handle_interrupt,
949		.set_loopback		= genphy_c45_loopback,
950		.cable_test_start	= mv88q222x_cable_test_start,
951		.cable_test_get_status	= mv88q222x_cable_test_get_status,
952		.get_sqi		= mv88q2xxx_get_sqi,
953		.get_sqi_max		= mv88q2xxx_get_sqi_max,
954		.suspend		= mv88q2xxx_suspend,
955		.resume			= mv88q2xxx_resume,
956	},
957};
958
959module_phy_driver(mv88q2xxx_driver);
960
961static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = {
962	{ MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK },
963	{ MARVELL_PHY_ID_88Q2220, MARVELL_PHY_ID_MASK },
964	{ /*sentinel*/ }
965};
966MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl);
967
968MODULE_DESCRIPTION("Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet PHY driver");
969MODULE_LICENSE("GPL");