+commit 68cf19aae48f2969ec70669604d0d776f02c8bc4
+Author: Scott Wood <scottwood@freescale.com>
+Date: Wed Aug 13 18:24:05 2008 -0500
+
+ socrates: Update NAND driver to new API.
+
+ Also, fix some minor formatting issues, and simplify the handling of
+ "state" for writes.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit ba22d10f39eaeedd035e8265616e31ff88e314d5
+Author: Scott Wood <scottwood@freescale.com>
+Date: Wed Aug 13 18:03:40 2008 -0500
+
+ quad100hd: Update NAND driver to new API.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit f64cb652a8a84c5c34d0afcbd7ffef886aa1d838
+Author: Scott Wood <scottwood@freescale.com>
+Date: Wed Aug 13 17:53:48 2008 -0500
+
+ m5373evb: Update NAND driver to new API.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 1a23a197c8722b805f40895544bbdb1a648c1c82
+Author: Scott Wood <scottwood@freescale.com>
+Date: Wed Aug 13 17:04:30 2008 -0500
+
+ s3c24x0: Update NAND driver to new API.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit aa5f75f20db8a7103fad9c34d6f1193e10d1890f
+Author: Scott Wood <scottwood@freescale.com>
+Date: Wed Aug 13 15:56:00 2008 -0500
+
+ at91: Update board NAND drivers to current API.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit d438d50848e9425286e5fb0493e0affb5a0b1e1b
+Author: Kyungmin Park <kmpark@infradead.org>
+Date: Wed Aug 13 09:11:02 2008 +0900
+
+ Fix OneNAND build break
+
+ Since page size field is changed from oobblock to writesize. But OneNAND is not updated.
+ - fix bufferram management at erase operation
+ This patch includes the NAND/OneNAND state filed too.
+
+ Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 9483df6408c25f16060432de3868901e352e23bc
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:43 2008 +0200
+
+ drivers/mtd/nand_legacy: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit cc4a0ceeac5462106172d0cc9d9d542233aa3ab2
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:43 2008 +0200
+
+ drivers/mtd/nand: Move conditional compilation to Makefile
+
+ rename CFG_NAND_LEGACY to CONFIG_NAND_LEGACY
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 4fb09b81920e5dfdfc4576883186733f0bd6059c
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:42 2008 +0200
+
+ drivers/mtd/onenand: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 00b1883a4cac59d97cd297b1a3a398db85982865
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:42 2008 +0200
+
+ drivers/mtd: Move conditional compilation to Makefile
+
+ rename CFG_FLASH_CFI_DRIVER to CONFIG_FLASH_CFI_DRIVER
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 7ba44a5521cdb7fa1c72864025cde1e21a6f6921
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:41 2008 +0200
+
+ drivers/qe: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit ab6878c7bc68a7b5e5b731655bdc13221bbfc493
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:40 2008 +0200
+
+ drivers/pci: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 55d6d2d39fe3fe87802e399aa17539368b495d2e
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:40 2008 +0200
+
+ drivers/misc: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 65e41ea0548b86e3d7892defac8e4dc1ea70aed1
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:40 2008 +0200
+
+ drivers/input: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 88f57e093114a44aa9a858d52b099bcc52034a8c
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:39 2008 +0200
+
+ drivers/dma: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 1a02806c4b1b4a09ad4e95d3aac3783889e5f8d7
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:39 2008 +0200
+
+ drivers/block: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 1a6ffbfaf4353bec379ed1fcfc54b6f1a30af09a
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:39 2008 +0200
+
+ serial: move CFG_NS9750_UART to CONFIG_NS9750_UART
+
+ move also conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 6c58a030f86829fa4f0d4337cf4b794c41a1823e
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:38 2008 +0200
+
+ serial: move CFG_SCIF_CONSOLE to CONFIG_SCIF_CONSOLE
+
+ move also conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit d6e9ee92e890f67594ab150689510df361133ead
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:38 2008 +0200
+
+ common: Move conditional compilation to Makefile
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit f5acb9fd9bba1160de3ef349c7d33fe510eda286
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Wed Aug 13 01:40:09 2008 +0200
+
+ mx31: move freescale's mx31 boards to vendor board dir
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 8ed2f5f950e2581214d20b011a8f27a6396d65d2
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Sat Jul 5 23:11:11 2008 +0200
+
+ at91: move arch-at91sam9 to arch-at91
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 195ccfc5991d48764b2519941e3507f693851d5d
+Author: Fathi BOUDRA <fabo@debian.org>
+Date: Wed Aug 6 10:06:20 2008 +0200
+
+ OneNAND: Fill in MTD function pointers for OneNAND.
+
+ onenand_print_device_info():
+ - Now returns a string to be placed in mtd->name,
+ rather than calling printf.
+ - Remove verbose parameter as it becomes useless.
+
+ Signed-off-by: Fathi Boudra <fabo@debian.org>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit aa646643b6bc250cb3a4966bf728876e0c10d329
+Author: Guennadi Liakhovetski <lg@denx.de>
+Date: Wed Aug 6 21:42:07 2008 +0200
+
+ nand_spl: Support page-aligned read in nand_load, use chipselect
+
+ Supporting page-aligned reads doesn't incure any sinificant overhead, just
+ a small change in the algorithm. Also replace in_8 with readb, since there
+ is no in_8 on ARM.
+
+ Signed-off-by: Guennadi Liakhovetski <lg@denx.de>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 4f32d7760a58fe73981b6edc0b0751565d2daa4c
+Author: Scott Wood <scottwood@freescale.com>
+Date: Tue Aug 5 11:15:59 2008 -0500
+
+ NAND boot: Update large page support for current API.
+
+ Also, remove the ctrl variable in favor of passing the constants
+ directly, and remove redundant (u8) casts.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit e4c09508545d1c45617ba45391c03c03cbc360b9
+Author: Scott Wood <scottwood@freescale.com>
+Date: Mon Jun 30 14:13:28 2008 -0500
+
+ NAND boot: MPC8313ERDB support
+
+ Note that with older board revisions, NAND boot may only work after a
+ power-on reset, and not after a warm reset. I don't have a newer board
+ to test on; if you have a board with a 33MHz crystal, please let me know
+ if it works after a warm reset.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit acdab5c33f1ea6f5e08f06f08bc64af23ff40d71
+Author: Scott Wood <scottwood@freescale.com>
+Date: Thu Jun 26 14:06:52 2008 -0500
+
+ mpc8313erdb: Enable NAND in config.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit c3db8c649c6ab3da2f1411c4c6d61aecea054aa4
+Author: Guennadi Liakhovetski <lg@denx.de>
+Date: Thu Jul 31 12:38:26 2008 +0200
+
+ NAND: Do not write or read a whole block if it is larger than the environment
+
+ Environment can be smaller than NAND block size, do not need to read a whole
+ block and minimum for writing is one page. Also remove an unused variable.
+
+ Signed-off-by: Guennadi Liakhovetski <lg@denx.de>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit eafcabd15f00c142156235c519fcc55b10993241
+Author: Marcel Ziswiler <marcel@ziswiler.com>
+Date: Sun Jun 22 16:30:06 2008 +0200
+
+ NAND: chip->state does not always get set.
+
+ Fixes an issue with chip->state not always being set causing troubles.
+
+ Signed-off-by: Marcel Ziswiler <marcel@ziswiler.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 13f0fd94e3cae6f8a0d9fba5d367e311edc8ebde
+Author: Ilya Yanok <yanok@emcraft.com>
+Date: Mon Jun 30 15:34:40 2008 +0200
+
+ NAND: Scan bad blocks lazily.
+
+ Rather than scanning on boot, scan upon the first attempt to check the
+ badness of a block. This speeds up boot when not using NAND, and reduces
+ the likelihood of needing to reflash via JTAG if NAND becomes
+ nonfunctional.
+
+ Signed-off-by: Ilya Yanok <yanok@emcraft.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit dfbf617ff055e4216f78d358b0867c548916d14b
+Author: Scott Wood <scottwood@freescale.com>
+Date: Thu Jun 12 13:20:16 2008 -0500
+
+ NAND read/write fix
+
+ Implement block-skipping read/write, based on a patch from
+ Morten Ebbell Hestens <morten.hestnes@tandberg.com>.
+
+ Signed-off-by: Morten Ebbell Hestnes <morten.hestnes@tandberg.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 984e03cdf1431bb593aeaa1b74c445d616f955d3
+Author: Scott Wood <scottwood@freescale.com>
+Date: Thu Jun 12 13:13:23 2008 -0500
+
+ NAND: Always skip blocks on read/write/boot.
+
+ Use of the non-skipping versions was almost always (if not always)
+ an error, and no valid use case has been identified.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit e1c3dbada349992875934575c97b328ab2cb33ca
+Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+Date: Thu Jun 12 11:10:21 2008 -0500
+
+ nand: fsl_upm: convert to updated MTD NAND infrastructure
+
+ Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 300253306acc72b1b2e9faf0987f86551151d7cf
+Author: Scott Wood <scottwood@freescale.com>
+Date: Thu May 22 15:02:46 2008 -0500
+
+ fsl_elbc_nand: Hard-code the FBAR/FPAR split.
+
+ The hardware has separate registers for block and page-within-block,
+ but the division between the two has no apparent relation to the
+ actual erase block size of the NAND chip.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 9c814b0a716aae884bec977b9a032dfa59cfb79a
+Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+Date: Fri Mar 28 22:10:54 2008 +0300
+
+ fsl_elbc_nand: workaround for hangs during nand write
+
+ Using current driver elbc sometimes hangs during nand write. Reading back
+ last byte helps though (thanks to Scott Wood for the idea).
+
+ Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 9fd020d6b4b36b9fb67cd834bc1ae7fdba15ee9e
+Author: Scott Wood <scottwood@freescale.com>
+Date: Fri Mar 21 16:12:51 2008 -0500
+
+ Freescale eLBC FCM NAND driver
+
+ This is a driver for the Flash Control Machine of the enhanched Local Bus
+ Controller found on some Freescale chips (such as the mpc8313 and the
+ mpc8379).
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 41ef8c716e93fdf50efe9c1ba733ca6675daaca6
+Author: Scott Wood <scottwood@freescale.com>
+Date: Tue Mar 18 15:29:14 2008 -0500
+
+ Don't panic if a controller driver does ecc its own way.
+
+ Some hardware, such as the enhanced local bus controller used on some
+ mpc83xx chips, does ecc transparently when reading and writing data, rather
+ than providing a generic calculate/correct mechanism that can be exported to
+ the nand subsystem.
+
+ The subsystem should not BUG() when calculate, correct, or hwctl are
+ missing, if the methods that call them have been overridden.
+
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit e52b34d40a8a646e3d11638ea8797e96398dba13
+Author: Stefan Roese <sr@denx.de>
+Date: Thu Jan 10 18:47:33 2008 +0100
+
+ NAND: Make NAND driver less verbose per default
+
+ This patch turns off printing of bad blocks per default upon bootup.
+ This can always be shown via the "nand bad" command later.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit fe56a2772e5c59577df906163d0d4b29b056140e
+Author: Sergey Kubushyn <ksi@koi8.net>
+Date: Wed Jan 9 15:36:20 2008 +0100
+
+ NAND: Davinci driver updates
+
+ Here comes a trivial patch to cpu/arm926ejs/davinci/nand.c. Unfortunately I
+ don't have hardware handy so I can not test it at the moment but changes are
+ rather trivial so it should work. It would be nice if somebody with a
+ hardware checked it anyways.
+
+ Signed-off-by: Sergey Kubushyn <ksi@koi8.net>
+
+commit deac913effd8d80535c9ff4687b6fcdff540c554
+Author: Stefan Roese <sr@denx.de>
+Date: Sat Jan 5 16:50:32 2008 +0100
+
+ NAND: Fix compilation warning and small coding style issue
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit c568f77acdf896fc3dd6413ce53205b17ba809a3
+Author: Stefan Roese <sr@denx.de>
+Date: Sat Jan 5 16:49:37 2008 +0100
+
+ NAND: Update nand_spl driver to match updated nand subsystem
+
+ This patch changes the NAND booting driver nand_spl/nand_boot.c to match
+ the new infrastructure from the updated NAND subsystem. This NAND
+ subsystem was recently synced again with the Linux 2.6.22 MTD/NAND
+ subsystem.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 3df2ece0f0fbba47d27f02fff96c533732b98c14
+Author: Stefan Roese <sr@denx.de>
+Date: Sat Jan 5 16:47:58 2008 +0100
+
+ NAND: Update 4xx NDFC driver to match updated nand subsystem
+
+ This patch changes the 4xx NAND driver ndfc.c to match the new
+ infrastructure from the updated NAND subsystem. This NAND
+ subsystem was recently synced again with the Linux 2.6.22 MTD/NAND
+ subsystem.
+
+ Tested successfully on AMCC Sequoia and Bamboo.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 12072264528eba33737bc9674e19f0e925ffda23
+Author: Stefan Roese <sr@denx.de>
+Date: Sat Jan 5 16:43:25 2008 +0100
+
+ NAND: Change nand_wait_ready() to not call nand_wait()
+
+ This patch changes nand_wait_ready() to not just call nand_wait(),
+ since this will send a new command to the NAND chip. We just want to
+ wait for the chip to become ready here.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 9ad754fef5053144daed3b007adaf1c9bec654c9
+Author: William Juul <william.juul@datarespons.no>
+Date: Fri Dec 14 16:33:45 2007 +0100
+
+ make nand dump and nand dump.oob work
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 43ea36fb8fdcbc6e26f0caffe808c63633b18838
+Author: William Juul <william.juul@datarespons.no>
+Date: Mon Nov 19 14:46:00 2007 +0100
+
+ moving files from yaffs2/direct/ to yaffs2/ and deleting all symlinks
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+
+commit 98824ce3f95e6c4d08d439b779c0acb0048045a6
+Author: William Juul <william.juul@tandberg.com>
+Date: Tue Jun 10 16:18:13 2008 -0500
+
+ Clean out unneeded files
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+
+commit ec29a32b5a71b203f7d9087f1f4d786e7f13dd23
+Author: William Juul <william.juul@datarespons.no>
+Date: Fri Nov 16 08:44:27 2007 +0100
+
+ Create symlinks from yaffs2/direct to yaffs2
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+
+commit 90ef117b68387d66763291af0117677644166611
+Author: William Juul <william.juul@datarespons.no>
+Date: Thu Nov 15 12:23:57 2007 +0100
+
+ Incorporate yaffs2 into U-boot
+
+ To use YAFFS2 define CONFIG_YAFFS2
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 0e8cc8bd92257da2e1df88cbc985e166e472ce61
+Author: William Juul <william.juul@datarespons.no>
+Date: Thu Nov 15 11:13:05 2007 +0100
+
+ YAFFS2 import
+
+ Direct import of yaffs as a tarball as of 20071113 from their public
+ CVS-web at http://www.aleph1.co.uk/cgi-bin/viewcvs.cgi/yaffs2/
+
+ The code can also be imported on the command line with:
+ export CVSROOT=:pserver:anonymous@cvs.aleph1.co.uk:/home/aleph1/cvs cvs logon
+ (Hit return when asked for a password)
+ cvs checkout yaffs2
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+ Signed-off-by: Stig Olsen <stig.olsen@tandberg.com>
+
+commit 3043c045d5a9897faba7d5c7218c2f4d06cd0038
+Author: William Juul <william.juul@datarespons.no>
+Date: Wed Nov 14 14:28:11 2007 +0100
+
+ Whitespace cleanup and marking broken code.
+
+ Changes requested by maintainer Stefan Roese after
+ posting patch to U-boot mailing list.
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 5e1dae5c3db7f4026f31b6a2a81ecd9e9dee475f
+Author: William Juul <william.juul@datarespons.no>
+Date: Fri Nov 9 13:32:30 2007 +0100
+
+ Fixing coding style issues
+
+ - Fixing leading white spaces
+ - Fixing indentation where 4 spaces are used instead of tab
+ - Removing C++ comments (//), wherever I introduced them
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit 4cbb651b29cb64d378a06729970e1e153bb605b1
+Author: William Juul <william.juul@datarespons.no>
+Date: Thu Nov 8 10:39:53 2007 +0100
+
+ Remove white space at end.
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit cfa460adfdefcc30d104e1a9ee44994ee349bb7b
+Author: William Juul <william.juul@datarespons.no>
+Date: Wed Oct 31 13:53:06 2007 +0100
+
+ Update MTD to that of Linux 2.6.22.1
+
+ A lot changed in the Linux MTD code, since it was last ported from
+ Linux to U-Boot. This patch takes U-Boot NAND support to the level
+ of Linux 2.6.22.1 and will enable support for very large NAND devices
+ (4KB pages) and ease the compatibility between U-Boot and Linux
+ filesystems.
+
+ This patch is tested on two custom boards with PPC and ARM
+ processors running YAFFS in U-Boot and Linux using gcc-4.1.2
+ cross compilers.
+
+ MAKEALL ppc/arm has some issues:
+ * DOC/OneNand/nand_spl is not building (I have not tried porting
+ these parts, and since I do not have any HW and I am not familiar
+ with this code/HW I think its best left to someone else.)
+
+ Except for the issues mentioned above, I have ported all drivers
+ necessary to run MAKEALL ppc/arm without errors and warnings. Many
+ drivers were trivial to port, but some were not so trivial. The
+ following drivers must be examined carefully and maybe rewritten to
+ some degree:
+ cpu/ppc4xx/ndfc.c
+ cpu/arm926ejs/davinci/nand.c
+ board/delta/nand.c
+ board/zylonite/nand.c
+
+ Signed-off-by: William Juul <william.juul@tandberg.com>
+ Signed-off-by: Stig Olsen <stig.olsen@tandberg.com>
+ Signed-off-by: Scott Wood <scottwood@freescale.com>
+
+commit cd82919e6c8a73b363a26f34b734923844e52d1c
+Author: Wolfgang Denk <wd@denx.de>
+Date: Tue Aug 12 16:08:38 2008 +0200
+
+ Coding style cleanup, update CHANGELOG, prepare release
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 17e900b8c0f38d922da47073246219dce2a847f2
+Author: Wolfgang Denk <wd@denx.de>
+Date: Tue Aug 12 14:54:04 2008 +0200
+
+ MVBC_P: fix compile problem
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 52b047ae48219b59bebe37ba743ab103fd4f8316
+Author: Wolfgang Denk <wd@denx.de>
+Date: Tue Aug 12 12:10:11 2008 +0200
+
+ MPC8272ADS: fix build error: 'bd_t' has no member named 'pci_clk'
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit c9c101c660b3d1995045c61c7c6041f52b6cf335
+Author: Wolfgang Denk <wd@denx.de>
+Date: Tue Aug 12 00:36:53 2008 +0200
+
+ ads5121: fix compiler warnings (unused variables)
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 902ca09246039964d59bbcb519b1e1b5aed01308
+Author: Kumar Gala <galak@kernel.crashing.org>
+Date: Mon Aug 11 11:29:28 2008 -0500
+
+ 85xx: Rename CONFIG_NR_CPUS to CONFIG_NUM_CPUS
+
+ Use CONFIG_NUM_CPUS to match existing define used by 86xx.
+
+ Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
+ Acked-by: Jon Loeliger <jdl@freescale.com>
+
+commit 3216ca9692ff80d7c638723ef448f3d36301d9e7
+Author: Kumar Gala <galak@kernel.crashing.org>
+Date: Mon Aug 11 09:20:53 2008 -0500
+
+ Fix fallout from autostart revert
+
+ The autostart revert caused a bit of duplicated code as well as
+ code that was using images->autostart that needs to get removed so
+ we can build again.
+
+ Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
+
+commit 3cf8a234b8e8c02e4da1f23566043bc288b05220
+Author: Kumar Gala <galak@kernel.crashing.org>
+Date: Mon Aug 11 09:16:25 2008 -0500
+
+ Fix compile error related to r8a66597-hcd & usb
+
+ When building the 8544DS board we get this error:
+
+ In file included from r8a66597-hcd.c:22:
+ u-boot/include/usb.h:190:2: error: #error USB Lowlevel not defined
+ make[1]: *** [r8a66597-hcd.o] Error 1
+
+ The cleanest fix is to only build r8a66597-hcd.c if CONFIG_USB_R8A66597_HCD
+ is set.
+
+ Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
+
+commit 2d0daa03612338a813e3c9d22680e54eabfea378
+Author: Becky Bruce <becky.bruce@freescale.com>
+Date: Mon Aug 4 14:02:26 2008 -0500
+
+ POWERPC 86xx: Move BAT setup code to C
+
+ This is needed because we will be possibly be locating
+ devices at physical addresses above 32bits, and the asm
+ preprocessing does not appear to deal with ULL constants
+ properly. We now call write_bat in lib_ppc/bat_rw.c.
+
+ Signed-off-by: Becky Bruce <becky.bruce@freescale.com>
+ Acked-by: Jon Loeliger <jdl@freescale.com>
+
+commit 9de67149db576c91b9c2a0a182652331e7e44211
+Author: Becky Bruce <becky.bruce@freescale.com>
+Date: Mon Aug 4 14:01:53 2008 -0500
+
+ POWERPC: Add synchronization to write_bat in lib_ppc/bat_rw.c
+
+ Perform sync/isync as required by the architecture.
+
+ Signed-off-by: Becky Bruce <becky.bruce@freescale.com>
+ Acked-by: Jon Loeliger <jdl@freescale.com>
+
+commit 23f935c073e7578c6066804fd2f9ee116cae6ffe
+Author: Becky Bruce <becky.bruce@freescale.com>
+Date: Mon Aug 4 14:01:16 2008 -0500
+
+ POWERPC: 86xx - add missing CONFIG_HIGH_BATS to sbc8641d config
+
+ Signed-off-by: Becky Bruce <becky.bruce@freescale.com>
+ Acked-by: Jon Loeliger <jdl@freescale.com>
+
+commit 5276a3584d26a9533404f0ec00c3b61cf9a97939
+Author: Magnus Lilja <lilja.magnus@gmail.com>
+Date: Sun Aug 3 21:44:10 2008 +0200
+
+ i.MX31: Fix mx31_gpio_mux() function and MUX_-macros.
+
+ Correct the mx31_gpio_mux() function to allow changing all i.MX31 IOMUX
+ contacts instead of only the first 256 ones as is the case prior to
+ this patch.
+
+ Add missing MUX_* macros and update board files to use the new macros.
+
+ Signed-off-by: Magnus Lilja <lilja.magnus@gmail.com>
+
+commit b6b183c5b2fffd4c456b7e3fcb064cceb47fe7ac
+Author: Magnus Lilja <lilja.magnus@gmail.com>
+Date: Sun Aug 3 21:43:37 2008 +0200
+
+ i.MX31: Fix IOMUX related typos
+
+ Correct the names of some IOMUX macros.
+
+ Signed-off-by: Magnus Lilja <lilja.magnus@gmail.com>
+
+commit 4d57b0fb2927d4f50d834884b4ec4a7ca01708b0
+Author: Steve Sakoman <steve@sakoman.com>
+Date: Mon Aug 11 20:26:16 2008 +0200
+
+ OneNAND: Remove unused parameters to onenand_verify_page
+
+ The block and page parameters of onenand_verify_page() are not used. This causes a compiler error when CONFIG_MTD_ONENAND_VERIFY_WRITE is enabled.
+
+ Signed-off-by: Steve Sakoman <steve@sakoman.com>
+ Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
+
+commit e84d568fa2a9f4ce7888141e71676368ef6b3f25
+Author: Anatolij Gustschin <agust@denx.de>
+Date: Fri Aug 8 18:00:40 2008 +0200
+
+ video: fix bug in cfb_console code
+
+ FILL_15BIT_555RGB macro extension for pixel swapping
+ by commit bed53753dd1d7e6bcbea4339be0fb7760214cc35
+ introduced a bug in cfb_console:
+
+ Bitmaps with odd-numbered width won't be rendered
+ correctly and even U-Boot crashes are observed on
+ some platforms while repeated rendering of such
+ bitmaps with "bmp display". Also if a bitmap is
+ rendered to an odd-numbered x starting position,
+ the same problem occurs. This patch is an attempt
+ to fix it.
+
+ Signed-off-by: Anatolij Gustschin <agust@denx.de>
+
+commit d9015f6a50d7258125349ef5c2af836458a0029a
+Author: Anatolij Gustschin <agust@denx.de>
+Date: Fri Aug 8 18:00:39 2008 +0200
+
+ video: fix bug in logo_plot
+
+ If logo_plot() should ever be called with x starting
+ position other than zero and for pixel depths greater
+ than 8bpp, logo colors distortion will be observed.
+ This patch fixes the issue.
+
+ Signed-off-by: Anatolij Gustschin <agust@denx.de>
+
+commit 406819ae94f79f5b59e01d163380ca7d83709251
+Author: Wolfgang Denk <wd@denx.de>
+Date: Mon Aug 11 00:17:52 2008 +0200
+
+ MAINTAINERS: sort entries
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit cfc442d7913d4d1c3a9bf494f90c012c2f8c3bdc
+Author: Roy Zang <tie-fei.zang@freescale.com>
+Date: Thu Aug 7 18:19:28 2008 +0800
+
+ Add mpc7448hpc2 maintainer information
+
+ Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
+
+commit a9fe0c3e7ca48afa50d6a0db99fa91e7282d73d8
+Author: Gururaja Hebbar K R <gururajakr@sanyo.co.in>
+Date: Thu Aug 7 13:13:27 2008 +0530
+
+ common/cmd_load.c - Minor code & Coding Style cleanup
+
+ - os_data_header Variable is a carry over feature
+ & unused. So removed all instance of this variable
+ - Minor Code Style Update
+
+ Signed-off-by: Gururaja Hebbar <gururajakr@sanyo.co.in>
+ Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 0d28f34bbe56d0971bd603789dcc6fe7adf11f14
+Author: Magnus Lilja <lilja.magnus@gmail.com>
+Date: Wed Aug 6 19:32:33 2008 +0200
+
+ Update the U-Boot wiki URL.
+
+ Signed-off-by: Magnus Lilja <lilja.magnus@gmail.com>
+
+commit aa5ffa16d7e4c461b7b77bf8e79d2ef5638cf754
+Author: dirk.behme@googlemail.com <dirk.behme@googlemail.com>
+Date: Sun Aug 10 17:56:36 2008 +0200
+
+ OneNAND: Remove base address offset usage
+
+ While locally preparing some U-Boot patches for ARM based OMAP3 boards, some
+ using OneNAND and some using NAND, we found some differences in OneNAND and
+ NAND command address handling.
+
+ As this might confuse users (it already confused us), we like to align OneNAND
+ and NAND address handling.
+
+ The issue is that cmd_onenand.c subtracts the onenand base address from the
+ addresses you type into the u-boot command line so, unlike nand, you can't
+ use addresses relative to the start of the onenand part e.g. this won't work:
+
+ onenand read 82000000 280000 400000
+
+ you have to use:
+
+ onenand read 82000000 20280000 400000
+
+ Looking at recent git, the only board currently using OneNAND is Apollon, and
+ for this the OneNAND base address is 0 (apollon.h)
+
+ #define CFG_ONENAND_BASE 0x00000000
+
+ so patch below won't break any existing boards and will align OneNAND and NAND
+ handling on boards where OneNAND base address is != 0.
+
+ Signed-off-by: Steve Sakoman <sakoman@gmail.com>
+ Signed-off-by: Manikandan Pillai <mani.pillai@ti.com>
+ Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
+
+commit c11528083ef6e55e76df742228c26e39d151813d
+Author: Kumar Gala <galak@kernel.crashing.org>
+Date: Thu Aug 7 09:28:20 2008 -0500
+
+ mpc85xx: workaround old binutils bug
+
+ The recent change to move the .bss outside of the image gives older
+ binutils (ld from eldk4.1/binutils-2.16) some headache:
+
+ ppc_85xx-ld: u-boot: Not enough room for program headers (allocated 3, need 4)
+ ppc_85xx-ld: final link failed: Bad value
+
+ We workaround it by being explicit about the program headers and not
+ assigning the .bss to a program header.
+
+ Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
+
+commit 0bf202ec586d4466c900e987720fa635c594d689
+Author: Wolfgang Denk <wd@denx.de>
+Date: Sun Aug 10 01:26:26 2008 +0200
+
+ Revert "[new uImage] Add autostart flag to bootm_headers structure"
+
+ This reverts commit f5614e7926863bf0225ec860d9b319741a9c4004.
+
+ The commit was based on a misunderstanding of the (documented)
+ meaning of the 'autostart' environment variable. It might cause
+ boards to hang if 'autostart' was used, with the potential to brick
+ them. Go back to the documented behaviour.
+
+ Conflicts:
+
+ common/cmd_bootm.c
+ common/image.c
+ include/image.h
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 29f8f58ff40c67f7f2e11afd1715173094e52ac2
+Author: Wolfgang Denk <wd@denx.de>
+Date: Sat Aug 9 23:17:32 2008 +0200
+
+ TQM8xx{L,M}: try to normalize config files for TQM8xx? based board
+
+ - enable CFI driver where this was forgotten
+ - enable mtdparts support
+ - adjust default environment
+ etc.
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 41266c9b5a5f873df3ec891bb0907616958b5602
+Author: Peter Tyser <ptyser@xes-inc.com>
+Date: Tue Aug 5 10:51:57 2008 -0500
+
+ FIT: Fix handling of images without ramdisks
+
+ boot_get_ramdisk() should not treat the case when a FIT image does
+ not contain a ramdisk as an error.
+
+ Signed-off-by: Peter Tyser <ptyser@xes-inc.com>
+ Acked-by: Michal Simek <monstr@monstr.eu>
+
+commit f77d92a3f56d88e63cc02226a1204b3bdbac6961
+Author: Sergey Lapin <slapin@ossfans.org>
+Date: Sat Aug 9 01:39:09 2008 +0400
+
+ DataFlash: AT45DB021 fix and AT45DB081 support
+
+ Fix for page size of AT45DB021. Also adding bigger AT45DB081
+ which comes with some newer boards.
+
+ Signed-off-by: Sergey Lapin <slapin@ossfans.org>
+
+commit ba9324451b662dd393afa53e5cc36fc5d3d10966
+Author: Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+Date: Fri Aug 8 16:30:23 2008 +0900
+
+ sh: Update sh7763rdp config
+
+ Add sh_eth support to sh7763rdp.
+
+ Signed-off-by: Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+
+commit 21f971ec265f6042ec21636d55d06a6bc0751077
+Author: Wolfgang Denk <wd@denx.de>
+Date: Mon Jul 7 01:22:29 2008 +0200
+
+ TQM823L: re-enable logo support; update LCD_INFO text
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 3b8d17f0f082073346c0df017c9dfd6acdb40d6d
+Author: Wolfgang Denk <wd@denx.de>
+Date: Fri Aug 8 16:41:56 2008 +0200
+
+ TQM8xxL: fix support for second flash bank
+
+ When switching the TQM8xxL modules to use the CFI flash driver,
+ support for the second flash bank was broken because the CFI driver
+ did not support dynamically sized banks. This gets fixed now.
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 2a112b234d879f6390503a5f4e38246acce9d0b0
+Author: Wolfgang Denk <wd@denx.de>
+Date: Fri Aug 8 16:39:54 2008 +0200
+
+ CFI: allow for dynamically determined flash sizes and addresses
+
+ The CFI driver allowed only for static initializers in the
+ CFG_FLASH_BANKS_LIST definition, i. e. it did not allow to map
+ several flash banks contiguously if the bank sizes were not known in
+ advance, which kind of violates U-Boot's design philosophy.
+
+ (will be used for example by the TQM8xxL boards)
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit d9d78ee46d9a396d0a81d00c2b003a9bd32c2e61
+Author: Ben Warren <biggerbadderben@gmail.com>
+Date: Thu Aug 7 23:26:35 2008 -0700
+
+ QE UEC: Fix compiler warnings
+
+ Moved static functions earlier in file so forward declarations are not needed.
+
+ Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
+
+commit d5d28fe4aad5f4535400647a5617c11039506467
+Author: David Saada <David.Saada@ecitele.com>
+Date: Mon Mar 31 02:37:38 2008 -0700
+
+ QE UEC: Add MII Commands
+
+ Add MII commands to the UEC driver. Note that once a UEC device is selected,
+ any device on its MDIO bus can be addressed.
+
+ Signed-off-by: David Saada <david.saada@ecitele.com>
+ Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
+
+commit fd0f2f3796ff2a7a32d35deb1b7996e485849df7
+Author: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+Date: Wed Jul 9 21:07:38 2008 +0900
+
+ usb: add support for R8A66597 usb controller
+
+ add support for Renesas R8A66597 usb controller.
+ This patch supports USB Host mode.
+
+ Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ Signed-off-by: Markus Klotzbuecher <mk@denx.de>
+
+commit 1d10dcd041aaeae9fd7c821005692898a0303382
+Author: Hunter, Jon <jon-hunter@ti.com>
+Date: Sat Jul 26 18:59:16 2008 -0500
+
+ Add support for OMAP5912 and OMAP16xx to usbdcore_omap1510.c
+
+ Add support to drivers/usb/usbdcore_omap1510.c for OMAP5912 and OMAP16xx devices.
+
+ Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+ Signed-off-by: Markus Klotzbuecher <mk@denx.de>
+
+commit eab1007334b93a6209f1ec33615e26ef5311ede7
+Author: Steven A. Falco <sfalco@harris.com>
+Date: Wed Aug 6 15:42:52 2008 -0400
+
+ ppc4xx: Sequoia has two UARTs in "4-pin" mode. Configure the GPIOs as per schematic.
+
+ The Sequoia board has two UARTs in "4-pin" mode. This patch modifies the GPIO
+ configuration to match the schematic, and also sets the SDR0_PFC1 register to
+ select the corresponding mode for the UARTs.
+
+ Signed-off-by: Steven A. Falco <sfalco@harris.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 1318673045fe188c6e24c582b1e6efc00ae1c62c
+Author: Stefan Roese <sr@denx.de>
+Date: Wed Aug 6 14:06:03 2008 +0200
+
+ Fix merge problems
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit f2302d4430e7f3f48308d6a585320fe96af8afbd
+Author: Stefan Roese <sr@denx.de>
+Date: Wed Aug 6 14:05:38 2008 +0200
+
+ Fix merge problems
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 6689484ccd43189322aaa5a1c6cd02cdd511ad7d
+Author: Kenneth Johansson <kenneth@southpole.se>
+Date: Tue Jul 15 12:13:38 2008 +0200
+
+ mpc5121: Move iopin features from board specific to common files.
+
+ And in the process eliminate some duplicate register defines.
+
+ Signed-off-by: Kenneth Johansson <kenneth@southpole.se>
+
+commit ef11df6b66ecf5797e94ba322254b8fb7a4e2e12
+Author: John Rigby <jrigby@freescale.com>
+Date: Tue Aug 5 17:38:57 2008 -0600
+
+ mpc5121: squash some fdt fixup errors
+
+ On ADS5121 when booting linux the following errors are seen:
+ Unable to update property /soc5121@80000000:bus-frequency, err=FDT_ERR_NOTFOUND
+ Unable to update property /soc5121@80000000/ethernet@2800:local-mac-address, err=FDT_ERR_NOTFOUND
+ Unable to update property /soc5121@80000000/ethernet@2800:address, err=FDT_ERR_NOTFOUND
+
+ This is caused by ft_cpu_setup trying to deal with
+ both old and new soc node naming. This patch
+ fixes this by being smarter about what to
+ fixup.
+
+ Also do soc node fixups by compatible instead of by path.
+ A new board config called OF_SOC_COMPAT defined
+ to be "fsl,mpc5121-immr" replaces the old
+ OF_SOC node path that was defined to be "soc@80000000".
+
+ Old device trees still work, but the compatiblity
+ is conditional on CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
+ which is on by default in include/configs/ads5121.h.
+
+ Signed-off-by: John Rigby <jrigby@freescale.com>
+
+commit 81091f58f0c58ecd26c5b05de2ae20ca6cdb521c
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Sat Aug 2 23:48:30 2008 +0200
+
+ drivers/serial: Move conditional compilation to Makefile for CONFIG_* macros
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 4cd7e6528f61ec669755c3754bb4f9779874fab3
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Sat Aug 2 23:48:32 2008 +0200
+
+ nios2/sysid: fix printf warning
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 66da6fa0e35e7ee56628c85981709afe7180fc8e
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Sat Aug 2 23:48:33 2008 +0200
+
+ Fix remaining build issues with MPC8xx FADS boards.
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 81d3f1fdddafd1eb53bbca8739f488d417eb3dd2
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Sat Aug 2 23:48:31 2008 +0200
+
+ nios2: fix phys_addr_t and phys_size_t support
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 5fa62000db6d0b46ecdeadbeb50faf5197db49ef
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Sat Aug 2 23:48:34 2008 +0200
+
+ mvbc_p: Fix problem with '#if (CONFIG_CMD_KGDB)'
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit 1464eff77e7fdaed609ecf263a2423c9dcf96b1f
+Author: Mark Jackson <mpfj@mimc.co.uk>
+Date: Fri Aug 1 09:48:29 2008 +0100
+
+ Fix bitmap display for atmel lcd controller
+
+ The current lcd_display_bitmap() function does not work properly
+ for the Atmel LCD controller.
+
+ 2 fixes need to be done:-
+
+ (a) when setting the colour map, use the lcd_setcolreg() function
+ as provided by the Atmel driver
+ (b) the data is never actually written to the lcd framebuffer !!
+
+ Signed-off-by: Mark Jackson <mpfj@mimc.co.uk>
+
+commit 2a433c66b1e2770349fe4911be23c375f053ebd8
+Author: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+Date: Fri Aug 1 08:40:34 2008 +0200
+
+ qemu_mips: update README to follow qemu update about default machine
+
+ Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+
+commit ac169d645f5f0e0b9a232563099209e92a355d8e
+Author: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+Date: Thu Jul 31 19:53:21 2008 -0500
+
+ ColdFire: Fix compilation issue caused by a missing function
+
+ Implement usec2ticks() which is used by fsl_i2c.c in
+ lib_m68k/time.c
+
+ Signed-off-by: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+
+commit 01ae85b58b51d2fb1fac5b93095f6042cf48ae7b
+Author: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+Date: Thu Jul 31 19:53:06 2008 -0500
+
+ Fix compilation error for TASREG
+
+ TASREG is ColdFire platform, the include ppc4xx.h in
+ board/esd/common/flash.c causes conflict.
+
+ Signed-off-by: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+
+commit 35d3bd3cc35c508a6823dac77e0fd126808e4fc7
+Author: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+Date: Thu Jul 31 19:52:36 2008 -0500
+
+ Fix compilation error for MCF5275
+
+ Rename OBJ to COBJ in board/platform/Makefile
+
+ Signed-off-by: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+
+commit 5c40548f01218360a1f1395198c50ff45f3035b5
+Author: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+Date: Thu Jul 31 19:52:28 2008 -0500
+
+ Fix compile error caused by incorrect function return type
+
+ Rename int mii_init(void) to void mii_init(void) for idmr
+ ColdFire platform
+
+ Signed-off-by: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
+
+commit a58c78067c928976c082c758d3987e89ead5b191
+Author: Wolfgang Denk <wd@denx.de>
+Date: Fri Aug 1 12:06:22 2008 +0200
+
+ Fix build issues with MPC8xx FADS boards.
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
+commit 4b50cd12a3b3c644153c4cf393f4a4c12289e5aa
+Author: Wolfgang Denk <wd@denx.de>
+Date: Thu Jul 31 17:54:03 2008 +0200
+
+ Prepare v1.3.4-rc2: update CHANGELOG
+
+ Signed-off-by: Wolfgang Denk <wd@denx.de>
+
commit a48311557db6e7e9473a6163b44bb1e6c6ed64c4
Author: Mark Jackson <mpfj@mimc.co.uk>
Date: Thu Jul 31 16:09:00 2008 +0100
Signed-off-by: Wolfgang Denk <wd@denx.de>
+commit 9246f5ecfd353ae297a02ffd5328402acf16c9dd
+Author: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+Date: Wed Jul 30 12:39:28 2008 +0200
+
+ ppc4xx: ML507: Environment in flash and MTD Support
+
+ - Relocate the location of U-Boot in the flash
+ - Save the environment in one sector of the flash memory
+ - MTD Support
+
+ Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit a8a16af4d59d14cc1c1187c10aaad80d6b8394b5
+Author: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+Date: Tue Jul 29 17:16:10 2008 +0200
+
+ ppc4xx: ML507: Use of get_ram_size in board ml507
+
+ - Change suggested by WD
+
+ Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 01a004313c5ec2d128b611df4c208b1b0d3c3fb4
+Author: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+Date: Mon Jul 21 20:30:07 2008 +0200
+
+ ppc4xx: ML507: U-Boot in flash and System ACE
+
+ This patch allows booting from FLASH the ML507 board by Xilinx.
+ Previously, U-Boot needed to be loaded from JTAG or a Sytem ACE CF
+
+ Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
commit 09d318a8bb1444ec92e31cafcdba877eb9409e58
Author: Kumar Gala <galak@kernel.crashing.org>
Date: Tue Jul 29 12:23:49 2008 -0500
Signed-off-by: Stefan Roese <sr@denx.de>
+commit 60204d06ed9f8c2a67cc79eb67fd2b1d22bcbc8c
+Author: Stefan Roese <sr@denx.de>
+Date: Fri Jul 18 12:24:41 2008 +0200
+
+ ppc4xx: Minor coding style cleanup of Xilinx Virtex5 ml507 support
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 086511fc96a8a9bb56e5e19a3d84c40f4dba80cc
+Author: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+Date: Thu Jul 17 12:47:09 2008 +0200
+
+ ppc4xx: ML507 Board Support
+
+ The Xilinx ML507 Board is a Virtex 5 prototyping board that includes,
+ among others:
+ -Virtex 5 FX FPGA (With a ppc440x5 in it)
+ -256MB of SDRAM2
+ -32MB of Flash
+ -I2C Eeprom
+ -System ACE chip
+ -Serial ATA connectors
+ -RS232 Level Conversors
+ -Ethernet Transceiver
+
+ This patch gives support to a standard design produced by EDK for this
+ board: ppc440, uartlite, xilinx_int and flash
+
+ - Includes Changes propossed by Stefan Roese and Michal Simek
+
+ Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+ Acked-by: Stefan Roese <sr@denx.de>
+
+commit d865fd09809a3a18669f35f970781820af40e4de
+Author: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+Date: Thu Jul 17 11:44:12 2008 +0200
+
+ ppc4xx: CPU PPC440x5 on Virtex5 FX
+
+ -This patchs gives support for the embbedded ppc440
+ on the Virtex5 FPGAs
+ -interrupts.c divided in uic.c and interrupts.c
+ -xilinx_irq.c for xilinx interrupt controller
+ -Include modifications propossed by Stefan Roese
+
+ Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@uam.es>
+ Acked-by: Stefan Roese <sr@denx.de>
+
commit 340ccb260f21516be360745d5c5e3bd0657698df
Author: Sebastian Siewior <bigeasy@linutronix.de>
Date: Wed Jul 16 20:04:49 2008 +0200
Cc: Vasiliy Leonenko <vasiliy.leonenko@mail.ru>
Signed-off-by: Sebastian Siewior <bigeasy@linutronix.de>
+commit 11188d55bc16dd907451c00282e00a038f73dd62
+Author: Stefan Roese <sr@denx.de>
+Date: Thu Jul 17 10:40:51 2008 +0200
+
+ ppc4xx: Fix alphabetical order in 4xx Makefile part (redwood)
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
commit 699f05125509249072a0b865c8d35520d97cd501
Author: Wolfgang Denk <wd@denx.de>
Date: Tue Jul 15 22:22:44 2008 +0200
Signed-off-by: Stefan Roese <sr@denx.de>
+commit 69e2c6d0d13d7c8cf1612ac090bdc4c59ba6858e
+Author: Stefan Roese <sr@denx.de>
+Date: Fri Jul 11 13:10:56 2008 +0200
+
+ ppc4xx: Fix compile warning in 44x_spd_ddr2.c
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 6bd9138498c2e4f4f09190108b99157d1b2140b5
+Author: Stefan Roese <sr@denx.de>
+Date: Fri Jul 11 11:40:13 2008 +0200
+
+ ppc4xx: Fix small korat merge problem
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 1d0554736a0a1dd59718acda660871ce56b69e18
+Author: Stefan Roese <sr@denx.de>
+Date: Fri Jul 11 11:34:52 2008 +0200
+
+ ppc4xx: Some Rewood cleanups (coding style, leading white spaces)
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 3a82113ed5934d498f25080441a8261fc9454b15
+Author: Stefan Roese <sr@denx.de>
+Date: Thu Jul 10 16:37:09 2008 +0200
+
+ ppc4xx: Add 460SX UIC defines
+
+ Only the really needed ones are added (cascading and EMAC/MAL).
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 26173fc6f60521c2a8072f652f863617fc11ba9a
+Author: Stefan Roese <sr@denx.de>
+Date: Mon Jun 30 14:11:07 2008 +0200
+
+ ppc4xx: Continue cleanup of ppc440.h
+
+ This patch continues the ppc440.h cleanup by removing some of the unused
+ defines.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit d9056b7913ed6a228d2f33671d916efedee541dd
+Author: Stefan Roese <sr@denx.de>
+Date: Mon Jun 30 14:05:05 2008 +0200
+
+ ppc4xx: Cleanup Katmai & Yucca PCIe register usage
+
+ This patch cleans up the 440SPe PCIe register usage. Now only defines
+ from the include/asm-ppc/4xx_pcie.h are used.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 5de851403b01489b493fa83137ad990b8ce60d1c
+Author: Stefan Roese <sr@denx.de>
+Date: Thu Jun 26 17:36:39 2008 +0200
+
+ ppc4xx: Rework 440GX UIC handling
+
+ This patch reworks the 440GX interrupt handling so that the common 4xx
+ code can be used. The 440GX is an exception to all other 4xx variants
+ by having the cascading interrupt vectors not on UIC0 but on a special
+ UIC named UICB0 (UIC Base 0). With this patch now, U-Boot references
+ the 440GX UICB0 when UIC0 is selected. And the common 4xx interrupt
+ handling is simpler without any 440GX special cases.
+
+ Also some additional cleanup to cpu/ppc4xx/interrupt.c is done.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit d1631fe1a05b063ccaf62ea892a8887b829847d1
+Author: Stefan Roese <sr@denx.de>
+Date: Thu Jun 26 13:40:57 2008 +0200
+
+ ppc4xx: Consolidate PPC4xx UIC defines
+
+ This 2nd patch now removes all UIC mask bit definition. They should be
+ generated from the vectors by using the UIC_MASK() macro from now on.
+ This way only the vectors need to get defined for new PPC's.
+
+ Also only the really used interrupt vectors are now defined. This makes
+ definitions for new PPC versions easier and less error prone.
+
+ Another part of this patch is that the 4xx emac driver got a little
+ cleanup, since now the usage of the interrupts is clearer.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 4fb25a3db3b3839094aa9ab748efd7a95924690b
+Author: Stefan Roese <sr@denx.de>
+Date: Wed Jun 25 10:59:22 2008 +0200
+
+ ppc4xx: Consolidate PPC4xx UIC defines
+
+ This patch is the first step to consolidate the UIC related defines in the
+ 4xx headers. Move header from asm-ppc/ppc4xx-intvec.h to
+ asm-ppc/ppc4xx-uic.h as it will hold all UIC related defines in the next
+ steps.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 7ee2619c20ccecd57966d74d844e6329e141261c
+Author: Stefan Roese <sr@denx.de>
+Date: Tue Jun 24 17:18:50 2008 +0200
+
+ ppc4xx: Consolidate PPC4xx EBC defines
+
+ This patch removes all EBC related defines from the PPC4xx headers
+ ppc405.h and ppc440.h and introduces a new header
+
+ include/asm-ppc/ppc4xx-ebc.h
+
+ with all those defines.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit e321801bed5a6d896d298c00fd20046f039d5d66
+Author: Stefan Roese <sr@denx.de>
+Date: Thu Jul 10 13:52:44 2008 +0200
+
+ ppc4xx: Remove redundant ft_board_setup() functions from some 4xx boards
+
+ This patch removes some ft_board_setup() functions from some 4xx boards.
+ This can be done since we now have a default weak implementation for this
+ in cpu/ppc4xx/fdt.c. Only board in need for a different/custom
+ implementation like canyonlands need their own version.
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 08250eb2edbd96514d049602d9e134110ac3185f
+Author: Stefan Roese <sr@denx.de>
+Date: Thu Jul 10 15:32:32 2008 +0200
+
+ ppc4xx: Fix merge problems in 44x_spd_ddr2.c
+
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 1740c1bf40e3c6d03ac16c29943fdd9fc1e87038
+Author: Grant Erickson <gerickson@nuovations.com>
+Date: Tue Jul 8 08:35:00 2008 -0700
+
+ ppc4xx: Add MII mode support to the EMAC RGMII Bridge
+
+ This patch adds support for placing the RGMII bridge on the
+ PPC405EX(r) into MII/GMII mode and allows a board-specific
+ configuration to specify the bridge mode at compile-time.
+
+ Signed-off-by: Grant Erickson <gerickson@nuovations.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 2e2050842e731c823ce8d41fb0c15579eb70ced9
+Author: Grant Erickson <gerickson@nuovations.com>
+Date: Wed Jul 9 16:46:35 2008 -0700
+
+ ppc4xx: Add Mnemonics for AMCC/IBM DDR2 SDRAM Controller
+
+ This patch completes the preprocessor mneomics for the IBM DDR2 SDRAM
+ controller registers (MODT and INITPLR) used by the
+ PowerPC405EX(r). The MMODE and MEMODE registers are unified with their
+ peer values used for the INITPLR MR and EMR registers,
+ respectively. Finally, a spelling typo is correct (MANUEL to MANUAL).
+
+ With these mnemonics in place, the CFG_SDRAM0_* magic numbers for
+ Kilauea are replaced by equivalent mnemonics to make it easier to
+ compare and contrast other 405EX(r)-based boards (e.g. during board
+ bring-up).
+
+ Finally, unified the SDRAM controller register dump routine such that
+ it can be used across all processor variants that utilize the IBM DDR2
+ SDRAM controller core. It produces output of the form:
+
+ PPC4xx IBM DDR2 Register Dump:
+ ...
+ SDRAM_MB0CF[40] = 0x00006701
+ ...
+
+ which is '<mnemonic>[<DCR #>] = <value>'. The DCR number is included
+ since it is not uncommon that the DCR values in header files get mixed
+ up and it helps to validate, at a glance, they match what is printed
+ in the user manual.
+
+ Tested on:
+ AMCC Kilauea/Haleakala:
+ - NFS Linux Boot: PASSED
+ - NAND Linux Boot: PASSED
+
+ Signed-off-by: Grant Erickson <gerickson@nuovations.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit ad7382d828982e9c1bafc4313ef1b666f6145f58
+Author: Grant Erickson <gerickson@nuovations.com>
+Date: Wed Jul 9 16:31:59 2008 -0700
+
+ ppc4xx: Add AMCC/IBM DDR2 SDRAM ECC Field Mnemonics
+
+ Add additional DDR2 SDRAM memory controller DCR mneomnics, condition
+ revision ID DCR based on 405EX, and add field mnemonics for bus error
+ status and ECC error status registers.
+
+ Signed-off-by: Grant Erickson <gerickson@nuovations.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 103201731bd8e85404d0f51a5b4e8abd14c0b6c6
+Author: Grant Erickson <gerickson@nuovations.com>
+Date: Wed Jul 9 16:31:36 2008 -0700
+
+ ppc4xx: Add SDR0_SRST Mnemonics for the 405EX(r)
+
+ This patch adds bit field mnemonics for the 405EX(r) SDR0_SRST soft reset register.
+
+ Signed-off-by: Grant Erickson <gerickson@nuovations.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 5b457d00730d4aa0c6450d21a9104723e606fb98
+Author: Grant Erickson <gerickson@nuovations.com>
+Date: Wed Jul 9 11:55:46 2008 -0700
+
+ PPC4xx: Correct SDRAM_MCSTAT for PPC405EX(r)
+
+ While the PowerPC 405EX(r) shares in common the AMCC/IBM DDR2 SDRAM
+ controller core also used in the 440SP, 440SPe, 460EX, and 460GT, in
+ the 405EX(r), SDRAM_MCSTAT has a different DCR value.
+
+ Its present value on the 405EX(r) causes a read back of 0xFFFFFFFF
+ which causes SDRAM initialization to periodically fail since it can
+ prematurely indicate SDRAM ready status.
+
+ Signed-off-by: Grant Erickson <gerickson@nuovations.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 0ce5c8675bb2c61f1d71fb97f0bbe822663fb93d
+Author: Feng Kan <fkan@amcc.com>
+Date: Tue Jul 8 22:48:42 2008 -0700
+
+ ppc4xx: Initial framework of the AMCC PPC460SX redwood reference board.
+
+ Add AMCC Redwood reference board that uses the latest
+ PPC 464 CPU processor combined with a rich mix of peripheral
+ controllers. The board will support PCIe, mutiple Gig ethernet
+ ports, advanced hardware RAID assistance and IEEE 1588.
+
+ Signed-off-by: Feng Kan <fkan@amcc.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 96e5fc0e6a1861d0fea4efa3cd376df95a5b1b89
+Author: Feng Kan <fkan@amcc.com>
+Date: Tue Jul 8 22:48:07 2008 -0700
+
+ ppc4xx: Add initial 460SX reference board (redwood) config file and defines.
+
+ Signed-off-by: Feng Kan <fkan@amcc.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
+commit 7d30793685efcada183891c78fc892e6c9ba50c7
+Author: Feng Kan <fkan@amcc.com>
+Date: Tue Jul 8 22:47:31 2008 -0700
+
+ ppc4xx: Add initial 460SX defines for the cpu/ppc4xx directory.
+
+ Signed-off-by: Feng Kan <fkan@amcc.com>
+ Signed-off-by: Stefan Roese <sr@denx.de>
+
commit 9b55a2536919f4de1bb1044e6eb8262c2f53bc96
Author: Wolfgang Denk <wd@denx.de>
Date: Fri Jul 11 01:16:00 2008 +0200
Signed-off-by: Jens Gehrlein <sew_s@tqs.de>
Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
+commit 6324e5bec8825f7fee3026ffbd394454ae8b53fb
+Author: Christian Eggers <ceggers@gmx.de>
+Date: Wed May 21 21:29:10 2008 +0200
+
+ Fix endianess conversion in usb_ohci.c
+
+ Sorry, I forgot this line:
+
+ Signed-off-by: Christian Eggers <ceggers@gmx.de>
+
+ I think this must be swapped (result may be equal).
+
commit c918261c6d9f265f88baf70f8a73dfe6f0cb9596
Author: Christian Eggers <ceggers@gmx.de>
Date: Wed May 21 22:12:00 2008 +0200
E: stelian.pop@leadtechdesign.com
D: Atmel AT91CAP9ADK support
+N: Ricardo Ribalda Delgado
+E: ricardo.ribalda@uam.es
+D: PPC440x5 (Virtex5), ML507 Board, eeprom_simul, adt7460
+W: http://www.ii.uam.es/~rribalda
+
N: Stefan Roese
E: sr@denx.de
D: AMCC PPC4xx Support
MPC837xERDB MPC837x
-K�ri Dav��sson <kd@flaga.is>
+Kári Davíðsson <kd@flaga.is>
FLAGADM MPC823
ELPT860 MPC860T
+Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+
+ linkstation MPC8241
+
Dave Liu <daveliu@freescale.com>
MPC8315ERDB MPC8315
sbc8240 MPC8240
sbc405 PPC405GP
+Ricardo Ribalda <ricardo.ribalda@uam.es>
+
+ ml507 PPC440x5
+
Stefan Roese <sr@denx.de>
P3M7448 MPC7448
JSE PPC405GPr
+Roy Zang <tie-fei.zang@freescale.com>
+
+ mpc7448hpc2 MPC7448
+
John Zhan <zhanz@sinovee.com>
svm_sc8xx MPC8xx
-Guennadi Liakhovetski <g.liakhovetski@gmx.de>
-
- linkstation MPC8241
+Feng Kan <fkan@amcc.com>
+ redwood PPC4xx
-------------------------------------------------------------------------
Unknown / orphaned boards:
wepep250 xscale
-Marius Gr�ger <mag@sysgo.de>
+Marius Gröger <mag@sysgo.de>
impa7 ARM720T (EP7211)
ep7312 ARM720T (EP7312)
cerf250 xscale
-David M�ller <d.mueller@elsoft.ch>
+David Müller <d.mueller@elsoft.ch>
smdk2410 ARM920T
VCMA9 ARM920T
shannon SA1100
+Kyungmin Park <kyungmin.park@samsung.com>
+
+ apollon ARM1136EJS
+
Peter Pearse <peter.pearse@arm.com>
integratorcp All current ARM supplied & supported core modules
-see http://www.arm.com/products/DevTools/Hardware_Platforms.html
csb226 xscale
innokom xscale
+Michael Schwingen <michael@schwingen.org>
+
+ actux1 xscale
+ actux2 xscale
+ actux3 xscale
+ actux4 xscale
+
Andrea Scian <andrea.scian@dave-tech.it>
B2 ARM7TDMI (S3C44B0X)
omap2420h4 ARM1136EJS
-Kyungmin Park <kyungmin.park@samsung.com>
-
- apollon ARM1136EJS
-
-Alex Z�pke <azu@sysgo.de>
+Alex Züpke <azu@sysgo.de>
lart SA1100
dnp1110 SA1110
-Michael Schwingen <michael@schwingen.org>
-
- actux1 xscale
- actux2 xscale
- actux3 xscale
- actux4 xscale
-
-------------------------------------------------------------------------
Unknown / orphaned boards:
# Board CPU #
#########################################################################
-Daniel Engstr�m <daniel@omicron.se>
+Daniel Engström <daniel@omicron.se>
sc520_cdp x86
TASREG MCF5249
+Hayden Fraser <Hayden.Fraser@freescale.com>
+
+ M5253EVBE mcf52x2
+
TsiChung Liew <Tsi-Chung.Liew@freescale.com>
M52277EVB mcf5227x
M5235EVB mcf52x2
+ M5253DEMO mcf52x2
M5329EVB mcf532x
M5373EVB mcf532x
M54455EVB mcf5445x
M5475EVB mcf547x_8x
M5485EVB mcf547x_8x
-Hayden Fraser <Hayden.Fraser@freescale.com>
-
- M5253EVBE mcf52x2
-
#########################################################################
# AVR32 Systems: #
# #
# Board CPU #
#########################################################################
+Yusuke Goda <goda.yusuke@renesas.com>
+
+ MIGO-R SH7722
+
Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
MS7750SE SH7750
MS7720SE SH7720
-Yusuke Goda <goda.yusuke@renesas.com>
-
- MIGO-R SH7722
-
#########################################################################
# Blackfin Systems: #
# #
MIP405T \
ML2 \
ml300 \
+ ml507 \
+ ml507_flash \
ocotea \
OCRTC \
ORSG \
PPChameleonEVB \
quad100hd \
rainier \
+ redwood \
sbc405 \
sc3 \
sequoia \
M52277EVB \
M5235EVB \
M5249EVB \
+ M5253DEMO \
M5253EVBE \
M5271EVB \
M5272C3 \
M5282EVB \
M5329AFEE \
M5373EVB \
+ M54451EVB \
M54455EVB \
M5475AFE \
M5485AFE \
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
-EXTRAVERSION = -rc2
+EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h
endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
- fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
+ fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += drivers/bios_emulator/libatibiosemu.a
TAG_SUBDIRS += fs/fat
TAG_SUBDIRS += fs/fdos
TAG_SUBDIRS += fs/jffs2
+TAG_SUBDIRS += fs/yaffs2
TAG_SUBDIRS += net
TAG_SUBDIRS += disk
TAG_SUBDIRS += common
git log --no-merges U-Boot-1_1_5.. | \
unexpand -a | sed -e 's/\s\s*$$//' > $@
+include/license.h: tools/bin2header COPYING
+ cat COPYING | gzip -9 -c | ./tools/bin2header license_gzip > include/license.h
#########################################################################
unconfig:
ml300_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx ml300 xilinx
+ml507_flash_config: unconfig
+ @mkdir -p $(obj)include $(obj)board/xilinx/ml507
+ @cp $(obj)board/xilinx/ml507/u-boot-rom.lds $(obj)board/xilinx/ml507/u-boot.lds
+ @echo "TEXT_BASE = 0xFE360000" > $(obj)board/xilinx/ml507/config.tmp
+ @$(MKCONFIG) $(@:_flash_config=) ppc ppc4xx ml507 xilinx
+
+ml507_config: unconfig
+ @mkdir -p $(obj)include $(obj)board/xilinx/ml507
+ @cp $(obj)board/xilinx/ml507/u-boot-ram.lds $(obj)board/xilinx/ml507/u-boot.lds
+ @$(MKCONFIG) $(@:_config=) ppc ppc4xx ml507 xilinx
+
ocotea_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx ocotea amcc
quad100hd_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx quad100hd
+redwood_config: unconfig
+ @$(MKCONFIG) $(@:_config=) ppc ppc4xx redwood amcc
+
sbc405_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx sbc405
M5249EVB_config : unconfig
@$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5249evb freescale
+M5253DEMO_config : unconfig
+ @$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5253demo freescale
+
M5253EVBE_config : unconfig
@$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5253evbe freescale
@$(MKCONFIG) $(@:_config=) m68k mcf52x2 idmr
M5271EVB_config : unconfig
- @$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5271evb
+ @$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5271evb freescale
M5272C3_config : unconfig
- @$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5272c3
+ @$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5272c3 freescale
M5275EVB_config : unconfig
@$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5275evb freescale
M5282EVB_config : unconfig
- @$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5282evb
+ @$(MKCONFIG) $(@:_config=) m68k mcf52x2 m5282evb freescale
M5329AFEE_config \
M5329BFEE_config : unconfig
fi
@$(MKCONFIG) -a M5373EVB m68k mcf532x m5373evb freescale
+M54451EVB_config \
+M54451EVB_spansion_config \
+M54451EVB_stmicro_config : unconfig
+ @case "$@" in \
+ M54451EVB_config) FLASH=SPANSION;; \
+ M54451EVB_spansion_config) FLASH=SPANSION;; \
+ M54451EVB_stmicro_config) FLASH=STMICRO;; \
+ esac; \
+ if [ "$${FLASH}" = "SPANSION" ] ; then \
+ echo "#define CFG_SPANSION_BOOT" >> $(obj)include/config.h ; \
+ echo "TEXT_BASE = 0x00000000" > $(obj)board/freescale/m54451evb/config.tmp ; \
+ cp $(obj)board/freescale/m54451evb/u-boot.spa $(obj)board/freescale/m54451evb/u-boot.lds ; \
+ $(XECHO) "... with SPANSION boot..." ; \
+ fi; \
+ if [ "$${FLASH}" = "STMICRO" ] ; then \
+ echo "#define CONFIG_CF_SBF" >> $(obj)include/config.h ; \
+ echo "#define CFG_STMICRO_BOOT" >> $(obj)include/config.h ; \
+ echo "TEXT_BASE = 0x47E00000" > $(obj)board/freescale/m54451evb/config.tmp ; \
+ cp $(obj)board/freescale/m54451evb/u-boot.stm $(obj)board/freescale/m54451evb/u-boot.lds ; \
+ $(XECHO) "... with ST Micro boot..." ; \
+ fi; \
+ echo "#define CFG_INPUT_CLKSRC 24000000" >> $(obj)include/config.h ;
+ @$(MKCONFIG) -a M54451EVB m68k mcf5445x m54451evb freescale
+
M54455EVB_config \
M54455EVB_atmel_config \
M54455EVB_intel_config \
M54455EVB_a33_config \
M54455EVB_a66_config \
M54455EVB_i33_config \
-M54455EVB_i66_config : unconfig
+M54455EVB_i66_config \
+M54455EVB_stm33_config : unconfig
@case "$@" in \
M54455EVB_config) FLASH=ATMEL; FREQ=33333333;; \
M54455EVB_atmel_config) FLASH=ATMEL; FREQ=33333333;; \
M54455EVB_a66_config) FLASH=ATMEL; FREQ=66666666;; \
M54455EVB_i33_config) FLASH=INTEL; FREQ=33333333;; \
M54455EVB_i66_config) FLASH=INTEL; FREQ=66666666;; \
+ M54455EVB_stm33_config) FLASH=STMICRO; FREQ=33333333;; \
esac; \
if [ "$${FLASH}" = "INTEL" ] ; then \
- echo "#undef CFG_ATMEL_BOOT" >> $(obj)include/config.h ; \
+ echo "#define CFG_INTEL_BOOT" >> $(obj)include/config.h ; \
echo "TEXT_BASE = 0x00000000" > $(obj)board/freescale/m54455evb/config.tmp ; \
cp $(obj)board/freescale/m54455evb/u-boot.int $(obj)board/freescale/m54455evb/u-boot.lds ; \
$(XECHO) "... with INTEL boot..." ; \
- else \
+ fi; \
+ if [ "$${FLASH}" = "ATMEL" ] ; then \
echo "#define CFG_ATMEL_BOOT" >> $(obj)include/config.h ; \
echo "TEXT_BASE = 0x04000000" > $(obj)board/freescale/m54455evb/config.tmp ; \
cp $(obj)board/freescale/m54455evb/u-boot.atm $(obj)board/freescale/m54455evb/u-boot.lds ; \
$(XECHO) "... with ATMEL boot..." ; \
fi; \
+ if [ "$${FLASH}" = "STMICRO" ] ; then \
+ echo "#define CONFIG_CF_SBF" >> $(obj)include/config.h ; \
+ echo "#define CFG_STMICRO_BOOT" >> $(obj)include/config.h ; \
+ echo "TEXT_BASE = 0x4FE00000" > $(obj)board/freescale/m54455evb/config.tmp ; \
+ cp $(obj)board/freescale/m54455evb/u-boot.stm $(obj)board/freescale/m54455evb/u-boot.lds ; \
+ $(XECHO) "... with ST Micro boot..." ; \
+ fi; \
echo "#define CFG_INPUT_CLKSRC $${FREQ}" >> $(obj)include/config.h ; \
$(XECHO) "... with $${FREQ}Hz input clock"
@$(MKCONFIG) -a M54455EVB m68k mcf5445x m54455evb freescale
#########################################################################
MPC8313ERDB_33_config \
-MPC8313ERDB_66_config: unconfig
+MPC8313ERDB_66_config \
+MPC8313ERDB_NAND_33_config \
+MPC8313ERDB_NAND_66_config: unconfig
@mkdir -p $(obj)include
+ @mkdir -p $(obj)board/freescale/mpc8313erdb
@if [ "$(findstring _33_,$@)" ] ; then \
$(XECHO) -n "...33M ..." ; \
echo "#define CFG_33MHZ" >>$(obj)include/config.h ; \
if [ "$(findstring _66_,$@)" ] ; then \
$(XECHO) -n "...66M..." ; \
echo "#define CFG_66MHZ" >>$(obj)include/config.h ; \
+ fi ; \
+ if [ "$(findstring _NAND_,$@)" ] ; then \
+ $(XECHO) -n "...NAND..." ; \
+ echo "TEXT_BASE = 0x00100000" > $(obj)/board/freescale/mpc8313erdb/config.tmp ; \
+ echo "#define CONFIG_NAND_U_BOOT" >>$(obj)include/config.h ; \
fi ;
@$(MKCONFIG) -a MPC8313ERDB ppc mpc83xx mpc8313erdb freescale
@$(MKCONFIG) $(@:_config=) arm arm920t at91rm9200dk atmel at91rm9200
at91sam9261ek_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm arm926ejs at91sam9261ek atmel at91sam9
+ @$(MKCONFIG) $(@:_config=) arm arm926ejs at91sam9261ek atmel at91
at91sam9263ek_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm arm926ejs at91sam9263ek atmel at91sam9
+ @$(MKCONFIG) $(@:_config=) arm arm926ejs at91sam9263ek atmel at91
at91sam9rlek_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm arm926ejs at91sam9rlek atmel at91sam9
+ @$(MKCONFIG) $(@:_config=) arm arm926ejs at91sam9rlek atmel at91
cmc_pu2_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t cmc_pu2 NULL at91rm9200
#########################################################################
at91cap9adk_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm arm926ejs at91cap9adk atmel at91sam9
+ @$(MKCONFIG) $(@:_config=) arm arm926ejs at91cap9adk atmel at91
at91sam9260ek_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm arm926ejs at91sam9260ek atmel at91sam9
+ @$(MKCONFIG) $(@:_config=) arm arm926ejs at91sam9260ek atmel at91
########################################################################
## ARM Integrator boards - see doc/README-integrator for more info.
@$(MKCONFIG) $(@:_config=) arm arm1136 imx31_phycore NULL mx31
mx31ads_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm arm1136 mx31ads NULL mx31
+ @$(MKCONFIG) $(@:_config=) arm arm1136 mx31ads freescale mx31
omap2420h4_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm1136 omap2420h4 NULL omap24xx
- create ARMBoot project (http://sourceforge.net/projects/armboot)
- add other CPU families (starting with ARM)
- create U-Boot project (http://sourceforge.net/projects/u-boot)
-- current project page: see http://www.denx.de/wiki/UBoot
+- current project page: see http://www.denx.de/wiki/U-Boot
Names and Spelling:
Define if the flash driver uses extra elements in the
common flash structure for storing flash geometry.
-- CFG_FLASH_CFI_DRIVER
+- CONFIG_FLASH_CFI_DRIVER
This option also enables the building of the cfi_flash driver
in the drivers directory
Patches shall be sent to the u-boot-users mailing list.
-Please see http://www.denx.de/wiki/UBoot/Patches for details.
+Please see http://www.denx.de/wiki/U-Boot/Patches for details.
When you send a patch, please include the following information with
it:
#define DP(x)
#endif
-extern void flush_data_cache (void);
-extern void invalidate_l1_instruction_cache (void);
-
/* ------------------------------------------------------------------------- */
/* this is the current GT register space location */
my_remap_gt_regs_bootm (CFG_GT_REGS, BRIDGE_REG_BASE_BOOTM);
icache_disable ();
- invalidate_l1_instruction_cache ();
- flush_data_cache ();
dcache_disable ();
}
#define DP(x)
#endif
-extern void flush_data_cache (void);
-extern void invalidate_l1_instruction_cache (void);
-
/* ------------------------------------------------------------------------- */
/* this is the current GT register space location */
my_remap_gt_regs_bootm (CFG_GT_REGS, BRIDGE_REG_BASE_BOOTM);
icache_disable ();
- invalidate_l1_instruction_cache ();
- flush_data_cache ();
dcache_disable ();
}
LIB = $(obj)lib$(BOARD).a
-COBJS-y := $(BOARD).o iopin.o
+COBJS-y := $(BOARD).o
COBJS-${CONFIG_FSL_DIU_FB} += ads5121_diu.o
COBJS-${CONFIG_FSL_DIU_FB} += ../freescale/common/fsl_diu_fb.o
COBJS-${CONFIG_FSL_DIU_FB} += ../freescale/common/fsl_logo_bmp.o
#include <common.h>
#include <mpc512x.h>
-#include "iopin.h"
#include <asm/bitops.h>
#include <command.h>
#include <fdt_support.h>
#ifdef CONFIG_MISC_INIT_R
#include <i2c.h>
#endif
-#include "iopin.h" /* for iopin_initialize() prototype */
/* Clocks in use */
#define SCCR1_CLOCKS_EN (CLOCK_SCCR1_CFG_EN | \
u32 i;
/* Initialize IO Control */
- im->io_ctrl.regs[MEM_IDX] = IOCTRL_MUX_DDR;
+ im->io_ctrl.regs[IOCTL_MEM/4] = IOCTRL_MUX_DDR;
/* Initialize DDR Local Window */
im->sysconf.ddrlaw.bar = CFG_DDR_BASE & 0xFFFFF000;
return 0;
}
+static iopin_t ioregs_init[] = {
+ /* FUNC1=FEC_RX_DV Sets Next 3 to FEC pads */
+ {
+ IOCTL_SPDIF_TXCLK, 3, 0,
+ IO_PIN_FMUX(1) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
+ IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
+ },
+ /* Set highest Slew on 9 PATA pins */
+ {
+ IOCTL_PATA_CE1, 9, 1,
+ IO_PIN_FMUX(0) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
+ IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
+ },
+ /* FUNC1=FEC_COL Sets Next 15 to FEC pads */
+ {
+ IOCTL_PSC0_0, 15, 0,
+ IO_PIN_FMUX(1) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
+ IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
+ },
+ /* FUNC1=SPDIF_TXCLK */
+ {
+ IOCTL_LPC_CS1, 1, 0,
+ IO_PIN_FMUX(1) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
+ IO_PIN_PUE(0) | IO_PIN_ST(1) | IO_PIN_DS(3)
+ },
+ /* FUNC2=SPDIF_TX and sets Next pin to SPDIF_RX */
+ {
+ IOCTL_I2C1_SCL, 2, 0,
+ IO_PIN_FMUX(2) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
+ IO_PIN_PUE(0) | IO_PIN_ST(1) | IO_PIN_DS(3)
+ },
+ /* FUNC2=DIU CLK */
+ {
+ IOCTL_PSC6_0, 1, 0,
+ IO_PIN_FMUX(2) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
+ IO_PIN_PUE(0) | IO_PIN_ST(1) | IO_PIN_DS(3)
+ },
+ /* FUNC2=DIU_HSYNC */
+ {
+ IOCTL_PSC6_1, 1, 0,
+ IO_PIN_FMUX(2) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
+ IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
+ },
+ /* FUNC2=DIUVSYNC Sets Next 26 to DIU Pads */
+ {
+ IOCTL_PSC6_4, 26, 0,
+ IO_PIN_FMUX(2) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
+ IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
+ }
+};
int checkboard (void)
{
printf ("Board: ADS5121 rev. 0x%04x (CPLD rev. 0x%02x)\n",
brd_rev, cpld_rev);
/* initialize function mux & slew rate IO inter alia on IO Pins */
- iopin_initialize();
+
+
+ iopin_initialize(ioregs_init, sizeof(ioregs_init) / sizeof(ioregs_init[0]));
return 0;
}
+++ /dev/null
-/*
- * (C) Copyright 2008
- * Martha J Marx, Silicon Turnkey Express, mmarx@silicontkx.com
- * mpc512x I/O pin/pad initialization for the ADS5121 board
- * 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 <linux/types.h>
-#include "iopin.h"
-
-/* IO pin fields */
-#define IO_PIN_FMUX(v) ((v) << 7) /* pin function */
-#define IO_PIN_HOLD(v) ((v) << 5) /* hold time, pci only */
-#define IO_PIN_PUD(v) ((v) << 4) /* if PUE, 0=pull-down, 1=pull-up */
-#define IO_PIN_PUE(v) ((v) << 3) /* pull up/down enable */
-#define IO_PIN_ST(v) ((v) << 2) /* schmitt trigger */
-#define IO_PIN_DS(v) ((v)) /* slew rate */
-
-static struct iopin_t {
- int p_offset; /* offset from IOCTL_MEM_OFFSET */
- int nr_pins; /* number of pins to set this way */
- int bit_or; /* or in the value instead of overwrite */
- u_long val; /* value to write or or */
-} ioregs_init[] = {
- /* FUNC1=FEC_RX_DV Sets Next 3 to FEC pads */
- {
- IOCTL_SPDIF_TXCLK, 3, 0,
- IO_PIN_FMUX(1) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
- IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
- },
- /* Set highest Slew on 9 PATA pins */
- {
- IOCTL_PATA_CE1, 9, 1,
- IO_PIN_FMUX(0) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
- IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
- },
- /* FUNC1=FEC_COL Sets Next 15 to FEC pads */
- {
- IOCTL_PSC0_0, 15, 0,
- IO_PIN_FMUX(1) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
- IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
- },
- /* FUNC1=SPDIF_TXCLK */
- {
- IOCTL_LPC_CS1, 1, 0,
- IO_PIN_FMUX(1) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
- IO_PIN_PUE(0) | IO_PIN_ST(1) | IO_PIN_DS(3)
- },
- /* FUNC2=SPDIF_TX and sets Next pin to SPDIF_RX */
- {
- IOCTL_I2C1_SCL, 2, 0,
- IO_PIN_FMUX(2) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
- IO_PIN_PUE(0) | IO_PIN_ST(1) | IO_PIN_DS(3)
- },
- /* FUNC2=DIU CLK */
- {
- IOCTL_PSC6_0, 1, 0,
- IO_PIN_FMUX(2) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
- IO_PIN_PUE(0) | IO_PIN_ST(1) | IO_PIN_DS(3)
- },
- /* FUNC2=DIU_HSYNC */
- {
- IOCTL_PSC6_1, 1, 0,
- IO_PIN_FMUX(2) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
- IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
- },
- /* FUNC2=DIUVSYNC Sets Next 26 to DIU Pads */
- {
- IOCTL_PSC6_4, 26, 0,
- IO_PIN_FMUX(2) | IO_PIN_HOLD(0) | IO_PIN_PUD(0) |
- IO_PIN_PUE(0) | IO_PIN_ST(0) | IO_PIN_DS(3)
- }
-};
-
-void iopin_initialize(void)
-{
- short i, j, n, p;
- u_long *reg;
- immap_t *im = (immap_t *)CFG_IMMR;
-
- reg = (u_long *)&(im->io_ctrl.regs[0]);
-
- if (sizeof(ioregs_init) == 0)
- return;
-
- n = sizeof(ioregs_init) / sizeof(ioregs_init[0]);
-
- for (i = 0; i < n; i++) {
- for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long);
- p < ioregs_init[i].nr_pins; p++, j++) {
- if (ioregs_init[i].bit_or)
- reg[j] |= ioregs_init[i].val;
- else
- reg[j] = ioregs_init[i].val;
- }
- }
- return;
-}
+++ /dev/null
-/*
- * (C) Copyright 2008
- * Martha J Marx, Silicon Turnkey Express, mmarx@silicontkx.com
- * mpc512x I/O pin/pad initialization for the ADS5121 board
- * 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
- */
-
-#define IOCTL_MEM 0x000
-#define IOCTL_GP 0x004
-#define IOCTL_LPC_CLK 0x008
-#define IOCTL_LPC_OE 0x00C
-#define IOCTL_LPC_RWB 0x010
-#define IOCTL_LPC_ACK 0x014
-#define IOCTL_LPC_CS0 0x018
-#define IOCTL_NFC_CE0 0x01C
-#define IOCTL_LPC_CS1 0x020
-#define IOCTL_LPC_CS2 0x024
-#define IOCTL_LPC_AX03 0x028
-#define IOCTL_EMB_AX02 0x02C
-#define IOCTL_EMB_AX01 0x030
-#define IOCTL_EMB_AX00 0x034
-#define IOCTL_EMB_AD31 0x038
-#define IOCTL_EMB_AD30 0x03C
-#define IOCTL_EMB_AD29 0x040
-#define IOCTL_EMB_AD28 0x044
-#define IOCTL_EMB_AD27 0x048
-#define IOCTL_EMB_AD26 0x04C
-#define IOCTL_EMB_AD25 0x050
-#define IOCTL_EMB_AD24 0x054
-#define IOCTL_EMB_AD23 0x058
-#define IOCTL_EMB_AD22 0x05C
-#define IOCTL_EMB_AD21 0x060
-#define IOCTL_EMB_AD20 0x064
-#define IOCTL_EMB_AD19 0x068
-#define IOCTL_EMB_AD18 0x06C
-#define IOCTL_EMB_AD17 0x070
-#define IOCTL_EMB_AD16 0x074
-#define IOCTL_EMB_AD15 0x078
-#define IOCTL_EMB_AD14 0x07C
-#define IOCTL_EMB_AD13 0x080
-#define IOCTL_EMB_AD12 0x084
-#define IOCTL_EMB_AD11 0x088
-#define IOCTL_EMB_AD10 0x08C
-#define IOCTL_EMB_AD09 0x090
-#define IOCTL_EMB_AD08 0x094
-#define IOCTL_EMB_AD07 0x098
-#define IOCTL_EMB_AD06 0x09C
-#define IOCTL_EMB_AD05 0x0A0
-#define IOCTL_EMB_AD04 0x0A4
-#define IOCTL_EMB_AD03 0x0A8
-#define IOCTL_EMB_AD02 0x0AC
-#define IOCTL_EMB_AD01 0x0B0
-#define IOCTL_EMB_AD00 0x0B4
-#define IOCTL_PATA_CE1 0x0B8
-#define IOCTL_PATA_CE2 0x0BC
-#define IOCTL_PATA_ISOLATE 0x0C0
-#define IOCTL_PATA_IOR 0x0C4
-#define IOCTL_PATA_IOW 0x0C8
-#define IOCTL_PATA_IOCHRDY 0x0CC
-#define IOCTL_PATA_INTRQ 0x0D0
-#define IOCTL_PATA_DRQ 0x0D4
-#define IOCTL_PATA_DACK 0x0D8
-#define IOCTL_NFC_WP 0x0DC
-#define IOCTL_NFC_RB 0x0E0
-#define IOCTL_NFC_ALE 0x0E4
-#define IOCTL_NFC_CLE 0x0E8
-#define IOCTL_NFC_WE 0x0EC
-#define IOCTL_NFC_RE 0x0F0
-#define IOCTL_PCI_AD31 0x0F4
-#define IOCTL_PCI_AD30 0x0F8
-#define IOCTL_PCI_AD29 0x0FC
-#define IOCTL_PCI_AD28 0x100
-#define IOCTL_PCI_AD27 0x104
-#define IOCTL_PCI_AD26 0x108
-#define IOCTL_PCI_AD25 0x10C
-#define IOCTL_PCI_AD24 0x110
-#define IOCTL_PCI_AD23 0x114
-#define IOCTL_PCI_AD22 0x118
-#define IOCTL_PCI_AD21 0x11C
-#define IOCTL_PCI_AD20 0x120
-#define IOCTL_PCI_AD19 0x124
-#define IOCTL_PCI_AD18 0x128
-#define IOCTL_PCI_AD17 0x12C
-#define IOCTL_PCI_AD16 0x130
-#define IOCTL_PCI_AD15 0x134
-#define IOCTL_PCI_AD14 0x138
-#define IOCTL_PCI_AD13 0x13C
-#define IOCTL_PCI_AD12 0x140
-#define IOCTL_PCI_AD11 0x144
-#define IOCTL_PCI_AD10 0x148
-#define IOCTL_PCI_AD09 0x14C
-#define IOCTL_PCI_AD08 0x150
-#define IOCTL_PCI_AD07 0x154
-#define IOCTL_PCI_AD06 0x158
-#define IOCTL_PCI_AD05 0x15C
-#define IOCTL_PCI_AD04 0x160
-#define IOCTL_PCI_AD03 0x164
-#define IOCTL_PCI_AD02 0x168
-#define IOCTL_PCI_AD01 0x16C
-#define IOCTL_PCI_AD00 0x170
-#define IOCTL_PCI_CBE0 0x174
-#define IOCTL_PCI_CBE1 0x178
-#define IOCTL_PCI_CBE2 0x17C
-#define IOCTL_PCI_CBE3 0x180
-#define IOCTL_PCI_GNT2 0x184
-#define IOCTL_PCI_REQ2 0x188
-#define IOCTL_PCI_GNT1 0x18C
-#define IOCTL_PCI_REQ1 0x190
-#define IOCTL_PCI_GNT0 0x194
-#define IOCTL_PCI_REQ0 0x198
-#define IOCTL_PCI_INTA 0x19C
-#define IOCTL_PCI_CLK 0x1A0
-#define IOCTL_PCI_RST_OUT 0x1A4
-#define IOCTL_PCI_FRAME 0x1A8
-#define IOCTL_PCI_IDSEL 0x1AC
-#define IOCTL_PCI_DEVSEL 0x1B0
-#define IOCTL_PCI_IRDY 0x1B4
-#define IOCTL_PCI_TRDY 0x1B8
-#define IOCTL_PCI_STOP 0x1BC
-#define IOCTL_PCI_PAR 0x1C0
-#define IOCTL_PCI_PERR 0x1C4
-#define IOCTL_PCI_SERR 0x1C8
-#define IOCTL_SPDIF_TXCLK 0x1CC
-#define IOCTL_SPDIF_TX 0x1D0
-#define IOCTL_SPDIF_RX 0x1D4
-#define IOCTL_I2C0_SCL 0x1D8
-#define IOCTL_I2C0_SDA 0x1DC
-#define IOCTL_I2C1_SCL 0x1E0
-#define IOCTL_I2C1_SDA 0x1E4
-#define IOCTL_I2C2_SCL 0x1E8
-#define IOCTL_I2C2_SDA 0x1EC
-#define IOCTL_IRQ0 0x1F0
-#define IOCTL_IRQ1 0x1F4
-#define IOCTL_CAN1_TX 0x1F8
-#define IOCTL_CAN2_TX 0x1FC
-#define IOCTL_J1850_TX 0x200
-#define IOCTL_J1850_RX 0x204
-#define IOCTL_PSC_MCLK_IN 0x208
-#define IOCTL_PSC0_0 0x20C
-#define IOCTL_PSC0_1 0x210
-#define IOCTL_PSC0_2 0x214
-#define IOCTL_PSC0_3 0x218
-#define IOCTL_PSC0_4 0x21C
-#define IOCTL_PSC1_0 0x220
-#define IOCTL_PSC1_1 0x224
-#define IOCTL_PSC1_2 0x228
-#define IOCTL_PSC1_3 0x22C
-#define IOCTL_PSC1_4 0x230
-#define IOCTL_PSC2_0 0x234
-#define IOCTL_PSC2_1 0x238
-#define IOCTL_PSC2_2 0x23C
-#define IOCTL_PSC2_3 0x240
-#define IOCTL_PSC2_4 0x244
-#define IOCTL_PSC3_0 0x248
-#define IOCTL_PSC3_1 0x24C
-#define IOCTL_PSC3_2 0x250
-#define IOCTL_PSC3_3 0x254
-#define IOCTL_PSC3_4 0x258
-#define IOCTL_PSC4_0 0x25C
-#define IOCTL_PSC4_1 0x260
-#define IOCTL_PSC4_2 0x264
-#define IOCTL_PSC4_3 0x268
-#define IOCTL_PSC4_4 0x26C
-#define IOCTL_PSC5_0 0x270
-#define IOCTL_PSC5_1 0x274
-#define IOCTL_PSC5_2 0x278
-#define IOCTL_PSC5_3 0x27C
-#define IOCTL_PSC5_4 0x280
-#define IOCTL_PSC6_0 0x284
-#define IOCTL_PSC6_1 0x288
-#define IOCTL_PSC6_2 0x28C
-#define IOCTL_PSC6_3 0x290
-#define IOCTL_PSC6_4 0x294
-#define IOCTL_PSC7_0 0x298
-#define IOCTL_PSC7_1 0x29C
-#define IOCTL_PSC7_2 0x2A0
-#define IOCTL_PSC7_3 0x2A4
-#define IOCTL_PSC7_4 0x2A8
-#define IOCTL_PSC8_0 0x2AC
-#define IOCTL_PSC8_1 0x2B0
-#define IOCTL_PSC8_2 0x2B4
-#define IOCTL_PSC8_3 0x2B8
-#define IOCTL_PSC8_4 0x2BC
-#define IOCTL_PSC9_0 0x2C0
-#define IOCTL_PSC9_1 0x2C4
-#define IOCTL_PSC9_2 0x2C8
-#define IOCTL_PSC9_3 0x2CC
-#define IOCTL_PSC9_4 0x2D0
-#define IOCTL_PSC10_0 0x2D4
-#define IOCTL_PSC10_1 0x2D8
-#define IOCTL_PSC10_2 0x2DC
-#define IOCTL_PSC10_3 0x2E0
-#define IOCTL_PSC10_4 0x2E4
-#define IOCTL_PSC11_0 0x2E8
-#define IOCTL_PSC11_1 0x2EC
-#define IOCTL_PSC11_2 0x2F0
-#define IOCTL_PSC11_3 0x2F4
-#define IOCTL_PSC11_4 0x2F8
-#define IOCTL_HRESET 0x2FC
-#define IOCTL_SRESET 0x300
-#define IOCTL_CKSTP_OUT 0x304
-#define IOCTL_USB2_VBUS_PWR_FAULT 0x308
-#define IOCTL_USB2_VBUS_PWR_SELECT 0x30C
-#define IOCTL_USB2_PHY_DRVV_BUS 0x310
-
-extern void iopin_initialize(void);
return 1;
}
-int katmai_pcie_card_present(int port)
+static int katmai_pcie_card_present(int port)
{
u32 val;
}
#endif /* defined(CONFIG_PCI) */
-int misc_init_f (void)
-{
- uint reg;
-#if defined(CONFIG_STRESS)
- uint i ;
- uint disp;
-#endif
-
- /* minimal init for PCIe */
-#if 0 /* test-only: test endpoint at some time, for now rootpoint only */
- /* pci express 0 Endpoint Mode */
- mfsdr(SDR0_PE0DLPSET, reg);
- reg &= (~0x00400000);
- mtsdr(SDR0_PE0DLPSET, reg);
-#else
- /* pci express 0 Rootpoint Mode */
- mfsdr(SDR0_PE0DLPSET, reg);
- reg |= 0x00400000;
- mtsdr(SDR0_PE0DLPSET, reg);
-#endif
- /* pci express 1 Rootpoint Mode */
- mfsdr(SDR0_PE1DLPSET, reg);
- reg |= 0x00400000;
- mtsdr(SDR0_PE1DLPSET, reg);
- /* pci express 2 Rootpoint Mode */
- mfsdr(SDR0_PE2DLPSET, reg);
- reg |= 0x00400000;
- mtsdr(SDR0_PE2DLPSET, reg);
-
-#if defined(CONFIG_STRESS)
- /*
- * All this setting done by linux only needed by stress an charac. test
- * procedure
- * PCIe 1 Rootpoint PCIe2 Endpoint
- * PCIe 0 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level
- */
- for (i=0,disp=0; i<8; i++,disp+=3) {
- mfsdr(SDR0_PE0HSSSET1L0+disp, reg);
- reg |= 0x33000000;
- mtsdr(SDR0_PE0HSSSET1L0+disp, reg);
- }
-
- /*PCIe 1 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level */
- for (i=0,disp=0; i<4; i++,disp+=3) {
- mfsdr(SDR0_PE1HSSSET1L0+disp, reg);
- reg |= 0x33000000;
- mtsdr(SDR0_PE1HSSSET1L0+disp, reg);
- }
-
- /*PCIE 2 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level */
- for (i=0,disp=0; i<4; i++,disp+=3) {
- mfsdr(SDR0_PE2HSSSET1L0+disp, reg);
- reg |= 0x33000000;
- mtsdr(SDR0_PE2HSSSET1L0+disp, reg);
- }
-
- reg = 0x21242222;
- mtsdr(SDR0_PE2UTLSET1, reg);
- reg = 0x11000000;
- mtsdr(SDR0_PE2UTLSET2, reg);
- /* pci express 1 Endpoint Mode */
- reg = 0x00004000;
- mtsdr(SDR0_PE2DLPSET, reg);
-
- mtsdr(SDR0_UART1, 0x2080005a); /* patch for TG */
-#endif
-
- return 0;
-}
-
#ifdef CONFIG_POST
/*
* Returns 1 if keys pressed to start the power-on long-running tests
/*--------------------------------------------------------------------
* Setup the interrupt controller polarities, triggers, etc.
*-------------------------------------------------------------------*/
- mtdcr (uic0sr, 0xffffffff); /* clear all */
- mtdcr (uic0er, 0x00000000); /* disable all */
- mtdcr (uic0cr, 0x00000009); /* SMI & UIC1 crit are critical */
- mtdcr (uic0pr, 0xfffffe13); /* per ref-board manual */
- mtdcr (uic0tr, 0x01c00008); /* per ref-board manual */
- mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */
- mtdcr (uic0sr, 0xffffffff); /* clear all */
-
+ /*
+ * Because of the interrupt handling rework to handle 440GX interrupts
+ * with the common code, we needed to change names of the UIC registers.
+ * Here the new relationship:
+ *
+ * U-Boot name 440GX name
+ * -----------------------
+ * UIC0 UICB0
+ * UIC1 UIC0
+ * UIC2 UIC1
+ * UIC3 UIC2
+ */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic1er, 0x00000000); /* disable all */
- mtdcr (uic1cr, 0x00000000); /* all non-critical */
- mtdcr (uic1pr, 0xffffe0ff); /* per ref-board manual */
- mtdcr (uic1tr, 0x00ffc000); /* per ref-board manual */
+ mtdcr (uic1cr, 0x00000009); /* SMI & UIC1 crit are critical */
+ mtdcr (uic1pr, 0xfffffe13); /* per ref-board manual */
+ mtdcr (uic1tr, 0x01c00008); /* per ref-board manual */
mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic2sr, 0xffffffff); /* clear all */
mtdcr (uic2er, 0x00000000); /* disable all */
mtdcr (uic2cr, 0x00000000); /* all non-critical */
- mtdcr (uic2pr, 0xffffffff); /* per ref-board manual */
- mtdcr (uic2tr, 0x00ff8c0f); /* per ref-board manual */
+ mtdcr (uic2pr, 0xffffe0ff); /* per ref-board manual */
+ mtdcr (uic2tr, 0x00ffc000); /* per ref-board manual */
mtdcr (uic2vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic2sr, 0xffffffff); /* clear all */
- mtdcr (uicb0sr, 0xfc000000); /* clear all */
- mtdcr (uicb0er, 0x00000000); /* disable all */
- mtdcr (uicb0cr, 0x00000000); /* all non-critical */
- mtdcr (uicb0pr, 0xfc000000); /* */
- mtdcr (uicb0tr, 0x00000000); /* */
- mtdcr (uicb0vr, 0x00000001); /* */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+ mtdcr (uic3er, 0x00000000); /* disable all */
+ mtdcr (uic3cr, 0x00000000); /* all non-critical */
+ mtdcr (uic3pr, 0xffffffff); /* per ref-board manual */
+ mtdcr (uic3tr, 0x00ff8c0f); /* per ref-board manual */
+ mtdcr (uic3vr, 0x00000001); /* int31 highest, base=0x000 */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+
+ mtdcr (uic0sr, 0xfc000000); /* clear all */
+ mtdcr (uic0er, 0x00000000); /* disable all */
+ mtdcr (uic0cr, 0x00000000); /* all non-critical */
+ mtdcr (uic0pr, 0xfc000000); /* */
+ mtdcr (uic0tr, 0x00000000); /* */
+ mtdcr (uic0vr, 0x00000001); /* */
mfsdr (sdr_mfr, mfr);
mfr &= ~SDR0_MFR_ECS_MASK;
/* mtsdr(sdr_mfr, mfr); */
--- /dev/null
+#
+# (C) Copyright 2008
+# Feng Kan, Applied Micro Circuits Corp., fkan@amcc.com.
+#
+# 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 = $(obj)lib$(BOARD).a
+
+COBJS = $(BOARD).o
+SOBJS = init.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend *~
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
--- /dev/null
+#
+# (C) Copyright 2008
+# Feng Kan, Applied Micro Circuits Corp., fkan@amcc.com.
+#
+# 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
+#
+
+#
+# AMCC 460SX Reference Platform (redwood) board
+#
+
+ifeq ($(ramsym),1)
+TEXT_BASE = 0x07FD0000
+else
+TEXT_BASE = 0xfffb0000
+endif
+
+PLATFORM_CPPFLAGS += -DCONFIG_440=1
+
+ifeq ($(debug),1)
+PLATFORM_CPPFLAGS += -DDEBUG
+endif
+
+ifeq ($(dbcr),1)
+PLATFORM_CPPFLAGS += -DCFG_INIT_DBCR=0x8cff0000
+endif
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Feng Kan, Applied Micro Circuits Corp., fkan@amcc.com.
+ *
+ * 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 <ppc_asm.tmpl>
+#include <config.h>
+#include <asm-ppc/mmu.h>
+
+/**************************************************************************
+ * TLB TABLE
+ *
+ * This table is used by the cpu boot code to setup the initial tlb
+ * entries. Rather than make broad assumptions in the cpu source tree,
+ * this table lets each board set things up however they like.
+ *
+ * Pointer to the table is returned in r1
+ *
+ *************************************************************************/
+
+ .section .bootpg,"ax"
+ .globl tlbtab
+tlbtab:
+ tlbtab_start
+
+ /*
+ * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the
+ * speed up boot process. It is patched after relocation to enable SA_I
+ */
+ tlbentry(0xff000000, SZ_16M, 0xff000000, 4, AC_R|AC_W|AC_X|SA_G)
+
+ /*
+ * TLB entries for SDRAM are not needed on this platform.
+ * They are dynamically generated in the SPD DDR(2) detection
+ * routine.
+ */
+
+ /* Although 512 KB, map 256k at a time */
+ tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I)
+ tlbentry(CFG_ISRAM_BASE + 0x40000, SZ_256K, 0x00040000, 4, AC_R|AC_W|AC_X|SA_I)
+
+ tlbentry(CFG_OPER_FLASH, SZ_16M, 0xE7000000, 4,AC_R|AC_W|AC_X|SA_G|SA_I)
+
+ /*
+ * Peripheral base
+ */
+ tlbentry(CFG_PERIPHERAL_BASE, SZ_16K, 0xEF600000, 4, AC_R|AC_W|SA_G|SA_I)
+
+ tlbentry(CFG_PCIE0_XCFGBASE,SZ_16M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE1_XCFGBASE,SZ_16M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE2_XCFGBASE,SZ_16M, 0x20000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+
+ tlbentry(CFG_PCIE0_MEMBASE, SZ_256M, 0x00000000, 0xD, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE1_MEMBASE, SZ_256M, 0x00000000, 0xE, AC_R|AC_W|SA_G|SA_I)
+
+ tlbentry(CFG_PCIE0_REGBASE, SZ_64K, 0x30000000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE1_REGBASE, SZ_64K, 0x30010000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbentry(CFG_PCIE2_REGBASE, SZ_64K, 0x30020000, 0xC, AC_R|AC_W|SA_G|SA_I)
+ tlbtab_end
--- /dev/null
+/*
+ * This is the main board level file for the Redwood AMCC board.
+ *
+ * (C) Copyright 2008
+ * Feng Kan, Applied Micro Circuits Corp., fkan@amcc.com
+ *
+ * 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 "redwood.h"
+#include <ppc4xx.h>
+#include <asm/processor.h>
+#include <i2c.h>
+#include <asm-ppc/io.h>
+
+int compare_to_true(char *str);
+char *remove_l_w_space(char *in_str);
+char *remove_t_w_space(char *in_str);
+int get_console_port(void);
+
+static void early_init_EBC(void);
+static int bootdevice_selected(void);
+static void early_reinit_EBC(int);
+static void early_init_UIC(void);
+
+/*
+ * Define Boot devices
+ */
+#define BOOT_FROM_8BIT_SRAM 0x00
+#define BOOT_FROM_16BIT_SRAM 0x01
+#define BOOT_FROM_32BIT_SRAM 0x02
+#define BOOT_FROM_8BIT_NAND 0x03
+#define BOOT_FROM_16BIT_NOR 0x04
+#define BOOT_DEVICE_UNKNOWN 0xff
+
+/*
+ * EBC Devices Characteristics
+ * Peripheral Bank Access Parameters - EBC_BxAP
+ * Peripheral Bank Configuration Register - EBC_BxCR
+ */
+
+/*
+ * 8 bit width SRAM
+ * BU Value
+ * BxAP : 0x03800000 - 0 00000111 0 00 00 00 00 00 000 0 0 0 0 00000
+ * B0CR : 0xff098000 - BAS = ff0 - 100 11 00 0000000000000
+ * B2CR : 0xe7098000 - BAS = e70 - 100 11 00 0000000000000
+ */
+#define EBC_BXAP_8BIT_SRAM \
+ EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(7) | \
+ EBC_BXAP_BCE_DISABLE | EBC_BXAP_BCT_2TRANS | \
+ EBC_BXAP_CSN_ENCODE(0) | EBC_BXAP_OEN_ENCODE(0) | \
+ EBC_BXAP_WBN_ENCODE(0) | EBC_BXAP_WBF_ENCODE(0) | \
+ EBC_BXAP_TH_ENCODE(0) | EBC_BXAP_RE_DISABLED | \
+ EBC_BXAP_SOR_DELAYED | EBC_BXAP_BEM_WRITEONLY | \
+ EBC_BXAP_PEN_DISABLED
+
+#define EBC_BXAP_16BIT_SRAM EBC_BXAP_8BIT_SRAM
+#define EBC_BXAP_32BIT_SRAM EBC_BXAP_8BIT_SRAM
+
+/*
+ * NAND flash
+ * BU Value
+ * BxAP : 0x048ff240 - 0 00000111 0 00 00 00 00 00 000 0 0 0 0 00000
+ * B0CR : 0xff09a000 - BAS = ff0 - 100 11 01 0000000000000
+ * B2CR : 0xe709a000 - BAS = e70 - 100 11 01 0000000000000
+*/
+#define EBC_BXAP_NAND \
+ EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(7) | \
+ EBC_BXAP_BCE_DISABLE | EBC_BXAP_BCT_2TRANS | \
+ EBC_BXAP_CSN_ENCODE(0) | EBC_BXAP_OEN_ENCODE(0) | \
+ EBC_BXAP_WBN_ENCODE(0) | EBC_BXAP_WBF_ENCODE(0) | \
+ EBC_BXAP_TH_ENCODE(0) | EBC_BXAP_RE_DISABLED | \
+ EBC_BXAP_SOR_DELAYED | EBC_BXAP_BEM_WRITEONLY | \
+ EBC_BXAP_PEN_DISABLED
+
+/*
+ * NOR flash
+ * BU Value
+ * BxAP : 0x048ff240 - 0 00000111 0 00 00 00 00 00 000 0 0 0 0 00000
+ * B0CR : 0xff09a000 - BAS = ff0 - 100 11 01 0000000000000
+ * B2CR : 0xe709a000 - BAS = e70 - 100 11 01 0000000000000
+*/
+#define EBC_BXAP_NOR \
+ EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(7) | \
+ EBC_BXAP_BCE_DISABLE | EBC_BXAP_BCT_2TRANS | \
+ EBC_BXAP_CSN_ENCODE(0) | EBC_BXAP_OEN_ENCODE(0) | \
+ EBC_BXAP_WBN_ENCODE(0) | EBC_BXAP_WBF_ENCODE(0) | \
+ EBC_BXAP_TH_ENCODE(0) | EBC_BXAP_RE_DISABLED | \
+ EBC_BXAP_SOR_DELAYED | EBC_BXAP_BEM_WRITEONLY | \
+ EBC_BXAP_PEN_DISABLED
+
+/*
+ * FPGA
+ * BU value :
+ * B1AP = 0x05895240 - 0 00001011 0 00 10 01 01 01 001 0 0 1 0 00000
+ * B1CR = 0xe201a000 - BAS = e20 - 000 11 01 00000000000000
+ */
+#define EBC_BXAP_FPGA \
+ EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(11) | \
+ EBC_BXAP_BCE_DISABLE | EBC_BXAP_BCT_2TRANS | \
+ EBC_BXAP_CSN_ENCODE(10) | EBC_BXAP_OEN_ENCODE(1) | \
+ EBC_BXAP_WBN_ENCODE(1) | EBC_BXAP_WBF_ENCODE(1) | \
+ EBC_BXAP_TH_ENCODE(1) | EBC_BXAP_RE_DISABLED | \
+ EBC_BXAP_SOR_DELAYED | EBC_BXAP_BEM_RW | \
+ EBC_BXAP_PEN_DISABLED
+
+#define EBC_BXCR_8BIT_SRAM_CS0 \
+ EBC_BXCR_BAS_ENCODE(0xFFE00000) | EBC_BXCR_BS_1MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_8BIT
+
+#define EBC_BXCR_32BIT_SRAM_CS0 \
+ EBC_BXCR_BAS_ENCODE(0xFFC00000) | EBC_BXCR_BS_1MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_32BIT
+
+#define EBC_BXCR_NAND_CS0 \
+ EBC_BXCR_BAS_ENCODE(0xFF000000) | EBC_BXCR_BS_16MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_8BIT
+
+#define EBC_BXCR_16BIT_SRAM_CS0 \
+ EBC_BXCR_BAS_ENCODE(0xFFE00000) | EBC_BXCR_BS_2MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_16BIT
+
+#define EBC_BXCR_NOR_CS0 \
+ EBC_BXCR_BAS_ENCODE(0xFF000000) | EBC_BXCR_BS_16MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_16BIT
+
+#define EBC_BXCR_NOR_CS1 \
+ EBC_BXCR_BAS_ENCODE(0xE0000000) | EBC_BXCR_BS_128MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_16BIT
+
+#define EBC_BXCR_NAND_CS1 \
+ EBC_BXCR_BAS_ENCODE(0xE0000000) | EBC_BXCR_BS_128MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_8BIT
+
+#define EBC_BXCR_NAND_CS2 \
+ EBC_BXCR_BAS_ENCODE(0xC0000000) | EBC_BXCR_BS_128MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_8BIT
+
+#define EBC_BXCR_SRAM_CS2 \
+ EBC_BXCR_BAS_ENCODE(0xC0000000) | EBC_BXCR_BS_4MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_32BIT
+
+#define EBC_BXCR_LARGE_FLASH_CS2 \
+ EBC_BXCR_BAS_ENCODE(0xE7000000) | EBC_BXCR_BS_16MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_16BIT
+
+#define EBC_BXCR_FPGA_CS3 \
+ EBC_BXCR_BAS_ENCODE(0xE2000000) | EBC_BXCR_BS_1MB | \
+ EBC_BXCR_BU_RW | EBC_BXCR_BW_16BIT
+
+/*****************************************************************************
+ * UBOOT initiated board specific function calls
+ ****************************************************************************/
+
+int board_early_init_f(void)
+{
+ int computed_boot_device = BOOT_DEVICE_UNKNOWN;
+
+ /*
+ * Initialise EBC
+ */
+ early_init_EBC();
+
+ /*
+ * Determine which boot device was selected
+ */
+ computed_boot_device = bootdevice_selected();
+
+ /*
+ * Reinit EBC based on selected boot device
+ */
+ early_reinit_EBC(computed_boot_device);
+
+ /*
+ * Setup for UIC on 460SX redwood board
+ */
+ early_init_UIC();
+
+ return 0;
+}
+
+int checkboard(void)
+{
+ char *s = getenv("serial#");
+
+ printf("Board: Redwood - AMCC 460SX Reference Board");
+ if (s != NULL) {
+ puts(", serial# ");
+ puts(s);
+ }
+ putc('\n');
+
+ return 0;
+}
+
+static void early_init_EBC(void)
+{
+ /*
+ * Initialize EBC CONFIG -
+ * Keep the Default value, but the bit PDT which has to be set to 1 ?TBC
+ * default value :
+ * 0x07C00000 - 0 0 000 1 1 1 1 1 0000 0 00000 000000000000
+ */
+ mtebc(xbcfg, EBC_CFG_LE_UNLOCK |
+ EBC_CFG_PTD_ENABLE |
+ EBC_CFG_RTC_16PERCLK |
+ EBC_CFG_ATC_PREVIOUS |
+ EBC_CFG_DTC_PREVIOUS |
+ EBC_CFG_CTC_PREVIOUS |
+ EBC_CFG_OEO_PREVIOUS |
+ EBC_CFG_EMC_DEFAULT | EBC_CFG_PME_DISABLE | EBC_CFG_PR_16);
+
+ /*
+ * PART 1 : Initialize EBC Bank 3
+ * ==============================
+ * Bank1 is always associated to the EPLD.
+ * It has to be initialized prior to other banks settings computation
+ * since some board registers values may be needed to determine the
+ * boot type
+ */
+ mtebc(pb1ap, EBC_BXAP_FPGA);
+ mtebc(pb1cr, EBC_BXCR_FPGA_CS3);
+
+}
+
+static int bootdevice_selected(void)
+{
+ unsigned long sdr0_pinstp;
+ unsigned long bootstrap_settings;
+ int computed_boot_device = BOOT_DEVICE_UNKNOWN;
+
+ /*
+ * Determine which boot device was selected
+ * =================================================
+ *
+ * Read Pin Strap Register in PPC460SX
+ * Result can either be :
+ * - Boot strap = boot from EBC 8bits => Small Flash
+ * - Boot strap = boot from PCI
+ * - Boot strap = IIC
+ * In case of boot from IIC, read Serial Device Strap Register1
+ *
+ * Result can either be :
+ * - Boot from EBC - EBC Bus Width = 8bits => Small Flash
+ * - Boot from EBC - EBC Bus Width = 16bits => Large Flash or SRAM
+ * - Boot from PCI
+ */
+
+ /* Read Pin Strap Register in PPC460SX */
+ mfsdr(SDR0_PINSTP, sdr0_pinstp);
+ bootstrap_settings = sdr0_pinstp & SDR0_PSTRP0_BOOTSTRAP_MASK;
+
+ switch (bootstrap_settings) {
+ case SDR0_PSTRP0_BOOTSTRAP_SETTINGS0:
+ /*
+ * Boot from SRAM, 8bit width
+ */
+ computed_boot_device = BOOT_FROM_8BIT_SRAM;
+ break;
+ case SDR0_PSTRP0_BOOTSTRAP_SETTINGS1:
+ /*
+ * Boot from SRAM, 32bit width
+ */
+ computed_boot_device = BOOT_FROM_32BIT_SRAM;
+ break;
+ case SDR0_PSTRP0_BOOTSTRAP_SETTINGS2:
+ /*
+ * Boot from NAND, 8bit width
+ */
+ computed_boot_device = BOOT_FROM_8BIT_NAND;
+ break;
+ case SDR0_PSTRP0_BOOTSTRAP_SETTINGS4:
+ /*
+ * Boot from SRAM, 16bit width
+ * Boot setting in IIC EEPROM 0x50
+ */
+ computed_boot_device = BOOT_FROM_16BIT_SRAM;
+ break;
+ case SDR0_PSTRP0_BOOTSTRAP_SETTINGS5:
+ /*
+ * Boot from NOR, 16bit width
+ * Boot setting in IIC EEPROM 0x54
+ */
+ computed_boot_device = BOOT_FROM_16BIT_NOR;
+ break;
+ default:
+ /* should not be */
+ computed_boot_device = BOOT_DEVICE_UNKNOWN;
+ break;
+ }
+
+ return computed_boot_device;
+}
+
+static void early_reinit_EBC(int computed_boot_device)
+{
+ /*
+ * Compute EBC settings depending on selected boot device
+ * ======================================================
+ *
+ * Resulting EBC init will be among following configurations :
+ *
+ * - Boot from EBC 8bits => boot from Small Flash selected
+ * EBC-CS0 = Small Flash
+ * EBC-CS2 = Large Flash and SRAM
+ *
+ * - Boot from EBC 16bits => boot from Large Flash or SRAM
+ * EBC-CS0 = Large Flash or SRAM
+ * EBC-CS2 = Small Flash
+ *
+ * - Boot from PCI
+ * EBC-CS0 = not initialized to avoid address contention
+ * EBC-CS2 = same as boot from Small Flash selected
+ */
+
+ unsigned long ebc0_cs0_bxap_value = 0, ebc0_cs0_bxcr_value = 0;
+ unsigned long ebc0_cs1_bxap_value = 0, ebc0_cs1_bxcr_value = 0;
+ unsigned long ebc0_cs2_bxap_value = 0, ebc0_cs2_bxcr_value = 0;
+
+ switch (computed_boot_device) {
+ /*-------------------------------------------------------------------*/
+ case BOOT_FROM_8BIT_SRAM:
+ /*-------------------------------------------------------------------*/
+ ebc0_cs0_bxap_value = EBC_BXAP_8BIT_SRAM;
+ ebc0_cs0_bxcr_value = EBC_BXCR_8BIT_SRAM_CS0;
+ ebc0_cs1_bxap_value = EBC_BXAP_NOR;
+ ebc0_cs1_bxcr_value = EBC_BXCR_NOR_CS1;
+ ebc0_cs2_bxap_value = EBC_BXAP_NAND;
+ ebc0_cs2_bxcr_value = EBC_BXCR_NAND_CS2;
+ break;
+
+ /*-------------------------------------------------------------------*/
+ case BOOT_FROM_16BIT_SRAM:
+ /*-------------------------------------------------------------------*/
+ ebc0_cs0_bxap_value = EBC_BXAP_16BIT_SRAM;
+ ebc0_cs0_bxcr_value = EBC_BXCR_16BIT_SRAM_CS0;
+ ebc0_cs1_bxap_value = EBC_BXAP_NOR;
+ ebc0_cs1_bxcr_value = EBC_BXCR_NOR_CS1;
+ ebc0_cs2_bxap_value = EBC_BXAP_NAND;
+ ebc0_cs2_bxcr_value = EBC_BXCR_NAND_CS2;
+ break;
+
+ /*-------------------------------------------------------------------*/
+ case BOOT_FROM_32BIT_SRAM:
+ /*-------------------------------------------------------------------*/
+ ebc0_cs0_bxap_value = EBC_BXAP_32BIT_SRAM;
+ ebc0_cs0_bxcr_value = EBC_BXCR_32BIT_SRAM_CS0;
+ ebc0_cs1_bxap_value = EBC_BXAP_NOR;
+ ebc0_cs1_bxcr_value = EBC_BXCR_NOR_CS1;
+ ebc0_cs2_bxap_value = EBC_BXAP_NAND;
+ ebc0_cs2_bxcr_value = EBC_BXCR_NAND_CS2;
+ break;
+
+ /*-------------------------------------------------------------------*/
+ case BOOT_FROM_16BIT_NOR:
+ /*-------------------------------------------------------------------*/
+ ebc0_cs0_bxap_value = EBC_BXAP_NOR;
+ ebc0_cs0_bxcr_value = EBC_BXCR_NOR_CS0;
+ ebc0_cs1_bxap_value = EBC_BXAP_NAND;
+ ebc0_cs1_bxcr_value = EBC_BXCR_NAND_CS1;
+ ebc0_cs2_bxap_value = EBC_BXAP_32BIT_SRAM;
+ ebc0_cs2_bxcr_value = EBC_BXCR_SRAM_CS2;
+ break;
+
+ /*-------------------------------------------------------------------*/
+ case BOOT_FROM_8BIT_NAND:
+ /*-------------------------------------------------------------------*/
+ ebc0_cs0_bxap_value = EBC_BXAP_NAND;
+ ebc0_cs0_bxcr_value = EBC_BXCR_NAND_CS0;
+ ebc0_cs1_bxap_value = EBC_BXAP_NOR;
+ ebc0_cs1_bxcr_value = EBC_BXCR_NOR_CS1;
+ ebc0_cs2_bxap_value = EBC_BXAP_32BIT_SRAM;
+ ebc0_cs2_bxcr_value = EBC_BXCR_SRAM_CS2;
+ break;
+
+ /*-------------------------------------------------------------------*/
+ default:
+ /*-------------------------------------------------------------------*/
+ /* BOOT_DEVICE_UNKNOWN */
+ break;
+ }
+
+ mtebc(pb0ap, ebc0_cs0_bxap_value);
+ mtebc(pb0cr, ebc0_cs0_bxcr_value);
+ mtebc(pb1ap, ebc0_cs1_bxap_value);
+ mtebc(pb1cr, ebc0_cs1_bxcr_value);
+ mtebc(pb2ap, ebc0_cs2_bxap_value);
+ mtebc(pb2cr, ebc0_cs2_bxcr_value);
+}
+
+static void early_init_UIC(void)
+{
+ /*
+ * Initialise UIC registers. Clear all interrupts. Disable all
+ * interrupts.
+ * Set critical interrupt values. Set interrupt polarities. Set
+ * interrupt trigger levels. Make bit 0 High priority. Clear all
+ * interrupts again.
+ */
+ mtdcr(uic3sr, 0xffffffff); /* Clear all interrupts */
+ mtdcr(uic3er, 0x00000000); /* disable all interrupts */
+ mtdcr(uic3cr, 0x00000000); /* Set Critical / Non Critical
+ * interrupts */
+ mtdcr(uic3pr, 0xffffffff); /* Set Interrupt Polarities */
+ mtdcr(uic3tr, 0x001fffff); /* Set Interrupt Trigger Levels */
+ mtdcr(uic3vr, 0x00000000); /* int31 highest, base=0x000 */
+ mtdcr(uic3sr, 0xffffffff); /* clear all interrupts */
+
+ mtdcr(uic2sr, 0xffffffff); /* Clear all interrupts */
+ mtdcr(uic2er, 0x00000000); /* disable all interrupts */
+ mtdcr(uic2cr, 0x00000000); /* Set Critical / Non Critical
+ * interrupts */
+ mtdcr(uic2pr, 0xebebebff); /* Set Interrupt Polarities */
+ mtdcr(uic2tr, 0x74747400); /* Set Interrupt Trigger Levels */
+ mtdcr(uic2vr, 0x00000000); /* int31 highest, base=0x000 */
+ mtdcr(uic2sr, 0xffffffff); /* clear all interrupts */
+
+ mtdcr(uic1sr, 0xffffffff); /* Clear all interrupts */
+ mtdcr(uic1er, 0x00000000); /* disable all interrupts */
+ mtdcr(uic1cr, 0x00000000); /* Set Critical / Non Critical
+ * interrupts */
+ mtdcr(uic1pr, 0xffffffff); /* Set Interrupt Polarities */
+ mtdcr(uic1tr, 0x001fc0ff); /* Set Interrupt Trigger Levels */
+ mtdcr(uic1vr, 0x00000000); /* int31 highest, base=0x000 */
+ mtdcr(uic1sr, 0xffffffff); /* clear all interrupts */
+
+ mtdcr(uic0sr, 0xffffffff); /* Clear all interrupts */
+ mtdcr(uic0er, 0x00000000); /* disable all interrupts excepted
+ * cascade to be checked */
+ mtdcr(uic0cr, 0x00104001); /* Set Critical / Non Critical
+ * interrupts */
+ mtdcr(uic0pr, 0xffffffff); /* Set Interrupt Polarities */
+ mtdcr(uic0tr, 0x000f003c); /* Set Interrupt Trigger Levels */
+ mtdcr(uic0vr, 0x00000000); /* int31 highest, base=0x000 */
+ mtdcr(uic0sr, 0xffffffff); /* clear all interrupts */
+
+}
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Feng Kan, Applied Micro Circuit Corp., fkan@amcc.com.
+ *
+ * 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 __REDWOOD_H_
+#define __REDWOOD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------------+
+| Defines
++----------------------------------------------------------------------------*/
+/* Pin Straps Reg */
+#define SDR0_PSTRP0 0x0040
+#define SDR0_PSTRP0_BOOTSTRAP_MASK 0xE0000000 /* Strap Bits */
+
+#define SDR0_PSTRP0_BOOTSTRAP_SETTINGS0 0x00000000 /* Default strap settings 0 */
+#define SDR0_PSTRP0_BOOTSTRAP_SETTINGS1 0x20000000 /* Default strap settings 1 */
+#define SDR0_PSTRP0_BOOTSTRAP_SETTINGS2 0x40000000 /* Default strap settings 2 */
+#define SDR0_PSTRP0_BOOTSTRAP_SETTINGS3 0x60000000 /* Default strap settings 3 */
+#define SDR0_PSTRP0_BOOTSTRAP_SETTINGS4 0x80000000 /* Default strap settings 4 */
+#define SDR0_PSTRP0_BOOTSTRAP_SETTINGS5 0xA0000000 /* Default strap settings 5 */
+#define SDR0_PSTRP0_BOOTSTRAP_SETTINGS6 0xC0000000 /* Default strap settings 6 */
+#define SDR0_PSTRP0_BOOTSTRAP_SETTINGS7 0xE0000000 /* Default strap settings 7 */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __REDWOOD_H_ */
--- /dev/null
+/*
+ * (C) Copyright 2004
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ .resetvec 0xFFFFFFFC :
+ {
+ *(.resetvec)
+ } = 0xffff
+
+ .bootpg 0xFFFFF000 :
+ {
+ cpu/ppc4xx/start.o (.bootpg)
+ } = 0xffff
+
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/ppc4xx/start.o (.text)
+ board/amcc/redwood/init.o (.text)
+
+/* . = env_offset;*/
+/* common/environment.o(.text)*/
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
#include <common.h>
#include <libfdt.h>
#include <fdt_support.h>
-#include <ppc440.h>
+#include <ppc4xx.h>
#include <asm/gpio.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/bitops.h>
-#include <asm/ppc4xx-intvec.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_I2C_MULTI_BUS
sdr0_pfc1 |= ((sdr0_pfc1 & ~SDR0_PFC1_SIS_MASK) | SDR0_PFC1_SIS_IIC1_SEL);
#endif
+ /* Two UARTs, so we need 4-pin mode. Also, we want CTS/RTS mode. */
+ sdr0_pfc1 = (sdr0_pfc1 & ~SDR0_PFC1_U0IM_MASK) | SDR0_PFC1_U0IM_4PINS;
+ sdr0_pfc1 = (sdr0_pfc1 & ~SDR0_PFC1_U0ME_MASK) | SDR0_PFC1_U0ME_CTS_RTS;
+ sdr0_pfc1 = (sdr0_pfc1 & ~SDR0_PFC1_U1ME_MASK) | SDR0_PFC1_U1ME_CTS_RTS;
+
mfsdr(SDR0_PFC2, sdr0_pfc2);
sdr0_pfc2 = (sdr0_pfc2 & ~SDR0_PFC2_SELECT_MASK) |
SDR0_PFC2_SELECT_CONFIG_4;
*/
void sequoia_pci_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
{
- pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, VECNUM_EIR2);
+ pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, VECNUM_EIRQ2);
}
#endif
/*--------------------------------------------------------------------
* Setup the interrupt controller polarities, triggers, etc.
*-------------------------------------------------------------------*/
- mtdcr (uic0sr, 0xffffffff); /* clear all */
- mtdcr (uic0er, 0x00000000); /* disable all */
- mtdcr (uic0cr, 0x00000009); /* SMI & UIC1 crit are critical */
- mtdcr (uic0pr, 0xfffffe13); /* per ref-board manual */
- mtdcr (uic0tr, 0x01c00008); /* per ref-board manual */
- mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */
- mtdcr (uic0sr, 0xffffffff); /* clear all */
-
+ /*
+ * Because of the interrupt handling rework to handle 440GX interrupts
+ * with the common code, we needed to change names of the UIC registers.
+ * Here the new relationship:
+ *
+ * U-Boot name 440GX name
+ * -----------------------
+ * UIC0 UICB0
+ * UIC1 UIC0
+ * UIC2 UIC1
+ * UIC3 UIC2
+ */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic1er, 0x00000000); /* disable all */
- mtdcr (uic1cr, 0x00000000); /* all non-critical */
- mtdcr (uic1pr, 0xffffe0ff); /* per ref-board manual */
- mtdcr (uic1tr, 0x00ffc000); /* per ref-board manual */
+ mtdcr (uic1cr, 0x00000009); /* SMI & UIC1 crit are critical */
+ mtdcr (uic1pr, 0xfffffe13); /* per ref-board manual */
+ mtdcr (uic1tr, 0x01c00008); /* per ref-board manual */
mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic2sr, 0xffffffff); /* clear all */
mtdcr (uic2er, 0x00000000); /* disable all */
mtdcr (uic2cr, 0x00000000); /* all non-critical */
- mtdcr (uic2pr, 0xffffffff); /* per ref-board manual */
- mtdcr (uic2tr, 0x00ff8c0f); /* per ref-board manual */
+ mtdcr (uic2pr, 0xffffe0ff); /* per ref-board manual */
+ mtdcr (uic2tr, 0x00ffc000); /* per ref-board manual */
mtdcr (uic2vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic2sr, 0xffffffff); /* clear all */
- mtdcr (uicb0sr, 0xfc000000); /* clear all */
- mtdcr (uicb0er, 0x00000000); /* disable all */
- mtdcr (uicb0cr, 0x00000000); /* all non-critical */
- mtdcr (uicb0pr, 0xfc000000); /* */
- mtdcr (uicb0tr, 0x00000000); /* */
- mtdcr (uicb0vr, 0x00000001); /* */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+ mtdcr (uic3er, 0x00000000); /* disable all */
+ mtdcr (uic3cr, 0x00000000); /* all non-critical */
+ mtdcr (uic3pr, 0xffffffff); /* per ref-board manual */
+ mtdcr (uic3tr, 0x00ff8c0f); /* per ref-board manual */
+ mtdcr (uic3vr, 0x00000001); /* int31 highest, base=0x000 */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+
+ mtdcr (uic0sr, 0xfc000000); /* clear all */
+ mtdcr (uic0er, 0x00000000); /* disable all */
+ mtdcr (uic0cr, 0x00000000); /* all non-critical */
+ mtdcr (uic0pr, 0xfc000000); /* */
+ mtdcr (uic0tr, 0x00000000); /* */
+ mtdcr (uic0vr, 0x00000001); /* */
/* Enable two GPIO 10~11 and TraceA signal */
mfsdr(sdr_pfc0,reg);
return 1;
}
-int yucca_pcie_card_present(int port)
+static int yucca_pcie_card_present(int port)
{
u16 reg;
int misc_init_f (void)
{
uint reg;
-#if defined(CONFIG_STRESS)
- uint i ;
- uint disp;
-#endif
out16(FPGA_REG10, (in16(FPGA_REG10) &
~(FPGA_REG10_AUTO_NEG_DIS|FPGA_REG10_RESET_ETH)) |
/* minimal init for PCIe */
/* pci express 0 Endpoint Mode */
- mfsdr(SDR0_PE0DLPSET, reg);
+ mfsdr(SDRN_PESDR_DLPSET(0), reg);
reg &= (~0x00400000);
- mtsdr(SDR0_PE0DLPSET, reg);
+ mtsdr(SDRN_PESDR_DLPSET(0), reg);
/* pci express 1 Rootpoint Mode */
- mfsdr(SDR0_PE1DLPSET, reg);
+ mfsdr(SDRN_PESDR_DLPSET(1), reg);
reg |= 0x00400000;
- mtsdr(SDR0_PE1DLPSET, reg);
+ mtsdr(SDRN_PESDR_DLPSET(1), reg);
/* pci express 2 Rootpoint Mode */
- mfsdr(SDR0_PE2DLPSET, reg);
+ mfsdr(SDRN_PESDR_DLPSET(2), reg);
reg |= 0x00400000;
- mtsdr(SDR0_PE2DLPSET, reg);
+ mtsdr(SDRN_PESDR_DLPSET(2), reg);
out16(FPGA_REG1C,(in16 (FPGA_REG1C) &
~FPGA_REG1C_PE0_ROOTPOINT &
~FPGA_REG1C_PE1_ENDPOINT &
~FPGA_REG1C_PE2_ENDPOINT));
-#if defined(CONFIG_STRESS)
- /*
- * all this setting done by linux only needed by stress an charac. test
- * procedure
- * PCIe 1 Rootpoint PCIe2 Endpoint
- * PCIe 0 FIR Pre-emphasis Filter Coefficients & Transmit Driver
- * Power Level
- */
- for (i = 0, disp = 0; i < 8; i++, disp += 3) {
- mfsdr(SDR0_PE0HSSSET1L0 + disp, reg);
- reg |= 0x33000000;
- mtsdr(SDR0_PE0HSSSET1L0 + disp, reg);
- }
-
- /*
- * PCIe 1 FIR Pre-emphasis Filter Coefficients & Transmit Driver
- * Power Level
- */
- for (i = 0, disp = 0; i < 4; i++, disp += 3) {
- mfsdr(SDR0_PE1HSSSET1L0 + disp, reg);
- reg |= 0x33000000;
- mtsdr(SDR0_PE1HSSSET1L0 + disp, reg);
- }
-
- /*
- * PCIE 2 FIR Pre-emphasis Filter Coefficients & Transmit Driver
- * Power Level
- */
- for (i = 0, disp = 0; i < 4; i++, disp += 3) {
- mfsdr(SDR0_PE2HSSSET1L0 + disp, reg);
- reg |= 0x33000000;
- mtsdr(SDR0_PE2HSSSET1L0 + disp, reg);
- }
-
- reg = 0x21242222;
- mtsdr(SDR0_PE2UTLSET1, reg);
- reg = 0x11000000;
- mtsdr(SDR0_PE2UTLSET2, reg);
- /* pci express 1 Endpoint Mode */
- reg = 0x00004000;
- mtsdr(SDR0_PE2DLPSET, reg);
-
- mtsdr(SDR0_UART1, 0x2080005a); /* patch for TG */
-#endif
return 0;
}
#define MASK_ALE (1 << 21) /* our ALE is AD21 */
#define MASK_CLE (1 << 22) /* our CLE is AD22 */
-static void at91cap9adk_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void at91cap9adk_nand_hwcontrol(struct mtd_info *mtd,
+ int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
- IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
- switch (cmd) {
- case NAND_CTL_SETCLE:
- IO_ADDR_W |= MASK_CLE;
- break;
- case NAND_CTL_SETALE:
- IO_ADDR_W |= MASK_ALE;
- break;
- case NAND_CTL_CLRNCE:
- at91_set_gpio_value(AT91_PIN_PD15, 1);
- break;
- case NAND_CTL_SETNCE:
- at91_set_gpio_value(AT91_PIN_PD15, 0);
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
+ IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
+
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W |= MASK_CLE;
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W |= MASK_ALE;
+
+ at91_set_gpio_value(AT91_PIN_PD15, !(ctrl & NAND_NCE));
+ this->IO_ADDR_W = (void *) IO_ADDR_W;
}
- this->IO_ADDR_W = (void *) IO_ADDR_W;
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
int board_nand_init(struct nand_chip *nand)
{
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
#ifdef CFG_NAND_DBW_16
nand->options = NAND_BUSWIDTH_16;
#endif
- nand->hwcontrol = at91cap9adk_nand_hwcontrol;
+ nand->cmd_ctrl = at91cap9adk_nand_hwcontrol;
nand->chip_delay = 20;
return 0;
#define MASK_ALE (1 << 21) /* our ALE is AD21 */
#define MASK_CLE (1 << 22) /* our CLE is AD22 */
-static void at91sam9260ek_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void at91sam9260ek_nand_hwcontrol(struct mtd_info *mtd,
+ int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
- IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
- switch (cmd) {
- case NAND_CTL_SETCLE:
- IO_ADDR_W |= MASK_CLE;
- break;
- case NAND_CTL_SETALE:
- IO_ADDR_W |= MASK_ALE;
- break;
- case NAND_CTL_CLRNCE:
- at91_set_gpio_value(AT91_PIN_PC14, 1);
- break;
- case NAND_CTL_SETNCE:
- at91_set_gpio_value(AT91_PIN_PC14, 0);
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
+ IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
+
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W |= MASK_CLE;
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W |= MASK_ALE;
+
+ at91_set_gpio_value(AT91_PIN_PC14, !(ctrl & NAND_NCE));
+ this->IO_ADDR_W = (void *) IO_ADDR_W;
}
- this->IO_ADDR_W = (void *) IO_ADDR_W;
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static int at91sam9260ek_nand_ready(struct mtd_info *mtd)
int board_nand_init(struct nand_chip *nand)
{
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
#ifdef CFG_NAND_DBW_16
nand->options = NAND_BUSWIDTH_16;
#endif
- nand->hwcontrol = at91sam9260ek_nand_hwcontrol;
+ nand->cmd_ctrl = at91sam9260ek_nand_hwcontrol;
nand->dev_ready = at91sam9260ek_nand_ready;
nand->chip_delay = 20;
#define MASK_ALE (1 << 22) /* our ALE is AD22 */
#define MASK_CLE (1 << 21) /* our CLE is AD21 */
-static void at91sam9261ek_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void at91sam9261ek_nand_hwcontrol(struct mtd_info *mtd,
+ int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
- IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
- switch (cmd) {
- case NAND_CTL_SETCLE:
- IO_ADDR_W |= MASK_CLE;
- break;
- case NAND_CTL_SETALE:
- IO_ADDR_W |= MASK_ALE;
- break;
- case NAND_CTL_CLRNCE:
- at91_set_gpio_value(AT91_PIN_PC14, 1);
- break;
- case NAND_CTL_SETNCE:
- at91_set_gpio_value(AT91_PIN_PC14, 0);
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
+ IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
+
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W |= MASK_CLE;
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W |= MASK_ALE;
+
+ at91_set_gpio_value(AT91_PIN_PC14, !(ctrl & NAND_NCE));
+ this->IO_ADDR_W = (void *) IO_ADDR_W;
}
- this->IO_ADDR_W = (void *) IO_ADDR_W;
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static int at91sam9261ek_nand_ready(struct mtd_info *mtd)
int board_nand_init(struct nand_chip *nand)
{
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
#ifdef CFG_NAND_DBW_16
nand->options = NAND_BUSWIDTH_16;
#endif
- nand->hwcontrol = at91sam9261ek_nand_hwcontrol;
+ nand->cmd_ctrl = at91sam9261ek_nand_hwcontrol;
nand->dev_ready = at91sam9261ek_nand_ready;
nand->chip_delay = 20;
#define MASK_ALE (1 << 21) /* our ALE is AD21 */
#define MASK_CLE (1 << 22) /* our CLE is AD22 */
-static void at91sam9263ek_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void at91sam9263ek_nand_hwcontrol(struct mtd_info *mtd,
+ int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
- IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
- switch (cmd) {
- case NAND_CTL_SETCLE:
- IO_ADDR_W |= MASK_CLE;
- break;
- case NAND_CTL_SETALE:
- IO_ADDR_W |= MASK_ALE;
- break;
- case NAND_CTL_CLRNCE:
- at91_set_gpio_value(AT91_PIN_PD15, 1);
- break;
- case NAND_CTL_SETNCE:
- at91_set_gpio_value(AT91_PIN_PD15, 0);
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
+ IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
+
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W |= MASK_CLE;
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W |= MASK_ALE;
+
+ at91_set_gpio_value(AT91_PIN_PD15, !(ctrl & NAND_NCE));
+ this->IO_ADDR_W = (void *) IO_ADDR_W;
}
- this->IO_ADDR_W = (void *) IO_ADDR_W;
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static int at91sam9263ek_nand_ready(struct mtd_info *mtd)
int board_nand_init(struct nand_chip *nand)
{
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
#ifdef CFG_NAND_DBW_16
nand->options = NAND_BUSWIDTH_16;
#endif
- nand->hwcontrol = at91sam9263ek_nand_hwcontrol;
+ nand->cmd_ctrl = at91sam9263ek_nand_hwcontrol;
nand->dev_ready = at91sam9263ek_nand_ready;
nand->chip_delay = 20;
#define MASK_ALE (1 << 21) /* our ALE is AD21 */
#define MASK_CLE (1 << 22) /* our CLE is AD22 */
-static void at91sam9rlek_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void at91sam9rlek_nand_hwcontrol(struct mtd_info *mtd,
+ int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
- IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
- switch (cmd) {
- case NAND_CTL_SETCLE:
- IO_ADDR_W |= MASK_CLE;
- break;
- case NAND_CTL_SETALE:
- IO_ADDR_W |= MASK_ALE;
- break;
- case NAND_CTL_CLRNCE:
- at91_set_gpio_value(AT91_PIN_PB6, 1);
- break;
- case NAND_CTL_SETNCE:
- at91_set_gpio_value(AT91_PIN_PB6, 0);
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
+ IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
+
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W |= MASK_CLE;
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W |= MASK_ALE;
+
+ at91_set_gpio_value(AT91_PIN_PB6, !(ctrl & NAND_NCE));
+ this->IO_ADDR_W = (void *) IO_ADDR_W;
}
- this->IO_ADDR_W = (void *) IO_ADDR_W;
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static int at91sam9rlek_nand_ready(struct mtd_info *mtd)
int board_nand_init(struct nand_chip *nand)
{
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
#ifdef CFG_NAND_DBW_16
nand->options = NAND_BUSWIDTH_16;
#endif
- nand->hwcontrol = at91sam9rlek_nand_hwcontrol;
+ nand->cmd_ctrl = at91sam9rlek_nand_hwcontrol;
nand->dev_ready = at91sam9rlek_nand_ready;
nand->chip_delay = 20;
/*
* hardware specific access to control-lines
*/
-static void bfin_hwcontrol(struct mtd_info *mtd, int cmd)
+static void bfin_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
register struct nand_chip *this = mtd->priv;
+ u32 IO_ADDR_W = (u32) this->IO_ADDR_W;
- switch (cmd) {
-
- case NAND_CTL_SETCLE:
- this->IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_CLE;
- break;
- case NAND_CTL_CLRCLE:
- this->IO_ADDR_W = CFG_NAND_BASE;
- break;
-
- case NAND_CTL_SETALE:
- this->IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_ALE;
- break;
- case NAND_CTL_CLRALE:
- this->IO_ADDR_W = CFG_NAND_BASE;
- break;
- case NAND_CTL_SETNCE:
- case NAND_CTL_CLRNCE:
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if( ctrl & NAND_CLE )
+ IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_CLE;
+ else
+ IO_ADDR_W = CFG_NAND_BASE;
+ if( ctrl & NAND_ALE )
+ IO_ADDR_W = CFG_NAND_BASE + BFIN_NAND_ALE;
+ else
+ IO_ADDR_W = CFG_NAND_BASE;
+ this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
}
-
this->IO_ADDR_R = this->IO_ADDR_W;
/* Drain the writebuffer */
SSYNC();
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
int bfin_device_ready(struct mtd_info *mtd)
* argument are board-specific (per include/linux/mtd/nand.h):
* - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
* - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
- * - hwcontrol: hardwarespecific function for accesing control-lines
+ * - cmd_ctrl: hardwarespecific function for accesing control-lines
* - dev_ready: hardwarespecific function for accesing device ready/busy line
* - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
* only be provided if a hardware ECC is available
- * - eccmode: mode of ecc, see defines
+ * - ecc.mode: mode of ecc, see defines
* - chip_delay: chip dependent delay for transfering data from array to
* read regs (tR)
* - options: various chip options. They can partly be set to inform
*PORT(CONFIG_NAND_GPIO_PORT, IO_DIR) &= ~BFIN_NAND_READY;
*PORT(CONFIG_NAND_GPIO_PORT, IO_INEN) |= BFIN_NAND_READY;
- nand->hwcontrol = bfin_hwcontrol;
- nand->eccmode = NAND_ECC_SOFT;
+ nand->cmd_ctrl = bfin_hwcontrol;
+ nand->ecc.mode = NAND_ECC_SOFT;
nand->dev_ready = bfin_device_ready;
nand->chip_delay = 30;
}
*/
#include <common.h>
-
+#include <asm/io.h>
#if defined(CONFIG_CMD_NAND)
* hardware specific access to control-lines
* function borrowed from Linux 2.6 (drivers/mtd/nand/ppchameleonevb.c)
*/
-static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void ppchameleonevb_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd->priv;
ulong base = (ulong) this->IO_ADDR_W;
- switch(cmd) {
- case NAND_CTL_SETCLE:
- MACRO_NAND_CTL_SETCLE((unsigned long)base);
- break;
- case NAND_CTL_CLRCLE:
- MACRO_NAND_CTL_CLRCLE((unsigned long)base);
- break;
- case NAND_CTL_SETALE:
- MACRO_NAND_CTL_SETALE((unsigned long)base);
- break;
- case NAND_CTL_CLRALE:
- MACRO_NAND_CTL_CLRALE((unsigned long)base);
- break;
- case NAND_CTL_SETNCE:
- MACRO_NAND_ENABLE_CE((unsigned long)base);
- break;
- case NAND_CTL_CLRNCE:
- MACRO_NAND_DISABLE_CE((unsigned long)base);
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ MACRO_NAND_CTL_SETCLE((unsigned long)base);
+ else
+ MACRO_NAND_CTL_CLRCLE((unsigned long)base);
+ if ( ctrl & NAND_ALE )
+ MACRO_NAND_CTL_CLRCLE((unsigned long)base);
+ else
+ MACRO_NAND_CTL_CLRALE((unsigned long)base);
+ if ( ctrl & NAND_NCE )
+ MACRO_NAND_ENABLE_CE((unsigned long)base);
+ else
+ MACRO_NAND_DISABLE_CE((unsigned long)base);
}
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
* argument are board-specific (per include/linux/mtd/nand.h):
* - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
* - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
- * - hwcontrol: hardwarespecific function for accesing control-lines
+ * - cmd_ctrl: hardwarespecific function for accesing control-lines
* - dev_ready: hardwarespecific function for accesing device ready/busy line
* - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
* only be provided if a hardware ECC is available
- * - eccmode: mode of ecc, see defines
+ * - ecc.mode: mode of ecc, see defines
* - chip_delay: chip dependent delay for transfering data from array to
* read regs (tR)
* - options: various chip options. They can partly be set to inform
int board_nand_init(struct nand_chip *nand)
{
- nand->hwcontrol = ppchameleonevb_hwcontrol;
+ nand->cmd_ctrl = ppchameleonevb_hwcontrol;
nand->dev_ready = ppchameleonevb_device_ready;
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
nand->chip_delay = NAND_BIG_DELAY_US;
nand->options = NAND_SAMSUNG_LP_OPTIONS;
return 0;
#include <common.h>
#if defined(CONFIG_CMD_NAND)
-#if !defined(CFG_NAND_LEGACY)
+#if !defined(CONFIG_NAND_LEGACY)
#include <nand.h>
#include <asm/arch/pxa-regs.h>
/*
* not required for Monahans DFC
*/
-static void dfc_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void dfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
return;
}
}
-/*
- * These functions are quite problematic for the DFC. Luckily they are
- * not used in the current nand code, except for nand_command, which
- * we've defined our own anyway. The problem is, that we always need
- * to write 4 bytes to the DFC Data Buffer, but in these functions we
- * don't know if to buffer the bytes/half words until we've gathered 4
- * bytes or if to send them straight away.
- *
- * Solution: Don't use these with Mona's DFC and complain loudly.
- */
-static void dfc_write_word(struct mtd_info *mtd, u16 word)
-{
- printf("dfc_write_word: WARNING, this function does not work with the Monahans DFC!\n");
-}
-static void dfc_write_byte(struct mtd_info *mtd, u_char byte)
-{
- printf("dfc_write_byte: WARNING, this function does not work with the Monahans DFC!\n");
-}
-
-/* The original:
- * static void dfc_read_buf(struct mtd_info *mtd, const u_char *buf, int len)
- *
- * Shouldn't this be "u_char * const buf" ?
- */
static void dfc_read_buf(struct mtd_info *mtd, u_char* const buf, int len)
{
int i=0, j;
*/
static u16 dfc_read_word(struct mtd_info *mtd)
{
- printf("dfc_write_byte: UNIMPLEMENTED.\n");
+ printf("dfc_read_word: UNIMPLEMENTED.\n");
return 0;
}
/* this function is called after Programm and Erase Operations to
* check for success or failure */
-static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this)
{
unsigned long ndsr=0, event=0;
+ int state = this->state;
if(state == FL_WRITING) {
event = NDSR_CS0_CMDD | NDSR_CS0_BBD;
* - dev_ready: hardwarespecific function for accesing device ready/busy line
* - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
* only be provided if a hardware ECC is available
- * - eccmode: mode of ecc, see defines
+ * - ecc.mode: mode of ecc, see defines
* - chip_delay: chip dependent delay for transfering data from array to
* read regs (tR)
* - options: various chip options. They can partly be set to inform
/* wait(10); */
- nand->hwcontrol = dfc_hwcontrol;
+ nand->cmd_ctrl = dfc_hwcontrol;
/* nand->dev_ready = dfc_device_ready; */
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
nand->options = NAND_BUSWIDTH_16;
nand->waitfunc = dfc_wait;
nand->read_byte = dfc_read_byte;
- nand->write_byte = dfc_write_byte;
nand->read_word = dfc_read_word;
- nand->write_word = dfc_write_word;
nand->read_buf = dfc_read_buf;
nand->write_buf = dfc_write_buf;
nand->cmdfunc = dfc_cmdfunc;
- nand->autooob = &delta_oob;
+/* nand->autooob = &delta_oob; */
nand->badblock_pattern = &delta_bbt_descr;
return 0;
}
#include <command.h>
#include <image.h>
#include <asm/byteorder.h>
-#if defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_NAND_LEGACY)
#include <linux/mtd/nand_legacy.h>
#endif
#include <fat.h>
extern int flash_sect_protect (int, ulong, ulong);
extern int flash_write (char *, ulong, ulong);
-#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_LEGACY)
/* references to names in cmd_nand.c */
#define NANDRW_READ 0x01
#define NANDRW_WRITE 0x00
int off, rc;
uint nbytes;
int k;
-#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_LEGACY)
int total;
#endif
debug ("flash_sect_erase(%lx, %lx);\n", start, end);
flash_sect_erase (start, end);
} else {
-#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_LEGACY)
printf ("Updating NAND FLASH with image %s\n",
au_image[i].name);
debug ("nand_legacy_erase(%lx, %lx);\n", start, end);
rc = flash_write ((char *)addr, start,
(nbytes + 1) & ~1);
} else {
-#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_LEGACY)
debug ("nand_legacy_rw(%p, %lx, %x)\n",
addr, start, nbytes);
rc = nand_legacy_rw (nand_dev_desc,
rc = crc32 (0, (uchar *)(start + off),
image_get_data_size (hdr));
} else {
-#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_LEGACY)
rc = nand_legacy_rw (nand_dev_desc,
NANDRW_READ | NANDRW_JFFS2 |
NANDRW_JFFS2_SKIP,
/*
* hardware specific access to control-lines
*/
-static void esd405ep_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void esd405ep_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- switch(cmd) {
- case NAND_CTL_SETCLE:
- out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CLE);
- break;
- case NAND_CTL_CLRCLE:
- out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_CLE);
- break;
- case NAND_CTL_SETALE:
- out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_ALE);
- break;
- case NAND_CTL_CLRALE:
- out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_ALE);
- break;
- case NAND_CTL_SETNCE:
- out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_CE);
- break;
- case NAND_CTL_CLRNCE:
- out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CE);
- break;
+ struct nand_chip *this = mtd->priv;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CLE);
+ else
+ out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_CLE);
+ if ( ctrl & NAND_ALE )
+ out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_ALE);
+ else
+ out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_ALE);
+ if ( ctrl & NAND_NCE )
+ out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) & ~CFG_NAND_CE);
+ else
+ out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CFG_NAND_CE);
}
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
/*
* Initialize nand_chip structure
*/
- nand->hwcontrol = esd405ep_nand_hwcontrol;
+ nand->cmd_ctrl = esd405ep_nand_hwcontrol;
nand->dev_ready = esd405ep_nand_device_ready;
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
nand->chip_delay = NAND_BIG_DELAY_US;
nand->options = NAND_SAMSUNG_LP_OPTIONS;
return 0;
{"DRAMPLL_NDiv_1"}, /* 01 */
{"DRAMPLL_NDiv_0"}}; /* 00 */
-extern void flush_data_cache (void);
-extern void invalidate_l1_instruction_cache (void);
extern flash_info_t flash_info[];
/* ------------------------------------------------------------------------- */
my_remap_gt_regs_bootm (CFG_GT_REGS, CFG_DFL_GT_REGS);
icache_disable ();
- invalidate_l1_instruction_cache ();
- flush_data_cache ();
dcache_disable ();
}
--- /dev/null
+#
+# (C) Copyright 2000-2006
+# 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 = $(obj)lib$(BOARD).a
+
+COBJS = $(BOARD).o flash.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
--- /dev/null
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+# Coldfire contribution by Bernhard Kuhn <bkuhn@metrowerks.com>
+#
+# 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
+#
+
+TEXT_BASE = 0xFF800000
--- /dev/null
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
+ * 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 <asm/immap.h>
+
+#ifndef CFG_FLASH_CFI
+typedef unsigned short FLASH_PORT_WIDTH;
+typedef volatile unsigned short FLASH_PORT_WIDTHV;
+
+#define FPW FLASH_PORT_WIDTH
+#define FPWV FLASH_PORT_WIDTHV
+
+#define FLASH_CYCLE1 0x5555
+#define FLASH_CYCLE2 0x2aaa
+
+#define SYNC __asm__("nop")
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+
+ulong flash_get_size(FPWV * addr, flash_info_t * info);
+int flash_get_offsets(ulong base, flash_info_t * info);
+int write_word(flash_info_t * info, FPWV * dest, u16 data);
+void inline spin_wheel(void);
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+ulong flash_init(void)
+{
+ ulong size = 0;
+ ulong fbase = 0;
+
+ fbase = (ulong) CFG_FLASH_BASE;
+ flash_get_size((FPWV *) fbase, &flash_info[0]);
+ flash_get_offsets((ulong) fbase, &flash_info[0]);
+ fbase += flash_info[0].size;
+ size += flash_info[0].size;
+
+ /* Protect monitor and environment sectors */
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
+
+ return size;
+}
+
+int flash_get_offsets(ulong base, flash_info_t * info)
+{
+ int j, k;
+
+ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
+
+ info->start[0] = base;
+ for (k = 0, j = 0; j < CFG_SST_SECT; j++, k++) {
+ info->start[k + 1] = info->start[k] + CFG_SST_SECTSZ;
+ info->protect[k] = 0;
+ }
+ }
+
+ return ERR_OK;
+}
+
+void flash_print_info(flash_info_t * info)
+{
+ int i;
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_SST:
+ printf("SST ");
+ break;
+ default:
+ printf("Unknown Vendor ");
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_SST6401B:
+ printf("SST39VF6401B\n");
+ break;
+ default:
+ printf("Unknown Chip Type\n");
+ return;
+ }
+
+ if (info->size > 0x100000) {
+ int remainder;
+
+ printf(" Size: %ld", info->size >> 20);
+
+ remainder = (info->size % 0x100000);
+ if (remainder) {
+ remainder >>= 10;
+ remainder = (int)((float)
+ (((float)remainder / (float)1024) *
+ 10000));
+ printf(".%d ", remainder);
+ }
+
+ printf("MB in %d Sectors\n", info->sector_count);
+ } else
+ printf(" Size: %ld KB in %d Sectors\n",
+ info->size >> 10, info->sector_count);
+
+ printf(" Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; ++i) {
+ if ((i % 5) == 0)
+ printf("\n ");
+ printf(" %08lX%s",
+ info->start[i], info->protect[i] ? " (RO)" : " ");
+ }
+ printf("\n");
+}
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+ulong flash_get_size(FPWV * addr, flash_info_t * info)
+{
+ u16 value;
+
+ addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
+ addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
+ addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
+
+ switch (addr[0] & 0xffff) {
+ case (u8) SST_MANUFACT:
+ info->flash_id = FLASH_MAN_SST;
+ value = addr[1];
+ break;
+ default:
+ printf("Unknown Flash\n");
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+
+ *addr = (FPW) 0x00F000F0;
+ return (0); /* no or unknown flash */
+ }
+
+ switch (value) {
+ case (u16) SST_ID_xF6401B:
+ info->flash_id += FLASH_SST6401B;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ break;
+ }
+
+ info->sector_count = 0;
+ info->size = 0;
+ info->sector_count = CFG_SST_SECT;
+ info->size = CFG_SST_SECT * CFG_SST_SECTSZ;
+
+ /* reset ID mode */
+ *addr = (FPWV) 0x00F000F0;
+
+ if (info->sector_count > CFG_MAX_FLASH_SECT) {
+ printf("** ERROR: sector count %d > max (%d) **\n",
+ info->sector_count, CFG_MAX_FLASH_SECT);
+ info->sector_count = CFG_MAX_FLASH_SECT;
+ }
+
+ return (info->size);
+}
+
+int flash_erase(flash_info_t * info, int s_first, int s_last)
+{
+ FPWV *addr;
+ int flag, prot, sect, count;
+ ulong type, start, last;
+ int rcode = 0, flashtype = 0;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN)
+ printf("- missing\n");
+ else
+ printf("- no sectors to erase\n");
+ return 1;
+ }
+
+ type = (info->flash_id & FLASH_VENDMASK);
+
+ switch (type) {
+ case FLASH_MAN_SST:
+ flashtype = 1;
+ break;
+ default:
+ type = (info->flash_id & FLASH_VENDMASK);
+ printf("Can't erase unknown flash type %08lx - aborted\n",
+ info->flash_id);
+ return 1;
+ }
+
+ prot = 0;
+ for (sect = s_first; sect <= s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+
+ if (prot)
+ printf("- Warning: %d protected sectors will not be erased!\n",
+ prot);
+ else
+ printf("\n");
+
+ flag = disable_interrupts();
+
+ start = get_timer(0);
+ last = start;
+
+ if ((s_last - s_first) == (CFG_SST_SECT - 1)) {
+ if (prot == 0) {
+ addr = (FPWV *) info->start[0];
+
+ addr[FLASH_CYCLE1] = 0x00AA; /* unlock */
+ addr[FLASH_CYCLE2] = 0x0055; /* unlock */
+ addr[FLASH_CYCLE1] = 0x0080; /* erase mode */
+ addr[FLASH_CYCLE1] = 0x00AA; /* unlock */
+ addr[FLASH_CYCLE2] = 0x0055; /* unlock */
+ *addr = 0x0030; /* erase chip */
+
+ count = 0;
+ start = get_timer(0);
+
+ while ((*addr & 0x0080) != 0x0080) {
+ if (count++ > 0x10000) {
+ spin_wheel();
+ count = 0;
+ }
+
+ if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
+ printf("Timeout\n");
+ *addr = 0x00F0; /* reset to read mode */
+
+ return 1;
+ }
+ }
+
+ *addr = 0x00F0; /* reset to read mode */
+
+ printf("\b. done\n");
+
+ if (flag)
+ enable_interrupts();
+
+ return 0;
+ } else if (prot == CFG_SST_SECT) {
+ return 1;
+ }
+ }
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+
+ addr = (FPWV *) (info->start[sect]);
+
+ printf(".");
+
+ /* arm simple, non interrupt dependent timer */
+ start = get_timer(0);
+
+ switch (flashtype) {
+ case 1:
+ {
+ FPWV *base; /* first address in bank */
+
+ flag = disable_interrupts();
+
+ base = (FPWV *) (CFG_FLASH_BASE); /* First sector */
+
+ base[FLASH_CYCLE1] = 0x00AA; /* unlock */
+ base[FLASH_CYCLE2] = 0x0055; /* unlock */
+ base[FLASH_CYCLE1] = 0x0080; /* erase mode */
+ base[FLASH_CYCLE1] = 0x00AA; /* unlock */
+ base[FLASH_CYCLE2] = 0x0055; /* unlock */
+ *addr = 0x0050; /* erase sector */
+
+ if (flag)
+ enable_interrupts();
+
+ while ((*addr & 0x0080) != 0x0080) {
+ if (get_timer(start) >
+ CFG_FLASH_ERASE_TOUT) {
+ printf("Timeout\n");
+ *addr = 0x00F0; /* reset to read mode */
+
+ rcode = 1;
+ break;
+ }
+ }
+
+ *addr = 0x00F0; /* reset to read mode */
+ break;
+ }
+ } /* switch (flashtype) */
+ }
+ }
+ printf(" done\n");
+
+ if (flag)
+ enable_interrupts();
+
+ return rcode;
+}
+
+int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+ ulong wp, count;
+ u16 data;
+ int rc, port_width;
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ return 4;
+
+ /* get lower word aligned address */
+ wp = addr;
+ port_width = sizeof(FPW);
+
+ /* handle unaligned start bytes */
+ if (wp & 1) {
+ data = *((FPWV *) wp);
+ data = (data << 8) | *src;
+
+ if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
+ return (rc);
+
+ wp++;
+ cnt -= 1;
+ src++;
+ }
+
+ while (cnt >= 2) {
+ /*
+ * handle word aligned part
+ */
+ count = 0;
+ data = *((FPWV *) src);
+
+ if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
+ return (rc);
+
+ wp += 2;
+ src += 2;
+ cnt -= 2;
+
+ if (count++ > 0x800) {
+ spin_wheel();
+ count = 0;
+ }
+ }
+ /* handle word aligned part */
+ if (cnt) {
+ /* handle word aligned part */
+ count = 0;
+ data = *((FPWV *) wp);
+
+ data = (data & 0x00FF) | (*src << 8);
+
+ if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
+ return (rc);
+
+ wp++;
+ src++;
+ cnt -= 1;
+ if (count++ > 0x800) {
+ spin_wheel();
+ count = 0;
+ }
+ }
+
+ if (cnt == 0)
+ return ERR_OK;
+
+ return ERR_OK;
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash
+ * A word is 16 bits, whichever the bus width of the flash bank
+ * (not an individual chip) is.
+ *
+ * returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int write_word(flash_info_t * info, FPWV * dest, u16 data)
+{
+ ulong start;
+ int flag;
+ int res = 0; /* result, assume success */
+ FPWV *base; /* first address in flash bank */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*dest & (u8) data) != (u8) data) {
+ return (2);
+ }
+
+ base = (FPWV *) (CFG_FLASH_BASE);
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
+ base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
+ base[FLASH_CYCLE1] = (u8) 0x00A000A0; /* selects program mode */
+
+ *dest = data; /* start programming the data */
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ start = get_timer(0);
+
+ /* data polling for D7 */
+ while (res == 0
+ && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ *dest = (u8) 0x00F000F0; /* reset bank */
+ res = 1;
+ }
+ }
+
+ *dest++ = (u8) 0x00F000F0; /* reset bank */
+
+ return (res);
+}
+
+void inline spin_wheel(void)
+{
+ static int p = 0;
+ static char w[] = "\\/-";
+
+ printf("\010%c", w[p]);
+ (++p == 3) ? (p = 0) : 0;
+}
+
+#endif
--- /dev/null
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ * Hayden Fraser (Hayden.Fraser@freescale.com)
+ *
+ * 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 <asm/immap.h>
+
+int checkboard(void)
+{
+ puts("Board: ");
+ puts("Freescale MCF5253 DEMO\n");
+ return 0;
+};
+
+phys_size_t initdram(int board_type)
+{
+ u32 dramsize = 0;
+
+ /*
+ * Check to see if the SDRAM has already been initialized
+ * by a run control tool
+ */
+ if (!(mbar_readLong(MCFSIM_DCR) & 0x8000)) {
+ u32 RC, temp;
+
+ RC = (CFG_CLK / 1000000) >> 1;
+ RC = (RC * 15) >> 4;
+
+ /* Initialize DRAM Control Register: DCR */
+ mbar_writeShort(MCFSIM_DCR, (0x8400 | RC));
+ __asm__("nop");
+
+ mbar_writeLong(MCFSIM_DACR0, 0x00003224);
+ __asm__("nop");
+
+ /* Initialize DMR0 */
+ dramsize = (CFG_SDRAM_SIZE << 20);
+ temp = (dramsize - 1) & 0xFFFC0000;
+ mbar_writeLong(MCFSIM_DMR0, temp | 1);
+ __asm__("nop");
+
+ mbar_writeLong(MCFSIM_DACR0, 0x0000322c);
+ __asm__("nop");
+
+ /* Write to this block to initiate precharge */
+ *(u32 *) (CFG_SDRAM_BASE) = 0xa5a5a5a5;
+ __asm__("nop");
+
+ /* Set RE bit in DACR */
+ mbar_writeLong(MCFSIM_DACR0,
+ mbar_readLong(MCFSIM_DACR0) | 0x8000);
+ __asm__("nop");
+
+ /* Wait for at least 8 auto refresh cycles to occur */
+ udelay(500);
+
+ /* Finish the configuration by issuing the MRS */
+ mbar_writeLong(MCFSIM_DACR0,
+ mbar_readLong(MCFSIM_DACR0) | 0x0040);
+ __asm__("nop");
+
+ *(u32 *) (CFG_SDRAM_BASE + 0x800) = 0xa5a5a5a5;
+ }
+
+ return dramsize;
+}
+
+int testdram(void)
+{
+ /* TODO: XXX XXX XXX */
+ printf("DRAM test not implemented!\n");
+
+ return (0);
+}
+
+#ifdef CONFIG_CMD_IDE
+#include <ata.h>
+int ide_preinit(void)
+{
+ return (0);
+}
+
+void ide_set_reset(int idereset)
+{
+ volatile atac_t *ata = (atac_t *) CFG_ATA_BASE_ADDR;
+ long period;
+ /* t1, t2, t3, t4, t5, t6, t9, tRD, tA */
+ int piotms[5][9] = { {70, 165, 60, 30, 50, 5, 20, 0, 35}, /* PIO 0 */
+ {50, 125, 45, 20, 35, 5, 15, 0, 35}, /* PIO 1 */
+ {30, 100, 30, 15, 20, 5, 10, 0, 35}, /* PIO 2 */
+ {30, 80, 30, 10, 20, 5, 10, 0, 35}, /* PIO 3 */
+ {25, 70, 20, 10, 20, 5, 10, 0, 35} /* PIO 4 */
+ };
+
+ if (idereset) {
+ ata->cr = 0; /* control reset */
+ udelay(100);
+ } else {
+ mbar2_writeLong(CIM_MISCCR, CIM_MISCCR_CPUEND);
+
+#define CALC_TIMING(t) (t + period - 1) / period
+ period = 1000000000 / (CFG_CLK / 2); /* period in ns */
+
+ /*ata->ton = CALC_TIMING (180); */
+ ata->t1 = CALC_TIMING(piotms[2][0]);
+ ata->t2w = CALC_TIMING(piotms[2][1]);
+ ata->t2r = CALC_TIMING(piotms[2][1]);
+ ata->ta = CALC_TIMING(piotms[2][8]);
+ ata->trd = CALC_TIMING(piotms[2][7]);
+ ata->t4 = CALC_TIMING(piotms[2][3]);
+ ata->t9 = CALC_TIMING(piotms[2][6]);
+
+ ata->cr = 0x40; /* IORDY enable */
+ udelay(2000);
+ ata->cr |= 0x01; /* IORDY enable */
+ }
+}
+#endif /* CONFIG_CMD_IDE */
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * 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
+ */
+
+OUTPUT_ARCH(m68k)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/mcf52x2/start.o (.text)
+ lib_m68k/traps.o (.text)
+ cpu/mcf52x2/interrupts.o (.text)
+ common/dlmalloc.o (.text)
+ lib_generic/zlib.o (.text)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/environment.o (.text)
+
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+
+ .reloc :
+ {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ _sbss = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
phys_size_t initdram(int board_type)
{
- int i;
-
/*
* Check to see if the SDRAM has already been initialized
* by a run control tool
/* Initialize DRAM Control Register: DCR */
mbar_writeShort(MCFSIM_DCR, (0x8400 | RC));
+ asm("nop");
- mbar_writeLong(MCFSIM_DACR0, 0x00003224);
+ mbar_writeLong(MCFSIM_DACR0, 0x00002320);
+ asm("nop");
/* Initialize DMR0 */
dramsize = ((CFG_SDRAM_SIZE << 20) - 1) & 0xFFFC0000;
mbar_writeLong(MCFSIM_DMR0, dramsize | 1);
+ asm("nop");
- mbar_writeLong(MCFSIM_DACR0, 0x0000322c);
+ mbar_writeLong(MCFSIM_DACR0, 0x00002328);
+ asm("nop");
/* Write to this block to initiate precharge */
*(u32 *) (CFG_SDRAM_BASE) = 0xa5a5a5a5;
+ asm("nop");
/* Set RE bit in DACR */
mbar_writeLong(MCFSIM_DACR0,
mbar_readLong(MCFSIM_DACR0) | 0x8000);
+ asm("nop");
/* Wait for at least 8 auto refresh cycles to occur */
udelay(500);
/* Finish the configuration by issuing the MRS */
mbar_writeLong(MCFSIM_DACR0,
mbar_readLong(MCFSIM_DACR0) | 0x0040);
+ asm("nop");
*(u32 *) (CFG_SDRAM_BASE + 0x800) = 0xa5a5a5a5;
}
MCFSDRAMC_DCR = (0
| MCFSDRAMC_DCR_RTIM_6
| MCFSDRAMC_DCR_RC((15 * dramclk)>>4));
+ asm("nop");
/* Initialize DACR0 */
MCFSDRAMC_DACR0 = (0
| MCFSDRAMC_DACR_CASL(1)
| MCFSDRAMC_DACR_CBM(3)
| MCFSDRAMC_DACR_PS_32);
+ asm("nop");
/* Initialize DMR0 */
MCFSDRAMC_DMR0 = (0
| ((dramsize - 1) & 0xFFFC0000)
| MCFSDRAMC_DMR_V);
+ asm("nop");
/* Set IP (bit 3) in DACR */
MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IP;
+ asm("nop");
/* Wait 30ns to allow banks to precharge */
for (i = 0; i < 5; i++) {
/* Write to this block to initiate precharge */
*(u32 *)(CFG_SDRAM_BASE) = 0xA5A59696;
+ asm("nop");
/* Set RE (bit 15) in DACR */
MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_RE;
+ asm("nop");
/* Wait for at least 8 auto refresh cycles to occur */
for (i = 0; i < 2000; i++) {
/* Finish the configuration by issuing the IMRS. */
MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IMRS;
+ asm("nop");
/* Write to the SDRAM Mode Register */
*(u32 *)(CFG_SDRAM_BASE + 0x400) = 0xA5A59696;
lib_generic/string.o (.text)
lib_generic/vsprintf.o (.text)
lib_generic/crc32.o (.text)
- lib_generic/zlib.o (.text)
-/* . = env_offset; */
+ . = env_offset;
common/environment.o(.text)
*(.text)
#define SET_ALE 0x08
#define CLR_ALE ~SET_ALE
-static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtdinfo->priv;
- volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS;
+/* volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS; TODO: handle wp */
u32 nand_baseaddr = (u32) this->IO_ADDR_W;
- switch (cmd) {
- case NAND_CTL_SETNCE:
- case NAND_CTL_CLRNCE:
- break;
- case NAND_CTL_SETCLE:
- nand_baseaddr |= SET_CLE;
- break;
- case NAND_CTL_CLRCLE:
- nand_baseaddr &= CLR_CLE;
- break;
- case NAND_CTL_SETALE:
- nand_baseaddr |= SET_ALE;
- break;
- case NAND_CTL_CLRALE:
- nand_baseaddr |= CLR_ALE;
- break;
- case NAND_CTL_SETWP:
- fbcs->csmr2 |= FBCS_CSMR_WP;
- break;
- case NAND_CTL_CLRWP:
- fbcs->csmr2 &= ~FBCS_CSMR_WP;
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ nand_baseaddr |= SET_CLE;
+ else
+ nand_baseaddr &= CLR_CLE;
+ if ( ctrl & NAND_ALE )
+ nand_baseaddr |= SET_ALE;
+ else
+ nand_baseaddr &= CLR_ALE;
}
this->IO_ADDR_W = (void __iomem *)(nand_baseaddr);
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static void nand_write_byte(struct mtd_info *mtdinfo, u_char byte)
gpio->podr_timer = 0;
nand->chip_delay = 50;
- nand->eccmode = NAND_ECC_SOFT;
- nand->hwcontrol = nand_hwcontrol;
+ nand->ecc.mode = NAND_ECC_SOFT;
+ nand->cmd_ctrl = nand_hwcontrol;
nand->read_byte = nand_read_byte;
nand->write_byte = nand_write_byte;
nand->dev_ready = nand_dev_ready;
#include <linux/mtd/mtd.h>
#define SET_CLE 0x10
-#define CLR_CLE ~SET_CLE
#define SET_ALE 0x08
-#define CLR_ALE ~SET_ALE
-static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtdinfo->priv;
volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS;
u32 nand_baseaddr = (u32) this->IO_ADDR_W;
- switch (cmd) {
- case NAND_CTL_SETNCE:
- case NAND_CTL_CLRNCE:
- break;
- case NAND_CTL_SETCLE:
- nand_baseaddr |= SET_CLE;
- break;
- case NAND_CTL_CLRCLE:
- nand_baseaddr &= CLR_CLE;
- break;
- case NAND_CTL_SETALE:
- nand_baseaddr |= SET_ALE;
- break;
- case NAND_CTL_CLRALE:
- nand_baseaddr |= CLR_ALE;
- break;
- case NAND_CTL_SETWP:
- fbcs->csmr2 |= FBCS_CSMR_WP;
- break;
- case NAND_CTL_CLRWP:
- fbcs->csmr2 &= ~FBCS_CSMR_WP;
- break;
- }
- this->IO_ADDR_W = (void __iomem *)(nand_baseaddr);
-}
+ if (ctrl & NAND_CTRL_CHANGE) {
+ ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
+ IO_ADDR_W &= ~(SET_ALE | SE_CLE);
-static void nand_write_byte(struct mtd_info *mtdinfo, u_char byte)
-{
- struct nand_chip *this = mtdinfo->priv;
- *((volatile u8 *)(this->IO_ADDR_W)) = byte;
-}
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W |= SET_CLE;
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W |= SET_ALE;
-static u8 nand_read_byte(struct mtd_info *mtdinfo)
-{
- struct nand_chip *this = mtdinfo->priv;
- return (u8) (*((volatile u8 *)this->IO_ADDR_R));
-}
+ at91_set_gpio_value(AT91_PIN_PD15, !(ctrl & NAND_NCE));
+ this->IO_ADDR_W = (void *)IO_ADDR_W;
-static int nand_dev_ready(struct mtd_info *mtdinfo)
-{
- return 1;
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
int board_nand_init(struct nand_chip *nand)
{
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
+ volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS;
*((volatile u16 *)CFG_LATCH_ADDR) |= 0x0004;
+ fbcs->csmr2 &= ~FBCS_CSMR_WP;
/* set up pin configuration */
gpio->par_timer &= ~GPIO_PAR_TIN3_TIN3;
gpio->podr_timer = 0;
nand->chip_delay = 50;
- nand->eccmode = NAND_ECC_SOFT;
- nand->hwcontrol = nand_hwcontrol;
- nand->read_byte = nand_read_byte;
- nand->write_byte = nand_write_byte;
- nand->dev_ready = nand_dev_ready;
+ nand->ecc.mode = NAND_ECC_SOFT;
+ nand->cmd_ctrl = nand_hwcontrol;
return 0;
}
--- /dev/null
+#
+# (C) Copyright 2000-2003
+# 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 = $(obj)lib$(BOARD).a
+
+COBJS = $(BOARD).o mii.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
--- /dev/null
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+# Coldfire contribution by Bernhard Kuhn <bkuhn@metrowerks.com>
+#
+# 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
+#
+
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
--- /dev/null
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
+ * 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 <spi.h>
+#include <asm/immap.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkboard(void)
+{
+ /*
+ * need to to:
+ * Check serial flash size. if 2mb evb, else 8mb demo
+ */
+ puts("Board: ");
+ puts("Freescale M54451 EVB\n");
+ return 0;
+};
+
+phys_size_t initdram(int board_type)
+{
+ u32 dramsize;
+#ifdef CONFIG_CF_SBF
+ /*
+ * Serial Boot: The dram is already initialized in start.S
+ * only require to return DRAM size
+ */
+ dramsize = CFG_SDRAM_SIZE * 0x100000 >> 1;
+#else
+ volatile sdramc_t *sdram = (volatile sdramc_t *)(MMAP_SDRAM);
+ volatile gpio_t *gpio = (volatile gpio_t *)(MMAP_GPIO);
+ u32 i;
+
+ dramsize = CFG_SDRAM_SIZE * 0x100000;
+
+ if ((sdram->sdcfg1 == CFG_SDRAM_CFG1) &&
+ (sdram->sdcfg2 == CFG_SDRAM_CFG2))
+ return dramsize;
+
+ for (i = 0x13; i < 0x20; i++) {
+ if (dramsize == (1 << i))
+ break;
+ }
+ i--;
+
+ gpio->mscr_sdram = 0x44;
+
+ sdram->sdcs0 = (CFG_SDRAM_BASE | i);
+
+ sdram->sdcfg1 = CFG_SDRAM_CFG1;
+ sdram->sdcfg2 = CFG_SDRAM_CFG2;
+
+ udelay(200);
+
+ /* Issue PALL */
+ sdram->sdcr = CFG_SDRAM_CTRL | 2;
+ __asm__("nop");
+
+ /* Perform two refresh cycles */
+ sdram->sdcr = CFG_SDRAM_CTRL | 4;
+ __asm__("nop");
+ sdram->sdcr = CFG_SDRAM_CTRL | 4;
+ __asm__("nop");
+
+ /* Issue LEMR */
+ sdram->sdmr = CFG_SDRAM_MODE;
+ __asm__("nop");
+ sdram->sdmr = CFG_SDRAM_EMOD;
+ __asm__("nop");
+
+ sdram->sdcr = (CFG_SDRAM_CTRL & ~0x80000000) | 0x10000000;
+
+ udelay(100);
+#endif
+ return (dramsize);
+};
+
+int testdram(void)
+{
+ /* TODO: XXX XXX XXX */
+ printf("DRAM test not implemented!\n");
+
+ return (0);
+}
--- /dev/null
+/*
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
+ * 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 <asm/fec.h>
+#include <asm/immap.h>
+
+#include <config.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI)
+#undef MII_DEBUG
+#undef ET_DEBUG
+
+int fecpin_setclear(struct eth_device *dev, int setclear)
+{
+ volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
+ struct fec_info_s *info = (struct fec_info_s *)dev->priv;
+
+ if (setclear) {
+ gpio->par_feci2c |=
+ (GPIO_PAR_FECI2C_MDC0_MDC0 | GPIO_PAR_FECI2C_MDIO0_MDIO0);
+
+ if (info->iobase == CFG_FEC0_IOBASE)
+ gpio->par_fec |= GPIO_PAR_FEC_FEC0_RMII_GPIO;
+ else
+ gpio->par_fec |= GPIO_PAR_FEC_FEC1_RMII_ATA;
+ } else {
+ gpio->par_feci2c &=
+ ~(GPIO_PAR_FECI2C_MDC0_MDC0 | GPIO_PAR_FECI2C_MDIO0_MDIO0);
+
+ if (info->iobase == CFG_FEC0_IOBASE)
+ gpio->par_fec &= GPIO_PAR_FEC_FEC0_MASK;
+ else
+ gpio->par_fec &= GPIO_PAR_FEC_FEC1_MASK;
+ }
+ return 0;
+}
+
+#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+
+/* Make MII read/write commands for the FEC. */
+#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | (REG & 0x1f) << 18))
+
+#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | (REG & 0x1f) << 18) | (VAL & 0xffff))
+
+/* PHY identification */
+#define PHY_ID_KSZ8041NL 0x00221512
+#define STR_ID_KSZ8041NL "KSZ8041NL"
+
+/****************************************************************************
+ * mii_init -- Initialize the MII for MII command without ethernet
+ * This function is a subset of eth_init
+ ****************************************************************************
+ */
+void mii_reset(struct fec_info_s *info)
+{
+ volatile fec_t *fecp = (fec_t *) (info->miibase);
+ struct eth_device *dev;
+ int i, miispd;
+ u16 rst = 0;
+
+ dev = eth_get_dev();
+
+ miispd = (gd->bus_clk / 1000000) / 5;
+ fecp->mscr = miispd << 1;
+
+ miiphy_write(dev->name, info->phy_addr, PHY_BMCR, PHY_BMCR_RESET);
+ for (i = 0; i < FEC_RESET_DELAY; ++i) {
+ udelay(500);
+ miiphy_read(dev->name, info->phy_addr, PHY_BMCR, &rst);
+ if ((rst & PHY_BMCR_RESET) == 0)
+ break;
+ }
+ if (i == FEC_RESET_DELAY)
+ printf("Mii reset timeout %d\n", i);
+}
+
+/* send command to phy using mii, wait for result */
+uint mii_send(uint mii_cmd)
+{
+ struct fec_info_s *info;
+ struct eth_device *dev;
+ volatile fec_t *ep;
+ uint mii_reply;
+ int j = 0;
+
+ /* retrieve from register structure */
+ dev = eth_get_dev();
+ info = dev->priv;
+
+ ep = (fec_t *) info->miibase;
+
+ ep->mmfr = mii_cmd; /* command to phy */
+
+ /* wait for mii complete */
+ while (!(ep->eir & FEC_EIR_MII) && (j < MCFFEC_TOUT_LOOP)) {
+ udelay(1);
+ j++;
+ }
+ if (j >= MCFFEC_TOUT_LOOP) {
+ printf("MII not complete\n");
+ return -1;
+ }
+
+ mii_reply = ep->mmfr; /* result from phy */
+ ep->eir = FEC_EIR_MII; /* clear MII complete */
+#ifdef ET_DEBUG
+ printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
+ __FILE__, __LINE__, __FUNCTION__, mii_cmd, mii_reply);
+#endif
+
+ return (mii_reply & 0xffff); /* data read from phy */
+}
+#endif /* CFG_DISCOVER_PHY || (CONFIG_MII) */
+
+#if defined(CFG_DISCOVER_PHY)
+int mii_discover_phy(struct eth_device *dev)
+{
+#define MAX_PHY_PASSES 11
+ struct fec_info_s *info = dev->priv;
+ int phyaddr, pass;
+ uint phyno, phytype;
+
+ if (info->phyname_init)
+ return info->phy_addr;
+
+ phyaddr = -1; /* didn't find a PHY yet */
+ for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
+ if (pass > 1) {
+ /* PHY may need more time to recover from reset.
+ * The LXT970 needs 50ms typical, no maximum is
+ * specified, so wait 10ms before try again.
+ * With 11 passes this gives it 100ms to wake up.
+ */
+ udelay(10000); /* wait 10ms */
+ }
+
+ for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
+
+ phytype = mii_send(mk_mii_read(phyno, PHY_PHYIDR1));
+#ifdef ET_DEBUG
+ printf("PHY type 0x%x pass %d type\n", phytype, pass);
+#endif
+ if (phytype != 0xffff) {
+ phyaddr = phyno;
+ phytype <<= 16;
+ phytype |=
+ mii_send(mk_mii_read(phyno, PHY_PHYIDR2));
+
+ switch (phytype & 0xffffffff) {
+ case PHY_ID_KSZ8041NL:
+ strcpy(info->phy_name,
+ STR_ID_KSZ8041NL);
+ info->phyname_init = 1;
+ break;
+ default:
+ strcpy(info->phy_name, "unknown");
+ info->phyname_init = 1;
+ break;
+ }
+
+#ifdef ET_DEBUG
+ printf("PHY @ 0x%x pass %d type ", phyno, pass);
+ switch (phytype & 0xffffffff) {
+ case PHY_ID_KSZ8041NL:
+ printf(STR_ID_KSZ8041NL);
+ break;
+ default:
+ printf("0x%08x\n", phytype);
+ break;
+ }
+#endif
+ }
+ }
+ }
+ if (phyaddr < 0)
+ printf("No PHY device found.\n");
+
+ return phyaddr;
+}
+#endif /* CFG_DISCOVER_PHY */
+
+void mii_init(void) __attribute__ ((weak, alias("__mii_init")));
+
+void __mii_init(void)
+{
+ volatile fec_t *fecp;
+ struct fec_info_s *info;
+ struct eth_device *dev;
+ int miispd = 0, i = 0;
+ u16 autoneg = 0;
+
+ /* retrieve from register structure */
+ dev = eth_get_dev();
+ info = dev->priv;
+
+ fecp = (fec_t *) info->miibase;
+
+ /* We use strictly polling mode only */
+ fecp->eimr = 0;
+
+ /* Clear any pending interrupt */
+ fecp->eir = 0xffffffff;
+
+ /* Set MII speed */
+ miispd = (gd->bus_clk / 1000000) / 5;
+ fecp->mscr = miispd << 1;
+
+ info->phy_addr = mii_discover_phy(dev);
+
+#define AUTONEGLINK (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)
+ while (i < MCFFEC_TOUT_LOOP) {
+ autoneg = 0;
+ miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &autoneg);
+ i++;
+
+ if ((autoneg & AUTONEGLINK) == AUTONEGLINK)
+ break;
+
+ udelay(500);
+ }
+ if (i >= MCFFEC_TOUT_LOOP) {
+ printf("Auto Negotiation not complete\n");
+ }
+
+ /* adapt to the half/full speed settings */
+ info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16;
+ info->dup_spd |= miiphy_speed(dev->name, info->phy_addr);
+}
+
+/*****************************************************************************
+ * Read and write a MII PHY register, routines used by MII Utilities
+ *
+ * FIXME: These routines are expected to return 0 on success, but mii_send
+ * does _not_ return an error code. Maybe 0xFFFF means error, i.e.
+ * no PHY connected...
+ * For now always return 0.
+ * FIXME: These routines only work after calling eth_init() at least once!
+ * Otherwise they hang in mii_send() !!! Sorry!
+ *****************************************************************************/
+
+int mcffec_miiphy_read(char *devname, unsigned char addr, unsigned char reg,
+ unsigned short *value)
+{
+ short rdreg; /* register working value */
+
+#ifdef MII_DEBUG
+ printf("miiphy_read(0x%x) @ 0x%x = ", reg, addr);
+#endif
+ rdreg = mii_send(mk_mii_read(addr, reg));
+
+ *value = rdreg;
+
+#ifdef MII_DEBUG
+ printf("0x%04x\n", *value);
+#endif
+
+ return 0;
+}
+
+int mcffec_miiphy_write(char *devname, unsigned char addr, unsigned char reg,
+ unsigned short value)
+{
+ short rdreg; /* register working value */
+
+#ifdef MII_DEBUG
+ printf("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
+#endif
+
+ rdreg = mii_send(mk_mii_write(addr, reg, value));
+
+#ifdef MII_DEBUG
+ printf("0x%04x\n", value);
+#endif
+
+ return 0;
+}
+
+#endif /* CONFIG_CMD_NET, FEC_ENET & NET_MULTI */
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * 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
+ */
+
+OUTPUT_ARCH(m68k)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/mcf5445x/start.o (.text)
+ lib_m68k/traps.o (.text)
+ lib_m68k/interrupts.o (.text)
+ common/dlmalloc.o (.text)
+ lib_generic/zlib.o (.text)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/environment.o (.text)
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+
+ .reloc :
+ {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ _sbss = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * 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
+ */
+
+OUTPUT_ARCH(m68k)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/mcf5445x/start.o (.text)
+/* cpu/mcf5445x/cpu_init.o (.text)
+ cpu/mcf5445x/cpu.o (.text)
+ cpu/mcf5445x/dspi.o (.text)
+ cpu/mcf5445x/interrupt.o (.text)
+ cpu/mcf5445x/speed.o (.text)
+ lib_m68k/board.o (.text)
+ common/serial.o (.text)
+ common/console.o (.text)
+ lib_generic/display_options.o (.text)
+ board/freescale/m54455evb/m54455evb.o (.text)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/environment.o (.text)
+*/
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+
+ .reloc :
+ {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ _sbss = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
LIB = $(obj)lib$(BOARD).a
-COBJS = $(BOARD).o flash.o mii.o
+COBJS = $(BOARD).o mii.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
sinclude $(obj).depend
-#########################################################################
\ No newline at end of file
+#########################################################################
+++ /dev/null
-/*
- * (C) Copyright 2000-2003
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
- *
- * 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 <asm/immap.h>
-
-#ifndef CFG_FLASH_CFI
-typedef unsigned char FLASH_PORT_WIDTH;
-typedef volatile unsigned char FLASH_PORT_WIDTHV;
-
-#define FPW FLASH_PORT_WIDTH
-#define FPWV FLASH_PORT_WIDTHV
-
-#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
-#define CFG_FLASH_NONCFI_WIDTH FLASH_CFI_8BIT
-
-/* Intel-compatible flash commands */
-#define INTEL_PROGRAM 0x00100010
-#define INTEL_ERASE 0x00200020
-#define INTEL_WRSETUP 0x00400040
-#define INTEL_CLEAR 0x00500050
-#define INTEL_LOCKBIT 0x00600060
-#define INTEL_PROTECT 0x00010001
-#define INTEL_STATUS 0x00700070
-#define INTEL_READID 0x00900090
-#define INTEL_CFIQRY 0x00980098
-#define INTEL_SUSERASE 0x00B000B0
-#define INTEL_PROTPROG 0x00C000C0
-#define INTEL_CONFIRM 0x00D000D0
-#define INTEL_WRBLK 0x00e800e8
-#define INTEL_RESET 0x00FF00FF
-
-/* Intel-compatible flash status bits */
-#define INTEL_FINISHED 0x00800080
-#define INTEL_OK 0x00800080
-#define INTEL_ERASESUS 0x00600060
-#define INTEL_WSM_SUS (INTEL_FINISHED | INTEL_ERASESUS)
-
-/* 28F160C3B CFI Data offset - This could vary */
-#define INTEL_CFI_MFG 0x00 /* Manufacturer ID */
-#define INTEL_CFI_PART 0x01 /* Product ID */
-#define INTEL_CFI_LOCK 0x02 /* */
-#define INTEL_CFI_TWPRG 0x1F /* Typical Single Word Program Timeout 2^n us */
-#define INTEL_CFI_MBUFW 0x20 /* Typical Max Buffer Write Timeout 2^n us */
-#define INTEL_CFI_TERB 0x21 /* Typical Block Erase Timeout 2^n ms */
-#define INTEL_CFI_MWPRG 0x23 /* Maximum Word program timeout 2^n us */
-#define INTEL_CFI_MERB 0x25 /* Maximum Block Erase Timeout 2^n s */
-#define INTEL_CFI_SIZE 0x27 /* Device size 2^n bytes */
-#define INTEL_CFI_CAP 0x28
-#define INTEL_CFI_WRBUF 0x2A
-#define INTEL_CFI_BANK 0x2C /* Number of Bank */
-#define INTEL_CFI_BLK1A 0x2D /* Number of Blocks */
-#define INTEL_CFI_BLK1B 0x2E /* Number of Blocks */
-#define INTEL_CFI_SZ1A 0x2F /* Block Region Size */
-#define INTEL_CFI_SZ1B 0x30
-#define INTEL_CFI_BLK2A 0x31
-#define INTEL_CFI_BLK2B 0x32
-#define INTEL_CFI_SZ2A 0x33
-#define INTEL_CFI_SZ2B 0x34
-
-#define FLASH_CYCLE1 0x0555
-#define FLASH_CYCLE2 0x0aaa
-
-#define WR_BLOCK 0x20
-
-/* not in the flash.h yet */
-#define FLASH_28F64P30T 0x00B9 /* Intel 28F64P30T ( 64M) */
-#define FLASH_28F64P30B 0x00BA /* Intel 28F64P30B ( 64M) */
-#define FLASH_28F128P30T 0x00BB /* Intel 28F128P30T ( 128M = 8M x 16 ) */
-#define FLASH_28F128P30B 0x00BC /* Intel 28F128P30B ( 128M = 8M x 16 ) */
-#define FLASH_28F256P30T 0x00BD /* Intel 28F256P30T ( 256M = 16M x 16 ) */
-#define FLASH_28F256P30B 0x00BE /* Intel 28F256P30B ( 256M = 16M x 16 ) */
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
-#define STM_ID_M25P16 0x20152015
-#define FLASH_M25P16 0x0055
-#endif
-
-#define SYNC __asm__("nop")
-
-/*-----------------------------------------------------------------------
- * Functions
- */
-
-ulong flash_get_size(FPWV * addr, flash_info_t * info);
-int flash_get_offsets(ulong base, flash_info_t * info);
-int flash_cmd_rd(volatile u16 * addr, int index);
-int write_data(flash_info_t * info, ulong dest, FPW data);
-int write_data_block(flash_info_t * info, ulong src, ulong dest);
-int write_word_atm(flash_info_t * info, volatile u8 * dest, u16 data);
-void inline spin_wheel(void);
-void flash_sync_real_protect(flash_info_t * info);
-uchar intel_sector_protected(flash_info_t * info, ushort sector);
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
-int write_ser_data(flash_info_t * info, ulong dest, uchar * data, ulong cnt);
-int serial_flash_read_status(int chipsel);
-static int ser_flash_cs = 0;
-#endif
-
-flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
-
-ulong flash_init(void)
-{
- int i;
- ulong size = 0;
- ulong fbase = 0;
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- dspi_init();
-#endif
-
- for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
- memset(&flash_info[i], 0, sizeof(flash_info_t));
-
- switch (i) {
- case 0:
- fbase = (ulong) CFG_FLASH0_BASE;
- break;
- case 1:
- fbase = (ulong) CFG_FLASH1_BASE;
- break;
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- case 2:
- fbase = (ulong) CFG_FLASH2_BASE;
- break;
-#endif
- }
-
- flash_get_size((FPWV *) fbase, &flash_info[i]);
- flash_get_offsets((ulong) fbase, &flash_info[i]);
- fbase += flash_info[i].size;
- size += flash_info[i].size;
-
- /* get the h/w and s/w protection status in sync */
- flash_sync_real_protect(&flash_info[i]);
- }
-
- /* Protect monitor and environment sectors */
- flash_protect(FLAG_PROTECT_SET,
- CFG_MONITOR_BASE,
- CFG_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
-
- return size;
-}
-
-int flash_get_offsets(ulong base, flash_info_t * info)
-{
- int i, j, k;
- int sectors, bs, banks;
-
- if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_ATM) {
- int sect[] = CFG_ATMEL_SECT;
- int sectsz[] = CFG_ATMEL_SECTSZ;
-
- info->start[0] = base;
- for (k = 0, i = 0; i < CFG_ATMEL_REGION; i++) {
- for (j = 0; j < sect[i]; j++, k++) {
- info->start[k + 1] = info->start[k] + sectsz[i];
- info->protect[k] = 0;
- }
- }
- }
-
- if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
- volatile u16 *addr16 = (volatile u16 *)base;
-
- *addr16 = (FPW) INTEL_RESET; /* restore read mode */
- *addr16 = (FPW) INTEL_READID;
-
- banks = addr16[INTEL_CFI_BANK] & 0xff;
-
- sectors = 0;
- info->start[0] = base;
-
- for (k = 0, i = 0; i < banks; i++) {
- /* Geometry y1 = y1 + 1, y2 = y2 + 1, CFI spec.
- * To be exact, Z = [0x2f 0x30] (LE) * 256 bytes * [0x2D 0x2E] block count
- * Z = [0x33 0x34] (LE) * 256 bytes * [0x31 0x32] block count
- */
- bs = ((((addr16[INTEL_CFI_SZ1B + (i * 4)] & 0xff) << 8)
- | (addr16[INTEL_CFI_SZ1A + (i * 4)] & 0xff)) *
- 0x100);
- sectors =
- (addr16[INTEL_CFI_BLK1A + (i * 4)] & 0xff) + 1;
-
- for (j = 0; j < sectors; j++, k++) {
- info->start[k + 1] = info->start[k] + bs;
- }
- }
-
- *addr16 = (FPW) INTEL_RESET; /* restore read mode */
- }
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM) {
- info->start[0] = CFG_FLASH2_BASE;
- for (k = 0, i = 0; i < CFG_STM_SECT; i++, k++) {
- info->start[k + 1] = info->start[k] + CFG_STM_SECTSZ;
- info->protect[k] = 0;
- }
- }
-#endif
-
- return ERR_OK;
-}
-
-void flash_print_info(flash_info_t * info)
-{
- int i;
-
- switch (info->flash_id & FLASH_VENDMASK) {
- case FLASH_MAN_INTEL:
- printf("INTEL ");
- break;
- case FLASH_MAN_ATM:
- printf("ATMEL ");
- break;
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- case FLASH_MAN_STM:
- printf("ST ");
- break;
-#endif
- default:
- printf("Unknown Vendor ");
- break;
- }
-
- switch (info->flash_id & FLASH_TYPEMASK) {
- case FLASH_AT040:
- printf("AT49BV040A\n");
- break;
- case FLASH_28F128J3A:
- printf("28F128J3A\n");
- break;
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- case FLASH_M25P16:
- printf("M25P16\n");
- break;
-#endif
- default:
- printf("Unknown Chip Type\n");
- return;
- }
-
- if (info->size > 0x100000) {
- int remainder;
-
- printf(" Size: %ld", info->size >> 20);
-
- remainder = (info->size % 0x100000);
- if (remainder) {
- remainder >>= 10;
- remainder = (int)((float)
- (((float)remainder / (float)1024) *
- 10000));
- printf(".%d ", remainder);
- }
-
- printf("MB in %d Sectors\n", info->sector_count);
- } else
- printf(" Size: %ld KB in %d Sectors\n",
- info->size >> 10, info->sector_count);
-
- printf(" Sector Start Addresses:");
- for (i = 0; i < info->sector_count; ++i) {
- if ((i % 5) == 0)
- printf("\n ");
- printf(" %08lX%s",
- info->start[i], info->protect[i] ? " (RO)" : " ");
- }
- printf("\n");
-}
-
-/*
- * The following code cannot be run from FLASH!
- */
-ulong flash_get_size(FPWV * addr, flash_info_t * info)
-{
- volatile u16 *addr16 = (volatile u16 *)addr;
- int intel = 0, banks = 0;
- u16 value;
- int i;
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- if ((ulong) addr == CFG_FLASH2_BASE) {
- int manufactId = 0;
- int deviceId = 0;
-
- ser_flash_cs = 1;
-
- dspi_tx(ser_flash_cs, 0x80, SER_RDID);
- dspi_tx(ser_flash_cs, 0x80, 0);
- dspi_tx(ser_flash_cs, 0x80, 0);
- dspi_tx(ser_flash_cs, 0x80, 0);
-
- dspi_rx();
- manufactId = dspi_rx();
- deviceId = dspi_rx() << 8;
- deviceId |= dspi_rx();
-
- dspi_tx(ser_flash_cs, 0x00, 0);
- dspi_rx();
-
- switch (manufactId) {
- case (u8) STM_MANUFACT:
- info->flash_id = FLASH_MAN_STM;
- break;
- }
-
- switch (deviceId) {
- case (u16) STM_ID_M25P16:
- info->flash_id += FLASH_M25P16;
- break;
- }
-
- info->sector_count = CFG_STM_SECT;
- info->size = CFG_STM_SECT * CFG_STM_SECTSZ;
-
- return (info->size);
- }
-#endif
-
- addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
- addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
- addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
-
- switch (addr[0] & 0xff) {
- case (u8) ATM_MANUFACT:
- info->flash_id = FLASH_MAN_ATM;
- value = addr[1];
- break;
- case (u8) INTEL_MANUFACT:
- /* Terminate Atmel ID read */
- addr[0] = (FPWV) 0x00F000F0;
- /* Write auto select command: read Manufacturer ID */
- /* Write auto select command sequence and test FLASH answer */
- *addr16 = (FPW) INTEL_RESET; /* restore read mode */
- *addr16 = (FPW) INTEL_READID;
-
- info->flash_id = FLASH_MAN_INTEL;
- value = (addr16[INTEL_CFI_MFG] << 8);
- value |= addr16[INTEL_CFI_PART] & 0xff;
- intel = 1;
- break;
- default:
- printf("Unknown Flash\n");
- info->flash_id = FLASH_UNKNOWN;
- info->sector_count = 0;
- info->size = 0;
-
- *addr = (FPW) 0x00F000F0;
- *addr = (FPW) INTEL_RESET; /* restore read mode */
- return (0); /* no or unknown flash */
- }
-
- switch (value) {
- case (u8) ATM_ID_LV040:
- info->flash_id += FLASH_AT040;
- break;
- case (u16) INTEL_ID_28F128J3:
- info->flash_id += FLASH_28F128J3A;
- break;
- case (u16) INTEL_ID_28F64P30T:
- info->flash_id += FLASH_28F64P30T;
- break;
- case (u16) INTEL_ID_28F64P30B:
- info->flash_id += FLASH_28F64P30B;
- break;
- case (u16) INTEL_ID_28F128P30T:
- info->flash_id += FLASH_28F128P30T;
- break;
- case (u16) INTEL_ID_28F128P30B:
- info->flash_id += FLASH_28F128P30B;
- break;
- case (u16) INTEL_ID_28F256P30T:
- info->flash_id += FLASH_28F256P30T;
- break;
- case (u16) INTEL_ID_28F256P30B:
- info->flash_id += FLASH_28F256P30B;
- break;
- default:
- info->flash_id = FLASH_UNKNOWN;
- break;
- }
-
- if (intel) {
- /* Intel spec. under CFI section */
- u32 sz;
- int sectors, bs;
-
- banks = addr16[INTEL_CFI_BANK] & 0xff;
-
- sectors = sz = 0;
- for (i = 0; i < banks; i++) {
- /* Geometry y1 = y1 + 1, y2 = y2 + 1, CFI spec.
- * To be exact, Z = [0x2f 0x30] (LE) * 256 bytes * [0x2D 0x2E] block count
- * Z = [0x33 0x34] (LE) * 256 bytes * [0x31 0x32] block count
- */
- bs = ((((addr16[INTEL_CFI_SZ1B + (i * 4)] & 0xff) << 8)
- | (addr16[INTEL_CFI_SZ1A + (i * 4)] & 0xff)) *
- 0x100);
- sectors +=
- (addr16[INTEL_CFI_BLK1A + (i * 4)] & 0xff) + 1;
- sz += (bs * sectors);
- }
-
- info->sector_count = sectors;
- info->size = sz;
- *addr = (FPW) INTEL_RESET; /* restore read mode */
- } else {
- int sect[] = CFG_ATMEL_SECT;
- int sectsz[] = CFG_ATMEL_SECTSZ;
-
- info->sector_count = 0;
- info->size = 0;
- for (i = 0; i < CFG_ATMEL_REGION; i++) {
- info->sector_count += sect[i];
- info->size += sect[i] * sectsz[i];
- }
-
- /* reset ID mode */
- addr[0] = (FPWV) 0x00F000F0;
- }
-
- if (info->sector_count > CFG_MAX_FLASH_SECT) {
- printf("** ERROR: sector count %d > max (%d) **\n",
- info->sector_count, CFG_MAX_FLASH_SECT);
- info->sector_count = CFG_MAX_FLASH_SECT;
- }
-
- return (info->size);
-}
-
-int flash_cmd_rd(volatile u16 * addr, int index)
-{
- return (int)addr[index];
-}
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
-int serial_flash_read_status(int chipsel)
-{
- u16 status;
-
- dspi_tx(chipsel, 0x80, SER_RDSR);
- dspi_rx();
-
- dspi_tx(chipsel, 0x00, 0);
- status = dspi_rx();
-
- return status;
-}
-#endif
-
-/*
- * This function gets the u-boot flash sector protection status
- * (flash_info_t.protect[]) in sync with the sector protection
- * status stored in hardware.
- */
-void flash_sync_real_protect(flash_info_t * info)
-{
- int i;
-
- switch (info->flash_id & FLASH_TYPEMASK) {
- case FLASH_28F160C3B:
- case FLASH_28F160C3T:
- case FLASH_28F320C3B:
- case FLASH_28F320C3T:
- case FLASH_28F640C3B:
- case FLASH_28F640C3T:
- for (i = 0; i < info->sector_count; ++i) {
- info->protect[i] = intel_sector_protected(info, i);
- }
- break;
- default:
- /* no h/w protect support */
- break;
- }
-}
-
-/*
- * checks if "sector" in bank "info" is protected. Should work on intel
- * strata flash chips 28FxxxJ3x in 8-bit mode.
- * Returns 1 if sector is protected (or timed-out while trying to read
- * protection status), 0 if it is not.
- */
-uchar intel_sector_protected(flash_info_t * info, ushort sector)
-{
- FPWV *addr;
- FPWV *lock_conf_addr;
- ulong start;
- unsigned char ret;
-
- /*
- * first, wait for the WSM to be finished. The rationale for
- * waiting for the WSM to become idle for at most
- * CFG_FLASH_ERASE_TOUT is as follows. The WSM can be busy
- * because of: (1) erase, (2) program or (3) lock bit
- * configuration. So we just wait for the longest timeout of
- * the (1)-(3), i.e. the erase timeout.
- */
-
- /* wait at least 35ns (W12) before issuing Read Status Register */
- /*udelay(1); */
- addr = (FPWV *) info->start[sector];
- *addr = (FPW) INTEL_STATUS;
-
- start = get_timer(0);
- while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) {
- if (get_timer(start) > CFG_FLASH_UNLOCK_TOUT) {
- *addr = (FPW) INTEL_RESET; /* restore read mode */
- printf("WSM busy too long, can't get prot status\n");
- return 1;
- }
- }
-
- /* issue the Read Identifier Codes command */
- *addr = (FPW) INTEL_READID;
-
- /* Intel example code uses offset of 4 for 8-bit flash */
- lock_conf_addr = (FPWV *) info->start[sector];
- ret = (lock_conf_addr[INTEL_CFI_LOCK] & (FPW) INTEL_PROTECT) ? 1 : 0;
-
- /* put flash back in read mode */
- *addr = (FPW) INTEL_RESET;
-
- return ret;
-}
-
-int flash_erase(flash_info_t * info, int s_first, int s_last)
-{
- int flag, prot, sect;
- ulong type, start, last;
- int rcode = 0, flashtype = 0;
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- int count;
- u16 status;
-#endif
- if ((s_first < 0) || (s_first > s_last)) {
- if (info->flash_id == FLASH_UNKNOWN)
- printf("- missing\n");
- else
- printf("- no sectors to erase\n");
- return 1;
- }
-
- type = (info->flash_id & FLASH_VENDMASK);
-
- switch (type) {
- case FLASH_MAN_ATM:
- flashtype = 1;
- break;
- case FLASH_MAN_INTEL:
- flashtype = 2;
- break;
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- case FLASH_MAN_STM:
- flashtype = 3;
- break;
-#endif
- default:
- type = (info->flash_id & FLASH_VENDMASK);
- printf("Can't erase unknown flash type %08lx - aborted\n",
- info->flash_id);
- return 1;
- }
-
- prot = 0;
- for (sect = s_first; sect <= s_last; ++sect) {
- if (info->protect[sect]) {
- prot++;
- }
- }
-
- if (prot)
- printf("- Warning: %d protected sectors will not be erased!\n",
- prot);
- else
- printf("\n");
-
- start = get_timer(0);
- last = start;
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- /* Perform bulk erase */
- if (flashtype == 3) {
- if ((s_last - s_first) == (CFG_STM_SECT - 1)) {
- if (prot == 0) {
- dspi_tx(ser_flash_cs, 0x00, SER_WREN);
- dspi_rx();
-
- status = serial_flash_read_status(ser_flash_cs);
- if (((status & 0x9C) != 0)
- && ((status & 0x02) != 0x02)) {
- printf("Can't erase flash\n");
- return 1;
- }
-
- dspi_tx(ser_flash_cs, 0x00, SER_BULK_ERASE);
- dspi_rx();
-
- count = 0;
- start = get_timer(0);
- do {
- status =
- serial_flash_read_status
- (ser_flash_cs);
-
- if (count++ > 0x10000) {
- spin_wheel();
- count = 0;
- }
-
- if (get_timer(start) >
- CFG_FLASH_ERASE_TOUT) {
- printf("Timeout\n");
- return 1;
- }
- } while (status & 0x01);
-
- printf("\b. done\n");
- return 0;
- } else if (prot == CFG_STM_SECT) {
- return 1;
- }
- }
- }
-#endif
- /* Start erase on unprotected sectors */
- for (sect = s_first; sect <= s_last; sect++) {
- if (info->protect[sect] == 0) { /* not protected */
-
- FPWV *addr = (FPWV *) (info->start[sect]);
- int min = 0;
-
- printf(".");
-
- /* arm simple, non interrupt dependent timer */
- start = get_timer(0);
-
- switch (flashtype) {
- case 1:
- {
- FPWV *base; /* first address in bank */
- FPWV *atmeladdr;
-
- flag = disable_interrupts();
-
- atmeladdr = (FPWV *) addr; /* concatenate to 8 bit */
- base = (FPWV *) (CFG_ATMEL_BASE); /* First sector */
-
- base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
- base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
- base[FLASH_CYCLE1] = (u8) 0x00800080; /* erase mode */
- base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
- base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
- *atmeladdr = (u8) 0x00300030; /* erase sector */
-
- if (flag)
- enable_interrupts();
-
- while ((*atmeladdr & (u8) 0x00800080) !=
- (u8) 0x00800080) {
- if (get_timer(start) >
- CFG_FLASH_ERASE_TOUT) {
- printf("Timeout\n");
- *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
-
- rcode = 1;
- break;
- }
- }
-
- *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
- break;
- }
-
- case 2:
- {
- *addr = (FPW) INTEL_READID;
- min = addr[INTEL_CFI_TERB] & 0xff;
- min = 1 << min; /* ms */
- min = (min / info->sector_count) * 1000;
-
- /* start erase block */
- *addr = (FPW) INTEL_CLEAR; /* clear status register */
- *addr = (FPW) INTEL_ERASE; /* erase setup */
- *addr = (FPW) INTEL_CONFIRM; /* erase confirm */
-
- while ((*addr & (FPW) INTEL_FINISHED) !=
- (FPW) INTEL_FINISHED) {
-
- if (get_timer(start) >
- CFG_FLASH_ERASE_TOUT) {
- printf("Timeout\n");
- *addr = (FPW) INTEL_SUSERASE; /* suspend erase */
- *addr = (FPW) INTEL_RESET; /* reset to read mode */
-
- rcode = 1;
- break;
- }
- }
-
- *addr = (FPW) INTEL_RESET; /* resest to read mode */
- break;
- }
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- case 3:
- {
- u8 sec = ((ulong) addr >> 16) & 0xFF;
-
- dspi_tx(ser_flash_cs, 0x00, SER_WREN);
- dspi_rx();
- status =
- serial_flash_read_status
- (ser_flash_cs);
- if (((status & 0x9C) != 0)
- && ((status & 0x02) != 0x02)) {
- printf("Error Programming\n");
- return 1;
- }
-
- dspi_tx(ser_flash_cs, 0x80,
- SER_SECT_ERASE);
- dspi_tx(ser_flash_cs, 0x80, sec);
- dspi_tx(ser_flash_cs, 0x80, 0);
- dspi_tx(ser_flash_cs, 0x00, 0);
-
- dspi_rx();
- dspi_rx();
- dspi_rx();
- dspi_rx();
-
- do {
- status =
- serial_flash_read_status
- (ser_flash_cs);
-
- if (get_timer(start) >
- CFG_FLASH_ERASE_TOUT) {
- printf("Timeout\n");
- return 1;
- }
- } while (status & 0x01);
-
- break;
- }
-#endif
- } /* switch (flashtype) */
- }
- }
- printf(" done\n");
-
- return rcode;
-}
-
-int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
-{
- int count;
-
- if (info->flash_id == FLASH_UNKNOWN)
- return 4;
-
- switch (info->flash_id & FLASH_VENDMASK) {
- case FLASH_MAN_ATM:
- {
- u16 data = 0;
- int bytes; /* number of bytes to program in current word */
- int left; /* number of bytes left to program */
- int i, res;
-
- for (left = cnt, res = 0;
- left > 0 && res == 0;
- addr += sizeof(data), left -=
- sizeof(data) - bytes) {
-
- bytes = addr & (sizeof(data) - 1);
- addr &= ~(sizeof(data) - 1);
-
- /* combine source and destination data so can program
- * an entire word of 16 or 32 bits
- */
- for (i = 0; i < sizeof(data); i++) {
- data <<= 8;
- if (i < bytes || i - bytes >= left)
- data += *((uchar *) addr + i);
- else
- data += *src++;
- }
-
- data = (data >> 8) | (data << 8);
- res = write_word_atm(info, (FPWV *) addr, data);
- }
- return res;
- } /* case FLASH_MAN_ATM */
-
- case FLASH_MAN_INTEL:
- {
- ulong cp, wp;
- u16 data;
- int i, l, rc, port_width;
-
- /* get lower word aligned address */
- wp = addr;
- port_width = sizeof(FPW);
-
- /*
- * handle unaligned start bytes
- */
- if ((l = addr - wp) != 0) {
- data = 0;
- for (i = 0, cp = wp; i < l; ++i, ++cp) {
- data = (data << 8) | (*(uchar *) cp);
- }
-
- for (; i < port_width && cnt > 0; ++i) {
- data = (data << 8) | *src++;
- --cnt;
- ++cp;
- }
-
- for (; cnt == 0 && i < port_width; ++i, ++cp)
- data = (data << 8) | (*(uchar *) cp);
-
- if ((rc = write_data(info, wp, data)) != 0)
- return (rc);
-
- wp += port_width;
- }
-
- if (cnt > WR_BLOCK) {
- /*
- * handle word aligned part
- */
- count = 0;
- while (cnt >= WR_BLOCK) {
-
- if ((rc =
- write_data_block(info,
- (ulong) src,
- wp)) != 0)
- return (rc);
-
- wp += WR_BLOCK;
- src += WR_BLOCK;
- cnt -= WR_BLOCK;
-
- if (count++ > 0x800) {
- spin_wheel();
- count = 0;
- }
- }
- }
-
- /* handle word aligned part */
- if (cnt < WR_BLOCK) {
- /*
- * handle word aligned part
- */
- count = 0;
- while (cnt >= port_width) {
- data = 0;
- for (i = 0; i < port_width; ++i)
- data = (data << 8) | *src++;
-
- if ((rc =
- write_data(info,
- (ulong) ((FPWV *) wp),
- (FPW) (data))) != 0)
- return (rc);
-
- wp += port_width;
- cnt -= port_width;
- if (count++ > 0x800) {
- spin_wheel();
- count = 0;
- }
- }
- }
-
- if (cnt == 0)
- return ERR_OK;
-
- /*
- * handle unaligned tail bytes
- */
- data = 0;
- for (i = 0, cp = wp; i < port_width && cnt > 0;
- ++i, ++cp) {
- data = (data << 8) | (*src++);
- --cnt;
- }
- for (; i < port_width; ++i, ++cp) {
- data = (data << 8) | (*(uchar *) cp);
- }
-
- return write_data(info, (ulong) ((FPWV *) wp),
- (FPW) data);
-
- } /* case FLASH_MAN_INTEL */
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
- case FLASH_MAN_STM:
- {
- ulong wp;
- u8 *data = (u8 *) src;
- int left; /* number of bytes left to program */
-
- wp = addr;
-
- /* page align, each page is 256 bytes */
- if ((wp % 0x100) != 0) {
- left = (0x100 - (wp & 0xFF));
- write_ser_data(info, wp, data, left);
- cnt -= left;
- wp += left;
- data += left;
- }
-
- /* page program - 256 bytes at a time */
- if (cnt > 255) {
- count = 0;
- while (cnt >= 0x100) {
- write_ser_data(info, wp, data, 0x100);
- cnt -= 0x100;
- wp += 0x100;
- data += 0x100;
-
- if (count++ > 0x400) {
- spin_wheel();
- count = 0;
- }
- }
- }
-
- /* remainint bytes */
- if (cnt && (cnt < 256)) {
- write_ser_data(info, wp, data, cnt);
- wp += cnt;
- data += cnt;
- cnt -= cnt;
- }
-
- printf("\b.");
- }
-#endif
- } /* switch */
-
- return ERR_OK;
-}
-
-/*-----------------------------------------------------------------------
- * Write a word or halfword to Flash, returns:
- * 0 - OK
- * 1 - write timeout
- * 2 - Flash not erased
- */
-int write_data_block(flash_info_t * info, ulong src, ulong dest)
-{
- FPWV *srcaddr = (FPWV *) src;
- FPWV *dstaddr = (FPWV *) dest;
- ulong start;
- int flag, i;
-
- /* Check if Flash is (sufficiently) erased */
- for (i = 0; i < WR_BLOCK; i++)
- if ((*dstaddr++ & 0xff) != 0xff) {
- printf("not erased at %08lx (%lx)\n",
- (ulong) dstaddr, *dstaddr);
- return (2);
- }
-
- dstaddr = (FPWV *) dest;
-
- /* Disable interrupts which might cause a timeout here */
- flag = disable_interrupts();
-
- *dstaddr = (FPW) INTEL_WRBLK; /* write block setup */
-
- if (flag)
- enable_interrupts();
-
- /* arm simple, non interrupt dependent timer */
- start = get_timer(0);
-
- /* wait while polling the status register */
- while ((*dstaddr & (FPW) INTEL_FINISHED) != (FPW) INTEL_OK) {
- if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
- *dstaddr = (FPW) INTEL_RESET; /* restore read mode */
- return (1);
- }
- }
-
- *dstaddr = (FPW) WR_BLOCK - 1; /* write 32 to buffer */
- for (i = 0; i < WR_BLOCK; i++)
- *dstaddr++ = *srcaddr++;
-
- dstaddr -= 1;
- *dstaddr = (FPW) INTEL_CONFIRM; /* write 32 to buffer */
-
- /* arm simple, non interrupt dependent timer */
- start = get_timer(0);
-
- /* wait while polling the status register */
- while ((*dstaddr & (FPW) INTEL_FINISHED) != (FPW) INTEL_OK) {
- if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
- *dstaddr = (FPW) INTEL_RESET; /* restore read mode */
- return (1);
- }
- }
-
- *dstaddr = (FPW) INTEL_RESET; /* restore read mode */
-
- return (0);
-}
-
-/*-----------------------------------------------------------------------
- * Write a word or halfword to Flash, returns:
- * 0 - OK
- * 1 - write timeout
- * 2 - Flash not erased
- */
-int write_data(flash_info_t * info, ulong dest, FPW data)
-{
- FPWV *addr = (FPWV *) dest;
- ulong start;
- int flag;
-
- /* Check if Flash is (sufficiently) erased */
- if ((*addr & data) != data) {
- printf("not erased at %08lx (%lx)\n", (ulong) addr,
- (ulong) * addr);
- return (2);
- }
-
- /* Disable interrupts which might cause a timeout here */
- flag = (int)disable_interrupts();
-
- *addr = (FPW) INTEL_CLEAR;
- *addr = (FPW) INTEL_RESET;
-
- *addr = (FPW) INTEL_WRSETUP; /* write setup */
- *addr = data;
-
- if (flag)
- enable_interrupts();
-
- /* arm simple, non interrupt dependent timer */
- start = get_timer(0);
-
- /* wait while polling the status register */
- while ((*addr & (FPW) INTEL_OK) != (FPW) INTEL_OK) {
- if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
- *addr = (FPW) INTEL_SUSERASE; /* suspend mode */
- *addr = (FPW) INTEL_CLEAR; /* clear status */
- *addr = (FPW) INTEL_RESET; /* reset */
- return (1);
- }
- }
-
- *addr = (FPW) INTEL_CLEAR; /* clear status */
- *addr = (FPW) INTEL_RESET; /* restore read mode */
-
- return (0);
-}
-
-#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
-int write_ser_data(flash_info_t * info, ulong dest, uchar * data, ulong cnt)
-{
- ulong start;
- int status, i;
- u8 flashdata;
-
- /* Check if Flash is (sufficiently) erased */
- dspi_tx(ser_flash_cs, 0x80, SER_READ);
- dspi_tx(ser_flash_cs, 0x80, (dest >> 16) & 0xFF);
- dspi_tx(ser_flash_cs, 0x80, (dest >> 8) & 0xFF);
- dspi_tx(ser_flash_cs, 0x80, dest & 0xFF);
- dspi_rx();
- dspi_rx();
- dspi_rx();
- dspi_rx();
- dspi_tx(ser_flash_cs, 0x80, 0);
- flashdata = dspi_rx();
- dspi_tx(ser_flash_cs, 0x00, 0);
- dspi_rx();
-
- if ((flashdata & *data) != *data) {
- printf("not erased at %08lx (%lx)\n", (ulong) dest,
- (ulong) flashdata);
- return (2);
- }
-
- dspi_tx(ser_flash_cs, 0x00, SER_WREN);
- dspi_rx();
-
- status = serial_flash_read_status(ser_flash_cs);
- if (((status & 0x9C) != 0) && ((status & 0x02) != 0x02)) {
- printf("Error Programming\n");
- return 1;
- }
-
- start = get_timer(0);
-
- dspi_tx(ser_flash_cs, 0x80, SER_PAGE_PROG);
- dspi_tx(ser_flash_cs, 0x80, ((dest & 0xFF0000) >> 16));
- dspi_tx(ser_flash_cs, 0x80, ((dest & 0xFF00) >> 8));
- dspi_tx(ser_flash_cs, 0x80, (dest & 0xFF));
- dspi_rx();
- dspi_rx();
- dspi_rx();
- dspi_rx();
-
- for (i = 0; i < (cnt - 1); i++) {
- dspi_tx(ser_flash_cs, 0x80, *data);
- dspi_rx();
- data++;
- }
-
- dspi_tx(ser_flash_cs, 0x00, *data);
- dspi_rx();
-
- do {
- status = serial_flash_read_status(ser_flash_cs);
-
- if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
- printf("Timeout\n");
- return 1;
- }
- } while (status & 0x01);
-
- return (0);
-}
-#endif
-
-/*-----------------------------------------------------------------------
- * Write a word to Flash for ATMEL FLASH
- * A word is 16 bits, whichever the bus width of the flash bank
- * (not an individual chip) is.
- *
- * returns:
- * 0 - OK
- * 1 - write timeout
- * 2 - Flash not erased
- */
-int write_word_atm(flash_info_t * info, volatile u8 * dest, u16 data)
-{
- ulong start;
- int flag, i;
- int res = 0; /* result, assume success */
- FPWV *base; /* first address in flash bank */
-
- /* Check if Flash is (sufficiently) erased */
- if ((*((volatile u16 *)dest) & data) != data) {
- return (2);
- }
-
- base = (FPWV *) (CFG_ATMEL_BASE);
-
- for (i = 0; i < sizeof(u16); i++) {
- /* Disable interrupts which might cause a timeout here */
- flag = disable_interrupts();
-
- base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
- base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
- base[FLASH_CYCLE1] = (u8) 0x00A000A0; /* selects program mode */
-
- *dest = data; /* start programming the data */
-
- /* re-enable interrupts if necessary */
- if (flag)
- enable_interrupts();
-
- start = get_timer(0);
-
- /* data polling for D7 */
- while (res == 0
- && (*dest & (u8) 0x00800080) !=
- (data & (u8) 0x00800080)) {
- if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
- *dest = (u8) 0x00F000F0; /* reset bank */
- res = 1;
- }
- }
-
- *dest++ = (u8) 0x00F000F0; /* reset bank */
- data >>= 8;
- }
-
- return (res);
-}
-
-void inline spin_wheel(void)
-{
- static int p = 0;
- static char w[] = "\\/-";
-
- printf("\010%c", w[p]);
- (++p == 3) ? (p = 0) : 0;
-}
-
-#ifdef CFG_FLASH_PROTECTION
-/*-----------------------------------------------------------------------
- */
-int flash_real_protect(flash_info_t * info, long sector, int prot)
-{
- int rcode = 0; /* assume success */
- FPWV *addr; /* address of sector */
- FPW value;
-
- addr = (FPWV *) (info->start[sector]);
-
- switch (info->flash_id & FLASH_TYPEMASK) {
- case FLASH_28F160C3B:
- case FLASH_28F160C3T:
- case FLASH_28F320C3B:
- case FLASH_28F320C3T:
- case FLASH_28F640C3B:
- case FLASH_28F640C3T:
- *addr = (FPW) INTEL_RESET; /* make sure in read mode */
- *addr = (FPW) INTEL_LOCKBIT; /* lock command setup */
-
- if (prot)
- *addr = (FPW) INTEL_PROTECT; /* lock sector */
- else
- *addr = (FPW) INTEL_CONFIRM; /* unlock sector */
-
- /* now see if it really is locked/unlocked as requested */
- *addr = (FPW) INTEL_READID;
-
- /* read sector protection at sector address, (A7 .. A0) = 0x02.
- * D0 = 1 for each device if protected.
- * If at least one device is protected the sector is marked
- * protected, but return failure. Mixed protected and
- * unprotected devices within a sector should never happen.
- */
- value = addr[2] & (FPW) INTEL_PROTECT;
- if (value == 0)
- info->protect[sector] = 0;
- else if (value == (FPW) INTEL_PROTECT)
- info->protect[sector] = 1;
- else {
- /* error, mixed protected and unprotected */
- rcode = 1;
- info->protect[sector] = 1;
- }
- if (info->protect[sector] != prot)
- rcode = 1; /* failed to protect/unprotect as requested */
-
- /* reload all protection bits from hardware for now */
- flash_sync_real_protect(info);
- break;
-
- default:
- /* no hardware protect that we support */
- info->protect[sector] = prot;
- break;
- }
-
- return rcode;
-}
-#endif
-#endif
phys_size_t initdram(int board_type)
{
+ u32 dramsize;
+#ifdef CONFIG_CF_SBF
+ /*
+ * Serial Boot: The dram is already initialized in start.S
+ * only require to return DRAM size
+ */
+ dramsize = CFG_SDRAM_SIZE * 0x100000 >> 1;
+#else
volatile sdramc_t *sdram = (volatile sdramc_t *)(MMAP_SDRAM);
volatile gpio_t *gpio = (volatile gpio_t *)(MMAP_GPIO);
- u32 dramsize, i;
+ u32 i;
dramsize = CFG_SDRAM_SIZE * 0x100000 >> 1;
}
i--;
- gpio->mscr_sdram = 0xAA;
+ gpio->mscr_sdram = CFG_SDRAM_DRV_STRENGTH;
sdram->sdcs0 = (CFG_SDRAM_BASE | i);
sdram->sdcs1 = (CFG_SDRAM_BASE1 | i);
sdram->sdcr = (CFG_SDRAM_CTRL & ~0x80000000) | 0x10000c00;
udelay(100);
-
+#endif
return (dramsize << 1);
};
pci_mcf5445x_init(&hose);
}
#endif /* CONFIG_PCI */
+
+#if defined(CFG_FLASH_CFI)
+#include <flash.h>
+ulong board_flash_get_legacy (ulong base, int banknum, flash_info_t * info)
+{
+ int sect[] = CFG_ATMEL_SECT;
+ int sectsz[] = CFG_ATMEL_SECTSZ;
+ int i, j, k;
+
+ if (base != CFG_ATMEL_BASE)
+ return 0;
+
+ info->flash_id = 0x01000000;
+ info->portwidth = 1;
+ info->chipwidth = 1;
+ info->buffer_size = 32;
+ info->erase_blk_tout = 16384;
+ info->write_tout = 2;
+ info->buffer_write_tout = 5;
+ info->vendor = 2; /* CFI_CMDSET_AMD_STANDARD */
+ info->cmd_reset = 0x00F0;
+ info->interface = FLASH_CFI_X8;
+ info->legacy_unlock = 0;
+ info->manufacturer_id = (u16) ATM_MANUFACT;
+ info->device_id = ATM_ID_LV040;
+ info->device_id2 = 0;
+
+ info->ext_addr = 0;
+ info->cfi_version = 0x3133;
+ info->cfi_offset = 0x0055;
+ info->addr_unlock1 = 0x00000555;
+ info->addr_unlock2 = 0x000002AA;
+ info->name = "CFI conformant";
+
+
+ info->size = 0;
+ info->sector_count = CFG_ATMEL_TOTALSECT;
+ info->start[0] = base;
+ for (k = 0, i = 0; i < CFG_ATMEL_REGION; i++) {
+ info->size += sect[i] * sectsz[i];
+
+ for (j = 0; j < sect[i]; j++, k++) {
+ info->start[k + 1] = info->start[k] + sectsz[i];
+ info->protect[k] = 0;
+ }
+ }
+
+ return 1;
+}
+#endif /* CFG_FLASH_CFI */
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * 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
+ */
+
+OUTPUT_ARCH(m68k)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/mcf5445x/start.o (.text)
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+
+ .reloc :
+ {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ _sbss = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
DECLARE_GLOBAL_DATA_PTR;
-extern void flush_data_cache (void);
-extern void invalidate_l1_instruction_cache (void);
extern void tsi108_init_f (void);
int display_mem_map (void);
+ifndef NAND_SPL
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+endif
+
+ifndef TEXT_BASE
TEXT_BASE = 0xFE000000
+endif
#include <pci.h>
#include <mpc83xx.h>
#include <vsc7385.h>
+#include <ns16550.h>
+#include <nand.h>
DECLARE_GLOBAL_DATA_PTR;
return 0;
}
+#ifndef CONFIG_NAND_SPL
static struct pci_region pci_regions[] = {
{
bus_start: CFG_PCI1_MEM_BASE,
#endif
}
#endif
+#else /* CONFIG_NAND_SPL */
+void board_init_f(ulong bootflag)
+{
+ board_early_init_f();
+ NS16550_init((NS16550_t)(CFG_IMMR + 0x4500),
+ CFG_NS16550_CLK / 16 / CONFIG_BAUDRATE);
+ puts("NAND boot... ");
+ init_timebase();
+ initdram(0);
+ relocate_code(CFG_NAND_U_BOOT_RELOC + 0x10000, (gd_t *)gd,
+ CFG_NAND_U_BOOT_RELOC);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+ nand_boot();
+}
+
+void putc(char c)
+{
+ if (gd->flags & GD_FLG_SILENT)
+ return;
+
+ if (c == '\n')
+ NS16550_putc((NS16550_t)(CFG_IMMR + 0x4500), '\r');
+
+ NS16550_putc((NS16550_t)(CFG_IMMR + 0x4500), c);
+}
+#endif
*/
static long fixed_sdram(void)
{
- volatile immap_t *im = (volatile immap_t *)CFG_IMMR;
u32 msize = CFG_DDR_SIZE * 1024 * 1024;
+
+#ifndef CFG_RAMBOOT
+ volatile immap_t *im = (volatile immap_t *)CFG_IMMR;
u32 msize_log2 = __ilog2(msize);
im->sysconf.ddrlaw[0].bar = CFG_DDR_SDRAM_BASE >> 12;
/* enable DDR controller */
im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN;
+#endif
return msize;
}
OUTPUT_ARCH(powerpc)
/* Do we need any of these for elf?
__DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
SECTIONS
{
/* Read-only sections, merged into text segment: */
*(.text)
*(.fixup)
*(.got1)
- }
+ } :text
_etext = .;
PROVIDE (etext = .);
.rodata :
*(.rodata1)
*(.rodata.str1.4)
*(.eh_frame)
- }
+ } :text
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
.bootpg ADDR(.text) + 0x7f000 :
{
cpu/mpc85xx/start.o (.bootpg)
- } = 0xffff
+ } :text = 0xffff
.resetvec ADDR(.text) + 0x7fffc :
{
*(.resetvec)
- } = 0xffff
+ } :text = 0xffff
. = ADDR(.text) + 0x80000;
*(.dynbss)
*(.bss)
*(COMMON)
- }
+ } :bss
. = ALIGN(4);
_end = . ;
OUTPUT_ARCH(powerpc)
/* Do we need any of these for elf?
__DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
SECTIONS
{
/* Read-only sections, merged into text segment: */
*(.text)
*(.fixup)
*(.got1)
- }
+ } :text
_etext = .;
PROVIDE (etext = .);
.rodata :
*(.rodata1)
*(.rodata.str1.4)
*(.eh_frame)
- }
+ } :text
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
.bootpg ADDR(.text) + 0x7f000 :
{
cpu/mpc85xx/start.o (.bootpg)
- } = 0xffff
+ } :text = 0xffff
.resetvec ADDR(.text) + 0x7fffc :
{
*(.resetvec)
- } = 0xffff
+ } :text = 0xffff
. = ADDR(.text) + 0x80000;
*(.dynbss)
*(.bss)
*(COMMON)
- }
+ } :bss
. = ALIGN(4);
_end = . ;
OUTPUT_ARCH(powerpc)
/* Do we need any of these for elf?
__DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
SECTIONS
{
/* Read-only sections, merged into text segment: */
*(.text)
*(.fixup)
*(.got1)
- }
+ } :text
_etext = .;
PROVIDE (etext = .);
.rodata :
*(.rodata1)
*(.rodata.str1.4)
*(.eh_frame)
- }
+ } :text
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
.bootpg ADDR(.text) + 0x7f000 :
{
cpu/mpc85xx/start.o (.bootpg)
- } = 0xffff
+ } :text = 0xffff
.resetvec ADDR(.text) + 0x7fffc :
{
*(.resetvec)
- } = 0xffff
+ } :text = 0xffff
. = ADDR(.text) + 0x80000;
*(.dynbss)
*(.bss)
*(COMMON)
- }
+ } :bss
. = ALIGN(4);
_end = . ;
OUTPUT_ARCH(powerpc)
/* Do we need any of these for elf?
__DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
SECTIONS
{
/* Read-only sections, merged into text segment: */
*(.text)
*(.fixup)
*(.got1)
- }
+ } :text
_etext = .;
PROVIDE (etext = .);
.rodata :
*(.rodata1)
*(.rodata.str1.4)
*(.eh_frame)
- }
+ } :text
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
.bootpg ADDR(.text) + 0x7f000 :
{
cpu/mpc85xx/start.o (.bootpg)
- } = 0xffff
+ } :text = 0xffff
.resetvec ADDR(.text) + 0x7fffc :
{
*(.resetvec)
- } = 0xffff
+ } :text = 0xffff
. = ADDR(.text) + 0x80000;
*(.dynbss)
*(.bss)
*(COMMON)
- }
+ } :bss
. = ALIGN(4);
_end = . ;
OUTPUT_ARCH(powerpc)
/* Do we need any of these for elf?
__DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
SECTIONS
{
/* Read-only sections, merged into text segment: */
*(.text)
*(.fixup)
*(.got1)
- }
+ } :text
_etext = .;
PROVIDE (etext = .);
.rodata :
*(.rodata1)
*(.rodata.str1.4)
*(.eh_frame)
- }
+ } :text
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
.bootpg ADDR(.text) + 0x7f000 :
{
cpu/mpc85xx/start.o (.bootpg)
- } = 0xffff
+ } :text = 0xffff
.resetvec ADDR(.text) + 0x7fffc :
{
*(.resetvec)
- } = 0xffff
+ } :text = 0xffff
. = ADDR(.text) + 0x80000;
*(.dynbss)
*(.bss)
*(COMMON)
- }
+ } :bss
. = ALIGN(4);
_end = . ;
OUTPUT_ARCH(powerpc)
/* Do we need any of these for elf?
__DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
SECTIONS
{
/* Read-only sections, merged into text segment: */
*(.text)
*(.fixup)
*(.got1)
- }
+ } :text
_etext = .;
PROVIDE (etext = .);
.rodata :
*(.rodata1)
*(.rodata.str1.4)
*(.eh_frame)
- }
+ } :text
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
.bootpg ADDR(.text) + 0x7f000 :
{
cpu/mpc85xx/start.o (.bootpg)
- } = 0xffff
+ } :text = 0xffff
.resetvec ADDR(.text) + 0x7fffc :
{
*(.resetvec)
- } = 0xffff
+ } :text = 0xffff
. = ADDR(.text) + 0x80000;
*(.dynbss)
*(.bss)
*(COMMON)
- }
+ } :bss
. = ALIGN(4);
_end = . ;
OUTPUT_ARCH(powerpc)
/* Do we need any of these for elf?
__DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
SECTIONS
{
/* Read-only sections, merged into text segment: */
*(.text)
*(.fixup)
*(.got1)
- }
+ } :text
_etext = .;
PROVIDE (etext = .);
.rodata :
*(.rodata1)
*(.rodata.str1.4)
*(.eh_frame)
- }
+ } :text
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
.bootpg ADDR(.text) + 0x7f000 :
{
cpu/mpc85xx/start.o (.bootpg)
- } = 0xffff
+ } :text = 0xffff
.resetvec ADDR(.text) + 0x7fffc :
{
*(.resetvec)
- } = 0xffff
+ } :text = 0xffff
. = ADDR(.text) + 0x80000;
*(.dynbss)
*(.bss)
*(COMMON)
- }
+ } :bss
. = ALIGN(4);
_end = . ;
mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX);
mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX);
mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
- mx31_gpio_mux(MUX_RTS1__UART1_CTS_B);
+ mx31_gpio_mux(MUX_CTS1__UART1_CTS_B);
/* SPI2 */
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS2);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SCLK);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SPI_RDY);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_MOSI);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_MISO);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS0);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS1);
+ mx31_gpio_mux(MUX_CSPI2_SS2__CSPI2_SS2_B);
+ mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK);
+ mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B);
+ mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI);
+ mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO);
+ mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B);
+ mx31_gpio_mux(MUX_CSPI2_SS1__CSPI2_SS1_B);
/* start SPI2 clock */
__REG(CCM_CGR2) = __REG(CCM_CGR2) | (3 << 4);
/* WARNING - the following is hand-optimized to fit within */
/* the sector layout of our flash chips! XXX FIXME XXX */
- cpu/arm1136/start.o (.text)
- board/mx31ads/libmx31ads.a (.text)
- lib_arm/libarm.a (.text)
- net/libnet.a (.text)
- drivers/mtd/libmtd.a (.text)
+ cpu/arm1136/start.o (.text)
+ board/freescale/mx31ads/libmx31ads.a (.text)
+ lib_arm/libarm.a (.text)
+ net/libnet.a (.text)
+ drivers/mtd/libmtd.a (.text)
. = DEFINED(env_offset) ? env_offset : .;
common/environment.o(.text)
#include <common.h>
-#ifndef CFG_FLASH_CFI_DRIVER
+#ifndef CONFIG_FLASH_CFI_DRIVER
flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
return (res);
}
-#endif /*CFG_FLASH_CFI_DRIVER*/
+#endif /*CONFIG_FLASH_CFI_DRIVER*/
mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX);
mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX);
mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
- mx31_gpio_mux(MUX_RTS1__UART1_CTS_B);
+ mx31_gpio_mux(MUX_CTS1__UART1_CTS_B);
/* SPI2 */
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS2);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SCLK);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SPI_RDY);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_MOSI);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_MISO);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS0);
- mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS1);
+ mx31_gpio_mux(MUX_CSPI2_SS2__CSPI2_SS2_B);
+ mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK);
+ mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B);
+ mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI);
+ mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO);
+ mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B);
+ mx31_gpio_mux(MUX_CSPI2_SS1__CSPI2_SS1_B);
/* start SPI2 clock */
__REG(CCM_CGR2) = __REG(CCM_CGR2) | (3 << 4);
mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX);
mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX);
mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
- mx31_gpio_mux(MUX_RTS1__UART1_CTS_B);
+ mx31_gpio_mux(MUX_CTS1__UART1_CTS_B);
/* setup pins for I2C2 (for EEPROM, RTC) */
mx31_gpio_mux(MUX_CSPI2_MOSI__I2C2_SCL);
- mx31_gpio_mux(MUX_CSPI2_MISO__I2C2_SCL);
+ mx31_gpio_mux(MUX_CSPI2_MISO__I2C2_SDA);
gd->bd->bi_arch_number = 447; /* board id for linux */
gd->bd->bi_boot_params = (0x80000100); /* adress of boot parameters */
#include <asm/bitops.h>
#include <asm/gpio.h>
#include <asm/io.h>
-#include <asm/ppc4xx-intvec.h>
+#include <asm/ppc4xx-uic.h>
#include <asm/processor.h>
DECLARE_GLOBAL_DATA_PTR;
*/
void korat_pci_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
{
- pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, VECNUM_EIR2);
+ pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, VECNUM_EIRQ2);
}
#endif
*/
#include <common.h>
-
+#include <asm/io.h>
#if defined(CONFIG_CMD_NAND)
/*
* hardware specific access to control-lines
*/
-static void nc650_hwcontrol(struct mtd_info *mtd, int cmd)
+static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
- switch(cmd) {
- case NAND_CTL_SETCLE:
- this->IO_ADDR_W += 2;
- break;
- case NAND_CTL_CLRCLE:
- this->IO_ADDR_W -= 2;
- break;
- case NAND_CTL_SETALE:
- this->IO_ADDR_W += 1;
- break;
- case NAND_CTL_CLRALE:
- this->IO_ADDR_W -= 1;
- break;
- case NAND_CTL_SETNCE:
- case NAND_CTL_CLRNCE:
- /* nop */
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ this->IO_ADDR_W += 2;
+ else
+ this->IO_ADDR_W -= 2;
+ if ( ctrl & NAND_ALE )
+ this->IO_ADDR_W += 1;
+ else
+ this->IO_ADDR_W -= 1;
}
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
#elif defined(CONFIG_IDS852_REV2)
/*
* hardware specific access to control-lines
*/
-static void nc650_hwcontrol(struct mtd_info *mtd, int cmd)
+static void nc650_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
- switch(cmd) {
- case NAND_CTL_SETCLE:
- *(((volatile __u8 *) this->IO_ADDR_W) + 0xa) = 0;
- break;
- case NAND_CTL_CLRCLE:
- *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0;
- break;
- case NAND_CTL_SETALE:
- *(((volatile __u8 *) this->IO_ADDR_W) + 0x9) = 0;
- break;
- case NAND_CTL_CLRALE:
- *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0;
- break;
- case NAND_CTL_SETNCE:
- *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0;
- break;
- case NAND_CTL_CLRNCE:
- *(((volatile __u8 *) this->IO_ADDR_W) + 0xc) = 0;
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ writeb(0, (volatile __u8 *) this->IO_ADDR_W + 0xa);
+ else
+ writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0x8);
+ if ( ctrl & NAND_ALE )
+ writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0x9);
+ else
+ writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0x8);
+ if ( ctrl & NAND_NCE )
+ writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0x8);
+ else
+ writeb(0, (volatile __u8 *) this->IO_ADDR_W) + 0xc);
}
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
#else
#error Unknown IDS852 module revision
* argument are board-specific (per include/linux/mtd/nand.h):
* - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
* - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
- * - hwcontrol: hardwarespecific function for accesing control-lines
+ * - cmd_ctrl: hardwarespecific function for accesing control-lines
* - dev_ready: hardwarespecific function for accesing device ready/busy line
* - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
* only be provided if a hardware ECC is available
- * - eccmode: mode of ecc, see defines
+ * - eccm.ode: mode of ecc, see defines
* - chip_delay: chip dependent delay for transfering data from array to
* read regs (tR)
* - options: various chip options. They can partly be set to inform
int board_nand_init(struct nand_chip *nand)
{
- nand->hwcontrol = nc650_hwcontrol;
- nand->eccmode = NAND_ECC_SOFT;
+ nand->cmd_ctrl = nc650_hwcontrol;
+ nand->ecc.mode = NAND_ECC_SOFT;
nand->chip_delay = 12;
/* nand->options = NAND_SAMSUNG_LP_OPTIONS;*/
return 0;
*/
#include <common.h>
+#include <asm/io.h>
#if defined(CONFIG_CMD_NAND)
#define MASK_CLE 0x02
#define MASK_ALE 0x04
-static void netstar_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void netstar_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
- switch (cmd) {
- case NAND_CTL_SETCLE: IO_ADDR_W |= MASK_CLE; break;
- case NAND_CTL_SETALE: IO_ADDR_W |= MASK_ALE; break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ IO_ADDR_W |= MASK_CLE;
+ if ( ctrl & NAND_ALE )
+ IO_ADDR_W |= MASK_ALE;
}
- this->IO_ADDR_W = (void *) IO_ADDR_W;
+ this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
int board_nand_init(struct nand_chip *nand)
{
nand->options = NAND_SAMSUNG_LP_OPTIONS;
- nand->eccmode = NAND_ECC_SOFT;
- nand->hwcontrol = netstar_nand_hwcontrol;
+ nand->ecc.mode = NAND_ECC_SOFT;
+ nand->cmd_ctrl = netstar_nand_hwcontrol;
nand->chip_delay = 400;
return 0;
}
return 0;
}
-#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_LEGACY)
#include <linux/mtd/nand_legacy.h>
/*--------------------------------------------------------------------
* Setup the interrupt controller polarities, triggers, etc.
*-------------------------------------------------------------------*/
- mtdcr (uic0sr, 0xffffffff); /* clear all */
- mtdcr (uic0er, 0x00000000); /* disable all */
- mtdcr (uic0cr, 0x00000009); /* SMI & UIC1 crit are critical */
- mtdcr (uic0pr, 0xfffffe03); /* per manual */
- mtdcr (uic0tr, 0x01c00000); /* per manual */
- mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */
- mtdcr (uic0sr, 0xffffffff); /* clear all */
-
+ /*
+ * Because of the interrupt handling rework to handle 440GX interrupts
+ * with the common code, we needed to change names of the UIC registers.
+ * Here the new relationship:
+ *
+ * U-Boot name 440GX name
+ * -----------------------
+ * UIC0 UICB0
+ * UIC1 UIC0
+ * UIC2 UIC1
+ * UIC3 UIC2
+ */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic1er, 0x00000000); /* disable all */
- mtdcr (uic1cr, 0x00000000); /* all non-critical */
- mtdcr (uic1pr, 0xffffe0ff); /* per ref-board manual */
- mtdcr (uic1tr, 0x00ffc000); /* per ref-board manual */
+ mtdcr (uic1cr, 0x00000009); /* SMI & UIC1 crit are critical */
+ mtdcr (uic1pr, 0xfffffe03); /* per manual */
+ mtdcr (uic1tr, 0x01c00000); /* per manual */
mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic2sr, 0xffffffff); /* clear all */
mtdcr (uic2er, 0x00000000); /* disable all */
mtdcr (uic2cr, 0x00000000); /* all non-critical */
- mtdcr (uic2pr, 0xffffffff); /* per ref-board manual */
- mtdcr (uic2tr, 0x00ff8c0f); /* per ref-board manual */
+ mtdcr (uic2pr, 0xffffe0ff); /* per ref-board manual */
+ mtdcr (uic2tr, 0x00ffc000); /* per ref-board manual */
mtdcr (uic2vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic2sr, 0xffffffff); /* clear all */
- mtdcr (uicb0sr, 0xfc000000); /* clear all */
- mtdcr (uicb0er, 0x00000000); /* disable all */
- mtdcr (uicb0cr, 0x00000000); /* all non-critical */
- mtdcr (uicb0pr, 0xfc000000); /* */
- mtdcr (uicb0tr, 0x00000000); /* */
- mtdcr (uicb0vr, 0x00000001); /* */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+ mtdcr (uic3er, 0x00000000); /* disable all */
+ mtdcr (uic3cr, 0x00000000); /* all non-critical */
+ mtdcr (uic3pr, 0xffffffff); /* per ref-board manual */
+ mtdcr (uic3tr, 0x00ff8c0f); /* per ref-board manual */
+ mtdcr (uic3vr, 0x00000001); /* int31 highest, base=0x000 */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+
+ mtdcr (uic0sr, 0xfc000000); /* clear all */
+ mtdcr (uic0er, 0x00000000); /* disable all */
+ mtdcr (uic0cr, 0x00000000); /* all non-critical */
+ mtdcr (uic0pr, 0xfc000000); /* */
+ mtdcr (uic0tr, 0x00000000); /* */
+ mtdcr (uic0vr, 0x00000001); /* */
/* Setup shutdown/SSD empty interrupt as inputs */
out32(GPIO0_TCR, in32(GPIO0_TCR) & ~(CFG_GPIO_SHUTDOWN | CFG_GPIO_SSD_EMPTY));
*
* There are 2 NAND devices on the board, a Hynix HY27US08561A (1 GByte).
*/
-static void alpr_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void alpr_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- switch (cmd) {
- case NAND_CTL_SETCLE:
- hwctl |= 0x1;
- break;
- case NAND_CTL_CLRCLE:
- hwctl &= ~0x1;
- break;
- case NAND_CTL_SETALE:
- hwctl |= 0x2;
- break;
- case NAND_CTL_CLRALE:
- hwctl &= ~0x2;
- break;
- case NAND_CTL_SETNCE:
- break;
- case NAND_CTL_CLRNCE:
- writeb(0x00, &(alpr_ndfc->term));
- break;
- }
-}
-
-static void alpr_nand_write_byte(struct mtd_info *mtd, u_char byte)
-{
- struct nand_chip *nand = mtd->priv;
+ struct nand_chip *this = mtd->priv;
- if (hwctl & 0x1)
- /*
- * IO_ADDR_W used as CMD[i] reg to support multiple NAND
- * chips.
- */
- writeb(byte, nand->IO_ADDR_W);
- else if (hwctl & 0x2) {
- writeb(byte, &(alpr_ndfc->addr_wait));
- } else
- writeb(byte, &(alpr_ndfc->data));
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ hwctl |= 0x1;
+ else
+ hwctl &= ~0x1;
+ if ( ctrl & NAND_ALE )
+ hwctl |= 0x2;
+ else
+ hwctl &= ~0x2;
+ if ( (ctrl & NAND_NCE) != NAND_NCE)
+ writeb(0x00, &(alpr_ndfc->term));
+ }
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static u_char alpr_nand_read_byte(struct mtd_info *mtd)
{
alpr_ndfc = (struct alpr_ndfc_regs *)CFG_NAND_BASE;
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
/* Reference hardware control function */
- nand->hwcontrol = alpr_nand_hwcontrol;
- /* Set command delay time */
- nand->write_byte = alpr_nand_write_byte;
+ nand->cmd_ctrl = alpr_nand_hwcontrol;
nand->read_byte = alpr_nand_read_byte;
nand->write_buf = alpr_nand_write_buf;
nand->read_buf = alpr_nand_read_buf;
#define DP(x)
#endif
-extern void flush_data_cache (void);
-extern void invalidate_l1_instruction_cache (void);
extern flash_info_t flash_info[];
/* ------------------------------------------------------------------------- */
#include <common.h>
#include <asm/arch/ixp425.h>
-#if !defined(CFG_FLASH_CFI_DRIVER)
+#if !defined(CONFIG_FLASH_CFI_DRIVER)
/*
* include common flash code (for esd boards)
return size;
}
-#endif /* CFG_FLASH_CFI_DRIVER */
+#endif /* CONFIG_FLASH_CFI_DRIVER */
*
* There is one NAND devices on the board, a Hynix HY27US08561A (32 MByte).
*/
-static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- switch (cmd) {
- case NAND_CTL_SETCLE:
- hwctl |= 0x1;
- break;
- case NAND_CTL_CLRCLE:
- hwctl &= ~0x1;
- break;
-
- case NAND_CTL_SETALE:
- hwctl |= 0x2;
- break;
- case NAND_CTL_CLRALE:
- hwctl &= ~0x2;
- break;
-
- case NAND_CTL_SETNCE:
- break;
- case NAND_CTL_CLRNCE:
- writeb(0x00, &(pdnb3_ndfc->term));
- break;
+ struct nand_chip *this = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ hwctl |= 0x1;
+ else
+ hwctl &= ~0x1;
+ if ( ctrl & NAND_ALE )
+ hwctl |= 0x2;
+ else
+ hwctl &= ~0x2;
+ if ( (ctrl & NAND_NCE) != NAND_NCE)
+ writeb(0x00, &(pdnb3_ndfc->term));
}
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
-static void pdnb3_nand_write_byte(struct mtd_info *mtd, u_char byte)
-{
- if (hwctl & 0x1)
- writeb(byte, &(pdnb3_ndfc->cmd));
- else if (hwctl & 0x2)
- writeb(byte, &(pdnb3_ndfc->addr));
- else
- writeb(byte, &(pdnb3_ndfc->data));
-}
static u_char pdnb3_nand_read_byte(struct mtd_info *mtd)
{
{
pdnb3_ndfc = (struct pdnb3_ndfc_regs *)CFG_NAND_BASE;
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
/* Set address of NAND IO lines (Using Linear Data Access Region) */
nand->IO_ADDR_R = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4);
nand->IO_ADDR_W = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4);
/* Reference hardware control function */
- nand->hwcontrol = pdnb3_nand_hwcontrol;
- /* Set command delay time */
- nand->hwcontrol = pdnb3_nand_hwcontrol;
- nand->write_byte = pdnb3_nand_write_byte;
+ nand->cmd_ctrl = pdnb3_nand_hwcontrol;
nand->read_byte = pdnb3_nand_read_byte;
nand->write_buf = pdnb3_nand_write_buf;
nand->read_buf = pdnb3_nand_read_buf;
#include <config.h>
#if defined(CONFIG_CMD_NAND)
#include <asm/gpio.h>
+#include <asm/io.h>
#include <nand.h>
/*
* hardware specific access to control-lines
*/
-static void quad100hd_hwcontrol(struct mtd_info *mtd, int cmd)
+static void quad100hd_hwcontrol(struct mtd_info *mtd,
+ int cmd, unsigned int ctrl)
{
- switch(cmd) {
- case NAND_CTL_SETCLE:
- gpio_write_bit(CFG_NAND_CLE, 1);
- break;
- case NAND_CTL_CLRCLE:
- gpio_write_bit(CFG_NAND_CLE, 0);
- break;
+ struct nand_chip *this = mtd->priv;
- case NAND_CTL_SETALE:
- gpio_write_bit(CFG_NAND_ALE, 1);
- break;
- case NAND_CTL_CLRALE:
- gpio_write_bit(CFG_NAND_ALE, 0);
- break;
-
- case NAND_CTL_SETNCE:
- gpio_write_bit(CFG_NAND_CE, 0);
- break;
- case NAND_CTL_CLRNCE:
- gpio_write_bit(CFG_NAND_CE, 1);
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ gpio_write_bit(CFG_NAND_CLE, !!(ctrl & NAND_CLE));
+ gpio_write_bit(CFG_NAND_ALE, !!(ctrl & NAND_ALE));
+ gpio_write_bit(CFG_NAND_CE, !(ctrl & NAND_NCE));
}
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static int quad100hd_nand_ready(struct mtd_info *mtd)
int board_nand_init(struct nand_chip *nand)
{
/* Set address of hardware control function */
- nand->hwcontrol = quad100hd_hwcontrol;
+ nand->cmd_ctrl = quad100hd_hwcontrol;
nand->dev_ready = quad100hd_nand_ready;
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
/* 15 us command delay time */
nand->chip_delay = 20;
/*--------------------------------------------------------------------+
* Setup the interrupt controller polarities, triggers, etc.
+-------------------------------------------------------------------*/
- mtdcr (uic0sr, 0xffffffff); /* clear all */
- mtdcr (uic0er, 0x00000000); /* disable all */
- mtdcr (uic0cr, 0x00000000); /* all non- critical */
- mtdcr (uic0pr, 0xfffffe03); /* polarity */
- mtdcr (uic0tr, 0x01c00000); /* trigger edge vs level */
- mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */
- mtdcr (uic0sr, 0xffffffff); /* clear all */
-
+ /*
+ * Because of the interrupt handling rework to handle 440GX interrupts
+ * with the common code, we needed to change names of the UIC registers.
+ * Here the new relationship:
+ *
+ * U-Boot name 440GX name
+ * -----------------------
+ * UIC0 UICB0
+ * UIC1 UIC0
+ * UIC2 UIC1
+ * UIC3 UIC2
+ */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic1er, 0x00000000); /* disable all */
- mtdcr (uic1cr, 0x00000000); /* all non-critical */
- mtdcr (uic1pr, 0xffffc8ff); /* polarity */
- mtdcr (uic1tr, 0x00ff0000); /* trigger edge vs level */
+ mtdcr (uic1cr, 0x00000000); /* all non- critical */
+ mtdcr (uic1pr, 0xfffffe03); /* polarity */
+ mtdcr (uic1tr, 0x01c00000); /* trigger edge vs level */
mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic2sr, 0xffffffff); /* clear all */
mtdcr (uic2er, 0x00000000); /* disable all */
mtdcr (uic2cr, 0x00000000); /* all non-critical */
- mtdcr (uic2pr, 0xffff83ff); /* polarity */
- mtdcr (uic2tr, 0x00ff8c0f); /* trigger edge vs level */
+ mtdcr (uic2pr, 0xffffc8ff); /* polarity */
+ mtdcr (uic2tr, 0x00ff0000); /* trigger edge vs level */
mtdcr (uic2vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic2sr, 0xffffffff); /* clear all */
- mtdcr (uicb0sr, 0xfc000000); /* clear all */
- mtdcr (uicb0er, 0x00000000); /* disable all */
- mtdcr (uicb0cr, 0x00000000); /* all non-critical */
- mtdcr (uicb0pr, 0xfc000000);
- mtdcr (uicb0tr, 0x00000000);
- mtdcr (uicb0vr, 0x00000001);
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+ mtdcr (uic3er, 0x00000000); /* disable all */
+ mtdcr (uic3cr, 0x00000000); /* all non-critical */
+ mtdcr (uic3pr, 0xffff83ff); /* polarity */
+ mtdcr (uic3tr, 0x00ff8c0f); /* trigger edge vs level */
+ mtdcr (uic3vr, 0x00000001); /* int31 highest, base=0x000 */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+
+ mtdcr (uic0sr, 0xfc000000); /* clear all */
+ mtdcr (uic0er, 0x00000000); /* disable all */
+ mtdcr (uic0cr, 0x00000000); /* all non-critical */
+ mtdcr (uic0pr, 0xfc000000);
+ mtdcr (uic0tr, 0x00000000);
+ mtdcr (uic0vr, 0x00000001);
fpga_init();
/*--------------------------------------------------------------------+
* Setup the interrupt controller polarities, triggers, etc.
+-------------------------------------------------------------------*/
- mtdcr (uic0sr, 0xffffffff); /* clear all */
- mtdcr (uic0er, 0x00000000); /* disable all */
- mtdcr (uic0cr, 0x00000000); /* all non- critical */
- mtdcr (uic0pr, 0xfffffe03); /* polarity */
- mtdcr (uic0tr, 0x01c00000); /* trigger edge vs level */
- mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */
- mtdcr (uic0sr, 0xffffffff); /* clear all */
-
+ /*
+ * Because of the interrupt handling rework to handle 440GX interrupts
+ * with the common code, we needed to change names of the UIC registers.
+ * Here the new relationship:
+ *
+ * U-Boot name 440GX name
+ * -----------------------
+ * UIC0 UICB0
+ * UIC1 UIC0
+ * UIC2 UIC1
+ * UIC3 UIC2
+ */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic1er, 0x00000000); /* disable all */
- mtdcr (uic1cr, 0x00000000); /* all non-critical */
- mtdcr (uic1pr, 0xffffc8ff); /* polarity */
- mtdcr (uic1tr, 0x00ff0000); /* trigger edge vs level */
+ mtdcr (uic1cr, 0x00000000); /* all non- critical */
+ mtdcr (uic1pr, 0xfffffe03); /* polarity */
+ mtdcr (uic1tr, 0x01c00000); /* trigger edge vs level */
mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic2sr, 0xffffffff); /* clear all */
mtdcr (uic2er, 0x00000000); /* disable all */
mtdcr (uic2cr, 0x00000000); /* all non-critical */
- mtdcr (uic2pr, 0xffff83ff); /* polarity */
- mtdcr (uic2tr, 0x00ff8c0f); /* trigger edge vs level */
+ mtdcr (uic2pr, 0xffffc8ff); /* polarity */
+ mtdcr (uic2tr, 0x00ff0000); /* trigger edge vs level */
mtdcr (uic2vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic2sr, 0xffffffff); /* clear all */
- mtdcr (uicb0sr, 0xfc000000); /* clear all */
- mtdcr (uicb0er, 0x00000000); /* disable all */
- mtdcr (uicb0cr, 0x00000000); /* all non-critical */
- mtdcr (uicb0pr, 0xfc000000);
- mtdcr (uicb0tr, 0x00000000);
- mtdcr (uicb0vr, 0x00000001);
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+ mtdcr (uic3er, 0x00000000); /* disable all */
+ mtdcr (uic3cr, 0x00000000); /* all non-critical */
+ mtdcr (uic3pr, 0xffff83ff); /* polarity */
+ mtdcr (uic3tr, 0x00ff8c0f); /* trigger edge vs level */
+ mtdcr (uic3vr, 0x00000001); /* int31 highest, base=0x000 */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+
+ mtdcr (uic0sr, 0xfc000000); /* clear all */
+ mtdcr (uic0er, 0x00000000); /* disable all */
+ mtdcr (uic0cr, 0x00000000); /* all non-critical */
+ mtdcr (uic0pr, 0xfc000000);
+ mtdcr (uic0tr, 0x00000000);
+ mtdcr (uic0vr, 0x00000001);
fpga_init();
static void *sc3_io_base;
static void *sc3_control_base = (void *)0xEF600700;
-static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void sc3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- switch (cmd) {
- case NAND_CTL_SETCLE:
- set_bit (SC3_NAND_CLE, sc3_control_base);
- break;
- case NAND_CTL_CLRCLE:
- clear_bit (SC3_NAND_CLE, sc3_control_base);
- break;
-
- case NAND_CTL_SETALE:
- set_bit (SC3_NAND_ALE, sc3_control_base);
- break;
- case NAND_CTL_CLRALE:
- clear_bit (SC3_NAND_ALE, sc3_control_base);
- break;
-
- case NAND_CTL_SETNCE:
- set_bit (SC3_NAND_CE, sc3_control_base);
- break;
- case NAND_CTL_CLRNCE:
- clear_bit (SC3_NAND_CE, sc3_control_base);
- break;
+ struct nand_chip *this = mtd->priv;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ set_bit (SC3_NAND_CLE, sc3_control_base);
+ else
+ clear_bit (SC3_NAND_CLE, sc3_control_base);
+ if ( ctrl & NAND_ALE )
+ set_bit (SC3_NAND_ALE, sc3_control_base);
+ else
+ clear_bit (SC3_NAND_ALE, sc3_control_base);
+ if ( ctrl & NAND_NCE )
+ set_bit (SC3_NAND_CE, sc3_control_base);
+ else
+ clear_bit (SC3_NAND_CE, sc3_control_base);
}
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static int sc3_nand_dev_ready(struct mtd_info *mtd)
int board_nand_init(struct nand_chip *nand)
{
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
sc3_io_base = (void *) CFG_NAND_BASE;
/* Set address of NAND IO lines (Using Linear Data Access Region) */
nand->IO_ADDR_R = (void __iomem *) sc3_io_base;
nand->IO_ADDR_W = (void __iomem *) sc3_io_base;
/* Reference hardware control function */
- nand->hwcontrol = sc3_nand_hwcontrol;
+ nand->cmd_ctrl = sc3_nand_hwcontrol;
nand->dev_ready = sc3_nand_dev_ready;
nand->select_chip = sc3_select_chip;
return 0;
static int state;
static void nand_write_byte(struct mtd_info *mtd, u_char byte);
static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
-static void nand_write_word(struct mtd_info *mtd, u16 word);
static u_char nand_read_byte(struct mtd_info *mtd);
static u16 nand_read_word(struct mtd_info *mtd);
static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
static int nand_device_ready(struct mtd_info *mtdinfo);
-static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd);
#define FPGA_NAND_CMD_MASK (0x7 << 28)
-#define FPGA_NAND_CMD_COMMAND (0x0 << 28)
+#define FPGA_NAND_CMD_COMMAND (0x0 << 28)
#define FPGA_NAND_CMD_ADDR (0x1 << 28)
#define FPGA_NAND_CMD_READ (0x2 << 28)
#define FPGA_NAND_CMD_WRITE (0x3 << 28)
#define FPGA_NAND_BUSY (0x1 << 15)
#define FPGA_NAND_ENABLE (0x1 << 31)
-#define FPGA_NAND_DATA_SHIFT 16
+#define FPGA_NAND_DATA_SHIFT 16
/**
* nand_write_byte - write one byte to the chip
}
/**
- * nand_write_word - write one word to the chip
- * @mtd: MTD device structure
- * @word: data word to write
- */
-static void nand_write_word(struct mtd_info *mtd, u16 word)
-{
- nand_write_buf(mtd, (const uchar *)&word, sizeof(word));
-}
-
-/**
* nand_write_buf - write buffer to chip
* @mtd: MTD device structure
* @buf: data buffer
{
int i;
struct nand_chip *this = mtd->priv;
- long val;
-
- if ((state & FPGA_NAND_CMD_MASK) == FPGA_NAND_CMD_MASK) {
- /* Write data */
- val = (state & FPGA_NAND_ENABLE) | FPGA_NAND_CMD_WRITE;
- } else {
- /* Write address or command */
- val = state;
- }
for (i = 0; i < len; i++) {
- out_be32(this->IO_ADDR_W, val | (buf[i] << FPGA_NAND_DATA_SHIFT));
+ out_be32(this->IO_ADDR_W,
+ state | (buf[i] << FPGA_NAND_DATA_SHIFT));
}
}
for (i = 0; i < len; i++) {
if (buf[i] != nand_read_byte(mtd));
- return -EFAULT;
+ return -EFAULT;
}
return 0;
}
* @mtd: MTD device structure
* @cmd: Command
*/
-static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
{
+ if (ctrl & NAND_CTRL_CHANGE) {
+ state &= ~(FPGA_NAND_CMD_MASK | FPGA_NAND_ENABLE);
+
+ switch (ctrl & (NAND_ALE | NAND_CLE)) {
+ case 0:
+ state |= FPGA_NAND_CMD_WRITE;
+ break;
+
+ case NAND_ALE:
+ state |= FPGA_NAND_CMD_ADDR;
+ break;
- switch(cmd) {
- case NAND_CTL_CLRALE:
- state |= FPGA_NAND_CMD_MASK; /* use all 1s to mark */
- break;
- case NAND_CTL_CLRCLE:
- state |= FPGA_NAND_CMD_MASK; /* use all 1s to mark */
- break;
- case NAND_CTL_SETCLE:
- state = (state & ~FPGA_NAND_CMD_MASK) | FPGA_NAND_CMD_COMMAND;
- break;
- case NAND_CTL_SETALE:
- state = (state & ~FPGA_NAND_CMD_MASK) | FPGA_NAND_CMD_ADDR;
- break;
- case NAND_CTL_SETNCE:
- state |= FPGA_NAND_ENABLE;
- break;
- case NAND_CTL_CLRNCE:
- state &= ~FPGA_NAND_ENABLE;
- break;
- default:
- printf("%s: unknown cmd %#x\n", __FUNCTION__, cmd);
- break;
+ case NAND_CLE:
+ state |= FPGA_NAND_CMD_COMMAND;
+ break;
+
+ default:
+ printf("%s: unknown ctrl %#x\n", __FUNCTION__, ctrl);
+ }
+
+ if (ctrl & NAND_NCE)
+ state |= FPGA_NAND_ENABLE;
}
+
+ if (cmd != NAND_CMD_NONE)
+ nand_write_byte(mtdinfo, cmd);
}
int board_nand_init(struct nand_chip *nand)
{
- nand->hwcontrol = nand_hwcontrol;
- nand->eccmode = NAND_ECC_SOFT;
+ nand->cmd_ctrl = nand_hwcontrol;
+ nand->ecc.mode = NAND_ECC_SOFT;
nand->dev_ready = nand_device_ready;
- nand->write_byte = nand_write_byte;
nand->read_byte = nand_read_byte;
- nand->write_word = nand_write_word;
nand->read_word = nand_read_word;
nand->write_buf = nand_write_buf;
nand->read_buf = nand_read_buf;
static u8 hwctl = 0;
-static void upmnand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void upmnand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- switch (cmd) {
- case NAND_CTL_SETCLE:
- hwctl |= 0x1;
- break;
- case NAND_CTL_CLRCLE:
- hwctl &= ~0x1;
- break;
-
- case NAND_CTL_SETALE:
- hwctl |= 0x2;
- break;
-
- case NAND_CTL_CLRALE:
- hwctl &= ~0x2;
- break;
+ struct nand_chip *this = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
+ hwctl |= 0x1;
+ else
+ hwctl &= ~0x1;
+ if ( ctrl & NAND_ALE )
+ hwctl |= 0x2;
+ else
+ hwctl &= ~0x2;
}
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
static void upmnand_write_byte(struct mtd_info *mtdinfo, u_char byte)
memctl->memc_br3 = CFG_NAND_BR;
memctl->memc_mbmr = (MxMR_OP_NORM);
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
- nand->hwcontrol = upmnand_hwcontrol;
+ nand->cmd_ctrl = upmnand_hwcontrol;
nand->read_byte = upmnand_read_byte;
nand->write_byte = upmnand_write_byte;
nand->dev_ready = tqm8272_dev_ready;
DECLARE_GLOBAL_DATA_PTR;
-#if !defined(CFG_FLASH_CFI_DRIVER) /* do not use if CFI driver is configured */
+#if !defined(CONFIG_FLASH_CFI_DRIVER) /* do not use if CFI driver is configured */
#if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \
&& !defined(CONFIG_TQM885D)
/*-----------------------------------------------------------------------
*/
-#endif /* !defined(CFG_FLASH_CFI_DRIVER) */
+#endif /* !defined(CONFIG_FLASH_CFI_DRIVER) */
--- /dev/null
+#
+# (C) Copyright 2000-2006
+# 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
+ifneq ($(OBJTREE),$(SRCTREE))
+endif
+
+INCS :=
+CFLAGS += $(INCS)
+HOST_CFLAGS += $(INCS)
+
+LIB = $(obj)lib$(BOARD).a
+
+COBJS = $(BOARD).o
+
+SOBJS = init.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $^
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
--- /dev/null
+#
+# (C) Copyright 2000
+# 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
+#
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+ifndef TEXT_BASE
+TEXT_BASE = 0x04000000
+endif
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <ppc_asm.tmpl>
+#include <config.h>
+#include <asm-ppc/mmu.h>
+
+.section .bootpg,"ax"
+.globl tlbtab
+
+tlbtab:
+tlbtab_start
+ /* SDRAM */
+tlbentry(XPAR_DDR2_SDRAM_MEM_BASEADDR, SZ_256M, CFG_SDRAM_BASE, 0,
+ AC_R | AC_W | AC_X | SA_G | SA_I)
+ /* UART */
+tlbentry(XPAR_UARTLITE_0_BASEADDR, SZ_64K, XPAR_UARTLITE_0_BASEADDR, 0,
+ AC_R | AC_W | SA_G | SA_I)
+ /* PIC */
+tlbentry(XPAR_INTC_0_BASEADDR, SZ_64K, XPAR_INTC_0_BASEADDR, 0,
+ AC_R | AC_W | SA_G | SA_I)
+#ifdef XPAR_IIC_EEPROM_BASEADDR
+ /* I2C */
+tlbentry(XPAR_IIC_EEPROM_BASEADDR, SZ_64K, XPAR_IIC_EEPROM_BASEADDR, 0,
+ AC_R | AC_W | SA_G | SA_I)
+#endif
+#ifdef XPAR_LLTEMAC_0_BASEADDR
+ /* Net */
+tlbentry(XPAR_LLTEMAC_0_BASEADDR, SZ_64K, XPAR_LLTEMAC_0_BASEADDR, 0,
+ AC_R | AC_W | SA_G | SA_I)
+#endif
+#ifdef XPAR_FLASH_MEM0_BASEADDR
+ /*Flash*/
+tlbentry(XPAR_FLASH_MEM0_BASEADDR, SZ_256M, XPAR_FLASH_MEM0_BASEADDR, 0,
+ AC_R | AC_W | AC_X | SA_G | SA_I)
+#endif
+tlbtab_end
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+#include <common.h>
+#include <asm/processor.h>
+
+int board_pre_init(void)
+{
+ return 0;
+}
+
+int checkboard(void)
+{
+ puts("ML507 Board\n");
+ return 0;
+}
+
+phys_size_t initdram(int board_type)
+{
+ return get_ram_size(XPAR_DDR2_SDRAM_MEM_BASEADDR,
+ CFG_SDRAM_SIZE_MB * 1024 * 1024);
+}
+
+void get_sys_info(sys_info_t * sysInfo)
+{
+ sysInfo->freqProcessor = XPAR_CORE_CLOCK_FREQ_HZ;
+ sysInfo->freqPLB = XPAR_PLB_CLOCK_FREQ_HZ;
+ sysInfo->freqPCI = 0;
+
+ return;
+}
--- /dev/null
+/*
+ * (C) Copyright 2000-2004
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+ENTRY(_start_440)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+
+ ppcenv_assert = ASSERT(. < 0xFFFFB000, ".bss section too big, overlaps .ppcenv section. Please update your confguration: CFG_MONITOR_BASE, CFG_MONITOR_LEN and TEXT_BASE may need to be modified.");
+
+ _end = . ;
+ PROVIDE (end = .);
+}
--- /dev/null
+/*
+ * (C) Copyright 2000-2004
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+ENTRY(_start_440)
+
+SECTIONS
+{
+ .resetvec 0xFFFFFFFC :
+ {
+ *(.resetvec)
+ } = 0xffff
+
+ .bootpg 0xFFFFF000 :
+ {
+ cpu/ppc4xx/start.o (.bootpg)
+ } = 0xffff
+
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+
+ ppcenv_assert = ASSERT(. < 0xFFFFB000, ".bss section too big, overlaps .ppcenv section. Please update your confguration: CFG_MONITOR_BASE, CFG_MONITOR_LEN and TEXT_BASE may need to be modified.");
+
+ _end = . ;
+ PROVIDE (end = .);
+}
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * based on xparameters-ml507.h by Xilinx
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef XPARAMETER_H
+#define XPARAMETER_H
+
+#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000
+#define XPAR_IIC_EEPROM_BASEADDR 0x81600000
+#define XPAR_INTC_0_BASEADDR 0x81800000
+#define XPAR_LLTEMAC_0_BASEADDR 0x81C00000
+#define XPAR_UARTLITE_0_BASEADDR 0x84000000
+#define XPAR_FLASH_MEM0_BASEADDR 0xFE000000
+#define XPAR_PLB_CLOCK_FREQ_HZ 100000000
+#define XPAR_CORE_CLOCK_FREQ_HZ 400000000
+#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13
+#define XPAR_UARTLITE_0_BAUDRATE 9600
+
+#endif
/*--------------------------------------------------------------------
* Setup the interrupt controller polarities, triggers, etc.
*-------------------------------------------------------------------*/
- mtdcr (uic0sr, 0xffffffff); /* clear all */
- mtdcr (uic0er, 0x00000000); /* disable all */
- mtdcr (uic0cr, 0x00000003); /* SMI & UIC1 crit are critical */
- mtdcr (uic0pr, 0xfffffe00); /* per ref-board manual */
- mtdcr (uic0tr, 0x01c00000); /* per ref-board manual */
- mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */
- mtdcr (uic0sr, 0xffffffff); /* clear all */
-
+ /*
+ * Because of the interrupt handling rework to handle 440GX interrupts
+ * with the common code, we needed to change names of the UIC registers.
+ * Here the new relationship:
+ *
+ * U-Boot name 440GX name
+ * -----------------------
+ * UIC0 UICB0
+ * UIC1 UIC0
+ * UIC2 UIC1
+ * UIC3 UIC2
+ */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic1er, 0x00000000); /* disable all */
- mtdcr (uic1cr, 0x00000000); /* all non-critical */
- mtdcr (uic1pr, 0xffffc0ff); /* per ref-board manual */
- mtdcr (uic1tr, 0x00ff8000); /* per ref-board manual */
+ mtdcr (uic1cr, 0x00000003); /* SMI & UIC1 crit are critical */
+ mtdcr (uic1pr, 0xfffffe00); /* per ref-board manual */
+ mtdcr (uic1tr, 0x01c00000); /* per ref-board manual */
mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic1sr, 0xffffffff); /* clear all */
mtdcr (uic2sr, 0xffffffff); /* clear all */
mtdcr (uic2er, 0x00000000); /* disable all */
mtdcr (uic2cr, 0x00000000); /* all non-critical */
- mtdcr (uic2pr, 0xffffffff); /* per ref-board manual */
- mtdcr (uic2tr, 0x00ff8c0f); /* per ref-board manual */
+ mtdcr (uic2pr, 0xffffc0ff); /* per ref-board manual */
+ mtdcr (uic2tr, 0x00ff8000); /* per ref-board manual */
mtdcr (uic2vr, 0x00000001); /* int31 highest, base=0x000 */
mtdcr (uic2sr, 0xffffffff); /* clear all */
- mtdcr (uicb0sr, 0xfc000000); /* clear all */
- mtdcr (uicb0er, 0x00000000); /* disable all */
- mtdcr (uicb0cr, 0x00000000); /* all non-critical */
- mtdcr (uicb0pr, 0xfc000000); /* */
- mtdcr (uicb0tr, 0x00000000); /* */
- mtdcr (uicb0vr, 0x00000001); /* */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+ mtdcr (uic3er, 0x00000000); /* disable all */
+ mtdcr (uic3cr, 0x00000000); /* all non-critical */
+ mtdcr (uic3pr, 0xffffffff); /* per ref-board manual */
+ mtdcr (uic3tr, 0x00ff8c0f); /* per ref-board manual */
+ mtdcr (uic3vr, 0x00000001); /* int31 highest, base=0x000 */
+ mtdcr (uic3sr, 0xffffffff); /* clear all */
+
+ mtdcr (uic0sr, 0xfc000000); /* clear all */
+ mtdcr (uic0er, 0x00000000); /* disable all */
+ mtdcr (uic0cr, 0x00000000); /* all non-critical */
+ mtdcr (uic0pr, 0xfc000000); /* */
+ mtdcr (uic0tr, 0x00000000); /* */
+ mtdcr (uic0vr, 0x00000001); /* */
LED0_ON();
/*
* not required for Monahans DFC
*/
-static void dfc_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void dfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
return;
}
}
-/*
- * These functions are quite problematic for the DFC. Luckily they are
- * not used in the current nand code, except for nand_command, which
- * we've defined our own anyway. The problem is, that we always need
- * to write 4 bytes to the DFC Data Buffer, but in these functions we
- * don't know if to buffer the bytes/half words until we've gathered 4
- * bytes or if to send them straight away.
- *
- * Solution: Don't use these with Mona's DFC and complain loudly.
- */
-static void dfc_write_word(struct mtd_info *mtd, u16 word)
-{
- printf("dfc_write_word: WARNING, this function does not work with the Monahans DFC!\n");
-}
-static void dfc_write_byte(struct mtd_info *mtd, u_char byte)
-{
- printf("dfc_write_byte: WARNING, this function does not work with the Monahans DFC!\n");
-}
-
/* The original:
* static void dfc_read_buf(struct mtd_info *mtd, const u_char *buf, int len)
*
*/
static u16 dfc_read_word(struct mtd_info *mtd)
{
- printf("dfc_write_byte: UNIMPLEMENTED.\n");
+ printf("dfc_read_word: UNIMPLEMENTED.\n");
return 0;
}
/* this function is called after Programm and Erase Operations to
* check for success or failure */
-static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this)
{
unsigned long ndsr=0, event=0;
+ int state = this->state;
if(state == FL_WRITING) {
event = NDSR_CS0_CMDD | NDSR_CS0_BBD;
* argument are board-specific (per include/linux/mtd/nand_new.h):
* - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
* - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
- * - hwcontrol: hardwarespecific function for accesing control-lines
+ * - cmd_ctrl: hardwarespecific function for accesing control-lines
* - dev_ready: hardwarespecific function for accesing device ready/busy line
* - enable_hwecc?: function to enable (reset) hardware ecc generator. Must
* only be provided if a hardware ECC is available
- * - eccmode: mode of ecc, see defines
+ * - ecc.mode: mode of ecc, see defines
* - chip_delay: chip dependent delay for transfering data from array to
* read regs (tR)
* - options: various chip options. They can partly be set to inform
/* wait 10 us due to cmd buffer clear reset */
/* wait(10); */
-
- nand->hwcontrol = dfc_hwcontrol;
+ nand->cmd_ctrl = dfc_hwcontrol;
/* nand->dev_ready = dfc_device_ready; */
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
nand->options = NAND_BUSWIDTH_16;
nand->waitfunc = dfc_wait;
nand->read_byte = dfc_read_byte;
- nand->write_byte = dfc_write_byte;
nand->read_word = dfc_read_word;
- nand->write_word = dfc_write_word;
nand->read_buf = dfc_read_buf;
nand->write_buf = dfc_write_buf;
nand->cmdfunc = dfc_cmdfunc;
- nand->autooob = &delta_oob;
+/* nand->autooob = &delta_oob; */
nand->badblock_pattern = &delta_bbt_descr;
return 0;
}
#include <common.h> /* core U-Boot definitions */
#include <ACEX1K.h> /* ACEX device family */
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ALTERA) && defined(CONFIG_FPGA_ACEX1K)
-
/* Define FPGA_DEBUG to get debug printf's */
#ifdef FPGA_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
return ret_val;
}
-
-#endif /* CONFIG_FPGA && CONFIG_FPGA_ALTERA && CONFIG_FPGA_ACEX1K */
AOBJS =
COBJS-y += main.o
-COBJS-y += ACEX1K.o
-COBJS-y += altera.o
-COBJS-y += bedbug.o
+COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o
COBJS-y += circbuf.o
COBJS-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o
COBJS-y += cmd_autoscript.o
COBJS-$(CONFIG_CMD_FDOS) += cmd_fdos.o
COBJS-$(CONFIG_CMD_FLASH) += cmd_flash.o
ifdef CONFIG_FPGA
+COBJS-y += fpga.o
COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o
+COBJS-$(CONFIG_FPGA_SPARTAN2) += spartan2.o
+COBJS-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
+COBJS-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
+COBJS-$(CONFIG_FPGA_XILINX) += xilinx.o
+ifdef CONFIG_FPGA_ALTERA
+COBJS-y += altera.o
+COBJS-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
+COBJS-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
+COBJS-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
+endif
endif
COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o
COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o
COBJS-$(CONFIG_CMD_IMMAP) += cmd_immap.o
COBJS-$(CONFIG_CMD_ITEST) += cmd_itest.o
COBJS-$(CONFIG_CMD_JFFS2) += cmd_jffs2.o
+COBJS-$(CONFIG_CMD_LICENSE) += cmd_license.o
COBJS-y += cmd_load.o
COBJS-$(CONFIG_LOGBUFFER) += cmd_log.o
COBJS-y += cmd_mem.o
COBJS-y += cmd_nand.o
COBJS-$(CONFIG_CMD_NET) += cmd_net.o
COBJS-y += cmd_nvedit.o
-COBJS-y += cmd_onenand.o
+COBJS-$(CONFIG_CMD_ONENAND) += cmd_onenand.o
COBJS-$(CONFIG_CMD_OTP) += cmd_otp.o
ifdef CONFIG_PCI
COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o
COBJS-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o
COBJS-$(CONFIG_CMD_USB) += cmd_usb.o
COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o
+COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o
COBJS-y += cmd_vfd.o
COBJS-y += command.o
COBJS-y += console.o
-COBJS-y += cyclon2.o
-COBJS-y += stratixII.o
COBJS-y += devices.o
COBJS-y += dlmalloc.o
-COBJS-y += docecc.o
+COBJS-$(CONFIG_CMD_DOC) += docecc.o
COBJS-y += environment.o
COBJS-y += env_common.o
COBJS-y += env_nand.o
COBJS-y += env_nowhere.o
COBJS-y += exports.o
COBJS-y += flash.o
-COBJS-y += fpga.o
COBJS-y += hush.o
COBJS-y += kgdb.o
-COBJS-y += lcd.o
+COBJS-$(CONFIG_LCD) += lcd.o
COBJS-y += lists.o
-COBJS-y += lynxkdi.o
+COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o
COBJS-y += memsize.o
-COBJS-y += miiphybb.o
+COBJS-$(CONFIG_BITBANGMII) += miiphybb.o
COBJS-y += miiphyutil.o
COBJS-y += s_record.o
COBJS-y += serial.o
-COBJS-y += soft_i2c.o
-COBJS-y += soft_spi.o
-COBJS-y += spartan2.o
-COBJS-y += spartan3.o
+COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o
+COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
+ifdef CONFIG_CMD_USB
COBJS-y += usb.o
-COBJS-y += usb_kbd.o
-COBJS-y += usb_storage.o
-COBJS-y += virtex2.o
-COBJS-y += xilinx.o
+COBJS-$(CONFIG_USB_STORAGE) += usb_storage.o
+endif
+COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
COBJS-y += crc16.o
COBJS-y += xyzModem.o
COBJS-y += cmd_mac.o
#define PRINTF(fmt,args...)
#endif
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ALTERA)
-
/* Local Static Functions */
static int altera_validate (Altera_desc * desc, const char *fn);
}
/* ------------------------------------------------------------------------- */
-
-#endif /* CONFIG_FPGA & CONFIG_FPGA_ALTERA */
#include <common.h>
-#if defined(CONFIG_CMD_BEDBUG)
-
#include <linux/ctype.h>
#include <bedbug/bedbug.h>
#include <bedbug/ppc.h>
* warranties of merchantability and fitness for a particular
* purpose.
*/
-
-#endif
memset ((void *)&images, 0, sizeof (images));
images.verify = getenv_yesno ("verify");
- images.autostart = getenv_yesno ("autostart");
images.lmb = &lmb;
lmb_init(&lmb);
* bios emulation, so turn them off again
*/
icache_disable();
- invalidate_l1_instruction_cache();
- flush_data_cache();
dcache_disable();
#endif
show_boot_progress (-9);
#ifdef DEBUG
puts ("\n## Control returned to monitor - resetting...\n");
- if (images.autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
#endif
- if (!images.autostart && iflag)
+ if (iflag)
enable_interrupts();
return 1;
#include <linux/mtd/nftl.h>
#include <linux/mtd/doc2000.h>
+/*
+ * ! BROKEN !
+ *
+ * TODO: must be implemented and tested by someone with HW
+ */
+#if 0
#ifdef CFG_DOC_SUPPORT_2000
#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k)
#else
puts ("No DiskOnChip found\n");
}
}
+#else
+void doc_probe(unsigned long physadr) {}
+#endif
#include <cramfs/cramfs_fs.h>
#if defined(CONFIG_CMD_NAND)
-#ifdef CFG_NAND_LEGACY
+#ifdef CONFIG_NAND_LEGACY
#include <linux/mtd/nand_legacy.h>
-#else /* !CFG_NAND_LEGACY */
+#else /* !CONFIG_NAND_LEGACY */
#include <linux/mtd/nand.h>
#include <nand.h>
-#endif /* !CFG_NAND_LEGACY */
+#endif /* !CONFIG_NAND_LEGACY */
#endif
/* enable/disable debugging messages */
#define DEBUG_JFFS
}
}
-#ifdef CFG_NAND_LEGACY
+#ifdef CONFIG_NAND_LEGACY
jffs2_free_cache(part);
#endif
list_del(&part->link);
list_for_each_safe(entry, n, head) {
part_tmp = list_entry(entry, struct part_info, link);
-#ifdef CFG_NAND_LEGACY
+#ifdef CONFIG_NAND_LEGACY
jffs2_free_cache(part_tmp);
#endif
list_del(entry);
} else if (type == MTD_DEV_TYPE_NAND) {
#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
if (num < CFG_MAX_NAND_DEVICE) {
-#ifndef CFG_NAND_LEGACY
+#ifndef CONFIG_NAND_LEGACY
*size = nand_info[num].size;
#else
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
--- /dev/null
+/*
+ * (C) Copyright 2007 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
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_CMD_LICENSE)
+
+/* COPYING is currently 15951 bytes in size */
+#define LICENSE_MAX 20480
+
+#include <command.h>
+#include <malloc.h>
+#include <license.h>
+int gunzip(void *, int, unsigned char *, unsigned long *);
+
+int do_license(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *tok, *dst = malloc(LICENSE_MAX);
+ unsigned long len = LICENSE_MAX;
+
+ if (!dst)
+ return -1;
+
+ if (gunzip(dst, LICENSE_MAX, license_gz, &len) != 0) {
+ printf("Error uncompressing license text\n");
+ free(dst);
+ return -1;
+ }
+ puts(dst);
+ free(dst);
+
+ return 0;
+}
+
+U_BOOT_CMD(license, 1, 1, do_license,
+ "license - print GPL license text\n",
+ NULL);
+
+#endif /* CONFIG_CMD_LICENSE */
#define untochar(x) ((int) (((x) - SPACE) & 0xff))
extern int os_data_count;
-extern int os_data_header[8];
static void set_kerm_bin_mode(unsigned long *);
static int k_recv(void);
}
-/* os_data_* takes an OS Open image and puts it into memory, and
- puts the boot header in an array named os_data_header
-
- if image is binary, no header is stored in os_data_header.
-*/
void (*os_data_init) (void);
void (*os_data_char) (char new_char);
static int os_data_state, os_data_state_saved;
static int os_data_count_saved;
static char *os_data_addr, *os_data_addr_saved;
static char *bin_start_address;
-int os_data_header[8];
+
static void bin_data_init (void)
{
os_data_state = 0;
os_data_count = 0;
os_data_addr = bin_start_address;
}
+
static void os_data_save (void)
{
os_data_state_saved = os_data_state;
os_data_count_saved = os_data_count;
os_data_addr_saved = os_data_addr;
}
+
static void os_data_restore (void)
{
os_data_state = os_data_state_saved;
os_data_count = os_data_count_saved;
os_data_addr = os_data_addr_saved;
}
+
static void bin_data_char (char new_char)
{
switch (os_data_state) {
break;
}
}
+
static void set_kerm_bin_mode (unsigned long *addr)
{
bin_start_address = (char *) addr;
k_data_escape = 0;
os_data_init ();
}
+
void k_data_save (void)
{
k_data_escape_saved = k_data_escape;
os_data_save ();
}
+
void k_data_restore (void)
{
k_data_escape = k_data_escape_saved;
os_data_restore ();
}
+
void k_data_char (char new_char)
{
if (k_data_escape) {
}
#endif /* CONFIG_CRC32_VERIFY */
+
+#ifdef CONFIG_CMD_UNZIP
+int gunzip (void *, int, unsigned char *, unsigned long *);
+
+int do_unzip ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ unsigned long src, dst;
+ unsigned long src_len = ~0UL, dst_len = ~0UL;
+ int err;
+
+ switch (argc) {
+ case 4:
+ dst_len = simple_strtoul(argv[3], NULL, 16);
+ /* fall through */
+ case 3:
+ src = simple_strtoul(argv[1], NULL, 16);
+ dst = simple_strtoul(argv[2], NULL, 16);
+ break;
+ default:
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+
+ return !!gunzip((void *) dst, dst_len, (void *) src, &src_len);
+}
+#endif /* CONFIG_CMD_UNZIP */
+
+
/**************************************************/
#if defined(CONFIG_CMD_MEMORY)
U_BOOT_CMD(
);
#endif /* CONFIG_MX_CYCLIC */
+#ifdef CONFIG_CMD_UNZIP
+U_BOOT_CMD(
+ unzip, 4, 1, do_unzip,
+ "unzip - unzip a memory region\n",
+ "srcaddr dstaddr [dstsize]\n"
+);
+#endif /* CONFIG_CMD_UNZIP */
+
#endif
#endif
}
cpuid = simple_strtoul(argv[1], NULL, 10);
- if (cpuid >= CONFIG_NR_CPUS) {
+ if (cpuid >= CONFIG_NUM_CPUS) {
printf ("Core num: %lu is out of range[0..%d]\n",
- cpuid, CONFIG_NR_CPUS - 1);
+ cpuid, CONFIG_NUM_CPUS - 1);
return 1;
}
#include <common.h>
-#ifndef CFG_NAND_LEGACY
+#ifndef CONFIG_NAND_LEGACY
/*
*
* New NAND support
*
*/
#include <common.h>
+#include <linux/mtd/mtd.h>
#if defined(CONFIG_CMD_NAND)
int mtdparts_init(void);
int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
int find_dev_and_part(const char *id, struct mtd_device **dev,
- u8 *part_num, struct part_info **part);
+ u8 *part_num, struct part_info **part);
#endif
-static int nand_dump_oob(nand_info_t *nand, ulong off)
-{
- return 0;
-}
-
-static int nand_dump(nand_info_t *nand, ulong off)
+static int nand_dump(nand_info_t *nand, ulong off, int only_oob)
{
int i;
- u_char *buf, *p;
+ u_char *datbuf, *oobbuf, *p;
- buf = malloc(nand->oobblock + nand->oobsize);
- if (!buf) {
+ datbuf = malloc(nand->writesize + nand->oobsize);
+ oobbuf = malloc(nand->oobsize);
+ if (!datbuf || !oobbuf) {
puts("No memory for page buffer\n");
return 1;
}
- off &= ~(nand->oobblock - 1);
- i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
+ off &= ~(nand->writesize - 1);
+ loff_t addr = (loff_t) off;
+ struct mtd_oob_ops ops;
+ memset(&ops, 0, sizeof(ops));
+ ops.datbuf = datbuf;
+ ops.oobbuf = oobbuf; /* must exist, but oob data will be appended to ops.datbuf */
+ ops.len = nand->writesize;
+ ops.ooblen = nand->oobsize;
+ ops.mode = MTD_OOB_RAW;
+ i = nand->read_oob(nand, addr, &ops);
if (i < 0) {
printf("Error (%d) reading page %08lx\n", i, off);
- free(buf);
+ free(datbuf);
+ free(oobbuf);
return 1;
}
printf("Page %08lx dump:\n", off);
- i = nand->oobblock >> 4; p = buf;
+ i = nand->writesize >> 4;
+ p = datbuf;
+
while (i--) {
- printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
- " %02x %02x %02x %02x %02x %02x %02x %02x\n",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
- p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
+ if (!only_oob)
+ printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
+ " %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+ p[8], p[9], p[10], p[11], p[12], p[13], p[14],
+ p[15]);
p += 16;
}
puts("OOB:\n");
i = nand->oobsize >> 3;
while (i--) {
- printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
p += 8;
}
- free(buf);
+ free(datbuf);
+ free(oobbuf);
return 0;
}
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
- int i, dev, ret;
+ int i, dev, ret = 0;
ulong addr, off;
size_t size;
char *cmd, *s;
for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
if (nand_info[i].name)
printf("Device %d: %s, sector size %u KiB\n",
- i, nand_info[i].name,
- nand_info[i].erasesize >> 10);
+ i, nand_info[i].name,
+ nand_info[i].erasesize >> 10);
}
return 0;
}
puts("\nno devices available\n");
else
printf("\nDevice %d: %s\n", nand_curr_device,
- nand_info[nand_curr_device].name);
+ nand_info[nand_curr_device].name);
return 0;
}
dev = (int)simple_strtoul(argv[2], NULL, 10);
off = (int)simple_strtoul(argv[2], NULL, 16);
if (s != NULL && strcmp(s, ".oob") == 0)
- ret = nand_dump_oob(nand, off);
+ ret = nand_dump(nand, off, 1);
else
- ret = nand_dump(nand, off);
+ ret = nand_dump(nand, off, 0);
return ret == 0 ? 1 : 0;
}
- /* read write */
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
int read;
return 1;
s = strchr(cmd, '.');
- if (s != NULL &&
- (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
- if (read) {
- /* read */
- nand_read_options_t opts;
- memset(&opts, 0, sizeof(opts));
- opts.buffer = (u_char*) addr;
- opts.length = size;
- opts.offset = off;
- opts.quiet = quiet;
- ret = nand_read_opts(nand, &opts);
- } else {
- /* write */
- nand_write_options_t opts;
- memset(&opts, 0, sizeof(opts));
- opts.buffer = (u_char*) addr;
- opts.length = size;
- opts.offset = off;
- /* opts.forcejffs2 = 1; */
- opts.pad = 1;
- opts.blockalign = 1;
- opts.quiet = quiet;
- ret = nand_write_opts(nand, &opts);
- }
- } else if (s != NULL && !strcmp(s, ".oob")) {
- /* read out-of-band data */
+ if (!s || !strcmp(s, ".jffs2") ||
+ !strcmp(s, ".e") || !strcmp(s, ".i")) {
if (read)
- ret = nand->read_oob(nand, off, size, &size,
- (u_char *) addr);
+ ret = nand_read_skip_bad(nand, off, &size,
+ (u_char *)addr);
else
- ret = nand->write_oob(nand, off, size, &size,
- (u_char *) addr);
- } else {
+ ret = nand_write_skip_bad(nand, off, &size,
+ (u_char *)addr);
+ } else if (s != NULL && !strcmp(s, ".oob")) {
+ /* out-of-band data */
+ mtd_oob_ops_t ops = {
+ .oobbuf = (u8 *)addr,
+ .ooblen = size,
+ .mode = MTD_OOB_RAW
+ };
+
if (read)
- ret = nand_read(nand, off, &size, (u_char *)addr);
+ ret = nand->read_oob(nand, off, &ops);
else
- ret = nand_write(nand, off, &size, (u_char *)addr);
+ ret = nand->write_oob(nand, off, &ops);
+ } else {
+ printf("Unknown nand command suffix '%s'.\n", s);
+ return 1;
}
printf(" %d bytes %s: %s\n", size,
}
return 1;
}
+
if (strcmp(cmd, "biterr") == 0) {
/* todo */
return 1;
if (!strcmp("status", argv[2]))
status = 1;
}
-
+/*
+ * ! BROKEN !
+ *
+ * TODO: must be implemented and tested by someone with HW
+ */
+#if 0
if (status) {
ulong block_start = 0;
ulong off;
nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1);
printf("device is %swrite protected\n",
(nand_chip->read_byte(nand) & 0x80 ?
- "NOT " : "" ) );
+ "NOT " : ""));
- for (off = 0; off < nand->size; off += nand->oobblock) {
+ for (off = 0; off < nand->size; off += nand->writesize) {
int s = nand_get_lock_status(nand, off);
/* print message only if status has changed
* or at end of chip
*/
- if (off == nand->size - nand->oobblock
+ if (off == nand->size - nand->writesize
|| (s != last_status && off != 0)) {
- printf("%08lx - %08lx: %8lu pages %s%s%s\n",
+ printf("%08lx - %08lx: %8d pages %s%s%s\n",
block_start,
off-1,
- (off-block_start)/nand->oobblock,
+ (off-block_start)/nand->writesize,
((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""),
((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
}
last_status = s;
- }
+ }
} else {
if (!nand_lock(nand, tight)) {
puts("NAND flash successfully locked\n");
return 1;
}
}
+#endif
return 0;
}
if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
return 1;
+/*
+ * ! BROKEN !
+ *
+ * TODO: must be implemented and tested by someone with HW
+ */
+#if 0
if (!nand_unlock(nand, off, size)) {
puts("NAND flash successfully unlocked\n");
} else {
"write and erase will probably fail\n");
return 1;
}
+#endif
return 0;
}
}
U_BOOT_CMD(nand, 5, 1, do_nand,
- "nand - NAND sub-system\n",
- "info - show available NAND devices\n"
- "nand device [dev] - show or set current device\n"
- "nand read[.jffs2] - addr off|partition size\n"
- "nand write[.jffs2] - addr off|partition size - read/write `size' bytes starting\n"
- " at offset `off' to/from memory address `addr'\n"
- "nand erase [clean] [off size] - erase `size' bytes from\n"
- " offset `off' (entire device if not specified)\n"
- "nand bad - show bad blocks\n"
- "nand dump[.oob] off - dump page\n"
- "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
- "nand markbad off - mark bad block at offset (UNSAFE)\n"
- "nand biterr off - make a bit error at offset (UNSAFE)\n"
- "nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
- "nand unlock [offset] [size] - unlock section\n");
+ "nand - NAND sub-system\n",
+ "info - show available NAND devices\n"
+ "nand device [dev] - show or set current device\n"
+ "nand read - addr off|partition size\n"
+ "nand write - addr off|partition size\n"
+ " read/write 'size' bytes starting at offset 'off'\n"
+ " to/from memory address 'addr', skipping bad blocks.\n"
+ "nand erase [clean] [off size] - erase 'size' bytes from\n"
+ " offset 'off' (entire device if not specified)\n"
+ "nand bad - show bad blocks\n"
+ "nand dump[.oob] off - dump page\n"
+ "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
+ "nand markbad off - mark bad block at offset (UNSAFE)\n"
+ "nand biterr off - make a bit error at offset (UNSAFE)\n"
+ "nand lock [tight] [status]\n"
+ " bring nand to lock state or display locked pages\n"
+ "nand unlock [offset] [size] - unlock section\n");
static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
ulong offset, ulong addr, char *cmd)
char *ep, *s;
size_t cnt;
image_header_t *hdr;
- int jffs2 = 0;
#if defined(CONFIG_FIT)
const void *fit_hdr = NULL;
#endif
s = strchr(cmd, '.');
if (s != NULL &&
- (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")))
- jffs2 = 1;
+ (strcmp(s, ".jffs2") && !strcmp(s, ".e") && !strcmp(s, ".i"))) {
+ printf("Unknown nand load suffix '%s'\n", s);
+ show_boot_progress(-53);
+ return 1;
+ }
printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
- cnt = nand->oobblock;
- if (jffs2) {
- nand_read_options_t opts;
- memset(&opts, 0, sizeof(opts));
- opts.buffer = (u_char*) addr;
- opts.length = cnt;
- opts.offset = offset;
- opts.quiet = 1;
- r = nand_read_opts(nand, &opts);
- } else {
- r = nand_read(nand, offset, &cnt, (u_char *) addr);
- }
-
+ cnt = nand->writesize;
+ r = nand_read(nand, offset, &cnt, (u_char *) addr);
if (r) {
puts("** Read error\n");
show_boot_progress (-56);
puts ("** Unknown image type\n");
return 1;
}
+ show_boot_progress (57);
- if (jffs2) {
- nand_read_options_t opts;
- memset(&opts, 0, sizeof(opts));
- opts.buffer = (u_char*) addr;
- opts.length = cnt;
- opts.offset = offset;
- opts.quiet = 1;
- r = nand_read_opts(nand, &opts);
- } else {
- r = nand_read(nand, offset, &cnt, (u_char *) addr);
- }
-
+ /* FIXME: skip bad blocks */
+ r = nand_read(nand, offset, &cnt, (u_char *) addr);
if (r) {
puts("** Read error\n");
show_boot_progress (-58);
U_BOOT_CMD(nboot, 4, 1, do_nandboot,
"nboot - boot from NAND device\n",
- "[.jffs2] [partition] | [[[loadAddr] dev] offset]\n");
+ "[partition] | [[[loadAddr] dev] offset]\n");
#endif
-#else /* CFG_NAND_LEGACY */
+#else /* CONFIG_NAND_LEGACY */
/*
*
* Legacy NAND support - to be phased out
#define CONFIG_MTD_NAND_ECC_JFFS2
/* bits for nand_legacy_rw() `cmd'; or together as needed */
-#define NANDRW_READ 0x01
-#define NANDRW_WRITE 0x00
-#define NANDRW_JFFS2 0x02
-#define NANDRW_JFFS2_SKIP 0x04
+#define NANDRW_READ 0x01
+#define NANDRW_WRITE 0x00
+#define NANDRW_JFFS2 0x02
+#define NANDRW_JFFS2_SKIP 0x04
/*
* Imports from nand_legacy.c
if (strncmp (argv[1], "read", 4) == 0 ||
strncmp (argv[1], "write", 5) == 0) {
- ulong addr = simple_strtoul (argv[2], NULL, 16);
- off_t off = simple_strtoul (argv[3], NULL, 16);
- size_t size = simple_strtoul (argv[4], NULL, 16);
- int cmd = (strncmp (argv[1], "read", 4) == 0) ?
- NANDRW_READ : NANDRW_WRITE;
+ ulong addr = simple_strtoul (argv[2], NULL, 16);
+ off_t off = simple_strtoul (argv[3], NULL, 16);
+ size_t size = simple_strtoul (argv[4], NULL, 16);
+ int cmd = (strncmp (argv[1], "read", 4) == 0) ?
+ NANDRW_READ : NANDRW_WRITE;
size_t total;
int ret;
char *cmdtail = strchr (argv[1], '.');
ret = nand_legacy_rw (nand_dev_desc + curr_device,
cmd, off, size,
- &total,
- (u_char *) addr);
+ &total, (u_char *) addr);
printf (" %d bytes %s: %s\n", total,
(cmd & NANDRW_READ) ? "read" : "written",
show_boot_progress (55);
printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
- dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
- offset);
+ dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
+ offset);
if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
- SECTORSIZE, NULL, (u_char *)addr)) {
+ SECTORSIZE, NULL, (u_char *)addr)) {
printf ("** Read error on %d\n", dev);
show_boot_progress (-56);
return 1;
show_boot_progress (57);
if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
- offset + SECTORSIZE, cnt, NULL,
- (u_char *)(addr+SECTORSIZE))) {
+ offset + SECTORSIZE, cnt, NULL,
+ (u_char *)(addr+SECTORSIZE))) {
printf ("** Read error on %d\n", dev);
show_boot_progress (-58);
return 1;
#endif
-#endif /* CFG_NAND_LEGACY */
+#endif /* CONFIG_NAND_LEGACY */
#include <common.h>
#include <command.h>
-#ifdef CONFIG_CMD_ONENAND
-
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
onenand_init();
return 0;
}
- onenand_print_device_info(onenand_chip.device_id, 1);
+ printf("%s\n", onenand_mtd.name);
return 0;
default:
} else {
start = simple_strtoul(argv[2], NULL, 10);
end = simple_strtoul(argv[3], NULL, 10);
- start -= (unsigned long)onenand_chip.base;
- end -= (unsigned long)onenand_chip.base;
start >>= onenand_chip.erase_shift;
end >>= onenand_chip.erase_shift;
size_t retlen = 0;
int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
- ofs -= (unsigned long)onenand_chip.base;
-
if (oob)
onenand_read_oob(&onenand_mtd, ofs, len,
&retlen, (u_char *) addr);
size_t len = simple_strtoul(argv[4], NULL, 16);
size_t retlen = 0;
- ofs -= (unsigned long)onenand_chip.base;
-
onenand_write(&onenand_mtd, ofs, len, &retlen,
(u_char *) addr);
printf("Done\n");
"onenand block[.oob] addr block [page] [len] - "
"read data with (block [, page]) to addr"
);
-
-#endif /* CONFIG_CMD_ONENAND */
#elif defined (CONFIG_405GP)
printf ("\n405GP registers; MSR=%08x\n",mfmsr());
printf ("\nUniversal Interrupt Controller Regs\n"
- "uicsr uicsrs uicer uiccr uicpr uictr uicmsr uicvr uicvcr"
+ "uicsr uicer uiccr uicpr uictr uicmsr uicvr uicvcr"
"\n"
- "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ "%08x %08x %08x %08x %08x %08x %08x %08x\n",
mfdcr(uicsr),
- mfdcr(uicsrs),
mfdcr(uicer),
mfdcr(uiccr),
mfdcr(uicpr),
--- /dev/null
+#include <common.h>
+
+#include <config.h>
+#include <command.h>
+
+#ifdef YAFFS2_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+extern void cmd_yaffs_mount(char *mp);
+extern void cmd_yaffs_umount(char *mp);
+extern void cmd_yaffs_read_file(char *fn);
+extern void cmd_yaffs_write_file(char *fn,char bval,int sizeOfFile);
+extern void cmd_yaffs_ls(const char *mountpt, int longlist);
+extern void cmd_yaffs_mwrite_file(char *fn, char *addr, int size);
+extern void cmd_yaffs_mread_file(char *fn, char *addr);
+extern void cmd_yaffs_mkdir(const char *dir);
+extern void cmd_yaffs_rmdir(const char *dir);
+extern void cmd_yaffs_rm(const char *path);
+extern void cmd_yaffs_mv(const char *oldPath, const char *newPath);
+
+extern int yaffs_DumpDevStruct(const char *path);
+
+
+int do_ymount (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *mtpoint = argv[1];
+ cmd_yaffs_mount(mtpoint);
+
+ return(0);
+}
+
+int do_yumount (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *mtpoint = argv[1];
+ cmd_yaffs_umount(mtpoint);
+
+ return(0);
+}
+
+int do_yls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *dirname = argv[argc-1];
+
+ cmd_yaffs_ls(dirname, (argc>2)?1:0);
+
+ return(0);
+}
+
+int do_yrd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *filename = argv[1];
+ printf ("Reading file %s ", filename);
+
+ cmd_yaffs_read_file(filename);
+
+ printf ("done\n");
+ return(0);
+}
+
+int do_ywr (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *filename = argv[1];
+ ulong value = simple_strtoul(argv[2], NULL, 16);
+ ulong numValues = simple_strtoul(argv[3], NULL, 16);
+
+ printf ("Writing value (%x) %x times to %s... ", value, numValues, filename);
+
+ cmd_yaffs_write_file(filename,value,numValues);
+
+ printf ("done\n");
+ return(0);
+}
+
+int do_yrdm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *filename = argv[1];
+ ulong addr = simple_strtoul(argv[2], NULL, 16);
+
+ cmd_yaffs_mread_file(filename, (char *)addr);
+
+ return(0);
+}
+
+int do_ywrm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *filename = argv[1];
+ ulong addr = simple_strtoul(argv[2], NULL, 16);
+ ulong size = simple_strtoul(argv[3], NULL, 16);
+
+ cmd_yaffs_mwrite_file(filename, (char *)addr, size);
+
+ return(0);
+}
+
+int do_ymkdir (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *dirname = argv[1];
+
+ cmd_yaffs_mkdir(dirname);
+
+ return(0);
+}
+
+int do_yrmdir (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *dirname = argv[1];
+
+ cmd_yaffs_rmdir(dirname);
+
+ return(0);
+}
+
+int do_yrm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *path = argv[1];
+
+ cmd_yaffs_rm(path);
+
+ return(0);
+}
+
+int do_ymv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *oldPath = argv[1];
+ char *newPath = argv[2];
+
+ cmd_yaffs_mv(newPath, oldPath);
+
+ return(0);
+}
+
+int do_ydump (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char *dirname = argv[1];
+ if (yaffs_DumpDevStruct(dirname) != 0)
+ printf("yaffs_DumpDevStruct returning error when dumping path: , %s\n", dirname);
+ return 0;
+}
+
+
+
+U_BOOT_CMD(
+ ymount, 3, 0, do_ymount,
+ "ymount\t- mount yaffs\n",
+ "\n"
+);
+
+U_BOOT_CMD(
+ yumount, 3, 0, do_yumount,
+ "yumount\t- unmount yaffs\n",
+ "\n"
+);
+
+U_BOOT_CMD(
+ yls, 4, 0, do_yls,
+ "yls\t- yaffs ls\n",
+ "[-l] name\n"
+);
+
+U_BOOT_CMD(
+ yrd, 2, 0, do_yrd,
+ "yrd\t- read file from yaffs\n",
+ "filename\n"
+);
+
+U_BOOT_CMD(
+ ywr, 4, 0, do_ywr,
+ "ywr\t- write file to yaffs\n",
+ "filename value num_vlues\n"
+);
+
+U_BOOT_CMD(
+ yrdm, 3, 0, do_yrdm,
+ "yrdm\t- read file to memory from yaffs\n",
+ "filename offset\n"
+);
+
+U_BOOT_CMD(
+ ywrm, 4, 0, do_ywrm,
+ "ywrm\t- write file from memory to yaffs\n",
+ "filename offset size\n"
+);
+
+U_BOOT_CMD(
+ ymkdir, 2, 0, do_ymkdir,
+ "ymkdir\t- YAFFS mkdir\n",
+ "dirname\n"
+);
+
+U_BOOT_CMD(
+ yrmdir, 2, 0, do_yrmdir,
+ "yrmdir\t- YAFFS rmdir\n",
+ "dirname\n"
+);
+
+U_BOOT_CMD(
+ yrm, 2, 0, do_yrm,
+ "yrm\t- YAFFS rm\n",
+ "path\n"
+);
+
+U_BOOT_CMD(
+ ymv, 4, 0, do_ymv,
+ "ymv\t- YAFFS mv\n",
+ "oldPath newPath\n"
+);
+
+U_BOOT_CMD(
+ ydump, 2, 0, do_ydump,
+ "ydump\t- YAFFS device struct\n",
+ "dirname\n"
+);
#include <altera.h>
#include <ACEX1K.h> /* ACEX device family */
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ALTERA) && defined(CONFIG_FPGA_CYCLON2)
-
/* Define FPGA_DEBUG to get debug printf's */
#ifdef FPGA_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
return ret_val;
}
-
-#endif /* CONFIG_FPGA && CONFIG_FPGA_ALTERA && CONFIG_FPGA_CYCLON2 */
#undef ECC_DEBUG
#undef PSYCHO_DEBUG
-#if defined(CONFIG_CMD_DOC)
-
#include <linux/mtd/doc2000.h>
/* need to undef it (from asm/termbits.h) */
free(Index_of);
return nb_errors;
}
-
-#endif
{
size_t end = offset + CFG_ENV_RANGE;
size_t amount_saved = 0;
- size_t blocksize;
+ size_t blocksize, len;
u_char *char_ptr;
blocksize = nand_info[0].erasesize;
+ len = min(blocksize, CFG_ENV_SIZE);
while (amount_saved < CFG_ENV_SIZE && offset < end) {
if (nand_block_isbad(&nand_info[0], offset)) {
offset += blocksize;
} else {
char_ptr = &buf[amount_saved];
- if (nand_write(&nand_info[0], offset, &blocksize,
+ if (nand_write(&nand_info[0], offset, &len,
char_ptr))
return 1;
offset += blocksize;
- amount_saved += blocksize;
+ amount_saved += len;
}
}
if (amount_saved != CFG_ENV_SIZE)
{
size_t end = offset + CFG_ENV_RANGE;
size_t amount_loaded = 0;
- size_t blocksize;
+ size_t blocksize, len;
u_char *char_ptr;
blocksize = nand_info[0].erasesize;
+ len = min(blocksize, CFG_ENV_SIZE);
while (amount_loaded < CFG_ENV_SIZE && offset < end) {
if (nand_block_isbad(&nand_info[0], offset)) {
offset += blocksize;
} else {
char_ptr = &buf[amount_loaded];
- if (nand_read(&nand_info[0], offset, &blocksize, char_ptr))
+ if (nand_read(&nand_info[0], offset, &len, char_ptr))
return 1;
offset += blocksize;
- amount_loaded += blocksize;
+ amount_loaded += len;
}
}
if (amount_loaded != CFG_ENV_SIZE)
void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
- size_t total;
int ret;
- total = CFG_ENV_SIZE;
ret = readenv(CFG_ENV_OFFSET, (u_char *) env_ptr);
- if (ret || total != CFG_ENV_SIZE)
+ if (ret)
return use_default();
if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
/* References to names in env_common.c */
extern uchar default_environment[];
-#define ONENAND_ENV_SIZE(mtd) (mtd.oobblock - ENV_HEADER_SIZE)
+#define ONENAND_ENV_SIZE(mtd) (mtd.writesize - ENV_HEADER_SIZE)
char *env_name_spec = "OneNAND";
size_t retlen;
env_addr = CFG_ENV_ADDR;
- env_addr -= (unsigned long) onenand_chip.base;
/* Check OneNAND exist */
- if (onenand_mtd.oobblock)
+ if (onenand_mtd.writesize)
/* Ignore read fail */
- onenand_read(&onenand_mtd, env_addr, onenand_mtd.oobblock,
+ onenand_read(&onenand_mtd, env_addr, onenand_mtd.writesize,
&retlen, (u_char *) env_ptr);
else
- onenand_mtd.oobblock = MAX_ONENAND_PAGESIZE;
+ onenand_mtd.writesize = MAX_ONENAND_PAGESIZE;
if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) !=
env_ptr->crc)
instr.len = CFG_ENV_SIZE;
instr.addr = env_addr;
- instr.addr -= (unsigned long)onenand_chip.base;
if (onenand_erase(&onenand_mtd, &instr)) {
printf("OneNAND: erase failed at 0x%08lx\n", env_addr);
return 1;
env_ptr->crc =
crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));
- env_addr -= (unsigned long)onenand_chip.base;
- if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.oobblock, &retlen,
+ if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.writesize, &retlen,
(u_char *) env_ptr)) {
printf("OneNAND: write failed at 0x%08x\n", instr.addr);
return 2;
int saveenv(void)
{
+ u32 sector = 1;
+
if (!env_flash) {
puts("Environment SPI flash not initialized\n");
return 1;
}
+ if (CFG_ENV_SIZE > CFG_ENV_SECT_SIZE) {
+ sector = CFG_ENV_SIZE / CFG_ENV_SECT_SIZE;
+ if (CFG_ENV_SIZE % CFG_ENV_SECT_SIZE)
+ sector++;
+ }
+
puts("Erasing SPI flash...");
- if (spi_flash_erase(env_flash, CFG_ENV_OFFSET, CFG_ENV_SIZE))
+ if (spi_flash_erase(env_flash, CFG_ENV_OFFSET, sector * CFG_ENV_SECT_SIZE))
return 1;
puts("Writing to SPI flash...");
#include <xilinx.h> /* xilinx specific definitions */
#include <altera.h> /* altera specific definitions */
-#if defined(CONFIG_FPGA)
-
#if 0
#define FPGA_DEBUG /* define FPGA_DEBUG to get debug messages */
#endif
}
/* ------------------------------------------------------------------------- */
-
-#endif /* CONFIG_FPGA */
return (dcrc == image_get_dcrc (hdr));
}
-
/**
* image_multi_count - get component (sub-image) count
* @hdr: pointer to the header of the multi component image
rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset);
if (rd_noffset < 0) {
debug ("* ramdisk: no ramdisk in config\n");
- return 1;
+ return 0;
}
}
#endif
#include <nand.h>
#endif
-#ifdef CONFIG_LCD
-
/************************************************************************/
/* ** FONT DATA */
/************************************************************************/
sprintf (info, "%s (%s - %s) ", U_BOOT_VERSION, __DATE__, __TIME__);
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y, (uchar *)info, strlen(info));
- sprintf (info, "(C) 2004 DENX Software Engineering");
+ sprintf (info, "(C) 2008 DENX Software Engineering GmbH");
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT,
(uchar *)info, strlen(info));
/************************************************************************/
/************************************************************************/
-
-#endif /* CONFIG_LCD */
#include <asm/processor.h>
#include <image.h>
-#if defined(CONFIG_LYNXKDI)
#include <lynxkdi.h>
DECLARE_GLOBAL_DATA_PTR;
#else
#error "Lynx KDI support not implemented for configured CPU"
#endif
-
-#endif /* CONFIG_LYNXKDI */
#include <ioports.h>
#include <ppc_asm.tmpl>
-#ifdef CONFIG_BITBANGMII
-
-
/*****************************************************************************
*
* Utility to send the preamble, address, and register (common to read
return 0;
}
-
-#endif /* CONFIG_BITBANGMII */
#endif
#include <i2c.h>
-#if defined(CONFIG_SOFT_I2C)
-
/* #define DEBUG_I2C */
#ifdef DEBUG_I2C
{
i2c_write(i2c_addr, reg, 1, &val, 1);
}
-
-
-#endif /* CONFIG_SOFT_I2C */
#include <common.h>
#include <spi.h>
-#if defined(CONFIG_SOFT_SPI)
-
#include <malloc.h>
/*-----------------------------------------------------------------------
return(0);
}
-
-#endif /* CONFIG_SOFT_SPI */
#include <common.h> /* core U-Boot definitions */
#include <spartan2.h> /* Spartan-II device family */
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_SPARTAN2)
-
/* Define FPGA_DEBUG to get debug printf's */
#ifdef FPGA_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
return ret_val;
}
-
-#endif
#include <common.h> /* core U-Boot definitions */
#include <spartan3.h> /* Spartan-II device family */
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_SPARTAN3)
-
/* Define FPGA_DEBUG to get debug printf's */
#ifdef FPGA_DEBUG
#define PRINTF(fmt,args...) printf (fmt ,##args)
return ret_val;
}
-
-#endif
#include <common.h> /* core U-Boot definitions */
#include <altera.h>
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ALTERA) && defined(CONFIG_FPGA_STRATIX_II)
-
int StratixII_ps_fpp_load (Altera_desc * desc, void *buf, size_t bsize,
int isSerial, int isSecure);
int StratixII_ps_fpp_dump (Altera_desc * desc, void *buf, size_t bsize);
return FPGA_SUCCESS;
}
-
-#endif /* defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ALTERA) && defined(CONFIG_FPGA_STRATIX_II) */
#include <linux/ctype.h>
#include <asm/byteorder.h>
-#if defined(CONFIG_CMD_USB)
-
#include <usb.h>
#ifdef CONFIG_4xx
#include <asm/4xx_pci.h>
return ret;
}
-#endif
-
/* EOF */
#include <devices.h>
#include <asm/byteorder.h>
-#ifdef CONFIG_USB_KEYBOARD
-
#include <usb.h>
#undef USB_KBD_DEBUG
}
-
#endif
-
-#endif /* CONFIG_USB_KEYBOARD */
#include <asm/byteorder.h>
#include <asm/processor.h>
-
-#if defined(CONFIG_CMD_USB)
#include <part.h>
#include <usb.h>
-#ifdef CONFIG_USB_STORAGE
-
#undef USB_STOR_DEBUG
#undef BBB_COMDAT_TRACE
#undef BBB_XPORT_TRACE
USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type);
return 1;
}
-
-#endif /* CONFIG_USB_STORAGE */
-#endif
#include <common.h>
#include <virtex2.h>
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_VIRTEX2)
-
#if 0
#define FPGA_DEBUG
#endif
}
return ret_val;
}
-#endif
/* vim: set ts=4 tw=78: */
#include <spartan2.h>
#include <spartan3.h>
-#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_XILINX)
-
#if 0
#define FPGA_DEBUG
#endif
return ret_val;
}
-
-#endif /* CONFIG_FPGA && CONFIG_FPGA_XILINX */
* Disable L1 Instruction cache
*/
_GLOBAL(icache_disable)
+ mflr r4
+ bl invalidate_l1_instruction_cache /* uses r3 */
+ sync
+ mtlr r4
mfspr r3, HID0
li r5, 0
ori r5, r5, HID0_ICE
{
unsigned long reg, shift, tmp;
- reg = IOMUXC_BASE + (mode & 0xfc);
+ reg = IOMUXC_BASE + (mode & 0x1fc);
shift = (~mode & 0x3) * 8;
tmp = __REG(reg);
tmp &= ~(0xff << shift);
- tmp |= ((mode >> 8) & 0xff) << shift;
+ tmp |= ((mode >> IOMUX_MODE_POS) & 0xff) << shift;
__REG(reg) = tmp;
}
#endif
#if defined(CONFIG_CMD_NAND)
-#if !defined(CFG_NAND_LEGACY)
+#if !defined(CONFIG_NAND_LEGACY)
#include <nand.h>
#include <s3c2410.h>
+#include <asm/io.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0)
-static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd)
+#define S3C2410_ADDR_NALE 4
+#define S3C2410_ADDR_NCLE 8
+
+static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
- DEBUGN("hwcontrol(): 0x%02x: ", cmd);
-
- switch (cmd) {
- case NAND_CTL_SETNCE:
- NFCONF &= ~S3C2410_NFCONF_nFCE;
- DEBUGN("NFCONF=0x%08x\n", NFCONF);
- break;
- case NAND_CTL_CLRNCE:
- NFCONF |= S3C2410_NFCONF_nFCE;
- DEBUGN("NFCONF=0x%08x\n", NFCONF);
- break;
- case NAND_CTL_SETALE:
- chip->IO_ADDR_W = NF_BASE + 0x8;
- DEBUGN("SETALE\n");
- break;
- case NAND_CTL_SETCLE:
- chip->IO_ADDR_W = NF_BASE + 0x4;
- DEBUGN("SETCLE\n");
- break;
- default:
- chip->IO_ADDR_W = NF_BASE + 0xc;
- break;
+ DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ ulong IO_ADDR_W = NF_BASE;
+
+ if (!(ctrl & NAND_CLE))
+ IO_ADDR_W |= S3C2410_ADDR_NCLE;
+ if (!(ctrl & NAND_ALE))
+ IO_ADDR_W |= S3C2410_ADDR_NALE;
+
+ chip->IO_ADDR_W = (void *)IO_ADDR_W;
+
+ if (ctrl & NAND_NCE)
+ NFCONF &= ~S3C2410_NFCONF_nFCE;
+ else
+ NFCONF |= S3C2410_NFCONF_nFCE;
}
- return;
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->IO_ADDR_W);
}
static int s3c2410_dev_ready(struct mtd_info *mtd)
#ifdef CONFIG_S3C2410_NAND_HWECC
void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
- DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd ,mode);
+ DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
NFCONF |= S3C2410_NFCONF_INITECC;
}
NFCONF = cfg;
/* initialize nand_chip data structure */
- nand->IO_ADDR_R = nand->IO_ADDR_W = 0x4e00000c;
+ nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e00000c;
/* read_buf and write_buf are default */
/* read_byte and write_byte are default */
/* hwcontrol always must be implemented */
- nand->hwcontrol = s3c2410_hwcontrol;
+ nand->cmd_ctrl = s3c2410_hwcontrol;
nand->dev_ready = s3c2410_dev_ready;
#ifdef CONFIG_S3C2410_NAND_HWECC
- nand->enable_hwecc = s3c2410_nand_enable_hwecc;
- nand->calculate_ecc = s3c2410_nand_calculate_ecc;
- nand->correct_data = s3c2410_nand_correct_data;
- nand->eccmode = NAND_ECC_HW3_512;
+ nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
+ nand->ecc.calculate = s3c2410_nand_calculate_ecc;
+ nand->ecc.correct = s3c2410_nand_correct_data;
+ nand->ecc.mode = NAND_ECC_HW3_512;
#else
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
#endif
#ifdef CONFIG_S3C2410_NAND_BBT
PLATFORM_CPPFLAGS += -march=armv5te
PLATFORM_CPPFLAGS += $(call cc-option,-mtune=arm926ejs,)
-LDSCRIPT := $(SRCTREE)/cpu/arm926ejs/at91sam9/u-boot.lds
+LDSCRIPT := $(SRCTREE)/cpu/arm926ejs/at91/u-boot.lds
*/
#include <common.h>
+#include <asm/io.h>
#ifdef CFG_USE_NAND
-#if !defined(CFG_NAND_LEGACY)
+#if !defined(CONFIG_NAND_LEGACY)
#include <nand.h>
#include <asm/arch/nand_defs.h>
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
-static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd)
+static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
- switch (cmd) {
- case NAND_CTL_SETCLE:
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if ( ctrl & NAND_CLE )
IO_ADDR_W |= MASK_CLE;
- break;
- case NAND_CTL_SETALE:
+ if ( ctrl & NAND_ALE )
IO_ADDR_W |= MASK_ALE;
- break;
+ this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
}
- this->IO_ADDR_W = (void *)IO_ADDR_W;
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
}
/* Set WP on deselect, write enable on select */
#ifdef CFG_NAND_HW_ECC
#ifdef CFG_NAND_LARGEPAGE
-static struct nand_oobinfo davinci_nand_oobinfo = {
+static struct nand_ecclayout davinci_nand_ecclayout = {
.useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 12,
.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
- .oobfree = { {2, 6}, {12, 12}, {28, 12}, {44, 12}, {60, 4} }
+ .oobfree = {
+ {.offset = 2, .length = 6},
+ {.offset = 12, .length = 12},
+ {.offset = 28, .length = 12},
+ {.offset = 44, .length = 12},
+ {.offset = 60, .length = 4}
+ }
};
#elif defined(CFG_NAND_SMALLPAGE)
-static struct nand_oobinfo davinci_nand_oobinfo = {
+static struct nand_ecclayout davinci_nand_ecclayout = {
.useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 3,
.eccpos = {0, 1, 2},
- .oobfree = { {6, 2}, {8, 8} }
+ .oobfree = {
+ {.offset = 6, .length = 2},
+ {.offset = 8, .length = 8}
+ }
};
#else
#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
int region, n;
struct nand_chip *this = mtd->priv;
- n = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
+ n = (this->ecc.size/512);
region = 1;
while (n--) {
int block_count = 0, i, rc;
this = mtd->priv;
- block_count = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
+ block_count = (this->ecc.size/512);
for (i = 0; i < block_count; i++) {
if (memcmp(read_ecc, calc_ecc, 3) != 0) {
rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
return(emif_addr->NANDFSR & 0x1);
}
-static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
{
while(!nand_davinci_dev_ready(mtd)) {;}
*NAND_CE0CLE = NAND_STATUS;
#endif
#ifdef CFG_NAND_HW_ECC
#ifdef CFG_NAND_LARGEPAGE
- nand->eccmode = NAND_ECC_HW12_2048;
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.size = 2048;
+ nand->ecc.bytes = 12;
#elif defined(CFG_NAND_SMALLPAGE)
- nand->eccmode = NAND_ECC_HW3_512;
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.size = 512;
+ nand->ecc.bytes = 3;
#else
#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
#endif
- nand->autooob = &davinci_nand_oobinfo;
- nand->calculate_ecc = nand_davinci_calculate_ecc;
- nand->correct_data = nand_davinci_correct_data;
- nand->enable_hwecc = nand_davinci_enable_hwecc;
+ nand->ecc.layout = &davinci_nand_ecclayout;
+ nand->ecc.calculate = nand_davinci_calculate_ecc;
+ nand->ecc.correct = nand_davinci_correct_data;
+ nand->ecc.hwctl = nand_davinci_enable_hwecc;
#else
- nand->eccmode = NAND_ECC_SOFT;
+ nand->ecc.mode = NAND_ECC_SOFT;
#endif
/* Set address of hardware control function */
- nand->hwcontrol = nand_davinci_hwcontrol;
+ nand->cmd_ctrl = nand_davinci_hwcontrol;
nand->dev_ready = nand_davinci_dev_ready;
nand->waitfunc = nand_davinci_waitfunc;
MCFCSM_CSMR0 = MCFCSM_CSMR_BAM(CFG_CS0_SIZE - 1) | MCFCSM_CSMR_V;
#endif
#else
-#waring "Chip Select 0 are not initialized/used"
+#warning "Chip Select 0 are not initialized/used"
#endif
#if defined(CFG_CS1_BASE) & defined(CFG_CS1_SIZE) & \
#else
/* Setup code to initialize FLASHBAR, if start from external Memory */
move.l #(CFG_INT_FLASH_BASE + CFG_INT_FLASH_ENABLE), %d0
- movec %d0, %RAMBAR1
+ movec %d0, %FLASHBAR
#endif /* (TEXT_BASE == CFG_INT_FLASH_BASE) */
#endif
GPIO_PAR_FBCTL_OE | GPIO_PAR_FBCTL_TA_TA | GPIO_PAR_FBCTL_RW_RW |
GPIO_PAR_FBCTL_TS_TS;
+#if !defined(CONFIG_CF_SBF)
#if (defined(CFG_CS0_BASE) && defined(CFG_CS0_MASK) && defined(CFG_CS0_CTRL))
fbcs->csar0 = CFG_CS0_BASE;
fbcs->cscr0 = CFG_CS0_CTRL;
fbcs->csmr0 = CFG_CS0_MASK;
#endif
+#endif
#if (defined(CFG_CS1_BASE) && defined(CFG_CS1_MASK) && defined(CFG_CS1_CTRL))
/* Latch chipselect */
#include <common.h>
#include <spi.h>
+#include <malloc.h>
#if defined(CONFIG_CF_DSPI)
#include <asm/immap.h>
+
void dspi_init(void)
{
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
DSPI_DMCR_CSIS2 | DSPI_DMCR_CSIS1 | DSPI_DMCR_CSIS0 |
DSPI_DMCR_CRXF | DSPI_DMCR_CTXF;
- dspi->dctar0 = DSPI_DCTAR_TRSZ(7) | DSPI_DCTAR_CPOL | DSPI_DCTAR_CPHA |
- DSPI_DCTAR_PCSSCK_1CLK | DSPI_DCTAR_PASC(0) |
- DSPI_DCTAR_PDT(0) | DSPI_DCTAR_CSSCK(0) |
- DSPI_DCTAR_ASC(0) | DSPI_DCTAR_PBR(0) |
- DSPI_DCTAR_DT(1) | DSPI_DCTAR_BR(1);
+#ifdef CFG_DSPI_DCTAR0
+ dspi->dctar0 = CFG_DSPI_DCTAR0;
+#endif
+#ifdef CFG_DSPI_DCTAR1
+ dspi->dctar1 = CFG_DSPI_DCTAR1;
+#endif
+#ifdef CFG_DSPI_DCTAR2
+ dspi->dctar2 = CFG_DSPI_DCTAR2;
+#endif
+#ifdef CFG_DSPI_DCTAR3
+ dspi->dctar3 = CFG_DSPI_DCTAR3;
+#endif
+#ifdef CFG_DSPI_DCTAR4
+ dspi->dctar4 = CFG_DSPI_DCTAR4;
+#endif
+#ifdef CFG_DSPI_DCTAR5
+ dspi->dctar5 = CFG_DSPI_DCTAR5;
+#endif
+#ifdef CFG_DSPI_DCTAR6
+ dspi->dctar6 = CFG_DSPI_DCTAR6;
+#endif
+#ifdef CFG_DSPI_DCTAR7
+ dspi->dctar7 = CFG_DSPI_DCTAR7;
+#endif
}
void dspi_tx(int chipsel, u8 attrib, u16 data)
return (dspi->drfr & 0xFFFF);
}
-#endif /* CONFIG_HARD_SPI */
+#if defined(CONFIG_CMD_SPI)
+void spi_init_f(void)
+{
+}
+
+void spi_init_r(void)
+{
+}
+
+void spi_init(void)
+{
+ dspi_init();
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct spi_slave *slave;
+
+ slave = malloc(sizeof(struct spi_slave));
+ if (!slave)
+ return NULL;
+
+ slave->bus = bus;
+ slave->cs = cs;
+
+ return slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ free(slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ static int bWrite = 0;
+ u8 *spi_rd, *spi_wr;
+ int len = bitlen >> 3;
+
+ spi_rd = (u8 *) din;
+ spi_wr = (u8 *) dout;
+
+ /* command handling */
+ if (((len == 4) || (len == 1) || (len == 5)) && (dout != NULL)) {
+ switch (*spi_wr) {
+ case 0x02: /* Page Prog */
+ bWrite = 1;
+ dspi_tx(slave->cs, 0x80, spi_wr[0]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[1]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[2]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[3]);
+ dspi_rx();
+ return 0;
+ case 0x05: /* Read Status */
+ if (len == 4)
+ if ((spi_wr[1] == 0xFF) && (spi_wr[2] == 0xFF)
+ && (spi_wr[3] == 0xFF)) {
+ dspi_tx(slave->cs, 0x80, *spi_wr);
+ dspi_rx();
+ }
+ return 0;
+ case 0x06: /* WREN */
+ dspi_tx(slave->cs, 0x00, *spi_wr);
+ dspi_rx();
+ return 0;
+ case 0x0B: /* Fast read */
+ if ((len == 5) && (spi_wr[4] == 0)) {
+ dspi_tx(slave->cs, 0x80, spi_wr[0]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[1]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[2]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[3]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[4]);
+ dspi_rx();
+ }
+ return 0;
+ case 0x9F: /* RDID */
+ dspi_tx(slave->cs, 0x80, *spi_wr);
+ dspi_rx();
+ return 0;
+ case 0xD8: /* Sector erase */
+ if (len == 4)
+ if ((spi_wr[2] == 0) && (spi_wr[3] == 0)) {
+ dspi_tx(slave->cs, 0x80, spi_wr[0]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[1]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x80, spi_wr[2]);
+ dspi_rx();
+ dspi_tx(slave->cs, 0x00, spi_wr[3]);
+ dspi_rx();
+ }
+ return 0;
+ }
+ }
+
+ if (bWrite)
+ len--;
+
+ while (len--) {
+ if (dout != NULL) {
+ dspi_tx(slave->cs, 0x80, *spi_wr);
+ dspi_rx();
+ spi_wr++;
+ }
+
+ if (din != NULL) {
+ dspi_tx(slave->cs, 0x80, 0);
+ *spi_rd = dspi_rx();
+ spi_rd++;
+ }
+ }
+
+ if (flags == SPI_XFER_END) {
+ if (bWrite) {
+ dspi_tx(slave->cs, 0x00, *spi_wr);
+ dspi_rx();
+ bWrite = 0;
+ } else {
+ dspi_tx(slave->cs, 0x00, 0);
+ dspi_rx();
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_CMD_SPI */
+
+#endif /* CONFIG_CF_DSPI */
*/
int get_clocks(void)
{
+
volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;
volatile pll_t *pll = (volatile pll_t *)MMAP_PLL;
- volatile u8 *cpld = (volatile u8 *)(CFG_CS2_BASE + 3);
- volatile u8 *fpga = (volatile u8 *)(CFG_CS3_BASE + 14);
int pllmult_nopci[] = { 20, 10, 24, 18, 12, 6, 16, 8 };
int pllmult_pci[] = { 12, 6, 16, 8 };
- int vco, bPci, temp, fbtemp, pcrvalue;
+ int vco = 0, bPci, temp, fbtemp, pcrvalue;
int *pPllmult = NULL;
u16 fbpll_mask;
- u8 cpldmode;
+
+#ifdef CONFIG_M54455EVB
+ volatile u8 *cpld = (volatile u8 *)(CFG_CS2_BASE + 3);
+#endif
+ u8 bootmode;
/* To determine PCI is present or not */
if (((ccm->ccr & CCM_CCR_360_FBCONFIG_MASK) == 0x00e0) ||
((ccm->ccr & CCM_CCR_360_FBCONFIG_MASK) == 0x0060)) {
pPllmult = &pllmult_pci[0];
- fbpll_mask = 3;
+ fbpll_mask = 3; /* 11b */
bPci = 1;
} else {
pPllmult = &pllmult_nopci[0];
- fbpll_mask = 7;
+ fbpll_mask = 7; /* 111b */
#ifdef CONFIG_PCI
gd->pci_clk = 0;
#endif
}
#ifdef CONFIG_M54455EVB
- /* Temporary place here, belongs in board/freescale/... */
- /* Temporary read from CCR- fixed fb issue, must be the same clock
- as pci or input clock, causing cpld/fpga read inconsistancy */
- fbtemp = pPllmult[ccm->ccr & fbpll_mask];
+ bootmode = (*cpld & 0x03);
- /* Break down into small pieces, code still in flex bus */
- pcrvalue = pll->pcr & 0xFFFFF0FF;
- temp = fbtemp - 1;
- pcrvalue |= PLL_PCR_OUTDIV3(temp);
+ if (bootmode != 3) {
+ /* Temporary read from CCR- fixed fb issue, must be the same clock
+ as pci or input clock, causing cpld/fpga read inconsistancy */
+ fbtemp = pPllmult[ccm->ccr & fbpll_mask];
+ /* Break down into small pieces, code still in flex bus */
+ pcrvalue = pll->pcr & 0xFFFFF0FF;
+ temp = fbtemp - 1;
+ pcrvalue |= PLL_PCR_OUTDIV3(temp);
+
+ pll->pcr = pcrvalue;
+ }
+#endif
+#ifdef CONFIG_M54451EVB
+ /* No external logic to read the bootmode, hard coded from built */
+#ifdef CONFIG_CF_SBF
+ bootmode = 3;
+#else
+ bootmode = 2;
+
+ /* default value is 16 mul, set to 20 mul */
+ pcrvalue = (pll->pcr & 0x00FFFFFF) | 0x14000000;
pll->pcr = pcrvalue;
+ while ((pll->psr & PLL_PSR_LOCK) != PLL_PSR_LOCK);
+#endif
+#endif
- cpldmode = *cpld & 0x03;
- if (cpldmode == 0) {
+ if (bootmode == 0) {
/* RCON mode */
vco = pPllmult[ccm->rcon & fbpll_mask] * CFG_INPUT_CLKSRC;
pll->pcr = pcrvalue;
}
gd->vco_clk = vco; /* Vco clock */
- } else if (cpldmode == 2) {
+ } else if (bootmode == 2) {
/* Normal mode */
- vco = pPllmult[ccm->ccr & fbpll_mask] * CFG_INPUT_CLKSRC;
+ vco = ((pll->pcr & 0xFF000000) >> 24) * CFG_INPUT_CLKSRC;
+ if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) {
+ /* Default value */
+ pcrvalue = (pll->pcr & 0x00FFFFFF);
+ pcrvalue |= pPllmult[ccm->ccr & fbpll_mask] << 24;
+ pll->pcr = pcrvalue;
+ vco = ((pll->pcr & 0xFF000000) >> 24) * CFG_INPUT_CLKSRC;
+ }
gd->vco_clk = vco; /* Vco clock */
- } else if (cpldmode == 3) {
+ } else if (bootmode == 3) {
/* serial mode */
+ vco = ((pll->pcr & 0xFF000000) >> 24) * CFG_INPUT_CLKSRC;
+ gd->vco_clk = vco; /* Vco clock */
}
-#endif /* CONFIG_M54455EVB */
if ((ccm->ccr & CCM_MISCCR_LIMP) == CCM_MISCCR_LIMP) {
/* Limp mode */
addl #60,%sp; /* space for 15 regs */ \
rte;
+#if defined(CONFIG_CF_SBF)
+#define ASM_DRAMINIT (asm_dram_init - TEXT_BASE + CFG_INIT_RAM_ADDR)
+#define ASM_SBF_IMG_HDR (asm_sbf_img_hdr - TEXT_BASE + CFG_INIT_RAM_ADDR)
+#endif
+
.text
+
/*
* Vector table. This is used for initial platform startup.
* These vectors are to catch any un-intended traps.
*/
_vectors:
+#if defined(CONFIG_CF_SBF)
+
+INITSP: .long 0 /* Initial SP */
+INITPC: .long ASM_DRAMINIT /* Initial PC */
+
+#else
+
+INITSP: .long 0 /* Initial SP */
+INITPC: .long _START /* Initial PC */
+
+#endif
-INITSP: .long 0x00000000 /* Initial SP */
-INITPC: .long _START /* Initial PC */
vector02: .long _FAULT /* Access Error */
vector03: .long _FAULT /* Address Error */
vector04: .long _FAULT /* Illegal Instruction */
vector1E: .long _FAULT /* Autovector Level 6 */
vector1F: .long _FAULT /* Autovector Level 7 */
+#if !defined(CONFIG_CF_SBF)
+
/* TRAP #0 - #15 */
vector20_2F:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
+#endif
- .text
+#if defined(CONFIG_CF_SBF)
+ /* Image header: chksum 4 bytes, len 4 bytes, img dest 4 bytes */
+asm_sbf_img_hdr:
+ .long 0x00000000 /* checksum, not yet implemented */
+ .long 0x00030000 /* image length */
+ .long TEXT_BASE /* image to be relocated at */
+
+asm_dram_init:
+ move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_RAM_CTRL), %d0
+ movec %d0, %RAMBAR1 /* init Rambar */
+ move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET), %sp
+ clr.l %sp@-
+
+ /* Must disable global address */
+ move.l #0xFC008000, %a1
+ move.l #(CFG_CS0_BASE), (%a1)
+ move.l #0xFC008008, %a1
+ move.l #(CFG_CS0_CTRL), (%a1)
+ move.l #0xFC008004, %a1
+ move.l #(CFG_CS0_MASK), (%a1)
+
+ /*
+ * Dram Initialization
+ * a1, a2, and d0
+ */
+ /* mscr sdram */
+ move.l #0xFC0A4074, %a1
+ move.b #(CFG_SDRAM_DRV_STRENGTH), (%a1)
+ nop
+
+ /* SDRAM Chip 0 and 1 */
+ move.l #0xFC0B8110, %a1
+ move.l #0xFC0B8114, %a2
+
+ /* calculate the size */
+ move.l #0x13, %d1
+ move.l #(CFG_SDRAM_SIZE), %d2
+#ifdef CFG_SDRAM_BASE1
+ lsr.l #1, %d2
+#endif
+
+dramsz_loop:
+ lsr.l #1, %d2
+ add.l #1, %d1
+ cmp.l #1, %d2
+ bne dramsz_loop
+
+ /* SDRAM Chip 0 and 1 */
+ move.l #(CFG_SDRAM_BASE), (%a1)
+ or.l %d1, (%a1)
+#ifdef CFG_SDRAM_BASE1
+ move.l #(CFG_SDRAM_BASE1), (%a2)
+ or.l %d1, (%a2)
+#endif
+ nop
+
+ /* dram cfg1 and cfg2 */
+ move.l #0xFC0B8008, %a1
+ move.l #(CFG_SDRAM_CFG1), (%a1)
+ nop
+ move.l #0xFC0B800C, %a2
+ move.l #(CFG_SDRAM_CFG2), (%a2)
+ nop
+
+ move.l #0xFC0B8000, %a1 /* Mode */
+ move.l #0xFC0B8004, %a2 /* Ctrl */
+
+#ifdef CONFIG_M54455EVB
+ /* Issue PALL */
+ move.l #(CFG_SDRAM_CTRL + 2), (%a2)
+ nop
+
+ /* Issue LEMR */
+ move.l #(CFG_SDRAM_EMOD + 0x408), (%a1)
+ nop
+ move.l #(CFG_SDRAM_MODE + 0x300), (%a1)
+ nop
+
+ move.l #1000, %d0
+wait1000:
+ nop
+ subq.l #1, %d0
+ bne wait1000
+#endif
+
+ /* Issue PALL */
+ move.l #(CFG_SDRAM_CTRL + 2), (%a2)
+ nop
+
+ /* Perform two refresh cycles */
+ move.l #(CFG_SDRAM_CTRL + 4), %d0
+ nop
+ move.l %d0, (%a2)
+ move.l %d0, (%a2)
+ nop
+#ifdef CONFIG_M54455EVB
+ move.l #(CFG_SDRAM_MODE + 0x200), (%a1)
+ nop
+#elif defined(CONFIG_M54451EVB)
+ /* Issue LEMR */
+ move.l #(CFG_SDRAM_MODE), (%a2)
+ nop
+ move.l #(CFG_SDRAM_EMOD), (%a2)
+ nop
+#endif
+
+ move.l #500, %d0
+wait500:
+ nop
+ subq.l #1, %d0
+ bne wait500
+
+ move.l #(CFG_SDRAM_CTRL), %d0
+ and.l #0x7FFFFFFF, %d0
+#ifdef CONFIG_M54455EVB
+ or.l #0x10000c00, %d0
+#elif defined(CONFIG_M54451EVB)
+ or.l #0x10000000, %d0
+#endif
+ move.l %d0, (%a2)
+ nop
+
+ /*
+ * DSPI Initialization
+ * a0 - general, sram - 0x80008000 - 32, see M54455EVB.h
+ * a1 - dspi status
+ * a2 - dtfr
+ * a3 - drfr
+ * a4 - Dst addr
+ */
+ /* Enable pins for DSPI mode - chip-selects are enabled later */
+ move.l #0xFC0A4063, %a0
+ move.b #0x7F, (%a0)
+
+ /* Configure DSPI module */
+ move.l #0xFC05C000, %a0
+ move.l #0x80FF0C00, (%a0) /* Master, clear TX/RX FIFO */
+
+ move.l #0xFC05C00C, %a0
+ move.l #0x3E000011, (%a0)
+
+ move.l #0xFC05C034, %a2 /* dtfr */
+ move.l #0xFC05C03B, %a3 /* drfr */
+
+ move.l #(ASM_SBF_IMG_HDR + 4), %a1
+ move.l (%a1)+, %d5
+ move.l (%a1), %a4
+
+ move.l #(CFG_INIT_RAM_ADDR + CFG_SBFHDR_DATA_OFFSET), %a0
+ move.l #(CFG_SBFHDR_SIZE), %d4
+
+ move.l #0xFC05C02C, %a1 /* dspi status */
+
+ /* Issue commands and address */
+ move.l #0x8002000B, %d2 /* Fast Read Cmd */
+ jsr asm_dspi_wr_status
+ jsr asm_dspi_rd_status
+
+ move.l #0x80020000, %d2 /* Address byte 2 */
+ jsr asm_dspi_wr_status
+ jsr asm_dspi_rd_status
+
+ move.l #0x80020000, %d2 /* Address byte 1 */
+ jsr asm_dspi_wr_status
+ jsr asm_dspi_rd_status
+
+ move.l #0x80020000, %d2 /* Address byte 0 */
+ jsr asm_dspi_wr_status
+ jsr asm_dspi_rd_status
+
+ move.l #0x80020000, %d2 /* Dummy Wr and Rd */
+ jsr asm_dspi_wr_status
+ jsr asm_dspi_rd_status
+
+ /* Transfer serial boot header to sram */
+asm_dspi_rd_loop1:
+ move.l #0x80020000, %d2
+ jsr asm_dspi_wr_status
+ jsr asm_dspi_rd_status
+
+ move.b %d1, (%a0) /* read, copy to dst */
+
+ add.l #1, %a0 /* inc dst by 1 */
+ sub.l #1, %d4 /* dec cnt by 1 */
+ bne asm_dspi_rd_loop1
+
+ /* Transfer u-boot from serial flash to memory */
+asm_dspi_rd_loop2:
+ move.l #0x80020000, %d2
+ jsr asm_dspi_wr_status
+ jsr asm_dspi_rd_status
+
+ move.b %d1, (%a4) /* read, copy to dst */
+
+ add.l #1, %a4 /* inc dst by 1 */
+ sub.l #1, %d5 /* dec cnt by 1 */
+ bne asm_dspi_rd_loop2
+
+ move.l #0x00020000, %d2 /* Terminate */
+ jsr asm_dspi_wr_status
+ jsr asm_dspi_rd_status
+
+ /* jump to memory and execute */
+ move.l #(TEXT_BASE + 0x400), %a0
+ jmp (%a0)
+
+asm_dspi_wr_status:
+ move.l (%a1), %d0 /* status */
+ and.l #0x0000F000, %d0
+ cmp.l #0x00003000, %d0
+ bgt asm_dspi_wr_status
+
+ move.l %d2, (%a2)
+ rts
+
+asm_dspi_rd_status:
+ move.l (%a1), %d0 /* status */
+ and.l #0x000000F0, %d0
+ lsr.l #4, %d0
+ cmp.l #0, %d0
+ beq asm_dspi_rd_status
+
+ move.b (%a3), %d1
+ rts
+#endif /* CONFIG_CF_SBF */
+
+ .text
+ . = 0x400
.globl _start
_start:
nop
move.w #0x2700,%sr /* Mask off Interrupt */
/* Set vector base register at the beginning of the Flash */
+#if defined(CONFIG_CF_SBF)
+ move.l #TEXT_BASE, %d0
+ movec %d0, %VBR
+#else
move.l #CFG_FLASH_BASE, %d0
movec %d0, %VBR
move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_RAM_CTRL), %d0
movec %d0, %RAMBAR1
+#endif
/* initialize general use internal ram */
move.l #0, %d0
LIB = $(obj)lib$(CPU).a
START = start.o
-COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o fec.o i2c.o
+COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o fec.o i2c.o iopin.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
#endif
#ifdef CONFIG_OF_LIBFDT
-void ft_cpu_setup(void *blob, bd_t *bd)
+
+#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
+/*
+ * fdt setup for old device trees
+ * fix up
+ * cpu clocks
+ * soc clocks
+ * ethernet addresses
+ */
+static void old_ft_cpu_setup(void *blob, bd_t *bd)
+{
+ /*
+ * avoid fixing up by path because that
+ * produces scary error messages
+ */
+
+ /*
+ * old device trees have ethernet nodes with
+ * device_type = "network"
+ */
+ do_fixup_by_prop(blob, "device_type", "network", 8,
+ "local-mac-address", bd->bi_enetaddr, 6, 0);
+ do_fixup_by_prop(blob, "device_type", "network", 8,
+ "address", bd->bi_enetaddr, 6, 0);
+ /*
+ * old device trees have soc nodes with
+ * device_type = "soc"
+ */
+ do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+ "bus-frequency", bd->bi_ipsfreq, 0);
+}
+#endif
+
+static void ft_clock_setup(void *blob, bd_t *bd)
{
char *cpu_path = "/cpus/" OF_CPU;
- char *eth_path = "/" OF_SOC "/ethernet@2800";
- char *eth_path_old = "/" OF_SOC_OLD "/ethernet@2800";
-
- do_fixup_by_path_u32(blob, cpu_path, "timebase-frequency", OF_TBCLK, 1);
- do_fixup_by_path_u32(blob, cpu_path, "bus-frequency", bd->bi_busfreq, 1);
- do_fixup_by_path_u32(blob, cpu_path, "clock-frequency", bd->bi_intfreq, 1);
- do_fixup_by_path_u32(blob, "/" OF_SOC, "bus-frequency", bd->bi_ipsfreq, 1);
- do_fixup_by_path(blob, eth_path, "local-mac-address", bd->bi_enetaddr, 6, 0);
-
- /* this is so old kernels with old device trees will boot */
- do_fixup_by_path_u32(blob, "/" OF_SOC_OLD, "bus-frequency", bd->bi_ipsfreq, 0);
- do_fixup_by_path(blob, eth_path_old, "local-mac-address",
- bd->bi_enetaddr, 6, 0);
- do_fixup_by_path(blob, eth_path_old, "address", bd->bi_enetaddr, 6, 0);
+
+ /*
+ * fixup cpu clocks using path
+ */
+ do_fixup_by_path_u32(blob, cpu_path,
+ "timebase-frequency", OF_TBCLK, 1);
+ do_fixup_by_path_u32(blob, cpu_path,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_path_u32(blob, cpu_path,
+ "clock-frequency", bd->bi_intfreq, 1);
+ /*
+ * fixup soc clocks using compatible
+ */
+ do_fixup_by_compat_u32(blob, OF_SOC_COMPAT,
+ "bus-frequency", bd->bi_ipsfreq, 1);
+}
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
+ old_ft_cpu_setup(blob, bd);
+#endif
+ ft_clock_setup(blob, bd);
+#ifdef CONFIG_HAS_ETH0
+ fdt_fixup_ethernet(blob, bd);
+#endif
}
#endif
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Martha J Marx, Silicon Turnkey Express, mmarx@silicontkx.com
+ * mpc512x I/O pin/pad initialization for the ADS5121 board
+ * 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 <linux/types.h>
+#include <mpc512x.h>
+
+void iopin_initialize(iopin_t *ioregs_init, int len)
+{
+ short i, j, p;
+ u_long *reg;
+ immap_t *im = (immap_t *)CFG_IMMR;
+
+ reg = (u_long *)&(im->io_ctrl.regs[0]);
+
+ if (sizeof(ioregs_init) == 0)
+ return;
+
+ for (i = 0; i < len; i++) {
+ for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long);
+ p < ioregs_init[i].nr_pins; p++, j++) {
+ if (ioregs_init[i].bit_or)
+ reg[j] |= ioregs_init[i].val;
+ else
+ reg[j] = ioregs_init[i].val;
+ }
+ }
+ return;
+}
void ft_pci_setup(void *blob, bd_t *bd)
{
do_fixup_by_prop_u32(blob, "device_type", "pci", 4,
- "clock-frequency", bd->pci_clk, 1);
+ "clock-frequency", gd->pci_clk, 1);
}
#endif
--- /dev/null
+/*
+ * Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
+ *
+ * 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 <mpc83xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+ int i;
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
+
+ /* Clear initial global data */
+ for (i = 0; i < sizeof(gd_t); i++)
+ ((char *)gd)[i] = 0;
+
+ /* system performance tweaking */
+
+#ifdef CFG_ACR_PIPE_DEP
+ /* Arbiter pipeline depth */
+ im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) |
+ (CFG_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT);
+#endif
+
+#ifdef CFG_ACR_RPTCNT
+ /* Arbiter repeat count */
+ im->arbiter.acr = (im->arbiter.acr & ~(ACR_RPTCNT)) |
+ (CFG_ACR_RPTCNT << ACR_RPTCNT_SHIFT);
+#endif
+
+#ifdef CFG_SPCR_OPT
+ /* Optimize transactions between CSB and other devices */
+ im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_OPT) |
+ (CFG_SPCR_OPT << SPCR_OPT_SHIFT);
+#endif
+
+ /* Enable Time Base & Decrimenter (so we will have udelay()) */
+ im->sysconf.spcr |= SPCR_TBEN;
+
+ /* DDR control driver register */
+#ifdef CFG_DDRCDR
+ im->sysconf.ddrcdr = CFG_DDRCDR;
+#endif
+ /* Output buffer impedance register */
+#ifdef CFG_OBIR
+ im->sysconf.obir = CFG_OBIR;
+#endif
+
+ /*
+ * Memory Controller:
+ */
+
+ /* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+ * addresses - these have to be modified later when FLASH size
+ * has been determined
+ */
+
+#if defined(CFG_NAND_BR_PRELIM) \
+ && defined(CFG_NAND_OR_PRELIM) \
+ && defined(CFG_NAND_LBLAWBAR_PRELIM) \
+ && defined(CFG_NAND_LBLAWAR_PRELIM)
+ im->lbus.bank[0].br = CFG_NAND_BR_PRELIM;
+ im->lbus.bank[0].or = CFG_NAND_OR_PRELIM;
+ im->sysconf.lblaw[0].bar = CFG_NAND_LBLAWBAR_PRELIM;
+ im->sysconf.lblaw[0].ar = CFG_NAND_LBLAWAR_PRELIM;
+#else
+#error CFG_NAND_BR_PRELIM, CFG_NAND_OR_PRELIM, CFG_NAND_LBLAWBAR_PRELIM & CFG_NAND_LBLAWAR_PRELIM must be defined
+#endif
+}
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+unsigned long get_tbclk(void)
+{
+ return (gd->bus_clk + 3L) / 4L;
+}
+
+void puts(const char *str)
+{
+ while (*str)
+ putc(*str++);
+}
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
* Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
- * Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved.
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006, 2008.
*
* See file CREDITS for list of people who contributed to this
* project.
#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
#endif
+#if !defined(CONFIG_NAND_SPL) && !defined(CFG_RAMBOOT)
+#define CFG_FLASHBOOT
+#endif
+
/*
* Set up GOT: Global Offset Table
*
*/
START_GOT
GOT_ENTRY(_GOT2_TABLE_)
- GOT_ENTRY(_FIXUP_TABLE_)
+ GOT_ENTRY(__bss_start)
+ GOT_ENTRY(_end)
+#ifndef CONFIG_NAND_SPL
+ GOT_ENTRY(_FIXUP_TABLE_)
GOT_ENTRY(_start)
GOT_ENTRY(_start_of_vectors)
GOT_ENTRY(_end_of_vectors)
GOT_ENTRY(transfer_to_handler)
-
- GOT_ENTRY(__init_end)
- GOT_ENTRY(_end)
- GOT_ENTRY(__bss_start)
+#endif
END_GOT
/*
bl init_e300_core
-#ifndef CFG_RAMBOOT
+#ifdef CFG_FLASHBOOT
/* Inflate flash location so it appears everywhere, calculate */
/* the absolute address in final location of the FLASH, jump */
#if 1 /* Remapping flash with LAW0. */
bl remap_flash_by_law0
#endif
-#endif /* CFG_RAMBOOT */
+#endif /* CFG_FLASHBOOT */
/* setup the bats */
bl setup_bats
/* run 1st part of board init code (in Flash)*/
bl board_init_f
+#ifndef CONFIG_NAND_SPL
/*
* Vector Table
*/
lwz r1,GPR1(r1)
SYNC
rfi
+#endif /* !CONFIG_NAND_SPL */
/*
* This code initialises the E300 processor core
SYNC
mtspr HID2, r3
- /* clear all BAT's */
- /*----------------------------------*/
-
- xor r0, r0, r0
- mtspr DBAT0U, r0
- mtspr DBAT0L, r0
- mtspr DBAT1U, r0
- mtspr DBAT1L, r0
- mtspr DBAT2U, r0
- mtspr DBAT2L, r0
- mtspr DBAT3U, r0
- mtspr DBAT3L, r0
- mtspr IBAT0U, r0
- mtspr IBAT0L, r0
- mtspr IBAT1U, r0
- mtspr IBAT1L, r0
- mtspr IBAT2U, r0
- mtspr IBAT2L, r0
- mtspr IBAT3U, r0
- mtspr IBAT3L, r0
- SYNC
-
- /* invalidate all tlb's
- *
- * From the 603e User Manual: "The 603e provides the ability to
- * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
- * instruction invalidates the TLB entry indexed by the EA, and
- * operates on both the instruction and data TLBs simultaneously
- * invalidating four TLB entries (both sets in each TLB). The
- * index corresponds to bits 15-19 of the EA. To invalidate all
- * entries within both TLBs, 32 tlbie instructions should be
- * issued, incrementing this field by one each time."
- *
- * "Note that the tlbia instruction is not implemented on the
- * 603e."
- *
- * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
- * incrementing by 0x1000 each time. The code below is sort of
- * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
- *
- */
-
- li r3, 32
- mtctr r3
- li r3, 0
-1: tlbie r3
- addi r3, r3, 0x1000
- bdnz 1b
- SYNC
-
/* Done! */
/*------------------------------*/
blr
- .globl invalidate_bats
-invalidate_bats:
- /* invalidate BATs */
- mtspr IBAT0U, r0
- mtspr IBAT1U, r0
- mtspr IBAT2U, r0
- mtspr IBAT3U, r0
-#ifdef CONFIG_HIGH_BATS
- mtspr IBAT4U, r0
- mtspr IBAT5U, r0
- mtspr IBAT6U, r0
- mtspr IBAT7U, r0
-#endif
- isync
- mtspr DBAT0U, r0
- mtspr DBAT1U, r0
- mtspr DBAT2U, r0
- mtspr DBAT3U, r0
-#ifdef CONFIG_HIGH_BATS
- mtspr DBAT4U, r0
- mtspr DBAT5U, r0
- mtspr DBAT6U, r0
- mtspr DBAT7U, r0
-#endif
- isync
- sync
- blr
-
/* setup_bats - set them up to some initial state */
.globl setup_bats
setup_bats:
ori r3, r3, CFG_IBAT0U@l
mtspr IBAT0L, r4
mtspr IBAT0U, r3
- isync
/* DBAT 0 */
addis r4, r0, CFG_DBAT0L@h
ori r3, r3, CFG_DBAT0U@l
mtspr DBAT0L, r4
mtspr DBAT0U, r3
- isync
/* IBAT 1 */
addis r4, r0, CFG_IBAT1L@h
ori r3, r3, CFG_IBAT1U@l
mtspr IBAT1L, r4
mtspr IBAT1U, r3
- isync
/* DBAT 1 */
addis r4, r0, CFG_DBAT1L@h
ori r3, r3, CFG_DBAT1U@l
mtspr DBAT1L, r4
mtspr DBAT1U, r3
- isync
/* IBAT 2 */
addis r4, r0, CFG_IBAT2L@h
ori r3, r3, CFG_IBAT2U@l
mtspr IBAT2L, r4
mtspr IBAT2U, r3
- isync
/* DBAT 2 */
addis r4, r0, CFG_DBAT2L@h
ori r3, r3, CFG_DBAT2U@l
mtspr DBAT2L, r4
mtspr DBAT2U, r3
- isync
/* IBAT 3 */
addis r4, r0, CFG_IBAT3L@h
ori r3, r3, CFG_IBAT3U@l
mtspr IBAT3L, r4
mtspr IBAT3U, r3
- isync
/* DBAT 3 */
addis r4, r0, CFG_DBAT3L@h
ori r3, r3, CFG_DBAT3U@l
mtspr DBAT3L, r4
mtspr DBAT3U, r3
- isync
#ifdef CONFIG_HIGH_BATS
/* IBAT 4 */
ori r3, r3, CFG_IBAT4U@l
mtspr IBAT4L, r4
mtspr IBAT4U, r3
- isync
/* DBAT 4 */
addis r4, r0, CFG_DBAT4L@h
ori r3, r3, CFG_DBAT4U@l
mtspr DBAT4L, r4
mtspr DBAT4U, r3
- isync
/* IBAT 5 */
addis r4, r0, CFG_IBAT5L@h
ori r3, r3, CFG_IBAT5U@l
mtspr IBAT5L, r4
mtspr IBAT5U, r3
- isync
/* DBAT 5 */
addis r4, r0, CFG_DBAT5L@h
ori r3, r3, CFG_DBAT5U@l
mtspr DBAT5L, r4
mtspr DBAT5U, r3
- isync
/* IBAT 6 */
addis r4, r0, CFG_IBAT6L@h
ori r3, r3, CFG_IBAT6U@l
mtspr IBAT6L, r4
mtspr IBAT6U, r3
- isync
/* DBAT 6 */
addis r4, r0, CFG_DBAT6L@h
ori r3, r3, CFG_DBAT6U@l
mtspr DBAT6L, r4
mtspr DBAT6U, r3
- isync
/* IBAT 7 */
addis r4, r0, CFG_IBAT7L@h
ori r3, r3, CFG_IBAT7U@l
mtspr IBAT7L, r4
mtspr IBAT7U, r3
- isync
/* DBAT 7 */
addis r4, r0, CFG_DBAT7L@h
ori r3, r3, CFG_DBAT7U@l
mtspr DBAT7L, r4
mtspr DBAT7U, r3
- isync
#endif
- /* Invalidate TLBs.
- * -> for (val = 0; val < 0x20000; val+=0x1000)
- * -> tlbie(val);
+ isync
+
+ /* invalidate all tlb's
+ *
+ * From the 603e User Manual: "The 603e provides the ability to
+ * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
+ * instruction invalidates the TLB entry indexed by the EA, and
+ * operates on both the instruction and data TLBs simultaneously
+ * invalidating four TLB entries (both sets in each TLB). The
+ * index corresponds to bits 15-19 of the EA. To invalidate all
+ * entries within both TLBs, 32 tlbie instructions should be
+ * issued, incrementing this field by one each time."
+ *
+ * "Note that the tlbia instruction is not implemented on the
+ * 603e."
+ *
+ * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
+ * incrementing by 0x1000 each time. The code below is sort of
+ * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
+ *
*/
lis r3, 0
lis r5, 2
mr r3, r5 /* Destination Address */
lis r4, CFG_MONITOR_BASE@h /* Source Address */
ori r4, r4, CFG_MONITOR_BASE@l
- lwz r5, GOT(__init_end)
+ lwz r5, GOT(__bss_start)
sub r5, r5, r4
li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
stw r0,0(r3)
bdnz 1b
+#ifndef CONFIG_NAND_SPL
/*
* Now adjust the fixups and the pointers to the fixups
* in case we need to move ourselves again.
stw r0,0(r4)
bdnz 3b
4:
+#endif
+
clear_bss:
/*
* Now clear BSS segment
mr r4, r10 /* Destination Address */
bl board_init_r
+#ifndef CONFIG_NAND_SPL
/*
* Copy exception vector code to low memory
*
stw r0, 4(r7)
blr
+#endif /* !CONFIG_NAND_SPL */
#ifdef CFG_INIT_RAM_LOCK
lock_ram_in_cache:
sync
blr
+#ifndef CONFIG_NAND_SPL
.globl unlock_ram_in_cache
unlock_ram_in_cache:
/* invalidate the INIT_RAM section */
mtspr HID0, r3 /* no invalidate, unlock */
sync
blr
-#endif
+#endif /* !CONFIG_NAND_SPL */
+#endif /* CFG_INIT_RAM_LOCK */
+#ifdef CFG_FLASHBOOT
map_flash_by_law1:
/* When booting from ROM (Flash or EPROM), clear the */
/* Address Mask in OR0 so ROM appears everywhere */
stw r4, LBLAWBAR1(r3)
stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
blr
+#endif /* CFG_FLASHBOOT */
out_be32(&gur->devdisr, devdisr);
/* release the hounds */
- up = ((1 << CONFIG_NR_CPUS) - 1);
+ up = ((1 << CONFIG_NUM_CPUS) - 1);
bpcr = in_be32(&ecm->eebpcr);
bpcr |= (up << 24);
out_be32(&ecm->eebpcr, bpcr);
/* wait for everyone */
while (timeout) {
int i;
- for (i = 0; i < CONFIG_NR_CPUS; i++) {
+ for (i = 0; i < CONFIG_NUM_CPUS; i++) {
if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
cpu_up_mask |= (1 << i);
};
.align L1_CACHE_SHIFT
.globl __spin_table
__spin_table:
- .space CONFIG_NR_CPUS*ENTRY_SIZE
+ .space CONFIG_NUM_CPUS*ENTRY_SIZE
/* Fill in the empty space. The actual reset vector is
* the last word of the page */
* Disable L1 Instruction cache
*/
_GLOBAL(icache_disable)
+ mflr r4
+ bl invalidate_l1_instruction_cache /* uses r3 */
+ sync
+ mtlr r4
mfspr r3, HID0
li r5, 0
ori r5, r5, HID0_ICE
* cpu_init.c - low level cpu init
*/
+#include <config.h>
#include <common.h>
#include <mpc86xx.h>
+#include <asm/mmu.h>
#include <asm/fsl_law.h>
DECLARE_GLOBAL_DATA_PTR;
{
return 0;
}
+
+/* Set up BAT registers */
+void setup_bats(void)
+{
+ write_bat(DBAT0, CFG_DBAT0U, CFG_DBAT0L);
+ write_bat(IBAT0, CFG_IBAT0U, CFG_IBAT0L);
+ write_bat(DBAT1, CFG_DBAT1U, CFG_DBAT1L);
+ write_bat(IBAT1, CFG_IBAT1U, CFG_IBAT1L);
+ write_bat(DBAT2, CFG_DBAT2U, CFG_DBAT2L);
+ write_bat(IBAT2, CFG_IBAT2U, CFG_IBAT2L);
+ write_bat(DBAT3, CFG_DBAT3U, CFG_DBAT3L);
+ write_bat(IBAT3, CFG_IBAT3U, CFG_IBAT3L);
+ write_bat(DBAT4, CFG_DBAT4U, CFG_DBAT4L);
+ write_bat(IBAT4, CFG_IBAT4U, CFG_IBAT4L);
+ write_bat(DBAT5, CFG_DBAT5U, CFG_DBAT5L);
+ write_bat(IBAT5, CFG_IBAT5U, CFG_IBAT5L);
+ write_bat(DBAT6, CFG_DBAT6U, CFG_DBAT6L);
+ write_bat(IBAT6, CFG_IBAT6U, CFG_IBAT6L);
+ write_bat(DBAT7, CFG_DBAT7U, CFG_DBAT7L);
+ write_bat(IBAT7, CFG_IBAT7U, CFG_IBAT7L);
+
+ return;
+}
sync
blr
-
- /* setup_bats - set them up to some initial state */
- /* Skip any BATS setup in early_bats */
- .globl setup_bats
-setup_bats:
-
- addis r0, r0, 0x0000
-
- /* IBAT 0 */
- addis r4, r0, CFG_IBAT0L@h
- ori r4, r4, CFG_IBAT0L@l
- addis r3, r0, CFG_IBAT0U@h
- ori r3, r3, CFG_IBAT0U@l
- mtspr IBAT0L, r4
- mtspr IBAT0U, r3
- isync
-
- /* DBAT 0 */
- addis r4, r0, CFG_DBAT0L@h
- ori r4, r4, CFG_DBAT0L@l
- addis r3, r0, CFG_DBAT0U@h
- ori r3, r3, CFG_DBAT0U@l
- mtspr DBAT0L, r4
- mtspr DBAT0U, r3
- isync
-
- /* IBAT 1 */
- addis r4, r0, CFG_IBAT1L@h
- ori r4, r4, CFG_IBAT1L@l
- addis r3, r0, CFG_IBAT1U@h
- ori r3, r3, CFG_IBAT1U@l
- mtspr IBAT1L, r4
- mtspr IBAT1U, r3
- isync
-
- /* DBAT 1 */
- addis r4, r0, CFG_DBAT1L@h
- ori r4, r4, CFG_DBAT1L@l
- addis r3, r0, CFG_DBAT1U@h
- ori r3, r3, CFG_DBAT1U@l
- mtspr DBAT1L, r4
- mtspr DBAT1U, r3
- isync
-
- /* IBAT 2 */
- addis r4, r0, CFG_IBAT2L@h
- ori r4, r4, CFG_IBAT2L@l
- addis r3, r0, CFG_IBAT2U@h
- ori r3, r3, CFG_IBAT2U@l
- mtspr IBAT2L, r4
- mtspr IBAT2U, r3
- isync
-
- /* DBAT 2 */
- addis r4, r0, CFG_DBAT2L@h
- ori r4, r4, CFG_DBAT2L@l
- addis r3, r0, CFG_DBAT2U@h
- ori r3, r3, CFG_DBAT2U@l
- mtspr DBAT2L, r4
- mtspr DBAT2U, r3
- isync
-
- /* IBAT 3 */
- addis r4, r0, CFG_IBAT3L@h
- ori r4, r4, CFG_IBAT3L@l
- addis r3, r0, CFG_IBAT3U@h
- ori r3, r3, CFG_IBAT3U@l
- mtspr IBAT3L, r4
- mtspr IBAT3U, r3
- isync
-
- /* DBAT 3 */
- addis r4, r0, CFG_DBAT3L@h
- ori r4, r4, CFG_DBAT3L@l
- addis r3, r0, CFG_DBAT3U@h
- ori r3, r3, CFG_DBAT3U@l
- mtspr DBAT3L, r4
- mtspr DBAT3U, r3
- isync
-
- /* IBAT 4 */
- addis r4, r0, CFG_IBAT4L@h
- ori r4, r4, CFG_IBAT4L@l
- addis r3, r0, CFG_IBAT4U@h
- ori r3, r3, CFG_IBAT4U@l
- mtspr IBAT4L, r4
- mtspr IBAT4U, r3
- isync
-
- /* DBAT 4 */
- addis r4, r0, CFG_DBAT4L@h
- ori r4, r4, CFG_DBAT4L@l
- addis r3, r0, CFG_DBAT4U@h
- ori r3, r3, CFG_DBAT4U@l
- mtspr DBAT4L, r4
- mtspr DBAT4U, r3
- isync
-
- /* IBAT 7 */
- addis r4, r0, CFG_IBAT7L@h
- ori r4, r4, CFG_IBAT7L@l
- addis r3, r0, CFG_IBAT7U@h
- ori r3, r3, CFG_IBAT7U@l
- mtspr IBAT7L, r4
- mtspr IBAT7U, r3
- isync
-
- /* DBAT 7 */
- addis r4, r0, CFG_DBAT7L@h
- ori r4, r4, CFG_DBAT7L@l
- addis r3, r0, CFG_DBAT7U@h
- ori r3, r3, CFG_DBAT7U@l
- mtspr DBAT7L, r4
- mtspr DBAT7U, r3
- isync
-
- sync
- blr
-
/*
* early_bats:
*
#include "ecc.h"
-#if defined(CONFIG_SPD_EEPROM) && \
- (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT))
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+
+#define PPC4xx_IBM_DDR2_DUMP_REGISTER(mnemonic) \
+ do { \
+ u32 data; \
+ mfsdram(SDRAM_##mnemonic, data); \
+ printf("%20s[%02x] = 0x%08X\n", \
+ "SDRAM_" #mnemonic, SDRAM_##mnemonic, data); \
+ } while (0)
+
+static inline void ppc4xx_ibm_ddr2_register_dump(void);
+
+#if defined(CONFIG_SPD_EEPROM)
/*-----------------------------------------------------------------------------+
* Defines
#else
static void DQS_calibration_process(void);
#endif
-static void ppc440sp_sdram_register_dump(void);
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
void dcbz_area(u32 start_address, u32 num_bytes);
remove_tlb(0, dram_size);
program_tlb(0, 0, dram_size, MY_TLB_WORD2_I_ENABLE);
- ppc440sp_sdram_register_dump();
+ ppc4xx_ibm_ddr2_register_dump();
/*
* Clear potential errors resulting from auto-calibration.
printf("\nERROR: Cannot determine a common read delay for the "
"DIMM(s) installed.\n");
debug("%s[%d] ERROR : \n", __FUNCTION__,__LINE__);
- ppc440sp_sdram_register_dump();
+ ppc4xx_ibm_ddr2_register_dump();
spd_ddr_init_hang ();
}
}
#endif
-#if defined(DEBUG)
-static void ppc440sp_sdram_register_dump(void)
-{
- unsigned int sdram_reg;
- unsigned int sdram_data;
- unsigned int dcr_data;
-
- printf("\n Register Dump:\n");
- sdram_reg = SDRAM_MCSTAT;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MCSTAT = 0x%08X", sdram_data);
- sdram_reg = SDRAM_MCOPT1;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MCOPT1 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_MCOPT2;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MCOPT2 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_MODT0;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MODT0 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_MODT1;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MODT1 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_MODT2;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MODT2 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_MODT3;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MODT3 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_CODT;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_CODT = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_VVPR;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_VVPR = 0x%08X", sdram_data);
- sdram_reg = SDRAM_OPARS;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_OPARS = 0x%08X\n", sdram_data);
- /*
- * OPAR2 is only used as a trigger register.
- * No data is contained in this register, and reading or writing
- * to is can cause bad things to happen (hangs). Just skip it
- * and report NA
- * sdram_reg = SDRAM_OPAR2;
- * mfsdram(sdram_reg, sdram_data);
- * printf(" SDRAM_OPAR2 = 0x%08X\n", sdram_data);
- */
- printf(" SDRAM_OPART = N/A ");
- sdram_reg = SDRAM_RTR;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_RTR = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_MB0CF;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MB0CF = 0x%08X", sdram_data);
- sdram_reg = SDRAM_MB1CF;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MB1CF = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_MB2CF;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MB2CF = 0x%08X", sdram_data);
- sdram_reg = SDRAM_MB3CF;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MB3CF = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_INITPLR0;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR0 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_INITPLR1;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR1 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_INITPLR2;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR2 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_INITPLR3;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR3 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_INITPLR4;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR4 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_INITPLR5;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR5 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_INITPLR6;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR6 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_INITPLR7;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR7 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_INITPLR8;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR8 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_INITPLR9;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR9 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_INITPLR10;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR10 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_INITPLR11;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR11 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_INITPLR12;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR12 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_INITPLR13;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR13 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_INITPLR14;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR14 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_INITPLR15;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_INITPLR15 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_RQDC;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_RQDC = 0x%08X", sdram_data);
- sdram_reg = SDRAM_RFDC;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_RFDC = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_RDCC;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_RDCC = 0x%08X", sdram_data);
- sdram_reg = SDRAM_DLCR;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_DLCR = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_CLKTR;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_CLKTR = 0x%08X", sdram_data);
- sdram_reg = SDRAM_WRDTR;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_WRDTR = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_SDTR1;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_SDTR1 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_SDTR2;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_SDTR2 = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_SDTR3;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_SDTR3 = 0x%08X", sdram_data);
- sdram_reg = SDRAM_MMODE;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MMODE = 0x%08X\n", sdram_data);
- sdram_reg = SDRAM_MEMODE;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_MEMODE = 0x%08X", sdram_data);
- sdram_reg = SDRAM_ECCCR;
- mfsdram(sdram_reg, sdram_data);
- printf(" SDRAM_ECCCR = 0x%08X\n\n", sdram_data);
-
- dcr_data = mfdcr(SDRAM_R0BAS);
- printf(" MQ0_B0BAS = 0x%08X", dcr_data);
- dcr_data = mfdcr(SDRAM_R1BAS);
- printf(" MQ1_B0BAS = 0x%08X\n", dcr_data);
- dcr_data = mfdcr(SDRAM_R2BAS);
- printf(" MQ2_B0BAS = 0x%08X", dcr_data);
- dcr_data = mfdcr(SDRAM_R3BAS);
- printf(" MQ3_B0BAS = 0x%08X\n", dcr_data);
-}
-#else /* !defined(DEBUG) */
-static void ppc440sp_sdram_register_dump(void)
-{
-}
-#endif /* defined(DEBUG) */
-#elif defined(CONFIG_405EX)
+#else /* CONFIG_SPD_EEPROM */
+
/*-----------------------------------------------------------------------------
* Function: initdram
* Description: Configures the PPC405EX(r) DDR1/DDR2 SDRAM memory
#if defined(CONFIG_DDR_ECC)
ecc_init(CFG_SDRAM_BASE, CFG_MBYTES_SDRAM << 20);
#endif /* defined(CONFIG_DDR_ECC) */
+
+ ppc4xx_ibm_ddr2_register_dump();
#endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
return (CFG_MBYTES_SDRAM << 20);
}
-#endif /* defined(CONFIG_SPD_EEPROM) && defined(CONFIG_440SP) || ... */
+#endif /* CONFIG_SPD_EEPROM */
+
+static inline void ppc4xx_ibm_ddr2_register_dump(void)
+{
+#if defined(DEBUG)
+ printf("\nPPC4xx IBM DDR2 Register Dump:\n");
+
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(R0BAS);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(R1BAS);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(R2BAS);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(R3BAS);
+#endif /* (defined(CONFIG_440SP) || ... */
+#if defined(CONFIG_405EX)
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(BESR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(BEARL);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(BEARH);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(WMIRQ);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(PLBOPT);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(PUABA);
+#endif /* defined(CONFIG_405EX) */
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MB0CF);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MB1CF);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MB2CF);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MB3CF);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MCSTAT);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MCOPT1);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MCOPT2);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT0);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT1);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT2);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT3);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(CODT);
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(VVPR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(OPARS);
+ /*
+ * OPART is only used as a trigger register.
+ *
+ * No data is contained in this register, and reading or writing
+ * to is can cause bad things to happen (hangs). Just skip it and
+ * report "N/A".
+ */
+ printf("%20s = N/A\n", "SDRAM_OPART");
+#endif /* defined(CONFIG_440SP) || ... */
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RTR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR0);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR1);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR2);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR3);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR4);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR5);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR6);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR7);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR8);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR9);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR10);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR11);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR12);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR13);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR14);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR15);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RQDC);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RFDC);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RDCC);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(DLCR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(CLKTR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(WRDTR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR1);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR2);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR3);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MMODE);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MEMODE);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(ECCCR);
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(CID);
+#endif /* defined(CONFIG_440SP) || ... */
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RID);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(FCSR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RTSR);
+#endif /* defined(DEBUG) */
+}
+
+#endif /* CONFIG_SDRAM_PPC4xx_IBM_DDR2 */
#include <405_mal.h>
#include <miiphy.h>
#include <malloc.h>
-#include <asm/ppc4xx-intvec.h>
/*
* Only compile for platform with AMCC EMAC ethernet controller and
* Defines for MAL/EMAC interrupt conditions as reported in the UIC (Universal
* Interrupt Controller).
*-----------------------------------------------------------------------------*/
-#define MAL_UIC_ERR ( UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)
-#define MAL_UIC_DEF (UIC_MAL_RXEOB | MAL_UIC_ERR)
-#define EMAC_UIC_DEF UIC_ENET
-#define EMAC_UIC_DEF1 UIC_ENET1
-#define SEL_UIC_DEF(p) (p ? UIC_ENET1 : UIC_ENET )
+#define ETH_IRQ_NUM(dev) (VECNUM_ETH0 + ((dev) * VECNUM_ETH1_OFFS))
+
+#if defined(CONFIG_HAS_ETH3)
+#if !defined(CONFIG_440GX)
+#define UIC_ETHx (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)) || \
+ UIC_MASK(ETH_IRQ_NUM(2)) || UIC_MASK(ETH_IRQ_NUM(3)))
+#else
+/* Unfortunately 440GX spreads EMAC interrupts on multiple UIC's */
+#define UIC_ETHx (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)))
+#define UIC_ETHxB (UIC_MASK(ETH_IRQ_NUM(2)) || UIC_MASK(ETH_IRQ_NUM(3)))
+#endif /* !defined(CONFIG_440GX) */
+#elif defined(CONFIG_HAS_ETH2)
+#define UIC_ETHx (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)) || \
+ UIC_MASK(ETH_IRQ_NUM(2)))
+#elif defined(CONFIG_HAS_ETH1)
+#define UIC_ETHx (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)))
+#else
+#define UIC_ETHx UIC_MASK(ETH_IRQ_NUM(0))
+#endif
+
+/*
+ * Define a default version for UIC_ETHxB for non 440GX so that we can
+ * use common code for all 4xx variants
+ */
+#if !defined(UIC_ETHxB)
+#define UIC_ETHxB 0
+#endif
+
+#define UIC_MAL_SERR UIC_MASK(VECNUM_MAL_SERR)
+#define UIC_MAL_TXDE UIC_MASK(VECNUM_MAL_TXDE)
+#define UIC_MAL_RXDE UIC_MASK(VECNUM_MAL_RXDE)
+#define UIC_MAL_TXEOB UIC_MASK(VECNUM_MAL_TXEOB)
+#define UIC_MAL_RXEOB UIC_MASK(VECNUM_MAL_RXEOB)
+
+#define MAL_UIC_ERR (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)
+#define MAL_UIC_DEF (UIC_MAL_RXEOB | MAL_UIC_ERR)
+
+/*
+ * We have 3 different interrupt types:
+ * - MAL interrupts indicating successful transfer
+ * - MAL error interrupts indicating MAL related errors
+ * - EMAC interrupts indicating EMAC related errors
+ *
+ * All those interrupts can be on different UIC's, but since
+ * now at least all interrupts from one type are on the same
+ * UIC. Only exception is 440GX where the EMAC interrupts are
+ * spread over two UIC's!
+ */
+#if defined(CONFIG_440GX)
+#define UIC_BASE_MAL UIC1_DCR_BASE
+#define UIC_BASE_MAL_ERR UIC2_DCR_BASE
+#define UIC_BASE_EMAC UIC2_DCR_BASE
+#define UIC_BASE_EMAC_B UIC3_DCR_BASE
+#else
+#define UIC_BASE_MAL (UIC0_DCR_BASE + (UIC_NR(VECNUM_MAL_TXEOB) * 0x10))
+#define UIC_BASE_MAL_ERR (UIC0_DCR_BASE + (UIC_NR(VECNUM_MAL_SERR) * 0x10))
+#define UIC_BASE_EMAC (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(0)) * 0x10))
+#define UIC_BASE_EMAC_B (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(0)) * 0x10))
+#endif
#undef INFO_4XX_ENET
/*-----------------------------------------------------------------------------+
* Global variables. TX and RX descriptors and buffers.
*-----------------------------------------------------------------------------*/
-/* IER globals */
-static uint32_t mal_ier;
-
#if !defined(CONFIG_NET_MULTI)
struct eth_device *emac0_dev = NULL;
#endif
#define CONFIG_EMAC_NR_START 0
#endif
-#if defined(CONFIG_405EX) || defined(CONFIG_440EPX)
-#define ETH_IRQ_NUM(dev) (VECNUM_ETH0 + ((dev)))
-#else
-#define ETH_IRQ_NUM(dev) (VECNUM_ETH0 + ((dev) * 2))
-#endif
-
#define MAL_RX_DESC_SIZE 2048
#define MAL_TX_DESC_SIZE 2048
#define MAL_ALLOC_SIZE (MAL_TX_DESC_SIZE + MAL_RX_DESC_SIZE)
#if defined(CONFIG_405EX)
int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
{
- u32 gmiifer = 0;
+ u32 rgmiifer = 0;
/*
- * Right now only 2*RGMII is supported. Please extend when needed.
- * sr - 2007-09-19
+ * The 405EX(r)'s RGMII bridge can operate in one of several
+ * modes, only one of which (2 x RGMII) allows the
+ * simultaneous use of both EMACs on the 405EX.
*/
- switch (1) {
- case 1:
+
+ switch (CONFIG_EMAC_PHY_MODE) {
+
+ case EMAC_PHY_MODE_NONE:
+ /* No ports */
+ rgmiifer |= RGMII_FER_DIS << 0;
+ rgmiifer |= RGMII_FER_DIS << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ break;
+ case EMAC_PHY_MODE_NONE_RGMII:
+ /* 1 x RGMII port on channel 0 */
+ rgmiifer |= RGMII_FER_RGMII << 0;
+ rgmiifer |= RGMII_FER_DIS << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ break;
+ case EMAC_PHY_MODE_RGMII_NONE:
+ /* 1 x RGMII port on channel 1 */
+ rgmiifer |= RGMII_FER_DIS << 0;
+ rgmiifer |= RGMII_FER_RGMII << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+ break;
+ case EMAC_PHY_MODE_RGMII_RGMII:
/* 2 x RGMII ports */
- out_be32((void *)RGMII_FER, 0x00000055);
+ rgmiifer |= RGMII_FER_RGMII << 0;
+ rgmiifer |= RGMII_FER_RGMII << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
bis->bi_phymode[0] = BI_PHYMODE_RGMII;
bis->bi_phymode[1] = BI_PHYMODE_RGMII;
break;
- case 2:
- /* 2 x SMII ports */
+ case EMAC_PHY_MODE_NONE_GMII:
+ /* 1 x GMII port on channel 0 */
+ rgmiifer |= RGMII_FER_GMII << 0;
+ rgmiifer |= RGMII_FER_DIS << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_GMII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ break;
+ case EMAC_PHY_MODE_NONE_MII:
+ /* 1 x MII port on channel 0 */
+ rgmiifer |= RGMII_FER_MII << 0;
+ rgmiifer |= RGMII_FER_DIS << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_MII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ break;
+ case EMAC_PHY_MODE_GMII_NONE:
+ /* 1 x GMII port on channel 1 */
+ rgmiifer |= RGMII_FER_DIS << 0;
+ rgmiifer |= RGMII_FER_GMII << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_GMII;
+ break;
+ case EMAC_PHY_MODE_MII_NONE:
+ /* 1 x MII port on channel 1 */
+ rgmiifer |= RGMII_FER_DIS << 0;
+ rgmiifer |= RGMII_FER_MII << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_MII;
break;
default:
break;
}
/* Ensure we setup mdio for this devnum and ONLY this devnum */
- gmiifer = in_be32((void *)RGMII_FER);
- gmiifer |= (1 << (19-devnum));
- out_be32((void *)RGMII_FER, gmiifer);
+ rgmiifer = in_be32((void *)RGMII_FER);
+ rgmiifer |= (1 << (19-devnum));
+ out_be32((void *)RGMII_FER, rgmiifer);
return ((int)0x0);
}
}
}
-
-#if defined (CONFIG_440) || defined(CONFIG_405EX)
-
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
-/*
- * Hack: On 440SP all enet irq sources are located on UIC1
- * Needs some cleanup. --sr
- */
-#define UIC0MSR uic1msr
-#define UIC0SR uic1sr
-#define UIC1MSR uic1msr
-#define UIC1SR uic1sr
-#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
-/*
- * Hack: On 460EX/GT all enet irq sources are located on UIC2
- * Needs some cleanup. --ag
- */
-#define UIC0MSR uic2msr
-#define UIC0SR uic2sr
-#define UIC1MSR uic2msr
-#define UIC1SR uic2sr
-#else
-#define UIC0MSR uic0msr
-#define UIC0SR uic0sr
-#define UIC1MSR uic1msr
-#define UIC1SR uic1sr
-#endif
-
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
-#define UICMSR_ETHX uic0msr
-#define UICSR_ETHX uic0sr
-#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
-#define UICMSR_ETHX uic2msr
-#define UICSR_ETHX uic2sr
-#else
-#define UICMSR_ETHX uic1msr
-#define UICSR_ETHX uic1sr
-#endif
-
int enetInt (struct eth_device *dev)
{
int serviced;
int rc = -1; /* default to not us */
- unsigned long mal_isr;
- unsigned long emac_isr = 0;
- unsigned long mal_rx_eob;
- unsigned long my_uic0msr, my_uic1msr;
- unsigned long my_uicmsr_ethx;
-
-#if defined(CONFIG_440GX)
- unsigned long my_uic2msr;
-#endif
+ u32 mal_isr;
+ u32 emac_isr = 0;
+ u32 mal_eob;
+ u32 uic_mal;
+ u32 uic_mal_err;
+ u32 uic_emac;
+ u32 uic_emac_b;
EMAC_4XX_HW_PST hw_p;
/*
do {
serviced = 0;
- my_uic0msr = mfdcr (UIC0MSR);
- my_uic1msr = mfdcr (UIC1MSR);
-#if defined(CONFIG_440GX)
- my_uic2msr = mfdcr (uic2msr);
-#endif
- my_uicmsr_ethx = mfdcr (UICMSR_ETHX);
+ uic_mal = mfdcr(UIC_BASE_MAL + UIC_MSR);
+ uic_mal_err = mfdcr(UIC_BASE_MAL_ERR + UIC_MSR);
+ uic_emac = mfdcr(UIC_BASE_EMAC + UIC_MSR);
+ uic_emac_b = mfdcr(UIC_BASE_EMAC_B + UIC_MSR);
- if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
- && !(my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))
- && !(my_uicmsr_ethx & (UIC_ETH0 | UIC_ETH1))) {
- /* not for us */
- return (rc);
- }
-#if defined (CONFIG_440GX)
- if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
- && !(my_uic2msr & (UIC_ETH2 | UIC_ETH3))) {
+ if (!(uic_mal & (UIC_MAL_RXEOB | UIC_MAL_TXEOB))
+ && !(uic_mal_err & (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE))
+ && !(uic_emac & UIC_ETHx) && !(uic_emac_b & UIC_ETHxB)) {
/* not for us */
return (rc);
}
-#endif
+
/* get and clear controller status interrupts */
- /* look at Mal and EMAC interrupts */
- if ((my_uic0msr & (UIC_MRE | UIC_MTE))
- || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
- /* we have a MAL interrupt */
- mal_isr = mfdcr (malesr);
- /* look for mal error */
- if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) {
- mal_err (dev, mal_isr, my_uic1msr, MAL_UIC_DEF, MAL_UIC_ERR);
- serviced = 1;
- rc = 0;
- }
- }
+ /* look at MAL and EMAC error interrupts */
+ if (uic_mal_err & (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)) {
+ /* we have a MAL error interrupt */
+ mal_isr = mfdcr(malesr);
+ mal_err(dev, mal_isr, uic_mal_err,
+ MAL_UIC_DEF, MAL_UIC_ERR);
- /* port by port dispatch of emac interrupts */
- if (hw_p->devnum == 0) {
- if (UIC_ETH0 & my_uicmsr_ethx) { /* look for EMAC errors */
- emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
- if ((hw_p->emac_ier & emac_isr) != 0) {
- emac_err (dev, emac_isr);
- serviced = 1;
- rc = 0;
- }
- }
- if ((hw_p->emac_ier & emac_isr)
- || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
- mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */
- mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
- mtdcr (UICSR_ETHX, UIC_ETH0); /* Clear */
- return (rc); /* we had errors so get out */
- }
- }
+ /* clear MAL error interrupt status bits */
+ mtdcr(UIC_BASE_MAL_ERR + UIC_SR,
+ UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE);
-#if !defined(CONFIG_440SP)
- if (hw_p->devnum == 1) {
- if (UIC_ETH1 & my_uicmsr_ethx) { /* look for EMAC errors */
- emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
- if ((hw_p->emac_ier & emac_isr) != 0) {
- emac_err (dev, emac_isr);
- serviced = 1;
- rc = 0;
- }
- }
- if ((hw_p->emac_ier & emac_isr)
- || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
- mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */
- mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
- mtdcr (UICSR_ETHX, UIC_ETH1); /* Clear */
- return (rc); /* we had errors so get out */
- }
- }
-#if defined (CONFIG_440GX)
- if (hw_p->devnum == 2) {
- if (UIC_ETH2 & my_uic2msr) { /* look for EMAC errors */
- emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
- if ((hw_p->emac_ier & emac_isr) != 0) {
- emac_err (dev, emac_isr);
- serviced = 1;
- rc = 0;
- }
- }
- if ((hw_p->emac_ier & emac_isr)
- || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
- mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */
- mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
- mtdcr (uic2sr, UIC_ETH2);
- return (rc); /* we had errors so get out */
- }
+ return -1;
}
- if (hw_p->devnum == 3) {
- if (UIC_ETH3 & my_uic2msr) { /* look for EMAC errors */
- emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
- if ((hw_p->emac_ier & emac_isr) != 0) {
- emac_err (dev, emac_isr);
- serviced = 1;
- rc = 0;
- }
- }
- if ((hw_p->emac_ier & emac_isr)
- || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
- mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */
- mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
- mtdcr (uic2sr, UIC_ETH3);
- return (rc); /* we had errors so get out */
- }
- }
-#endif /* CONFIG_440GX */
-#endif /* !CONFIG_440SP */
+ /* look for EMAC errors */
+ if ((uic_emac & UIC_ETHx) || (uic_emac_b & UIC_ETHxB)) {
+ emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
+ emac_err(dev, emac_isr);
- /* handle MAX TX EOB interrupt from a tx */
- if (my_uic0msr & UIC_MTE) {
- mal_rx_eob = mfdcr (maltxeobisr);
- mtdcr (maltxeobisr, mal_rx_eob);
- mtdcr (UIC0SR, UIC_MTE);
- }
- /* handle MAL RX EOB interupt from a receive */
- /* check for EOB on valid channels */
- if (my_uic0msr & UIC_MRE) {
- mal_rx_eob = mfdcr (malrxeobisr);
- if ((mal_rx_eob &
- (0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)))
- != 0) { /* call emac routine for channel x */
- /* clear EOB
- mtdcr(malrxeobisr, mal_rx_eob); */
- enet_rcv (dev, emac_isr);
- /* indicate that we serviced an interrupt */
- serviced = 1;
- rc = 0;
- }
- }
+ /* clear EMAC error interrupt status bits */
+ mtdcr(UIC_BASE_EMAC + UIC_SR, UIC_ETHx);
+ mtdcr(UIC_BASE_EMAC_B + UIC_SR, UIC_ETHxB);
- mtdcr (UIC0SR, UIC_MRE); /* Clear */
- mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
- switch (hw_p->devnum) {
- case 0:
- mtdcr (UICSR_ETHX, UIC_ETH0);
- break;
- case 1:
- mtdcr (UICSR_ETHX, UIC_ETH1);
- break;
-#if defined (CONFIG_440GX)
- case 2:
- mtdcr (uic2sr, UIC_ETH2);
- break;
- case 3:
- mtdcr (uic2sr, UIC_ETH3);
- break;
-#endif /* CONFIG_440GX */
- default:
- break;
+ return -1;
}
- } while (serviced);
-
- return (rc);
-}
-
-#else /* CONFIG_440 */
-
-int enetInt (struct eth_device *dev)
-{
- int serviced;
- int rc = -1; /* default to not us */
- unsigned long mal_isr;
- unsigned long emac_isr = 0;
- unsigned long mal_rx_eob;
- unsigned long my_uicmsr;
-
- EMAC_4XX_HW_PST hw_p;
-
- /*
- * Because the mal is generic, we need to get the current
- * eth device
- */
-#if defined(CONFIG_NET_MULTI)
- dev = eth_get_dev();
-#else
- dev = emac0_dev;
-#endif
-
- hw_p = dev->priv;
-
- /* enter loop that stays in interrupt code until nothing to service */
- do {
- serviced = 0;
- my_uicmsr = mfdcr (uicmsr);
-
- if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0) { /* not for us */
- return (rc);
- }
- /* get and clear controller status interrupts */
- /* look at Mal and EMAC interrupts */
- if ((MAL_UIC_DEF & my_uicmsr) != 0) { /* we have a MAL interrupt */
- mal_isr = mfdcr (malesr);
- /* look for mal error */
- if ((my_uicmsr & MAL_UIC_ERR) != 0) {
- mal_err (dev, mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR);
- serviced = 1;
- rc = 0;
- }
+ /* handle MAX TX EOB interrupt from a tx */
+ if (uic_mal & UIC_MAL_TXEOB) {
+ /* clear MAL interrupt status bits */
+ mal_eob = mfdcr(maltxeobisr);
+ mtdcr(maltxeobisr, mal_eob);
+ mtdcr(UIC_BASE_MAL + UIC_SR, UIC_MAL_TXEOB);
+
+ /* indicate that we serviced an interrupt */
+ serviced = 1;
+ rc = 0;
}
- /* port by port dispatch of emac interrupts */
+ /* handle MAL RX EOB interupt from a receive */
+ /* check for EOB on valid channels */
+ if (uic_mal & UIC_MAL_RXEOB) {
+ mal_eob = mfdcr(malrxeobisr);
+ if (mal_eob &
+ (0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL))) {
+ /* push packet to upper layer */
+ enet_rcv(dev, emac_isr);
- if ((SEL_UIC_DEF(hw_p->devnum) & my_uicmsr) != 0) { /* look for EMAC errors */
- emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
- if ((hw_p->emac_ier & emac_isr) != 0) {
- emac_err (dev, emac_isr);
- serviced = 1;
- rc = 0;
- }
- }
- if (((hw_p->emac_ier & emac_isr) != 0) || ((MAL_UIC_ERR & my_uicmsr) != 0)) {
- mtdcr (uicsr, MAL_UIC_DEF | SEL_UIC_DEF(hw_p->devnum)); /* Clear */
- return (rc); /* we had errors so get out */
- }
+ /* clear MAL interrupt status bits */
+ mtdcr(UIC_BASE_MAL + UIC_SR, UIC_MAL_RXEOB);
- /* handle MAX TX EOB interrupt from a tx */
- if (my_uicmsr & UIC_MAL_TXEOB) {
- mal_rx_eob = mfdcr (maltxeobisr);
- mtdcr (maltxeobisr, mal_rx_eob);
- mtdcr (uicsr, UIC_MAL_TXEOB);
- }
- /* handle MAL RX EOB interupt from a receive */
- /* check for EOB on valid channels */
- if (my_uicmsr & UIC_MAL_RXEOB)
- {
- mal_rx_eob = mfdcr (malrxeobisr);
- if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
- /* clear EOB
- mtdcr(malrxeobisr, mal_rx_eob); */
- enet_rcv (dev, emac_isr);
/* indicate that we serviced an interrupt */
serviced = 1;
rc = 0;
}
}
- mtdcr (uicsr, MAL_UIC_DEF|EMAC_UIC_DEF|EMAC_UIC_DEF1); /* Clear */
-#if defined(CONFIG_405EZ)
- mtsdr (sdricintstat, SDR_ICRX_STAT | SDR_ICTX0_STAT | SDR_ICTX1_STAT);
-#endif /* defined(CONFIG_405EZ) */
- }
- while (serviced);
+ } while (serviced);
return (rc);
}
-#endif /* CONFIG_440 */
-
/*-----------------------------------------------------------------------------+
* MAL Error Routine
*-----------------------------------------------------------------------------*/
EMAC_4XX_HW_PST hw = NULL;
u8 ethaddr[4 + CONFIG_EMAC_NR_START][6];
u32 hw_addr[4];
+ u32 mal_ier;
#if defined(CONFIG_440GX)
unsigned long pfc1;
mtdcr (malier, mal_ier);
/* install MAL interrupt handler */
- irq_install_handler (VECNUM_MS,
+ irq_install_handler (VECNUM_MAL_SERR,
(interrupt_handler_t *) enetInt,
dev);
- irq_install_handler (VECNUM_MTE,
+ irq_install_handler (VECNUM_MAL_TXEOB,
(interrupt_handler_t *) enetInt,
dev);
- irq_install_handler (VECNUM_MRE,
+ irq_install_handler (VECNUM_MAL_RXEOB,
(interrupt_handler_t *) enetInt,
dev);
- irq_install_handler (VECNUM_TXDE,
+ irq_install_handler (VECNUM_MAL_TXDE,
(interrupt_handler_t *) enetInt,
dev);
- irq_install_handler (VECNUM_RXDE,
+ irq_install_handler (VECNUM_MAL_RXDE,
(interrupt_handler_t *) enetInt,
dev);
virgin = 1;
#include <asm/processor.h>
#include <asm/io.h>
#include <watchdog.h>
-#include <asm/ppc4xx-intvec.h>
+#include <ppc4xx.h>
#ifdef CONFIG_SERIAL_MULTI
#include <serial.h>
COBJS := 40x_spd_sdram.o
COBJS += 44x_spd_ddr.o
COBJS += 44x_spd_ddr2.o
-COBJS += 4xx_enet.o
COBJS += 4xx_pci.o
COBJS += 4xx_pcie.o
-COBJS += 4xx_uart.o
COBJS += bedbug_405.o
COBJS += commproc.o
COBJS += cpu.o
COBJS += denali_spd_ddr2.o
COBJS += ecc.o
COBJS += fdt.o
-COBJS += gpio.o
COBJS += i2c.o
COBJS += interrupts.o
COBJS += iop480_uart.o
-COBJS += miiphy.o
COBJS += ndfc.o
COBJS += sdram.o
COBJS += speed.o
COBJS += usb.o
COBJS += usb_ohci.o
COBJS += usbdev.o
+ifndef CONFIG_XILINX_440
+COBJS += 4xx_enet.o
+COBJS += 4xx_uart.o
+COBJS += gpio.o
+COBJS += miiphy.o
+COBJS += uic.o
+else
+COBJS += xilinx_irq.o
+endif
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
#endif
+#if defined(CONFIG_460SX)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "EBC (16 bits)",
+ "EBC (32 bits)",
+ "NAND (8 bits)",
+ "I2C (Addr 0x54)", /* A8 */
+ "I2C (Addr 0x52)", /* A4 */
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G' };
+#endif
+
#if defined(CONFIG_405EZ)
#define SDR0_PINSTP_SHIFT 28
static char *bootstrap_str[] = {
get_sys_info(&sys_info);
+#if defined(CONFIG_XILINX_440)
+ puts("IBM PowerPC 4");
+#else
puts("AMCC PowerPC 4");
+#endif
#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
strcpy(addstr, "Security/Kasumi support");
break;
+ case PVR_460SX_RA:
+ puts("SX Rev. A");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_460SX_RA_V1:
+ puts("SX Rev. A");
+ strcpy(addstr, "No Security support");
+ break;
+
+ case PVR_460GX_RA:
+ puts("GX Rev. A");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_460GX_RA_V1:
+ puts("GX Rev. A");
+ strcpy(addstr, "No Security support");
+ break;
+
+ case PVR_VIRTEX5:
+ puts("x5 VIRTEX5");
+ break;
+
default:
printf (" UNKNOWN (PVR=%08x)", pvr);
break;
void
cpu_init_f (void)
{
-#if defined(CONFIG_WATCHDOG) || defined(CONFIG_460EX)
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX)
u32 val;
#endif
+
reconfigure_pll(CFG_PLL_RECONFIG);
#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CFG_4xx_GPIO_TABLE)
reset_4xx_watchdog();
#endif /* CONFIG_WATCHDOG */
+#if defined(CONFIG_440GX)
+ /* Take the GX out of compatibility mode
+ * Travis Sawyer, 9 Mar 2004
+ * NOTE: 440gx user manual inconsistency here
+ * Compatibility mode and Ethernet Clock select are not
+ * correct in the manual
+ */
+ mfsdr(sdr_mfr, val);
+ val &= ~0x10000000;
+ mtsdr(sdr_mfr,val);
+#endif /* CONFIG_440GX */
+
#if defined(CONFIG_460EX)
/*
* Set SDR0_AHB_CFG[A2P_INCR4] (bit 24) and
* (C) Copyright 2003 (440GX port)
* Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
*
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
#include <watchdog.h>
#include <command.h>
#include <asm/processor.h>
+#include <asm/interrupt.h>
#include <ppc4xx.h>
#include <ppc_asm.tmpl>
#include <commproc.h>
-#include <asm/ppc4xx-intvec.h>
DECLARE_GLOBAL_DATA_PTR;
/*
- * Define the number of UIC's
- */
-#if defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT)
-#define UIC_MAX 4
-#elif defined(CONFIG_440GX) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
-#define UIC_MAX 3
-#elif defined(CONFIG_440GP) || defined(CONFIG_440SP) || \
- defined(CONFIG_440EP) || defined(CONFIG_440GR)
-#define UIC_MAX 2
-#else
-#define UIC_MAX 1
-#endif
-
-/*
* CPM interrupt vector functions.
*/
struct irq_action {
void *arg;
int count;
};
-
-static struct irq_action irq_vecs[UIC_MAX * 32];
-
-u32 get_dcr(u16);
-void set_dcr(u16, u32);
-
-#if (UIC_MAX > 1) && !defined(CONFIG_440GX)
-static void uic_cascade_interrupt(void *para);
-#endif
+static struct irq_action irq_vecs[IRQ_MAX];
#if defined(CONFIG_440)
/*
* Mark all irqs as free
*/
- for (vec = 0; vec < (UIC_MAX * 32); vec++) {
+ for (vec = 0; vec < IRQ_MAX; vec++) {
irq_vecs[vec].handler = NULL;
irq_vecs[vec].arg = NULL;
irq_vecs[vec].count = 0;
*/
set_evpr(0x00000000);
-#if !defined(CONFIG_440GX)
-#if (UIC_MAX > 1)
- /* Install the UIC1 handlers */
- irq_install_handler(VECNUM_UIC1NC, uic_cascade_interrupt, 0);
- irq_install_handler(VECNUM_UIC1C, uic_cascade_interrupt, 0);
-#endif
-#if (UIC_MAX > 2)
- irq_install_handler(VECNUM_UIC2NC, uic_cascade_interrupt, 0);
- irq_install_handler(VECNUM_UIC2C, uic_cascade_interrupt, 0);
-#endif
-#if (UIC_MAX > 3)
- irq_install_handler(VECNUM_UIC3NC, uic_cascade_interrupt, 0);
- irq_install_handler(VECNUM_UIC3C, uic_cascade_interrupt, 0);
-#endif
-#else /* !defined(CONFIG_440GX) */
- /* Take the GX out of compatibility mode
- * Travis Sawyer, 9 Mar 2004
- * NOTE: 440gx user manual inconsistency here
- * Compatibility mode and Ethernet Clock select are not
- * correct in the manual
+ /*
+ * Call uic or xilinx_irq pic_enable
*/
- mfsdr(sdr_mfr, val);
- val &= ~0x10000000;
- mtsdr(sdr_mfr,val);
-
- /* Enable UIC interrupts via UIC Base Enable Register */
- mtdcr(uicb0sr, UICB0_ALL);
- mtdcr(uicb0er, 0x54000000);
- /* None are critical */
- mtdcr(uicb0cr, 0);
-#endif /* !defined(CONFIG_440GX) */
+ pic_enable();
return (0);
}
-/* Handler for UIC interrupt */
-static void uic_interrupt(u32 uic_base, int vec_base)
+void timer_interrupt_cpu(struct pt_regs *regs)
{
- u32 uic_msr;
- u32 msr_shift;
- int vec;
-
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- uic_msr = get_dcr(uic_base + UIC_MSR);
- msr_shift = uic_msr;
- vec = vec_base;
-
- while (msr_shift != 0) {
- if (msr_shift & 0x80000000) {
- /*
- * Increment irq counter (for debug purpose only)
- */
- irq_vecs[vec].count++;
-
- if (irq_vecs[vec].handler != NULL) {
- /* call isr */
- (*irq_vecs[vec].handler)(irq_vecs[vec].arg);
- } else {
- set_dcr(uic_base + UIC_ER,
- get_dcr(uic_base + UIC_ER) &
- ~(0x80000000 >> (vec & 0x1f)));
- printf("Masking bogus interrupt vector %d"
- " (UIC_BASE=0x%x)\n", vec, uic_base);
- }
-
- /*
- * After servicing the interrupt, we have to remove the
- * status indicator
- */
- set_dcr(uic_base + UIC_SR, (0x80000000 >> (vec & 0x1f)));
- }
-
- /*
- * Shift msr to next position and increment vector
- */
- msr_shift <<= 1;
- vec++;
- }
+ /* nothing to do here */
+ return;
}
-#if (UIC_MAX > 1) && !defined(CONFIG_440GX)
-static void uic_cascade_interrupt(void *para)
+void interrupt_run_handler(int vec)
{
- external_interrupt(para);
-}
-#endif
-
-#if defined(CONFIG_440)
-#if defined(CONFIG_440GX)
-/* 440GX uses base uic register */
-#define UIC_BMSR uicb0msr
-#define UIC_BSR uicb0sr
-#else
-#define UIC_BMSR uic0msr
-#define UIC_BSR uic0sr
-#endif
-#else /* CONFIG_440 */
-#define UIC_BMSR uicmsr
-#define UIC_BSR uicsr
-#endif /* CONFIG_440 */
-
-/*
- * Handle external interrupts
- */
-void external_interrupt(struct pt_regs *regs)
-{
- u32 uic_msr;
-
- /*
- * Read masked interrupt status register to determine interrupt source
- */
- uic_msr = mfdcr(UIC_BMSR);
-
-#if (UIC_MAX > 1)
- if ((UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr))
- uic_interrupt(UIC1_DCR_BASE, 32);
-#endif
-
-#if (UIC_MAX > 2)
- if ((UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr))
- uic_interrupt(UIC2_DCR_BASE, 64);
-#endif
-
-#if (UIC_MAX > 3)
- if ((UICB0_UIC3CI & uic_msr) || (UICB0_UIC3NCI & uic_msr))
- uic_interrupt(UIC3_DCR_BASE, 96);
-#endif
-
-#if defined(CONFIG_440)
-#if !defined(CONFIG_440GX)
- if (uic_msr & ~(UICB0_ALL))
- uic_interrupt(UIC0_DCR_BASE, 0);
-#else
- if ((UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr))
- uic_interrupt(UIC0_DCR_BASE, 0);
-#endif
-#else /* CONFIG_440 */
- uic_interrupt(UIC0_DCR_BASE, 0);
-#endif /* CONFIG_440 */
-
- mtdcr(UIC_BSR, uic_msr);
+ irq_vecs[vec].count++;
+
+ if (irq_vecs[vec].handler != NULL) {
+ /* call isr */
+ (*irq_vecs[vec].handler) (irq_vecs[vec].arg);
+ } else {
+ pic_irq_disable(vec);
+ printf("Masking bogus interrupt vector %d\n", vec);
+ }
+ pic_irq_ack(vec);
return;
}
-/*
- * Install and free a interrupt handler.
- */
void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
{
- int i;
-
/*
* Print warning when replacing with a different irq vector
*/
irq_vecs[vec].handler = handler;
irq_vecs[vec].arg = arg;
- i = vec & 0x1f;
- if ((vec >= 0) && (vec < 32))
- mtdcr(uicer, mfdcr(uicer) | (0x80000000 >> i));
-#if (UIC_MAX > 1)
- else if ((vec >= 32) && (vec < 64))
- mtdcr(uic1er, mfdcr(uic1er) | (0x80000000 >> i));
-#endif
-#if (UIC_MAX > 2)
- else if ((vec >= 64) && (vec < 96))
- mtdcr(uic2er, mfdcr(uic2er) | (0x80000000 >> i));
-#endif
-#if (UIC_MAX > 3)
- else if (vec >= 96)
- mtdcr(uic3er, mfdcr(uic3er) | (0x80000000 >> i));
-#endif
-
- debug("Install interrupt for vector %d ==> %p\n", vec, handler);
+ pic_irq_enable(vec);
+ return;
}
-void irq_free_handler (int vec)
+void irq_free_handler(int vec)
{
- int i;
-
debug("Free interrupt for vector %d ==> %p\n",
vec, irq_vecs[vec].handler);
- i = vec & 0x1f;
- if ((vec >= 0) && (vec < 32))
- mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> i));
-#if (UIC_MAX > 1)
- else if ((vec >= 32) && (vec < 64))
- mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> i));
-#endif
-#if (UIC_MAX > 2)
- else if ((vec >= 64) && (vec < 96))
- mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> i));
-#endif
-#if (UIC_MAX > 3)
- else if (vec >= 96)
- mtdcr(uic3er, mfdcr(uic3er) & ~(0x80000000 >> i));
-#endif
+ pic_irq_disable(vec);
irq_vecs[vec].handler = NULL;
irq_vecs[vec].arg = NULL;
-}
-
-void timer_interrupt_cpu (struct pt_regs *regs)
-{
- /* nothing to do here */
return;
}
printf ("Interrupt-Information:\n");
printf ("Nr Routine Arg Count\n");
- for (vec = 0; vec < (UIC_MAX * 32); vec++) {
+ for (vec = 0; vec < IRQ_MAX; vec++) {
if (irq_vecs[vec].handler != NULL) {
printf ("%02d %08lx %08lx %d\n",
vec,
#include <asm/processor.h>
#include <asm/io.h>
#include <watchdog.h>
-#include <asm/ppc4xx-intvec.h>
#ifdef CONFIG_SERIAL_MULTI
#include <serial.h>
#include <common.h>
-#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY) && \
+#if defined(CONFIG_CMD_NAND) && !defined(CONFIG_NAND_LEGACY) && \
(defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_405EZ) || defined(CONFIG_405EX) || \
#include <asm/io.h>
#include <ppc4xx.h>
-static u8 hwctl = 0;
+/*
+ * We need to store the info, which chip-select (CS) is used for the
+ * chip number. For example on Sequoia NAND chip #0 uses
+ * CS #3.
+ */
+static int ndfc_cs[NDFC_MAX_BANKS];
-static void ndfc_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- switch (cmd) {
- case NAND_CTL_SETCLE:
- hwctl |= 0x1;
- break;
-
- case NAND_CTL_CLRCLE:
- hwctl &= ~0x1;
- break;
-
- case NAND_CTL_SETALE:
- hwctl |= 0x2;
- break;
-
- case NAND_CTL_CLRALE:
- hwctl &= ~0x2;
- break;
- }
-}
+ struct nand_chip *this = mtd->priv;
+ ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
-static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte)
-{
- struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
+ if (cmd == NAND_CMD_NONE)
+ return;
- if (hwctl & 0x1)
- out_8((u8 *)(base + NDFC_CMD), byte);
- else if (hwctl & 0x2)
- out_8((u8 *)(base + NDFC_ALE), byte);
+ if (ctrl & NAND_CLE)
+ out_8((u8 *)(base + NDFC_CMD), cmd & 0xFF);
else
- out_8((u8 *)(base + NDFC_DATA), byte);
-}
-
-static u_char ndfc_read_byte(struct mtd_info *mtdinfo)
-{
- struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
-
- return (in_8((u8 *)(base + NDFC_DATA)));
+ out_8((u8 *)(base + NDFC_ALE), cmd & 0xFF);
}
static int ndfc_dev_ready(struct mtd_info *mtdinfo)
{
struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
-
- while (!(in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY))
- ;
+ ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
- return 1;
+ return (in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY);
}
static void ndfc_enable_hwecc(struct mtd_info *mtdinfo, int mode)
{
struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
+ ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
u32 ccr;
ccr = in_be32((u32 *)(base + NDFC_CCR));
const u_char *dat, u_char *ecc_code)
{
struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
+ ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
u32 ecc;
u8 *p = (u8 *)&ecc;
static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
{
struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
+ ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
uint32_t *p = (uint32_t *) buf;
for (;len > 0; len -= 4)
static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
{
struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
+ ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
uint32_t *p = (uint32_t *) buf;
for (; len > 0; len -= 4)
static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
{
struct nand_chip *this = mtdinfo->priv;
- ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
+ ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
uint32_t *p = (uint32_t *) buf;
for (; len > 0; len -= 4)
* Don't use "chip" to address the NAND device,
* generate the cs from the address where it is encoded.
*/
- int cs = (ulong)nand->IO_ADDR_W & 0x00000003;
- ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc;
+ ulong base = (ulong)nand->IO_ADDR_W & 0xffffff00;
+ int cs = ndfc_cs[chip];
/* Set NandFlash Core Configuration Register */
/* 1 col x 2 rows */
out_be32((u32 *)(base + NDFC_CCR), 0x00000000 | (cs << 24));
+ out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222);
}
int board_nand_init(struct nand_chip *nand)
{
int cs = (ulong)nand->IO_ADDR_W & 0x00000003;
- ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc;
+ ulong base = (ulong)nand->IO_ADDR_W & 0xffffff00;
+ static int chip = 0;
- nand->hwcontrol = ndfc_hwcontrol;
- nand->read_byte = ndfc_read_byte;
- nand->read_buf = ndfc_read_buf;
- nand->write_byte = ndfc_write_byte;
- nand->dev_ready = ndfc_dev_ready;
+ /*
+ * Save chip-select for this chip #
+ */
+ ndfc_cs[chip] = cs;
- nand->eccmode = NAND_ECC_HW3_256;
- nand->enable_hwecc = ndfc_enable_hwecc;
- nand->calculate_ecc = ndfc_calculate_ecc;
- nand->correct_data = nand_correct_data;
+ /*
+ * Select required NAND chip in NDFC
+ */
+ board_nand_select_device(nand, chip);
+
+ nand->IO_ADDR_R = (void __iomem *)(base + NDFC_DATA);
+ nand->IO_ADDR_W = (void __iomem *)(base + NDFC_DATA);
+ nand->cmd_ctrl = ndfc_hwcontrol;
+ nand->chip_delay = 50;
+ nand->read_buf = ndfc_read_buf;
+ nand->dev_ready = ndfc_dev_ready;
+ nand->ecc.correct = nand_correct_data;
+ nand->ecc.hwctl = ndfc_enable_hwecc;
+ nand->ecc.calculate = ndfc_calculate_ecc;
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.size = 256;
+ nand->ecc.bytes = 3;
#ifndef CONFIG_NAND_SPL
nand->write_buf = ndfc_write_buf;
mtebc(pb0ap, CFG_EBC_PB0AP);
#endif
- /*
- * Select required NAND chip in NDFC
- */
- board_nand_select_device(nand, cs);
- out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222);
+ chip++;
return 0;
}
#elif defined(CONFIG_440)
-#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
static u8 pll_fwdv_multi_bits[] = {
/* values for: 1 - 16 */
0x00, 0x01, 0x0f, 0x04, 0x09, 0x0a, 0x0d, 0x0e, 0x03, 0x0c,
return sys_info.freqPCI;
}
-#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
+#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) \
+ && !defined(CONFIG_XILINX_440)
void get_sys_info (sys_info_t * sysInfo)
{
unsigned long strp0;
sysInfo->freqUART = sysInfo->freqPLB;
}
#else
+
+#if !defined(CONFIG_XILINX_440)
void get_sys_info (sys_info_t * sysInfo)
{
unsigned long strp0;
}
#endif
+#endif /* CONFIG_XILINX_440 */
#if defined(CONFIG_YUCCA)
unsigned long determine_sysper(void)
/* not all PPC's have internal SRAM usable as L2-cache */
#if defined(CONFIG_440GX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
mtdcr l2_cache_cfg,r0 /* Ensure L2 Cache is off */
#endif
lis r1,0x4000 /* BAS = 8000_0000 */
ori r1,r1,0x4580 /* 16k */
mtdcr isram0_sb0cr,r1
+#elif defined(CONFIG_460SX)
+ lis r1,0x0000 /* BAS = 0000_0000 */
+ ori r1,r1,0x0B84 /* first 128k */
+ mtdcr isram0_sb0cr,r1
+ lis r1,0x0001
+ ori r1,r1,0x0B84 /* second 128k */
+ mtdcr isram0_sb1cr,r1
+ lis r1, 0x0002
+ ori r1,r1, 0x0B84 /* third 128k */
+ mtdcr isram0_sb2cr,r1
+ lis r1, 0x0003
+ ori r1,r1, 0x0B84 /* fourth 128k */
+ mtdcr isram0_sb3cr,r1
#elif defined(CONFIG_440GP)
ori r1,r1,0x0380 /* 8k rw */
mtdcr isram0_sb0cr,r1
#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
/*
* On some 440er platforms the cache is enabled in the first TLB (Boot-CS)
* to speed up the boot process. Now this cache needs to be disabled.
--- /dev/null
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 (440GX port)
+ * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
+ *
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
+ * 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 <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/interrupt.h>
+#include <ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+
+#if (UIC_MAX > 3)
+#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \
+ UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI) | \
+ UIC_MASK(VECNUM_UIC3CI) | UIC_MASK(VECNUM_UIC3NCI))
+#elif (UIC_MAX > 2)
+#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \
+ UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI))
+#elif (UIC_MAX > 1)
+#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI))
+#else
+#define UICB0_ALL 0
+#endif
+
+u32 get_dcr(u16);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void pic_enable(void)
+{
+#if (UIC_MAX > 1)
+ /* Install the UIC1 handlers */
+ irq_install_handler(VECNUM_UIC1NCI, (void *)(void *)external_interrupt, 0);
+ irq_install_handler(VECNUM_UIC1CI, (void *)(void *)external_interrupt, 0);
+#endif
+#if (UIC_MAX > 2)
+ irq_install_handler(VECNUM_UIC2NCI, (void *)(void *)external_interrupt, 0);
+ irq_install_handler(VECNUM_UIC2CI, (void *)(void *)external_interrupt, 0);
+#endif
+#if (UIC_MAX > 3)
+ irq_install_handler(VECNUM_UIC3NCI, (void *)(void *)external_interrupt, 0);
+ irq_install_handler(VECNUM_UIC3CI, (void *)(void *)external_interrupt, 0);
+#endif
+}
+
+/* Handler for UIC interrupt */
+static void uic_interrupt(u32 uic_base, int vec_base)
+{
+ u32 uic_msr;
+ u32 msr_shift;
+ int vec;
+
+ /*
+ * Read masked interrupt status register to determine interrupt source
+ */
+ uic_msr = get_dcr(uic_base + UIC_MSR);
+ msr_shift = uic_msr;
+ vec = vec_base;
+
+ while (msr_shift != 0) {
+ if (msr_shift & 0x80000000)
+ interrupt_run_handler(vec);
+ /*
+ * Shift msr to next position and increment vector
+ */
+ msr_shift <<= 1;
+ vec++;
+ }
+}
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+ u32 uic_msr;
+
+ /*
+ * Read masked interrupt status register to determine interrupt source
+ */
+ uic_msr = mfdcr(uic0msr);
+
+#if (UIC_MAX > 1)
+ if ((UIC_MASK(VECNUM_UIC1CI) & uic_msr) ||
+ (UIC_MASK(VECNUM_UIC1NCI) & uic_msr))
+ uic_interrupt(UIC1_DCR_BASE, 32);
+#endif
+
+#if (UIC_MAX > 2)
+ if ((UIC_MASK(VECNUM_UIC2CI) & uic_msr) ||
+ (UIC_MASK(VECNUM_UIC2NCI) & uic_msr))
+ uic_interrupt(UIC2_DCR_BASE, 64);
+#endif
+
+#if (UIC_MAX > 3)
+ if ((UIC_MASK(VECNUM_UIC3CI) & uic_msr) ||
+ (UIC_MASK(VECNUM_UIC3NCI) & uic_msr))
+ uic_interrupt(UIC3_DCR_BASE, 96);
+#endif
+
+ if (uic_msr & ~(UICB0_ALL))
+ uic_interrupt(UIC0_DCR_BASE, 0);
+
+ mtdcr(uic0sr, uic_msr);
+
+ return;
+}
+
+void pic_irq_ack(unsigned int vec)
+{
+ if ((vec >= 0) && (vec < 32))
+ mtdcr(uicsr, UIC_MASK(vec));
+ else if ((vec >= 32) && (vec < 64))
+ mtdcr(uic1sr, UIC_MASK(vec));
+ else if ((vec >= 64) && (vec < 96))
+ mtdcr(uic2sr, UIC_MASK(vec));
+ else if (vec >= 96)
+ mtdcr(uic3sr, UIC_MASK(vec));
+}
+
+/*
+ * Install and free a interrupt handler.
+ */
+void pic_irq_enable(unsigned int vec)
+{
+
+ if ((vec >= 0) && (vec < 32))
+ mtdcr(uicer, mfdcr(uicer) | UIC_MASK(vec));
+ else if ((vec >= 32) && (vec < 64))
+ mtdcr(uic1er, mfdcr(uic1er) | UIC_MASK(vec));
+ else if ((vec >= 64) && (vec < 96))
+ mtdcr(uic2er, mfdcr(uic2er) | UIC_MASK(vec));
+ else if (vec >= 96)
+ mtdcr(uic3er, mfdcr(uic3er) | UIC_MASK(vec));
+
+ debug("Install interrupt for vector %d ==> %p\n", vec, handler);
+}
+
+void pic_irq_disable(unsigned int vec)
+{
+ if ((vec >= 0) && (vec < 32))
+ mtdcr(uicer, mfdcr(uicer) & ~UIC_MASK(vec));
+ else if ((vec >= 32) && (vec < 64))
+ mtdcr(uic1er, mfdcr(uic1er) & ~UIC_MASK(vec));
+ else if ((vec >= 64) && (vec < 96))
+ mtdcr(uic2er, mfdcr(uic2er) & ~UIC_MASK(vec));
+ else if (vec >= 96)
+ mtdcr(uic3er, mfdcr(uic3er) & ~UIC_MASK(vec));
+}
#if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && defined(CONFIG_CMD_USB)
#include <usb.h>
+#include <asm/ppc4xx-uic.h>
#include "usbdev.h"
-#include <asm/ppc4xx-intvec.h>
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
/*enable interrupts */
*(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f;
- irq_install_handler(VECNUM_HSB2D, (interrupt_handler_t *) usbInt,
+ irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt,
NULL);
}
#else
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/interrupt.h>
+#include <ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+#include <asm/io.h>
+#include <asm/xilinx_irq.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void pic_enable(void)
+{
+ debug("Xilinx PIC at 0x%8x\n", intc);
+
+ /*
+ * Disable all external interrupts until they are
+ * explicitly requested.
+ */
+ out_be32((u32 *) IER, 0);
+
+ /* Acknowledge any pending interrupts just in case. */
+ out_be32((u32 *) IAR, 0xffffffff);
+
+ /* Turn on the Master Enable. */
+ out_be32((u32 *) MER, 0x3UL);
+
+ return;
+}
+
+int xilinx_pic_irq_get(void)
+{
+ u32 irq;
+ irq = in_be32((u32 *) IVR);
+
+ /* If no interrupt is pending then all bits of the IVR are set to 1. As
+ * the IVR is as many bits wide as numbers of inputs are available.
+ * Therefore, if all bits of the IVR are set to one, its content will
+ * be bigger than XPAR_INTC_MAX_NUM_INTR_INPUTS.
+ */
+ if (irq >= XPAR_INTC_MAX_NUM_INTR_INPUTS)
+ irq = -1; /* report no pending interrupt. */
+
+ debug("get_irq: %d\n", irq);
+ return (irq);
+}
+
+void pic_irq_enable(unsigned int irq)
+{
+ u32 mask = IRQ_MASK(irq);
+ debug("enable: %d\n", irq);
+ out_be32((u32 *) SIE, mask);
+}
+
+void pic_irq_disable(unsigned int irq)
+{
+ u32 mask = IRQ_MASK(irq);
+ debug("disable: %d\n", irq);
+ out_be32((u32 *) CIE, mask);
+}
+
+void pic_irq_ack(unsigned int irq)
+{
+ u32 mask = IRQ_MASK(irq);
+ debug("ack: %d\n", irq);
+ out_be32((u32 *) IAR, mask);
+}
+
+void external_interrupt(struct pt_regs *regs)
+{
+ int irq;
+
+ irq = xilinx_pic_irq_get();
+ if (irq < 0)
+ return;
+
+ interrupt_run_handler(irq);
+
+ return;
+}
Print information about all of the NAND devices found.
nand read addr ofs|partition size
- Read `size' bytes from `ofs' in NAND flash to `addr'. If a page
- cannot be read because it is marked bad or an uncorrectable data
- error is found the command stops with an error.
-
- nand read.jffs2 addr ofs|partition size
- Like `read', but the data for blocks that are marked bad is read as
- 0xff. This gives a readable JFFS2 image that can be processed by
- the JFFS2 commands such as ls and fsload.
+ Read `size' bytes from `ofs' in NAND flash to `addr'. Blocks that
+ are marked bad are skipped. If a page cannot be read because an
+ uncorrectable data error is found, the command stops with an error.
nand read.oob addr ofs|partition size
Read `size' bytes from the out-of-band data area corresponding to
for bad blocks or ECC errors.
nand write addr ofs|partition size
- Write `size' bytes from `addr' to `ofs' in NAND flash. If a page
- cannot be written because it is marked bad or the write fails the
- command stops with an error.
-
- nand write.jffs2 addr ofs|partition size
- Like `write', but blocks that are marked bad are skipped and the
- data is written to the next block instead. This allows writing
- a JFFS2 image, as long as the image is short enough to fit even
- after skipping the bad blocks. Compact images, such as those
- produced by mkfs.jffs2 should work well, but loading an image copied
- from another flash is going to be trouble if there are any bad blocks.
+ Write `size' bytes from `addr' to `ofs' in NAND flash. Blocks that
+ are marked bad are skipped. If a page cannot be read because an
+ uncorrectable data error is found, the command stops with an error.
+
+ As JFFS2 skips blocks similarly, this allows writing a JFFS2 image,
+ as long as the image is short enough to fit even after skipping the
+ bad blocks. Compact images, such as those produced by mkfs.jffs2
+ should work well, but loading an image copied from another flash is
+ going to be trouble if there are any bad blocks.
nand write.oob addr ofs|partition size
Write `size' bytes from `addr' to the out-of-band data area
The old NAND handling code has been re-factored and is now confined
to only board-specific files and - unfortunately - to the DoC code
(see below). A new configuration variable has been introduced:
-CFG_NAND_LEGACY, which has to be defined in the board config file if
+CONFIG_NAND_LEGACY, which has to be defined in the board config file if
that board uses legacy code.
The necessary changes have been made to all affected boards, and no
using both the new code which is able to skip bad blocks
"nand erase clean" additionally writes JFFS2-cleanmarkers in the oob.
- "nand write.jffs2"
- like "nand write" but skip found bad eraseblocks
-
- "nand read.jffs2"
- like "nand read" but skip found bad eraseblocks
-
Miscellaneous and testing commands:
"markbad [offset]"
create an artificial bad block (for testing bad block handling)
LIB := $(obj)libblock.a
-COBJS-y += ahci.o
-COBJS-y += ata_piix.o
+COBJS-$(CONFIG_SCSI_AHCI) += ahci.o
+COBJS-$(CONFIG_ATA_PIIX) += ata_piix.o
COBJS-$(CONFIG_FSL_SATA) += fsl_sata.o
COBJS-$(CONFIG_LIBATA) += libata.o
COBJS-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
-COBJS-y += sil680.o
-COBJS-y += sym53c8xx.o
-COBJS-y += systemace.o
+COBJS-$(CONFIG_IDE_SIL680) += sil680.o
+COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
+COBJS-$(CONFIG_SYSTEMACE) += systemace.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
*/
#include <common.h>
-#ifdef CONFIG_SCSI_AHCI
-
#include <command.h>
#include <pci.h>
#include <asm/processor.h>
{
/*The ahci error info can be read in the ahci driver*/
}
-#endif
#include <ide.h>
#include <ata.h>
-#ifdef CFG_ATA_PIIX /*ata_piix driver */
-
extern block_dev_desc_t sata_dev_desc[CFG_SATA_MAX_DEVICE];
extern int curr_device;
{
return 0;
}
-
-#endif
* The following parameters must be defined in the configuration file
* of the target board:
*
- * #define CFG_IDE_SIL680
+ * #define CONFIG_IDE_SIL680
*
* #define CONFIG_PCI_PNP
* NOTE it may also be necessary to define this if the default of 8 is
*/
#include <common.h>
-#if defined(CFG_IDE_SIL680)
#include <ata.h>
#include <ide.h>
#include <pci.h>
void ide_set_reset (int flag) {
return;
}
-
-#endif /* CFG_IDE_SIL680 */
#include <common.h>
-#ifdef CONFIG_SCSI_SYM53C8XX
-
#include <command.h>
#include <pci.h>
#include <asm/processor.h>
#endif
}
#endif
-
-
-#endif /* CONFIG_SCSI_SYM53C8XX */
#include <part.h>
#include <asm/io.h>
-#ifdef CONFIG_SYSTEMACE
-
/*
* The ace_readw and writew functions read/write 16bit words, but the
* offset value is the BYTE offset as most used in the Xilinx
return blkcnt;
}
-#endif /* CONFIG_SYSTEMACE */
#include <common.h>
-#ifdef CONFIG_FSLDMAFEC
-
#include <MCD_dma.h>
#include <MCD_tasksInit.h>
#include <MCD_progCheck.h>
for (i = 0; i < size; i += sizeof(int), dest++, src++)
*dest = *src;
}
-#endif /* CONFIG_FSLDMAFEC */
#include <common.h>
-#ifdef CONFIG_FSLDMAFEC
-
#include <MCD_dma.h>
u32 MCD_varTab0[];
#ifdef MCD_INCLUDE_EU
MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#endif
-
-#endif /* CONFIG_FSLDMAFEC */
* Do not edit!
*/
-#ifdef CONFIG_FSLDMAFEC
-
#include <MCD_dma.h>
extern dmaRegs *MCD_dmaBar;
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16) 0x8000;
}
-
-#endif /* CONFIG_FSLDMAFEC */
LIB := $(obj)libdma.a
-COBJS-y += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
+COBJS-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
LIB = $(obj)libhwmon.a
COBJS-$(CONFIG_DTT_ADM1021) += adm1021.o
+COBJS-$(CONFIG_DTT_ADT7460) += adt7460.o
COBJS-$(CONFIG_DTT_DS1621) += ds1621.o
COBJS-$(CONFIG_DTT_DS1722) += ds1722.o
COBJS-$(CONFIG_DTT_DS1775) += ds1775.o
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid, ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <common.h>
+#include <i2c.h>
+#include <dtt.h>
+
+#define ADT7460_ADDRESS 0x2c
+#define ADT7460_INVALID 128
+#define ADT7460_CONFIG 0x40
+#define ADT7460_REM1_TEMP 0x25
+#define ADT7460_LOCAL_TEMP 0x26
+#define ADT7460_REM2_TEMP 0x27
+
+int dtt_read(int sensor, int reg)
+{
+ u8 dir = reg;
+ u8 data;
+
+ if (i2c_read(ADT7460_ADDRESS, dir, 1, &data, 1) == -1)
+ return -1;
+ if (data == ADT7460_INVALID)
+ return -1;
+
+ return data;
+}
+
+int dtt_write(int sensor, int reg, int val)
+{
+ u8 dir = reg;
+ u8 data = val;
+
+ if (i2c_write(ADT7460_ADDRESS, dir, 1, &data, 1) == -1)
+ return -1;
+
+ return 0;
+}
+
+int dtt_init(void)
+{
+ printf("ADT7460 at I2C address 0x%2x\n", ADT7460_ADDRESS);
+
+ if (dtt_write(0, ADT7460_CONFIG, 1) == -1) {
+ puts("Error initialiting ADT7460\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int dtt_get_temp(int sensor)
+{
+ int aux;
+ u8 table[] =
+ { ADT7460_REM1_TEMP, ADT7460_LOCAL_TEMP, ADT7460_REM2_TEMP };
+
+ if (sensor > 2) {
+ puts("DTT sensor does not exist\n");
+ return -1;
+ }
+
+ aux = dtt_read(0, table[sensor]);
+ if (aux == -1) {
+ puts("DTT temperature read failed\n");
+ return -1;
+ }
+
+ return aux;
+}
LIB := $(obj)libi2c.a
-COBJS-y += fsl_i2c.o
-COBJS-y += omap1510_i2c.o
-COBJS-y += omap24xx_i2c.o
-COBJS-y += tsi108_i2c.o
-COBJS-y += mxc_i2c.o
+COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o
+COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o
+COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
+COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
+COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
#include <common.h>
-#ifdef CONFIG_FSL_I2C
#ifdef CONFIG_HARD_I2C
#include <command.h>
}
#endif /* CONFIG_HARD_I2C */
-#endif /* CONFIG_FSL_I2C */
#include <common.h>
-#if defined(CONFIG_HARD_I2C) && defined (CONFIG_I2C_MXC)
+#if defined(CONFIG_HARD_I2C)
#include <asm/arch/mx31.h>
#include <asm/arch/mx31-regs.h>
#include <common.h>
-#ifdef CONFIG_DRIVER_OMAP1510_I2C
-
static void wait_for_bb (void);
static u16 wait_for_pin (void);
return status;
}
-
-#endif /* CONFIG_DRIVER_OMAP1510_I2C */
#include <common.h>
-#ifdef CONFIG_DRIVER_OMAP24XX_I2C
-
#include <asm/arch/i2c.h>
#include <asm/io.h>
}
return status;
}
-
-#endif /* CONFIG_DRIVER_OMAP24XX_I2C */
#include <config.h>
#include <common.h>
-#ifdef CONFIG_TSI108_I2C
#include <tsi108.h>
#if defined(CONFIG_CMD_I2C)
}
#endif
-#endif /* CONFIG_TSI108_I2C */
LIB := $(obj)libinput.a
-COBJS-y += i8042.o
-COBJS-y += keyboard.o
-COBJS-y += pc_keyb.o ps2ser.o ps2mult.o
+COBJS-$(CONFIG_I8042_KBD) += i8042.o
+ifdef CONFIG_PS2KBD
+COBJS-y += keyboard.o pc_keyb.o
+COBJS-$(CONFIG_PS2MULT) += ps2mult.o ps2ser.o
+endif
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
#include <common.h>
-#ifdef CONFIG_I8042_KBD
-
#ifdef CONFIG_USE_CPCIDVI
extern u8 gt_cpcidvi_in8(u32 offset);
extern void gt_cpcidvi_out8(u32 offset, u8 data);
return 0;
}
-
-#endif /* CONFIG_I8042_KBD */
#include <common.h>
-#ifdef CONFIG_PS2KBD
-
#include <devices.h>
#include <keyboard.h>
}
return error;
}
-
-#endif /* CONFIG_PS2KBD */
#include <common.h>
-#ifdef CONFIG_PS2KBD
-
#include <keyboard.h>
#include <pc_keyb.h>
kbd_send_data(KBD_CMD_SET_LEDS);
kbd_send_data(leds);
}
-
-#endif /* CONFIG_PS2KBD */
#include <common.h>
-#ifdef CONFIG_PS2MULT
-
#include <pc_keyb.h>
#include <asm/atomic.h>
#include <ps2mult.h>
return 0;
}
-
-#endif /* CONFIG_PS2MULT */
#include <common.h>
-#ifdef CONFIG_PS2SERIAL
-
#include <asm/io.h>
#include <asm/atomic.h>
#include <ps2mult.h>
ps2mult_callback(atomic_read(&ps2buf_cnt));
}
}
-
-#endif /* CONFIG_PS2SERIAL */
LIB := $(obj)libmisc.a
-COBJS-y += ali512x.o
-COBJS-y += ns87308.o
-COBJS-y += status_led.o
+COBJS-$(CONFIG_ALI152X) += ali512x.o
COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
+COBJS-$(CONFIG_NS87308) += ns87308.o
+COBJS-$(CONFIG_STATUS_LED) += status_led.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
#include <config.h>
-#ifdef CONFIG_ALI152X
-
#include <common.h>
#include <asm/io.h>
#include <asm/ic/ali512x.h>
return data & bit;
}
-
-
-#endif
#include <config.h>
-#ifdef CFG_NS87308
-
#include <ns87308.h>
void initialise_ns87308 (void)
PNP_PGCS_CSLINE_CONF(2, CFG_NS87308_CS2_CONF);
#endif
}
-
-#endif
/* ------------------------------------------------------------------------- */
-#ifdef CONFIG_STATUS_LED
-
typedef struct {
led_id_t mask;
int state;
}
__led_set (ld->mask, state);
}
-
-#endif /* CONFIG_STATUS_LED */
LIB := $(obj)libmtd.a
-COBJS-y += at45.o
-COBJS-y += cfi_flash.o
+COBJS-$(CONFIG_HAS_DATAFLASH) += at45.o
+COBJS-$(CONFIG_FLASH_CFI_DRIVER) += cfi_flash.o
COBJS-$(CONFIG_HAS_DATAFLASH) += dataflash.o
-COBJS-y += mw_eeprom.o
COBJS-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o
+COBJS-$(CONFIG_MW_EEPROM) += mw_eeprom.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
#include <config.h>
#include <common.h>
-
-#ifdef CONFIG_HAS_DATAFLASH
#include <dataflash.h>
/*
AT91F_DataFlashGetStatus(pDesc);
return ((pDesc->command[1] == 0xFF) ? 0 : pDesc->command[1] & 0x3C);
}
-#endif
#include <asm/io.h>
#include <asm/byteorder.h>
#include <environment.h>
-#ifdef CFG_FLASH_CFI_DRIVER
/*
* This file implements a Common Flash Interface (CFI) driver for
#define AMD_STATUS_TOGGLE 0x40
#define AMD_STATUS_ERROR 0x20
+#define ATM_CMD_UNLOCK_SECT 0x70
+#define ATM_CMD_SOFTLOCK_START 0x80
+#define ATM_CMD_LOCK_SECT 0x40
+
#define FLASH_OFFSET_MANUFACTURER_ID 0x00
#define FLASH_OFFSET_DEVICE_ID 0x01
#define FLASH_OFFSET_DEVICE_ID2 0x0E
/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
#ifdef CFG_MAX_FLASH_BANKS_DETECT
-static ulong bank_base[CFG_MAX_FLASH_BANKS_DETECT] = CFG_FLASH_BANKS_LIST;
-flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
+# define CFI_MAX_FLASH_BANKS CFG_MAX_FLASH_BANKS_DETECT
#else
-static ulong bank_base[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS_LIST;
-flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* FLASH chips info */
+# define CFI_MAX_FLASH_BANKS CFG_MAX_FLASH_BANKS
#endif
+flash_info_t flash_info[CFI_MAX_FLASH_BANKS]; /* FLASH chips info */
+
/*
* Check if chip width is defined. If not, start detecting with 8bit.
*/
{
int retcode = 0;
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
- if (prot)
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
- else
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_PROG_REGIONS:
+ case CFI_CMDSET_INTEL_STANDARD:
+ flash_write_cmd (info, sector, 0,
+ FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
+ if (prot)
+ flash_write_cmd (info, sector, 0,
+ FLASH_CMD_PROTECT_SET);
+ else
+ flash_write_cmd (info, sector, 0,
+ FLASH_CMD_PROTECT_CLEAR);
+ break;
+ case CFI_CMDSET_AMD_EXTENDED:
+ case CFI_CMDSET_AMD_STANDARD:
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
+#endif
+ /* U-Boot only checks the first byte */
+ if (info->manufacturer_id == (uchar)ATM_MANUFACT) {
+ if (prot) {
+ flash_unlock_seq (info, 0);
+ flash_write_cmd (info, 0,
+ info->addr_unlock1,
+ ATM_CMD_SOFTLOCK_START);
+ flash_unlock_seq (info, 0);
+ flash_write_cmd (info, sector, 0,
+ ATM_CMD_LOCK_SECT);
+ } else {
+ flash_write_cmd (info, 0,
+ info->addr_unlock1,
+ AMD_CMD_UNLOCK_START);
+ if (info->device_id == ATM_ID_BV6416)
+ flash_write_cmd (info, sector,
+ 0, ATM_CMD_UNLOCK_SECT);
+ }
+ }
+ break;
+ };
if ((retcode =
flash_full_status_check (info, sector, info->erase_blk_tout,
char *s = getenv("unlock");
#endif
+#define BANK_BASE(i) (((unsigned long [CFI_MAX_FLASH_BANKS])CFG_FLASH_BANKS_LIST)[i])
+
/* Init: no FLASHes known */
for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
flash_info[i].flash_id = FLASH_UNKNOWN;
- if (!flash_detect_legacy (bank_base[i], i))
- flash_get_size (bank_base[i], i);
+ if (!flash_detect_legacy (BANK_BASE(i), i))
+ flash_get_size (BANK_BASE(i), i);
size += flash_info[i].size;
if (flash_info[i].flash_id == FLASH_UNKNOWN) {
#ifndef CFG_FLASH_QUIET_TEST
#endif
return (size);
}
-
-#endif /* CFG_FLASH_CFI */
switch (dfcode) {
case AT45DB021:
dataflash_info[i].Device.pages_number = 1024;
- dataflash_info[i].Device.pages_size = 263;
+ dataflash_info[i].Device.pages_size = 264;
dataflash_info[i].Device.page_offset = 9;
dataflash_info[i].Device.byte_mask = 0x300;
dataflash_info[i].Device.cs = cs[i].cs;
dataflash_info[i].id = dfcode;
found[i] += dfcode;;
break;
+
+ case AT45DB081:
+ dataflash_info[i].Device.pages_number = 4096;
+ dataflash_info[i].Device.pages_size = 264;
+ dataflash_info[i].Device.page_offset = 9;
+ dataflash_info[i].Device.byte_mask = 0x300;
+ dataflash_info[i].Device.cs = cs[i].cs;
+ dataflash_info[i].Desc.DataFlash_state = IDLE;
+ dataflash_info[i].logical_address = cs[i].addr;
+ dataflash_info[i].id = dfcode;
+ found[i] += dfcode;;
+ break;
+
case AT45DB161:
dataflash_info[i].Device.pages_number = 4096;
dataflash_info[i].Device.pages_size = 528;
ERASEINFO(0x10000,7),
}
},
+ {
+ .mfr_id = MANUFACTURER_AMD,
+ .dev_id = AM29LV800BB,
+ .name = "AMD AM29LV800BB",
+ .uaddr = {
+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
+ },
+ .DevSize = SIZE_1MiB,
+ .CmdSet = CFI_CMDSET_AMD_LEGACY,
+ .NumEraseRegions= 4,
+ .regions = {
+ ERASEINFO(0x04000, 1),
+ ERASEINFO(0x02000, 2),
+ ERASEINFO(0x08000, 1),
+ ERASEINFO(0x10000, 15),
+ }
+ },
#endif
};
/* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */
#include <common.h>
-
-#ifdef CONFIG_MW_EEPROM
-
#include <ssi.h>
/*
}
return 0;
}
-
-#endif
LIB := $(obj)libnand.a
+ifdef CONFIG_CMD_NAND
+ifndef CONFIG_NAND_LEGACY
COBJS-y += nand.o
COBJS-y += nand_base.o
-COBJS-y += nand_ids.o
-COBJS-y += nand_ecc.o
COBJS-y += nand_bbt.o
+COBJS-y += nand_ecc.o
+COBJS-y += nand_ids.o
COBJS-y += nand_util.o
+endif
-COBJS-y += fsl_upm.o
+COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
+COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
+endif
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
*
* Interface to generic NAND code for M-Systems DiskOnChip devices
*
- * $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $
+ * $Id: diskonchip.c,v 1.55 2005/11/07 11:14:30 gleixner Exp $
*/
#include <common.h>
-#if !defined(CFG_NAND_LEGACY)
+#if !defined(CONFIG_NAND_LEGACY)
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/inftl.h>
/* Where to look for the devices? */
-#ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS
-#define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0
+#ifndef CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS
+#define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 0
#endif
static unsigned long __initdata doc_locations[] = {
#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
-#ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH
+#ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH
0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
0xff000000,
#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
0xff000000,
-##else
+#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
#endif
0xffffffff };
unsigned long physadr;
u_char ChipID;
u_char CDSNControl;
- int chips_per_floor; /* The number of chips detected on each floor */
+ int chips_per_floor; /* The number of chips detected on each floor */
int curfloor;
int curchip;
int mh0_page;
struct mtd_info *nextdoc;
};
-/* Max number of eraseblocks to scan (from start of device) for the (I)NFTL
- MediaHeader. The spec says to just keep going, I think, but that's just
- silly. */
-#define MAX_MEDIAHEADER_SCAN 8
-
/* This is the syndrome computed by the HW ecc generator upon reading an empty
page, one with all 0xff for data and stored ecc code. */
static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };
+
/* This is the ecc value computed by the HW ecc generator upon writing an empty
page, one with all 0xff for data. */
static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
-static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);
+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int bitmask);
static void doc200x_select_chip(struct mtd_info *mtd, int chip);
-static int debug=0;
+static int debug = 0;
module_param(debug, int, 0);
-static int try_dword=1;
+static int try_dword = 1;
module_param(try_dword, int, 0);
-static int no_ecc_failures=0;
+static int no_ecc_failures = 0;
module_param(no_ecc_failures, int, 0);
-#ifdef CONFIG_MTD_PARTITIONS
-static int no_autopart=0;
+static int no_autopart = 0;
module_param(no_autopart, int, 0);
-#endif
-#ifdef MTD_NAND_DISKONCHIP_BBTWRITE
-static int inftl_bbt_write=1;
+static int show_firmware_partition = 0;
+module_param(show_firmware_partition, int, 0);
+
+#ifdef CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE
+static int inftl_bbt_write = 1;
#else
-static int inftl_bbt_write=0;
+static int inftl_bbt_write = 0;
#endif
module_param(inftl_bbt_write, int, 0);
-static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS;
+static unsigned long doc_config_location = CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS;
module_param(doc_config_location, ulong, 0);
MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
-
/* Sector size for HW ECC */
#define SECTOR_SIZE 512
/* The sector bytes are packed into NB_DATA 10 bit words */
* some comments, improved a minor bit and converted it to make use
* of the generic Reed-Solomon libary. tglx
*/
-static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
+static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
{
int i, j, nerr, errpos[8];
uint8_t parity;
* s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0]
* where x = alpha^(FCR + i)
*/
- for(j = 1; j < NROOTS; j++) {
- if(ds[j] == 0)
+ for (j = 1; j < NROOTS; j++) {
+ if (ds[j] == 0)
continue;
tmp = rs->index_of[ds[j]];
- for(i = 0; i < NROOTS; i++)
+ for (i = 0; i < NROOTS; i++)
s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
}
* but they are given by the design of the de/encoder circuit
* in the DoC ASIC's.
*/
- for(i = 0;i < nerr; i++) {
+ for (i = 0; i < nerr; i++) {
int index, bitpos, pos = 1015 - errpos[i];
uint8_t val;
if (pos >= NB_DATA && pos < 1019)
can be modified since pos is even */
index = (pos >> 3) ^ 1;
bitpos = pos & 7;
- if ((index >= 0 && index < SECTOR_SIZE) ||
- index == (SECTOR_SIZE + 1)) {
+ if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) {
val = (uint8_t) (errval[i] >> (2 + bitpos));
parity ^= val;
if (index < SECTOR_SIZE)
bitpos = (bitpos + 10) & 7;
if (bitpos == 0)
bitpos = 8;
- if ((index >= 0 && index < SECTOR_SIZE) ||
- index == (SECTOR_SIZE + 1)) {
- val = (uint8_t)(errval[i] << (8 - bitpos));
+ if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) {
+ val = (uint8_t) (errval[i] << (8 - bitpos));
parity ^= val;
if (index < SECTOR_SIZE)
data[index] ^= val;
void __iomem *docptr = doc->virtadr;
unsigned long timeo = jiffies + (HZ * 10);
- if(debug) printk("_DoC_WaitReady...\n");
+ if (debug)
+ printk("_DoC_WaitReady...\n");
/* Out-of-line routine to wait for chip response */
if (DoC_is_MillenniumPlus(doc)) {
while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
DoC_Delay(doc, 2);
}
- if(debug) printk("DoC_WaitReady OK\n");
+ if (debug)
+ printk("DoC_WaitReady OK\n");
return ret;
}
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
- if(debug)printk("write_byte %02x\n", datum);
+ if (debug)
+ printk("write_byte %02x\n", datum);
WriteDOC(datum, docptr, CDSNSlowIO);
WriteDOC(datum, docptr, 2k_CDSN_IO);
}
ReadDOC(docptr, CDSNSlowIO);
DoC_Delay(doc, 2);
ret = ReadDOC(docptr, 2k_CDSN_IO);
- if (debug) printk("read_byte returns %02x\n", ret);
+ if (debug)
+ printk("read_byte returns %02x\n", ret);
return ret;
}
-static void doc2000_writebuf(struct mtd_info *mtd,
- const u_char *buf, int len)
+static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
int i;
- if (debug)printk("writebuf of %d bytes: ", len);
- for (i=0; i < len; i++) {
+ if (debug)
+ printk("writebuf of %d bytes: ", len);
+ for (i = 0; i < len; i++) {
WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i);
if (debug && i < 16)
printk("%02x ", buf[i]);
}
- if (debug) printk("\n");
+ if (debug)
+ printk("\n");
}
-static void doc2000_readbuf(struct mtd_info *mtd,
- u_char *buf, int len)
+static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
int i;
- if (debug)printk("readbuf of %d bytes: ", len);
+ if (debug)
+ printk("readbuf of %d bytes: ", len);
- for (i=0; i < len; i++) {
+ for (i = 0; i < len; i++) {
buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);
}
}
void __iomem *docptr = doc->virtadr;
int i;
- if (debug) printk("readbuf_dword of %d bytes: ", len);
+ if (debug)
+ printk("readbuf_dword of %d bytes: ", len);
- if (unlikely((((unsigned long)buf)|len) & 3)) {
- for (i=0; i < len; i++) {
- *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);
+ if (unlikely((((unsigned long)buf) | len) & 3)) {
+ for (i = 0; i < len; i++) {
+ *(uint8_t *) (&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);
}
} else {
- for (i=0; i < len; i+=4) {
- *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
+ for (i = 0; i < len; i += 4) {
+ *(uint32_t*) (&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
}
}
}
-static int doc2000_verifybuf(struct mtd_info *mtd,
- const u_char *buf, int len)
+static int doc2000_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
int i;
- for (i=0; i < len; i++)
+ for (i = 0; i < len; i++)
if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO))
return -EFAULT;
return 0;
uint16_t ret;
doc200x_select_chip(mtd, nr);
- doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
- this->write_byte(mtd, NAND_CMD_READID);
- doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
- doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
- this->write_byte(mtd, 0);
- doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
+ doc200x_hwcontrol(mtd, NAND_CMD_READID,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+
+ /* We cant' use dev_ready here, but at least we wait for the
+ * command to complete
+ */
+ udelay(50);
ret = this->read_byte(mtd) << 8;
ret |= this->read_byte(mtd);
} ident;
void __iomem *docptr = doc->virtadr;
- doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
- doc2000_write_byte(mtd, NAND_CMD_READID);
- doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
- doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
- doc2000_write_byte(mtd, 0);
- doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
+ doc200x_hwcontrol(mtd, NAND_CMD_READID,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ doc200x_hwcontrol(mtd, NAND_CMD_NONE,
+ NAND_NCE | NAND_CTRL_CHANGE);
+
+ udelay(50);
ident.dword = readl(docptr + DoC_2k_CDSN_IO);
if (((ident.byte[0] << 8) | ident.byte[1]) == ret) {
printk(KERN_DEBUG "Detected %d chips per floor.\n", i);
}
-static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
{
struct doc_priv *doc = this->priv;
return ReadDOC(docptr, LastDataRead);
}
-static void doc2001_writebuf(struct mtd_info *mtd,
- const u_char *buf, int len)
+static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
int i;
- for (i=0; i < len; i++)
+ for (i = 0; i < len; i++)
WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
/* Terminate write pipeline */
WriteDOC(0x00, docptr, WritePipeTerm);
}
-static void doc2001_readbuf(struct mtd_info *mtd,
- u_char *buf, int len)
+static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
/* Start read pipeline */
ReadDOC(docptr, ReadPipeInit);
- for (i=0; i < len-1; i++)
+ for (i = 0; i < len - 1; i++)
buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
/* Terminate read pipeline */
buf[i] = ReadDOC(docptr, LastDataRead);
}
-static int doc2001_verifybuf(struct mtd_info *mtd,
- const u_char *buf, int len)
+static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
/* Start read pipeline */
ReadDOC(docptr, ReadPipeInit);
- for (i=0; i < len-1; i++)
+ for (i = 0; i < len - 1; i++)
if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
ReadDOC(docptr, LastDataRead);
return i;
ReadDOC(docptr, Mplus_ReadPipeInit);
ReadDOC(docptr, Mplus_ReadPipeInit);
ret = ReadDOC(docptr, Mplus_LastDataRead);
- if (debug) printk("read_byte returns %02x\n", ret);
+ if (debug)
+ printk("read_byte returns %02x\n", ret);
return ret;
}
-static void doc2001plus_writebuf(struct mtd_info *mtd,
- const u_char *buf, int len)
+static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
int i;
- if (debug)printk("writebuf of %d bytes: ", len);
- for (i=0; i < len; i++) {
+ if (debug)
+ printk("writebuf of %d bytes: ", len);
+ for (i = 0; i < len; i++) {
WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
if (debug && i < 16)
printk("%02x ", buf[i]);
}
- if (debug) printk("\n");
+ if (debug)
+ printk("\n");
}
-static void doc2001plus_readbuf(struct mtd_info *mtd,
- u_char *buf, int len)
+static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
int i;
- if (debug)printk("readbuf of %d bytes: ", len);
+ if (debug)
+ printk("readbuf of %d bytes: ", len);
/* Start read pipeline */
ReadDOC(docptr, Mplus_ReadPipeInit);
ReadDOC(docptr, Mplus_ReadPipeInit);
- for (i=0; i < len-2; i++) {
+ for (i = 0; i < len - 2; i++) {
buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
if (debug && i < 16)
printk("%02x ", buf[i]);
}
/* Terminate read pipeline */
- buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead);
+ buf[len - 2] = ReadDOC(docptr, Mplus_LastDataRead);
if (debug && i < 16)
- printk("%02x ", buf[len-2]);
- buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead);
+ printk("%02x ", buf[len - 2]);
+ buf[len - 1] = ReadDOC(docptr, Mplus_LastDataRead);
if (debug && i < 16)
- printk("%02x ", buf[len-1]);
- if (debug) printk("\n");
+ printk("%02x ", buf[len - 1]);
+ if (debug)
+ printk("\n");
}
-static int doc2001plus_verifybuf(struct mtd_info *mtd,
- const u_char *buf, int len)
+static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
int i;
- if (debug)printk("verifybuf of %d bytes: ", len);
+ if (debug)
+ printk("verifybuf of %d bytes: ", len);
/* Start read pipeline */
ReadDOC(docptr, Mplus_ReadPipeInit);
ReadDOC(docptr, Mplus_ReadPipeInit);
- for (i=0; i < len-2; i++)
+ for (i = 0; i < len - 2; i++)
if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
ReadDOC(docptr, Mplus_LastDataRead);
ReadDOC(docptr, Mplus_LastDataRead);
return i;
}
- if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead))
- return len-2;
- if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead))
- return len-1;
+ if (buf[len - 2] != ReadDOC(docptr, Mplus_LastDataRead))
+ return len - 2;
+ if (buf[len - 1] != ReadDOC(docptr, Mplus_LastDataRead))
+ return len - 1;
return 0;
}
void __iomem *docptr = doc->virtadr;
int floor = 0;
- if(debug)printk("select chip (%d)\n", chip);
+ if (debug)
+ printk("select chip (%d)\n", chip);
if (chip == -1) {
/* Disable flash internally */
}
floor = chip / doc->chips_per_floor;
- chip -= (floor * doc->chips_per_floor);
+ chip -= (floor * doc->chips_per_floor);
/* Assert ChipEnable and deassert WriteProtect */
WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
void __iomem *docptr = doc->virtadr;
int floor = 0;
- if(debug)printk("select chip (%d)\n", chip);
+ if (debug)
+ printk("select chip (%d)\n", chip);
if (chip == -1)
return;
floor = chip / doc->chips_per_floor;
- chip -= (floor * doc->chips_per_floor);
+ chip -= (floor * doc->chips_per_floor);
/* 11.4.4 -- deassert CE before changing chip */
- doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE);
+ doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
WriteDOC(floor, docptr, FloorSelect);
WriteDOC(chip, docptr, CDSNDeviceSelect);
- doc200x_hwcontrol(mtd, NAND_CTL_SETNCE);
+ doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
doc->curchip = chip;
doc->curfloor = floor;
}
-static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
+#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
+
+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
- switch(cmd) {
- case NAND_CTL_SETNCE:
- doc->CDSNControl |= CDSN_CTRL_CE;
- break;
- case NAND_CTL_CLRNCE:
- doc->CDSNControl &= ~CDSN_CTRL_CE;
- break;
- case NAND_CTL_SETCLE:
- doc->CDSNControl |= CDSN_CTRL_CLE;
- break;
- case NAND_CTL_CLRCLE:
- doc->CDSNControl &= ~CDSN_CTRL_CLE;
- break;
- case NAND_CTL_SETALE:
- doc->CDSNControl |= CDSN_CTRL_ALE;
- break;
- case NAND_CTL_CLRALE:
- doc->CDSNControl &= ~CDSN_CTRL_ALE;
- break;
- case NAND_CTL_SETWP:
- doc->CDSNControl |= CDSN_CTRL_WP;
- break;
- case NAND_CTL_CLRWP:
- doc->CDSNControl &= ~CDSN_CTRL_WP;
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ doc->CDSNControl &= ~CDSN_CTRL_MSK;
+ doc->CDSNControl |= ctrl & CDSN_CTRL_MSK;
+ if (debug)
+ printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
+ WriteDOC(doc->CDSNControl, docptr, CDSNControl);
+ /* 11.4.3 -- 4 NOPs after CSDNControl write */
+ DoC_Delay(doc, 4);
+ }
+ if (cmd != NAND_CMD_NONE) {
+ if (DoC_is_2000(doc))
+ doc2000_write_byte(mtd, cmd);
+ else
+ doc2001_write_byte(mtd, cmd);
}
- if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
- WriteDOC(doc->CDSNControl, docptr, CDSNControl);
- /* 11.4.3 -- 4 NOPs after CSDNControl write */
- DoC_Delay(doc, 4);
}
-static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
if (command == NAND_CMD_SEQIN) {
int readcmd;
- if (column >= mtd->oobblock) {
+ if (column >= mtd->writesize) {
/* OOB area */
- column -= mtd->oobblock;
+ column -= mtd->writesize;
readcmd = NAND_CMD_READOOB;
} else if (column < 256) {
/* First 256 bytes --> READ0 */
WriteDOC(column, docptr, Mplus_FlashAddress);
}
if (page_addr != -1) {
- WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress);
- WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress);
+ WriteDOC((unsigned char)(page_addr & 0xff), docptr, Mplus_FlashAddress);
+ WriteDOC((unsigned char)((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress);
/* One more address cycle for higher density devices */
if (this->chipsize & 0x0c000000) {
- WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress);
+ WriteDOC((unsigned char)((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress);
printk("high density\n");
}
}
WriteDOC(0, docptr, Mplus_WritePipeTerm);
WriteDOC(0, docptr, Mplus_WritePipeTerm);
/* deassert ALE */
- if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID)
+ if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
+ command == NAND_CMD_READOOB || command == NAND_CMD_READID)
WriteDOC(0, docptr, Mplus_FlashControl);
}
/*
* program and erase have their own busy handlers
* status and sequential in needs no delay
- */
+ */
switch (command) {
case NAND_CMD_PAGEPROG:
WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd);
WriteDOC(0, docptr, Mplus_WritePipeTerm);
WriteDOC(0, docptr, Mplus_WritePipeTerm);
- while ( !(this->read_byte(mtd) & 0x40));
+ while (!(this->read_byte(mtd) & 0x40)) ;
return;
- /* This applies to read commands */
+ /* This applies to read commands */
default:
/*
* If we don't have access to the busy pin, we apply the given
* command delay
- */
+ */
if (!this->dev_ready) {
- udelay (this->chip_delay);
+ udelay(this->chip_delay);
return;
}
}
/* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine. */
- ndelay (100);
+ ndelay(100);
/* wait until command is processed */
- while (!this->dev_ready(mtd));
+ while (!this->dev_ready(mtd)) ;
}
static int doc200x_dev_ready(struct mtd_info *mtd)
/* 11.4.2 -- must NOP four times before checking FR/B# */
DoC_Delay(doc, 4);
if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
- if(debug)
+ if (debug)
printk("not ready\n");
return 0;
}
- if (debug)printk("was ready\n");
+ if (debug)
+ printk("was ready\n");
return 1;
} else {
/* 11.4.2 -- must NOP four times before checking FR/B# */
DoC_Delay(doc, 4);
if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
- if(debug)
+ if (debug)
printk("not ready\n");
return 0;
}
/* 11.4.2 -- Must NOP twice if it's ready */
DoC_Delay(doc, 2);
- if (debug)printk("was ready\n");
+ if (debug)
+ printk("was ready\n");
return 1;
}
}
void __iomem *docptr = doc->virtadr;
/* Prime the ECC engine */
- switch(mode) {
+ switch (mode) {
case NAND_ECC_READ:
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
WriteDOC(DOC_ECC_EN, docptr, ECCConf);
void __iomem *docptr = doc->virtadr;
/* Prime the ECC engine */
- switch(mode) {
+ switch (mode) {
case NAND_ECC_READ:
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
}
/* This code is only called on write */
-static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- unsigned char *ecc_code)
+static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
often. It could be optimized away by examining the data in
the writebuf routine, and remembering the result. */
for (i = 0; i < 512; i++) {
- if (dat[i] == 0xff) continue;
+ if (dat[i] == 0xff)
+ continue;
emptymatch = 0;
break;
}
/* If emptymatch still =1, we do have an all-0xff data buffer.
Return all-0xff ecc value instead of the computed one, so
it'll look just like a freshly-erased page. */
- if (emptymatch) memset(ecc_code, 0xff, 6);
+ if (emptymatch)
+ memset(ecc_code, 0xff, 6);
#endif
return 0;
}
-static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
+ u_char *read_ecc, u_char *isnull)
{
int i, ret = 0;
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
+ uint8_t calc_ecc[6];
volatile u_char dummy;
int emptymatch = 1;
all-0xff data and stored ecc block. Check the stored ecc. */
if (emptymatch) {
for (i = 0; i < 6; i++) {
- if (read_ecc[i] == 0xff) continue;
+ if (read_ecc[i] == 0xff)
+ continue;
emptymatch = 0;
break;
}
}
/* If emptymatch still =1, check the data block. */
if (emptymatch) {
- /* Note: this somewhat expensive test should not be triggered
- often. It could be optimized away by examining the data in
- the readbuf routine, and remembering the result. */
+ /* Note: this somewhat expensive test should not be triggered
+ often. It could be optimized away by examining the data in
+ the readbuf routine, and remembering the result. */
for (i = 0; i < 512; i++) {
- if (dat[i] == 0xff) continue;
+ if (dat[i] == 0xff)
+ continue;
emptymatch = 0;
break;
}
erased block, in which case the ECC will not come out right.
We'll suppress the error and tell the caller everything's
OK. Because it is. */
- if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc);
+ if (!emptymatch)
+ ret = doc_ecc_decode(rs_decoder, dat, calc_ecc);
if (ret > 0)
printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
}
/*u_char mydatabuf[528]; */
-static struct nand_oobinfo doc200x_oobinfo = {
- .useecc = MTD_NANDECC_AUTOPLACE,
+/* The strange out-of-order .oobfree list below is a (possibly unneeded)
+ * attempt to retain compatibility. It used to read:
+ * .oobfree = { {8, 8} }
+ * Since that leaves two bytes unusable, it was changed. But the following
+ * scheme might affect existing jffs2 installs by moving the cleanmarker:
+ * .oobfree = { {6, 10} }
+ * jffs2 seems to handle the above gracefully, but the current scheme seems
+ * safer. The only problem with it is that any code that parses oobfree must
+ * be able to handle out-of-order segments.
+ */
+static struct nand_ecclayout doc200x_oobinfo = {
.eccbytes = 6,
.eccpos = {0, 1, 2, 3, 4, 5},
- .oobfree = { {8, 8} }
+ .oobfree = {{8, 8}, {6, 2}}
};
/* Find the (I)NFTL Media Header, and optionally also the mirror media header.
either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media
header. The page #s of the found media headers are placed in mh0_page and
mh1_page in the DOC private structure. */
-static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
- const char *id, int findmirror)
+static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
- unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift);
+ unsigned offs;
int ret;
size_t retlen;
- end = min(end, mtd->size); /* paranoia */
- for (offs = 0; offs < end; offs += mtd->erasesize) {
- ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
- if (retlen != mtd->oobblock) continue;
+ for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
+ ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
+ if (retlen != mtd->writesize)
+ continue;
if (ret) {
- printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n",
- offs);
+ printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", offs);
}
- if (memcmp(buf, id, 6)) continue;
+ if (memcmp(buf, id, 6))
+ continue;
printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs);
if (doc->mh0_page == -1) {
doc->mh0_page = offs >> this->page_shift;
- if (!findmirror) return 1;
+ if (!findmirror)
+ return 1;
continue;
}
doc->mh1_page = offs >> this->page_shift;
/* Only one mediaheader was found. We want buf to contain a
mediaheader on return, so we'll have to re-read the one we found. */
offs = doc->mh0_page << this->page_shift;
- ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
- if (retlen != mtd->oobblock) {
+ ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
+ if (retlen != mtd->writesize) {
/* Insanity. Give up. */
printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");
return 0;
return 1;
}
-static inline int __init nftl_partscan(struct mtd_info *mtd,
- struct mtd_partition *parts)
+static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
u_char *buf;
struct NFTLMediaHeader *mh;
const unsigned psize = 1 << this->page_shift;
+ int numparts = 0;
unsigned blocks, maxblocks;
int offs, numheaders;
- buf = kmalloc(mtd->oobblock, GFP_KERNEL);
+ buf = kmalloc(mtd->writesize, GFP_KERNEL);
if (!buf) {
printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
return 0;
}
- if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;
- mh = (struct NFTLMediaHeader *) buf;
+ if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1)))
+ goto out;
+ mh = (struct NFTLMediaHeader *)buf;
+
+ mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits);
+ mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN);
+ mh->FormattedSize = le32_to_cpu(mh->FormattedSize);
-/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
-/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
printk(KERN_INFO " DataOrgID = %s\n"
" NumEraseUnits = %d\n"
" FirstPhysicalEUN = %d\n"
mh->DataOrgID, mh->NumEraseUnits,
mh->FirstPhysicalEUN, mh->FormattedSize,
mh->UnitSizeFactor);
-/*#endif */
blocks = mtd->size >> this->phys_erase_shift;
maxblocks = min(32768U, mtd->erasesize - psize);
/* Auto-determine UnitSizeFactor. The constraints are:
- There can be at most 32768 virtual blocks.
- There can be at most (virtual block size - page size)
- virtual blocks (because MediaHeader+BBT must fit in 1).
- */
+ virtual blocks (because MediaHeader+BBT must fit in 1).
+ */
mh->UnitSizeFactor = 0xff;
while (blocks > maxblocks) {
blocks >>= 1;
offs <<= this->page_shift;
offs += mtd->erasesize;
- /*parts[0].name = " DiskOnChip Boot / Media Header partition"; */
- /*parts[0].offset = 0; */
- /*parts[0].size = offs; */
+ if (show_firmware_partition == 1) {
+ parts[0].name = " DiskOnChip Firmware / Media Header partition";
+ parts[0].offset = 0;
+ parts[0].size = offs;
+ numparts = 1;
+ }
+
+ parts[numparts].name = " DiskOnChip BDTL partition";
+ parts[numparts].offset = offs;
+ parts[numparts].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift;
- parts[0].name = " DiskOnChip BDTL partition";
- parts[0].offset = offs;
- parts[0].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift;
+ offs += parts[numparts].size;
+ numparts++;
- offs += parts[0].size;
if (offs < mtd->size) {
- parts[1].name = " DiskOnChip Remainder partition";
- parts[1].offset = offs;
- parts[1].size = mtd->size - offs;
- ret = 2;
- goto out;
+ parts[numparts].name = " DiskOnChip Remainder partition";
+ parts[numparts].offset = offs;
+ parts[numparts].size = mtd->size - offs;
+ numparts++;
}
- ret = 1;
-out:
+
+ ret = numparts;
+ out:
kfree(buf);
return ret;
}
/* This is a stripped-down copy of the code in inftlmount.c */
-static inline int __init inftl_partscan(struct mtd_info *mtd,
- struct mtd_partition *parts)
+static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
if (inftl_bbt_write)
end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift);
- buf = kmalloc(mtd->oobblock, GFP_KERNEL);
+ buf = kmalloc(mtd->writesize, GFP_KERNEL);
if (!buf) {
printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
return 0;
}
- if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out;
+ if (!find_media_headers(mtd, buf, "BNAND", 0))
+ goto out;
doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift);
- mh = (struct INFTLMediaHeader *) buf;
+ mh = (struct INFTLMediaHeader *)buf;
mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
-/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
-/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
printk(KERN_INFO " bootRecordID = %s\n"
" NoOfBootImageBlocks = %d\n"
" NoOfBinaryPartitions = %d\n"
((unsigned char *) &mh->OsakVersion)[2] & 0xf,
((unsigned char *) &mh->OsakVersion)[3] & 0xf,
mh->PercentUsed);
-/*#endif */
vshift = this->phys_erase_shift + mh->BlockMultiplierBits;
ip->spareUnits = le32_to_cpu(ip->spareUnits);
ip->Reserved0 = le32_to_cpu(ip->Reserved0);
-/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */
-/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */
printk(KERN_INFO " PARTITION[%d] ->\n"
" virtualUnits = %d\n"
" firstUnit = %d\n"
i, ip->virtualUnits, ip->firstUnit,
ip->lastUnit, ip->flags,
ip->spareUnits);
-/*#endif */
-/*
- if ((i == 0) && (ip->firstUnit > 0)) {
+ if ((show_firmware_partition == 1) &&
+ (i == 0) && (ip->firstUnit > 0)) {
parts[0].name = " DiskOnChip IPL / Media Header partition";
parts[0].offset = 0;
parts[0].size = mtd->erasesize * ip->firstUnit;
numparts = 1;
}
-*/
if (ip->flags & INFTL_BINARY)
parts[numparts].name = " DiskOnChip BDK partition";
parts[numparts].offset = ip->firstUnit << vshift;
parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift;
numparts++;
- if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit;
- if (ip->flags & INFTL_LAST) break;
+ if (ip->lastUnit > lastvunit)
+ lastvunit = ip->lastUnit;
+ if (ip->flags & INFTL_LAST)
+ break;
}
lastvunit++;
if ((lastvunit << vshift) < end) {
numparts++;
}
ret = numparts;
-out:
+ out:
kfree(buf);
return ret;
}
struct doc_priv *doc = this->priv;
struct mtd_partition parts[2];
- memset((char *) parts, 0, sizeof(parts));
+ memset((char *)parts, 0, sizeof(parts));
/* On NFTL, we have to find the media headers before we can read the
BBTs, since they're stored in the media header eraseblocks. */
numparts = nftl_partscan(mtd, parts);
- if (!numparts) return -EIO;
+ if (!numparts)
+ return -EIO;
this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
NAND_BBT_VERSION;
this->bbt_td->pages[0] = 2;
this->bbt_md = NULL;
} else {
- this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
- NAND_BBT_VERSION;
+ this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION;
if (inftl_bbt_write)
this->bbt_td->options |= NAND_BBT_WRITE;
this->bbt_td->offs = 8;
this->bbt_td->reserved_block_code = 0x01;
this->bbt_td->pattern = "MSYS_BBT";
- this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
- NAND_BBT_VERSION;
+ this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION;
if (inftl_bbt_write)
this->bbt_md->options |= NAND_BBT_WRITE;
this->bbt_md->offs = 8;
At least as nand_bbt.c is currently written. */
if ((ret = nand_scan_bbt(mtd, NULL)))
return ret;
- memset((char *) parts, 0, sizeof(parts));
+ memset((char *)parts, 0, sizeof(parts));
numparts = inftl_partscan(mtd, parts);
/* At least for now, require the INFTL Media Header. We could probably
do without it for non-INFTL use, since all it gives us is
autopartitioning, but I want to give it more thought. */
- if (!numparts) return -EIO;
+ if (!numparts)
+ return -EIO;
add_mtd_device(mtd);
#ifdef CONFIG_MTD_PARTITIONS
if (!no_autopart)
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
- this->write_byte = doc2000_write_byte;
this->read_byte = doc2000_read_byte;
this->write_buf = doc2000_writebuf;
this->read_buf = doc2000_readbuf;
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
- this->write_byte = doc2001_write_byte;
this->read_byte = doc2001_read_byte;
this->write_buf = doc2001_writebuf;
this->read_buf = doc2001_readbuf;
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
- this->write_byte = NULL;
this->read_byte = doc2001plus_read_byte;
this->write_buf = doc2001plus_writebuf;
this->read_buf = doc2001plus_readbuf;
this->verify_buf = doc2001plus_verifybuf;
this->scan_bbt = inftl_scan_bbt;
- this->hwcontrol = NULL;
+ this->cmd_ctrl = NULL;
this->select_chip = doc2001plus_select_chip;
this->cmdfunc = doc2001plus_command;
- this->enable_hwecc = doc2001plus_enable_hwecc;
+ this->ecc.hwctl = doc2001plus_enable_hwecc;
doc->chips_per_floor = 1;
mtd->name = "DiskOnChip Millennium Plus";
return 1;
}
-static inline int __init doc_probe(unsigned long physadr)
+static int __init doc_probe(unsigned long physadr)
{
unsigned char ChipID;
struct mtd_info *mtd;
save_control = ReadDOC(virtadr, DOCControl);
/* Reset the DiskOnChip ASIC */
- WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
- virtadr, DOCControl);
- WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
- virtadr, DOCControl);
+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl);
+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl);
/* Enable the DiskOnChip ASIC */
- WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
- virtadr, DOCControl);
- WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
- virtadr, DOCControl);
+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl);
+ WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl);
ChipID = ReadDOC(virtadr, ChipID);
- switch(ChipID) {
+ switch (ChipID) {
case DOC_ChipID_Doc2k:
reg = DoC_2k_ECCStatus;
break;
ReadDOC(virtadr, Mplus_Power);
/* Reset the Millennium Plus ASIC */
- tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
- DOC_MODE_BDECT;
+ tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT;
WriteDOC(tmp, virtadr, Mplus_DOCControl);
WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
mdelay(1);
/* Enable the Millennium Plus ASIC */
- tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
- DOC_MODE_BDECT;
+ tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT;
WriteDOC(tmp, virtadr, Mplus_DOCControl);
WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
mdelay(1);
goto notfound;
}
/* Check the TOGGLE bit in the ECC register */
- tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
+ tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
if ((tmp == tmpb) || (tmp != tmpc)) {
if (ChipID == DOC_ChipID_DocMilPlus16) {
WriteDOC(~newval, virtadr, Mplus_AliasResolution);
oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
- WriteDOC(newval, virtadr, Mplus_AliasResolution); /* restore it */
+ WriteDOC(newval, virtadr, Mplus_AliasResolution); /* restore it */
} else {
WriteDOC(~newval, virtadr, AliasResolution);
oldval = ReadDOC(doc->virtadr, AliasResolution);
- WriteDOC(newval, virtadr, AliasResolution); /* restore it */
+ WriteDOC(newval, virtadr, AliasResolution); /* restore it */
}
newval = ~newval;
if (oldval == newval) {
printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr);
len = sizeof(struct mtd_info) +
- sizeof(struct nand_chip) +
- sizeof(struct doc_priv) +
- (2 * sizeof(struct nand_bbt_descr));
- mtd = kmalloc(len, GFP_KERNEL);
+ sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
+ mtd = kzalloc(len, GFP_KERNEL);
if (!mtd) {
printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
ret = -ENOMEM;
goto fail;
}
- memset(mtd, 0, len);
nand = (struct nand_chip *) (mtd + 1);
doc = (struct doc_priv *) (nand + 1);
nand->priv = doc;
nand->select_chip = doc200x_select_chip;
- nand->hwcontrol = doc200x_hwcontrol;
+ nand->cmd_ctrl = doc200x_hwcontrol;
nand->dev_ready = doc200x_dev_ready;
nand->waitfunc = doc200x_wait;
nand->block_bad = doc200x_block_bad;
- nand->enable_hwecc = doc200x_enable_hwecc;
- nand->calculate_ecc = doc200x_calculate_ecc;
- nand->correct_data = doc200x_correct_data;
+ nand->ecc.hwctl = doc200x_enable_hwecc;
+ nand->ecc.calculate = doc200x_calculate_ecc;
+ nand->ecc.correct = doc200x_correct_data;
- nand->autooob = &doc200x_oobinfo;
- nand->eccmode = NAND_ECC_HW6_512;
- nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
+ nand->ecc.layout = &doc200x_oobinfo;
+ nand->ecc.mode = NAND_ECC_HW_SYNDROME;
+ nand->ecc.size = 512;
+ nand->ecc.bytes = 6;
+ nand->options = NAND_USE_FLASH_BBT;
doc->physadr = physadr;
doc->virtadr = virtadr;
doclist = mtd;
return 0;
-notfound:
+ notfound:
/* Put back the contents of the DOCControl register, in case it's not
actually a DiskOnChip. */
WriteDOC(save_control, virtadr, DOCControl);
-fail:
+ fail:
iounmap(virtadr);
return ret;
}
*/
rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS);
if (!rs_decoder) {
- printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n");
+ printk(KERN_ERR "DiskOnChip: Could not create a RS decoder\n");
return -ENOMEM;
}
if (ret < 0)
goto outerr;
} else {
- for (i=0; (doc_locations[i] != 0xffffffff); i++) {
+ for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
doc_probe(doc_locations[i]);
}
}
goto outerr;
}
return 0;
-outerr:
+ outerr:
free_rs(rs_decoder);
return ret;
}
--- /dev/null
+/* Freescale Enhanced Local Bus Controller FCM NAND driver
+ *
+ * Copyright (c) 2006-2008 Freescale Semiconductor
+ *
+ * Authors: Nick Spence <nick.spence@freescale.com>,
+ * Scott Wood <scottwood@freescale.com>
+ *
+ * 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 <malloc.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#ifdef VERBOSE_DEBUG
+#define DEBUG_ELBC
+#define vdbg(format, arg...) printf("DEBUG: " format, ##arg)
+#else
+#define vdbg(format, arg...) do {} while (0)
+#endif
+
+/* Can't use plain old DEBUG because the linux mtd
+ * headers define it as a macro.
+ */
+#ifdef DEBUG_ELBC
+#define dbg(format, arg...) printf("DEBUG: " format, ##arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+
+#define MAX_BANKS 8
+#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
+#define FCM_TIMEOUT_MSECS 10 /* Maximum number of mSecs to wait for FCM */
+
+#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+
+struct fsl_elbc_ctrl;
+
+/* mtd information per set */
+
+struct fsl_elbc_mtd {
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ struct fsl_elbc_ctrl *ctrl;
+
+ struct device *dev;
+ int bank; /* Chip select bank number */
+ u8 __iomem *vbase; /* Chip select base virtual address */
+ int page_size; /* NAND page size (0=512, 1=2048) */
+ unsigned int fmr; /* FCM Flash Mode Register value */
+};
+
+/* overview of the fsl elbc controller */
+
+struct fsl_elbc_ctrl {
+ struct nand_hw_control controller;
+ struct fsl_elbc_mtd *chips[MAX_BANKS];
+
+ /* device info */
+ lbus83xx_t *regs;
+ u8 __iomem *addr; /* Address of assigned FCM buffer */
+ unsigned int page; /* Last page written to / read from */
+ unsigned int read_bytes; /* Number of bytes read during command */
+ unsigned int column; /* Saved column from SEQIN */
+ unsigned int index; /* Pointer to next byte to 'read' */
+ unsigned int status; /* status read from LTESR after last op */
+ unsigned int mdr; /* UPM/FCM Data Register value */
+ unsigned int use_mdr; /* Non zero if the MDR is to be set */
+ unsigned int oob; /* Non zero if operating on OOB data */
+ uint8_t *oob_poi; /* Place to write ECC after read back */
+};
+
+/* These map to the positions used by the FCM hardware ECC generator */
+
+/* Small Page FLASH with FMR[ECCM] = 0 */
+static struct nand_ecclayout fsl_elbc_oob_sp_eccm0 = {
+ .eccbytes = 3,
+ .eccpos = {6, 7, 8},
+ .oobfree = { {0, 5}, {9, 7} },
+ .oobavail = 12,
+};
+
+/* Small Page FLASH with FMR[ECCM] = 1 */
+static struct nand_ecclayout fsl_elbc_oob_sp_eccm1 = {
+ .eccbytes = 3,
+ .eccpos = {8, 9, 10},
+ .oobfree = { {0, 5}, {6, 2}, {11, 5} },
+ .oobavail = 12,
+};
+
+/* Large Page FLASH with FMR[ECCM] = 0 */
+static struct nand_ecclayout fsl_elbc_oob_lp_eccm0 = {
+ .eccbytes = 12,
+ .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56},
+ .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} },
+ .oobavail = 48,
+};
+
+/* Large Page FLASH with FMR[ECCM] = 1 */
+static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {
+ .eccbytes = 12,
+ .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
+ .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} },
+ .oobavail = 48,
+};
+
+/*=================================*/
+
+/*
+ * Set up the FCM hardware block and page address fields, and the fcm
+ * structure addr field to point to the correct FCM buffer in memory
+ */
+static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ lbus83xx_t *lbc = ctrl->regs;
+ int buf_num;
+
+ ctrl->page = page_addr;
+
+ if (priv->page_size) {
+ out_be32(&lbc->fbar, page_addr >> 6);
+ out_be32(&lbc->fpar,
+ ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
+ (oob ? FPAR_LP_MS : 0) | column);
+ buf_num = (page_addr & 1) << 2;
+ } else {
+ out_be32(&lbc->fbar, page_addr >> 5);
+ out_be32(&lbc->fpar,
+ ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
+ (oob ? FPAR_SP_MS : 0) | column);
+ buf_num = page_addr & 7;
+ }
+
+ ctrl->addr = priv->vbase + buf_num * 1024;
+ ctrl->index = column;
+
+ /* for OOB data point to the second half of the buffer */
+ if (oob)
+ ctrl->index += priv->page_size ? 2048 : 512;
+
+ vdbg("set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
+ "index %x, pes %d ps %d\n",
+ buf_num, ctrl->addr, priv->vbase, ctrl->index,
+ chip->phys_erase_shift, chip->page_shift);
+}
+
+/*
+ * execute FCM command and wait for it to complete
+ */
+static int fsl_elbc_run_command(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ lbus83xx_t *lbc = ctrl->regs;
+ long long end_tick;
+ u32 ltesr;
+
+ /* Setup the FMR[OP] to execute without write protection */
+ out_be32(&lbc->fmr, priv->fmr | 3);
+ if (ctrl->use_mdr)
+ out_be32(&lbc->mdr, ctrl->mdr);
+
+ vdbg("fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
+ in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
+ vdbg("fsl_elbc_run_command: fbar=%08x fpar=%08x "
+ "fbcr=%08x bank=%d\n",
+ in_be32(&lbc->fbar), in_be32(&lbc->fpar),
+ in_be32(&lbc->fbcr), priv->bank);
+
+ /* execute special operation */
+ out_be32(&lbc->lsor, priv->bank);
+
+ /* wait for FCM complete flag or timeout */
+ end_tick = usec2ticks(FCM_TIMEOUT_MSECS * 1000) + get_ticks();
+
+ ltesr = 0;
+ while (end_tick > get_ticks()) {
+ ltesr = in_be32(&lbc->ltesr);
+ if (ltesr & LTESR_CC)
+ break;
+ }
+
+ ctrl->status = ltesr & LTESR_NAND_MASK;
+ out_be32(&lbc->ltesr, ctrl->status);
+ out_be32(&lbc->lteatr, 0);
+
+ /* store mdr value in case it was needed */
+ if (ctrl->use_mdr)
+ ctrl->mdr = in_be32(&lbc->mdr);
+
+ ctrl->use_mdr = 0;
+
+ vdbg("fsl_elbc_run_command: stat=%08x mdr=%08x fmr=%08x\n",
+ ctrl->status, ctrl->mdr, in_be32(&lbc->fmr));
+
+ /* returns 0 on success otherwise non-zero) */
+ return ctrl->status == LTESR_CC ? 0 : -EIO;
+}
+
+static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
+{
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ lbus83xx_t *lbc = ctrl->regs;
+
+ if (priv->page_size) {
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+ (FIR_OP_RBW << FIR_OP4_SHIFT));
+
+ out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
+ (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
+ } else {
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_RBW << FIR_OP3_SHIFT));
+
+ if (oob)
+ out_be32(&lbc->fcr,
+ NAND_CMD_READOOB << FCR_CMD0_SHIFT);
+ else
+ out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
+ }
+}
+
+/* cmdfunc send commands to the FCM */
+static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+ int column, int page_addr)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ lbus83xx_t *lbc = ctrl->regs;
+
+ ctrl->use_mdr = 0;
+
+ /* clear the read buffer */
+ ctrl->read_bytes = 0;
+ if (command != NAND_CMD_PAGEPROG)
+ ctrl->index = 0;
+
+ switch (command) {
+ /* READ0 and READ1 read the entire buffer to use hardware ECC. */
+ case NAND_CMD_READ1:
+ column += 256;
+
+ /* fall-through */
+ case NAND_CMD_READ0:
+ vdbg("fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
+ " 0x%x, column: 0x%x.\n", page_addr, column);
+
+ out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
+ set_addr(mtd, 0, page_addr, 0);
+
+ ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+ ctrl->index += column;
+
+ fsl_elbc_do_read(chip, 0);
+ fsl_elbc_run_command(mtd);
+ return;
+
+ /* READOOB reads only the OOB because no ECC is performed. */
+ case NAND_CMD_READOOB:
+ vdbg("fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
+ " 0x%x, column: 0x%x.\n", page_addr, column);
+
+ out_be32(&lbc->fbcr, mtd->oobsize - column);
+ set_addr(mtd, column, page_addr, 1);
+
+ ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+
+ fsl_elbc_do_read(chip, 1);
+ fsl_elbc_run_command(mtd);
+
+ return;
+
+ /* READID must read all 5 possible bytes while CEB is active */
+ case NAND_CMD_READID:
+ vdbg("fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+
+ out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_UA << FIR_OP1_SHIFT) |
+ (FIR_OP_RBW << FIR_OP2_SHIFT));
+ out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
+ /* 5 bytes for manuf, device and exts */
+ out_be32(&lbc->fbcr, 5);
+ ctrl->read_bytes = 5;
+ ctrl->use_mdr = 1;
+ ctrl->mdr = 0;
+
+ set_addr(mtd, 0, 0, 0);
+ fsl_elbc_run_command(mtd);
+ return;
+
+ /* ERASE1 stores the block and page address */
+ case NAND_CMD_ERASE1:
+ vdbg("fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
+ "page_addr: 0x%x.\n", page_addr);
+ set_addr(mtd, 0, page_addr, 0);
+ return;
+
+ /* ERASE2 uses the block and page address from ERASE1 */
+ case NAND_CMD_ERASE2:
+ vdbg("fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_PA << FIR_OP1_SHIFT) |
+ (FIR_OP_CM1 << FIR_OP2_SHIFT));
+
+ out_be32(&lbc->fcr,
+ (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
+ (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
+
+ out_be32(&lbc->fbcr, 0);
+ ctrl->read_bytes = 0;
+
+ fsl_elbc_run_command(mtd);
+ return;
+
+ /* SEQIN sets up the addr buffer and all registers except the length */
+ case NAND_CMD_SEQIN: {
+ u32 fcr;
+ vdbg("fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
+ "page_addr: 0x%x, column: 0x%x.\n",
+ page_addr, column);
+
+ ctrl->column = column;
+ ctrl->oob = 0;
+
+ if (priv->page_size) {
+ fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
+ (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
+
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_WB << FIR_OP3_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP4_SHIFT));
+ } else {
+ fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
+ (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
+
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM2 << FIR_OP1_SHIFT) |
+ (FIR_OP_CA << FIR_OP2_SHIFT) |
+ (FIR_OP_PA << FIR_OP3_SHIFT) |
+ (FIR_OP_WB << FIR_OP4_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP5_SHIFT));
+
+ if (column >= mtd->writesize) {
+ /* OOB area --> READOOB */
+ column -= mtd->writesize;
+ fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
+ ctrl->oob = 1;
+ } else if (column < 256) {
+ /* First 256 bytes --> READ0 */
+ fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
+ } else {
+ /* Second 256 bytes --> READ1 */
+ fcr |= NAND_CMD_READ1 << FCR_CMD0_SHIFT;
+ }
+ }
+
+ out_be32(&lbc->fcr, fcr);
+ set_addr(mtd, column, page_addr, ctrl->oob);
+ return;
+ }
+
+ /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
+ case NAND_CMD_PAGEPROG: {
+ int full_page;
+ vdbg("fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
+ "writing %d bytes.\n", ctrl->index);
+
+ /* if the write did not start at 0 or is not a full page
+ * then set the exact length, otherwise use a full page
+ * write so the HW generates the ECC.
+ */
+ if (ctrl->oob || ctrl->column != 0 ||
+ ctrl->index != mtd->writesize + mtd->oobsize) {
+ out_be32(&lbc->fbcr, ctrl->index);
+ full_page = 0;
+ } else {
+ out_be32(&lbc->fbcr, 0);
+ full_page = 1;
+ }
+
+ fsl_elbc_run_command(mtd);
+
+ /* Read back the page in order to fill in the ECC for the
+ * caller. Is this really needed?
+ */
+ if (full_page && ctrl->oob_poi) {
+ out_be32(&lbc->fbcr, 3);
+ set_addr(mtd, 6, page_addr, 1);
+
+ ctrl->read_bytes = mtd->writesize + 9;
+
+ fsl_elbc_do_read(chip, 1);
+ fsl_elbc_run_command(mtd);
+
+ memcpy_fromio(ctrl->oob_poi + 6,
+ &ctrl->addr[ctrl->index], 3);
+ ctrl->index += 3;
+ }
+
+ ctrl->oob_poi = NULL;
+ return;
+ }
+
+ /* CMD_STATUS must read the status byte while CEB is active */
+ /* Note - it does not wait for the ready line */
+ case NAND_CMD_STATUS:
+ out_be32(&lbc->fir,
+ (FIR_OP_CM0 << FIR_OP0_SHIFT) |
+ (FIR_OP_RBW << FIR_OP1_SHIFT));
+ out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
+ out_be32(&lbc->fbcr, 1);
+ set_addr(mtd, 0, 0, 0);
+ ctrl->read_bytes = 1;
+
+ fsl_elbc_run_command(mtd);
+
+ /* The chip always seems to report that it is
+ * write-protected, even when it is not.
+ */
+ out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
+ return;
+
+ /* RESET without waiting for the ready line */
+ case NAND_CMD_RESET:
+ dbg("fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
+ out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
+ out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
+ fsl_elbc_run_command(mtd);
+ return;
+
+ default:
+ printf("fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
+ command);
+ }
+}
+
+static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
+{
+ /* The hardware does not seem to support multiple
+ * chips per bank.
+ */
+}
+
+/*
+ * Write buf to the FCM Controller Data Buffer
+ */
+static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ unsigned int bufsize = mtd->writesize + mtd->oobsize;
+
+ if (len <= 0) {
+ printf("write_buf of %d bytes", len);
+ ctrl->status = 0;
+ return;
+ }
+
+ if ((unsigned int)len > bufsize - ctrl->index) {
+ printf("write_buf beyond end of buffer "
+ "(%d requested, %u available)\n",
+ len, bufsize - ctrl->index);
+ len = bufsize - ctrl->index;
+ }
+
+ memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+ /*
+ * This is workaround for the weird elbc hangs during nand write,
+ * Scott Wood says: "...perhaps difference in how long it takes a
+ * write to make it through the localbus compared to a write to IMMR
+ * is causing problems, and sync isn't helping for some reason."
+ * Reading back the last byte helps though.
+ */
+ in_8(&ctrl->addr[ctrl->index] + len - 1);
+
+ ctrl->index += len;
+}
+
+/*
+ * read a byte from either the FCM hardware buffer if it has any data left
+ * otherwise issue a command to read a single byte.
+ */
+static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+
+ /* If there are still bytes in the FCM, then use the next byte. */
+ if (ctrl->index < ctrl->read_bytes)
+ return in_8(&ctrl->addr[ctrl->index++]);
+
+ printf("read_byte beyond end of buffer\n");
+ return ERR_BYTE;
+}
+
+/*
+ * Read from the FCM Controller Data Buffer
+ */
+static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ int avail;
+
+ if (len < 0)
+ return;
+
+ avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
+ memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
+ ctrl->index += avail;
+
+ if (len > avail)
+ printf("read_buf beyond end of buffer "
+ "(%d requested, %d available)\n",
+ len, avail);
+}
+
+/*
+ * Verify buffer against the FCM Controller Data Buffer
+ */
+static int fsl_elbc_verify_buf(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ int i;
+
+ if (len < 0) {
+ printf("write_buf of %d bytes", len);
+ return -EINVAL;
+ }
+
+ if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
+ printf("verify_buf beyond end of buffer "
+ "(%d requested, %u available)\n",
+ len, ctrl->read_bytes - ctrl->index);
+
+ ctrl->index = ctrl->read_bytes;
+ return -EINVAL;
+ }
+
+ for (i = 0; i < len; i++)
+ if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+ break;
+
+ ctrl->index += len;
+ return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+}
+
+/* This function is called after Program and Erase Operations to
+ * check for success or failure.
+ */
+static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ lbus83xx_t *lbc = ctrl->regs;
+
+ if (ctrl->status != LTESR_CC)
+ return NAND_STATUS_FAIL;
+
+ /* Use READ_STATUS command, but wait for the device to be ready */
+ ctrl->use_mdr = 0;
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_RBW << FIR_OP1_SHIFT));
+ out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
+ out_be32(&lbc->fbcr, 1);
+ set_addr(mtd, 0, 0, 0);
+ ctrl->read_bytes = 1;
+
+ fsl_elbc_run_command(mtd);
+
+ if (ctrl->status != LTESR_CC)
+ return NAND_STATUS_FAIL;
+
+ /* The chip always seems to report that it is
+ * write-protected, even when it is not.
+ */
+ out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
+ return fsl_elbc_read_byte(mtd);
+}
+
+static int fsl_elbc_read_page(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ uint8_t *buf)
+{
+ fsl_elbc_read_buf(mtd, buf, mtd->writesize);
+ fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL)
+ mtd->ecc_stats.failed++;
+
+ return 0;
+}
+
+/* ECC will be calculated automatically, and errors will be detected in
+ * waitfunc.
+ */
+static void fsl_elbc_write_page(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ const uint8_t *buf)
+{
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+
+ fsl_elbc_write_buf(mtd, buf, mtd->writesize);
+ fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ ctrl->oob_poi = chip->oob_poi;
+}
+
+static struct fsl_elbc_ctrl *elbc_ctrl;
+
+static void fsl_elbc_ctrl_init(void)
+{
+ immap_t *im = (immap_t *)CFG_IMMR;
+
+ elbc_ctrl = kzalloc(sizeof(*elbc_ctrl), GFP_KERNEL);
+ if (!elbc_ctrl)
+ return;
+
+ elbc_ctrl->regs = &im->lbus;
+
+ /* clear event registers */
+ out_be32(&elbc_ctrl->regs->ltesr, LTESR_NAND_MASK);
+ out_be32(&elbc_ctrl->regs->lteatr, 0);
+
+ /* Enable interrupts for any detected events */
+ out_be32(&elbc_ctrl->regs->lteir, LTESR_NAND_MASK);
+
+ elbc_ctrl->read_bytes = 0;
+ elbc_ctrl->index = 0;
+ elbc_ctrl->addr = NULL;
+}
+
+int board_nand_init(struct nand_chip *nand)
+{
+ struct fsl_elbc_mtd *priv;
+ uint32_t br, or;
+
+ if (!elbc_ctrl) {
+ fsl_elbc_ctrl_init();
+ if (!elbc_ctrl)
+ return -1;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->ctrl = elbc_ctrl;
+ priv->vbase = nand->IO_ADDR_R;
+
+ /* Find which chip select it is connected to. It'd be nice
+ * if we could pass more than one datum to the NAND driver...
+ */
+ for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
+ br = in_be32(&elbc_ctrl->regs->bank[priv->bank].br);
+ or = in_be32(&elbc_ctrl->regs->bank[priv->bank].or);
+
+ if ((br & BR_V) && (br & BR_MSEL) == BR_MS_FCM &&
+ (br & or & BR_BA) == (phys_addr_t)nand->IO_ADDR_R)
+ break;
+ }
+
+ if (priv->bank >= MAX_BANKS) {
+ printf("fsl_elbc_nand: address did not match any "
+ "chip selects\n");
+ return -ENODEV;
+ }
+
+ elbc_ctrl->chips[priv->bank] = priv;
+
+ /* fill in nand_chip structure */
+ /* set up function call table */
+ nand->read_byte = fsl_elbc_read_byte;
+ nand->write_buf = fsl_elbc_write_buf;
+ nand->read_buf = fsl_elbc_read_buf;
+ nand->verify_buf = fsl_elbc_verify_buf;
+ nand->select_chip = fsl_elbc_select_chip;
+ nand->cmdfunc = fsl_elbc_cmdfunc;
+ nand->waitfunc = fsl_elbc_wait;
+
+ /* set up nand options */
+ nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;
+
+ nand->controller = &elbc_ctrl->controller;
+ nand->priv = priv;
+
+ nand->ecc.read_page = fsl_elbc_read_page;
+ nand->ecc.write_page = fsl_elbc_write_page;
+
+ /* If CS Base Register selects full hardware ECC then use it */
+ if ((br & BR_DECC) == BR_DECC_CHK_GEN) {
+ nand->ecc.mode = NAND_ECC_HW;
+
+ nand->ecc.layout = (priv->fmr & FMR_ECCM) ?
+ &fsl_elbc_oob_sp_eccm1 :
+ &fsl_elbc_oob_sp_eccm0;
+
+ nand->ecc.size = 512;
+ nand->ecc.bytes = 3;
+ nand->ecc.steps = 1;
+ } else {
+ /* otherwise fall back to default software ECC */
+ nand->ecc.mode = NAND_ECC_SOFT;
+ }
+
+ priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT);
+
+ /* adjust Option Register and ECC to match Flash page size */
+ if (or & OR_FCM_PGS) {
+ priv->page_size = 1;
+
+ /* adjust ecc setup if needed */
+ if ((br & BR_DECC) == BR_DECC_CHK_GEN) {
+ nand->ecc.steps = 4;
+ nand->ecc.layout = (priv->fmr & FMR_ECCM) ?
+ &fsl_elbc_oob_lp_eccm1 :
+ &fsl_elbc_oob_lp_eccm0;
+ }
+ }
+
+ return 0;
+}
*/
#include <config.h>
-
-#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_FSL_UPM)
#include <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <linux/mtd/fsl_upm.h>
#include <nand.h>
-static int fsl_upm_in_pattern;
-
static void fsl_upm_start_pattern(struct fsl_upm *upm, u32 pat_offset)
{
clrsetbits_be32(upm->mxmr, MxMR_MAD_MSK, MxMR_OP_RUNP | pat_offset);
}
}
-static void nand_hwcontrol (struct mtd_info *mtd, int cmd)
+static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
struct fsl_upm_nand *fun = chip->priv;
- switch (cmd) {
- case NAND_CTL_SETCLE:
- fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
- fsl_upm_in_pattern++;
- break;
- case NAND_CTL_SETALE:
- fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset);
- fsl_upm_in_pattern++;
- break;
- case NAND_CTL_CLRCLE:
- case NAND_CTL_CLRALE:
+ if (!(ctrl & fun->last_ctrl)) {
fsl_upm_end_pattern(&fun->upm);
- fsl_upm_in_pattern--;
- break;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ fun->last_ctrl = ctrl & (NAND_ALE | NAND_CLE);
}
-}
-static void nand_write_byte(struct mtd_info *mtd, u_char byte)
-{
- struct nand_chip *chip = mtd->priv;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if (ctrl & NAND_ALE)
+ fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset);
+ else if (ctrl & NAND_CLE)
+ fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
+ }
- if (fsl_upm_in_pattern) {
- struct fsl_upm_nand *fun = chip->priv;
-
- fsl_upm_run_pattern(&fun->upm, fun->width, byte);
-
- /*
- * Some boards/chips needs this. At least on MPC8360E-RDK we
- * need it. Probably weird chip, because I don't see any need
- * for this on MPC8555E + Samsung K9F1G08U0A. Usually here are
- * 0-2 unexpected busy states per block read.
- */
- if (fun->wait_pattern) {
- while (!fun->dev_ready())
- debug("unexpected busy state\n");
- }
- } else {
- out_8(chip->IO_ADDR_W, byte);
+ fsl_upm_run_pattern(&fun->upm, fun->width, cmd);
+
+ /*
+ * Some boards/chips needs this. At least on MPC8360E-RDK we
+ * need it. Probably weird chip, because I don't see any need
+ * for this on MPC8555E + Samsung K9F1G08U0A. Usually here are
+ * 0-2 unexpected busy states per block read.
+ */
+ if (fun->wait_pattern) {
+ while (!fun->dev_ready())
+ debug("unexpected busy state\n");
}
}
if (fun->width != 8 && fun->width != 16 && fun->width != 32)
return -ENOSYS;
+ fun->last_ctrl = NAND_CLE;
+
chip->priv = fun;
chip->chip_delay = fun->chip_delay;
- chip->eccmode = NAND_ECC_SOFT;
- chip->hwcontrol = nand_hwcontrol;
+ chip->ecc.mode = NAND_ECC_SOFT;
+ chip->cmd_ctrl = fun_cmd_ctrl;
chip->read_byte = nand_read_byte;
chip->read_buf = nand_read_buf;
- chip->write_byte = nand_write_byte;
chip->write_buf = nand_write_buf;
chip->verify_buf = nand_verify_buf;
if (fun->dev_ready)
return 0;
}
-#endif /* CONFIG_CMD_NAND */
*/
#include <common.h>
-
-#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
-
#include <nand.h>
#ifndef CFG_NAND_BASE_LIST
board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);
#endif
}
-
-#endif
* http://www.linux-mtd.infradead.org/tech/nand.html
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- * 2002 Thomas Gleixner (tglx@linutronix.de)
+ * 2002-2006 Thomas Gleixner (tglx@linutronix.de)
*
- * 02-08-2004 tglx: support for strange chips, which cannot auto increment
- * pages on read / read_oob
- *
- * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes
- * pointed this out, as he marked an auto increment capable chip
- * as NOAUTOINCR in the board driver.
- * Make reads over block boundaries work too
- *
- * 04-14-2004 tglx: first working version for 2k page size chips
- *
- * 05-19-2004 tglx: Basic support for Renesas AG-AND chips
- *
- * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared
- * among multiple independend devices. Suggestions and initial patch
- * from Ben Dooks <ben-mtd@fluff.org>
- *
- * Credits:
+ * Credits:
* David Woodhouse for adding multichip support
*
* Aleph One Ltd. and Toby Churchill Ltd. for supporting the
* rework for 2K page size chips
*
- * TODO:
+ * TODO:
* Enable cached programming for 2k page size chips
* Check, if mtd->ecctype should be set to MTD_ECC_HW
* if we have HW ecc support.
* The AG-AND chips have nice features for speed improvement,
* which are not supported yet. Read / program 4 pages in one go.
*
- * $Id: nand_base.c,v 1.126 2004/12/13 11:22:25 lavinen Exp $
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
/* XXX U-BOOT XXX */
#if 0
+#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/mtd/compatmac.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
+#include <linux/leds.h>
#include <asm/io.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <common.h>
-#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+#define ENOTSUPP 524 /* Operation is not supported */
#include <malloc.h>
#include <watchdog.h>
+#include <linux/err.h>
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#endif
/* Define default oob placement schemes for large and small page devices */
-static struct nand_oobinfo nand_oob_8 = {
- .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_8 = {
.eccbytes = 3,
.eccpos = {0, 1, 2},
- .oobfree = { {3, 2}, {6, 2} }
+ .oobfree = {
+ {.offset = 3,
+ .length = 2},
+ {.offset = 6,
+ .length = 2}}
};
-static struct nand_oobinfo nand_oob_16 = {
- .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_16 = {
.eccbytes = 6,
.eccpos = {0, 1, 2, 3, 6, 7},
- .oobfree = { {8, 8} }
+ .oobfree = {
+ {.offset = 8,
+ . length = 8}}
};
-static struct nand_oobinfo nand_oob_64 = {
- .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_64 = {
.eccbytes = 24,
.eccpos = {
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63},
- .oobfree = { {2, 38} }
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63},
+ .oobfree = {
+ {.offset = 2,
+ .length = 38}}
};
-static struct nand_oobinfo nand_oob_128 = {
- .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_128 = {
.eccbytes = 48,
.eccpos = {
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127},
- .oobfree = { {2, 78} }
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127},
+ .oobfree = {
+ {.offset = 2,
+ .length = 78}}
};
-/* This is used for padding purposes in nand_write_oob */
-static u_char *ffchars;
+
+static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
+ int new_state);
+
+static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops);
+
+static int nand_wait(struct mtd_info *mtd, struct nand_chip *this);
/*
- * NAND low-level MTD interface functions
+ * For devices which display every fart in the system on a seperate LED. Is
+ * compiled away when LED support is disabled.
*/
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
-
-static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
- size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);
-static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
- size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf);
/* XXX U-BOOT XXX */
#if 0
-static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long count, loff_t to, size_t * retlen);
-static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
-#endif
-static int nand_erase (struct mtd_info *mtd, struct erase_info *instr);
-static void nand_sync (struct mtd_info *mtd);
-
-/* Some internal functions */
-static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,
- struct nand_oobinfo *oobsel, int mode);
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
- u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode);
-#else
-#define nand_verify_pages(...) (0)
+DEFINE_LED_TRIGGER(nand_led_trigger);
#endif
-static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state);
-
/**
* nand_release_device - [GENERIC] release chip
* @mtd: MTD device structure
*/
/* XXX U-BOOT XXX */
#if 0
-static void nand_release_device (struct mtd_info *mtd)
+static void nand_release_device(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
/* De-select the NAND device */
- this->select_chip(mtd, -1);
- /* Do we have a hardware controller ? */
- if (this->controller) {
- spin_lock(&this->controller->lock);
- this->controller->active = NULL;
- spin_unlock(&this->controller->lock);
- }
- /* Release the chip */
- spin_lock (&this->chip_lock);
- this->state = FL_READY;
- wake_up (&this->wq);
- spin_unlock (&this->chip_lock);
+ chip->select_chip(mtd, -1);
+
+ /* Release the controller and the chip */
+ spin_lock(&chip->controller->lock);
+ chip->controller->active = NULL;
+ chip->state = FL_READY;
+ wake_up(&chip->controller->wq);
+ spin_unlock(&chip->controller->lock);
}
#else
static void nand_release_device (struct mtd_info *mtd)
{
struct nand_chip *this = mtd->priv;
this->select_chip(mtd, -1); /* De-select the NAND device */
- if (ffchars) {
- kfree(ffchars);
- ffchars = NULL;
- }
}
#endif
*
* Default read function for 8bit buswith
*/
-static u_char nand_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *this = mtd->priv;
- return readb(this->IO_ADDR_R);
-}
-
-/**
- * nand_write_byte - [DEFAULT] write one byte to the chip
- * @mtd: MTD device structure
- * @byte: pointer to data byte to write
- *
- * Default write function for 8it buswith
- */
-static void nand_write_byte(struct mtd_info *mtd, u_char byte)
+static uint8_t nand_read_byte(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
- writeb(byte, this->IO_ADDR_W);
+ struct nand_chip *chip = mtd->priv;
+ return readb(chip->IO_ADDR_R);
}
/**
* Default read function for 16bit buswith with
* endianess conversion
*/
-static u_char nand_read_byte16(struct mtd_info *mtd)
-{
- struct nand_chip *this = mtd->priv;
- return (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
-}
-
-/**
- * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip
- * @mtd: MTD device structure
- * @byte: pointer to data byte to write
- *
- * Default write function for 16bit buswith with
- * endianess conversion
- */
-static void nand_write_byte16(struct mtd_info *mtd, u_char byte)
+static uint8_t nand_read_byte16(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
- writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
+ struct nand_chip *chip = mtd->priv;
+ return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
}
/**
*/
static u16 nand_read_word(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
- return readw(this->IO_ADDR_R);
-}
-
-/**
- * nand_write_word - [DEFAULT] write one word to the chip
- * @mtd: MTD device structure
- * @word: data word to write
- *
- * Default write function for 16bit buswith without
- * endianess conversion
- */
-static void nand_write_word(struct mtd_info *mtd, u16 word)
-{
- struct nand_chip *this = mtd->priv;
- writew(word, this->IO_ADDR_W);
+ struct nand_chip *chip = mtd->priv;
+ return readw(chip->IO_ADDR_R);
}
/**
* nand_select_chip - [DEFAULT] control CE line
* @mtd: MTD device structure
- * @chip: chipnumber to select, -1 for deselect
+ * @chipnr: chipnumber to select, -1 for deselect
*
* Default select function for 1 chip devices.
*/
-static void nand_select_chip(struct mtd_info *mtd, int chip)
+static void nand_select_chip(struct mtd_info *mtd, int chipnr)
{
- struct nand_chip *this = mtd->priv;
- switch(chip) {
+ struct nand_chip *chip = mtd->priv;
+
+ switch (chipnr) {
case -1:
- this->hwcontrol(mtd, NAND_CTL_CLRNCE);
+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
break;
case 0:
- this->hwcontrol(mtd, NAND_CTL_SETNCE);
break;
default:
*
* Default write function for 8bit buswith
*/
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
- for (i=0; i<len; i++)
- writeb(buf[i], this->IO_ADDR_W);
+ for (i = 0; i < len; i++)
+ writeb(buf[i], chip->IO_ADDR_W);
}
/**
*
* Default read function for 8bit buswith
*/
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
- for (i=0; i<len; i++)
- buf[i] = readb(this->IO_ADDR_R);
+ for (i = 0; i < len; i++)
+ buf[i] = readb(chip->IO_ADDR_R);
}
/**
*
* Default verify function for 8bit buswith
*/
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
- for (i=0; i<len; i++)
- if (buf[i] != readb(this->IO_ADDR_R))
+ for (i = 0; i < len; i++)
+ if (buf[i] != readb(chip->IO_ADDR_R))
return -EFAULT;
-
return 0;
}
*
* Default write function for 16bit buswith
*/
-static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
+static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
u16 *p = (u16 *) buf;
len >>= 1;
- for (i=0; i<len; i++)
- writew(p[i], this->IO_ADDR_W);
+ for (i = 0; i < len; i++)
+ writew(p[i], chip->IO_ADDR_W);
}
*
* Default read function for 16bit buswith
*/
-static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
+static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
u16 *p = (u16 *) buf;
len >>= 1;
- for (i=0; i<len; i++)
- p[i] = readw(this->IO_ADDR_R);
+ for (i = 0; i < len; i++)
+ p[i] = readw(chip->IO_ADDR_R);
}
/**
*
* Default verify function for 16bit buswith
*/
-static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
+static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
u16 *p = (u16 *) buf;
len >>= 1;
- for (i=0; i<len; i++)
- if (p[i] != readw(this->IO_ADDR_R))
+ for (i = 0; i < len; i++)
+ if (p[i] != readw(chip->IO_ADDR_R))
return -EFAULT;
return 0;
static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
{
int page, chipnr, res = 0;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
u16 bad;
- page = (int)(ofs >> this->page_shift) & this->pagemask;
+ page = (int)(ofs >> chip->page_shift) & chip->pagemask;
if (getchip) {
- chipnr = (int)(ofs >> this->chip_shift);
+ chipnr = (int)(ofs >> chip->chip_shift);
- /* Grab the lock and see if the device is available */
- nand_get_device (this, mtd, FL_READING);
+ nand_get_device(chip, mtd, FL_READING);
/* Select the NAND device */
- this->select_chip(mtd, chipnr);
+ chip->select_chip(mtd, chipnr);
}
- if (this->options & NAND_BUSWIDTH_16) {
- this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page);
- bad = cpu_to_le16(this->read_word(mtd));
- if (this->badblockpos & 0x1)
- bad >>= 1;
+ if (chip->options & NAND_BUSWIDTH_16) {
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
+ page);
+ bad = cpu_to_le16(chip->read_word(mtd));
+ if (chip->badblockpos & 0x1)
+ bad >>= 8;
if ((bad & 0xFF) != 0xff)
res = 1;
} else {
- this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page);
- if (this->read_byte(mtd) != 0xff)
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page);
+ if (chip->read_byte(mtd) != 0xff)
res = 1;
}
- if (getchip) {
- /* Deselect and wake up anyone waiting on the device */
+ if (getchip)
nand_release_device(mtd);
- }
return res;
}
*/
static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- struct nand_chip *this = mtd->priv;
- u_char buf[2] = {0, 0};
- size_t retlen;
- int block;
+ struct nand_chip *chip = mtd->priv;
+ uint8_t buf[2] = { 0, 0 };
+ int block, ret;
/* Get block number */
- block = ((int) ofs) >> this->bbt_erase_shift;
- this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
+ block = (int)(ofs >> chip->bbt_erase_shift);
+ if (chip->bbt)
+ chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
/* Do we have a flash based bad block table ? */
- if (this->options & NAND_USE_FLASH_BBT)
- return nand_update_bbt (mtd, ofs);
+ if (chip->options & NAND_USE_FLASH_BBT)
+ ret = nand_update_bbt(mtd, ofs);
+ else {
+ /* We write two bytes, so we dont have to mess with 16 bit
+ * access
+ */
+ ofs += mtd->oobsize;
+ chip->ops.len = chip->ops.ooblen = 2;
+ chip->ops.datbuf = NULL;
+ chip->ops.oobbuf = buf;
+ chip->ops.ooboffs = chip->badblockpos & ~0x01;
- /* We write two bytes, so we dont have to mess with 16 bit access */
- ofs += mtd->oobsize + (this->badblockpos & ~0x01);
- return nand_write_oob (mtd, ofs , 2, &retlen, buf);
+ ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+ }
+ if (!ret)
+ mtd->ecc_stats.badblocks++;
+ return ret;
}
/**
*
* The function expects, that the device is already selected
*/
-static int nand_check_wp (struct mtd_info *mtd)
+static int nand_check_wp(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
/* Check the WP bit */
- this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
- return (this->read_byte(mtd) & 0x80) ? 0 : 1;
+ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+ return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
}
/**
* Check, if the block is bad. Either by reading the bad block table or
* calling of the scan function.
*/
-static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
+static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
+ int allowbbt)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
+
+ if (!(chip->options & NAND_BBT_SCANNED)) {
+ chip->scan_bbt(mtd);
+ chip->options |= NAND_BBT_SCANNED;
+ }
- if (!this->bbt)
- return this->block_bad(mtd, ofs, getchip);
+ if (!chip->bbt)
+ return chip->block_bad(mtd, ofs, getchip);
/* Return info from the table */
- return nand_isbad_bbt (mtd, ofs, allowbbt);
+ return nand_isbad_bbt(mtd, ofs, allowbbt);
+}
+
+/*
+ * Wait for the ready pin, after a command
+ * The timeout is catched later.
+ */
+/* XXX U-BOOT XXX */
+#if 0
+void nand_wait_ready(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+ unsigned long timeo = jiffies + 2;
+
+ led_trigger_event(nand_led_trigger, LED_FULL);
+ /* wait until command is processed or timeout occures */
+ do {
+ if (chip->dev_ready(mtd))
+ break;
+ touch_softlockup_watchdog();
+ } while (time_before(jiffies, timeo));
+ led_trigger_event(nand_led_trigger, LED_OFF);
+}
+EXPORT_SYMBOL_GPL(nand_wait_ready);
+#else
+void nand_wait_ready(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+ u32 timeo = (CFG_HZ * 20) / 1000;
+
+ reset_timer();
+
+ /* wait until command is processed or timeout occures */
+ while (get_timer(0) < timeo) {
+ if (chip->dev_ready)
+ if (chip->dev_ready(mtd))
+ break;
+ }
}
+#endif
/**
* nand_command - [DEFAULT] Send command to NAND device
* Send command to NAND device. This function is used for small page
* devices (256/512 Bytes per page)
*/
-static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void nand_command(struct mtd_info *mtd, unsigned int command,
+ int column, int page_addr)
{
- register struct nand_chip *this = mtd->priv;
+ register struct nand_chip *chip = mtd->priv;
+ int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
- /* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
/*
* Write out the command to the device.
*/
if (command == NAND_CMD_SEQIN) {
int readcmd;
- if (column >= mtd->oobblock) {
+ if (column >= mtd->writesize) {
/* OOB area */
- column -= mtd->oobblock;
+ column -= mtd->writesize;
readcmd = NAND_CMD_READOOB;
} else if (column < 256) {
/* First 256 bytes --> READ0 */
column -= 256;
readcmd = NAND_CMD_READ1;
}
- this->write_byte(mtd, readcmd);
+ chip->cmd_ctrl(mtd, readcmd, ctrl);
+ ctrl &= ~NAND_CTRL_CHANGE;
}
- this->write_byte(mtd, command);
-
- /* Set ALE and clear CLE to start address cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-
- if (column != -1 || page_addr != -1) {
- this->hwcontrol(mtd, NAND_CTL_SETALE);
+ chip->cmd_ctrl(mtd, command, ctrl);
- /* Serially input address */
- if (column != -1) {
- /* Adjust columns for 16 bit buswidth */
- if (this->options & NAND_BUSWIDTH_16)
- column >>= 1;
- this->write_byte(mtd, column);
- }
- if (page_addr != -1) {
- this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
- this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
- /* One more address cycle for devices > 32MiB */
- if (this->chipsize > (32 << 20))
- this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));
- }
- /* Latch in address */
- this->hwcontrol(mtd, NAND_CTL_CLRALE);
+ /*
+ * Address cycle, when necessary
+ */
+ ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
+ /* Serially input address */
+ if (column != -1) {
+ /* Adjust columns for 16 bit buswidth */
+ if (chip->options & NAND_BUSWIDTH_16)
+ column >>= 1;
+ chip->cmd_ctrl(mtd, column, ctrl);
+ ctrl &= ~NAND_CTRL_CHANGE;
+ }
+ if (page_addr != -1) {
+ chip->cmd_ctrl(mtd, page_addr, ctrl);
+ ctrl &= ~NAND_CTRL_CHANGE;
+ chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
+ /* One more address cycle for devices > 32MiB */
+ if (chip->chipsize > (32 << 20))
+ chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
}
+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* program and erase have their own busy handlers
* status and sequential in needs no delay
- */
+ */
switch (command) {
case NAND_CMD_PAGEPROG:
return;
case NAND_CMD_RESET:
- if (this->dev_ready)
+ if (chip->dev_ready)
break;
- udelay(this->chip_delay);
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- this->write_byte(mtd, NAND_CMD_STATUS);
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
- while ( !(this->read_byte(mtd) & 0x40));
+ udelay(chip->chip_delay);
+ chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ chip->cmd_ctrl(mtd,
+ NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
return;
- /* This applies to read commands */
+ /* This applies to read commands */
default:
/*
* If we don't have access to the busy pin, we apply the given
* command delay
- */
- if (!this->dev_ready) {
- udelay (this->chip_delay);
+ */
+ if (!chip->dev_ready) {
+ udelay(chip->chip_delay);
return;
}
}
-
/* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine. */
- ndelay (100);
- /* wait until command is processed */
- while (!this->dev_ready(mtd));
+ ndelay(100);
+
+ nand_wait_ready(mtd);
}
/**
* @column: the column address for this command, -1 if none
* @page_addr: the page address for this command, -1 if none
*
- * Send command to NAND device. This is the version for the new large page devices
- * We dont have the seperate regions as we have in the small page devices.
- * We must emulate NAND_CMD_READOOB to keep the code compatible.
- *
+ * Send command to NAND device. This is the version for the new large page
+ * devices We dont have the separate regions as we have in the small page
+ * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
*/
-static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
+ int column, int page_addr)
{
- register struct nand_chip *this = mtd->priv;
+ register struct nand_chip *chip = mtd->priv;
/* Emulate NAND_CMD_READOOB */
if (command == NAND_CMD_READOOB) {
- column += mtd->oobblock;
+ column += mtd->writesize;
command = NAND_CMD_READ0;
}
-
- /* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- /* Write out the command to the device. */
- this->write_byte(mtd, command);
- /* End command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
+ /* Command latch cycle */
+ chip->cmd_ctrl(mtd, command & 0xff,
+ NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
if (column != -1 || page_addr != -1) {
- this->hwcontrol(mtd, NAND_CTL_SETALE);
+ int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
- if (this->options & NAND_BUSWIDTH_16)
+ if (chip->options & NAND_BUSWIDTH_16)
column >>= 1;
- this->write_byte(mtd, column & 0xff);
- this->write_byte(mtd, column >> 8);
+ chip->cmd_ctrl(mtd, column, ctrl);
+ ctrl &= ~NAND_CTRL_CHANGE;
+ chip->cmd_ctrl(mtd, column >> 8, ctrl);
}
if (page_addr != -1) {
- this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
- this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
+ chip->cmd_ctrl(mtd, page_addr, ctrl);
+ chip->cmd_ctrl(mtd, page_addr >> 8,
+ NAND_NCE | NAND_ALE);
/* One more address cycle for devices > 128MiB */
- if (this->chipsize > (128 << 20))
- this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff));
+ if (chip->chipsize > (128 << 20))
+ chip->cmd_ctrl(mtd, page_addr >> 16,
+ NAND_NCE | NAND_ALE);
}
- /* Latch in address */
- this->hwcontrol(mtd, NAND_CTL_CLRALE);
}
+ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* program and erase have their own busy handlers
- * status and sequential in needs no delay
- */
+ * status, sequential in, and deplete1 need no delay
+ */
switch (command) {
case NAND_CMD_CACHEDPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
+ case NAND_CMD_RNDIN:
case NAND_CMD_STATUS:
+ case NAND_CMD_DEPLETE1:
return;
+ /*
+ * read error status commands require only a short delay
+ */
+ case NAND_CMD_STATUS_ERROR:
+ case NAND_CMD_STATUS_ERROR0:
+ case NAND_CMD_STATUS_ERROR1:
+ case NAND_CMD_STATUS_ERROR2:
+ case NAND_CMD_STATUS_ERROR3:
+ udelay(chip->chip_delay);
+ return;
case NAND_CMD_RESET:
- if (this->dev_ready)
+ if (chip->dev_ready)
break;
- udelay(this->chip_delay);
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- this->write_byte(mtd, NAND_CMD_STATUS);
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
- while ( !(this->read_byte(mtd) & 0x40));
+ udelay(chip->chip_delay);
+ chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
+ NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+ chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+ NAND_NCE | NAND_CTRL_CHANGE);
+ while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
+ return;
+
+ case NAND_CMD_RNDOUT:
+ /* No ready / busy check necessary */
+ chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
+ NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+ chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+ NAND_NCE | NAND_CTRL_CHANGE);
return;
case NAND_CMD_READ0:
- /* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- /* Write out the start read command */
- this->write_byte(mtd, NAND_CMD_READSTART);
- /* End command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
- /* Fall through into ready check */
-
- /* This applies to read commands */
+ chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
+ NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+ chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+ NAND_NCE | NAND_CTRL_CHANGE);
+
+ /* This applies to read commands */
default:
/*
* If we don't have access to the busy pin, we apply the given
* command delay
- */
- if (!this->dev_ready) {
- udelay (this->chip_delay);
+ */
+ if (!chip->dev_ready) {
+ udelay(chip->chip_delay);
return;
}
}
/* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine. */
- ndelay (100);
- /* wait until command is processed */
- while (!this->dev_ready(mtd));
+ ndelay(100);
+
+ nand_wait_ready(mtd);
}
/**
* nand_get_device - [GENERIC] Get chip for selected access
- * @this: the nand chip descriptor
+ * @chip: the nand chip descriptor
* @mtd: MTD device structure
* @new_state: the state which is requested
*
*/
/* XXX U-BOOT XXX */
#if 0
-static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)
+static int
+nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
{
- struct nand_chip *active = this;
+ spinlock_t *lock = &chip->controller->lock;
+ wait_queue_head_t *wq = &chip->controller->wq;
+ DECLARE_WAITQUEUE(wait, current);
+ retry:
+ spin_lock(lock);
- DECLARE_WAITQUEUE (wait, current);
-
- /*
- * Grab the lock and see if the device is available
- */
-retry:
/* Hardware controller shared among independend devices */
- if (this->controller) {
- spin_lock (&this->controller->lock);
- if (this->controller->active)
- active = this->controller->active;
- else
- this->controller->active = this;
- spin_unlock (&this->controller->lock);
- }
+ /* Hardware controller shared among independend devices */
+ if (!chip->controller->active)
+ chip->controller->active = chip;
- if (active == this) {
- spin_lock (&this->chip_lock);
- if (this->state == FL_READY) {
- this->state = new_state;
- spin_unlock (&this->chip_lock);
- return;
- }
+ if (chip->controller->active == chip && chip->state == FL_READY) {
+ chip->state = new_state;
+ spin_unlock(lock);
+ return 0;
+ }
+ if (new_state == FL_PM_SUSPENDED) {
+ spin_unlock(lock);
+ return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
}
- set_current_state (TASK_UNINTERRUPTIBLE);
- add_wait_queue (&active->wq, &wait);
- spin_unlock (&active->chip_lock);
- schedule ();
- remove_wait_queue (&active->wq, &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(wq, &wait);
+ spin_unlock(lock);
+ schedule();
+ remove_wait_queue(wq, &wait);
goto retry;
}
#else
-static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) {}
+static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)
+{
+ this->state = new_state;
+ return 0;
+}
#endif
/**
* nand_wait - [DEFAULT] wait until the command is done
* @mtd: MTD device structure
- * @this: NAND chip structure
- * @state: state to select the max. timeout value
+ * @chip: NAND chip structure
*
* Wait for command done. This applies to erase and program only
* Erase can take up to 400ms and program up to 20ms according to
* general NAND and SmartMedia specs
- *
-*/
+ */
/* XXX U-BOOT XXX */
#if 0
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
- unsigned long timeo = jiffies;
- int status;
+
+ unsigned long timeo = jiffies;
+ int status, state = chip->state;
if (state == FL_ERASING)
- timeo += (HZ * 400) / 1000;
+ timeo += (HZ * 400) / 1000;
else
- timeo += (HZ * 20) / 1000;
+ timeo += (HZ * 20) / 1000;
+
+ led_trigger_event(nand_led_trigger, LED_FULL);
/* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine. */
- ndelay (100);
+ ndelay(100);
- if ((state == FL_ERASING) && (this->options & NAND_IS_AND))
- this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1);
+ if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
+ chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
else
- this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
+ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
while (time_before(jiffies, timeo)) {
- /* Check, if we were interrupted */
- if (this->state != state)
- return 0;
-
- if (this->dev_ready) {
- if (this->dev_ready(mtd))
+ if (chip->dev_ready) {
+ if (chip->dev_ready(mtd))
break;
} else {
- if (this->read_byte(mtd) & NAND_STATUS_READY)
+ if (chip->read_byte(mtd) & NAND_STATUS_READY)
break;
}
- yield ();
+ cond_resched();
}
- status = (int) this->read_byte(mtd);
- return status;
+ led_trigger_event(nand_led_trigger, LED_OFF);
- return 0;
+ status = (int)chip->read_byte(mtd);
+ return status;
}
#else
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
{
unsigned long timeo;
+ int state = this->state;
if (state == FL_ERASING)
timeo = (CFG_HZ * 400) / 1000;
#endif
/**
- * nand_write_page - [GENERIC] write one page
- * @mtd: MTD device structure
- * @this: NAND chip structure
- * @page: startpage inside the chip, must be called with (page & this->pagemask)
- * @oob_buf: out of band data buffer
- * @oobsel: out of band selecttion structre
- * @cached: 1 = enable cached programming if supported by chip
- *
- * Nand_page_program function is used for write and writev !
- * This function will always program a full page of data
- * If you call it with a non page aligned buffer, you're lost :)
- *
- * Cached programming is not supported yet.
+ * nand_read_page_raw - [Intern] read raw page data without ecc
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
*/
-static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page,
- u_char *oob_buf, struct nand_oobinfo *oobsel, int cached)
+static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf)
{
- int i, status;
- u_char ecc_code[NAND_MAX_OOBSIZE];
- int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
- uint *oob_config = oobsel->eccpos;
- int datidx = 0, eccidx = 0, eccsteps = this->eccsteps;
- int eccbytes = 0;
+ chip->read_buf(mtd, buf, mtd->writesize);
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+ return 0;
+}
- /* FIXME: Enable cached programming */
- cached = 0;
+/**
+ * nand_read_page_swecc - [REPLACABLE] software ecc based page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ */
+static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *p = buf;
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+ uint8_t *ecc_code = chip->buffers->ecccode;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
- /* Send command to begin auto page programming */
- this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page);
+ chip->ecc.read_page_raw(mtd, chip, buf);
- /* Write out complete page of data, take care of eccmode */
- switch (eccmode) {
- /* No ecc, write all */
- case NAND_ECC_NONE:
- printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
- this->write_buf(mtd, this->data_poi, mtd->oobblock);
- break;
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
- /* Software ecc 3/256, write all */
- case NAND_ECC_SOFT:
- for (; eccsteps; eccsteps--) {
- this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
- for (i = 0; i < 3; i++, eccidx++)
- oob_buf[oob_config[eccidx]] = ecc_code[i];
- datidx += this->eccsize;
- }
- this->write_buf(mtd, this->data_poi, mtd->oobblock);
- break;
- default:
- eccbytes = this->eccbytes;
- for (; eccsteps; eccsteps--) {
- /* enable hardware ecc logic for write */
- this->enable_hwecc(mtd, NAND_ECC_WRITE);
- this->write_buf(mtd, &this->data_poi[datidx], this->eccsize);
- this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
- for (i = 0; i < eccbytes; i++, eccidx++)
- oob_buf[oob_config[eccidx]] = ecc_code[i];
- /* If the hardware ecc provides syndromes then
- * the ecc code must be written immediately after
- * the data bytes (words) */
- if (this->options & NAND_HWECC_SYNDROME)
- this->write_buf(mtd, ecc_code, eccbytes);
- datidx += this->eccsize;
- }
- break;
- }
+ for (i = 0; i < chip->ecc.total; i++)
+ ecc_code[i] = chip->oob_poi[eccpos[i]];
- /* Write out OOB data */
- if (this->options & NAND_HWECC_SYNDROME)
- this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
- else
- this->write_buf(mtd, oob_buf, mtd->oobsize);
-
- /* Send command to actually program the data */
- this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
-
- if (!cached) {
- /* call wait ready function */
- status = this->waitfunc (mtd, this, FL_WRITING);
- /* See if device thinks it succeeded */
- if (status & 0x01) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "%s: Failed write, page 0x%08x, ",
- __FUNCTION__, page);
- return -EIO;
- }
- } else {
- /* FIXME: Implement cached programming ! */
- /* wait until cache is ready*/
- /* status = this->waitfunc (mtd, this, FL_CACHEDRPG); */
+ eccsteps = chip->ecc.steps;
+ p = buf;
+
+ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ int stat;
+
+ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+ if (stat == -1)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
}
return 0;
}
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
/**
- * nand_verify_pages - [GENERIC] verify the chip contents after a write
- * @mtd: MTD device structure
- * @this: NAND chip structure
- * @page: startpage inside the chip, must be called with (page & this->pagemask)
- * @numpages: number of pages to verify
- * @oob_buf: out of band data buffer
- * @oobsel: out of band selecttion structre
- * @chipnr: number of the current chip
- * @oobmode: 1 = full buffer verify, 0 = ecc only
+ * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
*
- * The NAND device assumes that it is always writing to a cleanly erased page.
- * Hence, it performs its internal write verification only on bits that
- * transitioned from 1 to 0. The device does NOT verify the whole page on a
- * byte by byte basis. It is possible that the page was not completely erased
- * or the page is becoming unusable due to wear. The read with ECC would catch
- * the error later when the ECC page check fails, but we would rather catch
- * it early in the page write stage. Better to write no data than invalid data.
+ * Not for syndrome calculating ecc controllers which need a special oob layout
*/
-static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
- u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
-{
- int i, j, datidx = 0, oobofs = 0, res = -EIO;
- int eccsteps = this->eccsteps;
- int hweccbytes;
- u_char oobdata[64];
-
- hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
-
- /* Send command to read back the first page */
- this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
-
- for(;;) {
- for (j = 0; j < eccsteps; j++) {
- /* Loop through and verify the data */
- if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "%s: "
- "Failed write verify, page 0x%08x ",
- __FUNCTION__, page);
- goto out;
- }
- datidx += mtd->eccsize;
- /* Have we a hw generator layout ? */
- if (!hweccbytes)
- continue;
- if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "%s: "
- "Failed write verify, page 0x%08x ",
- __FUNCTION__, page);
- goto out;
- }
- oobofs += hweccbytes;
- }
+static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *p = buf;
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+ uint8_t *ecc_code = chip->buffers->ecccode;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ chip->read_buf(mtd, p, eccsize);
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+ }
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
- /* check, if we must compare all data or if we just have to
- * compare the ecc bytes
- */
- if (oobmode) {
- if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "%s: "
- "Failed write verify, page 0x%08x ",
- __FUNCTION__, page);
- goto out;
- }
- } else {
- /* Read always, else autoincrement fails */
- this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
-
- if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
- int ecccnt = oobsel->eccbytes;
-
- for (i = 0; i < ecccnt; i++) {
- int idx = oobsel->eccpos[i];
- if (oobdata[idx] != oob_buf[oobofs + idx] ) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "%s: Failed ECC write "
- "verify, page 0x%08x, "
- "%6i bytes were succesful\n",
- __FUNCTION__, page, i);
- goto out;
- }
- }
- }
- }
- oobofs += mtd->oobsize - hweccbytes * eccsteps;
- page++;
- numpages--;
-
- /* Apply delay or wait for ready/busy pin
- * Do this before the AUTOINCR check, so no problems
- * arise if a chip which does auto increment
- * is marked as NOAUTOINCR by the board driver.
- * Do this also before returning, so the chip is
- * ready for the next command.
- */
- if (!this->dev_ready)
- udelay (this->chip_delay);
- else
- while (!this->dev_ready(mtd));
+ for (i = 0; i < chip->ecc.total; i++)
+ ecc_code[i] = chip->oob_poi[eccpos[i]];
- /* All done, return happy */
- if (!numpages)
- return 0;
+ eccsteps = chip->ecc.steps;
+ p = buf;
+ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ int stat;
- /* Check, if the chip supports auto page increment */
- if (!NAND_CANAUTOINCR(this))
- this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
+ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+ if (stat == -1)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
}
- /*
- * Terminate the read command. We come here in case of an error
- * So we must issue a reset command.
- */
-out:
- this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1);
- return res;
+ return 0;
}
-#endif
/**
- * nand_read - [MTD Interface] MTD compability function for nand_read_ecc
- * @mtd: MTD device structure
- * @from: offset to read from
- * @len: number of bytes to read
- * @retlen: pointer to variable to store the number of read bytes
- * @buf: the databuffer to put data
+ * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
*
- * This function simply calls nand_read_ecc with oob buffer and oobsel = NULL
-*/
-static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
+ * The hw generator calculates the error syndrome automatically. Therefor
+ * we need a special oob layout and handling.
+ */
+static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf)
{
- return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);
-}
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *p = buf;
+ uint8_t *oob = chip->oob_poi;
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ int stat;
-/**
- * nand_read_ecc - [MTD Interface] Read data with ECC
- * @mtd: MTD device structure
- * @from: offset to read from
- * @len: number of bytes to read
- * @retlen: pointer to variable to store the number of read bytes
- * @buf: the databuffer to put data
- * @oob_buf: filesystem supplied oob data buffer
- * @oobsel: oob selection structure
- *
- * NAND read with ECC
- */
-static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
- size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)
-{
- int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
- int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
- struct nand_chip *this = mtd->priv;
- u_char *data_poi, *oob_data = oob_buf;
- u_char ecc_calc[NAND_MAX_OOBSIZE];
- u_char ecc_code[NAND_MAX_OOBSIZE];
- int eccmode, eccsteps;
- unsigned *oob_config;
- int datidx;
- int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
- int eccbytes;
- int compareecc = 1;
- int oobreadlen;
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ chip->read_buf(mtd, p, eccsize);
+ if (chip->ecc.prepad) {
+ chip->read_buf(mtd, oob, chip->ecc.prepad);
+ oob += chip->ecc.prepad;
+ }
- MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n",
- (unsigned int) from, (int) len);
+ chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
+ chip->read_buf(mtd, oob, eccbytes);
+ stat = chip->ecc.correct(mtd, p, oob, NULL);
- /* Do not allow reads past end of device */
- if ((from + len) > mtd->size) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "nand_read_ecc: Attempt read beyond end of device\n");
- *retlen = 0;
- return -EINVAL;
- }
+ if (stat == -1)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
- /* Grab the lock and see if the device is available */
- nand_get_device (this, mtd ,FL_READING);
+ oob += eccbytes;
- /* use userspace supplied oobinfo, if zero */
- if (oobsel == NULL)
- oobsel = &mtd->oobinfo;
+ if (chip->ecc.postpad) {
+ chip->read_buf(mtd, oob, chip->ecc.postpad);
+ oob += chip->ecc.postpad;
+ }
+ }
- /* Autoplace of oob data ? Use the default placement scheme */
- if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
- oobsel = this->autooob;
+ /* Calculate remaining oob bytes */
+ i = mtd->oobsize - (oob - chip->oob_poi);
+ if (i)
+ chip->read_buf(mtd, oob, i);
- eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
- oob_config = oobsel->eccpos;
+ return 0;
+}
- /* Select the NAND device */
- chipnr = (int)(from >> this->chip_shift);
- this->select_chip(mtd, chipnr);
+/**
+ * nand_transfer_oob - [Internal] Transfer oob to client buffer
+ * @chip: nand chip structure
+ * @oob: oob destination address
+ * @ops: oob ops structure
+ * @len: size of oob to transfer
+ */
+static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
+ struct mtd_oob_ops *ops, size_t len)
+{
+ switch(ops->mode) {
+
+ case MTD_OOB_PLACE:
+ case MTD_OOB_RAW:
+ memcpy(oob, chip->oob_poi + ops->ooboffs, len);
+ return oob + len;
+
+ case MTD_OOB_AUTO: {
+ struct nand_oobfree *free = chip->ecc.layout->oobfree;
+ uint32_t boffs = 0, roffs = ops->ooboffs;
+ size_t bytes = 0;
+
+ for(; free->length && len; free++, len -= bytes) {
+ /* Read request not from offset 0 ? */
+ if (unlikely(roffs)) {
+ if (roffs >= free->length) {
+ roffs -= free->length;
+ continue;
+ }
+ boffs = free->offset + roffs;
+ bytes = min_t(size_t, len,
+ (free->length - roffs));
+ roffs = 0;
+ } else {
+ bytes = min_t(size_t, len, free->length);
+ boffs = free->offset;
+ }
+ memcpy(oob, chip->oob_poi + boffs, bytes);
+ oob += bytes;
+ }
+ return oob;
+ }
+ default:
+ BUG();
+ }
+ return NULL;
+}
- /* First we calculate the starting page */
- realpage = (int) (from >> this->page_shift);
- page = realpage & this->pagemask;
+/**
+ * nand_do_read_ops - [Internal] Read data with ECC
+ *
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob ops structure
+ *
+ * Internal function. Called with chip held.
+ */
+static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
+{
+ int chipnr, page, realpage, col, bytes, aligned;
+ struct nand_chip *chip = mtd->priv;
+ struct mtd_ecc_stats stats;
+ int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+ int sndcmd = 1;
+ int ret = 0;
+ uint32_t readlen = ops->len;
+ uint32_t oobreadlen = ops->ooblen;
+ uint8_t *bufpoi, *oob, *buf;
- /* Get raw starting column */
- col = from & (mtd->oobblock - 1);
+ stats = mtd->ecc_stats;
- end = mtd->oobblock;
- ecc = this->eccsize;
- eccbytes = this->eccbytes;
+ chipnr = (int)(from >> chip->chip_shift);
+ chip->select_chip(mtd, chipnr);
- if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
- compareecc = 0;
+ realpage = (int)(from >> chip->page_shift);
+ page = realpage & chip->pagemask;
- oobreadlen = mtd->oobsize;
- if (this->options & NAND_HWECC_SYNDROME)
- oobreadlen -= oobsel->eccbytes;
+ col = (int)(from & (mtd->writesize - 1));
- /* Loop until all data read */
- while (read < len) {
+ buf = ops->datbuf;
+ oob = ops->oobbuf;
- int aligned = (!col && (len - read) >= end);
- /*
- * If the read is not page aligned, we have to read into data buffer
- * due to ecc, else we read into return buffer direct
- */
- if (aligned)
- data_poi = &buf[read];
- else
- data_poi = this->data_buf;
+ while(1) {
+ bytes = min(mtd->writesize - col, readlen);
+ aligned = (bytes == mtd->writesize);
- /* Check, if we have this page in the buffer
- *
- * FIXME: Make it work when we must provide oob data too,
- * check the usage of data_buf oob field
- */
- if (realpage == this->pagebuf && !oob_buf) {
- /* aligned read ? */
- if (aligned)
- memcpy (data_poi, this->data_buf, end);
- goto readdata;
- }
+ /* Is the current page in the buffer ? */
+ if (realpage != chip->pagebuf || oob) {
+ bufpoi = aligned ? buf : chip->buffers->databuf;
- /* Check, if we must send the read command */
- if (sndcmd) {
- this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
- sndcmd = 0;
- }
+ if (likely(sndcmd)) {
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+ sndcmd = 0;
+ }
- /* get oob area, if we have no oob buffer from fs-driver */
- if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
- oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
- oob_data = &this->data_buf[end];
+ /* Now read the page into the buffer */
+ if (unlikely(ops->mode == MTD_OOB_RAW))
+ ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
+ else
+ ret = chip->ecc.read_page(mtd, chip, bufpoi);
+ if (ret < 0)
+ break;
- eccsteps = this->eccsteps;
+ /* Transfer not aligned data */
+ if (!aligned) {
+ chip->pagebuf = realpage;
+ memcpy(buf, chip->buffers->databuf + col, bytes);
+ }
- switch (eccmode) {
- case NAND_ECC_NONE: { /* No ECC, Read in a page */
-/* XXX U-BOOT XXX */
-#if 0
- static unsigned long lastwhinge = 0;
- if ((lastwhinge / HZ) != (jiffies / HZ)) {
- printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n");
- lastwhinge = jiffies;
+ buf += bytes;
+
+ if (unlikely(oob)) {
+ /* Raw mode does data:oob:data:oob */
+ if (ops->mode != MTD_OOB_RAW) {
+ int toread = min(oobreadlen,
+ chip->ecc.layout->oobavail);
+ if (toread) {
+ oob = nand_transfer_oob(chip,
+ oob, ops, toread);
+ oobreadlen -= toread;
+ }
+ } else
+ buf = nand_transfer_oob(chip,
+ buf, ops, mtd->oobsize);
}
-#else
- puts("Reading data from NAND FLASH without ECC is not recommended\n");
-#endif
- this->read_buf(mtd, data_poi, end);
- break;
+
+ if (!(chip->options & NAND_NO_READRDY)) {
+ /*
+ * Apply delay or wait for ready/busy pin. Do
+ * this before the AUTOINCR check, so no
+ * problems arise if a chip which does auto
+ * increment is marked as NOAUTOINCR by the
+ * board driver.
+ */
+ if (!chip->dev_ready)
+ udelay(chip->chip_delay);
+ else
+ nand_wait_ready(mtd);
+ }
+ } else {
+ memcpy(buf, chip->buffers->databuf + col, bytes);
+ buf += bytes;
}
- case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
- this->read_buf(mtd, data_poi, end);
- for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc)
- this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
- break;
-
- default:
- for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) {
- this->enable_hwecc(mtd, NAND_ECC_READ);
- this->read_buf(mtd, &data_poi[datidx], ecc);
-
- /* HW ecc with syndrome calculation must read the
- * syndrome from flash immidiately after the data */
- if (!compareecc) {
- /* Some hw ecc generators need to know when the
- * syndrome is read from flash */
- this->enable_hwecc(mtd, NAND_ECC_READSYN);
- this->read_buf(mtd, &oob_data[i], eccbytes);
- /* We calc error correction directly, it checks the hw
- * generator for an error, reads back the syndrome and
- * does the error correction on the fly */
- if (this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]) == -1) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: "
- "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
- ecc_failed++;
- }
- } else {
- this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
- }
- }
- break;
- }
-
- /* read oobdata */
- this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
-
- /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
- if (!compareecc)
- goto readoob;
-
- /* Pick the ECC bytes out of the oob data */
- for (j = 0; j < oobsel->eccbytes; j++)
- ecc_code[j] = oob_data[oob_config[j]];
-
- /* correct data, if neccecary */
- for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) {
- ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
-
- /* Get next chunk of ecc bytes */
- j += eccbytes;
-
- /* Check, if we have a fs supplied oob-buffer,
- * This is the legacy mode. Used by YAFFS1
- * Should go away some day
- */
- if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
- int *p = (int *)(&oob_data[mtd->oobsize]);
- p[i] = ecc_status;
- }
-
- if (ecc_status == -1) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: "
- "Failed ECC read, page 0x%08x\n",
- page);
- ecc_failed++;
- }
- }
-
- readoob:
- /* check, if we have a fs supplied oob-buffer */
- if (oob_buf) {
- /* without autoplace. Legacy mode used by YAFFS1 */
- switch(oobsel->useecc) {
- case MTD_NANDECC_AUTOPLACE:
- case MTD_NANDECC_AUTOPL_USR:
- /* Walk through the autoplace chunks */
- for (i = 0, j = 0; j < mtd->oobavail; i++) {
- int from = oobsel->oobfree[i][0];
- int num = oobsel->oobfree[i][1];
- memcpy(&oob_buf[oob+j], &oob_data[from], num);
- j+= num;
- }
- oob += mtd->oobavail;
- break;
- case MTD_NANDECC_PLACE:
- /* YAFFS1 legacy mode */
- oob_data += this->eccsteps * sizeof (int);
- default:
- oob_data += mtd->oobsize;
- }
- }
- readdata:
- /* Partial page read, transfer data into fs buffer */
- if (!aligned) {
- for (j = col; j < end && read < len; j++)
- buf[read++] = data_poi[j];
- this->pagebuf = realpage;
- } else
- read += mtd->oobblock;
-
- /* Apply delay or wait for ready/busy pin
- * Do this before the AUTOINCR check, so no problems
- * arise if a chip which does auto increment
- * is marked as NOAUTOINCR by the board driver.
- */
- if (!this->dev_ready)
- udelay (this->chip_delay);
- else
- while (!this->dev_ready(mtd));
-
- if (read == len)
+ readlen -= bytes;
+
+ if (!readlen)
break;
/* For subsequent reads align to page boundary. */
/* Increment page address */
realpage++;
- page = realpage & this->pagemask;
+ page = realpage & chip->pagemask;
/* Check, if we cross a chip boundary */
if (!page) {
chipnr++;
- this->select_chip(mtd, -1);
- this->select_chip(mtd, chipnr);
+ chip->select_chip(mtd, -1);
+ chip->select_chip(mtd, chipnr);
}
+
/* Check, if the chip supports auto page increment
* or if we have hit a block boundary.
- */
- if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
+ */
+ if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
sndcmd = 1;
}
- /* Deselect and wake up anyone waiting on the device */
- nand_release_device(mtd);
+ ops->retlen = ops->len - (size_t) readlen;
+ if (oob)
+ ops->oobretlen = ops->ooblen - oobreadlen;
- /*
- * Return success, if no ECC failures, else -EBADMSG
- * fs driver will take care of that, because
- * retlen == desired len and result == -EBADMSG
- */
- *retlen = read;
- return ecc_failed ? -EBADMSG : 0;
+ if (ret)
+ return ret;
+
+ if (mtd->ecc_stats.failed - stats.failed)
+ return -EBADMSG;
+
+ return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
}
/**
- * nand_read_oob - [MTD Interface] NAND read out-of-band
+ * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
* @mtd: MTD device structure
* @from: offset to read from
* @len: number of bytes to read
* @retlen: pointer to variable to store the number of read bytes
* @buf: the databuffer to put data
*
- * NAND read out-of-band data from the spare area
+ * Get hold of the chip and call nand_do_read
*/
-static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
+static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, uint8_t *buf)
{
- int i, col, page, chipnr;
- struct nand_chip *this = mtd->priv;
- int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
+ struct nand_chip *chip = mtd->priv;
+ int ret;
- MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n",
- (unsigned int) from, (int) len);
+ /* Do not allow reads past end of device */
+ if ((from + len) > mtd->size)
+ return -EINVAL;
+ if (!len)
+ return 0;
- /* Shift to get page */
- page = (int)(from >> this->page_shift);
- chipnr = (int)(from >> this->chip_shift);
+ nand_get_device(chip, mtd, FL_READING);
- /* Mask to get column */
- col = from & (mtd->oobsize - 1);
+ chip->ops.len = len;
+ chip->ops.datbuf = buf;
+ chip->ops.oobbuf = NULL;
- /* Initialize return length value */
- *retlen = 0;
+ ret = nand_do_read_ops(mtd, from, &chip->ops);
- /* Do not allow reads past end of device */
- if ((from + len) > mtd->size) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "nand_read_oob: Attempt read beyond end of device\n");
- *retlen = 0;
- return -EINVAL;
+ *retlen = chip->ops.retlen;
+
+ nand_release_device(mtd);
+
+ return ret;
+}
+
+/**
+ * nand_read_oob_std - [REPLACABLE] the most common OOB data read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to read
+ * @sndcmd: flag whether to issue read command or not
+ */
+static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
+ int page, int sndcmd)
+{
+ if (sndcmd) {
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+ sndcmd = 0;
}
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+ return sndcmd;
+}
- /* Grab the lock and see if the device is available */
- nand_get_device (this, mtd , FL_READING);
+/**
+ * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
+ * with syndromes
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to read
+ * @sndcmd: flag whether to issue read command or not
+ */
+static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+ int page, int sndcmd)
+{
+ uint8_t *buf = chip->oob_poi;
+ int length = mtd->oobsize;
+ int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+ int eccsize = chip->ecc.size;
+ uint8_t *bufpoi = buf;
+ int i, toread, sndrnd = 0, pos;
+
+ chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page);
+ for (i = 0; i < chip->ecc.steps; i++) {
+ if (sndrnd) {
+ pos = eccsize + i * (eccsize + chunk);
+ if (mtd->writesize > 512)
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1);
+ else
+ chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page);
+ } else
+ sndrnd = 1;
+ toread = min_t(int, length, chunk);
+ chip->read_buf(mtd, bufpoi, toread);
+ bufpoi += toread;
+ length -= toread;
+ }
+ if (length > 0)
+ chip->read_buf(mtd, bufpoi, length);
- /* Select the NAND device */
- this->select_chip(mtd, chipnr);
+ return 1;
+}
+
+/**
+ * nand_write_oob_std - [REPLACABLE] the most common OOB data write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to write
+ */
+static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
+ int page)
+{
+ int status = 0;
+ const uint8_t *buf = chip->oob_poi;
+ int length = mtd->oobsize;
+
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+ chip->write_buf(mtd, buf, length);
+ /* Send command to program the OOB data */
+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+ status = chip->waitfunc(mtd, chip);
+
+ return status & NAND_STATUS_FAIL ? -EIO : 0;
+}
+
+/**
+ * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
+ * with syndrome - only for large page flash !
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @page: page number to write
+ */
+static int nand_write_oob_syndrome(struct mtd_info *mtd,
+ struct nand_chip *chip, int page)
+{
+ int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+ int eccsize = chip->ecc.size, length = mtd->oobsize;
+ int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps;
+ const uint8_t *bufpoi = chip->oob_poi;
- /* Send the read command */
- this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask);
/*
- * Read the data, if we read more than one page
- * oob data, let the device transfer the data !
+ * data-ecc-data-ecc ... ecc-oob
+ * or
+ * data-pad-ecc-pad-data-pad .... ecc-pad-oob
*/
- i = 0;
- while (i < len) {
- int thislen = mtd->oobsize - col;
- thislen = min_t(int, thislen, len);
- this->read_buf(mtd, &buf[i], thislen);
- i += thislen;
-
- /* Apply delay or wait for ready/busy pin
- * Do this before the AUTOINCR check, so no problems
- * arise if a chip which does auto increment
- * is marked as NOAUTOINCR by the board driver.
- */
- if (!this->dev_ready)
- udelay (this->chip_delay);
- else
- while (!this->dev_ready(mtd));
-
- /* Read more ? */
- if (i < len) {
- page++;
- col = 0;
-
- /* Check, if we cross a chip boundary */
- if (!(page & this->pagemask)) {
- chipnr++;
- this->select_chip(mtd, -1);
- this->select_chip(mtd, chipnr);
- }
-
- /* Check, if the chip supports auto page increment
- * or if we have hit a block boundary.
- */
- if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {
- /* For subsequent page reads set offset to 0 */
- this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
+ if (!chip->ecc.prepad && !chip->ecc.postpad) {
+ pos = steps * (eccsize + chunk);
+ steps = 0;
+ } else
+ pos = eccsize;
+
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
+ for (i = 0; i < steps; i++) {
+ if (sndcmd) {
+ if (mtd->writesize <= 512) {
+ uint32_t fill = 0xFFFFFFFF;
+
+ len = eccsize;
+ while (len > 0) {
+ int num = min_t(int, len, 4);
+ chip->write_buf(mtd, (uint8_t *)&fill,
+ num);
+ len -= num;
+ }
+ } else {
+ pos = eccsize + i * (eccsize + chunk);
+ chip->cmdfunc(mtd, NAND_CMD_RNDIN, pos, -1);
}
- }
+ } else
+ sndcmd = 1;
+ len = min_t(int, length, chunk);
+ chip->write_buf(mtd, bufpoi, len);
+ bufpoi += len;
+ length -= len;
}
+ if (length > 0)
+ chip->write_buf(mtd, bufpoi, length);
- /* Deselect and wake up anyone waiting on the device */
- nand_release_device(mtd);
+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+ status = chip->waitfunc(mtd, chip);
- /* Return happy */
- *retlen = len;
- return 0;
+ return status & NAND_STATUS_FAIL ? -EIO : 0;
}
/**
- * nand_read_raw - [GENERIC] Read raw data including oob into buffer
+ * nand_do_read_oob - [Intern] NAND read out-of-band
* @mtd: MTD device structure
- * @buf: temporary buffer
* @from: offset to read from
- * @len: number of bytes to read
- * @ooblen: number of oob data bytes to read
+ * @ops: oob operations description structure
*
- * Read raw data including oob into buffer
+ * NAND read out-of-band data from the spare area
*/
-int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen)
+static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
{
- struct nand_chip *this = mtd->priv;
- int page = (int) (from >> this->page_shift);
- int chip = (int) (from >> this->chip_shift);
- int sndcmd = 1;
- int cnt = 0;
- int pagesize = mtd->oobblock + mtd->oobsize;
- int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
+ int page, realpage, chipnr, sndcmd = 1;
+ struct nand_chip *chip = mtd->priv;
+ int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+ int readlen = ops->ooblen;
+ int len;
+ uint8_t *buf = ops->oobbuf;
+
+ MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
+ (unsigned long long)from, readlen);
+
+ if (ops->mode == MTD_OOB_AUTO)
+ len = chip->ecc.layout->oobavail;
+ else
+ len = mtd->oobsize;
+
+ if (unlikely(ops->ooboffs >= len)) {
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: "
+ "Attempt to start read outside oob\n");
+ return -EINVAL;
+ }
/* Do not allow reads past end of device */
- if ((from + len) > mtd->size) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "nand_read_raw: Attempt read beyond end of device\n");
+ if (unlikely(from >= mtd->size ||
+ ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
+ (from >> chip->page_shift)) * len)) {
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: "
+ "Attempt read beyond end of device\n");
return -EINVAL;
}
- /* Grab the lock and see if the device is available */
- nand_get_device (this, mtd , FL_READING);
+ chipnr = (int)(from >> chip->chip_shift);
+ chip->select_chip(mtd, chipnr);
- this->select_chip (mtd, chip);
+ /* Shift to get page */
+ realpage = (int)(from >> chip->page_shift);
+ page = realpage & chip->pagemask;
- /* Add requested oob length */
- len += ooblen;
+ while(1) {
+ sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
- while (len) {
- if (sndcmd)
- this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask);
- sndcmd = 0;
+ len = min(len, readlen);
+ buf = nand_transfer_oob(chip, buf, ops, len);
- this->read_buf (mtd, &buf[cnt], pagesize);
+ if (!(chip->options & NAND_NO_READRDY)) {
+ /*
+ * Apply delay or wait for ready/busy pin. Do this
+ * before the AUTOINCR check, so no problems arise if a
+ * chip which does auto increment is marked as
+ * NOAUTOINCR by the board driver.
+ */
+ if (!chip->dev_ready)
+ udelay(chip->chip_delay);
+ else
+ nand_wait_ready(mtd);
+ }
- len -= pagesize;
- cnt += pagesize;
- page++;
+ readlen -= len;
+ if (!readlen)
+ break;
- if (!this->dev_ready)
- udelay (this->chip_delay);
- else
- while (!this->dev_ready(mtd));
+ /* Increment page address */
+ realpage++;
- /* Check, if the chip supports auto page increment */
- if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
+ page = realpage & chip->pagemask;
+ /* Check, if we cross a chip boundary */
+ if (!page) {
+ chipnr++;
+ chip->select_chip(mtd, -1);
+ chip->select_chip(mtd, chipnr);
+ }
+
+ /* Check, if the chip supports auto page increment
+ * or if we have hit a block boundary.
+ */
+ if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
sndcmd = 1;
}
- /* Deselect and wake up anyone waiting on the device */
- nand_release_device(mtd);
+ ops->oobretlen = ops->ooblen;
return 0;
}
-
/**
- * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
+ * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
* @mtd: MTD device structure
- * @fsbuf: buffer given by fs driver
- * @oobsel: out of band selection structre
- * @autoplace: 1 = place given buffer into the oob bytes
- * @numpages: number of pages to prepare
- *
- * Return:
- * 1. Filesystem buffer available and autoplacement is off,
- * return filesystem buffer
- * 2. No filesystem buffer or autoplace is off, return internal
- * buffer
- * 3. Filesystem buffer is given and autoplace selected
- * put data from fs buffer into internal buffer and
- * retrun internal buffer
- *
- * Note: The internal buffer is filled with 0xff. This must
- * be done only once, when no autoplacement happens
- * Autoplacement sets the buffer dirty flag, which
- * forces the 0xff fill before using the buffer again.
+ * @from: offset to read from
+ * @ops: oob operation description structure
*
-*/
-static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel,
- int autoplace, int numpages)
+ * NAND read data and/or out-of-band data
+ */
+static int nand_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
{
- struct nand_chip *this = mtd->priv;
- int i, len, ofs;
-
- /* Zero copy fs supplied buffer */
- if (fsbuf && !autoplace)
- return fsbuf;
-
- /* Check, if the buffer must be filled with ff again */
- if (this->oobdirty) {
- memset (this->oob_buf, 0xff,
- mtd->oobsize << (this->phys_erase_shift - this->page_shift));
- this->oobdirty = 0;
- }
-
- /* If we have no autoplacement or no fs buffer use the internal one */
- if (!autoplace || !fsbuf)
- return this->oob_buf;
-
- /* Walk through the pages and place the data */
- this->oobdirty = 1;
- ofs = 0;
- while (numpages--) {
- for (i = 0, len = 0; len < mtd->oobavail; i++) {
- int to = ofs + oobsel->oobfree[i][0];
- int num = oobsel->oobfree[i][1];
- memcpy (&this->oob_buf[to], fsbuf, num);
- len += num;
- fsbuf += num;
- }
- ofs += mtd->oobavail;
+ struct nand_chip *chip = mtd->priv;
+ int ret = -ENOTSUPP;
+
+ ops->retlen = 0;
+
+ /* Do not allow reads past end of device */
+ if (ops->datbuf && (from + ops->len) > mtd->size) {
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: "
+ "Attempt read beyond end of device\n");
+ return -EINVAL;
+ }
+
+ nand_get_device(chip, mtd, FL_READING);
+
+ switch(ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ case MTD_OOB_RAW:
+ break;
+
+ default:
+ goto out;
}
- return this->oob_buf;
+
+ if (!ops->datbuf)
+ ret = nand_do_read_oob(mtd, from, ops);
+ else
+ ret = nand_do_read_ops(mtd, from, ops);
+
+ out:
+ nand_release_device(mtd);
+ return ret;
}
-#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
/**
- * nand_write - [MTD Interface] compability function for nand_write_ecc
- * @mtd: MTD device structure
- * @to: offset to write to
- * @len: number of bytes to write
- * @retlen: pointer to variable to store the number of written bytes
- * @buf: the data to write
- *
- * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
- *
-*/
-static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
+ * nand_write_page_raw - [Intern] raw page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
+ */
+static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf)
{
- return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
+ chip->write_buf(mtd, buf, mtd->writesize);
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
}
/**
- * nand_write_ecc - [MTD Interface] NAND write with ECC
- * @mtd: MTD device structure
- * @to: offset to write to
- * @len: number of bytes to write
- * @retlen: pointer to variable to store the number of written bytes
- * @buf: the data to write
- * @eccbuf: filesystem supplied oob data buffer
- * @oobsel: oob selection structure
- *
- * NAND write with ECC
+ * nand_write_page_swecc - [REPLACABLE] software ecc based page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
*/
-static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
- size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
+static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf)
{
- int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
- int autoplace = 0, numpages, totalpages;
- struct nand_chip *this = mtd->priv;
- u_char *oobbuf, *bufstart;
- int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+ const uint8_t *p = buf;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
- MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n",
- (unsigned int) to, (int) len);
+ /* Software ecc calculation */
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
- /* Initialize retlen, in case of early exit */
- *retlen = 0;
+ for (i = 0; i < chip->ecc.total; i++)
+ chip->oob_poi[eccpos[i]] = ecc_calc[i];
- /* Do not allow write past end of device */
- if ((to + len) > mtd->size) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "nand_write_ecc: Attempt to write past end of page\n");
- return -EINVAL;
- }
+ chip->ecc.write_page_raw(mtd, chip, buf);
+}
- /* reject writes, which are not page aligned */
- if (NOTALIGNED (to) || NOTALIGNED(len)) {
- printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
- return -EINVAL;
+/**
+ * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
+ */
+static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+ const uint8_t *p = buf;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+ chip->write_buf(mtd, p, eccsize);
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
}
- /* Grab the lock and see if the device is available */
- nand_get_device (this, mtd, FL_WRITING);
+ for (i = 0; i < chip->ecc.total; i++)
+ chip->oob_poi[eccpos[i]] = ecc_calc[i];
- /* Calculate chipnr */
- chipnr = (int)(to >> this->chip_shift);
- /* Select the NAND device */
- this->select_chip(mtd, chipnr);
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
- /* Check, if it is write protected */
- if (nand_check_wp(mtd)) {
- printk (KERN_NOTICE "nand_write_ecc: Device is write protected\n");
- goto out;
- }
+/**
+ * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: data buffer
+ *
+ * The hw generator calculates the error syndrome automatically. Therefor
+ * we need a special oob layout and handling.
+ */
+static void nand_write_page_syndrome(struct mtd_info *mtd,
+ struct nand_chip *chip, const uint8_t *buf)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ const uint8_t *p = buf;
+ uint8_t *oob = chip->oob_poi;
- /* if oobsel is NULL, use chip defaults */
- if (oobsel == NULL)
- oobsel = &mtd->oobinfo;
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- /* Autoplace of oob data ? Use the default placement scheme */
- if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
- oobsel = this->autooob;
- autoplace = 1;
- }
- if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
- autoplace = 1;
+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+ chip->write_buf(mtd, p, eccsize);
- /* Setup variables and oob buffer */
- totalpages = len >> this->page_shift;
- page = (int) (to >> this->page_shift);
- /* Invalidate the page cache, if we write to the cached page */
- if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
- this->pagebuf = -1;
-
- /* Set it relative to chip */
- page &= this->pagemask;
- startpage = page;
- /* Calc number of pages we can write in one go */
- numpages = min (ppblock - (startpage & (ppblock - 1)), totalpages);
- oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages);
- bufstart = (u_char *)buf;
-
- /* Loop until all data is written */
- while (written < len) {
-
- this->data_poi = (u_char*) &buf[written];
- /* Write one page. If this is the last page to write
- * or the last page in this block, then use the
- * real pageprogram command, else select cached programming
- * if supported by the chip.
- */
- ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
- if (ret) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "nand_write_ecc: write_page failed %d\n", ret);
- goto out;
+ if (chip->ecc.prepad) {
+ chip->write_buf(mtd, oob, chip->ecc.prepad);
+ oob += chip->ecc.prepad;
}
- /* Next oob page */
- oob += mtd->oobsize;
- /* Update written bytes count */
- written += mtd->oobblock;
- if (written == len)
- goto cmp;
- /* Increment page address */
- page++;
-
- /* Have we hit a block boundary ? Then we have to verify and
- * if verify is ok, we have to setup the oob buffer for
- * the next pages.
- */
- if (!(page & (ppblock - 1))){
- int ofs;
- this->data_poi = bufstart;
- ret = nand_verify_pages (mtd, this, startpage,
- page - startpage,
- oobbuf, oobsel, chipnr, (eccbuf != NULL));
- if (ret) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: "
- "verify_pages failed %d\n", ret);
- goto out;
- }
- *retlen = written;
- bufstart = (u_char*) &buf[written];
-
- ofs = autoplace ? mtd->oobavail : mtd->oobsize;
- if (eccbuf)
- eccbuf += (page - startpage) * ofs;
- totalpages -= page - startpage;
- numpages = min (totalpages, ppblock);
- page &= this->pagemask;
- startpage = page;
- oob = 0;
- this->oobdirty = 1;
- oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel,
- autoplace, numpages);
- /* Check, if we cross a chip boundary */
- if (!page) {
- chipnr++;
- this->select_chip(mtd, -1);
- this->select_chip(mtd, chipnr);
- }
+ chip->ecc.calculate(mtd, p, oob);
+ chip->write_buf(mtd, oob, eccbytes);
+ oob += eccbytes;
+
+ if (chip->ecc.postpad) {
+ chip->write_buf(mtd, oob, chip->ecc.postpad);
+ oob += chip->ecc.postpad;
}
}
- /* Verify the remaining pages */
-cmp:
- this->data_poi = bufstart;
- ret = nand_verify_pages (mtd, this, startpage, totalpages,
- oobbuf, oobsel, chipnr, (eccbuf != NULL));
- if (!ret)
- *retlen = written;
+
+ /* Calculate remaining oob bytes */
+ i = mtd->oobsize - (oob - chip->oob_poi);
+ if (i)
+ chip->write_buf(mtd, oob, i);
+}
+
+/**
+ * nand_write_page - [REPLACEABLE] write one page
+ * @mtd: MTD device structure
+ * @chip: NAND chip descriptor
+ * @buf: the data to write
+ * @page: page number to write
+ * @cached: cached programming
+ * @raw: use _raw version of write_page
+ */
+static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int page, int cached, int raw)
+{
+ int status;
+
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+
+ if (unlikely(raw))
+ chip->ecc.write_page_raw(mtd, chip, buf);
else
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "nand_write_ecc: verify_pages failed %d\n", ret);
+ chip->ecc.write_page(mtd, chip, buf);
-out:
- /* Deselect and wake up anyone waiting on the device */
- nand_release_device(mtd);
+ /*
+ * Cached progamming disabled for now, Not sure if its worth the
+ * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
+ */
+ cached = 0;
- return ret;
+ if (!cached || !(chip->options & NAND_CACHEPRG)) {
+
+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+ status = chip->waitfunc(mtd, chip);
+ /*
+ * See if operation failed and additional status checks are
+ * available
+ */
+ if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+ status = chip->errstat(mtd, chip, FL_WRITING, status,
+ page);
+
+ if (status & NAND_STATUS_FAIL)
+ return -EIO;
+ } else {
+ chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
+ status = chip->waitfunc(mtd, chip);
+ }
+
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+ /* Send command to read back the data */
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+ if (chip->verify_buf(mtd, buf, mtd->writesize))
+ return -EIO;
+#endif
+ return 0;
+}
+
+/**
+ * nand_fill_oob - [Internal] Transfer client buffer to oob
+ * @chip: nand chip structure
+ * @oob: oob data buffer
+ * @ops: oob ops structure
+ */
+static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
+ struct mtd_oob_ops *ops)
+{
+ size_t len = ops->ooblen;
+
+ switch(ops->mode) {
+
+ case MTD_OOB_PLACE:
+ case MTD_OOB_RAW:
+ memcpy(chip->oob_poi + ops->ooboffs, oob, len);
+ return oob + len;
+
+ case MTD_OOB_AUTO: {
+ struct nand_oobfree *free = chip->ecc.layout->oobfree;
+ uint32_t boffs = 0, woffs = ops->ooboffs;
+ size_t bytes = 0;
+
+ for(; free->length && len; free++, len -= bytes) {
+ /* Write request not from offset 0 ? */
+ if (unlikely(woffs)) {
+ if (woffs >= free->length) {
+ woffs -= free->length;
+ continue;
+ }
+ boffs = free->offset + woffs;
+ bytes = min_t(size_t, len,
+ (free->length - woffs));
+ woffs = 0;
+ } else {
+ bytes = min_t(size_t, len, free->length);
+ boffs = free->offset;
+ }
+ memcpy(chip->oob_poi + boffs, oob, bytes);
+ oob += bytes;
+ }
+ return oob;
+ }
+ default:
+ BUG();
+ }
+ return NULL;
}
+#define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0
/**
- * nand_write_oob - [MTD Interface] NAND write out-of-band
+ * nand_do_write_ops - [Internal] NAND write with ECC
* @mtd: MTD device structure
* @to: offset to write to
- * @len: number of bytes to write
- * @retlen: pointer to variable to store the number of written bytes
- * @buf: the data to write
+ * @ops: oob operations description structure
*
- * NAND write out-of-band
+ * NAND write with ECC
*/
-static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
+static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
{
- int column, page, status, ret = -EIO, chipnr;
- struct nand_chip *this = mtd->priv;
+ int chipnr, realpage, page, blockmask, column;
+ struct nand_chip *chip = mtd->priv;
+ uint32_t writelen = ops->len;
+ uint8_t *oob = ops->oobbuf;
+ uint8_t *buf = ops->datbuf;
+ int ret, subpage;
- MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
- (unsigned int) to, (int) len);
+ ops->retlen = 0;
+ if (!writelen)
+ return 0;
- /* Shift to get page */
- page = (int) (to >> this->page_shift);
- chipnr = (int) (to >> this->chip_shift);
-
- /* Mask to get column */
- column = to & (mtd->oobsize - 1);
-
- /* Initialize return length value */
- *retlen = 0;
-
- /* Do not allow write past end of page */
- if ((column + len) > mtd->oobsize) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: "
- "Attempt to write past end of page\n");
+ /* reject writes, which are not page aligned */
+ if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
+ printk(KERN_NOTICE "nand_write: "
+ "Attempt to write not page aligned data\n");
return -EINVAL;
}
- /* Grab the lock and see if the device is available */
- nand_get_device (this, mtd, FL_WRITING);
+ column = to & (mtd->writesize - 1);
+ subpage = column || (writelen & (mtd->writesize - 1));
- /* Select the NAND device */
- this->select_chip(mtd, chipnr);
+ if (subpage && oob)
+ return -EINVAL;
- /* Reset the chip. Some chips (like the Toshiba TC5832DC found
- in one of my DiskOnChip 2000 test units) will clear the whole
- data page too if we don't do this. I have no clue why, but
- I seem to have 'fixed' it in the doc2000 driver in
- August 1999. dwmw2. */
- this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+ chipnr = (int)(to >> chip->chip_shift);
+ chip->select_chip(mtd, chipnr);
/* Check, if it is write protected */
- if (nand_check_wp(mtd))
- goto out;
+ if (nand_check_wp(mtd)) {
+ printk (KERN_NOTICE "nand_do_write_ops: Device is write protected\n");
+ return -EIO;
+ }
- /* Invalidate the page cache, if we write to the cached page */
- if (page == this->pagebuf)
- this->pagebuf = -1;
-
- if (NAND_MUST_PAD(this)) {
- /* Write out desired data */
- this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask);
- if (!ffchars) {
- if (!(ffchars = kmalloc (mtd->oobsize, GFP_KERNEL))) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: "
- "No memory for padding array, "
- "need %d bytes", mtd->oobsize);
- ret = -ENOMEM;
- goto out;
- }
- memset(ffchars, 0xff, mtd->oobsize);
+ realpage = (int)(to >> chip->page_shift);
+ page = realpage & chip->pagemask;
+ blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+
+ /* Invalidate the page cache, when we write to the cached page */
+ if (to <= (chip->pagebuf << chip->page_shift) &&
+ (chip->pagebuf << chip->page_shift) < (to + ops->len))
+ chip->pagebuf = -1;
+
+ /* If we're not given explicit OOB data, let it be 0xFF */
+ if (likely(!oob))
+ memset(chip->oob_poi, 0xff, mtd->oobsize);
+
+ while(1) {
+ int bytes = mtd->writesize;
+ int cached = writelen > bytes && page != blockmask;
+ uint8_t *wbuf = buf;
+
+ /* Partial page write ? */
+ if (unlikely(column || writelen < (mtd->writesize - 1))) {
+ cached = 0;
+ bytes = min_t(int, bytes - column, (int) writelen);
+ chip->pagebuf = -1;
+ memset(chip->buffers->databuf, 0xff, mtd->writesize);
+ memcpy(&chip->buffers->databuf[column], buf, bytes);
+ wbuf = chip->buffers->databuf;
}
- /* prepad 0xff for partial programming */
- this->write_buf(mtd, ffchars, column);
- /* write data */
- this->write_buf(mtd, buf, len);
- /* postpad 0xff for partial programming */
- this->write_buf(mtd, ffchars, mtd->oobsize - (len+column));
- } else {
- /* Write out desired data */
- this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask);
- /* write data */
- this->write_buf(mtd, buf, len);
- }
- /* Send command to program the OOB data */
- this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1);
- status = this->waitfunc (mtd, this, FL_WRITING);
+ if (unlikely(oob))
+ oob = nand_fill_oob(chip, oob, ops);
- /* See if device thinks it succeeded */
- if (status & 0x01) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: "
- "Failed write, page 0x%08x\n", page);
- ret = -EIO;
- goto out;
- }
- /* Return happy */
- *retlen = len;
+ ret = chip->write_page(mtd, chip, wbuf, page, cached,
+ (ops->mode == MTD_OOB_RAW));
+ if (ret)
+ break;
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
- /* Send command to read back the data */
- this->cmdfunc (mtd, NAND_CMD_READOOB, column, page & this->pagemask);
+ writelen -= bytes;
+ if (!writelen)
+ break;
- if (this->verify_buf(mtd, buf, len)) {
- MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: "
- "Failed write verify, page 0x%08x\n", page);
- ret = -EIO;
- goto out;
+ column = 0;
+ buf += bytes;
+ realpage++;
+
+ page = realpage & chip->pagemask;
+ /* Check, if we cross a chip boundary */
+ if (!page) {
+ chipnr++;
+ chip->select_chip(mtd, -1);
+ chip->select_chip(mtd, chipnr);
+ }
}
-#endif
- ret = 0;
-out:
- /* Deselect and wake up anyone waiting on the device */
- nand_release_device(mtd);
+ ops->retlen = ops->len - writelen;
+ if (unlikely(oob))
+ ops->oobretlen = ops->ooblen;
return ret;
}
-/* XXX U-BOOT XXX */
-#if 0
/**
- * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc
+ * nand_write - [MTD Interface] NAND write with ECC
* @mtd: MTD device structure
- * @vecs: the iovectors to write
- * @count: number of vectors
* @to: offset to write to
+ * @len: number of bytes to write
* @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
*
- * NAND write with kvec. This just calls the ecc function
+ * NAND write with ECC
*/
-static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
- loff_t to, size_t * retlen)
+static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const uint8_t *buf)
{
- return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL));
+ struct nand_chip *chip = mtd->priv;
+ int ret;
+
+ /* Do not allow reads past end of device */
+ if ((to + len) > mtd->size)
+ return -EINVAL;
+ if (!len)
+ return 0;
+
+ nand_get_device(chip, mtd, FL_WRITING);
+
+ chip->ops.len = len;
+ chip->ops.datbuf = (uint8_t *)buf;
+ chip->ops.oobbuf = NULL;
+
+ ret = nand_do_write_ops(mtd, to, &chip->ops);
+
+ *retlen = chip->ops.retlen;
+
+ nand_release_device(mtd);
+
+ return ret;
}
/**
- * nand_writev_ecc - [MTD Interface] write with iovec with ecc
+ * nand_do_write_oob - [MTD Interface] NAND write out-of-band
* @mtd: MTD device structure
- * @vecs: the iovectors to write
- * @count: number of vectors
* @to: offset to write to
- * @retlen: pointer to variable to store the number of written bytes
- * @eccbuf: filesystem supplied oob data buffer
- * @oobsel: oob selection structure
+ * @ops: oob operation description structure
*
- * NAND write with iovec with ecc
+ * NAND write out-of-band
*/
-static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
- loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
{
- int i, page, len, total_len, ret = -EIO, written = 0, chipnr;
- int oob, numpages, autoplace = 0, startpage;
- struct nand_chip *this = mtd->priv;
- int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
- u_char *oobbuf, *bufstart;
+ int chipnr, page, status, len;
+ struct nand_chip *chip = mtd->priv;
- /* Preset written len for early exit */
- *retlen = 0;
+ MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
+ (unsigned int)to, (int)ops->ooblen);
- /* Calculate total length of data */
- total_len = 0;
- for (i = 0; i < count; i++)
- total_len += (int) vecs[i].iov_len;
+ if (ops->mode == MTD_OOB_AUTO)
+ len = chip->ecc.layout->oobavail;
+ else
+ len = mtd->oobsize;
- MTDDEBUG (MTD_DEBUG_LEVEL3,
- "nand_writev: to = 0x%08x, len = %i, count = %ld\n",
- (unsigned int) to, (unsigned int) total_len, count);
+ /* Do not allow write past end of page */
+ if ((ops->ooboffs + ops->ooblen) > len) {
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: "
+ "Attempt to write past end of page\n");
+ return -EINVAL;
+ }
- /* Do not allow write past end of page */
- if ((to + total_len) > mtd->size) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "nand_writev: Attempted write past end of device\n");
+ if (unlikely(ops->ooboffs >= len)) {
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: "
+ "Attempt to start write outside oob\n");
return -EINVAL;
}
- /* reject writes, which are not page aligned */
- if (NOTALIGNED (to) || NOTALIGNED(total_len)) {
- printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
+ /* Do not allow reads past end of device */
+ if (unlikely(to >= mtd->size ||
+ ops->ooboffs + ops->ooblen >
+ ((mtd->size >> chip->page_shift) -
+ (to >> chip->page_shift)) * len)) {
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: "
+ "Attempt write beyond end of device\n");
return -EINVAL;
}
- /* Grab the lock and see if the device is available */
- nand_get_device (this, mtd, FL_WRITING);
+ chipnr = (int)(to >> chip->chip_shift);
+ chip->select_chip(mtd, chipnr);
- /* Get the current chip-nr */
- chipnr = (int) (to >> this->chip_shift);
- /* Select the NAND device */
- this->select_chip(mtd, chipnr);
+ /* Shift to get page */
+ page = (int)(to >> chip->page_shift);
+
+ /*
+ * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
+ * of my DiskOnChip 2000 test units) will clear the whole data page too
+ * if we don't do this. I have no clue why, but I seem to have 'fixed'
+ * it in the doc2000 driver in August 1999. dwmw2.
+ */
+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
/* Check, if it is write protected */
if (nand_check_wp(mtd))
- goto out;
+ return -EROFS;
- /* if oobsel is NULL, use chip defaults */
- if (oobsel == NULL)
- oobsel = &mtd->oobinfo;
+ /* Invalidate the page cache, if we write to the cached page */
+ if (page == chip->pagebuf)
+ chip->pagebuf = -1;
- /* Autoplace of oob data ? Use the default placement scheme */
- if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
- oobsel = this->autooob;
- autoplace = 1;
- }
- if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
- autoplace = 1;
+ memset(chip->oob_poi, 0xff, mtd->oobsize);
+ nand_fill_oob(chip, ops->oobbuf, ops);
+ status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
+ memset(chip->oob_poi, 0xff, mtd->oobsize);
- /* Setup start page */
- page = (int) (to >> this->page_shift);
- /* Invalidate the page cache, if we write to the cached page */
- if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift))
- this->pagebuf = -1;
+ if (status)
+ return status;
- startpage = page & this->pagemask;
+ ops->oobretlen = ops->ooblen;
- /* Loop until all kvec' data has been written */
- len = 0;
- while (count) {
- /* If the given tuple is >= pagesize then
- * write it out from the iov
- */
- if ((vecs->iov_len - len) >= mtd->oobblock) {
- /* Calc number of pages we can write
- * out of this iov in one go */
- numpages = (vecs->iov_len - len) >> this->page_shift;
- /* Do not cross block boundaries */
- numpages = min (ppblock - (startpage & (ppblock - 1)), numpages);
- oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
- bufstart = (u_char *)vecs->iov_base;
- bufstart += len;
- this->data_poi = bufstart;
- oob = 0;
- for (i = 1; i <= numpages; i++) {
- /* Write one page. If this is the last page to write
- * then use the real pageprogram command, else select
- * cached programming if supported by the chip.
- */
- ret = nand_write_page (mtd, this, page & this->pagemask,
- &oobbuf[oob], oobsel, i != numpages);
- if (ret)
- goto out;
- this->data_poi += mtd->oobblock;
- len += mtd->oobblock;
- oob += mtd->oobsize;
- page++;
- }
- /* Check, if we have to switch to the next tuple */
- if (len >= (int) vecs->iov_len) {
- vecs++;
- len = 0;
- count--;
- }
- } else {
- /* We must use the internal buffer, read data out of each
- * tuple until we have a full page to write
- */
- int cnt = 0;
- while (cnt < mtd->oobblock) {
- if (vecs->iov_base != NULL && vecs->iov_len)
- this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
- /* Check, if we have to switch to the next tuple */
- if (len >= (int) vecs->iov_len) {
- vecs++;
- len = 0;
- count--;
- }
- }
- this->pagebuf = page;
- this->data_poi = this->data_buf;
- bufstart = this->data_poi;
- numpages = 1;
- oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
- ret = nand_write_page (mtd, this, page & this->pagemask,
- oobbuf, oobsel, 0);
- if (ret)
- goto out;
- page++;
- }
+ return 0;
+}
- this->data_poi = bufstart;
- ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0);
- if (ret)
- goto out;
+/**
+ * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operation description structure
+ */
+static int nand_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ struct nand_chip *chip = mtd->priv;
+ int ret = -ENOTSUPP;
- written += mtd->oobblock * numpages;
- /* All done ? */
- if (!count)
- break;
+ ops->retlen = 0;
- startpage = page & this->pagemask;
- /* Check, if we cross a chip boundary */
- if (!startpage) {
- chipnr++;
- this->select_chip(mtd, -1);
- this->select_chip(mtd, chipnr);
- }
+ /* Do not allow writes past end of device */
+ if (ops->datbuf && (to + ops->len) > mtd->size) {
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: "
+ "Attempt read beyond end of device\n");
+ return -EINVAL;
}
- ret = 0;
-out:
- /* Deselect and wake up anyone waiting on the device */
- nand_release_device(mtd);
- *retlen = written;
+ nand_get_device(chip, mtd, FL_WRITING);
+
+ switch(ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ case MTD_OOB_RAW:
+ break;
+
+ default:
+ goto out;
+ }
+
+ if (!ops->datbuf)
+ ret = nand_do_write_oob(mtd, to, ops);
+ else
+ ret = nand_do_write_ops(mtd, to, ops);
+
+ out:
+ nand_release_device(mtd);
return ret;
}
-#endif
/**
* single_erease_cmd - [GENERIC] NAND standard block erase command function
*
* Standard erase command for NAND chips
*/
-static void single_erase_cmd (struct mtd_info *mtd, int page)
+static void single_erase_cmd(struct mtd_info *mtd, int page)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
/* Send commands to erase a block */
- this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page);
- this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1);
+ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
}
/**
* AND multi block erase command function
* Erase 4 consecutive blocks
*/
-static void multi_erase_cmd (struct mtd_info *mtd, int page)
+static void multi_erase_cmd(struct mtd_info *mtd, int page)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
/* Send commands to erase a block */
- this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
- this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
- this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
- this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page);
- this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1);
+ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
}
/**
*
* Erase one ore more blocks
*/
-static int nand_erase (struct mtd_info *mtd, struct erase_info *instr)
+static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
{
- return nand_erase_nand (mtd, instr, 0);
+ return nand_erase_nand(mtd, instr, 0);
}
+#define BBT_PAGE_MASK 0xffffff3f
/**
- * nand_erase_intern - [NAND Interface] erase block(s)
+ * nand_erase_nand - [Internal] erase block(s)
* @mtd: MTD device structure
* @instr: erase instruction
* @allowbbt: allow erasing the bbt area
*
* Erase one ore more blocks
*/
-int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
+int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+ int allowbbt)
{
int page, len, status, pages_per_block, ret, chipnr;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
+ int rewrite_bbt[NAND_MAX_CHIPS]={0};
+ unsigned int bbt_masked_page = 0xffffffff;
MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
(unsigned int) instr->addr, (unsigned int) instr->len);
/* Start address must align on block boundary */
- if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
+ if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
return -EINVAL;
}
/* Length must align on block boundary */
- if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
+ if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
"nand_erase: Length not block aligned\n");
return -EINVAL;
instr->fail_addr = 0xffffffff;
/* Grab the lock and see if the device is available */
- nand_get_device (this, mtd, FL_ERASING);
+ nand_get_device(chip, mtd, FL_ERASING);
/* Shift to get first page */
- page = (int) (instr->addr >> this->page_shift);
- chipnr = (int) (instr->addr >> this->chip_shift);
+ page = (int)(instr->addr >> chip->page_shift);
+ chipnr = (int)(instr->addr >> chip->chip_shift);
/* Calculate pages in each block */
- pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
+ pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
/* Select the NAND device */
- this->select_chip(mtd, chipnr);
+ chip->select_chip(mtd, chipnr);
- /* Check the WP bit */
/* Check, if it is write protected */
if (nand_check_wp(mtd)) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
goto erase_exit;
}
+ /*
+ * If BBT requires refresh, set the BBT page mask to see if the BBT
+ * should be rewritten. Otherwise the mask is set to 0xffffffff which
+ * can not be matched. This is also done when the bbt is actually
+ * erased to avoid recusrsive updates
+ */
+ if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
+ bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
+
/* Loop through the pages */
len = instr->len;
instr->state = MTD_ERASING;
while (len) {
-#ifndef NAND_ALLOW_ERASE_ALL
- /* Check if we have a bad block, we do not erase bad blocks ! */
- if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) {
- printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
+ /*
+ * heck if we have a bad block, we do not erase bad blocks !
+ */
+ if (nand_block_checkbad(mtd, ((loff_t) page) <<
+ chip->page_shift, 0, allowbbt)) {
+ printk(KERN_WARNING "nand_erase: attempt to erase a "
+ "bad block at page 0x%08x\n", page);
instr->state = MTD_ERASE_FAILED;
goto erase_exit;
}
-#endif
- /* Invalidate the page cache, if we erase the block which contains
- the current cached page */
- if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
- this->pagebuf = -1;
- this->erase_cmd (mtd, page & this->pagemask);
+ /*
+ * Invalidate the page cache, if we erase the block which
+ * contains the current cached page
+ */
+ if (page <= chip->pagebuf && chip->pagebuf <
+ (page + pages_per_block))
+ chip->pagebuf = -1;
+
+ chip->erase_cmd(mtd, page & chip->pagemask);
- status = this->waitfunc (mtd, this, FL_ERASING);
+ status = chip->waitfunc(mtd, chip);
+
+ /*
+ * See if operation failed and additional status checks are
+ * available
+ */
+ if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+ status = chip->errstat(mtd, chip, FL_ERASING,
+ status, page);
/* See if block erase succeeded */
- if (status & 0x01) {
+ if (status & NAND_STATUS_FAIL) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase: "
"Failed erase, page 0x%08x\n", page);
instr->state = MTD_ERASE_FAILED;
- instr->fail_addr = (page << this->page_shift);
+ instr->fail_addr = (page << chip->page_shift);
goto erase_exit;
}
+ /*
+ * If BBT requires refresh, set the BBT rewrite flag to the
+ * page being erased
+ */
+ if (bbt_masked_page != 0xffffffff &&
+ (page & BBT_PAGE_MASK) == bbt_masked_page)
+ rewrite_bbt[chipnr] = (page << chip->page_shift);
+
/* Increment page address and decrement length */
- len -= (1 << this->phys_erase_shift);
+ len -= (1 << chip->phys_erase_shift);
page += pages_per_block;
/* Check, if we cross a chip boundary */
- if (len && !(page & this->pagemask)) {
+ if (len && !(page & chip->pagemask)) {
chipnr++;
- this->select_chip(mtd, -1);
- this->select_chip(mtd, chipnr);
+ chip->select_chip(mtd, -1);
+ chip->select_chip(mtd, chipnr);
+
+ /*
+ * If BBT requires refresh and BBT-PERCHIP, set the BBT
+ * page mask to see if this BBT should be rewritten
+ */
+ if (bbt_masked_page != 0xffffffff &&
+ (chip->bbt_td->options & NAND_BBT_PERCHIP))
+ bbt_masked_page = chip->bbt_td->pages[chipnr] &
+ BBT_PAGE_MASK;
}
}
instr->state = MTD_ERASE_DONE;
-erase_exit:
+ erase_exit:
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
/* Do call back function */
/* Deselect and wake up anyone waiting on the device */
nand_release_device(mtd);
+ /*
+ * If BBT requires refresh and erase was successful, rewrite any
+ * selected bad block tables
+ */
+ if (bbt_masked_page == 0xffffffff || ret)
+ return ret;
+
+ for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
+ if (!rewrite_bbt[chipnr])
+ continue;
+ /* update the BBT for chip */
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
+ "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
+ chip->bbt_td->pages[chipnr]);
+ nand_update_bbt(mtd, rewrite_bbt[chipnr]);
+ }
+
/* Return more or less happy */
return ret;
}
*
* Sync is actually a wait for chip ready function
*/
-static void nand_sync (struct mtd_info *mtd)
+static void nand_sync(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
/* Grab the lock and see if the device is available */
- nand_get_device (this, mtd, FL_SYNCING);
+ nand_get_device(chip, mtd, FL_SYNCING);
/* Release it and go back */
- nand_release_device (mtd);
+ nand_release_device(mtd);
}
-
/**
- * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
+ * nand_block_isbad - [MTD Interface] Check if block at offset is bad
* @mtd: MTD device structure
- * @ofs: offset relative to mtd start
+ * @offs: offset relative to mtd start
*/
-static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
+static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
{
/* Check for invalid offset */
- if (ofs > mtd->size)
+ if (offs > mtd->size)
return -EINVAL;
- return nand_block_checkbad (mtd, ofs, 1, 0);
+ return nand_block_checkbad(mtd, offs, 1, 0);
}
/**
- * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
+ * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
* @mtd: MTD device structure
* @ofs: offset relative to mtd start
*/
-static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
+static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
int ret;
if ((ret = nand_block_isbad(mtd, ofs))) {
return ret;
}
- return this->block_markbad(mtd, ofs);
+ return chip->block_markbad(mtd, ofs);
}
/**
- * nand_scan - [NAND Interface] Scan for the NAND device
+ * nand_suspend - [MTD Interface] Suspend the NAND flash
* @mtd: MTD device structure
- * @maxchips: Number of chips to scan for
- *
- * This fills out all the not initialized function pointers
- * with the defaults.
- * The flash ID is read and the mtd/chip structures are
- * filled with the appropriate values. Buffers are allocated if
- * they are not provided by the board driver
- *
*/
-int nand_scan (struct mtd_info *mtd, int maxchips)
+static int nand_suspend(struct mtd_info *mtd)
{
- int i, j, nand_maf_id, nand_dev_id, busw;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
+
+ return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
+}
+
+/**
+ * nand_resume - [MTD Interface] Resume the NAND flash
+ * @mtd: MTD device structure
+ */
+static void nand_resume(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
- /* Get buswidth to select the correct functions*/
- busw = this->options & NAND_BUSWIDTH_16;
+ if (chip->state == FL_PM_SUSPENDED)
+ nand_release_device(mtd);
+ else
+ printk(KERN_ERR "nand_resume() called for a chip which is not "
+ "in suspended state\n");
+}
+/*
+ * Set default functions
+ */
+static void nand_set_defaults(struct nand_chip *chip, int busw)
+{
/* check for proper chip_delay setup, set 20us if not */
- if (!this->chip_delay)
- this->chip_delay = 20;
+ if (!chip->chip_delay)
+ chip->chip_delay = 20;
/* check, if a user supplied command function given */
- if (this->cmdfunc == NULL)
- this->cmdfunc = nand_command;
+ if (chip->cmdfunc == NULL)
+ chip->cmdfunc = nand_command;
/* check, if a user supplied wait function given */
- if (this->waitfunc == NULL)
- this->waitfunc = nand_wait;
-
- if (!this->select_chip)
- this->select_chip = nand_select_chip;
- if (!this->write_byte)
- this->write_byte = busw ? nand_write_byte16 : nand_write_byte;
- if (!this->read_byte)
- this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
- if (!this->write_word)
- this->write_word = nand_write_word;
- if (!this->read_word)
- this->read_word = nand_read_word;
- if (!this->block_bad)
- this->block_bad = nand_block_bad;
- if (!this->block_markbad)
- this->block_markbad = nand_default_block_markbad;
- if (!this->write_buf)
- this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
- if (!this->read_buf)
- this->read_buf = busw ? nand_read_buf16 : nand_read_buf;
- if (!this->verify_buf)
- this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
- if (!this->scan_bbt)
- this->scan_bbt = nand_default_bbt;
+ if (chip->waitfunc == NULL)
+ chip->waitfunc = nand_wait;
+
+ if (!chip->select_chip)
+ chip->select_chip = nand_select_chip;
+ if (!chip->read_byte)
+ chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
+ if (!chip->read_word)
+ chip->read_word = nand_read_word;
+ if (!chip->block_bad)
+ chip->block_bad = nand_block_bad;
+ if (!chip->block_markbad)
+ chip->block_markbad = nand_default_block_markbad;
+ if (!chip->write_buf)
+ chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
+ if (!chip->read_buf)
+ chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
+ if (!chip->verify_buf)
+ chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
+ if (!chip->scan_bbt)
+ chip->scan_bbt = nand_default_bbt;
+
+ if (!chip->controller) {
+ chip->controller = &chip->hwcontrol;
+
+ /* XXX U-BOOT XXX */
+#if 0
+ spin_lock_init(&chip->controller->lock);
+ init_waitqueue_head(&chip->controller->wq);
+#endif
+ }
+
+}
+
+/*
+ * Get the flash and manufacturer id and lookup if the type is supported
+ */
+static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ int busw, int *maf_id)
+{
+ struct nand_flash_dev *type = NULL;
+ int i, dev_id, maf_idx;
/* Select the device */
- this->select_chip(mtd, 0);
+ chip->select_chip(mtd, 0);
/* Send the command for reading device ID */
- this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read manufacturer and device IDs */
- nand_maf_id = this->read_byte(mtd);
- nand_dev_id = this->read_byte(mtd);
+ *maf_id = chip->read_byte(mtd);
+ dev_id = chip->read_byte(mtd);
- /* Print and store flash device information */
+ /* Lookup the flash id */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+ if (dev_id == nand_flash_ids[i].id) {
+ type = &nand_flash_ids[i];
+ break;
+ }
+ }
- if (nand_dev_id != nand_flash_ids[i].id)
- continue;
+ if (!type)
+ return ERR_PTR(-ENODEV);
+
+ if (!mtd->name)
+ mtd->name = type->name;
+
+ chip->chipsize = type->chipsize << 20;
+
+ /* Newer devices have all the information in additional id bytes */
+ if (!type->pagesize) {
+ int extid;
+ /* The 3rd id byte holds MLC / multichip data */
+ chip->cellinfo = chip->read_byte(mtd);
+ /* The 4th id byte is the important one */
+ extid = chip->read_byte(mtd);
+ /* Calc pagesize */
+ mtd->writesize = 1024 << (extid & 0x3);
+ extid >>= 2;
+ /* Calc oobsize */
+ mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
+ extid >>= 2;
+ /* Calc blocksize. Blocksize is multiples of 64KiB */
+ mtd->erasesize = (64 * 1024) << (extid & 0x03);
+ extid >>= 2;
+ /* Get buswidth information */
+ busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
- if (!mtd->name) mtd->name = nand_flash_ids[i].name;
- this->chipsize = nand_flash_ids[i].chipsize << 20;
-
- /* New devices have all the information in additional id bytes */
- if (!nand_flash_ids[i].pagesize) {
- int extid;
- /* The 3rd id byte contains non relevant data ATM */
- extid = this->read_byte(mtd);
- /* The 4th id byte is the important one */
- extid = this->read_byte(mtd);
- /* Calc pagesize */
- mtd->oobblock = 1024 << (extid & 0x3);
- extid >>= 2;
- /* Calc oobsize */
- mtd->oobsize = (8 << (extid & 0x01)) * (mtd->oobblock / 512);
- extid >>= 2;
- /* Calc blocksize. Blocksize is multiples of 64KiB */
- mtd->erasesize = (64 * 1024) << (extid & 0x03);
- extid >>= 2;
- /* Get buswidth information */
- busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+ } else {
+ /*
+ * Old devices have chip data hardcoded in the device id table
+ */
+ mtd->erasesize = type->erasesize;
+ mtd->writesize = type->pagesize;
+ mtd->oobsize = mtd->writesize / 32;
+ busw = type->options & NAND_BUSWIDTH_16;
+ }
- } else {
- /* Old devices have this data hardcoded in the
- * device id table */
- mtd->erasesize = nand_flash_ids[i].erasesize;
- mtd->oobblock = nand_flash_ids[i].pagesize;
- mtd->oobsize = mtd->oobblock / 32;
- busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
- }
+ /* Try to identify manufacturer */
+ for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
+ if (nand_manuf_ids[maf_idx].id == *maf_id)
+ break;
+ }
- /* Check, if buswidth is correct. Hardware drivers should set
- * this correct ! */
- if (busw != (this->options & NAND_BUSWIDTH_16)) {
- printk (KERN_INFO "NAND device: Manufacturer ID:"
- " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
- nand_manuf_ids[i].name , mtd->name);
- printk (KERN_WARNING
- "NAND bus width %d instead %d bit\n",
- (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
- busw ? 16 : 8);
- this->select_chip(mtd, -1);
- return 1;
- }
+ /*
+ * Check, if buswidth is correct. Hardware drivers should set
+ * chip correct !
+ */
+ if (busw != (chip->options & NAND_BUSWIDTH_16)) {
+ printk(KERN_INFO "NAND device: Manufacturer ID:"
+ " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
+ dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
+ printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
+ (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
+ busw ? 16 : 8);
+ return ERR_PTR(-EINVAL);
+ }
- /* Calculate the address shift from the page size */
- this->page_shift = ffs(mtd->oobblock) - 1;
- this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
- this->chip_shift = ffs(this->chipsize) - 1;
-
- /* Set the bad block position */
- this->badblockpos = mtd->oobblock > 512 ?
- NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-
- /* Get chip options, preserve non chip based options */
- this->options &= ~NAND_CHIPOPTIONS_MSK;
- this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
- /* Set this as a default. Board drivers can override it, if neccecary */
- this->options |= NAND_NO_AUTOINCR;
- /* Check if this is a not a samsung device. Do not clear the options
- * for chips which are not having an extended id.
- */
- if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
- this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
+ /* Calculate the address shift from the page size */
+ chip->page_shift = ffs(mtd->writesize) - 1;
+ /* Convert chipsize to number of pages per chip -1. */
+ chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
- /* Check for AND chips with 4 page planes */
- if (this->options & NAND_4PAGE_ARRAY)
- this->erase_cmd = multi_erase_cmd;
- else
- this->erase_cmd = single_erase_cmd;
+ chip->bbt_erase_shift = chip->phys_erase_shift =
+ ffs(mtd->erasesize) - 1;
+ chip->chip_shift = ffs(chip->chipsize) - 1;
- /* Do not replace user supplied command function ! */
- if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
- this->cmdfunc = nand_command_lp;
+ /* Set the bad block position */
+ chip->badblockpos = mtd->writesize > 512 ?
+ NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
- /* Try to identify manufacturer */
- for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
- if (nand_manuf_ids[j].id == nand_maf_id)
- break;
- }
- break;
- }
+ /* Get chip options, preserve non chip based options */
+ chip->options &= ~NAND_CHIPOPTIONS_MSK;
+ chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
- if (!nand_flash_ids[i].name) {
-#ifndef CFG_NAND_QUIET_TEST
- printk (KERN_WARNING "No NAND device found!!!\n");
-#endif
- this->select_chip(mtd, -1);
- return 1;
- }
+ /*
+ * Set chip as a default. Board drivers can override it, if necessary
+ */
+ chip->options |= NAND_NO_AUTOINCR;
- for (i=1; i < maxchips; i++) {
- this->select_chip(mtd, i);
+ /* Check if chip is a not a samsung device. Do not clear the
+ * options for chips which are not having an extended id.
+ */
+ if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
+ chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
- /* Send the command for reading device ID */
- this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
+ /* Check for AND chips with 4 page planes */
+ if (chip->options & NAND_4PAGE_ARRAY)
+ chip->erase_cmd = multi_erase_cmd;
+ else
+ chip->erase_cmd = single_erase_cmd;
+
+ /* Do not replace user supplied command function ! */
+ if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
+ chip->cmdfunc = nand_command_lp;
+
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "NAND device: Manufacturer ID:"
+ " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
+ nand_manuf_ids[maf_idx].name, type->name);
+
+ return type;
+}
+
+/**
+ * nand_scan_ident - [NAND Interface] Scan for the NAND device
+ * @mtd: MTD device structure
+ * @maxchips: Number of chips to scan for
+ *
+ * This is the first phase of the normal nand_scan() function. It
+ * reads the flash ID and sets up MTD fields accordingly.
+ *
+ * The mtd->owner field must be set to the module of the caller.
+ */
+int nand_scan_ident(struct mtd_info *mtd, int maxchips)
+{
+ int i, busw, nand_maf_id;
+ struct nand_chip *chip = mtd->priv;
+ struct nand_flash_dev *type;
+
+ /* Get buswidth to select the correct functions */
+ busw = chip->options & NAND_BUSWIDTH_16;
+ /* Set the default functions */
+ nand_set_defaults(chip, busw);
+
+ /* Read the flash type */
+ type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
+
+ if (IS_ERR(type)) {
+ printk(KERN_WARNING "No NAND device found!!!\n");
+ chip->select_chip(mtd, -1);
+ return PTR_ERR(type);
+ }
+ /* Check for a chip array */
+ for (i = 1; i < maxchips; i++) {
+ chip->select_chip(mtd, i);
+ /* Send the command for reading device ID */
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read manufacturer and device IDs */
- if (nand_maf_id != this->read_byte(mtd) ||
- nand_dev_id != this->read_byte(mtd))
+ if (nand_maf_id != chip->read_byte(mtd) ||
+ type->id != chip->read_byte(mtd))
break;
}
if (i > 1)
printk(KERN_INFO "%d NAND chips detected\n", i);
- /* Allocate buffers, if neccecary */
- if (!this->oob_buf) {
- size_t len;
- len = mtd->oobsize << (this->phys_erase_shift - this->page_shift);
- this->oob_buf = kmalloc (len, GFP_KERNEL);
- if (!this->oob_buf) {
- printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n");
- return -ENOMEM;
- }
- this->options |= NAND_OOBBUF_ALLOC;
- }
-
- if (!this->data_buf) {
- size_t len;
- len = mtd->oobblock + mtd->oobsize;
- this->data_buf = kmalloc (len, GFP_KERNEL);
- if (!this->data_buf) {
- if (this->options & NAND_OOBBUF_ALLOC)
- kfree (this->oob_buf);
- printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n");
- return -ENOMEM;
- }
- this->options |= NAND_DATABUF_ALLOC;
- }
-
/* Store the number of chips and calc total size for mtd */
- this->numchips = i;
- mtd->size = i * this->chipsize;
- /* Convert chipsize to number of pages per chip -1. */
- this->pagemask = (this->chipsize >> this->page_shift) - 1;
- /* Preset the internal oob buffer */
- memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
-
- /* If no default placement scheme is given, select an
- * appropriate one */
- if (!this->autooob) {
- /* Select the appropriate default oob placement scheme for
- * placement agnostic filesystems */
+ chip->numchips = i;
+ mtd->size = i * chip->chipsize;
+
+ return 0;
+}
+
+
+/**
+ * nand_scan_tail - [NAND Interface] Scan for the NAND device
+ * @mtd: MTD device structure
+ * @maxchips: Number of chips to scan for
+ *
+ * This is the second phase of the normal nand_scan() function. It
+ * fills out all the uninitialized function pointers with the defaults
+ * and scans for a bad block table if appropriate.
+ */
+int nand_scan_tail(struct mtd_info *mtd)
+{
+ int i;
+ struct nand_chip *chip = mtd->priv;
+
+ if (!(chip->options & NAND_OWN_BUFFERS))
+ chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
+ if (!chip->buffers)
+ return -ENOMEM;
+
+ /* Set the internal oob buffer location, just after the page data */
+ chip->oob_poi = chip->buffers->databuf + mtd->writesize;
+
+ /*
+ * If no default placement scheme is given, select an appropriate one
+ */
+ if (!chip->ecc.layout) {
switch (mtd->oobsize) {
case 8:
- this->autooob = &nand_oob_8;
+ chip->ecc.layout = &nand_oob_8;
break;
case 16:
- this->autooob = &nand_oob_16;
+ chip->ecc.layout = &nand_oob_16;
break;
case 64:
- this->autooob = &nand_oob_64;
+ chip->ecc.layout = &nand_oob_64;
break;
case 128:
- this->autooob = &nand_oob_128;
+ chip->ecc.layout = &nand_oob_128;
break;
default:
- printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
- mtd->oobsize);
+ printk(KERN_WARNING "No oob scheme defined for "
+ "oobsize %d\n", mtd->oobsize);
/* BUG(); */
}
}
- /* The number of bytes available for the filesystem to place fs dependend
- * oob data */
- mtd->oobavail = 0;
- for (i=0; this->autooob->oobfree[i][1]; i++)
- mtd->oobavail += this->autooob->oobfree[i][1];
+ if (!chip->write_page)
+ chip->write_page = nand_write_page;
/*
- * check ECC mode, default to software
- * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize
- * fallback to software ECC
- */
- this->eccsize = 256; /* set default eccsize */
- this->eccbytes = 3;
-
- switch (this->eccmode) {
- case NAND_ECC_HW12_2048:
- if (mtd->oobblock < 2048) {
- printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",
- mtd->oobblock);
- this->eccmode = NAND_ECC_SOFT;
- this->calculate_ecc = nand_calculate_ecc;
- this->correct_data = nand_correct_data;
- } else
- this->eccsize = 2048;
- break;
-
- case NAND_ECC_HW3_512:
- case NAND_ECC_HW6_512:
- case NAND_ECC_HW8_512:
- if (mtd->oobblock == 256) {
- printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
- this->eccmode = NAND_ECC_SOFT;
- this->calculate_ecc = nand_calculate_ecc;
- this->correct_data = nand_correct_data;
- } else
- this->eccsize = 512; /* set eccsize to 512 */
- break;
+ * check ECC mode, default to software if 3byte/512byte hardware ECC is
+ * selected and we have 256 byte pagesize fallback to software ECC
+ */
+ if (!chip->ecc.read_page_raw)
+ chip->ecc.read_page_raw = nand_read_page_raw;
+ if (!chip->ecc.write_page_raw)
+ chip->ecc.write_page_raw = nand_write_page_raw;
+
+ switch (chip->ecc.mode) {
+ case NAND_ECC_HW:
+ /* Use standard hwecc read page function ? */
+ if (!chip->ecc.read_page)
+ chip->ecc.read_page = nand_read_page_hwecc;
+ if (!chip->ecc.write_page)
+ chip->ecc.write_page = nand_write_page_hwecc;
+ if (!chip->ecc.read_oob)
+ chip->ecc.read_oob = nand_read_oob_std;
+ if (!chip->ecc.write_oob)
+ chip->ecc.write_oob = nand_write_oob_std;
+
+ case NAND_ECC_HW_SYNDROME:
+ if ((!chip->ecc.calculate || !chip->ecc.correct ||
+ !chip->ecc.hwctl) &&
+ (!chip->ecc.read_page ||
+ chip->ecc.read_page == nand_read_page_hwecc ||
+ !chip->ecc.write_page ||
+ chip->ecc.write_page == nand_write_page_hwecc)) {
+ printk(KERN_WARNING "No ECC functions supplied, "
+ "Hardware ECC not possible\n");
+ BUG();
+ }
+ /* Use standard syndrome read/write page function ? */
+ if (!chip->ecc.read_page)
+ chip->ecc.read_page = nand_read_page_syndrome;
+ if (!chip->ecc.write_page)
+ chip->ecc.write_page = nand_write_page_syndrome;
+ if (!chip->ecc.read_oob)
+ chip->ecc.read_oob = nand_read_oob_syndrome;
+ if (!chip->ecc.write_oob)
+ chip->ecc.write_oob = nand_write_oob_syndrome;
+
+ if (mtd->writesize >= chip->ecc.size)
+ break;
+ printk(KERN_WARNING "%d byte HW ECC not possible on "
+ "%d byte page size, fallback to SW ECC\n",
+ chip->ecc.size, mtd->writesize);
+ chip->ecc.mode = NAND_ECC_SOFT;
- case NAND_ECC_HW3_256:
+ case NAND_ECC_SOFT:
+ chip->ecc.calculate = nand_calculate_ecc;
+ chip->ecc.correct = nand_correct_data;
+ chip->ecc.read_page = nand_read_page_swecc;
+ chip->ecc.write_page = nand_write_page_swecc;
+ chip->ecc.read_oob = nand_read_oob_std;
+ chip->ecc.write_oob = nand_write_oob_std;
+ chip->ecc.size = 256;
+ chip->ecc.bytes = 3;
break;
case NAND_ECC_NONE:
- printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");
- this->eccmode = NAND_ECC_NONE;
- break;
-
- case NAND_ECC_SOFT:
- this->calculate_ecc = nand_calculate_ecc;
- this->correct_data = nand_correct_data;
+ printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
+ "This is not recommended !!\n");
+ chip->ecc.read_page = nand_read_page_raw;
+ chip->ecc.write_page = nand_write_page_raw;
+ chip->ecc.read_oob = nand_read_oob_std;
+ chip->ecc.write_oob = nand_write_oob_std;
+ chip->ecc.size = mtd->writesize;
+ chip->ecc.bytes = 0;
break;
default:
- printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
-/* BUG(); */
- }
-
- /* Check hardware ecc function availability and adjust number of ecc bytes per
- * calculation step
- */
- switch (this->eccmode) {
- case NAND_ECC_HW12_2048:
- this->eccbytes += 4;
- case NAND_ECC_HW8_512:
- this->eccbytes += 2;
- case NAND_ECC_HW6_512:
- this->eccbytes += 3;
- case NAND_ECC_HW3_512:
- case NAND_ECC_HW3_256:
- if (this->calculate_ecc && this->correct_data && this->enable_hwecc)
- break;
- printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");
-/* BUG(); */
+ printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
+ chip->ecc.mode);
+ BUG();
}
- mtd->eccsize = this->eccsize;
+ /*
+ * The number of bytes available for a client to place data into
+ * the out of band area
+ */
+ chip->ecc.layout->oobavail = 0;
+ for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
+ chip->ecc.layout->oobavail +=
+ chip->ecc.layout->oobfree[i].length;
+ mtd->oobavail = chip->ecc.layout->oobavail;
- /* Set the number of read / write steps for one page to ensure ECC generation */
- switch (this->eccmode) {
- case NAND_ECC_HW12_2048:
- this->eccsteps = mtd->oobblock / 2048;
- break;
- case NAND_ECC_HW3_512:
- case NAND_ECC_HW6_512:
- case NAND_ECC_HW8_512:
- this->eccsteps = mtd->oobblock / 512;
- break;
- case NAND_ECC_HW3_256:
- case NAND_ECC_SOFT:
- this->eccsteps = mtd->oobblock / 256;
- break;
+ /*
+ * Set the number of read / write steps for one page depending on ECC
+ * mode
+ */
+ chip->ecc.steps = mtd->writesize / chip->ecc.size;
+ if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
+ printk(KERN_WARNING "Invalid ecc parameters\n");
+ BUG();
+ }
+ chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
- case NAND_ECC_NONE:
- this->eccsteps = 1;
- break;
+ /*
+ * Allow subpage writes up to ecc.steps. Not possible for MLC
+ * FLASH.
+ */
+ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
+ !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+ switch(chip->ecc.steps) {
+ case 2:
+ mtd->subpage_sft = 1;
+ break;
+ case 4:
+ case 8:
+ mtd->subpage_sft = 2;
+ break;
+ }
}
+ chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
-/* XXX U-BOOT XXX */
-#if 0
- /* Initialize state, waitqueue and spinlock */
- this->state = FL_READY;
- init_waitqueue_head (&this->wq);
- spin_lock_init (&this->chip_lock);
-#endif
+ /* Initialize state */
+ chip->state = FL_READY;
/* De-select the device */
- this->select_chip(mtd, -1);
+ chip->select_chip(mtd, -1);
/* Invalidate the pagebuffer reference */
- this->pagebuf = -1;
+ chip->pagebuf = -1;
/* Fill in remaining MTD driver data */
mtd->type = MTD_NANDFLASH;
- mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
- mtd->ecctype = MTD_ECC_SW;
+ mtd->flags = MTD_CAP_NANDFLASH;
mtd->erase = nand_erase;
mtd->point = NULL;
mtd->unpoint = NULL;
mtd->read = nand_read;
mtd->write = nand_write;
- mtd->read_ecc = nand_read_ecc;
- mtd->write_ecc = nand_write_ecc;
mtd->read_oob = nand_read_oob;
mtd->write_oob = nand_write_oob;
-/* XXX U-BOOT XXX */
-#if 0
- mtd->readv = NULL;
- mtd->writev = nand_writev;
- mtd->writev_ecc = nand_writev_ecc;
-#endif
mtd->sync = nand_sync;
-/* XXX U-BOOT XXX */
-#if 0
mtd->lock = NULL;
mtd->unlock = NULL;
- mtd->suspend = NULL;
- mtd->resume = NULL;
-#endif
+ mtd->suspend = nand_suspend;
+ mtd->resume = nand_resume;
mtd->block_isbad = nand_block_isbad;
mtd->block_markbad = nand_block_markbad;
- /* and make the autooob the default one */
- memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
-/* XXX U-BOOT XXX */
+ /* propagate ecc.layout to mtd_info */
+ mtd->ecclayout = chip->ecc.layout;
+
+ /* Check, if we should skip the bad block table scan */
+ if (chip->options & NAND_SKIP_BBTSCAN)
+ chip->options |= NAND_BBT_SCANNED;
+
+ return 0;
+}
+
+/* module_text_address() isn't exported, and it's mostly a pointless
+ test if this is a module _anyway_ -- they'd have to try _really_ hard
+ to call us from in-kernel code if the core NAND support is modular. */
+#ifdef MODULE
+#define caller_is_module() (1)
+#else
+#define caller_is_module() \
+ module_text_address((unsigned long)__builtin_return_address(0))
+#endif
+
+/**
+ * nand_scan - [NAND Interface] Scan for the NAND device
+ * @mtd: MTD device structure
+ * @maxchips: Number of chips to scan for
+ *
+ * This fills out all the uninitialized function pointers
+ * with the defaults.
+ * The flash ID is read and the mtd/chip structures are
+ * filled with the appropriate values.
+ * The mtd->owner field must be set to the module of the caller
+ *
+ */
+int nand_scan(struct mtd_info *mtd, int maxchips)
+{
+ int ret;
+
+ /* Many callers got this wrong, so check for it for a while... */
+ /* XXX U-BOOT XXX */
#if 0
- mtd->owner = THIS_MODULE;
+ if (!mtd->owner && caller_is_module()) {
+ printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
+ BUG();
+ }
#endif
- /* Build bad block table */
- return this->scan_bbt (mtd);
+
+ ret = nand_scan_ident(mtd, maxchips);
+ if (!ret)
+ ret = nand_scan_tail(mtd);
+ return ret;
}
/**
* nand_release - [NAND Interface] Free resources held by the NAND device
* @mtd: MTD device structure
- */
-void nand_release (struct mtd_info *mtd)
+*/
+void nand_release(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
#ifdef CONFIG_MTD_PARTITIONS
/* Deregister partitions */
- del_mtd_partitions (mtd);
+ del_mtd_partitions(mtd);
#endif
/* Deregister the device */
-/* XXX U-BOOT XXX */
+ /* XXX U-BOOT XXX */
#if 0
- del_mtd_device (mtd);
+ del_mtd_device(mtd);
#endif
- /* Free bad block table memory, if allocated */
- if (this->bbt)
- kfree (this->bbt);
- /* Buffer allocated by nand_scan ? */
- if (this->options & NAND_OOBBUF_ALLOC)
- kfree (this->oob_buf);
- /* Buffer allocated by nand_scan ? */
- if (this->options & NAND_DATABUF_ALLOC)
- kfree (this->data_buf);
+
+ /* Free bad block table memory */
+ kfree(chip->bbt);
+ if (!(chip->options & NAND_OWN_BUFFERS))
+ kfree(chip->buffers);
+}
+
+/* XXX U-BOOT XXX */
+#if 0
+EXPORT_SYMBOL_GPL(nand_scan);
+EXPORT_SYMBOL_GPL(nand_scan_ident);
+EXPORT_SYMBOL_GPL(nand_scan_tail);
+EXPORT_SYMBOL_GPL(nand_release);
+
+static int __init nand_base_init(void)
+{
+ led_trigger_register_simple("nand-disk", &nand_led_trigger);
+ return 0;
}
+static void __exit nand_base_exit(void)
+{
+ led_trigger_unregister_simple(nand_led_trigger);
+}
+
+module_init(nand_base_init);
+module_exit(nand_base_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Generic NAND flash driver code");
#endif
*
* Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
*
- * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $
+ * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
*
* Following assumptions are made:
* - bbts start at a page boundary, if autolocated on a block boundary
- * - the space neccecary for a bbt in FLASH does not exceed a block boundary
+ * - the space necessary for a bbt in FLASH does not exceed a block boundary
*
*/
#include <common.h>
-
-#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
-
#include <malloc.h>
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <asm/errno.h>
+/* XXX U-BOOT XXX */
+#if 0
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/compatmac.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#endif
+
/**
* check_pattern - [GENERIC] check if a pattern is in the buffer
* @buf: the buffer to search
* pattern area contain 0xff
*
*/
-static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
+static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
{
- int i, end;
+ int i, end = 0;
uint8_t *p = buf;
end = paglen + td->offs;
return -1;
}
- p += td->len;
- end += td->len;
if (td->options & NAND_BBT_SCANEMPTY) {
+ p += td->len;
+ end += td->len;
for (i = end; i < len; i++) {
if (*p++ != 0xff)
return -1;
}
/**
+ * check_short_pattern - [GENERIC] check if a pattern is in the buffer
+ * @buf: the buffer to search
+ * @td: search pattern descriptor
+ *
+ * Check for a pattern at the given place. Used to search bad block
+ * tables and good / bad block identifiers. Same as check_pattern, but
+ * no optional empty check
+ *
+*/
+static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
+{
+ int i;
+ uint8_t *p = buf;
+
+ /* Compare the pattern */
+ for (i = 0; i < td->len; i++) {
+ if (p[td->offs + i] != td->pattern[i])
+ return -1;
+ }
+ return 0;
+}
+
+/**
* read_bbt - [GENERIC] Read the bad block table starting from page
* @mtd: MTD device structure
* @buf: temporary buffer
* Read the bad block table starting from page.
*
*/
-static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
- int bits, int offs, int reserved_block_code)
+static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
+ int bits, int offs, int reserved_block_code)
{
int res, i, j, act = 0;
struct nand_chip *this = mtd->priv;
uint8_t msk = (uint8_t) ((1 << bits) - 1);
totlen = (num * bits) >> 3;
- from = ((loff_t)page) << this->page_shift;
+ from = ((loff_t) page) << this->page_shift;
while (totlen) {
- len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
- res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
+ len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
+ res = mtd->read(mtd, from, len, &retlen, buf);
if (res < 0) {
if (retlen != len) {
- printk (KERN_INFO "nand_bbt: Error reading bad block table\n");
+ printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
return res;
}
- printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
+ printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
}
/* Analyse data */
uint8_t tmp = (dat >> j) & msk;
if (tmp == msk)
continue;
- if (reserved_block_code &&
- (tmp == reserved_block_code)) {
- printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
- ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+ if (reserved_block_code && (tmp == reserved_block_code)) {
+ printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
+ ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
+ mtd->ecc_stats.bbtblocks++;
continue;
}
/* Leave it for now, if its matured we can move this
* message to MTD_DEBUG_LEVEL0 */
- printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
- ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+ printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
+ ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
/* Factory marked bad or worn out ? */
if (tmp == 0)
this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
else
this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
+ mtd->ecc_stats.badblocks++;
}
}
totlen -= len;
* Read the bad block table for all chips starting at a given page
* We assume that the bbt bits are in consecutive order.
*/
-static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
+static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
{
struct nand_chip *this = mtd->priv;
int res = 0, i;
return 0;
}
+/*
+ * Scan read raw data from flash
+ */
+static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+ size_t len)
+{
+ struct mtd_oob_ops ops;
+
+ ops.mode = MTD_OOB_RAW;
+ ops.ooboffs = 0;
+ ops.ooblen = mtd->oobsize;
+ ops.oobbuf = buf;
+ ops.datbuf = buf;
+ ops.len = len;
+
+ return mtd->read_oob(mtd, offs, &ops);
+}
+
+/*
+ * Scan write data with oob to flash
+ */
+static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
+ uint8_t *buf, uint8_t *oob)
+{
+ struct mtd_oob_ops ops;
+
+ ops.mode = MTD_OOB_PLACE;
+ ops.ooboffs = 0;
+ ops.ooblen = mtd->oobsize;
+ ops.datbuf = buf;
+ ops.oobbuf = oob;
+ ops.len = len;
+
+ return mtd->write_oob(mtd, offs, &ops);
+}
+
/**
* read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
* @mtd: MTD device structure
* We assume that the bbt bits are in consecutive order.
*
*/
-static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
- struct nand_bbt_descr *md)
+static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *td, struct nand_bbt_descr *md)
{
struct nand_chip *this = mtd->priv;
/* Read the primary version, if available */
if (td->options & NAND_BBT_VERSION) {
- nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
- td->version[0] = buf[mtd->oobblock + td->veroffs];
- printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
+ scan_read_raw(mtd, buf, td->pages[0] << this->page_shift,
+ mtd->writesize);
+ td->version[0] = buf[mtd->writesize + td->veroffs];
+ printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+ td->pages[0], td->version[0]);
}
/* Read the mirror version, if available */
if (md && (md->options & NAND_BBT_VERSION)) {
- nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
- md->version[0] = buf[mtd->oobblock + md->veroffs];
- printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
+ scan_read_raw(mtd, buf, md->pages[0] << this->page_shift,
+ mtd->writesize);
+ md->version[0] = buf[mtd->writesize + md->veroffs];
+ printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+ md->pages[0], md->version[0]);
}
-
return 1;
}
+/*
+ * Scan a given block full
+ */
+static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+ loff_t offs, uint8_t *buf, size_t readlen,
+ int scanlen, int len)
+{
+ int ret, j;
+
+ ret = scan_read_raw(mtd, buf, offs, readlen);
+ if (ret)
+ return ret;
+
+ for (j = 0; j < len; j++, buf += scanlen) {
+ if (check_pattern(buf, scanlen, mtd->writesize, bd))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Scan a given block partially
+ */
+static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+ loff_t offs, uint8_t *buf, int len)
+{
+ struct mtd_oob_ops ops;
+ int j, ret;
+
+ ops.ooblen = mtd->oobsize;
+ ops.oobbuf = buf;
+ ops.ooboffs = 0;
+ ops.datbuf = NULL;
+ ops.mode = MTD_OOB_PLACE;
+
+ for (j = 0; j < len; j++) {
+ /*
+ * Read the full oob until read_oob is fixed to
+ * handle single byte reads for 16 bit
+ * buswidth
+ */
+ ret = mtd->read_oob(mtd, offs, &ops);
+ if (ret)
+ return ret;
+
+ if (check_short_pattern(buf, bd))
+ return 1;
+
+ offs += mtd->writesize;
+ }
+ return 0;
+}
+
/**
* create_bbt - [GENERIC] Create a bad block table by scanning the device
* @mtd: MTD device structure
* Create a bad block table by scanning the device
* for the given good/bad block identify pattern
*/
-static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
+static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *bd, int chip)
{
struct nand_chip *this = mtd->priv;
- int i, j, numblocks, len, scanlen;
+ int i, numblocks, len, scanlen;
int startblock;
loff_t from;
- size_t readlen, ooblen;
+ size_t readlen;
+
+ MTDDEBUG (MTD_DEBUG_LEVEL0, "Scanning device for bad blocks\n");
if (bd->options & NAND_BBT_SCANALLPAGES)
len = 1 << (this->bbt_erase_shift - this->page_shift);
else
len = 1;
}
- scanlen = mtd->oobblock + mtd->oobsize;
- readlen = len * mtd->oobblock;
- ooblen = len * mtd->oobsize;
+
+ if (!(bd->options & NAND_BBT_SCANEMPTY)) {
+ /* We need only read few bytes from the OOB area */
+ scanlen = 0;
+ readlen = bd->len;
+ } else {
+ /* Full page content should be read */
+ scanlen = mtd->writesize + mtd->oobsize;
+ readlen = len * mtd->writesize;
+ }
if (chip == -1) {
- /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it
- * makes shifting and masking less painful */
+ /* Note that numblocks is 2 * (real numblocks) here, see i+=2
+ * below as it makes shifting and masking less painful */
numblocks = mtd->size >> (this->bbt_erase_shift - 1);
startblock = 0;
from = 0;
} else {
if (chip >= this->numchips) {
- printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
- chip + 1, this->numchips);
- return;
+ printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
+ chip + 1, this->numchips);
+ return -EINVAL;
}
numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
startblock = chip * numblocks;
}
for (i = startblock; i < numblocks;) {
- nand_read_raw (mtd, buf, from, readlen, ooblen);
- for (j = 0; j < len; j++) {
- if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
- this->bbt[i >> 3] |= 0x03 << (i & 0x6);
- break;
- }
+ int ret;
+
+ if (bd->options & NAND_BBT_SCANALLPAGES)
+ ret = scan_block_full(mtd, bd, from, buf, readlen,
+ scanlen, len);
+ else
+ ret = scan_block_fast(mtd, bd, from, buf, len);
+
+ if (ret < 0)
+ return ret;
+
+ if (ret) {
+ this->bbt[i >> 3] |= 0x03 << (i & 0x6);
+ MTDDEBUG (MTD_DEBUG_LEVEL0,
+ "Bad eraseblock %d at 0x%08x\n",
+ i >> 1, (unsigned int)from);
+ mtd->ecc_stats.badblocks++;
}
+
i += 2;
from += (1 << this->bbt_erase_shift);
}
+ return 0;
}
/**
* block.
* If the option NAND_BBT_PERCHIP is given, each chip is searched
* for a bbt, which contains the bad block information of this chip.
- * This is neccecary to provide support for certain DOC devices.
+ * This is necessary to provide support for certain DOC devices.
*
* The bbt ident pattern resides in the oob area of the first page
* in a block.
*/
-static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
+static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
{
struct nand_chip *this = mtd->priv;
int i, chips;
int bits, startblock, block, dir;
- int scanlen = mtd->oobblock + mtd->oobsize;
+ int scanlen = mtd->writesize + mtd->oobsize;
int bbtblocks;
+ int blocktopage = this->bbt_erase_shift - this->page_shift;
/* Search direction top -> down ? */
if (td->options & NAND_BBT_LASTBLOCK) {
- startblock = (mtd->size >> this->bbt_erase_shift) -1;
+ startblock = (mtd->size >> this->bbt_erase_shift) - 1;
dir = -1;
} else {
startblock = 0;
td->pages[i] = -1;
/* Scan the maximum number of blocks */
for (block = 0; block < td->maxblocks; block++) {
+
int actblock = startblock + dir * block;
+ loff_t offs = actblock << this->bbt_erase_shift;
+
/* Read first page */
- nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
- if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
- td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
+ scan_read_raw(mtd, buf, offs, mtd->writesize);
+ if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
+ td->pages[i] = actblock << blocktopage;
if (td->options & NAND_BBT_VERSION) {
- td->version[i] = buf[mtd->oobblock + td->veroffs];
+ td->version[i] = buf[mtd->writesize + td->veroffs];
}
break;
}
/* Check, if we found a bbt for each requested chip */
for (i = 0; i < chips; i++) {
if (td->pages[i] == -1)
- printk (KERN_WARNING "Bad block table not found for chip %d\n", i);
+ printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
else
- printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
+ printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
+ td->version[i]);
}
return 0;
}
*
* Search and read the bad block table(s)
*/
-static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
- struct nand_bbt_descr *td, struct nand_bbt_descr *md)
+static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
{
/* Search the primary table */
- search_bbt (mtd, buf, td);
+ search_bbt(mtd, buf, td);
/* Search the mirror table */
if (md)
- search_bbt (mtd, buf, md);
+ search_bbt(mtd, buf, md);
/* Force result check */
return 1;
}
-
/**
* write_bbt - [GENERIC] (Re)write the bad block table
*
* (Re)write the bad block table
*
*/
-static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
- struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
+static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *td, struct nand_bbt_descr *md,
+ int chipsel)
{
struct nand_chip *this = mtd->priv;
- struct nand_oobinfo oobinfo;
struct erase_info einfo;
int i, j, res, chip = 0;
int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
- int nrchips, bbtoffs, pageoffs;
+ int nrchips, bbtoffs, pageoffs, ooboffs;
uint8_t msk[4];
uint8_t rcode = td->reserved_block_code;
size_t retlen, len = 0;
loff_t to;
+ struct mtd_oob_ops ops;
+
+ ops.ooblen = mtd->oobsize;
+ ops.ooboffs = 0;
+ ops.datbuf = NULL;
+ ops.mode = MTD_OOB_PLACE;
if (!rcode)
rcode = 0xff;
/* Write bad block table per chip rather than per device ? */
if (td->options & NAND_BBT_PERCHIP) {
- numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
+ numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
/* Full device write or specific chip ? */
if (chipsel == -1) {
nrchips = this->numchips;
chip = chipsel;
}
} else {
- numblocks = (int) (mtd->size >> this->bbt_erase_shift);
+ numblocks = (int)(mtd->size >> this->bbt_erase_shift);
nrchips = 1;
}
for (i = 0; i < td->maxblocks; i++) {
int block = startblock + dir * i;
/* Check, if the block is bad */
- switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) {
+ switch ((this->bbt[block >> 2] >>
+ (2 * (block & 0x03))) & 0x03) {
case 0x01:
case 0x03:
continue;
}
- page = block << (this->bbt_erase_shift - this->page_shift);
+ page = block <<
+ (this->bbt_erase_shift - this->page_shift);
/* Check, if the block is used by the mirror table */
if (!md || md->pages[chip] != page)
goto write;
}
- printk (KERN_ERR "No space left to write bad block table\n");
+ printk(KERN_ERR "No space left to write bad block table\n");
return -ENOSPC;
-write:
+ write:
/* Set up shift count and masks for the flash table */
bits = td->options & NAND_BBT_NRBITS_MSK;
+ msk[2] = ~rcode;
switch (bits) {
- case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break;
- case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break;
- case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break;
- case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
+ case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
+ msk[3] = 0x01;
+ break;
+ case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
+ msk[3] = 0x03;
+ break;
+ case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
+ msk[3] = 0x0f;
+ break;
+ case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
+ msk[3] = 0xff;
+ break;
default: return -EINVAL;
}
to = ((loff_t) page) << this->page_shift;
- memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
- oobinfo.useecc = MTD_NANDECC_PLACEONLY;
-
/* Must we save the block contents ? */
if (td->options & NAND_BBT_SAVECONTENT) {
/* Make it block aligned */
to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
len = 1 << this->bbt_erase_shift;
- res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
+ res = mtd->read(mtd, to, len, &retlen, buf);
if (res < 0) {
if (retlen != len) {
- printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n");
+ printk(KERN_INFO "nand_bbt: Error "
+ "reading block for writing "
+ "the bad block table\n");
return res;
}
- printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
+ printk(KERN_WARNING "nand_bbt: ECC error "
+ "while reading block for writing "
+ "bad block table\n");
}
+ /* Read oob data */
+ ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
+ ops.oobbuf = &buf[len];
+ res = mtd->read_oob(mtd, to + mtd->writesize, &ops);
+ if (res < 0 || ops.oobretlen != ops.ooblen)
+ goto outerr;
+
/* Calc the byte offset in the buffer */
pageoffs = page - (int)(to >> this->page_shift);
offs = pageoffs << this->page_shift;
/* Preset the bbt area with 0xff */
- memset (&buf[offs], 0xff, (size_t)(numblocks >> sft));
- /* Preset the bbt's oob area with 0xff */
- memset (&buf[len + pageoffs * mtd->oobsize], 0xff,
- ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
- if (td->options & NAND_BBT_VERSION) {
- buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
- }
+ memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
+ ooboffs = len + (pageoffs * mtd->oobsize);
+
} else {
/* Calc length */
len = (size_t) (numblocks >> sft);
/* Make it page aligned ! */
- len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1);
+ len = (len + (mtd->writesize - 1)) &
+ ~(mtd->writesize - 1);
/* Preset the buffer with 0xff */
- memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
+ memset(buf, 0xff, len +
+ (len >> this->page_shift)* mtd->oobsize);
offs = 0;
+ ooboffs = len;
/* Pattern is located in oob area of first page */
- memcpy (&buf[len + td->offs], td->pattern, td->len);
- if (td->options & NAND_BBT_VERSION) {
- buf[len + td->veroffs] = td->version[chip];
- }
+ memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
}
+ if (td->options & NAND_BBT_VERSION)
+ buf[ooboffs + td->veroffs] = td->version[chip];
+
/* walk through the memory table */
- for (i = 0; i < numblocks; ) {
+ for (i = 0; i < numblocks;) {
uint8_t dat;
dat = this->bbt[bbtoffs + (i >> 2)];
- for (j = 0; j < 4; j++ , i++) {
+ for (j = 0; j < 4; j++, i++) {
int sftcnt = (i << (3 - sft)) & sftmsk;
/* Do not store the reserved bbt blocks ! */
- buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
+ buf[offs + (i >> sft)] &=
+ ~(msk[dat & 0x03] << sftcnt);
dat >>= 2;
}
}
- memset (&einfo, 0, sizeof (einfo));
+ memset(&einfo, 0, sizeof(einfo));
einfo.mtd = mtd;
- einfo.addr = (unsigned long) to;
+ einfo.addr = (unsigned long)to;
einfo.len = 1 << this->bbt_erase_shift;
- res = nand_erase_nand (mtd, &einfo, 1);
- if (res < 0) {
- printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
- return res;
- }
+ res = nand_erase_nand(mtd, &einfo, 1);
+ if (res < 0)
+ goto outerr;
- res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
- if (res < 0) {
- printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
- return res;
- }
- printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
- (unsigned int) to, td->version[chip]);
+ res = scan_write_bbt(mtd, to, len, buf, &buf[len]);
+ if (res < 0)
+ goto outerr;
+
+ printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
+ "0x%02X\n", (unsigned int)to, td->version[chip]);
/* Mark it as used */
td->pages[chip] = page;
}
return 0;
+
+ outerr:
+ printk(KERN_WARNING
+ "nand_bbt: Error while writing bad block table %d\n", res);
+ return res;
}
/**
* The function creates a memory based bbt by scanning the device
* for manufacturer / software marked good / bad blocks
*/
-static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
+static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
{
struct nand_chip *this = mtd->priv;
- /* Ensure that we only scan for the pattern and nothing else */
- bd->options = 0;
- create_bbt (mtd, this->data_buf, bd, -1);
- return 0;
+ bd->options &= ~NAND_BBT_SCANEMPTY;
+ return create_bbt(mtd, this->buffers->databuf, bd, -1);
}
/**
- * check_create - [GENERIC] create and write bbt(s) if neccecary
+ * check_create - [GENERIC] create and write bbt(s) if necessary
* @mtd: MTD device structure
* @buf: temporary buffer
* @bd: descriptor for the good/bad block search pattern
*
* The function checks the results of the previous call to read_bbt
- * and creates / updates the bbt(s) if neccecary
- * Creation is neccecary if no bbt was found for the chip/device
- * Update is neccecary if one of the tables is missing or the
+ * and creates / updates the bbt(s) if necessary
+ * Creation is necessary if no bbt was found for the chip/device
+ * Update is necessary if one of the tables is missing or the
* version nr. of one table is less than the other
*/
-static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
+static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
{
int i, chips, writeops, chipsel, res;
struct nand_chip *this = mtd->priv;
rd = td;
goto writecheck;
}
-create:
+ create:
/* Create the bad block table by scanning the device ? */
if (!(td->options & NAND_BBT_CREATE))
continue;
/* Create the table in memory by scanning the chip(s) */
- create_bbt (mtd, buf, bd, chipsel);
+ create_bbt(mtd, buf, bd, chipsel);
td->version[i] = 1;
if (md)
md->version[i] = 1;
-writecheck:
+ writecheck:
/* read back first ? */
if (rd)
- read_abs_bbt (mtd, buf, rd, chipsel);
+ read_abs_bbt(mtd, buf, rd, chipsel);
/* If they weren't versioned, read both. */
if (rd2)
- read_abs_bbt (mtd, buf, rd2, chipsel);
+ read_abs_bbt(mtd, buf, rd2, chipsel);
/* Write the bad block table to the device ? */
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
- res = write_bbt (mtd, buf, td, md, chipsel);
+ res = write_bbt(mtd, buf, td, md, chipsel);
if (res < 0)
return res;
}
/* Write the mirror bad block table to the device ? */
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
- res = write_bbt (mtd, buf, md, td, chipsel);
+ res = write_bbt(mtd, buf, md, td, chipsel);
if (res < 0)
return res;
}
* accidental erasures / writes. The regions are identified by
* the mark 0x02.
*/
-static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
+static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
{
struct nand_chip *this = mtd->priv;
int i, j, chips, block, nrblocks, update;
for (i = 0; i < chips; i++) {
if ((td->options & NAND_BBT_ABSPAGE) ||
!(td->options & NAND_BBT_WRITE)) {
- if (td->pages[i] == -1) continue;
+ if (td->pages[i] == -1)
+ continue;
block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
block <<= 1;
oldval = this->bbt[(block >> 3)];
oldval = this->bbt[(block >> 3)];
newval = oldval | (0x2 << (block & 0x06));
this->bbt[(block >> 3)] = newval;
- if (oldval != newval) update = 1;
+ if (oldval != newval)
+ update = 1;
block += 2;
}
/* If we want reserved blocks to be recorded to flash, and some
* by calling the nand_free_bbt function.
*
*/
-int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
+int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
{
struct nand_chip *this = mtd->priv;
int len, res = 0;
struct nand_bbt_descr *md = this->bbt_md;
len = mtd->size >> (this->bbt_erase_shift + 2);
- /* Allocate memory (2bit per block) */
- this->bbt = kmalloc (len, GFP_KERNEL);
+ /* Allocate memory (2bit per block) and clear the memory bad block table */
+ this->bbt = kzalloc(len, GFP_KERNEL);
if (!this->bbt) {
- printk (KERN_ERR "nand_scan_bbt: Out of memory\n");
+ printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
return -ENOMEM;
}
- /* Clear the memory bad block table */
- memset (this->bbt, 0x00, len);
/* If no primary table decriptor is given, scan the device
* to build a memory based bad block table
*/
- if (!td)
- return nand_memory_bbt(mtd, bd);
+ if (!td) {
+ if ((res = nand_memory_bbt(mtd, bd))) {
+ printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+ kfree(this->bbt);
+ this->bbt = NULL;
+ }
+ return res;
+ }
/* Allocate a temporary buffer for one eraseblock incl. oob */
len = (1 << this->bbt_erase_shift);
len += (len >> this->page_shift) * mtd->oobsize;
- buf = kmalloc (len, GFP_KERNEL);
+ buf = vmalloc(len);
if (!buf) {
- printk (KERN_ERR "nand_bbt: Out of memory\n");
- kfree (this->bbt);
+ printk(KERN_ERR "nand_bbt: Out of memory\n");
+ kfree(this->bbt);
this->bbt = NULL;
return -ENOMEM;
}
/* Is the bbt at a given page ? */
if (td->options & NAND_BBT_ABSPAGE) {
- res = read_abs_bbts (mtd, buf, td, md);
+ res = read_abs_bbts(mtd, buf, td, md);
} else {
/* Search the bad block table using a pattern in oob */
- res = search_read_bbts (mtd, buf, td, md);
+ res = search_read_bbts(mtd, buf, td, md);
}
if (res)
- res = check_create (mtd, buf, bd);
+ res = check_create(mtd, buf, bd);
/* Prevent the bbt regions from erasing / writing */
- mark_bbt_region (mtd, td);
+ mark_bbt_region(mtd, td);
if (md)
- mark_bbt_region (mtd, md);
+ mark_bbt_region(mtd, md);
- kfree (buf);
+ vfree(buf);
return res;
}
-
/**
* nand_update_bbt - [NAND Interface] update bad block table(s)
* @mtd: MTD device structure
*
* The function updates the bad block table(s)
*/
-int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
+int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
{
struct nand_chip *this = mtd->priv;
int len, res = 0, writeops = 0;
/* Allocate a temporary buffer for one eraseblock incl. oob */
len = (1 << this->bbt_erase_shift);
len += (len >> this->page_shift) * mtd->oobsize;
- buf = kmalloc (len, GFP_KERNEL);
+ buf = kmalloc(len, GFP_KERNEL);
if (!buf) {
- printk (KERN_ERR "nand_update_bbt: Out of memory\n");
+ printk(KERN_ERR "nand_update_bbt: Out of memory\n");
return -ENOMEM;
}
/* Do we have a bbt per chip ? */
if (td->options & NAND_BBT_PERCHIP) {
- chip = (int) (offs >> this->chip_shift);
+ chip = (int)(offs >> this->chip_shift);
chipsel = chip;
} else {
chip = 0;
/* Write the bad block table to the device ? */
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
- res = write_bbt (mtd, buf, td, md, chipsel);
+ res = write_bbt(mtd, buf, td, md, chipsel);
if (res < 0)
goto out;
}
/* Write the mirror bad block table to the device ? */
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
- res = write_bbt (mtd, buf, md, td, chipsel);
+ res = write_bbt(mtd, buf, md, td, chipsel);
}
-out:
- kfree (buf);
+ out:
+ kfree(buf);
return res;
}
/* Define some generic bad / good block scan pattern which are used
- * while scanning a device for factory marked good / bad blocks
- *
- * The memory based patterns just
- */
+ * while scanning a device for factory marked good / bad blocks. */
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
static struct nand_bbt_descr smallpage_memorybased = {
- .options = 0,
+ .options = NAND_BBT_SCAN2NDPAGE,
.offs = 5,
.len = 1,
.pattern = scan_ff_pattern
};
static struct nand_bbt_descr smallpage_flashbased = {
- .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+ .options = NAND_BBT_SCAN2NDPAGE,
.offs = 5,
.len = 1,
.pattern = scan_ff_pattern
};
static struct nand_bbt_descr largepage_flashbased = {
- .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+ .options = NAND_BBT_SCAN2NDPAGE,
.offs = 0,
.len = 2,
.pattern = scan_ff_pattern
* support for the device and calls the nand_scan_bbt function
*
*/
-int nand_default_bbt (struct mtd_info *mtd)
+int nand_default_bbt(struct mtd_info *mtd)
{
struct nand_chip *this = mtd->priv;
* of the good / bad information, so we _must_ store
* this information in a good / bad table during
* startup
- */
+ */
if (this->options & NAND_IS_AND) {
/* Use the default pattern descriptors */
if (!this->bbt_td) {
this->bbt_md = &bbt_mirror_descr;
}
this->options |= NAND_USE_FLASH_BBT;
- return nand_scan_bbt (mtd, &agand_flashbased);
+ return nand_scan_bbt(mtd, &agand_flashbased);
}
-
/* Is a flash based bad block table requested ? */
if (this->options & NAND_USE_FLASH_BBT) {
/* Use the default pattern descriptors */
this->bbt_md = &bbt_mirror_descr;
}
if (!this->badblock_pattern) {
- this->badblock_pattern = (mtd->oobblock > 512) ?
- &largepage_flashbased : &smallpage_flashbased;
+ this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased;
}
} else {
this->bbt_td = NULL;
this->bbt_md = NULL;
if (!this->badblock_pattern) {
- this->badblock_pattern = (mtd->oobblock > 512) ?
- &largepage_memorybased : &smallpage_memorybased;
+ this->badblock_pattern = (mtd->writesize > 512) ?
+ &largepage_memorybased : &smallpage_memorybased;
}
}
- return nand_scan_bbt (mtd, this->badblock_pattern);
+ return nand_scan_bbt(mtd, this->badblock_pattern);
}
/**
* @offs: offset in the device
* @allowbbt: allow access to bad block table region
*
- */
-int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
+*/
+int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
{
struct nand_chip *this = mtd->priv;
int block;
- uint8_t res;
+ uint8_t res;
/* Get block number * 2 */
- block = (int) (offs >> (this->bbt_erase_shift - 1));
+ block = (int)(offs >> (this->bbt_erase_shift - 1));
res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
MTDDEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: "
"(block %d) 0x%02x\n", (unsigned int)offs, res, block >> 1);
switch ((int)res) {
- case 0x00: return 0;
- case 0x01: return 1;
- case 0x02: return allowbbt ? 0 : 1;
+ case 0x00:
+ return 0;
+ case 0x01:
+ return 1;
+ case 0x02:
+ return allowbbt ? 0 : 1;
}
return 1;
}
+/* XXX U-BOOT XXX */
+#if 0
+EXPORT_SYMBOL(nand_scan_bbt);
+EXPORT_SYMBOL(nand_default_bbt);
#endif
* Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
* Toshiba America Electronics Components, Inc.
*
- * $Id: nand_ecc.c,v 1.14 2004/06/16 15:34:37 gleixner Exp $
+ * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#include <common.h>
-#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+/* XXX U-BOOT XXX */
+#if 0
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/nand_ecc.h>
+#endif
#include<linux/mtd/mtd.h>
return 0;
}
+/* XXX U-BOOT XXX */
+#if 0
+EXPORT_SYMBOL(nand_calculate_ecc);
+#endif
#endif /* CONFIG_NAND_SPL */
static inline int countbits(uint32_t byte)
return -1;
}
+/* XXX U-BOOT XXX */
+#if 0
+EXPORT_SYMBOL(nand_correct_data);
#endif
* drivers/mtd/nandids.c
*
* Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
- *
- * $Id: nand_ids.c,v 1.10 2004/05/26 13:40:12 gleixner Exp $
+ *
+ * $Id: nand_ids.c,v 1.16 2005/11/07 11:14:31 gleixner Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
*/
#include <common.h>
-
-#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
-
#include <linux/mtd/nand.h>
-
/*
* Chip ID list
*
* 512 512 Byte page size
*/
struct nand_flash_dev nand_flash_ids[] = {
+
+#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
{"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
{"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
{"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
{"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
{"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
{"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
- {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
+ {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
{"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
{"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
{"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
{"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
+#endif
{"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
{"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
{"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
+ {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0},
{"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
{"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+ {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+ {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
- /* These are the new chips with large page size. The pagesize
- * and the erasesize is determined from the extended id bytes
- */
+ /*
+ * These are the new chips with large page size. The pagesize and the
+ * erasesize is determined from the extended id bytes
+ */
+#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR)
+#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
+
+ /*512 Megabit */
+ {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS},
+ {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS},
+ {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16},
+ {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16},
+
/* 1 Gigabit */
- {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
- {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+ {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS},
+ {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS},
+ {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16},
+ {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16},
/* 2 Gigabit */
- {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
- {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+ {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS},
+ {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, LP_OPTIONS},
+ {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, LP_OPTIONS16},
+ {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, LP_OPTIONS16},
/* 4 Gigabit */
- {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
- {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+ {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, LP_OPTIONS},
+ {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, LP_OPTIONS},
+ {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, LP_OPTIONS16},
+ {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, LP_OPTIONS16},
/* 8 Gigabit */
- {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
- {"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+ {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS},
+ {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS},
+ {"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16},
+ {"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, LP_OPTIONS16},
/* 16 Gigabit */
- {"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
- {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
- {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-
- /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
- * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
- * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
- * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
- * There are more speed improvements for reads and writes possible, but not implemented now
+ {"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, LP_OPTIONS},
+ {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, LP_OPTIONS},
+ {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16},
+ {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16},
+
+ /*
+ * Renesas AND 1 Gigabit. Those chips do not support extended id and
+ * have a strange page/block layout ! The chosen minimum erasesize is
+ * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page
+ * planes 1 block = 2 pages, but due to plane arrangement the blocks
+ * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would
+ * increase the eraseblock size so we chose a combined one which can be
+ * erased in one go There are more speed improvements for reads and
+ * writes possible, but not implemented now
*/
- {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},
+ {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000,
+ NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY |
+ BBT_AUTO_REFRESH
+ },
{NULL,}
};
{NAND_MFR_NATIONAL, "National"},
{NAND_MFR_RENESAS, "Renesas"},
{NAND_MFR_STMICRO, "ST Micro"},
+ {NAND_MFR_HYNIX, "Hynix"},
{NAND_MFR_MICRON, "Micron"},
{0x0, "Unknown"}
};
-#endif
*/
#include <common.h>
-
-#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
-
#include <command.h>
#include <watchdog.h>
#include <malloc.h>
#include <div64.h>
+
+#include <asm/errno.h>
+#include <linux/mtd/mtd.h>
#include <nand.h>
#include <jffs2/jffs2.h>
int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
{
struct jffs2_unknown_node cleanmarker;
- int clmpos = 0;
- int clmlen = 8;
erase_info_t erase;
ulong erase_length;
- int isNAND;
int bbtest = 1;
int result;
int percent_complete = -1;
int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL;
const char *mtd_device = meminfo->name;
+ struct mtd_oob_ops oob_opts;
+ struct nand_chip *chip = meminfo->priv;
+ uint8_t buf[64];
+ memset(buf, 0, sizeof(buf));
memset(&erase, 0, sizeof(erase));
+ memset(&oob_opts, 0, sizeof(oob_opts));
erase.mtd = meminfo;
erase.len = meminfo->erasesize;
erase.addr = opts->offset;
erase_length = opts->length;
- isNAND = meminfo->type == MTD_NANDFLASH ? 1 : 0;
-
- if (opts->jffs2) {
- cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
- cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
- if (isNAND) {
- struct nand_oobinfo *oobinfo = &meminfo->oobinfo;
-
- /* check for autoplacement */
- if (oobinfo->useecc == MTD_NANDECC_AUTOPLACE) {
- /* get the position of the free bytes */
- if (!oobinfo->oobfree[0][1]) {
- printf(" Eeep. Autoplacement selected "
- "and no empty space in oob\n");
- return -1;
- }
- clmpos = oobinfo->oobfree[0][0];
- clmlen = oobinfo->oobfree[0][1];
- if (clmlen > 8)
- clmlen = 8;
- } else {
- /* legacy mode */
- switch (meminfo->oobsize) {
- case 8:
- clmpos = 6;
- clmlen = 2;
- break;
- case 16:
- clmpos = 8;
- clmlen = 8;
- break;
- case 64:
- clmpos = 16;
- clmlen = 8;
- break;
- }
- }
- cleanmarker.totlen = cpu_to_je32(8);
- } else {
- cleanmarker.totlen =
- cpu_to_je32(sizeof(struct jffs2_unknown_node));
- }
- cleanmarker.hdr_crc = cpu_to_je32(
- crc32_no_comp(0, (unsigned char *) &cleanmarker,
- sizeof(struct jffs2_unknown_node) - 4));
- }
+ cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
+ cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
+ cleanmarker.totlen = cpu_to_je32(8);
+ cleanmarker.hdr_crc = cpu_to_je32(
+ crc32_no_comp(0, (unsigned char *) &cleanmarker,
+ sizeof(struct jffs2_unknown_node) - 4));
/* scrub option allows to erase badblock. To prevent internal
* check from erase() method, set block check method to dummy
/* format for JFFS2 ? */
if (opts->jffs2) {
- /* write cleanmarker */
- if (isNAND) {
- size_t written;
- result = meminfo->write_oob(meminfo,
- erase.addr + clmpos,
- clmlen,
- &written,
- (unsigned char *)
- &cleanmarker);
- if (result != 0) {
- printf("\n%s: MTD writeoob failure: %d\n",
- mtd_device, result);
- continue;
- }
- } else {
- printf("\n%s: this erase routine only supports"
- " NAND devices!\n",
- mtd_device);
+ chip->ops.len = chip->ops.ooblen = 64;
+ chip->ops.datbuf = NULL;
+ chip->ops.oobbuf = buf;
+ chip->ops.ooboffs = chip->badblockpos & ~0x01;
+
+ result = meminfo->write_oob(meminfo,
+ erase.addr + meminfo->oobsize,
+ &chip->ops);
+ if (result != 0) {
+ printf("\n%s: MTD writeoob failure: %d\n",
+ mtd_device, result);
+ continue;
}
+ else
+ printf("%s: MTD writeoob at 0x%08x\n",mtd_device, erase.addr + meminfo->oobsize );
}
if (!opts->quiet) {
percent_complete = percent;
printf("\rErasing at 0x%x -- %3d%% complete.",
- erase.addr, percent);
+ erase.addr, percent);
if (opts->jffs2 && result == 0)
- printf(" Cleanmarker written at 0x%x.",
- erase.addr);
+ printf(" Cleanmarker written at 0x%x.",
+ erase.addr);
}
}
}
return 0;
}
+/* XXX U-BOOT XXX */
+#if 0
+
#define MAX_PAGE_SIZE 2048
#define MAX_OOB_SIZE 64
static unsigned char oob_buf[MAX_OOB_SIZE];
/* OOB layouts to pass into the kernel as default */
-static struct nand_oobinfo none_oobinfo = {
+static struct nand_ecclayout none_ecclayout = {
.useecc = MTD_NANDECC_OFF,
};
-static struct nand_oobinfo jffs2_oobinfo = {
+static struct nand_ecclayout jffs2_ecclayout = {
.useecc = MTD_NANDECC_PLACE,
.eccbytes = 6,
.eccpos = { 0, 1, 2, 3, 6, 7 }
};
-static struct nand_oobinfo yaffs_oobinfo = {
+static struct nand_ecclayout yaffs_ecclayout = {
.useecc = MTD_NANDECC_PLACE,
.eccbytes = 6,
.eccpos = { 8, 9, 10, 13, 14, 15}
};
-static struct nand_oobinfo autoplace_oobinfo = {
+static struct nand_ecclayout autoplace_ecclayout = {
.useecc = MTD_NANDECC_AUTOPLACE
};
+#endif
-/**
- * nand_write_opts: - write image to NAND flash with support for various options
- *
- * @param meminfo NAND device to erase
- * @param opts write options (@see nand_write_options)
- * @return 0 in case of success
- *
- * This code is ported from nandwrite.c from Linux mtd utils by
- * Steven J. Hill and Thomas Gleixner.
- */
-int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
-{
- int imglen = 0;
- int pagelen;
- int baderaseblock;
- int blockstart = -1;
- loff_t offs;
- int readlen;
- int oobinfochanged = 0;
- int percent_complete = -1;
- struct nand_oobinfo old_oobinfo;
- ulong mtdoffset = opts->offset;
- ulong erasesize_blockalign;
- u_char *buffer = opts->buffer;
- size_t written;
- int result;
-
- if (opts->pad && opts->writeoob) {
- printf("Can't pad when oob data is present.\n");
- return -1;
- }
-
- /* set erasesize to specified number of blocks - to match
- * jffs2 (virtual) block size */
- if (opts->blockalign == 0) {
- erasesize_blockalign = meminfo->erasesize;
- } else {
- erasesize_blockalign = meminfo->erasesize * opts->blockalign;
- }
-
- /* make sure device page sizes are valid */
- if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)
- && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)
- && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {
- printf("Unknown flash (not normal NAND)\n");
- return -1;
- }
-
- /* read the current oob info */
- memcpy(&old_oobinfo, &meminfo->oobinfo, sizeof(old_oobinfo));
-
- /* write without ecc? */
- if (opts->noecc) {
- memcpy(&meminfo->oobinfo, &none_oobinfo,
- sizeof(meminfo->oobinfo));
- oobinfochanged = 1;
- }
-
- /* autoplace ECC? */
- if (opts->autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
-
- memcpy(&meminfo->oobinfo, &autoplace_oobinfo,
- sizeof(meminfo->oobinfo));
- oobinfochanged = 1;
- }
-
- /* force OOB layout for jffs2 or yaffs? */
- if (opts->forcejffs2 || opts->forceyaffs) {
- struct nand_oobinfo *oobsel =
- opts->forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
-
- if (meminfo->oobsize == 8) {
- if (opts->forceyaffs) {
- printf("YAFSS cannot operate on "
- "256 Byte page size\n");
- goto restoreoob;
- }
- /* Adjust number of ecc bytes */
- jffs2_oobinfo.eccbytes = 3;
- }
-
- memcpy(&meminfo->oobinfo, oobsel, sizeof(meminfo->oobinfo));
- }
-
- /* get image length */
- imglen = opts->length;
- pagelen = meminfo->oobblock
- + ((opts->writeoob != 0) ? meminfo->oobsize : 0);
-
- /* check, if file is pagealigned */
- if ((!opts->pad) && ((imglen % pagelen) != 0)) {
- printf("Input block length is not page aligned\n");
- goto restoreoob;
- }
-
- /* check, if length fits into device */
- if (((imglen / pagelen) * meminfo->oobblock)
- > (meminfo->size - opts->offset)) {
- printf("Image %d bytes, NAND page %d bytes, "
- "OOB area %u bytes, device size %u bytes\n",
- imglen, pagelen, meminfo->oobblock, meminfo->size);
- printf("Input block does not fit into device\n");
- goto restoreoob;
- }
-
- if (!opts->quiet)
- printf("\n");
-
- /* get data from input and write to the device */
- while (imglen && (mtdoffset < meminfo->size)) {
-
- WATCHDOG_RESET ();
-
- /*
- * new eraseblock, check for bad block(s). Stay in the
- * loop to be sure if the offset changes because of
- * a bad block, that the next block that will be
- * written to is also checked. Thus avoiding errors if
- * the block(s) after the skipped block(s) is also bad
- * (number of blocks depending on the blockalign
- */
- while (blockstart != (mtdoffset & (~erasesize_blockalign+1))) {
- blockstart = mtdoffset & (~erasesize_blockalign+1);
- offs = blockstart;
- baderaseblock = 0;
-
- /* check all the blocks in an erase block for
- * bad blocks */
- do {
- int ret = meminfo->block_isbad(meminfo, offs);
-
- if (ret < 0) {
- printf("Bad block check failed\n");
- goto restoreoob;
- }
- if (ret == 1) {
- baderaseblock = 1;
- if (!opts->quiet)
- printf("\rBad block at 0x%lx "
- "in erase block from "
- "0x%x will be skipped\n",
- (long) offs,
- blockstart);
- }
-
- if (baderaseblock) {
- mtdoffset = blockstart
- + erasesize_blockalign;
- }
- offs += erasesize_blockalign
- / opts->blockalign;
- } while (offs < blockstart + erasesize_blockalign);
- }
-
- readlen = meminfo->oobblock;
- if (opts->pad && (imglen < readlen)) {
- readlen = imglen;
- memset(data_buf + readlen, 0xff,
- meminfo->oobblock - readlen);
- }
-
- /* read page data from input memory buffer */
- memcpy(data_buf, buffer, readlen);
- buffer += readlen;
-
- if (opts->writeoob) {
- /* read OOB data from input memory block, exit
- * on failure */
- memcpy(oob_buf, buffer, meminfo->oobsize);
- buffer += meminfo->oobsize;
-
- /* write OOB data first, as ecc will be placed
- * in there*/
- result = meminfo->write_oob(meminfo,
- mtdoffset,
- meminfo->oobsize,
- &written,
- (unsigned char *)
- &oob_buf);
-
- if (result != 0) {
- printf("\nMTD writeoob failure: %d\n",
- result);
- goto restoreoob;
- }
- imglen -= meminfo->oobsize;
- }
-
- /* write out the page data */
- result = meminfo->write(meminfo,
- mtdoffset,
- meminfo->oobblock,
- &written,
- (unsigned char *) &data_buf);
-
- if (result != 0) {
- printf("writing NAND page at offset 0x%lx failed\n",
- mtdoffset);
- goto restoreoob;
- }
- imglen -= readlen;
-
- if (!opts->quiet) {
- unsigned long long n = (unsigned long long)
- (opts->length-imglen) * 100;
- int percent;
-
- do_div(n, opts->length);
- percent = (int)n;
-
- /* output progress message only at whole percent
- * steps to reduce the number of messages printed
- * on (slow) serial consoles
- */
- if (percent != percent_complete) {
- printf("\rWriting data at 0x%lx "
- "-- %3d%% complete.",
- mtdoffset, percent);
- percent_complete = percent;
- }
- }
-
- mtdoffset += meminfo->oobblock;
- }
-
- if (!opts->quiet)
- printf("\n");
-
-restoreoob:
- if (oobinfochanged) {
- memcpy(&meminfo->oobinfo, &old_oobinfo,
- sizeof(meminfo->oobinfo));
- }
-
- if (imglen > 0) {
- printf("Data did not fit into device, due to bad blocks\n");
- return -1;
- }
-
- /* return happy */
- return 0;
-}
-
-/**
- * nand_read_opts: - read image from NAND flash with support for various options
- *
- * @param meminfo NAND device to erase
- * @param opts read options (@see struct nand_read_options)
- * @return 0 in case of success
- *
- */
-int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)
-{
- int imglen = opts->length;
- int pagelen;
- int baderaseblock;
- int blockstart = -1;
- int percent_complete = -1;
- loff_t offs;
- size_t readlen;
- ulong mtdoffset = opts->offset;
- u_char *buffer = opts->buffer;
- int result;
-
- /* make sure device page sizes are valid */
- if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)
- && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)
- && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {
- printf("Unknown flash (not normal NAND)\n");
- return -1;
- }
-
- pagelen = meminfo->oobblock
- + ((opts->readoob != 0) ? meminfo->oobsize : 0);
-
- /* check, if length is not larger than device */
- if (((imglen / pagelen) * meminfo->oobblock)
- > (meminfo->size - opts->offset)) {
- printf("Image %d bytes, NAND page %d bytes, "
- "OOB area %u bytes, device size %u bytes\n",
- imglen, pagelen, meminfo->oobblock, meminfo->size);
- printf("Input block is larger than device\n");
- return -1;
- }
-
- if (!opts->quiet)
- printf("\n");
-
- /* get data from input and write to the device */
- while (imglen && (mtdoffset < meminfo->size)) {
-
- WATCHDOG_RESET ();
-
- /*
- * new eraseblock, check for bad block(s). Stay in the
- * loop to be sure if the offset changes because of
- * a bad block, that the next block that will be
- * written to is also checked. Thus avoiding errors if
- * the block(s) after the skipped block(s) is also bad
- * (number of blocks depending on the blockalign
- */
- while (blockstart != (mtdoffset & (~meminfo->erasesize+1))) {
- blockstart = mtdoffset & (~meminfo->erasesize+1);
- offs = blockstart;
- baderaseblock = 0;
-
- /* check all the blocks in an erase block for
- * bad blocks */
- do {
- int ret = meminfo->block_isbad(meminfo, offs);
-
- if (ret < 0) {
- printf("Bad block check failed\n");
- return -1;
- }
- if (ret == 1) {
- baderaseblock = 1;
- if (!opts->quiet)
- printf("\rBad block at 0x%lx "
- "in erase block from "
- "0x%x will be skipped\n",
- (long) offs,
- blockstart);
- }
-
- if (baderaseblock) {
- mtdoffset = blockstart
- + meminfo->erasesize;
- }
- offs += meminfo->erasesize;
-
- } while (offs < blockstart + meminfo->erasesize);
- }
-
-
- /* read page data to memory buffer */
- result = meminfo->read(meminfo,
- mtdoffset,
- meminfo->oobblock,
- &readlen,
- (unsigned char *) &data_buf);
-
- if (result != 0) {
- printf("reading NAND page at offset 0x%lx failed\n",
- mtdoffset);
- return -1;
- }
-
- if (imglen < readlen) {
- readlen = imglen;
- }
-
- memcpy(buffer, data_buf, readlen);
- buffer += readlen;
- imglen -= readlen;
-
- if (opts->readoob) {
- result = meminfo->read_oob(meminfo,
- mtdoffset,
- meminfo->oobsize,
- &readlen,
- (unsigned char *)
- &oob_buf);
-
- if (result != 0) {
- printf("\nMTD readoob failure: %d\n",
- result);
- return -1;
- }
-
-
- if (imglen < readlen) {
- readlen = imglen;
- }
-
- memcpy(buffer, oob_buf, readlen);
-
- buffer += readlen;
- imglen -= readlen;
- }
-
- if (!opts->quiet) {
- unsigned long long n = (unsigned long long)
- (opts->length-imglen) * 100;
- int percent;
-
- do_div(n, opts->length);
- percent = (int)n;
-
- /* output progress message only at whole percent
- * steps to reduce the number of messages printed
- * on (slow) serial consoles
- */
- if (percent != percent_complete) {
- if (!opts->quiet)
- printf("\rReading data from 0x%lx "
- "-- %3d%% complete.",
- mtdoffset, percent);
- percent_complete = percent;
- }
- }
-
- mtdoffset += meminfo->oobblock;
- }
-
- if (!opts->quiet)
- printf("\n");
-
- if (imglen > 0) {
- printf("Could not read entire image due to bad blocks\n");
- return -1;
- }
-
- /* return happy */
- return 0;
-}
-
+/* XXX U-BOOT XXX */
+#if 0
/******************************************************************************
* Support for locking / unlocking operations of some NAND devices
*****************************************************************************/
this->select_chip(meminfo, chipnr);
- if ((offset & (meminfo->oobblock - 1)) != 0) {
+ if ((offset & (meminfo->writesize - 1)) != 0) {
printf ("nand_get_lock_status: "
"Start address must be beginning of "
"nand page!\n");
* @param meminfo nand mtd instance
* @param start start byte address
* @param length number of bytes to unlock (must be a multiple of
- * page size nand->oobblock)
+ * page size nand->writesize)
*
* @return 0 on success, -1 in case of error
*/
goto out;
}
- if ((start & (meminfo->oobblock - 1)) != 0) {
+ if ((start & (meminfo->writesize - 1)) != 0) {
printf ("nand_unlock: Start address must be beginning of "
"nand page!\n");
ret = -1;
goto out;
}
- if (length == 0 || (length & (meminfo->oobblock - 1)) != 0) {
+ if (length == 0 || (length & (meminfo->writesize - 1)) != 0) {
printf ("nand_unlock: Length must be a multiple of nand page "
"size!\n");
ret = -1;
this->select_chip(meminfo, -1);
return ret;
}
-
#endif
+
+/**
+ * get_len_incl_bad
+ *
+ * Check if length including bad blocks fits into device.
+ *
+ * @param nand NAND device
+ * @param offset offset in flash
+ * @param length image length
+ * @return image length including bad blocks
+ */
+static size_t get_len_incl_bad (nand_info_t *nand, size_t offset,
+ const size_t length)
+{
+ size_t len_incl_bad = 0;
+ size_t len_excl_bad = 0;
+ size_t block_len;
+
+ while (len_excl_bad < length) {
+ block_len = nand->erasesize - (offset & (nand->erasesize - 1));
+
+ if (!nand_block_isbad (nand, offset & ~(nand->erasesize - 1)))
+ len_excl_bad += block_len;
+
+ len_incl_bad += block_len;
+ offset += block_len;
+
+ if ((offset + len_incl_bad) >= nand->size)
+ break;
+ }
+
+ return len_incl_bad;
+}
+
+/**
+ * nand_write_skip_bad:
+ *
+ * Write image to NAND flash.
+ * Blocks that are marked bad are skipped and the is written to the next
+ * block instead as long as the image is short enough to fit even after
+ * skipping the bad blocks.
+ *
+ * @param nand NAND device
+ * @param offset offset in flash
+ * @param length buffer length
+ * @param buf buffer to read from
+ * @return 0 in case of success
+ */
+int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
+ u_char *buffer)
+{
+ int rval;
+ size_t left_to_write = *length;
+ size_t len_incl_bad;
+ u_char *p_buffer = buffer;
+
+ /* Reject writes, which are not page aligned */
+ if ((offset & (nand->writesize - 1)) != 0 ||
+ (*length & (nand->writesize - 1)) != 0) {
+ printf ("Attempt to write non page aligned data\n");
+ return -EINVAL;
+ }
+
+ len_incl_bad = get_len_incl_bad (nand, offset, *length);
+
+ if ((offset + len_incl_bad) >= nand->size) {
+ printf ("Attempt to write outside the flash area\n");
+ return -EINVAL;
+ }
+
+ if (len_incl_bad == *length) {
+ rval = nand_write (nand, offset, length, buffer);
+ if (rval != 0) {
+ printf ("NAND write to offset %x failed %d\n",
+ offset, rval);
+ return rval;
+ }
+ }
+
+ while (left_to_write > 0) {
+ size_t block_offset = offset & (nand->erasesize - 1);
+ size_t write_size;
+
+ if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
+ printf ("Skip bad block 0x%08x\n",
+ offset & ~(nand->erasesize - 1));
+ offset += nand->erasesize - block_offset;
+ continue;
+ }
+
+ if (left_to_write < (nand->erasesize - block_offset))
+ write_size = left_to_write;
+ else
+ write_size = nand->erasesize - block_offset;
+
+ rval = nand_write (nand, offset, &write_size, p_buffer);
+ if (rval != 0) {
+ printf ("NAND write to offset %x failed %d\n",
+ offset, rval);
+ *length -= left_to_write;
+ return rval;
+ }
+
+ left_to_write -= write_size;
+ offset += write_size;
+ p_buffer += write_size;
+ }
+
+ return 0;
+}
+
+/**
+ * nand_read_skip_bad:
+ *
+ * Read image from NAND flash.
+ * Blocks that are marked bad are skipped and the next block is readen
+ * instead as long as the image is short enough to fit even after skipping the
+ * bad blocks.
+ *
+ * @param nand NAND device
+ * @param offset offset in flash
+ * @param length buffer length, on return holds remaining bytes to read
+ * @param buffer buffer to write to
+ * @return 0 in case of success
+ */
+int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
+ u_char *buffer)
+{
+ int rval;
+ size_t left_to_read = *length;
+ size_t len_incl_bad;
+ u_char *p_buffer = buffer;
+
+ len_incl_bad = get_len_incl_bad (nand, offset, *length);
+
+ if ((offset + len_incl_bad) >= nand->size) {
+ printf ("Attempt to read outside the flash area\n");
+ return -EINVAL;
+ }
+
+ if (len_incl_bad == *length) {
+ rval = nand_read (nand, offset, length, buffer);
+ if (rval != 0) {
+ printf ("NAND read from offset %x failed %d\n",
+ offset, rval);
+ return rval;
+ }
+ }
+
+ while (left_to_read > 0) {
+ size_t block_offset = offset & (nand->erasesize - 1);
+ size_t read_length;
+
+ if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
+ printf ("Skipping bad block 0x%08x\n",
+ offset & ~(nand->erasesize - 1));
+ offset += nand->erasesize - block_offset;
+ continue;
+ }
+
+ if (left_to_read < (nand->erasesize - block_offset))
+ read_length = left_to_read;
+ else
+ read_length = nand->erasesize - block_offset;
+
+ rval = nand_read (nand, offset, &read_length, p_buffer);
+ if (rval != 0) {
+ printf ("NAND read from offset %x failed %d\n",
+ offset, rval);
+ *length -= left_to_read;
+ return rval;
+ }
+
+ left_to_read -= read_length;
+ offset += read_length;
+ p_buffer += read_length;
+ }
+
+ return 0;
+}
LIB := $(obj)libnand_legacy.a
-COBJS := nand_legacy.o
+ifdef CONFIG_CMD_NAND
+COBJS-$(CONFIG_NAND_LEGACY) := nand_legacy.o
+endif
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
#include <malloc.h>
#include <asm/io.h>
#include <watchdog.h>
-
-#if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY)
-
#include <linux/mtd/nand_legacy.h>
#include <linux/mtd/nand_ids.h>
#include <jffs2/jffs2.h>
start, len, retlen, buf);
}
#endif /* CONFIG_JFFS2_NAND */
-
-#endif
LIB := $(obj)libonenand.a
-COBJS := onenand_uboot.o onenand_base.o onenand_bbt.o
+COBJS-$(CONFIG_CMD_ONENAND) := onenand_uboot.o onenand_base.o onenand_bbt.o
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
*/
#include <common.h>
-
-#ifdef CONFIG_CMD_ONENAND
-
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <asm/io.h>
#include <asm/errno.h>
+#include <malloc.h>
/* It should access 16-bit instead of 8-bit */
static inline void *memcpy_16(void *dst, const void *src, unsigned int len)
if (ctrl & ONENAND_CTRL_ERROR) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_wait: controller error = 0x%04x\n", ctrl);
+ "onenand_wait: controller error = 0x%04x\n", ctrl);
return -EAGAIN;
}
if (ctrl & ONENAND_CTRL_LOCK) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_wait: it's locked error = 0x%04x\n", ctrl);
+ "onenand_wait: it's locked error = 0x%04x\n", ctrl);
return -EIO;
}
ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
if (ecc & ONENAND_ECC_2BIT_ALL) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_wait: ECC error = 0x%04x\n", ecc);
+ "onenand_wait: ECC error = 0x%04x\n", ecc);
return -EBADMSG;
}
}
if (ONENAND_CURRENT_BUFFERRAM(this)) {
if (area == ONENAND_DATARAM)
- return mtd->oobblock;
+ return mtd->writesize;
if (area == ONENAND_SPARERAM)
return mtd->oobsize;
}
}
/**
+ * onenand_invalidate_bufferram - [GENERIC] Invalidate BufferRAM information
+ * @param mtd MTD data structure
+ * @param addr start address to invalidate
+ * @param len length to invalidate
+ *
+ * Invalidate BufferRAM information
+ */
+static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr,
+ unsigned int len)
+{
+ struct onenand_chip *this = mtd->priv;
+ int i;
+ loff_t end_addr = addr + len;
+
+ /* Invalidate BufferRAM */
+ for (i = 0; i < MAX_BUFFERRAM; i++) {
+ loff_t buf_addr = this->bufferram[i].block << this->erase_shift;
+
+ if (buf_addr >= addr && buf_addr < end_addr)
+ this->bufferram[i].valid = 0;
+ }
+}
+
+/**
* onenand_get_device - [GENERIC] Get chip for selected access
* @param mtd MTD device structure
* @param new_state the state which is requested
int ret = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_read_ecc: "
- "from = 0x%08x, len = %i\n",
- (unsigned int)from, (int)len);
+ "from = 0x%08x, len = %i\n",
+ (unsigned int)from, (int)len);
/* Do not allow reads past end of device */
if ((from + len) > mtd->size) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_read_ecc: "
- "Attempt read beyond end of device\n");
+ "Attempt read beyond end of device\n");
*retlen = 0;
return -EINVAL;
}
onenand_get_device(mtd, FL_READING);
while (read < len) {
- thislen = min_t(int, mtd->oobblock, len - read);
+ thislen = min_t(int, mtd->writesize, len - read);
- column = from & (mtd->oobblock - 1);
- if (column + thislen > mtd->oobblock)
- thislen = mtd->oobblock - column;
+ column = from & (mtd->writesize - 1);
+ if (column + thislen > mtd->writesize)
+ thislen = mtd->writesize - column;
if (!onenand_check_bufferram(mtd, from)) {
this->command(mtd, ONENAND_CMD_READ, from,
- mtd->oobblock);
+ mtd->writesize);
ret = this->wait(mtd, FL_READING);
/* First copy data and check return value for ECC handling */
onenand_update_bufferram(mtd, from, 1);
if (ret) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_read_ecc: read failed = %d\n", ret);
+ "onenand_read_ecc: read failed = %d\n", ret);
break;
}
int ret = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_read_oob: "
- "from = 0x%08x, len = %i\n",
- (unsigned int)from, (int)len);
+ "from = 0x%08x, len = %i\n",
+ (unsigned int)from, (int)len);
/* Initialize return length value */
*retlen = 0;
/* Do not allow reads past end of device */
if (unlikely((from + len) > mtd->size)) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_read_oob: "
- "Attempt read beyond end of device\n");
+ "Attempt read beyond end of device\n");
return -EINVAL;
}
if (ret) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_read_oob: read failed = %d\n", ret);
+ "onenand_read_oob: read failed = %d\n", ret);
break;
}
/* Read more? */
if (read < len) {
/* Page size */
- from += mtd->oobblock;
+ from += mtd->writesize;
column = 0;
}
}
* onenand_verify_page - [GENERIC] verify the chip contents after a write
* @param mtd MTD device structure
* @param buf the databuffer to verify
- * @param block block address
- * @param page page address
*
* Check DataRAM area directly
*/
static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
- loff_t addr, int block, int page)
+ loff_t addr)
{
struct onenand_chip *this = mtd->priv;
void __iomem *dataram0, *dataram1;
int ret = 0;
- this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);
+ this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
ret = this->wait(mtd, FL_READING);
if (ret)
/* Check, if the two dataram areas are same */
dataram0 = this->base + ONENAND_DATARAM;
- dataram1 = dataram0 + mtd->oobblock;
+ dataram1 = dataram0 + mtd->writesize;
- if (memcmp(dataram0, dataram1, mtd->oobblock))
+ if (memcmp(dataram0, dataram1, mtd->writesize))
return -EBADMSG;
return 0;
#define onenand_verify_page(...) (0)
#endif
-#define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0)
+#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)
/**
* onenand_write_ecc - [MTD Interface] OneNAND write with ECC
int ret = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_write_ecc: "
- "to = 0x%08x, len = %i\n",
- (unsigned int)to, (int)len);
+ "to = 0x%08x, len = %i\n",
+ (unsigned int)to, (int)len);
/* Initialize retlen, in case of early exit */
*retlen = 0;
/* Do not allow writes past end of device */
if (unlikely((to + len) > mtd->size)) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_ecc: "
- "Attempt write to past end of device\n");
+ "Attempt write to past end of device\n");
return -EINVAL;
}
/* Reject writes, which are not page aligned */
if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_ecc: "
- "Attempt to write not page aligned data\n");
+ "Attempt to write not page aligned data\n");
return -EINVAL;
}
/* Loop until all data write */
while (written < len) {
- int thislen = min_t(int, mtd->oobblock, len - written);
+ int thislen = min_t(int, mtd->writesize, len - written);
- this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
+ this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
mtd->oobsize);
- this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
+ this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
onenand_update_bufferram(mtd, to, 1);
ret = this->wait(mtd, FL_WRITING);
if (ret) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_write_ecc: write filaed %d\n", ret);
+ "onenand_write_ecc: write filaed %d\n", ret);
break;
}
written += thislen;
/* Only check verify write turn on */
- ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page);
+ ret = onenand_verify_page(mtd, (u_char *) buf, to);
if (ret) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_write_ecc: verify failed %d\n", ret);
+ "onenand_write_ecc: verify failed %d\n", ret);
break;
}
int written = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_write_oob: "
- "to = 0x%08x, len = %i\n",
- (unsigned int)to, (int)len);
+ "to = 0x%08x, len = %i\n",
+ (unsigned int)to, (int)len);
/* Initialize retlen, in case of early exit */
*retlen = 0;
/* Do not allow writes past end of device */
if (unlikely((to + len) > mtd->size)) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_oob: "
- "Attempt write to past end of device\n");
+ "Attempt write to past end of device\n");
return -EINVAL;
}
}
/**
+ * onenand_block_isbad_nolock - [GENERIC] Check if a block is marked bad
+ * @param mtd MTD device structure
+ * @param ofs offset from device start
+ * @param allowbbt 1, if its allowed to access the bbt area
+ *
+ * Check, if the block is bad, Either by reading the bad block table or
+ * calling of the scan function.
+ */
+static int onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allowbbt)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+
+ /* Return info from the table */
+ return bbm->isbad_bbt(mtd, ofs, allowbbt);
+}
+
+
+/**
* onenand_erase - [MTD Interface] erase block(s)
* @param mtd MTD device structure
* @param instr erase instruction
int ret = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n",
- (unsigned int)instr->addr, (unsigned int)instr->len);
+ (unsigned int)instr->addr, (unsigned int)instr->len);
block_size = (1 << this->erase_shift);
/* Start address must align on block boundary */
if (unlikely(instr->addr & (block_size - 1))) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_erase: Unaligned address\n");
+ "onenand_erase: Unaligned address\n");
return -EINVAL;
}
/* Length must align on block boundary */
if (unlikely(instr->len & (block_size - 1))) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_erase: Length not block aligned\n");
+ "onenand_erase: Length not block aligned\n");
return -EINVAL;
}
/* Do not allow erase past end of device */
if (unlikely((instr->len + instr->addr) > mtd->size)) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_erase: Erase past end of device\n");
+ "onenand_erase: Erase past end of device\n");
return -EINVAL;
}
this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
+ onenand_invalidate_bufferram(mtd, addr, block_size);
+
ret = this->wait(mtd, FL_ERASING);
/* Check, if it is write protected */
if (ret) {
if (ret == -EPERM)
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
- "Device is write protected!!!\n");
+ "Device is write protected!!!\n");
else
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
- "Failed erase, block %d\n",
- (unsigned)(addr >> this->erase_shift));
+ "Failed erase, block %d\n",
+ (unsigned)(addr >> this->erase_shift));
instr->state = MTD_ERASE_FAILED;
instr->fail_addr = addr;
goto erase_exit;
* onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
+ *
+ * Check whether the block is bad
*/
int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
- /*
- * TODO
- * 1. Bad block table (BBT)
- * -> using NAND BBT to support JFFS2
- * 2. Bad block management (BBM)
- * -> bad block replace scheme
- *
- * Currently we do nothing
- */
- return 0;
+ int ret;
+
+ /* Check for invalid offset */
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ onenand_get_device(mtd, FL_READING);
+ ret = onenand_block_isbad_nolock(mtd,ofs, 0);
+ onenand_release_device(mtd);
+ return ret;
}
/**
* onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
+ *
+ * Mark the block as bad
*/
int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- /* see above */
- return 0;
+ struct onenand_chip *this = mtd->priv;
+ int ret;
+
+ ret = onenand_block_isbad(mtd, ofs);
+ if (ret) {
+ /* If it was bad already, return success and do nothing */
+ if (ret > 0)
+ return 0;
+ return ret;
+ }
+
+ ret = this->block_markbad(mtd, ofs);
+ return ret;
}
/**
*
* Print device ID
*/
-void onenand_print_device_info(int device, int verbose)
+char * onenand_print_device_info(int device)
{
int vcc, demuxed, ddp, density;
-
- if (!verbose)
- return;
+ char *dev_info = malloc(80);
vcc = device & ONENAND_DEVICE_VCC_MASK;
demuxed = device & ONENAND_DEVICE_IS_DEMUX;
ddp = device & ONENAND_DEVICE_IS_DDP;
density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
- printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
+ sprintf(dev_info, "%sOneNAND%s %dMB %sV 16-bit (0x%02x)",
demuxed ? "" : "Muxed ",
ddp ? "(DDP)" : "",
(16 << density), vcc ? "2.65/3.3" : "1.8", device);
+
+ return dev_info;
}
static const struct onenand_manufacturers onenand_manuf_ids[] = {
/* Reset OneNAND to read default register values */
this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
- {
- int i;
- for (i = 0; i < 10000; i++) ;
- }
+ /* Wait reset */
+ this->wait(mtd, FL_RESETING);
/* Read manufacturer and device IDs from Register */
maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
}
/* Flash device information */
- onenand_print_device_info(dev_id, 0);
+ mtd->name = onenand_print_device_info(dev_id);
this->device_id = dev_id;
density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
/* OneNAND page size & block size */
/* The data buffer size is equal to page size */
- mtd->oobblock =
+ mtd->writesize =
this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
- mtd->oobsize = mtd->oobblock >> 5;
+ mtd->oobsize = mtd->writesize >> 5;
/* Pagers per block is always 64 in OneNAND */
- mtd->erasesize = mtd->oobblock << 6;
+ mtd->erasesize = mtd->writesize << 6;
this->erase_shift = ffs(mtd->erasesize) - 1;
- this->page_shift = ffs(mtd->oobblock) - 1;
+ this->page_shift = ffs(mtd->writesize) - 1;
this->ppb_shift = (this->erase_shift - this->page_shift);
- this->page_mask = (mtd->erasesize / mtd->oobblock) - 1;
+ this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
/* REVIST: Multichip handling */
this->options |= ONENAND_CONT_LOCK;
}
+ mtd->flags = MTD_CAP_NANDFLASH;
+ mtd->erase = onenand_erase;
+ mtd->read = onenand_read;
+ mtd->write = onenand_write;
+ mtd->read_oob = onenand_read_oob;
+ mtd->write_oob = onenand_write_oob;
+ mtd->sync = onenand_sync;
+ mtd->block_isbad = onenand_block_isbad;
+ mtd->block_markbad = onenand_block_markbad;
+
return 0;
}
void onenand_release(struct mtd_info *mtd)
{
}
-
-#endif /* CONFIG_CMD_ONENAND */
*/
#include <common.h>
-
-#ifdef CONFIG_CMD_ONENAND
-
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
/* No need to read pages fully,
* just read required OOB bytes */
ret = onenand_read_oob(mtd,
- from + j * mtd->oobblock +
+ from + j * mtd->writesize +
bd->offs, readlen, &retlen,
&buf[0]);
}
if (check_short_pattern
- (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+ (&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
printk(KERN_WARNING
"Bad eraseblock %d at 0x%08x\n", i >> 1,
return onenand_scan_bbt(mtd, bbm->badblock_pattern);
}
-
-#endif /* CFG_CMD_ONENAND */
*/
#include <common.h>
-
-#ifdef CONFIG_CMD_ONENAND
-
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
puts("OneNAND: ");
print_size(onenand_mtd.size, "\n");
}
-
-#endif /* CONFIG_CMD_ONENAND */
LIB := $(obj)libpci.a
-COBJS-y += fsl_pci_init.o
-COBJS-y += pci.o
-COBJS-y += pci_auto.o
-COBJS-y += pci_indirect.o
-COBJS-y += tsi108_pci.o
-COBJS-y += w83c553f.o
+COBJS-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o
+COBJS-$(CONFIG_PCI) += pci.o pci_auto.o pci_indirect.o
COBJS-$(CONFIG_SH4_PCI) += pci_sh4.o
COBJS-$(CONFIG_SH7751_PCI) +=pci_sh7751.o
COBJS-$(CONFIG_SH7780_PCI) +=pci_sh7780.o
+COBJS-$(CONFIG_TSI108_PCI) += tsi108_pci.o
+COBJS-$(CONFIG_WINBOND_83C553) += w83c553f.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
#include <common.h>
-#ifdef CONFIG_FSL_PCI_INIT
-
/*
* PCI/PCIE Controller initialization for mpc85xx/mpc86xx soc's
*
pci_hose_write_config_word(hose, dev, PCI_SEC_STATUS, 0xffff);
}
}
-
-#endif /* CONFIG_FSL_PCI */
#include <common.h>
-#ifdef CONFIG_PCI
-
#include <command.h>
#include <asm/processor.h>
#include <asm/io.h>
/* now call board specific pci_init()... */
pci_init_board();
}
-
-#endif /* CONFIG_PCI */
#include <common.h>
-#ifdef CONFIG_PCI
-
#include <pci.h>
#undef DEBUG
return sub_bus;
}
-
-#endif /* CONFIG_PCI */
#include <common.h>
-#ifdef CONFIG_PCI
#if (!defined(__I386__) && !defined(CONFIG_IXDP425))
#include <asm/processor.h>
}
#endif /* !__I386__ && !CONFIG_IXDP425 */
-#endif /* CONFIG_PCI */
#include <config.h>
-#ifdef CONFIG_TSI108_PCI
-
#include <common.h>
#include <pci.h>
#include <asm/io.h>
}
}
#endif /* CONFIG_OF_LIBFDT */
-
-#endif /* CONFIG_TSI108_PCI */
#include <common.h>
#include <config.h>
-#ifdef CFG_WINBOND_83C553
-
#include <asm/io.h>
#include <pci.h>
out8(W83C553F_DMA1 + W83C553F_DMA1_CS, 0x00);
out16(W83C553F_DMA2 + W83C553F_DMA2_CS, 0x0000);
}
-
-#endif /* CFG_WINBOND_83C553 */
LIB := $(obj)qe.a
COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
-COBJS := qe.o uccf.o uec.o uec_phy.o $(COBJS-y)
+COBJS-$(CONFIG_QE) += qe.o uccf.o uec.o uec_phy.o
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
#include "asm/immap_qe.h"
#include "qe.h"
-#if defined(CONFIG_QE)
qe_map_t *qe_immr = NULL;
static qe_snum_t snums[QE_NUM_OF_SNUM];
"fw <addr> [<length>] - Upload firmware binary at address <addr> to "
"the QE,\n\twith optional length <length> verification.\n"
);
-
-#endif /* CONFIG_QE */
#include "qe.h"
#include "uccf.h"
-#if defined(CONFIG_QE)
void ucc_fast_transmit_on_demand(ucc_fast_private_t *uccf)
{
out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
*uccf_ret = uccf;
return 0;
}
-#endif /* CONFIG_QE */
#include "uccf.h"
#include "uec.h"
#include "uec_phy.h"
-
-#if defined(CONFIG_QE)
+#include "miiphy.h"
#ifdef CONFIG_UEC_ETH1
static uec_info_t eth1_uec_info = {
};
#endif
+#define MAXCONTROLLERS (4)
+
+static struct eth_device *devlist[MAXCONTROLLERS];
+
+u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
+void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
+
static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode)
{
uec_t *uec_regs;
adjust_link(dev);
}
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
+ && !defined(BITBANGMII)
+
+/*
+ * Read a MII PHY register.
+ *
+ * Returns:
+ * 0 on success
+ */
+static int uec_miiphy_read(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value)
+{
+ *value = uec_read_phy_reg(devlist[0], addr, reg);
+
+ return 0;
+}
+
+/*
+ * Write a MII PHY register.
+ *
+ * Returns:
+ * 0 on success
+ */
+static int uec_miiphy_write(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value)
+{
+ uec_write_phy_reg(devlist[0], addr, reg, value);
+
+ return 0;
+}
+
+#endif
+
static int uec_set_mac_address(uec_private_t *uec, u8 *mac_addr)
{
uec_t *uec_regs;
return -EINVAL;
}
+ devlist[index] = dev;
+
uec->uec_info = uec_info;
sprintf(dev->name, "FSL UEC%d", index);
return err;
}
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
+ && !defined(BITBANGMII)
+ miiphy_register(dev->name, uec_miiphy_read, uec_miiphy_write);
+#endif
+
return 1;
}
-#endif /* CONFIG_QE */
#include "uec_phy.h"
#include "miiphy.h"
-#if defined(CONFIG_QE)
-
#define ugphy_printk(format, arg...) \
printf(format "\n", ## arg)
marvell_phy_interface_mode (dev, mode);
#endif
}
-#endif /* CONFIG_QE */
LIB = $(obj)librtc.a
-COBJS-y += bfin_rtc.o
+COBJS-$(CONFIG_RTC_BFIN) += bfin_rtc.o
COBJS-y += date.o
-COBJS-y += ds12887.o
-COBJS-y += ds1302.o
-COBJS-y += ds1306.o
-COBJS-y += ds1307.o
-COBJS-y += ds1337.o
-COBJS-y += ds1374.o
-COBJS-y += ds1556.o
-COBJS-y += ds164x.o
-COBJS-y += ds174x.o
-COBJS-y += ds3231.o
+COBJS-$(CONFIG_RTC_DS12887) += ds12887.o
+COBJS-$(CONFIG_RTC_DS1302) += ds1302.o
+COBJS-$(CONFIG_RTC_DS1306) += ds1306.o
+COBJS-$(CONFIG_RTC_DS1307 || CONFIG_RTC_DS1338) += ds1307.o
+COBJS-$(CONFIG_RTC_DS1337) += ds1337.o
+COBJS-$(CONFIG_RTC_DS1374) += ds1374.o
+COBJS-$(CONFIG_RTC_DS1556) += ds1556.o
+COBJS-$(CONFIG_RTC_DS164x) += ds164x.o
+COBJS-$(CONFIG_RTC_DS174x) += ds174x.o
+COBJS-$(CONFIG_RTC_DS3231) += ds3231.o
COBJS-$(CONFIG_RTC_ISL1208) += isl1208.o
-COBJS-y += m41t11.o
-COBJS-y += m41t60.o
+COBJS-$(CONFIG_RTC_M41T11) += m41t11.o
+COBJS-$(CONFIG_RTC_M41T60) += m41t60.o
COBJS-$(CONFIG_RTC_M41T62) += m41t62.o
-COBJS-y += m48t35ax.o
-COBJS-y += max6900.o
+COBJS-$(CONFIG_RTC_M48T35A) += m48t35ax.o
+COBJS-$(CONFIG_RTC_MAX6900) += max6900.o
COBJS-$(CONFIG_RTC_MC13783) += mc13783-rtc.o
-COBJS-y += mc146818.o
-COBJS-y += mcfrtc.o
-COBJS-y += mk48t59.o
-COBJS-y += mpc5xxx.o
-COBJS-y += mpc8xx.o
-COBJS-y += pcf8563.o
-COBJS-y += rs5c372.o
-COBJS-y += rx8025.o
-COBJS-y += s3c24x0_rtc.o
-COBJS-y += x1205.o
+COBJS-$(CONFIG_RTC_MC146818) += mc146818.o
+COBJS-$(CONFIG_MCFRTC) += mcfrtc.o
+COBJS-$(CONFIG_RTC_MK48T59) += mk48t59.o
+COBJS-$(CONFIG_RTC_MPC5200) += mpc5xxx.o
+COBJS-$(CONFIG_RTC_MPC8xx) += mpc8xx.o
+COBJS-$(CONFIG_RTC_PCF8563) += pcf8563.o
+COBJS-$(CONFIG_RTC_RS5C372A) += rs5c372.o
+COBJS-$(CONFIG_RTC_RX8025) += rx8025.o
+COBJS-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o
+COBJS-$(CONFIG_RTC_X1205) += x1205.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
#include <command.h>
#include <rtc.h>
-#if defined(CONFIG_RTC_BFIN) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
#include <asm/blackfin.h>
#include <asm/mach-common/bits/rtc.h>
#include <config.h>
#include <rtc.h>
-#if defined(CONFIG_RTC_DS12887) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
#define RTC_SECONDS 0x00
#define RTC_SECONDS_ALARM 0x01
#include <command.h>
#include <rtc.h>
-#if defined(CONFIG_RTC_DS1302) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/* GPP Pins */
#define DATA 0x200
#include <rtc.h>
#include <spi.h>
-#if defined(CONFIG_RTC_DS1306) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
#define RTC_SECONDS 0x00
#define RTC_MINUTES 0x01
#include <rtc.h>
#include <i2c.h>
-#if (defined(CONFIG_RTC_DS1307) || defined(CONFIG_RTC_DS1338) ) && \
- defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/*---------------------------------------------------------------------*/
#undef DEBUG_RTC
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_RTC_DS1337) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/*---------------------------------------------------------------------*/
#undef DEBUG_RTC
#include <rtc.h>
#include <i2c.h>
-#if (defined(CONFIG_RTC_DS1374)) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/*---------------------------------------------------------------------*/
#undef DEBUG_RTC
#include <command.h>
#include <rtc.h>
-
-#if defined(CONFIG_RTC_DS1556) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
static uchar rtc_read( unsigned int addr );
static void rtc_write( unsigned int addr, uchar val);
#include <rtc.h>
-#if defined(CONFIG_RTC_DS164x) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
static uchar rtc_read(unsigned int addr );
static void rtc_write(unsigned int addr, uchar val);
#include <command.h>
#include <rtc.h>
-#if defined(CONFIG_RTC_DS174x) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
static uchar rtc_read( unsigned int addr );
static void rtc_write( unsigned int addr, uchar val);
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_RTC_DS3231) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/*---------------------------------------------------------------------*/
#undef DEBUG_RTC
#endif
*/
-#if defined(CONFIG_RTC_M41T11) && defined(CFG_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
+#if defined(CFG_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
static unsigned bcd2bin (uchar n)
{
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_RTC_M41T60) && defined(CFG_I2C_RTC_ADDR) && \
- defined(CONFIG_CMD_DATE)
+#if defined(CFG_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
static unsigned bcd2bin(uchar n)
{
#include <rtc.h>
#include <config.h>
-#if defined(CONFIG_RTC_M48T35A) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_RTC_MAX6900) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
#ifndef CFG_I2C_RTC_ADDR
#define CFG_I2C_RTC_ADDR 0x50
#include <command.h>
#include <rtc.h>
-#if defined(CONFIG_RTC_MC146818) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
#include <common.h>
-#if defined(CONFIG_MCFRTC) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
#include <command.h>
#include <rtc.h>
#include <rtc.h>
#include <mk48t59.h>
-#if defined(CONFIG_RTC_MK48T59)
-
#if defined(CONFIG_BAB7xx)
static uchar rtc_read (short reg)
}
#endif
-#endif /* CONFIG_RTC_MK48T59 */
#include <command.h>
#include <rtc.h>
-#if defined(CONFIG_RTC_MPC5200) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/*****************************************************************************
* this structure should be defined in mpc5200.h ...
#include <command.h>
#include <rtc.h>
-#if defined(CONFIG_RTC_MPC8xx) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/* ------------------------------------------------------------------------- */
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_RTC_PCF8563) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_RTC_RS5C372A) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/*
* Reads are always done starting with register 15, which requires some
* jumping-through-hoops to access the data correctly.
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_RTC_RX8025) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
/*---------------------------------------------------------------------*/
#undef DEBUG_RTC
#include <common.h>
#include <command.h>
-#if defined(CONFIG_RTC_S3C24X0) && (defined(CONFIG_CMD_DATE))
+#if (defined(CONFIG_CMD_DATE))
#if defined(CONFIG_S3C2400)
#include <s3c2400.h>
#include <i2c.h>
#include <bcd.h>
-#if defined(CONFIG_RTC_X1205) && defined(CONFIG_CMD_DATE)
+#if defined(CONFIG_CMD_DATE)
#define CCR_SEC 0
#define CCR_MIN 1
COBJS-$(CONFIG_ATMEL_USART) += atmel_usart.o
COBJS-$(CONFIG_MCFUART) += mcfuart.o
-COBJS-y += ns9750_serial.o
+COBJS-$(CONFIG_NS9750_UART) += ns9750_serial.o
COBJS-y += ns16550.o
COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o
COBJS-y += serial.o
COBJS-y += serial_pl010.o
COBJS-y += serial_pl011.o
COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
-COBJS-y += serial_sh.o
+COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
COBJS-$(CONFIG_USB_TTY) += usbtty.o
COBJS := $(COBJS-y)
#include <common.h>
-#ifdef CFG_NS9750_UART
-
#include "ns9750_bbus.h" /* for GPIOs */
#include "ns9750_ser.h" /* for serial configuration */
{
return NS9750_SER_RX_CHAR_TIMER_TRUN;
}
-
-#endif /* CFG_NS9750_UART */
#ifdef CFG_NS16550_SERIAL
#include <ns16550.h>
-#ifdef CFG_NS87308
+#ifdef CONFIG_NS87308
#include <ns87308.h>
#endif
{
int clock_divisor;
-#ifdef CFG_NS87308
+#ifdef CONFIG_NS87308
initialise_ns87308();
#endif
#include <common.h>
#include <asm/processor.h>
-#ifdef CFG_SCIF_CONSOLE
-
#if defined (CONFIG_CONS_SCIF0)
#define SCIF_BASE SCIF0_BASE
#elif defined (CONFIG_CONS_SCIF1)
return ch;
}
-
-#endif /* CFG_SCIF_CONSOLE */
LIB := $(obj)libusb.a
+COBJS-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
+
COBJS-y += isp116x-hcd.o
COBJS-y += sl811_usb.o
COBJS-y += usb_ohci.o
--- /dev/null
+/*
+ * R8A66597 HCD (Host Controller Driver) for u-boot
+ *
+ * Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <common.h>
+#include <usb.h>
+#include <asm/io.h>
+
+#include "r8a66597.h"
+
+#ifdef R8A66597_DEBUG
+#define R8A66597_DPRINT printf
+#else
+#define R8A66597_DPRINT(...)
+#endif
+
+static const char hcd_name[] = "r8a66597_hcd";
+static unsigned short clock = CONFIG_R8A66597_XTAL;
+static unsigned short vif = CONFIG_R8A66597_LDRV;
+static unsigned short endian = CONFIG_R8A66597_ENDIAN;
+static struct r8a66597 gr8a66597;
+
+static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address,
+ u16 usbspd, u8 upphub, u8 hubport, int port)
+{
+ u16 val;
+ unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
+
+ val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001);
+ r8a66597_write(r8a66597, val, devadd_reg);
+}
+
+static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
+{
+ u16 tmp;
+ int i = 0;
+
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+ do {
+ r8a66597_write(r8a66597, SCKE, SYSCFG0);
+ tmp = r8a66597_read(r8a66597, SYSCFG0);
+ if (i++ > 1000) {
+ printf("register access fail.\n");
+ return -1;
+ }
+ } while ((tmp & SCKE) != SCKE);
+ r8a66597_write(r8a66597, 0x04, 0x02);
+#else
+ do {
+ r8a66597_write(r8a66597, USBE, SYSCFG0);
+ tmp = r8a66597_read(r8a66597, SYSCFG0);
+ if (i++ > 1000) {
+ printf("register access fail.\n");
+ return -1;
+ }
+ } while ((tmp & USBE) != USBE);
+ r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+ r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0);
+
+ i = 0;
+ r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+ do {
+ udelay(1000);
+ tmp = r8a66597_read(r8a66597, SYSCFG0);
+ if (i++ > 500) {
+ printf("register access fail.\n");
+ return -1;
+ }
+ } while ((tmp & SCKE) != SCKE);
+#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
+
+ return 0;
+}
+
+static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
+{
+ r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+ udelay(1);
+#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+ r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+ r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+ r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+#endif
+}
+
+static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
+{
+ u16 val;
+
+ val = port ? DRPD : DCFM | DRPD;
+ r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
+ r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+
+ r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port));
+}
+
+static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
+{
+ u16 val, tmp;
+
+ r8a66597_write(r8a66597, 0, get_intenb_reg(port));
+ r8a66597_write(r8a66597, 0, get_intsts_reg(port));
+
+ r8a66597_port_power(r8a66597, port, 0);
+
+ do {
+ tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+ udelay(640);
+ } while (tmp == EDGESTS);
+
+ val = port ? DRPD : DCFM | DRPD;
+ r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
+ r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+}
+
+static int enable_controller(struct r8a66597 *r8a66597)
+{
+ int ret, port;
+
+ ret = r8a66597_clock_enable(r8a66597);
+ if (ret < 0)
+ return ret;
+
+ r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+ r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+ r8a66597_bset(r8a66597, INTL, SOFCFG);
+ r8a66597_write(r8a66597, 0, INTENB0);
+ r8a66597_write(r8a66597, 0, INTENB1);
+ r8a66597_write(r8a66597, 0, INTENB2);
+
+ r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
+ r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
+ r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+ r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
+
+ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
+ r8a66597_enable_port(r8a66597, port);
+
+ return 0;
+}
+
+static void disable_controller(struct r8a66597 *r8a66597)
+{
+ int i;
+
+ if (!(r8a66597_read(r8a66597, SYSCFG0) & USBE))
+ return;
+
+ r8a66597_write(r8a66597, 0, INTENB0);
+ r8a66597_write(r8a66597, 0, INTSTS0);
+
+ r8a66597_write(r8a66597, 0, D0FIFOSEL);
+ r8a66597_write(r8a66597, 0, D1FIFOSEL);
+ r8a66597_write(r8a66597, 0, DCPCFG);
+ r8a66597_write(r8a66597, 0x40, DCPMAXP);
+ r8a66597_write(r8a66597, 0, DCPCTR);
+
+ for (i = 0; i <= 10; i++)
+ r8a66597_write(r8a66597, 0, get_devadd_addr(i));
+ for (i = 1; i <= 5; i++) {
+ r8a66597_write(r8a66597, 0, get_pipetre_addr(i));
+ r8a66597_write(r8a66597, 0, get_pipetrn_addr(i));
+ }
+ for (i = 1; i < R8A66597_MAX_NUM_PIPE; i++) {
+ r8a66597_write(r8a66597, 0, get_pipectr_addr(i));
+ r8a66597_write(r8a66597, i, PIPESEL);
+ r8a66597_write(r8a66597, 0, PIPECFG);
+ r8a66597_write(r8a66597, 0, PIPEBUF);
+ r8a66597_write(r8a66597, 0, PIPEMAXP);
+ r8a66597_write(r8a66597, 0, PIPEPERI);
+ }
+
+ for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++)
+ r8a66597_disable_port(r8a66597, i);
+
+ r8a66597_clock_disable(r8a66597);
+}
+
+static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
+ u16 mask, u16 loop)
+{
+ u16 tmp;
+ int i = 0;
+
+ do {
+ tmp = r8a66597_read(r8a66597, reg);
+ if (i++ > 1000000) {
+ printf("register%lx, loop %x is timeout\n", reg, loop);
+ break;
+ }
+ } while ((tmp & mask) != loop);
+}
+
+static void pipe_buffer_setting(struct r8a66597 *r8a66597,
+ struct usb_device *dev, unsigned long pipe)
+{
+ u16 val = 0;
+ u16 pipenum, bufnum, maxpacket;
+
+ if (usb_pipein(pipe)) {
+ pipenum = BULK_IN_PIPENUM;
+ bufnum = BULK_IN_BUFNUM;
+ maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
+ } else {
+ pipenum = BULK_OUT_PIPENUM;
+ bufnum = BULK_OUT_BUFNUM;
+ maxpacket = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
+ }
+
+ if (r8a66597->pipe_config & (1 << pipenum))
+ return;
+ r8a66597->pipe_config |= (1 << pipenum);
+
+ r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(pipenum));
+ r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(pipenum));
+ r8a66597_write(r8a66597, pipenum, PIPESEL);
+
+ /* FIXME: This driver support bulk transfer only. */
+ if (!usb_pipein(pipe))
+ val |= R8A66597_DIR;
+ else
+ val |= R8A66597_SHTNAK;
+ val |= R8A66597_BULK | R8A66597_DBLB | usb_pipeendpoint(pipe);
+ r8a66597_write(r8a66597, val, PIPECFG);
+
+ r8a66597_write(r8a66597, (8 << 10) | bufnum, PIPEBUF);
+ r8a66597_write(r8a66597, make_devsel(usb_pipedevice(pipe)) |
+ maxpacket, PIPEMAXP);
+ r8a66597_write(r8a66597, 0, PIPEPERI);
+ r8a66597_write(r8a66597, SQCLR, get_pipectr_addr(pipenum));
+}
+
+static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
+ struct devrequest *setup)
+{
+ int i;
+ unsigned short *p = (unsigned short *)setup;
+ unsigned long setup_addr = USBREQ;
+ u16 intsts1;
+ int timeout = 3000;
+ u16 devsel = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum;
+
+ r8a66597_write(r8a66597, make_devsel(devsel) |
+ (8 << dev->maxpacketsize), DCPMAXP);
+ r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1);
+
+ for (i = 0; i < 4; i++) {
+ r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr);
+ setup_addr += 2;
+ }
+ r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
+ r8a66597_write(r8a66597, SUREQ, DCPCTR);
+
+ while (1) {
+ intsts1 = r8a66597_read(r8a66597, INTSTS1);
+ if (intsts1 & SACK)
+ break;
+ if (intsts1 & SIGN) {
+ printf("setup packet send error\n");
+ return -1;
+ }
+ if (timeout-- < 0) {
+ printf("setup packet timeout\n");
+ return -1;
+ }
+ udelay(500);
+ }
+
+ return 0;
+}
+
+static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
+ unsigned long pipe, void *buffer, int transfer_len)
+{
+ u16 tmp, bufsize;
+ u16 *buf;
+ size_t size;
+
+ R8A66597_DPRINT("%s\n", __func__);
+
+ r8a66597_mdfy(r8a66597, MBW | BULK_OUT_PIPENUM,
+ MBW | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, BULK_OUT_PIPENUM);
+ tmp = r8a66597_read(r8a66597, CFIFOCTR);
+ if ((tmp & FRDY) == 0) {
+ printf("%s FRDY is not set (%x)\n", __func__, tmp);
+ return -1;
+ }
+
+ /* prepare parameters */
+ bufsize = dev->epmaxpacketout[usb_pipeendpoint(pipe)];
+ buf = (u16 *)(buffer + dev->act_len);
+ size = min((int)bufsize, transfer_len - dev->act_len);
+
+ /* write fifo */
+ r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
+ if (buffer) {
+ r8a66597_write_fifo(r8a66597, CFIFO, buf, size);
+ r8a66597_write(r8a66597, BVAL, CFIFOCTR);
+ }
+
+ /* update parameters */
+ dev->act_len += size;
+
+ r8a66597_mdfy(r8a66597, PID_BUF, PID,
+ get_pipectr_addr(BULK_OUT_PIPENUM));
+
+ while (!(r8a66597_read(r8a66597, BEMPSTS) & (1 << BULK_OUT_PIPENUM)))
+ if (ctrlc())
+ return -1;
+ r8a66597_write(r8a66597, ~(1 << BULK_OUT_PIPENUM), BEMPSTS);
+
+ if (dev->act_len >= transfer_len)
+ r8a66597_mdfy(r8a66597, PID_NAK, PID,
+ get_pipectr_addr(BULK_OUT_PIPENUM));
+
+ return 0;
+}
+
+static int receive_bulk_packet(struct r8a66597 *r8a66597,
+ struct usb_device *dev,
+ unsigned long pipe,
+ void *buffer, int transfer_len)
+{
+ u16 tmp;
+ u16 *buf;
+ const u16 pipenum = BULK_IN_PIPENUM;
+ int rcv_len;
+ int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)];
+
+ R8A66597_DPRINT("%s\n", __func__);
+
+ /* prepare */
+ if (dev->act_len == 0) {
+ r8a66597_mdfy(r8a66597, PID_NAK, PID,
+ get_pipectr_addr(pipenum));
+ r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
+
+ r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum));
+ r8a66597_write(r8a66597,
+ (transfer_len + maxpacket - 1) / maxpacket,
+ get_pipetrn_addr(pipenum));
+ r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum));
+
+ r8a66597_mdfy(r8a66597, PID_BUF, PID,
+ get_pipectr_addr(pipenum));
+ }
+
+ r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
+
+ while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum)))
+ if (ctrlc())
+ return -1;
+ r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
+
+ tmp = r8a66597_read(r8a66597, CFIFOCTR);
+ if ((tmp & FRDY) == 0) {
+ printf("%s FRDY is not set. (%x)\n", __func__, tmp);
+ return -1;
+ }
+
+ buf = (u16 *)(buffer + dev->act_len);
+ rcv_len = tmp & DTLN;
+ dev->act_len += rcv_len;
+
+ if (buffer) {
+ if (rcv_len == 0)
+ r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+ else
+ r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len);
+ }
+
+ return 0;
+}
+
+static int receive_control_packet(struct r8a66597 *r8a66597,
+ struct usb_device *dev,
+ void *buffer, int transfer_len)
+{
+ u16 tmp;
+ int rcv_len;
+
+ /* FIXME: limit transfer size : 64byte or less */
+
+ r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+ r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ r8a66597_bset(r8a66597, SQSET, DCPCTR);
+ r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+ r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
+
+ while (!(r8a66597_read(r8a66597, BRDYSTS) & 0x0001))
+ if (ctrlc())
+ return -1;
+ r8a66597_write(r8a66597, ~0x0001, BRDYSTS);
+
+ r8a66597_mdfy(r8a66597, MBW, MBW | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+
+ tmp = r8a66597_read(r8a66597, CFIFOCTR);
+ if ((tmp & FRDY) == 0) {
+ printf("%s FRDY is not set. (%x)\n", __func__, tmp);
+ return -1;
+ }
+
+ rcv_len = tmp & DTLN;
+ dev->act_len += rcv_len;
+
+ r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
+
+ if (buffer) {
+ if (rcv_len == 0)
+ r8a66597_write(r8a66597, BCLR, DCPCTR);
+ else
+ r8a66597_read_fifo(r8a66597, CFIFO, buffer, rcv_len);
+ }
+
+ return 0;
+}
+
+static int send_status_packet(struct r8a66597 *r8a66597,
+ unsigned long pipe)
+{
+ r8a66597_bset(r8a66597, SQSET, DCPCTR);
+ r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
+
+ if (usb_pipein(pipe)) {
+ r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+ r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+ r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR);
+ } else {
+ r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+ r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+ }
+ r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR);
+
+ while (!(r8a66597_read(r8a66597, BEMPSTS) & 0x0001))
+ if (ctrlc())
+ return -1;
+
+ return 0;
+}
+
+static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port)
+{
+ int count = R8A66597_MAX_SAMPLING;
+ unsigned short syssts, old_syssts;
+
+ R8A66597_DPRINT("%s\n", __func__);
+
+ old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
+ while (count > 0) {
+ wait_ms(R8A66597_RH_POLL_TIME);
+
+ syssts = r8a66597_read(r8a66597, get_syssts_reg(port) & LNST);
+ if (syssts == old_syssts) {
+ count--;
+ } else {
+ count = R8A66597_MAX_SAMPLING;
+ old_syssts = syssts;
+ }
+ }
+}
+
+static void r8a66597_bus_reset(struct r8a66597 *r8a66597, int port)
+{
+ wait_ms(10);
+ r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, get_dvstctr_reg(port));
+ wait_ms(50);
+ r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, get_dvstctr_reg(port));
+ wait_ms(50);
+}
+
+static int check_usb_device_connecting(struct r8a66597 *r8a66597)
+{
+ int timeout = 10000; /* 100usec * 10000 = 1sec */
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ /* check a usb cable connect */
+ while (!(r8a66597_read(r8a66597, INTSTS1) & ATTCH)) {
+ if (timeout-- < 0) {
+ printf("%s timeout.\n", __func__);
+ return -1;
+ }
+ udelay(100);
+ }
+
+ /* check a data line */
+ r8a66597_check_syssts(r8a66597, 0);
+
+ r8a66597_bus_reset(r8a66597, 0);
+ r8a66597->speed = get_rh_usb_speed(r8a66597, 0);
+
+ if (!(r8a66597_read(r8a66597, INTSTS1) & DTCH)) {
+ r8a66597->port_change = USB_PORT_STAT_C_CONNECTION;
+ r8a66597->port_status = USB_PORT_STAT_CONNECTION |
+ USB_PORT_STAT_ENABLE;
+ return 0; /* success */
+ }
+
+ R8A66597_DPRINT("USB device has detached. retry = %d\n", i);
+ r8a66597_write(r8a66597, ~DTCH, INTSTS1);
+ }
+
+ return -1; /* fail */
+}
+
+/* based on usb_ohci.c */
+#define min_t(type, x, y) \
+ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x01, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes; */
+
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+ 34, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '8', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'A', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '6', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '6', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '5', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '9', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '7', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len, struct devrequest *cmd)
+{
+ struct r8a66597 *r8a66597 = &gr8a66597;
+ int leni = transfer_len;
+ int len = 0;
+ int stat = 0;
+ __u16 bmRType_bReq;
+ __u16 wValue;
+ __u16 wIndex;
+ __u16 wLength;
+ unsigned char data[32];
+
+ R8A66597_DPRINT("%s\n", __func__);
+
+ if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
+ printf("Root-Hub submit IRQ: NOT implemented");
+ return 0;
+ }
+
+ bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+ wValue = cpu_to_le16 (cmd->value);
+ wIndex = cpu_to_le16 (cmd->index);
+ wLength = cpu_to_le16 (cmd->length);
+
+ switch (bmRType_bReq) {
+ case RH_GET_STATUS:
+ *(__u16 *)buffer = cpu_to_le16(1);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_INTERFACE:
+ *(__u16 *)buffer = cpu_to_le16(0);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_ENDPOINT:
+ *(__u16 *)buffer = cpu_to_le16(0);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_CLASS:
+ *(__u32 *)buffer = cpu_to_le32(0);
+ len = 4;
+ break;
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ *(__u32 *)buffer = cpu_to_le32(r8a66597->port_status |
+ (r8a66597->port_change << 16));
+ len = 4;
+ break;
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ break;
+
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case RH_C_PORT_CONNECTION:
+ r8a66597->port_change &= ~USB_PORT_STAT_C_CONNECTION;
+ break;
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_SUSPEND):
+ break;
+ case (RH_PORT_RESET):
+ r8a66597_bus_reset(r8a66597, 0);
+ break;
+ case (RH_PORT_POWER):
+ break;
+ case (RH_PORT_ENABLE):
+ break;
+ }
+ break;
+ case RH_SET_ADDRESS:
+ gr8a66597.rh_devnum = wValue;
+ break;
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case (0x01): /* device descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_dev_des),
+ wLength));
+ memcpy(buffer, root_hub_dev_des, len);
+ break;
+ case (0x02): /* configuration descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_config_des),
+ wLength));
+ memcpy(buffer, root_hub_config_des, len);
+ break;
+ case (0x03): /* string descriptors */
+ if (wValue == 0x0300) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_str_index0),
+ wLength));
+ memcpy(buffer, root_hub_str_index0, len);
+ }
+ if (wValue == 0x0301) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_str_index1),
+ wLength));
+ memcpy(buffer, root_hub_str_index1, len);
+ }
+ break;
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ {
+ __u32 temp = 0x00000001;
+
+ data[0] = 9; /* min length; */
+ data[1] = 0x29;
+ data[2] = temp & RH_A_NDP;
+ data[3] = 0;
+ if (temp & RH_A_PSM)
+ data[3] |= 0x1;
+ if (temp & RH_A_NOCP)
+ data[3] |= 0x10;
+ else if (temp & RH_A_OCPM)
+ data[3] |= 0x8;
+
+ /* corresponds to data[4-7] */
+ data[5] = (temp & RH_A_POTPGT) >> 24;
+ data[7] = temp & RH_B_DR;
+ if (data[2] < 7) {
+ data[8] = 0xff;
+ } else {
+ data[0] += 2;
+ data[8] = (temp & RH_B_DR) >> 8;
+ data[10] = data[9] = 0xff;
+ }
+
+ len = min_t(unsigned int, leni,
+ min_t(unsigned int, data[0], wLength));
+ memcpy(buffer, data, len);
+ break;
+ }
+
+ case RH_GET_CONFIGURATION:
+ *(__u8 *) buffer = 0x01;
+ len = 1;
+ break;
+ case RH_SET_CONFIGURATION:
+ break;
+ default:
+ dbg("unsupported root hub command");
+ stat = USB_ST_STALLED;
+ }
+
+ wait_ms(1);
+
+ len = min_t(int, len, leni);
+
+ dev->act_len = len;
+ dev->status = stat;
+
+ return stat;
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len)
+{
+ struct r8a66597 *r8a66597 = &gr8a66597;
+ int ret = 0;
+
+ R8A66597_DPRINT("%s\n", __func__);
+ R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n",
+ pipe, buffer, transfer_len, dev->devnum);
+
+ set_devadd_reg(r8a66597, dev->devnum, r8a66597->speed, 0, 0, 0);
+
+ pipe_buffer_setting(r8a66597, dev, pipe);
+
+ dev->act_len = 0;
+ while (dev->act_len < transfer_len && ret == 0) {
+ if (ctrlc())
+ return -1;
+
+ if (usb_pipein(pipe))
+ ret = receive_bulk_packet(r8a66597, dev, pipe, buffer,
+ transfer_len);
+ else
+ ret = send_bulk_packet(r8a66597, dev, pipe, buffer,
+ transfer_len);
+ }
+
+ if (ret == 0)
+ dev->status = 0;
+
+ return ret;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len, struct devrequest *setup)
+{
+ struct r8a66597 *r8a66597 = &gr8a66597;
+ u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ?
+ 0 : dev->devnum;
+
+ R8A66597_DPRINT("%s\n", __func__);
+ if (usb_pipedevice(pipe) == r8a66597->rh_devnum)
+ return r8a66597_submit_rh_msg(dev, pipe, buffer, transfer_len,
+ setup);
+
+ R8A66597_DPRINT("%s: setup\n", __func__);
+ set_devadd_reg(r8a66597, r8a66597_address, r8a66597->speed, 0, 0, 0);
+
+ if (send_setup_packet(r8a66597, dev, setup) < 0) {
+ printf("setup packet send error\n");
+ return -1;
+ }
+
+ if (usb_pipein(pipe))
+ if (receive_control_packet(r8a66597, dev, buffer,
+ transfer_len) < 0)
+ return -1;
+
+ if (send_status_packet(r8a66597, pipe) < 0)
+ return -1;
+
+ dev->status = 0;
+
+ return 0;
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, int interval)
+{
+ /* no implement */
+ R8A66597_DPRINT("%s\n", __func__);
+ return 0;
+}
+
+void usb_event_poll(void)
+{
+ /* no implement */
+ R8A66597_DPRINT("%s\n", __func__);
+}
+
+int usb_lowlevel_init(void)
+{
+ struct r8a66597 *r8a66597 = &gr8a66597;
+
+ R8A66597_DPRINT("%s\n", __func__);
+
+ memset(r8a66597, 0, sizeof(r8a66597));
+ r8a66597->reg = CONFIG_R8A66597_BASE_ADDR;
+
+ disable_controller(r8a66597);
+ wait_ms(100);
+
+ enable_controller(r8a66597);
+ r8a66597_port_power(r8a66597, 0 , 1);
+
+ /* check usb device */
+ check_usb_device_connecting(r8a66597);
+
+ wait_ms(50);
+
+ return 0;
+}
+
+int usb_lowlevel_stop(void)
+{
+ disable_controller(&gr8a66597);
+
+ return 0;
+}
--- /dev/null
+/*
+ * R8A66597 HCD (Host Controller Driver) for u-boot
+ *
+ * Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __R8A66597_H__
+#define __R8A66597_H__
+
+#define SYSCFG0 0x00
+#define SYSCFG1 0x02
+#define SYSSTS0 0x04
+#define SYSSTS1 0x06
+#define DVSTCTR0 0x08
+#define DVSTCTR1 0x0A
+#define TESTMODE 0x0C
+#define PINCFG 0x0E
+#define DMA0CFG 0x10
+#define DMA1CFG 0x12
+#define CFIFO 0x14
+#define D0FIFO 0x18
+#define D1FIFO 0x1C
+#define CFIFOSEL 0x20
+#define CFIFOCTR 0x22
+#define CFIFOSIE 0x24
+#define D0FIFOSEL 0x28
+#define D0FIFOCTR 0x2A
+#define D1FIFOSEL 0x2C
+#define D1FIFOCTR 0x2E
+#define INTENB0 0x30
+#define INTENB1 0x32
+#define INTENB2 0x34
+#define BRDYENB 0x36
+#define NRDYENB 0x38
+#define BEMPENB 0x3A
+#define SOFCFG 0x3C
+#define INTSTS0 0x40
+#define INTSTS1 0x42
+#define INTSTS2 0x44
+#define BRDYSTS 0x46
+#define NRDYSTS 0x48
+#define BEMPSTS 0x4A
+#define FRMNUM 0x4C
+#define UFRMNUM 0x4E
+#define USBADDR 0x50
+#define USBREQ 0x54
+#define USBVAL 0x56
+#define USBINDX 0x58
+#define USBLENG 0x5A
+#define DCPCFG 0x5C
+#define DCPMAXP 0x5E
+#define DCPCTR 0x60
+#define PIPESEL 0x64
+#define PIPECFG 0x68
+#define PIPEBUF 0x6A
+#define PIPEMAXP 0x6C
+#define PIPEPERI 0x6E
+#define PIPE1CTR 0x70
+#define PIPE2CTR 0x72
+#define PIPE3CTR 0x74
+#define PIPE4CTR 0x76
+#define PIPE5CTR 0x78
+#define PIPE6CTR 0x7A
+#define PIPE7CTR 0x7C
+#define PIPE8CTR 0x7E
+#define PIPE9CTR 0x80
+#define PIPE1TRE 0x90
+#define PIPE1TRN 0x92
+#define PIPE2TRE 0x94
+#define PIPE2TRN 0x96
+#define PIPE3TRE 0x98
+#define PIPE3TRN 0x9A
+#define PIPE4TRE 0x9C
+#define PIPE4TRN 0x9E
+#define PIPE5TRE 0xA0
+#define PIPE5TRN 0xA2
+#define DEVADD0 0xD0
+#define DEVADD1 0xD2
+#define DEVADD2 0xD4
+#define DEVADD3 0xD6
+#define DEVADD4 0xD8
+#define DEVADD5 0xDA
+#define DEVADD6 0xDC
+#define DEVADD7 0xDE
+#define DEVADD8 0xE0
+#define DEVADD9 0xE2
+#define DEVADDA 0xE4
+
+/* System Configuration Control Register */
+#define XTAL 0xC000 /* b15-14: Crystal selection */
+#define XTAL48 0x8000 /* 48MHz */
+#define XTAL24 0x4000 /* 24MHz */
+#define XTAL12 0x0000 /* 12MHz */
+#define XCKE 0x2000 /* b13: External clock enable */
+#define PLLC 0x0800 /* b11: PLL control */
+#define SCKE 0x0400 /* b10: USB clock enable */
+#define PCSDIS 0x0200 /* b9: not CS wakeup */
+#define LPSME 0x0100 /* b8: Low power sleep mode */
+#define HSE 0x0080 /* b7: Hi-speed enable */
+#define DCFM 0x0040 /* b6: Controller function select */
+#define DRPD 0x0020 /* b5: D+/- pull down control */
+#define DPRPU 0x0010 /* b4: D+ pull up control */
+#define USBE 0x0001 /* b0: USB module operation enable */
+
+/* System Configuration Status Register */
+#define OVCBIT 0x8000 /* b15-14: Over-current bit */
+#define OVCMON 0xC000 /* b15-14: Over-current monitor */
+#define SOFEA 0x0020 /* b5: SOF monitor */
+#define IDMON 0x0004 /* b3: ID-pin monitor */
+#define LNST 0x0003 /* b1-0: D+, D- line status */
+#define SE1 0x0003 /* SE1 */
+#define FS_KSTS 0x0002 /* Full-Speed K State */
+#define FS_JSTS 0x0001 /* Full-Speed J State */
+#define LS_JSTS 0x0002 /* Low-Speed J State */
+#define LS_KSTS 0x0001 /* Low-Speed K State */
+#define SE0 0x0000 /* SE0 */
+
+/* Device State Control Register */
+#define EXTLP0 0x0400 /* b10: External port */
+#define VBOUT 0x0200 /* b9: VBUS output */
+#define WKUP 0x0100 /* b8: Remote wakeup */
+#define RWUPE 0x0080 /* b7: Remote wakeup sense */
+#define USBRST 0x0040 /* b6: USB reset enable */
+#define RESUME 0x0020 /* b5: Resume enable */
+#define UACT 0x0010 /* b4: USB bus enable */
+#define RHST 0x0007 /* b1-0: Reset handshake status */
+#define HSPROC 0x0004 /* HS handshake is processing */
+#define HSMODE 0x0003 /* Hi-Speed mode */
+#define FSMODE 0x0002 /* Full-Speed mode */
+#define LSMODE 0x0001 /* Low-Speed mode */
+#define UNDECID 0x0000 /* Undecided */
+
+/* Test Mode Register */
+#define UTST 0x000F /* b3-0: Test select */
+#define H_TST_PACKET 0x000C /* HOST TEST Packet */
+#define H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */
+#define H_TST_K 0x000A /* HOST TEST K */
+#define H_TST_J 0x0009 /* HOST TEST J */
+#define H_TST_NORMAL 0x0000 /* HOST Normal Mode */
+#define P_TST_PACKET 0x0004 /* PERI TEST Packet */
+#define P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */
+#define P_TST_K 0x0002 /* PERI TEST K */
+#define P_TST_J 0x0001 /* PERI TEST J */
+#define P_TST_NORMAL 0x0000 /* PERI Normal Mode */
+
+/* Data Pin Configuration Register */
+#define LDRV 0x8000 /* b15: Drive Current Adjust */
+#define VIF1 0x0000 /* VIF = 1.8V */
+#define VIF3 0x8000 /* VIF = 3.3V */
+#define INTA 0x0001 /* b1: USB INT-pin active */
+
+/* DMAx Pin Configuration Register */
+#define DREQA 0x4000 /* b14: Dreq active select */
+#define BURST 0x2000 /* b13: Burst mode */
+#define DACKA 0x0400 /* b10: Dack active select */
+#define DFORM 0x0380 /* b9-7: DMA mode select */
+#define CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */
+#define CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */
+#define CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */
+#define SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */
+#define DENDA 0x0040 /* b6: Dend active select */
+#define PKTM 0x0020 /* b5: Packet mode */
+#define DENDE 0x0010 /* b4: Dend enable */
+#define OBUS 0x0004 /* b2: OUTbus mode */
+
+/* CFIFO/DxFIFO Port Select Register */
+#define RCNT 0x8000 /* b15: Read count mode */
+#define REW 0x4000 /* b14: Buffer rewind */
+#define DCLRM 0x2000 /* b13: DMA buffer clear mode */
+#define DREQE 0x1000 /* b12: DREQ output enable */
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+#define MBW 0x0800
+#else
+#define MBW 0x0400 /* b10: Maximum bit width for FIFO access */
+#endif
+#define MBW_8 0x0000 /* 8bit */
+#define MBW_16 0x0400 /* 16bit */
+#define BIGEND 0x0100 /* b8: Big endian mode */
+#define BYTE_LITTLE 0x0000 /* little dendian */
+#define BYTE_BIG 0x0100 /* big endifan */
+#define ISEL 0x0020 /* b5: DCP FIFO port direction select */
+#define CURPIPE 0x000F /* b2-0: PIPE select */
+
+/* CFIFO/DxFIFO Port Control Register */
+#define BVAL 0x8000 /* b15: Buffer valid flag */
+#define BCLR 0x4000 /* b14: Buffer clear */
+#define FRDY 0x2000 /* b13: FIFO ready */
+#define DTLN 0x0FFF /* b11-0: FIFO received data length */
+
+/* Interrupt Enable Register 0 */
+#define VBSE 0x8000 /* b15: VBUS interrupt */
+#define RSME 0x4000 /* b14: Resume interrupt */
+#define SOFE 0x2000 /* b13: Frame update interrupt */
+#define DVSE 0x1000 /* b12: Device state transition interrupt */
+#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */
+#define BEMPE 0x0400 /* b10: Buffer empty interrupt */
+#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */
+#define BRDYE 0x0100 /* b8: Buffer ready interrupt */
+
+/* Interrupt Enable Register 1 */
+#define OVRCRE 0x8000 /* b15: Over-current interrupt */
+#define BCHGE 0x4000 /* b14: USB us chenge interrupt */
+#define DTCHE 0x1000 /* b12: Detach sense interrupt */
+#define ATTCHE 0x0800 /* b11: Attach sense interrupt */
+#define EOFERRE 0x0040 /* b6: EOF error interrupt */
+#define SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */
+#define SACKE 0x0010 /* b4: SETUP ACK interrupt */
+
+/* BRDY Interrupt Enable/Status Register */
+#define BRDY9 0x0200 /* b9: PIPE9 */
+#define BRDY8 0x0100 /* b8: PIPE8 */
+#define BRDY7 0x0080 /* b7: PIPE7 */
+#define BRDY6 0x0040 /* b6: PIPE6 */
+#define BRDY5 0x0020 /* b5: PIPE5 */
+#define BRDY4 0x0010 /* b4: PIPE4 */
+#define BRDY3 0x0008 /* b3: PIPE3 */
+#define BRDY2 0x0004 /* b2: PIPE2 */
+#define BRDY1 0x0002 /* b1: PIPE1 */
+#define BRDY0 0x0001 /* b1: PIPE0 */
+
+/* NRDY Interrupt Enable/Status Register */
+#define NRDY9 0x0200 /* b9: PIPE9 */
+#define NRDY8 0x0100 /* b8: PIPE8 */
+#define NRDY7 0x0080 /* b7: PIPE7 */
+#define NRDY6 0x0040 /* b6: PIPE6 */
+#define NRDY5 0x0020 /* b5: PIPE5 */
+#define NRDY4 0x0010 /* b4: PIPE4 */
+#define NRDY3 0x0008 /* b3: PIPE3 */
+#define NRDY2 0x0004 /* b2: PIPE2 */
+#define NRDY1 0x0002 /* b1: PIPE1 */
+#define NRDY0 0x0001 /* b1: PIPE0 */
+
+/* BEMP Interrupt Enable/Status Register */
+#define BEMP9 0x0200 /* b9: PIPE9 */
+#define BEMP8 0x0100 /* b8: PIPE8 */
+#define BEMP7 0x0080 /* b7: PIPE7 */
+#define BEMP6 0x0040 /* b6: PIPE6 */
+#define BEMP5 0x0020 /* b5: PIPE5 */
+#define BEMP4 0x0010 /* b4: PIPE4 */
+#define BEMP3 0x0008 /* b3: PIPE3 */
+#define BEMP2 0x0004 /* b2: PIPE2 */
+#define BEMP1 0x0002 /* b1: PIPE1 */
+#define BEMP0 0x0001 /* b0: PIPE0 */
+
+/* SOF Pin Configuration Register */
+#define TRNENSEL 0x0100 /* b8: Select transaction enable period */
+#define BRDYM 0x0040 /* b6: BRDY clear timing */
+#define INTL 0x0020 /* b5: Interrupt sense select */
+#define EDGESTS 0x0010 /* b4: */
+#define SOFMODE 0x000C /* b3-2: SOF pin select */
+#define SOF_125US 0x0008 /* SOF OUT 125us Frame Signal */
+#define SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */
+#define SOF_DISABLE 0x0000 /* SOF OUT Disable */
+
+/* Interrupt Status Register 0 */
+#define VBINT 0x8000 /* b15: VBUS interrupt */
+#define RESM 0x4000 /* b14: Resume interrupt */
+#define SOFR 0x2000 /* b13: SOF frame update interrupt */
+#define DVST 0x1000 /* b12: Device state transition interrupt */
+#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */
+#define BEMP 0x0400 /* b10: Buffer empty interrupt */
+#define NRDY 0x0200 /* b9: Buffer not ready interrupt */
+#define BRDY 0x0100 /* b8: Buffer ready interrupt */
+#define VBSTS 0x0080 /* b7: VBUS input port */
+#define DVSQ 0x0070 /* b6-4: Device state */
+#define DS_SPD_CNFG 0x0070 /* Suspend Configured */
+#define DS_SPD_ADDR 0x0060 /* Suspend Address */
+#define DS_SPD_DFLT 0x0050 /* Suspend Default */
+#define DS_SPD_POWR 0x0040 /* Suspend Powered */
+#define DS_SUSP 0x0040 /* Suspend */
+#define DS_CNFG 0x0030 /* Configured */
+#define DS_ADDS 0x0020 /* Address */
+#define DS_DFLT 0x0010 /* Default */
+#define DS_POWR 0x0000 /* Powered */
+#define DVSQS 0x0030 /* b5-4: Device state */
+#define VALID 0x0008 /* b3: Setup packet detected flag */
+#define CTSQ 0x0007 /* b2-0: Control transfer stage */
+#define CS_SQER 0x0006 /* Sequence error */
+#define CS_WRND 0x0005 /* Control write nodata status stage */
+#define CS_WRSS 0x0004 /* Control write status stage */
+#define CS_WRDS 0x0003 /* Control write data stage */
+#define CS_RDSS 0x0002 /* Control read status stage */
+#define CS_RDDS 0x0001 /* Control read data stage */
+#define CS_IDST 0x0000 /* Idle or setup stage */
+
+/* Interrupt Status Register 1 */
+#define OVRCR 0x8000 /* b15: Over-current interrupt */
+#define BCHG 0x4000 /* b14: USB bus chenge interrupt */
+#define DTCH 0x1000 /* b12: Detach sense interrupt */
+#define ATTCH 0x0800 /* b11: Attach sense interrupt */
+#define EOFERR 0x0040 /* b6: EOF-error interrupt */
+#define SIGN 0x0020 /* b5: Setup ignore interrupt */
+#define SACK 0x0010 /* b4: Setup acknowledge interrupt */
+
+/* Frame Number Register */
+#define OVRN 0x8000 /* b15: Overrun error */
+#define CRCE 0x4000 /* b14: Received data error */
+#define FRNM 0x07FF /* b10-0: Frame number */
+
+/* Micro Frame Number Register */
+#define UFRNM 0x0007 /* b2-0: Micro frame number */
+
+/* Default Control Pipe Maxpacket Size Register */
+/* Pipe Maxpacket Size Register */
+#define DEVSEL 0xF000 /* b15-14: Device address select */
+#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */
+
+/* Default Control Pipe Control Register */
+#define BSTS 0x8000 /* b15: Buffer status */
+#define SUREQ 0x4000 /* b14: Send USB request */
+#define CSCLR 0x2000 /* b13: complete-split status clear */
+#define CSSTS 0x1000 /* b12: complete-split status */
+#define SUREQCLR 0x0800 /* b11: stop setup request */
+#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */
+#define SQSET 0x0080 /* b7: Sequence toggle bit set */
+#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */
+#define PBUSY 0x0020 /* b5: pipe busy */
+#define PINGE 0x0010 /* b4: ping enable */
+#define CCPL 0x0004 /* b2: Enable control transfer complete */
+#define PID 0x0003 /* b1-0: Response PID */
+#define PID_STALL11 0x0003 /* STALL */
+#define PID_STALL 0x0002 /* STALL */
+#define PID_BUF 0x0001 /* BUF */
+#define PID_NAK 0x0000 /* NAK */
+
+/* Pipe Window Select Register */
+#define PIPENM 0x0007 /* b2-0: Pipe select */
+
+/* Pipe Configuration Register */
+#define R8A66597_TYP 0xC000 /* b15-14: Transfer type */
+#define R8A66597_ISO 0xC000 /* Isochronous */
+#define R8A66597_INT 0x8000 /* Interrupt */
+#define R8A66597_BULK 0x4000 /* Bulk */
+#define R8A66597_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */
+#define R8A66597_DBLB 0x0200 /* b9: Double buffer mode select */
+#define R8A66597_CNTMD 0x0100 /* b8: Continuous transfer mode select */
+#define R8A66597_SHTNAK 0x0080 /* b7: Transfer end NAK */
+#define R8A66597_DIR 0x0010 /* b4: Transfer direction select */
+#define R8A66597_EPNUM 0x000F /* b3-0: Eendpoint number select */
+
+/* Pipe Buffer Configuration Register */
+#define BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */
+#define BUFNMB 0x007F /* b6-0: Pipe buffer number */
+#define PIPE0BUF 256
+#define PIPExBUF 64
+
+/* Pipe Maxpacket Size Register */
+#define MXPS 0x07FF /* b10-0: Maxpacket size */
+
+/* Pipe Cycle Configuration Register */
+#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */
+#define IITV 0x0007 /* b2-0: Isochronous interval */
+
+/* Pipex Control Register */
+#define BSTS 0x8000 /* b15: Buffer status */
+#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define CSCLR 0x2000 /* b13: complete-split status clear */
+#define CSSTS 0x1000 /* b12: complete-split status */
+#define ATREPM 0x0400 /* b10: Auto repeat mode */
+#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */
+#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */
+#define SQSET 0x0080 /* b7: Sequence toggle bit set */
+#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */
+#define PBUSY 0x0020 /* b5: pipe busy */
+#define PID 0x0003 /* b1-0: Response PID */
+
+/* PIPExTRE */
+#define TRENB 0x0200 /* b9: Transaction counter enable */
+#define TRCLR 0x0100 /* b8: Transaction counter clear */
+
+/* PIPExTRN */
+#define TRNCNT 0xFFFF /* b15-0: Transaction counter */
+
+/* DEVADDx */
+#define UPPHUB 0x7800
+#define HUBPORT 0x0700
+#define USBSPD 0x00C0
+#define RTPORT 0x0001
+
+#define R8A66597_MAX_NUM_PIPE 10
+#define R8A66597_BUF_BSIZE 8
+#define R8A66597_MAX_DEVICE 10
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+#define R8A66597_MAX_ROOT_HUB 1
+#else
+#define R8A66597_MAX_ROOT_HUB 2
+#endif
+#define R8A66597_MAX_SAMPLING 5
+#define R8A66597_RH_POLL_TIME 10
+
+#define BULK_IN_PIPENUM 3
+#define BULK_IN_BUFNUM 8
+
+#define BULK_OUT_PIPENUM 4
+#define BULK_OUT_BUFNUM 40
+
+#define check_bulk_or_isoc(pipenum) ((pipenum >= 1 && pipenum <= 5))
+#define check_interrupt(pipenum) ((pipenum >= 6 && pipenum <= 9))
+#define make_devsel(addr) (addr << 12)
+
+struct r8a66597 {
+ unsigned long reg;
+ unsigned short pipe_config; /* bit field */
+ unsigned short port_status;
+ unsigned short port_change;
+ u16 speed; /* HSMODE or FSMODE or LSMODE */
+ unsigned char rh_devnum;
+};
+
+static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
+{
+ return inw(r8a66597->reg + offset);
+}
+
+static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+ unsigned long offset, void *buf,
+ int len)
+{
+ int i;
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+ unsigned long fifoaddr = r8a66597->reg + offset;
+ unsigned long count;
+ unsigned long *p = buf;
+
+ count = len / 4;
+ for (i = 0; i < count; i++)
+ inl(p[i], r8a66597->reg + offset);
+
+ if (len & 0x00000003) {
+ unsigned long tmp = inl(fifoaddr);
+ memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
+ }
+#else
+ unsigned short *p = buf;
+
+ len = (len + 1) / 2;
+ for (i = 0; i < len; i++)
+ p[i] = inw(r8a66597->reg + offset);
+#endif
+}
+
+static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+ unsigned long offset)
+{
+ outw(val, r8a66597->reg + offset);
+}
+
+static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+ unsigned long offset, void *buf,
+ int len)
+{
+ int i;
+ unsigned long fifoaddr = r8a66597->reg + offset;
+#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+ unsigned long count;
+ unsigned char *pb;
+ unsigned long *p = buf;
+
+ count = len / 4;
+ for (i = 0; i < count; i++)
+ outl(p[i], fifoaddr);
+
+ if (len & 0x00000003) {
+ pb = (unsigned char *)buf + count * 4;
+ for (i = 0; i < (len & 0x00000003); i++) {
+ if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
+ outb(pb[i], fifoaddr + i);
+ else
+ outb(pb[i], fifoaddr + 3 - i);
+ }
+ }
+#else
+ int odd = len & 0x0001;
+ unsigned short *p = buf;
+
+ len = len / 2;
+ for (i = 0; i < len; i++)
+ outw(p[i], fifoaddr);
+
+ if (odd) {
+ unsigned char *pb = (unsigned char *)(buf + len);
+ outb(*pb, fifoaddr);
+ }
+#endif
+}
+
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+ u16 val, u16 pat, unsigned long offset)
+{
+ u16 tmp;
+ tmp = r8a66597_read(r8a66597, offset);
+ tmp = tmp & (~pat);
+ tmp = tmp | val;
+ r8a66597_write(r8a66597, tmp, offset);
+}
+
+#define r8a66597_bclr(r8a66597, val, offset) \
+ r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset) \
+ r8a66597_mdfy(r8a66597, val, 0, offset)
+
+static inline unsigned long get_syscfg_reg(int port)
+{
+ return port == 0 ? SYSCFG0 : SYSCFG1;
+}
+
+static inline unsigned long get_syssts_reg(int port)
+{
+ return port == 0 ? SYSSTS0 : SYSSTS1;
+}
+
+static inline unsigned long get_dvstctr_reg(int port)
+{
+ return port == 0 ? DVSTCTR0 : DVSTCTR1;
+}
+
+static inline unsigned long get_dmacfg_reg(int port)
+{
+ return port == 0 ? DMA0CFG : DMA1CFG;
+}
+
+static inline unsigned long get_intenb_reg(int port)
+{
+ return port == 0 ? INTENB1 : INTENB2;
+}
+
+static inline unsigned long get_intsts_reg(int port)
+{
+ return port == 0 ? INTSTS1 : INTSTS2;
+}
+
+static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port)
+{
+ unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+ return r8a66597_read(r8a66597, dvstctr_reg) & RHST;
+}
+
+static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port,
+ int power)
+{
+ unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+ if (power)
+ r8a66597_bset(r8a66597, VBOUT, dvstctr_reg);
+ else
+ r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg);
+}
+
+#define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2)
+#define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4)
+#define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4)
+#define get_devadd_addr(address) (DEVADD0 + address * 2)
+
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h, based on usb_ohci.h) */
+
+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS 0x00000001 /* current connect status */
+#define RH_PS_PES 0x00000002 /* port enable status*/
+#define RH_PS_PSS 0x00000004 /* port suspend status */
+#define RH_PS_POCI 0x00000008 /* port over current indicator */
+#define RH_PS_PRS 0x00000010 /* port reset status */
+#define RH_PS_PPS 0x00000100 /* port power status */
+#define RH_PS_LSDA 0x00000200 /* low speed device attached */
+#define RH_PS_CSC 0x00010000 /* connect status change */
+#define RH_PS_PESC 0x00020000 /* port enable status change */
+#define RH_PS_PSSC 0x00040000 /* port suspend status change */
+#define RH_PS_OCIC 0x00080000 /* over current indicator change */
+#define RH_PS_PRSC 0x00100000 /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS 0x00000001 /* local power status */
+#define RH_HS_OCI 0x00000002 /* over current indicator */
+#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
+#define RH_HS_LPSC 0x00010000 /* local power status change */
+#define RH_HS_OCIC 0x00020000 /* over current indicator change */
+#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR 0x0000ffff /* device removable flags */
+#define RH_B_PPCM 0xffff0000 /* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP (0xff << 0) /* number of downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* over current protection mode */
+#define RH_A_NOCP (1 << 12) /* no over current protection */
+#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
+
+#endif /* __R8A66597_H__ */
#include <common.h>
-#if defined(CONFIG_OMAP1510) && defined(CONFIG_USB_DEVICE)
+#if ((defined(CONFIG_OMAP1510) || defined(CONFIG_OMAP1610)) && defined(CONFIG_USB_DEVICE))
#include <asm/io.h>
#ifdef CONFIG_OMAP_SX1
*/
outw ((1 << 4) | (1 << 5), CLOCK_CTRL);
UDCREG (CLOCK_CTRL);
+
+#ifdef CONFIG_OMAP1510
+ /* This code was originally implemented for OMAP1510 and
+ * therefore is only applicable for OMAP1510 boards. For
+ * OMAP5912 or OMAP16xx the register APLL_CTRL does not
+ * exist and DPLL_CTRL is already configured.
+ */
+
/* Set and check APLL */
outw (0x0008, APLL_CTRL);
UDCREG (APLL_CTRL);
/* Set and check DPLL */
outw (0x2210, DPLL_CTRL);
UDCREG (DPLL_CTRL);
- /* Set and check SOFT */
- outw ((1 << 4) | (1 << 3) | 1, SOFT_REQ);
+#endif
+ /* Set and check SOFT
+ * The below line of code has been changed to perform a
+ * read-modify-write instead of a simple write for
+ * configuring the SOFT_REQ register. This allows the code
+ * to be compatible with OMAP5912 and OMAP16xx devices
+ */
+ outw ((1 << 4) | (1 << 3) | 1 | (inw(SOFT_REQ)), SOFT_REQ);
+
/* Short delay to wait for DPLL */
udelay (1000);
/* Print banner with device revision */
udc_rev = inw (UDC_REV) & 0xff;
+#ifdef CONFIG_OMAP1510
printf ("USB: TI OMAP1510 USB function module rev %d.%d\n",
udc_rev >> 4, udc_rev & 0xf);
+#endif
+
+#ifdef CONFIG_OMAP1610
+ printf ("USB: TI OMAP5912 USB function module rev %d.%d\n",
+ udc_rev >> 4, udc_rev & 0xf);
+#endif
#ifdef CONFIG_OMAP_SX1
i2c_read (0x32, 0x04, 1, &value, 1);
LIB := $(obj)libvideo.a
-COBJS-y += ati_radeon_fb.o
+COBJS-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o
COBJS-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o
-COBJS-y += cfb_console.o
-COBJS-y += ct69000.o
-COBJS-y += mb862xx.o
-COBJS-y += sed13806.o
-COBJS-y += sed156x.o
-COBJS-y += sm501.o
-COBJS-y += smiLynxEM.o
+COBJS-$(CONFIG_CFB_CONSOLE) += cfb_console.o
+COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o
+COBJS-$(CONFIG_VIDEO_MB862xx) += mb862xx.o
+COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o
+COBJS-$(CONFIG_SED156X) += sed156x.o
+COBJS-$(CONFIG_VIDEO_SM501) += sm501.o
+COBJS-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o
COBJS-y += videomodes.o
COBJS := $(COBJS-y)
#include <common.h>
-#ifdef CONFIG_ATI_RADEON_FB
-
#include <command.h>
#include <pci.h>
#include <asm/processor.h>
OUTREG(PALETTE_INDEX, index);
OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);
}
-#endif
#include <common.h>
-#ifdef CONFIG_CFB_CONSOLE
-
#include <malloc.h>
/*****************************************************************************/
fb ++; \
}
-#if !defined(VIDEO_FB_16BPP_PIXEL_SWAP)
#define FILL_15BIT_555RGB(r,g,b) { \
*(unsigned short *)fb = SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3))); \
fb += 2; \
}
-#else
-static int tgl;
-static unsigned short p0;
-#define FILL_15BIT_555RGB(r,g,b) { \
- if (!tgl++) { \
- p0 = SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3))); \
- } else { \
- tgl=0; \
- *(unsigned long *)(fb-2) = (SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3)))<<16) | p0; \
- } \
- fb += 2; \
-}
-#endif
#define FILL_16BIT_565RGB(r,g,b) { \
*(unsigned short *)fb = SWAP16((unsigned short)((((r)>>3)<<11) | (((g)>>2)<<5) | ((b)>>3))); \
}
#endif
+#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
+static void inline fill_555rgb_pswap(uchar *fb, int x,
+ u8 r, u8 g, u8 b)
+{
+ ushort *dst = (ushort *)fb;
+ ushort color = (ushort)(((r >> 3) << 10) |
+ ((g >> 3) << 5) |
+ (b >> 3));
+ if (x & 1)
+ *(--dst) = color;
+ else
+ *(++dst) = color;
+}
+#endif
/*
* Display the BMP file located at address bmp_image.
break;
case GDF_15BIT_555RGB:
while (ycount--) {
+#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
+ int xpos = x;
+#endif
WATCHDOG_RESET ();
xcount = width;
while (xcount--) {
cte = bmp->color_table[*bmap++];
+#if !defined(VIDEO_FB_16BPP_PIXEL_SWAP)
FILL_15BIT_555RGB (cte.red, cte.green, cte.blue);
+#else
+ fill_555rgb_pswap (fb, xpos++, cte.red,
+ cte.green, cte.blue);
+ fb += 2;
+#endif
}
bmap += padded_line;
fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
break;
case GDF_15BIT_555RGB:
while (ycount--) {
+#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
+ int xpos = x;
+#endif
WATCHDOG_RESET ();
xcount = width;
while (xcount--) {
+#if !defined(VIDEO_FB_16BPP_PIXEL_SWAP)
FILL_15BIT_555RGB (bmap[2], bmap[1], bmap[0]);
+#else
+ fill_555rgb_pswap (fb, xpos++, bmap[2],
+ bmap[1], bmap[0]);
+ fb += 2;
+#endif
bmap += 3;
}
bmap += padded_line;
int ycount = VIDEO_LOGO_HEIGHT;
unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
unsigned char *source;
- unsigned char *dest = (unsigned char *)screen + ((y * width * VIDEO_PIXEL_SIZE) + x);
+ unsigned char *dest = (unsigned char *)screen +
+ ((y * width * VIDEO_PIXEL_SIZE) +
+ x * VIDEO_PIXEL_SIZE);
#ifdef CONFIG_VIDEO_BMP_LOGO
source = bmp_logo_bitmap;
}
while (ycount--) {
+#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
+ int xpos = x;
+#endif
xcount = VIDEO_LOGO_WIDTH;
while (xcount--) {
r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
*(unsigned short *) dest =
SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)));
#else
- {
- if (!tgl++) {
- p0 = SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)));
- } else {
- *(unsigned long *)(dest-2) =
- (SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)))<<16) | p0;
- tgl=0;
- }
- }
+ fill_555rgb_pswap (dest, xpos++, r, g, b);
#endif
break;
case GDF_16BIT_565RGB:
/* No console dev available */
return 0;
}
-#endif /* CONFIG_CFB_CONSOLE */
#include <video_fb.h>
#include "videomodes.h"
-#ifdef CONFIG_VIDEO_CT69000
-
/* debug */
#undef VGA_DEBUG
#undef VGA_DUMP_REG
out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x); /* start the BITBlt */
video_wait_bitblt (pGD->pciBase + BR04_o);
}
-
-#endif /* CONFIG_CT69000 */
-
#endif /* CONFIG_VIDEO */
#include <common.h>
-#if defined(CONFIG_VIDEO_MB862xx)
-
#include <asm/io.h>
#include <pci.h>
#include <video_fb.h>
DE_WR_FIFO ((height << 16) | width);
de_wait (); /* sync */
}
-#endif /* CONFIG_VIDEO_MB862xx */
#include <common.h>
-#ifdef CONFIG_VIDEO_SED13806
-
#include <video_fb.h>
#include <sed13806.h>
writeByte (LCD_CURSOR_CNTL, 1);
}
#endif
-#endif
#include <sed156x.h>
-#ifdef CONFIG_SED156X
-
/* configure according to the selected display */
#if defined(CONFIG_SED156X_PG12864Q)
#define LCD_WIDTH 128
sed156x_sync();
sed156x_cmd_transfer(LCD_ON); /* Turn display ON */
}
-
-#endif /* CONFIG_SED156X */
#include <common.h>
-#ifdef CONFIG_VIDEO_SM501
-
#include <video_fb.h>
#include <sm501.h>
)
{
}
-
-#endif /* CONFIG_VIDEO_SM501 */
#include <common.h>
-#if defined(CONFIG_VIDEO_SMI_LYNXEM)
-
#include <pci.h>
#include <video_fb.h>
#include "videomodes.h"
out8 (SMI_LUT_RGB, b>>2); /* blue */
udelay (10);
}
-
-#endif /* CONFIG_VIDEO_SMI_LYNXEM */
#
#
-SUBDIRS := jffs2 cramfs fdos fat reiserfs ext2
+SUBDIRS := jffs2 cramfs fdos fat reiserfs ext2 yaffs2
$(obj).depend all:
@for dir in $(SUBDIRS) ; do \
#if (defined(CONFIG_JFFS2_NAND) && \
defined(CONFIG_CMD_NAND) )
-#if defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_NAND_LEGACY)
#include <linux/mtd/nand_legacy.h>
#else
#include <nand.h>
*
*/
-#if defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_NAND_LEGACY)
/* this one defined in nand_legacy.c */
int read_jffs2_nand(size_t start, size_t len,
size_t * retlen, u_char * buf, int nanddev);
}
}
-#if defined(CFG_NAND_LEGACY)
+#if defined(CONFIG_NAND_LEGACY)
if (read_jffs2_nand(nand_cache_off, NAND_CACHE_SIZE,
&retlen, nand_cache, id->num) < 0 ||
retlen != NAND_CACHE_SIZE) {
#include <common.h>
-#if !defined(CFG_NAND_LEGACY) && defined(CONFIG_CMD_JFFS2)
+#if !defined(CONFIG_NAND_LEGACY) && defined(CONFIG_CMD_JFFS2)
#include <malloc.h>
#include <linux/stat.h>
--- /dev/null
+# Makefile for YAFFS direct test
+#
+#
+# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
+#
+# Copyright (C) 2003 Aleph One Ltd.
+#
+#
+# Created by Charles Manning <charles@aleph1.co.uk>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# NB Warning this Makefile does not include header dependencies.
+#
+# $Id: Makefile,v 1.15 2007/07/18 19:40:38 charles Exp $
+
+#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)libyaffs2.a
+
+COBJS-$(CONFIG_YAFFS2) := \
+ yaffscfg.o yaffs_ecc.o yaffsfs.o yaffs_guts.o yaffs_packedtags1.o \
+ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o \
+ yaffs_nand.o yaffs_checkptrw.o yaffs_qsort.o yaffs_mtdif.o \
+ yaffs_mtdif2.o
+
+SRCS := $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS-y))
+
+# -DCONFIG_YAFFS_NO_YAFFS1
+CFLAGS += -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -DNO_Y_INLINE -DLINUX_VERSION_CODE=0x20622
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+.PHONY: clean distclean
+clean:
+ rm -f $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
--- /dev/null
+Welcome to YAFFS, the first file system developed specifically for NAND flash.
+
+It is now YAFFS2 - original YAFFS (AYFFS1) only supports 512-byte page
+NAND and is now deprectated. YAFFS2 supports 512b page in 'YAFFS1
+compatibility' mode (CONFIG_YAFFS_YAFFS1) and 2K or larger page NAND
+in YAFFS2 mode (CONFIG_YAFFS_YAFFS2).
+
+
+A note on licencing
+-------------------
+YAFFS is available under the GPL and via alternative licensing
+arrangements with Aleph One. If you're using YAFFS as a Linux kernel
+file system then it will be under the GPL. For use in other situations
+you should discuss licensing issues with Aleph One.
+
+
+Terminology
+-----------
+Page - NAND addressable unit (normally 512b or 2Kbyte size) - can
+ be read, written, marked bad. Has associated OOB.
+Block - Eraseable unit. 64 Pages. (128K on 2K NAND, 32K on 512b NAND)
+OOB - 'spare area' of each page for ECC, bad block marked and YAFFS
+ tags. 16 bytes per 512b - 64 bytes for 2K page size.
+Chunk - Basic YAFFS addressable unit. Same size as Page.
+Object - YAFFS Object: File, Directory, Link, Device etc.
+
+YAFFS design
+------------
+
+YAFFS is a log-structured filesystem. It is designed particularly for
+NAND (as opposed to NOR) flash, to be flash-friendly, robust due to
+journalling, and to have low RAM and boot time overheads. File data is
+stored in 'chunks'. Chunks are the same size as NAND pages. Each page
+is marked with file id and chunk number. These marking 'tags' are
+stored in the OOB (or 'spare') region of the flash. The chunk number
+is determined by dividing the file position by the chunk size. Each
+chunk has a number of valid bytes, which equals the page size for all
+except the last chunk in a file.
+
+File 'headers' are stored as the first page in a file, marked as a
+different type to data pages. The same mechanism is used to store
+directories, device files, links etc. The first page describes which
+type of object it is.
+
+YAFFS2 never re-writes a page, because the spec of NAND chips does not
+allow it. (YAFFS1 used to mark a block 'deleted' in the OOB). Deletion
+is managed by moving deleted objects to the special, hidden 'unlinked'
+directory. These records are preserved until all the pages containing
+the object have been erased (We know when this happen by keeping a
+count of chunks remaining on the system for each object - when it
+reaches zero the object really is gone).
+
+When data in a file is overwritten, the relevant chunks are replaced
+by writing new pages to flash containing the new data but the same
+tags.
+
+Pages are also marked with a short (2 bit) serial number that
+increments each time the page at this position is incremented. The
+reason for this is that if power loss/crash/other act of demonic
+forces happens before the replaced page is marked as discarded, it is
+possible to have two pages with the same tags. The serial number is
+used to arbitrate.
+
+A block containing only discarded pages (termed a dirty block) is an
+obvious candidate for garbage collection. Otherwise valid pages can be
+copied off a block thus rendering the whole block discarded and ready
+for garbage collection.
+
+In theory you don't need to hold the file structure in RAM... you
+could just scan the whole flash looking for pages when you need them.
+In practice though you'd want better file access times than that! The
+mechanism proposed here is to have a list of __u16 page addresses
+associated with each file. Since there are 2^18 pages in a 128MB NAND,
+a __u16 is insufficient to uniquely identify a page but is does
+identify a group of 4 pages - a small enough region to search
+exhaustively. This mechanism is clearly expandable to larger NAND
+devices - within reason. The RAM overhead with this approach is approx
+2 bytes per page - 512kB of RAM for a whole 128MB NAND.
+
+Boot-time scanning to build the file structure lists only requires
+one pass reading NAND. If proper shutdowns happen the current RAM
+summary of the filesystem status is saved to flash, called
+'checkpointing'. This saves re-scanning the flash on startup, and gives
+huge boot/mount time savings.
+
+YAFFS regenerates its state by 'replaying the tape' - i.e. by
+scanning the chunks in their allocation order (i.e. block sequence ID
+order), which is usually different form the media block order. Each
+block is still only read once - starting from the end of the media and
+working back.
+
+YAFFS tags in YAFFS1 mode:
+
+18-bit Object ID (2^18 files, i.e. > 260,000 files). File id 0- is not
+ valid and indicates a deleted page. File od 0x3ffff is also not valid.
+ Synonymous with inode.
+2-bit serial number
+20-bit Chunk ID within file. Limit of 2^20 chunks/pages per file (i.e.
+ > 500MB max file size). Chunk ID 0 is the file header for the file.
+10-bit counter of the number of bytes used in the page.
+12 bit ECC on tags
+
+YAFFS tags in YAFFS2 mode:
+ 4 bytes 32-bit chunk ID
+ 4 bytes 32-bit object ID
+ 2 bytes Number of data bytes in this chunk
+ 4 bytes Sequence number for this block
+ 3 bytes ECC on tags
+ 12 bytes ECC on data (3 bytes per 256 bytes of data)
+
+
+Page allocation and garbage collection
+
+Pages are allocated sequentially from the currently selected block.
+When all the pages in the block are filled, another clean block is
+selected for allocation. At least two or three clean blocks are
+reserved for garbage collection purposes. If there are insufficient
+clean blocks available, then a dirty block ( ie one containing only
+discarded pages) is erased to free it up as a clean block. If no dirty
+blocks are available, then the dirtiest block is selected for garbage
+collection.
+
+Garbage collection is performed by copying the valid data pages into
+new data pages thus rendering all the pages in this block dirty and
+freeing it up for erasure. I also like the idea of selecting a block
+at random some small percentage of the time - thus reducing the chance
+of wear differences.
+
+YAFFS is single-threaded. Garbage-collection is done as a parasitic
+task of writing data. So each time some data is written, a bit of
+pending garbage collection is done. More pages are garbage-collected
+when free space is tight.
+
+
+Flash writing
+
+YAFFS only ever writes each page once, complying with the requirements
+of the most restricitve NAND devices.
+
+Wear levelling
+
+This comes as a side-effect of the block-allocation strategy. Data is
+always written on the next free block, so they are all used equally.
+Blocks containing data that is written but never erased will not get
+back into the free list, so wear is levelled over only blocks which
+are free or become free, not blocks which never change.
+
+
+
+Some helpful info
+-----------------
+
+Formatting a YAFFS device is simply done by erasing it.
+
+Making an initial filesystem can be tricky because YAFFS uses the OOB
+and thus the bytes that get written depend on the YAFFS data (tags),
+and the ECC bytes and bad block markers which are dictated by the
+hardware and/or the MTD subsystem. The data layout also depends on the
+device page size (512b or 2K). Because YAFFS is only responsible for
+some of the OOB data, generating a filesystem offline requires
+detailed knowledge of what the other parts (MTD and NAND
+driver/hardware) are going to do.
+
+To make a YAFFS filesystem you have 3 options:
+
+1) Boot the system with an empty NAND device mounted as YAFFS and copy
+ stuff on.
+
+2) Make a filesystem image offline, then boot the system and use
+ MTDutils to write an image to flash.
+
+3) Make a filesystem image offline and use some tool like a bootloader to
+ write it to flash.
+
+Option 1 avoids a lot of issues because all the parts
+(YAFFS/MTD/hardware) all take care of their own bits and (if you have
+put things together properly) it will 'just work'. YAFFS just needs to
+know how many bytes of the OOB it can use. However sometimes it is not
+practical.
+
+Option 2 lets MTD/hardware take care of the ECC so the filesystem
+image just had to know which bytes to use for YAFFS Tags.
+
+Option 3 is hardest as the image creator needs to know exactly what
+ECC bytes, endianness and algorithm to use as well as which bytes are
+available to YAFFS.
+
+mkyaffs2image creates an image suitable for option 3 for the
+particular case of yaffs2 on 2K page NAND with default MTD layout.
+
+mkyaffsimage creates an equivalent image for 512b page NAND (i.e.
+yaffs1 format).
+
+Bootloaders
+-----------
+
+A bootloader using YAFFS needs to know how MTD is laying out the OOB
+so that it can skip bad blocks.
+
+YAFFS Tracing
+-------------
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/*
+ * This file is just holds extra declarations used during development.
+ * Most of these are from kernel includes placed here so we can use them in
+ * applications.
+ *
+ */
+
+#ifndef __EXTRAS_H__
+#define __EXTRAS_H__
+
+#if defined WIN32
+#define __inline__ __inline
+#define new newHack
+#endif
+
+/* XXX U-BOOT XXX */
+#if 1 /* !(defined __KERNEL__) || (defined WIN32) */
+
+/* User space defines */
+
+/* XXX U-BOOT XXX */
+#if 0
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned __u32;
+#endif
+
+#include <asm/types.h>
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+#define prefetch(x) 1
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static __inline__ void list_add_tail(struct list_head *new,
+ struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static __inline__ void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static __inline__ void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static __inline__ int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static __inline__ void list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, prefetch(pos->next))
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal
+ * of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/*
+ * File types
+ */
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+#ifndef WIN32
+/* XXX U-BOOT XXX */
+#if 0
+#include <sys/stat.h>
+#else
+#include "common.h"
+#endif
+#endif
+
+/*
+ * Attribute flags. These should be or-ed together to figure out what
+ * has been changed!
+ */
+#define ATTR_MODE 1
+#define ATTR_UID 2
+#define ATTR_GID 4
+#define ATTR_SIZE 8
+#define ATTR_ATIME 16
+#define ATTR_MTIME 32
+#define ATTR_CTIME 64
+#define ATTR_ATIME_SET 128
+#define ATTR_MTIME_SET 256
+#define ATTR_FORCE 512 /* Not a change, but a change it */
+#define ATTR_ATTR_FLAG 1024
+
+struct iattr {
+ unsigned int ia_valid;
+ unsigned ia_mode;
+ unsigned ia_uid;
+ unsigned ia_gid;
+ unsigned ia_size;
+ unsigned ia_atime;
+ unsigned ia_mtime;
+ unsigned ia_ctime;
+ unsigned int ia_attr_flags;
+};
+
+#define KERN_DEBUG
+
+#else
+
+#ifndef WIN32
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#endif
+
+#endif
+
+#if defined WIN32
+#undef new
+#endif
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+#include <malloc.h>
+
+const char *yaffs_checkptrw_c_version =
+ "$Id: yaffs_checkptrw.c,v 1.14 2007/05/15 20:07:40 charles Exp $";
+
+
+#include "yaffs_checkptrw.h"
+
+
+static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
+{
+
+ int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
+
+ T(YAFFS_TRACE_CHECKPOINT,
+ (TSTR("checkpt blocks available = %d" TENDSTR),
+ blocksAvailable));
+
+
+ return (blocksAvailable <= 0) ? 0 : 1;
+}
+
+
+static int yaffs_CheckpointErase(yaffs_Device *dev)
+{
+
+ int i;
+
+
+ if(!dev->eraseBlockInNAND)
+ return 0;
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("checking blocks %d to %d"TENDSTR),
+ dev->internalStartBlock,dev->internalEndBlock));
+
+ for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
+ if(bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt block %d"TENDSTR),i));
+ if(dev->eraseBlockInNAND(dev,i- dev->blockOffset /* realign */)){
+ bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
+ dev->nErasedBlocks++;
+ dev->nFreeChunks += dev->nChunksPerBlock;
+ }
+ else {
+ dev->markNANDBlockBad(dev,i);
+ bi->blockState = YAFFS_BLOCK_STATE_DEAD;
+ }
+ }
+ }
+
+ dev->blocksInCheckpoint = 0;
+
+ return 1;
+}
+
+
+static void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev)
+{
+ int i;
+ int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
+ T(YAFFS_TRACE_CHECKPOINT,
+ (TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR),
+ dev->nErasedBlocks,dev->nReservedBlocks,blocksAvailable,dev->checkpointNextBlock));
+
+ if(dev->checkpointNextBlock >= 0 &&
+ dev->checkpointNextBlock <= dev->internalEndBlock &&
+ blocksAvailable > 0){
+
+ for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
+ if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY){
+ dev->checkpointNextBlock = i + 1;
+ dev->checkpointCurrentBlock = i;
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("allocating checkpt block %d"TENDSTR),i));
+ return;
+ }
+ }
+ }
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR)));
+
+ dev->checkpointNextBlock = -1;
+ dev->checkpointCurrentBlock = -1;
+}
+
+static void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
+{
+ int i;
+ yaffs_ExtendedTags tags;
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: start: blocks %d next %d" TENDSTR),
+ dev->blocksInCheckpoint, dev->checkpointNextBlock));
+
+ if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks)
+ for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){
+ int chunk = i * dev->nChunksPerBlock;
+ int realignedChunk = chunk - dev->chunkOffset;
+
+ dev->readChunkWithTagsFromNAND(dev,realignedChunk,NULL,&tags);
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR),
+ i, tags.objectId,tags.sequenceNumber,tags.eccResult));
+
+ if(tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA){
+ /* Right kind of block */
+ dev->checkpointNextBlock = tags.objectId;
+ dev->checkpointCurrentBlock = i;
+ dev->checkpointBlockList[dev->blocksInCheckpoint] = i;
+ dev->blocksInCheckpoint++;
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("found checkpt block %d"TENDSTR),i));
+ return;
+ }
+ }
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("found no more checkpt blocks"TENDSTR)));
+
+ dev->checkpointNextBlock = -1;
+ dev->checkpointCurrentBlock = -1;
+}
+
+
+int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
+{
+
+ /* Got the functions we need? */
+ if (!dev->writeChunkWithTagsToNAND ||
+ !dev->readChunkWithTagsFromNAND ||
+ !dev->eraseBlockInNAND ||
+ !dev->markNANDBlockBad)
+ return 0;
+
+ if(forWriting && !yaffs_CheckpointSpaceOk(dev))
+ return 0;
+
+ if(!dev->checkpointBuffer)
+ dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
+ if(!dev->checkpointBuffer)
+ return 0;
+
+
+ dev->checkpointPageSequence = 0;
+
+ dev->checkpointOpenForWrite = forWriting;
+
+ dev->checkpointByteCount = 0;
+ dev->checkpointSum = 0;
+ dev->checkpointXor = 0;
+ dev->checkpointCurrentBlock = -1;
+ dev->checkpointCurrentChunk = -1;
+ dev->checkpointNextBlock = dev->internalStartBlock;
+
+ /* Erase all the blocks in the checkpoint area */
+ if(forWriting){
+ memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk);
+ dev->checkpointByteOffset = 0;
+ return yaffs_CheckpointErase(dev);
+
+
+ } else {
+ int i;
+ /* Set to a value that will kick off a read */
+ dev->checkpointByteOffset = dev->nDataBytesPerChunk;
+ /* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully)
+ * going to be way more than we need */
+ dev->blocksInCheckpoint = 0;
+ dev->checkpointMaxBlocks = (dev->internalEndBlock - dev->internalStartBlock)/16 + 2;
+ dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks);
+ for(i = 0; i < dev->checkpointMaxBlocks; i++)
+ dev->checkpointBlockList[i] = -1;
+ }
+
+ return 1;
+}
+
+int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)
+{
+ __u32 compositeSum;
+ compositeSum = (dev->checkpointSum << 8) | (dev->checkpointXor & 0xFF);
+ *sum = compositeSum;
+ return 1;
+}
+
+static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
+{
+
+ int chunk;
+ int realignedChunk;
+
+ yaffs_ExtendedTags tags;
+
+ if(dev->checkpointCurrentBlock < 0){
+ yaffs_CheckpointFindNextErasedBlock(dev);
+ dev->checkpointCurrentChunk = 0;
+ }
+
+ if(dev->checkpointCurrentBlock < 0)
+ return 0;
+
+ tags.chunkDeleted = 0;
+ tags.objectId = dev->checkpointNextBlock; /* Hint to next place to look */
+ tags.chunkId = dev->checkpointPageSequence + 1;
+ tags.sequenceNumber = YAFFS_SEQUENCE_CHECKPOINT_DATA;
+ tags.byteCount = dev->nDataBytesPerChunk;
+ if(dev->checkpointCurrentChunk == 0){
+ /* First chunk we write for the block? Set block state to
+ checkpoint */
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointCurrentBlock);
+ bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
+ dev->blocksInCheckpoint++;
+ }
+
+ chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk;
+
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR),
+ chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk,tags.objectId,tags.chunkId));
+
+ realignedChunk = chunk - dev->chunkOffset;
+
+ dev->writeChunkWithTagsToNAND(dev,realignedChunk,dev->checkpointBuffer,&tags);
+ dev->checkpointByteOffset = 0;
+ dev->checkpointPageSequence++;
+ dev->checkpointCurrentChunk++;
+ if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){
+ dev->checkpointCurrentChunk = 0;
+ dev->checkpointCurrentBlock = -1;
+ }
+ memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk);
+
+ return 1;
+}
+
+
+int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes)
+{
+ int i=0;
+ int ok = 1;
+
+
+ __u8 * dataBytes = (__u8 *)data;
+
+
+
+ if(!dev->checkpointBuffer)
+ return 0;
+
+ if(!dev->checkpointOpenForWrite)
+ return -1;
+
+ while(i < nBytes && ok) {
+
+
+
+ dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ;
+ dev->checkpointSum += *dataBytes;
+ dev->checkpointXor ^= *dataBytes;
+
+ dev->checkpointByteOffset++;
+ i++;
+ dataBytes++;
+ dev->checkpointByteCount++;
+
+
+ if(dev->checkpointByteOffset < 0 ||
+ dev->checkpointByteOffset >= dev->nDataBytesPerChunk)
+ ok = yaffs_CheckpointFlushBuffer(dev);
+
+ }
+
+ return i;
+}
+
+int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
+{
+ int i=0;
+ int ok = 1;
+ yaffs_ExtendedTags tags;
+
+
+ int chunk;
+ int realignedChunk;
+
+ __u8 *dataBytes = (__u8 *)data;
+
+ if(!dev->checkpointBuffer)
+ return 0;
+
+ if(dev->checkpointOpenForWrite)
+ return -1;
+
+ while(i < nBytes && ok) {
+
+
+ if(dev->checkpointByteOffset < 0 ||
+ dev->checkpointByteOffset >= dev->nDataBytesPerChunk) {
+
+ if(dev->checkpointCurrentBlock < 0){
+ yaffs_CheckpointFindNextCheckpointBlock(dev);
+ dev->checkpointCurrentChunk = 0;
+ }
+
+ if(dev->checkpointCurrentBlock < 0)
+ ok = 0;
+ else {
+
+ chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock +
+ dev->checkpointCurrentChunk;
+
+ realignedChunk = chunk - dev->chunkOffset;
+
+ /* read in the next chunk */
+ /* printf("read checkpoint page %d\n",dev->checkpointPage); */
+ dev->readChunkWithTagsFromNAND(dev, realignedChunk,
+ dev->checkpointBuffer,
+ &tags);
+
+ if(tags.chunkId != (dev->checkpointPageSequence + 1) ||
+ tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
+ ok = 0;
+
+ dev->checkpointByteOffset = 0;
+ dev->checkpointPageSequence++;
+ dev->checkpointCurrentChunk++;
+
+ if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock)
+ dev->checkpointCurrentBlock = -1;
+ }
+ }
+
+ if(ok){
+ *dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset];
+ dev->checkpointSum += *dataBytes;
+ dev->checkpointXor ^= *dataBytes;
+ dev->checkpointByteOffset++;
+ i++;
+ dataBytes++;
+ dev->checkpointByteCount++;
+ }
+ }
+
+ return i;
+}
+
+int yaffs_CheckpointClose(yaffs_Device *dev)
+{
+
+ if(dev->checkpointOpenForWrite){
+ if(dev->checkpointByteOffset != 0)
+ yaffs_CheckpointFlushBuffer(dev);
+ } else {
+ int i;
+ for(i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++){
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointBlockList[i]);
+ if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
+ bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
+ else {
+ // Todo this looks odd...
+ }
+ }
+ YFREE(dev->checkpointBlockList);
+ dev->checkpointBlockList = NULL;
+ }
+
+ dev->nFreeChunks -= dev->blocksInCheckpoint * dev->nChunksPerBlock;
+ dev->nErasedBlocks -= dev->blocksInCheckpoint;
+
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR),
+ dev->checkpointByteCount));
+
+ if(dev->checkpointBuffer){
+ /* free the buffer */
+ YFREE(dev->checkpointBuffer);
+ dev->checkpointBuffer = NULL;
+ return 1;
+ }
+ else
+ return 0;
+
+}
+
+int yaffs_CheckpointInvalidateStream(yaffs_Device *dev)
+{
+ /* Erase the first checksum block */
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint invalidate"TENDSTR)));
+
+ if(!yaffs_CheckpointSpaceOk(dev))
+ return 0;
+
+ return yaffs_CheckpointErase(dev);
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_CHECKPTRW_H__
+#define __YAFFS_CHECKPTRW_H__
+
+#include "yaffs_guts.h"
+
+int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting);
+
+int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes);
+
+int yaffs_CheckpointRead(yaffs_Device *dev,void *data, int nBytes);
+
+int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum);
+
+int yaffs_CheckpointClose(yaffs_Device *dev);
+
+int yaffs_CheckpointInvalidateStream(yaffs_Device *dev);
+
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This code implements the ECC algorithm used in SmartMedia.
+ *
+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
+ * The two unused bit are set to 1.
+ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
+ * blocks are used on a 512-byte NAND page.
+ *
+ */
+
+/* Table generated by gen-ecc.c
+ * Using a table means we do not have to calculate p1..p4 and p1'..p4'
+ * for each byte of data. These are instead provided in a table in bits7..2.
+ * Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore
+ * this bytes influence on the line parity.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+const char *yaffs_ecc_c_version =
+ "$Id: yaffs_ecc.c,v 1.9 2007/02/14 01:09:06 wookey Exp $";
+
+#include "yportenv.h"
+
+#include "yaffs_ecc.h"
+
+static const unsigned char column_parity_table[] = {
+ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
+ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
+ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
+ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
+ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
+ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
+ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
+ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
+ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
+ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
+ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
+ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
+ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
+ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
+ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
+ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
+ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
+ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
+ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
+ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
+ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
+ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
+ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
+ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
+ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
+ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
+ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
+ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
+ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
+ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
+ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
+ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
+};
+
+/* Count the bits in an unsigned char or a U32 */
+
+static int yaffs_CountBits(unsigned char x)
+{
+ int r = 0;
+ while (x) {
+ if (x & 1)
+ r++;
+ x >>= 1;
+ }
+ return r;
+}
+
+static int yaffs_CountBits32(unsigned x)
+{
+ int r = 0;
+ while (x) {
+ if (x & 1)
+ r++;
+ x >>= 1;
+ }
+ return r;
+}
+
+/* Calculate the ECC for a 256-byte block of data */
+void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)
+{
+ unsigned int i;
+
+ unsigned char col_parity = 0;
+ unsigned char line_parity = 0;
+ unsigned char line_parity_prime = 0;
+ unsigned char t;
+ unsigned char b;
+
+ for (i = 0; i < 256; i++) {
+ b = column_parity_table[*data++];
+ col_parity ^= b;
+
+ if (b & 0x01) // odd number of bits in the byte
+ {
+ line_parity ^= i;
+ line_parity_prime ^= ~i;
+ }
+
+ }
+
+ ecc[2] = (~col_parity) | 0x03;
+
+ t = 0;
+ if (line_parity & 0x80)
+ t |= 0x80;
+ if (line_parity_prime & 0x80)
+ t |= 0x40;
+ if (line_parity & 0x40)
+ t |= 0x20;
+ if (line_parity_prime & 0x40)
+ t |= 0x10;
+ if (line_parity & 0x20)
+ t |= 0x08;
+ if (line_parity_prime & 0x20)
+ t |= 0x04;
+ if (line_parity & 0x10)
+ t |= 0x02;
+ if (line_parity_prime & 0x10)
+ t |= 0x01;
+ ecc[1] = ~t;
+
+ t = 0;
+ if (line_parity & 0x08)
+ t |= 0x80;
+ if (line_parity_prime & 0x08)
+ t |= 0x40;
+ if (line_parity & 0x04)
+ t |= 0x20;
+ if (line_parity_prime & 0x04)
+ t |= 0x10;
+ if (line_parity & 0x02)
+ t |= 0x08;
+ if (line_parity_prime & 0x02)
+ t |= 0x04;
+ if (line_parity & 0x01)
+ t |= 0x02;
+ if (line_parity_prime & 0x01)
+ t |= 0x01;
+ ecc[0] = ~t;
+
+#ifdef CONFIG_YAFFS_ECC_WRONG_ORDER
+ // Swap the bytes into the wrong order
+ t = ecc[0];
+ ecc[0] = ecc[1];
+ ecc[1] = t;
+#endif
+}
+
+
+/* Correct the ECC on a 256 byte block of data */
+
+int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
+ const unsigned char *test_ecc)
+{
+ unsigned char d0, d1, d2; /* deltas */
+
+ d0 = read_ecc[0] ^ test_ecc[0];
+ d1 = read_ecc[1] ^ test_ecc[1];
+ d2 = read_ecc[2] ^ test_ecc[2];
+
+ if ((d0 | d1 | d2) == 0)
+ return 0; /* no error */
+
+ if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
+ ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
+ ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) {
+ /* Single bit (recoverable) error in data */
+
+ unsigned byte;
+ unsigned bit;
+
+#ifdef CONFIG_YAFFS_ECC_WRONG_ORDER
+ // swap the bytes to correct for the wrong order
+ unsigned char t;
+
+ t = d0;
+ d0 = d1;
+ d1 = t;
+#endif
+
+ bit = byte = 0;
+
+ if (d1 & 0x80)
+ byte |= 0x80;
+ if (d1 & 0x20)
+ byte |= 0x40;
+ if (d1 & 0x08)
+ byte |= 0x20;
+ if (d1 & 0x02)
+ byte |= 0x10;
+ if (d0 & 0x80)
+ byte |= 0x08;
+ if (d0 & 0x20)
+ byte |= 0x04;
+ if (d0 & 0x08)
+ byte |= 0x02;
+ if (d0 & 0x02)
+ byte |= 0x01;
+
+ if (d2 & 0x80)
+ bit |= 0x04;
+ if (d2 & 0x20)
+ bit |= 0x02;
+ if (d2 & 0x08)
+ bit |= 0x01;
+
+ data[byte] ^= (1 << bit);
+
+ return 1; /* Corrected the error */
+ }
+
+ if ((yaffs_CountBits(d0) +
+ yaffs_CountBits(d1) +
+ yaffs_CountBits(d2)) == 1) {
+ /* Reccoverable error in ecc */
+
+ read_ecc[0] = test_ecc[0];
+ read_ecc[1] = test_ecc[1];
+ read_ecc[2] = test_ecc[2];
+
+ return 1; /* Corrected the error */
+ }
+
+ /* Unrecoverable error */
+
+ return -1;
+
+}
+
+
+/*
+ * ECCxxxOther does ECC calcs on arbitrary n bytes of data
+ */
+void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
+ yaffs_ECCOther * eccOther)
+{
+ unsigned int i;
+
+ unsigned char col_parity = 0;
+ unsigned line_parity = 0;
+ unsigned line_parity_prime = 0;
+ unsigned char b;
+
+ for (i = 0; i < nBytes; i++) {
+ b = column_parity_table[*data++];
+ col_parity ^= b;
+
+ if (b & 0x01) {
+ /* odd number of bits in the byte */
+ line_parity ^= i;
+ line_parity_prime ^= ~i;
+ }
+
+ }
+
+ eccOther->colParity = (col_parity >> 2) & 0x3f;
+ eccOther->lineParity = line_parity;
+ eccOther->lineParityPrime = line_parity_prime;
+}
+
+int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
+ yaffs_ECCOther * read_ecc,
+ const yaffs_ECCOther * test_ecc)
+{
+ unsigned char cDelta; /* column parity delta */
+ unsigned lDelta; /* line parity delta */
+ unsigned lDeltaPrime; /* line parity delta */
+ unsigned bit;
+
+ cDelta = read_ecc->colParity ^ test_ecc->colParity;
+ lDelta = read_ecc->lineParity ^ test_ecc->lineParity;
+ lDeltaPrime = read_ecc->lineParityPrime ^ test_ecc->lineParityPrime;
+
+ if ((cDelta | lDelta | lDeltaPrime) == 0)
+ return 0; /* no error */
+
+ if (lDelta == ~lDeltaPrime &&
+ (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15))
+ {
+ /* Single bit (recoverable) error in data */
+
+ bit = 0;
+
+ if (cDelta & 0x20)
+ bit |= 0x04;
+ if (cDelta & 0x08)
+ bit |= 0x02;
+ if (cDelta & 0x02)
+ bit |= 0x01;
+
+ if(lDelta >= nBytes)
+ return -1;
+
+ data[lDelta] ^= (1 << bit);
+
+ return 1; /* corrected */
+ }
+
+ if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
+ yaffs_CountBits(cDelta)) == 1) {
+ /* Reccoverable error in ecc */
+
+ *read_ecc = *test_ecc;
+ return 1; /* corrected */
+ }
+
+ /* Unrecoverable error */
+
+ return -1;
+
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+ /*
+ * This code implements the ECC algorithm used in SmartMedia.
+ *
+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
+ * The two unused bit are set to 1.
+ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
+ * blocks are used on a 512-byte NAND page.
+ *
+ */
+
+#ifndef __YAFFS_ECC_H__
+#define __YAFFS_ECC_H__
+
+typedef struct {
+ unsigned char colParity;
+ unsigned lineParity;
+ unsigned lineParityPrime;
+} yaffs_ECCOther;
+
+void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc);
+int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
+ const unsigned char *test_ecc);
+
+void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
+ yaffs_ECCOther * ecc);
+int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
+ yaffs_ECCOther * read_ecc,
+ const yaffs_ECCOther * test_ecc);
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_FLASH_H__
+#define __YAFFS_FLASH_H__
+
+
+#include "yaffs_guts.h"
+int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
+int yflash_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare);
+int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags);
+int yflash_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);
+int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
+int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
+int yflash_InitialiseNAND(yaffs_Device *dev);
+int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
+int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+const char *yaffs_guts_c_version =
+ "$Id: yaffs_guts.c,v 1.52 2007/10/16 00:45:05 charles Exp $";
+
+#include "yportenv.h"
+#include "linux/stat.h"
+
+#include "yaffsinterface.h"
+#include "yaffsfs.h"
+#include "yaffs_guts.h"
+#include "yaffs_tagsvalidity.h"
+
+#include "yaffs_tagscompat.h"
+#ifndef CONFIG_YAFFS_USE_OWN_SORT
+#include "yaffs_qsort.h"
+#endif
+#include "yaffs_nand.h"
+
+#include "yaffs_checkptrw.h"
+
+#include "yaffs_nand.h"
+#include "yaffs_packedtags2.h"
+
+#include "malloc.h"
+
+#ifdef CONFIG_YAFFS_WINCE
+void yfsd_LockYAFFS(BOOL fsLockOnly);
+void yfsd_UnlockYAFFS(BOOL fsLockOnly);
+#endif
+
+#define YAFFS_PASSIVE_GC_CHUNKS 2
+
+#include "yaffs_ecc.h"
+
+
+/* Robustification (if it ever comes about...) */
+static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND);
+static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk);
+static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data,
+ const yaffs_ExtendedTags * tags);
+static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
+ const yaffs_ExtendedTags * tags);
+
+/* Other local prototypes */
+static int yaffs_UnlinkObject( yaffs_Object *obj);
+static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj);
+
+static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList);
+
+static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device * dev,
+ const __u8 * buffer,
+ yaffs_ExtendedTags * tags,
+ int useReserve);
+static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
+ int chunkInNAND, int inScan);
+
+static yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
+ yaffs_ObjectType type);
+static void yaffs_AddObjectToDirectory(yaffs_Object * directory,
+ yaffs_Object * obj);
+static int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name,
+ int force, int isShrink, int shadows);
+static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj);
+static int yaffs_CheckStructures(void);
+static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,
+ int chunkOffset, int *limit);
+static int yaffs_DoGenericObjectDeletion(yaffs_Object * in);
+
+static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
+
+static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
+static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
+ int lineNo);
+
+static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
+ int chunkInNAND);
+
+static int yaffs_UnlinkWorker(yaffs_Object * obj);
+static void yaffs_DestroyObject(yaffs_Object * obj);
+
+static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId,
+ int chunkInObject);
+
+loff_t yaffs_GetFileSize(yaffs_Object * obj);
+
+static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr);
+
+static void yaffs_VerifyFreeChunks(yaffs_Device * dev);
+
+static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in);
+
+#ifdef YAFFS_PARANOID
+static int yaffs_CheckFileSanity(yaffs_Object * in);
+#else
+#define yaffs_CheckFileSanity(in)
+#endif
+
+static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in);
+static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId);
+
+static void yaffs_InvalidateCheckpoint(yaffs_Device *dev);
+
+static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode,
+ yaffs_ExtendedTags * tags);
+
+static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos);
+static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev,
+ yaffs_FileStructure * fStruct,
+ __u32 chunkId);
+
+
+/* Function to calculate chunk and offset */
+
+static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
+{
+ if(dev->chunkShift){
+ /* Easy-peasy power of 2 case */
+ *chunk = (__u32)(addr >> dev->chunkShift);
+ *offset = (__u32)(addr & dev->chunkMask);
+ }
+ else if(dev->crumbsPerChunk)
+ {
+ /* Case where we're using "crumbs" */
+ *offset = (__u32)(addr & dev->crumbMask);
+ addr >>= dev->crumbShift;
+ *chunk = ((__u32)addr)/dev->crumbsPerChunk;
+ *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
+ }
+ else
+ YBUG();
+}
+
+/* Function to return the number of shifts for a power of 2 greater than or equal
+ * to the given number
+ * Note we don't try to cater for all possible numbers and this does not have to
+ * be hellishly efficient.
+ */
+
+static __u32 ShiftsGE(__u32 x)
+{
+ int extraBits;
+ int nShifts;
+
+ nShifts = extraBits = 0;
+
+ while(x>1){
+ if(x & 1) extraBits++;
+ x>>=1;
+ nShifts++;
+ }
+
+ if(extraBits)
+ nShifts++;
+
+ return nShifts;
+}
+
+/* Function to return the number of shifts to get a 1 in bit 0
+ */
+
+static __u32 ShiftDiv(__u32 x)
+{
+ int nShifts;
+
+ nShifts = 0;
+
+ if(!x) return 0;
+
+ while( !(x&1)){
+ x>>=1;
+ nShifts++;
+ }
+
+ return nShifts;
+}
+
+
+
+/*
+ * Temporary buffer manipulations.
+ */
+
+static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
+{
+ int i;
+ __u8 *buf = (__u8 *)1;
+
+ memset(dev->tempBuffer,0,sizeof(dev->tempBuffer));
+
+ for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
+ dev->tempBuffer[i].line = 0; /* not in use */
+ dev->tempBuffer[i].buffer = buf =
+ YMALLOC_DMA(dev->nDataBytesPerChunk);
+ }
+
+ return buf ? YAFFS_OK : YAFFS_FAIL;
+
+}
+
+static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
+{
+ int i, j;
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ if (dev->tempBuffer[i].line == 0) {
+ dev->tempBuffer[i].line = lineNo;
+ if ((i + 1) > dev->maxTemp) {
+ dev->maxTemp = i + 1;
+ for (j = 0; j <= i; j++)
+ dev->tempBuffer[j].maxLine =
+ dev->tempBuffer[j].line;
+ }
+
+ return dev->tempBuffer[i].buffer;
+ }
+ }
+
+ T(YAFFS_TRACE_BUFFERS,
+ (TSTR("Out of temp buffers at line %d, other held by lines:"),
+ lineNo));
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ T(YAFFS_TRACE_BUFFERS, (TSTR(" %d "), dev->tempBuffer[i].line));
+ }
+ T(YAFFS_TRACE_BUFFERS, (TSTR(" " TENDSTR)));
+
+ /*
+ * If we got here then we have to allocate an unmanaged one
+ * This is not good.
+ */
+
+ dev->unmanagedTempAllocations++;
+ return YMALLOC(dev->nDataBytesPerChunk);
+
+}
+
+static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
+ int lineNo)
+{
+ int i;
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ if (dev->tempBuffer[i].buffer == buffer) {
+ dev->tempBuffer[i].line = 0;
+ return;
+ }
+ }
+
+ if (buffer) {
+ /* assume it is an unmanaged one. */
+ T(YAFFS_TRACE_BUFFERS,
+ (TSTR("Releasing unmanaged temp buffer in line %d" TENDSTR),
+ lineNo));
+ YFREE(buffer);
+ dev->unmanagedTempDeallocations++;
+ }
+
+}
+
+/*
+ * Determine if we have a managed buffer.
+ */
+int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer)
+{
+ int i;
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ if (dev->tempBuffer[i].buffer == buffer)
+ return 1;
+
+ }
+
+ for (i = 0; i < dev->nShortOpCaches; i++) {
+ if( dev->srCache[i].data == buffer )
+ return 1;
+
+ }
+
+ if (buffer == dev->checkpointBuffer)
+ return 1;
+
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR)));
+ return 0;
+}
+
+
+
+/*
+ * Chunk bitmap manipulations
+ */
+
+static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device * dev, int blk)
+{
+ if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),
+ blk));
+ YBUG();
+ }
+ return dev->chunkBits +
+ (dev->chunkBitmapStride * (blk - dev->internalStartBlock));
+}
+
+static Y_INLINE void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk)
+{
+ if(blk < dev->internalStartBlock || blk > dev->internalEndBlock ||
+ chunk < 0 || chunk >= dev->nChunksPerBlock) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR),blk,chunk));
+ YBUG();
+ }
+}
+
+static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev, blk);
+
+ memset(blkBits, 0, dev->chunkBitmapStride);
+}
+
+static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device * dev, int blk, int chunk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev, blk);
+
+ yaffs_VerifyChunkBitId(dev,blk,chunk);
+
+ blkBits[chunk / 8] &= ~(1 << (chunk & 7));
+}
+
+static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev, blk);
+
+ yaffs_VerifyChunkBitId(dev,blk,chunk);
+
+ blkBits[chunk / 8] |= (1 << (chunk & 7));
+}
+
+static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev, blk);
+ yaffs_VerifyChunkBitId(dev,blk,chunk);
+
+ return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
+}
+
+static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev, blk);
+ int i;
+ for (i = 0; i < dev->chunkBitmapStride; i++) {
+ if (*blkBits)
+ return 1;
+ blkBits++;
+ }
+ return 0;
+}
+
+static int yaffs_CountChunkBits(yaffs_Device * dev, int blk)
+{
+ __u8 *blkBits = yaffs_BlockBits(dev, blk);
+ int i;
+ int n = 0;
+ for (i = 0; i < dev->chunkBitmapStride; i++) {
+ __u8 x = *blkBits;
+ while(x){
+ if(x & 1)
+ n++;
+ x >>=1;
+ }
+
+ blkBits++;
+ }
+ return n;
+}
+
+/*
+ * Verification code
+ */
+
+static int yaffs_SkipVerification(yaffs_Device *dev)
+{
+ return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
+}
+
+static int yaffs_SkipFullVerification(yaffs_Device *dev)
+{
+ return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL));
+}
+
+static int yaffs_SkipNANDVerification(yaffs_Device *dev)
+{
+ return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND));
+}
+
+static const char * blockStateName[] = {
+"Unknown",
+"Needs scanning",
+"Scanning",
+"Empty",
+"Allocating",
+"Full",
+"Dirty",
+"Checkpoint",
+"Collecting",
+"Dead"
+};
+
+static void yaffs_VerifyBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n)
+{
+ int actuallyUsed;
+ int inUse;
+
+ if(yaffs_SkipVerification(dev))
+ return;
+
+ /* Report illegal runtime states */
+ if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
+ T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState));
+
+ switch(bi->blockState){
+ case YAFFS_BLOCK_STATE_UNKNOWN:
+ case YAFFS_BLOCK_STATE_SCANNING:
+ case YAFFS_BLOCK_STATE_NEEDS_SCANNING:
+ T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has bad run-state %s"TENDSTR),
+ n,blockStateName[bi->blockState]));
+ }
+
+ /* Check pages in use and soft deletions are legal */
+
+ actuallyUsed = bi->pagesInUse - bi->softDeletions;
+
+ if(bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock ||
+ bi->softDeletions < 0 || bi->softDeletions > dev->nChunksPerBlock ||
+ actuallyUsed < 0 || actuallyUsed > dev->nChunksPerBlock)
+ T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR),
+ n,bi->pagesInUse,bi->softDeletions));
+
+
+ /* Check chunk bitmap legal */
+ inUse = yaffs_CountChunkBits(dev,n);
+ if(inUse != bi->pagesInUse)
+ T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR),
+ n,bi->pagesInUse,inUse));
+
+ /* Check that the sequence number is valid.
+ * Ten million is legal, but is very unlikely
+ */
+ if(dev->isYaffs2 &&
+ (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) &&
+ (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000 ))
+ T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has suspect sequence number of %d"TENDSTR),
+ n,bi->sequenceNumber));
+
+}
+
+static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n)
+{
+ yaffs_VerifyBlock(dev,bi,n);
+
+ /* After collection the block should be in the erased state */
+ /* TODO: This will need to change if we do partial gc */
+
+ if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
+ T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR),
+ n,bi->blockState));
+ }
+}
+
+static void yaffs_VerifyBlocks(yaffs_Device *dev)
+{
+ int i;
+ int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES];
+ int nIllegalBlockStates = 0;
+
+
+ if(yaffs_SkipVerification(dev))
+ return;
+
+ memset(nBlocksPerState,0,sizeof(nBlocksPerState));
+
+
+ for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
+ yaffs_VerifyBlock(dev,bi,i);
+
+ if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
+ nBlocksPerState[bi->blockState]++;
+ else
+ nIllegalBlockStates++;
+
+ }
+
+ T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR)));
+ T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR)));
+
+ T(YAFFS_TRACE_VERIFY,(TSTR("%d blocks have illegal states"TENDSTR),nIllegalBlockStates));
+ if(nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
+ T(YAFFS_TRACE_VERIFY,(TSTR("Too many allocating blocks"TENDSTR)));
+
+ for(i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++)
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("%s %d blocks"TENDSTR),
+ blockStateName[i],nBlocksPerState[i]));
+
+ if(dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR),
+ dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]));
+
+ if(dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Erased block count wrong dev %d count %d"TENDSTR),
+ dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]));
+
+ if(nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1)
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR),
+ nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING]));
+
+ T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR)));
+
+}
+
+/*
+ * Verify the object header. oh must be valid, but obj and tags may be NULL in which
+ * case those tests will not be performed.
+ */
+static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck)
+{
+ if(yaffs_SkipVerification(obj->myDev))
+ return;
+
+ if(!(tags && obj && oh)){
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR),
+ (__u32)tags,(__u32)obj,(__u32)oh));
+ return;
+ }
+
+ if(oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
+ oh->type > YAFFS_OBJECT_TYPE_MAX)
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d header type is illegal value 0x%x"TENDSTR),
+ tags->objectId, oh->type));
+
+ if(tags->objectId != obj->objectId)
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d header mismatch objectId %d"TENDSTR),
+ tags->objectId, obj->objectId));
+
+
+ /*
+ * Check that the object's parent ids match if parentCheck requested.
+ *
+ * Tests do not apply to the root object.
+ */
+
+ if(parentCheck && tags->objectId > 1 && !obj->parent)
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR),
+ tags->objectId, oh->parentObjectId));
+
+
+ if(parentCheck && obj->parent &&
+ oh->parentObjectId != obj->parent->objectId &&
+ (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED ||
+ obj->parent->objectId != YAFFS_OBJECTID_DELETED))
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR),
+ tags->objectId, oh->parentObjectId, obj->parent->objectId));
+
+
+ if(tags->objectId > 1 && oh->name[0] == 0) /* Null name */
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d header name is NULL"TENDSTR),
+ obj->objectId));
+
+ if(tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d header name is 0xFF"TENDSTR),
+ obj->objectId));
+}
+
+
+
+static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn,
+ __u32 level, int chunkOffset)
+{
+ int i;
+ yaffs_Device *dev = obj->myDev;
+ int ok = 1;
+
+ if (tn) {
+ if (level > 0) {
+
+ for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){
+ if (tn->internal[i]) {
+ ok = yaffs_VerifyTnodeWorker(obj,
+ tn->internal[i],
+ level - 1,
+ (chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i);
+ }
+ }
+ } else if (level == 0) {
+ int i;
+ yaffs_ExtendedTags tags;
+ __u32 objectId = obj->objectId;
+
+ chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS;
+
+ for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){
+ __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
+
+ if(theChunk > 0){
+ /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */
+ yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags);
+ if(tags.objectId != objectId || tags.chunkId != chunkOffset){
+ T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR),
+ objectId, chunkOffset, theChunk,
+ tags.objectId, tags.chunkId));
+ }
+ }
+ chunkOffset++;
+ }
+ }
+ }
+
+ return ok;
+
+}
+
+
+static void yaffs_VerifyFile(yaffs_Object *obj)
+{
+ int requiredTallness;
+ int actualTallness;
+ __u32 lastChunk;
+ __u32 x;
+ __u32 i;
+ yaffs_Device *dev;
+ yaffs_ExtendedTags tags;
+ yaffs_Tnode *tn;
+ __u32 objectId;
+
+ if(obj && yaffs_SkipVerification(obj->myDev))
+ return;
+
+ dev = obj->myDev;
+ objectId = obj->objectId;
+
+ /* Check file size is consistent with tnode depth */
+ lastChunk = obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1;
+ x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS;
+ requiredTallness = 0;
+ while (x> 0) {
+ x >>= YAFFS_TNODES_INTERNAL_BITS;
+ requiredTallness++;
+ }
+
+ actualTallness = obj->variant.fileVariant.topLevel;
+
+ if(requiredTallness > actualTallness )
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR),
+ obj->objectId,actualTallness, requiredTallness));
+
+
+ /* Check that the chunks in the tnode tree are all correct.
+ * We do this by scanning through the tnode tree and
+ * checking the tags for every chunk match.
+ */
+
+ if(yaffs_SkipNANDVerification(dev))
+ return;
+
+ for(i = 1; i <= lastChunk; i++){
+ tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i);
+
+ if (tn) {
+ __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
+ if(theChunk > 0){
+ /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),objectId,i,theChunk)); */
+ yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags);
+ if(tags.objectId != objectId || tags.chunkId != i){
+ T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR),
+ objectId, i, theChunk,
+ tags.objectId, tags.chunkId));
+ }
+ }
+ }
+
+ }
+
+}
+
+static void yaffs_VerifyDirectory(yaffs_Object *obj)
+{
+ if(obj && yaffs_SkipVerification(obj->myDev))
+ return;
+
+}
+
+static void yaffs_VerifyHardLink(yaffs_Object *obj)
+{
+ if(obj && yaffs_SkipVerification(obj->myDev))
+ return;
+
+ /* Verify sane equivalent object */
+}
+
+static void yaffs_VerifySymlink(yaffs_Object *obj)
+{
+ if(obj && yaffs_SkipVerification(obj->myDev))
+ return;
+
+ /* Verify symlink string */
+}
+
+static void yaffs_VerifySpecial(yaffs_Object *obj)
+{
+ if(obj && yaffs_SkipVerification(obj->myDev))
+ return;
+}
+
+static void yaffs_VerifyObject(yaffs_Object *obj)
+{
+ yaffs_Device *dev;
+
+ __u32 chunkMin;
+ __u32 chunkMax;
+
+ __u32 chunkIdOk;
+ __u32 chunkIsLive;
+
+ if(!obj)
+ return;
+
+ dev = obj->myDev;
+
+ if(yaffs_SkipVerification(dev))
+ return;
+
+ /* Check sane object header chunk */
+
+ chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
+ chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
+
+ chunkIdOk = (obj->chunkId >= chunkMin && obj->chunkId <= chunkMax);
+ chunkIsLive = chunkIdOk &&
+ yaffs_CheckChunkBit(dev,
+ obj->chunkId / dev->nChunksPerBlock,
+ obj->chunkId % dev->nChunksPerBlock);
+ if(!obj->fake &&
+ (!chunkIdOk || !chunkIsLive)) {
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d has chunkId %d %s %s"TENDSTR),
+ obj->objectId,obj->chunkId,
+ chunkIdOk ? "" : ",out of range",
+ chunkIsLive || !chunkIdOk ? "" : ",marked as deleted"));
+ }
+
+ if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) {
+ yaffs_ExtendedTags tags;
+ yaffs_ObjectHeader *oh;
+ __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__);
+
+ oh = (yaffs_ObjectHeader *)buffer;
+
+ yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags);
+
+ yaffs_VerifyObjectHeader(obj,oh,&tags,1);
+
+ yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
+ }
+
+ /* Verify it has a parent */
+ if(obj && !obj->fake &&
+ (!obj->parent || obj->parent->myDev != dev)){
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR),
+ obj->objectId,obj->parent));
+ }
+
+ /* Verify parent is a directory */
+ if(obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR),
+ obj->objectId,obj->parent->variantType));
+ }
+
+ switch(obj->variantType){
+ case YAFFS_OBJECT_TYPE_FILE:
+ yaffs_VerifyFile(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ yaffs_VerifySymlink(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ yaffs_VerifyDirectory(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ yaffs_VerifyHardLink(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ yaffs_VerifySpecial(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ default:
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Obj %d has illegaltype %d"TENDSTR),
+ obj->objectId,obj->variantType));
+ break;
+ }
+
+
+}
+
+static void yaffs_VerifyObjects(yaffs_Device *dev)
+{
+ yaffs_Object *obj;
+ int i;
+ struct list_head *lh;
+
+ if(yaffs_SkipVerification(dev))
+ return;
+
+ /* Iterate through the objects in each hash entry */
+
+ for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
+ list_for_each(lh, &dev->objectBucket[i].list) {
+ if (lh) {
+ obj = list_entry(lh, yaffs_Object, hashLink);
+ yaffs_VerifyObject(obj);
+ }
+ }
+ }
+
+}
+
+
+/*
+ * Simple hash function. Needs to have a reasonable spread
+ */
+
+static Y_INLINE int yaffs_HashFunction(int n)
+{
+/* XXX U-BOOT XXX */
+ /*n = abs(n); */
+ if (n < 0)
+ n = -n;
+ return (n % YAFFS_NOBJECT_BUCKETS);
+}
+
+/*
+ * Access functions to useful fake objects
+ */
+
+yaffs_Object *yaffs_Root(yaffs_Device * dev)
+{
+ return dev->rootDir;
+}
+
+yaffs_Object *yaffs_LostNFound(yaffs_Device * dev)
+{
+ return dev->lostNFoundDir;
+}
+
+
+/*
+ * Erased NAND checking functions
+ */
+
+int yaffs_CheckFF(__u8 * buffer, int nBytes)
+{
+ /* Horrible, slow implementation */
+ while (nBytes--) {
+ if (*buffer != 0xFF)
+ return 0;
+ buffer++;
+ }
+ return 1;
+}
+
+static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
+ int chunkInNAND)
+{
+
+ int retval = YAFFS_OK;
+ __u8 *data = yaffs_GetTempBuffer(dev, __LINE__);
+ yaffs_ExtendedTags tags;
+ int result;
+
+ result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);
+
+ if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)
+ retval = YAFFS_FAIL;
+
+
+ if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {
+ T(YAFFS_TRACE_NANDACCESS,
+ (TSTR("Chunk %d not erased" TENDSTR), chunkInNAND));
+ retval = YAFFS_FAIL;
+ }
+
+ yaffs_ReleaseTempBuffer(dev, data, __LINE__);
+
+ return retval;
+
+}
+
+static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
+ const __u8 * data,
+ yaffs_ExtendedTags * tags,
+ int useReserve)
+{
+ int attempts = 0;
+ int writeOk = 0;
+ int chunk;
+
+ yaffs_InvalidateCheckpoint(dev);
+
+ do {
+ yaffs_BlockInfo *bi = 0;
+ int erasedOk = 0;
+
+ chunk = yaffs_AllocateChunk(dev, useReserve, &bi);
+ if (chunk < 0) {
+ /* no space */
+ break;
+ }
+
+ /* First check this chunk is erased, if it needs
+ * checking. The checking policy (unless forced
+ * always on) is as follows:
+ *
+ * Check the first page we try to write in a block.
+ * If the check passes then we don't need to check any
+ * more. If the check fails, we check again...
+ * If the block has been erased, we don't need to check.
+ *
+ * However, if the block has been prioritised for gc,
+ * then we think there might be something odd about
+ * this block and stop using it.
+ *
+ * Rationale: We should only ever see chunks that have
+ * not been erased if there was a partially written
+ * chunk due to power loss. This checking policy should
+ * catch that case with very few checks and thus save a
+ * lot of checks that are most likely not needed.
+ */
+ if (bi->gcPrioritise) {
+ yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
+ /* try another chunk */
+ continue;
+ }
+
+ /* let's give it a try */
+ attempts++;
+
+#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED
+ bi->skipErasedCheck = 0;
+#endif
+ if (!bi->skipErasedCheck) {
+ erasedOk = yaffs_CheckChunkErased(dev, chunk);
+ if (erasedOk != YAFFS_OK) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR ("**>> yaffs chunk %d was not erased"
+ TENDSTR), chunk));
+
+ /* try another chunk */
+ continue;
+ }
+ bi->skipErasedCheck = 1;
+ }
+
+ writeOk = yaffs_WriteChunkWithTagsToNAND(dev, chunk,
+ data, tags);
+ if (writeOk != YAFFS_OK) {
+ yaffs_HandleWriteChunkError(dev, chunk, erasedOk);
+ /* try another chunk */
+ continue;
+ }
+
+ /* Copy the data into the robustification buffer */
+ yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
+
+ } while (writeOk != YAFFS_OK &&
+ (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
+
+ if(!writeOk)
+ chunk = -1;
+
+ if (attempts > 1) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("**>> yaffs write required %d attempts" TENDSTR),
+ attempts));
+
+ dev->nRetriedWrites += (attempts - 1);
+ }
+
+ return chunk;
+}
+
+/*
+ * Block retiring for handling a broken block.
+ */
+
+static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
+{
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
+
+ yaffs_InvalidateCheckpoint(dev);
+
+ yaffs_MarkBlockBad(dev, blockInNAND);
+
+ bi->blockState = YAFFS_BLOCK_STATE_DEAD;
+ bi->gcPrioritise = 0;
+ bi->needsRetiring = 0;
+
+ dev->nRetiredBlocks++;
+}
+
+/*
+ * Functions for robustisizing TODO
+ *
+ */
+
+static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data,
+ const yaffs_ExtendedTags * tags)
+{
+}
+
+static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
+ const yaffs_ExtendedTags * tags)
+{
+}
+
+void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi)
+{
+ if(!bi->gcPrioritise){
+ bi->gcPrioritise = 1;
+ dev->hasPendingPrioritisedGCs = 1;
+ bi->chunkErrorStrikes ++;
+
+ if(bi->chunkErrorStrikes > 3){
+ bi->needsRetiring = 1; /* Too many stikes, so retire this */
+ T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));
+
+ }
+
+ }
+}
+
+static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk)
+{
+
+ int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
+
+ yaffs_HandleChunkError(dev,bi);
+
+
+ if(erasedOk ) {
+ /* Was an actual write failure, so mark the block for retirement */
+ bi->needsRetiring = 1;
+ T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND));
+
+
+ }
+
+ /* Delete the chunk */
+ yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
+}
+
+
+/*---------------- Name handling functions ------------*/
+
+static __u16 yaffs_CalcNameSum(const YCHAR * name)
+{
+ __u16 sum = 0;
+ __u16 i = 1;
+
+ YUCHAR *bname = (YUCHAR *) name;
+ if (bname) {
+ while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) {
+
+#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
+ sum += yaffs_toupper(*bname) * i;
+#else
+ sum += (*bname) * i;
+#endif
+ i++;
+ bname++;
+ }
+ }
+ return sum;
+}
+
+static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
+{
+#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
+ if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {
+ yaffs_strcpy(obj->shortName, name);
+ } else {
+ obj->shortName[0] = _Y('\0');
+ }
+#endif
+ obj->sum = yaffs_CalcNameSum(name);
+}
+
+/*-------------------- TNODES -------------------
+
+ * List of spare tnodes
+ * The list is hooked together using the first pointer
+ * in the tnode.
+ */
+
+/* yaffs_CreateTnodes creates a bunch more tnodes and
+ * adds them to the tnode free list.
+ * Don't use this function directly
+ */
+
+static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)
+{
+ int i;
+ int tnodeSize;
+ yaffs_Tnode *newTnodes;
+ __u8 *mem;
+ yaffs_Tnode *curr;
+ yaffs_Tnode *next;
+ yaffs_TnodeList *tnl;
+
+ if (nTnodes < 1)
+ return YAFFS_OK;
+
+ /* Calculate the tnode size in bytes for variable width tnode support.
+ * Must be a multiple of 32-bits */
+ tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+
+ /* make these things */
+
+ newTnodes = YMALLOC(nTnodes * tnodeSize);
+ mem = (__u8 *)newTnodes;
+
+ if (!newTnodes) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ /* Hook them into the free list */
+#if 0
+ for (i = 0; i < nTnodes - 1; i++) {
+ newTnodes[i].internal[0] = &newTnodes[i + 1];
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
+#endif
+ }
+
+ newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes;
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
+#endif
+ dev->freeTnodes = newTnodes;
+#else
+ /* New hookup for wide tnodes */
+ for(i = 0; i < nTnodes -1; i++) {
+ curr = (yaffs_Tnode *) &mem[i * tnodeSize];
+ next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
+ curr->internal[0] = next;
+ }
+
+ curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
+ curr->internal[0] = dev->freeTnodes;
+ dev->freeTnodes = (yaffs_Tnode *)mem;
+
+#endif
+
+
+ dev->nFreeTnodes += nTnodes;
+ dev->nTnodesCreated += nTnodes;
+
+ /* Now add this bunch of tnodes to a list for freeing up.
+ * NB If we can't add this to the management list it isn't fatal
+ * but it just means we can't free this bunch of tnodes later.
+ */
+
+ tnl = YMALLOC(sizeof(yaffs_TnodeList));
+ if (!tnl) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("yaffs: Could not add tnodes to management list" TENDSTR)));
+ return YAFFS_FAIL;
+
+ } else {
+ tnl->tnodes = newTnodes;
+ tnl->next = dev->allocatedTnodeList;
+ dev->allocatedTnodeList = tnl;
+ }
+
+ T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
+
+ return YAFFS_OK;
+}
+
+/* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */
+
+static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device * dev)
+{
+ yaffs_Tnode *tn = NULL;
+
+ /* If there are none left make more */
+ if (!dev->freeTnodes) {
+ yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
+ }
+
+ if (dev->freeTnodes) {
+ tn = dev->freeTnodes;
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ if (tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) {
+ /* Hoosterman, this thing looks like it isn't in the list */
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs: Tnode list bug 1" TENDSTR)));
+ }
+#endif
+ dev->freeTnodes = dev->freeTnodes->internal[0];
+ dev->nFreeTnodes--;
+ }
+
+ return tn;
+}
+
+static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
+{
+ yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
+
+ if(tn)
+ memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
+
+ return tn;
+}
+
+/* FreeTnode frees up a tnode and puts it back on the free list */
+static void yaffs_FreeTnode(yaffs_Device * dev, yaffs_Tnode * tn)
+{
+ if (tn) {
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ if (tn->internal[YAFFS_NTNODES_INTERNAL] != 0) {
+ /* Hoosterman, this thing looks like it is already in the list */
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs: Tnode list bug 2" TENDSTR)));
+ }
+ tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
+#endif
+ tn->internal[0] = dev->freeTnodes;
+ dev->freeTnodes = tn;
+ dev->nFreeTnodes++;
+ }
+}
+
+static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
+{
+ /* Free the list of allocated tnodes */
+ yaffs_TnodeList *tmp;
+
+ while (dev->allocatedTnodeList) {
+ tmp = dev->allocatedTnodeList->next;
+
+ YFREE(dev->allocatedTnodeList->tnodes);
+ YFREE(dev->allocatedTnodeList);
+ dev->allocatedTnodeList = tmp;
+
+ }
+
+ dev->freeTnodes = NULL;
+ dev->nFreeTnodes = 0;
+}
+
+static void yaffs_InitialiseTnodes(yaffs_Device * dev)
+{
+ dev->allocatedTnodeList = NULL;
+ dev->freeTnodes = NULL;
+ dev->nFreeTnodes = 0;
+ dev->nTnodesCreated = 0;
+
+}
+
+
+void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val)
+{
+ __u32 *map = (__u32 *)tn;
+ __u32 bitInMap;
+ __u32 bitInWord;
+ __u32 wordInMap;
+ __u32 mask;
+
+ pos &= YAFFS_TNODES_LEVEL0_MASK;
+ val >>= dev->chunkGroupBits;
+
+ bitInMap = pos * dev->tnodeWidth;
+ wordInMap = bitInMap /32;
+ bitInWord = bitInMap & (32 -1);
+
+ mask = dev->tnodeMask << bitInWord;
+
+ map[wordInMap] &= ~mask;
+ map[wordInMap] |= (mask & (val << bitInWord));
+
+ if(dev->tnodeWidth > (32-bitInWord)) {
+ bitInWord = (32 - bitInWord);
+ wordInMap++;;
+ mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord);
+ map[wordInMap] &= ~mask;
+ map[wordInMap] |= (mask & (val >> bitInWord));
+ }
+}
+
+static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos)
+{
+ __u32 *map = (__u32 *)tn;
+ __u32 bitInMap;
+ __u32 bitInWord;
+ __u32 wordInMap;
+ __u32 val;
+
+ pos &= YAFFS_TNODES_LEVEL0_MASK;
+
+ bitInMap = pos * dev->tnodeWidth;
+ wordInMap = bitInMap /32;
+ bitInWord = bitInMap & (32 -1);
+
+ val = map[wordInMap] >> bitInWord;
+
+ if(dev->tnodeWidth > (32-bitInWord)) {
+ bitInWord = (32 - bitInWord);
+ wordInMap++;;
+ val |= (map[wordInMap] << bitInWord);
+ }
+
+ val &= dev->tnodeMask;
+ val <<= dev->chunkGroupBits;
+
+ return val;
+}
+
+/* ------------------- End of individual tnode manipulation -----------------*/
+
+/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------
+ * The look up tree is represented by the top tnode and the number of topLevel
+ * in the tree. 0 means only the level 0 tnode is in the tree.
+ */
+
+/* FindLevel0Tnode finds the level 0 tnode, if one exists. */
+static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev,
+ yaffs_FileStructure * fStruct,
+ __u32 chunkId)
+{
+
+ yaffs_Tnode *tn = fStruct->top;
+ __u32 i;
+ int requiredTallness;
+ int level = fStruct->topLevel;
+
+ /* Check sane level and chunk Id */
+ if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) {
+ return NULL;
+ }
+
+ if (chunkId > YAFFS_MAX_CHUNK_ID) {
+ return NULL;
+ }
+
+ /* First check we're tall enough (ie enough topLevel) */
+
+ i = chunkId >> YAFFS_TNODES_LEVEL0_BITS;
+ requiredTallness = 0;
+ while (i) {
+ i >>= YAFFS_TNODES_INTERNAL_BITS;
+ requiredTallness++;
+ }
+
+ if (requiredTallness > fStruct->topLevel) {
+ /* Not tall enough, so we can't find it, return NULL. */
+ return NULL;
+ }
+
+ /* Traverse down to level 0 */
+ while (level > 0 && tn) {
+ tn = tn->
+ internal[(chunkId >>
+ ( YAFFS_TNODES_LEVEL0_BITS +
+ (level - 1) *
+ YAFFS_TNODES_INTERNAL_BITS)
+ ) &
+ YAFFS_TNODES_INTERNAL_MASK];
+ level--;
+
+ }
+
+ return tn;
+}
+
+/* AddOrFindLevel0Tnode finds the level 0 tnode if it exists, otherwise first expands the tree.
+ * This happens in two steps:
+ * 1. If the tree isn't tall enough, then make it taller.
+ * 2. Scan down the tree towards the level 0 tnode adding tnodes if required.
+ *
+ * Used when modifying the tree.
+ *
+ * If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will
+ * be plugged into the ttree.
+ */
+
+static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,
+ yaffs_FileStructure * fStruct,
+ __u32 chunkId,
+ yaffs_Tnode *passedTn)
+{
+
+ int requiredTallness;
+ int i;
+ int l;
+ yaffs_Tnode *tn;
+
+ __u32 x;
+
+
+ /* Check sane level and page Id */
+ if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) {
+ return NULL;
+ }
+
+ if (chunkId > YAFFS_MAX_CHUNK_ID) {
+ return NULL;
+ }
+
+ /* First check we're tall enough (ie enough topLevel) */
+
+ x = chunkId >> YAFFS_TNODES_LEVEL0_BITS;
+ requiredTallness = 0;
+ while (x) {
+ x >>= YAFFS_TNODES_INTERNAL_BITS;
+ requiredTallness++;
+ }
+
+
+ if (requiredTallness > fStruct->topLevel) {
+ /* Not tall enough,gotta make the tree taller */
+ for (i = fStruct->topLevel; i < requiredTallness; i++) {
+
+ tn = yaffs_GetTnode(dev);
+
+ if (tn) {
+ tn->internal[0] = fStruct->top;
+ fStruct->top = tn;
+ } else {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("yaffs: no more tnodes" TENDSTR)));
+ }
+ }
+
+ fStruct->topLevel = requiredTallness;
+ }
+
+ /* Traverse down to level 0, adding anything we need */
+
+ l = fStruct->topLevel;
+ tn = fStruct->top;
+
+ if(l > 0) {
+ while (l > 0 && tn) {
+ x = (chunkId >>
+ ( YAFFS_TNODES_LEVEL0_BITS +
+ (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) &
+ YAFFS_TNODES_INTERNAL_MASK;
+
+
+ if((l>1) && !tn->internal[x]){
+ /* Add missing non-level-zero tnode */
+ tn->internal[x] = yaffs_GetTnode(dev);
+
+ } else if(l == 1) {
+ /* Looking from level 1 at level 0 */
+ if (passedTn) {
+ /* If we already have one, then release it.*/
+ if(tn->internal[x])
+ yaffs_FreeTnode(dev,tn->internal[x]);
+ tn->internal[x] = passedTn;
+
+ } else if(!tn->internal[x]) {
+ /* Don't have one, none passed in */
+ tn->internal[x] = yaffs_GetTnode(dev);
+ }
+ }
+
+ tn = tn->internal[x];
+ l--;
+ }
+ } else {
+ /* top is level 0 */
+ if(passedTn) {
+ memcpy(tn,passedTn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
+ yaffs_FreeTnode(dev,passedTn);
+ }
+ }
+
+ return tn;
+}
+
+static int yaffs_FindChunkInGroup(yaffs_Device * dev, int theChunk,
+ yaffs_ExtendedTags * tags, int objectId,
+ int chunkInInode)
+{
+ int j;
+
+ for (j = 0; theChunk && j < dev->chunkGroupSize; j++) {
+ if (yaffs_CheckChunkBit
+ (dev, theChunk / dev->nChunksPerBlock,
+ theChunk % dev->nChunksPerBlock)) {
+ yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL,
+ tags);
+ if (yaffs_TagsMatch(tags, objectId, chunkInInode)) {
+ /* found it; */
+ return theChunk;
+
+ }
+ }
+ theChunk++;
+ }
+ return -1;
+}
+
+
+/* DeleteWorker scans backwards through the tnode tree and deletes all the
+ * chunks and tnodes in the file
+ * Returns 1 if the tree was deleted.
+ * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
+ */
+
+static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,
+ int chunkOffset, int *limit)
+{
+ int i;
+ int chunkInInode;
+ int theChunk;
+ yaffs_ExtendedTags tags;
+ int foundChunk;
+ yaffs_Device *dev = in->myDev;
+
+ int allDone = 1;
+
+ if (tn) {
+ if (level > 0) {
+
+ for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0;
+ i--) {
+ if (tn->internal[i]) {
+ if (limit && (*limit) < 0) {
+ allDone = 0;
+ } else {
+ allDone =
+ yaffs_DeleteWorker(in,
+ tn->
+ internal
+ [i],
+ level -
+ 1,
+ (chunkOffset
+ <<
+ YAFFS_TNODES_INTERNAL_BITS)
+ + i,
+ limit);
+ }
+ if (allDone) {
+ yaffs_FreeTnode(dev,
+ tn->
+ internal[i]);
+ tn->internal[i] = NULL;
+ }
+ }
+
+ }
+ return (allDone) ? 1 : 0;
+ } else if (level == 0) {
+ int hitLimit = 0;
+
+ for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit;
+ i--) {
+ theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
+ if (theChunk) {
+
+ chunkInInode =
+ (chunkOffset <<
+ YAFFS_TNODES_LEVEL0_BITS) + i;
+
+ foundChunk =
+ yaffs_FindChunkInGroup(dev,
+ theChunk,
+ &tags,
+ in->objectId,
+ chunkInInode);
+
+ if (foundChunk > 0) {
+ yaffs_DeleteChunk(dev,
+ foundChunk, 1,
+ __LINE__);
+ in->nDataChunks--;
+ if (limit) {
+ *limit = *limit - 1;
+ if (*limit <= 0) {
+ hitLimit = 1;
+ }
+ }
+
+ }
+
+ yaffs_PutLevel0Tnode(dev,tn,i,0);
+ }
+
+ }
+ return (i < 0) ? 1 : 0;
+
+ }
+
+ }
+
+ return 1;
+
+}
+
+static void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk)
+{
+
+ yaffs_BlockInfo *theBlock;
+
+ T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk));
+
+ theBlock = yaffs_GetBlockInfo(dev, chunk / dev->nChunksPerBlock);
+ if (theBlock) {
+ theBlock->softDeletions++;
+ dev->nFreeChunks++;
+ }
+}
+
+/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file.
+ * All soft deleting does is increment the block's softdelete count and pulls the chunk out
+ * of the tnode.
+ * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
+ */
+
+static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
+ __u32 level, int chunkOffset)
+{
+ int i;
+ int theChunk;
+ int allDone = 1;
+ yaffs_Device *dev = in->myDev;
+
+ if (tn) {
+ if (level > 0) {
+
+ for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0;
+ i--) {
+ if (tn->internal[i]) {
+ allDone =
+ yaffs_SoftDeleteWorker(in,
+ tn->
+ internal[i],
+ level - 1,
+ (chunkOffset
+ <<
+ YAFFS_TNODES_INTERNAL_BITS)
+ + i);
+ if (allDone) {
+ yaffs_FreeTnode(dev,
+ tn->
+ internal[i]);
+ tn->internal[i] = NULL;
+ } else {
+ /* Hoosterman... how could this happen? */
+ }
+ }
+ }
+ return (allDone) ? 1 : 0;
+ } else if (level == 0) {
+
+ for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) {
+ theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
+ if (theChunk) {
+ /* Note this does not find the real chunk, only the chunk group.
+ * We make an assumption that a chunk group is not larger than
+ * a block.
+ */
+ yaffs_SoftDeleteChunk(dev, theChunk);
+ yaffs_PutLevel0Tnode(dev,tn,i,0);
+ }
+
+ }
+ return 1;
+
+ }
+
+ }
+
+ return 1;
+
+}
+
+static void yaffs_SoftDeleteFile(yaffs_Object * obj)
+{
+ if (obj->deleted &&
+ obj->variantType == YAFFS_OBJECT_TYPE_FILE && !obj->softDeleted) {
+ if (obj->nDataChunks <= 0) {
+ /* Empty file with no duplicate object headers, just delete it immediately */
+ yaffs_FreeTnode(obj->myDev,
+ obj->variant.fileVariant.top);
+ obj->variant.fileVariant.top = NULL;
+ T(YAFFS_TRACE_TRACING,
+ (TSTR("yaffs: Deleting empty file %d" TENDSTR),
+ obj->objectId));
+ yaffs_DoGenericObjectDeletion(obj);
+ } else {
+ yaffs_SoftDeleteWorker(obj,
+ obj->variant.fileVariant.top,
+ obj->variant.fileVariant.
+ topLevel, 0);
+ obj->softDeleted = 1;
+ }
+ }
+}
+
+/* Pruning removes any part of the file structure tree that is beyond the
+ * bounds of the file (ie that does not point to chunks).
+ *
+ * A file should only get pruned when its size is reduced.
+ *
+ * Before pruning, the chunks must be pulled from the tree and the
+ * level 0 tnode entries must be zeroed out.
+ * Could also use this for file deletion, but that's probably better handled
+ * by a special case.
+ */
+
+static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn,
+ __u32 level, int del0)
+{
+ int i;
+ int hasData;
+
+ if (tn) {
+ hasData = 0;
+
+ for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) {
+ if (tn->internal[i] && level > 0) {
+ tn->internal[i] =
+ yaffs_PruneWorker(dev, tn->internal[i],
+ level - 1,
+ (i == 0) ? del0 : 1);
+ }
+
+ if (tn->internal[i]) {
+ hasData++;
+ }
+ }
+
+ if (hasData == 0 && del0) {
+ /* Free and return NULL */
+
+ yaffs_FreeTnode(dev, tn);
+ tn = NULL;
+ }
+
+ }
+
+ return tn;
+
+}
+
+static int yaffs_PruneFileStructure(yaffs_Device * dev,
+ yaffs_FileStructure * fStruct)
+{
+ int i;
+ int hasData;
+ int done = 0;
+ yaffs_Tnode *tn;
+
+ if (fStruct->topLevel > 0) {
+ fStruct->top =
+ yaffs_PruneWorker(dev, fStruct->top, fStruct->topLevel, 0);
+
+ /* Now we have a tree with all the non-zero branches NULL but the height
+ * is the same as it was.
+ * Let's see if we can trim internal tnodes to shorten the tree.
+ * We can do this if only the 0th element in the tnode is in use
+ * (ie all the non-zero are NULL)
+ */
+
+ while (fStruct->topLevel && !done) {
+ tn = fStruct->top;
+
+ hasData = 0;
+ for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) {
+ if (tn->internal[i]) {
+ hasData++;
+ }
+ }
+
+ if (!hasData) {
+ fStruct->top = tn->internal[0];
+ fStruct->topLevel--;
+ yaffs_FreeTnode(dev, tn);
+ } else {
+ done = 1;
+ }
+ }
+ }
+
+ return YAFFS_OK;
+}
+
+/*-------------------- End of File Structure functions.-------------------*/
+
+/* yaffs_CreateFreeObjects creates a bunch more objects and
+ * adds them to the object free list.
+ */
+static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects)
+{
+ int i;
+ yaffs_Object *newObjects;
+ yaffs_ObjectList *list;
+
+ if (nObjects < 1)
+ return YAFFS_OK;
+
+ /* make these things */
+ newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
+ list = YMALLOC(sizeof(yaffs_ObjectList));
+
+ if (!newObjects || !list) {
+ if(newObjects)
+ YFREE(newObjects);
+ if(list)
+ YFREE(list);
+ T(YAFFS_TRACE_ALLOCATE,
+ (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ /* Hook them into the free list */
+ for (i = 0; i < nObjects - 1; i++) {
+ newObjects[i].siblings.next =
+ (struct list_head *)(&newObjects[i + 1]);
+ }
+
+ newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
+ dev->freeObjects = newObjects;
+ dev->nFreeObjects += nObjects;
+ dev->nObjectsCreated += nObjects;
+
+ /* Now add this bunch of Objects to a list for freeing up. */
+
+ list->objects = newObjects;
+ list->next = dev->allocatedObjectList;
+ dev->allocatedObjectList = list;
+
+ return YAFFS_OK;
+}
+
+
+/* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */
+static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
+{
+ yaffs_Object *tn = NULL;
+
+ /* If there are none left make more */
+ if (!dev->freeObjects) {
+ yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
+ }
+
+ if (dev->freeObjects) {
+ tn = dev->freeObjects;
+ dev->freeObjects =
+ (yaffs_Object *) (dev->freeObjects->siblings.next);
+ dev->nFreeObjects--;
+
+ /* Now sweeten it up... */
+
+ memset(tn, 0, sizeof(yaffs_Object));
+ tn->myDev = dev;
+ tn->chunkId = -1;
+ tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
+ INIT_LIST_HEAD(&(tn->hardLinks));
+ INIT_LIST_HEAD(&(tn->hashLink));
+ INIT_LIST_HEAD(&tn->siblings);
+
+ /* Add it to the lost and found directory.
+ * NB Can't put root or lostNFound in lostNFound so
+ * check if lostNFound exists first
+ */
+ if (dev->lostNFoundDir) {
+ yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
+ }
+ }
+
+ return tn;
+}
+
+static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device * dev, int number,
+ __u32 mode)
+{
+
+ yaffs_Object *obj =
+ yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
+ if (obj) {
+ obj->fake = 1; /* it is fake so it has no NAND presence... */
+ obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */
+ obj->unlinkAllowed = 0; /* ... or unlink it */
+ obj->deleted = 0;
+ obj->unlinked = 0;
+ obj->yst_mode = mode;
+ obj->myDev = dev;
+ obj->chunkId = 0; /* Not a valid chunk. */
+ }
+
+ return obj;
+
+}
+
+static void yaffs_UnhashObject(yaffs_Object * tn)
+{
+ int bucket;
+ yaffs_Device *dev = tn->myDev;
+
+ /* If it is still linked into the bucket list, free from the list */
+ if (!list_empty(&tn->hashLink)) {
+ list_del_init(&tn->hashLink);
+ bucket = yaffs_HashFunction(tn->objectId);
+ dev->objectBucket[bucket].count--;
+ }
+
+}
+
+/* FreeObject frees up a Object and puts it back on the free list */
+static void yaffs_FreeObject(yaffs_Object * tn)
+{
+
+ yaffs_Device *dev = tn->myDev;
+
+/* XXX U-BOOT XXX */
+#if 0
+#ifdef __KERNEL__
+ if (tn->myInode) {
+ /* We're still hooked up to a cached inode.
+ * Don't delete now, but mark for later deletion
+ */
+ tn->deferedFree = 1;
+ return;
+ }
+#endif
+#endif
+ yaffs_UnhashObject(tn);
+
+ /* Link into the free list. */
+ tn->siblings.next = (struct list_head *)(dev->freeObjects);
+ dev->freeObjects = tn;
+ dev->nFreeObjects++;
+}
+
+/* XXX U-BOOT XXX */
+#if 0
+#ifdef __KERNEL__
+
+void yaffs_HandleDeferedFree(yaffs_Object * obj)
+{
+ if (obj->deferedFree) {
+ yaffs_FreeObject(obj);
+ }
+}
+
+#endif
+#endif
+
+static void yaffs_DeinitialiseObjects(yaffs_Device * dev)
+{
+ /* Free the list of allocated Objects */
+
+ yaffs_ObjectList *tmp;
+
+ while (dev->allocatedObjectList) {
+ tmp = dev->allocatedObjectList->next;
+ YFREE(dev->allocatedObjectList->objects);
+ YFREE(dev->allocatedObjectList);
+
+ dev->allocatedObjectList = tmp;
+ }
+
+ dev->freeObjects = NULL;
+ dev->nFreeObjects = 0;
+}
+
+static void yaffs_InitialiseObjects(yaffs_Device * dev)
+{
+ int i;
+
+ dev->allocatedObjectList = NULL;
+ dev->freeObjects = NULL;
+ dev->nFreeObjects = 0;
+
+ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
+ INIT_LIST_HEAD(&dev->objectBucket[i].list);
+ dev->objectBucket[i].count = 0;
+ }
+
+}
+
+static int yaffs_FindNiceObjectBucket(yaffs_Device * dev)
+{
+ static int x = 0;
+ int i;
+ int l = 999;
+ int lowest = 999999;
+
+ /* First let's see if we can find one that's empty. */
+
+ for (i = 0; i < 10 && lowest > 0; i++) {
+ x++;
+ x %= YAFFS_NOBJECT_BUCKETS;
+ if (dev->objectBucket[x].count < lowest) {
+ lowest = dev->objectBucket[x].count;
+ l = x;
+ }
+
+ }
+
+ /* If we didn't find an empty list, then try
+ * looking a bit further for a short one
+ */
+
+ for (i = 0; i < 10 && lowest > 3; i++) {
+ x++;
+ x %= YAFFS_NOBJECT_BUCKETS;
+ if (dev->objectBucket[x].count < lowest) {
+ lowest = dev->objectBucket[x].count;
+ l = x;
+ }
+
+ }
+
+ return l;
+}
+
+static int yaffs_CreateNewObjectNumber(yaffs_Device * dev)
+{
+ int bucket = yaffs_FindNiceObjectBucket(dev);
+
+ /* Now find an object value that has not already been taken
+ * by scanning the list.
+ */
+
+ int found = 0;
+ struct list_head *i;
+
+ __u32 n = (__u32) bucket;
+
+ /* yaffs_CheckObjectHashSanity(); */
+
+ while (!found) {
+ found = 1;
+ n += YAFFS_NOBJECT_BUCKETS;
+ if (1 || dev->objectBucket[bucket].count > 0) {
+ list_for_each(i, &dev->objectBucket[bucket].list) {
+ /* If there is already one in the list */
+ if (i
+ && list_entry(i, yaffs_Object,
+ hashLink)->objectId == n) {
+ found = 0;
+ }
+ }
+ }
+ }
+
+
+ return n;
+}
+
+static void yaffs_HashObject(yaffs_Object * in)
+{
+ int bucket = yaffs_HashFunction(in->objectId);
+ yaffs_Device *dev = in->myDev;
+
+ list_add(&in->hashLink, &dev->objectBucket[bucket].list);
+ dev->objectBucket[bucket].count++;
+
+}
+
+yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
+{
+ int bucket = yaffs_HashFunction(number);
+ struct list_head *i;
+ yaffs_Object *in;
+
+ list_for_each(i, &dev->objectBucket[bucket].list) {
+ /* Look if it is in the list */
+ if (i) {
+ in = list_entry(i, yaffs_Object, hashLink);
+ if (in->objectId == number) {
+/* XXX U-BOOT XXX */
+#if 0
+#ifdef __KERNEL__
+ /* Don't tell the VFS about this one if it is defered free */
+ if (in->deferedFree)
+ return NULL;
+#endif
+#endif
+ return in;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
+ yaffs_ObjectType type)
+{
+
+ yaffs_Object *theObject;
+ yaffs_Tnode *tn;
+
+ if (number < 0) {
+ number = yaffs_CreateNewObjectNumber(dev);
+ }
+
+ theObject = yaffs_AllocateEmptyObject(dev);
+ if(!theObject)
+ return NULL;
+
+ if(type == YAFFS_OBJECT_TYPE_FILE){
+ tn = yaffs_GetTnode(dev);
+ if(!tn){
+ yaffs_FreeObject(theObject);
+ return NULL;
+ }
+ }
+
+
+
+ if (theObject) {
+ theObject->fake = 0;
+ theObject->renameAllowed = 1;
+ theObject->unlinkAllowed = 1;
+ theObject->objectId = number;
+ yaffs_HashObject(theObject);
+ theObject->variantType = type;
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_WinFileTimeNow(theObject->win_atime);
+ theObject->win_ctime[0] = theObject->win_mtime[0] =
+ theObject->win_atime[0];
+ theObject->win_ctime[1] = theObject->win_mtime[1] =
+ theObject->win_atime[1];
+
+#else
+
+ theObject->yst_atime = theObject->yst_mtime =
+ theObject->yst_ctime = Y_CURRENT_TIME;
+#endif
+ switch (type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ theObject->variant.fileVariant.fileSize = 0;
+ theObject->variant.fileVariant.scannedFileSize = 0;
+ theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */
+ theObject->variant.fileVariant.topLevel = 0;
+ theObject->variant.fileVariant.top = tn;
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ INIT_LIST_HEAD(&theObject->variant.directoryVariant.
+ children);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ /* No action required */
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* todo this should not happen */
+ break;
+ }
+ }
+
+ return theObject;
+}
+
+static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device * dev,
+ int number,
+ yaffs_ObjectType type)
+{
+ yaffs_Object *theObject = NULL;
+
+ if (number > 0) {
+ theObject = yaffs_FindObjectByNumber(dev, number);
+ }
+
+ if (!theObject) {
+ theObject = yaffs_CreateNewObject(dev, number, type);
+ }
+
+ return theObject;
+
+}
+
+
+static YCHAR *yaffs_CloneString(const YCHAR * str)
+{
+ YCHAR *newStr = NULL;
+
+ if (str && *str) {
+ newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR));
+ if(newStr)
+ yaffs_strcpy(newStr, str);
+ }
+
+ return newStr;
+
+}
+
+/*
+ * Mknod (create) a new object.
+ * equivalentObject only has meaning for a hard link;
+ * aliasString only has meaning for a sumlink.
+ * rdev only has meaning for devices (a subset of special objects)
+ */
+
+static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
+ yaffs_Object * parent,
+ const YCHAR * name,
+ __u32 mode,
+ __u32 uid,
+ __u32 gid,
+ yaffs_Object * equivalentObject,
+ const YCHAR * aliasString, __u32 rdev)
+{
+ yaffs_Object *in;
+ YCHAR *str;
+
+ yaffs_Device *dev = parent->myDev;
+
+ /* Check if the entry exists. If it does then fail the call since we don't want a dup.*/
+ if (yaffs_FindObjectByName(parent, name)) {
+ return NULL;
+ }
+
+ in = yaffs_CreateNewObject(dev, -1, type);
+
+ if(type == YAFFS_OBJECT_TYPE_SYMLINK){
+ str = yaffs_CloneString(aliasString);
+ if(!str){
+ yaffs_FreeObject(in);
+ return NULL;
+ }
+ }
+
+
+
+ if (in) {
+ in->chunkId = -1;
+ in->valid = 1;
+ in->variantType = type;
+
+ in->yst_mode = mode;
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_WinFileTimeNow(in->win_atime);
+ in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];
+ in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1];
+
+#else
+ in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME;
+
+ in->yst_rdev = rdev;
+ in->yst_uid = uid;
+ in->yst_gid = gid;
+#endif
+ in->nDataChunks = 0;
+
+ yaffs_SetObjectName(in, name);
+ in->dirty = 1;
+
+ yaffs_AddObjectToDirectory(parent, in);
+
+ in->myDev = parent->myDev;
+
+ switch (type) {
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ in->variant.symLinkVariant.alias = str;
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ in->variant.hardLinkVariant.equivalentObject =
+ equivalentObject;
+ in->variant.hardLinkVariant.equivalentObjectId =
+ equivalentObject->objectId;
+ list_add(&in->hardLinks, &equivalentObject->hardLinks);
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* do nothing */
+ break;
+ }
+
+ if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) {
+ /* Could not create the object header, fail the creation */
+ yaffs_DestroyObject(in);
+ in = NULL;
+ }
+
+ }
+
+ return in;
+}
+
+yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
+ __u32 mode, __u32 uid, __u32 gid)
+{
+ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE, parent, name, mode,
+ uid, gid, NULL, NULL, 0);
+}
+
+yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name,
+ __u32 mode, __u32 uid, __u32 gid)
+{
+ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,
+ mode, uid, gid, NULL, NULL, 0);
+}
+
+yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name,
+ __u32 mode, __u32 uid, __u32 gid, __u32 rdev)
+{
+ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,
+ uid, gid, NULL, NULL, rdev);
+}
+
+yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name,
+ __u32 mode, __u32 uid, __u32 gid,
+ const YCHAR * alias)
+{
+ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode,
+ uid, gid, NULL, alias, 0);
+}
+
+/* yaffs_Link returns the object id of the equivalent object.*/
+yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name,
+ yaffs_Object * equivalentObject)
+{
+ /* Get the real object in case we were fed a hard link as an equivalent object */
+ equivalentObject = yaffs_GetEquivalentObject(equivalentObject);
+
+ if (yaffs_MknodObject
+ (YAFFS_OBJECT_TYPE_HARDLINK, parent, name, 0, 0, 0,
+ equivalentObject, NULL, 0)) {
+ return equivalentObject;
+ } else {
+ return NULL;
+ }
+
+}
+
+static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir,
+ const YCHAR * newName, int force, int shadows)
+{
+ int unlinkOp;
+ int deleteOp;
+
+ yaffs_Object *existingTarget;
+
+ if (newDir == NULL) {
+ newDir = obj->parent; /* use the old directory */
+ }
+
+ if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"
+ TENDSTR)));
+ YBUG();
+ }
+
+ /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
+ if (obj->myDev->isYaffs2) {
+ unlinkOp = (newDir == obj->myDev->unlinkedDir);
+ } else {
+ unlinkOp = (newDir == obj->myDev->unlinkedDir
+ && obj->variantType == YAFFS_OBJECT_TYPE_FILE);
+ }
+
+ deleteOp = (newDir == obj->myDev->deletedDir);
+
+ existingTarget = yaffs_FindObjectByName(newDir, newName);
+
+ /* If the object is a file going into the unlinked directory,
+ * then it is OK to just stuff it in since duplicate names are allowed.
+ * else only proceed if the new name does not exist and if we're putting
+ * it into a directory.
+ */
+ if ((unlinkOp ||
+ deleteOp ||
+ force ||
+ (shadows > 0) ||
+ !existingTarget) &&
+ newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) {
+ yaffs_SetObjectName(obj, newName);
+ obj->dirty = 1;
+
+ yaffs_AddObjectToDirectory(newDir, obj);
+
+ if (unlinkOp)
+ obj->unlinked = 1;
+
+ /* If it is a deletion then we mark it as a shrink for gc purposes. */
+ if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows)>= 0)
+ return YAFFS_OK;
+ }
+
+ return YAFFS_FAIL;
+}
+
+int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
+ yaffs_Object * newDir, const YCHAR * newName)
+{
+ yaffs_Object *obj;
+ yaffs_Object *existingTarget;
+ int force = 0;
+
+#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
+ /* Special case for case insemsitive systems (eg. WinCE).
+ * While look-up is case insensitive, the name isn't.
+ * Therefore we might want to change x.txt to X.txt
+ */
+ if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0) {
+ force = 1;
+ }
+#endif
+
+ obj = yaffs_FindObjectByName(oldDir, oldName);
+ /* Check new name to long. */
+ if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
+ yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
+ /* ENAMETOOLONG */
+ return YAFFS_FAIL;
+ else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
+ yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
+ /* ENAMETOOLONG */
+ return YAFFS_FAIL;
+
+ if (obj && obj->renameAllowed) {
+
+ /* Now do the handling for an existing target, if there is one */
+
+ existingTarget = yaffs_FindObjectByName(newDir, newName);
+ if (existingTarget &&
+ existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
+ !list_empty(&existingTarget->variant.directoryVariant.children)) {
+ /* There is a target that is a non-empty directory, so we fail */
+ return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */
+ } else if (existingTarget && existingTarget != obj) {
+ /* Nuke the target first, using shadowing,
+ * but only if it isn't the same object
+ */
+ yaffs_ChangeObjectName(obj, newDir, newName, force,
+ existingTarget->objectId);
+ yaffs_UnlinkObject(existingTarget);
+ }
+
+ return yaffs_ChangeObjectName(obj, newDir, newName, 1, 0);
+ }
+ return YAFFS_FAIL;
+}
+
+/*------------------------- Block Management and Page Allocation ----------------*/
+
+static int yaffs_InitialiseBlocks(yaffs_Device * dev)
+{
+ int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
+
+ dev->blockInfo = NULL;
+ dev->chunkBits = NULL;
+
+ dev->allocationBlock = -1; /* force it to get a new one */
+
+ /* If the first allocation strategy fails, thry the alternate one */
+ dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo));
+ if(!dev->blockInfo){
+ dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo));
+ dev->blockInfoAlt = 1;
+ }
+ else
+ dev->blockInfoAlt = 0;
+
+ if(dev->blockInfo){
+
+ /* Set up dynamic blockinfo stuff. */
+ dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */
+ dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
+ if(!dev->chunkBits){
+ dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks);
+ dev->chunkBitsAlt = 1;
+ }
+ else
+ dev->chunkBitsAlt = 0;
+ }
+
+ if (dev->blockInfo && dev->chunkBits) {
+ memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo));
+ memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks);
+ return YAFFS_OK;
+ }
+
+ return YAFFS_FAIL;
+
+}
+
+static void yaffs_DeinitialiseBlocks(yaffs_Device * dev)
+{
+ if(dev->blockInfoAlt && dev->blockInfo)
+ YFREE_ALT(dev->blockInfo);
+ else if(dev->blockInfo)
+ YFREE(dev->blockInfo);
+
+ dev->blockInfoAlt = 0;
+
+ dev->blockInfo = NULL;
+
+ if(dev->chunkBitsAlt && dev->chunkBits)
+ YFREE_ALT(dev->chunkBits);
+ else if(dev->chunkBits)
+ YFREE(dev->chunkBits);
+ dev->chunkBitsAlt = 0;
+ dev->chunkBits = NULL;
+}
+
+static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev,
+ yaffs_BlockInfo * bi)
+{
+ int i;
+ __u32 seq;
+ yaffs_BlockInfo *b;
+
+ if (!dev->isYaffs2)
+ return 1; /* disqualification only applies to yaffs2. */
+
+ if (!bi->hasShrinkHeader)
+ return 1; /* can gc */
+
+ /* Find the oldest dirty sequence number if we don't know it and save it
+ * so we don't have to keep recomputing it.
+ */
+ if (!dev->oldestDirtySequence) {
+ seq = dev->sequenceNumber;
+
+ for (i = dev->internalStartBlock; i <= dev->internalEndBlock;
+ i++) {
+ b = yaffs_GetBlockInfo(dev, i);
+ if (b->blockState == YAFFS_BLOCK_STATE_FULL &&
+ (b->pagesInUse - b->softDeletions) <
+ dev->nChunksPerBlock && b->sequenceNumber < seq) {
+ seq = b->sequenceNumber;
+ }
+ }
+ dev->oldestDirtySequence = seq;
+ }
+
+ /* Can't do gc of this block if there are any blocks older than this one that have
+ * discarded pages.
+ */
+ return (bi->sequenceNumber <= dev->oldestDirtySequence);
+
+}
+
+/* FindDiretiestBlock is used to select the dirtiest block (or close enough)
+ * for garbage collection.
+ */
+
+static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev,
+ int aggressive)
+{
+
+ int b = dev->currentDirtyChecker;
+
+ int i;
+ int iterations;
+ int dirtiest = -1;
+ int pagesInUse = 0;
+ int prioritised=0;
+ yaffs_BlockInfo *bi;
+ int pendingPrioritisedExist = 0;
+
+ /* First let's see if we need to grab a prioritised block */
+ if(dev->hasPendingPrioritisedGCs){
+ for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
+
+ bi = yaffs_GetBlockInfo(dev, i);
+ //yaffs_VerifyBlock(dev,bi,i);
+
+ if(bi->gcPrioritise) {
+ pendingPrioritisedExist = 1;
+ if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
+ yaffs_BlockNotDisqualifiedFromGC(dev, bi)){
+ pagesInUse = (bi->pagesInUse - bi->softDeletions);
+ dirtiest = i;
+ prioritised = 1;
+ aggressive = 1; /* Fool the non-aggressive skip logiv below */
+ }
+ }
+ }
+
+ if(!pendingPrioritisedExist) /* None found, so we can clear this */
+ dev->hasPendingPrioritisedGCs = 0;
+ }
+
+ /* If we're doing aggressive GC then we are happy to take a less-dirty block, and
+ * search harder.
+ * else (we're doing a leasurely gc), then we only bother to do this if the
+ * block has only a few pages in use.
+ */
+
+ dev->nonAggressiveSkip--;
+
+ if (!aggressive && (dev->nonAggressiveSkip > 0)) {
+ return -1;
+ }
+
+ if(!prioritised)
+ pagesInUse =
+ (aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1;
+
+ if (aggressive) {
+ iterations =
+ dev->internalEndBlock - dev->internalStartBlock + 1;
+ } else {
+ iterations =
+ dev->internalEndBlock - dev->internalStartBlock + 1;
+ iterations = iterations / 16;
+ if (iterations > 200) {
+ iterations = 200;
+ }
+ }
+
+ for (i = 0; i <= iterations && pagesInUse > 0 && !prioritised; i++) {
+ b++;
+ if (b < dev->internalStartBlock || b > dev->internalEndBlock) {
+ b = dev->internalStartBlock;
+ }
+
+ if (b < dev->internalStartBlock || b > dev->internalEndBlock) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("**>> Block %d is not valid" TENDSTR), b));
+ YBUG();
+ }
+
+ bi = yaffs_GetBlockInfo(dev, b);
+
+#if 0
+ if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) {
+ dirtiest = b;
+ pagesInUse = 0;
+ }
+ else
+#endif
+
+ if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
+ (bi->pagesInUse - bi->softDeletions) < pagesInUse &&
+ yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {
+ dirtiest = b;
+ pagesInUse = (bi->pagesInUse - bi->softDeletions);
+ }
+ }
+
+ dev->currentDirtyChecker = b;
+
+ if (dirtiest > 0) {
+ T(YAFFS_TRACE_GC,
+ (TSTR("GC Selected block %d with %d free, prioritised:%d" TENDSTR), dirtiest,
+ dev->nChunksPerBlock - pagesInUse,prioritised));
+ }
+
+ dev->oldestDirtySequence = 0;
+
+ if (dirtiest > 0) {
+ dev->nonAggressiveSkip = 4;
+ }
+
+ return dirtiest;
+}
+
+static void yaffs_BlockBecameDirty(yaffs_Device * dev, int blockNo)
+{
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockNo);
+
+ int erasedOk = 0;
+
+ /* If the block is still healthy erase it and mark as clean.
+ * If the block has had a data failure, then retire it.
+ */
+
+ T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
+ (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
+ blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
+
+ bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
+
+ if (!bi->needsRetiring) {
+ yaffs_InvalidateCheckpoint(dev);
+ erasedOk = yaffs_EraseBlockInNAND(dev, blockNo);
+ if (!erasedOk) {
+ dev->nErasureFailures++;
+ T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ (TSTR("**>> Erasure failed %d" TENDSTR), blockNo));
+ }
+ }
+
+ if (erasedOk &&
+ ((yaffs_traceMask & YAFFS_TRACE_ERASE) || !yaffs_SkipVerification(dev))) {
+ int i;
+ for (i = 0; i < dev->nChunksPerBlock; i++) {
+ if (!yaffs_CheckChunkErased
+ (dev, blockNo * dev->nChunksPerBlock + i)) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ (">>Block %d erasure supposedly OK, but chunk %d not erased"
+ TENDSTR), blockNo, i));
+ }
+ }
+ }
+
+ if (erasedOk) {
+ /* Clean it up... */
+ bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
+ dev->nErasedBlocks++;
+ bi->pagesInUse = 0;
+ bi->softDeletions = 0;
+ bi->hasShrinkHeader = 0;
+ bi->skipErasedCheck = 1; /* This is clean, so no need to check */
+ bi->gcPrioritise = 0;
+ yaffs_ClearChunkBits(dev, blockNo);
+
+ T(YAFFS_TRACE_ERASE,
+ (TSTR("Erased block %d" TENDSTR), blockNo));
+ } else {
+ dev->nFreeChunks -= dev->nChunksPerBlock; /* We lost a block of free space */
+
+ yaffs_RetireBlock(dev, blockNo);
+ T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ (TSTR("**>> Block %d retired" TENDSTR), blockNo));
+ }
+}
+
+static int yaffs_FindBlockForAllocation(yaffs_Device * dev)
+{
+ int i;
+
+ yaffs_BlockInfo *bi;
+
+ if (dev->nErasedBlocks < 1) {
+ /* Hoosterman we've got a problem.
+ * Can't get space to gc
+ */
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
+
+ return -1;
+ }
+
+ /* Find an empty block. */
+
+ for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
+ dev->allocationBlockFinder++;
+ if (dev->allocationBlockFinder < dev->internalStartBlock
+ || dev->allocationBlockFinder > dev->internalEndBlock) {
+ dev->allocationBlockFinder = dev->internalStartBlock;
+ }
+
+ bi = yaffs_GetBlockInfo(dev, dev->allocationBlockFinder);
+
+ if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) {
+ bi->blockState = YAFFS_BLOCK_STATE_ALLOCATING;
+ dev->sequenceNumber++;
+ bi->sequenceNumber = dev->sequenceNumber;
+ dev->nErasedBlocks--;
+ T(YAFFS_TRACE_ALLOCATE,
+ (TSTR("Allocated block %d, seq %d, %d left" TENDSTR),
+ dev->allocationBlockFinder, dev->sequenceNumber,
+ dev->nErasedBlocks));
+ return dev->allocationBlockFinder;
+ }
+ }
+
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("yaffs tragedy: no more eraased blocks, but there should have been %d"
+ TENDSTR), dev->nErasedBlocks));
+
+ return -1;
+}
+
+
+// Check if there's space to allocate...
+// Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?
+static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
+{
+ int reservedChunks;
+ int reservedBlocks = dev->nReservedBlocks;
+ int checkpointBlocks;
+
+ checkpointBlocks = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
+ if(checkpointBlocks < 0)
+ checkpointBlocks = 0;
+
+ reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
+
+ return (dev->nFreeChunks > reservedChunks);
+}
+
+static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr)
+{
+ int retVal;
+ yaffs_BlockInfo *bi;
+
+ if (dev->allocationBlock < 0) {
+ /* Get next block to allocate off */
+ dev->allocationBlock = yaffs_FindBlockForAllocation(dev);
+ dev->allocationPage = 0;
+ }
+
+ if (!useReserve && !yaffs_CheckSpaceForAllocation(dev)) {
+ /* Not enough space to allocate unless we're allowed to use the reserve. */
+ return -1;
+ }
+
+ if (dev->nErasedBlocks < dev->nReservedBlocks
+ && dev->allocationPage == 0) {
+ T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocating reserve" TENDSTR)));
+ }
+
+ /* Next page please.... */
+ if (dev->allocationBlock >= 0) {
+ bi = yaffs_GetBlockInfo(dev, dev->allocationBlock);
+
+ retVal = (dev->allocationBlock * dev->nChunksPerBlock) +
+ dev->allocationPage;
+ bi->pagesInUse++;
+ yaffs_SetChunkBit(dev, dev->allocationBlock,
+ dev->allocationPage);
+
+ dev->allocationPage++;
+
+ dev->nFreeChunks--;
+
+ /* If the block is full set the state to full */
+ if (dev->allocationPage >= dev->nChunksPerBlock) {
+ bi->blockState = YAFFS_BLOCK_STATE_FULL;
+ dev->allocationBlock = -1;
+ }
+
+ if(blockUsedPtr)
+ *blockUsedPtr = bi;
+
+ return retVal;
+ }
+
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
+
+ return -1;
+}
+
+static int yaffs_GetErasedChunks(yaffs_Device * dev)
+{
+ int n;
+
+ n = dev->nErasedBlocks * dev->nChunksPerBlock;
+
+ if (dev->allocationBlock > 0) {
+ n += (dev->nChunksPerBlock - dev->allocationPage);
+ }
+
+ return n;
+
+}
+
+static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
+{
+ int oldChunk;
+ int newChunk;
+ int chunkInBlock;
+ int markNAND;
+ int retVal = YAFFS_OK;
+ int cleanups = 0;
+ int i;
+ int isCheckpointBlock;
+ int matchingChunk;
+
+ int chunksBefore = yaffs_GetErasedChunks(dev);
+ int chunksAfter;
+
+ yaffs_ExtendedTags tags;
+
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, block);
+
+ yaffs_Object *object;
+
+ isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);
+
+ bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;
+
+ T(YAFFS_TRACE_TRACING,
+ (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,
+ bi->pagesInUse, bi->hasShrinkHeader));
+
+ /*yaffs_VerifyFreeChunks(dev); */
+
+ bi->hasShrinkHeader = 0; /* clear the flag so that the block can erase */
+
+ /* Take off the number of soft deleted entries because
+ * they're going to get really deleted during GC.
+ */
+ dev->nFreeChunks -= bi->softDeletions;
+
+ dev->isDoingGC = 1;
+
+ if (isCheckpointBlock ||
+ !yaffs_StillSomeChunkBits(dev, block)) {
+ T(YAFFS_TRACE_TRACING,
+ (TSTR
+ ("Collecting block %d that has no chunks in use" TENDSTR),
+ block));
+ yaffs_BlockBecameDirty(dev, block);
+ } else {
+
+ __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
+
+ yaffs_VerifyBlock(dev,bi,block);
+
+ for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock;
+ chunkInBlock < dev->nChunksPerBlock
+ && yaffs_StillSomeChunkBits(dev, block);
+ chunkInBlock++, oldChunk++) {
+ if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) {
+
+ /* This page is in use and might need to be copied off */
+
+ markNAND = 1;
+
+ yaffs_InitialiseTags(&tags);
+
+ yaffs_ReadChunkWithTagsFromNAND(dev, oldChunk,
+ buffer, &tags);
+
+ object =
+ yaffs_FindObjectByNumber(dev,
+ tags.objectId);
+
+ T(YAFFS_TRACE_GC_DETAIL,
+ (TSTR
+ ("Collecting page %d, %d %d %d " TENDSTR),
+ chunkInBlock, tags.objectId, tags.chunkId,
+ tags.byteCount));
+
+ if(object && !yaffs_SkipVerification(dev)){
+ if(tags.chunkId == 0)
+ matchingChunk = object->chunkId;
+ else if(object->softDeleted)
+ matchingChunk = oldChunk; /* Defeat the test */
+ else
+ matchingChunk = yaffs_FindChunkInFile(object,tags.chunkId,NULL);
+
+ if(oldChunk != matchingChunk)
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("gc: page in gc mismatch: %d %d %d %d"TENDSTR),
+ oldChunk,matchingChunk,tags.objectId, tags.chunkId));
+
+ }
+
+ if (!object) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("page %d in gc has no object: %d %d %d "
+ TENDSTR), oldChunk,
+ tags.objectId, tags.chunkId, tags.byteCount));
+ }
+
+ if (object && object->deleted
+ && tags.chunkId != 0) {
+ /* Data chunk in a deleted file, throw it away
+ * It's a soft deleted data chunk,
+ * No need to copy this, just forget about it and
+ * fix up the object.
+ */
+
+ object->nDataChunks--;
+
+ if (object->nDataChunks <= 0) {
+ /* remeber to clean up the object */
+ dev->gcCleanupList[cleanups] =
+ tags.objectId;
+ cleanups++;
+ }
+ markNAND = 0;
+ } else if (0
+ /* Todo object && object->deleted && object->nDataChunks == 0 */
+ ) {
+ /* Deleted object header with no data chunks.
+ * Can be discarded and the file deleted.
+ */
+ object->chunkId = 0;
+ yaffs_FreeTnode(object->myDev,
+ object->variant.
+ fileVariant.top);
+ object->variant.fileVariant.top = NULL;
+ yaffs_DoGenericObjectDeletion(object);
+
+ } else if (object) {
+ /* It's either a data chunk in a live file or
+ * an ObjectHeader, so we're interested in it.
+ * NB Need to keep the ObjectHeaders of deleted files
+ * until the whole file has been deleted off
+ */
+ tags.serialNumber++;
+
+ dev->nGCCopies++;
+
+ if (tags.chunkId == 0) {
+ /* It is an object Id,
+ * We need to nuke the shrinkheader flags first
+ * We no longer want the shrinkHeader flag since its work is done
+ * and if it is left in place it will mess up scanning.
+ * Also, clear out any shadowing stuff
+ */
+
+ yaffs_ObjectHeader *oh;
+ oh = (yaffs_ObjectHeader *)buffer;
+ oh->isShrink = 0;
+ oh->shadowsObject = -1;
+ tags.extraShadows = 0;
+ tags.extraIsShrinkHeader = 0;
+
+ yaffs_VerifyObjectHeader(object,oh,&tags,1);
+ }
+
+ newChunk =
+ yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &tags, 1);
+
+ if (newChunk < 0) {
+ retVal = YAFFS_FAIL;
+ } else {
+
+ /* Ok, now fix up the Tnodes etc. */
+
+ if (tags.chunkId == 0) {
+ /* It's a header */
+ object->chunkId = newChunk;
+ object->serial = tags.serialNumber;
+ } else {
+ /* It's a data chunk */
+ yaffs_PutChunkIntoFile
+ (object,
+ tags.chunkId,
+ newChunk, 0);
+ }
+ }
+ }
+
+ yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
+
+ }
+ }
+
+ yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
+
+
+ /* Do any required cleanups */
+ for (i = 0; i < cleanups; i++) {
+ /* Time to delete the file too */
+ object =
+ yaffs_FindObjectByNumber(dev,
+ dev->gcCleanupList[i]);
+ if (object) {
+ yaffs_FreeTnode(dev,
+ object->variant.fileVariant.
+ top);
+ object->variant.fileVariant.top = NULL;
+ T(YAFFS_TRACE_GC,
+ (TSTR
+ ("yaffs: About to finally delete object %d"
+ TENDSTR), object->objectId));
+ yaffs_DoGenericObjectDeletion(object);
+ object->myDev->nDeletedFiles--;
+ }
+
+ }
+
+ }
+
+ yaffs_VerifyCollectedBlock(dev,bi,block);
+
+ if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) {
+ T(YAFFS_TRACE_GC,
+ (TSTR
+ ("gc did not increase free chunks before %d after %d"
+ TENDSTR), chunksBefore, chunksAfter));
+ }
+
+ dev->isDoingGC = 0;
+
+ return YAFFS_OK;
+}
+
+/* New garbage collector
+ * If we're very low on erased blocks then we do aggressive garbage collection
+ * otherwise we do "leasurely" garbage collection.
+ * Aggressive gc looks further (whole array) and will accept less dirty blocks.
+ * Passive gc only inspects smaller areas and will only accept more dirty blocks.
+ *
+ * The idea is to help clear out space in a more spread-out manner.
+ * Dunno if it really does anything useful.
+ */
+static int yaffs_CheckGarbageCollection(yaffs_Device * dev)
+{
+ int block;
+ int aggressive;
+ int gcOk = YAFFS_OK;
+ int maxTries = 0;
+
+ int checkpointBlockAdjust;
+
+ if (dev->isDoingGC) {
+ /* Bail out so we don't get recursive gc */
+ return YAFFS_OK;
+ }
+
+ /* This loop should pass the first time.
+ * We'll only see looping here if the erase of the collected block fails.
+ */
+
+ do {
+ maxTries++;
+
+ checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
+ if(checkpointBlockAdjust < 0)
+ checkpointBlockAdjust = 0;
+
+ if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust + 2)) {
+ /* We need a block soon...*/
+ aggressive = 1;
+ } else {
+ /* We're in no hurry */
+ aggressive = 0;
+ }
+
+ block = yaffs_FindBlockForGarbageCollection(dev, aggressive);
+
+ if (block > 0) {
+ dev->garbageCollections++;
+ if (!aggressive) {
+ dev->passiveGarbageCollections++;
+ }
+
+ T(YAFFS_TRACE_GC,
+ (TSTR
+ ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
+ dev->nErasedBlocks, aggressive));
+
+ gcOk = yaffs_GarbageCollectBlock(dev, block);
+ }
+
+ if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {
+ T(YAFFS_TRACE_GC,
+ (TSTR
+ ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
+ TENDSTR), dev->nErasedBlocks, maxTries, block));
+ }
+ } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)
+ && (maxTries < 2));
+
+ return aggressive ? gcOk : YAFFS_OK;
+}
+
+/*------------------------- TAGS --------------------------------*/
+
+static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId,
+ int chunkInObject)
+{
+ return (tags->chunkId == chunkInObject &&
+ tags->objectId == objectId && !tags->chunkDeleted) ? 1 : 0;
+
+}
+
+
+/*-------------------- Data file manipulation -----------------*/
+
+static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode,
+ yaffs_ExtendedTags * tags)
+{
+ /*Get the Tnode, then get the level 0 offset chunk offset */
+ yaffs_Tnode *tn;
+ int theChunk = -1;
+ yaffs_ExtendedTags localTags;
+ int retVal = -1;
+
+ yaffs_Device *dev = in->myDev;
+
+ if (!tags) {
+ /* Passed a NULL, so use our own tags space */
+ tags = &localTags;
+ }
+
+ tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
+
+ if (tn) {
+ theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
+
+ retVal =
+ yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
+ chunkInInode);
+ }
+ return retVal;
+}
+
+static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode,
+ yaffs_ExtendedTags * tags)
+{
+ /* Get the Tnode, then get the level 0 offset chunk offset */
+ yaffs_Tnode *tn;
+ int theChunk = -1;
+ yaffs_ExtendedTags localTags;
+
+ yaffs_Device *dev = in->myDev;
+ int retVal = -1;
+
+ if (!tags) {
+ /* Passed a NULL, so use our own tags space */
+ tags = &localTags;
+ }
+
+ tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
+
+ if (tn) {
+
+ theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
+
+ retVal =
+ yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
+ chunkInInode);
+
+ /* Delete the entry in the filestructure (if found) */
+ if (retVal != -1) {
+ yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0);
+ }
+ } else {
+ /*T(("No level 0 found for %d\n", chunkInInode)); */
+ }
+
+ if (retVal == -1) {
+ /* T(("Could not find %d to delete\n",chunkInInode)); */
+ }
+ return retVal;
+}
+
+#ifdef YAFFS_PARANOID
+
+static int yaffs_CheckFileSanity(yaffs_Object * in)
+{
+ int chunk;
+ int nChunks;
+ int fSize;
+ int failed = 0;
+ int objId;
+ yaffs_Tnode *tn;
+ yaffs_Tags localTags;
+ yaffs_Tags *tags = &localTags;
+ int theChunk;
+ int chunkDeleted;
+
+ if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
+ /* T(("Object not a file\n")); */
+ return YAFFS_FAIL;
+ }
+
+ objId = in->objectId;
+ fSize = in->variant.fileVariant.fileSize;
+ nChunks =
+ (fSize + in->myDev->nDataBytesPerChunk - 1) / in->myDev->nDataBytesPerChunk;
+
+ for (chunk = 1; chunk <= nChunks; chunk++) {
+ tn = yaffs_FindLevel0Tnode(in->myDev, &in->variant.fileVariant,
+ chunk);
+
+ if (tn) {
+
+ theChunk = yaffs_GetChunkGroupBase(dev,tn,chunk);
+
+ if (yaffs_CheckChunkBits
+ (dev, theChunk / dev->nChunksPerBlock,
+ theChunk % dev->nChunksPerBlock)) {
+
+ yaffs_ReadChunkTagsFromNAND(in->myDev, theChunk,
+ tags,
+ &chunkDeleted);
+ if (yaffs_TagsMatch
+ (tags, in->objectId, chunk, chunkDeleted)) {
+ /* found it; */
+
+ }
+ } else {
+
+ failed = 1;
+ }
+
+ } else {
+ /* T(("No level 0 found for %d\n", chunk)); */
+ }
+ }
+
+ return failed ? YAFFS_FAIL : YAFFS_OK;
+}
+
+#endif
+
+static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
+ int chunkInNAND, int inScan)
+{
+ /* NB inScan is zero unless scanning.
+ * For forward scanning, inScan is > 0;
+ * for backward scanning inScan is < 0
+ */
+
+ yaffs_Tnode *tn;
+ yaffs_Device *dev = in->myDev;
+ int existingChunk;
+ yaffs_ExtendedTags existingTags;
+ yaffs_ExtendedTags newTags;
+ unsigned existingSerial, newSerial;
+
+ if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
+ /* Just ignore an attempt at putting a chunk into a non-file during scanning
+ * If it is not during Scanning then something went wrong!
+ */
+ if (!inScan) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("yaffs tragedy:attempt to put data chunk into a non-file"
+ TENDSTR)));
+ YBUG();
+ }
+
+ yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
+ return YAFFS_OK;
+ }
+
+ tn = yaffs_AddOrFindLevel0Tnode(dev,
+ &in->variant.fileVariant,
+ chunkInInode,
+ NULL);
+ if (!tn) {
+ return YAFFS_FAIL;
+ }
+
+ existingChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
+
+ if (inScan != 0) {
+ /* If we're scanning then we need to test for duplicates
+ * NB This does not need to be efficient since it should only ever
+ * happen when the power fails during a write, then only one
+ * chunk should ever be affected.
+ *
+ * Correction for YAFFS2: This could happen quite a lot and we need to think about efficiency! TODO
+ * Update: For backward scanning we don't need to re-read tags so this is quite cheap.
+ */
+
+ if (existingChunk != 0) {
+ /* NB Right now existing chunk will not be real chunkId if the device >= 32MB
+ * thus we have to do a FindChunkInFile to get the real chunk id.
+ *
+ * We have a duplicate now we need to decide which one to use:
+ *
+ * Backwards scanning YAFFS2: The old one is what we use, dump the new one.
+ * Forward scanning YAFFS2: The new one is what we use, dump the old one.
+ * YAFFS1: Get both sets of tags and compare serial numbers.
+ */
+
+ if (inScan > 0) {
+ /* Only do this for forward scanning */
+ yaffs_ReadChunkWithTagsFromNAND(dev,
+ chunkInNAND,
+ NULL, &newTags);
+
+ /* Do a proper find */
+ existingChunk =
+ yaffs_FindChunkInFile(in, chunkInInode,
+ &existingTags);
+ }
+
+ if (existingChunk <= 0) {
+ /*Hoosterman - how did this happen? */
+
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("yaffs tragedy: existing chunk < 0 in scan"
+ TENDSTR)));
+
+ }
+
+ /* NB The deleted flags should be false, otherwise the chunks will
+ * not be loaded during a scan
+ */
+
+ newSerial = newTags.serialNumber;
+ existingSerial = existingTags.serialNumber;
+
+ if ((inScan > 0) &&
+ (in->myDev->isYaffs2 ||
+ existingChunk <= 0 ||
+ ((existingSerial + 1) & 3) == newSerial)) {
+ /* Forward scanning.
+ * Use new
+ * Delete the old one and drop through to update the tnode
+ */
+ yaffs_DeleteChunk(dev, existingChunk, 1,
+ __LINE__);
+ } else {
+ /* Backward scanning or we want to use the existing one
+ * Use existing.
+ * Delete the new one and return early so that the tnode isn't changed
+ */
+ yaffs_DeleteChunk(dev, chunkInNAND, 1,
+ __LINE__);
+ return YAFFS_OK;
+ }
+ }
+
+ }
+
+ if (existingChunk == 0) {
+ in->nDataChunks++;
+ }
+
+ yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND);
+
+ return YAFFS_OK;
+}
+
+static int yaffs_ReadChunkDataFromObject(yaffs_Object * in, int chunkInInode,
+ __u8 * buffer)
+{
+ int chunkInNAND = yaffs_FindChunkInFile(in, chunkInInode, NULL);
+
+ if (chunkInNAND >= 0) {
+ return yaffs_ReadChunkWithTagsFromNAND(in->myDev, chunkInNAND,
+ buffer,NULL);
+ } else {
+ T(YAFFS_TRACE_NANDACCESS,
+ (TSTR("Chunk %d not found zero instead" TENDSTR),
+ chunkInNAND));
+ /* get sane (zero) data if you read a hole */
+ memset(buffer, 0, in->myDev->nDataBytesPerChunk);
+ return 0;
+ }
+
+}
+
+void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn)
+{
+ int block;
+ int page;
+ yaffs_ExtendedTags tags;
+ yaffs_BlockInfo *bi;
+
+ if (chunkId <= 0)
+ return;
+
+
+ dev->nDeletions++;
+ block = chunkId / dev->nChunksPerBlock;
+ page = chunkId % dev->nChunksPerBlock;
+
+
+ if(!yaffs_CheckChunkBit(dev,block,page))
+ T(YAFFS_TRACE_VERIFY,
+ (TSTR("Deleting invalid chunk %d"TENDSTR),
+ chunkId));
+
+ bi = yaffs_GetBlockInfo(dev, block);
+
+ T(YAFFS_TRACE_DELETION,
+ (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId));
+
+ if (markNAND &&
+ bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->isYaffs2) {
+
+ yaffs_InitialiseTags(&tags);
+
+ tags.chunkDeleted = 1;
+
+ yaffs_WriteChunkWithTagsToNAND(dev, chunkId, NULL, &tags);
+ yaffs_HandleUpdateChunk(dev, chunkId, &tags);
+ } else {
+ dev->nUnmarkedDeletions++;
+ }
+
+ /* Pull out of the management area.
+ * If the whole block became dirty, this will kick off an erasure.
+ */
+ if (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING ||
+ bi->blockState == YAFFS_BLOCK_STATE_FULL ||
+ bi->blockState == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
+ bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) {
+ dev->nFreeChunks++;
+
+ yaffs_ClearChunkBit(dev, block, page);
+
+ bi->pagesInUse--;
+
+ if (bi->pagesInUse == 0 &&
+ !bi->hasShrinkHeader &&
+ bi->blockState != YAFFS_BLOCK_STATE_ALLOCATING &&
+ bi->blockState != YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
+ yaffs_BlockBecameDirty(dev, block);
+ }
+
+ } else {
+ /* T(("Bad news deleting chunk %d\n",chunkId)); */
+ }
+
+}
+
+static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode,
+ const __u8 * buffer, int nBytes,
+ int useReserve)
+{
+ /* Find old chunk Need to do this to get serial number
+ * Write new one and patch into tree.
+ * Invalidate old tags.
+ */
+
+ int prevChunkId;
+ yaffs_ExtendedTags prevTags;
+
+ int newChunkId;
+ yaffs_ExtendedTags newTags;
+
+ yaffs_Device *dev = in->myDev;
+
+ yaffs_CheckGarbageCollection(dev);
+
+ /* Get the previous chunk at this location in the file if it exists */
+ prevChunkId = yaffs_FindChunkInFile(in, chunkInInode, &prevTags);
+
+ /* Set up new tags */
+ yaffs_InitialiseTags(&newTags);
+
+ newTags.chunkId = chunkInInode;
+ newTags.objectId = in->objectId;
+ newTags.serialNumber =
+ (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
+ newTags.byteCount = nBytes;
+
+ newChunkId =
+ yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
+ useReserve);
+
+ if (newChunkId >= 0) {
+ yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0);
+
+ if (prevChunkId >= 0) {
+ yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__);
+
+ }
+
+ yaffs_CheckFileSanity(in);
+ }
+ return newChunkId;
+
+}
+
+/* UpdateObjectHeader updates the header on NAND for an object.
+ * If name is not NULL, then that new name is used.
+ */
+int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,
+ int isShrink, int shadows)
+{
+
+ yaffs_BlockInfo *bi;
+
+ yaffs_Device *dev = in->myDev;
+
+ int prevChunkId;
+ int retVal = 0;
+ int result = 0;
+
+ int newChunkId;
+ yaffs_ExtendedTags newTags;
+ yaffs_ExtendedTags oldTags;
+
+ __u8 *buffer = NULL;
+ YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1];
+
+ yaffs_ObjectHeader *oh = NULL;
+
+ yaffs_strcpy(oldName,"silly old name");
+
+ if (!in->fake || force) {
+
+ yaffs_CheckGarbageCollection(dev);
+ yaffs_CheckObjectDetailsLoaded(in);
+
+ buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);
+ oh = (yaffs_ObjectHeader *) buffer;
+
+ prevChunkId = in->chunkId;
+
+ if (prevChunkId >= 0) {
+ result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,
+ buffer, &oldTags);
+
+ yaffs_VerifyObjectHeader(in,oh,&oldTags,0);
+
+ memcpy(oldName, oh->name, sizeof(oh->name));
+ }
+
+ memset(buffer, 0xFF, dev->nDataBytesPerChunk);
+
+ oh->type = in->variantType;
+ oh->yst_mode = in->yst_mode;
+ oh->shadowsObject = shadows;
+
+#ifdef CONFIG_YAFFS_WINCE
+ oh->win_atime[0] = in->win_atime[0];
+ oh->win_ctime[0] = in->win_ctime[0];
+ oh->win_mtime[0] = in->win_mtime[0];
+ oh->win_atime[1] = in->win_atime[1];
+ oh->win_ctime[1] = in->win_ctime[1];
+ oh->win_mtime[1] = in->win_mtime[1];
+#else
+ oh->yst_uid = in->yst_uid;
+ oh->yst_gid = in->yst_gid;
+ oh->yst_atime = in->yst_atime;
+ oh->yst_mtime = in->yst_mtime;
+ oh->yst_ctime = in->yst_ctime;
+ oh->yst_rdev = in->yst_rdev;
+#endif
+ if (in->parent) {
+ oh->parentObjectId = in->parent->objectId;
+ } else {
+ oh->parentObjectId = 0;
+ }
+
+ if (name && *name) {
+ memset(oh->name, 0, sizeof(oh->name));
+ yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH);
+ } else if (prevChunkId>=0) {
+ memcpy(oh->name, oldName, sizeof(oh->name));
+ } else {
+ memset(oh->name, 0, sizeof(oh->name));
+ }
+
+ oh->isShrink = isShrink;
+
+ switch (in->variantType) {
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* Should not happen */
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+ oh->fileSize =
+ (oh->parentObjectId == YAFFS_OBJECTID_DELETED
+ || oh->parentObjectId ==
+ YAFFS_OBJECTID_UNLINKED) ? 0 : in->variant.
+ fileVariant.fileSize;
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ oh->equivalentObjectId =
+ in->variant.hardLinkVariant.equivalentObjectId;
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ yaffs_strncpy(oh->alias,
+ in->variant.symLinkVariant.alias,
+ YAFFS_MAX_ALIAS_LENGTH);
+ oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
+ break;
+ }
+
+ /* Tags */
+ yaffs_InitialiseTags(&newTags);
+ in->serial++;
+ newTags.chunkId = 0;
+ newTags.objectId = in->objectId;
+ newTags.serialNumber = in->serial;
+
+ /* Add extra info for file header */
+
+ newTags.extraHeaderInfoAvailable = 1;
+ newTags.extraParentObjectId = oh->parentObjectId;
+ newTags.extraFileLength = oh->fileSize;
+ newTags.extraIsShrinkHeader = oh->isShrink;
+ newTags.extraEquivalentObjectId = oh->equivalentObjectId;
+ newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0;
+ newTags.extraObjectType = in->variantType;
+
+ yaffs_VerifyObjectHeader(in,oh,&newTags,1);
+
+ /* Create new chunk in NAND */
+ newChunkId =
+ yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
+ (prevChunkId >= 0) ? 1 : 0);
+
+ if (newChunkId >= 0) {
+
+ in->chunkId = newChunkId;
+
+ if (prevChunkId >= 0) {
+ yaffs_DeleteChunk(dev, prevChunkId, 1,
+ __LINE__);
+ }
+
+ if(!yaffs_ObjectHasCachedWriteData(in))
+ in->dirty = 0;
+
+ /* If this was a shrink, then mark the block that the chunk lives on */
+ if (isShrink) {
+ bi = yaffs_GetBlockInfo(in->myDev,
+ newChunkId /in->myDev-> nChunksPerBlock);
+ bi->hasShrinkHeader = 1;
+ }
+
+ }
+
+ retVal = newChunkId;
+
+ }
+
+ if (buffer)
+ yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
+
+ return retVal;
+}
+
+/*------------------------ Short Operations Cache ----------------------------------------
+ * In many situations where there is no high level buffering (eg WinCE) a lot of
+ * reads might be short sequential reads, and a lot of writes may be short
+ * sequential writes. eg. scanning/writing a jpeg file.
+ * In these cases, a short read/write cache can provide a huge perfomance benefit
+ * with dumb-as-a-rock code.
+ * In Linux, the page cache provides read buffering aand the short op cache provides write
+ * buffering.
+ *
+ * There are a limited number (~10) of cache chunks per device so that we don't
+ * need a very intelligent search.
+ */
+
+static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj)
+{
+ yaffs_Device *dev = obj->myDev;
+ int i;
+ yaffs_ChunkCache *cache;
+ int nCaches = obj->myDev->nShortOpCaches;
+
+ for(i = 0; i < nCaches; i++){
+ cache = &dev->srCache[i];
+ if (cache->object == obj &&
+ cache->dirty)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static void yaffs_FlushFilesChunkCache(yaffs_Object * obj)
+{
+ yaffs_Device *dev = obj->myDev;
+ int lowest = -99; /* Stop compiler whining. */
+ int i;
+ yaffs_ChunkCache *cache;
+ int chunkWritten = 0;
+ int nCaches = obj->myDev->nShortOpCaches;
+
+ if (nCaches > 0) {
+ do {
+ cache = NULL;
+
+ /* Find the dirty cache for this object with the lowest chunk id. */
+ for (i = 0; i < nCaches; i++) {
+ if (dev->srCache[i].object == obj &&
+ dev->srCache[i].dirty) {
+ if (!cache
+ || dev->srCache[i].chunkId <
+ lowest) {
+ cache = &dev->srCache[i];
+ lowest = cache->chunkId;
+ }
+ }
+ }
+
+ if (cache && !cache->locked) {
+ /* Write it out and free it up */
+
+ chunkWritten =
+ yaffs_WriteChunkDataToObject(cache->object,
+ cache->chunkId,
+ cache->data,
+ cache->nBytes,
+ 1);
+ cache->dirty = 0;
+ cache->object = NULL;
+ }
+
+ } while (cache && chunkWritten > 0);
+
+ if (cache) {
+ /* Hoosterman, disk full while writing cache out. */
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("yaffs tragedy: no space during cache write" TENDSTR)));
+
+ }
+ }
+
+}
+
+/*yaffs_FlushEntireDeviceCache(dev)
+ *
+ *
+ */
+
+void yaffs_FlushEntireDeviceCache(yaffs_Device *dev)
+{
+ yaffs_Object *obj;
+ int nCaches = dev->nShortOpCaches;
+ int i;
+
+ /* Find a dirty object in the cache and flush it...
+ * until there are no further dirty objects.
+ */
+ do {
+ obj = NULL;
+ for( i = 0; i < nCaches && !obj; i++) {
+ if (dev->srCache[i].object &&
+ dev->srCache[i].dirty)
+ obj = dev->srCache[i].object;
+
+ }
+ if(obj)
+ yaffs_FlushFilesChunkCache(obj);
+
+ } while(obj);
+
+}
+
+
+/* Grab us a cache chunk for use.
+ * First look for an empty one.
+ * Then look for the least recently used non-dirty one.
+ * Then look for the least recently used dirty one...., flush and look again.
+ */
+static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev)
+{
+ int i;
+ int usage;
+ int theOne;
+
+ if (dev->nShortOpCaches > 0) {
+ for (i = 0; i < dev->nShortOpCaches; i++) {
+ if (!dev->srCache[i].object)
+ return &dev->srCache[i];
+ }
+
+ return NULL;
+
+ theOne = -1;
+ usage = 0; /* just to stop the compiler grizzling */
+
+ for (i = 0; i < dev->nShortOpCaches; i++) {
+ if (!dev->srCache[i].dirty &&
+ ((dev->srCache[i].lastUse < usage && theOne >= 0) ||
+ theOne < 0)) {
+ usage = dev->srCache[i].lastUse;
+ theOne = i;
+ }
+ }
+
+
+ return theOne >= 0 ? &dev->srCache[theOne] : NULL;
+ } else {
+ return NULL;
+ }
+
+}
+
+static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)
+{
+ yaffs_ChunkCache *cache;
+ yaffs_Object *theObj;
+ int usage;
+ int i;
+ int pushout;
+
+ if (dev->nShortOpCaches > 0) {
+ /* Try find a non-dirty one... */
+
+ cache = yaffs_GrabChunkCacheWorker(dev);
+
+ if (!cache) {
+ /* They were all dirty, find the last recently used object and flush
+ * its cache, then find again.
+ * NB what's here is not very accurate, we actually flush the object
+ * the last recently used page.
+ */
+
+ /* With locking we can't assume we can use entry zero */
+
+ theObj = NULL;
+ usage = -1;
+ cache = NULL;
+ pushout = -1;
+
+ for (i = 0; i < dev->nShortOpCaches; i++) {
+ if (dev->srCache[i].object &&
+ !dev->srCache[i].locked &&
+ (dev->srCache[i].lastUse < usage || !cache))
+ {
+ usage = dev->srCache[i].lastUse;
+ theObj = dev->srCache[i].object;
+ cache = &dev->srCache[i];
+ pushout = i;
+ }
+ }
+
+ if (!cache || cache->dirty) {
+ /* Flush and try again */
+ yaffs_FlushFilesChunkCache(theObj);
+ cache = yaffs_GrabChunkCacheWorker(dev);
+ }
+
+ }
+ return cache;
+ } else
+ return NULL;
+
+}
+
+/* Find a cached chunk */
+static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object * obj,
+ int chunkId)
+{
+ yaffs_Device *dev = obj->myDev;
+ int i;
+ if (dev->nShortOpCaches > 0) {
+ for (i = 0; i < dev->nShortOpCaches; i++) {
+ if (dev->srCache[i].object == obj &&
+ dev->srCache[i].chunkId == chunkId) {
+ dev->cacheHits++;
+
+ return &dev->srCache[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+/* Mark the chunk for the least recently used algorithym */
+static void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache,
+ int isAWrite)
+{
+
+ if (dev->nShortOpCaches > 0) {
+ if (dev->srLastUse < 0 || dev->srLastUse > 100000000) {
+ /* Reset the cache usages */
+ int i;
+ for (i = 1; i < dev->nShortOpCaches; i++) {
+ dev->srCache[i].lastUse = 0;
+ }
+ dev->srLastUse = 0;
+ }
+
+ dev->srLastUse++;
+
+ cache->lastUse = dev->srLastUse;
+
+ if (isAWrite) {
+ cache->dirty = 1;
+ }
+ }
+}
+
+/* Invalidate a single cache page.
+ * Do this when a whole page gets written,
+ * ie the short cache for this page is no longer valid.
+ */
+static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId)
+{
+ if (object->myDev->nShortOpCaches > 0) {
+ yaffs_ChunkCache *cache = yaffs_FindChunkCache(object, chunkId);
+
+ if (cache) {
+ cache->object = NULL;
+ }
+ }
+}
+
+/* Invalidate all the cache pages associated with this object
+ * Do this whenever ther file is deleted or resized.
+ */
+static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in)
+{
+ int i;
+ yaffs_Device *dev = in->myDev;
+
+ if (dev->nShortOpCaches > 0) {
+ /* Invalidate it. */
+ for (i = 0; i < dev->nShortOpCaches; i++) {
+ if (dev->srCache[i].object == in) {
+ dev->srCache[i].object = NULL;
+ }
+ }
+ }
+}
+
+/*--------------------- Checkpointing --------------------*/
+
+
+static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head)
+{
+ yaffs_CheckpointValidity cp;
+
+ memset(&cp,0,sizeof(cp));
+
+ cp.structType = sizeof(cp);
+ cp.magic = YAFFS_MAGIC;
+ cp.version = YAFFS_CHECKPOINT_VERSION;
+ cp.head = (head) ? 1 : 0;
+
+ return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))?
+ 1 : 0;
+}
+
+static int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head)
+{
+ yaffs_CheckpointValidity cp;
+ int ok;
+
+ ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
+
+ if(ok)
+ ok = (cp.structType == sizeof(cp)) &&
+ (cp.magic == YAFFS_MAGIC) &&
+ (cp.version == YAFFS_CHECKPOINT_VERSION) &&
+ (cp.head == ((head) ? 1 : 0));
+ return ok ? 1 : 0;
+}
+
+static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
+ yaffs_Device *dev)
+{
+ cp->nErasedBlocks = dev->nErasedBlocks;
+ cp->allocationBlock = dev->allocationBlock;
+ cp->allocationPage = dev->allocationPage;
+ cp->nFreeChunks = dev->nFreeChunks;
+
+ cp->nDeletedFiles = dev->nDeletedFiles;
+ cp->nUnlinkedFiles = dev->nUnlinkedFiles;
+ cp->nBackgroundDeletions = dev->nBackgroundDeletions;
+ cp->sequenceNumber = dev->sequenceNumber;
+ cp->oldestDirtySequence = dev->oldestDirtySequence;
+
+}
+
+static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
+ yaffs_CheckpointDevice *cp)
+{
+ dev->nErasedBlocks = cp->nErasedBlocks;
+ dev->allocationBlock = cp->allocationBlock;
+ dev->allocationPage = cp->allocationPage;
+ dev->nFreeChunks = cp->nFreeChunks;
+
+ dev->nDeletedFiles = cp->nDeletedFiles;
+ dev->nUnlinkedFiles = cp->nUnlinkedFiles;
+ dev->nBackgroundDeletions = cp->nBackgroundDeletions;
+ dev->sequenceNumber = cp->sequenceNumber;
+ dev->oldestDirtySequence = cp->oldestDirtySequence;
+}
+
+
+static int yaffs_WriteCheckpointDevice(yaffs_Device *dev)
+{
+ yaffs_CheckpointDevice cp;
+ __u32 nBytes;
+ __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
+
+ int ok;
+
+ /* Write device runtime values*/
+ yaffs_DeviceToCheckpointDevice(&cp,dev);
+ cp.structType = sizeof(cp);
+
+ ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
+
+ /* Write block info */
+ if(ok) {
+ nBytes = nBlocks * sizeof(yaffs_BlockInfo);
+ ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes);
+ }
+
+ /* Write chunk bits */
+ if(ok) {
+ nBytes = nBlocks * dev->chunkBitmapStride;
+ ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes);
+ }
+ return ok ? 1 : 0;
+
+}
+
+static int yaffs_ReadCheckpointDevice(yaffs_Device *dev)
+{
+ yaffs_CheckpointDevice cp;
+ __u32 nBytes;
+ __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
+
+ int ok;
+
+ ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
+ if(!ok)
+ return 0;
+
+ if(cp.structType != sizeof(cp))
+ return 0;
+
+
+ yaffs_CheckpointDeviceToDevice(dev,&cp);
+
+ nBytes = nBlocks * sizeof(yaffs_BlockInfo);
+
+ ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes);
+
+ if(!ok)
+ return 0;
+ nBytes = nBlocks * dev->chunkBitmapStride;
+
+ ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes);
+
+ return ok ? 1 : 0;
+}
+
+static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,
+ yaffs_Object *obj)
+{
+
+ cp->objectId = obj->objectId;
+ cp->parentId = (obj->parent) ? obj->parent->objectId : 0;
+ cp->chunkId = obj->chunkId;
+ cp->variantType = obj->variantType;
+ cp->deleted = obj->deleted;
+ cp->softDeleted = obj->softDeleted;
+ cp->unlinked = obj->unlinked;
+ cp->fake = obj->fake;
+ cp->renameAllowed = obj->renameAllowed;
+ cp->unlinkAllowed = obj->unlinkAllowed;
+ cp->serial = obj->serial;
+ cp->nDataChunks = obj->nDataChunks;
+
+ if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
+ cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize;
+ else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
+ cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId;
+}
+
+static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp)
+{
+
+ yaffs_Object *parent;
+
+ obj->objectId = cp->objectId;
+
+ if(cp->parentId)
+ parent = yaffs_FindOrCreateObjectByNumber(
+ obj->myDev,
+ cp->parentId,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+ else
+ parent = NULL;
+
+ if(parent)
+ yaffs_AddObjectToDirectory(parent, obj);
+
+ obj->chunkId = cp->chunkId;
+ obj->variantType = cp->variantType;
+ obj->deleted = cp->deleted;
+ obj->softDeleted = cp->softDeleted;
+ obj->unlinked = cp->unlinked;
+ obj->fake = cp->fake;
+ obj->renameAllowed = cp->renameAllowed;
+ obj->unlinkAllowed = cp->unlinkAllowed;
+ obj->serial = cp->serial;
+ obj->nDataChunks = cp->nDataChunks;
+
+ if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
+ obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId;
+ else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
+ obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId;
+
+ if(obj->objectId >= YAFFS_NOBJECT_BUCKETS)
+ obj->lazyLoaded = 1;
+}
+
+
+
+static int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn,
+ __u32 level, int chunkOffset)
+{
+ int i;
+ yaffs_Device *dev = in->myDev;
+ int ok = 1;
+ int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+
+ if (tn) {
+ if (level > 0) {
+
+ for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){
+ if (tn->internal[i]) {
+ ok = yaffs_CheckpointTnodeWorker(in,
+ tn->internal[i],
+ level - 1,
+ (chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i);
+ }
+ }
+ } else if (level == 0) {
+ __u32 baseOffset = chunkOffset << YAFFS_TNODES_LEVEL0_BITS;
+ /* printf("write tnode at %d\n",baseOffset); */
+ ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
+ if(ok)
+ ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
+ }
+ }
+
+ return ok;
+
+}
+
+static int yaffs_WriteCheckpointTnodes(yaffs_Object *obj)
+{
+ __u32 endMarker = ~0;
+ int ok = 1;
+
+ if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){
+ ok = yaffs_CheckpointTnodeWorker(obj,
+ obj->variant.fileVariant.top,
+ obj->variant.fileVariant.topLevel,
+ 0);
+ if(ok)
+ ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) ==
+ sizeof(endMarker));
+ }
+
+ return ok ? 1 : 0;
+}
+
+static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
+{
+ __u32 baseChunk;
+ int ok = 1;
+ yaffs_Device *dev = obj->myDev;
+ yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
+ yaffs_Tnode *tn;
+ int nread = 0;
+
+ ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
+
+ while(ok && (~baseChunk)){
+ nread++;
+ /* Read level 0 tnode */
+
+
+ /* printf("read tnode at %d\n",baseChunk); */
+ tn = yaffs_GetTnodeRaw(dev);
+ if(tn)
+ ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) ==
+ (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
+ else
+ ok = 0;
+
+ if(tn && ok){
+ ok = yaffs_AddOrFindLevel0Tnode(dev,
+ fileStructPtr,
+ baseChunk,
+ tn) ? 1 : 0;
+
+ }
+
+ if(ok)
+ ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
+
+ }
+
+ T(YAFFS_TRACE_CHECKPOINT,(
+ TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR),
+ nread,baseChunk,ok));
+
+ return ok ? 1 : 0;
+}
+
+
+static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
+{
+ yaffs_Object *obj;
+ yaffs_CheckpointObject cp;
+ int i;
+ int ok = 1;
+ struct list_head *lh;
+
+
+ /* Iterate through the objects in each hash entry,
+ * dumping them to the checkpointing stream.
+ */
+
+ for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){
+ list_for_each(lh, &dev->objectBucket[i].list) {
+ if (lh) {
+ obj = list_entry(lh, yaffs_Object, hashLink);
+ if (!obj->deferedFree) {
+ yaffs_ObjectToCheckpointObject(&cp,obj);
+ cp.structType = sizeof(cp);
+
+ T(YAFFS_TRACE_CHECKPOINT,(
+ TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
+ cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
+
+ ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
+
+ if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
+ ok = yaffs_WriteCheckpointTnodes(obj);
+ }
+ }
+ }
+ }
+ }
+
+ /* Dump end of list */
+ memset(&cp,0xFF,sizeof(yaffs_CheckpointObject));
+ cp.structType = sizeof(cp);
+
+ if(ok)
+ ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
+
+ return ok ? 1 : 0;
+}
+
+static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
+{
+ yaffs_Object *obj;
+ yaffs_CheckpointObject cp;
+ int ok = 1;
+ int done = 0;
+ yaffs_Object *hardList = NULL;
+
+ while(ok && !done) {
+ ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
+ if(cp.structType != sizeof(cp)) {
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("struct size %d instead of %d ok %d"TENDSTR),
+ cp.structType,sizeof(cp),ok));
+ ok = 0;
+ }
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR),
+ cp.objectId,cp.parentId,cp.variantType,cp.chunkId));
+
+ if(ok && cp.objectId == ~0)
+ done = 1;
+ else if(ok){
+ obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType);
+ if(obj) {
+ yaffs_CheckpointObjectToObject(obj,&cp);
+ if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
+ ok = yaffs_ReadCheckpointTnodes(obj);
+ } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
+ obj->hardLinks.next =
+ (struct list_head *)
+ hardList;
+ hardList = obj;
+ }
+
+ }
+ }
+ }
+
+ if(ok)
+ yaffs_HardlinkFixup(dev,hardList);
+
+ return ok ? 1 : 0;
+}
+
+static int yaffs_WriteCheckpointSum(yaffs_Device *dev)
+{
+ __u32 checkpointSum;
+ int ok;
+
+ yaffs_GetCheckpointSum(dev,&checkpointSum);
+
+ ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum));
+
+ if(!ok)
+ return 0;
+
+ return 1;
+}
+
+static int yaffs_ReadCheckpointSum(yaffs_Device *dev)
+{
+ __u32 checkpointSum0;
+ __u32 checkpointSum1;
+ int ok;
+
+ yaffs_GetCheckpointSum(dev,&checkpointSum0);
+
+ ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1));
+
+ if(!ok)
+ return 0;
+
+ if(checkpointSum0 != checkpointSum1)
+ return 0;
+
+ return 1;
+}
+
+
+static int yaffs_WriteCheckpointData(yaffs_Device *dev)
+{
+
+ int ok = 1;
+
+ if(dev->skipCheckpointWrite || !dev->isYaffs2){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR)));
+ ok = 0;
+ }
+
+ if(ok)
+ ok = yaffs_CheckpointOpen(dev,1);
+
+ if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
+ ok = yaffs_WriteCheckpointValidityMarker(dev,1);
+ }
+ if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint device" TENDSTR)));
+ ok = yaffs_WriteCheckpointDevice(dev);
+ }
+ if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint objects" TENDSTR)));
+ ok = yaffs_WriteCheckpointObjects(dev);
+ }
+ if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
+ ok = yaffs_WriteCheckpointValidityMarker(dev,0);
+ }
+
+ if(ok){
+ ok = yaffs_WriteCheckpointSum(dev);
+ }
+
+
+ if(!yaffs_CheckpointClose(dev))
+ ok = 0;
+
+ if(ok)
+ dev->isCheckpointed = 1;
+ else
+ dev->isCheckpointed = 0;
+
+ return dev->isCheckpointed;
+}
+
+static int yaffs_ReadCheckpointData(yaffs_Device *dev)
+{
+ int ok = 1;
+
+ if(dev->skipCheckpointRead || !dev->isYaffs2){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR)));
+ ok = 0;
+ }
+
+ if(ok)
+ ok = yaffs_CheckpointOpen(dev,0); /* open for read */
+
+ if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
+ ok = yaffs_ReadCheckpointValidityMarker(dev,1);
+ }
+ if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint device" TENDSTR)));
+ ok = yaffs_ReadCheckpointDevice(dev);
+ }
+ if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));
+ ok = yaffs_ReadCheckpointObjects(dev);
+ }
+ if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
+ ok = yaffs_ReadCheckpointValidityMarker(dev,0);
+ }
+
+ if(ok){
+ ok = yaffs_ReadCheckpointSum(dev);
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok));
+ }
+
+ if(!yaffs_CheckpointClose(dev))
+ ok = 0;
+
+ if(ok)
+ dev->isCheckpointed = 1;
+ else
+ dev->isCheckpointed = 0;
+
+ return ok ? 1 : 0;
+
+}
+
+static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
+{
+ if(dev->isCheckpointed ||
+ dev->blocksInCheckpoint > 0){
+ dev->isCheckpointed = 0;
+ yaffs_CheckpointInvalidateStream(dev);
+ if(dev->superBlock && dev->markSuperBlockDirty)
+ dev->markSuperBlockDirty(dev->superBlock);
+ }
+}
+
+
+int yaffs_CheckpointSave(yaffs_Device *dev)
+{
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
+ yaffs_VerifyObjects(dev);
+ yaffs_VerifyBlocks(dev);
+ yaffs_VerifyFreeChunks(dev);
+
+ if(!dev->isCheckpointed) {
+ yaffs_InvalidateCheckpoint(dev);
+ yaffs_WriteCheckpointData(dev);
+ }
+
+ T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
+ return dev->isCheckpointed;
+}
+
+int yaffs_CheckpointRestore(yaffs_Device *dev)
+{
+ int retval;
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
+ retval = yaffs_ReadCheckpointData(dev);
+
+ if(dev->isCheckpointed){
+ yaffs_VerifyObjects(dev);
+ yaffs_VerifyBlocks(dev);
+ yaffs_VerifyFreeChunks(dev);
+ }
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
+ return retval;
+}
+
+/*--------------------- File read/write ------------------------
+ * Read and write have very similar structures.
+ * In general the read/write has three parts to it
+ * An incomplete chunk to start with (if the read/write is not chunk-aligned)
+ * Some complete chunks
+ * An incomplete chunk to end off with
+ *
+ * Curve-balls: the first chunk might also be the last chunk.
+ */
+
+int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,
+ int nBytes)
+{
+
+ int chunk;
+ int start;
+ int nToCopy;
+ int n = nBytes;
+ int nDone = 0;
+ yaffs_ChunkCache *cache;
+
+ yaffs_Device *dev;
+
+ dev = in->myDev;
+
+ while (n > 0) {
+ //chunk = offset / dev->nDataBytesPerChunk + 1;
+ //start = offset % dev->nDataBytesPerChunk;
+ yaffs_AddrToChunk(dev,offset,&chunk,&start);
+ chunk++;
+
+ /* OK now check for the curveball where the start and end are in
+ * the same chunk.
+ */
+ if ((start + n) < dev->nDataBytesPerChunk) {
+ nToCopy = n;
+ } else {
+ nToCopy = dev->nDataBytesPerChunk - start;
+ }
+
+ cache = yaffs_FindChunkCache(in, chunk);
+
+ /* If the chunk is already in the cache or it is less than a whole chunk
+ * then use the cache (if there is caching)
+ * else bypass the cache.
+ */
+ if (cache || nToCopy != dev->nDataBytesPerChunk) {
+ if (dev->nShortOpCaches > 0) {
+
+ /* If we can't find the data in the cache, then load it up. */
+
+ if (!cache) {
+ cache = yaffs_GrabChunkCache(in->myDev);
+ cache->object = in;
+ cache->chunkId = chunk;
+ cache->dirty = 0;
+ cache->locked = 0;
+ yaffs_ReadChunkDataFromObject(in, chunk,
+ cache->
+ data);
+ cache->nBytes = 0;
+ }
+
+ yaffs_UseChunkCache(dev, cache, 0);
+
+ cache->locked = 1;
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_UnlockYAFFS(TRUE);
+#endif
+ memcpy(buffer, &cache->data[start], nToCopy);
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_LockYAFFS(TRUE);
+#endif
+ cache->locked = 0;
+ } else {
+ /* Read into the local buffer then copy..*/
+
+ __u8 *localBuffer =
+ yaffs_GetTempBuffer(dev, __LINE__);
+ yaffs_ReadChunkDataFromObject(in, chunk,
+ localBuffer);
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_UnlockYAFFS(TRUE);
+#endif
+ memcpy(buffer, &localBuffer[start], nToCopy);
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_LockYAFFS(TRUE);
+#endif
+ yaffs_ReleaseTempBuffer(dev, localBuffer,
+ __LINE__);
+ }
+
+ } else {
+#ifdef CONFIG_YAFFS_WINCE
+ __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
+
+ /* Under WinCE can't do direct transfer. Need to use a local buffer.
+ * This is because we otherwise screw up WinCE's memory mapper
+ */
+ yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_UnlockYAFFS(TRUE);
+#endif
+ memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_LockYAFFS(TRUE);
+ yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
+#endif
+
+#else
+ /* A full chunk. Read directly into the supplied buffer. */
+ yaffs_ReadChunkDataFromObject(in, chunk, buffer);
+#endif
+ }
+
+ n -= nToCopy;
+ offset += nToCopy;
+ buffer += nToCopy;
+ nDone += nToCopy;
+
+ }
+
+ return nDone;
+}
+
+int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
+ int nBytes, int writeThrough)
+{
+
+ int chunk;
+ int start;
+ int nToCopy;
+ int n = nBytes;
+ int nDone = 0;
+ int nToWriteBack;
+ int startOfWrite = offset;
+ int chunkWritten = 0;
+ int nBytesRead;
+
+ yaffs_Device *dev;
+
+ dev = in->myDev;
+
+ while (n > 0 && chunkWritten >= 0) {
+ //chunk = offset / dev->nDataBytesPerChunk + 1;
+ //start = offset % dev->nDataBytesPerChunk;
+ yaffs_AddrToChunk(dev,offset,&chunk,&start);
+ chunk++;
+
+ /* OK now check for the curveball where the start and end are in
+ * the same chunk.
+ */
+
+ if ((start + n) < dev->nDataBytesPerChunk) {
+ nToCopy = n;
+
+ /* Now folks, to calculate how many bytes to write back....
+ * If we're overwriting and not writing to then end of file then
+ * we need to write back as much as was there before.
+ */
+
+ nBytesRead =
+ in->variant.fileVariant.fileSize -
+ ((chunk - 1) * dev->nDataBytesPerChunk);
+
+ if (nBytesRead > dev->nDataBytesPerChunk) {
+ nBytesRead = dev->nDataBytesPerChunk;
+ }
+
+ nToWriteBack =
+ (nBytesRead >
+ (start + n)) ? nBytesRead : (start + n);
+
+ } else {
+ nToCopy = dev->nDataBytesPerChunk - start;
+ nToWriteBack = dev->nDataBytesPerChunk;
+ }
+
+ if (nToCopy != dev->nDataBytesPerChunk) {
+ /* An incomplete start or end chunk (or maybe both start and end chunk) */
+ if (dev->nShortOpCaches > 0) {
+ yaffs_ChunkCache *cache;
+ /* If we can't find the data in the cache, then load the cache */
+ cache = yaffs_FindChunkCache(in, chunk);
+
+ if (!cache
+ && yaffs_CheckSpaceForAllocation(in->
+ myDev)) {
+ cache = yaffs_GrabChunkCache(in->myDev);
+ cache->object = in;
+ cache->chunkId = chunk;
+ cache->dirty = 0;
+ cache->locked = 0;
+ yaffs_ReadChunkDataFromObject(in, chunk,
+ cache->
+ data);
+ }
+ else if(cache &&
+ !cache->dirty &&
+ !yaffs_CheckSpaceForAllocation(in->myDev)){
+ /* Drop the cache if it was a read cache item and
+ * no space check has been made for it.
+ */
+ cache = NULL;
+ }
+
+ if (cache) {
+ yaffs_UseChunkCache(dev, cache, 1);
+ cache->locked = 1;
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_UnlockYAFFS(TRUE);
+#endif
+
+ memcpy(&cache->data[start], buffer,
+ nToCopy);
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_LockYAFFS(TRUE);
+#endif
+ cache->locked = 0;
+ cache->nBytes = nToWriteBack;
+
+ if (writeThrough) {
+ chunkWritten =
+ yaffs_WriteChunkDataToObject
+ (cache->object,
+ cache->chunkId,
+ cache->data, cache->nBytes,
+ 1);
+ cache->dirty = 0;
+ }
+
+ } else {
+ chunkWritten = -1; /* fail the write */
+ }
+ } else {
+ /* An incomplete start or end chunk (or maybe both start and end chunk)
+ * Read into the local buffer then copy, then copy over and write back.
+ */
+
+ __u8 *localBuffer =
+ yaffs_GetTempBuffer(dev, __LINE__);
+
+ yaffs_ReadChunkDataFromObject(in, chunk,
+ localBuffer);
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_UnlockYAFFS(TRUE);
+#endif
+
+ memcpy(&localBuffer[start], buffer, nToCopy);
+
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_LockYAFFS(TRUE);
+#endif
+ chunkWritten =
+ yaffs_WriteChunkDataToObject(in, chunk,
+ localBuffer,
+ nToWriteBack,
+ 0);
+
+ yaffs_ReleaseTempBuffer(dev, localBuffer,
+ __LINE__);
+
+ }
+
+ } else {
+
+#ifdef CONFIG_YAFFS_WINCE
+ /* Under WinCE can't do direct transfer. Need to use a local buffer.
+ * This is because we otherwise screw up WinCE's memory mapper
+ */
+ __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_UnlockYAFFS(TRUE);
+#endif
+ memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_LockYAFFS(TRUE);
+#endif
+ chunkWritten =
+ yaffs_WriteChunkDataToObject(in, chunk, localBuffer,
+ dev->nDataBytesPerChunk,
+ 0);
+ yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
+#else
+ /* A full chunk. Write directly from the supplied buffer. */
+ chunkWritten =
+ yaffs_WriteChunkDataToObject(in, chunk, buffer,
+ dev->nDataBytesPerChunk,
+ 0);
+#endif
+ /* Since we've overwritten the cached data, we better invalidate it. */
+ yaffs_InvalidateChunkCache(in, chunk);
+ }
+
+ if (chunkWritten >= 0) {
+ n -= nToCopy;
+ offset += nToCopy;
+ buffer += nToCopy;
+ nDone += nToCopy;
+ }
+
+ }
+
+ /* Update file object */
+
+ if ((startOfWrite + nDone) > in->variant.fileVariant.fileSize) {
+ in->variant.fileVariant.fileSize = (startOfWrite + nDone);
+ }
+
+ in->dirty = 1;
+
+ return nDone;
+}
+
+
+/* ---------------------- File resizing stuff ------------------ */
+
+static void yaffs_PruneResizedChunks(yaffs_Object * in, int newSize)
+{
+
+ yaffs_Device *dev = in->myDev;
+ int oldFileSize = in->variant.fileVariant.fileSize;
+
+ int lastDel = 1 + (oldFileSize - 1) / dev->nDataBytesPerChunk;
+
+ int startDel = 1 + (newSize + dev->nDataBytesPerChunk - 1) /
+ dev->nDataBytesPerChunk;
+ int i;
+ int chunkId;
+
+ /* Delete backwards so that we don't end up with holes if
+ * power is lost part-way through the operation.
+ */
+ for (i = lastDel; i >= startDel; i--) {
+ /* NB this could be optimised somewhat,
+ * eg. could retrieve the tags and write them without
+ * using yaffs_DeleteChunk
+ */
+
+ chunkId = yaffs_FindAndDeleteChunkInFile(in, i, NULL);
+ if (chunkId > 0) {
+ if (chunkId <
+ (dev->internalStartBlock * dev->nChunksPerBlock)
+ || chunkId >=
+ ((dev->internalEndBlock +
+ 1) * dev->nChunksPerBlock)) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("Found daft chunkId %d for %d" TENDSTR),
+ chunkId, i));
+ } else {
+ in->nDataChunks--;
+ yaffs_DeleteChunk(dev, chunkId, 1, __LINE__);
+ }
+ }
+ }
+
+}
+
+int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize)
+{
+
+ int oldFileSize = in->variant.fileVariant.fileSize;
+ int newSizeOfPartialChunk;
+ int newFullChunks;
+
+ yaffs_Device *dev = in->myDev;
+
+ yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk);
+
+ yaffs_FlushFilesChunkCache(in);
+ yaffs_InvalidateWholeChunkCache(in);
+
+ yaffs_CheckGarbageCollection(dev);
+
+ if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
+ return yaffs_GetFileSize(in);
+ }
+
+ if (newSize == oldFileSize) {
+ return oldFileSize;
+ }
+
+ if (newSize < oldFileSize) {
+
+ yaffs_PruneResizedChunks(in, newSize);
+
+ if (newSizeOfPartialChunk != 0) {
+ int lastChunk = 1 + newFullChunks;
+
+ __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
+
+ /* Got to read and rewrite the last chunk with its new size and zero pad */
+ yaffs_ReadChunkDataFromObject(in, lastChunk,
+ localBuffer);
+
+ memset(localBuffer + newSizeOfPartialChunk, 0,
+ dev->nDataBytesPerChunk - newSizeOfPartialChunk);
+
+ yaffs_WriteChunkDataToObject(in, lastChunk, localBuffer,
+ newSizeOfPartialChunk, 1);
+
+ yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
+ }
+
+ in->variant.fileVariant.fileSize = newSize;
+
+ yaffs_PruneFileStructure(dev, &in->variant.fileVariant);
+ } else {
+ /* newsSize > oldFileSize */
+ in->variant.fileVariant.fileSize = newSize;
+ }
+
+
+
+ /* Write a new object header.
+ * show we've shrunk the file, if need be
+ * Do this only if the file is not in the deleted directories.
+ */
+ if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
+ in->parent->objectId != YAFFS_OBJECTID_DELETED) {
+ yaffs_UpdateObjectHeader(in, NULL, 0,
+ (newSize < oldFileSize) ? 1 : 0, 0);
+ }
+
+ return YAFFS_OK;
+}
+
+loff_t yaffs_GetFileSize(yaffs_Object * obj)
+{
+ obj = yaffs_GetEquivalentObject(obj);
+
+ switch (obj->variantType) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ return obj->variant.fileVariant.fileSize;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ return yaffs_strlen(obj->variant.symLinkVariant.alias);
+ default:
+ return 0;
+ }
+}
+
+
+
+int yaffs_FlushFile(yaffs_Object * in, int updateTime)
+{
+ int retVal;
+ if (in->dirty) {
+ yaffs_FlushFilesChunkCache(in);
+ if (updateTime) {
+#ifdef CONFIG_YAFFS_WINCE
+ yfsd_WinFileTimeNow(in->win_mtime);
+#else
+
+ in->yst_mtime = Y_CURRENT_TIME;
+
+#endif
+ }
+
+ retVal =
+ (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >=
+ 0) ? YAFFS_OK : YAFFS_FAIL;
+ } else {
+ retVal = YAFFS_OK;
+ }
+
+ return retVal;
+
+}
+
+static int yaffs_DoGenericObjectDeletion(yaffs_Object * in)
+{
+
+ /* First off, invalidate the file's data in the cache, without flushing. */
+ yaffs_InvalidateWholeChunkCache(in);
+
+ if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
+ /* Move to the unlinked directory so we have a record that it was deleted. */
+ yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0);
+
+ }
+
+ yaffs_RemoveObjectFromDirectory(in);
+ yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
+ in->chunkId = -1;
+
+ yaffs_FreeObject(in);
+ return YAFFS_OK;
+
+}
+
+/* yaffs_DeleteFile deletes the whole file data
+ * and the inode associated with the file.
+ * It does not delete the links associated with the file.
+ */
+static int yaffs_UnlinkFile(yaffs_Object * in)
+{
+
+ int retVal;
+ int immediateDeletion = 0;
+
+ if (1) {
+/* XXX U-BOOT XXX */
+#if 0
+#ifdef __KERNEL__
+ if (!in->myInode) {
+ immediateDeletion = 1;
+
+ }
+#endif
+#else
+ if (in->inUse <= 0) {
+ immediateDeletion = 1;
+
+ }
+#endif
+ if (immediateDeletion) {
+ retVal =
+ yaffs_ChangeObjectName(in, in->myDev->deletedDir,
+ "deleted", 0, 0);
+ T(YAFFS_TRACE_TRACING,
+ (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
+ in->objectId));
+ in->deleted = 1;
+ in->myDev->nDeletedFiles++;
+ if (0 && in->myDev->isYaffs2) {
+ yaffs_ResizeFile(in, 0);
+ }
+ yaffs_SoftDeleteFile(in);
+ } else {
+ retVal =
+ yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
+ "unlinked", 0, 0);
+ }
+
+ }
+ return retVal;
+}
+
+int yaffs_DeleteFile(yaffs_Object * in)
+{
+ int retVal = YAFFS_OK;
+
+ if (in->nDataChunks > 0) {
+ /* Use soft deletion if there is data in the file */
+ if (!in->unlinked) {
+ retVal = yaffs_UnlinkFile(in);
+ }
+ if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
+ in->deleted = 1;
+ in->myDev->nDeletedFiles++;
+ yaffs_SoftDeleteFile(in);
+ }
+ return in->deleted ? YAFFS_OK : YAFFS_FAIL;
+ } else {
+ /* The file has no data chunks so we toss it immediately */
+ yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
+ in->variant.fileVariant.top = NULL;
+ yaffs_DoGenericObjectDeletion(in);
+
+ return YAFFS_OK;
+ }
+}
+
+static int yaffs_DeleteDirectory(yaffs_Object * in)
+{
+ /* First check that the directory is empty. */
+ if (list_empty(&in->variant.directoryVariant.children)) {
+ return yaffs_DoGenericObjectDeletion(in);
+ }
+
+ return YAFFS_FAIL;
+
+}
+
+static int yaffs_DeleteSymLink(yaffs_Object * in)
+{
+ YFREE(in->variant.symLinkVariant.alias);
+
+ return yaffs_DoGenericObjectDeletion(in);
+}
+
+static int yaffs_DeleteHardLink(yaffs_Object * in)
+{
+ /* remove this hardlink from the list assocaited with the equivalent
+ * object
+ */
+ list_del(&in->hardLinks);
+ return yaffs_DoGenericObjectDeletion(in);
+}
+
+static void yaffs_DestroyObject(yaffs_Object * obj)
+{
+ switch (obj->variantType) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ yaffs_DeleteFile(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ yaffs_DeleteDirectory(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ yaffs_DeleteSymLink(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ yaffs_DeleteHardLink(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ yaffs_DoGenericObjectDeletion(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ break; /* should not happen. */
+ }
+}
+
+static int yaffs_UnlinkWorker(yaffs_Object * obj)
+{
+
+ if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
+ return yaffs_DeleteHardLink(obj);
+ } else if (!list_empty(&obj->hardLinks)) {
+ /* Curve ball: We're unlinking an object that has a hardlink.
+ *
+ * This problem arises because we are not strictly following
+ * The Linux link/inode model.
+ *
+ * We can't really delete the object.
+ * Instead, we do the following:
+ * - Select a hardlink.
+ * - Unhook it from the hard links
+ * - Unhook it from its parent directory (so that the rename can work)
+ * - Rename the object to the hardlink's name.
+ * - Delete the hardlink
+ */
+
+ yaffs_Object *hl;
+ int retVal;
+ YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
+
+ hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
+
+ list_del_init(&hl->hardLinks);
+ list_del_init(&hl->siblings);
+
+ yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
+
+ retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0);
+
+ if (retVal == YAFFS_OK) {
+ retVal = yaffs_DoGenericObjectDeletion(hl);
+ }
+ return retVal;
+
+ } else {
+ switch (obj->variantType) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ return yaffs_UnlinkFile(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ return yaffs_DeleteDirectory(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ return yaffs_DeleteSymLink(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ return yaffs_DoGenericObjectDeletion(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ default:
+ return YAFFS_FAIL;
+ }
+ }
+}
+
+
+static int yaffs_UnlinkObject( yaffs_Object *obj)
+{
+
+ if (obj && obj->unlinkAllowed) {
+ return yaffs_UnlinkWorker(obj);
+ }
+
+ return YAFFS_FAIL;
+
+}
+int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name)
+{
+ yaffs_Object *obj;
+
+ obj = yaffs_FindObjectByName(dir, name);
+ return yaffs_UnlinkObject(obj);
+}
+
+/*----------------------- Initialisation Scanning ---------------------- */
+
+static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId,
+ int backwardScanning)
+{
+ yaffs_Object *obj;
+
+ if (!backwardScanning) {
+ /* Handle YAFFS1 forward scanning case
+ * For YAFFS1 we always do the deletion
+ */
+
+ } else {
+ /* Handle YAFFS2 case (backward scanning)
+ * If the shadowed object exists then ignore.
+ */
+ if (yaffs_FindObjectByNumber(dev, objId)) {
+ return;
+ }
+ }
+
+ /* Let's create it (if it does not exist) assuming it is a file so that it can do shrinking etc.
+ * We put it in unlinked dir to be cleaned up after the scanning
+ */
+ obj =
+ yaffs_FindOrCreateObjectByNumber(dev, objId,
+ YAFFS_OBJECT_TYPE_FILE);
+ yaffs_AddObjectToDirectory(dev->unlinkedDir, obj);
+ obj->variant.fileVariant.shrinkSize = 0;
+ obj->valid = 1; /* So that we don't read any other info for this file */
+
+}
+
+typedef struct {
+ int seq;
+ int block;
+} yaffs_BlockIndex;
+
+
+static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList)
+{
+ yaffs_Object *hl;
+ yaffs_Object *in;
+
+ while (hardList) {
+ hl = hardList;
+ hardList = (yaffs_Object *) (hardList->hardLinks.next);
+
+ in = yaffs_FindObjectByNumber(dev,
+ hl->variant.hardLinkVariant.
+ equivalentObjectId);
+
+ if (in) {
+ /* Add the hardlink pointers */
+ hl->variant.hardLinkVariant.equivalentObject = in;
+ list_add(&hl->hardLinks, &in->hardLinks);
+ } else {
+ /* Todo Need to report/handle this better.
+ * Got a problem... hardlink to a non-existant object
+ */
+ hl->variant.hardLinkVariant.equivalentObject = NULL;
+ INIT_LIST_HEAD(&hl->hardLinks);
+
+ }
+
+ }
+
+}
+
+
+
+
+
+static int ybicmp(const void *a, const void *b){
+ register int aseq = ((yaffs_BlockIndex *)a)->seq;
+ register int bseq = ((yaffs_BlockIndex *)b)->seq;
+ register int ablock = ((yaffs_BlockIndex *)a)->block;
+ register int bblock = ((yaffs_BlockIndex *)b)->block;
+ if( aseq == bseq )
+ return ablock - bblock;
+ else
+ return aseq - bseq;
+
+}
+
+static int yaffs_Scan(yaffs_Device * dev)
+{
+ yaffs_ExtendedTags tags;
+ int blk;
+ int blockIterator;
+ int startIterator;
+ int endIterator;
+ int nBlocksToScan = 0;
+ int result;
+
+ int chunk;
+ int c;
+ int deleted;
+ yaffs_BlockState state;
+ yaffs_Object *hardList = NULL;
+ yaffs_BlockInfo *bi;
+ int sequenceNumber;
+ yaffs_ObjectHeader *oh;
+ yaffs_Object *in;
+ yaffs_Object *parent;
+ int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
+
+ int alloc_failed = 0;
+
+
+ __u8 *chunkData;
+
+ yaffs_BlockIndex *blockIndex = NULL;
+
+ if (dev->isYaffs2) {
+ T(YAFFS_TRACE_SCAN,
+ (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ //TODO Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.
+
+ T(YAFFS_TRACE_SCAN,
+ (TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR),
+ dev->internalStartBlock, dev->internalEndBlock));
+
+ chunkData = yaffs_GetTempBuffer(dev, __LINE__);
+
+ dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
+
+ if (dev->isYaffs2) {
+ blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
+ if(!blockIndex)
+ return YAFFS_FAIL;
+ }
+
+ /* Scan all the blocks to determine their state */
+ for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
+ bi = yaffs_GetBlockInfo(dev, blk);
+ yaffs_ClearChunkBits(dev, blk);
+ bi->pagesInUse = 0;
+ bi->softDeletions = 0;
+
+ yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
+
+ bi->blockState = state;
+ bi->sequenceNumber = sequenceNumber;
+
+ T(YAFFS_TRACE_SCAN_DEBUG,
+ (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
+ state, sequenceNumber));
+
+ if (state == YAFFS_BLOCK_STATE_DEAD) {
+ T(YAFFS_TRACE_BAD_BLOCKS,
+ (TSTR("block %d is bad" TENDSTR), blk));
+ } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
+ T(YAFFS_TRACE_SCAN_DEBUG,
+ (TSTR("Block empty " TENDSTR)));
+ dev->nErasedBlocks++;
+ dev->nFreeChunks += dev->nChunksPerBlock;
+ } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
+
+ /* Determine the highest sequence number */
+ if (dev->isYaffs2 &&
+ sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
+ sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
+
+ blockIndex[nBlocksToScan].seq = sequenceNumber;
+ blockIndex[nBlocksToScan].block = blk;
+
+ nBlocksToScan++;
+
+ if (sequenceNumber >= dev->sequenceNumber) {
+ dev->sequenceNumber = sequenceNumber;
+ }
+ } else if (dev->isYaffs2) {
+ /* TODO: Nasty sequence number! */
+ T(YAFFS_TRACE_SCAN,
+ (TSTR
+ ("Block scanning block %d has bad sequence number %d"
+ TENDSTR), blk, sequenceNumber));
+
+ }
+ }
+ }
+
+ /* Sort the blocks
+ * Dungy old bubble sort for now...
+ */
+ if (dev->isYaffs2) {
+ yaffs_BlockIndex temp;
+ int i;
+ int j;
+
+ for (i = 0; i < nBlocksToScan; i++)
+ for (j = i + 1; j < nBlocksToScan; j++)
+ if (blockIndex[i].seq > blockIndex[j].seq) {
+ temp = blockIndex[j];
+ blockIndex[j] = blockIndex[i];
+ blockIndex[i] = temp;
+ }
+ }
+
+ /* Now scan the blocks looking at the data. */
+ if (dev->isYaffs2) {
+ startIterator = 0;
+ endIterator = nBlocksToScan - 1;
+ T(YAFFS_TRACE_SCAN_DEBUG,
+ (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
+ } else {
+ startIterator = dev->internalStartBlock;
+ endIterator = dev->internalEndBlock;
+ }
+
+ /* For each block.... */
+ for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator;
+ blockIterator++) {
+
+ if (dev->isYaffs2) {
+ /* get the block to scan in the correct order */
+ blk = blockIndex[blockIterator].block;
+ } else {
+ blk = blockIterator;
+ }
+
+ bi = yaffs_GetBlockInfo(dev, blk);
+ state = bi->blockState;
+
+ deleted = 0;
+
+ /* For each chunk in each block that needs scanning....*/
+ for (c = 0; !alloc_failed && c < dev->nChunksPerBlock &&
+ state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) {
+ /* Read the tags and decide what to do */
+ chunk = blk * dev->nChunksPerBlock + c;
+
+ result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
+ &tags);
+
+ /* Let's have a good look at this chunk... */
+
+ if (!dev->isYaffs2 && tags.chunkDeleted) {
+ /* YAFFS1 only...
+ * A deleted chunk
+ */
+ deleted++;
+ dev->nFreeChunks++;
+ /*T((" %d %d deleted\n",blk,c)); */
+ } else if (!tags.chunkUsed) {
+ /* An unassigned chunk in the block
+ * This means that either the block is empty or
+ * this is the one being allocated from
+ */
+
+ if (c == 0) {
+ /* We're looking at the first chunk in the block so the block is unused */
+ state = YAFFS_BLOCK_STATE_EMPTY;
+ dev->nErasedBlocks++;
+ } else {
+ /* this is the block being allocated from */
+ T(YAFFS_TRACE_SCAN,
+ (TSTR
+ (" Allocating from %d %d" TENDSTR),
+ blk, c));
+ state = YAFFS_BLOCK_STATE_ALLOCATING;
+ dev->allocationBlock = blk;
+ dev->allocationPage = c;
+ dev->allocationBlockFinder = blk;
+ /* Set it to here to encourage the allocator to go forth from here. */
+
+ /* Yaffs2 sanity check:
+ * This should be the one with the highest sequence number
+ */
+ if (dev->isYaffs2
+ && (dev->sequenceNumber !=
+ bi->sequenceNumber)) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("yaffs: Allocation block %d was not highest sequence id:"
+ " block seq = %d, dev seq = %d"
+ TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
+ }
+ }
+
+ dev->nFreeChunks += (dev->nChunksPerBlock - c);
+ } else if (tags.chunkId > 0) {
+ /* chunkId > 0 so it is a data chunk... */
+ unsigned int endpos;
+
+ yaffs_SetChunkBit(dev, blk, c);
+ bi->pagesInUse++;
+
+ in = yaffs_FindOrCreateObjectByNumber(dev,
+ tags.
+ objectId,
+ YAFFS_OBJECT_TYPE_FILE);
+ /* PutChunkIntoFile checks for a clash (two data chunks with
+ * the same chunkId).
+ */
+
+ if(!in)
+ alloc_failed = 1;
+
+ if(in){
+ if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1))
+ alloc_failed = 1;
+ }
+
+ endpos =
+ (tags.chunkId - 1) * dev->nDataBytesPerChunk +
+ tags.byteCount;
+ if (in &&
+ in->variantType == YAFFS_OBJECT_TYPE_FILE
+ && in->variant.fileVariant.scannedFileSize <
+ endpos) {
+ in->variant.fileVariant.
+ scannedFileSize = endpos;
+ if (!dev->useHeaderFileSize) {
+ in->variant.fileVariant.
+ fileSize =
+ in->variant.fileVariant.
+ scannedFileSize;
+ }
+
+ }
+ /* T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); */
+ } else {
+ /* chunkId == 0, so it is an ObjectHeader.
+ * Thus, we read in the object header and make the object
+ */
+ yaffs_SetChunkBit(dev, blk, c);
+ bi->pagesInUse++;
+
+ result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk,
+ chunkData,
+ NULL);
+
+ oh = (yaffs_ObjectHeader *) chunkData;
+
+ in = yaffs_FindObjectByNumber(dev,
+ tags.objectId);
+ if (in && in->variantType != oh->type) {
+ /* This should not happen, but somehow
+ * Wev'e ended up with an objectId that has been reused but not yet
+ * deleted, and worse still it has changed type. Delete the old object.
+ */
+
+ yaffs_DestroyObject(in);
+
+ in = 0;
+ }
+
+ in = yaffs_FindOrCreateObjectByNumber(dev,
+ tags.
+ objectId,
+ oh->type);
+
+ if(!in)
+ alloc_failed = 1;
+
+ if (in && oh->shadowsObject > 0) {
+ yaffs_HandleShadowedObject(dev,
+ oh->
+ shadowsObject,
+ 0);
+ }
+
+ if (in && in->valid) {
+ /* We have already filled this one. We have a duplicate and need to resolve it. */
+
+ unsigned existingSerial = in->serial;
+ unsigned newSerial = tags.serialNumber;
+
+ if (dev->isYaffs2 ||
+ ((existingSerial + 1) & 3) ==
+ newSerial) {
+ /* Use new one - destroy the exisiting one */
+ yaffs_DeleteChunk(dev,
+ in->chunkId,
+ 1, __LINE__);
+ in->valid = 0;
+ } else {
+ /* Use existing - destroy this one. */
+ yaffs_DeleteChunk(dev, chunk, 1,
+ __LINE__);
+ }
+ }
+
+ if (in && !in->valid &&
+ (tags.objectId == YAFFS_OBJECTID_ROOT ||
+ tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) {
+ /* We only load some info, don't fiddle with directory structure */
+ in->valid = 1;
+ in->variantType = oh->type;
+
+ in->yst_mode = oh->yst_mode;
+#ifdef CONFIG_YAFFS_WINCE
+ in->win_atime[0] = oh->win_atime[0];
+ in->win_ctime[0] = oh->win_ctime[0];
+ in->win_mtime[0] = oh->win_mtime[0];
+ in->win_atime[1] = oh->win_atime[1];
+ in->win_ctime[1] = oh->win_ctime[1];
+ in->win_mtime[1] = oh->win_mtime[1];
+#else
+ in->yst_uid = oh->yst_uid;
+ in->yst_gid = oh->yst_gid;
+ in->yst_atime = oh->yst_atime;
+ in->yst_mtime = oh->yst_mtime;
+ in->yst_ctime = oh->yst_ctime;
+ in->yst_rdev = oh->yst_rdev;
+#endif
+ in->chunkId = chunk;
+
+ } else if (in && !in->valid) {
+ /* we need to load this info */
+
+ in->valid = 1;
+ in->variantType = oh->type;
+
+ in->yst_mode = oh->yst_mode;
+#ifdef CONFIG_YAFFS_WINCE
+ in->win_atime[0] = oh->win_atime[0];
+ in->win_ctime[0] = oh->win_ctime[0];
+ in->win_mtime[0] = oh->win_mtime[0];
+ in->win_atime[1] = oh->win_atime[1];
+ in->win_ctime[1] = oh->win_ctime[1];
+ in->win_mtime[1] = oh->win_mtime[1];
+#else
+ in->yst_uid = oh->yst_uid;
+ in->yst_gid = oh->yst_gid;
+ in->yst_atime = oh->yst_atime;
+ in->yst_mtime = oh->yst_mtime;
+ in->yst_ctime = oh->yst_ctime;
+ in->yst_rdev = oh->yst_rdev;
+#endif
+ in->chunkId = chunk;
+
+ yaffs_SetObjectName(in, oh->name);
+ in->dirty = 0;
+
+ /* directory stuff...
+ * hook up to parent
+ */
+
+ parent =
+ yaffs_FindOrCreateObjectByNumber
+ (dev, oh->parentObjectId,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+ if (parent->variantType ==
+ YAFFS_OBJECT_TYPE_UNKNOWN) {
+ /* Set up as a directory */
+ parent->variantType =
+ YAFFS_OBJECT_TYPE_DIRECTORY;
+ INIT_LIST_HEAD(&parent->variant.
+ directoryVariant.
+ children);
+ } else if (parent->variantType !=
+ YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ /* Hoosterman, another problem....
+ * We're trying to use a non-directory as a directory
+ */
+
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("yaffs tragedy: attempting to use non-directory as"
+ " a directory in scan. Put in lost+found."
+ TENDSTR)));
+ parent = dev->lostNFoundDir;
+ }
+
+ yaffs_AddObjectToDirectory(parent, in);
+
+ if (0 && (parent == dev->deletedDir ||
+ parent == dev->unlinkedDir)) {
+ in->deleted = 1; /* If it is unlinked at start up then it wants deleting */
+ dev->nDeletedFiles++;
+ }
+ /* Note re hardlinks.
+ * Since we might scan a hardlink before its equivalent object is scanned
+ * we put them all in a list.
+ * After scanning is complete, we should have all the objects, so we run through this
+ * list and fix up all the chains.
+ */
+
+ switch (in->variantType) {
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* Todo got a problem */
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+ if (dev->isYaffs2
+ && oh->isShrink) {
+ /* Prune back the shrunken chunks */
+ yaffs_PruneResizedChunks
+ (in, oh->fileSize);
+ /* Mark the block as having a shrinkHeader */
+ bi->hasShrinkHeader = 1;
+ }
+
+ if (dev->useHeaderFileSize)
+
+ in->variant.fileVariant.
+ fileSize =
+ oh->fileSize;
+
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ in->variant.hardLinkVariant.
+ equivalentObjectId =
+ oh->equivalentObjectId;
+ in->hardLinks.next =
+ (struct list_head *)
+ hardList;
+ hardList = in;
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ in->variant.symLinkVariant.alias =
+ yaffs_CloneString(oh->alias);
+ if(!in->variant.symLinkVariant.alias)
+ alloc_failed = 1;
+ break;
+ }
+
+ if (parent == dev->deletedDir) {
+ yaffs_DestroyObject(in);
+ bi->hasShrinkHeader = 1;
+ }
+ }
+ }
+ }
+
+ if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
+ /* If we got this far while scanning, then the block is fully allocated.*/
+ state = YAFFS_BLOCK_STATE_FULL;
+ }
+
+ bi->blockState = state;
+
+ /* Now let's see if it was dirty */
+ if (bi->pagesInUse == 0 &&
+ !bi->hasShrinkHeader &&
+ bi->blockState == YAFFS_BLOCK_STATE_FULL) {
+ yaffs_BlockBecameDirty(dev, blk);
+ }
+
+ }
+
+ if (blockIndex) {
+ YFREE(blockIndex);
+ }
+
+
+ /* Ok, we've done all the scanning.
+ * Fix up the hard link chains.
+ * We should now have scanned all the objects, now it's time to add these
+ * hardlinks.
+ */
+
+ yaffs_HardlinkFixup(dev,hardList);
+
+ /* Handle the unlinked files. Since they were left in an unlinked state we should
+ * just delete them.
+ */
+ {
+ struct list_head *i;
+ struct list_head *n;
+
+ yaffs_Object *l;
+ /* Soft delete all the unlinked files */
+ list_for_each_safe(i, n,
+ &dev->unlinkedDir->variant.directoryVariant.
+ children) {
+ if (i) {
+ l = list_entry(i, yaffs_Object, siblings);
+ yaffs_DestroyObject(l);
+ }
+ }
+ }
+
+ yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
+
+ if(alloc_failed){
+ return YAFFS_FAIL;
+ }
+
+ T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
+
+
+ return YAFFS_OK;
+}
+
+static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)
+{
+ __u8 *chunkData;
+ yaffs_ObjectHeader *oh;
+ yaffs_Device *dev = in->myDev;
+ yaffs_ExtendedTags tags;
+ int result;
+ int alloc_failed = 0;
+
+ if(!in)
+ return;
+
+#if 0
+ T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR),
+ in->objectId,
+ in->lazyLoaded ? "not yet" : "already"));
+#endif
+
+ if(in->lazyLoaded){
+ in->lazyLoaded = 0;
+ chunkData = yaffs_GetTempBuffer(dev, __LINE__);
+
+ result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags);
+ oh = (yaffs_ObjectHeader *) chunkData;
+
+ in->yst_mode = oh->yst_mode;
+#ifdef CONFIG_YAFFS_WINCE
+ in->win_atime[0] = oh->win_atime[0];
+ in->win_ctime[0] = oh->win_ctime[0];
+ in->win_mtime[0] = oh->win_mtime[0];
+ in->win_atime[1] = oh->win_atime[1];
+ in->win_ctime[1] = oh->win_ctime[1];
+ in->win_mtime[1] = oh->win_mtime[1];
+#else
+ in->yst_uid = oh->yst_uid;
+ in->yst_gid = oh->yst_gid;
+ in->yst_atime = oh->yst_atime;
+ in->yst_mtime = oh->yst_mtime;
+ in->yst_ctime = oh->yst_ctime;
+ in->yst_rdev = oh->yst_rdev;
+
+#endif
+ yaffs_SetObjectName(in, oh->name);
+
+ if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK){
+ in->variant.symLinkVariant.alias =
+ yaffs_CloneString(oh->alias);
+ if(!in->variant.symLinkVariant.alias)
+ alloc_failed = 1; /* Not returned to caller */
+ }
+
+ yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__);
+ }
+}
+
+static int yaffs_ScanBackwards(yaffs_Device * dev)
+{
+ yaffs_ExtendedTags tags;
+ int blk;
+ int blockIterator;
+ int startIterator;
+ int endIterator;
+ int nBlocksToScan = 0;
+
+ int chunk;
+ int result;
+ int c;
+ int deleted;
+ yaffs_BlockState state;
+ yaffs_Object *hardList = NULL;
+ yaffs_BlockInfo *bi;
+ int sequenceNumber;
+ yaffs_ObjectHeader *oh;
+ yaffs_Object *in;
+ yaffs_Object *parent;
+ int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
+ int itsUnlinked;
+ __u8 *chunkData;
+
+ int fileSize;
+ int isShrink;
+ int foundChunksInBlock;
+ int equivalentObjectId;
+ int alloc_failed = 0;
+
+
+ yaffs_BlockIndex *blockIndex = NULL;
+ int altBlockIndex = 0;
+
+ if (!dev->isYaffs2) {
+ T(YAFFS_TRACE_SCAN,
+ (TSTR("yaffs_ScanBackwards is only for YAFFS2!" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ T(YAFFS_TRACE_SCAN,
+ (TSTR
+ ("yaffs_ScanBackwards starts intstartblk %d intendblk %d..."
+ TENDSTR), dev->internalStartBlock, dev->internalEndBlock));
+
+
+ dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
+
+ blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
+
+ if(!blockIndex) {
+ blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
+ altBlockIndex = 1;
+ }
+
+ if(!blockIndex) {
+ T(YAFFS_TRACE_SCAN,
+ (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ dev->blocksInCheckpoint = 0;
+
+ chunkData = yaffs_GetTempBuffer(dev, __LINE__);
+
+ /* Scan all the blocks to determine their state */
+ for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
+ bi = yaffs_GetBlockInfo(dev, blk);
+ yaffs_ClearChunkBits(dev, blk);
+ bi->pagesInUse = 0;
+ bi->softDeletions = 0;
+
+ yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
+
+ bi->blockState = state;
+ bi->sequenceNumber = sequenceNumber;
+
+ if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)
+ bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT;
+
+ T(YAFFS_TRACE_SCAN_DEBUG,
+ (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
+ state, sequenceNumber));
+
+
+ if(state == YAFFS_BLOCK_STATE_CHECKPOINT){
+ dev->blocksInCheckpoint++;
+
+ } else if (state == YAFFS_BLOCK_STATE_DEAD) {
+ T(YAFFS_TRACE_BAD_BLOCKS,
+ (TSTR("block %d is bad" TENDSTR), blk));
+ } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
+ T(YAFFS_TRACE_SCAN_DEBUG,
+ (TSTR("Block empty " TENDSTR)));
+ dev->nErasedBlocks++;
+ dev->nFreeChunks += dev->nChunksPerBlock;
+ } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
+
+ /* Determine the highest sequence number */
+ if (dev->isYaffs2 &&
+ sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
+ sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
+
+ blockIndex[nBlocksToScan].seq = sequenceNumber;
+ blockIndex[nBlocksToScan].block = blk;
+
+ nBlocksToScan++;
+
+ if (sequenceNumber >= dev->sequenceNumber) {
+ dev->sequenceNumber = sequenceNumber;
+ }
+ } else if (dev->isYaffs2) {
+ /* TODO: Nasty sequence number! */
+ T(YAFFS_TRACE_SCAN,
+ (TSTR
+ ("Block scanning block %d has bad sequence number %d"
+ TENDSTR), blk, sequenceNumber));
+
+ }
+ }
+ }
+
+ T(YAFFS_TRACE_SCAN,
+ (TSTR("%d blocks to be sorted..." TENDSTR), nBlocksToScan));
+
+
+
+ YYIELD();
+
+ /* Sort the blocks */
+#ifndef CONFIG_YAFFS_USE_OWN_SORT
+ {
+ /* Use qsort now. */
+ yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
+ }
+#else
+ {
+ /* Dungy old bubble sort... */
+
+ yaffs_BlockIndex temp;
+ int i;
+ int j;
+
+ for (i = 0; i < nBlocksToScan; i++)
+ for (j = i + 1; j < nBlocksToScan; j++)
+ if (blockIndex[i].seq > blockIndex[j].seq) {
+ temp = blockIndex[j];
+ blockIndex[j] = blockIndex[i];
+ blockIndex[i] = temp;
+ }
+ }
+#endif
+
+ YYIELD();
+
+ T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR)));
+
+ /* Now scan the blocks looking at the data. */
+ startIterator = 0;
+ endIterator = nBlocksToScan - 1;
+ T(YAFFS_TRACE_SCAN_DEBUG,
+ (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
+
+ /* For each block.... backwards */
+ for (blockIterator = endIterator; !alloc_failed && blockIterator >= startIterator;
+ blockIterator--) {
+ /* Cooperative multitasking! This loop can run for so
+ long that watchdog timers expire. */
+ YYIELD();
+
+ /* get the block to scan in the correct order */
+ blk = blockIndex[blockIterator].block;
+
+ bi = yaffs_GetBlockInfo(dev, blk);
+
+
+ state = bi->blockState;
+
+ deleted = 0;
+
+ /* For each chunk in each block that needs scanning.... */
+ foundChunksInBlock = 0;
+ for (c = dev->nChunksPerBlock - 1;
+ !alloc_failed && c >= 0 &&
+ (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
+ state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
+ /* Scan backwards...
+ * Read the tags and decide what to do
+ */
+
+ chunk = blk * dev->nChunksPerBlock + c;
+
+ result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
+ &tags);
+
+ /* Let's have a good look at this chunk... */
+
+ if (!tags.chunkUsed) {
+ /* An unassigned chunk in the block.
+ * If there are used chunks after this one, then
+ * it is a chunk that was skipped due to failing the erased
+ * check. Just skip it so that it can be deleted.
+ * But, more typically, We get here when this is an unallocated
+ * chunk and his means that either the block is empty or
+ * this is the one being allocated from
+ */
+
+ if(foundChunksInBlock)
+ {
+ /* This is a chunk that was skipped due to failing the erased check */
+
+ } else if (c == 0) {
+ /* We're looking at the first chunk in the block so the block is unused */
+ state = YAFFS_BLOCK_STATE_EMPTY;
+ dev->nErasedBlocks++;
+ } else {
+ if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
+ state == YAFFS_BLOCK_STATE_ALLOCATING) {
+ if(dev->sequenceNumber == bi->sequenceNumber) {
+ /* this is the block being allocated from */
+
+ T(YAFFS_TRACE_SCAN,
+ (TSTR
+ (" Allocating from %d %d"
+ TENDSTR), blk, c));
+
+ state = YAFFS_BLOCK_STATE_ALLOCATING;
+ dev->allocationBlock = blk;
+ dev->allocationPage = c;
+ dev->allocationBlockFinder = blk;
+ }
+ else {
+ /* This is a partially written block that is not
+ * the current allocation block. This block must have
+ * had a write failure, so set up for retirement.
+ */
+
+ bi->needsRetiring = 1;
+ bi->gcPrioritise = 1;
+
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("Partially written block %d being set for retirement" TENDSTR),
+ blk));
+ }
+
+ }
+
+ }
+
+ dev->nFreeChunks++;
+
+ } else if (tags.chunkId > 0) {
+ /* chunkId > 0 so it is a data chunk... */
+ unsigned int endpos;
+ __u32 chunkBase =
+ (tags.chunkId - 1) * dev->nDataBytesPerChunk;
+
+ foundChunksInBlock = 1;
+
+
+ yaffs_SetChunkBit(dev, blk, c);
+ bi->pagesInUse++;
+
+ in = yaffs_FindOrCreateObjectByNumber(dev,
+ tags.
+ objectId,
+ YAFFS_OBJECT_TYPE_FILE);
+ if(!in){
+ /* Out of memory */
+ alloc_failed = 1;
+ }
+
+ if (in &&
+ in->variantType == YAFFS_OBJECT_TYPE_FILE
+ && chunkBase <
+ in->variant.fileVariant.shrinkSize) {
+ /* This has not been invalidated by a resize */
+ if(!yaffs_PutChunkIntoFile(in, tags.chunkId,
+ chunk, -1)){
+ alloc_failed = 1;
+ }
+
+ /* File size is calculated by looking at the data chunks if we have not
+ * seen an object header yet. Stop this practice once we find an object header.
+ */
+ endpos =
+ (tags.chunkId -
+ 1) * dev->nDataBytesPerChunk +
+ tags.byteCount;
+
+ if (!in->valid && /* have not got an object header yet */
+ in->variant.fileVariant.
+ scannedFileSize < endpos) {
+ in->variant.fileVariant.
+ scannedFileSize = endpos;
+ in->variant.fileVariant.
+ fileSize =
+ in->variant.fileVariant.
+ scannedFileSize;
+ }
+
+ } else if(in) {
+ /* This chunk has been invalidated by a resize, so delete */
+ yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
+
+ }
+ } else {
+ /* chunkId == 0, so it is an ObjectHeader.
+ * Thus, we read in the object header and make the object
+ */
+ foundChunksInBlock = 1;
+
+ yaffs_SetChunkBit(dev, blk, c);
+ bi->pagesInUse++;
+
+ oh = NULL;
+ in = NULL;
+
+ if (tags.extraHeaderInfoAvailable) {
+ in = yaffs_FindOrCreateObjectByNumber
+ (dev, tags.objectId,
+ tags.extraObjectType);
+ }
+
+ if (!in ||
+#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
+ !in->valid ||
+#endif
+ tags.extraShadows ||
+ (!in->valid &&
+ (tags.objectId == YAFFS_OBJECTID_ROOT ||
+ tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))
+ ) {
+
+ /* If we don't have valid info then we need to read the chunk
+ * TODO In future we can probably defer reading the chunk and
+ * living with invalid data until needed.
+ */
+
+ result = yaffs_ReadChunkWithTagsFromNAND(dev,
+ chunk,
+ chunkData,
+ NULL);
+
+ oh = (yaffs_ObjectHeader *) chunkData;
+
+ if (!in)
+ in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
+
+ }
+
+ if (!in) {
+ /* TODO Hoosterman we have a problem! */
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("yaffs tragedy: Could not make object for object %d "
+ "at chunk %d during scan"
+ TENDSTR), tags.objectId, chunk));
+
+ }
+
+ if (in->valid) {
+ /* We have already filled this one.
+ * We have a duplicate that will be discarded, but
+ * we first have to suck out resize info if it is a file.
+ */
+
+ if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
+ ((oh &&
+ oh-> type == YAFFS_OBJECT_TYPE_FILE)||
+ (tags.extraHeaderInfoAvailable &&
+ tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
+ ) {
+ __u32 thisSize =
+ (oh) ? oh->fileSize : tags.
+ extraFileLength;
+ __u32 parentObjectId =
+ (oh) ? oh->
+ parentObjectId : tags.
+ extraParentObjectId;
+ unsigned isShrink =
+ (oh) ? oh->isShrink : tags.
+ extraIsShrinkHeader;
+
+ /* If it is deleted (unlinked at start also means deleted)
+ * we treat the file size as being zeroed at this point.
+ */
+ if (parentObjectId ==
+ YAFFS_OBJECTID_DELETED
+ || parentObjectId ==
+ YAFFS_OBJECTID_UNLINKED) {
+ thisSize = 0;
+ isShrink = 1;
+ }
+
+ if (isShrink &&
+ in->variant.fileVariant.
+ shrinkSize > thisSize) {
+ in->variant.fileVariant.
+ shrinkSize =
+ thisSize;
+ }
+
+ if (isShrink) {
+ bi->hasShrinkHeader = 1;
+ }
+
+ }
+ /* Use existing - destroy this one. */
+ yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
+
+ }
+
+ if (!in->valid &&
+ (tags.objectId == YAFFS_OBJECTID_ROOT ||
+ tags.objectId ==
+ YAFFS_OBJECTID_LOSTNFOUND)) {
+ /* We only load some info, don't fiddle with directory structure */
+ in->valid = 1;
+
+ if(oh) {
+ in->variantType = oh->type;
+
+ in->yst_mode = oh->yst_mode;
+#ifdef CONFIG_YAFFS_WINCE
+ in->win_atime[0] = oh->win_atime[0];
+ in->win_ctime[0] = oh->win_ctime[0];
+ in->win_mtime[0] = oh->win_mtime[0];
+ in->win_atime[1] = oh->win_atime[1];
+ in->win_ctime[1] = oh->win_ctime[1];
+ in->win_mtime[1] = oh->win_mtime[1];
+#else
+ in->yst_uid = oh->yst_uid;
+ in->yst_gid = oh->yst_gid;
+ in->yst_atime = oh->yst_atime;
+ in->yst_mtime = oh->yst_mtime;
+ in->yst_ctime = oh->yst_ctime;
+ in->yst_rdev = oh->yst_rdev;
+
+#endif
+ } else {
+ in->variantType = tags.extraObjectType;
+ in->lazyLoaded = 1;
+ }
+
+ in->chunkId = chunk;
+
+ } else if (!in->valid) {
+ /* we need to load this info */
+
+ in->valid = 1;
+ in->chunkId = chunk;
+
+ if(oh) {
+ in->variantType = oh->type;
+
+ in->yst_mode = oh->yst_mode;
+#ifdef CONFIG_YAFFS_WINCE
+ in->win_atime[0] = oh->win_atime[0];
+ in->win_ctime[0] = oh->win_ctime[0];
+ in->win_mtime[0] = oh->win_mtime[0];
+ in->win_atime[1] = oh->win_atime[1];
+ in->win_ctime[1] = oh->win_ctime[1];
+ in->win_mtime[1] = oh->win_mtime[1];
+#else
+ in->yst_uid = oh->yst_uid;
+ in->yst_gid = oh->yst_gid;
+ in->yst_atime = oh->yst_atime;
+ in->yst_mtime = oh->yst_mtime;
+ in->yst_ctime = oh->yst_ctime;
+ in->yst_rdev = oh->yst_rdev;
+#endif
+
+ if (oh->shadowsObject > 0)
+ yaffs_HandleShadowedObject(dev,
+ oh->
+ shadowsObject,
+ 1);
+
+
+ yaffs_SetObjectName(in, oh->name);
+ parent =
+ yaffs_FindOrCreateObjectByNumber
+ (dev, oh->parentObjectId,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+
+ fileSize = oh->fileSize;
+ isShrink = oh->isShrink;
+ equivalentObjectId = oh->equivalentObjectId;
+
+ }
+ else {
+ in->variantType = tags.extraObjectType;
+ parent =
+ yaffs_FindOrCreateObjectByNumber
+ (dev, tags.extraParentObjectId,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+ fileSize = tags.extraFileLength;
+ isShrink = tags.extraIsShrinkHeader;
+ equivalentObjectId = tags.extraEquivalentObjectId;
+ in->lazyLoaded = 1;
+
+ }
+ in->dirty = 0;
+
+ /* directory stuff...
+ * hook up to parent
+ */
+
+ if (parent->variantType ==
+ YAFFS_OBJECT_TYPE_UNKNOWN) {
+ /* Set up as a directory */
+ parent->variantType =
+ YAFFS_OBJECT_TYPE_DIRECTORY;
+ INIT_LIST_HEAD(&parent->variant.
+ directoryVariant.
+ children);
+ } else if (parent->variantType !=
+ YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ /* Hoosterman, another problem....
+ * We're trying to use a non-directory as a directory
+ */
+
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("yaffs tragedy: attempting to use non-directory as"
+ " a directory in scan. Put in lost+found."
+ TENDSTR)));
+ parent = dev->lostNFoundDir;
+ }
+
+ yaffs_AddObjectToDirectory(parent, in);
+
+ itsUnlinked = (parent == dev->deletedDir) ||
+ (parent == dev->unlinkedDir);
+
+ if (isShrink) {
+ /* Mark the block as having a shrinkHeader */
+ bi->hasShrinkHeader = 1;
+ }
+
+ /* Note re hardlinks.
+ * Since we might scan a hardlink before its equivalent object is scanned
+ * we put them all in a list.
+ * After scanning is complete, we should have all the objects, so we run
+ * through this list and fix up all the chains.
+ */
+
+ switch (in->variantType) {
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* Todo got a problem */
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+
+ if (in->variant.fileVariant.
+ scannedFileSize < fileSize) {
+ /* This covers the case where the file size is greater
+ * than where the data is
+ * This will happen if the file is resized to be larger
+ * than its current data extents.
+ */
+ in->variant.fileVariant.fileSize = fileSize;
+ in->variant.fileVariant.scannedFileSize =
+ in->variant.fileVariant.fileSize;
+ }
+
+ if (isShrink &&
+ in->variant.fileVariant.shrinkSize > fileSize) {
+ in->variant.fileVariant.shrinkSize = fileSize;
+ }
+
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ if(!itsUnlinked) {
+ in->variant.hardLinkVariant.equivalentObjectId =
+ equivalentObjectId;
+ in->hardLinks.next =
+ (struct list_head *) hardList;
+ hardList = in;
+ }
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ if(oh){
+ in->variant.symLinkVariant.alias =
+ yaffs_CloneString(oh->
+ alias);
+ if(!in->variant.symLinkVariant.alias)
+ alloc_failed = 1;
+ }
+ break;
+ }
+
+ }
+
+ }
+
+ } /* End of scanning for each chunk */
+
+ if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
+ /* If we got this far while scanning, then the block is fully allocated. */
+ state = YAFFS_BLOCK_STATE_FULL;
+ }
+
+ bi->blockState = state;
+
+ /* Now let's see if it was dirty */
+ if (bi->pagesInUse == 0 &&
+ !bi->hasShrinkHeader &&
+ bi->blockState == YAFFS_BLOCK_STATE_FULL) {
+ yaffs_BlockBecameDirty(dev, blk);
+ }
+
+ }
+
+ if (altBlockIndex)
+ YFREE_ALT(blockIndex);
+ else
+ YFREE(blockIndex);
+
+ /* Ok, we've done all the scanning.
+ * Fix up the hard link chains.
+ * We should now have scanned all the objects, now it's time to add these
+ * hardlinks.
+ */
+ yaffs_HardlinkFixup(dev,hardList);
+
+
+ /*
+ * Sort out state of unlinked and deleted objects.
+ */
+ {
+ struct list_head *i;
+ struct list_head *n;
+
+ yaffs_Object *l;
+
+ /* Soft delete all the unlinked files */
+ list_for_each_safe(i, n,
+ &dev->unlinkedDir->variant.directoryVariant.
+ children) {
+ if (i) {
+ l = list_entry(i, yaffs_Object, siblings);
+ yaffs_DestroyObject(l);
+ }
+ }
+
+ /* Soft delete all the deletedDir files */
+ list_for_each_safe(i, n,
+ &dev->deletedDir->variant.directoryVariant.
+ children) {
+ if (i) {
+ l = list_entry(i, yaffs_Object, siblings);
+ yaffs_DestroyObject(l);
+
+ }
+ }
+ }
+
+ yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
+
+ if(alloc_failed){
+ return YAFFS_FAIL;
+ }
+
+ T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
+
+ return YAFFS_OK;
+}
+
+/*------------------------------ Directory Functions ----------------------------- */
+
+static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
+{
+ yaffs_Device *dev = obj->myDev;
+
+ if(dev && dev->removeObjectCallback)
+ dev->removeObjectCallback(obj);
+
+ list_del_init(&obj->siblings);
+ obj->parent = NULL;
+}
+
+
+static void yaffs_AddObjectToDirectory(yaffs_Object * directory,
+ yaffs_Object * obj)
+{
+
+ if (!directory) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("tragedy: Trying to add an object to a null pointer directory"
+ TENDSTR)));
+ YBUG();
+ }
+ if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("tragedy: Trying to add an object to a non-directory"
+ TENDSTR)));
+ YBUG();
+ }
+
+ if (obj->siblings.prev == NULL) {
+ /* Not initialised */
+ INIT_LIST_HEAD(&obj->siblings);
+
+ } else if (!list_empty(&obj->siblings)) {
+ /* If it is holed up somewhere else, un hook it */
+ yaffs_RemoveObjectFromDirectory(obj);
+ }
+ /* Now add it */
+ list_add(&obj->siblings, &directory->variant.directoryVariant.children);
+ obj->parent = directory;
+
+ if (directory == obj->myDev->unlinkedDir
+ || directory == obj->myDev->deletedDir) {
+ obj->unlinked = 1;
+ obj->myDev->nUnlinkedFiles++;
+ obj->renameAllowed = 0;
+ }
+}
+
+yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
+ const YCHAR * name)
+{
+ int sum;
+
+ struct list_head *i;
+ YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
+
+ yaffs_Object *l;
+
+ if (!name) {
+ return NULL;
+ }
+
+ if (!directory) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("tragedy: yaffs_FindObjectByName: null pointer directory"
+ TENDSTR)));
+ YBUG();
+ }
+ if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
+ YBUG();
+ }
+
+ sum = yaffs_CalcNameSum(name);
+
+ list_for_each(i, &directory->variant.directoryVariant.children) {
+ if (i) {
+ l = list_entry(i, yaffs_Object, siblings);
+
+ yaffs_CheckObjectDetailsLoaded(l);
+
+ /* Special case for lost-n-found */
+ if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
+ if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) {
+ return l;
+ }
+ } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0)
+ {
+ /* LostnFound cunk called Objxxx
+ * Do a real check
+ */
+ yaffs_GetObjectName(l, buffer,
+ YAFFS_MAX_NAME_LENGTH);
+ if (yaffs_strncmp(name, buffer,YAFFS_MAX_NAME_LENGTH) == 0) {
+ return l;
+ }
+
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+#if 0
+int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
+ int (*fn) (yaffs_Object *))
+{
+ struct list_head *i;
+ yaffs_Object *l;
+
+ if (!theDir) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("tragedy: yaffs_FindObjectByName: null pointer directory"
+ TENDSTR)));
+ YBUG();
+ }
+ if (theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
+ YBUG();
+ }
+
+ list_for_each(i, &theDir->variant.directoryVariant.children) {
+ if (i) {
+ l = list_entry(i, yaffs_Object, siblings);
+ if (l && !fn(l)) {
+ return YAFFS_FAIL;
+ }
+ }
+ }
+
+ return YAFFS_OK;
+
+}
+#endif
+
+/* GetEquivalentObject dereferences any hard links to get to the
+ * actual object.
+ */
+
+yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj)
+{
+ if (obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
+ /* We want the object id of the equivalent object, not this one */
+ obj = obj->variant.hardLinkVariant.equivalentObject;
+ yaffs_CheckObjectDetailsLoaded(obj);
+ }
+ return obj;
+
+}
+
+int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
+{
+ memset(name, 0, buffSize * sizeof(YCHAR));
+
+ yaffs_CheckObjectDetailsLoaded(obj);
+
+ if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
+ yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
+ } else if (obj->chunkId <= 0) {
+ YCHAR locName[20];
+ /* make up a name */
+ yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX,
+ obj->objectId);
+ yaffs_strncpy(name, locName, buffSize - 1);
+
+ }
+#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
+ else if (obj->shortName[0]) {
+ yaffs_strcpy(name, obj->shortName);
+ }
+#endif
+ else {
+ int result;
+ __u8 *buffer = yaffs_GetTempBuffer(obj->myDev, __LINE__);
+
+ yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *) buffer;
+
+ memset(buffer, 0, obj->myDev->nDataBytesPerChunk);
+
+ if (obj->chunkId >= 0) {
+ result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,
+ obj->chunkId, buffer,
+ NULL);
+ }
+ yaffs_strncpy(name, oh->name, buffSize - 1);
+
+ yaffs_ReleaseTempBuffer(obj->myDev, buffer, __LINE__);
+ }
+
+ return yaffs_strlen(name);
+}
+
+int yaffs_GetObjectFileLength(yaffs_Object * obj)
+{
+
+ /* Dereference any hard linking */
+ obj = yaffs_GetEquivalentObject(obj);
+
+ if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
+ return obj->variant.fileVariant.fileSize;
+ }
+ if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
+ return yaffs_strlen(obj->variant.symLinkVariant.alias);
+ } else {
+ /* Only a directory should drop through to here */
+ return obj->myDev->nDataBytesPerChunk;
+ }
+}
+
+int yaffs_GetObjectLinkCount(yaffs_Object * obj)
+{
+ int count = 0;
+ struct list_head *i;
+
+ if (!obj->unlinked) {
+ count++; /* the object itself */
+ }
+ list_for_each(i, &obj->hardLinks) {
+ count++; /* add the hard links; */
+ }
+ return count;
+
+}
+
+int yaffs_GetObjectInode(yaffs_Object * obj)
+{
+ obj = yaffs_GetEquivalentObject(obj);
+
+ return obj->objectId;
+}
+
+unsigned yaffs_GetObjectType(yaffs_Object * obj)
+{
+ obj = yaffs_GetEquivalentObject(obj);
+
+ switch (obj->variantType) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ return DT_REG;
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ return DT_DIR;
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ return DT_LNK;
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ return DT_REG;
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ if (S_ISFIFO(obj->yst_mode))
+ return DT_FIFO;
+ if (S_ISCHR(obj->yst_mode))
+ return DT_CHR;
+ if (S_ISBLK(obj->yst_mode))
+ return DT_BLK;
+ if (S_ISSOCK(obj->yst_mode))
+ return DT_SOCK;
+ default:
+ return DT_REG;
+ break;
+ }
+}
+
+YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj)
+{
+ obj = yaffs_GetEquivalentObject(obj);
+ if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
+ return yaffs_CloneString(obj->variant.symLinkVariant.alias);
+ } else {
+ return yaffs_CloneString(_Y(""));
+ }
+}
+
+#ifndef CONFIG_YAFFS_WINCE
+
+int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr)
+{
+ unsigned int valid = attr->ia_valid;
+
+ if (valid & ATTR_MODE)
+ obj->yst_mode = attr->ia_mode;
+ if (valid & ATTR_UID)
+ obj->yst_uid = attr->ia_uid;
+ if (valid & ATTR_GID)
+ obj->yst_gid = attr->ia_gid;
+
+ if (valid & ATTR_ATIME)
+ obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
+ if (valid & ATTR_CTIME)
+ obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
+ if (valid & ATTR_MTIME)
+ obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
+
+ if (valid & ATTR_SIZE)
+ yaffs_ResizeFile(obj, attr->ia_size);
+
+ yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0);
+
+ return YAFFS_OK;
+
+}
+int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr)
+{
+ unsigned int valid = 0;
+
+ attr->ia_mode = obj->yst_mode;
+ valid |= ATTR_MODE;
+ attr->ia_uid = obj->yst_uid;
+ valid |= ATTR_UID;
+ attr->ia_gid = obj->yst_gid;
+ valid |= ATTR_GID;
+
+ Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
+ valid |= ATTR_ATIME;
+ Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
+ valid |= ATTR_CTIME;
+ Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
+ valid |= ATTR_MTIME;
+
+ attr->ia_size = yaffs_GetFileSize(obj);
+ valid |= ATTR_SIZE;
+
+ attr->ia_valid = valid;
+
+ return YAFFS_OK;
+
+}
+
+#endif
+
+#if 0
+int yaffs_DumpObject(yaffs_Object * obj)
+{
+ YCHAR name[257];
+
+ yaffs_GetObjectName(obj, name, 256);
+
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"
+ " chunk %d type %d size %d\n"
+ TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name,
+ obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId,
+ yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
+
+ return YAFFS_OK;
+}
+#endif
+
+/*---------------------------- Initialisation code -------------------------------------- */
+
+static int yaffs_CheckDevFunctions(const yaffs_Device * dev)
+{
+
+ /* Common functions, gotta have */
+ if (!dev->eraseBlockInNAND || !dev->initialiseNAND)
+ return 0;
+
+#ifdef CONFIG_YAFFS_YAFFS2
+
+ /* Can use the "with tags" style interface for yaffs1 or yaffs2 */
+ if (dev->writeChunkWithTagsToNAND &&
+ dev->readChunkWithTagsFromNAND &&
+ !dev->writeChunkToNAND &&
+ !dev->readChunkFromNAND &&
+ dev->markNANDBlockBad && dev->queryNANDBlock)
+ return 1;
+#endif
+
+ /* Can use the "spare" style interface for yaffs1 */
+ if (!dev->isYaffs2 &&
+ !dev->writeChunkWithTagsToNAND &&
+ !dev->readChunkWithTagsFromNAND &&
+ dev->writeChunkToNAND &&
+ dev->readChunkFromNAND &&
+ !dev->markNANDBlockBad && !dev->queryNANDBlock)
+ return 1;
+
+ return 0; /* bad */
+}
+
+
+static int yaffs_CreateInitialDirectories(yaffs_Device *dev)
+{
+ /* Initialise the unlinked, deleted, root and lost and found directories */
+
+ dev->lostNFoundDir = dev->rootDir = NULL;
+ dev->unlinkedDir = dev->deletedDir = NULL;
+
+ dev->unlinkedDir =
+ yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
+
+ dev->deletedDir =
+ yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
+
+ dev->rootDir =
+ yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_ROOT,
+ YAFFS_ROOT_MODE | S_IFDIR);
+ dev->lostNFoundDir =
+ yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND,
+ YAFFS_LOSTNFOUND_MODE | S_IFDIR);
+
+ if(dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir){
+ yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir);
+ return YAFFS_OK;
+ }
+
+ return YAFFS_FAIL;
+}
+
+int yaffs_GutsInitialise(yaffs_Device * dev)
+{
+ int init_failed = 0;
+ unsigned x;
+ int bits;
+
+ T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR)));
+
+ /* Check stuff that must be set */
+
+ if (!dev) {
+ T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Need a device" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ dev->internalStartBlock = dev->startBlock;
+ dev->internalEndBlock = dev->endBlock;
+ dev->blockOffset = 0;
+ dev->chunkOffset = 0;
+ dev->nFreeChunks = 0;
+
+ if (dev->startBlock == 0) {
+ dev->internalStartBlock = dev->startBlock + 1;
+ dev->internalEndBlock = dev->endBlock + 1;
+ dev->blockOffset = 1;
+ dev->chunkOffset = dev->nChunksPerBlock;
+ }
+
+ /* Check geometry parameters. */
+
+ if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
+ (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
+ dev->nChunksPerBlock < 2 ||
+ dev->nReservedBlocks < 2 ||
+ dev->internalStartBlock <= 0 ||
+ dev->internalEndBlock <= 0 ||
+ dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2) // otherwise it is too small
+ ) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
+ TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
+ return YAFFS_FAIL;
+ }
+
+ if (yaffs_InitialiseNAND(dev) != YAFFS_OK) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ /* Got the right mix of functions? */
+ if (!yaffs_CheckDevFunctions(dev)) {
+ /* Function missing */
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR
+ ("yaffs: device function(s) missing or wrong\n" TENDSTR)));
+
+ return YAFFS_FAIL;
+ }
+
+ /* This is really a compilation check. */
+ if (!yaffs_CheckStructures()) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs_CheckStructures failed\n" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ if (dev->isMounted) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs: device already mounted\n" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ /* Finished with most checks. One or two more checks happen later on too. */
+
+ dev->isMounted = 1;
+
+
+
+ /* OK now calculate a few things for the device */
+
+ /*
+ * Calculate all the chunk size manipulation numbers:
+ */
+ /* Start off assuming it is a power of 2 */
+ dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
+ dev->chunkMask = (1<<dev->chunkShift) - 1;
+
+ if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
+ /* Yes it is a power of 2, disable crumbs */
+ dev->crumbMask = 0;
+ dev->crumbShift = 0;
+ dev->crumbsPerChunk = 0;
+ } else {
+ /* Not a power of 2, use crumbs instead */
+ dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
+ dev->crumbMask = (1<<dev->crumbShift)-1;
+ dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
+ dev->chunkShift = 0;
+ dev->chunkMask = 0;
+ }
+
+
+ /*
+ * Calculate chunkGroupBits.
+ * We need to find the next power of 2 > than internalEndBlock
+ */
+
+ x = dev->nChunksPerBlock * (dev->internalEndBlock + 1);
+
+ bits = ShiftsGE(x);
+
+ /* Set up tnode width if wide tnodes are enabled. */
+ if(!dev->wideTnodesDisabled){
+ /* bits must be even so that we end up with 32-bit words */
+ if(bits & 1)
+ bits++;
+ if(bits < 16)
+ dev->tnodeWidth = 16;
+ else
+ dev->tnodeWidth = bits;
+ }
+ else
+ dev->tnodeWidth = 16;
+
+ dev->tnodeMask = (1<<dev->tnodeWidth)-1;
+
+ /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
+ * so if the bitwidth of the
+ * chunk range we're using is greater than 16 we need
+ * to figure out chunk shift and chunkGroupSize
+ */
+
+ if (bits <= dev->tnodeWidth)
+ dev->chunkGroupBits = 0;
+ else
+ dev->chunkGroupBits = bits - dev->tnodeWidth;
+
+
+ dev->chunkGroupSize = 1 << dev->chunkGroupBits;
+
+ if (dev->nChunksPerBlock < dev->chunkGroupSize) {
+ /* We have a problem because the soft delete won't work if
+ * the chunk group size > chunks per block.
+ * This can be remedied by using larger "virtual blocks".
+ */
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs: chunk group too large\n" TENDSTR)));
+
+ return YAFFS_FAIL;
+ }
+
+ /* OK, we've finished verifying the device, lets continue with initialisation */
+
+ /* More device initialisation */
+ dev->garbageCollections = 0;
+ dev->passiveGarbageCollections = 0;
+ dev->currentDirtyChecker = 0;
+ dev->bufferedBlock = -1;
+ dev->doingBufferedBlockRewrite = 0;
+ dev->nDeletedFiles = 0;
+ dev->nBackgroundDeletions = 0;
+ dev->nUnlinkedFiles = 0;
+ dev->eccFixed = 0;
+ dev->eccUnfixed = 0;
+ dev->tagsEccFixed = 0;
+ dev->tagsEccUnfixed = 0;
+ dev->nErasureFailures = 0;
+ dev->nErasedBlocks = 0;
+ dev->isDoingGC = 0;
+ dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */
+
+ /* Initialise temporary buffers and caches. */
+ if(!yaffs_InitialiseTempBuffers(dev))
+ init_failed = 1;
+
+ dev->srCache = NULL;
+ dev->gcCleanupList = NULL;
+
+
+ if (!init_failed &&
+ dev->nShortOpCaches > 0) {
+ int i;
+ __u8 *buf;
+ int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache);
+
+ if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
+ dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES;
+ }
+
+ buf = dev->srCache = YMALLOC(srCacheBytes);
+
+ if(dev->srCache)
+ memset(dev->srCache,0,srCacheBytes);
+
+ for (i = 0; i < dev->nShortOpCaches && buf; i++) {
+ dev->srCache[i].object = NULL;
+ dev->srCache[i].lastUse = 0;
+ dev->srCache[i].dirty = 0;
+ dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk);
+ }
+ if(!buf)
+ init_failed = 1;
+
+ dev->srLastUse = 0;
+ }
+
+ dev->cacheHits = 0;
+
+ if(!init_failed){
+ dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32));
+ if(!dev->gcCleanupList)
+ init_failed = 1;
+ }
+
+ if (dev->isYaffs2) {
+ dev->useHeaderFileSize = 1;
+ }
+ if(!init_failed && !yaffs_InitialiseBlocks(dev))
+ init_failed = 1;
+
+ yaffs_InitialiseTnodes(dev);
+ yaffs_InitialiseObjects(dev);
+
+ if(!init_failed && !yaffs_CreateInitialDirectories(dev))
+ init_failed = 1;
+
+
+ if(!init_failed){
+ /* Now scan the flash. */
+ if (dev->isYaffs2) {
+ if(yaffs_CheckpointRestore(dev)) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs: restored from checkpoint" TENDSTR)));
+ } else {
+
+ /* Clean up the mess caused by an aborted checkpoint load
+ * and scan backwards.
+ */
+ yaffs_DeinitialiseBlocks(dev);
+ yaffs_DeinitialiseTnodes(dev);
+ yaffs_DeinitialiseObjects(dev);
+
+
+ dev->nErasedBlocks = 0;
+ dev->nFreeChunks = 0;
+ dev->allocationBlock = -1;
+ dev->allocationPage = -1;
+ dev->nDeletedFiles = 0;
+ dev->nUnlinkedFiles = 0;
+ dev->nBackgroundDeletions = 0;
+ dev->oldestDirtySequence = 0;
+
+ if(!init_failed && !yaffs_InitialiseBlocks(dev))
+ init_failed = 1;
+
+ yaffs_InitialiseTnodes(dev);
+ yaffs_InitialiseObjects(dev);
+
+ if(!init_failed && !yaffs_CreateInitialDirectories(dev))
+ init_failed = 1;
+
+ if(!init_failed && !yaffs_ScanBackwards(dev))
+ init_failed = 1;
+ }
+ }else
+ if(!yaffs_Scan(dev))
+ init_failed = 1;
+ }
+
+ if(init_failed){
+ /* Clean up the mess */
+ T(YAFFS_TRACE_TRACING,
+ (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR)));
+
+ yaffs_Deinitialise(dev);
+ return YAFFS_FAIL;
+ }
+
+ /* Zero out stats */
+ dev->nPageReads = 0;
+ dev->nPageWrites = 0;
+ dev->nBlockErasures = 0;
+ dev->nGCCopies = 0;
+ dev->nRetriedWrites = 0;
+
+ dev->nRetiredBlocks = 0;
+
+ yaffs_VerifyFreeChunks(dev);
+ yaffs_VerifyBlocks(dev);
+
+
+ T(YAFFS_TRACE_TRACING,
+ (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
+ return YAFFS_OK;
+
+}
+
+void yaffs_Deinitialise(yaffs_Device * dev)
+{
+ if (dev->isMounted) {
+ int i;
+
+ yaffs_DeinitialiseBlocks(dev);
+ yaffs_DeinitialiseTnodes(dev);
+ yaffs_DeinitialiseObjects(dev);
+ if (dev->nShortOpCaches > 0 &&
+ dev->srCache) {
+
+ for (i = 0; i < dev->nShortOpCaches; i++) {
+ if(dev->srCache[i].data)
+ YFREE(dev->srCache[i].data);
+ dev->srCache[i].data = NULL;
+ }
+
+ YFREE(dev->srCache);
+ dev->srCache = NULL;
+ }
+
+ YFREE(dev->gcCleanupList);
+
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ YFREE(dev->tempBuffer[i].buffer);
+ }
+
+ dev->isMounted = 0;
+ }
+
+}
+
+static int yaffs_CountFreeChunks(yaffs_Device * dev)
+{
+ int nFree;
+ int b;
+
+ yaffs_BlockInfo *blk;
+
+ for (nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock;
+ b++) {
+ blk = yaffs_GetBlockInfo(dev, b);
+
+ switch (blk->blockState) {
+ case YAFFS_BLOCK_STATE_EMPTY:
+ case YAFFS_BLOCK_STATE_ALLOCATING:
+ case YAFFS_BLOCK_STATE_COLLECTING:
+ case YAFFS_BLOCK_STATE_FULL:
+ nFree +=
+ (dev->nChunksPerBlock - blk->pagesInUse +
+ blk->softDeletions);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ return nFree;
+}
+
+int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev)
+{
+ /* This is what we report to the outside world */
+
+ int nFree;
+ int nDirtyCacheChunks;
+ int blocksForCheckpoint;
+
+#if 1
+ nFree = dev->nFreeChunks;
+#else
+ nFree = yaffs_CountFreeChunks(dev);
+#endif
+
+ nFree += dev->nDeletedFiles;
+
+ /* Now count the number of dirty chunks in the cache and subtract those */
+
+ {
+ int i;
+ for (nDirtyCacheChunks = 0, i = 0; i < dev->nShortOpCaches; i++) {
+ if (dev->srCache[i].dirty)
+ nDirtyCacheChunks++;
+ }
+ }
+
+ nFree -= nDirtyCacheChunks;
+
+ nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
+
+ /* Now we figure out how much to reserve for the checkpoint and report that... */
+ blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
+ if(blocksForCheckpoint < 0)
+ blocksForCheckpoint = 0;
+
+ nFree -= (blocksForCheckpoint * dev->nChunksPerBlock);
+
+ if (nFree < 0)
+ nFree = 0;
+
+ return nFree;
+
+}
+
+static int yaffs_freeVerificationFailures;
+
+static void yaffs_VerifyFreeChunks(yaffs_Device * dev)
+{
+ int counted;
+ int difference;
+
+ if(yaffs_SkipVerification(dev))
+ return;
+
+ counted = yaffs_CountFreeChunks(dev);
+
+ difference = dev->nFreeChunks - counted;
+
+ if (difference) {
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("Freechunks verification failure %d %d %d" TENDSTR),
+ dev->nFreeChunks, counted, difference));
+ yaffs_freeVerificationFailures++;
+ }
+}
+
+/*---------------------------------------- YAFFS test code ----------------------*/
+
+#define yaffs_CheckStruct(structure,syze, name) \
+ if(sizeof(structure) != syze) \
+ { \
+ T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
+ name,syze,sizeof(structure))); \
+ return YAFFS_FAIL; \
+ }
+
+static int yaffs_CheckStructures(void)
+{
+/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
+/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
+/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
+#ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
+#endif
+ yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
+
+ return YAFFS_OK;
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_GUTS_H__
+#define __YAFFS_GUTS_H__
+
+#include "devextras.h"
+#include "yportenv.h"
+
+#define YAFFS_OK 1
+#define YAFFS_FAIL 0
+
+/* Give us a Y=0x59,
+ * Give us an A=0x41,
+ * Give us an FF=0xFF
+ * Give us an S=0x53
+ * And what have we got...
+ */
+#define YAFFS_MAGIC 0x5941FF53
+
+#define YAFFS_NTNODES_LEVEL0 16
+#define YAFFS_TNODES_LEVEL0_BITS 4
+#define YAFFS_TNODES_LEVEL0_MASK 0xf
+
+#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2)
+#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1)
+#define YAFFS_TNODES_INTERNAL_MASK 0x7
+#define YAFFS_TNODES_MAX_LEVEL 6
+
+#ifndef CONFIG_YAFFS_NO_YAFFS1
+#define YAFFS_BYTES_PER_SPARE 16
+#define YAFFS_BYTES_PER_CHUNK 512
+#define YAFFS_CHUNK_SIZE_SHIFT 9
+#define YAFFS_CHUNKS_PER_BLOCK 32
+#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
+#endif
+
+#define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024
+#define YAFFS_MIN_YAFFS2_SPARE_SIZE 32
+
+#define YAFFS_MAX_CHUNK_ID 0x000FFFFF
+
+#define YAFFS_UNUSED_OBJECT_ID 0x0003FFFF
+
+#define YAFFS_ALLOCATION_NOBJECTS 100
+#define YAFFS_ALLOCATION_NTNODES 100
+#define YAFFS_ALLOCATION_NLINKS 100
+
+#define YAFFS_NOBJECT_BUCKETS 256
+
+
+#define YAFFS_OBJECT_SPACE 0x40000
+
+#define YAFFS_CHECKPOINT_VERSION 3
+
+#ifdef CONFIG_YAFFS_UNICODE
+#define YAFFS_MAX_NAME_LENGTH 127
+#define YAFFS_MAX_ALIAS_LENGTH 79
+#else
+#define YAFFS_MAX_NAME_LENGTH 255
+#define YAFFS_MAX_ALIAS_LENGTH 159
+#endif
+
+#define YAFFS_SHORT_NAME_LENGTH 15
+
+/* Some special object ids for pseudo objects */
+#define YAFFS_OBJECTID_ROOT 1
+#define YAFFS_OBJECTID_LOSTNFOUND 2
+#define YAFFS_OBJECTID_UNLINKED 3
+#define YAFFS_OBJECTID_DELETED 4
+
+/* Sseudo object ids for checkpointing */
+#define YAFFS_OBJECTID_SB_HEADER 0x10
+#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20
+#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21
+
+/* */
+
+#define YAFFS_MAX_SHORT_OP_CACHES 20
+
+#define YAFFS_N_TEMP_BUFFERS 4
+
+/* We limit the number attempts at sucessfully saving a chunk of data.
+ * Small-page devices have 32 pages per block; large-page devices have 64.
+ * Default to something in the order of 5 to 10 blocks worth of chunks.
+ */
+#define YAFFS_WR_ATTEMPTS (5*64)
+
+/* Sequence numbers are used in YAFFS2 to determine block allocation order.
+ * The range is limited slightly to help distinguish bad numbers from good.
+ * This also allows us to perhaps in the future use special numbers for
+ * special purposes.
+ * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
+ * and is a larger number than the lifetime of a 2GB device.
+ */
+#define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000
+#define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xEFFFFF00
+
+/* ChunkCache is used for short read/write operations.*/
+typedef struct {
+ struct yaffs_ObjectStruct *object;
+ int chunkId;
+ int lastUse;
+ int dirty;
+ int nBytes; /* Only valid if the cache is dirty */
+ int locked; /* Can't push out or flush while locked. */
+#ifdef CONFIG_YAFFS_YAFFS2
+ __u8 *data;
+#else
+ __u8 data[YAFFS_BYTES_PER_CHUNK];
+#endif
+} yaffs_ChunkCache;
+
+
+
+/* Tags structures in RAM
+ * NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise
+ * the structure size will get blown out.
+ */
+
+#ifndef CONFIG_YAFFS_NO_YAFFS1
+typedef struct {
+ unsigned chunkId:20;
+ unsigned serialNumber:2;
+ unsigned byteCount:10;
+ unsigned objectId:18;
+ unsigned ecc:12;
+ unsigned unusedStuff:2;
+
+} yaffs_Tags;
+
+typedef union {
+ yaffs_Tags asTags;
+ __u8 asBytes[8];
+} yaffs_TagsUnion;
+
+#endif
+
+/* Stuff used for extended tags in YAFFS2 */
+
+typedef enum {
+ YAFFS_ECC_RESULT_UNKNOWN,
+ YAFFS_ECC_RESULT_NO_ERROR,
+ YAFFS_ECC_RESULT_FIXED,
+ YAFFS_ECC_RESULT_UNFIXED
+} yaffs_ECCResult;
+
+typedef enum {
+ YAFFS_OBJECT_TYPE_UNKNOWN,
+ YAFFS_OBJECT_TYPE_FILE,
+ YAFFS_OBJECT_TYPE_SYMLINK,
+ YAFFS_OBJECT_TYPE_DIRECTORY,
+ YAFFS_OBJECT_TYPE_HARDLINK,
+ YAFFS_OBJECT_TYPE_SPECIAL
+} yaffs_ObjectType;
+
+#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL
+
+typedef struct {
+
+ unsigned validMarker0;
+ unsigned chunkUsed; /* Status of the chunk: used or unused */
+ unsigned objectId; /* If 0 then this is not part of an object (unused) */
+ unsigned chunkId; /* If 0 then this is a header, else a data chunk */
+ unsigned byteCount; /* Only valid for data chunks */
+
+ /* The following stuff only has meaning when we read */
+ yaffs_ECCResult eccResult;
+ unsigned blockBad;
+
+ /* YAFFS 1 stuff */
+ unsigned chunkDeleted; /* The chunk is marked deleted */
+ unsigned serialNumber; /* Yaffs1 2-bit serial number */
+
+ /* YAFFS2 stuff */
+ unsigned sequenceNumber; /* The sequence number of this block */
+
+ /* Extra info if this is an object header (YAFFS2 only) */
+
+ unsigned extraHeaderInfoAvailable; /* There is extra info available if this is not zero */
+ unsigned extraParentObjectId; /* The parent object */
+ unsigned extraIsShrinkHeader; /* Is it a shrink header? */
+ unsigned extraShadows; /* Does this shadow another object? */
+
+ yaffs_ObjectType extraObjectType; /* What object type? */
+
+ unsigned extraFileLength; /* Length if it is a file */
+ unsigned extraEquivalentObjectId; /* Equivalent object Id if it is a hard link */
+
+ unsigned validMarker1;
+
+} yaffs_ExtendedTags;
+
+/* Spare structure for YAFFS1 */
+typedef struct {
+ __u8 tagByte0;
+ __u8 tagByte1;
+ __u8 tagByte2;
+ __u8 tagByte3;
+ __u8 pageStatus; /* set to 0 to delete the chunk */
+ __u8 blockStatus;
+ __u8 tagByte4;
+ __u8 tagByte5;
+ __u8 ecc1[3];
+ __u8 tagByte6;
+ __u8 tagByte7;
+ __u8 ecc2[3];
+} yaffs_Spare;
+
+/*Special structure for passing through to mtd */
+struct yaffs_NANDSpare {
+ yaffs_Spare spare;
+ int eccres1;
+ int eccres2;
+};
+
+/* Block data in RAM */
+
+typedef enum {
+ YAFFS_BLOCK_STATE_UNKNOWN = 0,
+
+ YAFFS_BLOCK_STATE_SCANNING,
+ YAFFS_BLOCK_STATE_NEEDS_SCANNING,
+ /* The block might have something on it (ie it is allocating or full, perhaps empty)
+ * but it needs to be scanned to determine its true state.
+ * This state is only valid during yaffs_Scan.
+ * NB We tolerate empty because the pre-scanner might be incapable of deciding
+ * However, if this state is returned on a YAFFS2 device, then we expect a sequence number
+ */
+
+ YAFFS_BLOCK_STATE_EMPTY,
+ /* This block is empty */
+
+ YAFFS_BLOCK_STATE_ALLOCATING,
+ /* This block is partially allocated.
+ * At least one page holds valid data.
+ * This is the one currently being used for page
+ * allocation. Should never be more than one of these
+ */
+
+ YAFFS_BLOCK_STATE_FULL,
+ /* All the pages in this block have been allocated.
+ */
+
+ YAFFS_BLOCK_STATE_DIRTY,
+ /* All pages have been allocated and deleted.
+ * Erase me, reuse me.
+ */
+
+ YAFFS_BLOCK_STATE_CHECKPOINT,
+ /* This block is assigned to holding checkpoint data.
+ */
+
+ YAFFS_BLOCK_STATE_COLLECTING,
+ /* This block is being garbage collected */
+
+ YAFFS_BLOCK_STATE_DEAD
+ /* This block has failed and is not in use */
+} yaffs_BlockState;
+
+#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1)
+
+
+typedef struct {
+
+ int softDeletions:10; /* number of soft deleted pages */
+ int pagesInUse:10; /* number of pages in use */
+ unsigned blockState:4; /* One of the above block states. NB use unsigned because enum is sometimes an int */
+ __u32 needsRetiring:1; /* Data has failed on this block, need to get valid data off */
+ /* and retire the block. */
+ __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */
+ __u32 gcPrioritise: 1; /* An ECC check or blank check has failed on this block.
+ It should be prioritised for GC */
+ __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
+
+#ifdef CONFIG_YAFFS_YAFFS2
+ __u32 hasShrinkHeader:1; /* This block has at least one shrink object header */
+ __u32 sequenceNumber; /* block sequence number for yaffs2 */
+#endif
+
+} yaffs_BlockInfo;
+
+/* -------------------------- Object structure -------------------------------*/
+/* This is the object structure as stored on NAND */
+
+typedef struct {
+ yaffs_ObjectType type;
+
+ /* Apply to everything */
+ int parentObjectId;
+ __u16 sum__NoLongerUsed; /* checksum of name. No longer used */
+ YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
+
+ /* Thes following apply to directories, files, symlinks - not hard links */
+ __u32 yst_mode; /* protection */
+
+#ifdef CONFIG_YAFFS_WINCE
+ __u32 notForWinCE[5];
+#else
+ __u32 yst_uid;
+ __u32 yst_gid;
+ __u32 yst_atime;
+ __u32 yst_mtime;
+ __u32 yst_ctime;
+#endif
+
+ /* File size applies to files only */
+ int fileSize;
+
+ /* Equivalent object id applies to hard links only. */
+ int equivalentObjectId;
+
+ /* Alias is for symlinks only. */
+ YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1];
+
+ __u32 yst_rdev; /* device stuff for block and char devices (major/min) */
+
+#ifdef CONFIG_YAFFS_WINCE
+ __u32 win_ctime[2];
+ __u32 win_atime[2];
+ __u32 win_mtime[2];
+ __u32 roomToGrow[4];
+#else
+ __u32 roomToGrow[10];
+#endif
+
+ int shadowsObject; /* This object header shadows the specified object if > 0 */
+
+ /* isShrink applies to object headers written when we shrink the file (ie resize) */
+ __u32 isShrink;
+
+} yaffs_ObjectHeader;
+
+/*--------------------------- Tnode -------------------------- */
+
+union yaffs_Tnode_union {
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+ union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL + 1];
+#else
+ union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL];
+#endif
+/* __u16 level0[YAFFS_NTNODES_LEVEL0]; */
+
+};
+
+typedef union yaffs_Tnode_union yaffs_Tnode;
+
+struct yaffs_TnodeList_struct {
+ struct yaffs_TnodeList_struct *next;
+ yaffs_Tnode *tnodes;
+};
+
+typedef struct yaffs_TnodeList_struct yaffs_TnodeList;
+
+/*------------------------ Object -----------------------------*/
+/* An object can be one of:
+ * - a directory (no data, has children links
+ * - a regular file (data.... not prunes :->).
+ * - a symlink [symbolic link] (the alias).
+ * - a hard link
+ */
+
+typedef struct {
+ __u32 fileSize;
+ __u32 scannedFileSize;
+ __u32 shrinkSize;
+ int topLevel;
+ yaffs_Tnode *top;
+} yaffs_FileStructure;
+
+typedef struct {
+ struct list_head children; /* list of child links */
+} yaffs_DirectoryStructure;
+
+typedef struct {
+ YCHAR *alias;
+} yaffs_SymLinkStructure;
+
+typedef struct {
+ struct yaffs_ObjectStruct *equivalentObject;
+ __u32 equivalentObjectId;
+} yaffs_HardLinkStructure;
+
+typedef union {
+ yaffs_FileStructure fileVariant;
+ yaffs_DirectoryStructure directoryVariant;
+ yaffs_SymLinkStructure symLinkVariant;
+ yaffs_HardLinkStructure hardLinkVariant;
+} yaffs_ObjectVariant;
+
+struct yaffs_ObjectStruct {
+ __u8 deleted:1; /* This should only apply to unlinked files. */
+ __u8 softDeleted:1; /* it has also been soft deleted */
+ __u8 unlinked:1; /* An unlinked file. The file should be in the unlinked directory.*/
+ __u8 fake:1; /* A fake object has no presence on NAND. */
+ __u8 renameAllowed:1; /* Some objects are not allowed to be renamed. */
+ __u8 unlinkAllowed:1;
+ __u8 dirty:1; /* the object needs to be written to flash */
+ __u8 valid:1; /* When the file system is being loaded up, this
+ * object might be created before the data
+ * is available (ie. file data records appear before the header).
+ */
+ __u8 lazyLoaded:1; /* This object has been lazy loaded and is missing some detail */
+
+ __u8 deferedFree:1; /* For Linux kernel. Object is removed from NAND, but is
+ * still in the inode cache. Free of object is defered.
+ * until the inode is released.
+ */
+
+ __u8 serial; /* serial number of chunk in NAND. Cached here */
+ __u16 sum; /* sum of the name to speed searching */
+
+ struct yaffs_DeviceStruct *myDev; /* The device I'm on */
+
+ struct list_head hashLink; /* list of objects in this hash bucket */
+
+ struct list_head hardLinks; /* all the equivalent hard linked objects */
+
+ /* directory structure stuff */
+ /* also used for linking up the free list */
+ struct yaffs_ObjectStruct *parent;
+ struct list_head siblings;
+
+ /* Where's my object header in NAND? */
+ int chunkId;
+
+ int nDataChunks; /* Number of data chunks attached to the file. */
+
+ __u32 objectId; /* the object id value */
+
+ __u32 yst_mode;
+
+#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
+ YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
+#endif
+
+/* XXX U-BOOT XXX */
+/* #ifndef __KERNEL__ */
+ __u32 inUse;
+/* #endif */
+
+#ifdef CONFIG_YAFFS_WINCE
+ __u32 win_ctime[2];
+ __u32 win_mtime[2];
+ __u32 win_atime[2];
+#else
+ __u32 yst_uid;
+ __u32 yst_gid;
+ __u32 yst_atime;
+ __u32 yst_mtime;
+ __u32 yst_ctime;
+#endif
+
+ __u32 yst_rdev;
+
+/* XXX U-BOOT XXX */
+/* #ifndef __KERNEL__ */
+ struct inode *myInode;
+/* #endif */
+
+ yaffs_ObjectType variantType;
+
+ yaffs_ObjectVariant variant;
+
+};
+
+typedef struct yaffs_ObjectStruct yaffs_Object;
+
+struct yaffs_ObjectList_struct {
+ yaffs_Object *objects;
+ struct yaffs_ObjectList_struct *next;
+};
+
+typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
+
+typedef struct {
+ struct list_head list;
+ int count;
+} yaffs_ObjectBucket;
+
+
+/* yaffs_CheckpointObject holds the definition of an object as dumped
+ * by checkpointing.
+ */
+
+typedef struct {
+ int structType;
+ __u32 objectId;
+ __u32 parentId;
+ int chunkId;
+
+ yaffs_ObjectType variantType:3;
+ __u8 deleted:1;
+ __u8 softDeleted:1;
+ __u8 unlinked:1;
+ __u8 fake:1;
+ __u8 renameAllowed:1;
+ __u8 unlinkAllowed:1;
+ __u8 serial;
+
+ int nDataChunks;
+ __u32 fileSizeOrEquivalentObjectId;
+
+}yaffs_CheckpointObject;
+
+/*--------------------- Temporary buffers ----------------
+ *
+ * These are chunk-sized working buffers. Each device has a few
+ */
+
+typedef struct {
+ __u8 *buffer;
+ int line; /* track from whence this buffer was allocated */
+ int maxLine;
+} yaffs_TempBuffer;
+
+/*----------------- Device ---------------------------------*/
+
+struct yaffs_DeviceStruct {
+ struct list_head devList;
+ const char *name;
+
+ /* Entry parameters set up way early. Yaffs sets up the rest.*/
+ int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
+ int nChunksPerBlock; /* does not need to be a power of 2 */
+ int nBytesPerSpare; /* spare area size */
+ int startBlock; /* Start block we're allowed to use */
+ int endBlock; /* End block we're allowed to use */
+ int nReservedBlocks; /* We want this tuneable so that we can reduce */
+ /* reserved blocks on NOR and RAM. */
+
+
+ /* Stuff used by the shared space checkpointing mechanism */
+ /* If this value is zero, then this mechanism is disabled */
+
+ int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
+
+
+
+
+ int nShortOpCaches; /* If <= 0, then short op caching is disabled, else
+ * the number of short op caches (don't use too many)
+ */
+
+ int useHeaderFileSize; /* Flag to determine if we should use file sizes from the header */
+
+ int useNANDECC; /* Flag to decide whether or not to use NANDECC */
+
+ void *genericDevice; /* Pointer to device context
+ * On an mtd this holds the mtd pointer.
+ */
+ void *superBlock;
+
+ /* NAND access functions (Must be set before calling YAFFS)*/
+
+ int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev,
+ int chunkInNAND, const __u8 * data,
+ const yaffs_Spare * spare);
+ int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev,
+ int chunkInNAND, __u8 * data,
+ yaffs_Spare * spare);
+ int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
+ int blockInNAND);
+ int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
+
+#ifdef CONFIG_YAFFS_YAFFS2
+ int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
+ int chunkInNAND, const __u8 * data,
+ const yaffs_ExtendedTags * tags);
+ int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev,
+ int chunkInNAND, __u8 * data,
+ yaffs_ExtendedTags * tags);
+ int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
+ int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
+ yaffs_BlockState * state, int *sequenceNumber);
+#endif
+
+ int isYaffs2;
+
+ /* The removeObjectCallback function must be supplied by OS flavours that
+ * need it. The Linux kernel does not use this, but yaffs direct does use
+ * it to implement the faster readdir
+ */
+ void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
+
+ /* Callback to mark the superblock dirsty */
+ void (*markSuperBlockDirty)(void * superblock);
+
+ int wideTnodesDisabled; /* Set to disable wide tnodes */
+
+
+ /* End of stuff that must be set before initialisation. */
+
+ /* Checkpoint control. Can be set before or after initialisation */
+ __u8 skipCheckpointRead;
+ __u8 skipCheckpointWrite;
+
+ /* Runtime parameters. Set up by YAFFS. */
+
+ __u16 chunkGroupBits; /* 0 for devices <= 32MB. else log2(nchunks) - 16 */
+ __u16 chunkGroupSize; /* == 2^^chunkGroupBits */
+
+ /* Stuff to support wide tnodes */
+ __u32 tnodeWidth;
+ __u32 tnodeMask;
+
+ /* Stuff to support various file offses to chunk/offset translations */
+ /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
+ __u32 crumbMask;
+ __u32 crumbShift;
+ __u32 crumbsPerChunk;
+
+ /* Straight shifting for nDataBytesPerChunk being a power of 2 */
+ __u32 chunkShift;
+ __u32 chunkMask;
+
+
+/* XXX U-BOOT XXX */
+#if 0
+#ifndef __KERNEL__
+
+ struct semaphore sem; /* Semaphore for waiting on erasure.*/
+ struct semaphore grossLock; /* Gross locking semaphore */
+ void (*putSuperFunc) (struct super_block * sb);
+#endif
+#endif
+ __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer
+ * at compile time so we have to allocate it.
+ */
+
+ int isMounted;
+
+ int isCheckpointed;
+
+
+ /* Stuff to support block offsetting to support start block zero */
+ int internalStartBlock;
+ int internalEndBlock;
+ int blockOffset;
+ int chunkOffset;
+
+
+ /* Runtime checkpointing stuff */
+ int checkpointPageSequence; /* running sequence number of checkpoint pages */
+ int checkpointByteCount;
+ int checkpointByteOffset;
+ __u8 *checkpointBuffer;
+ int checkpointOpenForWrite;
+ int blocksInCheckpoint;
+ int checkpointCurrentChunk;
+ int checkpointCurrentBlock;
+ int checkpointNextBlock;
+ int *checkpointBlockList;
+ int checkpointMaxBlocks;
+ __u32 checkpointSum;
+ __u32 checkpointXor;
+
+ /* Block Info */
+ yaffs_BlockInfo *blockInfo;
+ __u8 *chunkBits; /* bitmap of chunks in use */
+ unsigned blockInfoAlt:1; /* was allocated using alternative strategy */
+ unsigned chunkBitsAlt:1; /* was allocated using alternative strategy */
+ int chunkBitmapStride; /* Number of bytes of chunkBits per block.
+ * Must be consistent with nChunksPerBlock.
+ */
+
+ int nErasedBlocks;
+ int allocationBlock; /* Current block being allocated off */
+ __u32 allocationPage;
+ int allocationBlockFinder; /* Used to search for next allocation block */
+
+ /* Runtime state */
+ int nTnodesCreated;
+ yaffs_Tnode *freeTnodes;
+ int nFreeTnodes;
+ yaffs_TnodeList *allocatedTnodeList;
+
+ int isDoingGC;
+
+ int nObjectsCreated;
+ yaffs_Object *freeObjects;
+ int nFreeObjects;
+
+ yaffs_ObjectList *allocatedObjectList;
+
+ yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];
+
+ int nFreeChunks;
+
+ int currentDirtyChecker; /* Used to find current dirtiest block */
+
+ __u32 *gcCleanupList; /* objects to delete at the end of a GC. */
+ int nonAggressiveSkip; /* GC state/mode */
+
+ /* Statistcs */
+ int nPageWrites;
+ int nPageReads;
+ int nBlockErasures;
+ int nErasureFailures;
+ int nGCCopies;
+ int garbageCollections;
+ int passiveGarbageCollections;
+ int nRetriedWrites;
+ int nRetiredBlocks;
+ int eccFixed;
+ int eccUnfixed;
+ int tagsEccFixed;
+ int tagsEccUnfixed;
+ int nDeletions;
+ int nUnmarkedDeletions;
+
+ int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */
+
+ /* Special directories */
+ yaffs_Object *rootDir;
+ yaffs_Object *lostNFoundDir;
+
+ /* Buffer areas for storing data to recover from write failures TODO
+ * __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
+ * yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
+ */
+
+ int bufferedBlock; /* Which block is buffered here? */
+ int doingBufferedBlockRewrite;
+
+ yaffs_ChunkCache *srCache;
+ int srLastUse;
+
+ int cacheHits;
+
+ /* Stuff for background deletion and unlinked files.*/
+ yaffs_Object *unlinkedDir; /* Directory where unlinked and deleted files live. */
+ yaffs_Object *deletedDir; /* Directory where deleted objects are sent to disappear. */
+ yaffs_Object *unlinkedDeletion; /* Current file being background deleted.*/
+ int nDeletedFiles; /* Count of files awaiting deletion;*/
+ int nUnlinkedFiles; /* Count of unlinked files. */
+ int nBackgroundDeletions; /* Count of background deletions. */
+
+
+ yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
+ int maxTemp;
+ int unmanagedTempAllocations;
+ int unmanagedTempDeallocations;
+
+ /* yaffs2 runtime stuff */
+ unsigned sequenceNumber; /* Sequence number of currently allocating block */
+ unsigned oldestDirtySequence;
+
+};
+
+typedef struct yaffs_DeviceStruct yaffs_Device;
+
+/* The static layout of bllock usage etc is stored in the super block header */
+typedef struct {
+ int StructType;
+ int version;
+ int checkpointStartBlock;
+ int checkpointEndBlock;
+ int startBlock;
+ int endBlock;
+ int rfu[100];
+} yaffs_SuperBlockHeader;
+
+/* The CheckpointDevice structure holds the device information that changes at runtime and
+ * must be preserved over unmount/mount cycles.
+ */
+typedef struct {
+ int structType;
+ int nErasedBlocks;
+ int allocationBlock; /* Current block being allocated off */
+ __u32 allocationPage;
+ int nFreeChunks;
+
+ int nDeletedFiles; /* Count of files awaiting deletion;*/
+ int nUnlinkedFiles; /* Count of unlinked files. */
+ int nBackgroundDeletions; /* Count of background deletions. */
+
+ /* yaffs2 runtime stuff */
+ unsigned sequenceNumber; /* Sequence number of currently allocating block */
+ unsigned oldestDirtySequence;
+
+} yaffs_CheckpointDevice;
+
+
+typedef struct {
+ int structType;
+ __u32 magic;
+ __u32 version;
+ __u32 head;
+} yaffs_CheckpointValidity;
+
+/* Function to manipulate block info */
+static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
+{
+ if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
+ blk));
+ YBUG();
+ }
+ return &dev->blockInfo[blk - dev->internalStartBlock];
+}
+
+/*----------------------- YAFFS Functions -----------------------*/
+
+int yaffs_GutsInitialise(yaffs_Device * dev);
+void yaffs_Deinitialise(yaffs_Device * dev);
+
+int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev);
+
+int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
+ yaffs_Object * newDir, const YCHAR * newName);
+
+int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name);
+int yaffs_DeleteFile(yaffs_Object * obj);
+
+int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize);
+int yaffs_GetObjectFileLength(yaffs_Object * obj);
+int yaffs_GetObjectInode(yaffs_Object * obj);
+unsigned yaffs_GetObjectType(yaffs_Object * obj);
+int yaffs_GetObjectLinkCount(yaffs_Object * obj);
+
+int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr);
+int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr);
+
+/* File operations */
+int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset,
+ int nBytes);
+int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset,
+ int nBytes, int writeThrough);
+int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize);
+
+yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
+ __u32 mode, __u32 uid, __u32 gid);
+int yaffs_FlushFile(yaffs_Object * obj, int updateTime);
+
+/* Flushing and checkpointing */
+void yaffs_FlushEntireDeviceCache(yaffs_Device *dev);
+
+int yaffs_CheckpointSave(yaffs_Device *dev);
+int yaffs_CheckpointRestore(yaffs_Device *dev);
+
+/* Directory operations */
+yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name,
+ __u32 mode, __u32 uid, __u32 gid);
+yaffs_Object *yaffs_FindObjectByName(yaffs_Object * theDir, const YCHAR * name);
+int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
+ int (*fn) (yaffs_Object *));
+
+yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number);
+
+/* Link operations */
+yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name,
+ yaffs_Object * equivalentObject);
+
+yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj);
+
+/* Symlink operations */
+yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name,
+ __u32 mode, __u32 uid, __u32 gid,
+ const YCHAR * alias);
+YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj);
+
+/* Special inodes (fifos, sockets and devices) */
+yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name,
+ __u32 mode, __u32 uid, __u32 gid, __u32 rdev);
+
+/* Special directories */
+yaffs_Object *yaffs_Root(yaffs_Device * dev);
+yaffs_Object *yaffs_LostNFound(yaffs_Device * dev);
+
+#ifdef CONFIG_YAFFS_WINCE
+/* CONFIG_YAFFS_WINCE special stuff */
+void yfsd_WinFileTimeNow(__u32 target[2]);
+#endif
+
+/* XXX U-BOOT XXX */
+#if 0
+#ifndef __KERNEL__
+void yaffs_HandleDeferedFree(yaffs_Object * obj);
+#endif
+#endif
+
+/* Debug dump */
+int yaffs_DumpObject(yaffs_Object * obj);
+
+void yaffs_GutsTest(yaffs_Device * dev);
+
+/* A few useful functions */
+void yaffs_InitialiseTags(yaffs_ExtendedTags * tags);
+void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn);
+int yaffs_CheckFF(__u8 * buffer, int nBytes);
+void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
+
+#endif
--- /dev/null
+#ifndef __YAFFS_MALLOC_H__
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/* XXX U-BOOT XXX */
+#if 0
+#include <stdlib.h>
+#endif
+
+void *yaffs_malloc(size_t size);
+void yaffs_free(void *ptr);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+const char *yaffs_mtdif_c_version =
+ "$Id: yaffs_mtdif.c,v 1.19 2007/02/14 01:09:06 wookey Exp $";
+
+#include "yportenv.h"
+
+
+#include "yaffs_mtdif.h"
+
+#include "linux/mtd/mtd.h"
+#include "linux/types.h"
+#include "linux/time.h"
+#include "linux/mtd/nand.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
+static struct nand_oobinfo yaffs_oobinfo = {
+ .useecc = 1,
+ .eccbytes = 6,
+ .eccpos = {8, 9, 10, 13, 14, 15}
+};
+
+static struct nand_oobinfo yaffs_noeccinfo = {
+ .useecc = 0,
+};
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
+{
+ oob[0] = spare->tagByte0;
+ oob[1] = spare->tagByte1;
+ oob[2] = spare->tagByte2;
+ oob[3] = spare->tagByte3;
+ oob[4] = spare->tagByte4;
+ oob[5] = spare->tagByte5 & 0x3f;
+ oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80;
+ oob[5] |= spare->pageStatus == 0 ? 0: 0x40;
+ oob[6] = spare->tagByte6;
+ oob[7] = spare->tagByte7;
+}
+
+static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob)
+{
+ struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare;
+ spare->tagByte0 = oob[0];
+ spare->tagByte1 = oob[1];
+ spare->tagByte2 = oob[2];
+ spare->tagByte3 = oob[3];
+ spare->tagByte4 = oob[4];
+ spare->tagByte5 = oob[5] == 0xff ? 0xff : oob[5] & 0x3f;
+ spare->blockStatus = oob[5] & 0x80 ? 0xff : 'Y';
+ spare->pageStatus = oob[5] & 0x40 ? 0xff : 0;
+ spare->ecc1[0] = spare->ecc1[1] = spare->ecc1[2] = 0xff;
+ spare->tagByte6 = oob[6];
+ spare->tagByte7 = oob[7];
+ spare->ecc2[0] = spare->ecc2[1] = spare->ecc2[2] = 0xff;
+
+ nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */
+}
+#endif
+
+int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data, const yaffs_Spare * spare)
+{
+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ struct mtd_oob_ops ops;
+#endif
+ size_t dummy;
+ int retval = 0;
+
+ loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ __u8 spareAsBytes[8]; /* OOB */
+
+ if (data && !spare)
+ retval = mtd->write(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data);
+ else if (spare) {
+ if (dev->useNANDECC) {
+ translate_spare2oob(spare, spareAsBytes);
+ ops.mode = MTD_OOB_AUTO;
+ ops.ooblen = 8; /* temp hack */
+ } else {
+ ops.mode = MTD_OOB_RAW;
+ ops.ooblen = YAFFS_BYTES_PER_SPARE;
+ }
+ ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
+ ops.datbuf = (u8 *)data;
+ ops.ooboffs = 0;
+ ops.oobbuf = spareAsBytes;
+ retval = mtd->write_oob(mtd, addr, &ops);
+ }
+#else
+ __u8 *spareAsBytes = (__u8 *) spare;
+
+ if (data && spare) {
+ if (dev->useNANDECC)
+ retval =
+ mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, spareAsBytes,
+ &yaffs_oobinfo);
+ else
+ retval =
+ mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, spareAsBytes,
+ &yaffs_noeccinfo);
+ } else {
+ if (data)
+ retval =
+ mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
+ data);
+ if (spare)
+ retval =
+ mtd->write_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
+ &dummy, spareAsBytes);
+ }
+#endif
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
+ yaffs_Spare * spare)
+{
+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ struct mtd_oob_ops ops;
+#endif
+ size_t dummy;
+ int retval = 0;
+
+ loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ __u8 spareAsBytes[8]; /* OOB */
+
+ if (data && !spare)
+ retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data);
+ else if (spare) {
+ if (dev->useNANDECC) {
+ ops.mode = MTD_OOB_AUTO;
+ ops.ooblen = 8; /* temp hack */
+ } else {
+ ops.mode = MTD_OOB_RAW;
+ ops.ooblen = YAFFS_BYTES_PER_SPARE;
+ }
+ ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
+ ops.datbuf = data;
+ ops.ooboffs = 0;
+ ops.oobbuf = spareAsBytes;
+ retval = mtd->read_oob(mtd, addr, &ops);
+ if (dev->useNANDECC)
+ translate_oob2spare(spare, spareAsBytes);
+ }
+#else
+ __u8 *spareAsBytes = (__u8 *) spare;
+
+ if (data && spare) {
+ if (dev->useNANDECC) {
+ /* Careful, this call adds 2 ints */
+ /* to the end of the spare data. Calling function */
+ /* should allocate enough memory for spare, */
+ /* i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)]. */
+ retval =
+ mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, spareAsBytes,
+ &yaffs_oobinfo);
+ } else {
+ retval =
+ mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, spareAsBytes,
+ &yaffs_noeccinfo);
+ }
+ } else {
+ if (data)
+ retval =
+ mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
+ data);
+ if (spare)
+ retval =
+ mtd->read_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
+ &dummy, spareAsBytes);
+ }
+#endif
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber)
+{
+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+ __u32 addr =
+ ((loff_t) blockNumber) * dev->nDataBytesPerChunk
+ * dev->nChunksPerBlock;
+ struct erase_info ei;
+ int retval = 0;
+
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = dev->nDataBytesPerChunk * dev->nChunksPerBlock;
+ ei.time = 1000;
+ ei.retries = 2;
+ ei.callback = NULL;
+ ei.priv = (u_long) dev;
+
+ /* Todo finish off the ei if required */
+
+/* XXX U-BOOT XXX */
+#if 0
+ sema_init(&dev->sem, 0);
+#endif
+
+ retval = mtd->erase(mtd, &ei);
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+int nandmtd_InitialiseNAND(yaffs_Device * dev)
+{
+ return YAFFS_OK;
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_MTDIF_H__
+#define __YAFFS_MTDIF_H__
+
+#include "yaffs_guts.h"
+
+int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data, const yaffs_Spare * spare);
+int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
+ yaffs_Spare * spare);
+int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber);
+int nandmtd_InitialiseNAND(yaffs_Device * dev);
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* mtd interface for YAFFS2 */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+#include "asm/errno.h"
+
+const char *yaffs_mtdif2_c_version =
+ "$Id: yaffs_mtdif2.c,v 1.17 2007/02/14 01:09:06 wookey Exp $";
+
+#include "yportenv.h"
+
+
+#include "yaffs_mtdif2.h"
+
+#include "linux/mtd/mtd.h"
+#include "linux/types.h"
+#include "linux/time.h"
+
+#include "yaffs_packedtags2.h"
+
+int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data,
+ const yaffs_ExtendedTags * tags)
+{
+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ struct mtd_oob_ops ops;
+#else
+ size_t dummy;
+#endif
+ int retval = 0;
+
+ loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+
+ yaffs_PackedTags2 pt;
+
+ T(YAFFS_TRACE_MTD,
+ (TSTR
+ ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
+ TENDSTR), chunkInNAND, data, tags));
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ if (tags)
+ yaffs_PackTags2(&pt, tags);
+ else
+ BUG(); /* both tags and data should always be present */
+
+ if (data) {
+ ops.mode = MTD_OOB_AUTO;
+ ops.ooblen = sizeof(pt);
+ ops.len = dev->nDataBytesPerChunk;
+ ops.ooboffs = 0;
+ ops.datbuf = (__u8 *)data;
+ ops.oobbuf = (void *)&pt;
+ retval = mtd->write_oob(mtd, addr, &ops);
+ } else
+ BUG(); /* both tags and data should always be present */
+#else
+ if (tags) {
+ yaffs_PackTags2(&pt, tags);
+ }
+
+ if (data && tags) {
+ if (dev->useNANDECC)
+ retval =
+ mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, (__u8 *) & pt, NULL);
+ else
+ retval =
+ mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, (__u8 *) & pt, NULL);
+ } else {
+ if (data)
+ retval =
+ mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
+ data);
+ if (tags)
+ retval =
+ mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
+ (__u8 *) & pt);
+
+ }
+#endif
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
+ __u8 * data, yaffs_ExtendedTags * tags)
+{
+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ struct mtd_oob_ops ops;
+#endif
+ size_t dummy;
+ int retval = 0;
+
+ loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+
+ yaffs_PackedTags2 pt;
+
+ T(YAFFS_TRACE_MTD,
+ (TSTR
+ ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
+ TENDSTR), chunkInNAND, data, tags));
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ if (data && !tags)
+ retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data);
+ else if (tags) {
+ ops.mode = MTD_OOB_AUTO;
+ ops.ooblen = sizeof(pt);
+ ops.len = data ? dev->nDataBytesPerChunk : sizeof(pt);
+ ops.ooboffs = 0;
+ ops.datbuf = data;
+ ops.oobbuf = dev->spareBuffer;
+ retval = mtd->read_oob(mtd, addr, &ops);
+ }
+#else
+ if (data && tags) {
+ if (dev->useNANDECC) {
+ retval =
+ mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, dev->spareBuffer,
+ NULL);
+ } else {
+ retval =
+ mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, dev->spareBuffer,
+ NULL);
+ }
+ } else {
+ if (data)
+ retval =
+ mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
+ data);
+ if (tags)
+ retval =
+ mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
+ dev->spareBuffer);
+ }
+#endif
+
+ memcpy(&pt, dev->spareBuffer, sizeof(pt));
+
+ if (tags)
+ yaffs_UnpackTags2(tags, &pt);
+
+ if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
+ tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
+{
+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+ int retval;
+ T(YAFFS_TRACE_MTD,
+ (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
+
+ retval =
+ mtd->block_markbad(mtd,
+ blockNo * dev->nChunksPerBlock *
+ dev->nDataBytesPerChunk);
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+
+}
+
+int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+ yaffs_BlockState * state, int *sequenceNumber)
+{
+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+ int retval;
+
+ T(YAFFS_TRACE_MTD,
+ (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
+ retval =
+ mtd->block_isbad(mtd,
+ blockNo * dev->nChunksPerBlock *
+ dev->nDataBytesPerChunk);
+
+ if (retval) {
+ T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
+
+ *state = YAFFS_BLOCK_STATE_DEAD;
+ *sequenceNumber = 0;
+ } else {
+ yaffs_ExtendedTags t;
+ nandmtd2_ReadChunkWithTagsFromNAND(dev,
+ blockNo *
+ dev->nChunksPerBlock, NULL,
+ &t);
+
+ if (t.chunkUsed) {
+ *sequenceNumber = t.sequenceNumber;
+ *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+ } else {
+ *sequenceNumber = 0;
+ *state = YAFFS_BLOCK_STATE_EMPTY;
+ }
+ }
+ T(YAFFS_TRACE_MTD,
+ (TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber,
+ *state));
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_MTDIF2_H__
+#define __YAFFS_MTDIF2_H__
+
+#include "yaffs_guts.h"
+int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data,
+ const yaffs_ExtendedTags * tags);
+int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
+ __u8 * data, yaffs_ExtendedTags * tags);
+int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
+int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+ yaffs_BlockState * state, int *sequenceNumber);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+const char *yaffs_nand_c_version =
+ "$Id: yaffs_nand.c,v 1.7 2007/02/14 01:09:06 wookey Exp $";
+
+#include "yaffs_nand.h"
+#include "yaffs_tagscompat.h"
+#include "yaffs_tagsvalidity.h"
+
+
+int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
+ __u8 * buffer,
+ yaffs_ExtendedTags * tags)
+{
+ int result;
+ yaffs_ExtendedTags localTags;
+
+ int realignedChunkInNAND = chunkInNAND - dev->chunkOffset;
+
+ /* If there are no tags provided, use local tags to get prioritised gc working */
+ if(!tags)
+ tags = &localTags;
+
+ if (dev->readChunkWithTagsFromNAND)
+ result = dev->readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer,
+ tags);
+ else
+ result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,
+ realignedChunkInNAND,
+ buffer,
+ tags);
+ if(tags &&
+ tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){
+
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock);
+ yaffs_HandleChunkError(dev,bi);
+ }
+
+ return result;
+}
+
+int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
+ int chunkInNAND,
+ const __u8 * buffer,
+ yaffs_ExtendedTags * tags)
+{
+ chunkInNAND -= dev->chunkOffset;
+
+
+ if (tags) {
+ tags->sequenceNumber = dev->sequenceNumber;
+ tags->chunkUsed = 1;
+ if (!yaffs_ValidateTags(tags)) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("Writing uninitialised tags" TENDSTR)));
+ YBUG();
+ }
+ T(YAFFS_TRACE_WRITE,
+ (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND,
+ tags->objectId, tags->chunkId));
+ } else {
+ T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR)));
+ YBUG();
+ }
+
+ if (dev->writeChunkWithTagsToNAND)
+ return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,
+ tags);
+ else
+ return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,
+ chunkInNAND,
+ buffer,
+ tags);
+}
+
+int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo)
+{
+ blockNo -= dev->blockOffset;
+
+;
+ if (dev->markNANDBlockBad)
+ return dev->markNANDBlockBad(dev, blockNo);
+ else
+ return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);
+}
+
+int yaffs_QueryInitialBlockState(yaffs_Device * dev,
+ int blockNo,
+ yaffs_BlockState * state,
+ unsigned *sequenceNumber)
+{
+ blockNo -= dev->blockOffset;
+
+ if (dev->queryNANDBlock)
+ return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber);
+ else
+ return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo,
+ state,
+ sequenceNumber);
+}
+
+
+int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
+ int blockInNAND)
+{
+ int result;
+
+ blockInNAND -= dev->blockOffset;
+
+
+ dev->nBlockErasures++;
+ result = dev->eraseBlockInNAND(dev, blockInNAND);
+
+ return result;
+}
+
+int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
+{
+ return dev->initialiseNAND(dev);
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_NAND_H__
+#define __YAFFS_NAND_H__
+#include "yaffs_guts.h"
+
+
+
+int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
+ __u8 * buffer,
+ yaffs_ExtendedTags * tags);
+
+int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
+ int chunkInNAND,
+ const __u8 * buffer,
+ yaffs_ExtendedTags * tags);
+
+int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo);
+
+int yaffs_QueryInitialBlockState(yaffs_Device * dev,
+ int blockNo,
+ yaffs_BlockState * state,
+ unsigned *sequenceNumber);
+
+int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
+ int blockInNAND);
+
+int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/* Interface to emulated NAND functions (2k page size) */
+
+#ifndef __YAFFS_NANDEMUL2K_H__
+#define __YAFFS_NANDEMUL2K_H__
+
+#include "yaffs_guts.h"
+
+int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
+ int chunkInNAND, const __u8 * data,
+ yaffs_ExtendedTags * tags);
+int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
+ int chunkInNAND, __u8 * data,
+ yaffs_ExtendedTags * tags);
+int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
+int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+ yaffs_BlockState * state, int *sequenceNumber);
+int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
+ int blockInNAND);
+int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);
+int nandemul2k_GetBytesPerChunk(void);
+int nandemul2k_GetChunksPerBlock(void);
+int nandemul2k_GetNumberOfBlocks(void);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+#include "yaffs_packedtags1.h"
+#include "yportenv.h"
+
+void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t)
+{
+ pt->chunkId = t->chunkId;
+ pt->serialNumber = t->serialNumber;
+ pt->byteCount = t->byteCount;
+ pt->objectId = t->objectId;
+ pt->ecc = 0;
+ pt->deleted = (t->chunkDeleted) ? 0 : 1;
+ pt->unusedStuff = 0;
+ pt->shouldBeFF = 0xFFFFFFFF;
+
+}
+
+void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt)
+{
+ static const __u8 allFF[] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff };
+
+ if (memcmp(allFF, pt, sizeof(yaffs_PackedTags1))) {
+ t->blockBad = 0;
+ if (pt->shouldBeFF != 0xFFFFFFFF) {
+ t->blockBad = 1;
+ }
+ t->chunkUsed = 1;
+ t->objectId = pt->objectId;
+ t->chunkId = pt->chunkId;
+ t->byteCount = pt->byteCount;
+ t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+ t->chunkDeleted = (pt->deleted) ? 0 : 1;
+ t->serialNumber = pt->serialNumber;
+ } else {
+ memset(t, 0, sizeof(yaffs_ExtendedTags));
+
+ }
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/* This is used to pack YAFFS1 tags, not YAFFS2 tags. */
+
+#ifndef __YAFFS_PACKEDTAGS1_H__
+#define __YAFFS_PACKEDTAGS1_H__
+
+#include "yaffs_guts.h"
+
+typedef struct {
+ unsigned chunkId:20;
+ unsigned serialNumber:2;
+ unsigned byteCount:10;
+ unsigned objectId:18;
+ unsigned ecc:12;
+ unsigned deleted:1;
+ unsigned unusedStuff:1;
+ unsigned shouldBeFF;
+
+} yaffs_PackedTags1;
+
+void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t);
+void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt);
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+#include "yaffs_packedtags2.h"
+#include "yportenv.h"
+#include "yaffs_tagsvalidity.h"
+
+/* This code packs a set of extended tags into a binary structure for
+ * NAND storage
+ */
+
+/* Some of the information is "extra" struff which can be packed in to
+ * speed scanning
+ * This is defined by having the EXTRA_HEADER_INFO_FLAG set.
+ */
+
+/* Extra flags applied to chunkId */
+
+#define EXTRA_HEADER_INFO_FLAG 0x80000000
+#define EXTRA_SHRINK_FLAG 0x40000000
+#define EXTRA_SHADOWS_FLAG 0x20000000
+#define EXTRA_SPARE_FLAGS 0x10000000
+
+#define ALL_EXTRA_FLAGS 0xF0000000
+
+/* Also, the top 4 bits of the object Id are set to the object type. */
+#define EXTRA_OBJECT_TYPE_SHIFT (28)
+#define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
+
+static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
+{
+ T(YAFFS_TRACE_MTD,
+ (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
+ pt->t.objectId, pt->t.chunkId, pt->t.byteCount,
+ pt->t.sequenceNumber));
+}
+
+static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
+{
+ T(YAFFS_TRACE_MTD,
+ (TSTR
+ ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte "
+ "%d del %d ser %d seq %d"
+ TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
+ t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
+ t->sequenceNumber));
+
+}
+
+void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
+{
+ pt->t.chunkId = t->chunkId;
+ pt->t.sequenceNumber = t->sequenceNumber;
+ pt->t.byteCount = t->byteCount;
+ pt->t.objectId = t->objectId;
+
+ if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
+ /* Store the extra header info instead */
+ /* We save the parent object in the chunkId */
+ pt->t.chunkId = EXTRA_HEADER_INFO_FLAG
+ | t->extraParentObjectId;
+ if (t->extraIsShrinkHeader) {
+ pt->t.chunkId |= EXTRA_SHRINK_FLAG;
+ }
+ if (t->extraShadows) {
+ pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
+ }
+
+ pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
+ pt->t.objectId |=
+ (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
+
+ if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
+ pt->t.byteCount = t->extraEquivalentObjectId;
+ } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
+ pt->t.byteCount = t->extraFileLength;
+ } else {
+ pt->t.byteCount = 0;
+ }
+ }
+
+ yaffs_DumpPackedTags2(pt);
+ yaffs_DumpTags2(t);
+
+#ifndef YAFFS_IGNORE_TAGS_ECC
+ {
+ yaffs_ECCCalculateOther((unsigned char *)&pt->t,
+ sizeof(yaffs_PackedTags2TagsPart),
+ &pt->ecc);
+ }
+#endif
+}
+
+void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
+{
+
+ memset(t, 0, sizeof(yaffs_ExtendedTags));
+
+ yaffs_InitialiseTags(t);
+
+ if (pt->t.sequenceNumber != 0xFFFFFFFF) {
+ /* Page is in use */
+#ifdef YAFFS_IGNORE_TAGS_ECC
+ {
+ t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+ }
+#else
+ {
+ yaffs_ECCOther ecc;
+ int result;
+ yaffs_ECCCalculateOther((unsigned char *)&pt->t,
+ sizeof
+ (yaffs_PackedTags2TagsPart),
+ &ecc);
+ result =
+ yaffs_ECCCorrectOther((unsigned char *)&pt->t,
+ sizeof
+ (yaffs_PackedTags2TagsPart),
+ &pt->ecc, &ecc);
+ switch(result){
+ case 0:
+ t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+ break;
+ case 1:
+ t->eccResult = YAFFS_ECC_RESULT_FIXED;
+ break;
+ case -1:
+ t->eccResult = YAFFS_ECC_RESULT_UNFIXED;
+ break;
+ default:
+ t->eccResult = YAFFS_ECC_RESULT_UNKNOWN;
+ }
+ }
+#endif
+ t->blockBad = 0;
+ t->chunkUsed = 1;
+ t->objectId = pt->t.objectId;
+ t->chunkId = pt->t.chunkId;
+ t->byteCount = pt->t.byteCount;
+ t->chunkDeleted = 0;
+ t->serialNumber = 0;
+ t->sequenceNumber = pt->t.sequenceNumber;
+
+ /* Do extra header info stuff */
+
+ if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
+ t->chunkId = 0;
+ t->byteCount = 0;
+
+ t->extraHeaderInfoAvailable = 1;
+ t->extraParentObjectId =
+ pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
+ t->extraIsShrinkHeader =
+ (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
+ t->extraShadows =
+ (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
+ t->extraObjectType =
+ pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
+ t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
+
+ if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
+ t->extraEquivalentObjectId = pt->t.byteCount;
+ } else {
+ t->extraFileLength = pt->t.byteCount;
+ }
+ }
+ }
+
+ yaffs_DumpPackedTags2(pt);
+ yaffs_DumpTags2(t);
+
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/* This is used to pack YAFFS2 tags, not YAFFS1tags. */
+
+#ifndef __YAFFS_PACKEDTAGS2_H__
+#define __YAFFS_PACKEDTAGS2_H__
+
+#include "yaffs_guts.h"
+#include "yaffs_ecc.h"
+
+typedef struct {
+ unsigned sequenceNumber;
+ unsigned objectId;
+ unsigned chunkId;
+ unsigned byteCount;
+} yaffs_PackedTags2TagsPart;
+
+typedef struct {
+ yaffs_PackedTags2TagsPart t;
+ yaffs_ECCOther ecc;
+} yaffs_PackedTags2;
+
+void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
+void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
+#endif
--- /dev/null
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+#include "yportenv.h"
+//#include <linux/string.h>
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ register TYPE *pi = (TYPE *) (parmi); \
+ register TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ register TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static __inline void
+swapfunc(char *a, char *b, int n, int swaptype)
+{
+ if (swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+
+static __inline char *
+med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
+{
+ return cmp(a, b) < 0 ?
+ (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
+ :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
+}
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+void
+yaffs_qsort(void *aa, size_t n, size_t es,
+ int (*cmp)(const void *, const void *))
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int d, r, swaptype, swap_cnt;
+ register char *a = aa;
+
+loop: SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = (char *)a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp);
+ pm = med3(pm - d, pm, pm + d, cmp);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp);
+ }
+ pm = med3(pl, pm, pn, cmp);
+ }
+ swap(a, pm);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (r = cmp(pb, a)) <= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (r = cmp(pc, a)) >= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+
+ pn = (char *)a + n * es;
+ r = min(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = min((long)(pd - pc), (long)(pn - pd - es));
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > es)
+ yaffs_qsort(a, r / es, es, cmp);
+ if ((r = pd - pc) > es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+/* yaffs_qsort(pn - r, r / es, es, cmp);*/
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+
+#ifndef __YAFFS_QSORT_H__
+#define __YAFFS_QSORT_H__
+
+extern void yaffs_qsort (void *const base, size_t total_elems, size_t size,
+ int (*cmp)(const void *, const void *));
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/*
+ * yaffs_ramdisk.h: yaffs ram disk component
+ */
+
+#ifndef __YAFFS_RAMDISK_H__
+#define __YAFFS_RAMDISK_H__
+
+
+#include "yaffs_guts.h"
+int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
+int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags);
+int yramdisk_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
+int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
+int yramdisk_InitialiseNAND(yaffs_Device *dev);
+int yramdisk_MarkNANDBlockBad(yaffs_Device *dev,int blockNumber);
+int yramdisk_QueryNANDBlock(yaffs_Device *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber);
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+#include "yaffs_guts.h"
+#include "yaffs_tagscompat.h"
+#include "yaffs_ecc.h"
+
+static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
+#ifdef NOTYET
+static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND);
+static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data,
+ const yaffs_Spare * spare);
+static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
+ const yaffs_Spare * spare);
+static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND);
+#endif
+
+static const char yaffs_countBitsTable[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+int yaffs_CountBits(__u8 x)
+{
+ int retVal;
+ retVal = yaffs_countBitsTable[x];
+ return retVal;
+}
+
+/********** Tags ECC calculations *********/
+
+void yaffs_CalcECC(const __u8 * data, yaffs_Spare * spare)
+{
+ yaffs_ECCCalculate(data, spare->ecc1);
+ yaffs_ECCCalculate(&data[256], spare->ecc2);
+}
+
+void yaffs_CalcTagsECC(yaffs_Tags * tags)
+{
+ /* Calculate an ecc */
+
+ unsigned char *b = ((yaffs_TagsUnion *) tags)->asBytes;
+ unsigned i, j;
+ unsigned ecc = 0;
+ unsigned bit = 0;
+
+ tags->ecc = 0;
+
+ for (i = 0; i < 8; i++) {
+ for (j = 1; j & 0xff; j <<= 1) {
+ bit++;
+ if (b[i] & j) {
+ ecc ^= bit;
+ }
+ }
+ }
+
+ tags->ecc = ecc;
+
+}
+
+int yaffs_CheckECCOnTags(yaffs_Tags * tags)
+{
+ unsigned ecc = tags->ecc;
+
+ yaffs_CalcTagsECC(tags);
+
+ ecc ^= tags->ecc;
+
+ if (ecc && ecc <= 64) {
+ /* TODO: Handle the failure better. Retire? */
+ unsigned char *b = ((yaffs_TagsUnion *) tags)->asBytes;
+
+ ecc--;
+
+ b[ecc / 8] ^= (1 << (ecc & 7));
+
+ /* Now recvalc the ecc */
+ yaffs_CalcTagsECC(tags);
+
+ return 1; /* recovered error */
+ } else if (ecc) {
+ /* Wierd ecc failure value */
+ /* TODO Need to do somethiong here */
+ return -1; /* unrecovered error */
+ }
+
+ return 0;
+}
+
+/********** Tags **********/
+
+static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr,
+ yaffs_Tags * tagsPtr)
+{
+ yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
+
+ yaffs_CalcTagsECC(tagsPtr);
+
+ sparePtr->tagByte0 = tu->asBytes[0];
+ sparePtr->tagByte1 = tu->asBytes[1];
+ sparePtr->tagByte2 = tu->asBytes[2];
+ sparePtr->tagByte3 = tu->asBytes[3];
+ sparePtr->tagByte4 = tu->asBytes[4];
+ sparePtr->tagByte5 = tu->asBytes[5];
+ sparePtr->tagByte6 = tu->asBytes[6];
+ sparePtr->tagByte7 = tu->asBytes[7];
+}
+
+static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr,
+ yaffs_Tags * tagsPtr)
+{
+ yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
+ int result;
+
+ tu->asBytes[0] = sparePtr->tagByte0;
+ tu->asBytes[1] = sparePtr->tagByte1;
+ tu->asBytes[2] = sparePtr->tagByte2;
+ tu->asBytes[3] = sparePtr->tagByte3;
+ tu->asBytes[4] = sparePtr->tagByte4;
+ tu->asBytes[5] = sparePtr->tagByte5;
+ tu->asBytes[6] = sparePtr->tagByte6;
+ tu->asBytes[7] = sparePtr->tagByte7;
+
+ result = yaffs_CheckECCOnTags(tagsPtr);
+ if (result > 0) {
+ dev->tagsEccFixed++;
+ } else if (result < 0) {
+ dev->tagsEccUnfixed++;
+ }
+}
+
+static void yaffs_SpareInitialise(yaffs_Spare * spare)
+{
+ memset(spare, 0xFF, sizeof(yaffs_Spare));
+}
+
+static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,
+ int chunkInNAND, const __u8 * data,
+ yaffs_Spare * spare)
+{
+ if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR("**>> yaffs chunk %d is not valid" TENDSTR),
+ chunkInNAND));
+ return YAFFS_FAIL;
+ }
+
+ dev->nPageWrites++;
+ return dev->writeChunkToNAND(dev, chunkInNAND, data, spare);
+}
+
+static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
+ int chunkInNAND,
+ __u8 * data,
+ yaffs_Spare * spare,
+ yaffs_ECCResult * eccResult,
+ int doErrorCorrection)
+{
+ int retVal;
+ yaffs_Spare localSpare;
+
+ dev->nPageReads++;
+
+ if (!spare && data) {
+ /* If we don't have a real spare, then we use a local one. */
+ /* Need this for the calculation of the ecc */
+ spare = &localSpare;
+ }
+
+ if (!dev->useNANDECC) {
+ retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare);
+ if (data && doErrorCorrection) {
+ /* Do ECC correction */
+ /* Todo handle any errors */
+ int eccResult1, eccResult2;
+ __u8 calcEcc[3];
+
+ yaffs_ECCCalculate(data, calcEcc);
+ eccResult1 =
+ yaffs_ECCCorrect(data, spare->ecc1, calcEcc);
+ yaffs_ECCCalculate(&data[256], calcEcc);
+ eccResult2 =
+ yaffs_ECCCorrect(&data[256], spare->ecc2, calcEcc);
+
+ if (eccResult1 > 0) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>>yaffs ecc error fix performed on chunk %d:0"
+ TENDSTR), chunkInNAND));
+ dev->eccFixed++;
+ } else if (eccResult1 < 0) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>>yaffs ecc error unfixed on chunk %d:0"
+ TENDSTR), chunkInNAND));
+ dev->eccUnfixed++;
+ }
+
+ if (eccResult2 > 0) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>>yaffs ecc error fix performed on chunk %d:1"
+ TENDSTR), chunkInNAND));
+ dev->eccFixed++;
+ } else if (eccResult2 < 0) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>>yaffs ecc error unfixed on chunk %d:1"
+ TENDSTR), chunkInNAND));
+ dev->eccUnfixed++;
+ }
+
+ if (eccResult1 || eccResult2) {
+ /* We had a data problem on this page */
+ yaffs_HandleReadDataError(dev, chunkInNAND);
+ }
+
+ if (eccResult1 < 0 || eccResult2 < 0)
+ *eccResult = YAFFS_ECC_RESULT_UNFIXED;
+ else if (eccResult1 > 0 || eccResult2 > 0)
+ *eccResult = YAFFS_ECC_RESULT_FIXED;
+ else
+ *eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+ }
+ } else {
+ /* Must allocate enough memory for spare+2*sizeof(int) */
+ /* for ecc results from device. */
+ struct yaffs_NANDSpare nspare;
+ retVal =
+ dev->readChunkFromNAND(dev, chunkInNAND, data,
+ (yaffs_Spare *) & nspare);
+ memcpy(spare, &nspare, sizeof(yaffs_Spare));
+ if (data && doErrorCorrection) {
+ if (nspare.eccres1 > 0) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>>mtd ecc error fix performed on chunk %d:0"
+ TENDSTR), chunkInNAND));
+ } else if (nspare.eccres1 < 0) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>>mtd ecc error unfixed on chunk %d:0"
+ TENDSTR), chunkInNAND));
+ }
+
+ if (nspare.eccres2 > 0) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>>mtd ecc error fix performed on chunk %d:1"
+ TENDSTR), chunkInNAND));
+ } else if (nspare.eccres2 < 0) {
+ T(YAFFS_TRACE_ERROR,
+ (TSTR
+ ("**>>mtd ecc error unfixed on chunk %d:1"
+ TENDSTR), chunkInNAND));
+ }
+
+ if (nspare.eccres1 || nspare.eccres2) {
+ /* We had a data problem on this page */
+ yaffs_HandleReadDataError(dev, chunkInNAND);
+ }
+
+ if (nspare.eccres1 < 0 || nspare.eccres2 < 0)
+ *eccResult = YAFFS_ECC_RESULT_UNFIXED;
+ else if (nspare.eccres1 > 0 || nspare.eccres2 > 0)
+ *eccResult = YAFFS_ECC_RESULT_FIXED;
+ else
+ *eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+
+ }
+ }
+ return retVal;
+}
+
+#ifdef NOTYET
+static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
+ int chunkInNAND)
+{
+
+ static int init = 0;
+ static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];
+ static __u8 data[YAFFS_BYTES_PER_CHUNK];
+ /* Might as well always allocate the larger size for */
+ /* dev->useNANDECC == true; */
+ static __u8 spare[sizeof(struct yaffs_NANDSpare)];
+
+ dev->readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) spare);
+
+ if (!init) {
+ memset(cmpbuf, 0xff, YAFFS_BYTES_PER_CHUNK);
+ init = 1;
+ }
+
+ if (memcmp(cmpbuf, data, YAFFS_BYTES_PER_CHUNK))
+ return YAFFS_FAIL;
+ if (memcmp(cmpbuf, spare, 16))
+ return YAFFS_FAIL;
+
+ return YAFFS_OK;
+
+}
+#endif
+
+/*
+ * Functions for robustisizing
+ */
+
+static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND)
+{
+ int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
+
+ /* Mark the block for retirement */
+ yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
+ T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
+
+ /* TODO:
+ * Just do a garbage collection on the affected block
+ * then retire the block
+ * NB recursion
+ */
+}
+
+#ifdef NOTYET
+static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND)
+{
+}
+
+static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
+ const __u8 * data,
+ const yaffs_Spare * spare)
+{
+}
+
+static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
+ const yaffs_Spare * spare)
+{
+}
+
+static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND)
+{
+ int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
+
+ /* Mark the block for retirement */
+ yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
+ /* Delete the chunk */
+ yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
+}
+
+static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1,
+ const yaffs_Spare * s0, const yaffs_Spare * s1)
+{
+
+ if (memcmp(d0, d1, YAFFS_BYTES_PER_CHUNK) != 0 ||
+ s0->tagByte0 != s1->tagByte0 ||
+ s0->tagByte1 != s1->tagByte1 ||
+ s0->tagByte2 != s1->tagByte2 ||
+ s0->tagByte3 != s1->tagByte3 ||
+ s0->tagByte4 != s1->tagByte4 ||
+ s0->tagByte5 != s1->tagByte5 ||
+ s0->tagByte6 != s1->tagByte6 ||
+ s0->tagByte7 != s1->tagByte7 ||
+ s0->ecc1[0] != s1->ecc1[0] ||
+ s0->ecc1[1] != s1->ecc1[1] ||
+ s0->ecc1[2] != s1->ecc1[2] ||
+ s0->ecc2[0] != s1->ecc2[0] ||
+ s0->ecc2[1] != s1->ecc2[1] || s0->ecc2[2] != s1->ecc2[2]) {
+ return 0;
+ }
+
+ return 1;
+}
+#endif /* NOTYET */
+
+int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
+ int chunkInNAND,
+ const __u8 * data,
+ const yaffs_ExtendedTags *
+ eTags)
+{
+ yaffs_Spare spare;
+ yaffs_Tags tags;
+
+ yaffs_SpareInitialise(&spare);
+
+ if (eTags->chunkDeleted) {
+ spare.pageStatus = 0;
+ } else {
+ tags.objectId = eTags->objectId;
+ tags.chunkId = eTags->chunkId;
+ tags.byteCount = eTags->byteCount;
+ tags.serialNumber = eTags->serialNumber;
+
+ if (!dev->useNANDECC && data) {
+ yaffs_CalcECC(data, &spare);
+ }
+ yaffs_LoadTagsIntoSpare(&spare, &tags);
+
+ }
+
+ return yaffs_WriteChunkToNAND(dev, chunkInNAND, data, &spare);
+}
+
+int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
+ int chunkInNAND,
+ __u8 * data,
+ yaffs_ExtendedTags * eTags)
+{
+
+ yaffs_Spare spare;
+ yaffs_Tags tags;
+ yaffs_ECCResult eccResult;
+
+ static yaffs_Spare spareFF;
+ static int init;
+
+ if (!init) {
+ memset(&spareFF, 0xFF, sizeof(spareFF));
+ init = 1;
+ }
+
+ if (yaffs_ReadChunkFromNAND
+ (dev, chunkInNAND, data, &spare, &eccResult, 1)) {
+ /* eTags may be NULL */
+ if (eTags) {
+
+ int deleted =
+ (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0;
+
+ eTags->chunkDeleted = deleted;
+ eTags->eccResult = eccResult;
+ eTags->blockBad = 0; /* We're reading it */
+ /* therefore it is not a bad block */
+ eTags->chunkUsed =
+ (memcmp(&spareFF, &spare, sizeof(spareFF)) !=
+ 0) ? 1 : 0;
+
+ if (eTags->chunkUsed) {
+ yaffs_GetTagsFromSpare(dev, &spare, &tags);
+
+ eTags->objectId = tags.objectId;
+ eTags->chunkId = tags.chunkId;
+ eTags->byteCount = tags.byteCount;
+ eTags->serialNumber = tags.serialNumber;
+ }
+ }
+
+ return YAFFS_OK;
+ } else {
+ return YAFFS_FAIL;
+ }
+}
+
+int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
+ int blockInNAND)
+{
+
+ yaffs_Spare spare;
+
+ memset(&spare, 0xff, sizeof(yaffs_Spare));
+
+ spare.blockStatus = 'Y';
+
+ yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL,
+ &spare);
+ yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1,
+ NULL, &spare);
+
+ return YAFFS_OK;
+
+}
+
+int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
+ int blockNo, yaffs_BlockState *
+ state,
+ int *sequenceNumber)
+{
+
+ yaffs_Spare spare0, spare1;
+ static yaffs_Spare spareFF;
+ static int init;
+ yaffs_ECCResult dummy;
+
+ if (!init) {
+ memset(&spareFF, 0xFF, sizeof(spareFF));
+ init = 1;
+ }
+
+ *sequenceNumber = 0;
+
+ yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock, NULL,
+ &spare0, &dummy, 1);
+ yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock + 1, NULL,
+ &spare1, &dummy, 1);
+
+ if (yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7)
+ *state = YAFFS_BLOCK_STATE_DEAD;
+ else if (memcmp(&spareFF, &spare0, sizeof(spareFF)) == 0)
+ *state = YAFFS_BLOCK_STATE_EMPTY;
+ else
+ *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+
+ return YAFFS_OK;
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_TAGSCOMPAT_H__
+#define __YAFFS_TAGSCOMPAT_H__
+
+#include "yaffs_guts.h"
+int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
+ int chunkInNAND,
+ const __u8 * data,
+ const yaffs_ExtendedTags *
+ tags);
+int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
+ int chunkInNAND,
+ __u8 * data,
+ yaffs_ExtendedTags *
+ tags);
+int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
+ int blockNo);
+int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
+ int blockNo, yaffs_BlockState *
+ state, int *sequenceNumber);
+
+void yaffs_CalcTagsECC(yaffs_Tags * tags);
+int yaffs_CheckECCOnTags(yaffs_Tags * tags);
+int yaffs_CountBits(__u8 byte);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+#include "yaffs_tagsvalidity.h"
+
+void yaffs_InitialiseTags(yaffs_ExtendedTags * tags)
+{
+ memset(tags, 0, sizeof(yaffs_ExtendedTags));
+ tags->validMarker0 = 0xAAAAAAAA;
+ tags->validMarker1 = 0x55555555;
+}
+
+int yaffs_ValidateTags(yaffs_ExtendedTags * tags)
+{
+ return (tags->validMarker0 == 0xAAAAAAAA &&
+ tags->validMarker1 == 0x55555555);
+
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+
+#ifndef __YAFFS_TAGS_VALIDITY_H__
+#define __YAFFS_TAGS_VALIDITY_H__
+
+#include "yaffs_guts.h"
+
+void yaffs_InitialiseTags(yaffs_ExtendedTags * tags);
+int yaffs_ValidateTags(yaffs_ExtendedTags * tags);
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * yaffscfg.c The configuration for the "direct" use of yaffs.
+ *
+ * This file is intended to be modified to your requirements.
+ * There is no need to redistribute this file.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+
+#include <config.h>
+#include "nand.h"
+#include "yaffscfg.h"
+#include "yaffsfs.h"
+#include "yaffs_packedtags2.h"
+#include "yaffs_mtdif.h"
+#include "yaffs_mtdif2.h"
+#if 0
+#include <errno.h>
+#else
+#include "malloc.h"
+#endif
+
+unsigned yaffs_traceMask = 0xFFFFFFFF;
+static int yaffs_errno = 0;
+
+void yaffsfs_SetError(int err)
+{
+ //Do whatever to set error
+ yaffs_errno = err;
+}
+
+int yaffsfs_GetError(void)
+{
+ return yaffs_errno;
+}
+
+void yaffsfs_Lock(void)
+{
+}
+
+void yaffsfs_Unlock(void)
+{
+}
+
+__u32 yaffsfs_CurrentTime(void)
+{
+ return 0;
+}
+
+void *yaffs_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+void yaffs_free(void *ptr)
+{
+ free(ptr);
+}
+
+void yaffsfs_LocalInitialisation(void)
+{
+ // Define locking semaphore.
+}
+
+// Configuration for:
+// /ram 2MB ramdisk
+// /boot 2MB boot disk (flash)
+// /flash 14MB flash disk (flash)
+// NB Though /boot and /flash occupy the same physical device they
+// are still disticnt "yaffs_Devices. You may think of these as "partitions"
+// using non-overlapping areas in the same device.
+//
+
+#include "yaffs_ramdisk.h"
+#include "yaffs_flashif.h"
+
+static int isMounted = 0;
+#define MOUNT_POINT "/flash"
+extern nand_info_t nand_info[];
+
+/* XXX U-BOOT XXX */
+#if 0
+static yaffs_Device ramDev;
+static yaffs_Device bootDev;
+static yaffs_Device flashDev;
+#endif
+
+static yaffsfs_DeviceConfiguration yaffsfs_config[] = {
+/* XXX U-BOOT XXX */
+#if 0
+ { "/ram", &ramDev},
+ { "/boot", &bootDev},
+ { "/flash", &flashDev},
+#else
+ { MOUNT_POINT, 0},
+#endif
+ {(void *)0,(void *)0}
+};
+
+
+int yaffs_StartUp(void)
+{
+ struct mtd_info *mtd = &nand_info[0];
+ int yaffsVersion = 2;
+ int nBlocks;
+
+ yaffs_Device *flashDev = calloc(1, sizeof(yaffs_Device));
+ yaffsfs_config[0].dev = flashDev;
+
+ // Stuff to configure YAFFS
+ // Stuff to initialise anything special (eg lock semaphore).
+ yaffsfs_LocalInitialisation();
+
+ // Set up devices
+
+/* XXX U-BOOT XXX */
+#if 0
+ // /ram
+ ramDev.nBytesPerChunk = 512;
+ ramDev.nChunksPerBlock = 32;
+ ramDev.nReservedBlocks = 2; // Set this smaller for RAM
+ ramDev.startBlock = 1; // Can't use block 0
+ ramDev.endBlock = 127; // Last block in 2MB.
+ ramDev.useNANDECC = 1;
+ ramDev.nShortOpCaches = 0; // Disable caching on this device.
+ ramDev.genericDevice = (void *) 0; // Used to identify the device in fstat.
+ ramDev.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND;
+ ramDev.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND;
+ ramDev.eraseBlockInNAND = yramdisk_EraseBlockInNAND;
+ ramDev.initialiseNAND = yramdisk_InitialiseNAND;
+
+ // /boot
+ bootDev.nBytesPerChunk = 612;
+ bootDev.nChunksPerBlock = 32;
+ bootDev.nReservedBlocks = 5;
+ bootDev.startBlock = 1; // Can't use block 0
+ bootDev.endBlock = 127; // Last block in 2MB.
+ bootDev.useNANDECC = 0; // use YAFFS's ECC
+ bootDev.nShortOpCaches = 10; // Use caches
+ bootDev.genericDevice = (void *) 1; // Used to identify the device in fstat.
+ bootDev.writeChunkToNAND = yflash_WriteChunkToNAND;
+ bootDev.readChunkFromNAND = yflash_ReadChunkFromNAND;
+ bootDev.eraseBlockInNAND = yflash_EraseBlockInNAND;
+ bootDev.initialiseNAND = yflash_InitialiseNAND;
+#endif
+
+ // /flash
+ flashDev->nReservedBlocks = 5;
+// flashDev->nShortOpCaches = (options.no_cache) ? 0 : 10;
+ flashDev->nShortOpCaches = 10; // Use caches
+ flashDev->useNANDECC = 0; // do not use YAFFS's ECC
+
+ if (yaffsVersion == 2)
+ {
+ flashDev->writeChunkWithTagsToNAND = nandmtd2_WriteChunkWithTagsToNAND;
+ flashDev->readChunkWithTagsFromNAND = nandmtd2_ReadChunkWithTagsFromNAND;
+ flashDev->markNANDBlockBad = nandmtd2_MarkNANDBlockBad;
+ flashDev->queryNANDBlock = nandmtd2_QueryNANDBlock;
+ flashDev->spareBuffer = YMALLOC(mtd->oobsize);
+ flashDev->isYaffs2 = 1;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ flashDev->nDataBytesPerChunk = mtd->writesize;
+ flashDev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
+#else
+ flashDev->nDataBytesPerChunk = mtd->oobblock;
+ flashDev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
+#endif
+ nBlocks = mtd->size / mtd->erasesize;
+
+ flashDev->nCheckpointReservedBlocks = 10;
+ flashDev->startBlock = 0;
+ flashDev->endBlock = nBlocks - 1;
+ }
+ else
+ {
+ flashDev->writeChunkToNAND = nandmtd_WriteChunkToNAND;
+ flashDev->readChunkFromNAND = nandmtd_ReadChunkFromNAND;
+ flashDev->isYaffs2 = 0;
+ nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
+ flashDev->startBlock = 320;
+ flashDev->endBlock = nBlocks - 1;
+ flashDev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
+ flashDev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+ }
+
+ /* ... and common functions */
+ flashDev->eraseBlockInNAND = nandmtd_EraseBlockInNAND;
+ flashDev->initialiseNAND = nandmtd_InitialiseNAND;
+
+ yaffs_initialise(yaffsfs_config);
+
+ return 0;
+}
+
+
+void make_a_file(char *yaffsName,char bval,int sizeOfFile)
+{
+ int outh;
+ int i;
+ unsigned char buffer[100];
+
+ outh = yaffs_open(yaffsName, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
+ if (outh < 0)
+ {
+ printf("Error opening file: %d\n", outh);
+ return;
+ }
+
+ memset(buffer,bval,100);
+
+ do{
+ i = sizeOfFile;
+ if(i > 100) i = 100;
+ sizeOfFile -= i;
+
+ yaffs_write(outh,buffer,i);
+
+ } while (sizeOfFile > 0);
+
+
+ yaffs_close(outh);
+}
+
+void read_a_file(char *fn)
+{
+ int h;
+ int i = 0;
+ unsigned char b;
+
+ h = yaffs_open(fn, O_RDWR,0);
+ if(h<0)
+ {
+ printf("File not found\n");
+ return;
+ }
+
+ while(yaffs_read(h,&b,1)> 0)
+ {
+ printf("%02x ",b);
+ i++;
+ if(i > 32)
+ {
+ printf("\n");
+ i = 0;;
+ }
+ }
+ printf("\n");
+ yaffs_close(h);
+}
+
+void cmd_yaffs_mount(char *mp)
+{
+ yaffs_StartUp();
+ int retval = yaffs_mount(mp);
+ if( retval != -1)
+ isMounted = 1;
+ else
+ printf("Error mounting %s, return value: %d\n", mp, yaffsfs_GetError());
+}
+
+static void checkMount(void)
+{
+ if( !isMounted )
+ {
+ cmd_yaffs_mount(MOUNT_POINT);
+ }
+}
+
+void cmd_yaffs_umount(char *mp)
+{
+ checkMount();
+ if( yaffs_unmount(mp) == -1)
+ printf("Error umounting %s, return value: %d\n", mp, yaffsfs_GetError());
+}
+
+void cmd_yaffs_write_file(char *yaffsName,char bval,int sizeOfFile)
+{
+ checkMount();
+ make_a_file(yaffsName,bval,sizeOfFile);
+}
+
+
+void cmd_yaffs_read_file(char *fn)
+{
+ checkMount();
+ read_a_file(fn);
+}
+
+
+void cmd_yaffs_mread_file(char *fn, char *addr)
+{
+ int h;
+ struct yaffs_stat s;
+
+ checkMount();
+
+ yaffs_stat(fn,&s);
+
+ printf ("Copy %s to 0x%08x... ", fn, addr);
+ h = yaffs_open(fn, O_RDWR,0);
+ if(h<0)
+ {
+ printf("File not found\n");
+ return;
+ }
+
+ yaffs_read(h,addr,(int)s.st_size);
+ printf("\t[DONE]\n");
+
+ yaffs_close(h);
+}
+
+
+void cmd_yaffs_mwrite_file(char *fn, char *addr, int size)
+{
+ int outh;
+
+ checkMount();
+ outh = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
+ if (outh < 0)
+ {
+ printf("Error opening file: %d\n", outh);
+ }
+
+ yaffs_write(outh,addr,size);
+
+ yaffs_close(outh);
+}
+
+
+void cmd_yaffs_ls(const char *mountpt, int longlist)
+{
+ int i;
+ yaffs_DIR *d;
+ yaffs_dirent *de;
+ struct yaffs_stat stat;
+ char tempstr[255];
+
+ checkMount();
+ d = yaffs_opendir(mountpt);
+
+ if(!d)
+ {
+ printf("opendir failed\n");
+ }
+ else
+ {
+ for(i = 0; (de = yaffs_readdir(d)) != NULL; i++)
+ {
+ if (longlist)
+ {
+ sprintf(tempstr, "%s/%s", mountpt, de->d_name);
+ yaffs_stat(tempstr, &stat);
+ printf("%-25s\t%7d\n",de->d_name, stat.st_size);
+ }
+ else
+ {
+ printf("%s\n",de->d_name);
+ }
+ }
+ }
+}
+
+
+void cmd_yaffs_mkdir(const char *dir)
+{
+ checkMount();
+
+ int retval = yaffs_mkdir(dir, 0);
+
+ if ( retval < 0)
+ printf("yaffs_mkdir returning error: %d\n", retval);
+}
+
+void cmd_yaffs_rmdir(const char *dir)
+{
+ checkMount();
+
+ int retval = yaffs_rmdir(dir);
+
+ if ( retval < 0)
+ printf("yaffs_rmdir returning error: %d\n", retval);
+}
+
+void cmd_yaffs_rm(const char *path)
+{
+ checkMount();
+
+ int retval = yaffs_unlink(path);
+
+ if ( retval < 0)
+ printf("yaffs_unlink returning error: %d\n", retval);
+}
+
+void cmd_yaffs_mv(const char *oldPath, const char *newPath)
+{
+ checkMount();
+
+ int retval = yaffs_rename(newPath, oldPath);
+
+ if ( retval < 0)
+ printf("yaffs_unlink returning error: %d\n", retval);
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/*
+ * Header file for using yaffs in an application via
+ * a direct interface.
+ */
+
+
+#ifndef __YAFFSCFG_H__
+#define __YAFFSCFG_H__
+
+
+#include "devextras.h"
+
+#define YAFFSFS_N_HANDLES 200
+
+
+typedef struct {
+ const char *prefix;
+ struct yaffs_DeviceStruct *dev;
+} yaffsfs_DeviceConfiguration;
+
+
+void yaffsfs_Lock(void);
+void yaffsfs_Unlock(void);
+
+__u32 yaffsfs_CurrentTime(void);
+
+void yaffsfs_SetError(int err);
+int yaffsfs_GetError(void);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* XXX U-BOOT XXX */
+#include <common.h>
+#include <malloc.h>
+
+#include "yaffsfs.h"
+#include "yaffs_guts.h"
+#include "yaffscfg.h"
+#include "yportenv.h"
+
+/* XXX U-BOOT XXX */
+#if 0
+#include <string.h> // for memset
+#endif
+
+#define YAFFSFS_MAX_SYMLINK_DEREFERENCES 5
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+
+const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.18 2007/07/18 19:40:38 charles Exp $";
+
+// configurationList is the list of devices that are supported
+static yaffsfs_DeviceConfiguration *yaffsfs_configurationList;
+
+
+/* Some forward references */
+static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path, int symDepth);
+static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj);
+
+
+// Handle management.
+//
+
+
+unsigned int yaffs_wr_attempts;
+
+typedef struct
+{
+ __u8 inUse:1; // this handle is in use
+ __u8 readOnly:1; // this handle is read only
+ __u8 append:1; // append only
+ __u8 exclusive:1; // exclusive
+ __u32 position; // current position in file
+ yaffs_Object *obj; // the object
+}yaffsfs_Handle;
+
+
+static yaffsfs_Handle yaffsfs_handle[YAFFSFS_N_HANDLES];
+
+// yaffsfs_InitHandle
+/// Inilitalise handles on start-up.
+//
+static int yaffsfs_InitHandles(void)
+{
+ int i;
+ for(i = 0; i < YAFFSFS_N_HANDLES; i++)
+ {
+ yaffsfs_handle[i].inUse = 0;
+ yaffsfs_handle[i].obj = NULL;
+ }
+ return 0;
+}
+
+yaffsfs_Handle *yaffsfs_GetHandlePointer(int h)
+{
+ if(h < 0 || h >= YAFFSFS_N_HANDLES)
+ {
+ return NULL;
+ }
+
+ return &yaffsfs_handle[h];
+}
+
+yaffs_Object *yaffsfs_GetHandleObject(int handle)
+{
+ yaffsfs_Handle *h = yaffsfs_GetHandlePointer(handle);
+
+ if(h && h->inUse)
+ {
+ return h->obj;
+ }
+
+ return NULL;
+}
+
+
+//yaffsfs_GetHandle
+// Grab a handle (when opening a file)
+//
+
+static int yaffsfs_GetHandle(void)
+{
+ int i;
+ yaffsfs_Handle *h;
+
+ for(i = 0; i < YAFFSFS_N_HANDLES; i++)
+ {
+ h = yaffsfs_GetHandlePointer(i);
+ if(!h)
+ {
+ // todo bug: should never happen
+ }
+ if(!h->inUse)
+ {
+ memset(h,0,sizeof(yaffsfs_Handle));
+ h->inUse=1;
+ return i;
+ }
+ }
+ return -1;
+}
+
+// yaffs_PutHandle
+// Let go of a handle (when closing a file)
+//
+static int yaffsfs_PutHandle(int handle)
+{
+ yaffsfs_Handle *h = yaffsfs_GetHandlePointer(handle);
+
+ if(h)
+ {
+ h->inUse = 0;
+ h->obj = NULL;
+ }
+ return 0;
+}
+
+
+
+// Stuff to search for a directory from a path
+
+
+int yaffsfs_Match(char a, char b)
+{
+ // case sensitive
+ return (a == b);
+}
+
+// yaffsfs_FindDevice
+// yaffsfs_FindRoot
+// Scan the configuration list to find the root.
+// Curveballs: Should match paths that end in '/' too
+// Curveball2 Might have "/x/ and "/x/y". Need to return the longest match
+static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath)
+{
+ yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList;
+ const char *leftOver;
+ const char *p;
+ yaffs_Device *retval = NULL;
+ int thisMatchLength;
+ int longestMatch = -1;
+
+ // Check all configs, choose the one that:
+ // 1) Actually matches a prefix (ie /a amd /abc will not match
+ // 2) Matches the longest.
+ while(cfg && cfg->prefix && cfg->dev)
+ {
+ leftOver = path;
+ p = cfg->prefix;
+ thisMatchLength = 0;
+
+ while(*p && //unmatched part of prefix
+ strcmp(p,"/") && // the rest of the prefix is not / (to catch / at end)
+ *leftOver &&
+ yaffsfs_Match(*p,*leftOver))
+ {
+ p++;
+ leftOver++;
+ thisMatchLength++;
+ }
+ if((!*p || strcmp(p,"/") == 0) && // end of prefix
+ (!*leftOver || *leftOver == '/') && // no more in this path name part
+ (thisMatchLength > longestMatch))
+ {
+ // Matched prefix
+ *restOfPath = (char *)leftOver;
+ retval = cfg->dev;
+ longestMatch = thisMatchLength;
+ }
+ cfg++;
+ }
+ return retval;
+}
+
+static yaffs_Object *yaffsfs_FindRoot(const char *path, char **restOfPath)
+{
+
+ yaffs_Device *dev;
+
+ dev= yaffsfs_FindDevice(path,restOfPath);
+ if(dev && dev->isMounted)
+ {
+ return dev->rootDir;
+ }
+ return NULL;
+}
+
+static yaffs_Object *yaffsfs_FollowLink(yaffs_Object *obj,int symDepth)
+{
+
+ while(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
+ {
+ char *alias = obj->variant.symLinkVariant.alias;
+
+ if(*alias == '/')
+ {
+ // Starts with a /, need to scan from root up
+ obj = yaffsfs_FindObject(NULL,alias,symDepth++);
+ }
+ else
+ {
+ // Relative to here, so use the parent of the symlink as a start
+ obj = yaffsfs_FindObject(obj->parent,alias,symDepth++);
+ }
+ }
+ return obj;
+}
+
+
+// yaffsfs_FindDirectory
+// Parse a path to determine the directory and the name within the directory.
+//
+// eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx"
+static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *path,char **name,int symDepth)
+{
+ yaffs_Object *dir;
+ char *restOfPath;
+ char str[YAFFS_MAX_NAME_LENGTH+1];
+ int i;
+
+ if(symDepth > YAFFSFS_MAX_SYMLINK_DEREFERENCES)
+ {
+ return NULL;
+ }
+
+ if(startDir)
+ {
+ dir = startDir;
+ restOfPath = (char *)path;
+ }
+ else
+ {
+ dir = yaffsfs_FindRoot(path,&restOfPath);
+ }
+
+ while(dir)
+ {
+ // parse off /.
+ // curve ball: also throw away surplus '/'
+ // eg. "/ram/x////ff" gets treated the same as "/ram/x/ff"
+ while(*restOfPath == '/')
+ {
+ restOfPath++; // get rid of '/'
+ }
+
+ *name = restOfPath;
+ i = 0;
+
+ while(*restOfPath && *restOfPath != '/')
+ {
+ if (i < YAFFS_MAX_NAME_LENGTH)
+ {
+ str[i] = *restOfPath;
+ str[i+1] = '\0';
+ i++;
+ }
+ restOfPath++;
+ }
+
+ if(!*restOfPath)
+ {
+ // got to the end of the string
+ return dir;
+ }
+ else
+ {
+ if(strcmp(str,".") == 0)
+ {
+ // Do nothing
+ }
+ else if(strcmp(str,"..") == 0)
+ {
+ dir = dir->parent;
+ }
+ else
+ {
+ dir = yaffs_FindObjectByName(dir,str);
+
+ while(dir && dir->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
+ {
+
+ dir = yaffsfs_FollowLink(dir,symDepth);
+
+ }
+
+ if(dir && dir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ dir = NULL;
+ }
+ }
+ }
+ }
+ // directory did not exist.
+ return NULL;
+}
+
+static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const char *path,char **name,int symDepth)
+{
+ return yaffsfs_DoFindDirectory(relativeDirectory,path,name,symDepth);
+}
+
+// yaffsfs_FindObject turns a path for an existing object into the object
+//
+static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path,int symDepth)
+{
+ yaffs_Object *dir;
+ char *name;
+
+ dir = yaffsfs_FindDirectory(relativeDirectory,path,&name,symDepth);
+
+ if(dir && *name)
+ {
+ return yaffs_FindObjectByName(dir,name);
+ }
+
+ return dir;
+}
+
+
+
+int yaffs_open(const char *path, int oflag, int mode)
+{
+ yaffs_Object *obj = NULL;
+ yaffs_Object *dir = NULL;
+ char *name;
+ int handle = -1;
+ yaffsfs_Handle *h = NULL;
+ int alreadyOpen = 0;
+ int alreadyExclusive = 0;
+ int openDenied = 0;
+ int symDepth = 0;
+ int errorReported = 0;
+
+ int i;
+
+
+ // todo sanity check oflag (eg. can't have O_TRUNC without WRONLY or RDWR
+
+
+ yaffsfs_Lock();
+
+ handle = yaffsfs_GetHandle();
+
+ if(handle >= 0)
+ {
+
+ h = yaffsfs_GetHandlePointer(handle);
+
+
+ // try to find the exisiting object
+ obj = yaffsfs_FindObject(NULL,path,0);
+
+ if(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
+ {
+
+ obj = yaffsfs_FollowLink(obj,symDepth++);
+ }
+
+ if(obj)
+ {
+ // Check if the object is already in use
+ alreadyOpen = alreadyExclusive = 0;
+
+ for(i = 0; i <= YAFFSFS_N_HANDLES; i++)
+ {
+
+ if(i != handle &&
+ yaffsfs_handle[i].inUse &&
+ obj == yaffsfs_handle[i].obj)
+ {
+ alreadyOpen = 1;
+ if(yaffsfs_handle[i].exclusive)
+ {
+ alreadyExclusive = 1;
+ }
+ }
+ }
+
+ if(((oflag & O_EXCL) && alreadyOpen) || alreadyExclusive)
+ {
+ openDenied = 1;
+ }
+
+ // Open should fail if O_CREAT and O_EXCL are specified
+ if((oflag & O_EXCL) && (oflag & O_CREAT))
+ {
+ openDenied = 1;
+ yaffsfs_SetError(-EEXIST);
+ errorReported = 1;
+ }
+
+ // Check file permissions
+ if( (oflag & (O_RDWR | O_WRONLY)) == 0 && // ie O_RDONLY
+ !(obj->yst_mode & S_IREAD))
+ {
+ openDenied = 1;
+ }
+
+ if( (oflag & O_RDWR) &&
+ !(obj->yst_mode & S_IREAD))
+ {
+ openDenied = 1;
+ }
+
+ if( (oflag & (O_RDWR | O_WRONLY)) &&
+ !(obj->yst_mode & S_IWRITE))
+ {
+ openDenied = 1;
+ }
+
+ }
+
+ else if((oflag & O_CREAT))
+ {
+ // Let's see if we can create this file
+ dir = yaffsfs_FindDirectory(NULL,path,&name,0);
+ if(dir)
+ {
+ obj = yaffs_MknodFile(dir,name,mode,0,0);
+ }
+ else
+ {
+ yaffsfs_SetError(-ENOTDIR);
+ }
+ }
+
+ if(obj && !openDenied)
+ {
+ h->obj = obj;
+ h->inUse = 1;
+ h->readOnly = (oflag & (O_WRONLY | O_RDWR)) ? 0 : 1;
+ h->append = (oflag & O_APPEND) ? 1 : 0;
+ h->exclusive = (oflag & O_EXCL) ? 1 : 0;
+ h->position = 0;
+
+ obj->inUse++;
+ if((oflag & O_TRUNC) && !h->readOnly)
+ {
+ //todo truncate
+ yaffs_ResizeFile(obj,0);
+ }
+
+ }
+ else
+ {
+ yaffsfs_PutHandle(handle);
+ if(!errorReported)
+ {
+ yaffsfs_SetError(-EACCESS);
+ errorReported = 1;
+ }
+ handle = -1;
+ }
+
+ }
+
+ yaffsfs_Unlock();
+
+ return handle;
+}
+
+int yaffs_close(int fd)
+{
+ yaffsfs_Handle *h = NULL;
+ int retVal = 0;
+
+ yaffsfs_Lock();
+
+ h = yaffsfs_GetHandlePointer(fd);
+
+ if(h && h->inUse)
+ {
+ // clean up
+ yaffs_FlushFile(h->obj,1);
+ h->obj->inUse--;
+ if(h->obj->inUse <= 0 && h->obj->unlinked)
+ {
+ yaffs_DeleteFile(h->obj);
+ }
+ yaffsfs_PutHandle(fd);
+ retVal = 0;
+ }
+ else
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ retVal = -1;
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+}
+
+int yaffs_read(int fd, void *buf, unsigned int nbyte)
+{
+ yaffsfs_Handle *h = NULL;
+ yaffs_Object *obj = NULL;
+ int pos = 0;
+ int nRead = -1;
+ int maxRead;
+
+ yaffsfs_Lock();
+ h = yaffsfs_GetHandlePointer(fd);
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(!h || !obj)
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+ else if( h && obj)
+ {
+ pos= h->position;
+ if(yaffs_GetObjectFileLength(obj) > pos)
+ {
+ maxRead = yaffs_GetObjectFileLength(obj) - pos;
+ }
+ else
+ {
+ maxRead = 0;
+ }
+
+ if(nbyte > maxRead)
+ {
+ nbyte = maxRead;
+ }
+
+
+ if(nbyte > 0)
+ {
+ nRead = yaffs_ReadDataFromFile(obj,buf,pos,nbyte);
+ if(nRead >= 0)
+ {
+ h->position = pos + nRead;
+ }
+ else
+ {
+ //todo error
+ }
+ }
+ else
+ {
+ nRead = 0;
+ }
+
+ }
+
+ yaffsfs_Unlock();
+
+
+ return (nRead >= 0) ? nRead : -1;
+
+}
+
+int yaffs_write(int fd, const void *buf, unsigned int nbyte)
+{
+ yaffsfs_Handle *h = NULL;
+ yaffs_Object *obj = NULL;
+ int pos = 0;
+ int nWritten = -1;
+ int writeThrough = 0;
+
+ yaffsfs_Lock();
+ h = yaffsfs_GetHandlePointer(fd);
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(!h || !obj)
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+ else if( h && obj && h->readOnly)
+ {
+ // todo error
+ }
+ else if( h && obj)
+ {
+ if(h->append)
+ {
+ pos = yaffs_GetObjectFileLength(obj);
+ }
+ else
+ {
+ pos = h->position;
+ }
+
+ nWritten = yaffs_WriteDataToFile(obj,buf,pos,nbyte,writeThrough);
+
+ if(nWritten >= 0)
+ {
+ h->position = pos + nWritten;
+ }
+ else
+ {
+ //todo error
+ }
+
+ }
+
+ yaffsfs_Unlock();
+
+
+ return (nWritten >= 0) ? nWritten : -1;
+
+}
+
+int yaffs_truncate(int fd, off_t newSize)
+{
+ yaffsfs_Handle *h = NULL;
+ yaffs_Object *obj = NULL;
+ int result = 0;
+
+ yaffsfs_Lock();
+ h = yaffsfs_GetHandlePointer(fd);
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(!h || !obj)
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+ else
+ {
+ // resize the file
+ result = yaffs_ResizeFile(obj,newSize);
+ }
+ yaffsfs_Unlock();
+
+
+ return (result) ? 0 : -1;
+
+}
+
+off_t yaffs_lseek(int fd, off_t offset, int whence)
+{
+ yaffsfs_Handle *h = NULL;
+ yaffs_Object *obj = NULL;
+ int pos = -1;
+ int fSize = -1;
+
+ yaffsfs_Lock();
+ h = yaffsfs_GetHandlePointer(fd);
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(!h || !obj)
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+ else if(whence == SEEK_SET)
+ {
+ if(offset >= 0)
+ {
+ pos = offset;
+ }
+ }
+ else if(whence == SEEK_CUR)
+ {
+ if( (h->position + offset) >= 0)
+ {
+ pos = (h->position + offset);
+ }
+ }
+ else if(whence == SEEK_END)
+ {
+ fSize = yaffs_GetObjectFileLength(obj);
+ if(fSize >= 0 && (fSize + offset) >= 0)
+ {
+ pos = fSize + offset;
+ }
+ }
+
+ if(pos >= 0)
+ {
+ h->position = pos;
+ }
+ else
+ {
+ // todo error
+ }
+
+
+ yaffsfs_Unlock();
+
+ return pos;
+}
+
+
+int yaffsfs_DoUnlink(const char *path,int isDirectory)
+{
+ yaffs_Object *dir = NULL;
+ yaffs_Object *obj = NULL;
+ char *name;
+ int result = YAFFS_FAIL;
+
+ yaffsfs_Lock();
+
+ obj = yaffsfs_FindObject(NULL,path,0);
+ dir = yaffsfs_FindDirectory(NULL,path,&name,0);
+ if(!dir)
+ {
+ yaffsfs_SetError(-ENOTDIR);
+ }
+ else if(!obj)
+ {
+ yaffsfs_SetError(-ENOENT);
+ }
+ else if(!isDirectory && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ yaffsfs_SetError(-EISDIR);
+ }
+ else if(isDirectory && obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ yaffsfs_SetError(-ENOTDIR);
+ }
+ else
+ {
+ result = yaffs_Unlink(dir,name);
+
+ if(result == YAFFS_FAIL && isDirectory)
+ {
+ yaffsfs_SetError(-ENOTEMPTY);
+ }
+ }
+
+ yaffsfs_Unlock();
+
+ // todo error
+
+ return (result == YAFFS_FAIL) ? -1 : 0;
+}
+int yaffs_rmdir(const char *path)
+{
+ return yaffsfs_DoUnlink(path,1);
+}
+
+int yaffs_unlink(const char *path)
+{
+ return yaffsfs_DoUnlink(path,0);
+}
+
+int yaffs_rename(const char *oldPath, const char *newPath)
+{
+ yaffs_Object *olddir = NULL;
+ yaffs_Object *newdir = NULL;
+ yaffs_Object *obj = NULL;
+ char *oldname;
+ char *newname;
+ int result= YAFFS_FAIL;
+ int renameAllowed = 1;
+
+ yaffsfs_Lock();
+
+ olddir = yaffsfs_FindDirectory(NULL,oldPath,&oldname,0);
+ newdir = yaffsfs_FindDirectory(NULL,newPath,&newname,0);
+ obj = yaffsfs_FindObject(NULL,oldPath,0);
+
+ if(!olddir || !newdir || !obj)
+ {
+ // bad file
+ yaffsfs_SetError(-EBADF);
+ renameAllowed = 0;
+ }
+ else if(olddir->myDev != newdir->myDev)
+ {
+ // oops must be on same device
+ // todo error
+ yaffsfs_SetError(-EXDEV);
+ renameAllowed = 0;
+ }
+ else if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ // It is a directory, check that it is not being renamed to
+ // being its own decendent.
+ // Do this by tracing from the new directory back to the root, checking for obj
+
+ yaffs_Object *xx = newdir;
+
+ while( renameAllowed && xx)
+ {
+ if(xx == obj)
+ {
+ renameAllowed = 0;
+ }
+ xx = xx->parent;
+ }
+ if(!renameAllowed) yaffsfs_SetError(-EACCESS);
+ }
+
+ if(renameAllowed)
+ {
+ result = yaffs_RenameObject(olddir,oldname,newdir,newname);
+ }
+
+ yaffsfs_Unlock();
+
+ return (result == YAFFS_FAIL) ? -1 : 0;
+}
+
+
+static int yaffsfs_DoStat(yaffs_Object *obj,struct yaffs_stat *buf)
+{
+ int retVal = -1;
+
+ if(obj)
+ {
+ obj = yaffs_GetEquivalentObject(obj);
+ }
+
+ if(obj && buf)
+ {
+ buf->st_dev = (int)obj->myDev->genericDevice;
+ buf->st_ino = obj->objectId;
+ buf->st_mode = obj->yst_mode & ~S_IFMT; // clear out file type bits
+
+ if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+ buf->st_mode |= S_IFDIR;
+ }
+ else if(obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
+ {
+ buf->st_mode |= S_IFLNK;
+ }
+ else if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
+ {
+ buf->st_mode |= S_IFREG;
+ }
+
+ buf->st_nlink = yaffs_GetObjectLinkCount(obj);
+ buf->st_uid = 0;
+ buf->st_gid = 0;;
+ buf->st_rdev = obj->yst_rdev;
+ buf->st_size = yaffs_GetObjectFileLength(obj);
+ buf->st_blksize = obj->myDev->nDataBytesPerChunk;
+ buf->st_blocks = (buf->st_size + buf->st_blksize -1)/buf->st_blksize;
+ buf->yst_atime = obj->yst_atime;
+ buf->yst_ctime = obj->yst_ctime;
+ buf->yst_mtime = obj->yst_mtime;
+ retVal = 0;
+ }
+ return retVal;
+}
+
+static int yaffsfs_DoStatOrLStat(const char *path, struct yaffs_stat *buf,int doLStat)
+{
+ yaffs_Object *obj;
+
+ int retVal = -1;
+
+ yaffsfs_Lock();
+ obj = yaffsfs_FindObject(NULL,path,0);
+
+ if(!doLStat && obj)
+ {
+ obj = yaffsfs_FollowLink(obj,0);
+ }
+
+ if(obj)
+ {
+ retVal = yaffsfs_DoStat(obj,buf);
+ }
+ else
+ {
+ // todo error not found
+ yaffsfs_SetError(-ENOENT);
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+
+}
+
+int yaffs_stat(const char *path, struct yaffs_stat *buf)
+{
+ return yaffsfs_DoStatOrLStat(path,buf,0);
+}
+
+int yaffs_lstat(const char *path, struct yaffs_stat *buf)
+{
+ return yaffsfs_DoStatOrLStat(path,buf,1);
+}
+
+int yaffs_fstat(int fd, struct yaffs_stat *buf)
+{
+ yaffs_Object *obj;
+
+ int retVal = -1;
+
+ yaffsfs_Lock();
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(obj)
+ {
+ retVal = yaffsfs_DoStat(obj,buf);
+ }
+ else
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+}
+
+static int yaffsfs_DoChMod(yaffs_Object *obj,mode_t mode)
+{
+ int result = YAFFS_FAIL;
+
+ if(obj)
+ {
+ obj = yaffs_GetEquivalentObject(obj);
+ }
+
+ if(obj)
+ {
+ obj->yst_mode = mode;
+ obj->dirty = 1;
+ result = yaffs_FlushFile(obj,0);
+ }
+
+ return result == YAFFS_OK ? 0 : -1;
+}
+
+
+int yaffs_chmod(const char *path, mode_t mode)
+{
+ yaffs_Object *obj;
+
+ int retVal = -1;
+
+ yaffsfs_Lock();
+ obj = yaffsfs_FindObject(NULL,path,0);
+
+ if(obj)
+ {
+ retVal = yaffsfs_DoChMod(obj,mode);
+ }
+ else
+ {
+ // todo error not found
+ yaffsfs_SetError(-ENOENT);
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+
+}
+
+
+int yaffs_fchmod(int fd, mode_t mode)
+{
+ yaffs_Object *obj;
+
+ int retVal = -1;
+
+ yaffsfs_Lock();
+ obj = yaffsfs_GetHandleObject(fd);
+
+ if(obj)
+ {
+ retVal = yaffsfs_DoChMod(obj,mode);
+ }
+ else
+ {
+ // bad handle
+ yaffsfs_SetError(-EBADF);
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+}
+
+
+int yaffs_mkdir(const char *path, mode_t mode)
+{
+ yaffs_Object *parent = NULL;
+ yaffs_Object *dir = NULL;
+ char *name;
+ int retVal= -1;
+
+ yaffsfs_Lock();
+ parent = yaffsfs_FindDirectory(NULL,path,&name,0);
+ if(parent)
+ dir = yaffs_MknodDirectory(parent,name,mode,0,0);
+ if(dir)
+ {
+ retVal = 0;
+ }
+ else
+ {
+ yaffsfs_SetError(-ENOSPC); // just assume no space for now
+ retVal = -1;
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+}
+
+int yaffs_mount(const char *path)
+{
+ int retVal=-1;
+ int result=YAFFS_FAIL;
+ yaffs_Device *dev=NULL;
+ char *dummy;
+
+ T(YAFFS_TRACE_ALWAYS,("yaffs: Mounting %s\n",path));
+
+ yaffsfs_Lock();
+ dev = yaffsfs_FindDevice(path,&dummy);
+ if(dev)
+ {
+ if(!dev->isMounted)
+ {
+ result = yaffs_GutsInitialise(dev);
+ if(result == YAFFS_FAIL)
+ {
+ // todo error - mount failed
+ yaffsfs_SetError(-ENOMEM);
+ }
+ retVal = result ? 0 : -1;
+
+ }
+ else
+ {
+ //todo error - already mounted.
+ yaffsfs_SetError(-EBUSY);
+ }
+ }
+ else
+ {
+ // todo error - no device
+ yaffsfs_SetError(-ENODEV);
+ }
+ yaffsfs_Unlock();
+ return retVal;
+
+}
+
+int yaffs_unmount(const char *path)
+{
+ int retVal=-1;
+ yaffs_Device *dev=NULL;
+ char *dummy;
+
+ yaffsfs_Lock();
+ dev = yaffsfs_FindDevice(path,&dummy);
+ if(dev)
+ {
+ if(dev->isMounted)
+ {
+ int i;
+ int inUse;
+
+ yaffs_FlushEntireDeviceCache(dev);
+ yaffs_CheckpointSave(dev);
+
+ for(i = inUse = 0; i < YAFFSFS_N_HANDLES && !inUse; i++)
+ {
+ if(yaffsfs_handle[i].inUse && yaffsfs_handle[i].obj->myDev == dev)
+ {
+ inUse = 1; // the device is in use, can't unmount
+ }
+ }
+
+ if(!inUse)
+ {
+ yaffs_Deinitialise(dev);
+
+ retVal = 0;
+ }
+ else
+ {
+ // todo error can't unmount as files are open
+ yaffsfs_SetError(-EBUSY);
+ }
+
+ }
+ else
+ {
+ //todo error - not mounted.
+ yaffsfs_SetError(-EINVAL);
+
+ }
+ }
+ else
+ {
+ // todo error - no device
+ yaffsfs_SetError(-ENODEV);
+ }
+ yaffsfs_Unlock();
+ return retVal;
+
+}
+
+loff_t yaffs_freespace(const char *path)
+{
+ loff_t retVal=-1;
+ yaffs_Device *dev=NULL;
+ char *dummy;
+
+ yaffsfs_Lock();
+ dev = yaffsfs_FindDevice(path,&dummy);
+ if(dev && dev->isMounted)
+ {
+ retVal = yaffs_GetNumberOfFreeChunks(dev);
+ retVal *= dev->nDataBytesPerChunk;
+
+ }
+ else
+ {
+ yaffsfs_SetError(-EINVAL);
+ }
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+
+
+void yaffs_initialise(yaffsfs_DeviceConfiguration *cfgList)
+{
+
+ yaffsfs_DeviceConfiguration *cfg;
+
+ yaffsfs_configurationList = cfgList;
+
+ yaffsfs_InitHandles();
+
+ cfg = yaffsfs_configurationList;
+
+ while(cfg && cfg->prefix && cfg->dev)
+ {
+ cfg->dev->isMounted = 0;
+ cfg->dev->removeObjectCallback = yaffsfs_RemoveObjectCallback;
+ cfg++;
+ }
+}
+
+
+//
+// Directory search stuff.
+
+//
+// Directory search context
+//
+// NB this is an opaque structure.
+
+
+typedef struct
+{
+ __u32 magic;
+ yaffs_dirent de; /* directory entry being used by this dsc */
+ char name[NAME_MAX+1]; /* name of directory being searched */
+ yaffs_Object *dirObj; /* ptr to directory being searched */
+ yaffs_Object *nextReturn; /* obj to be returned by next readddir */
+ int offset;
+ struct list_head others;
+} yaffsfs_DirectorySearchContext;
+
+
+
+static struct list_head search_contexts;
+
+
+static void yaffsfs_SetDirRewound(yaffsfs_DirectorySearchContext *dsc)
+{
+ if(dsc &&
+ dsc->dirObj &&
+ dsc->dirObj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY){
+
+ dsc->offset = 0;
+
+ if( list_empty(&dsc->dirObj->variant.directoryVariant.children)){
+ dsc->nextReturn = NULL;
+ } else {
+ dsc->nextReturn = list_entry(dsc->dirObj->variant.directoryVariant.children.next,
+ yaffs_Object,siblings);
+ }
+ } else {
+ /* Hey someone isn't playing nice! */
+ }
+}
+
+static void yaffsfs_DirAdvance(yaffsfs_DirectorySearchContext *dsc)
+{
+ if(dsc &&
+ dsc->dirObj &&
+ dsc->dirObj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY){
+
+ if( dsc->nextReturn == NULL ||
+ list_empty(&dsc->dirObj->variant.directoryVariant.children)){
+ dsc->nextReturn = NULL;
+ } else {
+ struct list_head *next = dsc->nextReturn->siblings.next;
+
+ if( next == &dsc->dirObj->variant.directoryVariant.children)
+ dsc->nextReturn = NULL; /* end of list */
+ else
+ dsc->nextReturn = list_entry(next,yaffs_Object,siblings);
+ }
+ } else {
+ /* Hey someone isn't playing nice! */
+ }
+}
+
+static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj)
+{
+
+ struct list_head *i;
+ yaffsfs_DirectorySearchContext *dsc;
+
+ /* if search contexts not initilised then skip */
+ if(!search_contexts.next)
+ return;
+
+ /* Iteratethrough the directory search contexts.
+ * If any are the one being removed, then advance the dsc to
+ * the next one to prevent a hanging ptr.
+ */
+ list_for_each(i, &search_contexts) {
+ if (i) {
+ dsc = list_entry(i, yaffsfs_DirectorySearchContext,others);
+ if(dsc->nextReturn == obj)
+ yaffsfs_DirAdvance(dsc);
+ }
+ }
+
+}
+
+yaffs_DIR *yaffs_opendir(const char *dirname)
+{
+ yaffs_DIR *dir = NULL;
+ yaffs_Object *obj = NULL;
+ yaffsfs_DirectorySearchContext *dsc = NULL;
+
+ yaffsfs_Lock();
+
+ obj = yaffsfs_FindObject(NULL,dirname,0);
+
+ if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+ {
+
+ dsc = YMALLOC(sizeof(yaffsfs_DirectorySearchContext));
+ dir = (yaffs_DIR *)dsc;
+ if(dsc)
+ {
+ memset(dsc,0,sizeof(yaffsfs_DirectorySearchContext));
+ dsc->magic = YAFFS_MAGIC;
+ dsc->dirObj = obj;
+ strncpy(dsc->name,dirname,NAME_MAX);
+ INIT_LIST_HEAD(&dsc->others);
+
+ if(!search_contexts.next)
+ INIT_LIST_HEAD(&search_contexts);
+
+ list_add(&dsc->others,&search_contexts);
+ yaffsfs_SetDirRewound(dsc); }
+
+ }
+
+ yaffsfs_Unlock();
+
+ return dir;
+}
+
+struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp)
+{
+ yaffsfs_DirectorySearchContext *dsc = (yaffsfs_DirectorySearchContext *)dirp;
+ struct yaffs_dirent *retVal = NULL;
+
+ yaffsfs_Lock();
+
+ if(dsc && dsc->magic == YAFFS_MAGIC){
+ yaffsfs_SetError(0);
+ if(dsc->nextReturn){
+ dsc->de.d_ino = yaffs_GetEquivalentObject(dsc->nextReturn)->objectId;
+ dsc->de.d_dont_use = (unsigned)dsc->nextReturn;
+ dsc->de.d_off = dsc->offset++;
+ yaffs_GetObjectName(dsc->nextReturn,dsc->de.d_name,NAME_MAX);
+ if(strlen(dsc->de.d_name) == 0)
+ {
+ // this should not happen!
+ strcpy(dsc->de.d_name,"zz");
+ }
+ dsc->de.d_reclen = sizeof(struct yaffs_dirent);
+ retVal = &dsc->de;
+ yaffsfs_DirAdvance(dsc);
+ } else
+ retVal = NULL;
+ }
+ else
+ {
+ yaffsfs_SetError(-EBADF);
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+
+}
+
+
+void yaffs_rewinddir(yaffs_DIR *dirp)
+{
+ yaffsfs_DirectorySearchContext *dsc = (yaffsfs_DirectorySearchContext *)dirp;
+
+ yaffsfs_Lock();
+
+ yaffsfs_SetDirRewound(dsc);
+
+ yaffsfs_Unlock();
+}
+
+
+int yaffs_closedir(yaffs_DIR *dirp)
+{
+ yaffsfs_DirectorySearchContext *dsc = (yaffsfs_DirectorySearchContext *)dirp;
+
+ yaffsfs_Lock();
+ dsc->magic = 0;
+ list_del(&dsc->others); /* unhook from list */
+ YFREE(dsc);
+ yaffsfs_Unlock();
+ return 0;
+}
+
+// end of directory stuff
+
+
+int yaffs_symlink(const char *oldpath, const char *newpath)
+{
+ yaffs_Object *parent = NULL;
+ yaffs_Object *obj;
+ char *name;
+ int retVal= -1;
+ int mode = 0; // ignore for now
+
+ yaffsfs_Lock();
+ parent = yaffsfs_FindDirectory(NULL,newpath,&name,0);
+ obj = yaffs_MknodSymLink(parent,name,mode,0,0,oldpath);
+ if(obj)
+ {
+ retVal = 0;
+ }
+ else
+ {
+ yaffsfs_SetError(-ENOSPC); // just assume no space for now
+ retVal = -1;
+ }
+
+ yaffsfs_Unlock();
+
+ return retVal;
+
+}
+
+int yaffs_readlink(const char *path, char *buf, int bufsiz)
+{
+ yaffs_Object *obj = NULL;
+ int retVal;
+
+
+ yaffsfs_Lock();
+
+ obj = yaffsfs_FindObject(NULL,path,0);
+
+ if(!obj)
+ {
+ yaffsfs_SetError(-ENOENT);
+ retVal = -1;
+ }
+ else if(obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK)
+ {
+ yaffsfs_SetError(-EINVAL);
+ retVal = -1;
+ }
+ else
+ {
+ char *alias = obj->variant.symLinkVariant.alias;
+ memset(buf,0,bufsiz);
+ strncpy(buf,alias,bufsiz - 1);
+ retVal = 0;
+ }
+ yaffsfs_Unlock();
+ return retVal;
+}
+
+int yaffs_link(const char *oldpath, const char *newpath)
+{
+ // Creates a link called newpath to existing oldpath
+ yaffs_Object *obj = NULL;
+ yaffs_Object *target = NULL;
+ int retVal = 0;
+
+
+ yaffsfs_Lock();
+
+ obj = yaffsfs_FindObject(NULL,oldpath,0);
+ target = yaffsfs_FindObject(NULL,newpath,0);
+
+ if(!obj)
+ {
+ yaffsfs_SetError(-ENOENT);
+ retVal = -1;
+ }
+ else if(target)
+ {
+ yaffsfs_SetError(-EEXIST);
+ retVal = -1;
+ }
+ else
+ {
+ yaffs_Object *newdir = NULL;
+ yaffs_Object *link = NULL;
+
+ char *newname;
+
+ newdir = yaffsfs_FindDirectory(NULL,newpath,&newname,0);
+
+ if(!newdir)
+ {
+ yaffsfs_SetError(-ENOTDIR);
+ retVal = -1;
+ }
+ else if(newdir->myDev != obj->myDev)
+ {
+ yaffsfs_SetError(-EXDEV);
+ retVal = -1;
+ }
+ if(newdir && strlen(newname) > 0)
+ {
+ link = yaffs_Link(newdir,newname,obj);
+ if(link)
+ retVal = 0;
+ else
+ {
+ yaffsfs_SetError(-ENOSPC);
+ retVal = -1;
+ }
+
+ }
+ }
+ yaffsfs_Unlock();
+
+ return retVal;
+}
+
+int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev);
+
+int yaffs_DumpDevStruct(const char *path)
+{
+ char *rest;
+
+ yaffs_Object *obj = yaffsfs_FindRoot(path,&rest);
+
+ if(obj)
+ {
+ yaffs_Device *dev = obj->myDev;
+
+ printf("\n"
+ "nPageWrites.......... %d\n"
+ "nPageReads........... %d\n"
+ "nBlockErasures....... %d\n"
+ "nGCCopies............ %d\n"
+ "garbageCollections... %d\n"
+ "passiveGarbageColl'ns %d\n"
+ "\n",
+ dev->nPageWrites,
+ dev->nPageReads,
+ dev->nBlockErasures,
+ dev->nGCCopies,
+ dev->garbageCollections,
+ dev->passiveGarbageCollections
+ );
+
+ }
+ return 0;
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/*
+ * Header file for using yaffs in an application via
+ * a direct interface.
+ */
+
+
+#ifndef __YAFFSFS_H__
+#define __YAFFSFS_H__
+
+#include "yaffscfg.h"
+#include "yportenv.h"
+
+
+//typedef long off_t;
+//typedef long dev_t;
+//typedef unsigned long mode_t;
+
+
+#ifndef NAME_MAX
+#define NAME_MAX 256
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 00
+#endif
+
+#ifndef O_WRONLY
+#define O_WRONLY 01
+#endif
+
+#ifndef O_RDWR
+#define O_RDWR 02
+#endif
+
+#ifndef O_CREAT
+#define O_CREAT 0100
+#endif
+
+#ifndef O_EXCL
+#define O_EXCL 0200
+#endif
+
+#ifndef O_TRUNC
+#define O_TRUNC 01000
+#endif
+
+#ifndef O_APPEND
+#define O_APPEND 02000
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef EBUSY
+#define EBUSY 16
+#endif
+
+#ifndef ENODEV
+#define ENODEV 19
+#endif
+
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+
+#ifndef EBADF
+#define EBADF 9
+#endif
+
+#ifndef EACCESS
+#define EACCESS 13
+#endif
+
+#ifndef EXDEV
+#define EXDEV 18
+#endif
+
+#ifndef ENOENT
+#define ENOENT 2
+#endif
+
+#ifndef ENOSPC
+#define ENOSPC 28
+#endif
+
+#ifndef ENOTEMPTY
+#define ENOTEMPTY 39
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+
+#ifndef EEXIST
+#define EEXIST 17
+#endif
+
+#ifndef ENOTDIR
+#define ENOTDIR 20
+#endif
+
+#ifndef EISDIR
+#define EISDIR 21
+#endif
+
+
+// Mode flags
+
+#ifndef S_IFMT
+#define S_IFMT 0170000
+#endif
+
+#ifndef S_IFLNK
+#define S_IFLNK 0120000
+#endif
+
+#ifndef S_IFDIR
+#define S_IFDIR 0040000
+#endif
+
+#ifndef S_IFREG
+#define S_IFREG 0100000
+#endif
+
+#ifndef S_IREAD
+#define S_IREAD 0000400
+#endif
+
+#ifndef S_IWRITE
+#define S_IWRITE 0000200
+#endif
+
+
+
+
+struct yaffs_dirent{
+ long d_ino; /* inode number */
+ off_t d_off; /* offset to this dirent */
+ unsigned short d_reclen; /* length of this d_name */
+ char d_name [NAME_MAX+1]; /* file name (null-terminated) */
+ unsigned d_dont_use; /* debug pointer, not for public consumption */
+};
+
+typedef struct yaffs_dirent yaffs_dirent;
+
+
+typedef struct __opaque yaffs_DIR;
+
+
+
+struct yaffs_stat{
+ int st_dev; /* device */
+ int st_ino; /* inode */
+ mode_t st_mode; /* protection */
+ int st_nlink; /* number of hard links */
+ int st_uid; /* user ID of owner */
+ int st_gid; /* group ID of owner */
+ unsigned st_rdev; /* device type (if inode device) */
+ off_t st_size; /* total size, in bytes */
+ unsigned long st_blksize; /* blocksize for filesystem I/O */
+ unsigned long st_blocks; /* number of blocks allocated */
+ unsigned long yst_atime; /* time of last access */
+ unsigned long yst_mtime; /* time of last modification */
+ unsigned long yst_ctime; /* time of last change */
+};
+
+int yaffs_open(const char *path, int oflag, int mode) ;
+int yaffs_read(int fd, void *buf, unsigned int nbyte) ;
+int yaffs_write(int fd, const void *buf, unsigned int nbyte) ;
+int yaffs_close(int fd) ;
+off_t yaffs_lseek(int fd, off_t offset, int whence) ;
+int yaffs_truncate(int fd, off_t newSize);
+
+int yaffs_unlink(const char *path) ;
+int yaffs_rename(const char *oldPath, const char *newPath) ;
+
+int yaffs_stat(const char *path, struct yaffs_stat *buf) ;
+int yaffs_lstat(const char *path, struct yaffs_stat *buf) ;
+int yaffs_fstat(int fd, struct yaffs_stat *buf) ;
+
+int yaffs_chmod(const char *path, mode_t mode);
+int yaffs_fchmod(int fd, mode_t mode);
+
+int yaffs_mkdir(const char *path, mode_t mode) ;
+int yaffs_rmdir(const char *path) ;
+
+yaffs_DIR *yaffs_opendir(const char *dirname) ;
+struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp) ;
+void yaffs_rewinddir(yaffs_DIR *dirp) ;
+int yaffs_closedir(yaffs_DIR *dirp) ;
+
+int yaffs_mount(const char *path) ;
+int yaffs_unmount(const char *path) ;
+
+int yaffs_symlink(const char *oldpath, const char *newpath);
+int yaffs_readlink(const char *path, char *buf, int bufsiz);
+
+int yaffs_link(const char *oldpath, const char *newpath);
+int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev);
+
+loff_t yaffs_freespace(const char *path);
+
+void yaffs_initialise(yaffsfs_DeviceConfiguration *configList);
+
+int yaffs_StartUp(void);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFSINTERFACE_H__
+#define __YAFFSINTERFACE_H__
+
+int yaffs_Initialise(unsigned nBlocks);
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/*
+ * ydirectenv.h: Environment wrappers for YAFFS direct.
+ */
+
+#ifndef __YDIRECTENV_H__
+#define __YDIRECTENV_H__
+
+/* Direct interface */
+
+#include "devextras.h"
+
+/* XXX U-BOOT XXX */
+#if 0
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+#include "assert.h"
+#endif
+#include "yaffs_malloc.h"
+
+/* XXX U-BOOT XXX */
+#if 0
+#define YBUG() assert(1)
+#endif
+
+#define YCHAR char
+#define YUCHAR unsigned char
+#define _Y(x) x
+#define yaffs_strcpy(a,b) strcpy(a,b)
+#define yaffs_strncpy(a,b,c) strncpy(a,b,c)
+#define yaffs_strncmp(a,b,c) strncmp(a,b,c)
+#define yaffs_strlen(s) strlen(s)
+#define yaffs_sprintf sprintf
+#define yaffs_toupper(a) toupper(a)
+
+#ifdef NO_Y_INLINE
+#define Y_INLINE
+#else
+#define Y_INLINE inline
+#endif
+
+#define YMALLOC(x) yaffs_malloc(x)
+#define YFREE(x) free(x)
+#define YMALLOC_ALT(x) yaffs_malloc(x)
+#define YFREE_ALT(x) free(x)
+
+#define YMALLOC_DMA(x) yaffs_malloc(x)
+
+#define YYIELD() do {} while(0)
+
+
+
+//#define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s))
+//#define YALERT(s) YINFO(s)
+
+
+#define TENDSTR "\n"
+#define TSTR(x) x
+#define TOUT(p) printf p
+
+
+#define YAFFS_LOSTNFOUND_NAME "lost+found"
+#define YAFFS_LOSTNFOUND_PREFIX "obj"
+//#define YPRINTF(x) printf x
+
+#include "yaffscfg.h"
+
+#define Y_CURRENT_TIME yaffsfs_CurrentTime()
+#define Y_TIME_CONVERT(x) x
+
+#define YAFFS_ROOT_MODE 0666
+#define YAFFS_LOSTNFOUND_MODE 0666
+
+#define yaffs_SumCompare(x,y) ((x) == (y))
+#define yaffs_strcmp(a,b) strcmp(a,b)
+
+#endif
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2007 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+
+#ifndef __YPORTENV_H__
+#define __YPORTENV_H__
+
+/* XXX U-BOOT XXX */
+#ifndef CONFIG_YAFFS_DIRECT
+#define CONFIG_YAFFS_DIRECT
+#endif
+
+#if defined CONFIG_YAFFS_WINCE
+
+#include "ywinceenv.h"
+
+/* XXX U-BOOT XXX */
+#elif 0 /* defined __KERNEL__ */
+
+#include "moduleconfig.h"
+
+/* Linux kernel */
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+#include <linux/config.h>
+#endif
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#define YCHAR char
+#define YUCHAR unsigned char
+#define _Y(x) x
+#define yaffs_strcpy(a,b) strcpy(a,b)
+#define yaffs_strncpy(a,b,c) strncpy(a,b,c)
+#define yaffs_strncmp(a,b,c) strncmp(a,b,c)
+#define yaffs_strlen(s) strlen(s)
+#define yaffs_sprintf sprintf
+#define yaffs_toupper(a) toupper(a)
+
+#define Y_INLINE inline
+
+#define YAFFS_LOSTNFOUND_NAME "lost+found"
+#define YAFFS_LOSTNFOUND_PREFIX "obj"
+
+/* #define YPRINTF(x) printk x */
+#define YMALLOC(x) kmalloc(x,GFP_KERNEL)
+#define YFREE(x) kfree(x)
+#define YMALLOC_ALT(x) vmalloc(x)
+#define YFREE_ALT(x) vfree(x)
+#define YMALLOC_DMA(x) YMALLOC(x)
+
+// KR - added for use in scan so processes aren't blocked indefinitely.
+#define YYIELD() schedule()
+
+#define YAFFS_ROOT_MODE 0666
+#define YAFFS_LOSTNFOUND_MODE 0666
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#define Y_CURRENT_TIME CURRENT_TIME.tv_sec
+#define Y_TIME_CONVERT(x) (x).tv_sec
+#else
+#define Y_CURRENT_TIME CURRENT_TIME
+#define Y_TIME_CONVERT(x) (x)
+#endif
+
+#define yaffs_SumCompare(x,y) ((x) == (y))
+#define yaffs_strcmp(a,b) strcmp(a,b)
+
+#define TENDSTR "\n"
+#define TSTR(x) KERN_WARNING x
+#define TOUT(p) printk p
+
+#define yaffs_trace(mask, fmt, args...) \
+ do { if ((mask) & (yaffs_traceMask|YAFFS_TRACE_ERROR)) \
+ printk(KERN_WARNING "yaffs: " fmt, ## args); \
+ } while (0)
+
+#define compile_time_assertion(assertion) \
+ ({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; })
+
+#elif defined CONFIG_YAFFS_DIRECT
+
+/* Direct interface */
+#include "ydirectenv.h"
+
+#elif defined CONFIG_YAFFS_UTIL
+
+/* Stuff for YAFFS utilities */
+
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+
+#include "devextras.h"
+
+#define YMALLOC(x) malloc(x)
+#define YFREE(x) free(x)
+#define YMALLOC_ALT(x) malloc(x)
+#define YFREE_ALT(x) free(x)
+
+#define YCHAR char
+#define YUCHAR unsigned char
+#define _Y(x) x
+#define yaffs_strcpy(a,b) strcpy(a,b)
+#define yaffs_strncpy(a,b,c) strncpy(a,b,c)
+#define yaffs_strlen(s) strlen(s)
+#define yaffs_sprintf sprintf
+#define yaffs_toupper(a) toupper(a)
+
+#define Y_INLINE inline
+
+/* #define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s)) */
+/* #define YALERT(s) YINFO(s) */
+
+#define TENDSTR "\n"
+#define TSTR(x) x
+#define TOUT(p) printf p
+
+#define YAFFS_LOSTNFOUND_NAME "lost+found"
+#define YAFFS_LOSTNFOUND_PREFIX "obj"
+/* #define YPRINTF(x) printf x */
+
+#define YAFFS_ROOT_MODE 0666
+#define YAFFS_LOSTNFOUND_MODE 0666
+
+#define yaffs_SumCompare(x,y) ((x) == (y))
+#define yaffs_strcmp(a,b) strcmp(a,b)
+
+#else
+/* Should have specified a configuration type */
+#error Unknown configuration
+
+#endif
+
+/* see yaffs_fs.c */
+extern unsigned int yaffs_traceMask;
+extern unsigned int yaffs_wr_attempts;
+
+/*
+ * Tracing flags.
+ * The flags masked in YAFFS_TRACE_ALWAYS are always traced.
+ */
+
+#define YAFFS_TRACE_OS 0x00000002
+#define YAFFS_TRACE_ALLOCATE 0x00000004
+#define YAFFS_TRACE_SCAN 0x00000008
+#define YAFFS_TRACE_BAD_BLOCKS 0x00000010
+#define YAFFS_TRACE_ERASE 0x00000020
+#define YAFFS_TRACE_GC 0x00000040
+#define YAFFS_TRACE_WRITE 0x00000080
+#define YAFFS_TRACE_TRACING 0x00000100
+#define YAFFS_TRACE_DELETION 0x00000200
+#define YAFFS_TRACE_BUFFERS 0x00000400
+#define YAFFS_TRACE_NANDACCESS 0x00000800
+#define YAFFS_TRACE_GC_DETAIL 0x00001000
+#define YAFFS_TRACE_SCAN_DEBUG 0x00002000
+#define YAFFS_TRACE_MTD 0x00004000
+#define YAFFS_TRACE_CHECKPOINT 0x00008000
+
+#define YAFFS_TRACE_VERIFY 0x00010000
+#define YAFFS_TRACE_VERIFY_NAND 0x00020000
+#define YAFFS_TRACE_VERIFY_FULL 0x00040000
+#define YAFFS_TRACE_VERIFY_ALL 0x000F0000
+
+
+#define YAFFS_TRACE_ERROR 0x40000000
+#define YAFFS_TRACE_BUG 0x80000000
+#define YAFFS_TRACE_ALWAYS 0xF0000000
+
+
+#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0)
+
+#ifndef CONFIG_YAFFS_WINCE
+#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))
+#endif
+
+#endif
#define MUX_CTL_CSPI2_SS2 0x87
#define MUX_CTL_CSPI2_MOSI 0x8b
-/* The modes a specific pin can be in
- * these macros can be used in mx31_gpio_mux() and have the form
- * MUX_[contact name]__[pin function]
+/*
+ * Helper macros for the MUX_[contact name]__[pin function] macros
*/
-#define MUX_RXD1__UART1_RXD_MUX ((MUX_CTL_FUNC << 8) | MUX_CTL_RXD1)
-#define MUX_TXD1__UART1_TXD_MUX ((MUX_CTL_FUNC << 8) | MUX_CTL_TXD1)
-#define MUX_RTS1__UART1_RTS_B ((MUX_CTL_FUNC << 8) | MUX_CTL_RTS1)
-#define MUX_RTS1__UART1_CTS_B ((MUX_CTL_FUNC << 8) | MUX_CTL_CTS1)
+#define IOMUX_MODE_POS 9
+#define IOMUX_MODE(contact, mode) (((mode) << IOMUX_MODE_POS) | (contact))
-#define MUX_CSPI2_MOSI__I2C2_SCL ((MUX_CTL_ALT1 << 8) | MUX_CTL_CSPI2_MOSI)
-#define MUX_CSPI2_MISO__I2C2_SCL ((MUX_CTL_ALT1 << 8) | MUX_CTL_CSPI2_MISO)
+/*
+ * These macros can be used in mx31_gpio_mux() and have the form
+ * MUX_[contact name]__[pin function]
+ */
+#define MUX_RXD1__UART1_RXD_MUX IOMUX_MODE(MUX_CTL_RXD1, MUX_CTL_FUNC)
+#define MUX_TXD1__UART1_TXD_MUX IOMUX_MODE(MUX_CTL_TXD1, MUX_CTL_FUNC)
+#define MUX_RTS1__UART1_RTS_B IOMUX_MODE(MUX_CTL_RTS1, MUX_CTL_FUNC)
+#define MUX_CTS1__UART1_CTS_B IOMUX_MODE(MUX_CTL_CTS1, MUX_CTL_FUNC)
+
+#define MUX_CSPI2_SS0__CSPI2_SS0_B IOMUX_MODE(MUX_CTL_CSPI2_SS0, MUX_CTL_FUNC)
+#define MUX_CSPI2_SS1__CSPI2_SS1_B IOMUX_MODE(MUX_CTL_CSPI2_SS1, MUX_CTL_FUNC)
+#define MUX_CSPI2_SS2__CSPI2_SS2_B IOMUX_MODE(MUX_CTL_CSPI2_SS2, MUX_CTL_FUNC)
+#define MUX_CSPI2_MOSI__CSPI2_MOSI IOMUX_MODE(MUX_CTL_CSPI2_MOSI, MUX_CTL_FUNC)
+#define MUX_CSPI2_MISO__CSPI2_MISO IOMUX_MODE(MUX_CTL_CSPI2_MISO, MUX_CTL_FUNC)
+#define MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B \
+ IOMUX_MODE(MUX_CTL_CSPI2_SPI_RDY, MUX_CTL_FUNC)
+#define MUX_CSPI2_SCLK__CSPI2_CLK IOMUX_MODE(MUX_CTL_CSPI2_SCLK, MUX_CTL_FUNC)
+
+#define MUX_CSPI2_MOSI__I2C2_SCL IOMUX_MODE(MUX_CTL_CSPI2_MOSI, MUX_CTL_ALT1)
+#define MUX_CSPI2_MISO__I2C2_SDA IOMUX_MODE(MUX_CTL_CSPI2_MISO, MUX_CTL_ALT1)
/*
* Memory regions and CS
#define CFG_NUM_IRQS (128)
#endif /* CONFIG_M5329 && CONFIG_M5373 */
-#ifdef CONFIG_M54455
+#if defined(CONFIG_M54451) || defined(CONFIG_M54455)
#include <asm/immap_5445x.h>
#include <asm/m5445x.h>
#define CFG_FEC0_IOBASE (MMAP_FEC0)
+#if defined(CONFIG_M54455EVB)
#define CFG_FEC1_IOBASE (MMAP_FEC1)
+#endif
#define CFG_UART_BASE (MMAP_UART0 + (CFG_UART_PORT * 0x4000))
#define CFG_PCI_TBATR0 (CFG_MBAR)
#define CFG_PCI_TBATR5 (CFG_SDRAM_BASE)
#endif
-#endif /* CONFIG_M54455 */
+#endif /* CONFIG_M54451 || CONFIG_M54455 */
#ifdef CONFIG_M547x
#include <asm/immap_547x_8x.h>
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef INTERRUPT_H
+#define INTERRUPT_H
+
+#if defined(CONFIG_XILINX_440)
+#include <asm/xilinx_irq.h>
+#else
+#include <asm/ppc4xx-uic.h>
+#endif
+
+void pic_enable(void);
+void pic_irq_enable(unsigned int irq);
+void pic_irq_disable(unsigned int irq);
+void pic_irq_ack(unsigned int irq);
+void external_interrupt(struct pt_regs *regs);
+void interrupt_run_handler(int vec);
+
+#endif
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Stefan Roese, DENX Software Engineering, sr@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
+ */
+
+#ifndef _PPC4xx_EBC_H_
+#define _PPC4xx_EBC_H_
+
+/*
+ * Currently there are two register layout versions for the
+ * IBM EBC core used on 4xx PPC's:
+ */
+#if defined(CONFIG_405CR) || defined(CONFIG_405GP) || \
+ defined(CONFIG_405EP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#define CONFIG_EBC_PPC4xx_IBM_VER1
+#endif
+
+/* Bank Configuration Register */
+#define EBC_BXCR_BAS_MASK PPC_REG_VAL(11, 0xFFF)
+#define EBC_BXCR_BAS_ENCODE(n) (((static_cast(u32, n)) & EBC_BXCR_BAS_MASK))
+#define EBC_BXCR_BS_MASK PPC_REG_VAL(14, 0x7)
+#define EBC_BXCR_BS_1MB PPC_REG_VAL(14, 0x0)
+#define EBC_BXCR_BS_2MB PPC_REG_VAL(14, 0x1)
+#define EBC_BXCR_BS_4MB PPC_REG_VAL(14, 0x2)
+#define EBC_BXCR_BS_8MB PPC_REG_VAL(14, 0x3)
+#define EBC_BXCR_BS_16MB PPC_REG_VAL(14, 0x4)
+#define EBC_BXCR_BS_32MB PPC_REG_VAL(14, 0x5)
+#define EBC_BXCR_BS_64MB PPC_REG_VAL(14, 0x6)
+#define EBC_BXCR_BS_128MB PPC_REG_VAL(14, 0x7)
+#define EBC_BXCR_BU_MASK PPC_REG_VAL(16, 0x3)
+#define EBC_BXCR_BU_NONE PPC_REG_VAL(16, 0x0)
+#define EBC_BXCR_BU_R PPC_REG_VAL(16, 0x1)
+#define EBC_BXCR_BU_W PPC_REG_VAL(16, 0x2)
+#define EBC_BXCR_BU_RW PPC_REG_VAL(16, 0x3)
+#define EBC_BXCR_BW_MASK PPC_REG_VAL(18, 0x3)
+#define EBC_BXCR_BW_8BIT PPC_REG_VAL(18, 0x0)
+#define EBC_BXCR_BW_16BIT PPC_REG_VAL(18, 0x1)
+#if defined(CONFIG_EBC_PPC4xx_IBM_VER1)
+#define EBC_BXCR_BW_32BIT PPC_REG_VAL(18, 0x2)
+#else
+#define EBC_BXCR_BW_32BIT PPC_REG_VAL(18, 0x3)
+#endif
+
+/* Bank Access Parameter Register */
+#define EBC_BXAP_BME_ENABLED PPC_REG_VAL(0, 0x1)
+#define EBC_BXAP_BME_DISABLED PPC_REG_VAL(0, 0x0)
+#define EBC_BXAP_TWT_ENCODE(n) PPC_REG_VAL(8, (static_cast(u32, n)) & 0xFF)
+#define EBC_BXAP_FWT_ENCODE(n) PPC_REG_VAL(5, (static_cast(u32, n)) & 0x1F)
+#define EBC_BXAP_BWT_ENCODE(n) PPC_REG_VAL(8, (static_cast(u32, n)) & 0x7)
+#define EBC_BXAP_BCE_DISABLE PPC_REG_VAL(9, 0x0)
+#define EBC_BXAP_BCE_ENABLE PPC_REG_VAL(9, 0x1)
+#define EBC_BXAP_BCT_MASK PPC_REG_VAL(11, 0x3)
+#define EBC_BXAP_BCT_2TRANS PPC_REG_VAL(11, 0x0)
+#define EBC_BXAP_BCT_4TRANS PPC_REG_VAL(11, 0x1)
+#define EBC_BXAP_BCT_8TRANS PPC_REG_VAL(11, 0x2)
+#define EBC_BXAP_BCT_16TRANS PPC_REG_VAL(11, 0x3)
+#define EBC_BXAP_CSN_ENCODE(n) PPC_REG_VAL(13, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_OEN_ENCODE(n) PPC_REG_VAL(15, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_WBN_ENCODE(n) PPC_REG_VAL(17, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_WBF_ENCODE(n) PPC_REG_VAL(19, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_TH_ENCODE(n) PPC_REG_VAL(22, (static_cast(u32, n)) & 0x7)
+#define EBC_BXAP_RE_ENABLED PPC_REG_VAL(23, 0x1)
+#define EBC_BXAP_RE_DISABLED PPC_REG_VAL(23, 0x0)
+#define EBC_BXAP_SOR_DELAYED PPC_REG_VAL(24, 0x0)
+#define EBC_BXAP_SOR_NONDELAYED PPC_REG_VAL(24, 0x1)
+#define EBC_BXAP_BEM_WRITEONLY PPC_REG_VAL(25, 0x0)
+#define EBC_BXAP_BEM_RW PPC_REG_VAL(25, 0x1)
+#define EBC_BXAP_PEN_DISABLED PPC_REG_VAL(26, 0x0)
+#define EBC_BXAP_PEN_ENABLED PPC_REG_VAL(26, 0x1)
+
+/* Common fields in EBC0_CFG register */
+#define EBC_CFG_PTD_MASK PPC_REG_VAL(1, 0x1)
+#define EBC_CFG_PTD_ENABLE PPC_REG_VAL(1, 0x0)
+#define EBC_CFG_PTD_DISABLE PPC_REG_VAL(1, 0x1)
+#define EBC_CFG_RTC_MASK PPC_REG_VAL(4, 0x7)
+#define EBC_CFG_RTC_16PERCLK PPC_REG_VAL(4, 0x0)
+#define EBC_CFG_RTC_32PERCLK PPC_REG_VAL(4, 0x1)
+#define EBC_CFG_RTC_64PERCLK PPC_REG_VAL(4, 0x2)
+#define EBC_CFG_RTC_128PERCLK PPC_REG_VAL(4, 0x3)
+#define EBC_CFG_RTC_256PERCLK PPC_REG_VAL(4, 0x4)
+#define EBC_CFG_RTC_512PERCLK PPC_REG_VAL(4, 0x5)
+#define EBC_CFG_RTC_1024PERCLK PPC_REG_VAL(4, 0x6)
+#define EBC_CFG_RTC_2048PERCLK PPC_REG_VAL(4, 0x7)
+#define EBC_CFG_PME_MASK PPC_REG_VAL(14, 0x1)
+#define EBC_CFG_PME_DISABLE PPC_REG_VAL(14, 0x0)
+#define EBC_CFG_PME_ENABLE PPC_REG_VAL(14, 0x1)
+#define EBC_CFG_PMT_MASK PPC_REG_VAL(19, 0x1F)
+#define EBC_CFG_PMT_ENCODE(n) PPC_REG_VAL(19, (static_cast(u32, n)) & 0x1F)
+
+/* Now the two versions of the other bits */
+#if defined(CONFIG_EBC_PPC4xx_IBM_VER1)
+#define EBC_CFG_EBTC_MASK PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_EBTC_HI PPC_REG_VAL(0, 0x0)
+#define EBC_CFG_EBTC_DRIVEN PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_EMPH_MASK PPC_REG_VAL(6, 0x3)
+#define EBC_CFG_EMPH_ENCODE(n) PPC_REG_VAL(6, (static_cast(u32, n)) & 0x3)
+#define EBC_CFG_EMPL_MASK PPC_REG_VAL(8, 0x3)
+#define EBC_CFG_EMPL_ENCODE(n) PPC_REG_VAL(8, (static_cast(u32, n)) & 0x3)
+#define EBC_CFG_CSTC_MASK PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_CSTC_HI PPC_REG_VAL(9, 0x0)
+#define EBC_CFG_CSTC_DRIVEN PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_BPR_MASK PPC_REG_VAL(11, 0x3)
+#define EBC_CFG_BPR_1DW PPC_REG_VAL(11, 0x0)
+#define EBC_CFG_BPR_2DW PPC_REG_VAL(11, 0x1)
+#define EBC_CFG_BPR_4DW PPC_REG_VAL(11, 0x2)
+#define EBC_CFG_EMS_MASK PPC_REG_VAL(13, 0x3)
+#define EBC_CFG_EMS_8BIT PPC_REG_VAL(13, 0x0)
+#define EBC_CFG_EMS_16BIT PPC_REG_VAL(13, 0x1)
+#define EBC_CFG_EMS_32BIT PPC_REG_VAL(13, 0x2)
+#else
+#define EBC_CFG_LE_MASK PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_LE_UNLOCK PPC_REG_VAL(0, 0x0)
+#define EBC_CFG_LE_LOCK PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_ATC_MASK PPC_REG_VAL(5, 0x1)
+#define EBC_CFG_ATC_HI PPC_REG_VAL(5, 0x0)
+#define EBC_CFG_ATC_PREVIOUS PPC_REG_VAL(5, 0x1)
+#define EBC_CFG_DTC_MASK PPC_REG_VAL(6, 0x1)
+#define EBC_CFG_DTC_HI PPC_REG_VAL(6, 0x0)
+#define EBC_CFG_DTC_PREVIOUS PPC_REG_VAL(6, 0x1)
+#define EBC_CFG_CTC_MASK PPC_REG_VAL(7, 0x1)
+#define EBC_CFG_CTC_HI PPC_REG_VAL(7, 0x0)
+#define EBC_CFG_CTC_PREVIOUS PPC_REG_VAL(7, 0x1)
+#define EBC_CFG_OEO_MASK PPC_REG_VAL(8, 0x1)
+#define EBC_CFG_OEO_HI PPC_REG_VAL(8, 0x0)
+#define EBC_CFG_OEO_PREVIOUS PPC_REG_VAL(8, 0x1)
+#define EBC_CFG_EMC_MASK PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_EMC_NONDEFAULT PPC_REG_VAL(9, 0x0)
+#define EBC_CFG_EMC_DEFAULT PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_PR_MASK PPC_REG_VAL(21, 0x3)
+#define EBC_CFG_PR_16 PPC_REG_VAL(21, 0x0)
+#define EBC_CFG_PR_32 PPC_REG_VAL(21, 0x1)
+#define EBC_CFG_PR_64 PPC_REG_VAL(21, 0x2)
+#define EBC_CFG_PR_128 PPC_REG_VAL(21, 0x3)
+#endif
+
+#endif /* _PPC4xx_EBC_H_ */
+++ /dev/null
-/*
-* Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com>
-*
-* 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
-*/
-
-/*
- * Interrupt vector number definitions to ease the
- * 405 -- 440 porting pain ;-)
- *
- * NOTE: They're not all here yet ... update as needed.
- *
- */
-
-#ifndef _VECNUMS_H_
-#define _VECNUMS_H_
-
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-
-/* UIC 0 */
-#define VECNUM_U0 0 /* UART 0 */
-#define VECNUM_U1 1 /* UART 1 */
-#define VECNUM_IIC0 2 /* IIC */
-#define VECNUM_KRD 3 /* Kasumi Ready for data */
-#define VECNUM_KDA 4 /* Kasumi Data Available */
-#define VECNUM_PCRW 5 /* PCI command register write */
-#define VECNUM_PPM 6 /* PCI power management */
-#define VECNUM_IIC1 7 /* IIC */
-#define VECNUM_SPI 8 /* SPI */
-#define VECNUM_EPCISER 9 /* External PCI SERR */
-#define VECNUM_MTE 10 /* MAL TXEOB */
-#define VECNUM_MRE 11 /* MAL RXEOB */
-#define VECNUM_D0 12 /* DMA channel 0 */
-#define VECNUM_D1 13 /* DMA channel 1 */
-#define VECNUM_D2 14 /* DMA channel 2 */
-#define VECNUM_D3 15 /* DMA channel 3 */
-#define VECNUM_UD0 16 /* UDMA irq 0 */
-#define VECNUM_UD1 17 /* UDMA irq 1 */
-#define VECNUM_UD2 18 /* UDMA irq 2 */
-#define VECNUM_UD3 19 /* UDMA irq 3 */
-#define VECNUM_HSB2D 20 /* USB2.0 Device */
-#define VECNUM_USBDEV 20 /* USB 1.1/USB 2.0 Device */
-#define VECNUM_OHCI1 21 /* USB2.0 Host OHCI irq 1 */
-#define VECNUM_OHCI2 22 /* USB2.0 Host OHCI irq 2 */
-#define VECNUM_EIP94 23 /* Security EIP94 */
-#define VECNUM_ETH0 24 /* Emac 0 */
-#define VECNUM_ETH1 25 /* Emac 1 */
-#define VECNUM_EHCI 26 /* USB2.0 Host EHCI */
-#define VECNUM_EIR4 27 /* External interrupt 4 */
-#define VECNUM_UIC2NC 28 /* UIC2 non-critical interrupt */
-#define VECNUM_UIC2C 29 /* UIC2 critical interrupt */
-#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */
-#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */
-
-/* UIC 1 */
-#define VECNUM_MS (32 + 0) /* MAL SERR */
-#define VECNUM_MTDE (32 + 1) /* MAL TXDE */
-#define VECNUM_MRDE (32 + 2) /* MAL RXDE */
-#define VECNUM_U2 (32 + 3) /* UART 2 */
-#define VECNUM_U3 (32 + 4) /* UART 3 */
-#define VECNUM_EBCO (32 + 5) /* EBCO interrupt status */
-#define VECNUM_NDFC (32 + 6) /* NDFC */
-#define VECNUM_KSLE (32 + 7) /* KASUMI slave error */
-#define VECNUM_CT5 (32 + 8) /* GPT compare timer 5 */
-#define VECNUM_CT6 (32 + 9) /* GPT compare timer 6 */
-#define VECNUM_PLB34I0 (32 + 10) /* PLB3X4X MIRQ0 */
-#define VECNUM_PLB34I1 (32 + 11) /* PLB3X4X MIRQ1 */
-#define VECNUM_PLB34I2 (32 + 12) /* PLB3X4X MIRQ2 */
-#define VECNUM_PLB34I3 (32 + 13) /* PLB3X4X MIRQ3 */
-#define VECNUM_PLB34I4 (32 + 14) /* PLB3X4X MIRQ4 */
-#define VECNUM_PLB34I5 (32 + 15) /* PLB3X4X MIRQ5 */
-#define VECNUM_CT0 (32 + 16) /* GPT compare timer 0 */
-#define VECNUM_CT1 (32 + 17) /* GPT compare timer 1 */
-#define VECNUM_EIR7 (32 + 18) /* External interrupt 7 */
-#define VECNUM_EIR8 (32 + 19) /* External interrupt 8 */
-#define VECNUM_EIR9 (32 + 20) /* External interrupt 9 */
-#define VECNUM_CT2 (32 + 21) /* GPT compare timer 2 */
-#define VECNUM_CT3 (32 + 22) /* GPT compare timer 3 */
-#define VECNUM_CT4 (32 + 23) /* GPT compare timer 4 */
-#define VECNUM_SRE (32 + 24) /* Serial ROM error */
-#define VECNUM_GPTDC (32 + 25) /* GPT decrementer pulse */
-#define VECNUM_RSVD0 (32 + 26) /* Reserved */
-#define VECNUM_EPCIPER (32 + 27) /* External PCI PERR */
-#define VECNUM_EIR0 (32 + 28) /* External interrupt 0 */
-#define VECNUM_EWU0 (32 + 29) /* Ethernet 0 wakeup */
-#define VECNUM_EIR1 (32 + 30) /* External interrupt 1 */
-#define VECNUM_EWU1 (32 + 31) /* Ethernet 1 wakeup */
-
-#define VECNUM_TXDE VECNUM_MTDE
-#define VECNUM_RXDE VECNUM_MRDE
-
-/* UIC 2 */
-#define VECNUM_EIR5 (64 + 0) /* External interrupt 5 */
-#define VECNUM_EIR6 (64 + 1) /* External interrupt 6 */
-#define VECNUM_OPB (64 + 2) /* OPB to PLB bridge int stat */
-#define VECNUM_EIR2 (64 + 3) /* External interrupt 2 */
-#define VECNUM_EIR3 (64 + 4) /* External interrupt 3 */
-#define VECNUM_DDR2 (64 + 5) /* DDR2 sdram */
-#define VECNUM_MCTX0 (64 + 6) /* MAl intp coalescence TX0 */
-#define VECNUM_MCTX1 (64 + 7) /* MAl intp coalescence TX1 */
-#define VECNUM_MCTR0 (64 + 8) /* MAl intp coalescence TR0 */
-#define VECNUM_MCTR1 (64 + 9) /* MAl intp coalescence TR1 */
-
-#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
-
-/* UIC 0 */
-#define VECNUM_U1 1 /* UART1 */
-#define VECNUM_IIC0 2 /* IIC0 */
-#define VECNUM_IIC1 3 /* IIC1 */
-#define VECNUM_PIM 4 /* PCI inbound message */
-#define VECNUM_PCRW 5 /* PCI command reg write */
-#define VECNUM_PPM 6 /* PCI power management */
-#define VECNUM_MSI0 8 /* PCI MSI level 0 */
-#define VECNUM_EIR0 9 /* External interrupt 0 */
-#define VECNUM_UIC2NC 10 /* UIC2 non-critical interrupt */
-#define VECNUM_UIC2C 11 /* UIC2 critical interrupt */
-#define VECNUM_D0 12 /* DMA channel 0 */
-#define VECNUM_D1 13 /* DMA channel 1 */
-#define VECNUM_D2 14 /* DMA channel 2 */
-#define VECNUM_D3 15 /* DMA channel 3 */
-#define VECNUM_UIC3NC 16 /* UIC3 non-critical interrupt */
-#define VECNUM_UIC3C 17 /* UIC3 critical interrupt */
-#define VECNUM_EIR1 9 /* External interrupt 1 */
-#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */
-#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */
-
-/* UIC 1 */
-#define VECNUM_EIR2 (32 + 0) /* External interrupt 0 */
-#define VECNUM_U0 (32 + 1) /* UART0 */
-#define VECNUM_EIR3 (32 + 20) /* External interrupt 3 */
-#define VECNUM_EIR4 (32 + 21) /* External interrupt 4 */
-#define VECNUM_EIR5 (32 + 26) /* External interrupt 5 */
-#define VECNUM_EIR6 (32 + 27) /* External interrupt 6 */
-#define VECNUM_U2 (32 + 28) /* UART2 */
-#define VECNUM_U3 (32 + 29) /* UART3 */
-#define VECNUM_EIR7 (32 + 30) /* External interrupt 7 */
-#define VECNUM_EIR8 (32 + 31) /* External interrupt 8 */
-
-/* UIC 2 */
-#define VECNUM_EIR9 (64 + 2) /* External interrupt 9 */
-#define VECNUM_MS (64 + 3) /* MAL SERR */
-#define VECNUM_TXDE (64 + 4) /* MAL TXDE */
-#define VECNUM_RXDE (64 + 5) /* MAL RXDE */
-#define VECNUM_MTE (64 + 6) /* MAL TXEOB */
-#define VECNUM_MRE (64 + 7) /* MAL RXEOB */
-#define VECNUM_ETH0 (64 + 16) /* Ethernet 0 */
-#define VECNUM_ETH1 (64 + 17) /* Ethernet 1 */
-#define VECNUM_ETH2 (64 + 18) /* Ethernet 2 */
-#define VECNUM_ETH3 (64 + 19) /* Ethernet 3 */
-#define VECNUM_EWU0 (64 + 20) /* Emac 0 wakeup */
-#define VECNUM_EWU1 (64 + 21) /* Emac 1 wakeup */
-#define VECNUM_EWU2 (64 + 22) /* Emac 2 wakeup */
-#define VECNUM_EWU3 (64 + 23) /* Emac 3 wakeup */
-#define VECNUM_EIR10 (64 + 24) /* External interrupt 10 */
-#define VECNUM_EIR11 (64 + 25) /* External interrupt 11 */
-
-/* UIC 3 */
-#define VECNUM_EIR12 (96 + 20) /* External interrupt 20 */
-#define VECNUM_EIR13 (96 + 21) /* External interrupt 21 */
-#define VECNUM_EIR14 (96 + 22) /* External interrupt 22 */
-#define VECNUM_EIR15 (96 + 23) /* External interrupt 23 */
-#define VECNUM_PCIEMSI0 (96 + 24) /* PCI Express MSI level 0 */
-#define VECNUM_PCIEMSI1 (96 + 25) /* PCI Express MSI level 1 */
-#define VECNUM_PCIEMSI2 (96 + 26) /* PCI Express MSI level 2 */
-#define VECNUM_PCIEMSI3 (96 + 27) /* PCI Express MSI level 3 */
-#define VECNUM_PCIEMSI4 (96 + 28) /* PCI Express MSI level 4 */
-#define VECNUM_PCIEMSI5 (96 + 29) /* PCI Express MSI level 5 */
-#define VECNUM_PCIEMSI6 (96 + 30) /* PCI Express MSI level 6 */
-#define VECNUM_PCIEMSI7 (96 + 31) /* PCI Express MSI level 7 */
-
-#elif defined(CONFIG_440SPE)
-
-/* UIC 0 */
-#define VECNUM_U0 0 /* UART0 */
-#define VECNUM_U1 1 /* UART1 */
-#define VECNUM_IIC0 2 /* IIC0 */
-#define VECNUM_IIC1 3 /* IIC1 */
-#define VECNUM_PIM 4 /* PCI inbound message */
-#define VECNUM_PCRW 5 /* PCI command reg write */
-#define VECNUM_PPM 6 /* PCI power management */
-#define VECNUM_MSI0 7 /* PCI MSI level 0 */
-#define VECNUM_MSI1 8 /* PCI MSI level 0 */
-#define VECNUM_MSI2 9 /* PCI MSI level 0 */
-#define VECNUM_UIC2NC 10 /* UIC2 non-critical interrupt */
-#define VECNUM_UIC2C 11 /* UIC2 critical interrupt */
-#define VECNUM_D0 12 /* DMA channel 0 */
-#define VECNUM_D1 13 /* DMA channel 1 */
-#define VECNUM_D2 14 /* DMA channel 2 */
-#define VECNUM_D3 15 /* DMA channel 3 */
-#define VECNUM_UIC3NC 16 /* UIC3 non-critical interrupt */
-#define VECNUM_UIC3C 17 /* UIC3 critical interrupt */
-#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */
-#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */
-
-/* UIC 1 */
-#define VECNUM_MS (32 + 1 ) /* MAL SERR */
-#define VECNUM_TXDE (32 + 2 ) /* MAL TXDE */
-#define VECNUM_RXDE (32 + 3 ) /* MAL RXDE */
-#define VECNUM_MTE (32 + 6 ) /* MAL Tx EOB */
-#define VECNUM_MRE (32 + 7 ) /* MAL Rx EOB */
-#define VECNUM_CT0 (32 + 12 ) /* GPT compare timer 0 */
-#define VECNUM_CT1 (32 + 13 ) /* GPT compare timer 1 */
-#define VECNUM_CT2 (32 + 14 ) /* GPT compare timer 2 */
-#define VECNUM_CT3 (32 + 15 ) /* GPT compare timer 3 */
-#define VECNUM_CT4 (32 + 16 ) /* GPT compare timer 4 */
-#define VECNUM_ETH0 (32 + 28) /* Ethernet interrupt status */
-#define VECNUM_EWU0 (32 + 29) /* Emac wakeup */
-
-/* UIC 2 */
-#define VECNUM_EIR5 (64 + 24) /* External interrupt 5 */
-#define VECNUM_EIR4 (64 + 25) /* External interrupt 4 */
-#define VECNUM_EIR3 (64 + 26) /* External interrupt 3 */
-#define VECNUM_EIR2 (64 + 27) /* External interrupt 2 */
-#define VECNUM_EIR1 (64 + 28) /* External interrupt 1 */
-#define VECNUM_EIR0 (64 + 29) /* External interrupt 0 */
-
-#elif defined(CONFIG_440SP)
-
-/* UIC 0 */
-#define VECNUM_U0 0 /* UART0 */
-#define VECNUM_U1 1 /* UART1 */
-#define VECNUM_IIC0 2 /* IIC0 */
-#define VECNUM_IIC1 3 /* IIC1 */
-#define VECNUM_PIM 4 /* PCI inbound message */
-#define VECNUM_PCRW 5 /* PCI command reg write */
-#define VECNUM_PPM 6 /* PCI power management */
-#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */
-#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */
-
-/* UIC 1 */
-#define VECNUM_EIR0 (32 + 0) /* External interrupt 0 */
-#define VECNUM_MS (32 + 1) /* MAL SERR */
-#define VECNUM_TXDE (32 + 2) /* MAL TXDE */
-#define VECNUM_RXDE (32 + 3) /* MAL RXDE */
-#define VECNUM_MTE (32 + 6) /* MAL Tx EOB */
-#define VECNUM_MRE (32 + 7) /* MAL Rx EOB */
-#define VECNUM_CT0 (32 + 12) /* GPT compare timer 0 */
-#define VECNUM_CT1 (32 + 13) /* GPT compare timer 1 */
-#define VECNUM_CT2 (32 + 14) /* GPT compare timer 2 */
-#define VECNUM_CT3 (32 + 15) /* GPT compare timer 3 */
-#define VECNUM_CT4 (32 + 16) /* GPT compare timer 4 */
-#define VECNUM_ETH0 (32 + 28) /* Ethernet interrupt status */
-#define VECNUM_EWU0 (32 + 29) /* Emac wakeup */
-
-#elif defined(CONFIG_440)
-
-/* UIC 0 */
-#define VECNUM_U0 0 /* UART0 */
-#define VECNUM_U1 1 /* UART1 */
-#define VECNUM_IIC0 2 /* IIC0 */
-#define VECNUM_IIC1 3 /* IIC1 */
-#define VECNUM_PIM 4 /* PCI inbound message */
-#define VECNUM_PCRW 5 /* PCI command reg write */
-#define VECNUM_PPM 6 /* PCI power management */
-#define VECNUM_MSI0 7 /* PCI MSI level 0 */
-#define VECNUM_MSI1 8 /* PCI MSI level 0 */
-#define VECNUM_MSI2 9 /* PCI MSI level 0 */
-#define VECNUM_MTE 10 /* MAL TXEOB */
-#define VECNUM_MRE 11 /* MAL RXEOB */
-#define VECNUM_D0 12 /* DMA channel 0 */
-#define VECNUM_D1 13 /* DMA channel 1 */
-#define VECNUM_D2 14 /* DMA channel 2 */
-#define VECNUM_D3 15 /* DMA channel 3 */
-#define VECNUM_CT0 18 /* GPT compare timer 0 */
-#define VECNUM_CT1 19 /* GPT compare timer 1 */
-#define VECNUM_CT2 20 /* GPT compare timer 2 */
-#define VECNUM_CT3 21 /* GPT compare timer 3 */
-#define VECNUM_CT4 22 /* GPT compare timer 4 */
-#define VECNUM_EIR0 23 /* External interrupt 0 */
-#define VECNUM_EIR1 24 /* External interrupt 1 */
-#define VECNUM_EIR2 25 /* External interrupt 2 */
-#define VECNUM_EIR3 26 /* External interrupt 3 */
-#define VECNUM_EIR4 27 /* External interrupt 4 */
-#define VECNUM_EIR5 28 /* External interrupt 5 */
-#define VECNUM_EIR6 29 /* External interrupt 6 */
-#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */
-#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */
-
-/* UIC 1 */
-#define VECNUM_MS (32 + 0 ) /* MAL SERR */
-#define VECNUM_TXDE (32 + 1 ) /* MAL TXDE */
-#define VECNUM_RXDE (32 + 2 ) /* MAL RXDE */
-#define VECNUM_USBDEV (32 + 23) /* USB 1.1/USB 2.0 Device */
-#define VECNUM_ETH0 (32 + 28) /* Ethernet 0 interrupt status */
-#define VECNUM_EWU0 (32 + 29) /* Ethernet 0 wakeup */
-
-#else /* !defined(CONFIG_440) */
-
-#if defined(CONFIG_405EZ)
-#define VECNUM_D0 0 /* DMA channel 0 */
-#define VECNUM_D1 1 /* DMA channel 1 */
-#define VECNUM_D2 2 /* DMA channel 2 */
-#define VECNUM_D3 3 /* DMA channel 3 */
-#define VECNUM_1588 4 /* IEEE 1588 network synchronization */
-#define VECNUM_U0 5 /* UART0 */
-#define VECNUM_U1 6 /* UART1 */
-#define VECNUM_CAN0 7 /* CAN 0 */
-#define VECNUM_CAN1 8 /* CAN 1 */
-#define VECNUM_SPI 9 /* SPI */
-#define VECNUM_IIC0 10 /* I2C */
-#define VECNUM_CHT0 11 /* Chameleon timer high pri interrupt */
-#define VECNUM_CHT1 12 /* Chameleon timer high pri interrupt */
-#define VECNUM_USBH1 13 /* USB Host 1 */
-#define VECNUM_USBH2 14 /* USB Host 2 */
-#define VECNUM_USBDEV 15 /* USB Device */
-#define VECNUM_ETH0 16 /* 10/100 Ethernet interrupt status */
-#define VECNUM_EWU0 17 /* Ethernet wakeup sequence detected */
-
-#define VECNUM_MADMAL 18 /* Logical OR of following MadMAL int */
-#define VECNUM_MS 18 /* MAL_SERR_INT */
-#define VECNUM_TXDE 18 /* MAL_TXDE_INT */
-#define VECNUM_RXDE 18 /* MAL_RXDE_INT */
-
-#define VECNUM_MTE 19 /* MAL TXEOB */
-#define VECNUM_MTE1 20 /* MAL TXEOB1 */
-#define VECNUM_MRE 21 /* MAL RXEOB */
-#define VECNUM_NAND 22 /* NAND Flash controller */
-#define VECNUM_ADC 23 /* ADC */
-#define VECNUM_DAC 24 /* DAC */
-#define VECNUM_OPB2PLB 25 /* OPB to PLB bridge interrupt */
-#define VECNUM_RESERVED0 26 /* Reserved */
-#define VECNUM_EIR0 27 /* External interrupt 0 */
-#define VECNUM_EIR1 28 /* External interrupt 1 */
-#define VECNUM_EIR2 29 /* External interrupt 2 */
-#define VECNUM_EIR3 30 /* External interrupt 3 */
-#define VECNUM_EIR4 31 /* External interrupt 4 */
-
-#elif defined(CONFIG_405EX)
-
-/* UIC 0 */
-#define VECNUM_U0 00
-#define VECNUM_U1 01
-#define VECNUM_IIC0 02
-#define VECNUM_PKA 03
-#define VECNUM_TRNG 04
-#define VECNUM_EBM 05
-#define VECNUM_BGI 06
-#define VECNUM_IIC1 07
-#define VECNUM_SPI 08
-#define VECNUM_EIR0 09
-#define VECNUM_MTE 10 /* MAL Tx EOB */
-#define VECNUM_MRE 11 /* MAL Rx EOB */
-#define VECNUM_DMA0 12
-#define VECNUM_DMA1 13
-#define VECNUM_DMA2 14
-#define VECNUM_DMA3 15
-#define VECNUM_PCIE0AL 16
-#define VECNUM_PCIE0VPD 17
-#define VECNUM_RPCIE0HRST 18
-#define VECNUM_FPCIE0HRST 19
-#define VECNUM_PCIE0TCR 20
-#define VECNUM_PCIEMSI0 21
-#define VECNUM_PCIEMSI1 22
-#define VECNUM_SECURITY 23
-#define VECNUM_ETH0 24
-#define VECNUM_ETH1 25
-#define VECNUM_PCIEMSI2 26
-#define VECNUM_EIR4 27
-#define VECNUM_UIC2NC 28
-#define VECNUM_UIC2C 29
-#define VECNUM_UIC1NC 30
-#define VECNUM_UIC1C 31
-
-/* UIC 1 */
-#define VECNUM_MS (32 + 00) /* MAL SERR */
-#define VECNUM_TXDE (32 + 01) /* MAL TXDE */
-#define VECNUM_RXDE (32 + 02) /* MAL RXDE */
-#define VECNUM_PCIE0BMVC0 (32 + 03)
-#define VECNUM_PCIE0DCRERR (32 + 04)
-#define VECNUM_EBC (32 + 05)
-#define VECNUM_NDFC (32 + 06)
-#define VECNUM_PCEI1DCRERR (32 + 07)
-#define VECNUM_CT8 (32 + 08)
-#define VECNUM_CT9 (32 + 09)
-#define VECNUM_PCIE1AL (32 + 10)
-#define VECNUM_PCIE1VPD (32 + 11)
-#define VECNUM_RPCE1HRST (32 + 12)
-#define VECNUM_FPCE1HRST (32 + 13)
-#define VECNUM_PCIE1TCR (32 + 14)
-#define VECNUM_PCIE1VC0 (32 + 15)
-#define VECNUM_CT3 (32 + 16)
-#define VECNUM_CT4 (32 + 17)
-#define VECNUM_EIR7 (32 + 18)
-#define VECNUM_EIR8 (32 + 19)
-#define VECNUM_EIR9 (32 + 20)
-#define VECNUM_CT5 (32 + 21)
-#define VECNUM_CT6 (32 + 22)
-#define VECNUM_CT7 (32 + 23)
-#define VECNUM_SROM (32 + 24) /* SERIAL ROM */
-#define VECNUM_GPTDECPULS (32 + 25) /* GPT Decrement pulse */
-#define VECNUM_EIR2 (32 + 26)
-#define VECNUM_EIR5 (32 + 27)
-#define VECNUM_EIR6 (32 + 28)
-#define VECNUM_EMAC0WAKE (32 + 29)
-#define VECNUM_EIR1 (32 + 30)
-#define VECNUM_EMAC1WAKE (32 + 31)
-
-/* UIC 2 */
-#define VECNUM_PCIE0INTA (64 + 00) /* PCIE0 INTA */
-#define VECNUM_PCIE0INTB (64 + 01) /* PCIE0 INTB */
-#define VECNUM_PCIE0INTC (64 + 02) /* PCIE0 INTC */
-#define VECNUM_PCIE0INTD (64 + 03) /* PCIE0 INTD */
-#define VECNUM_EIR3 (64 + 04) /* External IRQ 3 */
-#define VECNUM_DDRMCUE (64 + 05)
-#define VECNUM_DDRMCCE (64 + 06)
-#define VECNUM_MALINTCOATX0 (64 + 07) /* Interrupt coalecence TX0 */
-#define VECNUM_MALINTCOATX1 (64 + 08) /* Interrupt coalecence TX1 */
-#define VECNUM_MALINTCOARX0 (64 + 09) /* Interrupt coalecence RX0 */
-#define VECNUM_MALINTCOARX1 (64 + 10) /* Interrupt coalecence RX1 */
-#define VECNUM_PCIE1INTA (64 + 11) /* PCIE0 INTA */
-#define VECNUM_PCIE1INTB (64 + 12) /* PCIE0 INTB */
-#define VECNUM_PCIE1INTC (64 + 13) /* PCIE0 INTC */
-#define VECNUM_PCIE1INTD (64 + 14) /* PCIE0 INTD */
-#define VECNUM_RPCIEMSI2 (64 + 15) /* MSI level 2 */
-#define VECNUM_PCIEMSI3 (64 + 16) /* MSI level 2 */
-#define VECNUM_PCIEMSI4 (64 + 17) /* MSI level 2 */
-#define VECNUM_PCIEMSI5 (64 + 18) /* MSI level 2 */
-#define VECNUM_PCIEMSI6 (64 + 19) /* MSI level 2 */
-#define VECNUM_PCIEMSI7 (64 + 20) /* MSI level 2 */
-#define VECNUM_PCIEMSI8 (64 + 21) /* MSI level 2 */
-#define VECNUM_PCIEMSI9 (64 + 22) /* MSI level 2 */
-#define VECNUM_PCIEMSI10 (64 + 23) /* MSI level 2 */
-#define VECNUM_PCIEMSI11 (64 + 24) /* MSI level 2 */
-#define VECNUM_PCIEMSI12 (64 + 25) /* MSI level 2 */
-#define VECNUM_PCIEMSI13 (64 + 26) /* MSI level 2 */
-#define VECNUM_PCIEMSI14 (64 + 27) /* MSI level 2 */
-#define VECNUM_PCIEMSI15 (64 + 28) /* MSI level 2 */
-#define VECNUM_PLB4XAHB (64 + 29) /* PLBxAHB bridge */
-#define VECNUM_USBWAKE (64 + 30) /* USB wakup */
-#define VECNUM_USBOTG (64 + 31) /* USB OTG */
-
-#else /* !CONFIG_405EZ */
-
-#define VECNUM_U0 0 /* UART0 */
-#define VECNUM_U1 1 /* UART1 */
-#define VECNUM_D0 5 /* DMA channel 0 */
-#define VECNUM_D1 6 /* DMA channel 1 */
-#define VECNUM_D2 7 /* DMA channel 2 */
-#define VECNUM_D3 8 /* DMA channel 3 */
-#define VECNUM_EWU0 9 /* Ethernet wakeup */
-#define VECNUM_MS 10 /* MAL SERR */
-#define VECNUM_MTE 11 /* MAL TXEOB */
-#define VECNUM_MRE 12 /* MAL RXEOB */
-#define VECNUM_TXDE 13 /* MAL TXDE */
-#define VECNUM_RXDE 14 /* MAL RXDE */
-#define VECNUM_ETH0 15 /* Ethernet interrupt status */
-#define VECNUM_EIR0 25 /* External interrupt 0 */
-#define VECNUM_EIR1 26 /* External interrupt 1 */
-#define VECNUM_EIR2 27 /* External interrupt 2 */
-#define VECNUM_EIR3 28 /* External interrupt 3 */
-#define VECNUM_EIR4 29 /* External interrupt 4 */
-#define VECNUM_EIR5 30 /* External interrupt 5 */
-#define VECNUM_EIR6 31 /* External interrupt 6 */
-#endif /* defined(CONFIG_405EZ) */
-
-#endif /* defined(CONFIG_440) */
-
-#endif /* _VECNUMS_H_ */
* Memory Bank 0-7 configuration
*/
#if defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
#define SDRAM_RXBAS_SDBA_MASK 0xFFE00000 /* Base address */
#define SDRAM_RXBAS_SDBA_ENCODE(n) ((u32)(((phys_size_t)(n) >> 2) & 0xFFE00000))
#define SDRAM_RXBAS_SDBA_DECODE(n) ((((phys_size_t)(n)) & 0xFFE00000) << 2)
/*
* Memory controller registers
*/
+#define SDRAM_BESR 0x00 /* PLB bus error status (read/clear) */
+#define SDRAM_BESRT 0x01 /* PLB bus error status (test/set) */
+#define SDRAM_BEARL 0x02 /* PLB bus error address low */
+#define SDRAM_BEARH 0x03 /* PLB bus error address high */
+#define SDRAM_WMIRQ 0x06 /* PLB write master interrupt (read/clear) */
+#define SDRAM_WMIRQT 0x07 /* PLB write master interrupt (test/set) */
+#define SDRAM_PLBOPT 0x08 /* PLB slave options */
+#define SDRAM_PUABA 0x09 /* PLB upper address base */
+#ifndef CONFIG_405EX
#define SDRAM_MCSTAT 0x14 /* memory controller status */
+#else
+#define SDRAM_MCSTAT 0x1F /* memory controller status */
+#endif
#define SDRAM_MCOPT1 0x20 /* memory controller options 1 */
#define SDRAM_MCOPT2 0x21 /* memory controller options 2 */
#define SDRAM_MODT0 0x22 /* on die termination for bank 0 */
#define SDRAM_MMODE 0x88 /* memory mode */
#define SDRAM_MEMODE 0x89 /* memory extended mode */
#define SDRAM_ECCCR 0x98 /* ECC error status */
+#define SDRAM_ECCES SDRAM_ECCCR
#define SDRAM_CID 0xA4 /* core ID */
+#ifndef CONFIG_405EX
#define SDRAM_RID 0xA8 /* revision ID */
+#endif
+#define SDRAM_FCSR 0xB0 /* feedback calibration status */
#define SDRAM_RTSR 0xB1 /* run time status tracking */
+#ifdef CONFIG_405EX
+#define SDRAM_RID 0xF8 /* revision ID */
+#endif
+
+/*
+ * Memory Controller Bus Error Status
+ */
+#define SDRAM_BESR_MASK PPC_REG_VAL(7, 0xFF)
+#define SDRAM_BESR_M0ID_MASK PPC_REG_VAL(3, 0xF)
+#define SDRAM_BESR_M0ID_ICU PPC_REG_VAL(3, 0x0)
+#define SDRAM_BESR_M0ID_PCIE0 PPC_REG_VAL(3, 0x1)
+#define SDRAM_BESR_M0ID_PCIE1 PPC_REG_VAL(3, 0x2)
+#define SDRAM_BESR_M0ID_DMA PPC_REG_VAL(3, 0x3)
+#define SDRAM_BESR_M0ID_DCU PPC_REG_VAL(3, 0x4)
+#define SDRAM_BESR_M0ID_OPB PPC_REG_VAL(3, 0x5)
+#define SDRAM_BESR_M0ID_MAL PPC_REG_VAL(3, 0x6)
+#define SDRAM_BESR_M0ID_SEC PPC_REG_VAL(3, 0x7)
+#define SDRAM_BESR_M0ET_MASK PPC_REG_VAL(6, 0x7)
+#define SDRAM_BESR_M0ET_NONE PPC_REG_VAL(6, 0x0)
+#define SDRAM_BESR_M0ET_ECC PPC_REG_VAL(6, 0x1)
+#define SDRAM_BESR_M0RW_WRITE PPC_REG_VAL(7, 0)
+#define SDRAM_BESR_M0RW_READ PPC_REG_VAL(8, 1)
/*
* Memory Controller Status
* SDRAM Delay Line Calibration Register
*/
#define SDRAM_DLCR_DCLM_MASK 0x80000000
-#define SDRAM_DLCR_DCLM_MANUEL 0x80000000
+#define SDRAM_DLCR_DCLM_MANUAL 0x80000000
#define SDRAM_DLCR_DCLM_AUTO 0x00000000
#define SDRAM_DLCR_DLCR_MASK 0x08000000
#define SDRAM_DLCR_DLCR_CALIBRATE 0x08000000
#define SDRAM_DLCR_DLCV_DECODE(n) ((((u32)(n))>>0)&0x1FF)
/*
+ * SDRAM Memory On Die Terimination Control Register
+ */
+#define SDRAM_MODT_ODTON_DISABLE PPC_REG_VAL(0, 0)
+#define SDRAM_MODT_ODTON_ENABLE PPC_REG_VAL(0, 1)
+#define SDRAM_MODT_EB1W_DISABLE PPC_REG_VAL(1, 0)
+#define SDRAM_MODT_EB1W_ENABLE PPC_REG_VAL(1, 1)
+#define SDRAM_MODT_EB1R_DISABLE PPC_REG_VAL(2, 0)
+#define SDRAM_MODT_EB1R_ENABLE PPC_REG_VAL(2, 1)
+#define SDRAM_MODT_EB0W_DISABLE PPC_REG_VAL(7, 0)
+#define SDRAM_MODT_EB0W_ENABLE PPC_REG_VAL(7, 1)
+#define SDRAM_MODT_EB0R_DISABLE PPC_REG_VAL(8, 0)
+#define SDRAM_MODT_EB0R_ENABLE PPC_REG_VAL(8, 1)
+
+/*
* SDRAM Controller On Die Termination Register
*/
-#define SDRAM_CODT_ODT_ON 0x80000000
-#define SDRAM_CODT_ODT_OFF 0x00000000
-#define SDRAM_CODT_DQS_VOLTAGE_DDR_MASK 0x00000020
-#define SDRAM_CODT_DQS_2_5_V_DDR1 0x00000000
-#define SDRAM_CODT_DQS_1_8_V_DDR2 0x00000020
-#define SDRAM_CODT_DQS_MASK 0x00000010
-#define SDRAM_CODT_DQS_DIFFERENTIAL 0x00000000
-#define SDRAM_CODT_DQS_SINGLE_END 0x00000010
-#define SDRAM_CODT_CKSE_DIFFERENTIAL 0x00000000
-#define SDRAM_CODT_CKSE_SINGLE_END 0x00000008
-#define SDRAM_CODT_FEEBBACK_RCV_SINGLE_END 0x00000004
-#define SDRAM_CODT_FEEBBACK_DRV_SINGLE_END 0x00000002
-#define SDRAM_CODT_IO_HIZ 0x00000000
-#define SDRAM_CODT_IO_NMODE 0x00000001
+#define SDRAM_CODT_ODT_ON PPC_REG_VAL(0, 1)
+#define SDRAM_CODT_ODT_OFF PPC_REG_VAL(0, 0)
+#define SDRAM_CODT_RK1W_ON PPC_REG_VAL(1, 1)
+#define SDRAM_CODT_RK1W_OFF PPC_REG_VAL(1, 0)
+#define SDRAM_CODT_RK1R_ON PPC_REG_VAL(2, 1)
+#define SDRAM_CODT_RK1R_OFF PPC_REG_VAL(2, 0)
+#define SDRAM_CODT_RK0W_ON PPC_REG_VAL(7, 1)
+#define SDRAM_CODT_RK0W_OFF PPC_REG_VAL(7, 0)
+#define SDRAM_CODT_RK0R_ON PPC_REG_VAL(8, 1)
+#define SDRAM_CODT_RK0R_OFF PPC_REG_VAL(8, 0)
+#define SDRAM_CODT_ODTSH_NORMAL PPC_REG_VAL(10, 0)
+#define SDRAM_CODT_ODTSH_REMOVE_ONE_AT_END PPC_REG_VAL(10, 1)
+#define SDRAM_CODT_ODTSH_ADD_ONE_AT_START PPC_REG_VAL(10, 2)
+#define SDRAM_CODT_ODTSH_SHIFT_ONE_EARLIER PPC_REG_VAL(10, 3)
+#define SDRAM_CODT_CODTZ_75OHM PPC_REG_VAL(11, 0)
+#define SDRAM_CODT_CKEG_ON PPC_REG_VAL(12, 1)
+#define SDRAM_CODT_CKEG_OFF PPC_REG_VAL(12, 0)
+#define SDRAM_CODT_CTLG_ON PPC_REG_VAL(13, 1)
+#define SDRAM_CODT_CTLG_OFF PPC_REG_VAL(13, 0)
+#define SDRAM_CODT_FBDG_ON PPC_REG_VAL(14, 1)
+#define SDRAM_CODT_FBDG_OFF PPC_REG_VAL(14, 0)
+#define SDRAM_CODT_FBRG_ON PPC_REG_VAL(15, 1)
+#define SDRAM_CODT_FBRG_OFF PPC_REG_VAL(15, 0)
+#define SDRAM_CODT_CKLZ_36OHM PPC_REG_VAL(18, 1)
+#define SDRAM_CODT_CKLZ_18OHM PPC_REG_VAL(18, 0)
+#define SDRAM_CODT_DQS_VOLTAGE_DDR_MASK PPC_REG_VAL(26, 1)
+#define SDRAM_CODT_DQS_2_5_V_DDR1 PPC_REG_VAL(26, 0)
+#define SDRAM_CODT_DQS_1_8_V_DDR2 PPC_REG_VAL(26, 1)
+#define SDRAM_CODT_DQS_MASK PPC_REG_VAL(27, 1)
+#define SDRAM_CODT_DQS_DIFFERENTIAL PPC_REG_VAL(27, 0)
+#define SDRAM_CODT_DQS_SINGLE_END PPC_REG_VAL(27, 1)
+#define SDRAM_CODT_CKSE_DIFFERENTIAL PPC_REG_VAL(28, 0)
+#define SDRAM_CODT_CKSE_SINGLE_END PPC_REG_VAL(28, 1)
+#define SDRAM_CODT_FEEBBACK_RCV_SINGLE_END PPC_REG_VAL(29, 1)
+#define SDRAM_CODT_FEEBBACK_DRV_SINGLE_END PPC_REG_VAL(30, 1)
+#define SDRAM_CODT_IO_HIZ PPC_REG_VAL(31, 0)
+#define SDRAM_CODT_IO_NMODE PPC_REG_VAL(31, 1)
/*
- * SDRAM Mode Register
+ * SDRAM Initialization Preload Register
*/
-#define SDRAM_MMODE_WR_MASK 0x00000E00
-#define SDRAM_MMODE_WR_DDR1 0x00000000
-#define SDRAM_MMODE_WR_DDR2_3_CYC 0x00000400
-#define SDRAM_MMODE_WR_DDR2_4_CYC 0x00000600
-#define SDRAM_MMODE_WR_DDR2_5_CYC 0x00000800
-#define SDRAM_MMODE_WR_DDR2_6_CYC 0x00000A00
-#define SDRAM_MMODE_DCL_MASK 0x00000070
-#define SDRAM_MMODE_DCL_DDR1_2_0_CLK 0x00000020
-#define SDRAM_MMODE_DCL_DDR1_2_5_CLK 0x00000060
-#define SDRAM_MMODE_DCL_DDR1_3_0_CLK 0x00000030
-#define SDRAM_MMODE_DCL_DDR2_2_0_CLK 0x00000020
-#define SDRAM_MMODE_DCL_DDR2_3_0_CLK 0x00000030
-#define SDRAM_MMODE_DCL_DDR2_4_0_CLK 0x00000040
-#define SDRAM_MMODE_DCL_DDR2_5_0_CLK 0x00000050
-#define SDRAM_MMODE_DCL_DDR2_6_0_CLK 0x00000060
-#define SDRAM_MMODE_DCL_DDR2_7_0_CLK 0x00000070
+#define SDRAM_INITPLR_ENABLE PPC_REG_VAL(0, 1)
+#define SDRAM_INITPLR_DISABLE PPC_REG_VAL(0, 0)
+#define SDRAM_INITPLR_IMWT_MASK PPC_REG_VAL(8, 0xFF)
+#define SDRAM_INITPLR_IMWT_ENCODE(n) PPC_REG_VAL(8, \
+ (static_cast(u32, \
+ n)) \
+ & 0xFF)
+#define SDRAM_INITPLR_ICMD_MASK PPC_REG_VAL(12, 0x7)
+#define SDRAM_INITPLR_ICMD_ENCODE(n) PPC_REG_VAL(12, \
+ (static_cast(u32, \
+ n)) \
+ & 0x7)
+#define SDRAM_INITPLR_IBA_MASK PPC_REG_VAL(15, 0x7)
+#define SDRAM_INITPLR_IBA_ENCODE(n) PPC_REG_VAL(15, \
+ (static_cast(u32, \
+ n)) \
+ & 0x7)
+#define SDRAM_INITPLR_IMA_MASK PPC_REG_VAL(31, 0x7FFF)
+#define SDRAM_INITPLR_IMA_ENCODE(n) PPC_REG_VAL(31, \
+ (static_cast(u32, \
+ n)) \
+ & 0x7FFF)
/*
- * SDRAM Extended Mode Register
+ * JEDEC DDR Initialization Commands
*/
-#define SDRAM_MEMODE_DIC_MASK 0x00000002
-#define SDRAM_MEMODE_DIC_NORMAL 0x00000000
-#define SDRAM_MEMODE_DIC_WEAK 0x00000002
-#define SDRAM_MEMODE_DLL_MASK 0x00000001
-#define SDRAM_MEMODE_DLL_DISABLE 0x00000001
-#define SDRAM_MEMODE_DLL_ENABLE 0x00000000
-#define SDRAM_MEMODE_RTT_MASK 0x00000044
-#define SDRAM_MEMODE_RTT_DISABLED 0x00000000
-#define SDRAM_MEMODE_RTT_75OHM 0x00000004
-#define SDRAM_MEMODE_RTT_150OHM 0x00000040
-#define SDRAM_MEMODE_DQS_MASK 0x00000400
-#define SDRAM_MEMODE_DQS_DISABLE 0x00000400
-#define SDRAM_MEMODE_DQS_ENABLE 0x00000000
+#define JEDEC_CMD_NOP 7
+#define JEDEC_CMD_PRECHARGE 2
+#define JEDEC_CMD_REFRESH 1
+#define JEDEC_CMD_EMR 0
+#define JEDEC_CMD_READ 5
+#define JEDEC_CMD_WRITE 4
+
+/*
+ * JEDEC Precharge Command Memory Address Arguments
+ */
+#define JEDEC_MA_PRECHARGE_ONE (0 << 10)
+#define JEDEC_MA_PRECHARGE_ALL (1 << 10)
+
+/*
+ * JEDEC DDR EMR Command Bank Address Arguments
+ */
+#define JEDEC_BA_MR 0
+#define JEDEC_BA_EMR 1
+#define JEDEC_BA_EMR2 2
+#define JEDEC_BA_EMR3 3
+
+/*
+ * JEDEC DDR Mode Register
+ */
+#define JEDEC_MA_MR_PDMODE_FAST_EXIT (0 << 12)
+#define JEDEC_MA_MR_PDMODE_SLOW_EXIT (1 << 12)
+#define JEDEC_MA_MR_WR_MASK (0x7 << 9)
+#define JEDEC_MA_MR_WR_DDR1 (0x0 << 9)
+#define JEDEC_MA_MR_WR_DDR2_2_CYC (0x1 << 9)
+#define JEDEC_MA_MR_WR_DDR2_3_CYC (0x2 << 9)
+#define JEDEC_MA_MR_WR_DDR2_4_CYC (0x3 << 9)
+#define JEDEC_MA_MR_WR_DDR2_5_CYC (0x4 << 9)
+#define JEDEC_MA_MR_WR_DDR2_6_CYC (0x5 << 9)
+#define JEDEC_MA_MR_DLL_RESET (1 << 8)
+#define JEDEC_MA_MR_MODE_NORMAL (0 << 8)
+#define JEDEC_MA_MR_MODE_TEST (1 << 8)
+#define JEDEC_MA_MR_CL_MASK (0x7 << 4)
+#define JEDEC_MA_MR_CL_DDR1_2_0_CLK (0x2 << 4)
+#define JEDEC_MA_MR_CL_DDR1_2_5_CLK (0x6 << 4)
+#define JEDEC_MA_MR_CL_DDR1_3_0_CLK (0x3 << 4)
+#define JEDEC_MA_MR_CL_DDR2_2_0_CLK (0x2 << 4)
+#define JEDEC_MA_MR_CL_DDR2_3_0_CLK (0x3 << 4)
+#define JEDEC_MA_MR_CL_DDR2_4_0_CLK (0x4 << 4)
+#define JEDEC_MA_MR_CL_DDR2_5_0_CLK (0x5 << 4)
+#define JEDEC_MA_MR_CL_DDR2_6_0_CLK (0x6 << 4)
+#define JEDEC_MA_MR_CL_DDR2_7_0_CLK (0x7 << 4)
+#define JEDEC_MA_MR_BTYP_SEQUENTIAL (0 << 3)
+#define JEDEC_MA_MR_BTYP_INTERLEAVED (1 << 3)
+#define JEDEC_MA_MR_BLEN_MASK (0x7 << 0)
+#define JEDEC_MA_MR_BLEN_4 (2 << 0)
+#define JEDEC_MA_MR_BLEN_8 (3 << 0)
+
+/*
+ * JEDEC DDR Extended Mode Register
+ */
+#define JEDEC_MA_EMR_OUTPUT_MASK (1 << 12)
+#define JEDEC_MA_EMR_OUTPUT_ENABLE (0 << 12)
+#define JEDEC_MA_EMR_OUTPUT_DISABLE (1 << 12)
+#define JEDEC_MA_EMR_RQDS_MASK (1 << 11)
+#define JEDEC_MA_EMR_RDQS_DISABLE (0 << 11)
+#define JEDEC_MA_EMR_RDQS_ENABLE (1 << 11)
+#define JEDEC_MA_EMR_DQS_MASK (1 << 10)
+#define JEDEC_MA_EMR_DQS_DISABLE (1 << 10)
+#define JEDEC_MA_EMR_DQS_ENABLE (0 << 10)
+#define JEDEC_MA_EMR_OCD_MASK (0x7 << 7)
+#define JEDEC_MA_EMR_OCD_EXIT (0 << 7)
+#define JEDEC_MA_EMR_OCD_ENTER (7 << 7)
+#define JEDEC_MA_EMR_AL_DDR1_0_CYC (0 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_1_CYC (1 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_2_CYC (2 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_3_CYC (3 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_4_CYC (4 << 3)
+#define JEDEC_MA_EMR_RTT_MASK (0x11 << 2)
+#define JEDEC_MA_EMR_RTT_DISABLED (0x00 << 2)
+#define JEDEC_MA_EMR_RTT_75OHM (0x01 << 2)
+#define JEDEC_MA_EMR_RTT_150OHM (0x10 << 2)
+#define JEDEC_MA_EMR_RTT_50OHM (0x11 << 2)
+#define JEDEC_MA_EMR_ODS_MASK (1 << 1)
+#define JEDEC_MA_EMR_ODS_NORMAL (0 << 1)
+#define JEDEC_MA_EMR_ODS_WEAK (1 << 1)
+#define JEDEC_MA_EMR_DLL_MASK (1 << 0)
+#define JEDEC_MA_EMR_DLL_ENABLE (0 << 0)
+#define JEDEC_MA_EMR_DLL_DISABLE (1 << 0)
+
+/*
+ * JEDEC DDR Extended Mode Register 2
+ */
+#define JEDEC_MA_EMR2_TEMP_COMMERCIAL (0 << 7)
+#define JEDEC_MA_EMR2_TEMP_INDUSTRIAL (1 << 7)
+
+/*
+ * SDRAM Mode Register (Corresponds 1:1 w/ JEDEC Mode Register)
+ */
+#define SDRAM_MMODE_WR_MASK JEDEC_MA_MR_WR_MASK
+#define SDRAM_MMODE_WR_DDR1 JEDEC_MA_MR_WR_DDR1
+#define SDRAM_MMODE_WR_DDR2_2_CYC JEDEC_MA_MR_WR_DDR2_2_CYC
+#define SDRAM_MMODE_WR_DDR2_3_CYC JEDEC_MA_MR_WR_DDR2_3_CYC
+#define SDRAM_MMODE_WR_DDR2_4_CYC JEDEC_MA_MR_WR_DDR2_4_CYC
+#define SDRAM_MMODE_WR_DDR2_5_CYC JEDEC_MA_MR_WR_DDR2_5_CYC
+#define SDRAM_MMODE_WR_DDR2_6_CYC JEDEC_MA_MR_WR_DDR2_6_CYC
+#define SDRAM_MMODE_DCL_MASK JEDEC_MA_MR_CL_MASK
+#define SDRAM_MMODE_DCL_DDR1_2_0_CLK JEDEC_MA_MR_CL_DDR1_2_0_CLK
+#define SDRAM_MMODE_DCL_DDR1_2_5_CLK JEDEC_MA_MR_CL_DDR1_2_5_CLK
+#define SDRAM_MMODE_DCL_DDR1_3_0_CLK JEDEC_MA_MR_CL_DDR1_3_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_2_0_CLK JEDEC_MA_MR_CL_DDR2_2_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_3_0_CLK JEDEC_MA_MR_CL_DDR2_3_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_4_0_CLK JEDEC_MA_MR_CL_DDR2_4_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_5_0_CLK JEDEC_MA_MR_CL_DDR2_5_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_6_0_CLK JEDEC_MA_MR_CL_DDR2_6_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_7_0_CLK JEDEC_MA_MR_CL_DDR2_7_0_CLK
+#define SDRAM_MMODE_BTYP_SEQUENTIAL JEDEC_MA_MR_BTYP_SEQUENTIAL
+#define SDRAM_MMODE_BTYP_INTERLEAVED JEDEC_MA_MR_BTYP_INTERLEAVED
+#define SDRAM_MMODE_BLEN_MASK JEDEC_MA_MR_BLEN_MASK
+#define SDRAM_MMODE_BLEN_4 JEDEC_MA_MR_BLEN_4
+#define SDRAM_MMODE_BLEN_8 JEDEC_MA_MR_BLEN_8
+
+/*
+ * SDRAM Extended Mode Register (Corresponds 1:1 w/ JEDEC Extended
+ * Mode Register)
+ */
+#define SDRAM_MEMODE_QOFF_MASK JEDEC_MA_EMR_OUTPUT_MASK
+#define SDRAM_MEMODE_QOFF_DISABLE JEDEC_MA_EMR_OUTPUT_DISABLE
+#define SDRAM_MEMODE_QOFF_ENABLE JEDEC_MA_EMR_OUTPUT_ENABLE
+#define SDRAM_MEMODE_RDQS_MASK JEDEC_MA_EMR_RQDS_MASK
+#define SDRAM_MEMODE_RDQS_DISABLE JEDEC_MA_EMR_RDQS_DISABLE
+#define SDRAM_MEMODE_RDQS_ENABLE JEDEC_MA_EMR_RDQS_ENABLE
+#define SDRAM_MEMODE_DQS_MASK JEDEC_MA_EMR_DQS_MASK
+#define SDRAM_MEMODE_DQS_DISABLE JEDEC_MA_EMR_DQS_DISABLE
+#define SDRAM_MEMODE_DQS_ENABLE JEDEC_MA_EMR_DQS_ENABLE
+#define SDRAM_MEMODE_AL_DDR1_0_CYC JEDEC_MA_EMR_AL_DDR1_0_CYC
+#define SDRAM_MEMODE_AL_DDR2_1_CYC JEDEC_MA_EMR_AL_DDR2_1_CYC
+#define SDRAM_MEMODE_AL_DDR2_2_CYC JEDEC_MA_EMR_AL_DDR2_2_CYC
+#define SDRAM_MEMODE_AL_DDR2_3_CYC JEDEC_MA_EMR_AL_DDR2_3_CYC
+#define SDRAM_MEMODE_AL_DDR2_4_CYC JEDEC_MA_EMR_AL_DDR2_4_CYC
+#define SDRAM_MEMODE_RTT_MASK JEDEC_MA_EMR_RTT_MASK
+#define SDRAM_MEMODE_RTT_DISABLED JEDEC_MA_EMR_RTT_DISABLED
+#define SDRAM_MEMODE_RTT_75OHM JEDEC_MA_EMR_RTT_75OHM
+#define SDRAM_MEMODE_RTT_150OHM JEDEC_MA_EMR_RTT_150OHM
+#define SDRAM_MEMODE_RTT_50OHM JEDEC_MA_EMR_RTT_50OHM
+#define SDRAM_MEMODE_DIC_MASK JEDEC_MA_EMR_ODS_MASK
+#define SDRAM_MEMODE_DIC_NORMAL JEDEC_MA_EMR_ODS_NORMAL
+#define SDRAM_MEMODE_DIC_WEAK JEDEC_MA_EMR_ODS_WEAK
+#define SDRAM_MEMODE_DLL_MASK JEDEC_MA_EMR_DLL_MASK
+#define SDRAM_MEMODE_DLL_DISABLE JEDEC_MA_EMR_DLL_DISABLE
+#define SDRAM_MEMODE_DLL_ENABLE JEDEC_MA_EMR_DLL_ENABLE
/*
* SDRAM Clock Timing Register
#define SDRAM_SDTR3_RFC_ENCODE(n) ((((u32)(n))&0x3F)<<0)
/*
+ * ECC Error Status
+ */
+#define SDRAM_ECCES_MASK PPC_REG_VAL(21, 0x3FFFFF)
+#define SDRAM_ECCES_BNCE_MASK PPC_REG_VAL(15, 0xFFFF)
+#define SDRAM_ECCES_BNCE_ENCODE(lane) PPC_REG_VAL(((lane) & 0xF), 1)
+#define SDRAM_ECCES_CKBER_MASK PPC_REG_VAL(17, 0x3)
+#define SDRAM_ECCES_CKBER_NONE PPC_REG_VAL(17, 0)
+#define SDRAM_ECCES_CKBER_16_ECC_0_3 PPC_REG_VAL(17, 2)
+#define SDRAM_ECCES_CKBER_32_ECC_0_3 PPC_REG_VAL(17, 1)
+#define SDRAM_ECCES_CKBER_32_ECC_4_8 PPC_REG_VAL(17, 2)
+#define SDRAM_ECCES_CKBER_32_ECC_0_8 PPC_REG_VAL(17, 3)
+#define SDRAM_ECCES_CE PPC_REG_VAL(18, 1)
+#define SDRAM_ECCES_UE PPC_REG_VAL(19, 1)
+#define SDRAM_ECCES_BKNER_MASK PPC_REG_VAL(21, 0x3)
+#define SDRAM_ECCES_BK0ER PPC_REG_VAL(20, 1)
+#define SDRAM_ECCES_BK1ER PPC_REG_VAL(21, 1)
+
+/*
* Memory Bank 0-1 configuration
*/
#define SDRAM_BXCF_M_AM_MASK 0x00000F00 /* Addressing mode */
--- /dev/null
+/*
+ * Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com>
+ *
+ * (C) Copyright 2008
+ * Stefan Roese, DENX Software Engineering, sr@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
+ */
+
+#ifndef _PPC4xx_UIC_H_
+#define _PPC4xx_UIC_H_
+
+/*
+ * Define the number of UIC's
+ */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
+#define UIC_MAX 4
+#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
+#define UIC_MAX 3
+#elif defined(CONFIG_440GP) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#define UIC_MAX 2
+#else
+#define UIC_MAX 1
+#endif
+
+#define IRQ_MAX UIC_MAX * 32
+
+/*
+ * UIC register
+ */
+#define UIC_SR 0x0 /* UIC status */
+#define UIC_ER 0x2 /* UIC enable */
+#define UIC_CR 0x3 /* UIC critical */
+#define UIC_PR 0x4 /* UIC polarity */
+#define UIC_TR 0x5 /* UIC triggering */
+#define UIC_MSR 0x6 /* UIC masked status */
+#define UIC_VR 0x7 /* UIC vector */
+#define UIC_VCR 0x8 /* UIC vector configuration */
+
+/*
+ * On 440GX we use the UICB0 as UIC0. Its the root UIC where all other UIC's
+ * are cascaded on. With this trick we can use the common UIC code for 440GX
+ * too.
+ */
+#if defined(CONFIG_440GX)
+#define UIC0_DCR_BASE 0x200
+#define UIC1_DCR_BASE 0xc0
+#define UIC2_DCR_BASE 0xd0
+#define UIC3_DCR_BASE 0x210
+#else
+#define UIC0_DCR_BASE 0xc0
+#define UIC1_DCR_BASE 0xd0
+#define UIC2_DCR_BASE 0xe0
+#define UIC3_DCR_BASE 0xf0
+#endif
+
+#define uic0sr (UIC0_DCR_BASE+0x0) /* UIC0 status */
+#define uic0er (UIC0_DCR_BASE+0x2) /* UIC0 enable */
+#define uic0cr (UIC0_DCR_BASE+0x3) /* UIC0 critical */
+#define uic0pr (UIC0_DCR_BASE+0x4) /* UIC0 polarity */
+#define uic0tr (UIC0_DCR_BASE+0x5) /* UIC0 triggering */
+#define uic0msr (UIC0_DCR_BASE+0x6) /* UIC0 masked status */
+#define uic0vr (UIC0_DCR_BASE+0x7) /* UIC0 vector */
+#define uic0vcr (UIC0_DCR_BASE+0x8) /* UIC0 vector configuration */
+
+#define uic1sr (UIC1_DCR_BASE+0x0) /* UIC1 status */
+#define uic1er (UIC1_DCR_BASE+0x2) /* UIC1 enable */
+#define uic1cr (UIC1_DCR_BASE+0x3) /* UIC1 critical */
+#define uic1pr (UIC1_DCR_BASE+0x4) /* UIC1 polarity */
+#define uic1tr (UIC1_DCR_BASE+0x5) /* UIC1 triggering */
+#define uic1msr (UIC1_DCR_BASE+0x6) /* UIC1 masked status */
+#define uic1vr (UIC1_DCR_BASE+0x7) /* UIC1 vector */
+#define uic1vcr (UIC1_DCR_BASE+0x8) /* UIC1 vector configuration */
+
+#define uic2sr (UIC2_DCR_BASE+0x0) /* UIC2 status-Read Clear */
+#define uic2srs (UIC2_DCR_BASE+0x1) /* UIC2 status-Read Set */
+#define uic2er (UIC2_DCR_BASE+0x2) /* UIC2 enable */
+#define uic2cr (UIC2_DCR_BASE+0x3) /* UIC2 critical */
+#define uic2pr (UIC2_DCR_BASE+0x4) /* UIC2 polarity */
+#define uic2tr (UIC2_DCR_BASE+0x5) /* UIC2 triggering */
+#define uic2msr (UIC2_DCR_BASE+0x6) /* UIC2 masked status */
+#define uic2vr (UIC2_DCR_BASE+0x7) /* UIC2 vector */
+#define uic2vcr (UIC2_DCR_BASE+0x8) /* UIC2 vector configuration */
+
+#define uic3sr (UIC3_DCR_BASE+0x0) /* UIC3 status-Read Clear */
+#define uic3srs (UIC3_DCR_BASE+0x1) /* UIC3 status-Read Set */
+#define uic3er (UIC3_DCR_BASE+0x2) /* UIC3 enable */
+#define uic3cr (UIC3_DCR_BASE+0x3) /* UIC3 critical */
+#define uic3pr (UIC3_DCR_BASE+0x4) /* UIC3 polarity */
+#define uic3tr (UIC3_DCR_BASE+0x5) /* UIC3 triggering */
+#define uic3msr (UIC3_DCR_BASE+0x6) /* UIC3 masked status */
+#define uic3vr (UIC3_DCR_BASE+0x7) /* UIC3 vector */
+#define uic3vcr (UIC3_DCR_BASE+0x8) /* UIC3 vector configuration */
+
+/* The following is for compatibility with 405 code */
+#define uicsr uic0sr
+#define uicer uic0er
+#define uiccr uic0cr
+#define uicpr uic0pr
+#define uictr uic0tr
+#define uicmsr uic0msr
+#define uicvr uic0vr
+#define uicvcr uic0vcr
+
+/*
+ * Now the interrupt vector definitions. They are different for most of
+ * the 4xx variants, so we need some more #ifdef's here. No mask
+ * definitions anymore here. For this please use the UIC_MASK macro below.
+ *
+ * Note: Please only define the interrupts really used in U-Boot here.
+ * Those are the cascading and EMAC/MAL related interrupt.
+ */
+
+#if defined(CONFIG_405EP) || defined(CONFIG_405GP)
+#define VECNUM_MAL_SERR 10
+#define VECNUM_MAL_TXEOB 11
+#define VECNUM_MAL_RXEOB 12
+#define VECNUM_MAL_TXDE 13
+#define VECNUM_MAL_RXDE 14
+#define VECNUM_ETH0 15
+#define VECNUM_ETH1_OFFS 2
+#define VECNUM_EIRQ6 29
+#endif /* defined(CONFIG_405EP) */
+
+#if defined(CONFIG_405EZ)
+#define VECNUM_USBDEV 15
+#define VECNUM_ETH0 16
+#define VECNUM_MAL_SERR 18
+#define VECNUM_MAL_TXDE 18
+#define VECNUM_MAL_RXDE 18
+#define VECNUM_MAL_TXEOB 19
+#define VECNUM_MAL_RXEOB 21
+#endif /* CONFIG_405EX */
+
+#if defined(CONFIG_405EX)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB 10
+#define VECNUM_MAL_RXEOB 11
+#define VECNUM_ETH0 24
+#define VECNUM_ETH1_OFFS 1
+#define VECNUM_UIC2NCI 28
+#define VECNUM_UIC2CI 29
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 0)
+#define VECNUM_MAL_TXDE (32 + 1)
+#define VECNUM_MAL_RXDE (32 + 2)
+#endif /* CONFIG_405EX */
+
+#if defined(CONFIG_440GP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB 10
+#define VECNUM_MAL_RXEOB 11
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 0)
+#define VECNUM_MAL_TXDE (32 + 1)
+#define VECNUM_MAL_RXDE (32 + 2)
+#define VECNUM_USBDEV (32 + 23)
+#define VECNUM_ETH0 (32 + 28)
+#define VECNUM_ETH1_OFFS 2
+#endif /* CONFIG_440GP */
+
+#if defined(CONFIG_440GX)
+/* UICB 0 (440GX only) */
+/*
+ * All those defines below are off-by-one, so that the common UIC code
+ * can be used. So VECNUM_UIC1CI refers to VECNUM_UIC0CI etc.
+ */
+#define VECNUM_UIC1CI 0
+#define VECNUM_UIC1NCI 1
+#define VECNUM_UIC2CI 2
+#define VECNUM_UIC2NCI 3
+#define VECNUM_UIC3CI 4
+#define VECNUM_UIC3NCI 5
+
+/* UIC 0, used as UIC1 on 440GX because of UICB0 */
+#define VECNUM_MAL_TXEOB (32 + 10)
+#define VECNUM_MAL_RXEOB (32 + 11)
+
+/* UIC 1, used as UIC2 on 440GX because of UICB0 */
+#define VECNUM_MAL_SERR (64 + 0)
+#define VECNUM_MAL_TXDE (64 + 1)
+#define VECNUM_MAL_RXDE (64 + 2)
+#define VECNUM_ETH0 (64 + 28)
+#define VECNUM_ETH1_OFFS 2
+#endif /* CONFIG_440GX */
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB 10
+#define VECNUM_MAL_RXEOB 11
+#define VECNUM_USBDEV 20
+#define VECNUM_ETH0 24
+#define VECNUM_ETH1_OFFS 1
+#define VECNUM_UIC2NCI 28
+#define VECNUM_UIC2CI 29
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 0)
+#define VECNUM_MAL_TXDE (32 + 1)
+#define VECNUM_MAL_RXDE (32 + 2)
+
+/* UIC 2 */
+#define VECNUM_EIRQ2 (64 + 3)
+#endif /* CONFIG_440EPX */
+
+#if defined(CONFIG_440SP)
+/* UIC 0 */
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 1)
+#define VECNUM_MAL_TXDE (32 + 2)
+#define VECNUM_MAL_RXDE (32 + 3)
+#define VECNUM_MAL_TXEOB (32 + 6)
+#define VECNUM_MAL_RXEOB (32 + 7)
+#define VECNUM_ETH0 (32 + 28)
+#endif /* CONFIG_440SP */
+
+#if defined(CONFIG_440SPE)
+/* UIC 0 */
+#define VECNUM_UIC2NCI 10
+#define VECNUM_UIC2CI 11
+#define VECNUM_UIC3NCI 16
+#define VECNUM_UIC3CI 17
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 1)
+#define VECNUM_MAL_TXDE (32 + 2)
+#define VECNUM_MAL_RXDE (32 + 3)
+#define VECNUM_MAL_TXEOB (32 + 6)
+#define VECNUM_MAL_RXEOB (32 + 7)
+#define VECNUM_ETH0 (32 + 28)
+#endif /* CONFIG_440SPE */
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+/* UIC 0 */
+#define VECNUM_UIC2NCI 10
+#define VECNUM_UIC2CI 11
+#define VECNUM_UIC3NCI 16
+#define VECNUM_UIC3CI 17
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 2 */
+#define VECNUM_MAL_SERR (64 + 3)
+#define VECNUM_MAL_TXDE (64 + 4)
+#define VECNUM_MAL_RXDE (64 + 5)
+#define VECNUM_MAL_TXEOB (64 + 6)
+#define VECNUM_MAL_RXEOB (64 + 7)
+#define VECNUM_ETH0 (64 + 16)
+#define VECNUM_ETH1_OFFS 1
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_460SX)
+/* UIC 0 */
+#define VECNUM_UIC2NCI 10
+#define VECNUM_UIC2CI 11
+#define VECNUM_UIC3NCI 16
+#define VECNUM_UIC3CI 17
+#define VECNUM_ETH0 19
+#define VECNUM_ETH1_OFFS 1
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 1)
+#define VECNUM_MAL_TXDE (32 + 2)
+#define VECNUM_MAL_RXDE (32 + 3)
+#define VECNUM_MAL_TXEOB (32 + 6)
+#define VECNUM_MAL_RXEOB (32 + 7)
+#endif /* CONFIG_460EX */
+
+#if !defined(VECNUM_ETH1_OFFS)
+#define VECNUM_ETH1_OFFS 1
+#endif
+
+/*
+ * Mask definitions (used for example in 4xx_enet.c)
+ */
+#define UIC_MASK(vec) (0x80000000 >> ((vec) & 0x1f))
+/* UIC_NR won't work for 440GX because of its specific UIC DCR addresses */
+#define UIC_NR(vec) ((vec) >> 5)
+
+#endif /* _PPC4xx_UIC_H_ */
#define PVR_460EX_RA 0x130218A3 /* 460EX rev A without Security Engine */
#define PVR_460GT_SE_RA 0x130218A0 /* 460GT rev A with Security Engine */
#define PVR_460GT_RA 0x130218A1 /* 460GT rev A without Security Engine */
+#define PVR_460SX_RA 0x13541800 /* 460SX rev A */
+#define PVR_460SX_RA_V1 0x13541801 /* 460SX rev A Variant 1 Security disabled */
+#define PVR_460GX_RA 0x13541802 /* 460GX rev A */
+#define PVR_460GX_RA_V1 0x13541803 /* 460GX rev A Variant 1 Security disabled */
#define PVR_601 0x00010000
#define PVR_602 0x00050000
#define PVR_603 0x00030000
#define PVR_86xx 0x80040000
#define PVR_86xx_REV1 (PVR_86xx | 0x0010)
+#define PVR_VIRTEX5 0x7ff21912
+
/*
* For the 8xx processors, all of them report the same PVR family for
* the PowerPC core. The various versions of these processors must be
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef XILINX_IRQ_H
+#define XILINX_IRQ_H
+
+#define intc XPAR_INTC_0_BASEADDR
+#define ISR (intc + (0 * 4)) /* Interrupt Status Register */
+#define IPR (intc + (1 * 4)) /* Interrupt Pending Register */
+#define IER (intc + (2 * 4)) /* Interrupt Enable Register */
+#define IAR (intc + (3 * 4)) /* Interrupt Acknowledge Register */
+#define SIE (intc + (4 * 4)) /* Set Interrupt Enable bits */
+#define CIE (intc + (5 * 4)) /* Clear Interrupt Enable bits */
+#define IVR (intc + (6 * 4)) /* Interrupt Vector Register */
+#define MER (intc + (7 * 4)) /* Master Enable Register */
+
+#define IRQ_MASK(irq) (1 << (irq & 0x1f))
+
+#define IRQ_MAX XPAR_INTC_MAX_NUM_INTR_INPUTS
+
+#endif
#define debugX(level,fmt,args...)
#endif /* DEBUG */
+#ifndef BUG
#define BUG() do { \
printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
panic("BUG!"); \
} while (0)
#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#endif /* BUG */
typedef void (interrupt_handler_t)(void *);
#define CONFIG_CMD_ITEST /* Integer (and string) test */
#define CONFIG_CMD_JFFS2 /* JFFS2 Support */
#define CONFIG_CMD_KGDB /* kgdb */
+#define CONFIG_CMD_LICENSE /* console license display */
#define CONFIG_CMD_LOADB /* loadb */
#define CONFIG_CMD_LOADS /* loads */
#define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop mtest */
#define CONFIG_CMD_SPI /* SPI utility */
#define CONFIG_CMD_TERMINAL /* built-in Serial Terminal */
#define CONFIG_CMD_UNIVERSE /* Tundra Universe Support */
+#define CONFIG_CMD_UNZIP /* unzip from memory to memory */
#define CONFIG_CMD_USB /* USB Support */
#define CONFIG_CMD_VFD /* VFD support (TRAB) */
#define CONFIG_CMD_XIMG /* Load part of Multi Image */
#define CFG_FLASH_BASE 0xFE000000
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_MAX_FLASH_SECT 256 /* max num of sects on one chip */
#define CFG_MAX_FLASH_BANKS flash_banks /* max num of flash banks */
/* updated in board_early_init_r */
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_CFI 1
#define CFG_FLASH_EMPTY_INFO
*/
#define CFG_FLASH_BASE 0xFE000000
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_MAX_FLASH_BANKS 1 /* Max number of flash banks */
#define CFG_MAX_FLASH_SECT 128 /* Max num of sects on one chip */
/*
* Winbond Configuration
*/
-#define CFG_WINBOND_83C553 1 /* has a winbond bridge */
+#define CONFIG_WINBOND_83C553 1 /* has a winbond bridge */
#define CFG_USE_WINBOND_IDE 0 /* use winbond 83c553 internal ide */
#define CFG_WINBOND_ISA_CFG_ADDR 0x80005800 /* pci-isa bridge config addr */
#define CFG_WINBOND_IDE_CFG_ADDR 0x80005900 /* ide config addr */
/*
* NS87308 Configuration
*/
-#define CFG_NS87308 /* Nat Semi super-io cntr on ISA bus */
+#define CONFIG_NS87308 /* Nat Semi super-io cntr on ISA bus */
#define CFG_NS87308_BADDR_10 1
#define CFG_NS87308_DEVS (CFG_NS87308_UART1 | \
CFG_NS87308_UART2 | \
/* use CFI flash driver if no module variant is spezified */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_BOOTCS_START }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_SIZE 0x04000000 /* 64 MByte */
/* CONFIG_CMD_DOC required legacy NAND support */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#if 0
#define CONFIG_PCI 1
* FLASH related
*----------------------------------------------------------------------*/
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
#define CFG_FLASH_PROTECTION 1 /* use hardware protection */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#endif
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
/*
* Miscellaneous configurable options
* FLASH related
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
*/
#define CFG_FLASH_BASE 0xFC000000
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_MAX_FLASH_BANKS 1 /* Max number of flash banks */
#define CFG_MAX_FLASH_SECT 512 /* Max num of sects on one chip */
/*
- * (C) Copyright 2000
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/fps850L/uImage\0" \
+ "hostname=FPS850L\0" \
+ "bootfile=FPS850L/uImage\0" \
"fdt_addr=40040000\0" \
"kernel_addr=40060000\0" \
"ramdisk_addr=40200000\0" \
+ "u-boot=FPS850L/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
/*-----------------------------------------------------------------------
* FLASH organization
*/
-#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
-#define CFG_MAX_FLASH_SECT 71 /* max number of sectors on one chip */
-#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
-#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */
+/* use CFI flash driver */
+#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
+#define CFG_FLASH_EMPTY_INFO
+#define CFG_FLASH_USE_BUFFER_WRITE 1
+#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
+#define CFG_MAX_FLASH_SECT 71 /* max number of sectors on one chip */
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_OFFSET 0x8000 /* Offset of Environment Sector */
#define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET+CFG_ENV_SIZE)
#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE)
+#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
+
+/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
+ "128k(dtb)," \
+ "1664k(kernel)," \
+ "2m(rootfs)," \
+ "4m(data)"
+
/*-----------------------------------------------------------------------
* Hardware Information Block
*/
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/fps850L/uImage\0" \
+ "hostname=FPS860L\0" \
+ "bootfile=FPS860L/uImage\0" \
"fdt_addr=40040000\0" \
"kernel_addr=40060000\0" \
"ramdisk_addr=40200000\0" \
+ "u-boot=FPS860L/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
/*-----------------------------------------------------------------------
* FLASH organization
*/
-#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
-#define CFG_MAX_FLASH_SECT 67 /* max number of sectors on one chip */
-#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
-#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */
+/* use CFI flash driver */
+#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
+#define CFG_FLASH_EMPTY_INFO
+#define CFG_FLASH_USE_BUFFER_WRITE 1
+#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
+#define CFG_MAX_FLASH_SECT 71 /* max number of sectors on one chip */
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_OFFSET 0x8000 /* Offset of Environment Sector */
#define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET+CFG_ENV_SIZE)
#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE)
+#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
+
+/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
+ "128k(dtb)," \
+ "1664k(kernel)," \
+ "2m(rootfs)," \
+ "4m(data)"
+
/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_REMAP_OR_AM 0x80000000 /* OR addr mask */
#define CFG_PRELIM_OR_AM 0xE0000000 /* OR addr mask */
-/* FLASH timing: ACS = 11, TRLX = 0, CSNT = 1, SCY = 5, EHTR = 1 */
-#define CFG_OR_TIMING_FLASH (OR_CSNT_SAM | OR_ACS_DIV2 | OR_BI | \
- OR_SCY_5_CLK | OR_EHTR)
+/*
+ * FLASH timing:
+ */
+#define CFG_OR_TIMING_FLASH (OR_ACS_DIV1 | OR_TRLX | OR_CSNT_SAM | \
+ OR_SCY_3_CLK | OR_EHTR | OR_BI)
#define CFG_OR0_REMAP (CFG_REMAP_OR_AM | CFG_OR_TIMING_FLASH)
#define CFG_OR0_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_FLASH)
/*
* Memory Periodic Timer Prescaler
+ *
+ * The Divider for PTA (refresh timer) configuration is based on an
+ * example SDRAM configuration (64 MBit, one bank). The adjustment to
+ * the number of chip selects (NCS) and the actually needed refresh
+ * rate is done by setting MPTPR.
+ *
+ * PTA is calculated from
+ * PTA = (gclk * Trefresh) / ((2 ^ (2 * DFBRG)) * PTP * NCS)
+ *
+ * gclk CPU clock (not bus clock!)
+ * Trefresh Refresh cycle * 4 (four word bursts used)
+ *
+ * 4096 Rows from SDRAM example configuration
+ * 1000 factor s -> ms
+ * 32 PTP (pre-divider from MPTPR) from SDRAM example configuration
+ * 4 Number of refresh cycles per period
+ * 64 Refresh cycle in ms per number of rows
+ * --------------------------------------------
+ * Divider = 4096 * 32 * 1000 / (4 * 64) = 512000
+ *
+ * 50 MHz => 50.000.000 / Divider = 98
+ * 66 Mhz => 66.000.000 / Divider = 129
+ * 80 Mhz => 80.000.000 / Divider = 156
*/
-/* periodic timer for refresh */
-#define CFG_MAMR_PTA 97 /* start with divider for 100 MHz */
+#define CFG_PTA_PER_CLK ((4096 * 32 * 1000) / (4 * 64))
+#define CFG_MAMR_PTA 98
-/* refresh rate 15.6 us (= 64 ms / 4K = 62.4 / quad bursts) for <= 128 MBit */
+/*
+ * For 16 MBit, refresh rates could be 31.3 us
+ * (= 64 ms / 2K = 125 / quad bursts).
+ * For a simpler initialization, 15.6 us is used instead.
+ *
+ * #define CFG_MPTPR_2BK_2K MPTPR_PTP_DIV32 for 2 banks
+ * #define CFG_MPTPR_1BK_2K MPTPR_PTP_DIV64 for 1 bank
+ */
#define CFG_MPTPR_2BK_4K MPTPR_PTP_DIV16 /* setting for 2 banks */
#define CFG_MPTPR_1BK_4K MPTPR_PTP_DIV32 /* setting for 1 bank */
#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */
#define BOOTFLAG_WARM 0x02 /* Software reboot */
+#define CONFIG_SCC1_ENET
+
#endif /* __CONFIG_H */
#define CFG_FPGA_PROG_FEEDBACK
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
/*
* Verbose help from command monitor.
/*
* define UIC_EXT0 ... UIC_EXT6 if external interrupt is active high
*/
-#define CFG_UIC0_POLARITY (0xFFFFFF80 | UIC_EXT6)
+#define CFG_UIC0_POLARITY (0xFFFFFF80 | UIC_MASK(VECNUM_EIRQ6))
/*-----------------------------------------------------------------------
* FPGA stuff
*/
-#define CFG_WINBOND_83C553 1 /*has a winbond bridge */
+#define CONFIG_WINBOND_83C553 1 /*has a winbond bridge */
#define CFG_USE_WINBOND_IDE 0 /*use winbond 83c553 internal IDE ctrlr */
#define CFG_WINBOND_ISA_CFG_ADDR 0x80005800 /*pci-isa bridge config addr */
#define CFG_WINBOND_IDE_CFG_ADDR 0x80005900 /*ide config addr */
/*
* NS87308 Configuration
*/
-#define CFG_NS87308 /* Nat Semi super-io controller on ISA bus */
+#define CONFIG_NS87308 /* Nat Semi super-io controller on ISA bus */
#define CFG_NS87308_BADDR_10 1
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST { 0xFF800000 }
#define CFG_MAX_FLASH_BANKS_DETECT 1
/* What should the base address of the main FLASH be and how big is
*/
#if defined(CONFIG_CMD_NAND)
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_NAND0_BASE 0xE1000000
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
*/
#define CFG_FLASH_BASE 0xFE000000
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_MAX_FLASH_BANKS 1 /* Max num of memory banks */
#define CFG_MAX_FLASH_SECT 142 /* Max num of sects on one chip */
#undef CONFIG_FLASH_16BIT /* Flash is 8-bit */
#if defined(CONFIG_LITE5200B)
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_BANKS_LIST {CFG_CS1_START,CFG_CS0_START}
#endif
#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_SIZE 0x1000000 /* Max size that the board might have */
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
# define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
*/
#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_SIZE 0x800000 /* Max size that the board might have */
#ifdef NORFLASH_PS32BIT
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_32BIT
#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_SIZE 0x1000000 /* Max size that the board might have */
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
# define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
--- /dev/null
+/*
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ * Hayden Fraser (Hayden.Fraser@freescale.com)
+ *
+ * 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 _M5253DEMO_H
+#define _M5253DEMO_H
+
+#define CONFIG_MCF52x2 /* define processor family */
+#define CONFIG_M5253 /* define processor type */
+#define CONFIG_M5253DEMO /* define board type */
+
+#define CONFIG_MCFTMR
+
+#define CONFIG_MCFUART
+#define CFG_UART_PORT (0)
+#define CONFIG_BAUDRATE 115200
+#define CFG_BAUDRATE_TABLE { 9600 , 19200 , 38400 , 57600, 115200 }
+
+#undef CONFIG_WATCHDOG /* disable watchdog */
+
+#define CONFIG_BOOTDELAY 5
+
+/* Configuration for environment
+ * Environment is embedded in u-boot in the second sector of the flash
+ */
+#ifdef CONFIG_MONITOR_IS_IN_RAM
+# define CFG_ENV_OFFSET 0x4000
+# define CFG_ENV_SECT_SIZE 0x1000
+# define CFG_ENV_IS_IN_FLASH 1
+#else
+# define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x4000)
+# define CFG_ENV_SECT_SIZE 0x1000
+# define CFG_ENV_IS_IN_FLASH 1
+#endif
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_LOADB
+#define CONFIG_CMD_LOADS
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_IDE
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_MISC
+#define CONFIG_CMD_PING
+
+#ifdef CONFIG_CMD_IDE
+/* ATA */
+# define CONFIG_DOS_PARTITION
+# define CONFIG_MAC_PARTITION
+# define CONFIG_IDE_RESET 1
+# define CONFIG_IDE_PREINIT 1
+# define CONFIG_ATAPI
+# undef CONFIG_LBA48
+
+# define CFG_IDE_MAXBUS 1
+# define CFG_IDE_MAXDEVICE 2
+
+# define CFG_ATA_BASE_ADDR (CFG_MBAR2 + 0x800)
+# define CFG_ATA_IDE0_OFFSET 0
+
+# define CFG_ATA_DATA_OFFSET 0xA0 /* Offset for data I/O */
+# define CFG_ATA_REG_OFFSET 0xA0 /* Offset for normal register accesses */
+# define CFG_ATA_ALT_OFFSET 0xC0 /* Offset for alternate registers */
+# define CFG_ATA_STRIDE 4 /* Interval between registers */
+# define _IO_BASE 0
+#endif
+
+#define CONFIG_DRIVER_DM9000
+#ifdef CONFIG_DRIVER_DM9000
+# define CONFIG_DM9000_BASE ((CFG_CSAR1 << 16) | 0x300)
+# define DM9000_IO CONFIG_DM9000_BASE
+# define DM9000_DATA (CONFIG_DM9000_BASE + 4)
+# undef CONFIG_DM9000_DEBUG
+
+# define CONFIG_ETHADDR 00:e0:0c:bc:e5:60
+# define CONFIG_IPADDR 10.82.121.249
+# define CONFIG_NETMASK 255.255.252.0
+# define CONFIG_SERVERIP 10.82.120.80
+# define CONFIG_GATEWAYIP 10.82.123.254
+# define CONFIG_OVERWRITE_ETHADDR_ONCE
+
+# define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "inpclk=" MK_STR(CFG_INPUT_CLKSRC) "\0" \
+ "loadaddr=10000\0" \
+ "u-boot=u-boot.bin\0" \
+ "load=tftp ${loadaddr) ${u-boot}\0" \
+ "upd=run load; run prog\0" \
+ "prog=prot off 0 2ffff;" \
+ "era 0 2ffff;" \
+ "cp.b ${loadaddr} 0 ${filesize};" \
+ "save\0" \
+ ""
+#endif
+
+#define CONFIG_HOSTNAME M5253DEMO
+
+#define CFG_PROMPT "=> "
+#define CFG_LONGHELP /* undef to save memory */
+
+#if defined(CONFIG_CMD_KGDB)
+# define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#else
+# define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#endif
+#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_LOAD_ADDR 0x00100000
+
+#define CFG_MEMTEST_START 0x400
+#define CFG_MEMTEST_END 0x380000
+
+#define CFG_HZ 1000
+
+#undef CFG_PLL_BYPASS /* bypass PLL for test purpose */
+#define CFG_FAST_CLK
+#ifdef CFG_FAST_CLK
+# define CFG_PLLCR 0x1243E054
+# define CFG_CLK 140000000
+#else
+# define CFG_PLLCR 0x135a4140
+# define CFG_CLK 70000000
+#endif
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+#define CFG_MBAR 0x10000000 /* Register Base Addrs */
+#define CFG_MBAR2 0x80000000 /* Module Base Addrs 2 */
+
+/*
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR 0x20000000
+#define CFG_INIT_RAM_END 0x10000 /* End of used area in internal SRAM */
+#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
+
+/*
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE 0x00000000
+#define CFG_SDRAM_SIZE 16 /* SDRAM size in MB */
+
+#ifdef CONFIG_MONITOR_IS_IN_RAM
+# define CFG_MONITOR_BASE 0x20000
+#else
+# define CFG_MONITOR_BASE (CFG_FLASH_BASE + 0x400)
+#endif
+
+#define CFG_MONITOR_LEN 0x40000
+#define CFG_MALLOC_LEN (256 << 10)
+#define CFG_BOOTPARAMS_LEN (64*1024)
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization ??
+ */
+#define CFG_BOOTMAPSZ (CFG_SDRAM_BASE + (CFG_SDRAM_SIZE << 20))
+
+/* FLASH organization */
+#define CFG_FLASH_BASE (CFG_CSAR0 << 16)
+#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
+#define CFG_MAX_FLASH_SECT 2048 /* max number of sectors on one chip */
+#define CFG_FLASH_ERASE_TOUT 1000
+
+#define FLASH_SST6401B 0x200
+#define SST_ID_xF6401B 0x236D236D
+
+#undef CFG_FLASH_CFI
+#ifdef CFG_FLASH_CFI
+/*
+ * Unable to use CFI driver, due to incompatible sector erase command by SST.
+ * Amd/Atmel use 0x30 for sector erase, SST use 0x50.
+ * 0x30 is block erase in SST
+ */
+# define CFG_FLASH_CFI_DRIVER 1
+# define CFG_FLASH_SIZE 0x800000
+# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
+# define CONFIG_FLASH_CFI_LEGACY
+#else
+# define CFG_SST_SECT 2048
+# define CFG_SST_SECTSZ 0x1000
+# define CFG_FLASH_WRITE_TOUT 500
+#endif
+
+/* Cache Configuration */
+#define CFG_CACHELINE_SIZE 16
+
+/* Port configuration */
+#define CFG_FECI2C 0xF0
+
+#define CFG_CSAR0 0xFF80
+#define CFG_CSMR0 0x007F0021
+#define CFG_CSCR0 0x1D80
+
+#define CFG_CSAR1 0xE000
+#define CFG_CSMR1 0x00000001
+#define CFG_CSCR1 0x3DD8
+
+#define CFG_CSAR2 0
+#define CFG_CSMR2 0
+#define CFG_CSCR2 0
+
+#define CFG_CSAR3 0
+#define CFG_CSMR3 0
+#define CFG_CSCR3 0
+
+/*-----------------------------------------------------------------------
+ * Port configuration
+ */
+#define CFG_GPIO_FUNC 0x00000008 /* Set gpio pins: none */
+#define CFG_GPIO1_FUNC 0x00df00f0 /* 36-39(SWITCH),48-52(FPGAs),54 */
+#define CFG_GPIO_EN 0x00000008 /* Set gpio output enable */
+#define CFG_GPIO1_EN 0x00c70000 /* Set gpio output enable */
+#define CFG_GPIO_OUT 0x00000008 /* Set outputs to default state */
+#define CFG_GPIO1_OUT 0x00c70000 /* Set outputs to default state */
+#define CFG_GPIO1_LED 0x00400000 /* user led */
+
+#endif /* _M5253DEMO_H */
#define CONFIG_MCFUART
#define CFG_UART_PORT (0)
-#define CONFIG_BAUDRATE 19200
+#define CONFIG_BAUDRATE 115200
#define CFG_BAUDRATE_TABLE { 9600 , 19200 , 38400 , 57600, 115200 }
#undef CONFIG_WATCHDOG /* disable watchdog */
#define CFG_FLASH_ERASE_TOUT 1000
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_SIZE 0x200000
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
#define CFG_FLASH_ERASE_TOUT 1000
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_SIZE 0x200000
/* Cache Configuration */
#define CFG_FLASH_ERASE_TOUT 1000
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_SIZE 0x200000
/*-----------------------------------------------------------------------
# define CONFIG_OVERWRITE_ETHADDR_ONCE
#endif /* CONFIG_MCFFEC */
-#define CONFIG_HOSTNAME M5272C3
+#define CONFIG_HOSTNAME M5282EVB
#define CONFIG_EXTRA_ENV_SETTINGS \
"netdev=eth0\0" \
"loadaddr=10000\0" \
#define CFG_MEMTEST_START 0x400
#define CFG_MEMTEST_END 0x380000
-#define CFG_HZ 1000000
+#define CFG_HZ 1000
#define CFG_CLK 64000000
/* PLL Configuration: Ext Clock * 6 (see table 9-4 of MCF user manual) */
#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_SIZE 0x1000000 /* Max size that the board might have */
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
# define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
*/
#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_SIZE 0x800000 /* Max size that the board might have */
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
# define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
*/
#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_SIZE 0x800000 /* Max size that the board might have */
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
# define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
--- /dev/null
+/*
+ * Configuation settings for the Freescale MCF54451 EVB board.
+ *
+ * Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
+ * 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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef _M54451EVB_H
+#define _M54451EVB_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_MCF5445x /* define processor family */
+#define CONFIG_M54451 /* define processor type */
+#define CONFIG_M54451EVB /* M54451EVB board */
+
+#define CONFIG_MCFUART
+#define CFG_UART_PORT (0)
+#define CONFIG_BAUDRATE 115200
+#define CFG_BAUDRATE_TABLE { 9600 , 19200 , 38400 , 57600, 115200 }
+
+#undef CONFIG_WATCHDOG
+
+#define CONFIG_TIMESTAMP /* Print image info with timestamp */
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+/* Command line configuration */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_BOOTD
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_FLASH
+#define CONFIG_CMD_I2C
+#undef CONFIG_CMD_JFFS2
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_MISC
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_SF
+
+#undef CONFIG_CMD_LOADB
+#undef CONFIG_CMD_LOADS
+
+/* Network configuration */
+#define CONFIG_MCFFEC
+#ifdef CONFIG_MCFFEC
+# define CONFIG_NET_MULTI 1
+# define CONFIG_MII 1
+# define CONFIG_MII_INIT 1
+# define CFG_DISCOVER_PHY
+# define CFG_RX_ETH_BUFFER 8
+# define CFG_FAULT_ECHO_LINK_DOWN
+
+# define CFG_FEC0_PINMUX 0
+# define CFG_FEC0_MIIBASE CFG_FEC0_IOBASE
+# define MCFFEC_TOUT_LOOP 50000
+
+# define CONFIG_BOOTDELAY 1 /* autoboot after 5 seconds */
+# define CONFIG_BOOTARGS "root=/dev/mtdblock1 rw rootfstype=jffs2 ip=none mtdparts=physmap-flash.0:5M(kernel)ro,-(jffs2)"
+# define CONFIG_ETHADDR 00:e0:0c:bc:e5:60
+# define CONFIG_ETHPRIME "FEC0"
+# define CONFIG_IPADDR 192.162.1.2
+# define CONFIG_NETMASK 255.255.255.0
+# define CONFIG_SERVERIP 192.162.1.1
+# define CONFIG_GATEWAYIP 192.162.1.1
+# define CONFIG_OVERWRITE_ETHADDR_ONCE
+
+/* If CFG_DISCOVER_PHY is not defined - hardcoded */
+# ifndef CFG_DISCOVER_PHY
+# define FECDUPLEX FULL
+# define FECSPEED _100BASET
+# else
+# ifndef CFG_FAULT_ECHO_LINK_DOWN
+# define CFG_FAULT_ECHO_LINK_DOWN
+# endif
+# endif /* CFG_DISCOVER_PHY */
+#endif
+
+#define CONFIG_HOSTNAME M54451EVB
+#ifdef CFG_STMICRO_BOOT
+/* ST Micro serial flash */
+#define CFG_LOAD_ADDR2 0x40010007
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "inpclk=" MK_STR(CFG_INPUT_CLKSRC) "\0" \
+ "loadaddr=0x40010000\0" \
+ "sbfhdr=sbfhdr.bin\0" \
+ "uboot=u-boot.bin\0" \
+ "load=tftp ${loadaddr} ${sbfhdr};" \
+ "tftp " MK_STR(CFG_LOAD_ADDR2) " ${uboot} \0" \
+ "upd=run load; run prog\0" \
+ "prog=sf probe 0:1 10000 1;" \
+ "sf erase 0 30000;" \
+ "sf write ${loadaddr} 0 30000;" \
+ "save\0" \
+ ""
+#else
+#define CFG_UBOOT_END 0x3FFFF
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "inpclk=" MK_STR(CFG_INPUT_CLKSRC) "\0" \
+ "loadaddr=40010000\0" \
+ "u-boot=u-boot.bin\0" \
+ "load=tftp ${loadaddr) ${u-boot}\0" \
+ "upd=run load; run prog\0" \
+ "prog=prot off 0 " MK_STR(CFG_UBOOT_END)\
+ "; era 0 " MK_STR(CFG_UBOOT_END) \
+ "2ffff;" \
+ "cp.b ${loadaddr} 0 ${filesize};" \
+ "save\0" \
+ ""
+#endif
+
+/* Realtime clock */
+#define CONFIG_MCFRTC
+#undef RTC_DEBUG
+#define CFG_RTC_OSCILLATOR (32 * CFG_HZ)
+
+/* Timer */
+#define CONFIG_MCFTMR
+#undef CONFIG_MCFPIT
+
+/* I2c */
+#define CONFIG_FSL_I2C
+#define CONFIG_HARD_I2C /* I2C with hardware support */
+#undef CONFIG_SOFT_I2C /* I2C bit-banged */
+#define CFG_I2C_SPEED 80000 /* I2C speed and slave address */
+#define CFG_I2C_SLAVE 0x7F
+#define CFG_I2C_OFFSET 0x58000
+#define CFG_IMMR CFG_MBAR
+
+/* DSPI and Serial Flash */
+#define CONFIG_CF_DSPI
+#define CONFIG_SERIAL_FLASH
+#define CONFIG_HARD_SPI
+#define CFG_SER_FLASH_BASE 0x01000000
+#define CFG_SBFHDR_SIZE 0x7
+#ifdef CONFIG_CMD_SPI
+# define CONFIG_SPI_FLASH
+# define CONFIG_SPI_FLASH_STMICRO
+
+# define CFG_DSPI_DCTAR0 (DSPI_DCTAR_TRSZ(7) | \
+ DSPI_DCTAR_CPOL | \
+ DSPI_DCTAR_CPHA | \
+ DSPI_DCTAR_PCSSCK_1CLK | \
+ DSPI_DCTAR_PASC(0) | \
+ DSPI_DCTAR_PDT(0) | \
+ DSPI_DCTAR_CSSCK(0) | \
+ DSPI_DCTAR_ASC(0) | \
+ DSPI_DCTAR_PBR(0) | \
+ DSPI_DCTAR_DT(1) | \
+ DSPI_DCTAR_BR(1))
+#endif
+
+/* Input, PCI, Flexbus, and VCO */
+#define CONFIG_EXTRA_CLOCK
+
+#define CONFIG_PRAM 2048 /* 2048 KB */
+
+#define CFG_PROMPT "-> "
+#define CFG_LONGHELP /* undef to save memory */
+
+#if defined(CONFIG_CMD_KGDB)
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#else
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#endif
+#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_LOAD_ADDR (CFG_SDRAM_BASE + 0x10000)
+
+#define CFG_HZ 1000
+
+#define CFG_MBAR 0xFC000000
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR 0x80000000
+#define CFG_INIT_RAM_END 0x8000 /* End of used area in internal SRAM */
+#define CFG_INIT_RAM_CTRL 0x221
+#define CFG_GBL_DATA_SIZE 256 /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET ((CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) - 32)
+#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
+#define CFG_SBFHDR_DATA_OFFSET (CFG_INIT_RAM_END - 32)
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE 0x40000000
+#define CFG_SDRAM_SIZE 128 /* SDRAM size in MB */
+#define CFG_SDRAM_CFG1 0x33633F30
+#define CFG_SDRAM_CFG2 0x57670000
+#define CFG_SDRAM_CTRL 0xE20D2C00
+#define CFG_SDRAM_EMOD 0x80810000
+#define CFG_SDRAM_MODE 0x008D0000
+#define CFG_SDRAM_DRV_STRENGTH 0x44
+
+#define CFG_MEMTEST_START CFG_SDRAM_BASE + 0x400
+#define CFG_MEMTEST_END ((CFG_SDRAM_SIZE - 3) << 20)
+
+#ifdef CONFIG_CF_SBF
+# define CFG_MONITOR_BASE (TEXT_BASE + 0x400)
+#else
+# define CFG_MONITOR_BASE (CFG_FLASH_BASE + 0x400)
+#endif
+#define CFG_BOOTPARAMS_LEN 64*1024
+#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */
+#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization ??
+ */
+/* Initial Memory map for Linux */
+#define CFG_BOOTMAPSZ (CFG_SDRAM_BASE + (CFG_SDRAM_SIZE << 20))
+
+/* Configuration for environment
+ * Environment is embedded in u-boot in the second sector of the flash
+ */
+#if defined(CONFIG_CF_SBF)
+# define CFG_ENV_IS_IN_SPI_FLASH 1
+# define CFG_ENV_SPI_CS 1
+# define CFG_ENV_OFFSET 0x20000
+# define CFG_ENV_SIZE 0x2000
+# define CFG_ENV_SECT_SIZE 0x10000
+#else
+# define CFG_ENV_IS_IN_FLASH 1
+# define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x4000)
+# define CFG_ENV_SECT_SIZE 0x2000
+#endif
+#undef CONFIG_ENV_OVERWRITE
+#undef CFG_ENV_IS_EMBEDDED
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#ifdef CFG_STMICRO_BOOT
+# define CFG_FLASH_BASE CFG_SER_FLASH_BASE
+# define CFG_FLASH0_BASE CFG_SER_FLASH_BASE
+# define CFG_FLASH1_BASE CFG_CS0_BASE
+#endif
+#ifdef CFG_SPANSION_BOOT
+# define CFG_FLASH_BASE CFG_CS0_BASE
+# define CFG_FLASH0_BASE CFG_CS0_BASE
+# define CFG_FLASH1_BASE CFG_SER_FLASH_BASE
+#endif
+
+#define CFG_FLASH_CFI
+#ifdef CFG_FLASH_CFI
+
+# define CONFIG_FLASH_CFI_DRIVER 1
+# define CFG_FLASH_SIZE 0x1000000 /* Max size that the board might have */
+# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
+# define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
+# define CFG_MAX_FLASH_SECT 137 /* max number of sectors on one chip */
+# define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */
+# define CFG_FLASH_CHECKSUM
+# define CFG_FLASH_BANKS_LIST { CFG_CS0_BASE }
+
+#endif
+
+/*
+ * This is setting for JFFS2 support in u-boot.
+ * NOTE: Enable CONFIG_CMD_JFFS2 for JFFS2 support.
+ */
+#ifdef CFG_SPANSION_BOOT
+# define CONFIG_JFFS2_DEV "nor0"
+# define CONFIG_JFFS2_PART_SIZE 0x01000000
+# define CONFIG_JFFS2_PART_OFFSET (CFG_FLASH0_BASE + 0x500000)
+#endif
+#ifdef CFG_STMICRO_BOOT
+# define CONFIG_JFFS2_DEV "nor0"
+# define CONFIG_JFFS2_PART_SIZE 0x01000000
+# define CONFIG_JFFS2_PART_OFFSET (CFG_FLASH0_BASE + 0x500000)
+#endif
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE 16
+
+/*-----------------------------------------------------------------------
+ * Memory bank definitions
+ */
+/*
+ * CS0 - NOR Flash 8MB
+ * CS1 - Available
+ * CS2 - Available
+ * CS3 - Available
+ * CS4 - Available
+ * CS5 - Available
+ */
+
+ /* SPANSION Flash */
+#define CFG_CS0_BASE 0x00000000
+#define CFG_CS0_MASK 0x007F0001
+#define CFG_CS0_CTRL 0x00001180
+
+#define CFG_SPANSION_BASE CFG_CS0_BASE
+
+#endif /* _M54451EVB_H */
#undef CONFIG_CMD_PCI
#define CONFIG_CMD_PING
#define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_SF
#undef CONFIG_CMD_LOADB
#undef CONFIG_CMD_LOADS
#endif
#define CONFIG_HOSTNAME M54455EVB
+#ifdef CFG_STMICRO_BOOT
+/* ST Micro serial flash */
+#define CFG_LOAD_ADDR2 0x40010013
#define CONFIG_EXTRA_ENV_SETTINGS \
"netdev=eth0\0" \
"inpclk=" MK_STR(CFG_INPUT_CLKSRC) "\0" \
- "loadaddr=40010000\0" \
- "u-boot=u-boot.bin\0" \
- "load=tftp ${loadaddr) ${u-boot}\0" \
+ "loadaddr=0x40010000\0" \
+ "sbfhdr=sbfhdr.bin\0" \
+ "uboot=u-boot.bin\0" \
+ "load=tftp ${loadaddr} ${sbfhdr};" \
+ "tftp " MK_STR(CFG_LOAD_ADDR2) " ${uboot} \0" \
"upd=run load; run prog\0" \
- "prog=prot off 4000000 402ffff;" \
- "era 4000000 402ffff;" \
- "cp.b ${loadaddr} 0 ${filesize};" \
+ "prog=sf probe 0:1 10000 1;" \
+ "sf erase 0 30000;" \
+ "sf write ${loadaddr} 0 0x30000;" \
"save\0" \
""
+#else
+/* Atmel and Intel */
+#ifdef CFG_ATMEL_BOOT
+# define CFG_UBOOT_END 0x0403FFFF
+#elif defined(CFG_INTEL_BOOT)
+# define CFG_UBOOT_END 0x3FFFF
+#endif
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "inpclk=" MK_STR(CFG_INPUT_CLKSRC) "\0" \
+ "loadaddr=0x40010000\0" \
+ "uboot=u-boot.bin\0" \
+ "load=tftp ${loadaddr} ${uboot}\0" \
+ "upd=run load; run prog\0" \
+ "prog=prot off " MK_STR(CFG_FLASH_BASE) \
+ " " MK_STR(CFG_UBOOT_END) ";" \
+ "era " MK_STR(CFG_FLASH_BASE) " " \
+ MK_STR(CFG_UBOOT_END) ";" \
+ "cp.b ${loadaddr} " MK_STR(CFG_FLASH_BASE)\
+ " ${filesize}; save\0" \
+ ""
+#endif
/* ATA configuration */
#define CONFIG_ISO_PARTITION
/* DSPI and Serial Flash */
#define CONFIG_CF_DSPI
-#define CONFIG_SERIAL_FLASH
+#define CONFIG_HARD_SPI
+#define CFG_SER_FLASH_BASE 0x01000000
+#define CFG_SBFHDR_SIZE 0x13
+#ifdef CONFIG_CMD_SPI
+# define CONFIG_SPI_FLASH
+# define CONFIG_SPI_FLASH_STMICRO
+
+# define CFG_DSPI_DCTAR0 (DSPI_DCTAR_TRSZ(7) | \
+ DSPI_DCTAR_CPOL | \
+ DSPI_DCTAR_CPHA | \
+ DSPI_DCTAR_PCSSCK_1CLK | \
+ DSPI_DCTAR_PASC(0) | \
+ DSPI_DCTAR_PDT(0) | \
+ DSPI_DCTAR_CSSCK(0) | \
+ DSPI_DCTAR_ASC(0) | \
+ DSPI_DCTAR_PBR(0) | \
+ DSPI_DCTAR_DT(1) | \
+ DSPI_DCTAR_BR(1))
+#endif
/* PCI */
#ifdef CONFIG_CMD_PCI
/* Input, PCI, Flexbus, and VCO */
#define CONFIG_EXTRA_CLOCK
-#define CONFIG_PRAM 512 /* 512 KB */
+#define CONFIG_PRAM 2048 /* 2048 KB */
#define CFG_PROMPT "-> "
#define CFG_LONGHELP /* undef to save memory */
#define CFG_INIT_RAM_END 0x8000 /* End of used area in internal SRAM */
#define CFG_INIT_RAM_CTRL 0x221
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
-#define CFG_GBL_DATA_OFFSET ((CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) - 16)
+#define CFG_GBL_DATA_OFFSET ((CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) - 32)
#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
+#define CFG_SBFHDR_DATA_OFFSET (CFG_INIT_RAM_END - 32)
/*-----------------------------------------------------------------------
* Start addresses for the final memory configuration
#define CFG_SDRAM_CTRL 0xEA0B2000
#define CFG_SDRAM_EMOD 0x40010000
#define CFG_SDRAM_MODE 0x00010033
+#define CFG_SDRAM_DRV_STRENGTH 0xAA
#define CFG_MEMTEST_START CFG_SDRAM_BASE + 0x400
#define CFG_MEMTEST_END ((CFG_SDRAM_SIZE - 3) << 20)
-#define CFG_MONITOR_BASE (CFG_FLASH_BASE + 0x400)
+#ifdef CONFIG_CF_SBF
+# define CFG_MONITOR_BASE (TEXT_BASE + 0x400)
+#else
+# define CFG_MONITOR_BASE (CFG_FLASH_BASE + 0x400)
+#endif
#define CFG_BOOTPARAMS_LEN 64*1024
#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */
#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */
/* Initial Memory map for Linux */
#define CFG_BOOTMAPSZ (CFG_SDRAM_BASE + (CFG_SDRAM_SIZE << 20))
-/* Configuration for environment
+/*
+ * Configuration for environment
* Environment is embedded in u-boot in the second sector of the flash
*/
-#define CFG_ENV_IS_IN_FLASH 1
-#define CONFIG_ENV_OVERWRITE 1
+#ifdef CONFIG_CF_SBF
+# define CFG_ENV_IS_IN_SPI_FLASH
+# define CFG_ENV_SPI_CS 1
+#else
+# define CFG_ENV_IS_IN_FLASH 1
+#endif
+#undef CONFIG_ENV_OVERWRITE
#undef CFG_ENV_IS_EMBEDDED
/*-----------------------------------------------------------------------
* FLASH organization
*/
+#ifdef CFG_STMICRO_BOOT
+# define CFG_FLASH_BASE CFG_SER_FLASH_BASE
+# define CFG_FLASH0_BASE CFG_SER_FLASH_BASE
+# define CFG_FLASH1_BASE CFG_CS0_BASE
+# define CFG_FLASH2_BASE CFG_CS1_BASE
+# define CFG_ENV_OFFSET 0x30000
+# define CFG_ENV_SIZE 0x2000
+# define CFG_ENV_SECT_SIZE 0x10000
+#endif
#ifdef CFG_ATMEL_BOOT
# define CFG_FLASH_BASE CFG_CS0_BASE
# define CFG_FLASH0_BASE CFG_CS0_BASE
# define CFG_FLASH1_BASE CFG_CS1_BASE
# define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x4000)
# define CFG_ENV_SECT_SIZE 0x2000
-#else
+#endif
+#ifdef CFG_INTEL_BOOT
# define CFG_FLASH_BASE CFG_CS0_BASE
# define CFG_FLASH0_BASE CFG_CS0_BASE
# define CFG_FLASH1_BASE CFG_CS1_BASE
-# define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x60000)
+# define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x40000)
+# define CFG_ENV_SIZE 0x2000
# define CFG_ENV_SECT_SIZE 0x20000
#endif
-/* M54455EVB has one non CFI flash, defined CFG_FLASH_CFI will cause the system
- keep reset. */
-#undef CFG_FLASH_CFI
+#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_SIZE 0x1000000 /* Max size that the board might have */
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
# define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
# define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */
# define CFG_FLASH_CHECKSUM
# define CFG_FLASH_BANKS_LIST { CFG_CS0_BASE, CFG_CS1_BASE }
+# define CONFIG_FLASH_CFI_LEGACY
-#else
-
-# define CFG_MAX_FLASH_BANKS 3 /* max number of memory banks */
-
+#ifdef CONFIG_FLASH_CFI_LEGACY
# define CFG_ATMEL_REGION 4
# define CFG_ATMEL_TOTALSECT 11
# define CFG_ATMEL_SECT {1, 2, 1, 7}
# define CFG_ATMEL_SECTSZ {0x4000, 0x2000, 0x8000, 0x10000}
-# define CFG_INTEL_SECT 137
-
-/* max number of sectors on one chip */
-# define CFG_MAX_FLASH_SECT (CFG_ATMEL_TOTALSECT + CFG_INTEL_SECT)
-# define CFG_FLASH_ERASE_TOUT 2000 /* Atmel needs longer timeout */
-# define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */
-# define CFG_FLASH_LOCK_TOUT 5 /* Timeout for Flash Set Lock Bit (in ms) */
-# define CFG_FLASH_UNLOCK_TOUT 100 /* Timeout for Flash Clear Lock Bits (in ms) */
-# define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */
-# define CFG_FLASH_CHECKSUM
-
-#ifdef CONFIG_SERIAL_FLASH
-# define CFG_FLASH2_BASE 0x01000000
-# define CFG_STM_SECT 32
-# define CFG_STM_SECTSZ 0x10000
-
-# undef CFG_FLASH_ERASE_TOUT
-# define CFG_FLASH_ERASE_TOUT 20000
-
-# define SER_WREN 0x06
-# define SER_WRDI 0x04
-# define SER_RDID 0x9F
-# define SER_RDSR 0x05
-# define SER_WRSR 0x01
-# define SER_READ 0x03
-# define SER_F_READ 0x0B
-# define SER_PAGE_PROG 0x02
-# define SER_SECT_ERASE 0xD8
-# define SER_BULK_ERASE 0xC7
-# define SER_DEEP_PWRDN 0xB9
-# define SER_RES 0xAB
#endif
-
#endif
+#define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */
+#define CFG_FLASH_CHECKSUM
+
/*
* This is setting for JFFS2 support in u-boot.
* NOTE: Enable CONFIG_CMD_JFFS2 for JFFS2 support.
*/
+#ifdef CONFIG_CMD_JFFS2
+#ifdef CF_STMICRO_BOOT
+# define CONFIG_JFFS2_DEV "nor1"
+# define CONFIG_JFFS2_PART_SIZE 0x01000000
+# define CONFIG_JFFS2_PART_OFFSET (CFG_FLASH2_BASE + 0x500000)
+#endif
#ifdef CFG_ATMEL_BOOT
# define CONFIG_JFFS2_DEV "nor1"
# define CONFIG_JFFS2_PART_SIZE 0x01000000
# define CONFIG_JFFS2_PART_OFFSET (CFG_FLASH1_BASE + 0x500000)
-#else
+#endif
+#ifdef CFG_INTEL_BOOT
# define CONFIG_JFFS2_DEV "nor0"
# define CONFIG_JFFS2_PART_SIZE (0x01000000 - 0x500000)
# define CONFIG_JFFS2_PART_OFFSET (CFG_FLASH0_BASE + 0x500000)
#endif
+#endif
/*-----------------------------------------------------------------------
* Cache Configuration
* CS5 - Available
*/
-#ifdef CFG_ATMEL_BOOT
+#if defined(CFG_ATMEL_BOOT) || defined(CFG_STMICRO_BOOT)
/* Atmel Flash */
#define CFG_CS0_BASE 0x04000000
#define CFG_CS0_MASK 0x00070001
#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
# define CFG_FLASH_BASE (CFG_CS0_BASE)
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
# define CFG_MAX_FLASH_SECT 137 /* max number of sectors on one chip */
# define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */
#define CFG_FLASH_CFI
#ifdef CFG_FLASH_CFI
# define CFG_FLASH_BASE (CFG_CS0_BASE)
-# define CFG_FLASH_CFI_DRIVER 1
+# define CONFIG_FLASH_CFI_DRIVER 1
# define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
# define CFG_MAX_FLASH_SECT 137 /* max number of sectors on one chip */
# define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */
#endif
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_HUSH_PARSER
#define CFG_PROMPT_HUSH_PS2 "> "
#define CFG_IMMR 0xE0000000
+#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+#define CONFIG_DEFAULT_IMMR CFG_IMMR
+#endif
+
#define CFG_MEMTEST_START 0x00001000
#define CFG_MEMTEST_END 0x07f00000
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFE000000 /* start of FLASH */
#define CFG_FLASH_SIZE 8 /* flash size in MB */
#define CFG_FLASH_EMPTY_INFO /* display empty sectors */
#define CFG_FLASH_USE_BUFFER_WRITE /* buffer up multiple bytes */
-#define CFG_BR0_PRELIM (CFG_FLASH_BASE | /* flash Base address */ \
+#define CFG_NOR_BR_PRELIM (CFG_FLASH_BASE | /* flash Base address */ \
(2 << BR_PS_SHIFT) | /* 16 bit port size */ \
BR_V) /* valid */
-#define CFG_OR0_PRELIM ( 0xFF000000 /* 16 MByte */ \
+#define CFG_NOR_OR_PRELIM ( 0xFF800000 /* 8 MByte */ \
| OR_GPCM_XACS \
| OR_GPCM_SCY_9 \
| OR_GPCM_EHTR \
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#if (CFG_MONITOR_BASE < CFG_FLASH_BASE)
+#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) && !defined(CONFIG_NAND_SPL)
#define CFG_RAMBOOT
#endif
#define CFG_LBC_MRTPR 0x20000000 /*TODO */ /* LB refresh timer prescal, 266MHz/32 */
/* drivers/mtd/nand/nand.c */
-#define CFG_NAND_BASE 0xE2800000 /* 0xF0000000 */
+#ifdef CONFIG_NAND_SPL
+#define CFG_NAND_BASE 0xFFF00000
+#else
+#define CFG_NAND_BASE 0xE2800000
+#endif
+
#define CFG_MAX_NAND_DEVICE 1
#define NAND_MAX_CHIPS 1
#define CONFIG_MTD_NAND_VERIFY_WRITE
+#define CONFIG_CMD_NAND 1
+#define CONFIG_NAND_FSL_ELBC 1
+#define CFG_NAND_BLOCK_SIZE 16384
+
+#define CFG_NAND_U_BOOT_SIZE (512 << 10)
+#define CFG_NAND_U_BOOT_DST 0x00100000
+#define CFG_NAND_U_BOOT_START 0x00100100
+#define CFG_NAND_U_BOOT_OFFS 16384
+#define CFG_NAND_U_BOOT_RELOC 0x00010000
-#define CFG_BR1_PRELIM ( CFG_NAND_BASE \
+#define CFG_NAND_BR_PRELIM ( CFG_NAND_BASE \
| (2<<BR_DECC_SHIFT) /* Use HW ECC */ \
| BR_PS_8 /* Port Size = 8 bit */ \
| BR_MS_FCM /* MSEL = FCM */ \
| BR_V ) /* valid */
-#define CFG_OR1_PRELIM ( 0xFFFF8000 /* length 32K */ \
+#define CFG_NAND_OR_PRELIM ( 0xFFFF8000 /* length 32K */ \
| OR_FCM_CSCT \
| OR_FCM_CST \
| OR_FCM_CHT \
| OR_FCM_TRLX \
| OR_FCM_EHTR )
/* 0xFFFF8396 */
+
+#ifdef CONFIG_NAND_U_BOOT
+#define CFG_BR0_PRELIM CFG_NAND_BR_PRELIM
+#define CFG_OR0_PRELIM CFG_NAND_OR_PRELIM
+#define CFG_BR1_PRELIM CFG_NOR_BR_PRELIM
+#define CFG_OR1_PRELIM CFG_NOR_OR_PRELIM
+#else
+#define CFG_BR0_PRELIM CFG_NOR_BR_PRELIM
+#define CFG_OR0_PRELIM CFG_NOR_OR_PRELIM
+#define CFG_BR1_PRELIM CFG_NAND_BR_PRELIM
+#define CFG_OR1_PRELIM CFG_NAND_OR_PRELIM
+#endif
+
#define CFG_LBLAWBAR1_PRELIM CFG_NAND_BASE
#define CFG_LBLAWAR1_PRELIM 0x8000000E /* 32KB */
+#define CFG_NAND_LBLAWBAR_PRELIM CFG_LBLAWBAR1_PRELIM
+#define CFG_NAND_LBLAWAR_PRELIM CFG_LBLAWAR1_PRELIM
+
/* local bus read write buffer mapping */
#define CFG_BR3_PRELIM 0xFA000801 /* map at 0xFA000000 */
#define CFG_OR3_PRELIM 0xFFFF8FF7 /* 32kB */
#define CFG_NS16550
#define CFG_NS16550_SERIAL
#define CFG_NS16550_REG_SIZE 1
-#define CFG_NS16550_CLK get_bus_freq(0)
#define CFG_BAUDRATE_TABLE \
{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 115200}
/*
* Environment
*/
-#ifndef CFG_RAMBOOT
+#if defined(CONFIG_NAND_U_BOOT)
+ #define CFG_ENV_IS_IN_NAND 1
+ #define CFG_ENV_OFFSET (512 * 1024)
+ #define CFG_ENV_SECT_SIZE CFG_NAND_BLOCK_SIZE
+ #define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
+ #define CFG_ENV_SIZE_REDUND CFG_ENV_SIZE
+ #define CFG_ENV_RANGE (CFG_ENV_SECT_SIZE * 4)
+ #define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET + CFG_ENV_RANGE)
+#elif !defined(CFG_RAMBOOT)
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_ADDR (CFG_MONITOR_BASE + CFG_MONITOR_LEN)
#define CFG_ENV_SECT_SIZE 0x10000 /* 64K(one sector) for env */
#define CONFIG_CMD_DATE
#define CONFIG_CMD_PCI
-#if defined(CFG_RAMBOOT)
+#if defined(CFG_RAMBOOT) && !defined(CONFIG_NAND_U_BOOT)
#undef CONFIG_CMD_ENV
#undef CONFIG_CMD_LOADS
#endif
HRCWL_CSB_TO_CLKIN_2X1 |\
HRCWL_CORE_TO_CSB_2X1)
+#define CFG_NS16550_CLK (CONFIG_83XX_CLKIN * 2)
+
#elif defined(CFG_33MHZ)
/* 33MHz IN, 165MHz CSB, 330 DDR, 330 CORE */
HRCWL_CSB_TO_CLKIN_5X1 |\
HRCWL_CORE_TO_CSB_2X1)
+#define CFG_NS16550_CLK (CONFIG_83XX_CLKIN * 5)
+
#endif
-/* 0xa0606c00 */
-#define CFG_HRCW_HIGH (\
+#define CFG_HRCW_HIGH_BASE (\
HRCWH_PCI_HOST |\
HRCWH_PCI1_ARBITER_ENABLE |\
HRCWH_CORE_ENABLE |\
- HRCWH_FROM_0X00000100 |\
HRCWH_BOOTSEQ_DISABLE |\
HRCWH_SW_WATCHDOG_DISABLE |\
- HRCWH_ROM_LOC_LOCAL_16BIT |\
- HRCWH_RL_EXT_LEGACY |\
HRCWH_TSEC1M_IN_RGMII |\
HRCWH_TSEC2M_IN_RGMII |\
- HRCWH_BIG_ENDIAN |\
- HRCWH_LALE_NORMAL)
+ HRCWH_BIG_ENDIAN)
+
+#ifdef CONFIG_NAND_SPL
+#define CFG_HRCW_HIGH (CFG_HRCW_HIGH_BASE |\
+ HRCWH_FROM_0XFFF00100 |\
+ HRCWH_ROM_LOC_NAND_SP_8BIT |\
+ HRCWH_RL_EXT_NAND)
+#else
+#define CFG_HRCW_HIGH (CFG_HRCW_HIGH_BASE |\
+ HRCWH_FROM_0X00000100 |\
+ HRCWH_ROM_LOC_LOCAL_16BIT |\
+ HRCWH_RL_EXT_LEGACY)
+#endif
/* System IO Config */
#define CFG_SICRH (SICRH_TSOBI1 | SICRH_TSOBI2) /* RGMII */
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
#define CFG_FLASH_BASE 0xFE000000 /* FLASH base address */
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFE000000 /* FLASH base address */
#define CFG_FLASH_SIZE 16 /* FLASH size is 16M */
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFE000000 /* FLASH base address */
#define CFG_FLASH_SIZE 16 /* FLASH size is 16M */
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFE000000 /* start of FLASH */
#define CFG_FLASH_SIZE 32 /* max flash size in MB */
/* #define CFG_FLASH_USE_BUFFER_WRITE */
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFE000000 /* start of FLASH */
#define CFG_FLASH_EMPTY_INFO
#define CFG_MAX_FLASH_SECT 135 /* 127 64KB sectors + 8 8KB sectors per device */
#define CFG_ENV_SIZE 0x2000
#else
#define CFG_NO_FLASH /* Flash is not usable now */
- #undef CFG_FLASH_CFI_DRIVER
+ #undef CONFIG_FLASH_CFI_DRIVER
#define CFG_ENV_IS_NOWHERE /* Store ENV in memory only */
#define CFG_ENV_ADDR (CFG_MONITOR_BASE - 0x1000)
#define CFG_ENV_SIZE 0x2000
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFE000000 /* FLASH base address */
#define CFG_FLASH_SIZE 32 /* max FLASH size is 32M */
#define CONFIG_FLASH_SHOW_PROGRESS 45 /* count down from 45/5: 9..1 */
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_SIZE 8 /* max FLASH size is 32M */
#define CFG_FLASH_PROTECTION 1 /* Use intel Flash protection. */
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFE000000 /* FLASH base address */
#define CFG_FLASH_SIZE 32 /* max FLASH size is 32M */
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFE000000 /* FLASH base address */
#define CFG_FLASH_SIZE 8 /* max FLASH size is 32M */
#undef CFG_RAMBOOT
#endif
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#undef CFG_RAMBOOT
#endif
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CONFIG_MISC_INIT_R 1
#define CFG_CACHELINE_SIZE 32
-#ifdef (CONFIG_CMD_KGDB)
+#ifdef CONFIG_CMD_KGDB
#define CFG_CACHELINE_SHIFT 5
#endif
*/
#undef CONFIG_FLASH_16BIT
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI_AMD_RESET 1
#define CFG_FLASH_EMPTY_INFO
#define CFG_PROMPT_HUSH_PS2 "> "
#undef CFG_LONGHELP
#define CFG_PROMPT "=> "
-#ifdef (CONFIG_CMD_KGDB)
+#ifdef CONFIG_CMD_KGDB
#define CFG_CBSIZE 1024
#else
#define CFG_CBSIZE 256
/* Flash */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
#define CFG_FLASH_BASE 0xFF800000
#define CFG_BAUDRATE_TABLE { 115200 } /* List of legal baudrate settings for this board */
/* SCIF */
-#define CFG_SCIF_CONSOLE 1
+#define CONFIG_SCIF_CONSOLE 1
#define CONFIG_CONS_SCIF0 1
#undef CFG_CONSOLE_INFO_QUIET /* Suppress display of console
information at boot */
/* FLASH */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#undef CFG_FLASH_QUIET_TEST
/* print 'E' for empty sector on flinfo */
#define CFG_FLASH_EMPTY_INFO
/****************************************************************/
/* NAND */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_NAND_BASE NAND_BASE
#define CONFIG_MTD_NAND_ECC_JFFS2
#define CONFIG_MTD_NAND_VERIFY_WRITE
/****************************************************************/
/* NAND */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_NAND_BASE NAND_BASE
#define CONFIG_MTD_NAND_VERIFY_WRITE
#define CONFIG_MTD_NAND_UNSAFE
/****************************************************************/
/* NAND */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_NAND_BASE NAND_BASE
#define CONFIG_MTD_NAND_ECC_JFFS2
#define CONFIG_MTD_NAND_VERIFY_WRITE
/*****************************************************************************/
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#if defined(CONFIG_NETVIA_VERSION) && CONFIG_NETVIA_VERSION >= 2
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/NSCU/uImage\0" \
+ "hostname=NSCU\0" \
+ "bootfile=${hostname}/uImage\0" \
"kernel_addr=40080000\0" \
"ramdisk_addr=40180000\0" \
+ "u-boot=${hostname}/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "=> " /* Monitor Command Prompt */
-#if 0
+#define CONFIG_CMDLINE_EDITING 1 /* add command line history
+*/
#define CFG_HUSH_PARSER 1 /* use "hush" command parser */
-#endif
#ifdef CFG_HUSH_PARSER
#define CFG_PROMPT_HUSH_PS2 "> "
#endif
/*-----------------------------------------------------------------------
* FLASH organization
*/
-#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
-#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */
-#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
-#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */
+/* use CFI flash driver */
+#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
+#define CFG_FLASH_EMPTY_INFO
+#define CFG_FLASH_USE_BUFFER_WRITE 1
+#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
+#define CFG_MAX_FLASH_SECT 71 /* max number of sectors on one chip */
#define CFG_ENV_IS_IN_FLASH 1
-#define CFG_ENV_OFFSET 0x40000 /* Offset of Environment Sector */
-#define CFG_ENV_SIZE 0x08000 /* Total Size of Environment Sector */
-#define CFG_ENV_SECT_SIZE 0x20000 /* Total Size of Environment Sector */
+#define CFG_ENV_OFFSET 0x8000 /* Offset of Environment Sector */
+#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */
/* Address and size of Redundant Environment Sector */
-#define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET+CFG_ENV_SECT_SIZE)
+#define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET+CFG_ENV_SIZE)
#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE)
+#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
+
/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CONFIG_PCI 1
#define CONFIG_PCI_PNP 1 /* PCI plug-and-play */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
/*
* Miscellaneous configurable options
#define CONFIG_PCI 1
#define CONFIG_PCI_PNP 1 /* PCI plug-and-play */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
/*
* Miscellaneous configurable options
#define CONFIG_CMD_BSP
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_HUSH_PARSER
#define CFG_PROMPT_HUSH_PS2 "> "
#if !defined(CONFIG_BOOT_ROM)
/* DoC requires legacy NAND for now */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#endif
#endif
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
/*
* Disk-On-Chip configuration
/*
* Disk-On-Chip configuration
*/
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_DOC_SHORT_TIMEOUT
#define CFG_MAX_DOC_DEVICE 1 /* Max number of DOC devices */
#undef CFG_RAMBOOT
#endif
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#undef CFG_RAMBOOT
#endif
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_INCREMENT 0x01000000
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_PROTECTION 1 /* don't use hardware protection */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_BANKS 2 /* max num of flash banks */
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_BASE 0xFE000000
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_MAX_FLASH_BANKS 1 /* max num of flash banks */
#define CFG_MAX_FLASH_SECT 256 /* max num of sects on one chip */
*/
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#if 0
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_FLASH_PROTECTION /* use hardware protection */
* FLASH driver setup
*/
#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/mtd/cfi_flash.c */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use drivers/mtd/cfi_flash.c */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* Use buffered writes (~10x faster) */
#define CFG_FLASH_PROTECTION 1 /* Use hardware sector protection */
*/
/* NAND flash support */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CONFIG_MTD_NAND_ECC_JFFS2
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
*/
-#define CFG_WINBOND_83C553 1 /*has a winbond bridge */
+#define CONFIG_WINBOND_83C553 1 /*has a winbond bridge */
#define CFG_USE_WINBOND_IDE 0 /*use winbond 83c553 internal IDE ctrlr */
#define CFG_WINBOND_ISA_CFG_ADDR 0x80005800 /*pci-isa bridge config addr */
#define CFG_WINBOND_IDE_CFG_ADDR 0x80005900 /*ide config addr */
/*
* NS87308 Configuration
*/
-#define CFG_NS87308 /* Nat Semi super-io controller on ISA bus */
+#define CONFIG_NS87308 /* Nat Semi super-io controller on ISA bus */
#define CFG_NS87308_BADDR_10 1
*/
-#define CFG_WINBOND_83C553 1 /*has a winbond bridge */
+#define CONFIG_WINBOND_83C553 1 /*has a winbond bridge */
#define CFG_USE_WINBOND_IDE 0 /*use winbond 83c553 internal IDE ctrlr */
#define CFG_WINBOND_ISA_CFG_ADDR 0x80005800 /*pci-isa bridge config addr */
#define CFG_WINBOND_IDE_CFG_ADDR 0x80005900 /*ide config addr */
/*
* NS87308 Configuration
*/
-#define CFG_NS87308 /* Nat Semi super-io controller on ISA bus */
+#define CONFIG_NS87308 /* Nat Semi super-io controller on ISA bus */
#define CFG_NS87308_BADDR_10 1
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_BOOTCS_START }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_SIZE 0x04000000 /* 64 MByte */
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#else
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_BOOTCS_START }
#define CFG_MAX_FLASH_BANKS 1 /* max num of flash banks
(= chip selects) */
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
#define CONFIG_TQM823L 1 /* ...on a TQM8xxL module */
#ifdef CONFIG_LCD /* with LCD controller ? */
+#define CONFIG_LCD_LOGO 1 /* print our logo on the LCD */
+#define CONFIG_LCD_INFO 1 /* ... and some board info */
#define CONFIG_SPLASH_SCREEN /* ... with splashscreen support*/
#endif
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM823L/uImage\0" \
+ "hostname=TQM823L\0" \
+ "bootfile=TQM823L/uImage\0" \
"fdt_addr=40040000\0" \
"kernel_addr=40060000\0" \
"ramdisk_addr=40200000\0" \
+ "u-boot=TQM823L/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
#endif
+#define CONFIG_NETCONSOLE
+
/*
* Miscellaneous configurable options
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
-#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
+ "128k(dtb)," \
+ "1664k(kernel)," \
+ "2m(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM823M/uImage\0" \
+ "hostname=TQM823M\0" \
+ "bootfile=TQM823M/uImage\0" \
"fdt_addr=40080000\0" \
"kernel_addr=400A0000\0" \
"ramdisk_addr=40280000\0" \
+ "u-boot=TQM823M/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
+ "128k(dtb)," \
+ "1920k(kernel)," \
+ "5632(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
#define CFG_MAX_FLASH_SECT 128 /* max num of sects on one chip */
#define CFG_FLASH_CFI /* flash is CFI compat. */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver*/
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver*/
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector */
#define CFG_FLASH_QUIET_TEST 1 /* don't warn upon unknown flash*/
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#undef CFG_FLASH_CHECKSUM
#define CFG_FLASH_BASE 0x80000000 /* start of FLASH */
#define CFG_FLASH_SIZE 8 /* FLASH size in MB */
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM850L/uImage\0" \
+ "hostname=TQM850L\0" \
+ "bootfile=TQM850L/uImage\0" \
"fdt_addr=40040000\0" \
"kernel_addr=40060000\0" \
"ramdisk_addr=40200000\0" \
+ "u-boot=TQM850L/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
/*
* Miscellaneous configurable options
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
-#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
+ "128k(dtb)," \
+ "1664k(kernel)," \
+ "2m(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM850M/uImage\0" \
+ "hostname=TQM850M\0" \
+ "bootfile=TQM850M/uImage\0" \
"fdt_addr=40080000\0" \
"kernel_addr=400A0000\0" \
"ramdisk_addr=40280000\0" \
+ "u-boot=TQM850M/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
+ "128k(dtb)," \
+ "1920k(kernel)," \
+ "5632(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM855L/uImage\0" \
+ "hostname=TQM855L\0" \
+ "bootfile=TQM855L/uImage\0" \
"fdt_addr=40040000\0" \
"kernel_addr=40060000\0" \
"ramdisk_addr=40200000\0" \
+ "u-boot=TQM855L/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
-#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
+ "128k(dtb)," \
+ "1664k(kernel)," \
+ "2m(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM855M/uImage\0" \
+ "hostname=TQM855M\0" \
+ "bootfile=TQM855M/uImage\0" \
"fdt_addr=40080000\0" \
"kernel_addr=400A0000\0" \
"ramdisk_addr=40280000\0" \
+ "u-boot=TQM855M/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_EEPROM
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
+ "128k(dtb)," \
+ "1920k(kernel)," \
+ "5632(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
#endif /* CONFIG_TQM_BIGFLASH */
#define CFG_FLASH_CFI /* flash is CFI compat. */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector */
#define CFG_FLASH_QUIET_TEST 1 /* don't warn upon unknown flash*/
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* speed up output to Flash */
/* NAND FLASH */
#ifdef CONFIG_NAND
-#undef CFG_NAND_LEGACY
+#undef CONFIG_NAND_LEGACY
#define CONFIG_NAND_FSL_UPM 1
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM860L/uImage\0" \
+ "hostname=TQM860L\0" \
+ "bootfile=TQM860L/uImage\0" \
"fdt_addr=40040000\0" \
"kernel_addr=40060000\0" \
"ramdisk_addr=40200000\0" \
+ "u-boot=TQM860L/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
-#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
+ "128k(dtb)," \
+ "1664k(kernel)," \
+ "2m(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM860M/uImage\0" \
+ "hostname=TQM860M\0" \
+ "bootfile=TQM860M/uImage\0" \
"fdt_addr=400C0000\0" \
"kernel_addr=40100000\0" \
"ramdisk_addr=40280000\0" \
+ "u-boot=TQM860M/u-image.bin\0" \
"load=tftp 200000 ${u-boot}\0" \
- "update=protect off 40000000 +${filesize};" \
- "erase 40000000 +${filesize};" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
"cp.b 200000 40000000 ${filesize};" \
- "protect on 40000000 +${filesize}\0" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
+ "128k(dtb)," \
+ "1920k(kernel)," \
+ "5632(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
/*
- * (C) Copyright 2000-2005
+ * (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM862L/uImage\0" \
+ "hostname=TQM862L\0" \
+ "bootfile=TQM862L/uImage\0" \
"fdt_addr=40040000\0" \
"kernel_addr=40060000\0" \
"ramdisk_addr=40200000\0" \
+ "u-boot=TQM862L/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
-#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
+ "128k(dtb)," \
+ "1664k(kernel)," \
+ "2m(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM862M/uImage\0" \
+ "hostname=TQM862M\0" \
+ "bootfile=TQM862M/uImage\0" \
"fdt_addr=40080000\0" \
"kernel_addr=400A0000\0" \
"ramdisk_addr=40280000\0" \
+ "u-boot=TQM862M/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
+#define CONFIG_NETCONSOLE
+
+
/*
* Miscellaneous configurable options
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
+ "128k(dtb)," \
+ "1920k(kernel)," \
+ "5632(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM866M/uImage\0" \
+ "hostname=TQM866M\0" \
+ "bootfile=TQM866M/uImage\0" \
"fdt_addr=400C0000\0" \
"kernel_addr=40100000\0" \
"ramdisk_addr=40280000\0" \
+ "u-boot=TQM866M/u-image.bin\0" \
"load=tftp 200000 ${u-boot}\0" \
- "update=protect off 40000000 +${filesize};" \
- "erase 40000000 +${filesize};" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
"cp.b 200000 40000000 ${filesize};" \
- "protect on 40000000 +${filesize}\0" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_EEPROM
-#define CONFIG_CMD_I2C
+#define CONFIG_CMD_ELF
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
+#define CONFIG_CMD_SNTP
+
+
+#define CONFIG_NETCONSOLE
/*
*/
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxM-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxM-0:512k(u-boot)," \
+ "128k(dtb)," \
+ "1920k(kernel)," \
+ "5632(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
* Flash configuration
*/
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#if CONFIG_TOTAL5200_REV==2
# define CFG_MAX_FLASH_BANKS 3 /* max num of flash banks */
# define CFG_FLASH_BANKS_LIST { CFG_CS5_START, CFG_CS4_START, CFG_BOOTCS_START }
*/
#if defined(CONFIG_CMD_NAND)
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define CFG_FLSIMM_BASE 0xFF000000
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_MAX_FLASH_BANKS 2 /* max num of flash banks */
#define CFG_MAX_FLASH_SECT 32 /* max num of sects on one chip */
*----------------------------------------------------------------------*/
#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST {CFG_FLASH_BASE}
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
/* Use common CFI driver */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
/* no byte writes on IXP4xx */
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
/* print 'E' for empty sector on flinfo */
/* Use common CFI driver */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
/* no byte writes on IXP4xx */
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
/* Use common CFI driver */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
/* no byte writes on IXP4xx */
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT
/* Use common CFI driver */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
/* board provides its own flash_init code */
#define CONFIG_FLASH_CFI_LEGACY 1
/* no byte writes on IXP4xx */
*/
#undef CONFIG_BKUP_FLASH
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#ifdef CONFIG_BKUP_FLASH
#define CFG_FLASH_BASE 0xFF800000 /* start of FLASH */
#define CFG_FLASH_SIZE 0x00800000 /* max flash size in bytes */
#define CONFIG_PHY_ADDR 0x1
#define CONFIG_MII 1 /* MII PHY management */
#define CONFIG_FEC_AN_TIMEOUT 1
+#define CONFIG_HAS_ETH0
/*
* Configure on-board RTC
#define CONFIG_OF_LIBFDT 1
#define CONFIG_OF_BOARD_SETUP 1
+#define CONFIG_OF_SUPPORT_OLD_DEVICE_TREES 1
#define OF_CPU "PowerPC,5121@0"
-#define OF_SOC "soc@80000000"
-#define OF_SOC_OLD "soc5121@80000000"
+#define OF_SOC_COMPAT "fsl,mpc5121-immr"
#define OF_TBCLK (bd->bi_busfreq / 4)
#define OF_STDOUT_PATH "/soc@80000000/serial@11300"
/* use CFI flash driver if no module variant is spezified */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_BOOTCS_START }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_SIZE 0x04000000 /* 64 MByte */
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI 1 /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use common CFI driver */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_MAX_FLASH_SECT 512 /* max number of sectors on one chip */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
* CFI FLASH driver setup
*/
# define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-# define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */
+# define CONFIG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */
/* #define CFG_FLASH_USE_BUFFER_WRITE 1 */ /* Use buffered writes (~10x faster) */
# define CFG_FLASH_PROTECTION 1 /* Use h/w sector protection*/
#define CFG_FLASH_BASE PHYS_FLASH_1
#define CFG_FLASH_SIZE PHYS_FLASH_SIZE
#define CFG_FLASH_CFI 1 /* flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_BANKS 1 /* max # of memory banks */
#define CFG_FLASH_INCREMENT 0 /* there is only one bank */
/* NOR flash */
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define PHYS_FLASH_1 0x10000000
#define CFG_FLASH_BASE PHYS_FLASH_1
#define CFG_MAX_FLASH_SECT 256
#define CONFIG_CMD_MII
#define CONFIG_CMD_NAND
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define CFG_NO_FLASH 1
#else
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define PHYS_FLASH_1 0x10000000
#define CFG_FLASH_BASE PHYS_FLASH_1
#define CFG_MAX_FLASH_SECT 256
#define CONFIG_NR_DRAM_BANKS 1
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_BASE 0x00000000
#define CFG_FLASH_SIZE 0x800000
/* External flash on STK1000 */
#if 0
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#endif
#define CFG_FLASH_BASE 0x00000000
/* External flash on STK1000 */
#if 0
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#endif
#define CFG_FLASH_BASE 0x00000000
/* External flash on STK1000 */
#if 0
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#endif
#define CFG_FLASH_BASE 0x00000000
/* External flash on STK1000 */
#if 0
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#endif
#define CFG_FLASH_BASE 0x00000000
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_CFI_AMD_RESET
#define CFG_FLASH_BASE 0x20000000
#define CFG_FLASH_BASE 0x20000000
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_PROTECTION
#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 71 /* some have 67 sectors (M29W320DB), but newer have 71 (M29W320EB) */
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_CFI_AMD_RESET
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_FLASH_BASE 0x20000000
#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */
#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_CFI_AMD_RESET 1 /* Use AMD (Spansion) reset cmd */
#define CFG_FLASH_BANKS_LIST {CFG_FLASH_BASE}
* Flash configuration
*/
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_BASE 0xfc000000
/* we need these despite using CFI */
#define CFG_MAX_FLASH_BANKS 1 /* max num of flash banks */
*
*/
#define CFG_FLASH_CFI 1 /* flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_BANKS 1 /* max # of memory banks */
#define CFG_FLASH_INCREMENT 0 /* there is only one bank */
*
*/
#define CFG_FLASH_CFI 1 /* flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_BANKS 1 /* max # of memory banks */
#define CFG_FLASH_INCREMENT 0 /* there is only one bank */
#define PHYS_FLASH_SIZE 0x800000 /* 8 megs main flash */
#define CFG_FLASH_BASE PHYS_FLASH_1
#define CFG_FLASH_CFI 1 /* flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_BANKS 1 /* max # of memory banks */
#endif
#define CFG_ENV_IS_IN_FLASH
#undef CFG_NO_FLASH
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_MAX_FLASH_BANKS 1 /* max number of flash banks */
#define CFG_FLASH_SECT_SZ 0x10000 /* 64KB sect size AMD Flash */
#endif
#define CFG_ENV_IS_IN_FLASH
#undef CFG_NO_FLASH
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_MAX_FLASH_BANKS 1 /* max number of flash banks */
#define CFG_FLASH_SECT_SZ 0x20000 /* 128KB sect size AMD Flash */
#define CFG_FLASH_BANKS_LIST {PHYS_FLASH_1, PHYS_FLASH_2}
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
/* The following #defines are needed to get flash environment right */
#define CFG_MONITOR_BASE TEXT_BASE
/*
* NAND Flash
*/
-#undef CFG_NAND_LEGACY
+#undef CONFIG_NAND_LEGACY
#define CFG_NAND0_BASE 0x0 /* 0x43100040 */ /* 0x10000000 */
#undef CFG_NAND1_BASE
*/
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_MAX_FLASH_SECT 64 /* max number of sectors on one chip */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_FLASH_INCREMENT 0 /* there is only one bank */
#define CFG_FLASH_BASE 0xFF800000
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_MAX_FLASH_BANKS 1 /* max num of flash banks */
#define CFG_MAX_FLASH_SECT 256 /* max num of sects on one chip */
*----------------------------------------------------------------------*/
#define CFG_FLASH_BASE 0xFC000000
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_MAX_FLASH_BANKS 1 /* max num of flash banks */
#define CFG_MAX_FLASH_SECT 512 /* max num of sects on one chip */
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector in flinfo */
#else
/* REVISIT: This doesn't work on ADS GCPlus just yet: */
#define CFG_FLASH_CFI 1 /* flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* use common cfi driver */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_BANKS 1 /* max # of memory banks */
#define CFG_FLASH_INCREMENT 0 /* there is only one bank */
/*** CFI CONFIG ***/
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
/* Bypass cache when reading regs from flash memory */
#define CFG_FLASH_CFI_BYPASS_READ
/*** CFI CONFIG ***/
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
/* Bypass cache when reading regs from flash memory */
#define CFG_FLASH_CFI_BYPASS_READ
/*** CFI CONFIG ***/
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
/* Bypass cache when reading regs from flash memory */
#define CFG_FLASH_CFI_BYPASS_READ
/*** CFI CONFIG ***/
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#endif
/*** CFI CONFIG ***/
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#endif
/* Use common CFI driver */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
/* board provides its own flash_init code */
#define CONFIG_FLASH_CFI_LEGACY 1
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
/* Use common CFI driver */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
/* board provides its own flash_init code */
#define CONFIG_FLASH_CFI_LEGACY 1
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */
#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_CFI_AMD_RESET
* CFI FLASH driver setup
*/
#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* Use buffered writes (~10x faster) */
#define CFG_FLASH_PROTECTION 1 /* Use hardware sector protection */
* CFI FLASH driver setup
*/
#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* Use buffered writes (~10x faster) */
#define CFG_FLASH_PROTECTION 1 /* Use hardware sector protection */
* Flash configuration
*/
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_BASE 0xffe00000
#define CFG_FLASH_SIZE 0x00200000
#define CFG_MAX_FLASH_BANKS 1 /* max num of memory banks */
#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_BANKS 1 /* max num of flash banks */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
#include "amcc-common.h"
#define CONFIG_BOARD_EARLY_INIT_F 1 /* Call board_pre_init */
-#define CONFIG_MISC_INIT_F 1 /* Use misc_init_f() */
#undef CONFIG_SHOW_BOOT_PROGRESS
/*-----------------------------------------------------------------------
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_MAXARGS 16 /* max number of command args */
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#ifndef __ASSEMBLY__
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST {CFG_FLASH_BASE}
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_SDRAM0_MB1CF SDRAM_RXBAS_SDBE_DISABLE
#define CFG_SDRAM0_MB2CF SDRAM_RXBAS_SDBE_DISABLE
#define CFG_SDRAM0_MB3CF SDRAM_RXBAS_SDBE_DISABLE
-#define CFG_SDRAM0_MCOPT1 0x04322000
+#define CFG_SDRAM0_MCOPT1 (SDRAM_MCOPT1_PMU_OPEN | \
+ SDRAM_MCOPT1_8_BANKS | \
+ SDRAM_MCOPT1_DDR2_TYPE | \
+ SDRAM_MCOPT1_QDEP | \
+ SDRAM_MCOPT1_DCOO_DISABLED)
#define CFG_SDRAM0_MCOPT2 0x00000000
-#define CFG_SDRAM0_MODT0 0x01800000
+#define CFG_SDRAM0_MODT0 (SDRAM_MODT_EB0W_ENABLE | \
+ SDRAM_MODT_EB0R_ENABLE)
#define CFG_SDRAM0_MODT1 0x00000000
-#define CFG_SDRAM0_CODT 0x0080f837
-#define CFG_SDRAM0_RTR 0x06180000
-#define CFG_SDRAM0_INITPLR0 0xa8380000
-#define CFG_SDRAM0_INITPLR1 0x81900400
-#define CFG_SDRAM0_INITPLR2 0x81020000
-#define CFG_SDRAM0_INITPLR3 0x81030000
-#define CFG_SDRAM0_INITPLR4 0x81010404
-#define CFG_SDRAM0_INITPLR5 0x81000542
-#define CFG_SDRAM0_INITPLR6 0x81900400
-#define CFG_SDRAM0_INITPLR7 0x8D080000
-#define CFG_SDRAM0_INITPLR8 0x8D080000
-#define CFG_SDRAM0_INITPLR9 0x8D080000
-#define CFG_SDRAM0_INITPLR10 0x8D080000
-#define CFG_SDRAM0_INITPLR11 0x81000442
-#define CFG_SDRAM0_INITPLR12 0x81010780
-#define CFG_SDRAM0_INITPLR13 0x81010400
-#define CFG_SDRAM0_INITPLR14 0x00000000
-#define CFG_SDRAM0_INITPLR15 0x00000000
-#define CFG_SDRAM0_RQDC 0x80000038
-#define CFG_SDRAM0_RFDC 0x00000209
-#define CFG_SDRAM0_RDCC 0x40000000
-#define CFG_SDRAM0_DLCR 0x030000a5
-#define CFG_SDRAM0_CLKTR 0x80000000
+#define CFG_SDRAM0_CODT (SDRAM_CODT_RK0R_ON | \
+ SDRAM_CODT_CKLZ_36OHM | \
+ SDRAM_CODT_DQS_1_8_V_DDR2 | \
+ SDRAM_CODT_IO_NMODE)
+#define CFG_SDRAM0_RTR SDRAM_RTR_RINT_ENCODE(1560)
+#define CFG_SDRAM0_INITPLR0 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(80) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_NOP))
+#define CFG_SDRAM0_INITPLR1 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(3) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_PRECHARGE) | \
+ SDRAM_INITPLR_IBA_ENCODE(JEDEC_BA_MR) | \
+ SDRAM_INITPLR_IMA_ENCODE(JEDEC_MA_PRECHARGE_ALL))
+#define CFG_SDRAM0_INITPLR2 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(2) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_EMR) | \
+ SDRAM_INITPLR_IBA_ENCODE(JEDEC_BA_EMR2) | \
+ SDRAM_INITPLR_IMA_ENCODE(JEDEC_MA_EMR2_TEMP_COMMERCIAL))
+#define CFG_SDRAM0_INITPLR3 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(2) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_EMR) | \
+ SDRAM_INITPLR_IBA_ENCODE(JEDEC_BA_EMR3) | \
+ SDRAM_INITPLR_IMA_ENCODE(0))
+#define CFG_SDRAM0_INITPLR4 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(2) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_EMR) | \
+ SDRAM_INITPLR_IBA_ENCODE(JEDEC_BA_EMR) | \
+ SDRAM_INITPLR_IMA_ENCODE(JEDEC_MA_EMR_DQS_DISABLE | \
+ JEDEC_MA_EMR_RTT_75OHM))
+#define CFG_SDRAM0_INITPLR5 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(2) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_EMR) | \
+ SDRAM_INITPLR_IBA_ENCODE(JEDEC_BA_MR) | \
+ SDRAM_INITPLR_IMA_ENCODE(JEDEC_MA_MR_WR_DDR2_3_CYC | \
+ JEDEC_MA_MR_CL_DDR2_4_0_CLK | \
+ JEDEC_MA_MR_BLEN_4 | \
+ JEDEC_MA_MR_DLL_RESET))
+#define CFG_SDRAM0_INITPLR6 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(3) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_PRECHARGE) | \
+ SDRAM_INITPLR_IBA_ENCODE(0x0) | \
+ SDRAM_INITPLR_IMA_ENCODE(JEDEC_MA_PRECHARGE_ALL))
+#define CFG_SDRAM0_INITPLR7 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(26) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_REFRESH))
+#define CFG_SDRAM0_INITPLR8 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(26) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_REFRESH))
+#define CFG_SDRAM0_INITPLR9 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(26) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_REFRESH))
+#define CFG_SDRAM0_INITPLR10 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(26) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_REFRESH))
+#define CFG_SDRAM0_INITPLR11 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(2) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_EMR) | \
+ SDRAM_INITPLR_IBA_ENCODE(JEDEC_BA_MR) | \
+ SDRAM_INITPLR_IMA_ENCODE(JEDEC_MA_MR_WR_DDR2_3_CYC | \
+ JEDEC_MA_MR_CL_DDR2_4_0_CLK | \
+ JEDEC_MA_MR_BLEN_4))
+#define CFG_SDRAM0_INITPLR12 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(2) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_EMR) | \
+ SDRAM_INITPLR_IBA_ENCODE(JEDEC_BA_EMR) | \
+ SDRAM_INITPLR_IMA_ENCODE(JEDEC_MA_EMR_OCD_ENTER | \
+ JEDEC_MA_EMR_RDQS_DISABLE | \
+ JEDEC_MA_EMR_DQS_DISABLE | \
+ JEDEC_MA_EMR_RTT_DISABLED | \
+ JEDEC_MA_EMR_ODS_NORMAL))
+#define CFG_SDRAM0_INITPLR13 (SDRAM_INITPLR_ENABLE | \
+ SDRAM_INITPLR_IMWT_ENCODE(2) | \
+ SDRAM_INITPLR_ICMD_ENCODE(JEDEC_CMD_EMR) | \
+ SDRAM_INITPLR_IBA_ENCODE(JEDEC_BA_EMR) | \
+ SDRAM_INITPLR_IMA_ENCODE(JEDEC_MA_EMR_OCD_EXIT | \
+ JEDEC_MA_EMR_RDQS_DISABLE | \
+ JEDEC_MA_EMR_DQS_DISABLE | \
+ JEDEC_MA_EMR_RTT_DISABLED | \
+ JEDEC_MA_EMR_ODS_NORMAL))
+#define CFG_SDRAM0_INITPLR14 (SDRAM_INITPLR_DISABLE)
+#define CFG_SDRAM0_INITPLR15 (SDRAM_INITPLR_DISABLE)
+#define CFG_SDRAM0_RQDC (SDRAM_RQDC_RQDE_ENABLE | \
+ SDRAM_RQDC_RQFD_ENCODE(56))
+#define CFG_SDRAM0_RFDC SDRAM_RFDC_RFFD_ENCODE(521)
+#define CFG_SDRAM0_RDCC (SDRAM_RDCC_RDSS_T2)
+#define CFG_SDRAM0_DLCR (SDRAM_DLCR_DCLM_AUTO | \
+ SDRAM_DLCR_DLCS_CONT_DONE | \
+ SDRAM_DLCR_DLCV_ENCODE(165))
+#define CFG_SDRAM0_CLKTR (SDRAM_CLKTR_CLKP_180_DEG_ADV)
#define CFG_SDRAM0_WRDTR 0x00000000
-#define CFG_SDRAM0_SDTR1 0x80201000
-#define CFG_SDRAM0_SDTR2 0x32204232
-#define CFG_SDRAM0_SDTR3 0x080b0d1a
-#define CFG_SDRAM0_MMODE 0x00000442
-#define CFG_SDRAM0_MEMODE 0x00000404
+#define CFG_SDRAM0_SDTR1 (SDRAM_SDTR1_LDOF_2_CLK | \
+ SDRAM_SDTR1_RTW_2_CLK | \
+ SDRAM_SDTR1_RTRO_1_CLK)
+#define CFG_SDRAM0_SDTR2 (SDRAM_SDTR2_RCD_3_CLK | \
+ SDRAM_SDTR2_WTR_2_CLK | \
+ SDRAM_SDTR2_XSNR_32_CLK | \
+ SDRAM_SDTR2_WPC_4_CLK | \
+ SDRAM_SDTR2_RPC_2_CLK | \
+ SDRAM_SDTR2_RP_3_CLK | \
+ SDRAM_SDTR2_RRD_2_CLK)
+#define CFG_SDRAM0_SDTR3 (SDRAM_SDTR3_RAS_ENCODE(8) | \
+ SDRAM_SDTR3_RC_ENCODE(11) | \
+ SDRAM_SDTR3_XCS | \
+ SDRAM_SDTR3_RFC_ENCODE(26))
+#define CFG_SDRAM0_MMODE (SDRAM_MMODE_WR_DDR2_3_CYC | \
+ SDRAM_MMODE_DCL_DDR2_4_0_CLK | \
+ SDRAM_MMODE_BLEN_4)
+#define CFG_SDRAM0_MEMODE (SDRAM_MEMODE_DQS_DISABLE | \
+ SDRAM_MEMODE_RTT_75OHM)
/*-----------------------------------------------------------------------
* I2C
*----------------------------------------------------------------------*/
#define CONFIG_M88E1111_PHY 1
#define CONFIG_IBM_EMAC4_V4 1
+#define CONFIG_EMAC_PHY_MODE EMAC_PHY_MODE_RGMII_RGMII
#define CONFIG_PHY_ADDR 1 /* PHY address, See schematics */
#define CONFIG_PHY_RESET 1 /* reset phy upon startup */
* FLASH related
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CONFIG_FLASH_CFI_LEGACY /* Allow hard-coded config for FLASH0 */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH1_ADDR, CFG_FLASH0_ADDR }
#define CFG_BOOTMAPSZ (8 << 20)
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_USE_BUFFER_WRITE
#define CFG_FLASH_PROTECTION
#define CFG_FLASH_EMPTY_INFO
* FLASH organization
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#undef CFG_FLASH_PROTECTION
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH0 0xFC000000
#define CFG_FLASH1 0xF8000000
* Hardware drivers
*/
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_ENV_SECT_SIZE 0x20000
#define CFG_FLASH_USE_BUFFER_WRITE
#define CFG_FLASH_PROTECTION /*for Intel P30 Flash*/
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST {CFG_FLASH_BASE}
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
*----------------------------------------------------------------------*/
#define CONFIG_M88E1111_PHY 1
#define CONFIG_IBM_EMAC4_V4 1
+#define CONFIG_EMAC_PHY_MODE EMAC_PHY_MODE_RGMII_RGMII
#define CONFIG_PHY_ADDR 6 /* PHY address, See schematics */
#define CONFIG_PHY_RESET 1 /* reset phy upon startup */
#define CFG_FLASH_SIZE 0x04000000
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
/* Use common CFI driver */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
/* board provides its own flash_init code */
#define CONFIG_FLASH_CFI_LEGACY 1
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
#define CONFIG_ENV_OVERWRITE 1
#endif
-#define CFG_FLASH_CFI_DRIVER 1 /* Flash is CFI conformant */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Flash is CFI conformant */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
#define CFG_FLASH_PROTECTION 1 /* use hardware protection */
#if 0
#define CFG_FLASH_BASE 0xFE000000
#define CFG_FLASH_SIZE 32
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_MAX_FLASH_BANKS 2 /* max num of flash banks */
#define CFG_MAX_FLASH_SECT 512 /* max num of sects on one chip */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_FLASH_SIZE 32
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_MAX_FLASH_SECT 256 /* max num of sects on one chip */
#define CFG_FLASH_BASE XILINX_FLASH_START
#define CFG_FLASH_SIZE XILINX_FLASH_SIZE
#define CFG_FLASH_CFI 1
- #define CFG_FLASH_CFI_DRIVER 1
+ #define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_EMPTY_INFO 1 /* ?empty sector */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */
--- /dev/null
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+/*
+#define DEBUG
+#define ET_DEBUG
+*/
+ /*CPU*/
+#define CONFIG_XILINX_ML507 1
+#define CONFIG_XILINX_440 1
+#define CONFIG_440 1
+#define CONFIG_4xx 1
+#include "../board/xilinx/ml507/xparameters.h"
+
+/*Mem Map*/
+#define CFG_SDRAM_BASE 0x0
+#define CFG_SDRAM_SIZE_MB 256
+#define CFG_MONITOR_BASE TEXT_BASE
+#define CFG_MONITOR_LEN ( 192 * 1024 )
+#define CFG_MALLOC_LEN ( CFG_ENV_SIZE + 128 * 1024 )
+
+/*Uart*/
+#define CONFIG_XILINX_UARTLITE
+#define CONFIG_BAUDRATE XPAR_UARTLITE_0_BAUDRATE
+#define CFG_BAUDRATE_TABLE { XPAR_UARTLITE_0_BAUDRATE }
+#define CONFIG_SERIAL_BASE XPAR_UARTLITE_0_BASEADDR
+
+/*Cmd*/
+#include <config_cmd_default.h>
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DIAG
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_IRQ
+#define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_JFFS2
+#define CONFIG_JFFS2_CMDLINE
+#undef CONFIG_CMD_I2C
+#undef CONFIG_CMD_DTT
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_PING
+#undef CONFIG_CMD_DHCP
+#undef CONFIG_CMD_EEPROM
+#undef CONFIG_CMD_IMLS
+
+/*Env*/
+#define CFG_ENV_IS_IN_FLASH
+#define CFG_ENV_SIZE 0x20000
+#define CFG_ENV_SECT_SIZE 0x20000
+#define CFG_ENV_OFFSET 0x340000
+#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET)
+
+/*Misc*/
+#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */
+#define CFG_LONGHELP /* undef to save memory */
+#define CFG_PROMPT "board:/# " /* Monitor Command Prompt */
+#if defined(CONFIG_CMD_KGDB)
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#else
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#endif
+#define CFG_PBSIZE ( CFG_CBSIZE + sizeof( CFG_PROMPT ) + 16 )
+#define CFG_MAXARGS 16 /* max number of command args */
+#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
+#define CFG_MEMTEST_START 0x00400000 /* memtest works on */
+#define CFG_MEMTEST_END 0x00C00000 /* 4 ... 12 MB in DRAM */
+#define CFG_LOAD_ADDR 0x00400000 /* default load address */
+#define CFG_EXTBDINFO 1 /* Extended board_into (bd_t) */
+#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
+#define CONFIG_CMDLINE_EDITING /* add command line history */
+#define CONFIG_AUTO_COMPLETE /* add autocompletion support */
+#define CONFIG_LOOPW /* enable loopw command */
+#define CONFIG_MX_CYCLIC /* enable mdc/mwc commands */
+#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */
+#define CONFIG_VERSION_VARIABLE /* include version env variable */
+#define CFG_CONSOLE_INFO_QUIET /* don't print console @ startup */
+#define CFG_HUSH_PARSER /* Use the HUSH parser */
+#define CFG_PROMPT_HUSH_PS2 "> "
+#define CONFIG_LOADS_ECHO /* echo on for serial download */
+#define CFG_LOADS_BAUD_CHANGE /* allow baudrate change */
+#define CFG_BOOTMAPSZ ( 8 << 20 ) /* Initial Memory map for Linux */
+#define CONFIG_PREBOOT "echo U-Boot is up and runnining;"
+
+/*Stack*/
+#define CFG_INIT_RAM_ADDR 0x800000 /* Initial RAM address */
+#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */
+#define CFG_GBL_DATA_SIZE 128 /* num bytes initial data */
+#define CFG_GBL_DATA_OFFSET ( CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE )
+#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
+/*Speed*/
+#define CONFIG_SYS_CLK_FREQ XPAR_CORE_CLOCK_FREQ_HZ
+
+/*Flash*/
+#define CFG_FLASH_BASE XPAR_FLASH_MEM0_BASEADDR
+#define CFG_FLASH_SIZE (32*1024*1024)
+#define CFG_FLASH_CFI 1
+#define CFG_FLASH_CFI_DRIVER 1
+#define CFG_FLASH_EMPTY_INFO 1
+#define CFG_MAX_FLASH_BANKS 1
+#define CFG_MAX_FLASH_SECT 259
+#define CFG_FLASH_PROTECTION
+#define MTDIDS_DEFAULT "nor0=ml507-flash"
+#define MTDPARTS_DEFAULT "mtdparts=ml507-flash:-(user)"
+
+
+#endif /* __CONFIG_H */
* Flash configuration
*/
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_BASE 0xff000000
#define CFG_FLASH_SIZE 0x01000000
#define CFG_MAX_FLASH_BANKS 1 /* max num of memory banks */
#define FLASH_BANK_SIZE 0x01000000 /* 16 MB Total */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, /* CFG_FLASH_BASE2 */ }
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_WRITE_SWAPPED_DATA
/* Flash */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_BASE 0xA0000000
#define CFG_MAX_FLASH_SECT 256
#define CFG_HZ (CONFIG_SYS_CLK_FREQ / TMU_CLK_DIVIDER)
/* UART */
-#define CFG_SCIF_CONSOLE 1
+#define CONFIG_SCIF_CONSOLE 1
#define CONFIG_CONS_SCIF0 1
#endif /* __MPR2_H */
#define CFG_BAUDRATE_TABLE { 115200 }
/* SCIF */
-#define CFG_SCIF_CONSOLE 1
+#define CONFIG_SCIF_CONSOLE 1
#define CONFIG_CONS_SCIF0 1
#define CFG_MEMTEST_START MS7720SE_SDRAM_BASE
/* FLASH */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#undef CFG_FLASH_QUIET_TEST
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */
#define CFG_BAUDRATE_TABLE { 115200 } /* List of legal baudrate settings for this board */
/* SCIF */
-#define CFG_SCIF_CONSOLE 1
+#define CONFIG_SCIF_CONSOLE 1
#define CONFIG_CONS_SCIF0 1
#undef CFG_CONSOLE_INFO_QUIET /* Suppress display of console information at boot */
#undef CFG_CONSOLE_OVERWRITE_ROUTINE
/* FLASH */
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#undef CFG_FLASH_QUIET_TEST
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */
#define CONFIG_CMD_FLASH
#define CONFIG_CMD_ENV
-#define CFG_SCIF_CONSOLE 1
+#define CONFIG_SCIF_CONSOLE 1
#define CONFIG_BAUDRATE 38400
#define CONFIG_CONS_SCIF1 1
#define BOARD_LATE_INIT 1
#define CFG_RX_ETH_BUFFER (8)
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#undef CFG_FLASH_CFI_BROKEN_TABLE
#undef CFG_FLASH_QUIET_TEST
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */
*/
#define CFG_FLASH_BASE 0xFF000000
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_SIZE 0x01000000 /* 16 MByte */
* CFI FLASH driver setup
*/
#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use drivers/cfi_flash.c */
#define CONFIG_FLASH_SPANSION_S29WS_N 1 /* A non-standard buffered write algorithm */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* Use buffered writes (~10x faster) */
#define CFG_FLASH_PROTECTION 1 /* Use hardware sector protection */
/*
* Hardware drivers
*/
-#define CFG_NS9750_UART 1 /* use on-chip UART */
+#define CONFIG_NS9750_UART 1 /* use on-chip UART */
#define CONFIG_DRIVER_NS9750_ETHERNET 1 /* use on-chip ethernet */
/*
* FLASH driver setup
*/
#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/mtd/cfi_flash.c */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use drivers/mtd/cfi_flash.c */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* Use buffered writes (~10x faster) */
#define CFG_FLASH_PROTECTION 1 /* Use hardware sector protection */
/*
* Board NAND Info.
*/
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_NAND_ADDR 0x04000000 /* physical address to access nand at CS0*/
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
* CFI FLASH driver setup
*/
#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/mtd/cfi_flash.c */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use drivers/mtd/cfi_flash.c */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* Use buffered writes (~10x faster) */
#define CFG_FLASH_PROTECTION 1 /* Use hardware sector protection */
* FLASH driver setup
*/
#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use drivers/mtd/cfi_flash.c */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use drivers/mtd/cfi_flash.c */
#define CFG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_MAX_FLASH_SECT 512 /* max number of sectors on one chip */
#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH3, CFG_FLASH2, CFG_FLASH1, CFG_FLASH0 }
*/
#if defined(CONFIG_SCPU)
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_16BIT /* no byte writes on IXP4xx */
#endif
*/
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_FLASH_INCREMENT 0 /* there is only one bank */
* FLASH and environment organization
*/
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_MONITOR_BASE 0
#define CFG_MONITOR_LEN PHYS_FLASH_SECT_SIZE
#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 128
#define CFG_FLASH_CFI 1 /* Flash memory is CFI compliant */
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_ENV_IS_IN_FLASH 1
* FLASH organization
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
#define CFG_FLASH_BASE 0xFF000000
#if 1
- #define CFG_FLASH_CFI_DRIVER
+ #define CONFIG_FLASH_CFI_DRIVER
#else
- #undef CFG_FLASH_CFI_DRIVER
+ #undef CONFIG_FLASH_CFI_DRIVER
#endif
-#ifdef CFG_FLASH_CFI_DRIVER
+#ifdef CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI 1
#undef CFG_FLASH_USE_BUFFER_WRITE
#define CFG_FLASH_BANKS_LIST {CFG_FLASH_BASE}
#define CONFIG_DOS_PARTITION
/* SCIF */
-#define CFG_SCIF_CONSOLE 1
+#define CONFIG_SCIF_CONSOLE 1
#define CONFIG_BAUDRATE 115200
#define CONFIG_CONS_SCIF1 1
#define BOARD_LATE_INIT 1
* NOR Flash ( Spantion S29GL256P )
*/
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_BASE (0xA0000000)
#define CFG_MAX_FLASH_BANKS (1)
#define CFG_MAX_FLASH_SECT 256
#define CONFIG_CMD_EXT2
#define CONFIG_DOS_PARTITION
-#define CFG_SCIF_CONSOLE 1
+#define CONFIG_SCIF_CONSOLE 1
#define CONFIG_BAUDRATE 115200
#define CONFIG_CONS_SCIF0 1
#define CFG_RX_ETH_BUFFER (8)
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#undef CFG_FLASH_CFI_BROKEN_TABLE
#undef CFG_FLASH_QUIET_TEST
/* print 'E' for empty sector on flinfo */
--- /dev/null
+/*
+ * Configuration for AMCC 460SX Ref (redwood)
+ *
+ * (C) Copyright 2008
+ * Feng Kan, Applied Micro Circuits Corp., fkan@amcc.com
+ *
+ * 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
+
+/*-----------------------------------------------------------------------
+ * High Level Configuration Options
+ *----------------------------------------------------------------------*/
+#define CONFIG_4xx 1 /* ... PPC4xx family */
+#define CONFIG_440 1 /* ... PPC460 family */
+#define CONFIG_460SX 1 /* ... PPC460 family */
+#define CONFIG_BOARD_EARLY_INIT_F 1 /* Call board_pre_init */
+
+/*-----------------------------------------------------------------------
+ * Include common defines/options for all AMCC boards
+ *----------------------------------------------------------------------*/
+#define CONFIG_HOSTNAME redwood
+
+#include "amcc-common.h"
+
+#define CONFIG_SYS_CLK_FREQ 33333333 /* external freq to pll */
+
+/*-----------------------------------------------------------------------
+ * Base addresses -- Note these are effective addresses where the
+ * actual resources get mapped (not physical addresses)
+ *----------------------------------------------------------------------*/
+#define CFG_FLASH_BASE 0xfff00000 /* start of FLASH */
+#define CFG_PERIPHERAL_BASE 0xa0000000 /* internal peripherals */
+#define CFG_ISRAM_BASE 0x90000000 /* internal SRAM */
+
+#define CFG_PCI_BASE 0xd0000000 /* internal PCI regs */
+
+#define CFG_PCIE_MEMBASE 0x90000000 /* mapped PCIe memory */
+#define CFG_PCIE0_MEMBASE 0x90000000 /* mapped PCIe memory */
+#define CFG_PCIE1_MEMBASE 0xa0000000 /* mapped PCIe memory */
+#define CFG_PCIE_MEMSIZE 0x01000000
+
+#define CFG_PCIE0_XCFGBASE 0xb0000000
+#define CFG_PCIE1_XCFGBASE 0xb2000000
+#define CFG_PCIE2_XCFGBASE 0xb4000000
+#define CFG_PCIE0_CFGBASE 0xb6000000
+#define CFG_PCIE1_CFGBASE 0xb8000000
+#define CFG_PCIE2_CFGBASE 0xba000000
+
+/* PCIe mapped UTL registers */
+#define CFG_PCIE0_REGBASE 0xd0000000
+#define CFG_PCIE1_REGBASE 0xd0010000
+#define CFG_PCIE2_REGBASE 0xd0020000
+
+/* System RAM mapped to PCI space */
+#define CONFIG_PCI_SYS_MEM_BUS CFG_SDRAM_BASE
+#define CONFIG_PCI_SYS_MEM_PHYS CFG_SDRAM_BASE
+#define CONFIG_PCI_SYS_MEM_SIZE (1024 * 1024 * 1024)
+
+#define CFG_FPGA_BASE 0xe2000000 /* epld */
+#define CFG_OPER_FLASH 0xe7000000 /* SRAM - OPER Flash */
+
+/*-----------------------------------------------------------------------
+ * Initial RAM & stack pointer (placed in internal SRAM)
+ *----------------------------------------------------------------------*/
+#define CFG_TEMP_STACK_OCM 1
+#define CFG_OCM_DATA_ADDR CFG_ISRAM_BASE
+#define CFG_INIT_RAM_ADDR CFG_ISRAM_BASE /* Initial RAM address */
+#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */
+#define CFG_GBL_DATA_SIZE 128 /* num bytes initial data */
+
+#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_POST_WORD_ADDR (CFG_GBL_DATA_OFFSET - 0x4)
+#define CFG_INIT_SP_OFFSET CFG_POST_WORD_ADDR
+
+/*-----------------------------------------------------------------------
+ * DDR SDRAM
+ *----------------------------------------------------------------------*/
+#define CONFIG_SPD_EEPROM 1 /* Use SPD EEPROM for setup */
+#define CONFIG_DDR_ECC 1 /* with ECC support */
+
+#define CFG_SPD_MAX_DIMMS 2
+
+/* SPD i2c spd addresses */
+#define SPD_EEPROM_ADDRESS {IIC0_DIMM0_ADDR, IIC0_DIMM1_ADDR}
+#define IIC0_DIMM0_ADDR 0x53
+#define IIC0_DIMM1_ADDR 0x52
+
+/*-----------------------------------------------------------------------
+ * I2C
+ *----------------------------------------------------------------------*/
+#define CFG_I2C_SPEED 400000 /* I2C speed */
+
+#define IIC0_BOOTPROM_ADDR 0x50
+#define IIC0_ALT_BOOTPROM_ADDR 0x54
+
+/* Don't probe these addrs */
+#define CFG_I2C_NOPROBES {0x50, 0x52, 0x53, 0x54}
+
+#define CFG_I2C_EEPROM_ADDR_LEN 2 /* Bytes of address */
+
+/*-----------------------------------------------------------------------
+ * Environment
+ *----------------------------------------------------------------------*/
+#undef CFG_ENV_IS_IN_NVRAM /* ... not in NVRAM */
+#define CFG_ENV_IS_IN_FLASH 1 /* Environment uses flash */
+#undef CFG_ENV_IS_IN_EEPROM /* ... not in EEPROM */
+
+#define CONFIG_PREBOOT "echo;" \
+ "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \
+ "echo"
+
+#undef CONFIG_BOOTARGS
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ CONFIG_AMCC_DEF_ENV \
+ CONFIG_AMCC_DEF_ENV_POWERPC \
+ CONFIG_AMCC_DEF_ENV_NOR_UPD \
+ CONFIG_AMCC_DEF_ENV_NAND_UPD \
+ "kernel_addr=fc000000\0" \
+ "fdt_addr=fc1e0000\0" \
+ "ramdisk_addr=fc200000\0" \
+ ""
+
+/*----------------------------------------------------------------------------+
+| Commands in addition to amcc-common.h
++----------------------------------------------------------------------------*/
+#define CONFIG_CMD_SDRAM
+
+#define CONFIG_BOOTCOMMAND "run flash_self"
+
+#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */
+
+#define CONFIG_IBM_EMAC4_V4 1
+#define CONFIG_PHY_RESET 1 /* reset phy upon startup */
+#define CONFIG_PHY_RESET_DELAY 1000
+#define CONFIG_M88E1141_PHY 1 /* Enable phy */
+#define CONFIG_PHY_GIGE 1 /* Include GbE speed/duplex detection */
+
+#define CONFIG_HAS_ETH0
+#define CONFIG_HAS_ETH1
+#define CONFIG_PHY_ADDR 0 /* PHY address, See schematics */
+#define CONFIG_PHY1_ADDR 1 /* PHY address, See schematics */
+
+#undef CONFIG_WATCHDOG /* watchdog disabled */
+
+/*-----------------------------------------------------------------------
+ * FLASH related
+ *----------------------------------------------------------------------*/
+#define CFG_FLASH_CFI /* The flash is CFI compatible */
+#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CFG_FLASH_CFI_AMD_RESET 1 /* Use AMD (Spansion) reset cmd */
+
+#define CFG_MAX_FLASH_BANKS 3 /* number of banks */
+#define CFG_MAX_FLASH_SECT 256 /* sectors per device */
+
+#undef CFG_FLASH_CHECKSUM
+#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
+#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */
+
+#ifdef CFG_ENV_IS_IN_FLASH
+#define CFG_ENV_SECT_SIZE 0x10000 /* size of one complete sector */
+#define CFG_ENV_ADDR 0xfffa0000
+#define CFG_ENV_SIZE 0x10000 /* Size of Environment vars */
+#endif /* CFG_ENV_IS_IN_FLASH */
+
+/*---------------------------------------------------------------------------*/
+
+#endif /* __CONFIG_H */
* FLASH on the Local Bus
*/
#define CFG_FLASH_CFI /* use the Common Flash Interface */
-#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* use the CFI driver */
#define CFG_FLASH_BASE 0xFF800000 /* start of FLASH */
#define CFG_FLASH_SIZE 8 /* flash size in MB */
/* #define CFG_FLASH_USE_BUFFER_WRITE */
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
*/
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#if 0
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_FLASH_PROTECTION /* use hardware protection */
#define CONFIG_TSEC_ENET /* tsec ethernet support */
#define CONFIG_ENV_OVERWRITE
+#define CONFIG_HIGH_BATS 1 /* High BATs supported and enabled */
+
#undef CONFIG_SPD_EEPROM /* Do not use SPD EEPROM for DDR setup*/
#undef CONFIG_DDR_DLL /* possible DLL fix needed */
#define CONFIG_DDR_2T_TIMING /* Sets the 2T timing bit */
#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */
#define CFG_MONITOR_BASE TEXT_BASE /* start of monitor */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_WRITE_SWAPPED_DATA
#define CFG_FLASH_EMPTY_INFO
#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */
#define CFG_FLASH_CFI /* flash is CFI compat. */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver*/
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver*/
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector */
#define CFG_FLASH_QUIET_TEST 1 /* don't warn upon unknown flash*/
#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
#define CFG_SATA_MAXBUS 2 /*Max Sata buses supported */
#define CFG_SATA_DEVS_PER_BUS 2 /*Max no. of devices per bus/port */
#define CFG_SATA_MAX_DEVICE (CFG_SATA_MAXBUS* CFG_SATA_DEVS_PER_BUS)
-#define CFG_ATA_PIIX 1 /*Supports ata_piix driver */
+#define CONFIG_ATA_PIIX 1 /*Supports ata_piix driver */
/************************************************************
* DISK Partition support
* FLASH related
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
/* GPIO Core 1 */ \
{GPIO1_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_1}, /* GPIO32 USB2D_OPMODE0 EBC_DATA(2) */ \
{GPIO1_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_1}, /* GPIO33 USB2D_OPMODE1 EBC_DATA(3) */ \
-{GPIO1_BASE, GPIO_OUT, GPIO_ALT3, GPIO_OUT_1}, /* GPIO34 UART0_DCD_N UART1_DSR_CTS_N UART2_SOUT*/ \
-{GPIO1_BASE, GPIO_IN , GPIO_ALT3, GPIO_OUT_0}, /* GPIO35 UART0_8PIN_DSR_N UART1_RTS_DTR_N UART2_SIN*/ \
-{GPIO1_BASE, GPIO_IN , GPIO_ALT3, GPIO_OUT_0}, /* GPIO36 UART0_8PIN_CTS_N EBC_DATA(0) UART3_SIN*/ \
-{GPIO1_BASE, GPIO_BI , GPIO_ALT2, GPIO_OUT_0}, /* GPIO37 UART0_RTS_N EBC_DATA(1) UART3_SOUT*/ \
-{GPIO1_BASE, GPIO_OUT, GPIO_ALT2, GPIO_OUT_1}, /* GPIO38 UART0_DTR_N UART1_SOUT */ \
-{GPIO1_BASE, GPIO_IN , GPIO_ALT2, GPIO_OUT_0}, /* GPIO39 UART0_RI_N UART1_SIN */ \
+{GPIO1_BASE, GPIO_IN , GPIO_ALT2, GPIO_OUT_0}, /* GPIO34 UART0_8PIN_DCD_N UART1_DSR_CTS_N UART2_SOUT*/ \
+{GPIO1_BASE, GPIO_OUT, GPIO_ALT2, GPIO_OUT_1}, /* GPIO35 UART0_8PIN_DSR_N UART1_RTS_DTR_N UART2_SIN*/ \
+{GPIO1_BASE, GPIO_IN , GPIO_ALT1, GPIO_OUT_0}, /* GPIO36 UART0_CTS_N EBC_DATA(0) UART3_SIN*/ \
+{GPIO1_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_1}, /* GPIO37 UART0_RTS_N EBC_DATA(1) UART3_SOUT*/ \
+{GPIO1_BASE, GPIO_OUT, GPIO_ALT2, GPIO_OUT_1}, /* GPIO38 UART0_8PIN_DTR_N UART1_SOUT */ \
+{GPIO1_BASE, GPIO_IN , GPIO_ALT2, GPIO_OUT_0}, /* GPIO39 UART0_8PIN_RI_N UART1_SIN */ \
{GPIO1_BASE, GPIO_IN , GPIO_ALT1, GPIO_OUT_0}, /* GPIO40 UIC_IRQ(0) */ \
{GPIO1_BASE, GPIO_IN , GPIO_ALT1, GPIO_OUT_0}, /* GPIO41 UIC_IRQ(1) */ \
{GPIO1_BASE, GPIO_IN , GPIO_ALT1, GPIO_OUT_0}, /* GPIO42 UIC_IRQ(2) */ \
#define CONFIG_CMD_SDRAM
#define CONFIG_CMD_FLASH
#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
#define CONFIG_CMD_ENV
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_JFFS2
#define CONFIG_BOOTDELAY -1
#define CONFIG_BOOTARGS "console=ttySC2,115200 root=1f01"
#undef CONFIG_SHOW_BOOT_PROGRESS
/* SCIF */
-#define CFG_SCIF_CONSOLE 1
+#define CONFIG_SCIF_CONSOLE 1
#define CONFIG_BAUDRATE 115200
#define CONFIG_CONS_SCIF2 1
#define CFG_BOOTMAPSZ (8 * 1024 * 1024)
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#undef CFG_FLASH_QUIET_TEST
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */
/* Timeout for Flash erase operations (in ms) */
#define TMU_CLK_DIVIDER (4) /* 4 (default), 16, 64, 256 or 1024 */
#define CFG_HZ (CONFIG_SYS_CLK_FREQ / TMU_CLK_DIVIDER)
+/* Ether */
+#define CONFIG_SH_ETHER 1
+#define CONFIG_SH_ETHER_USE_PORT (1)
+#define CONFIG_SH_ETHER_PHY_ADDR (0x01)
+
#endif /* __SH7763RDP_H */
/* use CFI flash driver if no module variant is spezified */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_BOOTCS_START }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_SIZE 0x04000000 /* 64 MByte */
#define CFG_OR1_PRELIM 0xfe000ff7 /* 32MB Flash */
#define CFG_FLASH_CFI /* flash is CFI compat. */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver*/
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver*/
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector */
#define CFG_MAX_FLASH_BANKS 2 /* number of banks */
#define CFG_MAX_FLASH_BANKS 2 /* max num of flash banks */
#define CFG_MAX_FLASH_SECT 512 /* max num of sects on one chip */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, \
CFG_FLASH_BASE+0x04000000 } /* two banks */
*/
#define CFG_FLASH_BASE 0xFE000000
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_MAX_FLASH_BANKS 1 /* Max number of flash banks */
#define CFG_MAX_FLASH_SECT 128 /* Max num of sects on one chip */
/* use CFI flash driver if no module variant is spezified */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_BANKS_LIST { CFG_BOOTCS_START }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_SIZE 0x04000000 /* 64 MByte */
#define CFG_OR0_PRELIM (CFG_FLASH_BASE | 0x0FF7)
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#undef CFG_FLASH_USE_BUFFER_WRITE /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_ENV_SIZE_REDUND CFG_ENV_SIZE
#define CFG_FLASH_CFI 1
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#undef CFG_FLASH_USE_BUFFER_WRITE /* use buffered writes (20x faster) */
#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */
#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
/****************************************************************/
/* NAND */
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
#define CFG_NAND_BASE NAND_BASE
#define CONFIG_MTD_NAND_ECC_JFFS2
#define CONFIG_MTD_NAND_VERIFY_WRITE
#define CONFIG_CMD_DATE
-#define CFG_NAND_LEGACY
+#define CONFIG_NAND_LEGACY
/*
* Miscellaneous configurable options
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
*/
#define CFG_FLASH_CFI
-#define CFG_FLASH_CFI_DRIVER 1
+#define CONFIG_FLASH_CFI_DRIVER 1
#define CFG_MONITOR_BASE 0
#define CFG_MONITOR_LEN 0x40000
* FLASH organization
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_CFI_AMD_RESET 1 /* AMD RESET for STM 29W320DB! */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */
#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */
-#define CFG_FLASH_CFI_DRIVER
+#define CONFIG_FLASH_CFI_DRIVER
#define CFG_FLASH_CFI
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_CFI_AMD_RESET
* Flash configuration - use CFI driver
*/
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
#define CFG_FLASH_CFI_AMD_RESET 1
#define CFG_FLASH_BASE 0xFF000000
#define CFG_MAX_FLASH_BANKS 1 /* max num of flash banks */
/*
- * (C) Copyright 2006
+ * (C) Copyright 2006-2008
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
#define CONFIG_VIRTLAB2 1 /* ...on a virtlab2 module */
#define CONFIG_TQM8xxL 1
-#ifdef CONFIG_LCD /* with LCD controller ? */
-#define CONFIG_SPLASH_SCREEN /* ... with splashscreen support*/
-#endif
-
#define CONFIG_8xx_CONS_SMC1 1 /* Console is on SMC1 */
#undef CONFIG_8xx_CONS_SMC2
#undef CONFIG_8xx_CONS_NONE
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
"net_nfs=tftp 200000 ${bootfile};run nfsargs addip;bootm\0" \
"rootpath=/opt/eldk/ppc_8xx\0" \
- "bootfile=/tftpboot/TQM823L/uImage\0" \
- "kernel_addr=40040000\0" \
- "ramdisk_addr=40100000\0" \
+ "hostname=virtlab2\0" \
+ "bootfile=virtlab2/uImage\0" \
+ "fdt_addr=40040000\0" \
+ "kernel_addr=40060000\0" \
+ "ramdisk_addr=40200000\0" \
+ "u-boot=virtlab2/u-image.bin\0" \
+ "load=tftp 200000 ${u-boot}\0" \
+ "update=prot off 40000000 +${filesize};" \
+ "era 40000000 +${filesize};" \
+ "cp.b 200000 40000000 ${filesize};" \
+ "sete filesize;save\0" \
""
#define CONFIG_BOOTCOMMAND "run flash_self"
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_IDE
+#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_NFS
#define CONFIG_CMD_SNTP
#endif
+#define CONFIG_NETCONSOLE
+
/*
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "=> " /* Monitor Command Prompt */
-#if 0
+#define CONFIG_CMDLINE_EDITING 1 /* add command line history */
#define CFG_HUSH_PARSER 1 /* use "hush" command parser */
-#endif
#ifdef CFG_HUSH_PARSER
#define CFG_PROMPT_HUSH_PS2 "> "
#endif
/* use CFI flash driver */
#define CFG_FLASH_CFI 1 /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER 1 /* Use the common driver */
-#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
+#define CONFIG_FLASH_CFI_DRIVER 1 /* Use the common driver */
+#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE, CFG_FLASH_BASE+flash_info[0].size }
#define CFG_FLASH_EMPTY_INFO
#define CFG_FLASH_USE_BUFFER_WRITE 1
#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
#define CFG_USE_PPCENV /* Environment embedded in sect .ppcenv */
/*-----------------------------------------------------------------------
+ * Dynamic MTD partition support
+ */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=TQM8xxL-0"
+
+#define MTDPARTS_DEFAULT "mtdparts=TQM8xxL-0:256k(u-boot)," \
+ "128k(dtb)," \
+ "1664k(kernel)," \
+ "2m(rootfs)," \
+ "4m(data)"
+
+/*-----------------------------------------------------------------------
* Hardware Information Block
*/
#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */
* FLASH organization
*/
#define CFG_FLASH_CFI /* Flash is CFI conformant */
-#define CFG_FLASH_CFI_DRIVER /* Use the common driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use the common driver */
#define CFG_MAX_FLASH_BANKS 1
#define CFG_FLASH_BASE PHYS_FLASH_1
* FLASH related
*----------------------------------------------------------------------*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_CFI_AMD_RESET 1 /* AMD RESET for STM 29W320DB! */
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
* FLASH organization
*/
#define CFG_FLASH_CFI /* The flash is CFI compatible */
-#define CFG_FLASH_CFI_DRIVER /* Use common CFI driver */
+#define CONFIG_FLASH_CFI_DRIVER /* Use common CFI driver */
#define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }
int cs;
};
/*-------------------------------------------------------------------------------------------------*/
-
#define AT45DB161 0x2c
#define AT45DB021 0x14
+#define AT45DB081 0x24
#define AT45DB321 0x34
#define AT45DB642 0x3c
#define AT45DB128 0x10
#ifndef _DTT_H_
#define _DTT_H_
-#if defined(CONFIG_DTT_LM75) || \
- defined(CONFIG_DTT_DS1621) || \
- defined(CONFIG_DTT_DS1775) || \
- defined(CONFIG_DTT_LM81) || \
- defined(CONFIG_DTT_ADM1021) || \
- defined(CONFIG_DTT_LM73)
+#if defined(CONFIG_DTT_ADM1021) || \
+ defined(CONFIG_DTT_ADT7460) || \
+ defined(CONFIG_DTT_DS1621) || \
+ defined(CONFIG_DTT_DS1775) || \
+ defined(CONFIG_DTT_LM73) || \
+ defined(CONFIG_DTT_LM75) || \
+ defined(CONFIG_DTT_LM81)
#define CONFIG_DTT /* We have a DTT */
#endif
int verify; /* getenv("verify")[0] != 'n' */
- int autostart; /* getenv("autostart")[0] != 'n' */
struct lmb *lmb; /* for memory mgmt */
} bootm_headers_t;
--- /dev/null
+#ifndef _LINUX_ERR_H
+#define _LINUX_ERR_H
+
+/* XXX U-BOOT XXX */
+#if 0
+#include <linux/compiler.h>
+#else
+#include <linux/mtd/compat.h>
+#endif
+
+#include <asm/errno.h>
+
+
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define MAX_ERRNO 4095
+
+#ifndef __ASSEMBLY__
+
+#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
+
+static inline void *ERR_PTR(long error)
+{
+ return (void *) error;
+}
+
+static inline long PTR_ERR(const void *ptr)
+{
+ return (long) ptr;
+}
+
+static inline long IS_ERR(const void *ptr)
+{
+ return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#endif
+
+#endif /* _LINUX_ERR_H */
--- /dev/null
+/*
+ * $Id: blktrans.h,v 1.6 2005/11/07 11:14:54 gleixner Exp $
+ *
+ * (C) 2003 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Interface to Linux block layer for MTD 'translation layers'.
+ *
+ */
+
+#ifndef __MTD_TRANS_H__
+#define __MTD_TRANS_H__
+
+/* XXX U-BOOT XXX */
+#if 0
+#include <linux/mutex.h>
+#else
+#include <linux/list.h>
+#endif
+
+struct hd_geometry;
+struct mtd_info;
+struct mtd_blktrans_ops;
+struct file;
+struct inode;
+
+struct mtd_blktrans_dev {
+ struct mtd_blktrans_ops *tr;
+ struct list_head list;
+ struct mtd_info *mtd;
+/* XXX U-BOOT XXX */
+#if 0
+ struct mutex lock;
+#endif
+ int devnum;
+ unsigned long size;
+ int readonly;
+ void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */
+};
+
+struct blkcore_priv; /* Differs for 2.4 and 2.5 kernels; private */
+
+struct mtd_blktrans_ops {
+ char *name;
+ int major;
+ int part_bits;
+ int blksize;
+ int blkshift;
+
+ /* Access functions */
+ int (*readsect)(struct mtd_blktrans_dev *dev,
+ unsigned long block, char *buffer);
+ int (*writesect)(struct mtd_blktrans_dev *dev,
+ unsigned long block, char *buffer);
+
+ /* Block layer ioctls */
+ int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
+ int (*flush)(struct mtd_blktrans_dev *dev);
+
+ /* Called with mtd_table_mutex held; no race with add/remove */
+ int (*open)(struct mtd_blktrans_dev *dev);
+ int (*release)(struct mtd_blktrans_dev *dev);
+
+ /* Called on {de,}registration and on subsequent addition/removal
+ of devices, with mtd_table_mutex held. */
+ void (*add_mtd)(struct mtd_blktrans_ops *tr, struct mtd_info *mtd);
+ void (*remove_dev)(struct mtd_blktrans_dev *dev);
+
+ struct list_head devs;
+ struct list_head list;
+ struct module *owner;
+
+ struct mtd_blkcore_priv *blkcore_priv;
+};
+
+extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr);
+extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr);
+extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
+extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
+
+
+#endif /* __MTD_TRANS_H__ */
#define KERN_DEBUG
#define kmalloc(size, flags) malloc(size)
-#define kfree(ptr) free(ptr)
+#define kzalloc(size, flags) calloc(size, 1)
+#define vmalloc(size) malloc(size)
+#define kfree(ptr) free(ptr)
+#define vfree(ptr) free(ptr)
+
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
/*
* ..and if you can't take the strict
-
-/* Linux driver for Disk-On-Chip 2000 */
-/* (c) 1999 Machine Vision Holdings, Inc. */
-/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.h,v 1.15 2001/09/19 00:22:15 dwmw2 Exp $ */
+/*
+ * Linux driver for Disk-On-Chip devices
+ *
+ * Copyright (C) 1999 Machine Vision Holdings, Inc.
+ * Copyright (C) 2001-2003 David Woodhouse <dwmw2@infradead.org>
+ * Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
+ * Copyright (C) 2002-2003 SnapGear Inc
+ *
+ * $Id: doc2000.h,v 1.25 2005/11/07 11:14:54 gleixner Exp $
+ *
+ * Released under GPL
+ */
#ifndef __MTD_DOC2000_H__
#define __MTD_DOC2000_H__
-struct DiskOnChip;
-
-#include <linux/mtd/nftl.h>
+#include <linux/mtd/mtd.h>
+#if 0
+#include <linux/mutex.h>
+#endif
#define DoC_Sig1 0
#define DoC_Sig2 1
#define DoC_Mil_CDSN_IO 0x0800
#define DoC_2k_CDSN_IO 0x1800
-#define ReadDOC_(adr, reg) ((volatile unsigned char)(*(volatile __u8 *)(((unsigned long)adr)+((reg)))))
-#define WriteDOC_(d, adr, reg) do{ *(volatile __u8 *)(((unsigned long)adr)+((reg))) = (__u8)d; eieio();} while(0)
-
-#define DOC_IOREMAP_LEN 0x4000
+#define DoC_Mplus_NOP 0x1002
+#define DoC_Mplus_AliasResolution 0x1004
+#define DoC_Mplus_DOCControl 0x1006
+#define DoC_Mplus_AccessStatus 0x1008
+#define DoC_Mplus_DeviceSelect 0x1008
+#define DoC_Mplus_Configuration 0x100a
+#define DoC_Mplus_OutputControl 0x100c
+#define DoC_Mplus_FlashControl 0x1020
+#define DoC_Mplus_FlashSelect 0x1022
+#define DoC_Mplus_FlashCmd 0x1024
+#define DoC_Mplus_FlashAddress 0x1026
+#define DoC_Mplus_FlashData0 0x1028
+#define DoC_Mplus_FlashData1 0x1029
+#define DoC_Mplus_ReadPipeInit 0x102a
+#define DoC_Mplus_LastDataRead 0x102c
+#define DoC_Mplus_LastDataRead1 0x102d
+#define DoC_Mplus_WritePipeTerm 0x102e
+#define DoC_Mplus_ECCSyndrome0 0x1040
+#define DoC_Mplus_ECCSyndrome1 0x1041
+#define DoC_Mplus_ECCSyndrome2 0x1042
+#define DoC_Mplus_ECCSyndrome3 0x1043
+#define DoC_Mplus_ECCSyndrome4 0x1044
+#define DoC_Mplus_ECCSyndrome5 0x1045
+#define DoC_Mplus_ECCConf 0x1046
+#define DoC_Mplus_Toggle 0x1046
+#define DoC_Mplus_DownloadStatus 0x1074
+#define DoC_Mplus_CtrlConfirm 0x1076
+#define DoC_Mplus_Power 0x1fff
+
+/* How to access the device?
+ * On ARM, it'll be mmap'd directly with 32-bit wide accesses.
+ * On PPC, it's mmap'd and 16-bit wide.
+ * Others use readb/writeb
+ */
+#if defined(__arm__)
+#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2))))
+#define WriteDOC_(d, adr, reg) do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
+#define DOC_IOREMAP_LEN 0x8000
+#elif defined(__ppc__)
+#define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1))))
+#define WriteDOC_(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
+#define DOC_IOREMAP_LEN 0x4000
+#else
+#define ReadDOC_(adr, reg) readb((void __iomem *)(adr) + (reg))
+#define WriteDOC_(d, adr, reg) writeb(d, (void __iomem *)(adr) + (reg))
+#define DOC_IOREMAP_LEN 0x2000
+
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+#define USE_MEMCPY
+#endif
/* These are provided to directly use the DoC_xxx defines */
#define ReadDOC(adr, reg) ReadDOC_(adr,DoC_##reg)
#define DOC_MODE_RESERVED1 2
#define DOC_MODE_RESERVED2 3
-#define DOC_MODE_MDWREN 4
#define DOC_MODE_CLR_ERR 0x80
+#define DOC_MODE_RST_LAT 0x10
+#define DOC_MODE_BDECT 0x08
+#define DOC_MODE_MDWREN 0x04
-#define DOC_ChipID_UNKNOWN 0x00
#define DOC_ChipID_Doc2k 0x20
+#define DOC_ChipID_Doc2kTSOP 0x21 /* internal number for MTD */
#define DOC_ChipID_DocMil 0x30
+#define DOC_ChipID_DocMilPlus32 0x40
+#define DOC_ChipID_DocMilPlus16 0x41
#define CDSN_CTRL_FR_B 0x80
+#define CDSN_CTRL_FR_B0 0x40
+#define CDSN_CTRL_FR_B1 0x80
+
#define CDSN_CTRL_ECC_IO 0x20
#define CDSN_CTRL_FLASH_IO 0x10
#define CDSN_CTRL_WP 0x08
#define DOC_ECC_RESV 0x02
#define DOC_ECC_IGNORE 0x01
+#define DOC_FLASH_CE 0x80
+#define DOC_FLASH_WP 0x40
+#define DOC_FLASH_BANK 0x02
+
/* We have to also set the reserved bit 1 for enable */
#define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV)
#define DOC_ECC_DIS (DOC_ECC_RESV)
+struct Nand {
+ char floor, chip;
+ unsigned long curadr;
+ unsigned char curmode;
+ /* Also some erase/write/pipeline info when we get that far */
+};
+
#define MAX_FLOORS 4
#define MAX_CHIPS 4
-#define MAX_FLOORS_MIL 4
+#define MAX_FLOORS_MIL 1
#define MAX_CHIPS_MIL 1
+#define MAX_FLOORS_MPLUS 2
+#define MAX_CHIPS_MPLUS 1
+
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
-struct Nand {
- char floor, chip;
- unsigned long curadr;
- unsigned char curmode;
- /* Also some erase/write/pipeline info when we get that far */
-};
-
struct DiskOnChip {
unsigned long physadr;
- unsigned long virtadr;
+ void __iomem *virtadr;
unsigned long totlen;
- char* name;
- char ChipID; /* Type of DiskOnChip */
+ unsigned char ChipID; /* Type of DiskOnChip */
int ioreg;
- char* chips_name;
unsigned long mfr; /* Flash IDs - only one type of flash per device */
unsigned long id;
int chipshift;
char page256;
char pageadrlen;
+ char interleave; /* Internal interleaving - Millennium Plus style */
unsigned long erasesize;
int curfloor;
int numchips;
struct Nand *chips;
-
- int nftl_found;
- struct NFTLrecord nftl;
+ struct mtd_info *nextdoc;
+/* XXX U-BOOT XXX */
+#if 0
+ struct mutex lock;
+#endif
};
-#define SECTORSIZE 512
-
-/* Return codes from doc_write(), doc_read(), and doc_erase().
- */
-#define DOC_OK 0
-#define DOC_EIO 1
-#define DOC_EINVAL 2
-#define DOC_EECC 3
-#define DOC_ETIMEOUT 4
-
-/*
- * Function Prototypes
- */
int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);
-int doc_rw(struct DiskOnChip* this, int cmd, loff_t from, size_t len,
- size_t *retlen, u_char *buf);
-int doc_read_ecc(struct DiskOnChip* this, loff_t from, size_t len,
- size_t *retlen, u_char *buf, u_char *eccbuf);
-int doc_write_ecc(struct DiskOnChip* this, loff_t to, size_t len,
- size_t *retlen, const u_char *buf, u_char *eccbuf);
-int doc_read_oob(struct DiskOnChip* this, loff_t ofs, size_t len,
- size_t *retlen, u_char *buf);
-int doc_write_oob(struct DiskOnChip* this, loff_t ofs, size_t len,
- size_t *retlen, const u_char *buf);
-int doc_erase (struct DiskOnChip* this, loff_t ofs, size_t len);
-
-void doc_probe(unsigned long physadr);
-
-void doc_print(struct DiskOnChip*);
-
-/*
- * Standard NAND flash commands
- */
-#define NAND_CMD_READ0 0
-#define NAND_CMD_READ1 1
-#define NAND_CMD_PAGEPROG 0x10
-#define NAND_CMD_READOOB 0x50
-#define NAND_CMD_ERASE1 0x60
-#define NAND_CMD_STATUS 0x70
-#define NAND_CMD_SEQIN 0x80
-#define NAND_CMD_READID 0x90
-#define NAND_CMD_ERASE2 0xd0
-#define NAND_CMD_RESET 0xff
-
+/* XXX U-BOOT XXX */
+#if 1
/*
* NAND Flash Manufacturer ID Codes
*/
-#define NAND_MFR_TOSHIBA 0x98
-#define NAND_MFR_SAMSUNG 0xec
-
-/*
- * NAND Flash Device ID Structure
- *
- * Structure overview:
- *
- * name - Complete name of device
- *
- * manufacture_id - manufacturer ID code of device.
- *
- * model_id - model ID code of device.
- *
- * chipshift - total number of address bits for the device which
- * is used to calculate address offsets and the total
- * number of bytes the device is capable of.
- *
- * page256 - denotes if flash device has 256 byte pages or not.
- *
- * pageadrlen - number of bytes minus one needed to hold the
- * complete address into the flash array. Keep in
- * mind that when a read or write is done to a
- * specific address, the address is input serially
- * 8 bits at a time. This structure member is used
- * by the read/write routines as a loop index for
- * shifting the address out 8 bits at a time.
- *
- * erasesize - size of an erase block in the flash device.
- */
-struct nand_flash_dev {
- char * name;
- int manufacture_id;
- int model_id;
- int chipshift;
- char page256;
- char pageadrlen;
- unsigned long erasesize;
- int bus16;
-};
+#define NAND_MFR_TOSHIBA 0x98
+#define NAND_MFR_SAMSUNG 0xec
+#endif
#endif /* __MTD_DOC2000_H__ */
int wait_pattern;
int (*dev_ready)(void);
int chip_delay;
+
+ /* no need to fill */
+ int last_ctrl;
};
extern int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun);
--- /dev/null
+/*
+ * $Id: inftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $
+ *
+ * Parts of INFTL headers shared with userspace
+ *
+ */
+
+#ifndef __MTD_INFTL_USER_H__
+#define __MTD_INFTL_USER_H__
+
+#define OSAK_VERSION 0x5120
+#define PERCENTUSED 98
+
+#define SECTORSIZE 512
+
+/* Block Control Information */
+
+struct inftl_bci {
+ uint8_t ECCsig[6];
+ uint8_t Status;
+ uint8_t Status1;
+} __attribute__((packed));
+
+struct inftl_unithead1 {
+ uint16_t virtualUnitNo;
+ uint16_t prevUnitNo;
+ uint8_t ANAC;
+ uint8_t NACs;
+ uint8_t parityPerField;
+ uint8_t discarded;
+} __attribute__((packed));
+
+struct inftl_unithead2 {
+ uint8_t parityPerField;
+ uint8_t ANAC;
+ uint16_t prevUnitNo;
+ uint16_t virtualUnitNo;
+ uint8_t NACs;
+ uint8_t discarded;
+} __attribute__((packed));
+
+struct inftl_unittail {
+ uint8_t Reserved[4];
+ uint16_t EraseMark;
+ uint16_t EraseMark1;
+} __attribute__((packed));
+
+union inftl_uci {
+ struct inftl_unithead1 a;
+ struct inftl_unithead2 b;
+ struct inftl_unittail c;
+};
+
+struct inftl_oob {
+ struct inftl_bci b;
+ union inftl_uci u;
+};
+
+
+/* INFTL Media Header */
+
+struct INFTLPartition {
+ __u32 virtualUnits;
+ __u32 firstUnit;
+ __u32 lastUnit;
+ __u32 flags;
+ __u32 spareUnits;
+ __u32 Reserved0;
+ __u32 Reserved1;
+} __attribute__((packed));
+
+struct INFTLMediaHeader {
+ char bootRecordID[8];
+ __u32 NoOfBootImageBlocks;
+ __u32 NoOfBinaryPartitions;
+ __u32 NoOfBDTLPartitions;
+ __u32 BlockMultiplierBits;
+ __u32 FormatFlags;
+ __u32 OsakVersion;
+ __u32 PercentUsed;
+ struct INFTLPartition Partitions[4];
+} __attribute__((packed));
+
+/* Partition flag types */
+#define INFTL_BINARY 0x20000000
+#define INFTL_BDTL 0x40000000
+#define INFTL_LAST 0x80000000
+
+#endif /* __MTD_INFTL_USER_H__ */
--- /dev/null
+/*
+ * $Id: jffs2-user.h,v 1.1 2004/05/05 11:57:54 dwmw2 Exp $
+ *
+ * JFFS2 definitions for use in user space only
+ */
+
+#ifndef __JFFS2_USER_H__
+#define __JFFS2_USER_H__
+
+/* This file is blessed for inclusion by userspace */
+#include <linux/jffs2.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#undef cpu_to_je16
+#undef cpu_to_je32
+#undef cpu_to_jemode
+#undef je16_to_cpu
+#undef je32_to_cpu
+#undef jemode_to_cpu
+
+extern int target_endian;
+
+#define t16(x) ({ uint16_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); })
+#define t32(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); })
+
+#define cpu_to_je16(x) ((jint16_t){t16(x)})
+#define cpu_to_je32(x) ((jint32_t){t32(x)})
+#define cpu_to_jemode(x) ((jmode_t){t32(x)})
+
+#define je16_to_cpu(x) (t16((x).v16))
+#define je32_to_cpu(x) (t32((x).v32))
+#define jemode_to_cpu(x) (t32((x).m))
+
+#endif /* __JFFS2_USER_H__ */
/*
- * $Id: mtd-abi.h,v 1.7 2004/11/23 15:37:32 gleixner Exp $
+ * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
*
* Portions of MTD ABI definition which are shared by kernel and user space
*/
#ifndef __MTD_ABI_H__
#define __MTD_ABI_H__
+#if 1
+#include <linux/mtd/compat.h>
+#endif
+
struct erase_info_user {
uint32_t start;
uint32_t length;
struct mtd_oob_buf {
uint32_t start;
uint32_t length;
- unsigned char *ptr;
+ unsigned char __user *ptr;
};
#define MTD_ABSENT 0
#define MTD_ROM 2
#define MTD_NORFLASH 3
#define MTD_NANDFLASH 4
-#define MTD_PEROM 5
-#define MTD_OTHER 14
-#define MTD_UNKNOWN 15
-
-#define MTD_CLEAR_BITS 1 /* Bits can be cleared (flash) */
-#define MTD_SET_BITS 2 /* Bits can be set */
-#define MTD_ERASEABLE 4 /* Has an erase function */
-#define MTD_WRITEB_WRITEABLE 8 /* Direct IO is possible */
-#define MTD_VOLATILE 16 /* Set for RAMs */
-#define MTD_XIP 32 /* eXecute-In-Place possible */
-#define MTD_OOB 64 /* Out-of-band data (NAND flash) */
-#define MTD_ECC 128 /* Device capable of automatic ECC */
-#define MTD_NO_VIRTBLOCKS 256 /* Virtual blocks not allowed */
+#define MTD_DATAFLASH 6
+#define MTD_UBIVOLUME 7
+
+#define MTD_WRITEABLE 0x400 /* Device is writeable */
+#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
+#define MTD_NO_ERASE 0x1000 /* No erase necessary */
+#define MTD_STUPID_LOCK 0x2000 /* Always locked after reset */
/* Some common devices / combinations of capabilities */
#define MTD_CAP_ROM 0
-#define MTD_CAP_RAM (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
-#define MTD_CAP_NORFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE)
-#define MTD_CAP_NANDFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
-#define MTD_WRITEABLE (MTD_CLEAR_BITS|MTD_SET_BITS)
-
-
-/* Types of automatic ECC/Checksum available */
-#define MTD_ECC_NONE 0 /* No automatic ECC available */
-#define MTD_ECC_RS_DiskOnChip 1 /* Automatic ECC on DiskOnChip */
-#define MTD_ECC_SW 2 /* SW ECC for Toshiba & Samsung devices */
+#define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
+#define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE)
+#define MTD_CAP_NANDFLASH (MTD_WRITEABLE)
/* ECC byte placement */
#define MTD_NANDECC_OFF 0 /* Switch off ECC (Not recommended) */
#define MTD_NANDECC_PLACEONLY 3 /* Use the given placement in the structure (Do not store ecc result on read) */
#define MTD_NANDECC_AUTOPL_USR 4 /* Use the given autoplacement scheme rather than using the default */
+/* OTP mode selection */
+#define MTD_OTP_OFF 0
+#define MTD_OTP_FACTORY 1
+#define MTD_OTP_USER 2
+
struct mtd_info_user {
uint8_t type;
uint32_t flags;
- uint32_t size; /* Total size of the MTD */
+ uint32_t size; /* Total size of the MTD */
uint32_t erasesize;
- uint32_t oobblock; /* Size of OOB blocks (e.g. 512) */
- uint32_t oobsize; /* Amount of OOB data per block (e.g. 16) */
+ uint32_t writesize;
+ uint32_t oobsize; /* Amount of OOB data per block (e.g. 16) */
+ /* The below two fields are obsolete and broken, do not use them
+ * (TODO: remove at some point) */
uint32_t ecctype;
uint32_t eccsize;
};
uint32_t regionindex;
};
-#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
-#define MEMERASE _IOW('M', 2, struct erase_info_user)
-#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
-#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
-#define MEMLOCK _IOW('M', 5, struct erase_info_user)
-#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
+struct otp_info {
+ uint32_t start;
+ uint32_t length;
+ uint32_t locked;
+};
+
+#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
+#define MEMERASE _IOW('M', 2, struct erase_info_user)
+#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
+#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
+#define MEMLOCK _IOW('M', 5, struct erase_info_user)
+#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
#define MEMGETREGIONCOUNT _IOR('M', 7, int)
#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user)
#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo)
#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo)
#define MEMGETBADBLOCK _IOW('M', 11, loff_t)
#define MEMSETBADBLOCK _IOW('M', 12, loff_t)
+#define OTPSELECT _IOR('M', 13, int)
+#define OTPGETREGIONCOUNT _IOW('M', 14, int)
+#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info)
+#define OTPLOCK _IOR('M', 16, struct otp_info)
+#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout)
+#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
+#define MTDFILEMODE _IO('M', 19)
+/*
+ * Obsolete legacy interface. Keep it in order not to break userspace
+ * interfaces
+ */
struct nand_oobinfo {
uint32_t useecc;
uint32_t eccbytes;
uint32_t eccpos[48];
};
+struct nand_oobfree {
+ uint32_t offset;
+ uint32_t length;
+};
+
+#define MTD_MAX_OOBFREE_ENTRIES 8
+/*
+ * ECC layout control structure. Exported to userspace for
+ * diagnosis and to allow creation of raw images
+ */
+struct nand_ecclayout {
+ uint32_t eccbytes;
+ uint32_t eccpos[64];
+ uint32_t oobavail;
+ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
+};
+
+/**
+ * struct mtd_ecc_stats - error correction stats
+ *
+ * @corrected: number of corrected bits
+ * @failed: number of uncorrectable errors
+ * @badblocks: number of bad blocks in this partition
+ * @bbtblocks: number of blocks reserved for bad block tables
+ */
+struct mtd_ecc_stats {
+ uint32_t corrected;
+ uint32_t failed;
+ uint32_t badblocks;
+ uint32_t bbtblocks;
+};
+
+/*
+ * Read/write file modes for access to MTD
+ */
+enum mtd_file_modes {
+ MTD_MODE_NORMAL = MTD_OTP_OFF,
+ MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
+ MTD_MODE_OTP_USER = MTD_OTP_USER,
+ MTD_MODE_RAW,
+};
+
#endif /* __MTD_ABI_H__ */
/*
- * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
+ * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $
*
* Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
*
#ifndef __MTD_MTD_H__
#define __MTD_MTD_H__
+
#include <linux/types.h>
#include <linux/mtd/mtd-abi.h>
-#define MAX_MTD_DEVICES 16
+#define MTD_CHAR_MAJOR 90
+#define MTD_BLOCK_MAJOR 31
+#define MAX_MTD_DEVICES 32
#define MTD_ERASE_PENDING 0x01
#define MTD_ERASING 0x02
#define MTD_ERASE_DONE 0x08
#define MTD_ERASE_FAILED 0x10
+/*
+ * Enumeration for NAND/OneNAND flash chip state
+ */
+enum {
+ FL_READY,
+ FL_READING,
+ FL_WRITING,
+ FL_ERASING,
+ FL_SYNCING,
+ FL_CACHEDPRG,
+ FL_RESETING,
+ FL_UNLOCKING,
+ FL_LOCKING,
+ FL_PM_SUSPENDED,
+};
+
/* If the erase fails, fail_addr might indicate exactly which block failed. If
fail_addr = 0xffffffff, the failure was not at the device level or was not
specific to any particular block. */
u_int32_t offset; /* At which this region starts, from the beginning of the MTD */
u_int32_t erasesize; /* For this region */
u_int32_t numblocks; /* Number of blocks of erasesize in this region */
+ unsigned long *lockmap; /* If keeping bitmap of locks */
+};
+
+/*
+ * oob operation modes
+ *
+ * MTD_OOB_PLACE: oob data are placed at the given offset
+ * MTD_OOB_AUTO: oob data are automatically placed at the free areas
+ * which are defined by the ecclayout
+ * MTD_OOB_RAW: mode to read raw data+oob in one chunk. The oob data
+ * is inserted into the data. Thats a raw image of the
+ * flash contents.
+ */
+typedef enum {
+ MTD_OOB_PLACE,
+ MTD_OOB_AUTO,
+ MTD_OOB_RAW,
+} mtd_oob_mode_t;
+
+/**
+ * struct mtd_oob_ops - oob operation operands
+ * @mode: operation mode
+ *
+ * @len: number of data bytes to write/read
+ *
+ * @retlen: number of data bytes written/read
+ *
+ * @ooblen: number of oob bytes to write/read
+ * @oobretlen: number of oob bytes written/read
+ * @ooboffs: offset of oob data in the oob area (only relevant when
+ * mode = MTD_OOB_PLACE)
+ * @datbuf: data buffer - if NULL only oob data are read/written
+ * @oobbuf: oob data buffer
+ *
+ * Note, it is allowed to read more then one OOB area at one go, but not write.
+ * The interface assumes that the OOB write requests program only one page's
+ * OOB area.
+ */
+struct mtd_oob_ops {
+ mtd_oob_mode_t mode;
+ size_t len;
+ size_t retlen;
+ size_t ooblen;
+ size_t oobretlen;
+ uint32_t ooboffs;
+ uint8_t *datbuf;
+ uint8_t *oobbuf;
};
struct mtd_info {
u_int32_t flags;
u_int32_t size; /* Total size of the MTD */
- /* "Major" erase size for the device. Naïve users may take this
+ /* "Major" erase size for the device. Naïve users may take this
* to be the only erase size available, or may use the more detailed
* information below if they desire
*/
u_int32_t erasesize;
+ /* Minimal writable flash unit size. In case of NOR flash it is 1 (even
+ * though individual bits can be cleared), in case of NAND flash it is
+ * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
+ * it is of ECC block size, etc. It is illegal to have writesize = 0.
+ * Any driver registering a struct mtd_info must ensure a writesize of
+ * 1 or larger.
+ */
+ u_int32_t writesize;
- u_int32_t oobblock; /* Size of OOB blocks (e.g. 512) */
u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */
- u_int32_t oobavail; /* Number of bytes in OOB area available for fs */
- u_int32_t ecctype;
- u_int32_t eccsize;
-
+ u_int32_t oobavail; /* Available OOB bytes per block */
/* Kernel-only stuff starts here. */
char *name;
int index;
- /* oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) */
- struct nand_oobinfo oobinfo;
+ /* ecc layout structure pointer - read only ! */
+ struct nand_ecclayout *ecclayout;
/* Data for variable erase regions. If numeraseregions is zero,
* it means that the whole device has erasesize as given above.
int numeraseregions;
struct mtd_erase_region_info *eraseregions;
- /* This really shouldn't be here. It can go away in 2.5 */
- u_int32_t bank_size;
-
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
/* This stuff for eXecute-In-Place */
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
- int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
- int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
-
- int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
- int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+ int (*read_oob) (struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops);
+ int (*write_oob) (struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops);
/*
* Methods to access the protection register area, present in some
* flash devices. The user data is one time programmable but the
* factory data is read only.
*/
- int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
+ int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
- /* This function is not yet implemented */
+ int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
+ int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+ int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
+
+/* XXX U-BOOT XXX */
#if 0
- /* kvec-based read/write methods. We need these especially for NAND flash,
- with its limited number of write cycles per erase.
+ /* kvec-based read/write methods.
NB: The 'count' parameter is the number of _vectors_, each of
which contains an (ofs, len) tuple.
*/
- int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
- int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from,
- size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
- int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,
- size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
#endif
+
/* Sync */
void (*sync) (struct mtd_info *mtd);
-#if 0
+
/* Chip-supported device locking */
int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
/* Power Management functions */
int (*suspend) (struct mtd_info *mtd);
void (*resume) (struct mtd_info *mtd);
-#endif
+
/* Bad block management functions */
int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
+/* XXX U-BOOT XXX */
+#if 0
+ struct notifier_block reboot_notifier; /* default mode before reboot */
+#endif
+
+ /* ECC status information */
+ struct mtd_ecc_stats ecc_stats;
+ /* Subpage shift (NAND) */
+ int subpage_sft;
+
void *priv;
struct module *owner;
int usecount;
+
+ /* If the driver is something smart, like UBI, it may need to maintain
+ * its own reference counting. The below functions are only for driver.
+ * The driver may register its callbacks. These callbacks are not
+ * supposed to be called by MTD users */
+ int (*get_device) (struct mtd_info *mtd);
+ void (*put_device) (struct mtd_info *mtd);
};
extern int del_mtd_device (struct mtd_info *mtd);
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
+extern struct mtd_info *get_mtd_device_nm(const char *name);
extern void put_mtd_device(struct mtd_info *mtd);
+/* XXX U-BOOT XXX */
#if 0
struct mtd_notifier {
void (*add)(struct mtd_info *mtd);
struct list_head list;
};
-
extern void register_mtd_user (struct mtd_notifier *new);
extern int unregister_mtd_user (struct mtd_notifier *old);
unsigned long count, loff_t from, size_t *retlen);
#endif
-#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
-#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
-#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
-#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
-#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
-#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
-#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
-#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
-#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
-#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
-#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
-#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0)
-
-
#ifdef CONFIG_MTD_PARTITIONS
void mtd_erase_callback(struct erase_info *instr);
#else
} while(0)
#else /* CONFIG_MTD_DEBUG */
#define MTDDEBUG(n, args...) do { } while(0)
-
#endif /* CONFIG_MTD_DEBUG */
#endif /* __MTD_MTD_H__ */
* linux/include/linux/mtd/nand.h
*
* Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
- * Steven J. Hill <sjhill@realitydiluted.com>
+ * Steven J. Hill <sjhill@realitydiluted.com>
* Thomas Gleixner <tglx@linutronix.de>
*
- * $Id: nand.h,v 1.68 2004/11/12 10:40:37 gleixner Exp $
+ * $Id: nand.h,v 1.74 2005/09/15 13:58:50 vwool Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * Info:
- * Contains standard defines and IDs for NAND flash devices
+ * Info:
+ * Contains standard defines and IDs for NAND flash devices
*
- * Changelog:
- * 01-31-2000 DMW Created
- * 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers
- * so it can be used by other NAND flash device
- * drivers. I also changed the copyright since none
- * of the original contents of this file are specific
- * to DoC devices. David can whack me with a baseball
- * bat later if I did something naughty.
- * 10-11-2000 SJH Added private NAND flash structure for driver
- * 10-24-2000 SJH Added prototype for 'nand_scan' function
- * 10-29-2001 TG changed nand_chip structure to support
- * hardwarespecific function for accessing control lines
- * 02-21-2002 TG added support for different read/write adress and
- * ready/busy line access function
- * 02-26-2002 TG added chip_delay to nand_chip structure to optimize
- * command delay times for different chips
- * 04-28-2002 TG OOB config defines moved from nand.c to avoid duplicate
- * defines in jffs2/wbuf.c
- * 08-07-2002 TG forced bad block location to byte 5 of OOB, even if
- * CONFIG_MTD_NAND_ECC_JFFS2 is not set
- * 08-10-2002 TG extensions to nand_chip structure to support HW-ECC
- *
- * 08-29-2002 tglx nand_chip structure: data_poi for selecting
- * internal / fs-driver buffer
- * support for 6byte/512byte hardware ECC
- * read_ecc, write_ecc extended for different oob-layout
- * oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
- * NAND_YAFFS_OOB
- * 11-25-2002 tglx Added Manufacturer code FUJITSU, NATIONAL
- * Split manufacturer and device ID structures
- *
- * 02-08-2004 tglx added option field to nand structure for chip anomalities
- * 05-25-2004 tglx added bad block table support, ST-MICRO manufacturer id
- * update of nand_chip structure description
+ * Changelog:
+ * See git changelog.
*/
#ifndef __LINUX_MTD_NAND_H
#define __LINUX_MTD_NAND_H
-#include <linux/mtd/compat.h>
+/* XXX U-BOOT XXX */
+#if 0
+#include <linux/wait.h>
+#include <linux/spinlock.h>
#include <linux/mtd/mtd.h>
+#endif
+
+#include "config.h"
+
+#include "linux/mtd/compat.h"
+#include "linux/mtd/mtd.h"
+
struct mtd_info;
/* Scan and identify a NAND device */
extern int nand_scan (struct mtd_info *mtd, int max_chips);
+/* Separate phases of nand_scan(), allowing board driver to intervene
+ * and override command or ECC setup according to flash type */
+extern int nand_scan_ident(struct mtd_info *mtd, int max_chips);
+extern int nand_scan_tail(struct mtd_info *mtd);
+
/* Free resources held by the NAND device */
extern void nand_release (struct mtd_info *mtd);
-/* Read raw data from the device without ECC */
-extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
+/* Internal helper for board drivers which need to override command function */
+extern void nand_wait_ready(struct mtd_info *mtd);
+/* The maximum number of NAND chips in an array */
+#ifndef NAND_MAX_CHIPS
+#define NAND_MAX_CHIPS 8
+#endif
/* This constant declares the max. oobsize / page, which
* is supported now. If you add a chip with bigger oobsize/page
* adjust this accordingly.
*/
-#define NAND_MAX_OOBSIZE 64
+#define NAND_MAX_OOBSIZE 128
+#define NAND_MAX_PAGESIZE 4096
/*
* Constants for hardware specific CLE/ALE/NCE function
-*/
+ *
+ * These are bits which can be or'ed to set/clear multiple
+ * bits in one go.
+ */
/* Select the chip by setting nCE to low */
-#define NAND_CTL_SETNCE 1
-/* Deselect the chip by setting nCE to high */
-#define NAND_CTL_CLRNCE 2
+#define NAND_NCE 0x01
/* Select the command latch by setting CLE to high */
-#define NAND_CTL_SETCLE 3
-/* Deselect the command latch by setting CLE to low */
-#define NAND_CTL_CLRCLE 4
+#define NAND_CLE 0x02
/* Select the address latch by setting ALE to high */
-#define NAND_CTL_SETALE 5
-/* Deselect the address latch by setting ALE to low */
-#define NAND_CTL_CLRALE 6
-/* Set write protection by setting WP to high. Not used! */
-#define NAND_CTL_SETWP 7
-/* Clear write protection by setting WP to low. Not used! */
-#define NAND_CTL_CLRWP 8
+#define NAND_ALE 0x04
+
+#define NAND_CTRL_CLE (NAND_NCE | NAND_CLE)
+#define NAND_CTRL_ALE (NAND_NCE | NAND_ALE)
+#define NAND_CTRL_CHANGE 0x80
/*
* Standard NAND flash commands
*/
#define NAND_CMD_READ0 0
#define NAND_CMD_READ1 1
+#define NAND_CMD_RNDOUT 5
#define NAND_CMD_PAGEPROG 0x10
#define NAND_CMD_READOOB 0x50
#define NAND_CMD_ERASE1 0x60
#define NAND_CMD_STATUS 0x70
#define NAND_CMD_STATUS_MULTI 0x71
#define NAND_CMD_SEQIN 0x80
+#define NAND_CMD_RNDIN 0x85
#define NAND_CMD_READID 0x90
#define NAND_CMD_ERASE2 0xd0
#define NAND_CMD_RESET 0xff
/* Extended commands for large page devices */
#define NAND_CMD_READSTART 0x30
+#define NAND_CMD_RNDOUTSTART 0xE0
#define NAND_CMD_CACHEDPROG 0x15
+/* Extended commands for AG-AND device */
+/*
+ * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but
+ * there is no way to distinguish that from NAND_CMD_READ0
+ * until the remaining sequence of commands has been completed
+ * so add a high order bit and mask it off in the command.
+ */
+#define NAND_CMD_DEPLETE1 0x100
+#define NAND_CMD_DEPLETE2 0x38
+#define NAND_CMD_STATUS_MULTI 0x71
+#define NAND_CMD_STATUS_ERROR 0x72
+/* multi-bank error status (banks 0-3) */
+#define NAND_CMD_STATUS_ERROR0 0x73
+#define NAND_CMD_STATUS_ERROR1 0x74
+#define NAND_CMD_STATUS_ERROR2 0x75
+#define NAND_CMD_STATUS_ERROR3 0x76
+#define NAND_CMD_STATUS_RESET 0x7f
+#define NAND_CMD_STATUS_CLEAR 0xff
+
+#define NAND_CMD_NONE -1
+
/* Status bits */
#define NAND_STATUS_FAIL 0x01
#define NAND_STATUS_FAIL_N1 0x02
/*
* Constants for ECC_MODES
*/
-
-/* No ECC. Usage is not recommended ! */
-#define NAND_ECC_NONE 0
-/* Software ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_SOFT 1
-/* Hardware ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_HW3_256 2
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW3_512 3
-/* Hardware ECC 6 byte ECC per 512 Byte data */
-#define NAND_ECC_HW6_512 4
-/* Hardware ECC 8 byte ECC per 512 Byte data */
-#define NAND_ECC_HW8_512 6
-/* Hardware ECC 12 byte ECC per 2048 Byte data */
-#define NAND_ECC_HW12_2048 7
+typedef enum {
+ NAND_ECC_NONE,
+ NAND_ECC_SOFT,
+ NAND_ECC_HW,
+ NAND_ECC_HW_SYNDROME,
+} nand_ecc_modes_t;
/*
* Constants for Hardware ECC
-*/
+ */
/* Reset Hardware ECC for read */
#define NAND_ECC_READ 0
/* Reset Hardware ECC for write */
/* Enable Hardware ECC before syndrom is read back from flash */
#define NAND_ECC_READSYN 2
+/* Bit mask for flags passed to do_nand_read_ecc */
+#define NAND_GET_DEVICE 0x80
+
+
/* Option constants for bizarre disfunctionality and real
* features
*/
/* Chip has a array of 4 pages which can be read without
* additional ready /busy waits */
#define NAND_4PAGE_ARRAY 0x00000040
+/* Chip requires that BBT is periodically rewritten to prevent
+ * bits from adjacent blocks from 'leaking' in altering data.
+ * This happens with the Renesas AG-AND chips, possibly others. */
+#define BBT_AUTO_REFRESH 0x00000080
+/* Chip does not require ready check on read. True
+ * for all large page devices, as they do not support
+ * autoincrement.*/
+#define NAND_NO_READRDY 0x00000100
+/* Chip does not allow subpage writes */
+#define NAND_NO_SUBPAGE_WRITE 0x00000200
+
/* Options valid for Samsung large page devices */
#define NAND_SAMSUNG_LP_OPTIONS \
/* Use a flash based bad block table. This option is passed to the
* default bad block table function. */
#define NAND_USE_FLASH_BBT 0x00010000
-/* The hw ecc generator provides a syndrome instead a ecc value on read
- * This can only work if we have the ecc bytes directly behind the
- * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
-#define NAND_HWECC_SYNDROME 0x00020000
-
-
+/* This option skips the bbt scan during initialization. */
+#define NAND_SKIP_BBTSCAN 0x00020000
+/* This option is defined if the board driver allocates its own buffers
+ (e.g. because it needs them DMA-coherent */
+#define NAND_OWN_BUFFERS 0x00040000
/* Options set by nand scan */
-/* Nand scan has allocated oob_buf */
-#define NAND_OOBBUF_ALLOC 0x40000000
-/* Nand scan has allocated data_buf */
-#define NAND_DATABUF_ALLOC 0x80000000
+/* bbt has already been read */
+#define NAND_BBT_SCANNED 0x40000000
+/* Nand scan has allocated controller struct */
+#define NAND_CONTROLLER_ALLOC 0x80000000
-
-/*
- * nand_state_t - chip states
- * Enumeration for NAND flash chip state
- */
-typedef enum {
- FL_READY,
- FL_READING,
- FL_WRITING,
- FL_ERASING,
- FL_SYNCING,
- FL_CACHEDPRG,
-} nand_state_t;
+/* Cell info constants */
+#define NAND_CI_CHIPNR_MSK 0x03
+#define NAND_CI_CELLTYPE_MSK 0x0C
/* Keep gcc happy */
struct nand_chip;
-#if 0
/**
- * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices
- * @lock: protection lock
+ * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
+ * @lock: protection lock
* @active: the mtd device which holds the controller currently
+ * @wq: wait queue to sleep on if a NAND operation is in progress
+ * used instead of the per chip wait queue when a hw controller is available
*/
struct nand_hw_control {
+/* XXX U-BOOT XXX */
+#if 0
spinlock_t lock;
+ wait_queue_head_t wq;
+#endif
struct nand_chip *active;
};
-#endif
+
+/**
+ * struct nand_ecc_ctrl - Control structure for ecc
+ * @mode: ecc mode
+ * @steps: number of ecc steps per page
+ * @size: data bytes per ecc step
+ * @bytes: ecc bytes per step
+ * @total: total number of ecc bytes per page
+ * @prepad: padding information for syndrome based ecc generators
+ * @postpad: padding information for syndrome based ecc generators
+ * @layout: ECC layout control struct pointer
+ * @hwctl: function to control hardware ecc generator. Must only
+ * be provided if an hardware ECC is available
+ * @calculate: function for ecc calculation or readback from ecc hardware
+ * @correct: function for ecc correction, matching to ecc generator (sw/hw)
+ * @read_page_raw: function to read a raw page without ECC
+ * @write_page_raw: function to write a raw page without ECC
+ * @read_page: function to read a page according to the ecc generator requirements
+ * @write_page: function to write a page according to the ecc generator requirements
+ * @read_oob: function to read chip OOB data
+ * @write_oob: function to write chip OOB data
+ */
+struct nand_ecc_ctrl {
+ nand_ecc_modes_t mode;
+ int steps;
+ int size;
+ int bytes;
+ int total;
+ int prepad;
+ int postpad;
+ struct nand_ecclayout *layout;
+ void (*hwctl)(struct mtd_info *mtd, int mode);
+ int (*calculate)(struct mtd_info *mtd,
+ const uint8_t *dat,
+ uint8_t *ecc_code);
+ int (*correct)(struct mtd_info *mtd, uint8_t *dat,
+ uint8_t *read_ecc,
+ uint8_t *calc_ecc);
+ int (*read_page_raw)(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ uint8_t *buf);
+ void (*write_page_raw)(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ const uint8_t *buf);
+ int (*read_page)(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ uint8_t *buf);
+ void (*write_page)(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ const uint8_t *buf);
+ int (*read_oob)(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ int page,
+ int sndcmd);
+ int (*write_oob)(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ int page);
+};
+
+/**
+ * struct nand_buffers - buffer structure for read/write
+ * @ecccalc: buffer for calculated ecc
+ * @ecccode: buffer for ecc read from flash
+ * @databuf: buffer for data - dynamically sized
+ *
+ * Do not change the order of buffers. databuf and oobrbuf must be in
+ * consecutive order.
+ */
+struct nand_buffers {
+ uint8_t ecccalc[NAND_MAX_OOBSIZE];
+ uint8_t ecccode[NAND_MAX_OOBSIZE];
+ uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
+};
/**
* struct nand_chip - NAND Private Flash Chip Data
* @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
* @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
* @read_byte: [REPLACEABLE] read one byte from the chip
- * @write_byte: [REPLACEABLE] write one byte to the chip
* @read_word: [REPLACEABLE] read one word from the chip
- * @write_word: [REPLACEABLE] write one word to the chip
* @write_buf: [REPLACEABLE] write data from the buffer to the chip
* @read_buf: [REPLACEABLE] read data from the chip into the buffer
* @verify_buf: [REPLACEABLE] verify buffer contents against the chip data
* @select_chip: [REPLACEABLE] select chip nr
* @block_bad: [REPLACEABLE] check, if the block is bad
* @block_markbad: [REPLACEABLE] mark the block bad
- * @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
+ * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling
+ * ALE/CLE/nCE. Also used to write command and address
* @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
* If set to NULL no access to ready/busy is available and the ready/busy information
* is read from the chip status register
* @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip
* @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready
- * @calculate_ecc: [REPLACEABLE] function for ecc calculation or readback from ecc hardware
- * @correct_data: [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
- * @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
- * be provided if a hardware ECC is available
+ * @ecc: [BOARDSPECIFIC] ecc control ctructure
+ * @buffers: buffer structure for read/write
+ * @hwcontrol: platform-specific hardware control structure
+ * @ops: oob operation operands
* @erase_cmd: [INTERN] erase command write function, selectable due to AND support
* @scan_bbt: [REPLACEABLE] function to scan bad block table
- * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines
- * @eccsize: [INTERN] databytes used per ecc-calculation
- * @eccbytes: [INTERN] number of ecc bytes per ecc-calculation step
- * @eccsteps: [INTERN] number of ecc calculation steps per page
* @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
- * @chip_lock: [INTERN] spinlock used to protect access to this structure and the chip
* @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress
* @state: [INTERN] the current state of the NAND device
+ * @oob_poi: poison value buffer
* @page_shift: [INTERN] number of address bits in a page (column address bits)
* @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock
* @bbt_erase_shift: [INTERN] number of address bits in a bbt entry
* @chip_shift: [INTERN] number of address bits in one chip
- * @data_buf: [INTERN] internal buffer for one page + oob
- * @oob_buf: [INTERN] oob buffer for one eraseblock
+ * @datbuf: [INTERN] internal buffer for one page + oob
+ * @oobbuf: [INTERN] oob buffer for one eraseblock
* @oobdirty: [INTERN] indicates that oob_buf must be reinitialized
* @data_poi: [INTERN] pointer to a data buffer
* @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
* special functionality. See the defines for further explanation
* @badblockpos: [INTERN] position of the bad block marker in the oob area
+ * @cellinfo: [INTERN] MLC/multichip data from chip ident
* @numchips: [INTERN] number of physical chips
* @chipsize: [INTERN] the size of one chip for multichip arrays
* @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
* @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf
- * @autooob: [REPLACEABLE] the default (auto)placement scheme
+ * @subpagesize: [INTERN] holds the subpagesize
+ * @ecclayout: [REPLACEABLE] the default ecc placement scheme
* @bbt: [INTERN] bad block table pointer
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup
* @bbt_md: [REPLACEABLE] bad block table mirror descriptor
* @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan
- * @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
+ * @controller: [REPLACEABLE] a pointer to a hardware controller structure
+ * which is shared among multiple independend devices
* @priv: [OPTIONAL] pointer to private chip date
+ * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks
+ * (determine if errors are correctable)
+ * @write_page: [REPLACEABLE] High-level page write function
*/
struct nand_chip {
void __iomem *IO_ADDR_R;
void __iomem *IO_ADDR_W;
- u_char (*read_byte)(struct mtd_info *mtd);
- void (*write_byte)(struct mtd_info *mtd, u_char byte);
+ uint8_t (*read_byte)(struct mtd_info *mtd);
u16 (*read_word)(struct mtd_info *mtd);
- void (*write_word)(struct mtd_info *mtd, u16 word);
-
- void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
- void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
- int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
+ void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+ void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
+ int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
void (*select_chip)(struct mtd_info *mtd, int chip);
int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
- void (*hwcontrol)(struct mtd_info *mtd, int cmd);
+ void (*cmd_ctrl)(struct mtd_info *mtd, int dat,
+ unsigned int ctrl);
int (*dev_ready)(struct mtd_info *mtd);
void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
- int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
- int (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
- int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
- void (*enable_hwecc)(struct mtd_info *mtd, int mode);
+ int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
void (*erase_cmd)(struct mtd_info *mtd, int page);
int (*scan_bbt)(struct mtd_info *mtd);
- int eccmode;
- int eccsize;
- int eccbytes;
- int eccsteps;
+ int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
+ int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int page, int cached, int raw);
+
int chip_delay;
-#if 0
- spinlock_t chip_lock;
- wait_queue_head_t wq;
- nand_state_t state;
-#endif
+ unsigned int options;
+
int page_shift;
int phys_erase_shift;
int bbt_erase_shift;
int chip_shift;
- u_char *data_buf;
- u_char *oob_buf;
- int oobdirty;
- u_char *data_poi;
- unsigned int options;
- int badblockpos;
int numchips;
unsigned long chipsize;
int pagemask;
int pagebuf;
- struct nand_oobinfo *autooob;
+ int subpagesize;
+ uint8_t cellinfo;
+ int badblockpos;
+
+ int state;
+
+ uint8_t *oob_poi;
+ struct nand_hw_control *controller;
+ struct nand_ecclayout *ecclayout;
+
+ struct nand_ecc_ctrl ecc;
+ struct nand_buffers *buffers;
+
+ struct nand_hw_control hwcontrol;
+
+ struct mtd_oob_ops ops;
+
uint8_t *bbt;
struct nand_bbt_descr *bbt_td;
struct nand_bbt_descr *bbt_md;
+
struct nand_bbt_descr *badblock_pattern;
- struct nand_hw_control *controller;
+
void *priv;
};
#define NAND_MFR_NATIONAL 0x8f
#define NAND_MFR_RENESAS 0x07
#define NAND_MFR_STMICRO 0x20
+#define NAND_MFR_HYNIX 0xad
#define NAND_MFR_MICRON 0x2c
/**
* struct nand_flash_dev - NAND Flash Device ID Structure
- *
* @name: Identify the device type
* @id: device ID code
* @pagesize: Pagesize in bytes. Either 256 or 512 or 0
* blocks is reserved at the end of the device where the tables are
* written.
* @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
- * bad) block in the stored bbt
+ * bad) block in the stored bbt
* @pattern: pattern to identify bad block table or factory marked good /
* bad blocks, can be NULL, if len = 0
*
int pages[NAND_MAX_CHIPS];
int offs;
int veroffs;
- uint8_t version[NAND_MAX_CHIPS];
+ uint8_t version[NAND_MAX_CHIPS];
int len;
int maxblocks;
int reserved_block_code;
- uint8_t *pattern;
+ uint8_t *pattern;
};
/* Options for the bad block table descriptors */
#define NAND_BBT_4BIT 0x00000004
#define NAND_BBT_8BIT 0x00000008
/* The bad block table is in the last good block of the device */
-#define NAND_BBT_LASTBLOCK 0x00000010
+#define NAND_BBT_LASTBLOCK 0x00000010
/* The bbt is at the given page, else we must scan for the bbt */
#define NAND_BBT_ABSPAGE 0x00000020
/* The bbt is at the given page, else we must scan for the bbt */
#define NAND_BBT_SCAN2NDPAGE 0x00004000
/* The maximum number of blocks to scan for a bbt */
-#define NAND_BBT_SCAN_MAXBLOCKS 4
+#define NAND_BBT_SCAN_MAXBLOCKS 4
-extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
-extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
-extern int nand_default_bbt (struct mtd_info *mtd);
-extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
-extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
+extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
+extern int nand_default_bbt(struct mtd_info *mtd);
+extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
+extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+ int allowbbt);
+extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, uint8_t * buf);
/*
* Constants for oob configuration
#define NAND_SMALL_BADBLOCK_POS 5
#define NAND_LARGE_BADBLOCK_POS 0
+/**
+ * struct platform_nand_chip - chip level device structure
+ * @nr_chips: max. number of chips to scan for
+ * @chip_offset: chip number offset
+ * @nr_partitions: number of partitions pointed to by partitions (or zero)
+ * @partitions: mtd partition list
+ * @chip_delay: R/B delay value in us
+ * @options: Option flags, e.g. 16bit buswidth
+ * @ecclayout: ecc layout info structure
+ * @part_probe_types: NULL-terminated array of probe types
+ * @priv: hardware controller specific settings
+ */
+struct platform_nand_chip {
+ int nr_chips;
+ int chip_offset;
+ int nr_partitions;
+ struct mtd_partition *partitions;
+ struct nand_ecclayout *ecclayout;
+ int chip_delay;
+ unsigned int options;
+ const char **part_probe_types;
+ void *priv;
+};
+
+/**
+ * struct platform_nand_ctrl - controller level device structure
+ * @hwcontrol: platform specific hardware control structure
+ * @dev_ready: platform specific function to read ready/busy pin
+ * @select_chip: platform specific chip select function
+ * @cmd_ctrl: platform specific function for controlling
+ * ALE/CLE/nCE. Also used to write command and address
+ * @priv: private data to transport driver specific settings
+ *
+ * All fields are optional and depend on the hardware driver requirements
+ */
+struct platform_nand_ctrl {
+ void (*hwcontrol)(struct mtd_info *mtd, int cmd);
+ int (*dev_ready)(struct mtd_info *mtd);
+ void (*select_chip)(struct mtd_info *mtd, int chip);
+ void (*cmd_ctrl)(struct mtd_info *mtd, int dat,
+ unsigned int ctrl);
+ void *priv;
+};
+
+/**
+ * struct platform_nand_data - container structure for platform-specific data
+ * @chip: chip level chip structure
+ * @ctrl: controller level device structure
+ */
+struct platform_nand_data {
+ struct platform_nand_chip chip;
+ struct platform_nand_ctrl ctrl;
+};
+
+/* Some helpers to access the data structures */
+static inline
+struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ return chip->priv;
+}
+
#endif /* __LINUX_MTD_NAND_H */
#ifndef __LINUX_MTD_NAND_IDS_H
#define __LINUX_MTD_NAND_IDS_H
-#ifndef CFG_NAND_LEGACY
+#ifndef CONFIG_NAND_LEGACY
#error This module is for the legacy NAND support
#endif
#ifndef __LINUX_MTD_NAND_LEGACY_H
#define __LINUX_MTD_NAND_LEGACY_H
-#ifndef CFG_NAND_LEGACY
+#ifndef CONFIG_NAND_LEGACY
#error This module is for the legacy NAND support
#endif
#define NAND_CMD_RESET 0xff
/*
- * Enumeration for NAND flash chip state
- */
-typedef enum {
- FL_READY,
- FL_READING,
- FL_WRITING,
- FL_ERASING,
- FL_SYNCING
-} nand_state_t;
-
-
-/*
* NAND Private Flash Chip Data
*
* Structure overview:
--- /dev/null
+/*
+ * $Id: nftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $
+ *
+ * Parts of NFTL headers shared with userspace
+ *
+ */
+
+#ifndef __MTD_NFTL_USER_H__
+#define __MTD_NFTL_USER_H__
+
+/* Block Control Information */
+
+struct nftl_bci {
+ unsigned char ECCSig[6];
+ uint8_t Status;
+ uint8_t Status1;
+}__attribute__((packed));
+
+/* Unit Control Information */
+
+struct nftl_uci0 {
+ uint16_t VirtUnitNum;
+ uint16_t ReplUnitNum;
+ uint16_t SpareVirtUnitNum;
+ uint16_t SpareReplUnitNum;
+} __attribute__((packed));
+
+struct nftl_uci1 {
+ uint32_t WearInfo;
+ uint16_t EraseMark;
+ uint16_t EraseMark1;
+} __attribute__((packed));
+
+struct nftl_uci2 {
+ uint16_t FoldMark;
+ uint16_t FoldMark1;
+ uint32_t unused;
+} __attribute__((packed));
+
+union nftl_uci {
+ struct nftl_uci0 a;
+ struct nftl_uci1 b;
+ struct nftl_uci2 c;
+};
+
+struct nftl_oob {
+ struct nftl_bci b;
+ union nftl_uci u;
+};
+
+/* NFTL Media Header */
+
+struct NFTLMediaHeader {
+ char DataOrgID[6];
+ uint16_t NumEraseUnits;
+ uint16_t FirstPhysicalEUN;
+ uint32_t FormattedSize;
+ unsigned char UnitSizeFactor;
+} __attribute__((packed));
+
+#define MAX_ERASE_ZONES (8192 - 512)
+
+#define ERASE_MARK 0x3c69
+#define SECTOR_FREE 0xff
+#define SECTOR_USED 0x55
+#define SECTOR_IGNORE 0x11
+#define SECTOR_DELETED 0x00
+
+#define FOLD_MARK_IN_PROGRESS 0x5555
+
+#define ZONE_GOOD 0xff
+#define ZONE_BAD_ORIGINAL 0
+#define ZONE_BAD_MARKED 7
+
+
+#endif /* __MTD_NFTL_USER_H__ */
-
-/* Defines for NAND Flash Translation Layer */
-/* (c) 1999 Machine Vision Holdings, Inc. */
-/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: nftl.h,v 1.10 2000/12/29 00:25:38 dwmw2 Exp $ */
+/*
+ * $Id: nftl.h,v 1.16 2004/06/30 14:49:00 dbrown Exp $
+ *
+ * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
+ */
#ifndef __MTD_NFTL_H__
#define __MTD_NFTL_H__
-/* Block Control Information */
-
-struct nftl_bci {
- unsigned char ECCSig[6];
- __u8 Status;
- __u8 Status1;
-}__attribute__((packed));
-
-/* Unit Control Information */
-
-struct nftl_uci0 {
- __u16 VirtUnitNum;
- __u16 ReplUnitNum;
- __u16 SpareVirtUnitNum;
- __u16 SpareReplUnitNum;
-} __attribute__((packed));
-
-struct nftl_uci1 {
- __u32 WearInfo;
- __u16 EraseMark;
- __u16 EraseMark1;
-} __attribute__((packed));
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/blktrans.h>
-struct nftl_uci2 {
- __u16 FoldMark;
- __u16 FoldMark1;
- __u32 unused;
-} __attribute__((packed));
-
-union nftl_uci {
- struct nftl_uci0 a;
- struct nftl_uci1 b;
- struct nftl_uci2 c;
-};
-
-struct nftl_oob {
- struct nftl_bci b;
- union nftl_uci u;
-};
-
-/* NFTL Media Header */
-
-struct NFTLMediaHeader {
- char DataOrgID[6];
- __u16 NumEraseUnits;
- __u16 FirstPhysicalEUN;
- __u32 FormattedSize;
- unsigned char UnitSizeFactor;
-} __attribute__((packed));
-
-#define MAX_ERASE_ZONES (8192 - 512)
-
-#define ERASE_MARK 0x3c69
-#define SECTOR_FREE 0xff
-#define SECTOR_USED 0x55
-#define SECTOR_IGNORE 0x11
-#define SECTOR_DELETED 0x00
-
-#define FOLD_MARK_IN_PROGRESS 0x5555
-
-#define ZONE_GOOD 0xff
-#define ZONE_BAD_ORIGINAL 0
-#define ZONE_BAD_MARKED 7
+#include <linux/mtd/nftl-user.h>
/* these info are used in ReplUnitTable */
-#define BLOCK_NIL 0xffff /* last block of a chain */
-#define BLOCK_FREE 0xfffe /* free block */
+#define BLOCK_NIL 0xffff /* last block of a chain */
+#define BLOCK_FREE 0xfffe /* free block */
#define BLOCK_NOTEXPLORED 0xfffd /* non explored block, only used during mounting */
-#define BLOCK_RESERVED 0xfffc /* bios block or bad block */
+#define BLOCK_RESERVED 0xfffc /* bios block or bad block */
struct NFTLrecord {
- struct DiskOnChip *mtd;
+ struct mtd_blktrans_dev mbd;
__u16 MediaUnit, SpareMediaUnit;
__u32 EraseSize;
struct NFTLMediaHeader MediaHdr;
unsigned char sectors;
unsigned short cylinders;
__u16 numvunits;
- __u16 lastEUN; /* should be suppressed */
+ __u16 lastEUN; /* should be suppressed */
__u16 numfreeEUNs;
__u16 LastFreeEUN; /* To speed up finding a free EUN */
- __u32 nr_sects;
int head,sect,cyl;
__u16 *EUNtable; /* [numvunits]: First EUN for each virtual unit */
__u16 *ReplUnitTable; /* [numEUNs]: ReplUnitNumber for each */
unsigned int nb_blocks; /* number of physical blocks */
unsigned int nb_boot_blocks; /* number of blocks used by the bios */
+ struct erase_info instr;
+ struct nand_ecclayout oobinfo;
};
+int NFTL_mount(struct NFTLrecord *s);
+int NFTL_formatblock(struct NFTLrecord *s, int block);
+
+#ifndef NFTL_MAJOR
+#define NFTL_MAJOR 93
+#endif
+
#define MAX_NFTLS 16
-#define MAX_SECTORS_PER_UNIT 32
+#define MAX_SECTORS_PER_UNIT 64
#define NFTL_PARTN_BITS 4
#endif /* __MTD_NFTL_H__ */
/* Note: The header order is impoertant */
#include <onenand_uboot.h>
+#include <linux/mtd/compat.h>
#include <linux/mtd/bbm.h>
#define MAX_BUFFERRAM 2
extern void onenand_release (struct mtd_info *mtd);
/**
- * onenand_state_t - chip states
- * Enumeration for OneNAND flash chip state
- */
-typedef enum {
- FL_READY,
- FL_READING,
- FL_WRITING,
- FL_ERASING,
- FL_SYNCING,
- FL_UNLOCKING,
- FL_LOCKING,
-} onenand_state_t;
-
-/**
* struct onenand_bufferram - OneNAND BufferRAM Data
* @param block block address in BufferRAM
* @param page page address in BufferRAM
unsigned short (*read_word) (void __iomem * addr);
void (*write_word) (unsigned short value, void __iomem * addr);
void (*mmcontrol) (struct mtd_info * mtd, int sync_read);
+ int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
+ int (*scan_bbt)(struct mtd_info *mtd);
spinlock_t chip_lock;
wait_queue_head_t wq;
- onenand_state_t state;
+ int state;
struct nand_oobinfo *autooob;
--- /dev/null
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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
+ *
+ * Authors: Artem Bityutskiy (Битюцкий Артём)
+ * Thomas Gleixner
+ * Frank Haverkamp
+ * Oliver Lohmann
+ * Andreas Arnez
+ */
+
+/*
+ * This file defines the layout of UBI headers and all the other UBI on-flash
+ * data structures. May be included by user-space.
+ */
+
+#ifndef __UBI_HEADER_H__
+#define __UBI_HEADER_H__
+
+#include <asm/byteorder.h>
+
+/* The version of UBI images supported by this implementation */
+#define UBI_VERSION 1
+
+/* The highest erase counter value supported by this implementation */
+#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
+
+/* The initial CRC32 value used when calculating CRC checksums */
+#define UBI_CRC32_INIT 0xFFFFFFFFU
+
+/* Erase counter header magic number (ASCII "UBI#") */
+#define UBI_EC_HDR_MAGIC 0x55424923
+/* Volume identifier header magic number (ASCII "UBI!") */
+#define UBI_VID_HDR_MAGIC 0x55424921
+
+/*
+ * Volume type constants used in the volume identifier header.
+ *
+ * @UBI_VID_DYNAMIC: dynamic volume
+ * @UBI_VID_STATIC: static volume
+ */
+enum {
+ UBI_VID_DYNAMIC = 1,
+ UBI_VID_STATIC = 2
+};
+
+/*
+ * Compatibility constants used by internal volumes.
+ *
+ * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
+ * to the flash
+ * @UBI_COMPAT_RO: attach this device in read-only mode
+ * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
+ * physical eraseblocks, don't allow the wear-leveling unit to move them
+ * @UBI_COMPAT_REJECT: reject this UBI image
+ */
+enum {
+ UBI_COMPAT_DELETE = 1,
+ UBI_COMPAT_RO = 2,
+ UBI_COMPAT_PRESERVE = 4,
+ UBI_COMPAT_REJECT = 5
+};
+
+/*
+ * ubi16_t/ubi32_t/ubi64_t - 16, 32, and 64-bit integers used in UBI on-flash
+ * data structures.
+ */
+typedef struct {
+ uint16_t int16;
+} __attribute__ ((packed)) ubi16_t;
+
+typedef struct {
+ uint32_t int32;
+} __attribute__ ((packed)) ubi32_t;
+
+typedef struct {
+ uint64_t int64;
+} __attribute__ ((packed)) ubi64_t;
+
+/*
+ * In this implementation of UBI uses the big-endian format for on-flash
+ * integers. The below are the corresponding conversion macros.
+ */
+#define cpu_to_ubi16(x) ((ubi16_t){__cpu_to_be16(x)})
+#define ubi16_to_cpu(x) ((uint16_t)__be16_to_cpu((x).int16))
+
+#define cpu_to_ubi32(x) ((ubi32_t){__cpu_to_be32(x)})
+#define ubi32_to_cpu(x) ((uint32_t)__be32_to_cpu((x).int32))
+
+#define cpu_to_ubi64(x) ((ubi64_t){__cpu_to_be64(x)})
+#define ubi64_to_cpu(x) ((uint64_t)__be64_to_cpu((x).int64))
+
+/* Sizes of UBI headers */
+#define UBI_EC_HDR_SIZE sizeof(struct ubi_ec_hdr)
+#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
+
+/* Sizes of UBI headers without the ending CRC */
+#define UBI_EC_HDR_SIZE_CRC (UBI_EC_HDR_SIZE - sizeof(ubi32_t))
+#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(ubi32_t))
+
+/**
+ * struct ubi_ec_hdr - UBI erase counter header.
+ * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
+ * @version: version of UBI implementation which is supposed to accept this
+ * UBI image
+ * @padding1: reserved for future, zeroes
+ * @ec: the erase counter
+ * @vid_hdr_offset: where the VID header starts
+ * @data_offset: where the user data start
+ * @padding2: reserved for future, zeroes
+ * @hdr_crc: erase counter header CRC checksum
+ *
+ * The erase counter header takes 64 bytes and has a plenty of unused space for
+ * future usage. The unused fields are zeroed. The @version field is used to
+ * indicate the version of UBI implementation which is supposed to be able to
+ * work with this UBI image. If @version is greater then the current UBI
+ * version, the image is rejected. This may be useful in future if something
+ * is changed radically. This field is duplicated in the volume identifier
+ * header.
+ *
+ * The @vid_hdr_offset and @data_offset fields contain the offset of the the
+ * volume identifier header and user data, relative to the beginning of the
+ * physical eraseblock. These values have to be the same for all physical
+ * eraseblocks.
+ */
+struct ubi_ec_hdr {
+ ubi32_t magic;
+ uint8_t version;
+ uint8_t padding1[3];
+ ubi64_t ec; /* Warning: the current limit is 31-bit anyway! */
+ ubi32_t vid_hdr_offset;
+ ubi32_t data_offset;
+ uint8_t padding2[36];
+ ubi32_t hdr_crc;
+} __attribute__ ((packed));
+
+/**
+ * struct ubi_vid_hdr - on-flash UBI volume identifier header.
+ * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
+ * @version: UBI implementation version which is supposed to accept this UBI
+ * image (%UBI_VERSION)
+ * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
+ * @copy_flag: if this logical eraseblock was copied from another physical
+ * eraseblock (for wear-leveling reasons)
+ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
+ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ * @vol_id: ID of this volume
+ * @lnum: logical eraseblock number
+ * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
+ * removed, kept only for not breaking older UBI users)
+ * @data_size: how many bytes of data this logical eraseblock contains
+ * @used_ebs: total number of used logical eraseblocks in this volume
+ * @data_pad: how many bytes at the end of this physical eraseblock are not
+ * used
+ * @data_crc: CRC checksum of the data stored in this logical eraseblock
+ * @padding1: reserved for future, zeroes
+ * @sqnum: sequence number
+ * @padding2: reserved for future, zeroes
+ * @hdr_crc: volume identifier header CRC checksum
+ *
+ * The @sqnum is the value of the global sequence counter at the time when this
+ * VID header was created. The global sequence counter is incremented each time
+ * UBI writes a new VID header to the flash, i.e. when it maps a logical
+ * eraseblock to a new physical eraseblock. The global sequence counter is an
+ * unsigned 64-bit integer and we assume it never overflows. The @sqnum
+ * (sequence number) is used to distinguish between older and newer versions of
+ * logical eraseblocks.
+ *
+ * There are 2 situations when there may be more then one physical eraseblock
+ * corresponding to the same logical eraseblock, i.e., having the same @vol_id
+ * and @lnum values in the volume identifier header. Suppose we have a logical
+ * eraseblock L and it is mapped to the physical eraseblock P.
+ *
+ * 1. Because UBI may erase physical eraseblocks asynchronously, the following
+ * situation is possible: L is asynchronously erased, so P is scheduled for
+ * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
+ * so P1 is written to, then an unclean reboot happens. Result - there are 2
+ * physical eraseblocks P and P1 corresponding to the same logical eraseblock
+ * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
+ * flash.
+ *
+ * 2. From time to time UBI moves logical eraseblocks to other physical
+ * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
+ * to P1, and an unclean reboot happens before P is physically erased, there
+ * are two physical eraseblocks P and P1 corresponding to L and UBI has to
+ * select one of them when the flash is attached. The @sqnum field says which
+ * PEB is the original (obviously P will have lower @sqnum) and the copy. But
+ * it is not enough to select the physical eraseblock with the higher sequence
+ * number, because the unclean reboot could have happen in the middle of the
+ * copying process, so the data in P is corrupted. It is also not enough to
+ * just select the physical eraseblock with lower sequence number, because the
+ * data there may be old (consider a case if more data was added to P1 after
+ * the copying). Moreover, the unclean reboot may happen when the erasure of P
+ * was just started, so it result in unstable P, which is "mostly" OK, but
+ * still has unstable bits.
+ *
+ * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
+ * copy. UBI also calculates data CRC when the data is moved and stores it at
+ * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
+ * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
+ * examined. If it is cleared, the situation* is simple and the newer one is
+ * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
+ * checksum is correct, this physical eraseblock is selected (P1). Otherwise
+ * the older one (P) is selected.
+ *
+ * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
+ * in the past. But it is not used anymore and we keep it in order to be able
+ * to deal with old UBI images. It will be removed at some point.
+ *
+ * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
+ * Internal volumes are not seen from outside and are used for various internal
+ * UBI purposes. In this implementation there is only one internal volume - the
+ * layout volume. Internal volumes are the main mechanism of UBI extensions.
+ * For example, in future one may introduce a journal internal volume. Internal
+ * volumes have their own reserved range of IDs.
+ *
+ * The @compat field is only used for internal volumes and contains the "degree
+ * of their compatibility". It is always zero for user volumes. This field
+ * provides a mechanism to introduce UBI extensions and to be still compatible
+ * with older UBI binaries. For example, if someone introduced a journal in
+ * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
+ * journal volume. And in this case, older UBI binaries, which know nothing
+ * about the journal volume, would just delete this volume and work perfectly
+ * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
+ * - it just ignores the Ext3fs journal.
+ *
+ * The @data_crc field contains the CRC checksum of the contents of the logical
+ * eraseblock if this is a static volume. In case of dynamic volumes, it does
+ * not contain the CRC checksum as a rule. The only exception is when the
+ * data of the physical eraseblock was moved by the wear-leveling unit, then
+ * the wear-leveling unit calculates the data CRC and stores it in the
+ * @data_crc field. And of course, the @copy_flag is %in this case.
+ *
+ * The @data_size field is used only for static volumes because UBI has to know
+ * how many bytes of data are stored in this eraseblock. For dynamic volumes,
+ * this field usually contains zero. The only exception is when the data of the
+ * physical eraseblock was moved to another physical eraseblock for
+ * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
+ * contents and uses both @data_crc and @data_size fields. In this case, the
+ * @data_size field contains data size.
+ *
+ * The @used_ebs field is used only for static volumes and indicates how many
+ * eraseblocks the data of the volume takes. For dynamic volumes this field is
+ * not used and always contains zero.
+ *
+ * The @data_pad is calculated when volumes are created using the alignment
+ * parameter. So, effectively, the @data_pad field reduces the size of logical
+ * eraseblocks of this volume. This is very handy when one uses block-oriented
+ * software (say, cramfs) on top of the UBI volume.
+ */
+struct ubi_vid_hdr {
+ ubi32_t magic;
+ uint8_t version;
+ uint8_t vol_type;
+ uint8_t copy_flag;
+ uint8_t compat;
+ ubi32_t vol_id;
+ ubi32_t lnum;
+ ubi32_t leb_ver; /* obsolete, to be removed, don't use */
+ ubi32_t data_size;
+ ubi32_t used_ebs;
+ ubi32_t data_pad;
+ ubi32_t data_crc;
+ uint8_t padding1[4];
+ ubi64_t sqnum;
+ uint8_t padding2[12];
+ ubi32_t hdr_crc;
+} __attribute__ ((packed));
+
+/* Internal UBI volumes count */
+#define UBI_INT_VOL_COUNT 1
+
+/*
+ * Starting ID of internal volumes. There is reserved room for 4096 internal
+ * volumes.
+ */
+#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
+
+/* The layout volume contains the volume table */
+
+#define UBI_LAYOUT_VOL_ID UBI_INTERNAL_VOL_START
+#define UBI_LAYOUT_VOLUME_EBS 2
+#define UBI_LAYOUT_VOLUME_NAME "layout volume"
+#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
+
+/* The maximum number of volumes per one UBI device */
+#define UBI_MAX_VOLUMES 128
+
+/* The maximum volume name length */
+#define UBI_VOL_NAME_MAX 127
+
+/* Size of the volume table record */
+#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
+
+/* Size of the volume table record without the ending CRC */
+#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(ubi32_t))
+
+/**
+ * struct ubi_vtbl_record - a record in the volume table.
+ * @reserved_pebs: how many physical eraseblocks are reserved for this volume
+ * @alignment: volume alignment
+ * @data_pad: how many bytes are unused at the end of the each physical
+ * eraseblock to satisfy the requested alignment
+ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ * @upd_marker: if volume update was started but not finished
+ * @name_len: volume name length
+ * @name: the volume name
+ * @padding2: reserved, zeroes
+ * @crc: a CRC32 checksum of the record
+ *
+ * The volume table records are stored in the volume table, which is stored in
+ * the layout volume. The layout volume consists of 2 logical eraseblock, each
+ * of which contains a copy of the volume table (i.e., the volume table is
+ * duplicated). The volume table is an array of &struct ubi_vtbl_record
+ * objects indexed by the volume ID.
+ *
+ * If the size of the logical eraseblock is large enough to fit
+ * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
+ * records. Otherwise, it contains as many records as it can fit (i.e., size of
+ * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
+ *
+ * The @upd_marker flag is used to implement volume update. It is set to %1
+ * before update and set to %0 after the update. So if the update operation was
+ * interrupted, UBI knows that the volume is corrupted.
+ *
+ * The @alignment field is specified when the volume is created and cannot be
+ * later changed. It may be useful, for example, when a block-oriented file
+ * system works on top of UBI. The @data_pad field is calculated using the
+ * logical eraseblock size and @alignment. The alignment must be multiple to the
+ * minimal flash I/O unit. If @alignment is 1, all the available space of
+ * the physical eraseblocks is used.
+ *
+ * Empty records contain all zeroes and the CRC checksum of those zeroes.
+ */
+struct ubi_vtbl_record {
+ ubi32_t reserved_pebs;
+ ubi32_t alignment;
+ ubi32_t data_pad;
+ uint8_t vol_type;
+ uint8_t upd_marker;
+ ubi16_t name_len;
+ uint8_t name[UBI_VOL_NAME_MAX+1];
+ uint8_t padding2[24];
+ ubi32_t crc;
+} __attribute__ ((packed));
+
+#endif /* !__UBI_HEADER_H__ */
--- /dev/null
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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
+ *
+ * Author: Artem Bityutskiy (Битюцкий Артём)
+ */
+
+#ifndef __UBI_USER_H__
+#define __UBI_USER_H__
+
+/*
+ * UBI volume creation
+ * ~~~~~~~~~~~~~~~~~~~
+ *
+ * UBI volumes are created via the %UBI_IOCMKVOL IOCTL command of UBI character
+ * device. A &struct ubi_mkvol_req object has to be properly filled and a
+ * pointer to it has to be passed to the IOCTL.
+ *
+ * UBI volume deletion
+ * ~~~~~~~~~~~~~~~~~~~
+ *
+ * To delete a volume, the %UBI_IOCRMVOL IOCTL command of the UBI character
+ * device should be used. A pointer to the 32-bit volume ID hast to be passed
+ * to the IOCTL.
+ *
+ * UBI volume re-size
+ * ~~~~~~~~~~~~~~~~~~
+ *
+ * To re-size a volume, the %UBI_IOCRSVOL IOCTL command of the UBI character
+ * device should be used. A &struct ubi_rsvol_req object has to be properly
+ * filled and a pointer to it has to be passed to the IOCTL.
+ *
+ * UBI volume update
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * Volume update should be done via the %UBI_IOCVOLUP IOCTL command of the
+ * corresponding UBI volume character device. A pointer to a 64-bit update
+ * size should be passed to the IOCTL. After then, UBI expects user to write
+ * this number of bytes to the volume character device. The update is finished
+ * when the claimed number of bytes is passed. So, the volume update sequence
+ * is something like:
+ *
+ * fd = open("/dev/my_volume");
+ * ioctl(fd, UBI_IOCVOLUP, &image_size);
+ * write(fd, buf, image_size);
+ * close(fd);
+ */
+
+/*
+ * When a new volume is created, users may either specify the volume number they
+ * want to create or to let UBI automatically assign a volume number using this
+ * constant.
+ */
+#define UBI_VOL_NUM_AUTO (-1)
+
+/* Maximum volume name length */
+#define UBI_MAX_VOLUME_NAME 127
+
+/* IOCTL commands of UBI character devices */
+
+#define UBI_IOC_MAGIC 'o'
+
+/* Create an UBI volume */
+#define UBI_IOCMKVOL _IOW(UBI_IOC_MAGIC, 0, struct ubi_mkvol_req)
+/* Remove an UBI volume */
+#define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t)
+/* Re-size an UBI volume */
+#define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req)
+
+/* IOCTL commands of UBI volume character devices */
+
+#define UBI_VOL_IOC_MAGIC 'O'
+
+/* Start UBI volume update */
+#define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t)
+/* An eraseblock erasure command, used for debugging, disabled by default */
+#define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t)
+
+/*
+ * UBI volume type constants.
+ *
+ * @UBI_DYNAMIC_VOLUME: dynamic volume
+ * @UBI_STATIC_VOLUME: static volume
+ */
+enum {
+ UBI_DYNAMIC_VOLUME = 3,
+ UBI_STATIC_VOLUME = 4
+};
+
+/**
+ * struct ubi_mkvol_req - volume description data structure used in
+ * volume creation requests.
+ * @vol_id: volume number
+ * @alignment: volume alignment
+ * @bytes: volume size in bytes
+ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ * @padding1: reserved for future, not used
+ * @name_len: volume name length
+ * @padding2: reserved for future, not used
+ * @name: volume name
+ *
+ * This structure is used by userspace programs when creating new volumes. The
+ * @used_bytes field is only necessary when creating static volumes.
+ *
+ * The @alignment field specifies the required alignment of the volume logical
+ * eraseblock. This means, that the size of logical eraseblocks will be aligned
+ * to this number, i.e.,
+ * (UBI device logical eraseblock size) mod (@alignment) = 0.
+ *
+ * To put it differently, the logical eraseblock of this volume may be slightly
+ * shortened in order to make it properly aligned. The alignment has to be
+ * multiple of the flash minimal input/output unit, or %1 to utilize the entire
+ * available space of logical eraseblocks.
+ *
+ * The @alignment field may be useful, for example, when one wants to maintain
+ * a block device on top of an UBI volume. In this case, it is desirable to fit
+ * an integer number of blocks in logical eraseblocks of this UBI volume. With
+ * alignment it is possible to update this volume using plane UBI volume image
+ * BLOBs, without caring about how to properly align them.
+ */
+struct ubi_mkvol_req {
+ int32_t vol_id;
+ int32_t alignment;
+ int64_t bytes;
+ int8_t vol_type;
+ int8_t padding1;
+ int16_t name_len;
+ int8_t padding2[4];
+ char name[UBI_MAX_VOLUME_NAME+1];
+} __attribute__ ((packed));
+
+/**
+ * struct ubi_rsvol_req - a data structure used in volume re-size requests.
+ * @vol_id: ID of the volume to re-size
+ * @bytes: new size of the volume in bytes
+ *
+ * Re-sizing is possible for both dynamic and static volumes. But while dynamic
+ * volumes may be re-sized arbitrarily, static volumes cannot be made to be
+ * smaller then the number of bytes they bear. To arbitrarily shrink a static
+ * volume, it must be wiped out first (by means of volume update operation with
+ * zero number of bytes).
+ */
+struct ubi_rsvol_req {
+ int64_t bytes;
+ int32_t vol_id;
+} __attribute__ ((packed));
+
+#endif /* __UBI_USER_H__ */
/* IO Control Register
*/
+#define IOCTL_MEM 0x000
+#define IOCTL_GP 0x004
+#define IOCTL_LPC_CLK 0x008
+#define IOCTL_LPC_OE 0x00C
+#define IOCTL_LPC_RWB 0x010
+#define IOCTL_LPC_ACK 0x014
+#define IOCTL_LPC_CS0 0x018
+#define IOCTL_NFC_CE0 0x01C
+#define IOCTL_LPC_CS1 0x020
+#define IOCTL_LPC_CS2 0x024
+#define IOCTL_LPC_AX03 0x028
+#define IOCTL_EMB_AX02 0x02C
+#define IOCTL_EMB_AX01 0x030
+#define IOCTL_EMB_AX00 0x034
+#define IOCTL_EMB_AD31 0x038
+#define IOCTL_EMB_AD30 0x03C
+#define IOCTL_EMB_AD29 0x040
+#define IOCTL_EMB_AD28 0x044
+#define IOCTL_EMB_AD27 0x048
+#define IOCTL_EMB_AD26 0x04C
+#define IOCTL_EMB_AD25 0x050
+#define IOCTL_EMB_AD24 0x054
+#define IOCTL_EMB_AD23 0x058
+#define IOCTL_EMB_AD22 0x05C
+#define IOCTL_EMB_AD21 0x060
+#define IOCTL_EMB_AD20 0x064
+#define IOCTL_EMB_AD19 0x068
+#define IOCTL_EMB_AD18 0x06C
+#define IOCTL_EMB_AD17 0x070
+#define IOCTL_EMB_AD16 0x074
+#define IOCTL_EMB_AD15 0x078
+#define IOCTL_EMB_AD14 0x07C
+#define IOCTL_EMB_AD13 0x080
+#define IOCTL_EMB_AD12 0x084
+#define IOCTL_EMB_AD11 0x088
+#define IOCTL_EMB_AD10 0x08C
+#define IOCTL_EMB_AD09 0x090
+#define IOCTL_EMB_AD08 0x094
+#define IOCTL_EMB_AD07 0x098
+#define IOCTL_EMB_AD06 0x09C
+#define IOCTL_EMB_AD05 0x0A0
+#define IOCTL_EMB_AD04 0x0A4
+#define IOCTL_EMB_AD03 0x0A8
+#define IOCTL_EMB_AD02 0x0AC
+#define IOCTL_EMB_AD01 0x0B0
+#define IOCTL_EMB_AD00 0x0B4
+#define IOCTL_PATA_CE1 0x0B8
+#define IOCTL_PATA_CE2 0x0BC
+#define IOCTL_PATA_ISOLATE 0x0C0
+#define IOCTL_PATA_IOR 0x0C4
+#define IOCTL_PATA_IOW 0x0C8
+#define IOCTL_PATA_IOCHRDY 0x0CC
+#define IOCTL_PATA_INTRQ 0x0D0
+#define IOCTL_PATA_DRQ 0x0D4
+#define IOCTL_PATA_DACK 0x0D8
+#define IOCTL_NFC_WP 0x0DC
+#define IOCTL_NFC_RB 0x0E0
+#define IOCTL_NFC_ALE 0x0E4
+#define IOCTL_NFC_CLE 0x0E8
+#define IOCTL_NFC_WE 0x0EC
+#define IOCTL_NFC_RE 0x0F0
+#define IOCTL_PCI_AD31 0x0F4
+#define IOCTL_PCI_AD30 0x0F8
+#define IOCTL_PCI_AD29 0x0FC
+#define IOCTL_PCI_AD28 0x100
+#define IOCTL_PCI_AD27 0x104
+#define IOCTL_PCI_AD26 0x108
+#define IOCTL_PCI_AD25 0x10C
+#define IOCTL_PCI_AD24 0x110
+#define IOCTL_PCI_AD23 0x114
+#define IOCTL_PCI_AD22 0x118
+#define IOCTL_PCI_AD21 0x11C
+#define IOCTL_PCI_AD20 0x120
+#define IOCTL_PCI_AD19 0x124
+#define IOCTL_PCI_AD18 0x128
+#define IOCTL_PCI_AD17 0x12C
+#define IOCTL_PCI_AD16 0x130
+#define IOCTL_PCI_AD15 0x134
+#define IOCTL_PCI_AD14 0x138
+#define IOCTL_PCI_AD13 0x13C
+#define IOCTL_PCI_AD12 0x140
+#define IOCTL_PCI_AD11 0x144
+#define IOCTL_PCI_AD10 0x148
+#define IOCTL_PCI_AD09 0x14C
+#define IOCTL_PCI_AD08 0x150
+#define IOCTL_PCI_AD07 0x154
+#define IOCTL_PCI_AD06 0x158
+#define IOCTL_PCI_AD05 0x15C
+#define IOCTL_PCI_AD04 0x160
+#define IOCTL_PCI_AD03 0x164
+#define IOCTL_PCI_AD02 0x168
+#define IOCTL_PCI_AD01 0x16C
+#define IOCTL_PCI_AD00 0x170
+#define IOCTL_PCI_CBE0 0x174
+#define IOCTL_PCI_CBE1 0x178
+#define IOCTL_PCI_CBE2 0x17C
+#define IOCTL_PCI_CBE3 0x180
+#define IOCTL_PCI_GNT2 0x184
+#define IOCTL_PCI_REQ2 0x188
+#define IOCTL_PCI_GNT1 0x18C
+#define IOCTL_PCI_REQ1 0x190
+#define IOCTL_PCI_GNT0 0x194
+#define IOCTL_PCI_REQ0 0x198
+#define IOCTL_PCI_INTA 0x19C
+#define IOCTL_PCI_CLK 0x1A0
+#define IOCTL_PCI_RST_OUT 0x1A4
+#define IOCTL_PCI_FRAME 0x1A8
+#define IOCTL_PCI_IDSEL 0x1AC
+#define IOCTL_PCI_DEVSEL 0x1B0
+#define IOCTL_PCI_IRDY 0x1B4
+#define IOCTL_PCI_TRDY 0x1B8
+#define IOCTL_PCI_STOP 0x1BC
+#define IOCTL_PCI_PAR 0x1C0
+#define IOCTL_PCI_PERR 0x1C4
+#define IOCTL_PCI_SERR 0x1C8
+#define IOCTL_SPDIF_TXCLK 0x1CC
+#define IOCTL_SPDIF_TX 0x1D0
+#define IOCTL_SPDIF_RX 0x1D4
+#define IOCTL_I2C0_SCL 0x1D8
+#define IOCTL_I2C0_SDA 0x1DC
+#define IOCTL_I2C1_SCL 0x1E0
+#define IOCTL_I2C1_SDA 0x1E4
+#define IOCTL_I2C2_SCL 0x1E8
+#define IOCTL_I2C2_SDA 0x1EC
+#define IOCTL_IRQ0 0x1F0
+#define IOCTL_IRQ1 0x1F4
+#define IOCTL_CAN1_TX 0x1F8
+#define IOCTL_CAN2_TX 0x1FC
+#define IOCTL_J1850_TX 0x200
+#define IOCTL_J1850_RX 0x204
+#define IOCTL_PSC_MCLK_IN 0x208
+#define IOCTL_PSC0_0 0x20C
+#define IOCTL_PSC0_1 0x210
+#define IOCTL_PSC0_2 0x214
+#define IOCTL_PSC0_3 0x218
+#define IOCTL_PSC0_4 0x21C
+#define IOCTL_PSC1_0 0x220
+#define IOCTL_PSC1_1 0x224
+#define IOCTL_PSC1_2 0x228
+#define IOCTL_PSC1_3 0x22C
+#define IOCTL_PSC1_4 0x230
+#define IOCTL_PSC2_0 0x234
+#define IOCTL_PSC2_1 0x238
+#define IOCTL_PSC2_2 0x23C
+#define IOCTL_PSC2_3 0x240
+#define IOCTL_PSC2_4 0x244
+#define IOCTL_PSC3_0 0x248
+#define IOCTL_PSC3_1 0x24C
+#define IOCTL_PSC3_2 0x250
+#define IOCTL_PSC3_3 0x254
+#define IOCTL_PSC3_4 0x258
+#define IOCTL_PSC4_0 0x25C
+#define IOCTL_PSC4_1 0x260
+#define IOCTL_PSC4_2 0x264
+#define IOCTL_PSC4_3 0x268
+#define IOCTL_PSC4_4 0x26C
+#define IOCTL_PSC5_0 0x270
+#define IOCTL_PSC5_1 0x274
+#define IOCTL_PSC5_2 0x278
+#define IOCTL_PSC5_3 0x27C
+#define IOCTL_PSC5_4 0x280
+#define IOCTL_PSC6_0 0x284
+#define IOCTL_PSC6_1 0x288
+#define IOCTL_PSC6_2 0x28C
+#define IOCTL_PSC6_3 0x290
+#define IOCTL_PSC6_4 0x294
+#define IOCTL_PSC7_0 0x298
+#define IOCTL_PSC7_1 0x29C
+#define IOCTL_PSC7_2 0x2A0
+#define IOCTL_PSC7_3 0x2A4
+#define IOCTL_PSC7_4 0x2A8
+#define IOCTL_PSC8_0 0x2AC
+#define IOCTL_PSC8_1 0x2B0
+#define IOCTL_PSC8_2 0x2B4
+#define IOCTL_PSC8_3 0x2B8
+#define IOCTL_PSC8_4 0x2BC
+#define IOCTL_PSC9_0 0x2C0
+#define IOCTL_PSC9_1 0x2C4
+#define IOCTL_PSC9_2 0x2C8
+#define IOCTL_PSC9_3 0x2CC
+#define IOCTL_PSC9_4 0x2D0
+#define IOCTL_PSC10_0 0x2D4
+#define IOCTL_PSC10_1 0x2D8
+#define IOCTL_PSC10_2 0x2DC
+#define IOCTL_PSC10_3 0x2E0
+#define IOCTL_PSC10_4 0x2E4
+#define IOCTL_PSC11_0 0x2E8
+#define IOCTL_PSC11_1 0x2EC
+#define IOCTL_PSC11_2 0x2F0
+#define IOCTL_PSC11_3 0x2F4
+#define IOCTL_PSC11_4 0x2F8
+#define IOCTL_HRESET 0x2FC
+#define IOCTL_SRESET 0x300
+#define IOCTL_CKSTP_OUT 0x304
+#define IOCTL_USB2_VBUS_PWR_FAULT 0x308
+#define IOCTL_USB2_VBUS_PWR_SELECT 0x30C
+#define IOCTL_USB2_PHY_DRVV_BUS 0x310
+
+#ifndef __ASSEMBLY__
+
+
+/* IO pin fields */
+#define IO_PIN_FMUX(v) ((v) << 7) /* pin function */
+#define IO_PIN_HOLD(v) ((v) << 5) /* hold time, pci only */
+#define IO_PIN_PUD(v) ((v) << 4) /* if PUE, 0=pull-down, 1=pull-up */
+#define IO_PIN_PUE(v) ((v) << 3) /* pull up/down enable */
+#define IO_PIN_ST(v) ((v) << 2) /* schmitt trigger */
+#define IO_PIN_DS(v) ((v)) /* slew rate */
+
+typedef struct iopin_t {
+ int p_offset; /* offset from IOCTL_MEM_OFFSET */
+ int nr_pins; /* number of pins to set this way */
+ int bit_or; /* or in the value instead of overwrite */
+ u_long val; /* value to write or or */
+}iopin_t;
+
+void iopin_initialize(iopin_t *,int);
+#endif
/* Indexes in regs array */
-#define MEM_IDX 0x00
-#define PATA_CE1_IDX 0x2e
-#define PATA_CE2_IDX 0x2f
-#define PATA_ISOLATE_IDX 0x30
-#define PATA_IOR_IDX 0x31
-#define PATA_IOW_IDX 0x32
-#define PATA_IOCHRDY_IDX 0x33
-#define PATA_INTRQ_IDX 0x34
-#define PATA_DRQ_IDX 0x35
-#define PATA_DACK_IDX 0x36
-#define SPDIF_TXCLOCK_IDX 0x73
-#define SPDIF_TX_IDX 0x74
-#define SPDIF_RX_IDX 0x75
-#define PSC0_0_IDX 0x83
-#define PSC0_1_IDX 0x84
-#define PSC0_2_IDX 0x85
-#define PSC0_3_IDX 0x86
-#define PSC0_4_IDX 0x87
-#define PSC1_0_IDX 0x88
-#define PSC1_1_IDX 0x89
-#define PSC1_2_IDX 0x8a
-#define PSC1_3_IDX 0x8b
-#define PSC1_4_IDX 0x8c
-#define PSC2_0_IDX 0x8d
-#define PSC2_1_IDX 0x8e
-#define PSC2_2_IDX 0x8f
-#define PSC2_3_IDX 0x90
-#define PSC2_4_IDX 0x91
-
-#define IOCTRL_FUNCMUX_SHIFT 7
-#define IOCTRL_FUNCMUX_FEC 1
-#define IOCTRL_MUX_FEC (IOCTRL_FUNCMUX_FEC << IOCTRL_FUNCMUX_SHIFT)
-
/* Set for DDR */
#define IOCTRL_MUX_DDR 0x00000036
/* IMMRBAR - Internal Memory Register Base Address
*/
+#ifndef CONFIG_DEFAULT_IMMR
#define CONFIG_DEFAULT_IMMR 0xFF400000 /* Default IMMR base address */
+#endif
#define IMMRBAR 0x0000 /* Register offset to immr */
#define IMMRBAR_BASE_ADDR 0xFFF00000 /* Base address mask */
#define IMMRBAR_RES ~(IMMRBAR_BASE_ADDR)
extern void nand_init(void);
-#ifndef CFG_NAND_LEGACY
+#ifndef CONFIG_NAND_LEGACY
#include <linux/mtd/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
};
typedef struct nand_write_options nand_write_options_t;
+typedef struct mtd_oob_ops mtd_oob_ops_t;
struct nand_read_options {
u_char *buffer; /* memory block in which read image is written*/
typedef struct nand_erase_options nand_erase_options_t;
-int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts);
-
-int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts);
+int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
+ u_char *buffer);
+int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
+ u_char *buffer);
int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
#define NAND_LOCK_STATUS_TIGHT 0x01
void board_nand_select_device(struct nand_chip *nand, int chip);
#endif
-#endif /* !CFG_NAND_LEGACY */
+__attribute__((noreturn)) void nand_boot(void);
+
+#endif /* !CONFIG_NAND_LEGACY */
#endif
extern int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
-extern void onenand_print_device_info(int device, int verbose);
+extern char *onenand_print_device_info(int device);
#endif /* __UBOOT_ONENAND_H */
#define dmasgc (DMA_DCR_BASE+0x23) /* DMA scatter/gather command register */
#define dmaadr (DMA_DCR_BASE+0x24) /* DMA address decode register */
-/******************************************************************************
- * Universal interrupt controller
- ******************************************************************************/
-#define UIC_SR 0x0 /* UIC status */
-#define UIC_ER 0x2 /* UIC enable */
-#define UIC_CR 0x3 /* UIC critical */
-#define UIC_PR 0x4 /* UIC polarity */
-#define UIC_TR 0x5 /* UIC triggering */
-#define UIC_MSR 0x6 /* UIC masked status */
-#define UIC_VR 0x7 /* UIC vector */
-#define UIC_VCR 0x8 /* UIC vector configuration */
-
-#define UIC_DCR_BASE 0xc0
-#define UIC0_DCR_BASE UIC_DCR_BASE
-#define uicsr (UIC_DCR_BASE+0x0) /* UIC status */
-#define uicsrs (UIC_DCR_BASE+0x1) /* UIC status set */
-#define uicer (UIC_DCR_BASE+0x2) /* UIC enable */
-#define uiccr (UIC_DCR_BASE+0x3) /* UIC critical */
-#define uicpr (UIC_DCR_BASE+0x4) /* UIC polarity */
-#define uictr (UIC_DCR_BASE+0x5) /* UIC triggering */
-#define uicmsr (UIC_DCR_BASE+0x6) /* UIC masked status */
-#define uicvr (UIC_DCR_BASE+0x7) /* UIC vector */
-#define uicvcr (UIC_DCR_BASE+0x8) /* UIC vector configuration */
-
-#if defined(CONFIG_405EX)
-#define uic0sr uicsr /* UIC status */
-#define uic0srs uicsrs /* UIC status set */
-#define uic0er uicer /* UIC enable */
-#define uic0cr uiccr /* UIC critical */
-#define uic0pr uicpr /* UIC polarity */
-#define uic0tr uictr /* UIC triggering */
-#define uic0msr uicmsr /* UIC masked status */
-#define uic0vr uicvr /* UIC vector */
-#define uic0vcr uicvcr /* UIC vector configuration*/
-
-#define UIC_DCR_BASE1 0xd0
-#define UIC1_DCR_BASE 0xd0
-#define uic1sr (UIC_DCR_BASE1+0x0) /* UIC status */
-#define uic1srs (UIC_DCR_BASE1+0x1) /* UIC status set */
-#define uic1er (UIC_DCR_BASE1+0x2) /* UIC enable */
-#define uic1cr (UIC_DCR_BASE1+0x3) /* UIC critical */
-#define uic1pr (UIC_DCR_BASE1+0x4) /* UIC polarity */
-#define uic1tr (UIC_DCR_BASE1+0x5) /* UIC triggering */
-#define uic1msr (UIC_DCR_BASE1+0x6) /* UIC masked status */
-#define uic1vr (UIC_DCR_BASE1+0x7) /* UIC vector */
-#define uic1vcr (UIC_DCR_BASE1+0x8) /* UIC vector configuration*/
-
-#define UIC_DCR_BASE2 0xe0
-#define UIC2_DCR_BASE 0xe0
-#define uic2sr (UIC_DCR_BASE2+0x0) /* UIC status */
-#define uic2srs (UIC_DCR_BASE2+0x1) /* UIC status set */
-#define uic2er (UIC_DCR_BASE2+0x2) /* UIC enable */
-#define uic2cr (UIC_DCR_BASE2+0x3) /* UIC critical */
-#define uic2pr (UIC_DCR_BASE2+0x4) /* UIC polarity */
-#define uic2tr (UIC_DCR_BASE2+0x5) /* UIC triggering */
-#define uic2msr (UIC_DCR_BASE2+0x6) /* UIC masked status */
-#define uic2vr (UIC_DCR_BASE2+0x7) /* UIC vector */
-#define uic2vcr (UIC_DCR_BASE2+0x8) /* UIC vector configuration*/
-#endif
-
-/*-----------------------------------------------------------------------------+
-| Universal interrupt controller interrupts
-+-----------------------------------------------------------------------------*/
-#if defined(CONFIG_405EZ)
-#define UIC_DMA0 0x80000000 /* DMA chan. 0 */
-#define UIC_DMA1 0x40000000 /* DMA chan. 1 */
-#define UIC_DMA2 0x20000000 /* DMA chan. 2 */
-#define UIC_DMA3 0x10000000 /* DMA chan. 3 */
-#define UIC_1588 0x08000000 /* IEEE 1588 network synchronization */
-#define UIC_UART0 0x04000000 /* UART 0 */
-#define UIC_UART1 0x02000000 /* UART 1 */
-#define UIC_CAN0 0x01000000 /* CAN 0 */
-#define UIC_CAN1 0x00800000 /* CAN 1 */
-#define UIC_SPI 0x00400000 /* SPI */
-#define UIC_IIC 0x00200000 /* IIC */
-#define UIC_CHT0 0x00100000 /* Chameleon timer high pri interrupt */
-#define UIC_CHT1 0x00080000 /* Chameleon timer high pri interrupt */
-#define UIC_USBH1 0x00040000 /* USB Host 1 */
-#define UIC_USBH2 0x00020000 /* USB Host 2 */
-#define UIC_USBDEV 0x00010000 /* USB Device */
-#define UIC_ENET 0x00008000 /* Ethernet interrupt status */
-#define UIC_ENET1 0x00008000 /* dummy define */
-#define UIC_EMAC_WAKE 0x00004000 /* EMAC wake up */
-
-#define UIC_MADMAL 0x00002000 /* Logical OR of following MadMAL int */
-#define UIC_MAL_SERR 0x00002000 /* MAL SERR */
-#define UIC_MAL_TXDE 0x00002000 /* MAL TXDE */
-#define UIC_MAL_RXDE 0x00002000 /* MAL RXDE */
-
-#define UIC_MAL_TXEOB 0x00001000 /* MAL TXEOB */
-#define UIC_MAL_TXEOB1 0x00000800 /* MAL TXEOB1 */
-#define UIC_MAL_RXEOB 0x00000400 /* MAL RXEOB */
-#define UIC_NAND 0x00000200 /* NAND Flash controller */
-#define UIC_ADC 0x00000100 /* ADC */
-#define UIC_DAC 0x00000080 /* DAC */
-#define UIC_OPB2PLB 0x00000040 /* OPB to PLB bridge interrupt */
-#define UIC_RESERVED0 0x00000020 /* Reserved */
-#define UIC_EXT0 0x00000010 /* External interrupt 0 */
-#define UIC_EXT1 0x00000008 /* External interrupt 1 */
-#define UIC_EXT2 0x00000004 /* External interrupt 2 */
-#define UIC_EXT3 0x00000002 /* External interrupt 3 */
-#define UIC_EXT4 0x00000001 /* External interrupt 4 */
-
-#elif defined(CONFIG_405EX)
-
-/* UIC 0 */
-#define UIC_U0 0x80000000 /* */
-#define UIC_U1 0x40000000 /* */
-#define UIC_IIC0 0x20000000 /* */
-#define UIC_PKA 0x10000000 /* */
-#define UIC_TRNG 0x08000000 /* */
-#define UIC_EBM 0x04000000 /* */
-#define UIC_BGI 0x02000000 /* */
-#define UIC_IIC1 0x01000000 /* */
-#define UIC_SPI 0x00800000 /* */
-#define UIC_EIRQ0 0x00400000 /**/
-#define UIC_MTE 0x00200000 /*MAL Tx EOB */
-#define UIC_MRE 0x00100000 /*MAL Rx EOB */
-#define UIC_DMA0 0x00080000 /* */
-#define UIC_DMA1 0x00040000 /* */
-#define UIC_DMA2 0x00020000 /* */
-#define UIC_DMA3 0x00010000 /* */
-#define UIC_PCIE0AL 0x00008000 /* */
-#define UIC_PCIE0VPD 0x00004000 /* */
-#define UIC_RPCIE0HRST 0x00002000 /* */
-#define UIC_FPCIE0HRST 0x00001000 /* */
-#define UIC_PCIE0TCR 0x00000800 /* */
-#define UIC_PCIEMSI0 0x00000400 /* */
-#define UIC_PCIEMSI1 0x00000200 /* */
-#define UIC_SECURITY 0x00000100 /* */
-#define UIC_ENET 0x00000080 /* */
-#define UIC_ENET1 0x00000040 /* */
-#define UIC_PCIEMSI2 0x00000020 /* */
-#define UIC_EIRQ4 0x00000010 /**/
-#define UICB0_UIC2NCI 0x00000008 /* */
-#define UICB0_UIC2CI 0x00000004 /* */
-#define UICB0_UIC1NCI 0x00000002 /* */
-#define UICB0_UIC1CI 0x00000001 /* */
-
-#define UICB0_ALL (UICB0_UIC1CI | UICB0_UIC1NCI | \
- UICB0_UIC1CI | UICB0_UIC2NCI)
-
-#define UIC_MAL_TXEOB UIC_MTE/* MAL TXEOB */
-#define UIC_MAL_RXEOB UIC_MRE/* MAL RXEOB */
-/* UIC 1 */
-#define UIC_MS 0x80000000 /* MAL SERR */
-#define UIC_MTDE 0x40000000 /* MAL TXDE */
-#define UIC_MRDE 0x20000000 /* MAL RXDE */
-#define UIC_PCIE0BMVC0 0x10000000 /* */
-#define UIC_PCIE0DCRERR 0x08000000 /* */
-#define UIC_EBC 0x04000000 /* */
-#define UIC_NDFC 0x02000000 /* */
-#define UIC_PCEI1DCRERR 0x01000000 /* */
-#define UIC_GPTCMPT8 0x00800000 /* */
-#define UIC_GPTCMPT9 0x00400000 /* */
-#define UIC_PCIE1AL 0x00200000 /* */
-#define UIC_PCIE1VPD 0x00100000 /* */
-#define UIC_RPCE1HRST 0x00080000 /* */
-#define UIC_FPCE1HRST 0x00040000 /* */
-#define UIC_PCIE1TCR 0x00020000 /* */
-#define UIC_PCIE1VC0 0x00010000 /* */
-#define UIC_GPTCMPT3 0x00008000 /* */
-#define UIC_GPTCMPT4 0x00004000 /* */
-#define UIC_EIRQ7 0x00002000 /* */
-#define UIC_EIRQ8 0x00001000 /* */
-#define UIC_EIRQ9 0x00000800 /* */
-#define UIC_GPTCMP5 0x00000400 /* */
-#define UIC_GPTCMP6 0x00000200 /* */
-#define UIC_GPTCMP7 0x00000100 /* */
-#define UIC_SROM 0x00000080 /* SERIAL ROM*/
-#define UIC_GPTDECPULS 0x00000040 /* GPT Decrement pulse*/
-#define UIC_EIRQ2 0x00000020 /* */
-#define UIC_EIRQ5 0x00000010 /* */
-#define UIC_EIRQ6 0x00000008 /* */
-#define UIC_EMAC0WAKE 0x00000004 /* */
-#define UIC_EIRQ1 0x00000002 /* */
-#define UIC_EMAC1WAKE 0x00000001 /* */
-#define UIC_MAL_SERR UIC_MS /* MAL SERR */
-#define UIC_MAL_TXDE UIC_MTDE /* MAL TXDE */
-#define UIC_MAL_RXDE UIC_MRDE /* MAL RXDE */
-/* UIC 2 */
-#define UIC_PCIE0INTA 0x80000000 /* PCIE0 INTA*/
-#define UIC_PCIE0INTB 0x40000000 /* PCIE0 INTB*/
-#define UIC_PCIE0INTC 0x20000000 /* PCIE0 INTC*/
-#define UIC_PCIE0INTD 0x10000000 /* PCIE0 INTD*/
-#define UIC_EIRQ3 0x08000000 /* External IRQ 3*/
-#define UIC_DDRMCUE 0x04000000 /* */
-#define UIC_DDRMCCE 0x02000000 /* */
-#define UIC_MALINTCOATX0 0x01000000 /* Interrupt coalecence TX0*/
-#define UIC_MALINTCOATX1 0x00800000 /* Interrupt coalecence TX1*/
-#define UIC_MALINTCOARX0 0x00400000 /* Interrupt coalecence RX0*/
-#define UIC_MALINTCOARX1 0x00200000 /* Interrupt coalecence RX1*/
-#define UIC_PCIE1INTA 0x00100000 /* PCIE0 INTA*/
-#define UIC_PCIE1INTB 0x00080000 /* PCIE0 INTB*/
-#define UIC_PCIE1INTC 0x00040000 /* PCIE0 INTC*/
-#define UIC_PCIE1INTD 0x00020000 /* PCIE0 INTD*/
-#define UIC_RPCIEMSI2 0x00010000 /* MSI level 2 Note this looks same as uic0-26*/
-#define UIC_PCIEMSI3 0x00008000 /* MSI level 2*/
-#define UIC_PCIEMSI4 0x00004000 /* MSI level 2*/
-#define UIC_PCIEMSI5 0x00002000 /* MSI level 2*/
-#define UIC_PCIEMSI6 0x00001000 /* MSI level 2*/
-#define UIC_PCIEMSI7 0x00000800 /* MSI level 2*/
-#define UIC_PCIEMSI8 0x00000400 /* MSI level 2*/
-#define UIC_PCIEMSI9 0x00000200 /* MSI level 2*/
-#define UIC_PCIEMSI10 0x00000100 /* MSI level 2*/
-#define UIC_PCIEMSI11 0x00000080 /* MSI level 2*/
-#define UIC_PCIEMSI12 0x00000040 /* MSI level 2*/
-#define UIC_PCIEMSI13 0x00000020 /* MSI level 2*/
-#define UIC_PCIEMSI14 0x00000010 /* MSI level 2*/
-#define UIC_PCIEMSI15 0x00000008 /* MSI level 2*/
-#define UIC_PLB4XAHB 0x00000004 /* PLBxAHB bridge*/
-#define UIC_USBWAKE 0x00000002 /* USB wakup*/
-#define UIC_USBOTG 0x00000001 /* USB OTG*/
-#define UIC_ETH0 UIC_ENET
-#define UIC_ETH1 UIC_ENET1
-
-#else /* !defined(CONFIG_405EZ) */
-
-#define UIC_UART0 0x80000000 /* UART 0 */
-#define UIC_UART1 0x40000000 /* UART 1 */
-#define UIC_IIC 0x20000000 /* IIC */
-#define UIC_EXT_MAST 0x10000000 /* External Master */
-#define UIC_PCI 0x08000000 /* PCI write to command reg */
-#define UIC_DMA0 0x04000000 /* DMA chan. 0 */
-#define UIC_DMA1 0x02000000 /* DMA chan. 1 */
-#define UIC_DMA2 0x01000000 /* DMA chan. 2 */
-#define UIC_DMA3 0x00800000 /* DMA chan. 3 */
-#define UIC_EMAC_WAKE 0x00400000 /* EMAC wake up */
-#define UIC_MAL_SERR 0x00200000 /* MAL SERR */
-#define UIC_MAL_TXEOB 0x00100000 /* MAL TXEOB */
-#define UIC_MAL_RXEOB 0x00080000 /* MAL RXEOB */
-#define UIC_MAL_TXDE 0x00040000 /* MAL TXDE */
-#define UIC_MAL_RXDE 0x00020000 /* MAL RXDE */
-#define UIC_ENET 0x00010000 /* Ethernet0 */
-#define UIC_ENET1 0x00004000 /* Ethernet1 on 405EP */
-#define UIC_ECC_CE 0x00004000 /* ECC Correctable Error on 405GP */
-#define UIC_EXT_PCI_SERR 0x00008000 /* External PCI SERR# */
-#define UIC_PCI_PM 0x00002000 /* PCI Power Management */
-#define UIC_EXT0 0x00000040 /* External interrupt 0 */
-#define UIC_EXT1 0x00000020 /* External interrupt 1 */
-#define UIC_EXT2 0x00000010 /* External interrupt 2 */
-#define UIC_EXT3 0x00000008 /* External interrupt 3 */
-#define UIC_EXT4 0x00000004 /* External interrupt 4 */
-#define UIC_EXT5 0x00000002 /* External interrupt 5 */
-#define UIC_EXT6 0x00000001 /* External interrupt 6 */
-#endif /* defined(CONFIG_405EZ) */
-
-/******************************************************************************
- * External Bus Controller (EBC)
- *****************************************************************************/
-
-/* Bank Configuration Register */
-#define EBC_BXCR_BAS_MASK PPC_REG_VAL(11, 0xFFF)
-#define EBC_BXCR_BAS_ENCODE(n) (((static_cast(unsigned long, n)) & \
- EBC_BXCR_BAS_MASK) << 0)
-#define EBC_BXCR_BS_MASK PPC_REG_VAL(14, 0x7)
-#define EBC_BXCR_BS_1MB PPC_REG_VAL(14, 0x0)
-#define EBC_BXCR_BS_2MB PPC_REG_VAL(14, 0x1)
-#define EBC_BXCR_BS_4MB PPC_REG_VAL(14, 0x2)
-#define EBC_BXCR_BS_8MB PPC_REG_VAL(14, 0x3)
-#define EBC_BXCR_BS_16MB PPC_REG_VAL(14, 0x4)
-#define EBC_BXCR_BS_32MB PPC_REG_VAL(14, 0x5)
-#define EBC_BXCR_BS_64MB PPC_REG_VAL(14, 0x6)
-#define EBC_BXCR_BS_128MB PPC_REG_VAL(14, 0x7)
-#define EBC_BXCR_BU_MASK PPC_REG_VAL(16, 0x3)
-#define EBC_BXCR_BU_NONE PPC_REG_VAL(16, 0x0)
-#define EBC_BXCR_BU_R PPC_REG_VAL(16, 0x1)
-#define EBC_BXCR_BU_W PPC_REG_VAL(16, 0x2)
-#define EBC_BXCR_BU_RW PPC_REG_VAL(16, 0x3)
-#define EBC_BXCR_BW_MASK PPC_REG_VAL(18, 0x3)
-#define EBC_BXCR_BW_8BIT PPC_REG_VAL(18, 0x0)
-#define EBC_BXCR_BW_16BIT PPC_REG_VAL(18, 0x1)
-#define EBC_BXCR_BW_32BIT PPC_REG_VAL(18, 0x3)
-
-/* Bank Access Parameter Register */
-#define EBC_BXAP_BME_ENABLED PPC_REG_VAL(0, 0x1)
-#define EBC_BXAP_BME_DISABLED PPC_REG_VAL(0, 0x0)
-#define EBC_BXAP_TWT_ENCODE(n) PPC_REG_VAL(8, \
- (static_cast(unsigned long, n)) \
- & 0xFF)
-#define EBC_BXAP_FWT_ENCODE(n) PPC_REG_VAL(5, \
- (static_cast(unsigned long, n)) \
- & 0x1F)
-#define EBC_BXAP_BWT_ENCODE(n) PPC_REG_VAL(8, \
- (static_cast(unsigned long, n)) \
- & 0x7)
-#define EBC_BXAP_BCE_DISABLE PPC_REG_VAL(9, 0x0)
-#define EBC_BXAP_BCE_ENABLE PPC_REG_VAL(9, 0x1)
-#define EBC_BXAP_BCT_MASK PPC_REG_VAL(11, 0x3)
-#define EBC_BXAP_BCT_2TRANS PPC_REG_VAL(11, 0x0)
-#define EBC_BXAP_BCT_4TRANS PPC_REG_VAL(11, 0x1)
-#define EBC_BXAP_BCT_8TRANS PPC_REG_VAL(11, 0x2)
-#define EBC_BXAP_BCT_16TRANS PPC_REG_VAL(11, 0x3)
-#define EBC_BXAP_CSN_ENCODE(n) PPC_REG_VAL(13, \
- (static_cast(unsigned long, n)) \
- & 0x3)
-#define EBC_BXAP_OEN_ENCODE(n) PPC_REG_VAL(15, \
- (static_cast(unsigned long, n)) \
- & 0x3)
-#define EBC_BXAP_WBN_ENCODE(n) PPC_REG_VAL(17, \
- (static_cast(unsigned long, n)) \
- & 0x3)
-#define EBC_BXAP_WBF_ENCODE(n) PPC_REG_VAL(19, \
- (static_cast(unsigned long, n)) \
- & 0x3)
-#define EBC_BXAP_TH_ENCODE(n) PPC_REG_VAL(22, \
- (static_cast(unsigned long, n)) \
- & 0x7)
-#define EBC_BXAP_RE_ENABLED PPC_REG_VAL(23, 0x1)
-#define EBC_BXAP_RE_DISABLED PPC_REG_VAL(23, 0x0)
-#define EBC_BXAP_SOR_DELAYED PPC_REG_VAL(24, 0x0)
-#define EBC_BXAP_SOR_NONDELAYED PPC_REG_VAL(24, 0x1)
-#define EBC_BXAP_BEM_WRITEONLY PPC_REG_VAL(25, 0x0)
-#define EBC_BXAP_BEM_RW PPC_REG_VAL(25, 0x1)
-#define EBC_BXAP_PEN_DISABLED PPC_REG_VAL(26, 0x0)
-#define EBC_BXAP_PEN_ENABLED PPC_REG_VAL(26, 0x1)
-
-/* Configuration Register */
-#define EBC_CFG_LE_MASK PPC_REG_VAL(0, 0x1)
-#define EBC_CFG_LE_UNLOCK PPC_REG_VAL(0, 0x0)
-#define EBC_CFG_LE_LOCK PPC_REG_VAL(0, 0x1)
-#define EBC_CFG_PTD_MASK PPC_REG_VAL(1, 0x1)
-#define EBC_CFG_PTD_ENABLE PPC_REG_VAL(1, 0x0)
-#define EBC_CFG_PTD_DISABLE PPC_REG_VAL(1, 0x1)
-#define EBC_CFG_RTC_MASK PPC_REG_VAL(4, 0x7)
-#define EBC_CFG_RTC_16PERCLK PPC_REG_VAL(4, 0x0)
-#define EBC_CFG_RTC_32PERCLK PPC_REG_VAL(4, 0x1)
-#define EBC_CFG_RTC_64PERCLK PPC_REG_VAL(4, 0x2)
-#define EBC_CFG_RTC_128PERCLK PPC_REG_VAL(4, 0x3)
-#define EBC_CFG_RTC_256PERCLK PPC_REG_VAL(4, 0x4)
-#define EBC_CFG_RTC_512PERCLK PPC_REG_VAL(4, 0x5)
-#define EBC_CFG_RTC_1024PERCLK PPC_REG_VAL(4, 0x6)
-#define EBC_CFG_RTC_2048PERCLK PPC_REG_VAL(4, 0x7)
-#define EBC_CFG_ATC_MASK PPC_REG_VAL(5, 0x1)
-#define EBC_CFG_ATC_HI PPC_REG_VAL(5, 0x0)
-#define EBC_CFG_ATC_PREVIOUS PPC_REG_VAL(5, 0x1)
-#define EBC_CFG_DTC_MASK PPC_REG_VAL(6, 0x1)
-#define EBC_CFG_DTC_HI PPC_REG_VAL(6, 0x0)
-#define EBC_CFG_DTC_PREVIOUS PPC_REG_VAL(6, 0x1)
-#define EBC_CFG_CTC_MASK PPC_REG_VAL(7, 0x1)
-#define EBC_CFG_CTC_HI PPC_REG_VAL(7, 0x0)
-#define EBC_CFG_CTC_PREVIOUS PPC_REG_VAL(7, 0x1)
-#define EBC_CFG_OEO_MASK PPC_REG_VAL(8, 0x1)
-#define EBC_CFG_OEO_DISABLE PPC_REG_VAL(8, 0x0)
-#define EBC_CFG_OEO_ENABLE PPC_REG_VAL(8, 0x1)
-#define EBC_CFG_EMC_MASK PPC_REG_VAL(9, 0x1)
-#define EBC_CFG_EMC_NONDEFAULT PPC_REG_VAL(9, 0x0)
-#define EBC_CFG_EMC_DEFAULT PPC_REG_VAL(9, 0x1)
-#define EBC_CFG_PME_MASK PPC_REG_VAL(14, 0x1)
-#define EBC_CFG_PME_DISABLE PPC_REG_VAL(14, 0x0)
-#define EBC_CFG_PME_ENABLE PPC_REG_VAL(14, 0x1)
-#define EBC_CFG_PMT_MASK PPC_REG_VAL(19, 0x1F)
-#define EBC_CFG_PMT_ENCODE(n) PPC_REG_VAL(19, \
- (static_cast(unsigned long, n)) \
- & 0x1F)
-#define EBC_CFG_PR_MASK PPC_REG_VAL(21, 0x3)
-#define EBC_CFG_PR_16 PPC_REG_VAL(21, 0x0)
-#define EBC_CFG_PR_32 PPC_REG_VAL(21, 0x1)
-#define EBC_CFG_PR_64 PPC_REG_VAL(21, 0x2)
-#define EBC_CFG_PR_128 PPC_REG_VAL(21, 0x3)
-
#ifndef CONFIG_405EP
/******************************************************************************
* Decompression Controller
#if defined(CONFIG_405EX)
#define SDR0_SRST 0x0200
+/*
+ * Software Reset Register
+ */
+#define SDR0_SRST_BGO PPC_REG_VAL(0, 1)
+#define SDR0_SRST_PLB4 PPC_REG_VAL(1, 1)
+#define SDR0_SRST_EBC PPC_REG_VAL(2, 1)
+#define SDR0_SRST_OPB PPC_REG_VAL(3, 1)
+#define SDR0_SRST_UART0 PPC_REG_VAL(4, 1)
+#define SDR0_SRST_UART1 PPC_REG_VAL(5, 1)
+#define SDR0_SRST_IIC0 PPC_REG_VAL(6, 1)
+#define SDR0_SRST_BGI PPC_REG_VAL(7, 1)
+#define SDR0_SRST_GPIO PPC_REG_VAL(8, 1)
+#define SDR0_SRST_GPT PPC_REG_VAL(9, 1)
+#define SDR0_SRST_DMC PPC_REG_VAL(10, 1)
+#define SDR0_SRST_RGMII PPC_REG_VAL(11, 1)
+#define SDR0_SRST_EMAC0 PPC_REG_VAL(12, 1)
+#define SDR0_SRST_EMAC1 PPC_REG_VAL(13, 1)
+#define SDR0_SRST_CPM PPC_REG_VAL(14, 1)
+#define SDR0_SRST_EPLL PPC_REG_VAL(15, 1)
+#define SDR0_SRST_UIC PPC_REG_VAL(16, 1)
+#define SDR0_SRST_UPRST PPC_REG_VAL(17, 1)
+#define SDR0_SRST_IIC1 PPC_REG_VAL(18, 1)
+#define SDR0_SRST_SCP PPC_REG_VAL(19, 1)
+#define SDR0_SRST_UHRST PPC_REG_VAL(20, 1)
+#define SDR0_SRST_DMA PPC_REG_VAL(21, 1)
+#define SDR0_SRST_DMAC PPC_REG_VAL(22, 1)
+#define SDR0_SRST_MAL PPC_REG_VAL(23, 1)
+#define SDR0_SRST_EBM PPC_REG_VAL(24, 1)
+#define SDR0_SRST_GPTR PPC_REG_VAL(25, 1)
+#define SDR0_SRST_PE0 PPC_REG_VAL(26, 1)
+#define SDR0_SRST_PE1 PPC_REG_VAL(27, 1)
+#define SDR0_SRST_CRYP PPC_REG_VAL(28, 1)
+#define SDR0_SRST_PKP PPC_REG_VAL(29, 1)
+#define SDR0_SRST_AHB PPC_REG_VAL(30, 1)
+#define SDR0_SRST_NDFC PPC_REG_VAL(31, 1)
+
#define sdr_uart0 0x0120 /* UART0 Config */
#define sdr_uart1 0x0121 /* UART1 Config */
#define sdr_mfr 0x4300 /* SDR0_MFR reg */
#define tbl 0x11c /* time base lower (supervisor)*/
#define tbu 0x11d /* time base upper (supervisor)*/
#define pir 0x11e /* processor id register */
-/*#define pvr 0x11f processor version register */
#define dbsr 0x130 /* debug status register */
#define dbcr0 0x134 /* debug control register 0 */
#define dbcr1 0x135 /* debug control register 1 */
#define sdr_sdstp6 0x4005
#define sdr_sdstp7 0x4007
-/******************************************************************************
- * PCI express defines
- ******************************************************************************/
-#define SDR0_PE0UTLSET1 0x00000300 /* PE0 Upper transaction layer conf setting */
-#define SDR0_PE0UTLSET2 0x00000301 /* PE0 Upper transaction layer conf setting 2 */
-#define SDR0_PE0DLPSET 0x00000302 /* PE0 Data link & logical physical configuration */
-#define SDR0_PE0LOOP 0x00000303 /* PE0 Loopback interface status */
-#define SDR0_PE0RCSSET 0x00000304 /* PE0 Reset, clock & shutdown setting */
-#define SDR0_PE0RCSSTS 0x00000305 /* PE0 Reset, clock & shutdown status */
-#define SDR0_PE0HSSSET1L0 0x00000306 /* PE0 HSS Control Setting 1: Lane 0 */
-#define SDR0_PE0HSSSET2L0 0x00000307 /* PE0 HSS Control Setting 2: Lane 0 */
-#define SDR0_PE0HSSSTSL0 0x00000308 /* PE0 HSS Control Status : Lane 0 */
-#define SDR0_PE0HSSSET1L1 0x00000309 /* PE0 HSS Control Setting 1: Lane 1 */
-#define SDR0_PE0HSSSET2L1 0x0000030A /* PE0 HSS Control Setting 2: Lane 1 */
-#define SDR0_PE0HSSSTSL1 0x0000030B /* PE0 HSS Control Status : Lane 1 */
-#define SDR0_PE0HSSSET1L2 0x0000030C /* PE0 HSS Control Setting 1: Lane 2 */
-#define SDR0_PE0HSSSET2L2 0x0000030D /* PE0 HSS Control Setting 2: Lane 2 */
-#define SDR0_PE0HSSSTSL2 0x0000030E /* PE0 HSS Control Status : Lane 2 */
-#define SDR0_PE0HSSSET1L3 0x0000030F /* PE0 HSS Control Setting 1: Lane 3 */
-#define SDR0_PE0HSSSET2L3 0x00000310 /* PE0 HSS Control Setting 2: Lane 3 */
-#define SDR0_PE0HSSSTSL3 0x00000311 /* PE0 HSS Control Status : Lane 3 */
-#define SDR0_PE0HSSSET1L4 0x00000312 /* PE0 HSS Control Setting 1: Lane 4 */
-#define SDR0_PE0HSSSET2L4 0x00000313 /* PE0 HSS Control Setting 2: Lane 4 */
-#define SDR0_PE0HSSSTSL4 0x00000314 /* PE0 HSS Control Status : Lane 4 */
-#define SDR0_PE0HSSSET1L5 0x00000315 /* PE0 HSS Control Setting 1: Lane 5 */
-#define SDR0_PE0HSSSET2L5 0x00000316 /* PE0 HSS Control Setting 2: Lane 5 */
-#define SDR0_PE0HSSSTSL5 0x00000317 /* PE0 HSS Control Status : Lane 5 */
-#define SDR0_PE0HSSSET1L6 0x00000318 /* PE0 HSS Control Setting 1: Lane 6 */
-#define SDR0_PE0HSSSET2L6 0x00000319 /* PE0 HSS Control Setting 2: Lane 6 */
-#define SDR0_PE0HSSSTSL6 0x0000031A /* PE0 HSS Control Status : Lane 6 */
-#define SDR0_PE0HSSSET1L7 0x0000031B /* PE0 HSS Control Setting 1: Lane 7 */
-#define SDR0_PE0HSSSET2L7 0x0000031C /* PE0 HSS Control Setting 2: Lane 7 */
-#define SDR0_PE0HSSSTSL7 0x0000031D /* PE0 HSS Control Status : Lane 7 */
-#define SDR0_PE0HSSSEREN 0x0000031E /* PE0 Serdes Transmitter Enable */
-#define SDR0_PE0LANEABCD 0x0000031F /* PE0 Lanes ABCD affectation */
-#define SDR0_PE0LANEEFGH 0x00000320 /* PE0 Lanes EFGH affectation */
-
-#define SDR0_PE1UTLSET1 0x00000340 /* PE1 Upper transaction layer conf setting */
-#define SDR0_PE1UTLSET2 0x00000341 /* PE1 Upper transaction layer conf setting 2 */
-#define SDR0_PE1DLPSET 0x00000342 /* PE1 Data link & logical physical configuration */
-#define SDR0_PE1LOOP 0x00000343 /* PE1 Loopback interface status */
-#define SDR0_PE1RCSSET 0x00000344 /* PE1 Reset, clock & shutdown setting */
-#define SDR0_PE1RCSSTS 0x00000345 /* PE1 Reset, clock & shutdown status */
-#define SDR0_PE1HSSSET1L0 0x00000346 /* PE1 HSS Control Setting 1: Lane 0 */
-#define SDR0_PE1HSSSET2L0 0x00000347 /* PE1 HSS Control Setting 2: Lane 0 */
-#define SDR0_PE1HSSSTSL0 0x00000348 /* PE1 HSS Control Status : Lane 0 */
-#define SDR0_PE1HSSSET1L1 0x00000349 /* PE1 HSS Control Setting 1: Lane 1 */
-#define SDR0_PE1HSSSET2L1 0x0000034A /* PE1 HSS Control Setting 2: Lane 1 */
-#define SDR0_PE1HSSSTSL1 0x0000034B /* PE1 HSS Control Status : Lane 1 */
-#define SDR0_PE1HSSSET1L2 0x0000034C /* PE1 HSS Control Setting 1: Lane 2 */
-#define SDR0_PE1HSSSET2L2 0x0000034D /* PE1 HSS Control Setting 2: Lane 2 */
-#define SDR0_PE1HSSSTSL2 0x0000034E /* PE1 HSS Control Status : Lane 2 */
-#define SDR0_PE1HSSSET1L3 0x0000034F /* PE1 HSS Control Setting 1: Lane 3 */
-#define SDR0_PE1HSSSET2L3 0x00000350 /* PE1 HSS Control Setting 2: Lane 3 */
-#define SDR0_PE1HSSSTSL3 0x00000351 /* PE1 HSS Control Status : Lane 3 */
-#define SDR0_PE1HSSSEREN 0x00000352 /* PE1 Serdes Transmitter Enable */
-#define SDR0_PE1LANEABCD 0x00000353 /* PE1 Lanes ABCD affectation */
-#define SDR0_PE2UTLSET1 0x00000370 /* PE2 Upper transaction layer conf setting */
-#define SDR0_PE2UTLSET2 0x00000371 /* PE2 Upper transaction layer conf setting 2 */
-#define SDR0_PE2DLPSET 0x00000372 /* PE2 Data link & logical physical configuration */
-#define SDR0_PE2LOOP 0x00000373 /* PE2 Loopback interface status */
-#define SDR0_PE2RCSSET 0x00000374 /* PE2 Reset, clock & shutdown setting */
-#define SDR0_PE2RCSSTS 0x00000375 /* PE2 Reset, clock & shutdown status */
-#define SDR0_PE2HSSSET1L0 0x00000376 /* PE2 HSS Control Setting 1: Lane 0 */
-#define SDR0_PE2HSSSET2L0 0x00000377 /* PE2 HSS Control Setting 2: Lane 0 */
-#define SDR0_PE2HSSSTSL0 0x00000378 /* PE2 HSS Control Status : Lane 0 */
-#define SDR0_PE2HSSSET1L1 0x00000379 /* PE2 HSS Control Setting 1: Lane 1 */
-#define SDR0_PE2HSSSET2L1 0x0000037A /* PE2 HSS Control Setting 2: Lane 1 */
-#define SDR0_PE2HSSSTSL1 0x0000037B /* PE2 HSS Control Status : Lane 1 */
-#define SDR0_PE2HSSSET1L2 0x0000037C /* PE2 HSS Control Setting 1: Lane 2 */
-#define SDR0_PE2HSSSET2L2 0x0000037D /* PE2 HSS Control Setting 2: Lane 2 */
-#define SDR0_PE2HSSSTSL2 0x0000037E /* PE2 HSS Control Status : Lane 2 */
-#define SDR0_PE2HSSSET1L3 0x0000037F /* PE2 HSS Control Setting 1: Lane 3 */
-#define SDR0_PE2HSSSET2L3 0x00000380 /* PE2 HSS Control Setting 2: Lane 3 */
-#define SDR0_PE2HSSSTSL3 0x00000381 /* PE2 HSS Control Status : Lane 3 */
-#define SDR0_PE2HSSSEREN 0x00000382 /* PE2 Serdes Transmitter Enable */
-#define SDR0_PE2LANEABCD 0x00000383 /* PE2 Lanes ABCD affectation */
-#define SDR0_PEGPLLSET1 0x000003A0 /* PE Pll LC Tank Setting1 */
-#define SDR0_PEGPLLSET2 0x000003A1 /* PE Pll LC Tank Setting2 */
-#define SDR0_PEGPLLSTS 0x000003A2 /* PE Pll LC Tank Status */
#endif /* CONFIG_440SPE */
/*-----------------------------------------------------------------------------
+----------------------------------------------------------------------------*/
#if defined (CONFIG_440GX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
#define L2_CACHE_BASE 0x030
#define l2_cache_cfg (L2_CACHE_BASE+0x00) /* L2 Cache Config */
#define l2_cache_cmd (L2_CACHE_BASE+0x01) /* L2 Cache Command */
/*-----------------------------------------------------------------------------
| Clocking, Power Management and Chip Control
+----------------------------------------------------------------------------*/
-#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
#define CNTRL_DCR_BASE 0x160
#else
#define CNTRL_DCR_BASE 0x0b0
#define cntrl1 (CNTRL_DCR_BASE+0x3a) /* Control 1 register */
/*-----------------------------------------------------------------------------
- | Universal interrupt controller
- +----------------------------------------------------------------------------*/
-#define UIC_SR 0x0 /* UIC status */
-#define UIC_ER 0x2 /* UIC enable */
-#define UIC_CR 0x3 /* UIC critical */
-#define UIC_PR 0x4 /* UIC polarity */
-#define UIC_TR 0x5 /* UIC triggering */
-#define UIC_MSR 0x6 /* UIC masked status */
-#define UIC_VR 0x7 /* UIC vector */
-#define UIC_VCR 0x8 /* UIC vector configuration */
-
-#define UIC0_DCR_BASE 0xc0
-#define uic0sr (UIC0_DCR_BASE+0x0) /* UIC0 status */
-#define uic0er (UIC0_DCR_BASE+0x2) /* UIC0 enable */
-#define uic0cr (UIC0_DCR_BASE+0x3) /* UIC0 critical */
-#define uic0pr (UIC0_DCR_BASE+0x4) /* UIC0 polarity */
-#define uic0tr (UIC0_DCR_BASE+0x5) /* UIC0 triggering */
-#define uic0msr (UIC0_DCR_BASE+0x6) /* UIC0 masked status */
-#define uic0vr (UIC0_DCR_BASE+0x7) /* UIC0 vector */
-#define uic0vcr (UIC0_DCR_BASE+0x8) /* UIC0 vector configuration */
-
-#define UIC1_DCR_BASE 0xd0
-#define uic1sr (UIC1_DCR_BASE+0x0) /* UIC1 status */
-#define uic1er (UIC1_DCR_BASE+0x2) /* UIC1 enable */
-#define uic1cr (UIC1_DCR_BASE+0x3) /* UIC1 critical */
-#define uic1pr (UIC1_DCR_BASE+0x4) /* UIC1 polarity */
-#define uic1tr (UIC1_DCR_BASE+0x5) /* UIC1 triggering */
-#define uic1msr (UIC1_DCR_BASE+0x6) /* UIC1 masked status */
-#define uic1vr (UIC1_DCR_BASE+0x7) /* UIC1 vector */
-#define uic1vcr (UIC1_DCR_BASE+0x8) /* UIC1 vector configuration */
-
-#if defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT)
-#define UIC2_DCR_BASE 0xe0
-#define uic2sr (UIC2_DCR_BASE+0x0) /* UIC2 status-Read Clear */
-#define uic2srs (UIC2_DCR_BASE+0x1) /* UIC2 status-Read Set */
-#define uic2er (UIC2_DCR_BASE+0x2) /* UIC2 enable */
-#define uic2cr (UIC2_DCR_BASE+0x3) /* UIC2 critical */
-#define uic2pr (UIC2_DCR_BASE+0x4) /* UIC2 polarity */
-#define uic2tr (UIC2_DCR_BASE+0x5) /* UIC2 triggering */
-#define uic2msr (UIC2_DCR_BASE+0x6) /* UIC2 masked status */
-#define uic2vr (UIC2_DCR_BASE+0x7) /* UIC2 vector */
-#define uic2vcr (UIC2_DCR_BASE+0x8) /* UIC2 vector configuration */
-
-#define UIC3_DCR_BASE 0xf0
-#define uic3sr (UIC3_DCR_BASE+0x0) /* UIC3 status-Read Clear */
-#define uic3srs (UIC3_DCR_BASE+0x1) /* UIC3 status-Read Set */
-#define uic3er (UIC3_DCR_BASE+0x2) /* UIC3 enable */
-#define uic3cr (UIC3_DCR_BASE+0x3) /* UIC3 critical */
-#define uic3pr (UIC3_DCR_BASE+0x4) /* UIC3 polarity */
-#define uic3tr (UIC3_DCR_BASE+0x5) /* UIC3 triggering */
-#define uic3msr (UIC3_DCR_BASE+0x6) /* UIC3 masked status */
-#define uic3vr (UIC3_DCR_BASE+0x7) /* UIC3 vector */
-#define uic3vcr (UIC3_DCR_BASE+0x8) /* UIC3 vector configuration */
-#endif /* CONFIG_440SPE */
-
-#if defined(CONFIG_440GX)
-#define UIC2_DCR_BASE 0x210
-#define uic2sr (UIC2_DCR_BASE+0x0) /* UIC2 status */
-#define uic2er (UIC2_DCR_BASE+0x2) /* UIC2 enable */
-#define uic2cr (UIC2_DCR_BASE+0x3) /* UIC2 critical */
-#define uic2pr (UIC2_DCR_BASE+0x4) /* UIC2 polarity */
-#define uic2tr (UIC2_DCR_BASE+0x5) /* UIC2 triggering */
-#define uic2msr (UIC2_DCR_BASE+0x6) /* UIC2 masked status */
-#define uic2vr (UIC2_DCR_BASE+0x7) /* UIC2 vector */
-#define uic2vcr (UIC2_DCR_BASE+0x8) /* UIC2 vector configuration */
-
-
-#define UIC_DCR_BASE 0x200
-#define uicb0sr (UIC_DCR_BASE+0x0) /* UIC Base Status Register */
-#define uicb0er (UIC_DCR_BASE+0x2) /* UIC Base enable */
-#define uicb0cr (UIC_DCR_BASE+0x3) /* UIC Base critical */
-#define uicb0pr (UIC_DCR_BASE+0x4) /* UIC Base polarity */
-#define uicb0tr (UIC_DCR_BASE+0x5) /* UIC Base triggering */
-#define uicb0msr (UIC_DCR_BASE+0x6) /* UIC Base masked status */
-#define uicb0vr (UIC_DCR_BASE+0x7) /* UIC Base vector */
-#define uicb0vcr (UIC_DCR_BASE+0x8) /* UIC Base vector configuration */
-#endif /* CONFIG_440GX */
-
-/* The following is for compatibility with 405 code */
-#define uicsr uic0sr
-#define uicer uic0er
-#define uiccr uic0cr
-#define uicpr uic0pr
-#define uictr uic0tr
-#define uicmsr uic0msr
-#define uicvr uic0vr
-#define uicvcr uic0vcr
-
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX)
-/*----------------------------------------------------------------------------+
-| Clock / Power-on-reset DCR's.
-+----------------------------------------------------------------------------*/
-#define CPR0_CLKUPD 0x20
-#define CPR0_CLKUPD_BSY_MASK 0x80000000
-#define CPR0_CLKUPD_BSY_COMPLETED 0x00000000
-#define CPR0_CLKUPD_BSY_BUSY 0x80000000
-#define CPR0_CLKUPD_CUI_MASK 0x80000000
-#define CPR0_CLKUPD_CUI_DISABLE 0x00000000
-#define CPR0_CLKUPD_CUI_ENABLE 0x80000000
-#define CPR0_CLKUPD_CUD_MASK 0x40000000
-#define CPR0_CLKUPD_CUD_DISABLE 0x00000000
-#define CPR0_CLKUPD_CUD_ENABLE 0x40000000
-
-#define CPR0_PLLC 0x40
-#define CPR0_PLLC_RST_MASK 0x80000000
-#define CPR0_PLLC_RST_PLLLOCKED 0x00000000
-#define CPR0_PLLC_RST_PLLRESET 0x80000000
-#define CPR0_PLLC_ENG_MASK 0x40000000
-#define CPR0_PLLC_ENG_DISABLE 0x00000000
-#define CPR0_PLLC_ENG_ENABLE 0x40000000
-#define CPR0_PLLC_ENG_ENCODE(n) ((((unsigned long)(n))&0x01)<<30)
-#define CPR0_PLLC_ENG_DECODE(n) ((((unsigned long)(n))>>30)&0x01)
-#define CPR0_PLLC_SRC_MASK 0x20000000
-#define CPR0_PLLC_SRC_PLLOUTA 0x00000000
-#define CPR0_PLLC_SRC_PLLOUTB 0x20000000
-#define CPR0_PLLC_SRC_ENCODE(n) ((((unsigned long)(n))&0x01)<<29)
-#define CPR0_PLLC_SRC_DECODE(n) ((((unsigned long)(n))>>29)&0x01)
-#define CPR0_PLLC_SEL_MASK 0x07000000
-#define CPR0_PLLC_SEL_PLLOUT 0x00000000
-#define CPR0_PLLC_SEL_CPU 0x01000000
-#define CPR0_PLLC_SEL_EBC 0x05000000
-#define CPR0_PLLC_SEL_ENCODE(n) ((((unsigned long)(n))&0x07)<<24)
-#define CPR0_PLLC_SEL_DECODE(n) ((((unsigned long)(n))>>24)&0x07)
-#define CPR0_PLLC_TUNE_MASK 0x000003FF
-#define CPR0_PLLC_TUNE_ENCODE(n) ((((unsigned long)(n))&0x3FF)<<0)
-#define CPR0_PLLC_TUNE_DECODE(n) ((((unsigned long)(n))>>0)&0x3FF)
-
-#define CPR0_PLLD 0x60
-#define CPR0_PLLD_FBDV_MASK 0x1F000000
-#define CPR0_PLLD_FBDV_ENCODE(n) ((((unsigned long)(n))&0x1F)<<24)
-#define CPR0_PLLD_FBDV_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x1F)+1)
-#define CPR0_PLLD_FWDVA_MASK 0x000F0000
-#define CPR0_PLLD_FWDVA_ENCODE(n) ((((unsigned long)(n))&0x0F)<<16)
-#define CPR0_PLLD_FWDVA_DECODE(n) ((((((unsigned long)(n))>>16)-1)&0x0F)+1)
-#define CPR0_PLLD_FWDVB_MASK 0x00000700
-#define CPR0_PLLD_FWDVB_ENCODE(n) ((((unsigned long)(n))&0x07)<<8)
-#define CPR0_PLLD_FWDVB_DECODE(n) ((((((unsigned long)(n))>>8)-1)&0x07)+1)
-#define CPR0_PLLD_LFBDV_MASK 0x0000003F
-#define CPR0_PLLD_LFBDV_ENCODE(n) ((((unsigned long)(n))&0x3F)<<0)
-#define CPR0_PLLD_LFBDV_DECODE(n) ((((((unsigned long)(n))>>0)-1)&0x3F)+1)
-
-#define CPR0_PRIMAD 0x80
-#define CPR0_PRIMAD_PRADV0_MASK 0x07000000
-#define CPR0_PRIMAD_PRADV0_ENCODE(n) ((((unsigned long)(n))&0x07)<<24)
-#define CPR0_PRIMAD_PRADV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x07)+1)
-
-#define CPR0_PRIMBD 0xA0
-#define CPR0_PRIMBD_PRBDV0_MASK 0x07000000
-#define CPR0_PRIMBD_PRBDV0_ENCODE(n) ((((unsigned long)(n))&0x07)<<24)
-#define CPR0_PRIMBD_PRBDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x07)+1)
-
-#define CPR0_OPBD 0xC0
-#define CPR0_OPBD_OPBDV0_MASK 0x03000000
-#define CPR0_OPBD_OPBDV0_ENCODE(n) ((((unsigned long)(n))&0x03)<<24)
-#define CPR0_OPBD_OPBDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x03)+1)
-
-#define CPR0_PERD 0xE0
-#if !defined(CONFIG_440EPX)
-#define CPR0_PERD_PERDV0_MASK 0x03000000
-#define CPR0_PERD_PERDV0_ENCODE(n) ((((unsigned long)(n))&0x03)<<24)
-#define CPR0_PERD_PERDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x03)+1)
-#endif
-
-#define CPR0_MALD 0x100
-#define CPR0_MALD_MALDV0_MASK 0x03000000
-#define CPR0_MALD_MALDV0_ENCODE(n) ((((unsigned long)(n))&0x03)<<24)
-#define CPR0_MALD_MALDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x03)+1)
-
-#define CPR0_ICFG 0x140
-#define CPR0_ICFG_RLI_MASK 0x80000000
-#define CPR0_ICFG_RLI_RESETCPR 0x00000000
-#define CPR0_ICFG_RLI_PRESERVECPR 0x80000000
-#define CPR0_ICFG_ICS_MASK 0x00000007
-#define CPR0_ICFG_ICS_ENCODE(n) ((((unsigned long)(n))&0x3F)<<0)
-#define CPR0_ICFG_ICS_DECODE(n) ((((((unsigned long)(n))>>0)-1)&0x3F)+1)
-
-/************************/
-/* IIC defines */
-/************************/
-#define IIC0_MMIO_BASE 0xA0000400
-#define IIC1_MMIO_BASE 0xA0000500
-
-#endif /* CONFIG_440SP */
-
-/*-----------------------------------------------------------------------------
| DMA
+----------------------------------------------------------------------------*/
#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
#define malrcbs24 (MAL_DCR_BASE+0x78) /* RX 24 Channel buffer size reg */
#endif /* CONFIG_440GX */
-
-/*---------------------------------------------------------------------------+
-| Universal interrupt controller 0 interrupts (UIC0)
-+---------------------------------------------------------------------------*/
-#if defined(CONFIG_440SP)
-#define UIC_U0 0x80000000 /* UART 0 */
-#define UIC_U1 0x40000000 /* UART 1 */
-#define UIC_IIC0 0x20000000 /* IIC */
-#define UIC_IIC1 0x10000000 /* IIC */
-#define UIC_PIM 0x08000000 /* PCI0 inbound message */
-#define UIC_PCRW 0x04000000 /* PCI0 command write register */
-#define UIC_PPM 0x02000000 /* PCI0 power management */
-#define UIC_PVPD 0x01000000 /* PCI0 VPD Access */
-#define UIC_MSI0 0x00800000 /* PCI0 MSI level 0 */
-#define UIC_P1IM 0x00400000 /* PCI1 Inbound Message */
-#define UIC_P1CRW 0x00200000 /* PCI1 command write register */
-#define UIC_P1PM 0x00100000 /* PCI1 power management */
-#define UIC_P1VPD 0x00080000 /* PCI1 VPD Access */
-#define UIC_P1MSI0 0x00040000 /* PCI1 MSI level 0 */
-#define UIC_P2IM 0x00020000 /* PCI2 inbound message */
-#define UIC_P2CRW 0x00010000 /* PCI2 command register write */
-#define UIC_P2PM 0x00008000 /* PCI2 power management */
-#define UIC_P2VPD 0x00004000 /* PCI2 VPD access */
-#define UIC_P2MSI0 0x00002000 /* PCI2 MSI level 0 */
-#define UIC_D0CPF 0x00001000 /* DMA0 command pointer */
-#define UIC_D0CSF 0x00000800 /* DMA0 command status */
-#define UIC_D1CPF 0x00000400 /* DMA1 command pointer */
-#define UIC_D1CSF 0x00000200 /* DMA1 command status */
-#define UIC_I2OID 0x00000100 /* I2O inbound doorbell */
-#define UIC_I2OPLF 0x00000080 /* I2O inbound post list */
-#define UIC_I2O0LL 0x00000040 /* I2O0 low latency PLB write */
-#define UIC_I2O1LL 0x00000020 /* I2O1 low latency PLB write */
-#define UIC_I2O0HB 0x00000010 /* I2O0 high bandwidth PLB write */
-#define UIC_I2O1HB 0x00000008 /* I2O1 high bandwidth PLB write */
-#define UIC_GPTCT 0x00000004 /* GPT count timer */
-#define UIC_UIC1NC 0x00000002 /* UIC1 non-critical interrupt */
-#define UIC_UIC1C 0x00000001 /* UIC1 critical interrupt */
-#elif defined(CONFIG_440GX) || defined(CONFIG_440EP)
-#define UIC_U0 0x80000000 /* UART 0 */
-#define UIC_U1 0x40000000 /* UART 1 */
-#define UIC_IIC0 0x20000000 /* IIC */
-#define UIC_IIC1 0x10000000 /* IIC */
-#define UIC_PIM 0x08000000 /* PCI inbound message */
-#define UIC_PCRW 0x04000000 /* PCI command register write */
-#define UIC_PPM 0x02000000 /* PCI power management */
-#define UIC_MSI0 0x01000000 /* PCI MSI level 0 */
-#define UIC_MSI1 0x00800000 /* PCI MSI level 1 */
-#define UIC_MSI2 0x00400000 /* PCI MSI level 2 */
-#define UIC_MTE 0x00200000 /* MAL TXEOB */
-#define UIC_MRE 0x00100000 /* MAL RXEOB */
-#define UIC_D0 0x00080000 /* DMA channel 0 */
-#define UIC_D1 0x00040000 /* DMA channel 1 */
-#define UIC_D2 0x00020000 /* DMA channel 2 */
-#define UIC_D3 0x00010000 /* DMA channel 3 */
-#define UIC_RSVD0 0x00008000 /* Reserved */
-#define UIC_RSVD1 0x00004000 /* Reserved */
-#define UIC_CT0 0x00002000 /* GPT compare timer 0 */
-#define UIC_CT1 0x00001000 /* GPT compare timer 1 */
-#define UIC_CT2 0x00000800 /* GPT compare timer 2 */
-#define UIC_CT3 0x00000400 /* GPT compare timer 3 */
-#define UIC_CT4 0x00000200 /* GPT compare timer 4 */
-#define UIC_EIR0 0x00000100 /* External interrupt 0 */
-#define UIC_EIR1 0x00000080 /* External interrupt 1 */
-#define UIC_EIR2 0x00000040 /* External interrupt 2 */
-#define UIC_EIR3 0x00000020 /* External interrupt 3 */
-#define UIC_EIR4 0x00000010 /* External interrupt 4 */
-#define UIC_EIR5 0x00000008 /* External interrupt 5 */
-#define UIC_EIR6 0x00000004 /* External interrupt 6 */
-#define UIC_UIC1NC 0x00000002 /* UIC1 non-critical interrupt */
-#define UIC_UIC1C 0x00000001 /* UIC1 critical interrupt */
-
-#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-
-#define UIC_U0 0x80000000 /* UART 0 */
-#define UIC_U1 0x40000000 /* UART 1 */
-#define UIC_IIC0 0x20000000 /* IIC */
-#define UIC_KRD 0x10000000 /* Kasumi Ready for data */
-#define UIC_KDA 0x08000000 /* Kasumi Data Available */
-#define UIC_PCRW 0x04000000 /* PCI command register write */
-#define UIC_PPM 0x02000000 /* PCI power management */
-#define UIC_IIC1 0x01000000 /* IIC */
-#define UIC_SPI 0x00800000 /* SPI */
-#define UIC_EPCISER 0x00400000 /* External PCI SERR */
-#define UIC_MTE 0x00200000 /* MAL TXEOB */
-#define UIC_MRE 0x00100000 /* MAL RXEOB */
-#define UIC_D0 0x00080000 /* DMA channel 0 */
-#define UIC_D1 0x00040000 /* DMA channel 1 */
-#define UIC_D2 0x00020000 /* DMA channel 2 */
-#define UIC_D3 0x00010000 /* DMA channel 3 */
-#define UIC_UD0 0x00008000 /* UDMA irq 0 */
-#define UIC_UD1 0x00004000 /* UDMA irq 1 */
-#define UIC_UD2 0x00002000 /* UDMA irq 2 */
-#define UIC_UD3 0x00001000 /* UDMA irq 3 */
-#define UIC_HSB2D 0x00000800 /* USB2.0 Device */
-#define UIC_OHCI1 0x00000400 /* USB2.0 Host OHCI irq 1 */
-#define UIC_OHCI2 0x00000200 /* USB2.0 Host OHCI irq 2 */
-#define UIC_EIP94 0x00000100 /* Security EIP94 */
-#define UIC_ETH0 0x00000080 /* Emac 0 */
-#define UIC_ETH1 0x00000040 /* Emac 1 */
-#define UIC_EHCI 0x00000020 /* USB2.0 Host EHCI */
-#define UIC_EIR4 0x00000010 /* External interrupt 4 */
-#define UIC_UIC2NC 0x00000008 /* UIC2 non-critical interrupt */
-#define UIC_UIC2C 0x00000004 /* UIC2 critical interrupt */
-#define UIC_UIC1NC 0x00000002 /* UIC1 non-critical interrupt */
-#define UIC_UIC1C 0x00000001 /* UIC1 critical interrupt */
-
-/* For compatibility with 405 code */
-#define UIC_MAL_TXEOB UIC_MTE
-#define UIC_MAL_RXEOB UIC_MRE
-
-#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
-
-#define UIC_RSVD0 0x80000000 /* N/A - unused */
-#define UIC_U1 0x40000000 /* UART 1 */
-#define UIC_IIC0 0x20000000 /* IIC */
-#define UIC_IIC1 0x10000000 /* IIC */
-#define UIC_PIM 0x08000000 /* PCI inbound message */
-#define UIC_PCRW 0x04000000 /* PCI command register write */
-#define UIC_PPM 0x02000000 /* PCI power management */
-#define UIC_PCIVPD 0x01000000 /* PCI VPD */
-#define UIC_MSI0 0x00800000 /* PCI MSI level 0 */
-#define UIC_EIR0 0x00400000 /* External interrupt 0 */
-#define UIC_UIC2NC 0x00200000 /* UIC2 non-critical interrupt */
-#define UIC_UIC2C 0x00100000 /* UIC2 critical interrupt */
-#define UIC_D0 0x00080000 /* DMA channel 0 */
-#define UIC_D1 0x00040000 /* DMA channel 1 */
-#define UIC_D2 0x00020000 /* DMA channel 2 */
-#define UIC_D3 0x00010000 /* DMA channel 3 */
-#define UIC_UIC3NC 0x00008000 /* UIC3 non-critical interrupt */
-#define UIC_UIC3C 0x00004000 /* UIC3 critical interrupt */
-#define UIC_EIR1 0x00002000 /* External interrupt 1 */
-#define UIC_TRNGDA 0x00001000 /* TRNG data available */
-#define UIC_PKAR1 0x00000800 /* PKA ready (PKA[1]) */
-#define UIC_D1CPFF 0x00000400 /* DMA1 cp fifo full */
-#define UIC_D1CSNS 0x00000200 /* DMA1 cs fifo needs service */
-#define UIC_I2OID 0x00000100 /* I2O inbound door bell */
-#define UIC_I2OLNE 0x00000080 /* I2O Inbound Post List FIFO Not Empty */
-#define UIC_I20R0LL 0x00000040 /* I2O Region 0 Low Latency PLB Write */
-#define UIC_I2OR1LL 0x00000020 /* I2O Region 1 Low Latency PLB Write */
-#define UIC_I20R0HB 0x00000010 /* I2O Region 0 High Bandwidth PLB Write */
-#define UIC_I2OR1HB 0x00000008 /* I2O Region 1 High Bandwidth PLB Write */
-#define UIC_EIP94 0x00000004 /* Security EIP94 */
-#define UIC_UIC1NC 0x00000002 /* UIC1 non-critical interrupt */
-#define UIC_UIC1C 0x00000001 /* UIC1 critical interrupt */
-
-#elif !defined(CONFIG_440SPE)
-#define UIC_U0 0x80000000 /* UART 0 */
-#define UIC_U1 0x40000000 /* UART 1 */
-#define UIC_IIC0 0x20000000 /* IIC */
-#define UIC_IIC1 0x10000000 /* IIC */
-#define UIC_PIM 0x08000000 /* PCI inbound message */
-#define UIC_PCRW 0x04000000 /* PCI command register write */
-#define UIC_PPM 0x02000000 /* PCI power management */
-#define UIC_MSI0 0x01000000 /* PCI MSI level 0 */
-#define UIC_MSI1 0x00800000 /* PCI MSI level 1 */
-#define UIC_MSI2 0x00400000 /* PCI MSI level 2 */
-#define UIC_MTE 0x00200000 /* MAL TXEOB */
-#define UIC_MRE 0x00100000 /* MAL RXEOB */
-#define UIC_D0 0x00080000 /* DMA channel 0 */
-#define UIC_D1 0x00040000 /* DMA channel 1 */
-#define UIC_D2 0x00020000 /* DMA channel 2 */
-#define UIC_D3 0x00010000 /* DMA channel 3 */
-#define UIC_RSVD0 0x00008000 /* Reserved */
-#define UIC_RSVD1 0x00004000 /* Reserved */
-#define UIC_CT0 0x00002000 /* GPT compare timer 0 */
-#define UIC_CT1 0x00001000 /* GPT compare timer 1 */
-#define UIC_CT2 0x00000800 /* GPT compare timer 2 */
-#define UIC_CT3 0x00000400 /* GPT compare timer 3 */
-#define UIC_CT4 0x00000200 /* GPT compare timer 4 */
-#define UIC_EIR0 0x00000100 /* External interrupt 0 */
-#define UIC_EIR1 0x00000080 /* External interrupt 1 */
-#define UIC_EIR2 0x00000040 /* External interrupt 2 */
-#define UIC_EIR3 0x00000020 /* External interrupt 3 */
-#define UIC_EIR4 0x00000010 /* External interrupt 4 */
-#define UIC_EIR5 0x00000008 /* External interrupt 5 */
-#define UIC_EIR6 0x00000004 /* External interrupt 6 */
-#define UIC_UIC1NC 0x00000002 /* UIC1 non-critical interrupt */
-#define UIC_UIC1C 0x00000001 /* UIC1 critical interrupt */
-#endif /* CONFIG_440GX */
-
-/* For compatibility with 405 code */
-#define UIC_MAL_TXEOB UIC_MTE
-#define UIC_MAL_RXEOB UIC_MRE
-
-/*---------------------------------------------------------------------------+
-| Universal interrupt controller 1 interrupts (UIC1)
-+---------------------------------------------------------------------------*/
-#if defined(CONFIG_440SP)
-#define UIC_EIR0 0x80000000 /* External interrupt 0 */
-#define UIC_MS 0x40000000 /* MAL SERR */
-#define UIC_MTDE 0x20000000 /* MAL TXDE */
-#define UIC_MRDE 0x10000000 /* MAL RXDE */
-#define UIC_DECE 0x08000000 /* DDR SDRAM correctible error */
-#define UIC_EBCO 0x04000000 /* EBCO interrupt status */
-#define UIC_MTE 0x02000000 /* MAL TXEOB */
-#define UIC_MRE 0x01000000 /* MAL RXEOB */
-#define UIC_P0MSI1 0x00800000 /* PCI0 MSI level 1 */
-#define UIC_P1MSI1 0x00400000 /* PCI1 MSI level 1 */
-#define UIC_P2MSI1 0x00200000 /* PCI2 MSI level 1 */
-#define UIC_L2C 0x00100000 /* L2 cache */
-#define UIC_CT0 0x00080000 /* GPT compare timer 0 */
-#define UIC_CT1 0x00040000 /* GPT compare timer 1 */
-#define UIC_CT2 0x00020000 /* GPT compare timer 2 */
-#define UIC_CT3 0x00010000 /* GPT compare timer 3 */
-#define UIC_CT4 0x00008000 /* GPT compare timer 4 */
-#define UIC_EIR1 0x00004000 /* External interrupt 1 */
-#define UIC_EIR2 0x00002000 /* External interrupt 2 */
-#define UIC_EIR3 0x00001000 /* External interrupt 3 */
-#define UIC_EIR4 0x00000800 /* External interrupt 4 */
-#define UIC_EIR5 0x00000400 /* External interrupt 5 */
-#define UIC_DMAE 0x00000200 /* DMA error */
-#define UIC_I2OE 0x00000100 /* I2O error */
-#define UIC_SRE 0x00000080 /* Serial ROM error */
-#define UIC_P0AE 0x00000040 /* PCI0 asynchronous error */
-#define UIC_P1AE 0x00000020 /* PCI1 asynchronous error */
-#define UIC_P2AE 0x00000010 /* PCI2 asynchronous error */
-#define UIC_ETH0 0x00000008 /* Ethernet 0 */
-#define UIC_EWU0 0x00000004 /* Ethernet 0 wakeup */
-#define UIC_ETH1 0x00000002 /* Reserved */
-#define UIC_XOR 0x00000001 /* XOR */
-#elif defined(CONFIG_440GX) || defined(CONFIG_440EP)
-#define UIC_MS 0x80000000 /* MAL SERR */
-#define UIC_MTDE 0x40000000 /* MAL TXDE */
-#define UIC_MRDE 0x20000000 /* MAL RXDE */
-#define UIC_DEUE 0x10000000 /* DDR SDRAM ECC uncorrectible error*/
-#define UIC_DECE 0x08000000 /* DDR SDRAM correctible error */
-#define UIC_EBCO 0x04000000 /* EBCO interrupt status */
-#define UIC_EBMI 0x02000000 /* EBMI interrupt status */
-#define UIC_OPB 0x01000000 /* OPB to PLB bridge interrupt stat */
-#define UIC_MSI3 0x00800000 /* PCI MSI level 3 */
-#define UIC_MSI4 0x00400000 /* PCI MSI level 4 */
-#define UIC_MSI5 0x00200000 /* PCI MSI level 5 */
-#define UIC_MSI6 0x00100000 /* PCI MSI level 6 */
-#define UIC_MSI7 0x00080000 /* PCI MSI level 7 */
-#define UIC_MSI8 0x00040000 /* PCI MSI level 8 */
-#define UIC_MSI9 0x00020000 /* PCI MSI level 9 */
-#define UIC_MSI10 0x00010000 /* PCI MSI level 10 */
-#define UIC_MSI11 0x00008000 /* PCI MSI level 11 */
-#define UIC_PPMI 0x00004000 /* PPM interrupt status */
-#define UIC_EIR7 0x00002000 /* External interrupt 7 */
-#define UIC_EIR8 0x00001000 /* External interrupt 8 */
-#define UIC_EIR9 0x00000800 /* External interrupt 9 */
-#define UIC_EIR10 0x00000400 /* External interrupt 10 */
-#define UIC_EIR11 0x00000200 /* External interrupt 11 */
-#define UIC_EIR12 0x00000100 /* External interrupt 12 */
-#define UIC_SRE 0x00000080 /* Serial ROM error */
-#define UIC_RSVD2 0x00000040 /* Reserved */
-#define UIC_RSVD3 0x00000020 /* Reserved */
-#define UIC_PAE 0x00000010 /* PCI asynchronous error */
-#define UIC_ETH0 0x00000008 /* Ethernet 0 */
-#define UIC_EWU0 0x00000004 /* Ethernet 0 wakeup */
-#define UIC_ETH1 0x00000002 /* Ethernet 1 */
-#define UIC_EWU1 0x00000001 /* Ethernet 1 wakeup */
-
-#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
-
-#define UIC_EIR2 0x80000000 /* External interrupt 2 */
-#define UIC_U0 0x40000000 /* UART 0 */
-#define UIC_SPI 0x20000000 /* SPI */
-#define UIC_TRNGAL 0x10000000 /* TRNG alarm */
-#define UIC_DEUE 0x08000000 /* DDR SDRAM ECC correct/uncorrectable error */
-#define UIC_EBCO 0x04000000 /* EBCO interrupt status */
-#define UIC_NDFC 0x02000000 /* NDFC */
-#define UIC_EIPPKPSE 0x01000000 /* EIPPKP slave error */
-#define UIC_P0MSI1 0x00800000 /* PCI0 MSI level 1 */
-#define UIC_P0MSI2 0x00400000 /* PCI0 MSI level 2 */
-#define UIC_P0MSI3 0x00200000 /* PCI0 MSI level 3 */
-#define UIC_L2C 0x00100000 /* L2 cache */
-#define UIC_CT0 0x00080000 /* GPT compare timer 0 */
-#define UIC_CT1 0x00040000 /* GPT compare timer 1 */
-#define UIC_CT2 0x00020000 /* GPT compare timer 2 */
-#define UIC_CT3 0x00010000 /* GPT compare timer 3 */
-#define UIC_CT4 0x00008000 /* GPT compare timer 4 */
-#define UIC_CT5 0x00004000 /* GPT compare timer 5 */
-#define UIC_CT6 0x00002000 /* GPT compare timer 6 */
-#define UIC_GPTDC 0x00001000 /* GPT decrementer pulse */
-#define UIC_EIR3 0x00000800 /* External interrupt 3 */
-#define UIC_EIR4 0x00000400 /* External interrupt 4 */
-#define UIC_DMAE 0x00000200 /* DMA error */
-#define UIC_I2OE 0x00000100 /* I2O error */
-#define UIC_SRE 0x00000080 /* Serial ROM error */
-#define UIC_P0AE 0x00000040 /* PCI0 asynchronous error */
-#define UIC_EIR5 0x00000020 /* External interrupt 5 */
-#define UIC_EIR6 0x00000010 /* External interrupt 6 */
-#define UIC_U2 0x00000008 /* UART 2 */
-#define UIC_U3 0x00000004 /* UART 3 */
-#define UIC_EIR7 0x00000002 /* External interrupt 7 */
-#define UIC_EIR8 0x00000001 /* External interrupt 8 */
-
-#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-
-#define UIC_MS 0x80000000 /* MAL SERR */
-#define UIC_MTDE 0x40000000 /* MAL TXDE */
-#define UIC_MRDE 0x20000000 /* MAL RXDE */
-#define UIC_U2 0x10000000 /* UART 2 */
-#define UIC_U3 0x08000000 /* UART 3 */
-#define UIC_EBCO 0x04000000 /* EBCO interrupt status */
-#define UIC_NDFC 0x02000000 /* NDFC */
-#define UIC_KSLE 0x01000000 /* KASUMI slave error */
-#define UIC_CT5 0x00800000 /* GPT compare timer 5 */
-#define UIC_CT6 0x00400000 /* GPT compare timer 6 */
-#define UIC_PLB34I0 0x00200000 /* PLB3X4X MIRQ0 */
-#define UIC_PLB34I1 0x00100000 /* PLB3X4X MIRQ1 */
-#define UIC_PLB34I2 0x00080000 /* PLB3X4X MIRQ2 */
-#define UIC_PLB34I3 0x00040000 /* PLB3X4X MIRQ3 */
-#define UIC_PLB34I4 0x00020000 /* PLB3X4X MIRQ4 */
-#define UIC_PLB34I5 0x00010000 /* PLB3X4X MIRQ5 */
-#define UIC_CT0 0x00008000 /* GPT compare timer 0 */
-#define UIC_CT1 0x00004000 /* GPT compare timer 1 */
-#define UIC_EIR7 0x00002000 /* External interrupt 7 */
-#define UIC_EIR8 0x00001000 /* External interrupt 8 */
-#define UIC_EIR9 0x00000800 /* External interrupt 9 */
-#define UIC_CT2 0x00000400 /* GPT compare timer 2 */
-#define UIC_CT3 0x00000200 /* GPT compare timer 3 */
-#define UIC_CT4 0x00000100 /* GPT compare timer 4 */
-#define UIC_SRE 0x00000080 /* Serial ROM error */
-#define UIC_GPTDC 0x00000040 /* GPT decrementer pulse */
-#define UIC_RSVD0 0x00000020 /* Reserved */
-#define UIC_EPCIPER 0x00000010 /* External PCI PERR */
-#define UIC_EIR0 0x00000008 /* External interrupt 0 */
-#define UIC_EWU0 0x00000004 /* Ethernet 0 wakeup */
-#define UIC_EIR1 0x00000002 /* External interrupt 1 */
-#define UIC_EWU1 0x00000001 /* Ethernet 1 wakeup */
-
-/* For compatibility with 405 code */
-#define UIC_MAL_SERR UIC_MS
-#define UIC_MAL_TXDE UIC_MTDE
-#define UIC_MAL_RXDE UIC_MRDE
-#define UIC_ENET UIC_ETH0
-
-#elif !defined(CONFIG_440SPE)
-#define UIC_MS 0x80000000 /* MAL SERR */
-#define UIC_MTDE 0x40000000 /* MAL TXDE */
-#define UIC_MRDE 0x20000000 /* MAL RXDE */
-#define UIC_DEUE 0x10000000 /* DDR SDRAM ECC uncorrectible error*/
-#define UIC_DECE 0x08000000 /* DDR SDRAM correctible error */
-#define UIC_EBCO 0x04000000 /* EBCO interrupt status */
-#define UIC_EBMI 0x02000000 /* EBMI interrupt status */
-#define UIC_OPB 0x01000000 /* OPB to PLB bridge interrupt stat */
-#define UIC_MSI3 0x00800000 /* PCI MSI level 3 */
-#define UIC_MSI4 0x00400000 /* PCI MSI level 4 */
-#define UIC_MSI5 0x00200000 /* PCI MSI level 5 */
-#define UIC_MSI6 0x00100000 /* PCI MSI level 6 */
-#define UIC_MSI7 0x00080000 /* PCI MSI level 7 */
-#define UIC_MSI8 0x00040000 /* PCI MSI level 8 */
-#define UIC_MSI9 0x00020000 /* PCI MSI level 9 */
-#define UIC_MSI10 0x00010000 /* PCI MSI level 10 */
-#define UIC_MSI11 0x00008000 /* PCI MSI level 11 */
-#define UIC_PPMI 0x00004000 /* PPM interrupt status */
-#define UIC_EIR7 0x00002000 /* External interrupt 7 */
-#define UIC_EIR8 0x00001000 /* External interrupt 8 */
-#define UIC_EIR9 0x00000800 /* External interrupt 9 */
-#define UIC_EIR10 0x00000400 /* External interrupt 10 */
-#define UIC_EIR11 0x00000200 /* External interrupt 11 */
-#define UIC_EIR12 0x00000100 /* External interrupt 12 */
-#define UIC_SRE 0x00000080 /* Serial ROM error */
-#define UIC_RSVD2 0x00000040 /* Reserved */
-#define UIC_RSVD3 0x00000020 /* Reserved */
-#define UIC_PAE 0x00000010 /* PCI asynchronous error */
-#define UIC_ETH0 0x00000008 /* Ethernet 0 */
-#define UIC_EWU0 0x00000004 /* Ethernet 0 wakeup */
-#define UIC_ETH1 0x00000002 /* Ethernet 1 */
-#define UIC_EWU1 0x00000001 /* Ethernet 1 wakeup */
-#endif /* CONFIG_440SP */
-
-/* For compatibility with 405 code */
-#define UIC_MAL_SERR UIC_MS
-#define UIC_MAL_TXDE UIC_MTDE
-#define UIC_MAL_RXDE UIC_MRDE
-#define UIC_ENET UIC_ETH0
-
-/*---------------------------------------------------------------------------+
-| Universal interrupt controller 2 interrupts (UIC2)
-+---------------------------------------------------------------------------*/
-#if defined(CONFIG_440GX)
-#define UIC_ETH2 0x80000000 /* Ethernet 2 */
-#define UIC_EWU2 0x40000000 /* Ethernet 2 wakeup */
-#define UIC_ETH3 0x20000000 /* Ethernet 3 */
-#define UIC_EWU3 0x10000000 /* Ethernet 3 wakeup */
-#define UIC_TAH0 0x08000000 /* TAH 0 */
-#define UIC_TAH1 0x04000000 /* TAH 1 */
-#define UIC_IMUOBFQ 0x02000000 /* IMU outbound free queue */
-#define UIC_IMUIBPQ 0x01000000 /* IMU inbound post queue */
-#define UIC_IMUIRQDB 0x00800000 /* IMU irq doorbell */
-#define UIC_IMUIBDB 0x00400000 /* IMU inbound doorbell */
-#define UIC_IMUMSG0 0x00200000 /* IMU inbound message 0 */
-#define UIC_IMUMSG1 0x00100000 /* IMU inbound message 1 */
-#define UIC_IMUTO 0x00080000 /* IMU timeout */
-#define UIC_MSI12 0x00040000 /* PCI MSI level 12 */
-#define UIC_MSI13 0x00020000 /* PCI MSI level 13 */
-#define UIC_MSI14 0x00010000 /* PCI MSI level 14 */
-#define UIC_MSI15 0x00008000 /* PCI MSI level 15 */
-#define UIC_EIR13 0x00004000 /* External interrupt 13 */
-#define UIC_EIR14 0x00002000 /* External interrupt 14 */
-#define UIC_EIR15 0x00001000 /* External interrupt 15 */
-#define UIC_EIR16 0x00000800 /* External interrupt 16 */
-#define UIC_EIR17 0x00000400 /* External interrupt 17 */
-#define UIC_PCIVPD 0x00000200 /* PCI VPD */
-#define UIC_L2C 0x00000100 /* L2 Cache */
-#define UIC_ETH2PCS 0x00000080 /* Ethernet 2 PCS */
-#define UIC_ETH3PCS 0x00000040 /* Ethernet 3 PCS */
-#define UIC_RSVD26 0x00000020 /* Reserved */
-#define UIC_RSVD27 0x00000010 /* Reserved */
-#define UIC_RSVD28 0x00000008 /* Reserved */
-#define UIC_RSVD29 0x00000004 /* Reserved */
-#define UIC_RSVD30 0x00000002 /* Reserved */
-#define UIC_RSVD31 0x00000001 /* Reserved */
-
-#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
-
-#define UIC_TAH0 0x80000000 /* TAHOE 0 */
-#define UIC_TAH1 0x40000000 /* TAHOE 1 */
-#define UIC_EIR9 0x20000000 /* External interrupt 9 */
-#define UIC_MS 0x10000000 /* MAL SERR */
-#define UIC_MTDE 0x08000000 /* MAL TXDE */
-#define UIC_MRDE 0x04000000 /* MAL RXDE */
-#define UIC_MTE 0x02000000 /* MAL TXEOB */
-#define UIC_MRE 0x01000000 /* MAL RXEOB */
-#define UIC_MCTX0 0x00800000 /* MAL interrupt coalescence TX0 */
-#define UIC_MCTX1 0x00400000 /* MAL interrupt coalescence TX1 */
-#define UIC_MCTX2 0x00200000 /* MAL interrupt coalescence TX2 */
-#define UIC_MCTX3 0x00100000 /* MAL interrupt coalescence TX3 */
-#define UIC_MCTR0 0x00080000 /* MAL interrupt coalescence TR0 */
-#define UIC_MCTR1 0x00040000 /* MAL interrupt coalescence TR1 */
-#define UIC_MCTR2 0x00020000 /* MAL interrupt coalescence TR2 */
-#define UIC_MCTR3 0x00010000 /* MAL interrupt coalescence TR3 */
-#define UIC_ETH0 0x00008000 /* Ethernet 0 */
-#define UIC_ETH1 0x00004000 /* Ethernet 1 */
-#define UIC_ETH2 0x00002000 /* Ethernet 2 */
-#define UIC_ETH3 0x00001000 /* Ethernet 3 */
-#define UIC_EWU0 0x00000800 /* Ethernet 0 wakeup */
-#define UIC_EWU1 0x00000400 /* Ethernet 1 wakeup */
-#define UIC_EWU2 0x00000200 /* Ethernet 2 wakeup */
-#define UIC_EWU3 0x00000100 /* Ethernet 3 wakeup */
-#define UIC_EIR10 0x00000080 /* External interrupt 10 */
-#define UIC_EIR11 0x00000040 /* External interrupt 11 */
-#define UIC_RSVD2 0x00000020 /* Reserved */
-#define UIC_PLB4XAHB 0x00000010 /* PLB4XAHB / AHBARB error */
-#define UIC_OTG 0x00000008 /* USB2.0 OTG */
-#define UIC_EHCI 0x00000004 /* USB2.0 Host EHCI */
-#define UIC_OHCI 0x00000002 /* USB2.0 Host OHCI */
-#define UIC_OHCISMI 0x00000001 /* USB2.0 Host OHCI SMI */
-
-#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX) /* UIC2 */
-
-#define UIC_EIR5 0x80000000 /* External interrupt 5 */
-#define UIC_EIR6 0x40000000 /* External interrupt 6 */
-#define UIC_OPB 0x20000000 /* OPB to PLB bridge interrupt stat */
-#define UIC_EIR2 0x10000000 /* External interrupt 2 */
-#define UIC_EIR3 0x08000000 /* External interrupt 3 */
-#define UIC_DDR2 0x04000000 /* DDR2 sdram */
-#define UIC_MCTX0 0x02000000 /* MAl intp coalescence TX0 */
-#define UIC_MCTX1 0x01000000 /* MAl intp coalescence TX1 */
-#define UIC_MCTR0 0x00800000 /* MAl intp coalescence TR0 */
-#define UIC_MCTR1 0x00400000 /* MAl intp coalescence TR1 */
-
-#endif /* CONFIG_440GX */
-
-/*---------------------------------------------------------------------------+
-| Universal interrupt controller Base 0 interrupts (UICB0)
-+---------------------------------------------------------------------------*/
-#if defined(CONFIG_440GX)
-#define UICB0_UIC0CI 0x80000000 /* UIC0 Critical Interrupt */
-#define UICB0_UIC0NCI 0x40000000 /* UIC0 Noncritical Interrupt */
-#define UICB0_UIC1CI 0x20000000 /* UIC1 Critical Interrupt */
-#define UICB0_UIC1NCI 0x10000000 /* UIC1 Noncritical Interrupt */
-#define UICB0_UIC2CI 0x08000000 /* UIC2 Critical Interrupt */
-#define UICB0_UIC2NCI 0x04000000 /* UIC2 Noncritical Interrupt */
-
-#define UICB0_ALL (UICB0_UIC0CI | UICB0_UIC0NCI | UICB0_UIC1CI | \
- UICB0_UIC1NCI | UICB0_UIC2CI | UICB0_UIC2NCI)
-
-#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
-
-#define UICB0_UIC1NCI 0x00000002 /* UIC1 Noncritical Interrupt */
-#define UICB0_UIC1CI 0x00000001 /* UIC1 Critical Interrupt */
-#define UICB0_UIC2NCI 0x00200000 /* UIC2 Noncritical Interrupt */
-#define UICB0_UIC2CI 0x00100000 /* UIC2 Critical Interrupt */
-#define UICB0_UIC3NCI 0x00008000 /* UIC3 Noncritical Interrupt */
-#define UICB0_UIC3CI 0x00004000 /* UIC3 Critical Interrupt */
-
-#define UICB0_ALL (UICB0_UIC1CI | UICB0_UIC1NCI | UICB0_UIC2CI | \
- UICB0_UIC2NCI | UICB0_UIC3CI | UICB0_UIC3NCI)
-
-#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-
-#define UICB0_UIC1CI 0x00000001 /* UIC1 Critical Interrupt */
-#define UICB0_UIC1NCI 0x00000002 /* UIC1 Noncritical Interrupt */
-#define UICB0_UIC2CI 0x00000004 /* UIC2 Critical Interrupt */
-#define UICB0_UIC2NCI 0x00000008 /* UIC2 Noncritical Interrupt */
-
-#define UICB0_ALL (UICB0_UIC1CI | UICB0_UIC1NCI | \
- UICB0_UIC1CI | UICB0_UIC2NCI)
-
-#elif defined(CONFIG_440GP) || defined(CONFIG_440SP) || \
- defined(CONFIG_440EP) || defined(CONFIG_440GR)
-
-#define UICB0_UIC1CI 0x00000001 /* UIC1 Critical Interrupt */
-#define UICB0_UIC1NCI 0x00000002 /* UIC1 Noncritical Interrupt */
-
-#define UICB0_ALL (UICB0_UIC1CI | UICB0_UIC1NCI)
-
-#endif /* CONFIG_440GX */
-/*---------------------------------------------------------------------------+
-| Universal interrupt controller interrupts
-+---------------------------------------------------------------------------*/
-#if defined(CONFIG_440SPE)
-/*#define UICB0_UIC0CI 0x80000000*/ /* UIC0 Critical Interrupt */
-/*#define UICB0_UIC0NCI 0x40000000*/ /* UIC0 Noncritical Interrupt */
-#define UICB0_UIC1CI 0x00000002 /* UIC1 Critical Interrupt */
-#define UICB0_UIC1NCI 0x00000001 /* UIC1 Noncritical Interrupt */
-#define UICB0_UIC2CI 0x00200000 /* UIC2 Critical Interrupt */
-#define UICB0_UIC2NCI 0x00100000 /* UIC2 Noncritical Interrupt */
-#define UICB0_UIC3CI 0x00008000 /* UIC3 Critical Interrupt */
-#define UICB0_UIC3NCI 0x00004000 /* UIC3 Noncritical Interrupt */
-
-#define UICB0_ALL (UICB0_UIC1CI | UICB0_UIC1NCI | UICB0_UIC2CI | \
- UICB0_UIC2NCI | UICB0_UIC3CI | UICB0_UIC3NCI)
-/*---------------------------------------------------------------------------+
-| Universal interrupt controller 0 interrupts (UIC0)
-+---------------------------------------------------------------------------*/
-#define UIC_U0 0x80000000 /* UART 0 */
-#define UIC_U1 0x40000000 /* UART 1 */
-#define UIC_IIC0 0x20000000 /* IIC */
-#define UIC_IIC1 0x10000000 /* IIC */
-#define UIC_PIM 0x08000000 /* PCI inbound message */
-#define UIC_PCRW 0x04000000 /* PCI command register write */
-#define UIC_PPM 0x02000000 /* PCI power management */
-#define UIC_PVPDA 0x01000000 /* PCIx 0 vpd access */
-#define UIC_MSI0 0x00800000 /* PCIx MSI level 0 */
-#define UIC_EIR15 0x00400000 /* External intp 15 */
-#define UIC_PEMSI0 0x00080000 /* PCIe MSI level 0 */
-#define UIC_PEMSI1 0x00040000 /* PCIe MSI level 1 */
-#define UIC_PEMSI2 0x00020000 /* PCIe MSI level 2 */
-#define UIC_PEMSI3 0x00010000 /* PCIe MSI level 3 */
-#define UIC_EIR14 0x00002000 /* External interrupt 14 */
-#define UIC_D0CPFF 0x00001000 /* DMA0 cp fifo full */
-#define UIC_D0CSNS 0x00000800 /* DMA0 cs fifo needs service */
-#define UIC_D1CPFF 0x00000400 /* DMA1 cp fifo full */
-#define UIC_D1CSNS 0x00000200 /* DMA1 cs fifo needs service */
-#define UIC_I2OID 0x00000100 /* I2O inbound door bell */
-#define UIC_I2OLNE 0x00000080 /* I2O Inbound Post List FIFO Not Empty */
-#define UIC_I20R0LL 0x00000040 /* I2O Region 0 Low Latency PLB Write */
-#define UIC_I2OR1LL 0x00000020 /* I2O Region 1 Low Latency PLB Write */
-#define UIC_I20R0HB 0x00000010 /* I2O Region 0 High Bandwidth PLB Write */
-#define UIC_I2OR1HB 0x00000008 /* I2O Region 1 High Bandwidth PLB Write */
-#define UIC_CPTCNT 0x00000004 /* GPT Count Timer */
-/*---------------------------------------------------------------------------+
-| Universal interrupt controller 1 interrupts (UIC1)
-+---------------------------------------------------------------------------*/
-#define UIC_EIR13 0x80000000 /* externei intp 13 */
-#define UIC_MS 0x40000000 /* MAL SERR */
-#define UIC_MTDE 0x20000000 /* MAL TXDE */
-#define UIC_MRDE 0x10000000 /* MAL RXDE */
-#define UIC_DEUE 0x08000000 /* DDR SDRAM ECC correct/uncorrectable error */
-#define UIC_EBCO 0x04000000 /* EBCO interrupt status */
-#define UIC_MTE 0x02000000 /* MAL TXEOB */
-#define UIC_MRE 0x01000000 /* MAL RXEOB */
-#define UIC_MSI1 0x00800000 /* PCI MSI level 1 */
-#define UIC_MSI2 0x00400000 /* PCI MSI level 2 */
-#define UIC_MSI3 0x00200000 /* PCI MSI level 3 */
-#define UIC_L2C 0x00100000 /* L2 cache */
-#define UIC_CT0 0x00080000 /* GPT compare timer 0 */
-#define UIC_CT1 0x00040000 /* GPT compare timer 1 */
-#define UIC_CT2 0x00020000 /* GPT compare timer 2 */
-#define UIC_CT3 0x00010000 /* GPT compare timer 3 */
-#define UIC_CT4 0x00008000 /* GPT compare timer 4 */
-#define UIC_EIR12 0x00004000 /* External interrupt 12 */
-#define UIC_EIR11 0x00002000 /* External interrupt 11 */
-#define UIC_EIR10 0x00001000 /* External interrupt 10 */
-#define UIC_EIR9 0x00000800 /* External interrupt 9 */
-#define UIC_EIR8 0x00000400 /* External interrupt 8 */
-#define UIC_DMAE 0x00000200 /* dma error */
-#define UIC_I2OE 0x00000100 /* i2o error */
-#define UIC_SRE 0x00000080 /* Serial ROM error */
-#define UIC_PCIXAE 0x00000040 /* Pcix0 async error */
-#define UIC_EIR7 0x00000020 /* External interrupt 7 */
-#define UIC_EIR6 0x00000010 /* External interrupt 6 */
-#define UIC_ETH0 0x00000008 /* Ethernet 0 */
-#define UIC_EWU0 0x00000004 /* Ethernet 0 wakeup */
-#define UIC_ETH1 0x00000002 /* reserved */
-#define UIC_XOR 0x00000001 /* xor */
-
-/*---------------------------------------------------------------------------+
-| Universal interrupt controller 2 interrupts (UIC2)
-+---------------------------------------------------------------------------*/
-#define UIC_PEOAL 0x80000000 /* PE0 AL */
-#define UIC_PEOVA 0x40000000 /* PE0 VPD access */
-#define UIC_PEOHRR 0x20000000 /* PE0 Host reset request rising */
-#define UIC_PE0HRF 0x10000000 /* PE0 Host reset request falling */
-#define UIC_PE0TCR 0x08000000 /* PE0 TCR */
-#define UIC_PE0BVCO 0x04000000 /* PE0 Busmaster VCO */
-#define UIC_PE0DCRE 0x02000000 /* PE0 DCR error */
-#define UIC_PE1AL 0x00800000 /* PE1 AL */
-#define UIC_PE1VA 0x00400000 /* PE1 VPD access */
-#define UIC_PE1HRR 0x00200000 /* PE1 Host reset request rising */
-#define UIC_PE1HRF 0x00100000 /* PE1 Host reset request falling */
-#define UIC_PE1TCR 0x00080000 /* PE1 TCR */
-#define UIC_PE1BVCO 0x00040000 /* PE1 Busmaster VCO */
-#define UIC_PE1DCRE 0x00020000 /* PE1 DCR error */
-#define UIC_PE2AL 0x00008000 /* PE2 AL */
-#define UIC_PE2VA 0x00004000 /* PE2 VPD access */
-#define UIC_PE2HRR 0x00002000 /* PE2 Host reset request rising */
-#define UIC_PE2HRF 0x00001000 /* PE2 Host reset request falling */
-#define UIC_PE2TCR 0x00000800 /* PE2 TCR */
-#define UIC_PE2BVCO 0x00000400 /* PE2 Busmaster VCO */
-#define UIC_PE2DCRE 0x00000200 /* PE2 DCR error */
-#define UIC_EIR5 0x00000080 /* External interrupt 5 */
-#define UIC_EIR4 0x00000040 /* External interrupt 4 */
-#define UIC_EIR3 0x00000020 /* External interrupt 3 */
-#define UIC_EIR2 0x00000010 /* External interrupt 2 */
-#define UIC_EIR1 0x00000008 /* External interrupt 1 */
-#define UIC_EIR0 0x00000004 /* External interrupt 0 */
-#endif /* CONFIG_440SPE */
-
-/*-----------------------------------------------------------------------------+
-| External Bus Controller Bit Settings
-+-----------------------------------------------------------------------------*/
-#define EBC_CFGADDR_MASK 0x0000003F
-
-#define EBC_BXCR_BAS_ENCODE(n) ((((unsigned long)(n))&0xFFF00000)<<0)
-#define EBC_BXCR_BS_MASK 0x000E0000
-#define EBC_BXCR_BS_1MB 0x00000000
-#define EBC_BXCR_BS_2MB 0x00020000
-#define EBC_BXCR_BS_4MB 0x00040000
-#define EBC_BXCR_BS_8MB 0x00060000
-#define EBC_BXCR_BS_16MB 0x00080000
-#define EBC_BXCR_BS_32MB 0x000A0000
-#define EBC_BXCR_BS_64MB 0x000C0000
-#define EBC_BXCR_BS_128MB 0x000E0000
-#define EBC_BXCR_BU_MASK 0x00018000
-#define EBC_BXCR_BU_R 0x00008000
-#define EBC_BXCR_BU_W 0x00010000
-#define EBC_BXCR_BU_RW 0x00018000
-#define EBC_BXCR_BW_MASK 0x00006000
-#define EBC_BXCR_BW_8BIT 0x00000000
-#define EBC_BXCR_BW_16BIT 0x00002000
-#define EBC_BXCR_BW_32BIT 0x00006000
-#define EBC_BXAP_BME_ENABLED 0x80000000
-#define EBC_BXAP_BME_DISABLED 0x00000000
-#define EBC_BXAP_TWT_ENCODE(n) ((((unsigned long)(n))&0xFF)<<23)
-#define EBC_BXAP_BCE_DISABLE 0x00000000
-#define EBC_BXAP_BCE_ENABLE 0x00400000
-#define EBC_BXAP_BCT_MASK 0x00300000
-#define EBC_BXAP_BCT_2TRANS 0x00000000
-#define EBC_BXAP_BCT_4TRANS 0x00100000
-#define EBC_BXAP_BCT_8TRANS 0x00200000
-#define EBC_BXAP_BCT_16TRANS 0x00300000
-#define EBC_BXAP_CSN_ENCODE(n) ((((unsigned long)(n))&0x3)<<18)
-#define EBC_BXAP_OEN_ENCODE(n) ((((unsigned long)(n))&0x3)<<16)
-#define EBC_BXAP_WBN_ENCODE(n) ((((unsigned long)(n))&0x3)<<14)
-#define EBC_BXAP_WBF_ENCODE(n) ((((unsigned long)(n))&0x3)<<12)
-#define EBC_BXAP_TH_ENCODE(n) ((((unsigned long)(n))&0x7)<<9)
-#define EBC_BXAP_RE_ENABLED 0x00000100
-#define EBC_BXAP_RE_DISABLED 0x00000000
-#define EBC_BXAP_SOR_DELAYED 0x00000000
-#define EBC_BXAP_SOR_NONDELAYED 0x00000080
-#define EBC_BXAP_BEM_WRITEONLY 0x00000000
-#define EBC_BXAP_BEM_RW 0x00000040
-#define EBC_BXAP_PEN_DISABLED 0x00000000
-
-#define EBC_CFG_LE_MASK 0x80000000
-#define EBC_CFG_LE_UNLOCK 0x00000000
-#define EBC_CFG_LE_LOCK 0x80000000
-#define EBC_CFG_PTD_MASK 0x40000000
-#define EBC_CFG_PTD_ENABLE 0x00000000
-#define EBC_CFG_PTD_DISABLE 0x40000000
-#define EBC_CFG_RTC_MASK 0x38000000
-#define EBC_CFG_RTC_16PERCLK 0x00000000
-#define EBC_CFG_RTC_32PERCLK 0x08000000
-#define EBC_CFG_RTC_64PERCLK 0x10000000
-#define EBC_CFG_RTC_128PERCLK 0x18000000
-#define EBC_CFG_RTC_256PERCLK 0x20000000
-#define EBC_CFG_RTC_512PERCLK 0x28000000
-#define EBC_CFG_RTC_1024PERCLK 0x30000000
-#define EBC_CFG_RTC_2048PERCLK 0x38000000
-#define EBC_CFG_ATC_MASK 0x04000000
-#define EBC_CFG_ATC_HI 0x00000000
-#define EBC_CFG_ATC_PREVIOUS 0x04000000
-#define EBC_CFG_DTC_MASK 0x02000000
-#define EBC_CFG_DTC_HI 0x00000000
-#define EBC_CFG_DTC_PREVIOUS 0x02000000
-#define EBC_CFG_CTC_MASK 0x01000000
-#define EBC_CFG_CTC_HI 0x00000000
-#define EBC_CFG_CTC_PREVIOUS 0x01000000
-#define EBC_CFG_OEO_MASK 0x00800000
-#define EBC_CFG_OEO_HI 0x00000000
-#define EBC_CFG_OEO_PREVIOUS 0x00800000
-#define EBC_CFG_EMC_MASK 0x00400000
-#define EBC_CFG_EMC_NONDEFAULT 0x00000000
-#define EBC_CFG_EMC_DEFAULT 0x00400000
-#define EBC_CFG_PME_MASK 0x00200000
-#define EBC_CFG_PME_DISABLE 0x00000000
-#define EBC_CFG_PME_ENABLE 0x00200000
-#define EBC_CFG_PMT_MASK 0x001F0000
-#define EBC_CFG_PMT_ENCODE(n) ((((unsigned long)(n))&0x1F)<<12)
-#define EBC_CFG_PR_MASK 0x0000C000
-#define EBC_CFG_PR_16 0x00000000
-#define EBC_CFG_PR_32 0x00004000
-#define EBC_CFG_PR_64 0x00008000
-#define EBC_CFG_PR_128 0x0000C000
-
/*-----------------------------------------------------------------------------+
| SDR0 Bit Settings
+-----------------------------------------------------------------------------*/
#define SDR0_DDR0_TUNE_DECODE(n) ((((unsigned long)(n))>>0)&0x2FF)
#endif
-#if defined(CONFIG_440SPE)
+#if defined(CONFIG_440SPE) || defined(CONFIG_460SX)
#define SDR0_CP440 0x0180
#define SDR0_CP440_ERPN_MASK 0x30000000
#define SDR0_CP440_ERPN_MASK_HI 0x3000
/*-----------------------------------------------------------------------------+
| Clocking
+-----------------------------------------------------------------------------*/
-#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
#define PLLSYS0_FWD_DIV_A_MASK 0x000000f0 /* Fwd Div A */
#define PLLSYS0_FWD_DIV_B_MASK 0x0000000f /* Fwd Div B */
#define PLLSYS0_FB_DIV_MASK 0x0000ff00 /* Feedback divisor */
#endif /* CONFIG_440GX */
#if defined (CONFIG_440EPX) || defined (CONFIG_440GRX)
-/*--------------------------------------*/
-#define CPR0_PLLC 0x40
-#define CPR0_PLLC_RST_MASK 0x80000000
-#define CPR0_PLLC_RST_PLLLOCKED 0x00000000
-#define CPR0_PLLC_RST_PLLRESET 0x80000000
-#define CPR0_PLLC_ENG_MASK 0x40000000
-#define CPR0_PLLC_ENG_DISABLE 0x00000000
-#define CPR0_PLLC_ENG_ENABLE 0x40000000
-#define CPR0_PLLC_ENG_ENCODE(n) ((((unsigned long)(n))&0x01)<<30)
-#define CPR0_PLLC_ENG_DECODE(n) ((((unsigned long)(n))>>30)&0x01)
-#define CPR0_PLLC_SRC_MASK 0x20000000
-#define CPR0_PLLC_SRC_PLLOUTA 0x00000000
-#define CPR0_PLLC_SRC_PLLOUTB 0x20000000
-#define CPR0_PLLC_SRC_ENCODE(n) ((((unsigned long)(n))&0x01)<<29)
-#define CPR0_PLLC_SRC_DECODE(n) ((((unsigned long)(n))>>29)&0x01)
-#define CPR0_PLLC_SEL_MASK 0x07000000
-#define CPR0_PLLC_SEL_PLL 0x00000000
-#define CPR0_PLLC_SEL_CPU 0x01000000
-#define CPR0_PLLC_SEL_PER 0x05000000
-#define CPR0_PLLC_SEL_ENCODE(n) ((((unsigned long)(n))&0x07)<<24)
-#define CPR0_PLLC_SEL_DECODE(n) ((((unsigned long)(n))>>24)&0x07)
-#define CPR0_PLLC_TUNE_MASK 0x000003FF
-#define CPR0_PLLC_TUNE_ENCODE(n) ((((unsigned long)(n))&0x3FF)<<0)
-#define CPR0_PLLC_TUNE_DECODE(n) ((((unsigned long)(n))>>0)&0x3FF)
-/*--------------------------------------*/
-#define CPR0_PLLD 0x60
-#define CPR0_PLLD_FBDV_MASK 0x1F000000
-#define CPR0_PLLD_FBDV_ENCODE(n) ((((unsigned long)(n))&0x1F)<<24)
-#define CPR0_PLLD_FBDV_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x1F)+1)
-#define CPR0_PLLD_FWDVA_MASK 0x000F0000
-#define CPR0_PLLD_FWDVA_ENCODE(n) ((((unsigned long)(n))&0x0F)<<16)
-#define CPR0_PLLD_FWDVA_DECODE(n) ((((((unsigned long)(n))>>16)-1)&0x0F)+1)
-#define CPR0_PLLD_FWDVB_MASK 0x00000700
-#define CPR0_PLLD_FWDVB_ENCODE(n) ((((unsigned long)(n))&0x07)<<8)
-#define CPR0_PLLD_FWDVB_DECODE(n) ((((((unsigned long)(n))>>8)-1)&0x07)+1)
-#define CPR0_PLLD_LFBDV_MASK 0x0000003F
-#define CPR0_PLLD_LFBDV_ENCODE(n) ((((unsigned long)(n))&0x3F)<<0)
-#define CPR0_PLLD_LFBDV_DECODE(n) ((((((unsigned long)(n))>>0)-1)&0x3F)+1)
-/*--------------------------------------*/
-#define CPR0_PRIMAD 0x80
-#define CPR0_PRIMAD_PRADV0_MASK 0x07000000
-#define CPR0_PRIMAD_PRADV0_ENCODE(n) ((((unsigned long)(n))&0x07)<<24)
-#define CPR0_PRIMAD_PRADV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x07)+1)
-/*--------------------------------------*/
-#define CPR0_PRIMBD 0xA0
-#define CPR0_PRIMBD_PRBDV0_MASK 0x07000000
-#define CPR0_PRIMBD_PRBDV0_ENCODE(n) ((((unsigned long)(n))&0x07)<<24)
-#define CPR0_PRIMBD_PRBDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x07)+1)
-/*--------------------------------------*/
-#if 0
-#define CPR0_CPM0_ER 0xB0 /* CPM Enable Register */
-#define CPR0_CPM0_FR 0xB1 /* CPM Force Register */
-#define CPR0_CPM0_SR 0xB2 /* CPM Status Register */
-#define CPR0_CPM0_IIC0 0x80000000 /* Inter-Intergrated Circuit0 */
-#define CPR0_CPM0_IIC1 0x40000000 /* Inter-Intergrated Circuit1 */
-#define CPR0_CPM0_PCI 0x20000000 /* Peripheral Component Interconnect */
-#define CPR0_CPM0_USB1H 0x08000000 /* USB1.1 Host */
-#define CPR0_CPM0_FPU 0x04000000 /* PPC440 FPU */
-#define CPR0_CPM0_CPU 0x02000000 /* PPC440x5 Processor Core */
-#define CPR0_CPM0_DMA 0x01000000 /* Direct Memory Access Controller */
-#define CPR0_CPM0_BGO 0x00800000 /* PLB to OPB Bridge */
-#define CPR0_CPM0_BGI 0x00400000 /* OPB to PLB Bridge */
-#define CPR0_CPM0_EBC 0x00200000 /* External Bus Controller */
-#define CPR0_CPM0_NDFC 0x00100000 /* Nand Flash Controller */
-#define CPR0_CPM0_MADMAL 0x00080000 /* DDR SDRAM Controller or MADMAL ??? */
-#define CPR0_CPM0_DMC 0x00080000 /* DDR SDRAM Controller or MADMAL ??? */
-#define CPR0_CPM0_PLB4 0x00040000 /* PLB4 Arbiter */
-#define CPR0_CPM0_PLB4x3x 0x00020000 /* PLB4 to PLB3 */
-#define CPR0_CPM0_PLB3x4x 0x00010000 /* PLB3 to PLB4 */
-#define CPR0_CPM0_PLB3 0x00008000 /* PLB3 Arbiter */
-#define CPR0_CPM0_PPM 0x00002000 /* PLB Performance Monitor */
-#define CPR0_CPM0_UIC1 0x00001000 /* Universal Interrupt Controller 1 */
-#define CPR0_CPM0_GPIO 0x00000800 /* General Purpose IO */
-#define CPR0_CPM0_GPT 0x00000400 /* General Purpose Timer */
-#define CPR0_CPM0_UART0 0x00000200 /* Universal Asynchronous Rcver/Xmitter 0 */
-#define CPR0_CPM0_UART1 0x00000100 /* Universal Asynchronous Rcver/Xmitter 1 */
-#define CPR0_CPM0_UIC0 0x00000080 /* Universal Interrupt Controller 0 */
-#define CPR0_CPM0_TMRCLK 0x00000040 /* CPU Timer */
-#define CPR0_CPM0_EMC0 0x00000020 /* Ethernet 0 */
-#define CPR0_CPM0_EMC1 0x00000010 /* Ethernet 1 */
-#define CPR0_CPM0_UART2 0x00000008 /* Universal Asynchronous Rcver/Xmitter 2 */
-#define CPR0_CPM0_UART3 0x00000004 /* Universal Asynchronous Rcver/Xmitter 3 */
-#define CPR0_CPM0_USB2D 0x00000002 /* USB2.0 Device */
-#define CPR0_CPM0_USB2H 0x00000001 /* USB2.0 Host */
+#define CPR0_ICFG_RLI_MASK 0x80000000
+#define CPR0_SPCID_SPCIDV0_MASK 0x03000000
+#define CPR0_PERD_PERDV0_MASK 0x07000000
#endif
-/*--------------------------------------*/
-#define CPR0_OPBD 0xC0
-#define CPR0_OPBD_OPBDV0_MASK 0x03000000
-#define CPR0_OPBD_OPBDV0_ENCODE(n) ((((unsigned long)(n))&0x03)<<24)
-#define CPR0_OPBD_OPBDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x03)+1)
-/*--------------------------------------*/
-#define CPR0_PERD 0xE0
-#define CPR0_PERD_PERDV0_MASK 0x07000000
-#define CPR0_PERD_PERDV0_ENCODE(n) ((((unsigned long)(n))&0x07)<<24)
-#define CPR0_PERD_PERDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x07)+1)
-/*--------------------------------------*/
-#define CPR0_MALD 0x100
-#define CPR0_MALD_MALDV0_MASK 0x03000000
-#define CPR0_MALD_MALDV0_ENCODE(n) ((((unsigned long)(n))&0x03)<<24)
-#define CPR0_MALD_MALDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x03)+1)
-/*--------------------------------------*/
-#define CPR0_SPCID 0x120
-#define CPR0_SPCID_SPCIDV0_MASK 0x03000000
-#define CPR0_SPCID_SPCIDV0_ENCODE(n) ((((unsigned long)(n))&0x03)<<24)
-#define CPR0_SPCID_SPCIDV0_DECODE(n) ((((((unsigned long)(n))>>24)-1)&0x03)+1)
-/*--------------------------------------*/
-#define CPR0_ICFG 0x140
-#define CPR0_ICFG_RLI_MASK 0x80000000
-#define CPR0_ICFG_RLI_RESETCPR 0x00000000
-#define CPR0_ICFG_RLI_PRESERVECPR 0x80000000
-#define CPR0_ICFG_ICS_MASK 0x00000007
-#endif /* defined (CONFIG_440EPX) || defined (CONFIG_440GRX) */
/*-----------------------------------------------------------------------------
| IIC Register Offsets
#define IICDIRECTCNTL 0x10
/*-----------------------------------------------------------------------------
-| UART Register Offsets
-'----------------------------------------------------------------------------*/
-#define DATA_REG 0x00
-#define DL_LSB 0x00
-#define DL_MSB 0x01
-#define INT_ENABLE 0x01
-#define FIFO_CONTROL 0x02
-#define LINE_CONTROL 0x03
-#define MODEM_CONTROL 0x04
-#define LINE_STATUS 0x05
-#define MODEM_STATUS 0x06
-#define SCRATCH 0x07
-
-/*-----------------------------------------------------------------------------
| PCI Internal Registers et. al. (accessed via plb)
+----------------------------------------------------------------------------*/
#define PCIX0_CFGADR (CFG_PCI_BASE + 0x0ec00000)
* GPIO macro register defines
******************************************************************************/
#if defined(CONFIG_440GP) || defined(CONFIG_440GX) || \
- defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460SX)
#define GPIO0_BASE (CFG_PERIPHERAL_BASE+0x00000700)
#define GPIO0_OR (GPIO0_BASE+0x0)
#if defined(CONFIG_405EX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
#define CONFIG_SDRAM_PPC4xx_IBM_DDR2 /* IBM DDR(2) controller */
#endif
#endif
#include <asm/ppc4xx-sdram.h>
+#include <asm/ppc4xx-ebc.h>
+#if !defined(CONFIG_XILINX_440)
+#include <asm/ppc4xx-uic.h>
+#endif
/*
* Macro for generating register field mnemonics
#define SDR0_PFC1_EM_1000 (0x00200000)
#endif
+/*
+ * XMII bridge configurations for those systems (e.g. 405EX(r)) that do
+ * not have a pin function control (PFC) register to otherwise determine
+ * the bridge configuration.
+ */
+#define EMAC_PHY_MODE_NONE 0
+#define EMAC_PHY_MODE_NONE_RGMII 1
+#define EMAC_PHY_MODE_RGMII_NONE 2
+#define EMAC_PHY_MODE_RGMII_RGMII 3
+#define EMAC_PHY_MODE_NONE_GMII 4
+#define EMAC_PHY_MODE_GMII_NONE 5
+#define EMAC_PHY_MODE_NONE_MII 6
+#define EMAC_PHY_MODE_MII_NONE 7
+
/* ZMII Bridge Register addresses */
#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
#endif
/* RGMII Function Enable (FER) Register Bit Definitions */
-/* Note: for EMAC 2 and 3 only, 440GX only */
#define RGMII_FER_DIS (0x00)
#define RGMII_FER_RTBI (0x04)
#define RGMII_FER_RGMII (0x05)
#define RGMII_FER_TBI (0x06)
#define RGMII_FER_GMII (0x07)
+#define RGMII_FER_MII (RGMII_FER_GMII)
#define RGMII_FER_V(__x) ((__x - 2) * 4)
#if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \
defined(CONFIG_USB_OHCI_NEW) || defined (CONFIG_USB_SL811HS) || \
- defined(CONFIG_USB_ISP116X_HCD)
+ defined(CONFIG_USB_ISP116X_HCD) || defined(CONFIG_USB_R8A66597_HCD)
int usb_lowlevel_init(void);
int usb_lowlevel_stop(void);
setup_end_tag (bd);
#endif
- if (!images->autostart)
- return ;
-
/* we assume that the kernel is in place */
printf ("\nStarting kernel ...\n\n");
return;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return;
}
params = setup_ethernet_tags(params);
setup_end_tag(params);
- if (!images->autostart)
- return ;
-
printf("\nStarting kernel at %p (params at %p)...\n\n",
theKernel, params_start);
return;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return;
}
char *cmdline;
ulong ep = 0;
- if (!images->autostart)
- return;
-
#ifdef SHARED_RESOURCES
swap_to(FLASH);
#endif
return;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
}
#if defined(CONFIG_CMD_JFFS2) || \
(defined(CONFIG_CMD_NAND) \
- && !defined(CFG_NAND_LEGACY))
+ && !defined(CONFIG_NAND_LEGACY))
/* No ones complement version. JFFS2 (and other things ?)
* don't use ones compliment in their CRC calculations.
}
- if (!images->autostart)
- return ;
-
#ifdef DEBUG
printf ("## Transferring control to Linux (at address %08x) ...\n",
(u32)base_ptr);
return;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return;
}
#include <i2c.h>
#endif
+#ifdef CONFIG_CMD_SPI
+#include <spi.h>
+#endif
+
DECLARE_GLOBAL_DATA_PTR;
static char *failed = "*** failed ***\n";
}
#endif
+#if defined(CONFIG_HARD_SPI)
+static int init_func_spi (void)
+{
+ puts ("SPI: ");
+ spi_init ();
+ puts ("ready\n");
+ return (0);
+}
+#endif
+
/***********************************************************************/
/************************************************************************
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
+#if defined(CONFIG_HARD_SPI)
+ init_func_spi,
+#endif
init_func_ram,
#if defined(CFG_DRAM_TEST)
testdram,
show_boot_progress (15);
- if (!images->autostart)
- return;
/*
* Linux Kernel Parameters (passing board info data):
* r3: ptr to board info data
return ;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return ;
}
(ulong) theKernel);
#endif
- if (!images->autostart)
- return ;
-
theKernel (commandline);
/* does not return */
return;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return;
}
linux_env_set("eth1addr", cp);
}
- if (!images->autostart)
- return ;
-
/* we assume that the kernel is in place */
printf ("\nStarting kernel ...\n\n");
return;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return;
}
}
void (*kernel)(void) = (void (*)(void))ep;
- if (!images->autostart)
- return ;
-
/* For now we assume the Microtronix linux ... which only
* needs to be called ;-)
*/
return;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return;
}
#include <common.h>
#include <asm/processor.h>
#include <asm/mmu.h>
+#include <asm/io.h>
int write_bat (ppc_bat_t bat, unsigned long upper, unsigned long lower)
{
+ sync();
+
switch (bat) {
case DBAT0:
mtspr (DBAT0L, lower);
return (-1);
}
+ sync();
+ isync();
+
return (0);
}
ulong cmd_start, cmd_end, bootmap_base;
bd_t *kbd;
ulong ep = 0;
- void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
+ void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6,
+ ulong r7, ulong r8, ulong r9);
int ret;
ulong of_size = 0;
struct lmb *lmb = images->lmb;
puts ("Could not find kernel entry point!\n");
goto error;
}
- kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))ep;
-
+ kernel = (void (*)(bd_t *, ulong, ulong, ulong,
+ ulong, ulong, ulong))ep;
/* find ramdisk */
ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_PPC,
&rd_data_start, &rd_data_end);
#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500)
unlock_ram_in_cache();
#endif
- if (!images->autostart)
- return ;
#if defined(CONFIG_OF_LIBFDT)
if (of_flat_tree) { /* device tree; boot new style */
/*
* Linux Kernel Parameters (passing device tree):
- * r3: pointer to the fdt, followed by the board info data
- * r4: physical pointer to the kernel itself
- * r5: NULL
- * r6: NULL
- * r7: NULL
+ * r3: pointer to the fdt
+ * r4: 0
+ * r5: 0
+ * r6: epapr magic
+ * r7: size of IMA in bytes
+ * r8: 0
+ * r9: 0
*/
+#if defined(CONFIG_85xx) || defined(CONFIG_440)
+ #define EPAPR_MAGIC (0x45504150)
+#else
+ #define EPAPR_MAGIC (0x65504150)
+#endif
+
debug (" Booting using OF flat tree...\n");
- (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
+ (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC,
+ CFG_BOOTMAPSZ, 0, 0);
/* does not return */
} else
#endif
* r5: initrd_end - unused if r4 is 0
* r6: Start of command line string
* r7: End of command line string
+ * r8: 0
+ * r9: 0
*/
debug (" Booting using board info...\n");
- (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
+ (*kernel) (kbd, initrd_start, initrd_end,
+ cmd_start, cmd_end, 0, 0);
/* does not return */
}
return ;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return ;
}
}
/* ------------------------------------------------------------------------- */
-
+#ifndef CONFIG_NAND_SPL
unsigned long ticks2usec(unsigned long ticks)
{
ulong tbclk = get_tbclk();
return ((ulong)ticks);
}
-
+#endif
/* ------------------------------------------------------------------------- */
int init_timebase (void)
}
void (*kernel) (void) = (void (*)(void))ep;
- if (!images->autostart)
- return ;
-
/* Setup parameters */
memset(PARAM, 0, 0x1000); /* Clear zero page */
strcpy(COMMAND_LINE, bootargs);
return;
error:
- if (images->autostart)
- do_reset (cmdtp, flag, argc, argv);
+ do_reset (cmdtp, flag, argc, argv);
return;
}
bootargs = getenv("bootargs");
prepare_bootargs(bootargs);
- if (!images->autostart)
- return;
-
/* turn on mmu & setup context table & page table for process 0 (kernel) */
srmmu_init_cpu((unsigned int)kernel);
while (1) ;
error:
- if (images->autostart)
- do_reset(cmdtp, flag, argc, argv);
+ do_reset(cmdtp, flag, argc, argv);
return;
}
--- /dev/null
+#
+# (C) Copyright 2007
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+# (C) Copyright 2008 Freescale Semiconductor
+#
+# 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
+#
+
+NAND_SPL := y
+TEXT_BASE := 0xfff00000
+PAD_TO := 0xfff04000
+
+include $(TOPDIR)/config.mk
+
+LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds
+LDFLAGS = -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
+AFLAGS += -DCONFIG_NAND_SPL
+CFLAGS += -DCONFIG_NAND_SPL
+
+SOBJS = start.o ticks.o
+COBJS = nand_boot_fsl_elbc.o $(BOARD).o sdram.o ns16550.o nand_init.o time.o
+
+SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+__OBJS := $(SOBJS) $(COBJS)
+LNDIR := $(OBJTREE)/nand_spl/board/$(BOARDDIR)
+
+nandobj := $(OBJTREE)/nand_spl/
+
+ALL = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin
+
+all: $(obj).depend $(ALL)
+
+$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl
+ $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@
+
+$(nandobj)u-boot-spl.bin: $(nandobj)u-boot-spl
+ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
+
+$(nandobj)u-boot-spl: $(OBJS)
+ cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \
+ -Map $(nandobj)u-boot-spl.map \
+ -o $(nandobj)u-boot-spl
+
+# create symbolic links for common files
+
+$(obj)start.S:
+ ln -sf $(SRCTREE)/cpu/mpc83xx/start.S $(obj)start.S
+
+$(obj)nand_boot_fsl_elbc.c:
+ ln -sf $(SRCTREE)/nand_spl/nand_boot_fsl_elbc.c \
+ $(obj)nand_boot_fsl_elbc.c
+
+$(obj)sdram.c:
+ ln -sf $(SRCTREE)/board/$(BOARDDIR)/sdram.c $(obj)sdram.c
+
+$(obj)$(BOARD).c:
+ ln -sf $(SRCTREE)/board/$(BOARDDIR)/$(BOARD).c $(obj)$(BOARD).c
+
+$(obj)ns16550.c:
+ ln -sf $(SRCTREE)/drivers/serial/ns16550.c $(obj)ns16550.c
+
+$(obj)nand_init.c:
+ ln -sf $(SRCTREE)/cpu/mpc83xx/nand_init.c $(obj)nand_init.c
+
+$(obj)time.c:
+ ln -sf $(SRCTREE)/lib_ppc/time.c $(obj)time.c
+
+$(obj)ticks.S:
+ ln -sf $(SRCTREE)/lib_ppc/ticks.S $(obj)ticks.S
+
+#########################################################################
+
+$(obj)%.o: $(obj)%.S
+ $(CC) $(AFLAGS) -c -o $@ $<
+
+$(obj)%.o: $(obj)%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
--- /dev/null
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * 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_ARCH(powerpc)
+SECTIONS
+{
+ . = 0xfff00000;
+ .text : {
+ *(.text*)
+ . = ALIGN(16);
+ *(.rodata*)
+ *(.eh_frame)
+ }
+
+ . = ALIGN(8);
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ __got2_entries = (. - _GOT2_TABLE_) >> 2;
+ }
+
+ . = ALIGN(8);
+ __bss_start = .;
+ .bss (NOLOAD) : { *(.*bss) }
+ _end = .;
+}
+ENTRY(_start)
+ASSERT(_end <= 0xfff01000, "NAND bootstrap too big");
#include <common.h>
#include <nand.h>
+#include <asm/io.h>
#define CFG_NAND_READ_DELAY \
{ volatile int dummy; int i; for (i=0; i<10000; i++) dummy = i; }
int page_addr = page + block * CFG_NAND_PAGE_COUNT;
if (this->dev_ready)
- this->dev_ready(mtd);
+ while (!this->dev_ready(mtd))
+ ;
else
CFG_NAND_READ_DELAY;
/* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- this->write_byte(mtd, cmd);
+ this->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
/* Set ALE and clear CLE to start address cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
- this->hwcontrol(mtd, NAND_CTL_SETALE);
/* Column address */
- this->write_byte(mtd, offs); /* A[7:0] */
- this->write_byte(mtd, (uchar)(page_addr & 0xff)); /* A[16:9] */
- this->write_byte(mtd, (uchar)((page_addr >> 8) & 0xff)); /* A[24:17] */
+ this->cmd_ctrl(mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ this->cmd_ctrl(mtd, page_addr & 0xff, 0); /* A[16:9] */
+ this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff, 0); /* A[24:17] */
#ifdef CFG_NAND_4_ADDR_CYCLE
/* One more address cycle for devices > 32MiB */
- this->write_byte(mtd, (uchar)((page_addr >> 16) & 0x0f)); /* A[xx:25] */
+ this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f, 0); /* A[28:25] */
#endif
/* Latch in address */
- this->hwcontrol(mtd, NAND_CTL_CLRALE);
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* Wait a while for the data to be ready
*/
if (this->dev_ready)
- this->dev_ready(mtd);
+ while (!this->dev_ready(mtd))
+ ;
else
CFG_NAND_READ_DELAY;
static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 cmd)
{
struct nand_chip *this = mtd->priv;
- int page_offs = offs;
int page_addr = page + block * CFG_NAND_PAGE_COUNT;
if (this->dev_ready)
- this->dev_ready(mtd);
+ while (!this->dev_ready(mtd))
+ ;
else
CFG_NAND_READ_DELAY;
/* Emulate NAND_CMD_READOOB */
if (cmd == NAND_CMD_READOOB) {
- page_offs += CFG_NAND_PAGE_SIZE;
+ offs += CFG_NAND_PAGE_SIZE;
cmd = NAND_CMD_READ0;
}
/* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- this->write_byte(mtd, cmd);
+ this->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
/* Set ALE and clear CLE to start address cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
- this->hwcontrol(mtd, NAND_CTL_SETALE);
/* Column address */
- this->write_byte(mtd, page_offs & 0xff); /* A[7:0] */
- this->write_byte(mtd, (uchar)((page_offs >> 8) & 0xff)); /* A[11:9] */
+ this->cmd_ctrl(mtd, offs & 0xff,
+ NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
+ this->cmd_ctrl(mtd, (offs >> 8) & 0xff, 0); /* A[11:9] */
/* Row address */
- this->write_byte(mtd, (uchar)(page_addr & 0xff)); /* A[19:12] */
- this->write_byte(mtd, (uchar)((page_addr >> 8) & 0xff)); /* A[27:20] */
+ this->cmd_ctrl(mtd, (page_addr & 0xff), 0); /* A[19:12] */
+ this->cmd_ctrl(mtd, ((page_addr >> 8) & 0xff), 0); /* A[27:20] */
#ifdef CFG_NAND_5_ADDR_CYCLE
/* One more address cycle for devices > 128MiB */
- this->write_byte(mtd, (uchar)((page_addr >> 16) & 0x0f)); /* A[xx:28] */
+ this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f, 0); /* A[31:28] */
#endif
/* Latch in address */
- this->hwcontrol(mtd, NAND_CTL_CLRALE);
-
- /* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- /* Write out the start read command */
- this->write_byte(mtd, NAND_CMD_READSTART);
- /* End command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
+ this->cmd_ctrl(mtd, NAND_CMD_READSTART,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* Wait a while for the data to be ready
*/
if (this->dev_ready)
- this->dev_ready(mtd);
+ while (!this->dev_ready(mtd))
+ ;
else
CFG_NAND_READ_DELAY;
/*
* Read one byte
*/
- if (this->read_byte(mtd) != 0xff)
+ if (readb(this->IO_ADDR_R) != 0xff)
return 1;
return 0;
oob_data = ecc_calc + 0x200;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- this->enable_hwecc(mtd, NAND_ECC_READ);
+ this->ecc.hwctl(mtd, NAND_ECC_READ);
this->read_buf(mtd, p, eccsize);
- this->calculate_ecc(mtd, p, &ecc_calc[i]);
+ this->ecc.calculate(mtd, p, &ecc_calc[i]);
}
this->read_buf(mtd, oob_data, CFG_NAND_OOBSIZE);
* from correct_data(). We just hope that all possible errors
* are corrected by this routine.
*/
- stat = this->correct_data(mtd, p, &ecc_code[i], &ecc_calc[i]);
+ stat = this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
}
return 0;
}
-static int nand_load(struct mtd_info *mtd, int offs, int uboot_size, uchar *dst)
+static int nand_load(struct mtd_info *mtd, unsigned int offs,
+ unsigned int uboot_size, uchar *dst)
{
- int block;
- int blockcopy_count;
- int page;
+ unsigned int block, lastblock;
+ unsigned int page;
/*
- * offs has to be aligned to a block address!
+ * offs has to be aligned to a page address!
*/
block = offs / CFG_NAND_BLOCK_SIZE;
- blockcopy_count = 0;
+ lastblock = (offs + uboot_size - 1) / CFG_NAND_BLOCK_SIZE;
+ page = (offs % CFG_NAND_BLOCK_SIZE) / CFG_NAND_PAGE_SIZE;
- while (blockcopy_count < (uboot_size / CFG_NAND_BLOCK_SIZE)) {
+ while (block <= lastblock) {
if (!nand_is_bad_block(mtd, block)) {
/*
* Skip bad blocks
*/
- for (page = 0; page < CFG_NAND_PAGE_COUNT; page++) {
+ while (page < CFG_NAND_PAGE_COUNT) {
nand_read_page(mtd, block, page, dst);
dst += CFG_NAND_PAGE_SIZE;
+ page++;
}
- blockcopy_count++;
+ page = 0;
+ } else {
+ lastblock++;
}
block++;
struct nand_chip nand_chip;
nand_info_t nand_info;
int ret;
- void (*uboot)(void);
+ __attribute__((noreturn)) void (*uboot)(void);
/*
* Init board specific nand support
nand_chip.dev_ready = NULL; /* preset to NULL */
board_nand_init(&nand_chip);
+ if (nand_chip.select_chip)
+ nand_chip.select_chip(&nand_info, 0);
+
/*
* Load U-Boot image from NAND into RAM
*/
ret = nand_load(&nand_info, CFG_NAND_U_BOOT_OFFS, CFG_NAND_U_BOOT_SIZE,
(uchar *)CFG_NAND_U_BOOT_DST);
+ if (nand_chip.select_chip)
+ nand_chip.select_chip(&nand_info, -1);
+
/*
* Jump to U-Boot image
*/
- uboot = (void (*)(void))CFG_NAND_U_BOOT_START;
+ uboot = (void *)CFG_NAND_U_BOOT_START;
(*uboot)();
}
--- /dev/null
+/*
+ * NAND boot for Freescale Enhanced Local Bus Controller, Flash Control Machine
+ *
+ * (C) Copyright 2006-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * Copyright (c) 2008 Freescale Semiconductor, Inc.
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * 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 <asm/io.h>
+#include <asm/immap_83xx.h>
+#include <asm/fsl_lbc.h>
+#include <linux/mtd/nand.h>
+
+#define WINDOW_SIZE 8192
+
+static void nand_wait(void)
+{
+ lbus83xx_t *regs = (lbus83xx_t *)(CFG_IMMR + 0x5000);
+
+ for (;;) {
+ uint32_t status = in_be32(®s->ltesr);
+
+ if (status == 1)
+ return;
+
+ if (status & 1) {
+ puts("read failed (ltesr)\n");
+ for (;;);
+ }
+ }
+}
+
+static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
+{
+ lbus83xx_t *regs = (lbus83xx_t *)(CFG_IMMR + 0x5000);
+ uchar *buf = (uchar *)CFG_NAND_BASE;
+ int large = in_be32(®s->bank[0].or) & OR_FCM_PGS;
+ int block_shift = large ? 17 : 14;
+ int block_size = 1 << block_shift;
+ int page_size = large ? 2048 : 512;
+ int bad_marker = large ? page_size + 0 : page_size + 5;
+ int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2;
+ int pos = 0;
+
+ if (offs & (block_size - 1)) {
+ puts("bad offset\n");
+ for (;;);
+ }
+
+ if (large) {
+ fmr |= FMR_ECCM;
+ out_be32(®s->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
+ (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
+ out_be32(®s->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+ (FIR_OP_RBW << FIR_OP4_SHIFT));
+ } else {
+ out_be32(®s->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
+ out_be32(®s->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_RBW << FIR_OP3_SHIFT));
+ }
+
+ out_be32(®s->fbcr, 0);
+ clrsetbits_be32(®s->bank[0].br, BR_DECC, BR_DECC_CHK_GEN);
+
+ while (pos < uboot_size) {
+ int i = 0;
+ out_be32(®s->fbar, offs >> block_shift);
+
+ do {
+ int j;
+ unsigned int page_offs = (offs & (block_size - 1)) << 1;
+
+ out_be32(®s->ltesr, ~0);
+ out_be32(®s->lteatr, 0);
+ out_be32(®s->fpar, page_offs);
+ out_be32(®s->fmr, fmr);
+ out_be32(®s->lsor, 0);
+ nand_wait();
+
+ page_offs %= WINDOW_SIZE;
+
+ /*
+ * If either of the first two pages are marked bad,
+ * continue to the next block.
+ */
+ if (i++ < 2 && buf[page_offs + bad_marker] != 0xff) {
+ puts("skipping\n");
+ offs = (offs + block_size) & ~(block_size - 1);
+ pos &= ~(block_size - 1);
+ break;
+ }
+
+ for (j = 0; j < page_size; j++)
+ dst[pos + j] = buf[page_offs + j];
+
+ pos += page_size;
+ offs += page_size;
+ } while (offs & (block_size - 1));
+ }
+}
+
+/*
+ * The main entry for NAND booting. It's necessary that SDRAM is already
+ * configured and available since this code loads the main U-Boot image
+ * from NAND into SDRAM and starts it from there.
+ */
+void nand_boot(void)
+{
+ __attribute__((noreturn)) void (*uboot)(void);
+
+ udelay(1000000);
+
+ /*
+ * Load U-Boot image from NAND into RAM
+ */
+ nand_load(CFG_NAND_U_BOOT_OFFS, CFG_NAND_U_BOOT_SIZE,
+ (uchar *)CFG_NAND_U_BOOT_DST);
+
+ /*
+ * Jump to U-Boot image
+ */
+ puts("transfering control\n");
+ uboot = (void *)CFG_NAND_U_BOOT_START;
+ uboot();
+}
$(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^
$(STRIP) $@
+$(obj)bin2header$(SFX): $(obj)bin2header.o
+ $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^
+ $(STRIP) $@
+
$(obj)envcrc.o: $(src)envcrc.c
$(CC) -g $(CFLAGS) -c -o $@ $<
--- /dev/null
+/* bin2header.c - program to convert binary file into a C structure
+ * definition to be included in a header file.
+ *
+ * (C) Copyright 2008 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 <stdlib.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) {
+ fprintf(stderr, "%s needs one argument: the structure name\n",
+ argv[0]);
+ exit(1);
+ }
+
+ printf("/* bin2header output - automatically generated */\n");
+ printf("unsigned char %s[] = {\n", argv[1]);
+
+ while (1) {
+ int i, nread;
+ unsigned char buf[10];
+ nread = read(0, buf, sizeof(buf));
+ if (nread <= 0)
+ break;
+
+ printf("\t");
+ for (i = 0; i < nread - 1; i++)
+ printf("0x%02x, ", buf[i]);
+
+ printf("0x%02x,\n", buf[nread-1]);
+ }
+
+ printf("};\n");
+
+ exit(0);
+}