This patch adds neo1973 'board' (FIC Neo1973 phone) support to u-boot.
Specifically, it adds support for the GTA01v3, GTA01v4, GTA01Bv2 and
GTA01Bv3 hardware revisions.

Signed-off-by: Harald Welte <laforge@openmoko.org>

Index: u-boot/Makefile
===================================================================
--- u-boot.orig/Makefile
+++ u-boot/Makefile
@@ -2417,6 +2417,14 @@
 sbc2410x_config: unconfig
 	@$(MKCONFIG) $(@:_config=) arm arm920t sbc2410x NULL s3c24x0
 
+gta01_config \
+gta01v3_config \
+gta01bv2_config \
+gta01bv3_config \
+gta01bv4_config \
+gta01v4_config :	unconfig
+	@sh board/neo1973/gta01/split_by_variant.sh $@
+
 qt2410_config	:	unconfig
 	@./mkconfig $(@:_config=) arm arm920t qt2410 NULL s3c24x0
 
Index: u-boot/common/main.c
===================================================================
--- u-boot.orig/common/main.c
+++ u-boot/common/main.c
@@ -66,6 +66,7 @@
 #undef DEBUG_PARSER
 
 char        console_buffer[CFG_CBSIZE];		/* console I/O buffer	*/
+int nobootdelay;
 
 #ifndef CONFIG_CMDLINE_EDITING
 static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);
@@ -381,7 +382,7 @@
 
 	debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
 
