static u8 __init
ruffian_swizzle(struct pci_dev *dev, u8 *pinp)
{
	int slot, pin = *pinp;

	if (dev->bus->number == 0) {
		slot = PCI_SLOT(dev->devfn);
	}
	/* Check for the built-in bridge.  */
	else if (PCI_SLOT(dev->bus->self->devfn) == 13) {
		slot = PCI_SLOT(dev->devfn) + 10;
	}
	else
	{
		/* Must be a card-based bridge.  */
		do {
			if (PCI_SLOT(dev->bus->self->devfn) == 13) {
				slot = PCI_SLOT(dev->devfn) + 10;
				break;
			}
			pin = pci_swizzle_interrupt_pin(dev, pin);

			/* Move up the chain of bridges.  */
			dev = dev->bus->self;
			/* Slot of the next bridge.  */
			slot = PCI_SLOT(dev->devfn);
		} while (dev->bus->self);
	}
	*pinp = pin;
	return slot;
}
static u8 __init
miata_swizzle(struct pci_dev *dev, u8 *pinp)
{
	int slot, pin = *pinp;

	if (dev->bus->number == 0) {
		slot = PCI_SLOT(dev->devfn);
	}		
	/*                                 */
	else if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
		 (PCI_SLOT(dev->bus->self->devfn) == 20)) {
		slot = PCI_SLOT(dev->devfn) + 9;
	}
	else 
	{
		/*                               */
		do {
			if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
			    (PCI_SLOT(dev->bus->self->devfn) == 20)) {
				slot = PCI_SLOT(dev->devfn) + 9;
				break;
			}
			pin = pci_swizzle_interrupt_pin(dev, pin);

			/*                                */
			dev = dev->bus->self;
			/*                           */
			slot = PCI_SLOT(dev->devfn);
		} while (dev->bus->self);
	}
	*pinp = pin;
	return slot;
}
Ejemplo n.º 3
0
static u8 __init
monet_swizzle(struct pci_dev *dev, u8 *pinp)
{
	struct pci_controller *hose = dev->sysdata;
	int slot, pin = *pinp;

	if (!dev->bus->parent) {
		slot = PCI_SLOT(dev->devfn);
	}
	/* Check for the built-in bridge on hose 1. */
	else if (hose->index == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) {
		slot = PCI_SLOT(dev->devfn);
	} else {
		/* Must be a card-based bridge.  */
		do {
			/* Check for built-in bridge on hose 1. */
			if (hose->index == 1 &&
			    PCI_SLOT(dev->bus->self->devfn) == 8) {
				slot = PCI_SLOT(dev->devfn);
				break;
			}
			pin = pci_swizzle_interrupt_pin(dev, pin);

			/* Move up the chain of bridges.  */
			dev = dev->bus->self;
			/* Slot of the next bridge.  */
			slot = PCI_SLOT(dev->devfn);
		} while (dev->bus->self);
	}
	*pinp = pin;
	return slot;
}
Ejemplo n.º 4
0
static u8 __init integrator_swizzle(struct pci_dev *dev, u8 *pinp)
{
	int pin = *pinp;

	if (pin == 0)
		pin = 1;

	while (dev->bus->self) {
		pin = pci_swizzle_interrupt_pin(dev, pin);
		/*
                                                      
   */
		dev = dev->bus->self;
	}
	*pinp = pin;

	return PCI_SLOT(dev->devfn);
}
Ejemplo n.º 5
0
int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
{
	struct device_node *dn, *ppnode;
	struct pci_dev *ppdev;
	u32 lspec;
	u32 laddr[3];
	u8 pin;
	int rc;

	/* Check if we have a device node, if yes, fallback to standard OF
	 * parsing
	 */
	dn = pci_device_to_OF_node(pdev);
	if (dn)
		return of_irq_map_one(dn, 0, out_irq);

	/* Ok, we don't, time to have fun. Let's start by building up an
	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
	 * for PCI. If you do different, then don't use that routine.
	 */
	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
	if (rc != 0)
		return rc;
	/* No pin, exit */
	if (pin == 0)
		return -ENODEV;

	/* Now we walk up the PCI tree */
	lspec = pin;
	for (;;) {
		/* Get the pci_dev of our parent */
		ppdev = pdev->bus->self;

		/* Ouch, it's a host bridge... */
		if (ppdev == NULL) {
			struct pci_controller *host;
			host = pci_bus_to_host(pdev->bus);
			ppnode = host ? host->dn : NULL;
			/* No node for host bridge ? give up */
			if (ppnode == NULL)
				return -EINVAL;
		} else
			/* We found a P2P bridge, check if it has a node */
			ppnode = pci_device_to_OF_node(ppdev);

		/* Ok, we have found a parent with a device-node, hand over to
		 * the OF parsing code.
		 * We build a unit address from the linux device to be used for
		 * resolution. Note that we use the linux bus number which may
		 * not match your firmware bus numbering.
		 * Fortunately, in most cases, interrupt-map-mask doesn't
		 * include the bus number as part of the matching.
		 * You should still be careful about that though if you intend
		 * to rely on this function (you ship  a firmware that doesn't
		 * create device nodes for all PCI devices).
		 */
		if (ppnode)
			break;

		/* We can only get here if we hit a P2P bridge with no node,
		 * let's do standard swizzling and try again
		 */
		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
		pdev = ppdev;
	}

	laddr[0] = (pdev->bus->number << 16)
		| (pdev->devfn << 8);
	laddr[1]  = laddr[2] = 0;
	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
}
Ejemplo n.º 6
0
int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	int result = -1;

	/* The complication here is that the PCI IRQ lines from the Cayman's 2
	   5V slots get into the CPU via a different path from the IRQ lines
	   from the 3 3.3V slots.  Thus, we have to detect whether the card's
	   interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
	   at the point where we cross from 5V to 3.3V is not the normal case.

	   The added complication is that we don't know that the 5V slots are
	   always bus 2, because a card containing a PCI-PCI bridge may be
	   plugged into a 3.3V slot, and this changes the bus numbering.

	   Also, the Cayman has an intermediate PCI bus that goes a custom
	   expansion board header (and to the secondary bridge).  This bus has
	   never been used in practice.

	   The 1ary onboard PCI-PCI bridge is device 3 on bus 0
	   The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of
	   the 1ary bridge.
	   */

	struct slot_pin {
		int slot;
		int pin;
	} path[4];
	int i=0;

	while (dev->bus->number > 0) {

		slot = path[i].slot = PCI_SLOT(dev->devfn);
		pin = path[i].pin = pci_swizzle_interrupt_pin(dev, pin);
		dev = dev->bus->self;
		i++;
		if (i > 3) panic("PCI path to root bus too long!\n");
	}

	slot = PCI_SLOT(dev->devfn);
	/* This is the slot on bus 0 through which the device is eventually
	   reachable. */

	/* Now work back up. */
	if ((slot < 3) || (i == 0)) {
		/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
		   swizzle now. */
		result = IRQ_INTA + pci_swizzle_interrupt_pin(dev, pin) - 1;
	} else {
		i--;
		slot = path[i].slot;
		pin  = path[i].pin;
		if (slot > 0) {
			panic("PCI expansion bus device found - not handled!\n");
		} else {
			if (i > 0) {
				/* 5V slots */
				i--;
				slot = path[i].slot;
				pin  = path[i].pin;
				/* 'pin' was swizzled earlier wrt slot, don't do it again. */
				result = IRQ_P2INTA + (pin - 1);
			} else {
				/* IRQ for 2ary PCI-PCI bridge : unused */
				result = -1;
			}
		}
	}

	return result;
}
Ejemplo n.º 7
0
/**
 * of_irq_parse_pci - Resolve the interrupt for a PCI device
 * @pdev:       the device whose interrupt is to be resolved
 * @out_irq:    structure of_irq filled by this function
 *
 * This function resolves the PCI interrupt for a given PCI device. If a
 * device-node exists for a given pci_dev, it will use normal OF tree
 * walking. If not, it will implement standard swizzling and walk up the
 * PCI tree until an device-node is found, at which point it will finish
 * resolving using the OF tree walking.
 */
