diff options
author | David S. Miller <davem@davemloft.net> | 2014-11-12 13:55:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-12 13:55:41 -0500 |
commit | 8d326d818a2a8fc80c7df85dd88cb214804d1499 (patch) | |
tree | 0e59c69d42c2855ae5f63966596b7c22faba897a | |
parent | 59af81a14477d88a7a808fda2e2af3225a7d3f02 (diff) | |
parent | 7b52314cc44569f56aa07abdbe43e6ccfcef9478 (diff) |
Merge branch 'micrel-next'
Johan Hovold says:
====================
net: phy: micrel: refactoring and KSZ8081/KSZ8091 features
This series cleans up and refactors parts of the micrel PHY driver, and
adds support for broadcast-address-disable and led-mode configuration
for KSZ8081 and KSZ8091 PHYs.
Specifically, this enables dual KSZ8081 setups (which are limited to
using address 0 and 3).
A follow up series will add device-type abstraction which will allow for
further refactoring and shared initialisation code.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | Documentation/devicetree/bindings/net/micrel.txt | 2 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/net/phy.txt | 3 | ||||
-rw-r--r-- | drivers/net/phy/micrel.c | 125 |
3 files changed, 93 insertions, 37 deletions
diff --git a/Documentation/devicetree/bindings/net/micrel.txt b/Documentation/devicetree/bindings/net/micrel.txt index e1d99b95c4ec..30062fae5623 100644 --- a/Documentation/devicetree/bindings/net/micrel.txt +++ b/Documentation/devicetree/bindings/net/micrel.txt | |||
@@ -14,6 +14,8 @@ Optional properties: | |||
14 | KSZ8021: register 0x1f, bits 5..4 | 14 | KSZ8021: register 0x1f, bits 5..4 |
15 | KSZ8031: register 0x1f, bits 5..4 | 15 | KSZ8031: register 0x1f, bits 5..4 |
16 | KSZ8051: register 0x1f, bits 5..4 | 16 | KSZ8051: register 0x1f, bits 5..4 |
17 | KSZ8081: register 0x1f, bits 5..4 | ||
18 | KSZ8091: register 0x1f, bits 5..4 | ||
17 | 19 | ||
18 | See the respective PHY datasheet for the mode values. | 20 | See the respective PHY datasheet for the mode values. |
19 | 21 | ||
diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt index 5b8c58903077..40831fbaff72 100644 --- a/Documentation/devicetree/bindings/net/phy.txt +++ b/Documentation/devicetree/bindings/net/phy.txt | |||
@@ -19,7 +19,6 @@ Optional Properties: | |||
19 | specifications. If neither of these are specified, the default is to | 19 | specifications. If neither of these are specified, the default is to |
20 | assume clause 22. The compatible list may also contain other | 20 | assume clause 22. The compatible list may also contain other |
21 | elements. | 21 | elements. |
22 | - max-speed: Maximum PHY supported speed (10, 100, 1000...) | ||
23 | 22 | ||
24 | If the phy's identifier is known then the list may contain an entry | 23 | If the phy's identifier is known then the list may contain an entry |
25 | of the form: "ethernet-phy-idAAAA.BBBB" where | 24 | of the form: "ethernet-phy-idAAAA.BBBB" where |
@@ -29,6 +28,8 @@ Optional Properties: | |||
29 | 4 hex digits. This is the chip vendor OUI bits 19:24, | 28 | 4 hex digits. This is the chip vendor OUI bits 19:24, |
30 | followed by 10 bits of a vendor specific ID. | 29 | followed by 10 bits of a vendor specific ID. |
31 | 30 | ||
31 | - max-speed: Maximum PHY supported speed (10, 100, 1000...) | ||
32 | |||
32 | Example: | 33 | Example: |
33 | 34 | ||
34 | ethernet-phy@0 { | 35 | ethernet-phy@0 { |
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index bcc6c0ea75fa..30e894d6ffbd 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c | |||
@@ -30,30 +30,34 @@ | |||
30 | 30 | ||
31 | /* Operation Mode Strap Override */ | 31 | /* Operation Mode Strap Override */ |
32 | #define MII_KSZPHY_OMSO 0x16 | 32 | #define MII_KSZPHY_OMSO 0x16 |
33 | #define KSZPHY_OMSO_B_CAST_OFF (1 << 9) | 33 | #define KSZPHY_OMSO_B_CAST_OFF BIT(9) |
34 | #define KSZPHY_OMSO_RMII_OVERRIDE (1 << 1) | 34 | #define KSZPHY_OMSO_RMII_OVERRIDE BIT(1) |
35 | #define KSZPHY_OMSO_MII_OVERRIDE (1 << 0) | 35 | #define KSZPHY_OMSO_MII_OVERRIDE BIT(0) |
36 | 36 | ||
37 | /* general Interrupt control/status reg in vendor specific block. */ | 37 | /* general Interrupt control/status reg in vendor specific block. */ |
38 | #define MII_KSZPHY_INTCS 0x1B | 38 | #define MII_KSZPHY_INTCS 0x1B |
39 | #define KSZPHY_INTCS_JABBER (1 << 15) | 39 | #define KSZPHY_INTCS_JABBER BIT(15) |
40 | #define KSZPHY_INTCS_RECEIVE_ERR (1 << 14) | 40 | #define KSZPHY_INTCS_RECEIVE_ERR BIT(14) |
41 | #define KSZPHY_INTCS_PAGE_RECEIVE (1 << 13) | 41 | #define KSZPHY_INTCS_PAGE_RECEIVE BIT(13) |
42 | #define KSZPHY_INTCS_PARELLEL (1 << 12) | 42 | #define KSZPHY_INTCS_PARELLEL BIT(12) |
43 | #define KSZPHY_INTCS_LINK_PARTNER_ACK (1 << 11) | 43 | #define KSZPHY_INTCS_LINK_PARTNER_ACK BIT(11) |
44 | #define KSZPHY_INTCS_LINK_DOWN (1 << 10) | 44 | #define KSZPHY_INTCS_LINK_DOWN BIT(10) |
45 | #define KSZPHY_INTCS_REMOTE_FAULT (1 << 9) | 45 | #define KSZPHY_INTCS_REMOTE_FAULT BIT(9) |
46 | #define KSZPHY_INTCS_LINK_UP (1 << 8) | 46 | #define KSZPHY_INTCS_LINK_UP BIT(8) |
47 | #define KSZPHY_INTCS_ALL (KSZPHY_INTCS_LINK_UP |\ | 47 | #define KSZPHY_INTCS_ALL (KSZPHY_INTCS_LINK_UP |\ |
48 | KSZPHY_INTCS_LINK_DOWN) | 48 | KSZPHY_INTCS_LINK_DOWN) |
49 | 49 | ||
50 | /* general PHY control reg in vendor specific block. */ | 50 | /* PHY Control 1 */ |
51 | #define MII_KSZPHY_CTRL 0x1F | 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 | ||
52 | /* bitmap of PHY register to set interrupt mode */ | 56 | /* bitmap of PHY register to set interrupt mode */ |
53 | #define KSZPHY_CTRL_INT_ACTIVE_HIGH (1 << 9) | 57 | #define KSZPHY_CTRL_INT_ACTIVE_HIGH BIT(9) |
54 | #define KSZ9021_CTRL_INT_ACTIVE_HIGH (1 << 14) | 58 | #define KSZ9021_CTRL_INT_ACTIVE_HIGH BIT(14) |
55 | #define KS8737_CTRL_INT_ACTIVE_HIGH (1 << 14) | 59 | #define KS8737_CTRL_INT_ACTIVE_HIGH BIT(14) |
56 | #define KSZ8051_RMII_50MHZ_CLK (1 << 7) | 60 | #define KSZ8051_RMII_50MHZ_CLK BIT(7) |
57 | 61 | ||
58 | /* Write/read to/from extended registers */ | 62 | /* Write/read to/from extended registers */ |
59 | #define MII_KSZPHY_EXTREG 0x0b | 63 | #define MII_KSZPHY_EXTREG 0x0b |
@@ -122,6 +126,8 @@ static int kszphy_config_intr(struct phy_device *phydev) | |||
122 | 126 | ||
123 | /* set the interrupt pin active low */ | 127 | /* set the interrupt pin active low */ |
124 | temp = phy_read(phydev, MII_KSZPHY_CTRL); | 128 | temp = phy_read(phydev, MII_KSZPHY_CTRL); |
129 | if (temp < 0) | ||
130 | return temp; | ||
125 | temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH; | 131 | temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH; |
126 | phy_write(phydev, MII_KSZPHY_CTRL, temp); | 132 | phy_write(phydev, MII_KSZPHY_CTRL, temp); |
127 | rc = kszphy_set_interrupt(phydev); | 133 | rc = kszphy_set_interrupt(phydev); |
@@ -134,6 +140,8 @@ static int ksz9021_config_intr(struct phy_device *phydev) | |||
134 | 140 | ||
135 | /* set the interrupt pin active low */ | 141 | /* set the interrupt pin active low */ |
136 | temp = phy_read(phydev, MII_KSZPHY_CTRL); | 142 | temp = phy_read(phydev, MII_KSZPHY_CTRL); |
143 | if (temp < 0) | ||
144 | return temp; | ||
137 | temp &= ~KSZ9021_CTRL_INT_ACTIVE_HIGH; | 145 | temp &= ~KSZ9021_CTRL_INT_ACTIVE_HIGH; |
138 | phy_write(phydev, MII_KSZPHY_CTRL, temp); | 146 | phy_write(phydev, MII_KSZPHY_CTRL, temp); |
139 | rc = kszphy_set_interrupt(phydev); | 147 | rc = kszphy_set_interrupt(phydev); |
@@ -146,19 +154,20 @@ static int ks8737_config_intr(struct phy_device *phydev) | |||
146 | 154 | ||
147 | /* set the interrupt pin active low */ | 155 | /* set the interrupt pin active low */ |
148 | temp = phy_read(phydev, MII_KSZPHY_CTRL); | 156 | temp = phy_read(phydev, MII_KSZPHY_CTRL); |
157 | if (temp < 0) | ||
158 | return temp; | ||
149 | temp &= ~KS8737_CTRL_INT_ACTIVE_HIGH; | 159 | temp &= ~KS8737_CTRL_INT_ACTIVE_HIGH; |
150 | phy_write(phydev, MII_KSZPHY_CTRL, temp); | 160 | phy_write(phydev, MII_KSZPHY_CTRL, temp); |
151 | rc = kszphy_set_interrupt(phydev); | 161 | rc = kszphy_set_interrupt(phydev); |
152 | return rc < 0 ? rc : 0; | 162 | return rc < 0 ? rc : 0; |
153 | } | 163 | } |
154 | 164 | ||
155 | static int kszphy_setup_led(struct phy_device *phydev, | 165 | static int kszphy_setup_led(struct phy_device *phydev, u32 reg) |
156 | unsigned int reg, unsigned int shift) | ||
157 | { | 166 | { |
158 | 167 | ||
159 | struct device *dev = &phydev->dev; | 168 | struct device *dev = &phydev->dev; |
160 | struct device_node *of_node = dev->of_node; | 169 | struct device_node *of_node = dev->of_node; |
161 | int rc, temp; | 170 | int rc, temp, shift; |
162 | u32 val; | 171 | u32 val; |
163 | 172 | ||
164 | if (!of_node && dev->parent->of_node) | 173 | if (!of_node && dev->parent->of_node) |
@@ -167,15 +176,55 @@ static int kszphy_setup_led(struct phy_device *phydev, | |||
167 | if (of_property_read_u32(of_node, "micrel,led-mode", &val)) | 176 | if (of_property_read_u32(of_node, "micrel,led-mode", &val)) |
168 | return 0; | 177 | return 0; |
169 | 178 | ||
179 | if (val > 3) { | ||
180 | dev_err(&phydev->dev, "invalid led mode: 0x%02x\n", val); | ||
181 | return -EINVAL; | ||
182 | } | ||
183 | |||
184 | switch (reg) { | ||
185 | case MII_KSZPHY_CTRL_1: | ||
186 | shift = 14; | ||
187 | break; | ||
188 | case MII_KSZPHY_CTRL_2: | ||
189 | shift = 4; | ||
190 | break; | ||
191 | default: | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | |||
170 | temp = phy_read(phydev, reg); | 195 | temp = phy_read(phydev, reg); |
171 | if (temp < 0) | 196 | if (temp < 0) { |
172 | return temp; | 197 | rc = temp; |
198 | goto out; | ||
199 | } | ||
173 | 200 | ||
174 | temp &= ~(3 << shift); | 201 | temp &= ~(3 << shift); |
175 | temp |= val << shift; | 202 | temp |= val << shift; |
176 | rc = phy_write(phydev, reg, temp); | 203 | rc = phy_write(phydev, reg, temp); |
204 | out: | ||
205 | if (rc < 0) | ||
206 | dev_err(&phydev->dev, "failed to set led mode\n"); | ||
177 | 207 | ||
178 | return rc < 0 ? rc : 0; | 208 | return rc; |
209 | } | ||
210 | |||
211 | /* Disable PHY address 0 as the broadcast address, so that it can be used as a | ||
212 | * unique (non-broadcast) address on a shared bus. | ||
213 | */ | ||
214 | static int kszphy_broadcast_disable(struct phy_device *phydev) | ||
215 | { | ||
216 | int ret; | ||
217 | |||
218 | ret = phy_read(phydev, MII_KSZPHY_OMSO); | ||
219 | if (ret < 0) | ||
220 | goto out; | ||
221 | |||
222 | ret = phy_write(phydev, MII_KSZPHY_OMSO, ret | KSZPHY_OMSO_B_CAST_OFF); | ||
223 | out: | ||
224 | if (ret) | ||
225 | dev_err(&phydev->dev, "failed to disable broadcast address\n"); | ||
226 | |||
227 | return ret; | ||
179 | } | 228 | } |
180 | 229 | ||
181 | static int kszphy_config_init(struct phy_device *phydev) | 230 | static int kszphy_config_init(struct phy_device *phydev) |
@@ -185,23 +234,21 @@ static int kszphy_config_init(struct phy_device *phydev) | |||
185 | 234 | ||
186 | static int kszphy_config_init_led8041(struct phy_device *phydev) | 235 | static int kszphy_config_init_led8041(struct phy_device *phydev) |
187 | { | 236 | { |
188 | /* single led control, register 0x1e bits 15..14 */ | 237 | return kszphy_setup_led(phydev, MII_KSZPHY_CTRL_1); |
189 | return kszphy_setup_led(phydev, 0x1e, 14); | ||
190 | } | 238 | } |
191 | 239 | ||
192 | static int ksz8021_config_init(struct phy_device *phydev) | 240 | static int ksz8021_config_init(struct phy_device *phydev) |
193 | { | 241 | { |
194 | const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE; | ||
195 | int rc; | 242 | int rc; |
196 | 243 | ||
197 | rc = kszphy_setup_led(phydev, 0x1f, 4); | 244 | kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2); |
198 | if (rc) | ||
199 | dev_err(&phydev->dev, "failed to set led mode\n"); | ||
200 | 245 | ||
201 | rc = ksz_config_flags(phydev); | 246 | rc = ksz_config_flags(phydev); |
202 | if (rc < 0) | 247 | if (rc < 0) |
203 | return rc; | 248 | return rc; |
204 | rc = phy_write(phydev, MII_KSZPHY_OMSO, val); | 249 | |
250 | rc = kszphy_broadcast_disable(phydev); | ||
251 | |||
205 | return rc < 0 ? rc : 0; | 252 | return rc < 0 ? rc : 0; |
206 | } | 253 | } |
207 | 254 | ||
@@ -209,14 +256,20 @@ static int ks8051_config_init(struct phy_device *phydev) | |||
209 | { | 256 | { |
210 | int rc; | 257 | int rc; |
211 | 258 | ||
212 | rc = kszphy_setup_led(phydev, 0x1f, 4); | 259 | kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2); |
213 | if (rc) | ||
214 | dev_err(&phydev->dev, "failed to set led mode\n"); | ||
215 | 260 | ||
216 | rc = ksz_config_flags(phydev); | 261 | rc = ksz_config_flags(phydev); |
217 | return rc < 0 ? rc : 0; | 262 | return rc < 0 ? rc : 0; |
218 | } | 263 | } |
219 | 264 | ||
265 | static int ksz8081_config_init(struct phy_device *phydev) | ||
266 | { | ||
267 | kszphy_broadcast_disable(phydev); | ||
268 | kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
220 | static int ksz9021_load_values_from_of(struct phy_device *phydev, | 273 | static int ksz9021_load_values_from_of(struct phy_device *phydev, |
221 | struct device_node *of_node, u16 reg, | 274 | struct device_node *of_node, u16 reg, |
222 | char *field1, char *field2, | 275 | char *field1, char *field2, |
@@ -394,8 +447,8 @@ static int ksz9031_config_init(struct phy_device *phydev) | |||
394 | } | 447 | } |
395 | 448 | ||
396 | #define KSZ8873MLL_GLOBAL_CONTROL_4 0x06 | 449 | #define KSZ8873MLL_GLOBAL_CONTROL_4 0x06 |
397 | #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX (1 << 6) | 450 | #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX BIT(6) |
398 | #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED (1 << 4) | 451 | #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED BIT(4) |
399 | static int ksz8873mll_read_status(struct phy_device *phydev) | 452 | static int ksz8873mll_read_status(struct phy_device *phydev) |
400 | { | 453 | { |
401 | int regval; | 454 | int regval; |
@@ -579,7 +632,7 @@ static struct phy_driver ksphy_driver[] = { | |||
579 | .phy_id_mask = 0x00fffff0, | 632 | .phy_id_mask = 0x00fffff0, |
580 | .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), | 633 | .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), |
581 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, | 634 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, |
582 | .config_init = kszphy_config_init, | 635 | .config_init = ksz8081_config_init, |
583 | .config_aneg = genphy_config_aneg, | 636 | .config_aneg = genphy_config_aneg, |
584 | .read_status = genphy_read_status, | 637 | .read_status = genphy_read_status, |
585 | .ack_interrupt = kszphy_ack_interrupt, | 638 | .ack_interrupt = kszphy_ack_interrupt, |