initial commit of lk (little kernel) project
diff --git a/platform/armemu/debug.c b/platform/armemu/debug.c
new file mode 100644
index 0000000..aca3931
--- /dev/null
+++ b/platform/armemu/debug.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <platform/armemu/memmap.h>
+#include <platform/debug.h>
+
+void dputc(char c)
+{
+ *REG8(DEBUG_STDOUT) = c;
+}
+
+int dgetc(char *c)
+{
+ int8_t result = (int8_t)*REG8(DEBUG_STDIN);
+
+ if (result == -1)
+ return -1;
+
+ *c = (char)result;
+ return 0;
+}
+
+void debug_dump_regs(void)
+{
+ *REG32(DEBUG_REGDUMP) = 1;
+}
+
+void debug_halt(void)
+{
+ *REG32(DEBUG_HALT) = 1;
+ for(;;);
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+ *REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
+ *REG32(DEBUG_MEMDUMPLEN) = len;
+ *REG32(DEBUG_MEMDUMP_BYTE) = 1;
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+ len /= 2;
+
+ *REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
+ *REG32(DEBUG_MEMDUMPLEN) = len;
+ *REG32(DEBUG_MEMDUMP_HALFWORD) = 1;
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+ len /= 4;
+
+ *REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
+ *REG32(DEBUG_MEMDUMPLEN) = len;
+ *REG32(DEBUG_MEMDUMP_WORD) = 1;
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+ if(trace_type < 0 || trace_type >= 4)
+ return;
+
+ *REG32(DEBUG_SET_TRACELEVEL_CPU + trace_type * 4) = level;
+}
+
+uint32_t debug_cycle_count()
+{
+ return *REG32(DEBUG_CYCLE_COUNT);
+}
diff --git a/platform/armemu/include/platform/armemu.h b/platform/armemu/include/platform/armemu.h
new file mode 100644
index 0000000..10b0d60
--- /dev/null
+++ b/platform/armemu/include/platform/armemu.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_ARMEMU_H
+#define __PLATFORM_ARMEMU_H
+
+#include <platform/armemu/memmap.h>
+
+#endif
+
diff --git a/platform/armemu/include/platform/armemu/memmap.h b/platform/armemu/include/platform/armemu/memmap.h
new file mode 100644
index 0000000..9df4e0b
--- /dev/null
+++ b/platform/armemu/include/platform/armemu/memmap.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2005-2006 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __MEMMAP_H
+#define __MEMMAP_H
+
+#define MEMBANK_SIZE (4*1024*1024)
+
+/* some helpful macros */
+#define REG(x) ((volatile unsigned int *)(x))
+#define REG_H(x) ((volatile unsigned short *)(x))
+#define REG_B(x) ((volatile unsigned char *)(x))
+
+/* memory map of our generic arm system */
+// XXX make more dynamic
+#define MAINMEM_BASE 0x0
+#define MAINMEM_SIZE (MEMBANK_SIZE)
+
+/* peripherals are all mapped here */
+#define PERIPHERAL_BASE (0xf0000000)
+
+/* system info */
+#define SYSINFO_REGS_BASE (PERIPHERAL_BASE)
+#define SYSINFO_REGS_SIZE MEMBANK_SIZE
+#define SYSINFO_FEATURES (SYSINFO_REGS_BASE + 0)
+#define SYSINFO_FEATURE_DISPLAY 0x00000001
+#define SYSINFO_FEATURE_CONSOLE 0x00000002
+#define SYSINFO_FEATURE_NETWORK 0x00000004
+
+ /* a write to this register latches the current emulator system time, so the next two regs can be read atomically */
+#define SYSINFO_TIME_LATCH (SYSINFO_REGS_BASE + 4)
+ /* gettimeofday() style time values */
+#define SYSINFO_TIME_SECS (SYSINFO_REGS_BASE + 8)
+#define SYSINFO_TIME_USECS (SYSINFO_REGS_BASE + 12)
+
+/* display */
+#define DISPLAY_BASE (SYSINFO_REGS_BASE + SYSINFO_REGS_SIZE)
+#define DISPLAY_SIZE MEMBANK_SIZE
+#define DISPLAY_FRAMEBUFFER DISPLAY_BASE
+#define DISPLAY_REGS_BASE (DISPLAY_BASE + DISPLAY_SIZE)
+#define DISPLAY_REGS_SIZE MEMBANK_SIZE
+ /* no display regs for now */
+
+/* console (keyboard controller */
+#define CONSOLE_REGS_BASE (DISPLAY_REGS_BASE + DISPLAY_REGS_SIZE)
+#define CONSOLE_REGS_SIZE MEMBANK_SIZE
+#define KYBD_STAT (CONSOLE_REGS_BASE + 0)
+#define KYBD_DATA (CONSOLE_REGS_BASE + 4)
+
+/* programmable timer */
+#define PIT_REGS_BASE (CONSOLE_REGS_BASE + CONSOLE_REGS_SIZE)
+#define PIT_REGS_SIZE MEMBANK_SIZE
+#define PIT_STATUS (PIT_REGS_BASE + 0) // status bit
+#define PIT_CLEAR (PIT_REGS_BASE + 4) // a nonzero write clears any pending timer
+#define PIT_CLEAR_INT (PIT_REGS_BASE + 8) // a nonzero write clears the pending interrupt
+#define PIT_INTERVAL (PIT_REGS_BASE + 12) // set the countdown interval, and what the interval is reset to if periodic
+#define PIT_START_ONESHOT (PIT_REGS_BASE + 16) // a nonzero write starts a oneshot countdown
+#define PIT_START_PERIODIC (PIT_REGS_BASE + 20) // a nonzero write starts a periodic countdown
+
+#define PIT_STATUS_ACTIVE 0x1
+#define PIT_STATUS_INT_PEND 0x2
+
+/* interrupt controller */
+#define PIC_REGS_BASE (PIT_REGS_BASE + PIT_REGS_SIZE)
+#define PIC_REGS_SIZE MEMBANK_SIZE
+
+ /* Current vector mask, read-only */
+#define PIC_MASK (PIC_REGS_BASE + 0)
+ /* Mask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
+#define PIC_MASK_LATCH (PIC_REGS_BASE + 4)
+ /* Unmask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
+#define PIC_UNMASK_LATCH (PIC_REGS_BASE + 8)
+ /* each bit corresponds to the current status of the interrupt line */
+#define PIC_STAT (PIC_REGS_BASE + 12)
+ /* one bit set for the highest priority non-masked active interrupt */
+#define PIC_CURRENT_BIT (PIC_REGS_BASE + 16)
+ /* holds the current interrupt number of the highest priority non-masked active interrupt,
+ * or 0xffffffff if no interrupt is active
+ */
+#define PIC_CURRENT_NUM (PIC_REGS_BASE + 20)
+
+ /* interrupt map */
+#define INT_PIT 0
+#define INT_KEYBOARD 1
+#define INT_NET 2
+#define PIC_MAX_INT 32
+
+/* debug interface */
+#define DEBUG_REGS_BASE (PIC_REGS_BASE + PIC_REGS_SIZE)
+#define DEBUG_REGS_SIZE MEMBANK_SIZE
+#define DEBUG_STDOUT (DEBUG_REGS_BASE + 0) /* writes to this register are sent through to stdout */
+#define DEBUG_STDIN (DEBUG_REGS_BASE + 0) /* reads from this register return the contents of stdin
+ * or -1 if no data is pending */
+#define DEBUG_REGDUMP (DEBUG_REGS_BASE + 4) /* writes to this register cause the emulator to dump registers */
+#define DEBUG_HALT (DEBUG_REGS_BASE + 8) /* writes to this register will halt the emulator */
+
+#define DEBUG_MEMDUMPADDR (DEBUG_REGS_BASE + 12) /* set the base address of memory to dump */
+#define DEBUG_MEMDUMPLEN (DEBUG_REGS_BASE + 16) /* set the length of memory to dump */
+#define DEBUG_MEMDUMP_BYTE (DEBUG_REGS_BASE + 20) /* trigger a memory dump in byte format */
+#define DEBUG_MEMDUMP_HALFWORD (DEBUG_REGS_BASE + 24) /* trigger a memory dump in halfword format */
+#define DEBUG_MEMDUMP_WORD (DEBUG_REGS_BASE + 28) /* trigger a memory dump in word format */
+
+/* lets you set the trace level of the various subsystems from within the emulator */
+/* only works on emulator builds that support dynamic trace levels */
+#define DEBUG_SET_TRACELEVEL_CPU (DEBUG_REGS_BASE + 32)
+#define DEBUG_SET_TRACELEVEL_UOP (DEBUG_REGS_BASE + 36)
+#define DEBUG_SET_TRACELEVEL_SYS (DEBUG_REGS_BASE + 40)
+#define DEBUG_SET_TRACELEVEL_MMU (DEBUG_REGS_BASE + 44)
+
+#define DEBUG_CYCLE_COUNT (DEBUG_REGS_BASE + 48)
+#define DEBUG_INS_COUNT (DEBUG_REGS_BASE + 52)
+
+/* network interface */
+#define NET_REGS_BASE (DEBUG_REGS_BASE + DEBUG_REGS_SIZE)
+#define NET_REGS_SIZE MEMBANK_SIZE
+
+#define NET_BUF_LEN 2048
+#define NET_IN_BUF_COUNT 32
+
+#define NET_HEAD (NET_REGS_BASE + 0) /* current next buffer the hardware will write to */
+#define NET_TAIL (NET_REGS_BASE + 4) /* currently selected input buffer */
+#define NET_SEND (NET_REGS_BASE + 8) /* writes to this register sends whatever is in the out buf */
+#define NET_SEND_LEN (NET_REGS_BASE + 12) /* length of packet to send */
+#define NET_OUT_BUF (NET_REGS_BASE + NET_BUF_LEN)
+
+#define NET_IN_BUF_LEN (NET_REGS_BASE + 16) /* length of the currently selected in buffer, via tail register */
+#define NET_IN_BUF (NET_REGS_BASE + NET_BUF_LEN*2)
+
+#endif
diff --git a/platform/armemu/interrupts.c b/platform/armemu/interrupts.c
new file mode 100644
index 0000000..604d2dc
--- /dev/null
+++ b/platform/armemu/interrupts.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <sys/types.h>
+#include <debug.h>
+#include <reg.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <platform/armemu.h>
+#include <arch/ops.h>
+#include <arch/arm.h>
+#include "platform_p.h"
+
+struct int_handler_struct {
+ int_handler handler;
+ void *arg;
+};
+
+static struct int_handler_struct int_handler_table[PIC_MAX_INT];
+
+void platform_init_interrupts(void)
+{
+ // mask all the interrupts
+ *REG32(PIC_MASK_LATCH) = 0xffffffff;
+}
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+ if (vector >= PIC_MAX_INT)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = *REG32(PIC_MASK) & (1<<vector);
+ *REG32(PIC_MASK_LATCH) = 1 << vector;
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+ if (vector >= PIC_MAX_INT)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = *REG32(PIC_MASK) & (1<<vector);
+ *REG32(PIC_UNMASK_LATCH) = 1 << vector;
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+enum handler_return platform_irq(struct arm_iframe *frame)
+{
+ // get the current vector
+ unsigned int vector = *REG32(PIC_CURRENT_NUM);
+ if (vector == 0xffffffff)
+ return INT_NO_RESCHEDULE;
+
+// dprintf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector);
+
+ // deliver the interrupt
+ enum handler_return ret;
+
+ ret = INT_NO_RESCHEDULE;
+ if (int_handler_table[vector].handler)
+ ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
+
+// dprintf("platform_irq: exit %d\n", ret);
+
+ return ret;
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+ panic("FIQ: unimplemented\n");
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+ if (vector >= PIC_MAX_INT)
+ panic("register_int_handler: vector out of range %d\n", vector);
+
+ enter_critical_section();
+
+ int_handler_table[vector].handler = handler;
+ int_handler_table[vector].arg = arg;
+
+ exit_critical_section();
+}
+
diff --git a/platform/armemu/net.c b/platform/armemu/net.c
new file mode 100644
index 0000000..e27d321
--- /dev/null
+++ b/platform/armemu/net.c
@@ -0,0 +1,398 @@
+#if WITH_LWIP
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/*
+ * This file is a skeleton for developing Ethernet network interface
+ * drivers for lwIP. Add code to the low_level functions and do a
+ * search-and-replace for the word "ethernetif" to replace it with
+ * something that better describes your network interface.
+ */
+/*
+ * ARMEMU bits
+ * Copyright (c) 2006 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <malloc.h>
+#include <dev/ethernet.h>
+#include <err.h>
+#include <reg.h>
+#include <string.h>
+#include <platform/interrupts.h>
+#include <platform/armemu/memmap.h>
+
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+#include <lwip/stats.h>
+
+#include "netif/etharp.h"
+
+/* Define those to better describe your network interface. */
+#define IFNAME0 'e'
+#define IFNAME1 'n'
+
+struct ethernetif {
+ struct eth_addr *ethaddr;
+ /* Add whatever per-interface state that is needed here. */
+};
+
+static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
+
+/* Forward declarations. */
+static void ethernetif_input(struct netif *netif);
+static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr);
+
+static void
+low_level_init(struct netif *netif)
+{
+ struct ethernetif *ethernetif = netif->state;
+
+ /* set MAC hardware address length */
+ netif->hwaddr_len = 6;
+
+ /* set MAC hardware address */
+ netif->hwaddr[0] = 0;
+ netif->hwaddr[1] = 0x01;
+ netif->hwaddr[2] = 0x02;
+ netif->hwaddr[3] = 0x03;
+ netif->hwaddr[4] = 0x04;
+ netif->hwaddr[5] = 0x05;
+
+ /* maximum transfer unit */
+ netif->mtu = 1500;
+
+ /* broadcast capability */
+ netif->flags = NETIF_FLAG_BROADCAST;
+
+ /* Do whatever else is needed to initialize interface. */
+}
+
+/*
+ * low_level_output():
+ *
+ * Should do the actual transmission of the packet. The packet is
+ * contained in the pbuf that is passed to the function. This pbuf
+ * might be chained.
+ *
+ */
+
+static err_t
+low_level_output(struct netif *netif, struct pbuf *p)
+{
+ struct ethernetif *ethernetif = netif->state;
+ struct pbuf *q;
+ int i;
+ int j;
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* XXX maybe just a mutex? */
+ enter_critical_section();
+
+ i = 0;
+ for(q = p; q != NULL; q = q->next) {
+ /* Send the data from the pbuf to the interface, one pbuf at a
+ time. The size of the data in each pbuf is kept in the ->len
+ variable. */
+// debug_dump_memory_bytes(q->payload, q->len);
+ for (j = 0; j < q->len; j++)
+ *REG8(NET_OUT_BUF + i + j) = ((unsigned char *)q->payload)[j];
+ i += q->len;
+ }
+
+ *REG(NET_SEND_LEN) = i;
+ *REG(NET_SEND) = 1;
+
+ exit_critical_section();
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+#if LINK_STATS
+ lwip_stats.link.xmit++;
+#endif /* LINK_STATS */
+
+ return ERR_OK;
+}
+
+/*
+ * low_level_input():
+ *
+ * Should allocate a pbuf and transfer the bytes of the incoming
+ * packet from the interface into the pbuf.
+ *
+ */
+
+static struct pbuf *
+low_level_input(struct netif *netif)
+{
+ struct ethernetif *ethernetif = netif->state;
+ struct pbuf *p, *q;
+ u16_t len;
+ int i;
+ int head, tail;
+
+ /* get the head and tail pointers from the ethernet interface */
+ head = *REG(NET_HEAD);
+ tail = *REG(NET_TAIL);
+
+ if (tail == head)
+ return NULL; // false alarm
+
+ /* Obtain the size of the packet and put it into the "len"
+ variable. */
+ len = *REG(NET_IN_BUF_LEN);
+
+#if ETH_PAD_SIZE
+ len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
+#endif
+
+ /* We allocate a pbuf chain of pbufs from the pool. */
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (p != NULL) {
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* We iterate over the pbuf chain until we have read the entire
+ * packet into the pbuf. */
+ int pos = 0;
+ for(q = p; q != NULL; q = q->next) {
+ /* Read enough bytes to fill this pbuf in the chain. The
+ * available data in the pbuf is given by the q->len
+ * variable. */
+ for (i=0; i < q->len; i++) {
+ ((unsigned char *)q->payload)[i] = *REG8(NET_IN_BUF + pos);
+ pos++;
+ }
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+#if LINK_STATS
+ lwip_stats.link.recv++;
+#endif /* LINK_STATS */
+ } else {
+#if LINK_STATS
+ lwip_stats.link.memerr++;
+ lwip_stats.link.drop++;
+#endif /* LINK_STATS */
+ }
+
+ /* push the tail pointer up by one, giving the buffer back to the hardware */
+ *REG(NET_TAIL) = (tail + 1) % NET_IN_BUF_COUNT;
+
+ return p;
+}
+
+/*
+ * ethernetif_output():
+ *
+ * This function is called by the TCP/IP stack when an IP packet
+ * should be sent. It calls the function called low_level_output() to
+ * do the actual transmission of the packet.
+ *
+ */
+
+static err_t
+ethernetif_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr)
+{
+// dprintf("ethernetif_output: netif %p, pbuf %p, ipaddr %p\n", netif, p, ipaddr);
+
+ /* resolve hardware address, then send (or queue) packet */
+ return etharp_output(netif, ipaddr, p);
+
+}
+
+/*
+ * ethernetif_input():
+ *
+ * This function should be called when a packet is ready to be read
+ * from the interface. It uses the function low_level_input() that
+ * should handle the actual reception of bytes from the network
+ * interface.
+ *
+ */
+
+static void
+ethernetif_input(struct netif *netif)
+{
+ struct ethernetif *ethernetif;
+ struct eth_hdr *ethhdr;
+ struct pbuf *p;
+
+ ethernetif = netif->state;
+
+ /* move received packet into a new pbuf */
+ p = low_level_input(netif);
+ /* no packet could be read, silently ignore this */
+ if (p == NULL) return;
+ /* points to packet payload, which starts with an Ethernet header */
+ ethhdr = p->payload;
+
+#if LINK_STATS
+ lwip_stats.link.recv++;
+#endif /* LINK_STATS */
+
+ ethhdr = p->payload;
+
+// dprintf("ethernetif_input: type 0x%x\n", htons(ethhdr->type));
+
+ switch (htons(ethhdr->type)) {
+ /* IP packet? */
+ case ETHTYPE_IP:
+ /* update ARP table */
+ etharp_ip_input(netif, p);
+ /* skip Ethernet header */
+ pbuf_header(p, -sizeof(struct eth_hdr));
+ /* pass to network layer */
+ netif->input(p, netif);
+ break;
+
+ case ETHTYPE_ARP:
+ /* pass p to ARP module */
+ etharp_arp_input(netif, ethernetif->ethaddr, p);
+ break;
+ default:
+ pbuf_free(p);
+ p = NULL;
+ break;
+ }
+}
+
+static enum handler_return ethernet_int(void *arg)
+{
+ struct netif *netif = (struct netif *)arg;
+
+ ethernetif_input(netif);
+
+ return INT_RESCHEDULE;
+}
+
+
+
+/*
+ * ethernetif_init():
+ *
+ * Should be called at the beginning of the program to set up the
+ * network interface. It calls the function low_level_init() to do the
+ * actual setup of the hardware.
+ *
+ */
+
+static err_t
+ethernetif_init(struct netif *netif)
+{
+ struct ethernetif *ethernetif;
+
+ ethernetif = mem_malloc(sizeof(struct ethernetif));
+
+ if (ethernetif == NULL)
+ {
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
+ return ERR_MEM;
+ }
+
+ netif->state = ethernetif;
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = ethernetif_output;
+ netif->linkoutput = low_level_output;
+
+ ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
+
+ low_level_init(netif);
+
+ return ERR_OK;
+}
+
+status_t ethernet_init(void)
+{
+ /* check to see if the ethernet feature is turned on */
+ if ((*REG(SYSINFO_FEATURES) & SYSINFO_FEATURE_NETWORK) == 0)
+ return ERR_NOT_FOUND;
+
+ struct netif *netif = calloc(sizeof(struct netif), 1);
+ struct ip_addr *ipaddr = calloc(sizeof(struct ip_addr), 1);
+ struct ip_addr *netmask = calloc(sizeof(struct ip_addr), 1);
+ struct ip_addr *gw = calloc(sizeof(struct ip_addr), 1);
+
+ struct netif *netifret = netif_add(netif, ipaddr, netmask, gw, NULL, ðernetif_init, &ip_input);
+ if (netifret == NULL) {
+ free(netif);
+ free(ipaddr);
+ free(netmask);
+ free(gw);
+ return ERR_NOT_FOUND;
+ }
+
+ /* register for interrupt handlers */
+ register_int_handler(INT_NET, ethernet_int, netif);
+
+ netif_set_default(netif);
+
+ unmask_interrupt(INT_NET, NULL);
+
+ return NO_ERROR;
+}
+
+#endif // WITH_LWIP
diff --git a/platform/armemu/platform.c b/platform/armemu/platform.c
new file mode 100644
index 0000000..1425674
--- /dev/null
+++ b/platform/armemu/platform.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <debug.h>
+#include <platform.h>
+#include "platform_p.h"
+
+void platform_init_mmu_mappings(void)
+{
+}
+
+void platform_early_init(void)
+{
+ /* initialize the interrupt controller */
+ platform_init_interrupts();
+
+ /* initialize the timer block */
+ platform_init_timer();
+}
+
+void platform_init(void)
+{
+}
+
diff --git a/platform/armemu/platform_p.h b/platform/armemu/platform_p.h
new file mode 100644
index 0000000..872ea2b
--- /dev/null
+++ b/platform/armemu/platform_p.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_P_H
+#define __PLATFORM_P_H
+
+void platform_init_interrupts(void);
+void platform_init_timer(void);
+
+#endif
+
diff --git a/platform/armemu/rules.mk b/platform/armemu/rules.mk
new file mode 100644
index 0000000..f51b759
--- /dev/null
+++ b/platform/armemu/rules.mk
@@ -0,0 +1,28 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := arm926ej-s
+CPU := generic
+
+# emulater doesn't support thumb properly
+ENABLE_THUMB := false
+
+INCLUDES += \
+ -I$(LOCAL_DIR)/include
+
+OBJS += \
+ $(LOCAL_DIR)/debug.o \
+ $(LOCAL_DIR)/interrupts.o \
+ $(LOCAL_DIR)/net.o \
+ $(LOCAL_DIR)/platform.o \
+ $(LOCAL_DIR)/timer.o \
+
+
+# $(LOCAL_DIR)/console.o \
+
+MEMBASE := 0x0
+MEMSIZE := 0x400000 # 4MB
+
+LINKER_SCRIPT += \
+ $(BUILDDIR)/system-onesegment.ld
+
diff --git a/platform/armemu/timer.c b/platform/armemu/timer.c
new file mode 100644
index 0000000..770905b
--- /dev/null
+++ b/platform/armemu/timer.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <platform/armemu.h>
+#include "platform_p.h"
+
+static platform_timer_callback t_callback;
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+ enter_critical_section();
+
+ t_callback = callback;
+
+ *REG(PIT_CLEAR) = 1;
+ *REG(PIT_INTERVAL) = interval;
+ *REG(PIT_START_PERIODIC) = 1;
+
+ unmask_interrupt(INT_PIT, NULL);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+ time_t time;
+ *REG(SYSINFO_TIME_LATCH) = 1;
+ time = *REG(SYSINFO_TIME_SECS) * 1000;
+ time += *REG(SYSINFO_TIME_USECS) / 1000;
+
+ return time;
+}
+
+static enum handler_return platform_tick(void *arg)
+{
+ *REG(PIT_CLEAR_INT) = 1;
+ if (t_callback) {
+ return t_callback(arg, current_time());
+ } else {
+ return INT_NO_RESCHEDULE;
+ }
+}
+
+void platform_init_timer(void)
+{
+ register_int_handler(INT_PIT, &platform_tick, NULL);
+}
+
diff --git a/platform/at91sam7/README b/platform/at91sam7/README
new file mode 100644
index 0000000..41ce561
--- /dev/null
+++ b/platform/at91sam7/README
@@ -0,0 +1,15 @@
+
+Platform support for the ATMEL AT91SAM7[XS] ARM7 microcontrollers.
+
+This is a base platform -- it needs to be specialized for a particular
+board (see sam7ex256 as an example of this) to be useful. In particular
+it does not provide the platform/board.h (which must include the
+correct at91sam7*h file and mux config).
+
+TODO:
+- support clock rates other than (and above) 18MHz
+- compute uart divisor, PIT interval, etc from MCK
+- timer hook should honor the requested interval
+- current_time() should return a meaningful value
+- actually pass argument to interrupt handlers?
+
diff --git a/platform/at91sam7/at91sam7s.pins b/platform/at91sam7/at91sam7s.pins
new file mode 100644
index 0000000..e9c4474
--- /dev/null
+++ b/platform/at91sam7/at91sam7s.pins
@@ -0,0 +1,32 @@
+PA0 PWM0 TIOA0
+PA1 PWM1 TIOB0
+PA2 PWM2 SCK0
+PA3 TWD NPCS3
+PA4 TWCK TCLK0
+PA5 RXD0 NPCS3
+PA6 TXD0 PCK0
+PA7 RTS0 PWM3
+PA8 CTS0 ADTRG
+PA9 DRXD NPCS1
+PA10 DTXD NPCS2
+PA11 NPCS0 PWM0
+PA12 MISO PWM1
+PA13 MOSI PWM2
+PA14 SPCK PWM3
+PA15 TF TIOA1
+PA16 TK TIOB1
+PA17 TD PCK1
+PA18 RD PCK2
+PA19 RK FIQ
+PA20 RF IRQ0
+PA21 RXD1 PCK1
+PA22 TXD1 NPCS3
+PA23 SCK1 PWM0
+PA24 RTS1 PWM1
+PA25 CTS1 PWM2
+PA26 DCD1 TIOA2
+PA27 DTR1 TIOB2
+PA28 DSR1 TCLK1
+PA29 RI1 TCLK2
+PA30 IRQ1 NPCS2
+PA31 NPCS1 PCK2
\ No newline at end of file
diff --git a/platform/at91sam7/at91sam7x.pins b/platform/at91sam7/at91sam7x.pins
new file mode 100644
index 0000000..f026fb6
--- /dev/null
+++ b/platform/at91sam7/at91sam7x.pins
@@ -0,0 +1,31 @@
+PA0 RXD0 NC
+PA1 TXD0 NC
+PA2 SCK0 SPI1_NPCS1
+PA3 RTS0 SPI1_NPCS2
+PA4 CTS0 SPI1_NPCS3
+PA5 RXD1 NC
+PA6 TXD1 NC
+PA7 SCK1 SPI0_NPCS1
+PA8 RTS1 SPI0_NPCS2
+PA9 CTS1 SPI0_NPCS3
+PA10 TWD NC
+PA11 TWCK NC
+PA12 SPI0_NPCS0 NC
+PA13 SPI0_NPCS1 PCK1
+PA14 SPI0_NPCS2 IRQ1
+PA15 SPI0_NPCS3 TCLK2
+PA16 SPI0_MISO NC
+PA17 SPI0_MOSI NC
+PA18 SPI0_SPCK NC
+PA19 CANRX NC
+PA20 CANTX NC
+PA21 TF SPI1_NPCS0
+PA22 TK SPI1_SPCK
+PA23 TD SPI1_MOSI
+PA24 RD SPI1_MISO
+PA25 RK SPI1_NPCS1
+PA26 RF SPI1_NPCS2
+PA27 DRXD PCK3
+PA28 DTXD NC
+PA29 FIQ SPI1_NPCS3
+PA30 IRQ0 PCK2
diff --git a/platform/at91sam7/debug.c b/platform/at91sam7/debug.c
new file mode 100644
index 0000000..2cca7b3
--- /dev/null
+++ b/platform/at91sam7/debug.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <printf.h>
+#include <platform/at91sam7.h>
+#include <kernel/thread.h>
+#include <stdarg.h>
+
+void ser_init(void)
+{
+ AT91DBGU *dbgu = AT91DBGU_ADDR;
+
+// AT91PIO *pio = AT91PIO_ADDR;
+// pio->select_a = PIN_DRXD | PIN_DTXD;
+// pio->pio_disable = PIN_DRXD | PIN_DTXD;
+
+ dbgu->MR = DBGU_PAR_NONE | DBGU_MODE_NORMAL;
+ // dbgu->BRGR = 10; //MCK_IN_MHZ / 115200 / 16;
+ dbgu->BRGR = AT91_MCK_MHZ / 115200 / 16;
+ dbgu->CR = DBGU_RXEN | DBGU_TXEN;
+}
+
+void ser_putc(unsigned c)
+{
+ AT91DBGU *dbgu = AT91DBGU_ADDR;
+ if(c == 10) {
+ while(!(dbgu->SR & DBGU_TXRDY));
+ dbgu->THR = 13;
+ }
+ while(!(dbgu->SR & DBGU_TXRDY));
+ dbgu->THR = c;
+}
+
+void ser_puts(const char *s)
+{
+ AT91DBGU *dbgu = AT91DBGU_ADDR;
+ while(*s) {
+ if(*s == 10) {
+ while(!(dbgu->SR & DBGU_TXRDY));
+ dbgu->THR = 13;
+ }
+ while(!(dbgu->SR & DBGU_TXRDY));
+ dbgu->THR = *s++;
+ }
+}
+
+void dputc(char c)
+{
+ ser_putc(c);
+}
+
+void debug_halt()
+{
+ arch_disable_ints();
+ for(;;);
+}
+
+uint32_t debug_cycle_count()
+{
+ PANIC_UNIMPLEMENTED;
+}
diff --git a/platform/at91sam7/emac_dev.c b/platform/at91sam7/emac_dev.c
new file mode 100644
index 0000000..d042ef6
--- /dev/null
+++ b/platform/at91sam7/emac_dev.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <kernel/thread.h>
+#include <kernel/mutex.h>
+#include <platform/at91sam7.h>
+#include <platform/debug.h>
+
+#include <dev/ethernet.h>
+
+#include <malloc.h>
+#include <string.h>
+
+#include <hw/mii.h>
+
+void emac_init_send(void);
+
+#define PHYA 31
+
+static unsigned mi_rd(AT91EMAC *emac, unsigned addr)
+{
+ addr &= 0x1f;
+
+ thread_sleep(20);
+
+ emac->MAN =
+ (1 << 30) | /* sof: 01 */
+ (2 << 28) | /* rw: 10 = read */
+ (PHYA << 23) | /* phya: PHYA */
+ (addr << 18) | /* rega: addr */
+ (2 << 16); /* code: 10 */
+
+ while(!(emac->NSR & NSR_IDLE)) ;
+
+ thread_sleep(20);
+ return emac->MAN & 0xffff;
+}
+
+static void mi_wr(AT91EMAC *emac, unsigned addr, unsigned val)
+{
+ addr &= 0x1f;
+ val &= 0xffff;
+
+ emac->MAN =
+ (1 << 30) | /* sof: 01 */
+ (1 << 28) | /* rw: 01 = read */
+ (PHYA << 23) | /* phya: PHYA */
+ (addr << 18) | /* rega: addr */
+ (2 << 16) | /* code: 10 */
+ val; /* data: val */
+
+ while(!(emac->NSR & NSR_IDLE)) ;
+}
+
+#define PIN_EMAC_ALL 0x3ffff
+#define PIN_PHY_PD (1 << 18)
+#define PIN_PHY_IRQ (1 << 26)
+
+#define PIN_PHYAD0 (1 << 26)
+#define PIN_PHYAD1 (1 << 14)
+#define PIN_PHYAD2 (1 << 13)
+#define PIN_PHYAD3 (1 << 6)
+#define PIN_PHYAD4 (1 << 5)
+#define PIN_LPBK (1 << 15)
+#define PIN_ISOLATE (1 << 7)
+#define PIN_RMII_MODE (1 << 16)
+#define PIN_RMII_BTB (1 << 4)
+
+/* select RMII w/ BTB, 100mbps duplex autonegotiate
+** disable ISOLATE and LPBK
+** phya=00001b
+*/
+#define PIN_RESET_LOW (PIN_LPBK)
+
+int emac_init(void)
+{
+ AT91EMAC *emac = AT91EMAC_ADDR;
+ AT91PIO *piob = AT91PIOB_ADDR;
+ AT91PMC *pmc = AT91PMC_ADDR;
+ AT91RSTC *rstc = AT91RSTC_ADDR;
+
+ dprintf("emac_init()\n");
+
+ /* enable clock to EMAC */
+ pmc->PCER = (1 << PID_EMAC);
+
+ thread_sleep(10);
+
+ /* for reset, all lines are gpio inputs and pullups are
+ enabled or disabled per strapping mode defined above */
+ piob->pio_enable = PIN_EMAC_ALL | PIN_PHY_PD | PIN_PHY_IRQ;
+ piob->select_a = PIN_EMAC_ALL;
+ piob->pullup_enable = PIN_EMAC_ALL | PIN_PHY_IRQ;
+ piob->pullup_disable = PIN_LPBK | PIN_ISOLATE | PIN_RMII_MODE;
+ piob->output_disable = PIN_EMAC_ALL;
+
+ /* PHY PD becomes output and high (no powerdown mode */
+ piob->data_set = PIN_PHY_PD;
+ piob->output_enable = PIN_PHY_PD;
+
+ thread_sleep(30);
+
+ dprintf("emac_init() - reset phy\n");
+
+ /* assert the RST line and wait until the it deasserts */
+ rstc->CR = RSTC_KEY | RSTC_EXTRST;
+ while(rstc->SR & RSTC_NRSTL) ;
+
+ thread_sleep(30);
+
+ /* after reset all the gpios are assigned to the EMAC,
+ except for PHY_PD (which remains output and high) */
+ piob->pio_disable = PIN_EMAC_ALL;
+
+ emac->USRIO = USRIO_CLKEN;
+
+ thread_sleep(1000);
+
+ dprintf("emac_init() - read state\n");
+
+ emac->NCR = NCR_MPE;
+ emac->NCFG = NCFG_CLK_d64;
+
+ dprintf("bcr = %x\n", mi_rd(emac, MII_REG_BCR));
+ dprintf("id1 = %x\n", mi_rd(emac, MII_REG_PHY_ID1));
+ dprintf("id2 = %x\n", mi_rd(emac, MII_REG_PHY_ID2));
+
+#if 0
+ unsigned state, last;
+ last = 0xff;
+
+ for(;;) {
+ state = mi_rd(emac, MII_REG_100TX_PHY) & MII_100TX_MODE_MASK;
+ if(last != state) {
+ last = state;
+ char *name;
+ switch(state) {
+ case MII_100TX_MODE_AUTO:
+ name = "auto negotiate";
+ break;
+ case MII_100TX_MODE_10T_H:
+ name = "10-T half duplex";
+ break;
+ case MII_100TX_MODE_10T_F:
+ name = "10-T full duplex";
+ break;
+ case MII_100TX_MODE_100TX_H:
+ name = "100-TX half duplex";
+ break;
+ case MII_100TX_MODE_100TX_F:
+ name = "100-TX full duplex";
+ break;
+ case MII_100TX_MODE_ISOLATE:
+ name = "isolate";
+ break;
+ default:
+ name = "unknown";
+ }
+ dprintf("link state: %s\n", name);
+ }
+ thread_sleep(100);
+ }
+#endif
+
+ emac_init_send();
+
+ return 0;
+}
+
+#define XMIT_ENTRY_COUNT 32
+static emac_xmit_entry xmit_list[XMIT_ENTRY_COUNT];
+static unsigned xmit_next = 0;
+static mutex_t xmit_lock;
+
+void emac_init_send(void)
+{
+ AT91EMAC *emac = AT91EMAC_ADDR;
+ int i;
+
+ for(i = 0; i < XMIT_ENTRY_COUNT; i++) {
+ xmit_list[i].info = XMIT_USED;
+ xmit_list[i].addr = 0;
+ }
+ xmit_list[i-1].info |= XMIT_LAST;
+
+ emac->NCFG = NCFG_CLK_d64 | NCFG_SPD | NCFG_FD;
+ emac->NCR = NCR_TE | NCR_MPE;
+ emac->TBQP = (unsigned) xmit_list;
+
+ mutex_init(&xmit_lock);
+}
+
+int ethernet_send(void *data, unsigned len)
+{
+ AT91EMAC *emac = AT91EMAC_ADDR;
+
+ emac_xmit_entry *xe;
+ int waited = 0;
+
+ mutex_acquire(&xmit_lock);
+
+ xe = xmit_list + xmit_next;
+
+ while(!(xe->info & XMIT_USED)) {
+ thread_yield();
+ waited++;
+ }
+
+ if(waited) dprintf("W%d\n",waited);
+
+ if(xe->addr != 0) {
+ free((void*) xe->addr);
+ }
+
+ xe->addr = (unsigned) data;
+ if(xmit_next == (XMIT_ENTRY_COUNT - 1)) {
+ xe->info = XMIT_LENGTH(len) | XMIT_LAST | XMIT_WRAP;
+ xmit_next = 0;
+ } else {
+ xe->info = XMIT_LENGTH(len) | XMIT_LAST;
+ xmit_next++;
+ }
+
+ emac->NCR |= NCR_TSTART;
+
+ mutex_release(&xmit_lock);
+
+ return 0;
+}
+
diff --git a/platform/at91sam7/include/platform/at91sam7.h b/platform/at91sam7/include/platform/at91sam7.h
new file mode 100644
index 0000000..cd5a50f
--- /dev/null
+++ b/platform/at91sam7/include/platform/at91sam7.h
@@ -0,0 +1,794 @@
+/* at91sam7s.h -- AT91SAM7S hardware definitions
+**
+** Copyright 2006, Brian Swetland. All rights reserved.
+** See provided LICENSE file or http://frotz.net/LICENSE for details.
+*/
+
+#ifndef __PLATFORM_AT91SAM7_H__
+#define __PLATFORM_AT91SAM7_H__
+
+#if !defined(AT91_SAM7X) && !defined(AT91_SAM7S)
+#error Unspecified Architecture - AT91SAM7S or AT91SAM7X must be defined
+#endif
+
+/* peripheral ids */
+#define PID_AIC_FIQ 0
+#define PID_SYSIRQ 1
+#define PID_PIOA 2
+#define PID_USART0 6
+#define PID_USART1 7
+#define PID_SSC 8
+#define PID_TWI 9
+#define PID_PWMC 10
+#define PID_UDP 11
+#define PID_TC0 12
+#define PID_TC1 13
+#define PID_TC2 14
+#if AT91_SAM7X
+#define PID_PIOB 3
+#define PID_SPI0 4
+#define PID_SPI1 5
+#define PID_CAN 15
+#define PID_EMAC 16
+#define PID_ADC 17
+#define PID_AIC_IRQ0 30
+#define PID_AIC_IRQ1 31
+#else
+#define PID_ADC 4
+#define PID_SPI0 5
+#define PID_AIC_IRQ 30
+#endif
+
+#define BASE_FLASH 0x00100000
+#define BASE_SRAM 0x00200000
+#define BASE_TC 0xFFFA0000
+#define BASE_UDP 0xFFFB0000
+#define BASE_TWI 0xFFFB8000
+#define BASE_USART0 0xFFFC0000
+#define BASE_USART1 0xFFFC4000
+#define BASE_PWMC 0xFFFCC000
+#define BASE_SSC 0xFFFD4000
+#define BASE_ADC 0xFFFD8000
+#define BASE_SPI0 0xFFFE0000
+
+#define BASE_AIC 0xFFFFF000
+#define BASE_DBGU 0xFFFFF200
+#define BASE_PIOA 0xFFFFF400
+#define BASE_PMC 0xFFFFFC00
+#define BASE_RSTC 0xFFFFFD00
+#define BASE_RTT 0xFFFFFD20
+#define BASE_PIT 0xFFFFFD30
+#define BASE_WDT 0xFFFFFD40
+#define BASE_VREG 0xFFFFFD60
+#define BASE_MC 0xFFFFFF00
+
+#if AT91_SAM7X
+#define BASE_CAN 0xFFFD0000
+#define BASE_EMAC 0xFFFDC000
+#define BASE_SPI1 0xFFFE4000
+#define BASE_PIOB 0xFFFFF600
+#endif
+
+
+typedef volatile unsigned int vu4;
+
+typedef struct
+{
+ vu4 MR;
+ vu4 SR;
+ vu4 PIVR;
+ vu4 PIIR;
+} AT91PIT;
+
+/* MR */
+#define PIT_PITEN (1 << 24)
+#define PIT_PITIEN (1 << 25)
+
+/* SR */
+#define PIT_PITS (1)
+
+/* PIxR */
+#define PIT_PICNT(x) (x >> 20)
+#define PIT_CPIV(x) (x & 0x000fffff)
+
+#define AT91PIT_ADDR ((AT91PIT*) BASE_PIT)
+
+typedef struct
+{
+ vu4 CR;
+ vu4 MR;
+ vu4 IER;
+ vu4 IDR;
+ vu4 IMR;
+ vu4 SR;
+ vu4 RHR;
+ vu4 THR;
+ vu4 BRGR;
+ vu4 __0[7];
+ vu4 CIDR;
+ vu4 EXID;
+ vu4 FNR;
+} AT91DBGU;
+
+/* CR bits */
+#define DBGU_RSTRX 0x00000004
+#define DBGU_RSTTX 0x00000008
+#define DBGU_RXEN 0x00000010
+#define DBGU_RXDIS 0x00000020
+#define DBGU_TXEN 0x00000040
+#define DBGU_TXDIS 0x00000080
+#define DBGU_RSTSTA 0x00000100
+
+/* MR bits */
+#define DBGU_PAR_EVEN 0x00000000
+#define DBGU_PAR_ODD 0x00000200
+#define DBGU_PAR_SPACE 0x00000400
+#define DBGU_PAR_MARK 0x00000600
+#define DBGU_PAR_NONE 0x00000800
+
+#define DBGU_MODE_NORMAL 0x00000000
+#define DBGU_MODE_ECHO 0x0000C000
+#define DBGU_MODE_LLOOP 0x00008000
+#define DBGU_MODE_RLOOP 0x00004000
+
+/* IER, IDR, IMR, and SR bits */
+#define DBGU_RXRDY 0x00000001
+#define DBGU_TXRDY 0x00000002
+#define DBGU_ENDRX 0x00000008
+#define DBGU_ENDTX 0x00000010
+#define DBGU_OVRE 0x00000020
+#define DBGU_FRAME 0x00000040
+#define DBGU_PARE 0x00000080
+#define DBGU_TXEMPTY 0x00000200
+#define DBGU_TXBUFE 0x00000800
+#define DBGU_RXBUFF 0x00001000
+#define DBGU_COMMTX 0x40000000
+#define DBGU_COMMRX 0x80000000
+
+#define AT91DBGU_ADDR ((AT91DBGU*) BASE_DBGU)
+
+typedef struct
+{
+ vu4 pio_enable;
+ vu4 pio_disable;
+ vu4 pio_status;
+ vu4 __0;
+ vu4 output_enable;
+ vu4 output_disable;
+ vu4 output_status;
+ vu4 __1;
+ vu4 filter_enable;
+ vu4 filter_disable;
+ vu4 filter_status;
+ vu4 __2;
+ vu4 data_set;
+ vu4 data_clear;
+ vu4 data_status;
+ vu4 pin_status;
+ vu4 irq_enable;
+ vu4 irq_disable;
+ vu4 irq_mask;
+ vu4 irq_status;
+ vu4 multidriver_enable;
+ vu4 multidriver_disable;
+ vu4 multidriver_status;
+ vu4 __3;
+ vu4 pullup_disable;
+ vu4 pullup_enable;
+ vu4 pullup_status;
+ vu4 __4;
+ vu4 select_a;
+ vu4 select_b;
+ vu4 select_status;
+ vu4 __5[9];
+ vu4 write_enable;
+ vu4 write_disable;
+ vu4 write_status;
+} AT91PIO;
+
+#define AT91PIOA_ADDR ((AT91PIO*) BASE_PIOA)
+#if AT91_SAM7X
+#define AT91PIOB_ADDR ((AT91PIO*) BASE_PIOB)
+#endif
+
+typedef struct
+{
+ vu4 SCER;
+ vu4 SCDR;
+ vu4 SCSR;
+ vu4 __0;
+ vu4 PCER;
+ vu4 PCDR;
+ vu4 PCSR;
+ vu4 __1;
+ vu4 MOR;
+ vu4 MCFR;
+ vu4 __2;
+ vu4 PLLR;
+ vu4 MCKR;
+ vu4 __3[2];
+ vu4 PCK0;
+ vu4 PCK1;
+ vu4 PCK2;
+} AT91PMC;
+
+#define AT91PMC_ADDR ((AT91PMC*) BASE_PMC)
+
+/* PMC_SCER/SCDR */
+#define PMC_PCK 0x00000001
+#define PMC_UDP 0x00000080
+#define PMC_PCK0 0x00000100
+#define PMC_PCK1 0x00000200
+#define PMC_PCK2 0x00000400
+
+typedef struct
+{
+ vu4 CR;
+ vu4 MR;
+ vu4 RDR;
+ vu4 TDR;
+ vu4 SR;
+ vu4 IER;
+ vu4 IDR;
+ vu4 IMR;
+ vu4 __0[4];
+ vu4 CSR0;
+ vu4 CSR1;
+ vu4 CSR2;
+ vu4 CSR3;
+} AT91SPI;
+
+#define AT91SPI0_ADDR ((AT91SPI*) BASE_SPI0)
+#if AT91_SAM7X
+#define AT91SPI1_ADDR ((AT91SPI*) BASE_SPI0)
+#endif
+
+/* CR bits */
+#define SPI_SPIEN 0x00000001
+#define SPI_SPIDIS 0x00000002
+#define SPI_SWRST 0x00000080
+#define SPI_LASTXFER 0x01000000
+
+/* MR bits */
+#define SPI_MSTR 0x00000001
+#define SPI_PS 0x00000002
+#define SPI_PCSDEC 0x00000004
+#define SPI_MODFDIS 0x00000010
+#define SPI_LLB 0x00000080
+#define SPI_DLYBCS(n) (((n) & 0xff) << 24)
+#define SPI_PCS0 0x000e0000
+#define SPI_PCS1 0x000d0000
+#define SPI_PCS2 0x000b0000
+#define SPI_PCS3 0x00070000
+
+/* SR bits */
+#define SPI_RDRF 0x00000001 /* recv data reg full */
+#define SPI_TDRE 0x00000002 /* xmit data reg empty */
+#define SPI_MODF 0x00000004 /* mode fault error */
+#define SPI_OVRES 0x00000008 /* overrun error */
+#define SPI_ENDRX 0x00000010 /* end of rx buffer */
+#define SPI_ENDTX 0x00000020 /* end of tx buffer */
+#define SPI_RXBUFF 0x00000040 /* rx buffer full */
+#define SPI_TXBUFE 0x00000080 /* tx buffer empty */
+#define SPI_NSSR 0x00000100 /* rising edge on NSS */
+#define SPI_TXEMPTY 0x00000200 /* transmission regs empty */
+#define SPI_SPIENS 0x00010000
+
+typedef struct
+{
+ vu4 FRM_NUM;
+ vu4 GLB_STAT;
+ vu4 FADDR;
+ vu4 __0;
+ vu4 IER;
+ vu4 IDR;
+ vu4 IMR;
+ vu4 ISR;
+ vu4 ICR;
+ vu4 __1;
+ vu4 RST_EP;
+ vu4 __2;
+ vu4 CSR0;
+ vu4 CSR1;
+ vu4 CSR2;
+ vu4 CSR3;
+ vu4 __3[4];
+ vu4 FDR0;
+ vu4 FDR1;
+ vu4 FDR2;
+ vu4 FDR3;
+ vu4 __4[5];
+ vu4 TXVC;
+} AT91UDP;
+
+#define AT91UDP_ADDR ((AT91UDP*) BASE_UDP)
+
+// GLB_STAT bits
+#define UDP_FADDEN 0x00000001
+#define UDP_CONFG 0x00000002
+#define UDP_ESR 0x00000004
+#define UDP_RSMINPR 0x00000008
+#define UDP_RMWUPE 0x00000010
+
+// FADDR bits
+#define UDP_FEN 0x00000100
+
+// interrupt bits
+#define UDP_EP0INT 0x00000001
+#define UDP_EP1INT 0x00000002
+#define UDP_EP2INT 0x00000004
+#define UDP_EP3INT 0x00000008
+#define UDP_RXSUSP 0x00000100
+#define UDP_RXRSM 0x00000200
+#define UDP_EXTRSM 0x00000400
+#define UDP_SOFINT 0x00000800
+#define UDP_ENDBUSRES 0x00001000
+#define UDP_WAKEUP 0x00002000
+
+// RST_EP bits
+#define UDP_EP0 0x00000001
+#define UDP_EP1 0x00000002
+#define UDP_EP2 0x00000004
+#define UDP_EP3 0x00000008
+
+// CSR bits
+#define UDP_TXCOMP 0x00000001
+#define UDP_RX_DATA_BK0 0x00000002
+#define UDP_RXSETUP 0x00000004
+#define UDP_STALLSENT 0x00000008
+#define UDP_ISOERROR 0x00000008
+#define UDP_TXPKTRDY 0x00000010
+#define UDP_FORCESTALL 0x00000020
+#define UDP_RX_DATA_BK1 0x00000040
+#define UDP_DIR 0x00000080
+
+#define UDP_DTGL 0x00000800
+#define UDP_EPEDS 0x00008000
+
+#define UDP_TYPE_CONTROL 0x00000000
+#define UDP_TYPE_ISOCH_OUT 0x00000100
+#define UDP_TYPE_BULK_OUT 0x00000200
+#define UDP_TYPE_INT_OUT 0x00000300
+#define UDP_TYPE_ISOCH_IN 0x00000500
+#define UDP_TYPE_BULK_IN 0x00000600
+#define UDP_TYPE_INT_IN 0x00000700
+
+typedef struct
+{
+ vu4 SMR[32];
+ vu4 SVR[32];
+ vu4 IVR;
+ vu4 FVR;
+ vu4 ISR;
+ vu4 IPR;
+ vu4 IMR;
+ vu4 CISR;
+ vu4 __0[2];
+ vu4 IECR;
+ vu4 IDCR;
+ vu4 ICCR;
+ vu4 ISCR;
+ vu4 EOICR;
+ vu4 SPU;
+ vu4 DCR;
+ vu4 __1;
+ vu4 FFER;
+ vu4 FFDR;
+ vu4 FFSR;
+} AT91AIC;
+
+#define AT91AIC_ADDR ((AT91AIC*) BASE_AIC)
+
+
+typedef struct
+{
+ vu4 CR;
+ vu4 MR;
+ vu4 IER;
+ vu4 IDR;
+ vu4 IMD;
+ vu4 CSR;
+ vu4 RHR;
+ vu4 THR;
+ vu4 BRGR;
+ vu4 RTOR;
+ vu4 TTGR;
+ vu4 __0[5];
+ vu4 FIDI;
+ vu4 NER;
+ vu4 __1;
+ vu4 IF;
+ vu4 MAN;
+} AT91USART;
+
+#define AT91USART0_ADDR ((AT91USART*) 0xFFFC0000)
+#define AT91USART1_ADDR ((AT91USART*) 0xFFFC4000)
+
+/* CR */
+#define USART_RSTRX 0x00000004
+#define USART_RSTTX 0x00000008
+#define USART_RXEN 0x00000010
+#define USART_RXDIS 0x00000020
+#define USART_TXEN 0x00000040
+#define USART_TXDIS 0x00000080
+#define USART_RSTSTA 0x00000100
+#define USART_STTBRK 0x00000200
+#define USART_STPBRK 0x00000400
+#define USART_STTTO 0x00000800
+#define USART_SENDA 0x00001000
+#define USART_RSTIT 0x00002000
+#define USART_RSTNACK 0x00004000
+#define USART_RETTO 0x00008000
+#define USART_DTREN 0x00010000
+#define USART_DTRDIS 0x00020000
+#define USART_RTSEN 0x00040000
+#define USART_RTSDIS 0x00080000
+
+/* MR */
+#define USART_MODE_NORMAL 0x00000000
+#define USART_MODE_RS485 0x00000001
+#define USART_MODE_HWHS 0x00000002
+#define USART_MODE_MODEM 0x00000003
+#define USART_MODE_ISO7816T0 0x00000004
+#define USART_MODE_ISO7816T1 0x00000006
+#define USART_MODE_IRDA 0x00000008
+
+#define USART_CLK_MCK 0x00000000
+#define USART_CLK_MCK_DIV 0x00000010
+#define USART_CLK_SCK 0x00000030
+
+#define USART_CHRL_5BITS 0x00000000
+#define USART_CHRL_6BITS 0x00000040
+#define USART_CHRL_7BITS 0x00000080
+#define USART_CHRL_8BITS 0x000000C0
+
+#define USART_SYNCHRONOUS 0x00000100
+
+#define USART_PARITY_EVEN 0x00000000
+#define USART_PARITY_ODD 0x00000200
+#define USART_PARITY_SPACE 0x00000400
+#define USART_PARITY_MARK 0x00000600
+#define USART_PARITY_NONE 0x00000800
+#define USART_PARITY_MULTIDROP 0x00000C00
+
+#define USART_1STOP 0x00000000
+#define USART_1X5STOP 0x00001000
+#define USART_2STOP 0x00002000
+
+#define USART_CHMODE_NORMAL 0x00000000
+#define USART_CHMODE_ECHO 0x00004000
+#define USART_CHMODE_LLOOP 0x00008000
+#define USART_CHMODE_RLOOP 0x0000C000
+
+#define USART_MSBF 0x00010000
+#define USART_MODE9 0x00020000
+#define USART_CLKO 0x00040000
+#define USART_OVER 0x00080000
+#define USART_INACK 0x00100000
+#define USART_DSNACK 0x00200000
+#define USART_VAR_SYNC 0x00400000
+
+#define USART_FILTER 0x10000000
+#define USART_MAN 0x20000000
+#define USART_ONEBIT 0x80000000
+
+/* CSR */
+#define USART_RXRDY 0x00000001
+#define USART_TXRDY 0x00000002
+#define USART_RXBRK 0x00000004
+#define USART_ENDRX 0x00000008
+#define USART_ENDTX 0x00000010
+#define USART_OVRE 0x00000020
+#define USART_FRAME 0x00000040
+#define USART_PARE 0x00000080
+#define USART_TIMEOUT 0x00000100
+#define USART_TXEMPTY 0x00000200
+#define USART_ITERATION 0x00000400
+#define USART_TXBUFE 0x00000800
+#define USART_RXBUFF 0x00001000
+#define USART_NACK 0x00002000
+
+
+typedef struct
+{
+ vu4 CR;
+ vu4 SR;
+ vu4 MR;
+} AT91RSTC;
+
+#define RSTC_KEY 0xA5000000
+
+/* cr */
+#define RSTC_PROCRST 0x00000001
+#define RSTC_PERRST 0x00000004
+#define RSTC_EXTRST 0x00000008
+
+/* sr */
+#define RSTC_URSTS 0x00000001
+#define RSTC_BODSTS 0x00000002
+#define RSTC_RSTTYP_MASK 0x00000070
+#define RSTC_RSTTYP_COLD 0x00000000
+#define RSTC_RSTTYP_WATCHDOG 0x00000020
+#define RSTC_RSTTYP_SOFTWARE 0x00000030
+#define RSTC_RSTTYP_NRST_PIN 0x00000040
+#define RSTC_RSTTYP_BROWNOUT 0x00000060
+#define RSTC_NRSTL 0x00010000
+#define RSTC_SRCMP 0x00020000
+
+/* mr */
+#define RSTC_URSTEN 0x00000001
+#define RSTC_URSTIEN 0x00000010
+#define RSTC_ERSTL(n) (((n) & 0xf) << 8)
+#define RSTC_BODIEN 0x00010000
+
+#define AT91RSTC_ADDR ((AT91RSTC*) BASE_RSTC)
+
+#if AT91_SAM7X
+
+typedef struct
+{
+ vu4 NCR;
+ vu4 NCFG;
+ vu4 NSR;
+ vu4 __0;
+
+ vu4 __1;
+ vu4 TSR;
+ vu4 RBQP;
+ vu4 TBQP;
+
+ vu4 RSR;
+ vu4 ISR;
+ vu4 IER;
+ vu4 IDR;
+
+ vu4 IMR;
+ vu4 MAN;
+ vu4 PTR;
+ vu4 PFR;
+
+ vu4 FTO;
+ vu4 SCF;
+ vu4 MCF;
+ vu4 FRO;
+
+ vu4 FCSE;
+ vu4 ALE;
+ vu4 DTF;
+ vu4 LCOL;
+
+ vu4 ECOL;
+ vu4 TUND;
+ vu4 CSE;
+ vu4 RRE;
+
+ vu4 ROV;
+ vu4 RSE;
+ vu4 ELE;
+ vu4 RJA;
+
+ vu4 USF;
+ vu4 STE;
+ vu4 RLE;
+ vu4 __2;
+
+ vu4 HRB;
+ vu4 HRT;
+ vu4 SA1B;
+ vu4 SA1T;
+
+ vu4 SA2B;
+ vu4 SA2T;
+ vu4 SA3B;
+ vu4 SA3T;
+
+ vu4 SA4B;
+ vu4 SA5T;
+ vu4 TID;
+ vu4 __3;
+
+ vu4 USRIO;
+} AT91EMAC;
+
+
+#define NCR_LB 0x00000001
+#define NCR_LLB 0x00000002
+#define NCR_RE 0x00000004
+#define NCR_TE 0x00000008
+#define NCR_MPE 0x00000010
+#define NCR_CLRSTAT 0x00000020
+#define NCR_INCSTAT 0x00000040
+#define NCR_WESTAT 0x00000080
+#define NCR_BP 0x00000100
+#define NCR_TSTART 0x00000200
+#define NCR_THALT 0x00000400
+
+#define NCFG_SPD 0x00000001
+#define NCFG_FD 0x00000002
+#define NCFG_JFRAME 0x00000008
+#define NCFG_CAF 0x00000010
+#define NCFG_NBC 0x00000020
+#define NCFG_MTI 0x00000040
+#define NCFG_UNI 0x00000080
+#define NCFG_BIG 0x00000100
+#define NCFG_CLK_d8 0x00000000
+#define NCFG_CLK_d16 0x00000400
+#define NCFG_CLK_d32 0x00000800
+#define NCFG_CLK_d64 0x00000C00
+#define NCFG_RTY 0x00001000
+#define NCFG_PAE 0x00002000
+#define NCFG_RBOF_0 0x00000000
+#define NCFG_RBOF_1 0x00004000
+#define NCFG_RBOF_2 0x00008000
+#define NCFG_RBOF_3 0x0000C000
+#define NCFG_RLCE 0x00010000
+#define NCFG_DRFCS 0x00020000
+#define NCFG_EFRHD 0x00040000
+#define NCFG_IRXFCS 0x00080000
+
+#define NSR_MDIO 0x00000002
+#define NSR_IDLE 0x00000004
+
+#define TSR_UBR 0x00000001
+#define TSR_COL 0x00000002
+#define TSR_RLE 0x00000004
+#define TSR_TGO 0x00000008
+#define TSR_BEX 0x00000010
+#define TSR_COMP 0x00000020
+#define TSR_UND 0x00000040
+
+#define RSR_BNA 0x00000001
+#define RSR_REC 0x00000002
+#define RSR_OVR 0x00000004
+
+#define ISR_MFD 0x00000001
+#define ISR_RCOMP 0x00000002
+#define ISR_RXUBR 0x00000004
+#define ISR_TXUBR 0x00000008
+#define ISR_TUND 0x00000010
+#define ISR_RLE 0x00000020
+#define ISR_TXERR 0x00000040
+#define ISR_TCOMP 0x00000080
+#define ISR_ROVR 0x00000400
+#define ISR_HRESP 0x00000800
+#define ISR_PFR 0x00001000
+#define ISR_PTZ 0x00002000
+
+#define USRIO_RMII 0x00000001
+#define USRIO_CLKEN 0x00000002
+
+#define AT91EMAC_ADDR ((AT91EMAC*) BASE_EMAC)
+
+
+typedef struct
+{
+ vu4 addr;
+ vu4 info;
+} emac_xmit_entry;
+
+#define XMIT_USED 0x80000000
+#define XMIT_WRAP 0x40000000
+#define XMIT_ERR_RETRY 0x20000000
+#define XMIT_ERR_UNDERRUN 0x10000000
+#define XMIT_ERR_EXHAUSTED 0x08000000
+#define XMIT_NO_CRC 0x00010000
+#define XMIT_LAST 0x00008000
+#define XMIT_LENGTH(n) ((n) & 0x3FF)
+
+
+/* CAN Registers */
+
+
+typedef struct
+{
+ vu4 MMR; /* Mailbox Mode Register */
+ vu4 MAM; /* Mailbox Acceptance Mask Register */
+ vu4 MID; /* Mailbox ID Register */
+ vu4 MFID; /* Mailbox Family ID Register */
+ vu4 MSR; /* Mailbox Status Register */
+ vu4 MDL; /* Mailbox Data Low Register */
+ vu4 MDH; /* Mailbox Data High Register */
+ vu4 MCR; /* Mailbox Control Register */
+} AT91CAN_MAILBOX;
+
+typedef struct
+{
+ vu4 MR; /* Mode Register */
+ vu4 IER; /* Interrupt Enable Register */
+ vu4 IDR; /* Interrupt Disable Register */
+ vu4 IMR; /* Interrupt Mask Register */
+ vu4 SR; /* Status Register */
+ vu4 BR; /* Baudrate Register */
+ vu4 TIM; /* Timer Register */
+ vu4 TIMESTP; /* Timestamp Register */
+ vu4 ECR; /* Error Counter Register */
+ vu4 TCR; /* Transfer Command Register */
+ vu4 ACR; /* Abort Command Register */
+
+ vu4 __0[53]; /* 0x002c - 0x0100 is undefined */
+ vu4 __1[63]; /* 0x0200 - 0x01fc is reserved */
+ AT91CAN_MAILBOX Mailbox[8];
+} AT91CAN;
+
+#define CAN_CANEN 0x00000001 /* CAN Controller Enable */
+#define CAN_LPM 0x00000002 /* Enable Low Power Mode */
+#define CAN_ABM 0x00000004 /* Enable Autoband/Listen Mode */
+#define CAN_OVL 0x00000008 /* Enable Overload Frame */
+#define CAN_TEOF 0x00000010 /* Timestamp Messages at each Frame */
+#define CAN_TTM 0x00000020 /* Enable Time Trigger Mode */
+#define CAN_TIMFRZ 0x00000040 /* Enable Timer Freeze */
+#define CAN_DRPT 0x00000080 /* Disable Repeat */
+
+#define CAN_MB(x) (0x00000001 << x) /* Enable Interrupt Enable */
+#define CAN_ERRA 0x00010000 /* Enable Error Active Mode Interrupt */
+#define CAN_WARN 0x00020000 /* Enable Warning Limit Interrupt */
+#define CAN_ERRP 0x00040000 /* Enable Passive mode interrupt */
+#define CAN_BOFF 0x00080000 /* Enable Bus-off mode interrupt */
+#define CAN_SLEEP 0x00100000 /* Enable Sleep Interrupt */
+#define CAN_WAKEUP 0x00200000 /* Enable Wakeup Interrupt */
+#define CAN_TOVF 0x00400000 /* Enable Timer Overflow Interrupt */
+#define CAN_TSTP 0x00800000 /* Enable TimeStamp Interrupt */
+#define CAN_CERR 0x01000000 /* Enable CRC Error Interrupt */
+#define CAN_SERR 0x02000000 /* Enable Stuffing Error Interrupt */
+#define CAN_AERR 0x04000000 /* Enable Acknowledgement Error Int */
+#define CAN_FERR 0x08000000 /* Enable Form Error Interrupt */
+#define CAN_BERR 0x10000000 /* Enable Bit Error Interrupt */
+
+#define CAN_RBSY 0x20000000 /* Receiver Busy */
+#define CAN_TBSY 0x40000000 /* Transmitter Busy */
+#define CAN_OVLSY 0x80000000 /* Overload Busy */
+
+/* Can Baudrate Regiister */
+
+#define CAN_PHASE2(x) (x)
+#define CAN_PHASE2_MASK 0x07
+#define CAN_PHASE1(x) (x<<4)
+#define CAN_PHASE1_MASK (0x07 << 4)
+#define CAN_PROPAG(x) (x<<8)
+#define CAN_PROPAG_MASK (0x07 << 8)
+#define CAN_SJW(x) (x<<12)
+#define CAN_SJW_MASK(x) (0x03 << 12)
+#define CAN_BRP(x) (x<<16)
+#define CAN_BRP_MASK (0x7f << 16)
+#define CAN_SMP 0x01000000 /* Sampling Mode */
+
+/* CAN Transfer Command Register */
+
+#define TCR_TIMRST 0x80000000 /* Timer Reset */
+
+/* CAN Message Mode Register */
+
+#define CAN_MTIMEMARK(x) (0x0000001 << x)
+#define CAN_PRIOR(x) (x << 16)
+#define CAN_MOT(x) (x << 24)
+
+#define CAN_MIDVB(x) (x)
+#define CAN_MIDVA(x) (x << 18)
+#define CAN_MIDE 0x20000000
+
+
+/* CAN MSRx */
+
+/* These are receive, so pass in the value of the register... */
+
+#define CAN_MTIMESTAMP(x) (x & 0x0000ffff)
+#define CAN_MDLC(x) ( (x >> 16) & 0x0f) /* Mailbox code length */
+#define CAN_MRTR 0x00100000 /* Mailbox Remote Trx Request*/
+#define CAN_MABT 0x00400000 /* Mailbox Message Abort */
+#define CAN_MRDY 0x00800000 /* Mailbox Ready */
+#define CAN_MMI 0x01000000 /* Mailbox Message Ignored */
+
+/* Message Control Register */
+
+//#define CAN_MDLC(x) (x<<16) /* Mailbox Data Length Code */
+#define CAN_MACR (0x01 << 22) /* Abort Request */
+#define CAN_MTCR (0x01 << 23) /* Mailbox Transfer Command */
+
+
+#define AT91CAN_ADDR ((AT91CAN*) BASE_CAN)
+
+
+
+#endif
+
+#endif
diff --git a/platform/at91sam7/init_clock.S b/platform/at91sam7/init_clock.S
new file mode 100644
index 0000000..2de137f
--- /dev/null
+++ b/platform/at91sam7/init_clock.S
@@ -0,0 +1,101 @@
+/* init_clock.S -- AT91SAM7 clock coldstart code
+**
+** Copyright 2006, Brian Swetland. All rights reserved.
+** See provided LICENSE file or http://frotz.net/LICENSE for details.
+*/
+
+.globl init_clock
+
+init_clock:
+/* init flash controller timing for 18.432MHz */
+ mov r1, #0xffffff00
+ ldr r0, =0x00340100
+ str r0, [r1, #0x60]
+
+#define PMC_MOR 0x20
+#define PMC_MCFR 0x24
+#define PMC_PLLR 0x2c
+#define PMC_MCKR 0x30
+#define PMC_SR 0x68
+
+/* PMC_MOR */
+#define PMC_MOSCEN 0x01
+#define PMC_OSCBYPASS 0x02
+
+/* PMC_MCFR */
+#define PMC_MAINRDY 0x00010000
+
+/* PMC_SR */
+#define PMC_MOSCS 0x01
+#define PMC_LOCK 0x04
+#define PMC_MCKRDY 0x08
+
+/* PMC_MCKR */
+#define PMC_CSS_SLOW 0x00
+#define PMC_CSS_MAIN 0x01
+#define PMC_CSS_PLL 0x03
+#define PMC_PRES_NONE 0x00
+#define PMC_PRES_DIV2 0x04
+#define PMC_PRES_DIV4 0x08
+
+/* Oscillator Init Sequence based on the Atmel sample code
+** in cstartup_boot_SAM7S32_64.s
+**
+** I cleaned it up a bit -- why they use a temporary register,
+** AND and then CMP instead of just TSTing against an immediate
+** boggles my mind. I think this could be a bit simpler yet,
+** but debugging it is a pain, so Good Enough wins for now.
+*/
+ ldr r1, =0xfffffc00
+
+/* bypass main oscillator */
+ mov r0, #PMC_OSCBYPASS
+ str r0, [r1, #PMC_MOR]
+
+/* compensate MAINRDY rising flag (45 SCLK) */
+ mov r0, #45
+1: subs r0, r0, #1
+ bhi 1b
+
+/* if MAINRDY is set, we have an external oscillator */
+ ldr r0, [r1, #PMC_MCFR]
+ tst r0, #PMC_MAINRDY
+ bne ext_osc_found
+
+/* reset MOSCS flag */
+ mov r0, #0
+ str r0, [r1, #PMC_MOR]
+
+/* enable main oscillator */
+ ldr r0, =((0x40 << 8) | PMC_MOSCEN)
+ str r0, [r1, #PMC_MOR]
+
+/* wait for main oscillator to come online */
+1: ldr r0, [r1, #PMC_SR]
+ tst r0, #PMC_MOSCS
+ beq 1b
+
+ext_osc_found:
+/* select main oscillator, no prescaler for MCK */
+ mov r0, #(PMC_CSS_MAIN | PMC_PRES_NONE)
+ str r0, [r1, #PMC_MCKR]
+
+/* wait until MCK settles to continue */
+1: ldr r0, [r1, #PMC_SR]
+ tst r0, #PMC_MCKRDY
+ beq 1b
+
+/* this is a bit of voodoo for selecting a 96.109MHz PLL
+** freq (MUL=72, DIV=14, OUT=0, USBDIV=/1) from the 18.432MHz
+** main clock.
+*/
+ ldr r0, =0x10483f0e
+ str r0, [r1, #PMC_PLLR]
+
+/* let the PLL lock before we continue */
+1: ldr r0, [r1, #PMC_SR]
+ tst r0, #PMC_LOCK
+ beq 1b
+
+ mov pc, lr
+
diff --git a/platform/at91sam7/init_clock_48mhz.S b/platform/at91sam7/init_clock_48mhz.S
new file mode 100644
index 0000000..a5bf961
--- /dev/null
+++ b/platform/at91sam7/init_clock_48mhz.S
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+.globl init_48mhz_clock
+
+#define PMC_MCKR 0x30
+#define PMC_SR 0x68
+
+#define PMC_MCKRDY 0x08
+#define PMC_PRES_DIV2 0x04
+#define PMC_CSS_PLL 0x03
+
+/* BUG?
+**
+** If I try to exit by bx lr, lr is corrupted somewhere in here.
+** No clue why. FIQ USB wedge not playing nice? Am I cheating
+** with my CPSR calls?
+*/
+init_48mhz_clock:
+ ldr r1, =0xfffffc00
+ mov r2, lr
+
+ // turn on /2 prescaler
+ mov r0, #PMC_PRES_DIV2
+ str r0, [r1, #PMC_MCKR]
+wait_for_clock1:
+ ldr r0, [r1, #PMC_SR]
+ tst r0, #PMC_MCKRDY
+ beq wait_for_clock1
+
+ // switch to pll clock
+ mov r0, #(PMC_PRES_DIV2 | PMC_CSS_PLL)
+ str r0, [r1, #PMC_MCKR]
+wait_for_clock2:
+ ldr r0, [r1, #PMC_SR]
+ tst r0, #PMC_MCKRDY
+ beq wait_for_clock2
+
+ bx r2
diff --git a/platform/at91sam7/interrupts.c b/platform/at91sam7/interrupts.c
new file mode 100644
index 0000000..6c08ef9
--- /dev/null
+++ b/platform/at91sam7/interrupts.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <sys/types.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/at91sam7.h>
+#include <arch/arm.h>
+
+static int do_nothing()
+{
+ return INT_NO_RESCHEDULE;
+}
+
+void platform_init_interrupts(void)
+{
+ AT91AIC *aic = AT91AIC_ADDR;
+ int n;
+
+ for(n = 0; n < 31; n++) {
+ aic->SVR[n] = (unsigned) do_nothing;
+ }
+ aic->SPU = (unsigned) do_nothing;
+}
+
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+ AT91AIC *aic = AT91AIC_ADDR;
+
+ if(vector > 31) return ERR_INVALID_ARGS;
+
+ if(oldstate) {
+ enter_critical_section();
+ *oldstate = aic->IMR & (1 << vector) ? 1 : 0;
+ aic->IDCR = (1 << vector);
+ exit_critical_section();
+ } else {
+ aic->IDCR = (1 << vector);
+ }
+
+ return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+ AT91AIC *aic = AT91AIC_ADDR;
+ if(vector > 31) return ERR_INVALID_ARGS;
+
+ if(oldstate) {
+ enter_critical_section();
+ *oldstate = aic->IMR & (1 << vector) ? 1 : 0;
+ aic->IECR = (1 << vector);
+ exit_critical_section();
+ } else {
+ aic->IECR = (1 << vector);
+ }
+
+ return NO_ERROR;
+}
+
+void platform_irq(struct arm_iframe *frame)
+{
+ AT91AIC *aic = AT91AIC_ADDR;
+ int_handler func;
+ enum handler_return ret;
+
+ inc_critical_section();
+
+ func = (int_handler) aic->IVR;
+// dprintf("platform_irq() -> %p\n", func);
+
+ ret = func(0);
+
+ aic->EOICR = (unsigned) aic;
+
+ if(ret == INT_RESCHEDULE) {
+ thread_preempt();
+ }
+
+ dec_critical_section();
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+ AT91AIC *aic = AT91AIC_ADDR;
+ if(vector > 31) return;
+ aic->SVR[vector] = (unsigned) handler;
+}
diff --git a/platform/at91sam7/mkboard.py b/platform/at91sam7/mkboard.py
new file mode 100755
index 0000000..62ce696
--- /dev/null
+++ b/platform/at91sam7/mkboard.py
@@ -0,0 +1,178 @@
+#!/usr/bin/python
+
+## mkboard.py -- atmel pio mux utility
+##
+## Copyright 2006, Brian Swetland. All rights reserved.
+## See provided LICENSE file or http://frotz.net/LICENSE for details.
+##
+
+import os, sys, string
+
+# pindef -> num, out, pull, pio, sela, selb
+
+reg_output_disable = 0
+reg_output_enable = 0
+reg_pullup_disable = 0
+reg_pullup_enable = 0
+reg_pio_disable = 0
+reg_pio_enable = 0
+reg_select_a = 0
+reg_select_b = 0
+
+def setup_registers(pindef):
+ global reg_output_disable
+ global reg_output_enable
+ global reg_pullup_disable
+ global reg_pullup_enable
+ global reg_pio_disable
+ global reg_pio_enable
+ global reg_select_a
+ global reg_select_b
+
+ (num, out, pull, pio, sela, selb) = pindef
+
+ bit = 1 << num
+
+ if out:
+ reg_output_enable |= bit
+ reg_output_disable &= (~bit)
+ else:
+ reg_output_enable &= (~bit)
+ reg_output_disable |= bit
+
+ if pull:
+ reg_pullup_enable |= bit
+ reg_pullup_disable &= (~bit)
+ else:
+ reg_pullup_enable &= (~bit)
+ reg_pullup_disable |= bit
+
+ if pio:
+ reg_pio_enable |= bit
+ reg_pio_disable &= (~bit)
+ else:
+ reg_pio_enable &= (~bit)
+ reg_pio_disable |= bit
+
+ if sela:
+ reg_select_a |= bit
+ if selb:
+ reg_select_b |= bit
+
+def import_pindef(fn):
+ pass
+
+def read_pins_def(fn, table):
+ output = ""
+ fd = open(fn,'r')
+ for line in fd.xreadlines():
+ line = line.split('#')[0].strip()
+ if not line: continue
+
+ (gpio,pa,pb) = line.split()
+ num = int(gpio[2:])
+
+ table[gpio+"_IN"] = (num, 0, 0, 1, 0, 0)
+ table[gpio+"_IN_PULLUP"] = (num, 0, 1, 1, 0, 0)
+ table[gpio+"_OUT"] = (num, 1, 0, 1, 0, 0)
+ table[gpio+"_"+pa] = (num, 0, 0, 0, 1, 0)
+ table[gpio+"_"+pb] = (num, 0, 0, 0, 0, 1)
+
+ return output
+
+def read_board_def(fn, table):
+ pins = {}
+ output = ""
+ for n in range(0,32):
+ pins[n] = ''
+
+ fd = open(fn,'r')
+ for line in fd.xreadlines():
+ line = line.split('#')[0].strip()
+ if not line: continue
+
+ if len(line.split('=')) == 2:
+ (line,func) = line.split('=')
+ line = line.strip()
+ func = func.strip()
+ else:
+ func = ''
+
+ parts = line.split()
+ if len(parts) < 2:
+ print "ERROR: invalid definition '%s'" % line
+ sys.exit(1)
+
+ if not func:
+ if (parts[1] == 'IN') or (parts[1] == 'OUT'):
+ func = parts[0]
+ else:
+ func = parts[1]
+
+ pin = string.join(parts,"_")
+
+ if not table.has_key(pin):
+ print "ERROR: pin '%s' does not exist" % pin
+ sys.exit(1)
+
+ pindef = table[pin]
+ num = pindef[0]
+ if pins[num]:
+ print "ERROR: pin '%s' conflicts with pin '%s'" % (pin, pins[num])
+ sys.exit(1)
+ pins[num] = pin
+
+ setup_registers(pindef)
+ output += "#define PIN_%-12s (1 << %d)\n" % (func, num)
+
+ return output
+
+table = {}
+output = ""
+
+for fn in sys.argv[1:]:
+ if fn.endswith('.pins'):
+ if table:
+ print "ERROR: only one pin definition file allowed"
+ sys.exit(1)
+ output = read_pins_def(fn, table)
+ continue
+
+ if fn.endswith('.def'):
+ if not table:
+ print "ERROR: must specify a pin definition file first"
+ sys.exit(1)
+
+ reg_output_disable = 0xffffffffL
+ reg_output_enable = 0L
+ reg_pullup_disable = 0L
+ reg_pullup_enable = 0xffffffffL
+ reg_pio_disable = 0L
+ reg_pio_enable = 0xffffffffL
+ reg_select_a = 0L
+ reg_select_b = 0L
+
+ output = read_board_def(fn, table)
+ fd = open(fn[:-4] + ".h", 'w')
+ fd.write("/* DO NOT EDIT -- AUTOGENERATED FROM '%s' */\n\n" % fn)
+ fd.write("#ifndef __BOARD_DEFINITION_FILE__\n")
+ fd.write("#define __BOARD_DEFINITION_FILE__\n\n")
+ fd.write(output)
+ fd.write("\n")
+ fd.write("#define BOARD_OUTPUT_DISABLE 0x%08x\n" % reg_output_disable)
+ fd.write("#define BOARD_OUTPUT_ENABLE 0x%08x\n" % reg_output_enable)
+ fd.write("#define BOARD_PULLUP_DISABLE 0x%08x\n" % reg_pullup_disable)
+ fd.write("#define BOARD_PULLUP_ENABLE 0x%08x\n" % reg_pullup_enable)
+ fd.write("#define BOARD_PIO_DISABLE 0x%08x\n" % reg_pio_disable)
+ fd.write("#define BOARD_PIO_ENABLE 0x%08x\n" % reg_pio_enable)
+ fd.write("#define BOARD_SELECT_A 0x%08x\n" % reg_select_a)
+ fd.write("#define BOARD_SELECT_B 0x%08x\n" % reg_select_b)
+ fd.write("\n#endif\n")
+ fd.close()
+ continue
+
+ print "ERROR: what is '%s'?" % fn
+ sys.exit(1)
+
+
+
diff --git a/platform/at91sam7/mux.c b/platform/at91sam7/mux.c
new file mode 100644
index 0000000..7c9d9a6
--- /dev/null
+++ b/platform/at91sam7/mux.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <platform/at91sam7.h>
+#include <platform/mux.h>
+
+void mux_init(void)
+{
+ AT91PIO *pio = AT91PIOA_ADDR;
+
+ pio->output_disable = BOARD_OUTPUT_DISABLE;
+ pio->output_enable = BOARD_OUTPUT_ENABLE;
+ pio->pullup_disable = BOARD_PULLUP_DISABLE;
+ pio->pullup_enable = BOARD_PULLUP_ENABLE;
+ pio->pio_disable = BOARD_PIO_DISABLE;
+ pio->pio_enable = BOARD_PIO_ENABLE;
+ pio->select_a = BOARD_SELECT_A;
+ pio->select_b = BOARD_SELECT_B;
+}
+
diff --git a/platform/at91sam7/platform.c b/platform/at91sam7/platform.c
new file mode 100644
index 0000000..378c06d
--- /dev/null
+++ b/platform/at91sam7/platform.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+void emac_init();
+
+void platform_init(void)
+{
+#if AT91_SAM7X
+ emac_init();
+#endif
+}
diff --git a/platform/at91sam7/platform_early.S b/platform/at91sam7/platform_early.S
new file mode 100644
index 0000000..e78e271
--- /dev/null
+++ b/platform/at91sam7/platform_early.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+.globl platform_early_init
+platform_early_init:
+ stmdb sp!, {lr}
+
+/* enable the NRST reset pin */
+ ldr r1, =0xfffffd08
+ ldr r0, =0xa5000401
+ str r0, [r1]
+
+/* disable watchdog */
+ ldr r1, =0xfffffd44
+ ldr r0, =0x3fff8fff
+ str r0, [r1]
+
+ bl init_clock
+ bl init_48mhz_clock
+
+/* copy the .data section from ROM to RAM */
+ ldr r0, =__rodata_end
+ ldr r1, =__data_start
+ ldr r2, =__bss_start
+__data_loop:
+ cmp r1, r2
+ ldrlt r3, [r0], #4
+ strlt r3, [r1], #4
+ blt __data_loop
+
+ bl mux_init
+ bl ser_init
+ bl platform_init_interrupts
+
+ ldmia sp!, {lr}
+ bx lr
diff --git a/platform/at91sam7/rules.mk b/platform/at91sam7/rules.mk
new file mode 100644
index 0000000..9186ef8
--- /dev/null
+++ b/platform/at91sam7/rules.mk
@@ -0,0 +1,70 @@
+#
+# The TARGET is expected to indicate which *specific* AT91SAM7 chip
+# is being used, since features and memory vary from chip to chip
+#
+# chip ram rom EMAC CAN
+# AT91CHIP := sam7s64 16k 64k N N
+# AT91CHIP := sam7s256 64k 256k N N
+# AT91CHIP := sam7x256 64k 256k Y Y
+#
+
+# ROMBASE, MEMBASE, and MEMSIZE are required for the linker script
+ROMBASE := 0x0
+MEMBASE := 0x200000
+
+TMP_CFG := bad
+ifeq ($(AT91CHIP), sam7x256)
+DEFINES += AT91_SAM7X=1
+DEFINES += AT91_RAMSIZE=65536
+DEFINES += AT91_ROMSIZE=262144
+MEMSIZE := 65536
+TMP_CFG := ok
+endif
+ifeq ($(AT91CHIP), sam7s256)
+DEFINES += AT91_SAM7S=1
+DEFINES += AT91_RAMSIZE=65536
+DEFINES += AT91_ROMSIZE=262144
+MEMSIZE := 65536
+TMP_CFG := ok
+endif
+ifeq ($(AT91CHIP), sam7s64)
+DEFINES += AT91_SAM7S=1
+DEFINES += AT91_RAMSIZE=16384
+DEFINES += AT91_ROMSIZE=65536
+MEMSIZE := 16384
+TMP_CFG := ok
+endif
+
+ifeq ($(TMP_CFG), bad)
+$(error The AT91SAM7 platform requires AT91CHIP be set by the target)
+endif
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := arm7tdmi
+
+DEFINES += AT91_MCK_MHZ=48000000
+
+INCLUDES += \
+ -I$(LOCAL_DIR)/include
+
+OBJS += \
+ $(LOCAL_DIR)/debug.o \
+ $(LOCAL_DIR)/interrupts.o \
+ $(LOCAL_DIR)/platform_early.o \
+ $(LOCAL_DIR)/platform.o \
+ $(LOCAL_DIR)/timer.o \
+ $(LOCAL_DIR)/init_clock.o \
+ $(LOCAL_DIR)/init_clock_48mhz.o \
+ $(LOCAL_DIR)/mux.o \
+ $(LOCAL_DIR)/emac_dev.o
+
+# use a two segment memory layout, where all of the read-only sections
+# of the binary reside in rom, and the read/write are in memory. The
+# ROMBASE, MEMBASE, and MEMSIZE make variables are required to be set
+# for the linker script to be generated properly.
+#
+LINKER_SCRIPT += \
+ $(BUILDDIR)/system-twosegment.ld
+
diff --git a/platform/at91sam7/timer.c b/platform/at91sam7/timer.c
new file mode 100644
index 0000000..e4b6596
--- /dev/null
+++ b/platform/at91sam7/timer.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <sys/types.h>
+
+#include <kernel/thread.h>
+#include <platform/timer.h>
+#include <platform/interrupts.h>
+#include <platform/debug.h>
+#include <platform/at91sam7.h>
+
+#define FIXED_1KHZ_TIMER 0
+
+static platform_timer_callback timer_func;
+
+static volatile time_t ticks = 0;
+
+#if FIXED_1KHZ_TIMER
+static volatile int timer_interval;
+static volatile int timer_downcount;
+#else
+static int timer_ms_per_tick;
+#endif
+
+time_t current_time(void)
+{
+ return ticks;
+}
+
+static enum handler_return pit_irq_handler(void *arg)
+{
+ AT91PIT *pit = AT91PIT_ADDR;
+ unsigned n = PIT_PICNT(pit->PIVR);
+
+#if FIXED_1KHZ_TIMER
+ ticks += n;
+ timer_downcount -= n;
+
+ if(timer_downcount <= 0) {
+ timer_downcount = timer_interval;
+ return timer_func(0, ticks);
+ } else {
+ return INT_NO_RESCHEDULE;
+ }
+#else
+ ticks += (n * timer_ms_per_tick);
+ return timer_func(0, ticks);
+#endif
+}
+
+status_t platform_set_periodic_timer(platform_timer_callback callback,
+ void *arg, time_t interval)
+{
+ unsigned n;
+
+ AT91PIT *pit = AT91PIT_ADDR;
+
+ n = AT91_MCK_MHZ / 16 / 1000;
+ dprintf("timer: MCK=%dKHz, n=%d\n", AT91_MCK_MHZ / 1000, n);
+
+ enter_critical_section();
+
+ timer_func = callback;
+
+#if FIXED_1KHZ_TIMER
+ timer_interval = interval;
+ timer_downcount = interval;
+#else
+ timer_ms_per_tick = interval;
+ n *= interval;
+#endif
+
+ pit->MR = PIT_PITEN | PIT_PITIEN | (n & 0xfffff);
+
+ register_int_handler(PID_SYSIRQ, pit_irq_handler, 0);
+ unmask_interrupt(PID_SYSIRQ, 0);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
diff --git a/platform/debug.c b/platform/debug.c
new file mode 100644
index 0000000..a38ccbc
--- /dev/null
+++ b/platform/debug.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
diff --git a/platform/init.c b/platform/init.c
new file mode 100644
index 0000000..c397b50
--- /dev/null
+++ b/platform/init.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <debug.h>
+#include <platform.h>
+
+/*
+ * default implementations of these routines, if the platform code
+ * chooses not to implement.
+ */
+
+__WEAK void platform_init_mmu_mappings(void)
+{
+}
+
+__WEAK void platform_early_init(void)
+{
+}
+
+__WEAK void platform_init(void)
+{
+}
+
diff --git a/platform/integrator/debug.c b/platform/integrator/debug.c
new file mode 100644
index 0000000..ab9f901
--- /dev/null
+++ b/platform/integrator/debug.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <debug.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <platform/debug.h>
+#include <arch/ops.h>
+#include <platform/integrator.h>
+
+static void write_uart_reg(int uart, int reg, unsigned char data)
+{
+ unsigned long base;
+ int mul = 4;
+
+ switch(uart) {
+ case 0: base = INTEGRATOR_UART0_REG_BASE; break;
+ case 1: base = INTEGRATOR_UART1_REG_BASE; break;
+ default: return;
+ }
+
+ *(volatile unsigned char *)(base + reg * mul) = data;
+}
+
+static unsigned char read_uart_reg(int uart, int reg)
+{
+ unsigned long base;
+ int mul = 4;
+
+ switch(uart) {
+ case 0: base = INTEGRATOR_UART0_REG_BASE; break;
+ case 1: base = INTEGRATOR_UART1_REG_BASE; break;
+ default: return 0;
+ }
+
+ return *(volatile unsigned char *)(base + reg * mul);
+}
+
+static int uart_init(void)
+{
+#if 0
+ /* clear the tx & rx fifo and disable */
+ write_uart_reg(0, UART_FCR, 0x6);
+#endif
+
+ return 0;
+}
+
+static int uart_putc(int port, char c )
+{
+ write_uart_reg(0, PL011_UARTDR, c);
+#if 0
+ while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the shift register to empty
+ ;
+ write_uart_reg(port, UART_THR, c);
+#endif
+ return 0;
+}
+
+static int uart_getc(int port, bool wait) /* returns -1 if no data available */
+{
+#if 0
+ if (wait) {
+ while (!(read_uart_reg(port, UART_LSR) & (1<<0))) // wait for data to show up in the rx fifo
+ ;
+ } else {
+ if (!(read_uart_reg(port, UART_LSR) & (1<<0)))
+ return -1;
+ }
+ return read_uart_reg(port, UART_RHR);
+#endif
+ return -1;
+}
+
+void dputc(char c)
+{
+ uart_putc(0, c);
+}
+
+int dgetc(char *c)
+{
+ int result = uart_getc(0, false);
+
+ if (result < 0)
+ return -1;
+
+ *c = result;
+ return 0;
+}
+
+void debug_dump_regs(void)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_halt(void)
+{
+ dprintf("HALT: spinning forever...\n");
+ for(;;);
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+uint32_t debug_cycle_count()
+{
+ PANIC_UNIMPLEMENTED;
+}
diff --git a/platform/integrator/include/platform/integrator.h b/platform/integrator/include/platform/integrator.h
new file mode 100644
index 0000000..47eaacb
--- /dev/null
+++ b/platform/integrator/include/platform/integrator.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __INTEGRATOR_H
+#define __INTEGRATOR_H
+
+/* memory map */
+#define SDRAM_BASE 0x00000000
+
+#define INTEGRATOR_CORE_REG_BASE 0x10000000
+#define INTEGRATOR_SYS_REG_BASE 0x11000000
+#define INTEGRATOR_EBI_REG_BASE 0x12000000
+#define INTEGRATOR_TIMER_REG_BASE 0x13000000
+#define INTEGRATOR_INT_REG_BASE 0x14000000
+#define INTEGRATOR_UART0_REG_BASE 0x16000000
+#define INTEGRATOR_UART1_REG_BASE 0x17000000
+#define INTEGRATOR_LEDS_REG_BASE 0x1a000000
+#define INTEGRATOR_GPIO_REG_BASE 0x1b000000
+
+/* uart stuff */
+#define PL011_UARTDR (0)
+#define PL011_UARTRSR (1)
+#define PL011_UARTECR (1)
+#define PL011_UARTFR (6)
+#define PL011_UARTILPR (8)
+#define PL011_UARTIBRD (9)
+#define PL011_UARTFBRD (10)
+#define PL011_UARTLCR_H (11)
+#define PL011_UARTCR (12)
+#define PL011_UARTIFLS (13)
+#define PL011_UARTIMSC (14)
+#define PL011_UARTTRIS (15)
+#define PL011_UARTTMIS (16)
+#define PL011_UARTICR (17)
+#define PL011_UARTMACR (18)
+
+#define INT_VECTORS 32 // XXX just made this up
+
+#endif
+
diff --git a/platform/integrator/interrupts.c b/platform/integrator/interrupts.c
new file mode 100644
index 0000000..ef5f221
--- /dev/null
+++ b/platform/integrator/interrupts.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <sys/types.h>
+#include <debug.h>
+#include <reg.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <arch/ops.h>
+#include <arch/arm.h>
+#include "platform_p.h"
+#include <platform/integrator.h>
+
+struct int_handler_struct {
+ int_handler handler;
+ void *arg;
+};
+
+static struct int_handler_struct int_handler_table[INT_VECTORS];
+
+#if 0
+static const uint32_t icBase[5] = {
+ INTCON0_BASE, INTCON1_BASE, INTCON2_BASE, INTCON3_BASE, INTCON4_BASE };
+
+/* a bitmap of the level triggered interrupt vectors */
+static uint32_t level_trigger[5] = {
+ 0xb3fefe8f, // level 1 0-31
+ 0xfdb3c1fd, // level 2 0-31
+ 0xfffff7ff, // level 2 32-63
+ 0xbfffffff, // level 2 64-95
+ 0xffffffff // level 2 96-128
+};
+
+inline volatile uint32_t *ICReg(uint controller, uint reg)
+{
+ return (volatile uint32_t *)(icBase[controller] + reg);
+}
+
+inline uint32_t readICReg(uint controller, uint reg)
+{
+ return *ICReg(controller, reg);
+}
+inline void writeICReg(uint controller, uint reg, uint val)
+{
+ *ICReg(controller, reg) = val;
+}
+
+inline uint vectorToController(uint vector)
+{
+ return vector / 32;
+}
+#endif
+
+void platform_init_interrupts(void)
+{
+#if 0
+ unsigned int i;
+
+ // mask all interrupts
+ *ICReg(0, INTCON_MIR) = 0xfffffffa;
+ *ICReg(1, INTCON_MIR) = 0xffffffff;
+ *ICReg(2, INTCON_MIR) = 0xffffffff;
+ *ICReg(3, INTCON_MIR) = 0xffffffff;
+ *ICReg(4, INTCON_MIR) = 0xffffffff;
+
+ // set up each of the interrupts
+ for (i = 0; i < INT_VECTORS; i++) {
+ // set each vector up as high priority, IRQ, and default edge/level sensitivity
+ *ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
+ }
+
+ // clear any pending interrupts
+ *ICReg(0, INTCON_ITR) = 0;
+ *ICReg(1, INTCON_ITR) = 0;
+ *ICReg(2, INTCON_ITR) = 0;
+ *ICReg(3, INTCON_ITR) = 0;
+ *ICReg(4, INTCON_ITR) = 0;
+
+ // globally unmask interrupts
+ *ICReg(1, INTCON_CONTROL) = 3;
+ *ICReg(0, INTCON_CONTROL) = 3;
+ *ICReg(0, INTCON_GMR) = 0;
+
+ dprintf("end of platform_init_interrupts\n");
+
+#if 0
+ arch_enable_ints();
+
+ dprintf("&ITR0 0x%x\n", (uint32_t)ICReg(0, INTCON_ITR));
+
+ dprintf("ITR0 0x%x\n", *ICReg(0, INTCON_ITR));
+ dprintf("MIR0 0x%x\n", *ICReg(0, INTCON_MIR));
+ dprintf("SIR_IRQ0 0x%x\n", *ICReg(0, INTCON_SIR_IRQ));
+
+ *ICReg(0, INTCON_ILR_BASE + 4*7) = 0;
+ *ICReg(0, INTCON_MIR) &= ~0x80;
+
+ dprintf("triggering int\n");
+
+ *ICReg(0, INTCON_SISR) = 0x80;
+
+ dprintf("ITR0 0x%x\n", *ICReg(0, INTCON_ITR));
+ dprintf("MIR0 0x%x\n", *ICReg(0, INTCON_MIR));
+ dprintf("SIR_IRQ0 0x%x\n", *ICReg(0, INTCON_SIR_IRQ));
+
+ for(;;);
+#endif
+#endif
+}
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+#if 0
+ if (vector >= INT_VECTORS)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = false;
+
+ volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
+ *mir = *mir | (1<<(vector % 32));
+
+ exit_critical_section();
+#endif
+
+ return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+#if 0
+ if (vector >= INT_VECTORS)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = false;
+
+ volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
+ *mir = *mir & ~(1<<(vector % 32));
+
+ exit_critical_section();
+#endif
+
+ return NO_ERROR;
+}
+
+void platform_irq(struct arm_iframe *frame)
+{
+ PANIC_UNIMPLEMENTED;
+#if 0
+ // get the current vector
+ unsigned int vector;
+
+ inc_critical_section();
+
+ // read from the first level int handler
+ vector = *ICReg(0, INTCON_SIR_IRQ);
+
+ // see if it's coming from the second level handler
+ if (vector == 0) {
+ vector = *ICReg(1, INTCON_SIR_IRQ) + 32;
+ }
+
+// dprintf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector);
+
+ // deliver the interrupt
+ enum handler_return ret;
+
+ ret = INT_NO_RESCHEDULE;
+ if (int_handler_table[vector].handler)
+ ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
+
+ // ack the interrupt
+ if (vector >= 32) {
+ // interrupt is chained, so ack the second level first, and then the first
+ *ICReg(vector / 32, INTCON_ITR) = ~(1 << (vector % 32));
+ *ICReg(1, INTCON_CONTROL) |= 1;
+ vector = 0; // force the following code to ack the chained first level vector
+ }
+
+ *ICReg(0, INTCON_ITR) = ~(1 << vector);
+ *ICReg(0, INTCON_CONTROL) = 1;
+
+ if (ret == INT_RESCHEDULE)
+ thread_preempt();
+
+ dec_critical_section();
+
+// dprintf("platform_irq: exit\n");
+#endif
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+ if (vector >= INT_VECTORS)
+ panic("register_int_handler: vector out of range %d\n", vector);
+
+ enter_critical_section();
+
+ int_handler_table[vector].handler = handler;
+ int_handler_table[vector].arg = arg;
+
+ exit_critical_section();
+}
+
diff --git a/platform/integrator/platform.c b/platform/integrator/platform.c
new file mode 100644
index 0000000..5b31242
--- /dev/null
+++ b/platform/integrator/platform.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <debug.h>
+#include <platform.h>
+#include "platform_p.h"
+#include <platform/integrator.h>
+#include <arch/arm/mmu.h>
+
+void platform_init_mmu_mappings(void)
+{
+}
+
+void platform_early_init(void)
+{
+#if 0
+ /* do some memory map initialization */
+ addr_t addr;
+ arm_mmu_map_section(SDRAM_BASE, 0, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED);
+ for (addr = SDRAM_BASE; addr < SDRAM_BASE + SDRAM_SIZE; addr += (1024*1024)) {
+ arm_mmu_map_section(addr, addr, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED|MMU_FLAG_READWRITE);
+ }
+
+ /* initialize the interrupt controller */
+ platform_init_interrupts();
+
+ /* initialize the timer block */
+ platform_init_timer();
+#endif
+}
+
+void platform_init(void)
+{
+}
+
diff --git a/platform/integrator/platform_p.h b/platform/integrator/platform_p.h
new file mode 100644
index 0000000..872ea2b
--- /dev/null
+++ b/platform/integrator/platform_p.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_P_H
+#define __PLATFORM_P_H
+
+void platform_init_interrupts(void);
+void platform_init_timer(void);
+
+#endif
+
diff --git a/platform/integrator/rules.mk b/platform/integrator/rules.mk
new file mode 100644
index 0000000..a189153
--- /dev/null
+++ b/platform/integrator/rules.mk
@@ -0,0 +1,26 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := arm926ej-s
+CPU := generic
+
+INCLUDES += \
+ -I$(LOCAL_DIR)/include
+
+OBJS += \
+ $(LOCAL_DIR)/debug.o \
+ $(LOCAL_DIR)/platform.o \
+ $(LOCAL_DIR)/interrupts.o \
+ $(LOCAL_DIR)/timer.o \
+
+# $(LOCAL_DIR)/net.o \
+
+
+# $(LOCAL_DIR)/console.o \
+
+MEMBASE ?= 0x0
+MEMSIZE ?= 0x08000000 # 128MB
+
+LINKER_SCRIPT += \
+ $(BUILDDIR)/system-onesegment.ld
+
diff --git a/platform/integrator/timer.c b/platform/integrator/timer.c
new file mode 100644
index 0000000..55d14de
--- /dev/null
+++ b/platform/integrator/timer.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <kernel/thread.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <platform/integrator.h>
+#include "platform_p.h"
+
+static time_t system_time = 0;
+
+static time_t tick_interval;
+static uint32_t ticks_per_interval;
+static platform_timer_callback t_callback;
+static void *callback_arg;
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+#if 0
+ enter_critical_section();
+
+ t_callback = callback;
+ callback_arg = arg;
+ tick_interval = interval;
+ ticks_per_interval = interval * 32768 / 1000; // interval is in ms
+
+ OS_TIMER_CTRL_REG = 0; // stop it
+ OS_TIMER_TICK_VALUE_REG = ticks_per_interval;
+ OS_TIMER_CTRL_REG = (1<<3) | (1<<2) | (1<<1) | (1<<0);
+
+ exit_critical_section();
+#endif
+
+ return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+#if 0
+ time_t t;
+ uint32_t delta_ticks;
+ uint32_t delta_ticks2;
+
+retry:
+ delta_ticks = OS_TIMER_TICK_COUNTER_REG;
+ t = system_time;
+ delta_ticks2 = OS_TIMER_TICK_COUNTER_REG;
+ if (delta_ticks2 > delta_ticks)
+ goto retry;
+
+ t += ((ticks_per_interval - delta_ticks2) * tick_interval) / ticks_per_interval;
+
+ return t;
+#else
+ static time_t time = 0;
+ return time++;
+#endif
+
+}
+
+static enum handler_return os_timer_tick(void *arg)
+{
+ system_time += tick_interval;
+// dprintf("os_timer_tick %d\n", system_time);
+
+ return t_callback(callback_arg, system_time);
+}
+
+void platform_init_timer(void)
+{
+#if 0
+ OS_TIMER_CTRL_REG = 0; // stop the timer if it's already running
+
+ register_int_handler(IRQ_OS_TIMER, &os_timer_tick, NULL);
+ unmask_interrupt(IRQ_OS_TIMER, NULL);
+#endif
+}
+
diff --git a/platform/omap3/debug.c b/platform/omap3/debug.c
new file mode 100644
index 0000000..973287b
--- /dev/null
+++ b/platform/omap3/debug.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <debug.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <platform/debug.h>
+#include <arch/ops.h>
+#include <dev/uart.h>
+#include <target/debugconfig.h>
+
+void dputc(char c)
+{
+ if (c == '\n')
+ uart_putc(DEBUG_UART, '\r');
+ uart_putc(DEBUG_UART, c);
+}
+
+int dgetc(char *c)
+{
+ int _c;
+
+ if ((_c = uart_getc(DEBUG_UART, false)) < 0)
+ return -1;
+
+ *c = _c;
+ return 0;
+}
+
+void debug_dump_regs(void)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_halt(void)
+{
+ dprintf("HALT: spinning forever...\n");
+ for(;;);
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+uint32_t debug_cycle_count(void)
+{
+// PANIC_UNIMPLEMENTED;
+ return 0;
+}
diff --git a/platform/omap3/include/platform/omap3.h b/platform/omap3/include/platform/omap3.h
new file mode 100644
index 0000000..c7d9405
--- /dev/null
+++ b/platform/omap3/include/platform/omap3.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_OMAP3_H
+#define __PLATFORM_OMAP3_H
+
+#define SDRAM_BASE 0x80000000
+
+#define L4_BASE 0x48000000
+#define L4_WKUP_BASE 0x48300000
+#define L4_PER_BASE 0x49000000
+#define L4_EMU_BASE 0x54000000
+#define GFX_BASE 0x50000000
+#define L3_BASE 0x68000000
+#define SMS_BASE 0x6C000000
+#define SDRC_BASE 0x6D000000
+#define GPMC_BASE 0x6E000000
+#define SCM_BASE 0x48002000
+
+/* clocks */
+#define CM_CLKSEL_PER (L4_BASE + 0x5040)
+
+/* General Purpose Timers */
+#define OMAP34XX_GPT1 (L4_BASE + 0x318000)
+#define OMAP34XX_GPT2 (L4_BASE + 0x1032000)
+#define OMAP34XX_GPT3 (L4_BASE + 0x1034000)
+#define OMAP34XX_GPT4 (L4_BASE + 0x1036000)
+#define OMAP34XX_GPT5 (L4_BASE + 0x1038000)
+#define OMAP34XX_GPT6 (L4_BASE + 0x103A000)
+#define OMAP34XX_GPT7 (L4_BASE + 0x103C000)
+#define OMAP34XX_GPT8 (L4_BASE + 0x103E000)
+#define OMAP34XX_GPT9 (L4_BASE + 0x1040000)
+#define OMAP34XX_GPT10 (L4_BASE + 0x86000)
+#define OMAP34XX_GPT11 (L4_BASE + 0x88000)
+#define OMAP34XX_GPT12 (L4_BASE + 0x304000)
+
+#define TIDR 0x00
+#define TIOCP_CFG 0x10
+#define TISTAT 0x14
+#define TISR 0x18
+#define TIER 0x1C
+#define TWER 0x20
+#define TCLR 0x24
+#define TCRR 0x28
+#define TLDR 0x2C
+#define TTGR 0x30
+#define TWPS 0x34
+#define TMAR 0x38
+#define TCAR1 0x3C
+#define TSICR 0x40
+#define TCAR2 0x44
+#define TPIR 0x48
+#define TNIR 0x4C
+#define TCVR 0x50
+#define TOCR 0x54
+#define TOWR 0x58
+
+/* WatchDog Timers (1 secure, 3 GP) */
+#define WD1_BASE (0x4830C000)
+#define WD2_BASE (0x48314000)
+#define WD3_BASE (0x49030000)
+
+#define WIDR 0x00
+#define WD_SYSCONFIG 0x10
+#define WD_SYSSTATUS 0x14
+#define WISR 0x18
+#define WIER 0x1C
+#define WCLR 0x24
+#define WCRR 0x28
+#define WLDR 0x2C
+#define WTGR 0x30
+#define WWPS 0x34
+#define WSPR 0x48
+
+#define W_PEND_WCLR (1<<0)
+#define W_PEND_WCRR (1<<1)
+#define W_PEND_WLDR (1<<2)
+#define W_PEND_WTGR (1<<3)
+#define W_PEND_WSPR (1<<4)
+
+#define WD_UNLOCK1 0xAAAA
+#define WD_UNLOCK2 0x5555
+
+/* 32KTIMER */
+#define TIMER32K_BASE (L4_BASE + 0x320000)
+#define TIMER32K_REV (TIMER32K_BASE + 0x00)
+#define TIMER32K_CR (TIMER32K_BASE + 0x10)
+
+/* UART */
+#define OMAP_UART1_BASE (L4_BASE + 0x6a000)
+#define OMAP_UART2_BASE (L4_BASE + 0x6c000)
+#define OMAP_UART3_BASE (L4_BASE + 0x01020000)
+
+#define UART_RHR 0
+#define UART_THR 0
+#define UART_DLL 0
+#define UART_IER 1
+#define UART_DLH 1
+#define UART_IIR 2
+#define UART_FCR 2
+#define UART_EFR 2
+#define UART_LCR 3
+#define UART_MCR 4
+#define UART_LSR 5
+#define UART_MSR 6
+#define UART_TCR 6
+#define UART_SPR 7
+#define UART_TLR 7
+#define UART_MDR1 8
+#define UART_MDR2 9
+#define UART_SFLSR 10
+#define UART_RESUME 11
+#define UART_TXFLL 10
+#define UART_TXFLH 11
+#define UART_SFREGL 12
+#define UART_SFREGH 13
+#define UART_RXFLL 12
+#define UART_RXFLH 13
+#define UART_BLR 14
+#define UART_UASR 14
+#define UART_ACREG 15
+#define UART_SCR 16
+#define UART_SSR 17
+#define UART_EBLR 18
+#define UART_MVR 19
+#define UART_SYSC 20
+
+/* MPU INTC */
+#define INTC_BASE (L4_BASE + 0x200000)
+#define INTC_REVISION (INTC_BASE + 0x000)
+#define INTC_SYSCONFIG (INTC_BASE + 0x010)
+#define INTC_SYSSTATUS (INTC_BASE + 0x014)
+#define INTC_SIR_IRQ (INTC_BASE + 0x040)
+#define INTC_SIR_FIQ (INTC_BASE + 0x044)
+#define INTC_CONTROL (INTC_BASE + 0x048)
+#define INTC_PROTECTION (INTC_BASE + 0x04C)
+#define INTC_IDLE (INTC_BASE + 0x050)
+#define INTC_IRQ_PRIORITY (INTC_BASE + 0x060)
+#define INTC_FIQ_PRIORITY (INTC_BASE + 0x064)
+#define INTC_THRESHOLD (INTC_BASE + 0x068)
+#define INTC_ITR(n) (INTC_BASE + 0x080 + (n) * 0x20)
+#define INTC_MIR(n) (INTC_BASE + 0x084 + (n) * 0x20)
+#define INTC_MIR_CLEAR(n) (INTC_BASE + 0x088 + (n) * 0x20)
+#define INTC_MIR_SET(n) (INTC_BASE + 0x08C + (n) * 0x20)
+#define INTC_ISR_SET(n) (INTC_BASE + 0x090 + (n) * 0x20)
+#define INTC_ISR_CLEAR(n) (INTC_BASE + 0x094 + (n) * 0x20)
+#define INTC_PENDING_IRQ(n) (INTC_BASE + 0x098 + (n) * 0x20)
+#define INTC_PENDING_FIQ(n) (INTC_BASE + 0x09C + (n) * 0x20)
+#define INTC_ILR(n) (INTC_BASE + 0x100 + (n) * 4)
+
+/* interrupts */
+#define INT_VECTORS 96
+#define GPT2_IRQ 38
+
+#endif
+
diff --git a/platform/omap3/interrupts.c b/platform/omap3/interrupts.c
new file mode 100644
index 0000000..225d810
--- /dev/null
+++ b/platform/omap3/interrupts.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <debug.h>
+#include <err.h>
+#include <reg.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <arch/ops.h>
+#include <arch/arm.h>
+#include "platform_p.h"
+#include <platform/omap3.h>
+
+struct int_handler_struct {
+ int_handler handler;
+ void *arg;
+};
+
+static struct int_handler_struct int_handler_table[INT_VECTORS];
+
+#define vectorToController(vector) ((vector) / 32)
+
+void platform_init_interrupts(void)
+{
+ unsigned int i;
+
+ // reset the controller
+ *REG32(INTC_SYSCONFIG) = 0x2; // start a reset
+ while ((*REG32(INTC_SYSSTATUS) & 0x1) == 0)
+ ;
+
+ // mask all interrupts
+ *REG32(INTC_MIR(0)) = 0xffffffff;
+ *REG32(INTC_MIR(1)) = 0xffffffff;
+ *REG32(INTC_MIR(2)) = 0xffffffff;
+
+ // set up each of the interrupts
+ for (i = 0; i < INT_VECTORS; i++) {
+ // set each vector up as high priority IRQ
+ *REG32(INTC_ILR(i)) = 0;
+ //*ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
+ }
+
+ // disable the priority threshold
+ *REG32(INTC_THRESHOLD) = 0xff;
+
+ // clear any pending sw interrupts
+ *REG32(INTC_ISR_CLEAR(0)) = 0xffffffff;
+ *REG32(INTC_ISR_CLEAR(1)) = 0xffffffff;
+ *REG32(INTC_ISR_CLEAR(2)) = 0xffffffff;
+
+ // globally unmask interrupts
+ *REG32(INTC_CONTROL) = 3; // reset and enable the controller
+}
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+ if (vector >= INT_VECTORS)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = false;
+
+ *REG32(INTC_MIR_SET(vectorToController(vector))) = 1 << (vector % 32);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+
+void platform_mask_irqs(void)
+{
+ int i;
+ for (i=0; i<INT_VECTORS; i++)
+ mask_interrupt(i, NULL);
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+ if (vector >= INT_VECTORS)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = false;
+
+ *REG32(INTC_MIR_CLEAR(vectorToController(vector))) = 1 << (vector % 32);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+enum handler_return platform_irq(struct arm_iframe *frame)
+{
+ // get the current vector
+ unsigned int vector;
+
+ // read the currently active IRQ
+ vector = *REG32(INTC_SIR_IRQ) & 0x7f;
+
+// TRACEF("spsr 0x%x, pc 0x%x, currthread %p, vector %d, handler %p\n", frame->spsr, frame->pc, current_thread, vector, int_handler_table[vector].handler);
+
+#if THREAD_STATS
+ thread_stats.interrupts++;
+#endif
+
+ // deliver the interrupt
+ enum handler_return ret;
+
+ ret = INT_NO_RESCHEDULE;
+ if (int_handler_table[vector].handler)
+ ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
+
+ // ack the interrupt
+ *REG32(INTC_CONTROL) = 0x1;
+
+ return ret;
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+ if (vector >= INT_VECTORS)
+ panic("register_int_handler: vector out of range %d\n", vector);
+
+ enter_critical_section();
+
+ int_handler_table[vector].arg = arg;
+ int_handler_table[vector].handler = handler;
+
+ exit_critical_section();
+}
+
+
diff --git a/platform/omap3/platform.c b/platform/omap3/platform.c
new file mode 100644
index 0000000..0df0469
--- /dev/null
+++ b/platform/omap3/platform.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <debug.h>
+#include <arch/arm/mmu.h>
+#include <platform.h>
+#include "platform_p.h"
+#include <platform/omap3.h>
+#include <dev/uart.h>
+
+void platform_init_mmu_mappings(void)
+{
+ /* do some memory map initialization */
+ addr_t addr;
+ arm_mmu_map_section(SDRAM_BASE, 0, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED);
+ for (addr = SDRAM_BASE; addr < SDRAM_BASE + SDRAM_SIZE; addr += (1024*1024)) {
+ arm_mmu_map_section(addr, addr, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED|MMU_FLAG_READWRITE);
+ }
+}
+
+void platform_early_init(void)
+{
+ /* initialize the interrupt controller */
+ platform_init_interrupts();
+
+ /* initialize the timer block */
+ platform_init_timer();
+
+ /* initialize the uart */
+ uart_init_early();
+}
+
+void platform_init(void)
+{
+}
+
diff --git a/platform/omap3/platform_p.h b/platform/omap3/platform_p.h
new file mode 100644
index 0000000..872ea2b
--- /dev/null
+++ b/platform/omap3/platform_p.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_P_H
+#define __PLATFORM_P_H
+
+void platform_init_interrupts(void);
+void platform_init_timer(void);
+
+#endif
+
diff --git a/platform/omap3/rules.mk b/platform/omap3/rules.mk
new file mode 100644
index 0000000..41da8e6
--- /dev/null
+++ b/platform/omap3/rules.mk
@@ -0,0 +1,23 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := cortex-a8
+CPU := generic
+
+INCLUDES += \
+ -I$(LOCAL_DIR)/include
+
+OBJS += \
+ $(LOCAL_DIR)/debug.o \
+ $(LOCAL_DIR)/interrupts.o \
+ $(LOCAL_DIR)/platform.o \
+ $(LOCAL_DIR)/timer.o \
+ $(LOCAL_DIR)/uart.o
+
+MEMBASE := 0x80000000
+
+DEFINES += MEMBASE=$(MEMBASE)
+
+LINKER_SCRIPT += \
+ $(BUILDDIR)/system-onesegment.ld
+
diff --git a/platform/omap3/timer.c b/platform/omap3/timer.c
new file mode 100644
index 0000000..7c2b1f3
--- /dev/null
+++ b/platform/omap3/timer.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <reg.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <platform/omap3.h>
+#include "platform_p.h"
+
+static time_t tick_interval;
+static platform_timer_callback t_callback;
+static void *callback_arg;
+
+/* timer 2 */
+static const ulong timer_base = OMAP34XX_GPT2;
+
+#define TIMER_TICK_RATE 32768
+
+#define TIMER_REG(reg) *REG32(timer_base + (reg))
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+ enter_critical_section();
+
+ t_callback = callback;
+ callback_arg = arg;
+ tick_interval = interval;
+ uint32_t ticks_per_interval = (uint64_t)interval * TIMER_TICK_RATE / 1000; // interval is in ms
+
+ TIMER_REG(TCLR) = 0; // stop the timer
+ TIMER_REG(TLDR) = -ticks_per_interval;
+ TIMER_REG(TTGR) = 1;
+ TIMER_REG(TIER) = 0x2;
+ TIMER_REG(TCLR) = 0x3; // autoreload, start
+
+ unmask_interrupt(GPT2_IRQ, NULL);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+ uint32_t delta_ticks;
+ uint32_t delta_ticks2;
+
+retry:
+ delta_ticks = *REG32(TIMER32K_CR);
+ delta_ticks2 = *REG32(TIMER32K_CR);
+ if (delta_ticks2 != delta_ticks)
+ goto retry;
+
+ uint64_t longtime = delta_ticks * 1000ULL / 32768ULL;
+
+ return (time_t)longtime;
+}
+
+bigtime_t current_time_hires(void)
+{
+ uint32_t delta_ticks;
+ uint32_t delta_ticks2;
+
+retry:
+ delta_ticks = *REG32(TIMER32K_CR);
+ delta_ticks2 = *REG32(TIMER32K_CR);
+ if (delta_ticks2 != delta_ticks)
+ goto retry;
+
+ uint64_t longtime = delta_ticks * 1000000ULL / 32768ULL;
+
+ return (bigtime_t)longtime;
+}
+static enum handler_return os_timer_tick(void *arg)
+{
+ TIMER_REG(TISR) = TIMER_REG(TISR);
+
+ return t_callback(callback_arg, current_time());
+}
+
+void platform_init_timer(void)
+{
+ // reset the GP timer
+ TIMER_REG(TIOCP_CFG) = 0x2;
+ while ((TIMER_REG(TISTAT) & 1) == 0)
+ ;
+
+ // set GPT2-9 clock inputs over to 32k
+ *REG32(CM_CLKSEL_PER) = 0;
+
+ // disable ints
+ TIMER_REG(TIER) = 0;
+ TIMER_REG(TISR) = 0x7; // clear any pending bits
+
+ // XXX make sure 32K timer is running
+
+ register_int_handler(GPT2_IRQ, &os_timer_tick, NULL);
+}
+
+void platform_halt_timers(void)
+{
+ TIMER_REG(TCLR) = 0;
+}
+
diff --git a/platform/omap3/uart.c b/platform/omap3/uart.c
new file mode 100644
index 0000000..e4c5102
--- /dev/null
+++ b/platform/omap3/uart.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <dev/uart.h>
+#include <platform/omap3.h>
+#include <target/debugconfig.h>
+
+struct uart_stat {
+ addr_t base;
+ uint shift;
+};
+
+static struct uart_stat uart[3] = {
+ { OMAP_UART1_BASE, 2 },
+ { OMAP_UART2_BASE, 2 },
+ { OMAP_UART3_BASE, 2 },
+};
+
+static inline void write_uart_reg(int port, uint reg, unsigned char data)
+{
+ *(volatile unsigned char *)(uart[port].base + (reg << uart[port].shift)) = data;
+}
+
+static inline unsigned char read_uart_reg(int port, uint reg)
+{
+ return *(volatile unsigned char *)(uart[port].base + (reg << uart[port].shift));
+}
+
+#define LCR_8N1 0x03
+
+#define FCR_FIFO_EN 0x01 /* Fifo enable */
+#define FCR_RXSR 0x02 /* Receiver soft reset */
+#define FCR_TXSR 0x04 /* Transmitter soft reset */
+
+#define MCR_DTR 0x01
+#define MCR_RTS 0x02
+#define MCR_DMA_EN 0x04
+#define MCR_TX_DFR 0x08
+
+#define LCR_WLS_MSK 0x03 /* character length select mask */
+#define LCR_WLS_5 0x00 /* 5 bit character length */
+#define LCR_WLS_6 0x01 /* 6 bit character length */
+#define LCR_WLS_7 0x02 /* 7 bit character length */
+#define LCR_WLS_8 0x03 /* 8 bit character length */
+#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */
+#define LCR_PEN 0x08 /* Parity eneble */
+#define LCR_EPS 0x10 /* Even Parity Select */
+#define LCR_STKP 0x20 /* Stick Parity */
+#define LCR_SBRK 0x40 /* Set Break */
+#define LCR_BKSE 0x80 /* Bank select enable */
+
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break */
+#define LSR_THRE 0x20 /* Xmit holding register empty */
+#define LSR_TEMT 0x40 /* Xmitter empty */
+#define LSR_ERR 0x80 /* Error */
+
+#define LCRVAL LCR_8N1 /* 8 data, 1 stop, no parity */
+#define MCRVAL (MCR_DTR | MCR_RTS) /* RTS/DTR */
+#define FCRVAL (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR) /* Clear & enable FIFOs */
+
+#define V_NS16550_CLK (48000000) /* 48MHz (APLL96/2) */
+
+void uart_init_port(int port, uint baud)
+{
+ /* clear the tx & rx fifo and disable */
+ uint16_t baud_divisor = (V_NS16550_CLK / 16 / baud);
+
+ write_uart_reg(port, UART_IER, 0);
+ write_uart_reg(port, UART_LCR, LCR_BKSE | LCRVAL); // config mode A
+ write_uart_reg(port, UART_DLL, baud_divisor & 0xff);
+ write_uart_reg(port, UART_DLH, (baud_divisor >> 8) & 0xff);
+ write_uart_reg(port, UART_LCR, LCRVAL); // operational mode
+ write_uart_reg(port, UART_MCR, MCRVAL);
+ write_uart_reg(port, UART_FCR, FCRVAL);
+ write_uart_reg(port, UART_MDR1, 0); // UART 16x mode
+
+// write_uart_reg(port, UART_LCR, 0xBF); // config mode B
+// write_uart_reg(port, UART_EFR, (1<<7)|(1<<6)); // hw flow control
+// write_uart_reg(port, UART_LCR, LCRVAL); // operational mode
+}
+
+void uart_init_early(void)
+{
+ uart_init_port(DEBUG_UART, 115200);
+}
+
+void uart_init(void)
+{
+}
+
+int uart_putc(int port, char c )
+{
+ while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the last char to get out
+ ;
+ write_uart_reg(port, UART_THR, c);
+ return 0;
+}
+
+int uart_getc(int port, bool wait) /* returns -1 if no data available */
+{
+ if (wait) {
+ while (!(read_uart_reg(port, UART_LSR) & (1<<0))) // wait for data to show up in the rx fifo
+ ;
+ } else {
+ if (!(read_uart_reg(port, UART_LSR) & (1<<0)))
+ return -1;
+ }
+ return read_uart_reg(port, UART_RHR);
+}
+
+void uart_flush_tx(int port)
+{
+ while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the last char to get out
+ ;
+}
+
+void uart_flush_rx(int port)
+{
+ // empty the rx fifo
+ while (read_uart_reg(port, UART_LSR) & (1<<0)) {
+ volatile char c = read_uart_reg(port, UART_RHR);
+ (void)c;
+ }
+}
+
+
diff --git a/platform/omap5912/debug.c b/platform/omap5912/debug.c
new file mode 100644
index 0000000..cb3ea29
--- /dev/null
+++ b/platform/omap5912/debug.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <debug.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <platform/debug.h>
+#include <arch/ops.h>
+#include <platform/omap5912.h>
+
+static void write_uart_reg(int uart, int reg, unsigned char data)
+{
+ unsigned long base;
+ int mul = 4;
+
+ switch(uart) {
+ case 0: base = UART0_BASE; break;
+ case 1: base = UART1_BASE; break;
+ case 2: base = UART2_BASE; break;
+ default: return;
+ }
+
+ *(volatile unsigned char *)(base + reg * mul) = data;
+}
+
+static unsigned char read_uart_reg(int uart, int reg)
+{
+ unsigned long base;
+ int mul = 4;
+
+ switch(uart) {
+ case 0: base = UART0_BASE; break;
+ case 1: base = UART1_BASE; break;
+ case 2: base = UART2_BASE; break;
+ default: return 0;
+ }
+
+ return *(volatile unsigned char *)(base + reg * mul);
+}
+
+static int uart_init(void)
+{
+ /* clear the tx & rx fifo and disable */
+ write_uart_reg(0, UART_FCR, 0x6);
+
+ return 0;
+}
+
+static int uart_putc(int port, char c )
+{
+ while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the shift register to empty
+ ;
+ write_uart_reg(port, UART_THR, c);
+ return 0;
+}
+
+static int uart_getc(int port, bool wait) /* returns -1 if no data available */
+{
+ if (wait) {
+ while (!(read_uart_reg(port, UART_LSR) & (1<<0))) // wait for data to show up in the rx fifo
+ ;
+ } else {
+ if (!(read_uart_reg(port, UART_LSR) & (1<<0)))
+ return -1;
+ }
+ return read_uart_reg(port, UART_RHR);
+}
+
+void dputc(char c)
+{
+ if (c == '\n')
+ uart_putc(0, '\r');
+ uart_putc(0, c);
+}
+
+int dgetc(char *c)
+{
+ int _c;
+
+ if ((_c = uart_getc(0, false)) < 0)
+ return -1;
+
+ *c = _c;
+ return 0;
+}
+
+void debug_dump_regs(void)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_halt(void)
+{
+ dprintf("HALT: spinning forever...\n");
+ for(;;);
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+uint32_t debug_cycle_count(void)
+{
+// PANIC_UNIMPLEMENTED;
+ return 0;
+}
diff --git a/platform/omap5912/include/platform/omap5912.h b/platform/omap5912/include/platform/omap5912.h
new file mode 100644
index 0000000..0255b82
--- /dev/null
+++ b/platform/omap5912/include/platform/omap5912.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __OMAP5912_H
+#define __OMAP5912_H
+
+/* memory map */
+#define SDRAM_BASE 0x10000000
+
+/* clocks */
+#define DPLL_CTRL (*(volatile unsigned short *)0xfffecf00)
+#define ARM_CKCTL (*(volatile unsigned int *)0xfffece00)
+#define ARM_SYSST (*(volatile unsigned int *)0xfffece18)
+
+/* uart */
+#define UART0_BASE 0xfffb0000
+#define UART1_BASE 0xfffb0800
+#define UART2_BASE 0xfffb9800
+
+#define UART_RHR 0
+#define UART_THR 0
+#define UART_DLL 0
+#define UART_IER 1
+#define UART_DLH 1
+#define UART_IIR 2
+#define UART_FCR 2
+#define UART_EFR 2
+#define UART_LCR 3
+#define UART_MCR 4
+#define UART_LSR 5
+#define UART_MSR 6
+#define UART_TCR 6
+#define UART_SPR 7
+#define UART_TLR 7
+#define UART_MDR1 8
+#define UART_MDR2 9
+#define UART_SFLSR 10
+#define UART_RESUME 11
+#define UART_TXFLL 10
+#define UART_TXFLH 11
+#define UART_SFREGL 12
+#define UART_SFREGH 13
+#define UART_RXFLL 12
+#define UART_RXFLH 13
+#define UART_BLR 14
+#define UART_UASR 14
+#define UART_ACREG 15
+#define UART_SCR 16
+#define UART_SSR 17
+#define UART_EBLR 18
+#define UART_MVR 19
+#define UART_SYSC 20
+
+/* timers */
+#define MPU_TIMER0_BASE 0xfffec500
+#define MPU_TIMER1_BASE 0xfffec600
+#define MPU_TIMER2_BASE 0xfffec700
+#define WATCHDOG_TIMER_BASE 0xfffec800
+#define OS_TIMER_BASE 0xfffb9000
+#define GP_TIMER1_BASE 0xfffb1400
+#define GP_TIMER2_BASE 0xfffb1c00
+#define GP_TIMER3_BASE 0xfffb2400
+#define GP_TIMER4_BASE 0xfffb2c00
+#define GP_TIMER5_BASE 0xfffb3400
+#define GP_TIMER6_BASE 0xfffb3c00
+#define GP_TIMER7_BASE 0xfffb4400
+#define GP_TIMER8_BASE 0xfffb5c00
+
+#define MPU_CNTL_TIMER1 (*(volatile unsigned int *)(MPU_TIMER1_BASE + 0x00))
+#define MPU_LOAD_TIMER1 (*(volatile unsigned int *)(MPU_TIMER1_BASE + 0x04))
+#define MPU_READ_TIMER1 (*(volatile unsigned int *)(MPU_TIMER1_BASE + 0x08))
+#define MPU_CNTL_TIMER2 (*(volatile unsigned int *)(MPU_TIMER2_BASE + 0x00))
+#define MPU_LOAD_TIMER2 (*(volatile unsigned int *)(MPU_TIMER2_BASE + 0x04))
+#define MPU_READ_TIMER2 (*(volatile unsigned int *)(MPU_TIMER2_BASE + 0x08))
+#define MPU_CNTL_TIMER3 (*(volatile unsigned int *)(MPU_TIMER3_BASE + 0x00))
+#define MPU_LOAD_TIMER3 (*(volatile unsigned int *)(MPU_TIMER3_BASE + 0x04))
+#define MPU_READ_TIMER3 (*(volatile unsigned int *)(MPU_TIMER3_BASE + 0x08))
+
+#define OS_TIMER_TICK_VALUE_REG (*(volatile unsigned int *)(OS_TIMER_BASE + 0x00))
+#define OS_TIMER_TICK_COUNTER_REG (*(volatile unsigned int *)(OS_TIMER_BASE + 0x04))
+#define OS_TIMER_CTRL_REG (*(volatile unsigned int *)(OS_TIMER_BASE + 0x08))
+
+
+/* interrupt controller */
+#define INT_VECTORS (32 + 128)
+#define INTCON0_BASE 0xfffecb00
+#define INTCON1_BASE 0xfffe0000
+#define INTCON2_BASE 0xfffe0100
+#define INTCON3_BASE 0xfffe0200
+#define INTCON4_BASE 0xfffe0300
+
+#define INTCON_ITR 0x00
+#define INTCON_MIR 0x04
+#define INTCON_SIR_IRQ 0x10
+#define INTCON_SIR_FIQ 0x14
+#define INTCON_CONTROL 0x18
+#define INTCON_ILR_BASE 0x1c
+#define INTCON_SISR 0x9c
+#define INTCON_GMR 0xa0 /* only on first level controller */
+#define INTCON_STATUS 0xa0 /* only on second level controllers */
+#define INTCON_OCP_CFG 0xa4
+#define INTCON_INTH_REV 0xa8
+
+/* interrupts */
+#define IRQ_TIMER3 16
+#define IRQ_GPTIMER1 17
+#define IRQ_GPTIMER2 18
+#define IRQ_TIMER1 26
+#define IRQ_WD_TIMER 27
+#define IRQ_TIMER2 30
+#define IRQ_OS_TIMER (32 + 22)
+#define IRQ_GPTIMER3 (32 + 34)
+#define IRQ_GPTIMER4 (32 + 35)
+#define IRQ_GPTIMER5 (32 + 36)
+#define IRQ_GPTIMER6 (32 + 37)
+#define IRQ_GPTIMER7 (32 + 38)
+#define IRQ_GPTIMER8 (32 + 39)
+
+#endif
+
diff --git a/platform/omap5912/interrupts.c b/platform/omap5912/interrupts.c
new file mode 100644
index 0000000..5621561
--- /dev/null
+++ b/platform/omap5912/interrupts.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <sys/types.h>
+#include <debug.h>
+#include <reg.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <arch/ops.h>
+#include <arch/arm.h>
+#include "platform_p.h"
+#include <platform/omap5912.h>
+
+struct int_handler_struct {
+ int_handler handler;
+ void *arg;
+};
+
+static struct int_handler_struct int_handler_table[INT_VECTORS];
+
+static const uint32_t icBase[5] = {
+ INTCON0_BASE, INTCON1_BASE, INTCON2_BASE, INTCON3_BASE, INTCON4_BASE };
+
+/* a bitmap of the level triggered interrupt vectors */
+static uint32_t level_trigger[5] = {
+ 0xb3fefe8f, // level 1 0-31
+ 0xfdb3c1fd, // level 2 0-31
+ 0xfffff7ff, // level 2 32-63
+ 0xbfffffff, // level 2 64-95
+ 0xffffffff // level 2 96-128
+};
+
+static inline volatile uint32_t *ICReg(uint controller, uint reg)
+{
+ return (volatile uint32_t *)(icBase[controller] + reg);
+}
+
+static inline uint32_t readICReg(uint controller, uint reg)
+{
+ return *ICReg(controller, reg);
+}
+static inline void writeICReg(uint controller, uint reg, uint val)
+{
+ *ICReg(controller, reg) = val;
+}
+
+static inline uint vectorToController(uint vector)
+{
+ return vector / 32;
+}
+
+void platform_init_interrupts(void)
+{
+ unsigned int i;
+
+ // mask all interrupts
+ *ICReg(0, INTCON_MIR) = 0xfffffffa;
+ *ICReg(1, INTCON_MIR) = 0xffffffff;
+ *ICReg(2, INTCON_MIR) = 0xffffffff;
+ *ICReg(3, INTCON_MIR) = 0xffffffff;
+ *ICReg(4, INTCON_MIR) = 0xffffffff;
+
+ // set up each of the interrupts
+ for (i = 0; i < INT_VECTORS; i++) {
+ // set each vector up as high priority, IRQ, and default edge/level sensitivity
+ *ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
+ }
+
+ // clear any pending interrupts
+ *ICReg(0, INTCON_ITR) = 0;
+ *ICReg(1, INTCON_ITR) = 0;
+ *ICReg(2, INTCON_ITR) = 0;
+ *ICReg(3, INTCON_ITR) = 0;
+ *ICReg(4, INTCON_ITR) = 0;
+
+ // globally unmask interrupts
+ *ICReg(1, INTCON_CONTROL) = 3;
+ *ICReg(0, INTCON_CONTROL) = 3;
+ *ICReg(0, INTCON_GMR) = 0;
+}
+
+status_t mask_interrupt(unsigned int vector, bool *oldstate)
+{
+ if (vector >= INT_VECTORS)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = false;
+
+ volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
+ *mir = *mir | (1<<(vector % 32));
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector, bool *oldstate)
+{
+ if (vector >= INT_VECTORS)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ if (oldstate)
+ *oldstate = false;
+
+ volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
+ *mir = *mir & ~(1<<(vector % 32));
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+enum handler_return platform_irq(struct arm_iframe *frame)
+{
+ // get the current vector
+ unsigned int vector;
+
+#if THREAD_STATS
+ thread_stats.interrupts++;
+#endif
+
+ // read from the first level int handler
+ vector = *ICReg(0, INTCON_SIR_IRQ);
+
+ // see if it's coming from the second level handler
+ if (vector == 0) {
+ vector = *ICReg(1, INTCON_SIR_IRQ) + 32;
+ }
+
+// dprintf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector);
+
+ // deliver the interrupt
+ enum handler_return ret;
+
+ ret = INT_NO_RESCHEDULE;
+ if (int_handler_table[vector].handler)
+ ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
+
+ // ack the interrupt
+ if (vector >= 32) {
+ // interrupt is chained, so ack the second level first, and then the first
+ *ICReg(vector / 32, INTCON_ITR) = ~(1 << (vector % 32));
+ *ICReg(1, INTCON_CONTROL) |= 1;
+ vector = 0; // force the following code to ack the chained first level vector
+ }
+
+ *ICReg(0, INTCON_ITR) = ~(1 << vector);
+ *ICReg(0, INTCON_CONTROL) = 1;
+
+ return ret;
+}
+
+void platform_fiq(struct arm_iframe *frame)
+{
+ PANIC_UNIMPLEMENTED;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+ if (vector >= INT_VECTORS)
+ panic("register_int_handler: vector out of range %d\n", vector);
+
+ enter_critical_section();
+
+ int_handler_table[vector].handler = handler;
+ int_handler_table[vector].arg = arg;
+
+ exit_critical_section();
+}
+
diff --git a/platform/omap5912/platform.c b/platform/omap5912/platform.c
new file mode 100644
index 0000000..1dd703d
--- /dev/null
+++ b/platform/omap5912/platform.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <debug.h>
+#include <platform.h>
+#include "platform_p.h"
+#include <platform/omap5912.h>
+#include <arch/arm/mmu.h>
+
+void platform_init_mmu_mappings(void)
+{
+ /* do some memory map initialization */
+ addr_t addr;
+ arm_mmu_map_section(SDRAM_BASE, 0, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED);
+ for (addr = SDRAM_BASE; addr < SDRAM_BASE + SDRAM_SIZE; addr += (1024*1024)) {
+ arm_mmu_map_section(addr, addr, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED|MMU_FLAG_READWRITE);
+ }
+}
+
+void platform_early_init(void)
+{
+ /* initialize the interrupt controller */
+ platform_init_interrupts();
+
+ /* initialize the timer block */
+ platform_init_timer();
+}
+
+void platform_init(void)
+{
+}
+
diff --git a/platform/omap5912/platform_p.h b/platform/omap5912/platform_p.h
new file mode 100644
index 0000000..872ea2b
--- /dev/null
+++ b/platform/omap5912/platform_p.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_P_H
+#define __PLATFORM_P_H
+
+void platform_init_interrupts(void);
+void platform_init_timer(void);
+
+#endif
+
diff --git a/platform/omap5912/rules.mk b/platform/omap5912/rules.mk
new file mode 100644
index 0000000..e1bddc1
--- /dev/null
+++ b/platform/omap5912/rules.mk
@@ -0,0 +1,24 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := arm926ej-s
+CPU := generic
+
+INCLUDES += \
+ -I$(LOCAL_DIR)/include
+
+OBJS += \
+ $(LOCAL_DIR)/debug.o \
+ $(LOCAL_DIR)/interrupts.o \
+ $(LOCAL_DIR)/platform.o \
+ $(LOCAL_DIR)/timer.o
+
+
+# $(LOCAL_DIR)/console.o \
+
+MEMBASE := 0x10000000
+#MEMSIZE := 0x02000000 # 32MB
+
+LINKER_SCRIPT += \
+ $(BUILDDIR)/system-onesegment.ld
+
diff --git a/platform/omap5912/timer.c b/platform/omap5912/timer.c
new file mode 100644
index 0000000..72659f1
--- /dev/null
+++ b/platform/omap5912/timer.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <kernel/thread.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <platform/omap5912.h>
+#include "platform_p.h"
+
+static time_t system_time = 0;
+
+static time_t tick_interval;
+static uint32_t ticks_per_interval;
+static platform_timer_callback t_callback;
+static void *callback_arg;
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+ enter_critical_section();
+
+ t_callback = callback;
+ callback_arg = arg;
+ tick_interval = interval;
+ ticks_per_interval = interval * 32768 / 1000; // interval is in ms
+
+ OS_TIMER_CTRL_REG = 0; // stop it
+ OS_TIMER_TICK_VALUE_REG = ticks_per_interval;
+ OS_TIMER_CTRL_REG = (1<<3) | (1<<2) | (1<<1) | (1<<0);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+ time_t t;
+ uint32_t delta_ticks;
+ uint32_t delta_ticks2;
+
+retry:
+ delta_ticks = OS_TIMER_TICK_COUNTER_REG;
+ t = system_time;
+ delta_ticks2 = OS_TIMER_TICK_COUNTER_REG;
+ if (delta_ticks2 > delta_ticks)
+ goto retry;
+
+ t += ((ticks_per_interval - delta_ticks2) * tick_interval) / ticks_per_interval;
+
+ return t;
+}
+
+bigtime_t current_time_hires(void)
+{
+ time_t t;
+ uint32_t delta_ticks;
+ uint32_t delta_ticks2;
+
+retry:
+ delta_ticks = OS_TIMER_TICK_COUNTER_REG;
+ t = system_time;
+ delta_ticks2 = OS_TIMER_TICK_COUNTER_REG;
+ if (delta_ticks2 > delta_ticks)
+ goto retry;
+
+ t += ((ticks_per_interval - delta_ticks2) * tick_interval) / ticks_per_interval;
+
+ return t * 1000ULL;
+}
+
+
+static enum handler_return os_timer_tick(void *arg)
+{
+ system_time += tick_interval;
+// dprintf("os_timer_tick %d\n", system_time);
+
+ return t_callback(callback_arg, system_time);
+}
+
+void platform_init_timer(void)
+{
+ OS_TIMER_CTRL_REG = 0; // stop the timer if it's already running
+
+ register_int_handler(IRQ_OS_TIMER, &os_timer_tick, NULL);
+ unmask_interrupt(IRQ_OS_TIMER, NULL);
+}
+
diff --git a/platform/rules.mk b/platform/rules.mk
new file mode 100644
index 0000000..c1acc50
--- /dev/null
+++ b/platform/rules.mk
@@ -0,0 +1,7 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+# shared platform code
+OBJS += \
+ $(LOCAL_DIR)/debug.o \
+ $(LOCAL_DIR)/init.o
+