Commit 318ed91f authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'remotes/lorenzo/pci/aardvark'

  - Use LTSSM state to build link training flag since Aardvark doesn't
    implement the Link Training bit (Remi Pommarel)

  - Delay before training Aardvark link in case PERST# was asserted before
    the driver probe (Remi Pommarel)

  - Fix Aardvark issues with Root Control reads and writes (Remi Pommarel)

  - Don't rely on jiffies in Aardvark config access path since interrupts
    may be disabled (Remi Pommarel)

  - Fix Aardvark big-endian support (Grzegorz Jaszczyk)

  - Fix bridge emulation big-endian support (Grzegorz Jaszczyk)

* remotes/lorenzo/pci/aardvark:
  PCI: pci-bridge-emul: Fix big-endian support
  PCI: aardvark: Fix big endian support
  PCI: aardvark: Don't rely on jiffies while holding spinlock
  PCI: aardvark: Fix PCI_EXP_RTCTL register configuration
  PCI: aardvark: Wait for endpoint to be ready before training link
  PCI: aardvark: Use LTSSM state to build link training flag
parents f52412b1 e0d9d30b
Loading
Loading
Loading
Loading
+57 −15
Original line number Diff line number Diff line
@@ -176,11 +176,14 @@
	(PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn))	| \
	 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where))

#define PIO_TIMEOUT_MS			1
#define PIO_RETRY_CNT			500
#define PIO_RETRY_DELAY			2 /* 2 us*/

#define LINK_WAIT_MAX_RETRIES		10
#define LINK_WAIT_USLEEP_MIN		90000
#define LINK_WAIT_USLEEP_MAX		100000
#define RETRAIN_WAIT_MAX_RETRIES	10
#define RETRAIN_WAIT_USLEEP_US		2000

#define MSI_IRQ_NUM			32

@@ -240,6 +243,17 @@ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
	return -ETIMEDOUT;
}

static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
{
	size_t retries;

	for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) {
		if (!advk_pcie_link_up(pcie))
			break;
		udelay(RETRAIN_WAIT_USLEEP_US);
	}
}

