[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/lk/platform/bcm2835/include/platform/bcm2835.h b/src/bsp/lk/platform/bcm2835/include/platform/bcm2835.h
new file mode 100644
index 0000000..b44a0d2
--- /dev/null
+++ b/src/bsp/lk/platform/bcm2835/include/platform/bcm2835.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+#pragma once
+
+#define SDRAM_BASE 0
+
+#define BCM_PERIPH_BASE_PHYS    (0x3f000000U)
+#define BCM_PERIPH_SIZE         (0x01100000U)
+#define BCM_PERIPH_BASE_VIRT    (0xe0000000U)
+
+/* pointer to 'local' peripherals at 0x40000000 */
+#define BCM_LOCAL_PERIPH_BASE_VIRT (BCM_PERIPH_BASE_VIRT + 0x01000000)
+
+#define IC0_BASE                (BCM_PERIPH_BASE_VIRT + 0x2000)
+#define ST_BASE                 (BCM_PERIPH_BASE_VIRT + 0x3000)
+#define MPHI_BASE               (BCM_PERIPH_BASE_VIRT + 0x6000)
+#define DMA_BASE                (BCM_PERIPH_BASE_VIRT + 0x7000)
+#define ARM_BASE                (BCM_PERIPH_BASE_VIRT + 0xB000)
+#define PM_BASE                 (BCM_PERIPH_BASE_VIRT + 0x100000)
+#define PCM_CLOCK_BASE          (BCM_PERIPH_BASE_VIRT + 0x101098)
+#define RNG_BASE                (BCM_PERIPH_BASE_VIRT + 0x104000)
+#define GPIO_BASE               (BCM_PERIPH_BASE_VIRT + 0x200000)
+#define UART0_BASE              (BCM_PERIPH_BASE_VIRT + 0x201000)
+#define MMCI0_BASE              (BCM_PERIPH_BASE_VIRT + 0x202000)
+#define I2S_BASE                (BCM_PERIPH_BASE_VIRT + 0x203000)
+#define SPI0_BASE               (BCM_PERIPH_BASE_VIRT + 0x204000)
+#define BSC0_BASE               (BCM_PERIPH_BASE_VIRT + 0x205000)
+#define UART1_BASE              (BCM_PERIPH_BASE_VIRT + 0x215000)
+#define EMMC_BASE               (BCM_PERIPH_BASE_VIRT + 0x300000)
+#define SMI_BASE                (BCM_PERIPH_BASE_VIRT + 0x600000)
+#define BSC1_BASE               (BCM_PERIPH_BASE_VIRT + 0x804000)
+#define USB_BASE                (BCM_PERIPH_BASE_VIRT + 0x980000)
+#define MCORE_BASE              (BCM_PERIPH_BASE_VIRT + 0x0000)
+
+#define ARMCTRL_BASE            (ARM_BASE + 0x000)
+#define ARMCTRL_INTC_BASE       (ARM_BASE + 0x200)
+#define ARMCTRL_TIMER0_1_BASE   (ARM_BASE + 0x400)
+#define ARMCTRL_0_SBM_BASE      (ARM_BASE + 0x800)
+
+#define ARM_LOCAL_BASE          (BCM_LOCAL_PERIPH_BASE_VIRT)
+
+/* interrupts */
+#define ARM_IRQ1_BASE                  0
+#define INTERRUPT_TIMER0               (ARM_IRQ1_BASE + 0)
+#define INTERRUPT_TIMER1               (ARM_IRQ1_BASE + 1)
+#define INTERRUPT_TIMER2               (ARM_IRQ1_BASE + 2)
+#define INTERRUPT_TIMER3               (ARM_IRQ1_BASE + 3)
+#define INTERRUPT_CODEC0               (ARM_IRQ1_BASE + 4)
+#define INTERRUPT_CODEC1               (ARM_IRQ1_BASE + 5)
+#define INTERRUPT_CODEC2               (ARM_IRQ1_BASE + 6)
+#define INTERRUPT_VC_JPEG              (ARM_IRQ1_BASE + 7)
+#define INTERRUPT_ISP                  (ARM_IRQ1_BASE + 8)
+#define INTERRUPT_VC_USB               (ARM_IRQ1_BASE + 9)
+#define INTERRUPT_VC_3D                (ARM_IRQ1_BASE + 10)
+#define INTERRUPT_TRANSPOSER           (ARM_IRQ1_BASE + 11)
+#define INTERRUPT_MULTICORESYNC0       (ARM_IRQ1_BASE + 12)
+#define INTERRUPT_MULTICORESYNC1       (ARM_IRQ1_BASE + 13)
+#define INTERRUPT_MULTICORESYNC2       (ARM_IRQ1_BASE + 14)
+#define INTERRUPT_MULTICORESYNC3       (ARM_IRQ1_BASE + 15)
+#define INTERRUPT_DMA0                 (ARM_IRQ1_BASE + 16)
+#define INTERRUPT_DMA1                 (ARM_IRQ1_BASE + 17)
+#define INTERRUPT_VC_DMA2              (ARM_IRQ1_BASE + 18)
+#define INTERRUPT_VC_DMA3              (ARM_IRQ1_BASE + 19)
+#define INTERRUPT_DMA4                 (ARM_IRQ1_BASE + 20)
+#define INTERRUPT_DMA5                 (ARM_IRQ1_BASE + 21)
+#define INTERRUPT_DMA6                 (ARM_IRQ1_BASE + 22)
+#define INTERRUPT_DMA7                 (ARM_IRQ1_BASE + 23)
+#define INTERRUPT_DMA8                 (ARM_IRQ1_BASE + 24)
+#define INTERRUPT_DMA9                 (ARM_IRQ1_BASE + 25)
+#define INTERRUPT_DMA10                (ARM_IRQ1_BASE + 26)
+#define INTERRUPT_DMA11                (ARM_IRQ1_BASE + 27)
+#define INTERRUPT_DMA12                (ARM_IRQ1_BASE + 28)
+#define INTERRUPT_AUX                  (ARM_IRQ1_BASE + 29)
+#define INTERRUPT_ARM                  (ARM_IRQ1_BASE + 30)
+#define INTERRUPT_VPUDMA               (ARM_IRQ1_BASE + 31)
+
+#define ARM_IRQ2_BASE                  32
+#define INTERRUPT_HOSTPORT             (ARM_IRQ2_BASE + 0)
+#define INTERRUPT_VIDEOSCALER          (ARM_IRQ2_BASE + 1)
+#define INTERRUPT_CCP2TX               (ARM_IRQ2_BASE + 2)
+#define INTERRUPT_SDC                  (ARM_IRQ2_BASE + 3)
+#define INTERRUPT_DSI0                 (ARM_IRQ2_BASE + 4)
+#define INTERRUPT_AVE                  (ARM_IRQ2_BASE + 5)
+#define INTERRUPT_CAM0                 (ARM_IRQ2_BASE + 6)
+#define INTERRUPT_CAM1                 (ARM_IRQ2_BASE + 7)
+#define INTERRUPT_HDMI0                (ARM_IRQ2_BASE + 8)
+#define INTERRUPT_HDMI1                (ARM_IRQ2_BASE + 9)
+#define INTERRUPT_PIXELVALVE1          (ARM_IRQ2_BASE + 10)
+#define INTERRUPT_I2CSPISLV            (ARM_IRQ2_BASE + 11)
+#define INTERRUPT_DSI1                 (ARM_IRQ2_BASE + 12)
+#define INTERRUPT_PWA0                 (ARM_IRQ2_BASE + 13)
+#define INTERRUPT_PWA1                 (ARM_IRQ2_BASE + 14)
+#define INTERRUPT_CPR                  (ARM_IRQ2_BASE + 15)
+#define INTERRUPT_SMI                  (ARM_IRQ2_BASE + 16)
+#define INTERRUPT_GPIO0                (ARM_IRQ2_BASE + 17)
+#define INTERRUPT_GPIO1                (ARM_IRQ2_BASE + 18)
+#define INTERRUPT_GPIO2                (ARM_IRQ2_BASE + 19)
+#define INTERRUPT_GPIO3                (ARM_IRQ2_BASE + 20)
+#define INTERRUPT_VC_I2C               (ARM_IRQ2_BASE + 21)
+#define INTERRUPT_VC_SPI               (ARM_IRQ2_BASE + 22)
+#define INTERRUPT_VC_I2SPCM            (ARM_IRQ2_BASE + 23)
+#define INTERRUPT_VC_SDIO              (ARM_IRQ2_BASE + 24)
+#define INTERRUPT_VC_UART              (ARM_IRQ2_BASE + 25)
+#define INTERRUPT_SLIMBUS              (ARM_IRQ2_BASE + 26)
+#define INTERRUPT_VEC                  (ARM_IRQ2_BASE + 27)
+#define INTERRUPT_CPG                  (ARM_IRQ2_BASE + 28)
+#define INTERRUPT_RNG                  (ARM_IRQ2_BASE + 29)
+#define INTERRUPT_VC_ARASANSDIO        (ARM_IRQ2_BASE + 30)
+#define INTERRUPT_AVSPMON              (ARM_IRQ2_BASE + 31)
+
+/* ARM interrupts, which are mostly mirrored from bank 1 and 2 */
+#define ARM_IRQ0_BASE                  64
+#define INTERRUPT_ARM_TIMER            (ARM_IRQ0_BASE + 0)
+#define INTERRUPT_ARM_MAILBOX          (ARM_IRQ0_BASE + 1)
+#define INTERRUPT_ARM_DOORBELL_0       (ARM_IRQ0_BASE + 2)
+#define INTERRUPT_ARM_DOORBELL_1       (ARM_IRQ0_BASE + 3)
+#define INTERRUPT_VPU0_HALTED          (ARM_IRQ0_BASE + 4)
+#define INTERRUPT_VPU1_HALTED          (ARM_IRQ0_BASE + 5)
+#define INTERRUPT_ILLEGAL_TYPE0        (ARM_IRQ0_BASE + 6)
+#define INTERRUPT_ILLEGAL_TYPE1        (ARM_IRQ0_BASE + 7)
+#define INTERRUPT_PENDING1             (ARM_IRQ0_BASE + 8)
+#define INTERRUPT_PENDING2             (ARM_IRQ0_BASE + 9)
+#define INTERRUPT_JPEG                 (ARM_IRQ0_BASE + 10)
+#define INTERRUPT_USB                  (ARM_IRQ0_BASE + 11)
+#define INTERRUPT_3D                   (ARM_IRQ0_BASE + 12)
+#define INTERRUPT_DMA2                 (ARM_IRQ0_BASE + 13)
+#define INTERRUPT_DMA3                 (ARM_IRQ0_BASE + 14)
+#define INTERRUPT_I2C                  (ARM_IRQ0_BASE + 15)
+#define INTERRUPT_SPI                  (ARM_IRQ0_BASE + 16)
+#define INTERRUPT_I2SPCM               (ARM_IRQ0_BASE + 17)
+#define INTERRUPT_SDIO                 (ARM_IRQ0_BASE + 18)
+#define INTERRUPT_UART                 (ARM_IRQ0_BASE + 19)
+#define INTERRUPT_ARASANSDIO           (ARM_IRQ0_BASE + 20)
+
+#define ARM_IRQ_LOCAL_BASE             96
+#define INTERRUPT_ARM_LOCAL_CNTPSIRQ   (ARM_IRQ_LOCAL_BASE + 0)
+#define INTERRUPT_ARM_LOCAL_CNTPNSIRQ  (ARM_IRQ_LOCAL_BASE + 1)
+#define INTERRUPT_ARM_LOCAL_CNTHPIRQ   (ARM_IRQ_LOCAL_BASE + 2)
+#define INTERRUPT_ARM_LOCAL_CNTVIRQ    (ARM_IRQ_LOCAL_BASE + 3)
+#define INTERRUPT_ARM_LOCAL_MAILBOX0   (ARM_IRQ_LOCAL_BASE + 4)
+#define INTERRUPT_ARM_LOCAL_MAILBOX1   (ARM_IRQ_LOCAL_BASE + 5)
+#define INTERRUPT_ARM_LOCAL_MAILBOX2   (ARM_IRQ_LOCAL_BASE + 6)
+#define INTERRUPT_ARM_LOCAL_MAILBOX3   (ARM_IRQ_LOCAL_BASE + 7)
+#define INTERRUPT_ARM_LOCAL_GPU_FAST   (ARM_IRQ_LOCAL_BASE + 8)
+#define INTERRUPT_ARM_LOCAL_PMU_FAST   (ARM_IRQ_LOCAL_BASE + 9)
+#define INTERRUPT_ARM_LOCAL_ZERO       (ARM_IRQ_LOCAL_BASE + 10)
+#define INTERRUPT_ARM_LOCAL_TIMER      (ARM_IRQ_LOCAL_BASE + 11)
+
+#define MAX_INT INTERRUPT_ARM_LOCAL_TIMER
+
+
diff --git a/src/bsp/lk/platform/bcm2835/include/platform/gic.h b/src/bsp/lk/platform/bcm2835/include/platform/gic.h
new file mode 100644
index 0000000..d1e7c8c
--- /dev/null
+++ b/src/bsp/lk/platform/bcm2835/include/platform/gic.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+#pragma once
+
+#include <platform/bcm2835.h>
+
+#define GICBASE(n)  (CPUPRIV_BASE_PHYS)
+#define GICC_OFFSET (0x0100)
+#define GICD_OFFSET (0x1000)
+
+
diff --git a/src/bsp/lk/platform/bcm2835/intc.c b/src/bsp/lk/platform/bcm2835/intc.c
new file mode 100644
index 0000000..97688ab
--- /dev/null
+++ b/src/bsp/lk/platform/bcm2835/intc.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2015 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 <trace.h>
+#include <assert.h>
+#include <err.h>
+#include <bits.h>
+#include <arch/arm.h>
+#include <kernel/spinlock.h>
+#include <kernel/thread.h>
+#include <kernel/mp.h>
+#include <platform/interrupts.h>
+#include <platform/bcm2835.h>
+
+#define LOCAL_TRACE 0
+
+/* global interrupt controller */
+#define INTC_PEND0  (ARMCTRL_INTC_BASE + 0x0)
+#define INTC_PEND1  (ARMCTRL_INTC_BASE + 0x4)
+#define INTC_PEND2  (ARMCTRL_INTC_BASE + 0x8)
+#define INTC_FAST   (ARMCTRL_INTC_BASE + 0xc)
+#define INTC_ENABLE1   (ARMCTRL_INTC_BASE + 0x10)
+#define INTC_ENABLE2   (ARMCTRL_INTC_BASE + 0x14)
+#define INTC_ENABLE3   (ARMCTRL_INTC_BASE + 0x18)
+#define INTC_DISABLE1   (ARMCTRL_INTC_BASE + 0x1c)
+#define INTC_DISABLE2   (ARMCTRL_INTC_BASE + 0x20)
+#define INTC_DISABLE3   (ARMCTRL_INTC_BASE + 0x24)
+
+/* per-cpu local interrupt controller bits.
+ * each is repeated 4 times, one per cpu.
+ */
+#define INTC_LOCAL_TIMER_INT_CONTROL0 (ARM_LOCAL_BASE + 0x40)
+#define INTC_LOCAL_TIMER_INT_CONTROL1 (ARM_LOCAL_BASE + 0x44)
+#define INTC_LOCAL_TIMER_INT_CONTROL2 (ARM_LOCAL_BASE + 0x48)
+#define INTC_LOCAL_TIMER_INT_CONTROL3 (ARM_LOCAL_BASE + 0x4c)
+
+#define INTC_LOCAL_MAILBOX_INT_CONTROL0 (ARM_LOCAL_BASE + 0x50)
+#define INTC_LOCAL_MAILBOX_INT_CONTROL1 (ARM_LOCAL_BASE + 0x54)
+#define INTC_LOCAL_MAILBOX_INT_CONTROL2 (ARM_LOCAL_BASE + 0x58)
+#define INTC_LOCAL_MAILBOX_INT_CONTROL3 (ARM_LOCAL_BASE + 0x5c)
+
+#define INTC_LOCAL_IRQ_PEND0 (ARM_LOCAL_BASE + 0x60)
+#define INTC_LOCAL_IRQ_PEND1 (ARM_LOCAL_BASE + 0x64)
+#define INTC_LOCAL_IRQ_PEND2 (ARM_LOCAL_BASE + 0x68)
+#define INTC_LOCAL_IRQ_PEND3 (ARM_LOCAL_BASE + 0x6c)
+
+#define INTC_LOCAL_FIQ_PEND0 (ARM_LOCAL_BASE + 0x70)
+#define INTC_LOCAL_FIQ_PEND1 (ARM_LOCAL_BASE + 0x74)
+#define INTC_LOCAL_FIQ_PEND2 (ARM_LOCAL_BASE + 0x78)
+#define INTC_LOCAL_FIQ_PEND3 (ARM_LOCAL_BASE + 0x7c)
+
+#define INTC_LOCAL_MAILBOX0_SET0 (ARM_LOCAL_BASE + 0x80)
+#define INTC_LOCAL_MAILBOX0_SET1 (ARM_LOCAL_BASE + 0x90)
+#define INTC_LOCAL_MAILBOX0_SET2 (ARM_LOCAL_BASE + 0xa0)
+#define INTC_LOCAL_MAILBOX0_SET3 (ARM_LOCAL_BASE + 0xb0)
+
+#define INTC_LOCAL_MAILBOX0_CLR0 (ARM_LOCAL_BASE + 0xc0)
+#define INTC_LOCAL_MAILBOX0_CLR1 (ARM_LOCAL_BASE + 0xd0)
+#define INTC_LOCAL_MAILBOX0_CLR2 (ARM_LOCAL_BASE + 0xe0)
+#define INTC_LOCAL_MAILBOX0_CLR3 (ARM_LOCAL_BASE + 0xf0)
+
+struct int_handler_struct {
+    int_handler handler;
+    void *arg;
+};
+
+static struct int_handler_struct int_handler_table[MAX_INT];
+
+static spin_lock_t lock = SPIN_LOCK_INITIAL_VALUE;
+
+status_t mask_interrupt(unsigned int vector)
+{
+    LTRACEF("vector %u\n", vector);
+
+    spin_lock_saved_state_t state;
+    spin_lock_irqsave(&lock, state);
+
+    if (vector >= INTERRUPT_ARM_LOCAL_CNTPSIRQ && vector <= INTERRUPT_ARM_LOCAL_CNTVIRQ) {
+        // local timer interrupts, mask on all cpus
+        for (uint cpu = 0; cpu < 4; cpu++) {
+            uintptr_t reg = INTC_LOCAL_TIMER_INT_CONTROL0 + cpu * 4;
+
+            *REG32(reg) &= (1 << (vector - INTERRUPT_ARM_LOCAL_CNTPSIRQ));
+        }
+    } else if (/* vector >= ARM_IRQ1_BASE && */ vector < (ARM_IRQ0_BASE + 32)) {
+        uintptr_t reg;
+        if (vector >= ARM_IRQ0_BASE)
+            reg = INTC_DISABLE3;
+        else if (vector >= ARM_IRQ2_BASE)
+            reg = INTC_DISABLE2;
+        else
+            reg = INTC_DISABLE1;
+
+        *REG32(reg) = 1 << (vector % 32);
+    } else {
+        PANIC_UNIMPLEMENTED;
+    }
+
+    spin_unlock_irqrestore(&lock, state);
+
+    return NO_ERROR;
+}
+
+status_t unmask_interrupt(unsigned int vector)
+{
+    LTRACEF("vector %u\n", vector);
+
+    spin_lock_saved_state_t state;
+    spin_lock_irqsave(&lock, state);
+
+    if (vector >= INTERRUPT_ARM_LOCAL_CNTPSIRQ && vector <= INTERRUPT_ARM_LOCAL_CNTVIRQ) {
+        // local timer interrupts, unmask for all cpus
+        for (uint cpu = 0; cpu < 4; cpu++) {
+            uintptr_t reg = INTC_LOCAL_TIMER_INT_CONTROL0 + cpu * 4;
+
+            *REG32(reg) |= (1 << (vector - INTERRUPT_ARM_LOCAL_CNTPSIRQ));
+        }
+    } else if (/* vector >= ARM_IRQ1_BASE && */ vector < (ARM_IRQ0_BASE + 32)) {
+        uintptr_t reg;
+        if (vector >= ARM_IRQ0_BASE)
+            reg = INTC_ENABLE3;
+        else if (vector >= ARM_IRQ2_BASE)
+            reg = INTC_ENABLE2;
+        else
+            reg = INTC_ENABLE1;
+
+        *REG32(reg) = 1 << (vector % 32);
+    } else {
+        PANIC_UNIMPLEMENTED;
+    }
+
+    spin_unlock_irqrestore(&lock, state);
+
+    return NO_ERROR;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+    if (vector >= MAX_INT)
+        panic("register_int_handler: vector out of range %d\n", vector);
+
+    spin_lock_saved_state_t state;
+    spin_lock_irqsave(&lock, state);
+
+    int_handler_table[vector].handler = handler;
+    int_handler_table[vector].arg = arg;
+
+    spin_unlock_irqrestore(&lock, state);
+}
+
+enum handler_return platform_irq(struct arm_iframe *frame)
+{
+    uint vector;
+    uint cpu = arch_curr_cpu_num();
+
+    THREAD_STATS_INC(interrupts);
+
+    // see what kind of irq it is
+    uint32_t pend = *REG32(INTC_LOCAL_IRQ_PEND0 + cpu * 4);
+
+    pend &= ~(1 << (INTERRUPT_ARM_LOCAL_GPU_FAST % 32)); // mask out gpu interrupts
+
+    if (pend != 0) {
+        // it's a local interrupt
+        LTRACEF("local pend 0x%x\n", pend);
+        vector = ARM_IRQ_LOCAL_BASE + ctz(pend);
+        goto decoded;
+    }
+
+    // XXX disable for now, since all of the interesting irqs are mirrored into the other banks
+#if 0
+    // look in bank 0 (ARM interrupts)
+    pend = *REG32(INTC_PEND0);
+    LTRACEF("pend0 0x%x\n", pend);
+    pend &= ~((1<<8)|(1<<9)); // mask out bit 8 and 9
+    if (pend != 0) {
+        // it's a bank 0 interrupt
+        vector = ARM_IRQ0_BASE + ctz(pend);
+        goto decoded;
+    }
+#endif
+
+    // look for VC interrupt bank 1
+    pend = *REG32(INTC_PEND1);
+    LTRACEF("pend1 0x%x\n", pend);
+    if (pend != 0) {
+        // it's a bank 1 interrupt
+        vector = ARM_IRQ1_BASE + ctz(pend);
+        goto decoded;
+    }
+
+    // look for VC interrupt bank 2
+    pend = *REG32(INTC_PEND2);
+    LTRACEF("pend2 0x%x\n", pend);
+    if (pend != 0) {
+        // it's a bank 2 interrupt
+        vector = ARM_IRQ2_BASE + ctz(pend);
+        goto decoded;
+    }
+
+    vector = 0xffffffff;
+
+decoded:
+    LTRACEF("cpu %u vector %u\n", cpu, vector);
+
+    // dispatch the irq
+    enum handler_return ret = INT_NO_RESCHEDULE;
+
+#if WITH_SMP
+    if (vector == INTERRUPT_ARM_LOCAL_MAILBOX0) {
+        pend = *REG32(INTC_LOCAL_MAILBOX0_CLR0 + 0x10 * cpu);
+        LTRACEF("mailbox0 clr 0x%x\n", pend);
+
+        // ack it
+        *REG32(INTC_LOCAL_MAILBOX0_CLR0 + 0x10 * cpu) = pend;
+
+        if (pend & (1 << MP_IPI_GENERIC)) {
+            PANIC_UNIMPLEMENTED;
+        }
+        if (pend & (1 << MP_IPI_RESCHEDULE)) {
+            ret = mp_mbx_reschedule_irq();
+        }
+    } else
+#endif // WITH_SMP
+    if (vector == 0xffffffff) {
+        ret = INT_NO_RESCHEDULE;
+    } else if (int_handler_table[vector].handler) {
+        ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
+    } else {
+        panic("irq %u fired on cpu %u but no handler set!\n", vector, cpu);
+    }
+
+    return ret;
+}
+
+enum handler_return platform_fiq(struct arm_iframe *frame)
+{
+    PANIC_UNIMPLEMENTED;
+}
+
+void bcm2835_send_ipi(uint irq, uint cpu_mask)
+{
+    LTRACEF("irq %u, cpu_mask 0x%x\n", irq, cpu_mask);
+
+    for (uint i = 0; i < 4; i++) {
+        if (cpu_mask & (1<<i)) {
+            LTRACEF("sending to cpu %u\n", i);
+            *REG32(INTC_LOCAL_MAILBOX0_SET0 + 0x10 * i) = (1 << irq);
+        }
+    }
+}
+
+void intc_init(void)
+{
+    // mask everything
+    *REG32(INTC_DISABLE1) = 0xffffffff;
+    *REG32(INTC_DISABLE2) = 0xffffffff;
+    *REG32(INTC_DISABLE3) = 0xffffffff;
+
+#if WITH_SMP
+    // unable mailbox irqs on all cores
+    for (uint i = 0; i < 4; i++) {
+        *REG32(INTC_LOCAL_MAILBOX_INT_CONTROL0 + 0x4 * i) = 0x1;
+    }
+#endif
+}
+
diff --git a/src/bsp/lk/platform/bcm2835/platform.c b/src/bsp/lk/platform/bcm2835/platform.c
new file mode 100644
index 0000000..453aaf9
--- /dev/null
+++ b/src/bsp/lk/platform/bcm2835/platform.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015 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 <reg.h>
+#include <err.h>
+#include <debug.h>
+#include <trace.h>
+#include <dev/uart.h>
+#include <arch.h>
+#include <arch/arm.h>
+#include <arch/arm/mmu.h>
+#include <lk/init.h>
+#include <kernel/vm.h>
+#include <kernel/spinlock.h>
+#include <dev/timer/arm_generic.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/bcm2835.h>
+
+extern void intc_init(void);
+extern void arm_reset(void);
+
+/* initial memory mappings. parsed by start.S */
+struct mmu_initial_mapping mmu_initial_mappings[] = {
+    /* 1GB of sdram space */
+    { .phys = SDRAM_BASE,
+      .virt = KERNEL_BASE,
+      .size = MEMSIZE,
+      .flags = 0,
+      .name = "memory" },
+
+    /* peripherals */
+    { .phys = BCM_PERIPH_BASE_PHYS,
+      .virt = BCM_PERIPH_BASE_VIRT,
+      .size = BCM_PERIPH_SIZE,
+      .flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
+      .name = "bcm peripherals" },
+
+    /* identity map to let the boot code run */
+    { .phys = SDRAM_BASE,
+      .virt = SDRAM_BASE,
+      .size = 16*1024*1024,
+      .flags = MMU_INITIAL_MAPPING_TEMPORARY },
+
+    /* null entry to terminate the list */
+    { 0 }
+};
+
+static pmm_arena_t arena = {
+    .name = "sdram",
+    .base = SDRAM_BASE,
+    .size = MEMSIZE,
+    .flags = PMM_ARENA_FLAG_KMAP,
+};
+
+void platform_init_mmu_mappings(void)
+{
+}
+
+void platform_early_init(void)
+{
+    uart_init_early();
+
+    intc_init();
+
+    arm_generic_timer_init(INTERRUPT_ARM_LOCAL_CNTPNSIRQ, 1000000);
+
+    /* add the main memory arena */
+    pmm_add_arena(&arena);
+
+#if WITH_SMP
+    /* start the other cpus */
+    uintptr_t sec_entry = (uintptr_t)&arm_reset;
+    sec_entry -= (KERNEL_BASE - MEMBASE);
+    for (uint i = 1; i <= 3; i++) {
+        *REG32(ARM_LOCAL_BASE + 0x8c + 0x10 * i) = sec_entry;
+    }
+#endif
+}
+
+void platform_init(void)
+{
+    uart_init();
+}
+
+#define DEBUG_UART 0
+
+void platform_dputc(char c)
+{
+    if (c == '\n')
+        uart_putc(DEBUG_UART, '\r');
+    uart_putc(DEBUG_UART, c);
+}
+
+int platform_dgetc(char *c, bool wait)
+{
+    int ret = uart_getc(DEBUG_UART, wait);
+    if (ret == -1)
+        return -1;
+    *c = ret;
+    return 0;
+}
+
diff --git a/src/bsp/lk/platform/bcm2835/rules.mk b/src/bsp/lk/platform/bcm2835/rules.mk
new file mode 100644
index 0000000..62b6da5
--- /dev/null
+++ b/src/bsp/lk/platform/bcm2835/rules.mk
@@ -0,0 +1,41 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+ARCH := arm
+ARM_CPU := cortex-a7
+WITH_SMP := 1
+SMP_CPU_ID_BITS := 8
+
+MODULE_DEPS := \
+	dev/timer/arm_generic \
+	lib/cbuf
+
+#lib/bio \
+	lib/cbuf \
+	lib/minip \
+	dev/interrupt/arm_gic \
+	dev/timer/arm_cortex_a9
+
+MODULE_SRCS += \
+	$(LOCAL_DIR)/intc.c \
+	$(LOCAL_DIR)/platform.c \
+	$(LOCAL_DIR)/uart.c \
+
+# default to no sdram unless the target calls it out
+ZYNQ_SDRAM_SIZE ?= 0
+
+MEMBASE := 0x00000000
+MEMSIZE ?= 0x10000000 # 256MB
+KERNEL_LOAD_OFFSET := 0x00008000 # loaded 32KB into physical
+
+# put our kernel at 0x80000000
+KERNEL_BASE = 0x80000000
+
+GLOBAL_DEFINES += \
+	ARM_ARCH_WAIT_FOR_SECONDARIES=1
+
+LINKER_SCRIPT += \
+	$(BUILDDIR)/system-onesegment.ld
+
+include make/module.mk
diff --git a/src/bsp/lk/platform/bcm2835/uart.c b/src/bsp/lk/platform/bcm2835/uart.c
new file mode 100644
index 0000000..5c3d5ab
--- /dev/null
+++ b/src/bsp/lk/platform/bcm2835/uart.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015 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 <reg.h>
+#include <stdio.h>
+#include <trace.h>
+#include <lib/cbuf.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <platform/debug.h>
+#include <platform/bcm2835.h>
+
+/* TODO: extract this into a generic PL011 driver */
+
+/* PL011 implementation */
+#define UART_DR    (0x00)
+#define UART_RSR   (0x04)
+#define UART_TFR   (0x18)
+#define UART_ILPR  (0x20)
+#define UART_IBRD  (0x24)
+#define UART_FBRD  (0x28)
+#define UART_LCRH  (0x2c)
+#define UART_CR    (0x30)
+#define UART_IFLS  (0x34)
+#define UART_IMSC  (0x38)
+#define UART_TRIS  (0x3c)
+#define UART_TMIS  (0x40)
+#define UART_ICR   (0x44)
+#define UART_DMACR (0x48)
+
+#define UARTREG(base, reg)  (*REG32((base)  + (reg)))
+
+#define RXBUF_SIZE 16
+#define NUM_UART 1
+
+static cbuf_t uart_rx_buf[NUM_UART];
+
+static inline uintptr_t uart_to_ptr(unsigned int n)
+{
+    switch (n) {
+        default:
+        case 0: return UART0_BASE;
+    }
+}
+
+static enum handler_return uart_irq(void *arg)
+{
+    bool resched = false;
+    uint port = (uint)arg;
+    uintptr_t base = uart_to_ptr(port);
+
+    /* read interrupt status and mask */
+    uint32_t isr = UARTREG(base, UART_TMIS);
+
+    if (isr & ((1<<6) | (1<<4))) { // rtmis, rxmis
+        UARTREG(base, UART_ICR) = (1<<4);
+        cbuf_t *rxbuf = &uart_rx_buf[port];
+
+        /* while fifo is not empty, read chars out of it */
+        while ((UARTREG(base, UART_TFR) & (1<<4)) == 0) {
+            char c = UARTREG(base, UART_DR);
+            cbuf_write_char(rxbuf, c, false);
+
+            resched = true;
+        }
+    }
+
+    return resched ? INT_RESCHEDULE : INT_NO_RESCHEDULE;
+}
+
+void uart_init(void)
+{
+    for (size_t i = 0; i < NUM_UART; i++) {
+        // create circular buffer to hold received data
+        cbuf_initialize(&uart_rx_buf[i], RXBUF_SIZE);
+
+        // assumes interrupts are contiguous
+        register_int_handler(INTERRUPT_VC_UART + i, &uart_irq, (void *)i);
+
+        // clear all irqs
+        UARTREG(uart_to_ptr(i), UART_ICR) = 0x3ff;
+
+        // set fifo trigger level
+        UARTREG(uart_to_ptr(i), UART_IFLS) = 0; // 1/8 rxfifo, 1/8 txfifo
+
+        // enable rx interrupt
+        UARTREG(uart_to_ptr(i), UART_IMSC) = (1<<6)|(1<<4); // rtim, rxim
+
+        // enable receive
+        UARTREG(uart_to_ptr(i), UART_CR) |= (1<<9); // rxen
+
+        // enable interrupt
+        unmask_interrupt(INTERRUPT_VC_UART + i);
+    }
+}
+
+void uart_init_early(void)
+{
+    for (size_t i = 0; i < NUM_UART; i++) {
+        UARTREG(uart_to_ptr(i), UART_CR) = (1<<8)|(1<<0); // tx_enable, uarten
+    }
+}
+
+int uart_putc(int port, char c)
+{
+    uintptr_t base = uart_to_ptr(port);
+
+    /* spin while fifo is full */
+    while (UARTREG(base, UART_TFR) & (1<<5))
+        ;
+    UARTREG(base, UART_DR) = c;
+
+    return 1;
+}
+
+int uart_getc(int port, bool wait)
+{
+    cbuf_t *rxbuf = &uart_rx_buf[port];
+
+    char c;
+    if (cbuf_read_char(rxbuf, &c, wait) == 1)
+        return c;
+
+    return -1;
+}
+
+void uart_flush_tx(int port)
+{
+}
+
+void uart_flush_rx(int port)
+{
+}
+
+void uart_init_port(int port, uint baud)
+{
+}
+
+