* i.MX6 PCI support
@ 2015-03-17 6:38 Sascha Hauer
2015-03-17 6:38 ` [PATCH 1/7] pci: Use standard pr_debug Sascha Hauer
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Sascha Hauer @ 2015-03-17 6:38 UTC (permalink / raw)
To: Barebox List
The following series adds PCIe support for i.MX6. Some PCI cleanup
patches are needed, then the designware PCIe driver from the kernel,
the i.MX6 PCIe driver, also from the kernel and finally the needed
clocks for the PCIe controller.
Sascha
----------------------------------------------------------------
Sascha Hauer (7):
pci: Use standard pr_debug
pci: fix copy-paste bug
pci: pci_regs.h: Sync with Linux
pci: Add pcie-designware driver
ARM: i.MX: Add imx_clk_gate_exclusive
ARM: i.MX6: Add PCI clocks
pci: Add i.MX6 pcie support
arch/arm/mach-imx/Kconfig | 1 +
arch/arm/mach-imx/Makefile | 2 +-
arch/arm/mach-imx/clk-gate-exclusive.c | 103 +++++
arch/arm/mach-imx/clk-imx6.c | 29 ++
arch/arm/mach-imx/clk.h | 3 +
drivers/pci/Kconfig | 10 +
drivers/pci/Makefile | 2 +
drivers/pci/pci-imx6.c | 612 ++++++++++++++++++++++++++
drivers/pci/pci.c | 36 +-
drivers/pci/pcie-designware.c | 564 ++++++++++++++++++++++++
drivers/pci/pcie-designware.h | 71 +++
include/linux/pci_regs.h | 769 +++++++++++++++++++++++++++++++++
include/mfd/imx6q-iomuxc-gpr.h | 8 +
13 files changed, 2189 insertions(+), 21 deletions(-)
create mode 100644 arch/arm/mach-imx/clk-gate-exclusive.c
create mode 100644 drivers/pci/pci-imx6.c
create mode 100644 drivers/pci/pcie-designware.c
create mode 100644 drivers/pci/pcie-designware.h
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/7] pci: Use standard pr_debug
2015-03-17 6:38 i.MX6 PCI support Sascha Hauer
@ 2015-03-17 6:38 ` Sascha Hauer
2015-03-18 9:08 ` Jean-Christophe PLAGNIOL-VILLARD
2015-03-17 6:38 ` [PATCH 2/7] pci: fix copy-paste bug Sascha Hauer
` (5 subsequent siblings)
6 siblings, 1 reply; 9+ messages in thread
From: Sascha Hauer @ 2015-03-17 6:38 UTC (permalink / raw)
To: Barebox List
Use pr_debug instead of custom DBG macro.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pci.c | 34 +++++++++++++++-------------------
1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1f5dc78..cb8c539 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1,13 +1,9 @@
+#define pr_fmt(fmt) "pci: " fmt
+
#include <common.h>
#include <linux/sizes.h>
#include <linux/pci.h>
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
static struct pci_controller *hose_head, **hose_tail = &hose_head;
LIST_HEAD(pci_root_buses);
@@ -150,16 +146,16 @@ static void setup_device(struct pci_dev *dev, int max_bar)
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &mask);
if (mask == 0 || mask == 0xffffffff) {
- DBG(" PCI: pbar%d set bad mask\n", bar);
+ pr_debug("pbar%d set bad mask\n", bar);
continue;
}
if (mask & 0x01) { /* IO */
size = ((~(mask & 0xfffffffe)) & 0xffff) + 1;
- DBG(" PCI: pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
+ pr_debug("pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
if (last_io + size >
dev->bus->resource[PCI_BUS_RESOURCE_IO]->end) {
- DBG("BAR does not fit within bus IO res\n");
+ pr_debug("BAR does not fit within bus IO res\n");
return;
}
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
@@ -169,11 +165,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
} else if ((mask & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
last_mem_pref) /* prefetchable MEM */ {
size = (~(mask & 0xfffffff0)) + 1;
- DBG(" PCI: pbar%d: mask=%08x P memory %d bytes\n",
+ pr_debug("pbar%d: mask=%08x P memory %d bytes\n",
bar, mask, size);
if (last_mem_pref + size >
dev->bus->resource[PCI_BUS_RESOURCE_MEM_PREF]->end) {
- DBG("BAR does not fit within bus p-mem res\n");
+ pr_debug("BAR does not fit within bus p-mem res\n");
return;
}
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem_pref);
@@ -183,11 +179,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
last_mem_pref += size;
} else { /* non-prefetch MEM */
size = (~(mask & 0xfffffff0)) + 1;
- DBG(" PCI: pbar%d: mask=%08x NP memory %d bytes\n",
+ pr_debug("pbar%d: mask=%08x NP memory %d bytes\n",
bar, mask, size);
if (last_mem + size >
dev->bus->resource[PCI_BUS_RESOURCE_MEM]->end) {
- DBG("BAR does not fit within bus np-mem res\n");
+ pr_debug("BAR does not fit within bus np-mem res\n");
return;
}
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
@@ -287,8 +283,8 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
unsigned int devfn, l, max, class;
unsigned char cmd, tmp, hdr_type, is_multi = 0;
- DBG("pci_scan_bus for bus %d\n", bus->number);
- DBG(" last_io = 0x%08x, last_mem = 0x%08x, last_mem_pref = 0x%08x\n",
+ pr_debug("pci_scan_bus for bus %d\n", bus->number);
+ pr_debug(" last_io = 0x%08x, last_mem = 0x%08x, last_mem_pref = 0x%08x\n",
last_io, last_mem, last_mem_pref);
max = bus->secondary;
@@ -331,8 +327,8 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
class >>= 8;
dev->hdr_type = hdr_type;
- DBG("PCI: class = %08x, hdr_type = %08x\n", class, hdr_type);
- DBG("PCI: %02x:%02x [%04x:%04x]\n", bus->number, dev->devfn,
+ pr_debug("class = %08x, hdr_type = %08x\n", class, hdr_type);
+ pr_debug("%02x:%02x [%04x:%04x]\n", bus->number, dev->devfn,
dev->vendor, dev->device);
switch (hdr_type & 0x7f) {
@@ -385,7 +381,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
}
if (class == PCI_CLASS_BRIDGE_HOST) {
- DBG("PCI: skip pci host bridge\n");
+ pr_debug("skip pci host bridge\n");
continue;
}
}
@@ -398,7 +394,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
* Return how far we've got finding sub-buses.
*/
max = bus_index;
- DBG("PCI: pci_scan_bus returning with max=%02x\n", max);
+ pr_debug("pci_scan_bus returning with max=%02x\n", max);
return max;
}
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/7] pci: fix copy-paste bug
2015-03-17 6:38 i.MX6 PCI support Sascha Hauer
2015-03-17 6:38 ` [PATCH 1/7] pci: Use standard pr_debug Sascha Hauer
@ 2015-03-17 6:38 ` Sascha Hauer
2015-03-17 6:38 ` [PATCH 3/7] pci: pci_regs.h: Sync with Linux Sascha Hauer
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2015-03-17 6:38 UTC (permalink / raw)
To: Barebox List
Test for the correct resource before derefencing it.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/pci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index cb8c539..d6e95c3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -53,7 +53,7 @@ void register_pci_controller(struct pci_controller *hose)
else
last_mem = 0;
- if (bus->resource[PCI_BUS_RESOURCE_MEM])
+ if (bus->resource[PCI_BUS_RESOURCE_MEM_PREF])
last_mem_pref = bus->resource[PCI_BUS_RESOURCE_MEM_PREF]->start;
else
last_mem_pref = 0;
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/7] pci: pci_regs.h: Sync with Linux
2015-03-17 6:38 i.MX6 PCI support Sascha Hauer
2015-03-17 6:38 ` [PATCH 1/7] pci: Use standard pr_debug Sascha Hauer
2015-03-17 6:38 ` [PATCH 2/7] pci: fix copy-paste bug Sascha Hauer
@ 2015-03-17 6:38 ` Sascha Hauer
2015-03-17 6:38 ` [PATCH 4/7] pci: Add pcie-designware driver Sascha Hauer
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2015-03-17 6:38 UTC (permalink / raw)
To: Barebox List
Sync the pci register definitions with Linux 4.0-rc1. Some are needed
for the upcoming designware pcie driver.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
include/linux/pci_regs.h | 769 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 769 insertions(+)
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index 8669fc7..efe3443 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -26,6 +26,7 @@
* Under PCI, each device has 256 bytes of configuration address space,
* of which the first 64 bytes are standardized as follows:
*/
+#define PCI_STD_HEADER_SIZEOF 64
#define PCI_VENDOR_ID 0x00 /* 16 bits */
#define PCI_DEVICE_ID 0x02 /* 16 bits */
#define PCI_COMMAND 0x04 /* 16 bits */
@@ -107,6 +108,14 @@
#define PCI_ROM_ADDRESS_ENABLE 0x01
#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
+#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
+#define PCI_MIN_GNT 0x3e /* 8 bits */
+#define PCI_MAX_LAT 0x3f /* 8 bits */
+
/* Header type 1 (PCI-to-PCI bridges) */
#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
@@ -134,5 +143,765 @@
#define PCI_PREF_LIMIT_UPPER32 0x2c
#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
#define PCI_IO_LIMIT_UPPER16 0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL 0x3e
+#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
+#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
+#define PCI_BRIDGE_CTL_ISA 0x04 /* Enable ISA mode */
+#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
+#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
+#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+#define PCI_CB_CAPABILITY_LIST 0x14
+/* 0x15 reserved */
+#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */
+#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */
+#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0 0x1c
+#define PCI_CB_MEMORY_LIMIT_0 0x20
+#define PCI_CB_MEMORY_BASE_1 0x24
+#define PCI_CB_MEMORY_LIMIT_1 0x28
+#define PCI_CB_IO_BASE_0 0x2c
+#define PCI_CB_IO_BASE_0_HI 0x2e
+#define PCI_CB_IO_LIMIT_0 0x30
+#define PCI_CB_IO_LIMIT_0_HI 0x32
+#define PCI_CB_IO_BASE_1 0x34
+#define PCI_CB_IO_BASE_1_HI 0x36
+#define PCI_CB_IO_LIMIT_1 0x38
+#define PCI_CB_IO_LIMIT_1_HI 0x3a
+#define PCI_CB_IO_RANGE_MASK (~0x03UL)
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL 0x3e
+#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */
+#define PCI_CB_BRIDGE_CTL_SERR 0x02
+#define PCI_CB_BRIDGE_CTL_ISA 0x04
+#define PCI_CB_BRIDGE_CTL_VGA 0x08
+#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
+#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */
+#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID 0x42
+#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID 0 /* Capability ID */
+#define PCI_CAP_ID_PM 0x01 /* Power Management */
+#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
+#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
+#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
+#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
+#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+#define PCI_CAP_ID_HT 0x08 /* HyperTransport */
+#define PCI_CAP_ID_VNDR 0x09 /* Vendor-Specific */
+#define PCI_CAP_ID_DBG 0x0A /* Debug port */
+#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */
+#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */
+#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */
+#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */
+#define PCI_CAP_ID_SECDEV 0x0F /* Secure Device */
+#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
+#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
+#define PCI_CAP_ID_SATA 0x12 /* SATA Data/Index Conf. */
+#define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */
+#define PCI_CAP_ID_MAX PCI_CAP_ID_AF
+#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
+#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF 4
+
+/* Power Management Registers */
+
+#define PCI_PM_PMC 2 /* PM Capabilities Register */
+#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */
+#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
+#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
+#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
+#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxiliary power support mask */
+#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
+#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
+#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
+#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
+#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
+#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
+#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
+#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
+#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
+#define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */
+#define PCI_PM_CTRL 4 /* PM control and status register */
+#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
+#define PCI_PM_CTRL_NO_SOFT_RESET 0x0008 /* No reset for D3hot->D0 */
+#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
+#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
+#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
+#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */
+#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */
+#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */
+#define PCI_PM_DATA_REGISTER 7 /* (??) */
+#define PCI_PM_SIZEOF 8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION 2 /* BCD version number */
+#define PCI_AGP_RFU 3 /* Rest of capability flags */
+#define PCI_AGP_STATUS 4 /* Status register */
+#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
+#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */
+#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */
+#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */
+#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */
+#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */
+#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */
+#define PCI_AGP_COMMAND 8 /* Control register */
+#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */
+#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */
+#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */
+#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */
+#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */
+#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */
+#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */
+#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */
+#define PCI_AGP_SIZEOF 12
+
+/* Vital Product Data */
+
+#define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */
+#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */
+#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */
+#define PCI_VPD_DATA 4 /* 32-bits of data returned here */
+#define PCI_CAP_VPD_SIZEOF 8
+
+/* Slot Identification */
+
+#define PCI_SID_ESR 2 /* Expansion Slot Register */
+#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
+#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS 2 /* Message Control */
+#define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */
+#define PCI_MSI_FLAGS_QMASK 0x000e /* Maximum queue size available */
+#define PCI_MSI_FLAGS_QSIZE 0x0070 /* Message queue size configured */
+#define PCI_MSI_FLAGS_64BIT 0x0080 /* 64-bit addresses allowed */
+#define PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking capable */
+#define PCI_MSI_RFU 3 /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */
+#define PCI_MSI_PENDING_32 16 /* Pending intrs for 32-bit devices */
+#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
+#define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */
+#define PCI_MSI_PENDING_64 20 /* Pending intrs for 64-bit devices */
+
+/* MSI-X registers */
+#define PCI_MSIX_FLAGS 2 /* Message Control */
+#define PCI_MSIX_FLAGS_QSIZE 0x07FF /* Table size */
+#define PCI_MSIX_FLAGS_MASKALL 0x4000 /* Mask all vectors for this function */
+#define PCI_MSIX_FLAGS_ENABLE 0x8000 /* MSI-X enable */
+#define PCI_MSIX_TABLE 4 /* Table offset */
+#define PCI_MSIX_TABLE_BIR 0x00000007 /* BAR index */
+#define PCI_MSIX_TABLE_OFFSET 0xfffffff8 /* Offset into specified BAR */
+#define PCI_MSIX_PBA 8 /* Pending Bit Array offset */
+#define PCI_MSIX_PBA_BIR 0x00000007 /* BAR index */
+#define PCI_MSIX_PBA_OFFSET 0xfffffff8 /* Offset into specified BAR */
+#define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */
+
+/* MSI-X Table entry format */
+#define PCI_MSIX_ENTRY_SIZE 16
+#define PCI_MSIX_ENTRY_LOWER_ADDR 0
+#define PCI_MSIX_ENTRY_UPPER_ADDR 4
+#define PCI_MSIX_ENTRY_DATA 8
+#define PCI_MSIX_ENTRY_VECTOR_CTRL 12
+#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1
+
+/* CompactPCI Hotswap Register */
+
+#define PCI_CHSWP_CSR 2 /* Control and Status Register */
+#define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */
+#define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */
+#define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */
+#define PCI_CHSWP_LOO 0x08 /* LED On / Off */
+#define PCI_CHSWP_PI 0x30 /* Programming Interface */
+#define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */
+#define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */
+
+/* PCI Advanced Feature registers */
+
+#define PCI_AF_LENGTH 2
+#define PCI_AF_CAP 3
+#define PCI_AF_CAP_TP 0x01
+#define PCI_AF_CAP_FLR 0x02
+#define PCI_AF_CTRL 4
+#define PCI_AF_CTRL_FLR 0x01
+#define PCI_AF_STATUS 5
+#define PCI_AF_STATUS_TP 0x01
+#define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */
+
+/* PCI-X registers (Type 0 (non-bridge) devices) */
+
+#define PCI_X_CMD 2 /* Modes & Features */
+#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
+#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
+#define PCI_X_CMD_READ_512 0x0000 /* 512 byte maximum read byte count */
+#define PCI_X_CMD_READ_1K 0x0004 /* 1Kbyte maximum read byte count */
+#define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */
+#define PCI_X_CMD_READ_4K 0x000c /* 4Kbyte maximum read byte count */
+#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */
+ /* Max # of outstanding split transactions */
+#define PCI_X_CMD_SPLIT_1 0x0000 /* Max 1 */
+#define PCI_X_CMD_SPLIT_2 0x0010 /* Max 2 */
+#define PCI_X_CMD_SPLIT_3 0x0020 /* Max 3 */
+#define PCI_X_CMD_SPLIT_4 0x0030 /* Max 4 */
+#define PCI_X_CMD_SPLIT_8 0x0040 /* Max 8 */
+#define PCI_X_CMD_SPLIT_12 0x0050 /* Max 12 */
+#define PCI_X_CMD_SPLIT_16 0x0060 /* Max 16 */
+#define PCI_X_CMD_SPLIT_32 0x0070 /* Max 32 */
+#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */
+#define PCI_X_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */
+#define PCI_X_STATUS 4 /* PCI-X capabilities */
+#define PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */
+#define PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */
+#define PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */
+#define PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */
+#define PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */
+#define PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */
+#define PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity */
+#define PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */
+#define PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */
+#define PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */
+#define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */
+#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */
+#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */
+#define PCI_X_ECC_CSR 8 /* ECC control and status */
+#define PCI_CAP_PCIX_SIZEOF_V0 8 /* size of registers for Version 0 */
+#define PCI_CAP_PCIX_SIZEOF_V1 24 /* size for Version 1 */
+#define PCI_CAP_PCIX_SIZEOF_V2 PCI_CAP_PCIX_SIZEOF_V1 /* Same for v2 */
+
+/* PCI-X registers (Type 1 (bridge) devices) */
+
+#define PCI_X_BRIDGE_SSTATUS 2 /* Secondary Status */
+#define PCI_X_SSTATUS_64BIT 0x0001 /* Secondary AD interface is 64 bits */
+#define PCI_X_SSTATUS_133MHZ 0x0002 /* 133 MHz capable */
+#define PCI_X_SSTATUS_FREQ 0x03c0 /* Secondary Bus Mode and Frequency */
+#define PCI_X_SSTATUS_VERS 0x3000 /* PCI-X Capability Version */
+#define PCI_X_SSTATUS_V1 0x1000 /* Mode 2, not Mode 1 */
+#define PCI_X_SSTATUS_V2 0x2000 /* Mode 1 or Modes 1 and 2 */
+#define PCI_X_SSTATUS_266MHZ 0x4000 /* 266 MHz capable */
+#define PCI_X_SSTATUS_533MHZ 0x8000 /* 533 MHz capable */
+#define PCI_X_BRIDGE_STATUS 4 /* Bridge Status */
+
+/* PCI Bridge Subsystem ID registers */
+
+#define PCI_SSVID_VENDOR_ID 4 /* PCI Bridge subsystem vendor ID */
+#define PCI_SSVID_DEVICE_ID 6 /* PCI Bridge subsystem device ID */
+
+/* PCI Express capability registers */
+
+#define PCI_EXP_FLAGS 2 /* Capabilities register */
+#define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */
+#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */
+#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */
+#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */
+#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */
+#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */
+#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
+#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCIe to PCI/PCI-X Bridge */
+#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIe Bridge */
+#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */
+#define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */
+#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
+#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
+#define PCI_EXP_DEVCAP 4 /* Device capabilities */
+#define PCI_EXP_DEVCAP_PAYLOAD 0x00000007 /* Max_Payload_Size */
+#define PCI_EXP_DEVCAP_PHANTOM 0x00000018 /* Phantom functions */
+#define PCI_EXP_DEVCAP_EXT_TAG 0x00000020 /* Extended tags */
+#define PCI_EXP_DEVCAP_L0S 0x000001c0 /* L0s Acceptable Latency */
+#define PCI_EXP_DEVCAP_L1 0x00000e00 /* L1 Acceptable Latency */
+#define PCI_EXP_DEVCAP_ATN_BUT 0x00001000 /* Attention Button Present */
+#define PCI_EXP_DEVCAP_ATN_IND 0x00002000 /* Attention Indicator Present */
+#define PCI_EXP_DEVCAP_PWR_IND 0x00004000 /* Power Indicator Present */
+#define PCI_EXP_DEVCAP_RBER 0x00008000 /* Role-Based Error Reporting */
+#define PCI_EXP_DEVCAP_PWR_VAL 0x03fc0000 /* Slot Power Limit Value */
+#define PCI_EXP_DEVCAP_PWR_SCL 0x0c000000 /* Slot Power Limit Scale */
+#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */
+#define PCI_EXP_DEVCTL 8 /* Device Control */
+#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */
+#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */
+#define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */
+#define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */
+#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
+#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
+#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */
+#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */
+#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */
+#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
+#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
+#define PCI_EXP_DEVCTL_READRQ_128B 0x0000 /* 128 Bytes */
+#define PCI_EXP_DEVCTL_READRQ_256B 0x1000 /* 256 Bytes */
+#define PCI_EXP_DEVCTL_READRQ_512B 0x2000 /* 512 Bytes */
+#define PCI_EXP_DEVCTL_READRQ_1024B 0x3000 /* 1024 Bytes */
+#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */
+#define PCI_EXP_DEVSTA 10 /* Device Status */
+#define PCI_EXP_DEVSTA_CED 0x0001 /* Correctable Error Detected */
+#define PCI_EXP_DEVSTA_NFED 0x0002 /* Non-Fatal Error Detected */
+#define PCI_EXP_DEVSTA_FED 0x0004 /* Fatal Error Detected */
+#define PCI_EXP_DEVSTA_URD 0x0008 /* Unsupported Request Detected */
+#define PCI_EXP_DEVSTA_AUXPD 0x0010 /* AUX Power Detected */
+#define PCI_EXP_DEVSTA_TRPND 0x0020 /* Transactions Pending */
+#define PCI_EXP_LNKCAP 12 /* Link Capabilities */
+#define PCI_EXP_LNKCAP_SLS 0x0000000f /* Supported Link Speeds */
+#define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */
+#define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */
+#define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */
+#define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */
+#define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */
+#define PCI_EXP_LNKCAP_L1EL 0x00038000 /* L1 Exit Latency */
+#define PCI_EXP_LNKCAP_CLKPM 0x00040000 /* Clock Power Management */
+#define PCI_EXP_LNKCAP_SDERC 0x00080000 /* Surprise Down Error Reporting Capable */
+#define PCI_EXP_LNKCAP_DLLLARC 0x00100000 /* Data Link Layer Link Active Reporting Capable */
+#define PCI_EXP_LNKCAP_LBNC 0x00200000 /* Link Bandwidth Notification Capability */
+#define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */
+#define PCI_EXP_LNKCTL 16 /* Link Control */
+#define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */
+#define PCI_EXP_LNKCTL_ASPM_L0S 0x0001 /* L0s Enable */
+#define PCI_EXP_LNKCTL_ASPM_L1 0x0002 /* L1 Enable */
+#define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */
+#define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */
+#define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */
+#define PCI_EXP_LNKCTL_CCC 0x0040 /* Common Clock Configuration */
+#define PCI_EXP_LNKCTL_ES 0x0080 /* Extended Synch */
+#define PCI_EXP_LNKCTL_CLKREQ_EN 0x0100 /* Enable clkreq */
+#define PCI_EXP_LNKCTL_HAWD 0x0200 /* Hardware Autonomous Width Disable */
+#define PCI_EXP_LNKCTL_LBMIE 0x0400 /* Link Bandwidth Management Interrupt Enable */
+#define PCI_EXP_LNKCTL_LABIE 0x0800 /* Link Autonomous Bandwidth Interrupt Enable */
+#define PCI_EXP_LNKSTA 18 /* Link Status */
+#define PCI_EXP_LNKSTA_CLS 0x000f /* Current Link Speed */
+#define PCI_EXP_LNKSTA_CLS_2_5GB 0x0001 /* Current Link Speed 2.5GT/s */
+#define PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */
+#define PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */
+#define PCI_EXP_LNKSTA_NLW 0x03f0 /* Negotiated Link Width */
+#define PCI_EXP_LNKSTA_NLW_X1 0x0010 /* Current Link Width x1 */
+#define PCI_EXP_LNKSTA_NLW_X2 0x0020 /* Current Link Width x2 */
+#define PCI_EXP_LNKSTA_NLW_X4 0x0040 /* Current Link Width x4 */
+#define PCI_EXP_LNKSTA_NLW_X8 0x0080 /* Current Link Width x8 */
+#define PCI_EXP_LNKSTA_NLW_SHIFT 4 /* start of NLW mask in link status */
+#define PCI_EXP_LNKSTA_LT 0x0800 /* Link Training */
+#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
+#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */
+#define PCI_EXP_LNKSTA_LBMS 0x4000 /* Link Bandwidth Management Status */
+#define PCI_EXP_LNKSTA_LABS 0x8000 /* Link Autonomous Bandwidth Status */
+#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V1 20 /* v1 endpoints end here */
+#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
+#define PCI_EXP_SLTCAP_ABP 0x00000001 /* Attention Button Present */
+#define PCI_EXP_SLTCAP_PCP 0x00000002 /* Power Controller Present */
+#define PCI_EXP_SLTCAP_MRLSP 0x00000004 /* MRL Sensor Present */
+#define PCI_EXP_SLTCAP_AIP 0x00000008 /* Attention Indicator Present */
+#define PCI_EXP_SLTCAP_PIP 0x00000010 /* Power Indicator Present */
+#define PCI_EXP_SLTCAP_HPS 0x00000020 /* Hot-Plug Surprise */
+#define PCI_EXP_SLTCAP_HPC 0x00000040 /* Hot-Plug Capable */
+#define PCI_EXP_SLTCAP_SPLV 0x00007f80 /* Slot Power Limit Value */
+#define PCI_EXP_SLTCAP_SPLS 0x00018000 /* Slot Power Limit Scale */
+#define PCI_EXP_SLTCAP_EIP 0x00020000 /* Electromechanical Interlock Present */
+#define PCI_EXP_SLTCAP_NCCS 0x00040000 /* No Command Completed Support */
+#define PCI_EXP_SLTCAP_PSN 0xfff80000 /* Physical Slot Number */
+#define PCI_EXP_SLTCTL 24 /* Slot Control */
+#define PCI_EXP_SLTCTL_ABPE 0x0001 /* Attention Button Pressed Enable */
+#define PCI_EXP_SLTCTL_PFDE 0x0002 /* Power Fault Detected Enable */
+#define PCI_EXP_SLTCTL_MRLSCE 0x0004 /* MRL Sensor Changed Enable */
+#define PCI_EXP_SLTCTL_PDCE 0x0008 /* Presence Detect Changed Enable */
+#define PCI_EXP_SLTCTL_CCIE 0x0010 /* Command Completed Interrupt Enable */
+#define PCI_EXP_SLTCTL_HPIE 0x0020 /* Hot-Plug Interrupt Enable */
+#define PCI_EXP_SLTCTL_AIC 0x00c0 /* Attention Indicator Control */
+#define PCI_EXP_SLTCTL_ATTN_IND_ON 0x0040 /* Attention Indicator on */
+#define PCI_EXP_SLTCTL_ATTN_IND_BLINK 0x0080 /* Attention Indicator blinking */
+#define PCI_EXP_SLTCTL_ATTN_IND_OFF 0x00c0 /* Attention Indicator off */
+#define PCI_EXP_SLTCTL_PIC 0x0300 /* Power Indicator Control */
+#define PCI_EXP_SLTCTL_PWR_IND_ON 0x0100 /* Power Indicator on */
+#define PCI_EXP_SLTCTL_PWR_IND_BLINK 0x0200 /* Power Indicator blinking */
+#define PCI_EXP_SLTCTL_PWR_IND_OFF 0x0300 /* Power Indicator off */
+#define PCI_EXP_SLTCTL_PCC 0x0400 /* Power Controller Control */
+#define PCI_EXP_SLTCTL_PWR_ON 0x0000 /* Power On */
+#define PCI_EXP_SLTCTL_PWR_OFF 0x0400 /* Power Off */
+#define PCI_EXP_SLTCTL_EIC 0x0800 /* Electromechanical Interlock Control */
+#define PCI_EXP_SLTCTL_DLLSCE 0x1000 /* Data Link Layer State Changed Enable */
+#define PCI_EXP_SLTSTA 26 /* Slot Status */
+#define PCI_EXP_SLTSTA_ABP 0x0001 /* Attention Button Pressed */
+#define PCI_EXP_SLTSTA_PFD 0x0002 /* Power Fault Detected */
+#define PCI_EXP_SLTSTA_MRLSC 0x0004 /* MRL Sensor Changed */
+#define PCI_EXP_SLTSTA_PDC 0x0008 /* Presence Detect Changed */
+#define PCI_EXP_SLTSTA_CC 0x0010 /* Command Completed */
+#define PCI_EXP_SLTSTA_MRLSS 0x0020 /* MRL Sensor State */
+#define PCI_EXP_SLTSTA_PDS 0x0040 /* Presence Detect State */
+#define PCI_EXP_SLTSTA_EIS 0x0080 /* Electromechanical Interlock Status */
+#define PCI_EXP_SLTSTA_DLLSC 0x0100 /* Data Link Layer State Changed */
+#define PCI_EXP_RTCTL 28 /* Root Control */
+#define PCI_EXP_RTCTL_SECEE 0x0001 /* System Error on Correctable Error */
+#define PCI_EXP_RTCTL_SENFEE 0x0002 /* System Error on Non-Fatal Error */
+#define PCI_EXP_RTCTL_SEFEE 0x0004 /* System Error on Fatal Error */
+#define PCI_EXP_RTCTL_PMEIE 0x0008 /* PME Interrupt Enable */
+#define PCI_EXP_RTCTL_CRSSVE 0x0010 /* CRS Software Visibility Enable */
+#define PCI_EXP_RTCAP 30 /* Root Capabilities */
+#define PCI_EXP_RTCAP_CRSVIS 0x0001 /* CRS Software Visibility capability */
+#define PCI_EXP_RTSTA 32 /* Root Status */
+#define PCI_EXP_RTSTA_PME 0x00010000 /* PME status */
+#define PCI_EXP_RTSTA_PENDING 0x00020000 /* PME pending */
+/*
+ * The Device Capabilities 2, Device Status 2, Device Control 2,
+ * Link Capabilities 2, Link Status 2, Link Control 2,
+ * Slot Capabilities 2, Slot Status 2, and Slot Control 2 registers
+ * are only present on devices with PCIe Capability version 2.
+ * Use pcie_capability_read_word() and similar interfaces to use them
+ * safely.
+ */
+#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
+#define PCI_EXP_DEVCAP2_ARI 0x00000020 /* Alternative Routing-ID */
+#define PCI_EXP_DEVCAP2_LTR 0x00000800 /* Latency tolerance reporting */
+#define PCI_EXP_DEVCAP2_OBFF_MASK 0x000c0000 /* OBFF support mechanism */
+#define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */
+#define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */
+#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
+#define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f /* Completion Timeout Value */
+#define PCI_EXP_DEVCTL2_ARI 0x0020 /* Alternative Routing-ID */
+#define PCI_EXP_DEVCTL2_IDO_REQ_EN 0x0100 /* Allow IDO for requests */
+#define PCI_EXP_DEVCTL2_IDO_CMP_EN 0x0200 /* Allow IDO for completions */
+#define PCI_EXP_DEVCTL2_LTR_EN 0x0400 /* Enable LTR mechanism */
+#define PCI_EXP_DEVCTL2_OBFF_MSGA_EN 0x2000 /* Enable OBFF Message type A */
+#define PCI_EXP_DEVCTL2_OBFF_MSGB_EN 0x4000 /* Enable OBFF Message type B */
+#define PCI_EXP_DEVCTL2_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */
+#define PCI_EXP_DEVSTA2 42 /* Device Status 2 */
+#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */
+#define PCI_EXP_LNKCAP2 44 /* Link Capabilities 2 */
+#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x00000002 /* Supported Speed 2.5GT/s */
+#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x00000004 /* Supported Speed 5.0GT/s */
+#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8.0GT/s */
+#define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100 /* Crosslink supported */
+#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
+#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
+#define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */
+#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */
+#define PCI_EXP_SLTSTA2 58 /* Slot Status 2 */
+
+/* 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 */
+#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PASID
+
+#define PCI_EXT_CAP_DSN_SIZEOF 12
+#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
+
+/* Advanced Error Reporting */
+#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
+#define PCI_ERR_UNC_UND 0x00000001 /* Undefined */
+#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */
+#define PCI_ERR_UNC_SURPDN 0x00000020 /* Surprise Down */
+#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */
+#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */
+#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */
+#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */
+#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */
+#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */
+#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */
+#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */
+#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */
+#define PCI_ERR_UNC_ACSV 0x00200000 /* ACS Violation */
+#define PCI_ERR_UNC_INTN 0x00400000 /* internal error */
+#define PCI_ERR_UNC_MCBTLP 0x00800000 /* MC blocked TLP */
+#define PCI_ERR_UNC_ATOMEG 0x01000000 /* Atomic egress blocked */
+#define PCI_ERR_UNC_TLPPRE 0x02000000 /* TLP prefix blocked */
+#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */
+ /* Same bits as above */
+#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */
+ /* Same bits as above */
+#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */
+#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */
+#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */
+#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */
+#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */
+#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */
+#define PCI_ERR_COR_ADV_NFAT 0x00002000 /* Advisory Non-Fatal */
+#define PCI_ERR_COR_INTERNAL 0x00004000 /* Corrected Internal */
+#define PCI_ERR_COR_LOG_OVER 0x00008000 /* Header Log Overflow */
+#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */
+ /* Same bits as above */
+#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */
+#define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */
+#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */
+#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */
+#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */
+#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */
+#define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */
+#define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */
+/* Correctable Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_COR_EN 0x00000001
+/* Non-fatal Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_NONFATAL_EN 0x00000002
+/* Fatal Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_FATAL_EN 0x00000004
+#define PCI_ERR_ROOT_STATUS 48
+#define PCI_ERR_ROOT_COR_RCV 0x00000001 /* ERR_COR Received */
+/* Multi ERR_COR Received */
+#define PCI_ERR_ROOT_MULTI_COR_RCV 0x00000002
+/* ERR_FATAL/NONFATAL Received */
+#define PCI_ERR_ROOT_UNCOR_RCV 0x00000004
+/* Multi ERR_FATAL/NONFATAL Received */
+#define PCI_ERR_ROOT_MULTI_UNCOR_RCV 0x00000008
+#define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */
+#define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */
+#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */
+#define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */
+
+/* Virtual Channel */
+#define PCI_VC_PORT_CAP1 4
+#define PCI_VC_CAP1_EVCC 0x00000007 /* extended VC count */
+#define PCI_VC_CAP1_LPEVCC 0x00000070 /* low prio extended VC count */
+#define PCI_VC_CAP1_ARB_SIZE 0x00000c00
+#define PCI_VC_PORT_CAP2 8
+#define PCI_VC_CAP2_32_PHASE 0x00000002
+#define PCI_VC_CAP2_64_PHASE 0x00000004
+#define PCI_VC_CAP2_128_PHASE 0x00000008
+#define PCI_VC_CAP2_ARB_OFF 0xff000000
+#define PCI_VC_PORT_CTRL 12
+#define PCI_VC_PORT_CTRL_LOAD_TABLE 0x00000001
+#define PCI_VC_PORT_STATUS 14
+#define PCI_VC_PORT_STATUS_TABLE 0x00000001
+#define PCI_VC_RES_CAP 16
+#define PCI_VC_RES_CAP_32_PHASE 0x00000002
+#define PCI_VC_RES_CAP_64_PHASE 0x00000004
+#define PCI_VC_RES_CAP_128_PHASE 0x00000008
+#define PCI_VC_RES_CAP_128_PHASE_TB 0x00000010
+#define PCI_VC_RES_CAP_256_PHASE 0x00000020
+#define PCI_VC_RES_CAP_ARB_OFF 0xff000000
+#define PCI_VC_RES_CTRL 20
+#define PCI_VC_RES_CTRL_LOAD_TABLE 0x00010000
+#define PCI_VC_RES_CTRL_ARB_SELECT 0x000e0000
+#define PCI_VC_RES_CTRL_ID 0x07000000
+#define PCI_VC_RES_CTRL_ENABLE 0x80000000
+#define PCI_VC_RES_STATUS 26
+#define PCI_VC_RES_STATUS_TABLE 0x00000001
+#define PCI_VC_RES_STATUS_NEGO 0x00000002
+#define PCI_CAP_VC_BASE_SIZEOF 0x10
+#define PCI_CAP_VC_PER_VC_SIZEOF 0x0C
+
+/* Power Budgeting */
+#define PCI_PWR_DSR 4 /* Data Select Register */
+#define PCI_PWR_DATA 8 /* Data Register */
+#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */
+#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */
+#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */
+#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
+#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */
+#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */
+#define PCI_PWR_CAP 12 /* Capability */
+#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
+#define PCI_EXT_CAP_PWR_SIZEOF 16
+
+/* Vendor-Specific (VSEC, PCI_EXT_CAP_ID_VNDR) */
+#define PCI_VNDR_HEADER 4 /* Vendor-Specific Header */
+#define PCI_VNDR_HEADER_ID(x) ((x) & 0xffff)
+#define PCI_VNDR_HEADER_REV(x) (((x) >> 16) & 0xf)
+#define PCI_VNDR_HEADER_LEN(x) (((x) >> 20) & 0xfff)
+
+/*
+ * HyperTransport sub capability types
+ *
+ * Unfortunately there are both 3 bit and 5 bit capability types defined
+ * in the HT spec, catering for that is a little messy. You probably don't
+ * want to use these directly, just use pci_find_ht_capability() and it
+ * will do the right thing for you.
+ */
+#define HT_3BIT_CAP_MASK 0xE0
+#define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */
+#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */
+
+#define HT_5BIT_CAP_MASK 0xF8
+#define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */
+#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */
+#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */
+#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */
+#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */
+#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */
+#define HT_MSI_FLAGS 0x02 /* Offset to flags */
+#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */
+#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */
+#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */
+#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */
+#define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */
+#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */
+#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */
+#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */
+#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */
+#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 HyperTransport configuration */
+#define HT_CAPTYPE_PM 0xE0 /* HyperTransport power management configuration */
+#define HT_CAP_SIZEOF_LONG 28 /* slave & primary */
+#define HT_CAP_SIZEOF_SHORT 24 /* host & secondary */
+
+/* Alternative Routing-ID Interpretation */
+#define PCI_ARI_CAP 0x04 /* ARI Capability Register */
+#define PCI_ARI_CAP_MFVC 0x0001 /* MFVC Function Groups Capability */
+#define PCI_ARI_CAP_ACS 0x0002 /* ACS Function Groups Capability */
+#define PCI_ARI_CAP_NFN(x) (((x) >> 8) & 0xff) /* Next Function Number */
+#define PCI_ARI_CTRL 0x06 /* ARI Control Register */
+#define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */
+#define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */
+#define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */
+#define PCI_EXT_CAP_ARI_SIZEOF 8
+
+/* Address Translation Service */
+#define PCI_ATS_CAP 0x04 /* ATS Capability Register */
+#define PCI_ATS_CAP_QDEP(x) ((x) & 0x1f) /* Invalidate Queue Depth */
+#define PCI_ATS_MAX_QDEP 32 /* Max Invalidate Queue Depth */
+#define PCI_ATS_CTRL 0x06 /* ATS Control Register */
+#define PCI_ATS_CTRL_ENABLE 0x8000 /* ATS Enable */
+#define PCI_ATS_CTRL_STU(x) ((x) & 0x1f) /* Smallest Translation Unit */
+#define PCI_ATS_MIN_STU 12 /* shift of minimum STU block */
+#define PCI_EXT_CAP_ATS_SIZEOF 8
+
+/* Page Request Interface */
+#define PCI_PRI_CTRL 0x04 /* PRI control register */
+#define PCI_PRI_CTRL_ENABLE 0x01 /* Enable */
+#define PCI_PRI_CTRL_RESET 0x02 /* Reset */
+#define PCI_PRI_STATUS 0x06 /* PRI status register */
+#define PCI_PRI_STATUS_RF 0x001 /* Response Failure */
+#define PCI_PRI_STATUS_UPRGI 0x002 /* Unexpected PRG index */
+#define PCI_PRI_STATUS_STOPPED 0x100 /* PRI Stopped */
+#define PCI_PRI_MAX_REQ 0x08 /* PRI max reqs supported */
+#define PCI_PRI_ALLOC_REQ 0x0c /* PRI max reqs allowed */
+#define PCI_EXT_CAP_PRI_SIZEOF 16
+
+/* Process Address Space ID */
+#define PCI_PASID_CAP 0x04 /* PASID feature register */
+#define PCI_PASID_CAP_EXEC 0x02 /* Exec permissions Supported */
+#define PCI_PASID_CAP_PRIV 0x04 /* Privilege Mode Supported */
+#define PCI_PASID_CTRL 0x06 /* PASID control register */
+#define PCI_PASID_CTRL_ENABLE 0x01 /* Enable bit */
+#define PCI_PASID_CTRL_EXEC 0x02 /* Exec permissions Enable */
+#define PCI_PASID_CTRL_PRIV 0x04 /* Privilege Mode Enable */
+#define PCI_EXT_CAP_PASID_SIZEOF 8
+
+/* Single Root I/O Virtualization */
+#define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */
+#define PCI_SRIOV_CAP_VFM 0x01 /* VF Migration Capable */
+#define PCI_SRIOV_CAP_INTR(x) ((x) >> 21) /* Interrupt Message Number */
+#define PCI_SRIOV_CTRL 0x08 /* SR-IOV Control */
+#define PCI_SRIOV_CTRL_VFE 0x01 /* VF Enable */
+#define PCI_SRIOV_CTRL_VFM 0x02 /* VF Migration Enable */
+#define PCI_SRIOV_CTRL_INTR 0x04 /* VF Migration Interrupt Enable */
+#define PCI_SRIOV_CTRL_MSE 0x08 /* VF Memory Space Enable */
+#define PCI_SRIOV_CTRL_ARI 0x10 /* ARI Capable Hierarchy */
+#define PCI_SRIOV_STATUS 0x0a /* SR-IOV Status */
+#define PCI_SRIOV_STATUS_VFM 0x01 /* VF Migration Status */
+#define PCI_SRIOV_INITIAL_VF 0x0c /* Initial VFs */
+#define PCI_SRIOV_TOTAL_VF 0x0e /* Total VFs */
+#define PCI_SRIOV_NUM_VF 0x10 /* Number of VFs */
+#define PCI_SRIOV_FUNC_LINK 0x12 /* Function Dependency Link */
+#define PCI_SRIOV_VF_OFFSET 0x14 /* First VF Offset */
+#define PCI_SRIOV_VF_STRIDE 0x16 /* Following VF Stride */
+#define PCI_SRIOV_VF_DID 0x1a /* VF Device ID */
+#define PCI_SRIOV_SUP_PGSIZE 0x1c /* Supported Page Sizes */
+#define PCI_SRIOV_SYS_PGSIZE 0x20 /* System Page Size */
+#define PCI_SRIOV_BAR 0x24 /* VF BAR0 */
+#define PCI_SRIOV_NUM_BARS 6 /* Number of VF BARs */
+#define PCI_SRIOV_VFM 0x3c /* VF Migration State Array Offset*/
+#define PCI_SRIOV_VFM_BIR(x) ((x) & 7) /* State BIR */
+#define PCI_SRIOV_VFM_OFFSET(x) ((x) & ~7) /* State Offset */
+#define PCI_SRIOV_VFM_UA 0x0 /* Inactive.Unavailable */
+#define PCI_SRIOV_VFM_MI 0x1 /* Dormant.MigrateIn */
+#define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */
+#define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */
+#define PCI_EXT_CAP_SRIOV_SIZEOF 64
+
+#define PCI_LTR_MAX_SNOOP_LAT 0x4
+#define PCI_LTR_MAX_NOSNOOP_LAT 0x6
+#define PCI_LTR_VALUE_MASK 0x000003ff
+#define PCI_LTR_SCALE_MASK 0x00001c00
+#define PCI_LTR_SCALE_SHIFT 10
+#define PCI_EXT_CAP_LTR_SIZEOF 8
+
+/* Access Control Service */
+#define PCI_ACS_CAP 0x04 /* ACS Capability Register */
+#define PCI_ACS_SV 0x01 /* Source Validation */
+#define PCI_ACS_TB 0x02 /* Translation Blocking */
+#define PCI_ACS_RR 0x04 /* P2P Request Redirect */
+#define PCI_ACS_CR 0x08 /* P2P Completion Redirect */
+#define PCI_ACS_UF 0x10 /* Upstream Forwarding */
+#define PCI_ACS_EC 0x20 /* P2P Egress Control */
+#define PCI_ACS_DT 0x40 /* Direct Translated P2P */
+#define PCI_ACS_EGRESS_BITS 0x05 /* ACS Egress Control Vector Size */
+#define PCI_ACS_CTRL 0x06 /* ACS Control Register */
+#define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */
+
+#define PCI_VSEC_HDR 4 /* extended cap - vendor-specific */
+#define PCI_VSEC_HDR_LEN_SHIFT 20 /* shift for length field */
+
+/* SATA capability */
+#define PCI_SATA_REGS 4 /* SATA REGs specifier */
+#define PCI_SATA_REGS_MASK 0xF /* location - BAR#/inline */
+#define PCI_SATA_REGS_INLINE 0xF /* REGS in config space */
+#define PCI_SATA_SIZEOF_SHORT 8
+#define PCI_SATA_SIZEOF_LONG 16
+
+/* Resizable BARs */
+#define PCI_REBAR_CTRL 8 /* control register */
+#define PCI_REBAR_CTRL_NBAR_MASK (7 << 5) /* mask for # bars */
+#define PCI_REBAR_CTRL_NBAR_SHIFT 5 /* shift for # bars */
+
+/* Dynamic Power Allocation */
+#define PCI_DPA_CAP 4 /* capability register */
+#define PCI_DPA_CAP_SUBSTATE_MASK 0x1F /* # substates - 1 */
+#define PCI_DPA_BASE_SIZEOF 16 /* size with 0 substates */
+
+/* TPH Requester */
+#define PCI_TPH_CAP 4 /* capability register */
+#define PCI_TPH_CAP_LOC_MASK 0x600 /* location mask */
+#define PCI_TPH_LOC_NONE 0x000 /* no location */
+#define PCI_TPH_LOC_CAP 0x200 /* in capability */
+#define PCI_TPH_LOC_MSIX 0x400 /* in MSI-X */
+#define PCI_TPH_CAP_ST_MASK 0x07FF0000 /* st table mask */
+#define PCI_TPH_CAP_ST_SHIFT 16 /* st table shift */
+#define PCI_TPH_BASE_SIZEOF 12 /* size with no st table */
#endif /* LINUX_PCI_REGS_H */
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/7] pci: Add pcie-designware driver
2015-03-17 6:38 i.MX6 PCI support Sascha Hauer
` (2 preceding siblings ...)
2015-03-17 6:38 ` [PATCH 3/7] pci: pci_regs.h: Sync with Linux Sascha Hauer
@ 2015-03-17 6:38 ` Sascha Hauer
2015-03-17 6:38 ` [PATCH 5/7] ARM: i.MX: Add imx_clk_gate_exclusive Sascha Hauer
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2015-03-17 6:38 UTC (permalink / raw)
To: Barebox List
Based on the corresponding kernel driver, only small changes
to make it work on barebox.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pci/Kconfig | 3 +
drivers/pci/Makefile | 1 +
drivers/pci/pcie-designware.c | 564 ++++++++++++++++++++++++++++++++++++++++++
drivers/pci/pcie-designware.h | 71 ++++++
4 files changed, 639 insertions(+)
create mode 100644 drivers/pci/pcie-designware.c
create mode 100644 drivers/pci/pcie-designware.h
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 0e9308e..bd24ce0 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -24,6 +24,9 @@ config PCI_DEBUG
When in doubt, say N.
+config PCIE_DW
+ bool
+
config PCI_MVEBU
bool "Marvell EBU PCIe driver"
depends on ARCH_MVEBU
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index b93b28a..3240abd 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -9,3 +9,4 @@ CPPFLAGS += $(ccflags-y)
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o pci-mvebu-phy.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
+obj-$(CONFIG_PCIE_DW) += pcie-designware.o
diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
new file mode 100644
index 0000000..4edaede
--- /dev/null
+++ b/drivers/pci/pcie-designware.c
@@ -0,0 +1,564 @@
+/*
+ * Synopsys Designware PCIe host controller driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <common.h>
+#include <clock.h>
+#include <malloc.h>
+#include <io.h>
+#include <init.h>
+#include <asm/mmu.h>
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <of_address.h>
+#include <of_pci.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/reset.h>
+#include <linux/sizes.h>
+
+#include "pcie-designware.h"
+
+/* Synopsis specific PCIE configuration registers */
+#define PCIE_PORT_LINK_CONTROL 0x710
+#define PORT_LINK_MODE_MASK (0x3f << 16)
+#define PORT_LINK_MODE_1_LANES (0x1 << 16)
+#define PORT_LINK_MODE_2_LANES (0x3 << 16)
+#define PORT_LINK_MODE_4_LANES (0x7 << 16)
+
+#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
+#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
+#define PORT_LOGIC_LINK_WIDTH_MASK (0x1ff << 8)
+#define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8)
+#define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8)
+#define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8)
+
+#define PCIE_MSI_ADDR_LO 0x820
+#define PCIE_MSI_ADDR_HI 0x824
+#define PCIE_MSI_INTR0_ENABLE 0x828
+#define PCIE_MSI_INTR0_MASK 0x82C
+#define PCIE_MSI_INTR0_STATUS 0x830
+
+#define PCIE_ATU_VIEWPORT 0x900
+#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
+#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
+#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
+#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
+#define PCIE_ATU_CR1 0x904
+#define PCIE_ATU_TYPE_MEM (0x0 << 0)
+#define PCIE_ATU_TYPE_IO (0x2 << 0)
+#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
+#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
+#define PCIE_ATU_CR2 0x908
+#define PCIE_ATU_ENABLE (0x1 << 31)
+#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
+#define PCIE_ATU_LOWER_BASE 0x90C
+#define PCIE_ATU_UPPER_BASE 0x910
+#define PCIE_ATU_LIMIT 0x914
+#define PCIE_ATU_LOWER_TARGET 0x918
+#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
+#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
+#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
+#define PCIE_ATU_UPPER_TARGET 0x91C
+
+static unsigned long global_io_offset;
+
+int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
+{
+ *val = readl(addr);
+
+ if (size == 1)
+ *val = (*val >> (8 * (where & 3))) & 0xff;
+ else if (size == 2)
+ *val = (*val >> (8 * (where & 3))) & 0xffff;
+ else if (size != 4)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val)
+{
+ if (size == 4)
+ writel(val, addr);
+ else if (size == 2)
+ writew(val, addr + (where & 2));
+ else if (size == 1)
+ writeb(val, addr + (where & 3));
+ else
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline void dw_pcie_readl_rc(struct pcie_port *pp, u32 reg, u32 *val)
+{
+ if (pp->ops->readl_rc)
+ pp->ops->readl_rc(pp, pp->dbi_base + reg, val);
+ else
+ *val = readl(pp->dbi_base + reg);
+}
+
+static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg)
+{
+ if (pp->ops->writel_rc)
+ pp->ops->writel_rc(pp, val, pp->dbi_base + reg);
+ else
+ writel(val, pp->dbi_base + reg);
+}
+
+#include <abort.h>
+
+static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
+ u32 *val)
+{
+ int ret;
+
+ if (pp->ops->rd_own_conf)
+ ret = pp->ops->rd_own_conf(pp, where, size, val);
+ else
+ ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where,
+ size, val);
+
+ return ret;
+}
+
+static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
+ u32 val)
+{
+ int ret;
+
+ if (pp->ops->wr_own_conf)
+ ret = pp->ops->wr_own_conf(pp, where, size, val);
+ else
+ ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3), where,
+ size, val);
+
+ return ret;
+}
+
+int dw_pcie_link_up(struct pcie_port *pp)
+{
+ if (pp->ops->link_up)
+ return pp->ops->link_up(pp);
+ else
+ return 0;
+}
+
+static inline struct pcie_port *host_to_pcie(struct pci_controller *host)
+{
+ return container_of(host, struct pcie_port, pci);
+}
+
+static void dw_pcie_set_local_bus_nr(struct pci_controller *host, int busno)
+{
+ struct pcie_port *pp = host_to_pcie(host);
+
+ pp->root_bus_nr = busno;
+}
+
+static struct pci_ops dw_pcie_ops;
+
+int __init dw_pcie_host_init(struct pcie_port *pp)
+{
+ struct device_node *np = pp->dev->device_node;
+ struct of_pci_range range;
+ struct of_pci_range_parser parser;
+ struct resource *cfg_res;
+ u32 val, na, ns;
+ const __be32 *addrp;
+ int index;
+
+ /* Find the address cell size and the number of cells in order to get
+ * the untranslated address.
+ */
+ of_property_read_u32(np, "#address-cells", &na);
+ ns = of_n_size_cells(np);
+
+ cfg_res = dev_get_resource_by_name(pp->dev, IORESOURCE_MEM, "config");
+ if (cfg_res) {
+ pp->cfg0_size = resource_size(cfg_res)/2;
+ pp->cfg1_size = resource_size(cfg_res)/2;
+ pp->cfg0_base = cfg_res->start;
+ pp->cfg1_base = cfg_res->start + pp->cfg0_size;
+
+ /* Find the untranslated configuration space address */
+ index = of_property_match_string(np, "reg-names", "config");
+ addrp = of_get_address(np, index, NULL, NULL);
+ pp->cfg0_mod_base = of_read_number(addrp, ns);
+ pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+ } else {
+ dev_err(pp->dev, "missing *config* reg space\n");
+ }
+
+ if (of_pci_range_parser_init(&parser, np)) {
+ dev_err(pp->dev, "missing ranges property\n");
+ return -EINVAL;
+ }
+
+ /* Get the I/O and memory ranges from DT */
+ for_each_of_pci_range(&parser, &range) {
+ unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
+
+ if (restype == IORESOURCE_IO) {
+ of_pci_range_to_resource(&range, np, &pp->io);
+ pp->io.name = "I/O";
+ pp->io.start = range.pci_addr + global_io_offset;
+ pp->io.end = range.pci_addr + range.size + global_io_offset - 1;
+ pp->io_size = resource_size(&pp->io);
+ pp->io_bus_addr = range.pci_addr;
+ pp->io_base = range.cpu_addr;
+
+ /* Find the untranslated IO space address */
+ pp->io_mod_base = of_read_number(parser.range -
+ parser.np + na, ns);
+ }
+ if (restype == IORESOURCE_MEM) {
+ of_pci_range_to_resource(&range, np, &pp->mem);
+ pp->mem.name = "MEM";
+ pp->mem_size = resource_size(&pp->mem);
+ pp->mem_bus_addr = range.pci_addr;
+
+ /* Find the untranslated MEM space address */
+ pp->mem_mod_base = of_read_number(parser.range -
+ parser.np + na, ns);
+ }
+ if (restype == 0) {
+ of_pci_range_to_resource(&range, np, &pp->cfg);
+ pp->cfg0_size = resource_size(&pp->cfg)/2;
+ pp->cfg1_size = resource_size(&pp->cfg)/2;
+ pp->cfg0_base = pp->cfg.start;
+ pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+
+ /* Find the untranslated configuration space address */
+ pp->cfg0_mod_base = of_read_number(parser.range -
+ parser.np + na, ns);
+ pp->cfg1_mod_base = pp->cfg0_mod_base +
+ pp->cfg0_size;
+ }
+ }
+
+ if (!pp->dbi_base)
+ pp->dbi_base = (void __force *)pp->cfg.start;
+
+ pp->mem_base = pp->mem.start;
+
+ if (!pp->va_cfg0_base)
+ pp->va_cfg0_base = (void __force *)(u32)pp->cfg0_base;
+
+ if (!pp->va_cfg1_base)
+ pp->va_cfg1_base = (void __force *)(u32)pp->cfg1_base;
+
+ if (of_property_read_u32(np, "num-lanes", &pp->lanes)) {
+ dev_err(pp->dev, "Failed to parse the number of lanes\n");
+ return -EINVAL;
+ }
+
+ if (pp->ops->host_init)
+ pp->ops->host_init(pp);
+
+ dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+
+ /* program correct class for RC */
+ dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
+
+ dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
+ val |= PORT_LOGIC_SPEED_CHANGE;
+ dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
+
+ pp->pci.parent = pp->dev;
+ pp->pci.pci_ops = &dw_pcie_ops;
+ pp->pci.set_busno = dw_pcie_set_local_bus_nr;
+ pp->pci.mem_resource = &pp->mem;
+ pp->pci.io_resource = &pp->io;
+
+ register_pci_controller(&pp->pci);
+
+ return 0;
+}
+
+static void dw_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev)
+{
+ /* Program viewport 0 : OUTBOUND : CFG0 */
+ dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
+ PCIE_ATU_VIEWPORT);
+ dw_pcie_writel_rc(pp, pp->cfg0_mod_base, PCIE_ATU_LOWER_BASE);
+ dw_pcie_writel_rc(pp, (pp->cfg0_mod_base >> 32), PCIE_ATU_UPPER_BASE);
+ dw_pcie_writel_rc(pp, pp->cfg0_mod_base + pp->cfg0_size - 1,
+ PCIE_ATU_LIMIT);
+ dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
+ dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
+ dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG0, PCIE_ATU_CR1);
+ dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
+}
+
+static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)
+{
+ /* Program viewport 1 : OUTBOUND : CFG1 */
+ dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
+ PCIE_ATU_VIEWPORT);
+ dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1);
+ dw_pcie_writel_rc(pp, pp->cfg1_mod_base, PCIE_ATU_LOWER_BASE);
+ dw_pcie_writel_rc(pp, (pp->cfg1_mod_base >> 32), PCIE_ATU_UPPER_BASE);
+ dw_pcie_writel_rc(pp, pp->cfg1_mod_base + pp->cfg1_size - 1,
+ PCIE_ATU_LIMIT);
+ dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
+ dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
+ dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
+}
+
+static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
+{
+ /* Program viewport 0 : OUTBOUND : MEM */
+ dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
+ PCIE_ATU_VIEWPORT);
+ dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
+ dw_pcie_writel_rc(pp, pp->mem_mod_base, PCIE_ATU_LOWER_BASE);
+ dw_pcie_writel_rc(pp, (pp->mem_mod_base >> 32), PCIE_ATU_UPPER_BASE);
+ dw_pcie_writel_rc(pp, pp->mem_mod_base + pp->mem_size - 1,
+ PCIE_ATU_LIMIT);
+ dw_pcie_writel_rc(pp, pp->mem_bus_addr, PCIE_ATU_LOWER_TARGET);
+ dw_pcie_writel_rc(pp, upper_32_bits(pp->mem_bus_addr),
+ PCIE_ATU_UPPER_TARGET);
+ dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
+}
+
+static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
+{
+ /* Program viewport 1 : OUTBOUND : IO */
+ dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
+ PCIE_ATU_VIEWPORT);
+ dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1);
+ dw_pcie_writel_rc(pp, pp->io_mod_base, PCIE_ATU_LOWER_BASE);
+ dw_pcie_writel_rc(pp, (pp->io_mod_base >> 32), PCIE_ATU_UPPER_BASE);
+ dw_pcie_writel_rc(pp, pp->io_mod_base + pp->io_size - 1,
+ PCIE_ATU_LIMIT);
+ dw_pcie_writel_rc(pp, pp->io_bus_addr, PCIE_ATU_LOWER_TARGET);
+ dw_pcie_writel_rc(pp, upper_32_bits(pp->io_bus_addr),
+ PCIE_ATU_UPPER_TARGET);
+ dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
+}
+
+struct pci_bus *get_parent_bus(struct pci_bus *bus)
+{
+ struct pci_dev *bridge = container_of(bus->parent, struct pci_dev, dev);
+
+ return bridge->bus;
+}
+
+static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ u32 devfn, int where, int size, u32 *val)
+{
+ int ret = PCIBIOS_SUCCESSFUL;
+ u32 address, busdev;
+
+ busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
+ PCIE_ATU_FUNC(PCI_FUNC(devfn));
+ address = where & ~0x3;
+
+ if (get_parent_bus(bus)->number == pp->root_bus_nr) {
+ dw_pcie_prog_viewport_cfg0(pp, busdev);
+ ret = dw_pcie_cfg_read(pp->va_cfg0_base + address, where, size,
+ val);
+ dw_pcie_prog_viewport_mem_outbound(pp);
+ } else {
+ dw_pcie_prog_viewport_cfg1(pp, busdev);
+ ret = dw_pcie_cfg_read(pp->va_cfg1_base + address, where, size,
+ val);
+ dw_pcie_prog_viewport_io_outbound(pp);
+ }
+
+ return ret;
+}
+
+static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ u32 devfn, int where, int size, u32 val)
+{
+ int ret = PCIBIOS_SUCCESSFUL;
+ u32 address, busdev;
+
+ busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
+ PCIE_ATU_FUNC(PCI_FUNC(devfn));
+ address = where & ~0x3;
+
+ if (get_parent_bus(bus)->number == pp->root_bus_nr) {
+ dw_pcie_prog_viewport_cfg0(pp, busdev);
+ ret = dw_pcie_cfg_write(pp->va_cfg0_base + address, where, size,
+ val);
+ dw_pcie_prog_viewport_mem_outbound(pp);
+ } else {
+ dw_pcie_prog_viewport_cfg1(pp, busdev);
+ ret = dw_pcie_cfg_write(pp->va_cfg1_base + address, where, size,
+ val);
+ dw_pcie_prog_viewport_io_outbound(pp);
+ }
+
+ return ret;
+}
+
+static int dw_pcie_valid_config(struct pcie_port *pp,
+ struct pci_bus *bus, int dev)
+{
+ /* If there is no link, then there is no device */
+ if (bus->number != pp->root_bus_nr) {
+ if (!dw_pcie_link_up(pp))
+ return 0;
+ }
+
+ /* access only one slot on each root port */
+ if (bus->number == pp->root_bus_nr && dev > 0)
+ return 0;
+
+ /*
+ * do not read more than one device on the bus directly attached
+ * to RC's (Virtual Bridge's) DS side.
+ */
+ if (bus->primary == pp->root_bus_nr && dev > 0)
+ return 0;
+
+ return 1;
+}
+
+static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+ int size, u32 *val)
+{
+ struct pcie_port *pp = host_to_pcie(bus->host);
+ int ret;
+
+ *val = 0xffffffff;
+
+ if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ data_abort_mask();
+
+ if (bus->number != pp->root_bus_nr)
+ if (pp->ops->rd_other_conf)
+ ret = pp->ops->rd_other_conf(pp, bus, devfn,
+ where, size, val);
+ else
+ ret = dw_pcie_rd_other_conf(pp, bus, devfn,
+ where, size, val);
+ else
+ ret = dw_pcie_rd_own_conf(pp, where, size, val);
+
+ if (data_abort_unmask())
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ret;
+}
+
+static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+ int where, int size, u32 val)
+{
+ struct pcie_port *pp = host_to_pcie(bus->host);
+ int ret;
+
+ if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ data_abort_mask();
+
+ if (bus->number != pp->root_bus_nr)
+ if (pp->ops->wr_other_conf)
+ ret = pp->ops->wr_other_conf(pp, bus, devfn,
+ where, size, val);
+ else
+ ret = dw_pcie_wr_other_conf(pp, bus, devfn,
+ where, size, val);
+ else
+ ret = dw_pcie_wr_own_conf(pp, where, size, val);
+
+ if (data_abort_unmask())
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ret;
+}
+
+static int dw_pcie_res_start(struct pci_bus *bus, resource_size_t res_addr)
+{
+ return res_addr;
+}
+
+static struct pci_ops dw_pcie_ops = {
+ .read = dw_pcie_rd_conf,
+ .write = dw_pcie_wr_conf,
+ .res_start = dw_pcie_res_start,
+};
+
+void dw_pcie_setup_rc(struct pcie_port *pp)
+{
+ u32 val;
+ u32 membase;
+ u32 memlimit;
+
+ /* set the number of lanes */
+ dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val);
+ val &= ~PORT_LINK_MODE_MASK;
+ switch (pp->lanes) {
+ case 1:
+ val |= PORT_LINK_MODE_1_LANES;
+ break;
+ case 2:
+ val |= PORT_LINK_MODE_2_LANES;
+ break;
+ case 4:
+ val |= PORT_LINK_MODE_4_LANES;
+ break;
+ }
+ dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL);
+
+ /* set link width speed control register */
+ dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, &val);
+ val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
+ switch (pp->lanes) {
+ case 1:
+ val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
+ break;
+ case 2:
+ val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
+ break;
+ case 4:
+ val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
+ break;
+ }
+ dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL);
+
+ /* setup RC BARs */
+ dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_0);
+ dw_pcie_writel_rc(pp, 0x00000000, PCI_BASE_ADDRESS_1);
+
+ /* setup bus numbers */
+ dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS, &val);
+ val &= 0xff000000;
+ val |= 0x00010100;
+ dw_pcie_writel_rc(pp, val, PCI_PRIMARY_BUS);
+
+ /* setup memory base, memory limit */
+ membase = ((u32)pp->mem_base & 0xfff00000) >> 16;
+ memlimit = (pp->mem_size + (u32)pp->mem_base) & 0xfff00000;
+ val = memlimit | membase;
+ dw_pcie_writel_rc(pp, val, PCI_MEMORY_BASE);
+
+ /* setup command register */
+ dw_pcie_readl_rc(pp, PCI_COMMAND, &val);
+ val &= 0xffff0000;
+ val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
+ dw_pcie_writel_rc(pp, val, PCI_COMMAND);
+}
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Designware PCIe host controller driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
new file mode 100644
index 0000000..8d0330a
--- /dev/null
+++ b/drivers/pci/pcie-designware.h
@@ -0,0 +1,71 @@
+/*
+ * Synopsys Designware PCIe host controller driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PCIE_DESIGNWARE_H
+#define _PCIE_DESIGNWARE_H
+
+struct pcie_port {
+ struct device_d *dev;
+ u8 root_bus_nr;
+ void __iomem *dbi_base;
+ u64 cfg0_base;
+ u64 cfg0_mod_base;
+ void __iomem *va_cfg0_base;
+ u32 cfg0_size;
+ u64 cfg1_base;
+ u64 cfg1_mod_base;
+ void __iomem *va_cfg1_base;
+ u32 cfg1_size;
+ u64 io_base;
+ u64 io_mod_base;
+ phys_addr_t io_bus_addr;
+ u32 io_size;
+ u64 mem_base;
+ u64 mem_mod_base;
+ phys_addr_t mem_bus_addr;
+ u32 mem_size;
+ struct resource cfg;
+ struct resource io;
+ struct resource mem;
+ struct resource busn;
+ int irq;
+ u32 lanes;
+ struct pcie_host_ops *ops;
+ struct pci_controller pci;
+};
+
+struct pcie_host_ops {
+ void (*readl_rc)(struct pcie_port *pp,
+ void __iomem *dbi_base, u32 *val);
+ void (*writel_rc)(struct pcie_port *pp,
+ u32 val, void __iomem *dbi_base);
+ int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);
+ int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val);
+ int (*rd_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 *val);
+ int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 val);
+ int (*link_up)(struct pcie_port *pp);
+ void (*host_init)(struct pcie_port *pp);
+ void (*scan_bus)(struct pcie_port *pp);
+};
+
+int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val);
+int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val);
+irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
+void dw_pcie_msi_init(struct pcie_port *pp);
+int dw_pcie_link_up(struct pcie_port *pp);
+void dw_pcie_setup_rc(struct pcie_port *pp);
+int dw_pcie_host_init(struct pcie_port *pp);
+
+#endif /* _PCIE_DESIGNWARE_H */
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/7] ARM: i.MX: Add imx_clk_gate_exclusive
2015-03-17 6:38 i.MX6 PCI support Sascha Hauer
` (3 preceding siblings ...)
2015-03-17 6:38 ` [PATCH 4/7] pci: Add pcie-designware driver Sascha Hauer
@ 2015-03-17 6:38 ` Sascha Hauer
2015-03-17 6:38 ` [PATCH 6/7] ARM: i.MX6: Add PCI clocks Sascha Hauer
2015-03-17 6:38 ` [PATCH 7/7] pci: Add i.MX6 pcie support Sascha Hauer
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2015-03-17 6:38 UTC (permalink / raw)
To: Barebox List
This adds support for two gates from can only exclusively be enabled.
Based on the corresponding Linux code.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/Makefile | 2 +-
arch/arm/mach-imx/clk-gate-exclusive.c | 103 +++++++++++++++++++++++++++++++++
arch/arm/mach-imx/clk.h | 3 +
3 files changed, 107 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/mach-imx/clk-gate-exclusive.c
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 048cac5..ae953b1 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -16,7 +16,7 @@ obj-$(CONFIG_IMX_IIM) += iim.o
obj-$(CONFIG_IMX_OCOTP) += ocotp.o
obj-$(CONFIG_NAND_IMX) += nand.o
lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o
-obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-pfd.o clk-gate2.o
+obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-pfd.o clk-gate2.o clk-gate-exclusive.o
obj-y += devices.o imx.o esdctl.o
obj-y += boot.o
obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
diff --git a/arch/arm/mach-imx/clk-gate-exclusive.c b/arch/arm/mach-imx/clk-gate-exclusive.c
new file mode 100644
index 0000000..db88db0
--- /dev/null
+++ b/arch/arm/mach-imx/clk-gate-exclusive.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <io.h>
+#include <malloc.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+/**
+ * struct clk_gate_exclusive - i.MX specific gate clock which is mutually
+ * exclusive with other gate clocks
+ *
+ * @gate: the parent class
+ * @exclusive_mask: mask of gate bits which are mutually exclusive to this
+ * gate clock
+ *
+ * The imx exclusive gate clock is a subclass of basic clk_gate
+ * with an addtional mask to indicate which other gate bits in the same
+ * register is mutually exclusive to this gate clock.
+ */
+struct clk_gate_exclusive {
+ struct clk clk;
+ void __iomem *reg;
+ int shift;
+ const char *parent;
+ u32 exclusive_mask;
+};
+
+static int clk_gate_exclusive_enable(struct clk *clk)
+{
+ struct clk_gate_exclusive *exgate = container_of(clk,
+ struct clk_gate_exclusive, clk);
+ u32 val = readl(exgate->reg);
+
+ if (val & exgate->exclusive_mask)
+ return -EBUSY;
+
+ val |= 1 << exgate->shift;
+
+ writel(val, exgate->reg);
+
+ return 0;
+}
+
+static void clk_gate_exclusive_disable(struct clk *clk)
+{
+ struct clk_gate_exclusive *exgate = container_of(clk,
+ struct clk_gate_exclusive, clk);
+ u32 val = readl(exgate->reg);
+
+ val &= ~(1 << exgate->shift);
+
+ writel(val, exgate->reg);
+}
+
+static int clk_gate_exclusive_is_enabled(struct clk *clk)
+{
+ struct clk_gate_exclusive *exgate = container_of(clk,
+ struct clk_gate_exclusive, clk);
+
+ return readl(exgate->reg) & (1 << exgate->shift);
+}
+
+static const struct clk_ops clk_gate_exclusive_ops = {
+ .enable = clk_gate_exclusive_enable,
+ .disable = clk_gate_exclusive_disable,
+ .is_enabled = clk_gate_exclusive_is_enabled,
+};
+
+struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
+ void __iomem *reg, u8 shift, u32 exclusive_mask)
+{
+ struct clk_gate_exclusive *exgate;
+ int ret;
+
+ exgate = xzalloc(sizeof(*exgate));
+ exgate->parent = parent;
+ exgate->clk.name = name;
+ exgate->clk.ops = &clk_gate_exclusive_ops;
+ exgate->clk.flags = CLK_SET_RATE_PARENT;
+ exgate->clk.parent_names = &exgate->parent;
+ exgate->clk.num_parents = 1;
+
+ exgate->reg = reg;
+ exgate->shift = shift;
+ exgate->exclusive_mask = exclusive_mask;
+
+ ret = clk_register(&exgate->clk);
+ if (ret) {
+ free(exgate);
+ return ERR_PTR(ret);
+ }
+
+ return &exgate->clk;
+}
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 8ec3eb5..c8da2fa 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -92,4 +92,7 @@ static inline struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg,
return imx_clk_mux(name, reg, shift, width, parents, num_parents);
}
+struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
+ void __iomem *reg, u8 shift, u32 exclusive_mask);
+
#endif /* __IMX_CLK_H */
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/7] ARM: i.MX6: Add PCI clocks
2015-03-17 6:38 i.MX6 PCI support Sascha Hauer
` (4 preceding siblings ...)
2015-03-17 6:38 ` [PATCH 5/7] ARM: i.MX: Add imx_clk_gate_exclusive Sascha Hauer
@ 2015-03-17 6:38 ` Sascha Hauer
2015-03-17 6:38 ` [PATCH 7/7] pci: Add i.MX6 pcie support Sascha Hauer
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2015-03-17 6:38 UTC (permalink / raw)
To: Barebox List
Needed for pcie support.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/clk-imx6.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c
index dccf0a8..2d46447 100644
--- a/arch/arm/mach-imx/clk-imx6.c
+++ b/arch/arm/mach-imx/clk-imx6.c
@@ -196,6 +196,26 @@ static const char *ipu2_di1_sels[] = {
"ldb_di1_podf",
};
+static const char *lvds_sels[] = {
+ "dummy",
+ "dummy",
+ "dummy",
+ "dummy",
+ "dummy",
+ "dummy",
+ "pll4_audio",
+ "pll5_video",
+ "pll8_mlb",
+ "enet_ref",
+ "pcie_ref_125m",
+ "sata_ref_100m",
+};
+
+static const char *pcie_axi_sels[] = {
+ "axi",
+ "ahb",
+};
+
static struct clk_div_table clk_enet_ref_table[] = {
{ .val = 0, .div = 20, },
{ .val = 1, .div = 10, },
@@ -306,6 +326,12 @@ static int imx6_ccm_probe(struct device_d *dev)
clks[IMX6QDL_CLK_ENET_REF] = imx_clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table);
+ clks[IMX6QDL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+ clks[IMX6QDL_CLK_LVDS2_SEL] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+
+ clks[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate_exclusive("lvds1_gate", "lvds1_sel", base + 0x160, 10, BIT(12));
+ clks[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate_exclusive("lvds2_gate", "lvds2_sel", base + 0x160, 11, BIT(13));
+
/* name parent_name reg idx */
clks[IMX6QDL_CLK_PLL2_PFD0_352M] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
clks[IMX6QDL_CLK_PLL2_PFD1_594M] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
@@ -341,6 +367,7 @@ static int imx6_ccm_probe(struct device_d *dev)
clks[IMX6QDL_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_sels, ARRAY_SIZE(eim_sels));
clks[IMX6QDL_CLK_VDO_AXI_SEL] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels));
clks[IMX6QDL_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels));
+ clks[IMX6QDL_CLK_PCIE_AXI_SEL] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels));
/* name reg shift width busy: reg, shift parent_names num_parents */
clks[IMX6QDL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
@@ -433,6 +460,8 @@ static int imx6_ccm_probe(struct device_d *dev)
clk_enable(clks[IMX6QDL_CLK_SATA_REF_100M]);
clk_enable(clks[IMX6QDL_CLK_ENFC_PODF]);
+ clk_set_parent(clks[IMX6QDL_CLK_LVDS1_SEL], clks[IMX6QDL_CLK_SATA_REF_100M]);
+
return 0;
}
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 7/7] pci: Add i.MX6 pcie support
2015-03-17 6:38 i.MX6 PCI support Sascha Hauer
` (5 preceding siblings ...)
2015-03-17 6:38 ` [PATCH 6/7] ARM: i.MX6: Add PCI clocks Sascha Hauer
@ 2015-03-17 6:38 ` Sascha Hauer
6 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2015-03-17 6:38 UTC (permalink / raw)
To: Barebox List
Based on the corresponding kernel driver with changes to make it
work on barebox.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/Kconfig | 1 +
drivers/pci/Kconfig | 7 +
drivers/pci/Makefile | 1 +
drivers/pci/pci-imx6.c | 612 +++++++++++++++++++++++++++++++++++++++++
include/mfd/imx6q-iomuxc-gpr.h | 8 +
5 files changed, 629 insertions(+)
create mode 100644 drivers/pci/pci-imx6.c
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index c62cea8..fe6c679 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -174,6 +174,7 @@ config ARCH_IMX6
select CPU_V7
select PINCTRL_IMX_IOMUX_V3
select COMMON_CLK_OF_PROVIDER
+ select HW_HAS_PCI
config ARCH_IMX6SX
bool
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index bd24ce0..1c45a1c 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -40,6 +40,13 @@ config PCI_TEGRA
select OF_PCI
select PCI
+config PCI_IMX6
+ bool "Freescale i.MX6 PCIe controller"
+ depends on ARCH_IMX6
+ select PCIE_DW
+ select OF_PCI
+ select PCI
+
endmenu
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 3240abd..ce5d0e2 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -10,3 +10,4 @@ CPPFLAGS += $(ccflags-y)
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o pci-mvebu-phy.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
obj-$(CONFIG_PCIE_DW) += pcie-designware.o
+obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c
new file mode 100644
index 0000000..eaa5f0e
--- /dev/null
+++ b/drivers/pci/pci-imx6.c
@@ -0,0 +1,612 @@
+/*
+ * PCIe host controller driver for Freescale i.MX6 SoCs
+ *
+ * Copyright (C) 2013 Kosagi
+ * http://www.kosagi.com
+ *
+ * Author: Sean Cross <xobs@kosagi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <malloc.h>
+#include <io.h>
+#include <init.h>
+#include <gpio.h>
+#include <asm/mmu.h>
+#include <of_gpio.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <of_address.h>
+#include <of_pci.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/reset.h>
+#include <linux/sizes.h>
+#include <mfd/imx6q-iomuxc-gpr.h>
+
+#include <mach/imx6-regs.h>
+
+#include "pcie-designware.h"
+
+#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp)
+
+struct imx6_pcie {
+ int reset_gpio;
+ struct clk *pcie_bus;
+ struct clk *pcie_phy;
+ struct clk *pcie;
+ struct pcie_port pp;
+ void __iomem *iomuxc_gpr;
+ void __iomem *mem_base;
+};
+
+/* PCIe Root Complex registers (memory-mapped) */
+#define PCIE_RC_LCR 0x7c
+#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1
+#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2
+#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf
+
+/* PCIe Port Logic registers (memory-mapped) */
+#define PL_OFFSET 0x700
+#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
+#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
+#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
+#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
+#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
+#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
+#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP (1 << 4)
+
+#define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
+#define PCIE_PHY_CTRL_DATA_LOC 0
+#define PCIE_PHY_CTRL_CAP_ADR_LOC 16
+#define PCIE_PHY_CTRL_CAP_DAT_LOC 17
+#define PCIE_PHY_CTRL_WR_LOC 18
+#define PCIE_PHY_CTRL_RD_LOC 19
+
+#define PCIE_PHY_STAT (PL_OFFSET + 0x110)
+#define PCIE_PHY_STAT_ACK_LOC 16
+
+#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
+#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
+
+/* PHY registers (not memory-mapped) */
+#define PCIE_PHY_RX_ASIC_OUT 0x100D
+
+#define PHY_RX_OVRD_IN_LO 0x1005
+#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
+#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
+
+static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
+{
+ u32 val;
+ u32 max_iterations = 10;
+ u32 wait_counter = 0;
+
+ do {
+ val = readl(dbi_base + PCIE_PHY_STAT);
+ val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
+ wait_counter++;
+
+ if (val == exp_val)
+ return 0;
+
+ udelay(1);
+ } while (wait_counter < max_iterations);
+
+ return -ETIMEDOUT;
+}
+
+static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
+{
+ u32 val;
+ int ret;
+
+ val = addr << PCIE_PHY_CTRL_DATA_LOC;
+ writel(val, dbi_base + PCIE_PHY_CTRL);
+
+ val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
+ writel(val, dbi_base + PCIE_PHY_CTRL);
+
+ ret = pcie_phy_poll_ack(dbi_base, 1);
+ if (ret)
+ return ret;
+
+ val = addr << PCIE_PHY_CTRL_DATA_LOC;
+ writel(val, dbi_base + PCIE_PHY_CTRL);
+
+ ret = pcie_phy_poll_ack(dbi_base, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
+static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
+{
+ u32 val, phy_ctl;
+ int ret;
+
+ ret = pcie_phy_wait_ack(dbi_base, addr);
+ if (ret)
+ return ret;
+
+ /* assert Read signal */
+ phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
+ writel(phy_ctl, dbi_base + PCIE_PHY_CTRL);
+
+ ret = pcie_phy_poll_ack(dbi_base, 1);
+ if (ret)
+ return ret;
+
+ val = readl(dbi_base + PCIE_PHY_STAT);
+ *data = val & 0xffff;
+
+ /* deassert Read signal */
+ writel(0x00, dbi_base + PCIE_PHY_CTRL);
+
+ ret = pcie_phy_poll_ack(dbi_base, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
+{
+ u32 var;
+ int ret;
+
+ /* write addr */
+ /* cap addr */
+ ret = pcie_phy_wait_ack(dbi_base, addr);
+ if (ret)
+ return ret;
+
+ var = data << PCIE_PHY_CTRL_DATA_LOC;
+ writel(var, dbi_base + PCIE_PHY_CTRL);
+
+ /* capture data */
+ var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
+ writel(var, dbi_base + PCIE_PHY_CTRL);
+
+ ret = pcie_phy_poll_ack(dbi_base, 1);
+ if (ret)
+ return ret;
+
+ /* deassert cap data */
+ var = data << PCIE_PHY_CTRL_DATA_LOC;
+ writel(var, dbi_base + PCIE_PHY_CTRL);
+
+ /* wait for ack de-assertion */
+ ret = pcie_phy_poll_ack(dbi_base, 0);
+ if (ret)
+ return ret;
+
+ /* assert wr signal */
+ var = 0x1 << PCIE_PHY_CTRL_WR_LOC;
+ writel(var, dbi_base + PCIE_PHY_CTRL);
+
+ /* wait for ack */
+ ret = pcie_phy_poll_ack(dbi_base, 1);
+ if (ret)
+ return ret;
+
+ /* deassert wr signal */
+ var = data << PCIE_PHY_CTRL_DATA_LOC;
+ writel(var, dbi_base + PCIE_PHY_CTRL);
+
+ /* wait for ack de-assertion */
+ ret = pcie_phy_poll_ack(dbi_base, 0);
+ if (ret)
+ return ret;
+
+ writel(0x0, dbi_base + PCIE_PHY_CTRL);
+
+ return 0;
+}
+
+static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
+{
+ struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ u32 val, gpr1, gpr12;
+
+ /*
+ * If the bootloader already enabled the link we need some special
+ * handling to get the core back into a state where it is safe to
+ * touch it for configuration. As there is no dedicated reset signal
+ * wired up for MX6QDL, we need to manually force LTSSM into "detect"
+ * state before completely disabling LTSSM, which is a prerequisite
+ * for core configuration.
+ *
+ * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we have a strong
+ * indication that the bootloader activated the link.
+ */
+ gpr1 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+ gpr12 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+
+ if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) &&
+ (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) {
+ val = readl(pp->dbi_base + PCIE_PL_PFLR);
+ val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
+ val |= PCIE_PL_PFLR_FORCE_LINK;
+ writel(val, pp->dbi_base + PCIE_PL_PFLR);
+
+ gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2;
+ writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+ }
+
+ gpr1 |= IMX6Q_GPR1_PCIE_TEST_PD;
+ writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+
+ gpr1 &= ~IMX6Q_GPR1_PCIE_REF_CLK_EN;
+ writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+
+ return 0;
+}
+
+static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
+{
+ struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ int ret;
+ u32 gpr1;
+
+ ret = clk_enable(imx6_pcie->pcie_phy);
+ if (ret)
+ goto err_pcie_phy;
+
+ ret = clk_enable(imx6_pcie->pcie_bus);
+ if (ret)
+ goto err_pcie_bus;
+
+ ret = clk_enable(imx6_pcie->pcie);
+ if (ret)
+ goto err_pcie;
+
+ /* power up core phy and enable ref clock */
+ gpr1 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+ gpr1 &= ~IMX6Q_GPR1_PCIE_TEST_PD;
+ writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+ /*
+ * the async reset input need ref clock to sync internally,
+ * when the ref clock comes after reset, internal synced
+ * reset time is too short, cannot meet the requirement.
+ * add one ~10us delay here.
+ */
+ udelay(10);
+ gpr1 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+ gpr1 |= IMX6Q_GPR1_PCIE_REF_CLK_EN;
+ writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1);
+
+ /* allow the clocks to stabilize */
+ udelay(200);
+
+ /* Some boards don't have PCIe reset GPIO. */
+ if (gpio_is_valid(imx6_pcie->reset_gpio)) {
+ gpio_set_value(imx6_pcie->reset_gpio, 0);
+ mdelay(100);
+ gpio_set_value(imx6_pcie->reset_gpio, 1);
+ }
+ return 0;
+
+err_pcie:
+ clk_disable(imx6_pcie->pcie_bus);
+err_pcie_bus:
+ clk_disable(imx6_pcie->pcie_phy);
+err_pcie_phy:
+ return ret;
+
+}
+
+static void imx6_pcie_init_phy(struct pcie_port *pp)
+{
+ struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ u32 gpr12, gpr8;
+
+ gpr12 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+ gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2;
+ writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+
+ /* configure constant input signal to the pcie ctrl and phy */
+ gpr12 &= ~IMX6Q_GPR12_DEVICE_TYPE;
+ gpr12 |= PCI_EXP_TYPE_ROOT_PORT << 12;
+ writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+
+ gpr12 &= ~IMX6Q_GPR12_LOS_LEVEL;
+ gpr12 |= 9 << 4;
+ writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+
+ gpr8 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR8);
+ gpr8 &= ~IMX6Q_GPR8_TX_DEEMPH_GEN1;
+ writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8);
+
+ gpr8 &= ~IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB;
+ writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8);
+
+ gpr8 &= ~IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB;
+ gpr8 |= 20 << 12;
+ writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8);
+
+ gpr8 &= ~IMX6Q_GPR8_TX_SWING_FULL;
+ gpr8 |= 127 << 18;
+ writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8);
+
+ gpr8 &= ~IMX6Q_GPR8_TX_SWING_LOW;
+ gpr8 |= 127 << 25;
+ writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8);
+}
+
+static int imx6_pcie_wait_for_link(struct pcie_port *pp)
+{
+ uint64_t start = get_time_ns();
+
+ while (1) {
+ if (dw_pcie_link_up(pp))
+ return 0;
+
+ if (!is_timeout(start, SECOND))
+ continue;
+
+ dev_err(pp->dev, "phy link never came up\n");
+ dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
+ readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
+ readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
+ return -EINVAL;
+ }
+}
+
+static int imx6_pcie_start_link(struct pcie_port *pp)
+{
+ struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ uint32_t tmp;
+ int ret;
+ u32 gpr12;
+ u64 start;
+
+ /*
+ * Force Gen1 operation when starting the link. In case the link is
+ * started in Gen2 mode, there is a possibility the devices on the
+ * bus will not be detected at all. This happens with PCIe switches.
+ */
+ tmp = readl(pp->dbi_base + PCIE_RC_LCR);
+ tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
+ tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
+ writel(tmp, pp->dbi_base + PCIE_RC_LCR);
+
+ /* Start LTSSM. */
+ gpr12 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+ gpr12 |= IMX6Q_GPR12_PCIE_CTL_2;
+ writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12);
+
+ ret = imx6_pcie_wait_for_link(pp);
+ if (ret)
+ return ret;
+
+ /* Allow Gen2 mode after the link is up. */
+ tmp = readl(pp->dbi_base + PCIE_RC_LCR);
+ tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
+ tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
+ writel(tmp, pp->dbi_base + PCIE_RC_LCR);
+
+ /*
+ * Start Directed Speed Change so the best possible speed both link
+ * partners support can be negotiated.
+ */
+ tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+ tmp |= PORT_LOGIC_SPEED_CHANGE;
+ writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+
+ start = get_time_ns();
+ while (!is_timeout(start, SECOND)) {
+ tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
+ /* Test if the speed change finished. */
+ if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
+ break;
+ }
+
+ /* Make sure link training is finished as well! */
+ if (tmp & PORT_LOGIC_SPEED_CHANGE)
+ ret = -EINVAL;
+ else
+ ret = imx6_pcie_wait_for_link(pp);
+
+ if (ret) {
+ dev_err(pp->dev, "Failed to bring link up!\n");
+ } else {
+ tmp = readl(pp->dbi_base + 0x80);
+ dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
+ }
+
+ return ret;
+}
+
+static void imx6_pcie_host_init(struct pcie_port *pp)
+{
+ imx6_pcie_assert_core_reset(pp);
+
+ imx6_pcie_init_phy(pp);
+
+ imx6_pcie_deassert_core_reset(pp);
+
+ dw_pcie_setup_rc(pp);
+
+ imx6_pcie_start_link(pp);
+}
+
+static void imx6_pcie_reset_phy(struct pcie_port *pp)
+{
+ uint32_t temp;
+
+ pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp);
+ temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
+ PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+ pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp);
+
+ udelay(2000);
+
+ pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp);
+ temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
+ PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+ pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp);
+}
+
+static int imx6_pcie_link_up(struct pcie_port *pp)
+{
+ u32 rc, debug_r0, rx_valid;
+ int count = 5;
+
+ /*
+ * Test if the PHY reports that the link is up and also that the LTSSM
+ * training finished. There are three possible states of the link when
+ * this code is called:
+ * 1) The link is DOWN (unlikely)
+ * The link didn't come up yet for some reason. This usually means
+ * we have a real problem somewhere. Reset the PHY and exit. This
+ * state calls for inspection of the DEBUG registers.
+ * 2) The link is UP, but still in LTSSM training
+ * Wait for the training to finish, which should take a very short
+ * time. If the training does not finish, we have a problem and we
+ * need to inspect the DEBUG registers. If the training does finish,
+ * the link is up and operating correctly.
+ * 3) The link is UP and no longer in LTSSM training
+ * The link is up and operating correctly.
+ */
+ while (1) {
+ rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
+ if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP))
+ break;
+ if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
+ return 1;
+ if (!count--)
+ break;
+ dev_dbg(pp->dev, "Link is up, but still in training\n");
+ /*
+ * Wait a little bit, then re-check if the link finished
+ * the training.
+ */
+ udelay(1000);
+ }
+ /*
+ * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
+ * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
+ * If (MAC/LTSSM.state == Recovery.RcvrLock)
+ * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition
+ * to gen2 is stuck
+ */
+ pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
+ debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
+
+ if (rx_valid & 0x01)
+ return 0;
+
+ if ((debug_r0 & 0x3f) != 0x0d)
+ return 0;
+
+ dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
+ dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc);
+
+ imx6_pcie_reset_phy(pp);
+
+ return 0;
+}
+
+static struct pcie_host_ops imx6_pcie_host_ops = {
+ .link_up = imx6_pcie_link_up,
+ .host_init = imx6_pcie_host_init,
+};
+
+static int __init imx6_add_pcie_port(struct pcie_port *pp,
+ struct device_d *dev)
+{
+ int ret;
+
+ pp->root_bus_nr = -1;
+ pp->ops = &imx6_pcie_host_ops;
+
+ ret = dw_pcie_host_init(pp);
+ if (ret) {
+ dev_err(dev, "failed to initialize host\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __init imx6_pcie_probe(struct device_d *dev)
+{
+ struct imx6_pcie *imx6_pcie;
+ struct pcie_port *pp;
+ struct device_node *np = dev->device_node;
+ int ret;
+
+ imx6_pcie = xzalloc(sizeof(*imx6_pcie));
+ if (!imx6_pcie)
+ return -ENOMEM;
+
+ pp = &imx6_pcie->pp;
+ pp->dev = dev;
+
+ pp->dbi_base = dev_request_mem_region(dev, 0);
+ if (IS_ERR(pp->dbi_base))
+ return PTR_ERR(pp->dbi_base);
+
+ /* Fetch GPIOs */
+ imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
+ if (gpio_is_valid(imx6_pcie->reset_gpio)) {
+ ret = gpio_request_one(imx6_pcie->reset_gpio,
+ GPIOF_OUT_INIT_LOW, "PCIe reset");
+ if (ret) {
+ dev_err(dev, "unable to get reset gpio\n");
+ return ret;
+ }
+ }
+
+ /* Fetch clocks */
+ imx6_pcie->pcie_phy = clk_get(dev, "pcie_phy");
+ if (IS_ERR(imx6_pcie->pcie_phy)) {
+ dev_err(dev, "pcie_phy clock source missing or invalid\n");
+ return PTR_ERR(imx6_pcie->pcie_phy);
+ }
+
+ imx6_pcie->pcie_bus = clk_get(dev, "pcie_bus");
+ if (IS_ERR(imx6_pcie->pcie_bus)) {
+ dev_err(dev, "pcie_bus clock source missing or invalid\n");
+ return PTR_ERR(imx6_pcie->pcie_bus);
+ }
+
+ imx6_pcie->pcie = clk_get(dev, "pcie");
+ if (IS_ERR(imx6_pcie->pcie)) {
+ dev_err(dev, "pcie clock source missing or invalid\n");
+ return PTR_ERR(imx6_pcie->pcie);
+ }
+
+ /* Grab GPR config register range */
+ imx6_pcie->iomuxc_gpr = IOMEM(MX6_IOMUXC_BASE_ADDR);
+
+ ret = imx6_add_pcie_port(pp, dev);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct of_device_id imx6_pcie_of_match[] = {
+ { .compatible = "fsl,imx6q-pcie", },
+ {},
+};
+
+static struct driver_d imx6_pcie_driver = {
+ .name = "imx6-pcie",
+ .of_compatible = DRV_OF_COMPAT(imx6_pcie_of_match),
+ .probe = imx6_pcie_probe,
+};
+device_platform_driver(imx6_pcie_driver);
+
+MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
+MODULE_DESCRIPTION("Freescale i.MX6 PCIe host controller driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/mfd/imx6q-iomuxc-gpr.h b/include/mfd/imx6q-iomuxc-gpr.h
index 24993ff..a7ef1c8 100644
--- a/include/mfd/imx6q-iomuxc-gpr.h
+++ b/include/mfd/imx6q-iomuxc-gpr.h
@@ -259,6 +259,12 @@
#define IMX6Q_GPR7_IPU2_ID10_RD_QOS_MASK (0xf << 24)
#define IMX6Q_GPR7_IPU2_ID11_RD_QOS_MASK (0xf << 28)
+#define IMX6Q_GPR8_TX_SWING_LOW (0x7f << 25)
+#define IMX6Q_GPR8_TX_SWING_FULL (0x7f << 18)
+#define IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB (0x3f << 12)
+#define IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB (0x3f << 6)
+#define IMX6Q_GPR8_TX_DEEMPH_GEN1 (0x3f << 0)
+
#define IMX6Q_GPR9_TZASC2_BYP BIT(1)
#define IMX6Q_GPR9_TZASC1_BYP BIT(0)
@@ -291,7 +297,9 @@
#define IMX6Q_GPR12_ARMP_AHB_CLK_EN BIT(26)
#define IMX6Q_GPR12_ARMP_ATB_CLK_EN BIT(25)
#define IMX6Q_GPR12_ARMP_APB_CLK_EN BIT(24)
+#define IMX6Q_GPR12_DEVICE_TYPE (0xf << 12)
#define IMX6Q_GPR12_PCIE_CTL_2 BIT(10)
+#define IMX6Q_GPR12_LOS_LEVEL (0x1f << 4)
#define IMX6Q_GPR13_SDMA_STOP_REQ BIT(30)
#define IMX6Q_GPR13_CAN2_STOP_REQ BIT(29)
--
2.1.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/7] pci: Use standard pr_debug
2015-03-17 6:38 ` [PATCH 1/7] pci: Use standard pr_debug Sascha Hauer
@ 2015-03-18 9:08 ` Jean-Christophe PLAGNIOL-VILLARD
0 siblings, 0 replies; 9+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2015-03-18 9:08 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
On 07:38 Tue 17 Mar , Sascha Hauer wrote:
> Use pr_debug instead of custom DBG macro.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> drivers/pci/pci.c | 34 +++++++++++++++-------------------
> 1 file changed, 15 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 1f5dc78..cb8c539 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1,13 +1,9 @@
> +#define pr_fmt(fmt) "pci: " fmt
> +
> #include <common.h>
> #include <linux/sizes.h>
> #include <linux/pci.h>
>
> -#ifdef DEBUG
> -#define DBG(x...) printk(x)
> -#else
> -#define DBG(x...)
> -#endif
> -
> static struct pci_controller *hose_head, **hose_tail = &hose_head;
>
> LIST_HEAD(pci_root_buses);
> @@ -150,16 +146,16 @@ static void setup_device(struct pci_dev *dev, int max_bar)
> pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &mask);
>
> if (mask == 0 || mask == 0xffffffff) {
> - DBG(" PCI: pbar%d set bad mask\n", bar);
> + pr_debug("pbar%d set bad mask\n", bar);
dev_debug
please
Best Regards,
J.
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-03-18 9:09 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-17 6:38 i.MX6 PCI support Sascha Hauer
2015-03-17 6:38 ` [PATCH 1/7] pci: Use standard pr_debug Sascha Hauer
2015-03-18 9:08 ` Jean-Christophe PLAGNIOL-VILLARD
2015-03-17 6:38 ` [PATCH 2/7] pci: fix copy-paste bug Sascha Hauer
2015-03-17 6:38 ` [PATCH 3/7] pci: pci_regs.h: Sync with Linux Sascha Hauer
2015-03-17 6:38 ` [PATCH 4/7] pci: Add pcie-designware driver Sascha Hauer
2015-03-17 6:38 ` [PATCH 5/7] ARM: i.MX: Add imx_clk_gate_exclusive Sascha Hauer
2015-03-17 6:38 ` [PATCH 6/7] ARM: i.MX6: Add PCI clocks Sascha Hauer
2015-03-17 6:38 ` [PATCH 7/7] pci: Add i.MX6 pcie support Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox