Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  2/*
  3 *  Driver for Analog Devices Industrial Ethernet T1L PHYs
  4 *
  5 * Copyright 2020 Analog Devices Inc.
  6 */
  7#include <linux/kernel.h>
  8#include <linux/bitfield.h>
  9#include <linux/delay.h>
 10#include <linux/errno.h>
 11#include <linux/init.h>
 12#include <linux/module.h>
 13#include <linux/mii.h>
 14#include <linux/phy.h>
 15#include <linux/property.h>
 16
 17#define PHY_ID_ADIN1100				0x0283bc81
 18#define PHY_ID_ADIN1110				0x0283bc91
 19#define PHY_ID_ADIN2111				0x0283bca1
 20
 
 
 
 
 
 
 21#define ADIN_FORCED_MODE			0x8000
 22#define   ADIN_FORCED_MODE_EN			BIT(0)
 23
 24#define ADIN_CRSM_SFT_RST			0x8810
 25#define   ADIN_CRSM_SFT_RST_EN			BIT(0)
 26
 27#define ADIN_CRSM_SFT_PD_CNTRL			0x8812
 28#define   ADIN_CRSM_SFT_PD_CNTRL_EN		BIT(0)
 29
 30#define ADIN_AN_PHY_INST_STATUS			0x8030
 31#define   ADIN_IS_CFG_SLV			BIT(2)
 32#define   ADIN_IS_CFG_MST			BIT(3)
 33
 34#define ADIN_CRSM_STAT				0x8818
 35#define   ADIN_CRSM_SFT_PD_RDY			BIT(1)
 36#define   ADIN_CRSM_SYS_RDY			BIT(0)
 37
 38#define ADIN_MSE_VAL				0x830B
 39
 40#define ADIN_SQI_MAX	7
 41
 42struct adin_mse_sqi_range {
 43	u16 start;
 44	u16 end;
 45};
 46
 47static const struct adin_mse_sqi_range adin_mse_sqi_map[] = {
 48	{ 0x0A74, 0xFFFF },
 49	{ 0x084E, 0x0A74 },
 50	{ 0x0698, 0x084E },
 51	{ 0x053D, 0x0698 },
 52	{ 0x0429, 0x053D },
 53	{ 0x034E, 0x0429 },
 54	{ 0x02A0, 0x034E },
 55	{ 0x0000, 0x02A0 },
 56};
 57
 58/**
 59 * struct adin_priv - ADIN PHY driver private data
 60 * @tx_level_2v4_able:		set if the PHY supports 2.4V TX levels (10BASE-T1L)
 61 * @tx_level_2v4:		set if the PHY requests 2.4V TX levels (10BASE-T1L)
 62 * @tx_level_prop_present:	set if the TX level is specified in DT
 63 */
 64struct adin_priv {
 65	unsigned int		tx_level_2v4_able:1;
 66	unsigned int		tx_level_2v4:1;
 67	unsigned int		tx_level_prop_present:1;
 68};
 69
 70static int adin_read_status(struct phy_device *phydev)
 71{
 72	int ret;
 73
 74	ret = genphy_c45_read_status(phydev);
 75	if (ret)
 76		return ret;
 77
 78	ret = phy_read_mmd(phydev, MDIO_MMD_AN, ADIN_AN_PHY_INST_STATUS);
 79	if (ret < 0)
 80		return ret;
 81
 82	if (ret & ADIN_IS_CFG_SLV)
 83		phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
 84
 85	if (ret & ADIN_IS_CFG_MST)
 86		phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
 87
 88	return 0;
 89}
 90
 91static int adin_config_aneg(struct phy_device *phydev)
 92{
 93	struct adin_priv *priv = phydev->priv;
 94	int ret;
 95
 96	if (phydev->autoneg == AUTONEG_DISABLE) {
 97		ret = genphy_c45_pma_setup_forced(phydev);
 98		if (ret < 0)
 99			return ret;
100
101		if (priv->tx_level_prop_present && priv->tx_level_2v4)
102			ret = phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
103					       MDIO_PMA_10T1L_CTRL_2V4_EN);
104		else
105			ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
106						 MDIO_PMA_10T1L_CTRL_2V4_EN);
107		if (ret < 0)
108			return ret;
109
110		/* Force PHY to use above configurations */
111		return phy_set_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
112	}
113
114	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
115	if (ret < 0)
116		return ret;
117
118	/* Request increased transmit level from LP. */
119	if (priv->tx_level_prop_present && priv->tx_level_2v4) {
120		ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
121				       MDIO_AN_T1_ADV_H_10L_TX_HI |
122				       MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
123		if (ret < 0)
124			return ret;
125	}
126
127	/* Disable 2.4 Vpp transmit level. */
128	if ((priv->tx_level_prop_present && !priv->tx_level_2v4) || !priv->tx_level_2v4_able) {
129		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
130					 MDIO_AN_T1_ADV_H_10L_TX_HI |
131					 MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
132		if (ret < 0)
133			return ret;
134	}
135
136	return genphy_c45_config_aneg(phydev);
137}
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139static int adin_set_powerdown_mode(struct phy_device *phydev, bool en)
140{
141	int ret;
142	int val;
143
144	val = en ? ADIN_CRSM_SFT_PD_CNTRL_EN : 0;
145	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
146			    ADIN_CRSM_SFT_PD_CNTRL, val);
147	if (ret < 0)
148		return ret;
149
150	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ADIN_CRSM_STAT, ret,
151					 (ret & ADIN_CRSM_SFT_PD_RDY) == val,
152					 1000, 30000, true);
153}
154
155static int adin_suspend(struct phy_device *phydev)
156{
157	return adin_set_powerdown_mode(phydev, true);
158}
159
160static int adin_resume(struct phy_device *phydev)
161{
162	return adin_set_powerdown_mode(phydev, false);
163}
164
165static int adin_set_loopback(struct phy_device *phydev, bool enable)
166{
167	if (enable)
168		return phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
169					BMCR_LOOPBACK);
170
171	/* PCS loopback (according to 10BASE-T1L spec) */
172	return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
173				 BMCR_LOOPBACK);
174}
175
176static int adin_soft_reset(struct phy_device *phydev)
177{
178	int ret;
179
180	ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, ADIN_CRSM_SFT_RST, ADIN_CRSM_SFT_RST_EN);
181	if (ret < 0)
182		return ret;
183
184	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ADIN_CRSM_STAT, ret,
185					 (ret & ADIN_CRSM_SYS_RDY),
186					 10000, 30000, true);
187}
188
189static int adin_get_features(struct phy_device *phydev)
190{
191	struct adin_priv *priv = phydev->priv;
192	struct device *dev = &phydev->mdio.dev;
193	int ret;
194	u8 val;
195
196	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10T1L_STAT);
197	if (ret < 0)
198		return ret;
199
200	/* This depends on the voltage level from the power source */
201	priv->tx_level_2v4_able = !!(ret & MDIO_PMA_10T1L_STAT_2V4_ABLE);
202
203	phydev_dbg(phydev, "PHY supports 2.4V TX level: %s\n",
204		   priv->tx_level_2v4_able ? "yes" : "no");
205
206	priv->tx_level_prop_present = device_property_present(dev, "phy-10base-t1l-2.4vpp");
207	if (priv->tx_level_prop_present) {
208		ret = device_property_read_u8(dev, "phy-10base-t1l-2.4vpp", &val);
209		if (ret < 0)
210			return ret;
211
212		priv->tx_level_2v4 = val;
213		if (!priv->tx_level_2v4 && priv->tx_level_2v4_able)
214			phydev_info(phydev,
215				    "PHY supports 2.4V TX level, but disabled via config\n");
216	}
217
218	linkmode_set_bit_array(phy_basic_ports_array, ARRAY_SIZE(phy_basic_ports_array),
219			       phydev->supported);
220
221	return genphy_c45_pma_read_abilities(phydev);
222}
223
224static int adin_get_sqi(struct phy_device *phydev)
225{
226	u16 mse_val;
227	int sqi;
228	int ret;
229
230	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT1);
231	if (ret < 0)
232		return ret;
233	else if (!(ret & MDIO_STAT1_LSTATUS))
234		return 0;
235
236	ret = phy_read_mmd(phydev, MDIO_STAT1, ADIN_MSE_VAL);
237	if (ret < 0)
238		return ret;
239
240	mse_val = 0xFFFF & ret;
241	for (sqi = 0; sqi < ARRAY_SIZE(adin_mse_sqi_map); sqi++) {
242		if (mse_val >= adin_mse_sqi_map[sqi].start && mse_val <= adin_mse_sqi_map[sqi].end)
243			return sqi;
244	}
245
246	return -EINVAL;
247}
248
249static int adin_get_sqi_max(struct phy_device *phydev)
250{
251	return ADIN_SQI_MAX;
252}
253
254static int adin_probe(struct phy_device *phydev)
255{
256	struct device *dev = &phydev->mdio.dev;
257	struct adin_priv *priv;
258
259	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
260	if (!priv)
261		return -ENOMEM;
262
263	phydev->priv = priv;
264
265	return 0;
266}
267
268static struct phy_driver adin_driver[] = {
269	{
270		.phy_id			= PHY_ID_ADIN1100,
271		.phy_id_mask		= 0xffffffcf,
272		.name			= "ADIN1100",
273		.get_features		= adin_get_features,
274		.soft_reset		= adin_soft_reset,
275		.probe			= adin_probe,
276		.config_aneg		= adin_config_aneg,
277		.read_status		= adin_read_status,
 
 
278		.set_loopback		= adin_set_loopback,
279		.suspend		= adin_suspend,
280		.resume			= adin_resume,
281		.get_sqi		= adin_get_sqi,
282		.get_sqi_max		= adin_get_sqi_max,
283	},
284};
285
286module_phy_driver(adin_driver);
287
288static struct mdio_device_id __maybe_unused adin_tbl[] = {
289	{ PHY_ID_MATCH_MODEL(PHY_ID_ADIN1100) },
290	{ PHY_ID_MATCH_MODEL(PHY_ID_ADIN1110) },
291	{ PHY_ID_MATCH_MODEL(PHY_ID_ADIN2111) },
292	{ }
293};
294
295MODULE_DEVICE_TABLE(mdio, adin_tbl);
296MODULE_DESCRIPTION("Analog Devices Industrial Ethernet T1L PHY driver");
297MODULE_LICENSE("Dual BSD/GPL");
v6.9.4
  1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  2/*
  3 *  Driver for Analog Devices Industrial Ethernet T1L PHYs
  4 *
  5 * Copyright 2020 Analog Devices Inc.
  6 */
  7#include <linux/kernel.h>
  8#include <linux/bitfield.h>
  9#include <linux/delay.h>
 10#include <linux/errno.h>
 11#include <linux/init.h>
 12#include <linux/module.h>
 13#include <linux/mii.h>
 14#include <linux/phy.h>
 15#include <linux/property.h>
 16
 17#define PHY_ID_ADIN1100				0x0283bc81
 18#define PHY_ID_ADIN1110				0x0283bc91
 19#define PHY_ID_ADIN2111				0x0283bca1
 20
 21#define ADIN_PHY_SUBSYS_IRQ_MASK		0x0021
 22#define   ADIN_LINK_STAT_CHNG_IRQ_EN		BIT(1)
 23
 24#define ADIN_PHY_SUBSYS_IRQ_STATUS		0x0011
 25#define   ADIN_LINK_STAT_CHNG			BIT(1)
 26
 27#define ADIN_FORCED_MODE			0x8000
 28#define   ADIN_FORCED_MODE_EN			BIT(0)
 29
 30#define ADIN_CRSM_SFT_RST			0x8810
 31#define   ADIN_CRSM_SFT_RST_EN			BIT(0)
 32
 33#define ADIN_CRSM_SFT_PD_CNTRL			0x8812
 34#define   ADIN_CRSM_SFT_PD_CNTRL_EN		BIT(0)
 35
 36#define ADIN_AN_PHY_INST_STATUS			0x8030
 37#define   ADIN_IS_CFG_SLV			BIT(2)
 38#define   ADIN_IS_CFG_MST			BIT(3)
 39
 40#define ADIN_CRSM_STAT				0x8818
 41#define   ADIN_CRSM_SFT_PD_RDY			BIT(1)
 42#define   ADIN_CRSM_SYS_RDY			BIT(0)
 43
 44#define ADIN_MSE_VAL				0x830B
 45
 46#define ADIN_SQI_MAX	7
 47
 48struct adin_mse_sqi_range {
 49	u16 start;
 50	u16 end;
 51};
 52
 53static const struct adin_mse_sqi_range adin_mse_sqi_map[] = {
 54	{ 0x0A74, 0xFFFF },
 55	{ 0x084E, 0x0A74 },
 56	{ 0x0698, 0x084E },
 57	{ 0x053D, 0x0698 },
 58	{ 0x0429, 0x053D },
 59	{ 0x034E, 0x0429 },
 60	{ 0x02A0, 0x034E },
 61	{ 0x0000, 0x02A0 },
 62};
 63
 64/**
 65 * struct adin_priv - ADIN PHY driver private data
 66 * @tx_level_2v4_able:		set if the PHY supports 2.4V TX levels (10BASE-T1L)
 67 * @tx_level_2v4:		set if the PHY requests 2.4V TX levels (10BASE-T1L)
 68 * @tx_level_prop_present:	set if the TX level is specified in DT
 69 */
 70struct adin_priv {
 71	unsigned int		tx_level_2v4_able:1;
 72	unsigned int		tx_level_2v4:1;
 73	unsigned int		tx_level_prop_present:1;
 74};
 75
 76static int adin_read_status(struct phy_device *phydev)
 77{
 78	int ret;
 79
 80	ret = genphy_c45_read_status(phydev);
 81	if (ret)
 82		return ret;
 83
 84	ret = phy_read_mmd(phydev, MDIO_MMD_AN, ADIN_AN_PHY_INST_STATUS);
 85	if (ret < 0)
 86		return ret;
 87
 88	if (ret & ADIN_IS_CFG_SLV)
 89		phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
 90
 91	if (ret & ADIN_IS_CFG_MST)
 92		phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
 93
 94	return 0;
 95}
 96
 97static int adin_config_aneg(struct phy_device *phydev)
 98{
 99	struct adin_priv *priv = phydev->priv;
100	int ret;
101
102	if (phydev->autoneg == AUTONEG_DISABLE) {
103		ret = genphy_c45_pma_setup_forced(phydev);
104		if (ret < 0)
105			return ret;
106
107		if (priv->tx_level_prop_present && priv->tx_level_2v4)
108			ret = phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
109					       MDIO_PMA_10T1L_CTRL_2V4_EN);
110		else
111			ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
112						 MDIO_PMA_10T1L_CTRL_2V4_EN);
113		if (ret < 0)
114			return ret;
115
116		/* Force PHY to use above configurations */
117		return phy_set_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
118	}
119
120	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
121	if (ret < 0)
122		return ret;
123
124	/* Request increased transmit level from LP. */
125	if (priv->tx_level_prop_present && priv->tx_level_2v4) {
126		ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
127				       MDIO_AN_T1_ADV_H_10L_TX_HI |
128				       MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
129		if (ret < 0)
130			return ret;
131	}
132
133	/* Disable 2.4 Vpp transmit level. */
134	if ((priv->tx_level_prop_present && !priv->tx_level_2v4) || !priv->tx_level_2v4_able) {
135		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
136					 MDIO_AN_T1_ADV_H_10L_TX_HI |
137					 MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
138		if (ret < 0)
139			return ret;
140	}
141
142	return genphy_c45_config_aneg(phydev);
143}
144
145static int adin_phy_ack_intr(struct phy_device *phydev)
146{
147	/* Clear pending interrupts */
148	int rc = phy_read_mmd(phydev, MDIO_MMD_VEND2,
149			      ADIN_PHY_SUBSYS_IRQ_STATUS);
150
151	return rc < 0 ? rc : 0;
152}
153
154static int adin_config_intr(struct phy_device *phydev)
155{
156	u16 irq_mask;
157	int ret;
158
159	ret = adin_phy_ack_intr(phydev);
160	if (ret)
161		return ret;
162
163	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
164		irq_mask = ADIN_LINK_STAT_CHNG_IRQ_EN;
165	else
166		irq_mask = 0;
167
168	return phy_modify_mmd(phydev, MDIO_MMD_VEND2,
169			      ADIN_PHY_SUBSYS_IRQ_MASK,
170			      ADIN_LINK_STAT_CHNG_IRQ_EN, irq_mask);
171}
172
173static irqreturn_t adin_phy_handle_interrupt(struct phy_device *phydev)
174{
175	int irq_status;
176
177	irq_status = phy_read_mmd(phydev, MDIO_MMD_VEND2,
178				  ADIN_PHY_SUBSYS_IRQ_STATUS);
179	if (irq_status < 0) {
180		phy_error(phydev);
181		return IRQ_NONE;
182	}
183
184	if (!(irq_status & ADIN_LINK_STAT_CHNG))
185		return IRQ_NONE;
186
187	phy_trigger_machine(phydev);
188
189	return IRQ_HANDLED;
190}
191
192static int adin_set_powerdown_mode(struct phy_device *phydev, bool en)
193{
194	int ret;
195	int val;
196
197	val = en ? ADIN_CRSM_SFT_PD_CNTRL_EN : 0;
198	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
199			    ADIN_CRSM_SFT_PD_CNTRL, val);
200	if (ret < 0)
201		return ret;
202
203	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ADIN_CRSM_STAT, ret,
204					 (ret & ADIN_CRSM_SFT_PD_RDY) == val,
205					 1000, 30000, true);
206}
207
208static int adin_suspend(struct phy_device *phydev)
209{
210	return adin_set_powerdown_mode(phydev, true);
211}
212
213static int adin_resume(struct phy_device *phydev)
214{
215	return adin_set_powerdown_mode(phydev, false);
216}
217
218static int adin_set_loopback(struct phy_device *phydev, bool enable)
219{
220	if (enable)
221		return phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
222					BMCR_LOOPBACK);
223
224	/* PCS loopback (according to 10BASE-T1L spec) */
225	return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
226				 BMCR_LOOPBACK);
227}
228
229static int adin_soft_reset(struct phy_device *phydev)
230{
231	int ret;
232
233	ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, ADIN_CRSM_SFT_RST, ADIN_CRSM_SFT_RST_EN);
234	if (ret < 0)
235		return ret;
236
237	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ADIN_CRSM_STAT, ret,
238					 (ret & ADIN_CRSM_SYS_RDY),
239					 10000, 30000, true);
240}
241
242static int adin_get_features(struct phy_device *phydev)
243{
244	struct adin_priv *priv = phydev->priv;
245	struct device *dev = &phydev->mdio.dev;
246	int ret;
247	u8 val;
248
249	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10T1L_STAT);
250	if (ret < 0)
251		return ret;
252
253	/* This depends on the voltage level from the power source */
254	priv->tx_level_2v4_able = !!(ret & MDIO_PMA_10T1L_STAT_2V4_ABLE);
255
256	phydev_dbg(phydev, "PHY supports 2.4V TX level: %s\n",
257		   priv->tx_level_2v4_able ? "yes" : "no");
258
259	priv->tx_level_prop_present = device_property_present(dev, "phy-10base-t1l-2.4vpp");
260	if (priv->tx_level_prop_present) {
261		ret = device_property_read_u8(dev, "phy-10base-t1l-2.4vpp", &val);
262		if (ret < 0)
263			return ret;
264
265		priv->tx_level_2v4 = val;
266		if (!priv->tx_level_2v4 && priv->tx_level_2v4_able)
267			phydev_info(phydev,
268				    "PHY supports 2.4V TX level, but disabled via config\n");
269	}
270
271	linkmode_set_bit_array(phy_basic_ports_array, ARRAY_SIZE(phy_basic_ports_array),
272			       phydev->supported);
273
274	return genphy_c45_pma_read_abilities(phydev);
275}
276
277static int adin_get_sqi(struct phy_device *phydev)
278{
279	u16 mse_val;
280	int sqi;
281	int ret;
282
283	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT1);
284	if (ret < 0)
285		return ret;
286	else if (!(ret & MDIO_STAT1_LSTATUS))
287		return 0;
288
289	ret = phy_read_mmd(phydev, MDIO_STAT1, ADIN_MSE_VAL);
290	if (ret < 0)
291		return ret;
292
293	mse_val = 0xFFFF & ret;
294	for (sqi = 0; sqi < ARRAY_SIZE(adin_mse_sqi_map); sqi++) {
295		if (mse_val >= adin_mse_sqi_map[sqi].start && mse_val <= adin_mse_sqi_map[sqi].end)
296			return sqi;
297	}
298
299	return -EINVAL;
300}
301
302static int adin_get_sqi_max(struct phy_device *phydev)
303{
304	return ADIN_SQI_MAX;
305}
306
307static int adin_probe(struct phy_device *phydev)
308{
309	struct device *dev = &phydev->mdio.dev;
310	struct adin_priv *priv;
311
312	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
313	if (!priv)
314		return -ENOMEM;
315
316	phydev->priv = priv;
317
318	return 0;
319}
320
321static struct phy_driver adin_driver[] = {
322	{
323		.phy_id			= PHY_ID_ADIN1100,
324		.phy_id_mask		= 0xffffffcf,
325		.name			= "ADIN1100",
326		.get_features		= adin_get_features,
327		.soft_reset		= adin_soft_reset,
328		.probe			= adin_probe,
329		.config_aneg		= adin_config_aneg,
330		.read_status		= adin_read_status,
331		.config_intr		= adin_config_intr,
332		.handle_interrupt	= adin_phy_handle_interrupt,
333		.set_loopback		= adin_set_loopback,
334		.suspend		= adin_suspend,
335		.resume			= adin_resume,
336		.get_sqi		= adin_get_sqi,
337		.get_sqi_max		= adin_get_sqi_max,
338	},
339};
340
341module_phy_driver(adin_driver);
342
343static struct mdio_device_id __maybe_unused adin_tbl[] = {
344	{ PHY_ID_MATCH_MODEL(PHY_ID_ADIN1100) },
345	{ PHY_ID_MATCH_MODEL(PHY_ID_ADIN1110) },
346	{ PHY_ID_MATCH_MODEL(PHY_ID_ADIN2111) },
347	{ }
348};
349
350MODULE_DEVICE_TABLE(mdio, adin_tbl);
351MODULE_DESCRIPTION("Analog Devices Industrial Ethernet T1L PHY driver");
352MODULE_LICENSE("Dual BSD/GPL");