Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7c44527 authored by Ray Jui's avatar Ray Jui Committed by Bjorn Helgaas
Browse files

PCI: iproc: Add support for the next-gen PAXB controller



Add support for the next generation of the iProc PAXB host controller, used
in Stingray.

Signed-off-by: default avatarOza Oza <oza.oza@broadcom.com>
Signed-off-by: default avatarRay Jui <ray.jui@broadcom.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarScott Branden <scott.branden@broadcom.com>
parent f7acf811
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@ static const struct of_device_id iproc_pcie_of_match_table[] = {
	{
		.compatible = "brcm,iproc-pcie",
		.data = (int *)IPROC_PCIE_PAXB,
	}, {
		.compatible = "brcm,iproc-pcie-paxb-v2",
		.data = (int *)IPROC_PCIE_PAXB_V2,
	}, {
		.compatible = "brcm,iproc-pcie-paxc",
		.data = (int *)IPROC_PCIE_PAXC,
+128 −0
Original line number Diff line number Diff line
@@ -118,6 +118,29 @@ static const struct iproc_pcie_ob_map paxb_ob_map[] = {
	},
};

static const struct iproc_pcie_ob_map paxb_v2_ob_map[] = {
	{
		/* OARR0/OMAP0 */
		.window_sizes = { 128, 256 },
		.nr_sizes = 2,
	},
	{
		/* OARR1/OMAP1 */
		.window_sizes = { 128, 256 },
		.nr_sizes = 2,
	},
	{
		/* OARR2/OMAP2 */
		.window_sizes = { 128, 256, 512, 1024 },
		.nr_sizes = 4,
	},
	{
		/* OARR3/OMAP3 */
		.window_sizes = { 128, 256, 512, 1024 },
		.nr_sizes = 4,
	},
};

/**
 * iProc PCIe inbound mapping type
 */
@@ -156,6 +179,54 @@ struct iproc_pcie_ib_map {
	u16 imap_window_offset;
};

static const struct iproc_pcie_ib_map paxb_v2_ib_map[] = {
	{
		/* IARR0/IMAP0 */
		.type = IPROC_PCIE_IB_MAP_IO,
		.size_unit = SZ_1K,
		.region_sizes = { 32 },
		.nr_sizes = 1,
		.nr_windows = 8,
		.imap_addr_offset = 0x40,
		.imap_window_offset = 0x4,
	},
	{
		/* IARR1/IMAP1 (currently unused) */
		.type = IPROC_PCIE_IB_MAP_INVALID,
	},
	{
		/* IARR2/IMAP2 */
		.type = IPROC_PCIE_IB_MAP_MEM,
		.size_unit = SZ_1M,
		.region_sizes = { 64, 128, 256, 512, 1024, 2048, 4096, 8192,
				  16384 },
		.nr_sizes = 9,
		.nr_windows = 1,
		.imap_addr_offset = 0x4,
		.imap_window_offset = 0x8,
	},
	{
		/* IARR3/IMAP3 */
		.type = IPROC_PCIE_IB_MAP_MEM,
		.size_unit = SZ_1G,
		.region_sizes = { 1, 2, 4, 8, 16, 32 },
		.nr_sizes = 6,
		.nr_windows = 8,
		.imap_addr_offset = 0x4,
		.imap_window_offset = 0x8,
	},
	{
		/* IARR4/IMAP4 */
		.type = IPROC_PCIE_IB_MAP_MEM,
		.size_unit = SZ_1G,
		.region_sizes = { 32, 64, 128, 256, 512 },
		.nr_sizes = 5,
		.nr_windows = 8,
		.imap_addr_offset = 0x4,
		.imap_window_offset = 0x8,
	},
};

/*
 * iProc PCIe host registers
 */
@@ -258,6 +329,34 @@ static const u16 iproc_pcie_reg_paxb[] = {
	[IPROC_PCIE_APB_ERR_EN]       = 0xf40,
};

/* iProc PCIe PAXB v2 registers */
static const u16 iproc_pcie_reg_paxb_v2[] = {
	[IPROC_PCIE_CLK_CTRL]         = 0x000,
	[IPROC_PCIE_CFG_IND_ADDR]     = 0x120,
	[IPROC_PCIE_CFG_IND_DATA]     = 0x124,
	[IPROC_PCIE_CFG_ADDR]         = 0x1f8,
	[IPROC_PCIE_CFG_DATA]         = 0x1fc,
	[IPROC_PCIE_INTX_EN]          = 0x330,
	[IPROC_PCIE_OARR0]            = 0xd20,
	[IPROC_PCIE_OMAP0]            = 0xd40,
	[IPROC_PCIE_OARR1]            = 0xd28,
	[IPROC_PCIE_OMAP1]            = 0xd48,
	[IPROC_PCIE_OARR2]            = 0xd60,
	[IPROC_PCIE_OMAP2]            = 0xd68,
	[IPROC_PCIE_OARR3]            = 0xdf0,
	[IPROC_PCIE_OMAP3]            = 0xdf8,
	[IPROC_PCIE_IARR0]            = 0xd00,
	[IPROC_PCIE_IMAP0]            = 0xc00,
	[IPROC_PCIE_IARR2]            = 0xd10,
	[IPROC_PCIE_IMAP2]            = 0xcc0,
	[IPROC_PCIE_IARR3]            = 0xe00,
	[IPROC_PCIE_IMAP3]            = 0xe08,
	[IPROC_PCIE_IARR4]            = 0xe68,
	[IPROC_PCIE_IMAP4]            = 0xe70,
	[IPROC_PCIE_LINK_STATUS]      = 0xf0c,
	[IPROC_PCIE_APB_ERR_EN]       = 0xf40,
};

/* iProc PCIe PAXC v1 registers */
static const u16 iproc_pcie_reg_paxc[] = {
	[IPROC_PCIE_CLK_CTRL]         = 0x000,
@@ -914,6 +1013,19 @@ static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
	return 0;
}

static int iproc_pcie_paxb_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr)
{
	int ret;
	struct of_pci_range range;

	memset(&range, 0, sizeof(range));
	range.size = SZ_32K;
	range.pci_addr = range.cpu_addr = ALIGN(msi_addr, range.size);

	ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_IO);
	return ret;
}

