Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/virtex: Add support for Xilinx PCI host bridge

This patch adds support for the Xilinx plbv46-pci-1.03.a PCI host
bridge IPcore.

Signed-off-by: Roderick Colenbrander <thunderbird2k@gmail.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

authored by

Roderick Colenbrander and committed by
Grant Likely
64f16502 baf75b0a

+162
+21
arch/powerpc/include/asm/xilinx_pci.h
··· 1 + /* 2 + * Xilinx pci external definitions 3 + * 4 + * Copyright 2009 Roderick Colenbrander 5 + * Copyright 2009 Secret Lab Technologies Ltd. 6 + * 7 + * This file is licensed under the terms of the GNU General Public License 8 + * version 2. This program is licensed "as is" without any warranty of any 9 + * kind, whether express or implied. 10 + */ 11 + 12 + #ifndef INCLUDE_XILINX_PCI 13 + #define INCLUDE_XILINX_PCI 14 + 15 + #ifdef CONFIG_XILINX_PCI 16 + extern void __init xilinx_pci_init(void); 17 + #else 18 + static inline void __init xilinx_pci_init(void) { return; } 19 + #endif 20 + 21 + #endif /* INCLUDE_XILINX_PCI */
+2
arch/powerpc/platforms/40x/virtex.c
··· 14 14 #include <asm/prom.h> 15 15 #include <asm/time.h> 16 16 #include <asm/xilinx_intc.h> 17 + #include <asm/xilinx_pci.h> 17 18 #include <asm/ppc4xx.h> 18 19 19 20 static struct of_device_id xilinx_of_bus_ids[] __initdata = { ··· 48 47 define_machine(virtex) { 49 48 .name = "Xilinx Virtex", 50 49 .probe = virtex_probe, 50 + .setup_arch = xilinx_pci_init, 51 51 .init_IRQ = xilinx_intc_init_tree, 52 52 .get_irq = xilinx_intc_get_irq, 53 53 .restart = ppc4xx_reset_system,
+2
arch/powerpc/platforms/44x/virtex.c
··· 16 16 #include <asm/prom.h> 17 17 #include <asm/time.h> 18 18 #include <asm/xilinx_intc.h> 19 + #include <asm/xilinx_pci.h> 19 20 #include <asm/reg.h> 20 21 #include <asm/ppc4xx.h> 21 22 #include "44x.h" ··· 54 53 define_machine(virtex) { 55 54 .name = "Xilinx Virtex440", 56 55 .probe = virtex_probe, 56 + .setup_arch = xilinx_pci_init, 57 57 .init_IRQ = xilinx_intc_init_tree, 58 58 .get_irq = xilinx_intc_get_irq, 59 59 .calibrate_decr = generic_calibrate_decr,
+4
arch/powerpc/platforms/Kconfig
··· 329 329 also register MCU GPIOs with the generic GPIO API, so you'll able 330 330 to use MCU pins as GPIOs. 331 331 332 + config XILINX_PCI 333 + bool "Xilinx PCI host bridge support" 334 + depends on PCI && XILINX_VIRTEX 335 + 332 336 endmenu
+1
arch/powerpc/sysdev/Makefile
··· 34 34 obj-$(CONFIG_4xx) += uic.o 35 35 obj-$(CONFIG_4xx_SOC) += ppc4xx_soc.o 36 36 obj-$(CONFIG_XILINX_VIRTEX) += xilinx_intc.o 37 + obj-$(CONFIG_XILINX_PCI) += xilinx_pci.o 37 38 obj-$(CONFIG_OF_RTC) += of_rtc.o 38 39 ifeq ($(CONFIG_PCI),y) 39 40 obj-$(CONFIG_4xx) += ppc4xx_pci.o
+132
arch/powerpc/sysdev/xilinx_pci.c
··· 1 + /* 2 + * PCI support for Xilinx plbv46_pci soft-core which can be used on 3 + * Xilinx Virtex ML410 / ML510 boards. 4 + * 5 + * Copyright 2009 Roderick Colenbrander 6 + * Copyright 2009 Secret Lab Technologies Ltd. 7 + * 8 + * The pci bridge fixup code was copied from ppc4xx_pci.c and was written 9 + * by Benjamin Herrenschmidt. 10 + * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. 11 + * 12 + * This file is licensed under the terms of the GNU General Public License 13 + * version 2. This program is licensed "as is" without any warranty of any 14 + * kind, whether express or implied. 15 + */ 16 + 17 + #include <linux/ioport.h> 18 + #include <linux/of.h> 19 + #include <linux/pci.h> 20 + #include <mm/mmu_decl.h> 21 + #include <asm/io.h> 22 + #include <asm/xilinx_pci.h> 23 + 24 + #define XPLB_PCI_ADDR 0x10c 25 + #define XPLB_PCI_DATA 0x110 26 + #define XPLB_PCI_BUS 0x114 27 + 28 + #define PCI_HOST_ENABLE_CMD PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY 29 + 30 + static struct of_device_id xilinx_pci_match[] = { 31 + { .compatible = "xlnx,plbv46-pci-1.03.a", }, 32 + {} 33 + }; 34 + 35 + /** 36 + * xilinx_pci_fixup_bridge - Block Xilinx PHB configuration. 37 + */ 38 + static void xilinx_pci_fixup_bridge(struct pci_dev *dev) 39 + { 40 + struct pci_controller *hose; 41 + int i; 42 + 43 + if (dev->devfn || dev->bus->self) 44 + return; 45 + 46 + hose = pci_bus_to_host(dev->bus); 47 + if (!hose) 48 + return; 49 + 50 + if (!of_match_node(xilinx_pci_match, hose->dn)) 51 + return; 52 + 53 + /* Hide the PCI host BARs from the kernel as their content doesn't 54 + * fit well in the resource management 55 + */ 56 + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 57 + dev->resource[i].start = 0; 58 + dev->resource[i].end = 0; 59 + dev->resource[i].flags = 0; 60 + } 61 + 62 + dev_info(&dev->dev, "Hiding Xilinx plb-pci host bridge resources %s\n", 63 + pci_name(dev)); 64 + } 65 + DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, xilinx_pci_fixup_bridge); 66 + 67 + /** 68 + * xilinx_pci_exclude_device - Don't do config access for non-root bus 69 + * 70 + * This is a hack. Config access to any bus other than bus 0 does not 71 + * currently work on the ML510 so we prevent it here. 72 + */ 73 + static int 74 + xilinx_pci_exclude_device(struct pci_controller *hose, u_char bus, u8 devfn) 75 + { 76 + return (bus != 0); 77 + } 78 + 79 + /** 80 + * xilinx_pci_init - Find and register a Xilinx PCI host bridge 81 + */ 82 + void __init xilinx_pci_init(void) 83 + { 84 + struct pci_controller *hose; 85 + struct resource r; 86 + void __iomem *pci_reg; 87 + struct device_node *pci_node; 88 + 89 + pci_node = of_find_matching_node(NULL, xilinx_pci_match); 90 + if(!pci_node) 91 + return; 92 + 93 + if (of_address_to_resource(pci_node, 0, &r)) { 94 + pr_err("xilinx-pci: cannot resolve base address\n"); 95 + return; 96 + } 97 + 98 + hose = pcibios_alloc_controller(pci_node); 99 + if (!hose) { 100 + pr_err("xilinx-pci: pcibios_alloc_controller() failed\n"); 101 + return; 102 + } 103 + 104 + /* Setup config space */ 105 + setup_indirect_pci(hose, r.start + XPLB_PCI_ADDR, 106 + r.start + XPLB_PCI_DATA, 107 + PPC_INDIRECT_TYPE_SET_CFG_TYPE); 108 + 109 + /* According to the xilinx plbv46_pci documentation the soft-core starts 110 + * a self-init when the bus master enable bit is set. Without this bit 111 + * set the pci bus can't be scanned. 112 + */ 113 + early_write_config_word(hose, 0, 0, PCI_COMMAND, PCI_HOST_ENABLE_CMD); 114 + 115 + /* Set the max latency timer to 255 */ 116 + early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0xff); 117 + 118 + /* Set the max bus number to 255 */ 119 + pci_reg = of_iomap(pci_node, 0); 120 + out_8(pci_reg + XPLB_PCI_BUS, 0xff); 121 + iounmap(pci_reg); 122 + 123 + /* Nothing past the root bridge is working right now. By default 124 + * exclude config access to anything except bus 0 */ 125 + if (!ppc_md.pci_exclude_device) 126 + ppc_md.pci_exclude_device = xilinx_pci_exclude_device; 127 + 128 + /* Register the host bridge with the linux kernel! */ 129 + pci_process_bridge_OF_ranges(hose, pci_node, 1); 130 + 131 + pr_info("xilinx-pci: Registered PCI host bridge\n"); 132 + }