161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt/* 261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * Support PCI/PCIe on PowerNV platforms 361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * 461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * Currently supports only P5IOC2 561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * 661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * Copyright 2011 Benjamin Herrenschmidt, IBM Corp. 761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * 861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * This program is free software; you can redistribute it and/or 961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * modify it under the terms of the GNU General Public License 1061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * as published by the Free Software Foundation; either version 1161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * 2 of the License, or (at your option) any later version. 1261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt */ 1361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 1461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <linux/kernel.h> 1561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <linux/pci.h> 1661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <linux/delay.h> 1761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <linux/string.h> 1861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <linux/init.h> 1961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <linux/bootmem.h> 2061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <linux/irq.h> 2161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <linux/io.h> 22c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt#include <linux/msi.h> 2361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 2461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/sections.h> 2561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/io.h> 2661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/prom.h> 2761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/pci-bridge.h> 2861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/machdep.h> 29fb1b55d654a7038ca6337fbf55839a308c9bc1a7Gavin Shan#include <asm/msi_bitmap.h> 3061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/ppc-pci.h> 3161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/opal.h> 3261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/iommu.h> 3361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include <asm/tce.h> 3461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 3561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include "powernv.h" 3661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#include "pci.h" 3761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 3861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt/* For now, use a fixed amount of TCE memory for each p5ioc2 3961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * hub, 16M will do 4061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt */ 4161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt#define P5IOC2_TCE_MEMORY 0x01000000 4261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 43c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt#ifdef CONFIG_PCI_MSI 44c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidtstatic int pnv_pci_p5ioc2_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, 45137436c9a6ee385c883db09e41af763888ee7642Gavin Shan unsigned int hwirq, unsigned int virq, 46137436c9a6ee385c883db09e41af763888ee7642Gavin Shan unsigned int is_64, struct msi_msg *msg) 47c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt{ 48c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt if (WARN_ON(!is_64)) 49c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt return -ENXIO; 50c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt msg->data = hwirq - phb->msi_base; 51c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt msg->address_hi = 0x10000000; 52c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt msg->address_lo = 0; 53c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt 54c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt return 0; 55c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt} 56c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt 57c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidtstatic void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb) 58c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt{ 59fb1b55d654a7038ca6337fbf55839a308c9bc1a7Gavin Shan unsigned int count; 60c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt const __be32 *prop = of_get_property(phb->hose->dn, 61c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt "ibm,opal-msi-ranges", NULL); 62c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt if (!prop) 63c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt return; 64c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt 65c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt /* Don't do MSI's on p5ioc2 PCI-X are they are not properly 66c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt * verified in HW 67c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt */ 68c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt if (of_device_is_compatible(phb->hose->dn, "ibm,p5ioc2-pcix")) 69c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt return; 70c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt phb->msi_base = be32_to_cpup(prop); 71fb1b55d654a7038ca6337fbf55839a308c9bc1a7Gavin Shan count = be32_to_cpup(prop + 1); 72fb1b55d654a7038ca6337fbf55839a308c9bc1a7Gavin Shan if (msi_bitmap_alloc(&phb->msi_bmp, count, phb->hose->dn)) { 73c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt pr_err("PCI %d: Failed to allocate MSI bitmap !\n", 74c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt phb->hose->global_number); 75c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt return; 76c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt } 77c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt phb->msi_setup = pnv_pci_p5ioc2_msi_setup; 78c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt phb->msi32_support = 0; 79c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt pr_info(" Allocated bitmap for %d MSIs (base IRQ 0x%x)\n", 80fb1b55d654a7038ca6337fbf55839a308c9bc1a7Gavin Shan count, phb->msi_base); 81c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt} 82c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt#else 83c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidtstatic void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb) { } 84c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt#endif /* CONFIG_PCI_MSI */ 85c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt 86cad5cef62a5a0c525d39118d2e94b6e2034d5e05Greg Kroah-Hartmanstatic void pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb, 87cad5cef62a5a0c525d39118d2e94b6e2034d5e05Greg Kroah-Hartman struct pci_dev *pdev) 8861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt{ 894e13c1ac6baa1d6c2b650d66ca89e1e12727ec19Alexey Kardashevskiy if (phb->p5ioc2.iommu_table.it_map == NULL) { 9061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt iommu_init_table(&phb->p5ioc2.iommu_table, phb->hose->node); 914e13c1ac6baa1d6c2b650d66ca89e1e12727ec19Alexey Kardashevskiy iommu_register_group(&phb->p5ioc2.iommu_table, 924e13c1ac6baa1d6c2b650d66ca89e1e12727ec19Alexey Kardashevskiy pci_domain_nr(phb->hose->bus), phb->opal_id); 934e13c1ac6baa1d6c2b650d66ca89e1e12727ec19Alexey Kardashevskiy } 9461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 95d905c5df9aef38d63df268f6f5e7b13894f626d3Alexey Kardashevskiy set_iommu_table_base_and_group(&pdev->dev, &phb->p5ioc2.iommu_table); 9661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt} 9761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 98e9cc17d4ded2d10b332c7f3788d7817f7d9d01efGavin Shanstatic void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id, 9961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt void *tce_mem, u64 tce_size) 10061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt{ 10161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt struct pnv_phb *phb; 1028c5fcc83afd0738a089641bc0862b9058e9cfd06Alistair Popple const __be64 *prop64; 10361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt u64 phb_id; 10461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt int64_t rc; 10561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt static int primary = 1; 10661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 10761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_info(" Initializing p5ioc2 PHB %s\n", np->full_name); 10861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 10961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt prop64 = of_get_property(np, "ibm,opal-phbid", NULL); 11061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (!prop64) { 11161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_err(" Missing \"ibm,opal-phbid\" property !\n"); 11261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt return; 11361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 11461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb_id = be64_to_cpup(prop64); 11561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" PHB-ID : 0x%016llx\n", phb_id); 11661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" TCE AT : 0x%016lx\n", __pa(tce_mem)); 11761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" TCE SZ : 0x%016llx\n", tce_size); 11861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 11961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt rc = opal_pci_set_phb_tce_memory(phb_id, __pa(tce_mem), tce_size); 12061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (rc != OPAL_SUCCESS) { 12161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_err(" Failed to set TCE memory, OPAL error %lld\n", rc); 12261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt return; 12361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 12461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 12561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb = alloc_bootmem(sizeof(struct pnv_phb)); 12661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (phb) { 12761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt memset(phb, 0, sizeof(struct pnv_phb)); 12861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->hose = pcibios_alloc_controller(np); 12961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 13061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (!phb || !phb->hose) { 13161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_err(" Failed to allocate PCI controller\n"); 13261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt return; 13361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 13461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 13561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt spin_lock_init(&phb->lock); 13661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->hose->first_busno = 0; 13761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->hose->last_busno = 0xff; 13861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->hose->private_data = phb; 139e9cc17d4ded2d10b332c7f3788d7817f7d9d01efGavin Shan phb->hub_id = hub_id; 14061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->opal_id = phb_id; 14161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->type = PNV_PHB_P5IOC2; 142cee72d5bb48952f2e50acd2610d52ea82f7092c9Benjamin Herrenschmidt phb->model = PNV_PHB_MODEL_P5IOC2; 14361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 14461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->regs = of_iomap(np, 0); 14561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 14661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (phb->regs == NULL) 14761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_err(" Failed to map registers !\n"); 14861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt else { 14961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_BUID = 0x%08x\n", in_be32(phb->regs + 0x100)); 15061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_IOSZ = 0x%08x\n", in_be32(phb->regs + 0x1b0)); 15161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_IO_ST = 0x%08x\n", in_be32(phb->regs + 0x1e0)); 15261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_MEM1_H = 0x%08x\n", in_be32(phb->regs + 0x1a0)); 15361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_MEM1_L = 0x%08x\n", in_be32(phb->regs + 0x190)); 15461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_MSZ1_L = 0x%08x\n", in_be32(phb->regs + 0x1c0)); 15561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_MEM_ST = 0x%08x\n", in_be32(phb->regs + 0x1d0)); 15661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_MEM2_H = 0x%08x\n", in_be32(phb->regs + 0x2c0)); 15761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_MEM2_L = 0x%08x\n", in_be32(phb->regs + 0x2b0)); 15861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_MSZ2_H = 0x%08x\n", in_be32(phb->regs + 0x2d0)); 15961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_devel(" P_MSZ2_L = 0x%08x\n", in_be32(phb->regs + 0x2e0)); 16061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 16161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 16261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt /* Interpret the "ranges" property */ 16361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt /* This also maps the I/O region and sets isa_io/mem_base */ 16461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pci_process_bridge_OF_ranges(phb->hose, np, primary); 16561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt primary = 0; 16661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 16761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->hose->ops = &pnv_pci_ops; 16861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 169c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt /* Setup MSI support */ 170c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt pnv_pci_init_p5ioc2_msis(phb); 171c1a2562ac5edcb3965760f4a37368122d85657afBenjamin Herrenschmidt 17261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt /* Setup TCEs */ 17361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup; 17461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table, 1758fa5d4547eb69b7ed710cb03486d33a3a5dc2eadAlexey Kardashevskiy tce_mem, tce_size, 0, 1768fa5d4547eb69b7ed710cb03486d33a3a5dc2eadAlexey Kardashevskiy IOMMU_PAGE_SHIFT_4K); 17761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt} 17861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 17961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidtvoid __init pnv_pci_init_p5ioc2_hub(struct device_node *np) 18061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt{ 18161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt struct device_node *phbn; 1828c5fcc83afd0738a089641bc0862b9058e9cfd06Alistair Popple const __be64 *prop64; 18361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt u64 hub_id; 18461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt void *tce_mem; 18561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt uint64_t tce_per_phb; 18661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt int64_t rc; 18761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt int phb_count = 0; 18861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 18961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_info("Probing p5ioc2 IO-Hub %s\n", np->full_name); 19061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 19161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt prop64 = of_get_property(np, "ibm,opal-hubid", NULL); 19261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (!prop64) { 19361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_err(" Missing \"ibm,opal-hubid\" property !\n"); 19461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt return; 19561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 19661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt hub_id = be64_to_cpup(prop64); 19761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_info(" HUB-ID : 0x%016llx\n", hub_id); 19861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 19961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt /* Currently allocate 16M of TCE memory for every Hub 20061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * 20161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt * XXX TODO: Make it chip local if possible 20261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt */ 20361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt tce_mem = __alloc_bootmem(P5IOC2_TCE_MEMORY, P5IOC2_TCE_MEMORY, 20461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt __pa(MAX_DMA_ADDRESS)); 20561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (!tce_mem) { 20661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_err(" Failed to allocate TCE Memory !\n"); 20761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt return; 20861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 20961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_debug(" TCE : 0x%016lx..0x%016lx\n", 21061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt __pa(tce_mem), __pa(tce_mem) + P5IOC2_TCE_MEMORY - 1); 21161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt rc = opal_pci_set_hub_tce_memory(hub_id, __pa(tce_mem), 21261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt P5IOC2_TCE_MEMORY); 21361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (rc != OPAL_SUCCESS) { 21461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_err(" Failed to allocate TCE memory, OPAL error %lld\n", rc); 21561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt return; 21661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 21761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 21861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt /* Count child PHBs */ 21961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt for_each_child_of_node(np, phbn) { 22061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") || 22161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) 22261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt phb_count++; 22361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 22461305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 22561305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt /* Calculate how much TCE space we can give per PHB */ 22661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt tce_per_phb = __rounddown_pow_of_two(P5IOC2_TCE_MEMORY / phb_count); 22761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt pr_info(" Allocating %lld MB of TCE memory per PHB\n", 22861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt tce_per_phb >> 20); 22961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt 23061305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt /* Initialize PHBs */ 23161305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt for_each_child_of_node(np, phbn) { 23261305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") || 23361305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) { 234e9cc17d4ded2d10b332c7f3788d7817f7d9d01efGavin Shan pnv_pci_init_p5ioc2_phb(phbn, hub_id, 235e9cc17d4ded2d10b332c7f3788d7817f7d9d01efGavin Shan tce_mem, tce_per_phb); 23661305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt tce_mem += tce_per_phb; 23761305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 23861305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt } 23961305a96fad622ae0f0e78cb06f67ad721d378f9Benjamin Herrenschmidt} 240