Skip to content

Commit

Permalink
net: phy: add driver for aquantia phy
Browse files Browse the repository at this point in the history
This patch added driver to support Aquantia PHYs AQ1202, AQ2104, AQR105,
AQR405, which accessed through clause 45.

Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Shaohui Xie authored and David S. Miller committed Jul 31, 2015
1 parent 85b1d8b commit bee8259
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 0 deletions.
5 changes: 5 additions & 0 deletions drivers/net/phy/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ if PHYLIB

comment "MII PHY device drivers"

config AQUANTIA_PHY
tristate "Drivers for the Aquantia PHYs"
---help---
Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405

config AT803X_PHY
tristate "Drivers for Atheros AT803X PHYs"
---help---
Expand Down
1 change: 1 addition & 0 deletions drivers/net/phy/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
libphy-objs := phy.o phy_device.o mdio_bus.o

obj-$(CONFIG_PHYLIB) += libphy.o
obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o
obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
obj-$(CONFIG_CICADA_PHY) += cicada.o
Expand Down
152 changes: 152 additions & 0 deletions drivers/net/phy/aquantia.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Driver for Aquantia PHY
*
* Author: Shaohui Xie <Shaohui.Xie@freescale.com>
*
* Copyright 2015 Freescale Semiconductor, Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/mdio.h>

#define PHY_ID_AQ1202 0x03a1b445
#define PHY_ID_AQ2104 0x03a1b460
#define PHY_ID_AQR105 0x03a1b4a2
#define PHY_ID_AQR405 0x03a1b4b0

#define PHY_AQUANTIA_FEATURES (SUPPORTED_10000baseT_Full | \
SUPPORTED_1000baseT_Full | \
SUPPORTED_100baseT_Full | \
PHY_DEFAULT_FEATURES)

static int aquantia_config_aneg(struct phy_device *phydev)
{
phydev->supported = PHY_AQUANTIA_FEATURES;
phydev->advertising = phydev->supported;

return 0;
}

static int aquantia_aneg_done(struct phy_device *phydev)
{
int reg;

reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
return (reg < 0) ? reg : (reg & BMSR_ANEGCOMPLETE);
}

static int aquantia_read_status(struct phy_device *phydev)
{
int reg;

reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
if (reg & MDIO_STAT1_LSTATUS)
phydev->link = 1;
else
phydev->link = 0;

reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800);
mdelay(10);
reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800);

switch (reg) {
case 0x9:
phydev->speed = SPEED_2500;
break;
case 0x5:
phydev->speed = SPEED_1000;
break;
case 0x3:
phydev->speed = SPEED_100;
break;
case 0x7:
default:
phydev->speed = SPEED_10000;
break;
}
phydev->duplex = DUPLEX_FULL;

return 0;
}

static struct phy_driver aquantia_driver[] = {
{
.phy_id = PHY_ID_AQ1202,
.phy_id_mask = 0xfffffff0,
.name = "Aquantia AQ1202",
.features = PHY_AQUANTIA_FEATURES,
.aneg_done = aquantia_aneg_done,
.config_aneg = aquantia_config_aneg,
.read_status = aquantia_read_status,
.driver = { .owner = THIS_MODULE,},
},
{
.phy_id = PHY_ID_AQ2104,
.phy_id_mask = 0xfffffff0,
.name = "Aquantia AQ2104",
.features = PHY_AQUANTIA_FEATURES,
.aneg_done = aquantia_aneg_done,
.config_aneg = aquantia_config_aneg,
.read_status = aquantia_read_status,
.driver = { .owner = THIS_MODULE,},
},
{
.phy_id = PHY_ID_AQR105,
.phy_id_mask = 0xfffffff0,
.name = "Aquantia AQR105",
.features = PHY_AQUANTIA_FEATURES,
.aneg_done = aquantia_aneg_done,
.config_aneg = aquantia_config_aneg,
.read_status = aquantia_read_status,
.driver = { .owner = THIS_MODULE,},
},
{
.phy_id = PHY_ID_AQR405,
.phy_id_mask = 0xfffffff0,
.name = "Aquantia AQR405",
.features = PHY_AQUANTIA_FEATURES,
.aneg_done = aquantia_aneg_done,
.config_aneg = aquantia_config_aneg,
.read_status = aquantia_read_status,
.driver = { .owner = THIS_MODULE,},
},
};

static int __init aquantia_init(void)
{
return phy_drivers_register(aquantia_driver,
ARRAY_SIZE(aquantia_driver));
}

static void __exit aquantia_exit(void)
{
return phy_drivers_unregister(aquantia_driver,
ARRAY_SIZE(aquantia_driver));
}

module_init(aquantia_init);
module_exit(aquantia_exit);

static struct mdio_device_id __maybe_unused aquantia_tbl[] = {
{ PHY_ID_AQ1202, 0xfffffff0 },
{ PHY_ID_AQ2104, 0xfffffff0 },
{ PHY_ID_AQR105, 0xfffffff0 },
{ PHY_ID_AQR405, 0xfffffff0 },
{ }
};

MODULE_DEVICE_TABLE(mdio, aquantia_tbl);

MODULE_DESCRIPTION("Aquantia PHY driver");
MODULE_AUTHOR("Shaohui Xie <Shaohui.Xie@freescale.com>");
MODULE_LICENSE("GPL v2");

0 comments on commit bee8259

Please sign in to comment.