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