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