static void iproc_pcie_paxc_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr)
{
	u32 val;
@@ -965,6 +1077,11 @@ static int iproc_pcie_msi_steer(struct iproc_pcie *pcie,
	}

	switch (pcie->type) {
	case IPROC_PCIE_PAXB_V2:
		ret = iproc_pcie_paxb_v2_msi_steer(pcie, msi_addr);
		if (ret)
			return ret;
		break;
	case IPROC_PCIE_PAXC_V2:
		iproc_pcie_paxc_v2_msi_steer(pcie, msi_addr);
		break;
@@ -1042,6 +1159,17 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)
			pcie->ob.nr_windows = ARRAY_SIZE(paxb_ob_map);
		}
		break;
	case IPROC_PCIE_PAXB_V2:
		regs = iproc_pcie_reg_paxb_v2;
		pcie->has_apb_err_disable = true;
		if (pcie->need_ob_cfg) {
			pcie->ob_map = paxb_v2_ob_map;
			pcie->ob.nr_windows = ARRAY_SIZE(paxb_v2_ob_map);
		}
		pcie->ib.nr_regions = ARRAY_SIZE(paxb_v2_ib_map);
		pcie->ib_map = paxb_v2_ib_map;
		pcie->need_msi_steer = true;
		break;
	case IPROC_PCIE_PAXC:
		regs = iproc_pcie_reg_paxc;
		pcie->ep_is_internal = true;
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
enum iproc_pcie_type {
	IPROC_PCIE_PAXB_BCMA = 0,
	IPROC_PCIE_PAXB,
	IPROC_PCIE_PAXB_V2,
	IPROC_PCIE_PAXC,
	IPROC_PCIE_PAXC_V2,
};