v4.19.13 snapshot.
diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile
new file mode 100644
index 0000000..9433605
--- /dev/null
+++ b/arch/arm/plat-orion/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux kernel.
+#
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+
+orion-gpio-$(CONFIG_GPIOLIB)      += gpio.o
+obj-$(CONFIG_PLAT_ORION_LEGACY)   += irq.o pcie.o time.o common.o mpp.o
+obj-$(CONFIG_PLAT_ORION_LEGACY)   += $(orion-gpio-y)
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
new file mode 100644
index 0000000..a2399fd
--- /dev/null
+++ b/arch/arm/plat-orion/common.c
@@ -0,0 +1,857 @@
+/*
+ * arch/arm/plat-orion/common.c
+ *
+ * Marvell Orion SoC common setup code used by multiple mach-/common.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/serial_8250.h>
+#include <linux/ata_platform.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/mv643xx_i2c.h>
+#include <net/dsa.h>
+#include <linux/platform_data/dma-mv_xor.h>
+#include <linux/platform_data/usb-ehci-orion.h>
+#include <plat/common.h>
+#include <linux/phy.h>
+
+/* Create a clkdev entry for a given device/clk */
+void __init orion_clkdev_add(const char *con_id, const char *dev_id,
+			     struct clk *clk)
+{
+	clkdev_create(clk, con_id, "%s", dev_id);
+}
+
+/* Create clkdev entries for all orion platforms except kirkwood.
+   Kirkwood has gated clocks for some of its peripherals, so creates
+   its own clkdev entries. For all the other orion devices, create
+   clkdev entries to the tclk. */
+void __init orion_clkdev_init(struct clk *tclk)
+{
+	orion_clkdev_add(NULL, "orion_spi.0", tclk);
+	orion_clkdev_add(NULL, "orion_spi.1", tclk);
+	orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", tclk);
+	orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", tclk);
+	orion_clkdev_add(NULL, MV643XX_ETH_NAME ".2", tclk);
+	orion_clkdev_add(NULL, MV643XX_ETH_NAME ".3", tclk);
+	orion_clkdev_add(NULL, "orion_wdt", tclk);
+	orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", tclk);
+}
+
+/* Fill in the resources structure and link it into the platform
+   device structure. There is always a memory region, and nearly
+   always an interrupt.*/
+static void fill_resources(struct platform_device *device,
+			   struct resource *resources,
+			   resource_size_t mapbase,
+			   resource_size_t size)
+{
+	device->resource = resources;
+	device->num_resources = 1;
+	resources[0].flags = IORESOURCE_MEM;
+	resources[0].start = mapbase;
+	resources[0].end = mapbase + size;
+}
+
+static void fill_resources_irq(struct platform_device *device,
+			       struct resource *resources,
+			       resource_size_t mapbase,
+			       resource_size_t size,
+			       unsigned int irq)
+{
+	fill_resources(device, resources, mapbase, size);
+
+	device->num_resources++;
+	resources[1].flags = IORESOURCE_IRQ;
+	resources[1].start = irq;
+	resources[1].end = irq;
+}
+
+/*****************************************************************************
+ * UART
+ ****************************************************************************/
+static unsigned long __init uart_get_clk_rate(struct clk *clk)
+{
+	clk_prepare_enable(clk);
+	return clk_get_rate(clk);
+}
+
+static void __init uart_complete(
+	struct platform_device *orion_uart,
+	struct plat_serial8250_port *data,
+	struct resource *resources,
+	void __iomem *membase,
+	resource_size_t mapbase,
+	unsigned int irq,
+	struct clk *clk)
+{
+	data->mapbase = mapbase;
+	data->membase = membase;
+	data->irq = irq;
+	data->uartclk = uart_get_clk_rate(clk);
+	orion_uart->dev.platform_data = data;
+
+	fill_resources_irq(orion_uart, resources, mapbase, 0xff, irq);
+	platform_device_register(orion_uart);
+}
+
+/*****************************************************************************
+ * UART0
+ ****************************************************************************/
+static struct plat_serial8250_port orion_uart0_data[] = {
+	{
+		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	}, {
+	},
+};
+
+static struct resource orion_uart0_resources[2];
+
+static struct platform_device orion_uart0 = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+};
+
+void __init orion_uart0_init(void __iomem *membase,
+			     resource_size_t mapbase,
+			     unsigned int irq,
+			     struct clk *clk)
+{
+	uart_complete(&orion_uart0, orion_uart0_data, orion_uart0_resources,
+		      membase, mapbase, irq, clk);
+}
+
+/*****************************************************************************
+ * UART1
+ ****************************************************************************/
+static struct plat_serial8250_port orion_uart1_data[] = {
+	{
+		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	}, {
+	},
+};
+
+static struct resource orion_uart1_resources[2];
+
+static struct platform_device orion_uart1 = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM1,
+};
+
+void __init orion_uart1_init(void __iomem *membase,
+			     resource_size_t mapbase,
+			     unsigned int irq,
+			     struct clk *clk)
+{
+	uart_complete(&orion_uart1, orion_uart1_data, orion_uart1_resources,
+		      membase, mapbase, irq, clk);
+}
+
+/*****************************************************************************
+ * UART2
+ ****************************************************************************/
+static struct plat_serial8250_port orion_uart2_data[] = {
+	{
+		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	}, {
+	},
+};
+
+static struct resource orion_uart2_resources[2];
+
+static struct platform_device orion_uart2 = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM2,
+};
+
+void __init orion_uart2_init(void __iomem *membase,
+			     resource_size_t mapbase,
+			     unsigned int irq,
+			     struct clk *clk)
+{
+	uart_complete(&orion_uart2, orion_uart2_data, orion_uart2_resources,
+		      membase, mapbase, irq, clk);
+}
+
+/*****************************************************************************
+ * UART3
+ ****************************************************************************/
+static struct plat_serial8250_port orion_uart3_data[] = {
+	{
+		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	}, {
+	},
+};
+
+static struct resource orion_uart3_resources[2];
+
+static struct platform_device orion_uart3 = {
+	.name			= "serial8250",
+	.id			= 3,
+};
+
+void __init orion_uart3_init(void __iomem *membase,
+			     resource_size_t mapbase,
+			     unsigned int irq,
+			     struct clk *clk)
+{
+	uart_complete(&orion_uart3, orion_uart3_data, orion_uart3_resources,
+		      membase, mapbase, irq, clk);
+}
+
+/*****************************************************************************
+ * SoC RTC
+ ****************************************************************************/
+static struct resource orion_rtc_resource[2];
+
+void __init orion_rtc_init(unsigned long mapbase,
+			   unsigned long irq)
+{
+	orion_rtc_resource[0].start = mapbase;
+	orion_rtc_resource[0].end = mapbase + SZ_32 - 1;
+	orion_rtc_resource[0].flags = IORESOURCE_MEM;
+	orion_rtc_resource[1].start = irq;
+	orion_rtc_resource[1].end = irq;
+	orion_rtc_resource[1].flags = IORESOURCE_IRQ;
+
+	platform_device_register_simple("rtc-mv", -1, orion_rtc_resource, 2);
+}
+
+/*****************************************************************************
+ * GE
+ ****************************************************************************/
+static __init void ge_complete(
+	struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
+	struct resource *orion_ge_resource, unsigned long irq,
+	struct platform_device *orion_ge_shared,
+	struct platform_device *orion_ge_mvmdio,
+	struct mv643xx_eth_platform_data *eth_data,
+	struct platform_device *orion_ge)
+{
+	orion_ge_resource->start = irq;
+	orion_ge_resource->end = irq;
+	eth_data->shared = orion_ge_shared;
+	orion_ge->dev.platform_data = eth_data;
+
+	platform_device_register(orion_ge_shared);
+	if (orion_ge_mvmdio)
+		platform_device_register(orion_ge_mvmdio);
+	platform_device_register(orion_ge);
+}
+
+/*****************************************************************************
+ * GE00
+ ****************************************************************************/
+static struct mv643xx_eth_shared_platform_data orion_ge00_shared_data;
+
+static struct resource orion_ge00_shared_resources[] = {
+	{
+		.name	= "ge00 base",
+	},
+};
+
+static struct platform_device orion_ge00_shared = {
+	.name		= MV643XX_ETH_SHARED_NAME,
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &orion_ge00_shared_data,
+	},
+};
+
+static struct resource orion_ge_mvmdio_resources[] = {
+	{
+		.name	= "ge00 mvmdio base",
+	}, {
+		.name	= "ge00 mvmdio err irq",
+	},
+};
+
+static struct platform_device orion_ge_mvmdio = {
+	.name		= "orion-mdio",
+	.id		= -1,
+};
+
+static struct resource orion_ge00_resources[] = {
+	{
+		.name	= "ge00 irq",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device orion_ge00 = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 0,
+	.num_resources	= 1,
+	.resource	= orion_ge00_resources,
+	.dev		= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
+			    unsigned long mapbase,
+			    unsigned long irq,
+			    unsigned long irq_err,
+			    unsigned int tx_csum_limit)
+{
+	fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
+		       mapbase + 0x2000, SZ_16K - 1);
+	fill_resources_irq(&orion_ge_mvmdio, orion_ge_mvmdio_resources,
+			mapbase + 0x2004, 0x84 - 1, irq_err);
+	orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
+	ge_complete(&orion_ge00_shared_data,
+		    orion_ge00_resources, irq, &orion_ge00_shared,
+		    &orion_ge_mvmdio,
+		    eth_data, &orion_ge00);
+}
+
+/*****************************************************************************
+ * GE01
+ ****************************************************************************/
+static struct mv643xx_eth_shared_platform_data orion_ge01_shared_data;
+
+static struct resource orion_ge01_shared_resources[] = {
+	{
+		.name	= "ge01 base",
+	}
+};
+
+static struct platform_device orion_ge01_shared = {
+	.name		= MV643XX_ETH_SHARED_NAME,
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &orion_ge01_shared_data,
+	},
+};
+
+static struct resource orion_ge01_resources[] = {
+	{
+		.name	= "ge01 irq",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device orion_ge01 = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 1,
+	.num_resources	= 1,
+	.resource	= orion_ge01_resources,
+	.dev		= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
+			    unsigned long mapbase,
+			    unsigned long irq,
+			    unsigned int tx_csum_limit)
+{
+	fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
+		       mapbase + 0x2000, SZ_16K - 1);
+	orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
+	ge_complete(&orion_ge01_shared_data,
+		    orion_ge01_resources, irq, &orion_ge01_shared,
+		    NULL,
+		    eth_data, &orion_ge01);
+}
+
+/*****************************************************************************
+ * GE10
+ ****************************************************************************/
+static struct mv643xx_eth_shared_platform_data orion_ge10_shared_data;
+
+static struct resource orion_ge10_shared_resources[] = {
+	{
+		.name	= "ge10 base",
+	}
+};
+
+static struct platform_device orion_ge10_shared = {
+	.name		= MV643XX_ETH_SHARED_NAME,
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &orion_ge10_shared_data,
+	},
+};
+
+static struct resource orion_ge10_resources[] = {
+	{
+		.name	= "ge10 irq",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device orion_ge10 = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 2,
+	.num_resources	= 1,
+	.resource	= orion_ge10_resources,
+	.dev		= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
+			    unsigned long mapbase,
+			    unsigned long irq)
+{
+	fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
+		       mapbase + 0x2000, SZ_16K - 1);
+	ge_complete(&orion_ge10_shared_data,
+		    orion_ge10_resources, irq, &orion_ge10_shared,
+		    NULL,
+		    eth_data, &orion_ge10);
+}
+
+/*****************************************************************************
+ * GE11
+ ****************************************************************************/
+static struct mv643xx_eth_shared_platform_data orion_ge11_shared_data;
+
+static struct resource orion_ge11_shared_resources[] = {
+	{
+		.name	= "ge11 base",
+	},
+};
+
+static struct platform_device orion_ge11_shared = {
+	.name		= MV643XX_ETH_SHARED_NAME,
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &orion_ge11_shared_data,
+	},
+};
+
+static struct resource orion_ge11_resources[] = {
+	{
+		.name	= "ge11 irq",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device orion_ge11 = {
+	.name		= MV643XX_ETH_NAME,
+	.id		= 3,
+	.num_resources	= 1,
+	.resource	= orion_ge11_resources,
+	.dev		= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
+			    unsigned long mapbase,
+			    unsigned long irq)
+{
+	fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
+		       mapbase + 0x2000, SZ_16K - 1);
+	ge_complete(&orion_ge11_shared_data,
+		    orion_ge11_resources, irq, &orion_ge11_shared,
+		    NULL,
+		    eth_data, &orion_ge11);
+}
+
+#ifdef CONFIG_ARCH_ORION5X
+/*****************************************************************************
+ * Ethernet switch
+ ****************************************************************************/
+static __initdata struct mdio_board_info orion_ge00_switch_board_info = {
+	.bus_id   = "orion-mii",
+	.modalias = "mv88e6085",
+};
+
+void __init orion_ge00_switch_init(struct dsa_chip_data *d)
+{
+	unsigned int i;
+
+	if (!IS_BUILTIN(CONFIG_PHYLIB))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(d->port_names); i++) {
+		if (!strcmp(d->port_names[i], "cpu")) {
+			d->netdev[i] = &orion_ge00.dev;
+			break;
+		}
+	}
+
+	orion_ge00_switch_board_info.mdio_addr = d->sw_addr;
+	orion_ge00_switch_board_info.platform_data = d;
+
+	mdiobus_register_board_info(&orion_ge00_switch_board_info, 1);
+}
+#endif
+
+/*****************************************************************************
+ * I2C
+ ****************************************************************************/
+static struct mv64xxx_i2c_pdata orion_i2c_pdata = {
+	.freq_n		= 3,
+	.timeout	= 1000, /* Default timeout of 1 second */
+};
+
+static struct resource orion_i2c_resources[2];
+
+static struct platform_device orion_i2c = {
+	.name		= MV64XXX_I2C_CTLR_NAME,
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &orion_i2c_pdata,
+	},
+};
+
+static struct mv64xxx_i2c_pdata orion_i2c_1_pdata = {
+	.freq_n		= 3,
+	.timeout	= 1000, /* Default timeout of 1 second */
+};
+
+static struct resource orion_i2c_1_resources[2];
+
+static struct platform_device orion_i2c_1 = {
+	.name		= MV64XXX_I2C_CTLR_NAME,
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &orion_i2c_1_pdata,
+	},
+};
+
+void __init orion_i2c_init(unsigned long mapbase,
+			   unsigned long irq,
+			   unsigned long freq_m)
+{
+	orion_i2c_pdata.freq_m = freq_m;
+	fill_resources_irq(&orion_i2c, orion_i2c_resources, mapbase,
+		       SZ_32 - 1, irq);
+	platform_device_register(&orion_i2c);
+}
+
+void __init orion_i2c_1_init(unsigned long mapbase,
+			     unsigned long irq,
+			     unsigned long freq_m)
+{
+	orion_i2c_1_pdata.freq_m = freq_m;
+	fill_resources_irq(&orion_i2c_1, orion_i2c_1_resources, mapbase,
+		       SZ_32 - 1, irq);
+	platform_device_register(&orion_i2c_1);
+}
+
+/*****************************************************************************
+ * SPI
+ ****************************************************************************/
+static struct resource orion_spi_resources;
+
+static struct platform_device orion_spi = {
+	.name		= "orion_spi",
+	.id		= 0,
+};
+
+static struct resource orion_spi_1_resources;
+
+static struct platform_device orion_spi_1 = {
+	.name		= "orion_spi",
+	.id		= 1,
+};
+
+/* Note: The SPI silicon core does have interrupts. However the
+ * current Linux software driver does not use interrupts. */
+
+void __init orion_spi_init(unsigned long mapbase)
+{
+	fill_resources(&orion_spi, &orion_spi_resources,
+		       mapbase, SZ_512 - 1);
+	platform_device_register(&orion_spi);
+}
+
+void __init orion_spi_1_init(unsigned long mapbase)
+{
+	fill_resources(&orion_spi_1, &orion_spi_1_resources,
+		       mapbase, SZ_512 - 1);
+	platform_device_register(&orion_spi_1);
+}
+
+/*****************************************************************************
+ * XOR
+ ****************************************************************************/
+static u64 orion_xor_dmamask = DMA_BIT_MASK(32);
+
+/*****************************************************************************
+ * XOR0
+ ****************************************************************************/
+static struct resource orion_xor0_shared_resources[] = {
+	{
+		.name	= "xor 0 low",
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "xor 0 high",
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name   = "irq channel 0",
+		.flags  = IORESOURCE_IRQ,
+	}, {
+		.name   = "irq channel 1",
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct mv_xor_channel_data orion_xor0_channels_data[2];
+
+static struct mv_xor_platform_data orion_xor0_pdata = {
+	.channels = orion_xor0_channels_data,
+};
+
+static struct platform_device orion_xor0_shared = {
+	.name		= MV_XOR_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(orion_xor0_shared_resources),
+	.resource	= orion_xor0_shared_resources,
+	.dev            = {
+		.dma_mask               = &orion_xor_dmamask,
+		.coherent_dma_mask      = DMA_BIT_MASK(64),
+		.platform_data          = &orion_xor0_pdata,
+	},
+};
+
+void __init orion_xor0_init(unsigned long mapbase_low,
+			    unsigned long mapbase_high,
+			    unsigned long irq_0,
+			    unsigned long irq_1)
+{
+	orion_xor0_shared_resources[0].start = mapbase_low;
+	orion_xor0_shared_resources[0].end = mapbase_low + 0xff;
+	orion_xor0_shared_resources[1].start = mapbase_high;
+	orion_xor0_shared_resources[1].end = mapbase_high + 0xff;
+
+	orion_xor0_shared_resources[2].start = irq_0;
+	orion_xor0_shared_resources[2].end = irq_0;
+	orion_xor0_shared_resources[3].start = irq_1;
+	orion_xor0_shared_resources[3].end = irq_1;
+
+	dma_cap_set(DMA_MEMCPY, orion_xor0_channels_data[0].cap_mask);
+	dma_cap_set(DMA_XOR, orion_xor0_channels_data[0].cap_mask);
+
+	dma_cap_set(DMA_MEMCPY, orion_xor0_channels_data[1].cap_mask);
+	dma_cap_set(DMA_XOR, orion_xor0_channels_data[1].cap_mask);
+
+	platform_device_register(&orion_xor0_shared);
+}
+
+/*****************************************************************************
+ * XOR1
+ ****************************************************************************/
+static struct resource orion_xor1_shared_resources[] = {
+	{
+		.name	= "xor 1 low",
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "xor 1 high",
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name   = "irq channel 0",
+		.flags  = IORESOURCE_IRQ,
+	}, {
+		.name   = "irq channel 1",
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct mv_xor_channel_data orion_xor1_channels_data[2];
+
+static struct mv_xor_platform_data orion_xor1_pdata = {
+	.channels = orion_xor1_channels_data,
+};
+
+static struct platform_device orion_xor1_shared = {
+	.name		= MV_XOR_NAME,
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(orion_xor1_shared_resources),
+	.resource	= orion_xor1_shared_resources,
+	.dev            = {
+		.dma_mask               = &orion_xor_dmamask,
+		.coherent_dma_mask      = DMA_BIT_MASK(64),
+		.platform_data          = &orion_xor1_pdata,
+	},
+};
+
+void __init orion_xor1_init(unsigned long mapbase_low,
+			    unsigned long mapbase_high,
+			    unsigned long irq_0,
+			    unsigned long irq_1)
+{
+	orion_xor1_shared_resources[0].start = mapbase_low;
+	orion_xor1_shared_resources[0].end = mapbase_low + 0xff;
+	orion_xor1_shared_resources[1].start = mapbase_high;
+	orion_xor1_shared_resources[1].end = mapbase_high + 0xff;
+
+	orion_xor1_shared_resources[2].start = irq_0;
+	orion_xor1_shared_resources[2].end = irq_0;
+	orion_xor1_shared_resources[3].start = irq_1;
+	orion_xor1_shared_resources[3].end = irq_1;
+
+	dma_cap_set(DMA_MEMCPY, orion_xor1_channels_data[0].cap_mask);
+	dma_cap_set(DMA_XOR, orion_xor1_channels_data[0].cap_mask);
+
+	dma_cap_set(DMA_MEMCPY, orion_xor1_channels_data[1].cap_mask);
+	dma_cap_set(DMA_XOR, orion_xor1_channels_data[1].cap_mask);
+
+	platform_device_register(&orion_xor1_shared);
+}
+
+/*****************************************************************************
+ * EHCI
+ ****************************************************************************/
+static struct orion_ehci_data orion_ehci_data;
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
+
+
+/*****************************************************************************
+ * EHCI0
+ ****************************************************************************/
+static struct resource orion_ehci_resources[2];
+
+static struct platform_device orion_ehci = {
+	.name		= "orion-ehci",
+	.id		= 0,
+	.dev		= {
+		.dma_mask		= &ehci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &orion_ehci_data,
+	},
+};
+
+void __init orion_ehci_init(unsigned long mapbase,
+			    unsigned long irq,
+			    enum orion_ehci_phy_ver phy_version)
+{
+	orion_ehci_data.phy_version = phy_version;
+	fill_resources_irq(&orion_ehci, orion_ehci_resources, mapbase, SZ_4K - 1,
+		       irq);
+
+	platform_device_register(&orion_ehci);
+}
+
+/*****************************************************************************
+ * EHCI1
+ ****************************************************************************/
+static struct resource orion_ehci_1_resources[2];
+
+static struct platform_device orion_ehci_1 = {
+	.name		= "orion-ehci",
+	.id		= 1,
+	.dev		= {
+		.dma_mask		= &ehci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &orion_ehci_data,
+	},
+};
+
+void __init orion_ehci_1_init(unsigned long mapbase,
+			      unsigned long irq)
+{
+	fill_resources_irq(&orion_ehci_1, orion_ehci_1_resources,
+		       mapbase, SZ_4K - 1, irq);
+
+	platform_device_register(&orion_ehci_1);
+}
+
+/*****************************************************************************
+ * EHCI2
+ ****************************************************************************/
+static struct resource orion_ehci_2_resources[2];
+
+static struct platform_device orion_ehci_2 = {
+	.name		= "orion-ehci",
+	.id		= 2,
+	.dev		= {
+		.dma_mask		= &ehci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &orion_ehci_data,
+	},
+};
+
+void __init orion_ehci_2_init(unsigned long mapbase,
+			      unsigned long irq)
+{
+	fill_resources_irq(&orion_ehci_2, orion_ehci_2_resources,
+		       mapbase, SZ_4K - 1, irq);
+
+	platform_device_register(&orion_ehci_2);
+}
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct resource orion_sata_resources[2] = {
+	{
+		.name	= "sata base",
+	}, {
+		.name	= "sata irq",
+	},
+};
+
+static struct platform_device orion_sata = {
+	.name		= "sata_mv",
+	.id		= 0,
+	.dev		= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init orion_sata_init(struct mv_sata_platform_data *sata_data,
+			    unsigned long mapbase,
+			    unsigned long irq)
+{
+	orion_sata.dev.platform_data = sata_data;
+	fill_resources_irq(&orion_sata, orion_sata_resources,
+		       mapbase, 0x5000 - 1, irq);
+
+	platform_device_register(&orion_sata);
+}
+
+/*****************************************************************************
+ * Cryptographic Engines and Security Accelerator (CESA)
+ ****************************************************************************/
+static struct resource orion_crypto_resources[] = {
+	{
+		.name   = "regs",
+	}, {
+		.name   = "crypto interrupt",
+	}, {
+		.name   = "sram",
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device orion_crypto = {
+	.name           = "mv_crypto",
+	.id             = -1,
+};
+
+void __init orion_crypto_init(unsigned long mapbase,
+			      unsigned long srambase,
+			      unsigned long sram_size,
+			      unsigned long irq)
+{
+	fill_resources_irq(&orion_crypto, orion_crypto_resources,
+		       mapbase, 0xffff, irq);
+	orion_crypto.num_resources = 3;
+	orion_crypto_resources[2].start = srambase;
+	orion_crypto_resources[2].end = srambase + sram_size - 1;
+
+	platform_device_register(&orion_crypto);
+}
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
new file mode 100644
index 0000000..26a531e
--- /dev/null
+++ b/arch/arm/plat-orion/gpio.c
@@ -0,0 +1,623 @@
+/*
+ * arch/arm/plat-orion/gpio.c
+ *
+ * Marvell Orion SoC GPIO handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <plat/orion-gpio.h>
+
+/*
+ * GPIO unit register offsets.
+ */
+#define GPIO_OUT_OFF		0x0000
+#define GPIO_IO_CONF_OFF	0x0004
+#define GPIO_BLINK_EN_OFF	0x0008
+#define GPIO_IN_POL_OFF		0x000c
+#define GPIO_DATA_IN_OFF	0x0010
+#define GPIO_EDGE_CAUSE_OFF	0x0014
+#define GPIO_EDGE_MASK_OFF	0x0018
+#define GPIO_LEVEL_MASK_OFF	0x001c
+
+struct orion_gpio_chip {
+	struct gpio_chip	chip;
+	spinlock_t		lock;
+	void __iomem		*base;
+	unsigned long		valid_input;
+	unsigned long		valid_output;
+	int			mask_offset;
+	int			secondary_irq_base;
+	struct irq_domain       *domain;
+};
+
+static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_OUT_OFF;
+}
+
+static void __iomem *GPIO_IO_CONF(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_IO_CONF_OFF;
+}
+
+static void __iomem *GPIO_BLINK_EN(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_BLINK_EN_OFF;
+}
+
+static void __iomem *GPIO_IN_POL(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_IN_POL_OFF;
+}
+
+static void __iomem *GPIO_DATA_IN(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_DATA_IN_OFF;
+}
+
+static void __iomem *GPIO_EDGE_CAUSE(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_EDGE_CAUSE_OFF;
+}
+
+static void __iomem *GPIO_EDGE_MASK(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + ochip->mask_offset + GPIO_EDGE_MASK_OFF;
+}
+
+static void __iomem *GPIO_LEVEL_MASK(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
+}
+
+
+static struct orion_gpio_chip orion_gpio_chips[2];
+static int orion_gpio_chip_count;
+
+static inline void
+__set_direction(struct orion_gpio_chip *ochip, unsigned pin, int input)
+{
+	u32 u;
+
+	u = readl(GPIO_IO_CONF(ochip));
+	if (input)
+		u |= 1 << pin;
+	else
+		u &= ~(1 << pin);
+	writel(u, GPIO_IO_CONF(ochip));
+}
+
+static void __set_level(struct orion_gpio_chip *ochip, unsigned pin, int high)
+{
+	u32 u;
+
+	u = readl(GPIO_OUT(ochip));
+	if (high)
+		u |= 1 << pin;
+	else
+		u &= ~(1 << pin);
+	writel(u, GPIO_OUT(ochip));
+}
+
+static inline void
+__set_blinking(struct orion_gpio_chip *ochip, unsigned pin, int blink)
+{
+	u32 u;
+
+	u = readl(GPIO_BLINK_EN(ochip));
+	if (blink)
+		u |= 1 << pin;
+	else
+		u &= ~(1 << pin);
+	writel(u, GPIO_BLINK_EN(ochip));
+}
+
+static inline int
+orion_gpio_is_valid(struct orion_gpio_chip *ochip, unsigned pin, int mode)
+{
+	if (pin >= ochip->chip.ngpio)
+		goto err_out;
+
+	if ((mode & GPIO_INPUT_OK) && !test_bit(pin, &ochip->valid_input))
+		goto err_out;
+
+	if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, &ochip->valid_output))
+		goto err_out;
+
+	return 1;
+
+err_out:
+	pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+	return false;
+}
+
+/*
+ * GPIO primitives.
+ */
+static int orion_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	struct orion_gpio_chip *ochip = gpiochip_get_data(chip);
+
+	if (orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK) ||
+	    orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
+{
+	struct orion_gpio_chip *ochip = gpiochip_get_data(chip);
+	unsigned long flags;
+
+	if (!orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK))
+		return -EINVAL;
+
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_direction(ochip, pin, 1);
+	spin_unlock_irqrestore(&ochip->lock, flags);
+
+	return 0;
+}
+
+static int orion_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+	struct orion_gpio_chip *ochip = gpiochip_get_data(chip);
+	int val;
+
+	if (readl(GPIO_IO_CONF(ochip)) & (1 << pin)) {
+		val = readl(GPIO_DATA_IN(ochip)) ^ readl(GPIO_IN_POL(ochip));
+	} else {
+		val = readl(GPIO_OUT(ochip));
+	}
+
+	return (val >> pin) & 1;
+}
+
+static int
+orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int value)
+{
+	struct orion_gpio_chip *ochip = gpiochip_get_data(chip);
+	unsigned long flags;
+
+	if (!orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK))
+		return -EINVAL;
+
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_blinking(ochip, pin, 0);
+	__set_level(ochip, pin, value);
+	__set_direction(ochip, pin, 0);
+	spin_unlock_irqrestore(&ochip->lock, flags);
+
+	return 0;
+}
+
+static void orion_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
+{
+	struct orion_gpio_chip *ochip = gpiochip_get_data(chip);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_level(ochip, pin, value);
+	spin_unlock_irqrestore(&ochip->lock, flags);
+}
+
+static int orion_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+	struct orion_gpio_chip *ochip = gpiochip_get_data(chip);
+
+	return irq_create_mapping(ochip->domain,
+				  ochip->secondary_irq_base + pin);
+}
+
+/*
+ * Orion-specific GPIO API extensions.
+ */
+static struct orion_gpio_chip *orion_gpio_chip_find(int pin)
+{
+	int i;
+
+	for (i = 0; i < orion_gpio_chip_count; i++) {
+		struct orion_gpio_chip *ochip = orion_gpio_chips + i;
+		struct gpio_chip *chip = &ochip->chip;
+
+		if (pin >= chip->base && pin < chip->base + chip->ngpio)
+			return ochip;
+	}
+
+	return NULL;
+}
+
+void __init orion_gpio_set_unused(unsigned pin)
+{
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
+
+	if (ochip == NULL)
+		return;
+
+	pin -= ochip->chip.base;
+
+	/* Configure as output, drive low. */
+	__set_level(ochip, pin, 0);
+	__set_direction(ochip, pin, 0);
+}
+
+void __init orion_gpio_set_valid(unsigned pin, int mode)
+{
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
+
+	if (ochip == NULL)
+		return;
+
+	pin -= ochip->chip.base;
+
+	if (mode == 1)
+		mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
+
+	if (mode & GPIO_INPUT_OK)
+		__set_bit(pin, &ochip->valid_input);
+	else
+		__clear_bit(pin, &ochip->valid_input);
+
+	if (mode & GPIO_OUTPUT_OK)
+		__set_bit(pin, &ochip->valid_output);
+	else
+		__clear_bit(pin, &ochip->valid_output);
+}
+
+void orion_gpio_set_blink(unsigned pin, int blink)
+{
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
+	unsigned long flags;
+
+	if (ochip == NULL)
+		return;
+
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_level(ochip, pin & 31, 0);
+	__set_blinking(ochip, pin & 31, blink);
+	spin_unlock_irqrestore(&ochip->lock, flags);
+}
+EXPORT_SYMBOL(orion_gpio_set_blink);
+
+#define ORION_BLINK_HALF_PERIOD 100 /* ms */
+
+int orion_gpio_led_blink_set(struct gpio_desc *desc, int state,
+	unsigned long *delay_on, unsigned long *delay_off)
+{
+	unsigned gpio = desc_to_gpio(desc);
+
+	if (delay_on && delay_off && !*delay_on && !*delay_off)
+		*delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
+
+	switch (state) {
+	case GPIO_LED_NO_BLINK_LOW:
+	case GPIO_LED_NO_BLINK_HIGH:
+		orion_gpio_set_blink(gpio, 0);
+		gpio_set_value(gpio, state);
+		break;
+	case GPIO_LED_BLINK:
+		orion_gpio_set_blink(gpio, 1);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(orion_gpio_led_blink_set);
+
+
+/*****************************************************************************
+ * Orion GPIO IRQ
+ *
+ * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same
+ * value of the line or the opposite value.
+ *
+ * Level IRQ handlers: DATA_IN is used directly as cause register.
+ *                     Interrupt are masked by LEVEL_MASK registers.
+ * Edge IRQ handlers:  Change in DATA_IN are latched in EDGE_CAUSE.
+ *                     Interrupt are masked by EDGE_MASK registers.
+ * Both-edge handlers: Similar to regular Edge handlers, but also swaps
+ *                     the polarity to catch the next line transaction.
+ *                     This is a race condition that might not perfectly
+ *                     work on some use cases.
+ *
+ * Every eight GPIO lines are grouped (OR'ed) before going up to main
+ * cause register.
+ *
+ *                    EDGE  cause    mask
+ *        data-in   /--------| |-----| |----\
+ *     -----| |-----                         ---- to main cause reg
+ *           X      \----------------| |----/
+ *        polarity    LEVEL          mask
+ *
+ ****************************************************************************/
+
+static int gpio_irq_set_type(struct irq_data *d, u32 type)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
+	struct orion_gpio_chip *ochip = gc->private;
+	int pin;
+	u32 u;
+
+	pin = d->hwirq - ochip->secondary_irq_base;
+
+	u = readl(GPIO_IO_CONF(ochip)) & (1 << pin);
+	if (!u) {
+		return -EINVAL;
+	}
+
+	type &= IRQ_TYPE_SENSE_MASK;
+	if (type == IRQ_TYPE_NONE)
+		return -EINVAL;
+
+	/* Check if we need to change chip and handler */
+	if (!(ct->type & type))
+		if (irq_setup_alt_chip(d, type))
+			return -EINVAL;
+
+	/*
+	 * Configure interrupt polarity.
+	 */
+	if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) {
+		u = readl(GPIO_IN_POL(ochip));
+		u &= ~(1 << pin);
+		writel(u, GPIO_IN_POL(ochip));
+	} else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) {
+		u = readl(GPIO_IN_POL(ochip));
+		u |= 1 << pin;
+		writel(u, GPIO_IN_POL(ochip));
+	} else if (type == IRQ_TYPE_EDGE_BOTH) {
+		u32 v;
+
+		v = readl(GPIO_IN_POL(ochip)) ^ readl(GPIO_DATA_IN(ochip));
+
+		/*
+		 * set initial polarity based on current input level
+		 */
+		u = readl(GPIO_IN_POL(ochip));
+		if (v & (1 << pin))
+			u |= 1 << pin;		/* falling */
+		else
+			u &= ~(1 << pin);	/* rising */
+		writel(u, GPIO_IN_POL(ochip));
+	}
+	return 0;
+}
+
+static void gpio_irq_handler(struct irq_desc *desc)
+{
+	struct orion_gpio_chip *ochip = irq_desc_get_handler_data(desc);
+	u32 cause, type;
+	int i;
+
+	if (ochip == NULL)
+		return;
+
+	cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip));
+	cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip));
+
+	for (i = 0; i < ochip->chip.ngpio; i++) {
+		int irq;
+
+		irq = ochip->secondary_irq_base + i;
+
+		if (!(cause & (1 << i)))
+			continue;
+
+		type = irq_get_trigger_type(irq);
+		if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+			/* Swap polarity (race with GPIO line) */
+			u32 polarity;
+
+			polarity = readl(GPIO_IN_POL(ochip));
+			polarity ^= 1 << i;
+			writel(polarity, GPIO_IN_POL(ochip));
+		}
+		generic_handle_irq(irq);
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/seq_file.h>
+
+static void orion_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+
+	struct orion_gpio_chip *ochip = gpiochip_get_data(chip);
+	u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk;
+	int i;
+
+	out	= readl_relaxed(GPIO_OUT(ochip));
+	io_conf	= readl_relaxed(GPIO_IO_CONF(ochip));
+	blink	= readl_relaxed(GPIO_BLINK_EN(ochip));
+	in_pol	= readl_relaxed(GPIO_IN_POL(ochip));
+	data_in	= readl_relaxed(GPIO_DATA_IN(ochip));
+	cause	= readl_relaxed(GPIO_EDGE_CAUSE(ochip));
+	edg_msk	= readl_relaxed(GPIO_EDGE_MASK(ochip));
+	lvl_msk	= readl_relaxed(GPIO_LEVEL_MASK(ochip));
+
+	for (i = 0; i < chip->ngpio; i++) {
+		const char *label;
+		u32 msk;
+		bool is_out;
+
+		label = gpiochip_is_requested(chip, i);
+		if (!label)
+			continue;
+
+		msk = 1 << i;
+		is_out = !(io_conf & msk);
+
+		seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label);
+
+		if (is_out) {
+			seq_printf(s, " out %s %s\n",
+				   out & msk ? "hi" : "lo",
+				   blink & msk ? "(blink )" : "");
+			continue;
+		}
+
+		seq_printf(s, " in  %s (act %s) - IRQ",
+			   (data_in ^ in_pol) & msk  ? "hi" : "lo",
+			   in_pol & msk ? "lo" : "hi");
+		if (!((edg_msk | lvl_msk) & msk)) {
+			seq_puts(s, " disabled\n");
+			continue;
+		}
+		if (edg_msk & msk)
+			seq_puts(s, " edge ");
+		if (lvl_msk & msk)
+			seq_puts(s, " level");
+		seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear  ");
+	}
+}
+#else
+#define orion_gpio_dbg_show NULL
+#endif
+
+static void orion_gpio_unmask_irq(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
+	u32 reg_val;
+	u32 mask = d->mask;
+
+	irq_gc_lock(gc);
+	reg_val = irq_reg_readl(gc, ct->regs.mask);
+	reg_val |= mask;
+	irq_reg_writel(gc, reg_val, ct->regs.mask);
+	irq_gc_unlock(gc);
+}
+
+static void orion_gpio_mask_irq(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
+	u32 mask = d->mask;
+	u32 reg_val;
+
+	irq_gc_lock(gc);
+	reg_val = irq_reg_readl(gc, ct->regs.mask);
+	reg_val &= ~mask;
+	irq_reg_writel(gc, reg_val, ct->regs.mask);
+	irq_gc_unlock(gc);
+}
+
+void __init orion_gpio_init(struct device_node *np,
+			    int gpio_base, int ngpio,
+			    void __iomem *base, int mask_offset,
+			    int secondary_irq_base,
+			    int irqs[4])
+{
+	struct orion_gpio_chip *ochip;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	char gc_label[16];
+	int i;
+
+	if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
+		return;
+
+	snprintf(gc_label, sizeof(gc_label), "orion_gpio%d",
+		orion_gpio_chip_count);
+
+	ochip = orion_gpio_chips + orion_gpio_chip_count;
+	ochip->chip.label = kstrdup(gc_label, GFP_KERNEL);
+	ochip->chip.request = orion_gpio_request;
+	ochip->chip.direction_input = orion_gpio_direction_input;
+	ochip->chip.get = orion_gpio_get;
+	ochip->chip.direction_output = orion_gpio_direction_output;
+	ochip->chip.set = orion_gpio_set;
+	ochip->chip.to_irq = orion_gpio_to_irq;
+	ochip->chip.base = gpio_base;
+	ochip->chip.ngpio = ngpio;
+	ochip->chip.can_sleep = 0;
+#ifdef CONFIG_OF
+	ochip->chip.of_node = np;
+#endif
+	ochip->chip.dbg_show = orion_gpio_dbg_show;
+
+	spin_lock_init(&ochip->lock);
+	ochip->base = (void __iomem *)base;
+	ochip->valid_input = 0;
+	ochip->valid_output = 0;
+	ochip->mask_offset = mask_offset;
+	ochip->secondary_irq_base = secondary_irq_base;
+
+	gpiochip_add_data(&ochip->chip, ochip);
+
+	/*
+	 * Mask and clear GPIO interrupts.
+	 */
+	writel(0, GPIO_EDGE_CAUSE(ochip));
+	writel(0, GPIO_EDGE_MASK(ochip));
+	writel(0, GPIO_LEVEL_MASK(ochip));
+
+	/* Setup the interrupt handlers. Each chip can have up to 4
+	 * interrupt handlers, with each handler dealing with 8 GPIO
+	 * pins. */
+
+	for (i = 0; i < 4; i++) {
+		if (irqs[i]) {
+			irq_set_chained_handler_and_data(irqs[i],
+							 gpio_irq_handler,
+							 ochip);
+		}
+	}
+
+	gc = irq_alloc_generic_chip("orion_gpio_irq", 2,
+				    secondary_irq_base,
+				    ochip->base, handle_level_irq);
+	gc->private = ochip;
+	ct = gc->chip_types;
+	ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
+	ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
+	ct->chip.irq_mask = orion_gpio_mask_irq;
+	ct->chip.irq_unmask = orion_gpio_unmask_irq;
+	ct->chip.irq_set_type = gpio_irq_set_type;
+	ct->chip.name = ochip->chip.label;
+
+	ct++;
+	ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF;
+	ct->regs.ack = GPIO_EDGE_CAUSE_OFF;
+	ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	ct->chip.irq_ack = irq_gc_ack_clr_bit;
+	ct->chip.irq_mask = orion_gpio_mask_irq;
+	ct->chip.irq_unmask = orion_gpio_unmask_irq;
+	ct->chip.irq_set_type = gpio_irq_set_type;
+	ct->handler = handle_edge_irq;
+	ct->chip.name = ochip->chip.label;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+
+	/* Setup irq domain on top of the generic chip. */
+	ochip->domain = irq_domain_add_legacy(np,
+					      ochip->chip.ngpio,
+					      ochip->secondary_irq_base,
+					      ochip->secondary_irq_base,
+					      &irq_domain_simple_ops,
+					      ochip);
+	if (!ochip->domain)
+		panic("%s: couldn't allocate irq domain (DT).\n",
+		      ochip->chip.label);
+
+	orion_gpio_chip_count++;
+}
diff --git a/arch/arm/plat-orion/include/plat/addr-map.h b/arch/arm/plat-orion/include/plat/addr-map.h
new file mode 100644
index 0000000..b76c065
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/addr-map.h
@@ -0,0 +1,54 @@
+/*
+ * arch/arm/plat-orion/include/plat/addr-map.h
+ *
+ * Marvell Orion SoC address map handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_ADDR_MAP_H
+#define __PLAT_ADDR_MAP_H
+
+extern struct mbus_dram_target_info orion_mbus_dram_info;
+
+struct orion_addr_map_cfg {
+	const int num_wins;	/* Total number of windows */
+	const int remappable_wins;
+	void __iomem *bridge_virt_base;
+	int hw_io_coherency;
+
+	/* If NULL, the default cpu_win_can_remap will be used, using
+	   the value in remappable_wins */
+	int (*cpu_win_can_remap) (const struct orion_addr_map_cfg *cfg,
+				  const int win);
+	/* If NULL, the default win_cfg_base will be used, using the
+	   value in bridge_virt_base */
+	void __iomem *(*win_cfg_base) (const struct orion_addr_map_cfg *cfg,
+				 const int win);
+};
+
+/*
+ * Information needed to setup one address mapping.
+ */
+struct orion_addr_map_info {
+	const int win;
+	const u32 base;
+	const u32 size;
+	const u8 target;
+	const u8 attr;
+	const int remap;
+};
+
+void __init orion_config_wins(struct orion_addr_map_cfg *cfg,
+			      const struct orion_addr_map_info *info);
+
+void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg,
+				const int win, const u32 base,
+				const u32 size, const u8 target,
+				const u8 attr, const int remap);
+
+void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
+					const void __iomem *ddr_window_cpu_base);
+#endif
diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
new file mode 100644
index 0000000..3647d3b
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/common.h
@@ -0,0 +1,107 @@
+/*
+ * arch/arm/plat-orion/include/plat/common.h
+ *
+ * Marvell Orion SoC common setup code used by different mach-/common.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_COMMON_H
+#include <linux/mv643xx_eth.h>
+#include <linux/platform_data/usb-ehci-orion.h>
+
+struct dsa_chip_data;
+struct mv_sata_platform_data;
+
+void __init orion_uart0_init(void __iomem *membase,
+			     resource_size_t mapbase,
+			     unsigned int irq,
+			     struct clk *clk);
+
+void __init orion_uart1_init(void __iomem *membase,
+			     resource_size_t mapbase,
+			     unsigned int irq,
+			     struct clk *clk);
+
+void __init orion_uart2_init(void __iomem *membase,
+			     resource_size_t mapbase,
+			     unsigned int irq,
+			     struct clk *clk);
+
+void __init orion_uart3_init(void __iomem *membase,
+			     resource_size_t mapbase,
+			     unsigned int irq,
+			     struct clk *clk);
+
+void __init orion_rtc_init(unsigned long mapbase,
+			   unsigned long irq);
+
+void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
+			    unsigned long mapbase,
+			    unsigned long irq,
+			    unsigned long irq_err,
+			    unsigned int tx_csum_limit);
+
+void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
+			    unsigned long mapbase,
+			    unsigned long irq,
+			    unsigned int tx_csum_limit);
+
+void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
+			    unsigned long mapbase,
+			    unsigned long irq);
+
+void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
+			    unsigned long mapbase,
+			    unsigned long irq);
+
+void __init orion_ge00_switch_init(struct dsa_chip_data *d);
+
+void __init orion_i2c_init(unsigned long mapbase,
+			   unsigned long irq,
+			   unsigned long freq_m);
+
+void __init orion_i2c_1_init(unsigned long mapbase,
+			     unsigned long irq,
+			     unsigned long freq_m);
+
+void __init orion_spi_init(unsigned long mapbase);
+
+void __init orion_spi_1_init(unsigned long mapbase);
+
+void __init orion_xor0_init(unsigned long mapbase_low,
+			    unsigned long mapbase_high,
+			    unsigned long irq_0,
+			    unsigned long irq_1);
+
+void __init orion_xor1_init(unsigned long mapbase_low,
+			    unsigned long mapbase_high,
+			    unsigned long irq_0,
+			    unsigned long irq_1);
+
+void __init orion_ehci_init(unsigned long mapbase,
+			    unsigned long irq,
+			    enum orion_ehci_phy_ver phy_version);
+
+void __init orion_ehci_1_init(unsigned long mapbase,
+			      unsigned long irq);
+
+void __init orion_ehci_2_init(unsigned long mapbase,
+			      unsigned long irq);
+
+void __init orion_sata_init(struct mv_sata_platform_data *sata_data,
+			    unsigned long mapbase,
+			    unsigned long irq);
+
+void __init orion_crypto_init(unsigned long mapbase,
+			      unsigned long srambase,
+			      unsigned long sram_size,
+			      unsigned long irq);
+
+void __init orion_clkdev_add(const char *con_id, const char *dev_id,
+			     struct clk *clk);
+
+void __init orion_clkdev_init(struct clk *tclk);
+#endif
diff --git a/arch/arm/plat-orion/include/plat/irq.h b/arch/arm/plat-orion/include/plat/irq.h
new file mode 100644
index 0000000..96be19e
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/irq.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/plat-orion/include/plat/irq.h
+ *
+ * Marvell Orion SoC IRQ handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_IRQ_H
+#define __PLAT_IRQ_H
+
+void orion_irq_init(unsigned int irq_start, void __iomem *maskaddr);
+#endif
diff --git a/arch/arm/plat-orion/include/plat/mpp.h b/arch/arm/plat-orion/include/plat/mpp.h
new file mode 100644
index 0000000..254552f
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/mpp.h
@@ -0,0 +1,34 @@
+/*
+ * arch/arm/plat-orion/include/plat/mpp.h
+ *
+ * Marvell Orion SoC MPP handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_MPP_H
+#define __PLAT_MPP_H
+
+#define MPP_NUM(x)	((x) & 0xff)
+#define MPP_SEL(x)	(((x) >> 8) & 0xf)
+
+/* This is the generic MPP macro, without any variant information.
+   Each machine architecture is expected to extend this with further
+   bit fields indicating which MPP configurations are valid for a
+   specific variant. */
+
+#define GENERIC_MPP(_num, _sel, _in, _out) ( \
+	/* MPP number */		((_num) & 0xff) | \
+	/* MPP select value */		(((_sel) & 0xf) << 8) | \
+	/* may be input signal */	((!!(_in)) << 12) | \
+	/* may be output signal */	((!!(_out)) << 13))
+
+#define MPP_INPUT_MASK		GENERIC_MPP(0, 0x0, 1, 0)
+#define MPP_OUTPUT_MASK		GENERIC_MPP(0, 0x0, 0, 1)
+
+void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
+			   unsigned int mpp_max, void __iomem *dev_bus);
+
+#endif
diff --git a/arch/arm/plat-orion/include/plat/orion-gpio.h b/arch/arm/plat-orion/include/plat/orion-gpio.h
new file mode 100644
index 0000000..e856b07
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/orion-gpio.h
@@ -0,0 +1,39 @@
+/*
+ * arch/arm/plat-orion/include/plat/orion-gpio.h
+ *
+ * Marvell Orion SoC GPIO handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_GPIO_H
+#define __PLAT_GPIO_H
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/irqdomain.h>
+
+struct gpio_desc;
+
+/*
+ * Orion-specific GPIO API extensions.
+ */
+void orion_gpio_set_unused(unsigned pin);
+void orion_gpio_set_blink(unsigned pin, int blink);
+int orion_gpio_led_blink_set(struct gpio_desc *desc, int state,
+	unsigned long *delay_on, unsigned long *delay_off);
+
+#define GPIO_INPUT_OK		(1 << 0)
+#define GPIO_OUTPUT_OK		(1 << 1)
+void orion_gpio_set_valid(unsigned pin, int mode);
+
+/* Initialize gpiolib. */
+void __init orion_gpio_init(struct device_node *np,
+			    int gpio_base, int ngpio,
+			    void __iomem *base, int mask_offset,
+			    int secondary_irq_base,
+			    int irq[4]);
+
+#endif
diff --git a/arch/arm/plat-orion/include/plat/pcie.h b/arch/arm/plat-orion/include/plat/pcie.h
new file mode 100644
index 0000000..fe5b9e8
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/pcie.h
@@ -0,0 +1,34 @@
+/*
+ * arch/arm/plat-orion/include/plat/pcie.h
+ *
+ * Marvell Orion SoC PCIe handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_PCIE_H
+#define __PLAT_PCIE_H
+
+struct pci_bus;
+
+u32 orion_pcie_dev_id(void __iomem *base);
+u32 orion_pcie_rev(void __iomem *base);
+int orion_pcie_link_up(void __iomem *base);
+int orion_pcie_x4_mode(void __iomem *base);
+int orion_pcie_get_local_bus_nr(void __iomem *base);
+void orion_pcie_set_local_bus_nr(void __iomem *base, int nr);
+void orion_pcie_reset(void __iomem *base);
+void orion_pcie_setup(void __iomem *base);
+int orion_pcie_rd_conf(void __iomem *base, struct pci_bus *bus,
+		       u32 devfn, int where, int size, u32 *val);
+int orion_pcie_rd_conf_tlp(void __iomem *base, struct pci_bus *bus,
+			   u32 devfn, int where, int size, u32 *val);
+int orion_pcie_rd_conf_wa(void __iomem *wa_base, struct pci_bus *bus,
+			  u32 devfn, int where, int size, u32 *val);
+int orion_pcie_wr_conf(void __iomem *base, struct pci_bus *bus,
+		       u32 devfn, int where, int size, u32 val);
+
+
+#endif
diff --git a/arch/arm/plat-orion/include/plat/time.h b/arch/arm/plat-orion/include/plat/time.h
new file mode 100644
index 0000000..07527e4
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/time.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/plat-orion/include/plat/time.h
+ *
+ * Marvell Orion SoC time handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_TIME_H
+#define __PLAT_TIME_H
+
+void orion_time_set_base(void __iomem *timer_base);
+
+void orion_time_init(void __iomem *bridge_base, u32 bridge_timer1_clr_mask,
+		     unsigned int irq, unsigned int tclk);
+
+
+#endif
diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
new file mode 100644
index 0000000..5b63b28
--- /dev/null
+++ b/arch/arm/plat-orion/irq.c
@@ -0,0 +1,39 @@
+/*
+ * arch/arm/plat-orion/irq.c
+ *
+ * Marvell Orion SoC IRQ handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/exception.h>
+#include <plat/irq.h>
+#include <plat/orion-gpio.h>
+
+void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	/*
+	 * Mask all interrupts initially.
+	 */
+	writel(0, maskaddr);
+
+	gc = irq_alloc_generic_chip("orion_irq", 1, irq_start, maskaddr,
+				    handle_level_irq);
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_clr_bit;
+	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+}
diff --git a/arch/arm/plat-orion/mpp.c b/arch/arm/plat-orion/mpp.c
new file mode 100644
index 0000000..5b4ff93
--- /dev/null
+++ b/arch/arm/plat-orion/mpp.c
@@ -0,0 +1,77 @@
+/*
+ * arch/arm/plat-orion/mpp.c
+ *
+ * MPP functions for Marvell orion SoCs
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mbus.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <plat/orion-gpio.h>
+#include <plat/mpp.h>
+
+/* Address of the ith MPP control register */
+static __init void __iomem *mpp_ctrl_addr(unsigned int i,
+					  void __iomem *dev_bus)
+{
+	return dev_bus + (i) * 4;
+}
+
+
+void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
+			   unsigned int mpp_max, void __iomem *dev_bus)
+{
+	unsigned int mpp_nr_regs = (1 + mpp_max/8);
+	u32 mpp_ctrl[mpp_nr_regs];
+	int i;
+
+	printk(KERN_DEBUG "initial MPP regs:");
+	for (i = 0; i < mpp_nr_regs; i++) {
+		mpp_ctrl[i] = readl(mpp_ctrl_addr(i, dev_bus));
+		printk(" %08x", mpp_ctrl[i]);
+	}
+	printk("\n");
+
+	for ( ; *mpp_list; mpp_list++) {
+		unsigned int num = MPP_NUM(*mpp_list);
+		unsigned int sel = MPP_SEL(*mpp_list);
+		int shift, gpio_mode;
+
+		if (num > mpp_max) {
+			printk(KERN_ERR "orion_mpp_conf: invalid MPP "
+					"number (%u)\n", num);
+			continue;
+		}
+		if (variant_mask && !(*mpp_list & variant_mask)) {
+			printk(KERN_WARNING
+			       "orion_mpp_conf: requested MPP%u config "
+			       "unavailable on this hardware\n", num);
+			continue;
+		}
+
+		shift = (num & 7) << 2;
+		mpp_ctrl[num / 8] &= ~(0xf << shift);
+		mpp_ctrl[num / 8] |= sel << shift;
+
+		gpio_mode = 0;
+		if (*mpp_list & MPP_INPUT_MASK)
+			gpio_mode |= GPIO_INPUT_OK;
+		if (*mpp_list & MPP_OUTPUT_MASK)
+			gpio_mode |= GPIO_OUTPUT_OK;
+
+		orion_gpio_set_valid(num, gpio_mode);
+	}
+
+	printk(KERN_DEBUG "  final MPP regs:");
+	for (i = 0; i < mpp_nr_regs; i++) {
+		writel(mpp_ctrl[i], mpp_ctrl_addr(i, dev_bus));
+		printk(" %08x", mpp_ctrl[i]);
+	}
+	printk("\n");
+}
diff --git a/arch/arm/plat-orion/pcie.c b/arch/arm/plat-orion/pcie.c
new file mode 100644
index 0000000..8b8c06d
--- /dev/null
+++ b/arch/arm/plat-orion/pcie.c
@@ -0,0 +1,288 @@
+/*
+ * arch/arm/plat-orion/pcie.c
+ *
+ * Marvell Orion SoC PCIe handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/mbus.h>
+#include <asm/mach/pci.h>
+#include <plat/pcie.h>
+#include <plat/addr-map.h>
+#include <linux/delay.h>
+
+/*
+ * PCIe unit register offsets.
+ */
+#define PCIE_DEV_ID_OFF		0x0000
+#define PCIE_CMD_OFF		0x0004
+#define PCIE_DEV_REV_OFF	0x0008
+#define PCIE_BAR_LO_OFF(n)	(0x0010 + ((n) << 3))
+#define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
+#define PCIE_HEADER_LOG_4_OFF	0x0128
+#define PCIE_BAR_CTRL_OFF(n)	(0x1804 + ((n - 1) * 4))
+#define PCIE_WIN04_CTRL_OFF(n)	(0x1820 + ((n) << 4))
+#define PCIE_WIN04_BASE_OFF(n)	(0x1824 + ((n) << 4))
+#define PCIE_WIN04_REMAP_OFF(n)	(0x182c + ((n) << 4))
+#define PCIE_WIN5_CTRL_OFF	0x1880
+#define PCIE_WIN5_BASE_OFF	0x1884
+#define PCIE_WIN5_REMAP_OFF	0x188c
+#define PCIE_CONF_ADDR_OFF	0x18f8
+#define  PCIE_CONF_ADDR_EN		0x80000000
+#define  PCIE_CONF_REG(r)		((((r) & 0xf00) << 16) | ((r) & 0xfc))
+#define  PCIE_CONF_BUS(b)		(((b) & 0xff) << 16)
+#define  PCIE_CONF_DEV(d)		(((d) & 0x1f) << 11)
+#define  PCIE_CONF_FUNC(f)		(((f) & 0x7) << 8)
+#define PCIE_CONF_DATA_OFF	0x18fc
+#define PCIE_MASK_OFF		0x1910
+#define PCIE_CTRL_OFF		0x1a00
+#define  PCIE_CTRL_X1_MODE		0x0001
+#define PCIE_STAT_OFF		0x1a04
+#define  PCIE_STAT_DEV_OFFS		20
+#define  PCIE_STAT_DEV_MASK		0x1f
+#define  PCIE_STAT_BUS_OFFS		8
+#define  PCIE_STAT_BUS_MASK		0xff
+#define  PCIE_STAT_LINK_DOWN		1
+#define PCIE_DEBUG_CTRL         0x1a60
+#define  PCIE_DEBUG_SOFT_RESET		(1<<20)
+
+
+u32 orion_pcie_dev_id(void __iomem *base)
+{
+	return readl(base + PCIE_DEV_ID_OFF) >> 16;
+}
+
+u32 orion_pcie_rev(void __iomem *base)
+{
+	return readl(base + PCIE_DEV_REV_OFF) & 0xff;
+}
+
+int orion_pcie_link_up(void __iomem *base)
+{
+	return !(readl(base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
+}
+
+int __init orion_pcie_x4_mode(void __iomem *base)
+{
+	return !(readl(base + PCIE_CTRL_OFF) & PCIE_CTRL_X1_MODE);
+}
+
+int orion_pcie_get_local_bus_nr(void __iomem *base)
+{
+	u32 stat = readl(base + PCIE_STAT_OFF);
+
+	return (stat >> PCIE_STAT_BUS_OFFS) & PCIE_STAT_BUS_MASK;
+}
+
+void __init orion_pcie_set_local_bus_nr(void __iomem *base, int nr)
+{
+	u32 stat;
+
+	stat = readl(base + PCIE_STAT_OFF);
+	stat &= ~(PCIE_STAT_BUS_MASK << PCIE_STAT_BUS_OFFS);
+	stat |= nr << PCIE_STAT_BUS_OFFS;
+	writel(stat, base + PCIE_STAT_OFF);
+}
+
+void __init orion_pcie_reset(void __iomem *base)
+{
+	u32 reg;
+	int i;
+
+	/*
+	 * MV-S104860-U0, Rev. C:
+	 * PCI Express Unit Soft Reset
+	 * When set, generates an internal reset in the PCI Express unit.
+	 * This bit should be cleared after the link is re-established.
+	 */
+	reg = readl(base + PCIE_DEBUG_CTRL);
+	reg |= PCIE_DEBUG_SOFT_RESET;
+	writel(reg, base + PCIE_DEBUG_CTRL);
+
+	for (i = 0; i < 20; i++) {
+		mdelay(10);
+
+		if (orion_pcie_link_up(base))
+			break;
+	}
+
+	reg &= ~(PCIE_DEBUG_SOFT_RESET);
+	writel(reg, base + PCIE_DEBUG_CTRL);
+}
+
+/*
+ * Setup PCIE BARs and Address Decode Wins:
+ * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
+ * WIN[0-3] -> DRAM bank[0-3]
+ */
+static void __init orion_pcie_setup_wins(void __iomem *base)
+{
+	const struct mbus_dram_target_info *dram;
+	u32 size;
+	int i;
+
+	dram = mv_mbus_dram_info();
+
+	/*
+	 * First, disable and clear BARs and windows.
+	 */
+	for (i = 1; i <= 2; i++) {
+		writel(0, base + PCIE_BAR_CTRL_OFF(i));
+		writel(0, base + PCIE_BAR_LO_OFF(i));
+		writel(0, base + PCIE_BAR_HI_OFF(i));
+	}
+
+	for (i = 0; i < 5; i++) {
+		writel(0, base + PCIE_WIN04_CTRL_OFF(i));
+		writel(0, base + PCIE_WIN04_BASE_OFF(i));
+		writel(0, base + PCIE_WIN04_REMAP_OFF(i));
+	}
+
+	writel(0, base + PCIE_WIN5_CTRL_OFF);
+	writel(0, base + PCIE_WIN5_BASE_OFF);
+	writel(0, base + PCIE_WIN5_REMAP_OFF);
+
+	/*
+	 * Setup windows for DDR banks.  Count total DDR size on the fly.
+	 */
+	size = 0;
+	for (i = 0; i < dram->num_cs; i++) {
+		const struct mbus_dram_window *cs = dram->cs + i;
+
+		writel(cs->base & 0xffff0000, base + PCIE_WIN04_BASE_OFF(i));
+		writel(0, base + PCIE_WIN04_REMAP_OFF(i));
+		writel(((cs->size - 1) & 0xffff0000) |
+			(cs->mbus_attr << 8) |
+			(dram->mbus_dram_target_id << 4) | 1,
+				base + PCIE_WIN04_CTRL_OFF(i));
+
+		size += cs->size;
+	}
+
+	/*
+	 * Round up 'size' to the nearest power of two.
+	 */
+	if ((size & (size - 1)) != 0)
+		size = 1 << fls(size);
+
+	/*
+	 * Setup BAR[1] to all DRAM banks.
+	 */
+	writel(dram->cs[0].base, base + PCIE_BAR_LO_OFF(1));
+	writel(0, base + PCIE_BAR_HI_OFF(1));
+	writel(((size - 1) & 0xffff0000) | 1, base + PCIE_BAR_CTRL_OFF(1));
+}
+
+void __init orion_pcie_setup(void __iomem *base)
+{
+	u16 cmd;
+	u32 mask;
+
+	/*
+	 * Point PCIe unit MBUS decode windows to DRAM space.
+	 */
+	orion_pcie_setup_wins(base);
+
+	/*
+	 * Master + slave enable.
+	 */
+	cmd = readw(base + PCIE_CMD_OFF);
+	cmd |= PCI_COMMAND_IO;
+	cmd |= PCI_COMMAND_MEMORY;
+	cmd |= PCI_COMMAND_MASTER;
+	writew(cmd, base + PCIE_CMD_OFF);
+
+	/*
+	 * Enable interrupt lines A-D.
+	 */
+	mask = readl(base + PCIE_MASK_OFF);
+	mask |= 0x0f000000;
+	writel(mask, base + PCIE_MASK_OFF);
+}
+
+int orion_pcie_rd_conf(void __iomem *base, struct pci_bus *bus,
+		       u32 devfn, int where, int size, u32 *val)
+{
+	writel(PCIE_CONF_BUS(bus->number) |
+		PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+		PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+		PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
+			base + PCIE_CONF_ADDR_OFF);
+
+	*val = readl(base + PCIE_CONF_DATA_OFF);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int orion_pcie_rd_conf_tlp(void __iomem *base, struct pci_bus *bus,
+			   u32 devfn, int where, int size, u32 *val)
+{
+	writel(PCIE_CONF_BUS(bus->number) |
+		PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+		PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+		PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
+			base + PCIE_CONF_ADDR_OFF);
+
+	*val = readl(base + PCIE_CONF_DATA_OFF);
+
+	if (bus->number != orion_pcie_get_local_bus_nr(base) ||
+	    PCI_FUNC(devfn) != 0)
+		*val = readl(base + PCIE_HEADER_LOG_4_OFF);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int orion_pcie_rd_conf_wa(void __iomem *wa_base, struct pci_bus *bus,
+			  u32 devfn, int where, int size, u32 *val)
+{
+	*val = readl(wa_base + (PCIE_CONF_BUS(bus->number) |
+				PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+				PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+				PCIE_CONF_REG(where)));
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int orion_pcie_wr_conf(void __iomem *base, struct pci_bus *bus,
+		       u32 devfn, int where, int size, u32 val)
+{
+	int ret = PCIBIOS_SUCCESSFUL;
+
+	writel(PCIE_CONF_BUS(bus->number) |
+		PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+		PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+		PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
+			base + PCIE_CONF_ADDR_OFF);
+
+	if (size == 4) {
+		writel(val, base + PCIE_CONF_DATA_OFF);
+	} else if (size == 2) {
+		writew(val, base + PCIE_CONF_DATA_OFF + (where & 3));
+	} else if (size == 1) {
+		writeb(val, base + PCIE_CONF_DATA_OFF + (where & 3));
+	} else {
+		ret = PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	return ret;
+}
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
new file mode 100644
index 0000000..ffb93db
--- /dev/null
+++ b/arch/arm/plat-orion/time.c
@@ -0,0 +1,242 @@
+/*
+ * arch/arm/plat-orion/time.c
+ *
+ * Marvell Orion SoC timer handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Timer 0 is used as free-running clocksource, while timer 1 is
+ * used as clock_event_device.
+ */
+
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched_clock.h>
+#include <plat/time.h>
+#include <asm/delay.h>
+
+/*
+ * MBus bridge block registers.
+ */
+#define BRIDGE_CAUSE_OFF	0x0110
+#define BRIDGE_MASK_OFF		0x0114
+#define  BRIDGE_INT_TIMER0	 0x0002
+#define  BRIDGE_INT_TIMER1	 0x0004
+
+
+/*
+ * Timer block registers.
+ */
+#define TIMER_CTRL_OFF		0x0000
+#define  TIMER0_EN		 0x0001
+#define  TIMER0_RELOAD_EN	 0x0002
+#define  TIMER1_EN		 0x0004
+#define  TIMER1_RELOAD_EN	 0x0008
+#define TIMER0_RELOAD_OFF	0x0010
+#define TIMER0_VAL_OFF		0x0014
+#define TIMER1_RELOAD_OFF	0x0018
+#define TIMER1_VAL_OFF		0x001c
+
+
+/*
+ * SoC-specific data.
+ */
+static void __iomem *bridge_base;
+static u32 bridge_timer1_clr_mask;
+static void __iomem *timer_base;
+
+
+/*
+ * Number of timer ticks per jiffy.
+ */
+static u32 ticks_per_jiffy;
+
+
+/*
+ * Orion's sched_clock implementation. It has a resolution of
+ * at least 7.5ns (133MHz TCLK).
+ */
+
+static u64 notrace orion_read_sched_clock(void)
+{
+	return ~readl(timer_base + TIMER0_VAL_OFF);
+}
+
+/*
+ * Clockevent handling.
+ */
+static int
+orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
+{
+	unsigned long flags;
+	u32 u;
+
+	if (delta == 0)
+		return -ETIME;
+
+	local_irq_save(flags);
+
+	/*
+	 * Clear and enable clockevent timer interrupt.
+	 */
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
+
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
+	u |= BRIDGE_INT_TIMER1;
+	writel(u, bridge_base + BRIDGE_MASK_OFF);
+
+	/*
+	 * Setup new clockevent timer value.
+	 */
+	writel(delta, timer_base + TIMER1_VAL_OFF);
+
+	/*
+	 * Enable the timer.
+	 */
+	u = readl(timer_base + TIMER_CTRL_OFF);
+	u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
+	writel(u, timer_base + TIMER_CTRL_OFF);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static int orion_clkevt_shutdown(struct clock_event_device *evt)
+{
+	unsigned long flags;
+	u32 u;
+
+	local_irq_save(flags);
+
+	/* Disable timer */
+	u = readl(timer_base + TIMER_CTRL_OFF);
+	writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
+
+	/* Disable timer interrupt */
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
+	writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
+
+	/* ACK pending timer interrupt */
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static int orion_clkevt_set_periodic(struct clock_event_device *evt)
+{
+	unsigned long flags;
+	u32 u;
+
+	local_irq_save(flags);
+
+	/* Setup timer to fire at 1/HZ intervals */
+	writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
+	writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
+
+	/* Enable timer interrupt */
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
+	writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
+
+	/* Enable timer */
+	u = readl(timer_base + TIMER_CTRL_OFF);
+	writel(u | TIMER1_EN | TIMER1_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static struct clock_event_device orion_clkevt = {
+	.name			= "orion_tick",
+	.features		= CLOCK_EVT_FEAT_ONESHOT |
+				  CLOCK_EVT_FEAT_PERIODIC,
+	.rating			= 300,
+	.set_next_event		= orion_clkevt_next_event,
+	.set_state_shutdown	= orion_clkevt_shutdown,
+	.set_state_periodic	= orion_clkevt_set_periodic,
+	.set_state_oneshot	= orion_clkevt_shutdown,
+	.tick_resume		= orion_clkevt_shutdown,
+};
+
+static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
+{
+	/*
+	 * ACK timer interrupt and call event handler.
+	 */
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
+	orion_clkevt.event_handler(&orion_clkevt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction orion_timer_irq = {
+	.name		= "orion_tick",
+	.flags		= IRQF_TIMER,
+	.handler	= orion_timer_interrupt
+};
+
+void __init
+orion_time_set_base(void __iomem *_timer_base)
+{
+	timer_base = _timer_base;
+}
+
+static unsigned long orion_delay_timer_read(void)
+{
+	return ~readl(timer_base + TIMER0_VAL_OFF);
+}
+
+static struct delay_timer orion_delay_timer = {
+	.read_current_timer = orion_delay_timer_read,
+};
+
+void __init
+orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
+		unsigned int irq, unsigned int tclk)
+{
+	u32 u;
+
+	/*
+	 * Set SoC-specific data.
+	 */
+	bridge_base = _bridge_base;
+	bridge_timer1_clr_mask = _bridge_timer1_clr_mask;
+
+	ticks_per_jiffy = (tclk + HZ/2) / HZ;
+
+	orion_delay_timer.freq = tclk;
+	register_current_timer_delay(&orion_delay_timer);
+
+	/*
+	 * Set scale and timer for sched_clock.
+	 */
+	sched_clock_register(orion_read_sched_clock, 32, tclk);
+
+	/*
+	 * Setup free-running clocksource timer (interrupts
+	 * disabled).
+	 */
+	writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+	writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
+	writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
+	u = readl(timer_base + TIMER_CTRL_OFF);
+	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
+	clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, "orion_clocksource",
+		tclk, 300, 32, clocksource_mmio_readl_down);
+
+	/*
+	 * Setup clockevent timer (interrupt-driven).
+	 */
+	setup_irq(irq, &orion_timer_irq);
+	orion_clkevt.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&orion_clkevt, tclk, 1, 0xfffffffe);
+}