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.

at v5.5-rc7 403 lines 9.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* NXP TJA1100 BroadRReach PHY driver 3 * 4 * Copyright (C) 2018 Marek Vasut <marex@denx.de> 5 */ 6#include <linux/delay.h> 7#include <linux/ethtool.h> 8#include <linux/kernel.h> 9#include <linux/mii.h> 10#include <linux/module.h> 11#include <linux/phy.h> 12#include <linux/hwmon.h> 13#include <linux/bitfield.h> 14 15#define PHY_ID_MASK 0xfffffff0 16#define PHY_ID_TJA1100 0x0180dc40 17#define PHY_ID_TJA1101 0x0180dd00 18 19#define MII_ECTRL 17 20#define MII_ECTRL_LINK_CONTROL BIT(15) 21#define MII_ECTRL_POWER_MODE_MASK GENMASK(14, 11) 22#define MII_ECTRL_POWER_MODE_NO_CHANGE (0x0 << 11) 23#define MII_ECTRL_POWER_MODE_NORMAL (0x3 << 11) 24#define MII_ECTRL_POWER_MODE_STANDBY (0xc << 11) 25#define MII_ECTRL_CONFIG_EN BIT(2) 26#define MII_ECTRL_WAKE_REQUEST BIT(0) 27 28#define MII_CFG1 18 29#define MII_CFG1_AUTO_OP BIT(14) 30#define MII_CFG1_SLEEP_CONFIRM BIT(6) 31#define MII_CFG1_LED_MODE_MASK GENMASK(5, 4) 32#define MII_CFG1_LED_MODE_LINKUP 0 33#define MII_CFG1_LED_ENABLE BIT(3) 34 35#define MII_CFG2 19 36#define MII_CFG2_SLEEP_REQUEST_TO GENMASK(1, 0) 37#define MII_CFG2_SLEEP_REQUEST_TO_16MS 0x3 38 39#define MII_INTSRC 21 40#define MII_INTSRC_TEMP_ERR BIT(1) 41#define MII_INTSRC_UV_ERR BIT(3) 42 43#define MII_COMMSTAT 23 44#define MII_COMMSTAT_LINK_UP BIT(15) 45 46#define MII_GENSTAT 24 47#define MII_GENSTAT_PLL_LOCKED BIT(14) 48 49#define MII_COMMCFG 27 50#define MII_COMMCFG_AUTO_OP BIT(15) 51 52struct tja11xx_priv { 53 char *hwmon_name; 54 struct device *hwmon_dev; 55}; 56 57struct tja11xx_phy_stats { 58 const char *string; 59 u8 reg; 60 u8 off; 61 u16 mask; 62}; 63 64static struct tja11xx_phy_stats tja11xx_hw_stats[] = { 65 { "phy_symbol_error_count", 20, 0, GENMASK(15, 0) }, 66 { "phy_polarity_detect", 25, 6, BIT(6) }, 67 { "phy_open_detect", 25, 7, BIT(7) }, 68 { "phy_short_detect", 25, 8, BIT(8) }, 69 { "phy_rem_rcvr_count", 26, 0, GENMASK(7, 0) }, 70 { "phy_loc_rcvr_count", 26, 8, GENMASK(15, 8) }, 71}; 72 73static int tja11xx_check(struct phy_device *phydev, u8 reg, u16 mask, u16 set) 74{ 75 int i, ret; 76 77 for (i = 0; i < 200; i++) { 78 ret = phy_read(phydev, reg); 79 if (ret < 0) 80 return ret; 81 82 if ((ret & mask) == set) 83 return 0; 84 85 usleep_range(100, 150); 86 } 87 88 return -ETIMEDOUT; 89} 90 91static int phy_modify_check(struct phy_device *phydev, u8 reg, 92 u16 mask, u16 set) 93{ 94 int ret; 95 96 ret = phy_modify(phydev, reg, mask, set); 97 if (ret) 98 return ret; 99 100 return tja11xx_check(phydev, reg, mask, set); 101} 102 103static int tja11xx_enable_reg_write(struct phy_device *phydev) 104{ 105 return phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_CONFIG_EN); 106} 107 108static int tja11xx_enable_link_control(struct phy_device *phydev) 109{ 110 return phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_LINK_CONTROL); 111} 112 113static int tja11xx_wakeup(struct phy_device *phydev) 114{ 115 int ret; 116 117 ret = phy_read(phydev, MII_ECTRL); 118 if (ret < 0) 119 return ret; 120 121 switch (ret & MII_ECTRL_POWER_MODE_MASK) { 122 case MII_ECTRL_POWER_MODE_NO_CHANGE: 123 break; 124 case MII_ECTRL_POWER_MODE_NORMAL: 125 ret = phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_WAKE_REQUEST); 126 if (ret) 127 return ret; 128 129 ret = phy_clear_bits(phydev, MII_ECTRL, MII_ECTRL_WAKE_REQUEST); 130 if (ret) 131 return ret; 132 break; 133 case MII_ECTRL_POWER_MODE_STANDBY: 134 ret = phy_modify_check(phydev, MII_ECTRL, 135 MII_ECTRL_POWER_MODE_MASK, 136 MII_ECTRL_POWER_MODE_STANDBY); 137 if (ret) 138 return ret; 139 140 ret = phy_modify(phydev, MII_ECTRL, MII_ECTRL_POWER_MODE_MASK, 141 MII_ECTRL_POWER_MODE_NORMAL); 142 if (ret) 143 return ret; 144 145 ret = phy_modify_check(phydev, MII_GENSTAT, 146 MII_GENSTAT_PLL_LOCKED, 147 MII_GENSTAT_PLL_LOCKED); 148 if (ret) 149 return ret; 150 151 return tja11xx_enable_link_control(phydev); 152 default: 153 break; 154 } 155 156 return 0; 157} 158 159static int tja11xx_soft_reset(struct phy_device *phydev) 160{ 161 int ret; 162 163 ret = tja11xx_enable_reg_write(phydev); 164 if (ret) 165 return ret; 166 167 return genphy_soft_reset(phydev); 168} 169 170static int tja11xx_config_init(struct phy_device *phydev) 171{ 172 int ret; 173 174 ret = tja11xx_enable_reg_write(phydev); 175 if (ret) 176 return ret; 177 178 phydev->autoneg = AUTONEG_DISABLE; 179 phydev->speed = SPEED_100; 180 phydev->duplex = DUPLEX_FULL; 181 182 switch (phydev->phy_id & PHY_ID_MASK) { 183 case PHY_ID_TJA1100: 184 ret = phy_modify(phydev, MII_CFG1, 185 MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_MASK | 186 MII_CFG1_LED_ENABLE, 187 MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_LINKUP | 188 MII_CFG1_LED_ENABLE); 189 if (ret) 190 return ret; 191 break; 192 case PHY_ID_TJA1101: 193 ret = phy_set_bits(phydev, MII_COMMCFG, MII_COMMCFG_AUTO_OP); 194 if (ret) 195 return ret; 196 break; 197 default: 198 return -EINVAL; 199 } 200 201 ret = phy_clear_bits(phydev, MII_CFG1, MII_CFG1_SLEEP_CONFIRM); 202 if (ret) 203 return ret; 204 205 ret = phy_modify(phydev, MII_CFG2, MII_CFG2_SLEEP_REQUEST_TO, 206 MII_CFG2_SLEEP_REQUEST_TO_16MS); 207 if (ret) 208 return ret; 209 210 ret = tja11xx_wakeup(phydev); 211 if (ret < 0) 212 return ret; 213 214 /* ACK interrupts by reading the status register */ 215 ret = phy_read(phydev, MII_INTSRC); 216 if (ret < 0) 217 return ret; 218 219 return 0; 220} 221 222static int tja11xx_read_status(struct phy_device *phydev) 223{ 224 int ret; 225 226 ret = genphy_update_link(phydev); 227 if (ret) 228 return ret; 229 230 if (phydev->link) { 231 ret = phy_read(phydev, MII_COMMSTAT); 232 if (ret < 0) 233 return ret; 234 235 if (!(ret & MII_COMMSTAT_LINK_UP)) 236 phydev->link = 0; 237 } 238 239 return 0; 240} 241 242static int tja11xx_get_sset_count(struct phy_device *phydev) 243{ 244 return ARRAY_SIZE(tja11xx_hw_stats); 245} 246 247static void tja11xx_get_strings(struct phy_device *phydev, u8 *data) 248{ 249 int i; 250 251 for (i = 0; i < ARRAY_SIZE(tja11xx_hw_stats); i++) { 252 strncpy(data + i * ETH_GSTRING_LEN, 253 tja11xx_hw_stats[i].string, ETH_GSTRING_LEN); 254 } 255} 256 257static void tja11xx_get_stats(struct phy_device *phydev, 258 struct ethtool_stats *stats, u64 *data) 259{ 260 int i, ret; 261 262 for (i = 0; i < ARRAY_SIZE(tja11xx_hw_stats); i++) { 263 ret = phy_read(phydev, tja11xx_hw_stats[i].reg); 264 if (ret < 0) 265 data[i] = U64_MAX; 266 else { 267 data[i] = ret & tja11xx_hw_stats[i].mask; 268 data[i] >>= tja11xx_hw_stats[i].off; 269 } 270 } 271} 272 273static int tja11xx_hwmon_read(struct device *dev, 274 enum hwmon_sensor_types type, 275 u32 attr, int channel, long *value) 276{ 277 struct phy_device *phydev = dev_get_drvdata(dev); 278 int ret; 279 280 if (type == hwmon_in && attr == hwmon_in_lcrit_alarm) { 281 ret = phy_read(phydev, MII_INTSRC); 282 if (ret < 0) 283 return ret; 284 285 *value = !!(ret & MII_INTSRC_TEMP_ERR); 286 return 0; 287 } 288 289 if (type == hwmon_temp && attr == hwmon_temp_crit_alarm) { 290 ret = phy_read(phydev, MII_INTSRC); 291 if (ret < 0) 292 return ret; 293 294 *value = !!(ret & MII_INTSRC_UV_ERR); 295 return 0; 296 } 297 298 return -EOPNOTSUPP; 299} 300 301static umode_t tja11xx_hwmon_is_visible(const void *data, 302 enum hwmon_sensor_types type, 303 u32 attr, int channel) 304{ 305 if (type == hwmon_in && attr == hwmon_in_lcrit_alarm) 306 return 0444; 307 308 if (type == hwmon_temp && attr == hwmon_temp_crit_alarm) 309 return 0444; 310 311 return 0; 312} 313 314static const struct hwmon_channel_info *tja11xx_hwmon_info[] = { 315 HWMON_CHANNEL_INFO(in, HWMON_I_LCRIT_ALARM), 316 HWMON_CHANNEL_INFO(temp, HWMON_T_CRIT_ALARM), 317 NULL 318}; 319 320static const struct hwmon_ops tja11xx_hwmon_hwmon_ops = { 321 .is_visible = tja11xx_hwmon_is_visible, 322 .read = tja11xx_hwmon_read, 323}; 324 325static const struct hwmon_chip_info tja11xx_hwmon_chip_info = { 326 .ops = &tja11xx_hwmon_hwmon_ops, 327 .info = tja11xx_hwmon_info, 328}; 329 330static int tja11xx_probe(struct phy_device *phydev) 331{ 332 struct device *dev = &phydev->mdio.dev; 333 struct tja11xx_priv *priv; 334 int i; 335 336 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 337 if (!priv) 338 return -ENOMEM; 339 340 priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); 341 if (!priv->hwmon_name) 342 return -ENOMEM; 343 344 for (i = 0; priv->hwmon_name[i]; i++) 345 if (hwmon_is_bad_char(priv->hwmon_name[i])) 346 priv->hwmon_name[i] = '_'; 347 348 priv->hwmon_dev = 349 devm_hwmon_device_register_with_info(dev, priv->hwmon_name, 350 phydev, 351 &tja11xx_hwmon_chip_info, 352 NULL); 353 354 return PTR_ERR_OR_ZERO(priv->hwmon_dev); 355} 356 357static struct phy_driver tja11xx_driver[] = { 358 { 359 PHY_ID_MATCH_MODEL(PHY_ID_TJA1100), 360 .name = "NXP TJA1100", 361 .features = PHY_BASIC_T1_FEATURES, 362 .probe = tja11xx_probe, 363 .soft_reset = tja11xx_soft_reset, 364 .config_init = tja11xx_config_init, 365 .read_status = tja11xx_read_status, 366 .suspend = genphy_suspend, 367 .resume = genphy_resume, 368 .set_loopback = genphy_loopback, 369 /* Statistics */ 370 .get_sset_count = tja11xx_get_sset_count, 371 .get_strings = tja11xx_get_strings, 372 .get_stats = tja11xx_get_stats, 373 }, { 374 PHY_ID_MATCH_MODEL(PHY_ID_TJA1101), 375 .name = "NXP TJA1101", 376 .features = PHY_BASIC_T1_FEATURES, 377 .probe = tja11xx_probe, 378 .soft_reset = tja11xx_soft_reset, 379 .config_init = tja11xx_config_init, 380 .read_status = tja11xx_read_status, 381 .suspend = genphy_suspend, 382 .resume = genphy_resume, 383 .set_loopback = genphy_loopback, 384 /* Statistics */ 385 .get_sset_count = tja11xx_get_sset_count, 386 .get_strings = tja11xx_get_strings, 387 .get_stats = tja11xx_get_stats, 388 } 389}; 390 391module_phy_driver(tja11xx_driver); 392 393static struct mdio_device_id __maybe_unused tja11xx_tbl[] = { 394 { PHY_ID_MATCH_MODEL(PHY_ID_TJA1100) }, 395 { PHY_ID_MATCH_MODEL(PHY_ID_TJA1101) }, 396 { } 397}; 398 399MODULE_DEVICE_TABLE(mdio, tja11xx_tbl); 400 401MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); 402MODULE_DESCRIPTION("NXP TJA11xx BoardR-Reach PHY driver"); 403MODULE_LICENSE("GPL");