2 * Driver for Aquantia PHY
4 * Author: Shaohui Xie <Shaohui.Xie@freescale.com>
6 * Copyright 2015 Freescale Semiconductor, Inc.
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.
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>
21 #define PHY_ID_AQ1202 0x03a1b445
22 #define PHY_ID_AQ2104 0x03a1b460
23 #define PHY_ID_AQR105 0x03a1b4a2
24 #define PHY_ID_AQR405 0x03a1b4b0
26 #define PHY_AQUANTIA_FEATURES (SUPPORTED_10000baseT_Full | \
27 SUPPORTED_1000baseT_Full | \
28 SUPPORTED_100baseT_Full | \
31 static int aquantia_config_aneg(struct phy_device
*phydev
)
33 phydev
->supported
= PHY_AQUANTIA_FEATURES
;
34 phydev
->advertising
= phydev
->supported
;
39 static int aquantia_aneg_done(struct phy_device
*phydev
)
43 reg
= phy_read_mmd(phydev
, MDIO_MMD_AN
, MDIO_STAT1
);
44 return (reg
< 0) ? reg
: (reg
& BMSR_ANEGCOMPLETE
);
47 static int aquantia_read_status(struct phy_device
*phydev
)
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
)
58 reg
= phy_read_mmd(phydev
, MDIO_MMD_AN
, 0xc800);
60 reg
= phy_read_mmd(phydev
, MDIO_MMD_AN
, 0xc800);
64 phydev
->speed
= SPEED_2500
;
67 phydev
->speed
= SPEED_1000
;
70 phydev
->speed
= SPEED_100
;
74 phydev
->speed
= SPEED_10000
;
77 phydev
->duplex
= DUPLEX_FULL
;
82 static struct phy_driver aquantia_driver
[] = {
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
,},
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
,},
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
,},
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
,},
125 static int __init
aquantia_init(void)
127 return phy_drivers_register(aquantia_driver
,
128 ARRAY_SIZE(aquantia_driver
));
131 static void __exit
aquantia_exit(void)
133 return phy_drivers_unregister(aquantia_driver
,
134 ARRAY_SIZE(aquantia_driver
));
137 module_init(aquantia_init
);
138 module_exit(aquantia_exit
);
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 },
148 MODULE_DEVICE_TABLE(mdio
, aquantia_tbl
);
150 MODULE_DESCRIPTION("Aquantia PHY driver");
151 MODULE_AUTHOR("Shaohui Xie <Shaohui.Xie@freescale.com>");
152 MODULE_LICENSE("GPL v2");