150-ocracoke_island.patch 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. --- a/Embedded/src/GbE/iegbe_oem_phy.c
  2. +++ b/Embedded/src/GbE/iegbe_oem_phy.c
  3. @@ -65,6 +65,10 @@ static int32_t iegbe_oem_link_m88_setup(
  4. static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw);
  5. static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw);
  6. +static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw);
  7. +static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data);
  8. +static int32_t oi_phy_setup (struct iegbe_hw *hw);
  9. +
  10. /**
  11. * iegbe_oem_setup_link
  12. * @hw: iegbe_hw struct containing device specific information
  13. @@ -114,6 +118,10 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
  14. }
  15. switch (hw->phy_id) {
  16. + case BCM5395S_PHY_ID:
  17. + return E1000_SUCCESS;
  18. + break;
  19. +
  20. case M88E1000_I_PHY_ID:
  21. case M88E1141_E_PHY_ID:
  22. ret_val = iegbe_oem_link_m88_setup(hw);
  23. @@ -121,6 +129,12 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
  24. return ret_val;
  25. }
  26. break;
  27. + case BCM5481_PHY_ID:
  28. + ret_val = iegbe_oem_link_bcm5481_setup(hw);
  29. + if(ret_val) {
  30. + return ret_val;
  31. + }
  32. + break;
  33. default:
  34. DEBUGOUT("Invalid PHY ID\n");
  35. return -E1000_ERR_PHY_TYPE;
  36. @@ -179,6 +193,51 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
  37. #endif /* ifdef EXTERNAL_MDIO */
  38. }
  39. +/**
  40. + * iegbe_oem_link_bcm5481_setup
  41. + * @hw: iegbe_hw struct containing device specific information
  42. + *
  43. + * Returns E1000_SUCCESS, negative E1000 error code on failure
  44. + *
  45. + * copied verbatim from iegbe_oem_link_m88_setup
  46. + **/
  47. +static int32_t
  48. +iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw)
  49. +{
  50. + int32_t ret_val;
  51. + uint16_t phy_data;
  52. +
  53. + //DEBUGFUNC(__func__);
  54. +
  55. + if(!hw)
  56. + return -1;
  57. +
  58. + /* phy_reset_disable is set in iegbe_oem_set_phy_mode */
  59. + if(hw->phy_reset_disable)
  60. + return E1000_SUCCESS;
  61. +
  62. + // Enable MDIX in extended control reg.
  63. + ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data);
  64. + if(ret_val)
  65. + {
  66. + DEBUGOUT("Unable to read BCM5481_ECTRL register\n");
  67. + return ret_val;
  68. + }
  69. +
  70. + phy_data &= ~BCM5481_ECTRL_DISMDIX;
  71. + ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data);
  72. + if(ret_val)
  73. + {
  74. + DEBUGOUT("Unable to write BCM5481_ECTRL register\n");
  75. + return ret_val;
  76. + }
  77. +
  78. + ret_val = oi_phy_setup (hw);
  79. + if (ret_val)
  80. + return ret_val;
  81. +
  82. + return E1000_SUCCESS;
  83. +}
  84. /**
  85. * iegbe_oem_link_m88_setup
  86. @@ -340,6 +399,11 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw,
  87. * see iegbe_phy_force_speed_duplex, which does the following for M88
  88. */
  89. switch (hw->phy_id) {
  90. + case BCM5395S_PHY_ID:
  91. + case BCM5481_PHY_ID:
  92. + DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n");
  93. + break;
  94. +
  95. case M88E1000_I_PHY_ID:
  96. case M88E1141_E_PHY_ID:
  97. ret_val = iegbe_oem_read_phy_reg_ex(hw,
  98. @@ -415,6 +479,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw
  99. switch (hw->phy_id) {
  100. case M88E1000_I_PHY_ID:
  101. case M88E1141_E_PHY_ID:
  102. + case BCM5481_PHY_ID:
  103. + case BCM5395S_PHY_ID:
  104. DEBUGOUT("No DSP to reset on OEM PHY\n");
  105. break;
  106. default:
  107. @@ -460,6 +526,11 @@ iegbe_oem_cleanup_after_phy_reset(struct
  108. * see iegbe_phy_force_speed_duplex, which does the following for M88
  109. */
  110. switch (hw->phy_id) {
  111. + case BCM5395S_PHY_ID:
  112. + case BCM5481_PHY_ID:
  113. + DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n");
  114. + break;
  115. +
  116. case M88E1000_I_PHY_ID:
  117. case M88E1141_E_PHY_ID:
  118. /*
  119. @@ -573,6 +644,11 @@ iegbe_oem_set_phy_mode(struct iegbe_hw *
  120. * use iegbe_set_phy_mode as example
  121. */
  122. switch (hw->phy_id) {
  123. + case BCM5395S_PHY_ID:
  124. + case BCM5481_PHY_ID:
  125. + DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n");
  126. + break;
  127. +
  128. case M88E1000_I_PHY_ID:
  129. case M88E1141_E_PHY_ID:
  130. ret_val = iegbe_read_eeprom(hw,
  131. @@ -641,6 +717,19 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw
  132. }
  133. hw->phy_type = iegbe_phy_oem;
  134. +{
  135. + // If MAC2 (BCM5395 switch), manually detect the phy
  136. + struct iegbe_adapter *adapter;
  137. + uint32_t device_number;
  138. + adapter = (struct iegbe_adapter *) hw->back;
  139. + device_number = PCI_SLOT(adapter->pdev->devfn);
  140. + if (device_number == ICP_XXXX_MAC_2) {
  141. + hw->phy_id = BCM5395S_PHY_ID;
  142. + hw->phy_revision = 0;
  143. + return E1000_SUCCESS;
  144. + }
  145. +}
  146. +
  147. ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high);
  148. if(ret_val) {
  149. DEBUGOUT("Unable to read PHY register PHY_ID1\n");
  150. @@ -690,6 +779,8 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw)
  151. switch (hw->phy_id) {
  152. case M88E1000_I_PHY_ID:
  153. case M88E1141_E_PHY_ID:
  154. + case BCM5481_PHY_ID:
  155. + case BCM5395S_PHY_ID:
  156. phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT;
  157. break;
  158. default:
  159. @@ -738,6 +829,8 @@ iegbe_oem_phy_is_copper(struct iegbe_hw
  160. switch (hw->phy_id) {
  161. case M88E1000_I_PHY_ID:
  162. case M88E1141_E_PHY_ID:
  163. + case BCM5481_PHY_ID:
  164. + case BCM5395S_PHY_ID:
  165. isCopper = TRUE;
  166. break;
  167. default:
  168. @@ -796,13 +889,13 @@ iegbe_oem_get_phy_dev_number(struct iegb
  169. switch(device_number)
  170. {
  171. case ICP_XXXX_MAC_0:
  172. - hw->phy_addr = 0x00;
  173. + hw->phy_addr = 0x01;
  174. break;
  175. case ICP_XXXX_MAC_1:
  176. - hw->phy_addr = 0x01;
  177. + hw->phy_addr = 0x02;
  178. break;
  179. case ICP_XXXX_MAC_2:
  180. - hw->phy_addr = 0x02;
  181. + hw->phy_addr = 0x00;
  182. break;
  183. default: hw->phy_addr = 0x00;
  184. }
  185. @@ -851,6 +944,12 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter
  186. if(!adapter || !ifr) {
  187. return -1;
  188. }
  189. +
  190. + // If MAC2 (BCM5395 switch) then leave now
  191. + if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) {
  192. + return -1;
  193. + }
  194. +
  195. switch (data->reg_num) {
  196. case PHY_CTRL:
  197. if(mii_reg & MII_CR_POWER_DOWN) {
  198. @@ -987,6 +1086,11 @@ void iegbe_oem_get_phy_regs(struct iegbe
  199. * [10] = mdix mode
  200. */
  201. switch (adapter->hw.phy_id) {
  202. + case BCM5395S_PHY_ID:
  203. + case BCM5481_PHY_ID:
  204. + DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n");
  205. + break;
  206. +
  207. case M88E1000_I_PHY_ID:
  208. case M88E1141_E_PHY_ID:
  209. if(corrected_len > 0) {
  210. @@ -1068,8 +1172,13 @@ iegbe_oem_phy_loopback(struct iegbe_adap
  211. * Loopback configuration is the same for each of the supported PHYs.
  212. */
  213. switch (adapter->hw.phy_id) {
  214. + case BCM5395S_PHY_ID:
  215. + DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n");
  216. + break;
  217. +
  218. case M88E1000_I_PHY_ID:
  219. case M88E1141_E_PHY_ID:
  220. + case BCM5481_PHY_ID:
  221. adapter->hw.autoneg = FALSE;
  222. @@ -1182,8 +1291,14 @@ iegbe_oem_loopback_cleanup(struct iegbe_
  223. }
  224. switch (adapter->hw.phy_id) {
  225. + case BCM5395S_PHY_ID:
  226. + DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n");
  227. + return;
  228. + break;
  229. +
  230. case M88E1000_I_PHY_ID:
  231. case M88E1141_E_PHY_ID:
  232. + case BCM5481_PHY_ID:
  233. default:
  234. adapter->hw.autoneg = TRUE;
  235. @@ -1243,6 +1358,11 @@ iegbe_oem_phy_speed_downgraded(struct ie
  236. */
  237. switch (hw->phy_id) {
  238. + case BCM5395S_PHY_ID:
  239. + case BCM5481_PHY_ID:
  240. + *isDowngraded = 0;
  241. + break;
  242. +
  243. case M88E1000_I_PHY_ID:
  244. case M88E1141_E_PHY_ID:
  245. ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
  246. @@ -1305,6 +1425,11 @@ iegbe_oem_check_polarity(struct iegbe_hw
  247. */
  248. switch (hw->phy_id) {
  249. + case BCM5395S_PHY_ID:
  250. + case BCM5481_PHY_ID:
  251. + *polarity = 0;
  252. + break;
  253. +
  254. case M88E1000_I_PHY_ID:
  255. case M88E1141_E_PHY_ID:
  256. /* return the Polarity bit in the Status register. */
  257. @@ -1367,6 +1492,25 @@ iegbe_oem_phy_is_full_duplex(struct iegb
  258. */
  259. switch (hw->phy_id) {
  260. + case BCM5395S_PHY_ID:
  261. + /* Always full duplex */
  262. + *isFD = 1;
  263. + break;
  264. +
  265. + case BCM5481_PHY_ID:
  266. + ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
  267. + if(ret_val) return ret_val;
  268. +
  269. + switch (BCM5481_ASTAT_HCD(phy_data)) {
  270. + case BCM5481_ASTAT_1KBTFD:
  271. + case BCM5481_ASTAT_100BTXFD:
  272. + *isFD = 1;
  273. + break;
  274. + default:
  275. + *isFD = 0;
  276. + }
  277. + break;
  278. +
  279. case M88E1000_I_PHY_ID:
  280. case M88E1141_E_PHY_ID:
  281. ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
  282. @@ -1423,6 +1567,25 @@ iegbe_oem_phy_is_speed_1000(struct iegbe
  283. */
  284. switch (hw->phy_id) {
  285. + case BCM5395S_PHY_ID:
  286. + /* Always 1000mb */
  287. + *is1000 = 1;
  288. + break;
  289. +
  290. + case BCM5481_PHY_ID:
  291. + ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
  292. + if(ret_val) return ret_val;
  293. +
  294. + switch (BCM5481_ASTAT_HCD(phy_data)) {
  295. + case BCM5481_ASTAT_1KBTFD:
  296. + case BCM5481_ASTAT_1KBTHD:
  297. + *is1000 = 1;
  298. + break;
  299. + default:
  300. + *is1000 = 0;
  301. + }
  302. + break;
  303. +
  304. case M88E1000_I_PHY_ID:
  305. case M88E1141_E_PHY_ID:
  306. ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
  307. @@ -1478,6 +1641,25 @@ iegbe_oem_phy_is_speed_100(struct iegbe_
  308. * see iegbe_config_mac_to_phy
  309. */
  310. switch (hw->phy_id) {
  311. + case BCM5395S_PHY_ID:
  312. + /* Always 1000Mb, never 100mb */
  313. + *is100 = 0;
  314. + break;
  315. +
  316. + case BCM5481_PHY_ID:
  317. + ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
  318. + if(ret_val) return ret_val;
  319. +
  320. + switch (BCM5481_ASTAT_HCD(phy_data)) {
  321. + case BCM5481_ASTAT_100BTXFD:
  322. + case BCM5481_ASTAT_100BTXHD:
  323. + *is100 = 1;
  324. + break;
  325. + default:
  326. + *is100 = 0;
  327. + }
  328. + break;
  329. +
  330. case M88E1000_I_PHY_ID:
  331. case M88E1141_E_PHY_ID:
  332. ret_val = iegbe_oem_read_phy_reg_ex(hw,
  333. @@ -1535,6 +1717,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw *
  334. * see iegbe_phy_m88_get_info
  335. */
  336. switch (hw->phy_id) {
  337. + case BCM5395S_PHY_ID:
  338. + case BCM5481_PHY_ID:
  339. + DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n");
  340. + break;
  341. +
  342. case M88E1000_I_PHY_ID:
  343. case M88E1141_E_PHY_ID:
  344. /* The downshift status is checked only once, after link is
  345. @@ -1636,8 +1823,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw *
  346. * the M88 used in truxton.
  347. */
  348. switch (hw->phy_id) {
  349. + case BCM5395S_PHY_ID:
  350. + DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n");
  351. + break;
  352. +
  353. case M88E1000_I_PHY_ID:
  354. case M88E1141_E_PHY_ID:
  355. + case BCM5481_PHY_ID:
  356. ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data);
  357. if(ret_val) {
  358. DEBUGOUT("Unable to read register PHY_CTRL\n");
  359. @@ -1699,6 +1891,8 @@ iegbe_oem_phy_init_script(struct iegbe_h
  360. switch (hw->phy_id) {
  361. case M88E1000_I_PHY_ID:
  362. case M88E1141_E_PHY_ID:
  363. + case BCM5481_PHY_ID:
  364. + case BCM5395S_PHY_ID:
  365. DEBUGOUT("Nothing to do for OEM PHY Init");
  366. break;
  367. default:
  368. @@ -1735,6 +1929,11 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h
  369. return -1;
  370. }
  371. + if (hw->phy_id == BCM5395S_PHY_ID) {
  372. + DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n");
  373. + return -1;
  374. + }
  375. +
  376. /* call the GCU func that will read the phy
  377. *
  378. * Make note that the M88 phy is what'll be used on Truxton.
  379. @@ -1782,6 +1981,11 @@ iegbe_oem_set_trans_gasket(struct iegbe_
  380. }
  381. switch (hw->phy_id) {
  382. + case BCM5395S_PHY_ID:
  383. + case BCM5481_PHY_ID:
  384. + DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n");
  385. + break;
  386. +
  387. case M88E1000_I_PHY_ID:
  388. case M88E1141_E_PHY_ID:
  389. /* Gasket set correctly for Marvell Phys, so nothing to do */
  390. @@ -1886,6 +2090,8 @@ iegbe_oem_phy_needs_reset_with_mac(struc
  391. switch (hw->phy_id) {
  392. case M88E1000_I_PHY_ID:
  393. case M88E1141_E_PHY_ID:
  394. + case BCM5481_PHY_ID:
  395. + case BCM5395S_PHY_ID:
  396. ret_val = FALSE;
  397. break;
  398. default:
  399. @@ -1935,6 +2141,8 @@ iegbe_oem_config_dsp_after_link_change(s
  400. switch (hw->phy_id) {
  401. case M88E1000_I_PHY_ID:
  402. case M88E1141_E_PHY_ID:
  403. + case BCM5481_PHY_ID:
  404. + case BCM5395S_PHY_ID:
  405. DEBUGOUT("No DSP to configure on OEM PHY");
  406. break;
  407. default:
  408. @@ -1978,6 +2186,12 @@ iegbe_oem_get_cable_length(struct iegbe_
  409. }
  410. switch (hw->phy_id) {
  411. + case BCM5395S_PHY_ID:
  412. + case BCM5481_PHY_ID:
  413. + *min_length = 0;
  414. + *max_length = iegbe_igp_cable_length_150;
  415. + break;
  416. +
  417. case M88E1000_I_PHY_ID:
  418. case M88E1141_E_PHY_ID:
  419. ret_val = iegbe_oem_read_phy_reg_ex(hw,
  420. @@ -2061,6 +2275,23 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw
  421. */
  422. switch (hw->phy_id) {
  423. + case BCM5395S_PHY_ID:
  424. + /* Link always up */
  425. + *isUp = TRUE;
  426. + return E1000_SUCCESS;
  427. + break;
  428. +
  429. + case BCM5481_PHY_ID:
  430. + iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data);
  431. + ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data);
  432. + if(ret_val)
  433. + {
  434. + DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n");
  435. + return ret_val;
  436. + }
  437. + statusMask = BCM5481_ESTAT_LINK;
  438. + break;
  439. +
  440. case M88E1000_I_PHY_ID:
  441. case M88E1141_E_PHY_ID:
  442. iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
  443. @@ -2092,3 +2323,210 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw
  444. #endif /* ifdef EXTERNAL_MDIO */
  445. }
  446. +
  447. +
  448. +//-----
  449. +// Read BCM5481 expansion register
  450. +//
  451. +int32_t
  452. +bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data)
  453. +{
  454. + int ret;
  455. + uint16_t selector;
  456. + uint16_t reg_data;
  457. +
  458. + // Get the current value of bits 15:12
  459. + ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector);
  460. + if (ret)
  461. + return ret;
  462. +
  463. + // Select the expansion register
  464. + selector &= 0xf000;
  465. + selector |= (0xf << 8) | (reg);
  466. + iegbe_oem_write_phy_reg_ex (hw, 0x17, selector);
  467. +
  468. + // Read the expansion register
  469. + ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &reg_data);
  470. +
  471. + // De-select the expansion registers.
  472. + selector &= 0xf000;
  473. + iegbe_oem_write_phy_reg_ex (hw, 0x17, selector);
  474. +
  475. + if (ret)
  476. + return ret;
  477. +
  478. + *data = reg_data;
  479. + return ret;
  480. +}
  481. +
  482. +//-----
  483. +// Read reg 0x18 sub-register
  484. +//
  485. +static int32_t
  486. +bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data)
  487. +{
  488. + int ret;
  489. + uint16_t tmp_data;
  490. +
  491. + // Select reg 0x18, sv
  492. + tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL;
  493. + ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data);
  494. + if(ret)
  495. + return ret;
  496. +
  497. + // Read reg 0x18, sv
  498. + ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data);
  499. + if(ret)
  500. + return ret;
  501. +
  502. + *data = tmp_data;
  503. + return ret;
  504. +}
  505. +
  506. +//-----
  507. +// Read reg 0x1C sub-register
  508. +//
  509. +int32_t
  510. +bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data)
  511. +{
  512. + int ret;
  513. + uint16_t tmp_data;
  514. +
  515. + // Select reg 0x1c, sv
  516. + tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT);
  517. +
  518. + ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data);
  519. + if(ret)
  520. + return ret;
  521. +
  522. + // Read reg 0x1c, sv
  523. + ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data);
  524. + if(ret)
  525. + return ret;
  526. +
  527. + *data = tmp_data;
  528. + return ret;
  529. +}
  530. +
  531. +//-----
  532. +// Read-modify-write a 0x1C register.
  533. +//
  534. +// hw - hardware access info.
  535. +// reg - 0x1C register to modify.
  536. +// data - bits which should be set.
  537. +// mask - the '1' bits in this argument will be cleared in the data
  538. +// read from 'reg' then 'data' will be or'd in and the result
  539. +// will be written to 'reg'.
  540. +
  541. +int32_t
  542. +bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask)
  543. +{
  544. + int32_t ret;
  545. + uint16_t reg_data;
  546. +
  547. + ret = 0;
  548. +
  549. + ret = bcm5481_read_1csv (hw, reg, &reg_data);
  550. + if (ret)
  551. + {
  552. + DEBUGOUT("Unable to read BCM5481 1CH register\n");
  553. + printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg);
  554. + return ret;
  555. + }
  556. +
  557. + reg_data &= ~mask;
  558. + reg_data |= (BCM5481_R1CH_WE | data);
  559. +
  560. + ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data);
  561. + if(ret)
  562. + {
  563. + DEBUGOUT("Unable to write BCM5481 1CH register\n");
  564. + printk (KERN_ERR "Unable to write BCM5481 1CH register\n");
  565. + return ret;
  566. + }
  567. +
  568. + return ret;
  569. +}
  570. +
  571. +int32_t
  572. +oi_phy_setup (struct iegbe_hw *hw)
  573. +{
  574. + int ret;
  575. + uint16_t pmii_data;
  576. + uint16_t mctrl_data;
  577. + uint16_t cacr_data;
  578. +
  579. + ret = 0;
  580. +
  581. + // Set low power mode via reg 0x18, sv010, bit 6
  582. + // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits.
  583. + ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data);
  584. + if (ret)
  585. + {
  586. + DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n");
  587. + printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n");
  588. + return ret;
  589. + }
  590. +
  591. + // Set the LPM bit in the data just read and write back to sv010
  592. + // The shadow register select bits [2:0] are set by reading the sv010
  593. + // register.
  594. + pmii_data |= BCM5481_R18H_SV010_LPM;
  595. + ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data);
  596. + if(ret)
  597. + {
  598. + DEBUGOUT("Unable to write BCM5481_R18H register\n");
  599. + printk (KERN_ERR "Unable to write BCM5481_R18H register\n");
  600. + return ret;
  601. + }
  602. +
  603. +
  604. + // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111
  605. +
  606. + if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data))
  607. + {
  608. + DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n");
  609. + printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n");
  610. + return ret;
  611. + }
  612. + mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW);
  613. +
  614. + ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data);
  615. + if(ret)
  616. + {
  617. + DEBUGOUT("Unable to write BCM5481_R18H register\n");
  618. + printk (KERN_ERR "Unable to write BCM5481_R18H register\n");
  619. + return ret;
  620. + }
  621. +
  622. + // Enable RGMII transmit clock delay in reg 0x1c, sv00011
  623. + ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data);
  624. + if (ret)
  625. + {
  626. + DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n");
  627. + printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n");
  628. + return ret;
  629. + }
  630. +
  631. + cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD);
  632. +
  633. + ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data);
  634. + if(ret)
  635. + {
  636. + DEBUGOUT("Unable to write BCM5481_R1CH register\n");
  637. + printk (KERN_ERR "Unable to write BCM5481_R1CH register\n");
  638. + return ret;
  639. + }
  640. +
  641. + // Enable dual link speed indication (0x1c, sv 00010, bit 2)
  642. + ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK);
  643. + if (ret)
  644. + return ret;
  645. +
  646. + // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0)
  647. + ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN);
  648. + if (ret)
  649. + return ret;
  650. +
  651. + return ret;
  652. +}
  653. --- a/Embedded/src/GbE/iegbe_oem_phy.h
  654. +++ b/Embedded/src/GbE/iegbe_oem_phy.h
  655. @@ -95,6 +95,8 @@ int32_t iegbe_oem_phy_is_link_up(struct
  656. #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */
  657. #define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL
  658. +#define BCM5481_PHY_ID 0x0143BCA0
  659. +#define BCM5395S_PHY_ID 0x0143BCF0
  660. /* Miscellaneous defines */
  661. #ifdef IEGBE_10_100_ONLY
  662. @@ -103,5 +105,65 @@ int32_t iegbe_oem_phy_is_link_up(struct
  663. #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F
  664. #endif
  665. +/* BCM5481 specifics */
  666. +
  667. +#define BCM5481_ECTRL (0x10)
  668. +#define BCM5481_ESTAT (0x11)
  669. +#define BCM5481_RXERR (0x12)
  670. +#define BCM5481_EXPRW (0x15)
  671. +#define BCM5481_EXPACC (0x17)
  672. +#define BCM5481_ASTAT (0x19)
  673. +#define BCM5481_R18H (0x18)
  674. +#define BCM5481_R1CH (0x1c)
  675. +
  676. +/* indirect register access via register 18h */
  677. +
  678. +#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits.
  679. +#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control
  680. +#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T
  681. +#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control
  682. +#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test
  683. +#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control
  684. +
  685. +#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity
  686. +#define BCM5481_R18H_SV010_LPM (1 << 6)
  687. +#define BCM5481_R18H_SV111_SKEW (1 << 8)
  688. +#define BCM5481_R18H_WE (1 << 15) // Write enable
  689. +
  690. +// 0x1c registers
  691. +#define BCM5481_R1CH_SV_SHIFT (10)
  692. +#define BCM5481_R1CH_SV_MASK (0x1f)
  693. +#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1
  694. +#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control
  695. +#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control
  696. +#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1
  697. +
  698. +// 0x1c common
  699. +#define BCM5481_R1CH_WE (1 << 15) // Write enable
  700. +
  701. +// 0x1c, sv 00010
  702. +#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed
  703. +
  704. +// 0x1c, sv 00011
  705. +#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay
  706. +
  707. +// 0x1c, sv 01001
  708. +#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED
  709. +#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED
  710. +
  711. +#define BCM5481_ECTRL_DISMDIX (1 <<14)
  712. +
  713. +#define BCM5481_MCTRL_AUTOMDIX (1 <<9)
  714. +
  715. +#define BCM5481_ESTAT_LINK (1 << 8)
  716. +
  717. +#define BCM5481_ASTAT_ANC (1 << 15)
  718. +#define BCM5481_ASTAT_ANHCD (7 << 8)
  719. +#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7)
  720. +#define BCM5481_ASTAT_1KBTFD (0x7)
  721. +#define BCM5481_ASTAT_1KBTHD (0x6)
  722. +#define BCM5481_ASTAT_100BTXFD (0x5)
  723. +#define BCM5481_ASTAT_100BTXHD (0x3)
  724. +
  725. #endif /* ifndef _IEGBE_OEM_PHY_H_ */