Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / powerpc / cpu / mpc85xx / mpc8536_serdes.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2008,2010 Freescale Semiconductor, Inc.
4  *      Dave Liu <daveliu@freescale.com>
5  */
6
7 #include <config.h>
8 #include <common.h>
9 #include <log.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;
75
76         if (!(serdes1_prtcl_map & (1 << NONE)))
77                 fsl_serdes_init();
78
79         ret = (1 << device) & serdes1_prtcl_map;
80
81         if (ret)
82                 return ret;
83
84         if (!(serdes2_prtcl_map & (1 << NONE)))
85                 fsl_serdes_init();
86
87         return (1 << device) & serdes2_prtcl_map;
88 }
89
90 void fsl_serdes_init(void)
91 {
92         void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
93         void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
94         u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
95         u32 srds1_io_sel, srds2_io_sel;
96         u32 tmp;
97         int lane;
98
99         if (serdes1_prtcl_map & (1 << NONE) &&
100             serdes2_prtcl_map & (1 << NONE))
101                 return;
102
103         srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
104                                 MPC85xx_PORDEVSR_IO_SEL_SHIFT;
105
106         /* parse the SRDS2_IO_SEL of PORDEVSR */
107         srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
108                        >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
109
110         debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel);
111         debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel);
112
113         switch (srds2_io_sel) {
114         case 1: /* Lane A - SATA1, Lane E - SATA2 */
115                 /* CR 0 */
116                 tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
117                 tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
118                 tmp |= FSL_SRDSCR0_TXEQA_SATA;
119                 tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
120                 tmp |= FSL_SRDSCR0_TXEQE_SATA;
121                 out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
122                 /* CR 1 */
123                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
124                 tmp &= ~FSL_SRDSCR1_LANEA_MASK;
125                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
126                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
127                 /* CR 2 */
128                 tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
129                 tmp &= ~FSL_SRDSCR2_EICA_MASK;
130                 tmp |= FSL_SRDSCR2_EICA_SATA;
131                 tmp &= ~FSL_SRDSCR2_EICE_MASK;
132                 tmp |= FSL_SRDSCR2_EICE_SATA;
133                 out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
134                 /* CR 3 */
135                 tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
136                 tmp &= ~FSL_SRDSCR3_LANEA_MASK;
137                 tmp |= FSL_SRDSCR3_LANEA_SATA;
138                 tmp &= ~FSL_SRDSCR3_LANEE_MASK;
139                 tmp |= FSL_SRDSCR3_LANEE_SATA;
140                 out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
141                 break;
142         case 3: /* Lane A - SATA1, Lane E - disabled */
143                 /* CR 0 */
144                 tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
145                 tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
146                 tmp |= FSL_SRDSCR0_TXEQA_SATA;
147                 out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
148                 /* CR 1 */
149                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
150                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
151                 tmp |= FSL_SRDSCR1_LANEE_OFF;
152                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
153                 /* CR 2 */
154                 tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
155                 tmp &= ~FSL_SRDSCR2_EICA_MASK;
156                 tmp |= FSL_SRDSCR2_EICA_SATA;
157                 out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
158                 /* CR 3 */
159                 tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
160                 tmp &= ~FSL_SRDSCR3_LANEA_MASK;
161                 tmp |= FSL_SRDSCR3_LANEA_SATA;
162                 out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
163                 break;
164         case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
165                 /* CR 0 */
166                 tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
167                 tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
168                 tmp |= FSL_SRDSCR0_TXEQA_SGMII;
169                 tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
170                 tmp |= FSL_SRDSCR0_TXEQE_SGMII;
171                 out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
172                 /* CR 1 */
173                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
174                 tmp &= ~FSL_SRDSCR1_LANEA_MASK;
175                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
176                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
177                 /* CR 2 */
178                 tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
179                 tmp &= ~FSL_SRDSCR2_EICA_MASK;
180                 tmp |= FSL_SRDSCR2_EICA_SGMII;
181                 tmp &= ~FSL_SRDSCR2_EICE_MASK;
182                 tmp |= FSL_SRDSCR2_EICE_SGMII;
183                 out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
184                 /* CR 3 */
185                 tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
186                 tmp &= ~FSL_SRDSCR3_LANEA_MASK;
187                 tmp |= FSL_SRDSCR3_LANEA_SGMII;
188                 tmp &= ~FSL_SRDSCR3_LANEE_MASK;
189                 tmp |= FSL_SRDSCR3_LANEE_SGMII;
190                 out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
191                 break;
192         case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
193                 /* CR 0 */
194                 tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
195                 tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
196                 tmp |= FSL_SRDSCR0_TXEQA_SGMII;
197                 out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
198                 /* CR 1 */
199                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
200                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
201                 tmp |= FSL_SRDSCR1_LANEE_OFF;
202                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
203                 /* CR 2 */
204                 tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
205                 tmp &= ~FSL_SRDSCR2_EICA_MASK;
206                 tmp |= FSL_SRDSCR2_EICA_SGMII;
207                 out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
208                 /* CR 3 */
209                 tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
210                 tmp &= ~FSL_SRDSCR3_LANEA_MASK;
211                 tmp |= FSL_SRDSCR3_LANEA_SGMII;
212                 out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
213                 break;
214         case 7: /* Lane A - disabled, Lane E - disabled */
215                 /* CR 1 */
216                 tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
217                 tmp &= ~FSL_SRDSCR1_LANEA_MASK;
218                 tmp |= FSL_SRDSCR1_LANEA_OFF;
219                 tmp &= ~FSL_SRDSCR1_LANEE_MASK;
220                 tmp |= FSL_SRDSCR1_LANEE_OFF;
221                 out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
222                 break;
223         default:
224                 break;
225         }
226
227         if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
228                 printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
229                 return;
230         }
231         for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
232                 enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane];
233                 serdes1_prtcl_map |= (1 << lane_prtcl);
234         }
235
236         /* Set the first bit to indicate serdes has been initialized */
237         serdes1_prtcl_map |= (1 << NONE);
238
239         if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
240                 printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
241                 return;
242         }
243
244         for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
245                 enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane];
246                 serdes2_prtcl_map |= (1 << lane_prtcl);
247         }
248
249         /* Set the first bit to indicate serdes has been initialized */
250         serdes2_prtcl_map |= (1 << NONE);
251 }