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