summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2017-03-27 15:46:55 +0800
committerYe Li <ye.li@nxp.com>2018-04-27 02:32:28 -0700
commit99c90ff2de4849aafa0043932353e2c199d22e5f (patch)
treea9df110c5c71874704a63f0fa4b7345af4fa7be9 /drivers/pci
parentfd99a9f057097a64034cd7b419fd983f487791e4 (diff)
MLK-14938-17 pcie: Add support for i.MX8QM/QXP PCIe
- one lane pcie gen2 link is okay, the cfg space of the rc/ep can be accessed. rc cfg base 0x5f00_0000. ep cfg base 0x6000_0000 - limit to gen2 speed - mask the wait of eq3 finish, because it is used for gen3. - use pcie_ctrla_init_rc() to do the initialization of the pciea controller - setup the common pcie codes in pcie_imx8x.c, separate the different soc speicifed initialization codes into their own pcie/board codes, move the macro definitions into the new header file imx8_hsio.h. - i.MX8QXP only have PCIe Control B. Enable PORT B at default. i.MX8QM needs to set CONFIG_IMX_PCIEB to enable PORT B. - Disable the LTSSM when link is down. Signed-off-by: Frank Li <Frank.Li@nxp.com> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com> Signed-off-by: Ye Li <ye.li@nxp.com> (cherry picked from commit 03141c2b955ce6034f06e701126aea1493dc2b4b)
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/pcie_imx8qm.c297
-rw-r--r--drivers/pci/pcie_imx8x.c224
3 files changed, 522 insertions, 0 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 8fbab462a4..c23c2877e1 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o
obj-$(CONFIG_PCI_GT64120) += pci_gt64120.o
obj-$(CONFIG_PCI_MSC01) += pci_msc01.o
obj-$(CONFIG_PCIE_IMX) += pcie_imx.o
+obj-$(CONFIG_PCIE_IMX8X) += pcie_imx8x.o pcie_imx8qm.o
obj-$(CONFIG_FTPCI100) += pci_ftpci100.o
obj-$(CONFIG_PCI_MVEBU) += pci_mvebu.o
obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
diff --git a/drivers/pci/pcie_imx8qm.c b/drivers/pci/pcie_imx8qm.c
new file mode 100644
index 0000000000..edac842d62
--- /dev/null
+++ b/drivers/pci/pcie_imx8qm.c
@@ -0,0 +1,297 @@
+/*
+ *
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/mach-imx/sci/sci.h>
+#include <common.h>
+#include <linux/sizes.h>
+#include <imx8_hsio.h>
+
+void pcie_ctrlx2_rst(void)
+{
+ /* gpio config */
+ /* dir wakeup input clkreq and pereset output */
+ writel(0x2d, HSIO_GPIO_BASE_ADDR + 0x4);
+ writel(0x24, HSIO_GPIO_BASE_ADDR + 0x0); /* do pereset 1 */
+
+ clrbits_le32(HW_PCIEX2_CTRL2_ADDR, HW_PCIEX2_CTRL2_BUTTON_RST_N);
+ clrbits_le32(HW_PCIEX2_CTRL2_ADDR, HW_PCIEX2_CTRL2_PERST_N);
+ clrbits_le32(HW_PCIEX2_CTRL2_ADDR, HW_PCIEX2_CTRL2_POWER_UP_RST_N);
+ udelay(10);
+ setbits_le32(HW_PCIEX2_CTRL2_ADDR, HW_PCIEX2_CTRL2_BUTTON_RST_N);
+ setbits_le32(HW_PCIEX2_CTRL2_ADDR, HW_PCIEX2_CTRL2_PERST_N);
+ setbits_le32(HW_PCIEX2_CTRL2_ADDR, HW_PCIEX2_CTRL2_POWER_UP_RST_N);
+}
+
+void pcie_ctrlx1_rst(void)
+{
+ /* gpio config */
+ /* dir wakeup input clkreq and pereset output */
+ writel(0x2d, HSIO_GPIO_BASE_ADDR + 0x4);
+ writel(0x24, HSIO_GPIO_BASE_ADDR + 0x0); /* do pereset 1 */
+
+ clrbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_BUTTON_RST_N);
+ setbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_BUTTON_RST_N);
+ clrbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_PERST_N);
+ setbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_PERST_N);
+ clrbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_POWER_UP_RST_N);
+ setbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_POWER_UP_RST_N);
+}
+
+int pcie_ctrla_init_rc(int lane)
+{
+ u32 val, i = 0;
+
+ setbits_le32(HW_PHYX2_CTRL0_ADDR, HW_PHYX2_CTRL0_APB_RSTN_0
+ | HW_PHYX2_CTRL0_APB_RSTN_1); /* APB_RSTN_0/1 */
+
+ clrbits_le32(HW_PCIEX2_CTRL0_ADDR, HW_PCIEX2_CTRL0_DEVICE_TYPE_MASK);
+ setbits_le32(HW_PCIEX2_CTRL0_ADDR, HW_PCIEX2_CTRL0_DEVICE_TYPE_RC);
+
+ if (lane == 1) {
+ /*
+ * bit 0 rx ena. bit 11 fast_init.
+ * bit12 PHY_X1_EPCS_SEL 1.
+ * bit13 phy_ab_select 1.
+ */
+ setbits_le32(HW_MISC_CTRL0_ADDR, HW_MISC_CTRL0_IOB_RXENA
+ | HW_MISC_CTRL0_PHY_X1_EPCS_SEL
+ | HW_MISC_CTRL0_PCIE_AB_SELECT);
+ /* pipe_ln2lk = 1001 */
+ clrbits_le32(HW_PHYX2_CTRL0_ADDR,
+ HW_PHYX2_CTRL0_PIPE_LN2LK_MASK);
+ setbits_le32(HW_PHYX2_CTRL0_ADDR, HW_PHYX2_CTRL0_PIPE_LN2LK_3
+ | HW_PHYX2_CTRL0_PIPE_LN2LK_0);
+ for (i = 0; i < 100; i++) {
+ val = readl(HW_PHYX2_STTS0_ADDR);
+ val &= HW_PHYX2_STTS0_LANE0_TX_PLL_LOCK;
+ if (val == HW_PHYX2_STTS0_LANE0_TX_PLL_LOCK)
+ break;
+ udelay(10);
+ }
+
+ if (val != HW_PHYX2_STTS0_LANE0_TX_PLL_LOCK) {
+ printf("TX PLL is not locked.\n");
+ return -ENODEV;
+ }
+ setbits_le32(GPR_LPCG_PHYX2APB_0_APB, BIT(1));
+ /* Set the link_capable to be lane1 */
+ clrbits_le32(PORT0_LINK_CTRL, PORT_LINK_CTRL_LNK_EN_MASK);
+ setbits_le32(PORT0_LINK_CTRL, PORT_LINK_CTRL_LNK_LANE1);
+ clrbits_le32(PORT0_GEN2_CTRL, PORT_GEN2_CTRL_NUM_LANES_MASK);
+ setbits_le32(PORT0_GEN2_CTRL, PORT_GEN2_CTRL_NUM_LANES_1);
+ } else if (lane == 2) {
+ /*
+ * bit 0 rx ena. bit 11 fast_init.
+ * bit12 PHY_X1_EPCS_SEL 1.
+ */
+ setbits_le32(HW_MISC_CTRL0_ADDR, HW_MISC_CTRL0_IOB_RXENA
+ | HW_MISC_CTRL0_PHY_X1_EPCS_SEL);
+ /* pipe_ln2lk = 0011 */
+ clrbits_le32(HW_PHYX2_CTRL0_ADDR,
+ HW_PHYX2_CTRL0_PIPE_LN2LK_MASK);
+ setbits_le32(HW_PHYX2_CTRL0_ADDR, HW_PHYX2_CTRL0_PIPE_LN2LK_1
+ | HW_PHYX2_CTRL0_PIPE_LN2LK_0);
+ for (i = 0; i < 100; i++) {
+ val = readl(HW_PHYX2_STTS0_ADDR);
+ val &= (HW_PHYX2_STTS0_LANE0_TX_PLL_LOCK | HW_PHYX2_STTS0_LANE1_TX_PLL_LOCK);
+ if (val == (HW_PHYX2_STTS0_LANE0_TX_PLL_LOCK | HW_PHYX2_STTS0_LANE1_TX_PLL_LOCK))
+ break;
+ udelay(10);
+ }
+
+ if (val != (HW_PHYX2_STTS0_LANE0_TX_PLL_LOCK | HW_PHYX2_STTS0_LANE1_TX_PLL_LOCK)) {
+ printf("TX PLL is not locked.\n");
+ return -ENODEV;
+ }
+ setbits_le32(GPR_LPCG_PHYX2APB_0_APB, BIT(1) + BIT(5));
+ /* Set the link_capable to be lane2 */
+ clrbits_le32(PORT0_LINK_CTRL, PORT_LINK_CTRL_LNK_EN_MASK);
+ setbits_le32(PORT0_LINK_CTRL, PORT_LINK_CTRL_LNK_LANE2);
+ clrbits_le32(PORT0_GEN2_CTRL, PORT_GEN2_CTRL_NUM_LANES_MASK);
+ setbits_le32(PORT0_GEN2_CTRL, PORT_GEN2_CTRL_NUM_LANES_2);
+ } else {
+ printf("%s %d lane %d is invalid.\n", __func__, __LINE__, lane);
+ }
+
+ /* bit19 PM_REQ_CORE_RST of pciex2_stts0 should be cleared. */
+ for (i = 0; i < 100; i++) {
+ val = readl(HW_PCIEX2_STTS0_ADDR);
+ if ((val & HW_PCIEX2_STTS0_PM_REQ_CORE_RST) == 0)
+ break;
+ udelay(10);
+ }
+
+ if ((val & HW_PCIEX2_STTS0_PM_REQ_CORE_RST) != 0)
+ printf("ERROR PM_REQ_CORE_RST is set.\n");
+
+ /* DBI_RO_WR_EN =1 to write PF0_SPCIE_CAP_OFF_0CH_REG */
+ writel(0x1, PORT0_MISC_CONTROL_1);
+ writel(0x35353535, PF0_SPCIE_CAP_OFF_0CH_REG); /* set preset not golden */
+ setbits_le32(PORT0_LINK_CTRL, PORT_LINK_CTRL_LNK_FAST_LNK);
+ setbits_le32(HW_PCIEX2_CTRL2_ADDR, HW_PCIEX2_CTRL2_APP_LTSSM_ENABLE);
+
+ do {
+ udelay(100);
+ val = readl(PORT0_LINK_DEBUG1);
+ } while (((val & PORT_LINK_DEBUG1_LINK_UP) == 0) && (i++ < 100));
+
+ if ((val & PORT_LINK_DEBUG1_LINK_UP) == PORT_LINK_DEBUG1_LINK_UP)
+ printf("[%s] LNK UP %x\r\n", __func__, val);
+ else {
+ printf("[%s] LNK DOWN %x\r\n", __func__, val);
+ clrbits_le32(HW_PCIEX2_CTRL2_ADDR, HW_PCIEX2_CTRL2_APP_LTSSM_ENABLE);
+ return -ENODEV;
+ }
+
+ clrbits_le32(PORT0_LINK_CTRL, PORT_LINK_CTRL_LNK_FAST_LNK);
+
+ val = readl(PF0_LINK_CONTROL_LINK_STATUS_REG);
+ printf("[%s] PCIe GEN[%d] Lane[%d] is up.\n", __func__,
+ (val >> 16) & 0xF, (val >> 20) & 0x3F);
+
+ /* EQ phase 3 finish
+ * wait_read_check(LINK_CONTROL2_LINK_STATUS2_REG,BIT(17),BIT(17),1000);
+ */
+ /* make sure that pciea is L0 state now */
+ for (i = 0; i < 100; i++) {
+ val = readl(HW_PCIEX2_STTS0_ADDR);
+ if ((val & 0x3f) == 0x11)
+ break;
+ udelay(10);
+ }
+
+ if ((val & 0x3f) != 0x11)
+ printf("can't return back to L0 state.\n");
+
+ writel(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
+ PF0_TYPE1_STATUS_COMMAND_REG);
+ printf("pcie ctrla initialization is finished.\n");
+
+ return 0;
+}
+
+int pcie_ctrlb_sata_phy_init_rc(void)
+{
+ u32 val, i = 0;
+
+ setbits_le32(HW_PHYX1_CTRL0_ADDR, HW_PHYX1_CTRL0_APB_RSTN); /* APB_RSTN */
+
+ clrbits_le32(HW_PCIEX1_CTRL0_ADDR, HW_PCIEX1_CTRL0_DEVICE_TYPE_MASK);
+ setbits_le32(HW_PCIEX1_CTRL0_ADDR, HW_PCIEX1_CTRL0_DEVICE_TYPE_RC);
+
+ setbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_BUTTON_RST_N);
+ clrbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_PERST_N);
+ setbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_PERST_N);
+ clrbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_POWER_UP_RST_N);
+ setbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_POWER_UP_RST_N);
+
+ /*
+ * bit 0 rx ena. bit 11 fast_init.
+ * bit13 phy_ab_select 1.
+ */
+ setbits_le32(HW_MISC_CTRL0_ADDR, HW_MISC_CTRL0_IOB_RXENA);
+ clrbits_le32(HW_MISC_CTRL0_ADDR, HW_MISC_CTRL0_PHY_X1_EPCS_SEL);
+
+ /* pipe_ln2lk = 0011 */
+ clrbits_le32(HW_PHYX1_CTRL0_ADDR,
+ HW_PHYX1_CTRL0_PIPE_LN2LK_MASK);
+ setbits_le32(HW_PHYX1_CTRL0_ADDR, HW_PHYX1_CTRL0_PIPE_LN2LK_1
+ | HW_PHYX2_CTRL0_PIPE_LN2LK_0);
+ for (i = 0; i < 100; i++) {
+ val = readl(HW_PHYX1_STTS0_ADDR);
+ val &= HW_PHYX1_STTS0_LANE0_TX_PLL_LOCK;
+ if (val == HW_PHYX1_STTS0_LANE0_TX_PLL_LOCK)
+ break;
+ udelay(10);
+ }
+
+ if (val != HW_PHYX1_STTS0_LANE0_TX_PLL_LOCK) {
+ printf("TX PLL is not locked.\n");
+ return -ENODEV;
+ }
+
+ setbits_le32(GPR_LPCG_PHYX1_APB, BIT(1));
+
+ /* bit19 PM_REQ_CORE_RST of pciex1_stts0 should be cleared. */
+ for (i = 0; i < 100; i++) {
+ val = readl(HW_PCIEX1_STTS0_ADDR);
+ if ((val & HW_PCIEX1_STTS0_PM_REQ_CORE_RST) == 0)
+ break;
+ udelay(10);
+ }
+
+ if ((val & HW_PCIEX1_STTS0_PM_REQ_CORE_RST) != 0)
+ printf("ERROR PM_REQ_CORE_RST is set.\n");
+
+ /* DBI_RO_WR_EN =1 to write PF1_SPCIE_CAP_OFF_0CH_REG */
+ writel(0x1, PORT1_MISC_CONTROL_1);
+ writel(0x35353535, PF1_SPCIE_CAP_OFF_0CH_REG); /* set preset not golden */
+ setbits_le32(PORT1_LINK_CTRL, PORT_LINK_CTRL_LNK_FAST_LNK);
+ setbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_APP_LTSSM_ENABLE);
+
+ do {
+ udelay(100);
+ val = readl(PORT1_LINK_DEBUG1);
+ } while (((val & PORT_LINK_DEBUG1_LINK_UP) == 0) && (i++ < 100));
+
+ if ((val & PORT_LINK_DEBUG1_LINK_UP) == PORT_LINK_DEBUG1_LINK_UP) {
+ printf("[%s] LNK UP %x\r\n", __func__, val);
+ } else {
+ printf("[%s] LNK DOWN %x\r\n", __func__, val);
+ clrbits_le32(HW_PCIEX1_CTRL2_ADDR, HW_PCIEX1_CTRL2_APP_LTSSM_ENABLE);
+ return -ENODEV;
+ }
+ clrbits_le32(PORT1_LINK_CTRL, PORT_LINK_CTRL_LNK_FAST_LNK);
+
+ val = readl(PF1_LINK_CONTROL_LINK_STATUS_REG);
+ printf("[%s] PCIe GEN[%d] Lane[%d] is up.\n", __func__,
+ (val >> 16) & 0xF, (val >> 20) & 0x3F);
+
+ /* EQ phase 3 finish
+ * wait_read_check(LINK_CONTROL2_LINK_STATUS2_REG,BIT(17),BIT(17),1000);
+ */
+ /* make sure that pcieb is L0 state now */
+ for (i = 0; i < 100; i++) {
+ val = readl(HW_PCIEX1_STTS0_ADDR);
+ if ((val & 0x3f) == 0x11)
+ break;
+ udelay(10);
+ }
+
+ if ((val & 0x3f) != 0x11) {
+ printf("can't return back to L0 state.\n");
+ return -ENODEV;
+ }
+
+ writel(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
+ PF1_TYPE1_STATUS_COMMAND_REG);
+
+ return 0;
+}
+
+DECLARE_GLOBAL_DATA_PTR;
+void mx8qxp_pcie_init(void)
+{
+ pcie_ctrlx1_rst();
+ if (!pcie_ctrlb_sata_phy_init_rc())
+ mx8x_pcie_ctrlb_setup_regions();
+}
+
+void mx8qm_pcie_init(void)
+{
+ pcie_ctrlx2_rst();
+ if (!pcie_ctrla_init_rc(1))
+ mx8x_pcie_ctrla_setup_regions();
+
+#ifdef CONFIG_IMX_PCIEB
+ pcie_ctrlx1_rst();
+ if (!pcie_ctrlb_sata_phy_init_rc())
+ mx8x_pcie_ctrlb_setup_regions();
+#endif
+}
diff --git a/drivers/pci/pcie_imx8x.c b/drivers/pci/pcie_imx8x.c
new file mode 100644
index 0000000000..01f9a7deac
--- /dev/null
+++ b/drivers/pci/pcie_imx8x.c
@@ -0,0 +1,224 @@
+/*
+ *
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/mach-imx/sci/sci.h>
+#include <linux/sizes.h>
+#include <errno.h>
+#include <imx8_hsio.h>
+
+void mx8x_pcie_controller_reset(sc_ipc_t ipc, u32 scr)
+{
+ sc_err_t err;
+ int i;
+
+ err = sc_misc_set_control(ipc, scr, SC_C_PCIE_G_RST, 1);
+ if (err != SC_ERR_NONE)
+ printf("SC_R_PCIE G_RST failed! (error = %d)\n", err);
+ for (i = 0; i < 200; i = i + 1)
+ asm("nop");
+
+ err = sc_misc_set_control(ipc, scr, SC_C_PCIE_G_RST, 0);
+ if (err != SC_ERR_NONE)
+ printf("SC_R_PCIE G_RST failed! (error = %d)\n", err);
+
+ err = sc_misc_set_control(ipc, scr, SC_C_PCIE_PERST, 1);
+ if (err != SC_ERR_NONE)
+ printf("SC_R_PCIE PCIE_RST failed! (error = %d)\n", err);
+
+ err = sc_misc_set_control(ipc, scr, SC_C_PCIE_BUTTON_RST, 1);
+ if (err != SC_ERR_NONE)
+ printf("SC_R_PCIE BUTTON_RST failed! (error = %d)\n", err);
+}
+
+static void pcie_mapping_region(u32 index, u32 direction, u32 type,
+ u32 addr, u32 size, u32 target_l, u32 target_h)
+{
+ /* Select a iATU and configure its direction */
+ pcie_writel(index | direction, PCIE0_ATU_VIEWPORT);
+ setbits_le32(PCIE0_ATU_CR1, type);
+
+ /* Set memory address and size */
+ pcie_writel(addr, PCIE0_ATU_LOWER_BASE);
+ pcie_writel(0, PCIE0_ATU_UPPER_BASE);
+ pcie_writel((addr + size - 1), PCIE0_ATU_LIMIT);
+
+ pcie_writel(target_l, PCIE0_ATU_LOWER_TARGET);
+ pcie_writel(target_h, PCIE0_ATU_UPPER_TARGET);
+
+ /* Enable this iATU */
+ setbits_le32(PCIE0_ATU_CR2, PCIE_ATU_ENABLE);
+}
+
+static void pcie_ctrlb_mapping_region(u32 index, u32 direction, u32 type,
+ u32 addr, u32 size, u32 target_l, u32 target_h)
+{
+ /* Select a iATU and configure its direction */
+ pcie_writel(index | direction, PCIE1_ATU_VIEWPORT);
+ setbits_le32(PCIE1_ATU_CR1, type);
+
+ /* Set memory address and size */
+ pcie_writel(addr, PCIE1_ATU_LOWER_BASE);
+ pcie_writel(0, PCIE1_ATU_UPPER_BASE);
+ pcie_writel((addr + size - 1), PCIE1_ATU_LIMIT);
+
+ pcie_writel(target_l, PCIE1_ATU_LOWER_TARGET);
+ pcie_writel(target_h, PCIE1_ATU_UPPER_TARGET);
+
+ /* Enable this iATU */
+ setbits_le32(PCIE1_ATU_CR2, PCIE_ATU_ENABLE);
+}
+
+/* CFG Space --> 0x40000000
+ * 1st Region --> 0x41000000
+ * 2nd Region --> 0x42000000
+ * ...
+ */
+void mx8x_pcie_ctrla_setup_regions(void)
+{
+ u32 i, cmd;
+ u32 val, index;
+ u32 is_32bit;
+ u32 type, size;
+ u64 size64;
+ const u32 region_types[] = {
+ PCIE_ATU_TYPE_MEM,
+ PCIE_ATU_TYPE_IO,
+ };
+
+ cmd = PCI_COMMAND_MASTER;
+
+ pcie_mapping_region(0, PCIE_ATU_REGION_OUTBOUND, PCIE_ATU_TYPE_CFG0,
+ PCIEA_CFG_PCI_BASE, PCIE_CFG_MEM_SIZE, 0, 0);
+
+ index = 1;
+ udelay(1000);
+
+ for (i = 0; i < 6; i++) {
+ val = pcie_readl(PCIEA_CFG_CPU_BASE + 0x10 + i * 4);
+ printf("#### [%d] val=%X addr=%X\r\n ", i, val,
+ PCIEA_CFG_CPU_BASE + 0x10 + i * 4);
+ if (!val)
+ continue;
+ type = region_types[val & 0x1];
+ is_32bit = ((val & 0x4) == 0);
+ pcie_writel(0xFFFFFFFF, PCIEA_CFG_CPU_BASE + 0x10 + i * 4);
+ size = pcie_readl(PCIEA_CFG_CPU_BASE + 0x10 + i * 4);
+ size = 0xFFFFFFFF - (size & ~0xF) + 1;
+ if (is_32bit) {
+ pcie_mapping_region(index, PCIE_ATU_REGION_OUTBOUND,
+ type, PCIEA_CFG_PCI_BASE
+ + index * 0x1000000, size,
+ index * 0x1000000, 0);
+ val = (val & 0xF) + index * 0x1000000;
+ pcie_writel(val, (PCIEA_CFG_CPU_BASE + 0x10 + i * 4));
+ } else {
+ pcie_writel(0xFFFFFFFF, (PCIEA_CFG_CPU_BASE + 0x10
+ + i * 4 + 4));
+ size64 = pcie_readl(PCIEA_CFG_CPU_BASE
+ + 0x10 + i * 4 + 4);
+ size64 = 0xFFFFFFFF - size64;
+ size64 <<= 32;
+ size64 |= size;
+ size64++;
+ pcie_mapping_region(index, PCIE_ATU_REGION_OUTBOUND,
+ type, PCIEA_CFG_PCI_BASE
+ + index * 0x1000000, size64,
+ index * 0x1000000, 0);
+ val = (val & 0xF) + index * 0x1000000;
+ pcie_writel(val, (PCIEA_CFG_CPU_BASE + 0x10 + i * 4));
+ pcie_writel(0, (PCIEA_CFG_CPU_BASE + 0x10 + i * 4 + 4));
+ i++;
+ }
+
+ index++;
+
+ if (type == PCIE_ATU_TYPE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ else
+ cmd |= PCI_COMMAND_IO;
+ }
+
+ pcie_writel(cmd, PCIEA_CFG_CPU_BASE + 4);
+}
+
+/* CFG Space --> 0x80000000
+ * 1st Region --> 0x81000000
+ * 2nd Region --> 0x82000000
+ * ...
+ */
+void mx8x_pcie_ctrlb_setup_regions(void)
+{
+ u32 i, cmd;
+ u32 val, index;
+ u32 is_32bit;
+ u32 type, size;
+ u64 size64;
+ const u32 region_types[] = {
+ PCIE_ATU_TYPE_MEM,
+ PCIE_ATU_TYPE_IO,
+ };
+
+ cmd = PCI_COMMAND_MASTER;
+
+ pcie_ctrlb_mapping_region(0, PCIE_ATU_REGION_OUTBOUND, PCIE_ATU_TYPE_CFG0,
+ PCIEB_CFG_PCI_BASE, PCIE_CFG_MEM_SIZE, 0, 0);
+
+ index = 1;
+ udelay(1000);
+
+ for (i = 0; i < 6; i++) {
+ val = pcie_readl(PCIEB_CFG_CPU_BASE + 0x10 + i * 4);
+ printf("#### [%d] val=%X addr=%X\r\n ", i, val,
+ PCIEB_CFG_CPU_BASE + 0x10 + i * 4);
+ if (!val)
+ continue;
+ type = region_types[val & 0x1];
+ is_32bit = ((val & 0x4) == 0);
+ pcie_writel(0xFFFFFFFF, PCIEB_CFG_CPU_BASE + 0x10 + i * 4);
+ size = pcie_readl(PCIEB_CFG_CPU_BASE + 0x10 + i * 4);
+ size = 0xFFFFFFFF - (size & ~0xF) + 1;
+ if (is_32bit) {
+ pcie_ctrlb_mapping_region(index, PCIE_ATU_REGION_OUTBOUND,
+ type, PCIEB_CFG_PCI_BASE
+ + index * 0x1000000, size,
+ index * 0x1000000, 0);
+ val = (val & 0xF) + index * 0x1000000;
+ pcie_writel(val, (PCIEB_CFG_CPU_BASE + 0x10 + i * 4));
+ } else {
+ pcie_writel(0xFFFFFFFF, (PCIEB_CFG_CPU_BASE + 0x10
+ + i * 4 + 4));
+ size64 = pcie_readl(PCIEB_CFG_CPU_BASE
+ + 0x10 + i * 4 + 4);
+ size64 = 0xFFFFFFFF - size64;
+ size64 <<= 32;
+ size64 |= size;
+ size64++;
+ pcie_ctrlb_mapping_region(index, PCIE_ATU_REGION_OUTBOUND,
+ type, PCIEB_CFG_PCI_BASE
+ + index * 0x1000000, size64,
+ index * 0x1000000, 0);
+ val = (val & 0xF) + index * 0x1000000;
+ pcie_writel(val, (PCIEB_CFG_CPU_BASE + 0x10 + i * 4));
+ pcie_writel(0, (PCIEB_CFG_CPU_BASE + 0x10 + i * 4 + 4));
+ i++;
+ }
+
+ index++;
+
+ if (type == PCIE_ATU_TYPE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ else
+ cmd |= PCI_COMMAND_IO;
+ }
+
+ pcie_writel(cmd, PCIEB_CFG_CPU_BASE + 4);
+}
+