summaryrefslogtreecommitdiff
path: root/arch/arm/mach-at91
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-20 00:18:39 +0300
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-20 00:18:39 +0300
commit59b8175c771040afcd4ad67022b0cc80c216b866 (patch)
tree4ef5935bee1e342716d49b9d4b99e3fa835526e6 /arch/arm/mach-at91
parent920841d8d1d61bc12b43f95a579a5374f6d98f81 (diff)
parent3b0eb4a195a124567cd0dd6f700f8388def542c6 (diff)
downloadlinux-59b8175c771040afcd4ad67022b0cc80c216b866.tar.xz
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (117 commits) [ARM] 4058/2: iop32x: set ->broken_parity_status on n2100 onboard r8169 ports [ARM] 4140/1: AACI stability add ac97 timeout and retries [ARM] 4139/1: AACI record support [ARM] 4138/1: AACI: multiple channel support for IRQ handling [ARM] 4211/1: Provide a defconfig for ns9xxx [ARM] 4210/1: base for new machine type "NetSilicon NS9360" [ARM] 4222/1: S3C2443: Remove reference to missing S3C2443_PM [ARM] 4221/1: S3C2443: DMA support [ARM] 4220/1: S3C24XX: DMA system initialised from sysdev [ARM] 4219/1: S3C2443: DMA source definitions [ARM] 4218/1: S3C2412: fix CONFIG_CPU_S3C2412_ONLY wrt to S3C2443 [ARM] 4217/1: S3C24XX: remove the dma channel show at startup [ARM] 4090/2: avoid clash between PXA and SA1111 defines [ARM] 4216/1: add .gitignore entries for ARM specific files [ARM] 4214/2: S3C2410: Add Armzone QT2410 [ARM] 4215/1: s3c2410 usb device: per-platform vbus_draw [ARM] 4213/1: S3C2410 - Update definition of ADCTSC_XY_PST [ARM] 4098/1: ARM: rtc_lock only used with rtc_cmos [ARM] 4137/1: Add kexec support [ARM] 4201/1: SMP barriers pair needed for the secondary boot process ... Fix up conflict due to typedef removal in sound/arm/aaci.h
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r--arch/arm/mach-at91/Kconfig175
-rw-r--r--arch/arm/mach-at91/Makefile53
-rw-r--r--arch/arm/mach-at91/Makefile.boot9
-rw-r--r--arch/arm/mach-at91/at91rm9200.c329
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c879
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c146
-rw-r--r--arch/arm/mach-at91/at91sam9260.c367
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c871
-rw-r--r--arch/arm/mach-at91/at91sam9261.c307
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c745
-rw-r--r--arch/arm/mach-at91/at91sam9263.c313
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c818
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c113
-rw-r--r--arch/arm/mach-at91/board-1arm.c102
-rw-r--r--arch/arm/mach-at91/board-carmeva.c149
-rw-r--r--arch/arm/mach-at91/board-csb337.c184
-rw-r--r--arch/arm/mach-at91/board-csb637.c148
-rw-r--r--arch/arm/mach-at91/board-dk.c216
-rw-r--r--arch/arm/mach-at91/board-eb9200.c123
-rw-r--r--arch/arm/mach-at91/board-ek.c174
-rw-r--r--arch/arm/mach-at91/board-kafa.c109
-rw-r--r--arch/arm/mach-at91/board-kb9202.c143
-rw-r--r--arch/arm/mach-at91/board-sam9260ek.c202
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c259
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c176
-rw-r--r--arch/arm/mach-at91/clock.c640
-rw-r--r--arch/arm/mach-at91/clock.h31
-rw-r--r--arch/arm/mach-at91/generic.h51
-rw-r--r--arch/arm/mach-at91/gpio.c462
-rw-r--r--arch/arm/mach-at91/irq.c168
-rw-r--r--arch/arm/mach-at91/leds.c95
-rw-r--r--arch/arm/mach-at91/pm.c229
32 files changed, 8786 insertions, 0 deletions
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
new file mode 100644
index 000000000000..bf0d96272e3a
--- /dev/null
+++ b/arch/arm/mach-at91/Kconfig
@@ -0,0 +1,175 @@
+if ARCH_AT91
+
+menu "Atmel AT91 System-on-Chip"
+
+choice
+ prompt "Atmel AT91 Processor"
+
+config ARCH_AT91RM9200
+ bool "AT91RM9200"
+
+config ARCH_AT91SAM9260
+ bool "AT91SAM9260 or AT91SAM9XE"
+
+config ARCH_AT91SAM9261
+ bool "AT91SAM9261"
+
+config ARCH_AT91SAM9263
+ bool "AT91SAM9263"
+
+endchoice
+
+# ----------------------------------------------------------
+
+if ARCH_AT91RM9200
+
+comment "AT91RM9200 Board Type"
+
+config MACH_ONEARM
+ bool "Ajeco 1ARM Single Board Computer"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Ajeco's 1ARM Single Board Computer.
+ <http://www.ajeco.fi/products.htm>
+
+config ARCH_AT91RM9200DK
+ bool "Atmel AT91RM9200-DK Development board"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Atmel's AT91RM9200-DK Development board.
+ (Discontinued)
+
+config MACH_AT91RM9200EK
+ bool "Atmel AT91RM9200-EK Evaluation Kit"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit.
+ <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3507>
+
+config MACH_CSB337
+ bool "Cogent CSB337"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Cogent's CSB337 board.
+ <http://www.cogcomp.com/csb_csb337.htm>
+
+config MACH_CSB637
+ bool "Cogent CSB637"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Cogent's CSB637 board.
+ <http://www.cogcomp.com/csb_csb637.htm>
+
+config MACH_CARMEVA
+ bool "Conitec ARM&EVA"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Conitec's AT91RM9200-MCU-Module.
+ <http://www.conitec.net/english/linuxboard.htm>
+
+config MACH_ATEB9200
+ bool "Embest ATEB9200"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Embest's ATEB9200 board.
+ <http://www.embedinfo.com/english/product/ATEB9200.asp>
+
+config MACH_KB9200
+ bool "KwikByte KB920x"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using KwikByte's KB920x board.
+ <http://kwikbyte.com/KB9202_description_new.htm>
+
+config MACH_KAFA
+ bool "Sperry-Sun KAFA board"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Sperry-Sun's KAFA board.
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9260
+
+comment "AT91SAM9260 Variants"
+
+config ARCH_AT91SAM9260_SAM9XE
+ bool "AT91SAM9XE"
+ depends on ARCH_AT91SAM9260
+ help
+ Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
+ They are basicaly AT91SAM9260s with various sizes of embedded Flash.
+
+comment "AT91SAM9260 / AT91SAM9XE Board Type"
+
+config MACH_AT91SAM9260EK
+ bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit"
+ depends on ARCH_AT91SAM9260
+ help
+ Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
+ <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9261
+
+comment "AT91SAM9261 Board Type"
+
+config MACH_AT91SAM9261EK
+ bool "Atmel AT91SAM9261-EK Evaluation Kit"
+ depends on ARCH_AT91SAM9261
+ help
+ Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit.
+ <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820>
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_AT91SAM9263
+
+comment "AT91SAM9263 Board Type"
+
+config MACH_AT91SAM9263EK
+ bool "Atmel AT91SAM9263-EK Evaluation Kit"
+ depends on ARCH_AT91SAM9263
+ help
+ Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit.
+ <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057>
+
+endif
+
+# ----------------------------------------------------------
+
+comment "AT91 Board Options"
+
+config MTD_AT91_DATAFLASH_CARD
+ bool "Enable DataFlash Card support"
+ depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
+ help
+ Enable support for the DataFlash card.
+
+config MTD_NAND_AT91_BUSWIDTH_16
+ bool "Enable 16-bit data bus interface to NAND flash"
+ depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
+ help
+ On AT91SAM926x boards both types of NAND flash can be present
+ (8 and 16 bit data bus width).
+
+# ----------------------------------------------------------
+
+comment "AT91 Feature Selections"
+
+config AT91_PROGRAMMABLE_CLOCKS
+ bool "Programmable Clocks"
+ help
+ Select this if you need to program one or more of the PCK0..PCK3
+ programmable clock outputs.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
new file mode 100644
index 000000000000..05de6cdc88f1
--- /dev/null
+++ b/arch/arm/mach-at91/Makefile
@@ -0,0 +1,53 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := clock.o irq.o gpio.o
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_PM) += pm.o
+
+# CPU-specific support
+obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o
+
+# AT91RM9200 board-specific support
+obj-$(CONFIG_MACH_ONEARM) += board-1arm.o
+obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o
+obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o
+obj-$(CONFIG_MACH_CSB337) += board-csb337.o
+obj-$(CONFIG_MACH_CSB637) += board-csb637.o
+obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o
+obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
+obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o
+obj-$(CONFIG_MACH_KAFA) += board-kafa.o
+
+# AT91SAM9260 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
+
+# AT91SAM9261 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
+
+# AT91SAM9263 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
+
+# LEDs support
+led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
+led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
+led-$(CONFIG_MACH_CSB337) += leds.o
+led-$(CONFIG_MACH_CSB637) += leds.o
+led-$(CONFIG_MACH_KB9200) += leds.o
+led-$(CONFIG_MACH_KAFA) += leds.o
+obj-$(CONFIG_LEDS) += $(led-y)
+
+# VGA support
+#obj-$(CONFIG_FB_S1D13XXX) += ics1523.o
+
+
+ifeq ($(CONFIG_PM_DEBUG),y)
+CFLAGS_pm.o += -DDEBUG
+endif
diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
new file mode 100644
index 000000000000..e667dcc7cd34
--- /dev/null
+++ b/arch/arm/mach-at91/Makefile.boot
@@ -0,0 +1,9 @@
+# Note: the following conditions must always be true:
+# ZRELADDR == virt_to_phys(TEXTADDR)
+# PARAMS_PHYS must be within 4MB of ZRELADDR
+# INITRD_PHYS must be in RAM
+
+ zreladdr-y := 0x20008000
+params_phys-y := 0x20000100
+initrd_phys-y := 0x20410000
+
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
new file mode 100644
index 000000000000..2ddcdd69df7d
--- /dev/null
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -0,0 +1,329 @@
+/*
+ * arch/arm/mach-at91/at91rm9200.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * 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/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_st.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91rm9200_io_desc[] __initdata = {
+ {
+ .virtual = AT91_VA_BASE_SYS,
+ .pfn = __phys_to_pfn(AT91_BASE_SYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_EMAC,
+ .pfn = __phys_to_pfn(AT91RM9200_BASE_EMAC),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE,
+ .pfn = __phys_to_pfn(AT91RM9200_SRAM_BASE),
+ .length = AT91RM9200_SRAM_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+/* --------------------------------------------------------------------
+ * Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk udc_clk = {
+ .name = "udc_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_UDP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+ .name = "ohci_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_UHP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ether_clk = {
+ .name = "ether_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_EMAC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+ .name = "mci_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_MCI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+ .name = "twi_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TWI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+ .name = "usart0_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_US0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+ .name = "usart1_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_US1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+ .name = "usart2_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_US2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+ .name = "usart3_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_US3,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi_clk = {
+ .name = "spi_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_SPI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioA_clk = {
+ .name = "pioA_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_PIOA,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+ .name = "pioB_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_PIOB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+ .name = "pioC_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_PIOC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioD_clk = {
+ .name = "pioD_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_PIOD,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc0_clk = {
+ .name = "tc0_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+ .name = "tc1_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+ .name = "tc2_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc3_clk = {
+ .name = "tc3_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC3,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc4_clk = {
+ .name = "tc4_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC4,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc5_clk = {
+ .name = "tc5_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC5,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+ &pioA_clk,
+ &pioB_clk,
+ &pioC_clk,
+ &pioD_clk,
+ &usart0_clk,
+ &usart1_clk,
+ &usart2_clk,
+ &usart3_clk,
+ &mmc_clk,
+ &udc_clk,
+ &twi_clk,
+ &spi_clk,
+ // ssc 0 .. ssc2
+ &tc0_clk,
+ &tc1_clk,
+ &tc2_clk,
+ &tc3_clk,
+ &tc4_clk,
+ &tc5_clk,
+ &ohci_clk,
+ &ether_clk,
+ // irq0 .. irq6
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+ .name = "pck0",
+ .pmc_mask = AT91_PMC_PCK0,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 0,
+};
+static struct clk pck1 = {
+ .name = "pck1",
+ .pmc_mask = AT91_PMC_PCK1,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 1,
+};
+static struct clk pck2 = {
+ .name = "pck2",
+ .pmc_mask = AT91_PMC_PCK2,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 2,
+};
+static struct clk pck3 = {
+ .name = "pck3",
+ .pmc_mask = AT91_PMC_PCK3,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 3,
+};
+
+static void __init at91rm9200_register_clocks(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+ clk_register(periph_clocks[i]);
+
+ clk_register(&pck0);
+ clk_register(&pck1);
+ clk_register(&pck2);
+ clk_register(&pck3);
+}
+
+/* --------------------------------------------------------------------
+ * GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91rm9200_gpio[] = {
+ {
+ .id = AT91RM9200_ID_PIOA,
+ .offset = AT91_PIOA,
+ .clock = &pioA_clk,
+ }, {
+ .id = AT91RM9200_ID_PIOB,
+ .offset = AT91_PIOB,
+ .clock = &pioB_clk,
+ }, {
+ .id = AT91RM9200_ID_PIOC,
+ .offset = AT91_PIOC,
+ .clock = &pioC_clk,
+ }, {
+ .id = AT91RM9200_ID_PIOD,
+ .offset = AT91_PIOD,
+ .clock = &pioD_clk,
+ }
+};
+
+static void at91rm9200_reset(void)
+{
+ /*
+ * Perform a hardware reset with the use of the Watchdog timer.
+ */
+ at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
+ at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+
+/* --------------------------------------------------------------------
+ * AT91RM9200 processor initialization
+ * -------------------------------------------------------------------- */
+void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks)
+{
+ /* Map peripherals */
+ iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
+
+ at91_arch_reset = at91rm9200_reset;
+ at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
+ | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3)
+ | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5)
+ | (1 << AT91RM9200_ID_IRQ6);
+
+ /* Init clock subsystem */
+ at91_clock_init(main_clock);
+
+ /* Register the processor-specific clocks */
+ at91rm9200_register_clocks();
+
+ /* Initialize GPIO subsystem */
+ at91_gpio_init(at91rm9200_gpio, banks);
+}
+
+
+/* --------------------------------------------------------------------
+ * Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
+ 7, /* Advanced Interrupt Controller (FIQ) */
+ 7, /* System Peripherals */
+ 0, /* Parallel IO Controller A */
+ 0, /* Parallel IO Controller B */
+ 0, /* Parallel IO Controller C */
+ 0, /* Parallel IO Controller D */
+ 6, /* USART 0 */
+ 6, /* USART 1 */
+ 6, /* USART 2 */
+ 6, /* USART 3 */
+ 0, /* Multimedia Card Interface */
+ 4, /* USB Device Port */
+ 0, /* Two-Wire Interface */
+ 6, /* Serial Peripheral Interface */
+ 5, /* Serial Synchronous Controller 0 */
+ 5, /* Serial Synchronous Controller 1 */
+ 5, /* Serial Synchronous Controller 2 */
+ 0, /* Timer Counter 0 */
+ 0, /* Timer Counter 1 */
+ 0, /* Timer Counter 2 */
+ 0, /* Timer Counter 3 */
+ 0, /* Timer Counter 4 */
+ 0, /* Timer Counter 5 */
+ 3, /* USB Host port */
+ 3, /* Ethernet MAC */
+ 0, /* Advanced Interrupt Controller (IRQ0) */
+ 0, /* Advanced Interrupt Controller (IRQ1) */
+ 0, /* Advanced Interrupt Controller (IRQ2) */
+ 0, /* Advanced Interrupt Controller (IRQ3) */
+ 0, /* Advanced Interrupt Controller (IRQ4) */
+ 0, /* Advanced Interrupt Controller (IRQ5) */
+ 0 /* Advanced Interrupt Controller (IRQ6) */
+};
+
+void __init at91rm9200_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+ if (!priority)
+ priority = at91rm9200_default_irq_priority;
+
+ /* Initialize the AIC interrupt controller */
+ at91_aic_init(priority);
+
+ /* Enable GPIO interrupts */
+ at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
new file mode 100644
index 000000000000..2624a4f22d61
--- /dev/null
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -0,0 +1,879 @@
+/*
+ * arch/arm/mach-at91/at91rm9200_devices.c
+ *
+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright (C) 2005 David Brownell
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/at91rm9200_mc.h>
+
+#include "generic.h"
+
+#define SZ_512 0x00000200
+#define SZ_256 0x00000100
+#define SZ_16 0x00000010
+
+/* --------------------------------------------------------------------
+ * USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+ [0] = {
+ .start = AT91RM9200_UHP_BASE,
+ .end = AT91RM9200_UHP_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_UHP,
+ .end = AT91RM9200_ID_UHP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91rm9200_usbh_device = {
+ .name = "at91_ohci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbh_data,
+ },
+ .resource = usbh_resources,
+ .num_resources = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+ if (!data)
+ return;
+
+ usbh_data = *data;
+ platform_device_register(&at91rm9200_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+ [0] = {
+ .start = AT91RM9200_BASE_UDP,
+ .end = AT91RM9200_BASE_UDP + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_UDP,
+ .end = AT91RM9200_ID_UDP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91rm9200_udc_device = {
+ .name = "at91_udc",
+ .id = -1,
+ .dev = {
+ .platform_data = &udc_data,
+ },
+ .resource = udc_resources,
+ .num_resources = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->vbus_pin) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+ if (data->pullup_pin)
+ at91_set_gpio_output(data->pullup_pin, 0);
+
+ udc_data = *data;
+ platform_device_register(&at91rm9200_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+ [0] = {
+ .start = AT91_VA_BASE_EMAC,
+ .end = AT91_VA_BASE_EMAC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_EMAC,
+ .end = AT91RM9200_ID_EMAC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91rm9200_eth_device = {
+ .name = "at91_ether",
+ .id = -1,
+ .dev = {
+ .dma_mask = &eth_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &eth_data,
+ },
+ .resource = eth_resources,
+ .num_resources = ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->phy_irq_pin) {
+ at91_set_gpio_input(data->phy_irq_pin, 0);
+ at91_set_deglitch(data->phy_irq_pin, 1);
+ }
+
+ /* Pins used for MII and RMII */
+ at91_set_A_periph(AT91_PIN_PA16, 0); /* EMDIO */
+ at91_set_A_periph(AT91_PIN_PA15, 0); /* EMDC */
+ at91_set_A_periph(AT91_PIN_PA14, 0); /* ERXER */
+ at91_set_A_periph(AT91_PIN_PA13, 0); /* ERX1 */
+ at91_set_A_periph(AT91_PIN_PA12, 0); /* ERX0 */
+ at91_set_A_periph(AT91_PIN_PA11, 0); /* ECRS_ECRSDV */
+ at91_set_A_periph(AT91_PIN_PA10, 0); /* ETX1 */
+ at91_set_A_periph(AT91_PIN_PA9, 0); /* ETX0 */
+ at91_set_A_periph(AT91_PIN_PA8, 0); /* ETXEN */
+ at91_set_A_periph(AT91_PIN_PA7, 0); /* ETXCK_EREFCK */
+
+ if (!data->is_rmii) {
+ at91_set_B_periph(AT91_PIN_PB19, 0); /* ERXCK */
+ at91_set_B_periph(AT91_PIN_PB18, 0); /* ECOL */
+ at91_set_B_periph(AT91_PIN_PB17, 0); /* ERXDV */
+ at91_set_B_periph(AT91_PIN_PB16, 0); /* ERX3 */
+ at91_set_B_periph(AT91_PIN_PB15, 0); /* ERX2 */
+ at91_set_B_periph(AT91_PIN_PB14, 0); /* ETXER */
+ at91_set_B_periph(AT91_PIN_PB13, 0); /* ETX3 */
+ at91_set_B_periph(AT91_PIN_PB12, 0); /* ETX2 */
+ }
+
+ eth_data = *data;
+ platform_device_register(&at91rm9200_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * Compact Flash / PCMCIA
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
+static struct at91_cf_data cf_data;
+
+#define CF_BASE AT91_CHIPSELECT_4
+
+static struct resource cf_resources[] = {
+ [0] = {
+ .start = CF_BASE,
+ /* ties up CS4, CS5 and CS6 */
+ .end = CF_BASE + (0x30000000 - 1),
+ .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+ },
+};
+
+static struct platform_device at91rm9200_cf_device = {
+ .name = "at91_cf",
+ .id = -1,
+ .dev = {
+ .platform_data = &cf_data,
+ },
+ .resource = cf_resources,
+ .num_resources = ARRAY_SIZE(cf_resources),
+};
+
+void __init at91_add_device_cf(struct at91_cf_data *data)
+{
+ unsigned int csa;
+
+ if (!data)
+ return;
+
+ data->chipselect = 4; /* can only use EBI ChipSelect 4 */
+
+ /* CF takes over CS4, CS5, CS6 */
+ csa = at91_sys_read(AT91_EBI_CSA);
+ at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
+
+ /*
+ * Static memory controller timing adjustments.
+ * REVISIT: these timings are in terms of MCK cycles, so
+ * when MCK changes (cpufreq etc) so must these values...
+ */
+ at91_sys_write(AT91_SMC_CSR(4),
+ AT91_SMC_ACSS_STD
+ | AT91_SMC_DBW_16
+ | AT91_SMC_BAT
+ | AT91_SMC_WSEN
+ | AT91_SMC_NWS_(32) /* wait states */
+ | AT91_SMC_RWSETUP_(6) /* setup time */
+ | AT91_SMC_RWHOLD_(4) /* hold time */
+ );
+
+ /* input/irq */
+ if (data->irq_pin) {
+ at91_set_gpio_input(data->irq_pin, 1);
+ at91_set_deglitch(data->irq_pin, 1);
+ }
+ at91_set_gpio_input(data->det_pin, 1);
+ at91_set_deglitch(data->det_pin, 1);
+
+ /* outputs, initially off */
+ if (data->vcc_pin)
+ at91_set_gpio_output(data->vcc_pin, 0);
+ at91_set_gpio_output(data->rst_pin, 0);
+
+ /* force poweron defaults for these pins ... */
+ at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */
+ at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */
+ at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */
+ at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */
+
+ /* nWAIT is _not_ a default setting */
+ at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */
+
+ cf_data = *data;
+ platform_device_register(&at91rm9200_cf_device);
+}
+#else
+void __init at91_add_device_cf(struct at91_cf_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+ [0] = {
+ .start = AT91RM9200_BASE_MCI,
+ .end = AT91RM9200_BASE_MCI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_MCI,
+ .end = AT91RM9200_ID_MCI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91rm9200_mmc_device = {
+ .name = "at91_mci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &mmc_data,
+ },
+ .resource = mmc_resources,
+ .num_resources = ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+ if (!data)
+ return;
+
+ /* input/irq */
+ if (data->det_pin) {
+ at91_set_gpio_input(data->det_pin, 1);
+ at91_set_deglitch(data->det_pin, 1);
+ }
+ if (data->wp_pin)
+ at91_set_gpio_input(data->wp_pin, 1);
+ if (data->vcc_pin)
+ at91_set_gpio_output(data->vcc_pin, 0);
+
+ /* CLK */
+ at91_set_A_periph(AT91_PIN_PA27, 0);
+
+ if (data->slot_b) {
+ /* CMD */
+ at91_set_B_periph(AT91_PIN_PA8, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_B_periph(AT91_PIN_PA9, 1);
+ if (data->wire4) {
+ at91_set_B_periph(AT91_PIN_PA10, 1);
+ at91_set_B_periph(AT91_PIN_PA11, 1);
+ at91_set_B_periph(AT91_PIN_PA12, 1);
+ }
+ } else {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA28, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA29, 1);
+ if (data->wire4) {
+ at91_set_B_periph(AT91_PIN_PB3, 1);
+ at91_set_B_periph(AT91_PIN_PB4, 1);
+ at91_set_B_periph(AT91_PIN_PB5, 1);
+ }
+ }
+
+ mmc_data = *data;
+ platform_device_register(&at91rm9200_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+#define NAND_BASE AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+ {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91rm9200_nand_device = {
+ .name = "at91_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .resource = nand_resources,
+ .num_resources = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+ unsigned int csa;
+
+ if (!data)
+ return;
+
+ /* enable the address range of CS3 */
+ csa = at91_sys_read(AT91_EBI_CSA);
+ at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA);
+
+ /* set the bus interface characteristics */
+ at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN
+ | AT91_SMC_NWS_(5)
+ | AT91_SMC_TDF_(1)
+ | AT91_SMC_RWSETUP_(0) /* tDS Data Set up Time 30 - ns */
+ | AT91_SMC_RWHOLD_(1) /* tDH Data Hold Time 20 - ns */
+ );
+
+ /* enable pin */
+ if (data->enable_pin)
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (data->rdy_pin)
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (data->det_pin)
+ at91_set_gpio_input(data->det_pin, 1);
+
+ at91_set_A_periph(AT91_PIN_PC1, 0); /* SMOE */
+ at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */
+
+ nand_data = *data;
+ platform_device_register(&at91rm9200_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+ [0] = {
+ .start = AT91RM9200_BASE_TWI,
+ .end = AT91RM9200_BASE_TWI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_TWI,
+ .end = AT91RM9200_ID_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91rm9200_twi_device = {
+ .name = "at91_i2c",
+ .id = -1,
+ .resource = twi_resources,
+ .num_resources = ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+ /* pins used for TWI interface */
+ at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */
+ at91_set_multi_drive(AT91_PIN_PA25, 1);
+
+ at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */
+ at91_set_multi_drive(AT91_PIN_PA26, 1);
+
+ platform_device_register(&at91rm9200_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi_resources[] = {
+ [0] = {
+ .start = AT91RM9200_BASE_SPI,
+ .end = AT91RM9200_BASE_SPI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_SPI,
+ .end = AT91RM9200_ID_SPI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91rm9200_spi_device = {
+ .name = "at91_spi",
+ .id = 0,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi_resources,
+ .num_resources = ARRAY_SIZE(spi_resources),
+};
+
+static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+ int i;
+ unsigned long cs_pin;
+
+ at91_set_A_periph(AT91_PIN_PA0, 0); /* MISO */
+ at91_set_A_periph(AT91_PIN_PA1, 0); /* MOSI */
+ at91_set_A_periph(AT91_PIN_PA2, 0); /* SPCK */
+
+ /* Enable SPI chip-selects */
+ for (i = 0; i < nr_devices; i++) {
+ if (devices[i].controller_data)
+ cs_pin = (unsigned long) devices[i].controller_data;
+ else
+ cs_pin = spi_standard_cs[devices[i].chip_select];
+
+#ifdef CONFIG_SPI_AT91_MANUAL_CS
+ at91_set_gpio_output(cs_pin, 1);
+#else
+ at91_set_A_periph(cs_pin, 0);
+#endif
+
+ /* pass chip-select pin to driver */
+ devices[i].controller_data = (void *) cs_pin;
+ }
+
+ spi_register_board_info(devices, nr_devices);
+ at91_clock_associate("spi_clk", &at91rm9200_spi_device.dev, "spi");
+ platform_device_register(&at91rm9200_spi_device);
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * RTC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
+static struct platform_device at91rm9200_rtc_device = {
+ .name = "at91_rtc",
+ .id = -1,
+ .num_resources = 0,
+};
+
+static void __init at91_add_device_rtc(void)
+{
+ platform_device_register(&at91rm9200_rtc_device);
+}
+#else
+static void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * Watchdog
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE)
+static struct platform_device at91rm9200_wdt_device = {
+ .name = "at91_wdt",
+ .id = -1,
+ .num_resources = 0,
+};
+
+static void __init at91_add_device_watchdog(void)
+{
+ platform_device_register(&at91rm9200_wdt_device);
+}
+#else
+static void __init at91_add_device_watchdog(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+ /* Enable GPIO to access the LEDs */
+ at91_set_gpio_output(cpu_led, 1);
+ at91_set_gpio_output(timer_led, 1);
+
+ at91_leds_cpu = cpu_led;
+ at91_leds_timer = timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+ [0] = {
+ .start = AT91_VA_BASE_SYS + AT91_DBGU,
+ .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_SYS,
+ .end = AT91_ID_SYS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data dbgu_data = {
+ .use_dma_tx = 0,
+ .use_dma_rx = 0, /* DBGU not capable of receive DMA */
+ .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91rm9200_dbgu_device = {
+ .name = "atmel_usart",
+ .id = 0,
+ .dev = {
+ .platform_data = &dbgu_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = dbgu_resources,
+ .num_resources = ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PA30, 0); /* DRXD */
+ at91_set_A_periph(AT91_PIN_PA31, 1); /* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+ [0] = {
+ .start = AT91RM9200_BASE_US0,
+ .end = AT91RM9200_BASE_US0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_US0,
+ .end = AT91RM9200_ID_US0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart0_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91rm9200_uart0_device = {
+ .name = "atmel_usart",
+ .id = 1,
+ .dev = {
+ .platform_data = &uart0_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart0_resources,
+ .num_resources = ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PA17, 1); /* TXD0 */
+ at91_set_A_periph(AT91_PIN_PA18, 0); /* RXD0 */
+ at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */
+
+ /*
+ * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
+ * We need to drive the pin manually. Default is off (RTS is active low).
+ */
+ at91_set_gpio_output(AT91_PIN_PA21, 1);
+}
+
+static struct resource uart1_resources[] = {
+ [0] = {
+ .start = AT91RM9200_BASE_US1,
+ .end = AT91RM9200_BASE_US1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_US1,
+ .end = AT91RM9200_ID_US1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart1_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91rm9200_uart1_device = {
+ .name = "atmel_usart",
+ .id = 2,
+ .dev = {
+ .platform_data = &uart1_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart1_resources,
+ .num_resources = ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */
+ at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */
+ at91_set_A_periph(AT91_PIN_PB20, 1); /* TXD1 */
+ at91_set_A_periph(AT91_PIN_PB21, 0); /* RXD1 */
+ at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */
+ at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */
+ at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */
+ at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */
+}
+
+static struct resource uart2_resources[] = {
+ [0] = {
+ .start = AT91RM9200_BASE_US2,
+ .end = AT91RM9200_BASE_US2 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_US2,
+ .end = AT91RM9200_ID_US2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart2_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91rm9200_uart2_device = {
+ .name = "atmel_usart",
+ .id = 3,
+ .dev = {
+ .platform_data = &uart2_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart2_resources,
+ .num_resources = ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PA22, 0); /* RXD2 */
+ at91_set_A_periph(AT91_PIN_PA23, 1); /* TXD2 */
+}
+
+static struct resource uart3_resources[] = {
+ [0] = {
+ .start = AT91RM9200_BASE_US3,
+ .end = AT91RM9200_BASE_US3 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91RM9200_ID_US3,
+ .end = AT91RM9200_ID_US3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart3_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91rm9200_uart3_device = {
+ .name = "atmel_usart",
+ .id = 4,
+ .dev = {
+ .platform_data = &uart3_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart3_resources,
+ .num_resources = ARRAY_SIZE(uart3_resources),
+};
+
+static inline void configure_usart3_pins(void)
+{
+ at91_set_B_periph(AT91_PIN_PA5, 1); /* TXD3 */
+ at91_set_B_periph(AT91_PIN_PA6, 0); /* RXD3 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+struct platform_device *atmel_default_console_device; /* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+ int i;
+
+ /* Fill in list of supported UARTs */
+ for (i = 0; i < config->nr_tty; i++) {
+ switch (config->tty_map[i]) {
+ case 0:
+ configure_usart0_pins();
+ at91_uarts[i] = &at91rm9200_uart0_device;
+ at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart");
+ break;
+ case 1:
+ configure_usart1_pins();
+ at91_uarts[i] = &at91rm9200_uart1_device;
+ at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart");
+ break;
+ case 2:
+ configure_usart2_pins();
+ at91_uarts[i] = &at91rm9200_uart2_device;
+ at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart");
+ break;
+ case 3:
+ configure_usart3_pins();
+ at91_uarts[i] = &at91rm9200_uart3_device;
+ at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart");
+ break;
+ case 4:
+ configure_dbgu_pins();
+ at91_uarts[i] = &at91rm9200_dbgu_device;
+ at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart");
+ break;
+ default:
+ continue;
+ }
+ at91_uarts[i]->id = i; /* update ID number to mapped ID */
+ }
+
+ /* Set serial console device */
+ if (config->console_tty < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[config->console_tty];
+ if (!atmel_default_console_device)
+ printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+ int i;
+
+ for (i = 0; i < ATMEL_MAX_UART; i++) {
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+ at91_add_device_rtc();
+ at91_add_device_watchdog();
+ return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
new file mode 100644
index 000000000000..949199a244c7
--- /dev/null
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -0,0 +1,146 @@
+/*
+ * linux/arch/arm/mach-at91/at91rm9200_time.c
+ *
+ * Copyright (C) 2003 SAN People
+ * Copyright (C) 2003 ATMEL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/at91_st.h>
+
+static unsigned long last_crtr;
+
+/*
+ * The ST_CRTR is updated asynchronously to the master clock. It is therefore
+ * necessary to read it twice (with the same value) to ensure accuracy.
+ */
+static inline unsigned long read_CRTR(void) {
+ unsigned long x1, x2;
+
+ do {
+ x1 = at91_sys_read(AT91_ST_CRTR);
+ x2 = at91_sys_read(AT91_ST_CRTR);
+ } while (x1 != x2);
+
+ return x1;
+}
+
+/*
+ * Returns number of microseconds since last timer interrupt. Note that interrupts
+ * will have been disabled by do_gettimeofday()
+ * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+ * 'tick' is usecs per jiffy (linux/timex.h).
+ */
+static unsigned long at91rm9200_gettimeoffset(void)
+{
+ unsigned long elapsed;
+
+ elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
+
+ return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
+{
+ if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */
+ write_seqlock(&xtime_lock);
+
+ while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
+ timer_tick();
+ last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
+ }
+
+ write_sequnlock(&xtime_lock);
+
+ return IRQ_HANDLED;
+ }
+ else
+ return IRQ_NONE; /* not handled */
+}
+
+static struct irqaction at91rm9200_timer_irq = {
+ .name = "at91_tick",
+ .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
+ .handler = at91rm9200_timer_interrupt
+};
+
+void at91rm9200_timer_reset(void)
+{
+ last_crtr = 0;
+
+ /* Real time counter incremented every 30.51758 microseconds */
+ at91_sys_write(AT91_ST_RTMR, 1);
+
+ /* Set Period Interval timer */
+ at91_sys_write(AT91_ST_PIMR, LATCH);
+
+ /* Clear any pending interrupts */
+ (void) at91_sys_read(AT91_ST_SR);
+
+ /* Enable Period Interval Timer interrupt */
+ at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+}
+
+/*
+ * Set up timer interrupt.
+ */
+void __init at91rm9200_timer_init(void)
+{
+ /* Disable all timer interrupts */
+ at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
+ (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */
+
+ /* Make IRQs happen for the system timer */
+ setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
+
+ /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */
+ tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE;
+
+ /* Initialize and enable the timer interrupt */
+ at91rm9200_timer_reset();
+}
+
+#ifdef CONFIG_PM
+static void at91rm9200_timer_suspend(void)
+{
+ /* disable Period Interval Timer interrupt */
+ at91_sys_write(AT91_ST_IDR, AT91_ST_PITS);
+}
+#else
+#define at91rm9200_timer_suspend NULL
+#endif
+
+struct sys_timer at91rm9200_timer = {
+ .init = at91rm9200_timer_init,
+ .offset = at91rm9200_gettimeoffset,
+ .suspend = at91rm9200_timer_suspend,
+ .resume = at91rm9200_timer_reset,
+};
+
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
new file mode 100644
index 000000000000..6ea41d8266cb
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -0,0 +1,367 @@
+/*
+ * arch/arm/mach-at91/at91sam9260.c
+ *
+ * Copyright (C) 2006 SAN People
+ *
+ * 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/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/at91sam9260.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9260_io_desc[] __initdata = {
+ {
+ .virtual = AT91_VA_BASE_SYS,
+ .pfn = __phys_to_pfn(AT91_BASE_SYS),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }
+};
+
+static struct map_desc at91sam9260_sram_desc[] __initdata = {
+ {
+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
+ .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
+ .length = AT91SAM9260_SRAM0_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE,
+ .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
+ .length = AT91SAM9260_SRAM1_SIZE,
+ .type = MT_DEVICE,
+ }
+};
+
+static struct map_desc at91sam9xe_sram_desc[] __initdata = {
+ {
+ .pfn = __phys_to_pfn(AT91SAM9XE_SRAM_BASE),
+ .type = MT_DEVICE,
+ }
+};
+
+/* --------------------------------------------------------------------
+ * Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+ .name = "pioA_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_PIOA,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+ .name = "pioB_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_PIOB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+ .name = "pioC_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_PIOC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk adc_clk = {
+ .name = "adc_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_ADC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+ .name = "usart0_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_US0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+ .name = "usart1_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_US1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+ .name = "usart2_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_US2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+ .name = "mci_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_MCI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+ .name = "udc_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_UDP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+ .name = "twi_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TWI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+ .name = "spi0_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_SPI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+ .name = "spi1_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_SPI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc0_clk = {
+ .name = "tc0_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+ .name = "tc1_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+ .name = "tc2_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+ .name = "ohci_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_UHP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk macb_clk = {
+ .name = "macb_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_EMAC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk isi_clk = {
+ .name = "isi_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_ISI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+ .name = "usart3_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_US3,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart4_clk = {
+ .name = "usart4_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_US4,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart5_clk = {
+ .name = "usart5_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_US5,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc3_clk = {
+ .name = "tc3_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC3,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc4_clk = {
+ .name = "tc4_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC4,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc5_clk = {
+ .name = "tc5_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC5,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+ &pioA_clk,
+ &pioB_clk,
+ &pioC_clk,
+ &adc_clk,
+ &usart0_clk,
+ &usart1_clk,
+ &usart2_clk,
+ &mmc_clk,
+ &udc_clk,
+ &twi_clk,
+ &spi0_clk,
+ &spi1_clk,
+ // ssc
+ &tc0_clk,
+ &tc1_clk,
+ &tc2_clk,
+ &ohci_clk,
+ &macb_clk,
+ &isi_clk,
+ &usart3_clk,
+ &usart4_clk,
+ &usart5_clk,
+ &tc3_clk,
+ &tc4_clk,
+ &tc5_clk,
+ // irq0 .. irq2
+};
+
+/*
+ * The two programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+ .name = "pck0",
+ .pmc_mask = AT91_PMC_PCK0,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 0,
+};
+static struct clk pck1 = {
+ .name = "pck1",
+ .pmc_mask = AT91_PMC_PCK1,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 1,
+};
+
+static void __init at91sam9260_register_clocks(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+ clk_register(periph_clocks[i]);
+
+ clk_register(&pck0);
+ clk_register(&pck1);
+}
+
+/* --------------------------------------------------------------------
+ * GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9260_gpio[] = {
+ {
+ .id = AT91SAM9260_ID_PIOA,
+ .offset = AT91_PIOA,
+ .clock = &pioA_clk,
+ }, {
+ .id = AT91SAM9260_ID_PIOB,
+ .offset = AT91_PIOB,
+ .clock = &pioB_clk,
+ }, {
+ .id = AT91SAM9260_ID_PIOC,
+ .offset = AT91_PIOC,
+ .clock = &pioC_clk,
+ }
+};
+
+static void at91sam9260_reset(void)
+{
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ * AT91SAM9260 processor initialization
+ * -------------------------------------------------------------------- */
+
+static void __init at91sam9xe_initialize(void)
+{
+ unsigned long cidr, sram_size;
+
+ cidr = at91_sys_read(AT91_DBGU_CIDR);
+
+ switch (cidr & AT91_CIDR_SRAMSIZ) {
+ case AT91_CIDR_SRAMSIZ_32K:
+ sram_size = 2 * SZ_16K;
+ break;
+ case AT91_CIDR_SRAMSIZ_16K:
+ default:
+ sram_size = SZ_16K;
+ }
+
+ at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
+ at91sam9xe_sram_desc->length = sram_size;
+
+ iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc));
+}
+
+void __init at91sam9260_initialize(unsigned long main_clock)
+{
+ /* Map peripherals */
+ iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
+
+ if (cpu_is_at91sam9xe())
+ at91sam9xe_initialize();
+ else
+ iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
+
+ at91_arch_reset = at91sam9260_reset;
+ at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
+ | (1 << AT91SAM9260_ID_IRQ2);
+
+ /* Init clock subsystem */
+ at91_clock_init(main_clock);
+
+ /* Register the processor-specific clocks */
+ at91sam9260_register_clocks();
+
+ /* Register GPIO subsystem */
+ at91_gpio_init(at91sam9260_gpio, 3);
+}
+
+/* --------------------------------------------------------------------
+ * Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
+ 7, /* Advanced Interrupt Controller */
+ 7, /* System Peripherals */
+ 0, /* Parallel IO Controller A */
+ 0, /* Parallel IO Controller B */
+ 0, /* Parallel IO Controller C */
+ 0, /* Analog-to-Digital Converter */
+ 6, /* USART 0 */
+ 6, /* USART 1 */
+ 6, /* USART 2 */
+ 0, /* Multimedia Card Interface */
+ 4, /* USB Device Port */
+ 0, /* Two-Wire Interface */
+ 6, /* Serial Peripheral Interface 0 */
+ 6, /* Serial Peripheral Interface 1 */
+ 5, /* Serial Synchronous Controller */
+ 0,
+ 0,
+ 0, /* Timer Counter 0 */
+ 0, /* Timer Counter 1 */
+ 0, /* Timer Counter 2 */
+ 3, /* USB Host port */
+ 3, /* Ethernet */
+ 0, /* Image Sensor Interface */
+ 6, /* USART 3 */
+ 6, /* USART 4 */
+ 6, /* USART 5 */
+ 0, /* Timer Counter 3 */
+ 0, /* Timer Counter 4 */
+ 0, /* Timer Counter 5 */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+};
+
+void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+ if (!priority)
+ priority = at91sam9260_default_irq_priority;
+
+ /* Initialize the AIC interrupt controller */
+ at91_aic_init(priority);
+
+ /* Enable GPIO interrupts */
+ at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
new file mode 100644
index 000000000000..f7d342ccbebf
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -0,0 +1,871 @@
+/*
+ * arch/arm/mach-at91/at91sam9260_devices.c
+ *
+ * Copyright (C) 2006 Atmel
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9260.h>
+#include <asm/arch/at91sam926x_mc.h>
+#include <asm/arch/at91sam9260_matrix.h>
+
+#include "generic.h"
+
+#define SZ_512 0x00000200
+#define SZ_256 0x00000100
+#define SZ_16 0x00000010
+
+/* --------------------------------------------------------------------
+ * USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_UHP_BASE,
+ .end = AT91SAM9260_UHP_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_UHP,
+ .end = AT91SAM9260_ID_UHP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91_usbh_device = {
+ .name = "at91_ohci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbh_data,
+ },
+ .resource = usbh_resources,
+ .num_resources = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+ if (!data)
+ return;
+
+ usbh_data = *data;
+ platform_device_register(&at91_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_UDP,
+ .end = AT91SAM9260_BASE_UDP + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_UDP,
+ .end = AT91SAM9260_ID_UDP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91_udc_device = {
+ .name = "at91_udc",
+ .id = -1,
+ .dev = {
+ .platform_data = &udc_data,
+ },
+ .resource = udc_resources,
+ .num_resources = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->vbus_pin) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+
+ /* Pullup pin is handled internally by USB device peripheral */
+
+ udc_data = *data;
+ platform_device_register(&at91_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_EMAC,
+ .end = AT91SAM9260_BASE_EMAC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_EMAC,
+ .end = AT91SAM9260_ID_EMAC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9260_eth_device = {
+ .name = "macb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &eth_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &eth_data,
+ },
+ .resource = eth_resources,
+ .num_resources = ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->phy_irq_pin) {
+ at91_set_gpio_input(data->phy_irq_pin, 0);
+ at91_set_deglitch(data->phy_irq_pin, 1);
+ }
+
+ /* Pins used for MII and RMII */
+ at91_set_A_periph(AT91_PIN_PA19, 0); /* ETXCK_EREFCK */
+ at91_set_A_periph(AT91_PIN_PA17, 0); /* ERXDV */
+ at91_set_A_periph(AT91_PIN_PA14, 0); /* ERX0 */
+ at91_set_A_periph(AT91_PIN_PA15, 0); /* ERX1 */
+ at91_set_A_periph(AT91_PIN_PA18, 0); /* ERXER */
+ at91_set_A_periph(AT91_PIN_PA16, 0); /* ETXEN */
+ at91_set_A_periph(AT91_PIN_PA12, 0); /* ETX0 */
+ at91_set_A_periph(AT91_PIN_PA13, 0); /* ETX1 */
+ at91_set_A_periph(AT91_PIN_PA21, 0); /* EMDIO */
+ at91_set_A_periph(AT91_PIN_PA20, 0); /* EMDC */
+
+ if (!data->is_rmii) {
+ at91_set_B_periph(AT91_PIN_PA28, 0); /* ECRS */
+ at91_set_B_periph(AT91_PIN_PA29, 0); /* ECOL */
+ at91_set_B_periph(AT91_PIN_PA25, 0); /* ERX2 */
+ at91_set_B_periph(AT91_PIN_PA26, 0); /* ERX3 */
+ at91_set_B_periph(AT91_PIN_PA27, 0); /* ERXCK */
+ at91_set_B_periph(AT91_PIN_PA23, 0); /* ETX2 */
+ at91_set_B_periph(AT91_PIN_PA24, 0); /* ETX3 */
+ at91_set_B_periph(AT91_PIN_PA22, 0); /* ETXER */
+ }
+
+ eth_data = *data;
+ platform_device_register(&at91sam9260_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_MCI,
+ .end = AT91SAM9260_BASE_MCI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_MCI,
+ .end = AT91SAM9260_ID_MCI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9260_mmc_device = {
+ .name = "at91_mci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &mmc_data,
+ },
+ .resource = mmc_resources,
+ .num_resources = ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+ if (!data)
+ return;
+
+ /* input/irq */
+ if (data->det_pin) {
+ at91_set_gpio_input(data->det_pin, 1);
+ at91_set_deglitch(data->det_pin, 1);
+ }
+ if (data->wp_pin)
+ at91_set_gpio_input(data->wp_pin, 1);
+ if (data->vcc_pin)
+ at91_set_gpio_output(data->vcc_pin, 0);
+
+ /* CLK */
+ at91_set_A_periph(AT91_PIN_PA8, 0);
+
+ if (data->slot_b) {
+ /* CMD */
+ at91_set_B_periph(AT91_PIN_PA1, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_B_periph(AT91_PIN_PA0, 1);
+ if (data->wire4) {
+ at91_set_B_periph(AT91_PIN_PA5, 1);
+ at91_set_B_periph(AT91_PIN_PA4, 1);
+ at91_set_B_periph(AT91_PIN_PA3, 1);
+ }
+ } else {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA7, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA6, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA9, 1);
+ at91_set_A_periph(AT91_PIN_PA10, 1);
+ at91_set_A_periph(AT91_PIN_PA11, 1);
+ }
+ }
+
+ mmc_data = *data;
+ platform_device_register(&at91sam9260_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+#define NAND_BASE AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+ {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91sam9260_nand_device = {
+ .name = "at91_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .resource = nand_resources,
+ .num_resources = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+ unsigned long csa, mode;
+
+ if (!data)
+ return;
+
+ csa = at91_sys_read(AT91_MATRIX_EBICSA);
+ at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC);
+
+ /* set the bus interface characteristics */
+ at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+ | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+ at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5)
+ | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5));
+
+ at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7));
+
+ if (data->bus_width_16)
+ mode = AT91_SMC_DBW_16;
+ else
+ mode = AT91_SMC_DBW_8;
+ at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1));
+
+ /* enable pin */
+ if (data->enable_pin)
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (data->rdy_pin)
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (data->det_pin)
+ at91_set_gpio_input(data->det_pin, 1);
+
+ nand_data = *data;
+ platform_device_register(&at91sam9260_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_TWI,
+ .end = AT91SAM9260_BASE_TWI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_TWI,
+ .end = AT91SAM9260_ID_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9260_twi_device = {
+ .name = "at91_i2c",
+ .id = -1,
+ .resource = twi_resources,
+ .num_resources = ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+ /* pins used for TWI interface */
+ at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */
+ at91_set_multi_drive(AT91_PIN_PA23, 1);
+
+ at91_set_A_periph(AT91_PIN_PA24, 0); /* TWCK */
+ at91_set_multi_drive(AT91_PIN_PA24, 1);
+
+ platform_device_register(&at91sam9260_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_SPI0,
+ .end = AT91SAM9260_BASE_SPI0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_SPI0,
+ .end = AT91SAM9260_ID_SPI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9260_spi0_device = {
+ .name = "atmel_spi",
+ .id = 0,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi0_resources,
+ .num_resources = ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 };
+
+static struct resource spi1_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_SPI1,
+ .end = AT91SAM9260_BASE_SPI1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_SPI1,
+ .end = AT91SAM9260_ID_SPI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9260_spi1_device = {
+ .name = "atmel_spi",
+ .id = 1,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi1_resources,
+ .num_resources = ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+ int i;
+ unsigned long cs_pin;
+ short enable_spi0 = 0;
+ short enable_spi1 = 0;
+
+ /* Choose SPI chip-selects */
+ for (i = 0; i < nr_devices; i++) {
+ if (devices[i].controller_data)
+ cs_pin = (unsigned long) devices[i].controller_data;
+ else if (devices[i].bus_num == 0)
+ cs_pin = spi0_standard_cs[devices[i].chip_select];
+ else
+ cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+ if (devices[i].bus_num == 0)
+ enable_spi0 = 1;
+ else
+ enable_spi1 = 1;
+
+ /* enable chip-select pin */
+ at91_set_gpio_output(cs_pin, 1);
+
+ /* pass chip-select pin to driver */
+ devices[i].controller_data = (void *) cs_pin;
+ }
+
+ spi_register_board_info(devices, nr_devices);
+
+ /* Configure SPI bus(es) */
+ if (enable_spi0) {
+ at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */
+ at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */
+ at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */
+
+ at91_clock_associate("spi0_clk", &at91sam9260_spi0_device.dev, "spi_clk");
+ platform_device_register(&at91sam9260_spi0_device);
+ }
+ if (enable_spi1) {
+ at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI1_MISO */
+ at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI1_MOSI */
+ at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI1_SPCK */
+
+ at91_clock_associate("spi1_clk", &at91sam9260_spi1_device.dev, "spi_clk");
+ platform_device_register(&at91sam9260_spi1_device);
+ }
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+ /* Enable GPIO to access the LEDs */
+ at91_set_gpio_output(cpu_led, 1);
+ at91_set_gpio_output(timer_led, 1);
+
+ at91_leds_cpu = cpu_led;
+ at91_leds_timer = timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * UART
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+ [0] = {
+ .start = AT91_VA_BASE_SYS + AT91_DBGU,
+ .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_SYS,
+ .end = AT91_ID_SYS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data dbgu_data = {
+ .use_dma_tx = 0,
+ .use_dma_rx = 0, /* DBGU not capable of receive DMA */
+ .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9260_dbgu_device = {
+ .name = "atmel_usart",
+ .id = 0,
+ .dev = {
+ .platform_data = &dbgu_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = dbgu_resources,
+ .num_resources = ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PB14, 0); /* DRXD */
+ at91_set_A_periph(AT91_PIN_PB15, 1); /* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_US0,
+ .end = AT91SAM9260_BASE_US0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_US0,
+ .end = AT91SAM9260_ID_US0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart0_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9260_uart0_device = {
+ .name = "atmel_usart",
+ .id = 1,
+ .dev = {
+ .platform_data = &uart0_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart0_resources,
+ .num_resources = ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PB4, 1); /* TXD0 */
+ at91_set_A_periph(AT91_PIN_PB5, 0); /* RXD0 */
+ at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS0 */
+ at91_set_A_periph(AT91_PIN_PB27, 0); /* CTS0 */
+ at91_set_A_periph(AT91_PIN_PB24, 0); /* DTR0 */
+ at91_set_A_periph(AT91_PIN_PB22, 0); /* DSR0 */
+ at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD0 */
+ at91_set_A_periph(AT91_PIN_PB25, 0); /* RI0 */
+}
+
+static struct resource uart1_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_US1,
+ .end = AT91SAM9260_BASE_US1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_US1,
+ .end = AT91SAM9260_ID_US1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart1_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9260_uart1_device = {
+ .name = "atmel_usart",
+ .id = 2,
+ .dev = {
+ .platform_data = &uart1_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart1_resources,
+ .num_resources = ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PB6, 1); /* TXD1 */
+ at91_set_A_periph(AT91_PIN_PB7, 0); /* RXD1 */
+ at91_set_A_periph(AT91_PIN_PB28, 0); /* RTS1 */
+ at91_set_A_periph(AT91_PIN_PB29, 0); /* CTS1 */
+}
+
+static struct resource uart2_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_US2,
+ .end = AT91SAM9260_BASE_US2 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_US2,
+ .end = AT91SAM9260_ID_US2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart2_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9260_uart2_device = {
+ .name = "atmel_usart",
+ .id = 3,
+ .dev = {
+ .platform_data = &uart2_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart2_resources,
+ .num_resources = ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PB8, 1); /* TXD2 */
+ at91_set_A_periph(AT91_PIN_PB9, 0); /* RXD2 */
+}
+
+static struct resource uart3_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_US3,
+ .end = AT91SAM9260_BASE_US3 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_US3,
+ .end = AT91SAM9260_ID_US3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart3_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9260_uart3_device = {
+ .name = "atmel_usart",
+ .id = 4,
+ .dev = {
+ .platform_data = &uart3_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart3_resources,
+ .num_resources = ARRAY_SIZE(uart3_resources),
+};
+
+static inline void configure_usart3_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PB10, 1); /* TXD3 */
+ at91_set_A_periph(AT91_PIN_PB11, 0); /* RXD3 */
+}
+
+static struct resource uart4_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_US4,
+ .end = AT91SAM9260_BASE_US4 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_US4,
+ .end = AT91SAM9260_ID_US4,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart4_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9260_uart4_device = {
+ .name = "atmel_usart",
+ .id = 5,
+ .dev = {
+ .platform_data = &uart4_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart4_resources,
+ .num_resources = ARRAY_SIZE(uart4_resources),
+};
+
+static inline void configure_usart4_pins(void)
+{
+ at91_set_B_periph(AT91_PIN_PA31, 1); /* TXD4 */
+ at91_set_B_periph(AT91_PIN_PA30, 0); /* RXD4 */
+}
+
+static struct resource uart5_resources[] = {
+ [0] = {
+ .start = AT91SAM9260_BASE_US5,
+ .end = AT91SAM9260_BASE_US5 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9260_ID_US5,
+ .end = AT91SAM9260_ID_US5,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart5_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9260_uart5_device = {
+ .name = "atmel_usart",
+ .id = 6,
+ .dev = {
+ .platform_data = &uart5_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart5_resources,
+ .num_resources = ARRAY_SIZE(uart5_resources),
+};
+
+static inline void configure_usart5_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PB12, 1); /* TXD5 */
+ at91_set_A_periph(AT91_PIN_PB13, 0); /* RXD5 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+struct platform_device *atmel_default_console_device; /* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+ int i;
+
+ /* Fill in list of supported UARTs */
+ for (i = 0; i < config->nr_tty; i++) {
+ switch (config->tty_map[i]) {
+ case 0:
+ configure_usart0_pins();
+ at91_uarts[i] = &at91sam9260_uart0_device;
+ at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart");
+ break;
+ case 1:
+ configure_usart1_pins();
+ at91_uarts[i] = &at91sam9260_uart1_device;
+ at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart");
+ break;
+ case 2:
+ configure_usart2_pins();
+ at91_uarts[i] = &at91sam9260_uart2_device;
+ at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart");
+ break;
+ case 3:
+ configure_usart3_pins();
+ at91_uarts[i] = &at91sam9260_uart3_device;
+ at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart");
+ break;
+ case 4:
+ configure_usart4_pins();
+ at91_uarts[i] = &at91sam9260_uart4_device;
+ at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart");
+ break;
+ case 5:
+ configure_usart5_pins();
+ at91_uarts[i] = &at91sam9260_uart5_device;
+ at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart");
+ break;
+ case 6:
+ configure_dbgu_pins();
+ at91_uarts[i] = &at91sam9260_dbgu_device;
+ at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart");
+ break;
+ default:
+ continue;
+ }
+ at91_uarts[i]->id = i; /* update ID number to mapped ID */
+ }
+
+ /* Set serial console device */
+ if (config->console_tty < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[config->console_tty];
+ if (!atmel_default_console_device)
+ printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+ int i;
+
+ for (i = 0; i < ATMEL_MAX_UART; i++) {
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+ return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
new file mode 100644
index 000000000000..784d1e682d6d
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -0,0 +1,307 @@
+/*
+ * arch/arm/mach-at91/at91sam9261.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * 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/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91sam9261.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9261_io_desc[] __initdata = {
+ {
+ .virtual = AT91_VA_BASE_SYS,
+ .pfn = __phys_to_pfn(AT91_BASE_SYS),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE,
+ .pfn = __phys_to_pfn(AT91SAM9261_SRAM_BASE),
+ .length = AT91SAM9261_SRAM_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+/* --------------------------------------------------------------------
+ * Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+ .name = "pioA_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_PIOA,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+ .name = "pioB_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_PIOB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+ .name = "pioC_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_PIOC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+ .name = "usart0_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_US0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+ .name = "usart1_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_US1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+ .name = "usart2_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_US2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+ .name = "mci_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_MCI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+ .name = "udc_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_UDP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+ .name = "twi_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_TWI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+ .name = "spi0_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_SPI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+ .name = "spi1_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_SPI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc0_clk = {
+ .name = "tc0_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_TC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+ .name = "tc1_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_TC1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+ .name = "tc2_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_TC2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+ .name = "ohci_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_UHP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+ .name = "lcdc_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_LCDC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+ &pioA_clk,
+ &pioB_clk,
+ &pioC_clk,
+ &usart0_clk,
+ &usart1_clk,
+ &usart2_clk,
+ &mmc_clk,
+ &udc_clk,
+ &twi_clk,
+ &spi0_clk,
+ &spi1_clk,
+ // ssc 0 .. ssc2
+ &tc0_clk,
+ &tc1_clk,
+ &tc2_clk,
+ &ohci_clk,
+ &lcdc_clk,
+ // irq0 .. irq2
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+ .name = "pck0",
+ .pmc_mask = AT91_PMC_PCK0,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 0,
+};
+static struct clk pck1 = {
+ .name = "pck1",
+ .pmc_mask = AT91_PMC_PCK1,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 1,
+};
+static struct clk pck2 = {
+ .name = "pck2",
+ .pmc_mask = AT91_PMC_PCK2,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 2,
+};
+static struct clk pck3 = {
+ .name = "pck3",
+ .pmc_mask = AT91_PMC_PCK3,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 3,
+};
+
+/* HClocks */
+static struct clk hck0 = {
+ .name = "hck0",
+ .pmc_mask = AT91_PMC_HCK0,
+ .type = CLK_TYPE_SYSTEM,
+ .id = 0,
+};
+static struct clk hck1 = {
+ .name = "hck1",
+ .pmc_mask = AT91_PMC_HCK1,
+ .type = CLK_TYPE_SYSTEM,
+ .id = 1,
+};
+
+static void __init at91sam9261_register_clocks(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+ clk_register(periph_clocks[i]);
+
+ clk_register(&pck0);
+ clk_register(&pck1);
+ clk_register(&pck2);
+ clk_register(&pck3);
+
+ clk_register(&hck0);
+ clk_register(&hck1);
+}
+
+/* --------------------------------------------------------------------
+ * GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9261_gpio[] = {
+ {
+ .id = AT91SAM9261_ID_PIOA,
+ .offset = AT91_PIOA,
+ .clock = &pioA_clk,
+ }, {
+ .id = AT91SAM9261_ID_PIOB,
+ .offset = AT91_PIOB,
+ .clock = &pioB_clk,
+ }, {
+ .id = AT91SAM9261_ID_PIOC,
+ .offset = AT91_PIOC,
+ .clock = &pioC_clk,
+ }
+};
+
+static void at91sam9261_reset(void)
+{
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ * AT91SAM9261 processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at91sam9261_initialize(unsigned long main_clock)
+{
+ /* Map peripherals */
+ iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
+
+ at91_arch_reset = at91sam9261_reset;
+ at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
+ | (1 << AT91SAM9261_ID_IRQ2);
+
+ /* Init clock subsystem */
+ at91_clock_init(main_clock);
+
+ /* Register the processor-specific clocks */
+ at91sam9261_register_clocks();
+
+ /* Register GPIO subsystem */
+ at91_gpio_init(at91sam9261_gpio, 3);
+}
+
+/* --------------------------------------------------------------------
+ * Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
+ 7, /* Advanced Interrupt Controller */
+ 7, /* System Peripherals */
+ 0, /* Parallel IO Controller A */
+ 0, /* Parallel IO Controller B */
+ 0, /* Parallel IO Controller C */
+ 0,
+ 6, /* USART 0 */
+ 6, /* USART 1 */
+ 6, /* USART 2 */
+ 0, /* Multimedia Card Interface */
+ 4, /* USB Device Port */
+ 0, /* Two-Wire Interface */
+ 6, /* Serial Peripheral Interface 0 */
+ 6, /* Serial Peripheral Interface 1 */
+ 5, /* Serial Synchronous Controller 0 */
+ 5, /* Serial Synchronous Controller 1 */
+ 5, /* Serial Synchronous Controller 2 */
+ 0, /* Timer Counter 0 */
+ 0, /* Timer Counter 1 */
+ 0, /* Timer Counter 2 */
+ 3, /* USB Host port */
+ 3, /* LCD Controller */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+};
+
+void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+ if (!priority)
+ priority = at91sam9261_default_irq_priority;
+
+ /* Initialize the AIC interrupt controller */
+ at91_aic_init(priority);
+
+ /* Enable GPIO interrupts */
+ at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
new file mode 100644
index 000000000000..e1504766fd64
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -0,0 +1,745 @@
+/*
+ * arch/arm/mach-at91/at91sam9261_devices.c
+ *
+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright (C) 2005 David Brownell
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9261.h>
+#include <asm/arch/at91sam9261_matrix.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+#define SZ_512 0x00000200
+#define SZ_256 0x00000100
+#define SZ_16 0x00000010
+
+/* --------------------------------------------------------------------
+ * USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_UHP_BASE,
+ .end = AT91SAM9261_UHP_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_UHP,
+ .end = AT91SAM9261_ID_UHP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9261_usbh_device = {
+ .name = "at91_ohci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbh_data,
+ },
+ .resource = usbh_resources,
+ .num_resources = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+ if (!data)
+ return;
+
+ usbh_data = *data;
+ platform_device_register(&at91sam9261_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_UDP,
+ .end = AT91SAM9261_BASE_UDP + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_UDP,
+ .end = AT91SAM9261_ID_UDP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9261_udc_device = {
+ .name = "at91_udc",
+ .id = -1,
+ .dev = {
+ .platform_data = &udc_data,
+ },
+ .resource = udc_resources,
+ .num_resources = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ unsigned long x;
+
+ if (!data)
+ return;
+
+ if (data->vbus_pin) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+
+ /* Pullup pin is handled internally */
+ x = at91_sys_read(AT91_MATRIX_USBPUCR);
+ at91_sys_write(AT91_MATRIX_USBPUCR, x | AT91_MATRIX_USBPUCR_PUON);
+
+ udc_data = *data;
+ platform_device_register(&at91sam9261_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
+ * MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_MCI,
+ .end = AT91SAM9261_BASE_MCI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_MCI,
+ .end = AT91SAM9261_ID_MCI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9261_mmc_device = {
+ .name = "at91_mci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &mmc_data,
+ },
+ .resource = mmc_resources,
+ .num_resources = ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+ if (!data)
+ return;
+
+ /* input/irq */
+ if (data->det_pin) {
+ at91_set_gpio_input(data->det_pin, 1);
+ at91_set_deglitch(data->det_pin, 1);
+ }
+ if (data->wp_pin)
+ at91_set_gpio_input(data->wp_pin, 1);
+ if (data->vcc_pin)
+ at91_set_gpio_output(data->vcc_pin, 0);
+
+ /* CLK */
+ at91_set_B_periph(AT91_PIN_PA2, 0);
+
+ /* CMD */
+ at91_set_B_periph(AT91_PIN_PA1, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_B_periph(AT91_PIN_PA0, 1);
+ if (data->wire4) {
+ at91_set_B_periph(AT91_PIN_PA4, 1);
+ at91_set_B_periph(AT91_PIN_PA5, 1);
+ at91_set_B_periph(AT91_PIN_PA6, 1);
+ }
+
+ mmc_data = *data;
+ platform_device_register(&at91sam9261_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+#define NAND_BASE AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+ {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91_nand_device = {
+ .name = "at91_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .resource = nand_resources,
+ .num_resources = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+ unsigned long csa, mode;
+
+ if (!data)
+ return;
+
+ csa = at91_sys_read(AT91_MATRIX_EBICSA);
+ at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC);
+
+ /* set the bus interface characteristics */
+ at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+ | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+ at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5)
+ | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5));
+
+ at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7));
+
+ if (data->bus_width_16)
+ mode = AT91_SMC_DBW_16;
+ else
+ mode = AT91_SMC_DBW_8;
+ at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1));
+
+ /* enable pin */
+ if (data->enable_pin)
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (data->rdy_pin)
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (data->det_pin)
+ at91_set_gpio_input(data->det_pin, 1);
+
+ at91_set_A_periph(AT91_PIN_PC0, 0); /* NANDOE */
+ at91_set_A_periph(AT91_PIN_PC1, 0); /* NANDWE */
+
+ nand_data = *data;
+ platform_device_register(&at91_nand_device);
+}
+
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_TWI,
+ .end = AT91SAM9261_BASE_TWI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_TWI,
+ .end = AT91SAM9261_ID_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9261_twi_device = {
+ .name = "at91_i2c",
+ .id = -1,
+ .resource = twi_resources,
+ .num_resources = ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+ /* pins used for TWI interface */
+ at91_set_A_periph(AT91_PIN_PA7, 0); /* TWD */
+ at91_set_multi_drive(AT91_PIN_PA7, 1);
+
+ at91_set_A_periph(AT91_PIN_PA8, 0); /* TWCK */
+ at91_set_multi_drive(AT91_PIN_PA8, 1);
+
+ platform_device_register(&at91sam9261_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_SPI0,
+ .end = AT91SAM9261_BASE_SPI0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_SPI0,
+ .end = AT91SAM9261_ID_SPI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9261_spi0_device = {
+ .name = "atmel_spi",
+ .id = 0,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi0_resources,
+ .num_resources = ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
+
+static struct resource spi1_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_SPI1,
+ .end = AT91SAM9261_BASE_SPI1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_SPI1,
+ .end = AT91SAM9261_ID_SPI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9261_spi1_device = {
+ .name = "atmel_spi",
+ .id = 1,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi1_resources,
+ .num_resources = ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+ int i;
+ unsigned long cs_pin;
+ short enable_spi0 = 0;
+ short enable_spi1 = 0;
+
+ /* Choose SPI chip-selects */
+ for (i = 0; i < nr_devices; i++) {
+ if (devices[i].controller_data)
+ cs_pin = (unsigned long) devices[i].controller_data;
+ else if (devices[i].bus_num == 0)
+ cs_pin = spi0_standard_cs[devices[i].chip_select];
+ else
+ cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+ if (devices[i].bus_num == 0)
+ enable_spi0 = 1;
+ else
+ enable_spi1 = 1;
+
+ /* enable chip-select pin */
+ at91_set_gpio_output(cs_pin, 1);
+
+ /* pass chip-select pin to driver */
+ devices[i].controller_data = (void *) cs_pin;
+ }
+
+ spi_register_board_info(devices, nr_devices);
+
+ /* Configure SPI bus(es) */
+ if (enable_spi0) {
+ at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */
+ at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */
+ at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI0_SPCK */
+
+ at91_clock_associate("spi0_clk", &at91sam9261_spi0_device.dev, "spi_clk");
+ platform_device_register(&at91sam9261_spi0_device);
+ }
+ if (enable_spi1) {
+ at91_set_A_periph(AT91_PIN_PB30, 0); /* SPI1_MISO */
+ at91_set_A_periph(AT91_PIN_PB31, 0); /* SPI1_MOSI */
+ at91_set_A_periph(AT91_PIN_PB29, 0); /* SPI1_SPCK */
+
+ at91_clock_associate("spi1_clk", &at91sam9261_spi1_device.dev, "spi_clk");
+ platform_device_register(&at91sam9261_spi1_device);
+ }
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LCD Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE)
+static u64 lcdc_dmamask = 0xffffffffUL;
+static struct at91fb_info lcdc_data;
+
+static struct resource lcdc_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_LCDC_BASE,
+ .end = AT91SAM9261_LCDC_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_LCDC,
+ .end = AT91SAM9261_ID_LCDC,
+ .flags = IORESOURCE_IRQ,
+ },
+#if defined(CONFIG_FB_INTSRAM)
+ [2] = {
+ .start = AT91SAM9261_SRAM_BASE,
+ .end = AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+};
+
+static struct platform_device at91_lcdc_device = {
+ .name = "at91-fb",
+ .id = 0,
+ .dev = {
+ .dma_mask = &lcdc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &lcdc_data,
+ },
+ .resource = lcdc_resources,
+ .num_resources = ARRAY_SIZE(lcdc_resources),
+};
+
+void __init at91_add_device_lcdc(struct at91fb_info *data)
+{
+ if (!data) {
+ return;
+ }
+
+ at91_set_A_periph(AT91_PIN_PB1, 0); /* LCDHSYNC */
+ at91_set_A_periph(AT91_PIN_PB2, 0); /* LCDDOTCK */
+ at91_set_A_periph(AT91_PIN_PB3, 0); /* LCDDEN */
+ at91_set_A_periph(AT91_PIN_PB4, 0); /* LCDCC */
+ at91_set_A_periph(AT91_PIN_PB7, 0); /* LCDD2 */
+ at91_set_A_periph(AT91_PIN_PB8, 0); /* LCDD3 */
+ at91_set_A_periph(AT91_PIN_PB9, 0); /* LCDD4 */
+ at91_set_A_periph(AT91_PIN_PB10, 0); /* LCDD5 */
+ at91_set_A_periph(AT91_PIN_PB11, 0); /* LCDD6 */
+ at91_set_A_periph(AT91_PIN_PB12, 0); /* LCDD7 */
+ at91_set_A_periph(AT91_PIN_PB15, 0); /* LCDD10 */
+ at91_set_A_periph(AT91_PIN_PB16, 0); /* LCDD11 */
+ at91_set_A_periph(AT91_PIN_PB17, 0); /* LCDD12 */
+ at91_set_A_periph(AT91_PIN_PB18, 0); /* LCDD13 */
+ at91_set_A_periph(AT91_PIN_PB19, 0); /* LCDD14 */
+ at91_set_A_periph(AT91_PIN_PB20, 0); /* LCDD15 */
+ at91_set_B_periph(AT91_PIN_PB23, 0); /* LCDD18 */
+ at91_set_B_periph(AT91_PIN_PB24, 0); /* LCDD19 */
+ at91_set_B_periph(AT91_PIN_PB25, 0); /* LCDD20 */
+ at91_set_B_periph(AT91_PIN_PB26, 0); /* LCDD21 */
+ at91_set_B_periph(AT91_PIN_PB27, 0); /* LCDD22 */
+ at91_set_B_periph(AT91_PIN_PB28, 0); /* LCDD23 */
+
+ lcdc_data = *data;
+ platform_device_register(&at91_lcdc_device);
+}
+#else
+void __init at91_add_device_lcdc(struct at91fb_info *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+ /* Enable GPIO to access the LEDs */
+ at91_set_gpio_output(cpu_led, 1);
+ at91_set_gpio_output(timer_led, 1);
+
+ at91_leds_cpu = cpu_led;
+ at91_leds_timer = timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+ [0] = {
+ .start = AT91_VA_BASE_SYS + AT91_DBGU,
+ .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_SYS,
+ .end = AT91_ID_SYS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data dbgu_data = {
+ .use_dma_tx = 0,
+ .use_dma_rx = 0, /* DBGU not capable of receive DMA */
+ .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9261_dbgu_device = {
+ .name = "atmel_usart",
+ .id = 0,
+ .dev = {
+ .platform_data = &dbgu_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = dbgu_resources,
+ .num_resources = ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PA9, 0); /* DRXD */
+ at91_set_A_periph(AT91_PIN_PA10, 1); /* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_US0,
+ .end = AT91SAM9261_BASE_US0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_US0,
+ .end = AT91SAM9261_ID_US0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart0_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9261_uart0_device = {
+ .name = "atmel_usart",
+ .id = 1,
+ .dev = {
+ .platform_data = &uart0_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart0_resources,
+ .num_resources = ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PC8, 1); /* TXD0 */
+ at91_set_A_periph(AT91_PIN_PC9, 0); /* RXD0 */
+ at91_set_A_periph(AT91_PIN_PC10, 0); /* RTS0 */
+ at91_set_A_periph(AT91_PIN_PC11, 0); /* CTS0 */
+}
+
+static struct resource uart1_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_US1,
+ .end = AT91SAM9261_BASE_US1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_US1,
+ .end = AT91SAM9261_ID_US1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart1_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9261_uart1_device = {
+ .name = "atmel_usart",
+ .id = 2,
+ .dev = {
+ .platform_data = &uart1_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart1_resources,
+ .num_resources = ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PC12, 1); /* TXD1 */
+ at91_set_A_periph(AT91_PIN_PC13, 0); /* RXD1 */
+}
+
+static struct resource uart2_resources[] = {
+ [0] = {
+ .start = AT91SAM9261_BASE_US2,
+ .end = AT91SAM9261_BASE_US2 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9261_ID_US2,
+ .end = AT91SAM9261_ID_US2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart2_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9261_uart2_device = {
+ .name = "atmel_usart",
+ .id = 3,
+ .dev = {
+ .platform_data = &uart2_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart2_resources,
+ .num_resources = ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PC15, 0); /* RXD2 */
+ at91_set_A_periph(AT91_PIN_PC14, 1); /* TXD2 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+struct platform_device *atmel_default_console_device; /* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+ int i;
+
+ /* Fill in list of supported UARTs */
+ for (i = 0; i < config->nr_tty; i++) {
+ switch (config->tty_map[i]) {
+ case 0:
+ configure_usart0_pins();
+ at91_uarts[i] = &at91sam9261_uart0_device;
+ at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart");
+ break;
+ case 1:
+ configure_usart1_pins();
+ at91_uarts[i] = &at91sam9261_uart1_device;
+ at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart");
+ break;
+ case 2:
+ configure_usart2_pins();
+ at91_uarts[i] = &at91sam9261_uart2_device;
+ at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart");
+ break;
+ case 3:
+ configure_dbgu_pins();
+ at91_uarts[i] = &at91sam9261_dbgu_device;
+ at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart");
+ break;
+ default:
+ continue;
+ }
+ at91_uarts[i]->id = i; /* update ID number to mapped ID */
+ }
+
+ /* Set serial console device */
+ if (config->console_tty < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[config->console_tty];
+ if (!atmel_default_console_device)
+ printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+ int i;
+
+ for (i = 0; i < ATMEL_MAX_UART; i++) {
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+ return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
new file mode 100644
index 000000000000..6aa342e8f1b1
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -0,0 +1,313 @@
+/*
+ * arch/arm/mach-at91/at91sam9263.c
+ *
+ * Copyright (C) 2007 Atmel Corporation.
+ *
+ * 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/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91sam9263.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9263_io_desc[] __initdata = {
+ {
+ .virtual = AT91_VA_BASE_SYS,
+ .pfn = __phys_to_pfn(AT91_BASE_SYS),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE,
+ .pfn = __phys_to_pfn(AT91SAM9263_SRAM0_BASE),
+ .length = AT91SAM9263_SRAM0_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE,
+ .pfn = __phys_to_pfn(AT91SAM9263_SRAM1_BASE),
+ .length = AT91SAM9263_SRAM1_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+/* --------------------------------------------------------------------
+ * Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+ .name = "pioA_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_PIOA,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+ .name = "pioB_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_PIOB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioCDE_clk = {
+ .name = "pioCDE_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_PIOCDE,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+ .name = "usart0_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_US0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+ .name = "usart1_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_US1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+ .name = "usart2_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_US2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc0_clk = {
+ .name = "mci0_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_MCI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc1_clk = {
+ .name = "mci1_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_MCI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+ .name = "twi_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_TWI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+ .name = "spi0_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_SPI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+ .name = "spi1_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_SPI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tcb_clk = {
+ .name = "tcb_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_TCB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk macb_clk = {
+ .name = "macb_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_EMAC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+ .name = "udc_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_UDP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk isi_clk = {
+ .name = "isi_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_ISI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+ .name = "lcdc_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_ISI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+ .name = "ohci_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_UHP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+ &pioA_clk,
+ &pioB_clk,
+ &pioCDE_clk,
+ &usart0_clk,
+ &usart1_clk,
+ &usart2_clk,
+ &mmc0_clk,
+ &mmc1_clk,
+ // can
+ &twi_clk,
+ &spi0_clk,
+ &spi1_clk,
+ // ssc0 .. ssc1
+ // ac97
+ &tcb_clk,
+ // pwmc
+ &macb_clk,
+ // 2dge
+ &udc_clk,
+ &isi_clk,
+ &lcdc_clk,
+ // dma
+ &ohci_clk,
+ // irq0 .. irq1
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+ .name = "pck0",
+ .pmc_mask = AT91_PMC_PCK0,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 0,
+};
+static struct clk pck1 = {
+ .name = "pck1",
+ .pmc_mask = AT91_PMC_PCK1,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 1,
+};
+static struct clk pck2 = {
+ .name = "pck2",
+ .pmc_mask = AT91_PMC_PCK2,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 2,
+};
+static struct clk pck3 = {
+ .name = "pck3",
+ .pmc_mask = AT91_PMC_PCK3,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 3,
+};
+
+static void __init at91sam9263_register_clocks(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+ clk_register(periph_clocks[i]);
+
+ clk_register(&pck0);
+ clk_register(&pck1);
+ clk_register(&pck2);
+ clk_register(&pck3);
+}
+
+/* --------------------------------------------------------------------
+ * GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9263_gpio[] = {
+ {
+ .id = AT91SAM9263_ID_PIOA,
+ .offset = AT91_PIOA,
+ .clock = &pioA_clk,
+ }, {
+ .id = AT91SAM9263_ID_PIOB,
+ .offset = AT91_PIOB,
+ .clock = &pioB_clk,
+ }, {
+ .id = AT91SAM9263_ID_PIOCDE,
+ .offset = AT91_PIOC,
+ .clock = &pioCDE_clk,
+ }, {
+ .id = AT91SAM9263_ID_PIOCDE,
+ .offset = AT91_PIOD,
+ .clock = &pioCDE_clk,
+ }, {
+ .id = AT91SAM9263_ID_PIOCDE,
+ .offset = AT91_PIOE,
+ .clock = &pioCDE_clk,
+ }
+};
+
+static void at91sam9263_reset(void)
+{
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ * AT91SAM9263 processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at91sam9263_initialize(unsigned long main_clock)
+{
+ /* Map peripherals */
+ iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
+
+ at91_arch_reset = at91sam9263_reset;
+ at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
+
+ /* Init clock subsystem */
+ at91_clock_init(main_clock);
+
+ /* Register the processor-specific clocks */
+ at91sam9263_register_clocks();
+
+ /* Register GPIO subsystem */
+ at91_gpio_init(at91sam9263_gpio, 5);
+}
+
+/* --------------------------------------------------------------------
+ * Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
+ 7, /* Advanced Interrupt Controller (FIQ) */
+ 7, /* System Peripherals */
+ 0, /* Parallel IO Controller A */
+ 0, /* Parallel IO Controller B */
+ 0, /* Parallel IO Controller C, D and E */
+ 0,
+ 0,
+ 6, /* USART 0 */
+ 6, /* USART 1 */
+ 6, /* USART 2 */
+ 0, /* Multimedia Card Interface 0 */
+ 0, /* Multimedia Card Interface 1 */
+ 4, /* CAN */
+ 0, /* Two-Wire Interface */
+ 6, /* Serial Peripheral Interface 0 */
+ 6, /* Serial Peripheral Interface 1 */
+ 5, /* Serial Synchronous Controller 0 */
+ 5, /* Serial Synchronous Controller 1 */
+ 6, /* AC97 Controller */
+ 0, /* Timer Counter 0, 1 and 2 */
+ 0, /* Pulse Width Modulation Controller */
+ 3, /* Ethernet */
+ 0,
+ 0, /* 2D Graphic Engine */
+ 3, /* USB Device Port */
+ 0, /* Image Sensor Interface */
+ 3, /* LDC Controller */
+ 0, /* DMA Controller */
+ 0,
+ 3, /* USB Host port */
+ 0, /* Advanced Interrupt Controller (IRQ0) */
+ 0, /* Advanced Interrupt Controller (IRQ1) */
+};
+
+void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+ if (!priority)
+ priority = at91sam9263_default_irq_priority;
+
+ /* Initialize the AIC interrupt controller */
+ at91_aic_init(priority);
+
+ /* Enable GPIO interrupts */
+ at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
new file mode 100644
index 000000000000..d9af7ca58bce
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -0,0 +1,818 @@
+/*
+ * arch/arm/mach-at91/at91sam9263_devices.c
+ *
+ * Copyright (C) 2007 Atmel Corporation.
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9263.h>
+#include <asm/arch/at91sam926x_mc.h>
+#include <asm/arch/at91sam9263_matrix.h>
+
+#include "generic.h"
+
+#define SZ_512 0x00000200
+#define SZ_256 0x00000100
+#define SZ_16 0x00000010
+
+/* --------------------------------------------------------------------
+ * USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_UHP_BASE,
+ .end = AT91SAM9263_UHP_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_UHP,
+ .end = AT91SAM9263_ID_UHP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91_usbh_device = {
+ .name = "at91_ohci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbh_data,
+ },
+ .resource = usbh_resources,
+ .num_resources = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+ int i;
+
+ if (!data)
+ return;
+
+ /* Enable VBus control for UHP ports */
+ for (i = 0; i < data->ports; i++) {
+ if (data->vbus_pin[i])
+ at91_set_gpio_output(data->vbus_pin[i], 0);
+ }
+
+ usbh_data = *data;
+ platform_device_register(&at91_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_UDP,
+ .end = AT91SAM9263_BASE_UDP + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_UDP,
+ .end = AT91SAM9263_ID_UDP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91_udc_device = {
+ .name = "at91_udc",
+ .id = -1,
+ .dev = {
+ .platform_data = &udc_data,
+ },
+ .resource = udc_resources,
+ .num_resources = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->vbus_pin) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+
+ /* Pullup pin is handled internally by USB device peripheral */
+
+ udc_data = *data;
+ platform_device_register(&at91_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_EMAC,
+ .end = AT91SAM9263_BASE_EMAC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_EMAC,
+ .end = AT91SAM9263_ID_EMAC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_eth_device = {
+ .name = "macb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &eth_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &eth_data,
+ },
+ .resource = eth_resources,
+ .num_resources = ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->phy_irq_pin) {
+ at91_set_gpio_input(data->phy_irq_pin, 0);
+ at91_set_deglitch(data->phy_irq_pin, 1);
+ }
+
+ /* Pins used for MII and RMII */
+ at91_set_A_periph(AT91_PIN_PE21, 0); /* ETXCK_EREFCK */
+ at91_set_B_periph(AT91_PIN_PC25, 0); /* ERXDV */
+ at91_set_A_periph(AT91_PIN_PE25, 0); /* ERX0 */
+ at91_set_A_periph(AT91_PIN_PE26, 0); /* ERX1 */
+ at91_set_A_periph(AT91_PIN_PE27, 0); /* ERXER */
+ at91_set_A_periph(AT91_PIN_PE28, 0); /* ETXEN */
+ at91_set_A_periph(AT91_PIN_PE23, 0); /* ETX0 */
+ at91_set_A_periph(AT91_PIN_PE24, 0); /* ETX1 */
+ at91_set_A_periph(AT91_PIN_PE30, 0); /* EMDIO */
+ at91_set_A_periph(AT91_PIN_PE29, 0); /* EMDC */
+
+ if (!data->is_rmii) {
+ at91_set_A_periph(AT91_PIN_PE22, 0); /* ECRS */
+ at91_set_B_periph(AT91_PIN_PC26, 0); /* ECOL */
+ at91_set_B_periph(AT91_PIN_PC22, 0); /* ERX2 */
+ at91_set_B_periph(AT91_PIN_PC23, 0); /* ERX3 */
+ at91_set_B_periph(AT91_PIN_PC27, 0); /* ERXCK */
+ at91_set_B_periph(AT91_PIN_PC20, 0); /* ETX2 */
+ at91_set_B_periph(AT91_PIN_PC21, 0); /* ETX3 */
+ at91_set_B_periph(AT91_PIN_PC24, 0); /* ETXER */
+ }
+
+ eth_data = *data;
+ platform_device_register(&at91sam9263_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc0_data, mmc1_data;
+
+static struct resource mmc0_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_MCI0,
+ .end = AT91SAM9263_BASE_MCI0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_MCI0,
+ .end = AT91SAM9263_ID_MCI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_mmc0_device = {
+ .name = "at91_mci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &mmc0_data,
+ },
+ .resource = mmc0_resources,
+ .num_resources = ARRAY_SIZE(mmc0_resources),
+};
+
+static struct resource mmc1_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_MCI1,
+ .end = AT91SAM9263_BASE_MCI1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_MCI1,
+ .end = AT91SAM9263_ID_MCI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_mmc1_device = {
+ .name = "at91_mci",
+ .id = 1,
+ .dev = {
+ .dma_mask = &mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &mmc1_data,
+ },
+ .resource = mmc1_resources,
+ .num_resources = ARRAY_SIZE(mmc1_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+ if (!data)
+ return;
+
+ /* input/irq */
+ if (data->det_pin) {
+ at91_set_gpio_input(data->det_pin, 1);
+ at91_set_deglitch(data->det_pin, 1);
+ }
+ if (data->wp_pin)
+ at91_set_gpio_input(data->wp_pin, 1);
+ if (data->vcc_pin)
+ at91_set_gpio_output(data->vcc_pin, 0);
+
+ if (mmc_id == 0) { /* MCI0 */
+ /* CLK */
+ at91_set_A_periph(AT91_PIN_PA12, 0);
+
+ if (data->slot_b) {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA16, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA17, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA18, 1);
+ at91_set_A_periph(AT91_PIN_PA19, 1);
+ at91_set_A_periph(AT91_PIN_PA20, 1);
+ }
+ } else {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA1, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA0, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA3, 1);
+ at91_set_A_periph(AT91_PIN_PA4, 1);
+ at91_set_A_periph(AT91_PIN_PA5, 1);
+ }
+ }
+
+ mmc0_data = *data;
+ at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+ platform_device_register(&at91sam9263_mmc0_device);
+ } else { /* MCI1 */
+ /* CLK */
+ at91_set_A_periph(AT91_PIN_PA6, 0);
+
+ if (data->slot_b) {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA21, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA22, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA23, 1);
+ at91_set_A_periph(AT91_PIN_PA24, 1);
+ at91_set_A_periph(AT91_PIN_PA25, 1);
+ }
+ } else {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA7, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA8, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA9, 1);
+ at91_set_A_periph(AT91_PIN_PA10, 1);
+ at91_set_A_periph(AT91_PIN_PA11, 1);
+ }
+ }
+
+ mmc1_data = *data;
+ at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+ platform_device_register(&at91sam9263_mmc1_device);
+ }
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+#define NAND_BASE AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+ {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91sam9263_nand_device = {
+ .name = "at91_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .resource = nand_resources,
+ .num_resources = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+ unsigned long csa, mode;
+
+ if (!data)
+ return;
+
+ csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
+ at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC);
+
+ /* set the bus interface characteristics */
+ at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+ | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+ at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3)
+ | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3));
+
+ at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5));
+
+ if (data->bus_width_16)
+ mode = AT91_SMC_DBW_16;
+ else
+ mode = AT91_SMC_DBW_8;
+ at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2));
+
+ /* enable pin */
+ if (data->enable_pin)
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (data->rdy_pin)
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (data->det_pin)
+ at91_set_gpio_input(data->det_pin, 1);
+
+ nand_data = *data;
+ platform_device_register(&at91sam9263_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_TWI,
+ .end = AT91SAM9263_BASE_TWI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_TWI,
+ .end = AT91SAM9263_ID_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_twi_device = {
+ .name = "at91_i2c",
+ .id = -1,
+ .resource = twi_resources,
+ .num_resources = ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+ /* pins used for TWI interface */
+ at91_set_A_periph(AT91_PIN_PB4, 0); /* TWD */
+ at91_set_multi_drive(AT91_PIN_PB4, 1);
+
+ at91_set_A_periph(AT91_PIN_PB5, 0); /* TWCK */
+ at91_set_multi_drive(AT91_PIN_PB5, 1);
+
+ platform_device_register(&at91sam9263_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_SPI0,
+ .end = AT91SAM9263_BASE_SPI0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_SPI0,
+ .end = AT91SAM9263_ID_SPI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_spi0_device = {
+ .name = "atmel_spi",
+ .id = 0,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi0_resources,
+ .num_resources = ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 };
+
+static struct resource spi1_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_SPI1,
+ .end = AT91SAM9263_BASE_SPI1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_SPI1,
+ .end = AT91SAM9263_ID_SPI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_spi1_device = {
+ .name = "atmel_spi",
+ .id = 1,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi1_resources,
+ .num_resources = ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+ int i;
+ unsigned long cs_pin;
+ short enable_spi0 = 0;
+ short enable_spi1 = 0;
+
+ /* Choose SPI chip-selects */
+ for (i = 0; i < nr_devices; i++) {
+ if (devices[i].controller_data)
+ cs_pin = (unsigned long) devices[i].controller_data;
+ else if (devices[i].bus_num == 0)
+ cs_pin = spi0_standard_cs[devices[i].chip_select];
+ else
+ cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+ if (devices[i].bus_num == 0)
+ enable_spi0 = 1;
+ else
+ enable_spi1 = 1;
+
+ /* enable chip-select pin */
+ at91_set_gpio_output(cs_pin, 1);
+
+ /* pass chip-select pin to driver */
+ devices[i].controller_data = (void *) cs_pin;
+ }
+
+ spi_register_board_info(devices, nr_devices);
+
+ /* Configure SPI bus(es) */
+ if (enable_spi0) {
+ at91_set_B_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */
+ at91_set_B_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */
+ at91_set_B_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */
+
+ at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk");
+ platform_device_register(&at91sam9263_spi0_device);
+ }
+ if (enable_spi1) {
+ at91_set_A_periph(AT91_PIN_PB12, 0); /* SPI1_MISO */
+ at91_set_A_periph(AT91_PIN_PB13, 0); /* SPI1_MOSI */
+ at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_SPCK */
+
+ at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk");
+ platform_device_register(&at91sam9263_spi1_device);
+ }
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+ /* Enable GPIO to access the LEDs */
+ at91_set_gpio_output(cpu_led, 1);
+ at91_set_gpio_output(timer_led, 1);
+
+ at91_leds_cpu = cpu_led;
+ at91_leds_timer = timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+
+static struct resource dbgu_resources[] = {
+ [0] = {
+ .start = AT91_VA_BASE_SYS + AT91_DBGU,
+ .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_SYS,
+ .end = AT91_ID_SYS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data dbgu_data = {
+ .use_dma_tx = 0,
+ .use_dma_rx = 0, /* DBGU not capable of receive DMA */
+ .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9263_dbgu_device = {
+ .name = "atmel_usart",
+ .id = 0,
+ .dev = {
+ .platform_data = &dbgu_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = dbgu_resources,
+ .num_resources = ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */
+ at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_US0,
+ .end = AT91SAM9263_BASE_US0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_US0,
+ .end = AT91SAM9263_ID_US0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart0_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9263_uart0_device = {
+ .name = "atmel_usart",
+ .id = 1,
+ .dev = {
+ .platform_data = &uart0_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart0_resources,
+ .num_resources = ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PA26, 1); /* TXD0 */
+ at91_set_A_periph(AT91_PIN_PA27, 0); /* RXD0 */
+ at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */
+ at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */
+}
+
+static struct resource uart1_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_US1,
+ .end = AT91SAM9263_BASE_US1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_US1,
+ .end = AT91SAM9263_ID_US1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart1_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9263_uart1_device = {
+ .name = "atmel_usart",
+ .id = 2,
+ .dev = {
+ .platform_data = &uart1_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart1_resources,
+ .num_resources = ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PD0, 1); /* TXD1 */
+ at91_set_A_periph(AT91_PIN_PD1, 0); /* RXD1 */
+ at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */
+ at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */
+}
+
+static struct resource uart2_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_US2,
+ .end = AT91SAM9263_BASE_US2 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_US2,
+ .end = AT91SAM9263_ID_US2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart2_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9263_uart2_device = {
+ .name = "atmel_usart",
+ .id = 3,
+ .dev = {
+ .platform_data = &uart2_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart2_resources,
+ .num_resources = ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PD2, 1); /* TXD2 */
+ at91_set_A_periph(AT91_PIN_PD3, 0); /* RXD2 */
+ at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */
+ at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+struct platform_device *atmel_default_console_device; /* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+ int i;
+
+ /* Fill in list of supported UARTs */
+ for (i = 0; i < config->nr_tty; i++) {
+ switch (config->tty_map[i]) {
+ case 0:
+ configure_usart0_pins();
+ at91_uarts[i] = &at91sam9263_uart0_device;
+ at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart");
+ break;
+ case 1:
+ configure_usart1_pins();
+ at91_uarts[i] = &at91sam9263_uart1_device;
+ at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart");
+ break;
+ case 2:
+ configure_usart2_pins();
+ at91_uarts[i] = &at91sam9263_uart2_device;
+ at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart");
+ break;
+ case 3:
+ configure_dbgu_pins();
+ at91_uarts[i] = &at91sam9263_dbgu_device;
+ at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart");
+ break;
+ default:
+ continue;
+ }
+ at91_uarts[i]->id = i; /* update ID number to mapped ID */
+ }
+
+ /* Set serial console device */
+ if (config->console_tty < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[config->console_tty];
+ if (!atmel_default_console_device)
+ printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+ int i;
+
+ for (i = 0; i < ATMEL_MAX_UART; i++) {
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+ return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
new file mode 100644
index 000000000000..a4dded27fa16
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/arm/mach-at91/at91sam926x_time.c
+ *
+ * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
+ * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/at91_pit.h>
+
+
+#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV)
+#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20)
+
+/*
+ * Returns number of microseconds since last timer interrupt. Note that interrupts
+ * will have been disabled by do_gettimeofday()
+ * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+ */
+static unsigned long at91sam926x_gettimeoffset(void)
+{
+ unsigned long elapsed;
+ unsigned long t = at91_sys_read(AT91_PIT_PIIR);
+
+ elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */
+
+ return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH;
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
+{
+ volatile long nr_ticks;
+
+ if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { /* This is a shared interrupt */
+ write_seqlock(&xtime_lock);
+
+ /* Get number to ticks performed before interrupt and clear PIT interrupt */
+ nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
+ do {
+ timer_tick();
+ nr_ticks--;
+ } while (nr_ticks);
+
+ write_sequnlock(&xtime_lock);
+ return IRQ_HANDLED;
+ } else
+ return IRQ_NONE; /* not handled */
+}
+
+static struct irqaction at91sam926x_timer_irq = {
+ .name = "at91_tick",
+ .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
+ .handler = at91sam926x_timer_interrupt
+};
+
+void at91sam926x_timer_reset(void)
+{
+ /* Disable timer */
+ at91_sys_write(AT91_PIT_MR, 0);
+
+ /* Clear any pending interrupts */
+ (void) at91_sys_read(AT91_PIT_PIVR);
+
+ /* Set Period Interval timer and enable its interrupt */
+ at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN);
+}
+
+/*
+ * Set up timer interrupt.
+ */
+void __init at91sam926x_timer_init(void)
+{
+ /* Initialize and enable the timer */
+ at91sam926x_timer_reset();
+
+ /* Make IRQs happen for the system timer. */
+ setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq);
+}
+
+#ifdef CONFIG_PM
+static void at91sam926x_timer_suspend(void)
+{
+ /* Disable timer */
+ at91_sys_write(AT91_PIT_MR, 0);
+}
+#else
+#define at91sam926x_timer_suspend NULL
+#endif
+
+struct sys_timer at91sam926x_timer = {
+ .init = at91sam926x_timer_init,
+ .offset = at91sam926x_gettimeoffset,
+ .suspend = at91sam926x_timer_suspend,
+ .resume = at91sam926x_timer_reset,
+};
+
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
new file mode 100644
index 000000000000..2d3d4b6f7b02
--- /dev/null
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-at91/board-1arm.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata onearm_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 3,
+ .tty_map = { 4, 0, 1, -1, -1 }, /* ttyS0, ..., ttyS4 */
+};
+
+static void __init onearm_map_io(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91rm9200_initialize(18432000, AT91RM9200_PQFP);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&onearm_uart_config);
+}
+
+static void __init onearm_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata onearm_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+static struct at91_usbh_data __initdata onearm_usbh_data = {
+ .ports = 1,
+};
+
+static struct at91_udc_data __initdata onearm_udc_data = {
+ .vbus_pin = AT91_PIN_PC2,
+ .pullup_pin = AT91_PIN_PC3,
+};
+
+static void __init onearm_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&onearm_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&onearm_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&onearm_udc_data);
+}
+
+MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
+ /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = onearm_map_io,
+ .init_irq = onearm_init_irq,
+ .init_machine = onearm_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
new file mode 100644
index 000000000000..b4518619063a
--- /dev/null
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-at91/board-carmeva.c
+ *
+ * Copyright (c) 2005 Peer Georgi
+ * Conitec Datasystems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata carmeva_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+};
+
+static void __init carmeva_map_io(void)
+{
+ /* Initialize processor: 20.000 MHz crystal */
+ at91rm9200_initialize(20000000, AT91RM9200_BGA);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&carmeva_uart_config);
+}
+
+static void __init carmeva_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata carmeva_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+static struct at91_usbh_data __initdata carmeva_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata carmeva_udc_data = {
+ .vbus_pin = AT91_PIN_PD12,
+ .pullup_pin = AT91_PIN_PD9,
+};
+
+/* FIXME: user dependend */
+// static struct at91_cf_data __initdata carmeva_cf_data = {
+// .det_pin = AT91_PIN_PB0,
+// .rst_pin = AT91_PIN_PC5,
+ // .irq_pin = ... not connected
+ // .vcc_pin = ... always powered
+// };
+
+static struct at91_mmc_data __initdata carmeva_mmc_data = {
+ .slot_b = 0,
+ .wire4 = 1,
+ .det_pin = AT91_PIN_PB10,
+ .wp_pin = AT91_PIN_PC14,
+};
+
+static struct spi_board_info carmeva_spi_devices[] = {
+ { /* DataFlash chip */
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 10 * 1000 * 1000,
+ },
+ { /* User accessable spi - cs1 (250KHz) */
+ .modalias = "spi-cs1",
+ .chip_select = 1,
+ .max_speed_hz = 250 * 1000,
+ },
+ { /* User accessable spi - cs2 (1MHz) */
+ .modalias = "spi-cs2",
+ .chip_select = 2,
+ .max_speed_hz = 1 * 1000 * 1000,
+ },
+ { /* User accessable spi - cs3 (10MHz) */
+ .modalias = "spi-cs3",
+ .chip_select = 3,
+ .max_speed_hz = 10 * 1000 * 1000,
+ },
+};
+
+static void __init carmeva_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&carmeva_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&carmeva_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&carmeva_udc_data);
+ /* I2C */
+ at91_add_device_i2c();
+ /* SPI */
+ at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices));
+ /* Compact Flash */
+// at91_add_device_cf(&carmeva_cf_data);
+ /* MMC */
+ at91_add_device_mmc(0, &carmeva_mmc_data);
+}
+
+MACHINE_START(CARMEVA, "Carmeva")
+ /* Maintainer: Conitec Datasystems */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = carmeva_map_io,
+ .init_irq = carmeva_init_irq,
+ .init_machine = carmeva_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
new file mode 100644
index 000000000000..e18a41e61f0c
--- /dev/null
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -0,0 +1,184 @@
+/*
+ * linux/arch/arm/mach-at91/board-csb337.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata csb337_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+};
+
+static void __init csb337_map_io(void)
+{
+ /* Initialize processor: 3.6864 MHz crystal */
+ at91rm9200_initialize(3686400, AT91RM9200_BGA);
+
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&csb337_uart_config);
+}
+
+static void __init csb337_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata csb337_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC2,
+ .is_rmii = 0,
+};
+
+static struct at91_usbh_data __initdata csb337_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata csb337_udc_data = {
+ // this has no VBUS sensing pin
+ .pullup_pin = AT91_PIN_PA24,
+};
+
+static struct at91_cf_data __initdata csb337_cf_data = {
+ /*
+ * connector P4 on the CSB 337 mates to
+ * connector P8 on the CSB 300CF
+ */
+
+ /* CSB337 specific */
+ .det_pin = AT91_PIN_PC3,
+
+ /* CSB300CF specific */
+ .irq_pin = AT91_PIN_PA19,
+ .vcc_pin = AT91_PIN_PD0,
+ .rst_pin = AT91_PIN_PD2,
+};
+
+static struct at91_mmc_data __initdata csb337_mmc_data = {
+ .det_pin = AT91_PIN_PD5,
+ .slot_b = 0,
+ .wire4 = 1,
+ .wp_pin = AT91_PIN_PD6,
+};
+
+static struct spi_board_info csb337_spi_devices[] = {
+ { /* CAN controller */
+ .modalias = "sak82c900",
+ .chip_select = 0,
+ .max_speed_hz = 6 * 1000 * 1000,
+ },
+};
+
+#define CSB_FLASH_BASE AT91_CHIPSELECT_0
+#define CSB_FLASH_SIZE 0x800000
+
+static struct mtd_partition csb_flash_partitions[] = {
+ {
+ .name = "uMON flash",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = MTD_WRITEABLE, /* read only */
+ }
+};
+
+static struct physmap_flash_data csb_flash_data = {
+ .width = 2,
+ .parts = csb_flash_partitions,
+ .nr_parts = ARRAY_SIZE(csb_flash_partitions),
+};
+
+static struct resource csb_flash_resources[] = {
+ {
+ .start = CSB_FLASH_BASE,
+ .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device csb_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &csb_flash_data,
+ },
+ .resource = csb_flash_resources,
+ .num_resources = ARRAY_SIZE(csb_flash_resources),
+};
+
+static void __init csb337_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&csb337_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&csb337_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&csb337_udc_data);
+ /* I2C */
+ at91_add_device_i2c();
+ /* Compact Flash */
+ at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */
+ at91_add_device_cf(&csb337_cf_data);
+ /* SPI */
+ at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
+ /* MMC */
+ at91_add_device_mmc(0, &csb337_mmc_data);
+ /* NOR flash */
+ platform_device_register(&csb_flash);
+}
+
+MACHINE_START(CSB337, "Cogent CSB337")
+ /* Maintainer: Bill Gatliff */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = csb337_map_io,
+ .init_irq = csb337_init_irq,
+ .init_machine = csb337_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
new file mode 100644
index 000000000000..77f04b935b3a
--- /dev/null
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -0,0 +1,148 @@
+/*
+ * linux/arch/arm/mach-at91/board-csb637.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata csb637_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+};
+
+static void __init csb637_map_io(void)
+{
+ /* Initialize processor: 3.6864 MHz crystal */
+ at91rm9200_initialize(3686400, AT91RM9200_BGA);
+
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&csb637_uart_config);
+}
+
+static void __init csb637_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata csb637_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC0,
+ .is_rmii = 0,
+};
+
+static struct at91_usbh_data __initdata csb637_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata csb637_udc_data = {
+ .vbus_pin = AT91_PIN_PB28,
+ .pullup_pin = AT91_PIN_PB1,
+};
+
+#define CSB_FLASH_BASE AT91_CHIPSELECT_0
+#define CSB_FLASH_SIZE 0x1000000
+
+static struct mtd_partition csb_flash_partitions[] = {
+ {
+ .name = "uMON flash",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = MTD_WRITEABLE, /* read only */
+ }
+};
+
+static struct physmap_flash_data csb_flash_data = {
+ .width = 2,
+ .parts = csb_flash_partitions,
+ .nr_parts = ARRAY_SIZE(csb_flash_partitions),
+};
+
+static struct resource csb_flash_resources[] = {
+ {
+ .start = CSB_FLASH_BASE,
+ .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device csb_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &csb_flash_data,
+ },
+ .resource = csb_flash_resources,
+ .num_resources = ARRAY_SIZE(csb_flash_resources),
+};
+
+static void __init csb637_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&csb637_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&csb637_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&csb637_udc_data);
+ /* I2C */
+ at91_add_device_i2c();
+ /* SPI */
+ at91_add_device_spi(NULL, 0);
+ /* NOR flash */
+ platform_device_register(&csb_flash);
+}
+
+MACHINE_START(CSB637, "Cogent CSB637")
+ /* Maintainer: Bill Gatliff */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = csb637_map_io,
+ .init_irq = csb637_init_irq,
+ .init_machine = csb637_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c
new file mode 100644
index 000000000000..6043c38c0a9e
--- /dev/null
+++ b/arch/arm/mach-at91/board-dk.c
@@ -0,0 +1,216 @@
+/*
+ * linux/arch/arm/mach-at91/board-dk.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * Epson S1D framebuffer glue code is:
+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata dk_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+};
+
+static void __init dk_map_io(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91rm9200_initialize(18432000, AT91RM9200_BGA);
+
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&dk_uart_config);
+}
+
+static void __init dk_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata dk_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+static struct at91_usbh_data __initdata dk_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata dk_udc_data = {
+ .vbus_pin = AT91_PIN_PD4,
+ .pullup_pin = AT91_PIN_PD5,
+};
+
+static struct at91_cf_data __initdata dk_cf_data = {
+ .det_pin = AT91_PIN_PB0,
+ .rst_pin = AT91_PIN_PC5,
+ // .irq_pin = ... not connected
+ // .vcc_pin = ... always powered
+};
+
+static struct at91_mmc_data __initdata dk_mmc_data = {
+ .slot_b = 0,
+ .wire4 = 1,
+};
+
+static struct spi_board_info dk_spi_devices[] = {
+ { /* DataFlash chip */
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 15 * 1000 * 1000,
+ },
+ { /* UR6HCPS2-SP40 PS2-to-SPI adapter */
+ .modalias = "ur6hcps2",
+ .chip_select = 1,
+ .max_speed_hz = 250 * 1000,
+ },
+ { /* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */
+ .modalias = "tlv1504",
+ .chip_select = 2,
+ .max_speed_hz = 20 * 1000 * 1000,
+ },
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ { /* DataFlash card */
+ .modalias = "mtd_dataflash",
+ .chip_select = 3,
+ .max_speed_hz = 15 * 1000 * 1000,
+ }
+#endif
+};
+
+static struct mtd_partition __initdata dk_nand_partition[] = {
+ {
+ .name = "NAND Partition 1",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+ *num_partitions = ARRAY_SIZE(dk_nand_partition);
+ return dk_nand_partition;
+}
+
+static struct at91_nand_data __initdata dk_nand_data = {
+ .ale = 22,
+ .cle = 21,
+ .det_pin = AT91_PIN_PB1,
+ .rdy_pin = AT91_PIN_PC2,
+ // .enable_pin = ... not there
+ .partition_info = nand_partitions,
+};
+
+#define DK_FLASH_BASE AT91_CHIPSELECT_0
+#define DK_FLASH_SIZE 0x200000
+
+static struct physmap_flash_data dk_flash_data = {
+ .width = 2,
+};
+
+static struct resource dk_flash_resource = {
+ .start = DK_FLASH_BASE,
+ .end = DK_FLASH_BASE + DK_FLASH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device dk_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &dk_flash_data,
+ },
+ .resource = &dk_flash_resource,
+ .num_resources = 1,
+};
+
+
+static void __init dk_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&dk_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&dk_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&dk_udc_data);
+ at91_set_multi_drive(dk_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */
+ /* Compact Flash */
+ at91_add_device_cf(&dk_cf_data);
+ /* I2C */
+ at91_add_device_i2c();
+ /* SPI */
+ at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices));
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ /* DataFlash card */
+ at91_set_gpio_output(AT91_PIN_PB7, 0);
+#else
+ /* MMC */
+ at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
+ at91_add_device_mmc(0, &dk_mmc_data);
+#endif
+ /* NAND */
+ at91_add_device_nand(&dk_nand_data);
+ /* NOR Flash */
+ platform_device_register(&dk_flash);
+ /* VGA */
+// dk_add_device_video();
+}
+
+MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
+ /* Maintainer: SAN People/Atmel */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = dk_map_io,
+ .init_irq = dk_init_irq,
+ .init_machine = dk_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
new file mode 100644
index 000000000000..20458b5548f0
--- /dev/null
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/arm/mach-at91/board-eb9200.c
+ *
+ * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
+ * by Andrew Patrikalakis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata eb9200_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+};
+
+static void __init eb9200_map_io(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91rm9200_initialize(18432000, AT91RM9200_BGA);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&eb9200_uart_config);
+}
+
+static void __init eb9200_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata eb9200_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+static struct at91_usbh_data __initdata eb9200_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata eb9200_udc_data = {
+ .vbus_pin = AT91_PIN_PD4,
+ .pullup_pin = AT91_PIN_PD5,
+};
+
+static struct at91_cf_data __initdata eb9200_cf_data = {
+ .det_pin = AT91_PIN_PB0,
+ .rst_pin = AT91_PIN_PC5,
+ // .irq_pin = ... not connected
+ // .vcc_pin = ... always powered
+};
+
+static struct at91_mmc_data __initdata eb9200_mmc_data = {
+ .slot_b = 0,
+ .wire4 = 1,
+};
+
+static void __init eb9200_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&eb9200_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&eb9200_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&eb9200_udc_data);
+ /* I2C */
+ at91_add_device_i2c();
+ /* Compact Flash */
+ at91_add_device_cf(&eb9200_cf_data);
+ /* SPI */
+ at91_add_device_spi(NULL, 0);
+ /* MMC */
+ /* only supports 1 or 4 bit interface, not wired through to SPI */
+ at91_add_device_mmc(0, &eb9200_mmc_data);
+}
+
+MACHINE_START(ATEB9200, "Embest ATEB9200")
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = eb9200_map_io,
+ .init_irq = eb9200_init_irq,
+ .init_machine = eb9200_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-ek.c b/arch/arm/mach-at91/board-ek.c
new file mode 100644
index 000000000000..322fdd75a1e4
--- /dev/null
+++ b/arch/arm/mach-at91/board-ek.c
@@ -0,0 +1,174 @@
+/*
+ * linux/arch/arm/mach-at91/board-ek.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * Epson S1D framebuffer glue code is:
+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+};
+
+static void __init ek_map_io(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91rm9200_initialize(18432000, AT91RM9200_BGA);
+
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata ek_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+static struct at91_usbh_data __initdata ek_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PD4,
+ .pullup_pin = AT91_PIN_PD5,
+};
+
+static struct at91_mmc_data __initdata ek_mmc_data = {
+ .det_pin = AT91_PIN_PB27,
+ .slot_b = 0,
+ .wire4 = 1,
+ .wp_pin = AT91_PIN_PA17,
+};
+
+static struct spi_board_info ek_spi_devices[] = {
+ { /* DataFlash chip */
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 15 * 1000 * 1000,
+ },
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ { /* DataFlash card */
+ .modalias = "mtd_dataflash",
+ .chip_select = 3,
+ .max_speed_hz = 15 * 1000 * 1000,
+ },
+#endif
+};
+
+#define EK_FLASH_BASE AT91_CHIPSELECT_0
+#define EK_FLASH_SIZE 0x200000
+
+static struct physmap_flash_data ek_flash_data = {
+ .width = 2,
+};
+
+static struct resource ek_flash_resource = {
+ .start = EK_FLASH_BASE,
+ .end = EK_FLASH_BASE + EK_FLASH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ek_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &ek_flash_data,
+ },
+ .resource = &ek_flash_resource,
+ .num_resources = 1,
+};
+
+
+static void __init ek_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&ek_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&ek_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&ek_udc_data);
+ at91_set_multi_drive(ek_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */
+ /* I2C */
+ at91_add_device_i2c();
+ /* SPI */
+ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ /* DataFlash card */
+ at91_set_gpio_output(AT91_PIN_PB22, 0);
+#else
+ /* MMC */
+ at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
+ at91_add_device_mmc(0, &ek_mmc_data);
+#endif
+ /* NOR Flash */
+ platform_device_register(&ek_flash);
+ /* VGA */
+// ek_add_device_video();
+}
+
+MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
+ /* Maintainer: SAN People/Atmel */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = ek_map_io,
+ .init_irq = ek_init_irq,
+ .init_machine = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
new file mode 100644
index 000000000000..c77d84ce9cae
--- /dev/null
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -0,0 +1,109 @@
+/*
+ * linux/arch/arm/mach-at91/board-kafa.c
+ *
+ * Copyright (C) 2006 Sperry-Sun
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata kafa_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 4, 0, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+};
+
+static void __init kafa_map_io(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91rm9200_initialize(18432000, AT91RM9200_PQFP);
+
+ /* Set up the LEDs */
+ at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&kafa_uart_config);
+}
+
+static void __init kafa_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata kafa_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 0,
+};
+
+static struct at91_usbh_data __initdata kafa_usbh_data = {
+ .ports = 1,
+};
+
+static struct at91_udc_data __initdata kafa_udc_data = {
+ .vbus_pin = AT91_PIN_PB6,
+ .pullup_pin = AT91_PIN_PB7,
+};
+
+static void __init kafa_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&kafa_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&kafa_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&kafa_udc_data);
+ /* I2C */
+ at91_add_device_i2c();
+ /* SPI */
+ at91_add_device_spi(NULL, 0);
+}
+
+MACHINE_START(KAFA, "Sperry-Sun KAFA")
+ /* Maintainer: Sergei Sharonov */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = kafa_map_io,
+ .init_irq = kafa_init_irq,
+ .init_machine = kafa_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
new file mode 100644
index 000000000000..76f6e1e553ea
--- /dev/null
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -0,0 +1,143 @@
+/*
+ * linux/arch/arm/mach-at91/board-kb9202.c
+ *
+ * Copyright (c) 2005 kb_admin
+ * KwikByte, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+static struct at91_uart_config __initdata kb9202_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 3,
+ .tty_map = { 4, 0, 1, -1, -1 } /* ttyS0, ..., ttyS4 */
+};
+
+static void __init kb9202_map_io(void)
+{
+ /* Initialize processor: 10 MHz crystal */
+ at91rm9200_initialize(10000000, AT91RM9200_PQFP);
+
+ /* Set up the LEDs */
+ at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&kb9202_uart_config);
+}
+
+static void __init kb9202_init_irq(void)
+{
+ at91rm9200_init_interrupts(NULL);
+}
+
+static struct at91_eth_data __initdata kb9202_eth_data = {
+ .phy_irq_pin = AT91_PIN_PB29,
+ .is_rmii = 0,
+};
+
+static struct at91_usbh_data __initdata kb9202_usbh_data = {
+ .ports = 1,
+};
+
+static struct at91_udc_data __initdata kb9202_udc_data = {
+ .vbus_pin = AT91_PIN_PB24,
+ .pullup_pin = AT91_PIN_PB22,
+};
+
+static struct at91_mmc_data __initdata kb9202_mmc_data = {
+ .det_pin = AT91_PIN_PB2,
+ .slot_b = 0,
+ .wire4 = 1,
+};
+
+static struct mtd_partition __initdata kb9202_nand_partition[] = {
+ {
+ .name = "nand_fs",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+ *num_partitions = ARRAY_SIZE(kb9202_nand_partition);
+ return kb9202_nand_partition;
+}
+
+static struct at91_nand_data __initdata kb9202_nand_data = {
+ .ale = 22,
+ .cle = 21,
+ // .det_pin = ... not there
+ .rdy_pin = AT91_PIN_PC29,
+ .enable_pin = AT91_PIN_PC28,
+ .partition_info = nand_partitions,
+};
+
+static void __init kb9202_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+ at91_add_device_eth(&kb9202_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&kb9202_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&kb9202_udc_data);
+ /* MMC */
+ at91_add_device_mmc(0, &kb9202_mmc_data);
+ /* I2C */
+ at91_add_device_i2c();
+ /* SPI */
+ at91_add_device_spi(NULL, 0);
+ /* NAND */
+ at91_add_device_nand(&kb9202_nand_data);
+}
+
+MACHINE_START(KB9200, "KB920x")
+ /* Maintainer: KwikByte, Inc. */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = kb9202_map_io,
+ .init_irq = kb9202_init_irq,
+ .init_machine = kb9202_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
new file mode 100644
index 000000000000..57fb4499d969
--- /dev/null
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -0,0 +1,202 @@
+/*
+ * linux/arch/arm/mach-at91/board-sam9260ek.c
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2006 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 5 = USART0 .. USART5
+ * 6 = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 3,
+ .tty_map = { 6, 0, 1, -1, -1, -1, -1 } /* ttyS0, ..., ttyS6 */
+};
+
+static void __init ek_map_io(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91sam9260_initialize(18432000);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+ at91sam9260_init_interrupts(NULL);
+}
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+ .ports = 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PC5,
+ .pullup_pin = 0, /* pull-up driven by UDC */
+};
+
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info ek_spi_devices[] = {
+#if !defined(CONFIG_MMC_AT91)
+ { /* DataFlash chip */
+ .modalias = "mtd_dataflash",
+ .chip_select = 1,
+ .max_speed_hz = 15 * 1000 * 1000,
+ .bus_num = 0,
+ },
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+ { /* DataFlash card */
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 15 * 1000 * 1000,
+ .bus_num = 0,
+ },
+#endif
+#endif
+#if defined(CONFIG_SND_AT73C213)
+ { /* AT73C213 DAC */
+ .modalias = "snd_at73c213",
+ .chip_select = 0,
+ .max_speed_hz = 10 * 1000 * 1000,
+ .bus_num = 1,
+ },
+#endif
+};
+
+
+/*
+ * MACB Ethernet device
+ */
+static struct __initdata at91_eth_data ek_macb_data = {
+ .phy_irq_pin = AT91_PIN_PA7,
+ .is_rmii = 1,
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+ {
+ .name = "Partition 1",
+ .offset = 0,
+ .size = 256 * 1024,
+ },
+ {
+ .name = "Partition 2",
+ .offset = 256 * 1024,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+ *num_partitions = ARRAY_SIZE(ek_nand_partition);
+ return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+ .ale = 21,
+ .cle = 22,
+// .det_pin = ... not connected
+ .rdy_pin = AT91_PIN_PC13,
+ .enable_pin = AT91_PIN_PC14,
+ .partition_info = nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+ .bus_width_16 = 1,
+#else
+ .bus_width_16 = 0,
+#endif
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+ .slot_b = 1,
+ .wire4 = 1,
+// .det_pin = ... not connected
+// .wp_pin = ... not connected
+// .vcc_pin = ... not connected
+};
+
+static void __init ek_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* USB Host */
+ at91_add_device_usbh(&ek_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&ek_udc_data);
+ /* SPI */
+ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+ /* NAND */
+ at91_add_device_nand(&ek_nand_data);
+ /* Ethernet */
+ at91_add_device_eth(&ek_macb_data);
+ /* MMC */
+ at91_add_device_mmc(0, &ek_mmc_data);
+}
+
+MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
+ /* Maintainer: Atmel */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91sam926x_timer,
+ .map_io = ek_map_io,
+ .init_irq = ek_init_irq,
+ .init_machine = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
new file mode 100644
index 000000000000..b7e772467cf6
--- /dev/null
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -0,0 +1,259 @@
+/*
+ * linux/arch/arm/mach-at91/board-sam9261ek.c
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2006 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/dm9000.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 2 = USART0 .. USART2
+ * 3 = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 1,
+ .tty_map = { 3, -1, -1, -1 } /* ttyS0, ..., ttyS3 */
+};
+
+static void __init ek_map_io(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91sam9261_initialize(18432000);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+ at91sam9261_init_interrupts(NULL);
+}
+
+
+/*
+ * DM9000 ethernet device
+ */
+#if defined(CONFIG_DM9000)
+static struct resource at91sam9261_dm9000_resource[] = {
+ [0] = {
+ .start = AT91_CHIPSELECT_2,
+ .end = AT91_CHIPSELECT_2 + 3,
+ .flags = IORESOURCE_MEM
+ },
+ [1] = {
+ .start = AT91_CHIPSELECT_2 + 0x44,
+ .end = AT91_CHIPSELECT_2 + 0xFF,
+ .flags = IORESOURCE_MEM
+ },
+ [2] = {
+ .start = AT91_PIN_PC11,
+ .end = AT91_PIN_PC11,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct dm9000_plat_data dm9000_platdata = {
+ .flags = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device at91sam9261_dm9000_device = {
+ .name = "dm9000",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(at91sam9261_dm9000_resource),
+ .resource = at91sam9261_dm9000_resource,
+ .dev = {
+ .platform_data = &dm9000_platdata,
+ }
+};
+
+static void __init ek_add_device_dm9000(void)
+{
+ /*
+ * Configure Chip-Select 2 on SMC for the DM9000.
+ * Note: These timings were calculated for MASTER_CLOCK = 100000000
+ * according to the DM9000 timings.
+ */
+ at91_sys_write(AT91_SMC_SETUP(2), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0));
+ at91_sys_write(AT91_SMC_PULSE(2), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(8) | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(8));
+ at91_sys_write(AT91_SMC_CYCLE(2), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16));
+ at91_sys_write(AT91_SMC_MODE(2), AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1));
+
+ /* Configure Reset signal as output */
+ at91_set_gpio_output(AT91_PIN_PC10, 0);
+
+ /* Configure Interrupt pin as input, no pull-up */
+ at91_set_gpio_input(AT91_PIN_PC11, 0);
+
+ platform_device_register(&at91sam9261_dm9000_device);
+}
+#else
+static void __init ek_add_device_dm9000(void) {}
+#endif /* CONFIG_DM9000 */
+
+
+/*
+ * USB Host Port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+ .ports = 2,
+};
+
+
+/*
+ * USB Device Port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PB29,
+ .pullup_pin = 0, /* pull-up driven by UDC */
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+ .wire4 = 1,
+// .det_pin = ... not connected
+// .wp_pin = ... not connected
+// .vcc_pin = ... not connected
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+ {
+ .name = "Partition 1",
+ .offset = 0,
+ .size = 256 * 1024,
+ },
+ {
+ .name = "Partition 2",
+ .offset = 256 * 1024 ,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+ *num_partitions = ARRAY_SIZE(ek_nand_partition);
+ return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+ .ale = 22,
+ .cle = 21,
+// .det_pin = ... not connected
+ .rdy_pin = AT91_PIN_PC15,
+ .enable_pin = AT91_PIN_PC14,
+ .partition_info = nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+ .bus_width_16 = 1,
+#else
+ .bus_width_16 = 0,
+#endif
+};
+
+/*
+ * SPI devices
+ */
+static struct spi_board_info ek_spi_devices[] = {
+ { /* DataFlash chip */
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 15 * 1000 * 1000,
+ .bus_num = 0,
+ },
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+ { /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */
+ .modalias = "mtd_dataflash",
+ .chip_select = 3,
+ .max_speed_hz = 15 * 1000 * 1000,
+ .bus_num = 0,
+ },
+#elif defined(CONFIG_SND_AT73C213)
+ { /* AT73C213 DAC */
+ .modalias = "snd_at73c213",
+ .chip_select = 3,
+ .max_speed_hz = 10 * 1000 * 1000,
+ .bus_num = 0,
+ },
+#endif
+};
+
+
+static void __init ek_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* USB Host */
+ at91_add_device_usbh(&ek_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&ek_udc_data);
+ /* I2C */
+ at91_add_device_i2c();
+ /* NAND */
+ at91_add_device_nand(&ek_nand_data);
+ /* DM9000 ethernet */
+ ek_add_device_dm9000();
+
+ /* spi0 and mmc/sd share the same PIO pins */
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+ /* SPI */
+ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+#else
+ /* MMC */
+ at91_add_device_mmc(0, &ek_mmc_data);
+#endif
+}
+
+MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
+ /* Maintainer: Atmel */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91sam926x_timer,
+ .map_io = ek_map_io,
+ .init_irq = ek_init_irq,
+ .init_machine = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
new file mode 100644
index 000000000000..8fdce11a880c
--- /dev/null
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -0,0 +1,176 @@
+/*
+ * linux/arch/arm/mach-at91/board-sam9263ek.c
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2007 Atmel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 2 = USART0 .. USART2
+ * 3 = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 3, 0, -1, -1, } /* ttyS0, ..., ttyS3 */
+};
+
+static void __init ek_map_io(void)
+{
+ /* Initialize processor: 16.367 MHz crystal */
+ at91sam9263_initialize(16367660);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+ at91sam9263_init_interrupts(NULL);
+}
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+ .ports = 2,
+ .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 },
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PA25,
+ .pullup_pin = 0, /* pull-up driven by UDC */
+};
+
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info ek_spi_devices[] = {
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+ { /* DataFlash card */
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 15 * 1000 * 1000,
+ .bus_num = 0,
+ },
+#endif
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+ .wire4 = 1,
+ .det_pin = AT91_PIN_PE18,
+ .wp_pin = AT91_PIN_PE19,
+// .vcc_pin = ... not connected
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+ {
+ .name = "Partition 1",
+ .offset = 0,
+ .size = 64 * 1024 * 1024,
+ },
+ {
+ .name = "Partition 2",
+ .offset = 64 * 1024 * 1024,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+ *num_partitions = ARRAY_SIZE(ek_nand_partition);
+ return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+ .ale = 21,
+ .cle = 22,
+// .det_pin = ... not connected
+ .rdy_pin = AT91_PIN_PA22,
+ .enable_pin = AT91_PIN_PD15,
+ .partition_info = nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+ .bus_width_16 = 1,
+#else
+ .bus_width_16 = 0,
+#endif
+};
+
+
+static void __init ek_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* USB Host */
+ at91_add_device_usbh(&ek_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&ek_udc_data);
+ /* SPI */
+ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+ /* MMC */
+ at91_add_device_mmc(1, &ek_mmc_data);
+ /* NAND */
+ at91_add_device_nand(&ek_nand_data);
+}
+
+MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
+ /* Maintainer: Atmel */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91sam926x_timer,
+ .map_io = ek_map_io,
+ .init_irq = ek_init_irq,
+ .init_machine = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
new file mode 100644
index 000000000000..06c9a0507d0d
--- /dev/null
+++ b/arch/arm/mach-at91/clock.c
@@ -0,0 +1,640 @@
+/*
+ * linux/arch/arm/mach-at91/clock.c
+ *
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/cpu.h>
+
+#include "clock.h"
+
+
+/*
+ * There's a lot more which can be done with clocks, including cpufreq
+ * integration, slow clock mode support (for system suspend), letting
+ * PLLB be used at other rates (on boards that don't need USB), etc.
+ */
+
+#define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY)
+#define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE)
+#define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL)
+#define clk_is_sys(x) ((x)->type & CLK_TYPE_SYSTEM)
+
+
+static LIST_HEAD(clocks);
+static DEFINE_SPINLOCK(clk_lock);
+
+static u32 at91_pllb_usb_init;
+
+/*
+ * Four primary clock sources: two crystal oscillators (32K, main), and
+ * two PLLs. PLLA usually runs the master clock; and PLLB must run at
+ * 48 MHz (unless no USB function clocks are needed). The main clock and
+ * both PLLs are turned off to run in "slow clock mode" (system suspend).
+ */
+static struct clk clk32k = {
+ .name = "clk32k",
+ .rate_hz = AT91_SLOW_CLOCK,
+ .users = 1, /* always on */
+ .id = 0,
+ .type = CLK_TYPE_PRIMARY,
+};
+static struct clk main_clk = {
+ .name = "main",
+ .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */
+ .id = 1,
+ .type = CLK_TYPE_PRIMARY,
+};
+static struct clk plla = {
+ .name = "plla",
+ .parent = &main_clk,
+ .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */
+ .id = 2,
+ .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
+};
+
+static void pllb_mode(struct clk *clk, int is_on)
+{
+ u32 value;
+
+ if (is_on) {
+ is_on = AT91_PMC_LOCKB;
+ value = at91_pllb_usb_init;
+ } else
+ value = 0;
+
+ // REVISIT: Add work-around for AT91RM9200 Errata #26 ?
+ at91_sys_write(AT91_CKGR_PLLBR, value);
+
+ do {
+ cpu_relax();
+ } while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on);
+}
+
+static struct clk pllb = {
+ .name = "pllb",
+ .parent = &main_clk,
+ .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */
+ .mode = pllb_mode,
+ .id = 3,
+ .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
+};
+
+static void pmc_sys_mode(struct clk *clk, int is_on)
+{
+ if (is_on)
+ at91_sys_write(AT91_PMC_SCER, clk->pmc_mask);
+ else
+ at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
+}
+
+/* USB function clocks (PLLB must be 48 MHz) */
+static struct clk udpck = {
+ .name = "udpck",
+ .parent = &pllb,
+ .mode = pmc_sys_mode,
+};
+static struct clk uhpck = {
+ .name = "uhpck",
+ .parent = &pllb,
+ .mode = pmc_sys_mode,
+};
+
+
+/*
+ * The master clock is divided from the CPU clock (by 1-4). It's used for
+ * memory, interfaces to on-chip peripherals, the AIC, and sometimes more
+ * (e.g baud rate generation). It's sourced from one of the primary clocks.
+ */
+static struct clk mck = {
+ .name = "mck",
+ .pmc_mask = AT91_PMC_MCKRDY, /* in PMC_SR */
+};
+
+static void pmc_periph_mode(struct clk *clk, int is_on)
+{
+ if (is_on)
+ at91_sys_write(AT91_PMC_PCER, clk->pmc_mask);
+ else
+ at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
+}
+
+static struct clk __init *at91_css_to_clk(unsigned long css)
+{
+ switch (css) {
+ case AT91_PMC_CSS_SLOW:
+ return &clk32k;
+ case AT91_PMC_CSS_MAIN:
+ return &main_clk;
+ case AT91_PMC_CSS_PLLA:
+ return &plla;
+ case AT91_PMC_CSS_PLLB:
+ return &pllb;
+ }
+
+ return NULL;
+}
+
+/*
+ * Associate a particular clock with a function (eg, "uart") and device.
+ * The drivers can then request the same 'function' with several different
+ * devices and not care about which clock name to use.
+ */
+void __init at91_clock_associate(const char *id, struct device *dev, const char *func)
+{
+ struct clk *clk = clk_get(NULL, id);
+
+ if (!dev || !clk || !IS_ERR(clk_get(dev, func)))
+ return;
+
+ clk->function = func;
+ clk->dev = dev;
+}
+
+/* clocks cannot be de-registered no refcounting necessary */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ struct clk *clk;
+
+ list_for_each_entry(clk, &clocks, node) {
+ if (strcmp(id, clk->name) == 0)
+ return clk;
+ if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
+ return clk;
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+static void __clk_enable(struct clk *clk)
+{
+ if (clk->parent)
+ __clk_enable(clk->parent);
+ if (clk->users++ == 0 && clk->mode)
+ clk->mode(clk, 1);
+}
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+
+ 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)
+{
+ BUG_ON(clk->users == 0);
+ if (--clk->users == 0 && clk->mode)
+ clk->mode(clk, 0);
+ if (clk->parent)
+ __clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long flags;
+ unsigned long rate;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ for (;;) {
+ rate = clk->rate_hz;
+ if (rate || !clk->parent)
+ break;
+ clk = clk->parent;
+ }
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+/*------------------------------------------------------------------------*/
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+
+/*
+ * For now, only the programmable clocks support reparenting (MCK could
+ * do this too, with care) or rate changing (the PLLs could do this too,
+ * ditto MCK but that's more for cpufreq). Drivers may reparent to get
+ * a better rate match; we don't.
+ */
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ unsigned prescale;
+ unsigned long actual;
+
+ if (!clk_is_programmable(clk))
+ return -EINVAL;
+ spin_lock_irqsave(&clk_lock, flags);
+
+ actual = clk->parent->rate_hz;
+ for (prescale = 0; prescale < 7; prescale++) {
+ if (actual && actual <= rate)
+ break;
+ actual >>= 1;
+ }
+
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return (prescale < 7) ? actual : -ENOENT;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ unsigned prescale;
+ unsigned long actual;
+
+ if (!clk_is_programmable(clk))
+ return -EINVAL;
+ if (clk->users)
+ return -EBUSY;
+ spin_lock_irqsave(&clk_lock, flags);
+
+ actual = clk->parent->rate_hz;
+ for (prescale = 0; prescale < 7; prescale++) {
+ if (actual && actual <= rate) {
+ u32 pckr;
+
+ pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+ pckr &= AT91_PMC_CSS_PLLB; /* clock selection */
+ pckr |= prescale << 2;
+ at91_sys_write(AT91_PMC_PCKR(clk->id), pckr);
+ clk->rate_hz = actual;
+ break;
+ }
+ actual >>= 1;
+ }
+
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return (prescale < 7) ? actual : -ENOENT;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long flags;
+
+ if (clk->users)
+ return -EBUSY;
+ if (!clk_is_primary(parent) || !clk_is_programmable(clk))
+ return -EINVAL;
+ spin_lock_irqsave(&clk_lock, flags);
+
+ clk->rate_hz = parent->rate_hz;
+ clk->parent = parent;
+ at91_sys_write(AT91_PMC_PCKR(clk->id), parent->id);
+
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+/* establish PCK0..PCK3 parentage and rate */
+static void init_programmable_clock(struct clk *clk)
+{
+ struct clk *parent;
+ u32 pckr;
+
+ pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+ parent = at91_css_to_clk(pckr & AT91_PMC_CSS);
+ clk->parent = parent;
+ clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
+}
+
+#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
+
+/*------------------------------------------------------------------------*/
+
+#ifdef CONFIG_DEBUG_FS
+
+static int at91_clk_show(struct seq_file *s, void *unused)
+{
+ u32 scsr, pcsr, sr;
+ struct clk *clk;
+ unsigned i;
+
+ seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
+ seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR));
+
+ seq_printf(s, "MOR = %8x\n", at91_sys_read(AT91_CKGR_MOR));
+ seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
+ seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
+ seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
+
+ seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
+ for (i = 0; i < 4; i++)
+ seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i)));
+ seq_printf(s, "SR = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
+
+ seq_printf(s, "\n");
+
+ list_for_each_entry(clk, &clocks, node) {
+ char *state;
+
+ if (clk->mode == pmc_sys_mode)
+ state = (scsr & clk->pmc_mask) ? "on" : "off";
+ else if (clk->mode == pmc_periph_mode)
+ state = (pcsr & clk->pmc_mask) ? "on" : "off";
+ else if (clk->pmc_mask)
+ state = (sr & clk->pmc_mask) ? "on" : "off";
+ else if (clk == &clk32k || clk == &main_clk)
+ state = "on";
+ else
+ state = "";
+
+ seq_printf(s, "%-10s users=%2d %-3s %9ld Hz %s\n",
+ clk->name, clk->users, state, clk_get_rate(clk),
+ clk->parent ? clk->parent->name : "");
+ }
+ return 0;
+}
+
+static int at91_clk_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, at91_clk_show, NULL);
+}
+
+static const struct file_operations at91_clk_operations = {
+ .open = at91_clk_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init at91_clk_debugfs_init(void)
+{
+ /* /sys/kernel/debug/at91_clk */
+ (void) debugfs_create_file("at91_clk", S_IFREG | S_IRUGO, NULL, NULL, &at91_clk_operations);
+
+ return 0;
+}
+postcore_initcall(at91_clk_debugfs_init);
+
+#endif
+
+/*------------------------------------------------------------------------*/
+
+/* Register a new clock */
+int __init clk_register(struct clk *clk)
+{
+ if (clk_is_peripheral(clk)) {
+ clk->parent = &mck;
+ clk->mode = pmc_periph_mode;
+ list_add_tail(&clk->node, &clocks);
+ }
+ else if (clk_is_sys(clk)) {
+ clk->parent = &mck;
+ clk->mode = pmc_sys_mode;
+
+ list_add_tail(&clk->node, &clocks);
+ }
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+ else if (clk_is_programmable(clk)) {
+ clk->mode = pmc_sys_mode;
+ init_programmable_clock(clk);
+ list_add_tail(&clk->node, &clocks);
+ }
+#endif
+
+ return 0;
+}
+
+
+/*------------------------------------------------------------------------*/
+
+static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
+{
+ unsigned mul, div;
+
+ div = reg & 0xff;
+ mul = (reg >> 16) & 0x7ff;
+ if (div && mul) {
+ freq /= div;
+ freq *= mul + 1;
+ } else
+ freq = 0;
+
+ return freq;
+}
+
+static u32 __init at91_usb_rate(struct clk *pll, u32 freq, u32 reg)
+{
+ if (pll == &pllb && (reg & AT91_PMC_USB96M))
+ return freq / 2;
+ else
+ return freq;
+}
+
+static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq)
+{
+ unsigned i, div = 0, mul = 0, diff = 1 << 30;
+ unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
+
+ /* PLL output max 240 MHz (or 180 MHz per errata) */
+ if (out_freq > 240000000)
+ goto fail;
+
+ for (i = 1; i < 256; i++) {
+ int diff1;
+ unsigned input, mul1;
+
+ /*
+ * PLL input between 1MHz and 32MHz per spec, but lower
+ * frequences seem necessary in some cases so allow 100K.
+ */
+ input = main_freq / i;
+ if (input < 100000)
+ continue;
+ if (input > 32000000)
+ continue;
+
+ mul1 = out_freq / input;
+ if (mul1 > 2048)
+ continue;
+ if (mul1 < 2)
+ goto fail;
+
+ diff1 = out_freq - input * mul1;
+ if (diff1 < 0)
+ diff1 = -diff1;
+ if (diff > diff1) {
+ diff = diff1;
+ div = i;
+ mul = mul1;
+ if (diff == 0)
+ break;
+ }
+ }
+ if (i == 256 && diff > (out_freq >> 5))
+ goto fail;
+ return ret | ((mul - 1) << 16) | div;
+fail:
+ return 0;
+}
+
+static struct clk *const standard_pmc_clocks[] __initdata = {
+ /* four primary clocks */
+ &clk32k,
+ &main_clk,
+ &plla,
+ &pllb,
+
+ /* PLLB children (USB) */
+ &udpck,
+ &uhpck,
+
+ /* MCK */
+ &mck
+};
+
+int __init at91_clock_init(unsigned long main_clock)
+{
+ unsigned tmp, freq, mckr;
+ int i;
+
+ /*
+ * When the bootloader initialized the main oscillator correctly,
+ * there's no problem using the cycle counter. But if it didn't,
+ * or when using oscillator bypass mode, we must be told the speed
+ * of the main clock.
+ */
+ if (!main_clock) {
+ do {
+ tmp = at91_sys_read(AT91_CKGR_MCFR);
+ } while (!(tmp & AT91_PMC_MAINRDY));
+ main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16);
+ }
+ main_clk.rate_hz = main_clock;
+
+ /* report if PLLA is more than mildly overclocked */
+ plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
+ if (plla.rate_hz > 209000000)
+ pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
+
+ /*
+ * USB clock init: choose 48 MHz PLLB value,
+ * disable 48MHz clock during usb peripheral suspend.
+ *
+ * REVISIT: assumes MCK doesn't derive from PLLB!
+ */
+ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
+ pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
+ if (cpu_is_at91rm9200()) {
+ uhpck.pmc_mask = AT91RM9200_PMC_UHP;
+ udpck.pmc_mask = AT91RM9200_PMC_UDP;
+ at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
+ } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
+ uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
+ udpck.pmc_mask = AT91SAM926x_PMC_UDP;
+ }
+ at91_sys_write(AT91_CKGR_PLLBR, 0);
+
+ udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+ uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+
+ /*
+ * MCK and CPU derive from one of those primary clocks.
+ * For now, assume this parentage won't change.
+ */
+ mckr = at91_sys_read(AT91_PMC_MCKR);
+ mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
+ freq = mck.parent->rate_hz;
+ freq /= (1 << ((mckr >> 2) & 3)); /* prescale */
+ mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */
+
+ /* Register the PMC's standard clocks */
+ for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
+ list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
+
+ /* MCK and CPU clock are "always on" */
+ clk_enable(&mck);
+
+ printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
+ freq / 1000000, (unsigned) mck.rate_hz / 1000000,
+ (unsigned) main_clock / 1000000,
+ ((unsigned) main_clock % 1000000) / 1000);
+
+ return 0;
+}
+
+/*
+ * Several unused clocks may be active. Turn them off.
+ */
+static int __init at91_clock_reset(void)
+{
+ unsigned long pcdr = 0;
+ unsigned long scdr = 0;
+ struct clk *clk;
+
+ list_for_each_entry(clk, &clocks, node) {
+ if (clk->users > 0)
+ continue;
+
+ if (clk->mode == pmc_periph_mode)
+ pcdr |= clk->pmc_mask;
+
+ if (clk->mode == pmc_sys_mode)
+ scdr |= clk->pmc_mask;
+
+ pr_debug("Clocks: disable unused %s\n", clk->name);
+ }
+
+ at91_sys_write(AT91_PMC_PCDR, pcdr);
+ at91_sys_write(AT91_PMC_SCDR, scdr);
+
+ return 0;
+}
+late_initcall(at91_clock_reset);
diff --git a/arch/arm/mach-at91/clock.h b/arch/arm/mach-at91/clock.h
new file mode 100644
index 000000000000..1ba3b95ff359
--- /dev/null
+++ b/arch/arm/mach-at91/clock.h
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/arm/mach-at91/clock.h
+ *
+ * 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.
+ */
+
+#define CLK_TYPE_PRIMARY 0x1
+#define CLK_TYPE_PLL 0x2
+#define CLK_TYPE_PROGRAMMABLE 0x4
+#define CLK_TYPE_PERIPHERAL 0x8
+#define CLK_TYPE_SYSTEM 0x10
+
+
+struct clk {
+ struct list_head node;
+ const char *name; /* unique clock name */
+ const char *function; /* function of the clock */
+ struct device *dev; /* device associated with function */
+ unsigned long rate_hz;
+ struct clk *parent;
+ u32 pmc_mask;
+ void (*mode)(struct clk *, int);
+ unsigned id:2; /* PCK0..3, or 32k/main/a/b */
+ unsigned type; /* clock type */
+ u16 users;
+};
+
+
+extern int __init clk_register(struct clk *clk);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
new file mode 100644
index 000000000000..bda26221c522
--- /dev/null
+++ b/arch/arm/mach-at91/generic.h
@@ -0,0 +1,51 @@
+/*
+ * linux/arch/arm/mach-at91/generic.h
+ *
+ * Copyright (C) 2005 David Brownell
+ *
+ * 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.
+ */
+
+ /* Processors */
+extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
+extern void __init at91sam9260_initialize(unsigned long main_clock);
+extern void __init at91sam9261_initialize(unsigned long main_clock);
+extern void __init at91sam9263_initialize(unsigned long main_clock);
+
+ /* Interrupts */
+extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9263_init_interrupts(unsigned int priority[]);
+extern void __init at91_aic_init(unsigned int priority[]);
+
+ /* Timer */
+struct sys_timer;
+extern struct sys_timer at91rm9200_timer;
+extern struct sys_timer at91sam926x_timer;
+
+ /* Clocks */
+extern int __init at91_clock_init(unsigned long main_clock);
+struct device;
+extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func);
+
+ /* Power Management */
+extern void at91_irq_suspend(void);
+extern void at91_irq_resume(void);
+
+ /* GPIO */
+#define AT91RM9200_PQFP 3 /* AT91RM9200 PQFP package has 3 banks */
+#define AT91RM9200_BGA 4 /* AT91RM9200 BGA package has 4 banks */
+
+struct at91_gpio_bank {
+ unsigned short id; /* peripheral ID */
+ unsigned long offset; /* offset from system peripheral base */
+ struct clk *clock; /* associated clock */
+};
+extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
+extern void __init at91_gpio_irq_setup(void);
+
+extern void (*at91_arch_reset)(void);
+extern int at91_extern_irq;
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
new file mode 100644
index 000000000000..7b87f3f101b7
--- /dev/null
+++ b/arch/arm/mach-at91/gpio.c
@@ -0,0 +1,462 @@
+/*
+ * linux/arch/arm/mach-at91/gpio.c
+ *
+ * Copyright (C) 2005 HP Labs
+ *
+ * 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/clk.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+static struct at91_gpio_bank *gpio;
+static int gpio_banks;
+
+
+static inline void __iomem *pin_to_controller(unsigned pin)
+{
+ void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS;
+
+ pin -= PIN_BASE;
+ pin /= 32;
+ if (likely(pin < gpio_banks))
+ return sys_base + gpio[pin].offset;
+
+ return NULL;
+}
+
+static inline unsigned pin_to_mask(unsigned pin)
+{
+ pin -= PIN_BASE;
+ return 1 << (pin % 32);
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+/* Not all hardware capabilities are exposed through these calls; they
+ * only encapsulate the most common features and modes. (So if you
+ * want to change signals in groups, do it directly.)
+ *
+ * Bootloaders will usually handle some of the pin multiplexing setup.
+ * The intent is certainly that by the time Linux is fully booted, all
+ * pins should have been fully initialized. These setup calls should
+ * only be used by board setup routines, or possibly in driver probe().
+ *
+ * For bootloaders doing all that setup, these calls could be inlined
+ * as NOPs so Linux won't duplicate any setup code
+ */
+
+
+/*
+ * mux the pin to the "GPIO" peripheral role.
+ */
+int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+ __raw_writel(mask, pio + PIO_PER);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_GPIO_periph);
+
+
+/*
+ * mux the pin to the "A" internal peripheral role.
+ */
+int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+ __raw_writel(mask, pio + PIO_ASR);
+ __raw_writel(mask, pio + PIO_PDR);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_A_periph);
+
+
+/*
+ * mux the pin to the "B" internal peripheral role.
+ */
+int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+ __raw_writel(mask, pio + PIO_BSR);
+ __raw_writel(mask, pio + PIO_PDR);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_B_periph);
+
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
+ * configure it for an input.
+ */
+int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+ __raw_writel(mask, pio + PIO_ODR);
+ __raw_writel(mask, pio + PIO_PER);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_input);
+
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
+ * and configure it for an output.
+ */
+int __init_or_module at91_set_gpio_output(unsigned pin, int value)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + PIO_PUDR);
+ __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
+ __raw_writel(mask, pio + PIO_OER);
+ __raw_writel(mask, pio + PIO_PER);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_output);
+
+
+/*
+ * enable/disable the glitch filter; mostly used with IRQ handling.
+ */
+int __init_or_module at91_set_deglitch(unsigned pin, int is_on)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+ __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_deglitch);
+
+/*
+ * enable/disable the multi-driver; This is only valid for output and
+ * allows the output pin to run as an open collector output.
+ */
+int __init_or_module at91_set_multi_drive(unsigned pin, int is_on)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + (is_on ? PIO_MDER : PIO_MDDR));
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_multi_drive);
+
+/*--------------------------------------------------------------------------*/
+
+/* new-style GPIO calls; these expect at91_set_GPIO_periph to have been
+ * called, and maybe at91_set_multi_drive() for putout pins.
+ */
+
+int gpio_direction_input(unsigned pin)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
+ return -EINVAL;
+ __raw_writel(mask, pio + PIO_OER);
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned pin)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
+ return -EINVAL;
+ __raw_writel(mask, pio + PIO_OER);
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * assuming the pin is muxed as a gpio output, set its value.
+ */
+int at91_set_gpio_value(unsigned pin, int value)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+ __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_value);
+
+
+/*
+ * read the pin's value (works even if it's not muxed as a gpio).
+ */
+int at91_get_gpio_value(unsigned pin)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+ u32 pdsr;
+
+ if (!pio)
+ return -EINVAL;
+ pdsr = __raw_readl(pio + PIO_PDSR);
+ return (pdsr & mask) != 0;
+}
+EXPORT_SYMBOL(at91_get_gpio_value);
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+static u32 wakeups[MAX_GPIO_BANKS];
+static u32 backups[MAX_GPIO_BANKS];
+
+static int gpio_irq_set_wake(unsigned pin, unsigned state)
+{
+ unsigned mask = pin_to_mask(pin);
+ unsigned bank = (pin - PIN_BASE) / 32;
+
+ if (unlikely(bank >= MAX_GPIO_BANKS))
+ return -EINVAL;
+
+ if (state)
+ wakeups[bank] |= mask;
+ else
+ wakeups[bank] &= ~mask;
+
+ set_irq_wake(gpio[bank].id, state);
+
+ return 0;
+}
+
+void at91_gpio_suspend(void)
+{
+ int i;
+
+ for (i = 0; i < gpio_banks; i++) {
+ u32 pio = gpio[i].offset;
+
+ backups[i] = at91_sys_read(pio + PIO_IMR);
+ at91_sys_write(pio + PIO_IDR, backups[i]);
+ at91_sys_write(pio + PIO_IER, wakeups[i]);
+
+ if (!wakeups[i])
+ clk_disable(gpio[i].clock);
+ else {
+#ifdef CONFIG_PM_DEBUG
+ printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]);
+#endif
+ }
+ }
+}
+
+void at91_gpio_resume(void)
+{
+ int i;
+
+ for (i = 0; i < gpio_banks; i++) {
+ u32 pio = gpio[i].offset;
+
+ if (!wakeups[i])
+ clk_enable(gpio[i].clock);
+
+ at91_sys_write(pio + PIO_IDR, wakeups[i]);
+ at91_sys_write(pio + PIO_IER, backups[i]);
+ }
+}
+
+#else
+#define gpio_irq_set_wake NULL
+#endif
+
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * at91_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler, though it always triggers on rising and falling edges.
+ *
+ * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
+ * configuring them with at91_set_a_periph() or at91_set_b_periph().
+ * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
+ */
+
+static void gpio_irq_mask(unsigned pin)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (pio)
+ __raw_writel(mask, pio + PIO_IDR);
+}
+
+static void gpio_irq_unmask(unsigned pin)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (pio)
+ __raw_writel(mask, pio + PIO_IER);
+}
+
+static int gpio_irq_type(unsigned pin, unsigned type)
+{
+ return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
+}
+
+static struct irq_chip gpio_irqchip = {
+ .name = "GPIO",
+ .mask = gpio_irq_mask,
+ .unmask = gpio_irq_unmask,
+ .set_type = gpio_irq_type,
+ .set_wake = gpio_irq_set_wake,
+};
+
+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ unsigned pin;
+ struct irq_desc *gpio;
+ void __iomem *pio;
+ u32 isr;
+
+ pio = get_irq_chip_data(irq);
+
+ /* temporarily mask (level sensitive) parent IRQ */
+ desc->chip->ack(irq);
+ for (;;) {
+ /* reading ISR acks the pending (edge triggered) GPIO interrupt */
+ isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
+ if (!isr)
+ break;
+
+ pin = (unsigned) get_irq_data(irq);
+ gpio = &irq_desc[pin];
+
+ while (isr) {
+ if (isr & 1) {
+ if (unlikely(gpio->depth)) {
+ /*
+ * The core ARM interrupt handler lazily disables IRQs so
+ * another IRQ must be generated before it actually gets
+ * here to be disabled on the GPIO controller.
+ */
+ gpio_irq_mask(pin);
+ }
+ else
+ desc_handle_irq(pin, gpio);
+ }
+ pin++;
+ gpio++;
+ isr >>= 1;
+ }
+ }
+ desc->chip->unmask(irq);
+ /* now it may re-trigger */
+}
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Called from the processor-specific init to enable GPIO interrupt support.
+ */
+void __init at91_gpio_irq_setup(void)
+{
+ unsigned pioc, pin;
+
+ for (pioc = 0, pin = PIN_BASE;
+ pioc < gpio_banks;
+ pioc++) {
+ void __iomem *controller;
+ unsigned id = gpio[pioc].id;
+ unsigned i;
+
+ clk_enable(gpio[pioc].clock); /* enable PIO controller's clock */
+
+ controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
+ __raw_writel(~0, controller + PIO_IDR);
+
+ set_irq_data(id, (void *) pin);
+ set_irq_chip_data(id, controller);
+
+ for (i = 0; i < 32; i++, pin++) {
+ /*
+ * Can use the "simple" and not "edge" handler since it's
+ * shorter, and the AIC handles interupts sanely.
+ */
+ set_irq_chip(pin, &gpio_irqchip);
+ set_irq_handler(pin, handle_simple_irq);
+ set_irq_flags(pin, IRQF_VALID);
+ }
+
+ set_irq_chained_handler(id, gpio_irq_handler);
+ }
+ pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
+}
+
+/*
+ * Called from the processor-specific init to enable GPIO pin support.
+ */
+void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
+{
+ BUG_ON(nr_banks > MAX_GPIO_BANKS);
+
+ gpio = data;
+ gpio_banks = nr_banks;
+}
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
new file mode 100644
index 000000000000..78a5cdb746dc
--- /dev/null
+++ b/arch/arm/mach-at91/irq.c
@@ -0,0 +1,168 @@
+/*
+ * linux/arch/arm/mach-at91/irq.c
+ *
+ * Copyright (C) 2004 SAN People
+ * Copyright (C) 2004 ATMEL
+ * Copyright (C) Rick Bronson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+
+static void at91_aic_mask_irq(unsigned int irq)
+{
+ /* Disable interrupt on AIC */
+ at91_sys_write(AT91_AIC_IDCR, 1 << irq);
+}
+
+static void at91_aic_unmask_irq(unsigned int irq)
+{
+ /* Enable interrupt on AIC */
+ at91_sys_write(AT91_AIC_IECR, 1 << irq);
+}
+
+unsigned int at91_extern_irq;
+
+#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq)
+
+static int at91_aic_set_type(unsigned irq, unsigned type)
+{
+ unsigned int smr, srctype;
+
+ switch (type) {
+ case IRQT_HIGH:
+ srctype = AT91_AIC_SRCTYPE_HIGH;
+ break;
+ case IRQT_RISING:
+ srctype = AT91_AIC_SRCTYPE_RISING;
+ break;
+ case IRQT_LOW:
+ if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */
+ srctype = AT91_AIC_SRCTYPE_LOW;
+ else
+ return -EINVAL;
+ break;
+ case IRQT_FALLING:
+ if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */
+ srctype = AT91_AIC_SRCTYPE_FALLING;
+ else
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ smr = at91_sys_read(AT91_AIC_SMR(irq)) & ~AT91_AIC_SRCTYPE;
+ at91_sys_write(AT91_AIC_SMR(irq), smr | srctype);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static u32 wakeups;
+static u32 backups;
+
+static int at91_aic_set_wake(unsigned irq, unsigned value)
+{
+ if (unlikely(irq >= 32))
+ return -EINVAL;
+
+ if (value)
+ wakeups |= (1 << irq);
+ else
+ wakeups &= ~(1 << irq);
+
+ return 0;
+}
+
+void at91_irq_suspend(void)
+{
+ backups = at91_sys_read(AT91_AIC_IMR);
+ at91_sys_write(AT91_AIC_IDCR, backups);
+ at91_sys_write(AT91_AIC_IECR, wakeups);
+}
+
+void at91_irq_resume(void)
+{
+ at91_sys_write(AT91_AIC_IDCR, wakeups);
+ at91_sys_write(AT91_AIC_IECR, backups);
+}
+
+#else
+#define at91_aic_set_wake NULL
+#endif
+
+static struct irq_chip at91_aic_chip = {
+ .name = "AIC",
+ .ack = at91_aic_mask_irq,
+ .mask = at91_aic_mask_irq,
+ .unmask = at91_aic_unmask_irq,
+ .set_type = at91_aic_set_type,
+ .set_wake = at91_aic_set_wake,
+};
+
+/*
+ * Initialize the AIC interrupt controller.
+ */
+void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
+{
+ unsigned int i;
+
+ /*
+ * The IVR is used by macro get_irqnr_and_base to read and verify.
+ * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
+ */
+ for (i = 0; i < NR_AIC_IRQS; i++) {
+ /* Put irq number in Source Vector Register: */
+ at91_sys_write(AT91_AIC_SVR(i), i);
+ /* Active Low interrupt, with the specified priority */
+ at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
+
+ set_irq_chip(i, &at91_aic_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+
+ /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
+ if (i < 8)
+ at91_sys_write(AT91_AIC_EOICR, 0);
+ }
+
+ /*
+ * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS
+ * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU
+ */
+ at91_sys_write(AT91_AIC_SPU, NR_AIC_IRQS);
+
+ /* No debugging in AIC: Debug (Protect) Control Register */
+ at91_sys_write(AT91_AIC_DCR, 0);
+
+ /* Disable and clear all interrupts initially */
+ at91_sys_write(AT91_AIC_IDCR, 0xFFFFFFFF);
+ at91_sys_write(AT91_AIC_ICCR, 0xFFFFFFFF);
+}
diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
new file mode 100644
index 000000000000..0d5144973988
--- /dev/null
+++ b/arch/arm/mach-at91/leds.c
@@ -0,0 +1,95 @@
+/*
+ * LED driver for Atmel AT91-based boards.
+ *
+ * Copyright (C) SAN People (Pty) Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+#include <asm/leds.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+static inline void at91_led_on(unsigned int led)
+{
+ at91_set_gpio_value(led, 0);
+}
+
+static inline void at91_led_off(unsigned int led)
+{
+ at91_set_gpio_value(led, 1);
+}
+
+static inline void at91_led_toggle(unsigned int led)
+{
+ unsigned long is_off = at91_get_gpio_value(led);
+ if (is_off)
+ at91_led_on(led);
+ else
+ at91_led_off(led);
+}
+
+
+/*
+ * Handle LED events.
+ */
+static void at91_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ switch(evt) {
+ case led_start: /* System startup */
+ at91_led_on(at91_leds_cpu);
+ break;
+
+ case led_stop: /* System stop / suspend */
+ at91_led_off(at91_leds_cpu);
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer: /* Every 50 timer ticks */
+ at91_led_toggle(at91_leds_timer);
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start: /* Entering idle state */
+ at91_led_off(at91_leds_cpu);
+ break;
+
+ case led_idle_end: /* Exit idle state */
+ at91_led_on(at91_leds_cpu);
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ local_irq_restore(flags);
+}
+
+
+static int __init leds_init(void)
+{
+ if (!at91_leds_timer || !at91_leds_cpu)
+ return -ENODEV;
+
+ leds_event = at91_leds_event;
+
+ leds_event(led_start);
+ return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
new file mode 100644
index 000000000000..b49bfda53d7f
--- /dev/null
+++ b/arch/arm/mach-at91/pm.c
@@ -0,0 +1,229 @@
+/*
+ * arch/arm/mach-at91/pm.c
+ * AT91 Power Management
+ *
+ * Copyright (C) 2005 David Brownell
+ *
+ * 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/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91rm9200_mc.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
+
+#include "generic.h"
+
+
+static int at91_pm_valid_state(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_ON:
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+
+static suspend_state_t target_state;
+
+/*
+ * Called after processes are frozen, but before we shutdown devices.
+ */
+static int at91_pm_prepare(suspend_state_t state)
+{
+ target_state = state;
+ return 0;
+}
+
+/*
+ * Verify that all the clocks are correct before entering
+ * slow-clock mode.
+ */
+static int at91_pm_verify_clocks(void)
+{
+ unsigned long scsr;
+ int i;
+
+ scsr = at91_sys_read(AT91_PMC_SCSR);
+
+ /* USB must not be using PLLB */
+ if (cpu_is_at91rm9200()) {
+ if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) {
+ pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+ return 0;
+ }
+ } else if (cpu_is_at91sam9260()) {
+#warning "Check SAM9260 USB clocks"
+ } else if (cpu_is_at91sam9261()) {
+#warning "Check SAM9261 USB clocks"
+ } else if (cpu_is_at91sam9263()) {
+#warning "Check SAM9263 USB clocks"
+ }
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+ /* PCK0..PCK3 must be disabled, or configured to use clk32k */
+ for (i = 0; i < 4; i++) {
+ u32 css;
+
+ if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
+ continue;
+
+ css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+ if (css != AT91_PMC_CSS_SLOW) {
+ pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
+ return 0;
+ }
+ }
+#endif
+
+ return 1;
+}
+
+/*
+ * Call this from platform driver suspend() to see how deeply to suspend.
+ * For example, some controllers (like OHCI) need one of the PLL clocks
+ * in order to act as a wakeup source, and those are not available when
+ * going into slow clock mode.
+ *
+ * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have
+ * the very same problem (but not using at91 main_clk), and it'd be better
+ * to add one generic API rather than lots of platform-specific ones.
+ */
+int at91_suspend_entering_slow_clock(void)
+{
+ return (target_state == PM_SUSPEND_MEM);
+}
+EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+
+
+static void (*slow_clock)(void);
+
+
+static int at91_pm_enter(suspend_state_t state)
+{
+ at91_gpio_suspend();
+ at91_irq_suspend();
+
+ pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
+ /* remember all the always-wake irqs */
+ (at91_sys_read(AT91_PMC_PCSR)
+ | (1 << AT91_ID_FIQ)
+ | (1 << AT91_ID_SYS)
+ | (at91_extern_irq))
+ & at91_sys_read(AT91_AIC_IMR),
+ state);
+
+ switch (state) {
+ /*
+ * Suspend-to-RAM is like STANDBY plus slow clock mode, so
+ * drivers must suspend more deeply: only the master clock
+ * controller may be using the main oscillator.
+ */
+ case PM_SUSPEND_MEM:
+ /*
+ * Ensure that clocks are in a valid state.
+ */
+ if (!at91_pm_verify_clocks())
+ goto error;
+
+ /*
+ * Enter slow clock mode by switching over to clk32k and
+ * turning off the main oscillator; reverse on wakeup.
+ */
+ if (slow_clock) {
+ slow_clock();
+ break;
+ } else {
+ /* DEVELOPMENT ONLY */
+ pr_info("AT91: PM - no slow clock mode yet ...\n");
+ /* FALLTHROUGH leaving master clock alone */
+ }
+
+ /*
+ * STANDBY mode has *all* drivers suspended; ignores irqs not
+ * marked as 'wakeup' event sources; and reduces DRAM power.
+ * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and
+ * nothing fancy done with main or cpu clocks.
+ */
+ case PM_SUSPEND_STANDBY:
+ /*
+ * NOTE: the Wait-for-Interrupt instruction needs to be
+ * in icache so the SDRAM stays in self-refresh mode until
+ * the wakeup IRQ occurs.
+ */
+ asm("b 1f; .align 5; 1:");
+ asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
+ at91_sys_write(AT91_SDRAMC_SRR, 1); /* self-refresh mode */
+ /* fall though to next state */
+
+ case PM_SUSPEND_ON:
+ asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */
+ break;
+
+ default:
+ pr_debug("AT91: PM - bogus suspend state %d\n", state);
+ goto error;
+ }
+
+ pr_debug("AT91: PM - wakeup %08x\n",
+ at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
+
+error:
+ target_state = PM_SUSPEND_ON;
+ at91_irq_resume();
+ at91_gpio_resume();
+ return 0;
+}
+
+
+static struct pm_ops at91_pm_ops ={
+ .pm_disk_mode = 0,
+ .valid = at91_pm_valid_state,
+ .prepare = at91_pm_prepare,
+ .enter = at91_pm_enter,
+};
+
+static int __init at91_pm_init(void)
+{
+ printk("AT91: Power Management\n");
+
+#ifdef CONFIG_AT91_PM_SLOW_CLOCK
+ /* REVISIT allocations of SRAM should be dynamically managed.
+ * FIQ handlers and other components will want SRAM/TCM too...
+ */
+ slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
+ memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
+#endif
+
+ /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */
+ at91_sys_write(AT91_SDRAMC_LPR, 0);
+
+ pm_set_ops(&at91_pm_ops);
+
+ return 0;
+}
+arch_initcall(at91_pm_init);