xref: /openbmc/linux/drivers/net/phy/micrel.c (revision c6f9575cc86250422c84972219e2a1bd7ec7e2ae)
1 /*
2  * drivers/net/phy/micrel.c
3  *
4  * Driver for Micrel PHYs
5  *
6  * Author: David J. Choi
7  *
8  * Copyright (c) 2010-2013 Micrel, Inc.
9  *
10  * This program is free software; you can redistribute  it and/or modify it
11  * under  the terms of  the GNU General  Public License as published by the
12  * Free Software Foundation;  either version 2 of the  License, or (at your
13  * option) any later version.
14  *
15  * Support : Micrel Phys:
16  *		Giga phys: ksz9021, ksz9031
17  *		100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041
18  *			   ksz8021, ksz8031, ksz8051,
19  *			   ksz8081, ksz8091,
20  *			   ksz8061,
21  *		Switch : ksz8873, ksz886x
22  */
23 
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/phy.h>
27 #include <linux/micrel_phy.h>
28 #include <linux/of.h>
29 #include <linux/clk.h>
30 
31 /* Operation Mode Strap Override */
32 #define MII_KSZPHY_OMSO				0x16
33 #define KSZPHY_OMSO_B_CAST_OFF			BIT(9)
34 #define KSZPHY_OMSO_RMII_OVERRIDE		BIT(1)
35 #define KSZPHY_OMSO_MII_OVERRIDE		BIT(0)
36 
37 /* general Interrupt control/status reg in vendor specific block. */
38 #define MII_KSZPHY_INTCS			0x1B
39 #define	KSZPHY_INTCS_JABBER			BIT(15)
40 #define	KSZPHY_INTCS_RECEIVE_ERR		BIT(14)
41 #define	KSZPHY_INTCS_PAGE_RECEIVE		BIT(13)
42 #define	KSZPHY_INTCS_PARELLEL			BIT(12)
43 #define	KSZPHY_INTCS_LINK_PARTNER_ACK		BIT(11)
44 #define	KSZPHY_INTCS_LINK_DOWN			BIT(10)
45 #define	KSZPHY_INTCS_REMOTE_FAULT		BIT(9)
46 #define	KSZPHY_INTCS_LINK_UP			BIT(8)
47 #define	KSZPHY_INTCS_ALL			(KSZPHY_INTCS_LINK_UP |\
48 						KSZPHY_INTCS_LINK_DOWN)
49 
50 /* PHY Control 1 */
51 #define	MII_KSZPHY_CTRL_1			0x1e
52 
53 /* PHY Control 2 / PHY Control (if no PHY Control 1) */
54 #define	MII_KSZPHY_CTRL_2			0x1f
55 #define	MII_KSZPHY_CTRL				MII_KSZPHY_CTRL_2
56 /* bitmap of PHY register to set interrupt mode */
57 #define KSZPHY_CTRL_INT_ACTIVE_HIGH		BIT(9)
58 #define KSZPHY_RMII_REF_CLK_SEL			BIT(7)
59 
60 /* Write/read to/from extended registers */
61 #define MII_KSZPHY_EXTREG                       0x0b
62 #define KSZPHY_EXTREG_WRITE                     0x8000
63 
64 #define MII_KSZPHY_EXTREG_WRITE                 0x0c
65 #define MII_KSZPHY_EXTREG_READ                  0x0d
66 
67 /* Extended registers */
68 #define MII_KSZPHY_CLK_CONTROL_PAD_SKEW         0x104
69 #define MII_KSZPHY_RX_DATA_PAD_SKEW             0x105
70 #define MII_KSZPHY_TX_DATA_PAD_SKEW             0x106
71 
72 #define PS_TO_REG				200
73 
74 struct kszphy_type {
75 	u32 led_mode_reg;
76 	u16 interrupt_level_mask;
77 	bool has_broadcast_disable;
78 	bool has_rmii_ref_clk_sel;
79 };
80 
81 struct kszphy_priv {
82 	const struct kszphy_type *type;
83 	int led_mode;
84 	bool rmii_ref_clk_sel;
85 	bool rmii_ref_clk_sel_val;
86 };
87 
88 static const struct kszphy_type ksz8021_type = {
89 	.led_mode_reg		= MII_KSZPHY_CTRL_2,
90 	.has_rmii_ref_clk_sel	= true,
91 };
92 
93 static const struct kszphy_type ksz8041_type = {
94 	.led_mode_reg		= MII_KSZPHY_CTRL_1,
95 };
96 
97 static const struct kszphy_type ksz8051_type = {
98 	.led_mode_reg		= MII_KSZPHY_CTRL_2,
99 };
100 
101 static const struct kszphy_type ksz8081_type = {
102 	.led_mode_reg		= MII_KSZPHY_CTRL_2,
103 	.has_broadcast_disable	= true,
104 	.has_rmii_ref_clk_sel	= true,
105 };
106 
107 static const struct kszphy_type ks8737_type = {
108 	.interrupt_level_mask	= BIT(14),
109 };
110 
111 static const struct kszphy_type ksz9021_type = {
112 	.interrupt_level_mask	= BIT(14),
113 };
114 
115 static int kszphy_extended_write(struct phy_device *phydev,
116 				u32 regnum, u16 val)
117 {
118 	phy_write(phydev, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | regnum);
119 	return phy_write(phydev, MII_KSZPHY_EXTREG_WRITE, val);
120 }
121 
122 static int kszphy_extended_read(struct phy_device *phydev,
123 				u32 regnum)
124 {
125 	phy_write(phydev, MII_KSZPHY_EXTREG, regnum);
126 	return phy_read(phydev, MII_KSZPHY_EXTREG_READ);
127 }
128 
129 static int kszphy_ack_interrupt(struct phy_device *phydev)
130 {
131 	/* bit[7..0] int status, which is a read and clear register. */
132 	int rc;
133 
134 	rc = phy_read(phydev, MII_KSZPHY_INTCS);
135 
136 	return (rc < 0) ? rc : 0;
137 }
138 
139 static int kszphy_config_intr(struct phy_device *phydev)
140 {
141 	const struct kszphy_type *type = phydev->drv->driver_data;
142 	int temp;
143 	u16 mask;
144 
145 	if (type && type->interrupt_level_mask)
146 		mask = type->interrupt_level_mask;
147 	else
148 		mask = KSZPHY_CTRL_INT_ACTIVE_HIGH;
149 
150 	/* set the interrupt pin active low */
151 	temp = phy_read(phydev, MII_KSZPHY_CTRL);
152 	if (temp < 0)
153 		return temp;
154 	temp &= ~mask;
155 	phy_write(phydev, MII_KSZPHY_CTRL, temp);
156 
157 	/* enable / disable interrupts */
158 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
159 		temp = KSZPHY_INTCS_ALL;
160 	else
161 		temp = 0;
162 
163 	return phy_write(phydev, MII_KSZPHY_INTCS, temp);
164 }
165 
166 static int kszphy_rmii_clk_sel(struct phy_device *phydev, bool val)
167 {
168 	int ctrl;
169 
170 	ctrl = phy_read(phydev, MII_KSZPHY_CTRL);
171 	if (ctrl < 0)
172 		return ctrl;
173 
174 	if (val)
175 		ctrl |= KSZPHY_RMII_REF_CLK_SEL;
176 	else
177 		ctrl &= ~KSZPHY_RMII_REF_CLK_SEL;
178 
179 	return phy_write(phydev, MII_KSZPHY_CTRL, ctrl);
180 }
181 
182 static int kszphy_setup_led(struct phy_device *phydev, u32 reg, int val)
183 {
184 	int rc, temp, shift;
185 
186 	switch (reg) {
187 	case MII_KSZPHY_CTRL_1:
188 		shift = 14;
189 		break;
190 	case MII_KSZPHY_CTRL_2:
191 		shift = 4;
192 		break;
193 	default:
194 		return -EINVAL;
195 	}
196 
197 	temp = phy_read(phydev, reg);
198 	if (temp < 0) {
199 		rc = temp;
200 		goto out;
201 	}
202 
203 	temp &= ~(3 << shift);
204 	temp |= val << shift;
205 	rc = phy_write(phydev, reg, temp);
206 out:
207 	if (rc < 0)
208 		dev_err(&phydev->dev, "failed to set led mode\n");
209 
210 	return rc;
211 }
212 
213 /* Disable PHY address 0 as the broadcast address, so that it can be used as a
214  * unique (non-broadcast) address on a shared bus.
215  */
216 static int kszphy_broadcast_disable(struct phy_device *phydev)
217 {
218 	int ret;
219 
220 	ret = phy_read(phydev, MII_KSZPHY_OMSO);
221 	if (ret < 0)
222 		goto out;
223 
224 	ret = phy_write(phydev, MII_KSZPHY_OMSO, ret | KSZPHY_OMSO_B_CAST_OFF);
225 out:
226 	if (ret)
227 		dev_err(&phydev->dev, "failed to disable broadcast address\n");
228 
229 	return ret;
230 }
231 
232 static int kszphy_config_init(struct phy_device *phydev)
233 {
234 	struct kszphy_priv *priv = phydev->priv;
235 	const struct kszphy_type *type;
236 	int ret;
237 
238 	if (!priv)
239 		return 0;
240 
241 	type = priv->type;
242 
243 	if (type->has_broadcast_disable)
244 		kszphy_broadcast_disable(phydev);
245 
246 	if (priv->rmii_ref_clk_sel) {
247 		ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val);
248 		if (ret) {
249 			dev_err(&phydev->dev, "failed to set rmii reference clock\n");
250 			return ret;
251 		}
252 	}
253 
254 	if (priv->led_mode >= 0)
255 		kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode);
256 
257 	return 0;
258 }
259 
260 static int ksz8021_config_init(struct phy_device *phydev)
261 {
262 	int rc;
263 
264 	rc = kszphy_config_init(phydev);
265 	if (rc)
266 		return rc;
267 
268 	rc = kszphy_broadcast_disable(phydev);
269 
270 	return rc < 0 ? rc : 0;
271 }
272 
273 static int ksz9021_load_values_from_of(struct phy_device *phydev,
274 				       struct device_node *of_node, u16 reg,
275 				       char *field1, char *field2,
276 				       char *field3, char *field4)
277 {
278 	int val1 = -1;
279 	int val2 = -2;
280 	int val3 = -3;
281 	int val4 = -4;
282 	int newval;
283 	int matches = 0;
284 
285 	if (!of_property_read_u32(of_node, field1, &val1))
286 		matches++;
287 
288 	if (!of_property_read_u32(of_node, field2, &val2))
289 		matches++;
290 
291 	if (!of_property_read_u32(of_node, field3, &val3))
292 		matches++;
293 
294 	if (!of_property_read_u32(of_node, field4, &val4))
295 		matches++;
296 
297 	if (!matches)
298 		return 0;
299 
300 	if (matches < 4)
301 		newval = kszphy_extended_read(phydev, reg);
302 	else
303 		newval = 0;
304 
305 	if (val1 != -1)
306 		newval = ((newval & 0xfff0) | ((val1 / PS_TO_REG) & 0xf) << 0);
307 
308 	if (val2 != -2)
309 		newval = ((newval & 0xff0f) | ((val2 / PS_TO_REG) & 0xf) << 4);
310 
311 	if (val3 != -3)
312 		newval = ((newval & 0xf0ff) | ((val3 / PS_TO_REG) & 0xf) << 8);
313 
314 	if (val4 != -4)
315 		newval = ((newval & 0x0fff) | ((val4 / PS_TO_REG) & 0xf) << 12);
316 
317 	return kszphy_extended_write(phydev, reg, newval);
318 }
319 
320 static int ksz9021_config_init(struct phy_device *phydev)
321 {
322 	struct device *dev = &phydev->dev;
323 	struct device_node *of_node = dev->of_node;
324 
325 	if (!of_node && dev->parent->of_node)
326 		of_node = dev->parent->of_node;
327 
328 	if (of_node) {
329 		ksz9021_load_values_from_of(phydev, of_node,
330 				    MII_KSZPHY_CLK_CONTROL_PAD_SKEW,
331 				    "txen-skew-ps", "txc-skew-ps",
332 				    "rxdv-skew-ps", "rxc-skew-ps");
333 		ksz9021_load_values_from_of(phydev, of_node,
334 				    MII_KSZPHY_RX_DATA_PAD_SKEW,
335 				    "rxd0-skew-ps", "rxd1-skew-ps",
336 				    "rxd2-skew-ps", "rxd3-skew-ps");
337 		ksz9021_load_values_from_of(phydev, of_node,
338 				    MII_KSZPHY_TX_DATA_PAD_SKEW,
339 				    "txd0-skew-ps", "txd1-skew-ps",
340 				    "txd2-skew-ps", "txd3-skew-ps");
341 	}
342 	return 0;
343 }
344 
345 #define MII_KSZ9031RN_MMD_CTRL_REG	0x0d
346 #define MII_KSZ9031RN_MMD_REGDATA_REG	0x0e
347 #define OP_DATA				1
348 #define KSZ9031_PS_TO_REG		60
349 
350 /* Extended registers */
351 #define MII_KSZ9031RN_CONTROL_PAD_SKEW	4
352 #define MII_KSZ9031RN_RX_DATA_PAD_SKEW	5
353 #define MII_KSZ9031RN_TX_DATA_PAD_SKEW	6
354 #define MII_KSZ9031RN_CLK_PAD_SKEW	8
355 
356 static int ksz9031_extended_write(struct phy_device *phydev,
357 				  u8 mode, u32 dev_addr, u32 regnum, u16 val)
358 {
359 	phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr);
360 	phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum);
361 	phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr);
362 	return phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, val);
363 }
364 
365 static int ksz9031_extended_read(struct phy_device *phydev,
366 				 u8 mode, u32 dev_addr, u32 regnum)
367 {
368 	phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr);
369 	phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum);
370 	phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr);
371 	return phy_read(phydev, MII_KSZ9031RN_MMD_REGDATA_REG);
372 }
373 
374 static int ksz9031_of_load_skew_values(struct phy_device *phydev,
375 				       struct device_node *of_node,
376 				       u16 reg, size_t field_sz,
377 				       char *field[], u8 numfields)
378 {
379 	int val[4] = {-1, -2, -3, -4};
380 	int matches = 0;
381 	u16 mask;
382 	u16 maxval;
383 	u16 newval;
384 	int i;
385 
386 	for (i = 0; i < numfields; i++)
387 		if (!of_property_read_u32(of_node, field[i], val + i))
388 			matches++;
389 
390 	if (!matches)
391 		return 0;
392 
393 	if (matches < numfields)
394 		newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg);
395 	else
396 		newval = 0;
397 
398 	maxval = (field_sz == 4) ? 0xf : 0x1f;
399 	for (i = 0; i < numfields; i++)
400 		if (val[i] != -(i + 1)) {
401 			mask = 0xffff;
402 			mask ^= maxval << (field_sz * i);
403 			newval = (newval & mask) |
404 				(((val[i] / KSZ9031_PS_TO_REG) & maxval)
405 					<< (field_sz * i));
406 		}
407 
408 	return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval);
409 }
410 
411 static int ksz9031_config_init(struct phy_device *phydev)
412 {
413 	struct device *dev = &phydev->dev;
414 	struct device_node *of_node = dev->of_node;
415 	char *clk_skews[2] = {"rxc-skew-ps", "txc-skew-ps"};
416 	char *rx_data_skews[4] = {
417 		"rxd0-skew-ps", "rxd1-skew-ps",
418 		"rxd2-skew-ps", "rxd3-skew-ps"
419 	};
420 	char *tx_data_skews[4] = {
421 		"txd0-skew-ps", "txd1-skew-ps",
422 		"txd2-skew-ps", "txd3-skew-ps"
423 	};
424 	char *control_skews[2] = {"txen-skew-ps", "rxdv-skew-ps"};
425 
426 	if (!of_node && dev->parent->of_node)
427 		of_node = dev->parent->of_node;
428 
429 	if (of_node) {
430 		ksz9031_of_load_skew_values(phydev, of_node,
431 				MII_KSZ9031RN_CLK_PAD_SKEW, 5,
432 				clk_skews, 2);
433 
434 		ksz9031_of_load_skew_values(phydev, of_node,
435 				MII_KSZ9031RN_CONTROL_PAD_SKEW, 4,
436 				control_skews, 2);
437 
438 		ksz9031_of_load_skew_values(phydev, of_node,
439 				MII_KSZ9031RN_RX_DATA_PAD_SKEW, 4,
440 				rx_data_skews, 4);
441 
442 		ksz9031_of_load_skew_values(phydev, of_node,
443 				MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4,
444 				tx_data_skews, 4);
445 	}
446 	return 0;
447 }
448 
449 #define KSZ8873MLL_GLOBAL_CONTROL_4	0x06
450 #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX	BIT(6)
451 #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED	BIT(4)
452 static int ksz8873mll_read_status(struct phy_device *phydev)
453 {
454 	int regval;
455 
456 	/* dummy read */
457 	regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
458 
459 	regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
460 
461 	if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
462 		phydev->duplex = DUPLEX_HALF;
463 	else
464 		phydev->duplex = DUPLEX_FULL;
465 
466 	if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
467 		phydev->speed = SPEED_10;
468 	else
469 		phydev->speed = SPEED_100;
470 
471 	phydev->link = 1;
472 	phydev->pause = phydev->asym_pause = 0;
473 
474 	return 0;
475 }
476 
477 static int ksz8873mll_config_aneg(struct phy_device *phydev)
478 {
479 	return 0;
480 }
481 
482 /* This routine returns -1 as an indication to the caller that the
483  * Micrel ksz9021 10/100/1000 PHY does not support standard IEEE
484  * MMD extended PHY registers.
485  */
486 static int
487 ksz9021_rd_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
488 		      int regnum)
489 {
490 	return -1;
491 }
492 
493 /* This routine does nothing since the Micrel ksz9021 does not support
494  * standard IEEE MMD extended PHY registers.
495  */
496 static void
497 ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
498 		      int regnum, u32 val)
499 {
500 }
501 
502 static int kszphy_probe(struct phy_device *phydev)
503 {
504 	const struct kszphy_type *type = phydev->drv->driver_data;
505 	struct device_node *np = phydev->dev.of_node;
506 	struct kszphy_priv *priv;
507 	struct clk *clk;
508 	int ret;
509 
510 	priv = devm_kzalloc(&phydev->dev, sizeof(*priv), GFP_KERNEL);
511 	if (!priv)
512 		return -ENOMEM;
513 
514 	phydev->priv = priv;
515 
516 	priv->type = type;
517 
518 	if (type->led_mode_reg) {
519 		ret = of_property_read_u32(np, "micrel,led-mode",
520 				&priv->led_mode);
521 		if (ret)
522 			priv->led_mode = -1;
523 
524 		if (priv->led_mode > 3) {
525 			dev_err(&phydev->dev, "invalid led mode: 0x%02x\n",
526 					priv->led_mode);
527 			priv->led_mode = -1;
528 		}
529 	} else {
530 		priv->led_mode = -1;
531 	}
532 
533 	clk = devm_clk_get(&phydev->dev, "rmii-ref");
534 	if (!IS_ERR(clk)) {
535 		unsigned long rate = clk_get_rate(clk);
536 		bool rmii_ref_clk_sel_25_mhz;
537 
538 		priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
539 		rmii_ref_clk_sel_25_mhz = of_property_read_bool(np,
540 				"micrel,rmii-reference-clock-select-25-mhz");
541 
542 		if (rate > 24500000 && rate < 25500000) {
543 			priv->rmii_ref_clk_sel_val = rmii_ref_clk_sel_25_mhz;
544 		} else if (rate > 49500000 && rate < 50500000) {
545 			priv->rmii_ref_clk_sel_val = !rmii_ref_clk_sel_25_mhz;
546 		} else {
547 			dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate);
548 			return -EINVAL;
549 		}
550 	}
551 
552 	/* Support legacy board-file configuration */
553 	if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
554 		priv->rmii_ref_clk_sel = true;
555 		priv->rmii_ref_clk_sel_val = true;
556 	}
557 
558 	return 0;
559 }
560 
561 static struct phy_driver ksphy_driver[] = {
562 {
563 	.phy_id		= PHY_ID_KS8737,
564 	.phy_id_mask	= 0x00fffff0,
565 	.name		= "Micrel KS8737",
566 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
567 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
568 	.driver_data	= &ks8737_type,
569 	.config_init	= kszphy_config_init,
570 	.config_aneg	= genphy_config_aneg,
571 	.read_status	= genphy_read_status,
572 	.ack_interrupt	= kszphy_ack_interrupt,
573 	.config_intr	= kszphy_config_intr,
574 	.suspend	= genphy_suspend,
575 	.resume		= genphy_resume,
576 	.driver		= { .owner = THIS_MODULE,},
577 }, {
578 	.phy_id		= PHY_ID_KSZ8021,
579 	.phy_id_mask	= 0x00ffffff,
580 	.name		= "Micrel KSZ8021 or KSZ8031",
581 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
582 			   SUPPORTED_Asym_Pause),
583 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
584 	.driver_data	= &ksz8021_type,
585 	.probe		= kszphy_probe,
586 	.config_init	= ksz8021_config_init,
587 	.config_aneg	= genphy_config_aneg,
588 	.read_status	= genphy_read_status,
589 	.ack_interrupt	= kszphy_ack_interrupt,
590 	.config_intr	= kszphy_config_intr,
591 	.suspend	= genphy_suspend,
592 	.resume		= genphy_resume,
593 	.driver		= { .owner = THIS_MODULE,},
594 }, {
595 	.phy_id		= PHY_ID_KSZ8031,
596 	.phy_id_mask	= 0x00ffffff,
597 	.name		= "Micrel KSZ8031",
598 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
599 			   SUPPORTED_Asym_Pause),
600 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
601 	.driver_data	= &ksz8021_type,
602 	.probe		= kszphy_probe,
603 	.config_init	= ksz8021_config_init,
604 	.config_aneg	= genphy_config_aneg,
605 	.read_status	= genphy_read_status,
606 	.ack_interrupt	= kszphy_ack_interrupt,
607 	.config_intr	= kszphy_config_intr,
608 	.suspend	= genphy_suspend,
609 	.resume		= genphy_resume,
610 	.driver		= { .owner = THIS_MODULE,},
611 }, {
612 	.phy_id		= PHY_ID_KSZ8041,
613 	.phy_id_mask	= 0x00fffff0,
614 	.name		= "Micrel KSZ8041",
615 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
616 				| SUPPORTED_Asym_Pause),
617 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
618 	.driver_data	= &ksz8041_type,
619 	.probe		= kszphy_probe,
620 	.config_init	= kszphy_config_init,
621 	.config_aneg	= genphy_config_aneg,
622 	.read_status	= genphy_read_status,
623 	.ack_interrupt	= kszphy_ack_interrupt,
624 	.config_intr	= kszphy_config_intr,
625 	.suspend	= genphy_suspend,
626 	.resume		= genphy_resume,
627 	.driver		= { .owner = THIS_MODULE,},
628 }, {
629 	.phy_id		= PHY_ID_KSZ8041RNLI,
630 	.phy_id_mask	= 0x00fffff0,
631 	.name		= "Micrel KSZ8041RNLI",
632 	.features	= PHY_BASIC_FEATURES |
633 			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
634 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
635 	.driver_data	= &ksz8041_type,
636 	.probe		= kszphy_probe,
637 	.config_init	= kszphy_config_init,
638 	.config_aneg	= genphy_config_aneg,
639 	.read_status	= genphy_read_status,
640 	.ack_interrupt	= kszphy_ack_interrupt,
641 	.config_intr	= kszphy_config_intr,
642 	.suspend	= genphy_suspend,
643 	.resume		= genphy_resume,
644 	.driver		= { .owner = THIS_MODULE,},
645 }, {
646 	.phy_id		= PHY_ID_KSZ8051,
647 	.phy_id_mask	= 0x00fffff0,
648 	.name		= "Micrel KSZ8051",
649 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
650 				| SUPPORTED_Asym_Pause),
651 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
652 	.driver_data	= &ksz8051_type,
653 	.probe		= kszphy_probe,
654 	.config_init	= kszphy_config_init,
655 	.config_aneg	= genphy_config_aneg,
656 	.read_status	= genphy_read_status,
657 	.ack_interrupt	= kszphy_ack_interrupt,
658 	.config_intr	= kszphy_config_intr,
659 	.suspend	= genphy_suspend,
660 	.resume		= genphy_resume,
661 	.driver		= { .owner = THIS_MODULE,},
662 }, {
663 	.phy_id		= PHY_ID_KSZ8001,
664 	.name		= "Micrel KSZ8001 or KS8721",
665 	.phy_id_mask	= 0x00ffffff,
666 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
667 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
668 	.driver_data	= &ksz8041_type,
669 	.probe		= kszphy_probe,
670 	.config_init	= kszphy_config_init,
671 	.config_aneg	= genphy_config_aneg,
672 	.read_status	= genphy_read_status,
673 	.ack_interrupt	= kszphy_ack_interrupt,
674 	.config_intr	= kszphy_config_intr,
675 	.suspend	= genphy_suspend,
676 	.resume		= genphy_resume,
677 	.driver		= { .owner = THIS_MODULE,},
678 }, {
679 	.phy_id		= PHY_ID_KSZ8081,
680 	.name		= "Micrel KSZ8081 or KSZ8091",
681 	.phy_id_mask	= 0x00fffff0,
682 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
683 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
684 	.driver_data	= &ksz8081_type,
685 	.probe		= kszphy_probe,
686 	.config_init	= kszphy_config_init,
687 	.config_aneg	= genphy_config_aneg,
688 	.read_status	= genphy_read_status,
689 	.ack_interrupt	= kszphy_ack_interrupt,
690 	.config_intr	= kszphy_config_intr,
691 	.suspend	= genphy_suspend,
692 	.resume		= genphy_resume,
693 	.driver		= { .owner = THIS_MODULE,},
694 }, {
695 	.phy_id		= PHY_ID_KSZ8061,
696 	.name		= "Micrel KSZ8061",
697 	.phy_id_mask	= 0x00fffff0,
698 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
699 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
700 	.config_init	= kszphy_config_init,
701 	.config_aneg	= genphy_config_aneg,
702 	.read_status	= genphy_read_status,
703 	.ack_interrupt	= kszphy_ack_interrupt,
704 	.config_intr	= kszphy_config_intr,
705 	.suspend	= genphy_suspend,
706 	.resume		= genphy_resume,
707 	.driver		= { .owner = THIS_MODULE,},
708 }, {
709 	.phy_id		= PHY_ID_KSZ9021,
710 	.phy_id_mask	= 0x000ffffe,
711 	.name		= "Micrel KSZ9021 Gigabit PHY",
712 	.features	= (PHY_GBIT_FEATURES | SUPPORTED_Pause),
713 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
714 	.driver_data	= &ksz9021_type,
715 	.config_init	= ksz9021_config_init,
716 	.config_aneg	= genphy_config_aneg,
717 	.read_status	= genphy_read_status,
718 	.ack_interrupt	= kszphy_ack_interrupt,
719 	.config_intr	= kszphy_config_intr,
720 	.suspend	= genphy_suspend,
721 	.resume		= genphy_resume,
722 	.read_mmd_indirect = ksz9021_rd_mmd_phyreg,
723 	.write_mmd_indirect = ksz9021_wr_mmd_phyreg,
724 	.driver		= { .owner = THIS_MODULE, },
725 }, {
726 	.phy_id		= PHY_ID_KSZ9031,
727 	.phy_id_mask	= 0x00fffff0,
728 	.name		= "Micrel KSZ9031 Gigabit PHY",
729 	.features	= (PHY_GBIT_FEATURES | SUPPORTED_Pause),
730 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
731 	.driver_data	= &ksz9021_type,
732 	.config_init	= ksz9031_config_init,
733 	.config_aneg	= genphy_config_aneg,
734 	.read_status	= genphy_read_status,
735 	.ack_interrupt	= kszphy_ack_interrupt,
736 	.config_intr	= kszphy_config_intr,
737 	.suspend	= genphy_suspend,
738 	.resume		= genphy_resume,
739 	.driver		= { .owner = THIS_MODULE, },
740 }, {
741 	.phy_id		= PHY_ID_KSZ8873MLL,
742 	.phy_id_mask	= 0x00fffff0,
743 	.name		= "Micrel KSZ8873MLL Switch",
744 	.features	= (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
745 	.flags		= PHY_HAS_MAGICANEG,
746 	.config_init	= kszphy_config_init,
747 	.config_aneg	= ksz8873mll_config_aneg,
748 	.read_status	= ksz8873mll_read_status,
749 	.suspend	= genphy_suspend,
750 	.resume		= genphy_resume,
751 	.driver		= { .owner = THIS_MODULE, },
752 }, {
753 	.phy_id		= PHY_ID_KSZ886X,
754 	.phy_id_mask	= 0x00fffff0,
755 	.name		= "Micrel KSZ886X Switch",
756 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
757 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
758 	.config_init	= kszphy_config_init,
759 	.config_aneg	= genphy_config_aneg,
760 	.read_status	= genphy_read_status,
761 	.suspend	= genphy_suspend,
762 	.resume		= genphy_resume,
763 	.driver		= { .owner = THIS_MODULE, },
764 } };
765 
766 module_phy_driver(ksphy_driver);
767 
768 MODULE_DESCRIPTION("Micrel PHY driver");
769 MODULE_AUTHOR("David J. Choi");
770 MODULE_LICENSE("GPL");
771 
772 static struct mdio_device_id __maybe_unused micrel_tbl[] = {
773 	{ PHY_ID_KSZ9021, 0x000ffffe },
774 	{ PHY_ID_KSZ9031, 0x00fffff0 },
775 	{ PHY_ID_KSZ8001, 0x00ffffff },
776 	{ PHY_ID_KS8737, 0x00fffff0 },
777 	{ PHY_ID_KSZ8021, 0x00ffffff },
778 	{ PHY_ID_KSZ8031, 0x00ffffff },
779 	{ PHY_ID_KSZ8041, 0x00fffff0 },
780 	{ PHY_ID_KSZ8051, 0x00fffff0 },
781 	{ PHY_ID_KSZ8061, 0x00fffff0 },
782 	{ PHY_ID_KSZ8081, 0x00fffff0 },
783 	{ PHY_ID_KSZ8873MLL, 0x00fffff0 },
784 	{ PHY_ID_KSZ886X, 0x00fffff0 },
785 	{ }
786 };
787 
788 MODULE_DEVICE_TABLE(mdio, micrel_tbl);
789