diff mbox

[U-Boot,v2,7/7] add support for palm treo 680 board

Message ID 1365641128-15812-8-git-send-email-mikedunn@newsguy.com
State Superseded
Delegated to: Marek Vasut
Headers show

Commit Message

Mike Dunn April 11, 2013, 12:45 a.m. UTC
A quick overview of u-boot implementation on the treo 680...

The treo 680 has a Diskonchip G4 nand flash chip.  This device has a 2k region
that maps to the system bus at the reset vector in a NOR-like fashion so that it
can be used as the boot device.  The phone is shipped with this 2k region
configured as write-protected (can't be modified) and programmed with an initial
program loader (IPL).  At power-up, this IPL loads the contents of two flash
blocks to SDRAM and jumps to it.  The capacity of the two blocks is not large
enough to hold all of u-boot, so a u-boot SPL is used.  To conserve flash space,
these two blocks and the necessary number of subsequent blocks are programmed
with a concatenated spl + u-boot image.  That way, the IPL will also load a
portion of u-boot proper, and when the spl runs, it relocates the portion of
u-boot that the IPL has already loaded, and then resumes loading the remaining
part of u-boot before jumping to it.

The default_environment is used (CONFIG_ENV_IS_NOWHERE) because I didn't think
that having a writable environment was worth the cost of a flash block, although
adding it would be straightforward.  I abuse the CONFIG_EXTRA_ENV_SETTINGS
option to specify the usbtty for the console (CONFIG_SYS_CONSOLE_IS_IN_ENV).

Support for the LCD is included, but currently it is only useful for displaying
the u-boot splash screen.  But if u-boot is built without the usbtty console, it
does display the auto-boot progress nicely.

Signed-off-by: Mike Dunn <mikedunn@newsguy.com>
---
 CREDITS                               |    4 +
 MAINTAINERS                           |    3 +
 board/palmtreo680/Makefile            |   34 ++
 board/palmtreo680/palmtreo680.c       |  179 +++++++++++
 board/palmtreo680/palmtreo680_spl.lds |   51 +++
 boards.cfg                            |    1 +
 doc/README.palmtreo680                |  570 +++++++++++++++++++++++++++++++++
 include/configs/palmtreo680.h         |  295 +++++++++++++++++
 tools/palmtreo680/flash_u-boot.c      |  177 ++++++++++
 9 files changed, 1314 insertions(+), 0 deletions(-)
 create mode 100644 board/palmtreo680/Makefile
 create mode 100644 board/palmtreo680/palmtreo680.c
 create mode 100644 board/palmtreo680/palmtreo680_spl.lds
 create mode 100644 doc/README.palmtreo680
 create mode 100644 include/configs/palmtreo680.h
 create mode 100644 tools/palmtreo680/flash_u-boot.c

Comments

Marek Vasut April 11, 2013, 7:20 p.m. UTC | #1
Dear Mike Dunn,

> A quick overview of u-boot implementation on the treo 680...
> 
> The treo 680 has a Diskonchip G4 nand flash chip.  This device has a 2k
> region that maps to the system bus at the reset vector in a NOR-like
> fashion so that it can be used as the boot device.  The phone is shipped
> with this 2k region configured as write-protected (can't be modified) and
> programmed with an initial program loader (IPL).  At power-up, this IPL
> loads the contents of two flash blocks to SDRAM and jumps to it.  The
> capacity of the two blocks is not large enough to hold all of u-boot, so a
> u-boot SPL is used.  To conserve flash space, these two blocks and the
> necessary number of subsequent blocks are programmed with a concatenated
> spl + u-boot image.  That way, the IPL will also load a portion of u-boot
> proper, and when the spl runs, it relocates the portion of u-boot that the
> IPL has already loaded, and then resumes loading the remaining part of
> u-boot before jumping to it.
> 
> The default_environment is used (CONFIG_ENV_IS_NOWHERE) because I didn't
> think that having a writable environment was worth the cost of a flash
> block, although adding it would be straightforward.  I abuse the
> CONFIG_EXTRA_ENV_SETTINGS option to specify the usbtty for the console
> (CONFIG_SYS_CONSOLE_IS_IN_ENV).
> 
> Support for the LCD is included, but currently it is only useful for
> displaying the u-boot splash screen.  But if u-boot is built without the
> usbtty console, it does display the auto-boot progress nicely.
> 
> Signed-off-by: Mike Dunn <mikedunn@newsguy.com>

I think the tool shall really go as a separate patch. Besides, can the tool not 
be implemented as a part of u-boot's mkimage infrastructure?
Mike Dunn April 12, 2013, 12:51 p.m. UTC | #2
On 04/11/2013 12:20 PM, Marek Vasut wrote:
> Dear Mike Dunn,
> 
>> A quick overview of u-boot implementation on the treo 680...
>>
>> The treo 680 has a Diskonchip G4 nand flash chip.  This device has a 2k
>> region that maps to the system bus at the reset vector in a NOR-like
>> fashion so that it can be used as the boot device.  The phone is shipped
>> with this 2k region configured as write-protected (can't be modified) and
>> programmed with an initial program loader (IPL).  At power-up, this IPL
>> loads the contents of two flash blocks to SDRAM and jumps to it.  The
>> capacity of the two blocks is not large enough to hold all of u-boot, so a
>> u-boot SPL is used.  To conserve flash space, these two blocks and the
>> necessary number of subsequent blocks are programmed with a concatenated
>> spl + u-boot image.  That way, the IPL will also load a portion of u-boot
>> proper, and when the spl runs, it relocates the portion of u-boot that the
>> IPL has already loaded, and then resumes loading the remaining part of
>> u-boot before jumping to it.
>>
>> The default_environment is used (CONFIG_ENV_IS_NOWHERE) because I didn't
>> think that having a writable environment was worth the cost of a flash
>> block, although adding it would be straightforward.  I abuse the
>> CONFIG_EXTRA_ENV_SETTINGS option to specify the usbtty for the console
>> (CONFIG_SYS_CONSOLE_IS_IN_ENV).
>>
>> Support for the LCD is included, but currently it is only useful for
>> displaying the u-boot splash screen.  But if u-boot is built without the
>> usbtty console, it does display the auto-boot progress nicely.
>>
>> Signed-off-by: Mike Dunn <mikedunn@newsguy.com>
> 
> I think the tool shall really go as a separate patch. Besides, can the tool not 
> be implemented as a part of u-boot's mkimage infrastructure?


OK, I can make the flash_u-boot utility (which writes u-boot to the flash boot
blocks) a separate patch.

As for making it part of mkimage...  I didn't really consider that because based
on my (limited) knowledge, I figured they are unrelated.  As I understand it,
mkimage creates an OS image file that u-boot can parse and load.  flash_u-boot
is a utility that performs the task of writing u-boot itself to flash.

I figured that mine was a special case, since u-boot must be written in a
special format (redundant pages) and in a special manner (alternate 4k regions
skipped), with the flash device in a special mode, and so it can not be done in
the normal manner; e.g., 'nandwrite' from mtd-utils, or its u-boot 'nand write'
equivalent, even if you first ran the u-boot image through a separate utility
that simply converted the format of the image.

Hope that makes sense.  Any insight appreciated.  I'll take a look at what's in
the tools directory.

Thanks Marek,
Mike
Marek Vasut April 12, 2013, 5:26 p.m. UTC | #3
Dear Mike Dunn,

> On 04/11/2013 12:20 PM, Marek Vasut wrote:
> > Dear Mike Dunn,
> > 
> >> A quick overview of u-boot implementation on the treo 680...
> >> 
> >> The treo 680 has a Diskonchip G4 nand flash chip.  This device has a 2k
> >> region that maps to the system bus at the reset vector in a NOR-like
> >> fashion so that it can be used as the boot device.  The phone is shipped
> >> with this 2k region configured as write-protected (can't be modified)
> >> and programmed with an initial program loader (IPL).  At power-up, this
> >> IPL loads the contents of two flash blocks to SDRAM and jumps to it. 
> >> The capacity of the two blocks is not large enough to hold all of
> >> u-boot, so a u-boot SPL is used.  To conserve flash space, these two
> >> blocks and the necessary number of subsequent blocks are programmed
> >> with a concatenated spl + u-boot image.  That way, the IPL will also
> >> load a portion of u-boot proper, and when the spl runs, it relocates
> >> the portion of u-boot that the IPL has already loaded, and then resumes
> >> loading the remaining part of u-boot before jumping to it.
> >> 
> >> The default_environment is used (CONFIG_ENV_IS_NOWHERE) because I didn't
> >> think that having a writable environment was worth the cost of a flash
> >> block, although adding it would be straightforward.  I abuse the
> >> CONFIG_EXTRA_ENV_SETTINGS option to specify the usbtty for the console
> >> (CONFIG_SYS_CONSOLE_IS_IN_ENV).
> >> 
> >> Support for the LCD is included, but currently it is only useful for
> >> displaying the u-boot splash screen.  But if u-boot is built without the
> >> usbtty console, it does display the auto-boot progress nicely.
> >> 
> >> Signed-off-by: Mike Dunn <mikedunn@newsguy.com>
> > 
> > I think the tool shall really go as a separate patch. Besides, can the
> > tool not be implemented as a part of u-boot's mkimage infrastructure?
> 
> OK, I can make the flash_u-boot utility (which writes u-boot to the flash
> boot blocks) a separate patch.
> 
> As for making it part of mkimage...  I didn't really consider that because
> based on my (limited) knowledge, I figured they are unrelated.  As I
> understand it, mkimage creates an OS image file that u-boot can parse and
> load.  flash_u-boot is a utility that performs the task of writing u-boot
> itself to flash.

It can create an bootloader image that can be written to flash using standard 
mtd utilities. Does this not cut it for you? Why do you need a separate flasher, 
because the G4 is special ?

> I figured that mine was a special case, since u-boot must be written in a
> special format (redundant pages) and in a special manner (alternate 4k
> regions skipped), with the flash device in a special mode, and so it can
> not be done in the normal manner; e.g., 'nandwrite' from mtd-utils, or its
> u-boot 'nand write' equivalent, even if you first ran the u-boot image
> through a separate utility that simply converted the format of the image.
> 
> Hope that makes sense.  Any insight appreciated.  I'll take a look at
> what's in the tools directory.

I see ... so the G4 is such a horrible beast :( OK

Best regards,
Marek Vasut
diff mbox

Patch

diff --git a/CREDITS b/CREDITS
index 7c1458f..3b657e9 100644
--- a/CREDITS
+++ b/CREDITS
@@ -124,6 +124,10 @@  N: James F. Dougherty
 E: jfd@GigabitNetworks.COM
 D: Port to the MOUSSE board
 
+N: Mike Dunn
+E: mikedunn@newsguy.com
+D: Palmtreo680 board, docg4 nand flash driver
+
 N: Dave Ellis
 E: DGE@sixnetio.com
 D: EEPROM Speedup, SXNI855T port
diff --git a/MAINTAINERS b/MAINTAINERS
index 1614b91..db62af1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -650,6 +650,9 @@  Wolfgang Denk <wd@denx.de>
 	imx27lite	i.MX27
 	qong		i.MX31
 
+Mike Dunn <mikedunn@newsguy.com>
+	palmtreo680	pxa270
+
 Kristoffer Ericson <kristoffer.ericson@gmail.com>
 
 	jornada	SA1110
diff --git a/board/palmtreo680/Makefile b/board/palmtreo680/Makefile
new file mode 100644
index 0000000..34ffb99
--- /dev/null
+++ b/board/palmtreo680/Makefile
@@ -0,0 +1,34 @@ 
+#
+# Palm Treo680 Support
+#
+# Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
+#
+# This file is released under the terms of GPL v2 and any later version.
+# See the file COPYING in the root directory of the source tree for details.
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= palmtreo680.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+clean:
+	rm -f $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/palmtreo680/palmtreo680.c b/board/palmtreo680/palmtreo680.c
new file mode 100644
index 0000000..c23c570
--- /dev/null
+++ b/board/palmtreo680/palmtreo680.c
@@ -0,0 +1,179 @@ 
+/*
+ * Palm Treo 680 Support
+ *
+ * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <serial.h>
+#include <nand.h>
+#include <malloc.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch-pxa/pxa.h>
+#include <asm/arch-pxa/regs-mmc.h>
+#include <asm/io.h>
+#include <asm/global_data.h>
+#include <u-boot/crc.h>
+#include <linux/mtd/docg4.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct nand_chip docg4_nand_chip;
+
+int board_init(void)
+{
+	/* We have RAM, disable cache */
+	dcache_disable();
+	icache_disable();
+
+	gd->bd->bi_arch_number = MACH_TYPE_TREO680;
+	gd->bd->bi_boot_params = 0xa0000100;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	/* IPL initializes SDRAM (we're already running from it) */
+	gd->ram_size = PHYS_SDRAM_1_SIZE;
+	return 0;
+}
+
+#ifdef CONFIG_LCD
+void lcd_enable(void)
+{
+	/*
+	 * Undo the L_BIAS / gpio77 pin configuration performed by the pxa lcd
+	 * driver code.  We need it as an output gpio.
+	 */
+	writel((readl(GAFR2_L) & ~(0xc << 24)), GAFR2_L);
+
+	/* power-up and enable the lcd */
+	writel(0x00400000, GPSR(86)); /* enable; drive high */
+	writel(0x00002000, GPSR(77)); /* power; drive high */
+	writel(0x02000000, GPCR(25)); /* enable_n; drive low */
+
+	/* turn on LCD backlight and configure PWM for reasonable brightness */
+	writel(0x00, PWM_CTRL0);
+	writel(0x1b1, PWM_PERVAL0);
+	writel(0xfd, PWM_PWDUTY0);
+	writel(0x00000040, GPSR(38)); /*  backlight power on */
+}
+#endif
+
+#ifdef CONFIG_MMC
+int board_mmc_init(bd_t *bis)
+{
+	writel(0x00000400, GPSR(42)); /* power on */
+	return pxa_mmc_register(0);
+}
+#endif
+
+void board_nand_init(void)
+{
+	/* we have one 128M diskonchip G4  */
+
+	struct mtd_info *mtd = &nand_info[0];
+	struct nand_chip *nand = &docg4_nand_chip;
+	if (docg4_nand_init(mtd, nand, 0))
+		hang();
+}
+
+#ifdef CONFIG_SPL_BUILD
+void *memcpy(void *dest, const void *src, size_t count)
+{
+	unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src;
+	char *d8, *s8;
+
+	if (src == dest)
+		return dest;
+
+	/* while all data is aligned (common case), copy a word at a time */
+	if ((((ulong)dest | (ulong)src) & (sizeof(*dl) - 1)) == 0) {
+		while (count >= sizeof(*dl)) {
+			*dl++ = *sl++;
+			count -= sizeof(*dl);
+		}
+	}
+	/* copy the reset one byte at a time */
+	d8 = (char *)dl;
+	s8 = (char *)sl;
+	while (count--)
+		*d8++ = *s8++;
+
+	return dest;
+}
+
+
+void nand_boot(void)
+{
+	__attribute__((noreturn)) void (*uboot)(void);
+
+	extern const void *_start, *_end;   /* boundaries of spl in memory */
+
+	/* size of spl; ipl loads this, and then a portion of u-boot */
+	const size_t spl_image_size = ((size_t)&_end - (size_t)&_start);
+
+	/* the flash offset of the blocks that are loaded by the spl */
+	const uint32_t spl_load_offset = CONFIG_SYS_NAND_U_BOOT_OFFS +
+		DOCG4_IPL_LOAD_BLOCK_COUNT * DOCG4_BLOCK_SIZE;
+
+	/* total number of bytes loaded by IPL */
+	const size_t ipl_load_size =
+		DOCG4_IPL_LOAD_BLOCK_COUNT * DOCG4_BLOCK_CAPACITY_SPL;
+
+	/* number of bytes of u-boot proper that was loaded by the IPL */
+	const size_t ipl_uboot_load_size = ipl_load_size - spl_image_size;
+
+	/* number of remaining bytes of u-boot that the SPL must load */
+	const size_t spl_load_size =
+		CONFIG_SYS_NAND_U_BOOT_SIZE - ipl_load_size;
+
+	/* memory address where we resume loading u-boot */
+	void *const load_addr =
+		(void *)(CONFIG_SYS_NAND_U_BOOT_DST + ipl_uboot_load_size);
+
+	/*
+	 * Copy the portion of u-boot already read from flash by the IPL to its
+	 * correct load address.
+	 */
+	memcpy((void *)CONFIG_SYS_NAND_U_BOOT_DST, &_end, ipl_uboot_load_size);
+
+	/*
+	 * Resume loading u-boot where the IPL left off.
+	 */
+	nand_spl_load_image(spl_load_offset, spl_load_size, load_addr);
+
+#ifdef CONFIG_NAND_ENV_DST
+	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
+			    (void *)CONFIG_NAND_ENV_DST);
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
+			    (void *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
+#endif
+#endif
+	/*
+	 * Jump to U-Boot image
+	 */
+	uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
+	(*uboot)();
+}
+
+void board_init_f(ulong bootflag)
+{
+	nand_boot();
+}
+
+void hang(void)
+{
+	for (;;) {
+	}
+}
+
+#endif  /* CONFIG_SPL_BUILD */
diff --git a/board/palmtreo680/palmtreo680_spl.lds b/board/palmtreo680/palmtreo680_spl.lds
new file mode 100644
index 0000000..3e94311
--- /dev/null
+++ b/board/palmtreo680/palmtreo680_spl.lds
@@ -0,0 +1,51 @@ 
+/*
+ * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ *
+ * This file is a slight modification to the default pxa link script.  The '*'
+ * wildcard is added to the section names to consolidate all the sections
+ * created by the -ffunction-sections and -fdata-sections compiler flags.
+ */
+
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text :
+	{
+		arch/arm/cpu/pxa/start.o	(.text)
+		*(.text*)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data*)
+	}
+
+	. = ALIGN(4);
+
+	. = .;
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	_end = .;
+
+	/* internal SRAM is used for the SPL's bss */
+	.bss 0x5c000000 : {
+		__bss_start = .;
+		*(.bss*)
+		 . = ALIGN(4);
+		__bss_end = .;
+	}
+}
diff --git a/boards.cfg b/boards.cfg
index 5fc70be..72a9440 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -331,6 +331,7 @@  h2200                        arm         pxa
 lubbock                      arm         pxa
 palmld                       arm         pxa
 palmtc                       arm         pxa
+palmtreo680                  arm         pxa
 polaris                      arm         pxa         trizepsiv           -              -           trizepsiv:POLARIS
 pxa255_idp                   arm         pxa
 trizepsiv                    arm         pxa
diff --git a/doc/README.palmtreo680 b/doc/README.palmtreo680
new file mode 100644
index 0000000..e4a9305
--- /dev/null
+++ b/doc/README.palmtreo680
@@ -0,0 +1,570 @@ 
+
+README for the Palm Treo 680.
+
+Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
+
+You may reproduce the contents of this file entirely or in part, but please
+credit me by name if you do.  Thanks.
+
+
+Intro
+=====
+
+Yes, you can program u-boot onto the flash of your Palm Treo 680 so that u-boot
+(then Linux, Android, ...) runs at power-up.  This document describes how, and
+gives some implementation details on this port of u-boot.
+
+But first, I probably don't need to tell you that after doing this, your phone
+will no longer run PalmOS.  You *may* be able to later restore your phone to its
+original state by creating a backup image of the flash before writing u-boot
+(details below), but this is not heavily tested and should not be relied upon.
+There is also the possibility that something may go wrong during the process of
+programming u-boot, leaving you with a bricked phone.  If you follow these
+instructions carefully this chance will be minimized, but I do not recommend
+that you program u-boot onto a phone that you can not afford to lose, and
+certainly not one that contains important data that is not backed up elsewhere.
+I AM NOT RESPONSIBLE FOR THE LOSS OF YOUR PHONE.  DO THIS AT YOUR OWN RISK.
+Having said that, feel free to send me a note cursing me out if something does
+go wrong, but please tell me what happened exactly.  For that matter, I'd love
+to hear from you if you succeed.
+
+To program u-boot to your flash, you will need to boot the Linux kernel on your
+phone using a PalmOS bootloader such as cocoboot.  The details of building and
+running Linux on your Treo (cross-compiling, creating a root filesystem,
+configuring the kernel, etc) are beyond the scope of this document.
+
+
+
+Hardware Prerequisites
+======================
+
+A Palm Treo 680:
+  (dugh)
+
+A Palm usb cable:
+  You'll need this to establish a usbtty console connection to u-boot from a
+  desktop PC.  Currently there is no support in u-boot for the pxa27x keypad
+  (coming soon), so a serial link must be used for the console.
+  These cables are still widely available if you don't already have one.
+
+A Linux desktop PC.
+  You may be able to use Windows for the u-boot console if you have a usb driver
+  that is compatible with the Linux usbserial driver, but for programming u-boot
+  to flash, you'll really want to use a Linux PC.
+
+
+
+Treo-side Software Prerequisites
+================================
+
+Linux bootloader for PalmOS:
+
+  Cocoboot is the only one I'm aware of.  If you don't already have this, you
+  can download it from
+  https://download.enlightenment.org/misc/Illume/Treo-650/2008-11-13/sdcard-base.tar.gz
+  which is a compressed tar archive of the contents of an sd card containing
+  cocoboot.  Use mkdosfs to create a fat16 filesystem on the first primary
+  partition of the card, mount the partition, and extract the tar file to it.
+  You will probably need to edit the cocoboot.conf file to customize the
+  parameters passed to the kernel.
+
+
+
+Linux kernel:
+
+  The kernel on the Treo 680 is still a little rough around the edges, and the
+  official kernel frequently breaks on the Treo :(  A development kernel
+  specifically for the Treo 680 can be found on github:
+    http://github.com/mike-dunn/linux-treo680
+  The master branch of this tree has been tested on the Treo, and I recommend
+  using this kernel for programming u-boot.  As of this writing, there may be a
+  bug in the docg4 nand flash driver that sometimes causes block erasures to
+  fail.  This has been fixed in the above tree.
+
+  If you choose to use the official kernel, it must contain the docg4 driver that
+  includes the reliable_mode module parameter.  This was a later enhancement to
+  the driver, and was merged to the kernel as of v3.8.  Do not try to use an
+  earlier kernel that contains the docg4 driver without support for writing in
+  reliable mode.  If you try to program u-boot to flash with the docg4 driver
+  loaded without the reliable_mode parameter enabled, you *will* brick your
+  phone!
+
+  For the purpose of programming u-boot to flash, the following options must be
+  enabled in the Treo kernel's .config:
+
+     CONFIG_MTD=y
+     CONFIG_MTD_CMDLINE_PARTS=y
+     CONFIG_MTD_CHAR=y
+     CONFIG_MTD_NAND_DOCG4=m
+
+  Note that the docg4 nand driver is configured as a module, because we will
+  want to load and unload it with reliable_mode enabled or disabled as needed.
+
+  You will also need to specify mtd partitions on the kernel command line.  In
+  the instructions that follow, we will assume that the flash blocks to which
+  u-boot will be programmed are defined by the second partition on the device.
+  The u-boot config file (include/configs/palmtreo680.h) places the u-boot image
+  at the start of block 6 (offset 0x180000), which is the first writable
+  (non-protected) block on the flash (this is also where the PalmOS SPL starts).
+  The u-boot image occupies four blocks, so to create the u-boot partition, pass
+  this command line to the kernel:
+    mtdparts=Msys_Diskonchip_G4:1536k(protected_part)ro,1024k(bootloader_part),-(filesys_part)
+  This will create three partitions:
+    protected_part: the first six blocks, which are read-only
+    bootloader_part: the next four blocks, for the u-boot image
+    filesys_part: the remainder of the device
+  The mtdchar kernel device driver will use device nodes /dev/mtd0, /dev/mtd1,
+  and /dev/mtd2 for these partitions, respectively.  Ensure that your root file
+  system at least has /dev/mtd1 if you are not running udev or mdev.
+
+
+Userspace Utilities:
+
+  In addition to everything necessary to provide a useful userspace environment
+  (busybox is indispensable, of course), you will need the mtd-utils package on
+  your root filesystem.  I use version 1.5.0 of mtd-utils, and I suggest you use
+  this version as well, or at leat a version very close to this one, as
+  mtd-utils has tended to be fluid.
+
+  Note that busybox includes a version of mtd-utils.  These are deficient and
+  should not be used.  When you run one of these utilities (nanddump, etc),
+  ensure you are invoking the separate executable from mtd-utils, and not the
+  one built into busybox.  I recommend that you configure busybox with its
+  mtd-utils disabled to avoid any possibility of confusion.
+
+  You will also need to cross-compile the userspace Linux utility in
+  tools/palmtreo680/flash_u-boot.c, which we will run on the Treo to perform the
+  actual write of the u-boot image to flash.  This utility links against libmtd
+  from the mtd-utils package.
+
+
+
+Desktop PC-side Software Prerequisites
+======================================
+
+Terminal emulator application:
+  minicom, kermit, etc.
+
+
+Linux kernel:
+  Compiled with CONFIG_USB_SERIAL enabled.  Build this as a module.
+
+
+
+Recommended (Not directly related to u-boot)
+============================================
+
+Working directly on the Treo's tiny screen and keypad is difficult and
+error-prone.  I recommend that you log into the Linux kernel running on your
+Treo from your desktop PC using ethernet over usb.  The desktop's kernel must be
+configured with CONFIG_USB_USBNET, CONFIG_USB_NET_CDCETHER, and
+CONFIG_USB_NET_CDC_SUBSET.  The Treo's kernel will need CONFIG_USB_ETH, and its
+init script will need to start an ssh daemon like dropbear.  Note that the usb0
+network interface will not appear on the desktop PC until the Treo kernel's usb
+ethernet gadget driver has initialized.  You must wait for this to occur (watch
+the PC's kernel log) before you can assign usb0 an ip address and log in to the
+Treo.  If you also build the Treo's kernel with CONFIG_IP_PNP enabled, you can
+pass its ip address on the kernel command line, and obviate the need to
+initialize the network interface in your init script.
+
+Having the Palm usb cable connected to the host has the added benefit of keeping
+power supplied to your Treo, reducing the drain on the battery.  If something
+goes wrong while you're programming u-boot to the flash, you will have lots of
+time to correct it before the battery dies.
+
+I have encountered a situation where the kernel is sometimes unable to mount a
+root filesystem on the mmc card due to the mmc controller not coming up in time,
+(and CONFIG_MMC_UNSAFE_RESUME doesn't seem to help) so I recommend that you
+build a minimal root filesystem into the kernel using the kernel's initramfs
+feature (CONFIG_BLK_DEV_INITRD).  If you want your root filesystem on the mmc
+card, your init script can mount and switch_root to the mmc card after a short
+sleep.  But keep in mind that in this case you won't be able to use an mmc card
+to transfer files between your desktop and the Treo.  Another option for
+transfering files is to mount an nfs filesystem exported by the desktop PC.  For
+greatest convenience, you can export the root filesystem itself from your
+desktop PC and switch_root to it in your init script.  This will work if your
+init script contains a loop that waits for you to initialize the usb0 network
+interface on the desktop PC; e.g., loop while a ping to the desktop PC returns
+an error.  After the loop exits, do the nfs mount and call switch_root.  (You
+can not use the kernel nfsroot feature because the network will not be up when
+the kernel expects it to be; i.e., not until you configure the usb0 interface on
+the desktop.)  Use the nfs 'nolock' option when mounting to avoid the need to
+run a portmapper like rpcbind.
+
+
+
+Preliminaries
+=============
+
+Once Linux is running on your Treo, you may want to perform a few sanity checks
+before programming u-boot.  If you are impatient and reckless, you may skip this
+section, but see disclaimer at the top of this file!
+
+Load the docg4 driver (you did build this as a module, right?):
+
+  $ modprobe docg4 ignore_badblocks=1 reliable_mode=1
+
+We tell the driver to use the docg4's "reliable mode" when writing because this
+is the format required by the initial program loader (IPL), which runs from
+power-up and loads the first portion of u-boot.  We must ignore bad blocks
+because linux mtd uses out-of-band (oob) bytes to mark bad blocks, which will
+cause the blocks written by PalmOS to be misidentified as "bad" by libmtd.
+
+Check the kernel log to ensure that all's well:
+
+  $ dmesg | tail
+   	      <... snip ...>
+  docg4 docg4: NAND device: 128MiB Diskonchip G4 detected
+  3 cmdlinepart partitions found on MTD device Msys_Diskonchip_G4
+  Creating 3 MTD partitions on "Msys_Diskonchip_G4":
+  0x000000000000-0x000000180000 : "protected_part"
+  0x000000180000-0x000000280000 : "bootloader_part"
+  0x000000280000-0x000008000000 : "filesys_part"
+
+Ensure that the partition boundaries are as shown.  (If no partitions are shown,
+did you remember to pass them to the kernel on the command line?)  We will write
+u-boot to bootloader_part, which starts at offset 0x180000 (block 6) and spans 4
+256k blocks.  This partition is accessed through the device node /dev/mtd1.
+
+The docg4 contains a read-only table that identifies blocks that were marked as
+bad at the factory.  This table is in the page at offset 0x2000, which is within
+the partition protected_part (/dev/mtd0).  There is a slight chance that one or
+more of the four blocks that we will use for u-boot is listed in the table, so
+use nanddump to inspect the table to see if this is the case:
+
+  $ nanddump -p -l 512 -s 0x2000 -o /dev/mtd0
+  ECC failed: 0
+  ECC corrected: 0
+  Number of bad blocks: 0
+  Number of bbt blocks: 0
+  Block size 262144, page size 512, OOB size 16
+  Dumping data starting at 0x00002000 and ending at 0x00002200...
+  0x00002000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+   	      <... snip ...>
+
+The format of the table is simple: one bit per block, with block numbers
+increasing from left to right, starting with block 0 as the most significant bit
+of the first byte.  A bit will be clear if the corresponding block is bad.  We
+want to use blocks 6 throgh 9, so both of the two least significant bits of the
+first byte must be set, as must the two most significant bits of the second
+byte.  If this is not true in your case (you are very unlucky), you should use
+the first contiguous set of four good blocks after block 6, and adjust the
+partition boundaries accordingly.  You will also have to change the value of
+CONFIG_SYS_NAND_U_BOOT_OFFS in include/configs/palmtreo680.h and recompile
+u-boot.  Because the two blocks loaded by the IPL do not have to be contiguous,
+but our SPL expects them to be, you will need to erase any good blocks that are
+at an offset prior to CONFIG_SYS_NAND_U_BOOT_OFFS, so that the IPL does not find
+the magic number in oob and load it (details below).  Once you have done all
+this, the instructions in this file still apply, except that the instructions
+below for restoring the original PalmOS block contents may not work.
+
+Next, use nanddump to verify that the PalmOS SPL is where we expect it to be.
+The SPL can be identified by a magic number in the oob bytes of the first page
+of each of the two blocks containing the SPL image.  Pages are 512 bytes in
+size, so to dump the first page, plus the oob:
+
+  $ nanddump -p -l 512 -s 0 -o /dev/mtd1
+  ECC failed: 0
+  ECC corrected: 0
+  Number of bad blocks: 0
+  Number of bbt blocks: 0
+  Block size 262144, page size 512, OOB size 16
+  Dumping data starting at 0x00000000 and ending at 0x00000200...
+  0x00000000: 0a 00 00 ea 00 00 00 00 00 00 00 00 00 00 00 00
+   	      <... snip ...>
+  0x000001f0: 13 4c 21 60 13 4d 2a 69 13 4b 29 69 89 1a 99 42
+    OOB Data: 42 49 50 4f 30 30 30 10 3a e2 00 92 be a0 11 ff
+
+Verify that the first seven bytes of oob data match those in the above line.
+(This is ASCII "BIPO000".)
+
+Do the same for the next block:
+  $ nanddump -p -l 512 -s 0x40000 -o /dev/mtd1
+
+The first seven oob bytes in last line should read:
+
+    OOB Data: 42 49 50 4f 30 30 31 81 db 8e 8f 46 07 9b 59 ff
+
+(This is ASCII "BIPO001".)
+
+For additional assurance, verify that the next block does *not* contain SPL
+data.
+
+  $ nanddump -p -l 512 -s 0x80000 -o /dev/mtd1
+
+It doesn't matter what the oob contains, as long as the first four bytes are
+*not* ASCII "BIPO".  PalmOS should only be using two blocks for the SPL
+(although we will need four for u-boot).
+
+If you want, you can back up the contents of bootloader_part to a file.  You may
+be able to restore it later, if desired (see "Restoring PalmOS" below).
+
+  $ nanddump -l 0x100000 -s 0 -o -f bootloader_part.orig /dev/mtd1
+
+nanddump will spew voluminous warnings about uncorrectable ecc errors.  This is
+a consequence of reading pages that were written in reliable mode, and is
+expected (these should all occur on pages in odd-numbered 2k regions; i.e.,
+0x800, 0xa00, 0xc00, 0xe00, 0x1800, 0x1a00, ...).  The size of the file
+bootloader_part.orig should be 1081344, which is 2048 pages, each of size 512
+plus 16 oob bytes.  If you are using initramfs for the root filesystem, don't
+forget to copy the file to permanent storage, such as an mmc card.
+
+If all of the above went well, you can now program u-boot.
+
+
+
+Programming u-boot
+==================
+
+Our u-boot includes a small SPL (secondary program loader) that must be
+prepended to u-boot proper.  From the base u-boot source directory on your
+desktop PC:
+
+  $ cat spl/u-boot-spl.bin u-boot.bin > u-boot-concat.bin
+
+cd to the tools/palmtreo680/ directory, and cross-compile flash_u-boot.c for the
+Treo:
+
+  $(CC) -o flash_u-boot $(CFLAGS) $(INCLUDEPATH) $(LIBPATH) flash_u-boot.c -lmtd
+
+Substitute variable values from your cross-compilation environment as
+appropriate.  Note that it links to libmtd from mtd-utils, and this must be
+included in $(LIBPATH) and $(INCLUDEPATH).
+
+Transfer u-boot-concat.bin and the compiled flash_u-boot utility to the Treo's
+root filesystem.  On the Treo, cd to the directory where these files were
+placed.
+
+Load the docg4 driver if you have not already done so.
+
+  $ modprobe docg4 ignore_badblocks=1 reliable_mode=1
+
+Erase the blocks to which we will write u-boot.
+
+  $ flash_erase /dev/mtd1 0x00 4
+
+We can now program the flash.
+
+  ./flash_u-boot u-boot-concat.bin /dev/mtd1
+
+You can use nanddump (see above) to verify that the data was written.  This
+time, "BIPO" should be seen in the first four oob bytes of the first page of all
+four blocks in /dev/mtd1; i.e., at offsets 0x00000, 0x40000, 0x80000, 0xc0000.
+
+Shutdown linux, remove and re-insert the battery, hold your breath...
+
+
+
+Enjoying u-boot
+===============
+
+After you insert the battery, the u-boot splash screen should appear on the lcd
+after a few seconds.  With the usb cable connecting the Treo to your PC, in the
+kernel log of your PC you should see
+
+  <6>usb 3-1: New USB device found, idVendor=0525, idProduct=a4a6
+  <6>usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
+  <6>usb 3-1: Product: U-Boot 2013.01-00167-gd62ef56-dirty
+  <6>usb 3-1: Manufacturer: Das U-Boot
+
+Load the usbserial module on your desktop PC:
+
+  $ modprobe usbserial vendor=0x0525 product=0xa4a6
+
+and run your favorite terminal emulation utility (minicom, kermit, etc) with the
+serial device set to /dev/ttyUSB0 (assuming this is your only usb serial
+device).  You should be at the u-boot console (type 'help').
+
+There is not much that is unique about using u-boot on the palm treo 680.
+Kernels can be loaded from mmc, flash, and from the desktop PC via kermit.  You
+can expand the size of the second partition on the flash to contain a kernel, or
+else put the kernel(s) in their own partition.
+
+Nand commands work as expected, with the excepton that blocks not written by the
+linux mtd subsystem may be misidentified by the u-boot docg4 driver as "bad" if
+they contain data in the oob bytes.  This will be the case for the blocks
+containing the u-boot image, for example.  To work around this, use 'nand scrub'
+to erase these blocks, and 'nand read.raw' to read them.  (It would be useful if
+u-boot's nand commands provided a way to explicitly ignore "bad" blocks, because
+read.raw does not perform ecc.)
+
+Currently u-boot itself can only be programmed to flash from Linux; there is no
+support for reliable mode in u-boot's docg4 flash driver.  This should be
+corrected soon.
+
+
+
+Customizing
+===========
+
+If you change u-boot's configuration significantly (adding or removing
+features), you may have to adjust the value of CONFIG_SYS_NAND_U_BOOT_SIZE.
+This is the size of the concatenated spl + u-boot image, and tells the SPL how
+many flash blocks it needs to load.  It will be rounded up to the next 64k
+boundary (the spl flash block capacity), so it does not have to be exact, but
+you must ensure that it is not less than the actual image size.  If it is larger
+than the image, blocks may be needlessly loaded, but if too small, u-boot may
+only be partially loaded, resulting in a boot failure (bricked phone), so better
+to be too large.  The flash_u-boot utility will work with any size image and
+write the required number of blocks, provided that the partition is large
+enough.
+
+As the first writable block on the device, block 6 seems to make the most sense
+as the flash offset for writing u-boot (and this is where PalmOS places its
+SPL).  But you can place it elsewhere if you like.  If you do, you need to
+adjust CONFIG_SYS_NAND_U_BOOT_OFFS accordingly, and you must ensure that blocks
+preceeding the ones containing u-boot do *not* have the magic number in oob (the
+IPL looks for this).  In other words, make sure that any blocks that previously
+contained the u-boot image or PalmOS SPL are erased (and optionally written with
+something else) so that the IPL does not load it.  Also make sure that the new
+u-boot starting offset is at the start of a flash partition (check the kernel
+log after loading the docg4 driver), and pass the corresponding mtd device file
+to the flash_u-boot utility.
+
+The u-boot built-in default environment is used because a writable environment
+in flash did not seem worth the cost of a 256k flash block.  But adding this
+should be straightforward.
+
+
+
+Details on the SPL
+==================
+
+The docg4 features a 2k region at the start of its address space that interfaces
+to the system bus like a NOR flash.  This allows the docg4 to function as a boot
+ROM.  The Treo 680 uses this feature.  The contents of this 2k region are
+protected and can not be reprogrammed (at least I don't know how to do it).
+Fortunately, the code it contains does what we need to do, at least partially.
+After some essential hardware initialization (like the SDRAM controller), it
+runs an IPL (initial program loader) that copies 128K (no more, no less) to a
+fixed address in SDRAM and then jumps to it.  128K is too small for u-boot, so
+we use it to load a u-boot SPL.  But since our SPL only occupies a little over
+1k, we can economize on flash usage by having the IPL load a portion of u-boot
+proper as well.  We let the IPL load two blocks of a concatenated spl + u-boot
+image, and because the SPL is placed before u-boot proper, the IPL jumps to the
+SPL, which copies to its correct SDRAM address the portion of u-boot that the
+IPL has already loaded, and then loads the remaining u-boot blocks.
+
+
+
+The docg4's "reliable mode"
+===========================
+
+This is a special mode of operation of the hardware whereby consecutive pairs of
+2k regions are used in parallel (in some fashion) to store 2k of data.  In other
+words, the normal capacity is halved, but the data integrity is improved.  In
+this mode, the data is read or written from pages in even-numbered 2k regions
+(regions starting at 0x000, 0x1000, 0x2000, ...), and the odd-numbered 2k
+regions (regions starting at 0x800, 0x1800, 0x2800, ...) are transparently used
+in parallel.  In reliable mode, the odd-numbered 2k regions are not meant to be
+read or written directly.
+
+Reliable mode is used by the IPL because there is not enough space in its 2k
+footprint to implement the BCH ecc algorithm.  Data that is read while reliable
+mode is enabled must have been written in reliable mode, or the read fails.
+However, data written in reliable mode can also be read in normal mode (just not
+as reliably), but only from the even-numbered 2k regions; the odd-numbered 2k
+regions appear to contain junk, and will generate ecc errors.  When the IPL and
+SPL read from flash, the odd-numbered 2k regions are explicitly skipped.  The
+same is true for the flash_u-boot utility when it writes the u-boot image in
+reliable mode.
+
+The docg4 Linux driver supports writing in reliable mode (it is enabled by the
+module parameter), but not reading.  However, the u-boot docg4_spl driver does
+read in reliable mode, in the same fashion as the IPL.
+
+
+
+Details on the IPL and its data format
+======================================
+
+Starting from block 5 and counting upward, the IPL will search for and load the
+first two blocks it finds that contain a magic number in the oob of the first
+page of the block.  The contents are loaded to SDRAM starting at address
+0xa1700000.  After two blocks have been loaded, it jumps to 0xa1700000.  The
+number of blocks loaded and the load address in SDRAM are hard-coded; only the
+flash offset of the blocks can vary at run-time (based on the presence of the
+magic number).
+
+In addition to using the docg4's reliable mode, the IPL expects each 512 byte
+page to be written redundantly in the subsequent page.  The hardware is capable
+of detecting bit errors (but not correcting them), and if a bit error is
+detected when a page is read, the page contents are discarded and the subsequent
+page is read.
+
+Reliable mode reduces the capacity of a block by half, and the redundant pages
+reduce it by half again.  As a result, the normal 256k capacity of a block is
+reduced to 64k for the purposes of the IPL/SPL.
+
+For the sake of simplicity and uniformity, the SPL mimics the operation of the
+IPL, and expects the image to be stored in the same format.
+
+
+
+Restoring PalmOS
+================
+
+If you backed up the contents of bootloader_part flash partition earlier, you
+should be able to restore it with the shell script shown below.  The first two
+blocks of data contain the PalmOS SPL and were written in reliable mode, whereas
+the next two blocks were written in normal mode, so the script has to load and
+unload the docg4 driver.  Make sure that the mtd-utils nandwrite and flash_erase
+are in your path (and are not those from busybox).  Also double-check that the
+backup image file bootloader_part.orig is exactly 1081344 bytes in length.  If
+not, it was not backed up correctly.  Run the script as:
+
+  ./restore_bootpart bootloader_part.orig /dev/mtd1
+
+The script will take a minute or so to run.  When it finishes, you may want to
+verify with nanddump that the data looks correct before you cycle power, because
+if the backup or restore failed, your phone will be bricked.  Note that as a
+consequence of reliable mode, the odd-numbered 2k regions in the first two
+blocks will not exactly match the contents of the backup file (so unfortunately
+we can't simply dump the flash contents to a file and do a binary diff with the
+original back-up image to verify that it was restored correctly).  Also,
+nanddump will report uncorrectable ecc errors when it reads those regions.
+
+#!/bin/sh
+
+if [ $# -ne 2 ]; then
+    echo "usage: $0: <image file> <mtd device node>"
+    exit 1
+fi
+
+# reliable mode used for the first two blocks
+modprobe -r docg4
+modprobe docg4 ignore_badblocks=1 reliable_mode=1 || exit 1
+
+# erase all four blocks
+flash_erase $2 0 4
+
+# Program the first two blocks in reliable mode.
+# 2k (4 pages) is written at a time, skipping alternate 2k regions
+# Note that "2k" is 2112 bytes, including 64 oob bytes
+file_ofs=0
+flash_ofs=0
+page=0
+while [ $page -ne 1024 ]; do
+    dd if=$1 bs=2112 skip=$file_ofs count=1 | nandwrite -o -n -s $flash_ofs $2 - || exit 1
+    file_ofs=$((file_ofs+2))
+    flash_ofs=$((flash_ofs+0x1000))
+    page=$((page+8))
+done;
+
+# normal mode used for the next two blocks
+modprobe -r docg4
+modprobe docg4 ignore_badblocks=1 || exit 1
+dd if=$1 bs=1 skip=$file_ofs count=540672 | nandwrite -o -n -s 0x80000 $2 - || exit 1
+modprobe -r docg4
+
+
+TODO
+====
+
+  - Keypad support.
+  - Interactive boot menu using keypad and lcd.
+  - Add reliable mode support to the u-boot docg4 driver.
+  - U-boot command that will write a new image to the bootloader partition in
+    flash.
+  - Linux FTD support.
+
diff --git a/include/configs/palmtreo680.h b/include/configs/palmtreo680.h
new file mode 100644
index 0000000..e785900
--- /dev/null
+++ b/include/configs/palmtreo680.h
@@ -0,0 +1,295 @@ 
+/*
+ * Palm Treo 680 configuration file
+ *
+ * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ *
+ */
+
+#ifndef	__CONFIG_H
+#define	__CONFIG_H
+
+/*
+ * High Level Board Configuration Options
+ */
+#define CONFIG_CPU_PXA27X               1
+#define CONFIG_PALMTREO680              1
+
+
+#define CONFIG_SYS_MALLOC_LEN           (4096*1024)
+
+#define CONFIG_LZMA
+
+/*
+ * Serial Console Configuration
+ */
+#define CONFIG_PXA_SERIAL
+#define CONFIG_FFUART                   1
+#define CONFIG_BAUDRATE                 9600
+#define CONFIG_SYS_BAUDRATE_TABLE       { 9600, 19200, 38400, 57600, 115200 }
+#define CONFIG_CONS_INDEX               3
+
+/* we have nand (although technically nand *is* flash...) */
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_LCD
+/* #define CONFIG_KEYBOARD */  /* TODO */
+
+/*
+ * Bootloader Components Configuration
+ */
+#include <config_cmd_default.h>
+#undef  CONFIG_CMD_FPGA
+#undef  CONFIG_CMD_LOADS
+#undef  CONFIG_CMD_NET
+#undef  CONFIG_CMD_NFS
+#undef  CONFIG_CMD_IMLS
+#undef  CONFIG_CMD_FLASH
+#undef  CONFIG_CMD_SETGETDCR
+#undef  CONFIG_CMD_SOURCE
+#undef  CONFIG_CMD_XIMG
+
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_NAND
+
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+
+#define CONFIG_MACH_TYPE                1230
+
+
+/*
+ * MMC Card Configuration
+ */
+#ifdef CONFIG_CMD_MMC
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_PXA_MMC_GENERIC
+
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+#define CONFIG_DOS_PARTITION
+#endif
+
+/*
+ * LCD
+ */
+#ifdef CONFIG_LCD
+#define CONFIG_PXA_LCD
+#define CONFIG_ACX544AKN
+#define CONFIG_LCD_LOGO
+#define CONFIG_SYS_LCD_PXA_NO_L_BIAS /* don't configure GPIO77 as L_BIAS */
+#define LCD_BPP LCD_COLOR16
+#define CONFIG_FB_ADDR 0x5c000000    /* internal SRAM */
+#define CONFIG_CMD_BMP
+#define CONFIG_SPLASH_SCREEN         /* requires "splashimage" env var */
+#define CONFIG_SPLASH_SCREEN_ALIGN   /* requires "splashpos" env var */
+#define CONFIG_VIDEO_BMP_GZIP
+#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE  (2 << 20)
+
+#endif
+
+/*
+ * KGDB
+ */
+#ifdef CONFIG_CMD_KGDB
+#define CONFIG_KGDB_BAUDRATE            230400  /* kgdb serial port speed */
+#define CONFIG_KGDB_SER_INDEX           2       /* which serial port to use */
+#endif
+
+/*
+ * HUSH Shell Configuration
+ */
+#define CONFIG_SYS_HUSH_PARSER          1
+#define CONFIG_SYS_PROMPT_HUSH_PS2      "> "
+
+#define CONFIG_SYS_LONGHELP
+#ifdef CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT               "$ "
+#else
+#define CONFIG_SYS_PROMPT               "=> "
+#endif
+#define CONFIG_SYS_CBSIZE               256
+#define CONFIG_SYS_PBSIZE               \
+	(CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16)
+#define CONFIG_SYS_MAXARGS              16
+#define CONFIG_SYS_BARGSIZE             CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_DEVICE_NULLDEV       1
+
+/*
+ * Clock Configuration
+ */
+#undef  CONFIG_SYS_CLKS_IN_HZ
+#define CONFIG_SYS_HZ                   1000 /* decrementer freq: 1 ms ticks */
+#define CONFIG_SYS_CPUSPEED             0x210           /* 416MHz ; N=2,L=16 */
+
+/*
+ * Stack sizes
+ */
+#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
+
+/*
+ * DRAM Map
+ */
+#define CONFIG_NR_DRAM_BANKS            1               /* 1 bank of DRAM */
+#define PHYS_SDRAM_1                    0xa0000000      /* SDRAM Bank #1 */
+#define PHYS_SDRAM_1_SIZE               0x04000000      /* 64 MB */
+
+#define CONFIG_SYS_DRAM_BASE            0xa0000000
+#define CONFIG_SYS_DRAM_SIZE            0x04000000      /* 64 MB DRAM */
+
+#define CONFIG_SYS_MEMTEST_START        0xa0400000      /* memtest works on */
+#define CONFIG_SYS_MEMTEST_END          0xa0800000      /* 4 ... 8 MB in DRAM */
+#define CONFIG_SYS_LOAD_ADDR            CONFIG_SYS_DRAM_BASE
+#define CONFIG_SYS_SDRAM_BASE           PHYS_SDRAM_1
+
+
+
+/*
+ * GPIO settings
+ */
+#define CONFIG_SYS_GAFR0_L_VAL  0x0E000000
+#define CONFIG_SYS_GAFR0_U_VAL  0xA500001A
+#define CONFIG_SYS_GAFR1_L_VAL  0x60000002
+#define CONFIG_SYS_GAFR1_U_VAL  0xAAA07959
+#define CONFIG_SYS_GAFR2_L_VAL  0x02AAAAAA
+#define CONFIG_SYS_GAFR2_U_VAL  0x41440F08
+#define CONFIG_SYS_GAFR3_L_VAL  0x56AA95FF
+#define CONFIG_SYS_GAFR3_U_VAL  0x00001401
+#define CONFIG_SYS_GPCR0_VAL    0x1FF80400
+#define CONFIG_SYS_GPCR1_VAL    0x03003FC1
+#define CONFIG_SYS_GPCR2_VAL    0x01C1E000
+#define CONFIG_SYS_GPCR3_VAL    0x01C1E000
+#define CONFIG_SYS_GPDR0_VAL    0xCFF90400
+#define CONFIG_SYS_GPDR1_VAL    0xFB22BFC1
+#define CONFIG_SYS_GPDR2_VAL    0x93CDFFDF
+#define CONFIG_SYS_GPDR3_VAL    0x0069FF81
+#define CONFIG_SYS_GPSR0_VAL    0x02000018
+#define CONFIG_SYS_GPSR1_VAL    0x00000000
+#define CONFIG_SYS_GPSR2_VAL    0x000C0000
+#define CONFIG_SYS_GPSR3_VAL    0x00080000
+
+#define CONFIG_SYS_PSSR_VAL     0x30
+
+/*
+ * Clock settings
+ */
+#define CONFIG_SYS_CKEN         0x01ffffff
+#define CONFIG_SYS_CCCR         0x02000210
+
+/*
+ * Memory settings
+ */
+#define CONFIG_SYS_MSC0_VAL     0x7ff844c8
+#define CONFIG_SYS_MSC1_VAL     0x7ff86ab4
+#define CONFIG_SYS_MSC2_VAL     0x7ff87ff8
+#define CONFIG_SYS_MDCNFG_VAL   0x0B880acd
+#define CONFIG_SYS_MDREFR_VAL   0x201fa031
+#define CONFIG_SYS_MDMRS_VAL    0x00320032
+#define CONFIG_SYS_FLYCNFG_VAL  0x00000000
+#define CONFIG_SYS_SXCNFG_VAL   0x40044004
+
+/*
+ * PCMCIA and CF Interfaces
+ */
+#define CONFIG_SYS_MECR_VAL     0x00000003
+#define CONFIG_SYS_MCMEM0_VAL   0x0001c391
+#define CONFIG_SYS_MCMEM1_VAL   0x0001c391
+#define CONFIG_SYS_MCATT0_VAL   0x0001c391
+#define CONFIG_SYS_MCATT1_VAL   0x0001c391
+#define CONFIG_SYS_MCIO0_VAL    0x00014611
+#define CONFIG_SYS_MCIO1_VAL    0x0001c391
+
+/*
+ * USB
+ */
+#define CONFIG_USB_DEVICE
+#define CONFIG_USB_TTY
+#define CONFIG_USB_DEV_PULLUP_GPIO 114
+
+/*
+ * SPL
+ */
+#define CONFIG_SPL
+#define CONFIG_SPL_TEXT_BASE    0xa1700000 /* IPL loads SPL here */
+#define CONFIG_SPL_STACK        0x5c040000 /* top of internal SRAM */
+#define CONFIG_SPL_LDSCRIPT     board/palmtreo680/palmtreo680_spl.lds
+#define CONFIG_SPL_NAND_SUPPORT /* build libnand for spl */
+#define CONFIG_SPL_NAND_DOCG4   /* use lean docg4 nand spl driver */
+
+/*
+ * NAND
+ */
+#define CONFIG_NAND_DOCG4
+#define CONFIG_SYS_NAND_SELF_INIT
+#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* only one device */
+#define CONFIG_SYS_NAND_BASE 0x00000000 /* mapped to reset vector */
+#define CONFIG_SYS_NAND_PAGE_SIZE 0x200
+#define CONFIG_SYS_NAND_BLOCK_SIZE 0x40000
+#define CONFIG_BITREVERSE       /* needed by docg4 driver */
+#define CONFIG_BCH              /* needed by docg4 driver */
+
+/*
+ * IMPORTANT NOTE: this is the size of the concatenated spl + u-boot image.  It
+ * will be rounded up to the next 64k boundary (the spl flash block size), so it
+ * does not have to be exact, but you must ensure that it is not less than the
+ * actual image size, or it may fail to boot (bricked phone)!
+ * (Tip: reduces to three blocks with lcd and mmc support removed from u-boot.)
+*/
+#define CONFIG_SYS_NAND_U_BOOT_SIZE 0x40000 /* four 64k flash blocks */
+
+/*
+ * This is the byte offset into the flash at which the concatenated spl + u-boot
+ * image is placed.  It must be at the start of a block (256k boundary).  Blocks
+ * 0 - 5 are write-protected, so we start at block 6.
+ */
+#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x180000  /* block 6 */
+
+/* DRAM address to which u-boot proper is loaded (before it relocates itself) */
+#define CONFIG_SYS_NAND_U_BOOT_DST  0xa0000000
+#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST
+
+/* passed to linker by Makefile as arg to -Ttext option */
+#define CONFIG_SYS_TEXT_BASE 0xa0000000
+
+#define CONFIG_SYS_INIT_SP_ADDR         0x5c040000 /* end of internal SRAM */
+
+/*
+ * environment
+ */
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_BUILD_ENVCRC
+#define CONFIG_ENV_SIZE 0x200
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_EXTRA_ENV_SETTINGS  \
+	"stdin=usbtty\0"           \
+	"stdout=usbtty\0"          \
+	"stderr=usbtty"
+#define CONFIG_BOOTARGS "mtdparts=Msys_Diskonchip_G4:1536k(protected_part)ro,1024k(bootloader_part),-(filesys_part) \
+ip=192.168.11.102:::255.255.255.0:treo:usb0"
+#define CONFIG_BOOTDELAY   3
+
+#if 0 /* example: try 2nd mmc partition, then nand */
+#define CONFIG_BOOTCOMMAND                                              \
+	"mmc rescan; "                                                  \
+	"if mmcinfo && ext2load mmc 0:2 0xa1000000 uImage; then "       \
+	    "bootm 0xa1000000; "					\
+	"elif nand read 0xa1000000 0x280000 0x240000; then "            \
+	    "bootm 0xa1000000; "					\
+	"fi; "
+#endif
+
+/* u-boot lives at end of SDRAM, so use start of SDRAM for stand alone apps */
+#define CONFIG_STANDALONE_LOAD_ADDR 0xa0000000
+
+#define CONFIG_SYS_DCACHE_OFF
+#define CONFIG_SYS_ICACHE_OFF
+
+#endif  /* __CONFIG_H */
diff --git a/tools/palmtreo680/flash_u-boot.c b/tools/palmtreo680/flash_u-boot.c
new file mode 100644
index 0000000..cc0afec
--- /dev/null
+++ b/tools/palmtreo680/flash_u-boot.c
@@ -0,0 +1,177 @@ 
+/*
+ * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ *
+ *
+ * This is a userspace Linux utility that, when run on the Treo 680, will
+ * program u-boot to flash.  The docg4 driver *must* be loaded with the
+ * reliable_mode and ignore_badblocks parameters enabled:
+ *
+ *        modprobe docg4 ignore_badblocks=1 reliable_mode=1
+ *
+ * This utility writes the concatenated spl + u-boot image to the start of the
+ * mtd device in the format expected by the IPL/SPL.  The image file and mtd
+ * device node are passed to the utility as arguments.  The blocks must have
+ * been erased beforehand.
+ *
+ * When you compile this, note that it links to libmtd from mtd-utils, so ensure
+ * that your include and lib paths include this.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <mtd/mtd-user.h>
+#include "libmtd.h"
+
+#define RELIABLE_BLOCKSIZE  0x10000 /* block capacity in reliable mode */
+#define STANDARD_BLOCKSIZE  0x40000 /* block capacity in normal mode */
+#define PAGESIZE 512
+#define PAGES_PER_BLOCK 512
+#define OOBSIZE 7		/* available to user (16 total) */
+
+uint8_t ff_oob[OOBSIZE] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+/* this is the magic number the IPL looks for (ASCII "BIPO") */
+uint8_t page0_oob[OOBSIZE] = {'B', 'I', 'P', 'O', 0xff, 0xff, 0xff};
+
+int main(int argc, char * const argv[])
+{
+	int devfd, datafd, num_blocks, block;
+	off_t file_size;
+	libmtd_t mtd_desc;
+	struct mtd_dev_info devinfo;
+	uint8_t *blockbuf;
+	char response[8];
+
+	if (argc != 3) {
+		printf("usage: %s <image file> <mtd dev node>\n", argv[0]);
+		exit(-1);
+	}
+
+	mtd_desc = libmtd_open();
+	if (mtd_desc == NULL) {
+		fprintf(stderr, "can't initialize libmtd\n");
+		exit(-1);
+	}
+
+	/* open the spl image file and mtd device */
+	datafd = open(argv[1], O_RDONLY);
+	if (datafd == -1) {
+		perror(argv[1]);
+		exit(-1);
+	}
+	devfd = open(argv[2], O_WRONLY);
+	if (devfd == -1) {
+		perror(argv[2]);
+		exit(-1);
+	}
+	if (mtd_get_dev_info(mtd_desc, argv[2], &devinfo) < 0) {
+		fprintf(stderr, "mtd_get_dev_info failed\n");
+		exit(-1);
+	}
+
+	/* determine the number of blocks needed by the image */
+	file_size = lseek(datafd, 0, SEEK_END);
+	if (file_size == (off_t)-1) {
+		perror("lseek");
+		exit(-1);
+	}
+	num_blocks = (file_size + RELIABLE_BLOCKSIZE - 1) / RELIABLE_BLOCKSIZE;
+	file_size = lseek(datafd, 0, SEEK_SET);
+	if (file_size == (off_t)-1) {
+		perror("lseek");
+		exit(-1);
+	}
+	printf("The mtd partition contains %d blocks\n", devinfo.eb_cnt);
+	printf("U-boot will occupy %d blocks\n", num_blocks);
+	if (num_blocks > devinfo.eb_cnt) {
+		fprintf(stderr, "Insufficient blocks on partition\n");
+		exit(-1);
+	}
+
+	printf("Do you want to proceed?\n");
+	scanf("%s", response);
+	if ((response[0] != 'y') && (response[0] != 'Y')) {
+		printf("Exiting\n");
+		close(devfd);
+		close(datafd);
+		exit(-1);
+	}
+
+	blockbuf = malloc(RELIABLE_BLOCKSIZE);
+	if (blockbuf == NULL) {
+		perror("malloc");
+		exit(-1);
+	}
+
+	for (block = 0; block < num_blocks; block++) {
+		int ofs, page;
+		ssize_t read_ret;
+		uint8_t *pagebuf = blockbuf, *buf = blockbuf;
+		uint8_t *oobbuf = page0_oob; /* magic num in oob of 1st page */
+		size_t len = RELIABLE_BLOCKSIZE;
+		int ret;
+
+#if 0 /* to minimize risk, require the user to erase the partition beforehand */
+		printf("Block %d: erasing\r", block + 1);
+		ret = mtd_erase(mtd_desc, &devinfo, devfd, block);
+		if (ret) {
+			fprintf(stderr,
+				"\nmtd_erase on block %d returned %d\n",
+				block + 1, ret);
+			exit(-1);
+		}
+#endif
+
+		/* read data for one block from file */
+		while (len != 0 && (read_ret = read(datafd, buf, len)) != 0) {
+			if (read_ret == -1) {
+				if (errno == EINTR)
+					continue;
+				perror("read");
+				exit(-1);
+			}
+			len -= read_ret;
+			buf += read_ret;
+		}
+
+		printf("Block %d: writing\r", block + 1);
+		fflush(stdout);
+
+		for (page = 0, ofs = 0;
+		     page < PAGES_PER_BLOCK;
+		     page++, ofs += PAGESIZE) {
+			if (page & 0x04)  /* Odd-numbered 2k page */
+				continue; /* skipped in reliable mode */
+
+			ret = mtd_write(mtd_desc, &devinfo, devfd, block, ofs,
+					pagebuf, PAGESIZE, oobbuf, OOBSIZE,
+					MTD_OPS_PLACE_OOB);
+			if (ret) {
+				fprintf(stderr,
+					"\nmtd_write returned %d on block %d, ofs %x\n",
+					ret, block + 1, ofs);
+				exit(-1);
+			}
+			oobbuf = ff_oob;  /* oob for subsequent pages */
+
+			if (page & 0x01)  /* odd-numbered subpage */
+				pagebuf += PAGESIZE;
+		}
+	}
+
+	printf("\nDone\n");
+
+	close(devfd);
+	close(datafd);
+	free(blockbuf);
+	return 0;
+}