summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArun Parameswaran <arunp@broadcom.com>2015-10-06 15:25:49 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-08 07:45:52 -0400
commit8e185d6997bb67068f0ca8f062a50caa2608cf1b (patch)
treeb2d42099f3777dc770023566cfd8d1dc3f1cc761
parenta1cba5613edf50c2a213fa90c30aa10500b241b7 (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/Kconfig13
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/bcm-cygnus.c158
-rw-r--r--include/linux/brcmphy.h7
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
82config 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
82config BCM63XX_PHY 95config 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
17obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o 17obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
18obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o 18obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o
19obj-$(CONFIG_BCM87XX_PHY) += bcm87xx.o 19obj-$(CONFIG_BCM87XX_PHY) += bcm87xx.o
20obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o
20obj-$(CONFIG_ICPLUS_PHY) += icplus.o 21obj-$(CONFIG_ICPLUS_PHY) += icplus.o
21obj-$(CONFIG_REALTEK_PHY) += realtek.o 22obj-$(CONFIG_REALTEK_PHY) += realtek.o
22obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o 23obj-$(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
24static 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
79static 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
115static 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
132static 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
148static struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = {
149 { PHY_ID_BCM_CYGNUS, 0xfffffff0, },
150 { }
151};
152MODULE_DEVICE_TABLE(mdio, bcm_cygnus_phy_tbl);
153
154module_phy_driver(bcm_cygnus_phy_driver);
155
156MODULE_DESCRIPTION("Broadcom Cygnus internal PHY driver");
157MODULE_LICENSE("GPL v2");
158MODULE_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 */