diff --git a/arch/arm/dts/ipq806x-ap160.dts b/arch/arm/dts/ipq806x-ap160.dts index 33d8abdda9..5f615d5a96 100644 --- a/arch/arm/dts/ipq806x-ap160.dts +++ b/arch/arm/dts/ipq806x-ap160.dts @@ -23,6 +23,10 @@ console = "/serial@16340000"; nand = "/nand@1A600000"; gmac_gpio = "/gmac1_gpio"; + pci0 = "/pci@1b500000"; + pci1 = "/pci@1b700000"; + pci2 = "/pci@1b900000"; + pci_pwr = "/pci_pwr"; }; gmac_cfg { @@ -54,4 +58,57 @@ phy_name = "IPQ MDIO2"; }; }; + pci@1b500000 { + pci_gpio { + gpio3 { + gpio = <3>; + func = <1>; + pull = ; + drvstr = ; + oe = ; + }; + }; + }; + + pci@1b700000 { + pci_gpio { + gpio48 { + gpio = <48>; + func = <1>; + pull = ; + drvstr = ; + oe = ; + }; + }; + }; + + pci@1b900000 { + pci_gpio { + gpio63 { + gpio = <63>; + func = <1>; + pull = ; + drvstr = ; + oe = ; + }; + }; + }; + + pci_pwr { + gpio1 { + gpio = <9>; + func = <0>; + pull = ; + drvstr = ; + oe = ; + }; + + gpio2 { + gpio = <26>; + func = <0>; + pull = ; + drvstr = ; + oe = ; + }; + }; }; diff --git a/arch/arm/dts/ipq806x-ap160_2xx.dts b/arch/arm/dts/ipq806x-ap160_2xx.dts index 83b932a8a3..5d76d9492e 100644 --- a/arch/arm/dts/ipq806x-ap160_2xx.dts +++ b/arch/arm/dts/ipq806x-ap160_2xx.dts @@ -22,5 +22,45 @@ aliases { console = "/serial@16340000"; nand = "/nand@1A600000"; + pci0 = "/pci@1b500000"; + pci1 = "/pci@1b700000"; + pci2 = "/pci@1b900000"; }; + + pci@1b500000 { + pci_gpio { + gpio3 { + gpio = <3>; + func = <1>; + pull = ; + drvstr = ; + oe = ; + }; + }; + }; + + pci@1b700000 { + pci_gpio { + gpio48 { + gpio = <48>; + func = <1>; + pull = ; + drvstr = ; + oe = ; + }; + }; + }; + + pci@1b900000 { + pci_gpio { + gpio63 { + gpio = <63>; + func = <1>; + pull = ; + drvstr = ; + oe = ; + }; + }; + }; + }; diff --git a/board/qca/arm/ipq806x/ipq806x.c b/board/qca/arm/ipq806x/ipq806x.c index ef8178a8de..0851f82d4e 100644 --- a/board/qca/arm/ipq806x/ipq806x.c +++ b/board/qca/arm/ipq806x/ipq806x.c @@ -402,6 +402,41 @@ void qca_serial_init(struct ipq_serial_platdata *plat) GSBI_CTRL_REG(gsbi_base)); } + +void ipq_wifi_pci_power_enable() +{ + int offset; + u32 gpio; + + offset = fdt_path_offset(gd->fdt_blob, "pci_pwr"); + if (offset >= 0) { + qca_gpio_init(offset); + for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0; + offset = fdt_next_subnode(gd->fdt_blob, offset)) { + + gpio = fdtdec_get_uint(gd->fdt_blob, + offset, "gpio", 0); + gpio_set_value(gpio, 1); + } + } +} + +static void ipq_wifi_pci_power_disable() +{ + int offset; + u32 gpio; + offset = fdt_path_offset(gd->fdt_blob, "pci_pwr"); + if (offset >= 0) { + for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0; + offset = fdt_next_subnode(gd->fdt_blob, offset)) { + + gpio = fdtdec_get_uint(gd->fdt_blob, + offset, "gpio", 0); + gpio_set_value(gpio, 0); + } + } +} + void board_pcie_clock_init(int id) { switch(id) { @@ -444,6 +479,49 @@ void board_pci_init(int id) return; } +void board_pci_deinit() +{ + int node, gpio_node, i, gpio; + char name[16]; + struct fdt_resource parf; + struct fdt_resource pci_rst; + struct qca_gpio_config gpio_config = {0}; + + 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 in device tree\n"); + return; + } + gpio_config.gpio = fdtdec_get_uint(gd->fdt_blob, + node, "perst_gpio", 0); + + gpio_tlmm_config(&gpio_config); + + fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names", "pci_rst", + &pci_rst); + writel(0x7d, pci_rst.start); + fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names", "parf", + &parf); + writel(0x1, parf.start + 0x40); + switch(i) { + case PCIE_0: + pcie_clock_shutdown(&pcie_0_clk); + break; + case PCIE_1: + pcie_clock_shutdown(&pcie_1_clk); + break; + case PCIE_2: + pcie_clock_shutdown(&pcie_2_clk); + break; + } + + } + ipq_wifi_pci_power_disable(); + + return ; +} void ipq_fdt_fixup_socinfo(void *blob) { uint32_t cpu_type; diff --git a/drivers/pci/pci_ipq.c b/drivers/pci/pci_ipq.c index 464d4b746d..0b616ccebf 100644 --- a/drivers/pci/pci_ipq.c +++ b/drivers/pci/pci_ipq.c @@ -832,6 +832,11 @@ static int pci_ipq_ofdata_to_platdata(int id, struct ipq_pcie *pcie) return 0; } +__weak void ipq_wifi_pci_power_enable() +{ + return; +} + void pci_init_board (void) { struct ipq_pcie *pcie; @@ -855,6 +860,7 @@ void pci_init_board (void) break; } + ipq_wifi_pci_power_enable(); for (i = 0; i < PCI_MAX_DEVICES; i++) { pcie->linkup = 0; pci_ipq_ofdata_to_platdata(i, pcie);