aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-integrator
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-integrator')
-rw-r--r--arch/arm/mach-integrator/Kconfig37
-rw-r--r--arch/arm/mach-integrator/Makefile14
-rw-r--r--arch/arm/mach-integrator/Makefile.boot4
-rw-r--r--arch/arm/mach-integrator/common.h2
-rw-r--r--arch/arm/mach-integrator/core.c236
-rw-r--r--arch/arm/mach-integrator/cpu.c224
-rw-r--r--arch/arm/mach-integrator/impd1.c482
-rw-r--r--arch/arm/mach-integrator/include/mach/bits.h61
-rw-r--r--arch/arm/mach-integrator/include/mach/clkdev.h26
-rw-r--r--arch/arm/mach-integrator/include/mach/cm.h36
-rw-r--r--arch/arm/mach-integrator/include/mach/debug-macro.S20
-rw-r--r--arch/arm/mach-integrator/include/mach/entry-macro.S45
-rw-r--r--arch/arm/mach-integrator/include/mach/hardware.h52
-rw-r--r--arch/arm/mach-integrator/include/mach/impd1.h18
-rw-r--r--arch/arm/mach-integrator/include/mach/io.h36
-rw-r--r--arch/arm/mach-integrator/include/mach/irqs.h82
-rw-r--r--arch/arm/mach-integrator/include/mach/lm.h23
-rw-r--r--arch/arm/mach-integrator/include/mach/memory.h34
-rw-r--r--arch/arm/mach-integrator/include/mach/platform.h414
-rw-r--r--arch/arm/mach-integrator/include/mach/system.h44
-rw-r--r--arch/arm/mach-integrator/include/mach/timex.h26
-rw-r--r--arch/arm/mach-integrator/include/mach/uncompress.h50
-rw-r--r--arch/arm/mach-integrator/include/mach/vmalloc.h20
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c467
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c502
-rw-r--r--arch/arm/mach-integrator/leds.c91
-rw-r--r--arch/arm/mach-integrator/lm.c99
-rw-r--r--arch/arm/mach-integrator/pci.c124
-rw-r--r--arch/arm/mach-integrator/pci_v3.c609
29 files changed, 3878 insertions, 0 deletions
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
new file mode 100644
index 00000000..dfd18f3b
--- /dev/null
+++ b/arch/arm/mach-integrator/Kconfig
@@ -0,0 +1,37 @@
+if ARCH_INTEGRATOR
+
+menu "Integrator Options"
+
+config ARCH_INTEGRATOR_AP
+ bool "Support Integrator/AP and Integrator/PP2 platforms"
+ select CLKSRC_MMIO
+ select MIGHT_HAVE_PCI
+ help
+ Include support for the ARM(R) Integrator/AP and
+ Integrator/PP2 platforms.
+
+config ARCH_INTEGRATOR_CP
+ bool "Support Integrator/CP platform"
+ select ARCH_CINTEGRATOR
+ select ARM_TIMER_SP804
+ select PLAT_VERSATILE_CLCD
+ help
+ Include support for the ARM(R) Integrator CP platform.
+
+config ARCH_CINTEGRATOR
+ bool
+
+config INTEGRATOR_IMPD1
+ tristate "Include support for Integrator/IM-PD1"
+ depends on ARCH_INTEGRATOR_AP
+ help
+ The IM-PD1 is an add-on logic module for the Integrator which
+ allows ARM(R) Ltd PrimeCells to be developed and evaluated.
+ The IM-PD1 can be found on the Integrator/PP2 platform.
+
+ To compile this driver as a module, choose M here: the
+ module will be called impd1.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
new file mode 100644
index 00000000..ebeef966
--- /dev/null
+++ b/arch/arm/mach-integrator/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y := core.o lm.o
+obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
+obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o
+
+obj-$(CONFIG_LEDS) += leds.o
+obj-$(CONFIG_PCI) += pci_v3.o pci.o
+obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
+obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
diff --git a/arch/arm/mach-integrator/Makefile.boot b/arch/arm/mach-integrator/Makefile.boot
new file mode 100644
index 00000000..c7e75acf
--- /dev/null
+++ b/arch/arm/mach-integrator/Makefile.boot
@@ -0,0 +1,4 @@
+ zreladdr-y := 0x00008000
+params_phys-y := 0x00000100
+initrd_phys-y := 0x00800000
+
diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h
new file mode 100644
index 00000000..a08f9b02
--- /dev/null
+++ b/arch/arm/mach-integrator/common.h
@@ -0,0 +1,2 @@
+void integrator_init_early(void);
+void integrator_reserve(void);
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
new file mode 100644
index 00000000..77315b99
--- /dev/null
+++ b/arch/arm/mach-integrator/core.c
@@ -0,0 +1,236 @@
+/*
+ * linux/arch/arm/mach-integrator/core.c
+ *
+ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/memblock.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/termios.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <asm/irq.h>
+#include <mach/cm.h>
+#include <asm/system.h>
+#include <asm/leds.h>
+#include <asm/mach/time.h>
+#include <asm/pgtable.h>
+
+static struct amba_pl010_data integrator_uart_data;
+
+static struct amba_device rtc_device = {
+ .dev = {
+ .init_name = "mb:15",
+ },
+ .res = {
+ .start = INTEGRATOR_RTC_BASE,
+ .end = INTEGRATOR_RTC_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_RTCINT, NO_IRQ },
+ .periphid = 0x00041030,
+};
+
+static struct amba_device uart0_device = {
+ .dev = {
+ .init_name = "mb:16",
+ .platform_data = &integrator_uart_data,
+ },
+ .res = {
+ .start = INTEGRATOR_UART0_BASE,
+ .end = INTEGRATOR_UART0_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_UARTINT0, NO_IRQ },
+ .periphid = 0x0041010,
+};
+
+static struct amba_device uart1_device = {
+ .dev = {
+ .init_name = "mb:17",
+ .platform_data = &integrator_uart_data,
+ },
+ .res = {
+ .start = INTEGRATOR_UART1_BASE,
+ .end = INTEGRATOR_UART1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_UARTINT1, NO_IRQ },
+ .periphid = 0x0041010,
+};
+
+static struct amba_device kmi0_device = {
+ .dev = {
+ .init_name = "mb:18",
+ },
+ .res = {
+ .start = KMI0_BASE,
+ .end = KMI0_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_KMIINT0, NO_IRQ },
+ .periphid = 0x00041050,
+};
+
+static struct amba_device kmi1_device = {
+ .dev = {
+ .init_name = "mb:19",
+ },
+ .res = {
+ .start = KMI1_BASE,
+ .end = KMI1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_KMIINT1, NO_IRQ },
+ .periphid = 0x00041050,
+};
+
+static struct amba_device *amba_devs[] __initdata = {
+ &rtc_device,
+ &uart0_device,
+ &uart1_device,
+ &kmi0_device,
+ &kmi1_device,
+};
+
+/*
+ * These are fixed clocks.
+ */
+static struct clk clk24mhz = {
+ .rate = 24000000,
+};
+
+static struct clk uartclk = {
+ .rate = 14745600,
+};
+
+static struct clk dummy_apb_pclk;
+
+static struct clk_lookup lookups[] = {
+ { /* Bus clock */
+ .con_id = "apb_pclk",
+ .clk = &dummy_apb_pclk,
+ }, { /* UART0 */
+ .dev_id = "mb:16",
+ .clk = &uartclk,
+ }, { /* UART1 */
+ .dev_id = "mb:17",
+ .clk = &uartclk,
+ }, { /* KMI0 */
+ .dev_id = "mb:18",
+ .clk = &clk24mhz,
+ }, { /* KMI1 */
+ .dev_id = "mb:19",
+ .clk = &clk24mhz,
+ }, { /* MMCI - IntegratorCP */
+ .dev_id = "mb:1c",
+ .clk = &uartclk,
+ }
+};
+
+void __init integrator_init_early(void)
+{
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+}
+
+static int __init integrator_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+ amba_device_register(d, &iomem_resource);
+ }
+
+ return 0;
+}
+
+arch_initcall(integrator_init);
+
+/*
+ * On the Integrator platform, the port RTS and DTR are provided by
+ * bits in the following SC_CTRLS register bits:
+ * RTS DTR
+ * UART0 7 6
+ * UART1 5 4
+ */
+#define SC_CTRLC IO_ADDRESS(INTEGRATOR_SC_CTRLC)
+#define SC_CTRLS IO_ADDRESS(INTEGRATOR_SC_CTRLS)
+
+static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl)
+{
+ unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
+
+ if (dev == &uart0_device) {
+ rts_mask = 1 << 4;
+ dtr_mask = 1 << 5;
+ } else {
+ rts_mask = 1 << 6;
+ dtr_mask = 1 << 7;
+ }
+
+ if (mctrl & TIOCM_RTS)
+ ctrlc |= rts_mask;
+ else
+ ctrls |= rts_mask;
+
+ if (mctrl & TIOCM_DTR)
+ ctrlc |= dtr_mask;
+ else
+ ctrls |= dtr_mask;
+
+ __raw_writel(ctrls, SC_CTRLS);
+ __raw_writel(ctrlc, SC_CTRLC);
+}
+
+static struct amba_pl010_data integrator_uart_data = {
+ .set_mctrl = integrator_uart_set_mctrl,
+};
+
+#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL)
+
+static DEFINE_SPINLOCK(cm_lock);
+
+/**
+ * cm_control - update the CM_CTRL register.
+ * @mask: bits to change
+ * @set: bits to set
+ */
+void cm_control(u32 mask, u32 set)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&cm_lock, flags);
+ val = readl(CM_CTRL) & ~mask;
+ writel(val | set, CM_CTRL);
+ spin_unlock_irqrestore(&cm_lock, flags);
+}
+
+EXPORT_SYMBOL(cm_control);
+
+/*
+ * We need to stop things allocating the low memory; ideally we need a
+ * better implementation of GFP_DMA which does not assume that DMA-able
+ * memory starts at zero.
+ */
+void __init integrator_reserve(void)
+{
+ memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
+}
diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
new file mode 100644
index 00000000..fbb45777
--- /dev/null
+++ b/arch/arm/mach-integrator/cpu.c
@@ -0,0 +1,224 @@
+/*
+ * linux/arch/arm/mach-integrator/cpu.c
+ *
+ * Copyright (C) 2001-2002 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * CPU support functions
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/cpufreq.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/icst.h>
+
+static struct cpufreq_driver integrator_driver;
+
+#define CM_ID IO_ADDRESS(INTEGRATOR_HDR_ID)
+#define CM_OSC IO_ADDRESS(INTEGRATOR_HDR_OSC)
+#define CM_STAT IO_ADDRESS(INTEGRATOR_HDR_STAT)
+#define CM_LOCK IO_ADDRESS(INTEGRATOR_HDR_LOCK)
+
+static const struct icst_params lclk_params = {
+ .ref = 24000000,
+ .vco_max = ICST525_VCO_MAX_5V,
+ .vco_min = ICST525_VCO_MIN,
+ .vd_min = 8,
+ .vd_max = 132,
+ .rd_min = 24,
+ .rd_max = 24,
+ .s2div = icst525_s2div,
+ .idx2s = icst525_idx2s,
+};
+
+static const struct icst_params cclk_params = {
+ .ref = 24000000,
+ .vco_max = ICST525_VCO_MAX_5V,
+ .vco_min = ICST525_VCO_MIN,
+ .vd_min = 12,
+ .vd_max = 160,
+ .rd_min = 24,
+ .rd_max = 24,
+ .s2div = icst525_s2div,
+ .idx2s = icst525_idx2s,
+};
+
+/*
+ * Validate the speed policy.
+ */
+static int integrator_verify_policy(struct cpufreq_policy *policy)
+{
+ struct icst_vco vco;
+
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ vco = icst_hz_to_vco(&cclk_params, policy->max * 1000);
+ policy->max = icst_hz(&cclk_params, vco) / 1000;
+
+ vco = icst_hz_to_vco(&cclk_params, policy->min * 1000);
+ policy->min = icst_hz(&cclk_params, vco) / 1000;
+
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ return 0;
+}
+
+
+static int integrator_set_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ cpumask_t cpus_allowed;
+ int cpu = policy->cpu;
+ struct icst_vco vco;
+ struct cpufreq_freqs freqs;
+ u_int cm_osc;
+
+ /*
+ * Save this threads cpus_allowed mask.
+ */
+ cpus_allowed = current->cpus_allowed;
+
+ /*
+ * Bind to the specified CPU. When this call returns,
+ * we should be running on the right CPU.
+ */
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ BUG_ON(cpu != smp_processor_id());
+
+ /* get current setting */
+ cm_osc = __raw_readl(CM_OSC);
+
+ if (machine_is_integrator()) {
+ vco.s = (cm_osc >> 8) & 7;
+ } else if (machine_is_cintegrator()) {
+ vco.s = 1;
+ }
+ vco.v = cm_osc & 255;
+ vco.r = 22;
+ freqs.old = icst_hz(&cclk_params, vco) / 1000;
+
+ /* icst_hz_to_vco rounds down -- so we need the next
+ * larger freq in case of CPUFREQ_RELATION_L.
+ */
+ if (relation == CPUFREQ_RELATION_L)
+ target_freq += 999;
+ if (target_freq > policy->max)
+ target_freq = policy->max;
+ vco = icst_hz_to_vco(&cclk_params, target_freq * 1000);
+ freqs.new = icst_hz(&cclk_params, vco) / 1000;
+
+ freqs.cpu = policy->cpu;
+
+ if (freqs.old == freqs.new) {
+ set_cpus_allowed(current, cpus_allowed);
+ return 0;
+ }
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ cm_osc = __raw_readl(CM_OSC);
+
+ if (machine_is_integrator()) {
+ cm_osc &= 0xfffff800;
+ cm_osc |= vco.s << 8;
+ } else if (machine_is_cintegrator()) {
+ cm_osc &= 0xffffff00;
+ }
+ cm_osc |= vco.v;
+
+ __raw_writel(0xa05f, CM_LOCK);
+ __raw_writel(cm_osc, CM_OSC);
+ __raw_writel(0, CM_LOCK);
+
+ /*
+ * Restore the CPUs allowed mask.
+ */
+ set_cpus_allowed(current, cpus_allowed);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return 0;
+}
+
+static unsigned int integrator_get(unsigned int cpu)
+{
+ cpumask_t cpus_allowed;
+ unsigned int current_freq;
+ u_int cm_osc;
+ struct icst_vco vco;
+
+ cpus_allowed = current->cpus_allowed;
+
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ BUG_ON(cpu != smp_processor_id());
+
+ /* detect memory etc. */
+ cm_osc = __raw_readl(CM_OSC);
+
+ if (machine_is_integrator()) {
+ vco.s = (cm_osc >> 8) & 7;
+ } else {
+ vco.s = 1;
+ }
+ vco.v = cm_osc & 255;
+ vco.r = 22;
+
+ current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */
+
+ set_cpus_allowed(current, cpus_allowed);
+
+ return current_freq;
+}
+
+static int integrator_cpufreq_init(struct cpufreq_policy *policy)
+{
+
+ /* set default policy and cpuinfo */
+ policy->cpuinfo.max_freq = 160000;
+ policy->cpuinfo.min_freq = 12000;
+ policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
+ policy->cur = policy->min = policy->max = integrator_get(policy->cpu);
+
+ return 0;
+}
+
+static struct cpufreq_driver integrator_driver = {
+ .verify = integrator_verify_policy,
+ .target = integrator_set_target,
+ .get = integrator_get,
+ .init = integrator_cpufreq_init,
+ .name = "integrator",
+};
+
+static int __init integrator_cpu_init(void)
+{
+ return cpufreq_register_driver(&integrator_driver);
+}
+
+static void __exit integrator_cpu_exit(void)
+{
+ cpufreq_unregister_driver(&integrator_driver);
+}
+
+MODULE_AUTHOR ("Russell M. King");
+MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
+MODULE_LICENSE ("GPL");
+
+module_init(integrator_cpu_init);
+module_exit(integrator_cpu_exit);
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
new file mode 100644
index 00000000..8cbb75a9
--- /dev/null
+++ b/arch/arm/mach-integrator/impd1.c
@@ -0,0 +1,482 @@
+/*
+ * linux/arch/arm/mach-integrator/impd1.c
+ *
+ * Copyright (C) 2003 Deep Blue Solutions Ltd, 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file provides the core support for the IM-PD1 module.
+ *
+ * Module / boot parameters.
+ * lmid=n impd1.lmid=n - set the logic module position in stack to 'n'
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+
+#include <asm/hardware/icst.h>
+#include <mach/lm.h>
+#include <mach/impd1.h>
+#include <asm/sizes.h>
+
+static int module_id;
+
+module_param_named(lmid, module_id, int, 0444);
+MODULE_PARM_DESC(lmid, "logic module stack position");
+
+struct impd1_module {
+ void __iomem *base;
+ struct clk vcos[2];
+ struct clk_lookup *clks[3];
+};
+
+static const struct icst_params impd1_vco_params = {
+ .ref = 24000000, /* 24 MHz */
+ .vco_max = ICST525_VCO_MAX_3V,
+ .vco_min = ICST525_VCO_MIN,
+ .vd_min = 12,
+ .vd_max = 519,
+ .rd_min = 3,
+ .rd_max = 120,
+ .s2div = icst525_s2div,
+ .idx2s = icst525_idx2s,
+};
+
+static void impd1_setvco(struct clk *clk, struct icst_vco vco)
+{
+ struct impd1_module *impd1 = clk->data;
+ u32 val = vco.v | (vco.r << 9) | (vco.s << 16);
+
+ writel(0xa05f, impd1->base + IMPD1_LOCK);
+ writel(val, clk->vcoreg);
+ writel(0, impd1->base + IMPD1_LOCK);
+
+#ifdef DEBUG
+ vco.v = val & 0x1ff;
+ vco.r = (val >> 9) & 0x7f;
+ vco.s = (val >> 16) & 7;
+
+ pr_debug("IM-PD1: VCO%d clock is %ld Hz\n",
+ vconr, icst525_hz(&impd1_vco_params, vco));
+#endif
+}
+
+static const struct clk_ops impd1_clk_ops = {
+ .round = icst_clk_round,
+ .set = icst_clk_set,
+ .setvco = impd1_setvco,
+};
+
+void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
+{
+ struct impd1_module *impd1 = dev_get_drvdata(dev);
+ u32 cur;
+
+ val &= mask;
+ cur = readl(impd1->base + IMPD1_CTRL) & ~mask;
+ writel(cur | val, impd1->base + IMPD1_CTRL);
+}
+
+EXPORT_SYMBOL(impd1_tweak_control);
+
+/*
+ * CLCD support
+ */
+#define PANEL PROSPECTOR
+
+#define LTM10C209 1
+#define PROSPECTOR 2
+#define SVGA 3
+#define VGA 4
+
+#if PANEL == VGA
+#define PANELTYPE vga
+static struct clcd_panel vga = {
+ .mode = {
+ .name = "VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 39721,
+ .left_margin = 40,
+ .right_margin = 24,
+ .upper_margin = 32,
+ .lower_margin = 11,
+ .hsync_len = 96,
+ .vsync_len = 2,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ .width = -1,
+ .height = -1,
+ .tim2 = TIM2_BCD | TIM2_IPC,
+ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+ .caps = CLCD_CAP_5551,
+ .connector = IMPD1_CTRL_DISP_VGA,
+ .bpp = 16,
+ .grayscale = 0,
+};
+
+#elif PANEL == SVGA
+#define PANELTYPE svga
+static struct clcd_panel svga = {
+ .mode = {
+ .name = "SVGA",
+ .refresh = 0,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 27778,
+ .left_margin = 20,
+ .right_margin = 20,
+ .upper_margin = 5,
+ .lower_margin = 5,
+ .hsync_len = 164,
+ .vsync_len = 62,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ .width = -1,
+ .height = -1,
+ .tim2 = TIM2_BCD,
+ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+ .connector = IMPD1_CTRL_DISP_VGA,
+ .caps = CLCD_CAP_5551,
+ .bpp = 16,
+ .grayscale = 0,
+};
+
+#elif PANEL == PROSPECTOR
+#define PANELTYPE prospector
+static struct clcd_panel prospector = {
+ .mode = {
+ .name = "PROSPECTOR",
+ .refresh = 0,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 40000,
+ .left_margin = 33,
+ .right_margin = 64,
+ .upper_margin = 36,
+ .lower_margin = 7,
+ .hsync_len = 64,
+ .vsync_len = 25,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ .width = -1,
+ .height = -1,
+ .tim2 = TIM2_BCD,
+ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+ .caps = CLCD_CAP_5551,
+ .fixedtimings = 1,
+ .connector = IMPD1_CTRL_DISP_LCD,
+ .bpp = 16,
+ .grayscale = 0,
+};
+
+#elif PANEL == LTM10C209
+#define PANELTYPE ltm10c209
+/*
+ * Untested.
+ */
+static struct clcd_panel ltm10c209 = {
+ .mode = {
+ .name = "LTM10C209",
+ .refresh = 0,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 40000,
+ .left_margin = 20,
+ .right_margin = 20,
+ .upper_margin = 19,
+ .lower_margin = 19,
+ .hsync_len = 20,
+ .vsync_len = 10,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+ .width = -1,
+ .height = -1,
+ .tim2 = TIM2_BCD,
+ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+ .caps = CLCD_CAP_5551,
+ .fixedtimings = 1,
+ .connector = IMPD1_CTRL_DISP_LCD,
+ .bpp = 16,
+ .grayscale = 0,
+};
+#endif
+
+/*
+ * Disable all display connectors on the interface module.
+ */
+static void impd1fb_clcd_disable(struct clcd_fb *fb)
+{
+ impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK, 0);
+}
+
+/*
+ * Enable the relevant connector on the interface module.
+ */
+static void impd1fb_clcd_enable(struct clcd_fb *fb)
+{
+ impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK,
+ fb->panel->connector | IMPD1_CTRL_DISP_ENABLE);
+}
+
+static int impd1fb_clcd_setup(struct clcd_fb *fb)
+{
+ unsigned long framebase = fb->dev->res.start + 0x01000000;
+ unsigned long framesize = SZ_1M;
+ int ret = 0;
+
+ fb->panel = &PANELTYPE;
+
+ if (!request_mem_region(framebase, framesize, "clcd framebuffer")) {
+ printk(KERN_ERR "IM-PD1: unable to reserve framebuffer\n");
+ return -EBUSY;
+ }
+
+ fb->fb.screen_base = ioremap(framebase, framesize);
+ if (!fb->fb.screen_base) {
+ printk(KERN_ERR "IM-PD1: unable to map framebuffer\n");
+ ret = -ENOMEM;
+ goto free_buffer;
+ }
+
+ fb->fb.fix.smem_start = framebase;
+ fb->fb.fix.smem_len = framesize;
+
+ return 0;
+
+ free_buffer:
+ release_mem_region(framebase, framesize);
+ return ret;
+}
+
+static int impd1fb_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+ unsigned long start, size;
+
+ start = vma->vm_pgoff + (fb->fb.fix.smem_start >> PAGE_SHIFT);
+ size = vma->vm_end - vma->vm_start;
+
+ return remap_pfn_range(vma, vma->vm_start, start, size,
+ vma->vm_page_prot);
+}
+
+static void impd1fb_clcd_remove(struct clcd_fb *fb)
+{
+ iounmap(fb->fb.screen_base);
+ release_mem_region(fb->fb.fix.smem_start, fb->fb.fix.smem_len);
+}
+
+static struct clcd_board impd1_clcd_data = {
+ .name = "IM-PD/1",
+ .caps = CLCD_CAP_5551 | CLCD_CAP_888,
+ .check = clcdfb_check,
+ .decode = clcdfb_decode,
+ .disable = impd1fb_clcd_disable,
+ .enable = impd1fb_clcd_enable,
+ .setup = impd1fb_clcd_setup,
+ .mmap = impd1fb_clcd_mmap,
+ .remove = impd1fb_clcd_remove,
+};
+
+struct impd1_device {
+ unsigned long offset;
+ unsigned int irq[2];
+ unsigned int id;
+ void *platform_data;
+};
+
+static struct impd1_device impd1_devs[] = {
+ {
+ .offset = 0x03000000,
+ .id = 0x00041190,
+ }, {
+ .offset = 0x00100000,
+ .irq = { 1 },
+ .id = 0x00141011,
+ }, {
+ .offset = 0x00200000,
+ .irq = { 2 },
+ .id = 0x00141011,
+ }, {
+ .offset = 0x00300000,
+ .irq = { 3 },
+ .id = 0x00041022,
+ }, {
+ .offset = 0x00400000,
+ .irq = { 4 },
+ .id = 0x00041061,
+ }, {
+ .offset = 0x00500000,
+ .irq = { 5 },
+ .id = 0x00041061,
+ }, {
+ .offset = 0x00600000,
+ .irq = { 6 },
+ .id = 0x00041130,
+ }, {
+ .offset = 0x00700000,
+ .irq = { 7, 8 },
+ .id = 0x00041181,
+ }, {
+ .offset = 0x00800000,
+ .irq = { 9 },
+ .id = 0x00041041,
+ }, {
+ .offset = 0x01000000,
+ .irq = { 11 },
+ .id = 0x00041110,
+ .platform_data = &impd1_clcd_data,
+ }
+};
+
+static struct clk fixed_14745600 = {
+ .rate = 14745600,
+};
+
+static int impd1_probe(struct lm_device *dev)
+{
+ struct impd1_module *impd1;
+ int i, ret;
+
+ if (dev->id != module_id)
+ return -EINVAL;
+
+ if (!request_mem_region(dev->resource.start, SZ_4K, "LM registers"))
+ return -EBUSY;
+
+ impd1 = kzalloc(sizeof(struct impd1_module), GFP_KERNEL);
+ if (!impd1) {
+ ret = -ENOMEM;
+ goto release_lm;
+ }
+
+ impd1->base = ioremap(dev->resource.start, SZ_4K);
+ if (!impd1->base) {
+ ret = -ENOMEM;
+ goto free_impd1;
+ }
+
+ lm_set_drvdata(dev, impd1);
+
+ printk("IM-PD1 found at 0x%08lx\n",
+ (unsigned long)dev->resource.start);
+
+ for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) {
+ impd1->vcos[i].ops = &impd1_clk_ops,
+ impd1->vcos[i].owner = THIS_MODULE,
+ impd1->vcos[i].params = &impd1_vco_params,
+ impd1->vcos[i].data = impd1;
+ }
+ impd1->vcos[0].vcoreg = impd1->base + IMPD1_OSC1;
+ impd1->vcos[1].vcoreg = impd1->base + IMPD1_OSC2;
+
+ impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000",
+ dev->id);
+ impd1->clks[1] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00100",
+ dev->id);
+ impd1->clks[2] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00200",
+ dev->id);
+ for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
+ clkdev_add(impd1->clks[i]);
+
+ for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
+ struct impd1_device *idev = impd1_devs + i;
+ struct amba_device *d;
+ unsigned long pc_base;
+
+ pc_base = dev->resource.start + idev->offset;
+
+ d = kzalloc(sizeof(struct amba_device), GFP_KERNEL);
+ if (!d)
+ continue;
+
+ dev_set_name(&d->dev, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
+ d->dev.parent = &dev->dev;
+ d->res.start = dev->resource.start + idev->offset;
+ d->res.end = d->res.start + SZ_4K - 1;
+ d->res.flags = IORESOURCE_MEM;
+ d->irq[0] = dev->irq;
+ d->irq[1] = dev->irq;
+ d->periphid = idev->id;
+ d->dev.platform_data = idev->platform_data;
+
+ ret = amba_device_register(d, &dev->resource);
+ if (ret) {
+ dev_err(&d->dev, "unable to register device: %d\n", ret);
+ kfree(d);
+ }
+ }
+
+ return 0;
+
+ free_impd1:
+ if (impd1 && impd1->base)
+ iounmap(impd1->base);
+ kfree(impd1);
+ release_lm:
+ release_mem_region(dev->resource.start, SZ_4K);
+ return ret;
+}
+
+static int impd1_remove_one(struct device *dev, void *data)
+{
+ device_unregister(dev);
+ return 0;
+}
+
+static void impd1_remove(struct lm_device *dev)
+{
+ struct impd1_module *impd1 = lm_get_drvdata(dev);
+ int i;
+
+ device_for_each_child(&dev->dev, NULL, impd1_remove_one);
+
+ for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
+ clkdev_drop(impd1->clks[i]);
+
+ lm_set_drvdata(dev, NULL);
+
+ iounmap(impd1->base);
+ kfree(impd1);
+ release_mem_region(dev->resource.start, SZ_4K);
+}
+
+static struct lm_driver impd1_driver = {
+ .drv = {
+ .name = "impd1",
+ },
+ .probe = impd1_probe,
+ .remove = impd1_remove,
+};
+
+static int __init impd1_init(void)
+{
+ return lm_driver_register(&impd1_driver);
+}
+
+static void __exit impd1_exit(void)
+{
+ lm_driver_unregister(&impd1_driver);
+}
+
+module_init(impd1_init);
+module_exit(impd1_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Integrator/IM-PD1 logic module core driver");
+MODULE_AUTHOR("Deep Blue Solutions Ltd");
diff --git a/arch/arm/mach-integrator/include/mach/bits.h b/arch/arm/mach-integrator/include/mach/bits.h
new file mode 100644
index 00000000..09b024e0
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/bits.h
@@ -0,0 +1,61 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* DO NOT EDIT!! - this file automatically generated
+ * from .s file by awk -f s2h.awk
+ */
+/* Bit field definitions
+ * Copyright (C) ARM Limited 1998. All rights reserved.
+ */
+
+#ifndef __bits_h
+#define __bits_h 1
+
+#define BIT0 0x00000001
+#define BIT1 0x00000002
+#define BIT2 0x00000004
+#define BIT3 0x00000008
+#define BIT4 0x00000010
+#define BIT5 0x00000020
+#define BIT6 0x00000040
+#define BIT7 0x00000080
+#define BIT8 0x00000100
+#define BIT9 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+
+#endif
+
+/* END */
diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h
new file mode 100644
index 00000000..bfe07679
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/clkdev.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#include <linux/module.h>
+#include <plat/clock.h>
+
+struct clk {
+ unsigned long rate;
+ const struct clk_ops *ops;
+ struct module *owner;
+ const struct icst_params *params;
+ void __iomem *vcoreg;
+ void *data;
+};
+
+static inline int __clk_get(struct clk *clk)
+{
+ return try_module_get(clk->owner);
+}
+
+static inline void __clk_put(struct clk *clk)
+{
+ module_put(clk->owner);
+}
+
+#endif
diff --git a/arch/arm/mach-integrator/include/mach/cm.h b/arch/arm/mach-integrator/include/mach/cm.h
new file mode 100644
index 00000000..445d57ad
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/cm.h
@@ -0,0 +1,36 @@
+/*
+ * update the core module control register.
+ */
+void cm_control(u32, u32);
+
+#define CM_CTRL_LED (1 << 0)
+#define CM_CTRL_nMBDET (1 << 1)
+#define CM_CTRL_REMAP (1 << 2)
+#define CM_CTRL_RESET (1 << 3)
+
+/*
+ * Integrator/AP,PP2 specific
+ */
+#define CM_CTRL_HIGHVECTORS (1 << 4)
+#define CM_CTRL_BIGENDIAN (1 << 5)
+#define CM_CTRL_FASTBUS (1 << 6)
+#define CM_CTRL_SYNC (1 << 7)
+
+/*
+ * ARM926/946/966 Integrator/CP specific
+ */
+#define CM_CTRL_LCDBIASEN (1 << 8)
+#define CM_CTRL_LCDBIASUP (1 << 9)
+#define CM_CTRL_LCDBIASDN (1 << 10)
+#define CM_CTRL_LCDMUXSEL_MASK (7 << 11)
+#define CM_CTRL_LCDMUXSEL_GENLCD (1 << 11)
+#define CM_CTRL_LCDMUXSEL_VGA565_TFT555 (2 << 11)
+#define CM_CTRL_LCDMUXSEL_SHARPLCD (3 << 11)
+#define CM_CTRL_LCDMUXSEL_VGA555_TFT555 (4 << 11)
+#define CM_CTRL_LCDEN0 (1 << 14)
+#define CM_CTRL_LCDEN1 (1 << 15)
+#define CM_CTRL_STATIC1 (1 << 16)
+#define CM_CTRL_STATIC2 (1 << 17)
+#define CM_CTRL_STATIC (1 << 18)
+#define CM_CTRL_n24BITEN (1 << 19)
+#define CM_CTRL_EBIWP (1 << 20)
diff --git a/arch/arm/mach-integrator/include/mach/debug-macro.S b/arch/arm/mach-integrator/include/mach/debug-macro.S
new file mode 100644
index 00000000..a1f598fd
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/debug-macro.S
@@ -0,0 +1,20 @@
+/* arch/arm/mach-integrator/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+ .macro addruart, rp, rv
+ mov \rp, #0x16000000 @ physical base address
+ mov \rv, #0xf0000000 @ virtual base
+ add \rv, \rv, #0x16000000 >> 4
+ .endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-integrator/include/mach/entry-macro.S b/arch/arm/mach-integrator/include/mach/entry-macro.S
new file mode 100644
index 00000000..3d029c9f
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/entry-macro.S
@@ -0,0 +1,45 @@
+/*
+ * arch/arm/mach-integrator/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for Integrator platforms
+ *
+ * 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 <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/irqs.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+/* FIXME: should not be using soo many LDRs here */
+ ldr \base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
+ mov \irqnr, #IRQ_PIC_START
+ ldr \irqstat, [\base, #IRQ_STATUS] @ get masked status
+ ldr \base, =IO_ADDRESS(INTEGRATOR_HDR_BASE)
+ teq \irqstat, #0
+ ldreq \irqstat, [\base, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)]
+ moveq \irqnr, #IRQ_CIC_START
+
+1001: tst \irqstat, #15
+ bne 1002f
+ add \irqnr, \irqnr, #4
+ movs \irqstat, \irqstat, lsr #4
+ bne 1001b
+1002: tst \irqstat, #1
+ bne 1003f
+ add \irqnr, \irqnr, #1
+ movs \irqstat, \irqstat, lsr #1
+ bne 1002b
+1003: /* EQ will be set if no irqs pending */
+ .endm
+
diff --git a/arch/arm/mach-integrator/include/mach/hardware.h b/arch/arm/mach-integrator/include/mach/hardware.h
new file mode 100644
index 00000000..57f51ba1
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/hardware.h
@@ -0,0 +1,52 @@
+/*
+ * arch/arm/mach-integrator/include/mach/hardware.h
+ *
+ * This file contains the hardware definitions of the Integrator.
+ *
+ * Copyright (C) 1999 ARM Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+
+/*
+ * Where in virtual memory the IO devices (timers, system controllers
+ * and so on)
+ */
+#define IO_BASE 0xF0000000 // VA of IO
+#define IO_SIZE 0x0B000000 // How much?
+#define IO_START INTEGRATOR_HDR_BASE // PA of IO
+
+#define PCIMEM_BASE PCI_MEMORY_VADDR
+
+#define pcibios_assign_all_busses() 1
+
+#define PCIBIOS_MIN_IO 0x6000
+#define PCIBIOS_MIN_MEM 0x00100000
+
+/* macro to get at IO space when running virtually */
+#ifdef CONFIG_MMU
+#define IO_ADDRESS(x) (((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE)
+#else
+#define IO_ADDRESS(x) (x)
+#endif
+
+#define __io_address(n) ((void __iomem *)IO_ADDRESS(n))
+
+#endif
+
diff --git a/arch/arm/mach-integrator/include/mach/impd1.h b/arch/arm/mach-integrator/include/mach/impd1.h
new file mode 100644
index 00000000..d75de4b1
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/impd1.h
@@ -0,0 +1,18 @@
+#define IMPD1_OSC1 0x00
+#define IMPD1_OSC2 0x04
+#define IMPD1_LOCK 0x08
+#define IMPD1_LEDS 0x0c
+#define IMPD1_INT 0x10
+#define IMPD1_SW 0x14
+#define IMPD1_CTRL 0x18
+
+#define IMPD1_CTRL_DISP_LCD (0 << 0)
+#define IMPD1_CTRL_DISP_VGA (1 << 0)
+#define IMPD1_CTRL_DISP_LCD1 (2 << 0)
+#define IMPD1_CTRL_DISP_ENABLE (1 << 2)
+#define IMPD1_CTRL_DISP_MASK (7 << 0)
+
+struct device;
+
+void impd1_tweak_control(struct device *dev, u32 mask, u32 val);
+
diff --git a/arch/arm/mach-integrator/include/mach/io.h b/arch/arm/mach-integrator/include/mach/io.h
new file mode 100644
index 00000000..f21bb549
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/io.h
@@ -0,0 +1,36 @@
+/*
+ * arch/arm/mach-integrator/include/mach/io.h
+ *
+ * Copyright (C) 1999 ARM Limited
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffff
+
+/*
+ * WARNING: this has to mirror definitions in platform.h
+ */
+#define PCI_MEMORY_VADDR 0xe8000000
+#define PCI_CONFIG_VADDR 0xec000000
+#define PCI_V3_VADDR 0xed000000
+#define PCI_IO_VADDR 0xee000000
+
+#define __io(a) ((void __iomem *)(PCI_IO_VADDR + (a)))
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-integrator/include/mach/irqs.h b/arch/arm/mach-integrator/include/mach/irqs.h
new file mode 100644
index 00000000..1fbe6d19
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/irqs.h
@@ -0,0 +1,82 @@
+/*
+ * arch/arm/mach-integrator/include/mach/irqs.h
+ *
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Interrupt numbers
+ */
+#define IRQ_PIC_START 0
+#define IRQ_SOFTINT 0
+#define IRQ_UARTINT0 1
+#define IRQ_UARTINT1 2
+#define IRQ_KMIINT0 3
+#define IRQ_KMIINT1 4
+#define IRQ_TIMERINT0 5
+#define IRQ_TIMERINT1 6
+#define IRQ_TIMERINT2 7
+#define IRQ_RTCINT 8
+#define IRQ_AP_EXPINT0 9
+#define IRQ_AP_EXPINT1 10
+#define IRQ_AP_EXPINT2 11
+#define IRQ_AP_EXPINT3 12
+#define IRQ_AP_PCIINT0 13
+#define IRQ_AP_PCIINT1 14
+#define IRQ_AP_PCIINT2 15
+#define IRQ_AP_PCIINT3 16
+#define IRQ_AP_V3INT 17
+#define IRQ_AP_CPINT0 18
+#define IRQ_AP_CPINT1 19
+#define IRQ_AP_LBUSTIMEOUT 20
+#define IRQ_AP_APCINT 21
+#define IRQ_CP_CLCDCINT 22
+#define IRQ_CP_MMCIINT0 23
+#define IRQ_CP_MMCIINT1 24
+#define IRQ_CP_AACIINT 25
+#define IRQ_CP_CPPLDINT 26
+#define IRQ_CP_ETHINT 27
+#define IRQ_CP_TSPENINT 28
+#define IRQ_PIC_END 31
+
+#define IRQ_CIC_START 32
+#define IRQ_CM_SOFTINT 32
+#define IRQ_CM_COMMRX 33
+#define IRQ_CM_COMMTX 34
+#define IRQ_CIC_END 34
+
+/*
+ * IntegratorCP only
+ */
+#define IRQ_SIC_START 35
+#define IRQ_SIC_CP_SOFTINT 35
+#define IRQ_SIC_CP_RI0 36
+#define IRQ_SIC_CP_RI1 37
+#define IRQ_SIC_CP_CARDIN 38
+#define IRQ_SIC_CP_LMINT0 39
+#define IRQ_SIC_CP_LMINT1 40
+#define IRQ_SIC_CP_LMINT2 41
+#define IRQ_SIC_CP_LMINT3 42
+#define IRQ_SIC_CP_LMINT4 43
+#define IRQ_SIC_CP_LMINT5 44
+#define IRQ_SIC_CP_LMINT6 45
+#define IRQ_SIC_CP_LMINT7 46
+#define IRQ_SIC_END 46
+
+#define NR_IRQS 47
+
diff --git a/arch/arm/mach-integrator/include/mach/lm.h b/arch/arm/mach-integrator/include/mach/lm.h
new file mode 100644
index 00000000..28186b6f
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/lm.h
@@ -0,0 +1,23 @@
+
+struct lm_device {
+ struct device dev;
+ struct resource resource;
+ unsigned int irq;
+ unsigned int id;
+};
+
+struct lm_driver {
+ struct device_driver drv;
+ int (*probe)(struct lm_device *);
+ void (*remove)(struct lm_device *);
+ int (*suspend)(struct lm_device *, pm_message_t);
+ int (*resume)(struct lm_device *);
+};
+
+int lm_driver_register(struct lm_driver *drv);
+void lm_driver_unregister(struct lm_driver *drv);
+
+int lm_device_register(struct lm_device *dev);
+
+#define lm_get_drvdata(lm) dev_get_drvdata(&(lm)->dev)
+#define lm_set_drvdata(lm,d) dev_set_drvdata(&(lm)->dev, d)
diff --git a/arch/arm/mach-integrator/include/mach/memory.h b/arch/arm/mach-integrator/include/mach/memory.h
new file mode 100644
index 00000000..334d5e27
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/memory.h
@@ -0,0 +1,34 @@
+/*
+ * arch/arm/mach-integrator/include/mach/memory.h
+ *
+ * Copyright (C) 1999 ARM Limited
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PLAT_PHYS_OFFSET UL(0x00000000)
+
+#define BUS_OFFSET UL(0x80000000)
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET)
+#define __bus_to_virt(x) ((x) - BUS_OFFSET + PAGE_OFFSET)
+#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
+
+#endif
diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h
new file mode 100644
index 00000000..5e6ea5cf
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/platform.h
@@ -0,0 +1,414 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* DO NOT EDIT!! - this file automatically generated
+ * from .s file by awk -f s2h.awk
+ */
+/**************************************************************************
+ * * Copyright © ARM Limited 1998. All rights reserved.
+ * ***********************************************************************/
+/* ************************************************************************
+ *
+ * Integrator address map
+ *
+ * ***********************************************************************/
+
+#ifndef __address_h
+#define __address_h 1
+
+/* ========================================================================
+ * Integrator definitions
+ * ========================================================================
+ * ------------------------------------------------------------------------
+ * Memory definitions
+ * ------------------------------------------------------------------------
+ * Integrator memory map
+ *
+ */
+#define INTEGRATOR_BOOT_ROM_LO 0x00000000
+#define INTEGRATOR_BOOT_ROM_HI 0x20000000
+#define INTEGRATOR_BOOT_ROM_BASE INTEGRATOR_BOOT_ROM_HI /* Normal position */
+#define INTEGRATOR_BOOT_ROM_SIZE SZ_512K
+
+/*
+ * New Core Modules have different amounts of SSRAM, the amount of SSRAM
+ * fitted can be found in HDR_STAT.
+ *
+ * The symbol INTEGRATOR_SSRAM_SIZE is kept, however this now refers to
+ * the minimum amount of SSRAM fitted on any core module.
+ *
+ * New Core Modules also alias the SSRAM.
+ *
+ */
+#define INTEGRATOR_SSRAM_BASE 0x00000000
+#define INTEGRATOR_SSRAM_ALIAS_BASE 0x10800000
+#define INTEGRATOR_SSRAM_SIZE SZ_256K
+
+#define INTEGRATOR_FLASH_BASE 0x24000000
+#define INTEGRATOR_FLASH_SIZE SZ_32M
+
+#define INTEGRATOR_MBRD_SSRAM_BASE 0x28000000
+#define INTEGRATOR_MBRD_SSRAM_SIZE SZ_512K
+
+/*
+ * SDRAM is a SIMM therefore the size is not known.
+ *
+ */
+#define INTEGRATOR_SDRAM_BASE 0x00040000
+
+#define INTEGRATOR_SDRAM_ALIAS_BASE 0x80000000
+#define INTEGRATOR_HDR0_SDRAM_BASE 0x80000000
+#define INTEGRATOR_HDR1_SDRAM_BASE 0x90000000
+#define INTEGRATOR_HDR2_SDRAM_BASE 0xA0000000
+#define INTEGRATOR_HDR3_SDRAM_BASE 0xB0000000
+
+/*
+ * Logic expansion modules
+ *
+ */
+#define INTEGRATOR_LOGIC_MODULES_BASE 0xC0000000
+#define INTEGRATOR_LOGIC_MODULE0_BASE 0xC0000000
+#define INTEGRATOR_LOGIC_MODULE1_BASE 0xD0000000
+#define INTEGRATOR_LOGIC_MODULE2_BASE 0xE0000000
+#define INTEGRATOR_LOGIC_MODULE3_BASE 0xF0000000
+
+/* ------------------------------------------------------------------------
+ * Integrator header card registers
+ * ------------------------------------------------------------------------
+ *
+ */
+#define INTEGRATOR_HDR_ID_OFFSET 0x00
+#define INTEGRATOR_HDR_PROC_OFFSET 0x04
+#define INTEGRATOR_HDR_OSC_OFFSET 0x08
+#define INTEGRATOR_HDR_CTRL_OFFSET 0x0C
+#define INTEGRATOR_HDR_STAT_OFFSET 0x10
+#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
+#define INTEGRATOR_HDR_SDRAM_OFFSET 0x20
+#define INTEGRATOR_HDR_INIT_OFFSET 0x24 /* CM9x6 */
+#define INTEGRATOR_HDR_IC_OFFSET 0x40
+#define INTEGRATOR_HDR_SPDBASE_OFFSET 0x100
+#define INTEGRATOR_HDR_SPDTOP_OFFSET 0x200
+
+#define INTEGRATOR_HDR_BASE 0x10000000
+#define INTEGRATOR_HDR_ID (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_ID_OFFSET)
+#define INTEGRATOR_HDR_PROC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_PROC_OFFSET)
+#define INTEGRATOR_HDR_OSC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_OSC_OFFSET)
+#define INTEGRATOR_HDR_CTRL (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_CTRL_OFFSET)
+#define INTEGRATOR_HDR_STAT (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_STAT_OFFSET)
+#define INTEGRATOR_HDR_LOCK (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_LOCK_OFFSET)
+#define INTEGRATOR_HDR_SDRAM (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SDRAM_OFFSET)
+#define INTEGRATOR_HDR_INIT (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_INIT_OFFSET)
+#define INTEGRATOR_HDR_IC (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_IC_OFFSET)
+#define INTEGRATOR_HDR_SPDBASE (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SPDBASE_OFFSET)
+#define INTEGRATOR_HDR_SPDTOP (INTEGRATOR_HDR_BASE + INTEGRATOR_HDR_SPDTOP_OFFSET)
+
+#define INTEGRATOR_HDR_CTRL_LED 0x01
+#define INTEGRATOR_HDR_CTRL_MBRD_DETECH 0x02
+#define INTEGRATOR_HDR_CTRL_REMAP 0x04
+#define INTEGRATOR_HDR_CTRL_RESET 0x08
+#define INTEGRATOR_HDR_CTRL_HIGHVECTORS 0x10
+#define INTEGRATOR_HDR_CTRL_BIG_ENDIAN 0x20
+#define INTEGRATOR_HDR_CTRL_FASTBUS 0x40
+#define INTEGRATOR_HDR_CTRL_SYNC 0x80
+
+#define INTEGRATOR_HDR_OSC_CORE_10MHz 0x102
+#define INTEGRATOR_HDR_OSC_CORE_15MHz 0x107
+#define INTEGRATOR_HDR_OSC_CORE_20MHz 0x10C
+#define INTEGRATOR_HDR_OSC_CORE_25MHz 0x111
+#define INTEGRATOR_HDR_OSC_CORE_30MHz 0x116
+#define INTEGRATOR_HDR_OSC_CORE_35MHz 0x11B
+#define INTEGRATOR_HDR_OSC_CORE_40MHz 0x120
+#define INTEGRATOR_HDR_OSC_CORE_45MHz 0x125
+#define INTEGRATOR_HDR_OSC_CORE_50MHz 0x12A
+#define INTEGRATOR_HDR_OSC_CORE_55MHz 0x12F
+#define INTEGRATOR_HDR_OSC_CORE_60MHz 0x134
+#define INTEGRATOR_HDR_OSC_CORE_65MHz 0x139
+#define INTEGRATOR_HDR_OSC_CORE_70MHz 0x13E
+#define INTEGRATOR_HDR_OSC_CORE_75MHz 0x143
+#define INTEGRATOR_HDR_OSC_CORE_80MHz 0x148
+#define INTEGRATOR_HDR_OSC_CORE_85MHz 0x14D
+#define INTEGRATOR_HDR_OSC_CORE_90MHz 0x152
+#define INTEGRATOR_HDR_OSC_CORE_95MHz 0x157
+#define INTEGRATOR_HDR_OSC_CORE_100MHz 0x15C
+#define INTEGRATOR_HDR_OSC_CORE_105MHz 0x161
+#define INTEGRATOR_HDR_OSC_CORE_110MHz 0x166
+#define INTEGRATOR_HDR_OSC_CORE_115MHz 0x16B
+#define INTEGRATOR_HDR_OSC_CORE_120MHz 0x170
+#define INTEGRATOR_HDR_OSC_CORE_125MHz 0x175
+#define INTEGRATOR_HDR_OSC_CORE_130MHz 0x17A
+#define INTEGRATOR_HDR_OSC_CORE_135MHz 0x17F
+#define INTEGRATOR_HDR_OSC_CORE_140MHz 0x184
+#define INTEGRATOR_HDR_OSC_CORE_145MHz 0x189
+#define INTEGRATOR_HDR_OSC_CORE_150MHz 0x18E
+#define INTEGRATOR_HDR_OSC_CORE_155MHz 0x193
+#define INTEGRATOR_HDR_OSC_CORE_160MHz 0x198
+#define INTEGRATOR_HDR_OSC_CORE_MASK 0x7FF
+
+#define INTEGRATOR_HDR_OSC_MEM_10MHz 0x10C000
+#define INTEGRATOR_HDR_OSC_MEM_15MHz 0x116000
+#define INTEGRATOR_HDR_OSC_MEM_20MHz 0x120000
+#define INTEGRATOR_HDR_OSC_MEM_25MHz 0x12A000
+#define INTEGRATOR_HDR_OSC_MEM_30MHz 0x134000
+#define INTEGRATOR_HDR_OSC_MEM_33MHz 0x13A000
+#define INTEGRATOR_HDR_OSC_MEM_40MHz 0x148000
+#define INTEGRATOR_HDR_OSC_MEM_50MHz 0x15C000
+#define INTEGRATOR_HDR_OSC_MEM_60MHz 0x170000
+#define INTEGRATOR_HDR_OSC_MEM_66MHz 0x17C000
+#define INTEGRATOR_HDR_OSC_MEM_MASK 0x7FF000
+
+#define INTEGRATOR_HDR_OSC_BUS_MODE_CM7x0 0x0
+#define INTEGRATOR_HDR_OSC_BUS_MODE_CM9x0 0x0800000
+#define INTEGRATOR_HDR_OSC_BUS_MODE_CM9x6 0x1000000
+#define INTEGRATOR_HDR_OSC_BUS_MODE_CM10x00 0x1800000
+#define INTEGRATOR_HDR_OSC_BUS_MODE_MASK 0x1800000
+
+#define INTEGRATOR_HDR_SDRAM_SPD_OK (1 << 5)
+
+
+/* ------------------------------------------------------------------------
+ * Integrator system registers
+ * ------------------------------------------------------------------------
+ *
+ */
+
+/*
+ * System Controller
+ *
+ */
+#define INTEGRATOR_SC_ID_OFFSET 0x00
+#define INTEGRATOR_SC_OSC_OFFSET 0x04
+#define INTEGRATOR_SC_CTRLS_OFFSET 0x08
+#define INTEGRATOR_SC_CTRLC_OFFSET 0x0C
+#define INTEGRATOR_SC_DEC_OFFSET 0x10
+#define INTEGRATOR_SC_ARB_OFFSET 0x14
+#define INTEGRATOR_SC_PCIENABLE_OFFSET 0x18
+#define INTEGRATOR_SC_LOCK_OFFSET 0x1C
+
+#define INTEGRATOR_SC_BASE 0x11000000
+#define INTEGRATOR_SC_ID (INTEGRATOR_SC_BASE + INTEGRATOR_SC_ID_OFFSET)
+#define INTEGRATOR_SC_OSC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_OSC_OFFSET)
+#define INTEGRATOR_SC_CTRLS (INTEGRATOR_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
+#define INTEGRATOR_SC_CTRLC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
+#define INTEGRATOR_SC_DEC (INTEGRATOR_SC_BASE + INTEGRATOR_SC_DEC_OFFSET)
+#define INTEGRATOR_SC_ARB (INTEGRATOR_SC_BASE + INTEGRATOR_SC_ARB_OFFSET)
+#define INTEGRATOR_SC_PCIENABLE (INTEGRATOR_SC_BASE + INTEGRATOR_SC_PCIENABLE_OFFSET)
+#define INTEGRATOR_SC_LOCK (INTEGRATOR_SC_BASE + INTEGRATOR_SC_LOCK_OFFSET)
+
+#define INTEGRATOR_SC_OSC_SYS_10MHz 0x20
+#define INTEGRATOR_SC_OSC_SYS_15MHz 0x34
+#define INTEGRATOR_SC_OSC_SYS_20MHz 0x48
+#define INTEGRATOR_SC_OSC_SYS_25MHz 0x5C
+#define INTEGRATOR_SC_OSC_SYS_33MHz 0x7C
+#define INTEGRATOR_SC_OSC_SYS_MASK 0xFF
+
+#define INTEGRATOR_SC_OSC_PCI_25MHz 0x100
+#define INTEGRATOR_SC_OSC_PCI_33MHz 0x0
+#define INTEGRATOR_SC_OSC_PCI_MASK 0x100
+
+#define INTEGRATOR_SC_CTRL_SOFTRST (1 << 0)
+#define INTEGRATOR_SC_CTRL_nFLVPPEN (1 << 1)
+#define INTEGRATOR_SC_CTRL_nFLWP (1 << 2)
+#define INTEGRATOR_SC_CTRL_URTS0 (1 << 4)
+#define INTEGRATOR_SC_CTRL_UDTR0 (1 << 5)
+#define INTEGRATOR_SC_CTRL_URTS1 (1 << 6)
+#define INTEGRATOR_SC_CTRL_UDTR1 (1 << 7)
+
+/*
+ * External Bus Interface
+ *
+ */
+#define INTEGRATOR_EBI_BASE 0x12000000
+
+#define INTEGRATOR_EBI_CSR0_OFFSET 0x00
+#define INTEGRATOR_EBI_CSR1_OFFSET 0x04
+#define INTEGRATOR_EBI_CSR2_OFFSET 0x08
+#define INTEGRATOR_EBI_CSR3_OFFSET 0x0C
+#define INTEGRATOR_EBI_LOCK_OFFSET 0x20
+
+#define INTEGRATOR_EBI_CSR0 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR0_OFFSET)
+#define INTEGRATOR_EBI_CSR1 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
+#define INTEGRATOR_EBI_CSR2 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR2_OFFSET)
+#define INTEGRATOR_EBI_CSR3 (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_CSR3_OFFSET)
+#define INTEGRATOR_EBI_LOCK (INTEGRATOR_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
+
+#define INTEGRATOR_EBI_8_BIT 0x00
+#define INTEGRATOR_EBI_16_BIT 0x01
+#define INTEGRATOR_EBI_32_BIT 0x02
+#define INTEGRATOR_EBI_WRITE_ENABLE 0x04
+#define INTEGRATOR_EBI_SYNC 0x08
+#define INTEGRATOR_EBI_WS_2 0x00
+#define INTEGRATOR_EBI_WS_3 0x10
+#define INTEGRATOR_EBI_WS_4 0x20
+#define INTEGRATOR_EBI_WS_5 0x30
+#define INTEGRATOR_EBI_WS_6 0x40
+#define INTEGRATOR_EBI_WS_7 0x50
+#define INTEGRATOR_EBI_WS_8 0x60
+#define INTEGRATOR_EBI_WS_9 0x70
+#define INTEGRATOR_EBI_WS_10 0x80
+#define INTEGRATOR_EBI_WS_11 0x90
+#define INTEGRATOR_EBI_WS_12 0xA0
+#define INTEGRATOR_EBI_WS_13 0xB0
+#define INTEGRATOR_EBI_WS_14 0xC0
+#define INTEGRATOR_EBI_WS_15 0xD0
+#define INTEGRATOR_EBI_WS_16 0xE0
+#define INTEGRATOR_EBI_WS_17 0xF0
+
+
+#define INTEGRATOR_CT_BASE 0x13000000 /* Counter/Timers */
+#define INTEGRATOR_IC_BASE 0x14000000 /* Interrupt Controller */
+#define INTEGRATOR_RTC_BASE 0x15000000 /* Real Time Clock */
+#define INTEGRATOR_UART0_BASE 0x16000000 /* UART 0 */
+#define INTEGRATOR_UART1_BASE 0x17000000 /* UART 1 */
+#define INTEGRATOR_KBD_BASE 0x18000000 /* Keyboard */
+#define INTEGRATOR_MOUSE_BASE 0x19000000 /* Mouse */
+
+/*
+ * LED's & Switches
+ *
+ */
+#define INTEGRATOR_DBG_ALPHA_OFFSET 0x00
+#define INTEGRATOR_DBG_LEDS_OFFSET 0x04
+#define INTEGRATOR_DBG_SWITCH_OFFSET 0x08
+
+#define INTEGRATOR_DBG_BASE 0x1A000000
+#define INTEGRATOR_DBG_ALPHA (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_ALPHA_OFFSET)
+#define INTEGRATOR_DBG_LEDS (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_LEDS_OFFSET)
+#define INTEGRATOR_DBG_SWITCH (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_SWITCH_OFFSET)
+
+#define INTEGRATOR_AP_GPIO_BASE 0x1B000000 /* GPIO */
+
+#define INTEGRATOR_CP_MMC_BASE 0x1C000000 /* MMC */
+#define INTEGRATOR_CP_AACI_BASE 0x1D000000 /* AACI */
+#define INTEGRATOR_CP_ETH_BASE 0xC8000000 /* Ethernet */
+#define INTEGRATOR_CP_GPIO_BASE 0xC9000000 /* GPIO */
+#define INTEGRATOR_CP_SIC_BASE 0xCA000000 /* SIC */
+#define INTEGRATOR_CP_CTL_BASE 0xCB000000 /* CP system control */
+
+/* ------------------------------------------------------------------------
+ * KMI keyboard/mouse definitions
+ * ------------------------------------------------------------------------
+ */
+/* PS2 Keyboard interface */
+#define KMI0_BASE INTEGRATOR_KBD_BASE
+
+/* PS2 Mouse interface */
+#define KMI1_BASE INTEGRATOR_MOUSE_BASE
+
+/* KMI definitions are now in include/asm-arm/hardware/amba_kmi.h -- rmk */
+
+/* ------------------------------------------------------------------------
+ * Where in the memory map does PCI live?
+ * ------------------------------------------------------------------------
+ * This represents a fairly liberal usage of address space. Even though
+ * the V3 only has two windows (therefore we need to map stuff on the fly),
+ * we maintain the same addresses, even if they're not mapped.
+ *
+ */
+#define PHYS_PCI_MEM_BASE 0x40000000 /* 512M to xxx */
+/* unused 256M from A0000000-AFFFFFFF might be used for I2O ???
+ */
+#define PHYS_PCI_IO_BASE 0x60000000 /* 16M to xxx */
+/* unused (128-16)M from B1000000-B7FFFFFF
+ */
+#define PHYS_PCI_CONFIG_BASE 0x61000000 /* 16M to xxx */
+/* unused ((128-16)M - 64K) from XXX
+ */
+#define PHYS_PCI_V3_BASE 0x62000000
+
+/* ------------------------------------------------------------------------
+ * Integrator Interrupt Controllers
+ * ------------------------------------------------------------------------
+ *
+ * Offsets from interrupt controller base
+ *
+ * System Controller interrupt controller base is
+ *
+ * INTEGRATOR_IC_BASE + (header_number << 6)
+ *
+ * Core Module interrupt controller base is
+ *
+ * INTEGRATOR_HDR_IC
+ *
+ */
+#define IRQ_STATUS 0
+#define IRQ_RAW_STATUS 0x04
+#define IRQ_ENABLE 0x08
+#define IRQ_ENABLE_SET 0x08
+#define IRQ_ENABLE_CLEAR 0x0C
+
+#define INT_SOFT_SET 0x10
+#define INT_SOFT_CLEAR 0x14
+
+#define FIQ_STATUS 0x20
+#define FIQ_RAW_STATUS 0x24
+#define FIQ_ENABLE 0x28
+#define FIQ_ENABLE_SET 0x28
+#define FIQ_ENABLE_CLEAR 0x2C
+
+
+/* ------------------------------------------------------------------------
+ * Interrupts
+ * ------------------------------------------------------------------------
+ *
+ *
+ * Each Core Module has two interrupts controllers, one on the core module
+ * itself and one in the system controller on the motherboard. The
+ * READ_INT macro in target.s reads both interrupt controllers and returns
+ * a 32 bit bitmask, bits 0 to 23 are interrupts from the system controller
+ * and bits 24 to 31 are from the core module.
+ *
+ * The following definitions relate to the bitmask returned by READ_INT.
+ *
+ */
+
+/* ------------------------------------------------------------------------
+ * LED's
+ * ------------------------------------------------------------------------
+ *
+ */
+#define GREEN_LED 0x01
+#define YELLOW_LED 0x02
+#define RED_LED 0x04
+#define GREEN_LED_2 0x08
+#define ALL_LEDS 0x0F
+
+#define LED_BANK INTEGRATOR_DBG_LEDS
+
+/*
+ * Timer definitions
+ *
+ * Only use timer 1 & 2
+ * (both run at 24MHz and will need the clock divider set to 16).
+ *
+ * Timer 0 runs at bus frequency
+ */
+
+#define INTEGRATOR_TIMER0_BASE INTEGRATOR_CT_BASE
+#define INTEGRATOR_TIMER1_BASE (INTEGRATOR_CT_BASE + 0x100)
+#define INTEGRATOR_TIMER2_BASE (INTEGRATOR_CT_BASE + 0x200)
+
+#define TICKS_PER_uSEC 24
+
+/*
+ * These are useconds NOT ticks.
+ *
+ */
+#define mSEC_1 1000
+#define mSEC_10 (mSEC_1 * 10)
+
+#define INTEGRATOR_CSR_BASE 0x10000000
+#define INTEGRATOR_CSR_SIZE 0x10000000
+
+#endif
diff --git a/arch/arm/mach-integrator/include/mach/system.h b/arch/arm/mach-integrator/include/mach/system.h
new file mode 100644
index 00000000..e1551b8d
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/system.h
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-integrator/include/mach/system.h
+ *
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <mach/cm.h>
+
+static inline void arch_idle(void)
+{
+ /*
+ * This should do all the clock switching
+ * and wait for interrupt tricks
+ */
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ /*
+ * To reset, we hit the on-board reset register
+ * in the system FPGA
+ */
+ cm_control(CM_CTRL_RESET, CM_CTRL_RESET);
+}
+
+#endif
diff --git a/arch/arm/mach-integrator/include/mach/timex.h b/arch/arm/mach-integrator/include/mach/timex.h
new file mode 100644
index 00000000..1dcb4202
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/timex.h
@@ -0,0 +1,26 @@
+/*
+ * arch/arm/mach-integrator/include/mach/timex.h
+ *
+ * Integrator architecture timex specifications
+ *
+ * Copyright (C) 1999 ARM Limited
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * ??
+ */
+#define CLOCK_TICK_RATE (50000000 / 16)
diff --git a/arch/arm/mach-integrator/include/mach/uncompress.h b/arch/arm/mach-integrator/include/mach/uncompress.h
new file mode 100644
index 00000000..30452f00
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/uncompress.h
@@ -0,0 +1,50 @@
+/*
+ * arch/arm/mach-integrator/include/mach/uncompress.h
+ *
+ * Copyright (C) 1999 ARM Limited
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define AMBA_UART_DR (*(volatile unsigned char *)0x16000000)
+#define AMBA_UART_LCRH (*(volatile unsigned char *)0x16000008)
+#define AMBA_UART_LCRM (*(volatile unsigned char *)0x1600000c)
+#define AMBA_UART_LCRL (*(volatile unsigned char *)0x16000010)
+#define AMBA_UART_CR (*(volatile unsigned char *)0x16000014)
+#define AMBA_UART_FR (*(volatile unsigned char *)0x16000018)
+
+/*
+ * This does not append a newline
+ */
+static void putc(int c)
+{
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
+
+ AMBA_UART_DR = c;
+}
+
+static inline void flush(void)
+{
+ while (AMBA_UART_FR & (1 << 3))
+ barrier();
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-integrator/include/mach/vmalloc.h b/arch/arm/mach-integrator/include/mach/vmalloc.h
new file mode 100644
index 00000000..2f5a2baf
--- /dev/null
+++ b/arch/arm/mach-integrator/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-integrator/include/mach/vmalloc.h
+ *
+ * Copyright (C) 2000 Russell King.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define VMALLOC_END 0xd0000000UL
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
new file mode 100644
index 00000000..fcf0ae95
--- /dev/null
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -0,0 +1,467 @@
+/*
+ * linux/arch/arm/mach-integrator/integrator_ap.c
+ *
+ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/syscore_ops.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/kmi.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mtd/physmap.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <asm/hardware/arm_timer.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/param.h> /* HZ */
+#include <asm/mach-types.h>
+
+#include <mach/lm.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <plat/fpga-irq.h>
+
+#include "common.h"
+
+/*
+ * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
+ * is the (PA >> 12).
+ *
+ * Setup a VA for the Integrator interrupt controller (for header #0,
+ * just for now).
+ */
+#define VA_IC_BASE __io_address(INTEGRATOR_IC_BASE)
+#define VA_SC_BASE __io_address(INTEGRATOR_SC_BASE)
+#define VA_EBI_BASE __io_address(INTEGRATOR_EBI_BASE)
+#define VA_CMIC_BASE __io_address(INTEGRATOR_HDR_IC)
+
+/*
+ * Logical Physical
+ * e8000000 40000000 PCI memory PHYS_PCI_MEM_BASE (max 512M)
+ * ec000000 61000000 PCI config space PHYS_PCI_CONFIG_BASE (max 16M)
+ * ed000000 62000000 PCI V3 regs PHYS_PCI_V3_BASE (max 64k)
+ * ee000000 60000000 PCI IO PHYS_PCI_IO_BASE (max 16M)
+ * ef000000 Cache flush
+ * f1000000 10000000 Core module registers
+ * f1100000 11000000 System controller registers
+ * f1200000 12000000 EBI registers
+ * f1300000 13000000 Counter/Timer
+ * f1400000 14000000 Interrupt controller
+ * f1600000 16000000 UART 0
+ * f1700000 17000000 UART 1
+ * f1a00000 1a000000 Debug LEDs
+ * f1b00000 1b000000 GPIO
+ */
+
+static struct map_desc ap_io_desc[] __initdata = {
+ {
+ .virtual = IO_ADDRESS(INTEGRATOR_HDR_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_HDR_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_SC_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_SC_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_EBI_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_EBI_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_CT_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_CT_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_UART1_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_UART1_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_DBG_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_DBG_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_AP_GPIO_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_AP_GPIO_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = PCI_MEMORY_VADDR,
+ .pfn = __phys_to_pfn(PHYS_PCI_MEM_BASE),
+ .length = SZ_16M,
+ .type = MT_DEVICE
+ }, {
+ .virtual = PCI_CONFIG_VADDR,
+ .pfn = __phys_to_pfn(PHYS_PCI_CONFIG_BASE),
+ .length = SZ_16M,
+ .type = MT_DEVICE
+ }, {
+ .virtual = PCI_V3_VADDR,
+ .pfn = __phys_to_pfn(PHYS_PCI_V3_BASE),
+ .length = SZ_64K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = PCI_IO_VADDR,
+ .pfn = __phys_to_pfn(PHYS_PCI_IO_BASE),
+ .length = SZ_64K,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init ap_map_io(void)
+{
+ iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
+}
+
+#define INTEGRATOR_SC_VALID_INT 0x003fffff
+
+static struct fpga_irq_data sc_irq_data = {
+ .base = VA_IC_BASE,
+ .irq_start = 0,
+ .chip.name = "SC",
+};
+
+static void __init ap_init_irq(void)
+{
+ /* Disable all interrupts initially. */
+ /* Do the core module ones */
+ writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
+
+ /* do the header card stuff next */
+ writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
+ writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
+
+ fpga_irq_init(-1, INTEGRATOR_SC_VALID_INT, &sc_irq_data);
+}
+
+#ifdef CONFIG_PM
+static unsigned long ic_irq_enable;
+
+static int irq_suspend(void)
+{
+ ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
+ return 0;
+}
+
+static void irq_resume(void)
+{
+ /* disable all irq sources */
+ writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
+ writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
+ writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
+
+ writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
+}
+#else
+#define irq_suspend NULL
+#define irq_resume NULL
+#endif
+
+static struct syscore_ops irq_syscore_ops = {
+ .suspend = irq_suspend,
+ .resume = irq_resume,
+};
+
+static int __init irq_syscore_init(void)
+{
+ register_syscore_ops(&irq_syscore_ops);
+
+ return 0;
+}
+
+device_initcall(irq_syscore_init);
+
+/*
+ * Flash handling.
+ */
+#define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
+#define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
+#define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
+#define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
+
+static int ap_flash_init(struct platform_device *dev)
+{
+ u32 tmp;
+
+ writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
+
+ tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
+ writel(tmp, EBI_CSR1);
+
+ if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
+ writel(0xa05f, EBI_LOCK);
+ writel(tmp, EBI_CSR1);
+ writel(0, EBI_LOCK);
+ }
+ return 0;
+}
+
+static void ap_flash_exit(struct platform_device *dev)
+{
+ u32 tmp;
+
+ writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
+
+ tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
+ writel(tmp, EBI_CSR1);
+
+ if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
+ writel(0xa05f, EBI_LOCK);
+ writel(tmp, EBI_CSR1);
+ writel(0, EBI_LOCK);
+ }
+}
+
+static void ap_flash_set_vpp(struct platform_device *pdev, int on)
+{
+ void __iomem *reg = on ? SC_CTRLS : SC_CTRLC;
+
+ writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
+}
+
+static struct physmap_flash_data ap_flash_data = {
+ .width = 4,
+ .init = ap_flash_init,
+ .exit = ap_flash_exit,
+ .set_vpp = ap_flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+ .start = INTEGRATOR_FLASH_BASE,
+ .end = INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &ap_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &cfi_flash_resource,
+};
+
+static void __init ap_init(void)
+{
+ unsigned long sc_dec;
+ int i;
+
+ platform_device_register(&cfi_flash_device);
+
+ sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
+ for (i = 0; i < 4; i++) {
+ struct lm_device *lmdev;
+
+ if ((sc_dec & (16 << i)) == 0)
+ continue;
+
+ lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
+ if (!lmdev)
+ continue;
+
+ lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
+ lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
+ lmdev->resource.flags = IORESOURCE_MEM;
+ lmdev->irq = IRQ_AP_EXPINT0 + i;
+ lmdev->id = i;
+
+ lm_device_register(lmdev);
+ }
+}
+
+/*
+ * Where is the timer (VA)?
+ */
+#define TIMER0_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER0_BASE)
+#define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE)
+#define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE)
+
+/*
+ * How long is the timer interval?
+ */
+#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
+#if TIMER_INTERVAL >= 0x100000
+#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
+#elif TIMER_INTERVAL >= 0x10000
+#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
+#else
+#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
+#endif
+
+static unsigned long timer_reload;
+
+static void integrator_clocksource_init(u32 khz)
+{
+ void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
+ u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
+
+ if (khz >= 1500) {
+ khz /= 16;
+ ctrl |= TIMER_CTRL_DIV16;
+ }
+
+ writel(0xffff, base + TIMER_LOAD);
+ writel(ctrl, base + TIMER_CTRL);
+
+ clocksource_mmio_init(base + TIMER_VALUE, "timer2",
+ khz * 1000, 200, 16, clocksource_mmio_readl_down);
+}
+
+static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = dev_id;
+
+ /* clear the interrupt */
+ writel(1, clkevt_base + TIMER_INTCLR);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
+{
+ u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
+
+ BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT);
+
+ if (mode == CLOCK_EVT_MODE_PERIODIC) {
+ writel(ctrl, clkevt_base + TIMER_CTRL);
+ writel(timer_reload, clkevt_base + TIMER_LOAD);
+ ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
+ }
+
+ writel(ctrl, clkevt_base + TIMER_CTRL);
+}
+
+static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
+{
+ unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
+
+ writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
+ writel(next, clkevt_base + TIMER_LOAD);
+ writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
+
+ return 0;
+}
+
+static struct clock_event_device integrator_clockevent = {
+ .name = "timer1",
+ .shift = 34,
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+ .set_mode = clkevt_set_mode,
+ .set_next_event = clkevt_set_next_event,
+ .rating = 300,
+ .cpumask = cpu_all_mask,
+};
+
+static struct irqaction integrator_timer_irq = {
+ .name = "timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = integrator_timer_interrupt,
+ .dev_id = &integrator_clockevent,
+};
+
+static void integrator_clockevent_init(u32 khz)
+{
+ struct clock_event_device *evt = &integrator_clockevent;
+ unsigned int ctrl = 0;
+
+ if (khz * 1000 > 0x100000 * HZ) {
+ khz /= 256;
+ ctrl |= TIMER_CTRL_DIV256;
+ } else if (khz * 1000 > 0x10000 * HZ) {
+ khz /= 16;
+ ctrl |= TIMER_CTRL_DIV16;
+ }
+
+ timer_reload = khz * 1000 / HZ;
+ writel(ctrl, clkevt_base + TIMER_CTRL);
+
+ evt->irq = IRQ_TIMERINT1;
+ evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift);
+ evt->max_delta_ns = clockevent_delta2ns(0xffff, evt);
+ evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
+
+ setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
+ clockevents_register_device(evt);
+}
+
+/*
+ * Set up timer(s).
+ */
+static void __init ap_init_timer(void)
+{
+ u32 khz = TICKS_PER_uSEC * 1000;
+
+ writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+ writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+ writel(0, TIMER2_VA_BASE + TIMER_CTRL);
+
+ integrator_clocksource_init(khz);
+ integrator_clockevent_init(khz);
+}
+
+static struct sys_timer ap_timer = {
+ .init = ap_init_timer,
+};
+
+MACHINE_START(INTEGRATOR, "ARM-Integrator")
+ /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
+ .boot_params = 0x00000100,
+ .reserve = integrator_reserve,
+ .map_io = ap_map_io,
+ .init_early = integrator_init_early,
+ .init_irq = ap_init_irq,
+ .timer = &ap_timer,
+ .init_machine = ap_init,
+MACHINE_END
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
new file mode 100644
index 00000000..4eb03ab5
--- /dev/null
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -0,0 +1,502 @@
+/*
+ * linux/arch/arm/mach-integrator/integrator_cp.c
+ *
+ * Copyright (C) 2003 Deep Blue Solutions Ltd
+ *
+ * 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; either version 2 of the License.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/kmi.h>
+#include <linux/amba/clcd.h>
+#include <linux/amba/mmci.h>
+#include <linux/io.h>
+#include <linux/gfp.h>
+#include <linux/clkdev.h>
+#include <linux/mtd/physmap.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/arm_timer.h>
+#include <asm/hardware/icst.h>
+
+#include <mach/cm.h>
+#include <mach/lm.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <asm/hardware/timer-sp.h>
+
+#include <plat/clcd.h>
+#include <plat/fpga-irq.h>
+#include <plat/sched_clock.h>
+
+#include "common.h"
+
+#define INTCP_PA_FLASH_BASE 0x24000000
+#define INTCP_FLASH_SIZE SZ_32M
+
+#define INTCP_PA_CLCD_BASE 0xc0000000
+
+#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40)
+#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE)
+#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE)
+
+#define INTCP_ETH_SIZE 0x10
+
+#define INTCP_VA_CTRL_BASE IO_ADDRESS(INTEGRATOR_CP_CTL_BASE)
+#define INTCP_FLASHPROG 0x04
+#define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0)
+#define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1)
+
+/*
+ * Logical Physical
+ * f1000000 10000000 Core module registers
+ * f1100000 11000000 System controller registers
+ * f1200000 12000000 EBI registers
+ * f1300000 13000000 Counter/Timer
+ * f1400000 14000000 Interrupt controller
+ * f1600000 16000000 UART 0
+ * f1700000 17000000 UART 1
+ * f1a00000 1a000000 Debug LEDs
+ * fc900000 c9000000 GPIO
+ * fca00000 ca000000 SIC
+ * fcb00000 cb000000 CP system control
+ */
+
+static struct map_desc intcp_io_desc[] __initdata = {
+ {
+ .virtual = IO_ADDRESS(INTEGRATOR_HDR_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_HDR_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_SC_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_SC_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_EBI_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_EBI_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_CT_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_CT_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_UART1_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_UART1_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_DBG_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_DBG_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_CP_GPIO_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_CP_GPIO_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IO_ADDRESS(INTEGRATOR_CP_CTL_BASE),
+ .pfn = __phys_to_pfn(INTEGRATOR_CP_CTL_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init intcp_map_io(void)
+{
+ iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
+}
+
+static struct fpga_irq_data cic_irq_data = {
+ .base = INTCP_VA_CIC_BASE,
+ .irq_start = IRQ_CIC_START,
+ .chip.name = "CIC",
+};
+
+static struct fpga_irq_data pic_irq_data = {
+ .base = INTCP_VA_PIC_BASE,
+ .irq_start = IRQ_PIC_START,
+ .chip.name = "PIC",
+};
+
+static struct fpga_irq_data sic_irq_data = {
+ .base = INTCP_VA_SIC_BASE,
+ .irq_start = IRQ_SIC_START,
+ .chip.name = "SIC",
+};
+
+static void __init intcp_init_irq(void)
+{
+ u32 pic_mask, sic_mask;
+
+ pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
+ pic_mask |= (~((~0u) << (29 - 22))) << 22;
+ sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
+
+ /*
+ * Disable all interrupt sources
+ */
+ writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
+ writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
+ writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
+ writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
+ writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
+ writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
+
+ fpga_irq_init(-1, pic_mask, &pic_irq_data);
+
+ fpga_irq_init(-1, ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)),
+ &cic_irq_data);
+
+ fpga_irq_init(IRQ_CP_CPPLDINT, sic_mask, &sic_irq_data);
+}
+
+/*
+ * Clock handling
+ */
+#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
+#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c)
+
+static const struct icst_params cp_auxvco_params = {
+ .ref = 24000000,
+ .vco_max = ICST525_VCO_MAX_5V,
+ .vco_min = ICST525_VCO_MIN,
+ .vd_min = 8,
+ .vd_max = 263,
+ .rd_min = 3,
+ .rd_max = 65,
+ .s2div = icst525_s2div,
+ .idx2s = icst525_idx2s,
+};
+
+static void cp_auxvco_set(struct clk *clk, struct icst_vco vco)
+{
+ u32 val;
+
+ val = readl(clk->vcoreg) & ~0x7ffff;
+ val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+ writel(0xa05f, CM_LOCK);
+ writel(val, clk->vcoreg);
+ writel(0, CM_LOCK);
+}
+
+static const struct clk_ops cp_auxclk_ops = {
+ .round = icst_clk_round,
+ .set = icst_clk_set,
+ .setvco = cp_auxvco_set,
+};
+
+static struct clk cp_auxclk = {
+ .ops = &cp_auxclk_ops,
+ .params = &cp_auxvco_params,
+ .vcoreg = CM_AUXOSC,
+};
+
+static struct clk sp804_clk = {
+ .rate = 1000000,
+};
+
+static struct clk_lookup cp_lookups[] = {
+ { /* CLCD */
+ .dev_id = "mb:c0",
+ .clk = &cp_auxclk,
+ }, { /* SP804 timers */
+ .dev_id = "sp804",
+ .clk = &sp804_clk,
+ },
+};
+
+/*
+ * Flash handling.
+ */
+static int intcp_flash_init(struct platform_device *dev)
+{
+ u32 val;
+
+ val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+ val |= CINTEGRATOR_FLASHPROG_FLWREN;
+ writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+
+ return 0;
+}
+
+static void intcp_flash_exit(struct platform_device *dev)
+{
+ u32 val;
+
+ val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+ val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
+ writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+}
+
+static void intcp_flash_set_vpp(struct platform_device *pdev, int on)
+{
+ u32 val;
+
+ val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+ if (on)
+ val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
+ else
+ val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
+ writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+}
+
+static struct physmap_flash_data intcp_flash_data = {
+ .width = 4,
+ .init = intcp_flash_init,
+ .exit = intcp_flash_exit,
+ .set_vpp = intcp_flash_set_vpp,
+};
+
+static struct resource intcp_flash_resource = {
+ .start = INTCP_PA_FLASH_BASE,
+ .end = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device intcp_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &intcp_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &intcp_flash_resource,
+};
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = INTEGRATOR_CP_ETH_BASE,
+ .end = INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_CP_ETHINT,
+ .end = IRQ_CP_ETHINT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct platform_device *intcp_devs[] __initdata = {
+ &intcp_flash_device,
+ &smc91x_device,
+};
+
+/*
+ * It seems that the card insertion interrupt remains active after
+ * we've acknowledged it. We therefore ignore the interrupt, and
+ * rely on reading it from the SIC. This also means that we must
+ * clear the latched interrupt.
+ */
+static unsigned int mmc_status(struct device *dev)
+{
+ unsigned int status = readl(IO_ADDRESS(0xca000000 + 4));
+ writel(8, IO_ADDRESS(INTEGRATOR_CP_CTL_BASE + 8));
+
+ return status & 8;
+}
+
+static struct mmci_platform_data mmc_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .status = mmc_status,
+ .gpio_wp = -1,
+ .gpio_cd = -1,
+};
+
+static struct amba_device mmc_device = {
+ .dev = {
+ .init_name = "mb:1c",
+ .platform_data = &mmc_data,
+ },
+ .res = {
+ .start = INTEGRATOR_CP_MMC_BASE,
+ .end = INTEGRATOR_CP_MMC_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 },
+ .periphid = 0,
+};
+
+static struct amba_device aaci_device = {
+ .dev = {
+ .init_name = "mb:1d",
+ },
+ .res = {
+ .start = INTEGRATOR_CP_AACI_BASE,
+ .end = INTEGRATOR_CP_AACI_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_CP_AACIINT, NO_IRQ },
+ .periphid = 0,
+};
+
+
+/*
+ * CLCD support
+ */
+/*
+ * Ensure VGA is selected.
+ */
+static void cp_clcd_enable(struct clcd_fb *fb)
+{
+ struct fb_var_screeninfo *var = &fb->fb.var;
+ u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
+
+ if (var->bits_per_pixel <= 8 ||
+ (var->bits_per_pixel == 16 && var->green.length == 5))
+ /* Pseudocolor, RGB555, BGR555 */
+ val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555;
+ else if (fb->fb.var.bits_per_pixel <= 16)
+ /* truecolor RGB565 */
+ val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555;
+ else
+ val = 0; /* no idea for this, don't trust the docs */
+
+ cm_control(CM_CTRL_LCDMUXSEL_MASK|
+ CM_CTRL_LCDEN0|
+ CM_CTRL_LCDEN1|
+ CM_CTRL_STATIC1|
+ CM_CTRL_STATIC2|
+ CM_CTRL_STATIC|
+ CM_CTRL_n24BITEN, val);
+}
+
+static int cp_clcd_setup(struct clcd_fb *fb)
+{
+ fb->panel = versatile_clcd_get_panel("VGA");
+ if (!fb->panel)
+ return -EINVAL;
+
+ return versatile_clcd_setup_dma(fb, SZ_1M);
+}
+
+static struct clcd_board clcd_data = {
+ .name = "Integrator/CP",
+ .caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888,
+ .check = clcdfb_check,
+ .decode = clcdfb_decode,
+ .enable = cp_clcd_enable,
+ .setup = cp_clcd_setup,
+ .mmap = versatile_clcd_mmap_dma,
+ .remove = versatile_clcd_remove_dma,
+};
+
+static struct amba_device clcd_device = {
+ .dev = {
+ .init_name = "mb:c0",
+ .coherent_dma_mask = ~0,
+ .platform_data = &clcd_data,
+ },
+ .res = {
+ .start = INTCP_PA_CLCD_BASE,
+ .end = INTCP_PA_CLCD_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .dma_mask = ~0,
+ .irq = { IRQ_CP_CLCDCINT, NO_IRQ },
+ .periphid = 0,
+};
+
+static struct amba_device *amba_devs[] __initdata = {
+ &mmc_device,
+ &aaci_device,
+ &clcd_device,
+};
+
+#define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)
+
+static void __init intcp_init_early(void)
+{
+ clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
+
+ integrator_init_early();
+
+#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK
+ versatile_sched_clock_init(REFCOUNTER, 24000000);
+#endif
+}
+
+static void __init intcp_init(void)
+{
+ int i;
+
+ platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
+
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+ amba_device_register(d, &iomem_resource);
+ }
+}
+
+#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
+#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
+#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
+
+static void __init intcp_timer_init(void)
+{
+ writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+ writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+ writel(0, TIMER2_VA_BASE + TIMER_CTRL);
+
+ sp804_clocksource_init(TIMER2_VA_BASE, "timer2");
+ sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1");
+}
+
+static struct sys_timer cp_timer = {
+ .init = intcp_timer_init,
+};
+
+MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
+ /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
+ .boot_params = 0x00000100,
+ .reserve = integrator_reserve,
+ .map_io = intcp_map_io,
+ .init_early = intcp_init_early,
+ .init_irq = intcp_init_irq,
+ .timer = &cp_timer,
+ .init_machine = intcp_init,
+MACHINE_END
diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c
new file mode 100644
index 00000000..28be186a
--- /dev/null
+++ b/arch/arm/mach-integrator/leds.c
@@ -0,0 +1,91 @@
+/*
+ * linux/arch/arm/mach-integrator/leds.c
+ *
+ * Integrator/AP and Integrator/CP LED control routines
+ *
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/cm.h>
+
+static int saved_leds;
+
+static void integrator_leds_event(led_event_t ledevt)
+{
+ unsigned long flags;
+ const unsigned int dbg_base = IO_ADDRESS(INTEGRATOR_DBG_BASE);
+ unsigned int update_alpha_leds;
+
+ // yup, change the LEDs
+ local_irq_save(flags);
+ update_alpha_leds = 0;
+
+ switch(ledevt) {
+ case led_idle_start:
+ cm_control(CM_CTRL_LED, 0);
+ break;
+
+ case led_idle_end:
+ cm_control(CM_CTRL_LED, CM_CTRL_LED);
+ break;
+
+ case led_timer:
+ saved_leds ^= GREEN_LED;
+ update_alpha_leds = 1;
+ break;
+
+ case led_red_on:
+ saved_leds |= RED_LED;
+ update_alpha_leds = 1;
+ break;
+
+ case led_red_off:
+ saved_leds &= ~RED_LED;
+ update_alpha_leds = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ if (update_alpha_leds) {
+ while (__raw_readl(dbg_base + INTEGRATOR_DBG_ALPHA_OFFSET) & 1);
+ __raw_writel(saved_leds, dbg_base + INTEGRATOR_DBG_LEDS_OFFSET);
+ }
+ local_irq_restore(flags);
+}
+
+static int __init leds_init(void)
+{
+ if (machine_is_integrator() || machine_is_cintegrator())
+ leds_event = integrator_leds_event;
+
+ return 0;
+}
+
+core_initcall(leds_init);
diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c
new file mode 100644
index 00000000..f52c7af3
--- /dev/null
+++ b/arch/arm/mach-integrator/lm.c
@@ -0,0 +1,99 @@
+/*
+ * linux/arch/arm/mach-integrator/lm.c
+ *
+ * Copyright (C) 2003 Deep Blue Solutions Ltd, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+
+#include <mach/lm.h>
+
+#define to_lm_device(d) container_of(d, struct lm_device, dev)
+#define to_lm_driver(d) container_of(d, struct lm_driver, drv)
+
+static int lm_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
+static int lm_bus_probe(struct device *dev)
+{
+ struct lm_device *lmdev = to_lm_device(dev);
+ struct lm_driver *lmdrv = to_lm_driver(dev->driver);
+
+ return lmdrv->probe(lmdev);
+}
+
+static int lm_bus_remove(struct device *dev)
+{
+ struct lm_device *lmdev = to_lm_device(dev);
+ struct lm_driver *lmdrv = to_lm_driver(dev->driver);
+
+ if (lmdrv->remove)
+ lmdrv->remove(lmdev);
+ return 0;
+}
+
+static struct bus_type lm_bustype = {
+ .name = "logicmodule",
+ .match = lm_match,
+ .probe = lm_bus_probe,
+ .remove = lm_bus_remove,
+// .suspend = lm_bus_suspend,
+// .resume = lm_bus_resume,
+};
+
+static int __init lm_init(void)
+{
+ return bus_register(&lm_bustype);
+}
+
+postcore_initcall(lm_init);
+
+int lm_driver_register(struct lm_driver *drv)
+{
+ drv->drv.bus = &lm_bustype;
+ return driver_register(&drv->drv);
+}
+
+void lm_driver_unregister(struct lm_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+
+static void lm_device_release(struct device *dev)
+{
+ struct lm_device *d = to_lm_device(dev);
+
+ kfree(d);
+}
+
+int lm_device_register(struct lm_device *dev)
+{
+ int ret;
+
+ dev->dev.release = lm_device_release;
+ dev->dev.bus = &lm_bustype;
+
+ ret = dev_set_name(&dev->dev, "lm%d", dev->id);
+ if (ret)
+ return ret;
+ dev->resource.name = dev_name(&dev->dev);
+
+ ret = request_resource(&iomem_resource, &dev->resource);
+ if (ret == 0) {
+ ret = device_register(&dev->dev);
+ if (ret)
+ release_resource(&dev->resource);
+ }
+ return ret;
+}
+
+EXPORT_SYMBOL(lm_driver_register);
+EXPORT_SYMBOL(lm_driver_unregister);
diff --git a/arch/arm/mach-integrator/pci.c b/arch/arm/mach-integrator/pci.c
new file mode 100644
index 00000000..2fdb9543
--- /dev/null
+++ b/arch/arm/mach-integrator/pci.c
@@ -0,0 +1,124 @@
+/*
+ * linux/arch/arm/mach-integrator/pci-integrator.c
+ *
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * PCI functions for Integrator
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * A small note about bridges and interrupts. The DECchip 21050 (and
+ * later) adheres to the PCI-PCI bridge specification. This says that
+ * the interrupts on the other side of a bridge are swizzled in the
+ * following manner:
+ *
+ * Dev Interrupt Interrupt
+ * Pin on Pin on
+ * Device Connector
+ *
+ * 4 A A
+ * B B
+ * C C
+ * D D
+ *
+ * 5 A B
+ * B C
+ * C D
+ * D A
+ *
+ * 6 A C
+ * B D
+ * C A
+ * D B
+ *
+ * 7 A D
+ * B A
+ * C B
+ * D C
+ *
+ * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
+ * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
+ */
+
+/*
+ * This routine handles multiple bridges.
+ */
+static u8 __init integrator_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+ int pin = *pinp;
+
+ if (pin == 0)
+ pin = 1;
+
+ while (dev->bus->self) {
+ pin = pci_swizzle_interrupt_pin(dev, pin);
+ /*
+ * move up the chain of bridges, swizzling as we go.
+ */
+ dev = dev->bus->self;
+ }
+ *pinp = pin;
+
+ return PCI_SLOT(dev->devfn);
+}
+
+static int irq_tab[4] __initdata = {
+ IRQ_AP_PCIINT0, IRQ_AP_PCIINT1, IRQ_AP_PCIINT2, IRQ_AP_PCIINT3
+};
+
+/*
+ * map the specified device/slot/pin to an IRQ. This works out such
+ * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1.
+ */
+static int __init integrator_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int intnr = ((slot - 9) + (pin - 1)) & 3;
+
+ return irq_tab[intnr];
+}
+
+extern void pci_v3_init(void *);
+
+static struct hw_pci integrator_pci __initdata = {
+ .swizzle = integrator_swizzle,
+ .map_irq = integrator_map_irq,
+ .setup = pci_v3_setup,
+ .nr_controllers = 1,
+ .scan = pci_v3_scan_bus,
+ .preinit = pci_v3_preinit,
+ .postinit = pci_v3_postinit,
+};
+
+static int __init integrator_pci_init(void)
+{
+ if (machine_is_integrator())
+ pci_common_init(&integrator_pci);
+ return 0;
+}
+
+subsys_initcall(integrator_pci_init);
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
new file mode 100644
index 00000000..6467d99f
--- /dev/null
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -0,0 +1,609 @@
+/*
+ * linux/arch/arm/mach-integrator/pci_v3.c
+ *
+ * PCI functions for V3 host PCI bridge
+ *
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <asm/irq.h>
+#include <asm/signal.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/irq_regs.h>
+
+#include <asm/hardware/pci_v3.h>
+
+/*
+ * The V3 PCI interface chip in Integrator provides several windows from
+ * local bus memory into the PCI memory areas. Unfortunately, there
+ * are not really enough windows for our usage, therefore we reuse
+ * one of the windows for access to PCI configuration space. The
+ * memory map is as follows:
+ *
+ * Local Bus Memory Usage
+ *
+ * 40000000 - 4FFFFFFF PCI memory. 256M non-prefetchable
+ * 50000000 - 5FFFFFFF PCI memory. 256M prefetchable
+ * 60000000 - 60FFFFFF PCI IO. 16M
+ * 61000000 - 61FFFFFF PCI Configuration. 16M
+ *
+ * There are three V3 windows, each described by a pair of V3 registers.
+ * These are LB_BASE0/LB_MAP0, LB_BASE1/LB_MAP1 and LB_BASE2/LB_MAP2.
+ * Base0 and Base1 can be used for any type of PCI memory access. Base2
+ * can be used either for PCI I/O or for I20 accesses. By default, uHAL
+ * uses this only for PCI IO space.
+ *
+ * Normally these spaces are mapped using the following base registers:
+ *
+ * Usage Local Bus Memory Base/Map registers used
+ *
+ * Mem 40000000 - 4FFFFFFF LB_BASE0/LB_MAP0
+ * Mem 50000000 - 5FFFFFFF LB_BASE1/LB_MAP1
+ * IO 60000000 - 60FFFFFF LB_BASE2/LB_MAP2
+ * Cfg 61000000 - 61FFFFFF
+ *
+ * This means that I20 and PCI configuration space accesses will fail.
+ * When PCI configuration accesses are needed (via the uHAL PCI
+ * configuration space primitives) we must remap the spaces as follows:
+ *
+ * Usage Local Bus Memory Base/Map registers used
+ *
+ * Mem 40000000 - 4FFFFFFF LB_BASE0/LB_MAP0
+ * Mem 50000000 - 5FFFFFFF LB_BASE0/LB_MAP0
+ * IO 60000000 - 60FFFFFF LB_BASE2/LB_MAP2
+ * Cfg 61000000 - 61FFFFFF LB_BASE1/LB_MAP1
+ *
+ * To make this work, the code depends on overlapping windows working.
+ * The V3 chip translates an address by checking its range within
+ * each of the BASE/MAP pairs in turn (in ascending register number
+ * order). It will use the first matching pair. So, for example,
+ * if the same address is mapped by both LB_BASE0/LB_MAP0 and
+ * LB_BASE1/LB_MAP1, the V3 will use the translation from
+ * LB_BASE0/LB_MAP0.
+ *
+ * To allow PCI Configuration space access, the code enlarges the
+ * window mapped by LB_BASE0/LB_MAP0 from 256M to 512M. This occludes
+ * the windows currently mapped by LB_BASE1/LB_MAP1 so that it can
+ * be remapped for use by configuration cycles.
+ *
+ * At the end of the PCI Configuration space accesses,
+ * LB_BASE1/LB_MAP1 is reset to map PCI Memory. Finally the window
+ * mapped by LB_BASE0/LB_MAP0 is reduced in size from 512M to 256M to
+ * reveal the now restored LB_BASE1/LB_MAP1 window.
+ *
+ * NOTE: We do not set up I2O mapping. I suspect that this is only
+ * for an intelligent (target) device. Using I2O disables most of
+ * the mappings into PCI memory.
+ */
+
+// V3 access routines
+#define v3_writeb(o,v) __raw_writeb(v, PCI_V3_VADDR + (unsigned int)(o))
+#define v3_readb(o) (__raw_readb(PCI_V3_VADDR + (unsigned int)(o)))
+
+#define v3_writew(o,v) __raw_writew(v, PCI_V3_VADDR + (unsigned int)(o))
+#define v3_readw(o) (__raw_readw(PCI_V3_VADDR + (unsigned int)(o)))
+
+#define v3_writel(o,v) __raw_writel(v, PCI_V3_VADDR + (unsigned int)(o))
+#define v3_readl(o) (__raw_readl(PCI_V3_VADDR + (unsigned int)(o)))
+
+/*============================================================================
+ *
+ * routine: uHALir_PCIMakeConfigAddress()
+ *
+ * parameters: bus = which bus
+ * device = which device
+ * function = which function
+ * offset = configuration space register we are interested in
+ *
+ * description: this routine will generate a platform dependent config
+ * address.
+ *
+ * calls: none
+ *
+ * returns: configuration address to play on the PCI bus
+ *
+ * To generate the appropriate PCI configuration cycles in the PCI
+ * configuration address space, you present the V3 with the following pattern
+ * (which is very nearly a type 1 (except that the lower two bits are 00 and
+ * not 01). In order for this mapping to work you need to set up one of
+ * the local to PCI aperatures to 16Mbytes in length translating to
+ * PCI configuration space starting at 0x0000.0000.
+ *
+ * PCI configuration cycles look like this:
+ *
+ * Type 0:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:11 Device select bit.
+ * 10:8 Function number
+ * 7:2 Register number
+ *
+ * Type 1:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:24 reserved
+ * 23:16 bus number (8 bits = 128 possible buses)
+ * 15:11 Device number (5 bits)
+ * 10:8 function number
+ * 7:2 register number
+ *
+ */
+static DEFINE_SPINLOCK(v3_lock);
+
+#define PCI_BUS_NONMEM_START 0x00000000
+#define PCI_BUS_NONMEM_SIZE SZ_256M
+
+#define PCI_BUS_PREMEM_START PCI_BUS_NONMEM_START + PCI_BUS_NONMEM_SIZE
+#define PCI_BUS_PREMEM_SIZE SZ_256M
+
+#if PCI_BUS_NONMEM_START & 0x000fffff
+#error PCI_BUS_NONMEM_START must be megabyte aligned
+#endif
+#if PCI_BUS_PREMEM_START & 0x000fffff
+#error PCI_BUS_PREMEM_START must be megabyte aligned
+#endif
+
+#undef V3_LB_BASE_PREFETCH
+#define V3_LB_BASE_PREFETCH 0
+
+static unsigned long v3_open_config_window(struct pci_bus *bus,
+ unsigned int devfn, int offset)
+{
+ unsigned int address, mapaddress, busnr;
+
+ busnr = bus->number;
+
+ /*
+ * Trap out illegal values
+ */
+ if (offset > 255)
+ BUG();
+ if (busnr > 255)
+ BUG();
+ if (devfn > 255)
+ BUG();
+
+ if (busnr == 0) {
+ int slot = PCI_SLOT(devfn);
+
+ /*
+ * local bus segment so need a type 0 config cycle
+ *
+ * build the PCI configuration "address" with one-hot in
+ * A31-A11
+ *
+ * mapaddress:
+ * 3:1 = config cycle (101)
+ * 0 = PCI A1 & A0 are 0 (0)
+ */
+ address = PCI_FUNC(devfn) << 8;
+ mapaddress = V3_LB_MAP_TYPE_CONFIG;
+
+ if (slot > 12)
+ /*
+ * high order bits are handled by the MAP register
+ */
+ mapaddress |= 1 << (slot - 5);
+ else
+ /*
+ * low order bits handled directly in the address
+ */
+ address |= 1 << (slot + 11);
+ } else {
+ /*
+ * not the local bus segment so need a type 1 config cycle
+ *
+ * address:
+ * 23:16 = bus number
+ * 15:11 = slot number (7:3 of devfn)
+ * 10:8 = func number (2:0 of devfn)
+ *
+ * mapaddress:
+ * 3:1 = config cycle (101)
+ * 0 = PCI A1 & A0 from host bus (1)
+ */
+ mapaddress = V3_LB_MAP_TYPE_CONFIG | V3_LB_MAP_AD_LOW_EN;
+ address = (busnr << 16) | (devfn << 8);
+ }
+
+ /*
+ * Set up base0 to see all 512Mbytes of memory space (not
+ * prefetchable), this frees up base1 for re-use by
+ * configuration memory
+ */
+ v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) |
+ V3_LB_BASE_ADR_SIZE_512MB | V3_LB_BASE_ENABLE);
+
+ /*
+ * Set up base1/map1 to point into configuration space.
+ */
+ v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_CONFIG_BASE) |
+ V3_LB_BASE_ADR_SIZE_16MB | V3_LB_BASE_ENABLE);
+ v3_writew(V3_LB_MAP1, mapaddress);
+
+ return PCI_CONFIG_VADDR + address + offset;
+}
+
+static void v3_close_config_window(void)
+{
+ /*
+ * Reassign base1 for use by prefetchable PCI memory
+ */
+ v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE + SZ_256M) |
+ V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH |
+ V3_LB_BASE_ENABLE);
+ v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(PCI_BUS_PREMEM_START) |
+ V3_LB_MAP_TYPE_MEM_MULTIPLE);
+
+ /*
+ * And shrink base0 back to a 256M window (NOTE: MAP0 already correct)
+ */
+ v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) |
+ V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE);
+}
+
+static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 *val)
+{
+ unsigned long addr;
+ unsigned long flags;
+ u32 v;
+
+ spin_lock_irqsave(&v3_lock, flags);
+ addr = v3_open_config_window(bus, devfn, where);
+
+ switch (size) {
+ case 1:
+ v = __raw_readb(addr);
+ break;
+
+ case 2:
+ v = __raw_readw(addr);
+ break;
+
+ default:
+ v = __raw_readl(addr);
+ break;
+ }
+
+ v3_close_config_window();
+ spin_unlock_irqrestore(&v3_lock, flags);
+
+ *val = v;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
+{
+ unsigned long addr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&v3_lock, flags);
+ addr = v3_open_config_window(bus, devfn, where);
+
+ switch (size) {
+ case 1:
+ __raw_writeb((u8)val, addr);
+ __raw_readb(addr);
+ break;
+
+ case 2:
+ __raw_writew((u16)val, addr);
+ __raw_readw(addr);
+ break;
+
+ case 4:
+ __raw_writel(val, addr);
+ __raw_readl(addr);
+ break;
+ }
+
+ v3_close_config_window();
+ spin_unlock_irqrestore(&v3_lock, flags);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_v3_ops = {
+ .read = v3_read_config,
+ .write = v3_write_config,
+};
+
+static struct resource non_mem = {
+ .name = "PCI non-prefetchable",
+ .start = PHYS_PCI_MEM_BASE + PCI_BUS_NONMEM_START,
+ .end = PHYS_PCI_MEM_BASE + PCI_BUS_NONMEM_START + PCI_BUS_NONMEM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource pre_mem = {
+ .name = "PCI prefetchable",
+ .start = PHYS_PCI_MEM_BASE + PCI_BUS_PREMEM_START,
+ .end = PHYS_PCI_MEM_BASE + PCI_BUS_PREMEM_START + PCI_BUS_PREMEM_SIZE - 1,
+ .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_v3_setup_resources(struct resource **resource)
+{
+ if (request_resource(&iomem_resource, &non_mem)) {
+ printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
+ "memory region\n");
+ return -EBUSY;
+ }
+ if (request_resource(&iomem_resource, &pre_mem)) {
+ release_resource(&non_mem);
+ printk(KERN_ERR "PCI: unable to allocate prefetchable "
+ "memory region\n");
+ return -EBUSY;
+ }
+
+ /*
+ * bus->resource[0] is the IO resource for this bus
+ * bus->resource[1] is the mem resource for this bus
+ * bus->resource[2] is the prefetch mem resource for this bus
+ */
+ resource[0] = &ioport_resource;
+ resource[1] = &non_mem;
+ resource[2] = &pre_mem;
+
+ return 1;
+}
+
+/*
+ * These don't seem to be implemented on the Integrator I have, which
+ * means I can't get additional information on the reason for the pm2fb
+ * problems. I suppose I'll just have to mind-meld with the machine. ;)
+ */
+#define SC_PCI IO_ADDRESS(INTEGRATOR_SC_PCIENABLE)
+#define SC_LBFADDR IO_ADDRESS(INTEGRATOR_SC_BASE + 0x20)
+#define SC_LBFCODE IO_ADDRESS(INTEGRATOR_SC_BASE + 0x24)
+
+static int
+v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+ unsigned long pc = instruction_pointer(regs);
+ unsigned long instr = *(unsigned long *)pc;
+#if 0
+ char buf[128];
+
+ sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
+ addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
+ v3_readb(V3_LB_ISTAT));
+ printk(KERN_DEBUG "%s", buf);
+#endif
+
+ v3_writeb(V3_LB_ISTAT, 0);
+ __raw_writel(3, SC_PCI);
+
+ /*
+ * If the instruction being executed was a read,
+ * make it look like it read all-ones.
+ */
+ if ((instr & 0x0c100000) == 0x04100000) {
+ int reg = (instr >> 12) & 15;
+ unsigned long val;
+
+ if (instr & 0x00400000)
+ val = 255;
+ else
+ val = -1;
+
+ regs->uregs[reg] = val;
+ regs->ARM_pc += 4;
+ return 0;
+ }
+
+ if ((instr & 0x0e100090) == 0x00100090) {
+ int reg = (instr >> 12) & 15;
+
+ regs->uregs[reg] = -1;
+ regs->ARM_pc += 4;
+ return 0;
+ }
+
+ return 1;
+}
+
+static irqreturn_t v3_irq(int dummy, void *devid)
+{
+#ifdef CONFIG_DEBUG_LL
+ struct pt_regs *regs = get_irq_regs();
+ unsigned long pc = instruction_pointer(regs);
+ unsigned long instr = *(unsigned long *)pc;
+ char buf[128];
+ extern void printascii(const char *);
+
+ sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x "
+ "ISTAT=%02x\n", IRQ_AP_V3INT, pc, instr,
+ __raw_readl(SC_LBFADDR),
+ __raw_readl(SC_LBFCODE) & 255,
+ v3_readb(V3_LB_ISTAT));
+ printascii(buf);
+#endif
+
+ v3_writew(V3_PCI_STAT, 0xf000);
+ v3_writeb(V3_LB_ISTAT, 0);
+ __raw_writel(3, SC_PCI);
+
+#ifdef CONFIG_DEBUG_LL
+ /*
+ * If the instruction being executed was a read,
+ * make it look like it read all-ones.
+ */
+ if ((instr & 0x0c100000) == 0x04100000) {
+ int reg = (instr >> 16) & 15;
+ sprintf(buf, " reg%d = %08lx\n", reg, regs->uregs[reg]);
+ printascii(buf);
+ }
+#endif
+ return IRQ_HANDLED;
+}
+
+int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
+{
+ int ret = 0;
+
+ if (nr == 0) {
+ sys->mem_offset = PHYS_PCI_MEM_BASE;
+ ret = pci_v3_setup_resources(sys->resource);
+ }
+
+ return ret;
+}
+
+struct pci_bus * __init pci_v3_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ return pci_scan_bus(sys->busnr, &pci_v3_ops, sys);
+}
+
+/*
+ * V3_LB_BASE? - local bus address
+ * V3_LB_MAP? - pci bus address
+ */
+void __init pci_v3_preinit(void)
+{
+ unsigned long flags;
+ unsigned int temp;
+ int ret;
+
+ /*
+ * Hook in our fault handler for PCI errors
+ */
+ hook_fault_code(4, v3_pci_fault, SIGBUS, 0, "external abort on linefetch");
+ hook_fault_code(6, v3_pci_fault, SIGBUS, 0, "external abort on linefetch");
+ hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
+ hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
+
+ spin_lock_irqsave(&v3_lock, flags);
+
+ /*
+ * Unlock V3 registers, but only if they were previously locked.
+ */
+ if (v3_readw(V3_SYSTEM) & V3_SYSTEM_M_LOCK)
+ v3_writew(V3_SYSTEM, 0xa05f);
+
+ /*
+ * Setup window 0 - PCI non-prefetchable memory
+ * Local: 0x40000000 Bus: 0x00000000 Size: 256MB
+ */
+ v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) |
+ V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE);
+ v3_writew(V3_LB_MAP0, v3_addr_to_lb_map(PCI_BUS_NONMEM_START) |
+ V3_LB_MAP_TYPE_MEM);
+
+ /*
+ * Setup window 1 - PCI prefetchable memory
+ * Local: 0x50000000 Bus: 0x10000000 Size: 256MB
+ */
+ v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE + SZ_256M) |
+ V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH |
+ V3_LB_BASE_ENABLE);
+ v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(PCI_BUS_PREMEM_START) |
+ V3_LB_MAP_TYPE_MEM_MULTIPLE);
+
+ /*
+ * Setup window 2 - PCI IO
+ */
+ v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(PHYS_PCI_IO_BASE) |
+ V3_LB_BASE_ENABLE);
+ v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
+
+ /*
+ * Disable PCI to host IO cycles
+ */
+ temp = v3_readw(V3_PCI_CFG) & ~V3_PCI_CFG_M_I2O_EN;
+ temp |= V3_PCI_CFG_M_IO_REG_DIS | V3_PCI_CFG_M_IO_DIS;
+ v3_writew(V3_PCI_CFG, temp);
+
+ printk(KERN_DEBUG "FIFO_CFG: %04x FIFO_PRIO: %04x\n",
+ v3_readw(V3_FIFO_CFG), v3_readw(V3_FIFO_PRIORITY));
+
+ /*
+ * Set the V3 FIFO such that writes have higher priority than
+ * reads, and local bus write causes local bus read fifo flush.
+ * Same for PCI.
+ */
+ v3_writew(V3_FIFO_PRIORITY, 0x0a0a);
+
+ /*
+ * Re-lock the system register.
+ */
+ temp = v3_readw(V3_SYSTEM) | V3_SYSTEM_M_LOCK;
+ v3_writew(V3_SYSTEM, temp);
+
+ /*
+ * Clear any error conditions, and enable write errors.
+ */
+ v3_writeb(V3_LB_ISTAT, 0);
+ v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10));
+ v3_writeb(V3_LB_IMASK, 0x28);
+ __raw_writel(3, SC_PCI);
+
+ /*
+ * Grab the PCI error interrupt.
+ */
+ ret = request_irq(IRQ_AP_V3INT, v3_irq, 0, "V3", NULL);
+ if (ret)
+ printk(KERN_ERR "PCI: unable to grab PCI error "
+ "interrupt: %d\n", ret);
+
+ spin_unlock_irqrestore(&v3_lock, flags);
+}
+
+void __init pci_v3_postinit(void)
+{
+ unsigned int pci_cmd;
+
+ pci_cmd = PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
+
+ v3_writew(V3_PCI_CMD, pci_cmd);
+
+ v3_writeb(V3_LB_ISTAT, ~0x40);
+ v3_writeb(V3_LB_IMASK, 0x68);
+
+#if 0
+ ret = request_irq(IRQ_AP_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL);
+ if (ret)
+ printk(KERN_ERR "PCI: unable to grab local bus timeout "
+ "interrupt: %d\n", ret);
+#endif
+
+ register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0);
+}