initial commit of lk (little kernel) project
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;
+}
+