summaryrefslogtreecommitdiff
path: root/cpu/at32ap
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/at32ap')
-rw-r--r--cpu/at32ap/Makefile50
-rw-r--r--cpu/at32ap/at32ap7000/Makefile43
-rw-r--r--cpu/at32ap/at32ap7000/devices.c448
-rw-r--r--cpu/at32ap/at32ap7000/hebi.c38
-rw-r--r--cpu/at32ap/cache.c97
-rw-r--r--cpu/at32ap/config.mk22
-rw-r--r--cpu/at32ap/cpu.c83
-rw-r--r--cpu/at32ap/device.c126
-rw-r--r--cpu/at32ap/entry.S65
-rw-r--r--cpu/at32ap/exception.c119
-rw-r--r--cpu/at32ap/hsdramc.c155
-rw-r--r--cpu/at32ap/hsdramc1.h143
-rw-r--r--cpu/at32ap/hsmc3.h126
-rw-r--r--cpu/at32ap/interrupts.c154
-rw-r--r--cpu/at32ap/pio.c94
-rw-r--r--cpu/at32ap/pio2.h44
-rw-r--r--cpu/at32ap/pm.c163
-rw-r--r--cpu/at32ap/sm.h204
-rw-r--r--cpu/at32ap/start.S113
19 files changed, 2287 insertions, 0 deletions
diff --git a/cpu/at32ap/Makefile b/cpu/at32ap/Makefile
new file mode 100644
index 0000000..8ce79e9
--- /dev/null
+++ b/cpu/at32ap/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# Copyright (C) 2005-2006 Atmel Corporation.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB := $(obj)lib$(CPU).a
+
+START := start.o
+SOBJS := entry.o
+COBJS := cpu.o hsdramc.o exception.o cache.o
+COBJS += interrupts.o device.o pm.o pio.o
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) crv $@ $^
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/at32ap/at32ap7000/Makefile b/cpu/at32ap/at32ap7000/Makefile
new file mode 100644
index 0000000..1cd9444
--- /dev/null
+++ b/cpu/at32ap/at32ap7000/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2005-2006 Atmel Corporation
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB := $(obj)lib$(SOC).a
+
+COBJS := hebi.o devices.o
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) crv $@ $^
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/at32ap/at32ap7000/devices.c b/cpu/at32ap/at32ap7000/devices.c
new file mode 100644
index 0000000..8b216e9
--- /dev/null
+++ b/cpu/at32ap/at32ap7000/devices.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#include <asm/arch/memory-map.h>
+#include <asm/arch/platform.h>
+
+#include "../sm.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+const struct clock_domain chip_clock[] = {
+ [CLOCK_CPU] = {
+ .reg = SM_PM_CPU_MASK,
+ .id = CLOCK_CPU,
+ .bridge = NO_DEVICE,
+ },
+ [CLOCK_HSB] = {
+ .reg = SM_PM_HSB_MASK,
+ .id = CLOCK_HSB,
+ .bridge = NO_DEVICE,
+ },
+ [CLOCK_PBA] = {
+ .reg = SM_PM_PBA_MASK,
+ .id = CLOCK_PBA,
+ .bridge = DEVICE_PBA_BRIDGE,
+ },
+ [CLOCK_PBB] = {
+ .reg = SM_PM_PBB_MASK,
+ .id = CLOCK_PBB,
+ .bridge = DEVICE_PBB_BRIDGE,
+ },
+};
+
+static const struct resource hebi_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_HSB, 0 },
+ },
+ }, {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBB, 13 },
+ },
+ }, {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBB, 14 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 27, DEVICE_PIOE, GPIO_FUNC_A, 0 },
+ },
+ },
+};
+static const struct resource pba_bridge_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_HSB, 1 },
+ }
+ }, {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ /* HSB-HSB Bridge */
+ .clock = { CLOCK_HSB, 4 },
+ },
+ },
+};
+static const struct resource pbb_bridge_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_HSB, 2 },
+ },
+ },
+};
+static const struct resource hramc_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_HSB, 3 },
+ },
+ },
+};
+static const struct resource pioa_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 10 },
+ },
+ },
+};
+static const struct resource piob_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 11 },
+ },
+ },
+};
+static const struct resource pioc_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 12 },
+ },
+ },
+};
+static const struct resource piod_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 13 },
+ },
+ },
+};
+static const struct resource pioe_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 14 },
+ },
+ },
+};
+static const struct resource sm_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBB, 0 },
+ },
+ },
+};
+static const struct resource intc_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBB, 1 },
+ },
+ },
+};
+static const struct resource hmatrix_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBB, 2 },
+ },
+ },
+};
+#if defined(CFG_HPDC)
+static const struct resource hpdc_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 16 },
+ },
+ },
+};
+#endif
+#if defined(CFG_MACB0)
+static const struct resource macb0_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_HSB, 8 },
+ },
+ }, {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBB, 6 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 19, DEVICE_PIOC, GPIO_FUNC_A, 0 },
+ },
+ },
+};
+#endif
+#if defined(CFG_MACB1)
+static const struct resource macb1_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_HSB, 9 },
+ },
+ }, {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBB, 7 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 12, DEVICE_PIOC, GPIO_FUNC_B, 19 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 14, DEVICE_PIOD, GPIO_FUNC_B, 2 },
+ },
+ },
+};
+#endif
+#if defined(CFG_LCDC)
+static const struct resource lcdc_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_HSB, 7 },
+ },
+ },
+};
+#endif
+#if defined(CFG_USART0)
+static const struct resource usart0_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 3 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 2, DEVICE_PIOA, GPIO_FUNC_B, 8 },
+ },
+ },
+};
+#endif
+#if defined(CFG_USART1)
+static const struct resource usart1_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 4 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 2, DEVICE_PIOA, GPIO_FUNC_A, 17 },
+ },
+ },
+};
+#endif
+#if defined(CFG_USART2)
+static const struct resource usart2_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 5 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 2, DEVICE_PIOB, GPIO_FUNC_B, 26 },
+ },
+ },
+};
+#endif
+#if defined(CFG_USART3)
+static const struct resource usart3_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBA, 6 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 2, DEVICE_PIOB, GPIO_FUNC_B, 17 },
+ },
+ },
+};
+#endif
+#if defined(CFG_MMCI)
+static const struct resource mmci_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_PBB, 9 },
+ },
+ }, {
+ .type = RESOURCE_GPIO,
+ .u = {
+ .gpio = { 6, DEVICE_PIOA, GPIO_FUNC_A, 10 },
+ },
+ },
+};
+#endif
+#if defined(CFG_DMAC)
+static const struct resource dmac_resource[] = {
+ {
+ .type = RESOURCE_CLOCK,
+ .u = {
+ .clock = { CLOCK_HSB, 10 },
+ },
+ },
+};
+#endif
+
+const struct device chip_device[] = {
+ [DEVICE_HEBI] = {
+ .regs = (void *)HSMC_BASE,
+ .nr_resources = ARRAY_SIZE(hebi_resource),
+ .resource = hebi_resource,
+ },
+ [DEVICE_PBA_BRIDGE] = {
+ .nr_resources = ARRAY_SIZE(pba_bridge_resource),
+ .resource = pba_bridge_resource,
+ },
+ [DEVICE_PBB_BRIDGE] = {
+ .nr_resources = ARRAY_SIZE(pbb_bridge_resource),
+ .resource = pbb_bridge_resource,
+ },
+ [DEVICE_HRAMC] = {
+ .nr_resources = ARRAY_SIZE(hramc_resource),
+ .resource = hramc_resource,
+ },
+ [DEVICE_PIOA] = {
+ .regs = (void *)PIOA_BASE,
+ .nr_resources = ARRAY_SIZE(pioa_resource),
+ .resource = pioa_resource,
+ },
+ [DEVICE_PIOB] = {
+ .regs = (void *)PIOB_BASE,
+ .nr_resources = ARRAY_SIZE(piob_resource),
+ .resource = piob_resource,
+ },
+ [DEVICE_PIOC] = {
+ .regs = (void *)PIOC_BASE,
+ .nr_resources = ARRAY_SIZE(pioc_resource),
+ .resource = pioc_resource,
+ },
+ [DEVICE_PIOD] = {
+ .regs = (void *)PIOD_BASE,
+ .nr_resources = ARRAY_SIZE(piod_resource),
+ .resource = piod_resource,
+ },
+ [DEVICE_PIOE] = {
+ .regs = (void *)PIOE_BASE,
+ .nr_resources = ARRAY_SIZE(pioe_resource),
+ .resource = pioe_resource,
+ },
+ [DEVICE_SM] = {
+ .regs = (void *)SM_BASE,
+ .nr_resources = ARRAY_SIZE(sm_resource),
+ .resource = sm_resource,
+ },
+ [DEVICE_INTC] = {
+ .regs = (void *)INTC_BASE,
+ .nr_resources = ARRAY_SIZE(intc_resource),
+ .resource = intc_resource,
+ },
+ [DEVICE_HMATRIX] = {
+ .regs = (void *)HMATRIX_BASE,
+ .nr_resources = ARRAY_SIZE(hmatrix_resource),
+ .resource = hmatrix_resource,
+ },
+#if defined(CFG_HPDC)
+ [DEVICE_HPDC] = {
+ .nr_resources = ARRAY_SIZE(hpdc_resource),
+ .resource = hpdc_resource,
+ },
+#endif
+#if defined(CFG_MACB0)
+ [DEVICE_MACB0] = {
+ .regs = (void *)MACB0_BASE,
+ .nr_resources = ARRAY_SIZE(macb0_resource),
+ .resource = macb0_resource,
+ },
+#endif
+#if defined(CFG_MACB1)
+ [DEVICE_MACB1] = {
+ .regs = (void *)MACB1_BASE,
+ .nr_resources = ARRAY_SIZE(macb1_resource),
+ .resource = macb1_resource,
+ },
+#endif
+#if defined(CFG_LCDC)
+ [DEVICE_LCDC] = {
+ .nr_resources = ARRAY_SIZE(lcdc_resource),
+ .resource = lcdc_resource,
+ },
+#endif
+#if defined(CFG_USART0)
+ [DEVICE_USART0] = {
+ .regs = (void *)USART0_BASE,
+ .nr_resources = ARRAY_SIZE(usart0_resource),
+ .resource = usart0_resource,
+ },
+#endif
+#if defined(CFG_USART1)
+ [DEVICE_USART1] = {
+ .regs = (void *)USART1_BASE,
+ .nr_resources = ARRAY_SIZE(usart1_resource),
+ .resource = usart1_resource,
+ },
+#endif
+#if defined(CFG_USART2)
+ [DEVICE_USART2] = {
+ .regs = (void *)USART2_BASE,
+ .nr_resources = ARRAY_SIZE(usart2_resource),
+ .resource = usart2_resource,
+ },
+#endif
+#if defined(CFG_USART3)
+ [DEVICE_USART3] = {
+ .regs = (void *)USART3_BASE,
+ .nr_resources = ARRAY_SIZE(usart3_resource),
+ .resource = usart3_resource,
+ },
+#endif
+#if defined(CFG_MMCI)
+ [DEVICE_MMCI] = {
+ .regs = (void *)MMCI_BASE,
+ .nr_resources = ARRAY_SIZE(mmci_resource),
+ .resource = mmci_resource,
+ },
+#endif
+#if defined(CFG_DMAC)
+ [DEVICE_DMAC] = {
+ .regs = (void *)DMAC_BASE,
+ .nr_resources = ARRAY_SIZE(dmac_resource),
+ .resource = dmac_resource,
+ },
+#endif
+};
diff --git a/cpu/at32ap/at32ap7000/hebi.c b/cpu/at32ap/at32ap7000/hebi.c
new file mode 100644
index 0000000..3b32adf
--- /dev/null
+++ b/cpu/at32ap/at32ap7000/hebi.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/hmatrix2.h>
+#include <asm/arch/memory-map.h>
+#include <asm/arch/platform.h>
+
+void cpu_enable_sdram(void)
+{
+ const struct device *hmatrix;
+
+ hmatrix = get_device(DEVICE_HMATRIX);
+
+ /* Set the SDRAM_ENABLE bit in the HEBI SFR */
+ hmatrix2_writel(hmatrix, SFR4, 1 << 1);
+}
diff --git a/cpu/at32ap/cache.c b/cpu/at32ap/cache.c
new file mode 100644
index 0000000..41fb5aa
--- /dev/null
+++ b/cpu/at32ap/cache.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#include <asm/cacheflush.h>
+
+void dcache_clean_range(volatile void *start, size_t size)
+{
+ unsigned long v, begin, end, linesz;
+
+ linesz = CFG_DCACHE_LINESZ;
+
+ /* You asked for it, you got it */
+ begin = (unsigned long)start & ~(linesz - 1);
+ end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+
+ for (v = begin; v < end; v += linesz)
+ dcache_clean_line((void *)v);
+
+ sync_write_buffer();
+}
+
+void dcache_invalidate_range(volatile void *start, size_t size)
+{
+ unsigned long v, begin, end, linesz;
+
+ linesz = CFG_DCACHE_LINESZ;
+
+ /* You asked for it, you got it */
+ begin = (unsigned long)start & ~(linesz - 1);
+ end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+
+ for (v = begin; v < end; v += linesz)
+ dcache_invalidate_line((void *)v);
+}
+
+void dcache_flush_range(volatile void *start, size_t size)
+{
+ unsigned long v, begin, end, linesz;
+
+ linesz = CFG_DCACHE_LINESZ;
+
+ /* You asked for it, you got it */
+ begin = (unsigned long)start & ~(linesz - 1);
+ end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+
+ for (v = begin; v < end; v += linesz)
+ dcache_flush_line((void *)v);
+
+ sync_write_buffer();
+}
+
+void icache_invalidate_range(volatile void *start, size_t size)
+{
+ unsigned long v, begin, end, linesz;
+
+ linesz = CFG_ICACHE_LINESZ;
+
+ /* You asked for it, you got it */
+ begin = (unsigned long)start & ~(linesz - 1);
+ end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
+
+ for (v = begin; v < end; v += linesz)
+ icache_invalidate_line((void *)v);
+}
+
+/*
+ * This is called after loading something into memory. We need to
+ * make sure that everything that was loaded is actually written to
+ * RAM, and that the icache will look for it. Cleaning the dcache and
+ * invalidating the icache will do the trick.
+ */
+void flush_cache (unsigned long start_addr, unsigned long size)
+{
+ dcache_clean_range((void *)start_addr, size);
+ icache_invalidate_range((void *)start_addr, size);
+}
diff --git a/cpu/at32ap/config.mk b/cpu/at32ap/config.mk
new file mode 100644
index 0000000..1c12169
--- /dev/null
+++ b/cpu/at32ap/config.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2005-2006 Atmel Corporation
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+PLATFORM_RELFLAGS += -mcpu=ap7000
diff --git a/cpu/at32ap/cpu.c b/cpu/at32ap/cpu.c
new file mode 100644
index 0000000..37e3ea0
--- /dev/null
+++ b/cpu/at32ap/cpu.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+#include <command.h>
+
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <asm/sysreg.h>
+
+#include <asm/arch/memory-map.h>
+#include <asm/arch/platform.h>
+
+#include "hsmc3.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int cpu_init(void)
+{
+ const struct device *hebi;
+ extern void _evba(void);
+ char *p;
+
+ gd->cpu_hz = CFG_OSC0_HZ;
+
+ /* fff03400: 00010001 04030402 00050005 10011103 */
+ hebi = get_device(DEVICE_HEBI);
+ hsmc3_writel(hebi, MODE0, 0x00031103);
+ hsmc3_writel(hebi, CYCLE0, 0x000c000d);
+ hsmc3_writel(hebi, PULSE0, 0x0b0a0906);
+ hsmc3_writel(hebi, SETUP0, 0x00010002);
+
+ pm_init();
+
+ sysreg_write(EVBA, (unsigned long)&_evba);
+ asm volatile("csrf %0" : : "i"(SYSREG_EM_OFFSET));
+ gd->console_uart = get_device(CFG_CONSOLE_UART_DEV);
+
+ /* Lock everything that mess with the flash in the icache */
+ for (p = __flashprog_start; p <= (__flashprog_end + CFG_ICACHE_LINESZ);
+ p += CFG_ICACHE_LINESZ)
+ asm volatile("cache %0, 0x02" : "=m"(*p) :: "memory");
+
+ return 0;
+}
+
+void prepare_to_boot(void)
+{
+ /* Flush both caches and the write buffer */
+ asm volatile("cache %0[4], 010\n\t"
+ "cache %0[0], 000\n\t"
+ "sync 0" : : "r"(0) : "memory");
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ /* This will reset the CPU core, caches, MMU and all internal busses */
+ __builtin_mtdr(8, 1 << 13); /* set DC:DBE */
+ __builtin_mtdr(8, 1 << 30); /* set DC:RES */
+
+ /* Flush the pipeline before we declare it a failure */
+ asm volatile("sub pc, pc, -4");
+
+ return -1;
+}
diff --git a/cpu/at32ap/device.c b/cpu/at32ap/device.c
new file mode 100644
index 0000000..89914b6
--- /dev/null
+++ b/cpu/at32ap/device.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#include <asm/arch/platform.h>
+
+#include "sm.h"
+
+struct device_state {
+ int refcount;
+};
+
+static struct device_state device_state[NR_DEVICES];
+
+static int claim_resource(const struct resource *res)
+{
+ int ret = 0;
+
+ switch (res->type) {
+ case RESOURCE_GPIO:
+ ret = gpio_set_func(res->u.gpio.gpio_dev,
+ res->u.gpio.start,
+ res->u.gpio.nr_pins,
+ res->u.gpio.func);
+ break;
+ case RESOURCE_CLOCK:
+ ret = pm_enable_clock(res->u.clock.id, res->u.clock.index);
+ break;
+ }
+
+ return ret;
+}
+
+static void free_resource(const struct resource *res)
+{
+ switch (res->type) {
+ case RESOURCE_GPIO:
+ gpio_free(res->u.gpio.gpio_dev, res->u.gpio.start,
+ res->u.gpio.nr_pins);
+ break;
+ case RESOURCE_CLOCK:
+ pm_disable_clock(res->u.clock.id, res->u.clock.index);
+ break;
+ }
+}
+
+static int init_dev(const struct device *dev)
+{
+ unsigned int i;
+ int ret = 0;
+
+ for (i = 0; i < dev->nr_resources; i++) {
+ ret = claim_resource(&dev->resource[i]);
+ if (ret)
+ goto cleanup;
+ }
+
+ return 0;
+
+cleanup:
+ while (i--)
+ free_resource(&dev->resource[i]);
+
+ return ret;
+}
+
+const struct device *get_device(enum device_id devid)
+{
+ struct device_state *devstate;
+ const struct device *dev;
+ unsigned long flags;
+ int initialized = 0;
+ int ret = 0;
+
+ devstate = &device_state[devid];
+ dev = &chip_device[devid];
+
+ flags = disable_interrupts();
+ if (devstate->refcount++)
+ initialized = 1;
+ if (flags)
+ enable_interrupts();
+
+ if (!initialized)
+ ret = init_dev(dev);
+
+ return ret ? NULL : dev;
+}
+
+void put_device(const struct device *dev)
+{
+ struct device_state *devstate;
+ unsigned long devid, flags;
+
+ devid = (unsigned long)(dev - chip_device) / sizeof(struct device);
+ devstate = &device_state[devid];
+
+ flags = disable_interrupts();
+ devstate--;
+ if (!devstate) {
+ unsigned int i;
+ for (i = 0; i < dev->nr_resources; i++)
+ free_resource(&dev->resource[i]);
+ }
+ if (flags)
+ enable_interrupts();
+}
diff --git a/cpu/at32ap/entry.S b/cpu/at32ap/entry.S
new file mode 100644
index 0000000..b52d798
--- /dev/null
+++ b/cpu/at32ap/entry.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <asm/sysreg.h>
+#include <asm/ptrace.h>
+
+ .section .text.exception,"ax"
+ .global _evba
+ .type _evba,@function
+ .align 10
+_evba:
+ .irp x,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
+ .align 2
+ rjmp unknown_exception
+ .endr
+
+ .global timer_interrupt_handler
+ .type timer_interrupt_handler,@function
+ .align 2
+timer_interrupt_handler:
+ /*
+ * Increment timer_overflow and re-write COMPARE with 0xffffffff.
+ *
+ * We're running at interrupt level 3, so we don't need to save
+ * r8-r12 or lr to the stack.
+ */
+ mov r8, lo(timer_overflow)
+ orh r8, hi(timer_overflow)
+ ld.w r9, r8[0]
+ mov r10, -1
+ mtsr SYSREG_COMPARE, r10
+ sub r9, -1
+ st.w r8[0], r9
+ rete
+
+ .type unknown_exception, @function
+unknown_exception:
+ pushm r0-r12
+ sub r8, sp, REG_R12 - REG_R0 - 4
+ mov r9, lr
+ mfsr r10, SYSREG_RAR_EX
+ mfsr r11, SYSREG_RSR_EX
+ pushm r8-r11
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_unknown_exception
+1: rjmp 1b
diff --git a/cpu/at32ap/exception.c b/cpu/at32ap/exception.c
new file mode 100644
index 0000000..4123c44
--- /dev/null
+++ b/cpu/at32ap/exception.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#include <asm/sysreg.h>
+#include <asm/ptrace.h>
+
+static const char * const cpu_modes[8] = {
+ "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
+ "Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
+};
+
+static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+{
+ unsigned long p;
+ int i;
+
+ printf("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+
+ for (p = bottom & ~31; p < top; ) {
+ printf("%04lx: ", p & 0xffff);
+
+ for (i = 0; i < 8; i++, p += 4) {
+ unsigned int val;
+
+ if (p < bottom || p >= top)
+ printf(" ");
+ else {
+ val = *(unsigned long *)p;
+ printf("%08x ", val);
+ }
+ }
+ printf("\n");
+ }
+}
+
+void do_unknown_exception(unsigned int ecr, struct pt_regs *regs)
+{
+ unsigned int mode;
+
+ printf("\n *** Unhandled exception %u at PC=0x%08lx\n", ecr, regs->pc);
+
+ switch (ecr) {
+ case ECR_BUS_ERROR_WRITE:
+ case ECR_BUS_ERROR_READ:
+ printf("Bus error at address 0x%08lx\n",
+ sysreg_read(BEAR));
+ break;
+ case ECR_TLB_MULTIPLE:
+ case ECR_ADDR_ALIGN_X:
+ case ECR_PROTECTION_X:
+ case ECR_ADDR_ALIGN_R:
+ case ECR_ADDR_ALIGN_W:
+ case ECR_PROTECTION_R:
+ case ECR_PROTECTION_W:
+ case ECR_DTLB_MODIFIED:
+ case ECR_TLB_MISS_X:
+ case ECR_TLB_MISS_R:
+ case ECR_TLB_MISS_W:
+ printf("MMU exception at address 0x%08lx\n",
+ sysreg_read(TLBEAR));
+ break;
+ }
+
+ printf(" pc: %08lx lr: %08lx sp: %08lx r12: %08lx\n",
+ regs->pc, regs->lr, regs->sp, regs->r12);
+ printf(" r11: %08lx r10: %08lx r9: %08lx r8: %08lx\n",
+ regs->r11, regs->r10, regs->r9, regs->r8);
+ printf(" r7: %08lx r6: %08lx r5: %08lx r4: %08lx\n",
+ regs->r7, regs->r6, regs->r5, regs->r4);
+ printf(" r3: %08lx r2: %08lx r1: %08lx r0: %08lx\n",
+ regs->r3, regs->r2, regs->r1, regs->r0);
+ printf("Flags: %c%c%c%c%c\n",
+ regs->sr & SR_Q ? 'Q' : 'q',
+ regs->sr & SR_V ? 'V' : 'v',
+ regs->sr & SR_N ? 'N' : 'n',
+ regs->sr & SR_Z ? 'Z' : 'z',
+ regs->sr & SR_C ? 'C' : 'c');
+ printf("Mode bits: %c%c%c%c%c%c%c%c%c\n",
+ regs->sr & SR_H ? 'H' : 'h',
+ regs->sr & SR_R ? 'R' : 'r',
+ regs->sr & SR_J ? 'J' : 'j',
+ regs->sr & SR_EM ? 'E' : 'e',
+ regs->sr & SR_I3M ? '3' : '.',
+ regs->sr & SR_I2M ? '2' : '.',
+ regs->sr & SR_I1M ? '1' : '.',
+ regs->sr & SR_I0M ? '0' : '.',
+ regs->sr & SR_GM ? 'G' : 'g');
+ mode = (regs->sr >> SYSREG_M0_OFFSET) & 7;
+ printf("CPU Mode: %s\n", cpu_modes[mode]);
+
+ /* Avoid exception loops */
+ if (regs->sp >= CFG_INIT_SP_ADDR
+ || regs->sp < (CFG_INIT_SP_ADDR - CONFIG_STACKSIZE))
+ printf("\nStack pointer seems bogus, won't do stack dump\n");
+ else
+ dump_mem("\nStack: ", regs->sp, CFG_INIT_SP_ADDR);
+
+ panic("Unhandled exception\n");
+}
diff --git a/cpu/at32ap/hsdramc.c b/cpu/at32ap/hsdramc.c
new file mode 100644
index 0000000..f36da35
--- /dev/null
+++ b/cpu/at32ap/hsdramc.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#ifdef CFG_HSDRAMC
+#include <asm/io.h>
+#include <asm/sdram.h>
+
+#include <asm/arch/platform.h>
+
+#include "hsdramc1.h"
+
+struct hsdramc {
+ const struct device *hebi;
+ void *regs;
+};
+
+static struct hsdramc hsdramc;
+
+unsigned long sdram_init(const struct sdram_info *info)
+{
+ unsigned long *sdram = (unsigned long *)uncached(info->phys_addr);
+ unsigned long sdram_size;
+ unsigned long tmp;
+ unsigned long bus_hz;
+ unsigned int i;
+
+ hsdramc.hebi = get_device(DEVICE_HEBI);
+ if (!hsdramc.hebi)
+ return 0;
+
+ /* FIXME: Both of these lines are complete hacks */
+ hsdramc.regs = hsdramc.hebi->regs + 0x400;
+ bus_hz = pm_get_clock_freq(hsdramc.hebi->resource[0].u.clock.id);
+
+ cpu_enable_sdram();
+
+ tmp = (HSDRAMC1_BF(NC, info->col_bits - 8)
+ | HSDRAMC1_BF(NR, info->row_bits - 11)
+ | HSDRAMC1_BF(NB, info->bank_bits - 1)
+ | HSDRAMC1_BF(CAS, info->cas)
+ | HSDRAMC1_BF(TWR, info->twr)
+ | HSDRAMC1_BF(TRC, info->trc)
+ | HSDRAMC1_BF(TRP, info->trp)
+ | HSDRAMC1_BF(TRCD, info->trcd)
+ | HSDRAMC1_BF(TRAS, info->tras)
+ | HSDRAMC1_BF(TXSR, info->txsr));
+
+#ifdef CFG_SDRAM_16BIT
+ tmp |= HSDRAMC1_BIT(DBW);
+ sdram_size = 1 << (info->row_bits + info->col_bits
+ + info->bank_bits + 1);
+#else
+ sdram_size = 1 << (info->row_bits + info->col_bits
+ + info->bank_bits + 2);
+#endif
+
+ hsdramc1_writel(&hsdramc, CR, tmp);
+
+ /*
+ * Initialization sequence for SDRAM, from the data sheet:
+ *
+ * 1. A minimum pause of 200 us is provided to precede any
+ * signal toggle.
+ */
+ udelay(200);
+
+ /*
+ * 2. A Precharge All command is issued to the SDRAM
+ */
+ hsdramc1_writel(&hsdramc, MR, HSDRAMC1_MODE_BANKS_PRECHARGE);
+ hsdramc1_readl(&hsdramc, MR);
+ writel(0, sdram);
+
+ /*
+ * 3. Eight auto-refresh (CBR) cycles are provided
+ */
+ hsdramc1_writel(&hsdramc, MR, HSDRAMC1_MODE_AUTO_REFRESH);
+ hsdramc1_readl(&hsdramc, MR);
+ for (i = 0; i < 8; i++)
+ writel(0, sdram);
+
+ /*
+ * 4. A mode register set (MRS) cycle is issued to program
+ * SDRAM parameters, in particular CAS latency and burst
+ * length.
+ *
+ * CAS from info struct, burst length 1, serial burst type
+ */
+ hsdramc1_writel(&hsdramc, MR, HSDRAMC1_MODE_LOAD_MODE);
+ hsdramc1_readl(&hsdramc, MR);
+ writel(0, sdram + (info->cas << 4));
+
+ /*
+ * 5. A Normal Mode command is provided, 3 clocks after tMRD
+ * is met.
+ *
+ * From the timing diagram, it looks like tMRD is 3
+ * cycles...try a dummy read from the peripheral bus.
+ */
+ hsdramc1_readl(&hsdramc, MR);
+ hsdramc1_writel(&hsdramc, MR, HSDRAMC1_MODE_NORMAL);
+ hsdramc1_readl(&hsdramc, MR);
+ writel(0, sdram);
+
+ /*
+ * 6. Write refresh rate into SDRAMC refresh timer count
+ * register (refresh rate = timing between refresh cycles).
+ *
+ * 15.6 us is a typical value for a burst of length one
+ */
+ hsdramc1_writel(&hsdramc, TR, (156 * (bus_hz / 1000)) / 10000);
+
+ printf("SDRAM: %u MB at address 0x%08lx\n",
+ sdram_size >> 20, info->phys_addr);
+
+ printf("Testing SDRAM...");
+ for (i = 0; i < sdram_size / 4; i++)
+ sdram[i] = i;
+
+ for (i = 0; i < sdram_size / 4; i++) {
+ tmp = sdram[i];
+ if (tmp != i) {
+ printf("FAILED at address 0x%08lx\n",
+ info->phys_addr + i * 4);
+ printf("SDRAM: read 0x%lx, expected 0x%lx\n", tmp, i);
+ return 0;
+ }
+ }
+
+ puts("OK\n");
+
+ return sdram_size;
+}
+
+#endif /* CFG_HSDRAMC */
diff --git a/cpu/at32ap/hsdramc1.h b/cpu/at32ap/hsdramc1.h
new file mode 100644
index 0000000..ce229bc
--- /dev/null
+++ b/cpu/at32ap/hsdramc1.h
@@ -0,0 +1,143 @@
+/*
+ * Register definitions for SDRAM Controller
+ */
+#ifndef __ASM_AVR32_HSDRAMC1_H__
+#define __ASM_AVR32_HSDRAMC1_H__
+
+/* HSDRAMC1 register offsets */
+#define HSDRAMC1_MR 0x0000
+#define HSDRAMC1_TR 0x0004
+#define HSDRAMC1_CR 0x0008
+#define HSDRAMC1_HSR 0x000c
+#define HSDRAMC1_LPR 0x0010
+#define HSDRAMC1_IER 0x0014
+#define HSDRAMC1_IDR 0x0018
+#define HSDRAMC1_IMR 0x001c
+#define HSDRAMC1_ISR 0x0020
+#define HSDRAMC1_MDR 0x0024
+#define HSDRAMC1_VERSION 0x00fc
+
+/* Bitfields in MR */
+#define HSDRAMC1_MODE_OFFSET 0
+#define HSDRAMC1_MODE_SIZE 3
+
+/* Bitfields in TR */
+#define HSDRAMC1_COUNT_OFFSET 0
+#define HSDRAMC1_COUNT_SIZE 12
+
+/* Bitfields in CR */
+#define HSDRAMC1_NC_OFFSET 0
+#define HSDRAMC1_NC_SIZE 2
+#define HSDRAMC1_NR_OFFSET 2
+#define HSDRAMC1_NR_SIZE 2
+#define HSDRAMC1_NB_OFFSET 4
+#define HSDRAMC1_NB_SIZE 1
+#define HSDRAMC1_CAS_OFFSET 5
+#define HSDRAMC1_CAS_SIZE 2
+#define HSDRAMC1_DBW_OFFSET 7
+#define HSDRAMC1_DBW_SIZE 1
+#define HSDRAMC1_TWR_OFFSET 8
+#define HSDRAMC1_TWR_SIZE 4
+#define HSDRAMC1_TRC_OFFSET 12
+#define HSDRAMC1_TRC_SIZE 4
+#define HSDRAMC1_TRP_OFFSET 16
+#define HSDRAMC1_TRP_SIZE 4
+#define HSDRAMC1_TRCD_OFFSET 20
+#define HSDRAMC1_TRCD_SIZE 4
+#define HSDRAMC1_TRAS_OFFSET 24
+#define HSDRAMC1_TRAS_SIZE 4
+#define HSDRAMC1_TXSR_OFFSET 28
+#define HSDRAMC1_TXSR_SIZE 4
+
+/* Bitfields in HSR */
+#define HSDRAMC1_DA_OFFSET 0
+#define HSDRAMC1_DA_SIZE 1
+
+/* Bitfields in LPR */
+#define HSDRAMC1_LPCB_OFFSET 0
+#define HSDRAMC1_LPCB_SIZE 2
+#define HSDRAMC1_PASR_OFFSET 4
+#define HSDRAMC1_PASR_SIZE 3
+#define HSDRAMC1_TCSR_OFFSET 8
+#define HSDRAMC1_TCSR_SIZE 2
+#define HSDRAMC1_DS_OFFSET 10
+#define HSDRAMC1_DS_SIZE 2
+#define HSDRAMC1_TIMEOUT_OFFSET 12
+#define HSDRAMC1_TIMEOUT_SIZE 2
+
+/* Bitfields in IDR */
+#define HSDRAMC1_RES_OFFSET 0
+#define HSDRAMC1_RES_SIZE 1
+
+/* Bitfields in MDR */
+#define HSDRAMC1_MD_OFFSET 0
+#define HSDRAMC1_MD_SIZE 2
+
+/* Bitfields in VERSION */
+#define HSDRAMC1_VERSION_OFFSET 0
+#define HSDRAMC1_VERSION_SIZE 12
+#define HSDRAMC1_MFN_OFFSET 16
+#define HSDRAMC1_MFN_SIZE 3
+
+/* Constants for MODE */
+#define HSDRAMC1_MODE_NORMAL 0
+#define HSDRAMC1_MODE_NOP 1
+#define HSDRAMC1_MODE_BANKS_PRECHARGE 2
+#define HSDRAMC1_MODE_LOAD_MODE 3
+#define HSDRAMC1_MODE_AUTO_REFRESH 4
+#define HSDRAMC1_MODE_EXT_LOAD_MODE 5
+#define HSDRAMC1_MODE_POWER_DOWN 6
+
+/* Constants for NC */
+#define HSDRAMC1_NC_8_COLUMN_BITS 0
+#define HSDRAMC1_NC_9_COLUMN_BITS 1
+#define HSDRAMC1_NC_10_COLUMN_BITS 2
+#define HSDRAMC1_NC_11_COLUMN_BITS 3
+
+/* Constants for NR */
+#define HSDRAMC1_NR_11_ROW_BITS 0
+#define HSDRAMC1_NR_12_ROW_BITS 1
+#define HSDRAMC1_NR_13_ROW_BITS 2
+
+/* Constants for NB */
+#define HSDRAMC1_NB_TWO_BANKS 0
+#define HSDRAMC1_NB_FOUR_BANKS 1
+
+/* Constants for CAS */
+#define HSDRAMC1_CAS_ONE_CYCLE 1
+#define HSDRAMC1_CAS_TWO_CYCLES 2
+
+/* Constants for DBW */
+#define HSDRAMC1_DBW_32_BITS 0
+#define HSDRAMC1_DBW_16_BITS 1
+
+/* Constants for TIMEOUT */
+#define HSDRAMC1_TIMEOUT_AFTER_END 0
+#define HSDRAMC1_TIMEOUT_64_CYC_AFTER_END 1
+#define HSDRAMC1_TIMEOUT_128_CYC_AFTER_END 2
+
+/* Constants for MD */
+#define HSDRAMC1_MD_SDRAM 0
+#define HSDRAMC1_MD_LOW_POWER_SDRAM 1
+
+/* Bit manipulation macros */
+#define HSDRAMC1_BIT(name) \
+ (1 << HSDRAMC1_##name##_OFFSET)
+#define HSDRAMC1_BF(name,value) \
+ (((value) & ((1 << HSDRAMC1_##name##_SIZE) - 1)) \
+ << HSDRAMC1_##name##_OFFSET)
+#define HSDRAMC1_BFEXT(name,value) \
+ (((value) >> HSDRAMC1_##name##_OFFSET) \
+ & ((1 << HSDRAMC1_##name##_SIZE) - 1))
+#define HSDRAMC1_BFINS(name,value,old) \
+ (((old) & ~(((1 << HSDRAMC1_##name##_SIZE) - 1) \
+ << HSDRAMC1_##name##_OFFSET)) \
+ | HSDRAMC1_BF(name,value))
+
+/* Register access macros */
+#define hsdramc1_readl(port,reg) \
+ readl((port)->regs + HSDRAMC1_##reg)
+#define hsdramc1_writel(port,reg,value) \
+ writel((value), (port)->regs + HSDRAMC1_##reg)
+
+#endif /* __ASM_AVR32_HSDRAMC1_H__ */
diff --git a/cpu/at32ap/hsmc3.h b/cpu/at32ap/hsmc3.h
new file mode 100644
index 0000000..ec78cee
--- /dev/null
+++ b/cpu/at32ap/hsmc3.h
@@ -0,0 +1,126 @@
+/*
+ * Register definitions for Static Memory Controller
+ */
+#ifndef __CPU_AT32AP_HSMC3_H__
+#define __CPU_AT32AP_HSMC3_H__
+
+/* HSMC3 register offsets */
+#define HSMC3_SETUP0 0x0000
+#define HSMC3_PULSE0 0x0004
+#define HSMC3_CYCLE0 0x0008
+#define HSMC3_MODE0 0x000c
+#define HSMC3_SETUP1 0x0010
+#define HSMC3_PULSE1 0x0014
+#define HSMC3_CYCLE1 0x0018
+#define HSMC3_MODE1 0x001c
+#define HSMC3_SETUP2 0x0020
+#define HSMC3_PULSE2 0x0024
+#define HSMC3_CYCLE2 0x0028
+#define HSMC3_MODE2 0x002c
+#define HSMC3_SETUP3 0x0030
+#define HSMC3_PULSE3 0x0034
+#define HSMC3_CYCLE3 0x0038
+#define HSMC3_MODE3 0x003c
+#define HSMC3_SETUP4 0x0040
+#define HSMC3_PULSE4 0x0044
+#define HSMC3_CYCLE4 0x0048
+#define HSMC3_MODE4 0x004c
+#define HSMC3_SETUP5 0x0050
+#define HSMC3_PULSE5 0x0054
+#define HSMC3_CYCLE5 0x0058
+#define HSMC3_MODE5 0x005c
+
+/* Bitfields in SETUP0 */
+#define HSMC3_NWE_SETUP_OFFSET 0
+#define HSMC3_NWE_SETUP_SIZE 6
+#define HSMC3_NCS_WR_SETUP_OFFSET 8
+#define HSMC3_NCS_WR_SETUP_SIZE 6
+#define HSMC3_NRD_SETUP_OFFSET 16
+#define HSMC3_NRD_SETUP_SIZE 6
+#define HSMC3_NCS_RD_SETUP_OFFSET 24
+#define HSMC3_NCS_RD_SETUP_SIZE 6
+
+/* Bitfields in PULSE0 */
+#define HSMC3_NWE_PULSE_OFFSET 0
+#define HSMC3_NWE_PULSE_SIZE 7
+#define HSMC3_NCS_WR_PULSE_OFFSET 8
+#define HSMC3_NCS_WR_PULSE_SIZE 7
+#define HSMC3_NRD_PULSE_OFFSET 16
+#define HSMC3_NRD_PULSE_SIZE 7
+#define HSMC3_NCS_RD_PULSE_OFFSET 24
+#define HSMC3_NCS_RD_PULSE_SIZE 7
+
+/* Bitfields in CYCLE0 */
+#define HSMC3_NWE_CYCLE_OFFSET 0
+#define HSMC3_NWE_CYCLE_SIZE 9
+#define HSMC3_NRD_CYCLE_OFFSET 16
+#define HSMC3_NRD_CYCLE_SIZE 9
+
+/* Bitfields in MODE0 */
+#define HSMC3_READ_MODE_OFFSET 0
+#define HSMC3_READ_MODE_SIZE 1
+#define HSMC3_WRITE_MODE_OFFSET 1
+#define HSMC3_WRITE_MODE_SIZE 1
+#define HSMC3_EXNW_MODE_OFFSET 4
+#define HSMC3_EXNW_MODE_SIZE 2
+#define HSMC3_BAT_OFFSET 8
+#define HSMC3_BAT_SIZE 1
+#define HSMC3_DBW_OFFSET 12
+#define HSMC3_DBW_SIZE 2
+#define HSMC3_TDF_CYCLES_OFFSET 16
+#define HSMC3_TDF_CYCLES_SIZE 4
+#define HSMC3_TDF_MODE_OFFSET 20
+#define HSMC3_TDF_MODE_SIZE 1
+#define HSMC3_PMEN_OFFSET 24
+#define HSMC3_PMEN_SIZE 1
+#define HSMC3_PS_OFFSET 28
+#define HSMC3_PS_SIZE 2
+
+/* Bitfields in MODE1 */
+#define HSMC3_PD_OFFSET 28
+#define HSMC3_PD_SIZE 2
+
+/* Constants for READ_MODE */
+#define HSMC3_READ_MODE_NCS_CONTROLLED 0
+#define HSMC3_READ_MODE_NRD_CONTROLLED 1
+
+/* Constants for WRITE_MODE */
+#define HSMC3_WRITE_MODE_NCS_CONTROLLED 0
+#define HSMC3_WRITE_MODE_NWE_CONTROLLED 1
+
+/* Constants for EXNW_MODE */
+#define HSMC3_EXNW_MODE_DISABLED 0
+#define HSMC3_EXNW_MODE_RESERVED 1
+#define HSMC3_EXNW_MODE_FROZEN 2
+#define HSMC3_EXNW_MODE_READY 3
+
+/* Constants for BAT */
+#define HSMC3_BAT_BYTE_SELECT 0
+#define HSMC3_BAT_BYTE_WRITE 1
+
+/* Constants for DBW */
+#define HSMC3_DBW_8_BITS 0
+#define HSMC3_DBW_16_BITS 1
+#define HSMC3_DBW_32_BITS 2
+
+/* Bit manipulation macros */
+#define HSMC3_BIT(name) \
+ (1 << HSMC3_##name##_OFFSET)
+#define HSMC3_BF(name,value) \
+ (((value) & ((1 << HSMC3_##name##_SIZE) - 1)) \
+ << HSMC3_##name##_OFFSET)
+#define HSMC3_BFEXT(name,value) \
+ (((value) >> HSMC3_##name##_OFFSET) \
+ & ((1 << HSMC3_##name##_SIZE) - 1))
+#define HSMC3_BFINS(name,value,old)\
+ (((old) & ~(((1 << HSMC3_##name##_SIZE) - 1) \
+ << HSMC3_##name##_OFFSET)) \
+ | HSMC3_BF(name,value))
+
+/* Register access macros */
+#define hsmc3_readl(port,reg) \
+ readl((port)->regs + HSMC3_##reg)
+#define hsmc3_writel(port,reg,value) \
+ writel((value), (port)->regs + HSMC3_##reg)
+
+#endif /* __CPU_AT32AP_HSMC3_H__ */
diff --git a/cpu/at32ap/interrupts.c b/cpu/at32ap/interrupts.c
new file mode 100644
index 0000000..d720cfa
--- /dev/null
+++ b/cpu/at32ap/interrupts.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#include <asm/div64.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/sysreg.h>
+
+#include <asm/arch/platform.h>
+
+#define HANDLER_MASK 0x00ffffff
+#define INTLEV_SHIFT 30
+#define INTLEV_MASK 0x00000003
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Incremented whenever COUNT reaches 0xffffffff by timer_interrupt_handler */
+volatile unsigned long timer_overflow;
+
+/*
+ * Instead of dividing by get_tbclk(), multiply by this constant and
+ * right-shift the result by 32 bits.
+ */
+static unsigned long tb_factor;
+
+static const struct device *intc_dev;
+
+unsigned long get_tbclk(void)
+{
+ return gd->cpu_hz;
+}
+
+unsigned long long get_ticks(void)
+{
+ unsigned long lo, hi_now, hi_prev;
+
+ do {
+ hi_prev = timer_overflow;
+ lo = sysreg_read(COUNT);
+ hi_now = timer_overflow;
+ } while (hi_prev != hi_now);
+
+ return ((unsigned long long)hi_now << 32) | lo;
+}
+
+void reset_timer(void)
+{
+ sysreg_write(COUNT, 0);
+ cpu_sync_pipeline(); /* process any pending interrupts */
+ timer_overflow = 0;
+}
+
+unsigned long get_timer(unsigned long base)
+{
+ u64 now = get_ticks();
+
+ now *= tb_factor;
+ return (unsigned long)(now >> 32) - base;
+}
+
+void set_timer(unsigned long t)
+{
+ unsigned long long ticks = t;
+ unsigned long lo, hi, hi_new;
+
+ ticks = (ticks * get_tbclk()) / CFG_HZ;
+ hi = ticks >> 32;
+ lo = ticks & 0xffffffffUL;
+
+ do {
+ timer_overflow = hi;
+ sysreg_write(COUNT, lo);
+ hi_new = timer_overflow;
+ } while (hi_new != hi);
+}
+
+/*
+ * For short delays only. It will overflow after a few seconds.
+ */
+void udelay(unsigned long usec)
+{
+ unsigned long now, end;
+
+ now = sysreg_read(COUNT);
+
+ end = ((usec * (get_tbclk() / 10000)) + 50) / 100;
+ end += now;
+
+ while (now > end)
+ now = sysreg_read(COUNT);
+
+ while (now < end)
+ now = sysreg_read(COUNT);
+}
+
+static int set_interrupt_handler(unsigned int nr, void (*handler)(void),
+ unsigned int priority)
+{
+ unsigned long intpr;
+ unsigned long handler_addr = (unsigned long)handler;
+
+ if ((handler_addr & HANDLER_MASK) != handler_addr
+ || (priority & INTLEV_MASK) != priority)
+ return -EINVAL;
+
+ intpr = (handler_addr & HANDLER_MASK);
+ intpr |= (priority & INTLEV_MASK) << INTLEV_SHIFT;
+ writel(intpr, intc_dev->regs + 4 * nr);
+
+ return 0;
+}
+
+void timer_init(void)
+{
+ extern void timer_interrupt_handler(void);
+ u64 tmp;
+
+ sysreg_write(COUNT, 0);
+
+ tmp = (u64)CFG_HZ << 32;
+ tmp += gd->cpu_hz / 2;
+ do_div(tmp, gd->cpu_hz);
+ tb_factor = (u32)tmp;
+
+ intc_dev = get_device(DEVICE_INTC);
+
+ if (!intc_dev
+ || set_interrupt_handler(0, &timer_interrupt_handler, 3))
+ return;
+
+ /* For all practical purposes, this gives us an overflow interrupt */
+ sysreg_write(COMPARE, 0xffffffff);
+}
diff --git a/cpu/at32ap/pio.c b/cpu/at32ap/pio.c
new file mode 100644
index 0000000..8b6c3a3
--- /dev/null
+++ b/cpu/at32ap/pio.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+
+#include "pio2.h"
+
+struct pio_state {
+ const struct device *dev;
+ u32 alloc_mask;
+};
+
+static struct pio_state pio_state[CFG_NR_PIOS];
+
+int gpio_set_func(enum device_id gpio_devid, unsigned int start,
+ unsigned int nr_pins, enum gpio_func func)
+{
+ const struct device *gpio;
+ struct pio_state *state;
+ u32 mask;
+
+ state = &pio_state[gpio_devid - DEVICE_PIOA];
+
+ gpio = get_device(gpio_devid);
+ if (!gpio)
+ return -EBUSY;
+
+ state->dev = gpio;
+ mask = ((1 << nr_pins) - 1) << start;
+
+ if (mask & state->alloc_mask) {
+ put_device(gpio);
+ return -EBUSY;
+ }
+ state->alloc_mask |= mask;
+
+ switch (func) {
+ case GPIO_FUNC_GPIO:
+ /* TODO */
+ return -EINVAL;
+ case GPIO_FUNC_A:
+ pio2_writel(gpio, ASR, mask);
+ pio2_writel(gpio, PDR, mask);
+ pio2_writel(gpio, PUDR, mask);
+ break;
+ case GPIO_FUNC_B:
+ pio2_writel(gpio, BSR, mask);
+ pio2_writel(gpio, PDR, mask);
+ pio2_writel(gpio, PUDR, mask);
+ break;
+ }
+
+ return 0;
+}
+
+void gpio_free(enum device_id gpio_devid, unsigned int start,
+ unsigned int nr_pins)
+{
+ const struct device *gpio;
+ struct pio_state *state;
+ u32 mask;
+
+ state = &pio_state[gpio_devid - DEVICE_PIOA];
+ gpio = state->dev;
+ mask = ((1 << nr_pins) - 1) << start;
+
+ pio2_writel(gpio, ODR, mask);
+ pio2_writel(gpio, PER, mask);
+
+ state->alloc_mask &= ~mask;
+ put_device(gpio);
+}
diff --git a/cpu/at32ap/pio2.h b/cpu/at32ap/pio2.h
new file mode 100644
index 0000000..6b79de3
--- /dev/null
+++ b/cpu/at32ap/pio2.h
@@ -0,0 +1,44 @@
+/*
+ * Register definitions for Parallel Input/Output Controller
+ */
+#ifndef __CPU_AT32AP_PIO2_H__
+#define __CPU_AT32AP_PIO2_H__
+
+/* PIO2 register offsets */
+#define PIO2_PER 0x0000
+#define PIO2_PDR 0x0004
+#define PIO2_PSR 0x0008
+#define PIO2_OER 0x0010
+#define PIO2_ODR 0x0014
+#define PIO2_OSR 0x0018
+#define PIO2_IFER 0x0020
+#define PIO2_IFDR 0x0024
+#define PIO2_ISFR 0x0028
+#define PIO2_SODR 0x0030
+#define PIO2_CODR 0x0034
+#define PIO2_ODSR 0x0038
+#define PIO2_PDSR 0x003c
+#define PIO2_IER 0x0040
+#define PIO2_IDR 0x0044
+#define PIO2_IMR 0x0048
+#define PIO2_ISR 0x004c
+#define PIO2_MDER 0x0050
+#define PIO2_MDDR 0x0054
+#define PIO2_MDSR 0x0058
+#define PIO2_PUDR 0x0060
+#define PIO2_PUER 0x0064
+#define PIO2_PUSR 0x0068
+#define PIO2_ASR 0x0070
+#define PIO2_BSR 0x0074
+#define PIO2_ABSR 0x0078
+#define PIO2_OWER 0x00a0
+#define PIO2_OWDR 0x00a4
+#define PIO2_OWSR 0x00a8
+
+/* Register access macros */
+#define pio2_readl(port,reg) \
+ readl((port)->regs + PIO2_##reg)
+#define pio2_writel(port,reg,value) \
+ writel((value), (port)->regs + PIO2_##reg)
+
+#endif /* __CPU_AT32AP_PIO2_H__ */
diff --git a/cpu/at32ap/pm.c b/cpu/at32ap/pm.c
new file mode 100644
index 0000000..01ac325
--- /dev/null
+++ b/cpu/at32ap/pm.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <common.h>
+
+#ifdef CFG_POWER_MANAGER
+#include <asm/errno.h>
+#include <asm/io.h>
+
+#include <asm/arch/memory-map.h>
+#include <asm/arch/platform.h>
+
+#include "sm.h"
+
+/* Sanity checks */
+#if (CFG_CLKDIV_CPU > CFG_CLKDIV_HSB) \
+ || (CFG_CLKDIV_HSB > CFG_CLKDIV_PBA) \
+ || (CFG_CLKDIV_HSB > CFG_CLKDIV_PBB)
+# error Constraint fCPU >= fHSB >= fPB{A,B} violated
+#endif
+#if defined(CONFIG_PLL) && ((CFG_PLL0_MUL < 1) || (CFG_PLL0_DIV < 1))
+# error Invalid PLL multiplier and/or divider
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct clock_domain_state {
+ const struct device *bridge;
+ unsigned long freq;
+ u32 mask;
+};
+static struct clock_domain_state ckd_state[NR_CLOCK_DOMAINS];
+
+int pm_enable_clock(enum clock_domain_id id, unsigned int index)
+{
+ const struct clock_domain *ckd = &chip_clock[id];
+ struct clock_domain_state *state = &ckd_state[id];
+
+ if (ckd->bridge != NO_DEVICE) {
+ state->bridge = get_device(ckd->bridge);
+ if (!state->bridge)
+ return -EBUSY;
+ }
+
+ state->mask |= 1 << index;
+ if (gd->sm)
+ writel(state->mask, gd->sm->regs + ckd->reg);
+
+ return 0;
+}
+
+void pm_disable_clock(enum clock_domain_id id, unsigned int index)
+{
+ const struct clock_domain *ckd = &chip_clock[id];
+ struct clock_domain_state *state = &ckd_state[id];
+
+ state->mask &= ~(1 << index);
+ if (gd->sm)
+ writel(state->mask, gd->sm->regs + ckd->reg);
+
+ if (ckd->bridge)
+ put_device(state->bridge);
+}
+
+unsigned long pm_get_clock_freq(enum clock_domain_id domain)
+{
+ return ckd_state[domain].freq;
+}
+
+void pm_init(void)
+{
+ uint32_t cksel = 0;
+ unsigned long main_clock;
+
+ /* Make sure we don't disable any device we're already using */
+ get_device(DEVICE_HRAMC);
+ get_device(DEVICE_HEBI);
+
+ /* Enable the PICO as well */
+ ckd_state[CLOCK_CPU].mask |= 1;
+
+ gd->sm = get_device(DEVICE_SM);
+ if (!gd->sm)
+ panic("Unable to claim system manager device!\n");
+
+ /* Disable any devices that haven't been explicitly claimed */
+ sm_writel(gd->sm, PM_PBB_MASK, ckd_state[CLOCK_PBB].mask);
+ sm_writel(gd->sm, PM_PBA_MASK, ckd_state[CLOCK_PBA].mask);
+ sm_writel(gd->sm, PM_HSB_MASK, ckd_state[CLOCK_HSB].mask);
+ sm_writel(gd->sm, PM_CPU_MASK, ckd_state[CLOCK_CPU].mask);
+
+#ifdef CONFIG_PLL
+ /* Initialize the PLL */
+ main_clock = (CFG_OSC0_HZ / CFG_PLL0_DIV) * CFG_PLL0_MUL;
+
+ sm_writel(gd->sm, PM_PLL0, (SM_BF(PLLCOUNT, CFG_PLL0_SUPPRESS_CYCLES)
+ | SM_BF(PLLMUL, CFG_PLL0_MUL - 1)
+ | SM_BF(PLLDIV, CFG_PLL0_DIV - 1)
+ | SM_BF(PLLOPT, CFG_PLL0_OPT)
+ | SM_BF(PLLOSC, 0)
+ | SM_BIT(PLLEN)));
+
+ /* Wait for lock */
+ while (!(sm_readl(gd->sm, PM_ISR) & SM_BIT(LOCK0))) ;
+#else
+ main_clock = CFG_OSC0_HZ;
+#endif
+
+ /* Set up clocks for the CPU and all peripheral buses */
+ if (CFG_CLKDIV_CPU) {
+ cksel |= SM_BIT(CPUDIV) | SM_BF(CPUSEL, CFG_CLKDIV_CPU - 1);
+ ckd_state[CLOCK_CPU].freq = main_clock / (1 << CFG_CLKDIV_CPU);
+ } else {
+ ckd_state[CLOCK_CPU].freq = main_clock;
+ }
+ if (CFG_CLKDIV_HSB) {
+ cksel |= SM_BIT(HSBDIV) | SM_BF(HSBSEL, CFG_CLKDIV_HSB - 1);
+ ckd_state[CLOCK_HSB].freq = main_clock / (1 << CFG_CLKDIV_HSB);
+ } else {
+ ckd_state[CLOCK_HSB].freq = main_clock;
+ }
+ if (CFG_CLKDIV_PBA) {
+ cksel |= SM_BIT(PBADIV) | SM_BF(PBASEL, CFG_CLKDIV_PBA - 1);
+ ckd_state[CLOCK_PBA].freq = main_clock / (1 << CFG_CLKDIV_PBA);
+ } else {
+ ckd_state[CLOCK_PBA].freq = main_clock;
+ }
+ if (CFG_CLKDIV_PBB) {
+ cksel |= SM_BIT(PBBDIV) | SM_BF(PBBSEL, CFG_CLKDIV_PBB - 1);
+ ckd_state[CLOCK_PBB].freq = main_clock / (1 << CFG_CLKDIV_PBB);
+ } else {
+ ckd_state[CLOCK_PBB].freq = main_clock;
+ }
+ sm_writel(gd->sm, PM_CKSEL, cksel);
+
+ /* CFG_HZ currently depends on cpu_hz */
+ gd->cpu_hz = ckd_state[CLOCK_CPU].freq;
+
+#ifdef CONFIG_PLL
+ /* Use PLL0 as main clock */
+ sm_writel(gd->sm, PM_MCCTRL, SM_BIT(PLLSEL));
+#endif
+}
+
+#endif /* CFG_POWER_MANAGER */
diff --git a/cpu/at32ap/sm.h b/cpu/at32ap/sm.h
new file mode 100644
index 0000000..ce81ef0
--- /dev/null
+++ b/cpu/at32ap/sm.h
@@ -0,0 +1,204 @@
+/*
+ * Register definitions for System Manager
+ */
+#ifndef __CPU_AT32AP_SM_H__
+#define __CPU_AT32AP_SM_H__
+
+/* SM register offsets */
+#define SM_PM_MCCTRL 0x0000
+#define SM_PM_CKSEL 0x0004
+#define SM_PM_CPU_MASK 0x0008
+#define SM_PM_HSB_MASK 0x000c
+#define SM_PM_PBA_MASK 0x0010
+#define SM_PM_PBB_MASK 0x0014
+#define SM_PM_PLL0 0x0020
+#define SM_PM_PLL1 0x0024
+#define SM_PM_VCTRL 0x0030
+#define SM_PM_VMREF 0x0034
+#define SM_PM_VMV 0x0038
+#define SM_PM_IER 0x0040
+#define SM_PM_IDR 0x0044
+#define SM_PM_IMR 0x0048
+#define SM_PM_ISR 0x004c
+#define SM_PM_ICR 0x0050
+#define SM_PM_GCCTRL 0x0060
+#define SM_RTC_CTRL 0x0080
+#define SM_RTC_VAL 0x0084
+#define SM_RTC_TOP 0x0088
+#define SM_RTC_IER 0x0090
+#define SM_RTC_IDR 0x0094
+#define SM_RTC_IMR 0x0098
+#define SM_RTC_ISR 0x009c
+#define SM_RTC_ICR 0x00a0
+#define SM_WDT_CTRL 0x00b0
+#define SM_WDT_CLR 0x00b4
+#define SM_WDT_EXT 0x00b8
+#define SM_RC_RCAUSE 0x00c0
+#define SM_EIM_IER 0x0100
+#define SM_EIM_IDR 0x0104
+#define SM_EIM_IMR 0x0108
+#define SM_EIM_ISR 0x010c
+#define SM_EIM_ICR 0x0110
+#define SM_EIM_MODE 0x0114
+#define SM_EIM_EDGE 0x0118
+#define SM_EIM_LEVEL 0x011c
+#define SM_EIM_TEST 0x0120
+#define SM_EIM_NMIC 0x0124
+
+/* Bitfields in PM_CKSEL */
+#define SM_CPUSEL_OFFSET 0
+#define SM_CPUSEL_SIZE 3
+#define SM_CPUDIV_OFFSET 7
+#define SM_CPUDIV_SIZE 1
+#define SM_HSBSEL_OFFSET 8
+#define SM_HSBSEL_SIZE 3
+#define SM_HSBDIV_OFFSET 15
+#define SM_HSBDIV_SIZE 1
+#define SM_PBASEL_OFFSET 16
+#define SM_PBASEL_SIZE 3
+#define SM_PBADIV_OFFSET 23
+#define SM_PBADIV_SIZE 1
+#define SM_PBBSEL_OFFSET 24
+#define SM_PBBSEL_SIZE 3
+#define SM_PBBDIV_OFFSET 31
+#define SM_PBBDIV_SIZE 1
+
+/* Bitfields in PM_PLL0 */
+#define SM_PLLEN_OFFSET 0
+#define SM_PLLEN_SIZE 1
+#define SM_PLLOSC_OFFSET 1
+#define SM_PLLOSC_SIZE 1
+#define SM_PLLOPT_OFFSET 2
+#define SM_PLLOPT_SIZE 3
+#define SM_PLLDIV_OFFSET 8
+#define SM_PLLDIV_SIZE 8
+#define SM_PLLMUL_OFFSET 16
+#define SM_PLLMUL_SIZE 8
+#define SM_PLLCOUNT_OFFSET 24
+#define SM_PLLCOUNT_SIZE 6
+#define SM_PLLTEST_OFFSET 31
+#define SM_PLLTEST_SIZE 1
+
+/* Bitfields in PM_VCTRL */
+#define SM_VAUTO_OFFSET 0
+#define SM_VAUTO_SIZE 1
+#define SM_PM_VCTRL_VAL_OFFSET 8
+#define SM_PM_VCTRL_VAL_SIZE 7
+
+/* Bitfields in PM_VMREF */
+#define SM_REFSEL_OFFSET 0
+#define SM_REFSEL_SIZE 4
+
+/* Bitfields in PM_VMV */
+#define SM_PM_VMV_VAL_OFFSET 0
+#define SM_PM_VMV_VAL_SIZE 8
+
+/* Bitfields in PM_ICR */
+#define SM_LOCK0_OFFSET 0
+#define SM_LOCK0_SIZE 1
+#define SM_LOCK1_OFFSET 1
+#define SM_LOCK1_SIZE 1
+#define SM_WAKE_OFFSET 2
+#define SM_WAKE_SIZE 1
+#define SM_VOK_OFFSET 3
+#define SM_VOK_SIZE 1
+#define SM_VMRDY_OFFSET 4
+#define SM_VMRDY_SIZE 1
+#define SM_CKRDY_OFFSET 5
+#define SM_CKRDY_SIZE 1
+
+/* Bitfields in PM_GCCTRL */
+#define SM_OSCSEL_OFFSET 0
+#define SM_OSCSEL_SIZE 1
+#define SM_PLLSEL_OFFSET 1
+#define SM_PLLSEL_SIZE 1
+#define SM_CEN_OFFSET 2
+#define SM_CEN_SIZE 1
+#define SM_CPC_OFFSET 3
+#define SM_CPC_SIZE 1
+#define SM_DIVEN_OFFSET 4
+#define SM_DIVEN_SIZE 1
+#define SM_DIV_OFFSET 8
+#define SM_DIV_SIZE 8
+
+/* Bitfields in RTC_CTRL */
+#define SM_PCLR_OFFSET 1
+#define SM_PCLR_SIZE 1
+#define SM_TOPEN_OFFSET 2
+#define SM_TOPEN_SIZE 1
+#define SM_CLKEN_OFFSET 3
+#define SM_CLKEN_SIZE 1
+#define SM_PSEL_OFFSET 8
+#define SM_PSEL_SIZE 16
+
+/* Bitfields in RTC_VAL */
+#define SM_RTC_VAL_VAL_OFFSET 0
+#define SM_RTC_VAL_VAL_SIZE 31
+
+/* Bitfields in RTC_TOP */
+#define SM_RTC_TOP_VAL_OFFSET 0
+#define SM_RTC_TOP_VAL_SIZE 32
+
+/* Bitfields in RTC_ICR */
+#define SM_TOPI_OFFSET 0
+#define SM_TOPI_SIZE 1
+
+/* Bitfields in WDT_CTRL */
+#define SM_KEY_OFFSET 24
+#define SM_KEY_SIZE 8
+
+/* Bitfields in RC_RCAUSE */
+#define SM_POR_OFFSET 0
+#define SM_POR_SIZE 1
+#define SM_BOD_OFFSET 1
+#define SM_BOD_SIZE 1
+#define SM_EXT_OFFSET 2
+#define SM_EXT_SIZE 1
+#define SM_WDT_OFFSET 3
+#define SM_WDT_SIZE 1
+#define SM_NTAE_OFFSET 4
+#define SM_NTAE_SIZE 1
+#define SM_SERP_OFFSET 5
+#define SM_SERP_SIZE 1
+
+/* Bitfields in EIM_EDGE */
+#define SM_INT0_OFFSET 0
+#define SM_INT0_SIZE 1
+#define SM_INT1_OFFSET 1
+#define SM_INT1_SIZE 1
+#define SM_INT2_OFFSET 2
+#define SM_INT2_SIZE 1
+#define SM_INT3_OFFSET 3
+#define SM_INT3_SIZE 1
+
+/* Bitfields in EIM_LEVEL */
+
+/* Bitfields in EIM_TEST */
+#define SM_TESTEN_OFFSET 31
+#define SM_TESTEN_SIZE 1
+
+/* Bitfields in EIM_NMIC */
+#define SM_EN_OFFSET 0
+#define SM_EN_SIZE 1
+
+/* Bit manipulation macros */
+#define SM_BIT(name) \
+ (1 << SM_##name##_OFFSET)
+#define SM_BF(name,value) \
+ (((value) & ((1 << SM_##name##_SIZE) - 1)) \
+ << SM_##name##_OFFSET)
+#define SM_BFEXT(name,value) \
+ (((value) >> SM_##name##_OFFSET) \
+ & ((1 << SM_##name##_SIZE) - 1))
+#define SM_BFINS(name,value,old) \
+ (((old) & ~(((1 << SM_##name##_SIZE) - 1) \
+ << SM_##name##_OFFSET)) \
+ | SM_BF(name,value))
+
+/* Register access macros */
+#define sm_readl(port,reg) \
+ readl((port)->regs + SM_##reg)
+#define sm_writel(port,reg,value) \
+ writel((value), (port)->regs + SM_##reg)
+
+#endif /* __CPU_AT32AP_SM_H__ */
diff --git a/cpu/at32ap/start.S b/cpu/at32ap/start.S
new file mode 100644
index 0000000..79ee33b
--- /dev/null
+++ b/cpu/at32ap/start.S
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <config.h>
+#include <asm/sysreg.h>
+
+#ifndef PART_SPECIFIC_BOOTSTRAP
+# define PART_SPECIFIC_BOOTSTRAP
+#endif
+
+#define SYSREG_MMUCR_I_OFFSET 2
+#define SYSREG_MMUCR_S_OFFSET 4
+
+#define SR_INIT (SYSREG_BIT(GM) | SYSREG_BIT(EM) | SYSREG_BIT(M0))
+#define CPUCR_INIT (SYSREG_BIT(BI) | SYSREG_BIT(BE) \
+ | SYSREG_BIT(FE) | SYSREG_BIT(RE) \
+ | SYSREG_BIT(IBE) | SYSREG_BIT(IEE))
+
+ .text
+ .global _start
+_start:
+ PART_SPECIFIC_BOOTSTRAP
+
+ /* Reset the Status Register */
+ mov r0, lo(SR_INIT)
+ orh r0, hi(SR_INIT)
+ mtsr SYSREG_SR, r0
+
+ /* Reset CPUCR and invalidate the BTB */
+ mov r2, CPUCR_INIT
+ mtsr SYSREG_CPUCR, r2
+
+ /* Flush the caches */
+ mov r1, 0
+ cache r1[4], 8
+ cache r1[0], 0
+ sync 0
+
+ /* Reset the MMU to default settings */
+ mov r0, SYSREG_BIT(MMUCR_S) | SYSREG_BIT(MMUCR_I)
+ mtsr SYSREG_MMUCR, r0
+
+ /* Internal RAM should not need any initialization. We might
+ have to initialize external RAM here if the part doesn't
+ have internal RAM (or we may use the data cache) */
+
+ /* Jump to cacheable segment */
+ lddpc pc, 1f
+
+ .align 2
+1: .long 2f
+
+2: lddpc sp, sp_init
+
+ /*
+ * Relocate the data section and initialize .bss. Everything
+ * is guaranteed to be at least doubleword aligned by the
+ * linker script.
+ */
+ lddpc r12, .Ldata_vma
+ lddpc r11, .Ldata_lma
+ lddpc r10, .Ldata_end
+ sub r10, r12
+4: ld.d r8, r11++
+ sub r10, 8
+ st.d r12++, r8
+ brne 4b
+
+ mov r8, 0
+ mov r9, 0
+ lddpc r10, .Lbss_end
+ sub r10, r12
+4: sub r10, 8
+ st.d r12++, r8
+ brne 4b
+
+ /* Initialize the GOT pointer */
+ lddpc r6, got_init
+3: rsub r6, pc
+ ld.w pc, r6[start_u_boot@got]
+
+ .align 2
+ .type sp_init,@object
+sp_init:
+ .long CFG_INIT_SP_ADDR
+got_init:
+ .long 3b - _GLOBAL_OFFSET_TABLE_
+.Ldata_lma:
+ .long __data_lma
+.Ldata_vma:
+ .long _data
+.Ldata_end:
+ .long _edata
+.Lbss_end:
+ .long _end