mirror of
https://github.com/torvalds/linux.git
synced 2024-11-07 20:51:47 +00:00
powerpc/powernv: Supports PHB3
The patch intends to initialize PHB3 during system boot stage. The flag "PNV_PHB_MODEL_PHB3" is introduced to differentiate IODA2 compatible PHB3 from other types of PHBs. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
a485c70989
commit
aa0c033f99
@ -852,18 +852,19 @@ static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus,
|
||||
return phb->ioda.pe_rmap[(bus->number << 8) | devfn];
|
||||
}
|
||||
|
||||
void __init pnv_pci_init_ioda1_phb(struct device_node *np)
|
||||
void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
|
||||
{
|
||||
struct pci_controller *hose;
|
||||
static int primary = 1;
|
||||
struct pnv_phb *phb;
|
||||
unsigned long size, m32map_off, iomap_off, pemap_off;
|
||||
const u64 *prop64;
|
||||
const u32 *prop32;
|
||||
u64 phb_id;
|
||||
void *aux;
|
||||
long rc;
|
||||
|
||||
pr_info(" Initializing IODA OPAL PHB %s\n", np->full_name);
|
||||
pr_info(" Initializing IODA%d OPAL PHB %s\n", ioda_type, np->full_name);
|
||||
|
||||
prop64 = of_get_property(np, "ibm,opal-phbid", NULL);
|
||||
if (!prop64) {
|
||||
@ -890,37 +891,34 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
|
||||
hose->last_busno = 0xff;
|
||||
hose->private_data = phb;
|
||||
phb->opal_id = phb_id;
|
||||
phb->type = PNV_PHB_IODA1;
|
||||
phb->type = ioda_type;
|
||||
|
||||
/* Detect specific models for error handling */
|
||||
if (of_device_is_compatible(np, "ibm,p7ioc-pciex"))
|
||||
phb->model = PNV_PHB_MODEL_P7IOC;
|
||||
else if (of_device_is_compatible(np, "ibm,p8-pciex"))
|
||||
phb->model = PNV_PHB_MODEL_PHB3;
|
||||
else
|
||||
phb->model = PNV_PHB_MODEL_UNKNOWN;
|
||||
|
||||
/* We parse "ranges" now since we need to deduce the register base
|
||||
* from the IO base
|
||||
*/
|
||||
/* Parse 32-bit and IO ranges (if any) */
|
||||
pci_process_bridge_OF_ranges(phb->hose, np, primary);
|
||||
primary = 0;
|
||||
|
||||
/* Magic formula from Milton */
|
||||
/* Get registers */
|
||||
phb->regs = of_iomap(np, 0);
|
||||
if (phb->regs == NULL)
|
||||
pr_err(" Failed to map registers !\n");
|
||||
|
||||
|
||||
/* XXX This is hack-a-thon. This needs to be changed so that:
|
||||
* - we obtain stuff like PE# etc... from device-tree
|
||||
* - we properly re-allocate M32 ourselves
|
||||
* (the OFW one isn't very good)
|
||||
*/
|
||||
|
||||
/* Initialize more IODA stuff */
|
||||
phb->ioda.total_pe = 128;
|
||||
prop32 = of_get_property(np, "ibm,opal-num-pes", NULL);
|
||||
if (!prop32)
|
||||
phb->ioda.total_pe = 1;
|
||||
else
|
||||
phb->ioda.total_pe = *prop32;
|
||||
|
||||
phb->ioda.m32_size = resource_size(&hose->mem_resources[0]);
|
||||
/* OFW Has already off top 64k of M32 space (MSI space) */
|
||||
/* FW Has already off top 64k of M32 space (MSI space) */
|
||||
phb->ioda.m32_size += 0x10000;
|
||||
|
||||
phb->ioda.m32_segsize = phb->ioda.m32_size / phb->ioda.total_pe;
|
||||
@ -930,7 +928,10 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
|
||||
phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe;
|
||||
phb->ioda.io_pci_base = 0; /* XXX calculate this ? */
|
||||
|
||||
/* Allocate aux data & arrays */
|
||||
/* Allocate aux data & arrays
|
||||
*
|
||||
* XXX TODO: Don't allocate io segmap on PHB3
|
||||
*/
|
||||
size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
|
||||
m32map_off = size;
|
||||
size += phb->ioda.total_pe * sizeof(phb->ioda.m32_segmap[0]);
|
||||
@ -960,7 +961,7 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
|
||||
hose->mem_resources[2].start = 0;
|
||||
hose->mem_resources[2].end = 0;
|
||||
|
||||
#if 0
|
||||
#if 0 /* We should really do that ... */
|
||||
rc = opal_pci_set_phb_mem_window(opal->phb_id,
|
||||
window_type,
|
||||
window_num,
|
||||
@ -974,16 +975,6 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
|
||||
phb->ioda.m32_size, phb->ioda.m32_segsize,
|
||||
phb->ioda.io_size, phb->ioda.io_segsize);
|
||||
|
||||
if (phb->regs) {
|
||||
pr_devel(" BUID = 0x%016llx\n", in_be64(phb->regs + 0x100));
|
||||
pr_devel(" PHB2_CR = 0x%016llx\n", in_be64(phb->regs + 0x160));
|
||||
pr_devel(" IO_BAR = 0x%016llx\n", in_be64(phb->regs + 0x170));
|
||||
pr_devel(" IO_BAMR = 0x%016llx\n", in_be64(phb->regs + 0x178));
|
||||
pr_devel(" IO_SAR = 0x%016llx\n", in_be64(phb->regs + 0x180));
|
||||
pr_devel(" M32_BAR = 0x%016llx\n", in_be64(phb->regs + 0x190));
|
||||
pr_devel(" M32_BAMR = 0x%016llx\n", in_be64(phb->regs + 0x198));
|
||||
pr_devel(" M32_SAR = 0x%016llx\n", in_be64(phb->regs + 0x1a0));
|
||||
}
|
||||
phb->hose->ops = &pnv_pci_ops;
|
||||
|
||||
/* Setup RID -> PE mapping function */
|
||||
@ -1011,7 +1002,18 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
|
||||
rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
|
||||
if (rc)
|
||||
pr_warning(" OPAL Error %ld performing IODA table reset !\n", rc);
|
||||
opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE);
|
||||
|
||||
/*
|
||||
* On IODA1 map everything to PE#0, on IODA2 we assume the IODA reset
|
||||
* has cleared the RTT which has the same effect
|
||||
*/
|
||||
if (ioda_type == PNV_PHB_IODA1)
|
||||
opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE);
|
||||
}
|
||||
|
||||
void pnv_pci_init_ioda2_phb(struct device_node *np)
|
||||
{
|
||||
pnv_pci_init_ioda_phb(np, PNV_PHB_IODA2);
|
||||
}
|
||||
|
||||
void __init pnv_pci_init_ioda_hub(struct device_node *np)
|
||||
@ -1034,6 +1036,6 @@ void __init pnv_pci_init_ioda_hub(struct device_node *np)
|
||||
for_each_child_of_node(np, phbn) {
|
||||
/* Look for IODA1 PHBs */
|
||||
if (of_device_is_compatible(phbn, "ibm,ioda-phb"))
|
||||
pnv_pci_init_ioda1_phb(phbn);
|
||||
pnv_pci_init_ioda_phb(phbn, PNV_PHB_IODA1);
|
||||
}
|
||||
}
|
||||
|
@ -492,7 +492,7 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
|
||||
pnv_pci_dma_fallback_setup(hose, pdev);
|
||||
}
|
||||
|
||||
/* Fixup wrong class code in p7ioc root complex */
|
||||
/* Fixup wrong class code in p7ioc and p8 root complex */
|
||||
static void pnv_p7ioc_rc_quirk(struct pci_dev *dev)
|
||||
{
|
||||
dev->class = PCI_CLASS_BRIDGE_PCI << 8;
|
||||
@ -558,6 +558,10 @@ void __init pnv_pci_init(void)
|
||||
if (!found_ioda)
|
||||
for_each_compatible_node(np, NULL, "ibm,p5ioc2")
|
||||
pnv_pci_init_p5ioc2_hub(np);
|
||||
|
||||
/* Look for ioda2 built-in PHB3's */
|
||||
for_each_compatible_node(np, NULL, "ibm,ioda2-phb")
|
||||
pnv_pci_init_ioda2_phb(np);
|
||||
}
|
||||
|
||||
/* Setup the linkage between OF nodes and PHBs */
|
||||
|
@ -4,9 +4,9 @@
|
||||
struct pci_dn;
|
||||
|
||||
enum pnv_phb_type {
|
||||
PNV_PHB_P5IOC2,
|
||||
PNV_PHB_IODA1,
|
||||
PNV_PHB_IODA2,
|
||||
PNV_PHB_P5IOC2 = 0,
|
||||
PNV_PHB_IODA1 = 1,
|
||||
PNV_PHB_IODA2 = 2,
|
||||
};
|
||||
|
||||
/* Precise PHB model for error management */
|
||||
@ -14,6 +14,7 @@ enum pnv_phb_model {
|
||||
PNV_PHB_MODEL_UNKNOWN,
|
||||
PNV_PHB_MODEL_P5IOC2,
|
||||
PNV_PHB_MODEL_P7IOC,
|
||||
PNV_PHB_MODEL_PHB3,
|
||||
};
|
||||
|
||||
#define PNV_PCI_DIAG_BUF_SIZE 4096
|
||||
@ -148,6 +149,7 @@ extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
|
||||
u64 dma_offset);
|
||||
extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
|
||||
extern void pnv_pci_init_ioda_hub(struct device_node *np);
|
||||
extern void pnv_pci_init_ioda2_phb(struct device_node *np);
|
||||
|
||||
|
||||
#endif /* __POWERNV_PCI_H */
|
||||
|
Loading…
Reference in New Issue
Block a user