int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
{
	struct device_node *dn, *ppnode;
	struct pci_dev *ppdev;
	__be32 laddr[3];
	u8 pin;
	int rc;

	/* Check if we have a device node, if yes, fallback to standard
	 * device tree parsing
	 */
	dn = pci_device_to_OF_node(pdev);
	if (dn) {
		rc = of_irq_parse_one(dn, 0, out_irq);
		if (!rc)
			return rc;
	}

	/* Ok, we don't, time to have fun. Let's start by building up an
	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
	 * for PCI. If you do different, then don't use that routine.
	 */
	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
	if (rc != 0)
		goto err;
	/* No pin, exit with no error message. */
	if (pin == 0)
		return -ENODEV;

	/* Now we walk up the PCI tree */
	for (;;) {
		/* Get the pci_dev of our parent */
		ppdev = pdev->bus->self;

		/* Ouch, it's a host bridge... */
		if (ppdev == NULL) {
			ppnode = pci_bus_to_OF_node(pdev->bus);

			/* No node for host bridge ? give up */
			if (ppnode == NULL) {
				rc = -EINVAL;
				goto err;
			}
		} else {
			/* We found a P2P bridge, check if it has a node */
			ppnode = pci_device_to_OF_node(ppdev);
		}

		/* Ok, we have found a parent with a device-node, hand over to
		 * the OF parsing code.
		 * We build a unit address from the linux device to be used for
		 * resolution. Note that we use the linux bus number which may
		 * not match your firmware bus numbering.
		 * Fortunately, in most cases, interrupt-map-mask doesn't
		 * include the bus number as part of the matching.
		 * You should still be careful about that though if you intend
		 * to rely on this function (you ship  a firmware that doesn't
		 * create device nodes for all PCI devices).
		 */
		if (ppnode)
			break;

		/* We can only get here if we hit a P2P bridge with no node,
		 * let's do standard swizzling and try again
		 */
		pin = pci_swizzle_interrupt_pin(pdev, pin);
		pdev = ppdev;
	}

	out_irq->np = ppnode;
	out_irq->args_count = 1;
	out_irq->args[0] = pin;
	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
	laddr[1] = laddr[2] = cpu_to_be32(0);
	rc = of_irq_parse_raw(laddr, out_irq);
	if (rc)
		goto err;
	return 0;
err:
	if (rc == -ENOENT) {
		dev_warn(&pdev->dev,
			"%s: no interrupt-map found, INTx interrupts not available\n",
			__func__);
		pr_warn_once("%s: possibly some PCI slots don't have level triggered interrupts capability\n",
			__func__);
	} else {
		dev_err(&pdev->dev, "%s: failed with rc=%d\n", __func__, rc);
	}
	return rc;
}