1 /*
2  * Copyright (C) 2008 Freescale Semicondutor, Inc.
3  *	Dave Liu <daveliu@freescale.com>
4  *
5  * This program is free software; you can redistribute  it and/or modify it
6  * under  the terms of  the GNU General  Public License as published by the
7  * Free Software Foundation;  either version 2 of the  License, or (at your
8  * option) any later version.
9  */
10 
11 #include <config.h>
12 #include <common.h>
13 #include <asm/io.h>
14 #include <asm/immap_85xx.h>
15 
16 /* PORDEVSR register */
17 #define GUTS_PORDEVSR_OFFS		0xc
18 #define GUTS_PORDEVSR_SERDES2_IO_SEL	0x38000000
19 #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT	27
20 
21 /* SerDes CR0 register */
22 #define	FSL_SRDSCR0_OFFS	0x0
23 #define FSL_SRDSCR0_TXEQA_MASK	0x00007000
24 #define FSL_SRDSCR0_TXEQA_SGMII	0x00004000
25 #define FSL_SRDSCR0_TXEQA_SATA	0x00001000
26 #define FSL_SRDSCR0_TXEQE_MASK	0x00000700
27 #define FSL_SRDSCR0_TXEQE_SGMII	0x00000400
28 #define FSL_SRDSCR0_TXEQE_SATA	0x00000100
29 
30 /* SerDes CR1 register */
31 #define FSL_SRDSCR1_OFFS	0x4
32 #define FSL_SRDSCR1_LANEA_MASK	0x80200000
33 #define FSL_SRDSCR1_LANEA_OFF	0x80200000
34 #define FSL_SRDSCR1_LANEE_MASK	0x08020000
35 #define FSL_SRDSCR1_LANEE_OFF	0x08020000
36 
37 /* SerDes CR2 register */
38 #define FSL_SRDSCR2_OFFS	0x8
39 #define FSL_SRDSCR2_EICA_MASK	0x00001f00
40 #define FSL_SRDSCR2_EICA_SGMII	0x00000400
41 #define FSL_SRDSCR2_EICA_SATA	0x00001400
42 #define FSL_SRDSCR2_EICE_MASK	0x0000001f
43 #define FSL_SRDSCR2_EICE_SGMII	0x00000004
44 #define FSL_SRDSCR2_EICE_SATA	0x00000014
45 
46 /* SerDes CR3 register */
47 #define FSL_SRDSCR3_OFFS	0xc
48 #define FSL_SRDSCR3_LANEA_MASK	0x3f000700
49 #define FSL_SRDSCR3_LANEA_SGMII	0x00000000
50 #define FSL_SRDSCR3_LANEA_SATA	0x15000500
51 #define FSL_SRDSCR3_LANEE_MASK	0x003f0007
52 #define FSL_SRDSCR3_LANEE_SGMII	0x00000000
53 #define FSL_SRDSCR3_LANEE_SATA	0x00150005
54 
55 void fsl_serdes_init(void)
56 {
57 	void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
58 	void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
59 	u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
60 	u32 srds2_io_sel;
61 	u32 tmp;
62 
63 	/* parse the SRDS2_IO_SEL of PORDEVSR */
64 	srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
65 		       >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
66 
67 	switch (srds2_io_sel) {
68 	case 1:	/* Lane A - SATA1, Lane E - SATA2 */
69 		/* CR 0 */
70 		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
71 		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
72 		tmp |= FSL_SRDSCR0_TXEQA_SATA;
73 		tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
74 		tmp |= FSL_SRDSCR0_TXEQE_SATA;
75 		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
76 		/* CR 1 */
77 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
78 		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
79 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
80 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
81 		/* CR 2 */
82 		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
83 		tmp &= ~FSL_SRDSCR2_EICA_MASK;
84 		tmp |= FSL_SRDSCR2_EICA_SATA;
85 		tmp &= ~FSL_SRDSCR2_EICE_MASK;
86 		tmp |= FSL_SRDSCR2_EICE_SATA;
87 		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
88 		/* CR 3 */
89 		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
90 		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
91 		tmp |= FSL_SRDSCR3_LANEA_SATA;
92 		tmp &= ~FSL_SRDSCR3_LANEE_MASK;
93 		tmp |= FSL_SRDSCR3_LANEE_SATA;
94 		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
95 		break;
96 	case 3: /* Lane A - SATA1, Lane E - disabled */
97 		/* CR 0 */
98 		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
99 		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
100 		tmp |= FSL_SRDSCR0_TXEQA_SATA;
101 		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
102 		/* CR 1 */
103 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
104 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
105 		tmp |= FSL_SRDSCR1_LANEE_OFF;
106 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
107 		/* CR 2 */
108 		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
109 		tmp &= ~FSL_SRDSCR2_EICA_MASK;
110 		tmp |= FSL_SRDSCR2_EICA_SATA;
111 		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
112 		/* CR 3 */
113 		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
114 		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
115 		tmp |= FSL_SRDSCR3_LANEA_SATA;
116 		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
117 		break;
118 	case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
119 		/* CR 0 */
120 		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
121 		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
122 		tmp |= FSL_SRDSCR0_TXEQA_SGMII;
123 		tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
124 		tmp |= FSL_SRDSCR0_TXEQE_SGMII;
125 		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
126 		/* CR 1 */
127 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
128 		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
129 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
130 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
131 		/* CR 2 */
132 		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
133 		tmp &= ~FSL_SRDSCR2_EICA_MASK;
134 		tmp |= FSL_SRDSCR2_EICA_SGMII;
135 		tmp &= ~FSL_SRDSCR2_EICE_MASK;
136 		tmp |= FSL_SRDSCR2_EICE_SGMII;
137 		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
138 		/* CR 3 */
139 		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
140 		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
141 		tmp |= FSL_SRDSCR3_LANEA_SGMII;
142 		tmp &= ~FSL_SRDSCR3_LANEE_MASK;
143 		tmp |= FSL_SRDSCR3_LANEE_SGMII;
144 		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
145 		break;
146 	case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
147 		/* CR 0 */
148 		tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
149 		tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
150 		tmp |= FSL_SRDSCR0_TXEQA_SGMII;
151 		out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
152 		/* CR 1 */
153 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
154 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
155 		tmp |= FSL_SRDSCR1_LANEE_OFF;
156 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
157 		/* CR 2 */
158 		tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
159 		tmp &= ~FSL_SRDSCR2_EICA_MASK;
160 		tmp |= FSL_SRDSCR2_EICA_SGMII;
161 		out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
162 		/* CR 3 */
163 		tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
164 		tmp &= ~FSL_SRDSCR3_LANEA_MASK;
165 		tmp |= FSL_SRDSCR3_LANEA_SGMII;
166 		out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
167 		break;
168 	case 7: /* Lane A - disabled, Lane E - disabled */
169 		/* CR 1 */
170 		tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
171 		tmp &= ~FSL_SRDSCR1_LANEA_MASK;
172 		tmp |= FSL_SRDSCR1_LANEA_OFF;
173 		tmp &= ~FSL_SRDSCR1_LANEE_MASK;
174 		tmp |= FSL_SRDSCR1_LANEE_OFF;
175 		out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
176 		break;
177 	default:
178 		break;
179 	}
180 }
181