[PATCH] target/boards: add infrastructure for loaders for Mediatek platforms

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/baseband-devel@lists.osmocom.org/.

Wolfram Sang wolfram at the-dreams.de
Thu Apr 28 19:46:14 UTC 2011


We are just interested in the loaders here, no other applications needed.
Split it from the compal-based phones. Add mt62xx as first user.

Based on a patch by Steve, but cleaned up and seperated from compal/calypso.

Signed-off-by: Steve Markgraf <steve at steve-m.de>
Signed-off-by: Wolfram Sang <wolfram at the-dreams.de>
---

The new loader was succesfully tested on my Sciphone G2 by loading and
executing a bootloader.

This should get rid of the branches

  remotes/origin/steve-m/loader_sciphone
  remotes/origin/steve-m/mtk_hack

 src/Makefile                                       |    8 +-
 src/target/firmware/Makefile.mtk                   |   34 ++
 src/target/firmware/apps/loader_mtk/main.c         |  394 +++++++++++++++++
 .../board/mediatek/exceptions_redirected.S         |   20 +
 src/target/firmware/board/mediatek/handlers.S      |   82 ++++
 src/target/firmware/board/mediatek/header.S        |   11 +
 src/target/firmware/board/mediatek/macros.S        |   76 ++++
 src/target/firmware/board/mediatek/ram.lds         |  120 ++++++
 src/target/firmware/board/mediatek/start.ram.S     |   26 ++
 src/target/firmware/board/mediatek/uart.c          |  441 ++++++++++++++++++++
 src/target/firmware/board/mt62xx/init.c            |  140 +++++++
 src/target/firmware/include/mtk/emi.h              |   42 ++
 src/target/firmware/include/mtk/mt6235.h           |   74 ++++
 src/target/firmware/include/mtk/system.h           |  195 +++++++++
 14 files changed, 1662 insertions(+), 1 deletions(-)
 create mode 100644 src/target/firmware/Makefile.mtk
 create mode 100644 src/target/firmware/apps/loader_mtk/main.c
 create mode 100644 src/target/firmware/board/mediatek/exceptions_redirected.S
 create mode 100644 src/target/firmware/board/mediatek/handlers.S
 create mode 100644 src/target/firmware/board/mediatek/header.S
 create mode 100644 src/target/firmware/board/mediatek/macros.S
 create mode 100644 src/target/firmware/board/mediatek/ram.lds
 create mode 100644 src/target/firmware/board/mediatek/start.ram.S
 create mode 100644 src/target/firmware/board/mediatek/uart.c
 create mode 100644 src/target/firmware/board/mt62xx/init.c
 create mode 100644 src/target/firmware/include/mtk/emi.h
 create mode 100644 src/target/firmware/include/mtk/mt6235.h
 create mode 100644 src/target/firmware/include/mtk/system.h

diff --git a/src/Makefile b/src/Makefile
index 1b6f2f7..d6f556f 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -17,7 +17,7 @@ OSMOCORE_CONFIGURE_ENV= LIBOSMOCORE_LIBS=$(TOPDIR)/shared/libosmocore/build-host
 	 	    	LIBOSMOVTY_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include \
 			LIBOSMOGSM_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include
 
-all: libosmocore-target nofirmware firmware
+all: libosmocore-target nofirmware firmware mtk-firmware
 nofirmware: libosmocore-host layer23 osmocon gsmmap
 
 libosmocore-host: shared/libosmocore/build-host/src/.libs/libosmocore.la
@@ -93,6 +93,10 @@ host/layer23/layer23: host/layer23/Makefile libosmocore-host
 firmware: libosmocore-target
 	make -C target/firmware CROSS_COMPILE=$(CROSS_TOOL_PREFIX)
 
+.PHONY: mtk-firmware
+mtk-firmware: libosmocore-target
+	make -C target/firmware -f Makefile.mtk CROSS_COMPILE=$(CROSS_TOOL_PREFIX)
+
 
 clean:
 	make -C shared/libosmocore/build-host $@
@@ -100,10 +104,12 @@ clean:
 	make -C host/layer23 $@
 	make -C host/osmocon $@
 	make -C target/firmware $@
+	make -C target/firmware -f Makefile.mtk $@
 
 distclean:
 	rm -rf shared/libosmocore/build-host
 	rm -rf shared/libosmocore/build-target
 	make -C host/layer23 $@
 	make -C host/osmocon $@
+# 'firmware' also handles 'mtk-firmware'
 	make -C target/firmware $@
