linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/3] arch/tile: mark TILEGX as not EXPERIMENTAL
  2012-04-07 20:53 [PATCH 0/3] arch/tile: provide PCIe support for tilegx Chris Metcalf
@ 2012-04-07 19:58 ` Chris Metcalf
  2012-04-07 20:53 ` [PATCH 1/3] arch/tile: provide kernel support for the tilegx TRIO shim Chris Metcalf
  2012-04-07 21:10 ` [PATCH 3/3] arch/tile: tilegx PCI root complex support Chris Metcalf
  2 siblings, 0 replies; 19+ messages in thread
From: Chris Metcalf @ 2012-04-07 19:58 UTC (permalink / raw)
  To: linux-kernel

Also create a TILEPRO config setting to use for #ifdefs where it
is cleaner to do so, and make the 64BIT setting depend directly
on the setting of TILEGX.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
---
 arch/tile/Kconfig |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 533820c..d51b479 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -113,16 +113,14 @@ config HVC_TILE
 	select HVC_DRIVER
 	def_bool y
 
-# Please note: TILE-Gx support is not yet finalized; this is
-# the preliminary support.  TILE-Gx drivers are only provided
-# with the alpha or beta test versions for Tilera customers.
 config TILEGX
-	depends on EXPERIMENTAL
 	bool "Building with TILE-Gx (64-bit) compiler and toolchain"
 
+config TILEPRO
+	def_bool !TILEGX
+
 config 64BIT
-	depends on TILEGX
-	def_bool y
+	def_bool TILEGX
 
 config ARCH_DEFCONFIG
 	string
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 0/3] arch/tile: provide PCIe support for tilegx
@ 2012-04-07 20:53 Chris Metcalf
  2012-04-07 19:58 ` [PATCH 2/3] arch/tile: mark TILEGX as not EXPERIMENTAL Chris Metcalf
                   ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Chris Metcalf @ 2012-04-07 20:53 UTC (permalink / raw)
  To: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Arnd Bergmann, Jiri Kosina,
	Joe Perches, David Howells

This series of changes adds PCIe support to the tilegx architecture
using the on-chip TRIO ("Transation I/O") hardware.  The last change is
the one that adds PCI support per-se and it is cc'ed to a wider audience.

As usual, any code review would be appreciated.  This is layered on
top of the GXIO IORPC mechanism presented in the previous patch series,
which provided networking support for tilegx.

 arch/tile/Kconfig                            |   13 +-
 arch/tile/gxio/Kconfig                       |    9 +
 arch/tile/gxio/Makefile                      |    1 +
 arch/tile/gxio/iorpc_trio.c                  |  352 ++++++
 arch/tile/gxio/trio.c                        |   49 +
 arch/tile/include/arch/trio.h                |   68 ++
 arch/tile/include/arch/trio_constants.h      |   36 +
 arch/tile/include/arch/trio_def.h            |   41 +
 arch/tile/include/arch/trio_pcie_intfc.h     |  203 ++++
 arch/tile/include/arch/trio_pcie_intfc_def.h |   32 +
 arch/tile/include/arch/trio_pcie_rc.h        |  144 +++
 arch/tile/include/arch/trio_pcie_rc_def.h    |   24 +
 arch/tile/include/arch/trio_shm.h            |  111 ++
 arch/tile/include/arch/trio_shm_def.h        |   19 +
 arch/tile/include/asm/pci.h                  |   97 ++-
 arch/tile/include/gxio/iorpc_trio.h          |  198 ++++
 arch/tile/include/gxio/trio.h                |  303 +++++
 arch/tile/include/hv/drv_trio_intf.h         |  196 ++++
 arch/tile/kernel/Makefile                    |    4 +
 arch/tile/kernel/pci_gx.c                    | 1597 ++++++++++++++++++++++++++
 arch/tile/kernel/setup.c                     |    6 +
 arch/tile/mm/pgtable.c                       |    7 -
 drivers/pci/quirks.c                         |    6 +-
 23 files changed, 3490 insertions(+), 26 deletions(-)

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/3] arch/tile: provide kernel support for the tilegx TRIO shim
  2012-04-07 20:53 [PATCH 0/3] arch/tile: provide PCIe support for tilegx Chris Metcalf
  2012-04-07 19:58 ` [PATCH 2/3] arch/tile: mark TILEGX as not EXPERIMENTAL Chris Metcalf
@ 2012-04-07 20:53 ` Chris Metcalf
  2012-04-07 23:39   ` Jesper Juhl
  2012-04-07 21:10 ` [PATCH 3/3] arch/tile: tilegx PCI root complex support Chris Metcalf
  2 siblings, 1 reply; 19+ messages in thread
From: Chris Metcalf @ 2012-04-07 20:53 UTC (permalink / raw)
  To: linux-kernel

Provide kernel support for the tilegx "Transaction I/O" (TRIO) on-chip
hardware.  This hardware implements the PCIe interface for tilegx;
the driver changes to use TRIO for PCIe are in a subsequent commit.

The change is layered on top of the tilegx GXIO IORPC subsystem.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
---
 arch/tile/gxio/Kconfig                       |    9 +
 arch/tile/gxio/Makefile                      |    1 +
 arch/tile/gxio/iorpc_trio.c                  |  352 ++++++++++++++++++++++++++
 arch/tile/gxio/trio.c                        |   49 ++++
 arch/tile/include/arch/trio.h                |   68 +++++
 arch/tile/include/arch/trio_constants.h      |   36 +++
 arch/tile/include/arch/trio_def.h            |   41 +++
 arch/tile/include/arch/trio_pcie_intfc.h     |  203 +++++++++++++++
 arch/tile/include/arch/trio_pcie_intfc_def.h |   32 +++
 arch/tile/include/arch/trio_pcie_rc.h        |  144 +++++++++++
 arch/tile/include/arch/trio_pcie_rc_def.h    |   24 ++
 arch/tile/include/arch/trio_shm.h            |  111 ++++++++
 arch/tile/include/arch/trio_shm_def.h        |   19 ++
 arch/tile/include/gxio/iorpc_trio.h          |  198 +++++++++++++++
 arch/tile/include/gxio/trio.h                |  303 ++++++++++++++++++++++
 arch/tile/include/hv/drv_trio_intf.h         |  196 ++++++++++++++
 16 files changed, 1786 insertions(+), 0 deletions(-)
 create mode 100644 arch/tile/gxio/iorpc_trio.c
 create mode 100644 arch/tile/gxio/trio.c
 create mode 100644 arch/tile/include/arch/trio.h
 create mode 100644 arch/tile/include/arch/trio_constants.h
 create mode 100644 arch/tile/include/arch/trio_def.h
 create mode 100644 arch/tile/include/arch/trio_pcie_intfc.h
 create mode 100644 arch/tile/include/arch/trio_pcie_intfc_def.h
 create mode 100644 arch/tile/include/arch/trio_pcie_rc.h
 create mode 100644 arch/tile/include/arch/trio_pcie_rc_def.h
 create mode 100644 arch/tile/include/arch/trio_shm.h
 create mode 100644 arch/tile/include/arch/trio_shm_def.h
 create mode 100644 arch/tile/include/gxio/iorpc_trio.h
 create mode 100644 arch/tile/include/gxio/trio.h
 create mode 100644 arch/tile/include/hv/drv_trio_intf.h

diff --git a/arch/tile/gxio/Kconfig b/arch/tile/gxio/Kconfig
index ec20e8c..ed0cd48 100644
--- a/arch/tile/gxio/Kconfig
+++ b/arch/tile/gxio/Kconfig
@@ -23,3 +23,12 @@ config TILE_GXIO_MPIPE
 	  This option supports direct access to the TILE-Gx mPIPE hardware
 	  from kernel space.  It is not required in order to use the gxio
 	  library to access mPIPE from user space.
+
+config TILE_GXIO_TRIO
+	bool "Tilera Gx TRIO I/O support"
+	select TILE_GXIO
+	select TILE_GXIO_DMA
+	---help---
+	  This option supports direct access to the TILE-Gx TRIO hardware
+	  from kernel space.  It is not required in order to use the gxio
+	  library to access TRIO from user space.
diff --git a/arch/tile/gxio/Makefile b/arch/tile/gxio/Makefile
index 130eec4..2389ef3 100644
--- a/arch/tile/gxio/Makefile
+++ b/arch/tile/gxio/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_TILE_GXIO) += iorpc_globals.o kiorpc.o
 obj-$(CONFIG_TILE_GXIO_DMA) += dma_queue.o
 obj-$(CONFIG_TILE_GXIO_MPIPE) += mpipe.o iorpc_mpipe.o iorpc_mpipe_info.o
+obj-$(CONFIG_TILE_GXIO_TRIO) += trio.o iorpc_trio.o
diff --git a/arch/tile/gxio/iorpc_trio.c b/arch/tile/gxio/iorpc_trio.c
new file mode 100644
index 0000000..4ca91ab
--- /dev/null
+++ b/arch/tile/gxio/iorpc_trio.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#include "gxio/iorpc_trio.h"
+
+typedef struct {
+	unsigned int count;
+	unsigned int first;
+	unsigned int flags;
+} alloc_asids_param_t;
+
+int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+			  unsigned int first, unsigned int flags)
+{
+	uint64_t __offset;
+	int __result;
+	alloc_asids_param_t temp;
+	alloc_asids_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->count = count;
+	params->first = first;
+	params->flags = flags;
+
+	__offset = GXIO_TRIO_OP_ALLOC_ASIDS;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_asids);
+
+
+typedef struct {
+	unsigned int count;
+	unsigned int first;
+	unsigned int flags;
+} alloc_memory_maps_param_t;
+
+int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
+				unsigned int count, unsigned int first,
+				unsigned int flags)
+{
+	uint64_t __offset;
+	int __result;
+	alloc_memory_maps_param_t temp;
+	alloc_memory_maps_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->count = count;
+	params->first = first;
+	params->flags = flags;
+
+	__offset = GXIO_TRIO_OP_ALLOC_MEMORY_MAPS;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_memory_maps);
+
+
+typedef struct {
+	unsigned int count;
+	unsigned int first;
+	unsigned int flags;
+} alloc_pio_regions_param_t;
+
+int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
+				unsigned int count, unsigned int first,
+				unsigned int flags)
+{
+	uint64_t __offset;
+	int __result;
+	alloc_pio_regions_param_t temp;
+	alloc_pio_regions_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->count = count;
+	params->first = first;
+	params->flags = flags;
+
+	__offset = GXIO_TRIO_OP_ALLOC_PIO_REGIONS;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_pio_regions);
+
+typedef struct {
+	unsigned int pio_region;
+	unsigned int mac;
+	uint32_t bus_address_hi;
+	unsigned int flags;
+} init_pio_region_aux_param_t;
+
+int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
+				  unsigned int pio_region, unsigned int mac,
+				  uint32_t bus_address_hi, unsigned int flags)
+{
+	uint64_t __offset;
+	int __result;
+	init_pio_region_aux_param_t temp;
+	init_pio_region_aux_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->pio_region = pio_region;
+	params->mac = mac;
+	params->bus_address_hi = bus_address_hi;
+	params->flags = flags;
+
+	__offset = GXIO_TRIO_OP_INIT_PIO_REGION_AUX;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_init_pio_region_aux);
+
+
+typedef struct {
+	unsigned int map;
+	unsigned long va;
+	uint64_t size;
+	unsigned int asid;
+	unsigned int mac;
+	uint64_t bus_address;
+	unsigned int node;
+	unsigned int order_mode;
+} init_memory_map_mmu_aux_param_t;
+
+int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
+				      unsigned int map, unsigned long va,
+				      uint64_t size, unsigned int asid,
+				      unsigned int mac, uint64_t bus_address,
+				      unsigned int node,
+				      unsigned int order_mode)
+{
+	uint64_t __offset;
+	int __result;
+	init_memory_map_mmu_aux_param_t temp;
+	init_memory_map_mmu_aux_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->map = map;
+	params->va = va;
+	params->size = size;
+	params->asid = asid;
+	params->mac = mac;
+	params->bus_address = bus_address;
+	params->node = node;
+	params->order_mode = order_mode;
+
+	__offset = GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_init_memory_map_mmu_aux);
+
+
+typedef struct {
+	iorpc_interrupt_t interrupt;
+	unsigned int mac;
+	unsigned int intx;
+} config_legacy_intr_param_t;
+
+int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
+				 int inter_y, int inter_ipi, int inter_event,
+				 unsigned int mac, unsigned int intx)
+{
+	uint64_t __offset;
+	int __result;
+	config_legacy_intr_param_t temp;
+	config_legacy_intr_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->interrupt.kernel.x = inter_x;
+	params->interrupt.kernel.y = inter_y;
+	params->interrupt.kernel.ipi = inter_ipi;
+	params->interrupt.kernel.event = inter_event;
+	params->mac = mac;
+	params->intx = intx;
+
+	__offset = GXIO_TRIO_OP_CONFIG_LEGACY_INTR;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_config_legacy_intr);
+
+typedef struct {
+	iorpc_interrupt_t interrupt;
+	unsigned int mac;
+	unsigned int mem_map;
+	uint64_t mem_map_base;
+	uint64_t mem_map_limit;
+	unsigned int asid;
+} config_msi_intr_param_t;
+
+int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
+			      int inter_y, int inter_ipi, int inter_event,
+			      unsigned int mac, unsigned int mem_map,
+			      uint64_t mem_map_base, uint64_t mem_map_limit,
+			      unsigned int asid)
+{
+	uint64_t __offset;
+	int __result;
+	config_msi_intr_param_t temp;
+	config_msi_intr_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->interrupt.kernel.x = inter_x;
+	params->interrupt.kernel.y = inter_y;
+	params->interrupt.kernel.ipi = inter_ipi;
+	params->interrupt.kernel.event = inter_event;
+	params->mac = mac;
+	params->mem_map = mem_map;
+	params->mem_map_base = mem_map_base;
+	params->mem_map_limit = mem_map_limit;
+	params->asid = asid;
+
+	__offset = GXIO_TRIO_OP_CONFIG_MSI_INTR;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_config_msi_intr);
+
+
+typedef struct {
+	uint16_t mps;
+	uint16_t mrs;
+	unsigned int mac;
+} set_mps_mrs_param_t;
+
+int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
+			  uint16_t mrs, unsigned int mac)
+{
+	uint64_t __offset;
+	int __result;
+	set_mps_mrs_param_t temp;
+	set_mps_mrs_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->mps = mps;
+	params->mrs = mrs;
+	params->mac = mac;
+
+	__offset = GXIO_TRIO_OP_SET_MPS_MRS;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_set_mps_mrs);
+
+typedef struct {
+	unsigned int mac;
+} force_link_up_param_t;
+
+int gxio_trio_force_link_up(gxio_trio_context_t * context, unsigned int mac)
+{
+	uint64_t __offset;
+	int __result;
+	force_link_up_param_t temp;
+	force_link_up_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->mac = mac;
+
+	__offset = GXIO_TRIO_OP_FORCE_LINK_UP;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_force_link_up);
+
+typedef struct {
+	HV_PTE base;
+} get_mmio_base_param_t;
+
+int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base)
+{
+	uint64_t __offset;
+	int __result;
+	get_mmio_base_param_t temp;
+	get_mmio_base_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	__offset = GXIO_TRIO_OP_GET_MMIO_BASE;
+	__result =
+	    hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, __size,
+			 __offset);
+	*base = params->base;
+
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_get_mmio_base);
+
+typedef struct {
+	unsigned long offset;
+	unsigned long size;
+} check_mmio_offset_param_t;
+
+int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
+				unsigned long offset, unsigned long size)
+{
+	uint64_t __offset;
+	int __result;
+	check_mmio_offset_param_t temp;
+	check_mmio_offset_param_t *params = &temp;
+	size_t __size = sizeof(*params);
+
+	params->offset = offset;
+	params->size = size;
+
+	__offset = GXIO_TRIO_OP_CHECK_MMIO_OFFSET;
+	__result =
+	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
+			  __offset);
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_check_mmio_offset);
diff --git a/arch/tile/gxio/trio.c b/arch/tile/gxio/trio.c
new file mode 100644
index 0000000..cd5c103
--- /dev/null
+++ b/arch/tile/gxio/trio.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ * Implementation of trio gxio calls.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <gxio/trio.h>
+#include <gxio/iorpc_globals.h>
+#include <gxio/iorpc_trio.h>
+#include <gxio/kiorpc.h>
+
+int gxio_trio_init(gxio_trio_context_t * context, unsigned int trio_index)
+{
+	char file[32];
+	int fd;
+
+	snprintf(file, sizeof(file), "trio/%d/iorpc", trio_index);
+	fd = hv_dev_open((HV_VirtAddr) file, 0);
+	if (fd < 0) {
+		context->fd = -1;
+
+		if (fd >= GXIO_ERR_MIN && fd <= GXIO_ERR_MAX)
+			return fd;
+		else
+			return -ENODEV;
+	}
+
+	context->fd = fd;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(gxio_trio_init);
diff --git a/arch/tile/include/arch/trio.h b/arch/tile/include/arch/trio.h
new file mode 100644
index 0000000..b1f6bdf
--- /dev/null
+++ b/arch/tile/include/arch/trio.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_H__
+#define __ARCH_TRIO_H__
+
+#include <arch/abi.h>
+#include <arch/trio_def.h>
+
+#ifndef __ASSEMBLER__
+
+// Tile PIO Region Configuration - CFG Address Format.
+// This register describes the address format for PIO accesses when the
+// associated region is setup with TYPE=CFG.
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    // Register Address (full byte address).
+    uint_reg_t reg_addr     : 12;
+    // Function Number
+    uint_reg_t fn           : 3;
+    // Device Number
+    uint_reg_t dev          : 5;
+    // BUS Number
+    uint_reg_t bus          : 8;
+    // Config Type: 0 for access to directly-attached device.  1 otherwise.
+    uint_reg_t type         : 1;
+    // Reserved.
+    uint_reg_t __reserved_0 : 1;
+    // MAC select.  This must match the configuration in
+    // TILE_PIO_REGION_SETUP.MAC.
+    uint_reg_t mac          : 2;
+    // Reserved.
+    uint_reg_t __reserved_1 : 32;
+#else   // __BIG_ENDIAN__
+    uint_reg_t __reserved_1 : 32;
+    uint_reg_t mac          : 2;
+    uint_reg_t __reserved_0 : 1;
+    uint_reg_t type         : 1;
+    uint_reg_t bus          : 8;
+    uint_reg_t dev          : 5;
+    uint_reg_t fn           : 3;
+    uint_reg_t reg_addr     : 12;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_H__) */
diff --git a/arch/tile/include/arch/trio_constants.h b/arch/tile/include/arch/trio_constants.h
new file mode 100644
index 0000000..628b045
--- /dev/null
+++ b/arch/tile/include/arch/trio_constants.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+
+#ifndef __ARCH_TRIO_CONSTANTS_H__
+#define __ARCH_TRIO_CONSTANTS_H__
+
+#define TRIO_NUM_ASIDS 16
+#define TRIO_NUM_TLBS_PER_ASID 16
+
+#define TRIO_NUM_TPIO_REGIONS 8
+#define TRIO_LOG2_NUM_TPIO_REGIONS 3
+
+#define TRIO_NUM_MAP_MEM_REGIONS 16
+#define TRIO_LOG2_NUM_MAP_MEM_REGIONS 4
+#define TRIO_NUM_MAP_SQ_REGIONS 8
+#define TRIO_LOG2_NUM_MAP_SQ_REGIONS 3
+
+#define TRIO_LOG2_NUM_SQ_FIFO_ENTRIES 6
+
+#define TRIO_NUM_PUSH_DMA_RINGS 32
+
+#define TRIO_NUM_PULL_DMA_RINGS 32
+
+#endif /* __ARCH_TRIO_CONSTANTS_H__ */
diff --git a/arch/tile/include/arch/trio_def.h b/arch/tile/include/arch/trio_def.h
new file mode 100644
index 0000000..e805003
--- /dev/null
+++ b/arch/tile/include/arch/trio_def.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_DEF_H__
+#define __ARCH_TRIO_DEF_H__
+#define TRIO_CFG_REGION_ADDR__REG_SHIFT 0
+#define TRIO_CFG_REGION_ADDR__INTFC_SHIFT 16
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_TRIO 0x0
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE 0x1
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD 0x2
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED 0x3
+#define TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT 18
+#define TRIO_CFG_REGION_ADDR__PROT_SHIFT 20
+#define TRIO_PIO_REGIONS_ADDR__REGION_SHIFT 32
+#define TRIO_MAP_MEM_REG_INT0 0x1000000000
+#define TRIO_MAP_MEM_REG_INT1 0x1000000008
+#define TRIO_MAP_MEM_REG_INT2 0x1000000010
+#define TRIO_MAP_MEM_REG_INT3 0x1000000018
+#define TRIO_MAP_MEM_REG_INT4 0x1000000020
+#define TRIO_MAP_MEM_REG_INT5 0x1000000028
+#define TRIO_MAP_MEM_REG_INT6 0x1000000030
+#define TRIO_MAP_MEM_REG_INT7 0x1000000038
+#define TRIO_MAP_MEM_LIM__ADDR_SHIFT 12
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_UNORDERED 0x0
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_STRICT 0x1
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_REL_ORD 0x2
+#define TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT 30
+#endif /* !defined(__ARCH_TRIO_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_intfc.h b/arch/tile/include/arch/trio_pcie_intfc.h
new file mode 100644
index 0000000..a74b56b
--- /dev/null
+++ b/arch/tile/include/arch/trio_pcie_intfc.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_INTFC_H__
+#define __ARCH_TRIO_PCIE_INTFC_H__
+
+#include <arch/abi.h>
+#include <arch/trio_pcie_intfc_def.h>
+
+#ifndef __ASSEMBLER__
+
+// Port Configuration.
+// Configuration of the PCIe Port
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    // Provides the state of the strapping pins for this port.
+    uint_reg_t strap_state      : 3;
+    // Reserved.
+    uint_reg_t __reserved_0     : 1;
+    // When 1, the device type will be overridden using OVD_DEV_TYPE_VAL.
+    // When 0, the device type is determined based on the STRAP_STATE.
+    uint_reg_t ovd_dev_type     : 1;
+    // Provides the device type when OVD_DEV_TYPE is 1.
+    uint_reg_t ovd_dev_type_val : 4;
+    // Determines how link is trained.
+    uint_reg_t train_mode       : 2;
+    // Reserved.
+    uint_reg_t __reserved_1     : 1;
+    // For PCIe, used to flip physical RX lanes that were not properly wired.
+    //  This is not the same as lane reversal which is handled automatically
+    // during link training.  When 0, RX Lane0 must be wired to the link
+    // partner (either to its Lane0 or it's LaneN).  When RX_LANE_FLIP is 1,
+    // the highest numbered lane for this port becomes Lane0 and Lane0 does
+    // NOT have to be wired to the link partner.
+    uint_reg_t rx_lane_flip     : 1;
+    // For PCIe, used to flip physical TX lanes that were not properly wired.
+    //  This is not the same as lane reversal which is handled automatically
+    // during link training.  When 0, TX Lane0 must be wired to the link
+    // partner (either to its Lane0 or it's LaneN).  When TX_LANE_FLIP is 1,
+    // the highest numbered lane for this port becomes Lane0 and Lane0 does
+    // NOT have to be wired to the link partner.
+    uint_reg_t tx_lane_flip     : 1;
+    // For StreamIO port, configures the width of the port when TRAIN_MODE is
+    // not STRAP.
+    uint_reg_t stream_width     : 2;
+    // For StreamIO port, configures the rate of the port when TRAIN_MODE is
+    // not STRAP.
+    uint_reg_t stream_rate      : 2;
+    // Reserved.
+    uint_reg_t __reserved_2     : 46;
+#else   // __BIG_ENDIAN__
+    uint_reg_t __reserved_2     : 46;
+    uint_reg_t stream_rate      : 2;
+    uint_reg_t stream_width     : 2;
+    uint_reg_t tx_lane_flip     : 1;
+    uint_reg_t rx_lane_flip     : 1;
+    uint_reg_t __reserved_1     : 1;
+    uint_reg_t train_mode       : 2;
+    uint_reg_t ovd_dev_type_val : 4;
+    uint_reg_t ovd_dev_type     : 1;
+    uint_reg_t __reserved_0     : 1;
+    uint_reg_t strap_state      : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_PORT_CONFIG_t;
+
+// Port Status.
+// Status of the PCIe Port.  This register applies to the StreamIO port when
+// StreamIO is enabled.
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    // Indicates the DL state of the port.  When 1, the port is up and ready
+    // to receive traffic.
+    uint_reg_t dl_up        : 1;
+    // Indicates the number of times the link has gone down.  Clears on read.
+    uint_reg_t dl_down_cnt  : 7;
+    // Indicates the SERDES PLL has spun up and is providing a valid clock.
+    uint_reg_t clock_ready  : 1;
+    // Reserved.
+    uint_reg_t __reserved_0 : 7;
+    // Device revision ID.
+    uint_reg_t device_rev   : 8;
+    // Link state (PCIe).
+    uint_reg_t ltssm_state  : 6;
+    // Link power management state (PCIe).
+    uint_reg_t pm_state     : 3;
+    // Reserved.
+    uint_reg_t __reserved_1 : 31;
+#else   // __BIG_ENDIAN__
+    uint_reg_t __reserved_1 : 31;
+    uint_reg_t pm_state     : 3;
+    uint_reg_t ltssm_state  : 6;
+    uint_reg_t device_rev   : 8;
+    uint_reg_t __reserved_0 : 7;
+    uint_reg_t clock_ready  : 1;
+    uint_reg_t dl_down_cnt  : 7;
+    uint_reg_t dl_up        : 1;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_PORT_STATUS_t;
+
+// Transmit FIFO Control.
+// Contains TX FIFO thresholds.  These registers are for diagnostics purposes
+// only.  Changing these values causes undefined behavior.
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    // Almost-Empty level for TX0 data.  Typically set to at least
+    // roundup(38.0*M/N) where N=tclk frequency and M=MAC symbol rate in MHz
+    // for a x4 port (250MHz).
+    uint_reg_t tx0_data_ae_lvl : 7;
+    // Reserved.
+    uint_reg_t __reserved_0    : 1;
+    // Almost-Empty level for TX1 data.
+    uint_reg_t tx1_data_ae_lvl : 7;
+    // Reserved.
+    uint_reg_t __reserved_1    : 1;
+    // Almost-Full level for TX0 data.
+    uint_reg_t tx0_data_af_lvl : 7;
+    // Reserved.
+    uint_reg_t __reserved_2    : 1;
+    // Almost-Full level for TX1 data.
+    uint_reg_t tx1_data_af_lvl : 7;
+    // Reserved.
+    uint_reg_t __reserved_3    : 1;
+    // Almost-Full level for TX0 info.
+    uint_reg_t tx0_info_af_lvl : 5;
+    // Reserved.
+    uint_reg_t __reserved_4    : 3;
+    // Almost-Full level for TX1 info.
+    uint_reg_t tx1_info_af_lvl : 5;
+    // Reserved.
+    uint_reg_t __reserved_5    : 3;
+    // This register provides performance adjustment for high bandwidth
+    // flows.  The MAC will assert almost-full to TRIO if non-posted credits
+    // fall below this level.  Note that setting this larger than the initial
+    // PORT_CREDIT.NPH value will cause READS to never be sent.  If the
+    // initial credit value from the link partner is smaller than this value
+    // when the link comes up, the value will be reset to the initial credit
+    // value to prevent lockup.
+    uint_reg_t min_np_credits  : 8;
+    // This register provides performance adjustment for high bandwidth
+    // flows.  The MAC will assert almost-full to TRIO if posted credits fall
+    // below this level.  Note that setting this larger than the initial
+    // PORT_CREDIT.PH value will cause WRITES to never be sent.  If the
+    // initial credit value from the link partner is smaller than this value
+    // when the link comes up, the value will be reset to the initial credit
+    // value to prevent lockup.
+    uint_reg_t min_p_credits   : 8;
+#else   // __BIG_ENDIAN__
+    uint_reg_t min_p_credits   : 8;
+    uint_reg_t min_np_credits  : 8;
+    uint_reg_t __reserved_5    : 3;
+    uint_reg_t tx1_info_af_lvl : 5;
+    uint_reg_t __reserved_4    : 3;
+    uint_reg_t tx0_info_af_lvl : 5;
+    uint_reg_t __reserved_3    : 1;
+    uint_reg_t tx1_data_af_lvl : 7;
+    uint_reg_t __reserved_2    : 1;
+    uint_reg_t tx0_data_af_lvl : 7;
+    uint_reg_t __reserved_1    : 1;
+    uint_reg_t tx1_data_ae_lvl : 7;
+    uint_reg_t __reserved_0    : 1;
+    uint_reg_t tx0_data_ae_lvl : 7;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_TX_FIFO_CTL_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_PCIE_INTFC_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_intfc_def.h b/arch/tile/include/arch/trio_pcie_intfc_def.h
new file mode 100644
index 0000000..d3fd678
--- /dev/null
+++ b/arch/tile/include/arch/trio_pcie_intfc_def.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_INTFC_DEF_H__
+#define __ARCH_TRIO_PCIE_INTFC_DEF_H__
+#define TRIO_PCIE_INTFC_MAC_INT_STS 0x0000
+#define TRIO_PCIE_INTFC_MAC_INT_STS__INT_LEVEL_MASK  0xf000
+#define TRIO_PCIE_INTFC_PORT_CONFIG 0x0018
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_DISABLED 0x0
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT 0x1
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC 0x2
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1 0x3
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1 0x4
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_XLINK 0x5
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_STREAM_X1 0x6
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_STREAM_X4 0x7
+#define TRIO_PCIE_INTFC_PORT_STATUS 0x0020
+#define TRIO_PCIE_INTFC_TX_FIFO_CTL 0x0050
+#endif /* !defined(__ARCH_TRIO_PCIE_INTFC_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_rc.h b/arch/tile/include/arch/trio_pcie_rc.h
new file mode 100644
index 0000000..4986628
--- /dev/null
+++ b/arch/tile/include/arch/trio_pcie_rc.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_RC_H__
+#define __ARCH_TRIO_PCIE_RC_H__
+
+#include <arch/abi.h>
+#include <arch/trio_pcie_rc_def.h>
+
+#ifndef __ASSEMBLER__
+
+// Device Capabilities Register.
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    // Max_Payload_Size Supported, writablethrough the MAC_STANDARD interface
+    uint_reg_t mps_sup                    : 3;
+    // This field is writable through the MAC_STANDARD interface.  However,
+    // Phantom Function is not  supported. Therefore, the application must
+    // not write any value other than 0x0 to this  field.
+    uint_reg_t phantom_function_supported : 2;
+    // This bit is writable through the MAC_STANDARD interface.
+    uint_reg_t ext_tag_field_supported    : 1;
+    // Reserved.
+    uint_reg_t __reserved_0               : 3;
+    // Endpoint L1 Acceptable Latency Must be 0x0 for non-Endpoint devices.
+    uint_reg_t l1_lat                     : 3;
+    // Undefined since PCI Express 1.1 (Was Attention Button Present for PCI
+    // Express 1.0a)
+    uint_reg_t r1                         : 1;
+    // Undefined since PCI Express 1.1 (Was Attention Indicator Present for
+    // PCI  Express 1.0a)
+    uint_reg_t r2                         : 1;
+    // Undefined since PCI Express 1.1 (Was Power Indicator Present for PCI
+    // Express 1.0a)
+    uint_reg_t r3                         : 1;
+    // Role-Based Error Reporting, writable through the MAC_STANDARD
+    // interface.  Required to be set for device compliant to 1.1  spec and
+    // later.
+    uint_reg_t rer                        : 1;
+    // Reserved.
+    uint_reg_t __reserved_1               : 2;
+    // Captured Slot Power Limit Value Upstream port only.
+    uint_reg_t slot_pwr_lim               : 8;
+    // Captured Slot Power Limit Scale Upstream port only.
+    uint_reg_t slot_pwr_scale             : 2;
+    // Reserved.
+    uint_reg_t __reserved_2               : 4;
+    // Endpoint L0s Acceptable LatencyMust be 0x0 for non-Endpoint devices.
+    uint_reg_t l0s_lat                    : 1;
+    // Reserved.
+    uint_reg_t __reserved_3               : 31;
+#else   // __BIG_ENDIAN__
+    uint_reg_t __reserved_3               : 31;
+    uint_reg_t l0s_lat                    : 1;
+    uint_reg_t __reserved_2               : 4;
+    uint_reg_t slot_pwr_scale             : 2;
+    uint_reg_t slot_pwr_lim               : 8;
+    uint_reg_t __reserved_1               : 2;
+    uint_reg_t rer                        : 1;
+    uint_reg_t r3                         : 1;
+    uint_reg_t r2                         : 1;
+    uint_reg_t r1                         : 1;
+    uint_reg_t l1_lat                     : 3;
+    uint_reg_t __reserved_0               : 3;
+    uint_reg_t ext_tag_field_supported    : 1;
+    uint_reg_t phantom_function_supported : 2;
+    uint_reg_t mps_sup                    : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_RC_DEVICE_CAP_t;
+
+// Device Control Register.
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    // Correctable Error Reporting Enable
+    uint_reg_t cor_err_ena      : 1;
+    // Non-Fatal Error Reporting Enable
+    uint_reg_t nf_err_ena       : 1;
+    // Fatal Error Reporting Enable
+    uint_reg_t fatal_err_ena    : 1;
+    // Unsupported Request Reporting Enable
+    uint_reg_t ur_ena           : 1;
+    // Relaxed orderring enable
+    uint_reg_t ro_ena           : 1;
+    // Max Payload Size
+    uint_reg_t max_payload_size : 3;
+    // Extended Tag Field Enable
+    uint_reg_t ext_tag          : 1;
+    // Phantom Function Enable
+    uint_reg_t ph_fn_ena        : 1;
+    // AUX Power PM Enable
+    uint_reg_t aux_pm_ena       : 1;
+    // Enable NoSnoop
+    uint_reg_t no_snoop         : 1;
+    // Max read request size
+    uint_reg_t max_read_req_sz  : 3;
+    // Reserved.
+    uint_reg_t __reserved       : 49;
+#else   // __BIG_ENDIAN__
+    uint_reg_t __reserved       : 49;
+    uint_reg_t max_read_req_sz  : 3;
+    uint_reg_t no_snoop         : 1;
+    uint_reg_t aux_pm_ena       : 1;
+    uint_reg_t ph_fn_ena        : 1;
+    uint_reg_t ext_tag          : 1;
+    uint_reg_t max_payload_size : 3;
+    uint_reg_t ro_ena           : 1;
+    uint_reg_t ur_ena           : 1;
+    uint_reg_t fatal_err_ena    : 1;
+    uint_reg_t nf_err_ena       : 1;
+    uint_reg_t cor_err_ena      : 1;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_RC_DEVICE_CONTROL_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_PCIE_RC_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_rc_def.h b/arch/tile/include/arch/trio_pcie_rc_def.h
new file mode 100644
index 0000000..74081a6
--- /dev/null
+++ b/arch/tile/include/arch/trio_pcie_rc_def.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_RC_DEF_H__
+#define __ARCH_TRIO_PCIE_RC_DEF_H__
+#define TRIO_PCIE_RC_DEVICE_CAP 0x0074
+#define TRIO_PCIE_RC_DEVICE_CONTROL 0x0078
+#define TRIO_PCIE_RC_DEVICE_ID_VEN_ID 0x0000
+#define TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT 16
+#define TRIO_PCIE_RC_REVISION_ID 0x0008
+#endif /* !defined(__ARCH_TRIO_PCIE_RC_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_shm.h b/arch/tile/include/arch/trio_shm.h
new file mode 100644
index 0000000..652bbb7
--- /dev/null
+++ b/arch/tile/include/arch/trio_shm.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+
+#ifndef __ARCH_TRIO_SHM_H__
+#define __ARCH_TRIO_SHM_H__
+
+#include <arch/abi.h>
+#include <arch/trio_shm_def.h>
+
+#ifndef __ASSEMBLER__
+//! TRIO DMA Descriptor.
+//! The TRIO DMA descriptor is written by software and consumed by hardware.
+//! It is used to specify the location of transaction data in the IO and Tile
+//! domains.
+
+__extension__
+typedef union
+{
+  struct
+  {
+    // Word 0
+
+#ifndef __BIG_ENDIAN__
+    //! Tile side virtual address.
+    int_reg_t va           : 42;
+    //! Encoded size of buffer used on push DMA when C=1:
+    //! 0 = 128 bytes
+    //! 1 = 256 bytes
+    //! 2 = 512 bytes
+    //! 3 = 1024 bytes
+    //! 4 = 1664 bytes
+    //! 5 = 4096 bytes
+    //! 6 = 10368 bytes
+    //! 7 = 16384 bytes
+    uint_reg_t bsz          : 3;
+    //! Chaining designation.  Always zero for pull DMA
+    //! 0 : Unchained buffer pointer
+    //! 1 : Chained buffer pointer.  Next buffer descriptor (e.g. VA) stored
+    //! in 1st 8-bytes in buffer.  For chained buffers, first 8-bytes of each
+    //! buffer contain the next buffer descriptor formatted exactly like a PDE
+    //! buffer descriptor.  This allows a chained PDE buffer to be sent using
+    //! push DMA.
+    uint_reg_t c            : 1;
+    //! Notification interrupt will be delivered when the transaction has
+    //! completed (all data has been read from or written to the Tile-side
+    //! buffer).
+    uint_reg_t notif        : 1;
+    //! When 0, the XSIZE field specifies the total byte count for the
+    //! transaction.  When 1, the XSIZE field is encoded as 2^(N+14) for N in
+    //! {0..6}:
+    //! 0 = 16KB
+    //! 1 = 32KB
+    //! 2 = 64KB
+    //! 3 = 128KB
+    //! 4 = 256KB
+    //! 5 = 512KB
+    //! 6 = 1MB
+    //! All other encodings of the XSIZE field are reserved when SMOD=1
+    uint_reg_t smod         : 1;
+    //! Total number of bytes to move for this transaction.   When SMOD=1,
+    //! this field is encoded - see SMOD description.
+    uint_reg_t xsize        : 14;
+    //! Reserved.
+    uint_reg_t __reserved_0 : 1;
+    //! Generation number.  Used to indicate a valid descriptor in ring.  When
+    //! a new descriptor is written into the ring, software must toggle this
+    //! bit.  The net effect is that the GEN bit being written into new
+    //! descriptors toggles each time the ring tail pointer wraps.
+    uint_reg_t gen          : 1;
+#else   // __BIG_ENDIAN__
+    uint_reg_t gen          : 1;
+    uint_reg_t __reserved_0 : 1;
+    uint_reg_t xsize        : 14;
+    uint_reg_t smod         : 1;
+    uint_reg_t notif        : 1;
+    uint_reg_t c            : 1;
+    uint_reg_t bsz          : 3;
+    int_reg_t va           : 42;
+#endif
+
+    // Word 1
+
+#ifndef __BIG_ENDIAN__
+    //! IO-side address
+    uint_reg_t io_address : 64;
+#else   // __BIG_ENDIAN__
+    uint_reg_t io_address : 64;
+#endif
+
+  };
+
+  //! Word access
+  uint_reg_t words[2];
+} TRIO_DMA_DESC_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_SHM_H__) */
diff --git a/arch/tile/include/arch/trio_shm_def.h b/arch/tile/include/arch/trio_shm_def.h
new file mode 100644
index 0000000..72a59c8
--- /dev/null
+++ b/arch/tile/include/arch/trio_shm_def.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_SHM_DEF_H__
+#define __ARCH_TRIO_SHM_DEF_H__
+#endif /* !defined(__ARCH_TRIO_SHM_DEF_H__) */
diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h
new file mode 100644
index 0000000..3ef5642
--- /dev/null
+++ b/arch/tile/include/gxio/iorpc_trio.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#ifndef __GXIO_TRIO_LINUX_RPC_H__
+#define __GXIO_TRIO_LINUX_RPC_H__
+
+#include <hv/iorpc.h>
+
+#include <hv/drv_trio_intf.h>
+#include <gxio/trio.h>
+#include <gxio/kiorpc.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#define GXIO_TRIO_OP_ALLOC_ASIDS       IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+#define GXIO_TRIO_OP_REGISTER_PAGE_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x1401)
+#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402)
+#define GXIO_TRIO_OP_INIT_MEMORY_MAP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1403)
+#define GXIO_TRIO_OP_READ_ISR_STATUS_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404)
+#define GXIO_TRIO_OP_WRITE_ISR_STATUS_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1405)
+#define GXIO_TRIO_OP_ENABLE_MMI        IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1406)
+#define GXIO_TRIO_OP_MASK_MMI_AUX      IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1407)
+#define GXIO_TRIO_OP_UNMASK_MMI_AUX    IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1408)
+#define GXIO_TRIO_OP_READ_MMI_BITS_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1409)
+#define GXIO_TRIO_OP_WRITE_MMI_BITS_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140a)
+#define GXIO_TRIO_OP_ALLOC_SCATTER_QUEUES IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140b)
+#define GXIO_TRIO_OP_INIT_SCATTER_QUEUE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140c)
+#define GXIO_TRIO_OP_ENABLE_SQI        IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x140d)
+#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e)
+#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f)
+#define GXIO_TRIO_OP_ALLOC_PUSH_DMA_RING IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1410)
+#define GXIO_TRIO_OP_ALLOC_PULL_DMA_RING IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1411)
+#define GXIO_TRIO_OP_INIT_PUSH_DMA_RING_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x1412)
+#define GXIO_TRIO_OP_ENABLE_PUSH_DMA_ISR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1413)
+#define GXIO_TRIO_OP_INIT_PULL_DMA_RING_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x1414)
+#define GXIO_TRIO_OP_ENABLE_PULL_DMA_ISR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1415)
+#define GXIO_TRIO_OP_TRIGGER_HOST_INTERRUPT_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1416)
+#define GXIO_TRIO_OP_REGISTER_CLIENT_MEMORY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417)
+#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418)
+#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1419)
+#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a)
+#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141b)
+#define GXIO_TRIO_OP_CONFIG_CHAR_INTR  IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141c)
+#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d)
+#define GXIO_TRIO_OP_FORCE_LINK_UP     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_GET_MMIO_BASE     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
+#define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
+
+int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+			  unsigned int first, unsigned int flags);
+
+int gxio_trio_register_page_aux(gxio_trio_context_t * context, void *page_va,
+				size_t page_size, unsigned int page_flags,
+				unsigned int stack, uint64_t vpn);
+
+int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
+				unsigned int count, unsigned int first,
+				unsigned int flags);
+
+int gxio_trio_init_memory_map_aux(gxio_trio_context_t * context,
+				  unsigned int map, uint64_t vpn, uint64_t size,
+				  unsigned int asid, unsigned int mac,
+				  uint64_t bus_address,
+				  unsigned int order_mode);
+
+int gxio_trio_read_isr_status_aux(gxio_trio_context_t * context,
+				  unsigned int vec_num);
+
+int gxio_trio_write_isr_status_aux(gxio_trio_context_t * context,
+				   unsigned int vec_num,
+				   uint32_t bits_to_clear);
+
+int gxio_trio_enable_mmi(gxio_trio_context_t * context, int bind_x, int bind_y,
+			 int bind_ipi, int bind_event, unsigned int map,
+			 unsigned int mode);
+
+int gxio_trio_mask_mmi_aux(gxio_trio_context_t * context, unsigned int map,
+			   unsigned int mask);
+
+int gxio_trio_unmask_mmi_aux(gxio_trio_context_t * context, unsigned int map,
+			     unsigned int mask);
+
+int gxio_trio_read_mmi_bits_aux(gxio_trio_context_t * context,
+				unsigned int map);
+
+int gxio_trio_write_mmi_bits_aux(gxio_trio_context_t * context,
+				 unsigned int map, unsigned int bits,
+				 unsigned int mode);
+
+int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context,
+				   unsigned int count, unsigned int first,
+				   unsigned int flags);
+
+int gxio_trio_init_scatter_queue_aux(gxio_trio_context_t * context,
+				     unsigned int queue, uint64_t size,
+				     unsigned int asid, unsigned int mac,
+				     uint64_t bus_address,
+				     unsigned int order_mode);
+
+int gxio_trio_enable_sqi(gxio_trio_context_t * context, int bind_x, int bind_y,
+			 int bind_ipi, int bind_event, unsigned int queue);
+
+int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
+				unsigned int count, unsigned int first,
+				unsigned int flags);
+
+int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
+				  unsigned int pio_region, unsigned int mac,
+				  uint32_t bus_address_hi, unsigned int flags);
+
+int gxio_trio_alloc_push_dma_ring(gxio_trio_context_t * context,
+				  unsigned int count, unsigned int first,
+				  unsigned int flags);
+
+int gxio_trio_alloc_pull_dma_ring(gxio_trio_context_t * context,
+				  unsigned int count, unsigned int first,
+				  unsigned int flags);
+
+int gxio_trio_init_push_dma_ring_aux(gxio_trio_context_t * context,
+				     void *mem_va, size_t mem_size,
+				     unsigned int mem_flags, unsigned int ring,
+				     unsigned int mac, unsigned int asid,
+				     unsigned int flags);
+
+int gxio_trio_enable_push_dma_isr(gxio_trio_context_t * context, int bind_x,
+				  int bind_y, int bind_ipi, int bind_event,
+				  unsigned int ring);
+
+int gxio_trio_init_pull_dma_ring_aux(gxio_trio_context_t * context,
+				     void *mem_va, size_t mem_size,
+				     unsigned int mem_flags, unsigned int ring,
+				     unsigned int mac, unsigned int asid,
+				     unsigned int flags);
+
+int gxio_trio_enable_pull_dma_isr(gxio_trio_context_t * context, int bind_x,
+				  int bind_y, int bind_ipi, int bind_event,
+				  unsigned int ring);
+
+int gxio_trio_trigger_host_interrupt_aux(gxio_trio_context_t * context,
+					 unsigned int mac,
+					 unsigned long msix_addr,
+					 unsigned int msix_data);
+
+int gxio_trio_register_client_memory(gxio_trio_context_t * context,
+				     unsigned int iotlb, HV_PTE pte,
+				     unsigned int flags);
+
+int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
+				      unsigned int map, unsigned long va,
+				      uint64_t size, unsigned int asid,
+				      unsigned int mac, uint64_t bus_address,
+				      unsigned int node,
+				      unsigned int order_mode);
+
+int gxio_trio_get_port_property(gxio_trio_context_t * context,
+				struct pcie_trio_ports_property *trio_ports);
+
+int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
+				 int inter_y, int inter_ipi, int inter_event,
+				 unsigned int mac, unsigned int intx);
+
+int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
+			      int inter_y, int inter_ipi, int inter_event,
+			      unsigned int mac, unsigned int mem_map,
+			      uint64_t mem_map_base, uint64_t mem_map_limit,
+			      unsigned int asid);
+
+int gxio_trio_config_char_intr(gxio_trio_context_t * context, int inter_x,
+			       int inter_y, int inter_ipi, int inter_event,
+			       unsigned int mac, unsigned int mem_map,
+			       unsigned int push_dma_ring,
+			       unsigned int pull_dma_ring,
+			       pcie_stream_intr_config_sel_t conf);
+
+int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
+			  uint16_t mrs, unsigned int mac);
+
+int gxio_trio_force_link_up(gxio_trio_context_t * context, unsigned int mac);
+
+int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base);
+
+int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
+				unsigned long offset, unsigned long size);
+
+#endif /* !__GXIO_TRIO_LINUX_RPC_H__ */
diff --git a/arch/tile/include/gxio/trio.h b/arch/tile/include/gxio/trio.h
new file mode 100644
index 0000000..5e55fcc
--- /dev/null
+++ b/arch/tile/include/gxio/trio.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ *
+ * An API for allocating, configuring, and manipulating TRIO hardware
+ * resources
+ */
+
+/*
+ *
+ * The TILE-Gx TRIO shim provides connections to external devices via
+ * PCIe or other transaction IO standards.  The gxio_trio_ API,
+ * declared in <gxio/trio.h>, allows applications to allocate and
+ * configure TRIO IO resources like DMA command rings, memory map
+ * windows, and device interrupts.  The following sections introduce
+ * the various components of the API.  We strongly recommend reading
+ * the TRIO section of the IO Device Guide (UG404) before working with
+ * this API.
+ *
+ * @section trio__ingress TRIO Ingress Hardware Resources
+ *
+ * The TRIO ingress hardware is responsible for examining incoming
+ * PCIe or StreamIO packets and choosing a processing mechanism based
+ * on the packets' bus address.  The gxio_trio_ API can be used to
+ * configure different handlers for different ranges of bus address
+ * space.  The user can configure "mapped memory" and "scatter queue"
+ * regions to match incoming packets within 4kB-aligned ranges of bus
+ * addresses.  Each range specifies a different set of mapping
+ * parameters to be applied when handling the ingress packet.  The
+ * following sections describe how to work with MapMem and scatter
+ * queue regions.
+ *
+ * @subsection trio__mapmem TRIO MapMem Regions
+ *
+ * TRIO mapped memory (or MapMem) regions allow the user to map
+ * incoming read and write requests directly to the application's
+ * memory space.  MapMem regions are allocated via
+ * gxio_trio_alloc_memory_maps().  Given an integer MapMem number,
+ * applications can use gxio_trio_init_memory_map() to specify the
+ * range of bus addresses that will match the region and the range of
+ * virtual addresses to which those packets will be applied.
+ *
+ * As with many other gxio APIs, the programmer must be sure to
+ * register memory pages that will be used with MapMem regions.  Pages
+ * can be registered with TRIO by allocating an ASID (address space
+ * identifier) and then using gxio_trio_register_page() to register up to
+ * 16 pages with the hardware.  The initialization functions for
+ * resources that require registered memory (MapMem, scatter queues,
+ * push DMA, and pull DMA) then take an 'asid' parameter in order to
+ * configure which set of registered pages is used by each resource.
+ *
+ * @subsection trio__scatter_queue TRIO Scatter Queues
+ *
+ * The TRIO shim's scatter queue regions allow users to dynamically
+ * map buffers from a large address space into a small range of bus
+ * addresses.  This is particularly helpful for PCIe endpoint devices,
+ * where the host generally limits the size of BARs to tens of
+ * megabytes.
+ *
+ * Each scatter queue consists of a memory map region, a queue of
+ * tile-side buffer VAs to be mapped to that region, and a bus-mapped
+ * "doorbell" register that the remote endpoint can write to trigger a
+ * dequeue of the current buffer VA, thus swapping in a new buffer.
+ * The VAs pushed onto a scatter queue must be 4kB aligned, so
+ * applications may need to use higher-level protocols to inform
+ * remote entities that they should apply some additional, sub-4kB
+ * offset when reading or writing the scatter queue region.  For more
+ * information, see the IO Device Guide (UG404).
+ *
+ * @section trio__egress TRIO Egress Hardware Resources
+ *
+ * The TRIO shim supports two mechanisms for egress packet generation:
+ * programmed IO (PIO) and push/pull DMA.  PIO allows applications to
+ * create MMIO mappings for PCIe or StreamIO address space, such that
+ * the application can generate word-sized read or write transactions
+ * by issuing load or store instructions.  Push and pull DMA are tuned
+ * for larger transactions; they use specialized hardware engines to
+ * transfer large blocks of data at line rate.
+ *
+ * @subsection trio__pio TRIO Programmed IO
+ *
+ * Programmed IO allows applications to create MMIO mappings for PCIe
+ * or StreamIO address space.  The hardware PIO regions support access
+ * to PCIe configuration, IO, and memory space, but the gxio_trio API
+ * only supports memory space accesses.  PIO regions are allocated
+ * with gxio_trio_alloc_pio_regions() and initialized via
+ * gxio_trio_init_pio_region().  Once a region is bound to a range of
+ * bus address via the initialization function, the application can
+ * use gxio_trio_map_pio_region() to create MMIO mappings from its VA
+ * space onto the range of bus addresses supported by the PIO region.
+ *
+ * @subsection trio_dma TRIO Push and Pull DMA
+ *
+ * The TRIO push and pull DMA engines allow users to copy blocks of
+ * data between application memory and the bus.  Push DMA generates
+ * write packets that copy from application memory to the bus and pull
+ * DMA generates read packets that copy from the bus into application
+ * memory.  The DMA engines are managed via an API that is very
+ * similar to the mPIPE eDMA interface.  For a detailed explanation of
+ * the eDMA queue API, see @ref gxio_mpipe_wrappers.
+ *
+ * Push and pull DMA queues are allocated via
+ * gxio_trio_alloc_push_dma_ring() / gxio_trio_alloc_pull_dma_ring().
+ * Once allocated, users generally use a ::gxio_trio_dma_queue_t
+ * object to manage the queue, providing easy wrappers for reserving
+ * command slots in the DMA command ring, filling those slots, and
+ * waiting for commands to complete.  DMA queues can be initialized
+ * via gxio_trio_init_push_dma_queue() or
+ * gxio_trio_init_pull_dma_queue().
+ *
+ * See @ref trio/push_dma/app.c for an example of how to use push DMA.
+ *
+ * @section trio_shortcomings Plans for Future API Revisions
+ *
+ * The API and simulation framework is incomplete.  Future features
+ * include:
+ *
+ * - Support for larger page sizes.  Each hardware IOTLB can only map
+ * 16 pages at a time, so applications are currently limited to 16 *
+ * 16MB = 256MB of packet memory.  Larger page sizes will allow
+ * applications to map arbitrary amounts of packet memory.
+ *
+ * - Support for reset and deallocation of resources.
+ *
+ * - Support for pull DMA.
+ *
+ * - Support for interrupt regions and user-space interrupt delivery.
+ *
+ * - Support for getting BAR mappings and reserving regions of BAR
+ *   address space.
+ */
+#ifndef _GXIO_TRIO_H_
+#define _GXIO_TRIO_H_
+
+#include "common.h"
+#include "dma_queue.h"
+
+#include <arch/trio_constants.h>
+#include <arch/trio.h>
+#include <arch/trio_pcie_intfc.h>
+#include <arch/trio_pcie_rc.h>
+#include <arch/trio_shm.h>
+#include <hv/drv_trio_intf.h>
+#include <hv/iorpc.h>
+
+/* A context object used to manage TRIO hardware resources. */
+typedef struct {
+
+  /* File descriptor for calling up to Linux (and thus the HV). */
+	int fd;
+
+  /* The VA at which the MAC MMIO registers are mapped. */
+	char *mmio_base_mac;
+
+  /* The VA at which the PIO config space are mapped for each PCIe MAC.
+      Gx36 has max 3 PCIe MACs per TRIO shim. */
+	char *mmio_base_pio_cfg[TILEGX_TRIO_PCIES];
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+  /* Index of the shared PIO region for PCI config access. */
+	int pio_cfg_index;
+#else
+  /* Index of the PIO region for PCI config access per MAC. */
+	int pio_cfg_index[TILEGX_TRIO_PCIES];
+#endif
+
+  /*  The VA at which the push DMA MMIO registers are mapped. */
+	char *mmio_push_dma[TRIO_NUM_PUSH_DMA_RINGS];
+
+  /*  The VA at which the pull DMA MMIO registers are mapped. */
+	char *mmio_pull_dma[TRIO_NUM_PUSH_DMA_RINGS];
+
+  /* Application space ID. */
+	unsigned int asid;
+
+} gxio_trio_context_t;
+
+/* Command descriptor for push or pull DMA. */
+typedef TRIO_DMA_DESC_t gxio_trio_dma_desc_t;
+
+/* A convenient, thread-safe interface to an eDMA ring. */
+typedef struct {
+
+  /* State object for tracking head and tail pointers. */
+	__gxio_dma_queue_t dma_queue;
+
+  /* The ring entries. */
+	gxio_trio_dma_desc_t *dma_descs;
+
+  /* The number of entries minus one. */
+	unsigned long mask_num_entries;
+
+  /* The log2() of the number of entries. */
+	unsigned int log2_num_entries;
+
+} gxio_trio_dma_queue_t;
+
+/* Initialize a TRIO context.
+ *
+ * This function allocates a TRIO "service domain" and maps the MMIO
+ * registers into the the caller's VA space.
+ *
+ * @param trio_index Which TRIO shim; Gx36 must pass 0.
+ * @param context Context object to be initialized.
+ */
+extern int
+gxio_trio_init(gxio_trio_context_t * context, unsigned int trio_index);
+
+/* This indicates that an ASID hasn't been allocated. */
+#define GXIO_ASID_NULL -1
+
+/* Ordering modes for map memory regions and scatter queue regions. */
+typedef enum gxio_trio_order_mode_e {
+  /* Writes are not ordered.  Reads always wait for previous writes. */
+	GXIO_TRIO_ORDER_MODE_UNORDERED =
+	    TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_UNORDERED,
+  /* Both writes and reads wait for previous transactions to complete. */
+	GXIO_TRIO_ORDER_MODE_STRICT = TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_STRICT,
+  /* Writes are ordered unless the incoming packet has the
+      relaxed-ordering attributes set. */
+	GXIO_TRIO_ORDER_MODE_OBEY_PACKET =
+	    TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_REL_ORD
+} gxio_trio_order_mode_t;
+
+/* Initialize a memory mapping region.
+ *
+ * @param context An initialized TRIO context.
+ * @param map A Memory map region allocated by gxio_trio_alloc_memory_map().
+ * @param target_mem VA of backing memory, should be registered via
+ *   gxio_trio_register_page() and aligned to 4kB.
+ * @param target_size Length of the memory mapping, must be a multiple
+ * of 4kB.
+ * @param asid ASID to be used for Tile-side address translation.
+ * @param mac MAC number.
+ * @param bus_address Bus address at which the mapping starts.
+ * @param order_mode Memory ordering mode for this mapping.
+ * @return Zero on success, else ::GXIO_TRIO_ERR_BAD_MEMORY_MAP,
+ * GXIO_TRIO_ERR_BAD_ASID, or ::GXIO_TRIO_ERR_BAD_BUS_RANGE.
+ */
+extern int
+gxio_trio_init_memory_map(gxio_trio_context_t * context, unsigned int map,
+			  void *target_mem, size_t target_size,
+			  unsigned int asid,
+			  unsigned int mac,
+			  uint64_t bus_address,
+			  gxio_trio_order_mode_t order_mode);
+
+/* Flags that can be passed to resource allocation functions. */
+enum gxio_trio_alloc_flags_e {
+	GXIO_TRIO_ALLOC_FIXED = HV_TRIO_ALLOC_FIXED,
+};
+
+/* Flags that can be passed to memory registration functions. */
+enum gxio_trio_mem_flags_e {
+  /* Do not fill L3 when writing, and invalidate lines upon egress. */
+	GXIO_TRIO_MEM_FLAG_NT_HINT = IORPC_MEM_BUFFER_FLAG_NT_HINT,
+
+  /* L3 cache fills should only populate IO cache ways. */
+	GXIO_TRIO_MEM_FLAG_IO_PIN = IORPC_MEM_BUFFER_FLAG_IO_PIN,
+};
+
+/* Flag indicating a request generator uses a special traffic
+    class. */
+#define GXIO_TRIO_FLAG_TRAFFIC_CLASS(N) HV_TRIO_FLAG_TC(N)
+
+/* Flag indicating a request generator uses a virtual function
+    number. */
+#define GXIO_TRIO_FLAG_VFUNC(N) HV_TRIO_FLAG_VFUNC(N)
+
+/*****************************************************************
+ *                       Memory Registration                      *
+ ******************************************************************/
+
+/* Allocate Application Space Identifiers (ASIDs).  Each ASID can
+ * register up to 16 page translations.  ASIDs are used by memory map
+ * regions, scatter queues, and DMA queues to translate application
+ * VAs into memory system PAs.
+ *
+ * @param context An initialized TRIO context.
+ * @param count Number of ASIDs required.
+ * @param first Index of first ASID if ::GXIO_TRIO_ALLOC_FIXED flag
+ *   is set, otherwise ignored.
+ * @param flags Flag bits, including bits from ::gxio_trio_alloc_flags_e.
+ * @return Index of first ASID, or ::GXIO_TRIO_ERR_NO_ASID if allocation
+ *   failed.
+ */
+extern int
+gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+		      unsigned int first, unsigned int flags);
+
+#endif /* ! _GXIO_TRIO_H_ */
diff --git a/arch/tile/include/hv/drv_trio_intf.h b/arch/tile/include/hv/drv_trio_intf.h
new file mode 100644
index 0000000..18e8704
--- /dev/null
+++ b/arch/tile/include/hv/drv_trio_intf.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * Interface definitions for the trio driver.
+ */
+
+#ifndef _SYS_HV_DRV_TRIO_INTF_H
+#define _SYS_HV_DRV_TRIO_INTF_H
+
+#include <arch/trio.h>
+
+/** The vendor ID for all Tilera processors. */
+#define TILERA_VENDOR_ID 0x1a41
+
+/** The device ID for the Gx36 processor. */
+#define TILERA_GX36_DEV_ID 0x0200
+
+/** Device ID for our internal bridge when running as RC. */
+#define TILERA_GX36_RC_DEV_ID 0x2000
+
+/** Maximum number of TRIO interfaces. */
+#define TILEGX_NUM_TRIO         2
+
+/** Gx36 has max 3 PCIe MACs per TRIO interface. */
+#define TILEGX_TRIO_PCIES       3
+
+/** Specify port properties for a PCIe MAC. */
+struct pcie_port_property
+{
+  /** If true, the link can be configured in PCIe root complex mode. */
+  uint8_t allow_rc: 1;
+
+  /** If true, the link can be configured in PCIe endpoint mode. */
+  uint8_t allow_ep: 1;
+
+  /** If true, the link can be configured in StreamIO mode. */
+  uint8_t allow_sio: 1;
+
+  /** If true, the link is allowed to support 1-lane operation. Software
+   *  will not consider it an error if the link comes up as a x1 link. */
+  uint8_t allow_x1: 1;
+
+  /** If true, the link is allowed to support 2-lane operation. Software
+   *  will not consider it an error if the link comes up as a x2 link. */
+  uint8_t allow_x2: 1;
+
+  /** If true, the link is allowed to support 4-lane operation. Software
+   *  will not consider it an error if the link comes up as a x4 link. */
+  uint8_t allow_x4: 1;
+
+  /** If true, the link is allowed to support 8-lane operation. Software
+   *  will not consider it an error if the link comes up as a x8 link. */
+  uint8_t allow_x8: 1;
+
+  /** Reserved. */
+  uint8_t reserved: 1;
+
+};
+
+/** Configurations can be issued to configure a char stream interrupt. */
+typedef enum pcie_stream_intr_config_sel_e
+{
+  /** Interrupt configuration for memory map regions. */
+  MEM_MAP_SEL,
+
+  /** Interrupt configuration for push DMAs. */
+  PUSH_DMA_SEL,
+
+  /** Interrupt configuration for pull DMAs. */
+  PULL_DMA_SEL,
+}
+pcie_stream_intr_config_sel_t;
+
+
+/** The mmap file offset (PA) of the TRIO config region. */
+#define HV_TRIO_CONFIG_OFFSET                                        \
+  ((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_CFG <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT)
+
+/** The maximum size of the TRIO config region. */
+#define HV_TRIO_CONFIG_SIZE                                 \
+  (1ULL << TRIO_CFG_REGION_ADDR__REGION_SHIFT)
+
+/** Size of the config region mapped into client. We can't use
+ *  TRIO_MMIO_ADDRESS_SPACE__OFFSET_WIDTH because it
+ *  will require the kernel to allocate 4GB VA space
+ *  from the VMALLOC region which has a total range
+ *  of 4GB.
+ */
+#define HV_TRIO_CONFIG_IOREMAP_SIZE                            \
+  ((uint64_t) 1 << TRIO_CFG_REGION_ADDR__PROT_SHIFT)
+
+/** The mmap file offset (PA) of a scatter queue region. */
+#define HV_TRIO_SQ_OFFSET(queue)                                        \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_MAP_SQ <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((queue) << TRIO_MAP_SQ_REGION_ADDR__SQ_SEL_SHIFT))
+
+/** The maximum size of a scatter queue region. */
+#define HV_TRIO_SQ_SIZE                                 \
+  (1ULL << TRIO_MAP_SQ_REGION_ADDR__SQ_SEL_SHIFT)
+
+
+/** The "hardware MMIO region" of the first PIO region. */
+#define HV_TRIO_FIRST_PIO_REGION 8
+
+/** The mmap file offset (PA) of a PIO region. */
+#define HV_TRIO_PIO_OFFSET(region)                           \
+  (((unsigned long long)(region) + HV_TRIO_FIRST_PIO_REGION) \
+   << TRIO_PIO_REGIONS_ADDR__REGION_SHIFT)
+
+/** The maximum size of a PIO region. */
+#define HV_TRIO_PIO_SIZE (1ULL << TRIO_PIO_REGIONS_ADDR__ADDR_WIDTH)
+
+
+/** The mmap file offset (PA) of a push DMA region. */
+#define HV_TRIO_PUSH_DMA_OFFSET(ring)                                   \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_PUSH_DMA << \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((ring) << TRIO_PUSH_DMA_REGION_ADDR__RING_SEL_SHIFT))
+
+/** The mmap file offset (PA) of a pull DMA region. */
+#define HV_TRIO_PULL_DMA_OFFSET(ring)                                   \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_PULL_DMA << \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((ring) << TRIO_PULL_DMA_REGION_ADDR__RING_SEL_SHIFT))
+
+/** The maximum size of a DMA region. */
+#define HV_TRIO_DMA_REGION_SIZE                         \
+  (1ULL << TRIO_PUSH_DMA_REGION_ADDR__RING_SEL_SHIFT)
+
+
+/** The mmap file offset (PA) of a Mem-Map interrupt region. */
+#define HV_TRIO_MEM_MAP_INTR_OFFSET(map)                                 \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_MAP_MEM <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((map) << TRIO_MAP_MEM_REGION_ADDR__MAP_SEL_SHIFT))
+
+/** The maximum size of a Mem-Map interrupt region. */
+#define HV_TRIO_MEM_MAP_INTR_SIZE                                 \
+  (1ULL << TRIO_MAP_MEM_REGION_ADDR__MAP_SEL_SHIFT)
+
+
+/** A flag bit indicating a fixed resource allocation. */
+#define HV_TRIO_ALLOC_FIXED 0x01
+
+/** TRIO requires that all mappings have 4kB aligned start addresses. */
+#define HV_TRIO_PAGE_SHIFT 12
+
+/** TRIO requires that all mappings have 4kB aligned start addresses. */
+#define HV_TRIO_PAGE_SIZE (1ull << HV_TRIO_PAGE_SHIFT)
+
+
+
+/* Specify all PCIe port properties for a TRIO. */
+struct pcie_trio_ports_property
+{
+  struct pcie_port_property ports[TILEGX_TRIO_PCIES];
+};
+
+/* Flags indicating traffic class. */
+#define HV_TRIO_FLAG_TC_SHIFT 4
+#define HV_TRIO_FLAG_TC_RMASK 0xf
+#define HV_TRIO_FLAG_TC(N) \
+  ((((N) & HV_TRIO_FLAG_TC_RMASK) + 1) << HV_TRIO_FLAG_TC_SHIFT)
+
+/* Flags indicating virtual functions. */
+#define HV_TRIO_FLAG_VFUNC_SHIFT 8
+#define HV_TRIO_FLAG_VFUNC_RMASK 0xff
+#define HV_TRIO_FLAG_VFUNC(N) \
+  ((((N) & HV_TRIO_FLAG_VFUNC_RMASK) + 1) << HV_TRIO_FLAG_VFUNC_SHIFT)
+
+
+/* Flag indicating an ordered PIO region. */
+#define HV_TRIO_PIO_FLAG_ORDERED (1 << 16)
+
+/* Flags indicating special types of PIO regions. */
+#define HV_TRIO_PIO_FLAG_SPACE_SHIFT 17
+#define HV_TRIO_PIO_FLAG_SPACE_MASK (0x3 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+#define HV_TRIO_PIO_FLAG_CONFIG_SPACE (0x1 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+#define HV_TRIO_PIO_FLAG_IO_SPACE (0x2 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+
+
+#endif /* _SYS_HV_DRV_TRIO_INTF_H */
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-04-07 20:53 [PATCH 0/3] arch/tile: provide PCIe support for tilegx Chris Metcalf
  2012-04-07 19:58 ` [PATCH 2/3] arch/tile: mark TILEGX as not EXPERIMENTAL Chris Metcalf
  2012-04-07 20:53 ` [PATCH 1/3] arch/tile: provide kernel support for the tilegx TRIO shim Chris Metcalf
@ 2012-04-07 21:10 ` Chris Metcalf
  2012-04-09 13:59   ` Arnd Bergmann
                     ` (2 more replies)
  2 siblings, 3 replies; 19+ messages in thread
From: Chris Metcalf @ 2012-04-07 21:10 UTC (permalink / raw)
  To: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Arnd Bergmann, Jiri Kosina,
	Joe Perches, David Howells

This change implements PCIe root complex support for tilegx using
the kernel support layer for accessing the TRIO hardware shim.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
---
 arch/tile/Kconfig           |    3 +
 arch/tile/include/asm/pci.h |   97 +++-
 arch/tile/kernel/Makefile   |    4 +
 arch/tile/kernel/pci_gx.c   | 1597 +++++++++++++++++++++++++++++++++++++++++++
 arch/tile/kernel/setup.c    |    6 +
 arch/tile/mm/pgtable.c      |    7 -
 drivers/pci/quirks.c        |    6 +-
 7 files changed, 1700 insertions(+), 20 deletions(-)
 create mode 100644 arch/tile/kernel/pci_gx.c

diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index d51b479..6d6b9a6 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -355,6 +355,9 @@ config PCI
 	default y
 	select PCI_DOMAINS
 	select GENERIC_PCI_IOMAP
+	select TILE_GXIO_TRIO if TILEGX
+	select ARCH_SUPPORTS_MSI if TILEGX
+	select PCI_MSI if TILEGX
 	---help---
 	  Enable PCI root complex support, so PCIe endpoint devices can
 	  be attached to the Tile chip.  Many, but not all, PCI devices
diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h
index 5d5a635..47f8ce6 100644
--- a/arch/tile/include/asm/pci.h
+++ b/arch/tile/include/asm/pci.h
@@ -16,8 +16,11 @@
 #define _ASM_TILE_PCI_H
 
 #include <linux/pci.h>
+#include <linux/numa.h>
 #include <asm-generic/pci_iomap.h>
 
+#ifndef __tilegx__
+
 /*
  * Structure of a PCI controller (host bridge)
  */
@@ -41,6 +44,90 @@ struct pci_controller {
 };
 
 /*
+ * This flag tells if the platform is TILEmpower that needs
+ * special configuration for the PLX switch chip.
+ */
+extern int tile_plx_gen1;
+
+static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
+
+#define	TILE_NUM_PCIE	2
+
+#else
+
+#include <asm/page.h>
+#include <gxio/trio.h>
+
+/**
+ * We reserve the hugepage-size address range at the top of the 64-bit address
+ * space to serve as the PCI window, emulating the BAR0 space of an endpoint
+ * device. This window is used by the chip-to-chip applications running on
+ * the RC node. The reason for carving out this window is that Mem-Maps that
+ * back up this window will not overlap with those that map the real physical
+ * memory.
+ */
+#define PCIE_HOST_BAR0_SIZE		HPAGE_SIZE
+#define PCIE_HOST_BAR0_START		HPAGE_MASK
+
+/**
+ * The first PAGE_SIZE of the above "BAR" window is mapped to the
+ * gxpci_host_regs structure.
+ */
+#define PCIE_HOST_REGS_SIZE		PAGE_SIZE
+
+/*
+ * This is the PCI address where the Mem-Map interrupt regions start.
+ * We use the 2nd to the last huge page of the 64-bit address space.
+ * The last huge page is used for the rootcomplex "bar", for C2C purpose.
+ */
+#define	MEM_MAP_INTR_REGIONS_BASE	(HPAGE_MASK - HPAGE_SIZE)
+
+/*
+ * Each Mem-Map interrupt region occupies 4KB.
+ */
+#define	MEM_MAP_INTR_REGION_SIZE	(1<< TRIO_MAP_MEM_LIM__ADDR_SHIFT)
+
+/*
+ * Structure of a PCI controller (host bridge) on Gx.
+ */
+struct pci_controller {
+
+	/* Pointer back to the TRIO that this PCIe port is connected to. */
+	gxio_trio_context_t *trio;
+	int mac;		/* PCIe mac index on the TRIO shim */
+	int trio_index;		/* Index of TRIO shim that contains the MAC. */
+
+	int pio_mem_index;	/* PIO region index for memory access */
+
+	/*
+	 * Mem-Map regions for all the memory controllers so that Linux can
+	 * map all of its physical memory space to the PCI bus.
+	 */
+	int mem_maps[MAX_NUMNODES];
+
+	int index;		/* PCI domain number */
+	struct pci_bus *root_bus;
+
+	int last_busno;
+
+	struct pci_ops *ops;
+
+	/* Table that maps the INTx numbers to Linux irq numbers. */
+	int irq_intx_table[4];
+
+	/* Address ranges that are routed to this controller/bridge. */
+	struct resource mem_resources[3];
+};
+
+extern struct pci_controller *pci_controllers;
+extern gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
+
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+#endif /* __tilegx__ */
+
+/*
  * The hypervisor maps the entirety of CPA-space as bus addresses, so
  * bus addresses are physical addresses.  The networking and block
  * device layers use this boolean for bounce buffer decisions.
@@ -50,12 +137,8 @@ struct pci_controller {
 int __devinit tile_pci_init(void);
 int __devinit pcibios_init(void);
 
-static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
-
 void __devinit pcibios_fixup_bus(struct pci_bus *bus);
 
-#define	TILE_NUM_PCIE	2
-
 #define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index)
 
 /*
@@ -79,12 +162,6 @@ static inline int pcibios_assign_all_busses(void)
 #define PCIBIOS_MIN_MEM		0
 #define PCIBIOS_MIN_IO		0
 
-/*
- * This flag tells if the platform is TILEmpower that needs
- * special configuration for the PLX switch chip.
- */
-extern int tile_plx_gen1;
-
 /* Use any cpu for PCI. */
 #define cpumask_of_pcibus(bus) cpu_online_mask
 
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile
index f19116d..e09281f 100644
--- a/arch/tile/kernel/Makefile
+++ b/arch/tile/kernel/Makefile
@@ -14,4 +14,8 @@ obj-$(CONFIG_SMP)		+= smpboot.o smp.o tlb.o
 obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel_$(BITS).o
+ifdef CONFIG_TILEGX
+obj-$(CONFIG_PCI)		+= pci_gx.o
+else
 obj-$(CONFIG_PCI)		+= pci.o
+endif
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
new file mode 100644
index 0000000..6d44947
--- /dev/null
+++ b/arch/tile/kernel/pci_gx.c
@@ -0,0 +1,1597 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mmzone.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/byteorder.h>
+
+#include <gxio/iorpc_globals.h>
+#include <gxio/kiorpc.h>
+#include <gxio/trio.h>
+#include <gxio/iorpc_trio.h>
+#include <hv/drv_trio_intf.h>
+
+#include <arch/sim.h>
+
+/*
+ * Initialization flow and process
+ * -------------------------------
+ *
+ * This files containes the routines to search for PCI buses,
+ * enumerate the buses, and configure any attached devices.
+ *
+ * There are two entry points here:
+ * 1) tile_pci_init
+ *    This sets up the pci_controller structs, and opens the
+ *    FDs to the hypervisor.  This is called from setup_arch() early
+ *    in the boot process.
+ * 2) pcibios_init
+ *    This probes the PCI bus(es) for any attached hardware.  It's
+ *    called by subsys_initcall.  All of the real work is done by the
+ *    generic Linux PCI layer.
+ *
+ */
+
+static int __devinitdata pci_probe = 1;
+
+/* Information on the PCIe RC ports configuration. */
+static int __initdata pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+
+#ifndef GX_FPGA
+/* Array of the PCIe ports configuration info obtained from the BIB. */
+struct pcie_port_property pcie_ports[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+#endif
+
+/* All drivers share the TRIO contexts defined here. */
+gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
+
+/* Pointer to an array of PCIe RC controllers. */
+struct pci_controller *pci_controllers;
+int num_rc_controllers;
+static int num_ep_controllers;
+
+static struct pci_ops tile_cfg_ops;
+
+/* Mask of CPUs that should receive PCIe interrupts. */
+static struct cpumask intr_cpus_map;
+
+/*
+ * We don't need to worry about the alignment of resources.
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	return res->start;
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+
+/*
+ * Pick a CPU to receive and handle the PCIe interrupts, based on the IRQ #.
+ * For now, we simply send interrupts to non-dataplane CPUs.
+ * We may implement methods to allow user to specify the target CPUs,
+ * e.g. via boot arguments.
+ */
+static int tile_irq_cpu(int irq)
+{
+	unsigned int count;
+	int i = 0;
+	int cpu;
+
+	count = cpumask_weight(&intr_cpus_map);
+	if (unlikely(count == 0)) {
+		pr_warning("intr_cpus_map empty, interrupts will be"
+			   " delievered to dataplane tiles\n");
+		return irq % (smp_height * smp_width);
+	}
+
+	count = irq % count;
+	for_each_cpu(cpu, &intr_cpus_map) {
+		if (i++ == count)
+			break;
+	}
+	return cpu;
+}
+
+/*
+ * Open a file descriptor to the TRIO shim.
+ */
+static int __devinit tile_pcie_open(int trio_index)
+{
+	gxio_trio_context_t *context = &trio_contexts[trio_index];
+	int ret;
+
+	/*
+	 * This opens a file descriptor to the TRIO shim.
+	 */
+	ret = gxio_trio_init(context, trio_index);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Allocate an ASID for the kernel.
+	 */
+	ret = gxio_trio_alloc_asids(context, 1, 0, 0);
+	if (ret < 0) {
+		pr_err("PCI: ASID alloc failure on TRIO %d, give up\n",
+			trio_index);
+		goto asid_alloc_failure;
+	}
+
+	context->asid = ret;
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+	/*
+	 * Alloc a PIO region for config access, shared by all MACs per TRIO.
+	 * This shouldn't fail since the kernel is supposed to the first
+	 * client of the TRIO's PIO regions.
+	 */
+	ret = gxio_trio_alloc_pio_regions(context, 1, 0, 0);
+	if (ret < 0) {
+		pr_err("PCI: CFG PIO alloc failure on TRIO %d, give up\n",
+			trio_index);
+		goto pio_alloc_failure;
+	}
+
+	context->pio_cfg_index = ret;
+
+	/*
+	 * For PIO CFG, the bus_address_hi parameter is 0. The mac parameter
+	 * is also 0 because it is specified in PIO_REGION_SETUP_CFG_ADDR.
+	 */
+	ret = gxio_trio_init_pio_region_aux(context, context->pio_cfg_index,
+		0, 0, HV_TRIO_PIO_FLAG_CONFIG_SPACE);
+	if (ret < 0) {
+		pr_err("PCI: CFG PIO init failure on TRIO %d, give up\n",
+			trio_index);
+		goto pio_alloc_failure;
+	}
+#endif
+
+	return ret;
+
+asid_alloc_failure:
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+pio_alloc_failure:
+#endif
+	hv_dev_close(context->fd);
+
+	return ret;
+}
+
+static void
+tilegx_legacy_irq_ack(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_EVENT_RESET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_legacy_irq_mask(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_legacy_irq_unmask(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq);
+}
+
+static struct irq_chip tilegx_legacy_irq_chip = {
+	.name			= "tilegx_legacy_irq",
+	.irq_ack		= tilegx_legacy_irq_ack,
+	.irq_mask		= tilegx_legacy_irq_mask,
+	.irq_unmask		= tilegx_legacy_irq_unmask,
+
+	/* TBD: support set_affinity. */
+};
+
+/*
+ * This is a wrapper function of the kernel level-trigger interrupt
+ * handler handle_level_irq() for PCI legacy interrupts. The TRIO
+ * is configured such that only INTx Assert interrupts are proxied
+ * to Linux which just calls handle_level_irq() after clearing the
+ * MAC INTx Assert status bit associated with this interrupt.
+ */
+static void
+trio_handle_level_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct pci_controller *controller = irq_desc_get_handler_data(desc);
+	gxio_trio_context_t *trio_context = controller->trio;
+	uint64_t intx = (uint64_t)irq_desc_get_chip_data(desc);
+	int mac = controller->mac;
+	unsigned int reg_offset;
+	uint64_t level_mask;
+
+	handle_level_irq(irq, desc);
+
+	/*
+	 * Clear the INTx Level status, otherwise future interrupts are
+	 * not sent.
+	 */
+	reg_offset = (TRIO_PCIE_INTFC_MAC_INT_STS <<
+		TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+		(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+		TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+	level_mask = TRIO_PCIE_INTFC_MAC_INT_STS__INT_LEVEL_MASK << intx;
+
+	__gxio_mmio_write(trio_context->mmio_base_mac + reg_offset, level_mask);
+}
+
+/*
+ * Create kernel irqs and set up the handlers for the legacy interrupts.
+ * Also some minimum initialization for the MSI support.
+ */
+static int __devinit tile_init_irqs(struct pci_controller *controller)
+{
+	int i;
+	int j;
+	int irq;
+	int result;
+
+	cpumask_copy(&intr_cpus_map, cpu_online_mask);
+
+
+	for (i = 0; i < 4; i++) {
+		gxio_trio_context_t *context = controller->trio;
+		int cpu;
+
+		/* Ask the kernel to allocate an IRQ. */
+		irq = create_irq();
+		if (irq < 0) {
+			pr_err("PCI: no free irq vectors, failed for %d\n", i);
+
+			goto free_irqs;
+		}
+		controller->irq_intx_table[i] = irq;
+
+		/* Distribute the 4 IRQs to different tiles. */
+		cpu = tile_irq_cpu(irq);
+
+		/* Configure the TRIO intr binding for this IRQ. */
+		result = gxio_trio_config_legacy_intr(context, cpu_x(cpu),
+						      cpu_y(cpu), KERNEL_PL,
+						      irq, controller->mac, i);
+		if (result < 0) {
+			pr_err("PCI: MAC intx config failed for %d\n", i);
+
+			goto free_irqs;
+		}
+
+		/*
+		 * Register the IRQ handler with the kernel.
+		 */
+		irq_set_chip_and_handler(irq, &tilegx_legacy_irq_chip,
+					trio_handle_level_irq);
+		irq_set_chip_data(irq, (void *)(uint64_t)i);
+		irq_set_handler_data(irq, controller);
+	}
+
+	return 0;
+
+free_irqs:
+	for (j = 0; j < i; j++)
+		destroy_irq(controller->irq_intx_table[j]);
+
+	return -1;
+}
+
+/*
+ * First initialization entry point, called from setup_arch().
+ *
+ * Find valid controllers and fill in pci_controller structs for each
+ * of them.
+ *
+ * Returns the number of controllers discovered.
+ */
+int __devinit tile_pci_init(void)
+{
+	int num_trio_shims = 0;
+	int ctl_index = 0;
+	int i, j;
+
+	if (!pci_probe) {
+		pr_info("PCI: disabled by boot argument\n");
+		return 0;
+	}
+
+	pr_info("PCI: Searching for controllers...\n");
+
+	/*
+	 * We loop over all the TRIO shims.
+	 */
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		int ret;
+
+		ret = tile_pcie_open(i);
+		if (ret < 0)
+			continue;
+
+		num_trio_shims++;
+	}
+
+        if (num_trio_shims == 0 || sim_is_simulator())
+		return 0;
+
+	/*
+	 * Now determine which PCIe ports are configured to operate in RC mode.
+	 * We look at the Board Information Block first and then see if there
+	 * are any overriding configuration in the kernel boot arguments.
+	 */
+#ifndef GX_FPGA
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		gxio_trio_context_t *context = &trio_contexts[i];
+		int ret;
+
+		if (context->fd < 0)
+			continue;
+
+		ret = hv_dev_pread(context->fd, 0,
+			(HV_VirtAddr)&pcie_ports[i][0],
+			sizeof(struct pcie_port_property) * TILEGX_TRIO_PCIES,
+			GXIO_TRIO_OP_GET_PORT_PROPERTY);
+		if (ret < 0) {
+			pr_err("PCI: PCIE_GET_PORT_PROPERTY failure, error %d,"
+				" on TRIO %d\n", ret, i);
+			continue;
+		}
+
+		for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
+			if (pcie_ports[i][j].allow_rc) {
+				pcie_rc[i][j] = 1;
+				num_rc_controllers++;
+			}
+			else if (pcie_ports[i][j].allow_ep) {
+				num_ep_controllers++;
+			}
+		}
+	}
+#else
+	/*
+	 * For now, just assume that there is a single RC port on trio/0.
+	 */
+	num_rc_controllers = 1;
+	pcie_rc[0][2] = 1;
+#endif
+
+	/*
+	 * Return if no PCIe ports are configured to operate in RC mode.
+	 */
+        if (num_rc_controllers == 0)
+		return 0;
+
+	pci_controllers = alloc_bootmem(sizeof(struct pci_controller) *
+					num_rc_controllers);
+        if (pci_controllers == NULL)
+          return -ENOMEM;
+
+	/*
+	 * Set the TRIO pointer and MAC index for each PCIe RC port.
+	 */
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
+			if (pcie_rc[i][j]) {
+				pci_controllers[ctl_index].trio =
+					&trio_contexts[i];
+				pci_controllers[ctl_index].mac = j;
+				pci_controllers[ctl_index].trio_index = i;
+				ctl_index++;
+				if (ctl_index == num_rc_controllers)
+					goto out;
+			}
+		}
+	}
+
+out:
+	/*
+	 * Configure each PCIe RC port.
+	 */
+	for (i = 0; i < num_rc_controllers; i++) {
+		/*
+		 * Configure the PCIe MAC to run in RC mode.
+		 */
+
+		struct pci_controller *controller = &pci_controllers[i];
+
+		controller->index = i;
+		controller->last_busno = 0xff;
+		controller->ops = &tile_cfg_ops;
+
+	}
+
+	return num_rc_controllers;
+}
+
+/*
+ * (pin - 1) converts from the PCI standard's [1:4] convention to
+ * a normal [0:3] range.
+ */
+static int tile_map_irq(const struct pci_dev *dev, u8 device, u8 pin)
+{
+	struct pci_controller *controller =
+		(struct pci_controller *)dev->sysdata;
+	return controller->irq_intx_table[pin - 1];
+}
+
+
+static void __devinit fixup_read_and_payload_sizes(struct pci_controller *
+						controller)
+{
+	gxio_trio_context_t *trio_context = controller->trio;
+	TRIO_PCIE_RC_DEVICE_CONTROL_t dev_control;
+	TRIO_PCIE_RC_DEVICE_CAP_t rc_dev_cap;
+	unsigned int smallest_max_payload;
+	struct pci_dev *dev = NULL;
+	unsigned int reg_offset;
+	u16 new_values;
+	int mac;
+	int err;
+
+	mac = controller->mac;
+
+	/*
+	 * Set our max read request size to be 4KB.
+	 */
+	reg_offset =
+		(TRIO_PCIE_RC_DEVICE_CONTROL <<
+			TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+		(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+			TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+	dev_control.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
+						reg_offset);
+	dev_control.max_read_req_sz = 5;
+	__gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+						dev_control.word);
+
+	/*
+	 * Set the max payload size supported by this Gx PCIe MAC.
+	 * Though Gx PCIe supports Max Payload Size of up to 1024 bytes,
+	 * experiments have shown that setting MPS to 256 yields the
+	 * best performance.
+	 */
+	reg_offset =
+		(TRIO_PCIE_RC_DEVICE_CAP <<
+			TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+		(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+			TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+	rc_dev_cap.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
+						reg_offset);
+	rc_dev_cap.mps_sup = 1;
+	__gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+						rc_dev_cap.word);
+
+	smallest_max_payload = rc_dev_cap.mps_sup;
+
+	/* Scan for the smallest maximum payload size. */
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		int pcie_caps_offset;
+		u32 devcap;
+		int max_payload;
+
+		/* Skip device that is not in this PCIe domain. */
+		if ((struct pci_controller *)dev->sysdata != controller)
+			continue;
+
+		pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
+		if (pcie_caps_offset == 0)
+			continue;
+
+		pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP,
+				      &devcap);
+		max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD;
+		if (max_payload < smallest_max_payload)
+			smallest_max_payload = max_payload;
+	}
+
+	/* Now, set the max_payload_size for all devices to that value. */
+	new_values = smallest_max_payload << 5;
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		int pcie_caps_offset;
+		u16 devctl;
+
+		/* Skip device that is not in this PCIe domain. */
+		if ((struct pci_controller *)dev->sysdata != controller)
+			continue;
+
+		pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
+		if (pcie_caps_offset == 0)
+			continue;
+
+		pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
+				     &devctl);
+		devctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
+		devctl |= new_values;
+		pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
+				      devctl);
+	}
+
+	/*
+	 * Set the mac_config register in trio based on the MPS/MRS of the link.
+	 */
+        err = gxio_trio_set_mps_mrs(trio_context,
+                        smallest_max_payload,
+                        dev_control.max_read_req_sz,
+                        mac);
+        if (err < 0) {
+		pr_err("PCI: PCIE_CONFIGURE_MAC_MPS_MRS failure, "
+			"MAC %d on TRIO %d\n",
+			mac, controller->trio_index);
+	}
+}
+
+
+/*
+ * Second PCI initialization entry point, called by subsys_initcall.
+ *
+ * The controllers have been set up by the time we get here, by a call to
+ * tile_pci_init.
+ */
+int __devinit pcibios_init(void)
+{
+	resource_size_t offset;
+	int i;
+
+        if (num_rc_controllers == 0 && num_ep_controllers == 0)
+		return 0;
+
+	pr_info("PCI: Probing PCI hardware\n");
+
+	/*
+	 * We loop over all the TRIO shims and set up the MMIO mappings.
+	 * This step can't be done in tile_pci_init because the MM subsystem
+	 * hasn't been initialized then.
+	 */
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		gxio_trio_context_t *context = &trio_contexts[i];
+
+		if (context->fd < 0)
+			continue;
+
+		/*
+		 * Map in the MMIO space for the MAC.
+                 */
+		offset = 0;
+		context->mmio_base_mac =
+			iorpc_ioremap(context->fd, offset,
+				      HV_TRIO_CONFIG_IOREMAP_SIZE);
+		if (context->mmio_base_mac == NULL) {
+			pr_err("PCI: MAC map failure on TRIO %d\n", i);
+
+			hv_dev_close(context->fd);
+			context->fd = -1;
+			continue;
+		}
+	}
+
+	/*
+	 * Delay a bit in case devices aren't ready.  Some devices are
+	 * known to require at least 20ms here, but we use a more
+	 * conservative value.
+	 */
+	mdelay(250);
+
+	/* Scan all of the recorded PCI controllers.  */
+	for (i = 0; i < num_rc_controllers; i++) {
+		struct pci_controller *controller = &pci_controllers[i];
+		gxio_trio_context_t *trio_context = controller->trio;
+		TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
+		TRIO_PCIE_INTFC_PORT_STATUS_t port_status;
+		TRIO_PCIE_INTFC_TX_FIFO_CTL_t tx_fifo_ctl;
+		struct pci_bus *bus;
+		unsigned int reg_offset;
+		unsigned int class_code_revision;
+		int mac;
+#ifndef USE_SHARED_PCIE_CONFIG_REGION
+		int ret;
+#endif
+
+		if (trio_context->fd < 0)
+			continue;
+
+		mac = controller->mac;
+
+		/*
+		 * Check the port strap state which will override the BIB
+		 * setting.
+		 */
+
+		reg_offset =
+			(TRIO_PCIE_INTFC_PORT_CONFIG <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		port_config.word =
+			__gxio_mmio_read(trio_context->mmio_base_mac +
+					 reg_offset);
+
+		if ((port_config.strap_state !=
+			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC) &&
+			(port_config.strap_state !=
+			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1)) {
+			/*
+			 * If this is really intended to be an EP port,
+			 * record it so that the endpoint driver will know about it.
+			 */
+			if (port_config.strap_state ==
+			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT ||
+			port_config.strap_state ==
+			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1)
+				pcie_ports[controller->trio_index][mac].allow_ep = 1;
+
+			continue;
+		}
+
+		ret = gxio_trio_force_link_up(trio_context, mac);
+		if (ret < 0)
+			pr_err("PCI: PCIE_FORCE_LINK_UP failure, "
+				"MAC %d on TRIO %d\n",
+				mac, controller->trio_index);
+
+		pr_info("PCI: Found PCI controller #%d on TRIO %d MAC %d\n", i,
+			controller->trio_index, controller->mac);
+
+		/*
+		 * Wait a bit here because some EP devices take longer to come up.
+		 */
+		mdelay(1000);
+
+		/*
+		 * Check for PCIe link-up status.
+		 */
+
+		reg_offset =
+			(TRIO_PCIE_INTFC_PORT_STATUS <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		port_status.word =
+			__gxio_mmio_read(trio_context->mmio_base_mac +
+					 reg_offset);
+		if (!port_status.dl_up) {
+			pr_err("PCI: link is down, MAC %d on TRIO %d\n",
+				mac, controller->trio_index);
+			continue;
+		}
+
+		/*
+		 * Ensure that the link can come out of L1 power down state.
+		 * Strictly speaking, this is needed only in the case of
+		 * heavy RC-initiated DMAs.
+		 */
+		reg_offset =
+			(TRIO_PCIE_INTFC_TX_FIFO_CTL <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+		tx_fifo_ctl.word =
+			__gxio_mmio_read(trio_context->mmio_base_mac +
+					 reg_offset);
+		tx_fifo_ctl.min_p_credits = 0;
+		__gxio_mmio_write(trio_context->mmio_base_mac + reg_offset,
+				  tx_fifo_ctl.word);
+
+		/*
+		 * Change the device ID so that Linux bus crawl doesn't confuse
+		 * the internal bridge with any Tilera endpoints.
+		 */
+
+		reg_offset =
+			(TRIO_PCIE_RC_DEVICE_ID_VEN_ID <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		__gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+				    (TILERA_GX36_RC_DEV_ID <<
+				    TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT) |
+				    TILERA_VENDOR_ID);
+
+		/*
+		 * Set the internal P2P bridge class code.
+		 */
+
+		reg_offset =
+			(TRIO_PCIE_RC_REVISION_ID <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		class_code_revision =
+			__gxio_mmio_read32(trio_context->mmio_base_mac +
+					   reg_offset);
+		class_code_revision = (class_code_revision & 0xff ) |
+					(PCI_CLASS_BRIDGE_PCI << 16);
+
+		__gxio_mmio_write32(trio_context->mmio_base_mac +
+				    reg_offset, class_code_revision);
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+
+		/*
+		 * Map in the MMIO space for the PIO region.
+                 */
+		offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index) |
+			(((unsigned long long)mac) <<
+			TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
+
+#else
+
+		/*
+		 * Alloc a PIO region for PCI config access per MAC.
+		 */
+		ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
+		if (ret < 0) {
+			pr_err("PCI: PCI CFG PIO alloc failure for mac %d "
+				"on TRIO %d, give up\n",
+				mac, controller->trio_index);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		trio_context->pio_cfg_index[mac] = ret;
+
+		/*
+		 * For PIO CFG, the bus_address_hi parameter is 0.
+		 */
+		ret = gxio_trio_init_pio_region_aux(trio_context,
+			trio_context->pio_cfg_index[mac],
+			mac, 0, HV_TRIO_PIO_FLAG_CONFIG_SPACE);
+		if (ret < 0) {
+			pr_err("PCI: PCI CFG PIO init failure for mac %d "
+				"on TRIO %d, give up\n",
+				mac, controller->trio_index);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index[mac]) |
+			(((unsigned long long)mac) <<
+			TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
+
+#endif
+
+		trio_context->mmio_base_pio_cfg[mac] =
+			iorpc_ioremap(trio_context->fd, offset,
+			(1 << TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT));
+		if (trio_context->mmio_base_pio_cfg[mac] == NULL) {
+			pr_err("PCI: PIO map failure for mac %d on TRIO %d\n",
+				mac, controller->trio_index);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		/*
+		 * Initialize the PCIe interrupts.
+                 */
+		if (tile_init_irqs(controller)) {
+			pr_err("PCI: IRQs init failure for mac %d on TRIO %d\n",
+				mac, controller->trio_index);
+
+			continue;
+		}
+
+		/*
+		 * This comes from the generic Linux PCI driver.
+		 *
+		 * It reads the PCI tree for this bus into the Linux
+		 * data structures.
+		 *
+		 * This is inlined in linux/pci.h and calls into
+		 * pci_scan_bus_parented() in probe.c.
+		 */
+		bus = pci_scan_bus(0, controller->ops, controller);
+		controller->root_bus = bus;
+		controller->last_busno = bus->subordinate;
+
+	}
+
+	/* Do machine dependent PCI interrupt routing */
+	pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
+
+	/*
+	 * This comes from the generic Linux PCI driver.
+	 *
+	 * It allocates all of the resources (I/O memory, etc)
+	 * associated with the devices read in above.
+	 */
+
+	pci_assign_unassigned_resources();
+
+	/* Record the I/O resources in the PCI controller structure. */
+	for (i = 0; i < num_rc_controllers; i++) {
+		struct pci_controller *controller = &pci_controllers[i];
+		gxio_trio_context_t *trio_context = controller->trio;
+		struct pci_bus *root_bus = pci_controllers[i].root_bus;
+		struct pci_bus *next_bus;
+		uint32_t bus_address_hi;
+		struct pci_dev *dev;
+		int ret;
+		int j;
+
+		/*
+		 * Skip controllers that are not properly initialized or
+		 * have down links.
+		 */
+		if (root_bus == NULL)
+			continue;
+
+		/* Configure the max_payload_size values for this domain. */
+		fixup_read_and_payload_sizes(controller);
+
+		list_for_each_entry(dev, &root_bus->devices, bus_list) {
+			/* Find the PCI host controller, ie. the 1st bridge. */
+			if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+				(PCI_SLOT(dev->devfn) == 0)) {
+				next_bus = dev->subordinate;
+				pci_controllers[i].mem_resources[0] =
+					*next_bus->resource[0];
+				pci_controllers[i].mem_resources[1] =
+					 *next_bus->resource[1];
+				pci_controllers[i].mem_resources[2] =
+					 *next_bus->resource[2];
+
+				break;
+			}
+		}
+
+		if (pci_controllers[i].mem_resources[1].flags & IORESOURCE_MEM)
+			bus_address_hi =
+				pci_controllers[i].mem_resources[1].start >> 32;
+		else if (pci_controllers[i].mem_resources[2].flags & IORESOURCE_PREFETCH)
+			bus_address_hi =
+				pci_controllers[i].mem_resources[2].start >> 32;
+		else {
+			/* This is unlikely. */
+			pr_err("PCI: no memory resources on TRIO %d mac %d\n",
+				controller->trio_index, controller->mac);
+			continue;
+		}
+
+		/*
+		 * We always assign 32-bit PCI bus BAR ranges.
+                 */
+		BUG_ON(bus_address_hi != 0);
+
+		/*
+		 * Alloc a PIO region for PCI memory access for each RC port.
+		 */
+		ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
+		if (ret < 0) {
+			pr_err("PCI: MEM PIO alloc failure on TRIO %d mac %d, "
+				"give up\n", controller->trio_index,
+				controller->mac);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		controller->pio_mem_index = ret;
+
+		/*
+		 * For PIO MEM, the bus_address_hi parameter is hard-coded 0
+		 * because we always assign 32-bit PCI bus BAR ranges.
+                 */
+		ret = gxio_trio_init_pio_region_aux(trio_context,
+						    controller->pio_mem_index,
+						    controller->mac,
+						    bus_address_hi,
+						    0);
+		if (ret < 0) {
+			pr_err("PCI: MEM PIO init failure on TRIO %d mac %d, "
+				"give up\n", controller->trio_index,
+				controller->mac);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		/*
+		 * Configure a Mem-Map region for each memory controller so
+		 * that Linux can map all of its PA space to the PCI bus.
+		 * Use the IOMMU to handle hash-for-home memory.
+                 */
+		for_each_online_node(j) {
+			unsigned long start_pfn = node_start_pfn[j];
+			unsigned long end_pfn = node_end_pfn[j];
+			unsigned long nr_pages = end_pfn - start_pfn;
+
+			ret = gxio_trio_alloc_memory_maps(trio_context, 1, 0,
+							  0);
+			if (ret < 0) {
+				pr_err("PCI: Mem-Map alloc failure on TRIO %d "
+					"mac %d for MC %d, give up\n",
+					controller->trio_index,
+					controller->mac, j);
+
+				/* TBD: cleanup ... */
+
+				goto alloc_mem_map_failed;
+			}
+
+			controller->mem_maps[j] = ret;
+
+			/*
+			 * Initialize the Mem-Map and the I/O MMU so that all
+			 * the physical memory can be accessed by the endpoint
+			 * devices. The base bus address is set to the base CPA
+			 * of this memory controller, so is the base VA. The
+			 * I/O MMU table essentially translates the CPA to
+			 * the real PA.
+                         */
+			ret = gxio_trio_init_memory_map_mmu_aux(trio_context,
+				controller->mem_maps[j],
+				start_pfn << PAGE_SHIFT,
+				nr_pages << PAGE_SHIFT,
+				trio_context->asid,
+				controller->mac,
+				start_pfn << PAGE_SHIFT,
+				j,
+				GXIO_TRIO_ORDER_MODE_UNORDERED);
+			if (ret < 0) {
+				pr_err("PCI: Mem-Map init failure on TRIO %d "
+					"mac %d for MC %d, give up\n",
+					controller->trio_index,
+					controller->mac, j);
+
+				/* TBD: cleanup ... */
+
+				goto alloc_mem_map_failed;
+			}
+
+			continue;
+
+alloc_mem_map_failed:
+			break;
+		}
+
+	}
+
+	return 0;
+}
+subsys_initcall(pcibios_init);
+
+/*
+ * No bus fixups needed.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	/* Nothing needs to be done. */
+}
+
+/*
+ * This can be called from the generic PCI layer, but doesn't need to
+ * do anything.
+ */
+char __devinit *pcibios_setup(char *str)
+{
+	if (!strcmp(str, "off")) {
+		pci_probe = 0;
+		return NULL;
+	}
+	return str;
+}
+
+/*
+ * This is called from the generic Linux layer.
+ */
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ * Enable memory and/or address decoding, as appropriate, for the
+ * device described by the 'dev' struct.
+ *
+ * This is called from the generic PCI layer, and can be called
+ * for bridges or endpoints.
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	u8 header_type;
+	int i;
+	struct resource *r;
+
+	pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+		/*
+		 * For bridges, we enable both memory and I/O decoding
+		 * in call cases.
+		 */
+		cmd |= PCI_COMMAND_IO;
+		cmd |= PCI_COMMAND_MEMORY;
+	} else {
+		/*
+		 * For endpoints, we enable memory and/or I/O decoding
+		 * only if they have a memory resource of that type.
+		 */
+		for (i = 0; i < 6; i++) {
+			r = &dev->resource[i];
+			if (r->flags & IORESOURCE_UNSET) {
+				pr_err("PCI: Device %s not available "
+				       "because of resource collisions\n",
+				       pci_name(dev));
+				return -EINVAL;
+			}
+			if (r->flags & IORESOURCE_IO)
+				cmd |= PCI_COMMAND_IO;
+			if (r->flags & IORESOURCE_MEM)
+				cmd |= PCI_COMMAND_MEMORY;
+		}
+	}
+
+	/*
+	 * We only write the command if it changed.
+	 */
+	if (cmd != old_cmd)
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	return 0;
+}
+
+/* Map a PCI MMIO bus address into VA space. */
+void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
+{
+	struct pci_controller *controller = NULL;
+	resource_size_t bar_start;
+	resource_size_t bar_end;
+	resource_size_t offset;
+	resource_size_t start;
+	resource_size_t end;
+	int trio_fd;
+	int i, j;
+
+	start = phys_addr;
+	end = phys_addr + size - 1;
+
+	/*
+	 * In the following, each PCI controller's mem_resources[1]
+	 * represents its (non-prefetchable) PCI memory resource and
+	 * mem_resources[2] refers to its prefetchable PCI memory resource.
+	 * By searching phys_addr in each controller's mem_resources[], we can
+	 * determine the controller that should accept the PCI memory access.
+	 */
+
+	for (i = 0; i < num_rc_controllers; i++) {
+		/*
+		 * Skip controllers that are not properly initialized or
+		 * have down links.
+		 */
+		if (pci_controllers[i].root_bus == NULL)
+			continue;
+
+		for (j = 1; j < 3; j++) {
+			bar_start =
+				pci_controllers[i].mem_resources[j].start;
+			bar_end =
+				pci_controllers[i].mem_resources[j].end;
+
+			if ((start >= bar_start) && (end <= bar_end)) {
+
+				controller = &pci_controllers[i];
+
+				goto got_it;
+			}
+		}
+	}
+
+	if (controller == NULL)
+		return NULL;
+
+got_it:
+	trio_fd = controller->trio->fd;
+
+	offset = HV_TRIO_PIO_OFFSET(controller->pio_mem_index) + phys_addr;
+
+	/*
+	 * We need to keep the PCI bus address's in-page offset in the VA.
+	 */
+        return iorpc_ioremap(trio_fd, offset, size) +
+					(phys_addr & (PAGE_SIZE - 1));
+}
+EXPORT_SYMBOL(ioremap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+
+/****************************************************************
+ *
+ * Tile PCI config space read/write routines
+ *
+ ****************************************************************/
+
+/*
+ * These are the normal read and write ops
+ * These are expanded with macros from  pci_bus_read_config_byte() etc.
+ *
+ * devfn is the combined PCI device & function.
+ *
+ * offset is in bytes, from the start of config space for the
+ * specified bus & device.
+ */
+
+static int __devinit tile_cfg_read(struct pci_bus *bus,
+				   unsigned int devfn,
+				   int offset,
+				   int size,
+				   u32 *val)
+{
+	struct pci_controller *controller = bus->sysdata;
+	gxio_trio_context_t *trio_context = controller->trio;
+	int busnum = bus->number & 0xff;
+	int device = (devfn >> 3) & 0x1f;
+	int function = devfn & 0x7;
+	int config_type = 1;
+	TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t cfg_addr;
+	void *mmio_addr;
+
+	/*
+	 * Map all accesses to the local device (bus == 0) into the
+	 * MMIO space of the MAC. Accesses to the downstream devices
+	 * go to the PIO space.
+	 */
+	if (busnum == 0) {
+		if (device == 0) {
+			/*
+			 * This is the internal downstream P2P bridge,
+			 * access directly.
+			 */
+			unsigned int reg_offset;
+
+			reg_offset = ((offset & 0xFFF) <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+				(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED
+				<< TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+				(controller->mac <<
+					TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+			mmio_addr = trio_context->mmio_base_mac + reg_offset;
+
+			goto valid_device;
+
+		} else {
+			/*
+			 * We fake an empty device for (device > 0),
+			 * since there is only one device on bus 0.
+                         */
+			goto invalid_device;
+		}
+	}
+
+	/*
+	 * Accesses to the directly attached device (bus == 1) have to be
+	 * sent as type-0 configs.
+	 */
+
+	if (busnum == 1) {
+		/*
+		 * There is only one device off of our built-in P2P bridge.
+                 */
+		if (device != 0)
+			goto invalid_device;
+
+		config_type = 0;
+	}
+
+	cfg_addr.word = 0;
+	cfg_addr.reg_addr = (offset & 0xFFF);
+	cfg_addr.fn = function;
+	cfg_addr.dev = device;
+	cfg_addr.bus = busnum;
+	cfg_addr.type = config_type;
+
+	/*
+	 * Note that we don't set the mac field in cfg_addr because the
+	 * mapping is per port.
+	 */
+
+	mmio_addr = trio_context->mmio_base_pio_cfg[controller->mac] +
+			cfg_addr.word;
+
+valid_device:
+
+	switch (size) {
+	case 4:
+		*val = __gxio_mmio_read32(mmio_addr);
+		break;
+
+	case 2:
+		*val = __gxio_mmio_read16(mmio_addr);
+		break;
+
+	case 1:
+		*val = __gxio_mmio_read8(mmio_addr);
+		break;
+
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	return 0;
+
+invalid_device:
+
+	switch (size) {
+	case 4:
+		*val = 0xFFFFFFFF;
+		break;
+
+	case 2:
+		*val = 0xFFFF;
+		break;
+
+	case 1:
+		*val = 0xFF;
+		break;
+
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	return 0;
+}
+
+
+/*
+ * See tile_cfg_read() for relevent comments.
+ * Note that "val" is the value to write, not a pointer to that value.
+ */
+static int __devinit tile_cfg_write(struct pci_bus *bus,
+				    unsigned int devfn,
+				    int offset,
+				    int size,
+				    u32 val)
+{
+	struct pci_controller *controller = bus->sysdata;
+	gxio_trio_context_t *trio_context = controller->trio;
+	int busnum = bus->number & 0xff;
+	int device = (devfn >> 3) & 0x1f;
+	int function = devfn & 0x7;
+	int config_type = 1;
+	TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t cfg_addr;
+	void *mmio_addr;
+	u32 val_32 = (u32)val;
+	u16 val_16 = (u16)val;
+	u8 val_8 = (u8)val;
+
+	/*
+	 * Map all accesses to the local device (bus == 0) into the
+	 * MMIO space of the MAC. Accesses to the downstream devices
+	 * go to the PIO space.
+	 */
+	if (busnum == 0) {
+		if (device == 0) {
+			/*
+			 * This is the internal downstream P2P bridge,
+			 * access directly.
+			 */
+			unsigned int reg_offset;
+
+			reg_offset = ((offset & 0xFFF) <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+				(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED
+				<< TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+				(controller->mac <<
+					TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+			mmio_addr = trio_context->mmio_base_mac + reg_offset;
+
+			goto valid_device;
+
+		} else {
+			/*
+			 * We fake an empty device for (device > 0),
+			 * since there is only one device on bus 0.
+                         */
+			goto invalid_device;
+		}
+	}
+
+	/*
+	 * Accesses to the directly attached device (bus == 1) have to be
+	 * sent as type-0 configs.
+	 */
+
+	if (busnum == 1) {
+		/*
+		 * There is only one device off of our built-in P2P bridge.
+                 */
+		if (device != 0)
+			goto invalid_device;
+
+		config_type = 0;
+	}
+
+	cfg_addr.word = 0;
+	cfg_addr.reg_addr = (offset & 0xFFF);
+	cfg_addr.fn = function;
+	cfg_addr.dev = device;
+	cfg_addr.bus = busnum;
+	cfg_addr.type = config_type;
+
+	/*
+	 * Note that we don't set the mac field in cfg_addr because the
+	 * mapping is per port.
+	 */
+
+	mmio_addr = trio_context->mmio_base_pio_cfg[controller->mac] +
+			cfg_addr.word;
+
+valid_device:
+
+	switch (size) {
+	case 4:
+		__gxio_mmio_write32(mmio_addr, val_32);
+		break;
+
+	case 2:
+		__gxio_mmio_write16(mmio_addr, val_16);
+		break;
+
+	case 1:
+		__gxio_mmio_write8(mmio_addr, val_8);
+		break;
+
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+invalid_device:
+
+	return 0;
+}
+
+
+static struct pci_ops tile_cfg_ops = {
+	.read =         tile_cfg_read,
+	.write =        tile_cfg_write,
+};
+
+
+inline u8 _tile_readb(unsigned long addr)
+{
+	return __gxio_mmio_read8((void *)addr);
+}
+EXPORT_SYMBOL(_tile_readb);
+
+inline u16 _tile_readw(unsigned long addr)
+{
+	return __gxio_mmio_read16((void *)addr);
+}
+EXPORT_SYMBOL(_tile_readw);
+
+inline u32 _tile_readl(unsigned long addr)
+{
+	return __gxio_mmio_read32((void *)addr);
+}
+EXPORT_SYMBOL(_tile_readl);
+
+inline u64 _tile_readq(unsigned long addr)
+{
+	return __gxio_mmio_read64((void *)addr);
+}
+EXPORT_SYMBOL(_tile_readq);
+
+inline void _tile_writeb(u8 val, unsigned long addr)
+{
+	__gxio_mmio_write8((void *)addr, val);
+}
+EXPORT_SYMBOL(_tile_writeb);
+
+inline void _tile_writew(u16 val, unsigned long addr)
+{
+	__gxio_mmio_write16((void *)addr, val);
+}
+EXPORT_SYMBOL(_tile_writew);
+
+inline void _tile_writel(u32 val, unsigned long addr)
+{
+	__gxio_mmio_write32((void *)addr, val);
+}
+EXPORT_SYMBOL(_tile_writel);
+
+inline void _tile_writeq(u64 val, unsigned long addr)
+{
+	__gxio_mmio_write64((void *)addr, val);
+}
+EXPORT_SYMBOL(_tile_writeq);
+
+/*
+ * MSI support starts here.
+ */
+static unsigned int
+tilegx_msi_startup(struct irq_data *d)
+{
+	if (d->msi_desc)
+		unmask_msi_irq(d);
+
+	return 0;
+}
+
+static void
+tilegx_msi_ack(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_EVENT_RESET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_msi_mask(struct irq_data *d)
+{
+	mask_msi_irq(d);
+	__insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_msi_unmask(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq);
+	unmask_msi_irq(d);
+}
+
+static struct irq_chip tilegx_msi_chip = {
+	.name			= "tilegx_msi",
+	.irq_startup		= tilegx_msi_startup,
+	.irq_ack		= tilegx_msi_ack,
+	.irq_mask		= tilegx_msi_mask,
+	.irq_unmask		= tilegx_msi_unmask,
+
+	/* TBD: support set_affinity. */
+};
+
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+	struct pci_controller *controller;
+	gxio_trio_context_t *trio_context;
+	struct msi_msg msg;
+	int default_irq;
+	uint64_t mem_map_base;
+	uint64_t mem_map_limit;
+	u64 msi_addr;
+	int mem_map;
+	int cpu;
+	int irq;
+	int ret;
+
+	irq = create_irq();
+	if (irq < 0)
+		return irq;
+
+	/*
+	 * Since we use a 64-bit Mem-Map to accept the MSI write, we fail
+	 * devices that are not capable of generating a 64-bit message address.
+	 * These devices will fall back to using the legacy interrupts.
+	 * Most PCIe endpoint devices do support 64-bit message addressing.
+	 */
+	if (desc->msi_attrib.is_64 == 0) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			"64-bit MSI message address not supported, "
+			"falling back to legacy interrupts.\n");
+
+		ret = -ENOMEM;
+		goto is_64_failure;
+	}
+
+	default_irq = desc->msi_attrib.default_irq;
+	controller = irq_get_handler_data(default_irq);
+
+	BUG_ON(!controller);
+
+	trio_context = controller->trio;
+
+	/*
+	 * Allocate the Mem-Map that will accept the MSI write and
+	 * trigger the TILE-side interrupts.
+	 */
+	mem_map = gxio_trio_alloc_memory_maps(trio_context, 1, 0, 0);
+	if (mem_map < 0) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			"%s Mem-Map alloc failure. "
+			"Failed to initialize MSI interrupts. "
+			"Falling back to legacy interrupts.\n",
+			desc->msi_attrib.is_msix ? "MSI-X" : "MSI");
+
+		ret = -ENOMEM;
+		goto msi_mem_map_alloc_failure;
+	}
+
+	/* We try to distribute different IRQs to different tiles. */
+	cpu = tile_irq_cpu(irq);
+
+	/*
+	 * Now call up to the HV to configure the Mem-Map interrupt and
+	 * set up the IPI binding.
+	 */
+	mem_map_base = MEM_MAP_INTR_REGIONS_BASE +
+		mem_map * MEM_MAP_INTR_REGION_SIZE;
+	mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1;
+
+	ret = gxio_trio_config_msi_intr(trio_context, cpu_x(cpu), cpu_y(cpu),
+					KERNEL_PL, irq, controller->mac,
+					mem_map, mem_map_base, mem_map_limit,
+					trio_context->asid);
+	if (ret < 0) {
+		dev_printk(KERN_INFO, &pdev->dev, "HV MSI config failed.\n");
+
+		goto hv_msi_config_failure;
+	}
+
+	irq_set_msi_desc(irq, desc);
+
+	msi_addr = mem_map_base + TRIO_MAP_MEM_REG_INT3 - TRIO_MAP_MEM_REG_INT0;
+
+	msg.address_hi = msi_addr >> 32;
+	msg.address_lo = msi_addr & 0xffffffff;
+
+	msg.data = mem_map;
+
+	write_msi_msg(irq, &msg);
+	irq_set_chip_and_handler(irq, &tilegx_msi_chip, handle_level_irq);
+	irq_set_handler_data(irq, controller);
+
+	return 0;
+
+hv_msi_config_failure:
+	/* Free mem-map */
+msi_mem_map_alloc_failure:
+is_64_failure:
+	destroy_irq(irq);
+	return ret;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	destroy_irq(irq);
+}
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 787728e..857eb59 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -1312,6 +1312,7 @@ void __init setup_arch(char **cmdline_p)
 
 
 #ifdef CONFIG_PCI
+#if !defined (__tilegx__)
 	/*
 	 * Initialize the PCI structures.  This is done before memory
 	 * setup so that we know whether or not a pci_reserve region
@@ -1319,6 +1320,7 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	if (tile_pci_init() == 0)
 		pci_reserve_mb = 0;
+#endif
 
 	/* PCI systems reserve a region just below 4GB for mapping iomem. */
 	pci_reserve_end_pfn  = (1 << (32 - PAGE_SHIFT));
@@ -1347,6 +1349,10 @@ void __init setup_arch(char **cmdline_p)
 	setup_cpu(1);
 	setup_clock();
 	load_hv_initrd();
+
+#if defined(CONFIG_PCI) && defined (__tilegx__)
+	tile_pci_init();
+#endif
 }
 
 
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
index 591621f..3d5a6bb 100644
--- a/arch/tile/mm/pgtable.c
+++ b/arch/tile/mm/pgtable.c
@@ -573,13 +573,6 @@ void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
 }
 EXPORT_SYMBOL(ioremap_prot);
 
-/* Map a PCI MMIO bus address into VA space. */
-void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
-{
-	panic("ioremap for PCI MMIO is not supported");
-}
-EXPORT_SYMBOL(ioremap);
-
 /* Unmap an MMIO VA mapping. */
 void iounmap(volatile void __iomem *addr_in)
 {
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 4bf7102..1e7154b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2143,9 +2143,9 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB,
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
 			quirk_unhide_mch_dev6);
 
-#ifdef CONFIG_TILE
+#ifdef CONFIG_TILEPRO
 /*
- * The Tilera TILEmpower platform needs to set the link speed
+ * The Tilera TILEmpower tilepro platform needs to set the link speed
  * to 2.5GT(Giga-Transfers)/s (Gen 1). The default link speed
  * setting is 5GT/s (Gen 2). 0x98 is the Link Control2 PCIe
  * capability register of the PEX8624 PCIe switch. The switch
@@ -2160,7 +2160,7 @@ static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
 	}
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
-#endif /* CONFIG_TILE */
+#endif /* CONFIG_TILEPRO */
 
 #ifdef CONFIG_PCI_MSI
 /* Some chipsets do not support MSI. We cannot easily rely on setting
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] arch/tile: provide kernel support for the tilegx TRIO shim
  2012-04-07 20:53 ` [PATCH 1/3] arch/tile: provide kernel support for the tilegx TRIO shim Chris Metcalf
@ 2012-04-07 23:39   ` Jesper Juhl
  2012-04-08  0:21     ` Chris Metcalf
  0 siblings, 1 reply; 19+ messages in thread
From: Jesper Juhl @ 2012-04-07 23:39 UTC (permalink / raw)
  To: Chris Metcalf; +Cc: linux-kernel

On Sat, 7 Apr 2012, Chris Metcalf wrote:

> Provide kernel support for the tilegx "Transaction I/O" (TRIO) on-chip
> hardware.  This hardware implements the PCIe interface for tilegx;
> the driver changes to use TRIO for PCIe are in a subsequent commit.
> 
> The change is layered on top of the tilegx GXIO IORPC subsystem.
> 
> Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
> ---
>  arch/tile/gxio/Kconfig                       |    9 +
>  arch/tile/gxio/Makefile                      |    1 +
>  arch/tile/gxio/iorpc_trio.c                  |  352 ++++++++++++++++++++++++++
>  arch/tile/gxio/trio.c                        |   49 ++++
>  arch/tile/include/arch/trio.h                |   68 +++++
>  arch/tile/include/arch/trio_constants.h      |   36 +++
>  arch/tile/include/arch/trio_def.h            |   41 +++
>  arch/tile/include/arch/trio_pcie_intfc.h     |  203 +++++++++++++++
>  arch/tile/include/arch/trio_pcie_intfc_def.h |   32 +++
>  arch/tile/include/arch/trio_pcie_rc.h        |  144 +++++++++++
>  arch/tile/include/arch/trio_pcie_rc_def.h    |   24 ++
>  arch/tile/include/arch/trio_shm.h            |  111 ++++++++
>  arch/tile/include/arch/trio_shm_def.h        |   19 ++
>  arch/tile/include/gxio/iorpc_trio.h          |  198 +++++++++++++++
>  arch/tile/include/gxio/trio.h                |  303 ++++++++++++++++++++++
>  arch/tile/include/hv/drv_trio_intf.h         |  196 ++++++++++++++
>  16 files changed, 1786 insertions(+), 0 deletions(-)
>  create mode 100644 arch/tile/gxio/iorpc_trio.c
>  create mode 100644 arch/tile/gxio/trio.c
>  create mode 100644 arch/tile/include/arch/trio.h
>  create mode 100644 arch/tile/include/arch/trio_constants.h
>  create mode 100644 arch/tile/include/arch/trio_def.h
>  create mode 100644 arch/tile/include/arch/trio_pcie_intfc.h
>  create mode 100644 arch/tile/include/arch/trio_pcie_intfc_def.h
>  create mode 100644 arch/tile/include/arch/trio_pcie_rc.h
>  create mode 100644 arch/tile/include/arch/trio_pcie_rc_def.h
>  create mode 100644 arch/tile/include/arch/trio_shm.h
>  create mode 100644 arch/tile/include/arch/trio_shm_def.h
>  create mode 100644 arch/tile/include/gxio/iorpc_trio.h
>  create mode 100644 arch/tile/include/gxio/trio.h
>  create mode 100644 arch/tile/include/hv/drv_trio_intf.h
> 
> diff --git a/arch/tile/gxio/Kconfig b/arch/tile/gxio/Kconfig
> index ec20e8c..ed0cd48 100644
> --- a/arch/tile/gxio/Kconfig
> +++ b/arch/tile/gxio/Kconfig
> @@ -23,3 +23,12 @@ config TILE_GXIO_MPIPE
>  	  This option supports direct access to the TILE-Gx mPIPE hardware
>  	  from kernel space.  It is not required in order to use the gxio
>  	  library to access mPIPE from user space.
> +
> +config TILE_GXIO_TRIO
> +	bool "Tilera Gx TRIO I/O support"
> +	select TILE_GXIO
> +	select TILE_GXIO_DMA
> +	---help---
> +	  This option supports direct access to the TILE-Gx TRIO hardware
> +	  from kernel space.  It is not required in order to use the gxio
> +	  library to access TRIO from user space.
> diff --git a/arch/tile/gxio/Makefile b/arch/tile/gxio/Makefile
> index 130eec4..2389ef3 100644
> --- a/arch/tile/gxio/Makefile
> +++ b/arch/tile/gxio/Makefile
> @@ -5,3 +5,4 @@
>  obj-$(CONFIG_TILE_GXIO) += iorpc_globals.o kiorpc.o
>  obj-$(CONFIG_TILE_GXIO_DMA) += dma_queue.o
>  obj-$(CONFIG_TILE_GXIO_MPIPE) += mpipe.o iorpc_mpipe.o iorpc_mpipe_info.o
> +obj-$(CONFIG_TILE_GXIO_TRIO) += trio.o iorpc_trio.o
> diff --git a/arch/tile/gxio/iorpc_trio.c b/arch/tile/gxio/iorpc_trio.c
> new file mode 100644
> index 0000000..4ca91ab
> --- /dev/null
> +++ b/arch/tile/gxio/iorpc_trio.c
> @@ -0,0 +1,352 @@
> +/*
> + * Copyright 2011 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* This file is machine-generated; DO NOT EDIT! */
> +#include "gxio/iorpc_trio.h"
> +
> +typedef struct {
> +	unsigned int count;
> +	unsigned int first;
> +	unsigned int flags;
> +} alloc_asids_param_t;
> +
> +int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
> +			  unsigned int first, unsigned int flags)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	alloc_asids_param_t temp;
> +	alloc_asids_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->count = count;
> +	params->first = first;
> +	params->flags = flags;
> +
> +	__offset = GXIO_TRIO_OP_ALLOC_ASIDS;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}

Having the "__offset" variable seems redundant here. It is declared, then 
later initialized to GXIO_TRIO_OP_ALLOC_ASIDS and then later used just 
once.
I'd say either initialize it to GXIO_TRIO_OP_ALLOC_ASIDS when it's 
declared (and make that variable const) or just get rid of it entirely and 
just use GXIO_TRIO_OP_ALLOC_ASIDS directly in the one place the variable 
is used.
This goes for other functions as well, using a __offset variable in a 
similar way - not going to explicitly point them all out.


> +
> +EXPORT_SYMBOL(gxio_trio_alloc_asids);
> +
> +
> +typedef struct {
> +	unsigned int count;
> +	unsigned int first;
> +	unsigned int flags;
> +} alloc_memory_maps_param_t;
> +
> +int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
> +				unsigned int count, unsigned int first,
> +				unsigned int flags)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	alloc_memory_maps_param_t temp;
> +	alloc_memory_maps_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->count = count;
> +	params->first = first;
> +	params->flags = flags;
> +
> +	__offset = GXIO_TRIO_OP_ALLOC_MEMORY_MAPS;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}

What's the point of the "__result" variable? why not just get rid of it 
and just "return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, 
__size, __offset);" ??
Goes for other functions as well..


> +
> +EXPORT_SYMBOL(gxio_trio_alloc_memory_maps);
> +
> +
> +typedef struct {
> +	unsigned int count;
> +	unsigned int first;
> +	unsigned int flags;
> +} alloc_pio_regions_param_t;
> +
> +int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
> +				unsigned int count, unsigned int first,
> +				unsigned int flags)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	alloc_pio_regions_param_t temp;
> +	alloc_pio_regions_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->count = count;
> +	params->first = first;
> +	params->flags = flags;
> +
> +	__offset = GXIO_TRIO_OP_ALLOC_PIO_REGIONS;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_alloc_pio_regions);
> +
> +typedef struct {
> +	unsigned int pio_region;
> +	unsigned int mac;
> +	uint32_t bus_address_hi;
> +	unsigned int flags;
> +} init_pio_region_aux_param_t;
> +
> +int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
> +				  unsigned int pio_region, unsigned int mac,
> +				  uint32_t bus_address_hi, unsigned int flags)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	init_pio_region_aux_param_t temp;
> +	init_pio_region_aux_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->pio_region = pio_region;
> +	params->mac = mac;
> +	params->bus_address_hi = bus_address_hi;
> +	params->flags = flags;
> +
> +	__offset = GXIO_TRIO_OP_INIT_PIO_REGION_AUX;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_init_pio_region_aux);
> +
> +
> +typedef struct {
> +	unsigned int map;
> +	unsigned long va;
> +	uint64_t size;
> +	unsigned int asid;
> +	unsigned int mac;
> +	uint64_t bus_address;
> +	unsigned int node;
> +	unsigned int order_mode;
> +} init_memory_map_mmu_aux_param_t;
> +
> +int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
> +				      unsigned int map, unsigned long va,
> +				      uint64_t size, unsigned int asid,
> +				      unsigned int mac, uint64_t bus_address,
> +				      unsigned int node,
> +				      unsigned int order_mode)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	init_memory_map_mmu_aux_param_t temp;
> +	init_memory_map_mmu_aux_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->map = map;
> +	params->va = va;
> +	params->size = size;
> +	params->asid = asid;
> +	params->mac = mac;
> +	params->bus_address = bus_address;
> +	params->node = node;
> +	params->order_mode = order_mode;
> +
> +	__offset = GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_init_memory_map_mmu_aux);
> +
> +
> +typedef struct {
> +	iorpc_interrupt_t interrupt;
> +	unsigned int mac;
> +	unsigned int intx;
> +} config_legacy_intr_param_t;
> +
> +int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
> +				 int inter_y, int inter_ipi, int inter_event,
> +				 unsigned int mac, unsigned int intx)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	config_legacy_intr_param_t temp;
> +	config_legacy_intr_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +

const size_t __size = sizeof(*params);  ??? or maybe just get rid of the 
variable since it is only used once.?


> +	params->interrupt.kernel.x = inter_x;
> +	params->interrupt.kernel.y = inter_y;
> +	params->interrupt.kernel.ipi = inter_ipi;
> +	params->interrupt.kernel.event = inter_event;
> +	params->mac = mac;
> +	params->intx = intx;
> +
> +	__offset = GXIO_TRIO_OP_CONFIG_LEGACY_INTR;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_config_legacy_intr);
> +
> +typedef struct {
> +	iorpc_interrupt_t interrupt;
> +	unsigned int mac;
> +	unsigned int mem_map;
> +	uint64_t mem_map_base;
> +	uint64_t mem_map_limit;
> +	unsigned int asid;
> +} config_msi_intr_param_t;
> +
> +int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
> +			      int inter_y, int inter_ipi, int inter_event,
> +			      unsigned int mac, unsigned int mem_map,
> +			      uint64_t mem_map_base, uint64_t mem_map_limit,
> +			      unsigned int asid)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	config_msi_intr_param_t temp;
> +	config_msi_intr_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->interrupt.kernel.x = inter_x;
> +	params->interrupt.kernel.y = inter_y;
> +	params->interrupt.kernel.ipi = inter_ipi;
> +	params->interrupt.kernel.event = inter_event;
> +	params->mac = mac;
> +	params->mem_map = mem_map;
> +	params->mem_map_base = mem_map_base;
> +	params->mem_map_limit = mem_map_limit;
> +	params->asid = asid;
> +
> +	__offset = GXIO_TRIO_OP_CONFIG_MSI_INTR;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_config_msi_intr);
> +
> +
> +typedef struct {
> +	uint16_t mps;
> +	uint16_t mrs;
> +	unsigned int mac;
> +} set_mps_mrs_param_t;
> +
> +int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
> +			  uint16_t mrs, unsigned int mac)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	set_mps_mrs_param_t temp;
> +	set_mps_mrs_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->mps = mps;
> +	params->mrs = mrs;
> +	params->mac = mac;
> +
> +	__offset = GXIO_TRIO_OP_SET_MPS_MRS;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_set_mps_mrs);
> +
> +typedef struct {
> +	unsigned int mac;
> +} force_link_up_param_t;
> +
> +int gxio_trio_force_link_up(gxio_trio_context_t * context, unsigned int mac)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	force_link_up_param_t temp;
> +	force_link_up_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->mac = mac;
> +
> +	__offset = GXIO_TRIO_OP_FORCE_LINK_UP;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_force_link_up);
> +
> +typedef struct {
> +	HV_PTE base;
> +} get_mmio_base_param_t;
> +
> +int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	get_mmio_base_param_t temp;
> +	get_mmio_base_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	__offset = GXIO_TRIO_OP_GET_MMIO_BASE;
> +	__result =
> +	    hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, __size,
> +			 __offset);
> +	*base = params->base;
> +
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_get_mmio_base);
> +
> +typedef struct {
> +	unsigned long offset;
> +	unsigned long size;
> +} check_mmio_offset_param_t;
> +
> +int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
> +				unsigned long offset, unsigned long size)
> +{
> +	uint64_t __offset;
> +	int __result;
> +	check_mmio_offset_param_t temp;
> +	check_mmio_offset_param_t *params = &temp;
> +	size_t __size = sizeof(*params);
> +
> +	params->offset = offset;
> +	params->size = size;
> +
> +	__offset = GXIO_TRIO_OP_CHECK_MMIO_OFFSET;
> +	__result =
> +	    hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
> +			  __offset);
> +	return __result;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_check_mmio_offset);
> diff --git a/arch/tile/gxio/trio.c b/arch/tile/gxio/trio.c
> new file mode 100644
> index 0000000..cd5c103
> --- /dev/null
> +++ b/arch/tile/gxio/trio.c
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/*
> + * Implementation of trio gxio calls.
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +
> +#include <gxio/trio.h>
> +#include <gxio/iorpc_globals.h>
> +#include <gxio/iorpc_trio.h>
> +#include <gxio/kiorpc.h>
> +
> +int gxio_trio_init(gxio_trio_context_t * context, unsigned int trio_index)
> +{
> +	char file[32];
> +	int fd;
> +
> +	snprintf(file, sizeof(file), "trio/%d/iorpc", trio_index);
> +	fd = hv_dev_open((HV_VirtAddr) file, 0);
> +	if (fd < 0) {
> +		context->fd = -1;
> +
> +		if (fd >= GXIO_ERR_MIN && fd <= GXIO_ERR_MAX)
> +			return fd;
> +		else
> +			return -ENODEV;
> +	}
> +
> +	context->fd = fd;
> +
> +	return 0;
> +}
> +
> +EXPORT_SYMBOL(gxio_trio_init);
> diff --git a/arch/tile/include/arch/trio.h b/arch/tile/include/arch/trio.h
> new file mode 100644
> index 0000000..b1f6bdf
> --- /dev/null
> +++ b/arch/tile/include/arch/trio.h
> @@ -0,0 +1,68 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* Machine-generated file; do not edit. */
> +
> +#ifndef __ARCH_TRIO_H__
> +#define __ARCH_TRIO_H__
> +
> +#include <arch/abi.h>
> +#include <arch/trio_def.h>
> +
> +#ifndef __ASSEMBLER__
> +
> +// Tile PIO Region Configuration - CFG Address Format.
> +// This register describes the address format for PIO accesses when the
> +// associated region is setup with TYPE=CFG.
> +
> +__extension__
> +typedef union
> +{
> +  struct
> +  {
> +#ifndef __BIG_ENDIAN__
> +    // Register Address (full byte address).
> +    uint_reg_t reg_addr     : 12;
> +    // Function Number
> +    uint_reg_t fn           : 3;
> +    // Device Number
> +    uint_reg_t dev          : 5;
> +    // BUS Number
> +    uint_reg_t bus          : 8;
> +    // Config Type: 0 for access to directly-attached device.  1 otherwise.
> +    uint_reg_t type         : 1;
> +    // Reserved.
> +    uint_reg_t __reserved_0 : 1;
> +    // MAC select.  This must match the configuration in
> +    // TILE_PIO_REGION_SETUP.MAC.
> +    uint_reg_t mac          : 2;
> +    // Reserved.
> +    uint_reg_t __reserved_1 : 32;
> +#else   // __BIG_ENDIAN__
> +    uint_reg_t __reserved_1 : 32;
> +    uint_reg_t mac          : 2;
> +    uint_reg_t __reserved_0 : 1;
> +    uint_reg_t type         : 1;
> +    uint_reg_t bus          : 8;
> +    uint_reg_t dev          : 5;
> +    uint_reg_t fn           : 3;
> +    uint_reg_t reg_addr     : 12;
> +#endif
> +  };
> +
> +  uint_reg_t word;
> +} TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t;
> +#endif /* !defined(__ASSEMBLER__) */
> +
> +#endif /* !defined(__ARCH_TRIO_H__) */
> diff --git a/arch/tile/include/arch/trio_constants.h b/arch/tile/include/arch/trio_constants.h
> new file mode 100644
> index 0000000..628b045
> --- /dev/null
> +++ b/arch/tile/include/arch/trio_constants.h
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +
> +#ifndef __ARCH_TRIO_CONSTANTS_H__
> +#define __ARCH_TRIO_CONSTANTS_H__
> +
> +#define TRIO_NUM_ASIDS 16
> +#define TRIO_NUM_TLBS_PER_ASID 16
> +
> +#define TRIO_NUM_TPIO_REGIONS 8
> +#define TRIO_LOG2_NUM_TPIO_REGIONS 3
> +
> +#define TRIO_NUM_MAP_MEM_REGIONS 16
> +#define TRIO_LOG2_NUM_MAP_MEM_REGIONS 4
> +#define TRIO_NUM_MAP_SQ_REGIONS 8
> +#define TRIO_LOG2_NUM_MAP_SQ_REGIONS 3
> +
> +#define TRIO_LOG2_NUM_SQ_FIFO_ENTRIES 6
> +
> +#define TRIO_NUM_PUSH_DMA_RINGS 32
> +
> +#define TRIO_NUM_PULL_DMA_RINGS 32
> +
> +#endif /* __ARCH_TRIO_CONSTANTS_H__ */
> diff --git a/arch/tile/include/arch/trio_def.h b/arch/tile/include/arch/trio_def.h
> new file mode 100644
> index 0000000..e805003
> --- /dev/null
> +++ b/arch/tile/include/arch/trio_def.h
> @@ -0,0 +1,41 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* Machine-generated file; do not edit. */
> +
> +#ifndef __ARCH_TRIO_DEF_H__
> +#define __ARCH_TRIO_DEF_H__
> +#define TRIO_CFG_REGION_ADDR__REG_SHIFT 0
> +#define TRIO_CFG_REGION_ADDR__INTFC_SHIFT 16
> +#define TRIO_CFG_REGION_ADDR__INTFC_VAL_TRIO 0x0
> +#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE 0x1
> +#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD 0x2
> +#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED 0x3
> +#define TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT 18
> +#define TRIO_CFG_REGION_ADDR__PROT_SHIFT 20
> +#define TRIO_PIO_REGIONS_ADDR__REGION_SHIFT 32
> +#define TRIO_MAP_MEM_REG_INT0 0x1000000000
> +#define TRIO_MAP_MEM_REG_INT1 0x1000000008
> +#define TRIO_MAP_MEM_REG_INT2 0x1000000010
> +#define TRIO_MAP_MEM_REG_INT3 0x1000000018
> +#define TRIO_MAP_MEM_REG_INT4 0x1000000020
> +#define TRIO_MAP_MEM_REG_INT5 0x1000000028
> +#define TRIO_MAP_MEM_REG_INT6 0x1000000030
> +#define TRIO_MAP_MEM_REG_INT7 0x1000000038
> +#define TRIO_MAP_MEM_LIM__ADDR_SHIFT 12
> +#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_UNORDERED 0x0
> +#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_STRICT 0x1
> +#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_REL_ORD 0x2
> +#define TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT 30
> +#endif /* !defined(__ARCH_TRIO_DEF_H__) */
> diff --git a/arch/tile/include/arch/trio_pcie_intfc.h b/arch/tile/include/arch/trio_pcie_intfc.h
> new file mode 100644
> index 0000000..a74b56b
> --- /dev/null
> +++ b/arch/tile/include/arch/trio_pcie_intfc.h
> @@ -0,0 +1,203 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* Machine-generated file; do not edit. */
> +
> +#ifndef __ARCH_TRIO_PCIE_INTFC_H__
> +#define __ARCH_TRIO_PCIE_INTFC_H__
> +
> +#include <arch/abi.h>
> +#include <arch/trio_pcie_intfc_def.h>
> +
> +#ifndef __ASSEMBLER__
> +
> +// Port Configuration.
> +// Configuration of the PCIe Port
> +
> +__extension__
> +typedef union
> +{
> +  struct
> +  {
> +#ifndef __BIG_ENDIAN__
> +    // Provides the state of the strapping pins for this port.
> +    uint_reg_t strap_state      : 3;
> +    // Reserved.
> +    uint_reg_t __reserved_0     : 1;
> +    // When 1, the device type will be overridden using OVD_DEV_TYPE_VAL.
> +    // When 0, the device type is determined based on the STRAP_STATE.
> +    uint_reg_t ovd_dev_type     : 1;
> +    // Provides the device type when OVD_DEV_TYPE is 1.
> +    uint_reg_t ovd_dev_type_val : 4;
> +    // Determines how link is trained.
> +    uint_reg_t train_mode       : 2;
> +    // Reserved.
> +    uint_reg_t __reserved_1     : 1;
> +    // For PCIe, used to flip physical RX lanes that were not properly wired.
> +    //  This is not the same as lane reversal which is handled automatically
> +    // during link training.  When 0, RX Lane0 must be wired to the link
> +    // partner (either to its Lane0 or it's LaneN).  When RX_LANE_FLIP is 1,
> +    // the highest numbered lane for this port becomes Lane0 and Lane0 does
> +    // NOT have to be wired to the link partner.
> +    uint_reg_t rx_lane_flip     : 1;
> +    // For PCIe, used to flip physical TX lanes that were not properly wired.
> +    //  This is not the same as lane reversal which is handled automatically
> +    // during link training.  When 0, TX Lane0 must be wired to the link
> +    // partner (either to its Lane0 or it's LaneN).  When TX_LANE_FLIP is 1,
> +    // the highest numbered lane for this port becomes Lane0 and Lane0 does
> +    // NOT have to be wired to the link partner.
> +    uint_reg_t tx_lane_flip     : 1;
> +    // For StreamIO port, configures the width of the port when TRAIN_MODE is
> +    // not STRAP.
> +    uint_reg_t stream_width     : 2;
> +    // For StreamIO port, configures the rate of the port when TRAIN_MODE is
> +    // not STRAP.
> +    uint_reg_t stream_rate      : 2;
> +    // Reserved.
> +    uint_reg_t __reserved_2     : 46;
> +#else   // __BIG_ENDIAN__
> +    uint_reg_t __reserved_2     : 46;
> +    uint_reg_t stream_rate      : 2;
> +    uint_reg_t stream_width     : 2;
> +    uint_reg_t tx_lane_flip     : 1;
> +    uint_reg_t rx_lane_flip     : 1;
> +    uint_reg_t __reserved_1     : 1;
> +    uint_reg_t train_mode       : 2;
> +    uint_reg_t ovd_dev_type_val : 4;
> +    uint_reg_t ovd_dev_type     : 1;
> +    uint_reg_t __reserved_0     : 1;
> +    uint_reg_t strap_state      : 3;
> +#endif
> +  };
> +
> +  uint_reg_t word;
> +} TRIO_PCIE_INTFC_PORT_CONFIG_t;
> +
> +// Port Status.
> +// Status of the PCIe Port.  This register applies to the StreamIO port when
> +// StreamIO is enabled.
> +
> +__extension__
> +typedef union
> +{
> +  struct
> +  {
> +#ifndef __BIG_ENDIAN__
> +    // Indicates the DL state of the port.  When 1, the port is up and ready
> +    // to receive traffic.
> +    uint_reg_t dl_up        : 1;
> +    // Indicates the number of times the link has gone down.  Clears on read.
> +    uint_reg_t dl_down_cnt  : 7;
> +    // Indicates the SERDES PLL has spun up and is providing a valid clock.
> +    uint_reg_t clock_ready  : 1;
> +    // Reserved.
> +    uint_reg_t __reserved_0 : 7;
> +    // Device revision ID.
> +    uint_reg_t device_rev   : 8;
> +    // Link state (PCIe).
> +    uint_reg_t ltssm_state  : 6;
> +    // Link power management state (PCIe).
> +    uint_reg_t pm_state     : 3;
> +    // Reserved.
> +    uint_reg_t __reserved_1 : 31;
> +#else   // __BIG_ENDIAN__
> +    uint_reg_t __reserved_1 : 31;
> +    uint_reg_t pm_state     : 3;
> +    uint_reg_t ltssm_state  : 6;
> +    uint_reg_t device_rev   : 8;
> +    uint_reg_t __reserved_0 : 7;
> +    uint_reg_t clock_ready  : 1;
> +    uint_reg_t dl_down_cnt  : 7;
> +    uint_reg_t dl_up        : 1;
> +#endif
> +  };
> +
> +  uint_reg_t word;
> +} TRIO_PCIE_INTFC_PORT_STATUS_t;
> +
> +// Transmit FIFO Control.
> +// Contains TX FIFO thresholds.  These registers are for diagnostics purposes
> +// only.  Changing these values causes undefined behavior.
> +
> +__extension__
> +typedef union
> +{
> +  struct
> +  {
> +#ifndef __BIG_ENDIAN__
> +    // Almost-Empty level for TX0 data.  Typically set to at least
> +    // roundup(38.0*M/N) where N=tclk frequency and M=MAC symbol rate in MHz
> +    // for a x4 port (250MHz).
> +    uint_reg_t tx0_data_ae_lvl : 7;
> +    // Reserved.
> +    uint_reg_t __reserved_0    : 1;
> +    // Almost-Empty level for TX1 data.
> +    uint_reg_t tx1_data_ae_lvl : 7;
> +    // Reserved.
> +    uint_reg_t __reserved_1    : 1;
> +    // Almost-Full level for TX0 data.
> +    uint_reg_t tx0_data_af_lvl : 7;
> +    // Reserved.
> +    uint_reg_t __reserved_2    : 1;
> +    // Almost-Full level for TX1 data.
> +    uint_reg_t tx1_data_af_lvl : 7;
> +    // Reserved.
> +    uint_reg_t __reserved_3    : 1;
> +    // Almost-Full level for TX0 info.
> +    uint_reg_t tx0_info_af_lvl : 5;
> +    // Reserved.
> +    uint_reg_t __reserved_4    : 3;
> +    // Almost-Full level for TX1 info.
> +    uint_reg_t tx1_info_af_lvl : 5;
> +    // Reserved.
> +    uint_reg_t __reserved_5    : 3;
> +    // This register provides performance adjustment for high bandwidth
> +    // flows.  The MAC will assert almost-full to TRIO if non-posted credits
> +    // fall below this level.  Note that setting this larger than the initial
> +    // PORT_CREDIT.NPH value will cause READS to never be sent.  If the
> +    // initial credit value from the link partner is smaller than this value
> +    // when the link comes up, the value will be reset to the initial credit
> +    // value to prevent lockup.
> +    uint_reg_t min_np_credits  : 8;
> +    // This register provides performance adjustment for high bandwidth
> +    // flows.  The MAC will assert almost-full to TRIO if posted credits fall
> +    // below this level.  Note that setting this larger than the initial
> +    // PORT_CREDIT.PH value will cause WRITES to never be sent.  If the
> +    // initial credit value from the link partner is smaller than this value
> +    // when the link comes up, the value will be reset to the initial credit
> +    // value to prevent lockup.
> +    uint_reg_t min_p_credits   : 8;
> +#else   // __BIG_ENDIAN__
> +    uint_reg_t min_p_credits   : 8;
> +    uint_reg_t min_np_credits  : 8;
> +    uint_reg_t __reserved_5    : 3;
> +    uint_reg_t tx1_info_af_lvl : 5;
> +    uint_reg_t __reserved_4    : 3;
> +    uint_reg_t tx0_info_af_lvl : 5;
> +    uint_reg_t __reserved_3    : 1;
> +    uint_reg_t tx1_data_af_lvl : 7;
> +    uint_reg_t __reserved_2    : 1;
> +    uint_reg_t tx0_data_af_lvl : 7;
> +    uint_reg_t __reserved_1    : 1;
> +    uint_reg_t tx1_data_ae_lvl : 7;
> +    uint_reg_t __reserved_0    : 1;
> +    uint_reg_t tx0_data_ae_lvl : 7;
> +#endif
> +  };
> +
> +  uint_reg_t word;
> +} TRIO_PCIE_INTFC_TX_FIFO_CTL_t;
> +#endif /* !defined(__ASSEMBLER__) */
> +
> +#endif /* !defined(__ARCH_TRIO_PCIE_INTFC_H__) */
> diff --git a/arch/tile/include/arch/trio_pcie_intfc_def.h b/arch/tile/include/arch/trio_pcie_intfc_def.h
> new file mode 100644
> index 0000000..d3fd678
> --- /dev/null
> +++ b/arch/tile/include/arch/trio_pcie_intfc_def.h
> @@ -0,0 +1,32 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* Machine-generated file; do not edit. */
> +
> +#ifndef __ARCH_TRIO_PCIE_INTFC_DEF_H__
> +#define __ARCH_TRIO_PCIE_INTFC_DEF_H__
> +#define TRIO_PCIE_INTFC_MAC_INT_STS 0x0000
> +#define TRIO_PCIE_INTFC_MAC_INT_STS__INT_LEVEL_MASK  0xf000
> +#define TRIO_PCIE_INTFC_PORT_CONFIG 0x0018
> +#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_DISABLED 0x0
> +#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT 0x1
> +#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC 0x2
> +#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1 0x3
> +#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1 0x4
> +#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_XLINK 0x5
> +#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_STREAM_X1 0x6
> +#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_STREAM_X4 0x7
> +#define TRIO_PCIE_INTFC_PORT_STATUS 0x0020
> +#define TRIO_PCIE_INTFC_TX_FIFO_CTL 0x0050
> +#endif /* !defined(__ARCH_TRIO_PCIE_INTFC_DEF_H__) */
> diff --git a/arch/tile/include/arch/trio_pcie_rc.h b/arch/tile/include/arch/trio_pcie_rc.h
> new file mode 100644
> index 0000000..4986628
> --- /dev/null
> +++ b/arch/tile/include/arch/trio_pcie_rc.h
> @@ -0,0 +1,144 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* Machine-generated file; do not edit. */
> +
> +#ifndef __ARCH_TRIO_PCIE_RC_H__
> +#define __ARCH_TRIO_PCIE_RC_H__
> +
> +#include <arch/abi.h>
> +#include <arch/trio_pcie_rc_def.h>
> +
> +#ifndef __ASSEMBLER__
> +
> +// Device Capabilities Register.
> +
> +__extension__
> +typedef union
> +{
> +  struct
> +  {
> +#ifndef __BIG_ENDIAN__
> +    // Max_Payload_Size Supported, writablethrough the MAC_STANDARD interface
> +    uint_reg_t mps_sup                    : 3;
> +    // This field is writable through the MAC_STANDARD interface.  However,
> +    // Phantom Function is not  supported. Therefore, the application must
> +    // not write any value other than 0x0 to this  field.
> +    uint_reg_t phantom_function_supported : 2;
> +    // This bit is writable through the MAC_STANDARD interface.
> +    uint_reg_t ext_tag_field_supported    : 1;
> +    // Reserved.
> +    uint_reg_t __reserved_0               : 3;
> +    // Endpoint L1 Acceptable Latency Must be 0x0 for non-Endpoint devices.
> +    uint_reg_t l1_lat                     : 3;
> +    // Undefined since PCI Express 1.1 (Was Attention Button Present for PCI
> +    // Express 1.0a)
> +    uint_reg_t r1                         : 1;
> +    // Undefined since PCI Express 1.1 (Was Attention Indicator Present for
> +    // PCI  Express 1.0a)
> +    uint_reg_t r2                         : 1;
> +    // Undefined since PCI Express 1.1 (Was Power Indicator Present for PCI
> +    // Express 1.0a)
> +    uint_reg_t r3                         : 1;
> +    // Role-Based Error Reporting, writable through the MAC_STANDARD
> +    // interface.  Required to be set for device compliant to 1.1  spec and
> +    // later.
> +    uint_reg_t rer                        : 1;
> +    // Reserved.
> +    uint_reg_t __reserved_1               : 2;
> +    // Captured Slot Power Limit Value Upstream port only.
> +    uint_reg_t slot_pwr_lim               : 8;
> +    // Captured Slot Power Limit Scale Upstream port only.
> +    uint_reg_t slot_pwr_scale             : 2;
> +    // Reserved.
> +    uint_reg_t __reserved_2               : 4;
> +    // Endpoint L0s Acceptable LatencyMust be 0x0 for non-Endpoint devices.
> +    uint_reg_t l0s_lat                    : 1;
> +    // Reserved.
> +    uint_reg_t __reserved_3               : 31;
> +#else   // __BIG_ENDIAN__
> +    uint_reg_t __reserved_3               : 31;
> +    uint_reg_t l0s_lat                    : 1;
> +    uint_reg_t __reserved_2               : 4;
> +    uint_reg_t slot_pwr_scale             : 2;
> +    uint_reg_t slot_pwr_lim               : 8;
> +    uint_reg_t __reserved_1               : 2;
> +    uint_reg_t rer                        : 1;
> +    uint_reg_t r3                         : 1;
> +    uint_reg_t r2                         : 1;
> +    uint_reg_t r1                         : 1;
> +    uint_reg_t l1_lat                     : 3;
> +    uint_reg_t __reserved_0               : 3;
> +    uint_reg_t ext_tag_field_supported    : 1;
> +    uint_reg_t phantom_function_supported : 2;
> +    uint_reg_t mps_sup                    : 3;
> +#endif
> +  };
> +
> +  uint_reg_t word;
> +} TRIO_PCIE_RC_DEVICE_CAP_t;
> +
> +// Device Control Register.
> +
> +__extension__
> +typedef union
> +{
> +  struct
> +  {
> +#ifndef __BIG_ENDIAN__
> +    // Correctable Error Reporting Enable
> +    uint_reg_t cor_err_ena      : 1;
> +    // Non-Fatal Error Reporting Enable
> +    uint_reg_t nf_err_ena       : 1;
> +    // Fatal Error Reporting Enable
> +    uint_reg_t fatal_err_ena    : 1;
> +    // Unsupported Request Reporting Enable
> +    uint_reg_t ur_ena           : 1;
> +    // Relaxed orderring enable
> +    uint_reg_t ro_ena           : 1;
> +    // Max Payload Size
> +    uint_reg_t max_payload_size : 3;
> +    // Extended Tag Field Enable
> +    uint_reg_t ext_tag          : 1;
> +    // Phantom Function Enable
> +    uint_reg_t ph_fn_ena        : 1;
> +    // AUX Power PM Enable
> +    uint_reg_t aux_pm_ena       : 1;
> +    // Enable NoSnoop
> +    uint_reg_t no_snoop         : 1;
> +    // Max read request size
> +    uint_reg_t max_read_req_sz  : 3;
> +    // Reserved.
> +    uint_reg_t __reserved       : 49;
> +#else   // __BIG_ENDIAN__
> +    uint_reg_t __reserved       : 49;
> +    uint_reg_t max_read_req_sz  : 3;
> +    uint_reg_t no_snoop         : 1;
> +    uint_reg_t aux_pm_ena       : 1;
> +    uint_reg_t ph_fn_ena        : 1;
> +    uint_reg_t ext_tag          : 1;
> +    uint_reg_t max_payload_size : 3;
> +    uint_reg_t ro_ena           : 1;
> +    uint_reg_t ur_ena           : 1;
> +    uint_reg_t fatal_err_ena    : 1;
> +    uint_reg_t nf_err_ena       : 1;
> +    uint_reg_t cor_err_ena      : 1;
> +#endif
> +  };
> +
> +  uint_reg_t word;
> +} TRIO_PCIE_RC_DEVICE_CONTROL_t;
> +#endif /* !defined(__ASSEMBLER__) */
> +
> +#endif /* !defined(__ARCH_TRIO_PCIE_RC_H__) */
> diff --git a/arch/tile/include/arch/trio_pcie_rc_def.h b/arch/tile/include/arch/trio_pcie_rc_def.h
> new file mode 100644
> index 0000000..74081a6
> --- /dev/null
> +++ b/arch/tile/include/arch/trio_pcie_rc_def.h
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* Machine-generated file; do not edit. */
> +
> +#ifndef __ARCH_TRIO_PCIE_RC_DEF_H__
> +#define __ARCH_TRIO_PCIE_RC_DEF_H__
> +#define TRIO_PCIE_RC_DEVICE_CAP 0x0074
> +#define TRIO_PCIE_RC_DEVICE_CONTROL 0x0078
> +#define TRIO_PCIE_RC_DEVICE_ID_VEN_ID 0x0000
> +#define TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT 16
> +#define TRIO_PCIE_RC_REVISION_ID 0x0008
> +#endif /* !defined(__ARCH_TRIO_PCIE_RC_DEF_H__) */
> diff --git a/arch/tile/include/arch/trio_shm.h b/arch/tile/include/arch/trio_shm.h
> new file mode 100644
> index 0000000..652bbb7
> --- /dev/null
> +++ b/arch/tile/include/arch/trio_shm.h
> @@ -0,0 +1,111 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* Machine-generated file; do not edit. */
> +
> +
> +#ifndef __ARCH_TRIO_SHM_H__
> +#define __ARCH_TRIO_SHM_H__
> +
> +#include <arch/abi.h>
> +#include <arch/trio_shm_def.h>
> +
> +#ifndef __ASSEMBLER__
> +//! TRIO DMA Descriptor.
> +//! The TRIO DMA descriptor is written by software and consumed by hardware.
> +//! It is used to specify the location of transaction data in the IO and Tile
> +//! domains.
> +
> +__extension__
> +typedef union
> +{
> +  struct
> +  {
> +    // Word 0
> +
> +#ifndef __BIG_ENDIAN__
> +    //! Tile side virtual address.
> +    int_reg_t va           : 42;
> +    //! Encoded size of buffer used on push DMA when C=1:
> +    //! 0 = 128 bytes
> +    //! 1 = 256 bytes
> +    //! 2 = 512 bytes
> +    //! 3 = 1024 bytes
> +    //! 4 = 1664 bytes
> +    //! 5 = 4096 bytes
> +    //! 6 = 10368 bytes
> +    //! 7 = 16384 bytes
> +    uint_reg_t bsz          : 3;
> +    //! Chaining designation.  Always zero for pull DMA
> +    //! 0 : Unchained buffer pointer
> +    //! 1 : Chained buffer pointer.  Next buffer descriptor (e.g. VA) stored
> +    //! in 1st 8-bytes in buffer.  For chained buffers, first 8-bytes of each
> +    //! buffer contain the next buffer descriptor formatted exactly like a PDE
> +    //! buffer descriptor.  This allows a chained PDE buffer to be sent using
> +    //! push DMA.
> +    uint_reg_t c            : 1;
> +    //! Notification interrupt will be delivered when the transaction has
> +    //! completed (all data has been read from or written to the Tile-side
> +    //! buffer).
> +    uint_reg_t notif        : 1;
> +    //! When 0, the XSIZE field specifies the total byte count for the
> +    //! transaction.  When 1, the XSIZE field is encoded as 2^(N+14) for N in
> +    //! {0..6}:
> +    //! 0 = 16KB
> +    //! 1 = 32KB
> +    //! 2 = 64KB
> +    //! 3 = 128KB
> +    //! 4 = 256KB
> +    //! 5 = 512KB
> +    //! 6 = 1MB
> +    //! All other encodings of the XSIZE field are reserved when SMOD=1
> +    uint_reg_t smod         : 1;
> +    //! Total number of bytes to move for this transaction.   When SMOD=1,
> +    //! this field is encoded - see SMOD description.
> +    uint_reg_t xsize        : 14;
> +    //! Reserved.
> +    uint_reg_t __reserved_0 : 1;
> +    //! Generation number.  Used to indicate a valid descriptor in ring.  When
> +    //! a new descriptor is written into the ring, software must toggle this
> +    //! bit.  The net effect is that the GEN bit being written into new
> +    //! descriptors toggles each time the ring tail pointer wraps.
> +    uint_reg_t gen          : 1;
> +#else   // __BIG_ENDIAN__
> +    uint_reg_t gen          : 1;
> +    uint_reg_t __reserved_0 : 1;
> +    uint_reg_t xsize        : 14;
> +    uint_reg_t smod         : 1;
> +    uint_reg_t notif        : 1;
> +    uint_reg_t c            : 1;
> +    uint_reg_t bsz          : 3;
> +    int_reg_t va           : 42;
> +#endif
> +
> +    // Word 1
> +
> +#ifndef __BIG_ENDIAN__
> +    //! IO-side address
> +    uint_reg_t io_address : 64;
> +#else   // __BIG_ENDIAN__
> +    uint_reg_t io_address : 64;
> +#endif
> +
> +  };
> +
> +  //! Word access
> +  uint_reg_t words[2];
> +} TRIO_DMA_DESC_t;
> +#endif /* !defined(__ASSEMBLER__) */
> +
> +#endif /* !defined(__ARCH_TRIO_SHM_H__) */
> diff --git a/arch/tile/include/arch/trio_shm_def.h b/arch/tile/include/arch/trio_shm_def.h
> new file mode 100644
> index 0000000..72a59c8
> --- /dev/null
> +++ b/arch/tile/include/arch/trio_shm_def.h
> @@ -0,0 +1,19 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* Machine-generated file; do not edit. */
> +
> +#ifndef __ARCH_TRIO_SHM_DEF_H__
> +#define __ARCH_TRIO_SHM_DEF_H__
> +#endif /* !defined(__ARCH_TRIO_SHM_DEF_H__) */
> diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h
> new file mode 100644
> index 0000000..3ef5642
> --- /dev/null
> +++ b/arch/tile/include/gxio/iorpc_trio.h
> @@ -0,0 +1,198 @@
> +/*
> + * Copyright 2011 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/* This file is machine-generated; DO NOT EDIT! */
> +#ifndef __GXIO_TRIO_LINUX_RPC_H__
> +#define __GXIO_TRIO_LINUX_RPC_H__
> +
> +#include <hv/iorpc.h>
> +
> +#include <hv/drv_trio_intf.h>
> +#include <gxio/trio.h>
> +#include <gxio/kiorpc.h>
> +#include <linux/string.h>
> +#include <linux/module.h>
> +#include <asm/pgtable.h>
> +
> +#define GXIO_TRIO_OP_ALLOC_ASIDS       IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
> +#define GXIO_TRIO_OP_REGISTER_PAGE_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x1401)
> +#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402)
> +#define GXIO_TRIO_OP_INIT_MEMORY_MAP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1403)
> +#define GXIO_TRIO_OP_READ_ISR_STATUS_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404)
> +#define GXIO_TRIO_OP_WRITE_ISR_STATUS_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1405)
> +#define GXIO_TRIO_OP_ENABLE_MMI        IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1406)
> +#define GXIO_TRIO_OP_MASK_MMI_AUX      IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1407)
> +#define GXIO_TRIO_OP_UNMASK_MMI_AUX    IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1408)
> +#define GXIO_TRIO_OP_READ_MMI_BITS_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1409)
> +#define GXIO_TRIO_OP_WRITE_MMI_BITS_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140a)
> +#define GXIO_TRIO_OP_ALLOC_SCATTER_QUEUES IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140b)
> +#define GXIO_TRIO_OP_INIT_SCATTER_QUEUE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140c)
> +#define GXIO_TRIO_OP_ENABLE_SQI        IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x140d)
> +#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e)
> +#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f)
> +#define GXIO_TRIO_OP_ALLOC_PUSH_DMA_RING IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1410)
> +#define GXIO_TRIO_OP_ALLOC_PULL_DMA_RING IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1411)
> +#define GXIO_TRIO_OP_INIT_PUSH_DMA_RING_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x1412)
> +#define GXIO_TRIO_OP_ENABLE_PUSH_DMA_ISR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1413)
> +#define GXIO_TRIO_OP_INIT_PULL_DMA_RING_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x1414)
> +#define GXIO_TRIO_OP_ENABLE_PULL_DMA_ISR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1415)
> +#define GXIO_TRIO_OP_TRIGGER_HOST_INTERRUPT_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1416)
> +#define GXIO_TRIO_OP_REGISTER_CLIENT_MEMORY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417)
> +#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418)
> +#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1419)
> +#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a)
> +#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141b)
> +#define GXIO_TRIO_OP_CONFIG_CHAR_INTR  IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141c)
> +#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d)
> +#define GXIO_TRIO_OP_FORCE_LINK_UP     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
> +#define GXIO_TRIO_OP_GET_MMIO_BASE     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
> +#define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
> +


There is some funky formatting going on here (or my email client is 
playing tricks on me) : 

> +int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
> +			  unsigned int first, unsigned int flags);
> +
> +int gxio_trio_register_page_aux(gxio_trio_context_t * context, void *page_va,
> +				size_t page_size, unsigned int page_flags,
> +				unsigned int stack, uint64_t vpn);
> +
> +int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
> +				unsigned int count, unsigned int first,
> +				unsigned int flags);
> +
> +int gxio_trio_init_memory_map_aux(gxio_trio_context_t * context,
> +				  unsigned int map, uint64_t vpn, uint64_t size,
> +				  unsigned int asid, unsigned int mac,
> +				  uint64_t bus_address,
> +				  unsigned int order_mode);
> +
> +int gxio_trio_read_isr_status_aux(gxio_trio_context_t * context,
> +				  unsigned int vec_num);
> +
> +int gxio_trio_write_isr_status_aux(gxio_trio_context_t * context,
> +				   unsigned int vec_num,
> +				   uint32_t bits_to_clear);
> +
> +int gxio_trio_enable_mmi(gxio_trio_context_t * context, int bind_x, int bind_y,
> +			 int bind_ipi, int bind_event, unsigned int map,
> +			 unsigned int mode);
> +
> +int gxio_trio_mask_mmi_aux(gxio_trio_context_t * context, unsigned int map,
> +			   unsigned int mask);
> +
> +int gxio_trio_unmask_mmi_aux(gxio_trio_context_t * context, unsigned int map,
> +			     unsigned int mask);
> +
> +int gxio_trio_read_mmi_bits_aux(gxio_trio_context_t * context,
> +				unsigned int map);
> +
> +int gxio_trio_write_mmi_bits_aux(gxio_trio_context_t * context,
> +				 unsigned int map, unsigned int bits,
> +				 unsigned int mode);
> +
> +int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context,
> +				   unsigned int count, unsigned int first,
> +				   unsigned int flags);
> +
> +int gxio_trio_init_scatter_queue_aux(gxio_trio_context_t * context,
> +				     unsigned int queue, uint64_t size,
> +				     unsigned int asid, unsigned int mac,
> +				     uint64_t bus_address,
> +				     unsigned int order_mode);
> +
> +int gxio_trio_enable_sqi(gxio_trio_context_t * context, int bind_x, int bind_y,
> +			 int bind_ipi, int bind_event, unsigned int queue);
> +
> +int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
> +				unsigned int count, unsigned int first,
> +				unsigned int flags);
> +
> +int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
> +				  unsigned int pio_region, unsigned int mac,
> +				  uint32_t bus_address_hi, unsigned int flags);
> +
> +int gxio_trio_alloc_push_dma_ring(gxio_trio_context_t * context,
> +				  unsigned int count, unsigned int first,
> +				  unsigned int flags);
> +
> +int gxio_trio_alloc_pull_dma_ring(gxio_trio_context_t * context,
> +				  unsigned int count, unsigned int first,
> +				  unsigned int flags);
> +
> +int gxio_trio_init_push_dma_ring_aux(gxio_trio_context_t * context,
> +				     void *mem_va, size_t mem_size,
> +				     unsigned int mem_flags, unsigned int ring,
> +				     unsigned int mac, unsigned int asid,
> +				     unsigned int flags);
> +
> +int gxio_trio_enable_push_dma_isr(gxio_trio_context_t * context, int bind_x,
> +				  int bind_y, int bind_ipi, int bind_event,
> +				  unsigned int ring);
> +
> +int gxio_trio_init_pull_dma_ring_aux(gxio_trio_context_t * context,
> +				     void *mem_va, size_t mem_size,
> +				     unsigned int mem_flags, unsigned int ring,
> +				     unsigned int mac, unsigned int asid,
> +				     unsigned int flags);
> +
> +int gxio_trio_enable_pull_dma_isr(gxio_trio_context_t * context, int bind_x,
> +				  int bind_y, int bind_ipi, int bind_event,
> +				  unsigned int ring);
> +
> +int gxio_trio_trigger_host_interrupt_aux(gxio_trio_context_t * context,
> +					 unsigned int mac,
> +					 unsigned long msix_addr,
> +					 unsigned int msix_data);
> +
> +int gxio_trio_register_client_memory(gxio_trio_context_t * context,
> +				     unsigned int iotlb, HV_PTE pte,
> +				     unsigned int flags);
> +
> +int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
> +				      unsigned int map, unsigned long va,
> +				      uint64_t size, unsigned int asid,
> +				      unsigned int mac, uint64_t bus_address,
> +				      unsigned int node,
> +				      unsigned int order_mode);
> +
> +int gxio_trio_get_port_property(gxio_trio_context_t * context,
> +				struct pcie_trio_ports_property *trio_ports);
> +
> +int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
> +				 int inter_y, int inter_ipi, int inter_event,
> +				 unsigned int mac, unsigned int intx);
> +
> +int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
> +			      int inter_y, int inter_ipi, int inter_event,
> +			      unsigned int mac, unsigned int mem_map,
> +			      uint64_t mem_map_base, uint64_t mem_map_limit,
> +			      unsigned int asid);
> +
> +int gxio_trio_config_char_intr(gxio_trio_context_t * context, int inter_x,
> +			       int inter_y, int inter_ipi, int inter_event,
> +			       unsigned int mac, unsigned int mem_map,
> +			       unsigned int push_dma_ring,
> +			       unsigned int pull_dma_ring,
> +			       pcie_stream_intr_config_sel_t conf);
> +
> +int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
> +			  uint16_t mrs, unsigned int mac);
> +
> +int gxio_trio_force_link_up(gxio_trio_context_t * context, unsigned int mac);
> +
> +int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base);
> +
> +int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
> +				unsigned long offset, unsigned long size);
> +

First of all, when you have "pointer_type * variable", please use the 
style "pointer_type *variable" - as per accepted kernel coding style.
Also, I find the indentation to be inconsistent; varuing from function to 
function - is it just my email client or??  If not, please fix.


> +#endif /* !__GXIO_TRIO_LINUX_RPC_H__ */
> diff --git a/arch/tile/include/gxio/trio.h b/arch/tile/include/gxio/trio.h
> new file mode 100644
> index 0000000..5e55fcc
> --- /dev/null
> +++ b/arch/tile/include/gxio/trio.h
> @@ -0,0 +1,303 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/*
> + *
> + * An API for allocating, configuring, and manipulating TRIO hardware
> + * resources
> + */
> +
> +/*
> + *
> + * The TILE-Gx TRIO shim provides connections to external devices via
> + * PCIe or other transaction IO standards.  The gxio_trio_ API,
> + * declared in <gxio/trio.h>, allows applications to allocate and
> + * configure TRIO IO resources like DMA command rings, memory map
> + * windows, and device interrupts.  The following sections introduce
> + * the various components of the API.  We strongly recommend reading
> + * the TRIO section of the IO Device Guide (UG404) before working with
> + * this API.
> + *
> + * @section trio__ingress TRIO Ingress Hardware Resources
> + *
> + * The TRIO ingress hardware is responsible for examining incoming
> + * PCIe or StreamIO packets and choosing a processing mechanism based
> + * on the packets' bus address.  The gxio_trio_ API can be used to
> + * configure different handlers for different ranges of bus address
> + * space.  The user can configure "mapped memory" and "scatter queue"
> + * regions to match incoming packets within 4kB-aligned ranges of bus
> + * addresses.  Each range specifies a different set of mapping
> + * parameters to be applied when handling the ingress packet.  The
> + * following sections describe how to work with MapMem and scatter
> + * queue regions.
> + *
> + * @subsection trio__mapmem TRIO MapMem Regions
> + *
> + * TRIO mapped memory (or MapMem) regions allow the user to map
> + * incoming read and write requests directly to the application's
> + * memory space.  MapMem regions are allocated via
> + * gxio_trio_alloc_memory_maps().  Given an integer MapMem number,
> + * applications can use gxio_trio_init_memory_map() to specify the
> + * range of bus addresses that will match the region and the range of
> + * virtual addresses to which those packets will be applied.
> + *
> + * As with many other gxio APIs, the programmer must be sure to
> + * register memory pages that will be used with MapMem regions.  Pages
> + * can be registered with TRIO by allocating an ASID (address space
> + * identifier) and then using gxio_trio_register_page() to register up to
> + * 16 pages with the hardware.  The initialization functions for
> + * resources that require registered memory (MapMem, scatter queues,
> + * push DMA, and pull DMA) then take an 'asid' parameter in order to
> + * configure which set of registered pages is used by each resource.
> + *
> + * @subsection trio__scatter_queue TRIO Scatter Queues
> + *
> + * The TRIO shim's scatter queue regions allow users to dynamically
> + * map buffers from a large address space into a small range of bus
> + * addresses.  This is particularly helpful for PCIe endpoint devices,
> + * where the host generally limits the size of BARs to tens of
> + * megabytes.
> + *
> + * Each scatter queue consists of a memory map region, a queue of
> + * tile-side buffer VAs to be mapped to that region, and a bus-mapped
> + * "doorbell" register that the remote endpoint can write to trigger a
> + * dequeue of the current buffer VA, thus swapping in a new buffer.
> + * The VAs pushed onto a scatter queue must be 4kB aligned, so
> + * applications may need to use higher-level protocols to inform
> + * remote entities that they should apply some additional, sub-4kB
> + * offset when reading or writing the scatter queue region.  For more
> + * information, see the IO Device Guide (UG404).
> + *
> + * @section trio__egress TRIO Egress Hardware Resources
> + *
> + * The TRIO shim supports two mechanisms for egress packet generation:
> + * programmed IO (PIO) and push/pull DMA.  PIO allows applications to
> + * create MMIO mappings for PCIe or StreamIO address space, such that
> + * the application can generate word-sized read or write transactions
> + * by issuing load or store instructions.  Push and pull DMA are tuned
> + * for larger transactions; they use specialized hardware engines to
> + * transfer large blocks of data at line rate.
> + *
> + * @subsection trio__pio TRIO Programmed IO
> + *
> + * Programmed IO allows applications to create MMIO mappings for PCIe
> + * or StreamIO address space.  The hardware PIO regions support access
> + * to PCIe configuration, IO, and memory space, but the gxio_trio API
> + * only supports memory space accesses.  PIO regions are allocated
> + * with gxio_trio_alloc_pio_regions() and initialized via
> + * gxio_trio_init_pio_region().  Once a region is bound to a range of
> + * bus address via the initialization function, the application can
> + * use gxio_trio_map_pio_region() to create MMIO mappings from its VA
> + * space onto the range of bus addresses supported by the PIO region.
> + *
> + * @subsection trio_dma TRIO Push and Pull DMA
> + *
> + * The TRIO push and pull DMA engines allow users to copy blocks of
> + * data between application memory and the bus.  Push DMA generates
> + * write packets that copy from application memory to the bus and pull
> + * DMA generates read packets that copy from the bus into application
> + * memory.  The DMA engines are managed via an API that is very
> + * similar to the mPIPE eDMA interface.  For a detailed explanation of
> + * the eDMA queue API, see @ref gxio_mpipe_wrappers.
> + *
> + * Push and pull DMA queues are allocated via
> + * gxio_trio_alloc_push_dma_ring() / gxio_trio_alloc_pull_dma_ring().
> + * Once allocated, users generally use a ::gxio_trio_dma_queue_t
> + * object to manage the queue, providing easy wrappers for reserving
> + * command slots in the DMA command ring, filling those slots, and
> + * waiting for commands to complete.  DMA queues can be initialized
> + * via gxio_trio_init_push_dma_queue() or
> + * gxio_trio_init_pull_dma_queue().
> + *
> + * See @ref trio/push_dma/app.c for an example of how to use push DMA.
> + *
> + * @section trio_shortcomings Plans for Future API Revisions
> + *
> + * The API and simulation framework is incomplete.  Future features
> + * include:
> + *
> + * - Support for larger page sizes.  Each hardware IOTLB can only map
> + * 16 pages at a time, so applications are currently limited to 16 *
> + * 16MB = 256MB of packet memory.  Larger page sizes will allow
> + * applications to map arbitrary amounts of packet memory.
> + *
> + * - Support for reset and deallocation of resources.
> + *
> + * - Support for pull DMA.
> + *
> + * - Support for interrupt regions and user-space interrupt delivery.
> + *
> + * - Support for getting BAR mappings and reserving regions of BAR
> + *   address space.
> + */
> +#ifndef _GXIO_TRIO_H_
> +#define _GXIO_TRIO_H_
> +
> +#include "common.h"
> +#include "dma_queue.h"
> +
> +#include <arch/trio_constants.h>
> +#include <arch/trio.h>
> +#include <arch/trio_pcie_intfc.h>
> +#include <arch/trio_pcie_rc.h>
> +#include <arch/trio_shm.h>
> +#include <hv/drv_trio_intf.h>
> +#include <hv/iorpc.h>
> +
> +/* A context object used to manage TRIO hardware resources. */
> +typedef struct {
> +
> +  /* File descriptor for calling up to Linux (and thus the HV). */
> +	int fd;
> +
> +  /* The VA at which the MAC MMIO registers are mapped. */
> +	char *mmio_base_mac;
> +
> +  /* The VA at which the PIO config space are mapped for each PCIe MAC.
> +      Gx36 has max 3 PCIe MACs per TRIO shim. */
> +	char *mmio_base_pio_cfg[TILEGX_TRIO_PCIES];
> +
> +#ifdef USE_SHARED_PCIE_CONFIG_REGION
> +  /* Index of the shared PIO region for PCI config access. */
> +	int pio_cfg_index;
> +#else
> +  /* Index of the PIO region for PCI config access per MAC. */
> +	int pio_cfg_index[TILEGX_TRIO_PCIES];
> +#endif
> +
> +  /*  The VA at which the push DMA MMIO registers are mapped. */
> +	char *mmio_push_dma[TRIO_NUM_PUSH_DMA_RINGS];
> +
> +  /*  The VA at which the pull DMA MMIO registers are mapped. */
> +	char *mmio_pull_dma[TRIO_NUM_PUSH_DMA_RINGS];
> +
> +  /* Application space ID. */
> +	unsigned int asid;
> +
> +} gxio_trio_context_t;
> +
> +/* Command descriptor for push or pull DMA. */
> +typedef TRIO_DMA_DESC_t gxio_trio_dma_desc_t;
> +
> +/* A convenient, thread-safe interface to an eDMA ring. */
> +typedef struct {
> +
> +  /* State object for tracking head and tail pointers. */
> +	__gxio_dma_queue_t dma_queue;
> +
> +  /* The ring entries. */
> +	gxio_trio_dma_desc_t *dma_descs;
> +
> +  /* The number of entries minus one. */
> +	unsigned long mask_num_entries;
> +
> +  /* The log2() of the number of entries. */
> +	unsigned int log2_num_entries;
> +
> +} gxio_trio_dma_queue_t;
> +
> +/* Initialize a TRIO context.
> + *
> + * This function allocates a TRIO "service domain" and maps the MMIO
> + * registers into the the caller's VA space.
> + *
> + * @param trio_index Which TRIO shim; Gx36 must pass 0.
> + * @param context Context object to be initialized.
> + */
> +extern int
> +gxio_trio_init(gxio_trio_context_t * context, unsigned int trio_index);
> +
> +/* This indicates that an ASID hasn't been allocated. */
> +#define GXIO_ASID_NULL -1
> +
> +/* Ordering modes for map memory regions and scatter queue regions. */
> +typedef enum gxio_trio_order_mode_e {
> +  /* Writes are not ordered.  Reads always wait for previous writes. */
> +	GXIO_TRIO_ORDER_MODE_UNORDERED =
> +	    TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_UNORDERED,
> +  /* Both writes and reads wait for previous transactions to complete. */
> +	GXIO_TRIO_ORDER_MODE_STRICT = TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_STRICT,
> +  /* Writes are ordered unless the incoming packet has the
> +      relaxed-ordering attributes set. */
> +	GXIO_TRIO_ORDER_MODE_OBEY_PACKET =
> +	    TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_REL_ORD
> +} gxio_trio_order_mode_t;
> +
> +/* Initialize a memory mapping region.
> + *
> + * @param context An initialized TRIO context.
> + * @param map A Memory map region allocated by gxio_trio_alloc_memory_map().
> + * @param target_mem VA of backing memory, should be registered via
> + *   gxio_trio_register_page() and aligned to 4kB.
> + * @param target_size Length of the memory mapping, must be a multiple
> + * of 4kB.
> + * @param asid ASID to be used for Tile-side address translation.
> + * @param mac MAC number.
> + * @param bus_address Bus address at which the mapping starts.
> + * @param order_mode Memory ordering mode for this mapping.
> + * @return Zero on success, else ::GXIO_TRIO_ERR_BAD_MEMORY_MAP,
> + * GXIO_TRIO_ERR_BAD_ASID, or ::GXIO_TRIO_ERR_BAD_BUS_RANGE.
> + */
> +extern int
> +gxio_trio_init_memory_map(gxio_trio_context_t * context, unsigned int map,
> +			  void *target_mem, size_t target_size,
> +			  unsigned int asid,
> +			  unsigned int mac,
> +			  uint64_t bus_address,
> +			  gxio_trio_order_mode_t order_mode);
> +
> +/* Flags that can be passed to resource allocation functions. */
> +enum gxio_trio_alloc_flags_e {
> +	GXIO_TRIO_ALLOC_FIXED = HV_TRIO_ALLOC_FIXED,
> +};
> +
> +/* Flags that can be passed to memory registration functions. */
> +enum gxio_trio_mem_flags_e {
> +  /* Do not fill L3 when writing, and invalidate lines upon egress. */
> +	GXIO_TRIO_MEM_FLAG_NT_HINT = IORPC_MEM_BUFFER_FLAG_NT_HINT,
> +
> +  /* L3 cache fills should only populate IO cache ways. */
> +	GXIO_TRIO_MEM_FLAG_IO_PIN = IORPC_MEM_BUFFER_FLAG_IO_PIN,
> +};
> +
> +/* Flag indicating a request generator uses a special traffic
> +    class. */
> +#define GXIO_TRIO_FLAG_TRAFFIC_CLASS(N) HV_TRIO_FLAG_TC(N)
> +
> +/* Flag indicating a request generator uses a virtual function
> +    number. */
> +#define GXIO_TRIO_FLAG_VFUNC(N) HV_TRIO_FLAG_VFUNC(N)
> +
> +/*****************************************************************
> + *                       Memory Registration                      *
> + ******************************************************************/
> +
> +/* Allocate Application Space Identifiers (ASIDs).  Each ASID can
> + * register up to 16 page translations.  ASIDs are used by memory map
> + * regions, scatter queues, and DMA queues to translate application
> + * VAs into memory system PAs.
> + *
> + * @param context An initialized TRIO context.
> + * @param count Number of ASIDs required.
> + * @param first Index of first ASID if ::GXIO_TRIO_ALLOC_FIXED flag
> + *   is set, otherwise ignored.
> + * @param flags Flag bits, including bits from ::gxio_trio_alloc_flags_e.
> + * @return Index of first ASID, or ::GXIO_TRIO_ERR_NO_ASID if allocation
> + *   failed.
> + */
> +extern int
> +gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
> +		      unsigned int first, unsigned int flags);
> +
> +#endif /* ! _GXIO_TRIO_H_ */
> diff --git a/arch/tile/include/hv/drv_trio_intf.h b/arch/tile/include/hv/drv_trio_intf.h
> new file mode 100644
> index 0000000..18e8704
> --- /dev/null
> +++ b/arch/tile/include/hv/drv_trio_intf.h
> @@ -0,0 +1,196 @@
> +/*
> + * Copyright 2012 Tilera Corporation. All Rights Reserved.
> + *
> + *   This program is free software; you can redistribute it and/or
> + *   modify it under the terms of the GNU General Public License
> + *   as published by the Free Software Foundation, version 2.
> + *
> + *   This program is distributed in the hope that it will be useful, but
> + *   WITHOUT ANY WARRANTY; without even the implied warranty of
> + *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + *   NON INFRINGEMENT.  See the GNU General Public License for
> + *   more details.
> + */
> +
> +/**
> + * Interface definitions for the trio driver.
> + */
> +
> +#ifndef _SYS_HV_DRV_TRIO_INTF_H
> +#define _SYS_HV_DRV_TRIO_INTF_H
> +
> +#include <arch/trio.h>
> +
> +/** The vendor ID for all Tilera processors. */
> +#define TILERA_VENDOR_ID 0x1a41
> +
> +/** The device ID for the Gx36 processor. */
> +#define TILERA_GX36_DEV_ID 0x0200
> +
> +/** Device ID for our internal bridge when running as RC. */
> +#define TILERA_GX36_RC_DEV_ID 0x2000
> +
> +/** Maximum number of TRIO interfaces. */
> +#define TILEGX_NUM_TRIO         2
> +
> +/** Gx36 has max 3 PCIe MACs per TRIO interface. */
> +#define TILEGX_TRIO_PCIES       3
> +
> +/** Specify port properties for a PCIe MAC. */
> +struct pcie_port_property
> +{
> +  /** If true, the link can be configured in PCIe root complex mode. */
> +  uint8_t allow_rc: 1;
> +
> +  /** If true, the link can be configured in PCIe endpoint mode. */
> +  uint8_t allow_ep: 1;
> +
> +  /** If true, the link can be configured in StreamIO mode. */
> +  uint8_t allow_sio: 1;
> +
> +  /** If true, the link is allowed to support 1-lane operation. Software
> +   *  will not consider it an error if the link comes up as a x1 link. */
> +  uint8_t allow_x1: 1;
> +
> +  /** If true, the link is allowed to support 2-lane operation. Software
> +   *  will not consider it an error if the link comes up as a x2 link. */
> +  uint8_t allow_x2: 1;
> +
> +  /** If true, the link is allowed to support 4-lane operation. Software
> +   *  will not consider it an error if the link comes up as a x4 link. */
> +  uint8_t allow_x4: 1;
> +
> +  /** If true, the link is allowed to support 8-lane operation. Software
> +   *  will not consider it an error if the link comes up as a x8 link. */
> +  uint8_t allow_x8: 1;
> +
> +  /** Reserved. */
> +  uint8_t reserved: 1;
> +
> +};
> +
> +/** Configurations can be issued to configure a char stream interrupt. */
> +typedef enum pcie_stream_intr_config_sel_e
> +{
> +  /** Interrupt configuration for memory map regions. */
> +  MEM_MAP_SEL,
> +
> +  /** Interrupt configuration for push DMAs. */
> +  PUSH_DMA_SEL,
> +
> +  /** Interrupt configuration for pull DMAs. */
> +  PULL_DMA_SEL,
> +}
> +pcie_stream_intr_config_sel_t;
> +
> +
> +/** The mmap file offset (PA) of the TRIO config region. */
> +#define HV_TRIO_CONFIG_OFFSET                                        \
> +  ((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_CFG <<   \
> +    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT)
> +
> +/** The maximum size of the TRIO config region. */
> +#define HV_TRIO_CONFIG_SIZE                                 \
> +  (1ULL << TRIO_CFG_REGION_ADDR__REGION_SHIFT)
> +
> +/** Size of the config region mapped into client. We can't use
> + *  TRIO_MMIO_ADDRESS_SPACE__OFFSET_WIDTH because it
> + *  will require the kernel to allocate 4GB VA space
> + *  from the VMALLOC region which has a total range
> + *  of 4GB.
> + */
> +#define HV_TRIO_CONFIG_IOREMAP_SIZE                            \
> +  ((uint64_t) 1 << TRIO_CFG_REGION_ADDR__PROT_SHIFT)
> +
> +/** The mmap file offset (PA) of a scatter queue region. */
> +#define HV_TRIO_SQ_OFFSET(queue)                                        \
> +  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_MAP_SQ <<   \
> +    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
> +   ((queue) << TRIO_MAP_SQ_REGION_ADDR__SQ_SEL_SHIFT))
> +
> +/** The maximum size of a scatter queue region. */
> +#define HV_TRIO_SQ_SIZE                                 \
> +  (1ULL << TRIO_MAP_SQ_REGION_ADDR__SQ_SEL_SHIFT)
> +
> +
> +/** The "hardware MMIO region" of the first PIO region. */
> +#define HV_TRIO_FIRST_PIO_REGION 8
> +
> +/** The mmap file offset (PA) of a PIO region. */
> +#define HV_TRIO_PIO_OFFSET(region)                           \
> +  (((unsigned long long)(region) + HV_TRIO_FIRST_PIO_REGION) \
> +   << TRIO_PIO_REGIONS_ADDR__REGION_SHIFT)
> +
> +/** The maximum size of a PIO region. */
> +#define HV_TRIO_PIO_SIZE (1ULL << TRIO_PIO_REGIONS_ADDR__ADDR_WIDTH)
> +
> +
> +/** The mmap file offset (PA) of a push DMA region. */
> +#define HV_TRIO_PUSH_DMA_OFFSET(ring)                                   \
> +  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_PUSH_DMA << \
> +    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
> +   ((ring) << TRIO_PUSH_DMA_REGION_ADDR__RING_SEL_SHIFT))
> +
> +/** The mmap file offset (PA) of a pull DMA region. */
> +#define HV_TRIO_PULL_DMA_OFFSET(ring)                                   \
> +  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_PULL_DMA << \
> +    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
> +   ((ring) << TRIO_PULL_DMA_REGION_ADDR__RING_SEL_SHIFT))
> +
> +/** The maximum size of a DMA region. */
> +#define HV_TRIO_DMA_REGION_SIZE                         \
> +  (1ULL << TRIO_PUSH_DMA_REGION_ADDR__RING_SEL_SHIFT)
> +
> +
> +/** The mmap file offset (PA) of a Mem-Map interrupt region. */
> +#define HV_TRIO_MEM_MAP_INTR_OFFSET(map)                                 \
> +  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_MAP_MEM <<   \
> +    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
> +   ((map) << TRIO_MAP_MEM_REGION_ADDR__MAP_SEL_SHIFT))
> +
> +/** The maximum size of a Mem-Map interrupt region. */
> +#define HV_TRIO_MEM_MAP_INTR_SIZE                                 \
> +  (1ULL << TRIO_MAP_MEM_REGION_ADDR__MAP_SEL_SHIFT)
> +
> +
> +/** A flag bit indicating a fixed resource allocation. */
> +#define HV_TRIO_ALLOC_FIXED 0x01
> +
> +/** TRIO requires that all mappings have 4kB aligned start addresses. */
> +#define HV_TRIO_PAGE_SHIFT 12
> +
> +/** TRIO requires that all mappings have 4kB aligned start addresses. */
> +#define HV_TRIO_PAGE_SIZE (1ull << HV_TRIO_PAGE_SHIFT)
> +
> +
> +

3 blank lines seems excessive - surely 2 is enough.


> +/* Specify all PCIe port properties for a TRIO. */
> +struct pcie_trio_ports_property
> +{
> +  struct pcie_port_property ports[TILEGX_TRIO_PCIES];
> +};
> +
> +/* Flags indicating traffic class. */
> +#define HV_TRIO_FLAG_TC_SHIFT 4
> +#define HV_TRIO_FLAG_TC_RMASK 0xf
> +#define HV_TRIO_FLAG_TC(N) \
> +  ((((N) & HV_TRIO_FLAG_TC_RMASK) + 1) << HV_TRIO_FLAG_TC_SHIFT)
> +
> +/* Flags indicating virtual functions. */
> +#define HV_TRIO_FLAG_VFUNC_SHIFT 8
> +#define HV_TRIO_FLAG_VFUNC_RMASK 0xff
> +#define HV_TRIO_FLAG_VFUNC(N) \
> +  ((((N) & HV_TRIO_FLAG_VFUNC_RMASK) + 1) << HV_TRIO_FLAG_VFUNC_SHIFT)
> +
> +
> +/* Flag indicating an ordered PIO region. */
> +#define HV_TRIO_PIO_FLAG_ORDERED (1 << 16)
> +
> +/* Flags indicating special types of PIO regions. */
> +#define HV_TRIO_PIO_FLAG_SPACE_SHIFT 17
> +#define HV_TRIO_PIO_FLAG_SPACE_MASK (0x3 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
> +#define HV_TRIO_PIO_FLAG_CONFIG_SPACE (0x1 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
> +#define HV_TRIO_PIO_FLAG_IO_SPACE (0x2 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
> +
> +
> +#endif /* _SYS_HV_DRV_TRIO_INTF_H */
> 

-- 
Jesper Juhl <jj@chaosbits.net>       http://www.chaosbits.net/
Don't top-post http://www.catb.org/jargon/html/T/top-post.html
Plain text mails only, please.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/3] arch/tile: provide kernel support for the tilegx TRIO shim
  2012-04-07 23:39   ` Jesper Juhl
@ 2012-04-08  0:21     ` Chris Metcalf
  0 siblings, 0 replies; 19+ messages in thread
From: Chris Metcalf @ 2012-04-08  0:21 UTC (permalink / raw)
  To: Jesper Juhl; +Cc: linux-kernel

On 4/7/2012 7:39 PM, Jesper Juhl wrote:
> On Sat, 7 Apr 2012, Chris Metcalf wrote:
>> Provide kernel support for the tilegx "Transaction I/O" (TRIO) on-chip
>> hardware.  This hardware implements the PCIe interface for tilegx;
>> the driver changes to use TRIO for PCIe are in a subsequent commit.
>>
>> The change is layered on top of the tilegx GXIO IORPC subsystem.
>>
>> Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
>> [...]
>> +/* This file is machine-generated; DO NOT EDIT! */
>> +#include "gxio/iorpc_trio.h"
>> +
>> +typedef struct {
>> +     unsigned int count;
>> +     unsigned int first;
>> +     unsigned int flags;
>> +} alloc_asids_param_t;
>> +
>> +int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
>> +                       unsigned int first, unsigned int flags)
>> +{
>> +     uint64_t __offset;
>> +     int __result;
>> +     alloc_asids_param_t temp;
>> +     alloc_asids_param_t *params = &temp;
>> +     size_t __size = sizeof(*params);
>> +
>> +     params->count = count;
>> +     params->first = first;
>> +     params->flags = flags;
>> +
>> +     __offset = GXIO_TRIO_OP_ALLOC_ASIDS;
>> +     __result =
>> +         hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, __size,
>> +                       __offset);
>> +     return __result;
>> +}
> Having the "__offset" variable seems redundant here. It is declared, then
> later initialized to GXIO_TRIO_OP_ALLOC_ASIDS and then later used just
> once.
> I'd say either initialize it to GXIO_TRIO_OP_ALLOC_ASIDS when it's
> declared (and make that variable const) or just get rid of it entirely and
> just use GXIO_TRIO_OP_ALLOC_ASIDS directly in the one place the variable
> is used.
> This goes for other functions as well, using a __offset variable in a
> similar way - not going to explicitly point them all out.

Yes, there's certainly a tension here: as the comment at the top points
out, this file is machine-generated.  The compiled object code will clearly
be just as good whether __offset is done in a terser and more normal style,
or if it is done the way the generating code does it now.  This code also
comes from "upstream" internally at Tilera in the sense that Linux just
uses files that are generated by code in the hypervisor build process.  But
I can certainly look into whether the generated files can be easily made
terser.

> What's the point of the "__result" variable? why not just get rid of it
> and just "return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
> __size, __offset);" ??
> Goes for other functions as well..

Yes, same issue here too, and I'll look into this as well.

>> [...]
>> +int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
>> +                              int inter_y, int inter_ipi, int inter_event,
>> +                              unsigned int mac, unsigned int intx)
>> +{
>> +     uint64_t __offset;
>> +     int __result;
>> +     config_legacy_intr_param_t temp;
>> +     config_legacy_intr_param_t *params = &temp;
>> +     size_t __size = sizeof(*params);
>> +
> const size_t __size = sizeof(*params);  ??? or maybe just get rid of the
> variable since it is only used once.?

I don't see "const" used that much in the kernel (though there does seem to
be a slight swing towards more of it despite the threat of "const
poisoning" issues).  Getting rid of the variable might or might not be
easy, again, depending on the code generator issues.  I'll check.

>> [...]
>> +#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1419)
>> +#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a)
>> +#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141b)
>> +#define GXIO_TRIO_OP_CONFIG_CHAR_INTR  IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141c)
>> +#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d)
>> +#define GXIO_TRIO_OP_FORCE_LINK_UP     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
>> +#define GXIO_TRIO_OP_GET_MMIO_BASE     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
>> +#define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
>> +
>
> There is some funky formatting going on here (or my email client is
> playing tricks on me) :

The code generator here is trying to align the #define values at column 40
and if the #define symbol is too long, it just uses one space and leaves it
at that.

>> [...]
>> +int gxio_trio_force_link_up(gxio_trio_context_t * context, unsigned int mac);
>> +
>> +int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base);
>> +
>> +int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
>> +                             unsigned long offset, unsigned long size);
>> +
> First of all, when you have "pointer_type * variable", please use the
> style "pointer_type *variable" - as per accepted kernel coding style.

Yes, this is a bug from my missing some typenames when using "indent" to
try to force the upstream files into something closer to standard Linux
format.  I can add some "-T" arguments to remove the extra whitespace.

> Also, I find the indentation to be inconsistent; varuing from function to
> function - is it just my email client or??  If not, please fix.

The upstream code style is closer to FSF, with the return typename on the
line before the function.  Using "indent -npsl" is theoretically supposed
to fix this to Linux style, but in fact it appears that if the function and
its arguments is longer than 80 columns, indent "helpfully" doesn't do
this.  I'd like to fix this in a mechanical way so I don't end up in merge
hell in a year or two, but failing that I'm planning to just leave this
code with some signatures in the wrong style; it seems the lesser of
several evils.

>> +/** TRIO requires that all mappings have 4kB aligned start addresses. */
>> +#define HV_TRIO_PAGE_SIZE (1ull << HV_TRIO_PAGE_SHIFT)
>> +
>> +
>> +
> 3 blank lines seems excessive - surely 2 is enough.

Fixed.

Thanks for your review - I appreciate it!

-- 
Chris Metcalf, Tilera Corp.
http://www.tilera.com


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-04-07 21:10 ` [PATCH 3/3] arch/tile: tilegx PCI root complex support Chris Metcalf
@ 2012-04-09 13:59   ` Arnd Bergmann
  2012-04-09 21:38     ` Chris Metcalf
  2012-04-10  0:01   ` [PATCH 3/3] " Bjorn Helgaas
  2012-06-19 19:50   ` Geert Uytterhoeven
  2 siblings, 1 reply; 19+ messages in thread
From: Arnd Bergmann @ 2012-04-09 13:59 UTC (permalink / raw)
  To: Chris Metcalf
  Cc: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Jiri Kosina, Joe Perches,
	David Howells

On Saturday 07 April 2012, Chris Metcalf wrote:
> This change implements PCIe root complex support for tilegx using
> the kernel support layer for accessing the TRIO hardware shim.
> 
> Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>

Hi Chris,

I don't know if we discussed it during the initial merge, but I notice that the PIO
accessors (inb/outb and friends) are still not implemented in this patch. Normally
PIO can just be mapped into the MMIO address space, so that inb() becomes
a call to readb() with an offset on the address.

> +/*
> + * Second PCI initialization entry point, called by subsys_initcall.
> + *
> + * The controllers have been set up by the time we get here, by a call to
> + * tile_pci_init.
> + */
> +int __devinit pcibios_init(void)
> +{
> +	resource_size_t offset;
> +	int i;
> +
> +        if (num_rc_controllers == 0 && num_ep_controllers == 0)
> +		return 0;
> +
> +	pr_info("PCI: Probing PCI hardware\n");
> +
> +	/*
> +	 * We loop over all the TRIO shims and set up the MMIO mappings.
> +	 * This step can't be done in tile_pci_init because the MM subsystem
> +	 * hasn't been initialized then.
> +	 */
> +	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
> +		gxio_trio_context_t *context = &trio_contexts[i];
> +
> +		if (context->fd < 0)
> +			continue;
> +
> +		/*
> +		 * Map in the MMIO space for the MAC.
> +                 */
> +		offset = 0;
> +		context->mmio_base_mac =
> +			iorpc_ioremap(context->fd, offset,
> +				      HV_TRIO_CONFIG_IOREMAP_SIZE);
> +		if (context->mmio_base_mac == NULL) {
> +			pr_err("PCI: MAC map failure on TRIO %d\n", i);
> +
> +			hv_dev_close(context->fd);
> +			context->fd = -1;
> +			continue;
> +		}
> +	}
> +
> +	/*
> +	 * Delay a bit in case devices aren't ready.  Some devices are
> +	 * known to require at least 20ms here, but we use a more
> +	 * conservative value.
> +	 */
> +	mdelay(250);

Using mdelay is generally considered very rude. Since you are not in atomic
context here, just use msleep() instead.

	Arnd

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-04-09 13:59   ` Arnd Bergmann
@ 2012-04-09 21:38     ` Chris Metcalf
  2012-04-10  9:14       ` Arnd Bergmann
  0 siblings, 1 reply; 19+ messages in thread
From: Chris Metcalf @ 2012-04-09 21:38 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Jiri Kosina, Joe Perches,
	David Howells

On 4/9/2012 9:59 AM, Arnd Bergmann wrote:
> On Saturday 07 April 2012, Chris Metcalf wrote:
>> This change implements PCIe root complex support for tilegx using
>> the kernel support layer for accessing the TRIO hardware shim.
>>
>> Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
> Hi Chris,
>
> I don't know if we discussed it during the initial merge, but I notice that the PIO
> accessors (inb/outb and friends) are still not implemented in this patch. Normally
> PIO can just be mapped into the MMIO address space, so that inb() becomes
> a call to readb() with an offset on the address.

I asked our PCI expert here, who said, "My understanding is that if someone
wants to use inb/outb to access MMIO space, he'll get the MMIO, as opposed
to methods implemented with I/O instructions which are not supported by
TILE.  If the driver is dependent on the I/O instructions, it won't work on
TILE. These drivers are legacy PC drivers, e.g. ATA devices, which are not
supported by TILE."

Should we just arrange to #include <asm-generic/io.h> to pick up inb/outb
et al?  Any reason to think a non-zero offset should be part of the
solution?  (I don't really understand how inb/outb are used by modern drivers.)

> Using mdelay is generally considered very rude. Since you are not in
> atomic context here, just use msleep() instead.

Done.

Thanks for all your reviews!

-- 
Chris Metcalf, Tilera Corp.
http://www.tilera.com


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-04-07 21:10 ` [PATCH 3/3] arch/tile: tilegx PCI root complex support Chris Metcalf
  2012-04-09 13:59   ` Arnd Bergmann
@ 2012-04-10  0:01   ` Bjorn Helgaas
  2012-04-10  9:15     ` Arnd Bergmann
  2012-04-15 23:09     ` Chris Metcalf
  2012-06-19 19:50   ` Geert Uytterhoeven
  2 siblings, 2 replies; 19+ messages in thread
From: Bjorn Helgaas @ 2012-04-10  0:01 UTC (permalink / raw)
  To: Chris Metcalf
  Cc: linux-kernel, linux-pci, Jesse Barnes, Michael S. Tsirkin,
	Myron Stowe, Arnd Bergmann, Jiri Kosina, Joe Perches,
	David Howells

On Sat, Apr 7, 2012 at 3:10 PM, Chris Metcalf <cmetcalf@tilera.com> wrote:
> This change implements PCIe root complex support for tilegx using
> the kernel support layer for accessing the TRIO hardware shim.

> +static void __devinit fixup_read_and_payload_sizes(struct pci_controller *
> +                                               controller)
> +{
> +       gxio_trio_context_t *trio_context = controller->trio;
> +       TRIO_PCIE_RC_DEVICE_CONTROL_t dev_control;
> +       TRIO_PCIE_RC_DEVICE_CAP_t rc_dev_cap;
> +       unsigned int smallest_max_payload;
> +       struct pci_dev *dev = NULL;
> +       unsigned int reg_offset;
> +       u16 new_values;
> +       int mac;
> +       int err;
> +
> +       mac = controller->mac;
> +
> +       /*
> +        * Set our max read request size to be 4KB.
> +        */
> +       reg_offset =
> +               (TRIO_PCIE_RC_DEVICE_CONTROL <<
> +                       TRIO_CFG_REGION_ADDR__REG_SHIFT) |
> +               (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
> +                       TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
> +               (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
> +
> +       dev_control.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
> +                                               reg_offset);
> +       dev_control.max_read_req_sz = 5;
> +       __gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
> +                                               dev_control.word);
> +
> +       /*
> +        * Set the max payload size supported by this Gx PCIe MAC.
> +        * Though Gx PCIe supports Max Payload Size of up to 1024 bytes,
> +        * experiments have shown that setting MPS to 256 yields the
> +        * best performance.
> +        */
> +       reg_offset =
> +               (TRIO_PCIE_RC_DEVICE_CAP <<
> +                       TRIO_CFG_REGION_ADDR__REG_SHIFT) |
> +               (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
> +                       TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
> +               (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
> +
> +       rc_dev_cap.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
> +                                               reg_offset);
> +       rc_dev_cap.mps_sup = 1;
> +       __gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
> +                                               rc_dev_cap.word);
> +
> +       smallest_max_payload = rc_dev_cap.mps_sup;
> +
> +       /* Scan for the smallest maximum payload size. */
> +       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {

Can this be done with the generic pcie_bus_configure_settings() or is
there something tilegx-specific about this?

> +               int pcie_caps_offset;
> +               u32 devcap;
> +               int max_payload;
> +
> +               /* Skip device that is not in this PCIe domain. */
> +               if ((struct pci_controller *)dev->sysdata != controller)
> +                       continue;
> +
> +               pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
> +               if (pcie_caps_offset == 0)
> +                       continue;
> +
> +               pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP,
> +                                     &devcap);
> +               max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD;
> +               if (max_payload < smallest_max_payload)
> +                       smallest_max_payload = max_payload;
> +       }
> +
> +       /* Now, set the max_payload_size for all devices to that value. */
> +       new_values = smallest_max_payload << 5;
> +       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
> +               int pcie_caps_offset;
> +               u16 devctl;
> +
> +               /* Skip device that is not in this PCIe domain. */
> +               if ((struct pci_controller *)dev->sysdata != controller)
> +                       continue;
> +
> +               pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
> +               if (pcie_caps_offset == 0)
> +                       continue;
> +
> +               pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
> +                                    &devctl);
> +               devctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
> +               devctl |= new_values;
> +               pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
> +                                     devctl);
> +       }
> +
> +       /*
> +        * Set the mac_config register in trio based on the MPS/MRS of the link.
> +        */
> +        err = gxio_trio_set_mps_mrs(trio_context,
> +                        smallest_max_payload,
> +                        dev_control.max_read_req_sz,
> +                        mac);
> +        if (err < 0) {
> +               pr_err("PCI: PCIE_CONFIGURE_MAC_MPS_MRS failure, "
> +                       "MAC %d on TRIO %d\n",
> +                       mac, controller->trio_index);
> +       }
> +}
> +
> +
> +/*
> + * Second PCI initialization entry point, called by subsys_initcall.
> + *
> + * The controllers have been set up by the time we get here, by a call to
> + * tile_pci_init.
> + */
> +int __devinit pcibios_init(void)
> +{
> +       resource_size_t offset;
> +       int i;
> +
> +        if (num_rc_controllers == 0 && num_ep_controllers == 0)
> +               return 0;
> +
> +       pr_info("PCI: Probing PCI hardware\n");
> +
> +       /*
> +        * We loop over all the TRIO shims and set up the MMIO mappings.
> +        * This step can't be done in tile_pci_init because the MM subsystem
> +        * hasn't been initialized then.
> +        */
> +       for (i = 0; i < TILEGX_NUM_TRIO; i++) {
> +               gxio_trio_context_t *context = &trio_contexts[i];
> +
> +               if (context->fd < 0)
> +                       continue;
> +
> +               /*
> +                * Map in the MMIO space for the MAC.
> +                 */
> +               offset = 0;
> +               context->mmio_base_mac =
> +                       iorpc_ioremap(context->fd, offset,
> +                                     HV_TRIO_CONFIG_IOREMAP_SIZE);
> +               if (context->mmio_base_mac == NULL) {
> +                       pr_err("PCI: MAC map failure on TRIO %d\n", i);
> +
> +                       hv_dev_close(context->fd);
> +                       context->fd = -1;
> +                       continue;
> +               }
> +       }
> +
> +       /*
> +        * Delay a bit in case devices aren't ready.  Some devices are
> +        * known to require at least 20ms here, but we use a more
> +        * conservative value.
> +        */
> +       mdelay(250);
> +
> +       /* Scan all of the recorded PCI controllers.  */
> +       for (i = 0; i < num_rc_controllers; i++) {
> +               struct pci_controller *controller = &pci_controllers[i];
> +               gxio_trio_context_t *trio_context = controller->trio;
> +               TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
> +               TRIO_PCIE_INTFC_PORT_STATUS_t port_status;
> +               TRIO_PCIE_INTFC_TX_FIFO_CTL_t tx_fifo_ctl;
> +               struct pci_bus *bus;
> +               unsigned int reg_offset;
> +               unsigned int class_code_revision;
> +               int mac;
> +#ifndef USE_SHARED_PCIE_CONFIG_REGION
> +               int ret;
> +#endif
> +
> +               if (trio_context->fd < 0)
> +                       continue;
> +
> +               mac = controller->mac;
> +
> +               /*
> +                * Check the port strap state which will override the BIB
> +                * setting.
> +                */
> +
> +               reg_offset =
> +                       (TRIO_PCIE_INTFC_PORT_CONFIG <<
> +                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
> +                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
> +                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
> +                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
> +
> +               port_config.word =
> +                       __gxio_mmio_read(trio_context->mmio_base_mac +
> +                                        reg_offset);
> +
> +               if ((port_config.strap_state !=
> +                       TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC) &&
> +                       (port_config.strap_state !=
> +                       TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1)) {
> +                       /*
> +                        * If this is really intended to be an EP port,
> +                        * record it so that the endpoint driver will know about it.
> +                        */
> +                       if (port_config.strap_state ==
> +                       TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT ||
> +                       port_config.strap_state ==
> +                       TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1)
> +                               pcie_ports[controller->trio_index][mac].allow_ep = 1;
> +
> +                       continue;
> +               }
> +
> +               ret = gxio_trio_force_link_up(trio_context, mac);
> +               if (ret < 0)
> +                       pr_err("PCI: PCIE_FORCE_LINK_UP failure, "
> +                               "MAC %d on TRIO %d\n",
> +                               mac, controller->trio_index);
> +
> +               pr_info("PCI: Found PCI controller #%d on TRIO %d MAC %d\n", i,
> +                       controller->trio_index, controller->mac);
> +
> +               /*
> +                * Wait a bit here because some EP devices take longer to come up.
> +                */
> +               mdelay(1000);
> +
> +               /*
> +                * Check for PCIe link-up status.
> +                */
> +
> +               reg_offset =
> +                       (TRIO_PCIE_INTFC_PORT_STATUS <<
> +                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
> +                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
> +                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
> +                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
> +
> +               port_status.word =
> +                       __gxio_mmio_read(trio_context->mmio_base_mac +
> +                                        reg_offset);
> +               if (!port_status.dl_up) {
> +                       pr_err("PCI: link is down, MAC %d on TRIO %d\n",
> +                               mac, controller->trio_index);
> +                       continue;
> +               }
> +
> +               /*
> +                * Ensure that the link can come out of L1 power down state.
> +                * Strictly speaking, this is needed only in the case of
> +                * heavy RC-initiated DMAs.
> +                */
> +               reg_offset =
> +                       (TRIO_PCIE_INTFC_TX_FIFO_CTL <<
> +                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
> +                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
> +                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
> +                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
> +               tx_fifo_ctl.word =
> +                       __gxio_mmio_read(trio_context->mmio_base_mac +
> +                                        reg_offset);
> +               tx_fifo_ctl.min_p_credits = 0;
> +               __gxio_mmio_write(trio_context->mmio_base_mac + reg_offset,
> +                                 tx_fifo_ctl.word);
> +
> +               /*
> +                * Change the device ID so that Linux bus crawl doesn't confuse
> +                * the internal bridge with any Tilera endpoints.
> +                */
> +
> +               reg_offset =
> +                       (TRIO_PCIE_RC_DEVICE_ID_VEN_ID <<
> +                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
> +                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
> +                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
> +                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
> +
> +               __gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
> +                                   (TILERA_GX36_RC_DEV_ID <<
> +                                   TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT) |
> +                                   TILERA_VENDOR_ID);
> +
> +               /*
> +                * Set the internal P2P bridge class code.
> +                */
> +
> +               reg_offset =
> +                       (TRIO_PCIE_RC_REVISION_ID <<
> +                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
> +                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
> +                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
> +                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
> +
> +               class_code_revision =
> +                       __gxio_mmio_read32(trio_context->mmio_base_mac +
> +                                          reg_offset);
> +               class_code_revision = (class_code_revision & 0xff ) |
> +                                       (PCI_CLASS_BRIDGE_PCI << 16);
> +
> +               __gxio_mmio_write32(trio_context->mmio_base_mac +
> +                                   reg_offset, class_code_revision);
> +
> +#ifdef USE_SHARED_PCIE_CONFIG_REGION
> +
> +               /*
> +                * Map in the MMIO space for the PIO region.
> +                 */
> +               offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index) |
> +                       (((unsigned long long)mac) <<
> +                       TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
> +
> +#else
> +
> +               /*
> +                * Alloc a PIO region for PCI config access per MAC.
> +                */
> +               ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
> +               if (ret < 0) {
> +                       pr_err("PCI: PCI CFG PIO alloc failure for mac %d "
> +                               "on TRIO %d, give up\n",
> +                               mac, controller->trio_index);
> +
> +                       /* TBD: cleanup ... */
> +
> +                       continue;
> +               }
> +
> +               trio_context->pio_cfg_index[mac] = ret;
> +
> +               /*
> +                * For PIO CFG, the bus_address_hi parameter is 0.
> +                */
> +               ret = gxio_trio_init_pio_region_aux(trio_context,
> +                       trio_context->pio_cfg_index[mac],
> +                       mac, 0, HV_TRIO_PIO_FLAG_CONFIG_SPACE);
> +               if (ret < 0) {
> +                       pr_err("PCI: PCI CFG PIO init failure for mac %d "
> +                               "on TRIO %d, give up\n",
> +                               mac, controller->trio_index);
> +
> +                       /* TBD: cleanup ... */
> +
> +                       continue;
> +               }
> +
> +               offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index[mac]) |
> +                       (((unsigned long long)mac) <<
> +                       TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
> +
> +#endif
> +
> +               trio_context->mmio_base_pio_cfg[mac] =
> +                       iorpc_ioremap(trio_context->fd, offset,
> +                       (1 << TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT));
> +               if (trio_context->mmio_base_pio_cfg[mac] == NULL) {
> +                       pr_err("PCI: PIO map failure for mac %d on TRIO %d\n",
> +                               mac, controller->trio_index);
> +
> +                       /* TBD: cleanup ... */
> +
> +                       continue;
> +               }
> +
> +               /*
> +                * Initialize the PCIe interrupts.
> +                 */
> +               if (tile_init_irqs(controller)) {
> +                       pr_err("PCI: IRQs init failure for mac %d on TRIO %d\n",
> +                               mac, controller->trio_index);
> +
> +                       continue;
> +               }
> +
> +               /*
> +                * This comes from the generic Linux PCI driver.
> +                *
> +                * It reads the PCI tree for this bus into the Linux
> +                * data structures.
> +                *
> +                * This is inlined in linux/pci.h and calls into
> +                * pci_scan_bus_parented() in probe.c.
> +                */
> +               bus = pci_scan_bus(0, controller->ops, controller);

If at all possible, you should use pci_scan_root_bus() here instead,
so you can tell PCI what the host bridge apertures are.

You do fill in pci_controllers[].mem_resources[] below, which looks
like they might be apertures, but I don't see anywhere that the PCI
core would learn about those.

> +               controller->root_bus = bus;
> +               controller->last_busno = bus->subordinate;
> +
> +       }
> +
> +       /* Do machine dependent PCI interrupt routing */
> +       pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
> +
> +       /*
> +        * This comes from the generic Linux PCI driver.
> +        *
> +        * It allocates all of the resources (I/O memory, etc)
> +        * associated with the devices read in above.
> +        */
> +
> +       pci_assign_unassigned_resources();
> +
> +       /* Record the I/O resources in the PCI controller structure. */
> +       for (i = 0; i < num_rc_controllers; i++) {
> +               struct pci_controller *controller = &pci_controllers[i];
> +               gxio_trio_context_t *trio_context = controller->trio;
> +               struct pci_bus *root_bus = pci_controllers[i].root_bus;
> +               struct pci_bus *next_bus;
> +               uint32_t bus_address_hi;
> +               struct pci_dev *dev;
> +               int ret;
> +               int j;
> +
> +               /*
> +                * Skip controllers that are not properly initialized or
> +                * have down links.
> +                */
> +               if (root_bus == NULL)
> +                       continue;
> +
> +               /* Configure the max_payload_size values for this domain. */
> +               fixup_read_and_payload_sizes(controller);
> +
> +               list_for_each_entry(dev, &root_bus->devices, bus_list) {
> +                       /* Find the PCI host controller, ie. the 1st bridge. */
> +                       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
> +                               (PCI_SLOT(dev->devfn) == 0)) {
> +                               next_bus = dev->subordinate;
> +                               pci_controllers[i].mem_resources[0] =
> +                                       *next_bus->resource[0];
> +                               pci_controllers[i].mem_resources[1] =
> +                                        *next_bus->resource[1];
> +                               pci_controllers[i].mem_resources[2] =
> +                                        *next_bus->resource[2];
> +
> +                               break;
> +                       }
> +               }
> +
> +               if (pci_controllers[i].mem_resources[1].flags & IORESOURCE_MEM)
> +                       bus_address_hi =
> +                               pci_controllers[i].mem_resources[1].start >> 32;
> +               else if (pci_controllers[i].mem_resources[2].flags & IORESOURCE_PREFETCH)
> +                       bus_address_hi =
> +                               pci_controllers[i].mem_resources[2].start >> 32;
> +               else {
> +                       /* This is unlikely. */
> +                       pr_err("PCI: no memory resources on TRIO %d mac %d\n",
> +                               controller->trio_index, controller->mac);
> +                       continue;
> +               }
> +
> +               /*
> +                * We always assign 32-bit PCI bus BAR ranges.
> +                 */
> +               BUG_ON(bus_address_hi != 0);
> +
> +               /*
> +                * Alloc a PIO region for PCI memory access for each RC port.
> +                */
> +               ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
> +               if (ret < 0) {
> +                       pr_err("PCI: MEM PIO alloc failure on TRIO %d mac %d, "
> +                               "give up\n", controller->trio_index,
> +                               controller->mac);
> +
> +                       /* TBD: cleanup ... */
> +
> +                       continue;
> +               }
> +
> +               controller->pio_mem_index = ret;
> +
> +               /*
> +                * For PIO MEM, the bus_address_hi parameter is hard-coded 0
> +                * because we always assign 32-bit PCI bus BAR ranges.
> +                 */
> +               ret = gxio_trio_init_pio_region_aux(trio_context,
> +                                                   controller->pio_mem_index,
> +                                                   controller->mac,
> +                                                   bus_address_hi,
> +                                                   0);
> +               if (ret < 0) {
> +                       pr_err("PCI: MEM PIO init failure on TRIO %d mac %d, "
> +                               "give up\n", controller->trio_index,
> +                               controller->mac);
> +
> +                       /* TBD: cleanup ... */
> +
> +                       continue;
> +               }
> +
> +               /*
> +                * Configure a Mem-Map region for each memory controller so
> +                * that Linux can map all of its PA space to the PCI bus.
> +                * Use the IOMMU to handle hash-for-home memory.
> +                 */
> +               for_each_online_node(j) {
> +                       unsigned long start_pfn = node_start_pfn[j];
> +                       unsigned long end_pfn = node_end_pfn[j];
> +                       unsigned long nr_pages = end_pfn - start_pfn;
> +
> +                       ret = gxio_trio_alloc_memory_maps(trio_context, 1, 0,
> +                                                         0);
> +                       if (ret < 0) {
> +                               pr_err("PCI: Mem-Map alloc failure on TRIO %d "
> +                                       "mac %d for MC %d, give up\n",
> +                                       controller->trio_index,
> +                                       controller->mac, j);
> +
> +                               /* TBD: cleanup ... */
> +
> +                               goto alloc_mem_map_failed;
> +                       }
> +
> +                       controller->mem_maps[j] = ret;
> +
> +                       /*
> +                        * Initialize the Mem-Map and the I/O MMU so that all
> +                        * the physical memory can be accessed by the endpoint
> +                        * devices. The base bus address is set to the base CPA
> +                        * of this memory controller, so is the base VA. The
> +                        * I/O MMU table essentially translates the CPA to
> +                        * the real PA.
> +                         */
> +                       ret = gxio_trio_init_memory_map_mmu_aux(trio_context,
> +                               controller->mem_maps[j],
> +                               start_pfn << PAGE_SHIFT,
> +                               nr_pages << PAGE_SHIFT,
> +                               trio_context->asid,
> +                               controller->mac,
> +                               start_pfn << PAGE_SHIFT,
> +                               j,
> +                               GXIO_TRIO_ORDER_MODE_UNORDERED);
> +                       if (ret < 0) {
> +                               pr_err("PCI: Mem-Map init failure on TRIO %d "
> +                                       "mac %d for MC %d, give up\n",
> +                                       controller->trio_index,
> +                                       controller->mac, j);
> +
> +                               /* TBD: cleanup ... */
> +
> +                               goto alloc_mem_map_failed;
> +                       }
> +
> +                       continue;
> +
> +alloc_mem_map_failed:
> +                       break;
> +               }
> +
> +       }
> +
> +       return 0;
> +}
> +subsys_initcall(pcibios_init);

> +int pcibios_enable_device(struct pci_dev *dev, int mask)
> +{
> +       u16 cmd, old_cmd;
> +       u8 header_type;
> +       int i;
> +       struct resource *r;
> +
> +       pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
> +
> +       pci_read_config_word(dev, PCI_COMMAND, &cmd);
> +       old_cmd = cmd;
> +       if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
> +               /*
> +                * For bridges, we enable both memory and I/O decoding
> +                * in call cases.
> +                */
> +               cmd |= PCI_COMMAND_IO;
> +               cmd |= PCI_COMMAND_MEMORY;
> +       } else {
> +               /*
> +                * For endpoints, we enable memory and/or I/O decoding
> +                * only if they have a memory resource of that type.
> +                */
> +               for (i = 0; i < 6; i++) {
> +                       r = &dev->resource[i];
> +                       if (r->flags & IORESOURCE_UNSET) {
> +                               pr_err("PCI: Device %s not available "
> +                                      "because of resource collisions\n",
> +                                      pci_name(dev));
> +                               return -EINVAL;
> +                       }
> +                       if (r->flags & IORESOURCE_IO)
> +                               cmd |= PCI_COMMAND_IO;
> +                       if (r->flags & IORESOURCE_MEM)
> +                               cmd |= PCI_COMMAND_MEMORY;
> +               }

It would be nice if you could use pci_enable_resources() here, though
you use IORESOURCE_UNSET here, while pci_enable_resources() does not.
But you could at least use PCI_NUM_RESOURCES and "mask."  There's
nothing fundamentally architecture-dependent here, so I'd like to move
toward a generic implementation.

> +       }
> +
> +       /*
> +        * We only write the command if it changed.
> +        */
> +       if (cmd != old_cmd)
> +               pci_write_config_word(dev, PCI_COMMAND, cmd);
> +       return 0;
> +}

> +static int __devinit tile_cfg_read(struct pci_bus *bus,
> +                                  unsigned int devfn,
> +                                  int offset,
> +                                  int size,
> +                                  u32 *val)
> +{
> +       struct pci_controller *controller = bus->sysdata;
> +       gxio_trio_context_t *trio_context = controller->trio;
> +       int busnum = bus->number & 0xff;
> +       int device = (devfn >> 3) & 0x1f;
> +       int function = devfn & 0x7;

Could use PCI_SLOT() and PCI_FUNC() here and below.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-04-09 21:38     ` Chris Metcalf
@ 2012-04-10  9:14       ` Arnd Bergmann
  2012-05-08 20:53         ` [PATCH v2 0/2] arch/tile: " Chris Metcalf
  0 siblings, 1 reply; 19+ messages in thread
From: Arnd Bergmann @ 2012-04-10  9:14 UTC (permalink / raw)
  To: Chris Metcalf
  Cc: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Jiri Kosina, Joe Perches,
	David Howells

On Monday 09 April 2012, Chris Metcalf wrote:
> 
> On 4/9/2012 9:59 AM, Arnd Bergmann wrote:
> > On Saturday 07 April 2012, Chris Metcalf wrote:
> >> This change implements PCIe root complex support for tilegx using
> >> the kernel support layer for accessing the TRIO hardware shim.
> >>
> >> Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
> > Hi Chris,
> >
> > I don't know if we discussed it during the initial merge, but I notice that the PIO
> > accessors (inb/outb and friends) are still not implemented in this patch. Normally
> > PIO can just be mapped into the MMIO address space, so that inb() becomes
> > a call to readb() with an offset on the address.
> 
> I asked our PCI expert here, who said, "My understanding is that if someone
> wants to use inb/outb to access MMIO space, he'll get the MMIO, as opposed
> to methods implemented with I/O instructions which are not supported by
> TILE.  If the driver is dependent on the I/O instructions, it won't work on
> TILE. These drivers are legacy PC drivers, e.g. ATA devices, which are not
> supported by TILE."

I'm not sure what that means. The inb/outb instructions cannot be used to access
MMIO, they are only for PIO. They should instead be written to do whatever the
architecture requires for accessing PIO space. While PIO is indeed meant
for legacy x86 accesses and discouraged in new devices, any valid PCI
implementation still needs to support them.

> Should we just arrange to #include <asm-generic/io.h> to pick up inb/outb
> et al?  Any reason to think a non-zero offset should be part of the
> solution?  (I don't really understand how inb/outb are used by modern drivers.)

A zero offset is almost always a bug, it would mean that you have ioremapped the
PIO space into the NULL pointer of your virtual address space, which would be 
an extremely silly thing to do.

Some background: Each PCI domain comes with three address spaces: memory, config
and I/O. The memory space is usually identity mapped with your physical addresses
and you use ioremap to create page table entries for that so you can dereference
pointers to do an I/O. Your iorpc_ioremap() function suggests that this is not
the case for Tile, which is fine: you use __gxio_mmio_read32() and friends to
access the __iomem cookie, which is an arbitrary offsettable value returned from
iorpc_ioremap().
The configuration space is often memory mapped and ioremapped into the virtual
address space at boot time. Other implementations use two registers: one to set
the address and the other to access the data, or use an mmconfig hypercall.
Again, tile seems to be doing something completely different here and uses its
own __gxio_mmio_read32() function.
The i/o space is normally 64KB per domain that either have special instructions
(x86) or are accessed like the configuration space, typically memory mapped
(everyone else). In Linux, we access the I/O space using inb/outb that get the
16 bit register number as an argument, and in memory mapped implementations,
this gets added to the virtual address into which the I/O space was mapped at
boot time.

	Arnd


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-04-10  0:01   ` [PATCH 3/3] " Bjorn Helgaas
@ 2012-04-10  9:15     ` Arnd Bergmann
  2012-04-15 23:09     ` Chris Metcalf
  1 sibling, 0 replies; 19+ messages in thread
From: Arnd Bergmann @ 2012-04-10  9:15 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Chris Metcalf, linux-kernel, linux-pci, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Jiri Kosina, Joe Perches,
	David Howells

On Tuesday 10 April 2012, Bjorn Helgaas wrote:
> > +       if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
> > +               /*
> > +                * For bridges, we enable both memory and I/O decoding
> > +                * in call cases.
> > +                */
> > +               cmd |= PCI_COMMAND_IO;
> > +               cmd |= PCI_COMMAND_MEMORY;
> > +       } else {
> > +               /*
> > +                * For endpoints, we enable memory and/or I/O decoding
> > +                * only if they have a memory resource of that type.
> > +                */
> > +               for (i = 0; i < 6; i++) {
> > +                       r = &dev->resource[i];
> > +                       if (r->flags & IORESOURCE_UNSET) {
> > +                               pr_err("PCI: Device %s not available "
> > +                                      "because of resource collisions\n",
> > +                                      pci_name(dev));
> > +                               return -EINVAL;
> > +                       }
> > +                       if (r->flags & IORESOURCE_IO)
> > +                               cmd |= PCI_COMMAND_IO;
> > +                       if (r->flags & IORESOURCE_MEM)
> > +                               cmd |= PCI_COMMAND_MEMORY;
> > +               }
> 
> It would be nice if you could use pci_enable_resources() here, though
> you use IORESOURCE_UNSET here, while pci_enable_resources() does not.
> But you could at least use PCI_NUM_RESOURCES and "mask."  There's
> nothing fundamentally architecture-dependent here, so I'd like to move
> toward a generic implementation.

Note that if tile does not support I/O space as indicated, it should
never enable PCI_COMMAND_IO.

	Arnd


^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-04-10  0:01   ` [PATCH 3/3] " Bjorn Helgaas
  2012-04-10  9:15     ` Arnd Bergmann
@ 2012-04-15 23:09     ` Chris Metcalf
  1 sibling, 0 replies; 19+ messages in thread
From: Chris Metcalf @ 2012-04-15 23:09 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-kernel, linux-pci, Jesse Barnes, Michael S. Tsirkin,
	Myron Stowe, Arnd Bergmann, Jiri Kosina, Joe Perches,
	David Howells

Bjorn Helgaas wrote:
> Can this be done with the generic pcie_bus_configure_settings() or is
> there something tilegx-specific about this?
> If at all possible, you should use pci_scan_root_bus() here instead,
> so you can tell PCI what the host bridge apertures are.

I've been exchanging email with the author of this driver during the week (he's based out of the California office, and I'm in Massachusetts) and the two suggestions quoted above still need further investigation before we can get back to you.  I'm out next week for spring school break so it won't be until the following week that I'll put out a v2 of this patch.  The other comments (not quoted) we've already incorporated into the driver.

So thanks a lot for your feedback!

Chris Metcalf
Tilera Corp.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 0/2] arch/tile: PCI root complex support
  2012-04-10  9:14       ` Arnd Bergmann
@ 2012-05-08 20:53         ` Chris Metcalf
  2012-05-08 20:53           ` [PATCH v2 1/2] arch/tile: provide kernel support for the tilegx TRIO shim Chris Metcalf
  2012-05-08 21:10           ` [PATCH v2 2/2] arch/tile: tilegx PCI root complex support Chris Metcalf
  0 siblings, 2 replies; 19+ messages in thread
From: Chris Metcalf @ 2012-05-08 20:53 UTC (permalink / raw)
  To: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Arnd Bergmann, Jiri Kosina,
	Joe Perches,
	David Howells <dhowells@redhat.com> Jesper Juhl

This is the second version of the patch series to add PCI root complex
support to the tilegx architecture.  Again, I am cc'ing the change
that adds PCI support per-se to a wider audience.

This series incorporates feedback from Jesper Juhl, Arnd Bergmann, and
Bjorn Helgaas.

- Use pcie_bus_configure_settings(), pci_scan_root_bus(), and
  pci_enable_resources().
- Use PCI_SLOT() and PCI_FUNC() as appropriate.
- Stop enabling PCI_COMMAND_IO, since we don't support I/O space yet.
- Use msleep() instead of mdelay()
- Machine-generated code (e.g. iorpc_trio.c) is now terser and more
  human-readable.
- Some whitespace issues (e.g. " * " before a particular pointer, and
  function return type on a line by itself too frequently) corrected.

We don't currently plan to add support for I/O space.  We didn't implement
the kernel support in the RC driver, because only old, legacy devices use
PCI I/O space and it seems unlikely that our chip will end up having to
control one of these devices. Plus, supporting it costs one of 8 total
TRIO PIO regions, which are in short supply.  But this is secondary;
we'll add support if needed in the future.

 arch/tile/Kconfig                            |    3 +
 arch/tile/gxio/Kconfig                       |    6 +
 arch/tile/gxio/Makefile                      |    1 +
 arch/tile/gxio/iorpc_trio.c                  |  307 +++++
 arch/tile/gxio/trio.c                        |   49 +
 arch/tile/include/arch/trio.h                |   72 ++
 arch/tile/include/arch/trio_constants.h      |   36 +
 arch/tile/include/arch/trio_def.h            |   41 +
 arch/tile/include/arch/trio_pcie_intfc.h     |  229 ++++
 arch/tile/include/arch/trio_pcie_intfc_def.h |   32 +
 arch/tile/include/arch/trio_pcie_rc.h        |  156 +++
 arch/tile/include/arch/trio_pcie_rc_def.h    |   24 +
 arch/tile/include/arch/trio_shm.h            |  125 ++
 arch/tile/include/arch/trio_shm_def.h        |   19 +
 arch/tile/include/asm/pci.h                  |   99 ++-
 arch/tile/include/gxio/iorpc_trio.h          |   97 ++
 arch/tile/include/gxio/trio.h                |  304 +++++
 arch/tile/include/hv/drv_trio_intf.h         |  195 ++++
 arch/tile/kernel/Makefile                    |    4 +
 arch/tile/kernel/pci_gx.c                    | 1545 ++++++++++++++++++++++++++
 arch/tile/kernel/setup.c                     |    6 +
 arch/tile/mm/pgtable.c                       |    7 -
 drivers/pci/quirks.c                         |    6 +-
 23 files changed, 3363 insertions(+), 20 deletions(-)

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 1/2] arch/tile: provide kernel support for the tilegx TRIO shim
  2012-05-08 20:53         ` [PATCH v2 0/2] arch/tile: " Chris Metcalf
@ 2012-05-08 20:53           ` Chris Metcalf
  2012-05-08 21:10           ` [PATCH v2 2/2] arch/tile: tilegx PCI root complex support Chris Metcalf
  1 sibling, 0 replies; 19+ messages in thread
From: Chris Metcalf @ 2012-05-08 20:53 UTC (permalink / raw)
  To: linux-kernel, Jesper Juhl

Provide kernel support for the tilegx "Transaction I/O" (TRIO) on-chip
hardware.  This hardware implements the PCIe interface for tilegx;
the driver changes to use TRIO for PCIe are in a subsequent commit.

The change is layered on top of the tilegx GXIO IORPC subsystem.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
---
 arch/tile/gxio/Kconfig                       |    6 +
 arch/tile/gxio/Makefile                      |    1 +
 arch/tile/gxio/iorpc_trio.c                  |  307 ++++++++++++++++++++++++++
 arch/tile/gxio/trio.c                        |   49 ++++
 arch/tile/include/arch/trio.h                |   72 ++++++
 arch/tile/include/arch/trio_constants.h      |   36 +++
 arch/tile/include/arch/trio_def.h            |   41 ++++
 arch/tile/include/arch/trio_pcie_intfc.h     |  229 +++++++++++++++++++
 arch/tile/include/arch/trio_pcie_intfc_def.h |   32 +++
 arch/tile/include/arch/trio_pcie_rc.h        |  156 +++++++++++++
 arch/tile/include/arch/trio_pcie_rc_def.h    |   24 ++
 arch/tile/include/arch/trio_shm.h            |  125 +++++++++++
 arch/tile/include/arch/trio_shm_def.h        |   19 ++
 arch/tile/include/gxio/iorpc_trio.h          |   97 ++++++++
 arch/tile/include/gxio/trio.h                |  304 +++++++++++++++++++++++++
 arch/tile/include/hv/drv_trio_intf.h         |  195 ++++++++++++++++
 16 files changed, 1693 insertions(+), 0 deletions(-)
 create mode 100644 arch/tile/gxio/iorpc_trio.c
 create mode 100644 arch/tile/gxio/trio.c
 create mode 100644 arch/tile/include/arch/trio.h
 create mode 100644 arch/tile/include/arch/trio_constants.h
 create mode 100644 arch/tile/include/arch/trio_def.h
 create mode 100644 arch/tile/include/arch/trio_pcie_intfc.h
 create mode 100644 arch/tile/include/arch/trio_pcie_intfc_def.h
 create mode 100644 arch/tile/include/arch/trio_pcie_rc.h
 create mode 100644 arch/tile/include/arch/trio_pcie_rc_def.h
 create mode 100644 arch/tile/include/arch/trio_shm.h
 create mode 100644 arch/tile/include/arch/trio_shm_def.h
 create mode 100644 arch/tile/include/gxio/iorpc_trio.h
 create mode 100644 arch/tile/include/gxio/trio.h
 create mode 100644 arch/tile/include/hv/drv_trio_intf.h

diff --git a/arch/tile/gxio/Kconfig b/arch/tile/gxio/Kconfig
index 8aeebb7..68e1cca 100644
--- a/arch/tile/gxio/Kconfig
+++ b/arch/tile/gxio/Kconfig
@@ -15,3 +15,9 @@ config TILE_GXIO_MPIPE
 	bool
 	select TILE_GXIO
 	select TILE_GXIO_DMA
+
+# Support direct access to the TILE-Gx TRIO hardware from kernel space.
+config TILE_GXIO_TRIO
+	bool
+	select TILE_GXIO
+	select TILE_GXIO_DMA
diff --git a/arch/tile/gxio/Makefile b/arch/tile/gxio/Makefile
index 130eec4..2389ef3 100644
--- a/arch/tile/gxio/Makefile
+++ b/arch/tile/gxio/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_TILE_GXIO) += iorpc_globals.o kiorpc.o
 obj-$(CONFIG_TILE_GXIO_DMA) += dma_queue.o
 obj-$(CONFIG_TILE_GXIO_MPIPE) += mpipe.o iorpc_mpipe.o iorpc_mpipe_info.o
+obj-$(CONFIG_TILE_GXIO_TRIO) += trio.o iorpc_trio.o
diff --git a/arch/tile/gxio/iorpc_trio.c b/arch/tile/gxio/iorpc_trio.c
new file mode 100644
index 0000000..209cb0d
--- /dev/null
+++ b/arch/tile/gxio/iorpc_trio.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#include "gxio/iorpc_trio.h"
+
+struct alloc_asids_param {
+	unsigned int count;
+	unsigned int first;
+	unsigned int flags;
+};
+
+int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+			  unsigned int first, unsigned int flags)
+{
+	struct alloc_asids_param temp;
+	struct alloc_asids_param *params = &temp;
+
+	params->count = count;
+	params->first = first;
+	params->flags = flags;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_ALLOC_ASIDS);
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_asids);
+
+
+struct alloc_memory_maps_param {
+	unsigned int count;
+	unsigned int first;
+	unsigned int flags;
+};
+
+int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
+				unsigned int count, unsigned int first,
+				unsigned int flags)
+{
+	struct alloc_memory_maps_param temp;
+	struct alloc_memory_maps_param *params = &temp;
+
+	params->count = count;
+	params->first = first;
+	params->flags = flags;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_ALLOC_MEMORY_MAPS);
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_memory_maps);
+
+
+struct alloc_pio_regions_param {
+	unsigned int count;
+	unsigned int first;
+	unsigned int flags;
+};
+
+int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
+				unsigned int count, unsigned int first,
+				unsigned int flags)
+{
+	struct alloc_pio_regions_param temp;
+	struct alloc_pio_regions_param *params = &temp;
+
+	params->count = count;
+	params->first = first;
+	params->flags = flags;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_ALLOC_PIO_REGIONS);
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_pio_regions);
+
+struct init_pio_region_aux_param {
+	unsigned int pio_region;
+	unsigned int mac;
+	uint32_t bus_address_hi;
+	unsigned int flags;
+};
+
+int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
+				  unsigned int pio_region, unsigned int mac,
+				  uint32_t bus_address_hi, unsigned int flags)
+{
+	struct init_pio_region_aux_param temp;
+	struct init_pio_region_aux_param *params = &temp;
+
+	params->pio_region = pio_region;
+	params->mac = mac;
+	params->bus_address_hi = bus_address_hi;
+	params->flags = flags;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_INIT_PIO_REGION_AUX);
+}
+
+EXPORT_SYMBOL(gxio_trio_init_pio_region_aux);
+
+
+struct init_memory_map_mmu_aux_param {
+	unsigned int map;
+	unsigned long va;
+	uint64_t size;
+	unsigned int asid;
+	unsigned int mac;
+	uint64_t bus_address;
+	unsigned int node;
+	unsigned int order_mode;
+};
+
+int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
+				      unsigned int map, unsigned long va,
+				      uint64_t size, unsigned int asid,
+				      unsigned int mac, uint64_t bus_address,
+				      unsigned int node,
+				      unsigned int order_mode)
+{
+	struct init_memory_map_mmu_aux_param temp;
+	struct init_memory_map_mmu_aux_param *params = &temp;
+
+	params->map = map;
+	params->va = va;
+	params->size = size;
+	params->asid = asid;
+	params->mac = mac;
+	params->bus_address = bus_address;
+	params->node = node;
+	params->order_mode = order_mode;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params),
+			     GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX);
+}
+
+EXPORT_SYMBOL(gxio_trio_init_memory_map_mmu_aux);
+
+
+struct config_legacy_intr_param {
+	union iorpc_interrupt interrupt;
+	unsigned int mac;
+	unsigned int intx;
+};
+
+int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
+				 int inter_y, int inter_ipi, int inter_event,
+				 unsigned int mac, unsigned int intx)
+{
+	struct config_legacy_intr_param temp;
+	struct config_legacy_intr_param *params = &temp;
+
+	params->interrupt.kernel.x = inter_x;
+	params->interrupt.kernel.y = inter_y;
+	params->interrupt.kernel.ipi = inter_ipi;
+	params->interrupt.kernel.event = inter_event;
+	params->mac = mac;
+	params->intx = intx;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_CONFIG_LEGACY_INTR);
+}
+
+EXPORT_SYMBOL(gxio_trio_config_legacy_intr);
+
+struct config_msi_intr_param {
+	union iorpc_interrupt interrupt;
+	unsigned int mac;
+	unsigned int mem_map;
+	uint64_t mem_map_base;
+	uint64_t mem_map_limit;
+	unsigned int asid;
+};
+
+int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
+			      int inter_y, int inter_ipi, int inter_event,
+			      unsigned int mac, unsigned int mem_map,
+			      uint64_t mem_map_base, uint64_t mem_map_limit,
+			      unsigned int asid)
+{
+	struct config_msi_intr_param temp;
+	struct config_msi_intr_param *params = &temp;
+
+	params->interrupt.kernel.x = inter_x;
+	params->interrupt.kernel.y = inter_y;
+	params->interrupt.kernel.ipi = inter_ipi;
+	params->interrupt.kernel.event = inter_event;
+	params->mac = mac;
+	params->mem_map = mem_map;
+	params->mem_map_base = mem_map_base;
+	params->mem_map_limit = mem_map_limit;
+	params->asid = asid;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_CONFIG_MSI_INTR);
+}
+
+EXPORT_SYMBOL(gxio_trio_config_msi_intr);
+
+
+struct set_mps_mrs_param {
+	uint16_t mps;
+	uint16_t mrs;
+	unsigned int mac;
+};
+
+int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
+			  uint16_t mrs, unsigned int mac)
+{
+	struct set_mps_mrs_param temp;
+	struct set_mps_mrs_param *params = &temp;
+
+	params->mps = mps;
+	params->mrs = mrs;
+	params->mac = mac;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_SET_MPS_MRS);
+}
+
+EXPORT_SYMBOL(gxio_trio_set_mps_mrs);
+
+struct force_rc_link_up_param {
+	unsigned int mac;
+};
+
+int gxio_trio_force_rc_link_up(gxio_trio_context_t * context, unsigned int mac)
+{
+	struct force_rc_link_up_param temp;
+	struct force_rc_link_up_param *params = &temp;
+
+	params->mac = mac;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_FORCE_RC_LINK_UP);
+}
+
+EXPORT_SYMBOL(gxio_trio_force_rc_link_up);
+
+struct force_ep_link_up_param {
+	unsigned int mac;
+};
+
+int gxio_trio_force_ep_link_up(gxio_trio_context_t * context, unsigned int mac)
+{
+	struct force_ep_link_up_param temp;
+	struct force_ep_link_up_param *params = &temp;
+
+	params->mac = mac;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_FORCE_EP_LINK_UP);
+}
+
+EXPORT_SYMBOL(gxio_trio_force_ep_link_up);
+
+struct get_mmio_base_param {
+	HV_PTE base;
+};
+
+int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base)
+{
+	int __result;
+	struct get_mmio_base_param temp;
+	struct get_mmio_base_param *params = &temp;
+
+	__result =
+	    hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
+			 GXIO_TRIO_OP_GET_MMIO_BASE);
+	*base = params->base;
+
+	return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_get_mmio_base);
+
+struct check_mmio_offset_param {
+	unsigned long offset;
+	unsigned long size;
+};
+
+int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
+				unsigned long offset, unsigned long size)
+{
+	struct check_mmio_offset_param temp;
+	struct check_mmio_offset_param *params = &temp;
+
+	params->offset = offset;
+	params->size = size;
+
+	return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+			     sizeof(*params), GXIO_TRIO_OP_CHECK_MMIO_OFFSET);
+}
+
+EXPORT_SYMBOL(gxio_trio_check_mmio_offset);
diff --git a/arch/tile/gxio/trio.c b/arch/tile/gxio/trio.c
new file mode 100644
index 0000000..69f0b8d
--- /dev/null
+++ b/arch/tile/gxio/trio.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ * Implementation of trio gxio calls.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <gxio/trio.h>
+#include <gxio/iorpc_globals.h>
+#include <gxio/iorpc_trio.h>
+#include <gxio/kiorpc.h>
+
+int gxio_trio_init(gxio_trio_context_t *context, unsigned int trio_index)
+{
+	char file[32];
+	int fd;
+
+	snprintf(file, sizeof(file), "trio/%d/iorpc", trio_index);
+	fd = hv_dev_open((HV_VirtAddr) file, 0);
+	if (fd < 0) {
+		context->fd = -1;
+
+		if (fd >= GXIO_ERR_MIN && fd <= GXIO_ERR_MAX)
+			return fd;
+		else
+			return -ENODEV;
+	}
+
+	context->fd = fd;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_trio_init);
diff --git a/arch/tile/include/arch/trio.h b/arch/tile/include/arch/trio.h
new file mode 100644
index 0000000..d3000a8
--- /dev/null
+++ b/arch/tile/include/arch/trio.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_H__
+#define __ARCH_TRIO_H__
+
+#include <arch/abi.h>
+#include <arch/trio_def.h>
+
+#ifndef __ASSEMBLER__
+
+/*
+ * Tile PIO Region Configuration - CFG Address Format.
+ * This register describes the address format for PIO accesses when the
+ * associated region is setup with TYPE=CFG.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Register Address (full byte address). */
+    uint_reg_t reg_addr     : 12;
+    /* Function Number */
+    uint_reg_t fn           : 3;
+    /* Device Number */
+    uint_reg_t dev          : 5;
+    /* BUS Number */
+    uint_reg_t bus          : 8;
+    /* Config Type: 0 for access to directly-attached device.  1 otherwise. */
+    uint_reg_t type         : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_0 : 1;
+    /*
+     * MAC select.  This must match the configuration in
+     * TILE_PIO_REGION_SETUP.MAC.
+     */
+    uint_reg_t mac          : 2;
+    /* Reserved. */
+    uint_reg_t __reserved_1 : 32;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_1 : 32;
+    uint_reg_t mac          : 2;
+    uint_reg_t __reserved_0 : 1;
+    uint_reg_t type         : 1;
+    uint_reg_t bus          : 8;
+    uint_reg_t dev          : 5;
+    uint_reg_t fn           : 3;
+    uint_reg_t reg_addr     : 12;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_H__) */
diff --git a/arch/tile/include/arch/trio_constants.h b/arch/tile/include/arch/trio_constants.h
new file mode 100644
index 0000000..628b045
--- /dev/null
+++ b/arch/tile/include/arch/trio_constants.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+
+#ifndef __ARCH_TRIO_CONSTANTS_H__
+#define __ARCH_TRIO_CONSTANTS_H__
+
+#define TRIO_NUM_ASIDS 16
+#define TRIO_NUM_TLBS_PER_ASID 16
+
+#define TRIO_NUM_TPIO_REGIONS 8
+#define TRIO_LOG2_NUM_TPIO_REGIONS 3
+
+#define TRIO_NUM_MAP_MEM_REGIONS 16
+#define TRIO_LOG2_NUM_MAP_MEM_REGIONS 4
+#define TRIO_NUM_MAP_SQ_REGIONS 8
+#define TRIO_LOG2_NUM_MAP_SQ_REGIONS 3
+
+#define TRIO_LOG2_NUM_SQ_FIFO_ENTRIES 6
+
+#define TRIO_NUM_PUSH_DMA_RINGS 32
+
+#define TRIO_NUM_PULL_DMA_RINGS 32
+
+#endif /* __ARCH_TRIO_CONSTANTS_H__ */
diff --git a/arch/tile/include/arch/trio_def.h b/arch/tile/include/arch/trio_def.h
new file mode 100644
index 0000000..e805003
--- /dev/null
+++ b/arch/tile/include/arch/trio_def.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_DEF_H__
+#define __ARCH_TRIO_DEF_H__
+#define TRIO_CFG_REGION_ADDR__REG_SHIFT 0
+#define TRIO_CFG_REGION_ADDR__INTFC_SHIFT 16
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_TRIO 0x0
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE 0x1
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD 0x2
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED 0x3
+#define TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT 18
+#define TRIO_CFG_REGION_ADDR__PROT_SHIFT 20
+#define TRIO_PIO_REGIONS_ADDR__REGION_SHIFT 32
+#define TRIO_MAP_MEM_REG_INT0 0x1000000000
+#define TRIO_MAP_MEM_REG_INT1 0x1000000008
+#define TRIO_MAP_MEM_REG_INT2 0x1000000010
+#define TRIO_MAP_MEM_REG_INT3 0x1000000018
+#define TRIO_MAP_MEM_REG_INT4 0x1000000020
+#define TRIO_MAP_MEM_REG_INT5 0x1000000028
+#define TRIO_MAP_MEM_REG_INT6 0x1000000030
+#define TRIO_MAP_MEM_REG_INT7 0x1000000038
+#define TRIO_MAP_MEM_LIM__ADDR_SHIFT 12
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_UNORDERED 0x0
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_STRICT 0x1
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_REL_ORD 0x2
+#define TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT 30
+#endif /* !defined(__ARCH_TRIO_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_intfc.h b/arch/tile/include/arch/trio_pcie_intfc.h
new file mode 100644
index 0000000..0487fdb
--- /dev/null
+++ b/arch/tile/include/arch/trio_pcie_intfc.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_INTFC_H__
+#define __ARCH_TRIO_PCIE_INTFC_H__
+
+#include <arch/abi.h>
+#include <arch/trio_pcie_intfc_def.h>
+
+#ifndef __ASSEMBLER__
+
+/*
+ * Port Configuration.
+ * Configuration of the PCIe Port
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Provides the state of the strapping pins for this port. */
+    uint_reg_t strap_state      : 3;
+    /* Reserved. */
+    uint_reg_t __reserved_0     : 1;
+    /*
+     * When 1, the device type will be overridden using OVD_DEV_TYPE_VAL.
+     * When 0, the device type is determined based on the STRAP_STATE.
+     */
+    uint_reg_t ovd_dev_type     : 1;
+    /* Provides the device type when OVD_DEV_TYPE is 1. */
+    uint_reg_t ovd_dev_type_val : 4;
+    /* Determines how link is trained. */
+    uint_reg_t train_mode       : 2;
+    /* Reserved. */
+    uint_reg_t __reserved_1     : 1;
+    /*
+     * For PCIe, used to flip physical RX lanes that were not properly wired.
+     *  This is not the same as lane reversal which is handled automatically
+     * during link training.  When 0, RX Lane0 must be wired to the link
+     * partner (either to its Lane0 or it's LaneN).  When RX_LANE_FLIP is 1,
+     * the highest numbered lane for this port becomes Lane0 and Lane0 does
+     * NOT have to be wired to the link partner.
+     */
+    uint_reg_t rx_lane_flip     : 1;
+    /*
+     * For PCIe, used to flip physical TX lanes that were not properly wired.
+     *  This is not the same as lane reversal which is handled automatically
+     * during link training.  When 0, TX Lane0 must be wired to the link
+     * partner (either to its Lane0 or it's LaneN).  When TX_LANE_FLIP is 1,
+     * the highest numbered lane for this port becomes Lane0 and Lane0 does
+     * NOT have to be wired to the link partner.
+     */
+    uint_reg_t tx_lane_flip     : 1;
+    /*
+     * For StreamIO port, configures the width of the port when TRAIN_MODE is
+     * not STRAP.
+     */
+    uint_reg_t stream_width     : 2;
+    /*
+     * For StreamIO port, configures the rate of the port when TRAIN_MODE is
+     * not STRAP.
+     */
+    uint_reg_t stream_rate      : 2;
+    /* Reserved. */
+    uint_reg_t __reserved_2     : 46;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_2     : 46;
+    uint_reg_t stream_rate      : 2;
+    uint_reg_t stream_width     : 2;
+    uint_reg_t tx_lane_flip     : 1;
+    uint_reg_t rx_lane_flip     : 1;
+    uint_reg_t __reserved_1     : 1;
+    uint_reg_t train_mode       : 2;
+    uint_reg_t ovd_dev_type_val : 4;
+    uint_reg_t ovd_dev_type     : 1;
+    uint_reg_t __reserved_0     : 1;
+    uint_reg_t strap_state      : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_PORT_CONFIG_t;
+
+/*
+ * Port Status.
+ * Status of the PCIe Port.  This register applies to the StreamIO port when
+ * StreamIO is enabled.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * Indicates the DL state of the port.  When 1, the port is up and ready
+     * to receive traffic.
+     */
+    uint_reg_t dl_up        : 1;
+    /*
+     * Indicates the number of times the link has gone down.  Clears on read.
+     */
+    uint_reg_t dl_down_cnt  : 7;
+    /* Indicates the SERDES PLL has spun up and is providing a valid clock. */
+    uint_reg_t clock_ready  : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_0 : 7;
+    /* Device revision ID. */
+    uint_reg_t device_rev   : 8;
+    /* Link state (PCIe). */
+    uint_reg_t ltssm_state  : 6;
+    /* Link power management state (PCIe). */
+    uint_reg_t pm_state     : 3;
+    /* Reserved. */
+    uint_reg_t __reserved_1 : 31;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_1 : 31;
+    uint_reg_t pm_state     : 3;
+    uint_reg_t ltssm_state  : 6;
+    uint_reg_t device_rev   : 8;
+    uint_reg_t __reserved_0 : 7;
+    uint_reg_t clock_ready  : 1;
+    uint_reg_t dl_down_cnt  : 7;
+    uint_reg_t dl_up        : 1;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_PORT_STATUS_t;
+
+/*
+ * Transmit FIFO Control.
+ * Contains TX FIFO thresholds.  These registers are for diagnostics purposes
+ * only.  Changing these values causes undefined behavior.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * Almost-Empty level for TX0 data.  Typically set to at least
+     * roundup(38.0*M/N) where N=tclk frequency and M=MAC symbol rate in MHz
+     * for a x4 port (250MHz).
+     */
+    uint_reg_t tx0_data_ae_lvl : 7;
+    /* Reserved. */
+    uint_reg_t __reserved_0    : 1;
+    /* Almost-Empty level for TX1 data. */
+    uint_reg_t tx1_data_ae_lvl : 7;
+    /* Reserved. */
+    uint_reg_t __reserved_1    : 1;
+    /* Almost-Full level for TX0 data. */
+    uint_reg_t tx0_data_af_lvl : 7;
+    /* Reserved. */
+    uint_reg_t __reserved_2    : 1;
+    /* Almost-Full level for TX1 data. */
+    uint_reg_t tx1_data_af_lvl : 7;
+    /* Reserved. */
+    uint_reg_t __reserved_3    : 1;
+    /* Almost-Full level for TX0 info. */
+    uint_reg_t tx0_info_af_lvl : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_4    : 3;
+    /* Almost-Full level for TX1 info. */
+    uint_reg_t tx1_info_af_lvl : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_5    : 3;
+    /*
+     * This register provides performance adjustment for high bandwidth
+     * flows.  The MAC will assert almost-full to TRIO if non-posted credits
+     * fall below this level.  Note that setting this larger than the initial
+     * PORT_CREDIT.NPH value will cause READS to never be sent.  If the
+     * initial credit value from the link partner is smaller than this value
+     * when the link comes up, the value will be reset to the initial credit
+     * value to prevent lockup.
+     */
+    uint_reg_t min_np_credits  : 8;
+    /*
+     * This register provides performance adjustment for high bandwidth
+     * flows.  The MAC will assert almost-full to TRIO if posted credits fall
+     * below this level.  Note that setting this larger than the initial
+     * PORT_CREDIT.PH value will cause WRITES to never be sent.  If the
+     * initial credit value from the link partner is smaller than this value
+     * when the link comes up, the value will be reset to the initial credit
+     * value to prevent lockup.
+     */
+    uint_reg_t min_p_credits   : 8;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t min_p_credits   : 8;
+    uint_reg_t min_np_credits  : 8;
+    uint_reg_t __reserved_5    : 3;
+    uint_reg_t tx1_info_af_lvl : 5;
+    uint_reg_t __reserved_4    : 3;
+    uint_reg_t tx0_info_af_lvl : 5;
+    uint_reg_t __reserved_3    : 1;
+    uint_reg_t tx1_data_af_lvl : 7;
+    uint_reg_t __reserved_2    : 1;
+    uint_reg_t tx0_data_af_lvl : 7;
+    uint_reg_t __reserved_1    : 1;
+    uint_reg_t tx1_data_ae_lvl : 7;
+    uint_reg_t __reserved_0    : 1;
+    uint_reg_t tx0_data_ae_lvl : 7;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_TX_FIFO_CTL_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_PCIE_INTFC_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_intfc_def.h b/arch/tile/include/arch/trio_pcie_intfc_def.h
new file mode 100644
index 0000000..d3fd678
--- /dev/null
+++ b/arch/tile/include/arch/trio_pcie_intfc_def.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_INTFC_DEF_H__
+#define __ARCH_TRIO_PCIE_INTFC_DEF_H__
+#define TRIO_PCIE_INTFC_MAC_INT_STS 0x0000
+#define TRIO_PCIE_INTFC_MAC_INT_STS__INT_LEVEL_MASK  0xf000
+#define TRIO_PCIE_INTFC_PORT_CONFIG 0x0018
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_DISABLED 0x0
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT 0x1
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC 0x2
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1 0x3
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1 0x4
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_XLINK 0x5
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_STREAM_X1 0x6
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_STREAM_X4 0x7
+#define TRIO_PCIE_INTFC_PORT_STATUS 0x0020
+#define TRIO_PCIE_INTFC_TX_FIFO_CTL 0x0050
+#endif /* !defined(__ARCH_TRIO_PCIE_INTFC_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_rc.h b/arch/tile/include/arch/trio_pcie_rc.h
new file mode 100644
index 0000000..6a25d0a
--- /dev/null
+++ b/arch/tile/include/arch/trio_pcie_rc.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_RC_H__
+#define __ARCH_TRIO_PCIE_RC_H__
+
+#include <arch/abi.h>
+#include <arch/trio_pcie_rc_def.h>
+
+#ifndef __ASSEMBLER__
+
+/* Device Capabilities Register. */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * Max_Payload_Size Supported, writablethrough the MAC_STANDARD interface
+     */
+    uint_reg_t mps_sup                    : 3;
+    /*
+     * This field is writable through the MAC_STANDARD interface.  However,
+     * Phantom Function is not  supported. Therefore, the application must
+     * not write any value other than 0x0 to this  field.
+     */
+    uint_reg_t phantom_function_supported : 2;
+    /* This bit is writable through the MAC_STANDARD interface. */
+    uint_reg_t ext_tag_field_supported    : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_0               : 3;
+    /* Endpoint L1 Acceptable Latency Must be 0x0 for non-Endpoint devices. */
+    uint_reg_t l1_lat                     : 3;
+    /*
+     * Undefined since PCI Express 1.1 (Was Attention Button Present for PCI
+     * Express 1.0a)
+     */
+    uint_reg_t r1                         : 1;
+    /*
+     * Undefined since PCI Express 1.1 (Was Attention Indicator Present for
+     * PCI  Express 1.0a)
+     */
+    uint_reg_t r2                         : 1;
+    /*
+     * Undefined since PCI Express 1.1 (Was Power Indicator Present for PCI
+     * Express 1.0a)
+     */
+    uint_reg_t r3                         : 1;
+    /*
+     * Role-Based Error Reporting, writable through the MAC_STANDARD
+     * interface.  Required to be set for device compliant to 1.1  spec and
+     * later.
+     */
+    uint_reg_t rer                        : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_1               : 2;
+    /* Captured Slot Power Limit Value Upstream port only. */
+    uint_reg_t slot_pwr_lim               : 8;
+    /* Captured Slot Power Limit Scale Upstream port only. */
+    uint_reg_t slot_pwr_scale             : 2;
+    /* Reserved. */
+    uint_reg_t __reserved_2               : 4;
+    /* Endpoint L0s Acceptable LatencyMust be 0x0 for non-Endpoint devices. */
+    uint_reg_t l0s_lat                    : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_3               : 31;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_3               : 31;
+    uint_reg_t l0s_lat                    : 1;
+    uint_reg_t __reserved_2               : 4;
+    uint_reg_t slot_pwr_scale             : 2;
+    uint_reg_t slot_pwr_lim               : 8;
+    uint_reg_t __reserved_1               : 2;
+    uint_reg_t rer                        : 1;
+    uint_reg_t r3                         : 1;
+    uint_reg_t r2                         : 1;
+    uint_reg_t r1                         : 1;
+    uint_reg_t l1_lat                     : 3;
+    uint_reg_t __reserved_0               : 3;
+    uint_reg_t ext_tag_field_supported    : 1;
+    uint_reg_t phantom_function_supported : 2;
+    uint_reg_t mps_sup                    : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_RC_DEVICE_CAP_t;
+
+/* Device Control Register. */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Correctable Error Reporting Enable */
+    uint_reg_t cor_err_ena      : 1;
+    /* Non-Fatal Error Reporting Enable */
+    uint_reg_t nf_err_ena       : 1;
+    /* Fatal Error Reporting Enable */
+    uint_reg_t fatal_err_ena    : 1;
+    /* Unsupported Request Reporting Enable */
+    uint_reg_t ur_ena           : 1;
+    /* Relaxed orderring enable */
+    uint_reg_t ro_ena           : 1;
+    /* Max Payload Size */
+    uint_reg_t max_payload_size : 3;
+    /* Extended Tag Field Enable */
+    uint_reg_t ext_tag          : 1;
+    /* Phantom Function Enable */
+    uint_reg_t ph_fn_ena        : 1;
+    /* AUX Power PM Enable */
+    uint_reg_t aux_pm_ena       : 1;
+    /* Enable NoSnoop */
+    uint_reg_t no_snoop         : 1;
+    /* Max read request size */
+    uint_reg_t max_read_req_sz  : 3;
+    /* Reserved. */
+    uint_reg_t __reserved       : 49;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved       : 49;
+    uint_reg_t max_read_req_sz  : 3;
+    uint_reg_t no_snoop         : 1;
+    uint_reg_t aux_pm_ena       : 1;
+    uint_reg_t ph_fn_ena        : 1;
+    uint_reg_t ext_tag          : 1;
+    uint_reg_t max_payload_size : 3;
+    uint_reg_t ro_ena           : 1;
+    uint_reg_t ur_ena           : 1;
+    uint_reg_t fatal_err_ena    : 1;
+    uint_reg_t nf_err_ena       : 1;
+    uint_reg_t cor_err_ena      : 1;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_RC_DEVICE_CONTROL_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_PCIE_RC_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_rc_def.h b/arch/tile/include/arch/trio_pcie_rc_def.h
new file mode 100644
index 0000000..74081a6
--- /dev/null
+++ b/arch/tile/include/arch/trio_pcie_rc_def.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_RC_DEF_H__
+#define __ARCH_TRIO_PCIE_RC_DEF_H__
+#define TRIO_PCIE_RC_DEVICE_CAP 0x0074
+#define TRIO_PCIE_RC_DEVICE_CONTROL 0x0078
+#define TRIO_PCIE_RC_DEVICE_ID_VEN_ID 0x0000
+#define TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT 16
+#define TRIO_PCIE_RC_REVISION_ID 0x0008
+#endif /* !defined(__ARCH_TRIO_PCIE_RC_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_shm.h b/arch/tile/include/arch/trio_shm.h
new file mode 100644
index 0000000..3382e38
--- /dev/null
+++ b/arch/tile/include/arch/trio_shm.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+
+#ifndef __ARCH_TRIO_SHM_H__
+#define __ARCH_TRIO_SHM_H__
+
+#include <arch/abi.h>
+#include <arch/trio_shm_def.h>
+
+#ifndef __ASSEMBLER__
+/**
+ * TRIO DMA Descriptor.
+ * The TRIO DMA descriptor is written by software and consumed by hardware.
+ * It is used to specify the location of transaction data in the IO and Tile
+ * domains.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+    /* Word 0 */
+
+#ifndef __BIG_ENDIAN__
+    /** Tile side virtual address. */
+    int_reg_t va           : 42;
+    /**
+     * Encoded size of buffer used on push DMA when C=1:
+     * 0 = 128 bytes
+     * 1 = 256 bytes
+     * 2 = 512 bytes
+     * 3 = 1024 bytes
+     * 4 = 1664 bytes
+     * 5 = 4096 bytes
+     * 6 = 10368 bytes
+     * 7 = 16384 bytes
+     */
+    uint_reg_t bsz          : 3;
+    /**
+     * Chaining designation.  Always zero for pull DMA
+     * 0 : Unchained buffer pointer
+     * 1 : Chained buffer pointer.  Next buffer descriptor (e.g. VA) stored
+     * in 1st 8-bytes in buffer.  For chained buffers, first 8-bytes of each
+     * buffer contain the next buffer descriptor formatted exactly like a PDE
+     * buffer descriptor.  This allows a chained PDE buffer to be sent using
+     * push DMA.
+     */
+    uint_reg_t c            : 1;
+    /**
+     * Notification interrupt will be delivered when the transaction has
+     * completed (all data has been read from or written to the Tile-side
+     * buffer).
+     */
+    uint_reg_t notif        : 1;
+    /**
+     * When 0, the XSIZE field specifies the total byte count for the
+     * transaction.  When 1, the XSIZE field is encoded as 2^(N+14) for N in
+     * {0..6}:
+     * 0 = 16KB
+     * 1 = 32KB
+     * 2 = 64KB
+     * 3 = 128KB
+     * 4 = 256KB
+     * 5 = 512KB
+     * 6 = 1MB
+     * All other encodings of the XSIZE field are reserved when SMOD=1
+     */
+    uint_reg_t smod         : 1;
+    /**
+     * Total number of bytes to move for this transaction.   When SMOD=1,
+     * this field is encoded - see SMOD description.
+     */
+    uint_reg_t xsize        : 14;
+    /** Reserved. */
+    uint_reg_t __reserved_0 : 1;
+    /**
+     * Generation number.  Used to indicate a valid descriptor in ring.  When
+     * a new descriptor is written into the ring, software must toggle this
+     * bit.  The net effect is that the GEN bit being written into new
+     * descriptors toggles each time the ring tail pointer wraps.
+     */
+    uint_reg_t gen          : 1;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t gen          : 1;
+    uint_reg_t __reserved_0 : 1;
+    uint_reg_t xsize        : 14;
+    uint_reg_t smod         : 1;
+    uint_reg_t notif        : 1;
+    uint_reg_t c            : 1;
+    uint_reg_t bsz          : 3;
+    int_reg_t va           : 42;
+#endif
+
+    /* Word 1 */
+
+#ifndef __BIG_ENDIAN__
+    /** IO-side address */
+    uint_reg_t io_address : 64;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t io_address : 64;
+#endif
+
+  };
+
+  /** Word access */
+  uint_reg_t words[2];
+} TRIO_DMA_DESC_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_SHM_H__) */
diff --git a/arch/tile/include/arch/trio_shm_def.h b/arch/tile/include/arch/trio_shm_def.h
new file mode 100644
index 0000000..72a59c8
--- /dev/null
+++ b/arch/tile/include/arch/trio_shm_def.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_SHM_DEF_H__
+#define __ARCH_TRIO_SHM_DEF_H__
+#endif /* !defined(__ARCH_TRIO_SHM_DEF_H__) */
diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h
new file mode 100644
index 0000000..f13677d
--- /dev/null
+++ b/arch/tile/include/gxio/iorpc_trio.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#ifndef __GXIO_TRIO_LINUX_RPC_H__
+#define __GXIO_TRIO_LINUX_RPC_H__
+
+#include <hv/iorpc.h>
+
+#include <hv/drv_trio_intf.h>
+#include <gxio/trio.h>
+#include <gxio/kiorpc.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#define GXIO_TRIO_OP_ALLOC_ASIDS       IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+
+#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402)
+
+#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e)
+#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f)
+
+#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418)
+#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1419)
+#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a)
+#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141b)
+
+#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d)
+#define GXIO_TRIO_OP_FORCE_RC_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_FORCE_EP_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141f)
+#define GXIO_TRIO_OP_GET_MMIO_BASE     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
+#define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
+
+int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+			  unsigned int first, unsigned int flags);
+
+
+int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
+				unsigned int count, unsigned int first,
+				unsigned int flags);
+
+
+int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
+				unsigned int count, unsigned int first,
+				unsigned int flags);
+
+int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
+				  unsigned int pio_region, unsigned int mac,
+				  uint32_t bus_address_hi, unsigned int flags);
+
+
+int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
+				      unsigned int map, unsigned long va,
+				      uint64_t size, unsigned int asid,
+				      unsigned int mac, uint64_t bus_address,
+				      unsigned int node,
+				      unsigned int order_mode);
+
+int gxio_trio_get_port_property(gxio_trio_context_t * context,
+				struct pcie_trio_ports_property *trio_ports);
+
+int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
+				 int inter_y, int inter_ipi, int inter_event,
+				 unsigned int mac, unsigned int intx);
+
+int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
+			      int inter_y, int inter_ipi, int inter_event,
+			      unsigned int mac, unsigned int mem_map,
+			      uint64_t mem_map_base, uint64_t mem_map_limit,
+			      unsigned int asid);
+
+
+int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
+			  uint16_t mrs, unsigned int mac);
+
+int gxio_trio_force_rc_link_up(gxio_trio_context_t * context, unsigned int mac);
+
+int gxio_trio_force_ep_link_up(gxio_trio_context_t * context, unsigned int mac);
+
+int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base);
+
+int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
+				unsigned long offset, unsigned long size);
+
+#endif /* !__GXIO_TRIO_LINUX_RPC_H__ */
diff --git a/arch/tile/include/gxio/trio.h b/arch/tile/include/gxio/trio.h
new file mode 100644
index 0000000..4d79014
--- /dev/null
+++ b/arch/tile/include/gxio/trio.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ *
+ * An API for allocating, configuring, and manipulating TRIO hardware
+ * resources
+ */
+
+/*
+ *
+ * The TILE-Gx TRIO shim provides connections to external devices via
+ * PCIe or other transaction IO standards.  The gxio_trio_ API,
+ * declared in <gxio/trio.h>, allows applications to allocate and
+ * configure TRIO IO resources like DMA command rings, memory map
+ * windows, and device interrupts.  The following sections introduce
+ * the various components of the API.  We strongly recommend reading
+ * the TRIO section of the IO Device Guide (UG404) before working with
+ * this API.
+ *
+ * @section trio__ingress TRIO Ingress Hardware Resources
+ *
+ * The TRIO ingress hardware is responsible for examining incoming
+ * PCIe or StreamIO packets and choosing a processing mechanism based
+ * on the packets' bus address.  The gxio_trio_ API can be used to
+ * configure different handlers for different ranges of bus address
+ * space.  The user can configure "mapped memory" and "scatter queue"
+ * regions to match incoming packets within 4kB-aligned ranges of bus
+ * addresses.  Each range specifies a different set of mapping
+ * parameters to be applied when handling the ingress packet.  The
+ * following sections describe how to work with MapMem and scatter
+ * queue regions.
+ *
+ * @subsection trio__mapmem TRIO MapMem Regions
+ *
+ * TRIO mapped memory (or MapMem) regions allow the user to map
+ * incoming read and write requests directly to the application's
+ * memory space.  MapMem regions are allocated via
+ * gxio_trio_alloc_memory_maps().  Given an integer MapMem number,
+ * applications can use gxio_trio_init_memory_map() to specify the
+ * range of bus addresses that will match the region and the range of
+ * virtual addresses to which those packets will be applied.
+ *
+ * As with many other gxio APIs, the programmer must be sure to
+ * register memory pages that will be used with MapMem regions.  Pages
+ * can be registered with TRIO by allocating an ASID (address space
+ * identifier) and then using gxio_trio_register_page() to register up to
+ * 16 pages with the hardware.  The initialization functions for
+ * resources that require registered memory (MapMem, scatter queues,
+ * push DMA, and pull DMA) then take an 'asid' parameter in order to
+ * configure which set of registered pages is used by each resource.
+ *
+ * @subsection trio__scatter_queue TRIO Scatter Queues
+ *
+ * The TRIO shim's scatter queue regions allow users to dynamically
+ * map buffers from a large address space into a small range of bus
+ * addresses.  This is particularly helpful for PCIe endpoint devices,
+ * where the host generally limits the size of BARs to tens of
+ * megabytes.
+ *
+ * Each scatter queue consists of a memory map region, a queue of
+ * tile-side buffer VAs to be mapped to that region, and a bus-mapped
+ * "doorbell" register that the remote endpoint can write to trigger a
+ * dequeue of the current buffer VA, thus swapping in a new buffer.
+ * The VAs pushed onto a scatter queue must be 4kB aligned, so
+ * applications may need to use higher-level protocols to inform
+ * remote entities that they should apply some additional, sub-4kB
+ * offset when reading or writing the scatter queue region.  For more
+ * information, see the IO Device Guide (UG404).
+ *
+ * @section trio__egress TRIO Egress Hardware Resources
+ *
+ * The TRIO shim supports two mechanisms for egress packet generation:
+ * programmed IO (PIO) and push/pull DMA.  PIO allows applications to
+ * create MMIO mappings for PCIe or StreamIO address space, such that
+ * the application can generate word-sized read or write transactions
+ * by issuing load or store instructions.  Push and pull DMA are tuned
+ * for larger transactions; they use specialized hardware engines to
+ * transfer large blocks of data at line rate.
+ *
+ * @subsection trio__pio TRIO Programmed IO
+ *
+ * Programmed IO allows applications to create MMIO mappings for PCIe
+ * or StreamIO address space.  The hardware PIO regions support access
+ * to PCIe configuration, IO, and memory space, but the gxio_trio API
+ * only supports memory space accesses.  PIO regions are allocated
+ * with gxio_trio_alloc_pio_regions() and initialized via
+ * gxio_trio_init_pio_region().  Once a region is bound to a range of
+ * bus address via the initialization function, the application can
+ * use gxio_trio_map_pio_region() to create MMIO mappings from its VA
+ * space onto the range of bus addresses supported by the PIO region.
+ *
+ * @subsection trio_dma TRIO Push and Pull DMA
+ *
+ * The TRIO push and pull DMA engines allow users to copy blocks of
+ * data between application memory and the bus.  Push DMA generates
+ * write packets that copy from application memory to the bus and pull
+ * DMA generates read packets that copy from the bus into application
+ * memory.  The DMA engines are managed via an API that is very
+ * similar to the mPIPE eDMA interface.  For a detailed explanation of
+ * the eDMA queue API, see @ref gxio_mpipe_wrappers.
+ *
+ * Push and pull DMA queues are allocated via
+ * gxio_trio_alloc_push_dma_ring() / gxio_trio_alloc_pull_dma_ring().
+ * Once allocated, users generally use a ::gxio_trio_dma_queue_t
+ * object to manage the queue, providing easy wrappers for reserving
+ * command slots in the DMA command ring, filling those slots, and
+ * waiting for commands to complete.  DMA queues can be initialized
+ * via gxio_trio_init_push_dma_queue() or
+ * gxio_trio_init_pull_dma_queue().
+ *
+ * See @ref trio/push_dma/app.c for an example of how to use push DMA.
+ *
+ * @section trio_shortcomings Plans for Future API Revisions
+ *
+ * The API and simulation framework is incomplete.  Future features
+ * include:
+ *
+ * - Support for larger page sizes.  Each hardware IOTLB can only map
+ * 16 pages at a time, so applications are currently limited to 16 *
+ * 16MB = 256MB of packet memory.  Larger page sizes will allow
+ * applications to map arbitrary amounts of packet memory.
+ *
+ * - Support for reset and deallocation of resources.
+ *
+ * - Support for pull DMA.
+ *
+ * - Support for interrupt regions and user-space interrupt delivery.
+ *
+ * - Support for getting BAR mappings and reserving regions of BAR
+ *   address space.
+ */
+#ifndef _GXIO_TRIO_H_
+#define _GXIO_TRIO_H_
+
+#include <linux/types.h>
+
+#include "common.h"
+#include "dma_queue.h"
+
+#include <arch/trio_constants.h>
+#include <arch/trio.h>
+#include <arch/trio_pcie_intfc.h>
+#include <arch/trio_pcie_rc.h>
+#include <arch/trio_shm.h>
+#include <hv/drv_trio_intf.h>
+#include <hv/iorpc.h>
+
+/* A context object used to manage TRIO hardware resources. */
+typedef struct {
+
+	/* File descriptor for calling up to Linux (and thus the HV). */
+	int fd;
+
+	/* The VA at which the MAC MMIO registers are mapped. */
+	char *mmio_base_mac;
+
+	/* The VA at which the PIO config space are mapped for each PCIe MAC.
+	   Gx36 has max 3 PCIe MACs per TRIO shim. */
+	char *mmio_base_pio_cfg[TILEGX_TRIO_PCIES];
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+	/* Index of the shared PIO region for PCI config access. */
+	int pio_cfg_index;
+#else
+	/* Index of the PIO region for PCI config access per MAC. */
+	int pio_cfg_index[TILEGX_TRIO_PCIES];
+#endif
+
+	/*  The VA at which the push DMA MMIO registers are mapped. */
+	char *mmio_push_dma[TRIO_NUM_PUSH_DMA_RINGS];
+
+	/*  The VA at which the pull DMA MMIO registers are mapped. */
+	char *mmio_pull_dma[TRIO_NUM_PUSH_DMA_RINGS];
+
+	/* Application space ID. */
+	unsigned int asid;
+
+} gxio_trio_context_t;
+
+/* Command descriptor for push or pull DMA. */
+typedef TRIO_DMA_DESC_t gxio_trio_dma_desc_t;
+
+/* A convenient, thread-safe interface to an eDMA ring. */
+typedef struct {
+
+	/* State object for tracking head and tail pointers. */
+	__gxio_dma_queue_t dma_queue;
+
+	/* The ring entries. */
+	gxio_trio_dma_desc_t *dma_descs;
+
+	/* The number of entries minus one. */
+	unsigned long mask_num_entries;
+
+	/* The log2() of the number of entries. */
+	unsigned int log2_num_entries;
+
+} gxio_trio_dma_queue_t;
+
+/* Initialize a TRIO context.
+ *
+ * This function allocates a TRIO "service domain" and maps the MMIO
+ * registers into the the caller's VA space.
+ *
+ * @param trio_index Which TRIO shim; Gx36 must pass 0.
+ * @param context Context object to be initialized.
+ */
+extern int gxio_trio_init(gxio_trio_context_t *context,
+			  unsigned int trio_index);
+
+/* This indicates that an ASID hasn't been allocated. */
+#define GXIO_ASID_NULL -1
+
+/* Ordering modes for map memory regions and scatter queue regions. */
+typedef enum gxio_trio_order_mode_e {
+	/* Writes are not ordered.  Reads always wait for previous writes. */
+	GXIO_TRIO_ORDER_MODE_UNORDERED =
+		TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_UNORDERED,
+	/* Both writes and reads wait for previous transactions to complete. */
+	GXIO_TRIO_ORDER_MODE_STRICT =
+		TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_STRICT,
+	/* Writes are ordered unless the incoming packet has the
+	   relaxed-ordering attributes set. */
+	GXIO_TRIO_ORDER_MODE_OBEY_PACKET =
+		TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_REL_ORD
+} gxio_trio_order_mode_t;
+
+/* Initialize a memory mapping region.
+ *
+ * @param context An initialized TRIO context.
+ * @param map A Memory map region allocated by gxio_trio_alloc_memory_map().
+ * @param target_mem VA of backing memory, should be registered via
+ *   gxio_trio_register_page() and aligned to 4kB.
+ * @param target_size Length of the memory mapping, must be a multiple
+ * of 4kB.
+ * @param asid ASID to be used for Tile-side address translation.
+ * @param mac MAC number.
+ * @param bus_address Bus address at which the mapping starts.
+ * @param order_mode Memory ordering mode for this mapping.
+ * @return Zero on success, else ::GXIO_TRIO_ERR_BAD_MEMORY_MAP,
+ * GXIO_TRIO_ERR_BAD_ASID, or ::GXIO_TRIO_ERR_BAD_BUS_RANGE.
+ */
+extern int gxio_trio_init_memory_map(gxio_trio_context_t *context,
+				     unsigned int map, void *target_mem,
+				     size_t target_size, unsigned int asid,
+				     unsigned int mac, uint64_t bus_address,
+				     gxio_trio_order_mode_t order_mode);
+
+/* Flags that can be passed to resource allocation functions. */
+enum gxio_trio_alloc_flags_e {
+	GXIO_TRIO_ALLOC_FIXED = HV_TRIO_ALLOC_FIXED,
+};
+
+/* Flags that can be passed to memory registration functions. */
+enum gxio_trio_mem_flags_e {
+	/* Do not fill L3 when writing, and invalidate lines upon egress. */
+	GXIO_TRIO_MEM_FLAG_NT_HINT = IORPC_MEM_BUFFER_FLAG_NT_HINT,
+
+	/* L3 cache fills should only populate IO cache ways. */
+	GXIO_TRIO_MEM_FLAG_IO_PIN = IORPC_MEM_BUFFER_FLAG_IO_PIN,
+};
+
+/* Flag indicating a request generator uses a special traffic
+    class. */
+#define GXIO_TRIO_FLAG_TRAFFIC_CLASS(N) HV_TRIO_FLAG_TC(N)
+
+/* Flag indicating a request generator uses a virtual function
+    number. */
+#define GXIO_TRIO_FLAG_VFUNC(N) HV_TRIO_FLAG_VFUNC(N)
+
+/*****************************************************************
+ *                       Memory Registration                      *
+ ******************************************************************/
+
+/* Allocate Application Space Identifiers (ASIDs).  Each ASID can
+ * register up to 16 page translations.  ASIDs are used by memory map
+ * regions, scatter queues, and DMA queues to translate application
+ * VAs into memory system PAs.
+ *
+ * @param context An initialized TRIO context.
+ * @param count Number of ASIDs required.
+ * @param first Index of first ASID if ::GXIO_TRIO_ALLOC_FIXED flag
+ *   is set, otherwise ignored.
+ * @param flags Flag bits, including bits from ::gxio_trio_alloc_flags_e.
+ * @return Index of first ASID, or ::GXIO_TRIO_ERR_NO_ASID if allocation
+ *   failed.
+ */
+extern int gxio_trio_alloc_asids(gxio_trio_context_t *context,
+				 unsigned int count, unsigned int first,
+				 unsigned int flags);
+
+#endif /* ! _GXIO_TRIO_H_ */
diff --git a/arch/tile/include/hv/drv_trio_intf.h b/arch/tile/include/hv/drv_trio_intf.h
new file mode 100644
index 0000000..ef9f3f5
--- /dev/null
+++ b/arch/tile/include/hv/drv_trio_intf.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * Interface definitions for the trio driver.
+ */
+
+#ifndef _SYS_HV_DRV_TRIO_INTF_H
+#define _SYS_HV_DRV_TRIO_INTF_H
+
+#include <arch/trio.h>
+
+/** The vendor ID for all Tilera processors. */
+#define TILERA_VENDOR_ID 0x1a41
+
+/** The device ID for the Gx36 processor. */
+#define TILERA_GX36_DEV_ID 0x0200
+
+/** Device ID for our internal bridge when running as RC. */
+#define TILERA_GX36_RC_DEV_ID 0x2000
+
+/** Maximum number of TRIO interfaces. */
+#define TILEGX_NUM_TRIO         2
+
+/** Gx36 has max 3 PCIe MACs per TRIO interface. */
+#define TILEGX_TRIO_PCIES       3
+
+/** Specify port properties for a PCIe MAC. */
+struct pcie_port_property
+{
+  /** If true, the link can be configured in PCIe root complex mode. */
+  uint8_t allow_rc: 1;
+
+  /** If true, the link can be configured in PCIe endpoint mode. */
+  uint8_t allow_ep: 1;
+
+  /** If true, the link can be configured in StreamIO mode. */
+  uint8_t allow_sio: 1;
+
+  /** If true, the link is allowed to support 1-lane operation. Software
+   *  will not consider it an error if the link comes up as a x1 link. */
+  uint8_t allow_x1: 1;
+
+  /** If true, the link is allowed to support 2-lane operation. Software
+   *  will not consider it an error if the link comes up as a x2 link. */
+  uint8_t allow_x2: 1;
+
+  /** If true, the link is allowed to support 4-lane operation. Software
+   *  will not consider it an error if the link comes up as a x4 link. */
+  uint8_t allow_x4: 1;
+
+  /** If true, the link is allowed to support 8-lane operation. Software
+   *  will not consider it an error if the link comes up as a x8 link. */
+  uint8_t allow_x8: 1;
+
+  /** Reserved. */
+  uint8_t reserved: 1;
+
+};
+
+/** Configurations can be issued to configure a char stream interrupt. */
+typedef enum pcie_stream_intr_config_sel_e
+{
+  /** Interrupt configuration for memory map regions. */
+  MEM_MAP_SEL,
+
+  /** Interrupt configuration for push DMAs. */
+  PUSH_DMA_SEL,
+
+  /** Interrupt configuration for pull DMAs. */
+  PULL_DMA_SEL,
+}
+pcie_stream_intr_config_sel_t;
+
+
+/** The mmap file offset (PA) of the TRIO config region. */
+#define HV_TRIO_CONFIG_OFFSET                                        \
+  ((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_CFG <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT)
+
+/** The maximum size of the TRIO config region. */
+#define HV_TRIO_CONFIG_SIZE                                 \
+  (1ULL << TRIO_CFG_REGION_ADDR__REGION_SHIFT)
+
+/** Size of the config region mapped into client. We can't use
+ *  TRIO_MMIO_ADDRESS_SPACE__OFFSET_WIDTH because it
+ *  will require the kernel to allocate 4GB VA space
+ *  from the VMALLOC region which has a total range
+ *  of 4GB.
+ */
+#define HV_TRIO_CONFIG_IOREMAP_SIZE                            \
+  ((uint64_t) 1 << TRIO_CFG_REGION_ADDR__PROT_SHIFT)
+
+/** The mmap file offset (PA) of a scatter queue region. */
+#define HV_TRIO_SQ_OFFSET(queue)                                        \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_MAP_SQ <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((queue) << TRIO_MAP_SQ_REGION_ADDR__SQ_SEL_SHIFT))
+
+/** The maximum size of a scatter queue region. */
+#define HV_TRIO_SQ_SIZE                                 \
+  (1ULL << TRIO_MAP_SQ_REGION_ADDR__SQ_SEL_SHIFT)
+
+
+/** The "hardware MMIO region" of the first PIO region. */
+#define HV_TRIO_FIRST_PIO_REGION 8
+
+/** The mmap file offset (PA) of a PIO region. */
+#define HV_TRIO_PIO_OFFSET(region)                           \
+  (((unsigned long long)(region) + HV_TRIO_FIRST_PIO_REGION) \
+   << TRIO_PIO_REGIONS_ADDR__REGION_SHIFT)
+
+/** The maximum size of a PIO region. */
+#define HV_TRIO_PIO_SIZE (1ULL << TRIO_PIO_REGIONS_ADDR__ADDR_WIDTH)
+
+
+/** The mmap file offset (PA) of a push DMA region. */
+#define HV_TRIO_PUSH_DMA_OFFSET(ring)                                   \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_PUSH_DMA << \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((ring) << TRIO_PUSH_DMA_REGION_ADDR__RING_SEL_SHIFT))
+
+/** The mmap file offset (PA) of a pull DMA region. */
+#define HV_TRIO_PULL_DMA_OFFSET(ring)                                   \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_PULL_DMA << \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((ring) << TRIO_PULL_DMA_REGION_ADDR__RING_SEL_SHIFT))
+
+/** The maximum size of a DMA region. */
+#define HV_TRIO_DMA_REGION_SIZE                         \
+  (1ULL << TRIO_PUSH_DMA_REGION_ADDR__RING_SEL_SHIFT)
+
+
+/** The mmap file offset (PA) of a Mem-Map interrupt region. */
+#define HV_TRIO_MEM_MAP_INTR_OFFSET(map)                                 \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_MAP_MEM <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((map) << TRIO_MAP_MEM_REGION_ADDR__MAP_SEL_SHIFT))
+
+/** The maximum size of a Mem-Map interrupt region. */
+#define HV_TRIO_MEM_MAP_INTR_SIZE                                 \
+  (1ULL << TRIO_MAP_MEM_REGION_ADDR__MAP_SEL_SHIFT)
+
+
+/** A flag bit indicating a fixed resource allocation. */
+#define HV_TRIO_ALLOC_FIXED 0x01
+
+/** TRIO requires that all mappings have 4kB aligned start addresses. */
+#define HV_TRIO_PAGE_SHIFT 12
+
+/** TRIO requires that all mappings have 4kB aligned start addresses. */
+#define HV_TRIO_PAGE_SIZE (1ull << HV_TRIO_PAGE_SHIFT)
+
+
+/* Specify all PCIe port properties for a TRIO. */
+struct pcie_trio_ports_property
+{
+  struct pcie_port_property ports[TILEGX_TRIO_PCIES];
+};
+
+/* Flags indicating traffic class. */
+#define HV_TRIO_FLAG_TC_SHIFT 4
+#define HV_TRIO_FLAG_TC_RMASK 0xf
+#define HV_TRIO_FLAG_TC(N) \
+  ((((N) & HV_TRIO_FLAG_TC_RMASK) + 1) << HV_TRIO_FLAG_TC_SHIFT)
+
+/* Flags indicating virtual functions. */
+#define HV_TRIO_FLAG_VFUNC_SHIFT 8
+#define HV_TRIO_FLAG_VFUNC_RMASK 0xff
+#define HV_TRIO_FLAG_VFUNC(N) \
+  ((((N) & HV_TRIO_FLAG_VFUNC_RMASK) + 1) << HV_TRIO_FLAG_VFUNC_SHIFT)
+
+
+/* Flag indicating an ordered PIO region. */
+#define HV_TRIO_PIO_FLAG_ORDERED (1 << 16)
+
+/* Flags indicating special types of PIO regions. */
+#define HV_TRIO_PIO_FLAG_SPACE_SHIFT 17
+#define HV_TRIO_PIO_FLAG_SPACE_MASK (0x3 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+#define HV_TRIO_PIO_FLAG_CONFIG_SPACE (0x1 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+#define HV_TRIO_PIO_FLAG_IO_SPACE (0x2 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+
+
+#endif /* _SYS_HV_DRV_TRIO_INTF_H */
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 2/2] arch/tile: tilegx PCI root complex support
  2012-05-08 20:53         ` [PATCH v2 0/2] arch/tile: " Chris Metcalf
  2012-05-08 20:53           ` [PATCH v2 1/2] arch/tile: provide kernel support for the tilegx TRIO shim Chris Metcalf
@ 2012-05-08 21:10           ` Chris Metcalf
  2012-05-09 16:58             ` Michael S. Tsirkin
  1 sibling, 1 reply; 19+ messages in thread
From: Chris Metcalf @ 2012-05-08 21:10 UTC (permalink / raw)
  To: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Arnd Bergmann, Jiri Kosina,
	Joe Perches,
	David Howells <dhowells@redhat.com> Jesper Juhl

This change implements PCIe root complex support for tilegx using
the kernel support layer for accessing the TRIO hardware shim.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
---
 arch/tile/Kconfig           |    3 +
 arch/tile/include/asm/pci.h |   99 +++-
 arch/tile/kernel/Makefile   |    4 +
 arch/tile/kernel/pci_gx.c   | 1545 +++++++++++++++++++++++++++++++++++++++++++
 arch/tile/kernel/setup.c    |    6 +
 arch/tile/mm/pgtable.c      |    7 -
 drivers/pci/quirks.c        |    6 +-
 7 files changed, 1650 insertions(+), 20 deletions(-)
 create mode 100644 arch/tile/kernel/pci_gx.c

diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index d79ebc3..631971c 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -359,6 +359,9 @@ config PCI
 	default y
 	select PCI_DOMAINS
 	select GENERIC_PCI_IOMAP
+	select TILE_GXIO_TRIO if TILEGX
+	select ARCH_SUPPORTS_MSI if TILEGX
+	select PCI_MSI if TILEGX
 	---help---
 	  Enable PCI root complex support, so PCIe endpoint devices can
 	  be attached to the Tile chip.  Many, but not all, PCI devices
diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h
index 5d5a635..54907d8 100644
--- a/arch/tile/include/asm/pci.h
+++ b/arch/tile/include/asm/pci.h
@@ -16,8 +16,11 @@
 #define _ASM_TILE_PCI_H
 
 #include <linux/pci.h>
+#include <linux/numa.h>
 #include <asm-generic/pci_iomap.h>
 
+#ifndef __tilegx__
+
 /*
  * Structure of a PCI controller (host bridge)
  */
@@ -41,6 +44,92 @@ struct pci_controller {
 };
 
 /*
+ * This flag tells if the platform is TILEmpower that needs
+ * special configuration for the PLX switch chip.
+ */
+extern int tile_plx_gen1;
+
+static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
+
+#define	TILE_NUM_PCIE	2
+
+#else
+
+#include <asm/page.h>
+#include <gxio/trio.h>
+
+/**
+ * We reserve the hugepage-size address range at the top of the 64-bit address
+ * space to serve as the PCI window, emulating the BAR0 space of an endpoint
+ * device. This window is used by the chip-to-chip applications running on
+ * the RC node. The reason for carving out this window is that Mem-Maps that
+ * back up this window will not overlap with those that map the real physical
+ * memory.
+ */
+#define PCIE_HOST_BAR0_SIZE		HPAGE_SIZE
+#define PCIE_HOST_BAR0_START		HPAGE_MASK
+
+/**
+ * The first PAGE_SIZE of the above "BAR" window is mapped to the
+ * gxpci_host_regs structure.
+ */
+#define PCIE_HOST_REGS_SIZE		PAGE_SIZE
+
+/*
+ * This is the PCI address where the Mem-Map interrupt regions start.
+ * We use the 2nd to the last huge page of the 64-bit address space.
+ * The last huge page is used for the rootcomplex "bar", for C2C purpose.
+ */
+#define	MEM_MAP_INTR_REGIONS_BASE	(HPAGE_MASK - HPAGE_SIZE)
+
+/*
+ * Each Mem-Map interrupt region occupies 4KB.
+ */
+#define	MEM_MAP_INTR_REGION_SIZE	(1<< TRIO_MAP_MEM_LIM__ADDR_SHIFT)
+
+/*
+ * Structure of a PCI controller (host bridge) on Gx.
+ */
+struct pci_controller {
+
+	/* Pointer back to the TRIO that this PCIe port is connected to. */
+	gxio_trio_context_t *trio;
+	int mac;		/* PCIe mac index on the TRIO shim */
+	int trio_index;		/* Index of TRIO shim that contains the MAC. */
+
+	int pio_mem_index;	/* PIO region index for memory access */
+
+	/*
+	 * Mem-Map regions for all the memory controllers so that Linux can
+	 * map all of its physical memory space to the PCI bus.
+	 */
+	int mem_maps[MAX_NUMNODES];
+
+	int index;		/* PCI domain number */
+	struct pci_bus *root_bus;
+
+	int last_busno;
+
+	struct pci_ops *ops;
+
+	/* Table that maps the INTx numbers to Linux irq numbers. */
+	int irq_intx_table[4];
+
+	struct resource mem_space;
+
+	/* Address ranges that are routed to this controller/bridge. */
+	struct resource mem_resources[3];
+};
+
+extern struct pci_controller pci_controllers[TILEGX_NUM_TRIO * TILEGX_TRIO_PCIES];
+extern gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
+
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+#endif /* __tilegx__ */
+
+/*
  * The hypervisor maps the entirety of CPA-space as bus addresses, so
  * bus addresses are physical addresses.  The networking and block
  * device layers use this boolean for bounce buffer decisions.
@@ -50,12 +139,8 @@ struct pci_controller {
 int __devinit tile_pci_init(void);
 int __devinit pcibios_init(void);
 
-static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
-
 void __devinit pcibios_fixup_bus(struct pci_bus *bus);
 
-#define	TILE_NUM_PCIE	2
-
 #define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index)
 
 /*
@@ -79,12 +164,6 @@ static inline int pcibios_assign_all_busses(void)
 #define PCIBIOS_MIN_MEM		0
 #define PCIBIOS_MIN_IO		0
 
-/*
- * This flag tells if the platform is TILEmpower that needs
- * special configuration for the PLX switch chip.
- */
-extern int tile_plx_gen1;
-
 /* Use any cpu for PCI. */
 #define cpumask_of_pcibus(bus) cpu_online_mask
 
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile
index f19116d..e09281f 100644
--- a/arch/tile/kernel/Makefile
+++ b/arch/tile/kernel/Makefile
@@ -14,4 +14,8 @@ obj-$(CONFIG_SMP)		+= smpboot.o smp.o tlb.o
 obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel_$(BITS).o
+ifdef CONFIG_TILEGX
+obj-$(CONFIG_PCI)		+= pci_gx.o
+else
 obj-$(CONFIG_PCI)		+= pci.o
+endif
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
new file mode 100644
index 0000000..e42bef5
--- /dev/null
+++ b/arch/tile/kernel/pci_gx.c
@@ -0,0 +1,1545 @@
+/*
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mmzone.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/byteorder.h>
+
+#include <gxio/iorpc_globals.h>
+#include <gxio/kiorpc.h>
+#include <gxio/trio.h>
+#include <gxio/iorpc_trio.h>
+#include <hv/drv_trio_intf.h>
+
+#include <arch/sim.h>
+
+/*
+ * Initialization flow and process
+ * -------------------------------
+ *
+ * This files containes the routines to search for PCI buses,
+ * enumerate the buses, and configure any attached devices.
+ *
+ * There are two entry points here:
+ * 1) tile_pci_init
+ *    This sets up the pci_controller structs, and opens the
+ *    FDs to the hypervisor.  This is called from setup_arch() early
+ *    in the boot process.
+ * 2) pcibios_init
+ *    This probes the PCI bus(es) for any attached hardware.  It's
+ *    called by subsys_initcall.  All of the real work is done by the
+ *    generic Linux PCI layer.
+ *
+ */
+
+#define DEBUG_PCI_CFG	0
+
+#if DEBUG_PCI_CFG
+#define TRACE_CFG_WR(size, val, bus, dev, func, offset) \
+	pr_info("CFG WR %d-byte VAL %#x to bus %d dev %d func %d addr %u\n", \
+		size, val, bus, dev, func, offset & 0xFFF);
+#define TRACE_CFG_RD(size, val, bus, dev, func, offset) \
+	pr_info("CFG RD %d-byte VAL %#x from bus %d dev %d func %d addr %u\n", \
+		size, val, bus, dev, func, offset & 0xFFF);
+#else
+#define TRACE_CFG_WR(...)
+#define TRACE_CFG_RD(...)
+#endif
+
+static int __devinitdata pci_probe = 1;
+
+/* Information on the PCIe RC ports configuration. */
+static int __devinitdata pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+
+/*
+ * On some platforms with one or more Gx endpoint ports, we need to
+ * delay the PCIe RC port probe for a few seconds to work around
+ * a HW PCIe link-training bug. The exact delay is specified with
+ * a kernel boot argument in the form of "pcie_rc_delay=T,P,S",
+ * where T is the TRIO instance number, P is the port number and S is
+ * the delay in seconds. If the delay is not provided, the value
+ * will be DEFAULT_RC_DELAY.
+ */
+static int __devinitdata rc_delay[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+
+/* Default number of seconds that the PCIe RC port probe can be delayed. */
+#define DEFAULT_RC_DELAY	10
+
+/* Max number of seconds that the PCIe RC port probe can be delayed. */
+#define MAX_RC_DELAY		20
+
+/* Array of the PCIe ports configuration info obtained from the BIB. */
+struct pcie_port_property pcie_ports[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+
+/* All drivers share the TRIO contexts defined here. */
+gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
+
+/* Pointer to an array of PCIe RC controllers. */
+struct pci_controller pci_controllers[TILEGX_NUM_TRIO * TILEGX_TRIO_PCIES];
+int num_rc_controllers;
+static int num_ep_controllers;
+
+static struct pci_ops tile_cfg_ops;
+
+/* Mask of CPUs that should receive PCIe interrupts. */
+static struct cpumask intr_cpus_map;
+
+/*
+ * We don't need to worry about the alignment of resources.
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	return res->start;
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+
+/*
+ * Pick a CPU to receive and handle the PCIe interrupts, based on the IRQ #.
+ * For now, we simply send interrupts to non-dataplane CPUs.
+ * We may implement methods to allow user to specify the target CPUs,
+ * e.g. via boot arguments.
+ */
+static int tile_irq_cpu(int irq)
+{
+	unsigned int count;
+	int i = 0;
+	int cpu;
+
+	count = cpumask_weight(&intr_cpus_map);
+	if (unlikely(count == 0)) {
+		pr_warning("intr_cpus_map empty, interrupts will be"
+			   " delievered to dataplane tiles\n");
+		return irq % (smp_height * smp_width);
+	}
+
+	count = irq % count;
+	for_each_cpu(cpu, &intr_cpus_map) {
+		if (i++ == count)
+			break;
+	}
+	return cpu;
+}
+
+/*
+ * Open a file descriptor to the TRIO shim.
+ */
+static int __devinit tile_pcie_open(int trio_index)
+{
+	gxio_trio_context_t *context = &trio_contexts[trio_index];
+	int ret;
+
+	/*
+	 * This opens a file descriptor to the TRIO shim.
+	 */
+	ret = gxio_trio_init(context, trio_index);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Allocate an ASID for the kernel.
+	 */
+	ret = gxio_trio_alloc_asids(context, 1, 0, 0);
+	if (ret < 0) {
+		pr_err("PCI: ASID alloc failure on TRIO %d, give up\n",
+			trio_index);
+		goto asid_alloc_failure;
+	}
+
+	context->asid = ret;
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+	/*
+	 * Alloc a PIO region for config access, shared by all MACs per TRIO.
+	 * This shouldn't fail since the kernel is supposed to the first
+	 * client of the TRIO's PIO regions.
+	 */
+	ret = gxio_trio_alloc_pio_regions(context, 1, 0, 0);
+	if (ret < 0) {
+		pr_err("PCI: CFG PIO alloc failure on TRIO %d, give up\n",
+			trio_index);
+		goto pio_alloc_failure;
+	}
+
+	context->pio_cfg_index = ret;
+
+	/*
+	 * For PIO CFG, the bus_address_hi parameter is 0. The mac parameter
+	 * is also 0 because it is specified in PIO_REGION_SETUP_CFG_ADDR.
+	 */
+	ret = gxio_trio_init_pio_region_aux(context, context->pio_cfg_index,
+		0, 0, HV_TRIO_PIO_FLAG_CONFIG_SPACE);
+	if (ret < 0) {
+		pr_err("PCI: CFG PIO init failure on TRIO %d, give up\n",
+			trio_index);
+		goto pio_alloc_failure;
+	}
+#endif
+
+	return ret;
+
+asid_alloc_failure:
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+pio_alloc_failure:
+#endif
+	hv_dev_close(context->fd);
+
+	return ret;
+}
+
+static void
+tilegx_legacy_irq_ack(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_EVENT_RESET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_legacy_irq_mask(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_legacy_irq_unmask(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq);
+}
+
+static struct irq_chip tilegx_legacy_irq_chip = {
+	.name			= "tilegx_legacy_irq",
+	.irq_ack		= tilegx_legacy_irq_ack,
+	.irq_mask		= tilegx_legacy_irq_mask,
+	.irq_unmask		= tilegx_legacy_irq_unmask,
+
+	/* TBD: support set_affinity. */
+};
+
+/*
+ * This is a wrapper function of the kernel level-trigger interrupt
+ * handler handle_level_irq() for PCI legacy interrupts. The TRIO
+ * is configured such that only INTx Assert interrupts are proxied
+ * to Linux which just calls handle_level_irq() after clearing the
+ * MAC INTx Assert status bit associated with this interrupt.
+ */
+static void
+trio_handle_level_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct pci_controller *controller = irq_desc_get_handler_data(desc);
+	gxio_trio_context_t *trio_context = controller->trio;
+	uint64_t intx = (uint64_t)irq_desc_get_chip_data(desc);
+	int mac = controller->mac;
+	unsigned int reg_offset;
+	uint64_t level_mask;
+
+	handle_level_irq(irq, desc);
+
+	/*
+	 * Clear the INTx Level status, otherwise future interrupts are
+	 * not sent.
+	 */
+	reg_offset = (TRIO_PCIE_INTFC_MAC_INT_STS <<
+		TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+		(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+		TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+	level_mask = TRIO_PCIE_INTFC_MAC_INT_STS__INT_LEVEL_MASK << intx;
+
+	__gxio_mmio_write(trio_context->mmio_base_mac + reg_offset, level_mask);
+}
+
+/*
+ * Create kernel irqs and set up the handlers for the legacy interrupts.
+ * Also some minimum initialization for the MSI support.
+ */
+static int __devinit tile_init_irqs(struct pci_controller *controller)
+{
+	int i;
+	int j;
+	int irq;
+	int result;
+
+	cpumask_copy(&intr_cpus_map, cpu_online_mask);
+
+
+	for (i = 0; i < 4; i++) {
+		gxio_trio_context_t *context = controller->trio;
+		int cpu;
+
+		/* Ask the kernel to allocate an IRQ. */
+		irq = create_irq();
+		if (irq < 0) {
+			pr_err("PCI: no free irq vectors, failed for %d\n", i);
+
+			goto free_irqs;
+		}
+		controller->irq_intx_table[i] = irq;
+
+		/* Distribute the 4 IRQs to different tiles. */
+		cpu = tile_irq_cpu(irq);
+
+		/* Configure the TRIO intr binding for this IRQ. */
+		result = gxio_trio_config_legacy_intr(context, cpu_x(cpu),
+						      cpu_y(cpu), KERNEL_PL,
+						      irq, controller->mac, i);
+		if (result < 0) {
+			pr_err("PCI: MAC intx config failed for %d\n", i);
+
+			goto free_irqs;
+		}
+
+		/*
+		 * Register the IRQ handler with the kernel.
+		 */
+		irq_set_chip_and_handler(irq, &tilegx_legacy_irq_chip,
+					trio_handle_level_irq);
+		irq_set_chip_data(irq, (void *)(uint64_t)i);
+		irq_set_handler_data(irq, controller);
+	}
+
+	return 0;
+
+free_irqs:
+	for (j = 0; j < i; j++)
+		destroy_irq(controller->irq_intx_table[j]);
+
+	return -1;
+}
+
+/*
+ * First initialization entry point, called from setup_arch().
+ *
+ * Find valid controllers and fill in pci_controller structs for each
+ * of them.
+ *
+ * Returns the number of controllers discovered.
+ */
+int __init tile_pci_init(void)
+{
+	int num_trio_shims = 0;
+	int ctl_index = 0;
+	int i, j;
+
+	if (!pci_probe) {
+		pr_info("PCI: disabled by boot argument\n");
+		return 0;
+	}
+
+	pr_info("PCI: Searching for controllers...\n");
+
+	/*
+	 * We loop over all the TRIO shims.
+	 */
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		int ret;
+
+		ret = tile_pcie_open(i);
+		if (ret < 0)
+			continue;
+
+		num_trio_shims++;
+	}
+
+	if (num_trio_shims == 0 || sim_is_simulator())
+		return 0;
+
+	/*
+	 * Now determine which PCIe ports are configured to operate in RC mode.
+	 * We look at the Board Information Block first and then see if there
+	 * are any overriding configuration by the HW strapping pin.
+	 */
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		gxio_trio_context_t *context = &trio_contexts[i];
+		int ret;
+
+		if (context->fd < 0)
+			continue;
+
+		ret = hv_dev_pread(context->fd, 0,
+			(HV_VirtAddr)&pcie_ports[i][0],
+			sizeof(struct pcie_port_property) * TILEGX_TRIO_PCIES,
+			GXIO_TRIO_OP_GET_PORT_PROPERTY);
+		if (ret < 0) {
+			pr_err("PCI: PCIE_GET_PORT_PROPERTY failure, error %d,"
+				" on TRIO %d\n", ret, i);
+			continue;
+		}
+
+		for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
+			if (pcie_ports[i][j].allow_rc) {
+				pcie_rc[i][j] = 1;
+				num_rc_controllers++;
+			}
+			else if (pcie_ports[i][j].allow_ep) {
+				num_ep_controllers++;
+			}
+		}
+	}
+
+	/*
+	 * Return if no PCIe ports are configured to operate in RC mode.
+	 */
+	if (num_rc_controllers == 0)
+		return 0;
+
+	/*
+	 * Set the TRIO pointer and MAC index for each PCIe RC port.
+	 */
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
+			if (pcie_rc[i][j]) {
+				pci_controllers[ctl_index].trio =
+					&trio_contexts[i];
+				pci_controllers[ctl_index].mac = j;
+				pci_controllers[ctl_index].trio_index = i;
+				ctl_index++;
+				if (ctl_index == num_rc_controllers)
+					goto out;
+			}
+		}
+	}
+
+out:
+	/*
+	 * Configure each PCIe RC port.
+	 */
+	for (i = 0; i < num_rc_controllers; i++) {
+		/*
+		 * Configure the PCIe MAC to run in RC mode.
+		 */
+
+		struct pci_controller *controller = &pci_controllers[i];
+
+		controller->index = i;
+		controller->last_busno = 0xff;
+		controller->ops = &tile_cfg_ops;
+
+	}
+
+	return num_rc_controllers;
+}
+
+/*
+ * (pin - 1) converts from the PCI standard's [1:4] convention to
+ * a normal [0:3] range.
+ */
+static int tile_map_irq(const struct pci_dev *dev, u8 device, u8 pin)
+{
+	struct pci_controller *controller =
+		(struct pci_controller *)dev->sysdata;
+	return controller->irq_intx_table[pin - 1];
+}
+
+
+static void __devinit fixup_read_and_payload_sizes(struct pci_controller *
+						controller)
+{
+	gxio_trio_context_t *trio_context = controller->trio;
+	struct pci_bus *root_bus = controller->root_bus;
+	TRIO_PCIE_RC_DEVICE_CONTROL_t dev_control;
+	TRIO_PCIE_RC_DEVICE_CAP_t rc_dev_cap;
+	unsigned int reg_offset;
+	struct pci_bus *child;
+	int mac;
+	int err;
+
+	mac = controller->mac;
+
+	/*
+	 * Set our max read request size to be 4KB.
+	 */
+	reg_offset =
+		(TRIO_PCIE_RC_DEVICE_CONTROL <<
+			TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+		(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+			TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+	dev_control.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
+						reg_offset);
+	dev_control.max_read_req_sz = 5;
+	__gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+						dev_control.word);
+
+	/*
+	 * Set the max payload size supported by this Gx PCIe MAC.
+	 * Though Gx PCIe supports Max Payload Size of up to 1024 bytes,
+	 * experiments have shown that setting MPS to 256 yields the
+	 * best performance.
+	 */
+	reg_offset =
+		(TRIO_PCIE_RC_DEVICE_CAP <<
+			TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+		(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+			TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+	rc_dev_cap.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
+						reg_offset);
+	rc_dev_cap.mps_sup = 1;
+	__gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+						rc_dev_cap.word);
+
+	/* Configure PCI Express MPS setting. */
+	list_for_each_entry(child, &root_bus->children, node) {
+		struct pci_dev *self = child->self;
+		if (!self)
+			continue;
+
+		pcie_bus_configure_settings(child, self->pcie_mpss);
+	}
+
+	/*
+	 * Set the mac_config register in trio based on the MPS/MRS of the link.
+	 */
+	reg_offset =
+		(TRIO_PCIE_RC_DEVICE_CONTROL <<
+			TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+		(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+			TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+		(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+	dev_control.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
+						reg_offset);
+
+	err = gxio_trio_set_mps_mrs(trio_context,
+				    dev_control.max_payload_size,
+				    dev_control.max_read_req_sz,
+				    mac);
+        if (err < 0) {
+		pr_err("PCI: PCIE_CONFIGURE_MAC_MPS_MRS failure, "
+			"MAC %d on TRIO %d\n",
+			mac, controller->trio_index);
+	}
+}
+
+static int __devinit setup_pcie_rc_delay(char *str)
+{
+	unsigned long delay = 0;
+	unsigned long trio_index;
+	unsigned long mac;
+
+	if (str == NULL || !isdigit(*str))
+		return -EINVAL;
+	trio_index = simple_strtoul(str, (char **)&str, 10);
+	if (trio_index >= TILEGX_NUM_TRIO)
+		return -EINVAL;
+
+	if (*str != ',')
+		return -EINVAL;
+
+	str++;
+	if (!isdigit(*str))
+		return -EINVAL;
+	mac = simple_strtoul(str, (char **)&str, 10);
+	if (mac >= TILEGX_TRIO_PCIES)
+		return -EINVAL;
+
+	if (*str != '\0') {
+		if (*str != ',')
+			return -EINVAL;
+
+		str++;
+		if (!isdigit(*str))
+			return -EINVAL;
+		delay = simple_strtoul(str, (char **)&str, 10);
+		if (delay > MAX_RC_DELAY)
+			return -EINVAL;
+	}
+
+	rc_delay[trio_index][mac] = delay ? : DEFAULT_RC_DELAY;
+	pr_info("Delaying PCIe RC link training for %u sec"
+		" on MAC %lu on TRIO %lu\n", rc_delay[trio_index][mac],
+		mac, trio_index);
+	return 0;
+}
+early_param("pcie_rc_delay", setup_pcie_rc_delay);
+
+/*
+ * Second PCI initialization entry point, called by subsys_initcall.
+ *
+ * The controllers have been set up by the time we get here, by a call to
+ * tile_pci_init.
+ */
+int __init pcibios_init(void)
+{
+	struct list_head resources;
+	resource_size_t offset;
+	int i;
+
+	if (num_rc_controllers == 0 && num_ep_controllers == 0)
+		return 0;
+
+	pr_info("PCI: Probing PCI hardware\n");
+
+	/*
+	 * We loop over all the TRIO shims and set up the MMIO mappings.
+	 * This step can't be done in tile_pci_init because the MM subsystem
+	 * hasn't been initialized then.
+	 */
+	for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+		gxio_trio_context_t *context = &trio_contexts[i];
+
+		if (context->fd < 0)
+			continue;
+
+		/*
+		 * Map in the MMIO space for the MAC.
+		 */
+		offset = 0;
+		context->mmio_base_mac =
+			iorpc_ioremap(context->fd, offset,
+				      HV_TRIO_CONFIG_IOREMAP_SIZE);
+		if (context->mmio_base_mac == NULL) {
+			pr_err("PCI: MAC map failure on TRIO %d\n", i);
+
+			hv_dev_close(context->fd);
+			context->fd = -1;
+			continue;
+		}
+	}
+
+	/*
+	 * Delay a bit in case devices aren't ready.  Some devices are
+	 * known to require at least 20ms here, but we use a more
+	 * conservative value.
+	 */
+	msleep(250);
+
+	/* Scan all of the recorded PCI controllers.  */
+	for (i = 0; i < num_rc_controllers; i++) {
+		struct pci_controller *controller = &pci_controllers[i];
+		gxio_trio_context_t *trio_context = controller->trio;
+		TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
+		TRIO_PCIE_INTFC_PORT_STATUS_t port_status;
+		TRIO_PCIE_INTFC_TX_FIFO_CTL_t tx_fifo_ctl;
+		struct pci_bus *bus;
+		unsigned int reg_offset;
+		unsigned int class_code_revision;
+		int trio_index;
+		int mac;
+#ifndef USE_SHARED_PCIE_CONFIG_REGION
+		int ret;
+#endif
+
+		if (trio_context->fd < 0)
+			continue;
+
+		trio_index = controller->trio_index;
+		mac = controller->mac;
+
+		/*
+		 * Check the port strap state which will override the BIB
+		 * setting.
+		 */
+
+		reg_offset =
+			(TRIO_PCIE_INTFC_PORT_CONFIG <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		port_config.word =
+			__gxio_mmio_read(trio_context->mmio_base_mac +
+					 reg_offset);
+
+		if ((port_config.strap_state !=
+			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC) &&
+			(port_config.strap_state !=
+			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1)) {
+			/*
+			 * If this is really intended to be an EP port,
+			 * record it so that the endpoint driver will know about it.
+			 */
+			if (port_config.strap_state ==
+			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT ||
+			port_config.strap_state ==
+			TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1)
+				pcie_ports[trio_index][mac].allow_ep = 1;
+
+			continue;
+		}
+
+		/*
+		 * Delay the RC link training if needed.
+		 */
+		if (rc_delay[trio_index][mac])
+			msleep(rc_delay[trio_index][mac] * 1000);
+
+		ret = gxio_trio_force_rc_link_up(trio_context, mac);
+		if (ret < 0)
+			pr_err("PCI: PCIE_FORCE_LINK_UP failure, "
+				"MAC %d on TRIO %d\n", mac, trio_index);
+
+		pr_info("PCI: Found PCI controller #%d on TRIO %d MAC %d\n", i,
+			trio_index, controller->mac);
+
+		/*
+		 * Wait a bit here because some EP devices take longer
+		 * to come up.
+		 */
+		msleep(1000);
+
+		/*
+		 * Check for PCIe link-up status.
+		 */
+
+		reg_offset =
+			(TRIO_PCIE_INTFC_PORT_STATUS <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		port_status.word =
+			__gxio_mmio_read(trio_context->mmio_base_mac +
+					 reg_offset);
+		if (!port_status.dl_up) {
+			pr_err("PCI: link is down, MAC %d on TRIO %d\n",
+				mac, trio_index);
+			continue;
+		}
+
+		/*
+		 * Ensure that the link can come out of L1 power down state.
+		 * Strictly speaking, this is needed only in the case of
+		 * heavy RC-initiated DMAs.
+		 */
+		reg_offset =
+			(TRIO_PCIE_INTFC_TX_FIFO_CTL <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+		tx_fifo_ctl.word =
+			__gxio_mmio_read(trio_context->mmio_base_mac +
+					 reg_offset);
+		tx_fifo_ctl.min_p_credits = 0;
+		__gxio_mmio_write(trio_context->mmio_base_mac + reg_offset,
+				  tx_fifo_ctl.word);
+
+		/*
+		 * Change the device ID so that Linux bus crawl doesn't confuse
+		 * the internal bridge with any Tilera endpoints.
+		 */
+
+		reg_offset =
+			(TRIO_PCIE_RC_DEVICE_ID_VEN_ID <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		__gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+				    (TILERA_GX36_RC_DEV_ID <<
+				    TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT) |
+				    TILERA_VENDOR_ID);
+
+		/*
+		 * Set the internal P2P bridge class code.
+		 */
+
+		reg_offset =
+			(TRIO_PCIE_RC_REVISION_ID <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+			(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+				TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+			(mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+		class_code_revision =
+			__gxio_mmio_read32(trio_context->mmio_base_mac +
+					   reg_offset);
+		class_code_revision = (class_code_revision & 0xff ) |
+					(PCI_CLASS_BRIDGE_PCI << 16);
+
+		__gxio_mmio_write32(trio_context->mmio_base_mac +
+				    reg_offset, class_code_revision);
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+
+		/*
+		 * Map in the MMIO space for the PIO region.
+		 */
+		offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index) |
+			(((unsigned long long)mac) <<
+			TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
+
+#else
+
+		/*
+		 * Alloc a PIO region for PCI config access per MAC.
+		 */
+		ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
+		if (ret < 0) {
+			pr_err("PCI: PCI CFG PIO alloc failure for mac %d "
+				"on TRIO %d, give up\n", mac, trio_index);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		trio_context->pio_cfg_index[mac] = ret;
+
+		/*
+		 * For PIO CFG, the bus_address_hi parameter is 0.
+		 */
+		ret = gxio_trio_init_pio_region_aux(trio_context,
+			trio_context->pio_cfg_index[mac],
+			mac, 0, HV_TRIO_PIO_FLAG_CONFIG_SPACE);
+		if (ret < 0) {
+			pr_err("PCI: PCI CFG PIO init failure for mac %d "
+				"on TRIO %d, give up\n", mac, trio_index);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index[mac]) |
+			(((unsigned long long)mac) <<
+			TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
+
+#endif
+
+		trio_context->mmio_base_pio_cfg[mac] =
+			iorpc_ioremap(trio_context->fd, offset,
+			(1 << TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT));
+		if (trio_context->mmio_base_pio_cfg[mac] == NULL) {
+			pr_err("PCI: PIO map failure for mac %d on TRIO %d\n",
+				mac, trio_index);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		/*
+		 * Initialize the PCIe interrupts.
+		 */
+		if (tile_init_irqs(controller)) {
+			pr_err("PCI: IRQs init failure for mac %d on TRIO %d\n",
+				mac, trio_index);
+
+			continue;
+		}
+
+		INIT_LIST_HEAD(&resources);
+		pci_add_resource(&resources, &iomem_resource);
+		bus = pci_scan_root_bus(NULL, 0, controller->ops,
+					controller, &resources);
+		controller->root_bus = bus;
+		controller->last_busno = bus->subordinate;
+
+	}
+
+	/* Do machine dependent PCI interrupt routing */
+	pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
+
+	/*
+	 * This comes from the generic Linux PCI driver.
+	 *
+	 * It allocates all of the resources (I/O memory, etc)
+	 * associated with the devices read in above.
+	 */
+
+	pci_assign_unassigned_resources();
+
+	/* Record the I/O resources in the PCI controller structure. */
+	for (i = 0; i < num_rc_controllers; i++) {
+		struct pci_controller *controller = &pci_controllers[i];
+		gxio_trio_context_t *trio_context = controller->trio;
+		struct pci_bus *root_bus = pci_controllers[i].root_bus;
+		struct pci_bus *next_bus;
+		uint32_t bus_address_hi;
+		struct pci_dev *dev;
+		int ret;
+		int j;
+
+		/*
+		 * Skip controllers that are not properly initialized or
+		 * have down links.
+		 */
+		if (root_bus == NULL)
+			continue;
+
+		/* Configure the max_payload_size values for this domain. */
+		fixup_read_and_payload_sizes(controller);
+
+		list_for_each_entry(dev, &root_bus->devices, bus_list) {
+			/* Find the PCI host controller, ie. the 1st bridge. */
+			if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+				(PCI_SLOT(dev->devfn) == 0)) {
+				next_bus = dev->subordinate;
+				pci_controllers[i].mem_resources[0] =
+					*next_bus->resource[0];
+				pci_controllers[i].mem_resources[1] =
+					 *next_bus->resource[1];
+				pci_controllers[i].mem_resources[2] =
+					 *next_bus->resource[2];
+
+				break;
+			}
+		}
+
+		if (pci_controllers[i].mem_resources[1].flags & IORESOURCE_MEM)
+			bus_address_hi =
+				pci_controllers[i].mem_resources[1].start >> 32;
+		else if (pci_controllers[i].mem_resources[2].flags & IORESOURCE_PREFETCH)
+			bus_address_hi =
+				pci_controllers[i].mem_resources[2].start >> 32;
+		else {
+			/* This is unlikely. */
+			pr_err("PCI: no memory resources on TRIO %d mac %d\n",
+				controller->trio_index, controller->mac);
+			continue;
+		}
+
+		/*
+		 * We always assign 32-bit PCI bus BAR ranges.
+		 */
+		BUG_ON(bus_address_hi != 0);
+
+		/*
+		 * Alloc a PIO region for PCI memory access for each RC port.
+		 */
+		ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
+		if (ret < 0) {
+			pr_err("PCI: MEM PIO alloc failure on TRIO %d mac %d, "
+				"give up\n", controller->trio_index,
+				controller->mac);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		controller->pio_mem_index = ret;
+
+		/*
+		 * For PIO MEM, the bus_address_hi parameter is hard-coded 0
+		 * because we always assign 32-bit PCI bus BAR ranges.
+		 */
+		ret = gxio_trio_init_pio_region_aux(trio_context,
+						    controller->pio_mem_index,
+						    controller->mac,
+						    bus_address_hi,
+						    0);
+		if (ret < 0) {
+			pr_err("PCI: MEM PIO init failure on TRIO %d mac %d, "
+				"give up\n", controller->trio_index,
+				controller->mac);
+
+			/* TBD: cleanup ... */
+
+			continue;
+		}
+
+		/*
+		 * Configure a Mem-Map region for each memory controller so
+		 * that Linux can map all of its PA space to the PCI bus.
+		 * Use the IOMMU to handle hash-for-home memory.
+		 */
+		for_each_online_node(j) {
+			unsigned long start_pfn = node_start_pfn[j];
+			unsigned long end_pfn = node_end_pfn[j];
+			unsigned long nr_pages = end_pfn - start_pfn;
+
+			ret = gxio_trio_alloc_memory_maps(trio_context, 1, 0,
+							  0);
+			if (ret < 0) {
+				pr_err("PCI: Mem-Map alloc failure on TRIO %d "
+					"mac %d for MC %d, give up\n",
+					controller->trio_index,
+					controller->mac, j);
+
+				/* TBD: cleanup ... */
+
+				goto alloc_mem_map_failed;
+			}
+
+			controller->mem_maps[j] = ret;
+
+			/*
+			 * Initialize the Mem-Map and the I/O MMU so that all
+			 * the physical memory can be accessed by the endpoint
+			 * devices. The base bus address is set to the base CPA
+			 * of this memory controller, so is the base VA. The
+			 * I/O MMU table essentially translates the CPA to
+			 * the real PA.
+			 */
+			ret = gxio_trio_init_memory_map_mmu_aux(trio_context,
+				controller->mem_maps[j],
+				start_pfn << PAGE_SHIFT,
+				nr_pages << PAGE_SHIFT,
+				trio_context->asid,
+				controller->mac,
+				start_pfn << PAGE_SHIFT,
+				j,
+				GXIO_TRIO_ORDER_MODE_UNORDERED);
+			if (ret < 0) {
+				pr_err("PCI: Mem-Map init failure on TRIO %d "
+					"mac %d for MC %d, give up\n",
+					controller->trio_index,
+					controller->mac, j);
+
+				/* TBD: cleanup ... */
+
+				goto alloc_mem_map_failed;
+			}
+
+			continue;
+
+alloc_mem_map_failed:
+			break;
+		}
+
+	}
+
+	return 0;
+}
+subsys_initcall(pcibios_init);
+
+/*
+ * No bus fixups needed.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	/* Nothing needs to be done. */
+}
+
+/*
+ * This can be called from the generic PCI layer, but doesn't need to
+ * do anything.
+ */
+char __devinit *pcibios_setup(char *str)
+{
+	if (!strcmp(str, "off")) {
+		pci_probe = 0;
+		return NULL;
+	}
+	return str;
+}
+
+/*
+ * This is called from the generic Linux layer.
+ */
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ * Enable memory address decoding, as appropriate, for the
+ * device described by the 'dev' struct. The I/O decoding
+ * is disabled, though the TILE-Gx supports I/O addressing.
+ *
+ * This is called from the generic PCI layer, and can be called
+ * for bridges or endpoints.
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	return pci_enable_resources(dev, mask);
+}
+
+/* Map a PCI MMIO bus address into VA space. */
+void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
+{
+	struct pci_controller *controller = NULL;
+	resource_size_t bar_start;
+	resource_size_t bar_end;
+	resource_size_t offset;
+	resource_size_t start;
+	resource_size_t end;
+	int trio_fd;
+	int i, j;
+
+	start = phys_addr;
+	end = phys_addr + size - 1;
+
+	/*
+	 * In the following, each PCI controller's mem_resources[1]
+	 * represents its (non-prefetchable) PCI memory resource and
+	 * mem_resources[2] refers to its prefetchable PCI memory resource.
+	 * By searching phys_addr in each controller's mem_resources[], we can
+	 * determine the controller that should accept the PCI memory access.
+	 */
+
+	for (i = 0; i < num_rc_controllers; i++) {
+		/*
+		 * Skip controllers that are not properly initialized or
+		 * have down links.
+		 */
+		if (pci_controllers[i].root_bus == NULL)
+			continue;
+
+		for (j = 1; j < 3; j++) {
+			bar_start =
+				pci_controllers[i].mem_resources[j].start;
+			bar_end =
+				pci_controllers[i].mem_resources[j].end;
+
+			if ((start >= bar_start) && (end <= bar_end)) {
+
+				controller = &pci_controllers[i];
+
+				goto got_it;
+			}
+		}
+	}
+
+	if (controller == NULL)
+		return NULL;
+
+got_it:
+	trio_fd = controller->trio->fd;
+
+	offset = HV_TRIO_PIO_OFFSET(controller->pio_mem_index) + phys_addr;
+
+	/*
+	 * We need to keep the PCI bus address's in-page offset in the VA.
+	 */
+	return iorpc_ioremap(trio_fd, offset, size) +
+					(phys_addr & (PAGE_SIZE - 1));
+}
+EXPORT_SYMBOL(ioremap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+
+/****************************************************************
+ *
+ * Tile PCI config space read/write routines
+ *
+ ****************************************************************/
+
+/*
+ * These are the normal read and write ops
+ * These are expanded with macros from  pci_bus_read_config_byte() etc.
+ *
+ * devfn is the combined PCI device & function.
+ *
+ * offset is in bytes, from the start of config space for the
+ * specified bus & device.
+ */
+
+static int __devinit tile_cfg_read(struct pci_bus *bus,
+				   unsigned int devfn,
+				   int offset,
+				   int size,
+				   u32 *val)
+{
+	struct pci_controller *controller = bus->sysdata;
+	gxio_trio_context_t *trio_context = controller->trio;
+	int busnum = bus->number & 0xff;
+	int device = PCI_SLOT(devfn);
+	int function = PCI_FUNC(devfn);
+	int config_type = 1;
+	TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t cfg_addr;
+	void *mmio_addr;
+
+	/*
+	 * Map all accesses to the local device (bus == 0) into the
+	 * MMIO space of the MAC. Accesses to the downstream devices
+	 * go to the PIO space.
+	 */
+	if (busnum == 0) {
+		if (device == 0) {
+			/*
+			 * This is the internal downstream P2P bridge,
+			 * access directly.
+			 */
+			unsigned int reg_offset;
+
+			reg_offset = ((offset & 0xFFF) <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+				(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED
+				<< TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+				(controller->mac <<
+					TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+			mmio_addr = trio_context->mmio_base_mac + reg_offset;
+
+			goto valid_device;
+
+		} else {
+			/*
+			 * We fake an empty device for (device > 0),
+			 * since there is only one device on bus 0.
+			 */
+			goto invalid_device;
+		}
+	}
+
+	/*
+	 * Accesses to the directly attached device (bus == 1) have to be
+	 * sent as type-0 configs.
+	 */
+
+	if (busnum == 1) {
+		/*
+		 * There is only one device off of our built-in P2P bridge.
+		 */
+		if (device != 0)
+			goto invalid_device;
+
+		config_type = 0;
+	}
+
+	cfg_addr.word = 0;
+	cfg_addr.reg_addr = (offset & 0xFFF);
+	cfg_addr.fn = function;
+	cfg_addr.dev = device;
+	cfg_addr.bus = busnum;
+	cfg_addr.type = config_type;
+
+	/*
+	 * Note that we don't set the mac field in cfg_addr because the
+	 * mapping is per port.
+	 */
+
+	mmio_addr = trio_context->mmio_base_pio_cfg[controller->mac] +
+			cfg_addr.word;
+
+valid_device:
+
+	switch (size) {
+	case 4:
+		*val = __gxio_mmio_read32(mmio_addr);
+		break;
+
+	case 2:
+		*val = __gxio_mmio_read16(mmio_addr);
+		break;
+
+	case 1:
+		*val = __gxio_mmio_read8(mmio_addr);
+		break;
+
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	TRACE_CFG_RD(size, *val, busnum, device, function, offset);
+
+	return 0;
+
+invalid_device:
+
+	switch (size) {
+	case 4:
+		*val = 0xFFFFFFFF;
+		break;
+
+	case 2:
+		*val = 0xFFFF;
+		break;
+
+	case 1:
+		*val = 0xFF;
+		break;
+
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	return 0;
+}
+
+
+/*
+ * See tile_cfg_read() for relevent comments.
+ * Note that "val" is the value to write, not a pointer to that value.
+ */
+static int __devinit tile_cfg_write(struct pci_bus *bus,
+				    unsigned int devfn,
+				    int offset,
+				    int size,
+				    u32 val)
+{
+	struct pci_controller *controller = bus->sysdata;
+	gxio_trio_context_t *trio_context = controller->trio;
+	int busnum = bus->number & 0xff;
+	int device = PCI_SLOT(devfn);
+	int function = PCI_FUNC(devfn);
+	int config_type = 1;
+	TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t cfg_addr;
+	void *mmio_addr;
+	u32 val_32 = (u32)val;
+	u16 val_16 = (u16)val;
+	u8 val_8 = (u8)val;
+
+	/*
+	 * Map all accesses to the local device (bus == 0) into the
+	 * MMIO space of the MAC. Accesses to the downstream devices
+	 * go to the PIO space.
+	 */
+	if (busnum == 0) {
+		if (device == 0) {
+			/*
+			 * This is the internal downstream P2P bridge,
+			 * access directly.
+			 */
+			unsigned int reg_offset;
+
+			reg_offset = ((offset & 0xFFF) <<
+				TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+				(TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED
+				<< TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+				(controller->mac <<
+					TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+			mmio_addr = trio_context->mmio_base_mac + reg_offset;
+
+			goto valid_device;
+
+		} else {
+			/*
+			 * We fake an empty device for (device > 0),
+			 * since there is only one device on bus 0.
+			 */
+			goto invalid_device;
+		}
+	}
+
+	/*
+	 * Accesses to the directly attached device (bus == 1) have to be
+	 * sent as type-0 configs.
+	 */
+
+	if (busnum == 1) {
+		/*
+		 * There is only one device off of our built-in P2P bridge.
+		 */
+		if (device != 0)
+			goto invalid_device;
+
+		config_type = 0;
+	}
+
+	cfg_addr.word = 0;
+	cfg_addr.reg_addr = (offset & 0xFFF);
+	cfg_addr.fn = function;
+	cfg_addr.dev = device;
+	cfg_addr.bus = busnum;
+	cfg_addr.type = config_type;
+
+	/*
+	 * Note that we don't set the mac field in cfg_addr because the
+	 * mapping is per port.
+	 */
+
+	mmio_addr = trio_context->mmio_base_pio_cfg[controller->mac] +
+			cfg_addr.word;
+
+valid_device:
+
+	switch (size) {
+	case 4:
+		__gxio_mmio_write32(mmio_addr, val_32);
+		TRACE_CFG_WR(size, val_32, busnum, device, function, offset);
+		break;
+
+	case 2:
+		__gxio_mmio_write16(mmio_addr, val_16);
+		TRACE_CFG_WR(size, val_16, busnum, device, function, offset);
+		break;
+
+	case 1:
+		__gxio_mmio_write8(mmio_addr, val_8);
+		TRACE_CFG_WR(size, val_8, busnum, device, function, offset);
+		break;
+
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+invalid_device:
+
+	return 0;
+}
+
+
+static struct pci_ops tile_cfg_ops = {
+	.read =         tile_cfg_read,
+	.write =        tile_cfg_write,
+};
+
+
+/*
+ * MSI support starts here.
+ */
+static unsigned int
+tilegx_msi_startup(struct irq_data *d)
+{
+	if (d->msi_desc)
+		unmask_msi_irq(d);
+
+	return 0;
+}
+
+static void
+tilegx_msi_ack(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_EVENT_RESET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_msi_mask(struct irq_data *d)
+{
+	mask_msi_irq(d);
+	__insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_msi_unmask(struct irq_data *d)
+{
+	__insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq);
+	unmask_msi_irq(d);
+}
+
+static struct irq_chip tilegx_msi_chip = {
+	.name			= "tilegx_msi",
+	.irq_startup		= tilegx_msi_startup,
+	.irq_ack		= tilegx_msi_ack,
+	.irq_mask		= tilegx_msi_mask,
+	.irq_unmask		= tilegx_msi_unmask,
+
+	/* TBD: support set_affinity. */
+};
+
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+	struct pci_controller *controller;
+	gxio_trio_context_t *trio_context;
+	struct msi_msg msg;
+	int default_irq;
+	uint64_t mem_map_base;
+	uint64_t mem_map_limit;
+	u64 msi_addr;
+	int mem_map;
+	int cpu;
+	int irq;
+	int ret;
+
+	irq = create_irq();
+	if (irq < 0)
+		return irq;
+
+	/*
+	 * Since we use a 64-bit Mem-Map to accept the MSI write, we fail
+	 * devices that are not capable of generating a 64-bit message address.
+	 * These devices will fall back to using the legacy interrupts.
+	 * Most PCIe endpoint devices do support 64-bit message addressing.
+	 */
+	if (desc->msi_attrib.is_64 == 0) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			"64-bit MSI message address not supported, "
+			"falling back to legacy interrupts.\n");
+
+		ret = -ENOMEM;
+		goto is_64_failure;
+	}
+
+	default_irq = desc->msi_attrib.default_irq;
+	controller = irq_get_handler_data(default_irq);
+
+	BUG_ON(!controller);
+
+	trio_context = controller->trio;
+
+	/*
+	 * Allocate the Mem-Map that will accept the MSI write and
+	 * trigger the TILE-side interrupts.
+	 */
+	mem_map = gxio_trio_alloc_memory_maps(trio_context, 1, 0, 0);
+	if (mem_map < 0) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			"%s Mem-Map alloc failure. "
+			"Failed to initialize MSI interrupts. "
+			"Falling back to legacy interrupts.\n",
+			desc->msi_attrib.is_msix ? "MSI-X" : "MSI");
+
+		ret = -ENOMEM;
+		goto msi_mem_map_alloc_failure;
+	}
+
+	/* We try to distribute different IRQs to different tiles. */
+	cpu = tile_irq_cpu(irq);
+
+	/*
+	 * Now call up to the HV to configure the Mem-Map interrupt and
+	 * set up the IPI binding.
+	 */
+	mem_map_base = MEM_MAP_INTR_REGIONS_BASE +
+		mem_map * MEM_MAP_INTR_REGION_SIZE;
+	mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1;
+
+	ret = gxio_trio_config_msi_intr(trio_context, cpu_x(cpu), cpu_y(cpu),
+					KERNEL_PL, irq, controller->mac,
+					mem_map, mem_map_base, mem_map_limit,
+					trio_context->asid);
+	if (ret < 0) {
+		dev_printk(KERN_INFO, &pdev->dev, "HV MSI config failed.\n");
+
+		goto hv_msi_config_failure;
+	}
+
+	irq_set_msi_desc(irq, desc);
+
+	msi_addr = mem_map_base + TRIO_MAP_MEM_REG_INT3 - TRIO_MAP_MEM_REG_INT0;
+
+	msg.address_hi = msi_addr >> 32;
+	msg.address_lo = msi_addr & 0xffffffff;
+
+	msg.data = mem_map;
+
+	write_msi_msg(irq, &msg);
+	irq_set_chip_and_handler(irq, &tilegx_msi_chip, handle_level_irq);
+	irq_set_handler_data(irq, controller);
+
+	return 0;
+
+hv_msi_config_failure:
+	/* Free mem-map */
+msi_mem_map_alloc_failure:
+is_64_failure:
+	destroy_irq(irq);
+	return ret;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	destroy_irq(irq);
+}
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 445c220..a96ced3 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -1327,6 +1327,7 @@ void __init setup_arch(char **cmdline_p)
 
 
 #ifdef CONFIG_PCI
+#if !defined (__tilegx__)
 	/*
 	 * Initialize the PCI structures.  This is done before memory
 	 * setup so that we know whether or not a pci_reserve region
@@ -1334,6 +1335,7 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	if (tile_pci_init() == 0)
 		pci_reserve_mb = 0;
+#endif
 
 	/* PCI systems reserve a region just below 4GB for mapping iomem. */
 	pci_reserve_end_pfn  = (1 << (32 - PAGE_SHIFT));
@@ -1362,6 +1364,10 @@ void __init setup_arch(char **cmdline_p)
 	setup_cpu(1);
 	setup_clock();
 	load_hv_initrd();
+
+#if defined(CONFIG_PCI) && defined (__tilegx__)
+	tile_pci_init();
+#endif
 }
 
 
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
index 345edfe..de0de0c 100644
--- a/arch/tile/mm/pgtable.c
+++ b/arch/tile/mm/pgtable.c
@@ -575,13 +575,6 @@ void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
 }
 EXPORT_SYMBOL(ioremap_prot);
 
-/* Map a PCI MMIO bus address into VA space. */
-void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
-{
-	panic("ioremap for PCI MMIO is not supported");
-}
-EXPORT_SYMBOL(ioremap);
-
 /* Unmap an MMIO VA mapping. */
 void iounmap(volatile void __iomem *addr_in)
 {
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 4bf7102..1e7154b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2143,9 +2143,9 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB,
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
 			quirk_unhide_mch_dev6);
 
-#ifdef CONFIG_TILE
+#ifdef CONFIG_TILEPRO
 /*
- * The Tilera TILEmpower platform needs to set the link speed
+ * The Tilera TILEmpower tilepro platform needs to set the link speed
  * to 2.5GT(Giga-Transfers)/s (Gen 1). The default link speed
  * setting is 5GT/s (Gen 2). 0x98 is the Link Control2 PCIe
  * capability register of the PEX8624 PCIe switch. The switch
@@ -2160,7 +2160,7 @@ static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
 	}
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
-#endif /* CONFIG_TILE */
+#endif /* CONFIG_TILEPRO */
 
 #ifdef CONFIG_PCI_MSI
 /* Some chipsets do not support MSI. We cannot easily rely on setting
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/2] arch/tile: tilegx PCI root complex support
  2012-05-08 21:10           ` [PATCH v2 2/2] arch/tile: tilegx PCI root complex support Chris Metcalf
@ 2012-05-09 16:58             ` Michael S. Tsirkin
  0 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-05-09 16:58 UTC (permalink / raw)
  To: Chris Metcalf
  Cc: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Myron Stowe, Arnd Bergmann, Jiri Kosina, Joe Perches,
	David Howells <dhowells@redhat.com> Jesper Juhl

On Tue, May 08, 2012 at 05:10:17PM -0400, Chris Metcalf wrote:
> +extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);

Please don't put this here. asm-generic/pci_iomap.h already has
a declaration.

-- 
MST

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-04-07 21:10 ` [PATCH 3/3] arch/tile: tilegx PCI root complex support Chris Metcalf
  2012-04-09 13:59   ` Arnd Bergmann
  2012-04-10  0:01   ` [PATCH 3/3] " Bjorn Helgaas
@ 2012-06-19 19:50   ` Geert Uytterhoeven
  2012-06-19 20:07     ` Yinghai Lu
  2 siblings, 1 reply; 19+ messages in thread
From: Geert Uytterhoeven @ 2012-06-19 19:50 UTC (permalink / raw)
  To: Chris Metcalf, Yinghai Lu
  Cc: linux-kernel, linux-pci, Bjorn Helgaas, Jesse Barnes,
	Michael S. Tsirkin, Myron Stowe, Arnd Bergmann, Jiri Kosina,
	Joe Perches, David Howells

Hi Chris,

On Sat, Apr 7, 2012 at 11:10 PM, Chris Metcalf <cmetcalf@tilera.com> wrote:
> This change implements PCIe root complex support for tilegx using
> the kernel support layer for accessing the TRIO hardware shim.

> --- /dev/null
> +++ b/arch/tile/kernel/pci_gx.c

> +               bus = pci_scan_bus(0, controller->ops, controller);
> +               controller->root_bus = bus;
> +               controller->last_busno = bus->subordinate;

As of commit 3527ed81ca01bbaf09df952e68528377a9cd092f
("PCI: remove secondary/subordinate in struct pci_bus") in linux-next, the
"subordinate" field no longer exists:

http://kisskb.ellerman.id.au/kisskb/buildresult/6546355/
arch/tile/kernel/pci_gx.c:852:31: error: 'struct pci_bus' has no
member named 'subordinate'
make[3]: *** [arch/tile/kernel/pci_gx.o] Error 1

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-06-19 19:50   ` Geert Uytterhoeven
@ 2012-06-19 20:07     ` Yinghai Lu
  2012-06-19 20:40       ` Chris Metcalf
  0 siblings, 1 reply; 19+ messages in thread
From: Yinghai Lu @ 2012-06-19 20:07 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Chris Metcalf, linux-kernel, linux-pci, Bjorn Helgaas,
	Jesse Barnes, Michael S. Tsirkin, Myron Stowe, Arnd Bergmann,
	Jiri Kosina, Joe Perches, David Howells

On Tue, Jun 19, 2012 at 12:50 PM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> Hi Chris,
>
> On Sat, Apr 7, 2012 at 11:10 PM, Chris Metcalf <cmetcalf@tilera.com> wrote:
>> This change implements PCIe root complex support for tilegx using
>> the kernel support layer for accessing the TRIO hardware shim.
>
>> --- /dev/null
>> +++ b/arch/tile/kernel/pci_gx.c
>
>> +               bus = pci_scan_bus(0, controller->ops, controller);
>> +               controller->root_bus = bus;
>> +               controller->last_busno = bus->subordinate;
>
> As of commit 3527ed81ca01bbaf09df952e68528377a9cd092f
> ("PCI: remove secondary/subordinate in struct pci_bus") in linux-next, the
> "subordinate" field no longer exists:
>
> http://kisskb.ellerman.id.au/kisskb/buildresult/6546355/
> arch/tile/kernel/pci_gx.c:852:31: error: 'struct pci_bus' has no
> member named 'subordinate'
> make[3]: *** [arch/tile/kernel/pci_gx.o] Error 1

could changed to be
                   contoller->last_busno = bus->busn.end;

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/3] arch/tile: tilegx PCI root complex support
  2012-06-19 20:07     ` Yinghai Lu
@ 2012-06-19 20:40       ` Chris Metcalf
  0 siblings, 0 replies; 19+ messages in thread
From: Chris Metcalf @ 2012-06-19 20:40 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Geert Uytterhoeven, linux-kernel, linux-pci, Bjorn Helgaas,
	Jesse Barnes, Michael S. Tsirkin, Myron Stowe, Arnd Bergmann,
	Jiri Kosina, Joe Perches, David Howells

On 6/19/2012 4:07 PM, Yinghai Lu wrote:
> On Tue, Jun 19, 2012 at 12:50 PM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
>> Hi Chris,
>>
>> On Sat, Apr 7, 2012 at 11:10 PM, Chris Metcalf <cmetcalf@tilera.com> wrote:
>>> This change implements PCIe root complex support for tilegx using
>>> the kernel support layer for accessing the TRIO hardware shim.
>>> --- /dev/null
>>> +++ b/arch/tile/kernel/pci_gx.c
>>> +               bus = pci_scan_bus(0, controller->ops, controller);
>>> +               controller->root_bus = bus;
>>> +               controller->last_busno = bus->subordinate;
>> As of commit 3527ed81ca01bbaf09df952e68528377a9cd092f
>> ("PCI: remove secondary/subordinate in struct pci_bus") in linux-next, the
>> "subordinate" field no longer exists:
>>
>> http://kisskb.ellerman.id.au/kisskb/buildresult/6546355/
>> arch/tile/kernel/pci_gx.c:852:31: error: 'struct pci_bus' has no
>> member named 'subordinate'
>> make[3]: *** [arch/tile/kernel/pci_gx.o] Error 1
> could changed to be
>                    contoller->last_busno = bus->busn.end;

Yes, I saw this build failure in the linux-next logs, but I'm not sure what
to do about it.  I can't adopt Yinghai's solution in my tree since my tree
is based off of Linus's tree which doesn't have "bus->busn".  I suppose I
could publish two trees to linux-next, one based off of Bjorn's "pci" tree
(I assume) and one with all the non-PCI arch/tile stuff (my current
linux-next tree).

I admit I was lazily assuming I would just fix this once the trees collided
during the 3.6 merge window :-)

-- 
Chris Metcalf, Tilera Corp.
http://www.tilera.com


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-06-19 20:40 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-07 20:53 [PATCH 0/3] arch/tile: provide PCIe support for tilegx Chris Metcalf
2012-04-07 19:58 ` [PATCH 2/3] arch/tile: mark TILEGX as not EXPERIMENTAL Chris Metcalf
2012-04-07 20:53 ` [PATCH 1/3] arch/tile: provide kernel support for the tilegx TRIO shim Chris Metcalf
2012-04-07 23:39   ` Jesper Juhl
2012-04-08  0:21     ` Chris Metcalf
2012-04-07 21:10 ` [PATCH 3/3] arch/tile: tilegx PCI root complex support Chris Metcalf
2012-04-09 13:59   ` Arnd Bergmann
2012-04-09 21:38     ` Chris Metcalf
2012-04-10  9:14       ` Arnd Bergmann
2012-05-08 20:53         ` [PATCH v2 0/2] arch/tile: " Chris Metcalf
2012-05-08 20:53           ` [PATCH v2 1/2] arch/tile: provide kernel support for the tilegx TRIO shim Chris Metcalf
2012-05-08 21:10           ` [PATCH v2 2/2] arch/tile: tilegx PCI root complex support Chris Metcalf
2012-05-09 16:58             ` Michael S. Tsirkin
2012-04-10  0:01   ` [PATCH 3/3] " Bjorn Helgaas
2012-04-10  9:15     ` Arnd Bergmann
2012-04-15 23:09     ` Chris Metcalf
2012-06-19 19:50   ` Geert Uytterhoeven
2012-06-19 20:07     ` Yinghai Lu
2012-06-19 20:40       ` Chris Metcalf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).