summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx
diff options
context:
space:
mode:
authorAnton Arapov <anton@redhat.com>2012-04-16 10:05:28 +0200
committerAnton Arapov <anton@redhat.com>2012-04-16 10:05:28 +0200
commitb4b6116a13633898cf868f2f103c96a90c4c20f8 (patch)
tree93d1b7e2cfcdf473d8d4ff3ad141fa864f8491f6 /arch/arm/mach-ep93xx
parentedd4be777c953e5faafc80d091d3084b4343f5d3 (diff)
downloadkernel-uprobes-b4b6116a13633898cf868f2f103c96a90c4c20f8.tar.gz
kernel-uprobes-b4b6116a13633898cf868f2f103c96a90c4c20f8.tar.xz
kernel-uprobes-b4b6116a13633898cf868f2f103c96a90c4c20f8.zip
fedora kernel: d9aad82f3319f3cfd1aebc01234254ef0c37ad84v3.3.2-1
Signed-off-by: Anton Arapov <anton@redhat.com>
Diffstat (limited to 'arch/arm/mach-ep93xx')
-rw-r--r--arch/arm/mach-ep93xx/Kconfig208
-rw-r--r--arch/arm/mach-ep93xx/Makefile18
-rw-r--r--arch/arm/mach-ep93xx/Makefile.boot14
-rw-r--r--arch/arm/mach-ep93xx/adssphere.c44
-rw-r--r--arch/arm/mach-ep93xx/clock.c562
-rw-r--r--arch/arm/mach-ep93xx/core.c920
-rw-r--r--arch/arm/mach-ep93xx/dma.c108
-rw-r--r--arch/arm/mach-ep93xx/edb93xx.c350
-rw-r--r--arch/arm/mach-ep93xx/gesbc9312.c44
-rw-r--r--arch/arm/mach-ep93xx/include/mach/debug-macro.S21
-rw-r--r--arch/arm/mach-ep93xx/include/mach/dma.h93
-rw-r--r--arch/arm/mach-ep93xx/include/mach/entry-macro.S17
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h230
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h35
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h29
-rw-r--r--arch/arm/mach-ep93xx/include/mach/fb.h56
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h100
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-ep93xx/include/mach/hardware.h25
-rw-r--r--arch/arm/mach-ep93xx/include/mach/io.h22
-rw-r--r--arch/arm/mach-ep93xx/include/mach/irqs.h78
-rw-r--r--arch/arm/mach-ep93xx/include/mach/memory.h22
-rw-r--r--arch/arm/mach-ep93xx/include/mach/platform.h71
-rw-r--r--arch/arm/mach-ep93xx/include/mach/system.h7
-rw-r--r--arch/arm/mach-ep93xx/include/mach/timex.h5
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ts72xx.h98
-rw-r--r--arch/arm/mach-ep93xx/include/mach/uncompress.h94
-rw-r--r--arch/arm/mach-ep93xx/micro9.c128
-rw-r--r--arch/arm/mach-ep93xx/simone.c88
-rw-r--r--arch/arm/mach-ep93xx/snappercl15.c185
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c255
-rw-r--r--arch/arm/mach-ep93xx/vision_ep9307.c369
32 files changed, 4297 insertions, 0 deletions
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
new file mode 100644
index 00000000000..97a249395b5
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -0,0 +1,208 @@
+if ARCH_EP93XX
+
+menu "Cirrus EP93xx Implementation Options"
+
+config CRUNCH
+ bool "Support for MaverickCrunch"
+ help
+ Enable kernel support for MaverickCrunch.
+
+comment "EP93xx Platforms"
+
+choice
+ prompt "EP93xx first SDRAM bank selection"
+ default EP93XX_SDCE3_SYNC_PHYS_OFFSET
+
+config EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ bool "0x00000000 - SDCE3/SyncBoot"
+ help
+ Select this option if you want support for EP93xx boards with the
+ first SDRAM bank at 0x00000000.
+
+config EP93XX_SDCE0_PHYS_OFFSET
+ bool "0xc0000000 - SDCEO"
+ help
+ Select this option if you want support for EP93xx boards with the
+ first SDRAM bank at 0xc0000000.
+
+config EP93XX_SDCE1_PHYS_OFFSET
+ bool "0xd0000000 - SDCE1"
+ help
+ Select this option if you want support for EP93xx boards with the
+ first SDRAM bank at 0xd0000000.
+
+config EP93XX_SDCE2_PHYS_OFFSET
+ bool "0xe0000000 - SDCE2"
+ help
+ Select this option if you want support for EP93xx boards with the
+ first SDRAM bank at 0xe0000000.
+
+config EP93XX_SDCE3_ASYNC_PHYS_OFFSET
+ bool "0xf0000000 - SDCE3/AsyncBoot"
+ help
+ Select this option if you want support for EP93xx boards with the
+ first SDRAM bank at 0xf0000000.
+
+endchoice
+
+config MACH_ADSSPHERE
+ bool "Support ADS Sphere"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ help
+ Say 'Y' here if you want your kernel to support the ADS
+ Sphere board.
+
+config MACH_EDB93XX
+ bool
+
+config MACH_EDB9301
+ bool "Support Cirrus Logic EDB9301"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9301 Evaluation Board.
+
+config MACH_EDB9302
+ bool "Support Cirrus Logic EDB9302"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9302 Evaluation Board.
+
+config MACH_EDB9302A
+ bool "Support Cirrus Logic EDB9302A"
+ depends on EP93XX_SDCE0_PHYS_OFFSET
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9302A Evaluation Board.
+
+config MACH_EDB9307
+ bool "Support Cirrus Logic EDB9307"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9307 Evaluation Board.
+
+config MACH_EDB9307A
+ bool "Support Cirrus Logic EDB9307A"
+ depends on EP93XX_SDCE0_PHYS_OFFSET
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9307A Evaluation Board.
+
+config MACH_EDB9312
+ bool "Support Cirrus Logic EDB9312"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9312 Evaluation Board.
+
+config MACH_EDB9315
+ bool "Support Cirrus Logic EDB9315"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9315 Evaluation Board.
+
+config MACH_EDB9315A
+ bool "Support Cirrus Logic EDB9315A"
+ depends on EP93XX_SDCE0_PHYS_OFFSET
+ select MACH_EDB93XX
+ help
+ Say 'Y' here if you want your kernel to support the Cirrus
+ Logic EDB9315A Evaluation Board.
+
+config MACH_GESBC9312
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ bool "Support Glomation GESBC-9312-sx"
+ help
+ Say 'Y' here if you want your kernel to support the Glomation
+ GESBC-9312-sx board.
+
+config MACH_MICRO9
+ bool
+
+config MACH_MICRO9H
+ bool "Support Contec Micro9-High"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Micro9-High board.
+
+config MACH_MICRO9M
+ bool "Support Contec Micro9-Mid"
+ depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Micro9-Mid board.
+
+config MACH_MICRO9L
+ bool "Support Contec Micro9-Lite"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Micro9-Lite board.
+
+config MACH_MICRO9S
+ bool "Support Contec Micro9-Slim"
+ depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Micro9-Slim board.
+
+config MACH_SIM_ONE
+ bool "Support Simplemachines Sim.One board"
+ depends on EP93XX_SDCE0_PHYS_OFFSET
+ help
+ Say 'Y' here if you want your kernel to support the
+ Simplemachines Sim.One board.
+
+config MACH_SNAPPER_CL15
+ bool "Support Bluewater Systems Snapper CL15 Module"
+ depends on EP93XX_SDCE0_PHYS_OFFSET
+ help
+ Say 'Y' here if you want your kernel to support the Bluewater
+ Systems Snapper CL15 Module.
+
+config MACH_TS72XX
+ bool "Support Technologic Systems TS-72xx SBC"
+ depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ help
+ Say 'Y' here if you want your kernel to support the
+ Technologic Systems TS-72xx board.
+
+config MACH_VISION_EP9307
+ bool "Support Vision Engraving Systems EP9307 SoM"
+ depends on EP93XX_SDCE0_PHYS_OFFSET
+ help
+ Say 'Y' here if you want your kernel to support the
+ Vision Engraving Systems EP9307 SoM.
+
+choice
+ prompt "Select a UART for early kernel messages"
+
+config EP93XX_EARLY_UART1
+ bool "UART1"
+
+config EP93XX_EARLY_UART2
+ bool "UART2"
+
+config EP93XX_EARLY_UART3
+ bool "UART3"
+
+endchoice
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
new file mode 100644
index 00000000000..574209d9e24
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the linux kernel.
+#
+obj-y := core.o clock.o
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_EP93XX_DMA) += dma.o
+
+obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o
+obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
+obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o
+obj-$(CONFIG_MACH_MICRO9) += micro9.o
+obj-$(CONFIG_MACH_SIM_ONE) += simone.o
+obj-$(CONFIG_MACH_SNAPPER_CL15) += snappercl15.o
+obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
+obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o
diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot
new file mode 100644
index 00000000000..d3113a71cb4
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Makefile.boot
@@ -0,0 +1,14 @@
+ zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) += 0x00008000
+params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) := 0x00000100
+
+ zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) += 0xc0008000
+params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0000100
+
+ zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) += 0xd0008000
+params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0000100
+
+ zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) += 0xe0008000
+params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0000100
+
+ zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) += 0xf0008000
+params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0000100
diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c
new file mode 100644
index 00000000000..681e939407d
--- /dev/null
+++ b/arch/arm/mach-ep93xx/adssphere.c
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-ep93xx/adssphere.c
+ * ADS Sphere support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+
+static struct ep93xx_eth_data __initdata adssphere_eth_data = {
+ .phy_id = 1,
+};
+
+static void __init adssphere_init_machine(void)
+{
+ ep93xx_init_devices();
+ ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
+ ep93xx_register_eth(&adssphere_eth_data, 1);
+}
+
+MACHINE_START(ADSSPHERE, "ADS Sphere board")
+ /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = adssphere_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
new file mode 100644
index 00000000000..ca4de710509
--- /dev/null
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -0,0 +1,562 @@
+/*
+ * arch/arm/mach-ep93xx/clock.c
+ * Clock control for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/clkdev.h>
+
+#include <mach/hardware.h>
+
+#include <asm/div64.h>
+
+
+struct clk {
+ struct clk *parent;
+ unsigned long rate;
+ int users;
+ int sw_locked;
+ void __iomem *enable_reg;
+ u32 enable_mask;
+
+ unsigned long (*get_rate)(struct clk *clk);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+};
+
+
+static unsigned long get_uart_rate(struct clk *clk);
+
+static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
+static int set_div_rate(struct clk *clk, unsigned long rate);
+static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate);
+static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate);
+
+static struct clk clk_xtali = {
+ .rate = EP93XX_EXT_CLK_RATE,
+};
+static struct clk clk_uart1 = {
+ .parent = &clk_xtali,
+ .sw_locked = 1,
+ .enable_reg = EP93XX_SYSCON_DEVCFG,
+ .enable_mask = EP93XX_SYSCON_DEVCFG_U1EN,
+ .get_rate = get_uart_rate,
+};
+static struct clk clk_uart2 = {
+ .parent = &clk_xtali,
+ .sw_locked = 1,
+ .enable_reg = EP93XX_SYSCON_DEVCFG,
+ .enable_mask = EP93XX_SYSCON_DEVCFG_U2EN,
+ .get_rate = get_uart_rate,
+};
+static struct clk clk_uart3 = {
+ .parent = &clk_xtali,
+ .sw_locked = 1,
+ .enable_reg = EP93XX_SYSCON_DEVCFG,
+ .enable_mask = EP93XX_SYSCON_DEVCFG_U3EN,
+ .get_rate = get_uart_rate,
+};
+static struct clk clk_pll1 = {
+ .parent = &clk_xtali,
+};
+static struct clk clk_f = {
+ .parent = &clk_pll1,
+};
+static struct clk clk_h = {
+ .parent = &clk_pll1,
+};
+static struct clk clk_p = {
+ .parent = &clk_pll1,
+};
+static struct clk clk_pll2 = {
+ .parent = &clk_xtali,
+};
+static struct clk clk_usb_host = {
+ .parent = &clk_pll2,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN,
+};
+static struct clk clk_keypad = {
+ .parent = &clk_xtali,
+ .sw_locked = 1,
+ .enable_reg = EP93XX_SYSCON_KEYTCHCLKDIV,
+ .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
+ .set_rate = set_keytchclk_rate,
+};
+static struct clk clk_spi = {
+ .parent = &clk_xtali,
+ .rate = EP93XX_EXT_CLK_RATE,
+};
+static struct clk clk_pwm = {
+ .parent = &clk_xtali,
+ .rate = EP93XX_EXT_CLK_RATE,
+};
+
+static struct clk clk_video = {
+ .sw_locked = 1,
+ .enable_reg = EP93XX_SYSCON_VIDCLKDIV,
+ .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE,
+ .set_rate = set_div_rate,
+};
+
+static struct clk clk_i2s_mclk = {
+ .sw_locked = 1,
+ .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
+ .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE,
+ .set_rate = set_div_rate,
+};
+
+static struct clk clk_i2s_sclk = {
+ .sw_locked = 1,
+ .parent = &clk_i2s_mclk,
+ .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
+ .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA,
+ .set_rate = set_i2s_sclk_rate,
+};
+
+static struct clk clk_i2s_lrclk = {
+ .sw_locked = 1,
+ .parent = &clk_i2s_sclk,
+ .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
+ .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA,
+ .set_rate = set_i2s_lrclk_rate,
+};
+
+/* DMA Clocks */
+static struct clk clk_m2p0 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P0,
+};
+static struct clk clk_m2p1 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P1,
+};
+static struct clk clk_m2p2 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P2,
+};
+static struct clk clk_m2p3 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P3,
+};
+static struct clk clk_m2p4 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P4,
+};
+static struct clk clk_m2p5 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P5,
+};
+static struct clk clk_m2p6 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P6,
+};
+static struct clk clk_m2p7 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P7,
+};
+static struct clk clk_m2p8 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P8,
+};
+static struct clk clk_m2p9 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P9,
+};
+static struct clk clk_m2m0 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2M0,
+};
+static struct clk clk_m2m1 = {
+ .parent = &clk_h,
+ .enable_reg = EP93XX_SYSCON_PWRCNT,
+ .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2M1,
+};
+
+#define INIT_CK(dev,con,ck) \
+ { .dev_id = dev, .con_id = con, .clk = ck }
+
+static struct clk_lookup clocks[] = {
+ INIT_CK(NULL, "xtali", &clk_xtali),
+ INIT_CK("apb:uart1", NULL, &clk_uart1),
+ INIT_CK("apb:uart2", NULL, &clk_uart2),
+ INIT_CK("apb:uart3", NULL, &clk_uart3),
+ INIT_CK(NULL, "pll1", &clk_pll1),
+ INIT_CK(NULL, "fclk", &clk_f),
+ INIT_CK(NULL, "hclk", &clk_h),
+ INIT_CK(NULL, "apb_pclk", &clk_p),
+ INIT_CK(NULL, "pll2", &clk_pll2),
+ INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
+ INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
+ INIT_CK("ep93xx-fb", NULL, &clk_video),
+ INIT_CK("ep93xx-spi.0", NULL, &clk_spi),
+ INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk),
+ INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk),
+ INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk),
+ INIT_CK(NULL, "pwm_clk", &clk_pwm),
+ INIT_CK(NULL, "m2p0", &clk_m2p0),
+ INIT_CK(NULL, "m2p1", &clk_m2p1),
+ INIT_CK(NULL, "m2p2", &clk_m2p2),
+ INIT_CK(NULL, "m2p3", &clk_m2p3),
+ INIT_CK(NULL, "m2p4", &clk_m2p4),
+ INIT_CK(NULL, "m2p5", &clk_m2p5),
+ INIT_CK(NULL, "m2p6", &clk_m2p6),
+ INIT_CK(NULL, "m2p7", &clk_m2p7),
+ INIT_CK(NULL, "m2p8", &clk_m2p8),
+ INIT_CK(NULL, "m2p9", &clk_m2p9),
+ INIT_CK(NULL, "m2m0", &clk_m2m0),
+ INIT_CK(NULL, "m2m1", &clk_m2m1),
+};
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static void __clk_enable(struct clk *clk)
+{
+ if (!clk->users++) {
+ if (clk->parent)
+ __clk_enable(clk->parent);
+
+ if (clk->enable_reg) {
+ u32 v;
+
+ v = __raw_readl(clk->enable_reg);
+ v |= clk->enable_mask;
+ if (clk->sw_locked)
+ ep93xx_syscon_swlocked_write(v, clk->enable_reg);
+ else
+ __raw_writel(v, clk->enable_reg);
+ }
+ }
+}
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (!clk)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_enable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+static void __clk_disable(struct clk *clk)
+{
+ if (!--clk->users) {
+ if (clk->enable_reg) {
+ u32 v;
+
+ v = __raw_readl(clk->enable_reg);
+ v &= ~clk->enable_mask;
+ if (clk->sw_locked)
+ ep93xx_syscon_swlocked_write(v, clk->enable_reg);
+ else
+ __raw_writel(v, clk->enable_reg);
+ }
+
+ if (clk->parent)
+ __clk_disable(clk->parent);
+ }
+}
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (!clk)
+ return;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+static unsigned long get_uart_rate(struct clk *clk)
+{
+ unsigned long rate = clk_get_rate(clk->parent);
+ u32 value;
+
+ value = __raw_readl(EP93XX_SYSCON_PWRCNT);
+ if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
+ return rate;
+ else
+ return rate / 2;
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (clk->get_rate)
+ return clk->get_rate(clk);
+
+ return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val;
+ u32 div_bit;
+
+ val = __raw_readl(clk->enable_reg);
+
+ /*
+ * The Key Matrix and ADC clocks are configured using the same
+ * System Controller register. The clock used will be either
+ * 1/4 or 1/16 the external clock rate depending on the
+ * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV
+ * bit being set or cleared.
+ */
+ div_bit = clk->enable_mask >> 15;
+
+ if (rate == EP93XX_KEYTCHCLK_DIV4)
+ val |= div_bit;
+ else if (rate == EP93XX_KEYTCHCLK_DIV16)
+ val &= ~div_bit;
+ else
+ return -EINVAL;
+
+ ep93xx_syscon_swlocked_write(val, clk->enable_reg);
+ clk->rate = rate;
+ return 0;
+}
+
+static int calc_clk_div(struct clk *clk, unsigned long rate,
+ int *psel, int *esel, int *pdiv, int *div)
+{
+ struct clk *mclk;
+ unsigned long max_rate, actual_rate, mclk_rate, rate_err = -1;
+ int i, found = 0, __div = 0, __pdiv = 0;
+
+ /* Don't exceed the maximum rate */
+ max_rate = max3(clk_pll1.rate / 4, clk_pll2.rate / 4, clk_xtali.rate / 4);
+ rate = min(rate, max_rate);
+
+ /*
+ * Try the two pll's and the external clock
+ * Because the valid predividers are 2, 2.5 and 3, we multiply
+ * all the clocks by 2 to avoid floating point math.
+ *
+ * This is based on the algorithm in the ep93xx raster guide:
+ * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
+ *
+ */
+ for (i = 0; i < 3; i++) {
+ if (i == 0)
+ mclk = &clk_xtali;
+ else if (i == 1)
+ mclk = &clk_pll1;
+ else
+ mclk = &clk_pll2;
+ mclk_rate = mclk->rate * 2;
+
+ /* Try each predivider value */
+ for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
+ __div = mclk_rate / (rate * __pdiv);
+ if (__div < 2 || __div > 127)
+ continue;
+
+ actual_rate = mclk_rate / (__pdiv * __div);
+
+ if (!found || abs(actual_rate - rate) < rate_err) {
+ *pdiv = __pdiv - 3;
+ *div = __div;
+ *psel = (i == 2);
+ *esel = (i != 0);
+ clk->parent = mclk;
+ clk->rate = actual_rate;
+ rate_err = abs(actual_rate - rate);
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int set_div_rate(struct clk *clk, unsigned long rate)
+{
+ int err, psel = 0, esel = 0, pdiv = 0, div = 0;
+ u32 val;
+
+ err = calc_clk_div(clk, rate, &psel, &esel, &pdiv, &div);
+ if (err)
+ return err;
+
+ /* Clear the esel, psel, pdiv and div bits */
+ val = __raw_readl(clk->enable_reg);
+ val &= ~0x7fff;
+
+ /* Set the new esel, psel, pdiv and div bits for the new clock rate */
+ val |= (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) |
+ (psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) |
+ (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
+ ep93xx_syscon_swlocked_write(val, clk->enable_reg);
+ return 0;
+}
+
+static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned val = __raw_readl(clk->enable_reg);
+
+ if (rate == clk_i2s_mclk.rate / 2)
+ ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV,
+ clk->enable_reg);
+ else if (rate == clk_i2s_mclk.rate / 4)
+ ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV,
+ clk->enable_reg);
+ else
+ return -EINVAL;
+
+ clk_i2s_sclk.rate = rate;
+ return 0;
+}
+
+static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned val = __raw_readl(clk->enable_reg) &
+ ~EP93XX_I2SCLKDIV_LRDIV_MASK;
+
+ if (rate == clk_i2s_sclk.rate / 32)
+ ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32,
+ clk->enable_reg);
+ else if (rate == clk_i2s_sclk.rate / 64)
+ ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64,
+ clk->enable_reg);
+ else if (rate == clk_i2s_sclk.rate / 128)
+ ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128,
+ clk->enable_reg);
+ else
+ return -EINVAL;
+
+ clk_i2s_lrclk.rate = rate;
+ return 0;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk->set_rate)
+ return clk->set_rate(clk, rate);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+
+static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
+static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
+static char pclk_divisors[] = { 1, 2, 4, 8 };
+
+/*
+ * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
+ */
+static unsigned long calc_pll_rate(u32 config_word)
+{
+ unsigned long long rate;
+ int i;
+
+ rate = clk_xtali.rate;
+ rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */
+ rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */
+ do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */
+ for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */
+ rate >>= 1;
+
+ return (unsigned long)rate;
+}
+
+static void __init ep93xx_dma_clock_init(void)
+{
+ clk_m2p0.rate = clk_h.rate;
+ clk_m2p1.rate = clk_h.rate;
+ clk_m2p2.rate = clk_h.rate;
+ clk_m2p3.rate = clk_h.rate;
+ clk_m2p4.rate = clk_h.rate;
+ clk_m2p5.rate = clk_h.rate;
+ clk_m2p6.rate = clk_h.rate;
+ clk_m2p7.rate = clk_h.rate;
+ clk_m2p8.rate = clk_h.rate;
+ clk_m2p9.rate = clk_h.rate;
+ clk_m2m0.rate = clk_h.rate;
+ clk_m2m1.rate = clk_h.rate;
+}
+
+static int __init ep93xx_clock_init(void)
+{
+ u32 value;
+
+ /* Determine the bootloader configured pll1 rate */
+ value = __raw_readl(EP93XX_SYSCON_CLKSET1);
+ if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1))
+ clk_pll1.rate = clk_xtali.rate;
+ else
+ clk_pll1.rate = calc_pll_rate(value);
+
+ /* Initialize the pll1 derived clocks */
+ clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
+ clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
+ clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
+ ep93xx_dma_clock_init();
+
+ /* Determine the bootloader configured pll2 rate */
+ value = __raw_readl(EP93XX_SYSCON_CLKSET2);
+ if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
+ clk_pll2.rate = clk_xtali.rate;
+ else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
+ clk_pll2.rate = calc_pll_rate(value);
+ else
+ clk_pll2.rate = 0;
+
+ /* Initialize the pll2 derived clocks */
+ clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
+
+ /*
+ * EP93xx SSP clock rate was doubled in version E2. For more information
+ * see:
+ * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
+ */
+ if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2)
+ clk_spi.rate /= 2;
+
+ pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
+ clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
+ pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
+ clk_f.rate / 1000000, clk_h.rate / 1000000,
+ clk_p.rate / 1000000);
+
+ clkdev_add_table(clocks, ARRAY_SIZE(clocks));
+ return 0;
+}
+postcore_initcall(ep93xx_clock_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
new file mode 100644
index 00000000000..24203f9a679
--- /dev/null
+++ b/arch/arm/mach-ep93xx/core.c
@@ -0,0 +1,920 @@
+/*
+ * arch/arm/mach-ep93xx/core.c
+ * Core routines for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * Thanks go to Michael Burian and Ray Lehtiniemi for their key
+ * role in the ep93xx linux community.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/timex.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/termios.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/export.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_keypad.h>
+#include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <asm/hardware/vic.h>
+
+
+/*************************************************************************
+ * Static I/O mappings that are needed for all EP93xx platforms
+ *************************************************************************/
+static struct map_desc ep93xx_io_desc[] __initdata = {
+ {
+ .virtual = EP93XX_AHB_VIRT_BASE,
+ .pfn = __phys_to_pfn(EP93XX_AHB_PHYS_BASE),
+ .length = EP93XX_AHB_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = EP93XX_APB_VIRT_BASE,
+ .pfn = __phys_to_pfn(EP93XX_APB_PHYS_BASE),
+ .length = EP93XX_APB_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init ep93xx_map_io(void)
+{
+ iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc));
+}
+
+
+/*************************************************************************
+ * Timer handling for EP93xx
+ *************************************************************************
+ * The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and
+ * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate
+ * an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz,
+ * is free-running, and can't generate interrupts.
+ *
+ * The 508 kHz timers are ideal for use for the timer interrupt, as the
+ * most common values of HZ divide 508 kHz nicely. We pick one of the 16
+ * bit timers (timer 1) since we don't need more than 16 bits of reload
+ * value as long as HZ >= 8.
+ *
+ * The higher clock rate of timer 4 makes it a better choice than the
+ * other timers for use in gettimeoffset(), while the fact that it can't
+ * generate interrupts means we don't have to worry about not being able
+ * to use this timer for something else. We also use timer 4 for keeping
+ * track of lost jiffies.
+ */
+#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x))
+#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00)
+#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04)
+#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08)
+#define EP93XX_TIMER123_CONTROL_ENABLE (1 << 7)
+#define EP93XX_TIMER123_CONTROL_MODE (1 << 6)
+#define EP93XX_TIMER123_CONTROL_CLKSEL (1 << 3)
+#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c)
+#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20)
+#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24)
+#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28)
+#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c)
+#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60)
+#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64)
+#define EP93XX_TIMER4_VALUE_HIGH_ENABLE (1 << 8)
+#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80)
+#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84)
+#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88)
+#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c)
+
+#define EP93XX_TIMER123_CLOCK 508469
+#define EP93XX_TIMER4_CLOCK 983040
+
+#define TIMER1_RELOAD ((EP93XX_TIMER123_CLOCK / HZ) - 1)
+#define TIMER4_TICKS_PER_JIFFY DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ)
+
+static unsigned int last_jiffy_time;
+
+static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
+{
+ /* Writing any value clears the timer interrupt */
+ __raw_writel(1, EP93XX_TIMER1_CLEAR);
+
+ /* Recover lost jiffies */
+ while ((signed long)
+ (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time)
+ >= TIMER4_TICKS_PER_JIFFY) {
+ last_jiffy_time += TIMER4_TICKS_PER_JIFFY;
+ timer_tick();
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ep93xx_timer_irq = {
+ .name = "ep93xx timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = ep93xx_timer_interrupt,
+};
+
+static void __init ep93xx_timer_init(void)
+{
+ u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
+ EP93XX_TIMER123_CONTROL_CLKSEL;
+
+ /* Enable periodic HZ timer. */
+ __raw_writel(tmode, EP93XX_TIMER1_CONTROL);
+ __raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD);
+ __raw_writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE,
+ EP93XX_TIMER1_CONTROL);
+
+ /* Enable lost jiffy timer. */
+ __raw_writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE,
+ EP93XX_TIMER4_VALUE_HIGH);
+
+ setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);
+}
+
+static unsigned long ep93xx_gettimeoffset(void)
+{
+ int offset;
+
+ offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
+
+ /* Calculate (1000000 / 983040) * offset. */
+ return offset + (53 * offset / 3072);
+}
+
+struct sys_timer ep93xx_timer = {
+ .init = ep93xx_timer_init,
+ .offset = ep93xx_gettimeoffset,
+};
+
+
+/*************************************************************************
+ * EP93xx IRQ handling
+ *************************************************************************/
+void __init ep93xx_init_irq(void)
+{
+ vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
+ vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
+}
+
+
+/*************************************************************************
+ * EP93xx System Controller Software Locked register handling
+ *************************************************************************/
+
+/*
+ * syscon_swlock prevents anything else from writing to the syscon
+ * block while a software locked register is being written.
+ */
+static DEFINE_SPINLOCK(syscon_swlock);
+
+void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&syscon_swlock, flags);
+
+ __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+ __raw_writel(val, reg);
+
+ spin_unlock_irqrestore(&syscon_swlock, flags);
+}
+EXPORT_SYMBOL(ep93xx_syscon_swlocked_write);
+
+void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits)
+{
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&syscon_swlock, flags);
+
+ val = __raw_readl(EP93XX_SYSCON_DEVCFG);
+ val &= ~clear_bits;
+ val |= set_bits;
+ __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+ __raw_writel(val, EP93XX_SYSCON_DEVCFG);
+
+ spin_unlock_irqrestore(&syscon_swlock, flags);
+}
+EXPORT_SYMBOL(ep93xx_devcfg_set_clear);
+
+/**
+ * ep93xx_chip_revision() - returns the EP93xx chip revision
+ *
+ * See <mach/platform.h> for more information.
+ */
+unsigned int ep93xx_chip_revision(void)
+{
+ unsigned int v;
+
+ v = __raw_readl(EP93XX_SYSCON_SYSCFG);
+ v &= EP93XX_SYSCON_SYSCFG_REV_MASK;
+ v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT;
+ return v;
+}
+
+/*************************************************************************
+ * EP93xx GPIO
+ *************************************************************************/
+static struct resource ep93xx_gpio_resource[] = {
+ {
+ .start = EP93XX_GPIO_PHYS_BASE,
+ .end = EP93XX_GPIO_PHYS_BASE + 0xcc - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ep93xx_gpio_device = {
+ .name = "gpio-ep93xx",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ep93xx_gpio_resource),
+ .resource = ep93xx_gpio_resource,
+};
+
+/*************************************************************************
+ * EP93xx peripheral handling
+ *************************************************************************/
+#define EP93XX_UART_MCR_OFFSET (0x0100)
+
+static void ep93xx_uart_set_mctrl(struct amba_device *dev,
+ void __iomem *base, unsigned int mctrl)
+{
+ unsigned int mcr;
+
+ mcr = 0;
+ if (mctrl & TIOCM_RTS)
+ mcr |= 2;
+ if (mctrl & TIOCM_DTR)
+ mcr |= 1;
+
+ __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET);
+}
+
+static struct amba_pl010_data ep93xx_uart_data = {
+ .set_mctrl = ep93xx_uart_set_mctrl,
+};
+
+static struct amba_device uart1_device = {
+ .dev = {
+ .init_name = "apb:uart1",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART1_PHYS_BASE,
+ .end = EP93XX_UART1_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART1, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
+static struct amba_device uart2_device = {
+ .dev = {
+ .init_name = "apb:uart2",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART2_PHYS_BASE,
+ .end = EP93XX_UART2_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART2, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
+static struct amba_device uart3_device = {
+ .dev = {
+ .init_name = "apb:uart3",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART3_PHYS_BASE,
+ .end = EP93XX_UART3_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART3, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
+
+static struct resource ep93xx_rtc_resource[] = {
+ {
+ .start = EP93XX_RTC_PHYS_BASE,
+ .end = EP93XX_RTC_PHYS_BASE + 0x10c - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ep93xx_rtc_device = {
+ .name = "ep93xx-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ep93xx_rtc_resource),
+ .resource = ep93xx_rtc_resource,
+};
+
+
+static struct resource ep93xx_ohci_resources[] = {
+ [0] = {
+ .start = EP93XX_USB_PHYS_BASE,
+ .end = EP93XX_USB_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_EP93XX_USB,
+ .end = IRQ_EP93XX_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+
+static struct platform_device ep93xx_ohci_device = {
+ .name = "ep93xx-ohci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ep93xx_ohci_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(ep93xx_ohci_resources),
+ .resource = ep93xx_ohci_resources,
+};
+
+
+/*************************************************************************
+ * EP93xx physmap'ed flash
+ *************************************************************************/
+static struct physmap_flash_data ep93xx_flash_data;
+
+static struct resource ep93xx_flash_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ep93xx_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &ep93xx_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &ep93xx_flash_resource,
+};
+
+/**
+ * ep93xx_register_flash() - Register the external flash device.
+ * @width: bank width in octets
+ * @start: resource start address
+ * @size: resource size
+ */
+void __init ep93xx_register_flash(unsigned int width,
+ resource_size_t start, resource_size_t size)
+{
+ ep93xx_flash_data.width = width;
+
+ ep93xx_flash_resource.start = start;
+ ep93xx_flash_resource.end = start + size - 1;
+
+ platform_device_register(&ep93xx_flash);
+}
+
+
+/*************************************************************************
+ * EP93xx ethernet peripheral handling
+ *************************************************************************/
+static struct ep93xx_eth_data ep93xx_eth_data;
+
+static struct resource ep93xx_eth_resource[] = {
+ {
+ .start = EP93XX_ETHERNET_PHYS_BASE,
+ .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_EP93XX_ETHERNET,
+ .end = IRQ_EP93XX_ETHERNET,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ep93xx_eth_device = {
+ .name = "ep93xx-eth",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_eth_data,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &ep93xx_eth_dma_mask,
+ },
+ .num_resources = ARRAY_SIZE(ep93xx_eth_resource),
+ .resource = ep93xx_eth_resource,
+};
+
+/**
+ * ep93xx_register_eth - Register the built-in ethernet platform device.
+ * @data: platform specific ethernet configuration (__initdata)
+ * @copy_addr: flag indicating that the MAC address should be copied
+ * from the IndAd registers (as programmed by the bootloader)
+ */
+void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
+{
+ if (copy_addr)
+ memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6);
+
+ ep93xx_eth_data = *data;
+ platform_device_register(&ep93xx_eth_device);
+}
+
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
+
+static struct platform_device ep93xx_i2c_device = {
+ .name = "i2c-gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &ep93xx_i2c_data,
+ },
+};
+
+/**
+ * ep93xx_register_i2c - Register the i2c platform device.
+ * @data: platform specific i2c-gpio configuration (__initdata)
+ * @devices: platform specific i2c bus device information (__initdata)
+ * @num: the number of devices on the i2c bus
+ */
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+ struct i2c_board_info *devices, int num)
+{
+ /*
+ * Set the EEPROM interface pin drive type control.
+ * Defines the driver type for the EECLK and EEDAT pins as either
+ * open drain, which will require an external pull-up, or a normal
+ * CMOS driver.
+ */
+ if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
+ pr_warning("sda != EEDAT, open drain has no effect\n");
+ if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
+ pr_warning("scl != EECLK, open drain has no effect\n");
+
+ __raw_writel((data->sda_is_open_drain << 1) |
+ (data->scl_is_open_drain << 0),
+ EP93XX_GPIO_EEDRIVE);
+
+ ep93xx_i2c_data = *data;
+ i2c_register_board_info(0, devices, num);
+ platform_device_register(&ep93xx_i2c_device);
+}
+
+/*************************************************************************
+ * EP93xx SPI peripheral handling
+ *************************************************************************/
+static struct ep93xx_spi_info ep93xx_spi_master_data;
+
+static struct resource ep93xx_spi_resources[] = {
+ {
+ .start = EP93XX_SPI_PHYS_BASE,
+ .end = EP93XX_SPI_PHYS_BASE + 0x18 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_EP93XX_SSP,
+ .end = IRQ_EP93XX_SSP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ep93xx_spi_device = {
+ .name = "ep93xx-spi",
+ .id = 0,
+ .dev = {
+ .platform_data = &ep93xx_spi_master_data,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &ep93xx_spi_dma_mask,
+ },
+ .num_resources = ARRAY_SIZE(ep93xx_spi_resources),
+ .resource = ep93xx_spi_resources,
+};
+
+/**
+ * ep93xx_register_spi() - registers spi platform device
+ * @info: ep93xx board specific spi master info (__initdata)
+ * @devices: SPI devices to register (__initdata)
+ * @num: number of SPI devices to register
+ *
+ * This function registers platform device for the EP93xx SPI controller and
+ * also makes sure that SPI pins are muxed so that I2S is not using those pins.
+ */
+void __init ep93xx_register_spi(struct ep93xx_spi_info *info,
+ struct spi_board_info *devices, int num)
+{
+ /*
+ * When SPI is used, we need to make sure that I2S is muxed off from
+ * SPI pins.
+ */
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONSSP);
+
+ ep93xx_spi_master_data = *info;
+ spi_register_board_info(devices, num);
+ platform_device_register(&ep93xx_spi_device);
+}
+
+/*************************************************************************
+ * EP93xx LEDs
+ *************************************************************************/
+static struct gpio_led ep93xx_led_pins[] = {
+ {
+ .name = "platform:grled",
+ .gpio = EP93XX_GPIO_LINE_GRLED,
+ }, {
+ .name = "platform:rdled",
+ .gpio = EP93XX_GPIO_LINE_RDLED,
+ },
+};
+
+static struct gpio_led_platform_data ep93xx_led_data = {
+ .num_leds = ARRAY_SIZE(ep93xx_led_pins),
+ .leds = ep93xx_led_pins,
+};
+
+static struct platform_device ep93xx_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_led_data,
+ },
+};
+
+
+/*************************************************************************
+ * EP93xx pwm peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_pwm0_resource[] = {
+ {
+ .start = EP93XX_PWM_PHYS_BASE,
+ .end = EP93XX_PWM_PHYS_BASE + 0x10 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ep93xx_pwm0_device = {
+ .name = "ep93xx-pwm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(ep93xx_pwm0_resource),
+ .resource = ep93xx_pwm0_resource,
+};
+
+static struct resource ep93xx_pwm1_resource[] = {
+ {
+ .start = EP93XX_PWM_PHYS_BASE + 0x20,
+ .end = EP93XX_PWM_PHYS_BASE + 0x30 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ep93xx_pwm1_device = {
+ .name = "ep93xx-pwm",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(ep93xx_pwm1_resource),
+ .resource = ep93xx_pwm1_resource,
+};
+
+void __init ep93xx_register_pwm(int pwm0, int pwm1)
+{
+ if (pwm0)
+ platform_device_register(&ep93xx_pwm0_device);
+
+ /* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */
+ if (pwm1)
+ platform_device_register(&ep93xx_pwm1_device);
+}
+
+int ep93xx_pwm_acquire_gpio(struct platform_device *pdev)
+{
+ int err;
+
+ if (pdev->id == 0) {
+ err = 0;
+ } else if (pdev->id == 1) {
+ err = gpio_request(EP93XX_GPIO_LINE_EGPIO14,
+ dev_name(&pdev->dev));
+ if (err)
+ return err;
+ err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, 0);
+ if (err)
+ goto fail;
+
+ /* PWM 1 output on EGPIO[14] */
+ ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG);
+ } else {
+ err = -ENODEV;
+ }
+
+ return err;
+
+fail:
+ gpio_free(EP93XX_GPIO_LINE_EGPIO14);
+ return err;
+}
+EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio);
+
+void ep93xx_pwm_release_gpio(struct platform_device *pdev)
+{
+ if (pdev->id == 1) {
+ gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14);
+ gpio_free(EP93XX_GPIO_LINE_EGPIO14);
+
+ /* EGPIO[14] used for GPIO */
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG);
+ }
+}
+EXPORT_SYMBOL(ep93xx_pwm_release_gpio);
+
+
+/*************************************************************************
+ * EP93xx video peripheral handling
+ *************************************************************************/
+static struct ep93xxfb_mach_info ep93xxfb_data;
+
+static struct resource ep93xx_fb_resource[] = {
+ {
+ .start = EP93XX_RASTER_PHYS_BASE,
+ .end = EP93XX_RASTER_PHYS_BASE + 0x800 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ep93xx_fb_device = {
+ .name = "ep93xx-fb",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xxfb_data,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask,
+ },
+ .num_resources = ARRAY_SIZE(ep93xx_fb_resource),
+ .resource = ep93xx_fb_resource,
+};
+
+static struct platform_device ep93xx_bl_device = {
+ .name = "ep93xx-bl",
+ .id = -1,
+};
+
+/**
+ * ep93xx_register_fb - Register the framebuffer platform device.
+ * @data: platform specific framebuffer configuration (__initdata)
+ */
+void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data)
+{
+ ep93xxfb_data = *data;
+ platform_device_register(&ep93xx_fb_device);
+ platform_device_register(&ep93xx_bl_device);
+}
+
+
+/*************************************************************************
+ * EP93xx matrix keypad peripheral handling
+ *************************************************************************/
+static struct ep93xx_keypad_platform_data ep93xx_keypad_data;
+
+static struct resource ep93xx_keypad_resource[] = {
+ {
+ .start = EP93XX_KEY_MATRIX_PHYS_BASE,
+ .end = EP93XX_KEY_MATRIX_PHYS_BASE + 0x0c - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_EP93XX_KEY,
+ .end = IRQ_EP93XX_KEY,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ep93xx_keypad_device = {
+ .name = "ep93xx-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_keypad_data,
+ },
+ .num_resources = ARRAY_SIZE(ep93xx_keypad_resource),
+ .resource = ep93xx_keypad_resource,
+};
+
+/**
+ * ep93xx_register_keypad - Register the keypad platform device.
+ * @data: platform specific keypad configuration (__initdata)
+ */
+void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data)
+{
+ ep93xx_keypad_data = *data;
+ platform_device_register(&ep93xx_keypad_device);
+}
+
+int ep93xx_keypad_acquire_gpio(struct platform_device *pdev)
+{
+ int err;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ err = gpio_request(EP93XX_GPIO_LINE_C(i), dev_name(&pdev->dev));
+ if (err)
+ goto fail_gpio_c;
+ err = gpio_request(EP93XX_GPIO_LINE_D(i), dev_name(&pdev->dev));
+ if (err)
+ goto fail_gpio_d;
+ }
+
+ /* Enable the keypad controller; GPIO ports C and D used for keypad */
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+ EP93XX_SYSCON_DEVCFG_GONK);
+
+ return 0;
+
+fail_gpio_d:
+ gpio_free(EP93XX_GPIO_LINE_C(i));
+fail_gpio_c:
+ for ( ; i >= 0; --i) {
+ gpio_free(EP93XX_GPIO_LINE_C(i));
+ gpio_free(EP93XX_GPIO_LINE_D(i));
+ }
+ return err;
+}
+EXPORT_SYMBOL(ep93xx_keypad_acquire_gpio);
+
+void ep93xx_keypad_release_gpio(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ gpio_free(EP93XX_GPIO_LINE_C(i));
+ gpio_free(EP93XX_GPIO_LINE_D(i));
+ }
+
+ /* Disable the keypad controller; GPIO ports C and D used for GPIO */
+ ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+ EP93XX_SYSCON_DEVCFG_GONK);
+}
+EXPORT_SYMBOL(ep93xx_keypad_release_gpio);
+
+/*************************************************************************
+ * EP93xx I2S audio peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_i2s_resource[] = {
+ {
+ .start = EP93XX_I2S_PHYS_BASE,
+ .end = EP93XX_I2S_PHYS_BASE + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ep93xx_i2s_device = {
+ .name = "ep93xx-i2s",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ep93xx_i2s_resource),
+ .resource = ep93xx_i2s_resource,
+};
+
+static struct platform_device ep93xx_pcm_device = {
+ .name = "ep93xx-pcm-audio",
+ .id = -1,
+};
+
+void __init ep93xx_register_i2s(void)
+{
+ platform_device_register(&ep93xx_i2s_device);
+ platform_device_register(&ep93xx_pcm_device);
+}
+
+#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \
+ EP93XX_SYSCON_DEVCFG_I2SONAC97)
+
+#define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \
+ EP93XX_SYSCON_I2SCLKDIV_SPOL)
+
+int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
+{
+ unsigned val;
+
+ /* Sanity check */
+ if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK)
+ return -EINVAL;
+ if (i2s_config & ~EP93XX_I2SCLKDIV_MASK)
+ return -EINVAL;
+
+ /* Must have only one of I2SONSSP/I2SONAC97 set */
+ if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) ==
+ (i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97))
+ return -EINVAL;
+
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
+ ep93xx_devcfg_set_bits(i2s_pins);
+
+ /*
+ * This is potentially racy with the clock api for i2s_mclk, sclk and
+ * lrclk. Since the i2s driver is the only user of those clocks we
+ * rely on it to prevent parallel use of this function and the
+ * clock api for the i2s clocks.
+ */
+ val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
+ val &= ~EP93XX_I2SCLKDIV_MASK;
+ val |= i2s_config;
+ ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV);
+
+ return 0;
+}
+EXPORT_SYMBOL(ep93xx_i2s_acquire);
+
+void ep93xx_i2s_release(void)
+{
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
+}
+EXPORT_SYMBOL(ep93xx_i2s_release);
+
+/*************************************************************************
+ * EP93xx AC97 audio peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_ac97_resources[] = {
+ {
+ .start = EP93XX_AAC_PHYS_BASE,
+ .end = EP93XX_AAC_PHYS_BASE + 0xac - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_EP93XX_AACINTR,
+ .end = IRQ_EP93XX_AACINTR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ep93xx_ac97_device = {
+ .name = "ep93xx-ac97",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ep93xx_ac97_resources),
+ .resource = ep93xx_ac97_resources,
+};
+
+void __init ep93xx_register_ac97(void)
+{
+ /*
+ * Make sure that the AC97 pins are not used by I2S.
+ */
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97);
+
+ platform_device_register(&ep93xx_ac97_device);
+ platform_device_register(&ep93xx_pcm_device);
+}
+
+void __init ep93xx_init_devices(void)
+{
+ /* Disallow access to MaverickCrunch initially */
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);
+
+ /* Get the GPIO working early, other devices need it */
+ platform_device_register(&ep93xx_gpio_device);
+
+ amba_device_register(&uart1_device, &iomem_resource);
+ amba_device_register(&uart2_device, &iomem_resource);
+ amba_device_register(&uart3_device, &iomem_resource);
+
+ platform_device_register(&ep93xx_rtc_device);
+ platform_device_register(&ep93xx_ohci_device);
+ platform_device_register(&ep93xx_leds);
+}
+
+void ep93xx_restart(char mode, const char *cmd)
+{
+ /*
+ * Set then clear the SWRST bit to initiate a software reset
+ */
+ ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST);
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST);
+
+ while (1)
+ ;
+}
diff --git a/arch/arm/mach-ep93xx/dma.c b/arch/arm/mach-ep93xx/dma.c
new file mode 100644
index 00000000000..5a257088125
--- /dev/null
+++ b/arch/arm/mach-ep93xx/dma.c
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ep93xx/dma.c
+ *
+ * Platform support code for the EP93xx dmaengine driver.
+ *
+ * Copyright (C) 2011 Mika Westerberg
+ *
+ * This work is based on the original dma-m2p implementation with
+ * following copyrights:
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2006 Applied Data Systems
+ * Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
+ *
+ * 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.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+#define DMA_CHANNEL(_name, _base, _irq) \
+ { .name = (_name), .base = (_base), .irq = (_irq) }
+
+/*
+ * DMA M2P channels.
+ *
+ * On the EP93xx chip the following peripherals my be allocated to the 10
+ * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
+ *
+ * I2S contains 3 Tx and 3 Rx DMA Channels
+ * AAC contains 3 Tx and 3 Rx DMA Channels
+ * UART1 contains 1 Tx and 1 Rx DMA Channels
+ * UART2 contains 1 Tx and 1 Rx DMA Channels
+ * UART3 contains 1 Tx and 1 Rx DMA Channels
+ * IrDA contains 1 Tx and 1 Rx DMA Channels
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
+ DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
+ DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
+ DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
+ DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
+ DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
+ DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
+ DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
+ DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
+ DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
+ DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
+ .channels = ep93xx_dma_m2p_channels,
+ .num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels),
+};
+
+static struct platform_device ep93xx_dma_m2p_device = {
+ .name = "ep93xx-dma-m2p",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_dma_m2p_data,
+ },
+};
+
+/*
+ * DMA M2M channels.
+ *
+ * There are 2 M2M channels which support memcpy/memset and in addition simple
+ * hardware requests from/to SSP and IDE. We do not implement an external
+ * hardware requests.
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
+ DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
+ DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
+ .channels = ep93xx_dma_m2m_channels,
+ .num_channels = ARRAY_SIZE(ep93xx_dma_m2m_channels),
+};
+
+static struct platform_device ep93xx_dma_m2m_device = {
+ .name = "ep93xx-dma-m2m",
+ .id = -1,
+ .dev = {
+ .platform_data = &ep93xx_dma_m2m_data,
+ },
+};
+
+static int __init ep93xx_dma_init(void)
+{
+ platform_device_register(&ep93xx_dma_m2p_device);
+ platform_device_register(&ep93xx_dma_m2m_device);
+ return 0;
+}
+arch_initcall(ep93xx_dma_init);
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
new file mode 100644
index 00000000000..d115653edca
--- /dev/null
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -0,0 +1,350 @@
+/*
+ * arch/arm/mach-ep93xx/edb93xx.c
+ * Cirrus Logic EDB93xx Development Board support.
+ *
+ * EDB93XX, EDB9301, EDB9307A
+ * Copyright (C) 2008-2009 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * EDB9302
+ * Copyright (C) 2006 George Kashperko <george@chas.com.ua>
+ *
+ * EDB9302A, EDB9315, EDB9315A
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * EDB9307
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * EDB9312
+ * Copyright (C) 2006 Infosys Technologies Limited
+ * Toufeeq Hussain <toufeeq_hussain@infosys.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+
+#include <sound/cs4271.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+
+static void __init edb93xx_register_flash(void)
+{
+ if (machine_is_edb9307() || machine_is_edb9312() ||
+ machine_is_edb9315()) {
+ ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
+ } else {
+ ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
+ }
+}
+
+static struct ep93xx_eth_data __initdata edb93xx_eth_data = {
+ .phy_id = 1,
+};
+
+
+/*************************************************************************
+ * EDB93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data __initdata edb93xx_i2c_gpio_data = {
+ .sda_pin = EP93XX_GPIO_LINE_EEDAT,
+ .sda_is_open_drain = 0,
+ .scl_pin = EP93XX_GPIO_LINE_EECLK,
+ .scl_is_open_drain = 0,
+ .udelay = 0, /* default to 100 kHz */
+ .timeout = 0, /* default to 100 ms */
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("isl1208", 0x6f),
+ },
+};
+
+static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("ds1337", 0x68),
+ },
+};
+
+static void __init edb93xx_register_i2c(void)
+{
+ if (machine_is_edb9302a() || machine_is_edb9307a() ||
+ machine_is_edb9315a()) {
+ ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
+ edb93xxa_i2c_board_info,
+ ARRAY_SIZE(edb93xxa_i2c_board_info));
+ } else if (machine_is_edb9307() || machine_is_edb9312() ||
+ machine_is_edb9315()) {
+ ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
+ edb93xx_i2c_board_info,
+ ARRAY_SIZE(edb93xx_i2c_board_info));
+ }
+}
+
+
+/*************************************************************************
+ * EDB93xx SPI peripheral handling
+ *************************************************************************/
+static struct cs4271_platform_data edb93xx_cs4271_data = {
+ .gpio_nreset = -EINVAL, /* filled in later */
+};
+
+static int edb93xx_cs4271_hw_setup(struct spi_device *spi)
+{
+ return gpio_request_one(EP93XX_GPIO_LINE_EGPIO6,
+ GPIOF_OUT_INIT_HIGH, spi->modalias);
+}
+
+static void edb93xx_cs4271_hw_cleanup(struct spi_device *spi)
+{
+ gpio_free(EP93XX_GPIO_LINE_EGPIO6);
+}
+
+static void edb93xx_cs4271_hw_cs_control(struct spi_device *spi, int value)
+{
+ gpio_set_value(EP93XX_GPIO_LINE_EGPIO6, value);
+}
+
+static struct ep93xx_spi_chip_ops edb93xx_cs4271_hw = {
+ .setup = edb93xx_cs4271_hw_setup,
+ .cleanup = edb93xx_cs4271_hw_cleanup,
+ .cs_control = edb93xx_cs4271_hw_cs_control,
+};
+
+static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
+ {
+ .modalias = "cs4271",
+ .platform_data = &edb93xx_cs4271_data,
+ .controller_data = &edb93xx_cs4271_hw,
+ .max_speed_hz = 6000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ },
+};
+
+static struct ep93xx_spi_info edb93xx_spi_info __initdata = {
+ .num_chipselect = ARRAY_SIZE(edb93xx_spi_board_info),
+};
+
+static void __init edb93xx_register_spi(void)
+{
+ if (machine_is_edb9301() || machine_is_edb9302())
+ edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO1;
+ else if (machine_is_edb9302a() || machine_is_edb9307a())
+ edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_H(2);
+ else if (machine_is_edb9315a())
+ edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO14;
+
+ ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info,
+ ARRAY_SIZE(edb93xx_spi_board_info));
+}
+
+
+/*************************************************************************
+ * EDB93xx I2S
+ *************************************************************************/
+static struct platform_device edb93xx_audio_device = {
+ .name = "edb93xx-audio",
+ .id = -1,
+};
+
+static int __init edb93xx_has_audio(void)
+{
+ return (machine_is_edb9301() || machine_is_edb9302() ||
+ machine_is_edb9302a() || machine_is_edb9307a() ||
+ machine_is_edb9315a());
+}
+
+static void __init edb93xx_register_i2s(void)
+{
+ if (edb93xx_has_audio()) {
+ ep93xx_register_i2s();
+ platform_device_register(&edb93xx_audio_device);
+ }
+}
+
+
+/*************************************************************************
+ * EDB93xx pwm
+ *************************************************************************/
+static void __init edb93xx_register_pwm(void)
+{
+ if (machine_is_edb9301() ||
+ machine_is_edb9302() || machine_is_edb9302a()) {
+ /* EP9301 and EP9302 only have pwm.1 (EGPIO14) */
+ ep93xx_register_pwm(0, 1);
+ } else if (machine_is_edb9307() || machine_is_edb9307a()) {
+ /* EP9307 only has pwm.0 (PWMOUT) */
+ ep93xx_register_pwm(1, 0);
+ } else {
+ /* EP9312 and EP9315 have both */
+ ep93xx_register_pwm(1, 1);
+ }
+}
+
+
+/*************************************************************************
+ * EDB93xx framebuffer
+ *************************************************************************/
+static struct ep93xxfb_mach_info __initdata edb93xxfb_info = {
+ .num_modes = EP93XXFB_USE_MODEDB,
+ .bpp = 16,
+ .flags = 0,
+};
+
+static int __init edb93xx_has_fb(void)
+{
+ /* These platforms have an ep93xx with video capability */
+ return machine_is_edb9307() || machine_is_edb9307a() ||
+ machine_is_edb9312() || machine_is_edb9315() ||
+ machine_is_edb9315a();
+}
+
+static void __init edb93xx_register_fb(void)
+{
+ if (!edb93xx_has_fb())
+ return;
+
+ if (machine_is_edb9307a() || machine_is_edb9315a())
+ edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0;
+ else
+ edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3;
+
+ ep93xx_register_fb(&edb93xxfb_info);
+}
+
+
+static void __init edb93xx_init_machine(void)
+{
+ ep93xx_init_devices();
+ edb93xx_register_flash();
+ ep93xx_register_eth(&edb93xx_eth_data, 1);
+ edb93xx_register_i2c();
+ edb93xx_register_spi();
+ edb93xx_register_i2s();
+ edb93xx_register_pwm();
+ edb93xx_register_fb();
+}
+
+
+#ifdef CONFIG_MACH_EDB9301
+MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
+ /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb93xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9302
+MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
+ /* Maintainer: George Kashperko <george@chas.com.ua> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb93xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9302A
+MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
+ /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb93xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9307
+MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
+ /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb93xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9307A
+MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
+ /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb93xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9312
+MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
+ /* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb93xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9315
+MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
+ /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb93xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9315A
+MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
+ /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = edb93xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
new file mode 100644
index 00000000000..af46970dc58
--- /dev/null
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-ep93xx/gesbc9312.c
+ * Glomation GESBC-9312-sx support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+
+static struct ep93xx_eth_data __initdata gesbc9312_eth_data = {
+ .phy_id = 1,
+};
+
+static void __init gesbc9312_init_machine(void)
+{
+ ep93xx_init_devices();
+ ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_8M);
+ ep93xx_register_eth(&gesbc9312_eth_data, 0);
+}
+
+MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
+ /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = gesbc9312_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/include/mach/debug-macro.S b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
new file mode 100644
index 00000000000..af54e43132c
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
@@ -0,0 +1,21 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/debug-macro.S
+ * Debugging macro include header
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * 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.
+ */
+#include <mach/ep93xx-regs.h>
+
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =EP93XX_APB_PHYS_BASE @ Physical base
+ ldr \rv, =EP93XX_APB_VIRT_BASE @ virtual base
+ orr \rp, \rp, #0x000c0000
+ orr \rv, \rv, #0x000c0000
+ .endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
new file mode 100644
index 00000000000..e82c642fa53
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/dma.h
@@ -0,0 +1,93 @@
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#include <linux/types.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+
+/*
+ * M2P channels.
+ *
+ * Note that these values are also directly used for setting the PPALLOC
+ * register.
+ */
+#define EP93XX_DMA_I2S1 0
+#define EP93XX_DMA_I2S2 1
+#define EP93XX_DMA_AAC1 2
+#define EP93XX_DMA_AAC2 3
+#define EP93XX_DMA_AAC3 4
+#define EP93XX_DMA_I2S3 5
+#define EP93XX_DMA_UART1 6
+#define EP93XX_DMA_UART2 7
+#define EP93XX_DMA_UART3 8
+#define EP93XX_DMA_IRDA 9
+/* M2M channels */
+#define EP93XX_DMA_SSP 10
+#define EP93XX_DMA_IDE 11
+
+/**
+ * struct ep93xx_dma_data - configuration data for the EP93xx dmaengine
+ * @port: peripheral which is requesting the channel
+ * @direction: TX/RX channel
+ * @name: optional name for the channel, this is displayed in /proc/interrupts
+ *
+ * This information is passed as private channel parameter in a filter
+ * function. Note that this is only needed for slave/cyclic channels. For
+ * memcpy channels %NULL data should be passed.
+ */
+struct ep93xx_dma_data {
+ int port;
+ enum dma_transfer_direction direction;
+ const char *name;
+};
+
+/**
+ * struct ep93xx_dma_chan_data - platform specific data for a DMA channel
+ * @name: name of the channel, used for getting the right clock for the channel
+ * @base: mapped registers
+ * @irq: interrupt number used by this channel
+ */
+struct ep93xx_dma_chan_data {
+ const char *name;
+ void __iomem *base;
+ int irq;
+};
+
+/**
+ * struct ep93xx_dma_platform_data - platform data for the dmaengine driver
+ * @channels: array of channels which are passed to the driver
+ * @num_channels: number of channels in the array
+ *
+ * This structure is passed to the DMA engine driver via platform data. For
+ * M2P channels, contract is that even channels are for TX and odd for RX.
+ * There is no requirement for the M2M channels.
+ */
+struct ep93xx_dma_platform_data {
+ struct ep93xx_dma_chan_data *channels;
+ size_t num_channels;
+};
+
+static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan)
+{
+ return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p");
+}
+
+/**
+ * ep93xx_dma_chan_direction - returns direction the channel can be used
+ * @chan: channel
+ *
+ * This function can be used in filter functions to find out whether the
+ * channel supports given DMA direction. Only M2P channels have such
+ * limitation, for M2M channels the direction is configurable.
+ */
+static inline enum dma_transfer_direction
+ep93xx_dma_chan_direction(struct dma_chan *chan)
+{
+ if (!ep93xx_dma_chan_is_m2p(chan))
+ return DMA_NONE;
+
+ /* even channels are for TX, odd for RX */
+ return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+}
+
+#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/entry-macro.S b/arch/arm/mach-ep93xx/include/mach/entry-macro.S
new file mode 100644
index 00000000000..9be6edcf904
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/entry-macro.S
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/entry-macro.S
+ * IRQ demultiplexing for EP93xx
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * 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.
+ */
+
+ .macro disable_fiq
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
new file mode 100644
index 00000000000..c4a7b84ef06
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -0,0 +1,230 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+ */
+
+#ifndef __ASM_ARCH_EP93XX_REGS_H
+#define __ASM_ARCH_EP93XX_REGS_H
+
+/*
+ * EP93xx Physical Memory Map:
+ *
+ * The ASDO pin is sampled at system reset to select a synchronous or
+ * asynchronous boot configuration. When ASDO is "1" (i.e. pulled-up)
+ * the synchronous boot mode is selected. When ASDO is "0" (i.e
+ * pulled-down) the asynchronous boot mode is selected.
+ *
+ * In synchronous boot mode nSDCE3 is decoded starting at physical address
+ * 0x00000000 and nCS0 is decoded starting at 0xf0000000. For asynchronous
+ * boot mode they are swapped with nCS0 decoded at 0x00000000 ann nSDCE3
+ * decoded at 0xf0000000.
+ *
+ * There is known errata for the EP93xx dealing with External Memory
+ * Configurations. Please refer to "AN273: EP93xx Silicon Rev E Design
+ * Guidelines" for more information. This document can be found at:
+ *
+ * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
+ */
+
+#define EP93XX_CS0_PHYS_BASE_ASYNC 0x00000000 /* ASDO Pin = 0 */
+#define EP93XX_SDCE3_PHYS_BASE_SYNC 0x00000000 /* ASDO Pin = 1 */
+#define EP93XX_CS1_PHYS_BASE 0x10000000
+#define EP93XX_CS2_PHYS_BASE 0x20000000
+#define EP93XX_CS3_PHYS_BASE 0x30000000
+#define EP93XX_PCMCIA_PHYS_BASE 0x40000000
+#define EP93XX_CS6_PHYS_BASE 0x60000000
+#define EP93XX_CS7_PHYS_BASE 0x70000000
+#define EP93XX_SDCE0_PHYS_BASE 0xc0000000
+#define EP93XX_SDCE1_PHYS_BASE 0xd0000000
+#define EP93XX_SDCE2_PHYS_BASE 0xe0000000
+#define EP93XX_SDCE3_PHYS_BASE_ASYNC 0xf0000000 /* ASDO Pin = 0 */
+#define EP93XX_CS0_PHYS_BASE_SYNC 0xf0000000 /* ASDO Pin = 1 */
+
+/*
+ * EP93xx linux memory map:
+ *
+ * virt phys size
+ * fe800000 5M per-platform mappings
+ * fed00000 80800000 2M APB
+ * fef00000 80000000 1M AHB
+ */
+
+#define EP93XX_AHB_PHYS_BASE 0x80000000
+#define EP93XX_AHB_VIRT_BASE 0xfef00000
+#define EP93XX_AHB_SIZE 0x00100000
+
+#define EP93XX_AHB_PHYS(x) (EP93XX_AHB_PHYS_BASE + (x))
+#define EP93XX_AHB_IOMEM(x) IOMEM(EP93XX_AHB_VIRT_BASE + (x))
+
+#define EP93XX_APB_PHYS_BASE 0x80800000
+#define EP93XX_APB_VIRT_BASE 0xfed00000
+#define EP93XX_APB_SIZE 0x00200000
+
+#define EP93XX_APB_PHYS(x) (EP93XX_APB_PHYS_BASE + (x))
+#define EP93XX_APB_IOMEM(x) IOMEM(EP93XX_APB_VIRT_BASE + (x))
+
+
+/* AHB peripherals */
+#define EP93XX_DMA_BASE EP93XX_AHB_IOMEM(0x00000000)
+
+#define EP93XX_ETHERNET_PHYS_BASE EP93XX_AHB_PHYS(0x00010000)
+#define EP93XX_ETHERNET_BASE EP93XX_AHB_IOMEM(0x00010000)
+
+#define EP93XX_USB_PHYS_BASE EP93XX_AHB_PHYS(0x00020000)
+#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000)
+
+#define EP93XX_RASTER_PHYS_BASE EP93XX_AHB_PHYS(0x00030000)
+#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000)
+
+#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000)
+
+#define EP93XX_SDRAM_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00060000)
+
+#define EP93XX_PCMCIA_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00080000)
+
+#define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000)
+
+#define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000)
+
+#define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000)
+
+#define EP93XX_VIC2_BASE EP93XX_AHB_IOMEM(0x000c0000)
+
+
+/* APB peripherals */
+#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000)
+
+#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000)
+#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
+
+#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
+
+#define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000)
+#define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000)
+#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
+#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
+#define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0)
+#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8)
+
+#define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000)
+#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000)
+
+#define EP93XX_SPI_PHYS_BASE EP93XX_APB_PHYS(0x000a0000)
+#define EP93XX_SPI_BASE EP93XX_APB_IOMEM(0x000a0000)
+
+#define EP93XX_IRDA_BASE EP93XX_APB_IOMEM(0x000b0000)
+
+#define EP93XX_UART1_PHYS_BASE EP93XX_APB_PHYS(0x000c0000)
+#define EP93XX_UART1_BASE EP93XX_APB_IOMEM(0x000c0000)
+
+#define EP93XX_UART2_PHYS_BASE EP93XX_APB_PHYS(0x000d0000)
+#define EP93XX_UART2_BASE EP93XX_APB_IOMEM(0x000d0000)
+
+#define EP93XX_UART3_PHYS_BASE EP93XX_APB_PHYS(0x000e0000)
+#define EP93XX_UART3_BASE EP93XX_APB_IOMEM(0x000e0000)
+
+#define EP93XX_KEY_MATRIX_PHYS_BASE EP93XX_APB_PHYS(0x000f0000)
+#define EP93XX_KEY_MATRIX_BASE EP93XX_APB_IOMEM(0x000f0000)
+
+#define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000)
+#define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000)
+
+#define EP93XX_PWM_PHYS_BASE EP93XX_APB_PHYS(0x00110000)
+#define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000)
+
+#define EP93XX_RTC_PHYS_BASE EP93XX_APB_PHYS(0x00120000)
+#define EP93XX_RTC_BASE EP93XX_APB_IOMEM(0x00120000)
+
+#define EP93XX_SYSCON_BASE EP93XX_APB_IOMEM(0x00130000)
+#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x))
+#define EP93XX_SYSCON_POWER_STATE EP93XX_SYSCON_REG(0x00)
+#define EP93XX_SYSCON_PWRCNT EP93XX_SYSCON_REG(0x04)
+#define EP93XX_SYSCON_PWRCNT_FIR_EN (1<<31)
+#define EP93XX_SYSCON_PWRCNT_UARTBAUD (1<<29)
+#define EP93XX_SYSCON_PWRCNT_USH_EN (1<<28)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2M1 (1<<27)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2M0 (1<<26)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P8 (1<<25)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P9 (1<<24)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P6 (1<<23)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P7 (1<<22)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P4 (1<<21)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P5 (1<<20)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P2 (1<<19)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P3 (1<<18)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P0 (1<<17)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 (1<<16)
+#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08)
+#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c)
+#define EP93XX_SYSCON_CLKSET1 EP93XX_SYSCON_REG(0x20)
+#define EP93XX_SYSCON_CLKSET1_NBYP1 (1<<23)
+#define EP93XX_SYSCON_CLKSET2 EP93XX_SYSCON_REG(0x24)
+#define EP93XX_SYSCON_CLKSET2_NBYP2 (1<<19)
+#define EP93XX_SYSCON_CLKSET2_PLL2_EN (1<<18)
+#define EP93XX_SYSCON_DEVCFG EP93XX_SYSCON_REG(0x80)
+#define EP93XX_SYSCON_DEVCFG_SWRST (1<<31)
+#define EP93XX_SYSCON_DEVCFG_D1ONG (1<<30)
+#define EP93XX_SYSCON_DEVCFG_D0ONG (1<<29)
+#define EP93XX_SYSCON_DEVCFG_IONU2 (1<<28)
+#define EP93XX_SYSCON_DEVCFG_GONK (1<<27)
+#define EP93XX_SYSCON_DEVCFG_TONG (1<<26)
+#define EP93XX_SYSCON_DEVCFG_MONG (1<<25)
+#define EP93XX_SYSCON_DEVCFG_U3EN (1<<24)
+#define EP93XX_SYSCON_DEVCFG_CPENA (1<<23)
+#define EP93XX_SYSCON_DEVCFG_A2ONG (1<<22)
+#define EP93XX_SYSCON_DEVCFG_A1ONG (1<<21)
+#define EP93XX_SYSCON_DEVCFG_U2EN (1<<20)
+#define EP93XX_SYSCON_DEVCFG_EXVC (1<<19)
+#define EP93XX_SYSCON_DEVCFG_U1EN (1<<18)
+#define EP93XX_SYSCON_DEVCFG_TIN (1<<17)
+#define EP93XX_SYSCON_DEVCFG_HC3IN (1<<15)
+#define EP93XX_SYSCON_DEVCFG_HC3EN (1<<14)
+#define EP93XX_SYSCON_DEVCFG_HC1IN (1<<13)
+#define EP93XX_SYSCON_DEVCFG_HC1EN (1<<12)
+#define EP93XX_SYSCON_DEVCFG_HONIDE (1<<11)
+#define EP93XX_SYSCON_DEVCFG_GONIDE (1<<10)
+#define EP93XX_SYSCON_DEVCFG_PONG (1<<9)
+#define EP93XX_SYSCON_DEVCFG_EONIDE (1<<8)
+#define EP93XX_SYSCON_DEVCFG_I2SONSSP (1<<7)
+#define EP93XX_SYSCON_DEVCFG_I2SONAC97 (1<<6)
+#define EP93XX_SYSCON_DEVCFG_RASONP3 (1<<4)
+#define EP93XX_SYSCON_DEVCFG_RAS (1<<3)
+#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2)
+#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1)
+#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0)
+#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84)
+#define EP93XX_SYSCON_CLKDIV_ENABLE (1<<15)
+#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14)
+#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13)
+#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
+#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c)
+#define EP93XX_SYSCON_I2SCLKDIV_SENA (1<<31)
+#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29)
+#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19)
+#define EP93XX_I2SCLKDIV_SDIV (1 << 16)
+#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17)
+#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17)
+#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17)
+#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17)
+#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90)
+#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31)
+#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16)
+#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN (1<<15)
+#define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV (1<<0)
+#define EP93XX_SYSCON_SYSCFG EP93XX_SYSCON_REG(0x9c)
+#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000)
+#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28)
+#define EP93XX_SYSCON_SYSCFG_SBOOT (1<<8)
+#define EP93XX_SYSCON_SYSCFG_LCSN7 (1<<7)
+#define EP93XX_SYSCON_SYSCFG_LCSN6 (1<<6)
+#define EP93XX_SYSCON_SYSCFG_LASDO (1<<5)
+#define EP93XX_SYSCON_SYSCFG_LEEDA (1<<4)
+#define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3)
+#define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1)
+#define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0)
+#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
+
+#define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000)
+
+
+#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
new file mode 100644
index 00000000000..1e2f4e97f42
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
+ */
+
+#ifndef __ASM_ARCH_EP93XX_KEYPAD_H
+#define __ASM_ARCH_EP93XX_KEYPAD_H
+
+struct matrix_keymap_data;
+
+/* flags for the ep93xx_keypad driver */
+#define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */
+#define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */
+#define EP93XX_KEYPAD_BACK_DRIVE (1<<2) /* back driving mode */
+#define EP93XX_KEYPAD_TEST_MODE (1<<3) /* scan only column 0 */
+#define EP93XX_KEYPAD_KDIV (1<<4) /* 1/4 clock or 1/16 clock */
+#define EP93XX_KEYPAD_AUTOREPEAT (1<<5) /* enable key autorepeat */
+
+/**
+ * struct ep93xx_keypad_platform_data - platform specific device structure
+ * @keymap_data: pointer to &matrix_keymap_data
+ * @debounce: debounce start count; terminal count is 0xff
+ * @prescale: row/column counter pre-scaler load value
+ * @flags: see above
+ */
+struct ep93xx_keypad_platform_data {
+ struct matrix_keymap_data *keymap_data;
+ unsigned int debounce;
+ unsigned int prescale;
+ unsigned int flags;
+};
+
+#define EP93XX_MATRIX_ROWS (8)
+#define EP93XX_MATRIX_COLS (8)
+
+#endif /* __ASM_ARCH_EP93XX_KEYPAD_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
new file mode 100644
index 00000000000..9bb63ac13f0
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
@@ -0,0 +1,29 @@
+#ifndef __ASM_MACH_EP93XX_SPI_H
+#define __ASM_MACH_EP93XX_SPI_H
+
+struct spi_device;
+
+/**
+ * struct ep93xx_spi_info - EP93xx specific SPI descriptor
+ * @num_chipselect: number of chip selects on this board, must be
+ * at least one
+ * @use_dma: use DMA for the transfers
+ */
+struct ep93xx_spi_info {
+ int num_chipselect;
+ bool use_dma;
+};
+
+/**
+ * struct ep93xx_spi_chip_ops - operation callbacks for SPI slave device
+ * @setup: setup the chip select mechanism
+ * @cleanup: cleanup the chip select mechanism
+ * @cs_control: control the device chip select
+ */
+struct ep93xx_spi_chip_ops {
+ int (*setup)(struct spi_device *spi);
+ void (*cleanup)(struct spi_device *spi);
+ void (*cs_control)(struct spi_device *spi, int value);
+};
+
+#endif /* __ASM_MACH_EP93XX_SPI_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/fb.h b/arch/arm/mach-ep93xx/include/mach/fb.h
new file mode 100644
index 00000000000..d5ae11d7c45
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/fb.h
@@ -0,0 +1,56 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/fb.h
+ */
+
+#ifndef __ASM_ARCH_EP93XXFB_H
+#define __ASM_ARCH_EP93XXFB_H
+
+struct platform_device;
+struct fb_videomode;
+struct fb_info;
+
+#define EP93XXFB_USE_MODEDB 0
+
+/* VideoAttributes flags */
+#define EP93XXFB_STATE_MACHINE_ENABLE (1 << 0)
+#define EP93XXFB_PIXEL_CLOCK_ENABLE (1 << 1)
+#define EP93XXFB_VSYNC_ENABLE (1 << 2)
+#define EP93XXFB_PIXEL_DATA_ENABLE (1 << 3)
+#define EP93XXFB_COMPOSITE_SYNC (1 << 4)
+#define EP93XXFB_SYNC_VERT_HIGH (1 << 5)
+#define EP93XXFB_SYNC_HORIZ_HIGH (1 << 6)
+#define EP93XXFB_SYNC_BLANK_HIGH (1 << 7)
+#define EP93XXFB_PCLK_FALLING (1 << 8)
+#define EP93XXFB_ENABLE_AC (1 << 9)
+#define EP93XXFB_ENABLE_LCD (1 << 10)
+#define EP93XXFB_ENABLE_CCIR (1 << 12)
+#define EP93XXFB_USE_PARALLEL_INTERFACE (1 << 13)
+#define EP93XXFB_ENABLE_INTERRUPT (1 << 14)
+#define EP93XXFB_USB_INTERLACE (1 << 16)
+#define EP93XXFB_USE_EQUALIZATION (1 << 17)
+#define EP93XXFB_USE_DOUBLE_HORZ (1 << 18)
+#define EP93XXFB_USE_DOUBLE_VERT (1 << 19)
+#define EP93XXFB_USE_BLANK_PIXEL (1 << 20)
+#define EP93XXFB_USE_SDCSN0 (0 << 21)
+#define EP93XXFB_USE_SDCSN1 (1 << 21)
+#define EP93XXFB_USE_SDCSN2 (2 << 21)
+#define EP93XXFB_USE_SDCSN3 (3 << 21)
+
+#define EP93XXFB_ENABLE (EP93XXFB_STATE_MACHINE_ENABLE | \
+ EP93XXFB_PIXEL_CLOCK_ENABLE | \
+ EP93XXFB_VSYNC_ENABLE | \
+ EP93XXFB_PIXEL_DATA_ENABLE)
+
+struct ep93xxfb_mach_info {
+ unsigned int num_modes;
+ const struct fb_videomode *modes;
+ const struct fb_videomode *default_mode;
+ int bpp;
+ unsigned int flags;
+
+ int (*setup)(struct platform_device *pdev);
+ void (*teardown)(struct platform_device *pdev);
+ void (*blank)(int blank_mode, struct fb_info *info);
+};
+
+#endif /* __ASM_ARCH_EP93XXFB_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
new file mode 100644
index 00000000000..8aff2ea3587
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
@@ -0,0 +1,100 @@
+/* Include file for the EP93XX GPIO controller machine specifics */
+
+#ifndef __GPIO_EP93XX_H
+#define __GPIO_EP93XX_H
+
+/* GPIO port A. */
+#define EP93XX_GPIO_LINE_A(x) ((x) + 0)
+#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0)
+#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1)
+#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2)
+#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3)
+#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4)
+#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5)
+#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6)
+#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7)
+
+/* GPIO port B. */
+#define EP93XX_GPIO_LINE_B(x) ((x) + 8)
+#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0)
+#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1)
+#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2)
+#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3)
+#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4)
+#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5)
+#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6)
+#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7)
+
+/* GPIO port C. */
+#define EP93XX_GPIO_LINE_C(x) ((x) + 40)
+#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0)
+#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1)
+#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2)
+#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3)
+#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4)
+#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5)
+#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6)
+#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7)
+
+/* GPIO port D. */
+#define EP93XX_GPIO_LINE_D(x) ((x) + 24)
+#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0)
+#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1)
+#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2)
+#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3)
+#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4)
+#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5)
+#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6)
+#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7)
+
+/* GPIO port E. */
+#define EP93XX_GPIO_LINE_E(x) ((x) + 32)
+#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0)
+#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1)
+#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2)
+#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3)
+#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4)
+#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5)
+#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6)
+#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7)
+
+/* GPIO port F. */
+#define EP93XX_GPIO_LINE_F(x) ((x) + 16)
+#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0)
+#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1)
+#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2)
+#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3)
+#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4)
+#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5)
+#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6)
+#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7)
+
+/* GPIO port G. */
+#define EP93XX_GPIO_LINE_G(x) ((x) + 48)
+#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0)
+#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1)
+#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2)
+#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3)
+#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4)
+#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5)
+#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6)
+#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7)
+
+/* GPIO port H. */
+#define EP93XX_GPIO_LINE_H(x) ((x) + 56)
+#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0)
+#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1)
+#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2)
+#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3)
+#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4)
+#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5)
+#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6)
+#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for gpio line identifiers */
+#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for irq capable line identifiers */
+#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7)
+
+#endif /* __GPIO_EP93XX_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h
new file mode 100644
index 00000000000..40a8c178f10
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h
new file mode 100644
index 00000000000..4df842897ea
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/hardware.h
@@ -0,0 +1,25 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/hardware.h
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <mach/ep93xx-regs.h>
+#include <mach/platform.h>
+
+/*
+ * The EP93xx has two external crystal oscillators. To generate the
+ * required high-frequency clocks, the processor uses two phase-locked-
+ * loops (PLLs) to multiply the incoming external clock signal to much
+ * higher frequencies that are then divided down by programmable dividers
+ * to produce the needed clocks. The PLLs operate independently of one
+ * another.
+ */
+#define EP93XX_EXT_CLK_RATE 14745600
+#define EP93XX_EXT_RTC_RATE 32768
+
+#define EP93XX_KEYTCHCLK_DIV4 (EP93XX_EXT_CLK_RATE / 4)
+#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16)
+
+#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/io.h b/arch/arm/mach-ep93xx/include/mach/io.h
new file mode 100644
index 00000000000..594b77f2105
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/io.h
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/io.h
+ */
+
+#ifndef __ASM_MACH_IO_H
+#define __ASM_MACH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(p) __typesafe_io(p)
+#define __mem_pci(p) (p)
+
+/*
+ * A typesafe __io() variation for variable initialisers
+ */
+#ifdef __ASSEMBLER__
+#define IOMEM(p) p
+#else
+#define IOMEM(p) ((void __iomem __force *)(p))
+#endif
+
+#endif /* __ASM_MACH_IO_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/irqs.h b/arch/arm/mach-ep93xx/include/mach/irqs.h
new file mode 100644
index 00000000000..ff98390bbf0
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/irqs.h
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/irqs.h
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define IRQ_EP93XX_COMMRX 2
+#define IRQ_EP93XX_COMMTX 3
+#define IRQ_EP93XX_TIMER1 4
+#define IRQ_EP93XX_TIMER2 5
+#define IRQ_EP93XX_AACINTR 6
+#define IRQ_EP93XX_DMAM2P0 7
+#define IRQ_EP93XX_DMAM2P1 8
+#define IRQ_EP93XX_DMAM2P2 9
+#define IRQ_EP93XX_DMAM2P3 10
+#define IRQ_EP93XX_DMAM2P4 11
+#define IRQ_EP93XX_DMAM2P5 12
+#define IRQ_EP93XX_DMAM2P6 13
+#define IRQ_EP93XX_DMAM2P7 14
+#define IRQ_EP93XX_DMAM2P8 15
+#define IRQ_EP93XX_DMAM2P9 16
+#define IRQ_EP93XX_DMAM2M0 17
+#define IRQ_EP93XX_DMAM2M1 18
+#define IRQ_EP93XX_GPIO0MUX 19
+#define IRQ_EP93XX_GPIO1MUX 20
+#define IRQ_EP93XX_GPIO2MUX 21
+#define IRQ_EP93XX_GPIO3MUX 22
+#define IRQ_EP93XX_UART1RX 23
+#define IRQ_EP93XX_UART1TX 24
+#define IRQ_EP93XX_UART2RX 25
+#define IRQ_EP93XX_UART2TX 26
+#define IRQ_EP93XX_UART3RX 27
+#define IRQ_EP93XX_UART3TX 28
+#define IRQ_EP93XX_KEY 29
+#define IRQ_EP93XX_TOUCH 30
+#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc
+
+#define IRQ_EP93XX_EXT0 32
+#define IRQ_EP93XX_EXT1 33
+#define IRQ_EP93XX_EXT2 34
+#define IRQ_EP93XX_64HZ 35
+#define IRQ_EP93XX_WATCHDOG 36
+#define IRQ_EP93XX_RTC 37
+#define IRQ_EP93XX_IRDA 38
+#define IRQ_EP93XX_ETHERNET 39
+#define IRQ_EP93XX_EXT3 40
+#define IRQ_EP93XX_PROG 41
+#define IRQ_EP93XX_1HZ 42
+#define IRQ_EP93XX_VSYNC 43
+#define IRQ_EP93XX_VIDEO_FIFO 44
+#define IRQ_EP93XX_SSP1RX 45
+#define IRQ_EP93XX_SSP1TX 46
+#define IRQ_EP93XX_GPIO4MUX 47
+#define IRQ_EP93XX_GPIO5MUX 48
+#define IRQ_EP93XX_GPIO6MUX 49
+#define IRQ_EP93XX_GPIO7MUX 50
+#define IRQ_EP93XX_TIMER3 51
+#define IRQ_EP93XX_UART1 52
+#define IRQ_EP93XX_SSP 53
+#define IRQ_EP93XX_UART2 54
+#define IRQ_EP93XX_UART3 55
+#define IRQ_EP93XX_USB 56
+#define IRQ_EP93XX_ETHERNET_PME 57
+#define IRQ_EP93XX_DSP 58
+#define IRQ_EP93XX_GPIO_AB 59
+#define IRQ_EP93XX_SAI 60
+#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff
+
+#define NR_EP93XX_IRQS (64 + 24)
+
+#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x))
+#define EP93XX_BOARD_IRQS 32
+
+#define NR_IRQS (NR_EP93XX_IRQS + EP93XX_BOARD_IRQS)
+
+
+#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h
new file mode 100644
index 00000000000..c9400cf0051
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/memory.h
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/memory.h
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#if defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)
+#define PLAT_PHYS_OFFSET UL(0x00000000)
+#elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)
+#define PLAT_PHYS_OFFSET UL(0xc0000000)
+#elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)
+#define PLAT_PHYS_OFFSET UL(0xd0000000)
+#elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)
+#define PLAT_PHYS_OFFSET UL(0xe0000000)
+#elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)
+#define PLAT_PHYS_OFFSET UL(0xf0000000)
+#else
+#error "Kconfig bug: No EP93xx PHYS_OFFSET set"
+#endif
+
+#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
new file mode 100644
index 00000000000..d4c934931f9
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/platform.h
+ */
+
+#ifndef __ASSEMBLY__
+
+struct i2c_gpio_platform_data;
+struct i2c_board_info;
+struct spi_board_info;
+struct platform_device;
+struct ep93xxfb_mach_info;
+struct ep93xx_keypad_platform_data;
+struct ep93xx_spi_info;
+
+struct ep93xx_eth_data
+{
+ unsigned char dev_addr[6];
+ unsigned char phy_id;
+};
+
+void ep93xx_map_io(void);
+void ep93xx_init_irq(void);
+
+/* EP93xx System Controller software locked register write */
+void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg);
+void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits);
+
+static inline void ep93xx_devcfg_set_bits(unsigned int bits)
+{
+ ep93xx_devcfg_set_clear(bits, 0x00);
+}
+
+static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
+{
+ ep93xx_devcfg_set_clear(0x00, bits);
+}
+
+#define EP93XX_CHIP_REV_D0 3
+#define EP93XX_CHIP_REV_D1 4
+#define EP93XX_CHIP_REV_E0 5
+#define EP93XX_CHIP_REV_E1 6
+#define EP93XX_CHIP_REV_E2 7
+
+unsigned int ep93xx_chip_revision(void);
+
+void ep93xx_register_flash(unsigned int width,
+ resource_size_t start, resource_size_t size);
+
+void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
+void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+ struct i2c_board_info *devices, int num);
+void ep93xx_register_spi(struct ep93xx_spi_info *info,
+ struct spi_board_info *devices, int num);
+void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
+void ep93xx_register_pwm(int pwm0, int pwm1);
+int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
+void ep93xx_pwm_release_gpio(struct platform_device *pdev);
+void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
+int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
+void ep93xx_keypad_release_gpio(struct platform_device *pdev);
+void ep93xx_register_i2s(void);
+int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config);
+void ep93xx_i2s_release(void);
+void ep93xx_register_ac97(void);
+
+void ep93xx_init_devices(void);
+extern struct sys_timer ep93xx_timer;
+
+void ep93xx_restart(char, const char *);
+
+#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h
new file mode 100644
index 00000000000..b5bec7cb9b5
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/system.h
@@ -0,0 +1,7 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/system.h
+ */
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
diff --git a/arch/arm/mach-ep93xx/include/mach/timex.h b/arch/arm/mach-ep93xx/include/mach/timex.h
new file mode 100644
index 00000000000..6b3503b01fa
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/timex.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/timex.h
+ */
+
+#define CLOCK_TICK_RATE 983040
diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
new file mode 100644
index 00000000000..f1397a13e76
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
@@ -0,0 +1,98 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/ts72xx.h
+ */
+
+/*
+ * TS72xx memory map:
+ *
+ * virt phys size
+ * febff000 22000000 4K model number register (bits 0-2)
+ * febfe000 22400000 4K options register
+ * febfd000 22800000 4K options register #2
+ * febf9000 10800000 4K TS-5620 RTC index register
+ * febf8000 11700000 4K TS-5620 RTC data register
+ */
+
+#define TS72XX_MODEL_PHYS_BASE 0x22000000
+#define TS72XX_MODEL_VIRT_BASE 0xfebff000
+#define TS72XX_MODEL_SIZE 0x00001000
+
+#define TS72XX_MODEL_TS7200 0x00
+#define TS72XX_MODEL_TS7250 0x01
+#define TS72XX_MODEL_TS7260 0x02
+#define TS72XX_MODEL_TS7300 0x03
+#define TS72XX_MODEL_TS7400 0x04
+#define TS72XX_MODEL_MASK 0x07
+
+
+#define TS72XX_OPTIONS_PHYS_BASE 0x22400000
+#define TS72XX_OPTIONS_VIRT_BASE 0xfebfe000
+#define TS72XX_OPTIONS_SIZE 0x00001000
+
+#define TS72XX_OPTIONS_COM2_RS485 0x02
+#define TS72XX_OPTIONS_MAX197 0x01
+
+
+#define TS72XX_OPTIONS2_PHYS_BASE 0x22800000
+#define TS72XX_OPTIONS2_VIRT_BASE 0xfebfd000
+#define TS72XX_OPTIONS2_SIZE 0x00001000
+
+#define TS72XX_OPTIONS2_TS9420 0x04
+#define TS72XX_OPTIONS2_TS9420_BOOT 0x02
+
+
+#define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000
+#define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000
+#define TS72XX_RTC_INDEX_SIZE 0x00001000
+
+#define TS72XX_RTC_DATA_VIRT_BASE 0xfebf8000
+#define TS72XX_RTC_DATA_PHYS_BASE 0x11700000
+#define TS72XX_RTC_DATA_SIZE 0x00001000
+
+#define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000
+#define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000
+
+#ifndef __ASSEMBLY__
+
+static inline int ts72xx_model(void)
+{
+ return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK;
+}
+
+static inline int board_is_ts7200(void)
+{
+ return ts72xx_model() == TS72XX_MODEL_TS7200;
+}
+
+static inline int board_is_ts7250(void)
+{
+ return ts72xx_model() == TS72XX_MODEL_TS7250;
+}
+
+static inline int board_is_ts7260(void)
+{
+ return ts72xx_model() == TS72XX_MODEL_TS7260;
+}
+
+static inline int board_is_ts7300(void)
+{
+ return ts72xx_model() == TS72XX_MODEL_TS7300;
+}
+
+static inline int board_is_ts7400(void)
+{
+ return ts72xx_model() == TS72XX_MODEL_TS7400;
+}
+
+static inline int is_max197_installed(void)
+{
+ return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
+ TS72XX_OPTIONS_MAX197);
+}
+
+static inline int is_ts9420_installed(void)
+{
+ return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
+ TS72XX_OPTIONS2_TS9420);
+}
+#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/uncompress.h b/arch/arm/mach-ep93xx/include/mach/uncompress.h
new file mode 100644
index 00000000000..16026c2b1c8
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/uncompress.h
@@ -0,0 +1,94 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/uncompress.h
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * 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.
+ */
+
+#include <mach/ep93xx-regs.h>
+
+static unsigned char __raw_readb(unsigned int ptr)
+{
+ return *((volatile unsigned char *)ptr);
+}
+
+static unsigned int __raw_readl(unsigned int ptr)
+{
+ return *((volatile unsigned int *)ptr);
+}
+
+static void __raw_writeb(unsigned char value, unsigned int ptr)
+{
+ *((volatile unsigned char *)ptr) = value;
+}
+
+static void __raw_writel(unsigned int value, unsigned int ptr)
+{
+ *((volatile unsigned int *)ptr) = value;
+}
+
+#if defined(CONFIG_EP93XX_EARLY_UART1)
+#define UART_BASE EP93XX_UART1_PHYS_BASE
+#elif defined(CONFIG_EP93XX_EARLY_UART2)
+#define UART_BASE EP93XX_UART2_PHYS_BASE
+#elif defined(CONFIG_EP93XX_EARLY_UART3)
+#define UART_BASE EP93XX_UART3_PHYS_BASE
+#else
+#define UART_BASE EP93XX_UART1_PHYS_BASE
+#endif
+
+#define PHYS_UART_DATA (UART_BASE + 0x00)
+#define PHYS_UART_FLAG (UART_BASE + 0x18)
+#define UART_FLAG_TXFF 0x20
+
+static inline void putc(int c)
+{
+ int i;
+
+ for (i = 0; i < 1000; i++) {
+ /* Transmit fifo not full? */
+ if (!(__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF))
+ break;
+ }
+
+ __raw_writeb(c, PHYS_UART_DATA);
+}
+
+static inline void flush(void)
+{
+}
+
+
+/*
+ * Some bootloaders don't turn off DMA from the ethernet MAC before
+ * jumping to linux, which means that we might end up with bits of RX
+ * status and packet data scribbled over the uncompressed kernel image.
+ * Work around this by resetting the ethernet MAC before we uncompress.
+ */
+#define PHYS_ETH_SELF_CTL 0x80010020
+#define ETH_SELF_CTL_RESET 0x00000001
+
+static void ethernet_reset(void)
+{
+ unsigned int v;
+
+ /* Reset the ethernet MAC. */
+ v = __raw_readl(PHYS_ETH_SELF_CTL);
+ __raw_writel(v | ETH_SELF_CTL_RESET, PHYS_ETH_SELF_CTL);
+
+ /* Wait for reset to finish. */
+ while (__raw_readl(PHYS_ETH_SELF_CTL) & ETH_SELF_CTL_RESET)
+ ;
+}
+
+
+static void arch_decomp_setup(void)
+{
+ ethernet_reset();
+}
+
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
new file mode 100644
index 00000000000..7b98084f0c9
--- /dev/null
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -0,0 +1,128 @@
+/*
+ * linux/arch/arm/mach-ep93xx/micro9.c
+ *
+ * Copyright (C) 2006 Contec Steuerungstechnik & Automation GmbH
+ * Manfred Gruber <m.gruber@tirol.com>
+ * Copyright (C) 2009 Contec Steuerungstechnik & Automation GmbH
+ * Hubert Feurstein <hubert.feurstein@contec.at>
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+
+/*************************************************************************
+ * Micro9 NOR Flash
+ *
+ * Micro9-High has up to 64MB of 32-bit flash on CS1
+ * Micro9-Mid has up to 64MB of either 32-bit or 16-bit flash on CS1
+ * Micro9-Lite uses a separate MTD map driver for flash support
+ * Micro9-Slim has up to 64MB of either 32-bit or 16-bit flash on CS1
+ *************************************************************************/
+static unsigned int __init micro9_detect_bootwidth(void)
+{
+ u32 v;
+
+ /* Detect the bus width of the external flash memory */
+ v = __raw_readl(EP93XX_SYSCON_SYSCFG);
+ if (v & EP93XX_SYSCON_SYSCFG_LCSN7)
+ return 4; /* 32-bit */
+ else
+ return 2; /* 16-bit */
+}
+
+static void __init micro9_register_flash(void)
+{
+ unsigned int width;
+
+ if (machine_is_micro9())
+ width = 4;
+ else if (machine_is_micro9m() || machine_is_micro9s())
+ width = micro9_detect_bootwidth();
+ else
+ width = 0;
+
+ if (width)
+ ep93xx_register_flash(width, EP93XX_CS1_PHYS_BASE, SZ_64M);
+}
+
+
+/*************************************************************************
+ * Micro9 Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data __initdata micro9_eth_data = {
+ .phy_id = 0x1f,
+};
+
+
+static void __init micro9_init_machine(void)
+{
+ ep93xx_init_devices();
+ ep93xx_register_eth(&micro9_eth_data, 1);
+ micro9_register_flash();
+}
+
+
+#ifdef CONFIG_MACH_MICRO9H
+MACHINE_START(MICRO9, "Contec Micro9-High")
+ /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = micro9_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICRO9M
+MACHINE_START(MICRO9M, "Contec Micro9-Mid")
+ /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = micro9_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICRO9L
+MACHINE_START(MICRO9L, "Contec Micro9-Lite")
+ /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = micro9_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICRO9S
+MACHINE_START(MICRO9S, "Contec Micro9-Slim")
+ /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = micro9_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
new file mode 100644
index 00000000000..f4e553eca21
--- /dev/null
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-ep93xx/simone.c
+ * Simplemachines Sim.One support.
+ *
+ * Copyright (C) 2010 Ryan Mallon
+ *
+ * Based on the 2.6.24.7 support:
+ * Copyright (C) 2009 Simplemachines
+ * MMC support by Peter Ivanov <ivanovp@gmail.com>, 2007
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct ep93xx_eth_data __initdata simone_eth_data = {
+ .phy_id = 1,
+};
+
+static struct ep93xxfb_mach_info __initdata simone_fb_info = {
+ .num_modes = EP93XXFB_USE_MODEDB,
+ .bpp = 16,
+ .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+};
+
+static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = {
+ .sda_pin = EP93XX_GPIO_LINE_EEDAT,
+ .sda_is_open_drain = 0,
+ .scl_pin = EP93XX_GPIO_LINE_EECLK,
+ .scl_is_open_drain = 0,
+ .udelay = 0,
+ .timeout = 0,
+};
+
+static struct i2c_board_info __initdata simone_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("ds1337", 0x68),
+ },
+};
+
+static struct platform_device simone_audio_device = {
+ .name = "simone-audio",
+ .id = -1,
+};
+
+static void __init simone_register_audio(void)
+{
+ ep93xx_register_ac97();
+ platform_device_register(&simone_audio_device);
+}
+
+static void __init simone_init_machine(void)
+{
+ ep93xx_init_devices();
+ ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_8M);
+ ep93xx_register_eth(&simone_eth_data, 1);
+ ep93xx_register_fb(&simone_fb_info);
+ ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
+ ARRAY_SIZE(simone_i2c_board_info));
+ simone_register_audio();
+}
+
+MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
+ /* Maintainer: Ryan Mallon */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = simone_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
new file mode 100644
index 00000000000..fd846331ddf
--- /dev/null
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -0,0 +1,185 @@
+/*
+ * arch/arm/mach-ep93xx/snappercl15.c
+ * Bluewater Systems Snapper CL15 system module
+ *
+ * Copyright (C) 2009 Bluewater Systems Ltd
+ * Author: Ryan Mallon
+ *
+ * NAND code adapted from driver by:
+ * Andre Renaud <andre@bluewatersys.com>
+ * James R. McKaskill
+ *
+ * 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.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/fb.h>
+
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#define SNAPPERCL15_NAND_BASE (EP93XX_CS7_PHYS_BASE + SZ_16M)
+
+#define SNAPPERCL15_NAND_WPN (1 << 8) /* Write protect (active low) */
+#define SNAPPERCL15_NAND_ALE (1 << 9) /* Address latch */
+#define SNAPPERCL15_NAND_CLE (1 << 10) /* Command latch */
+#define SNAPPERCL15_NAND_CEN (1 << 11) /* Chip enable (active low) */
+#define SNAPPERCL15_NAND_RDY (1 << 14) /* Device ready */
+
+#define NAND_CTRL_ADDR(chip) (chip->IO_ADDR_W + 0x40)
+
+static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
+{
+ struct nand_chip *chip = mtd->priv;
+ static u16 nand_state = SNAPPERCL15_NAND_WPN;
+ u16 set;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ set = SNAPPERCL15_NAND_CEN | SNAPPERCL15_NAND_WPN;
+
+ if (ctrl & NAND_NCE)
+ set &= ~SNAPPERCL15_NAND_CEN;
+ if (ctrl & NAND_CLE)
+ set |= SNAPPERCL15_NAND_CLE;
+ if (ctrl & NAND_ALE)
+ set |= SNAPPERCL15_NAND_ALE;
+
+ nand_state &= ~(SNAPPERCL15_NAND_CEN |
+ SNAPPERCL15_NAND_CLE |
+ SNAPPERCL15_NAND_ALE);
+ nand_state |= set;
+ __raw_writew(nand_state, NAND_CTRL_ADDR(chip));
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ __raw_writew((cmd & 0xff) | nand_state, chip->IO_ADDR_W);
+}
+
+static int snappercl15_nand_dev_ready(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY);
+}
+
+static const char *snappercl15_nand_part_probes[] = {"cmdlinepart", NULL};
+
+static struct mtd_partition snappercl15_nand_parts[] = {
+ {
+ .name = "Kernel",
+ .offset = 0,
+ .size = SZ_2M,
+ },
+ {
+ .name = "Filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct platform_nand_data snappercl15_nand_data = {
+ .chip = {
+ .nr_chips = 1,
+ .part_probe_types = snappercl15_nand_part_probes,
+ .partitions = snappercl15_nand_parts,
+ .nr_partitions = ARRAY_SIZE(snappercl15_nand_parts),
+ .options = NAND_NO_AUTOINCR,
+ .chip_delay = 25,
+ },
+ .ctrl = {
+ .dev_ready = snappercl15_nand_dev_ready,
+ .cmd_ctrl = snappercl15_nand_cmd_ctrl,
+ },
+};
+
+static struct resource snappercl15_nand_resource[] = {
+ {
+ .start = SNAPPERCL15_NAND_BASE,
+ .end = SNAPPERCL15_NAND_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device snappercl15_nand_device = {
+ .name = "gen_nand",
+ .id = -1,
+ .dev.platform_data = &snappercl15_nand_data,
+ .resource = snappercl15_nand_resource,
+ .num_resources = ARRAY_SIZE(snappercl15_nand_resource),
+};
+
+static struct ep93xx_eth_data __initdata snappercl15_eth_data = {
+ .phy_id = 1,
+};
+
+static struct i2c_gpio_platform_data __initdata snappercl15_i2c_gpio_data = {
+ .sda_pin = EP93XX_GPIO_LINE_EEDAT,
+ .sda_is_open_drain = 0,
+ .scl_pin = EP93XX_GPIO_LINE_EECLK,
+ .scl_is_open_drain = 0,
+ .udelay = 0,
+ .timeout = 0,
+};
+
+static struct i2c_board_info __initdata snappercl15_i2c_data[] = {
+ {
+ /* Audio codec */
+ I2C_BOARD_INFO("tlv320aic23", 0x1a),
+ },
+};
+
+static struct ep93xxfb_mach_info __initdata snappercl15_fb_info = {
+ .num_modes = EP93XXFB_USE_MODEDB,
+ .bpp = 16,
+};
+
+static struct platform_device snappercl15_audio_device = {
+ .name = "snappercl15-audio",
+ .id = -1,
+};
+
+static void __init snappercl15_register_audio(void)
+{
+ ep93xx_register_i2s();
+ platform_device_register(&snappercl15_audio_device);
+}
+
+static void __init snappercl15_init_machine(void)
+{
+ ep93xx_init_devices();
+ ep93xx_register_eth(&snappercl15_eth_data, 1);
+ ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
+ ARRAY_SIZE(snappercl15_i2c_data));
+ ep93xx_register_fb(&snappercl15_fb_info);
+ snappercl15_register_audio();
+ platform_device_register(&snappercl15_nand_device);
+}
+
+MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
+ /* Maintainer: Ryan Mallon */
+ .atag_offset = 0x100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = snappercl15_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
new file mode 100644
index 00000000000..79f8ecf07a1
--- /dev/null
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -0,0 +1,255 @@
+/*
+ * arch/arm/mach-ep93xx/ts72xx.c
+ * Technologic Systems TS72xx SBC support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/m48t86.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <mach/hardware.h>
+#include <mach/ts72xx.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+
+static struct map_desc ts72xx_io_desc[] __initdata = {
+ {
+ .virtual = TS72XX_MODEL_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE),
+ .length = TS72XX_MODEL_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_OPTIONS_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
+ .length = TS72XX_OPTIONS_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_OPTIONS2_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
+ .length = TS72XX_OPTIONS2_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_RTC_INDEX_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
+ .length = TS72XX_RTC_INDEX_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_RTC_DATA_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
+ .length = TS72XX_RTC_DATA_SIZE,
+ .type = MT_DEVICE,
+ }
+};
+
+static void __init ts72xx_map_io(void)
+{
+ ep93xx_map_io();
+ iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc));
+}
+
+
+/*************************************************************************
+ * NAND flash
+ *************************************************************************/
+#define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */
+#define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */
+
+static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
+ int cmd, unsigned int ctrl)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ void __iomem *addr = chip->IO_ADDR_R;
+ unsigned char bits;
+
+ addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE);
+
+ bits = __raw_readb(addr) & ~0x07;
+ bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */
+ bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */
+ bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */
+
+ __raw_writeb(bits, addr);
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ __raw_writeb(cmd, chip->IO_ADDR_W);
+}
+
+static int ts72xx_nand_device_ready(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+ void __iomem *addr = chip->IO_ADDR_R;
+
+ addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
+
+ return !!(__raw_readb(addr) & 0x20);
+}
+
+static const char *ts72xx_nand_part_probes[] = { "cmdlinepart", NULL };
+
+#define TS72XX_BOOTROM_PART_SIZE (SZ_16K)
+#define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M)
+
+static struct mtd_partition ts72xx_nand_parts[] = {
+ {
+ .name = "TS-BOOTROM",
+ .offset = 0,
+ .size = TS72XX_BOOTROM_PART_SIZE,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "Linux",
+ .offset = MTDPART_OFS_RETAIN,
+ .size = TS72XX_REDBOOT_PART_SIZE,
+ /* leave so much for last partition */
+ }, {
+ .name = "RedBoot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+};
+
+static struct platform_nand_data ts72xx_nand_data = {
+ .chip = {
+ .nr_chips = 1,
+ .chip_offset = 0,
+ .chip_delay = 15,
+ .part_probe_types = ts72xx_nand_part_probes,
+ .partitions = ts72xx_nand_parts,
+ .nr_partitions = ARRAY_SIZE(ts72xx_nand_parts),
+ },
+ .ctrl = {
+ .cmd_ctrl = ts72xx_nand_hwcontrol,
+ .dev_ready = ts72xx_nand_device_ready,
+ },
+};
+
+static struct resource ts72xx_nand_resource[] = {
+ {
+ .start = 0, /* filled in later */
+ .end = 0, /* filled in later */
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ts72xx_nand_flash = {
+ .name = "gen_nand",
+ .id = -1,
+ .dev.platform_data = &ts72xx_nand_data,
+ .resource = ts72xx_nand_resource,
+ .num_resources = ARRAY_SIZE(ts72xx_nand_resource),
+};
+
+
+static void __init ts72xx_register_flash(void)
+{
+ /*
+ * TS7200 has NOR flash all other TS72xx board have NAND flash.
+ */
+ if (board_is_ts7200()) {
+ ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
+ } else {
+ resource_size_t start;
+
+ if (is_ts9420_installed())
+ start = EP93XX_CS7_PHYS_BASE;
+ else
+ start = EP93XX_CS6_PHYS_BASE;
+
+ ts72xx_nand_resource[0].start = start;
+ ts72xx_nand_resource[0].end = start + SZ_16M - 1;
+
+ platform_device_register(&ts72xx_nand_flash);
+ }
+}
+
+
+static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
+{
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+ return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr)
+{
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+ __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static struct m48t86_ops ts72xx_rtc_ops = {
+ .readbyte = ts72xx_rtc_readbyte,
+ .writebyte = ts72xx_rtc_writebyte,
+};
+
+static struct platform_device ts72xx_rtc_device = {
+ .name = "rtc-m48t86",
+ .id = -1,
+ .dev = {
+ .platform_data = &ts72xx_rtc_ops,
+ },
+ .num_resources = 0,
+};
+
+static struct resource ts72xx_wdt_resources[] = {
+ {
+ .start = TS72XX_WDT_CONTROL_PHYS_BASE,
+ .end = TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = TS72XX_WDT_FEED_PHYS_BASE,
+ .end = TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ts72xx_wdt_device = {
+ .name = "ts72xx-wdt",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ts72xx_wdt_resources),
+ .resource = ts72xx_wdt_resources,
+};
+
+static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
+ .phy_id = 1,
+};
+
+static void __init ts72xx_init_machine(void)
+{
+ ep93xx_init_devices();
+ ts72xx_register_flash();
+ platform_device_register(&ts72xx_rtc_device);
+ platform_device_register(&ts72xx_wdt_device);
+
+ ep93xx_register_eth(&ts72xx_eth_data, 1);
+}
+
+MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
+ /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+ .atag_offset = 0x100,
+ .map_io = ts72xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = ts72xx_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
new file mode 100644
index 00000000000..d67d0b4feb6
--- /dev/null
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -0,0 +1,369 @@
+/*
+ * arch/arm/mach-ep93xx/vision_ep9307.c
+ * Vision Engraving Systems EP9307 SoM support.
+ *
+ * Copyright (C) 2008-2011 Vision Engraving Systems
+ * H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * Static I/O mappings for the FPGA
+ *************************************************************************/
+#define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE
+#define VISION_VIRT_BASE 0xfebff000
+
+static struct map_desc vision_io_desc[] __initdata = {
+ {
+ .virtual = VISION_VIRT_BASE,
+ .pfn = __phys_to_pfn(VISION_PHYS_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init vision_map_io(void)
+{
+ ep93xx_map_io();
+
+ iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
+}
+
+/*************************************************************************
+ * Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data vision_eth_data __initdata = {
+ .phy_id = 1,
+};
+
+/*************************************************************************
+ * Framebuffer
+ *************************************************************************/
+#define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1
+
+static int vision_lcd_setup(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH,
+ dev_name(&pdev->dev));
+ if (err)
+ return err;
+
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
+ EP93XX_SYSCON_DEVCFG_RASONP3 |
+ EP93XX_SYSCON_DEVCFG_EXVC);
+
+ return 0;
+}
+
+static void vision_lcd_teardown(struct platform_device *pdev)
+{
+ gpio_free(VISION_LCD_ENABLE);
+}
+
+static void vision_lcd_blank(int blank_mode, struct fb_info *info)
+{
+ if (blank_mode)
+ gpio_set_value(VISION_LCD_ENABLE, 0);
+ else
+ gpio_set_value(VISION_LCD_ENABLE, 1);
+}
+
+static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
+ .num_modes = EP93XXFB_USE_MODEDB,
+ .bpp = 16,
+ .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+ .setup = vision_lcd_setup,
+ .teardown = vision_lcd_teardown,
+ .blank = vision_lcd_blank,
+};
+
+
+/*************************************************************************
+ * GPIO Expanders
+ *************************************************************************/
+#define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1)
+#define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16)
+#define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16)
+#define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16)
+
+static struct pca953x_platform_data pca953x_74_gpio_data = {
+ .gpio_base = PCA9539_74_GPIO_BASE,
+ .irq_base = EP93XX_BOARD_IRQ(0),
+};
+
+static struct pca953x_platform_data pca953x_75_gpio_data = {
+ .gpio_base = PCA9539_75_GPIO_BASE,
+ .irq_base = -1,
+};
+
+static struct pca953x_platform_data pca953x_76_gpio_data = {
+ .gpio_base = PCA9539_76_GPIO_BASE,
+ .irq_base = -1,
+};
+
+static struct pca953x_platform_data pca953x_77_gpio_data = {
+ .gpio_base = PCA9539_77_GPIO_BASE,
+ .irq_base = -1,
+};
+
+/*************************************************************************
+ * I2C Bus
+ *************************************************************************/
+static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
+ .sda_pin = EP93XX_GPIO_LINE_EEDAT,
+ .scl_pin = EP93XX_GPIO_LINE_EECLK,
+};
+
+static struct i2c_board_info vision_i2c_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isl1208", 0x6f),
+ .irq = IRQ_EP93XX_EXT1,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x74),
+ .platform_data = &pca953x_74_gpio_data,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x75),
+ .platform_data = &pca953x_75_gpio_data,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x76),
+ .platform_data = &pca953x_76_gpio_data,
+ }, {
+ I2C_BOARD_INFO("pca9539", 0x77),
+ .platform_data = &pca953x_77_gpio_data,
+ },
+};
+
+/*************************************************************************
+ * SPI Flash
+ *************************************************************************/
+#define VISION_SPI_FLASH_CS EP93XX_GPIO_LINE_EGPIO7
+
+static struct mtd_partition vision_spi_flash_partitions[] = {
+ {
+ .name = "SPI bootstrap",
+ .offset = 0,
+ .size = SZ_4K,
+ }, {
+ .name = "Bootstrap config",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4K,
+ }, {
+ .name = "System config",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data vision_spi_flash_data = {
+ .name = "SPI Flash",
+ .parts = vision_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(vision_spi_flash_partitions),
+};
+
+static int vision_spi_flash_hw_setup(struct spi_device *spi)
+{
+ return gpio_request_one(VISION_SPI_FLASH_CS, GPIOF_INIT_HIGH,
+ spi->modalias);
+}
+
+static void vision_spi_flash_hw_cleanup(struct spi_device *spi)
+{
+ gpio_free(VISION_SPI_FLASH_CS);
+}
+
+static void vision_spi_flash_hw_cs_control(struct spi_device *spi, int value)
+{
+ gpio_set_value(VISION_SPI_FLASH_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
+ .setup = vision_spi_flash_hw_setup,
+ .cleanup = vision_spi_flash_hw_cleanup,
+ .cs_control = vision_spi_flash_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI SD/MMC host
+ *************************************************************************/
+#define VISION_SPI_MMC_CS EP93XX_GPIO_LINE_G(2)
+#define VISION_SPI_MMC_WP EP93XX_GPIO_LINE_F(0)
+#define VISION_SPI_MMC_CD EP93XX_GPIO_LINE_EGPIO15
+
+static struct gpio vision_spi_mmc_gpios[] = {
+ { VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
+ { VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
+};
+
+static int vision_spi_mmc_init(struct device *pdev,
+ irqreturn_t (*func)(int, void *), void *pdata)
+{
+ int err;
+
+ err = gpio_request_array(vision_spi_mmc_gpios,
+ ARRAY_SIZE(vision_spi_mmc_gpios));
+ if (err)
+ return err;
+
+ err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
+ if (err)
+ goto exit_err;
+
+ err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
+ IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
+ if (err)
+ goto exit_err;
+
+ return 0;
+
+exit_err:
+ gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+ return err;
+
+}
+
+static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
+{
+ free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
+ gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+}
+
+static int vision_spi_mmc_get_ro(struct device *pdev)
+{
+ return !!gpio_get_value(VISION_SPI_MMC_WP);
+}
+
+static int vision_spi_mmc_get_cd(struct device *pdev)
+{
+ return !gpio_get_value(VISION_SPI_MMC_CD);
+}
+
+static struct mmc_spi_platform_data vision_spi_mmc_data = {
+ .init = vision_spi_mmc_init,
+ .exit = vision_spi_mmc_exit,
+ .get_ro = vision_spi_mmc_get_ro,
+ .get_cd = vision_spi_mmc_get_cd,
+ .detect_delay = 100,
+ .powerup_msecs = 100,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static int vision_spi_mmc_hw_setup(struct spi_device *spi)
+{
+ return gpio_request_one(VISION_SPI_MMC_CS, GPIOF_INIT_HIGH,
+ spi->modalias);
+}
+
+static void vision_spi_mmc_hw_cleanup(struct spi_device *spi)
+{
+ gpio_free(VISION_SPI_MMC_CS);
+}
+
+static void vision_spi_mmc_hw_cs_control(struct spi_device *spi, int value)
+{
+ gpio_set_value(VISION_SPI_MMC_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_mmc_hw = {
+ .setup = vision_spi_mmc_hw_setup,
+ .cleanup = vision_spi_mmc_hw_cleanup,
+ .cs_control = vision_spi_mmc_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI Bus
+ *************************************************************************/
+static struct spi_board_info vision_spi_board_info[] __initdata = {
+ {
+ .modalias = "sst25l",
+ .platform_data = &vision_spi_flash_data,
+ .controller_data = &vision_spi_flash_hw,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ }, {
+ .modalias = "mmc_spi",
+ .platform_data = &vision_spi_mmc_data,
+ .controller_data = &vision_spi_mmc_hw,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_3,
+ },
+};
+
+static struct ep93xx_spi_info vision_spi_master __initdata = {
+ .num_chipselect = ARRAY_SIZE(vision_spi_board_info),
+};
+
+/*************************************************************************
+ * Machine Initialization
+ *************************************************************************/
+static void __init vision_init_machine(void)
+{
+ ep93xx_init_devices();
+ ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
+ ep93xx_register_eth(&vision_eth_data, 1);
+ ep93xx_register_fb(&ep93xxfb_info);
+ ep93xx_register_pwm(1, 0);
+
+ /*
+ * Request the gpio expander's interrupt gpio line now to prevent
+ * the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
+ */
+ if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN,
+ "pca9539:74"))
+ pr_warn("cannot request interrupt gpio for pca9539:74\n");
+
+ vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
+
+ ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
+ ARRAY_SIZE(vision_i2c_info));
+ ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
+ ARRAY_SIZE(vision_spi_board_info));
+}
+
+MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
+ /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+ .atag_offset = 0x100,
+ .map_io = vision_map_io,
+ .init_irq = ep93xx_init_irq,
+ .handle_irq = vic_handle_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = vision_init_machine,
+ .restart = ep93xx_restart,
+MACHINE_END