mpc8536_serdes.c 7.6 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 u32 serdes1_prtcl_map, serdes2_prtcl_map;
  65. static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
  66. [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
  67. [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
  68. [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
  69. [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3},
  70. };
  71. static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
  72. [0x1] = {SATA1, SATA2},
  73. [0x3] = {SATA1, NONE},
  74. [0x4] = {SGMII_TSEC1, SGMII_TSEC3},
  75. [0x6] = {SGMII_TSEC1, NONE},
  76. };
  77. int is_serdes_configured(enum srds_prtcl device)
  78. {
  79. int ret = (1 << device) & serdes1_prtcl_map;
  80. if (ret)
  81. return ret;
  82. return (1 << device) & serdes2_prtcl_map;
  83. }
  84. void fsl_serdes_init(void)
  85. {
  86. void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
  87. void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
  88. u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
  89. u32 srds1_io_sel, srds2_io_sel;
  90. u32 tmp;
  91. int lane;
  92. srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
  93. MPC85xx_PORDEVSR_IO_SEL_SHIFT;
  94. /* parse the SRDS2_IO_SEL of PORDEVSR */
  95. srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
  96. >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
  97. debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel);
  98. debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel);
  99. switch (srds2_io_sel) {
  100. case 1: /* Lane A - SATA1, Lane E - SATA2 */
  101. /* CR 0 */
  102. tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
  103. tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
  104. tmp |= FSL_SRDSCR0_TXEQA_SATA;
  105. tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
  106. tmp |= FSL_SRDSCR0_TXEQE_SATA;
  107. out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
  108. /* CR 1 */
  109. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  110. tmp &= ~FSL_SRDSCR1_LANEA_MASK;
  111. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  112. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  113. /* CR 2 */
  114. tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
  115. tmp &= ~FSL_SRDSCR2_EICA_MASK;
  116. tmp |= FSL_SRDSCR2_EICA_SATA;
  117. tmp &= ~FSL_SRDSCR2_EICE_MASK;
  118. tmp |= FSL_SRDSCR2_EICE_SATA;
  119. out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
  120. /* CR 3 */
  121. tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
  122. tmp &= ~FSL_SRDSCR3_LANEA_MASK;
  123. tmp |= FSL_SRDSCR3_LANEA_SATA;
  124. tmp &= ~FSL_SRDSCR3_LANEE_MASK;
  125. tmp |= FSL_SRDSCR3_LANEE_SATA;
  126. out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
  127. break;
  128. case 3: /* Lane A - SATA1, Lane E - disabled */
  129. /* CR 0 */
  130. tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
  131. tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
  132. tmp |= FSL_SRDSCR0_TXEQA_SATA;
  133. out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
  134. /* CR 1 */
  135. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  136. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  137. tmp |= FSL_SRDSCR1_LANEE_OFF;
  138. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  139. /* CR 2 */
  140. tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
  141. tmp &= ~FSL_SRDSCR2_EICA_MASK;
  142. tmp |= FSL_SRDSCR2_EICA_SATA;
  143. out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
  144. /* CR 3 */
  145. tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
  146. tmp &= ~FSL_SRDSCR3_LANEA_MASK;
  147. tmp |= FSL_SRDSCR3_LANEA_SATA;
  148. out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
  149. break;
  150. case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
  151. /* CR 0 */
  152. tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
  153. tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
  154. tmp |= FSL_SRDSCR0_TXEQA_SGMII;
  155. tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
  156. tmp |= FSL_SRDSCR0_TXEQE_SGMII;
  157. out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
  158. /* CR 1 */
  159. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  160. tmp &= ~FSL_SRDSCR1_LANEA_MASK;
  161. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  162. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  163. /* CR 2 */
  164. tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
  165. tmp &= ~FSL_SRDSCR2_EICA_MASK;
  166. tmp |= FSL_SRDSCR2_EICA_SGMII;
  167. tmp &= ~FSL_SRDSCR2_EICE_MASK;
  168. tmp |= FSL_SRDSCR2_EICE_SGMII;
  169. out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
  170. /* CR 3 */
  171. tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
  172. tmp &= ~FSL_SRDSCR3_LANEA_MASK;
  173. tmp |= FSL_SRDSCR3_LANEA_SGMII;
  174. tmp &= ~FSL_SRDSCR3_LANEE_MASK;
  175. tmp |= FSL_SRDSCR3_LANEE_SGMII;
  176. out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
  177. break;
  178. case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
  179. /* CR 0 */
  180. tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
  181. tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
  182. tmp |= FSL_SRDSCR0_TXEQA_SGMII;
  183. out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
  184. /* CR 1 */
  185. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  186. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  187. tmp |= FSL_SRDSCR1_LANEE_OFF;
  188. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  189. /* CR 2 */
  190. tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
  191. tmp &= ~FSL_SRDSCR2_EICA_MASK;
  192. tmp |= FSL_SRDSCR2_EICA_SGMII;
  193. out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
  194. /* CR 3 */
  195. tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
  196. tmp &= ~FSL_SRDSCR3_LANEA_MASK;
  197. tmp |= FSL_SRDSCR3_LANEA_SGMII;
  198. out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
  199. break;
  200. case 7: /* Lane A - disabled, Lane E - disabled */
  201. /* CR 1 */
  202. tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
  203. tmp &= ~FSL_SRDSCR1_LANEA_MASK;
  204. tmp |= FSL_SRDSCR1_LANEA_OFF;
  205. tmp &= ~FSL_SRDSCR1_LANEE_MASK;
  206. tmp |= FSL_SRDSCR1_LANEE_OFF;
  207. out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
  208. break;
  209. default:
  210. break;
  211. }
  212. if (srds1_io_sel > ARRAY_SIZE(serdes1_cfg_tbl)) {
  213. printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
  214. return;
  215. }
  216. for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
  217. enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane];
  218. serdes1_prtcl_map |= (1 << lane_prtcl);
  219. }
  220. if (srds2_io_sel > ARRAY_SIZE(serdes2_cfg_tbl)) {
  221. printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
  222. return;
  223. }
  224. for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
  225. enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane];
  226. serdes2_prtcl_map |= (1 << lane_prtcl);
  227. }
  228. }