arch: Make board selection choices optional
[platform/kernel/u-boot.git] / arch / powerpc / cpu / mpc85xx / mpc8536_serdes.c
1 /*
2  * Copyright 2008,2010 Freescale Semiconductor, Inc.
3  *      Dave Liu <daveliu@freescale.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <config.h>
9 #include <common.h>
10 #include <asm/io.h>
11 #include <asm/immap_85xx.h>
12 #include <asm/fsl_serdes.h>
13
14 /* PORDEVSR register */
15 #define GUTS_PORDEVSR_OFFS              0xc
16 #define GUTS_PORDEVSR_SERDES2_IO_SEL    0x38000000
17 #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT      27
18
19 /* SerDes CR0 register */
20 #define FSL_SRDSCR0_OFFS        0x0
21 #define FSL_SRDSCR0_TXEQA_MASK  0x00007000
22 #define FSL_SRDSCR0_TXEQA_SGMII 0x00004000
23 #define FSL_SRDSCR0_TXEQA_SATA  0x00001000
24 #define FSL_SRDSCR0_TXEQE_MASK  0x00000700
25 #define FSL_SRDSCR0_TXEQE_SGMII 0x00000400
26 #define FSL_SRDSCR0_TXEQE_SATA  0x00000100
27
28 /* SerDes CR1 register */
29 #define FSL_SRDSCR1_OFFS        0x4
30 #define FSL_SRDSCR1_LANEA_MASK  0x80200000
31 #define FSL_SRDSCR1_LANEA_OFF   0x80200000
32 #define FSL_SRDSCR1_LANEE_MASK  0x08020000
33 #define FSL_SRDSCR1_LANEE_OFF   0x08020000
34
35 /* SerDes CR2 register */
36 #define FSL_SRDSCR2_OFFS        0x8
37 #define FSL_SRDSCR2_EICA_MASK   0x00001f00
38 #define FSL_SRDSCR2_EICA_SGMII  0x00000400
39 #define FSL_SRDSCR2_EICA_SATA   0x00001400
40 #define FSL_SRDSCR2_EICE_MASK   0x0000001f
41 #define FSL_SRDSCR2_EICE_SGMII  0x00000004
42 #define FSL_SRDSCR2_EICE_SATA   0x00000014
43
44 /* SerDes CR3 register */
45 #define FSL_SRDSCR3_OFFS        0xc
46 #define FSL_SRDSCR3_LANEA_MASK  0x3f000700
47 #define FSL_SRDSCR3_LANEA_SGMII 0x00000000
48 #define FSL_SRDSCR3_LANEA_SATA  0x15000500
49 #define FSL_SRDSCR3_LANEE_MASK  0x003f0007
50 #define FSL_SRDSCR3_LANEE_SGMII 0x00000000
51 #define FSL_SRDSCR3_LANEE_SATA  0x00150005
52
53 #define SRDS1_MAX_LANES         8
54 #define SRDS2_MAX_LANES         2
55
56 static u32 serdes1_prtcl_map, serdes2_prtcl_map;
57
58 static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
59         [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
60         [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
61         [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
62         [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3},
63 };
64
65 static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
66         [0x1] = {SATA1, SATA2},
67         [0x3] = {SATA1, NONE},
68         [0x4] = {SGMII_TSEC1, SGMII_TSEC3},
69         [0x6] = {SGMII_TSEC1, NONE},
70 };
71
72 int is_serdes_configured(enum srds_prtcl device)
73 {
74         int ret = (1 << device) & serdes1_prtcl_map;
75
76         if (ret)
77                 return ret;
78
79         return (1 << device) & serdes2_prtcl_map;
80 }
81
82 void fsl_serdes_init(void)
83 {
84         void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
85         void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
86         u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
87         u32 srds1_io_sel, srds2_io_sel;
88         u32 tmp;
89         int lane;
90
91         srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
92                                 MPC85xx_PORDEVSR_IO_SEL_SHIFT;
93
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
98         debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel);
99         debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel);
100
101         switch (srds2_io_sel) {
102         case 1: /* Lane A - SATA1, Lane E - SATA2 */
103                 /* CR 0 */
104                 tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
105                 tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
106                 tmp |= FSL_SRDSCR0_TXEQA_SATA;
107                 tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
108                 tmp |= FSL_SRDSCR0_TXEQE_SATA;
109                 out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
110                 /* CR 1 */
111                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
112                 tmp &= ~FSL_SRDSCR1_LANEA_MASK;
113                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
114                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
115                 /* CR 2 */
116                 tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
117                 tmp &= ~FSL_SRDSCR2_EICA_MASK;
118                 tmp |= FSL_SRDSCR2_EICA_SATA;
119                 tmp &= ~FSL_SRDSCR2_EICE_MASK;
120                 tmp |= FSL_SRDSCR2_EICE_SATA;
121                 out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
122                 /* CR 3 */
123                 tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
124                 tmp &= ~FSL_SRDSCR3_LANEA_MASK;
125                 tmp |= FSL_SRDSCR3_LANEA_SATA;
126                 tmp &= ~FSL_SRDSCR3_LANEE_MASK;
127                 tmp |= FSL_SRDSCR3_LANEE_SATA;
128                 out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
129                 break;
130         case 3: /* Lane A - SATA1, Lane E - disabled */
131                 /* CR 0 */
132                 tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
133                 tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
134                 tmp |= FSL_SRDSCR0_TXEQA_SATA;
135                 out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
136                 /* CR 1 */
137                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
138                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
139                 tmp |= FSL_SRDSCR1_LANEE_OFF;
140                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
141                 /* CR 2 */
142                 tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
143                 tmp &= ~FSL_SRDSCR2_EICA_MASK;
144                 tmp |= FSL_SRDSCR2_EICA_SATA;
145                 out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
146                 /* CR 3 */
147                 tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
148                 tmp &= ~FSL_SRDSCR3_LANEA_MASK;
149                 tmp |= FSL_SRDSCR3_LANEA_SATA;
150                 out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
151                 break;
152         case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
153                 /* CR 0 */
154                 tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
155                 tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
156                 tmp |= FSL_SRDSCR0_TXEQA_SGMII;
157                 tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
158                 tmp |= FSL_SRDSCR0_TXEQE_SGMII;
159                 out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
160                 /* CR 1 */
161                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
162                 tmp &= ~FSL_SRDSCR1_LANEA_MASK;
163                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
164                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
165                 /* CR 2 */
166                 tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
167                 tmp &= ~FSL_SRDSCR2_EICA_MASK;
168                 tmp |= FSL_SRDSCR2_EICA_SGMII;
169                 tmp &= ~FSL_SRDSCR2_EICE_MASK;
170                 tmp |= FSL_SRDSCR2_EICE_SGMII;
171                 out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
172                 /* CR 3 */
173                 tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
174                 tmp &= ~FSL_SRDSCR3_LANEA_MASK;
175                 tmp |= FSL_SRDSCR3_LANEA_SGMII;
176                 tmp &= ~FSL_SRDSCR3_LANEE_MASK;
177                 tmp |= FSL_SRDSCR3_LANEE_SGMII;
178                 out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
179                 break;
180         case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
181                 /* CR 0 */
182                 tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
183                 tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
184                 tmp |= FSL_SRDSCR0_TXEQA_SGMII;
185                 out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
186                 /* CR 1 */
187                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
188                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
189                 tmp |= FSL_SRDSCR1_LANEE_OFF;
190                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
191                 /* CR 2 */
192                 tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
193                 tmp &= ~FSL_SRDSCR2_EICA_MASK;
194                 tmp |= FSL_SRDSCR2_EICA_SGMII;
195                 out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
196                 /* CR 3 */
197                 tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
198                 tmp &= ~FSL_SRDSCR3_LANEA_MASK;
199                 tmp |= FSL_SRDSCR3_LANEA_SGMII;
200                 out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
201                 break;
202         case 7: /* Lane A - disabled, Lane E - disabled */
203                 /* CR 1 */
204                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
205                 tmp &= ~FSL_SRDSCR1_LANEA_MASK;
206                 tmp |= FSL_SRDSCR1_LANEA_OFF;
207                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
208                 tmp |= FSL_SRDSCR1_LANEE_OFF;
209                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
210                 break;
211         default:
212                 break;
213         }
214
215         if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
216                 printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
217                 return;
218         }
219         for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
220                 enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane];
221                 serdes1_prtcl_map |= (1 << lane_prtcl);
222         }
223
224         if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
225                 printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
226                 return;
227         }
228
229         for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
230                 enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane];
231                 serdes2_prtcl_map |= (1 << lane_prtcl);
232         }
233 }