-	if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
+	if (!nobootdelay && bootdelay >= 0 && s && !abortboot (bootdelay)) {
 # ifdef CONFIG_AUTOBOOT_KEYED
 		int prev = disable_ctrlc(1);	/* disable Control C checking */
 # endif
Index: u-boot/include/pcf50606.h
===================================================================
--- /dev/null
+++ u-boot/include/pcf50606.h
@@ -0,0 +1,273 @@
+#ifndef _PCF50606_H
+#define _PCF50606_H
+
+/* Philips PCF50606 Power Managemnt Unit (PMU) driver
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ *
+ */
+
+enum pfc50606_regs {
+	PCF50606_REG_ID		= 0x00,
+	PCF50606_REG_OOCS	= 0x01,
+	PCF50606_REG_INT1	= 0x02,	/* Interrupt Status */
+	PCF50606_REG_INT2	= 0x03,	/* Interrupt Status */
+	PCF50606_REG_INT3	= 0x04,	/* Interrupt Status */
+	PCF50606_REG_INT1M	= 0x05,	/* Interrupt Mask */
+	PCF50606_REG_INT2M	= 0x06,	/* Interrupt Mask */
+	PCF50606_REG_INT3M	= 0x07,	/* Interrupt Mask */
+	PCF50606_REG_OOCC1	= 0x08,
+	PCF50606_REG_OOCC2	= 0x09,
+	PCF50606_REG_RTCSC	= 0x0a,	/* Second */
+	PCF50606_REG_RTCMN	= 0x0b,	/* Minute */
+	PCF50606_REG_RTCHR	= 0x0c,	/* Hour */
+	PCF50606_REG_RTCWD	= 0x0d,	/* Weekday */
+	PCF50606_REG_RTCDT	= 0x0e,	/* Day */
+	PCF50606_REG_RTCMT	= 0x0f,	/* Month */
+	PCF50606_REG_RTCYR	= 0x10,	/* Year */
+	PCF50606_REG_RTCSCA	= 0x11, /* Alarm Second */
+	PCF50606_REG_RTCMNA	= 0x12, /* Alarm Minute */
+	PCF50606_REG_RTCHRA	= 0x13, /* Alarm Hour */
+	PCF50606_REG_RTCWDA	= 0x14, /* Alarm Weekday */
+	PCF50606_REG_RTCDTA	= 0x15, /* Alarm Day */
+	PCF50606_REG_RTCMTA	= 0x16, /* Alarm Month */
+	PCF50606_REG_RTCYRA	= 0x17, /* Alarm Year */
+	PCF50606_REG_PSSC	= 0x18,	/* Power sequencing */
+	PCF50606_REG_PWROKM	= 0x19,	/* PWROK mask */
+	PCF50606_REG_PWROKS	= 0x1a,	/* PWROK status */
+	PCF50606_REG_DCDC1	= 0x1b,
+	PCF50606_REG_DCDC2	= 0x1c,
+	PCF50606_REG_DCDC3	= 0x1d,
+	PCF50606_REG_DCDC4	= 0x1e,
+	PCF50606_REG_DCDEC1	= 0x1f,
+	PCF50606_REG_DCDEC2	= 0x20,
+	PCF50606_REG_DCUDC1	= 0x21,
+	PCF50606_REG_DCUDC2	= 0x22,
+	PCF50606_REG_IOREGC	= 0x23,
+	PCF50606_REG_D1REGC1	= 0x24,
+	PCF50606_REG_D2REGC1	= 0x25,
+	PCF50606_REG_D3REGC1	= 0x26,
+	PCF50606_REG_LPREGC1	= 0x27,
+	PCF50606_REG_LPREGC2	= 0x28,
+	PCF50606_REG_MBCC1	= 0x29,
+	PCF50606_REG_MBCC2	= 0x2a,
+	PCF50606_REG_MBCC3	= 0x2b,
+	PCF50606_REG_MBCS1	= 0x2c,
+	PCF50606_REG_BBCC	= 0x2d,
+	PCF50606_REG_ADCC1	= 0x2e,
+	PCF50606_REG_ADCC2	= 0x2f,
+	PCF50606_REG_ADCS1	= 0x30,
+	PCF50606_REG_ADCS2	= 0x31,
+	PCF50606_REG_ADCS3	= 0x32,
+	PCF50606_REG_ACDC1	= 0x33,
+	PCF50606_REG_BVMC	= 0x34,
+	PCF50606_REG_PWMC1	= 0x35,
+	PCF50606_REG_LEDC1	= 0x36,
+	PCF50606_REG_LEDC2	= 0x37,
+	PCF50606_REG_GPOC1	= 0x38,
+	PCF50606_REG_GPOC2	= 0x39,
+	PCF50606_REG_GPOC3	= 0x3a,
+	PCF50606_REG_GPOC4	= 0x3b,
+	PCF50606_REG_GPOC5	= 0x3c,
+	__NUM_PCF50606_REGS
+};
+
+enum pcf50606_reg_oocs {
+	PFC50606_OOCS_ONKEY	= 0x01,
+	PCF50606_OOCS_EXTON	= 0x02,
+	PCF50606_OOCS_PWROKRST	= 0x04,
+	PCF50606_OOCS_BATOK	= 0x08,
+	PCF50606_OOCS_BACKOK	= 0x10,
+	PCF50606_OOCS_CHGOK	= 0x20,
+	PCF50606_OOCS_TEMPOK	= 0x40,
+	PCF50606_OOCS_WDTEXP	= 0x80,
+};
+
+enum pcf50606_reg_oocc1 {
+	PCF50606_OOCC1_GOSTDBY	= 0x01,
+	PCF50606_OOCC1_TOTRST	= 0x02,
+	PCF50606_OOCC1_CLK32ON	= 0x04,
+	PCF50606_OOCC1_WDTRST	= 0x08,
+	PCF50606_OOCC1_RTCWAK	= 0x10,
+	PCF50606_OOCC1_CHGWAK	= 0x20,
+	PCF50606_OOCC1_EXTONWAK_HIGH	= 0x40,
+	PCF50606_OOCC1_EXTONWAK_LOW	= 0x80,
+	PCF50606_OOCC1_EXTONWAK_NO_WAKEUP = 0x3f,
+};
+
+enum pcf50606_reg_oocc2 {
+	PCF50606_OOCC2_ONKEYDB_NONE	= 0x00,
+	PCF50606_OOCC2_ONKEYDB_14ms	= 0x01,
+	PCF50606_OOCC2_ONKEYDB_62ms	= 0x02,
+	PCF50606_OOCC2_ONKEYDB_500ms	= 0x03,
+	PCF50606_OOCC2_EXTONDB_NONE	= 0x00,
+	PCF50606_OOCC2_EXTONDB_14ms	= 0x04,
+	PCF50606_OOCC2_EXTONDB_62ms	= 0x08,
+	PCF50606_OOCC2_EXTONDB_500ms	= 0x0c,
+};
+
+enum pcf50606_reg_int1 {
+	PCF50606_INT1_ONKEYR	= 0x01,	/* ONKEY rising edge */
+	PCF50606_INT1_ONKEYF	= 0x02,	/* ONKEY falling edge */
+	PCF50606_INT1_ONKEY1S	= 0x04,	/* OMKEY at least 1sec low */
+	PCF50606_INT1_EXTONR	= 0x08,	/* EXTON rising edge */
+	PCF50606_INT1_EXTONF	= 0x10,	/* EXTON falling edge */
+	PCF50606_INT1_SECOND	= 0x40,	/* RTC periodic second interrupt */
+	PCF50606_INT1_ALARM	= 0x80, /* RTC alarm time is reached */
+};
+
+enum pcf50606_reg_int2 {
+	PCF50606_INT2_CHGINS	= 0x01, /* Charger inserted */
+	PCF50606_INT2_CHGRM	= 0x02, /* Charger removed */
+	PCF50606_INT2_CHGFOK	= 0x04,	/* Fast charging OK */
+	PCF50606_INT2_CHGERR	= 0x08,	/* Error in charging mode */
+	PCF50606_INT2_CHGFRDY	= 0x10,	/* Fast charge completed */
+	PCF50606_INT2_CHGPROT	= 0x20,	/* Charging protection interrupt */
+	PCF50606_INT2_CHGWD10S	= 0x40,	/* Charger watchdig expires in 10s */
+	PCF50606_INT2_CHGWDEXP	= 0x80,	/* Charger watchdog expires */
+};
+
+enum pcf50606_reg_int3 {
+	PCF50606_INT3_ADCRDY	= 0x01,	/* ADC conversion finished */
+	PCF50606_INT3_ACDINS	= 0x02,	/* Accessory inserted */
+	PCF50606_INT3_ACDREM	= 0x04, /* Accessory removed */
+	PCF50606_INT3_TSCPRES	= 0x08,	/* Touch screen pressed */
+	PCF50606_INT3_LOWBAT	= 0x40,	/* Low battery voltage */
+	PCF50606_INT3_HIGHTMP	= 0x80, /* High temperature */
+};
+
+/* used by PSSC, PWROKM, PWROKS, */
+enum pcf50606_regu {
+	PCF50606_REGU_DCD	= 0x01,	/* DCD in phase 2 */
+	PCF50606_REGU_DCDE	= 0x02,	/* DCDE in phase 2 */
+	PCF50606_REGU_DCUD	= 0x04,	/* DCDU in phase 2 */
+	PCF50606_REGU_IO	= 0x08,	/* IO in phase 2 */
+	PCF50606_REGU_D1	= 0x10, /* D1 in phase 2 */
+	PCF50606_REGU_D2	= 0x20,	/* D2 in phase 2 */
+	PCF50606_REGU_D3	= 0x40,	/* D3 in phase 2 */
+	PCF50606_REGU_LP	= 0x80,	/* LP in phase 2 */
+};
+
+enum pcf50606_reg_dcdc4 {
+	PCF50606_DCDC4_MODE_AUTO	= 0x00,
+	PCF50606_DCDC4_MODE_PWM		= 0x01,
+	PCF50606_DCDC4_MODE_PCF		= 0x02,
+	PCF50606_DCDC4_OFF_FLOAT	= 0x00,
+	PCF50606_DCDC4_OFF_BYPASS	= 0x04,
+	PCF50606_DCDC4_OFF_PULLDOWN	= 0x08,
+	PCF50606_DCDC4_CURLIM_500mA	= 0x00,
+	PCF50606_DCDC4_CURLIM_750mA	= 0x10,
+	PCF50606_DCDC4_CURLIM_1000mA	= 0x20,
+	PCF50606_DCDC4_CURLIM_1250mA	= 0x30,
+	PCF50606_DCDC4_TOGGLE		= 0x40,
+	PCF50606_DCDC4_REGSEL_DCDC2	= 0x80,
+};
+
+enum pcf50606_reg_dcdec2 {
+	PCF50606_DCDEC2_MODE_AUTO	= 0x00,
+	PCF50606_DCDEC2_MODE_PWM	= 0x01,
+	PCF50606_DCDEC2_MODE_PCF	= 0x02,
+	PCF50606_DCDEC2_OFF_FLOAT	= 0x00,
+	PCF50606_DCDEC2_OFF_BYPASS	= 0x04,
+};
+
+enum pcf50606_reg_dcudc2 {
+	PCF50606_DCUDC2_MODE_AUTO	= 0x00,
+	PCF50606_DCUDC2_MODE_PWM	= 0x01,
+	PCF50606_DCUDC2_MODE_PCF	= 0x02,
+	PCF50606_DCUDC2_OFF_FLOAT	= 0x00,
+	PCF50606_DCUDC2_OFF_BYPASS	= 0x04,
+};
+
+enum pcf50606_reg_adcc1 {
+	PCF50606_ADCC1_TSCMODACT	= 0x01,
+	PCF50606_ADCC1_TSCMODSTB	= 0x02,
+	PCF50606_ADCC1_TRATSET		= 0x04,
+	PCF50606_ADCC1_NTCSWAPE		= 0x08,
+	PCF50606_ADCC1_NTCSWAOFF	= 0x10,
+	PCF50606_ADCC1_EXTSYNCBREAK	= 0x20,
+	/* reserved */
+	PCF50606_ADCC1_TSCINT		= 0x80,
+};
+
+enum pcf50606_reg_adcc2 {
+	PCF50606_ADCC2_ADCSTART		= 0x01,
+	/* see enum pcf50606_adcc2_adcmux */
+	PCF50606_ADCC2_SYNC_NONE	= 0x00,
+	PCF50606_ADCC2_SYNC_TXON	= 0x20,
+	PCF50606_ADCC2_SYNC_PWREN1	= 0x40,
+	PCF50606_ADCC2_SYNC_PWREN2	= 0x60,
+	PCF50606_ADCC2_RES_10BIT	= 0x00,
+	PCF50606_ADCC2_RES_8BIT		= 0x80,
+};
+
+#define PCF50606_ADCC2_ADCMUX_MASK	(0xf << 1)
+
+#define ADCMUX_SHIFT	1
+enum pcf50606_adcc2_adcmux {
+	PCF50606_ADCMUX_BATVOLT_RES	= 0x0 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_BATVOLT_SUBTR	= 0x1 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_ADCIN1_RES	= 0x2 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_ADCIN1_SUBTR	= 0x3 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_BATTEMP		= 0x4 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_ADCIN2		= 0x5 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_ADCIN3		= 0x6 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_ADCIN3_RATIO	= 0x7 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_XPOS		= 0x8 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_YPOS		= 0x9 << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_P1		= 0xa << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_P2		= 0xb << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_BATVOLT_ADCIN1	= 0xc << ADCMUX_SHIFT,
+	PCF50606_ADCMUX_XY_SEQUENCE	= 0xe << ADCMUX_SHIFT,
+	PCF50606_P1_P2_RESISTANCE	= 0xf << ADCMUX_SHIFT,
+};
+
+enum pcf50606_adcs2 {
+	PCF50606_ADCS2_ADCRDY		= 0x80,
+};
+
+enum pcf50606_reg_mbcc1 {
+	PCF50606_MBCC1_CHGAPE		= 0x01,
+	PCF50606_MBCC1_AUTOFST		= 0x02,
+#define	PCF50606_MBCC1_CHGMOD_MASK	  0x1c
+#define	PCF50606_MBCC1_CHGMOD_SHIFT	  2
+	PCF50606_MBCC1_CHGMOD_QUAL	= 0x00,
+	PCF50606_MBCC1_CHGMOD_PRE	= 0x04,
+	PCF50606_MBCC1_CHGMOD_TRICKLE	= 0x08,
+	PCF50606_MBCC1_CHGMOD_FAST_CCCV	= 0x0c,
+	PCF50606_MBCC1_CHGMOD_FAST_NOCC	= 0x10,
+	PCF50606_MBCC1_CHGMOD_FAST_NOCV	= 0x14,
+	PCF50606_MBCC1_CHGMOD_FAST_SW	= 0x18,
+	PCF50606_MBCC1_CHGMOD_IDLE	= 0x1c,
+	PCF50606_MBCC1_DETMOD_LOWCHG	= 0x20,
+	PCF50606_MBCC1_DETMOD_WDRST	= 0x40,
+};
+
+enum pcf50606_reg_bvmc {
+	PCF50606_BVMC_LOWBAT		= 0x01,
+	PCF50606_BVMC_THRSHLD_NULL	= 0x00,
+	PCF50606_BVMC_THRSHLD_2V8	= 0x02,
+	PCF50606_BVMC_THRSHLD_2V9	= 0x04,
+	PCF50606_BVMC_THRSHLD_3V	= 0x08,
+	PCF50606_BVMC_THRSHLD_3V1	= 0x08,
+	PCF50606_BVMC_THRSHLD_3V2	= 0x0a,
+	PCF50606_BVMC_THRSHLD_3V3	= 0x0c,
+	PCF50606_BVMC_THRSHLD_3V4	= 0x0e,
+	PCF50606_BVMC_DISDB		= 0x10,
+};
+
+/* this is to be provided by the board implementation */
+extern const u_int8_t pcf50606_initial_regs[__NUM_PCF50606_REGS];
+
+void pcf50606_reg_write(u_int8_t reg, u_int8_t val);
+
+u_int8_t pcf50606_reg_read(u_int8_t reg);
+
+void pcf50606_reg_set_bit_mask(u_int8_t reg, u_int8_t mask, u_int8_t val);
+void pcf50606_reg_clear_bits(u_int8_t reg, u_int8_t bits);
+
+void pcf50606_init(void);
+void pcf50606_charge_autofast(int on);
+
+#endif /* _PCF50606_H */
+
Index: u-boot/board/neo1973/common/cmd_neo1973.c
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/common/cmd_neo1973.c
@@ -0,0 +1,126 @@
+/*
+ * (C) Copyright 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>		/* for print_IPaddr */
+#include <s3c2410.h>
+
+#include "neo1973.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CMD_BDI)
+
+int do_neo1973 ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int i;
+
+	if (!strcmp(argv[1], "info")) {
+		printf("FIC Neo1973 Hardware Revision 0x%04x\n", get_board_rev());
+	} else if (!strcmp(argv[1], "power-off")) {
+		neo1973_poweroff();
+	} else if (!strcmp(argv[1], "charger") || !strcmp(argv[1], "charge")) {
+		if (argc < 3)
+			goto out_help;
+		if (!strcmp(argv[2], "status") || !strcmp(argv[2], "state")) {
+			printf("%s\n", neo1973_get_charge_status());
+		} else if (!strcmp(argv[2], "autofast")) {
+			neo1973_set_charge_mode(NEO1973_CHGCMD_AUTOFAST);
+		} else if (!strcmp(argv[2], "!autofast")) {
+			neo1973_set_charge_mode(NEO1973_CHGCMD_NO_AUTOFAST);
+		} else if (!strcmp(argv[2], "off")) {
+			neo1973_set_charge_mode(NEO1973_CHGCMD_OFF);
+		} else if (!strcmp(argv[2], "fast")) {
+			neo1973_set_charge_mode(NEO1973_CHGCMD_FAST);
+		} else
+			goto out_help;
+	} else if (!strcmp(argv[1], "backlight")) {
+		if (argc < 3)
+			goto out_help;
+		if (!strcmp(argv[2], "on"))
+			neo1973_backlight(1);
+		else
+			neo1973_backlight(0);
+	} else if (!strcmp(argv[1], "led")) {
+		long led = simple_strtol(argv[2], NULL, 10);
+		if (argc < 4)
+			goto out_help;
+		if (!strcmp(argv[3], "on"))
+			neo1973_led(led, 1);
+		else
+			neo1973_led(led, 0);
+	} else if (!strcmp(argv[1], "vibrator")) {
+		if (argc < 3)
+			goto out_help;
+		if (!strcmp(argv[2], "on"))
+			neo1973_vibrator(1);
+		else
+			neo1973_vibrator(0);
+	} else if (!strcmp(argv[1], "gsm")) {
+		if (argc < 3)
+			goto out_help;
+		if (!strcmp(argv[2], "on"))
+			neo1973_gsm(1);
+		else if (!strcmp(argv[2], "off"))
+			neo1973_gsm(0);
+		else if (!strcmp(argv[2], "version"))
+			neo1973_gsmver();
+	} else if (!strcmp(argv[1], "gps")) {
+		if (argc < 3)
+			goto out_help;
+		if (!strcmp(argv[2], "on"))
+			neo1973_gps(1);
+		else
+			neo1973_gps(0);
+	} else {
+out_help:
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------- */
+
+U_BOOT_CMD(
+	neo1973,	4,	1,	do_neo1973,
+	"neo1973 - phone specific commands\n",
+	"neo1973 info - display phone informantion\n"
+	"neo1973 power-off - switch off the phone\n"
+	"neo1973 charger status - display charger status\n"
+	"neo1973 charger autofast - enable automatic fast (500mA) charging\n"
+	"neo1973 charger !autofast - disable automatic fast (500mA) charging\n"
+	"neo1973 charger fast - enable fast (500mA) charging\n"
+	"neo1973 charger off - disable charging\n"
+	"neo1973 backlight (on|off) - switch backlight on or off\n"
+	"neo1973 led num (on|off) - switch LED number 'num' on or off\n"
+	"neo1973 vibrator (on|off) - switch vibrator on or off\n"
+	"neo1973 gsm (on|off|version) - switch GSM Modem on/off or print firmware version\n"
+	"neo1973 gps (on|off) - switch GPS system on or off\n"
+);
+#endif	/* CONFIG_CMD_BDI */
Index: u-boot/board/neo1973/common/jbt6k74.c
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/common/jbt6k74.c
@@ -0,0 +1,420 @@
+/* u-boot driver for the tpo JBT6K74-AS LCM ASIC
+ *
+ * Copyright (C) 2006-2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#include <common.h>
+#include <spi.h>
+#include <video_fb.h>
+#include <asm/errno.h>
+#include <s3c2410.h>
+#include "jbt6k74.h"
+
+#if 0
+#define DEBUGP(x, args...) printf("%s: " x, __FUNCTION__, ## args);
+#define DEBUGPC(x, args...) printf(x, ## args);
+#else
+#define DEBUGP(x, args...) do { } while (0)
+#define DEBUGPC(x, args...) do { } while (0)
+#endif
+
+
+enum jbt_register {
+	JBT_REG_SLEEP_IN		= 0x10,
+	JBT_REG_SLEEP_OUT		= 0x11,
+
+	JBT_REG_DISPLAY_OFF		= 0x28,
+	JBT_REG_DISPLAY_ON		= 0x29,
+
+	JBT_REG_RGB_FORMAT		= 0x3a,
+	JBT_REG_QUAD_RATE		= 0x3b,
+
+	JBT_REG_POWER_ON_OFF		= 0xb0,
+	JBT_REG_BOOSTER_OP		= 0xb1,
+	JBT_REG_BOOSTER_MODE		= 0xb2,
+	JBT_REG_BOOSTER_FREQ		= 0xb3,
+	JBT_REG_OPAMP_SYSCLK		= 0xb4,
+	JBT_REG_VSC_VOLTAGE		= 0xb5,
+	JBT_REG_VCOM_VOLTAGE		= 0xb6,
+	JBT_REG_EXT_DISPL		= 0xb7,
+	JBT_REG_OUTPUT_CONTROL		= 0xb8,
+	JBT_REG_DCCLK_DCEV		= 0xb9,
+	JBT_REG_DISPLAY_MODE1		= 0xba,
+	JBT_REG_DISPLAY_MODE2		= 0xbb,
+	JBT_REG_DISPLAY_MODE		= 0xbc,
+	JBT_REG_ASW_SLEW		= 0xbd,
+	JBT_REG_DUMMY_DISPLAY		= 0xbe,
+	JBT_REG_DRIVE_SYSTEM		= 0xbf,
+
+	JBT_REG_SLEEP_OUT_FR_A		= 0xc0,
+	JBT_REG_SLEEP_OUT_FR_B		= 0xc1,
+	JBT_REG_SLEEP_OUT_FR_C		= 0xc2,
+	JBT_REG_SLEEP_IN_LCCNT_D	= 0xc3,
+	JBT_REG_SLEEP_IN_LCCNT_E	= 0xc4,
+	JBT_REG_SLEEP_IN_LCCNT_F	= 0xc5,
+	JBT_REG_SLEEP_IN_LCCNT_G	= 0xc6,
+
+	JBT_REG_GAMMA1_FINE_1		= 0xc7,
+	JBT_REG_GAMMA1_FINE_2		= 0xc8,
+	JBT_REG_GAMMA1_INCLINATION	= 0xc9,
+	JBT_REG_GAMMA1_BLUE_OFFSET	= 0xca,
+
+	JBT_REG_BLANK_CONTROL		= 0xcf,
+	JBT_REG_BLANK_TH_TV		= 0xd0,
+	JBT_REG_CKV_ON_OFF		= 0xd1,
+	JBT_REG_CKV_1_2			= 0xd2,
+	JBT_REG_OEV_TIMING		= 0xd3,
+	JBT_REG_ASW_TIMING_1		= 0xd4,
+	JBT_REG_ASW_TIMING_2		= 0xd5,
+
+	JBT_REG_HCLOCK_VGA		= 0xec,
+	JBT_REG_HCLOCK_QVGA		= 0xed,
+
+};
+
+static const char *jbt_state_names[] = {
+	[JBT_STATE_DEEP_STANDBY]	= "deep-standby",
+	[JBT_STATE_SLEEP]		= "sleep",
+	[JBT_STATE_NORMAL]		= "normal",
+};
+
+#define GTA01_SCLK	(1 << 7) 	/* GPG7 */
+#define GTA01_MOSI	(1 << 6)	/* GPG6 */
+#define GTA01_MISO	(1 << 5)	/* GPG5 */
+#define GTA01_CS	(1 << 3)	/* GPG3 */
+
+#define SPI_READ        ((immr->GPGDAT & GTA01_MISO) != 0)
+
+#define SPI_CS(bit) 	if (bit) gpio->GPGDAT |= GTA01_CS; \
+			else gpio->GPGDAT &= ~GTA01_CS
+
+#define SPI_SDA(bit)    if (bit) gpio->GPGDAT |=  GTA01_MOSI; \
+			else    gpio->GPGDAT &= ~GTA01_MOSI
+
+#define SPI_SCL(bit)    if (bit) gpio->GPGDAT |=  GTA01_SCLK; \
+			else    gpio->GPGDAT &= ~GTA01_SCLK
+
+/* 150uS minimum clock cycle, we have two of this plus our other
+ * instructions */
+#define SPI_DELAY	udelay(100)	/* 200uS */
+
+
+#define JBT_TX_BUF_SIZE
+struct jbt_info {
+	enum jbt_state state;
+	u_int16_t tx_buf[4];
+	struct spi_device *spi_dev;
+};
+
+static struct jbt_info _jbt, *jbt = &_jbt;
+
+static int jbt_spi_xfer(int wordnum, int bitlen, u_int16_t *dout)
+{
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+	u_int16_t tmpdout = 0;
+	int   i, j;
+
+	DEBUGP("spi_xfer: dout %08X wordnum %u bitlen %d\n",
+		*(uint *)dout, wordnum, bitlen);
+
+	SPI_CS(0);
+
+	for (i = 0; i < wordnum; i ++) {
+		tmpdout = dout[i];
+
+		for (j = 0; j < bitlen; j++) {
+			SPI_SCL(0);
+			if (tmpdout & (1 << bitlen-1)) {
+				SPI_SDA(1);
+				DEBUGPC("1");
+			} else {
+				SPI_SDA(0);
+				DEBUGPC("0");
+			}
+			SPI_DELAY;
+			SPI_SCL(1);
+			SPI_DELAY;
+			tmpdout <<= 1;
+		}
+		DEBUGPC(" ");
+	}
+	DEBUGPC("\n");
+
+	SPI_CS(1);
+
+	return 0;
+}
+
+#define JBT_COMMAND	0x000
+#define JBT_DATA	0x100
+
+static int jbt_reg_write_nodata(struct jbt_info *jbt, u_int8_t reg)
+{
+	int rc;
+
+	jbt->tx_buf[0] = JBT_COMMAND | reg;
+
+	rc = jbt_spi_xfer(1, 9, jbt->tx_buf);
+
+	return rc;
+}
+
+
+static int jbt_reg_write(struct jbt_info *jbt, u_int8_t reg, u_int8_t data)
+{
+	int rc;
+
+	jbt->tx_buf[0] = JBT_COMMAND | reg;
+	jbt->tx_buf[1] = JBT_DATA | data;
+
+	rc = jbt_spi_xfer(2, 9, jbt->tx_buf);
+
+	return rc;
+}
+
+static int jbt_reg_write16(struct jbt_info *jbt, u_int8_t reg, u_int16_t data)
+{
+	int rc;
+
+	jbt->tx_buf[0] = JBT_COMMAND | reg;
+	jbt->tx_buf[1] = JBT_DATA | (data >> 8);
+	jbt->tx_buf[2] = JBT_DATA | (data & 0xff);
+
+	rc = jbt_spi_xfer(3, 9, jbt->tx_buf);
+
+	return rc;
+}
+
+static int jbt_init_regs(struct jbt_info *jbt)
+{
+	int rc;
+
+	DEBUGP("entering\n");
+
+	rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE1, 0x01);
+	rc |= jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE2, 0x00);
+	rc |= jbt_reg_write(jbt, JBT_REG_RGB_FORMAT, 0x60);
+	rc |= jbt_reg_write(jbt, JBT_REG_DRIVE_SYSTEM, 0x10);
+	rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_OP, 0x56);
+	rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_MODE, 0x33);
+	rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_FREQ, 0x11);
+	rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_FREQ, 0x11);
+	rc |= jbt_reg_write(jbt, JBT_REG_OPAMP_SYSCLK, 0x02);
+	rc |= jbt_reg_write(jbt, JBT_REG_VSC_VOLTAGE, 0x2b);
+	rc |= jbt_reg_write(jbt, JBT_REG_VCOM_VOLTAGE, 0x40);
+	rc |= jbt_reg_write(jbt, JBT_REG_EXT_DISPL, 0x03);
+	rc |= jbt_reg_write(jbt, JBT_REG_DCCLK_DCEV, 0x04);
+	rc |= jbt_reg_write(jbt, JBT_REG_ASW_SLEW, 0x02);
+	rc |= jbt_reg_write(jbt, JBT_REG_DUMMY_DISPLAY, 0x00);
+
+	rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_A, 0x11);
+	rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_B, 0x11);
+	rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_C, 0x11);
+	rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_D, 0x2040);
+	rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_E, 0x60c0);
+	rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_F, 0x1020);
+	rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_G, 0x60c0);
+
+	rc |= jbt_reg_write16(jbt, JBT_REG_GAMMA1_FINE_1, 0x5533);
+	rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_FINE_2, 0x00);
+	rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_INCLINATION, 0x00);
+	rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
+	rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
+
+	rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_VGA, 0x1f0);
+	rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL, 0x02);
+	rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
+	rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
+
+	rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF, 0x01);
+	rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2, 0x0000);
+
+	rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING, 0x0d0e);
+	rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1, 0x11a4);
+	rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2, 0x0e);
+
+#if 0
+	rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_QVGA, 0x00ff);
+	rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_QVGA, 0x00ff);
+#endif
+
+	return rc;
+}
+
+static int standby_to_sleep(struct jbt_info *jbt)
+{
+	int rc;
+
+	DEBUGP("entering\n");
+
+	/* three times command zero */
+	rc = jbt_reg_write_nodata(jbt, 0x00);
+	udelay(1000);
+	rc = jbt_reg_write_nodata(jbt, 0x00);
+	udelay(1000);
+	rc = jbt_reg_write_nodata(jbt, 0x00);
+	udelay(1000);
+
+	/* deep standby out */
+	rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x17);
+
+	return rc;
+}
+
+static int sleep_to_normal(struct jbt_info *jbt)
+{
+	int rc;
+	DEBUGP("entering\n");
+
+	/* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */
+	rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80);
+
+	/* Quad mode off */
+	rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00);
+
+	/* AVDD on, XVDD on */
+	rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16);
+
+	/* Output control */
+	rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
+
+	/* Sleep mode off */
+	rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
+
+	/* initialize register set */
+	rc |= jbt_init_regs(jbt);
+	return rc;
+}
+
+static int normal_to_sleep(struct jbt_info *jbt)
+{
+	int rc;
+	DEBUGP("entering\n");
+
+	rc = jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF);
+	rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0x8002);
+	rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_IN);
+
+	return rc;
+}
+
+static int sleep_to_standby(struct jbt_info *jbt)
+{
+	DEBUGP("entering\n");
+	return jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x00);
+}
+
+/* frontend function */
+int jbt6k74_enter_state(enum jbt_state new_state)
+{
+	int rc = -EINVAL;
+
+	DEBUGP("entering(old_state=%u, new_state=%u)\n", jbt->state, new_state);
+
+	switch (jbt->state) {
+	case JBT_STATE_DEEP_STANDBY:
+		switch (new_state) {
+		case JBT_STATE_DEEP_STANDBY:
+			rc = 0;
+			break;
+		case JBT_STATE_SLEEP:
+			rc = standby_to_sleep(jbt);
+			break;
+		case JBT_STATE_NORMAL:
+			/* first transition into sleep */
+			rc = standby_to_sleep(jbt);
+			/* then transition into normal */
+			rc |= sleep_to_normal(jbt);
+			break;
+		}
+		break;
+	case JBT_STATE_SLEEP:
+		switch (new_state) {
+		case JBT_STATE_SLEEP:
+			rc = 0;
+			break;
+		case JBT_STATE_DEEP_STANDBY:
+			rc = sleep_to_standby(jbt);
+			break;
+		case JBT_STATE_NORMAL:
+			rc = sleep_to_normal(jbt);
+			break;
+		}
+		break;
+	case JBT_STATE_NORMAL:
+		switch (new_state) {
+		case JBT_STATE_NORMAL:
+			rc = 0;
+			break;
+		case JBT_STATE_DEEP_STANDBY:
+			/* first transition into sleep */
+			rc = normal_to_sleep(jbt);
+			/* then transition into deep standby */
+			rc |= sleep_to_standby(jbt);
+			break;
+		case JBT_STATE_SLEEP:
+			rc = normal_to_sleep(jbt);
+			break;
+		}
+		break;
+	}
+
+	return rc;
+}
+
+int jbt6k74_display_onoff(int on)
+{
+	DEBUGP("entering\n");
+	if (on)
+		return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON);
+	else
+		return jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF);
+}
+
+int jbt6k74_init(void)
+{
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+	/* initialize SPI for GPIO bitbang */
+	gpio->GPGCON &= 0xffff033f;
+	gpio->GPGCON |= 0x00005440;
+
+	/* get LCM out of reset */
+	gpio->GPCDAT |= (1 << 6);
+
+	/* according to data sheet: wait 50ms (Tpos of LCM). However, 50ms
+	 * seems unreliable with later LCM batches, increasing to 90ms */
+	udelay(90000);
+
+	return 0;
+}
+
+void board_video_init(GraphicDevice *pGD)
+{
+	S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();
+
+	lcd->LCDCON1 = 0x00000178; /* CLKVAL=1, BPPMODE=16bpp, TFT, ENVID=0 */
+
+	lcd->LCDCON2 = 0x019fc3c1;
+	lcd->LCDCON3 = 0x0039df67;
+	lcd->LCDCON4 = 0x00000007;
+	lcd->LCDCON5 = 0x0001cf09;
+	lcd->LPCSEL  = 0x00000000;
+}
Index: u-boot/board/neo1973/common/jbt6k74.h
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/common/jbt6k74.h
@@ -0,0 +1,14 @@
+#ifndef _JBT6K74_H
+#define _JBT6K74_H
+
+enum jbt_state {
+	JBT_STATE_DEEP_STANDBY,
+	JBT_STATE_SLEEP,
+	JBT_STATE_NORMAL,
+};
+
+int jbt6k74_init(void);
+int jbt6k74_display_onoff(int on);
+int jbt6k74_enter_state(enum jbt_state new_state);
+
+#endif
Index: u-boot/board/neo1973/common/lowlevel_init.S
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/common/lowlevel_init.S
@@ -0,0 +1,187 @@
+/*
+ * Memory Setup stuff - taken from blob memsetup.S
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
+ *                     Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+ *
+ * Modified for the FIC Neo1973 GTA01 by Harald Welte <laforge@openmoko.org>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <config.h>
+#include <version.h>
+
+
+/* some parameters for the board */
+
+/*
+ *
+ * Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
+ *
+ * Copyright (C) 2002 Samsung Electronics SW.LEE  <hitchcar@sec.samsung.com>
+ *
+ */
+
+#define BWSCON	0x48000000
+
+/* BWSCON */
+#define DW8		 	(0x0)
+#define DW16		 	(0x1)
+#define DW32		 	(0x2)
+#define WAIT		 	(0x1<<2)
+#define UBLB		 	(0x1<<3)
+
+#define B1_BWSCON	  	(DW32)
+#define B2_BWSCON	  	(DW16)
+#define B3_BWSCON	  	(DW16 + WAIT + UBLB)
+#define B4_BWSCON	  	(DW16)
+#define B5_BWSCON	  	(DW16)
+#define B6_BWSCON	  	(DW32)
+#define B7_BWSCON	  	(DW32)
+
+/* BANK0CON */
+#define B0_Tacs		 	0x0	/*  0clk */
+#define B0_Tcos		 	0x0	/*  0clk */
+#define B0_Tacc		 	0x7	/* 14clk */
+#define B0_Tcoh		 	0x0	/*  0clk */
+#define B0_Tah		 	0x0	/*  0clk */
+#define B0_Tacp		 	0x0
+#define B0_PMC		 	0x0	/* normal */
+
+/* BANK1CON */
+#define B1_Tacs		 	0x0	/*  0clk */
+#define B1_Tcos		 	0x0	/*  0clk */
+#define B1_Tacc		 	0x7	/* 14clk */
+#define B1_Tcoh		 	0x0	/*  0clk */
+#define B1_Tah		 	0x0	/*  0clk */
+#define B1_Tacp		 	0x0
+#define B1_PMC		 	0x0
+
+#define B2_Tacs		 	0x0
+#define B2_Tcos		 	0x0
+#define B2_Tacc		 	0x7
+#define B2_Tcoh		 	0x0
+#define B2_Tah		 	0x0
+#define B2_Tacp		 	0x0
+#define B2_PMC		 	0x0
+
+#define B3_Tacs		 	0x0	/*  0clk */
+#define B3_Tcos		 	0x3	/*  4clk */
+#define B3_Tacc		 	0x7	/* 14clk */
+#define B3_Tcoh		 	0x1	/*  1clk */
+#define B3_Tah		 	0x0	/*  0clk */
+#define B3_Tacp		 	0x3     /*  6clk */
+#define B3_PMC		 	0x0	/* normal */
+
+#define B4_Tacs		 	0x0	/*  0clk */
+#define B4_Tcos		 	0x0	/*  0clk */
+#define B4_Tacc		 	0x7	/* 14clk */
+#define B4_Tcoh		 	0x0	/*  0clk */
+#define B4_Tah		 	0x0	/*  0clk */
+#define B4_Tacp		 	0x0
+#define B4_PMC		 	0x0	/* normal */
+
+#define B5_Tacs		 	0x0	/*  0clk */
+#define B5_Tcos		 	0x0	/*  0clk */
+#define B5_Tacc		 	0x7	/* 14clk */
+#define B5_Tcoh		 	0x0	/*  0clk */
+#define B5_Tah		 	0x0	/*  0clk */
+#define B5_Tacp		 	0x0
+#define B5_PMC		 	0x0	/* normal */
+
+#define B6_MT		 	0x3	/* SDRAM */
+#define B6_Trcd	 	 	0x1	/* 3clk */
+#if defined (CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
+#define B6_SCAN		 	0x1	/* 9bit */
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3) || \
+      defined(CONFIG_ARCH_GTA01B_v4)
+#define B6_SCAN		 	0x2	/* 10bit */
+#endif
+
+#define B7_MT		 	0x3	/* SDRAM */
+#define B7_Trcd		 	0x1	/* 3clk */
+#define B7_SCAN		 	0x2	/* 10bit */
+
+/* REFRESH parameter */
+#define REFEN		 	0x1	/* Refresh enable */
+#define TREFMD		 	0x0	/* CBR(CAS before RAS)/Auto refresh */
+#define Trp		 	0x1	/* 3clk */
+#define Trc		 	0x3	/* 7clk */
+#define Tchr		 	0x2	/* 3clk */
+//#define REFCNT		 	1113	/* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
+#define REFCNT		 	997	/* period=17.5us, HCLK=60Mhz, (2048+1-15.6*60) */
+/**************************************/
+
+_TEXT_BASE:
+	.word	TEXT_BASE
+
+.globl lowlevel_init
+lowlevel_init:
+	/* memory control configuration */
+	/* make r0 relative the current location so that it */
+	/* reads SMRDATA out of FLASH rather than memory ! */
+	adr	r0, SMRDATA
+	ldr	r1, =BWSCON	/* Bus Width Status Controller */
+	add     r2, r0, #13*4
+0:
+	ldr     r3, [r0], #4
+	str     r3, [r1], #4
+	cmp     r2, r0
+	bne     0b
+
+	/* setup asynchronous bus mode */
+	mrc	p15, 0, r1 ,c1 ,c0, 0
+	orr	r1, r1, #0xc0000000
+	mcr	p15, 0, r1, c1, c0, 0
+
+#if defined(CONFIG_ARCH_GTA01_v4) || defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
+	/* switch on power for NAND */
+	ldr	r0, =0x56000010	/* GPBCON */
+	ldr	r1, [r0]
+	orr	r1, r1, #0x10
+	str	r1, [r0]
+
+	ldr	r0, =0x56000014	/* GPBDAT */
+	ldr	r1, [r0]
+	orr	r1, r1, #(1 <<2)
+	str	r1, [r0]
+#endif
+
+	/* everything is fine now */
+	mov	pc, lr
+
+	.ltorg
+/* the literal pools origin */
+
+SMRDATA:
+    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
+    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
+    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
+    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
+    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
+    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
+    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
+    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
+    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
+    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+    .word 0xb2
+    .word 0x30
+    .word 0x30
Index: u-boot/board/neo1973/gta01/Makefile
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/gta01/Makefile
@@ -0,0 +1,48 @@
+#
+# (C) Copyright 2000, 2001, 2002
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= lib$(BOARD).a
+
+OBJS	:= gta01.o pcf50606.o ../common/cmd_neo1973.o ../common/jbt6k74.o \
+	   ../common/gsmver.o
+SOBJS	:= ../common/lowlevel_init.o
+
+$(LIB):	$(OBJS) $(SOBJS)
+	$(AR) crv $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+		$(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+-include .depend
+
+#########################################################################
Index: u-boot/board/neo1973/gta01/config.mk
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/gta01/config.mk
@@ -0,0 +1,34 @@
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
+#
+# FIC Neo1973 GTA01 board with S3C2410X (ARM920T) cpu
+#
+# see http://www.samsung.com/ for more information on SAMSUNG
+#
+
+# GTA01v3 has 1 bank of 64 MB SDRAM
+# GTA01v4 has 1 bank of 64 MB SDRAM
+#
+# 	3000'0000 to 3400'0000
+# we load ourself to 33F8'0000
+#
+# GTA01Bv2 or later has 1 bank of 128 MB SDRAM
+#
+# 	3000'0000 to 3800'0000
+# we load ourself to 37F8'0000
+#
+# Linux-Kernel is expected to be at 3000'8000, entry 3000'8000
+# optionally with a ramdisk at 3080'0000
+#
+# download area is 3200'0000 or 3300'0000
+
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+ifeq ($(GTA01_BIG_RAM),y)
+# FIXME: TEXT_BASE = 0x37F80000
+TEXT_BASE = 0x33F80000
+else
+TEXT_BASE = 0x33F80000
+endif
Index: u-boot/board/neo1973/gta01/gta01.c
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/gta01/gta01.c
@@ -0,0 +1,491 @@
+/*
+ * (C) 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ *
+ * based on existing S3C2410 startup code in u-boot:
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <devices.h>
+#include <s3c2410.h>
+#include <i2c.h>
+
+#include "pcf50606.h"
+
+#include "../common/neo1973.h"
+#include "../common/jbt6k74.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* That many seconds the power key needs to be pressed to power up */
+#define POWER_KEY_SECONDS	2
+
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
+//#define M_MDIV	0xA1		/* Fout = 202.8MHz */
+//#define M_PDIV	0x3
+//#define M_SDIV	0x1
+#define M_MDIV	0x90		/* Fout = 202.8MHz */
+#define M_PDIV	0x7
+#define M_SDIV	0x0
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
+/* In case the debug board is attached, we cannot go beyond 200 MHz */
+#if 0
+#define M_MDIV	0x7d		/* Fout = 266MHz */
+#define M_PDIV	0x1
+#define M_SDIV	0x1
+#else
+#define M_MDIV	0x90		/* Fout = 202.8MHz */
+#define M_PDIV	0x7
+#define M_SDIV	0x0
+#endif
+#elif defined(CONFIG_ARCH_GTA01B_v4)
+/* This board doesn't have bus lines at teh debug port, and we can go to 266 */
+#define M_MDIV	0x7d		/* Fout = 266MHz */
+#define M_PDIV	0x1
+#define M_SDIV	0x1
+#else
+#error Please define GTA01 revision
+#endif
+
+#define U_M_MDIV	0x78
+#define U_M_PDIV	0x2
+#define U_M_SDIV	0x3
+
+unsigned int neo1973_wakeup_cause;
+extern int nobootdelay;
+
+static inline void delay (unsigned long loops)
+{
+	__asm__ volatile ("1:\n"
+	  "subs %0, %1, #1\n"
+	  "bne 1b":"=r" (loops):"0" (loops));
+}
+
+/*
+ * Miscellaneous platform dependent initialisations
+ */
+
+int board_init (void)
+{
+	S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+	/* to reduce PLL lock time, adjust the LOCKTIME register */
+	clk_power->LOCKTIME = 0xFFFFFF;
+
+	/* configure MPLL */
+	clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
+
+	/* some delay between MPLL and UPLL */
+	delay (4000);
+
+	/* configure UPLL */
+	clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
+
+	/* some delay between MPLL and UPLL */
+	delay (8000);
+
+	/* set up the I/O ports */
+#if defined(CONFIG_ARCH_GTA01_v3)
+	gpio->GPACON = 0x007FFFFF;
+
+	gpio->GPBCON = 0x00005055;
+	gpio->GPBUP = 0x000007FF;
+
+	gpio->GPCCON = 0xAAAA12A8;
+	gpio->GPCUP = 0x0000FFFF;
+
+	gpio->GPDCON = 0xAAAAAAAA;
+	gpio->GPDUP = 0x0000FFFF;
+
+	gpio->GPECON = 0xAAAAAAAA;
+	gpio->GPEUP = 0x0000FFFF;
+
+	gpio->GPFCON = 0x00002AA9;
+	gpio->GPFUP = 0x000000FF;
+
+	gpio->GPGCON = 0xA846F0C0;
+	gpio->GPGUP = 0x0000AFEF;
+
+	gpio->GPHCON = 0x0008FAAA;
+	gpio->GPHUP = 0x000007FF;
+#elif defined(CONFIG_ARCH_GTA01_v4)
+	gpio->GPACON = 0x005E47FF;
+
+	gpio->GPBCON = 0x00045015;
+	gpio->GPBUP = 0x000007FF;
+	gpio->GPBDAT |= 0x4;		/* Set GPB2 to high (Flash power-up) */
+
+	gpio->GPCCON = 0xAAAA12A9;
+	gpio->GPCUP = 0x0000FFFF;
+
+	gpio->GPDCON = 0xAAAAAAAA;
+	gpio->GPDUP = 0x0000FFFF;
+
+	gpio->GPECON = 0xA02AAAAA;
+	gpio->GPEUP = 0x0000FFFF;
+
+	gpio->GPFCON = 0x0000aa09;
+	gpio->GPFUP = 0x000000FF;
+
+	gpio->GPGCON = 0xFF40F0C1;
+	gpio->GPGUP = 0x0000AFEF;
+
+	gpio->GPHCON = 0x0000FAAA;
+	gpio->GPHUP = 0x000007FF;
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
+	gpio->GPACON = 0x005E4FFF;
+
+	gpio->GPBCON = 0x00145415;
+	gpio->GPBUP = 0x000007FF;
+	gpio->GPBDAT |= 0x4;		/* Set GPB2 to high (Flash power-up) */
+
+	gpio->GPCCON = 0xAAAA12A9;
+	gpio->GPCUP = 0x0000FFFF;
+
+	gpio->GPDCON = 0xAAAAAAAA;
+	gpio->GPDUP = 0x0000FFFF;
+
+	gpio->GPECON = 0xA02AAAAA;
+	gpio->GPEUP = 0x0000FFFF;
+
+	gpio->GPFCON = 0x0000aa19;
+	gpio->GPFUP = 0x000000FF;
+	gpio->GPFDAT |= 0x4;		/* Set GBF2 to high (nGSM_EN) */
+
+	gpio->GPGCON = 0xFF40F0C1;
+	gpio->GPGUP = 0x0000AFEF;
+
+	gpio->GPHCON = 0x0000FAAA;
+	gpio->GPHUP = 0x000007FF;
+#elif defined(CONFIG_ARCH_GTA01B_v4)
+	gpio->GPACON = 0x0005E0FFF;
+	gpio->GPADAT |= (1 << 16);	/* Set GPA16 to high (nNAND_WP) */
+
+	gpio->GPBCON = 0x00045455;
+	gpio->GPBUP = 0x000007FF;
+	gpio->GPBDAT |= 0x4;            /* Set GPB2 to high (SD power down) */
+
+	gpio->GPCCON = 0xAAAA12A9;
+	gpio->GPCUP = 0x0000FFFF;
+
+	gpio->GPDCON = 0xAAAAAAAA;
+	gpio->GPDUP = 0x0000FFFF;
+
+	gpio->GPECON = 0xAAAAAAAA;
+	gpio->GPEUP = 0x0000FFFF;
+
+	gpio->GPFCON = 0x0000aa99;
+	gpio->GPFUP = 0x000000FF;
+	gpio->GPFDAT |= 0x4;		/* Set GBF2 to high (nGSM_EN) */
+
+	gpio->GPGCON = 0xFF14F0F8;
+	gpio->GPGUP = 0x0000AFEF;
+
+	gpio->GPHCON = 0x0000FAAA;
+	gpio->GPHUP = 0x000007FF;
+#else
+#error Please define GTA01 version
+#endif
+
+	/* arch number of SMDK2410-Board */
+	gd->bd->bi_arch_number = MACH_TYPE_NEO1973_GTA01;
+
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = 0x30000100;
+
+	icache_enable();
+	dcache_enable();
+
+	return 0;
+}
+
+int board_late_init(void)
+{
+	unsigned char tmp;
+	char buf[32];
+
+	/* Initialize the Power Management Unit with a safe register set */
+	pcf50606_init();
+
+	/* obtain wake-up reason, save INT1 in environment */
+	tmp = pcf50606_reg_read(PCF50606_REG_INT1);
+	sprintf(buf, "0x%02x", tmp);
+	setenv("pcf50606_int1", buf);
+
+	if (tmp & PCF50606_INT1_ALARM) {
+		/* we've been woken up by RTC alarm or charger insert, boot */
+		neo1973_wakeup_cause = NEO1973_WAKEUP_ALARM;
+		goto continue_boot;
+	}
+	if (tmp & PCF50606_INT1_EXTONR) {
+		neo1973_wakeup_cause = NEO1973_WAKEUP_CHARGER;
+	}
+
+	if (tmp & PCF50606_INT1_ONKEYF) {
+		int seconds = 0;
+		neo1973_wakeup_cause = NEO1973_WAKEUP_POWER_KEY;
+		/* we've been woken up by a falling edge of the onkey */
+
+		/* we can't just setenv(bootdelay,-1) because that would
+		 * accidentially become permanent if the user does saveenv */
+		if (neo1973_911_key_pressed())
+			nobootdelay = 1;
+
+		while (1) {
+			u_int8_t int1, oocs;
+
+			oocs = pcf50606_reg_read(PCF50606_REG_OOCS);
+			if (oocs & PFC50606_OOCS_ONKEY)
+				break;
+
+			int1 = pcf50606_reg_read(PCF50606_REG_INT1);
+			if (int1 & PCF50606_INT1_SECOND)
+				seconds++;
+
+			if (seconds >= POWER_KEY_SECONDS)
+				goto continue_boot;
+		}
+		/* Power off if minimum number of seconds not reached */
+		neo1973_poweroff();
+	}
+
+	/* if there's no other reason, must be regular reset */
+	neo1973_wakeup_cause = NEO1973_WAKEUP_RESET;
+
+continue_boot:
+	jbt6k74_init();
+	jbt6k74_enter_state(JBT_STATE_NORMAL);
+	jbt6k74_display_onoff(1);
+
+	/* issue a short pulse with the vibrator */
+	neo1973_vibrator(1);
+	udelay(50000);
+	neo1973_vibrator(0);
+
+	/* switch on the backlight */
+	neo1973_backlight(1);
+
+#if defined(CONFIG_ARCH_GTA01B_v4)
+	{
+		/* check if sd card is inserted, and power-up if it is */
+		S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+		if (!(gpio->GPFDAT & (1 << 5)))
+			gpio->GPBDAT &= ~(1 << 2);
+	}
+#endif
+
+	return 0;
+}
+
+int dram_init (void)
+{
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+
+	return 0;
+}
+
+u_int32_t get_board_rev(void)
+{
+#if defined(CONFIG_ARCH_GTA01_v3)
+	return 0x00000130;
+#elif defined(CONFIG_ARCH_GTA01_v4)
+	return 0x00000140;
+#elif defined(CONFIG_ARCH_GTA01B_v2)
+	return 0x00000220;
+#elif defined(CONFIG_ARCH_GTA01B_v3)
+	return 0x00000230;
+#elif defined(CONFIG_ARCH_GTA01B_v4)
+	return 0x00000240;
+#endif
+}
+
+void neo1973_poweroff(void)
+{
+	serial_printf("poweroff\n");
+	pcf50606_reg_write(PCF50606_REG_OOCC1, PCF50606_OOCC1_GOSTDBY);
+	/* don't return to caller */
+	while (1) ;
+}
+
+void neo1973_backlight(int on)
+{
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+	if (on)
+		gpio->GPBDAT |= 0x01;
+	else
+		gpio->GPBDAT &= ~0x01;
+}
+
+void neo1973_vibrator(int on)
+{
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+	if (on)
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
+		gpio->GPGDAT |= (1 << 11);	/* GPG11 */
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
+		gpio->GPBDAT |= (1 << 10);	/* GPB10 */
+#elif defined(CONFIG_ARCH_GTA01B_v4)
+		gpio->GPBDAT |= (1 << 3);	/* GPB3 */
+#endif
+	else
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
+		gpio->GPGDAT &= ~(1 << 11);	/* GPG11 */
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
+		gpio->GPBDAT &= ~(1 << 10);	/* GPB10 */
+#elif defined(CONFIG_ARCH_GTA01B_v4)
+		gpio->GPBDAT &= ~(1 << 3);	/* GPB3 */
+#endif
+}
+
+/* switch serial port 0 multiplexer */
+void neo1973_gta01_serial0_gsm(int on)
+{
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+	S3C24X0_UART * const uart = S3C24X0_GetBase_UART(0);
+	int i;
+
+	if (on) {
+		for (i = 0; i < 3; i++) {
+			if (!strcmp(stdio_devices[i]->name, "serial") ||
+			    !strcmp(stdio_devices[i]->name, "s3ser0")) {
+				puts("ERROR: serial port busy, can't enable GSM!\n");
+				return;
+			}
+		}
+		puts("switching s3ser0 from console into GSM mode\n");
+		uart->UMCON |= 0x10;		/* Hardware flow control */
+		gpio->GPFDAT &= ~(1 << 2);	/* GPF2: nGSM_EN */
+	} else {
+		gpio->GPFDAT |= (1 << 2);	/* GPF2: nGSM_EN */
+		uart->UMCON &= ~0x10;		/* No Hardware flow control */
+		puts("switched s3ser0 from GSM mode back into console mode\n");
+	}
+}
+
+/* switch gsm power on/off */
+void neo1973_gsm(int on)
+{
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+	device_t *dev = search_device(DEV_FLAGS_INPUT, "s3ser0");
+	if (!dev) {
+		puts("can't find s3ser0 device ?!?\n");
+		return;
+	}
+
+	if (on) {
+		gpio->GPBDAT &= ~(1 << 6);	/* GPB6: MODEM_RST */
+		gpio->GPBDAT |= (1 << 7);	/* GPB7: MODEM_ON */
+	} else {
+		/* unfortunately switching the modem off is not that easy.
+		 * Ti's firmware is insisting on not switching off... */
+		gpio->GPBDAT &= ~(1 << 7);	/* GPB7: MODEM_ON */
+		//gpio->GPBDAT |= (1 << 6);	/* GPB6: MODEM_RST */
+		if (!(gpio->GPFDAT & (1 << 2)))
+			puts("Can't power modem off while serial console "
+			     "in use!\n");
+		else {
+			S3C24X0_UART * const uart = S3C24X0_GetBase_UART(0);
+			uart->UMCON |= 0x10;		/* Hardware flow control */
+			gpio->GPFDAT &= ~(1 << 2);	/* GPF2: nGSM_EN */
+			dev->puts("AT@POFF\r\n");
+			gpio->GPFDAT |= (1 << 2);	/* GPF2: nGSM_EN */
+			uart->UMCON &= ~0x10;		/* No Hardware flow control */
+		}
+	}
+}
+
+/* switch gps power on/off */
+void neo1973_gps(int on)
+{
+	printf("not implemented yet!\n");
+}
+
+int neo1973_911_key_pressed(void)
+{
+	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+	if (gpio->GPFDAT & (1 << 6))
+		return 0;
+	return 1;
+}
+
+static const char *chgstate_names[] = {
+	[PCF50606_MBCC1_CHGMOD_QUAL]		= "qualification",
+	[PCF50606_MBCC1_CHGMOD_PRE]		= "pre",
+	[PCF50606_MBCC1_CHGMOD_TRICKLE]		= "trickle",
+	[PCF50606_MBCC1_CHGMOD_FAST_CCCV]	= "fast_cccv",
+	[PCF50606_MBCC1_CHGMOD_FAST_NOCC]	= "fast_nocc",
+	[PCF50606_MBCC1_CHGMOD_FAST_NOCV]	= "fast_nocv",
+	[PCF50606_MBCC1_CHGMOD_FAST_SW]		= "fast_switch",
+	[PCF50606_MBCC1_CHGMOD_IDLE]		= "idle",
+};
+
+const char *neo1973_get_charge_status(void)
+{
+	u_int8_t mbcc1 = pcf50606_reg_read(PCF50606_REG_MBCC1);
+	u_int8_t chgmod = (mbcc1 & PCF50606_MBCC1_CHGMOD_MASK);
+	return chgstate_names[chgmod];
+}
+
+int neo1973_set_charge_mode(enum neo1973_charger_cmd cmd)
+{
+	switch (cmd) {
+	case NEO1973_CHGCMD_NONE:
+		break;
+	case NEO1973_CHGCMD_AUTOFAST:
+		pcf50606_reg_set_bit_mask(PCF50606_REG_MBCC1,
+					  PCF50606_MBCC1_AUTOFST,
+					  PCF50606_MBCC1_AUTOFST);
+		break;
+	case NEO1973_CHGCMD_NO_AUTOFAST:
+		pcf50606_reg_set_bit_mask(PCF50606_REG_MBCC1,
+					  PCF50606_MBCC1_AUTOFST, 0);
+		break;
+	case NEO1973_CHGCMD_OFF:
+		pcf50606_reg_set_bit_mask(PCF50606_REG_MBCC1,
+					  PCF50606_MBCC1_CHGMOD_MASK,
+					  PCF50606_MBCC1_CHGMOD_IDLE);
+		break;
+
+	case NEO1973_CHGCMD_FAST:
+	case NEO1973_CHGCMD_FASTER:
+		pcf50606_reg_set_bit_mask(PCF50606_REG_MBCC1,
+					  PCF50606_MBCC1_CHGMOD_MASK,
+					  PCF50606_MBCC1_CHGMOD_FAST_CCCV);
+		break;
+	}
+	return 0;
+}
+
+void neo1973_led(int led, int on)
+{
+	printf("No LED's in this Neo1973 hardware revision\n");
+}
+
+
Index: u-boot/board/neo1973/gta01/pcf50606.c
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/gta01/pcf50606.c
@@ -0,0 +1,100 @@
+
+#include <common.h>
+#include <pcf50606.h>
+
+/* initial register set for PCF50606 in Neo1973 devices */
+const u_int8_t pcf50606_initial_regs[__NUM_PCF50606_REGS] = {
+	[PCF50606_REG_OOCS] 	= 0x00,
+	/* gap */
+	[PCF50606_REG_INT1M]	= PCF50606_INT1_SECOND,
+	[PCF50606_REG_INT2M]	= 0x00,
+	[PCF50606_REG_INT3M]	= PCF50606_INT3_TSCPRES,
+	[PCF50606_REG_OOCC1] 	= PCF50606_OOCC1_RTCWAK |
+				  PCF50606_OOCC1_CHGWAK |
+				  PCF50606_OOCC1_EXTONWAK_HIGH,
+	[PCF50606_REG_OOCC2]	= PCF50606_OOCC2_ONKEYDB_14ms |
+				  PCF50606_OOCC2_EXTONDB_14ms,
+	/* gap */
+	[PCF50606_REG_PSSC]	= 0x00,
+	[PCF50606_REG_PWROKM]	= 0x00,
+	/* gap */
+#if defined(CONFIG_ARCH_GTA01B_v2)
+	[PCF50606_REG_DCDC1]	= 0x1e,	/* GL_3V3: off */
+#elif defined(CONFIG_ARCH_GTA01B_v3) || defined(CONFIG_ARCH_GTA01B_v4)
+	[PCF50606_REG_DCDC1]	= 0x18,	/* GL_1V5: off */
+#endif
+	[PCF50606_REG_DCDC2]	= 0x00,
+	[PCF50606_REG_DCDC3]	= 0x00,
+	[PCF50606_REG_DCDC4]	= 0x30, /* 1.25A */
+
+	[PCF50606_REG_DCDEC1]	= 0xe8, /* IO_3V3: on */
+	[PCF50606_REG_DCDEC2]	= 0x00,
+
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
+	[PCF50606_REG_DCUDC1]	= 0xe3, /* CORE_1V8: 1.8V */
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
+	[PCF50606_REG_DCUDC1]	= 0xe4, /* CORE_1V8: 2.1V */
+#elif defined(CONFIG_ARCH_GTA01B_v4)
+	[PCF50606_REG_DCUDC1]	= 0xc4, /* CORE_1V8: 2.1V if PWREN2 = HIGH */
+#endif
+	[PCF50606_REG_DCUDC2]	= 0x30, /* 1.25A current limit */
+
+#if defined(CONFIG_ARCH_GTA01_v3)
+	[PCF50606_REG_IOREGC]	= 0x13, /* VTCXO_2V8: off */
+#elif defined(CONFIG_ARCH_GTA01_v4) || defined(CONFIG_ARCH_GTA01B_v2) || \
+      defined(CONFIG_ARCH_GTA01B_v3) || defined(CONFIG_ARCH_GTA01B_v4)
+	//see internal bug 94 [PCF50606_REG_IOREGC]	= 0x18, /* CODEC_3V3: off */
+	[PCF50606_REG_IOREGC]	= 0xf8, /* CODEC_3V3: on */
+#endif
+
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
+	[PCF50606_REG_D1REGC1]	= 0x15, /* VRF_3V: off */
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3) || \
+      defined(CONFIG_ARCH_GTA01B_v4)
+	[PCF50606_REG_D1REGC1]	= 0x16, /* BT_3V15: off */
+#endif
+
+#if defined(CONFIG_ARCH_GTA01_v3)
+	[PCF50606_REG_D2REGC1]	= 0xf8, /* SD_3V3: on */
+#elif defined(CONFIG_ARCH_GTA01_v4) || defined(CONFIG_ARCH_GTA01B_v2) || \
+      defined(CONFIG_ARCH_GTA01B_v3) || defined(CONFIG_ARCH_GTA01B_v4)
+	[PCF50606_REG_D2REGC1]	= 0x10, /* GL_2V5: off */
+#endif
+
+#if defined(CONFIG_ARCH_GTA01_v3)
+	[PCF50606_REG_D3REGC1]	= 0x18, /* CODEC_3V3: off */
+#elif defined(CONFIG_ARCH_GTA01_v4)
+	[PCF50606_REG_D3REGC1]	= 0x13, /* VTXCO_2V8: off */
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
+	[PCF50606_REG_D3REGC1]	= 0x00, /* USER1: off */
+#elif defined(CONFIG_ARCH_GTA01B_v4)
+	[PCF50606_REG_D3REGC1]	= 0xec, /* STBY_1V8: 2.1V */
+#endif
+
+	[PCF50606_REG_LPREGC1]	= 0xf8, /* LCM_3V3: on */
+	[PCF50606_REG_LPREGC2]	= 0x00,
+
+	[PCF50606_REG_MBCC1]	= 0x01, /* CHGAPE */
+	[PCF50606_REG_MBCC2]	= 0x00,	/* unlimited charging */
+	[PCF50606_REG_MBCC3]	= 0x2a, /* 0.2*Ifast, 4.20V */
+	[PCF50606_REG_BBCC]	= 0x1f, /* 400uA */
+	[PCF50606_REG_ADCC1]	= 0x00,
+	[PCF50606_REG_ADCC2]	= 0x00,
+	/* gap */
+#if defined(CONFIG_ARCH_GTA01B_v4)
+	[PCF50606_REG_ACDC1]	= 0x86,	/* ACD thresh 1.6V, enabled */
+#else
+	[PCF50606_REG_ACDC1]	= 0x00,
+#endif
+	[PCF50606_REG_BVMC]	= PCF50606_BVMC_THRSHLD_3V3,
+	[PCF50606_REG_PWMC1]	= 0x00,
+	[PCF50606_REG_LEDC1]	= 0x00,
+	[PCF50606_REG_LEDC2]	= 0x00,
+	[PCF50606_REG_GPOC1]	= 0x00,
+	[PCF50606_REG_GPOC2]	= 0x00,
+	[PCF50606_REG_GPOC3]	= 0x00,
+	[PCF50606_REG_GPOC4]	= 0x00,
+	[PCF50606_REG_GPOC5]	= 0x00,
+};
+
+
Index: u-boot/board/neo1973/gta01/split_by_variant.sh
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/gta01/split_by_variant.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# ---------------------------------------------------------
+#  Set the core module defines according to Core Module
+# ---------------------------------------------------------
+# ---------------------------------------------------------
+# Set up the GTA01 type define
+# ---------------------------------------------------------
+
+CFGINC=${obj}include/config.h
+CFGTMP=${obj}board/neo1973/gta01/config.tmp
+
+mkdir -p ${obj}include
+if [ "$1" = "" ]
+then
+	echo "$0:: No parameters - using GTA01Bv3 config"
+	echo "#define CONFIG_ARCH_GTA01B_v3" > $CFGINC
+	echo "GTA01_BIG_RAM=y" > $CFGTMP
+else
+	case "$1" in
+	gta01v4_config)
+	echo "#define CONFIG_ARCH_GTA01_v4" > $CFGINC
+	echo "GTA01_BIG_RAM=n" > $CFGTMP
+	;;
+
+	gta01v3_config)
+	echo "#define CONFIG_ARCH_GTA01_v3" > $CFGINC
+	echo "GTA01_BIG_RAM=n" > $CFGTMP
+	;;
+
+	gta01bv2_config)
+	echo "#define CONFIG_ARCH_GTA01B_v2" > $CFGINC
+	echo "GTA01_BIG_RAM=y" > $CFGTMP
+	;;
+
+	gta01bv3_config)
+	echo "#define CONFIG_ARCH_GTA01B_v3" > $CFGINC
+	echo "GTA01_BIG_RAM=y" > $CFGTMP
+	;;
+
+	gta01bv4_config)
+	echo "#define CONFIG_ARCH_GTA01B_v4" > $CFGINC
+	echo "GTA01_BIG_RAM=y" > $CFGTMP
+	;;
+
+	*)
+	echo "$0:: Unrecognised config - using GTA01Bv4 config"
+	echo "#define CONFIG_ARCH_GTA01B_v4" > $CFGINC
+	echo "GTA01_BIG_RAM=y" > $CFGTMP
+	;;
+
+	esac
+
+fi
+# ---------------------------------------------------------
+# Complete the configuration
+# ---------------------------------------------------------
+$MKCONFIG -a neo1973_gta01 arm arm920t gta01 neo1973 s3c24x0
Index: u-boot/board/neo1973/gta01/u-boot.lds
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/gta01/u-boot.lds
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text      :
+	{
+	  cpu/arm920t/start.o	(.text)
+	  cpu/arm920t/s3c24x0/nand_read.o (.text)
+	  *(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(.rodata) }
+
+	. = ALIGN(4);
+	.data : { *(.data) }
+
+	. = ALIGN(4);
+	.got : { *(.got) }
+
+	. = .;
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss (NOLOAD) : { *(.bss) }
+	_end = .;
+}
Index: u-boot/include/configs/neo1973_gta01.h
===================================================================
--- /dev/null
+++ u-boot/include/configs/neo1973_gta01.h
@@ -0,0 +1,257 @@
+/*
+ * (C) Copyright 2006 OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ *
+ * Configuation settings for the FIC Neo1973 GTA01 Linux GSM phone
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#if defined(BUILD_FOR_RAM)
+/* If we want to start u-boot from inside RAM */
+#define CONFIG_SKIP_RELOCATE_UBOOT	1
+#define CONFIG_SKIP_LOWLEVEL_INIT	1
+#else
+/* we want to start u-boot directly from within NAND flash */
+#define CONFIG_S3C2410_NAND_BOOT	1
+#define CONFIG_S3C2410_NAND_SKIP_BAD	1
+#endif
+
+#define CFG_UBOOT_SIZE		0x40000 /* size of u-boot, for NAND loading */
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_ARM920T		1	/* This is an ARM920T Core	*/
+#define	CONFIG_S3C2410		1	/* in a SAMSUNG S3C2410 SoC     */
+#define CONFIG_SMDK2410		1	/* on a SAMSUNG SMDK2410 Board  */
+
+/* input clock of PLL */
+#define CONFIG_SYS_CLK_FREQ	12000000/* the GTA01 has 12MHz input clock */
+
+
+#define USE_920T_MMU		1
+#define CONFIG_USE_IRQ		1
+
+/*
+ * Size of malloc() pool
+ */
+#define CFG_MALLOC_LEN		(CFG_ENV_SIZE + 128*1024)
+#define CFG_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
+
+/*
+ * Hardware drivers
+ */
+
+/*
+ * select serial console configuration
+ */
+#define CONFIG_SERIAL1          1	/* we use SERIAL 1 on GTA01 */
+#define CONFIG_SERIAL_MULTI
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_BAUDRATE		115200
+
+/***********************************************************
+ * Command definition
+ ***********************************************************/
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_LOADS
+#define CONFIG_CMD_LOADB
+#define CONFIG_CMD_IMI
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_BOOTD
+#define CONFIG_CMD_CONSOLE
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_RUN
+#define CONFIG_CMD_ECHO
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_IMMAP
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_AUTOSCRIPT
+#define CONFIG_CMD_BSP
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_MISC
+#define CONFIG_CMD_DIAG
+#define CONFIG_CMD_SAVES
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_PORTIO
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_TERMINAL
+
+#define CONFIG_BOOTDELAY	3
+#define CONFIG_BOOTARGS    	"rootfstype=jffs2 root=/dev/mtdblock4 console=ttySAC0,115200 console=tty0 loglevel=8"
+#define CONFIG_BOOTCOMMAND	"nand read.e 0x32000000 0x34000 0x200000; bootm 0x32000000"
+
+#define CONFIG_DOS_PARTITION	1
+
+#if defined(CONFIG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE	115200		/* speed to run kgdb serial port */
+/* what's this ? it's not used anywhere */
+#define CONFIG_KGDB_SER_INDEX	1		/* which serial port to use */
+#endif
+
+/*
+ * Miscellaneous configurable options
+ */
+#define	CFG_LONGHELP				/* undef to save memory		*/
+#if defined(CONFIG_ARCH_GTA01_v3)
+#define	CFG_PROMPT		"GTA01v3 # "	/* Monitor Command Prompt	*/
+#elif defined(CONFIG_ARCH_GTA01_v4)
+#define	CFG_PROMPT		"GTA01v4 # "	/* Monitor Command Prompt	*/
+#elif defined(CONFIG_ARCH_GTA01B_v2)
+#define	CFG_PROMPT		"GTA01Bv2 # "	/* Monitor Command Prompt	*/
+#elif defined(CONFIG_ARCH_GTA01B_v3)
+#define	CFG_PROMPT		"GTA01Bv3 # "	/* Monitor Command Prompt	*/
+#elif defined(CONFIG_ARCH_GTA01B_v4)
+#define	CFG_PROMPT		"GTA01Bv4 # "	/* Monitor Command Prompt	*/
+#endif
+#define	CFG_CBSIZE		256		/* Console I/O Buffer Size	*/
+#define	CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define	CFG_MAXARGS		16		/* max number of command args	*/
+#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size	*/
+
+#define CFG_MEMTEST_START	0x30000000	/* memtest works on	*/
+#define CFG_MEMTEST_END		0x33F00000	/* 63 MB in DRAM	*/
+
+#undef  CFG_CLKS_IN_HZ		/* everything, incl board info, in Hz */
+
+#define	CFG_LOAD_ADDR		0x33000000	/* default load address	*/
+
+/* the PWM TImer 4 uses a counter of 15625 for 10 ms, so we need */
+/* it to wrap 100 times (total 1562500) to get 1 sec. */
+#define	CFG_HZ			1562500
+
+/* valid baudrates */
+#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE	(128*1024)	/* regular stack */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ	(4*1024)	/* IRQ stack */
+#define CONFIG_STACKSIZE_FIQ	(4*1024)	/* FIQ stack */
+#endif
+
+#if 0
+#define CONFIG_USB_OHCI		1
+#endif
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS	1	   /* we have 1 bank of DRAM */
+#define PHYS_SDRAM_1		0x30000000 /* SDRAM Bank #1 */
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
+#define PHYS_SDRAM_1_SIZE	0x04000000 /* 64 MB */
+#elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3) || \
+      defined(CONFIG_ARCH_GTA01B_v4)
+#define PHYS_SDRAM_1_SIZE	0x08000000 /* 128 MB */
+#else
+#error Please define GTA01 variant
+#endif
+#define PHYS_SDRAM_RES_SIZE	0x00200000 /* 2 MB for frame buffer */
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+
+/* No NOR flash in this device */
+#define CFG_NO_FLASH		1
+
+#define	CFG_ENV_IS_IN_NAND	1
+#define CFG_ENV_SIZE		0x4000		/* 16k Total Size of Environment Sector */
+#define CFG_ENV_OFFSET_OOB    1               /* Location of ENV stored in block 0 OOB */
+
+#define NAND_MAX_CHIPS		1
+#define CFG_NAND_BASE		0x4e000000
+#define CFG_MAX_NAND_DEVICE	1
+
+#define CONFIG_MMC		1
+#define CFG_MMC_BASE		0xff000000
+
+/* EXT2 driver */
+#define CONFIG_EXT2		1
+
+#define CONFIG_FAT		1
+#define CONFIG_SUPPORT_VFAT
+
+#if 0
+/* JFFS2 driver */
+#define CONFIG_JFFS2_CMDLINE	1
+#define CONFIG_JFFS2_NAND	1
+#define CONFIG_JFFS2_NAND_DEV	0
+#define CONFIG_JFFS2_NAND_OFF	0x634000
+#define CONFIG_JFFS2_NAND_SIZE	0x39cc000
+#endif
+
+/* ATAG configuration */
+#define CONFIG_INITRD_TAG		1
+#define CONFIG_SETUP_MEMORY_TAGS	1
+#define CONFIG_CMDLINE_TAG		1
+#define CONFIG_REVISION_TAG		1
+#if 0
+#define CONFIG_SERIAL_TAG		1
+#endif
+
+#define CONFIG_DRIVER_S3C24X0_I2C	1
+#define CONFIG_HARD_I2C			1
+#define CFG_I2C_SPEED			400000	/* 400kHz according to PCF50606 data sheet */
+#define CFG_I2C_SLAVE			0x7f
+
+/* we have a board_late_init() function */
+#define BOARD_LATE_INIT			1
+
+#if 1
+#define CONFIG_VIDEO
+#define CONFIG_VIDEO_S3C2410
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+
+#define VIDEO_FB_16BPP_PIXEL_SWAP
+
+#define VIDEO_KBD_INIT_FCT	0
+#define VIDEO_TSTC_FCT		serial_tstc
+#define VIDEO_GETC_FCT		serial_getc
+
+#define LCD_VIDEO_ADDR		0x33d00000
+#endif
+
+#define CONFIG_S3C2410_NAND_BBT                1
+#define CONFIG_S3C2410_NAND_HWECC              1
+
+#define CONFIG_DRIVER_PCF50606		1
+#define CONFIG_RTC_PCF50606		1
+
+#endif	/* __CONFIG_H */
Index: u-boot/board/neo1973/common/neo1973.h
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/common/neo1973.h
@@ -0,0 +1,35 @@
+#ifndef _NEO1973_H
+#define _NEO1973_H
+
+enum wakeup_reason {
+	NEO1973_WAKEUP_NONE,
+	NEO1973_WAKEUP_RESET,
+	NEO1973_WAKEUP_POWER_KEY,
+	NEO1973_WAKEUP_CHARGER,
+	NEO1973_WAKEUP_ALARM,
+};
+
+enum neo1973_charger_cmd {
+	NEO1973_CHGCMD_NONE,
+	NEO1973_CHGCMD_AUTOFAST,
+	NEO1973_CHGCMD_NO_AUTOFAST,
+	NEO1973_CHGCMD_OFF,
+	NEO1973_CHGCMD_FAST,
+	NEO1973_CHGCMD_FASTER,
+};
+
+extern unsigned int neo1973_wakeup_cause;
+
+void neo1973_poweroff(void);
+void neo1973_backlight(int on);
+void neo1973_vibrator(int on);
+void neo1973_gsm(int on);
+void neo1973_gps(int on);
+void neo1973_led(int led, int on);
+
+int neo1973_911_key_pressed(void);
+
+const char *neo1973_get_charge_status(void);
+int neo1973_set_charge_mode(enum neo1973_charger_cmd cmd);
+
+#endif
Index: u-boot/common/cmd_terminal.c
===================================================================
--- u-boot.orig/common/cmd_terminal.c
+++ u-boot/common/cmd_terminal.c
@@ -50,7 +50,15 @@
 	if (!dev)
 		return -1;
 
