in kernel/pci_sabre.c [457:586]
static int sabre_probe(struct platform_device *op)
{
const struct of_device_id *match;
const struct linux_prom64_registers *pr_regs;
struct device_node *dp = op->dev.of_node;
struct pci_pbm_info *pbm;
u32 upa_portid, dma_mask;
struct iommu *iommu;
int tsbsize, err;
const u32 *vdma;
u64 clear_irq;
match = of_match_device(sabre_match, &op->dev);
hummingbird_p = match && (match->data != NULL);
if (!hummingbird_p) {
struct device_node *cpu_dp;
/* Of course, Sun has to encode things a thousand
* different ways, inconsistently.
*/
for_each_node_by_type(cpu_dp, "cpu") {
if (of_node_name_eq(cpu_dp, "SUNW,UltraSPARC-IIe"))
hummingbird_p = 1;
}
}
err = -ENOMEM;
pbm = kzalloc(sizeof(*pbm), GFP_KERNEL);
if (!pbm) {
printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n");
goto out_err;
}
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
if (!iommu) {
printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n");
goto out_free_controller;
}
pbm->iommu = iommu;
upa_portid = of_getintprop_default(dp, "upa-portid", 0xff);
pbm->portid = upa_portid;
/*
* Map in SABRE register set and report the presence of this SABRE.
*/
pr_regs = of_get_property(dp, "reg", NULL);
err = -ENODEV;
if (!pr_regs) {
printk(KERN_ERR PFX "No reg property\n");
goto out_free_iommu;
}
/*
* First REG in property is base of entire SABRE register space.
*/
pbm->controller_regs = pr_regs[0].phys_addr;
/* Clear interrupts */
/* PCI first */
for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8)
upa_writeq(0x0UL, pbm->controller_regs + clear_irq);
/* Then OBIO */
for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8)
upa_writeq(0x0UL, pbm->controller_regs + clear_irq);
/* Error interrupts are enabled later after the bus scan. */
upa_writeq((SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR |
SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN),
pbm->controller_regs + SABRE_PCICTRL);
/* Now map in PCI config space for entire SABRE. */
pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE;
vdma = of_get_property(dp, "virtual-dma", NULL);
if (!vdma) {
printk(KERN_ERR PFX "No virtual-dma property\n");
goto out_free_iommu;
}
dma_mask = vdma[0];
switch(vdma[1]) {
case 0x20000000:
dma_mask |= 0x1fffffff;
tsbsize = 64;
break;
case 0x40000000:
dma_mask |= 0x3fffffff;
tsbsize = 128;
break;
case 0x80000000:
dma_mask |= 0x7fffffff;
tsbsize = 128;
break;
default:
printk(KERN_ERR PFX "Strange virtual-dma size.\n");
goto out_free_iommu;
}
err = psycho_iommu_init(pbm, tsbsize, vdma[0], dma_mask, SABRE_WRSYNC);
if (err)
goto out_free_iommu;
/*
* Look for APB underneath.
*/
sabre_pbm_init(pbm, op);
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
dev_set_drvdata(&op->dev, pbm);
return 0;
out_free_iommu:
kfree(pbm->iommu);
out_free_controller:
kfree(pbm);
out_err:
return err;
}