diff options
author | Arun Parameswaran <arunp@broadcom.com> | 2015-10-06 15:25:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-08 07:45:52 -0400 |
commit | 8e185d6997bb67068f0ca8f062a50caa2608cf1b (patch) | |
tree | b2d42099f3777dc770023566cfd8d1dc3f1cc761 | |
parent | a1cba5613edf50c2a213fa90c30aa10500b241b7 (diff) |
net: phy: Broadcom Cygnus internal Etherent PHY driver
Add support for the Broadcom Cygnus SoCs internal PHY's.
The PHYs are 1000M/100M/10M capable with support for 'EEE'
and 'APD' (Auto Power Down).
This driver supports the following Broadcom Cygnus SoCs:
- BCM583XX (BCM58300, BCM58302, BCM58303, BCM58305)
- BCM113XX (BCM11300, BCM11320, BCM11350, BCM11360)
The PHY's on these SoC's require some workarounds for
stable operation, both during configuration time and
during suspend/resume. This driver handles the
application of the workarounds.
Signed-off-by: Arun Parameswaran <arunp@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/Kconfig | 13 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/bcm-cygnus.c | 158 | ||||
-rw-r--r-- | include/linux/brcmphy.h | 7 |
4 files changed, 179 insertions, 0 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 606fdc924768..9d097ae54fb2 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
@@ -79,6 +79,19 @@ config BROADCOM_PHY | |||
79 | Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464, | 79 | Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464, |
80 | BCM5481 and BCM5482 PHYs. | 80 | BCM5481 and BCM5482 PHYs. |
81 | 81 | ||
82 | config BCM_CYGNUS_PHY | ||
83 | tristate "Drivers for Broadcom Cygnus SoC internal PHY" | ||
84 | depends on ARCH_BCM_CYGNUS || COMPILE_TEST | ||
85 | depends on MDIO_BCM_IPROC | ||
86 | select BCM_NET_PHYLIB | ||
87 | ---help--- | ||
88 | This PHY driver is for the 1G internal PHYs of the Broadcom | ||
89 | Cygnus Family SoC. | ||
90 | |||
91 | Currently supports internal PHY's used in the BCM11300, | ||
92 | BCM11320, BCM11350, BCM11360, BCM58300, BCM58302, | ||
93 | BCM58303 & BCM58305 Broadcom Cygnus SoCs. | ||
94 | |||
82 | config BCM63XX_PHY | 95 | config BCM63XX_PHY |
83 | tristate "Drivers for Broadcom 63xx SOCs internal PHY" | 96 | tristate "Drivers for Broadcom 63xx SOCs internal PHY" |
84 | depends on BCM63XX | 97 | depends on BCM63XX |
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 6932475a1a8a..7655d47ad8d8 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_BROADCOM_PHY) += broadcom.o | |||
17 | obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o | 17 | obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o |
18 | obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o | 18 | obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o |
19 | obj-$(CONFIG_BCM87XX_PHY) += bcm87xx.o | 19 | obj-$(CONFIG_BCM87XX_PHY) += bcm87xx.o |
20 | obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o | ||
20 | obj-$(CONFIG_ICPLUS_PHY) += icplus.o | 21 | obj-$(CONFIG_ICPLUS_PHY) += icplus.o |
21 | obj-$(CONFIG_REALTEK_PHY) += realtek.o | 22 | obj-$(CONFIG_REALTEK_PHY) += realtek.o |
22 | obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o | 23 | obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o |
diff --git a/drivers/net/phy/bcm-cygnus.c b/drivers/net/phy/bcm-cygnus.c new file mode 100644 index 000000000000..49bbc6826883 --- /dev/null +++ b/drivers/net/phy/bcm-cygnus.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | /* Broadcom Cygnus SoC internal transceivers support. */ | ||
15 | #include "bcm-phy-lib.h" | ||
16 | #include <linux/brcmphy.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/phy.h> | ||
20 | |||
21 | /* Broadcom Cygnus Phy specific registers */ | ||
22 | #define MII_BCM_CYGNUS_AFE_VDAC_ICTRL_0 0x91E5 /* VDAL Control register */ | ||
23 | |||
24 | static int bcm_cygnus_afe_config(struct phy_device *phydev) | ||
25 | { | ||
26 | int rc; | ||
27 | |||
28 | /* ensure smdspclk is enabled */ | ||
29 | rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, 0x0c30); | ||
30 | if (rc < 0) | ||
31 | return rc; | ||
32 | |||
33 | /* AFE_VDAC_ICTRL_0 bit 7:4 Iq=1100 for 1g 10bt, normal modes */ | ||
34 | rc = bcm_phy_write_misc(phydev, 0x39, 0x01, 0xA7C8); | ||
35 | if (rc < 0) | ||
36 | return rc; | ||
37 | |||
38 | /* AFE_HPF_TRIM_OTHERS bit11=1, short cascode enable for all modes*/ | ||
39 | rc = bcm_phy_write_misc(phydev, 0x3A, 0x00, 0x0803); | ||
40 | if (rc < 0) | ||
41 | return rc; | ||
42 | |||
43 | /* AFE_TX_CONFIG_1 bit 7:4 Iq=1100 for test modes */ | ||
44 | rc = bcm_phy_write_misc(phydev, 0x3A, 0x01, 0xA740); | ||
45 | if (rc < 0) | ||
46 | return rc; | ||
47 | |||
48 | /* AFE TEMPSEN_OTHERS rcal_HT, rcal_LT 10000 */ | ||
49 | rc = bcm_phy_write_misc(phydev, 0x3A, 0x03, 0x8400); | ||
50 | if (rc < 0) | ||
51 | return rc; | ||
52 | |||
53 | /* AFE_FUTURE_RSV bit 2:0 rccal <2:0>=100 */ | ||
54 | rc = bcm_phy_write_misc(phydev, 0x3B, 0x00, 0x0004); | ||
55 | if (rc < 0) | ||
56 | return rc; | ||
57 | |||
58 | /* Adjust bias current trim to overcome digital offSet */ | ||
59 | rc = phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x02); | ||
60 | if (rc < 0) | ||
61 | return rc; | ||
62 | |||
63 | /* make rcal=100, since rdb default is 000 */ | ||
64 | rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB1, 0x10); | ||
65 | if (rc < 0) | ||
66 | return rc; | ||
67 | |||
68 | /* CORE_EXPB0, Reset R_CAL/RC_CAL Engine */ | ||
69 | rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x10); | ||
70 | if (rc < 0) | ||
71 | return rc; | ||
72 | |||
73 | /* CORE_EXPB0, Disable Reset R_CAL/RC_CAL Engine */ | ||
74 | rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x00); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int bcm_cygnus_config_init(struct phy_device *phydev) | ||
80 | { | ||
81 | int reg, rc; | ||
82 | |||
83 | reg = phy_read(phydev, MII_BCM54XX_ECR); | ||
84 | if (reg < 0) | ||
85 | return reg; | ||
86 | |||
87 | /* Mask interrupts globally. */ | ||
88 | reg |= MII_BCM54XX_ECR_IM; | ||
89 | rc = phy_write(phydev, MII_BCM54XX_ECR, reg); | ||
90 | if (rc) | ||
91 | return rc; | ||
92 | |||
93 | /* Unmask events of interest */ | ||
94 | reg = ~(MII_BCM54XX_INT_DUPLEX | | ||
95 | MII_BCM54XX_INT_SPEED | | ||
96 | MII_BCM54XX_INT_LINK); | ||
97 | rc = phy_write(phydev, MII_BCM54XX_IMR, reg); | ||
98 | if (rc) | ||
99 | return rc; | ||
100 | |||
101 | /* Apply AFE settings for the PHY */ | ||
102 | rc = bcm_cygnus_afe_config(phydev); | ||
103 | if (rc) | ||
104 | return rc; | ||
105 | |||
106 | /* Advertise EEE */ | ||
107 | rc = bcm_phy_enable_eee(phydev); | ||
108 | if (rc) | ||
109 | return rc; | ||
110 | |||
111 | /* Enable APD */ | ||
112 | return bcm_phy_enable_apd(phydev, false); | ||
113 | } | ||
114 | |||
115 | static int bcm_cygnus_resume(struct phy_device *phydev) | ||
116 | { | ||
117 | int rc; | ||
118 | |||
119 | genphy_resume(phydev); | ||
120 | |||
121 | /* Re-initialize the PHY to apply AFE work-arounds and | ||
122 | * configurations when coming out of suspend. | ||
123 | */ | ||
124 | rc = bcm_cygnus_config_init(phydev); | ||
125 | if (rc) | ||
126 | return rc; | ||
127 | |||
128 | /* restart auto negotiation with the new settings */ | ||
129 | return genphy_config_aneg(phydev); | ||
130 | } | ||
131 | |||
132 | static struct phy_driver bcm_cygnus_phy_driver[] = { | ||
133 | { | ||
134 | .phy_id = PHY_ID_BCM_CYGNUS, | ||
135 | .phy_id_mask = 0xfffffff0, | ||
136 | .name = "Broadcom Cygnus PHY", | ||
137 | .features = PHY_GBIT_FEATURES | | ||
138 | SUPPORTED_Pause | SUPPORTED_Asym_Pause, | ||
139 | .config_init = bcm_cygnus_config_init, | ||
140 | .config_aneg = genphy_config_aneg, | ||
141 | .read_status = genphy_read_status, | ||
142 | .ack_interrupt = bcm_phy_ack_intr, | ||
143 | .config_intr = bcm_phy_config_intr, | ||
144 | .suspend = genphy_suspend, | ||
145 | .resume = bcm_cygnus_resume, | ||
146 | } }; | ||
147 | |||
148 | static struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = { | ||
149 | { PHY_ID_BCM_CYGNUS, 0xfffffff0, }, | ||
150 | { } | ||
151 | }; | ||
152 | MODULE_DEVICE_TABLE(mdio, bcm_cygnus_phy_tbl); | ||
153 | |||
154 | module_phy_driver(bcm_cygnus_phy_driver); | ||
155 | |||
156 | MODULE_DESCRIPTION("Broadcom Cygnus internal PHY driver"); | ||
157 | MODULE_LICENSE("GPL v2"); | ||
158 | MODULE_AUTHOR("Broadcom Corporation"); | ||
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 6a53ab91407c..59f4a7304419 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h | |||
@@ -30,6 +30,8 @@ | |||
30 | #define PHY_ID_BCM7439_2 0xae025080 | 30 | #define PHY_ID_BCM7439_2 0xae025080 |
31 | #define PHY_ID_BCM7445 0x600d8510 | 31 | #define PHY_ID_BCM7445 0x600d8510 |
32 | 32 | ||
33 | #define PHY_ID_BCM_CYGNUS 0xae025200 | ||
34 | |||
33 | #define PHY_BCM_OUI_MASK 0xfffffc00 | 35 | #define PHY_BCM_OUI_MASK 0xfffffc00 |
34 | #define PHY_BCM_OUI_1 0x00206000 | 36 | #define PHY_BCM_OUI_1 0x00206000 |
35 | #define PHY_BCM_OUI_2 0x0143bc00 | 37 | #define PHY_BCM_OUI_2 0x0143bc00 |
@@ -216,4 +218,9 @@ | |||
216 | #define LPI_FEATURE_EN 0x8000 | 218 | #define LPI_FEATURE_EN 0x8000 |
217 | #define LPI_FEATURE_EN_DIG1000X 0x4000 | 219 | #define LPI_FEATURE_EN_DIG1000X 0x4000 |
218 | 220 | ||
221 | /* Core register definitions*/ | ||
222 | #define MII_BRCM_CORE_BASE1E 0x1E | ||
223 | #define MII_BRCM_CORE_EXPB0 0xB0 | ||
224 | #define MII_BRCM_CORE_EXPB1 0xB1 | ||
225 | |||
219 | #endif /* _LINUX_BRCMPHY_H */ | 226 | #endif /* _LINUX_BRCMPHY_H */ |