mpc8536_serdes.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright 2008,2010 Freescale Semiconductor, Inc.
  3. * Dave Liu <daveliu@freescale.com>
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <config.h>
  24. #include <common.h>
  25. #include <asm/io.h>
  26. #include <asm/immap_85xx.h>
  27. #include <asm/fsl_serdes.h>
  28. /* PORDEVSR register */
  29. #define GUTS_PORDEVSR_OFFS 0xc
  30. #define GUTS_PORDEVSR_SERDES2_IO_SEL 0x38000000
  31. #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT 27
  32. /* SerDes CR0 register */
  33. #define FSL_SRDSCR0_OFFS 0x0
  34. #define FSL_SRDSCR0_TXEQA_MASK 0x00007000
  35. #define FSL_SRDSCR0_TXEQA_SGMII 0x00004000
  36. #define FSL_SRDSCR0_TXEQA_SATA 0x00001000
  37. #define FSL_SRDSCR0_TXEQE_MASK 0x00000700
  38. #define FSL_SRDSCR0_TXEQE_SGMII 0x00000400
  39. #define FSL_SRDSCR0_TXEQE_SATA 0x00000100
  40. /* SerDes CR1 register */
  41. #define FSL_SRDSCR1_OFFS 0x4
  42. #define FSL_SRDSCR1_LANEA_MASK 0x80200000
  43. #define FSL_SRDSCR1_LANEA_OFF 0x80200000
  44. #define FSL_SRDSCR1_LANEE_MASK 0x08020000
  45. #define FSL_SRDSCR1_LANEE_OFF 0x08020000
  46. /* SerDes CR2 register */
  47. #define FSL_SRDSCR2_OFFS 0x8
  48. #define FSL_SRDSCR2_EICA_MASK 0x00001f00
  49. #define FSL_SRDSCR2_EICA_SGMII 0x00000400
  50. #define FSL_SRDSCR2_EICA_SATA 0x00001400
  51. #define FSL_SRDSCR2_EICE_MASK 0x0000001f
  52. #define FSL_SRDSCR2_EICE_SGMII 0x00000004
  53. #define FSL_SRDSCR2_EICE_SATA 0x00000014
  54. /* SerDes CR3 register */
  55. #define FSL_SRDSCR3_OFFS 0xc
  56. #define FSL_SRDSCR3_LANEA_MASK 0x3f000700
  57. #define FSL_SRDSCR3_LANEA_SGMII 0x00000000
  58. #define FSL_SRDSCR3_LANEA_SATA 0x15000500
  59. #define FSL_SRDSCR3_LANEE_MASK 0x003f0007
  60. #define FSL_SRDSCR3_LANEE_SGMII 0x00000000
  61. #define FSL_SRDSCR3_LANEE_SATA 0x00150005
  62. #define SRDS1_MAX_LANES 8
  63. #define SRDS2_MAX_LANES 2
  64. static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
  65. [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
  66. [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
  67. [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
  68. [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3},
  69. };
  70. static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
  71. [0x1] = {SATA1, SATA2},
  72. [0x3] = {SATA1, NONE},
  73. [0x4] = {SGMII_TSEC1, SGMII_TSEC3},
  74. [0x6] = {SGMII_TSEC1, NONE},
  75. };
  76. int is_serdes_configured(enum srds_prtcl device)
  77. {
  78. int i;
  79. ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
  80. u32 pordevsr = in_be32(&gur->pordevsr);
  81. u32 srds1_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
  82. MPC85xx_PORDEVSR_IO_SEL_SHIFT;
  83. u32 srds2_cfg = (pordevsr & MPC85xx_PORDEVSR_SRDS2_IO_SEL) >>
  84. GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
  85. debug("%s: dev = %d\n", __FUNCTION__, device);
  86. debug("PORDEVSR[IO_SEL] = %x\n", srds1_cfg);
  87. debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_cfg);
  88. if (srds1_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
  89. printf("Invalid PORDEVSR[IO_SEL] = %d\n", srds1_cfg);
  90. return 0;
  91. }
  92. if (srds2_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
  93. printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_cfg);
  94. return 0;
  95. }
  96. for (i = 0; i < SRDS1_MAX_LANES; i++) {
  97. if (serdes1_cfg_tbl[srds1_cfg][i] == device)
  98. return 1;
  99. }
  100. for (i = 0; i < SRDS2_MAX_LANES; i++) {
  101. if (serdes2_cfg_tbl[srds2_cfg][i] == device)
  102. return 1;
  103. }
  104. return 0;
  105. }
  106. void fsl_serdes_init(void)
  107. {
  108. void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
  109. void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
  110. u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
  111. u32 srds2_io_sel;
  112. u32 tmp;
  113. /* parse the SRDS2_IO_SEL of PORDEVSR */
  114. srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
  115. >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
  116. switch (srds2_io_sel) {
  117. case 1: /* Lane A - SATA1, Lane E - SATA2 */
  118. /* CR 0 */
  119. tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
  120. tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
  121. tmp |= FSL_SRDSCR0_TXEQA_SATA;
  122. tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
  123. tmp |= FSL_SRDSCR0_TXEQE_SATA;
  124. out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
  125. /* CR 1 */
  126. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  127. tmp &= ~FSL_SRDSCR1_LANEA_MASK;
  128. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  129. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  130. /* CR 2 */
  131. tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
  132. tmp &= ~FSL_SRDSCR2_EICA_MASK;
  133. tmp |= FSL_SRDSCR2_EICA_SATA;
  134. tmp &= ~FSL_SRDSCR2_EICE_MASK;
  135. tmp |= FSL_SRDSCR2_EICE_SATA;
  136. out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
  137. /* CR 3 */
  138. tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
  139. tmp &= ~FSL_SRDSCR3_LANEA_MASK;
  140. tmp |= FSL_SRDSCR3_LANEA_SATA;
  141. tmp &= ~FSL_SRDSCR3_LANEE_MASK;
  142. tmp |= FSL_SRDSCR3_LANEE_SATA;
  143. out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
  144. break;
  145. case 3: /* Lane A - SATA1, Lane E - disabled */
  146. /* CR 0 */
  147. tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
  148. tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
  149. tmp |= FSL_SRDSCR0_TXEQA_SATA;
  150. out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
  151. /* CR 1 */
  152. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  153. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  154. tmp |= FSL_SRDSCR1_LANEE_OFF;
  155. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  156. /* CR 2 */
  157. tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
  158. tmp &= ~FSL_SRDSCR2_EICA_MASK;
  159. tmp |= FSL_SRDSCR2_EICA_SATA;
  160. out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
  161. /* CR 3 */
  162. tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
  163. tmp &= ~FSL_SRDSCR3_LANEA_MASK;
  164. tmp |= FSL_SRDSCR3_LANEA_SATA;
  165. out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
  166. break;
  167. case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
  168. /* CR 0 */
  169. tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
  170. tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
  171. tmp |= FSL_SRDSCR0_TXEQA_SGMII;
  172. tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
  173. tmp |= FSL_SRDSCR0_TXEQE_SGMII;
  174. out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
  175. /* CR 1 */
  176. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  177. tmp &= ~FSL_SRDSCR1_LANEA_MASK;
  178. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  179. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  180. /* CR 2 */
  181. tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
  182. tmp &= ~FSL_SRDSCR2_EICA_MASK;
  183. tmp |= FSL_SRDSCR2_EICA_SGMII;
  184. tmp &= ~FSL_SRDSCR2_EICE_MASK;
  185. tmp |= FSL_SRDSCR2_EICE_SGMII;
  186. out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
  187. /* CR 3 */
  188. tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
  189. tmp &= ~FSL_SRDSCR3_LANEA_MASK;
  190. tmp |= FSL_SRDSCR3_LANEA_SGMII;
  191. tmp &= ~FSL_SRDSCR3_LANEE_MASK;
  192. tmp |= FSL_SRDSCR3_LANEE_SGMII;
  193. out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
  194. break;
  195. case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
  196. /* CR 0 */
  197. tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
  198. tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
  199. tmp |= FSL_SRDSCR0_TXEQA_SGMII;
  200. out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
  201. /* CR 1 */
  202. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  203. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  204. tmp |= FSL_SRDSCR1_LANEE_OFF;
  205. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  206. /* CR 2 */
  207. tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
  208. tmp &= ~FSL_SRDSCR2_EICA_MASK;
  209. tmp |= FSL_SRDSCR2_EICA_SGMII;
  210. out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
  211. /* CR 3 */
  212. tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
  213. tmp &= ~FSL_SRDSCR3_LANEA_MASK;
  214. tmp |= FSL_SRDSCR3_LANEA_SGMII;
  215. out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
  216. break;
  217. case 7: /* Lane A - disabled, Lane E - disabled */
  218. /* CR 1 */
  219. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  220. tmp &= ~FSL_SRDSCR1_LANEA_MASK;
  221. tmp |= FSL_SRDSCR1_LANEA_OFF;
  222. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  223. tmp |= FSL_SRDSCR1_LANEE_OFF;
  224. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  225. break;
  226. default:
  227. break;
  228. }
  229. }