xref: /openbmc/linux/drivers/net/phy/dp83822.c (revision 87461f7a58ab694e638ac52afa543b427751a9d0)
1*87461f7aSDan Murphy /*
2*87461f7aSDan Murphy  * Driver for the Texas Instruments DP83822 PHY
3*87461f7aSDan Murphy  *
4*87461f7aSDan Murphy  * Copyright (C) 2017 Texas Instruments Inc.
5*87461f7aSDan Murphy  *
6*87461f7aSDan Murphy  * This program is free software; you can redistribute it and/or modify
7*87461f7aSDan Murphy  * it under the terms of the GNU General Public License as published by
8*87461f7aSDan Murphy  * the Free Software Foundation; either version 2 of the License.
9*87461f7aSDan Murphy  *
10*87461f7aSDan Murphy  * This program is distributed in the hope that it will be useful,
11*87461f7aSDan Murphy  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*87461f7aSDan Murphy  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*87461f7aSDan Murphy  * GNU General Public License for more details.
14*87461f7aSDan Murphy  */
15*87461f7aSDan Murphy 
16*87461f7aSDan Murphy #include <linux/ethtool.h>
17*87461f7aSDan Murphy #include <linux/etherdevice.h>
18*87461f7aSDan Murphy #include <linux/kernel.h>
19*87461f7aSDan Murphy #include <linux/mii.h>
20*87461f7aSDan Murphy #include <linux/module.h>
21*87461f7aSDan Murphy #include <linux/of.h>
22*87461f7aSDan Murphy #include <linux/phy.h>
23*87461f7aSDan Murphy #include <linux/netdevice.h>
24*87461f7aSDan Murphy 
25*87461f7aSDan Murphy #define DP83822_PHY_ID	        0x2000a240
26*87461f7aSDan Murphy #define DP83822_DEVADDR		0x1f
27*87461f7aSDan Murphy 
28*87461f7aSDan Murphy #define MII_DP83822_PHYSCR	0x11
29*87461f7aSDan Murphy #define MII_DP83822_MISR1	0x12
30*87461f7aSDan Murphy #define MII_DP83822_MISR2	0x13
31*87461f7aSDan Murphy #define MII_DP83822_RESET_CTRL	0x1f
32*87461f7aSDan Murphy 
33*87461f7aSDan Murphy #define DP83822_HW_RESET	BIT(15)
34*87461f7aSDan Murphy #define DP83822_SW_RESET	BIT(14)
35*87461f7aSDan Murphy 
36*87461f7aSDan Murphy /* PHYSCR Register Fields */
37*87461f7aSDan Murphy #define DP83822_PHYSCR_INT_OE		BIT(0) /* Interrupt Output Enable */
38*87461f7aSDan Murphy #define DP83822_PHYSCR_INTEN		BIT(1) /* Interrupt Enable */
39*87461f7aSDan Murphy 
40*87461f7aSDan Murphy /* MISR1 bits */
41*87461f7aSDan Murphy #define DP83822_RX_ERR_HF_INT_EN	BIT(0)
42*87461f7aSDan Murphy #define DP83822_FALSE_CARRIER_HF_INT_EN	BIT(1)
43*87461f7aSDan Murphy #define DP83822_ANEG_COMPLETE_INT_EN	BIT(2)
44*87461f7aSDan Murphy #define DP83822_DUP_MODE_CHANGE_INT_EN	BIT(3)
45*87461f7aSDan Murphy #define DP83822_SPEED_CHANGED_INT_EN	BIT(4)
46*87461f7aSDan Murphy #define DP83822_LINK_STAT_INT_EN	BIT(5)
47*87461f7aSDan Murphy #define DP83822_ENERGY_DET_INT_EN	BIT(6)
48*87461f7aSDan Murphy #define DP83822_LINK_QUAL_INT_EN	BIT(7)
49*87461f7aSDan Murphy 
50*87461f7aSDan Murphy /* MISR2 bits */
51*87461f7aSDan Murphy #define DP83822_JABBER_DET_INT_EN	BIT(0)
52*87461f7aSDan Murphy #define DP83822_WOL_PKT_INT_EN		BIT(1)
53*87461f7aSDan Murphy #define DP83822_SLEEP_MODE_INT_EN	BIT(2)
54*87461f7aSDan Murphy #define DP83822_MDI_XOVER_INT_EN	BIT(3)
55*87461f7aSDan Murphy #define DP83822_LB_FIFO_INT_EN		BIT(4)
56*87461f7aSDan Murphy #define DP83822_PAGE_RX_INT_EN		BIT(5)
57*87461f7aSDan Murphy #define DP83822_ANEG_ERR_INT_EN		BIT(6)
58*87461f7aSDan Murphy #define DP83822_EEE_ERROR_CHANGE_INT_EN	BIT(7)
59*87461f7aSDan Murphy 
60*87461f7aSDan Murphy /* INT_STAT1 bits */
61*87461f7aSDan Murphy #define DP83822_WOL_INT_EN	BIT(4)
62*87461f7aSDan Murphy #define DP83822_WOL_INT_STAT	BIT(12)
63*87461f7aSDan Murphy 
64*87461f7aSDan Murphy #define MII_DP83822_RXSOP1	0x04a5
65*87461f7aSDan Murphy #define	MII_DP83822_RXSOP2	0x04a6
66*87461f7aSDan Murphy #define	MII_DP83822_RXSOP3	0x04a7
67*87461f7aSDan Murphy 
68*87461f7aSDan Murphy /* WoL Registers */
69*87461f7aSDan Murphy #define	MII_DP83822_WOL_CFG	0x04a0
70*87461f7aSDan Murphy #define	MII_DP83822_WOL_STAT	0x04a1
71*87461f7aSDan Murphy #define	MII_DP83822_WOL_DA1	0x04a2
72*87461f7aSDan Murphy #define	MII_DP83822_WOL_DA2	0x04a3
73*87461f7aSDan Murphy #define	MII_DP83822_WOL_DA3	0x04a4
74*87461f7aSDan Murphy 
75*87461f7aSDan Murphy /* WoL bits */
76*87461f7aSDan Murphy #define DP83822_WOL_MAGIC_EN	BIT(0)
77*87461f7aSDan Murphy #define DP83822_WOL_SECURE_ON	BIT(5)
78*87461f7aSDan Murphy #define DP83822_WOL_EN		BIT(7)
79*87461f7aSDan Murphy #define DP83822_WOL_INDICATION_SEL BIT(8)
80*87461f7aSDan Murphy #define DP83822_WOL_CLR_INDICATION BIT(11)
81*87461f7aSDan Murphy 
82*87461f7aSDan Murphy static int dp83822_ack_interrupt(struct phy_device *phydev)
83*87461f7aSDan Murphy {
84*87461f7aSDan Murphy 	int err;
85*87461f7aSDan Murphy 
86*87461f7aSDan Murphy 	err = phy_read(phydev, MII_DP83822_MISR1);
87*87461f7aSDan Murphy 	if (err < 0)
88*87461f7aSDan Murphy 		return err;
89*87461f7aSDan Murphy 
90*87461f7aSDan Murphy 	err = phy_read(phydev, MII_DP83822_MISR2);
91*87461f7aSDan Murphy 	if (err < 0)
92*87461f7aSDan Murphy 		return err;
93*87461f7aSDan Murphy 
94*87461f7aSDan Murphy 	return 0;
95*87461f7aSDan Murphy }
96*87461f7aSDan Murphy 
97*87461f7aSDan Murphy static int dp83822_set_wol(struct phy_device *phydev,
98*87461f7aSDan Murphy 			   struct ethtool_wolinfo *wol)
99*87461f7aSDan Murphy {
100*87461f7aSDan Murphy 	struct net_device *ndev = phydev->attached_dev;
101*87461f7aSDan Murphy 	u16 value;
102*87461f7aSDan Murphy 	const u8 *mac;
103*87461f7aSDan Murphy 
104*87461f7aSDan Murphy 	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
105*87461f7aSDan Murphy 		mac = (const u8 *)ndev->dev_addr;
106*87461f7aSDan Murphy 
107*87461f7aSDan Murphy 		if (!is_valid_ether_addr(mac))
108*87461f7aSDan Murphy 			return -EINVAL;
109*87461f7aSDan Murphy 
110*87461f7aSDan Murphy 		/* MAC addresses start with byte 5, but stored in mac[0].
111*87461f7aSDan Murphy 		 * 822 PHYs store bytes 4|5, 2|3, 0|1
112*87461f7aSDan Murphy 		 */
113*87461f7aSDan Murphy 		phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA1,
114*87461f7aSDan Murphy 			      (mac[1] << 8) | mac[0]);
115*87461f7aSDan Murphy 		phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA2,
116*87461f7aSDan Murphy 			      (mac[3] << 8) | mac[2]);
117*87461f7aSDan Murphy 		phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA3,
118*87461f7aSDan Murphy 			      (mac[5] << 8) | mac[4]);
119*87461f7aSDan Murphy 
120*87461f7aSDan Murphy 		value = phy_read_mmd(phydev, DP83822_DEVADDR,
121*87461f7aSDan Murphy 				     MII_DP83822_WOL_CFG);
122*87461f7aSDan Murphy 		if (wol->wolopts & WAKE_MAGIC)
123*87461f7aSDan Murphy 			value |= DP83822_WOL_MAGIC_EN;
124*87461f7aSDan Murphy 		else
125*87461f7aSDan Murphy 			value &= ~DP83822_WOL_MAGIC_EN;
126*87461f7aSDan Murphy 
127*87461f7aSDan Murphy 		if (wol->wolopts & WAKE_MAGICSECURE) {
128*87461f7aSDan Murphy 			phy_write_mmd(phydev, DP83822_DEVADDR,
129*87461f7aSDan Murphy 				      MII_DP83822_RXSOP1,
130*87461f7aSDan Murphy 				      (wol->sopass[1] << 8) | wol->sopass[0]);
131*87461f7aSDan Murphy 			phy_write_mmd(phydev, DP83822_DEVADDR,
132*87461f7aSDan Murphy 				      MII_DP83822_RXSOP2,
133*87461f7aSDan Murphy 				      (wol->sopass[3] << 8) | wol->sopass[2]);
134*87461f7aSDan Murphy 			phy_write_mmd(phydev, DP83822_DEVADDR,
135*87461f7aSDan Murphy 				      MII_DP83822_RXSOP3,
136*87461f7aSDan Murphy 				      (wol->sopass[5] << 8) | wol->sopass[4]);
137*87461f7aSDan Murphy 			value |= DP83822_WOL_SECURE_ON;
138*87461f7aSDan Murphy 		} else {
139*87461f7aSDan Murphy 			value &= ~DP83822_WOL_SECURE_ON;
140*87461f7aSDan Murphy 		}
141*87461f7aSDan Murphy 
142*87461f7aSDan Murphy 		value |= (DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL |
143*87461f7aSDan Murphy 			  DP83822_WOL_CLR_INDICATION);
144*87461f7aSDan Murphy 		phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
145*87461f7aSDan Murphy 			      value);
146*87461f7aSDan Murphy 	} else {
147*87461f7aSDan Murphy 		value = phy_read_mmd(phydev, DP83822_DEVADDR,
148*87461f7aSDan Murphy 				     MII_DP83822_WOL_CFG);
149*87461f7aSDan Murphy 		value &= ~DP83822_WOL_EN;
150*87461f7aSDan Murphy 		phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
151*87461f7aSDan Murphy 			      value);
152*87461f7aSDan Murphy 	}
153*87461f7aSDan Murphy 
154*87461f7aSDan Murphy 	return 0;
155*87461f7aSDan Murphy }
156*87461f7aSDan Murphy 
157*87461f7aSDan Murphy static void dp83822_get_wol(struct phy_device *phydev,
158*87461f7aSDan Murphy 			    struct ethtool_wolinfo *wol)
159*87461f7aSDan Murphy {
160*87461f7aSDan Murphy 	int value;
161*87461f7aSDan Murphy 	u16 sopass_val;
162*87461f7aSDan Murphy 
163*87461f7aSDan Murphy 	wol->supported = (WAKE_MAGIC | WAKE_MAGICSECURE);
164*87461f7aSDan Murphy 	wol->wolopts = 0;
165*87461f7aSDan Murphy 
166*87461f7aSDan Murphy 	value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
167*87461f7aSDan Murphy 
168*87461f7aSDan Murphy 	if (value & DP83822_WOL_MAGIC_EN)
169*87461f7aSDan Murphy 		wol->wolopts |= WAKE_MAGIC;
170*87461f7aSDan Murphy 
171*87461f7aSDan Murphy 	if (value & DP83822_WOL_SECURE_ON) {
172*87461f7aSDan Murphy 		sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
173*87461f7aSDan Murphy 					  MII_DP83822_RXSOP1);
174*87461f7aSDan Murphy 		wol->sopass[0] = (sopass_val & 0xff);
175*87461f7aSDan Murphy 		wol->sopass[1] = (sopass_val >> 8);
176*87461f7aSDan Murphy 
177*87461f7aSDan Murphy 		sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
178*87461f7aSDan Murphy 					  MII_DP83822_RXSOP2);
179*87461f7aSDan Murphy 		wol->sopass[2] = (sopass_val & 0xff);
180*87461f7aSDan Murphy 		wol->sopass[3] = (sopass_val >> 8);
181*87461f7aSDan Murphy 
182*87461f7aSDan Murphy 		sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
183*87461f7aSDan Murphy 					  MII_DP83822_RXSOP3);
184*87461f7aSDan Murphy 		wol->sopass[4] = (sopass_val & 0xff);
185*87461f7aSDan Murphy 		wol->sopass[5] = (sopass_val >> 8);
186*87461f7aSDan Murphy 
187*87461f7aSDan Murphy 		wol->wolopts |= WAKE_MAGICSECURE;
188*87461f7aSDan Murphy 	}
189*87461f7aSDan Murphy 
190*87461f7aSDan Murphy 	/* WoL is not enabled so set wolopts to 0 */
191*87461f7aSDan Murphy 	if (!(value & DP83822_WOL_EN))
192*87461f7aSDan Murphy 		wol->wolopts = 0;
193*87461f7aSDan Murphy }
194*87461f7aSDan Murphy 
195*87461f7aSDan Murphy static int dp83822_config_intr(struct phy_device *phydev)
196*87461f7aSDan Murphy {
197*87461f7aSDan Murphy 	int misr_status;
198*87461f7aSDan Murphy 	int physcr_status;
199*87461f7aSDan Murphy 	int err;
200*87461f7aSDan Murphy 
201*87461f7aSDan Murphy 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
202*87461f7aSDan Murphy 		misr_status = phy_read(phydev, MII_DP83822_MISR1);
203*87461f7aSDan Murphy 		if (misr_status < 0)
204*87461f7aSDan Murphy 			return misr_status;
205*87461f7aSDan Murphy 
206*87461f7aSDan Murphy 		misr_status |= (DP83822_RX_ERR_HF_INT_EN |
207*87461f7aSDan Murphy 				DP83822_FALSE_CARRIER_HF_INT_EN |
208*87461f7aSDan Murphy 				DP83822_ANEG_COMPLETE_INT_EN |
209*87461f7aSDan Murphy 				DP83822_DUP_MODE_CHANGE_INT_EN |
210*87461f7aSDan Murphy 				DP83822_SPEED_CHANGED_INT_EN |
211*87461f7aSDan Murphy 				DP83822_LINK_STAT_INT_EN |
212*87461f7aSDan Murphy 				DP83822_ENERGY_DET_INT_EN |
213*87461f7aSDan Murphy 				DP83822_LINK_QUAL_INT_EN);
214*87461f7aSDan Murphy 
215*87461f7aSDan Murphy 		err = phy_write(phydev, MII_DP83822_MISR1, misr_status);
216*87461f7aSDan Murphy 		if (err < 0)
217*87461f7aSDan Murphy 			return err;
218*87461f7aSDan Murphy 
219*87461f7aSDan Murphy 		misr_status = phy_read(phydev, MII_DP83822_MISR2);
220*87461f7aSDan Murphy 		if (misr_status < 0)
221*87461f7aSDan Murphy 			return misr_status;
222*87461f7aSDan Murphy 
223*87461f7aSDan Murphy 		misr_status |= (DP83822_JABBER_DET_INT_EN |
224*87461f7aSDan Murphy 				DP83822_WOL_PKT_INT_EN |
225*87461f7aSDan Murphy 				DP83822_SLEEP_MODE_INT_EN |
226*87461f7aSDan Murphy 				DP83822_MDI_XOVER_INT_EN |
227*87461f7aSDan Murphy 				DP83822_LB_FIFO_INT_EN |
228*87461f7aSDan Murphy 				DP83822_PAGE_RX_INT_EN |
229*87461f7aSDan Murphy 				DP83822_ANEG_ERR_INT_EN |
230*87461f7aSDan Murphy 				DP83822_EEE_ERROR_CHANGE_INT_EN);
231*87461f7aSDan Murphy 
232*87461f7aSDan Murphy 		err = phy_write(phydev, MII_DP83822_MISR2, misr_status);
233*87461f7aSDan Murphy 		if (err < 0)
234*87461f7aSDan Murphy 			return err;
235*87461f7aSDan Murphy 
236*87461f7aSDan Murphy 		physcr_status = phy_read(phydev, MII_DP83822_PHYSCR);
237*87461f7aSDan Murphy 		if (physcr_status < 0)
238*87461f7aSDan Murphy 			return physcr_status;
239*87461f7aSDan Murphy 
240*87461f7aSDan Murphy 		physcr_status |= DP83822_PHYSCR_INT_OE | DP83822_PHYSCR_INTEN;
241*87461f7aSDan Murphy 
242*87461f7aSDan Murphy 	} else {
243*87461f7aSDan Murphy 		err = phy_write(phydev, MII_DP83822_MISR1, 0);
244*87461f7aSDan Murphy 		if (err < 0)
245*87461f7aSDan Murphy 			return err;
246*87461f7aSDan Murphy 
247*87461f7aSDan Murphy 		err = phy_write(phydev, MII_DP83822_MISR1, 0);
248*87461f7aSDan Murphy 		if (err < 0)
249*87461f7aSDan Murphy 			return err;
250*87461f7aSDan Murphy 
251*87461f7aSDan Murphy 		physcr_status = phy_read(phydev, MII_DP83822_PHYSCR);
252*87461f7aSDan Murphy 		if (physcr_status < 0)
253*87461f7aSDan Murphy 			return physcr_status;
254*87461f7aSDan Murphy 
255*87461f7aSDan Murphy 		physcr_status &= ~DP83822_PHYSCR_INTEN;
256*87461f7aSDan Murphy 	}
257*87461f7aSDan Murphy 
258*87461f7aSDan Murphy 	return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status);
259*87461f7aSDan Murphy }
260*87461f7aSDan Murphy 
261*87461f7aSDan Murphy static int dp83822_config_init(struct phy_device *phydev)
262*87461f7aSDan Murphy {
263*87461f7aSDan Murphy 	int err;
264*87461f7aSDan Murphy 	int value;
265*87461f7aSDan Murphy 
266*87461f7aSDan Murphy 	err = genphy_config_init(phydev);
267*87461f7aSDan Murphy 	if (err < 0)
268*87461f7aSDan Murphy 		return err;
269*87461f7aSDan Murphy 
270*87461f7aSDan Murphy 	value = DP83822_WOL_MAGIC_EN | DP83822_WOL_SECURE_ON | DP83822_WOL_EN;
271*87461f7aSDan Murphy 
272*87461f7aSDan Murphy 	return phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
273*87461f7aSDan Murphy 	      value);
274*87461f7aSDan Murphy }
275*87461f7aSDan Murphy 
276*87461f7aSDan Murphy static int dp83822_phy_reset(struct phy_device *phydev)
277*87461f7aSDan Murphy {
278*87461f7aSDan Murphy 	int err;
279*87461f7aSDan Murphy 
280*87461f7aSDan Murphy 	err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_HW_RESET);
281*87461f7aSDan Murphy 	if (err < 0)
282*87461f7aSDan Murphy 		return err;
283*87461f7aSDan Murphy 
284*87461f7aSDan Murphy 	dp83822_config_init(phydev);
285*87461f7aSDan Murphy 
286*87461f7aSDan Murphy 	return 0;
287*87461f7aSDan Murphy }
288*87461f7aSDan Murphy 
289*87461f7aSDan Murphy static int dp83822_suspend(struct phy_device *phydev)
290*87461f7aSDan Murphy {
291*87461f7aSDan Murphy 	int value;
292*87461f7aSDan Murphy 
293*87461f7aSDan Murphy 	value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
294*87461f7aSDan Murphy 
295*87461f7aSDan Murphy 	if (!(value & DP83822_WOL_EN))
296*87461f7aSDan Murphy 		genphy_suspend(phydev);
297*87461f7aSDan Murphy 
298*87461f7aSDan Murphy 	return 0;
299*87461f7aSDan Murphy }
300*87461f7aSDan Murphy 
301*87461f7aSDan Murphy static int dp83822_resume(struct phy_device *phydev)
302*87461f7aSDan Murphy {
303*87461f7aSDan Murphy 	int value;
304*87461f7aSDan Murphy 
305*87461f7aSDan Murphy 	genphy_resume(phydev);
306*87461f7aSDan Murphy 
307*87461f7aSDan Murphy 	value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
308*87461f7aSDan Murphy 
309*87461f7aSDan Murphy 	phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG, value |
310*87461f7aSDan Murphy 		      DP83822_WOL_CLR_INDICATION);
311*87461f7aSDan Murphy 
312*87461f7aSDan Murphy 	return 0;
313*87461f7aSDan Murphy }
314*87461f7aSDan Murphy 
315*87461f7aSDan Murphy static struct phy_driver dp83822_driver[] = {
316*87461f7aSDan Murphy 	{
317*87461f7aSDan Murphy 		.phy_id = DP83822_PHY_ID,
318*87461f7aSDan Murphy 		.phy_id_mask = 0xfffffff0,
319*87461f7aSDan Murphy 		.name = "TI DP83822",
320*87461f7aSDan Murphy 		.features = PHY_BASIC_FEATURES,
321*87461f7aSDan Murphy 		.flags = PHY_HAS_INTERRUPT,
322*87461f7aSDan Murphy 		.config_init = dp83822_config_init,
323*87461f7aSDan Murphy 		.soft_reset = dp83822_phy_reset,
324*87461f7aSDan Murphy 		.get_wol = dp83822_get_wol,
325*87461f7aSDan Murphy 		.set_wol = dp83822_set_wol,
326*87461f7aSDan Murphy 		.ack_interrupt = dp83822_ack_interrupt,
327*87461f7aSDan Murphy 		.config_intr = dp83822_config_intr,
328*87461f7aSDan Murphy 		.config_aneg = genphy_config_aneg,
329*87461f7aSDan Murphy 		.read_status = genphy_read_status,
330*87461f7aSDan Murphy 		.suspend = dp83822_suspend,
331*87461f7aSDan Murphy 		.resume = dp83822_resume,
332*87461f7aSDan Murphy 	 },
333*87461f7aSDan Murphy };
334*87461f7aSDan Murphy module_phy_driver(dp83822_driver);
335*87461f7aSDan Murphy 
336*87461f7aSDan Murphy static struct mdio_device_id __maybe_unused dp83822_tbl[] = {
337*87461f7aSDan Murphy 	{ DP83822_PHY_ID, 0xfffffff0 },
338*87461f7aSDan Murphy 	{ },
339*87461f7aSDan Murphy };
340*87461f7aSDan Murphy MODULE_DEVICE_TABLE(mdio, dp83822_tbl);
341*87461f7aSDan Murphy 
342*87461f7aSDan Murphy MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver");
343*87461f7aSDan Murphy MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
344*87461f7aSDan Murphy MODULE_LICENSE("GPL");
345