From fd01d1b29b2b723dbea4df076d3e17652e1c45df Mon Sep 17 00:00:00 2001 From: Rajkumar Ayyasamy Date: Thu, 8 Feb 2018 17:24:37 +0530 Subject: [PATCH] ipq806x: Enabling pci for AP160 and Ap160_2xx board 1. Added pci entries in AP160 and AP160_2xx dts 2. The wifi pcie card requires to be powered on from GPIO pins. This patch also adds the same in AP160 dts file and enable it during PCIe configuration. Change-Id: Icd8f5741d5df38d46640c78a7475853e77b873a9 Signed-off-by: Rajkumar Ayyasamy --- arch/arm/dts/ipq806x-ap160.dts | 57 ++++++++++++++++++++++ arch/arm/dts/ipq806x-ap160_2xx.dts | 40 +++++++++++++++ board/qca/arm/ipq806x/ipq806x.c | 78 ++++++++++++++++++++++++++++++ drivers/pci/pci_ipq.c | 6 +++ 4 files changed, 181 insertions(+) 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);