aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShaohui Xie <Shaohui.Xie@freescale.com>2015-07-31 04:58:42 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-31 18:28:19 -0400
commitbee8259dd31f419a883174556b11edc6f9a153d1 (patch)
tree68a67ff96c08d9f281f1724327b00c6188ff6aea
parent85b1d8bbfd2ea6ae1dc6d0ccdb25abdcb52a5856 (diff)
net: phy: add driver for aquantia phy
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>
-rw-r--r--drivers/net/phy/Kconfig5
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/aquantia.c152
3 files changed, 158 insertions, 0 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 8ef819144220..c07030dbe748 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -14,6 +14,11 @@ if PHYLIB
14 14
15comment "MII PHY device drivers" 15comment "MII PHY device drivers"
16 16
17config AQUANTIA_PHY
18 tristate "Drivers for the Aquantia PHYs"
19 ---help---
20 Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
21
17config AT803X_PHY 22config AT803X_PHY
18 tristate "Drivers for Atheros AT803X PHYs" 23 tristate "Drivers for Atheros AT803X PHYs"
19 ---help--- 24 ---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 16aac1c3e703..9bb103358c74 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -3,6 +3,7 @@
3libphy-objs := phy.o phy_device.o mdio_bus.o 3libphy-objs := phy.o phy_device.o mdio_bus.o
4 4
5obj-$(CONFIG_PHYLIB) += libphy.o 5obj-$(CONFIG_PHYLIB) += libphy.o
6obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o
6obj-$(CONFIG_MARVELL_PHY) += marvell.o 7obj-$(CONFIG_MARVELL_PHY) += marvell.o
7obj-$(CONFIG_DAVICOM_PHY) += davicom.o 8obj-$(CONFIG_DAVICOM_PHY) += davicom.o
8obj-$(CONFIG_CICADA_PHY) += cicada.o 9obj-$(CONFIG_CICADA_PHY) += cicada.o
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
new file mode 100644
index 000000000000..73d347d7cb04
--- /dev/null
+++ b/drivers/net/phy/aquantia.c
@@ -0,0 +1,152 @@
1/*
2 * Driver for Aquantia PHY
3 *
4 * Author: Shaohui Xie <Shaohui.Xie@freescale.com>
5 *
6 * Copyright 2015 Freescale Semiconductor, Inc.
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/delay.h>
16#include <linux/mii.h>
17#include <linux/ethtool.h>
18#include <linux/phy.h>
19#include <linux/mdio.h>
20
21#define PHY_ID_AQ1202 0x03a1b445
22#define PHY_ID_AQ2104 0x03a1b460
23#define PHY_ID_AQR105 0x03a1b4a2
24#define PHY_ID_AQR405 0x03a1b4b0
25
26#define PHY_AQUANTIA_FEATURES (SUPPORTED_10000baseT_Full | \
27 SUPPORTED_1000baseT_Full | \
28 SUPPORTED_100baseT_Full | \
29 PHY_DEFAULT_FEATURES)
30
31static int aquantia_config_aneg(struct phy_device *phydev)
32{
33 phydev->supported = PHY_AQUANTIA_FEATURES;
34 phydev->advertising = phydev->supported;
35
36 return 0;
37}
38
39static int aquantia_aneg_done(struct phy_device *phydev)
40{
41 int reg;
42
43 reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
44 return (reg < 0) ? reg : (reg & BMSR_ANEGCOMPLETE);
45}
46
47static int aquantia_read_status(struct phy_device *phydev)
48{
49 int reg;
50
51 reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
52 reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
53 if (reg & MDIO_STAT1_LSTATUS)
54 phydev->link = 1;
55 else
56 phydev->link = 0;
57
58 reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800);
59 mdelay(10);
60 reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800);
61
62 switch (reg) {
63 case 0x9:
64 phydev->speed = SPEED_2500;
65 break;
66 case 0x5:
67 phydev->speed = SPEED_1000;
68 break;
69 case 0x3:
70 phydev->speed = SPEED_100;
71 break;
72 case 0x7:
73 default:
74 phydev->speed = SPEED_10000;
75 break;
76 }
77 phydev->duplex = DUPLEX_FULL;
78
79 return 0;
80}
81
82static struct phy_driver aquantia_driver[] = {
83{
84 .phy_id = PHY_ID_AQ1202,
85 .phy_id_mask = 0xfffffff0,
86 .name = "Aquantia AQ1202",
87 .features = PHY_AQUANTIA_FEATURES,
88 .aneg_done = aquantia_aneg_done,
89 .config_aneg = aquantia_config_aneg,
90 .read_status = aquantia_read_status,
91 .driver = { .owner = THIS_MODULE,},
92},
93{
94 .phy_id = PHY_ID_AQ2104,
95 .phy_id_mask = 0xfffffff0,
96 .name = "Aquantia AQ2104",
97 .features = PHY_AQUANTIA_FEATURES,
98 .aneg_done = aquantia_aneg_done,
99 .config_aneg = aquantia_config_aneg,
100 .read_status = aquantia_read_status,
101 .driver = { .owner = THIS_MODULE,},
102},
103{
104 .phy_id = PHY_ID_AQR105,
105 .phy_id_mask = 0xfffffff0,
106 .name = "Aquantia AQR105",
107 .features = PHY_AQUANTIA_FEATURES,
108 .aneg_done = aquantia_aneg_done,
109 .config_aneg = aquantia_config_aneg,
110 .read_status = aquantia_read_status,
111 .driver = { .owner = THIS_MODULE,},
112},
113{
114 .phy_id = PHY_ID_AQR405,
115 .phy_id_mask = 0xfffffff0,
116 .name = "Aquantia AQR405",
117 .features = PHY_AQUANTIA_FEATURES,
118 .aneg_done = aquantia_aneg_done,
119 .config_aneg = aquantia_config_aneg,
120 .read_status = aquantia_read_status,
121 .driver = { .owner = THIS_MODULE,},
122},
123};
124
125static int __init aquantia_init(void)
126{
127 return phy_drivers_register(aquantia_driver,
128 ARRAY_SIZE(aquantia_driver));
129}
130
131static void __exit aquantia_exit(void)
132{
133 return phy_drivers_unregister(aquantia_driver,
134 ARRAY_SIZE(aquantia_driver));
135}
136
137module_init(aquantia_init);
138module_exit(aquantia_exit);
139
140static struct mdio_device_id __maybe_unused aquantia_tbl[] = {
141 { PHY_ID_AQ1202, 0xfffffff0 },
142 { PHY_ID_AQ2104, 0xfffffff0 },
143 { PHY_ID_AQR105, 0xfffffff0 },
144 { PHY_ID_AQR405, 0xfffffff0 },
145 { }
146};
147
148MODULE_DEVICE_TABLE(mdio, aquantia_tbl);
149
150MODULE_DESCRIPTION("Aquantia PHY driver");
151MODULE_AUTHOR("Shaohui Xie <Shaohui.Xie@freescale.com>");
152MODULE_LICENSE("GPL v2");