miiphyutil.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2001
  4. * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
  5. */
  6. /*
  7. * This provides a bit-banged interface to the ethernet MII management
  8. * channel.
  9. */
  10. #include <common.h>
  11. #include <dm.h>
  12. #include <log.h>
  13. #include <miiphy.h>
  14. #include <phy.h>
  15. #include <linux/delay.h>
  16. #include <asm/types.h>
  17. #include <linux/list.h>
  18. #include <malloc.h>
  19. #include <net.h>
  20. /* local debug macro */
  21. #undef MII_DEBUG
  22. #undef debug
  23. #ifdef MII_DEBUG
  24. #define debug(fmt, args...) printf(fmt, ##args)
  25. #else
  26. #define debug(fmt, args...)
  27. #endif /* MII_DEBUG */
  28. static struct list_head mii_devs;
  29. static struct mii_dev *current_mii;
  30. /*
  31. * Lookup the mii_dev struct by the registered device name.
  32. */
  33. struct mii_dev *miiphy_get_dev_by_name(const char *devname)
  34. {
  35. struct list_head *entry;
  36. struct mii_dev *dev;
  37. if (!devname) {
  38. printf("NULL device name!\n");
  39. return NULL;
  40. }
  41. list_for_each(entry, &mii_devs) {
  42. dev = list_entry(entry, struct mii_dev, link);
  43. if (strcmp(dev->name, devname) == 0)
  44. return dev;
  45. }
  46. return NULL;
  47. }
  48. /*****************************************************************************
  49. *
  50. * Initialize global data. Need to be called before any other miiphy routine.
  51. */
  52. void miiphy_init(void)
  53. {
  54. INIT_LIST_HEAD(&mii_devs);
  55. current_mii = NULL;
  56. }
  57. struct mii_dev *mdio_alloc(void)
  58. {
  59. struct mii_dev *bus;
  60. bus = malloc(sizeof(*bus));
  61. if (!bus)
  62. return bus;
  63. memset(bus, 0, sizeof(*bus));
  64. /* initalize mii_dev struct fields */
  65. INIT_LIST_HEAD(&bus->link);
  66. return bus;
  67. }
  68. void mdio_free(struct mii_dev *bus)
  69. {
  70. free(bus);
  71. }
  72. int mdio_register(struct mii_dev *bus)
  73. {
  74. if (!bus || !bus->read || !bus->write)
  75. return -1;
  76. /* check if we have unique name */
  77. if (miiphy_get_dev_by_name(bus->name)) {
  78. printf("mdio_register: non unique device name '%s'\n",
  79. bus->name);
  80. return -1;
  81. }
  82. /* add it to the list */
  83. list_add_tail(&bus->link, &mii_devs);
  84. if (!current_mii)
  85. current_mii = bus;
  86. return 0;
  87. }
  88. int mdio_register_seq(struct mii_dev *bus, int seq)
  89. {
  90. int ret;
  91. /* Setup a unique name for each mdio bus */
  92. ret = snprintf(bus->name, MDIO_NAME_LEN, "eth%d", seq);
  93. if (ret < 0)
  94. return ret;
  95. return mdio_register(bus);
  96. }
  97. int mdio_unregister(struct mii_dev *bus)
  98. {
  99. if (!bus)
  100. return 0;
  101. /* delete it from the list */
  102. list_del(&bus->link);
  103. if (current_mii == bus)
  104. current_mii = NULL;
  105. return 0;
  106. }
  107. void mdio_list_devices(void)
  108. {
  109. struct list_head *entry;
  110. list_for_each(entry, &mii_devs) {
  111. int i;
  112. struct mii_dev *bus = list_entry(entry, struct mii_dev, link);
  113. printf("%s:\n", bus->name);
  114. for (i = 0; i < PHY_MAX_ADDR; i++) {
  115. struct phy_device *phydev = bus->phymap[i];
  116. if (phydev) {
  117. printf("%x - %s", i, phydev->drv->name);
  118. if (phydev->dev)
  119. printf(" <--> %s\n", phydev->dev->name);
  120. else
  121. printf("\n");
  122. }
  123. }
  124. }
  125. }
  126. int miiphy_set_current_dev(const char *devname)
  127. {
  128. struct mii_dev *dev;
  129. dev = miiphy_get_dev_by_name(devname);
  130. if (dev) {
  131. current_mii = dev;
  132. return 0;
  133. }
  134. printf("No such device: %s\n", devname);
  135. return 1;
  136. }
  137. struct mii_dev *mdio_get_current_dev(void)
  138. {
  139. return current_mii;
  140. }
  141. struct list_head *mdio_get_list_head(void)
  142. {
  143. return &mii_devs;
  144. }
  145. struct phy_device *mdio_phydev_for_ethname(const char *ethname)
  146. {
  147. struct list_head *entry;
  148. struct mii_dev *bus;
  149. list_for_each(entry, &mii_devs) {
  150. int i;
  151. bus = list_entry(entry, struct mii_dev, link);
  152. for (i = 0; i < PHY_MAX_ADDR; i++) {
  153. if (!bus->phymap[i] || !bus->phymap[i]->dev)
  154. continue;
  155. if (strcmp(bus->phymap[i]->dev->name, ethname) == 0)
  156. return bus->phymap[i];
  157. }
  158. }
  159. printf("%s is not a known ethernet\n", ethname);
  160. return NULL;
  161. }
  162. const char *miiphy_get_current_dev(void)
  163. {
  164. if (current_mii)
  165. return current_mii->name;
  166. return NULL;
  167. }
  168. static struct mii_dev *miiphy_get_active_dev(const char *devname)
  169. {
  170. /* If the current mii is the one we want, return it */
  171. if (current_mii)
  172. if (strcmp(current_mii->name, devname) == 0)
  173. return current_mii;
  174. /* Otherwise, set the active one to the one we want */
  175. if (miiphy_set_current_dev(devname))
  176. return NULL;
  177. else
  178. return current_mii;
  179. }
  180. /*****************************************************************************
  181. *
  182. * Read to variable <value> from the PHY attached to device <devname>,
  183. * use PHY address <addr> and register <reg>.
  184. *
  185. * This API is deprecated. Use phy_read on a phy_device found via phy_connect
  186. *
  187. * Returns:
  188. * 0 on success
  189. */
  190. int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
  191. unsigned short *value)
  192. {
  193. struct mii_dev *bus;
  194. int ret;
  195. bus = miiphy_get_active_dev(devname);
  196. if (!bus)
  197. return 1;
  198. ret = bus->read(bus, addr, MDIO_DEVAD_NONE, reg);
  199. if (ret < 0)
  200. return 1;
  201. *value = (unsigned short)ret;
  202. return 0;
  203. }
  204. /*****************************************************************************
  205. *
  206. * Write <value> to the PHY attached to device <devname>,
  207. * use PHY address <addr> and register <reg>.
  208. *
  209. * This API is deprecated. Use phy_write on a phy_device found by phy_connect
  210. *
  211. * Returns:
  212. * 0 on success
  213. */
  214. int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
  215. unsigned short value)
  216. {
  217. struct mii_dev *bus;
  218. bus = miiphy_get_active_dev(devname);
  219. if (bus)
  220. return bus->write(bus, addr, MDIO_DEVAD_NONE, reg, value);
  221. return 1;
  222. }
  223. /*****************************************************************************
  224. *
  225. * Print out list of registered MII capable devices.
  226. */
  227. void miiphy_listdev(void)
  228. {
  229. struct list_head *entry;
  230. struct mii_dev *dev;
  231. puts("MII devices: ");
  232. list_for_each(entry, &mii_devs) {
  233. dev = list_entry(entry, struct mii_dev, link);
  234. printf("'%s' ", dev->name);
  235. }
  236. puts("\n");
  237. if (current_mii)
  238. printf("Current device: '%s'\n", current_mii->name);
  239. }
  240. /*****************************************************************************
  241. *
  242. * Read the OUI, manufacture's model number, and revision number.
  243. *
  244. * OUI: 22 bits (unsigned int)
  245. * Model: 6 bits (unsigned char)
  246. * Revision: 4 bits (unsigned char)
  247. *
  248. * This API is deprecated.
  249. *
  250. * Returns:
  251. * 0 on success
  252. */
  253. int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
  254. unsigned char *model, unsigned char *rev)
  255. {
  256. unsigned int reg = 0;
  257. unsigned short tmp;
  258. if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) {
  259. debug("PHY ID register 2 read failed\n");
  260. return -1;
  261. }
  262. reg = tmp;
  263. debug("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg);
  264. if (reg == 0xFFFF) {
  265. /* No physical device present at this address */
  266. return -1;
  267. }
  268. if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) {
  269. debug("PHY ID register 1 read failed\n");
  270. return -1;
  271. }
  272. reg |= tmp << 16;
  273. debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
  274. *oui = (reg >> 10);
  275. *model = (unsigned char)((reg >> 4) & 0x0000003F);
  276. *rev = (unsigned char)(reg & 0x0000000F);
  277. return 0;
  278. }
  279. #ifndef CONFIG_PHYLIB
  280. /*****************************************************************************
  281. *
  282. * Reset the PHY.
  283. *
  284. * This API is deprecated. Use PHYLIB.
  285. *
  286. * Returns:
  287. * 0 on success
  288. */
  289. int miiphy_reset(const char *devname, unsigned char addr)
  290. {
  291. unsigned short reg;
  292. int timeout = 500;
  293. if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
  294. debug("PHY status read failed\n");
  295. return -1;
  296. }
  297. if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
  298. debug("PHY reset failed\n");
  299. return -1;
  300. }
  301. #ifdef CONFIG_PHY_RESET_DELAY
  302. udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
  303. #endif
  304. /*
  305. * Poll the control register for the reset bit to go to 0 (it is
  306. * auto-clearing). This should happen within 0.5 seconds per the
  307. * IEEE spec.
  308. */
  309. reg = 0x8000;
  310. while (((reg & 0x8000) != 0) && timeout--) {
  311. if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
  312. debug("PHY status read failed\n");
  313. return -1;
  314. }
  315. udelay(1000);
  316. }
  317. if ((reg & 0x8000) == 0) {
  318. return 0;
  319. } else {
  320. puts("PHY reset timed out\n");
  321. return -1;
  322. }
  323. return 0;
  324. }
  325. #endif /* !PHYLIB */
  326. /*****************************************************************************
  327. *
  328. * Determine the ethernet speed (10/100/1000). Return 10 on error.
  329. */
  330. int miiphy_speed(const char *devname, unsigned char addr)
  331. {
  332. u16 bmcr, anlpar, adv;
  333. #if defined(CONFIG_PHY_GIGE)
  334. u16 btsr;
  335. /*
  336. * Check for 1000BASE-X. If it is supported, then assume that the speed
  337. * is 1000.
  338. */
  339. if (miiphy_is_1000base_x(devname, addr))
  340. return _1000BASET;
  341. /*
  342. * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
  343. */
  344. /* Check for 1000BASE-T. */
  345. if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
  346. printf("PHY 1000BT status");
  347. goto miiphy_read_failed;
  348. }
  349. if (btsr != 0xFFFF &&
  350. (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
  351. return _1000BASET;
  352. #endif /* CONFIG_PHY_GIGE */
  353. /* Check Basic Management Control Register first. */
  354. if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
  355. printf("PHY speed");
  356. goto miiphy_read_failed;
  357. }
  358. /* Check if auto-negotiation is on. */
  359. if (bmcr & BMCR_ANENABLE) {
  360. /* Get auto-negotiation results. */
  361. if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  362. printf("PHY AN speed");
  363. goto miiphy_read_failed;
  364. }
  365. if (miiphy_read(devname, addr, MII_ADVERTISE, &adv)) {
  366. puts("PHY AN adv speed");
  367. goto miiphy_read_failed;
  368. }
  369. return ((anlpar & adv) & LPA_100) ? _100BASET : _10BASET;
  370. }
  371. /* Get speed from basic control settings. */
  372. return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
  373. miiphy_read_failed:
  374. printf(" read failed, assuming 10BASE-T\n");
  375. return _10BASET;
  376. }
  377. /*****************************************************************************
  378. *
  379. * Determine full/half duplex. Return half on error.
  380. */
  381. int miiphy_duplex(const char *devname, unsigned char addr)
  382. {
  383. u16 bmcr, anlpar, adv;
  384. #if defined(CONFIG_PHY_GIGE)
  385. u16 btsr;
  386. /* Check for 1000BASE-X. */
  387. if (miiphy_is_1000base_x(devname, addr)) {
  388. /* 1000BASE-X */
  389. if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  390. printf("1000BASE-X PHY AN duplex");
  391. goto miiphy_read_failed;
  392. }
  393. }
  394. /*
  395. * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
  396. */
  397. /* Check for 1000BASE-T. */
  398. if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
  399. printf("PHY 1000BT status");
  400. goto miiphy_read_failed;
  401. }
  402. if (btsr != 0xFFFF) {
  403. if (btsr & PHY_1000BTSR_1000FD) {
  404. return FULL;
  405. } else if (btsr & PHY_1000BTSR_1000HD) {
  406. return HALF;
  407. }
  408. }
  409. #endif /* CONFIG_PHY_GIGE */
  410. /* Check Basic Management Control Register first. */
  411. if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
  412. puts("PHY duplex");
  413. goto miiphy_read_failed;
  414. }
  415. /* Check if auto-negotiation is on. */
  416. if (bmcr & BMCR_ANENABLE) {
  417. /* Get auto-negotiation results. */
  418. if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  419. puts("PHY AN duplex");
  420. goto miiphy_read_failed;
  421. }
  422. if (miiphy_read(devname, addr, MII_ADVERTISE, &adv)) {
  423. puts("PHY AN adv duplex");
  424. goto miiphy_read_failed;
  425. }
  426. return ((anlpar & adv) & (LPA_10FULL | LPA_100FULL)) ?
  427. FULL : HALF;
  428. }
  429. /* Get speed from basic control settings. */
  430. return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
  431. miiphy_read_failed:
  432. printf(" read failed, assuming half duplex\n");
  433. return HALF;
  434. }
  435. /*****************************************************************************
  436. *
  437. * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
  438. * 1000BASE-T, or on error.
  439. */
  440. int miiphy_is_1000base_x(const char *devname, unsigned char addr)
  441. {
  442. #if defined(CONFIG_PHY_GIGE)
  443. u16 exsr;
  444. if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
  445. printf("PHY extended status read failed, assuming no "
  446. "1000BASE-X\n");
  447. return 0;
  448. }
  449. return 0 != (exsr & (ESTATUS_1000XF | ESTATUS_1000XH));
  450. #else
  451. return 0;
  452. #endif
  453. }
  454. #ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
  455. /*****************************************************************************
  456. *
  457. * Determine link status
  458. */
  459. int miiphy_link(const char *devname, unsigned char addr)
  460. {
  461. unsigned short reg;
  462. /* dummy read; needed to latch some phys */
  463. (void)miiphy_read(devname, addr, MII_BMSR, &reg);
  464. if (miiphy_read(devname, addr, MII_BMSR, &reg)) {
  465. puts("MII_BMSR read failed, assuming no link\n");
  466. return 0;
  467. }
  468. /* Determine if a link is active */
  469. if ((reg & BMSR_LSTATUS) != 0) {
  470. return 1;
  471. } else {
  472. return 0;
  473. }
  474. }
  475. #endif