]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/b4860qds/b4860qds.c
Merge branch 'dcc' of git://www.denx.de/git/u-boot-microblaze
[karo-tx-uboot.git] / board / freescale / b4860qds / b4860qds.c
1 /*
2  * Copyright 2011-2012 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
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>
14 #include <asm/cache.h>
15 #include <asm/immap_85xx.h>
16 #include <asm/fsl_law.h>
17 #include <asm/fsl_serdes.h>
18 #include <asm/fsl_portals.h>
19 #include <asm/fsl_liodn.h>
20 #include <fm_eth.h>
21
22 #include "../common/qixis.h"
23 #include "../common/vsc3316_3308.h"
24 #include "../common/idt8t49n222a_serdes_clk.h"
25 #include "b4860qds.h"
26 #include "b4860qds_qixis.h"
27 #include "b4860qds_crossbar_con.h"
28
29 #define CLK_MUX_SEL_MASK        0x4
30 #define ETH_PHY_CLK_OUT         0x4
31 #define PLL_NUM                 2
32
33 DECLARE_GLOBAL_DATA_PTR;
34
35 int checkboard(void)
36 {
37         char buf[64];
38         u8 sw;
39         struct cpu_type *cpu = gd->arch.cpu;
40         static const char *const freq[] = {"100", "125", "156.25", "161.13",
41                                                 "122.88", "122.88", "122.88"};
42         int clock;
43
44         printf("Board: %sQDS, ", cpu->name);
45         printf("Sys ID: 0x%02x, Sys Ver: 0x%02x, ",
46                 QIXIS_READ(id), QIXIS_READ(arch));
47
48         sw = QIXIS_READ(brdcfg[0]);
49         sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
50
51         if (sw < 0x8)
52                 printf("vBank: %d\n", sw);
53         else if (sw >= 0x8 && sw <= 0xE)
54                 puts("NAND\n");
55         else
56                 printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
57
58         printf("FPGA: v%d (%s), build %d",
59                 (int)QIXIS_READ(scver), qixis_read_tag(buf),
60                 (int)qixis_read_minor());
61         /* the timestamp string contains "\n" at the end */
62         printf(" on %s", qixis_read_time(buf));
63
64         /*
65          * Display the actual SERDES reference clocks as configured by the
66          * dip switches on the board.  Note that the SWx registers could
67          * technically be set to force the reference clocks to match the
68          * values that the SERDES expects (or vice versa).  For now, however,
69          * we just display both values and hope the user notices when they
70          * don't match.
71          */
72         puts("SERDES Reference Clocks: ");
73         sw = QIXIS_READ(brdcfg[2]);
74         clock = (sw >> 5) & 7;
75         printf("Bank1=%sMHz ", freq[clock]);
76         sw = QIXIS_READ(brdcfg[4]);
77         clock = (sw >> 6) & 3;
78         printf("Bank2=%sMHz\n", freq[clock]);
79
80         return 0;
81 }
82
83 int select_i2c_ch_pca(u8 ch)
84 {
85         int ret;
86
87         /* Selecting proper channel via PCA*/
88         ret = i2c_write(I2C_MUX_PCA_ADDR, 0x0, 1, &ch, 1);
89         if (ret) {
90                 printf("PCA: failed to select proper channel.\n");
91                 return ret;
92         }
93
94         return 0;
95 }
96
97 int configure_vsc3316_3308(void)
98 {
99         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
100         unsigned int num_vsc16_con, num_vsc08_con;
101         u32 serdes1_prtcl, serdes2_prtcl;
102         int ret;
103
104         serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
105                         FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
106         if (!serdes1_prtcl) {
107                 printf("SERDES1 is not enabled\n");
108                 return 0;
109         }
110         serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
111         debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
112
113         serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
114                         FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
115         if (!serdes2_prtcl) {
116                 printf("SERDES2 is not enabled\n");
117                 return 0;
118         }
119         serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
120         debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
121
122         switch (serdes1_prtcl) {
123         case 0x2a:
124         case 0x2C:
125         case 0x2D:
126         case 0x2E:
127                         /*
128                          * Configuration:
129                          * SERDES: 1
130                          * Lanes: A,B: SGMII
131                          * Lanes: C,D,E,F,G,H: CPRI
132                          */
133                 debug("Configuring crossbar to use onboard SGMII PHYs:"
134                                 "srds_prctl:%x\n", serdes1_prtcl);
135                 num_vsc16_con = NUM_CON_VSC3316;
136                 /* Configure VSC3316 crossbar switch */
137                 ret = select_i2c_ch_pca(I2C_CH_VSC3316);
138                 if (!ret) {
139                         ret = vsc3316_config(VSC3316_TX_ADDRESS,
140                                         vsc16_tx_4sfp_sgmii_12_56,
141                                         num_vsc16_con);
142                         if (ret)
143                                 return ret;
144                         ret = vsc3316_config(VSC3316_RX_ADDRESS,
145                                         vsc16_rx_4sfp_sgmii_12_56,
146                                         num_vsc16_con);
147                         if (ret)
148                                 return ret;
149                 } else {
150                         return ret;
151                 }
152                 break;
153
154 #ifdef CONFIG_PPC_B4420
155         case 0x18:
156                         /*
157                          * Configuration:
158                          * SERDES: 1
159                          * Lanes: A,B,C,D: SGMII
160                          * Lanes: E,F,G,H: CPRI
161                          */
162                 debug("Configuring crossbar to use onboard SGMII PHYs:"
163                                 "srds_prctl:%x\n", serdes1_prtcl);
164                 num_vsc16_con = NUM_CON_VSC3316;
165                 /* Configure VSC3316 crossbar switch */
166                 ret = select_i2c_ch_pca(I2C_CH_VSC3316);
167                 if (!ret) {
168                         ret = vsc3316_config(VSC3316_TX_ADDRESS,
169                                         vsc16_tx_sgmii_lane_cd, num_vsc16_con);
170                         if (ret)
171                                 return ret;
172                         ret = vsc3316_config(VSC3316_RX_ADDRESS,
173                                         vsc16_rx_sgmii_lane_cd, num_vsc16_con);
174                         if (ret)
175                                 return ret;
176                 } else {
177                         return ret;
178                 }
179                 break;
180 #endif
181
182         case 0x3E:
183         case 0x0D:
184         case 0x0E:
185         case 0x12:
186                 num_vsc16_con = NUM_CON_VSC3316;
187                 /* Configure VSC3316 crossbar switch */
188                 ret = select_i2c_ch_pca(I2C_CH_VSC3316);
189                 if (!ret) {
190                         ret = vsc3316_config(VSC3316_TX_ADDRESS,
191                                         vsc16_tx_sfp, num_vsc16_con);
192                         if (ret)
193                                 return ret;
194                         ret = vsc3316_config(VSC3316_RX_ADDRESS,
195                                         vsc16_rx_sfp, num_vsc16_con);
196                         if (ret)
197                                 return ret;
198                 } else {
199                         return ret;
200                 }
201                 break;
202         default:
203                 printf("WARNING:VSC crossbars programming not supported for:%x"
204                                         " SerDes1 Protocol.\n", serdes1_prtcl);
205                 return -1;
206         }
207
208         switch (serdes2_prtcl) {
209         case 0x9E:
210         case 0x9A:
211         case 0x98:
212         case 0xb2:
213         case 0x49:
214         case 0x4E:
215         case 0x8D:
216         case 0x7A:
217                 num_vsc08_con = NUM_CON_VSC3308;
218                 /* Configure VSC3308 crossbar switch */
219                 ret = select_i2c_ch_pca(I2C_CH_VSC3308);
220                 if (!ret) {
221                         ret = vsc3308_config(VSC3308_TX_ADDRESS,
222                                         vsc08_tx_amc, num_vsc08_con);
223                         if (ret)
224                                 return ret;
225                         ret = vsc3308_config(VSC3308_RX_ADDRESS,
226                                         vsc08_rx_amc, num_vsc08_con);
227                         if (ret)
228                                 return ret;
229                 } else {
230                         return ret;
231                 }
232                 break;
233         default:
234                 printf("WARNING:VSC crossbars programming not supported for: %x"
235                                         " SerDes2 Protocol.\n", serdes2_prtcl);
236                 return -1;
237         }
238
239         return 0;
240 }
241
242 int config_serdes1_refclks(void)
243 {
244         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
245         serdes_corenet_t *srds_regs =
246                 (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
247         u32 serdes1_prtcl, lane;
248         unsigned int flag_sgmii_prtcl = 0;
249         int ret, i;
250
251         serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
252                         FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
253         if (!serdes1_prtcl) {
254                 printf("SERDES1 is not enabled\n");
255                 return -1;
256         }
257         serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
258         debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
259
260         /* Clear SRDS_RSTCTL_RST bit for both PLLs before changing refclks
261          */
262         for (i = 0; i < PLL_NUM; i++)
263                 clrbits_be32(&srds_regs->bank[i].rstctl, SRDS_RSTCTL_RST);
264         /* Reconfigure IDT idt8t49n222a device for CPRI to work
265          * For this SerDes1's Refclk1 and refclk2 need to be set
266          * to 122.88MHz
267          */
268         switch (serdes1_prtcl) {
269         case 0x2A:
270         case 0x2C:
271         case 0x2D:
272         case 0x2E:
273                 debug("Configuring idt8t49n222a for CPRI SerDes clks:"
274                         " for srds_prctl:%x\n", serdes1_prtcl);
275                 ret = select_i2c_ch_pca(I2C_CH_IDT);
276                 if (!ret) {
277                         ret = set_serdes_refclk(IDT_SERDES1_ADDRESS, 1,
278                                         SERDES_REFCLK_122_88,
279                                         SERDES_REFCLK_122_88, 0);
280                         if (ret) {
281                                 printf("IDT8T49N222A configuration failed.\n");
282                                 return ret;
283                         } else
284                                 printf("IDT8T49N222A configured.\n");
285                 } else {
286                         return ret;
287                 }
288                 select_i2c_ch_pca(I2C_CH_DEFAULT);
289
290                 /* Change SerDes1's Refclk1 to 125MHz for on board
291                  * SGMIIs to work
292                  */
293                 for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
294                         enum srds_prtcl lane_prtcl = serdes_get_prtcl
295                                                 (0, serdes1_prtcl, lane);
296                         switch (lane_prtcl) {
297                         case SGMII_FM1_DTSEC1:
298                         case SGMII_FM1_DTSEC2:
299                         case SGMII_FM1_DTSEC3:
300                         case SGMII_FM1_DTSEC4:
301                         case SGMII_FM1_DTSEC5:
302                         case SGMII_FM1_DTSEC6:
303                                 flag_sgmii_prtcl++;
304                                 break;
305                         default:
306                                 break;
307                         }
308                 }
309
310                 if (flag_sgmii_prtcl)
311                         QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125);
312
313                 /* Steps For SerDes PLLs reset and reconfiguration after
314                  * changing SerDes's refclks
315                  */
316                 for (i = 0; i < PLL_NUM; i++) {
317                         debug("For PLL%d reset and reconfiguration after"
318                                " changing refclks\n", i+1);
319                         clrbits_be32(&srds_regs->bank[i].rstctl,
320                                         SRDS_RSTCTL_SDRST_B);
321                         udelay(10);
322                         clrbits_be32(&srds_regs->bank[i].rstctl,
323                                 (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B));
324                         udelay(10);
325                         setbits_be32(&srds_regs->bank[i].rstctl,
326                                         SRDS_RSTCTL_RST);
327                         setbits_be32(&srds_regs->bank[i].rstctl,
328                                 (SRDS_RSTCTL_SDEN | SRDS_RSTCTL_PLLRST_B
329                                 | SRDS_RSTCTL_SDRST_B));
330                 }
331                 break;
332         default:
333                 printf("WARNING:IDT8T49N222A configuration not"
334                         " supported for:%x SerDes1 Protocol.\n",
335                         serdes1_prtcl);
336                 return -1;
337         }
338
339         return 0;
340 }
341
342 int board_early_init_r(void)
343 {
344         const unsigned int flashbase = CONFIG_SYS_FLASH_BASE;
345         const u8 flash_esel = find_tlb_idx((void *)flashbase, 1);
346
347         /*
348          * Remap Boot flash + PROMJET region to caching-inhibited
349          * so that flash can be erased properly.
350          */
351
352         /* Flush d-cache and invalidate i-cache of any FLASH data */
353         flush_dcache();
354         invalidate_icache();
355
356         /* invalidate existing TLB entry for flash + promjet */
357         disable_tlb(flash_esel);
358
359         set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS,
360                         MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
361                         0, flash_esel, BOOKE_PAGESZ_256M, 1);
362
363         set_liodns();
364 #ifdef CONFIG_SYS_DPAA_QBMAN
365         setup_portals();
366 #endif
367         /* SerDes1 refclks need to be set again, as default clks
368          * are not suitable for CPRI and onboard SGMIIs to work
369          * simultaneously.
370          * This function will set SerDes1's Refclk1 and refclk2
371          * as per SerDes1 protocols
372          */
373         if (config_serdes1_refclks())
374                 printf("SerDes1 Refclks couldn't set properly.\n");
375         else
376                 printf("SerDes1 Refclks have been set.\n");
377
378         /* Configure VSC3316 and VSC3308 crossbar switches */
379         if (configure_vsc3316_3308())
380                 printf("VSC:failed to configure VSC3316/3308.\n");
381         else
382                 printf("VSC:VSC3316/3308 successfully configured.\n");
383
384         select_i2c_ch_pca(I2C_CH_DEFAULT);
385
386         return 0;
387 }
388
389 unsigned long get_board_sys_clk(void)
390 {
391         u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
392
393         switch ((sysclk_conf & 0x0C) >> 2) {
394         case QIXIS_CLK_100:
395                 return 100000000;
396         case QIXIS_CLK_125:
397                 return 125000000;
398         case QIXIS_CLK_133:
399                 return 133333333;
400         }
401         return 66666666;
402 }
403
404 unsigned long get_board_ddr_clk(void)
405 {
406         u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
407
408         switch (ddrclk_conf & 0x03) {
409         case QIXIS_CLK_100:
410                 return 100000000;
411         case QIXIS_CLK_125:
412                 return 125000000;
413         case QIXIS_CLK_133:
414                 return 133333333;
415         }
416         return 66666666;
417 }
418
419 static int serdes_refclock(u8 sw, u8 sdclk)
420 {
421         unsigned int clock;
422         int ret = -1;
423         u8 brdcfg4;
424
425         if (sdclk == 1) {
426                 brdcfg4 = QIXIS_READ(brdcfg[4]);
427                 if ((brdcfg4 & CLK_MUX_SEL_MASK) == ETH_PHY_CLK_OUT)
428                         return SRDS_PLLCR0_RFCK_SEL_125;
429                 else
430                         clock = (sw >> 5) & 7;
431         } else
432                 clock = (sw >> 6) & 3;
433
434         switch (clock) {
435         case 0:
436                 ret = SRDS_PLLCR0_RFCK_SEL_100;
437                 break;
438         case 1:
439                 ret = SRDS_PLLCR0_RFCK_SEL_125;
440                 break;
441         case 2:
442                 ret = SRDS_PLLCR0_RFCK_SEL_156_25;
443                 break;
444         case 3:
445                 ret = SRDS_PLLCR0_RFCK_SEL_161_13;
446                 break;
447         case 4:
448         case 5:
449         case 6:
450                 ret = SRDS_PLLCR0_RFCK_SEL_122_88;
451                 break;
452         default:
453                 ret = -1;
454                 break;
455         }
456
457         return ret;
458 }
459
460 static const char *serdes_clock_to_string(u32 clock)
461 {
462         switch (clock) {
463         case SRDS_PLLCR0_RFCK_SEL_100:
464                 return "100";
465         case SRDS_PLLCR0_RFCK_SEL_125:
466                 return "125";
467         case SRDS_PLLCR0_RFCK_SEL_156_25:
468                 return "156.25";
469         case SRDS_PLLCR0_RFCK_SEL_161_13:
470                 return "161.13";
471         default:
472                 return "122.88";
473         }
474 }
475
476 #define NUM_SRDS_BANKS  2
477
478 int misc_init_r(void)
479 {
480         u8 sw;
481         serdes_corenet_t *srds_regs =
482                 (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
483         u32 actual[NUM_SRDS_BANKS];
484         unsigned int i;
485         int clock;
486
487         sw = QIXIS_READ(brdcfg[2]);
488         clock = serdes_refclock(sw, 1);
489         if (clock >= 0)
490                 actual[0] = clock;
491         else
492                 printf("Warning: SDREFCLK1 switch setting is unsupported\n");
493
494         sw = QIXIS_READ(brdcfg[4]);
495         clock = serdes_refclock(sw, 2);
496         if (clock >= 0)
497                 actual[1] = clock;
498         else
499                 printf("Warning: SDREFCLK2 switch setting unsupported\n");
500
501         for (i = 0; i < NUM_SRDS_BANKS; i++) {
502                 u32 pllcr0 = srds_regs->bank[i].pllcr0;
503                 u32 expected = pllcr0 & SRDS_PLLCR0_RFCK_SEL_MASK;
504                 if (expected != actual[i]) {
505                         printf("Warning: SERDES bank %u expects reference clock"
506                                " %sMHz, but actual is %sMHz\n", i + 1,
507                                serdes_clock_to_string(expected),
508                                serdes_clock_to_string(actual[i]));
509                 }
510         }
511
512         return 0;
513 }
514
515 void ft_board_setup(void *blob, bd_t *bd)
516 {
517         phys_addr_t base;
518         phys_size_t size;
519
520         ft_cpu_setup(blob, bd);
521
522         base = getenv_bootm_low();
523         size = getenv_bootm_size();
524
525         fdt_fixup_memory(blob, (u64)base, (u64)size);
526
527 #ifdef CONFIG_PCI
528         pci_of_setup(blob, bd);
529 #endif
530
531         fdt_fixup_liodn(blob);
532
533 #ifdef CONFIG_HAS_FSL_DR_USB
534         fdt_fixup_dr_usb(blob, bd);
535 #endif
536
537 #ifdef CONFIG_SYS_DPAA_FMAN
538         fdt_fixup_fman_ethernet(blob);
539         fdt_fixup_board_enet(blob);
540 #endif
541 }
542
543 /*
544  * Dump board switch settings.
545  * The bits that cannot be read/sampled via some FPGA or some
546  * registers, they will be displayed as
547  * underscore in binary format. mask[] has those bits.
548  * Some bits are calculated differently than the actual switches
549  * if booting with overriding by FPGA.
550  */
551 void qixis_dump_switch(void)
552 {
553         int i;
554         u8 sw[5];
555
556         /*
557          * Any bit with 1 means that bit cannot be reverse engineered.
558          * It will be displayed as _ in binary format.
559          */
560         static const u8 mask[] = {0x07, 0, 0, 0xff, 0};
561         char buf[10];
562         u8 brdcfg[16], dutcfg[16];
563
564         for (i = 0; i < 16; i++) {
565                 brdcfg[i] = qixis_read(offsetof(struct qixis, brdcfg[0]) + i);
566                 dutcfg[i] = qixis_read(offsetof(struct qixis, dutcfg[0]) + i);
567         }
568
569         sw[0] = ((brdcfg[0] & 0x0f) << 4)       | \
570                 (brdcfg[9] & 0x08);
571         sw[1] = ((dutcfg[1] & 0x01) << 7)       | \
572                 ((dutcfg[2] & 0x07) << 4)       | \
573                 ((dutcfg[6] & 0x10) >> 1)       | \
574                 ((dutcfg[6] & 0x80) >> 5)       | \
575                 ((dutcfg[1] & 0x40) >> 5)       | \
576                 (dutcfg[6] & 0x01);
577         sw[2] = dutcfg[0];
578         sw[3] = 0;
579         sw[4] = ((brdcfg[1] & 0x30) << 2)       | \
580                 ((brdcfg[1] & 0xc0) >> 2)       | \
581                 (brdcfg[1] & 0x0f);
582
583         puts("DIP switch settings:\n");
584         for (i = 0; i < 5; i++) {
585                 printf("SW%d         = 0b%s (0x%02x)\n",
586                         i + 1, byte_to_binary_mask(sw[i], mask[i], buf), sw[i]);
587         }
588 }