diff --git a/src/target/firmware/Makefile.mtk b/src/target/firmware/Makefile.mtk
new file mode 100644
index 0000000..3a8d57b
--- /dev/null
+++ b/src/target/firmware/Makefile.mtk
@@ -0,0 +1,34 @@
+# List of all supported boards (meant to be overridden on command line)
+BOARDS?=mt62xx
+
+# List of all applications (meant to be overridden on command line)
+APPLICATIONS?=loader_mtk
+
+mtkram_LDS=board/mediatek/ram.lds
+mtkram_OBJS=board/mediatek/start.ram.o board/mediatek/exceptions_redirected.o board/mediatek/handlers.o
+
+mtk_COMMON_OBJS=board/mediatek/uart.o
+
+# Mediatek MT62xx
+mt62xx_OBJS=$(mtk_COMMON_OBJS) board/mt62xx/init.o
+mt62xx_ENVIRONMENTS=mtkram
+
+# Global include path
+INCLUDES=-Iinclude/ -I../../../include -I../../shared/libosmocore/include
+
+FLASH_OBJS=flash/cfi_flash.o
+
+# Objects that go in all applications
+ANY_APP_OBJS+=$(FLASH_OBJS)
+
+# Various objects that are currently linked into all applications
+# (should not use libcalypso; needed functionality should be refactored (yeah, unlikely, I know))
+ANY_APP_LIBS+=calypso/libcalypso.a lib/libmini.a comm/libcomm.a ../../shared/libosmocore/build-target/src/.libs/libosmocore.a
+
+# Libraries are defined in subdirectories
+-include calypso/Makefile
+-include comm/Makefile
+-include lib/Makefile
+
+# Include rules
+-include Makefile.inc
diff --git a/src/target/firmware/apps/loader_mtk/main.c b/src/target/firmware/apps/loader_mtk/main.c
new file mode 100644
index 0000000..cabcf1d
--- /dev/null
+++ b/src/target/firmware/apps/loader_mtk/main.c
@@ -0,0 +1,394 @@
+/*
+ * boot loader for MTK phones (based on the calypso-version)
+ *
+ * (C) 2010 by Ingo Albrecht <prom at berlin.ccc.de>
+ * (C) 2011 by Wolfram Sang <wolfram at the-dreams.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <debug.h>
+#include <memory.h>
+#include <delay.h>
+#include <keypad.h>
+#include <board.h>
+#include <console.h>
+#include <manifest.h>
+
+#include <osmocom/core/crc16.h>
+
+#include <comm/sercomm.h>
+
+#include <calypso/uart.h>
+
+#include <flash/cfi_flash.h>
+
+#include <mtk/emi.h>
+#include <mtk/mt6235.h>
+#include <mtk/system.h>
+
+#include "../loader/protocol.h"
+
+/* Main Program */
+const char *hr =
+    "======================================================================\n";
+
+static void key_handler(enum key_codes code, enum key_states state);
+static void cmd_handler(uint8_t dlci, struct msgb *msg);
+
+int flag = 0;
+
+static void flush_uart(void)
+{
+	unsigned i;
+	for (i = 0; i < 500; i++) {
+		uart_poll(SERCOMM_UART_NR);
+		delay_ms(1);
+	}
+}
+
+static void device_poweroff(void)
+{
+	flush_uart();
+	writew(BBPU_MAGIC | RTC_BBPU_WRITE_EN,
+	       MTK_RTC_BBPU);
+	writew(1, MTK_RTC_WRTGR);
+}
+
+static void device_reset(void)
+{
+	flush_uart();
+}
+
+static void device_enter_loader(unsigned char bootrom)
+{
+	flush_uart();
+	delay_ms(2000);
+	void (*entry)( void ) = (void (*)(void))0;
+	entry();
+}
+
+static void device_jump(void *entry)
+{
+	flush_uart();
+
+	void (*f) (void) = (void (*)(void))entry;
+	f();
+}
+
+static void loader_send_simple(struct msgb *msg, uint8_t dlci, uint8_t command)
+{
+	msgb_put_u8(msg, command);
+	sercomm_sendmsg(dlci, msg);
+}
+
+extern unsigned char _start;
+
+static void loader_send_init(uint8_t dlci)
+{
+	struct msgb *msg = sercomm_alloc_msgb(9);
+	msgb_put_u8(msg, LOADER_INIT);
+	msgb_put_u32(msg, 0);
+	msgb_put_u32(msg, &_start);
+	sercomm_sendmsg(dlci, msg);
+}
+
+flash_t the_flash;
+
+extern void putchar_asm(uint32_t c);
+
+static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
+
+int main(void)
+{
+	board_init ();
+
+	/* Initialize HDLC subsystem */
+	sercomm_init();
+
+	/* Say hi */
+	puts("\n\nOSMOCOM Loader (revision " GIT_REVISION ")\n");
+	puts(hr);
+
+	/* Identify environment */
+	printf("\nRunning on %s in environment %s\n", manifest_board,
+	       manifest_environment);
+
+	printf("\nHW_CODE = 0x%04x", readw(MTK_CONFG_HW_CODE));
+
+	/* Set up loader communications */
+	sercomm_register_rx_cb(SC_DLCI_LOADER, &cmd_handler);
+
+	/* Wait for events */
+
+	while (1) {
+		uart_poll(SERCOMM_UART_NR);
+	}
+
+}
+
+static void cmd_handler(uint8_t dlci, struct msgb *msg)
+{
+	if (msg->data_len < 1) {
+		return;
+	}
+
+	uint8_t command = msgb_get_u8(msg);
+
+	int res;
+
+	flash_lock_t lock;
+
+	void *data;
+
+	uint8_t chip;
+	uint8_t nbytes;
+	uint16_t crc, mycrc;
+	uint32_t address;
+
+	struct msgb *reply = sercomm_alloc_msgb(256);	// XXX
+
+	if (!reply) {
+		printf("Failed to allocate reply buffer!\n");
+		goto out;
+	}
+
+	switch (command) {
+
+	case LOADER_PING:
+		loader_send_simple(reply, dlci, LOADER_PING);
+		break;
+
+	case LOADER_RESET:
+		loader_send_simple(reply, dlci, LOADER_RESET);
+		device_reset();
+		break;
+
+	case LOADER_POWEROFF:
+		loader_send_simple(reply, dlci, LOADER_POWEROFF);
+		device_poweroff();
+		break;
+
+	case LOADER_ENTER_ROM_LOADER:
+		loader_send_simple(reply, dlci, LOADER_ENTER_ROM_LOADER);
+		device_enter_loader(1);
+		break;
+
+	case LOADER_ENTER_FLASH_LOADER:
+		loader_send_simple(reply, dlci, LOADER_ENTER_FLASH_LOADER);
+		device_enter_loader(0);
+		break;
+
+	case LOADER_MEM_READ:
+
+		nbytes = msgb_get_u8(msg);
+		address = msgb_get_u32(msg);
+
+		crc = crc16(0, (void *)address, nbytes);
+
+		msgb_put_u8(reply, LOADER_MEM_READ);
+		msgb_put_u8(reply, nbytes);
+		msgb_put_u16(reply, crc);
+		msgb_put_u32(reply, address);
+
+		memcpy(msgb_put(reply, nbytes), (void *)address, nbytes);
+
+		sercomm_sendmsg(dlci, reply);
+
+		break;
+
+	case LOADER_MEM_WRITE:
+
+		nbytes = msgb_get_u8(msg);
+		crc = msgb_get_u16(msg);
+		address = msgb_get_u32(msg);
+
+		data = msgb_get(msg, nbytes);
+
+		mycrc = crc16(0, data, nbytes);
+
+		if (mycrc == crc) {
+			memcpy((void *)address, data, nbytes);
+		}
+
+		msgb_put_u8(reply, LOADER_MEM_WRITE);
+		msgb_put_u8(reply, nbytes);
+		msgb_put_u16(reply, mycrc);
+		msgb_put_u32(reply, address);
+
+		sercomm_sendmsg(dlci, reply);
+
+		break;
+
+	case LOADER_JUMP:
+
+		address = msgb_get_u32(msg);
+
+		msgb_put_u8(reply, LOADER_JUMP);
+		msgb_put_u32(reply, address);
+
+		sercomm_sendmsg(dlci, reply);
+
+		device_jump((void *)address);
+
+		break;
+
+	case LOADER_FLASH_INFO:
+
+		msgb_put_u8(reply, LOADER_FLASH_INFO);
+		msgb_put_u8(reply, 1);	// nchips
+
+		// chip 1
+		msgb_put_u32(reply, the_flash.f_base);
+		msgb_put_u32(reply, the_flash.f_size);
+		msgb_put_u8(reply, the_flash.f_nregions);
+
+		int i;
+		for (i = 0; i < the_flash.f_nregions; i++) {
+			msgb_put_u32(reply, the_flash.f_regions[i].fr_bnum);
+			msgb_put_u32(reply, the_flash.f_regions[i].fr_bsize);
+		}
+
+		sercomm_sendmsg(dlci, reply);
+
+		break;
+
+	case LOADER_FLASH_ERASE:
+	case LOADER_FLASH_UNLOCK:
+	case LOADER_FLASH_LOCK:
+	case LOADER_FLASH_LOCKDOWN:
+
+		chip = msgb_get_u8(msg);
+		address = msgb_get_u32(msg);
+
+		if (command == LOADER_FLASH_ERASE) {
+			res = flash_block_erase(&the_flash, address);
+		}
+		if (command == LOADER_FLASH_UNLOCK) {
+			res = flash_block_unlock(&the_flash, address);
+		}
+		if (command == LOADER_FLASH_LOCK) {
+			res = flash_block_lock(&the_flash, address);
+		}
+		if (command == LOADER_FLASH_LOCKDOWN) {
+			res = flash_block_lockdown(&the_flash, address);
+		}
+
+		msgb_put_u8(reply, command);
+		msgb_put_u8(reply, chip);
+		msgb_put_u32(reply, address);
+		msgb_put_u32(reply, (res != 0));
+
+		sercomm_sendmsg(dlci, reply);
+
+		break;
+
+	case LOADER_FLASH_GETLOCK:
+
+		chip = msgb_get_u8(msg);
+		address = msgb_get_u32(msg);
+
+		lock = flash_block_getlock(&the_flash, address);
+
+		msgb_put_u8(reply, command);
+		msgb_put_u8(reply, chip);
+		msgb_put_u32(reply, address);
+
+		switch (lock) {
+		case FLASH_UNLOCKED:
+			msgb_put_u32(reply, LOADER_FLASH_UNLOCKED);
+			break;
+		case FLASH_LOCKED:
+			msgb_put_u32(reply, LOADER_FLASH_LOCKED);
+			break;
+		case FLASH_LOCKED_DOWN:
+			msgb_put_u32(reply, LOADER_FLASH_LOCKED_DOWN);
+			break;
+		default:
+			msgb_put_u32(reply, 0xFFFFFFFF);
+			break;
+		}
+
+		sercomm_sendmsg(dlci, reply);
+
+		break;
+
+	case LOADER_FLASH_PROGRAM:
+
+		nbytes = msgb_get_u8(msg);
+		crc = msgb_get_u16(msg);
+		msgb_get_u8(msg);	// XXX align
+		chip = msgb_get_u8(msg);
+		address = msgb_get_u32(msg);
+
+		data = msgb_get(msg, nbytes);
+
+		mycrc = crc16(0, data, nbytes);
+
+		if (mycrc == crc) {
+			res = flash_program(&the_flash, address, data, nbytes);
+		}
+
+		msgb_put_u8(reply, LOADER_FLASH_PROGRAM);
+		msgb_put_u8(reply, nbytes);
+		msgb_put_u16(reply, mycrc);
+		msgb_put_u8(reply, 0);	// XXX align
+		msgb_put_u8(reply, chip);
+		msgb_put_u32(reply, address);
+
+		msgb_put_u32(reply, (uint32_t) res);	// XXX
+
+		sercomm_sendmsg(dlci, reply);
+
+		break;
+
+	default:
+		printf("unknown command %d\n", command);
+
+		msgb_free(reply);
+
+		break;
+	}
+
+ out:
+
+	msgb_free(msg);
+}
+
+static void key_handler(enum key_codes code, enum key_states state)
+{
+	if (state != PRESSED)
+		return;
+
+	switch (code) {
+	case KEY_POWER:
+		puts("Powering off due to keypress.\n");
+		device_poweroff();
+		break;
+	case KEY_OK:
+		puts("Resetting due to keypress.\n");
+		device_reset();
+		break;
+	default:
+		break;
+	}
+}
diff --git a/src/target/firmware/board/mediatek/exceptions_redirected.S b/src/target/firmware/board/mediatek/exceptions_redirected.S
new file mode 100644
index 0000000..6908396
--- /dev/null
+++ b/src/target/firmware/board/mediatek/exceptions_redirected.S
@@ -0,0 +1,20 @@
+
+/* Exception Vectors like they are needed for the exception vector
+   indirection of the internal boot ROM.  The following section must be liked
+   to appear at 0x80001c */
+.section .text.exceptions
+_undef_instr:
+	b	handle_abort
+_sw_interr:
+	b	_sw_interr
+_prefetch_abort:
+	b	handle_abort
+_data_abort:
+	b	handle_abort
+_reserved:
+	b	_reserved
+_irq:
+	b	irq_entry
+_fiq:
+	b	fiq_entry
+
diff --git a/src/target/firmware/board/mediatek/handlers.S b/src/target/firmware/board/mediatek/handlers.S
new file mode 100644
index 0000000..2824ad5
--- /dev/null
+++ b/src/target/firmware/board/mediatek/handlers.S
@@ -0,0 +1,82 @@
+
+		.EQU	I_BIT,		0x80
+		.EQU	F_BIT,		0x40
+
+.section .text
+
+/* handler for all kinds of aborts */
+.global handle_abort
+handle_abort:
+		@ print the PC we would jump back to...
+		sub	lr, lr, #4		@ we assume to be ARM32
+
+		mov	r0, lr
+		mov	r1, #8
+/*
+		FIXME: Do all this for mtk
+
+		bl phex
+
+		@ print abort message
+		mov	r0, #'A'
+		bl	putchar_asm
+		mov	r0, #'B'
+		bl	putchar_asm
+		mov	r0, #'O'
+		bl	putchar_asm
+		mov	r0, #'R'
+		bl	putchar_asm
+		mov	r0, #'T'
+		bl	putchar_asm
+*/
+		@ disable IRQ and FIQ
+		msr	CPSR_c, #I_BIT | F_BIT
+
+0:					@ dead
+		b	0b
+
+/* entry point for IRQs */
+.global irq_entry
+irq_entry:
+		/* Adjust and save LR_irq in IRQ stack */
+		sub	lr, lr, #4
+		stmfd	sp!, {lr}
+
+		/* Save SPSR for nested interrupt */
+		mrs	r14, SPSR
+		stmfd	sp!, {r14}
+
+		/* Call the interrupt handler C function */
+		stmfd	sp!, {r0-r4, r12}
+		bl	irq
+		ldmfd	sp!, {r0-r4, r12}
+
+		/* Restore SPSR_irq from IRQ stack */
+		ldmia	sp!, {r14}
+		msr	SPSR_cxsf, r14
+
+		/* Restore adjusted LR_irq from IRQ stack directly in the PC */
+		ldmia	sp!, {pc}^
+
+/* entry point for FIQs */
+.global fiq_entry
+fiq_entry:
+		/* Adjust and save LR_irq in IRQ stack */
+		sub	lr, lr, #4
+		stmfd	sp!, {lr}
+
+		/* Save SPSR for nested interrupt */
+		mrs	r14, SPSR
+		stmfd	sp!, {r14}
+
+		/* Call the interrupt handler C function */
+		stmfd	sp!, {r0-r4, r12}
+		bl	fiq
+		ldmfd	sp!, {r0-r4, r12}
+
+		/* Restore SPSR_irq from IRQ stack */
+		ldmia	sp!, {r14}
+		msr	SPSR_cxsf, r14
+
+		/* Restore adjusted LR_irq from IRQ stack directly in the PC */
+		ldmia	sp!, {pc}^
diff --git a/src/target/firmware/board/mediatek/header.S b/src/target/firmware/board/mediatek/header.S
new file mode 100644
index 0000000..747f680
--- /dev/null
+++ b/src/target/firmware/board/mediatek/header.S
@@ -0,0 +1,11 @@
+/*
+ * This is a textual header that is prepended to images where appropriate.
+ *
+ * It is meant to ease identification of our firmwares in dumps as well
+ * as filling some space that is used for the same purpose by the vendor.
+ *
+ */
+.section .compal.header
+.ascii "OSMOCOM"
+. = 0x20
+.ascii GIT_REVISION
diff --git a/src/target/firmware/board/mediatek/macros.S b/src/target/firmware/board/mediatek/macros.S
new file mode 100644
index 0000000..14ee6e6
--- /dev/null
+++ b/src/target/firmware/board/mediatek/macros.S
@@ -0,0 +1,76 @@
+
+.macro clear_bss
+	mov   r0, #0
+	ldr   r1, =__bss_start
+	ldr   r2, =__bss_end
+loop_bss:
+	cmp   r1, r2
+	strlo r0, [r1], #4
+	blo   loop_bss
+.endm
+
+.macro copy_data
+    ldr   r0, =__data_start
+    ldr   r1, =_data_start
+    ldr   r2, =__data_end
+	cmp r0, r2
+	beq done_data
+loop_data:
+    ldrb  r4, [r0], #1
+    strb  r4, [r1], #1
+	cmp r0, r2
+    bne   loop_data
+done_data:
+.endm
+
+.macro copy_ramtext
+    ldr   r0, =__ramtext_start
+    ldr   r1, =_ramtext_start
+    ldr   r2, =__ramtext_end
+	cmp r0, r2
+	beq done_ramtext
+loop_ramtext:
+    ldrb  r4, [r0], #1
+    strb  r4, [r1], #1
+	cmp r0, r2
+    bne   loop_ramtext
+done_ramtext:
+.endm
+		
+	.EQU	ARM_MODE_FIQ,	0x11
+	.EQU	ARM_MODE_IRQ,	0x12
+	.EQU	ARM_MODE_SVC,	0x13
+
+	.EQU	I_BIT,		0x80
+	.EQU	F_BIT,		0x40
+
+#define	TOP_OF_RAM	0x4000a000
+#define FIQ_STACK_SIZE	1024
+#define IRQ_STACK_SIZE	1024
+		
+.macro init_stacks
+	/* initialize stacks, starting at TOP_OF_RAM */
+	ldr	r0, =TOP_OF_RAM
+
+	/* initialize FIQ stack */
+	msr	CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT
+	mov	r13, r0
+	sub	r0, r0, #FIQ_STACK_SIZE
+
+	/* initialize IRQ stack */
+	msr	CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
+	mov	r13, r0
+	sub	r0, r0, #IRQ_STACK_SIZE
+
+	/* initialize supervisor stack */
+	msr	CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT
+	mov	r13, r0
+.endm
+
+.macro call_ctors
+	/* call constructor functions */
+	ldr	r0, =_ctor_start
+	ldr	r1, =_ctor_end
+	bl	do_global_ctors
+.endm
+
diff --git a/src/target/firmware/board/mediatek/ram.lds b/src/target/firmware/board/mediatek/ram.lds
new file mode 100644
index 0000000..1bff82b
--- /dev/null
+++ b/src/target/firmware/board/mediatek/ram.lds
@@ -0,0 +1,120 @@
+/*
+ * Linker script for running from internal SRAM on Compal phones
+ *
+ * This script is tailored specifically to the requirements imposed
+ * on us by the Compal bootloader.
+ *
+ */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+MEMORY
+{
+    /* compal-loaded binary: our text, initialized data */
+    LRAM (rw) : ORIGIN = 0x40000000, LENGTH = 0x00005000
+    /* compal-loaded binary: our unitialized data, stacks, heap */
+    IRAM (rw) : ORIGIN = 0x40005000, LENGTH = 0x00005000
+}
+SECTIONS
+{
+    . = 0x40000000;
+
+    /* romloader data section, contains passthru interrupt vectors */
+    .compal.loader (NOLOAD) : { . = 0x1400; } > LRAM
+
+    /* initialization code */
+    . = ALIGN(4);
+    .text.start : {
+        PROVIDE(_start = .);
+        KEEP(*(.text.start))
+        *(.text.start)
+    } > LRAM
+
+    /* exception vectors from 0x80001c to 0x800034 */
+    .text.exceptions 0x4000001c : AT (LOADADDR(.text.start) + SIZEOF(.text.start)) {
+        KEEP(*(.text.exceptions))
+        * (.text.exceptions)
+        . = ALIGN(4);
+    } > LRAM
+    PROVIDE(_exceptions = LOADADDR(.text.exceptions));
+
+    /* code */
+    . = ALIGN(4);
+    .text (LOADADDR(.text.exceptions) + SIZEOF(.text.exceptions)) :
+          AT (LOADADDR(.text.exceptions) + SIZEOF(.text.exceptions)) {
+        /* regular code */
+        *(.text*)
+        /* always-in-ram code */
+        *(.ramtext*)
+        /* gcc voodoo */
+        *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)
+        . = ALIGN(4);
+    } > LRAM
+    PROVIDE(_text_start = LOADADDR(.text));
+    PROVIDE(_text_end = LOADADDR(.text) + SIZEOF(.text));
+
+    /* constructor pointers */
+    .ctors : {
+        /* ctor count */
+        LONG(SIZEOF(.ctors) / 4 - 2)
+        /* ctor pointers */
+        KEEP(*(SORT(.ctors)))
+        /* end of list */
+        LONG(0)
+    } > LRAM
+    PROVIDE(_ctor_start = LOADADDR(.ctors));
+    PROVIDE(_ctor_end = LOADADDR(.ctors) + SIZEOF(.ctors));
+
+    /* destructor pointers */
+    .dtors : {
+        /* dtor count */
+        LONG(SIZEOF(.dtors) / 4 - 2)
+        /* dtor pointers */
+        KEEP(*(SORT(.dtors)))
+        /* end of list */
+        LONG(0)
+    } > LRAM
+    PROVIDE(_dtor_start = LOADADDR(.dtors));
+    PROVIDE(_dtor_end = LOADADDR(.dtors) + SIZEOF(.dtors));
+
+    /* read-only data */
+    . = ALIGN(4);
+    .rodata : {
+        *(.rodata*)
+    } > LRAM
+    PROVIDE(_rodata_start = LOADADDR(.rodata));
+    PROVIDE(_rodata_end = LOADADDR(.rodata) + SIZEOF(.rodata));
+
+    /* initialized data */
+    . = ALIGN(4);
+    .data : {
+        *(.data)
+    } > LRAM
+    PROVIDE(_data_start = LOADADDR(.data));
+    PROVIDE(_data_end = LOADADDR(.data) + SIZEOF(.data));
+
+    /* pic offset tables */
+    . = ALIGN(4);
+    .got : {
+        *(.got)
+        *(.got.plt) *(.igot.plt) *(.got) *(.igot)
+    } > LRAM
+    PROVIDE(_got_start = LOADADDR(.got));
+    PROVIDE(_got_end = LOADADDR(.got) + SIZEOF(.got));
+
+    /* uninitialized data */
+    .bss (NOLOAD) : {
+        . = ALIGN(4);
+        __bss_start = .;
+        *(.bss)
+    } > IRAM
+    . = ALIGN(4);
+    __bss_end = .;
+    PROVIDE(_bss_start = __bss_start);
+    PROVIDE(_bss_end = __bss_end);
+
+    /* end of image */
+    . = ALIGN(4);
+    _end = .;
+    PROVIDE(end = .);
+}
diff --git a/src/target/firmware/board/mediatek/start.ram.S b/src/target/firmware/board/mediatek/start.ram.S
new file mode 100644
index 0000000..c8f242c
--- /dev/null
+++ b/src/target/firmware/board/mediatek/start.ram.S
@@ -0,0 +1,26 @@
+
+.section .text.start
+
+#include "macros.S"
+		
+.globl _start
+_start:
+	/* clear bss section */
+	clear_bss
+
+	/* initialize all stacks */
+	init_stacks
+
+	/* call constructors */
+	call_ctors
+
+	/* jump to main */
+	ldr	pc, _jump_main
+
+	/* endless loop at end of program */
+_loop:
+	b	_loop
+	b	_start
+
+_jump_main:
+	.word main
diff --git a/src/target/firmware/board/mediatek/uart.c b/src/target/firmware/board/mediatek/uart.c
new file mode 100644
index 0000000..bf37c0c
--- /dev/null
+++ b/src/target/firmware/board/mediatek/uart.c
@@ -0,0 +1,441 @@
+/* MediaTek MT62xx internal UART Driver
+ *
+ * based on the Calypso driver, so there might be some cruft from it left...
+ *
+ * (C) 2010 by Harald Welte <laforge at gnumonks.org>
+ * (C) 2010 by Ingo Albrecht <prom at berlin.ccc.de>
+ * (C) 2010 by Steve Markgraf <steve at steve-m.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <debug.h>
+
+#include <memory.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <defines.h>
+#include <console.h>
+#include <comm/sercomm.h>
+
+#include <calypso/irq.h>
+#include <calypso/uart.h>
+
+/* MT622x */
+#if 0
+#define BASE_ADDR_UART1	0x80130000
+#define BASE_ADDR_UART2	0x80180000
+#define BASE_ADDR_UART3	0x801b0000
+#endif
+
+/* MT 6235 */
+#define BASE_ADDR_UART1	0x81030000
+
+//TODO make UART2 and 3 work
+#define UART_REG(n,m)	(BASE_ADDR_UART1 + (m))
+
+#define LCR7BIT		0x80
+#define LCRBFBIT	0x40
+#define MCR6BIT		0x20
+#define REG_OFFS(m)	((m) & ~(LCR7BIT|LCRBFBIT|MCR6BIT))
+/* read access LCR[7] = 0 */
+enum uart_reg {
+	RBR		= 0x00,
+	IER		= 0x04,
+	IIR		= 0x08,
+	LCR		= 0x0c,
+	MCR		= 0x10,
+	LSR		= 0x14,
+	MSR		= 0x18,
+	SCR		= 0x1c,
+	AUTOBAUD_EN	= 0x20,
+	HIGHSPEED	= 0x24,
+	SAMPLE_COUNT	= 0x28,
+	SAMPLE_POINT	= 0x2c,
+	AUTOBAUD_REG	= 0x30,
+	RATE_FIX_REG	= 0x34, /* undocumented */
+	AUTOBAUDSAMPLE	= 0x38,
+	GUARD		= 0x3c,
+	ESCAPE_DAT	= 0x40,
+	ESCAPE_EN	= 0x44,
+	SLEEP_EN	= 0x48,
+	VFIFO_EN	= 0x4c,
+/* read access LCR[7] = 1 */
+	DLL	= RBR,
+	DLH	= IER,
+/* read/write access LCR[7:0] = 0xbf */
+	EFR	= IIR | LCRBFBIT,
+	XON1	= MCR | LCRBFBIT,
+	XON2	= LSR | LCRBFBIT,
+	XOFF1	= MSR | LCRBFBIT,
+	XOFF2 	= SCR | LCRBFBIT,
+};
+
+enum fcr_bits {
+	FIFO_EN		= (1 << 0),
+	RX_FIFO_CLEAR	= (1 << 1),
+	TX_FIFO_CLEAR	= (1 << 2),
+	DMA_MODE	= (1 << 3),
+};
+#define TX_FIFO_TRIG_SHIFT	4
+#define RX_FIFO_TRIG_SHIFT	6
+
+enum iir_bits {
+	IIR_INT_PENDING			= 0x01,
+	IIR_INT_TYPE			= 0x3E,
+	IIR_INT_TYPE_RX_STATUS_ERROR 	= 0x06,
+	IIR_INT_TYPE_RX_TIMEOUT		= 0x0C,
+	IIR_INT_TYPE_RBR		= 0x04,
+	IIR_INT_TYPE_THR		= 0x02,
+	IIR_INT_TYPE_MSR		= 0x00,
+	IIR_INT_TYPE_XOFF		= 0x10,
+	IIR_INT_TYPE_FLOW		= 0x20,
+	IIR_FCR0_MIRROR			= 0xC0,
+};
+
+
+/* enable or disable the divisor latch for access to DLL, DLH */
+static void uart_set_lcr7bit(int uart, int on)
+{
+	uint8_t reg;
+
+	reg = readb(UART_REG(uart, LCR));
+	if (on)
+		reg |= (1 << 7);
+	else
+		reg &= ~(1 << 7);
+	writeb(reg, UART_REG(uart, LCR));
+}
+
+static uint8_t old_lcr;
+static void uart_set_lcr_bf(int uart, int on)
+{
+	if (on) {
+		old_lcr = readb(UART_REG(uart, LCR));
+		writeb(0xBF, UART_REG(uart, LCR));
+	} else {
+		writeb(old_lcr, UART_REG(uart, LCR));
+	}
+}
+
+/* Enable or disable the TCR_TLR latch bit in MCR[6] */
+static void uart_set_mcr6bit(int uart, int on)
+{
+	uint8_t mcr;
+	/* we assume EFR[4] is always set to 1 */
+	mcr = readb(UART_REG(uart, MCR));
+	if (on)
+		mcr |= (1 << 6);
+	else
+		mcr &= ~(1 << 6);
+	writeb(mcr, UART_REG(uart, MCR));
+}
+
+static void uart_reg_write(int uart, enum uart_reg reg, uint8_t val)
+{
+	if (reg & LCRBFBIT)
+		uart_set_lcr_bf(uart, 1);
+	else if (reg & LCR7BIT)
+		uart_set_lcr7bit(uart, 1);
+	else if (reg & MCR6BIT)
+		uart_set_mcr6bit(uart, 1);
+
+	writeb(val, UART_REG(uart, REG_OFFS(reg)));
+
+	if (reg & LCRBFBIT)
+		uart_set_lcr_bf(uart, 0);
+	else if (reg & LCR7BIT)
+		uart_set_lcr7bit(uart, 0);
+	else if (reg & MCR6BIT)
+		uart_set_mcr6bit(uart, 0);
+}
+
+/* read from a UART register, applying any required latch bits */
+static uint8_t uart_reg_read(int uart, enum uart_reg reg)
+{
+	uint8_t ret;
+
+	if (reg & LCRBFBIT)
+		uart_set_lcr_bf(uart, 1);
+	else if (reg & LCR7BIT)
+		uart_set_lcr7bit(uart, 1);
+	else if (reg & MCR6BIT)
+		uart_set_mcr6bit(uart, 1);
+
+	ret = readb(UART_REG(uart, REG_OFFS(reg)));
+
+	if (reg & LCRBFBIT)
+		uart_set_lcr_bf(uart, 0);
+	else if (reg & LCR7BIT)
+		uart_set_lcr7bit(uart, 0);
+	else if (reg & MCR6BIT)
+		uart_set_mcr6bit(uart, 0);
+
+	return ret;
+}
+
+static void uart_irq_handler_cons(__unused enum irq_nr irqnr)
+{
+	const uint8_t uart = CONS_UART_NR;
+	uint8_t iir;
+
+	//uart_putchar_nb(uart, 'U');
+
+	iir = uart_reg_read(uart, IIR);
+	if (iir & IIR_INT_PENDING)
+		return;
+
+	switch (iir & IIR_INT_TYPE) {
+	case IIR_INT_TYPE_RBR:
+		break;
+	case IIR_INT_TYPE_THR:
+		if (cons_rb_flush() == 1) {
+			/* everything was flushed, disable RBR IRQ */
+			uint8_t ier = uart_reg_read(uart, IER);
+			ier &= ~(1 << 1);
+			uart_reg_write(uart, IER, ier);
+		}
+		break;
+	case IIR_INT_TYPE_MSR:
+		break;
+	case IIR_INT_TYPE_RX_STATUS_ERROR:
+		break;
+	case IIR_INT_TYPE_RX_TIMEOUT:
+		break;
+	case IIR_INT_TYPE_XOFF:
+		break;
+	}
+}
+
+static void uart_irq_handler_sercomm(__unused enum irq_nr irqnr)
+{
+	const uint8_t uart = SERCOMM_UART_NR;
+	uint8_t iir, ch;
+
+	//uart_putchar_nb(uart, 'U');
+
+	iir = uart_reg_read(uart, IIR);
+	if (iir & IIR_INT_PENDING)
+		return;
+
+	switch (iir & IIR_INT_TYPE) {
+	case IIR_INT_TYPE_RX_TIMEOUT:
+	case IIR_INT_TYPE_RBR:
+		/* as long as we have rx data available */
+		while (uart_getchar_nb(uart, &ch)) {
+			if (sercomm_drv_rx_char(ch) < 0) {
+				/* sercomm cannot receive more data right now */
+				uart_irq_enable(uart, UART_IRQ_RX_CHAR, 0);
+			}
+		}
+		break;
+	case IIR_INT_TYPE_THR:
+		/* as long as we have space in the FIFO */
+		while (!uart_tx_busy(uart)) {
+			/* get a byte from sercomm */
+			if (!sercomm_drv_pull(&ch)) {
+				/* no more bytes in sercomm, stop TX interrupts */
+				uart_irq_enable(uart, UART_IRQ_TX_EMPTY, 0);
+				break;
+			}
+			/* write the byte into the TX FIFO */
+			uart_putchar_nb(uart, ch);
+		}
+		break;
+	case IIR_INT_TYPE_MSR:
+		printf("UART IRQ MSR\n");
+		break;
+	case IIR_INT_TYPE_RX_STATUS_ERROR:
+		printf("UART IRQ RX_SE\n");
+		break;
+	case IIR_INT_TYPE_XOFF:
+		printf("UART IRQXOFF\n");
+		break;
+	}
+}
+
+static const uint8_t uart2irq[] = {
+	[0]	= IRQ_UART_IRDA,
+	[1]	= IRQ_UART_MODEM,
+};
+
+void uart_init(uint8_t uart, uint8_t interrupts)
+{
+	uint8_t irq = uart2irq[uart];
+
+	uart_reg_write(uart, IER, 0x00);
+	if (uart == CONS_UART_NR) {
+		cons_init();
+		if(interrupts) {
+			irq_register_handler(irq, &uart_irq_handler_cons);
+			irq_config(irq, 0, 0, 0xff);
+			irq_enable(irq);
+		}
+	} else {
+		sercomm_init();
+		if(interrupts) {
+			irq_register_handler(irq, &uart_irq_handler_sercomm);
+			irq_config(irq, 0, 0, 0xff);
+			irq_enable(irq);
+		}
+		uart_irq_enable(uart, UART_IRQ_RX_CHAR, 1);
+	}
+
+	uart_reg_write(uart, AUTOBAUD_EN, 0x00); /* disable AUTOBAUD */
+	uart_reg_write(uart,   EFR, 0x10); /* Enhanced Features Register */
+
+	/* no XON/XOFF flow control, ENHANCED_EN, no auto-RTS/CTS */
+	uart_reg_write(uart, EFR, (1 << 4));
+	/* enable Tx/Rx FIFO, Tx trigger at 56 spaces, Rx trigger at 60 chars */
+	//FIXME check those FIFO settings
+	uart_reg_write(uart, IIR, FIFO_EN | RX_FIFO_CLEAR | TX_FIFO_CLEAR |
+			(3 << TX_FIFO_TRIG_SHIFT) | (1 << RX_FIFO_TRIG_SHIFT));
+
+	/* RBR interrupt only when TX FIFO and TX shift register are empty */
+	uart_reg_write(uart, SCR, (1 << 0));// | (1 << 3));
+
+	/* 8 bit, 1 stop bit, no parity, no break */
+	uart_reg_write(uart, LCR, 0x03);
+
+	uart_set_lcr7bit(uart, 0);
+}
+
+void uart_poll(uint8_t uart) {
+	if(uart == CONS_UART_NR) {
+		uart_irq_handler_cons(0);
+	} else {
+		uart_irq_handler_sercomm(0);
+	}
+}
+
+void uart_irq_enable(uint8_t uart, enum uart_irq irq, int on)
+{
+	uint8_t ier = uart_reg_read(uart, IER);
+	uint8_t mask = 0;
+
+	switch (irq) {
+	case UART_IRQ_TX_EMPTY:
+		mask = (1 << 1);
+		break;
+	case UART_IRQ_RX_CHAR:
+		mask = (1 << 0);
+		break;
+	}
+
+	if (on)
+		ier |= mask;
+	else
+		ier &= ~mask;
+
+	uart_reg_write(uart, IER, ier);
+}
+
+
+void uart_putchar_wait(uint8_t uart, int c)
+{
+	/* wait while TX FIFO indicates full */
+	while (~readb(UART_REG(uart, LSR)) & 0x20) { }
+
+	/* put character in TX FIFO */
+	writeb(c, UART_REG(uart, RBR));
+}
+
+int uart_putchar_nb(uint8_t uart, int c)
+{
+	/* if TX FIFO indicates full, abort */
+	if (~readb(UART_REG(uart, LSR)) & 0x20)
+		return 0;
+
+	writeb(c, UART_REG(uart, RBR));
+	return 1;
+}
+
+int uart_getchar_nb(uint8_t uart, uint8_t *ch)
+{
+	uint8_t lsr;
+
+	lsr = readb(UART_REG(uart, LSR));
+
+	/* something strange happened */
+	if (lsr & 0x02)
+		printf("LSR RX_OE\n");
+	if (lsr & 0x04)
+		printf("LSR RX_PE\n");
+	if (lsr & 0x08)
+		printf("LSR RX_FE\n");
+	if (lsr & 0x10)
+		printf("LSR RX_BI\n");
+	if (lsr & 0x80)
+		printf("LSR RX_FIFO_STS\n");
+
+	/* is the Rx FIFO empty? */
+	if (!(lsr & 0x01))
+		return 0;
+
+	*ch = readb(UART_REG(uart, RBR));
+	//printf("getchar_nb(%u) = %02x\n", uart, *ch);
+	return 1;
+}
+
+int uart_tx_busy(uint8_t uart)
+{
+	/* Check THRE bit (LSR[5]) to see if FIFO is full */
+	if (~readb(UART_REG(uart, LSR)) & 0x20)
+		return 1;
+	return 0;
+}
+
+#if 0
+/* 26MHz clock input (used when no PLL initialized directly after poweron) */
+static const uint16_t divider[] = {
+	[UART_38400]	= 42,
+	[UART_57600]	= 28,
+	[UART_115200]	= 14,
+	[UART_230400]	= 7,
+	[UART_460800]	= 14,	/* would need UART_REG(HIGHSPEED) = 1 or 2 */
+	[UART_921600]	= 7,	/* would need UART_REG(HIGHSPEED) = 2 */
+};
+#endif
+
+/* 52MHz clock input (after PLL init) */
+static const uint16_t divider[] = {
+	[UART_38400]	= 85,
+	[UART_57600]	= 56,
+	[UART_115200]	= 28,
+	[UART_230400]	= 14,
+	[UART_460800]	= 7,
+	[UART_921600]	= 7,	/* would need UART_REG(HIGHSPEED) = 1 */
+};
+
+int uart_baudrate(uint8_t uart, enum uart_baudrate bdrt)
+{
+	uint16_t div;
+
+	if (bdrt > ARRAY_SIZE(divider))
+		return -1;
+
+	div = divider[bdrt];
+	uart_set_lcr7bit(uart, 1);
+	writeb(div & 0xff, UART_REG(uart, DLL));
+	writeb(div >> 8, UART_REG(uart, DLH));
+	uart_set_lcr7bit(uart, 0);
+
+	return 0;
+}
diff --git a/src/target/firmware/board/mt62xx/init.c b/src/target/firmware/board/mt62xx/init.c
new file mode 100644
index 0000000..f9e2130
--- /dev/null
+++ b/src/target/firmware/board/mt62xx/init.c
@@ -0,0 +1,140 @@
+/* Initialization for the MT62xx Basebands */
+
+/* (C) 2010 by Steve Markgraf <steve at steve-m.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <debug.h>
+#include <ctors.h>
+#include <memory.h>
+#include <board.h>
+#include <keypad.h>
+#include <console.h>
+
+#include <flash/cfi_flash.h>
+
+/* We emulate the calypso interface */
+#include <calypso/uart.h>
+
+#include <comm/sercomm.h>
+#include <comm/timer.h>
+
+#include <mtk/emi.h>
+#include <mtk/mt6235.h>
+#include <mtk/system.h>
+
+void pll_init(void)
+{
+	/* Power on PLL */
+	writew(0, MTK_PLL_PDN_CON);
+	writew(PLL_CLKSQ_DIV2_DSP | PLL_CLKSQ_DIV2_MCU, MTK_PLL_CLK_CON);
+
+	writew(PLL_RST, MTK_PLL_PLL);
+	writew(0, MTK_PLL_PLL);
+	delay_ms(1);
+
+	/* Turn on PLL for MCU, DSP and USB */
+	writew(PLL_MPLLSEL_PLL | PLL_DPLLSEL | PLL_UPLLSEL, MTK_PLL_PLL);
+
+	/*
+	 * Setup MCU clock register:
+	 * ARMCLK = 208MHz, AHBx4CLK = 52MHz, AHBx8CLK = 104MHz
+	 * we have to write to the read-only part (EMICLK) as well, otherwise
+	 * the EMI won't work! (datasheet lies)
+	 */
+	writew(7 << MCUCLK_CON_AHBX8CLK_SHIFT |
+	       3 << MCUCLK_CON_AHBX4CLK_SHIFT |
+	       15 << MCUCLK_CON_ARMCLK_SHIFT |
+	       7 << MCUCLK_CON_EMICLK_SHIFT,
+	       MTK_CONFG_MCUCLK_CON);
+}
+
+void memory_init(void)
+{
+	int i;
+
+	/* Initialization for Hynix RAM */
+
+	/* Configure DRAM controller */
+	writel(0x0001000e, MTK_EMI_GEND);
+	writel(0x00088a0a, MTK_EMI_GENA);
+	writel(0x00000280, MTK_EMI_GENB);
+	writel(0x52945294, MTK_EMI_GENC);
+	writel(0x1c016605, MTK_EMI_CONL);
+	writel(0x00002828, MTK_EMI_CONM);
+	writel(0x02334000, MTK_EMI_CONI);
+	writel(0x16c12212, MTK_EMI_CONJ);
+	writel(0x032d0000, MTK_EMI_CONK);
+
+	for (i = 0; i < 5; ++i) {
+		/* Setup five single bits, one by one for DRAM init */
+		writel((1 << (24 + i)) | (0x400013), MTK_EMI_CONN);
+		delay_ms(1);
+		writel(0x400013, MTK_EMI_CONN);
+		delay_ms(1);
+	}
+
+#if 0
+	/* Initialization for Toshiba RAM */
+
+	/* Configure DRAM controller */
+	writel(0x0001000E, MTK_EMI_GEND);
+	writel(0x00088E3A, MTK_EMI_GENA);
+	writel(0x000000C0, MTK_EMI_GENB);
+	writel(0x18C618C6, MTK_EMI_GENC);
+	writel(0x18007505, MTK_EMI_CONL);
+	writel(0x00002828, MTK_EMI_CONM);
+	writel(0x00332000, MTK_EMI_CONI);
+	writel(0x3CD24431, MTK_EMI_CONJ);
+	writel(0x02000000, MTK_EMI_CONK);
+
+	for (i = 0; i < 5; ++i) {
+		/* Setup five single bits, one by one for DRAM init */
+		writel((1 << (24 + i)) | (0x500013), MTK_EMI_CONN);
+		delay_ms(1);
+		writel(0x500013, MTK_EMI_CONN);
+		delay_ms(1);
+	}
+
+#endif
+}
+
+void board_init(void)
+{
+	/* powerup the baseband */
+	writew(POWERKEY1_MAGIC, MTK_RTC_POWERKEY1);
+	writew(POWERKEY2_MAGIC, MTK_RTC_POWERKEY2);
+	writew(BBPU_MAGIC | RTC_BBPU_WRITE_EN |
+	       RTC_BBPU_BBPU | RTC_BBPU_AUTO,
+	       MTK_RTC_BBPU);
+	writew(1, MTK_RTC_WRTGR);
+
+	/* disable watchdog timer */
+	writew(WDT_MODE_KEY, MTK_RGU_WDT_MODE);
+
+	pll_init();
+	memory_init();
+
+	/* Initialize UART without interrupts */
+	uart_init(SERCOMM_UART_NR, 0);
+	uart_baudrate(SERCOMM_UART_NR, UART_115200);
+}
diff --git a/src/target/firmware/include/mtk/emi.h b/src/target/firmware/include/mtk/emi.h
new file mode 100644
index 0000000..1818499
--- /dev/null
+++ b/src/target/firmware/include/mtk/emi.h
@@ -0,0 +1,42 @@
+/*
+ * (C) 2010 by Tieto <www.tieto.com>
+ *	Marcin Mielczarczyk <marcin.mielczarczyk at tieto.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __MTK_EMI_H_
+#define __MTK_EMI_H_
+
+/* External Memory Interface register definitions */
+#define MTK_EMI_CONA		(MTK_EMI_BASE + 0x00)
+#define MTK_EMI_CONB		(MTK_EMI_BASE + 0x08)
+#define MTK_EMI_CONC		(MTK_EMI_BASE + 0x10)
+#define MTK_EMI_COND		(MTK_EMI_BASE + 0x18)
+#define MTK_EMI_CONI		(MTK_EMI_BASE + 0x40)
+#define MTK_EMI_CONJ		(MTK_EMI_BASE + 0x48)
+#define MTK_EMI_CONK		(MTK_EMI_BASE + 0x50)
+#define MTK_EMI_CONL		(MTK_EMI_BASE + 0x58)
+#define MTK_EMI_CONM		(MTK_EMI_BASE + 0x60)
+#define MTK_EMI_CONN		(MTK_EMI_BASE + 0x68)
+#define MTK_EMI_GENA		(MTK_EMI_BASE + 0x70)
+#define MTK_EMI_GENB		(MTK_EMI_BASE + 0x78)
+#define MTK_EMI_GENC		(MTK_EMI_BASE + 0x80)
+#define MTK_EMI_GEND		(MTK_EMI_BASE + 0x88)
+
+#endif
diff --git a/src/target/firmware/include/mtk/mt6235.h b/src/target/firmware/include/mtk/mt6235.h
new file mode 100644
index 0000000..fb9d368
--- /dev/null
+++ b/src/target/firmware/include/mtk/mt6235.h
@@ -0,0 +1,74 @@
+/*
+ * (C) 2010 by Tieto <www.tieto.com>
+ *	Marcin Mielczarczyk <marcin.mielczarczyk at tieto.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __MT6235_H
+#define __MT6235_H
+
+/* Peripheral base addresses */
+#define MTK_EFUSE_BASE		0x80000000
+#define MTK_CONFG_BASE		0x80010000
+#define MTK_GPIO_BASE		0x80020000
+#define MTK_RGU_BASE		0x80030000
+#define MTK_EMI_BASE		0x81000000
+#define MTK_CIRQ_BASE		0x81010000
+#define MTK_DMA_BASE		0x81020000
+#define MTK_UART1_BASE		0x81030000
+#define MTK_UART2_BASE		0x81040000
+#define MTK_UART3_BASE		0x81050000
+#define MTK_GPT_BASE		0x81060000
+#define MTK_KP_BASE		0x81080000
+#define MTK_PWM_BASE		0x81090000
+#define MTK_SIM_BASE		0x810A0000
+#define MTK_RTC_BASE		0x810C0000
+#define MTK_SEJ_BASE		0x810D0000
+#define MTK_BM_BASE		0x810E0000
+#define MTK_IRDA_BASE		0x810F0000
+#define MTK_I2C_BASE		0x81100000
+#define MTK_MSDC_BASE		0x81110000
+#define MTK_NFI_BASE		0x81120000
+#define MTK_MSSDC2_BASE		0x81140000
+#define MTK_TDMA_BASE		0x82000000
+#define MTK_BSI_BASE		0x82010000
+#define MTK_BPI_BASE		0x82020000
+#define MTK_AFC_BASE		0x82030000
+#define MTK_APC_BASE		0x82040000
+#define MTK_AUXADC_BASE		0x82050000
+#define MTK_DIVIDER_BASE	0x82060000
+#define MTK_FSC_BASE		0x82070000
+#define MTK_GCU_BASE		0x82080000
+#define MTK_CSD_ACC_BASE	0x82090000
+#define MTK_SHARE1_BASE		0x820A0000
+#define MTK_IRDBG1_BASE		0x820B0000
+#define MTK_SHARE2_BASE		0x820C0000
+#define MTK_IRDBG2_BASE		0x820D0000
+#define MTK_PATCH_BASE		0x820E0000
+#define MTK_AFE_BASE		0x820F0000
+#define MTK_BFE_BASE		0x82100000
+#define MTK_PLL_BASE		0x83000000
+#define MTK_ACIF_BASE		0x83010000
+#define MTK_GMC_BASE		0x84000000
+#define MTK_G2D_BASE		0x84010000
+#define MTK_GCMQ_BASE		0x84020000
+#define MTK_CAM_BASE		0x840B0000
+#define MTK_CRZ_BASE		0x840E0000
+
+#endif
diff --git a/src/target/firmware/include/mtk/system.h b/src/target/firmware/include/mtk/system.h
new file mode 100644
index 0000000..4543029
--- /dev/null
+++ b/src/target/firmware/include/mtk/system.h
@@ -0,0 +1,195 @@
+/*
+ * (C) 2010 by Tieto <www.tieto.com>
+ *	Marcin Mielczarczyk <marcin.mielczarczyk at tieto.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __MTK_SYSTEM_H_
+#define __MTK_SYSTEM_H_
+
+/*
+ * Configuration block section (Clock, Power Down, Version and Reset
+ */
+
+/* Register definitions */
+#define MTK_CONFG_HW_VERSION	(MTK_CONFG_BASE + 0x000)
+#define MTK_CONFG_FW_VERSION	(MTK_CONFG_BASE + 0x004)
+#define MTK_CONFG_HW_CODE	(MTK_CONFG_BASE + 0x008)
+#define MTK_CONFG_SLEEP_CON	(MTK_CONFG_BASE + 0x114)
+#define MTK_CONFG_MCUCLK_CON	(MTK_CONFG_BASE + 0x118)
+#define MTK_CONFG_DSPCLK_CON	(MTK_CONFG_BASE + 0x11C)
+#define MTK_CONFG_IDN_SEL	(MTK_CONFG_BASE + 0x200)
+#define MTK_CONFG_PDN_CON0	(MTK_CONFG_BASE + 0x300)
+#define MTK_CONFG_PDN_CON1	(MTK_CONFG_BASE + 0x304)
+#define MTK_CONFG_PDN_CON2	(MTK_CONFG_BASE + 0x308)
+#define MTK_CONFG_PDN_CON3	(MTK_CONFG_BASE + 0x30C)
+#define MTK_CONFG_PDN_SET0	(MTK_CONFG_BASE + 0x310)
+#define MTK_CONFG_PDN_SET1	(MTK_CONFG_BASE + 0x314)
+#define MTK_CONFG_PDN_SET2	(MTK_CONFG_BASE + 0x318)
+#define MTK_CONFG_PDN_SET3	(MTK_CONFG_BASE + 0x31C)
+#define MTK_CONFG_PDN_CLR0	(MTK_CONFG_BASE + 0x320)
+#define MTK_CONFG_PDN_CLR1	(MTK_CONFG_BASE + 0x324)
+#define MTK_CONFG_PDN_CLR2	(MTK_CONFG_BASE + 0x328)
+#define MTK_CONFG_PDN_CLR3	(MTK_CONFG_BASE + 0x32C)
+
+/* CONFG_MCUCLK_CON bit fields definitions */
+#define MCUCLK_CON_AHBX8CLK_SHIFT	(0)
+#define MCUCLK_CON_AHBX4CLK_SHIFT	(4)
+#define MCUCLK_CON_ARMCLK_SHIFT		(8)
+#define MCUCLK_CON_EMICLK_SHIFT		(12)
+
+/* PDN_CON0 bit fields definitions */
+#define PDN_CON0_CON0_DMA	(1 << 0)
+#define PDN_CON0_USB		(1 << 1)
+#define PDN_CON0_GCU		(1 << 2)
+#define PDN_CON0_WAVE		(1 << 3)
+#define PDN_CON0_SEJ		(1 << 4)
+#define PDN_CON0_IR		(1 << 6)
+#define PDN_CON0_PWM3		(1 << 7)
+#define PDN_CON0_PWM		(1 << 8)
+#define PDN_CON0_SIM2		(1 << 10)
+#define PDN_CON0_IRDBG1		(1 << 12)
+#define PDN_CON0_IRDBG2		(1 << 13)
+
+/* PDN_CON1 bit fields definitions */
+#define PDN_CON1_GPT		(1 << 0)
+#define PDN_CON1_KP		(1 << 1)
+#define PDN_CON1_GPIO		(1 << 2)
+#define PDN_CON1_UART1		(1 << 3)
+#define PDN_CON1_SIM		(1 << 4)
+#define PDN_CON1_PWM1		(1 << 5)
+#define PDN_CON1_LCD		(1 << 7)
+#define PDN_CON1_UART2		(1 << 8)
+#define PDN_CON1_MSDC		(1 << 9)
+#define PDN_CON1_TP		(1 << 10)
+#define PDN_CON1_PWM2		(1 << 11)
+#define PDN_CON1_NFI		(1 << 12)
+#define PDN_CON1_UART3		(1 << 14)
+#define PDN_CON1_IRDA		(1 << 15)
+
+/* PDN_CON2 bit fields definitions */
+#define PDN_CON2_TDMA		(1 << 0)
+#define PDN_CON2_RTC		(1 << 1)
+#define PDN_CON2_BSI		(1 << 2)
+#define PDN_CON2_BPI		(1 << 3)
+#define PDN_CON2_AFC		(1 << 4)
+#define PDN_CON2_APC		(1 << 5)
+
+/*
+ * Reset Generation Unit block section
+ */
+#define MTK_RGU_WDT_MODE	(MTK_RGU_BASE + 0x00)
+#define MTK_RGU_WDT_LENGTH	(MTK_RGU_BASE + 0x04)
+#define MTK_RGU_WDT_RESTART	(MTK_RGU_BASE + 0x08)
+#define MTK_RGU_WDT_STA		(MTK_RGU_BASE + 0x0C)
+#define MTK_RGU_SW_PERIPH_RSTN	(MTK_RGU_BASE + 0x10)
+#define MTK_RGU_SW_DSP_RSTN	(MTK_RGU_BASE + 0x14)
+#define MTK_RGU_WDT_RSTINTERVAL	(MTK_RGU_BASE + 0x18)
+#define MTK_RGU_WDT_SWRST	(MTK_RGU_BASE + 0x1C)
+
+#define WDT_MODE_KEY		0x2200
+#define WDT_LENGTH_KEY		0x0008
+#define WDT_RESTART_KEY		0x1971
+#define SW_PERIPH_RSTN_KEY	0x0037
+#define WDT_SWRST_KEY		0x1209
+
+/*
+ * RTC block section
+ */
+
+/* RTC registers definition */
+#define MTK_RTC_BBPU		(MTK_RTC_BASE + 0x00)
+#define MTK_RTC_IRQ_STA		(MTK_RTC_BASE + 0x04)
+#define MTK_RTC_IRQ_EN		(MTK_RTC_BASE + 0x08)
+#define MTK_RTC_CII_EN		(MTK_RTC_BASE + 0x0C)
+#define MTK_RTC_AL_MASK		(MTK_RTC_BASE + 0x10)
+#define MTK_RTC_TC_SEC		(MTK_RTC_BASE + 0x14)
+#define MTK_RTC_TC_MIN		(MTK_RTC_BASE + 0x18)
+#define MTK_RTC_TC_HOU		(MTK_RTC_BASE + 0x1C)
+#define MTK_RTC_TC_DOM		(MTK_RTC_BASE + 0x20)
+#define MTK_RTC_TC_DOW		(MTK_RTC_BASE + 0x24)
+#define MTK_RTC_TC_MTH		(MTK_RTC_BASE + 0x28)
+#define MTK_RTC_TC_YEA		(MTK_RTC_BASE + 0x2C)
+#define MTK_RTC_AL_SEC		(MTK_RTC_BASE + 0x30)
+#define MTK_RTC_AL_MIN		(MTK_RTC_BASE + 0x34)
+#define MTK_RTC_AL_HOU		(MTK_RTC_BASE + 0x38)
+#define MTK_RTC_AL_DOM		(MTK_RTC_BASE + 0x3C)
+#define MTK_RTC_AL_DOW		(MTK_RTC_BASE + 0x40)
+#define MTK_RTC_AL_MTH		(MTK_RTC_BASE + 0x44)
+#define MTK_RTC_AL_YEA		(MTK_RTC_BASE + 0x48)
+#define MTK_RTC_XOSCCALI	(MTK_RTC_BASE + 0x4C)
+#define MTK_RTC_POWERKEY1	(MTK_RTC_BASE + 0x50)
+#define MTK_RTC_POWERKEY2	(MTK_RTC_BASE + 0x54)
+#define MTK_RTC_PDN1		(MTK_RTC_BASE + 0x58)
+#define MTK_RTC_PDN2		(MTK_RTC_BASE + 0x5C)
+#define MTK_RTC_SPAR1		(MTK_RTC_BASE + 0x64)
+#define MTK_RTC_DIFF		(MTK_RTC_BASE + 0x6C)
+#define MTK_RTC_CALI		(MTK_RTC_BASE + 0x70)
+#define MTK_RTC_WRTGR		(MTK_RTC_BASE + 0x74)
+
+#define POWERKEY1_MAGIC		0xA357
+#define POWERKEY2_MAGIC		0x67D2
+
+/* RTC_BBPU bit fields definitions */
+#define RTC_BBPU_PWREN		(1 << 0)
+#define RTC_BBPU_WRITE_EN	(1 << 1)
+#define RTC_BBPU_BBPU		(1 << 2)
+#define RTC_BBPU_AUTO		(1 << 3)
+#define RTC_BBPU_CLRPKY		(1 << 4)
+#define RTC_BBPU_RELOAD		(1 << 5)
+#define RTC_BBPU_CBUSY		(1 << 6)
+#define RTC_BBPU_DBING		(1 << 7)
+#define RTC_BBPU_KEY_BBPU	(1 << 8)
+
+/* RTC_BBPU write is only acceptable when KEY_BBPU=0x43 */
+#define BBPU_MAGIC		0x4300
+
+/*
+ * PLL block section
+ */
+
+/* PLL registers definition */
+#define MTK_PLL_PLL		(MTK_PLL_BASE + 0x00)
+#define MTK_PLL_PLL2		(MTK_PLL_BASE + 0x04)
+#define MTK_PLL_CLK_CON		(MTK_PLL_BASE + 0x18)
+#define MTK_PLL_PDN_CON		(MTK_PLL_BASE + 0x1C)
+
+/* MTK_PLL_PLL bit fields definitions */
+#define PLL_PLLVCOSEL		(0 << 0)
+#define PLL_MPLLSEL_SYSCLK	(1 << 3)
+#define PLL_MPLLSEL_PLL		(2 << 3)
+#define PLL_DPLLSEL		(1 << 5)
+#define PLL_UPLLSEL		(1 << 6)
+#define PLL_RST			(1 << 7)
+#define PLL_CALI		(1 << 8)
+
+/* MTK_PLL_CLK_CON bit fields definitions */
+#define PLL_CLKSQ_DIV2_DSP	(1 << 0)
+#define PLL_CLKSQ_DIV2_MCU	(1 << 1)
+#define PLL_CLKSQ_PLD		(1 << 2)
+#define PLL_SRCCLK		(1 << 7)
+#define PLL_CLKSQ_TEST		(1 << 15)
+
+/* MTK_PLL_PDN_CON bit fields definitions */
+#define PLL_PDN_CON_CLKSQ	(1 << 11)
+#define PLL_PDN_CON_MCU_DIV2	(1 << 12)
+#define PLL_PDN_CON_PLL		(1 << 13)
+#define PLL_PDN_CON_DSP_DIV2	(1 << 15)
+
+#endif
-- 
1.7.2.5





More information about the baseband-devel mailing list