* [U-Boot] [PATCH 2/2][V2] pci/layerscape: Add EP mode support
2015-07-10 3:35 [U-Boot] [PATCH 1/2][V2] pci: Add function to find an extended capability Minghuan Lian
@ 2015-07-10 3:35 ` Minghuan Lian
2015-08-04 15:55 ` York Sun
2015-07-10 8:38 ` [U-Boot] [PATCH 1/2][V2] pci: Add function to find an extended capability Bin Meng
2015-08-04 15:54 ` York Sun
2 siblings, 1 reply; 7+ messages in thread
From: Minghuan Lian @ 2015-07-10 3:35 UTC (permalink / raw)
To: u-boot
The patch will initialize PCIe controller on EP mode
1. Setup bar:
bar0 32bit 4K for specific configuration
bar1 32bit 8K for MSIX
bar2 64bit 4K for descriptor of memory
bar4 64bit 1M for DMA memory test
2. Setup iATU:
iATU inbound 0-3 to map bar transaction to memory address
started at CONFIG_SYS_PCI_EP_MEMORY_BASE
iATU outbound 0 to map 4G memory space
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
Change log:
v2-v1: no change
drivers/pci/pcie_layerscape.c | 137 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 135 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c
index 402c519..bf66225 100644
--- a/drivers/pci/pcie_layerscape.c
+++ b/drivers/pci/pcie_layerscape.c
@@ -24,6 +24,10 @@
#define CONFIG_SYS_PCI_MEMORY_SIZE (2 * 1024 * 1024 * 1024UL) /* 2G */
#endif
+#ifndef CONFIG_SYS_PCI_EP_MEMORY_BASE
+#define CONFIG_SYS_PCI_EP_MEMORY_BASE CONFIG_SYS_LOAD_ADDR
+#endif
+
/* iATU registers */
#define PCIE_ATU_VIEWPORT 0x900
#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
@@ -40,6 +44,7 @@
#define PCIE_ATU_CR2 0x908
#define PCIE_ATU_ENABLE (0x1 << 31)
#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
+#define PCIE_ATU_BAR_NUM(bar) ((bar) << 8)
#define PCIE_ATU_LOWER_BASE 0x90C
#define PCIE_ATU_UPPER_BASE 0x910
#define PCIE_ATU_LIMIT 0x914
@@ -51,6 +56,7 @@
/* LUT registers */
#define PCIE_LUT_BASE 0x80000
+#define PCIE_LUT_LCTRL0 0x7F8
#define PCIE_LUT_DBG 0x7FC
#define PCIE_DBI_RO_WR_EN 0x8bc
@@ -64,6 +70,25 @@
#define PCIE_DBI_SIZE 0x100000 /* 1M */
+#define PCIE_LCTRL0_CFG2_ENABLE (1 << 31)
+#define PCIE_LCTRL0_VF(vf) ((vf) << 22)
+#define PCIE_LCTRL0_PF(pf) ((pf) << 16)
+#define PCIE_LCTRL0_VF_ACTIVE (1 << 21)
+#define PCIE_LCTRL0_VAL(pf, vf) (PCIE_LCTRL0_PF(pf) | \
+ PCIE_LCTRL0_VF(vf) | \
+ ((vf) == 0 ? 0 : PCIE_LCTRL0_VF_ACTIVE) | \
+ PCIE_LCTRL0_CFG2_ENABLE)
+
+#define PCIE_NO_SRIOV_BAR_BASE 0x1000
+
+#define PCIE_PF_NUM 2
+#define PCIE_VF_NUM 64
+
+#define PCIE_BAR0_SIZE (4 * 1024) /* 4K */
+#define PCIE_BAR1_SIZE (8 * 1024) /* 8K for MSIX */
+#define PCIE_BAR2_SIZE (4 * 1024) /* 4K */
+#define PCIE_BAR4_SIZE (1 * 1024 * 1024) /* 1M */
+
struct ls_pcie {
int idx;
void __iomem *dbi;
@@ -75,6 +100,7 @@ struct ls_pcie {
struct ls_pcie_info {
unsigned long regs;
int pci_num;
+ u64 phys_base;
u64 cfg0_phys;
u64 cfg0_size;
u64 cfg1_phys;
@@ -90,6 +116,7 @@ struct ls_pcie_info {
#define SET_LS_PCIE_INFO(x, num) \
{ \
x.regs = CONFIG_SYS_PCIE##num##_ADDR; \
+ x.phys_base = CONFIG_SYS_PCIE##num##_PHYS_ADDR; \
x.cfg0_phys = CONFIG_SYS_PCIE_CFG0_PHYS_OFF + \
CONFIG_SYS_PCIE##num##_PHYS_ADDR; \
x.cfg0_size = CONFIG_SYS_PCIE_CFG0_SIZE; \
@@ -196,6 +223,18 @@ static void ls_pcie_iatu_outbound_set(struct ls_pcie *pcie, int idx, int type,
writel(PCIE_ATU_ENABLE, pcie->dbi + PCIE_ATU_CR2);
}
+/* Use bar match mode and MEM type as default */
+static void ls_pcie_iatu_inbound_set(struct ls_pcie *pcie, int idx,
+ int bar, u64 phys)
+{
+ writel(PCIE_ATU_REGION_INBOUND | idx, pcie->dbi + PCIE_ATU_VIEWPORT);
+ writel((u32)phys, pcie->dbi + PCIE_ATU_LOWER_TARGET);
+ writel(phys >> 32, pcie->dbi + PCIE_ATU_UPPER_TARGET);
+ writel(PCIE_ATU_TYPE_MEM, pcie->dbi + PCIE_ATU_CR1);
+ writel(PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE |
+ PCIE_ATU_BAR_NUM(bar), pcie->dbi + PCIE_ATU_CR2);
+}
+
static void ls_pcie_setup_atu(struct ls_pcie *pcie, struct ls_pcie_info *info)
{
#ifdef DEBUG
@@ -349,6 +388,97 @@ static void ls_pcie_setup_ctrl(struct ls_pcie *pcie,
#endif
}
+static void ls_pcie_ep_setup_atu(struct ls_pcie *pcie,
+ struct ls_pcie_info *info)
+{
+ u64 phys = CONFIG_SYS_PCI_EP_MEMORY_BASE;
+
+ /* ATU 0 : INBOUND : map BAR0 */
+ ls_pcie_iatu_inbound_set(pcie, PCIE_ATU_REGION_INDEX0, 0, phys);
+ /* ATU 1 : INBOUND : map BAR1 */
+ phys += PCIE_BAR1_SIZE;
+ ls_pcie_iatu_inbound_set(pcie, PCIE_ATU_REGION_INDEX1, 1, phys);
+ /* ATU 2 : INBOUND : map BAR2 */
+ phys += PCIE_BAR2_SIZE;
+ ls_pcie_iatu_inbound_set(pcie, PCIE_ATU_REGION_INDEX2, 2, phys);
+ /* ATU 3 : INBOUND : map BAR4 */
+ phys = CONFIG_SYS_PCI_EP_MEMORY_BASE + PCIE_BAR4_SIZE;
+ ls_pcie_iatu_inbound_set(pcie, PCIE_ATU_REGION_INDEX3, 4, phys);
+
+ /* ATU 0 : OUTBOUND : map 4G MEM */
+ ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX0,
+ PCIE_ATU_TYPE_MEM,
+ info->phys_base,
+ 0,
+ 4 * 1024 * 1024 * 1024ULL);
+}
+
+/* BAR0 and BAR1 are 32bit BAR2 and BAR4 are 64bit */
+static void ls_pcie_ep_setup_bar(void *bar_base, int bar, u32 size)
+{
+ if (size < 4 * 1024)
+ return;
+
+ switch (bar) {
+ case 0:
+ writel(size - 1, bar_base + PCI_BASE_ADDRESS_0);
+ break;
+ case 1:
+ writel(size - 1, bar_base + PCI_BASE_ADDRESS_1);
+ break;
+ case 2:
+ writel(size - 1, bar_base + PCI_BASE_ADDRESS_2);
+ writel(0, bar_base + PCI_BASE_ADDRESS_3);
+ break;
+ case 4:
+ writel(size - 1, bar_base + PCI_BASE_ADDRESS_4);
+ writel(0, bar_base + PCI_BASE_ADDRESS_5);
+ break;
+ default:
+ break;
+ }
+}
+
+static void ls_pcie_ep_setup_bars(void *bar_base)
+{
+ /* BAR0 - 32bit - 4K configuration */
+ ls_pcie_ep_setup_bar(bar_base, 0, PCIE_BAR0_SIZE);
+ /* BAR1 - 32bit - 8K MSIX*/
+ ls_pcie_ep_setup_bar(bar_base, 1, PCIE_BAR1_SIZE);
+ /* BAR2 - 64bit - 4K MEM desciptor */
+ ls_pcie_ep_setup_bar(bar_base, 2, PCIE_BAR2_SIZE);
+ /* BAR4 - 64bit - 1M MEM*/
+ ls_pcie_ep_setup_bar(bar_base, 4, PCIE_BAR4_SIZE);
+}
+
+static void ls_pcie_setup_ep(struct ls_pcie *pcie, struct ls_pcie_info *info)
+{
+ struct pci_controller *hose = &pcie->hose;
+ pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0);
+ int sriov;
+
+ sriov = pci_hose_find_ext_capability(hose, dev, PCI_EXT_CAP_ID_SRIOV);
+ if (sriov) {
+ int pf, vf;
+
+ for (pf = 0; pf < PCIE_PF_NUM; pf++) {
+ for (vf = 0; vf <= PCIE_VF_NUM; vf++) {
+ writel(PCIE_LCTRL0_VAL(pf, vf),
+ pcie->dbi + PCIE_LUT_BASE +
+ PCIE_LUT_LCTRL0);
+ ls_pcie_ep_setup_bars(pcie->dbi);
+ ls_pcie_ep_setup_atu(pcie, info);
+ }
+ }
+
+ /* Disable CFG2 */
+ writel(0, pcie->dbi + PCIE_LUT_BASE + PCIE_LUT_LCTRL0);
+ } else {
+ ls_pcie_ep_setup_bars(pcie->dbi + PCIE_NO_SRIOV_BAR_BASE);
+ ls_pcie_ep_setup_atu(pcie, info);
+ }
+}
+
int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
{
struct ls_pcie *pcie;
@@ -425,6 +555,11 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
printf("PCIe%u: %s ", info->pci_num,
ep_mode ? "Endpoint" : "Root Complex");
+ if (ep_mode)
+ ls_pcie_setup_ep(pcie, info);
+ else
+ ls_pcie_setup_ctrl(pcie, info);
+
linkup = ls_pcie_link_up(pcie);
if (!linkup) {
@@ -442,8 +577,6 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
if (ep_mode)
return busno;
- ls_pcie_setup_ctrl(pcie, info);
-
pci_register_hose(hose);
hose->last_busno = pci_hose_scan(hose);
--
1.9.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [U-Boot] [PATCH 1/2][V2] pci: Add function to find an extended capability
2015-07-10 3:35 [U-Boot] [PATCH 1/2][V2] pci: Add function to find an extended capability Minghuan Lian
2015-07-10 3:35 ` [U-Boot] [PATCH 2/2][V2] pci/layerscape: Add EP mode support Minghuan Lian
@ 2015-07-10 8:38 ` Bin Meng
2015-08-04 15:54 ` York Sun
2 siblings, 0 replies; 7+ messages in thread
From: Bin Meng @ 2015-07-10 8:38 UTC (permalink / raw)
To: u-boot
On Fri, Jul 10, 2015 at 11:35 AM, Minghuan Lian
<Minghuan.Lian@freescale.com> wrote:
> PCIe extends device's configuration space to 4k and provides
> extended capability. The patch adds function to find them.
> The code is ported from Linux PCIe driver.
>
> Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
> ---
> Change log:
> v2-v1:
> 1. add a descriptor of pci_find_next_ext_capability
> 2. fix a typo
>
> drivers/pci/pci.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/pci.h | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 94 insertions(+)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 157491c..df50b48 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -526,3 +526,56 @@ int pci_find_cap(struct pci_controller *hose, pci_dev_t dev, int pos, int cap)
> }
> return 0;
> }
> +
> +/**
> + * pci_find_next_ext_capability - Find an extended capability
> + *
> + * Returns the address of the next matching extended capability structure
> + * within the device's PCI configuration space or 0 if the device does
> + * not support it. Some capabilities can occur several times, e.g., the
> + * vendor-specific capability, and this provides a way to find them all.
> + */
> +int pci_find_next_ext_capability(struct pci_controller *hose, pci_dev_t dev,
> + int start, int cap)
> +{
> + u32 header;
> + int ttl, pos = PCI_CFG_SPACE_SIZE;
> +
> + /* minimum 8 bytes per capability */
> + ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
> +
> + if (start)
> + pos = start;
> +
> + pci_hose_read_config_dword(hose, dev, pos, &header);
> + if (header == 0xffffffff || header == 0)
> + return 0;
> +
> + while (ttl-- > 0) {
> + if (PCI_EXT_CAP_ID(header) == cap && pos != start)
> + return pos;
> +
> + pos = PCI_EXT_CAP_NEXT(header);
> + if (pos < PCI_CFG_SPACE_SIZE)
> + break;
> +
> + pci_hose_read_config_dword(hose, dev, pos, &header);
> + if (header == 0xffffffff || header == 0)
> + break;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * pci_hose_find_ext_capability - Find an extended capability
> + *
> + * Returns the address of the requested extended capability structure
> + * within the device's PCI configuration space or 0 if the device does
> + * not support it.
> + */
> +int pci_hose_find_ext_capability(struct pci_controller *hose, pci_dev_t dev,
> + int cap)
> +{
> + return pci_find_next_ext_capability(hose, dev, 0, cap);
> +}
> diff --git a/include/pci.h b/include/pci.h
> index 07b1e9a..2f88714 100644
> --- a/include/pci.h
> +++ b/include/pci.h
> @@ -11,6 +11,9 @@
> #ifndef _PCI_H
> #define _PCI_H
>
> +#define PCI_CFG_SPACE_SIZE 256
> +#define PCI_CFG_SPACE_EXP_SIZE 4096
> +
> /*
> * Under PCI, each device has 256 bytes of configuration address space,
> * of which the first 64 bytes are standardized as follows:
> @@ -413,6 +416,39 @@
> #define PCI_FIND_CAP_TTL 0x48
> #define CAP_START_POS 0x40
>
> +/* Extended Capabilities (PCI-X 2.0 and Express) */
> +#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
> +#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf)
> +#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc)
> +
> +#define PCI_EXT_CAP_ID_ERR 0x01 /* Advanced Error Reporting */
> +#define PCI_EXT_CAP_ID_VC 0x02 /* Virtual Channel Capability */
> +#define PCI_EXT_CAP_ID_DSN 0x03 /* Device Serial Number */
> +#define PCI_EXT_CAP_ID_PWR 0x04 /* Power Budgeting */
> +#define PCI_EXT_CAP_ID_RCLD 0x05 /* Root Complex Link Declaration */
> +#define PCI_EXT_CAP_ID_RCILC 0x06 /* Root Complex Internal Link Control */
> +#define PCI_EXT_CAP_ID_RCEC 0x07 /* Root Complex Event Collector */
> +#define PCI_EXT_CAP_ID_MFVC 0x08 /* Multi-Function VC Capability */
> +#define PCI_EXT_CAP_ID_VC9 0x09 /* same as _VC */
> +#define PCI_EXT_CAP_ID_RCRB 0x0A /* Root Complex RB? */
> +#define PCI_EXT_CAP_ID_VNDR 0x0B /* Vendor-Specific */
> +#define PCI_EXT_CAP_ID_CAC 0x0C /* Config Access - obsolete */
> +#define PCI_EXT_CAP_ID_ACS 0x0D /* Access Control Services */
> +#define PCI_EXT_CAP_ID_ARI 0x0E /* Alternate Routing ID */
> +#define PCI_EXT_CAP_ID_ATS 0x0F /* Address Translation Services */
> +#define PCI_EXT_CAP_ID_SRIOV 0x10 /* Single Root I/O Virtualization */
> +#define PCI_EXT_CAP_ID_MRIOV 0x11 /* Multi Root I/O Virtualization */
> +#define PCI_EXT_CAP_ID_MCAST 0x12 /* Multicast */
> +#define PCI_EXT_CAP_ID_PRI 0x13 /* Page Request Interface */
> +#define PCI_EXT_CAP_ID_AMD_XXX 0x14 /* Reserved for AMD */
> +#define PCI_EXT_CAP_ID_REBAR 0x15 /* Resizable BAR */
> +#define PCI_EXT_CAP_ID_DPA 0x16 /* Dynamic Power Allocation */
> +#define PCI_EXT_CAP_ID_TPH 0x17 /* TPH Requester */
> +#define PCI_EXT_CAP_ID_LTR 0x18 /* Latency Tolerance Reporting */
> +#define PCI_EXT_CAP_ID_SECPCI 0x19 /* Secondary PCIe Capability */
> +#define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */
> +#define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */
> +
> /* Include the ID list */
>
> #include <pci_ids.h>
> @@ -674,6 +710,11 @@ extern int pci_hose_find_cap_start(struct pci_controller *hose, pci_dev_t dev,
> extern int pci_find_cap(struct pci_controller *hose, pci_dev_t dev, int pos,
> int cap);
>
> +int pci_find_next_ext_capability(struct pci_controller *hose,
> + pci_dev_t dev, int start, int cap);
> +int pci_hose_find_ext_capability(struct pci_controller *hose,
> + pci_dev_t dev, int cap);
> +
> #ifdef CONFIG_PCI_FIXUP_DEV
> extern void board_pci_fixup_dev(struct pci_controller *hose, pci_dev_t dev,
> unsigned short vendor,
> --
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
^ permalink raw reply [flat|nested] 7+ messages in thread