Commit ec78595a24b5ff1020baa97b6d6e79a3a3326307
ENGR00325255 pcie:enable pcie support on imx6sx sd
Enable pcie support in uboot on imx6sx sd boards - enable_pcie_clock should be call before ssp_en is set, since that ssp_en control the phy_ref clk gate, turn on it after the source of the pcie clks are stable. - add debug info - add rx_eq of gpr12 on imx6sx - there are random link down issue on imx6sx. It's pcie ep reset issue. solution:reset ep, then retry link can fix it. Signed-off-by: Richard Zhu <r65037@freescale.com>
Showing 6 changed files with 190 additions and 14 deletions Side-by-side Diff
... | ... | @@ -733,6 +733,15 @@ |
733 | 733 | /* Enable SATA clock. */ |
734 | 734 | setbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK); |
735 | 735 | } |
736 | +#else | |
737 | +static void ungate_disp_axi_clock(void) | |
738 | +{ | |
739 | + struct mxc_ccm_reg *const imx_ccm = | |
740 | + (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
741 | + | |
742 | + /* Enable display axi clock. */ | |
743 | + setbits_le32(&imx_ccm->CCGR3, MXC_CCM_CCGR3_DISP_AXI_MASK); | |
744 | +} | |
736 | 745 | #endif |
737 | 746 | |
738 | 747 | static void ungate_pcie_clock(void) |
... | ... | @@ -758,6 +767,9 @@ |
758 | 767 | (struct anatop_regs *)ANATOP_BASE_ADDR; |
759 | 768 | struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR; |
760 | 769 | |
770 | + /* PCIe reference clock sourced from AXI. */ | |
771 | + clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL); | |
772 | + | |
761 | 773 | /* |
762 | 774 | * Here be dragons! |
763 | 775 | * |
764 | 776 | |
765 | 777 | |
766 | 778 | |
767 | 779 | |
... | ... | @@ -773,22 +785,30 @@ |
773 | 785 | #define ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12) |
774 | 786 | #define ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10) |
775 | 787 | #define ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK 0x0000001F |
788 | +#ifndef CONFIG_MX6SX | |
789 | + /* lvds_clk1 is sourced from sata ref on imx6q/dl/solo */ | |
776 | 790 | clrsetbits_le32(&anatop_regs->ana_misc1, |
777 | 791 | ANADIG_ANA_MISC1_LVDSCLK1_IBEN | |
778 | 792 | ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK, |
779 | 793 | ANADIG_ANA_MISC1_LVDSCLK1_OBEN | 0xb); |
780 | 794 | |
781 | - /* PCIe reference clock sourced from AXI. */ | |
782 | - clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL); | |
783 | - | |
784 | 795 | /* Party time! Ungate the clock to the PCIe. */ |
785 | -#ifndef CONFIG_MX6SX | |
786 | 796 | ungate_sata_clock(); |
787 | -#endif | |
788 | 797 | ungate_pcie_clock(); |
789 | 798 | |
790 | 799 | return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA | |
791 | - BM_ANADIG_PLL_ENET_ENABLE_PCIE); | |
800 | + BM_ANADIG_PLL_ENET_ENABLE_PCIE); | |
801 | +#else | |
802 | + /* lvds_clk1 is sourced from pcie ref on imx6sx */ | |
803 | + clrsetbits_le32(&anatop_regs->ana_misc1, | |
804 | + ANADIG_ANA_MISC1_LVDSCLK1_IBEN | | |
805 | + ANADIG_ANA_MISC1_LVDS1_CLK_SEL_MASK, | |
806 | + ANADIG_ANA_MISC1_LVDSCLK1_OBEN | 0xa); | |
807 | + | |
808 | + ungate_disp_axi_clock(); | |
809 | + ungate_pcie_clock(); | |
810 | + return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_PCIE); | |
811 | +#endif | |
792 | 812 | } |
793 | 813 | |
794 | 814 | #ifdef CONFIG_SECURE_BOOT |
... | ... | @@ -427,6 +427,16 @@ |
427 | 427 | val &= ~IMX6SX_GPR5_CSI1_MUX_CTRL_MASK, |
428 | 428 | writel(val, &iomux->gpr[5]); |
429 | 429 | } |
430 | + | |
431 | +void pcie_power_up(void) | |
432 | +{ | |
433 | + set_ldo_voltage(LDO_PU, 1100); /* Set VDDPU to 1.1V */ | |
434 | +} | |
435 | + | |
436 | +void pcie_power_off(void) | |
437 | +{ | |
438 | + set_ldo_voltage(LDO_PU, 0); /* Set VDDPU to 1.1V */ | |
439 | +} | |
430 | 440 | #endif |
431 | 441 | |
432 | 442 | static void imx_set_vddpu_power_down(void) |
... | ... | @@ -1104,6 +1104,8 @@ |
1104 | 1104 | #ifdef CONFIG_MX6SX |
1105 | 1105 | extern void vadc_power_up(void); |
1106 | 1106 | extern void vadc_power_down(void); |
1107 | +extern void pcie_power_up(void); | |
1108 | +extern void pcie_power_off(void); | |
1107 | 1109 | #endif |
1108 | 1110 | |
1109 | 1111 | /* If ROM fail back to USB recover mode, USBPH0_PWD will be clear to use USB |
... | ... | @@ -19,6 +19,12 @@ |
19 | 19 | #define IOMUXC_GPR1_TEST_POWERDOWN (1 << 18) |
20 | 20 | |
21 | 21 | /* |
22 | + * IOMUXC_GPR5 bit fields | |
23 | + */ | |
24 | +#define IOMUXC_GPR5_PCIE_BTNRST (1 << 19) | |
25 | +#define IOMUXC_GPR5_PCIE_PERST (1 << 18) | |
26 | + | |
27 | +/* | |
22 | 28 | * IOMUXC_GPR8 bit fields |
23 | 29 | */ |
24 | 30 | #define IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_MASK (0x3f << 0) |
25 | 31 | |
26 | 32 | |
... | ... | @@ -35,12 +41,15 @@ |
35 | 41 | /* |
36 | 42 | * IOMUXC_GPR12 bit fields |
37 | 43 | */ |
44 | +#define IOMUXC_GPR12_RX_EQ_2 (0x2 << 0) | |
45 | +#define IOMUXC_GPR12_RX_EQ_MASK (0x7 << 0) | |
38 | 46 | #define IOMUXC_GPR12_LOS_LEVEL_9 (0x9 << 4) |
39 | 47 | #define IOMUXC_GPR12_LOS_LEVEL_MASK (0x1f << 4) |
40 | 48 | #define IOMUXC_GPR12_APPS_LTSSM_ENABLE (1 << 10) |
41 | 49 | #define IOMUXC_GPR12_DEVICE_TYPE_EP (0x0 << 12) |
42 | -#define IOMUXC_GPR12_DEVICE_TYPE_RC (0x2 << 12) | |
50 | +#define IOMUXC_GPR12_DEVICE_TYPE_RC (0x4 << 12) | |
43 | 51 | #define IOMUXC_GPR12_DEVICE_TYPE_MASK (0xf << 12) |
52 | +#define IOMUXC_GPR12_TEST_POWERDOWN (1 << 30) | |
44 | 53 | |
45 | 54 | /* |
46 | 55 | * IOMUXC_GPR13 bit fields |
... | ... | @@ -23,13 +23,20 @@ |
23 | 23 | #define PCI_ACCESS_READ 0 |
24 | 24 | #define PCI_ACCESS_WRITE 1 |
25 | 25 | |
26 | +#ifdef CONFIG_MX6SX | |
27 | +#define MX6_DBI_ADDR 0x08ffc000 | |
28 | +#define MX6_IO_ADDR 0x08000000 | |
29 | +#define MX6_MEM_ADDR 0x08100000 | |
30 | +#define MX6_ROOT_ADDR 0x08f00000 | |
31 | +#else | |
26 | 32 | #define MX6_DBI_ADDR 0x01ffc000 |
27 | -#define MX6_DBI_SIZE 0x4000 | |
28 | 33 | #define MX6_IO_ADDR 0x01000000 |
29 | -#define MX6_IO_SIZE 0x100000 | |
30 | 34 | #define MX6_MEM_ADDR 0x01100000 |
31 | -#define MX6_MEM_SIZE 0xe00000 | |
32 | 35 | #define MX6_ROOT_ADDR 0x01f00000 |
36 | +#endif | |
37 | +#define MX6_DBI_SIZE 0x4000 | |
38 | +#define MX6_IO_SIZE 0x100000 | |
39 | +#define MX6_MEM_SIZE 0xe00000 | |
33 | 40 | #define MX6_ROOT_SIZE 0xfc000 |
34 | 41 | |
35 | 42 | /* PCIe Port Logic registers (memory-mapped) */ |
... | ... | @@ -80,6 +87,46 @@ |
80 | 87 | #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) |
81 | 88 | #define PCIE_ATU_UPPER_TARGET 0x91C |
82 | 89 | |
90 | +#ifdef DEBUG | |
91 | + | |
92 | +#ifdef DEBUG_STRESS_WR /* warm-reset stress tests */ | |
93 | +#define SNVS_LPGRP 0x020cc068 | |
94 | +#endif | |
95 | + | |
96 | +#define DBGF(x...) printf(x) | |
97 | + | |
98 | +static void print_regs(int contain_pcie_reg) | |
99 | +{ | |
100 | + u32 val; | |
101 | +#ifndef CONFIG_MX6SX | |
102 | + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; | |
103 | +#else | |
104 | + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; | |
105 | +#endif | |
106 | + val = readl(&iomuxc_regs->gpr[1]); | |
107 | + DBGF("GPR01 a:0x%08x v:0x%08x\n", (u32)&iomuxc_regs->gpr[1], val); | |
108 | + val = readl(&iomuxc_regs->gpr[5]); | |
109 | + DBGF("GPR05 a:0x%08x v:0x%08x\n", (u32)&iomuxc_regs->gpr[5], val); | |
110 | + val = readl(&iomuxc_regs->gpr[8]); | |
111 | + DBGF("GPR08 a:0x%08x v:0x%08x\n", (u32)&iomuxc_regs->gpr[8], val); | |
112 | + val = readl(&iomuxc_regs->gpr[12]); | |
113 | + DBGF("GPR12 a:0x%08x v:0x%08x\n", (u32)&iomuxc_regs->gpr[12], val); | |
114 | + val = readl(ANATOP_BASE_ADDR + 0xe0); | |
115 | + DBGF("PLL06 a:0x%08x v:0x%08x\n", ANATOP_BASE_ADDR + 0xe0, val); | |
116 | + val = readl(ANATOP_BASE_ADDR + 0x160); | |
117 | + DBGF("MISC1 a:0x%08x v:0x%08x\n", ANATOP_BASE_ADDR + 0x160, val); | |
118 | + if (contain_pcie_reg) { | |
119 | + val = readl(MX6_DBI_ADDR + 0x728); | |
120 | + DBGF("dbr0 offset 0x728 %08x\n", val); | |
121 | + val = readl(MX6_DBI_ADDR + 0x72c); | |
122 | + DBGF("dbr1 offset 0x72c %08x\n", val); | |
123 | + } | |
124 | +} | |
125 | +#else | |
126 | +#define DBGF(x...) | |
127 | +static void print_regs(int contain_pcie_reg) {} | |
128 | +#endif | |
129 | + | |
83 | 130 | /* |
84 | 131 | * PHY access functions |
85 | 132 | */ |
86 | 133 | |
87 | 134 | |
88 | 135 | |
89 | 136 | |
90 | 137 | |
91 | 138 | |
92 | 139 | |
... | ... | @@ -420,19 +467,43 @@ |
420 | 467 | */ |
421 | 468 | static int imx6_pcie_assert_core_reset(void) |
422 | 469 | { |
470 | +#ifndef CONFIG_MX6SX | |
423 | 471 | struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; |
472 | +#else | |
473 | + u32 val; | |
474 | + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; | |
475 | +#endif | |
424 | 476 | |
477 | +#if defined(CONFIG_MX6SX) | |
478 | + /* SSP_EN is not used on iMX6SX anymore */ | |
479 | + setbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_TEST_POWERDOWN); | |
480 | + /* Force PCIe PHY reset */ | |
481 | + setbits_le32(&iomuxc_regs->gpr[5], IOMUXC_GPR5_PCIE_BTNRST); | |
482 | + | |
483 | + /* Power up PCIe PHY, ANATOP_REG_CORE offset 0x140, bit13-9 */ | |
484 | + val = readl(GPC_BASE_ADDR + 0); | |
485 | + val |= (0x1 << 7); | |
486 | + writel(val, GPC_BASE_ADDR + 0); | |
487 | + pcie_power_up(); | |
488 | +#else | |
425 | 489 | setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN); |
426 | 490 | clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN); |
491 | +#endif | |
427 | 492 | |
428 | 493 | return 0; |
429 | 494 | } |
430 | 495 | |
431 | 496 | static int imx6_pcie_init_phy(void) |
432 | 497 | { |
498 | +#ifndef CONFIG_MX6SX | |
433 | 499 | struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; |
500 | +#else | |
501 | + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; | |
502 | +#endif | |
434 | 503 | |
504 | +#ifndef DEBUG | |
435 | 505 | clrbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_APPS_LTSSM_ENABLE); |
506 | +#endif | |
436 | 507 | |
437 | 508 | clrsetbits_le32(&iomuxc_regs->gpr[12], |
438 | 509 | IOMUXC_GPR12_DEVICE_TYPE_MASK, |
... | ... | @@ -440,6 +511,11 @@ |
440 | 511 | clrsetbits_le32(&iomuxc_regs->gpr[12], |
441 | 512 | IOMUXC_GPR12_LOS_LEVEL_MASK, |
442 | 513 | IOMUXC_GPR12_LOS_LEVEL_9); |
514 | +#ifdef CONFIG_MX6SX | |
515 | + clrsetbits_le32(&iomuxc_regs->gpr[12], | |
516 | + IOMUXC_GPR12_RX_EQ_MASK, | |
517 | + IOMUXC_GPR12_RX_EQ_2); | |
518 | +#endif | |
443 | 519 | |
444 | 520 | writel((0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN1_OFFSET) | |
445 | 521 | (0x0 << IOMUXC_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB_OFFSET) | |
446 | 522 | |
447 | 523 | |
448 | 524 | |
449 | 525 | |
450 | 526 | |
... | ... | @@ -505,21 +581,38 @@ |
505 | 581 | |
506 | 582 | static int imx6_pcie_deassert_core_reset(void) |
507 | 583 | { |
584 | +#ifndef CONFIG_MX6SX | |
508 | 585 | struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; |
586 | +#else | |
587 | + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; | |
588 | +#endif | |
509 | 589 | |
510 | 590 | imx6_pcie_toggle_power(); |
511 | 591 | |
592 | + enable_pcie_clock(); | |
593 | + | |
512 | 594 | /* Enable PCIe */ |
595 | +#if defined(CONFIG_MX6SX) | |
596 | + /* SSP_EN is not used on iMX6SX anymore */ | |
597 | + clrbits_le32(&iomuxc_regs->gpr[12], IOMUXC_GPR12_TEST_POWERDOWN); | |
598 | + /* | |
599 | + * iMX6SX PCIe has the stand-alone power domain. | |
600 | + * refer to the initialization for iMX6SX PCIe, | |
601 | + * release the PCIe PHY reset here, | |
602 | + * before LTSSM enable is set | |
603 | + * . | |
604 | + */ | |
605 | + clrbits_le32(&iomuxc_regs->gpr[5], IOMUXC_GPR5_PCIE_BTNRST); | |
606 | +#else | |
513 | 607 | clrbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_TEST_POWERDOWN); |
514 | 608 | setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_REF_SSP_EN); |
515 | 609 | |
516 | - enable_pcie_clock(); | |
517 | - | |
518 | 610 | /* |
519 | 611 | * Wait for the clock to settle a bit, when the clock are sourced |
520 | 612 | * from the CPU, we need about 30mS to settle. |
521 | 613 | */ |
522 | 614 | mdelay(50); |
615 | +#endif | |
523 | 616 | |
524 | 617 | imx6_pcie_toggle_reset(); |
525 | 618 | |
526 | 619 | |
... | ... | @@ -528,7 +621,11 @@ |
528 | 621 | |
529 | 622 | static int imx_pcie_link_up(void) |
530 | 623 | { |
624 | +#ifndef CONFIG_MX6SX | |
531 | 625 | struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; |
626 | +#else | |
627 | + struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; | |
628 | +#endif | |
532 | 629 | uint32_t tmp; |
533 | 630 | int count = 0; |
534 | 631 | |
535 | 632 | |
... | ... | @@ -555,9 +652,25 @@ |
555 | 652 | while (!imx6_pcie_link_up()) { |
556 | 653 | udelay(10); |
557 | 654 | count++; |
655 | + if (count == 1000) { | |
656 | + print_regs(1); | |
657 | + /* link down, try reset ep, and re-try link here */ | |
658 | + DBGF("pcie link is down, reset ep, then retry!\n"); | |
659 | + imx6_pcie_toggle_reset(); | |
660 | + continue; | |
661 | + } | |
662 | +#ifdef DEBUG | |
663 | + else if (count >= 2000) { | |
664 | + print_regs(1); | |
665 | + /* link is down, stop here */ | |
666 | + setenv("bootcmd", "sleep 2;"); | |
667 | + DBGF("pcie link is down, stop here!\n"); | |
668 | + return -EINVAL; | |
669 | + } | |
670 | +#endif | |
558 | 671 | if (count >= 2000) { |
559 | - debug("phy link never came up\n"); | |
560 | - debug("DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", | |
672 | + printf("phy link never came up\n"); | |
673 | + printf("DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", | |
561 | 674 | readl(MX6_DBI_ADDR + PCIE_PHY_DEBUG_R0), |
562 | 675 | readl(MX6_DBI_ADDR + PCIE_PHY_DEBUG_R1)); |
563 | 676 | return -EINVAL; |
... | ... | @@ -573,6 +686,10 @@ |
573 | 686 | static struct pci_controller pcc; |
574 | 687 | struct pci_controller *hose = &pcc; |
575 | 688 | int ret; |
689 | +#ifdef DEBUG_STRESS_WR | |
690 | + u32 dbg_reg_addr = SNVS_LPGRP; | |
691 | + u32 dbg_reg = readl(dbg_reg_addr) + 1; | |
692 | +#endif | |
576 | 693 | |
577 | 694 | memset(&pcc, 0, sizeof(pcc)); |
578 | 695 | |
579 | 696 | |
... | ... | @@ -607,7 +724,15 @@ |
607 | 724 | if (!ret) { |
608 | 725 | pci_register_hose(hose); |
609 | 726 | hose->last_busno = pci_hose_scan(hose); |
727 | +#ifdef DEBUG_STRESS_WR | |
728 | + dbg_reg += 1<<16; | |
729 | +#endif | |
610 | 730 | } |
731 | +#ifdef DEBUG_STRESS_WR | |
732 | + writel(dbg_reg, dbg_reg_addr); | |
733 | + DBGF("PCIe Successes/Attempts: %d/%d\n", | |
734 | + dbg_reg >> 16, dbg_reg & 0xffff); | |
735 | +#endif | |
611 | 736 | } |
612 | 737 | |
613 | 738 | /* Probe function. */ |
... | ... | @@ -367,6 +367,16 @@ |
367 | 367 | #define CONFIG_MXC_USB_FLAGS 0 |
368 | 368 | #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 |
369 | 369 | |
370 | +#define CONFIG_CMD_PCI | |
371 | +#ifdef CONFIG_CMD_PCI | |
372 | +#define CONFIG_PCI | |
373 | +#define CONFIG_PCI_PNP | |
374 | +#define CONFIG_PCI_SCAN_SHOW | |
375 | +#define CONFIG_PCIE_IMX | |
376 | +#define CONFIG_PCIE_IMX_PERST_GPIO IMX_GPIO_NR(2, 1) | |
377 | +#define CONFIG_PCIE_IMX_POWER_GPIO IMX_GPIO_NR(2, 0) | |
378 | +#endif | |
379 | + | |
370 | 380 | #if defined(CONFIG_ANDROID_SUPPORT) |
371 | 381 | #include "mx6sxsabresdandroid.h" |
372 | 382 | #endif |
-
mentioned in commit 8289dd
-
mentioned in commit 8289dd
-
mentioned in commit 8289dd
-
mentioned in commit 8289dd
-
mentioned in commit 8289dd
-
mentioned in commit 81fd30
-
mentioned in commit 586f20
-
mentioned in commit 586f20
-
mentioned in commit 586f20
-
mentioned in commit 586f20
-
mentioned in commit 586f20
-
mentioned in commit 586f20
-
mentioned in commit 4226ce
-
mentioned in commit 4226ce
-
mentioned in commit 4226ce
-
mentioned in commit 4226ce
-
mentioned in commit 4226ce
-
mentioned in commit 3e1a0a
-
mentioned in commit 4226ce
-
mentioned in commit 3e1a0a
-
mentioned in commit 2fed81
-
mentioned in commit 2fed81
-
mentioned in commit 2fed81
-
mentioned in commit 2fed81
-
mentioned in commit fa4b46
-
mentioned in commit fa4b46
-
mentioned in commit 2fed81
-
mentioned in commit fa4b46
-
mentioned in commit fa4b46
-
mentioned in commit fa4b46
-
mentioned in commit fa4b46
-
mentioned in commit a9ae45