Commit f7c38cf827a0cf9d5ab4ca60131dffa10a2e4309

Authored by Shaohui Xie
Committed by York Sun
1 parent 59d34ed022

phylib: add support for aquantia PHYs

This patch supports AQ1202, AQ2104, AQR105 PHY.

Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: York Sun <yorksun@freescale.com>

Showing 4 changed files with 161 additions and 0 deletions Side-by-side Diff

drivers/net/phy/Makefile
... ... @@ -11,6 +11,7 @@
11 11  
12 12 obj-$(CONFIG_PHYLIB) += phy.o
13 13 obj-$(CONFIG_PHYLIB_10G) += generic_10g.o
  14 +obj-$(CONFIG_PHY_AQUANTIA) += aquantia.o
14 15 obj-$(CONFIG_PHY_ATHEROS) += atheros.o
15 16 obj-$(CONFIG_PHY_BROADCOM) += broadcom.o
16 17 obj-$(CONFIG_PHY_CORTINA) += cortina.o
drivers/net/phy/aquantia.c
  1 +/*
  2 + * Aquantia PHY drivers
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + *
  6 + * Copyright 2014 Freescale Semiconductor, Inc.
  7 + */
  8 +#include <config.h>
  9 +#include <common.h>
  10 +#include <phy.h>
  11 +
  12 +#ifndef CONFIG_PHYLIB_10G
  13 +#error The Aquantia PHY needs 10G support
  14 +#endif
  15 +
  16 +#define AQUNTIA_10G_CTL 0x20
  17 +#define AQUNTIA_VENDOR_P1 0xc400
  18 +
  19 +#define AQUNTIA_SPEED_LSB_MASK 0x2000
  20 +#define AQUNTIA_SPEED_MSB_MASK 0x40
  21 +
  22 +int aquantia_config(struct phy_device *phydev)
  23 +{
  24 + u32 val = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR);
  25 +
  26 + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
  27 + /* 1000BASE-T mode */
  28 + phydev->advertising = SUPPORTED_1000baseT_Full;
  29 + phydev->supported = phydev->advertising;
  30 +
  31 + val = (val & ~AQUNTIA_SPEED_LSB_MASK) | AQUNTIA_SPEED_MSB_MASK;
  32 + phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val);
  33 + } else if (phydev->interface == PHY_INTERFACE_MODE_XGMII) {
  34 + /* 10GBASE-T mode */
  35 + phydev->advertising = SUPPORTED_10000baseT_Full;
  36 + phydev->supported = phydev->advertising;
  37 +
  38 + if (!(val & AQUNTIA_SPEED_LSB_MASK) ||
  39 + !(val & AQUNTIA_SPEED_MSB_MASK))
  40 + phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR,
  41 + AQUNTIA_SPEED_LSB_MASK |
  42 + AQUNTIA_SPEED_MSB_MASK);
  43 + } else if (phydev->interface == PHY_INTERFACE_MODE_SGMII_2500) {
  44 + /* 2.5GBASE-T mode */
  45 + phydev->advertising = SUPPORTED_1000baseT_Full;
  46 + phydev->supported = phydev->advertising;
  47 +
  48 + phy_write(phydev, MDIO_MMD_AN, AQUNTIA_10G_CTL, 1);
  49 + phy_write(phydev, MDIO_MMD_AN, AQUNTIA_VENDOR_P1, 0x9440);
  50 + } else if (phydev->interface == PHY_INTERFACE_MODE_MII) {
  51 + /* 100BASE-TX mode */
  52 + phydev->advertising = SUPPORTED_100baseT_Full;
  53 + phydev->supported = phydev->advertising;
  54 +
  55 + val = (val & ~AQUNTIA_SPEED_MSB_MASK) | AQUNTIA_SPEED_LSB_MASK;
  56 + phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val);
  57 + }
  58 + return 0;
  59 +}
  60 +
  61 +int aquantia_startup(struct phy_device *phydev)
  62 +{
  63 + u32 reg, speed;
  64 + int i = 0;
  65 +
  66 + phydev->duplex = DUPLEX_FULL;
  67 +
  68 + /* if the AN is still in progress, wait till timeout. */
  69 + phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
  70 + reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
  71 + if (!(reg & MDIO_AN_STAT1_COMPLETE)) {
  72 + printf("%s Waiting for PHY auto negotiation to complete",
  73 + phydev->dev->name);
  74 + do {
  75 + udelay(1000);
  76 + reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
  77 + if ((i++ % 500) == 0)
  78 + printf(".");
  79 + } while (!(reg & MDIO_AN_STAT1_COMPLETE) &&
  80 + i < (4 * PHY_ANEG_TIMEOUT));
  81 +
  82 + if (i > PHY_ANEG_TIMEOUT)
  83 + printf(" TIMEOUT !\n");
  84 + }
  85 +
  86 + /* Read twice because link state is latched and a
  87 + * read moves the current state into the register */
  88 + phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
  89 + reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1);
  90 + if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
  91 + phydev->link = 0;
  92 + else
  93 + phydev->link = 1;
  94 +
  95 + speed = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR);
  96 + if (speed & AQUNTIA_SPEED_MSB_MASK) {
  97 + if (speed & AQUNTIA_SPEED_LSB_MASK)
  98 + phydev->speed = SPEED_10000;
  99 + else
  100 + phydev->speed = SPEED_1000;
  101 + } else {
  102 + if (speed & AQUNTIA_SPEED_LSB_MASK)
  103 + phydev->speed = SPEED_100;
  104 + else
  105 + phydev->speed = SPEED_10;
  106 + }
  107 +
  108 + return 0;
  109 +}
  110 +
  111 +struct phy_driver aq1202_driver = {
  112 + .name = "Aquantia AQ1202",
  113 + .uid = 0x3a1b445,
  114 + .mask = 0xfffffff0,
  115 + .features = PHY_10G_FEATURES,
  116 + .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
  117 + MDIO_MMD_PHYXS | MDIO_MMD_AN |
  118 + MDIO_MMD_VEND1),
  119 + .config = &aquantia_config,
  120 + .startup = &aquantia_startup,
  121 + .shutdown = &gen10g_shutdown,
  122 +};
  123 +
  124 +struct phy_driver aq2104_driver = {
  125 + .name = "Aquantia AQ2104",
  126 + .uid = 0x3a1b460,
  127 + .mask = 0xfffffff0,
  128 + .features = PHY_10G_FEATURES,
  129 + .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
  130 + MDIO_MMD_PHYXS | MDIO_MMD_AN |
  131 + MDIO_MMD_VEND1),
  132 + .config = &aquantia_config,
  133 + .startup = &aquantia_startup,
  134 + .shutdown = &gen10g_shutdown,
  135 +};
  136 +
  137 +struct phy_driver aqr105_driver = {
  138 + .name = "Aquantia AQR105",
  139 + .uid = 0x3a1b4a2,
  140 + .mask = 0xfffffff0,
  141 + .features = PHY_10G_FEATURES,
  142 + .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS|
  143 + MDIO_MMD_PHYXS | MDIO_MMD_AN |
  144 + MDIO_MMD_VEND1),
  145 + .config = &aquantia_config,
  146 + .startup = &aquantia_startup,
  147 + .shutdown = &gen10g_shutdown,
  148 +};
  149 +int phy_aquantia_init(void)
  150 +{
  151 + phy_register(&aq1202_driver);
  152 + phy_register(&aq2104_driver);
  153 + phy_register(&aqr105_driver);
  154 +
  155 + return 0;
  156 +}
drivers/net/phy/phy.c
... ... @@ -442,6 +442,9 @@
442 442  
443 443 int phy_init(void)
444 444 {
  445 +#ifdef CONFIG_PHY_AQUANTIA
  446 + phy_aquantia_init();
  447 +#endif
445 448 #ifdef CONFIG_PHY_ATHEROS
446 449 phy_atheros_init();
447 450 #endif
... ... @@ -225,6 +225,7 @@
225 225 int gen10g_shutdown(struct phy_device *phydev);
226 226 int gen10g_discover_mmds(struct phy_device *phydev);
227 227  
  228 +int phy_aquantia_init(void);
228 229 int phy_atheros_init(void);
229 230 int phy_broadcom_init(void);
230 231 int phy_cortina_init(void);