diff options
-rw-r--r-- | drivers/pci/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/pcie_imx8qm.c | 297 | ||||
-rw-r--r-- | drivers/pci/pcie_imx8x.c | 224 | ||||
-rw-r--r-- | include/imx8_hsio.h | 215 | ||||
-rw-r--r-- | scripts/config_whitelist.txt | 3 |
5 files changed, 740 insertions, 0 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 8fbab462a43..c23c2877e1d 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 00000000000..edac842d622 --- /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 00000000000..01f9a7deac9 --- /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); +} + diff --git a/include/imx8_hsio.h b/include/imx8_hsio.h new file mode 100644 index 00000000000..13cc881966c --- /dev/null +++ b/include/imx8_hsio.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved. + */ +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef _IMX8_HSIO_H_ +#define _IMX8_HSIO_H_ + +#define PCIEA_CFG_CPU_BASE 0x60000000 +#define PCIEA_CFG_PCI_BASE 0x40000000 +#define PCIEB_CFG_CPU_BASE 0x70000000 +#define PCIEB_CFG_PCI_BASE 0x80000000 +#define PCIE_CFG_MEM_SIZE 0x4000 + +#define PCIE_DBI_BASE_ADDR 0x5f000000 +#define PCIE_CTRLA_BASE_ADDR PCIE_DBI_BASE_ADDR +#define PCIE_CTRLB_BASE_ADDR (PCIE_DBI_BASE_ADDR + 0x10000) + +/* For 8DV */ +#define DEVICE_TYPE_RC BIT(14) +#define REFCLK_SEL BIT(4) +#define CMN_REG_RST BIT(3) + +#define HSIO_BASE_ADDR 0x5F070000 +#define HSIO_GPR_PCIE_CTRL0_ADDR (HSIO_BASE_ADDR + 0x00000000) +#define HSIO_GPR_PCIE_CTRL1_ADDR (HSIO_BASE_ADDR + 0x00000004) +#define HSIO_GPR_PCIE_STATUS0_ADDR (HSIO_BASE_ADDR + 0x00000008) + +/* For 8QM */ +#define AHCI_BASE_ADDR 0x5F020000 +#define HW_SATA_CTRL0_ADDR (HSIO_CRR_BASE_ADDR + 0x00040000) +#define HW_SATA_CTRL0_ADDR_MASK 0x000017fb +#define HW_SATA_CTRL0_ADDR_RESET 0x0 +#define HW_SATA_CTRL0_PHY_FOMREQ BIT(0) +#define HW_SATA_CTRL0_PHY_PMA_DRVN BIT(1) +#define HW_SATA_CTRL0_EPCS_SKIPBIT BIT(3) +#define HW_SATA_CTRL0_EPCS_RXERR BIT(4) +#define HW_SATA_CTRL0_EPCS_TXDEEMP BIT(5) +#define HW_SATA_CTRL0_EPCS_TXDEEMP_SEL BIT(6) +#define HW_SATA_CTRL0_PHY_RESET BIT(7) +#define HW_SATA_CTRL0_EPCS_PHYRESET_SEL BIT(8) +#define HW_SATA_CTRL0_EPCS_RXOOB BIT(9) +#define HW_SATA_CTRL0_EPCS_RXOOB_SEL BIT(10) +#define HW_SATA_CTRL0_RESET BIT(12) + +#define HSIO_LPCG_BASE_ADDR 0x5F050000 +#define HSIO_GPIO_BASE_ADDR 0x5F170000 + +#define GPR_LPCG_PCIEA_CTRL_MSTR_ACLK (HSIO_LPCG_BASE_ADDR + 0x00000000) +#define GPR_LPCG_PCIEB_CTRL_MSTR_ACLK (HSIO_LPCG_BASE_ADDR + 0x00010000) +#define GPR_LPCG_PHYX2APB_0_APB (HSIO_LPCG_BASE_ADDR + 0x00030000) +#define GPR_LPCG_PHYX1_APB (HSIO_LPCG_BASE_ADDR + 0x00040000) +#define GPR_LPCG_CRR_0 (HSIO_LPCG_BASE_ADDR + 0x00050000) +#define GPR_LPCG_CRR_1 (HSIO_LPCG_BASE_ADDR + 0x00060000) +#define GPR_LPCG_CRR_2 (HSIO_LPCG_BASE_ADDR + 0x00070000) +#define GPR_LPCG_CRR_3 (HSIO_LPCG_BASE_ADDR + 0x00080000) +#define GPR_LPCG_CRR_4 (HSIO_LPCG_BASE_ADDR + 0x00090000) +#define GPR_LPCG_CRR_5 (HSIO_LPCG_BASE_ADDR + 0x000a0000) +#define GPR_LPCG_GPIO (HSIO_LPCG_BASE_ADDR + 0x000b0000) + +#define HSIO_CRR_BASE_ADDR 0x5F110000 + +#define HW_PHYX2_CTRL0_ADDR (HSIO_CRR_BASE_ADDR + 0x00000000) +#define HW_PHYX2_CTRL0_APB_RSTN_0 BIT(0) +#define HW_PHYX2_CTRL0_APB_RSTN_1 BIT(1) +#define HW_PHYX2_CTRL0_PIPE_LN2LK_MASK (0xF << 13) +#define HW_PHYX2_CTRL0_PIPE_LN2LK_0 BIT(13) +#define HW_PHYX2_CTRL0_PIPE_LN2LK_1 BIT(14) +#define HW_PHYX2_CTRL0_PIPE_LN2LK_2 BIT(15) +#define HW_PHYX2_CTRL0_PIPE_LN2LK_3 BIT(16) + +#define HW_PHYX2_STTS0_ADDR (HSIO_CRR_BASE_ADDR + 0x00000004) +#define HW_PHYX2_STTS0_LANE0_TX_PLL_LOCK BIT(4) +#define HW_PHYX2_STTS0_LANE1_TX_PLL_LOCK BIT(12) + +#define HW_PHYX1_CTRL0_ADDR (HSIO_CRR_BASE_ADDR + 0x00010000) +#define HW_PHYX1_CTRL0_APB_RSTN BIT(0) +#define HW_PHYX1_CTRL0_PIPE_LN2LK_MASK (0xF << 13) +#define HW_PHYX1_CTRL0_PIPE_LN2LK_0 BIT(13) +#define HW_PHYX1_CTRL0_PIPE_LN2LK_1 BIT(14) +#define HW_PHYX1_CTRL0_PIPE_LN2LK_2 BIT(15) +#define HW_PHYX1_CTRL0_PIPE_LN2LK_3 BIT(16) + +#define HW_PHYX1_STTS0_ADDR (HSIO_CRR_BASE_ADDR + 0x00010004) +#define HW_PHYX1_STTS0_LANE0_TX_PLL_LOCK BIT(4) +#define HW_PHYX1_STTS0_LANE0_RX_PLL_LOCK BIT(5) + +#define HW_MISC_CTRL0_ADDR (HSIO_CRR_BASE_ADDR + 0x00050000) +#define HW_MISC_CTRL0_IOB_RXENA BIT(0) +#define HW_MISC_CTRL0_IOB_TXENA BIT(1) +#define HW_MISC_CTRL0_FAST_INIT BIT(11) +#define HW_MISC_CTRL0_PHY_X1_EPCS_SEL BIT(12) +#define HW_MISC_CTRL0_PCIE_AB_SELECT BIT(13) + +#define HW_PCIEX2_CTRL0_ADDR (HSIO_CRR_BASE_ADDR + 0x00020000) +#define HW_PCIEX2_CTRL0_DEVICE_TYPE_MASK (0xF << 24) +#define HW_PCIEX2_CTRL0_DEVICE_TYPE_RC BIT(26) + +#define HW_PCIEX2_CTRL2_ADDR (HSIO_CRR_BASE_ADDR + 0x00020008) +#define HW_PCIEX2_CTRL2_APP_LTSSM_ENABLE BIT(4) +#define HW_PCIEX2_CTRL2_BUTTON_RST_N BIT(21) +#define HW_PCIEX2_CTRL2_PERST_N BIT(22) +#define HW_PCIEX2_CTRL2_POWER_UP_RST_N BIT(23) + +#define HW_PCIEX2_STTS0_ADDR (HSIO_CRR_BASE_ADDR + 0x0002000C) +#define HW_PCIEX2_STTS0_PM_REQ_CORE_RST BIT(19) + +#define HW_PCIEX1_CTRL0_ADDR (HSIO_CRR_BASE_ADDR + 0x00030000) +#define HW_PCIEX1_CTRL0_DEVICE_TYPE_MASK (0xF << 24) +#define HW_PCIEX1_CTRL0_DEVICE_TYPE_RC BIT(26) + +#define HW_PCIEX1_CTRL2_ADDR (HSIO_CRR_BASE_ADDR + 0x00030008) +#define HW_PCIEX1_CTRL2_APP_LTSSM_ENABLE BIT(4) +#define HW_PCIEX1_CTRL2_BUTTON_RST_N BIT(21) +#define HW_PCIEX1_CTRL2_PERST_N BIT(22) +#define HW_PCIEX1_CTRL2_POWER_UP_RST_N BIT(23) + +#define HW_PCIEX1_STTS0_ADDR (HSIO_CRR_BASE_ADDR + 0x0003000c) +#define HW_PCIEX1_STTS0_PM_REQ_CORE_RST BIT(19) + +/* PCIe Port Logic registers (memory-mapped) */ +#define PF0_PORT_LOGIC (PCIE_CTRLA_BASE_ADDR + 0x700) +#define PF1_PORT_LOGIC (PCIE_CTRLB_BASE_ADDR + 0x700) + +#define PORT0_LINK_CTRL (PF0_PORT_LOGIC + 0x10) +#define PORT1_LINK_CTRL (PF1_PORT_LOGIC + 0x10) +#define PORT_LINK_CTRL_LNK_EN_MASK (0x3F << 16) +#define PORT_LINK_CTRL_LNK_LANE1 (0x1 << 16) +#define PORT_LINK_CTRL_LNK_LANE2 (0x3 << 16) +#define PORT_LINK_CTRL_LNK_FAST_LNK BIT(7) + +#define PORT0_LINK_DEBUG1 (PF0_PORT_LOGIC + 0x2C) +#define PORT1_LINK_DEBUG1 (PF1_PORT_LOGIC + 0x2C) +#define PORT_LINK_DEBUG1_LINK_UP BIT(4) + +#define PORT0_GEN2_CTRL (PF0_PORT_LOGIC + 0x10C) +#define PORT1_GEN2_CTRL (PF1_PORT_LOGIC + 0x10C) +#define PORT_GEN2_CTRL_NUM_LANES_MASK (0xFF << 8) +#define PORT_GEN2_CTRL_NUM_LANES_1 (0x1 << 8) +#define PORT_GEN2_CTRL_NUM_LANES_2 (0x2 << 8) + +#define PORT0_MISC_CONTROL_1 (PF0_PORT_LOGIC + 0x1BC) +#define PORT1_MISC_CONTROL_1 (PF1_PORT_LOGIC + 0x1BC) + +#define PORT0_DBI_LNK_STS_CTRL2 (PCIE_CTRLA_BASE_ADDR + 0xA0) + +#define PF0_TYPE1_HDR (PCIE_CTRLA_BASE_ADDR + 0x0) +#define PF0_TYPE1_STATUS_COMMAND_REG (PF0_TYPE1_HDR + 0x4) +#define PF1_TYPE1_HDR (PCIE_CTRLB_BASE_ADDR + 0x0) +#define PF1_TYPE1_STATUS_COMMAND_REG (PF1_TYPE1_HDR + 0x4) + +#define PF0_PCIE_CAP (PCIE_CTRLA_BASE_ADDR + 0x70) +#define PF0_LINK_CONTROL_LINK_STATUS_REG (PF0_PCIE_CAP + 0x10) +#define PF1_PCIE_CAP (PCIE_CTRLB_BASE_ADDR + 0x70) +#define PF1_LINK_CONTROL_LINK_STATUS_REG (PF1_PCIE_CAP + 0x10) + +#define PF0_SPICE_CAP (PCIE_CTRLA_BASE_ADDR + 0x148) +#define PF0_SPCIE_CAP_OFF_0CH_REG (PF0_SPICE_CAP + 0xC) +#define PF1_SPICE_CAP (PCIE_CTRLB_BASE_ADDR + 0x148) +#define PF1_SPCIE_CAP_OFF_0CH_REG (PF1_SPICE_CAP + 0xC) + +/* iATU registers */ +#define PCIE0_ATU_VIEWPORT (PCIE_CTRLA_BASE_ADDR + 0x900) +#define PCIE1_ATU_VIEWPORT (PCIE_CTRLB_BASE_ADDR + 0x900) +#define PCIE_ATU_REGION_INBOUND (0x1 << 31) +#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) +#define PCIE_ATU_REGION_INDEX1 (0x1 << 0) +#define PCIE_ATU_REGION_INDEX0 (0x0 << 0) +#define PCIE0_ATU_CR1 (PCIE_CTRLA_BASE_ADDR + 0x904) +#define PCIE1_ATU_CR1 (PCIE_CTRLB_BASE_ADDR + 0x904) +#define PCIE_ATU_TYPE_MEM (0x0 << 0) +#define PCIE_ATU_TYPE_IO (0x2 << 0) +#define PCIE_ATU_TYPE_CFG0 (0x4 << 0) +#define PCIE_ATU_TYPE_CFG1 (0x5 << 0) +#define PCIE0_ATU_CR2 (PCIE_CTRLA_BASE_ADDR + 0x908) +#define PCIE1_ATU_CR2 (PCIE_CTRLB_BASE_ADDR + 0x908) +#define PCIE_ATU_ENABLE (0x1 << 31) +#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) +#define PCIE0_ATU_LOWER_BASE (PCIE_CTRLA_BASE_ADDR + 0x90C) +#define PCIE0_ATU_UPPER_BASE (PCIE_CTRLA_BASE_ADDR + 0x910) +#define PCIE0_ATU_LIMIT (PCIE_CTRLA_BASE_ADDR + 0x914) +#define PCIE0_ATU_LOWER_TARGET (PCIE_CTRLA_BASE_ADDR + 0x918) +#define PCIE0_ATU_UPPER_TARGET (PCIE_CTRLA_BASE_ADDR + 0x91C) +#define PCIE1_ATU_LOWER_BASE (PCIE_CTRLB_BASE_ADDR + 0x90C) +#define PCIE1_ATU_UPPER_BASE (PCIE_CTRLB_BASE_ADDR + 0x910) +#define PCIE1_ATU_LIMIT (PCIE_CTRLB_BASE_ADDR + 0x914) +#define PCIE1_ATU_LOWER_TARGET (PCIE_CTRLB_BASE_ADDR + 0x918) +#define PCIE1_ATU_UPPER_TARGET (PCIE_CTRLB_BASE_ADDR + 0x91C) + +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ + +#define pcie_readl(x) readl((unsigned long)x) +#define pcie_writel(v, c) writel(v, (unsigned long)c) +#define pcie_clrbits_le32(addr, clear) clrbits_le32((unsigned long)addr, clear) + +void mx8x_pcie_controller_reset(sc_ipc_t ipc, u32 SC_R_PCIE); +void mx8x_pcie_ctrla_setup_regions(void); +void mx8x_pcie_ctrlb_setup_regions(void); + +void mx8dv_pcie_init(void); +void mx8qm_pcie_init(void); +void mx8qxp_pcie_init(void); + +int sata_init(void); + +#endif /* _IMX8_HSIO_H_ */ diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 9c56bb05adc..ed43578b4bb 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -676,6 +676,7 @@ CONFIG_FSL_ESDHC_PIN_MUX CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK CONFIG_FSL_FIXED_MMC_LOCATION CONFIG_FSL_FM_10GEC_REGULAR_NOTATION +CONFIG_FSL_HSIO CONFIG_FSL_I2C_CUSTOM_DFSR CONFIG_FSL_I2C_CUSTOM_FDR CONFIG_FSL_IIM @@ -994,6 +995,7 @@ CONFIG_IMX6_PWM_PER_CLK CONFIG_IMX_HDMI CONFIG_IMX_NAND CONFIG_IMX_OTP +CONFIG_IMX_PCIEB CONFIG_IMX_VIDEO_SKIP CONFIG_IMX_WATCHDOG CONFIG_INETSPACE_V2 @@ -1501,6 +1503,7 @@ CONFIG_PCIE2 CONFIG_PCIE3 CONFIG_PCIE4 CONFIG_PCIE_IMX +CONFIG_PCIE_IMX8X CONFIG_PCIE_IMX_PERST_GPIO CONFIG_PCIE_IMX_POWER_GPIO CONFIG_PCISLAVE |