powerpc/p4080: Add support for initializing SERDES
[platform/kernel/u-boot.git] / arch / powerpc / cpu / mpc85xx / fsl_corenet_serdes.c
1 /*
2  * Copyright 2009-2010 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 #include <common.h>
24 #include <asm/fsl_serdes.h>
25 #include <asm/immap_85xx.h>
26 #include <asm/io.h>
27 #include <asm/processor.h>
28 #include "fsl_corenet_serdes.h"
29
30 static u32 serdes_prtcl_map;
31
32 #ifdef DEBUG
33 static const char *serdes_prtcl_str[] = {
34         [NONE] = "NA",
35         [PCIE1] = "PCIE1",
36         [PCIE2] = "PCIE2",
37         [PCIE3] = "PCIE3",
38         [PCIE4] = "PCIE4",
39         [SATA1] = "SATA1",
40         [SATA2] = "SATA2",
41         [SRIO1] = "SRIO1",
42         [SRIO2] = "SRIO2",
43         [SGMII_FM1_DTSEC1] = "SGMII_FM1_DTSEC1",
44         [SGMII_FM1_DTSEC2] = "SGMII_FM1_DTSEC2",
45         [SGMII_FM1_DTSEC3] = "SGMII_FM1_DTSEC3",
46         [SGMII_FM1_DTSEC4] = "SGMII_FM1_DTSEC4",
47         [SGMII_FM1_DTSEC5] = "SGMII_FM1_DTSEC5",
48         [SGMII_FM2_DTSEC1] = "SGMII_FM2_DTSEC1",
49         [SGMII_FM2_DTSEC2] = "SGMII_FM2_DTSEC2",
50         [SGMII_FM2_DTSEC3] = "SGMII_FM2_DTSEC3",
51         [SGMII_FM2_DTSEC4] = "SGMII_FM2_DTSEC4",
52         [XAUI_FM1] = "XAUI_FM1",
53         [XAUI_FM2] = "XAUI_FM2",
54         [AURORA] = "DEBUG",
55 };
56 #endif
57
58 static const struct {
59         int idx;
60         unsigned int lpd; /* RCW lane powerdown bit */
61         int bank;
62 } lanes[SRDS_MAX_LANES] = {
63         { 0, 152, FSL_SRDS_BANK_1 },
64         { 1, 153, FSL_SRDS_BANK_1 },
65         { 2, 154, FSL_SRDS_BANK_1 },
66         { 3, 155, FSL_SRDS_BANK_1 },
67         { 4, 156, FSL_SRDS_BANK_1 },
68         { 5, 157, FSL_SRDS_BANK_1 },
69         { 6, 158, FSL_SRDS_BANK_1 },
70         { 7, 159, FSL_SRDS_BANK_1 },
71         { 8, 160, FSL_SRDS_BANK_1 },
72         { 9, 161, FSL_SRDS_BANK_1 },
73         { 16, 162, FSL_SRDS_BANK_2 },
74         { 17, 163, FSL_SRDS_BANK_2 },
75         { 18, 164, FSL_SRDS_BANK_2 },
76         { 19, 165, FSL_SRDS_BANK_2 },
77         { 20, 170, FSL_SRDS_BANK_3 },
78         { 21, 171, FSL_SRDS_BANK_3 },
79         { 22, 172, FSL_SRDS_BANK_3 },
80         { 23, 173, FSL_SRDS_BANK_3 },
81 };
82
83 int serdes_get_lane_idx(int lane)
84 {
85         return lanes[lane].idx;
86 }
87
88 int serdes_get_bank(int lane)
89 {
90         return lanes[lane].bank;
91 }
92
93 int serdes_lane_enabled(int lane)
94 {
95         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
96         serdes_corenet_t *regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
97
98         int bank = lanes[lane].bank;
99         int word = lanes[lane].lpd / 32;
100         int bit = lanes[lane].lpd % 32;
101
102         if (in_be32(&regs->bank[bank].rstctl) & SRDS_RSTCTL_SDPD)
103                 return 0;
104
105         return !(in_be32(&gur->rcwsr[word]) & (0x80000000 >> bit));
106 }
107
108 int is_serdes_configured(enum srds_prtcl device)
109 {
110         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
111
112         /* Is serdes enabled at all? */
113         if (!(in_be32(&gur->rcwsr[5]) & FSL_CORENET_RCWSR5_SRDS_EN))
114                 return 0;
115
116         return (1 << device) & serdes_prtcl_map;
117 }
118
119 void fsl_serdes_init(void)
120 {
121         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
122         int cfg;
123         serdes_corenet_t *srds_regs;
124         int lane, bank, idx;
125         enum srds_prtcl lane_prtcl;
126         long long end_tick;
127         int have_bank[SRDS_MAX_BANK] = {};
128
129         /* Is serdes enabled at all? */
130         if (!(in_be32(&gur->rcwsr[5]) & FSL_CORENET_RCWSR5_SRDS_EN))
131                 return;
132
133         srds_regs = (void *)(CONFIG_SYS_FSL_CORENET_SERDES_ADDR);
134         cfg = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
135         debug("Using SERDES configuration 0x%x, lane settings:\n", cfg);
136
137         if (!is_serdes_prtcl_valid(cfg)) {
138                 printf("SERDES[PRTCL] = 0x%x is not valid\n", cfg);
139                 return;
140         }
141
142         /* Look for banks with all lanes disabled, and power down the bank. */
143         for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
144                 enum srds_prtcl lane_prtcl = serdes_get_prtcl(cfg, lane);
145                 if (serdes_lane_enabled(lane)) {
146                         have_bank[serdes_get_bank(lane)] = 1;
147                         serdes_prtcl_map |= (1 << lane_prtcl);
148                 }
149         }
150
151         for (bank = 0; bank < SRDS_MAX_BANK; bank++) {
152                 if (!have_bank[bank]) {
153                         printf("SERDES: bank %d disabled\n", bank + 1);
154                         setbits_be32(&srds_regs->bank[bank].rstctl,
155                                      SRDS_RSTCTL_SDPD);
156                 }
157         }
158
159         for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
160                 idx = serdes_get_lane_idx(lane);
161                 lane_prtcl = serdes_get_prtcl(cfg, lane);
162
163 #ifdef DEBUG
164                 switch (lane) {
165                 case 0:
166                         puts("Bank1: ");
167                         break;
168                 case 10:
169                         puts("\nBank2: ");
170                         break;
171                 case 14:
172                         puts("\nBank3: ");
173                         break;
174                 default:
175                         break;
176                 }
177
178                 printf("%s ", serdes_prtcl_str[lane_prtcl]);
179 #endif
180         }
181
182 #ifdef DEBUG
183         puts("\n");
184 #endif
185
186         for (idx = 0; idx < SRDS_MAX_BANK; idx++) {
187                 u32 rstctl;
188
189                 bank = idx;
190
191                 /* Skip disabled banks */
192                 if (!have_bank[bank])
193                         continue;
194
195                 /* reset banks for errata */
196                 setbits_be32(&srds_regs->bank[bank].rstctl, SRDS_RSTCTL_RST);
197
198                 /* wait for reset complete or 1-second timeout */
199                 end_tick = usec2ticks(1000000) + get_ticks();
200                 do {
201                         rstctl = in_be32(&srds_regs->bank[bank].rstctl);
202                         if (rstctl & SRDS_RSTCTL_RSTDONE)
203                                 break;
204                 } while (end_tick > get_ticks());
205
206                 if (!(rstctl & SRDS_RSTCTL_RSTDONE)) {
207                         printf("SERDES: timeout resetting bank %d\n",
208                                bank + 1);
209                         continue;
210                 }
211         }
212 }