Commit ec78595a24b5ff1020baa97b6d6e79a3a3326307

Authored by Richard Zhu
1 parent a09f718e5a

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

arch/arm/cpu/armv7/mx6/clock.c
... ... @@ -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
arch/arm/cpu/armv7/mx6/soc.c
... ... @@ -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)
arch/arm/include/asm/arch-mx6/imx-regs.h
... ... @@ -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
arch/arm/include/asm/arch-mx6/iomux.h
... ... @@ -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
drivers/pci/pcie_imx.c
... ... @@ -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. */
include/configs/mx6sxsabresd.h
... ... @@ -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