static void advk_pcie_setup_hw(struct advk_pcie *pcie)
{
	u32 reg;
@@ -325,6 +339,14 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
	reg |= PIO_CTRL_ADDR_WIN_DISABLE;
	advk_writel(pcie, reg, PIO_CTRL);

	/*
	 * PERST# signal could have been asserted by pinctrl subsystem before
	 * probe() callback has been called, making the endpoint going into
	 * fundamental reset. As required by PCI Express spec a delay for at
	 * least 100ms after such a reset before link training is needed.
	 */
	msleep(PCI_PM_D3COLD_WAIT);

	/* Start link training */
	reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
	reg |= PCIE_CORE_LINK_TRAINING;
@@ -384,17 +406,16 @@ static void advk_pcie_check_pio_status(struct advk_pcie *pcie)
static int advk_pcie_wait_pio(struct advk_pcie *pcie)
{
	struct device *dev = &pcie->pdev->dev;
	unsigned long timeout;

	timeout = jiffies + msecs_to_jiffies(PIO_TIMEOUT_MS);
	int i;

	while (time_before(jiffies, timeout)) {
	for (i = 0; i < PIO_RETRY_CNT; i++) {
		u32 start, isr;

		start = advk_readl(pcie, PIO_START);
		isr = advk_readl(pcie, PIO_ISR);
		if (!start && isr)
			return 0;
		udelay(PIO_RETRY_DELAY);
	}

	dev_err(dev, "config read/write timed out\n");
@@ -416,7 +437,7 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,

	case PCI_EXP_RTCTL: {
		u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
		*value = (val & PCIE_MSG_PM_PME_MASK) ? PCI_EXP_RTCTL_PMEIE : 0;
		*value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE;
		return PCI_BRIDGE_EMUL_HANDLED;
	}

@@ -427,11 +448,20 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
		return PCI_BRIDGE_EMUL_HANDLED;
	}

	case PCI_EXP_LNKCTL: {
		/* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */
		u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) &
			~(PCI_EXP_LNKSTA_LT << 16);
		if (!advk_pcie_link_up(pcie))
			val |= (PCI_EXP_LNKSTA_LT << 16);
		*value = val;
		return PCI_BRIDGE_EMUL_HANDLED;
	}

	case PCI_CAP_LIST_ID:
	case PCI_EXP_DEVCAP:
	case PCI_EXP_DEVCTL:
	case PCI_EXP_LNKCAP:
	case PCI_EXP_LNKCTL:
		*value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
		return PCI_BRIDGE_EMUL_HANDLED;
	default:
@@ -448,14 +478,24 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,

	switch (reg) {
	case PCI_EXP_DEVCTL:
		advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
		break;

	case PCI_EXP_LNKCTL:
		advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
		if (new & PCI_EXP_LNKCTL_RL)
			advk_pcie_wait_for_retrain(pcie);
		break;

	case PCI_EXP_RTCTL:
		new = (new & PCI_EXP_RTCTL_PMEIE) << 3;
		advk_writel(pcie, new, PCIE_ISR0_MASK_REG);
	case PCI_EXP_RTCTL: {
		/* Only mask/unmask PME interrupt */
		u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG) &
			~PCIE_MSG_PM_PME_MASK;
		if ((new & PCI_EXP_RTCTL_PMEIE) == 0)
			val |= PCIE_MSG_PM_PME_MASK;
		advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
		break;
	}

	case PCI_EXP_RTSTA:
		new = (new & PCI_EXP_RTSTA_PME) >> 9;
@@ -480,18 +520,20 @@ static void advk_sw_pci_bridge_init(struct advk_pcie *pcie)
{
	struct pci_bridge_emul *bridge = &pcie->bridge;

	bridge->conf.vendor = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff;
	bridge->conf.device = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16;
	bridge->conf.vendor =
		cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff);
	bridge->conf.device =
		cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16);
	bridge->conf.class_revision =
		advk_readl(pcie, PCIE_CORE_DEV_REV_REG) & 0xff;
		cpu_to_le32(advk_readl(pcie, PCIE_CORE_DEV_REV_REG) & 0xff);

	/* Support 32 bits I/O addressing */
	bridge->conf.iobase = PCI_IO_RANGE_TYPE_32;
	bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32;

	/* Support 64 bits memory pref */
	bridge->conf.pref_mem_base = PCI_PREF_RANGE_TYPE_64;
	bridge->conf.pref_mem_limit = PCI_PREF_RANGE_TYPE_64;
	bridge->conf.pref_mem_base = cpu_to_le16(PCI_PREF_RANGE_TYPE_64);
	bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64);

	/* Support interrupt A for MSI feature */
	bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
+13 −12
Original line number Diff line number Diff line
@@ -270,10 +270,10 @@ static const struct pci_bridge_reg_behavior pcie_cap_regs_behavior[] = {
int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
			 unsigned int flags)
{
	bridge->conf.class_revision |= PCI_CLASS_BRIDGE_PCI << 16;
	bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16);
	bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE;
	bridge->conf.cache_line_size = 0x10;
	bridge->conf.status = PCI_STATUS_CAP_LIST;
	bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST);
	bridge->pci_regs_behavior = kmemdup(pci_regs_behavior,
					    sizeof(pci_regs_behavior),
					    GFP_KERNEL);
@@ -284,8 +284,9 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
		bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START;
		bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP;
		/* Set PCIe v2, root port, slot support */
		bridge->pcie_conf.cap = PCI_EXP_TYPE_ROOT_PORT << 4 | 2 |
			PCI_EXP_FLAGS_SLOT;
		bridge->pcie_conf.cap =
			cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4 | 2 |
				    PCI_EXP_FLAGS_SLOT);
		bridge->pcie_cap_regs_behavior =
			kmemdup(pcie_cap_regs_behavior,
				sizeof(pcie_cap_regs_behavior),
@@ -327,7 +328,7 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
	int reg = where & ~3;
	pci_bridge_emul_read_status_t (*read_op)(struct pci_bridge_emul *bridge,
						 int reg, u32 *value);
	u32 *cfgspace;
	__le32 *cfgspace;
	const struct pci_bridge_reg_behavior *behavior;

	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END) {
@@ -343,11 +344,11 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
		reg -= PCI_CAP_PCIE_START;
		read_op = bridge->ops->read_pcie;
		cfgspace = (u32 *) &bridge->pcie_conf;
		cfgspace = (__le32 *) &bridge->pcie_conf;
		behavior = bridge->pcie_cap_regs_behavior;
	} else {
		read_op = bridge->ops->read_base;
		cfgspace = (u32 *) &bridge->conf;
		cfgspace = (__le32 *) &bridge->conf;
		behavior = bridge->pci_regs_behavior;
	}