-	serial_reinit_all();
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4) || \
+    defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3) || \
+    defined(CONFIG_ARCH_GTA01B_v4)
+	if (!strcmp(dev->name, "serial") ||
+	    !strcmp(dev->name, "s3ser0"))
+		neo1973_gta01_serial0_gsm(1);
+#endif
+
+	//serial_reinit_all();
 	printf("Entering terminal mode for port %s\n", dev->name);
 	puts("Use '~.' to leave the terminal and get back to u-boot\n");
 
@@ -87,6 +95,14 @@
 			putc(c);
 		}
 	}
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4) || \
+    defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3) || \
+    defined(CONFIG_ARCH_GTA01B_v4)
+	if (!strcmp(dev->name, "serial") ||
+	    !strcmp(dev->name, "s3ser0"))
+		neo1973_gta01_serial0_gsm(0);
+#endif
+
 	return 0;
 }
 
Index: u-boot/drivers/misc/Makefile
===================================================================
--- u-boot.orig/drivers/misc/Makefile
+++ u-boot/drivers/misc/Makefile
@@ -27,6 +27,7 @@
 
 COBJS-y += ali512x.o
 COBJS-y += ns87308.o
+COBJS-y += pcf50606.o
 COBJS-y += status_led.o
 COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
 
Index: u-boot/drivers/misc/pcf50606.c
===================================================================
--- /dev/null
+++ u-boot/drivers/misc/pcf50606.c
@@ -0,0 +1,161 @@
+
+#include <common.h>
+
+#ifdef CONFIG_DRIVER_PCF50606
+
+#include <i2c.h>
+#include <pcf50606.h>
+#include <asm/atomic.h>
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define PCF50606_I2C_ADDR		0x08
+
+void __pcf50606_reg_write(u_int8_t reg, u_int8_t val)
+{
+	i2c_write(PCF50606_I2C_ADDR, reg, 1, &val, 1);
+}
+
+u_int8_t __pcf50606_reg_read(u_int8_t reg)
+{
+	u_int8_t tmp;
+	i2c_read(PCF50606_I2C_ADDR, reg, 1, &tmp, 1);
+	return tmp;
+}
+
+void pcf50606_reg_write(u_int8_t reg, u_int8_t val)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	__pcf50606_reg_write(reg, val);
+	local_irq_restore(flags);
+}
+
+u_int8_t pcf50606_reg_read(u_int8_t reg)
+{
+	unsigned long flags;
+	u_int8_t tmp;
+
+	local_irq_save(flags);
+	tmp = __pcf50606_reg_read(reg);
+	local_irq_restore(flags);
+
+	return tmp;
+}
+
+void pcf50606_reg_set_bit_mask(u_int8_t reg, u_int8_t mask, u_int8_t val)
+{
+	unsigned long flags;
+	u_int8_t tmp;
+
+	local_irq_save(flags);
+	tmp = __pcf50606_reg_read(reg);
+	__pcf50606_reg_write(reg, (val & mask) | (tmp & ~mask));
+	local_irq_restore(flags);
+}
+
+void pcf50606_reg_clear_bits(u_int8_t reg, u_int8_t bits)
+{
+	unsigned long flags;
+	u_int8_t tmp;
+
+	local_irq_save(flags);
+	tmp = pcf50606_reg_read(reg);
+	pcf50606_reg_write(reg, (tmp & ~bits));
+	local_irq_restore(flags);
+}
+
+static const u_int8_t regs_valid[] = {
+	PCF50606_REG_OOCS, PCF50606_REG_INT1M, PCF50606_REG_INT2M,
+	PCF50606_REG_INT3M, PCF50606_REG_OOCC1, PCF50606_REG_OOCC2,
+	PCF50606_REG_PSSC, PCF50606_REG_PWROKM, PCF50606_REG_DCDC1,
+	PCF50606_REG_DCDC2, PCF50606_REG_DCDC3, PCF50606_REG_DCDC4,
+	PCF50606_REG_DCDEC1, PCF50606_REG_DCDEC2, PCF50606_REG_DCUDC1,
+	PCF50606_REG_DCUDC2, PCF50606_REG_IOREGC, PCF50606_REG_D1REGC1,
+	PCF50606_REG_D2REGC1, PCF50606_REG_D3REGC1, PCF50606_REG_LPREGC1,
+	PCF50606_REG_LPREGC2, PCF50606_REG_MBCC1, PCF50606_REG_MBCC2,
+	PCF50606_REG_MBCC3, PCF50606_REG_BBCC, PCF50606_REG_ADCC1,
+	PCF50606_REG_ADCC2, PCF50606_REG_ACDC1, PCF50606_REG_BVMC,
+	PCF50606_REG_PWMC1, PCF50606_REG_LEDC1, PCF50606_REG_LEDC2,
+	PCF50606_REG_GPOC1, PCF50606_REG_GPOC2, PCF50606_REG_GPOC3,
+	PCF50606_REG_GPOC4, PCF50606_REG_GPOC5,
+};
+
+
+/* initialize PCF50606 register set */
+void pcf50606_init(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < ARRAY_SIZE(regs_valid); i++) {
+		__pcf50606_reg_write(regs_valid[i],
+				     pcf50606_initial_regs[regs_valid[i]]);
+	}
+	local_irq_restore(flags);
+}
+
+void pcf50606_charge_autofast(int on)
+{
+	if (on) {
+		printf("Enabling automatic fast charge\n");
+		pcf50606_reg_set_bit_mask(PCF50606_REG_MBCC1,
+					  PCF50606_MBCC1_AUTOFST,
+					  PCF50606_MBCC1_AUTOFST);
+	} else {
+		printf("Disabling fast charge\n");
+		pcf50606_reg_write(PCF50606_REG_MBCC1, 0x00);
+	}
+}
+
+#if defined(CONFIG_RTC_PCF50606) && defined(CONFIG_CMD_DATE)
+
+#include <rtc.h>
+
+static unsigned bcd2bin (uchar n)
+{
+	return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
+}
+
+static unsigned char bin2bcd (unsigned int n)
+{
+	return (((n / 10) << 4) | (n % 10));
+}
+
+
+void rtc_get(struct rtc_time *tmp)
+{
+	tmp->tm_sec = bcd2bin(pcf50606_reg_read(PCF50606_REG_RTCSC));
+	tmp->tm_min = bcd2bin(pcf50606_reg_read(PCF50606_REG_RTCMN));
+	tmp->tm_hour = bcd2bin(pcf50606_reg_read(PCF50606_REG_RTCHR));
+	tmp->tm_wday = bcd2bin(pcf50606_reg_read(PCF50606_REG_RTCWD));
+	tmp->tm_mday = bcd2bin(pcf50606_reg_read(PCF50606_REG_RTCDT));
+	tmp->tm_mon = bcd2bin(pcf50606_reg_read(PCF50606_REG_RTCMT));
+	tmp->tm_year = bcd2bin(pcf50606_reg_read(PCF50606_REG_RTCYR));
+	if (tmp->tm_year < 70)
+		tmp->tm_year += 2000;
+	else
+		tmp->tm_year += 1900;
+	tmp->tm_yday = 0;
+	tmp->tm_isdst = 0;
+}
+
+void rtc_set(struct rtc_time *tmp)
+{
+	pcf50606_reg_write(PCF50606_REG_RTCSC, bin2bcd(tmp->tm_sec));
+	pcf50606_reg_write(PCF50606_REG_RTCMN, bin2bcd(tmp->tm_min));
+	pcf50606_reg_write(PCF50606_REG_RTCHR, bin2bcd(tmp->tm_hour));
+	pcf50606_reg_write(PCF50606_REG_RTCWD, bin2bcd(tmp->tm_wday));
+	pcf50606_reg_write(PCF50606_REG_RTCDT, bin2bcd(tmp->tm_mday));
+	pcf50606_reg_write(PCF50606_REG_RTCMT, bin2bcd(tmp->tm_mon));
+	pcf50606_reg_write(PCF50606_REG_RTCYR, bin2bcd(tmp->tm_year % 100));
+}
+
+void rtc_reset(void)
+{
+	/* FIXME */
+}
+#endif /* CONFIG_RTC_PCF50606 && CONFIG_CMD_DATE */
+
+#endif /* CONFIG DRIVER_PCF50606 */
Index: u-boot/board/neo1973/common/gsmver.c
===================================================================
--- /dev/null
+++ u-boot/board/neo1973/common/gsmver.c
@@ -0,0 +1,80 @@
+/*
+ * (C) Copyright 2007 OpenMoko, Inc.
+ * Written by Jim Huang <jserv@openmoko.org>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <devices.h>
+
+#define GSM_UART_DEVICE  "s3ser0"
+
+int neo1973_gsmver()
+{
+	int i;
+	device_t *dev = NULL;
+	int string_end_count = 0;
+
+	/* Scan for selected output/input device */
+	for (i = 1; i <= ListNumItems (devlist); i++) {
+		device_t *tmp = ListGetPtrToItem (devlist, i);
+		if (!strcmp(tmp->name, GSM_UART_DEVICE)) {
+			dev = tmp;
+			break;
+		}
+	}
+	if (!dev)
+		return -1;
+
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4) || \
+	defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3) || \
+	defined(CONFIG_ARCH_GTA01B_v4)
+	neo1973_gta01_serial0_gsm(1);
+#endif
+
+	/* Query GSM firmware information by AT command */
+	dev->puts("AT+CGMR\r\n");
+	puts("GSM firmware version: ");
+
+	/* read from serial and display version information */
+	while (1) {
+		if (dev->tstc()) {
+			i = dev->getc();
+			putc(i);
+			/* FIXME: should we just dump straightforward
+			 * version string such as "moko1" or "moko4"?
+			 */
+			if (i == '\n' || i == '\r')
+				continue;
+		}
+	}
+	putc('\n');
+
+#if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4) || \
+    defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3) || \
+    defined(CONFIG_ARCH_GTA01B_v4)
+	neo1973_gta01_serial0_gsm(0);
+#endif
+
+	return 0;
+}
