I don't claim to have any special knowledge of the MTD subsystem, but I wonder if part of the problem with successfully writing the NAND memory involves choosing the proper block size for the device. Here is what I get if I "cat /proc/mtd":
$ cat /proc/mtd
dev: size erasesize name
mtd0: 00100000 00020000 "u-boot"
mtd1: 00400000 00020000 "uImage"
mtd2: 02000000 00020000 "rootfs"
mtd3: 0db00000 00020000 "data"
$
As you can see, the erase size (block size) of the NAND is rather large -- 0x20000 or 131072 bytes, or 256 512-byte blocks. 'dd' defaults to a 512-byte block.
I don't particularly want to mess with my NAND, but those of you who are might try using "dd bs=128K ...". If anyone does this, I'd be interested in hearing if it work, or changes things.
The other inherent problem with 'dd' is that its behavior upon encountering an error does not work well with NAND. My understanding is that NAND errors are to be expected, and when they are encountered, that block is skipped and the contents written to the next good block. But, 'dd' doesn't do this, and as far as I know, it has no way to deal with NAND write errors appropriately. Thus, it is a poor tool for this task.
Again, I have no special knowledge of how the MTD subsystem is implemented in practice, so this may not be the problem at all. Perhaps the subsystem handles 512-byte writes. Perhaps it silently handles NAND block errors. It would be nice is someone who knew would answer us here. This is where I'd start looking, though, if I were trying to investigate this problem.