diff options
author | Shaohui Xie <Shaohui.Xie@freescale.com> | 2015-07-31 04:58:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-31 18:28:19 -0400 |
commit | bee8259dd31f419a883174556b11edc6f9a153d1 (patch) | |
tree | 68a67ff96c08d9f281f1724327b00c6188ff6aea | |
parent | 85b1d8bbfd2ea6ae1dc6d0ccdb25abdcb52a5856 (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/Kconfig | 5 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/aquantia.c | 152 |
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 | ||
15 | comment "MII PHY device drivers" | 15 | comment "MII PHY device drivers" |
16 | 16 | ||
17 | config AQUANTIA_PHY | ||
18 | tristate "Drivers for the Aquantia PHYs" | ||
19 | ---help--- | ||
20 | Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 | ||
21 | |||
17 | config AT803X_PHY | 22 | config 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 @@ | |||
3 | libphy-objs := phy.o phy_device.o mdio_bus.o | 3 | libphy-objs := phy.o phy_device.o mdio_bus.o |
4 | 4 | ||
5 | obj-$(CONFIG_PHYLIB) += libphy.o | 5 | obj-$(CONFIG_PHYLIB) += libphy.o |
6 | obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o | ||
6 | obj-$(CONFIG_MARVELL_PHY) += marvell.o | 7 | obj-$(CONFIG_MARVELL_PHY) += marvell.o |
7 | obj-$(CONFIG_DAVICOM_PHY) += davicom.o | 8 | obj-$(CONFIG_DAVICOM_PHY) += davicom.o |
8 | obj-$(CONFIG_CICADA_PHY) += cicada.o | 9 | obj-$(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 | |||
31 | static 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 | |||
39 | static 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 | |||
47 | static 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 | |||
82 | static 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 | |||
125 | static int __init aquantia_init(void) | ||
126 | { | ||
127 | return phy_drivers_register(aquantia_driver, | ||
128 | ARRAY_SIZE(aquantia_driver)); | ||
129 | } | ||
130 | |||
131 | static void __exit aquantia_exit(void) | ||
132 | { | ||
133 | return phy_drivers_unregister(aquantia_driver, | ||
134 | ARRAY_SIZE(aquantia_driver)); | ||
135 | } | ||
136 | |||
137 | module_init(aquantia_init); | ||
138 | module_exit(aquantia_exit); | ||
139 | |||
140 | static 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 | |||
148 | MODULE_DEVICE_TABLE(mdio, aquantia_tbl); | ||
149 | |||
150 | MODULE_DESCRIPTION("Aquantia PHY driver"); | ||
151 | MODULE_AUTHOR("Shaohui Xie <Shaohui.Xie@freescale.com>"); | ||
152 | MODULE_LICENSE("GPL v2"); | ||