@@ -357,7 +358,7 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
		ret = PCI_BRIDGE_EMUL_NOT_HANDLED;

	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED)
		*value = cfgspace[reg / 4];
		*value = le32_to_cpu(cfgspace[reg / 4]);

	/*
	 * Make sure we never return any reserved bit with a value
@@ -387,7 +388,7 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
	int mask, ret, old, new, shift;
	void (*write_op)(struct pci_bridge_emul *bridge, int reg,
			 u32 old, u32 new, u32 mask);
	u32 *cfgspace;
	__le32 *cfgspace;
	const struct pci_bridge_reg_behavior *behavior;

	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END)
@@ -414,11 +415,11 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
		reg -= PCI_CAP_PCIE_START;
		write_op = bridge->ops->write_pcie;
		cfgspace = (u32 *) &bridge->pcie_conf;
		cfgspace = (__le32 *) &bridge->pcie_conf;
		behavior = bridge->pcie_cap_regs_behavior;
	} else {
		write_op = bridge->ops->write_base;
		cfgspace = (u32 *) &bridge->conf;
		cfgspace = (__le32 *) &bridge->conf;
		behavior = bridge->pci_regs_behavior;
	}

@@ -431,7 +432,7 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
	/* Clear the W1C bits */
	new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));

	cfgspace[reg / 4] = new;
	cfgspace[reg / 4] = cpu_to_le32(new);

	if (write_op)
		write_op(bridge, reg, old, new, mask);
+39 −39
Original line number Diff line number Diff line
@@ -6,65 +6,65 @@

/* PCI configuration space of a PCI-to-PCI bridge. */
struct pci_bridge_emul_conf {
	u16 vendor;
	u16 device;
	u16 command;
	u16 status;
	u32 class_revision;
	__le16 vendor;
	__le16 device;
	__le16 command;
	__le16 status;
	__le32 class_revision;
	u8 cache_line_size;
	u8 latency_timer;
	u8 header_type;
	u8 bist;
	u32 bar[2];
	__le32 bar[2];
	u8 primary_bus;
	u8 secondary_bus;
	u8 subordinate_bus;
	u8 secondary_latency_timer;
	u8 iobase;
	u8 iolimit;
	u16 secondary_status;
	u16 membase;
	u16 memlimit;
	u16 pref_mem_base;
	u16 pref_mem_limit;
	u32 prefbaseupper;
	u32 preflimitupper;
	u16 iobaseupper;
	u16 iolimitupper;
	__le16 secondary_status;
	__le16 membase;
	__le16 memlimit;
	__le16 pref_mem_base;
	__le16 pref_mem_limit;
	__le32 prefbaseupper;
	__le32 preflimitupper;
	__le16 iobaseupper;
	__le16 iolimitupper;
	u8 capabilities_pointer;
	u8 reserve[3];
	u32 romaddr;
	__le32 romaddr;
	u8 intline;
	u8 intpin;
	u16 bridgectrl;
	__le16 bridgectrl;
};

/* PCI configuration space of the PCIe capabilities */
struct pci_bridge_emul_pcie_conf {
	u8 cap_id;
	u8 next;
	u16 cap;
	u32 devcap;
	u16 devctl;
	u16 devsta;
	u32 lnkcap;
	u16 lnkctl;
	u16 lnksta;
	u32 slotcap;
	u16 slotctl;
	u16 slotsta;
	u16 rootctl;
	u16 rsvd;
	u32 rootsta;
	u32 devcap2;
	u16 devctl2;
	u16 devsta2;
	u32 lnkcap2;
	u16 lnkctl2;
	u16 lnksta2;
	u32 slotcap2;
	u16 slotctl2;
	u16 slotsta2;
	__le16 cap;
	__le32 devcap;
	__le16 devctl;
	__le16 devsta;
	__le32 lnkcap;
	__le16 lnkctl;
	__le16 lnksta;
	__le32 slotcap;
	__le16 slotctl;
	__le16 slotsta;
	__le16 rootctl;
	__le16 rsvd;
	__le32 rootsta;
	__le32 devcap2;
	__le16 devctl2;
	__le16 devsta2;
	__le32 lnkcap2;
	__le16 lnkctl2;
	__le16 lnksta2;
	__le32 slotcap2;
	__le16 slotctl2;
	__le16 slotsta2;
};

struct pci_bridge_emul;