Commit b138f67d authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'remotes/lorenzo/pci/iproc'

  - Work around iproc CRS completion issues (Srinath Mannam)

  - Allow smaller iproc outbound windows so driver can work on 32-bit
    systems (Srinath Mannam)

  - Use iproc-specific config read for PAXBv2 (not PAXB) (Srinath Mannam)

* remotes/lorenzo/pci/iproc:
  PCI: iproc: Enable iProc config read for PAXBv2
  PCI: iproc: Allow outbound configuration for 32-bit I/O region
  PCI: iproc: Add CRS check in config read
parents 5349abcf 8cff9954
Loading
Loading
Loading
Loading
+41 −5
Original line number Diff line number Diff line
@@ -60,6 +60,10 @@
#define APB_ERR_EN_SHIFT		0
#define APB_ERR_EN			BIT(APB_ERR_EN_SHIFT)

#define CFG_RD_SUCCESS			0
#define CFG_RD_UR			1
#define CFG_RD_CRS			2
#define CFG_RD_CA			3
#define CFG_RETRY_STATUS		0xffff0001
#define CFG_RETRY_STATUS_TIMEOUT_US	500000 /* 500 milliseconds */

@@ -289,6 +293,9 @@ enum iproc_pcie_reg {
	IPROC_PCIE_IARR4,
	IPROC_PCIE_IMAP4,

	/* config read status */
	IPROC_PCIE_CFG_RD_STATUS,

	/* link status */
	IPROC_PCIE_LINK_STATUS,

@@ -350,6 +357,7 @@ static const u16 iproc_pcie_reg_paxb_v2[] = {
	[IPROC_PCIE_IMAP3]		= 0xe08,
	[IPROC_PCIE_IARR4]		= 0xe68,
	[IPROC_PCIE_IMAP4]		= 0xe70,
	[IPROC_PCIE_CFG_RD_STATUS]	= 0xee0,
	[IPROC_PCIE_LINK_STATUS]	= 0xf0c,
	[IPROC_PCIE_APB_ERR_EN]		= 0xf40,
};
@@ -474,10 +482,12 @@ static void __iomem *iproc_pcie_map_ep_cfg_reg(struct iproc_pcie *pcie,
	return (pcie->base + offset);
}

static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p)
static unsigned int iproc_pcie_cfg_retry(struct iproc_pcie *pcie,
					 void __iomem *cfg_data_p)
{
	int timeout = CFG_RETRY_STATUS_TIMEOUT_US;
	unsigned int data;
	u32 status;

	/*
	 * As per PCIe spec r3.1, sec 2.3.2, CRS Software Visibility only
@@ -498,6 +508,15 @@ static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p)
	 */
	data = readl(cfg_data_p);
	while (data == CFG_RETRY_STATUS && timeout--) {
		/*
		 * CRS state is set in CFG_RD status register
		 * This will handle the case where CFG_RETRY_STATUS is
		 * valid config data.
		 */
		status = iproc_pcie_read_reg(pcie, IPROC_PCIE_CFG_RD_STATUS);
		if (status != CFG_RD_CRS)
			return data;

		udelay(1);
		data = readl(cfg_data_p);
	}
@@ -576,7 +595,7 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
	if (!cfg_data_p)
		return PCIBIOS_DEVICE_NOT_FOUND;

	data = iproc_pcie_cfg_retry(cfg_data_p);
	data = iproc_pcie_cfg_retry(pcie, cfg_data_p);

	*val = data;
	if (size <= 2)
@@ -936,9 +955,26 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr,
			resource_size_t window_size =
				ob_map->window_sizes[size_idx] * SZ_1M;

			if (size < window_size)
			/*
			 * Keep iterating until we reach the last window and
			 * with the minimal window size at index zero. In this
			 * case, we take a compromise by mapping it using the
			 * minimum window size that can be supported
			 */
			if (size < window_size) {
				if (size_idx > 0 || window_idx > 0)
					continue;

				/*
				 * For the corner case of reaching the minimal
				 * window size that can be supported on the
				 * last window
				 */
				axi_addr = ALIGN_DOWN(axi_addr, window_size);
				pci_addr = ALIGN_DOWN(pci_addr, window_size);
				size = window_size;
			}

			if (!IS_ALIGNED(axi_addr, window_size) ||
			    !IS_ALIGNED(pci_addr, window_size)) {
				dev_err(dev,
@@ -1347,7 +1383,6 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)
		break;
	case IPROC_PCIE_PAXB:
		regs = iproc_pcie_reg_paxb;
		pcie->iproc_cfg_read = true;
		pcie->has_apb_err_disable = true;
		if (pcie->need_ob_cfg) {
			pcie->ob_map = paxb_ob_map;
@@ -1356,6 +1391,7 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)
		break;
	case IPROC_PCIE_PAXB_V2:
		regs = iproc_pcie_reg_paxb_v2;
		pcie->iproc_cfg_read = true;
		pcie->has_apb_err_disable = true;
		if (pcie->need_ob_cfg) {
			pcie->ob_map = paxb_v2_ob_map;