xref: /OK3568_Linux_fs/u-boot/board/freescale/b4860qds/b4860qds.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2011-2012 Freescale Semiconductor, Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <command.h>
9*4882a593Smuzhiyun #include <i2c.h>
10*4882a593Smuzhiyun #include <netdev.h>
11*4882a593Smuzhiyun #include <linux/compiler.h>
12*4882a593Smuzhiyun #include <asm/mmu.h>
13*4882a593Smuzhiyun #include <asm/processor.h>
14*4882a593Smuzhiyun #include <linux/errno.h>
15*4882a593Smuzhiyun #include <asm/cache.h>
16*4882a593Smuzhiyun #include <asm/immap_85xx.h>
17*4882a593Smuzhiyun #include <asm/fsl_law.h>
18*4882a593Smuzhiyun #include <asm/fsl_serdes.h>
19*4882a593Smuzhiyun #include <asm/fsl_liodn.h>
20*4882a593Smuzhiyun #include <fm_eth.h>
21*4882a593Smuzhiyun #include <hwconfig.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "../common/qixis.h"
24*4882a593Smuzhiyun #include "../common/vsc3316_3308.h"
25*4882a593Smuzhiyun #include "../common/idt8t49n222a_serdes_clk.h"
26*4882a593Smuzhiyun #include "../common/zm7300.h"
27*4882a593Smuzhiyun #include "b4860qds.h"
28*4882a593Smuzhiyun #include "b4860qds_qixis.h"
29*4882a593Smuzhiyun #include "b4860qds_crossbar_con.h"
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define CLK_MUX_SEL_MASK	0x4
32*4882a593Smuzhiyun #define ETH_PHY_CLK_OUT		0x4
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
35*4882a593Smuzhiyun 
checkboard(void)36*4882a593Smuzhiyun int checkboard(void)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	char buf[64];
39*4882a593Smuzhiyun 	u8 sw;
40*4882a593Smuzhiyun 	struct cpu_type *cpu = gd->arch.cpu;
41*4882a593Smuzhiyun 	static const char *const freq[] = {"100", "125", "156.25", "161.13",
42*4882a593Smuzhiyun 						"122.88", "122.88", "122.88"};
43*4882a593Smuzhiyun 	int clock;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	printf("Board: %sQDS, ", cpu->name);
46*4882a593Smuzhiyun 	printf("Sys ID: 0x%02x, Sys Ver: 0x%02x, ",
47*4882a593Smuzhiyun 		QIXIS_READ(id), QIXIS_READ(arch));
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	sw = QIXIS_READ(brdcfg[0]);
50*4882a593Smuzhiyun 	sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	if (sw < 0x8)
53*4882a593Smuzhiyun 		printf("vBank: %d\n", sw);
54*4882a593Smuzhiyun 	else if (sw >= 0x8 && sw <= 0xE)
55*4882a593Smuzhiyun 		puts("NAND\n");
56*4882a593Smuzhiyun 	else
57*4882a593Smuzhiyun 		printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	printf("FPGA: v%d (%s), build %d",
60*4882a593Smuzhiyun 		(int)QIXIS_READ(scver), qixis_read_tag(buf),
61*4882a593Smuzhiyun 		(int)qixis_read_minor());
62*4882a593Smuzhiyun 	/* the timestamp string contains "\n" at the end */
63*4882a593Smuzhiyun 	printf(" on %s", qixis_read_time(buf));
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	/*
66*4882a593Smuzhiyun 	 * Display the actual SERDES reference clocks as configured by the
67*4882a593Smuzhiyun 	 * dip switches on the board.  Note that the SWx registers could
68*4882a593Smuzhiyun 	 * technically be set to force the reference clocks to match the
69*4882a593Smuzhiyun 	 * values that the SERDES expects (or vice versa).  For now, however,
70*4882a593Smuzhiyun 	 * we just display both values and hope the user notices when they
71*4882a593Smuzhiyun 	 * don't match.
72*4882a593Smuzhiyun 	 */
73*4882a593Smuzhiyun 	puts("SERDES Reference Clocks: ");
74*4882a593Smuzhiyun 	sw = QIXIS_READ(brdcfg[2]);
75*4882a593Smuzhiyun 	clock = (sw >> 5) & 7;
76*4882a593Smuzhiyun 	printf("Bank1=%sMHz ", freq[clock]);
77*4882a593Smuzhiyun 	sw = QIXIS_READ(brdcfg[4]);
78*4882a593Smuzhiyun 	clock = (sw >> 6) & 3;
79*4882a593Smuzhiyun 	printf("Bank2=%sMHz\n", freq[clock]);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	return 0;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
select_i2c_ch_pca(u8 ch)84*4882a593Smuzhiyun int select_i2c_ch_pca(u8 ch)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	int ret;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* Selecting proper channel via PCA*/
89*4882a593Smuzhiyun 	ret = i2c_write(I2C_MUX_PCA_ADDR, 0x0, 1, &ch, 1);
90*4882a593Smuzhiyun 	if (ret) {
91*4882a593Smuzhiyun 		printf("PCA: failed to select proper channel.\n");
92*4882a593Smuzhiyun 		return ret;
93*4882a593Smuzhiyun 	}
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	return 0;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun /*
99*4882a593Smuzhiyun  * read_voltage from sensor on I2C bus
100*4882a593Smuzhiyun  * We use average of 4 readings, waiting for 532us befor another reading
101*4882a593Smuzhiyun  */
102*4882a593Smuzhiyun #define WAIT_FOR_ADC	532	/* wait for 532 microseconds for ADC */
103*4882a593Smuzhiyun #define NUM_READINGS	4	/* prefer to be power of 2 for efficiency */
104*4882a593Smuzhiyun 
read_voltage(void)105*4882a593Smuzhiyun static inline int read_voltage(void)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	int i, ret, voltage_read = 0;
108*4882a593Smuzhiyun 	u16 vol_mon;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	for (i = 0; i < NUM_READINGS; i++) {
111*4882a593Smuzhiyun 		ret = i2c_read(I2C_VOL_MONITOR_ADDR,
112*4882a593Smuzhiyun 			I2C_VOL_MONITOR_BUS_V_OFFSET, 1, (void *)&vol_mon, 2);
113*4882a593Smuzhiyun 		if (ret) {
114*4882a593Smuzhiyun 			printf("VID: failed to read core voltage\n");
115*4882a593Smuzhiyun 			return ret;
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 		if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) {
118*4882a593Smuzhiyun 			printf("VID: Core voltage sensor error\n");
119*4882a593Smuzhiyun 			return -1;
120*4882a593Smuzhiyun 		}
121*4882a593Smuzhiyun 		debug("VID: bus voltage reads 0x%04x\n", vol_mon);
122*4882a593Smuzhiyun 		/* LSB = 4mv */
123*4882a593Smuzhiyun 		voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4;
124*4882a593Smuzhiyun 		udelay(WAIT_FOR_ADC);
125*4882a593Smuzhiyun 	}
126*4882a593Smuzhiyun 	/* calculate the average */
127*4882a593Smuzhiyun 	voltage_read /= NUM_READINGS;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	return voltage_read;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
adjust_vdd(ulong vdd_override)132*4882a593Smuzhiyun static int adjust_vdd(ulong vdd_override)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	int re_enable = disable_interrupts();
135*4882a593Smuzhiyun 	ccsr_gur_t __iomem *gur =
136*4882a593Smuzhiyun 		(void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
137*4882a593Smuzhiyun 	u32 fusesr;
138*4882a593Smuzhiyun 	u8 vid;
139*4882a593Smuzhiyun 	int vdd_target, vdd_last;
140*4882a593Smuzhiyun 	int existing_voltage, temp_voltage, voltage; /* all in 1/10 mV */
141*4882a593Smuzhiyun 	int ret;
142*4882a593Smuzhiyun 	unsigned int orig_i2c_speed;
143*4882a593Smuzhiyun 	unsigned long vdd_string_override;
144*4882a593Smuzhiyun 	char *vdd_string;
145*4882a593Smuzhiyun 	static const uint16_t vdd[32] = {
146*4882a593Smuzhiyun 		0,	/* unused */
147*4882a593Smuzhiyun 		9875,	/* 0.9875V */
148*4882a593Smuzhiyun 		9750,
149*4882a593Smuzhiyun 		9625,
150*4882a593Smuzhiyun 		9500,
151*4882a593Smuzhiyun 		9375,
152*4882a593Smuzhiyun 		9250,
153*4882a593Smuzhiyun 		9125,
154*4882a593Smuzhiyun 		9000,
155*4882a593Smuzhiyun 		8875,
156*4882a593Smuzhiyun 		8750,
157*4882a593Smuzhiyun 		8625,
158*4882a593Smuzhiyun 		8500,
159*4882a593Smuzhiyun 		8375,
160*4882a593Smuzhiyun 		8250,
161*4882a593Smuzhiyun 		8125,
162*4882a593Smuzhiyun 		10000,	/* 1.0000V */
163*4882a593Smuzhiyun 		10125,
164*4882a593Smuzhiyun 		10250,
165*4882a593Smuzhiyun 		10375,
166*4882a593Smuzhiyun 		10500,
167*4882a593Smuzhiyun 		10625,
168*4882a593Smuzhiyun 		10750,
169*4882a593Smuzhiyun 		10875,
170*4882a593Smuzhiyun 		11000,
171*4882a593Smuzhiyun 		0,	/* reserved */
172*4882a593Smuzhiyun 	};
173*4882a593Smuzhiyun 	struct vdd_drive {
174*4882a593Smuzhiyun 		u8 vid;
175*4882a593Smuzhiyun 		unsigned voltage;
176*4882a593Smuzhiyun 	};
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	ret = select_i2c_ch_pca(I2C_MUX_CH_VOL_MONITOR);
179*4882a593Smuzhiyun 	if (ret) {
180*4882a593Smuzhiyun 		printf("VID: I2c failed to switch channel\n");
181*4882a593Smuzhiyun 		ret = -1;
182*4882a593Smuzhiyun 		goto exit;
183*4882a593Smuzhiyun 	}
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	/* get the voltage ID from fuse status register */
186*4882a593Smuzhiyun 	fusesr = in_be32(&gur->dcfg_fusesr);
187*4882a593Smuzhiyun 	vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) &
188*4882a593Smuzhiyun 		FSL_CORENET_DCFG_FUSESR_VID_MASK;
189*4882a593Smuzhiyun 	if (vid == FSL_CORENET_DCFG_FUSESR_VID_MASK) {
190*4882a593Smuzhiyun 		vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
191*4882a593Smuzhiyun 			FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
192*4882a593Smuzhiyun 	}
193*4882a593Smuzhiyun 	vdd_target = vdd[vid];
194*4882a593Smuzhiyun 	debug("VID:Reading from from fuse,vid=%x vdd is %dmV\n",
195*4882a593Smuzhiyun 	      vid, vdd_target/10);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/* check override variable for overriding VDD */
198*4882a593Smuzhiyun 	vdd_string = env_get("b4qds_vdd_mv");
199*4882a593Smuzhiyun 	if (vdd_override == 0 && vdd_string &&
200*4882a593Smuzhiyun 	    !strict_strtoul(vdd_string, 10, &vdd_string_override))
201*4882a593Smuzhiyun 		vdd_override = vdd_string_override;
202*4882a593Smuzhiyun 	if (vdd_override >= 819 && vdd_override <= 1212) {
203*4882a593Smuzhiyun 		vdd_target = vdd_override * 10; /* convert to 1/10 mV */
204*4882a593Smuzhiyun 		debug("VDD override is %lu\n", vdd_override);
205*4882a593Smuzhiyun 	} else if (vdd_override != 0) {
206*4882a593Smuzhiyun 		printf("Invalid value.\n");
207*4882a593Smuzhiyun 	}
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	if (vdd_target == 0) {
210*4882a593Smuzhiyun 		printf("VID: VID not used\n");
211*4882a593Smuzhiyun 		ret = 0;
212*4882a593Smuzhiyun 		goto exit;
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	/*
216*4882a593Smuzhiyun 	 * Read voltage monitor to check real voltage.
217*4882a593Smuzhiyun 	 * Voltage monitor LSB is 4mv.
218*4882a593Smuzhiyun 	 */
219*4882a593Smuzhiyun 	vdd_last = read_voltage();
220*4882a593Smuzhiyun 	if (vdd_last < 0) {
221*4882a593Smuzhiyun 		printf("VID: abort VID adjustment\n");
222*4882a593Smuzhiyun 		ret = -1;
223*4882a593Smuzhiyun 		goto exit;
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	debug("VID: Core voltage is at %d mV\n", vdd_last);
227*4882a593Smuzhiyun 	ret = select_i2c_ch_pca(I2C_MUX_CH_DPM);
228*4882a593Smuzhiyun 	if (ret) {
229*4882a593Smuzhiyun 		printf("VID: I2c failed to switch channel to DPM\n");
230*4882a593Smuzhiyun 		ret = -1;
231*4882a593Smuzhiyun 		goto exit;
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	/* Round up to the value of step of Voltage regulator */
235*4882a593Smuzhiyun 	voltage = roundup(vdd_target, ZM_STEP);
236*4882a593Smuzhiyun 	debug("VID: rounded up voltage = %d\n", voltage);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	/* lower the speed to 100kHz to access ZM7300 device */
239*4882a593Smuzhiyun 	debug("VID: Setting bus speed to 100KHz if not already set\n");
240*4882a593Smuzhiyun 	orig_i2c_speed = i2c_get_bus_speed();
241*4882a593Smuzhiyun 	if (orig_i2c_speed != 100000)
242*4882a593Smuzhiyun 		i2c_set_bus_speed(100000);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	/* Read the existing level on board, if equal to requsted one,
245*4882a593Smuzhiyun 	   no need to re-set */
246*4882a593Smuzhiyun 	existing_voltage = zm_read_voltage();
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	/* allowing the voltage difference of one step 0.0125V acceptable */
249*4882a593Smuzhiyun 	if ((existing_voltage >= voltage) &&
250*4882a593Smuzhiyun 	    (existing_voltage < (voltage + ZM_STEP))) {
251*4882a593Smuzhiyun 		debug("VID: voltage already set as requested,returning\n");
252*4882a593Smuzhiyun 		ret = existing_voltage;
253*4882a593Smuzhiyun 		goto out;
254*4882a593Smuzhiyun 	}
255*4882a593Smuzhiyun 	debug("VID: Changing voltage for board from %dmV to %dmV\n",
256*4882a593Smuzhiyun 	      existing_voltage/10, voltage/10);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	if (zm_disable_wp() < 0) {
259*4882a593Smuzhiyun 		ret = -1;
260*4882a593Smuzhiyun 		goto out;
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 	/* Change Voltage: the change is done through all the steps in the
263*4882a593Smuzhiyun 	   way, to avoid reset to the board due to power good signal fail
264*4882a593Smuzhiyun 	   in big voltage change gap jump.
265*4882a593Smuzhiyun 	*/
266*4882a593Smuzhiyun 	if (existing_voltage > voltage) {
267*4882a593Smuzhiyun 		temp_voltage = existing_voltage - ZM_STEP;
268*4882a593Smuzhiyun 			while (temp_voltage >= voltage) {
269*4882a593Smuzhiyun 				ret = zm_write_voltage(temp_voltage);
270*4882a593Smuzhiyun 				if (ret == temp_voltage) {
271*4882a593Smuzhiyun 					temp_voltage -= ZM_STEP;
272*4882a593Smuzhiyun 				} else {
273*4882a593Smuzhiyun 					/* ZM7300 device failed to set
274*4882a593Smuzhiyun 					 * the voltage */
275*4882a593Smuzhiyun 					printf
276*4882a593Smuzhiyun 					("VID:Stepping down vol failed:%dmV\n",
277*4882a593Smuzhiyun 					 temp_voltage/10);
278*4882a593Smuzhiyun 				     ret = -1;
279*4882a593Smuzhiyun 				     goto out;
280*4882a593Smuzhiyun 				}
281*4882a593Smuzhiyun 			}
282*4882a593Smuzhiyun 	} else {
283*4882a593Smuzhiyun 		temp_voltage = existing_voltage + ZM_STEP;
284*4882a593Smuzhiyun 			while (temp_voltage < (voltage + ZM_STEP)) {
285*4882a593Smuzhiyun 				ret = zm_write_voltage(temp_voltage);
286*4882a593Smuzhiyun 				if (ret == temp_voltage) {
287*4882a593Smuzhiyun 					temp_voltage += ZM_STEP;
288*4882a593Smuzhiyun 				} else {
289*4882a593Smuzhiyun 					/* ZM7300 device failed to set
290*4882a593Smuzhiyun 					 * the voltage */
291*4882a593Smuzhiyun 					printf
292*4882a593Smuzhiyun 					("VID:Stepping up vol failed:%dmV\n",
293*4882a593Smuzhiyun 					 temp_voltage/10);
294*4882a593Smuzhiyun 				     ret = -1;
295*4882a593Smuzhiyun 				     goto out;
296*4882a593Smuzhiyun 				}
297*4882a593Smuzhiyun 			}
298*4882a593Smuzhiyun 	}
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	if (zm_enable_wp() < 0)
301*4882a593Smuzhiyun 		ret = -1;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	/* restore the speed to 400kHz */
304*4882a593Smuzhiyun out:	debug("VID: Restore the I2C bus speed to %dKHz\n",
305*4882a593Smuzhiyun 				orig_i2c_speed/1000);
306*4882a593Smuzhiyun 	i2c_set_bus_speed(orig_i2c_speed);
307*4882a593Smuzhiyun 	if (ret < 0)
308*4882a593Smuzhiyun 		goto exit;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	ret = select_i2c_ch_pca(I2C_MUX_CH_VOL_MONITOR);
311*4882a593Smuzhiyun 	if (ret) {
312*4882a593Smuzhiyun 		printf("VID: I2c failed to switch channel\n");
313*4882a593Smuzhiyun 		ret = -1;
314*4882a593Smuzhiyun 		goto exit;
315*4882a593Smuzhiyun 	}
316*4882a593Smuzhiyun 	vdd_last = read_voltage();
317*4882a593Smuzhiyun 	select_i2c_ch_pca(I2C_CH_DEFAULT);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	if (vdd_last > 0)
320*4882a593Smuzhiyun 		printf("VID: Core voltage %d mV\n", vdd_last);
321*4882a593Smuzhiyun 	else
322*4882a593Smuzhiyun 		ret = -1;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun exit:
325*4882a593Smuzhiyun 	if (re_enable)
326*4882a593Smuzhiyun 		enable_interrupts();
327*4882a593Smuzhiyun 	return ret;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
configure_vsc3316_3308(void)330*4882a593Smuzhiyun int configure_vsc3316_3308(void)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
333*4882a593Smuzhiyun 	unsigned int num_vsc16_con, num_vsc08_con;
334*4882a593Smuzhiyun 	u32 serdes1_prtcl, serdes2_prtcl;
335*4882a593Smuzhiyun 	int ret;
336*4882a593Smuzhiyun 	char buffer[HWCONFIG_BUFFER_SIZE];
337*4882a593Smuzhiyun 	char *buf = NULL;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
340*4882a593Smuzhiyun 			FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
341*4882a593Smuzhiyun 	if (!serdes1_prtcl) {
342*4882a593Smuzhiyun 		printf("SERDES1 is not enabled\n");
343*4882a593Smuzhiyun 		return 0;
344*4882a593Smuzhiyun 	}
345*4882a593Smuzhiyun 	serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
346*4882a593Smuzhiyun 	debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
349*4882a593Smuzhiyun 			FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
350*4882a593Smuzhiyun 	if (!serdes2_prtcl) {
351*4882a593Smuzhiyun 		printf("SERDES2 is not enabled\n");
352*4882a593Smuzhiyun 		return 0;
353*4882a593Smuzhiyun 	}
354*4882a593Smuzhiyun 	serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
355*4882a593Smuzhiyun 	debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	switch (serdes1_prtcl) {
358*4882a593Smuzhiyun 	case 0x29:
359*4882a593Smuzhiyun 	case 0x2a:
360*4882a593Smuzhiyun 	case 0x2C:
361*4882a593Smuzhiyun 	case 0x2D:
362*4882a593Smuzhiyun 	case 0x2E:
363*4882a593Smuzhiyun 			/*
364*4882a593Smuzhiyun 			 * Configuration:
365*4882a593Smuzhiyun 			 * SERDES: 1
366*4882a593Smuzhiyun 			 * Lanes: A,B: SGMII
367*4882a593Smuzhiyun 			 * Lanes: C,D,E,F,G,H: CPRI
368*4882a593Smuzhiyun 			 */
369*4882a593Smuzhiyun 		debug("Configuring crossbar to use onboard SGMII PHYs:"
370*4882a593Smuzhiyun 				"srds_prctl:%x\n", serdes1_prtcl);
371*4882a593Smuzhiyun 		num_vsc16_con = NUM_CON_VSC3316;
372*4882a593Smuzhiyun 		/* Configure VSC3316 crossbar switch */
373*4882a593Smuzhiyun 		ret = select_i2c_ch_pca(I2C_CH_VSC3316);
374*4882a593Smuzhiyun 		if (!ret) {
375*4882a593Smuzhiyun 			ret = vsc3316_config(VSC3316_TX_ADDRESS,
376*4882a593Smuzhiyun 					vsc16_tx_4sfp_sgmii_12_56,
377*4882a593Smuzhiyun 					num_vsc16_con);
378*4882a593Smuzhiyun 			if (ret)
379*4882a593Smuzhiyun 				return ret;
380*4882a593Smuzhiyun 			ret = vsc3316_config(VSC3316_RX_ADDRESS,
381*4882a593Smuzhiyun 					vsc16_rx_4sfp_sgmii_12_56,
382*4882a593Smuzhiyun 					num_vsc16_con);
383*4882a593Smuzhiyun 			if (ret)
384*4882a593Smuzhiyun 				return ret;
385*4882a593Smuzhiyun 		} else {
386*4882a593Smuzhiyun 			return ret;
387*4882a593Smuzhiyun 		}
388*4882a593Smuzhiyun 		break;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	case 0x01:
391*4882a593Smuzhiyun 	case 0x02:
392*4882a593Smuzhiyun 	case 0x04:
393*4882a593Smuzhiyun 	case 0x05:
394*4882a593Smuzhiyun 	case 0x06:
395*4882a593Smuzhiyun 	case 0x07:
396*4882a593Smuzhiyun 	case 0x08:
397*4882a593Smuzhiyun 	case 0x09:
398*4882a593Smuzhiyun 	case 0x0A:
399*4882a593Smuzhiyun 	case 0x0B:
400*4882a593Smuzhiyun 	case 0x0C:
401*4882a593Smuzhiyun 	case 0x2F:
402*4882a593Smuzhiyun 	case 0x30:
403*4882a593Smuzhiyun 	case 0x32:
404*4882a593Smuzhiyun 	case 0x33:
405*4882a593Smuzhiyun 	case 0x34:
406*4882a593Smuzhiyun 	case 0x39:
407*4882a593Smuzhiyun 	case 0x3A:
408*4882a593Smuzhiyun 	case 0x3C:
409*4882a593Smuzhiyun 	case 0x3D:
410*4882a593Smuzhiyun 	case 0x5C:
411*4882a593Smuzhiyun 	case 0x5D:
412*4882a593Smuzhiyun 			/*
413*4882a593Smuzhiyun 			 * Configuration:
414*4882a593Smuzhiyun 			 * SERDES: 1
415*4882a593Smuzhiyun 			 * Lanes: A,B: AURORA
416*4882a593Smuzhiyun 			 * Lanes: C,d: SGMII
417*4882a593Smuzhiyun 			 * Lanes: E,F,G,H: CPRI
418*4882a593Smuzhiyun 			 */
419*4882a593Smuzhiyun 		debug("Configuring crossbar for Aurora, SGMII 3 and 4,"
420*4882a593Smuzhiyun 				" and CPRI. srds_prctl:%x\n", serdes1_prtcl);
421*4882a593Smuzhiyun 		num_vsc16_con = NUM_CON_VSC3316;
422*4882a593Smuzhiyun 		/* Configure VSC3316 crossbar switch */
423*4882a593Smuzhiyun 		ret = select_i2c_ch_pca(I2C_CH_VSC3316);
424*4882a593Smuzhiyun 		if (!ret) {
425*4882a593Smuzhiyun 			ret = vsc3316_config(VSC3316_TX_ADDRESS,
426*4882a593Smuzhiyun 					vsc16_tx_sfp_sgmii_aurora,
427*4882a593Smuzhiyun 					num_vsc16_con);
428*4882a593Smuzhiyun 			if (ret)
429*4882a593Smuzhiyun 				return ret;
430*4882a593Smuzhiyun 			ret = vsc3316_config(VSC3316_RX_ADDRESS,
431*4882a593Smuzhiyun 					vsc16_rx_sfp_sgmii_aurora,
432*4882a593Smuzhiyun 					num_vsc16_con);
433*4882a593Smuzhiyun 			if (ret)
434*4882a593Smuzhiyun 				return ret;
435*4882a593Smuzhiyun 		} else {
436*4882a593Smuzhiyun 			return ret;
437*4882a593Smuzhiyun 		}
438*4882a593Smuzhiyun 		break;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun #ifdef CONFIG_ARCH_B4420
441*4882a593Smuzhiyun 	case 0x17:
442*4882a593Smuzhiyun 	case 0x18:
443*4882a593Smuzhiyun 			/*
444*4882a593Smuzhiyun 			 * Configuration:
445*4882a593Smuzhiyun 			 * SERDES: 1
446*4882a593Smuzhiyun 			 * Lanes: A,B,C,D: SGMII
447*4882a593Smuzhiyun 			 * Lanes: E,F,G,H: CPRI
448*4882a593Smuzhiyun 			 */
449*4882a593Smuzhiyun 		debug("Configuring crossbar to use onboard SGMII PHYs:"
450*4882a593Smuzhiyun 				"srds_prctl:%x\n", serdes1_prtcl);
451*4882a593Smuzhiyun 		num_vsc16_con = NUM_CON_VSC3316;
452*4882a593Smuzhiyun 		/* Configure VSC3316 crossbar switch */
453*4882a593Smuzhiyun 		ret = select_i2c_ch_pca(I2C_CH_VSC3316);
454*4882a593Smuzhiyun 		if (!ret) {
455*4882a593Smuzhiyun 			ret = vsc3316_config(VSC3316_TX_ADDRESS,
456*4882a593Smuzhiyun 					vsc16_tx_sgmii_lane_cd, num_vsc16_con);
457*4882a593Smuzhiyun 			if (ret)
458*4882a593Smuzhiyun 				return ret;
459*4882a593Smuzhiyun 			ret = vsc3316_config(VSC3316_RX_ADDRESS,
460*4882a593Smuzhiyun 					vsc16_rx_sgmii_lane_cd, num_vsc16_con);
461*4882a593Smuzhiyun 			if (ret)
462*4882a593Smuzhiyun 				return ret;
463*4882a593Smuzhiyun 		} else {
464*4882a593Smuzhiyun 			return ret;
465*4882a593Smuzhiyun 		}
466*4882a593Smuzhiyun 		break;
467*4882a593Smuzhiyun #endif
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	case 0x3E:
470*4882a593Smuzhiyun 	case 0x0D:
471*4882a593Smuzhiyun 	case 0x0E:
472*4882a593Smuzhiyun 	case 0x12:
473*4882a593Smuzhiyun 		num_vsc16_con = NUM_CON_VSC3316;
474*4882a593Smuzhiyun 		/* Configure VSC3316 crossbar switch */
475*4882a593Smuzhiyun 		ret = select_i2c_ch_pca(I2C_CH_VSC3316);
476*4882a593Smuzhiyun 		if (!ret) {
477*4882a593Smuzhiyun 			ret = vsc3316_config(VSC3316_TX_ADDRESS,
478*4882a593Smuzhiyun 					vsc16_tx_sfp, num_vsc16_con);
479*4882a593Smuzhiyun 			if (ret)
480*4882a593Smuzhiyun 				return ret;
481*4882a593Smuzhiyun 			ret = vsc3316_config(VSC3316_RX_ADDRESS,
482*4882a593Smuzhiyun 					vsc16_rx_sfp, num_vsc16_con);
483*4882a593Smuzhiyun 			if (ret)
484*4882a593Smuzhiyun 				return ret;
485*4882a593Smuzhiyun 		} else {
486*4882a593Smuzhiyun 			return ret;
487*4882a593Smuzhiyun 		}
488*4882a593Smuzhiyun 		break;
489*4882a593Smuzhiyun 	default:
490*4882a593Smuzhiyun 		printf("WARNING:VSC crossbars programming not supported for:%x"
491*4882a593Smuzhiyun 					" SerDes1 Protocol.\n", serdes1_prtcl);
492*4882a593Smuzhiyun 		return -1;
493*4882a593Smuzhiyun 	}
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	num_vsc08_con = NUM_CON_VSC3308;
496*4882a593Smuzhiyun 	/* Configure VSC3308 crossbar switch */
497*4882a593Smuzhiyun 	ret = select_i2c_ch_pca(I2C_CH_VSC3308);
498*4882a593Smuzhiyun 	switch (serdes2_prtcl) {
499*4882a593Smuzhiyun #ifdef CONFIG_ARCH_B4420
500*4882a593Smuzhiyun 	case 0x9d:
501*4882a593Smuzhiyun #endif
502*4882a593Smuzhiyun 	case 0x9E:
503*4882a593Smuzhiyun 	case 0x9A:
504*4882a593Smuzhiyun 	case 0x98:
505*4882a593Smuzhiyun 	case 0x48:
506*4882a593Smuzhiyun 	case 0x49:
507*4882a593Smuzhiyun 	case 0x4E:
508*4882a593Smuzhiyun 	case 0x79:
509*4882a593Smuzhiyun 	case 0x7A:
510*4882a593Smuzhiyun 		if (!ret) {
511*4882a593Smuzhiyun 			ret = vsc3308_config(VSC3308_TX_ADDRESS,
512*4882a593Smuzhiyun 					vsc08_tx_amc, num_vsc08_con);
513*4882a593Smuzhiyun 			if (ret)
514*4882a593Smuzhiyun 				return ret;
515*4882a593Smuzhiyun 			ret = vsc3308_config(VSC3308_RX_ADDRESS,
516*4882a593Smuzhiyun 					vsc08_rx_amc, num_vsc08_con);
517*4882a593Smuzhiyun 			if (ret)
518*4882a593Smuzhiyun 				return ret;
519*4882a593Smuzhiyun 		} else {
520*4882a593Smuzhiyun 			return ret;
521*4882a593Smuzhiyun 		}
522*4882a593Smuzhiyun 		break;
523*4882a593Smuzhiyun 	case 0x80:
524*4882a593Smuzhiyun 	case 0x81:
525*4882a593Smuzhiyun 	case 0x82:
526*4882a593Smuzhiyun 	case 0x83:
527*4882a593Smuzhiyun 	case 0x84:
528*4882a593Smuzhiyun 	case 0x85:
529*4882a593Smuzhiyun 	case 0x86:
530*4882a593Smuzhiyun 	case 0x87:
531*4882a593Smuzhiyun 	case 0x88:
532*4882a593Smuzhiyun 	case 0x89:
533*4882a593Smuzhiyun 	case 0x8a:
534*4882a593Smuzhiyun 	case 0x8b:
535*4882a593Smuzhiyun 	case 0x8c:
536*4882a593Smuzhiyun 	case 0x8d:
537*4882a593Smuzhiyun 	case 0x8e:
538*4882a593Smuzhiyun 	case 0xb1:
539*4882a593Smuzhiyun 	case 0xb2:
540*4882a593Smuzhiyun 		if (!ret) {
541*4882a593Smuzhiyun 			/*
542*4882a593Smuzhiyun 			 * Extract hwconfig from environment since environment
543*4882a593Smuzhiyun 			 * is not setup properly yet
544*4882a593Smuzhiyun 			 */
545*4882a593Smuzhiyun 			env_get_f("hwconfig", buffer, sizeof(buffer));
546*4882a593Smuzhiyun 			buf = buffer;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 			if (hwconfig_subarg_cmp_f("fsl_b4860_serdes2",
549*4882a593Smuzhiyun 						  "sfp_amc", "sfp", buf)) {
550*4882a593Smuzhiyun #ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR
551*4882a593Smuzhiyun 				/* change default VSC3308 for XFI erratum */
552*4882a593Smuzhiyun 				ret = vsc3308_config_adjust(VSC3308_TX_ADDRESS,
553*4882a593Smuzhiyun 						vsc08_tx_sfp, num_vsc08_con);
554*4882a593Smuzhiyun 				if (ret)
555*4882a593Smuzhiyun 					return ret;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 				ret = vsc3308_config_adjust(VSC3308_RX_ADDRESS,
558*4882a593Smuzhiyun 						vsc08_rx_sfp, num_vsc08_con);
559*4882a593Smuzhiyun 				if (ret)
560*4882a593Smuzhiyun 					return ret;
561*4882a593Smuzhiyun #else
562*4882a593Smuzhiyun 				ret = vsc3308_config(VSC3308_TX_ADDRESS,
563*4882a593Smuzhiyun 						vsc08_tx_sfp, num_vsc08_con);
564*4882a593Smuzhiyun 				if (ret)
565*4882a593Smuzhiyun 					return ret;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 				ret = vsc3308_config(VSC3308_RX_ADDRESS,
568*4882a593Smuzhiyun 						vsc08_rx_sfp, num_vsc08_con);
569*4882a593Smuzhiyun 				if (ret)
570*4882a593Smuzhiyun 					return ret;
571*4882a593Smuzhiyun #endif
572*4882a593Smuzhiyun 			} else {
573*4882a593Smuzhiyun 				ret = vsc3308_config(VSC3308_TX_ADDRESS,
574*4882a593Smuzhiyun 						vsc08_tx_amc, num_vsc08_con);
575*4882a593Smuzhiyun 				if (ret)
576*4882a593Smuzhiyun 					return ret;
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 				ret = vsc3308_config(VSC3308_RX_ADDRESS,
579*4882a593Smuzhiyun 						vsc08_rx_amc, num_vsc08_con);
580*4882a593Smuzhiyun 				if (ret)
581*4882a593Smuzhiyun 					return ret;
582*4882a593Smuzhiyun 			}
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 		} else {
585*4882a593Smuzhiyun 			return ret;
586*4882a593Smuzhiyun 		}
587*4882a593Smuzhiyun 		break;
588*4882a593Smuzhiyun 	default:
589*4882a593Smuzhiyun 		printf("WARNING:VSC crossbars programming not supported for: %x"
590*4882a593Smuzhiyun 					" SerDes2 Protocol.\n", serdes2_prtcl);
591*4882a593Smuzhiyun 		return -1;
592*4882a593Smuzhiyun 	}
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	return 0;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun 
calibrate_pll(serdes_corenet_t * srds_regs,int pll_num)597*4882a593Smuzhiyun static int calibrate_pll(serdes_corenet_t *srds_regs, int pll_num)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	u32 rst_err;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	/* Steps For SerDes PLLs reset and reconfiguration
602*4882a593Smuzhiyun 	 * or PLL power-up procedure
603*4882a593Smuzhiyun 	 */
604*4882a593Smuzhiyun 	debug("CALIBRATE PLL:%d\n", pll_num);
605*4882a593Smuzhiyun 	clrbits_be32(&srds_regs->bank[pll_num].rstctl,
606*4882a593Smuzhiyun 			SRDS_RSTCTL_SDRST_B);
607*4882a593Smuzhiyun 	udelay(10);
608*4882a593Smuzhiyun 	clrbits_be32(&srds_regs->bank[pll_num].rstctl,
609*4882a593Smuzhiyun 		(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B));
610*4882a593Smuzhiyun 	udelay(10);
611*4882a593Smuzhiyun 	setbits_be32(&srds_regs->bank[pll_num].rstctl,
612*4882a593Smuzhiyun 			SRDS_RSTCTL_RST);
613*4882a593Smuzhiyun 	setbits_be32(&srds_regs->bank[pll_num].rstctl,
614*4882a593Smuzhiyun 		(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B
615*4882a593Smuzhiyun 		| SRDS_RSTCTL_SDRST_B));
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	udelay(20);
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	/* Check whether PLL has been locked or not */
620*4882a593Smuzhiyun 	rst_err = in_be32(&srds_regs->bank[pll_num].rstctl) &
621*4882a593Smuzhiyun 				SRDS_RSTCTL_RSTERR;
622*4882a593Smuzhiyun 	rst_err >>= SRDS_RSTCTL_RSTERR_SHIFT;
623*4882a593Smuzhiyun 	debug("RST_ERR value for PLL %d is: 0x%x:\n", pll_num, rst_err);
624*4882a593Smuzhiyun 	if (rst_err)
625*4882a593Smuzhiyun 		return rst_err;
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	return rst_err;
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun 
check_pll_locks(serdes_corenet_t * srds_regs,int pll_num)630*4882a593Smuzhiyun static int check_pll_locks(serdes_corenet_t *srds_regs, int pll_num)
631*4882a593Smuzhiyun {
632*4882a593Smuzhiyun 	int ret = 0;
633*4882a593Smuzhiyun 	u32 fcap, dcbias, bcap, pllcr1, pllcr0;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	if (calibrate_pll(srds_regs, pll_num)) {
636*4882a593Smuzhiyun 		/* STEP 1 */
637*4882a593Smuzhiyun 		/* Read fcap, dcbias and bcap value */
638*4882a593Smuzhiyun 		clrbits_be32(&srds_regs->bank[pll_num].pllcr0,
639*4882a593Smuzhiyun 				SRDS_PLLCR0_DCBIAS_OUT_EN);
640*4882a593Smuzhiyun 		fcap = in_be32(&srds_regs->bank[pll_num].pllsr2) &
641*4882a593Smuzhiyun 					SRDS_PLLSR2_FCAP;
642*4882a593Smuzhiyun 		fcap >>= SRDS_PLLSR2_FCAP_SHIFT;
643*4882a593Smuzhiyun 		bcap = in_be32(&srds_regs->bank[pll_num].pllsr2) &
644*4882a593Smuzhiyun 					SRDS_PLLSR2_BCAP_EN;
645*4882a593Smuzhiyun 		bcap >>= SRDS_PLLSR2_BCAP_EN_SHIFT;
646*4882a593Smuzhiyun 		setbits_be32(&srds_regs->bank[pll_num].pllcr0,
647*4882a593Smuzhiyun 				SRDS_PLLCR0_DCBIAS_OUT_EN);
648*4882a593Smuzhiyun 		dcbias = in_be32(&srds_regs->bank[pll_num].pllsr2) &
649*4882a593Smuzhiyun 					SRDS_PLLSR2_DCBIAS;
650*4882a593Smuzhiyun 		dcbias >>= SRDS_PLLSR2_DCBIAS_SHIFT;
651*4882a593Smuzhiyun 		debug("values of bcap:%x, fcap:%x and dcbias:%x\n",
652*4882a593Smuzhiyun 					bcap, fcap, dcbias);
653*4882a593Smuzhiyun 		if (fcap == 0 && bcap == 1) {
654*4882a593Smuzhiyun 			/* Step 3 */
655*4882a593Smuzhiyun 			clrbits_be32(&srds_regs->bank[pll_num].rstctl,
656*4882a593Smuzhiyun 				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B
657*4882a593Smuzhiyun 				 | SRDS_RSTCTL_SDRST_B));
658*4882a593Smuzhiyun 			clrbits_be32(&srds_regs->bank[pll_num].pllcr1,
659*4882a593Smuzhiyun 					SRDS_PLLCR1_BCAP_EN);
660*4882a593Smuzhiyun 			setbits_be32(&srds_regs->bank[pll_num].pllcr1,
661*4882a593Smuzhiyun 					SRDS_PLLCR1_BCAP_OVD);
662*4882a593Smuzhiyun 			if (calibrate_pll(srds_regs, pll_num)) {
663*4882a593Smuzhiyun 				/*save the fcap, dcbias and bcap values*/
664*4882a593Smuzhiyun 				clrbits_be32(&srds_regs->bank[pll_num].pllcr0,
665*4882a593Smuzhiyun 						SRDS_PLLCR0_DCBIAS_OUT_EN);
666*4882a593Smuzhiyun 				fcap = in_be32(&srds_regs->bank[pll_num].pllsr2)
667*4882a593Smuzhiyun 					& SRDS_PLLSR2_FCAP;
668*4882a593Smuzhiyun 				fcap >>= SRDS_PLLSR2_FCAP_SHIFT;
669*4882a593Smuzhiyun 				bcap = in_be32(&srds_regs->bank[pll_num].pllsr2)
670*4882a593Smuzhiyun 					& SRDS_PLLSR2_BCAP_EN;
671*4882a593Smuzhiyun 				bcap >>= SRDS_PLLSR2_BCAP_EN_SHIFT;
672*4882a593Smuzhiyun 				setbits_be32(&srds_regs->bank[pll_num].pllcr0,
673*4882a593Smuzhiyun 						SRDS_PLLCR0_DCBIAS_OUT_EN);
674*4882a593Smuzhiyun 				dcbias = in_be32
675*4882a593Smuzhiyun 					(&srds_regs->bank[pll_num].pllsr2) &
676*4882a593Smuzhiyun 							SRDS_PLLSR2_DCBIAS;
677*4882a593Smuzhiyun 				dcbias >>= SRDS_PLLSR2_DCBIAS_SHIFT;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 				/* Step 4*/
680*4882a593Smuzhiyun 				clrbits_be32(&srds_regs->bank[pll_num].rstctl,
681*4882a593Smuzhiyun 				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B
682*4882a593Smuzhiyun 				 | SRDS_RSTCTL_SDRST_B));
683*4882a593Smuzhiyun 				setbits_be32(&srds_regs->bank[pll_num].pllcr1,
684*4882a593Smuzhiyun 						SRDS_PLLCR1_BYP_CAL);
685*4882a593Smuzhiyun 				clrbits_be32(&srds_regs->bank[pll_num].pllcr1,
686*4882a593Smuzhiyun 						SRDS_PLLCR1_BCAP_EN);
687*4882a593Smuzhiyun 				setbits_be32(&srds_regs->bank[pll_num].pllcr1,
688*4882a593Smuzhiyun 						SRDS_PLLCR1_BCAP_OVD);
689*4882a593Smuzhiyun 				/* change the fcap and dcbias to the saved
690*4882a593Smuzhiyun 				 * values from Step 3 */
691*4882a593Smuzhiyun 				clrbits_be32(&srds_regs->bank[pll_num].pllcr1,
692*4882a593Smuzhiyun 							SRDS_PLLCR1_PLL_FCAP);
693*4882a593Smuzhiyun 				pllcr1 = (in_be32
694*4882a593Smuzhiyun 					(&srds_regs->bank[pll_num].pllcr1)|
695*4882a593Smuzhiyun 					(fcap << SRDS_PLLCR1_PLL_FCAP_SHIFT));
696*4882a593Smuzhiyun 				out_be32(&srds_regs->bank[pll_num].pllcr1,
697*4882a593Smuzhiyun 							pllcr1);
698*4882a593Smuzhiyun 				clrbits_be32(&srds_regs->bank[pll_num].pllcr0,
699*4882a593Smuzhiyun 						SRDS_PLLCR0_DCBIAS_OVRD);
700*4882a593Smuzhiyun 				pllcr0 = (in_be32
701*4882a593Smuzhiyun 				(&srds_regs->bank[pll_num].pllcr0)|
702*4882a593Smuzhiyun 				(dcbias << SRDS_PLLCR0_DCBIAS_OVRD_SHIFT));
703*4882a593Smuzhiyun 				out_be32(&srds_regs->bank[pll_num].pllcr0,
704*4882a593Smuzhiyun 							pllcr0);
705*4882a593Smuzhiyun 				ret = calibrate_pll(srds_regs, pll_num);
706*4882a593Smuzhiyun 				if (ret)
707*4882a593Smuzhiyun 					return ret;
708*4882a593Smuzhiyun 			} else {
709*4882a593Smuzhiyun 				goto out;
710*4882a593Smuzhiyun 			}
711*4882a593Smuzhiyun 		} else { /* Step 5 */
712*4882a593Smuzhiyun 			clrbits_be32(&srds_regs->bank[pll_num].rstctl,
713*4882a593Smuzhiyun 				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B
714*4882a593Smuzhiyun 				 | SRDS_RSTCTL_SDRST_B));
715*4882a593Smuzhiyun 			udelay(10);
716*4882a593Smuzhiyun 			/* Change the fcap, dcbias, and bcap to the
717*4882a593Smuzhiyun 			 * values from Step 1 */
718*4882a593Smuzhiyun 			setbits_be32(&srds_regs->bank[pll_num].pllcr1,
719*4882a593Smuzhiyun 					SRDS_PLLCR1_BYP_CAL);
720*4882a593Smuzhiyun 			clrbits_be32(&srds_regs->bank[pll_num].pllcr1,
721*4882a593Smuzhiyun 						SRDS_PLLCR1_PLL_FCAP);
722*4882a593Smuzhiyun 			pllcr1 = (in_be32(&srds_regs->bank[pll_num].pllcr1)|
723*4882a593Smuzhiyun 				(fcap << SRDS_PLLCR1_PLL_FCAP_SHIFT));
724*4882a593Smuzhiyun 			out_be32(&srds_regs->bank[pll_num].pllcr1,
725*4882a593Smuzhiyun 						pllcr1);
726*4882a593Smuzhiyun 			clrbits_be32(&srds_regs->bank[pll_num].pllcr0,
727*4882a593Smuzhiyun 						SRDS_PLLCR0_DCBIAS_OVRD);
728*4882a593Smuzhiyun 			pllcr0 = (in_be32(&srds_regs->bank[pll_num].pllcr0)|
729*4882a593Smuzhiyun 				(dcbias << SRDS_PLLCR0_DCBIAS_OVRD_SHIFT));
730*4882a593Smuzhiyun 			out_be32(&srds_regs->bank[pll_num].pllcr0,
731*4882a593Smuzhiyun 						pllcr0);
732*4882a593Smuzhiyun 			clrbits_be32(&srds_regs->bank[pll_num].pllcr1,
733*4882a593Smuzhiyun 					SRDS_PLLCR1_BCAP_EN);
734*4882a593Smuzhiyun 			setbits_be32(&srds_regs->bank[pll_num].pllcr1,
735*4882a593Smuzhiyun 					SRDS_PLLCR1_BCAP_OVD);
736*4882a593Smuzhiyun 			ret = calibrate_pll(srds_regs, pll_num);
737*4882a593Smuzhiyun 			if (ret)
738*4882a593Smuzhiyun 				return ret;
739*4882a593Smuzhiyun 		}
740*4882a593Smuzhiyun 	}
741*4882a593Smuzhiyun out:
742*4882a593Smuzhiyun 	return 0;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun 
check_serdes_pll_locks(void)745*4882a593Smuzhiyun static int check_serdes_pll_locks(void)
746*4882a593Smuzhiyun {
747*4882a593Smuzhiyun 	serdes_corenet_t *srds1_regs =
748*4882a593Smuzhiyun 		(void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
749*4882a593Smuzhiyun 	serdes_corenet_t *srds2_regs =
750*4882a593Smuzhiyun 		(void *)CONFIG_SYS_FSL_CORENET_SERDES2_ADDR;
751*4882a593Smuzhiyun 	int i, ret1, ret2;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	debug("\nSerDes1 Lock check\n");
754*4882a593Smuzhiyun 	for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) {
755*4882a593Smuzhiyun 		ret1 = check_pll_locks(srds1_regs, i);
756*4882a593Smuzhiyun 		if (ret1) {
757*4882a593Smuzhiyun 			printf("SerDes1, PLL:%d didnt lock\n", i);
758*4882a593Smuzhiyun 			return ret1;
759*4882a593Smuzhiyun 		}
760*4882a593Smuzhiyun 	}
761*4882a593Smuzhiyun 	debug("\nSerDes2 Lock check\n");
762*4882a593Smuzhiyun 	for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) {
763*4882a593Smuzhiyun 		ret2 = check_pll_locks(srds2_regs, i);
764*4882a593Smuzhiyun 		if (ret2) {
765*4882a593Smuzhiyun 			printf("SerDes2, PLL:%d didnt lock\n", i);
766*4882a593Smuzhiyun 			return ret2;
767*4882a593Smuzhiyun 		}
768*4882a593Smuzhiyun 	}
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	return 0;
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun 
config_serdes1_refclks(void)773*4882a593Smuzhiyun int config_serdes1_refclks(void)
774*4882a593Smuzhiyun {
775*4882a593Smuzhiyun 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
776*4882a593Smuzhiyun 	serdes_corenet_t *srds_regs =
777*4882a593Smuzhiyun 		(void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
778*4882a593Smuzhiyun 	u32 serdes1_prtcl, lane;
779*4882a593Smuzhiyun 	unsigned int flag_sgmii_aurora_prtcl = 0;
780*4882a593Smuzhiyun 	int i;
781*4882a593Smuzhiyun 	int ret = 0;
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
784*4882a593Smuzhiyun 			FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
785*4882a593Smuzhiyun 	if (!serdes1_prtcl) {
786*4882a593Smuzhiyun 		printf("SERDES1 is not enabled\n");
787*4882a593Smuzhiyun 		return -1;
788*4882a593Smuzhiyun 	}
789*4882a593Smuzhiyun 	serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
790*4882a593Smuzhiyun 	debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 	/* To prevent generation of reset request from SerDes
793*4882a593Smuzhiyun 	 * while changing the refclks, By setting SRDS_RST_MSK bit,
794*4882a593Smuzhiyun 	 * SerDes reset event cannot cause a reset request
795*4882a593Smuzhiyun 	 */
796*4882a593Smuzhiyun 	setbits_be32(&gur->rstrqmr1, FSL_CORENET_RSTRQMR1_SRDS_RST_MSK);
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	/* Reconfigure IDT idt8t49n222a device for CPRI to work
799*4882a593Smuzhiyun 	 * For this SerDes1's Refclk1 and refclk2 need to be set
800*4882a593Smuzhiyun 	 * to 122.88MHz
801*4882a593Smuzhiyun 	 */
802*4882a593Smuzhiyun 	switch (serdes1_prtcl) {
803*4882a593Smuzhiyun 	case 0x29:
804*4882a593Smuzhiyun 	case 0x2A:
805*4882a593Smuzhiyun 	case 0x2C:
806*4882a593Smuzhiyun 	case 0x2D:
807*4882a593Smuzhiyun 	case 0x2E:
808*4882a593Smuzhiyun 	case 0x01:
809*4882a593Smuzhiyun 	case 0x02:
810*4882a593Smuzhiyun 	case 0x04:
811*4882a593Smuzhiyun 	case 0x05:
812*4882a593Smuzhiyun 	case 0x06:
813*4882a593Smuzhiyun 	case 0x07:
814*4882a593Smuzhiyun 	case 0x08:
815*4882a593Smuzhiyun 	case 0x09:
816*4882a593Smuzhiyun 	case 0x0A:
817*4882a593Smuzhiyun 	case 0x0B:
818*4882a593Smuzhiyun 	case 0x0C:
819*4882a593Smuzhiyun 	case 0x2F:
820*4882a593Smuzhiyun 	case 0x30:
821*4882a593Smuzhiyun 	case 0x32:
822*4882a593Smuzhiyun 	case 0x33:
823*4882a593Smuzhiyun 	case 0x34:
824*4882a593Smuzhiyun 	case 0x39:
825*4882a593Smuzhiyun 	case 0x3A:
826*4882a593Smuzhiyun 	case 0x3C:
827*4882a593Smuzhiyun 	case 0x3D:
828*4882a593Smuzhiyun 	case 0x5C:
829*4882a593Smuzhiyun 	case 0x5D:
830*4882a593Smuzhiyun 		debug("Configuring idt8t49n222a for CPRI SerDes clks:"
831*4882a593Smuzhiyun 			" for srds_prctl:%x\n", serdes1_prtcl);
832*4882a593Smuzhiyun 		ret = select_i2c_ch_pca(I2C_CH_IDT);
833*4882a593Smuzhiyun 		if (!ret) {
834*4882a593Smuzhiyun 			ret = set_serdes_refclk(IDT_SERDES1_ADDRESS, 1,
835*4882a593Smuzhiyun 					SERDES_REFCLK_122_88,
836*4882a593Smuzhiyun 					SERDES_REFCLK_122_88, 0);
837*4882a593Smuzhiyun 			if (ret) {
838*4882a593Smuzhiyun 				printf("IDT8T49N222A configuration failed.\n");
839*4882a593Smuzhiyun 				goto out;
840*4882a593Smuzhiyun 			} else
841*4882a593Smuzhiyun 				debug("IDT8T49N222A configured.\n");
842*4882a593Smuzhiyun 		} else {
843*4882a593Smuzhiyun 			goto out;
844*4882a593Smuzhiyun 		}
845*4882a593Smuzhiyun 		select_i2c_ch_pca(I2C_CH_DEFAULT);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 		/* Change SerDes1's Refclk1 to 125MHz for on board
848*4882a593Smuzhiyun 		 * SGMIIs or Aurora to work
849*4882a593Smuzhiyun 		 */
850*4882a593Smuzhiyun 		for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
851*4882a593Smuzhiyun 			enum srds_prtcl lane_prtcl = serdes_get_prtcl
852*4882a593Smuzhiyun 						(0, serdes1_prtcl, lane);
853*4882a593Smuzhiyun 			switch (lane_prtcl) {
854*4882a593Smuzhiyun 			case SGMII_FM1_DTSEC1:
855*4882a593Smuzhiyun 			case SGMII_FM1_DTSEC2:
856*4882a593Smuzhiyun 			case SGMII_FM1_DTSEC3:
857*4882a593Smuzhiyun 			case SGMII_FM1_DTSEC4:
858*4882a593Smuzhiyun 			case SGMII_FM1_DTSEC5:
859*4882a593Smuzhiyun 			case SGMII_FM1_DTSEC6:
860*4882a593Smuzhiyun 			case AURORA:
861*4882a593Smuzhiyun 				flag_sgmii_aurora_prtcl++;
862*4882a593Smuzhiyun 				break;
863*4882a593Smuzhiyun 			default:
864*4882a593Smuzhiyun 				break;
865*4882a593Smuzhiyun 			}
866*4882a593Smuzhiyun 		}
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 		if (flag_sgmii_aurora_prtcl)
869*4882a593Smuzhiyun 			QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125);
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 		/* Steps For SerDes PLLs reset and reconfiguration after
872*4882a593Smuzhiyun 		 * changing SerDes's refclks
873*4882a593Smuzhiyun 		 */
874*4882a593Smuzhiyun 		for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) {
875*4882a593Smuzhiyun 			debug("For PLL%d reset and reconfiguration after"
876*4882a593Smuzhiyun 			       " changing refclks\n", i+1);
877*4882a593Smuzhiyun 			clrbits_be32(&srds_regs->bank[i].rstctl,
878*4882a593Smuzhiyun 					SRDS_RSTCTL_SDRST_B);
879*4882a593Smuzhiyun 			udelay(10);
880*4882a593Smuzhiyun 			clrbits_be32(&srds_regs->bank[i].rstctl,
881*4882a593Smuzhiyun 				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B));
882*4882a593Smuzhiyun 			udelay(10);
883*4882a593Smuzhiyun 			setbits_be32(&srds_regs->bank[i].rstctl,
884*4882a593Smuzhiyun 					SRDS_RSTCTL_RST);
885*4882a593Smuzhiyun 			setbits_be32(&srds_regs->bank[i].rstctl,
886*4882a593Smuzhiyun 				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B
887*4882a593Smuzhiyun 				| SRDS_RSTCTL_SDRST_B));
888*4882a593Smuzhiyun 		}
889*4882a593Smuzhiyun 		break;
890*4882a593Smuzhiyun 	default:
891*4882a593Smuzhiyun 		printf("WARNING:IDT8T49N222A configuration not"
892*4882a593Smuzhiyun 			" supported for:%x SerDes1 Protocol.\n",
893*4882a593Smuzhiyun 			serdes1_prtcl);
894*4882a593Smuzhiyun 	}
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun out:
897*4882a593Smuzhiyun 	/* Clearing SRDS_RST_MSK bit as now
898*4882a593Smuzhiyun 	 * SerDes reset event can cause a reset request
899*4882a593Smuzhiyun 	 */
900*4882a593Smuzhiyun 	clrbits_be32(&gur->rstrqmr1, FSL_CORENET_RSTRQMR1_SRDS_RST_MSK);
901*4882a593Smuzhiyun 	return ret;
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun 
config_serdes2_refclks(void)904*4882a593Smuzhiyun int config_serdes2_refclks(void)
905*4882a593Smuzhiyun {
906*4882a593Smuzhiyun 	ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
907*4882a593Smuzhiyun 	serdes_corenet_t *srds2_regs =
908*4882a593Smuzhiyun 		(void *)CONFIG_SYS_FSL_CORENET_SERDES2_ADDR;
909*4882a593Smuzhiyun 	u32 serdes2_prtcl;
910*4882a593Smuzhiyun 	int ret = 0;
911*4882a593Smuzhiyun 	int i;
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
914*4882a593Smuzhiyun 			FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
915*4882a593Smuzhiyun 	if (!serdes2_prtcl) {
916*4882a593Smuzhiyun 		debug("SERDES2 is not enabled\n");
917*4882a593Smuzhiyun 		return -ENODEV;
918*4882a593Smuzhiyun 	}
919*4882a593Smuzhiyun 	serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
920*4882a593Smuzhiyun 	debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 	/* To prevent generation of reset request from SerDes
923*4882a593Smuzhiyun 	 * while changing the refclks, By setting SRDS_RST_MSK bit,
924*4882a593Smuzhiyun 	 * SerDes reset event cannot cause a reset request
925*4882a593Smuzhiyun 	 */
926*4882a593Smuzhiyun 	setbits_be32(&gur->rstrqmr1, FSL_CORENET_RSTRQMR1_SRDS_RST_MSK);
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 	/* Reconfigure IDT idt8t49n222a device for PCIe SATA to work
929*4882a593Smuzhiyun 	 * For this SerDes2's Refclk1 need to be set to 100MHz
930*4882a593Smuzhiyun 	 */
931*4882a593Smuzhiyun 	switch (serdes2_prtcl) {
932*4882a593Smuzhiyun #ifdef CONFIG_ARCH_B4420
933*4882a593Smuzhiyun 	case 0x9d:
934*4882a593Smuzhiyun #endif
935*4882a593Smuzhiyun 	case 0x9E:
936*4882a593Smuzhiyun 	case 0x9A:
937*4882a593Smuzhiyun 		/* fallthrough */
938*4882a593Smuzhiyun 	case 0xb1:
939*4882a593Smuzhiyun 	case 0xb2:
940*4882a593Smuzhiyun 		debug("Configuring IDT for PCIe SATA for srds_prctl:%x\n",
941*4882a593Smuzhiyun 			serdes2_prtcl);
942*4882a593Smuzhiyun 		ret = select_i2c_ch_pca(I2C_CH_IDT);
943*4882a593Smuzhiyun 		if (!ret) {
944*4882a593Smuzhiyun 			ret = set_serdes_refclk(IDT_SERDES2_ADDRESS, 2,
945*4882a593Smuzhiyun 					SERDES_REFCLK_100,
946*4882a593Smuzhiyun 					SERDES_REFCLK_156_25, 0);
947*4882a593Smuzhiyun 			if (ret) {
948*4882a593Smuzhiyun 				printf("IDT8T49N222A configuration failed.\n");
949*4882a593Smuzhiyun 				goto out;
950*4882a593Smuzhiyun 			} else
951*4882a593Smuzhiyun 				debug("IDT8T49N222A configured.\n");
952*4882a593Smuzhiyun 		} else {
953*4882a593Smuzhiyun 			goto out;
954*4882a593Smuzhiyun 		}
955*4882a593Smuzhiyun 		select_i2c_ch_pca(I2C_CH_DEFAULT);
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun 		/* Steps For SerDes PLLs reset and reconfiguration after
958*4882a593Smuzhiyun 		 * changing SerDes's refclks
959*4882a593Smuzhiyun 		 */
960*4882a593Smuzhiyun 		for (i = 0; i < CONFIG_SYS_FSL_SRDS_NUM_PLLS; i++) {
961*4882a593Smuzhiyun 			clrbits_be32(&srds2_regs->bank[i].rstctl,
962*4882a593Smuzhiyun 					SRDS_RSTCTL_SDRST_B);
963*4882a593Smuzhiyun 			udelay(10);
964*4882a593Smuzhiyun 			clrbits_be32(&srds2_regs->bank[i].rstctl,
965*4882a593Smuzhiyun 				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B));
966*4882a593Smuzhiyun 			udelay(10);
967*4882a593Smuzhiyun 			setbits_be32(&srds2_regs->bank[i].rstctl,
968*4882a593Smuzhiyun 					SRDS_RSTCTL_RST);
969*4882a593Smuzhiyun 			setbits_be32(&srds2_regs->bank[i].rstctl,
970*4882a593Smuzhiyun 				(SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B
971*4882a593Smuzhiyun 				| SRDS_RSTCTL_SDRST_B));
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun 			udelay(10);
974*4882a593Smuzhiyun 		}
975*4882a593Smuzhiyun 		break;
976*4882a593Smuzhiyun 	default:
977*4882a593Smuzhiyun 		printf("IDT configuration not supported for:%x S2 Protocol.\n",
978*4882a593Smuzhiyun 			serdes2_prtcl);
979*4882a593Smuzhiyun 	}
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun out:
982*4882a593Smuzhiyun 	/* Clearing SRDS_RST_MSK bit as now
983*4882a593Smuzhiyun 	 * SerDes reset event can cause a reset request
984*4882a593Smuzhiyun 	 */
985*4882a593Smuzhiyun 	clrbits_be32(&gur->rstrqmr1, FSL_CORENET_RSTRQMR1_SRDS_RST_MSK);
986*4882a593Smuzhiyun 	return ret;
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun 
board_early_init_r(void)989*4882a593Smuzhiyun int board_early_init_r(void)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun 	const unsigned int flashbase = CONFIG_SYS_FLASH_BASE;
992*4882a593Smuzhiyun 	int flash_esel = find_tlb_idx((void *)flashbase, 1);
993*4882a593Smuzhiyun 	int ret;
994*4882a593Smuzhiyun 	u32 svr = SVR_SOC_VER(get_svr());
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 	/* Create law for MAPLE only for personalities having MAPLE */
997*4882a593Smuzhiyun 	if ((svr == SVR_B4860) || (svr == SVR_B4440) ||
998*4882a593Smuzhiyun 	    (svr == SVR_B4420) || (svr == SVR_B4220)) {
999*4882a593Smuzhiyun 		set_next_law(CONFIG_SYS_MAPLE_MEM_PHYS, LAW_SIZE_16M,
1000*4882a593Smuzhiyun 			     LAW_TRGT_IF_MAPLE);
1001*4882a593Smuzhiyun 	}
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun 	/*
1004*4882a593Smuzhiyun 	 * Remap Boot flash + PROMJET region to caching-inhibited
1005*4882a593Smuzhiyun 	 * so that flash can be erased properly.
1006*4882a593Smuzhiyun 	 */
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	/* Flush d-cache and invalidate i-cache of any FLASH data */
1009*4882a593Smuzhiyun 	flush_dcache();
1010*4882a593Smuzhiyun 	invalidate_icache();
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun 	if (flash_esel == -1) {
1013*4882a593Smuzhiyun 		/* very unlikely unless something is messed up */
1014*4882a593Smuzhiyun 		puts("Error: Could not find TLB for FLASH BASE\n");
1015*4882a593Smuzhiyun 		flash_esel = 2;	/* give our best effort to continue */
1016*4882a593Smuzhiyun 	} else {
1017*4882a593Smuzhiyun 		/* invalidate existing TLB entry for flash + promjet */
1018*4882a593Smuzhiyun 		disable_tlb(flash_esel);
1019*4882a593Smuzhiyun 	}
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 	set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS,
1022*4882a593Smuzhiyun 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
1023*4882a593Smuzhiyun 			0, flash_esel, BOOKE_PAGESZ_256M, 1);
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun 	/*
1026*4882a593Smuzhiyun 	 * Adjust core voltage according to voltage ID
1027*4882a593Smuzhiyun 	 * This function changes I2C mux to channel 2.
1028*4882a593Smuzhiyun 	 */
1029*4882a593Smuzhiyun 	if (adjust_vdd(0) < 0)
1030*4882a593Smuzhiyun 		printf("Warning: Adjusting core voltage failed\n");
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	/* SerDes1 refclks need to be set again, as default clks
1033*4882a593Smuzhiyun 	 * are not suitable for CPRI and onboard SGMIIs to work
1034*4882a593Smuzhiyun 	 * simultaneously.
1035*4882a593Smuzhiyun 	 * This function will set SerDes1's Refclk1 and refclk2
1036*4882a593Smuzhiyun 	 * as per SerDes1 protocols
1037*4882a593Smuzhiyun 	 */
1038*4882a593Smuzhiyun 	if (config_serdes1_refclks())
1039*4882a593Smuzhiyun 		printf("SerDes1 Refclks couldn't set properly.\n");
1040*4882a593Smuzhiyun 	else
1041*4882a593Smuzhiyun 		printf("SerDes1 Refclks have been set.\n");
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun 	/* SerDes2 refclks need to be set again, as default clks
1044*4882a593Smuzhiyun 	 * are not suitable for PCIe SATA to work
1045*4882a593Smuzhiyun 	 * This function will set SerDes2's Refclk1 and refclk2
1046*4882a593Smuzhiyun 	 * for SerDes2 protocols having PCIe in them
1047*4882a593Smuzhiyun 	 * for PCIe SATA to work
1048*4882a593Smuzhiyun 	 */
1049*4882a593Smuzhiyun 	ret = config_serdes2_refclks();
1050*4882a593Smuzhiyun 	if (!ret)
1051*4882a593Smuzhiyun 		printf("SerDes2 Refclks have been set.\n");
1052*4882a593Smuzhiyun 	else if (ret == -ENODEV)
1053*4882a593Smuzhiyun 		printf("SerDes disable, Refclks couldn't change.\n");
1054*4882a593Smuzhiyun 	else
1055*4882a593Smuzhiyun 		printf("SerDes2 Refclk reconfiguring failed.\n");
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun #if defined(CONFIG_SYS_FSL_ERRATUM_A006384) || \
1058*4882a593Smuzhiyun 			defined(CONFIG_SYS_FSL_ERRATUM_A006475)
1059*4882a593Smuzhiyun 	/* Rechecking the SerDes locks after all SerDes configurations
1060*4882a593Smuzhiyun 	 * are done, As SerDes PLLs may not lock reliably at 5 G VCO
1061*4882a593Smuzhiyun 	 * and at cold temperatures.
1062*4882a593Smuzhiyun 	 * Following sequence ensure the proper locking of SerDes PLLs.
1063*4882a593Smuzhiyun 	 */
1064*4882a593Smuzhiyun 	if (SVR_MAJ(get_svr()) == 1) {
1065*4882a593Smuzhiyun 		if (check_serdes_pll_locks())
1066*4882a593Smuzhiyun 			printf("SerDes plls still not locked properly.\n");
1067*4882a593Smuzhiyun 		else
1068*4882a593Smuzhiyun 			printf("SerDes plls have been locked well.\n");
1069*4882a593Smuzhiyun 	}
1070*4882a593Smuzhiyun #endif
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun 	/* Configure VSC3316 and VSC3308 crossbar switches */
1073*4882a593Smuzhiyun 	if (configure_vsc3316_3308())
1074*4882a593Smuzhiyun 		printf("VSC:failed to configure VSC3316/3308.\n");
1075*4882a593Smuzhiyun 	else
1076*4882a593Smuzhiyun 		printf("VSC:VSC3316/3308 successfully configured.\n");
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun 	select_i2c_ch_pca(I2C_CH_DEFAULT);
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	return 0;
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun 
get_board_sys_clk(void)1083*4882a593Smuzhiyun unsigned long get_board_sys_clk(void)
1084*4882a593Smuzhiyun {
1085*4882a593Smuzhiyun 	u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	switch ((sysclk_conf & 0x0C) >> 2) {
1088*4882a593Smuzhiyun 	case QIXIS_CLK_100:
1089*4882a593Smuzhiyun 		return 100000000;
1090*4882a593Smuzhiyun 	case QIXIS_CLK_125:
1091*4882a593Smuzhiyun 		return 125000000;
1092*4882a593Smuzhiyun 	case QIXIS_CLK_133:
1093*4882a593Smuzhiyun 		return 133333333;
1094*4882a593Smuzhiyun 	}
1095*4882a593Smuzhiyun 	return 66666666;
1096*4882a593Smuzhiyun }
1097*4882a593Smuzhiyun 
get_board_ddr_clk(void)1098*4882a593Smuzhiyun unsigned long get_board_ddr_clk(void)
1099*4882a593Smuzhiyun {
1100*4882a593Smuzhiyun 	u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun 	switch (ddrclk_conf & 0x03) {
1103*4882a593Smuzhiyun 	case QIXIS_CLK_100:
1104*4882a593Smuzhiyun 		return 100000000;
1105*4882a593Smuzhiyun 	case QIXIS_CLK_125:
1106*4882a593Smuzhiyun 		return 125000000;
1107*4882a593Smuzhiyun 	case QIXIS_CLK_133:
1108*4882a593Smuzhiyun 		return 133333333;
1109*4882a593Smuzhiyun 	}
1110*4882a593Smuzhiyun 	return 66666666;
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun 
serdes_refclock(u8 sw,u8 sdclk)1113*4882a593Smuzhiyun static int serdes_refclock(u8 sw, u8 sdclk)
1114*4882a593Smuzhiyun {
1115*4882a593Smuzhiyun 	unsigned int clock;
1116*4882a593Smuzhiyun 	int ret = -1;
1117*4882a593Smuzhiyun 	u8 brdcfg4;
1118*4882a593Smuzhiyun 
1119*4882a593Smuzhiyun 	if (sdclk == 1) {
1120*4882a593Smuzhiyun 		brdcfg4 = QIXIS_READ(brdcfg[4]);
1121*4882a593Smuzhiyun 		if ((brdcfg4 & CLK_MUX_SEL_MASK) == ETH_PHY_CLK_OUT)
1122*4882a593Smuzhiyun 			return SRDS_PLLCR0_RFCK_SEL_125;
1123*4882a593Smuzhiyun 		else
1124*4882a593Smuzhiyun 			clock = (sw >> 5) & 7;
1125*4882a593Smuzhiyun 	} else
1126*4882a593Smuzhiyun 		clock = (sw >> 6) & 3;
1127*4882a593Smuzhiyun 
1128*4882a593Smuzhiyun 	switch (clock) {
1129*4882a593Smuzhiyun 	case 0:
1130*4882a593Smuzhiyun 		ret = SRDS_PLLCR0_RFCK_SEL_100;
1131*4882a593Smuzhiyun 		break;
1132*4882a593Smuzhiyun 	case 1:
1133*4882a593Smuzhiyun 		ret = SRDS_PLLCR0_RFCK_SEL_125;
1134*4882a593Smuzhiyun 		break;
1135*4882a593Smuzhiyun 	case 2:
1136*4882a593Smuzhiyun 		ret = SRDS_PLLCR0_RFCK_SEL_156_25;
1137*4882a593Smuzhiyun 		break;
1138*4882a593Smuzhiyun 	case 3:
1139*4882a593Smuzhiyun 		ret = SRDS_PLLCR0_RFCK_SEL_161_13;
1140*4882a593Smuzhiyun 		break;
1141*4882a593Smuzhiyun 	case 4:
1142*4882a593Smuzhiyun 	case 5:
1143*4882a593Smuzhiyun 	case 6:
1144*4882a593Smuzhiyun 		ret = SRDS_PLLCR0_RFCK_SEL_122_88;
1145*4882a593Smuzhiyun 		break;
1146*4882a593Smuzhiyun 	default:
1147*4882a593Smuzhiyun 		ret = -1;
1148*4882a593Smuzhiyun 		break;
1149*4882a593Smuzhiyun 	}
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun 	return ret;
1152*4882a593Smuzhiyun }
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun #define NUM_SRDS_BANKS	2
1155*4882a593Smuzhiyun 
misc_init_r(void)1156*4882a593Smuzhiyun int misc_init_r(void)
1157*4882a593Smuzhiyun {
1158*4882a593Smuzhiyun 	u8 sw;
1159*4882a593Smuzhiyun 	serdes_corenet_t *srds_regs =
1160*4882a593Smuzhiyun 		(void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
1161*4882a593Smuzhiyun 	u32 actual[NUM_SRDS_BANKS];
1162*4882a593Smuzhiyun 	unsigned int i;
1163*4882a593Smuzhiyun 	int clock;
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun 	sw = QIXIS_READ(brdcfg[2]);
1166*4882a593Smuzhiyun 	clock = serdes_refclock(sw, 1);
1167*4882a593Smuzhiyun 	if (clock >= 0)
1168*4882a593Smuzhiyun 		actual[0] = clock;
1169*4882a593Smuzhiyun 	else
1170*4882a593Smuzhiyun 		printf("Warning: SDREFCLK1 switch setting is unsupported\n");
1171*4882a593Smuzhiyun 
1172*4882a593Smuzhiyun 	sw = QIXIS_READ(brdcfg[4]);
1173*4882a593Smuzhiyun 	clock = serdes_refclock(sw, 2);
1174*4882a593Smuzhiyun 	if (clock >= 0)
1175*4882a593Smuzhiyun 		actual[1] = clock;
1176*4882a593Smuzhiyun 	else
1177*4882a593Smuzhiyun 		printf("Warning: SDREFCLK2 switch setting unsupported\n");
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun 	for (i = 0; i < NUM_SRDS_BANKS; i++) {
1180*4882a593Smuzhiyun 		u32 pllcr0 = srds_regs->bank[i].pllcr0;
1181*4882a593Smuzhiyun 		u32 expected = pllcr0 & SRDS_PLLCR0_RFCK_SEL_MASK;
1182*4882a593Smuzhiyun 		if (expected != actual[i]) {
1183*4882a593Smuzhiyun 			printf("Warning: SERDES bank %u expects reference clock"
1184*4882a593Smuzhiyun 			       " %sMHz, but actual is %sMHz\n", i + 1,
1185*4882a593Smuzhiyun 			       serdes_clock_to_string(expected),
1186*4882a593Smuzhiyun 			       serdes_clock_to_string(actual[i]));
1187*4882a593Smuzhiyun 		}
1188*4882a593Smuzhiyun 	}
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun 	return 0;
1191*4882a593Smuzhiyun }
1192*4882a593Smuzhiyun 
ft_board_setup(void * blob,bd_t * bd)1193*4882a593Smuzhiyun int ft_board_setup(void *blob, bd_t *bd)
1194*4882a593Smuzhiyun {
1195*4882a593Smuzhiyun 	phys_addr_t base;
1196*4882a593Smuzhiyun 	phys_size_t size;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	ft_cpu_setup(blob, bd);
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun 	base = env_get_bootm_low();
1201*4882a593Smuzhiyun 	size = env_get_bootm_size();
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	fdt_fixup_memory(blob, (u64)base, (u64)size);
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun #ifdef CONFIG_PCI
1206*4882a593Smuzhiyun 	pci_of_setup(blob, bd);
1207*4882a593Smuzhiyun #endif
1208*4882a593Smuzhiyun 
1209*4882a593Smuzhiyun 	fdt_fixup_liodn(blob);
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun #ifdef CONFIG_HAS_FSL_DR_USB
1212*4882a593Smuzhiyun 	fsl_fdt_fixup_dr_usb(blob, bd);
1213*4882a593Smuzhiyun #endif
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun #ifdef CONFIG_SYS_DPAA_FMAN
1216*4882a593Smuzhiyun 	fdt_fixup_fman_ethernet(blob);
1217*4882a593Smuzhiyun 	fdt_fixup_board_enet(blob);
1218*4882a593Smuzhiyun #endif
1219*4882a593Smuzhiyun 
1220*4882a593Smuzhiyun 	return 0;
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun /*
1224*4882a593Smuzhiyun  * Dump board switch settings.
1225*4882a593Smuzhiyun  * The bits that cannot be read/sampled via some FPGA or some
1226*4882a593Smuzhiyun  * registers, they will be displayed as
1227*4882a593Smuzhiyun  * underscore in binary format. mask[] has those bits.
1228*4882a593Smuzhiyun  * Some bits are calculated differently than the actual switches
1229*4882a593Smuzhiyun  * if booting with overriding by FPGA.
1230*4882a593Smuzhiyun  */
qixis_dump_switch(void)1231*4882a593Smuzhiyun void qixis_dump_switch(void)
1232*4882a593Smuzhiyun {
1233*4882a593Smuzhiyun 	int i;
1234*4882a593Smuzhiyun 	u8 sw[5];
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun 	/*
1237*4882a593Smuzhiyun 	 * Any bit with 1 means that bit cannot be reverse engineered.
1238*4882a593Smuzhiyun 	 * It will be displayed as _ in binary format.
1239*4882a593Smuzhiyun 	 */
1240*4882a593Smuzhiyun 	static const u8 mask[] = {0x07, 0, 0, 0xff, 0};
1241*4882a593Smuzhiyun 	char buf[10];
1242*4882a593Smuzhiyun 	u8 brdcfg[16], dutcfg[16];
1243*4882a593Smuzhiyun 
1244*4882a593Smuzhiyun 	for (i = 0; i < 16; i++) {
1245*4882a593Smuzhiyun 		brdcfg[i] = qixis_read(offsetof(struct qixis, brdcfg[0]) + i);
1246*4882a593Smuzhiyun 		dutcfg[i] = qixis_read(offsetof(struct qixis, dutcfg[0]) + i);
1247*4882a593Smuzhiyun 	}
1248*4882a593Smuzhiyun 
1249*4882a593Smuzhiyun 	sw[0] = ((brdcfg[0] & 0x0f) << 4)	| \
1250*4882a593Smuzhiyun 		(brdcfg[9] & 0x08);
1251*4882a593Smuzhiyun 	sw[1] = ((dutcfg[1] & 0x01) << 7)	| \
1252*4882a593Smuzhiyun 		((dutcfg[2] & 0x07) << 4)       | \
1253*4882a593Smuzhiyun 		((dutcfg[6] & 0x10) >> 1)       | \
1254*4882a593Smuzhiyun 		((dutcfg[6] & 0x80) >> 5)       | \
1255*4882a593Smuzhiyun 		((dutcfg[1] & 0x40) >> 5)       | \
1256*4882a593Smuzhiyun 		(dutcfg[6] & 0x01);
1257*4882a593Smuzhiyun 	sw[2] = dutcfg[0];
1258*4882a593Smuzhiyun 	sw[3] = 0;
1259*4882a593Smuzhiyun 	sw[4] = ((brdcfg[1] & 0x30) << 2)	| \
1260*4882a593Smuzhiyun 		((brdcfg[1] & 0xc0) >> 2)	| \
1261*4882a593Smuzhiyun 		(brdcfg[1] & 0x0f);
1262*4882a593Smuzhiyun 
1263*4882a593Smuzhiyun 	puts("DIP switch settings:\n");
1264*4882a593Smuzhiyun 	for (i = 0; i < 5; i++) {
1265*4882a593Smuzhiyun 		printf("SW%d         = 0b%s (0x%02x)\n",
1266*4882a593Smuzhiyun 			i + 1, byte_to_binary_mask(sw[i], mask[i], buf), sw[i]);
1267*4882a593Smuzhiyun 	}
1268*4882a593Smuzhiyun }
1269