sungem_phy.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. /*
  2. * PHY drivers for the sungem ethernet driver.
  3. *
  4. * This file could be shared with other drivers.
  5. *
  6. * (c) 2002, Benjamin Herrenscmidt (benh@kernel.crashing.org)
  7. *
  8. * TODO:
  9. * - Implement WOL
  10. * - Add support for PHYs that provide an IRQ line
  11. * - Eventually moved the entire polling state machine in
  12. * there (out of the eth driver), so that it can easily be
  13. * skipped on PHYs that implement it in hardware.
  14. * - On LXT971 & BCM5201, Apple uses some chip specific regs
  15. * to read the link status. Figure out why and if it makes
  16. * sense to do the same (magic aneg ?)
  17. * - Apple has some additional power management code for some
  18. * Broadcom PHYs that they "hide" from the OpenSource version
  19. * of darwin, still need to reverse engineer that
  20. */
  21. #include <linux/config.h>
  22. #include <linux/module.h>
  23. #include <linux/kernel.h>
  24. #include <linux/sched.h>
  25. #include <linux/types.h>
  26. #include <linux/netdevice.h>
  27. #include <linux/etherdevice.h>
  28. #include <linux/mii.h>
  29. #include <linux/ethtool.h>
  30. #include <linux/delay.h>
  31. #ifdef CONFIG_PPC_PMAC
  32. #include <asm/prom.h>
  33. #endif
  34. #include "sungem_phy.h"
  35. /* Link modes of the BCM5400 PHY */
  36. static const int phy_BCM5400_link_table[8][3] = {
  37. { 0, 0, 0 }, /* No link */
  38. { 0, 0, 0 }, /* 10BT Half Duplex */
  39. { 1, 0, 0 }, /* 10BT Full Duplex */
  40. { 0, 1, 0 }, /* 100BT Half Duplex */
  41. { 0, 1, 0 }, /* 100BT Half Duplex */
  42. { 1, 1, 0 }, /* 100BT Full Duplex*/
  43. { 1, 0, 1 }, /* 1000BT */
  44. { 1, 0, 1 }, /* 1000BT */
  45. };
  46. static inline int __phy_read(struct mii_phy* phy, int id, int reg)
  47. {
  48. return phy->mdio_read(phy->dev, id, reg);
  49. }
  50. static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
  51. {
  52. phy->mdio_write(phy->dev, id, reg, val);
  53. }
  54. static inline int phy_read(struct mii_phy* phy, int reg)
  55. {
  56. return phy->mdio_read(phy->dev, phy->mii_id, reg);
  57. }
  58. static inline void phy_write(struct mii_phy* phy, int reg, int val)
  59. {
  60. phy->mdio_write(phy->dev, phy->mii_id, reg, val);
  61. }
  62. static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
  63. {
  64. u16 val;
  65. int limit = 10000;
  66. val = __phy_read(phy, phy_id, MII_BMCR);
  67. val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
  68. val |= BMCR_RESET;
  69. __phy_write(phy, phy_id, MII_BMCR, val);
  70. udelay(100);
  71. while (limit--) {
  72. val = __phy_read(phy, phy_id, MII_BMCR);
  73. if ((val & BMCR_RESET) == 0)
  74. break;
  75. udelay(10);
  76. }
  77. if ((val & BMCR_ISOLATE) && limit > 0)
  78. __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
  79. return (limit <= 0);
  80. }
  81. static int bcm5201_init(struct mii_phy* phy)
  82. {
  83. u16 data;
  84. data = phy_read(phy, MII_BCM5201_MULTIPHY);
  85. data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
  86. phy_write(phy, MII_BCM5201_MULTIPHY, data);
  87. phy_write(phy, MII_BCM5201_INTERRUPT, 0);
  88. return 0;
  89. }
  90. static int bcm5201_suspend(struct mii_phy* phy)
  91. {
  92. phy_write(phy, MII_BCM5201_INTERRUPT, 0);
  93. phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
  94. return 0;
  95. }
  96. static int bcm5221_init(struct mii_phy* phy)
  97. {
  98. u16 data;
  99. data = phy_read(phy, MII_BCM5221_TEST);
  100. phy_write(phy, MII_BCM5221_TEST,
  101. data | MII_BCM5221_TEST_ENABLE_SHADOWS);
  102. data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
  103. phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
  104. data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
  105. data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
  106. phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
  107. data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
  108. data = phy_read(phy, MII_BCM5221_TEST);
  109. phy_write(phy, MII_BCM5221_TEST,
  110. data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
  111. return 0;
  112. }
  113. static int bcm5221_suspend(struct mii_phy* phy)
  114. {
  115. u16 data;
  116. data = phy_read(phy, MII_BCM5221_TEST);
  117. phy_write(phy, MII_BCM5221_TEST,
  118. data | MII_BCM5221_TEST_ENABLE_SHADOWS);
  119. data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
  120. phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
  121. data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
  122. return 0;
  123. }
  124. static int bcm5400_init(struct mii_phy* phy)
  125. {
  126. u16 data;
  127. /* Configure for gigabit full duplex */
  128. data = phy_read(phy, MII_BCM5400_AUXCONTROL);
  129. data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
  130. phy_write(phy, MII_BCM5400_AUXCONTROL, data);
  131. data = phy_read(phy, MII_BCM5400_GB_CONTROL);
  132. data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
  133. phy_write(phy, MII_BCM5400_GB_CONTROL, data);
  134. udelay(100);
  135. /* Reset and configure cascaded 10/100 PHY */
  136. (void)reset_one_mii_phy(phy, 0x1f);
  137. data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
  138. data |= MII_BCM5201_MULTIPHY_SERIALMODE;
  139. __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
  140. data = phy_read(phy, MII_BCM5400_AUXCONTROL);
  141. data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
  142. phy_write(phy, MII_BCM5400_AUXCONTROL, data);
  143. return 0;
  144. }
  145. static int bcm5400_suspend(struct mii_phy* phy)
  146. {
  147. #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
  148. phy_write(phy, MII_BMCR, BMCR_PDOWN);
  149. #endif
  150. return 0;
  151. }
  152. static int bcm5401_init(struct mii_phy* phy)
  153. {
  154. u16 data;
  155. int rev;
  156. rev = phy_read(phy, MII_PHYSID2) & 0x000f;
  157. if (rev == 0 || rev == 3) {
  158. /* Some revisions of 5401 appear to need this
  159. * initialisation sequence to disable, according
  160. * to OF, "tap power management"
  161. *
  162. * WARNING ! OF and Darwin don't agree on the
  163. * register addresses. OF seem to interpret the
  164. * register numbers below as decimal
  165. *
  166. * Note: This should (and does) match tg3_init_5401phy_dsp
  167. * in the tg3.c driver. -DaveM
  168. */
  169. phy_write(phy, 0x18, 0x0c20);
  170. phy_write(phy, 0x17, 0x0012);
  171. phy_write(phy, 0x15, 0x1804);
  172. phy_write(phy, 0x17, 0x0013);
  173. phy_write(phy, 0x15, 0x1204);
  174. phy_write(phy, 0x17, 0x8006);
  175. phy_write(phy, 0x15, 0x0132);
  176. phy_write(phy, 0x17, 0x8006);
  177. phy_write(phy, 0x15, 0x0232);
  178. phy_write(phy, 0x17, 0x201f);
  179. phy_write(phy, 0x15, 0x0a20);
  180. }
  181. /* Configure for gigabit full duplex */
  182. data = phy_read(phy, MII_BCM5400_GB_CONTROL);
  183. data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
  184. phy_write(phy, MII_BCM5400_GB_CONTROL, data);
  185. udelay(10);
  186. /* Reset and configure cascaded 10/100 PHY */
  187. (void)reset_one_mii_phy(phy, 0x1f);
  188. data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
  189. data |= MII_BCM5201_MULTIPHY_SERIALMODE;
  190. __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
  191. return 0;
  192. }
  193. static int bcm5401_suspend(struct mii_phy* phy)
  194. {
  195. #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
  196. phy_write(phy, MII_BMCR, BMCR_PDOWN);
  197. #endif
  198. return 0;
  199. }
  200. static int bcm5411_init(struct mii_phy* phy)
  201. {
  202. u16 data;
  203. /* Here's some more Apple black magic to setup
  204. * some voltage stuffs.
  205. */
  206. phy_write(phy, 0x1c, 0x8c23);
  207. phy_write(phy, 0x1c, 0x8ca3);
  208. phy_write(phy, 0x1c, 0x8c23);
  209. /* Here, Apple seems to want to reset it, do
  210. * it as well
  211. */
  212. phy_write(phy, MII_BMCR, BMCR_RESET);
  213. phy_write(phy, MII_BMCR, 0x1340);
  214. data = phy_read(phy, MII_BCM5400_GB_CONTROL);
  215. data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
  216. phy_write(phy, MII_BCM5400_GB_CONTROL, data);
  217. udelay(10);
  218. /* Reset and configure cascaded 10/100 PHY */
  219. (void)reset_one_mii_phy(phy, 0x1f);
  220. return 0;
  221. }
  222. static int bcm5411_suspend(struct mii_phy* phy)
  223. {
  224. phy_write(phy, MII_BMCR, BMCR_PDOWN);
  225. return 0;
  226. }
  227. static int bcm5421_init(struct mii_phy* phy)
  228. {
  229. u16 data;
  230. unsigned int id;
  231. id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
  232. /* Revision 0 of 5421 needs some fixups */
  233. if (id == 0x002060e0) {
  234. /* This is borrowed from MacOS
  235. */
  236. phy_write(phy, 0x18, 0x1007);
  237. data = phy_read(phy, 0x18);
  238. phy_write(phy, 0x18, data | 0x0400);
  239. phy_write(phy, 0x18, 0x0007);
  240. data = phy_read(phy, 0x18);
  241. phy_write(phy, 0x18, data | 0x0800);
  242. phy_write(phy, 0x17, 0x000a);
  243. data = phy_read(phy, 0x15);
  244. phy_write(phy, 0x15, data | 0x0200);
  245. }
  246. /* Pick up some init code from OF for K2 version */
  247. if ((id & 0xfffffff0) == 0x002062e0) {
  248. phy_write(phy, 4, 0x01e1);
  249. phy_write(phy, 9, 0x0300);
  250. }
  251. /* Check if we can enable automatic low power */
  252. #ifdef CONFIG_PPC_PMAC
  253. if (phy->platform_data) {
  254. struct device_node *np = of_get_parent(phy->platform_data);
  255. int can_low_power = 1;
  256. if (np == NULL || get_property(np, "no-autolowpower", NULL))
  257. can_low_power = 0;
  258. if (can_low_power) {
  259. /* Enable automatic low-power */
  260. phy_write(phy, 0x1c, 0x9002);
  261. phy_write(phy, 0x1c, 0xa821);
  262. phy_write(phy, 0x1c, 0x941d);
  263. }
  264. }
  265. #endif /* CONFIG_PPC_PMAC */
  266. return 0;
  267. }
  268. static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
  269. {
  270. u16 ctl, adv;
  271. phy->autoneg = 1;
  272. phy->speed = SPEED_10;
  273. phy->duplex = DUPLEX_HALF;
  274. phy->pause = 0;
  275. phy->advertising = advertise;
  276. /* Setup standard advertise */
  277. adv = phy_read(phy, MII_ADVERTISE);
  278. adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
  279. if (advertise & ADVERTISED_10baseT_Half)
  280. adv |= ADVERTISE_10HALF;
  281. if (advertise & ADVERTISED_10baseT_Full)
  282. adv |= ADVERTISE_10FULL;
  283. if (advertise & ADVERTISED_100baseT_Half)
  284. adv |= ADVERTISE_100HALF;
  285. if (advertise & ADVERTISED_100baseT_Full)
  286. adv |= ADVERTISE_100FULL;
  287. phy_write(phy, MII_ADVERTISE, adv);
  288. /* Setup 1000BT advertise */
  289. adv = phy_read(phy, MII_1000BASETCONTROL);
  290. adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
  291. if (advertise & SUPPORTED_1000baseT_Half)
  292. adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
  293. if (advertise & SUPPORTED_1000baseT_Full)
  294. adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
  295. phy_write(phy, MII_1000BASETCONTROL, adv);
  296. /* Start/Restart aneg */
  297. ctl = phy_read(phy, MII_BMCR);
  298. ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
  299. phy_write(phy, MII_BMCR, ctl);
  300. return 0;
  301. }
  302. static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
  303. {
  304. u16 ctl;
  305. phy->autoneg = 0;
  306. phy->speed = speed;
  307. phy->duplex = fd;
  308. phy->pause = 0;
  309. ctl = phy_read(phy, MII_BMCR);
  310. ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
  311. /* First reset the PHY */
  312. phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
  313. /* Select speed & duplex */
  314. switch(speed) {
  315. case SPEED_10:
  316. break;
  317. case SPEED_100:
  318. ctl |= BMCR_SPEED100;
  319. break;
  320. case SPEED_1000:
  321. ctl |= BMCR_SPD2;
  322. }
  323. if (fd == DUPLEX_FULL)
  324. ctl |= BMCR_FULLDPLX;
  325. // XXX Should we set the sungem to GII now on 1000BT ?
  326. phy_write(phy, MII_BMCR, ctl);
  327. return 0;
  328. }
  329. static int bcm54xx_read_link(struct mii_phy *phy)
  330. {
  331. int link_mode;
  332. u16 val;
  333. if (phy->autoneg) {
  334. val = phy_read(phy, MII_BCM5400_AUXSTATUS);
  335. link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
  336. MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
  337. phy->duplex = phy_BCM5400_link_table[link_mode][0] ? DUPLEX_FULL : DUPLEX_HALF;
  338. phy->speed = phy_BCM5400_link_table[link_mode][2] ?
  339. SPEED_1000 :
  340. (phy_BCM5400_link_table[link_mode][1] ? SPEED_100 : SPEED_10);
  341. val = phy_read(phy, MII_LPA);
  342. phy->pause = ((val & LPA_PAUSE) != 0);
  343. }
  344. /* On non-aneg, we assume what we put in BMCR is the speed,
  345. * though magic-aneg shouldn't prevent this case from occurring
  346. */
  347. return 0;
  348. }
  349. static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
  350. {
  351. u16 ctl, adv;
  352. phy->autoneg = 1;
  353. phy->speed = SPEED_10;
  354. phy->duplex = DUPLEX_HALF;
  355. phy->pause = 0;
  356. phy->advertising = advertise;
  357. /* Setup standard advertise */
  358. adv = phy_read(phy, MII_ADVERTISE);
  359. adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
  360. if (advertise & ADVERTISED_10baseT_Half)
  361. adv |= ADVERTISE_10HALF;
  362. if (advertise & ADVERTISED_10baseT_Full)
  363. adv |= ADVERTISE_10FULL;
  364. if (advertise & ADVERTISED_100baseT_Half)
  365. adv |= ADVERTISE_100HALF;
  366. if (advertise & ADVERTISED_100baseT_Full)
  367. adv |= ADVERTISE_100FULL;
  368. phy_write(phy, MII_ADVERTISE, adv);
  369. /* Setup 1000BT advertise & enable crossover detect
  370. * XXX How do we advertise 1000BT ? Darwin source is
  371. * confusing here, they read from specific control and
  372. * write to control... Someone has specs for those
  373. * beasts ?
  374. */
  375. adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
  376. adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
  377. adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
  378. MII_1000BASETCONTROL_HALFDUPLEXCAP);
  379. if (advertise & SUPPORTED_1000baseT_Half)
  380. adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
  381. if (advertise & SUPPORTED_1000baseT_Full)
  382. adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
  383. phy_write(phy, MII_1000BASETCONTROL, adv);
  384. /* Start/Restart aneg */
  385. ctl = phy_read(phy, MII_BMCR);
  386. ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
  387. phy_write(phy, MII_BMCR, ctl);
  388. return 0;
  389. }
  390. static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
  391. {
  392. u16 ctl, ctl2;
  393. phy->autoneg = 0;
  394. phy->speed = speed;
  395. phy->duplex = fd;
  396. phy->pause = 0;
  397. ctl = phy_read(phy, MII_BMCR);
  398. ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
  399. ctl |= BMCR_RESET;
  400. /* Select speed & duplex */
  401. switch(speed) {
  402. case SPEED_10:
  403. break;
  404. case SPEED_100:
  405. ctl |= BMCR_SPEED100;
  406. break;
  407. /* I'm not sure about the one below, again, Darwin source is
  408. * quite confusing and I lack chip specs
  409. */
  410. case SPEED_1000:
  411. ctl |= BMCR_SPD2;
  412. }
  413. if (fd == DUPLEX_FULL)
  414. ctl |= BMCR_FULLDPLX;
  415. /* Disable crossover. Again, the way Apple does it is strange,
  416. * though I don't assume they are wrong ;)
  417. */
  418. ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
  419. ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
  420. MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
  421. MII_1000BASETCONTROL_FULLDUPLEXCAP |
  422. MII_1000BASETCONTROL_HALFDUPLEXCAP);
  423. if (speed == SPEED_1000)
  424. ctl2 |= (fd == DUPLEX_FULL) ?
  425. MII_1000BASETCONTROL_FULLDUPLEXCAP :
  426. MII_1000BASETCONTROL_HALFDUPLEXCAP;
  427. phy_write(phy, MII_1000BASETCONTROL, ctl2);
  428. // XXX Should we set the sungem to GII now on 1000BT ?
  429. phy_write(phy, MII_BMCR, ctl);
  430. return 0;
  431. }
  432. static int marvell_read_link(struct mii_phy *phy)
  433. {
  434. u16 status;
  435. if (phy->autoneg) {
  436. status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
  437. if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
  438. return -EAGAIN;
  439. if (status & MII_M1011_PHY_SPEC_STATUS_1000)
  440. phy->speed = SPEED_1000;
  441. else if (status & MII_M1011_PHY_SPEC_STATUS_100)
  442. phy->speed = SPEED_100;
  443. else
  444. phy->speed = SPEED_10;
  445. if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
  446. phy->duplex = DUPLEX_FULL;
  447. else
  448. phy->duplex = DUPLEX_HALF;
  449. phy->pause = 0; /* XXX Check against spec ! */
  450. }
  451. /* On non-aneg, we assume what we put in BMCR is the speed,
  452. * though magic-aneg shouldn't prevent this case from occurring
  453. */
  454. return 0;
  455. }
  456. static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
  457. {
  458. u16 ctl, adv;
  459. phy->autoneg = 1;
  460. phy->speed = SPEED_10;
  461. phy->duplex = DUPLEX_HALF;
  462. phy->pause = 0;
  463. phy->advertising = advertise;
  464. /* Setup standard advertise */
  465. adv = phy_read(phy, MII_ADVERTISE);
  466. adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
  467. if (advertise & ADVERTISED_10baseT_Half)
  468. adv |= ADVERTISE_10HALF;
  469. if (advertise & ADVERTISED_10baseT_Full)
  470. adv |= ADVERTISE_10FULL;
  471. if (advertise & ADVERTISED_100baseT_Half)
  472. adv |= ADVERTISE_100HALF;
  473. if (advertise & ADVERTISED_100baseT_Full)
  474. adv |= ADVERTISE_100FULL;
  475. phy_write(phy, MII_ADVERTISE, adv);
  476. /* Start/Restart aneg */
  477. ctl = phy_read(phy, MII_BMCR);
  478. ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
  479. phy_write(phy, MII_BMCR, ctl);
  480. return 0;
  481. }
  482. static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
  483. {
  484. u16 ctl;
  485. phy->autoneg = 0;
  486. phy->speed = speed;
  487. phy->duplex = fd;
  488. phy->pause = 0;
  489. ctl = phy_read(phy, MII_BMCR);
  490. ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
  491. /* First reset the PHY */
  492. phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
  493. /* Select speed & duplex */
  494. switch(speed) {
  495. case SPEED_10:
  496. break;
  497. case SPEED_100:
  498. ctl |= BMCR_SPEED100;
  499. break;
  500. case SPEED_1000:
  501. default:
  502. return -EINVAL;
  503. }
  504. if (fd == DUPLEX_FULL)
  505. ctl |= BMCR_FULLDPLX;
  506. phy_write(phy, MII_BMCR, ctl);
  507. return 0;
  508. }
  509. static int genmii_poll_link(struct mii_phy *phy)
  510. {
  511. u16 status;
  512. (void)phy_read(phy, MII_BMSR);
  513. status = phy_read(phy, MII_BMSR);
  514. if ((status & BMSR_LSTATUS) == 0)
  515. return 0;
  516. if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
  517. return 0;
  518. return 1;
  519. }
  520. static int genmii_read_link(struct mii_phy *phy)
  521. {
  522. u16 lpa;
  523. if (phy->autoneg) {
  524. lpa = phy_read(phy, MII_LPA);
  525. if (lpa & (LPA_10FULL | LPA_100FULL))
  526. phy->duplex = DUPLEX_FULL;
  527. else
  528. phy->duplex = DUPLEX_HALF;
  529. if (lpa & (LPA_100FULL | LPA_100HALF))
  530. phy->speed = SPEED_100;
  531. else
  532. phy->speed = SPEED_10;
  533. phy->pause = 0;
  534. }
  535. /* On non-aneg, we assume what we put in BMCR is the speed,
  536. * though magic-aneg shouldn't prevent this case from occurring
  537. */
  538. return 0;
  539. }
  540. #define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
  541. SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
  542. SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
  543. #define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
  544. SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
  545. /* Broadcom BCM 5201 */
  546. static struct mii_phy_ops bcm5201_phy_ops = {
  547. .init = bcm5201_init,
  548. .suspend = bcm5201_suspend,
  549. .setup_aneg = genmii_setup_aneg,
  550. .setup_forced = genmii_setup_forced,
  551. .poll_link = genmii_poll_link,
  552. .read_link = genmii_read_link,
  553. };
  554. static struct mii_phy_def bcm5201_phy_def = {
  555. .phy_id = 0x00406210,
  556. .phy_id_mask = 0xfffffff0,
  557. .name = "BCM5201",
  558. .features = MII_BASIC_FEATURES,
  559. .magic_aneg = 1,
  560. .ops = &bcm5201_phy_ops
  561. };
  562. /* Broadcom BCM 5221 */
  563. static struct mii_phy_ops bcm5221_phy_ops = {
  564. .suspend = bcm5221_suspend,
  565. .init = bcm5221_init,
  566. .setup_aneg = genmii_setup_aneg,
  567. .setup_forced = genmii_setup_forced,
  568. .poll_link = genmii_poll_link,
  569. .read_link = genmii_read_link,
  570. };
  571. static struct mii_phy_def bcm5221_phy_def = {
  572. .phy_id = 0x004061e0,
  573. .phy_id_mask = 0xfffffff0,
  574. .name = "BCM5221",
  575. .features = MII_BASIC_FEATURES,
  576. .magic_aneg = 1,
  577. .ops = &bcm5221_phy_ops
  578. };
  579. /* Broadcom BCM 5400 */
  580. static struct mii_phy_ops bcm5400_phy_ops = {
  581. .init = bcm5400_init,
  582. .suspend = bcm5400_suspend,
  583. .setup_aneg = bcm54xx_setup_aneg,
  584. .setup_forced = bcm54xx_setup_forced,
  585. .poll_link = genmii_poll_link,
  586. .read_link = bcm54xx_read_link,
  587. };
  588. static struct mii_phy_def bcm5400_phy_def = {
  589. .phy_id = 0x00206040,
  590. .phy_id_mask = 0xfffffff0,
  591. .name = "BCM5400",
  592. .features = MII_GBIT_FEATURES,
  593. .magic_aneg = 1,
  594. .ops = &bcm5400_phy_ops
  595. };
  596. /* Broadcom BCM 5401 */
  597. static struct mii_phy_ops bcm5401_phy_ops = {
  598. .init = bcm5401_init,
  599. .suspend = bcm5401_suspend,
  600. .setup_aneg = bcm54xx_setup_aneg,
  601. .setup_forced = bcm54xx_setup_forced,
  602. .poll_link = genmii_poll_link,
  603. .read_link = bcm54xx_read_link,
  604. };
  605. static struct mii_phy_def bcm5401_phy_def = {
  606. .phy_id = 0x00206050,
  607. .phy_id_mask = 0xfffffff0,
  608. .name = "BCM5401",
  609. .features = MII_GBIT_FEATURES,
  610. .magic_aneg = 1,
  611. .ops = &bcm5401_phy_ops
  612. };
  613. /* Broadcom BCM 5411 */
  614. static struct mii_phy_ops bcm5411_phy_ops = {
  615. .init = bcm5411_init,
  616. .suspend = bcm5411_suspend,
  617. .setup_aneg = bcm54xx_setup_aneg,
  618. .setup_forced = bcm54xx_setup_forced,
  619. .poll_link = genmii_poll_link,
  620. .read_link = bcm54xx_read_link,
  621. };
  622. static struct mii_phy_def bcm5411_phy_def = {
  623. .phy_id = 0x00206070,
  624. .phy_id_mask = 0xfffffff0,
  625. .name = "BCM5411",
  626. .features = MII_GBIT_FEATURES,
  627. .magic_aneg = 1,
  628. .ops = &bcm5411_phy_ops
  629. };
  630. /* Broadcom BCM 5421 */
  631. static struct mii_phy_ops bcm5421_phy_ops = {
  632. .init = bcm5421_init,
  633. .suspend = bcm5411_suspend,
  634. .setup_aneg = bcm54xx_setup_aneg,
  635. .setup_forced = bcm54xx_setup_forced,
  636. .poll_link = genmii_poll_link,
  637. .read_link = bcm54xx_read_link,
  638. };
  639. static struct mii_phy_def bcm5421_phy_def = {
  640. .phy_id = 0x002060e0,
  641. .phy_id_mask = 0xfffffff0,
  642. .name = "BCM5421",
  643. .features = MII_GBIT_FEATURES,
  644. .magic_aneg = 1,
  645. .ops = &bcm5421_phy_ops
  646. };
  647. /* Broadcom BCM 5421 built-in K2 */
  648. static struct mii_phy_ops bcm5421k2_phy_ops = {
  649. .init = bcm5421_init,
  650. .suspend = bcm5411_suspend,
  651. .setup_aneg = bcm54xx_setup_aneg,
  652. .setup_forced = bcm54xx_setup_forced,
  653. .poll_link = genmii_poll_link,
  654. .read_link = bcm54xx_read_link,
  655. };
  656. static struct mii_phy_def bcm5421k2_phy_def = {
  657. .phy_id = 0x002062e0,
  658. .phy_id_mask = 0xfffffff0,
  659. .name = "BCM5421-K2",
  660. .features = MII_GBIT_FEATURES,
  661. .magic_aneg = 1,
  662. .ops = &bcm5421k2_phy_ops
  663. };
  664. /* Broadcom BCM 5462 built-in Vesta */
  665. static struct mii_phy_ops bcm5462V_phy_ops = {
  666. .init = bcm5421_init,
  667. .suspend = bcm5411_suspend,
  668. .setup_aneg = bcm54xx_setup_aneg,
  669. .setup_forced = bcm54xx_setup_forced,
  670. .poll_link = genmii_poll_link,
  671. .read_link = bcm54xx_read_link,
  672. };
  673. static struct mii_phy_def bcm5462V_phy_def = {
  674. .phy_id = 0x002060d0,
  675. .phy_id_mask = 0xfffffff0,
  676. .name = "BCM5462-Vesta",
  677. .features = MII_GBIT_FEATURES,
  678. .magic_aneg = 1,
  679. .ops = &bcm5462V_phy_ops
  680. };
  681. /* Marvell 88E1101 (Apple seem to deal with 2 different revs,
  682. * I masked out the 8 last bits to get both, but some specs
  683. * would be useful here) --BenH.
  684. */
  685. static struct mii_phy_ops marvell_phy_ops = {
  686. .setup_aneg = marvell_setup_aneg,
  687. .setup_forced = marvell_setup_forced,
  688. .poll_link = genmii_poll_link,
  689. .read_link = marvell_read_link
  690. };
  691. static struct mii_phy_def marvell_phy_def = {
  692. .phy_id = 0x01410c00,
  693. .phy_id_mask = 0xffffff00,
  694. .name = "Marvell 88E1101",
  695. .features = MII_GBIT_FEATURES,
  696. .magic_aneg = 1,
  697. .ops = &marvell_phy_ops
  698. };
  699. /* Generic implementation for most 10/100 PHYs */
  700. static struct mii_phy_ops generic_phy_ops = {
  701. .setup_aneg = genmii_setup_aneg,
  702. .setup_forced = genmii_setup_forced,
  703. .poll_link = genmii_poll_link,
  704. .read_link = genmii_read_link
  705. };
  706. static struct mii_phy_def genmii_phy_def = {
  707. .phy_id = 0x00000000,
  708. .phy_id_mask = 0x00000000,
  709. .name = "Generic MII",
  710. .features = MII_BASIC_FEATURES,
  711. .magic_aneg = 0,
  712. .ops = &generic_phy_ops
  713. };
  714. static struct mii_phy_def* mii_phy_table[] = {
  715. &bcm5201_phy_def,
  716. &bcm5221_phy_def,
  717. &bcm5400_phy_def,
  718. &bcm5401_phy_def,
  719. &bcm5411_phy_def,
  720. &bcm5421_phy_def,
  721. &bcm5421k2_phy_def,
  722. &bcm5462V_phy_def,
  723. &marvell_phy_def,
  724. &genmii_phy_def,
  725. NULL
  726. };
  727. int mii_phy_probe(struct mii_phy *phy, int mii_id)
  728. {
  729. int rc;
  730. u32 id;
  731. struct mii_phy_def* def;
  732. int i;
  733. /* We do not reset the mii_phy structure as the driver
  734. * may re-probe the PHY regulary
  735. */
  736. phy->mii_id = mii_id;
  737. /* Take PHY out of isloate mode and reset it. */
  738. rc = reset_one_mii_phy(phy, mii_id);
  739. if (rc)
  740. goto fail;
  741. /* Read ID and find matching entry */
  742. id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
  743. printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id);
  744. for (i=0; (def = mii_phy_table[i]) != NULL; i++)
  745. if ((id & def->phy_id_mask) == def->phy_id)
  746. break;
  747. /* Should never be NULL (we have a generic entry), but... */
  748. if (def == NULL)
  749. goto fail;
  750. phy->def = def;
  751. return 0;
  752. fail:
  753. phy->speed = 0;
  754. phy->duplex = 0;
  755. phy->pause = 0;
  756. phy->advertising = 0;
  757. return -ENODEV;
  758. }
  759. EXPORT_SYMBOL(mii_phy_probe);
  760. MODULE_LICENSE("GPL");