Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Arun Parameswaran and committed by
David S. Miller
8e185d69 a1cba561

+179
+13
drivers/net/phy/Kconfig
··· 79 79 Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464, 80 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 95 config BCM63XX_PHY 83 96 tristate "Drivers for Broadcom 63xx SOCs internal PHY" 84 97 depends on BCM63XX
+1
drivers/net/phy/Makefile
··· 17 17 obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o 18 18 obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o 19 19 obj-$(CONFIG_BCM87XX_PHY) += bcm87xx.o 20 + obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o 20 21 obj-$(CONFIG_ICPLUS_PHY) += icplus.o 21 22 obj-$(CONFIG_REALTEK_PHY) += realtek.o 22 23 obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
+158
drivers/net/phy/bcm-cygnus.c
··· 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");
+7
include/linux/brcmphy.h
··· 30 30 #define PHY_ID_BCM7439_2 0xae025080 31 31 #define PHY_ID_BCM7445 0x600d8510 32 32 33 + #define PHY_ID_BCM_CYGNUS 0xae025200 34 + 33 35 #define PHY_BCM_OUI_MASK 0xfffffc00 34 36 #define PHY_BCM_OUI_1 0x00206000 35 37 #define PHY_BCM_OUI_2 0x0143bc00 ··· 217 215 #define BRCM_CL45VEN_EEE_CONTROL 0x803d 218 216 #define LPI_FEATURE_EN 0x8000 219 217 #define LPI_FEATURE_EN_DIG1000X 0x4000 218 + 219 + /* Core register definitions*/ 220 + #define MII_BRCM_CORE_BASE1E 0x1E 221 + #define MII_BRCM_CORE_EXPB0 0xB0 222 + #define MII_BRCM_CORE_EXPB1 0xB1 220 223 221 224 #endif /* _LINUX_BRCMPHY_H */