static int sabre_probe()

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;
}