[RFC v1 08/16] arm: mvebu: the core PCIe driver

Andrew Lunn andrew at lunn.ch
Mon Dec 10 03:28:47 EST 2012


> +static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
> +{
> +	/*
> +	 * Don't go out when trying to access --
> +	 * 1. nonexisting device on local bus
> +	 * 2. where there's no device connected (no link)
> +	 */
> +	if (bus == pp->root_bus_nr && dev == 0)
> +		return 1;
> +
> +	if (!orion_pcie_link_up(pp->base))
> +		return 0;
> +
> +	if (bus == pp->root_bus_nr && dev != 1)
> +		return 0;
> +
> +	return 1;
> +}
> +
> +/*
> + * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
> + * and then reading the PCIE_CONF_DATA register. Need to make sure these
> + * transactions are atomic.
> + */
> +static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> +			int size, u32 *val)
> +{
> +	struct pci_sys_data *sys = bus->sysdata;
> +	struct pcie_port *pp = sys->private_data;
> +	unsigned long flags;
> +	int ret;
> +
> +	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
> +		*val = 0xffffffff;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	spin_lock_irqsave(&pp->conf_lock, flags);
> +	ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
> +	spin_unlock_irqrestore(&pp->conf_lock, flags);
> +
> +	return ret;
> +}
> +
> +static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> +			int where, int size, u32 val)
> +{
> +	struct pci_sys_data *sys = bus->sysdata;
> +	struct pcie_port *pp = sys->private_data;
> +	unsigned long flags;
> +	int ret;
> +
> +	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	spin_lock_irqsave(&pp->conf_lock, flags);
> +	ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
> +	spin_unlock_irqrestore(&pp->conf_lock, flags);
> +
> +	return ret;
> +}
> +
> +static struct pci_ops pcie_ops = {
> +	.read = pcie_rd_conf,
> +	.write = pcie_wr_conf,
> +};

Hi Thomas

pcie_rd_conf, pcie_wr_conf and pci_ops_pcie_ops are common on orion5x,
dove and kirkwood. Could you maybe factor these functions out and
place them in plat-orion/pcie.c?

> +
> +static void __devinit rc_pci_fixup(struct pci_dev *dev)
> +{
> +	/*
> +	 * Prevent enumeration of root complex.
> +	 */
> +	if (dev->bus->parent == NULL && dev->devfn == 0) {
> +		int i;
> +
> +		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
> +			dev->resource[i].start = 0;
> +			dev->resource[i].end   = 0;
> +			dev->resource[i].flags = 0;
> +		}
> +	}
> +}
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);

rc_pci_fixup is also identical for all orion platforms, so is another
candidate for plat-orion/pcie.c

These are all exact copies, so are easy to cleanup. With more effort
there is more code which can be refactored and centralized, but that
is maybe too much work for the moment?

Thanks

   Andrew



More information about the linux-arm-kernel mailing list