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