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

Configure Feed

Select the types of activity you want to include in your feed.

net: phy: mxl-gpy: add support for MxL86252 and MxL86282

Add PHY driver support for Maxlinear MxL86252 and MxL86282 switches.
The PHYs built-into those switches are just like any other GPY 2.5G PHYs
with the exception of the temperature sensor data being encoded in a
different way.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/a6cd7fe461b011cec2b59dffaf34e9c8b0819059.1763818120.git.daniel@makrotopia.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Daniel Golle and committed by
Jakub Kicinski
de1e5c93 9d844da6

+89 -2
+89 -2
drivers/net/phy/mxl-gpy.c
··· 31 31 #define PHY_ID_GPY241BM 0x67C9DE80 32 32 #define PHY_ID_GPY245B 0x67C9DEC0 33 33 #define PHY_ID_MXL86211C 0xC1335400 34 + #define PHY_ID_MXL86252 0xC1335520 35 + #define PHY_ID_MXL86282 0xC1335500 34 36 35 37 #define PHY_CTL1 0x13 36 38 #define PHY_CTL1_MDICD BIT(3) ··· 202 200 return 0; 203 201 } 204 202 203 + static int mxl862x2_hwmon_read(struct device *dev, 204 + enum hwmon_sensor_types type, 205 + u32 attr, int channel, long *value) 206 + { 207 + struct phy_device *phydev = dev_get_drvdata(dev); 208 + long tmp; 209 + int ret; 210 + 211 + ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_TEMP_STA); 212 + if (ret < 0) 213 + return ret; 214 + if (!ret) 215 + return -ENODATA; 216 + 217 + tmp = (s16)ret; 218 + tmp *= 78125; 219 + tmp /= 10000; 220 + 221 + *value = tmp; 222 + 223 + return 0; 224 + } 225 + 205 226 static umode_t gpy_hwmon_is_visible(const void *data, 206 227 enum hwmon_sensor_types type, 207 228 u32 attr, int channel) ··· 242 217 .read = gpy_hwmon_read, 243 218 }; 244 219 220 + static const struct hwmon_ops mxl862x2_hwmon_hwmon_ops = { 221 + .is_visible = gpy_hwmon_is_visible, 222 + .read = mxl862x2_hwmon_read, 223 + }; 224 + 245 225 static const struct hwmon_chip_info gpy_hwmon_chip_info = { 246 226 .ops = &gpy_hwmon_hwmon_ops, 227 + .info = gpy_hwmon_info, 228 + }; 229 + 230 + static const struct hwmon_chip_info mxl862x2_hwmon_chip_info = { 231 + .ops = &mxl862x2_hwmon_hwmon_ops, 247 232 .info = gpy_hwmon_info, 248 233 }; 249 234 250 235 static int gpy_hwmon_register(struct phy_device *phydev) 251 236 { 252 237 struct device *dev = &phydev->mdio.dev; 238 + const struct hwmon_chip_info *info; 253 239 struct device *hwmon_dev; 254 240 241 + if (phy_id_compare_model(phydev->phy_id, PHY_ID_MXL86252) || 242 + phy_id_compare_model(phydev->phy_id, PHY_ID_MXL86282)) 243 + info = &mxl862x2_hwmon_chip_info; 244 + else 245 + info = &gpy_hwmon_chip_info; 246 + 255 247 hwmon_dev = devm_hwmon_device_register_with_info(dev, NULL, phydev, 256 - &gpy_hwmon_chip_info, 257 - NULL); 248 + info, NULL); 258 249 259 250 return PTR_ERR_OR_ZERO(hwmon_dev); 260 251 } ··· 1332 1291 .led_hw_control_set = gpy_led_hw_control_set, 1333 1292 .led_polarity_set = gpy_led_polarity_set, 1334 1293 }, 1294 + { 1295 + PHY_ID_MATCH_MODEL(PHY_ID_MXL86252), 1296 + .name = "MaxLinear Ethernet MxL86252", 1297 + .get_features = genphy_c45_pma_read_abilities, 1298 + .config_init = gpy_config_init, 1299 + .probe = gpy_probe, 1300 + .suspend = genphy_suspend, 1301 + .resume = genphy_resume, 1302 + .config_aneg = gpy_config_aneg, 1303 + .aneg_done = genphy_c45_aneg_done, 1304 + .read_status = gpy_read_status, 1305 + .config_intr = gpy_config_intr, 1306 + .handle_interrupt = gpy_handle_interrupt, 1307 + .set_wol = gpy_set_wol, 1308 + .get_wol = gpy_get_wol, 1309 + .set_loopback = gpy_loopback, 1310 + .led_brightness_set = gpy_led_brightness_set, 1311 + .led_hw_is_supported = gpy_led_hw_is_supported, 1312 + .led_hw_control_get = gpy_led_hw_control_get, 1313 + .led_hw_control_set = gpy_led_hw_control_set, 1314 + .led_polarity_set = gpy_led_polarity_set, 1315 + }, 1316 + { 1317 + PHY_ID_MATCH_MODEL(PHY_ID_MXL86282), 1318 + .name = "MaxLinear Ethernet MxL86282", 1319 + .get_features = genphy_c45_pma_read_abilities, 1320 + .config_init = gpy_config_init, 1321 + .probe = gpy_probe, 1322 + .suspend = genphy_suspend, 1323 + .resume = genphy_resume, 1324 + .config_aneg = gpy_config_aneg, 1325 + .aneg_done = genphy_c45_aneg_done, 1326 + .read_status = gpy_read_status, 1327 + .config_intr = gpy_config_intr, 1328 + .handle_interrupt = gpy_handle_interrupt, 1329 + .set_wol = gpy_set_wol, 1330 + .get_wol = gpy_get_wol, 1331 + .set_loopback = gpy_loopback, 1332 + .led_brightness_set = gpy_led_brightness_set, 1333 + .led_hw_is_supported = gpy_led_hw_is_supported, 1334 + .led_hw_control_get = gpy_led_hw_control_get, 1335 + .led_hw_control_set = gpy_led_hw_control_set, 1336 + .led_polarity_set = gpy_led_polarity_set, 1337 + }, 1335 1338 }; 1336 1339 module_phy_driver(gpy_drivers); 1337 1340 ··· 1393 1308 {PHY_ID_MATCH_MODEL(PHY_ID_GPY241BM)}, 1394 1309 {PHY_ID_MATCH_MODEL(PHY_ID_GPY245B)}, 1395 1310 {PHY_ID_MATCH_MODEL(PHY_ID_MXL86211C)}, 1311 + {PHY_ID_MATCH_MODEL(PHY_ID_MXL86252)}, 1312 + {PHY_ID_MATCH_MODEL(PHY_ID_MXL86282)}, 1396 1313 { } 1397 1314 }; 1398 1315 MODULE_DEVICE_TABLE(mdio, gpy_tbl);