diff --git a/arch/arm/dts/devsoc-emulation.dts b/arch/arm/dts/devsoc-emulation.dts index 1aedb6805f..31b10b678d 100644 --- a/arch/arm/dts/devsoc-emulation.dts +++ b/arch/arm/dts/devsoc-emulation.dts @@ -98,4 +98,70 @@ }; }; }; + + pci0: pci@20000000 { + status = "ok"; + perst_gpio = <42>; + lane = <1>; + pci_gpio { + pci_rst { + gpio = <42>; + func = <0>; + pull = ; + oe = ; + drvstr = ; + }; + pci_clk { + gpio = <37>; + func = <0>; + pull = ; + oe = ; + drvstr = ; + }; + }; + }; + + pci1: pci@18000000 { + status = "ok"; + perst_gpio = <41>; + lane = <2>; + pci_gpio { + pci_rst { + gpio = <41>; + func = <0>; + pull = ; + oe = ; + drvstr = ; + }; + pci_clk { + gpio = <46>; + func = <0>; + pull = ; + oe = ; + drvstr = ; + }; + }; + }; + + pci2: pci@10000000 { + status = "ok"; + perst_gpio = <40>; + lane = <1>; + pci_gpio { + pci_rst { + gpio = <40>; + func = <0>; + pull = ; + oe = ; + drvstr = ; + }; + pci_clk { + gpio = <43>; + func = <0>; + pull = ; + oe = ; + drvstr = ; + }; + }; + }; }; diff --git a/arch/arm/dts/devsoc-soc.dtsi b/arch/arm/dts/devsoc-soc.dtsi index ee7bf3cbd3..f70f3cfed2 100644 --- a/arch/arm/dts/devsoc-soc.dtsi +++ b/arch/arm/dts/devsoc-soc.dtsi @@ -84,4 +84,61 @@ mmc: sdhci@7804000 { compatible = "qcom,sdhci-msm"; }; + + pci0: pci@20000000 { + compatible = "qcom,devsoc-pcie"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x20000000 0xf1d + 0x80000 0x3000 + 0x20000F20 0xa8 + 0x20001000 0x1000 + 0x20300000 0xd00000 + 0x20100000 0x100000 + 0x1829000 0x60 + 0x8c000 0x1000>; + reg-names = "pci_dbi", "parf", "elbi","dm_iatu", "axi_bars", + "axi_conf", "pci_rst", "pci_phy"; + gen3 = <1>; + status = "disabled"; + skip_phy_int = <1>; + }; + + pci1: pci@18000000 { + compatible = "qcom,devsoc-pcie"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x18000000 0xf1d + 0x88000 0x3000 + 0x18000F20 0xa8 + 0x18001000 0x1000 + 0x18300000 0xd00000 + 0x18100000 0x100000 + 0x1828000 0x60 + 0xF4000 0x1000>; + reg-names = "pci_dbi", "parf", "elbi","dm_iatu", "axi_bars", + "axi_conf", "pci_rst", "pci_phy"; + gen3 = <1>; + status = "disabled"; + skip_phy_int = <1>; + }; + + pci2: pci@10000000 { + compatible = "qcom,devsoc-pcie"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x10000000 0xf1d + 0xF0000 0x3000 + 0x10000F20 0xa8 + 0x10001000 0x1000 + 0x10300000 0xd00000 + 0x10100000 0x100000 + 0x182A000 0x60 + 0xFC000 0x1000>; + reg-names = "pci_dbi", "parf", "elbi","dm_iatu", "axi_bars", + "axi_conf", "pci_rst", "pci_phy"; + gen3 = <1>; + status = "disabled"; + skip_phy_int = <1>; + }; }; diff --git a/arch/arm/include/asm/arch-devsoc/clk.h b/arch/arm/include/asm/arch-devsoc/clk.h index 576298330a..b8fa897af5 100644 --- a/arch/arm/include/asm/arch-devsoc/clk.h +++ b/arch/arm/include/asm/arch-devsoc/clk.h @@ -102,7 +102,10 @@ void emmc_clock_init(void); void emmc_clock_reset(void); #endif - +#ifdef CONFIG_PCI_IPQ +void pcie_v2_clock_init(int pcie_id); +void pcie_v2_clock_deinit(int pcie_id); +#endif int uart_clock_config(struct ipq_serial_platdata *plat); #endif /*IPQ9574_CLK_H*/ diff --git a/board/devsoc/Kconfig b/board/devsoc/Kconfig index f91dca335d..8f70ae6685 100644 --- a/board/devsoc/Kconfig +++ b/board/devsoc/Kconfig @@ -24,4 +24,7 @@ config UBI_WRITE config MMC_FLASH bool "Enable MMC flash support" +config PCI_IPQ + bool "Enable pci support" + endif diff --git a/board/qca/arm/devsoc/clock.c b/board/qca/arm/devsoc/clock.c index d3dff110f7..b2fae7b954 100644 --- a/board/qca/arm/devsoc/clock.c +++ b/board/qca/arm/devsoc/clock.c @@ -127,3 +127,109 @@ void emmc_clock_reset(void) writel(0x0, GCC_SDCC1_BCR); } #endif +#ifdef CONFIG_PCI_IPQ +void pcie_v2_clock_init(int pcie_id) +{ +#ifdef QCA_CLOCK_ENABLE + int cfg, div; + + /* Configure pcie_aux_clk_src */ + cfg = (GCC_PCIE_AUX_CFG_RCGR_MN_MODE | + GCC_PCIE_AUX_CFG_RCGR_SRC_SEL | + GCC_PCIE_AUX_CFG_RCGR_SRC_DIV); + writel(cfg, GCC_PCIE_REG(GCC_PCIE_AUX_CFG_RCGR, 0)); + writel(0x1, GCC_PCIE_REG(GCC_PCIE_AUX_M, 0)); + writel(0xFFFC, GCC_PCIE_REG(GCC_PCIE_AUX_N, 0)); + writel(0xFFFB, GCC_PCIE_REG(GCC_PCIE_AUX_D, 0)); + writel(CMD_UPDATE, GCC_PCIE_REG(GCC_PCIE_AUX_CMD_RCGR, 0)); + mdelay(100); + writel(ROOT_EN, GCC_PCIE_REG(GCC_PCIE_AUX_CMD_RCGR, 0)); + + /* Configure pcie_axi_m__clk_src */ + if ((pcie_id == 2) || (pcie_id == 3)) + div = GCC_PCIE_AXI_M_CFG_RCGR_SRC_DIV_LANE2; + else + div = GCC_PCIE_AXI_M_CFG_RCGR_SRC_DIV_LANE1; + + cfg = (GCC_PCIE_AXI_M_CFG_RCGR_SRC_SEL | div); + writel(cfg, GCC_PCIE_REG(GCC_PCIE_AXI_M_CFG_RCGR, pcie_id)); + writel(CMD_UPDATE, GCC_PCIE_REG(GCC_PCIE_AXI_M_CMD_RCGR, pcie_id)); + mdelay(100); + writel(ROOT_EN, GCC_PCIE_REG(GCC_PCIE_AXI_M_CMD_RCGR, pcie_id)); + + /* Configure pcie_axi_s__clk_src */ + cfg = (GCC_PCIE_AXI_S_CFG_RCGR_SRC_SEL | GCC_PCIE_AXI_S_CFG_RCGR_SRC_DIV); + writel(cfg, GCC_PCIE_REG(GCC_PCIE_AXI_S_CFG_RCGR, pcie_id)); + writel(CMD_UPDATE, GCC_PCIE_REG(GCC_PCIE_AXI_S_CMD_RCGR, pcie_id)); + mdelay(100); + writel(ROOT_EN, GCC_PCIE_REG(GCC_PCIE_AXI_S_CMD_RCGR, pcie_id)); + + /* Configure CBCRs */ + writel(CLK_ENABLE, GCC_PCIE_REG(GCC_PCIE_AHB_CBCR, pcie_id)); + writel(CLK_ENABLE, GCC_PCIE_REG(GCC_PCIE_AXI_M_CBCR, pcie_id)); + writel(CLK_ENABLE, GCC_PCIE_REG(GCC_PCIE_AXI_S_CBCR, pcie_id)); + writel(CLK_ENABLE, GCC_SNOC_PCIE0_1LANE_S_CBCR + (0x4 * pcie_id)); + switch(pcie_id){ + case 0: + writel(CLK_ENABLE, GCC_ANOC_PCIE0_1LANE_M_CBCR); + break; + case 1: + writel(CLK_ENABLE, GCC_ANOC_PCIE1_1LANE_M_CBCR); + break; + case 2: + writel(CLK_ENABLE, GCC_ANOC_PCIE2_2LANE_M_CBCR); + break; + case 3: + writel(CLK_ENABLE, GCC_ANOC_PCIE3_2LANE_M_CBCR); + break; + } + writel(CLK_ENABLE, GCC_PCIE_REG(GCC_PCIE_AXI_S_BRIDGE_CBCR, pcie_id)); + writel(PIPE_CLK_ENABLE, GCC_PCIE_REG(GCC_PCIE_PIPE_CBCR, pcie_id)); + + /* Configure pcie_rchng_clk_src */ + cfg = (GCC_PCIE_RCHNG_CFG_RCGR_SRC_SEL + | GCC_PCIE_RCHNG_CFG_RCGR_SRC_DIV); + writel(cfg, GCC_PCIE_REG(GCC_PCIE_RCHNG_CFG_RCGR, pcie_id)); + writel(CMD_UPDATE, GCC_PCIE_REG(GCC_PCIE_RCHNG_CMD_RCGR, pcie_id)); + mdelay(100); + writel(ROOT_EN, GCC_PCIE_REG(GCC_PCIE_RCHNG_CMD_RCGR, pcie_id)); + + writel(CLK_ENABLE, GCC_PCIE_REG(GCC_PCIE_AUX_CBCR, pcie_id)); +#else + return; +#endif +} + +void pcie_v2_clock_deinit(int pcie_id) +{ +#ifdef QCA_CLOCK_ENABLE + writel(0x0, GCC_PCIE_REG(GCC_PCIE_AUX_CMD_RCGR, 0)); + mdelay(100); + writel(0x0, GCC_PCIE_REG(GCC_PCIE_AHB_CBCR, pcie_id)); + writel(0x0, GCC_PCIE_REG(GCC_PCIE_AXI_M_CBCR, pcie_id)); + writel(0x0, GCC_PCIE_REG(GCC_PCIE_AXI_S_CBCR, pcie_id)); + writel(0x0, GCC_PCIE_REG(GCC_PCIE_AUX_CBCR, pcie_id)); + writel(0x0, GCC_PCIE_REG(GCC_PCIE_PIPE_CBCR, pcie_id)); + writel(0x0, GCC_PCIE_REG(GCC_PCIE_AXI_S_BRIDGE_CBCR, pcie_id)); + writel(0x0, GCC_PCIE_REG(GCC_PCIE_RCHNG_CFG_RCGR, pcie_id)); + writel(0x0, GCC_PCIE_REG(GCC_PCIE_RCHNG_CMD_RCGR, pcie_id)); + writel(0x0, GCC_SNOC_PCIE0_1LANE_S_CBCR + (0x4 * pcie_id)); + switch(pcie_id){ + case 0: + writel(0x0, GCC_ANOC_PCIE0_1LANE_M_CBCR); + break; + case 1: + writel(0x0, GCC_ANOC_PCIE1_1LANE_M_CBCR); + break; + case 2: + writel(0x0, GCC_ANOC_PCIE2_2LANE_M_CBCR); + break; + case 3: + writel(0x0, GCC_ANOC_PCIE3_2LANE_M_CBCR); + break; + } +#else + return; +#endif +} +#endif diff --git a/board/qca/arm/devsoc/devsoc.c b/board/qca/arm/devsoc/devsoc.c index 52bd2210b6..7015b705fa 100644 --- a/board/qca/arm/devsoc/devsoc.c +++ b/board/qca/arm/devsoc/devsoc.c @@ -201,6 +201,94 @@ int board_mmc_init(bd_t *bis) return 0; } #endif +#ifdef CONFIG_PCI_IPQ +void board_pci_init(int id) +{ + int node, gpio_node, ret, lane; + char name[16]; + struct fdt_resource pci_rst; + + snprintf(name, sizeof(name), "pci%d", id); + node = fdt_path_offset(gd->fdt_blob, name); + if (node < 0) { + printf("Could not find PCI%d in device tree\n", id); + return; + } + + gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "pci_gpio"); + if (gpio_node >= 0) + qca_gpio_init(gpio_node); + + lane = fdtdec_get_int(gd->fdt_blob, node, "lane", 1); + + /* + * setting dual port mode if PCIE1 & PCIE2 come up with 1 lane. + */ + if ((id == 1) || (id ==2)) { + if (lane == 1) + writel(TWO_PORT_MODE, + (void *)TCSR_MODE_CTRL_2PORT_2LANE); + else + writel(TWO_LANE_MODE, + (void *)TCSR_MODE_CTRL_2PORT_2LANE); + mdelay(10); + } + + ret = fdt_get_named_resource(gd->fdt_blob, node, "reg", + "reg-names", "pci_rst", &pci_rst); + if (ret == 0) { + set_mdelay_clearbits_le32(pci_rst.start, 0x1, 10); + set_mdelay_clearbits_le32(pci_rst.end + 1, 0x1, 10); + } + + pcie_v2_clock_init(id); + + return; +} + +void board_pci_deinit() +{ + int node, gpio_node, i, err, is_x2; + char name[16]; + struct fdt_resource parf; + struct fdt_resource pci_phy; + + for (i = 0; i < PCI_MAX_DEVICES; i++) { + snprintf(name, sizeof(name), "pci%d", i); + node = fdt_path_offset(gd->fdt_blob, name); + if (node < 0) { + printf("Could not find PCI%d in device tree\n", i); + continue; + } + err = fdt_get_named_resource(gd->fdt_blob, node, "reg", + "reg-names", "parf", &parf); + + writel(0x0, parf.start + 0x358); + writel(0x1, parf.start + 0x40); + + err = fdt_get_named_resource(gd->fdt_blob, node, "reg", + "reg-names", "pci_phy", &pci_phy); + if (err < 0) + continue; + + if ((i == 0) || (i == 1)) + is_x2 = 0; + else + is_x2 = 1; + + writel(0x1, pci_phy.start + (0x800 + (0x800 * is_x2))); + writel(0x0, pci_phy.start + (0x804 + (0x800 * is_x2))); + + gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "pci_gpio"); + if (gpio_node >= 0) + qca_gpio_deinit(gpio_node); + + pcie_v2_clock_deinit(i); + } + + return; +} +#endif __weak int ipq_get_tz_version(char *version_name, int buf_size) { diff --git a/board/qca/arm/devsoc/devsoc.h b/board/qca/arm/devsoc/devsoc.h index fddb52fb71..1a696df5ab 100644 --- a/board/qca/arm/devsoc/devsoc.h +++ b/board/qca/arm/devsoc/devsoc.h @@ -34,6 +34,8 @@ extern const add_node_t add_fdt_node[]; #define MSM_SDC1_BASE 0x7800000 #define MSM_SDC1_SDHCI_BASE 0x7804000 +#define TCSR_MODE_CTRL_2PORT_2LANE 0x1947544 + /* * weak function */ @@ -44,6 +46,19 @@ __weak void handle_noc_err(void) {} __weak void board_pcie_clock_init(int id) {} __weak void ubi_power_collapse(void) {} +/* + * PCIE + */ +enum pcie_port_lane_mode_t{ + TWO_LANE_MODE =0, + TWO_PORT_MODE +}; + +#define set_mdelay_clearbits_le32(addr, value, delay) \ + setbits_le32(addr, value); \ + mdelay(delay); \ + clrbits_le32(addr, value); \ + /* * SMEM */ @@ -156,5 +171,8 @@ int smem_ram_ptable_init_v2( struct usable_ram_partition_table *usable_ram_partition_table); void qpic_set_clk_rate(unsigned int clk_rate, int blk_type, int req_clk_src_type); +#ifdef CONFIG_PCI_IPQ +void board_pci_init(int id); +#endif #endif /* _DEVSOC_CDP_H_ */ diff --git a/configs/devsoc_defconfig b/configs/devsoc_defconfig index 4e0e76a6b5..e3f594e07e 100644 --- a/configs/devsoc_defconfig +++ b/configs/devsoc_defconfig @@ -248,7 +248,7 @@ CONFIG_QPIC_SERIAL=y # PCI # # CONFIG_DM_PCI is not set -# CONFIG_PCI_IPQ is not set +CONFIG_PCI_IPQ=y # # Pin controllers diff --git a/drivers/pci/pci_ipq.c b/drivers/pci/pci_ipq.c index f1724892dc..17c68f824e 100644 --- a/drivers/pci/pci_ipq.c +++ b/drivers/pci/pci_ipq.c @@ -968,6 +968,7 @@ static const struct udevice_id pcie_ver_ids[] = { { .compatible = "qcom,ipq807x-pcie", .data = PCIE_V2 }, { .compatible = "qcom,ipq6018-pcie", .data = PCIE_V2 }, { .compatible = "qcom,ipq5018-pcie", .data = PCIE_V2 }, + { .compatible = "qcom,devsoc-pcie", .data = PCIE_V2 }, { .compatible = "qcom,ipq9574-pcie", .data = PCIE_V2 }, { }, }; diff --git a/include/configs/devsoc.h b/include/configs/devsoc.h index 8f9b0d5044..8ce7b981ff 100644 --- a/include/configs/devsoc.h +++ b/include/configs/devsoc.h @@ -302,6 +302,15 @@ extern loff_t board_env_size; #define CONFIG_IPQ_FDT_FIXUP #define CONFIG_FDT_FIXUP_PARTITIONS #define CONFIG_OF_BOARD_SETUP +/* + * PCIE Enable + */ +#define PCI_MAX_DEVICES 3 +#ifdef CONFIG_PCI_IPQ +#define CONFIG_PCI +#define CONFIG_CMD_PCI +#define CONFIG_PCI_SCAN_SHOW +#endif #undef CONFIG_BOOTM_NETBSD #undef CONFIG_BOOTM_PLAN9