]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/ethernet/broadcom/genet/bcmmii.c
net: bcmgenet: remove PHY_BRCM_100MBPS_WAR
[mirror_ubuntu-artful-kernel.git] / drivers / net / ethernet / broadcom / genet / bcmmii.c
CommitLineData
aa09677c
FF
1/*
2 * Broadcom GENET MDIO routines
3 *
4 * Copyright (c) 2014 Broadcom Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
aa09677c
FF
9 */
10
11
12#include <linux/types.h>
13#include <linux/delay.h>
14#include <linux/wait.h>
15#include <linux/mii.h>
16#include <linux/ethtool.h>
17#include <linux/bitops.h>
18#include <linux/netdevice.h>
19#include <linux/platform_device.h>
20#include <linux/phy.h>
21#include <linux/phy_fixed.h>
22#include <linux/brcmphy.h>
23#include <linux/of.h>
24#include <linux/of_net.h>
25#include <linux/of_mdio.h>
26
27#include "bcmgenet.h"
28
29/* read a value from the MII */
30static int bcmgenet_mii_read(struct mii_bus *bus, int phy_id, int location)
31{
32 int ret;
33 struct net_device *dev = bus->priv;
34 struct bcmgenet_priv *priv = netdev_priv(dev);
35 u32 reg;
36
37 bcmgenet_umac_writel(priv, (MDIO_RD | (phy_id << MDIO_PMD_SHIFT) |
c91b7f66 38 (location << MDIO_REG_SHIFT)), UMAC_MDIO_CMD);
aa09677c
FF
39 /* Start MDIO transaction*/
40 reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
41 reg |= MDIO_START_BUSY;
42 bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD);
43 wait_event_timeout(priv->wq,
c91b7f66
FF
44 !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
45 & MDIO_START_BUSY),
46 HZ / 100);
aa09677c
FF
47 ret = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
48
49 if (ret & MDIO_READ_FAIL)
50 return -EIO;
51
52 return ret & 0xffff;
53}
54
55/* write a value to the MII */
56static int bcmgenet_mii_write(struct mii_bus *bus, int phy_id,
c91b7f66 57 int location, u16 val)
aa09677c
FF
58{
59 struct net_device *dev = bus->priv;
60 struct bcmgenet_priv *priv = netdev_priv(dev);
61 u32 reg;
62
63 bcmgenet_umac_writel(priv, (MDIO_WR | (phy_id << MDIO_PMD_SHIFT) |
c91b7f66
FF
64 (location << MDIO_REG_SHIFT) | (0xffff & val)),
65 UMAC_MDIO_CMD);
aa09677c
FF
66 reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
67 reg |= MDIO_START_BUSY;
68 bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD);
69 wait_event_timeout(priv->wq,
c91b7f66
FF
70 !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD) &
71 MDIO_START_BUSY),
72 HZ / 100);
aa09677c
FF
73
74 return 0;
75}
76
77/* setup netdev link state when PHY link status change and
78 * update UMAC and RGMII block when link up
79 */
80static void bcmgenet_mii_setup(struct net_device *dev)
81{
82 struct bcmgenet_priv *priv = netdev_priv(dev);
83 struct phy_device *phydev = priv->phydev;
84 u32 reg, cmd_bits = 0;
85 unsigned int status_changed = 0;
86
87 if (priv->old_link != phydev->link) {
88 status_changed = 1;
89 priv->old_link = phydev->link;
90 }
91
92 if (phydev->link) {
93 /* program UMAC and RGMII block based on established link
94 * speed, pause, and duplex.
95 * the speed set in umac->cmd tell RGMII block which clock
96 * 25MHz(100Mbps)/125MHz(1Gbps) to use for transmit.
97 * receive clock is provided by PHY.
98 */
99 reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
100 reg &= ~OOB_DISABLE;
101 reg |= RGMII_LINK;
102 bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
103
104 /* speed */
105 if (phydev->speed == SPEED_1000)
106 cmd_bits = UMAC_SPEED_1000;
107 else if (phydev->speed == SPEED_100)
108 cmd_bits = UMAC_SPEED_100;
109 else
110 cmd_bits = UMAC_SPEED_10;
111 cmd_bits <<= CMD_SPEED_SHIFT;
112
113 if (priv->old_duplex != phydev->duplex) {
114 status_changed = 1;
115 priv->old_duplex = phydev->duplex;
116 }
117
118 /* duplex */
119 if (phydev->duplex != DUPLEX_FULL)
120 cmd_bits |= CMD_HD_EN;
121
122 if (priv->old_pause != phydev->pause) {
123 status_changed = 1;
124 priv->old_pause = phydev->pause;
125 }
126
127 /* pause capability */
128 if (!phydev->pause)
129 cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
24052408 130 }
aa09677c 131
c677ba8b
FF
132 if (!status_changed)
133 return;
134
135 if (phydev->link) {
aa09677c
FF
136 reg = bcmgenet_umac_readl(priv, UMAC_CMD);
137 reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
138 CMD_HD_EN |
139 CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
140 reg |= cmd_bits;
141 bcmgenet_umac_writel(priv, reg, UMAC_CMD);
aa09677c 142
24052408 143 }
c677ba8b
FF
144
145 phy_print_status(phydev);
aa09677c
FF
146}
147
148void bcmgenet_mii_reset(struct net_device *dev)
149{
150 struct bcmgenet_priv *priv = netdev_priv(dev);
151
152 if (priv->phydev) {
153 phy_init_hw(priv->phydev);
154 phy_start_aneg(priv->phydev);
155 }
156}
157
158static void bcmgenet_ephy_power_up(struct net_device *dev)
159{
160 struct bcmgenet_priv *priv = netdev_priv(dev);
161 u32 reg = 0;
162
163 /* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
164 if (!GENET_IS_V4(priv))
165 return;
166
167 reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
168 reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN);
169 reg |= EXT_GPHY_RESET;
170 bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
171 mdelay(2);
172
173 reg &= ~EXT_GPHY_RESET;
174 bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
175 udelay(20);
176}
177
178static void bcmgenet_internal_phy_setup(struct net_device *dev)
179{
180 struct bcmgenet_priv *priv = netdev_priv(dev);
181 u32 reg;
182
183 /* Power up EPHY */
184 bcmgenet_ephy_power_up(dev);
185 /* enable APD */
186 reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
187 reg |= EXT_PWR_DN_EN_LD;
188 bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
189 bcmgenet_mii_reset(dev);
190}
191
192static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
193{
194 u32 reg;
195
196 /* Speed settings are set in bcmgenet_mii_setup() */
197 reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
198 reg |= LED_ACT_SOURCE_MAC;
199 bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
200}
201
202int bcmgenet_mii_config(struct net_device *dev)
203{
204 struct bcmgenet_priv *priv = netdev_priv(dev);
205 struct phy_device *phydev = priv->phydev;
206 struct device *kdev = &priv->pdev->dev;
207 const char *phy_name = NULL;
208 u32 id_mode_dis = 0;
209 u32 port_ctrl;
210 u32 reg;
211
212 priv->ext_phy = !phy_is_internal(priv->phydev) &&
213 (priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
214
215 if (phy_is_internal(priv->phydev))
216 priv->phy_interface = PHY_INTERFACE_MODE_NA;
217
218 switch (priv->phy_interface) {
219 case PHY_INTERFACE_MODE_NA:
220 case PHY_INTERFACE_MODE_MOCA:
221 /* Irrespective of the actually configured PHY speed (100 or
222 * 1000) GENETv4 only has an internal GPHY so we will just end
223 * up masking the Gigabit features from what we support, not
224 * switching to the EPHY
225 */
226 if (GENET_IS_V4(priv))
227 port_ctrl = PORT_MODE_INT_GPHY;
228 else
229 port_ctrl = PORT_MODE_INT_EPHY;
230
231 bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
232
233 if (phy_is_internal(priv->phydev)) {
234 phy_name = "internal PHY";
235 bcmgenet_internal_phy_setup(dev);
236 } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
237 phy_name = "MoCA";
238 bcmgenet_moca_phy_setup(priv);
239 }
240 break;
241
242 case PHY_INTERFACE_MODE_MII:
243 phy_name = "external MII";
244 phydev->supported &= PHY_BASIC_FEATURES;
245 bcmgenet_sys_writel(priv,
c91b7f66 246 PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
aa09677c
FF
247 break;
248
249 case PHY_INTERFACE_MODE_REVMII:
250 phy_name = "external RvMII";
251 /* of_mdiobus_register took care of reading the 'max-speed'
252 * PHY property for us, effectively limiting the PHY supported
253 * capabilities, use that knowledge to also configure the
254 * Reverse MII interface correctly.
255 */
256 if ((priv->phydev->supported & PHY_BASIC_FEATURES) ==
257 PHY_BASIC_FEATURES)
258 port_ctrl = PORT_MODE_EXT_RVMII_25;
259 else
260 port_ctrl = PORT_MODE_EXT_RVMII_50;
261 bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
262 break;
263
264 case PHY_INTERFACE_MODE_RGMII:
265 /* RGMII_NO_ID: TXC transitions at the same time as TXD
266 * (requires PCB or receiver-side delay)
267 * RGMII: Add 2ns delay on TXC (90 degree shift)
268 *
269 * ID is implicitly disabled for 100Mbps (RG)MII operation.
270 */
271 id_mode_dis = BIT(16);
272 /* fall through */
273 case PHY_INTERFACE_MODE_RGMII_TXID:
274 if (id_mode_dis)
275 phy_name = "external RGMII (no delay)";
276 else
277 phy_name = "external RGMII (TX delay)";
278 reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
279 reg |= RGMII_MODE_EN | id_mode_dis;
280 bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
281 bcmgenet_sys_writel(priv,
c91b7f66 282 PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
aa09677c
FF
283 break;
284 default:
285 dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
286 return -EINVAL;
287 }
288
289 dev_info(kdev, "configuring instance for %s\n", phy_name);
290
291 return 0;
292}
293
294static int bcmgenet_mii_probe(struct net_device *dev)
295{
296 struct bcmgenet_priv *priv = netdev_priv(dev);
9abf0c2b 297 struct device_node *dn = priv->pdev->dev.of_node;
aa09677c 298 struct phy_device *phydev;
aa09677c
FF
299 int ret;
300
301 if (priv->phydev) {
302 pr_info("PHY already attached\n");
303 return 0;
304 }
305
9abf0c2b
FF
306 /* In the case of a fixed PHY, the DT node associated
307 * to the PHY is the Ethernet MAC DT node.
308 */
9518259f 309 if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
9abf0c2b
FF
310 ret = of_phy_register_fixed_link(dn);
311 if (ret)
312 return ret;
aa09677c 313
9518259f 314 priv->phy_dn = of_node_get(dn);
9abf0c2b
FF
315 }
316
317 phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, 0,
318 priv->phy_interface);
aa09677c
FF
319 if (!phydev) {
320 pr_err("could not attach to PHY\n");
321 return -ENODEV;
322 }
323
324 priv->old_link = -1;
325 priv->old_duplex = -1;
326 priv->old_pause = -1;
327 priv->phydev = phydev;
328
329 /* Configure port multiplexer based on what the probed PHY device since
330 * reading the 'max-speed' property determines the maximum supported
331 * PHY speed which is needed for bcmgenet_mii_config() to configure
332 * things appropriately.
333 */
334 ret = bcmgenet_mii_config(dev);
335 if (ret) {
336 phy_disconnect(priv->phydev);
337 return ret;
338 }
339
aa09677c
FF
340 phydev->advertising = phydev->supported;
341
342 /* The internal PHY has its link interrupts routed to the
343 * Ethernet MAC ISRs
344 */
345 if (phy_is_internal(priv->phydev))
346 priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT;
347 else
348 priv->mii_bus->irq[phydev->addr] = PHY_POLL;
349
350 pr_info("attached PHY at address %d [%s]\n",
c91b7f66 351 phydev->addr, phydev->drv->name);
aa09677c
FF
352
353 return 0;
354}
355
356static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv)
357{
358 struct mii_bus *bus;
359
360 if (priv->mii_bus)
361 return 0;
362
363 priv->mii_bus = mdiobus_alloc();
364 if (!priv->mii_bus) {
365 pr_err("failed to allocate\n");
366 return -ENOMEM;
367 }
368
369 bus = priv->mii_bus;
370 bus->priv = priv->dev;
371 bus->name = "bcmgenet MII bus";
372 bus->parent = &priv->pdev->dev;
373 bus->read = bcmgenet_mii_read;
374 bus->write = bcmgenet_mii_write;
375 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d",
c91b7f66 376 priv->pdev->name, priv->pdev->id);
aa09677c 377
c489be08 378 bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
aa09677c
FF
379 if (!bus->irq) {
380 mdiobus_free(priv->mii_bus);
381 return -ENOMEM;
382 }
383
384 return 0;
385}
386
387static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
388{
389 struct device_node *dn = priv->pdev->dev.of_node;
390 struct device *kdev = &priv->pdev->dev;
391 struct device_node *mdio_dn;
392 char *compat;
393 int ret;
394
395 compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
396 if (!compat)
397 return -ENOMEM;
398
399 mdio_dn = of_find_compatible_node(dn, NULL, compat);
400 kfree(compat);
401 if (!mdio_dn) {
402 dev_err(kdev, "unable to find MDIO bus node\n");
403 return -ENODEV;
404 }
405
406 ret = of_mdiobus_register(priv->mii_bus, mdio_dn);
407 if (ret) {
408 dev_err(kdev, "failed to register MDIO bus\n");
409 return ret;
410 }
411
412 /* Fetch the PHY phandle */
413 priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
414
415 /* Get the link mode */
416 priv->phy_interface = of_get_phy_mode(dn);
417
418 return 0;
419}
420
421int bcmgenet_mii_init(struct net_device *dev)
422{
423 struct bcmgenet_priv *priv = netdev_priv(dev);
424 int ret;
425
426 ret = bcmgenet_mii_alloc(priv);
427 if (ret)
428 return ret;
429
430 ret = bcmgenet_mii_of_init(priv);
431 if (ret)
432 goto out_free;
433
434 ret = bcmgenet_mii_probe(dev);
435 if (ret)
436 goto out;
437
438 return 0;
439
440out:
9518259f 441 of_node_put(priv->phy_dn);
aa09677c
FF
442 mdiobus_unregister(priv->mii_bus);
443out_free:
444 kfree(priv->mii_bus->irq);
445 mdiobus_free(priv->mii_bus);
446 return ret;
447}
448
449void bcmgenet_mii_exit(struct net_device *dev)
450{
451 struct bcmgenet_priv *priv = netdev_priv(dev);
452
9518259f 453 of_node_put(priv->phy_dn);
aa09677c
FF
454 mdiobus_unregister(priv->mii_bus);
455 kfree(priv->mii_bus->irq);
456 mdiobus_free(priv->mii_bus);
457}