phy.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*
  35. * \verbatim
  36. * $Id: phy_drv.c 3143 2010-09-29 20:13:51Z Astralix $
  37. * \endverbatim
  38. */
  39. #include <cfg/os.h>
  40. #include <stdint.h>
  41. #include <string.h>
  42. #include <sys/heap.h>
  43. #include <sys/timer.h>
  44. #include <dev/phy.h>
  45. /* WARNING: Variadic macros are C99 and may fail with C89 compilers. */
  46. #ifdef NUTDEBUG
  47. #include <stdio.h>
  48. #define PHPRINTF(args,...) printf(args,##__VA_ARGS__); fflush(stdout);
  49. #else
  50. #define PHPRINTF(args,...)
  51. #endif
  52. /*
  53. * Basic Set Register Map:
  54. * This register map is valid for all manufactureres and chip.
  55. * Though some bits might not be supported.
  56. */
  57. #define PHY_BMCR 0x00 /* Basic Mode Control Register */
  58. #define PHY_BMSR 0x01 /* Basic Mode Status Register */
  59. #define PHY_ID1 0x02 /* OUI High Register */
  60. #define PHY_ID2 0x03 /* OUI Low Register */
  61. #define PHY_ANAR 0x04 /* Auto-Negotiation Ability Register */
  62. #define PHY_ANLP 0x05 /* Auto-Negotiation Link Partner Advertisement Register */
  63. #define PHY_ANER 0x06 /* Auto-Negotiation Expansion Register */
  64. #define PHY_ANTR 0x07 /* Auto-Negotiation Next Page TX Register */
  65. /*
  66. * Basic Mode Control Register Options
  67. */
  68. #define PHY_BMCR_RES 0x8000 /* 1: Reset PHY, flips to 0 if reset accomplished. */
  69. #define PHY_BMCR_LOOP 0x4000 /* 1: Enable Loopback Mode. */
  70. #define PHY_BMCR_SPEED 0x2000 /* 1: Manual Speed 100Mbit, 0: 10MBit). */
  71. #define PHY_BMCR_ANEG 0x1000 /* 1: Enable Auto-Negotiation. */
  72. #define PHY_BMCR_PDWN 0x0800 /* 1: Power Down Enabled. */
  73. #define PHY_BMCR_ISO 0x0400 /* 1: Isolate PHY from MII interface, only MDIO is still available. */
  74. #define PHY_BMCR_ANST 0x0200 /* 1: Restart Auto-Negotiation, flips to 0 if successfull. */
  75. #define PHY_BMCR_DUPX 0x0100 /* 1: Enable Full Duplex Operation. */
  76. #define PHYSET_COLTEST 0x0080 /* 1: Collision test enabled. */
  77. /*
  78. * Basic Mode Status Register Options
  79. */
  80. /* Chip capabilities */ /* (PR/O = fixed value, R/O read only */
  81. #define PHY_BMSR_CT4 0x8000 /* PR/O: Chip supports 100BASE-T4 mode */
  82. #define PHY_BMSR_C100FD 0x4000 /* PR/O: Chip supports 100BASE-TX Full Duplex mode */
  83. #define PHY_BMSR_C100HD 0x2000 /* PR/O: Chip supports 100BASE-TX Half Duplex mode */
  84. #define PHY_BMSR_C10FD 0x1000 /* PR/O: Chip supports 10BASE-TX Full Duplex mode */
  85. #define PHY_BMSR_C10HD 0x0800 /* PR/O: Chip supports 10BASE-TX Half Duplex mode */
  86. #define PHY_BMSR_CPRE 0x0040 /* PR/O: Chip supports MDIO preamble supression mode */
  87. #define PHY_BMSR_CANEG 0x0008 /* PR/O: Chip supports Auto-Negotiation */
  88. #define PHY_BMSR_CEXT 0x0001 /* PR/O: Chip supports extended MDIO registers */
  89. #define PHY_BMSR_CMSK 0xF849 /* Mask for chip capabilities */
  90. /* Chip status */
  91. #define PHY_BMSR_ANEG 0x0020 /* R/O: 1: Auto-Negotiation complete */
  92. #define PHY_BMSR_RFLT 0x0010 /* R/O: 1: Remote Fault (Partner cut us off) */
  93. #define PHY_BMSR_LNK 0x0004 /* R/O: 1: Link established */
  94. #define PHY_BMSR_JAB 0x0002 /* R/O: 1: Jabber condition detected */
  95. #define PHY_BMSR_SMSK 0x0036 /* Mask for chip status */
  96. #define phyw( reg, val) phydcb->mdiow( reg, val)
  97. #define phyr( reg) phydcb->mdior( reg)
  98. PHYDCB *phydcb = NULL;
  99. enum {
  100. PHY_BIT_DESCR_10M = 0,
  101. PHY_BIT_DESCR_100M,
  102. PHY_BIT_DESCR_1000M,
  103. PHY_BIT_DESCR_DUPLX,
  104. PHY_BIT_DESCR_POE,
  105. PHY_BIT_DESCR_MAX
  106. } phy_bit_descr_nr;
  107. typedef struct {
  108. uint8_t reg; /* register number */
  109. uint16_t mask; /* bit mask to identify what we are looking */
  110. } phy_bit_descr_t;
  111. typedef struct {
  112. uint32_t phy_oui; /* oui chip identifier */
  113. phy_bit_descr_t phy_bit_descr[PHY_BIT_DESCR_MAX];
  114. /* list of descriptors to identify where to get
  115. * [0] flag about 10Mbit/s speed
  116. * [1] flag about 100Mbit/s speed
  117. * [2] flag about 1000Mbit/s speed
  118. * [3] flag about full duplex
  119. * [4] flag about POE status */
  120. } phy_status_descr_t;
  121. phy_status_descr_t phy_status_descr[] = {
  122. /* Davicom DM9000 derivates */
  123. { DM9000, { {17, 0x3000}, {17, 0xC000}, {0, 0}, {17, 0xA000}, {0, 0} } },
  124. { DM9000A, { {17, 0x3000}, {17, 0xC000}, {0, 0}, {17, 0xA000}, {0, 0} } },
  125. { DM9000B, { {17, 0x3000}, {17, 0xC000}, {0, 0}, {17, 0xA000}, {0, 0} } },
  126. /* Davicom DM9161 derivates */
  127. { DM9161, { {17, 0x3000}, {17, 0xC000}, {0, 0}, {17, 0xA000}, {0, 0} } },
  128. /* DM9161A is the same as DM9000A and DM9161B is the same as DM9000B
  129. { DM9161A, { {17, 0x3000}, {17, 0xC000}, {0, 0}, {17, 0xA000}, {0, 0} } },
  130. { DM9161B, { {17, 0x3000}, {17, 0xC000}, {0, 0}, {17, 0xA000}, {0, 0} } },
  131. */
  132. /* SMSC LAN8700 derivates */
  133. { LAN8700, { {31, 0x0004}, {31, 0x0008}, {0, 0}, {31, 0x0010}, {0, 0} } },
  134. { LAN8700r4, { {31, 0x0004}, {31, 0x0008}, {0, 0}, {31, 0x0010}, {0, 0} } },
  135. { LAN8710, { {31, 0x0004}, {31, 0x0008}, {0, 0}, {31, 0x0010}, {0, 0} } },
  136. { LAN8720A, { {31, 0x0004}, {31, 0x0008}, {0, 0}, {31, 0x0010}, {0, 0} } },
  137. /* Micrel KS8721 */
  138. { KS8721, { {31, 0x0004}, {31, 0x0008}, {0, 0}, {31, 0x0010}, {0, 0} } },
  139. /* STM */
  140. { ST802RT1, { {0,0} , {17, 0x0200}, {0, 0}, {17, 0x0100}, {0, 0} } },
  141. /* NatSemi/TI DP83848 */
  142. // Table approach does not work as 10BASET and 100BASET
  143. // status share the same bit. Special treatment in NutPhyCtl required.
  144. { DP83848, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} } },
  145. };
  146. /*!
  147. * \brief Read PHY's Basic Mode Status Register
  148. *
  149. * \param None.
  150. *
  151. * \return 0 on fail or status register of PHY.
  152. */
  153. #define NutPhyGetStatus(void) phyr( PHY_BMSR))
  154. /*!
  155. * \brief Control PHY Options
  156. *
  157. * This function controls the physical layer chip.
  158. * Give
  159. *
  160. * \param ctl is the PHY option to control or test.
  161. * \param par Pointer to value of 1 to set, 0 to reset an option
  162. * or the return of a value test.
  163. * \return 0 on success, -1 on failure.
  164. */
  165. int NutPhyCtl( uint16_t ctl, uint32_t *par)
  166. {
  167. int rc = 0;
  168. uint16_t bmcr=0, bmsr=0;
  169. uint16_t p16 = (uint16_t)*par;
  170. uint8_t reg = (uint8_t)(*par>>16);
  171. PHPRINTF("NPCtl(0x%x, 0x%04x)\n", ctl, p16);
  172. /* Execute standard ioctl function */
  173. bmcr = phyr( PHY_BMCR);
  174. PHPRINTF(" bmcr=0x%04x\n", bmcr);
  175. switch (ctl)
  176. {
  177. case PHY_CTL_RESET:
  178. if (p16) {
  179. int wait = 0;
  180. /* Set Reset bit in BMCR register */
  181. phyw( PHY_BMCR, PHY_BMCR_RES);
  182. /* Wait till reset bit flips back to 0 */
  183. while( (phyr( PHY_BMCR) & PHY_BMCR_RES) && wait<10) {
  184. NutDelay(100);
  185. wait++;
  186. }
  187. if(wait >= 10) {
  188. rc = -1;
  189. }
  190. }
  191. break;
  192. case PHY_CTL_LOOPBACK:
  193. if (p16) {
  194. bmcr |= PHY_BMCR_LOOP;
  195. } else {
  196. bmcr &= ~PHY_BMCR_LOOP;
  197. }
  198. phyw( PHY_BMCR, bmcr);
  199. break;
  200. case PHY_CTL_SPEED:
  201. if (p16 == 100) {
  202. bmcr |= PHY_BMCR_SPEED;
  203. phyw( PHY_BMCR, bmcr);
  204. } else
  205. if (p16==10) {
  206. bmcr &= ~PHY_BMCR_SPEED;
  207. phyw( PHY_BMCR, bmcr);
  208. } else {
  209. rc = -1;
  210. }
  211. break;
  212. case PHY_CTL_AUTONEG:
  213. if (p16) {
  214. bmcr |= PHY_BMCR_ANEG;
  215. } else {
  216. bmcr &= ~PHY_BMCR_ANEG;
  217. }
  218. phyw( PHY_BMCR, bmcr);
  219. break;
  220. case PHY_CTL_POWERDOWN:
  221. if (p16) {
  222. bmcr |= PHY_BMCR_PDWN;
  223. } else {
  224. bmcr &= ~PHY_BMCR_PDWN;
  225. }
  226. phyw( PHY_BMCR, bmcr);
  227. break;
  228. case PHY_CTL_ISOLATE:
  229. if (p16) {
  230. bmcr |= PHY_BMCR_ISO;
  231. } else {
  232. bmcr &= ~PHY_BMCR_ISO;
  233. }
  234. phyw( PHY_BMCR, bmcr);
  235. break;
  236. case PHY_CTL_DUPLEX:
  237. if (p16) {
  238. bmcr |= PHY_BMCR_DUPX;
  239. } else {
  240. bmcr &= ~PHY_BMCR_DUPX;
  241. }
  242. phyw( PHY_BMCR, bmcr);
  243. break;
  244. case PHY_CTL_AUTONEG_RE:
  245. if (p16) {
  246. bmcr |= PHY_BMCR_ANST;
  247. phyw (PHY_BMCR, bmcr);
  248. }
  249. break;
  250. case PHY_GET_LINK:
  251. *par = (uint32_t)(phyr(PHY_BMSR)&PHY_BMSR_LNK);
  252. break;
  253. case PHY_GET_STATUS:
  254. bmsr = phyr(PHY_BMSR);
  255. /* only return a value different to zero if link is true */
  256. if (bmsr & PHY_BMSR_LNK) {
  257. int count, length;
  258. *par = PHY_STATUS_HAS_LINK |
  259. ((bmsr & PHY_BMSR_ANEG) ? PHY_STATUS_AUTONEG_OK : 0);
  260. /* KS8721 needs different interpretation of bits */
  261. if (phydcb->oui == KS8721)
  262. {
  263. uint16_t tempreg;
  264. tempreg = phyr(0x1f);
  265. tempreg >>= 2;
  266. tempreg &= 0x7;
  267. switch (tempreg) {
  268. case 1: *par |= PHY_STATUS_10M; break;
  269. case 2: *par |= PHY_STATUS_100M; break;
  270. case 5: *par |= PHY_STATUS_10M | PHY_STATUS_FULLDUPLEX; break;
  271. case 6: *par |= PHY_STATUS_100M | PHY_STATUS_FULLDUPLEX; break;
  272. }
  273. }
  274. /* Same for the DP83848, table approach does not work as
  275. 10BASET and 100BASET status share the same bit */
  276. else if (phydcb->oui == DP83848)
  277. {
  278. uint16_t tempreg;
  279. tempreg = phyr(0x10);
  280. tempreg &= 0x7;
  281. switch (tempreg) {
  282. case 1: *par |= PHY_STATUS_100M; break;
  283. case 3: *par |= PHY_STATUS_10M; break;
  284. case 5: *par |= PHY_STATUS_100M | PHY_STATUS_FULLDUPLEX; break;
  285. case 7: *par |= PHY_STATUS_10M | PHY_STATUS_FULLDUPLEX; break;
  286. }
  287. }
  288. else
  289. {
  290. length = sizeof(phy_status_descr) / sizeof(phy_status_descr[0]);
  291. for(count=0; count<length; count++) {
  292. if(phy_status_descr[count].phy_oui == phydcb->oui) {
  293. break;
  294. }
  295. }
  296. if(count<length) {
  297. uint16_t tempreg;
  298. /* entry in table found */
  299. PHPRINTF(" Reading status of known phy\n");
  300. tempreg = phyr(phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_10M].reg);
  301. if(tempreg & phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_10M].mask) {
  302. *par |= PHY_STATUS_10M;
  303. }
  304. tempreg = phyr(phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_100M].reg);
  305. if(tempreg & phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_100M].mask) {
  306. *par |= PHY_STATUS_100M;
  307. }
  308. tempreg = phyr(phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_1000M].reg);
  309. if(tempreg & phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_1000M].mask) {
  310. *par |= PHY_STATUS_1000M;
  311. }
  312. tempreg = phyr(phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_DUPLX].reg);
  313. if(tempreg & phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_DUPLX].mask) {
  314. *par |= PHY_STATUS_FULLDUPLEX;
  315. }
  316. }
  317. else {
  318. *par |= PHY_STATUS_CON_UNKNOWN;
  319. }
  320. }
  321. }
  322. else {
  323. *par = 0;
  324. }
  325. break;
  326. case PHY_GET_POE: {
  327. int count, length;
  328. *par = 0;
  329. length = sizeof(phy_status_descr) / sizeof(phy_status_descr[0]);
  330. for(count=0; count<length; count++) {
  331. if(phy_status_descr[count].phy_oui == phydcb->oui) {
  332. break;
  333. }
  334. }
  335. if(count<length) {
  336. uint16_t tempreg;
  337. /* entry in table found */
  338. PHPRINTF(" Reading POE status of known phy\n");
  339. tempreg = phyr(phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_POE].reg);
  340. if(tempreg & phy_status_descr[count].phy_bit_descr[PHY_BIT_DESCR_POE].mask) {
  341. *par = 1;
  342. }
  343. }
  344. else {
  345. rc = -1;
  346. }
  347. break;
  348. } /* endof case PHY_GET_POE */
  349. case PHY_GET_REGVAL:
  350. *par = (uint32_t)phyr(reg);
  351. break;
  352. case PHY_SET_REGVAL:
  353. phyw( reg, p16);
  354. break;
  355. default:
  356. rc = -1;
  357. break;
  358. }
  359. PHPRINTF(" bmcr=0x%04x, rc=%d, par=%x\n", bmcr, rc, (unsigned int) *par);
  360. return rc;
  361. }
  362. /*!
  363. * \brief Register and initialize PHY communication.
  364. *
  365. * This function registers a PHY for use by an EMAC.
  366. * For communication tests, the function reads out the OUI and
  367. * Model/Revision registers of the PHY.
  368. *
  369. * \param mda id the PHY's address on the MDIO interface bus of the EMAC.
  370. * \param mdiow Function provided by EMAC driver to write PHY regisers.
  371. * \param mdior Function provided by EMAC driver to read PHY regisers.
  372. *
  373. * \return 0 on success, -1 on communication failure.
  374. */
  375. int NutRegisterPhy( uint8_t mda, void(*mdiow)(uint8_t, uint16_t), uint16_t(*mdior)(uint8_t))
  376. {
  377. uint16_t temp1 = 0, temp2 = 0;
  378. uint_fast16_t count, length = sizeof(phy_status_descr) / sizeof(phy_status_descr[0]);
  379. PHPRINTF("NRP(%u, %p, %p)\n", mda, mdiow, mdior);
  380. if (phydcb != NULL)
  381. {
  382. /* Phy is just registered */
  383. return 0;
  384. }
  385. if ((mdiow == NULL)||(mdior == NULL)) {
  386. /* PHY Access functions are not given */
  387. return -1;
  388. }
  389. phydcb = NutHeapAlloc( sizeof(PHYDCB));
  390. if (phydcb == NULL) {
  391. /* Not enough memory to register PHY */
  392. return -1;
  393. }
  394. phydcb->addr = mda;
  395. phydcb->mdiow = mdiow;
  396. phydcb->mdior = mdior;
  397. /* Get chip's OUI data */
  398. temp1 = phyr(PHY_ID1);
  399. temp2 = phyr(PHY_ID2);
  400. phydcb->oui = (((uint32_t)temp1<<16)|(uint32_t)temp2);
  401. /* Mask out revision bits */
  402. phydcb->oui &= ~OUIMSK_REV;
  403. for(count=0; count<length; count++) {
  404. if(phy_status_descr[count].phy_oui == phydcb->oui) {
  405. break;
  406. }
  407. }
  408. if(count>=length)
  409. PHPRINTF("Unknown tranceiver ");
  410. PHPRINTF("PHY OUI=0x%08lx\n", phydcb->oui);
  411. return 0;
  412. }