1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include <linux/phy.h> 4 #include <linux/module.h> 5 6 #include "qcom.h" 7 8 #define AT803X_DEBUG_REG_3C 0x3C 9 10 #define AT803X_DEBUG_REG_GREEN 0x3D 11 #define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) 12 13 #define MDIO_AZ_DEBUG 0x800D 14 15 #define QCA8327_A_PHY_ID 0x004dd033 16 #define QCA8327_B_PHY_ID 0x004dd034 17 #define QCA8337_PHY_ID 0x004dd036 18 19 #define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) 20 21 static struct at803x_hw_stat qca83xx_hw_stats[] = { 22 { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, 23 { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, 24 { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, 25 }; 26 27 struct qca83xx_priv { 28 u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; 29 }; 30 31 MODULE_DESCRIPTION("Qualcomm Atheros QCA83XX PHY driver"); 32 MODULE_AUTHOR("Matus Ujhelyi"); 33 MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>"); 34 MODULE_LICENSE("GPL"); 35 36 static int qca83xx_get_sset_count(struct phy_device *phydev) 37 { 38 return ARRAY_SIZE(qca83xx_hw_stats); 39 } 40 41 static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) 42 { 43 int i; 44 45 for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { 46 strscpy(data + i * ETH_GSTRING_LEN, 47 qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); 48 } 49 } 50 51 static u64 qca83xx_get_stat(struct phy_device *phydev, int i) 52 { 53 struct at803x_hw_stat stat = qca83xx_hw_stats[i]; 54 struct qca83xx_priv *priv = phydev->priv; 55 int val; 56 u64 ret; 57 58 if (stat.access_type == MMD) 59 val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); 60 else 61 val = phy_read(phydev, stat.reg); 62 63 if (val < 0) { 64 ret = U64_MAX; 65 } else { 66 val = val & stat.mask; 67 priv->stats[i] += val; 68 ret = priv->stats[i]; 69 } 70 71 return ret; 72 } 73 74 static void qca83xx_get_stats(struct phy_device *phydev, 75 struct ethtool_stats *stats, u64 *data) 76 { 77 int i; 78 79 for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) 80 data[i] = qca83xx_get_stat(phydev, i); 81 } 82 83 static int qca83xx_probe(struct phy_device *phydev) 84 { 85 struct device *dev = &phydev->mdio.dev; 86 struct qca83xx_priv *priv; 87 88 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 89 if (!priv) 90 return -ENOMEM; 91 92 phydev->priv = priv; 93 94 return 0; 95 } 96 97 static int qca83xx_config_init(struct phy_device *phydev) 98 { 99 u8 switch_revision; 100 101 switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; 102 103 switch (switch_revision) { 104 case 1: 105 /* For 100M waveform */ 106 at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); 107 /* Turn on Gigabit clock */ 108 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); 109 break; 110 111 case 2: 112 phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); 113 fallthrough; 114 case 4: 115 phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); 116 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); 117 at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); 118 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); 119 break; 120 } 121 122 /* Following original QCA sourcecode set port to prefer master */ 123 phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); 124 125 return 0; 126 } 127 128 static int qca8327_config_init(struct phy_device *phydev) 129 { 130 /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. 131 * Disable on init and enable only with 100m speed following 132 * qca original source code. 133 */ 134 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 135 QCA8327_DEBUG_MANU_CTRL_EN, 0); 136 137 return qca83xx_config_init(phydev); 138 } 139 140 static void qca83xx_link_change_notify(struct phy_device *phydev) 141 { 142 /* Set DAC Amplitude adjustment to +6% for 100m on link running */ 143 if (phydev->state == PHY_RUNNING) { 144 if (phydev->speed == SPEED_100) 145 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 146 QCA8327_DEBUG_MANU_CTRL_EN, 147 QCA8327_DEBUG_MANU_CTRL_EN); 148 } else { 149 /* Reset DAC Amplitude adjustment */ 150 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 151 QCA8327_DEBUG_MANU_CTRL_EN, 0); 152 } 153 } 154 155 static int qca83xx_resume(struct phy_device *phydev) 156 { 157 int ret, val; 158 159 /* Skip reset if not suspended */ 160 if (!phydev->suspended) 161 return 0; 162 163 /* Reinit the port, reset values set by suspend */ 164 qca83xx_config_init(phydev); 165 166 /* Reset the port on port resume */ 167 phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); 168 169 /* On resume from suspend the switch execute a reset and 170 * restart auto-negotiation. Wait for reset to complete. 171 */ 172 ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), 173 50000, 600000, true); 174 if (ret) 175 return ret; 176 177 usleep_range(1000, 2000); 178 179 return 0; 180 } 181 182 static int qca83xx_suspend(struct phy_device *phydev) 183 { 184 at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, 185 AT803X_DEBUG_GATE_CLK_IN1000, 0); 186 187 at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, 188 AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | 189 AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); 190 191 return 0; 192 } 193 194 static int qca8337_suspend(struct phy_device *phydev) 195 { 196 /* Only QCA8337 support actual suspend. */ 197 genphy_suspend(phydev); 198 199 return qca83xx_suspend(phydev); 200 } 201 202 static int qca8327_suspend(struct phy_device *phydev) 203 { 204 u16 mask = 0; 205 206 /* QCA8327 cause port unreliability when phy suspend 207 * is set. 208 */ 209 mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); 210 phy_modify(phydev, MII_BMCR, mask, 0); 211 212 return qca83xx_suspend(phydev); 213 } 214 215 static struct phy_driver qca83xx_driver[] = { 216 { 217 /* QCA8337 */ 218 PHY_ID_MATCH_EXACT(QCA8337_PHY_ID), 219 .name = "Qualcomm Atheros 8337 internal PHY", 220 /* PHY_GBIT_FEATURES */ 221 .probe = qca83xx_probe, 222 .flags = PHY_IS_INTERNAL, 223 .config_init = qca83xx_config_init, 224 .soft_reset = genphy_soft_reset, 225 .get_sset_count = qca83xx_get_sset_count, 226 .get_strings = qca83xx_get_strings, 227 .get_stats = qca83xx_get_stats, 228 .suspend = qca8337_suspend, 229 .resume = qca83xx_resume, 230 }, { 231 /* QCA8327-A from switch QCA8327-AL1A */ 232 PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID), 233 .name = "Qualcomm Atheros 8327-A internal PHY", 234 /* PHY_GBIT_FEATURES */ 235 .link_change_notify = qca83xx_link_change_notify, 236 .probe = qca83xx_probe, 237 .flags = PHY_IS_INTERNAL, 238 .config_init = qca8327_config_init, 239 .soft_reset = genphy_soft_reset, 240 .get_sset_count = qca83xx_get_sset_count, 241 .get_strings = qca83xx_get_strings, 242 .get_stats = qca83xx_get_stats, 243 .suspend = qca8327_suspend, 244 .resume = qca83xx_resume, 245 }, { 246 /* QCA8327-B from switch QCA8327-BL1A */ 247 PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID), 248 .name = "Qualcomm Atheros 8327-B internal PHY", 249 /* PHY_GBIT_FEATURES */ 250 .link_change_notify = qca83xx_link_change_notify, 251 .probe = qca83xx_probe, 252 .flags = PHY_IS_INTERNAL, 253 .config_init = qca8327_config_init, 254 .soft_reset = genphy_soft_reset, 255 .get_sset_count = qca83xx_get_sset_count, 256 .get_strings = qca83xx_get_strings, 257 .get_stats = qca83xx_get_stats, 258 .suspend = qca8327_suspend, 259 .resume = qca83xx_resume, 260 }, }; 261 262 module_phy_driver(qca83xx_driver); 263 264 static struct mdio_device_id __maybe_unused qca83xx_tbl[] = { 265 { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, 266 { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, 267 { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, 268 { } 269 }; 270 271 MODULE_DEVICE_TABLE(mdio, qca83xx_tbl); 272