diff options
author | Stefan Roese <sr@denx.de> | 2008-08-14 08:25:13 +0200 |
---|---|---|
committer | Stefan Roese <sr@denx.de> | 2008-08-14 08:25:13 +0200 |
commit | becbbc7b2a1be44d38779c80ce94fb20e5e13f12 (patch) | |
tree | 38e933b70075e14b21fbb0eb891cc8c59d8e60be | |
parent | bc9019e19758a19a388fb20ef18dc771cd39fdda (diff) | |
parent | 2fd0aad443c966ce62008225e57b18e2dcf4e330 (diff) | |
download | u-boot-imx-becbbc7b2a1be44d38779c80ce94fb20e5e13f12.zip u-boot-imx-becbbc7b2a1be44d38779c80ce94fb20e5e13f12.tar.gz u-boot-imx-becbbc7b2a1be44d38779c80ce94fb20e5e13f12.tar.bz2 |
Merge branch 'master' of /home/stefan/git/u-boot/u-boot into next
520 files changed, 27870 insertions, 8225 deletions
@@ -1,3 +1,579 @@ +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 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 @@ -5117,6 +5693,18 @@ Date: Mon May 5 14:06:11 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 @@ -399,6 +399,11 @@ N: Stelian Pop 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 diff --git a/MAINTAINERS b/MAINTAINERS index cbe5c47..7efef6a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -239,6 +239,10 @@ The LEOX team <team@leox.org> ELPT860 MPC860T +Guennadi Liakhovetski <g.liakhovetski@gmx.de> + + linkstation MPC8241 + Dave Liu <daveliu@freescale.com> MPC8315ERDB MPC8315 @@ -311,6 +315,10 @@ Daniel Poirot <dan.poirot@windriver.com> sbc8240 MPC8240 sbc405 PPC405GP +Ricardo Ribalda <ricardo.ribalda@uam.es> + + ml507 PPC440x5 + Stefan Roese <sr@denx.de> P3M7448 MPC7448 @@ -412,14 +420,17 @@ Stephen Williams <steve@icarus.com> 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: @@ -523,6 +534,10 @@ Rolf Offermanns <rof@sysgo.de> 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 @@ -552,6 +567,13 @@ Robert Schwebel <r.schwebel@pengutronix.de> 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) @@ -566,22 +588,11 @@ Richard Woodruff <r-woodruff2@ti.com> omap2420h4 ARM1136EJS -Kyungmin Park <kyungmin.park@samsung.com> - - apollon ARM1136EJS - 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: @@ -679,6 +690,10 @@ Matthias Fuchs <matthias.fuchs@esd-electronics.com> TASREG MCF5249 +Hayden Fraser <Hayden.Fraser@freescale.com> + + M5253EVBE mcf52x2 + TsiChung Liew <Tsi-Chung.Liew@freescale.com> M52277EVB mcf5227x @@ -689,10 +704,6 @@ TsiChung Liew <Tsi-Chung.Liew@freescale.com> M5475EVB mcf547x_8x M5485EVB mcf547x_8x -Hayden Fraser <Hayden.Fraser@freescale.com> - - M5253EVBE mcf52x2 - ######################################################################### # AVR32 Systems: # # # @@ -716,6 +727,10 @@ Haavard Skinnemoen <hskinnemoen@atmel.com> # Board CPU # ######################################################################### +Yusuke Goda <goda.yusuke@renesas.com> + + MIGO-R SH7722 + Nobuhiro Iwamatsu <iwamatsu@nigauri.org> MS7750SE SH7750 @@ -732,10 +747,6 @@ Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> MS7720SE SH7720 -Yusuke Goda <goda.yusuke@renesas.com> - - MIGO-R SH7722 - ######################################################################### # Blackfin Systems: # # # @@ -209,6 +209,8 @@ LIST_4xx=" \ MIP405T \ ML2 \ ml300 \ + ml507 \ + ml507_flash \ ocotea \ OCRTC \ ORSG \ @@ -222,6 +224,7 @@ LIST_4xx=" \ PPChameleonEVB \ quad100hd \ rainier \ + redwood \ sbc405 \ sc3 \ sequoia \ @@ -24,7 +24,7 @@ VERSION = 1 PATCHLEVEL = 3 SUBLEVEL = 4 -EXTRAVERSION = -rc2 +EXTRAVERSION = U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) VERSION_FILE = $(obj)include/version_autogenerated.h @@ -210,7 +210,7 @@ LIBS += cpu/ixp/npe/libnpe.a 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 @@ -378,6 +378,7 @@ TAG_SUBDIRS += fs/cramfs 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 @@ -1348,6 +1349,17 @@ ML2_config: 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 @@ -1409,6 +1421,9 @@ PPChameleonEVB_HI_33_config: unconfig 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 @@ -1996,8 +2011,11 @@ TASREG_config : unconfig ######################################################################### 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 ; \ @@ -2005,6 +2023,11 @@ MPC8313ERDB_66_config: unconfig 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 @@ -2354,13 +2377,13 @@ at91rm9200dk_config : unconfig @$(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 @@ -2382,10 +2405,10 @@ mp2usb_config : unconfig ######################################################################### 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. @@ -2672,7 +2695,7 @@ imx31_phycore_config : unconfig @$(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 @@ -98,7 +98,7 @@ Where we come from: - 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: @@ -2064,7 +2064,7 @@ Configuration Settings: 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 @@ -3903,7 +3903,7 @@ may be rejected, even when they contain important and valuable stuff. 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: diff --git a/board/ads5121/Makefile b/board/ads5121/Makefile index 5b95682..52d0d3c 100644 --- a/board/ads5121/Makefile +++ b/board/ads5121/Makefile @@ -27,7 +27,7 @@ $(shell mkdir -p $(OBJTREE)/board/freescale/common) 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 diff --git a/board/ads5121/ads5121.c b/board/ads5121/ads5121.c index 8452054..ba3d7d2 100644 --- a/board/ads5121/ads5121.c +++ b/board/ads5121/ads5121.c @@ -23,14 +23,12 @@ #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 | \ @@ -124,7 +122,7 @@ long int fixed_sdram (void) 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; @@ -237,6 +235,56 @@ int misc_init_r(void) 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) { @@ -246,7 +294,9 @@ 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; } diff --git a/board/ads5121/iopin.c b/board/ads5121/iopin.c deleted file mode 100644 index a6792a0..0000000 --- a/board/ads5121/iopin.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * (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; -} diff --git a/board/ads5121/iopin.h b/board/ads5121/iopin.h deleted file mode 100644 index 7ef8472..0000000 --- a/board/ads5121/iopin.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * (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); diff --git a/board/amcc/katmai/katmai.c b/board/amcc/katmai/katmai.c index f2bed5c..08d89d7 100644 --- a/board/amcc/katmai/katmai.c +++ b/board/amcc/katmai/katmai.c @@ -349,7 +349,7 @@ int is_pci_host(struct pci_controller *hose) return 1; } -int katmai_pcie_card_present(int port) +static int katmai_pcie_card_present(int port) { u32 val; @@ -437,76 +437,6 @@ void pcie_setup_hoses(int busno) } #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 diff --git a/board/amcc/ocotea/ocotea.c b/board/amcc/ocotea/ocotea.c index eea1e1e..4d1d093 100644 --- a/board/amcc/ocotea/ocotea.c +++ b/board/amcc/ocotea/ocotea.c @@ -147,36 +147,48 @@ int board_early_init_f (void) /*-------------------------------------------------------------------- * 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); */ diff --git a/board/amcc/redwood/Makefile b/board/amcc/redwood/Makefile new file mode 100644 index 0000000..5793307 --- /dev/null +++ b/board/amcc/redwood/Makefile @@ -0,0 +1,50 @@ +# +# (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 + +######################################################################### diff --git a/board/amcc/redwood/config.mk b/board/amcc/redwood/config.mk new file mode 100644 index 0000000..f33336d --- /dev/null +++ b/board/amcc/redwood/config.mk @@ -0,0 +1,42 @@ +# +# (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 diff --git a/board/amcc/redwood/init.S b/board/amcc/redwood/init.S new file mode 100644 index 0000000..fcffada --- /dev/null +++ b/board/amcc/redwood/init.S @@ -0,0 +1,77 @@ +/* + * (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 diff --git a/board/amcc/redwood/redwood.c b/board/amcc/redwood/redwood.c new file mode 100644 index 0000000..37a0c31 --- /dev/null +++ b/board/amcc/redwood/redwood.c @@ -0,0 +1,456 @@ +/* + * 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 */ + +} diff --git a/board/amcc/redwood/redwood.h b/board/amcc/redwood/redwood.h new file mode 100644 index 0000000..89b87e6 --- /dev/null +++ b/board/amcc/redwood/redwood.h @@ -0,0 +1,50 @@ +/* + * (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_ */ diff --git a/board/amcc/redwood/u-boot.lds b/board/amcc/redwood/u-boot.lds new file mode 100644 index 0000000..2104cc2 --- /dev/null +++ b/board/amcc/redwood/u-boot.lds @@ -0,0 +1,147 @@ +/* + * (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 = .); +} diff --git a/board/amcc/sequoia/sequoia.c b/board/amcc/sequoia/sequoia.c index b833092..176d5cf 100644 --- a/board/amcc/sequoia/sequoia.c +++ b/board/amcc/sequoia/sequoia.c @@ -25,12 +25,11 @@ #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; @@ -93,6 +92,11 @@ int board_early_init_f(void) #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; @@ -335,7 +339,7 @@ int checkboard(void) */ 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 diff --git a/board/amcc/taishan/taishan.c b/board/amcc/taishan/taishan.c index b6c3065..fdd82e7 100644 --- a/board/amcc/taishan/taishan.c +++ b/board/amcc/taishan/taishan.c @@ -119,36 +119,48 @@ int board_early_init_f (void) /*-------------------------------------------------------------------- * 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); diff --git a/board/amcc/yucca/yucca.c b/board/amcc/yucca/yucca.c index 6608893..84c3938 100644 --- a/board/amcc/yucca/yucca.c +++ b/board/amcc/yucca/yucca.c @@ -677,7 +677,7 @@ int is_pci_host(struct pci_controller *hose) return 1; } -int yucca_pcie_card_present(int port) +static int yucca_pcie_card_present(int port) { u16 reg; @@ -879,10 +879,6 @@ void pcie_setup_hoses(int busno) 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)) | @@ -897,67 +893,23 @@ int misc_init_f (void) /* 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; } diff --git a/board/bf537-stamp/nand.c b/board/bf537-stamp/nand.c index 6ff0f4f..9800083 100644 --- a/board/bf537-stamp/nand.c +++ b/board/bf537-stamp/nand.c @@ -37,34 +37,29 @@ /* * 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) @@ -79,11 +74,11 @@ 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 @@ -98,8 +93,8 @@ void board_nand_init(struct nand_chip *nand) *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; } diff --git a/board/dave/PPChameleonEVB/nand.c b/board/dave/PPChameleonEVB/nand.c index 09c0b04..3ccbf65 100644 --- a/board/dave/PPChameleonEVB/nand.c +++ b/board/dave/PPChameleonEVB/nand.c @@ -21,7 +21,7 @@ */ #include <common.h> - +#include <asm/io.h> #if defined(CONFIG_CMD_NAND) @@ -31,31 +31,28 @@ * 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); } @@ -92,11 +89,11 @@ static int ppchameleonevb_device_ready(struct mtd_info *mtdinfo) * 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 @@ -108,9 +105,9 @@ static int ppchameleonevb_device_ready(struct mtd_info *mtdinfo) 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; diff --git a/board/delta/nand.c b/board/delta/nand.c index 5024056..4ce78a1 100644 --- a/board/delta/nand.c +++ b/board/delta/nand.c @@ -23,7 +23,7 @@ #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> @@ -69,7 +69,7 @@ static struct nand_oobinfo delta_oob = { /* * 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; } @@ -110,30 +110,6 @@ static void dfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len) } -/* - * 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; @@ -168,7 +144,7 @@ static void dfc_read_buf(struct mtd_info *mtd, u_char* const 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; } @@ -289,9 +265,10 @@ static void dfc_new_cmd(void) /* 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; @@ -439,7 +416,7 @@ static void dfc_gpio_init(void) * - 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 @@ -561,20 +538,18 @@ int board_nand_init(struct nand_chip *nand) /* 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; } diff --git a/board/esd/common/auto_update.c b/board/esd/common/auto_update.c index 7e6eea0..a1e0ce5 100644 --- a/board/esd/common/auto_update.c +++ b/board/esd/common/auto_update.c @@ -27,7 +27,7 @@ #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> @@ -58,7 +58,7 @@ extern int flash_sect_erase(ulong, ulong); 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 @@ -158,7 +158,7 @@ int au_do_update(int i, long sz) 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 @@ -241,7 +241,7 @@ int au_do_update(int i, long sz) 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); @@ -273,7 +273,7 @@ int au_do_update(int i, long sz) 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, @@ -298,7 +298,7 @@ int au_do_update(int i, long sz) 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, diff --git a/board/esd/common/esd405ep_nand.c b/board/esd/common/esd405ep_nand.c index 7bf6847..40d1efb 100644 --- a/board/esd/common/esd405ep_nand.c +++ b/board/esd/common/esd405ep_nand.c @@ -30,28 +30,26 @@ /* * 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); } @@ -77,9 +75,9 @@ int board_nand_init(struct nand_chip *nand) /* * 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; diff --git a/board/freescale/m5329evb/nand.c b/board/freescale/m5329evb/nand.c index 344a614..f84912e 100644 --- a/board/freescale/m5329evb/nand.c +++ b/board/freescale/m5329evb/nand.c @@ -40,36 +40,26 @@ DECLARE_GLOBAL_DATA_PTR; #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) @@ -103,8 +93,8 @@ int board_nand_init(struct nand_chip *nand) 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; diff --git a/board/freescale/mpc8313erdb/config.mk b/board/freescale/mpc8313erdb/config.mk index f768264..fd72a14 100644 --- a/board/freescale/mpc8313erdb/config.mk +++ b/board/freescale/mpc8313erdb/config.mk @@ -1 +1,7 @@ +ifndef NAND_SPL +sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp +endif + +ifndef TEXT_BASE TEXT_BASE = 0xFE000000 +endif diff --git a/board/freescale/mpc8313erdb/mpc8313erdb.c b/board/freescale/mpc8313erdb/mpc8313erdb.c index 7cbdb7b..ebb703d 100644 --- a/board/freescale/mpc8313erdb/mpc8313erdb.c +++ b/board/freescale/mpc8313erdb/mpc8313erdb.c @@ -29,6 +29,8 @@ #include <pci.h> #include <mpc83xx.h> #include <vsc7385.h> +#include <ns16550.h> +#include <nand.h> DECLARE_GLOBAL_DATA_PTR; @@ -50,6 +52,7 @@ int checkboard(void) return 0; } +#ifndef CONFIG_NAND_SPL static struct pci_region pci_regions[] = { { bus_start: CFG_PCI1_MEM_BASE, @@ -128,3 +131,32 @@ void ft_board_setup(void *blob, bd_t *bd) #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 diff --git a/board/freescale/mpc8313erdb/sdram.c b/board/freescale/mpc8313erdb/sdram.c index afd8b9d..3a6347f 100644 --- a/board/freescale/mpc8313erdb/sdram.c +++ b/board/freescale/mpc8313erdb/sdram.c @@ -58,8 +58,10 @@ static void resume_from_sleep(void) */ 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; @@ -100,6 +102,7 @@ static long fixed_sdram(void) /* enable DDR controller */ im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; +#endif return msize; } diff --git a/board/freescale/mpc8540ads/u-boot.lds b/board/freescale/mpc8540ads/u-boot.lds index 0e4f5a2..515d320 100644 --- a/board/freescale/mpc8540ads/u-boot.lds +++ b/board/freescale/mpc8540ads/u-boot.lds @@ -26,6 +26,12 @@ 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: */ @@ -57,7 +63,7 @@ SECTIONS *(.text) *(.fixup) *(.got1) - } + } :text _etext = .; PROVIDE (etext = .); .rodata : @@ -66,7 +72,7 @@ SECTIONS *(.rodata1) *(.rodata.str1.4) *(.eh_frame) - } + } :text .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -118,12 +124,12 @@ SECTIONS .bootpg ADDR(.text) + 0x7f000 : { cpu/mpc85xx/start.o (.bootpg) - } = 0xffff + } :text = 0xffff .resetvec ADDR(.text) + 0x7fffc : { *(.resetvec) - } = 0xffff + } :text = 0xffff . = ADDR(.text) + 0x80000; @@ -134,7 +140,7 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - } + } :bss . = ALIGN(4); _end = . ; diff --git a/board/freescale/mpc8541cds/u-boot.lds b/board/freescale/mpc8541cds/u-boot.lds index 1c583de..d728d8b 100644 --- a/board/freescale/mpc8541cds/u-boot.lds +++ b/board/freescale/mpc8541cds/u-boot.lds @@ -23,6 +23,12 @@ 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: */ @@ -54,7 +60,7 @@ SECTIONS *(.text) *(.fixup) *(.got1) - } + } :text _etext = .; PROVIDE (etext = .); .rodata : @@ -63,7 +69,7 @@ SECTIONS *(.rodata1) *(.rodata.str1.4) *(.eh_frame) - } + } :text .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -115,12 +121,12 @@ SECTIONS .bootpg ADDR(.text) + 0x7f000 : { cpu/mpc85xx/start.o (.bootpg) - } = 0xffff + } :text = 0xffff .resetvec ADDR(.text) + 0x7fffc : { *(.resetvec) - } = 0xffff + } :text = 0xffff . = ADDR(.text) + 0x80000; @@ -131,7 +137,7 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - } + } :bss . = ALIGN(4); _end = . ; diff --git a/board/freescale/mpc8544ds/u-boot.lds b/board/freescale/mpc8544ds/u-boot.lds index 500e647..a05ece5 100644 --- a/board/freescale/mpc8544ds/u-boot.lds +++ b/board/freescale/mpc8544ds/u-boot.lds @@ -23,6 +23,12 @@ 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: */ @@ -54,7 +60,7 @@ SECTIONS *(.text) *(.fixup) *(.got1) - } + } :text _etext = .; PROVIDE (etext = .); .rodata : @@ -63,7 +69,7 @@ SECTIONS *(.rodata1) *(.rodata.str1.4) *(.eh_frame) - } + } :text .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -115,12 +121,12 @@ SECTIONS .bootpg ADDR(.text) + 0x7f000 : { cpu/mpc85xx/start.o (.bootpg) - } = 0xffff + } :text = 0xffff .resetvec ADDR(.text) + 0x7fffc : { *(.resetvec) - } = 0xffff + } :text = 0xffff . = ADDR(.text) + 0x80000; @@ -131,7 +137,7 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - } + } :bss . = ALIGN(4); _end = . ; diff --git a/board/freescale/mpc8548cds/u-boot.lds b/board/freescale/mpc8548cds/u-boot.lds index 6b93395..d4a2f72 100644 --- a/board/freescale/mpc8548cds/u-boot.lds +++ b/board/freescale/mpc8548cds/u-boot.lds @@ -23,6 +23,12 @@ 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: */ @@ -54,7 +60,7 @@ SECTIONS *(.text) *(.fixup) *(.got1) - } + } :text _etext = .; PROVIDE (etext = .); .rodata : @@ -63,7 +69,7 @@ SECTIONS *(.rodata1) *(.rodata.str1.4) *(.eh_frame) - } + } :text .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -115,12 +121,12 @@ SECTIONS .bootpg ADDR(.text) + 0x7f000 : { cpu/mpc85xx/start.o (.bootpg) - } = 0xffff + } :text = 0xffff .resetvec ADDR(.text) + 0x7fffc : { *(.resetvec) - } = 0xffff + } :text = 0xffff . = ADDR(.text) + 0x80000; @@ -131,7 +137,7 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - } + } :bss . = ALIGN(4); _end = . ; diff --git a/board/freescale/mpc8555cds/u-boot.lds b/board/freescale/mpc8555cds/u-boot.lds index a18b3a7..11885e8 100644 --- a/board/freescale/mpc8555cds/u-boot.lds +++ b/board/freescale/mpc8555cds/u-boot.lds @@ -23,6 +23,12 @@ 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: */ @@ -54,7 +60,7 @@ SECTIONS *(.text) *(.fixup) *(.got1) - } + } :text _etext = .; PROVIDE (etext = .); .rodata : @@ -63,7 +69,7 @@ SECTIONS *(.rodata1) *(.rodata.str1.4) *(.eh_frame) - } + } :text .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -115,12 +121,12 @@ SECTIONS .bootpg ADDR(.text) + 0x7f000 : { cpu/mpc85xx/start.o (.bootpg) - } = 0xffff + } :text = 0xffff .resetvec ADDR(.text) + 0x7fffc : { *(.resetvec) - } = 0xffff + } :text = 0xffff . = ADDR(.text) + 0x80000; @@ -131,7 +137,7 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - } + } :bss . = ALIGN(4); _end = . ; diff --git a/board/freescale/mpc8560ads/u-boot.lds b/board/freescale/mpc8560ads/u-boot.lds index 0e4f5a2..515d320 100644 --- a/board/freescale/mpc8560ads/u-boot.lds +++ b/board/freescale/mpc8560ads/u-boot.lds @@ -26,6 +26,12 @@ 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: */ @@ -57,7 +63,7 @@ SECTIONS *(.text) *(.fixup) *(.got1) - } + } :text _etext = .; PROVIDE (etext = .); .rodata : @@ -66,7 +72,7 @@ SECTIONS *(.rodata1) *(.rodata.str1.4) *(.eh_frame) - } + } :text .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -118,12 +124,12 @@ SECTIONS .bootpg ADDR(.text) + 0x7f000 : { cpu/mpc85xx/start.o (.bootpg) - } = 0xffff + } :text = 0xffff .resetvec ADDR(.text) + 0x7fffc : { *(.resetvec) - } = 0xffff + } :text = 0xffff . = ADDR(.text) + 0x80000; @@ -134,7 +140,7 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - } + } :bss . = ALIGN(4); _end = . ; diff --git a/board/freescale/mpc8568mds/u-boot.lds b/board/freescale/mpc8568mds/u-boot.lds index 9d245e4..ad96410 100644 --- a/board/freescale/mpc8568mds/u-boot.lds +++ b/board/freescale/mpc8568mds/u-boot.lds @@ -23,6 +23,12 @@ 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: */ @@ -54,7 +60,7 @@ SECTIONS *(.text) *(.fixup) *(.got1) - } + } :text _etext = .; PROVIDE (etext = .); .rodata : @@ -63,7 +69,7 @@ SECTIONS *(.rodata1) *(.rodata.str1.4) *(.eh_frame) - } + } :text .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -115,12 +121,12 @@ SECTIONS .bootpg ADDR(.text) + 0x7f000 : { cpu/mpc85xx/start.o (.bootpg) - } = 0xffff + } :text = 0xffff .resetvec ADDR(.text) + 0x7fffc : { *(.resetvec) - } = 0xffff + } :text = 0xffff . = ADDR(.text) + 0x80000; @@ -131,7 +137,7 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - } + } :bss . = ALIGN(4); _end = . ; diff --git a/board/mx31ads/Makefile b/board/freescale/mx31ads/Makefile index a12f391..a12f391 100644 --- a/board/mx31ads/Makefile +++ b/board/freescale/mx31ads/Makefile diff --git a/board/mx31ads/config.mk b/board/freescale/mx31ads/config.mk index d34dc02..d34dc02 100644 --- a/board/mx31ads/config.mk +++ b/board/freescale/mx31ads/config.mk diff --git a/board/mx31ads/lowlevel_init.S b/board/freescale/mx31ads/lowlevel_init.S index e166058..e166058 100644 --- a/board/mx31ads/lowlevel_init.S +++ b/board/freescale/mx31ads/lowlevel_init.S diff --git a/board/mx31ads/mx31ads.c b/board/freescale/mx31ads/mx31ads.c index dd0e150..c24c47c 100644 --- a/board/mx31ads/mx31ads.c +++ b/board/freescale/mx31ads/mx31ads.c @@ -55,16 +55,16 @@ int board_init (void) 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); diff --git a/board/mx31ads/u-boot.lds b/board/freescale/mx31ads/u-boot.lds index 49713d4..c379460 100644 --- a/board/mx31ads/u-boot.lds +++ b/board/freescale/mx31ads/u-boot.lds @@ -37,11 +37,11 @@ SECTIONS /* 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) diff --git a/board/icecube/flash.c b/board/icecube/flash.c index 15e86d3..2d4026a 100644 --- a/board/icecube/flash.c +++ b/board/icecube/flash.c @@ -23,7 +23,7 @@ #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 @@ -490,4 +490,4 @@ static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data) return (res); } -#endif /*CFG_FLASH_CFI_DRIVER*/ +#endif /*CONFIG_FLASH_CFI_DRIVER*/ diff --git a/board/imx31_litekit/imx31_litekit.c b/board/imx31_litekit/imx31_litekit.c index 263dd9f..cb3e174 100644 --- a/board/imx31_litekit/imx31_litekit.c +++ b/board/imx31_litekit/imx31_litekit.c @@ -50,16 +50,16 @@ int board_init (void) 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); diff --git a/board/imx31_phycore/imx31_phycore.c b/board/imx31_phycore/imx31_phycore.c index 42ecb1e..ae93444 100644 --- a/board/imx31_phycore/imx31_phycore.c +++ b/board/imx31_phycore/imx31_phycore.c @@ -54,11 +54,11 @@ int board_init (void) 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 */ diff --git a/board/korat/korat.c b/board/korat/korat.c index 51874ea..0d90fb3 100644 --- a/board/korat/korat.c +++ b/board/korat/korat.c @@ -33,7 +33,7 @@ #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; @@ -575,7 +575,7 @@ int checkboard(void) */ 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 diff --git a/board/nc650/nand.c b/board/nc650/nand.c index 8617f74..7dca97f 100644 --- a/board/nc650/nand.c +++ b/board/nc650/nand.c @@ -22,7 +22,7 @@ */ #include <common.h> - +#include <asm/io.h> #if defined(CONFIG_CMD_NAND) @@ -32,57 +32,49 @@ /* * 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 @@ -93,11 +85,11 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd) * 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 @@ -109,8 +101,8 @@ static void nc650_hwcontrol(struct mtd_info *mtd, int cmd) 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; diff --git a/board/netstar/nand.c b/board/netstar/nand.c index b76d2a3..e3ab66f 100644 --- a/board/netstar/nand.c +++ b/board/netstar/nand.c @@ -21,6 +21,7 @@ */ #include <common.h> +#include <asm/io.h> #if defined(CONFIG_CMD_NAND) @@ -32,24 +33,29 @@ #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; } diff --git a/board/netta/netta.c b/board/netta/netta.c index 1183f33..bc31386 100644 --- a/board/netta/netta.c +++ b/board/netta/netta.c @@ -555,7 +555,7 @@ int board_early_init_f(void) 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> diff --git a/board/prodrive/alpr/alpr.c b/board/prodrive/alpr/alpr.c index 131a62d..cc491d0 100644 --- a/board/prodrive/alpr/alpr.c +++ b/board/prodrive/alpr/alpr.c @@ -48,36 +48,48 @@ int board_early_init_f (void) /*-------------------------------------------------------------------- * 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)); diff --git a/board/prodrive/alpr/nand.c b/board/prodrive/alpr/nand.c index 097e183..99f5737 100644 --- a/board/prodrive/alpr/nand.c +++ b/board/prodrive/alpr/nand.c @@ -56,43 +56,24 @@ static struct alpr_ndfc_regs *alpr_ndfc = NULL; * * 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) @@ -158,12 +139,10 @@ int board_nand_init(struct nand_chip *nand) { 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; diff --git a/board/prodrive/pdnb3/flash.c b/board/prodrive/pdnb3/flash.c index 518ea9c..0786324 100644 --- a/board/prodrive/pdnb3/flash.c +++ b/board/prodrive/pdnb3/flash.c @@ -24,7 +24,7 @@ #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) @@ -86,4 +86,4 @@ unsigned long flash_init(void) return size; } -#endif /* CFG_FLASH_CFI_DRIVER */ +#endif /* CONFIG_FLASH_CFI_DRIVER */ diff --git a/board/prodrive/pdnb3/nand.c b/board/prodrive/pdnb3/nand.c index b1e7041..1ce3c8c 100644 --- a/board/prodrive/pdnb3/nand.c +++ b/board/prodrive/pdnb3/nand.c @@ -52,40 +52,26 @@ static struct pdnb3_ndfc_regs *pdnb3_ndfc; * * 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) { @@ -152,16 +138,13 @@ int board_nand_init(struct nand_chip *nand) { 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; diff --git a/board/sandburst/karef/karef.c b/board/sandburst/karef/karef.c index 2d71d3b..72ce976 100644 --- a/board/sandburst/karef/karef.c +++ b/board/sandburst/karef/karef.c @@ -195,36 +195,48 @@ int board_early_init_f (void) /*--------------------------------------------------------------------+ * 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(); diff --git a/board/sandburst/metrobox/metrobox.c b/board/sandburst/metrobox/metrobox.c index 66cdfb1..c38850d 100644 --- a/board/sandburst/metrobox/metrobox.c +++ b/board/sandburst/metrobox/metrobox.c @@ -185,36 +185,48 @@ int board_early_init_f (void) /*--------------------------------------------------------------------+ * 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(); diff --git a/board/sc3/sc3nand.c b/board/sc3/sc3nand.c index 009567b..45eff28 100644 --- a/board/sc3/sc3nand.c +++ b/board/sc3/sc3nand.c @@ -39,30 +39,26 @@ 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) @@ -79,14 +75,14 @@ static void sc3_select_chip(struct mtd_info *mtd, int chip) 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; diff --git a/board/tqc/tqm8272/tqm8272.c b/board/tqc/tqm8272/tqm8272.c index cde0296..a0ec254 100644 --- a/board/tqc/tqm8272/tqm8272.c +++ b/board/tqc/tqm8272/tqm8272.c @@ -1068,24 +1068,22 @@ int update_flash_size (int flash_size) 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) @@ -1188,9 +1186,9 @@ int board_nand_init(struct nand_chip *nand) 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; diff --git a/board/tqc/tqm8xx/flash.c b/board/tqc/tqm8xx/flash.c index 4342ebc..1231c7c 100644 --- a/board/tqc/tqm8xx/flash.c +++ b/board/tqc/tqm8xx/flash.c @@ -33,7 +33,7 @@ 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) @@ -831,4 +831,4 @@ static int write_word (flash_info_t *info, ulong dest, ulong data) /*----------------------------------------------------------------------- */ -#endif /* !defined(CFG_FLASH_CFI_DRIVER) */ +#endif /* !defined(CONFIG_FLASH_CFI_DRIVER) */ diff --git a/board/xilinx/ml507/Makefile b/board/xilinx/ml507/Makefile new file mode 100644 index 0000000..7283704 --- /dev/null +++ b/board/xilinx/ml507/Makefile @@ -0,0 +1,58 @@ +# +# (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 + +######################################################################### diff --git a/board/xilinx/ml507/config.mk b/board/xilinx/ml507/config.mk new file mode 100644 index 0000000..e827e8a --- /dev/null +++ b/board/xilinx/ml507/config.mk @@ -0,0 +1,27 @@ +# +# (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 diff --git a/board/xilinx/ml507/init.S b/board/xilinx/ml507/init.S new file mode 100644 index 0000000..3228a65 --- /dev/null +++ b/board/xilinx/ml507/init.S @@ -0,0 +1,53 @@ +/* + * (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 diff --git a/board/xilinx/ml507/ml507.c b/board/xilinx/ml507/ml507.c new file mode 100644 index 0000000..d499303 --- /dev/null +++ b/board/xilinx/ml507/ml507.c @@ -0,0 +1,47 @@ +/* + * (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; +} diff --git a/board/xilinx/ml507/u-boot-ram.lds b/board/xilinx/ml507/u-boot-ram.lds new file mode 100644 index 0000000..2c98d27 --- /dev/null +++ b/board/xilinx/ml507/u-boot-ram.lds @@ -0,0 +1,134 @@ +/* + * (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 = .); +} diff --git a/board/xilinx/ml507/u-boot-rom.lds b/board/xilinx/ml507/u-boot-rom.lds new file mode 100644 index 0000000..d5da018 --- /dev/null +++ b/board/xilinx/ml507/u-boot-rom.lds @@ -0,0 +1,144 @@ +/* + * (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 = .); +} diff --git a/board/xilinx/ml507/xparameters.h b/board/xilinx/ml507/xparameters.h new file mode 100644 index 0000000..77d2ddf --- /dev/null +++ b/board/xilinx/ml507/xparameters.h @@ -0,0 +1,35 @@ +/* + * (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 diff --git a/board/xpedite1k/xpedite1k.c b/board/xpedite1k/xpedite1k.c index bc7e3bd..c94a345 100644 --- a/board/xpedite1k/xpedite1k.c +++ b/board/xpedite1k/xpedite1k.c @@ -59,36 +59,48 @@ int board_early_init_f(void) /*-------------------------------------------------------------------- * 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(); diff --git a/board/zylonite/nand.c b/board/zylonite/nand.c index ca16578..09bcbb2 100644 --- a/board/zylonite/nand.c +++ b/board/zylonite/nand.c @@ -69,7 +69,7 @@ static struct nand_oobinfo delta_oob = { /* * 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; } @@ -110,25 +110,6 @@ static void dfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len) } -/* - * 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) * @@ -168,7 +149,7 @@ static void dfc_read_buf(struct mtd_info *mtd, u_char* const 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; } @@ -289,9 +270,10 @@ static void dfc_new_cmd(void) /* 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; @@ -435,11 +417,11 @@ static void dfc_gpio_init(void) * 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 @@ -560,21 +542,18 @@ int board_nand_init(struct nand_chip *nand) /* 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; } diff --git a/common/ACEX1K.c b/common/ACEX1K.c index 76dc166..53677b8 100644 --- a/common/ACEX1K.c +++ b/common/ACEX1K.c @@ -28,8 +28,6 @@ #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) @@ -362,5 +360,3 @@ static int ACEX1K_ps_reloc (Altera_desc * desc, ulong reloc_offset) return ret_val; } - -#endif /* CONFIG_FPGA && CONFIG_FPGA_ALTERA && CONFIG_FPGA_ACEX1K */ diff --git a/common/Makefile b/common/Makefile index 4287108..c2b381b 100644 --- a/common/Makefile +++ b/common/Makefile @@ -28,9 +28,7 @@ LIB = $(obj)libcommon.a 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 @@ -64,7 +62,18 @@ COBJS-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.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 @@ -80,7 +89,7 @@ COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.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 @@ -98,14 +107,13 @@ COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.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 @@ -118,26 +126,23 @@ COBJS-y += env_nvram.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 diff --git a/common/altera.c b/common/altera.c index a2b5967..09dc0b2 100644 --- a/common/altera.c +++ b/common/altera.c @@ -41,8 +41,6 @@ #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); @@ -283,5 +281,3 @@ static int altera_validate (Altera_desc * desc, const char *fn) } /* ------------------------------------------------------------------------- */ - -#endif /* CONFIG_FPGA & CONFIG_FPGA_ALTERA */ diff --git a/common/bedbug.c b/common/bedbug.c index 3bf1fc3..60109cf 100644 --- a/common/bedbug.c +++ b/common/bedbug.c @@ -2,8 +2,6 @@ #include <common.h> -#if defined(CONFIG_CMD_BEDBUG) - #include <linux/ctype.h> #include <bedbug/bedbug.h> #include <bedbug/ppc.h> @@ -1252,5 +1250,3 @@ int find_next_address (unsigned char *nextaddr, int step_over, * warranties of merchantability and fitness for a particular * purpose. */ - -#endif diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 18d7100..5295969 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -138,7 +138,6 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) memset ((void *)&images, 0, sizeof (images)); images.verify = getenv_yesno ("verify"); - images.autostart = getenv_yesno ("autostart"); images.lmb = &lmb; lmb_init(&lmb); @@ -362,10 +361,9 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 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; diff --git a/common/cmd_doc.c b/common/cmd_doc.c index d7b2f53..a55ca41 100644 --- a/common/cmd_doc.c +++ b/common/cmd_doc.c @@ -14,6 +14,12 @@ #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 @@ -1629,3 +1635,6 @@ void doc_probe(unsigned long physadr) puts ("No DiskOnChip found\n"); } } +#else +void doc_probe(unsigned long physadr) {} +#endif diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index b4698be..c031d80 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -96,12 +96,12 @@ #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 @@ -476,7 +476,7 @@ static int part_del(struct mtd_device *dev, struct part_info *part) } } -#ifdef CFG_NAND_LEGACY +#ifdef CONFIG_NAND_LEGACY jffs2_free_cache(part); #endif list_del(&part->link); @@ -505,7 +505,7 @@ static void part_delall(struct list_head *head) 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); @@ -741,7 +741,7 @@ static int device_validate(u8 type, u8 num, u32 *size) } 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]; diff --git a/common/cmd_load.c b/common/cmd_load.c index 1b75a7b..ab167f5 100644 --- a/common/cmd_load.c +++ b/common/cmd_load.c @@ -424,7 +424,6 @@ write_record (char *buf) #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); @@ -631,11 +630,6 @@ void send_nack (int n) } -/* 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; @@ -643,25 +637,28 @@ int os_data_count; 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) { @@ -671,6 +668,7 @@ static void bin_data_char (char new_char) break; } } + static void set_kerm_bin_mode (unsigned long *addr) { bin_start_address = (char *) addr; @@ -686,16 +684,19 @@ void k_data_init (void) 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) { diff --git a/common/cmd_mp.c b/common/cmd_mp.c index b2a397c..c8444fb 100644 --- a/common/cmd_mp.c +++ b/common/cmd_mp.c @@ -34,9 +34,9 @@ cpu_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } 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; } diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 9e38bf7..fa7a438 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -11,13 +11,14 @@ #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) @@ -34,48 +35,58 @@ 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; } @@ -155,7 +166,7 @@ out: 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; @@ -182,8 +193,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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; } @@ -196,7 +207,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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); @@ -299,15 +310,14 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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; @@ -322,43 +332,29 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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, @@ -381,6 +377,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } return 1; } + if (strcmp(cmd, "biterr") == 0) { /* todo */ return 1; @@ -395,7 +392,12 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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; @@ -406,28 +408,28 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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"); @@ -436,6 +438,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; } } +#endif return 0; } @@ -443,6 +446,12 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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 { @@ -450,6 +459,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) "write and erase will probably fail\n"); return 1; } +#endif return 0; } @@ -459,54 +469,47 @@ usage: } 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) + ulong offset, ulong addr, char *cmd) { int r; 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); @@ -536,19 +539,10 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, 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); @@ -614,7 +608,7 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) else addr = CFG_LOAD_ADDR; return nand_load_image(cmdtp, &nand_info[dev->id->num], - part->offset, addr, argv[0]); + part->offset, addr, argv[0]); } } #endif @@ -669,11 +663,11 @@ usage: 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 @@ -726,10 +720,10 @@ void archflashwp(void *archdata, int wp); #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 @@ -839,11 +833,11 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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], '.'); @@ -892,8 +886,7 @@ int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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", @@ -1000,11 +993,11 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 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; @@ -1035,8 +1028,8 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 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; @@ -1084,4 +1077,4 @@ U_BOOT_CMD( #endif -#endif /* CFG_NAND_LEGACY */ +#endif /* CONFIG_NAND_LEGACY */ diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index ce99a38..5e2062b 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -12,8 +12,6 @@ #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> @@ -38,7 +36,7 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) onenand_init(); return 0; } - onenand_print_device_info(onenand_chip.device_id, 1); + printf("%s\n", onenand_mtd.name); return 0; default: @@ -58,8 +56,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } 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; @@ -92,8 +88,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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); @@ -111,8 +105,6 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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"); @@ -165,5 +157,3 @@ U_BOOT_CMD( "onenand block[.oob] addr block [page] [len] - " "read data with (block [, page]) to addr" ); - -#endif /* CONFIG_CMD_ONENAND */ diff --git a/common/cmd_reginfo.c b/common/cmd_reginfo.c index 0657e4b..c0a1459 100644 --- a/common/cmd_reginfo.c +++ b/common/cmd_reginfo.c @@ -93,11 +93,10 @@ int do_reginfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #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), diff --git a/common/cmd_yaffs2.c b/common/cmd_yaffs2.c new file mode 100644 index 0000000..ac4a518 --- /dev/null +++ b/common/cmd_yaffs2.c @@ -0,0 +1,215 @@ +#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" +); diff --git a/common/cyclon2.c b/common/cyclon2.c index 06f5e8a..479bebb 100644 --- a/common/cyclon2.c +++ b/common/cyclon2.c @@ -27,8 +27,6 @@ #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) @@ -301,5 +299,3 @@ static int CYC2_ps_reloc (Altera_desc * desc, ulong reloc_offset) return ret_val; } - -#endif /* CONFIG_FPGA && CONFIG_FPGA_ALTERA && CONFIG_FPGA_CYCLON2 */ diff --git a/common/docecc.c b/common/docecc.c index 5daa6fc..3412aff 100644 --- a/common/docecc.c +++ b/common/docecc.c @@ -31,8 +31,6 @@ #undef ECC_DEBUG #undef PSYCHO_DEBUG -#if defined(CONFIG_CMD_DOC) - #include <linux/mtd/doc2000.h> /* need to undef it (from asm/termbits.h) */ @@ -513,5 +511,3 @@ int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6]) free(Index_of); return nb_errors; } - -#endif diff --git a/common/env_nand.c b/common/env_nand.c index 104f085..a8f0de7 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -159,22 +159,23 @@ int writeenv(size_t offset, u_char *buf) { 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) @@ -261,21 +262,22 @@ int readenv (size_t offset, u_char * buf) { 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) @@ -345,12 +347,10 @@ void env_relocate_spec (void) 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) diff --git a/common/env_onenand.c b/common/env_onenand.c index ad5b1d7..dbd0883 100644 --- a/common/env_onenand.c +++ b/common/env_onenand.c @@ -66,7 +66,6 @@ void env_relocate_spec(void) size_t retlen; env_addr = CFG_ENV_ADDR; - env_addr -= (unsigned long) onenand_chip.base; /* Check OneNAND exist */ if (onenand_mtd.oobblock) @@ -101,7 +100,6 @@ int saveenv(void) 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; @@ -111,7 +109,6 @@ int saveenv(void) 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, (u_char *) env_ptr)) { printf("OneNAND: write failed at 0x%08x\n", instr.addr); diff --git a/common/fpga.c b/common/fpga.c index d16a92d..67a6c30 100644 --- a/common/fpga.c +++ b/common/fpga.c @@ -29,8 +29,6 @@ #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 @@ -335,5 +333,3 @@ int fpga_info( int devnum ) } /* ------------------------------------------------------------------------- */ - -#endif /* CONFIG_FPGA */ diff --git a/common/image.c b/common/image.c index 535c302..6d2ce32 100644 --- a/common/image.c +++ b/common/image.c @@ -189,7 +189,6 @@ int image_check_dcrc (image_header_t *hdr) return (dcrc == image_get_dcrc (hdr)); } - /** * image_multi_count - get component (sub-image) count * @hdr: pointer to the header of the multi component image @@ -833,7 +832,7 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, 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 diff --git a/common/lcd.c b/common/lcd.c index e3347ec..25f8664 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -55,8 +55,6 @@ #include <nand.h> #endif -#ifdef CONFIG_LCD - /************************************************************************/ /* ** FONT DATA */ /************************************************************************/ @@ -793,7 +791,7 @@ static void *lcd_logo (void) 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)); @@ -867,5 +865,3 @@ static void *lcd_logo (void) /************************************************************************/ /************************************************************************/ - -#endif /* CONFIG_LCD */ diff --git a/common/lynxkdi.c b/common/lynxkdi.c index a5dc887..5f12b0d 100644 --- a/common/lynxkdi.c +++ b/common/lynxkdi.c @@ -17,7 +17,6 @@ #include <asm/processor.h> #include <image.h> -#if defined(CONFIG_LYNXKDI) #include <lynxkdi.h> DECLARE_GLOBAL_DATA_PTR; @@ -66,5 +65,3 @@ void lynxkdi_boot (image_header_t *hdr) #else #error "Lynx KDI support not implemented for configured CPU" #endif - -#endif /* CONFIG_LYNXKDI */ diff --git a/common/miiphybb.c b/common/miiphybb.c index 537c15d..6446012 100644 --- a/common/miiphybb.c +++ b/common/miiphybb.c @@ -30,9 +30,6 @@ #include <ioports.h> #include <ppc_asm.tmpl> -#ifdef CONFIG_BITBANGMII - - /***************************************************************************** * * Utility to send the preamble, address, and register (common to read @@ -236,5 +233,3 @@ int bb_miiphy_write (char *devname, unsigned char addr, return 0; } - -#endif /* CONFIG_BITBANGMII */ diff --git a/common/soft_i2c.c b/common/soft_i2c.c index 5ef7f30..23db2ee 100644 --- a/common/soft_i2c.c +++ b/common/soft_i2c.c @@ -41,8 +41,6 @@ #endif #include <i2c.h> -#if defined(CONFIG_SOFT_I2C) - /* #define DEBUG_I2C */ #ifdef DEBUG_I2C @@ -423,6 +421,3 @@ void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val) { i2c_write(i2c_addr, reg, 1, &val, 1); } - - -#endif /* CONFIG_SOFT_I2C */ diff --git a/common/soft_spi.c b/common/soft_spi.c index c131650..25b589a 100644 --- a/common/soft_spi.c +++ b/common/soft_spi.c @@ -27,8 +27,6 @@ #include <common.h> #include <spi.h> -#if defined(CONFIG_SOFT_SPI) - #include <malloc.h> /*----------------------------------------------------------------------- @@ -193,5 +191,3 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, return(0); } - -#endif /* CONFIG_SOFT_SPI */ diff --git a/common/spartan2.c b/common/spartan2.c index 2f1ea2c..ebac388 100644 --- a/common/spartan2.c +++ b/common/spartan2.c @@ -25,8 +25,6 @@ #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) @@ -663,5 +661,3 @@ static int Spartan2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset) return ret_val; } - -#endif diff --git a/common/spartan3.c b/common/spartan3.c index d329e70..8f1ab80 100644 --- a/common/spartan3.c +++ b/common/spartan3.c @@ -30,8 +30,6 @@ #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) @@ -668,5 +666,3 @@ static int Spartan3_ss_reloc (Xilinx_desc * desc, ulong reloc_offset) return ret_val; } - -#endif diff --git a/common/stratixII.c b/common/stratixII.c index 85c461c..7556dbf 100644 --- a/common/stratixII.c +++ b/common/stratixII.c @@ -25,8 +25,6 @@ #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); @@ -231,5 +229,3 @@ int StratixII_ps_fpp_load (Altera_desc * desc, void *buf, size_t bsize, return FPGA_SUCCESS; } - -#endif /* defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ALTERA) && defined(CONFIG_FPGA_STRATIX_II) */ diff --git a/common/usb.c b/common/usb.c index a45d113..9502f39 100644 --- a/common/usb.c +++ b/common/usb.c @@ -50,8 +50,6 @@ #include <linux/ctype.h> #include <asm/byteorder.h> -#if defined(CONFIG_CMD_USB) - #include <usb.h> #ifdef CONFIG_4xx #include <asm/4xx_pci.h> @@ -1247,6 +1245,4 @@ int usb_hub_probe(struct usb_device *dev, int ifnum) return ret; } -#endif - /* EOF */ diff --git a/common/usb_kbd.c b/common/usb_kbd.c index c876495..04d9730e 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -28,8 +28,6 @@ #include <devices.h> #include <asm/byteorder.h> -#ifdef CONFIG_USB_KEYBOARD - #include <usb.h> #undef USB_KBD_DEBUG @@ -746,7 +744,4 @@ static int usb_kbd_get_hid_desc(struct usb_device *dev) } - #endif - -#endif /* CONFIG_USB_KEYBOARD */ diff --git a/common/usb_storage.c b/common/usb_storage.c index d8fbb69..94f659f 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -55,13 +55,9 @@ #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 @@ -1242,6 +1238,3 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type); return 1; } - -#endif /* CONFIG_USB_STORAGE */ -#endif diff --git a/common/virtex2.c b/common/virtex2.c index 665a503..52da1b2 100644 --- a/common/virtex2.c +++ b/common/virtex2.c @@ -31,8 +31,6 @@ #include <common.h> #include <virtex2.h> -#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_VIRTEX2) - #if 0 #define FPGA_DEBUG #endif @@ -552,6 +550,5 @@ static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset) } return ret_val; } -#endif /* vim: set ts=4 tw=78: */ diff --git a/common/xilinx.c b/common/xilinx.c index c898238..7b5e8c5 100644 --- a/common/xilinx.c +++ b/common/xilinx.c @@ -32,8 +32,6 @@ #include <spartan2.h> #include <spartan3.h> -#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_XILINX) - #if 0 #define FPGA_DEBUG #endif @@ -307,5 +305,3 @@ static int xilinx_validate (Xilinx_desc * desc, char *fn) return ret_val; } - -#endif /* CONFIG_FPGA && CONFIG_FPGA_XILINX */ diff --git a/cpu/arm1136/mx31/generic.c b/cpu/arm1136/mx31/generic.c index 29c08c1..dc031c9 100644 --- a/cpu/arm1136/mx31/generic.c +++ b/cpu/arm1136/mx31/generic.c @@ -81,12 +81,12 @@ void mx31_gpio_mux(unsigned long mode) { 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; } diff --git a/cpu/arm920t/s3c24x0/nand.c b/cpu/arm920t/s3c24x0/nand.c index e1bf128..14882cb 100644 --- a/cpu/arm920t/s3c24x0/nand.c +++ b/cpu/arm920t/s3c24x0/nand.c @@ -27,7 +27,7 @@ #endif #if defined(CONFIG_CMD_NAND) -#if !defined(CFG_NAND_LEGACY) +#if !defined(CONFIG_NAND_LEGACY) #include <nand.h> #include <s3c2410.h> diff --git a/cpu/arm926ejs/at91sam9/Makefile b/cpu/arm926ejs/at91/Makefile index 44cde1a..44cde1a 100644 --- a/cpu/arm926ejs/at91sam9/Makefile +++ b/cpu/arm926ejs/at91/Makefile diff --git a/cpu/arm926ejs/at91sam9/config.mk b/cpu/arm926ejs/at91/config.mk index 83040eb..31491a8 100644 --- a/cpu/arm926ejs/at91sam9/config.mk +++ b/cpu/arm926ejs/at91/config.mk @@ -1,3 +1,3 @@ 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 diff --git a/cpu/arm926ejs/at91sam9/ether.c b/cpu/arm926ejs/at91/ether.c index 7e11fe4..7e11fe4 100644 --- a/cpu/arm926ejs/at91sam9/ether.c +++ b/cpu/arm926ejs/at91/ether.c diff --git a/cpu/arm926ejs/at91sam9/lowlevel_init.S b/cpu/arm926ejs/at91/lowlevel_init.S index ec6ad5d..ec6ad5d 100644 --- a/cpu/arm926ejs/at91sam9/lowlevel_init.S +++ b/cpu/arm926ejs/at91/lowlevel_init.S diff --git a/cpu/arm926ejs/at91sam9/spi.c b/cpu/arm926ejs/at91/spi.c index c9fe6d8..c9fe6d8 100644 --- a/cpu/arm926ejs/at91sam9/spi.c +++ b/cpu/arm926ejs/at91/spi.c diff --git a/cpu/arm926ejs/at91sam9/timer.c b/cpu/arm926ejs/at91/timer.c index c79ec7e..c79ec7e 100644 --- a/cpu/arm926ejs/at91sam9/timer.c +++ b/cpu/arm926ejs/at91/timer.c diff --git a/cpu/arm926ejs/at91sam9/u-boot.lds b/cpu/arm926ejs/at91/u-boot.lds index 996f401..996f401 100644 --- a/cpu/arm926ejs/at91sam9/u-boot.lds +++ b/cpu/arm926ejs/at91/u-boot.lds diff --git a/cpu/arm926ejs/at91sam9/usb.c b/cpu/arm926ejs/at91/usb.c index 2a92f73..2a92f73 100644 --- a/cpu/arm926ejs/at91sam9/usb.c +++ b/cpu/arm926ejs/at91/usb.c diff --git a/cpu/arm926ejs/davinci/nand.c b/cpu/arm926ejs/davinci/nand.c index 36468e6..2aa01d6 100644 --- a/cpu/arm926ejs/davinci/nand.c +++ b/cpu/arm926ejs/davinci/nand.c @@ -42,9 +42,10 @@ */ #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> @@ -52,23 +53,23 @@ 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 */ @@ -88,18 +89,27 @@ static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) #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!" @@ -145,7 +155,7 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u 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--) { @@ -281,7 +291,7 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char * 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); @@ -306,7 +316,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd) 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; @@ -362,22 +372,26 @@ int board_nand_init(struct nand_chip *nand) #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; diff --git a/cpu/mpc512x/Makefile b/cpu/mpc512x/Makefile index 2be35b2..8ba8ae8 100644 --- a/cpu/mpc512x/Makefile +++ b/cpu/mpc512x/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk 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)) diff --git a/cpu/mpc512x/cpu.c b/cpu/mpc512x/cpu.c index b59f36d..703e188 100644 --- a/cpu/mpc512x/cpu.c +++ b/cpu/mpc512x/cpu.c @@ -131,22 +131,67 @@ void watchdog_reset (void) #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 diff --git a/cpu/mpc512x/iopin.c b/cpu/mpc512x/iopin.c new file mode 100644 index 0000000..3d7042d --- /dev/null +++ b/cpu/mpc512x/iopin.c @@ -0,0 +1,49 @@ +/* + * (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; +} diff --git a/cpu/mpc8260/pci.c b/cpu/mpc8260/pci.c index 940f5c0..8230364 100644 --- a/cpu/mpc8260/pci.c +++ b/cpu/mpc8260/pci.c @@ -457,7 +457,7 @@ void pci_mpc8250_init (struct pci_controller *hose) 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 diff --git a/cpu/mpc83xx/nand_init.c b/cpu/mpc83xx/nand_init.c new file mode 100644 index 0000000..e92f230 --- /dev/null +++ b/cpu/mpc83xx/nand_init.c @@ -0,0 +1,112 @@ +/* + * 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++); +} diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index c182174..16ed494 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -2,7 +2,7 @@ * 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. @@ -57,6 +57,10 @@ #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 * @@ -64,16 +68,16 @@ */ 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 /* @@ -165,7 +169,7 @@ boot_warm: /* time t 5 */ 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 */ @@ -181,7 +185,7 @@ in_flash: #if 1 /* Remapping flash with LAW0. */ bl remap_flash_by_law0 #endif -#endif /* CFG_RAMBOOT */ +#endif /* CFG_FLASHBOOT */ /* setup the bats */ bl setup_bats @@ -239,6 +243,7 @@ in_flash: /* run 1st part of board init code (in Flash)*/ bl board_init_f +#ifndef CONFIG_NAND_SPL /* * Vector Table */ @@ -428,6 +433,7 @@ int_return: lwz r1,GPR1(r1) SYNC rfi +#endif /* !CONFIG_NAND_SPL */ /* * This code initialises the E300 processor core @@ -496,88 +502,10 @@ init_e300_core: /* time t 10 */ 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: @@ -590,7 +518,6 @@ setup_bats: ori r3, r3, CFG_IBAT0U@l mtspr IBAT0L, r4 mtspr IBAT0U, r3 - isync /* DBAT 0 */ addis r4, r0, CFG_DBAT0L@h @@ -599,7 +526,6 @@ setup_bats: ori r3, r3, CFG_DBAT0U@l mtspr DBAT0L, r4 mtspr DBAT0U, r3 - isync /* IBAT 1 */ addis r4, r0, CFG_IBAT1L@h @@ -608,7 +534,6 @@ setup_bats: ori r3, r3, CFG_IBAT1U@l mtspr IBAT1L, r4 mtspr IBAT1U, r3 - isync /* DBAT 1 */ addis r4, r0, CFG_DBAT1L@h @@ -617,7 +542,6 @@ setup_bats: ori r3, r3, CFG_DBAT1U@l mtspr DBAT1L, r4 mtspr DBAT1U, r3 - isync /* IBAT 2 */ addis r4, r0, CFG_IBAT2L@h @@ -626,7 +550,6 @@ setup_bats: ori r3, r3, CFG_IBAT2U@l mtspr IBAT2L, r4 mtspr IBAT2U, r3 - isync /* DBAT 2 */ addis r4, r0, CFG_DBAT2L@h @@ -635,7 +558,6 @@ setup_bats: ori r3, r3, CFG_DBAT2U@l mtspr DBAT2L, r4 mtspr DBAT2U, r3 - isync /* IBAT 3 */ addis r4, r0, CFG_IBAT3L@h @@ -644,7 +566,6 @@ setup_bats: ori r3, r3, CFG_IBAT3U@l mtspr IBAT3L, r4 mtspr IBAT3U, r3 - isync /* DBAT 3 */ addis r4, r0, CFG_DBAT3L@h @@ -653,7 +574,6 @@ setup_bats: ori r3, r3, CFG_DBAT3U@l mtspr DBAT3L, r4 mtspr DBAT3U, r3 - isync #ifdef CONFIG_HIGH_BATS /* IBAT 4 */ @@ -663,7 +583,6 @@ setup_bats: ori r3, r3, CFG_IBAT4U@l mtspr IBAT4L, r4 mtspr IBAT4U, r3 - isync /* DBAT 4 */ addis r4, r0, CFG_DBAT4L@h @@ -672,7 +591,6 @@ setup_bats: ori r3, r3, CFG_DBAT4U@l mtspr DBAT4L, r4 mtspr DBAT4U, r3 - isync /* IBAT 5 */ addis r4, r0, CFG_IBAT5L@h @@ -681,7 +599,6 @@ setup_bats: ori r3, r3, CFG_IBAT5U@l mtspr IBAT5L, r4 mtspr IBAT5U, r3 - isync /* DBAT 5 */ addis r4, r0, CFG_DBAT5L@h @@ -690,7 +607,6 @@ setup_bats: ori r3, r3, CFG_DBAT5U@l mtspr DBAT5L, r4 mtspr DBAT5U, r3 - isync /* IBAT 6 */ addis r4, r0, CFG_IBAT6L@h @@ -699,7 +615,6 @@ setup_bats: ori r3, r3, CFG_IBAT6U@l mtspr IBAT6L, r4 mtspr IBAT6U, r3 - isync /* DBAT 6 */ addis r4, r0, CFG_DBAT6L@h @@ -708,7 +623,6 @@ setup_bats: ori r3, r3, CFG_DBAT6U@l mtspr DBAT6L, r4 mtspr DBAT6U, r3 - isync /* IBAT 7 */ addis r4, r0, CFG_IBAT7L@h @@ -717,7 +631,6 @@ setup_bats: ori r3, r3, CFG_IBAT7U@l mtspr IBAT7L, r4 mtspr IBAT7U, r3 - isync /* DBAT 7 */ addis r4, r0, CFG_DBAT7L@h @@ -726,12 +639,28 @@ setup_bats: 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 @@ -874,7 +803,7 @@ relocate_code: 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 */ @@ -987,6 +916,7 @@ in_ram: 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. @@ -1004,6 +934,8 @@ in_ram: stw r0,0(r4) bdnz 3b 4: +#endif + clear_bss: /* * Now clear BSS segment @@ -1037,6 +969,7 @@ clear_bss: mr r4, r10 /* Destination Address */ bl board_init_r +#ifndef CONFIG_NAND_SPL /* * Copy exception vector code to low memory * @@ -1119,6 +1052,7 @@ trap_reloc: stw r0, 4(r7) blr +#endif /* !CONFIG_NAND_SPL */ #ifdef CFG_INIT_RAM_LOCK lock_ram_in_cache: @@ -1142,6 +1076,7 @@ lock_ram_in_cache: sync blr +#ifndef CONFIG_NAND_SPL .globl unlock_ram_in_cache unlock_ram_in_cache: /* invalidate the INIT_RAM section */ @@ -1165,8 +1100,10 @@ unlock_ram_in_cache: 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 */ @@ -1245,3 +1182,4 @@ remap_flash_by_law0: stw r4, LBLAWBAR1(r3) stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */ blr +#endif /* CFG_FLASHBOOT */ diff --git a/cpu/mpc85xx/mp.c b/cpu/mpc85xx/mp.c index 554830f..4e09c9c 100644 --- a/cpu/mpc85xx/mp.c +++ b/cpu/mpc85xx/mp.c @@ -147,7 +147,7 @@ static void pq3_mp_up(unsigned long bootpg) 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); @@ -157,7 +157,7 @@ static void pq3_mp_up(unsigned long bootpg) /* 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); }; diff --git a/cpu/mpc85xx/release.S b/cpu/mpc85xx/release.S index a47edae..75676b5 100644 --- a/cpu/mpc85xx/release.S +++ b/cpu/mpc85xx/release.S @@ -173,7 +173,7 @@ __secondary_start_page: .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 */ diff --git a/cpu/mpc86xx/cpu_init.c b/cpu/mpc86xx/cpu_init.c index 78ba1ea..1fda3fe 100644 --- a/cpu/mpc86xx/cpu_init.c +++ b/cpu/mpc86xx/cpu_init.c @@ -26,8 +26,10 @@ * 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; @@ -121,3 +123,26 @@ int cpu_init_r(void) { 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; +} diff --git a/cpu/mpc86xx/start.S b/cpu/mpc86xx/start.S index c39dc46..03f2128 100644 --- a/cpu/mpc86xx/start.S +++ b/cpu/mpc86xx/start.S @@ -358,125 +358,6 @@ invalidate_bats: 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: * diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index e9940e8..1c36324 100644 --- a/cpu/ppc4xx/44x_spd_ddr2.c +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -50,9 +50,19 @@ #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 @@ -257,7 +267,6 @@ static void test(void); #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); @@ -607,7 +616,7 @@ phys_size_t initdram(int board_type) 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. @@ -2760,7 +2769,7 @@ calibration_loop: 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 (); } @@ -2946,169 +2955,8 @@ static void test(void) } #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 @@ -3222,8 +3070,96 @@ phys_size_t initdram(int board_type) #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 */ diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c index 4e863dc..8a38335 100644 --- a/cpu/ppc4xx/4xx_enet.c +++ b/cpu/ppc4xx/4xx_enet.c @@ -90,7 +90,6 @@ #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 @@ -122,11 +121,65 @@ * 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 @@ -166,9 +219,6 @@ /*-----------------------------------------------------------------------------+ * 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 @@ -200,12 +250,6 @@ struct eth_device *emac0_dev = NULL; #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) @@ -465,30 +509,88 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) #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); } @@ -1377,59 +1479,17 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, } } - -#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; /* @@ -1448,256 +1508,79 @@ int enetInt (struct eth_device *dev) 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 *-----------------------------------------------------------------------------*/ @@ -1883,6 +1766,7 @@ int ppc_4xx_eth_initialize (bd_t * bis) 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; @@ -2020,19 +1904,19 @@ int ppc_4xx_eth_initialize (bd_t * bis) 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; diff --git a/cpu/ppc4xx/4xx_uart.c b/cpu/ppc4xx/4xx_uart.c index a7587d4..766e586 100644 --- a/cpu/ppc4xx/4xx_uart.c +++ b/cpu/ppc4xx/4xx_uart.c @@ -46,7 +46,7 @@ #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> diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile index 800bb41..c773400 100644 --- a/cpu/ppc4xx/Makefile +++ b/cpu/ppc4xx/Makefile @@ -35,10 +35,8 @@ SOBJS += kgdb.o 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 @@ -47,11 +45,9 @@ COBJS += denali_data_eye.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 @@ -60,6 +56,15 @@ COBJS += traps.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)) diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c index 39f439d..bc9335a 100644 --- a/cpu/ppc4xx/cpu.c +++ b/cpu/ppc4xx/cpu.c @@ -184,6 +184,19 @@ static char *bootstrap_str[] = { 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[] = { @@ -266,7 +279,11 @@ int checkcpu (void) 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) || \ @@ -509,6 +526,30 @@ int checkcpu (void) 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; diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index ac64279..e2d0402 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -138,9 +138,10 @@ void reconfigure_pll(u32 new_cpu_freq) 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) @@ -273,6 +274,18 @@ cpu_init_f (void) 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 diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index 8620e2b..494bd8c 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -8,6 +8,10 @@ * (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. * @@ -31,31 +35,14 @@ #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 { @@ -63,15 +50,7 @@ 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) @@ -112,7 +91,7 @@ int interrupt_init_cpu (unsigned *decrementer_count) /* * 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; @@ -156,160 +135,38 @@ int interrupt_init_cpu (unsigned *decrementer_count) */ 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 */ @@ -320,55 +177,19 @@ void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg) 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; } @@ -380,7 +201,7 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 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, diff --git a/cpu/ppc4xx/iop480_uart.c b/cpu/ppc4xx/iop480_uart.c index 3af0767..0e3423f 100644 --- a/cpu/ppc4xx/iop480_uart.c +++ b/cpu/ppc4xx/iop480_uart.c @@ -26,7 +26,6 @@ #include <asm/processor.h> #include <asm/io.h> #include <watchdog.h> -#include <asm/ppc4xx-intvec.h> #ifdef CONFIG_SERIAL_MULTI #include <serial.h> diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c index 5b2ae88..72acfd0 100644 --- a/cpu/ppc4xx/ndfc.c +++ b/cpu/ppc4xx/ndfc.c @@ -31,7 +31,7 @@ #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) || \ @@ -44,65 +44,39 @@ #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)); @@ -114,7 +88,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtdinfo, 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; @@ -139,7 +113,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtdinfo, 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) @@ -154,7 +128,7 @@ static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len) 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) @@ -164,7 +138,7 @@ static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len 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) @@ -181,29 +155,43 @@ void board_nand_select_device(struct nand_chip *nand, int chip) * 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; @@ -218,11 +206,7 @@ int board_nand_init(struct nand_chip *nand) 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; } diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index 34bd721..d21bd82 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -205,7 +205,8 @@ ulong get_PCI_freq (void) #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, @@ -415,7 +416,8 @@ ulong get_PCI_freq (void) 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; @@ -448,6 +450,8 @@ void get_sys_info (sys_info_t * sysInfo) sysInfo->freqUART = sysInfo->freqPLB; } #else + +#if !defined(CONFIG_XILINX_440) void get_sys_info (sys_info_t * sysInfo) { unsigned long strp0; @@ -534,6 +538,7 @@ void get_sys_info (sys_info_t * sysInfo) } #endif +#endif /* CONFIG_XILINX_440 */ #if defined(CONFIG_YUCCA) unsigned long determine_sysper(void) diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index 426bf3c..97411bd 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -677,7 +677,8 @@ _start: /* 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 @@ -720,6 +721,19 @@ _start: 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 @@ -1415,7 +1429,8 @@ relocate_code: #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. diff --git a/cpu/ppc4xx/uic.c b/cpu/ppc4xx/uic.c new file mode 100644 index 0000000..7944c6c --- /dev/null +++ b/cpu/ppc4xx/uic.c @@ -0,0 +1,180 @@ +/* + * (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)); +} diff --git a/cpu/ppc4xx/usbdev.c b/cpu/ppc4xx/usbdev.c index d71ba77..faf7f08 100644 --- a/cpu/ppc4xx/usbdev.c +++ b/cpu/ppc4xx/usbdev.c @@ -6,8 +6,8 @@ #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 @@ -197,7 +197,7 @@ void usb_dev_init() /*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 diff --git a/cpu/ppc4xx/xilinx_irq.c b/cpu/ppc4xx/xilinx_irq.c new file mode 100644 index 0000000..7108777 --- /dev/null +++ b/cpu/ppc4xx/xilinx_irq.c @@ -0,0 +1,100 @@ +/* + * (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; +} diff --git a/doc/README.nand b/doc/README.nand index 647a6b8..171380e 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -57,14 +57,9 @@ Commands: 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 @@ -73,17 +68,15 @@ Commands: 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 @@ -191,7 +184,7 @@ We now use a complete rewrite of the NAND code based on what is in 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 @@ -215,12 +208,6 @@ JFFS2 related commands: 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) diff --git a/drivers/block/Makefile b/drivers/block/Makefile index a09cd2a..642582b 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -25,14 +25,14 @@ include $(TOPDIR)/config.mk 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) diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 3d82c62..52fd108 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -26,8 +26,6 @@ */ #include <common.h> -#ifdef CONFIG_SCSI_AHCI - #include <command.h> #include <pci.h> #include <asm/processor.h> @@ -700,4 +698,3 @@ void scsi_print_error(ccb * pccb) { /*The ahci error info can be read in the ahci driver*/ } -#endif diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c index 441a4dc..4c26b36 100644 --- a/drivers/block/ata_piix.c +++ b/drivers/block/ata_piix.c @@ -35,8 +35,6 @@ #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; @@ -756,5 +754,3 @@ int scan_sata(int dev) { return 0; } - -#endif diff --git a/drivers/block/sil680.c b/drivers/block/sil680.c index a6143df..052c3d3 100644 --- a/drivers/block/sil680.c +++ b/drivers/block/sil680.c @@ -27,7 +27,7 @@ * 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 @@ -54,7 +54,6 @@ */ #include <common.h> -#if defined(CFG_IDE_SIL680) #include <ata.h> #include <ide.h> #include <pci.h> @@ -106,5 +105,3 @@ int ide_preinit (void) void ide_set_reset (int flag) { return; } - -#endif /* CFG_IDE_SIL680 */ diff --git a/drivers/block/sym53c8xx.c b/drivers/block/sym53c8xx.c index b880435..44e998b 100644 --- a/drivers/block/sym53c8xx.c +++ b/drivers/block/sym53c8xx.c @@ -35,8 +35,6 @@ #include <common.h> -#ifdef CONFIG_SCSI_SYM53C8XX - #include <command.h> #include <pci.h> #include <asm/processor.h> @@ -870,6 +868,3 @@ void scsi_chip_init(void) #endif } #endif - - -#endif /* CONFIG_SCSI_SYM53C8XX */ diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 7d82c27..dfaab52 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -44,8 +44,6 @@ #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 @@ -255,4 +253,3 @@ static unsigned long systemace_read(int dev, unsigned long start, return blkcnt; } -#endif /* CONFIG_SYSTEMACE */ diff --git a/drivers/dma/MCD_dmaApi.c b/drivers/dma/MCD_dmaApi.c index b0062b7..5c95651 100644 --- a/drivers/dma/MCD_dmaApi.c +++ b/drivers/dma/MCD_dmaApi.c @@ -24,8 +24,6 @@ #include <common.h> -#ifdef CONFIG_FSLDMAFEC - #include <MCD_dma.h> #include <MCD_tasksInit.h> #include <MCD_progCheck.h> @@ -1023,4 +1021,3 @@ static void MCD_memcpy(int *dest, int *src, u32 size) for (i = 0; i < size; i += sizeof(int), dest++, src++) *dest = *src; } -#endif /* CONFIG_FSLDMAFEC */ diff --git a/drivers/dma/MCD_tasks.c b/drivers/dma/MCD_tasks.c index 06a2d53..4f6e346 100644 --- a/drivers/dma/MCD_tasks.c +++ b/drivers/dma/MCD_tasks.c @@ -24,8 +24,6 @@ #include <common.h> -#ifdef CONFIG_FSLDMAFEC - #include <MCD_dma.h> u32 MCD_varTab0[]; @@ -2430,5 +2428,3 @@ u32 MCD_ENetXmit_TDT[] = { #ifdef MCD_INCLUDE_EU MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; #endif - -#endif /* CONFIG_FSLDMAFEC */ diff --git a/drivers/dma/MCD_tasksInit.c b/drivers/dma/MCD_tasksInit.c index cf567db..2f19875 100644 --- a/drivers/dma/MCD_tasksInit.c +++ b/drivers/dma/MCD_tasksInit.c @@ -28,8 +28,6 @@ * Do not edit! */ -#ifdef CONFIG_FSLDMAFEC - #include <MCD_dma.h> extern dmaRegs *MCD_dmaBar; @@ -242,5 +240,3 @@ void MCD_startDmaENetXmit(char *bDBase, char *currBD, char *xmitFifoPtr, /* Set the task's Enable bit in its Task Control Register */ MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; } - -#endif /* CONFIG_FSLDMAFEC */ diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 7e17360..cf29efa 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk 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) diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 2933cb6..9a14407 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -25,9 +25,11 @@ include $(TOPDIR)/config.mk 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) diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index 22c2a4e..d152768 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -27,8 +27,6 @@ #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); @@ -670,5 +668,3 @@ static int kbd_reset (void) return 0; } - -#endif /* CONFIG_I8042_KBD */ diff --git a/drivers/input/keyboard.c b/drivers/input/keyboard.c index 54182a7..a634d76 100644 --- a/drivers/input/keyboard.c +++ b/drivers/input/keyboard.c @@ -11,8 +11,6 @@ #include <common.h> -#ifdef CONFIG_PS2KBD - #include <devices.h> #include <keyboard.h> @@ -301,5 +299,3 @@ int kbd_init (void) } return error; } - -#endif /* CONFIG_PS2KBD */ diff --git a/drivers/input/pc_keyb.c b/drivers/input/pc_keyb.c index 33e7c5f..25ad3e4 100644 --- a/drivers/input/pc_keyb.c +++ b/drivers/input/pc_keyb.c @@ -13,8 +13,6 @@ #include <common.h> -#ifdef CONFIG_PS2KBD - #include <keyboard.h> #include <pc_keyb.h> @@ -252,5 +250,3 @@ void pckbd_leds(unsigned char leds) kbd_send_data(KBD_CMD_SET_LEDS); kbd_send_data(leds); } - -#endif /* CONFIG_PS2KBD */ diff --git a/drivers/input/ps2mult.c b/drivers/input/ps2mult.c index 9515a0f..ecd5853 100644 --- a/drivers/input/ps2mult.c +++ b/drivers/input/ps2mult.c @@ -16,8 +16,6 @@ #include <common.h> -#ifdef CONFIG_PS2MULT - #include <pc_keyb.h> #include <asm/atomic.h> #include <ps2mult.h> @@ -462,5 +460,3 @@ int ps2mult_request_irq(void (*handler)(void *)) return 0; } - -#endif /* CONFIG_PS2MULT */ diff --git a/drivers/input/ps2ser.c b/drivers/input/ps2ser.c index c1741ea..480ffa2 100644 --- a/drivers/input/ps2ser.c +++ b/drivers/input/ps2ser.c @@ -15,8 +15,6 @@ #include <common.h> -#ifdef CONFIG_PS2SERIAL - #include <asm/io.h> #include <asm/atomic.h> #include <ps2mult.h> @@ -326,5 +324,3 @@ static void ps2ser_interrupt(void *dev_id) ps2mult_callback(atomic_read(&ps2buf_cnt)); } } - -#endif /* CONFIG_PS2SERIAL */ diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index fe8d3d8..01e0f39 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -25,10 +25,10 @@ include $(TOPDIR)/config.mk 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) diff --git a/drivers/misc/ali512x.c b/drivers/misc/ali512x.c index 90b45d9..d6a2c1f 100644 --- a/drivers/misc/ali512x.c +++ b/drivers/misc/ali512x.c @@ -32,8 +32,6 @@ #include <config.h> -#ifdef CONFIG_ALI152X - #include <common.h> #include <asm/io.h> #include <asm/ic/ali512x.h> @@ -418,6 +416,3 @@ int ali512x_cio_in(int pin) return data & bit; } - - -#endif diff --git a/drivers/misc/ns87308.c b/drivers/misc/ns87308.c index cf4d359..6642c2e 100644 --- a/drivers/misc/ns87308.c +++ b/drivers/misc/ns87308.c @@ -23,8 +23,6 @@ #include <config.h> -#ifdef CFG_NS87308 - #include <ns87308.h> void initialise_ns87308 (void) @@ -117,5 +115,3 @@ void initialise_ns87308 (void) PNP_PGCS_CSLINE_CONF(2, CFG_NS87308_CS2_CONF); #endif } - -#endif diff --git a/drivers/misc/status_led.c b/drivers/misc/status_led.c index ddb6c22..4ba3e18 100644 --- a/drivers/misc/status_led.c +++ b/drivers/misc/status_led.c @@ -35,8 +35,6 @@ /* ------------------------------------------------------------------------- */ -#ifdef CONFIG_STATUS_LED - typedef struct { led_id_t mask; int state; @@ -127,5 +125,3 @@ void status_led_set (int led, int state) } __led_set (ld->mask, state); } - -#endif /* CONFIG_STATUS_LED */ diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index ff932a1..6538f7a 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -25,11 +25,11 @@ include $(TOPDIR)/config.mk 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) diff --git a/drivers/mtd/at45.c b/drivers/mtd/at45.c index a9d13ff..d1a60aa 100644 --- a/drivers/mtd/at45.c +++ b/drivers/mtd/at45.c @@ -20,8 +20,6 @@ #include <config.h> #include <common.h> - -#ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> /* @@ -559,4 +557,3 @@ int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc) AT91F_DataFlashGetStatus(pDesc); return ((pDesc->command[1] == 0xFF) ? 0 : pDesc->command[1] & 0x3C); } -#endif diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index 31ee756..58295fe 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -39,7 +39,6 @@ #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 @@ -162,13 +161,13 @@ static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT }; /* 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. */ @@ -1949,12 +1948,14 @@ unsigned long flash_init (void) 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 @@ -2050,5 +2051,3 @@ unsigned long flash_init (void) #endif return (size); } - -#endif /* CFG_FLASH_CFI */ diff --git a/drivers/mtd/dataflash.c b/drivers/mtd/dataflash.c index 0ad48cd..049da69 100644 --- a/drivers/mtd/dataflash.c +++ b/drivers/mtd/dataflash.c @@ -56,7 +56,7 @@ int AT91F_DataflashInit (void) 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; @@ -65,6 +65,19 @@ int AT91F_DataflashInit (void) 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; diff --git a/drivers/mtd/mw_eeprom.c b/drivers/mtd/mw_eeprom.c index 2b33488..f32ced4 100644 --- a/drivers/mtd/mw_eeprom.c +++ b/drivers/mtd/mw_eeprom.c @@ -1,9 +1,6 @@ /* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */ #include <common.h> - -#ifdef CONFIG_MW_EEPROM - #include <ssi.h> /* @@ -237,5 +234,3 @@ int mw_eeprom_probe(int dev) } return 0; } - -#endif diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 7bd22a0..1923310 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -25,14 +25,19 @@ include $(TOPDIR)/config.mk 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) diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index fdd85c1..4cba810 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -16,12 +16,12 @@ * * 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> @@ -39,13 +39,13 @@ #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, @@ -65,7 +65,7 @@ static unsigned long __initdata doc_locations[] = { 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 }; @@ -77,7 +77,7 @@ struct doc_priv { 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; @@ -85,14 +85,10 @@ struct doc_priv { 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 }; @@ -103,35 +99,36 @@ 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 */ @@ -155,7 +152,7 @@ static struct rs_control *rs_decoder; * 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; @@ -176,11 +173,11 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) * 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)]; } @@ -201,7 +198,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) * 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) @@ -213,8 +210,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) 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) @@ -224,9 +220,8 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) 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; @@ -261,7 +256,8 @@ static int _DoC_WaitReady(struct doc_priv *doc) 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) { @@ -306,7 +302,8 @@ static inline int DoC_WaitReady(struct doc_priv *doc) DoC_Delay(doc, 2); } - if(debug) printk("DoC_WaitReady OK\n"); + if (debug) + printk("DoC_WaitReady OK\n"); return ret; } @@ -316,7 +313,8 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) 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); } @@ -331,37 +329,39 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) 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); } } @@ -374,28 +374,28 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, 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; @@ -408,12 +408,15 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) 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); @@ -426,12 +429,13 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) } 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) { @@ -465,7 +469,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd) 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; @@ -504,22 +508,20 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) 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; @@ -529,15 +531,14 @@ static void doc2001_readbuf(struct mtd_info *mtd, /* 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; @@ -547,7 +548,7 @@ static int doc2001_verifybuf(struct mtd_info *mtd, /* 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; @@ -567,81 +568,84 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) 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; } @@ -652,7 +656,8 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) 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 */ @@ -661,7 +666,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) } 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); @@ -678,65 +683,54 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip) 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; @@ -757,9 +751,9 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col 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 */ @@ -783,25 +777,26 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col 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: @@ -818,26 +813,26 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col 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) @@ -850,23 +845,25 @@ 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; } } @@ -885,7 +882,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) 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); @@ -904,7 +901,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) 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); @@ -917,8 +914,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) } /* 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; @@ -962,7 +958,8 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, 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; } @@ -970,17 +967,20 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, /* 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; @@ -1013,18 +1013,20 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ 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; } @@ -1033,7 +1035,8 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ 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); } @@ -1050,11 +1053,20 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ /*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. @@ -1063,28 +1075,28 @@ static struct nand_oobinfo doc200x_oobinfo = { 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; @@ -1097,8 +1109,8 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, /* 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; @@ -1106,8 +1118,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, 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; @@ -1115,19 +1126,23 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, 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" @@ -1136,7 +1151,6 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, mh->DataOrgID, mh->NumEraseUnits, mh->FirstPhysicalEUN, mh->FormattedSize, mh->UnitSizeFactor); -/*#endif */ blocks = mtd->size >> this->phys_erase_shift; maxblocks = min(32768U, mtd->erasesize - psize); @@ -1145,8 +1159,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, /* 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; @@ -1179,31 +1193,35 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, 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; @@ -1220,15 +1238,16 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, 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); @@ -1237,8 +1256,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, 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" @@ -1256,7 +1273,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, ((unsigned char *) &mh->OsakVersion)[2] & 0xf, ((unsigned char *) &mh->OsakVersion)[3] & 0xf, mh->PercentUsed); -/*#endif */ vshift = this->phys_erase_shift + mh->BlockMultiplierBits; @@ -1282,8 +1298,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, 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" @@ -1293,16 +1307,14 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, 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"; @@ -1311,8 +1323,10 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, 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) { @@ -1322,7 +1336,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, numparts++; } ret = numparts; -out: + out: kfree(buf); return ret; } @@ -1334,11 +1348,12 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd) 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; @@ -1385,8 +1400,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) 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; @@ -1396,8 +1410,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) 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; @@ -1412,12 +1425,13 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) 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) @@ -1431,7 +1445,6 @@ static inline int __init doc2000_init(struct mtd_info *mtd) 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; @@ -1449,7 +1462,6 @@ static inline int __init doc2001_init(struct mtd_info *mtd) 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; @@ -1481,16 +1493,15 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) 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"; @@ -1498,7 +1509,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) 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; @@ -1527,20 +1538,16 @@ static inline int __init doc_probe(unsigned long physadr) 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; @@ -1556,15 +1563,13 @@ static inline int __init doc_probe(unsigned long physadr) 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); @@ -1588,7 +1593,7 @@ static inline int __init doc_probe(unsigned long physadr) 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)) { @@ -1618,11 +1623,11 @@ static inline int __init doc_probe(unsigned long physadr) 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) { @@ -1634,16 +1639,13 @@ static inline int __init doc_probe(unsigned long physadr) 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); @@ -1655,17 +1657,19 @@ static inline int __init doc_probe(unsigned long physadr) 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; @@ -1699,11 +1703,11 @@ static inline int __init doc_probe(unsigned long physadr) 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; } @@ -1740,7 +1744,7 @@ static int __init init_nanddoc(void) */ 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; } @@ -1750,7 +1754,7 @@ static int __init init_nanddoc(void) 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]); } } @@ -1762,7 +1766,7 @@ static int __init init_nanddoc(void) goto outerr; } return 0; -outerr: + outerr: free_rs(rs_decoder); return ret; } diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c new file mode 100644 index 0000000..0bd1bdb --- /dev/null +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -0,0 +1,767 @@ +/* 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; +} diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 67ae9c8..1a1d8c4 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -11,8 +11,6 @@ */ #include <config.h> - -#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_FSL_UPM) #include <common.h> #include <asm/io.h> #include <asm/errno.h> @@ -20,8 +18,6 @@ #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); @@ -51,49 +47,38 @@ static void fsl_upm_run_pattern(struct fsl_upm *upm, int width, u32 cmd) } } -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"); } } @@ -148,13 +133,14 @@ int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun) 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) @@ -162,4 +148,3 @@ int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun) return 0; } -#endif /* CONFIG_CMD_NAND */ diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c index e44470e..ebd2acd 100644 --- a/drivers/mtd/nand/nand.c +++ b/drivers/mtd/nand/nand.c @@ -22,9 +22,6 @@ */ #include <common.h> - -#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY) - #include <nand.h> #ifndef CFG_NAND_BASE_LIST @@ -79,5 +76,3 @@ void nand_init(void) board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device); #endif } - -#endif diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 6416d15..0913bb8 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -10,39 +10,21 @@ * 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. @@ -51,8 +33,10 @@ /* 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> @@ -62,6 +46,7 @@ #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 @@ -72,10 +57,11 @@ #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> @@ -89,83 +75,67 @@ #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 @@ -174,33 +144,25 @@ static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int n */ /* 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 @@ -210,23 +172,10 @@ static void nand_release_device (struct mtd_info *mtd) * * Default read function for 8bit buswith */ -static u_char nand_read_byte(struct mtd_info *mtd) +static uint8_t 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) -{ - struct nand_chip *this = mtd->priv; - writeb(byte, this->IO_ADDR_W); + struct nand_chip *chip = mtd->priv; + return readb(chip->IO_ADDR_R); } /** @@ -236,24 +185,10 @@ static void nand_write_byte(struct mtd_info *mtd, u_char byte) * Default read function for 16bit buswith with * endianess conversion */ -static u_char nand_read_byte16(struct mtd_info *mtd) +static uint8_t 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) -{ - 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)); } /** @@ -265,40 +200,26 @@ static void nand_write_byte16(struct mtd_info *mtd, u_char byte) */ 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: @@ -314,13 +235,13 @@ static void nand_select_chip(struct mtd_info *mtd, int chip) * * 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); } /** @@ -331,13 +252,13 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) * * 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); } /** @@ -348,15 +269,14 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) * * 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; } @@ -368,15 +288,15 @@ static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) * * 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); } @@ -388,15 +308,15 @@ static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) * * 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); } /** @@ -407,15 +327,15 @@ static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len) * * 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; @@ -432,38 +352,36 @@ static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) 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; } @@ -478,22 +396,33 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) */ 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; } /** @@ -503,12 +432,12 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) * * 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; } /** @@ -521,16 +450,60 @@ static int nand_check_wp (struct mtd_info *mtd) * 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 @@ -542,21 +515,21 @@ static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, i * 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 */ @@ -565,38 +538,37 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in 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); + chip->cmd_ctrl(mtd, command, ctrl); - if (column != -1 || page_addr != -1) { - this->hwcontrol(mtd, NAND_CTL_SETALE); - - /* 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: @@ -607,32 +579,32 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in 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); } /** @@ -642,55 +614,53 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in * @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: @@ -698,51 +668,69 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, 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 * @@ -750,100 +738,97 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, */ /* 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; } - set_current_state (TASK_UNINTERRUPTIBLE); - add_wait_queue (&active->wq, &wait); - spin_unlock (&active->chip_lock); - schedule (); - remove_wait_queue (&active->wq, &wait); + 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(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; @@ -881,478 +866,305 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) #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) -{ - return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL); -} - - -/** - * 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 + * The hw generator calculates the error syndrome automatically. Therefor + * we need a special oob layout and handling. */ -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) +static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf) { - 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; + 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; - MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: 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, - "nand_read_ecc: Attempt read beyond end of device\n"); - *retlen = 0; - return -EINVAL; - } + chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->read_buf(mtd, p, eccsize); - /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd ,FL_READING); + if (chip->ecc.prepad) { + chip->read_buf(mtd, oob, chip->ecc.prepad); + oob += chip->ecc.prepad; + } - /* use userspace supplied oobinfo, if zero */ - if (oobsel == NULL) - oobsel = &mtd->oobinfo; + chip->ecc.hwctl(mtd, NAND_ECC_READSYN); + chip->read_buf(mtd, oob, eccbytes); + stat = chip->ecc.correct(mtd, p, oob, NULL); - /* Autoplace of oob data ? Use the default placement scheme */ - if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) - oobsel = this->autooob; + if (stat == -1) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; - eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; - oob_config = oobsel->eccpos; + oob += eccbytes; - /* Select the NAND device */ - chipnr = (int)(from >> this->chip_shift); - this->select_chip(mtd, chipnr); + if (chip->ecc.postpad) { + chip->read_buf(mtd, oob, chip->ecc.postpad); + oob += chip->ecc.postpad; + } + } - /* First we calculate the starting page */ - realpage = (int) (from >> this->page_shift); - page = realpage & this->pagemask; + /* Calculate remaining oob bytes */ + i = mtd->oobsize - (oob - chip->oob_poi); + if (i) + chip->read_buf(mtd, oob, i); - /* Get raw starting column */ - col = from & (mtd->oobblock - 1); + return 0; +} - end = mtd->oobblock; - ecc = this->eccsize; - eccbytes = this->eccbytes; +/** + * 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; +} - if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) - compareecc = 0; +/** + * 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; - oobreadlen = mtd->oobsize; - if (this->options & NAND_HWECC_SYNDROME) - oobreadlen -= oobsel->eccbytes; + stats = mtd->ecc_stats; - /* Loop until all data read */ - while (read < len) { + chipnr = (int)(from >> chip->chip_shift); + chip->select_chip(mtd, chipnr); - 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; + realpage = (int)(from >> chip->page_shift); + page = realpage & chip->pagemask; - /* 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; - } + col = (int)(from & (mtd->writesize - 1)); - /* Check, if we must send the read command */ - if (sndcmd) { - this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); - sndcmd = 0; - } + buf = ops->datbuf; + oob = ops->oobbuf; - /* 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]; + while(1) { + bytes = min(mtd->writesize - col, readlen); + aligned = (bytes == mtd->writesize); - eccsteps = this->eccsteps; + /* Is the current page in the buffer ? */ + if (realpage != chip->pagebuf || oob) { + bufpoi = aligned ? buf : chip->buffers->databuf; - 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; + if (likely(sndcmd)) { + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + sndcmd = 0; } -#else - puts("Reading data from NAND FLASH without ECC is not recommended\n"); -#endif - this->read_buf(mtd, data_poi, end); - break; - } - 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; + /* 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; - 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]); - } + /* Transfer not aligned data */ + if (!aligned) { + chip->pagebuf = realpage; + memcpy(buf, chip->buffers->databuf + col, bytes); } - 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; + 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); } - if (ecc_status == -1) { - MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " - "Failed ECC read, page 0x%08x\n", - page); - ecc_failed++; + 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; } - 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)); + readlen -= bytes; - if (read == len) + if (!readlen) break; /* For subsequent reads align to page boundary. */ @@ -1360,732 +1172,829 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, /* 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); + + 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); + } - this->read_buf (mtd, &buf[cnt], pagesize); + readlen -= len; + if (!readlen) + break; - len -= pagesize; - cnt += pagesize; - page++; + /* Increment page address */ + realpage++; - if (!this->dev_ready) - udelay (this->chip_delay); - else - while (!this->dev_ready(mtd)); + 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 */ - if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) + /* 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; - - MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", - (unsigned int) to, (int) len); - - /* Shift to get page */ - page = (int) (to >> this->page_shift); - chipnr = (int) (to >> this->chip_shift); + 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; - /* Mask to get column */ - column = to & (mtd->oobsize - 1); + ops->retlen = 0; + if (!writelen) + return 0; - /* 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; - - /* Calculate total length of data */ - total_len = 0; - for (i = 0; i < count; i++) - total_len += (int) vecs[i].iov_len; + MTDDEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", + (unsigned int)to, (int)ops->ooblen); - MTDDEBUG (MTD_DEBUG_LEVEL3, - "nand_writev: to = 0x%08x, len = %i, count = %ld\n", - (unsigned int) to, (unsigned int) total_len, count); + if (ops->mode == MTD_OOB_AUTO) + len = chip->ecc.layout->oobavail; + else + len = mtd->oobsize; /* 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 ((ops->ooboffs + ops->ooblen) > len) { + MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " + "Attempt to write past end of page\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"); + if (unlikely(ops->ooboffs >= len)) { + MTDDEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: " + "Attempt to start write outside oob\n"); return -EINVAL; } - /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd, FL_WRITING); + /* 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; + } - /* Get the current chip-nr */ - chipnr = (int) (to >> this->chip_shift); - /* Select the NAND device */ - this->select_chip(mtd, chipnr); + chipnr = (int)(to >> chip->chip_shift); + chip->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 @@ -2094,12 +2003,12 @@ out: * * 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); } /** @@ -2110,15 +2019,15 @@ static void single_erase_cmd (struct mtd_info *mtd, int page) * 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); } /** @@ -2128,35 +2037,39 @@ static void multi_erase_cmd (struct mtd_info *mtd, int page) * * 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; @@ -2172,19 +2085,18 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb 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, @@ -2193,52 +2105,92 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb 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 */ @@ -2248,6 +2200,23 @@ erase_exit: /* 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; } @@ -2258,41 +2227,40 @@ erase_exit: * * 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))) { @@ -2302,419 +2270,553 @@ static int nand_block_markbad (struct mtd_info *mtd, loff_t 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; - /* Get buswidth to select the correct functions*/ - busw = this->options & NAND_BUSWIDTH_16; + 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; + + 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 diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index a97743b..b3b740d 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -6,7 +6,7 @@ * * 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 @@ -48,14 +48,11 @@ * * 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> @@ -63,6 +60,19 @@ #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 @@ -76,9 +86,9 @@ * 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; @@ -96,9 +106,9 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des 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; @@ -108,6 +118,29 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des } /** + * 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 @@ -120,8 +153,8 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des * 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; @@ -130,17 +163,17 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, 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 */ @@ -150,22 +183,23 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, 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; @@ -185,7 +219,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, * 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; @@ -209,6 +243,42 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des 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 @@ -220,28 +290,84 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des * 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 @@ -253,13 +379,16 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de * 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); @@ -269,21 +398,28 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc 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; @@ -292,16 +428,29 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc } 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; } /** @@ -316,22 +465,23 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc * 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; @@ -357,13 +507,16 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr 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; } @@ -373,9 +526,10 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr /* 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; } @@ -389,21 +543,19 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr * * 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 * @@ -416,25 +568,31 @@ static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, * (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; @@ -443,7 +601,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, chip = chipsel; } } else { - numblocks = (int) (mtd->size >> this->bbt_erase_shift); + numblocks = (int)(mtd->size >> this->bbt_erase_shift); nrchips = 1; } @@ -472,27 +630,38 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, 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; } @@ -500,82 +669,92 @@ write: 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; } /** @@ -586,29 +765,27 @@ write: * 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; @@ -676,35 +853,35 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des 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; } @@ -721,7 +898,7 @@ writecheck: * 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; @@ -739,7 +916,8 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) 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)]; @@ -759,7 +937,8 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) 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 @@ -784,7 +963,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) * 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; @@ -793,53 +972,56 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) 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 @@ -847,7 +1029,7 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) * * 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; @@ -863,9 +1045,9 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) /* 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; } @@ -873,7 +1055,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) /* 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; @@ -886,29 +1068,26 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) /* 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 @@ -922,14 +1101,14 @@ static struct nand_bbt_descr largepage_memorybased = { }; 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 @@ -977,7 +1156,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { * 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; @@ -987,7 +1166,7 @@ int nand_default_bbt (struct mtd_info *mtd) * 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) { @@ -995,10 +1174,9 @@ int nand_default_bbt (struct mtd_info *mtd) 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 */ @@ -1007,18 +1185,17 @@ int nand_default_bbt (struct mtd_info *mtd) 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); } /** @@ -1027,26 +1204,33 @@ int nand_default_bbt (struct mtd_info *mtd) * @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 diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 4c532b0..ee1f6cc 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c @@ -7,7 +7,9 @@ * 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 @@ -37,7 +39,13 @@ #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> @@ -128,6 +136,10 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, 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) @@ -197,4 +209,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, return -1; } +/* XXX U-BOOT XXX */ +#if 0 +EXPORT_SYMBOL(nand_correct_data); #endif diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 7363490..2ff75c9 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -2,8 +2,8 @@ * 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 @@ -12,11 +12,7 @@ */ #include <common.h> - -#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY) - #include <linux/mtd/nand.h> - /* * Chip ID list * @@ -29,13 +25,15 @@ * 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}, @@ -44,6 +42,7 @@ struct nand_flash_dev nand_flash_ids[] = { {"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}, @@ -61,52 +60,72 @@ struct nand_flash_dev nand_flash_ids[] = { {"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,} }; @@ -121,7 +140,7 @@ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_NATIONAL, "National"}, {NAND_MFR_RENESAS, "Renesas"}, {NAND_MFR_STMICRO, "ST Micro"}, + {NAND_MFR_HYNIX, "Hynix"}, {NAND_MFR_MICRON, "Micron"}, {0x0, "Unknown"} }; -#endif diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 828cc33..22820d5 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -31,14 +31,14 @@ */ #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> @@ -69,71 +69,33 @@ static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip) 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 @@ -194,25 +156,21 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) /* 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) { @@ -232,11 +190,11 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) 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); } } } @@ -253,6 +211,9 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) return 0; } +/* XXX U-BOOT XXX */ +#if 0 + #define MAX_PAGE_SIZE 2048 #define MAX_OOB_SIZE 64 @@ -263,443 +224,29 @@ static unsigned char data_buf[MAX_PAGE_SIZE]; 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 *****************************************************************************/ @@ -784,7 +331,7 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset) 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"); @@ -813,7 +360,7 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset) * @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 */ @@ -839,14 +386,14 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length) 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; @@ -875,5 +422,184 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length) 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; +} diff --git a/drivers/mtd/nand_legacy/Makefile b/drivers/mtd/nand_legacy/Makefile index 4e29c36..a1a9cc9 100644 --- a/drivers/mtd/nand_legacy/Makefile +++ b/drivers/mtd/nand_legacy/Makefile @@ -25,8 +25,11 @@ include $(TOPDIR)/config.mk 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)) diff --git a/drivers/mtd/nand_legacy/nand_legacy.c b/drivers/mtd/nand_legacy/nand_legacy.c index fafefad..bf5565a 100644 --- a/drivers/mtd/nand_legacy/nand_legacy.c +++ b/drivers/mtd/nand_legacy/nand_legacy.c @@ -14,9 +14,6 @@ #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> @@ -1608,5 +1605,3 @@ int read_jffs2_nand(size_t start, size_t len, start, len, retlen, buf); } #endif /* CONFIG_JFFS2_NAND */ - -#endif diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile index 92074b2..1d35a57 100644 --- a/drivers/mtd/onenand/Makefile +++ b/drivers/mtd/onenand/Makefile @@ -25,8 +25,9 @@ include $(TOPDIR)/config.mk 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)) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index d32e382..7c9438b 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -10,15 +10,13 @@ */ #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) @@ -680,13 +678,11 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, * 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; @@ -783,7 +779,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, 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); @@ -1112,21 +1108,21 @@ int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) * * 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[] = { @@ -1205,7 +1201,7 @@ static int onenand_probe(struct mtd_info *mtd) } /* 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; @@ -1241,6 +1237,17 @@ static int onenand_probe(struct mtd_info *mtd) this->options |= ONENAND_CONT_LOCK; } + mtd->erase = onenand_erase; + mtd->read = onenand_read; + mtd->write = onenand_write; + mtd->read_ecc = onenand_read_ecc; + mtd->write_ecc = onenand_write_ecc; + 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; } @@ -1294,5 +1301,3 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) void onenand_release(struct mtd_info *mtd) { } - -#endif /* CONFIG_CMD_ONENAND */ diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 87344ab..0abaa1a 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -15,9 +15,6 @@ */ #include <common.h> - -#ifdef CONFIG_CMD_ONENAND - #include <linux/mtd/compat.h> #include <linux/mtd/mtd.h> #include <linux/mtd/onenand.h> @@ -261,5 +258,3 @@ int onenand_default_bbt(struct mtd_info *mtd) return onenand_scan_bbt(mtd, bbm->badblock_pattern); } - -#endif /* CFG_CMD_ONENAND */ diff --git a/drivers/mtd/onenand/onenand_uboot.c b/drivers/mtd/onenand/onenand_uboot.c index bd7466a..d614450 100644 --- a/drivers/mtd/onenand/onenand_uboot.c +++ b/drivers/mtd/onenand/onenand_uboot.c @@ -14,9 +14,6 @@ */ #include <common.h> - -#ifdef CONFIG_CMD_ONENAND - #include <linux/mtd/compat.h> #include <linux/mtd/mtd.h> #include <linux/mtd/onenand.h> @@ -37,5 +34,3 @@ void onenand_init(void) puts("OneNAND: "); print_size(onenand_mtd.size, "\n"); } - -#endif /* CONFIG_CMD_ONENAND */ diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index dec93b9..bffb1eb 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -25,15 +25,13 @@ include $(TOPDIR)/config.mk 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) diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index a7afa90..bb2813f 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -18,8 +18,6 @@ #include <common.h> -#ifdef CONFIG_FSL_PCI_INIT - /* * PCI/PCIE Controller initialization for mpc85xx/mpc86xx soc's * @@ -197,5 +195,3 @@ fsl_pci_init(struct pci_controller *hose) pci_hose_write_config_word(hose, dev, PCI_SEC_STATUS, 0xffff); } } - -#endif /* CONFIG_FSL_PCI */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 16180cb..b5eea89 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -30,8 +30,6 @@ #include <common.h> -#ifdef CONFIG_PCI - #include <command.h> #include <asm/processor.h> #include <asm/io.h> @@ -544,5 +542,3 @@ void pci_init(void) /* now call board specific pci_init()... */ pci_init_board(); } - -#endif /* CONFIG_PCI */ diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index eb69593..2acf9bf 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -15,8 +15,6 @@ #include <common.h> -#ifdef CONFIG_PCI - #include <pci.h> #undef DEBUG @@ -408,5 +406,3 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) return sub_bus; } - -#endif /* CONFIG_PCI */ diff --git a/drivers/pci/pci_indirect.c b/drivers/pci/pci_indirect.c index 55517a8..ab51f8d 100644 --- a/drivers/pci/pci_indirect.c +++ b/drivers/pci/pci_indirect.c @@ -11,7 +11,6 @@ #include <common.h> -#ifdef CONFIG_PCI #if (!defined(__I386__) && !defined(CONFIG_IXDP425)) #include <asm/processor.h> @@ -135,4 +134,3 @@ void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) } #endif /* !__I386__ && !CONFIG_IXDP425 */ -#endif /* CONFIG_PCI */ diff --git a/drivers/pci/tsi108_pci.c b/drivers/pci/tsi108_pci.c index 4f02cb8..edd614f 100644 --- a/drivers/pci/tsi108_pci.c +++ b/drivers/pci/tsi108_pci.c @@ -27,8 +27,6 @@ #include <config.h> -#ifdef CONFIG_TSI108_PCI - #include <common.h> #include <pci.h> #include <asm/io.h> @@ -182,5 +180,3 @@ void ft_pci_setup(void *blob, bd_t *bd) } } #endif /* CONFIG_OF_LIBFDT */ - -#endif /* CONFIG_TSI108_PCI */ diff --git a/drivers/pci/w83c553f.c b/drivers/pci/w83c553f.c index 9ea08a2..d7355a4 100644 --- a/drivers/pci/w83c553f.c +++ b/drivers/pci/w83c553f.c @@ -30,8 +30,6 @@ #include <common.h> #include <config.h> -#ifdef CFG_WINBOND_83C553 - #include <asm/io.h> #include <pci.h> @@ -222,5 +220,3 @@ void initialise_dma(void) out8(W83C553F_DMA1 + W83C553F_DMA1_CS, 0x00); out16(W83C553F_DMA2 + W83C553F_DMA2_CS, 0x0000); } - -#endif /* CFG_WINBOND_83C553 */ diff --git a/drivers/qe/Makefile b/drivers/qe/Makefile index 45a2fff..18fe9ce 100644 --- a/drivers/qe/Makefile +++ b/drivers/qe/Makefile @@ -25,8 +25,9 @@ include $(TOPDIR)/config.mk 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)) diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index 7b6ecd7..e914d01 100644 --- a/drivers/qe/qe.c +++ b/drivers/qe/qe.c @@ -27,7 +27,6 @@ #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]; @@ -466,5 +465,3 @@ U_BOOT_CMD( "fw <addr> [<length>] - Upload firmware binary at address <addr> to " "the QE,\n\twith optional length <length> verification.\n" ); - -#endif /* CONFIG_QE */ diff --git a/drivers/qe/uccf.c b/drivers/qe/uccf.c index 4a327ab..7f6337b 100644 --- a/drivers/qe/uccf.c +++ b/drivers/qe/uccf.c @@ -28,7 +28,6 @@ #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); @@ -401,4 +400,3 @@ int ucc_fast_init(ucc_fast_info_t *uf_info, ucc_fast_private_t **uccf_ret) *uccf_ret = uccf; return 0; } -#endif /* CONFIG_QE */ diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index d2c430b..344c649 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -29,8 +29,7 @@ #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 = { @@ -125,6 +124,13 @@ static uec_info_t eth4_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; @@ -629,6 +635,39 @@ static void phy_change(struct eth_device *dev) 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; @@ -1334,6 +1373,8 @@ int uec_initialize(int index) return -EINVAL; } + devlist[index] = dev; + uec->uec_info = uec_info; sprintf(dev->name, "FSL UEC%d", index); @@ -1356,6 +1397,10 @@ int uec_initialize(int 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 */ diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c index 423ba78..186922e 100644 --- a/drivers/qe/uec_phy.c +++ b/drivers/qe/uec_phy.c @@ -26,8 +26,6 @@ #include "uec_phy.h" #include "miiphy.h" -#if defined(CONFIG_QE) - #define ugphy_printk(format, arg...) \ printf(format "\n", ## arg) @@ -677,4 +675,3 @@ void change_phy_interface_mode (struct eth_device *dev, enet_interface_e mode) marvell_phy_interface_mode (dev, mode); #endif } -#endif /* CONFIG_QE */ diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index de6fbab..2384735 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -27,7 +27,7 @@ LIB := $(obj)libserial.a 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 @@ -35,7 +35,7 @@ COBJS-$(CONFIG_MAX3100_SERIAL) += serial_max3100.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) diff --git a/drivers/serial/ns9750_serial.c b/drivers/serial/ns9750_serial.c index 02c0d39..e9645a0 100644 --- a/drivers/serial/ns9750_serial.c +++ b/drivers/serial/ns9750_serial.c @@ -28,8 +28,6 @@ #include <common.h> -#ifdef CFG_NS9750_UART - #include "ns9750_bbus.h" /* for GPIOs */ #include "ns9750_ser.h" /* for serial configuration */ @@ -210,5 +208,3 @@ static unsigned int calcRxCharGapRegister( void ) { return NS9750_SER_RX_CHAR_TIMER_TRUN; } - -#endif /* CFG_NS9750_UART */ diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index 8bbfcf9..b361eef 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -26,7 +26,7 @@ #ifdef CFG_NS16550_SERIAL #include <ns16550.h> -#ifdef CFG_NS87308 +#ifdef CONFIG_NS87308 #include <ns87308.h> #endif @@ -159,7 +159,7 @@ int serial_init (void) { int clock_divisor; -#ifdef CFG_NS87308 +#ifdef CONFIG_NS87308 initialise_ns87308(); #endif diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 0801ac4..2b9eeed 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -20,8 +20,6 @@ #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) @@ -215,5 +213,3 @@ int serial_getc(void) return ch; } - -#endif /* CFG_SCIF_CONSOLE */ diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 252b00e..c67a490 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -25,6 +25,8 @@ include $(TOPDIR)/config.mk 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 diff --git a/drivers/usb/r8a66597-hcd.c b/drivers/usb/r8a66597-hcd.c new file mode 100644 index 0000000..0d3931e --- /dev/null +++ b/drivers/usb/r8a66597-hcd.c @@ -0,0 +1,919 @@ +/* + * 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; +} diff --git a/drivers/usb/r8a66597.h b/drivers/usb/r8a66597.h new file mode 100644 index 0000000..9af6446 --- /dev/null +++ b/drivers/usb/r8a66597.h @@ -0,0 +1,659 @@ +/* + * 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__ */ diff --git a/drivers/usb/usbdcore_omap1510.c b/drivers/usb/usbdcore_omap1510.c index 84bb936..4e3239f 100644 --- a/drivers/usb/usbdcore_omap1510.c +++ b/drivers/usb/usbdcore_omap1510.c @@ -28,7 +28,7 @@ #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 @@ -1109,21 +1109,43 @@ int udc_init (void) */ 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); diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 68b9861..d313e90 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -751,24 +751,10 @@ void video_puts (const char *s) 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))); \ @@ -796,6 +782,20 @@ static unsigned short p0; } #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. @@ -927,11 +927,20 @@ int video_display_bitmap (ulong bmp_image, int x, int y) 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; @@ -993,10 +1002,19 @@ int video_display_bitmap (ulong bmp_image, int x, int y) 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; @@ -1071,7 +1089,9 @@ void logo_plot (void *screen, int width, int x, int y) 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; @@ -1101,6 +1121,9 @@ void logo_plot (void *screen, int width, int x, int y) } 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]; @@ -1119,15 +1142,7 @@ void logo_plot (void *screen, int width, int x, int y) *(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: diff --git a/fs/Makefile b/fs/Makefile index 273d90e..95ac0e9 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -22,7 +22,7 @@ # # -SUBDIRS := jffs2 cramfs fdos fat reiserfs ext2 +SUBDIRS := jffs2 cramfs fdos fat reiserfs ext2 yaffs2 $(obj).depend all: @for dir in $(SUBDIRS) ; do \ diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 8a06777..b5e7ab8 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -146,7 +146,7 @@ static struct part_info *current_part; #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> @@ -161,7 +161,7 @@ static struct part_info *current_part; * */ -#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); @@ -201,7 +201,7 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf) } } -#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) { diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c index 3ce9c98..9f6de7d 100644 --- a/fs/jffs2/jffs2_nand_1pass.c +++ b/fs/jffs2/jffs2_nand_1pass.c @@ -1,6 +1,6 @@ #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> diff --git a/fs/yaffs2/Makefile b/fs/yaffs2/Makefile new file mode 100644 index 0000000..ab8b27f --- /dev/null +++ b/fs/yaffs2/Makefile @@ -0,0 +1,56 @@ +# 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 + +######################################################################### + diff --git a/fs/yaffs2/README-linux b/fs/yaffs2/README-linux new file mode 100644 index 0000000..589ae8d --- /dev/null +++ b/fs/yaffs2/README-linux @@ -0,0 +1,201 @@ +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 +------------- diff --git a/fs/yaffs2/devextras.h b/fs/yaffs2/devextras.h new file mode 100644 index 0000000..9acda79 --- /dev/null +++ b/fs/yaffs2/devextras.h @@ -0,0 +1,275 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_checkptrw.c b/fs/yaffs2/yaffs_checkptrw.c new file mode 100644 index 0000000..f97ba4b --- /dev/null +++ b/fs/yaffs2/yaffs_checkptrw.c @@ -0,0 +1,405 @@ +/* + * 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); +} diff --git a/fs/yaffs2/yaffs_checkptrw.h b/fs/yaffs2/yaffs_checkptrw.h new file mode 100644 index 0000000..f4b0c7d --- /dev/null +++ b/fs/yaffs2/yaffs_checkptrw.h @@ -0,0 +1,35 @@ +/* + * 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 + diff --git a/fs/yaffs2/yaffs_ecc.c b/fs/yaffs2/yaffs_ecc.c new file mode 100644 index 0000000..a05a6b5 --- /dev/null +++ b/fs/yaffs2/yaffs_ecc.c @@ -0,0 +1,333 @@ +/* + * 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; + +} diff --git a/fs/yaffs2/yaffs_ecc.h b/fs/yaffs2/yaffs_ecc.h new file mode 100644 index 0000000..40fd02b --- /dev/null +++ b/fs/yaffs2/yaffs_ecc.h @@ -0,0 +1,44 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_flashif.h b/fs/yaffs2/yaffs_flashif.h new file mode 100644 index 0000000..f7f4e42 --- /dev/null +++ b/fs/yaffs2/yaffs_flashif.h @@ -0,0 +1,31 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_guts.c b/fs/yaffs2/yaffs_guts.c new file mode 100644 index 0000000..7dc62ef --- /dev/null +++ b/fs/yaffs2/yaffs_guts.c @@ -0,0 +1,7491 @@ +/* + * 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; +} diff --git a/fs/yaffs2/yaffs_guts.h b/fs/yaffs2/yaffs_guts.h new file mode 100644 index 0000000..ecf701f --- /dev/null +++ b/fs/yaffs2/yaffs_guts.h @@ -0,0 +1,908 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_malloc.h b/fs/yaffs2/yaffs_malloc.h new file mode 100644 index 0000000..122fb4c --- /dev/null +++ b/fs/yaffs2/yaffs_malloc.h @@ -0,0 +1,26 @@ +#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 + diff --git a/fs/yaffs2/yaffs_mtdif.c b/fs/yaffs2/yaffs_mtdif.c new file mode 100644 index 0000000..407ef2b --- /dev/null +++ b/fs/yaffs2/yaffs_mtdif.c @@ -0,0 +1,246 @@ +/* + * 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; +} diff --git a/fs/yaffs2/yaffs_mtdif.h b/fs/yaffs2/yaffs_mtdif.h new file mode 100644 index 0000000..f75e08c --- /dev/null +++ b/fs/yaffs2/yaffs_mtdif.h @@ -0,0 +1,27 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_mtdif2.c b/fs/yaffs2/yaffs_mtdif2.c new file mode 100644 index 0000000..cd2a2a1 --- /dev/null +++ b/fs/yaffs2/yaffs_mtdif2.c @@ -0,0 +1,235 @@ +/* + * 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; +} diff --git a/fs/yaffs2/yaffs_mtdif2.h b/fs/yaffs2/yaffs_mtdif2.h new file mode 100644 index 0000000..e70d751 --- /dev/null +++ b/fs/yaffs2/yaffs_mtdif2.h @@ -0,0 +1,29 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_nand.c b/fs/yaffs2/yaffs_nand.c new file mode 100644 index 0000000..b201655 --- /dev/null +++ b/fs/yaffs2/yaffs_nand.c @@ -0,0 +1,134 @@ +/* + * 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); +} diff --git a/fs/yaffs2/yaffs_nand.h b/fs/yaffs2/yaffs_nand.h new file mode 100644 index 0000000..8ed1a2d --- /dev/null +++ b/fs/yaffs2/yaffs_nand.h @@ -0,0 +1,44 @@ +/* + * 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 + diff --git a/fs/yaffs2/yaffs_nandemul2k.h b/fs/yaffs2/yaffs_nandemul2k.h new file mode 100644 index 0000000..13520e1 --- /dev/null +++ b/fs/yaffs2/yaffs_nandemul2k.h @@ -0,0 +1,39 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_packedtags1.c b/fs/yaffs2/yaffs_packedtags1.c new file mode 100644 index 0000000..a149431 --- /dev/null +++ b/fs/yaffs2/yaffs_packedtags1.c @@ -0,0 +1,55 @@ +/* + * 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)); + + } +} diff --git a/fs/yaffs2/yaffs_packedtags1.h b/fs/yaffs2/yaffs_packedtags1.h new file mode 100644 index 0000000..627b2f8 --- /dev/null +++ b/fs/yaffs2/yaffs_packedtags1.h @@ -0,0 +1,37 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_packedtags2.c b/fs/yaffs2/yaffs_packedtags2.c new file mode 100644 index 0000000..467d5ac --- /dev/null +++ b/fs/yaffs2/yaffs_packedtags2.c @@ -0,0 +1,185 @@ +/* + * 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); + +} diff --git a/fs/yaffs2/yaffs_packedtags2.h b/fs/yaffs2/yaffs_packedtags2.h new file mode 100644 index 0000000..7c4a72c --- /dev/null +++ b/fs/yaffs2/yaffs_packedtags2.h @@ -0,0 +1,38 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_qsort.c b/fs/yaffs2/yaffs_qsort.c new file mode 100644 index 0000000..a74709f --- /dev/null +++ b/fs/yaffs2/yaffs_qsort.c @@ -0,0 +1,163 @@ +/* + * 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);*/ +} diff --git a/fs/yaffs2/yaffs_qsort.h b/fs/yaffs2/yaffs_qsort.h new file mode 100644 index 0000000..3ec7397 --- /dev/null +++ b/fs/yaffs2/yaffs_qsort.h @@ -0,0 +1,23 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_ramdisk.h b/fs/yaffs2/yaffs_ramdisk.h new file mode 100644 index 0000000..045ab42 --- /dev/null +++ b/fs/yaffs2/yaffs_ramdisk.h @@ -0,0 +1,32 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_tagscompat.c b/fs/yaffs2/yaffs_tagscompat.c new file mode 100644 index 0000000..70a8a8c --- /dev/null +++ b/fs/yaffs2/yaffs_tagscompat.c @@ -0,0 +1,533 @@ +/* + * 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; +} diff --git a/fs/yaffs2/yaffs_tagscompat.h b/fs/yaffs2/yaffs_tagscompat.h new file mode 100644 index 0000000..c1edb6a --- /dev/null +++ b/fs/yaffs2/yaffs_tagscompat.h @@ -0,0 +1,40 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffs_tagsvalidity.c b/fs/yaffs2/yaffs_tagsvalidity.c new file mode 100644 index 0000000..f588d3a --- /dev/null +++ b/fs/yaffs2/yaffs_tagsvalidity.c @@ -0,0 +1,31 @@ +/* + * 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); + +} diff --git a/fs/yaffs2/yaffs_tagsvalidity.h b/fs/yaffs2/yaffs_tagsvalidity.h new file mode 100644 index 0000000..ba56727 --- /dev/null +++ b/fs/yaffs2/yaffs_tagsvalidity.h @@ -0,0 +1,24 @@ +/* + * 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 diff --git a/fs/yaffs2/yaffscfg.c b/fs/yaffs2/yaffscfg.c new file mode 100644 index 0000000..a4a0924 --- /dev/null +++ b/fs/yaffs2/yaffscfg.c @@ -0,0 +1,417 @@ +/* + * 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); +} diff --git a/fs/yaffs2/yaffscfg.h b/fs/yaffs2/yaffscfg.h new file mode 100644 index 0000000..6ae1696 --- /dev/null +++ b/fs/yaffs2/yaffscfg.h @@ -0,0 +1,46 @@ +/* + * 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 + diff --git a/fs/yaffs2/yaffsfs.c b/fs/yaffs2/yaffsfs.c new file mode 100644 index 0000000..f62c952 --- /dev/null +++ b/fs/yaffs2/yaffsfs.c @@ -0,0 +1,1510 @@ +/* + * 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; +} diff --git a/fs/yaffs2/yaffsfs.h b/fs/yaffs2/yaffsfs.h new file mode 100644 index 0000000..9afe60a --- /dev/null +++ b/fs/yaffs2/yaffsfs.h @@ -0,0 +1,233 @@ +/* + * 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 + + diff --git a/fs/yaffs2/yaffsinterface.h b/fs/yaffs2/yaffsinterface.h new file mode 100644 index 0000000..0cfdfcf --- /dev/null +++ b/fs/yaffs2/yaffsinterface.h @@ -0,0 +1,21 @@ +/* + * 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 diff --git a/fs/yaffs2/ydirectenv.h b/fs/yaffs2/ydirectenv.h new file mode 100644 index 0000000..adcc0b5 --- /dev/null +++ b/fs/yaffs2/ydirectenv.h @@ -0,0 +1,94 @@ +/* + * 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 + + diff --git a/fs/yaffs2/yportenv.h b/fs/yaffs2/yportenv.h new file mode 100644 index 0000000..b316b16 --- /dev/null +++ b/fs/yaffs2/yportenv.h @@ -0,0 +1,193 @@ +/* + * 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 diff --git a/include/asm-arm/arch-at91sam9/at91_pio.h b/include/asm-arm/arch-at91/at91_pio.h index f6ce1f9..f6ce1f9 100644 --- a/include/asm-arm/arch-at91sam9/at91_pio.h +++ b/include/asm-arm/arch-at91/at91_pio.h diff --git a/include/asm-arm/arch-at91sam9/at91_pit.h b/include/asm-arm/arch-at91/at91_pit.h index 94dd242..94dd242 100644 --- a/include/asm-arm/arch-at91sam9/at91_pit.h +++ b/include/asm-arm/arch-at91/at91_pit.h diff --git a/include/asm-arm/arch-at91sam9/at91_pmc.h b/include/asm-arm/arch-at91/at91_pmc.h index b57875d..b57875d 100644 --- a/include/asm-arm/arch-at91sam9/at91_pmc.h +++ b/include/asm-arm/arch-at91/at91_pmc.h diff --git a/include/asm-arm/arch-at91sam9/at91_rstc.h b/include/asm-arm/arch-at91/at91_rstc.h index e49caef..e49caef 100644 --- a/include/asm-arm/arch-at91sam9/at91_rstc.h +++ b/include/asm-arm/arch-at91/at91_rstc.h diff --git a/include/asm-arm/arch-at91sam9/at91_spi.h b/include/asm-arm/arch-at91/at91_spi.h index 30643c6..30643c6 100644 --- a/include/asm-arm/arch-at91sam9/at91_spi.h +++ b/include/asm-arm/arch-at91/at91_spi.h diff --git a/include/asm-arm/arch-at91sam9/at91cap9.h b/include/asm-arm/arch-at91/at91cap9.h index 0b52228..0b52228 100644 --- a/include/asm-arm/arch-at91sam9/at91cap9.h +++ b/include/asm-arm/arch-at91/at91cap9.h diff --git a/include/asm-arm/arch-at91sam9/at91cap9_matrix.h b/include/asm-arm/arch-at91/at91cap9_matrix.h index 22b7e9b..22b7e9b 100644 --- a/include/asm-arm/arch-at91sam9/at91cap9_matrix.h +++ b/include/asm-arm/arch-at91/at91cap9_matrix.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9260.h b/include/asm-arm/arch-at91/at91sam9260.h index 920a7f3..920a7f3 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9260.h +++ b/include/asm-arm/arch-at91/at91sam9260.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9260_matrix.h b/include/asm-arm/arch-at91/at91sam9260_matrix.h index f8b023d..f8b023d 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9260_matrix.h +++ b/include/asm-arm/arch-at91/at91sam9260_matrix.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9261.h b/include/asm-arm/arch-at91/at91sam9261.h index 752d81d..752d81d 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9261.h +++ b/include/asm-arm/arch-at91/at91sam9261.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9261_matrix.h b/include/asm-arm/arch-at91/at91sam9261_matrix.h index e2bfc4b..e2bfc4b 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9261_matrix.h +++ b/include/asm-arm/arch-at91/at91sam9261_matrix.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h index 98251cb..98251cb 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9263.h +++ b/include/asm-arm/arch-at91/at91sam9263.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9263_matrix.h b/include/asm-arm/arch-at91/at91sam9263_matrix.h index 83aaaab..83aaaab 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9263_matrix.h +++ b/include/asm-arm/arch-at91/at91sam9263_matrix.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9_smc.h b/include/asm-arm/arch-at91/at91sam9_smc.h index d64511b..d64511b 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9_smc.h +++ b/include/asm-arm/arch-at91/at91sam9_smc.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9rl.h b/include/asm-arm/arch-at91/at91sam9rl.h index 215bbc8..215bbc8 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9rl.h +++ b/include/asm-arm/arch-at91/at91sam9rl.h diff --git a/include/asm-arm/arch-at91sam9/at91sam9rl_matrix.h b/include/asm-arm/arch-at91/at91sam9rl_matrix.h index af8d914..af8d914 100644 --- a/include/asm-arm/arch-at91sam9/at91sam9rl_matrix.h +++ b/include/asm-arm/arch-at91/at91sam9rl_matrix.h diff --git a/include/asm-arm/arch-at91sam9/clk.h b/include/asm-arm/arch-at91/clk.h index 1b502c8..1b502c8 100644 --- a/include/asm-arm/arch-at91sam9/clk.h +++ b/include/asm-arm/arch-at91/clk.h diff --git a/include/asm-arm/arch-at91sam9/gpio.h b/include/asm-arm/arch-at91/gpio.h index c4d7b97..c4d7b97 100644 --- a/include/asm-arm/arch-at91sam9/gpio.h +++ b/include/asm-arm/arch-at91/gpio.h diff --git a/include/asm-arm/arch-at91sam9/hardware.h b/include/asm-arm/arch-at91/hardware.h index f312419..f312419 100644 --- a/include/asm-arm/arch-at91sam9/hardware.h +++ b/include/asm-arm/arch-at91/hardware.h diff --git a/include/asm-arm/arch-at91sam9/io.h b/include/asm-arm/arch-at91/io.h index f09b2df..f09b2df 100644 --- a/include/asm-arm/arch-at91sam9/io.h +++ b/include/asm-arm/arch-at91/io.h diff --git a/include/asm-arm/arch-at91sam9/memory-map.h b/include/asm-arm/arch-at91/memory-map.h index 8015dad..8015dad 100644 --- a/include/asm-arm/arch-at91sam9/memory-map.h +++ b/include/asm-arm/arch-at91/memory-map.h diff --git a/include/asm-arm/arch-mx31/mx31-regs.h b/include/asm-arm/arch-mx31/mx31-regs.h index 02b7dcb..b04a718 100644 --- a/include/asm-arm/arch-mx31/mx31-regs.h +++ b/include/asm-arm/arch-mx31/mx31-regs.h @@ -126,17 +126,32 @@ #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 diff --git a/include/asm-ppc/interrupt.h b/include/asm-ppc/interrupt.h new file mode 100644 index 0000000..792836b --- /dev/null +++ b/include/asm-ppc/interrupt.h @@ -0,0 +1,36 @@ +/* + * (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 diff --git a/include/asm-ppc/ppc4xx-ebc.h b/include/asm-ppc/ppc4xx-ebc.h new file mode 100644 index 0000000..d180e04 --- /dev/null +++ b/include/asm-ppc/ppc4xx-ebc.h @@ -0,0 +1,156 @@ +/* + * (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_ */ diff --git a/include/asm-ppc/ppc4xx-intvec.h b/include/asm-ppc/ppc4xx-intvec.h deleted file mode 100644 index 5b45de4..0000000 --- a/include/asm-ppc/ppc4xx-intvec.h +++ /dev/null @@ -1,474 +0,0 @@ -/* -* 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_ */ diff --git a/include/asm-ppc/ppc4xx-sdram.h b/include/asm-ppc/ppc4xx-sdram.h index e151f0c..df787b3 100644 --- a/include/asm-ppc/ppc4xx-sdram.h +++ b/include/asm-ppc/ppc4xx-sdram.h @@ -282,7 +282,8 @@ * 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) @@ -353,7 +354,19 @@ /* * 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 */ @@ -398,9 +411,35 @@ #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 @@ -523,7 +562,7 @@ * 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 @@ -539,59 +578,234 @@ #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 @@ -684,6 +898,24 @@ #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 */ diff --git a/include/asm-ppc/ppc4xx-uic.h b/include/asm-ppc/ppc4xx-uic.h new file mode 100644 index 0000000..c908d42 --- /dev/null +++ b/include/asm-ppc/ppc4xx-uic.h @@ -0,0 +1,316 @@ +/* + * 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_ */ diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index e617868..dce4717 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -830,6 +830,10 @@ #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 @@ -855,6 +859,8 @@ #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 diff --git a/include/asm-ppc/xilinx_irq.h b/include/asm-ppc/xilinx_irq.h new file mode 100644 index 0000000..61171c2 --- /dev/null +++ b/include/asm-ppc/xilinx_irq.h @@ -0,0 +1,36 @@ +/* + * (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 diff --git a/include/common.h b/include/common.h index 2fcb1fd..06ed278 100644 --- a/include/common.h +++ b/include/common.h @@ -119,11 +119,13 @@ typedef volatile unsigned char vu_char; #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 *); diff --git a/include/configs/APC405.h b/include/configs/APC405.h index 2f266a2..6ee0a36 100644 --- a/include/configs/APC405.h +++ b/include/configs/APC405.h @@ -269,7 +269,7 @@ extern int flash_banks; #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 */ diff --git a/include/configs/ATUM8548.h b/include/configs/ATUM8548.h index f05c1d5..6aa881c 100644 --- a/include/configs/ATUM8548.h +++ b/include/configs/ATUM8548.h @@ -182,7 +182,7 @@ #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 diff --git a/include/configs/Adder.h b/include/configs/Adder.h index cefdd29..07a9f4e 100644 --- a/include/configs/Adder.h +++ b/include/configs/Adder.h @@ -143,7 +143,7 @@ */ #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 */ diff --git a/include/configs/BAB7xx.h b/include/configs/BAB7xx.h index 8ec70aa..26a1a2d 100644 --- a/include/configs/BAB7xx.h +++ b/include/configs/BAB7xx.h @@ -338,7 +338,7 @@ extern unsigned char scsi_sym53c8xx_ccf; /* * 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 */ @@ -346,7 +346,7 @@ extern unsigned char scsi_sym53c8xx_ccf; /* * 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 | \ diff --git a/include/configs/BC3450.h b/include/configs/BC3450.h index b7574bf..3c5d038 100644 --- a/include/configs/BC3450.h +++ b/include/configs/BC3450.h @@ -328,7 +328,7 @@ /* 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 */ diff --git a/include/configs/BMW.h b/include/configs/BMW.h index bb7856f..11d19c6 100644 --- a/include/configs/BMW.h +++ b/include/configs/BMW.h @@ -86,7 +86,7 @@ /* CONFIG_CMD_DOC required legacy NAND support */ -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY #if 0 #define CONFIG_PCI 1 diff --git a/include/configs/CPCI750.h b/include/configs/CPCI750.h index 89edbde..03756c3 100644 --- a/include/configs/CPCI750.h +++ b/include/configs/CPCI750.h @@ -294,7 +294,7 @@ * 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) */ diff --git a/include/configs/CPU87.h b/include/configs/CPU87.h index 3879d9b..d325c4d 100644 --- a/include/configs/CPU87.h +++ b/include/configs/CPU87.h @@ -191,7 +191,7 @@ #endif -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY /* * Miscellaneous configurable options diff --git a/include/configs/DU440.h b/include/configs/DU440.h index 64c9ac0..c757523 100644 --- a/include/configs/DU440.h +++ b/include/configs/DU440.h @@ -119,7 +119,7 @@ * 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 } diff --git a/include/configs/EP88x.h b/include/configs/EP88x.h index 7824b90..5f1743b 100644 --- a/include/configs/EP88x.h +++ b/include/configs/EP88x.h @@ -138,7 +138,7 @@ */ #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 */ diff --git a/include/configs/FPS850L.h b/include/configs/FPS850L.h index e4b68ab..e694a02 100644 --- a/include/configs/FPS850L.h +++ b/include/configs/FPS850L.h @@ -1,5 +1,5 @@ /* - * (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 @@ -65,10 +65,17 @@ "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" @@ -106,10 +113,14 @@ #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 */ @@ -180,11 +191,15 @@ /*----------------------------------------------------------------------- * 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 */ @@ -194,6 +209,20 @@ #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 */ diff --git a/include/configs/FPS860L.h b/include/configs/FPS860L.h index ed612c3..84b6824 100644 --- a/include/configs/FPS860L.h +++ b/include/configs/FPS860L.h @@ -1,5 +1,5 @@ /* - * (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 @@ -65,10 +65,17 @@ "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" @@ -106,10 +113,14 @@ #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 */ @@ -180,11 +191,15 @@ /*----------------------------------------------------------------------- * 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 */ @@ -194,6 +209,20 @@ #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 */ @@ -306,9 +335,11 @@ #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) @@ -337,12 +368,42 @@ /* * 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 */ @@ -372,4 +433,6 @@ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ #define BOOTFLAG_WARM 0x02 /* Software reboot */ +#define CONFIG_SCC1_ENET + #endif /* __CONFIG_H */ diff --git a/include/configs/GEN860T.h b/include/configs/GEN860T.h index 037b115..422ed32 100644 --- a/include/configs/GEN860T.h +++ b/include/configs/GEN860T.h @@ -280,7 +280,7 @@ #define CFG_FPGA_PROG_FEEDBACK -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY /* * Verbose help from command monitor. diff --git a/include/configs/HH405.h b/include/configs/HH405.h index 8ea1ac3..9bcbfe3 100644 --- a/include/configs/HH405.h +++ b/include/configs/HH405.h @@ -407,7 +407,7 @@ /* * 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 diff --git a/include/configs/HIDDEN_DRAGON.h b/include/configs/HIDDEN_DRAGON.h index 26dd954..5deb84d 100644 --- a/include/configs/HIDDEN_DRAGON.h +++ b/include/configs/HIDDEN_DRAGON.h @@ -201,7 +201,7 @@ */ -#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 */ @@ -214,7 +214,7 @@ /* * 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 diff --git a/include/configs/HMI10.h b/include/configs/HMI10.h index 081ca6c..a7e7c57 100644 --- a/include/configs/HMI10.h +++ b/include/configs/HMI10.h @@ -227,7 +227,7 @@ /* 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 diff --git a/include/configs/IDS8247.h b/include/configs/IDS8247.h index f7d4499..029bb99 100644 --- a/include/configs/IDS8247.h +++ b/include/configs/IDS8247.h @@ -227,7 +227,7 @@ #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 @@ -262,7 +262,7 @@ */ #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 */ diff --git a/include/configs/ISPAN.h b/include/configs/ISPAN.h index 760f7cc..27e46a4 100644 --- a/include/configs/ISPAN.h +++ b/include/configs/ISPAN.h @@ -180,7 +180,7 @@ */ #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 */ diff --git a/include/configs/IceCube.h b/include/configs/IceCube.h index 3a347ea..0b90946 100644 --- a/include/configs/IceCube.h +++ b/include/configs/IceCube.h @@ -246,7 +246,7 @@ #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 diff --git a/include/configs/M52277EVB.h b/include/configs/M52277EVB.h index 3d28913..8713b02 100644 --- a/include/configs/M52277EVB.h +++ b/include/configs/M52277EVB.h @@ -207,7 +207,7 @@ #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 */ diff --git a/include/configs/M5235EVB.h b/include/configs/M5235EVB.h index 8af1c52..e836132 100644 --- a/include/configs/M5235EVB.h +++ b/include/configs/M5235EVB.h @@ -200,7 +200,7 @@ */ #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 diff --git a/include/configs/M5249EVB.h b/include/configs/M5249EVB.h index de7ea42..c2f5dd9 100644 --- a/include/configs/M5249EVB.h +++ b/include/configs/M5249EVB.h @@ -150,7 +150,7 @@ #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 */ diff --git a/include/configs/M5253EVBE.h b/include/configs/M5253EVBE.h index f5e1b64..9dbd129 100644 --- a/include/configs/M5253EVBE.h +++ b/include/configs/M5253EVBE.h @@ -172,7 +172,7 @@ #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 diff --git a/include/configs/M5271EVB.h b/include/configs/M5271EVB.h index a6fac4c..12f9783 100644 --- a/include/configs/M5271EVB.h +++ b/include/configs/M5271EVB.h @@ -210,7 +210,7 @@ #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 */ diff --git a/include/configs/M5275EVB.h b/include/configs/M5275EVB.h index 283c873..30c70e5 100644 --- a/include/configs/M5275EVB.h +++ b/include/configs/M5275EVB.h @@ -197,7 +197,7 @@ #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 /*----------------------------------------------------------------------- diff --git a/include/configs/M5282EVB.h b/include/configs/M5282EVB.h index df46ee4..c2c7fab 100644 --- a/include/configs/M5282EVB.h +++ b/include/configs/M5282EVB.h @@ -194,7 +194,7 @@ #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 */ diff --git a/include/configs/M5329EVB.h b/include/configs/M5329EVB.h index b30d99c..58948a2 100644 --- a/include/configs/M5329EVB.h +++ b/include/configs/M5329EVB.h @@ -202,7 +202,7 @@ */ #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 */ diff --git a/include/configs/M5373EVB.h b/include/configs/M5373EVB.h index a710c6d..814c3a6 100644 --- a/include/configs/M5373EVB.h +++ b/include/configs/M5373EVB.h @@ -202,7 +202,7 @@ */ #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 */ diff --git a/include/configs/M54455EVB.h b/include/configs/M54455EVB.h index 3a022af..6620f03 100644 --- a/include/configs/M54455EVB.h +++ b/include/configs/M54455EVB.h @@ -302,7 +302,7 @@ #undef 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 */ diff --git a/include/configs/M5475EVB.h b/include/configs/M5475EVB.h index e8804b5..4037efb 100644 --- a/include/configs/M5475EVB.h +++ b/include/configs/M5475EVB.h @@ -259,7 +259,7 @@ #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 */ diff --git a/include/configs/M5485EVB.h b/include/configs/M5485EVB.h index 0f957ff..a14c55b 100644 --- a/include/configs/M5485EVB.h +++ b/include/configs/M5485EVB.h @@ -245,7 +245,7 @@ #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 */ diff --git a/include/configs/MIP405.h b/include/configs/MIP405.h index d683b87..66235e3 100644 --- a/include/configs/MIP405.h +++ b/include/configs/MIP405.h @@ -88,7 +88,7 @@ #endif -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY #define CFG_HUSH_PARSER #define CFG_PROMPT_HUSH_PS2 "> " diff --git a/include/configs/MPC8313ERDB.h b/include/configs/MPC8313ERDB.h index d547681..a4c4240 100644 --- a/include/configs/MPC8313ERDB.h +++ b/include/configs/MPC8313ERDB.h @@ -63,6 +63,10 @@ #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 @@ -167,16 +171,16 @@ * 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 \ @@ -193,7 +197,7 @@ #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 @@ -220,17 +224,31 @@ #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 \ @@ -238,9 +256,25 @@ | 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 */ @@ -272,7 +306,6 @@ #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} @@ -351,7 +384,15 @@ /* * 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 */ @@ -388,7 +429,7 @@ #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 @@ -430,6 +471,8 @@ 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 */ @@ -442,22 +485,31 @@ 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 */ diff --git a/include/configs/MPC8315ERDB.h b/include/configs/MPC8315ERDB.h index 095f665..b0cc36d 100644 --- a/include/configs/MPC8315ERDB.h +++ b/include/configs/MPC8315ERDB.h @@ -188,7 +188,7 @@ * 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 */ diff --git a/include/configs/MPC8323ERDB.h b/include/configs/MPC8323ERDB.h index 977c041..94b3d5a 100644 --- a/include/configs/MPC8323ERDB.h +++ b/include/configs/MPC8323ERDB.h @@ -178,7 +178,7 @@ * 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 */ diff --git a/include/configs/MPC832XEMDS.h b/include/configs/MPC832XEMDS.h index 9ca2a2b..401d0af 100644 --- a/include/configs/MPC832XEMDS.h +++ b/include/configs/MPC832XEMDS.h @@ -166,7 +166,7 @@ * 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 */ diff --git a/include/configs/MPC8349EMDS.h b/include/configs/MPC8349EMDS.h index 8705838..a53f5cd 100644 --- a/include/configs/MPC8349EMDS.h +++ b/include/configs/MPC8349EMDS.h @@ -148,7 +148,7 @@ * 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 */ diff --git a/include/configs/MPC8349ITX.h b/include/configs/MPC8349ITX.h index 82d0686..45ddd5c 100644 --- a/include/configs/MPC8349ITX.h +++ b/include/configs/MPC8349ITX.h @@ -175,7 +175,7 @@ */ #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 */ @@ -419,7 +419,7 @@ boards, we say we have two, but don't display a message if we find only one. */ #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 diff --git a/include/configs/MPC8360EMDS.h b/include/configs/MPC8360EMDS.h index b4bff9a..43d4118 100644 --- a/include/configs/MPC8360EMDS.h +++ b/include/configs/MPC8360EMDS.h @@ -191,7 +191,7 @@ * 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 */ diff --git a/include/configs/MPC8360ERDK.h b/include/configs/MPC8360ERDK.h index ca8d53c..6898495 100644 --- a/include/configs/MPC8360ERDK.h +++ b/include/configs/MPC8360ERDK.h @@ -184,7 +184,7 @@ * 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. */ diff --git a/include/configs/MPC837XEMDS.h b/include/configs/MPC837XEMDS.h index 0dd0279..f9c1b17 100644 --- a/include/configs/MPC837XEMDS.h +++ b/include/configs/MPC837XEMDS.h @@ -226,7 +226,7 @@ * 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 */ diff --git a/include/configs/MPC837XERDB.h b/include/configs/MPC837XERDB.h index 29c2490..82b3353 100644 --- a/include/configs/MPC837XERDB.h +++ b/include/configs/MPC837XERDB.h @@ -249,7 +249,7 @@ * 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 */ diff --git a/include/configs/MPC8540ADS.h b/include/configs/MPC8540ADS.h index d1d3cc3..6351925 100644 --- a/include/configs/MPC8540ADS.h +++ b/include/configs/MPC8540ADS.h @@ -152,7 +152,7 @@ #undef CFG_RAMBOOT #endif -#define CFG_FLASH_CFI_DRIVER +#define CONFIG_FLASH_CFI_DRIVER #define CFG_FLASH_CFI #define CFG_FLASH_EMPTY_INFO diff --git a/include/configs/MPC8541CDS.h b/include/configs/MPC8541CDS.h index a64565d..d948d76 100644 --- a/include/configs/MPC8541CDS.h +++ b/include/configs/MPC8541CDS.h @@ -154,7 +154,7 @@ extern unsigned long get_clock_freq(void); #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 diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h index 091fd2e..9a77b7b 100644 --- a/include/configs/MPC8544DS.h +++ b/include/configs/MPC8544DS.h @@ -168,7 +168,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #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 diff --git a/include/configs/MPC8548CDS.h b/include/configs/MPC8548CDS.h index acf6f0d..33c5c93 100644 --- a/include/configs/MPC8548CDS.h +++ b/include/configs/MPC8548CDS.h @@ -172,7 +172,7 @@ extern unsigned long get_clock_freq(void); #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 diff --git a/include/configs/MPC8555CDS.h b/include/configs/MPC8555CDS.h index 1948c0d..85c235c 100644 --- a/include/configs/MPC8555CDS.h +++ b/include/configs/MPC8555CDS.h @@ -154,7 +154,7 @@ extern unsigned long get_clock_freq(void); #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 diff --git a/include/configs/MPC8560ADS.h b/include/configs/MPC8560ADS.h index 27212162..3567d1ce 100644 --- a/include/configs/MPC8560ADS.h +++ b/include/configs/MPC8560ADS.h @@ -148,7 +148,7 @@ #undef CFG_RAMBOOT #endif -#define CFG_FLASH_CFI_DRIVER +#define CONFIG_FLASH_CFI_DRIVER #define CFG_FLASH_CFI #define CFG_FLASH_EMPTY_INFO diff --git a/include/configs/MPC8568MDS.h b/include/configs/MPC8568MDS.h index 9e6bb44..a82d528 100644 --- a/include/configs/MPC8568MDS.h +++ b/include/configs/MPC8568MDS.h @@ -167,7 +167,7 @@ extern unsigned long get_clock_freq(void); #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 diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h index 06899b1..e9371a2 100644 --- a/include/configs/MPC8610HPCD.h +++ b/include/configs/MPC8610HPCD.h @@ -192,7 +192,7 @@ #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 diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index cd35494..468fd08 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -214,7 +214,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #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 diff --git a/include/configs/MVBC_P.h b/include/configs/MVBC_P.h index 8c8a445..0ce88d6 100644 --- a/include/configs/MVBC_P.h +++ b/include/configs/MVBC_P.h @@ -40,7 +40,7 @@ #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 @@ -198,7 +198,7 @@ */ #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 @@ -268,7 +268,7 @@ #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 diff --git a/include/configs/MVBLM7.h b/include/configs/MVBLM7.h index b412655..0dce9b4 100644 --- a/include/configs/MVBLM7.h +++ b/include/configs/MVBLM7.h @@ -104,7 +104,7 @@ /* 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 diff --git a/include/configs/MigoR.h b/include/configs/MigoR.h index fa0e5db..40cf275 100644 --- a/include/configs/MigoR.h +++ b/include/configs/MigoR.h @@ -67,7 +67,7 @@ #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 */ @@ -103,7 +103,7 @@ /* 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 diff --git a/include/configs/NETPHONE.h b/include/configs/NETPHONE.h index 27e7ab9..6c18b81 100644 --- a/include/configs/NETPHONE.h +++ b/include/configs/NETPHONE.h @@ -502,7 +502,7 @@ /****************************************************************/ /* 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 diff --git a/include/configs/NETTA.h b/include/configs/NETTA.h index 56c76d3..1f1bc54 100644 --- a/include/configs/NETTA.h +++ b/include/configs/NETTA.h @@ -621,7 +621,7 @@ /****************************************************************/ /* 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 diff --git a/include/configs/NETTA2.h b/include/configs/NETTA2.h index b8c4848..9a1f1d6 100644 --- a/include/configs/NETTA2.h +++ b/include/configs/NETTA2.h @@ -503,7 +503,7 @@ /****************************************************************/ /* 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 diff --git a/include/configs/NETVIA.h b/include/configs/NETVIA.h index 1293fb0..c029594 100644 --- a/include/configs/NETVIA.h +++ b/include/configs/NETVIA.h @@ -397,7 +397,7 @@ /*****************************************************************************/ -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY #if defined(CONFIG_NETVIA_VERSION) && CONFIG_NETVIA_VERSION >= 2 diff --git a/include/configs/NSCU.h b/include/configs/NSCU.h index 11e5c63..31762b9 100644 --- a/include/configs/NSCU.h +++ b/include/configs/NSCU.h @@ -1,5 +1,5 @@ /* - * (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 @@ -67,9 +67,16 @@ "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" @@ -110,20 +117,24 @@ #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 @@ -186,21 +197,26 @@ /*----------------------------------------------------------------------- * 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 */ diff --git a/include/configs/PCIPPC2.h b/include/configs/PCIPPC2.h index 268b034..6ebaa85 100644 --- a/include/configs/PCIPPC2.h +++ b/include/configs/PCIPPC2.h @@ -84,7 +84,7 @@ #define CONFIG_PCI 1 #define CONFIG_PCI_PNP 1 /* PCI plug-and-play */ -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY /* * Miscellaneous configurable options diff --git a/include/configs/PCIPPC6.h b/include/configs/PCIPPC6.h index 250b586..9202794 100644 --- a/include/configs/PCIPPC6.h +++ b/include/configs/PCIPPC6.h @@ -86,7 +86,7 @@ #define CONFIG_PCI 1 #define CONFIG_PCI_PNP 1 /* PCI plug-and-play */ -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY /* * Miscellaneous configurable options diff --git a/include/configs/PIP405.h b/include/configs/PIP405.h index 5890012..2ceda00 100644 --- a/include/configs/PIP405.h +++ b/include/configs/PIP405.h @@ -77,7 +77,7 @@ #define CONFIG_CMD_BSP -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY #define CFG_HUSH_PARSER #define CFG_PROMPT_HUSH_PS2 "> " diff --git a/include/configs/PM520.h b/include/configs/PM520.h index 259178f..5e0bb05 100644 --- a/include/configs/PM520.h +++ b/include/configs/PM520.h @@ -88,7 +88,7 @@ #if !defined(CONFIG_BOOT_ROM) /* DoC requires legacy NAND for now */ -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY #endif diff --git a/include/configs/PM826.h b/include/configs/PM826.h index 36e9aa5..190e2a4 100644 --- a/include/configs/PM826.h +++ b/include/configs/PM826.h @@ -180,7 +180,7 @@ #endif -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY /* * Disk-On-Chip configuration diff --git a/include/configs/PM828.h b/include/configs/PM828.h index abf593c..96c0edf 100644 --- a/include/configs/PM828.h +++ b/include/configs/PM828.h @@ -183,7 +183,7 @@ /* * 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 */ diff --git a/include/configs/PM854.h b/include/configs/PM854.h index bd058fc..f2c11b0 100644 --- a/include/configs/PM854.h +++ b/include/configs/PM854.h @@ -148,7 +148,7 @@ #undef CFG_RAMBOOT #endif -#define CFG_FLASH_CFI_DRIVER +#define CONFIG_FLASH_CFI_DRIVER #define CFG_FLASH_CFI #define CFG_FLASH_EMPTY_INFO diff --git a/include/configs/PM856.h b/include/configs/PM856.h index 9355aaf..b2cf060 100644 --- a/include/configs/PM856.h +++ b/include/configs/PM856.h @@ -149,7 +149,7 @@ #undef CFG_RAMBOOT #endif -#define CFG_FLASH_CFI_DRIVER +#define CONFIG_FLASH_CFI_DRIVER #define CFG_FLASH_CFI #define CFG_FLASH_EMPTY_INFO diff --git a/include/configs/PMC405.h b/include/configs/PMC405.h index adbe8a9..966bbf9 100644 --- a/include/configs/PMC405.h +++ b/include/configs/PMC405.h @@ -214,7 +214,7 @@ #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 */ diff --git a/include/configs/PMC440.h b/include/configs/PMC440.h index 42f1d8d..9140287 100644 --- a/include/configs/PMC440.h +++ b/include/configs/PMC440.h @@ -120,7 +120,7 @@ * 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 } diff --git a/include/configs/Rattler.h b/include/configs/Rattler.h index 01ebc8f..e8ed095 100644 --- a/include/configs/Rattler.h +++ b/include/configs/Rattler.h @@ -187,7 +187,7 @@ #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 */ diff --git a/include/configs/SBC8540.h b/include/configs/SBC8540.h index 8a53fdd..6033d93 100644 --- a/include/configs/SBC8540.h +++ b/include/configs/SBC8540.h @@ -291,7 +291,7 @@ */ #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 */ diff --git a/include/configs/SX1.h b/include/configs/SX1.h index 50ad7dd..d233679 100644 --- a/include/configs/SX1.h +++ b/include/configs/SX1.h @@ -181,7 +181,7 @@ * 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 */ diff --git a/include/configs/SXNI855T.h b/include/configs/SXNI855T.h index aefc7ee..c5d5386 100644 --- a/include/configs/SXNI855T.h +++ b/include/configs/SXNI855T.h @@ -195,7 +195,7 @@ */ /* 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 diff --git a/include/configs/Sandpoint8240.h b/include/configs/Sandpoint8240.h index 5bbe3c5..cfd16d3 100644 --- a/include/configs/Sandpoint8240.h +++ b/include/configs/Sandpoint8240.h @@ -235,7 +235,7 @@ */ -#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 */ @@ -246,7 +246,7 @@ /* * 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 diff --git a/include/configs/Sandpoint8245.h b/include/configs/Sandpoint8245.h index a08451e..c0f2c57 100644 --- a/include/configs/Sandpoint8245.h +++ b/include/configs/Sandpoint8245.h @@ -203,7 +203,7 @@ */ -#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 */ @@ -214,7 +214,7 @@ /* * 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 diff --git a/include/configs/TB5200.h b/include/configs/TB5200.h index d21783b..3b68166 100644 --- a/include/configs/TB5200.h +++ b/include/configs/TB5200.h @@ -255,7 +255,7 @@ /* 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 */ diff --git a/include/configs/TK885D.h b/include/configs/TK885D.h index 7310abf..8073b7e 100644 --- a/include/configs/TK885D.h +++ b/include/configs/TK885D.h @@ -247,7 +247,7 @@ /* 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 diff --git a/include/configs/TQM5200.h b/include/configs/TQM5200.h index bfb478a..992439f 100644 --- a/include/configs/TQM5200.h +++ b/include/configs/TQM5200.h @@ -386,7 +386,7 @@ #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) */ diff --git a/include/configs/TQM823L.h b/include/configs/TQM823L.h index 100be7c..839b6be 100644 --- a/include/configs/TQM823L.h +++ b/include/configs/TQM823L.h @@ -1,5 +1,5 @@ /* - * (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 @@ -37,6 +37,8 @@ #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 @@ -69,10 +71,17 @@ "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" @@ -113,7 +122,9 @@ #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 @@ -122,6 +133,8 @@ #endif +#define CONFIG_NETCONSOLE + /* * Miscellaneous configurable options */ @@ -195,8 +208,8 @@ /* 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 */ @@ -213,6 +226,18 @@ #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 */ diff --git a/include/configs/TQM823M.h b/include/configs/TQM823M.h index 40dc26b..b9a7a59 100644 --- a/include/configs/TQM823M.h +++ b/include/configs/TQM823M.h @@ -1,5 +1,5 @@ /* - * (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 @@ -69,10 +69,17 @@ "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" @@ -113,11 +120,16 @@ #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 */ @@ -191,7 +203,7 @@ /* 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 @@ -210,6 +222,18 @@ #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 */ diff --git a/include/configs/TQM8272.h b/include/configs/TQM8272.h index ba0402d..039ecf1 100644 --- a/include/configs/TQM8272.h +++ b/include/configs/TQM8272.h @@ -372,7 +372,7 @@ #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*/ diff --git a/include/configs/TQM834x.h b/include/configs/TQM834x.h index 0d2ca72..e8f69f6 100644 --- a/include/configs/TQM834x.h +++ b/include/configs/TQM834x.h @@ -78,7 +78,7 @@ * 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 */ diff --git a/include/configs/TQM850L.h b/include/configs/TQM850L.h index 3097bc3..388fafc 100644 --- a/include/configs/TQM850L.h +++ b/include/configs/TQM850L.h @@ -1,5 +1,5 @@ /* - * (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 @@ -65,10 +65,17 @@ "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" @@ -104,11 +111,15 @@ #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 */ @@ -182,8 +193,8 @@ /* 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 */ @@ -200,6 +211,18 @@ #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 */ diff --git a/include/configs/TQM850M.h b/include/configs/TQM850M.h index becf82c..6f0864f 100644 --- a/include/configs/TQM850M.h +++ b/include/configs/TQM850M.h @@ -1,5 +1,5 @@ /* - * (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 @@ -63,10 +63,17 @@ "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" @@ -102,11 +109,16 @@ #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 */ @@ -180,7 +192,7 @@ /* 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 @@ -199,6 +211,18 @@ #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 */ diff --git a/include/configs/TQM855L.h b/include/configs/TQM855L.h index 8ca8906..093d659 100644 --- a/include/configs/TQM855L.h +++ b/include/configs/TQM855L.h @@ -1,5 +1,5 @@ /* - * (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 @@ -68,10 +68,17 @@ "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" @@ -108,11 +115,16 @@ #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 */ @@ -186,8 +198,8 @@ /* 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 */ @@ -204,6 +216,18 @@ #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 */ diff --git a/include/configs/TQM855M.h b/include/configs/TQM855M.h index 2696ea5..64bbc39 100644 --- a/include/configs/TQM855M.h +++ b/include/configs/TQM855M.h @@ -1,5 +1,5 @@ /* - * (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 @@ -68,10 +68,17 @@ "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" @@ -141,12 +148,17 @@ #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 */ @@ -220,7 +232,7 @@ /* 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 @@ -239,6 +251,18 @@ #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 */ diff --git a/include/configs/TQM85xx.h b/include/configs/TQM85xx.h index d18f234..d84554e 100644 --- a/include/configs/TQM85xx.h +++ b/include/configs/TQM85xx.h @@ -204,7 +204,7 @@ #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 */ @@ -345,7 +345,7 @@ /* NAND FLASH */ #ifdef CONFIG_NAND -#undef CFG_NAND_LEGACY +#undef CONFIG_NAND_LEGACY #define CONFIG_NAND_FSL_UPM 1 diff --git a/include/configs/TQM860L.h b/include/configs/TQM860L.h index f66aace..dacc340 100644 --- a/include/configs/TQM860L.h +++ b/include/configs/TQM860L.h @@ -1,5 +1,5 @@ /* - * (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 @@ -68,10 +68,17 @@ "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" @@ -110,6 +117,7 @@ #define CONFIG_CMD_DHCP #define CONFIG_CMD_ELF #define CONFIG_CMD_IDE +#define CONFIG_CMD_JFFS2 #define CONFIG_CMD_NFS #define CONFIG_CMD_SNTP @@ -189,8 +197,8 @@ /* 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 */ @@ -207,6 +215,18 @@ #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 */ diff --git a/include/configs/TQM860M.h b/include/configs/TQM860M.h index 00b7853..3ec849c 100644 --- a/include/configs/TQM860M.h +++ b/include/configs/TQM860M.h @@ -68,15 +68,17 @@ "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" @@ -115,10 +117,14 @@ #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 */ @@ -191,7 +197,7 @@ */ /* 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 @@ -210,6 +216,18 @@ #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 */ diff --git a/include/configs/TQM862L.h b/include/configs/TQM862L.h index 7813a20..6c610ee 100644 --- a/include/configs/TQM862L.h +++ b/include/configs/TQM862L.h @@ -1,5 +1,5 @@ /* - * (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 @@ -71,10 +71,17 @@ "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" @@ -111,11 +118,16 @@ #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 */ @@ -189,8 +201,8 @@ /* 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 */ @@ -207,6 +219,18 @@ #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 */ diff --git a/include/configs/TQM862M.h b/include/configs/TQM862M.h index 05395e0..2eca59b 100644 --- a/include/configs/TQM862M.h +++ b/include/configs/TQM862M.h @@ -71,10 +71,17 @@ "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" @@ -111,11 +118,16 @@ #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 */ @@ -189,7 +201,7 @@ /* 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 @@ -208,6 +220,18 @@ #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 */ diff --git a/include/configs/TQM866M.h b/include/configs/TQM866M.h index d033875..4683286 100644 --- a/include/configs/TQM866M.h +++ b/include/configs/TQM866M.h @@ -80,15 +80,17 @@ "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" @@ -157,9 +159,14 @@ #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 /* @@ -234,7 +241,7 @@ */ /* 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 @@ -253,6 +260,18 @@ #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 */ diff --git a/include/configs/TQM885D.h b/include/configs/TQM885D.h index f075442..5daaf04 100644 --- a/include/configs/TQM885D.h +++ b/include/configs/TQM885D.h @@ -244,7 +244,7 @@ /* 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 diff --git a/include/configs/Total5200.h b/include/configs/Total5200.h index 598fe7b..25e98e2 100644 --- a/include/configs/Total5200.h +++ b/include/configs/Total5200.h @@ -204,7 +204,7 @@ * 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 } diff --git a/include/configs/VCMA9.h b/include/configs/VCMA9.h index ad8db61..02cabb2 100644 --- a/include/configs/VCMA9.h +++ b/include/configs/VCMA9.h @@ -254,7 +254,7 @@ */ #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 diff --git a/include/configs/ZPC1900.h b/include/configs/ZPC1900.h index b04be76..388c747 100644 --- a/include/configs/ZPC1900.h +++ b/include/configs/ZPC1900.h @@ -179,7 +179,7 @@ #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 */ diff --git a/include/configs/acadia.h b/include/configs/acadia.h index 9092a7c..ed2754d 100644 --- a/include/configs/acadia.h +++ b/include/configs/acadia.h @@ -107,7 +107,7 @@ *----------------------------------------------------------------------*/ #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 */ diff --git a/include/configs/actux1.h b/include/configs/actux1.h index 4c4b1d1..33a7494 100644 --- a/include/configs/actux1.h +++ b/include/configs/actux1.h @@ -162,7 +162,7 @@ /* 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 */ diff --git a/include/configs/actux2.h b/include/configs/actux2.h index 873fced..75aaa11 100644 --- a/include/configs/actux2.h +++ b/include/configs/actux2.h @@ -136,7 +136,7 @@ /* 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 diff --git a/include/configs/actux3.h b/include/configs/actux3.h index 5e468e6..693c284 100644 --- a/include/configs/actux3.h +++ b/include/configs/actux3.h @@ -135,7 +135,7 @@ /* 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 diff --git a/include/configs/actux4.h b/include/configs/actux4.h index e4dca2a..7f8e0f4 100644 --- a/include/configs/actux4.h +++ b/include/configs/actux4.h @@ -134,7 +134,7 @@ /* 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 */ diff --git a/include/configs/ads5121.h b/include/configs/ads5121.h index f104e68..d129ea3 100644 --- a/include/configs/ads5121.h +++ b/include/configs/ads5121.h @@ -183,7 +183,7 @@ */ #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 */ @@ -308,6 +308,7 @@ #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 @@ -478,10 +479,10 @@ #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" diff --git a/include/configs/aev.h b/include/configs/aev.h index c5e4759..f27cc4a 100644 --- a/include/configs/aev.h +++ b/include/configs/aev.h @@ -225,7 +225,7 @@ /* 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 */ diff --git a/include/configs/alpr.h b/include/configs/alpr.h index fb6feb5..f342c7a 100644 --- a/include/configs/alpr.h +++ b/include/configs/alpr.h @@ -86,7 +86,7 @@ * 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) */ diff --git a/include/configs/apollon.h b/include/configs/apollon.h index 5884611..c93e77a 100644 --- a/include/configs/apollon.h +++ b/include/configs/apollon.h @@ -215,7 +215,7 @@ * 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*/ diff --git a/include/configs/assabet.h b/include/configs/assabet.h index d10f092..ed7b5ef 100644 --- a/include/configs/assabet.h +++ b/include/configs/assabet.h @@ -152,7 +152,7 @@ #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 */ diff --git a/include/configs/at91cap9adk.h b/include/configs/at91cap9adk.h index 342ce2a..520c676 100644 --- a/include/configs/at91cap9adk.h +++ b/include/configs/at91cap9adk.h @@ -109,7 +109,7 @@ /* 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 diff --git a/include/configs/at91rm9200dk.h b/include/configs/at91rm9200dk.h index cd2eae2..fca431e 100644 --- a/include/configs/at91rm9200dk.h +++ b/include/configs/at91rm9200dk.h @@ -116,7 +116,7 @@ #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 diff --git a/include/configs/at91sam9263ek.h b/include/configs/at91sam9263ek.h index a8194b5..5f90d39 100644 --- a/include/configs/at91sam9263ek.h +++ b/include/configs/at91sam9263ek.h @@ -113,7 +113,7 @@ #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 diff --git a/include/configs/atngw100.h b/include/configs/atngw100.h index f040b86..6d8c1b2 100644 --- a/include/configs/atngw100.h +++ b/include/configs/atngw100.h @@ -140,7 +140,7 @@ #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 diff --git a/include/configs/atstk1002.h b/include/configs/atstk1002.h index 68f0cec..3a7d273 100644 --- a/include/configs/atstk1002.h +++ b/include/configs/atstk1002.h @@ -163,7 +163,7 @@ /* 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 diff --git a/include/configs/atstk1003.h b/include/configs/atstk1003.h index d3a2f69..55ea7f2 100644 --- a/include/configs/atstk1003.h +++ b/include/configs/atstk1003.h @@ -146,7 +146,7 @@ /* 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 diff --git a/include/configs/atstk1004.h b/include/configs/atstk1004.h index a37ba92..369c619 100644 --- a/include/configs/atstk1004.h +++ b/include/configs/atstk1004.h @@ -146,7 +146,7 @@ /* 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 diff --git a/include/configs/atstk1006.h b/include/configs/atstk1006.h index a6c5b6e..902f822 100644 --- a/include/configs/atstk1006.h +++ b/include/configs/atstk1006.h @@ -163,7 +163,7 @@ /* 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 diff --git a/include/configs/bf533-stamp.h b/include/configs/bf533-stamp.h index d70aa10..9f5667b 100644 --- a/include/configs/bf533-stamp.h +++ b/include/configs/bf533-stamp.h @@ -94,7 +94,7 @@ */ #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 diff --git a/include/configs/bf537-stamp.h b/include/configs/bf537-stamp.h index a881d53..a06c1dc 100644 --- a/include/configs/bf537-stamp.h +++ b/include/configs/bf537-stamp.h @@ -221,7 +221,7 @@ #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) */ diff --git a/include/configs/bf561-ezkit.h b/include/configs/bf561-ezkit.h index e99e979..e4a7f9d 100644 --- a/include/configs/bf561-ezkit.h +++ b/include/configs/bf561-ezkit.h @@ -77,7 +77,7 @@ */ #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 diff --git a/include/configs/canmb.h b/include/configs/canmb.h index f097e2c..38714cc 100644 --- a/include/configs/canmb.h +++ b/include/configs/canmb.h @@ -130,7 +130,7 @@ #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 diff --git a/include/configs/canyonlands.h b/include/configs/canyonlands.h index ac2e5d9..3b5b280 100644 --- a/include/configs/canyonlands.h +++ b/include/configs/canyonlands.h @@ -188,7 +188,7 @@ * 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} diff --git a/include/configs/cm5200.h b/include/configs/cm5200.h index ef50c7c..0221dfe 100644 --- a/include/configs/cm5200.h +++ b/include/configs/cm5200.h @@ -177,7 +177,7 @@ * 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 */ diff --git a/include/configs/csb272.h b/include/configs/csb272.h index 15bf177..5145c00 100644 --- a/include/configs/csb272.h +++ b/include/configs/csb272.h @@ -264,7 +264,7 @@ * */ #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 */ diff --git a/include/configs/csb472.h b/include/configs/csb472.h index b06c0a2..d3e5ea8 100644 --- a/include/configs/csb472.h +++ b/include/configs/csb472.h @@ -263,7 +263,7 @@ * */ #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 */ diff --git a/include/configs/csb637.h b/include/configs/csb637.h index 735a211..88c8fdb 100644 --- a/include/configs/csb637.h +++ b/include/configs/csb637.h @@ -179,7 +179,7 @@ #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 */ diff --git a/include/configs/davinci_dvevm.h b/include/configs/davinci_dvevm.h index 632c4c2..c27ce18 100644 --- a/include/configs/davinci_dvevm.h +++ b/include/configs/davinci_dvevm.h @@ -140,7 +140,7 @@ #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 */ diff --git a/include/configs/davinci_sonata.h b/include/configs/davinci_sonata.h index ba68605..c55766c 100644 --- a/include/configs/davinci_sonata.h +++ b/include/configs/davinci_sonata.h @@ -135,7 +135,7 @@ #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 */ diff --git a/include/configs/dbau1x00.h b/include/configs/dbau1x00.h index 0e10396..8941c5e 100644 --- a/include/configs/dbau1x00.h +++ b/include/configs/dbau1x00.h @@ -183,7 +183,7 @@ #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 diff --git a/include/configs/delta.h b/include/configs/delta.h index 14fde1a..1db962a 100644 --- a/include/configs/delta.h +++ b/include/configs/delta.h @@ -217,7 +217,7 @@ /* * NAND Flash */ -#undef CFG_NAND_LEGACY +#undef CONFIG_NAND_LEGACY #define CFG_NAND0_BASE 0x0 /* 0x43100040 */ /* 0x10000000 */ #undef CFG_NAND1_BASE diff --git a/include/configs/eXalion.h b/include/configs/eXalion.h index f8e2c88..6ba0d3f 100644 --- a/include/configs/eXalion.h +++ b/include/configs/eXalion.h @@ -170,7 +170,7 @@ */ #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 */ diff --git a/include/configs/ep8248.h b/include/configs/ep8248.h index 8a220b6..ccc0d5d 100644 --- a/include/configs/ep8248.h +++ b/include/configs/ep8248.h @@ -186,7 +186,7 @@ #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 */ diff --git a/include/configs/ep82xxm.h b/include/configs/ep82xxm.h index ac5847c..ac68c86 100644 --- a/include/configs/ep82xxm.h +++ b/include/configs/ep82xxm.h @@ -202,7 +202,7 @@ *----------------------------------------------------------------------*/ #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 */ diff --git a/include/configs/gcplus.h b/include/configs/gcplus.h index 3b1b4ab..1d9c05b 100644 --- a/include/configs/gcplus.h +++ b/include/configs/gcplus.h @@ -169,7 +169,7 @@ #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 */ diff --git a/include/configs/gr_cpci_ax2000.h b/include/configs/gr_cpci_ax2000.h index ffe7671..942609f 100644 --- a/include/configs/gr_cpci_ax2000.h +++ b/include/configs/gr_cpci_ax2000.h @@ -208,7 +208,7 @@ /*** 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 diff --git a/include/configs/gr_ep2s60.h b/include/configs/gr_ep2s60.h index 7b1d582..ae25fb2 100644 --- a/include/configs/gr_ep2s60.h +++ b/include/configs/gr_ep2s60.h @@ -196,7 +196,7 @@ /*** 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 diff --git a/include/configs/gr_xc3s_1500.h b/include/configs/gr_xc3s_1500.h index 6fe2b7c..f019bb4 100644 --- a/include/configs/gr_xc3s_1500.h +++ b/include/configs/gr_xc3s_1500.h @@ -172,7 +172,7 @@ /*** 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 diff --git a/include/configs/grsim.h b/include/configs/grsim.h index 3fb8eb3..f880a7b 100644 --- a/include/configs/grsim.h +++ b/include/configs/grsim.h @@ -202,7 +202,7 @@ /*** 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 diff --git a/include/configs/grsim_leon2.h b/include/configs/grsim_leon2.h index 406ce3d..e5af9a6 100644 --- a/include/configs/grsim_leon2.h +++ b/include/configs/grsim_leon2.h @@ -199,7 +199,7 @@ /*** 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 diff --git a/include/configs/hcu4.h b/include/configs/hcu4.h index 13b0358..d99ac53 100644 --- a/include/configs/hcu4.h +++ b/include/configs/hcu4.h @@ -105,7 +105,7 @@ /* 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 diff --git a/include/configs/hcu5.h b/include/configs/hcu5.h index 2080868..54d6721 100644 --- a/include/configs/hcu5.h +++ b/include/configs/hcu5.h @@ -351,7 +351,7 @@ /* 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 diff --git a/include/configs/hmi1001.h b/include/configs/hmi1001.h index ad7cf76..205f5cc 100644 --- a/include/configs/hmi1001.h +++ b/include/configs/hmi1001.h @@ -155,7 +155,7 @@ #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 diff --git a/include/configs/imx31_litekit.h b/include/configs/imx31_litekit.h index ec4ed1e..c476333 100644 --- a/include/configs/imx31_litekit.h +++ b/include/configs/imx31_litekit.h @@ -158,7 +158,7 @@ * 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 */ diff --git a/include/configs/imx31_phycore.h b/include/configs/imx31_phycore.h index 7d6aaa1..237f361 100644 --- a/include/configs/imx31_phycore.h +++ b/include/configs/imx31_phycore.h @@ -164,7 +164,7 @@ * 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 */ diff --git a/include/configs/inka4x0.h b/include/configs/inka4x0.h index 6ec92c3..efa2802 100644 --- a/include/configs/inka4x0.h +++ b/include/configs/inka4x0.h @@ -160,7 +160,7 @@ * 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 */ diff --git a/include/configs/ixdp425.h b/include/configs/ixdp425.h index b7c43fe..6b73abe 100644 --- a/include/configs/ixdp425.h +++ b/include/configs/ixdp425.h @@ -181,7 +181,7 @@ #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 } diff --git a/include/configs/ixdpg425.h b/include/configs/ixdpg425.h index 05dc841..d4e4871 100644 --- a/include/configs/ixdpg425.h +++ b/include/configs/ixdpg425.h @@ -210,7 +210,7 @@ #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) */ diff --git a/include/configs/jupiter.h b/include/configs/jupiter.h index c985927..af88a3f 100644 --- a/include/configs/jupiter.h +++ b/include/configs/jupiter.h @@ -191,7 +191,7 @@ #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 diff --git a/include/configs/katmai.h b/include/configs/katmai.h index f07e470..5dcca75 100644 --- a/include/configs/katmai.h +++ b/include/configs/katmai.h @@ -54,7 +54,6 @@ #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 /*----------------------------------------------------------------------- @@ -208,7 +207,7 @@ * 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) */ diff --git a/include/configs/kb9202.h b/include/configs/kb9202.h index 7dcce83..e775e60 100644 --- a/include/configs/kb9202.h +++ b/include/configs/kb9202.h @@ -153,7 +153,7 @@ #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__ diff --git a/include/configs/kilauea.h b/include/configs/kilauea.h index 9c1a3a4..a475f97 100644 --- a/include/configs/kilauea.h +++ b/include/configs/kilauea.h @@ -131,7 +131,7 @@ * 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 */ @@ -233,39 +233,124 @@ #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 @@ -290,6 +375,7 @@ *----------------------------------------------------------------------*/ #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 */ diff --git a/include/configs/korat.h b/include/configs/korat.h index 4ca4ed0..a887446 100644 --- a/include/configs/korat.h +++ b/include/configs/korat.h @@ -110,7 +110,7 @@ * 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 } diff --git a/include/configs/kvme080.h b/include/configs/kvme080.h index 569800a..819e456 100644 --- a/include/configs/kvme080.h +++ b/include/configs/kvme080.h @@ -142,7 +142,7 @@ #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 diff --git a/include/configs/linkstation.h b/include/configs/linkstation.h index bc64294..e5a0fb9 100644 --- a/include/configs/linkstation.h +++ b/include/configs/linkstation.h @@ -434,7 +434,7 @@ * 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 } diff --git a/include/configs/lwmon5.h b/include/configs/lwmon5.h index 2f3a066..3d135c4 100644 --- a/include/configs/lwmon5.h +++ b/include/configs/lwmon5.h @@ -124,7 +124,7 @@ * 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 diff --git a/include/configs/m501sk.h b/include/configs/m501sk.h index e4be1ed..bc94cf4 100644 --- a/include/configs/m501sk.h +++ b/include/configs/m501sk.h @@ -57,7 +57,7 @@ * 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*/ diff --git a/include/configs/makalu.h b/include/configs/makalu.h index 65b240e..cfc6fdc 100644 --- a/include/configs/makalu.h +++ b/include/configs/makalu.h @@ -125,7 +125,7 @@ * 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 */ @@ -223,6 +223,7 @@ *----------------------------------------------------------------------*/ #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 */ diff --git a/include/configs/mcc200.h b/include/configs/mcc200.h index e4c3f72..f512847 100644 --- a/include/configs/mcc200.h +++ b/include/configs/mcc200.h @@ -211,7 +211,7 @@ #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 } diff --git a/include/configs/mcu25.h b/include/configs/mcu25.h index 4e9645e..6adba96 100644 --- a/include/configs/mcu25.h +++ b/include/configs/mcu25.h @@ -105,7 +105,7 @@ /* 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 diff --git a/include/configs/mecp5200.h b/include/configs/mecp5200.h index 8dfb9aa..75040fe 100644 --- a/include/configs/mecp5200.h +++ b/include/configs/mecp5200.h @@ -203,7 +203,7 @@ #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 diff --git a/include/configs/mgcoge.h b/include/configs/mgcoge.h index 59ff96b..5fe3075 100644 --- a/include/configs/mgcoge.h +++ b/include/configs/mgcoge.h @@ -153,7 +153,7 @@ #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 */ diff --git a/include/configs/mgsuvd.h b/include/configs/mgsuvd.h index 9cbc9cc..6f1c640 100644 --- a/include/configs/mgsuvd.h +++ b/include/configs/mgsuvd.h @@ -189,7 +189,7 @@ #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 */ diff --git a/include/configs/ml401.h b/include/configs/ml401.h index 7e0df87..36a42ba 100644 --- a/include/configs/ml401.h +++ b/include/configs/ml401.h @@ -154,7 +154,7 @@ #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 */ diff --git a/include/configs/ml507.h b/include/configs/ml507.h new file mode 100644 index 0000000..c653a51 --- /dev/null +++ b/include/configs/ml507.h @@ -0,0 +1,122 @@ +/* + * (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 */ diff --git a/include/configs/motionpro.h b/include/configs/motionpro.h index 3d1eafe..f2a35ee 100644 --- a/include/configs/motionpro.h +++ b/include/configs/motionpro.h @@ -263,7 +263,7 @@ * 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 */ diff --git a/include/configs/mpc7448hpc2.h b/include/configs/mpc7448hpc2.h index 2f24967..d379b1f 100644 --- a/include/configs/mpc7448hpc2.h +++ b/include/configs/mpc7448hpc2.h @@ -374,7 +374,7 @@ #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 diff --git a/include/configs/mpr2.h b/include/configs/mpr2.h index 0fc0b97..3df6e39 100644 --- a/include/configs/mpr2.h +++ b/include/configs/mpr2.h @@ -67,7 +67,7 @@ /* 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 @@ -86,7 +86,7 @@ #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 */ diff --git a/include/configs/ms7720se.h b/include/configs/ms7720se.h index 5e79a27..1c3d277 100644 --- a/include/configs/ms7720se.h +++ b/include/configs/ms7720se.h @@ -63,7 +63,7 @@ #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 @@ -82,7 +82,7 @@ /* 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 */ diff --git a/include/configs/ms7722se.h b/include/configs/ms7722se.h index 7298e55..3809e71 100644 --- a/include/configs/ms7722se.h +++ b/include/configs/ms7722se.h @@ -62,7 +62,7 @@ #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 @@ -90,7 +90,7 @@ /* 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 */ diff --git a/include/configs/ms7750se.h b/include/configs/ms7750se.h index 3000c77..4356a67 100644 --- a/include/configs/ms7750se.h +++ b/include/configs/ms7750se.h @@ -42,7 +42,7 @@ #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 @@ -86,7 +86,7 @@ #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 */ diff --git a/include/configs/munices.h b/include/configs/munices.h index e0046ec..cea2834 100644 --- a/include/configs/munices.h +++ b/include/configs/munices.h @@ -133,7 +133,7 @@ */ #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 */ diff --git a/include/configs/mx31ads.h b/include/configs/mx31ads.h index 37ba872..9ede764 100644 --- a/include/configs/mx31ads.h +++ b/include/configs/mx31ads.h @@ -185,7 +185,7 @@ * 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 */ diff --git a/include/configs/ns9750dev.h b/include/configs/ns9750dev.h index f30cb46..746a56e 100644 --- a/include/configs/ns9750dev.h +++ b/include/configs/ns9750dev.h @@ -56,7 +56,7 @@ /* * 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 */ /* diff --git a/include/configs/omap1510inn.h b/include/configs/omap1510inn.h index 0be46ea..46b30e0 100644 --- a/include/configs/omap1510inn.h +++ b/include/configs/omap1510inn.h @@ -179,7 +179,7 @@ * 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 */ diff --git a/include/configs/omap2420h4.h b/include/configs/omap2420h4.h index 88a3f6e..afdcba4 100644 --- a/include/configs/omap2420h4.h +++ b/include/configs/omap2420h4.h @@ -151,7 +151,7 @@ /* * 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 */ @@ -283,7 +283,7 @@ * 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 */ diff --git a/include/configs/omap5912osk.h b/include/configs/omap5912osk.h index e3bde4f..1c44ce0 100644 --- a/include/configs/omap5912osk.h +++ b/include/configs/omap5912osk.h @@ -174,7 +174,7 @@ * 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 } diff --git a/include/configs/p3mx.h b/include/configs/p3mx.h index 0913b14..33a94bc 100644 --- a/include/configs/p3mx.h +++ b/include/configs/p3mx.h @@ -128,7 +128,7 @@ * 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) */ diff --git a/include/configs/p3p440.h b/include/configs/p3p440.h index 82f2391..ac0d83a 100644 --- a/include/configs/p3p440.h +++ b/include/configs/p3p440.h @@ -279,7 +279,7 @@ * 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 } diff --git a/include/configs/pdnb3.h b/include/configs/pdnb3.h index aca70dc..889207a 100644 --- a/include/configs/pdnb3.h +++ b/include/configs/pdnb3.h @@ -218,7 +218,7 @@ */ #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 diff --git a/include/configs/ppmc8260.h b/include/configs/ppmc8260.h index dee6643..6f1195b 100644 --- a/include/configs/ppmc8260.h +++ b/include/configs/ppmc8260.h @@ -452,7 +452,7 @@ */ #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 */ diff --git a/include/configs/pxa255_idp.h b/include/configs/pxa255_idp.h index a2f3650..179ff7a 100644 --- a/include/configs/pxa255_idp.h +++ b/include/configs/pxa255_idp.h @@ -333,7 +333,7 @@ * 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 diff --git a/include/configs/qemu-mips.h b/include/configs/qemu-mips.h index 3dfd218..19e627b 100644 --- a/include/configs/qemu-mips.h +++ b/include/configs/qemu-mips.h @@ -146,7 +146,7 @@ #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 diff --git a/include/configs/quad100hd.h b/include/configs/quad100hd.h index 622a5d4..d464734 100644 --- a/include/configs/quad100hd.h +++ b/include/configs/quad100hd.h @@ -182,7 +182,7 @@ * 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 } diff --git a/include/configs/quantum.h b/include/configs/quantum.h index cc261c3..34a1ea6 100644 --- a/include/configs/quantum.h +++ b/include/configs/quantum.h @@ -170,13 +170,13 @@ #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} diff --git a/include/configs/r2dplus.h b/include/configs/r2dplus.h index e269336..06ede3e 100644 --- a/include/configs/r2dplus.h +++ b/include/configs/r2dplus.h @@ -26,7 +26,7 @@ #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 @@ -65,7 +65,7 @@ * 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 diff --git a/include/configs/r7780mp.h b/include/configs/r7780mp.h index 4c82c5a..77881e7 100644 --- a/include/configs/r7780mp.h +++ b/include/configs/r7780mp.h @@ -49,7 +49,7 @@ #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 @@ -106,7 +106,7 @@ #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 */ diff --git a/include/configs/redwood.h b/include/configs/redwood.h new file mode 100644 index 0000000..32ed574 --- /dev/null +++ b/include/configs/redwood.h @@ -0,0 +1,186 @@ +/* + * 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 */ diff --git a/include/configs/sbc8349.h b/include/configs/sbc8349.h index 7481556..261229c 100644 --- a/include/configs/sbc8349.h +++ b/include/configs/sbc8349.h @@ -133,7 +133,7 @@ * 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 */ diff --git a/include/configs/sbc8548.h b/include/configs/sbc8548.h index 358fc02..b4238e5 100644 --- a/include/configs/sbc8548.h +++ b/include/configs/sbc8548.h @@ -178,7 +178,7 @@ #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 diff --git a/include/configs/sbc8560.h b/include/configs/sbc8560.h index 6345cce..b244eef 100644 --- a/include/configs/sbc8560.h +++ b/include/configs/sbc8560.h @@ -290,7 +290,7 @@ */ #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 */ diff --git a/include/configs/sbc8641d.h b/include/configs/sbc8641d.h index 3cd9ff8..efc787e 100644 --- a/include/configs/sbc8641d.h +++ b/include/configs/sbc8641d.h @@ -58,6 +58,8 @@ #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 */ @@ -221,7 +223,7 @@ #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 diff --git a/include/configs/sc3.h b/include/configs/sc3.h index 87311ea..659f74e 100644 --- a/include/configs/sc3.h +++ b/include/configs/sc3.h @@ -397,7 +397,7 @@ extern unsigned long offsetOfEnvironment; #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) */ diff --git a/include/configs/sc520_cdp.h b/include/configs/sc520_cdp.h index 0e830b8..e29655e 100644 --- a/include/configs/sc520_cdp.h +++ b/include/configs/sc520_cdp.h @@ -178,7 +178,7 @@ #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 diff --git a/include/configs/sequoia.h b/include/configs/sequoia.h index f4eefae..18675c2 100644 --- a/include/configs/sequoia.h +++ b/include/configs/sequoia.h @@ -123,7 +123,7 @@ * 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 } @@ -422,12 +422,12 @@ /* 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) */ \ diff --git a/include/configs/sh7763rdp.h b/include/configs/sh7763rdp.h index 7713eaa..1306702 100644 --- a/include/configs/sh7763rdp.h +++ b/include/configs/sh7763rdp.h @@ -38,7 +38,11 @@ #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" @@ -48,7 +52,7 @@ #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 @@ -85,7 +89,7 @@ #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) */ @@ -113,4 +117,9 @@ #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 */ diff --git a/include/configs/smmaco4.h b/include/configs/smmaco4.h index 3e47eb8..1d202d4 100644 --- a/include/configs/smmaco4.h +++ b/include/configs/smmaco4.h @@ -196,7 +196,7 @@ /* 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 */ diff --git a/include/configs/socrates.h b/include/configs/socrates.h index 1627413..8a64942 100644 --- a/include/configs/socrates.h +++ b/include/configs/socrates.h @@ -139,7 +139,7 @@ #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 */ diff --git a/include/configs/sorcery.h b/include/configs/sorcery.h index 18f5533..f4e4608 100644 --- a/include/configs/sorcery.h +++ b/include/configs/sorcery.h @@ -189,7 +189,7 @@ #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 */ diff --git a/include/configs/spc1920.h b/include/configs/spc1920.h index f46c464..daaa23f 100644 --- a/include/configs/spc1920.h +++ b/include/configs/spc1920.h @@ -180,7 +180,7 @@ */ #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 */ diff --git a/include/configs/spieval.h b/include/configs/spieval.h index 69d2d67..93798a4 100644 --- a/include/configs/spieval.h +++ b/include/configs/spieval.h @@ -287,7 +287,7 @@ /* 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 */ diff --git a/include/configs/stxssa.h b/include/configs/stxssa.h index a1e9789..4f1c156 100644 --- a/include/configs/stxssa.h +++ b/include/configs/stxssa.h @@ -98,7 +98,7 @@ #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 */ diff --git a/include/configs/stxxtc.h b/include/configs/stxxtc.h index fcafba5..37a52cf 100644 --- a/include/configs/stxxtc.h +++ b/include/configs/stxxtc.h @@ -213,7 +213,7 @@ #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 */ @@ -449,7 +449,7 @@ /****************************************************************/ /* 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 diff --git a/include/configs/svm_sc8xx.h b/include/configs/svm_sc8xx.h index 70336b5..bbbfa15 100644 --- a/include/configs/svm_sc8xx.h +++ b/include/configs/svm_sc8xx.h @@ -151,7 +151,7 @@ #define CONFIG_CMD_DATE -#define CFG_NAND_LEGACY +#define CONFIG_NAND_LEGACY /* * Miscellaneous configurable options diff --git a/include/configs/taishan.h b/include/configs/taishan.h index ba42192..81133bb 100644 --- a/include/configs/taishan.h +++ b/include/configs/taishan.h @@ -89,7 +89,7 @@ * 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) */ diff --git a/include/configs/trizepsiv.h b/include/configs/trizepsiv.h index f77dd14..6367f87 100644 --- a/include/configs/trizepsiv.h +++ b/include/configs/trizepsiv.h @@ -293,7 +293,7 @@ */ #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 diff --git a/include/configs/uc100.h b/include/configs/uc100.h index e74b1bb..106e6f2 100644 --- a/include/configs/uc100.h +++ b/include/configs/uc100.h @@ -230,7 +230,7 @@ * 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 */ diff --git a/include/configs/uc101.h b/include/configs/uc101.h index 042750e..a186188 100644 --- a/include/configs/uc101.h +++ b/include/configs/uc101.h @@ -168,7 +168,7 @@ #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 diff --git a/include/configs/v38b.h b/include/configs/v38b.h index c203522..3574548 100644 --- a/include/configs/v38b.h +++ b/include/configs/v38b.h @@ -201,7 +201,7 @@ * 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 */ diff --git a/include/configs/virtlab2.h b/include/configs/virtlab2.h index 6bb075d..1a125f1 100644 --- a/include/configs/virtlab2.h +++ b/include/configs/virtlab2.h @@ -1,5 +1,5 @@ /* - * (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 @@ -37,10 +37,6 @@ #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 @@ -70,9 +66,17 @@ "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" @@ -114,6 +118,7 @@ #define CONFIG_CMD_DATE #define CONFIG_CMD_DHCP #define CONFIG_CMD_IDE +#define CONFIG_CMD_JFFS2 #define CONFIG_CMD_NFS #define CONFIG_CMD_SNTP @@ -122,15 +127,16 @@ #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 @@ -196,8 +202,8 @@ /* 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 */ @@ -214,6 +220,18 @@ #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 */ diff --git a/include/configs/voiceblue.h b/include/configs/voiceblue.h index 8c827af..20917ee 100644 --- a/include/configs/voiceblue.h +++ b/include/configs/voiceblue.h @@ -60,7 +60,7 @@ * 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 diff --git a/include/configs/yosemite.h b/include/configs/yosemite.h index 891b515..cb2042c 100644 --- a/include/configs/yosemite.h +++ b/include/configs/yosemite.h @@ -105,7 +105,7 @@ * 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 */ diff --git a/include/configs/zeus.h b/include/configs/zeus.h index cd120df..b50cba5 100644 --- a/include/configs/zeus.h +++ b/include/configs/zeus.h @@ -210,7 +210,7 @@ * 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 } diff --git a/include/dataflash.h b/include/dataflash.h index 80f0633..de04139 100644 --- a/include/dataflash.h +++ b/include/dataflash.h @@ -135,9 +135,9 @@ struct dataflash_addr { int cs; }; /*-------------------------------------------------------------------------------------------------*/ - #define AT45DB161 0x2c #define AT45DB021 0x14 +#define AT45DB081 0x24 #define AT45DB321 0x34 #define AT45DB642 0x3c #define AT45DB128 0x10 diff --git a/include/image.h b/include/image.h index 46138fa..4b9c582 100644 --- a/include/image.h +++ b/include/image.h @@ -220,7 +220,6 @@ typedef struct bootm_headers { #endif int verify; /* getenv("verify")[0] != 'n' */ - int autostart; /* getenv("autostart")[0] != 'n' */ struct lmb *lmb; /* for memory mgmt */ } bootm_headers_t; diff --git a/include/linux/err.h b/include/linux/err.h new file mode 100644 index 0000000..4e08c4f --- /dev/null +++ b/include/linux/err.h @@ -0,0 +1,45 @@ +#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 */ diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h new file mode 100644 index 0000000..d1ded51 --- /dev/null +++ b/include/linux/mtd/blktrans.h @@ -0,0 +1,81 @@ +/* + * $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__ */ diff --git a/include/linux/mtd/compat.h b/include/linux/mtd/compat.h index fe55087..9036b74 100644 --- a/include/linux/mtd/compat.h +++ b/include/linux/mtd/compat.h @@ -18,7 +18,12 @@ #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 diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index 29f6767..12de284 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h @@ -1,15 +1,23 @@ - -/* 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 @@ -40,10 +48,58 @@ struct DiskOnChip; #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) @@ -54,14 +110,21 @@ struct DiskOnChip; #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 @@ -77,41 +140,47 @@ struct DiskOnChip; #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; @@ -119,98 +188,22 @@ struct DiskOnChip { 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__ */ diff --git a/include/linux/mtd/fsl_upm.h b/include/linux/mtd/fsl_upm.h index 49fd8a6..638a4e4 100644 --- a/include/linux/mtd/fsl_upm.h +++ b/include/linux/mtd/fsl_upm.h @@ -31,6 +31,9 @@ struct fsl_upm_nand { 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); diff --git a/include/linux/mtd/inftl-user.h b/include/linux/mtd/inftl-user.h new file mode 100644 index 0000000..9b1e252 --- /dev/null +++ b/include/linux/mtd/inftl-user.h @@ -0,0 +1,91 @@ +/* + * $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__ */ + + diff --git a/include/linux/mtd/jffs2-user.h b/include/linux/mtd/jffs2-user.h new file mode 100644 index 0000000..d508ef0 --- /dev/null +++ b/include/linux/mtd/jffs2-user.h @@ -0,0 +1,35 @@ +/* + * $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__ */ diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h index 4cebea9..0ce2099 100644 --- a/include/linux/mtd/mtd-abi.h +++ b/include/linux/mtd/mtd-abi.h @@ -1,5 +1,5 @@ /* - * $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 */ @@ -7,6 +7,10 @@ #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; @@ -15,7 +19,7 @@ struct erase_info_user { struct mtd_oob_buf { uint32_t start; uint32_t length; - unsigned char *ptr; + unsigned char __user *ptr; }; #define MTD_ABSENT 0 @@ -23,47 +27,41 @@ struct mtd_oob_buf { #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 */ - -/* 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) +#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 */ -/* 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 */ +// Some common devices / combinations of capabilities +#define MTD_CAP_ROM 0 +#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_PLACE 1 /* Use the given placement in the structure (YAFFS1 legacy mode) */ -#define MTD_NANDECC_AUTOPLACE 2 /* Use the default placement scheme */ -#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 */ +#define MTD_NANDECC_OFF 0 // Switch off ECC (Not recommended) +#define MTD_NANDECC_PLACE 1 // Use the given placement in the structure (YAFFS1 legacy mode) +#define MTD_NANDECC_AUTOPLACE 2 // Use the default placement scheme +#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; }; @@ -76,19 +74,36 @@ struct region_info_user { 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; @@ -96,4 +111,46 @@ struct nand_oobinfo { 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__ */ diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 05ba375..8e0dc00 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,5 +1,5 @@ /* - * $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. * @@ -8,10 +8,13 @@ #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 @@ -41,32 +44,83 @@ struct mtd_erase_region_info { 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_char type; u_int32_t flags; - u_int32_t size; /* Total size of the MTD */ + 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 oobsize; // Amount of OOB data per block (e.g. 16) + u_int32_t oobavail; // Available OOB bytes per block - /* Kernel-only stuff starts here. */ + // 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. @@ -74,9 +128,6 @@ struct mtd_info { 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 */ @@ -89,39 +140,35 @@ struct mtd_info { 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); @@ -129,15 +176,32 @@ struct mtd_info { /* 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); }; @@ -147,9 +211,11 @@ extern int add_mtd_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); @@ -157,7 +223,6 @@ struct mtd_notifier { struct list_head list; }; - extern void register_mtd_user (struct mtd_notifier *new); extern int unregister_mtd_user (struct mtd_notifier *old); @@ -168,20 +233,6 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, 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 @@ -208,7 +259,6 @@ static inline void mtd_erase_callback(struct erase_info *instr) } while(0) #else /* CONFIG_MTD_DEBUG */ #define MTDDEBUG(n, args...) do { } while(0) - #endif /* CONFIG_MTD_DEBUG */ #endif /* __MTD_MTD_H__ */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index e2a25a6..2993a89 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -2,114 +2,123 @@ * 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 @@ -120,25 +129,16 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ /* * 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 */ @@ -146,6 +146,10 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ /* 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 */ @@ -165,6 +169,17 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ /* 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 \ @@ -183,18 +198,20 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ /* 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 +/* Cell info constants */ +#define NAND_CI_CHIPNR_MSK 0x03 +#define NAND_CI_CELLTYPE_MSK 0x0C /* * nand_state_t - chip states @@ -207,135 +224,217 @@ typedef enum { FL_ERASING, FL_SYNCING, FL_CACHEDPRG, + FL_PM_SUSPENDED, } nand_state_t; /* 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; + + nand_state_t 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; }; @@ -348,11 +447,11 @@ struct nand_chip { #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 @@ -403,7 +502,7 @@ extern struct nand_manufacturers nand_manuf_ids[]; * 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 * @@ -417,11 +516,11 @@ struct nand_bbt_descr { 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 */ @@ -433,7 +532,7 @@ struct nand_bbt_descr { #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 */ @@ -456,13 +555,16 @@ struct nand_bbt_descr { #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 @@ -470,4 +572,67 @@ extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int #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 */ diff --git a/include/linux/mtd/nand_ids.h b/include/linux/mtd/nand_ids.h index d9eb911..e7aa26d 100644 --- a/include/linux/mtd/nand_ids.h +++ b/include/linux/mtd/nand_ids.h @@ -28,7 +28,7 @@ #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 diff --git a/include/linux/mtd/nand_legacy.h b/include/linux/mtd/nand_legacy.h index b05e726..4494bc5 100644 --- a/include/linux/mtd/nand_legacy.h +++ b/include/linux/mtd/nand_legacy.h @@ -36,7 +36,7 @@ #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 diff --git a/include/linux/mtd/nftl-user.h b/include/linux/mtd/nftl-user.h new file mode 100644 index 0000000..b2bca18 --- /dev/null +++ b/include/linux/mtd/nftl-user.h @@ -0,0 +1,76 @@ +/* + * $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__ */ diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h index b0337c3..04963a5 100644 --- a/include/linux/mtd/nftl.h +++ b/include/linux/mtd/nftl.h @@ -1,75 +1,16 @@ - -/* 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 */ @@ -78,7 +19,7 @@ struct NFTLMediaHeader { #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; @@ -90,16 +31,24 @@ struct NFTLrecord { __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 */ + 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__ */ diff --git a/include/linux/mtd/ubi-header.h b/include/linux/mtd/ubi-header.h new file mode 100644 index 0000000..fa479c7 --- /dev/null +++ b/include/linux/mtd/ubi-header.h @@ -0,0 +1,360 @@ +/* + * 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__ */ diff --git a/include/linux/mtd/ubi-user.h b/include/linux/mtd/ubi-user.h new file mode 100644 index 0000000..fe06ded --- /dev/null +++ b/include/linux/mtd/ubi-user.h @@ -0,0 +1,161 @@ +/* + * 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__ */ diff --git a/include/mpc512x.h b/include/mpc512x.h index b4cc2b9..a76b1ca 100644 --- a/include/mpc512x.h +++ b/include/mpc512x.h @@ -347,41 +347,226 @@ /* 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 diff --git a/include/mpc83xx.h b/include/mpc83xx.h index 897ecd6..70a4de7 100644 --- a/include/mpc83xx.h +++ b/include/mpc83xx.h @@ -30,7 +30,9 @@ /* 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) diff --git a/include/nand.h b/include/nand.h index e1285cd..4c2b76d 100644 --- a/include/nand.h +++ b/include/nand.h @@ -26,7 +26,7 @@ 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> @@ -84,6 +84,7 @@ struct nand_write_options { }; 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*/ @@ -107,9 +108,10 @@ struct nand_erase_options { 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 @@ -124,5 +126,7 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset); 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 diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h index 4449f98..4260ee7 100644 --- a/include/onenand_uboot.h +++ b/include/onenand_uboot.h @@ -39,6 +39,6 @@ extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr); 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 */ diff --git a/include/ppc405.h b/include/ppc405.h index 2231a5f..f19b67f 100644 --- a/include/ppc405.h +++ b/include/ppc405.h @@ -119,367 +119,6 @@ #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 @@ -1254,6 +893,42 @@ #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 */ diff --git a/include/ppc440.h b/include/ppc440.h index c581f1b..92db15f 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -77,7 +77,6 @@ #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 */ @@ -268,86 +267,6 @@ #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 */ /*----------------------------------------------------------------------------- @@ -749,7 +668,8 @@ +----------------------------------------------------------------------------*/ #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 */ @@ -837,7 +757,8 @@ /*----------------------------------------------------------------------------- | 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 @@ -863,193 +784,6 @@ #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) @@ -1136,708 +870,6 @@ #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 +-----------------------------------------------------------------------------*/ @@ -1855,7 +887,7 @@ #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 @@ -2793,7 +1825,8 @@ /*-----------------------------------------------------------------------------+ | 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 */ @@ -2873,118 +1906,10 @@ #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 @@ -3006,20 +1931,6 @@ #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) @@ -3145,7 +2056,8 @@ * 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) diff --git a/include/ppc4xx.h b/include/ppc4xx.h index 1d06da8..c71da60 100644 --- a/include/ppc4xx.h +++ b/include/ppc4xx.h @@ -41,7 +41,8 @@ #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 @@ -58,6 +59,10 @@ #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 diff --git a/include/ppc4xx_enet.h b/include/ppc4xx_enet.h index 4c97b36..b74c6fc 100644 --- a/include/ppc4xx_enet.h +++ b/include/ppc4xx_enet.h @@ -153,6 +153,20 @@ typedef struct emac_4xx_hw_st { #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) || \ @@ -218,12 +232,12 @@ typedef struct emac_4xx_hw_st { #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) diff --git a/include/usb.h b/include/usb.h index 5a6ffdd..e68e98e 100644 --- a/include/usb.h +++ b/include/usb.h @@ -171,7 +171,7 @@ struct usb_device { #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); diff --git a/lib_arm/bootm.c b/lib_arm/bootm.c index b838c37..955a1ae 100644 --- a/lib_arm/bootm.c +++ b/lib_arm/bootm.c @@ -137,9 +137,6 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], setup_end_tag (bd); #endif - if (!images->autostart) - return ; - /* we assume that the kernel is in place */ printf ("\nStarting kernel ...\n\n"); @@ -157,8 +154,7 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); return; } diff --git a/lib_avr32/bootm.c b/lib_avr32/bootm.c index 5ff8c79..60e6b36 100644 --- a/lib_avr32/bootm.c +++ b/lib_avr32/bootm.c @@ -221,9 +221,6 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], 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); @@ -234,7 +231,6 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); return; } diff --git a/lib_blackfin/bootm.c b/lib_blackfin/bootm.c index ef4b112..54f69a9 100644 --- a/lib_blackfin/bootm.c +++ b/lib_blackfin/bootm.c @@ -40,9 +40,6 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], char *cmdline; ulong ep = 0; - if (!images->autostart) - return; - #ifdef SHARED_RESOURCES swap_to(FLASH); #endif @@ -74,6 +71,5 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); } diff --git a/lib_generic/crc32.c b/lib_generic/crc32.c index 83d1d1d..b6a7a91 100644 --- a/lib_generic/crc32.c +++ b/lib_generic/crc32.c @@ -174,7 +174,7 @@ uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *buf, uInt len) #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. diff --git a/lib_i386/bootm.c b/lib_i386/bootm.c index d959107..452eef7 100644 --- a/lib_i386/bootm.c +++ b/lib_i386/bootm.c @@ -84,9 +84,6 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } - if (!images->autostart) - return ; - #ifdef DEBUG printf ("## Transferring control to Linux (at address %08x) ...\n", (u32)base_ptr); @@ -100,7 +97,6 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); return; } diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index 61f1a36..b45203d 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -129,8 +129,6 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, show_boot_progress (15); - if (!images->autostart) - return; /* * Linux Kernel Parameters (passing board info data): * r3: ptr to board info data @@ -144,8 +142,7 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, return ; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); return ; } diff --git a/lib_microblaze/bootm.c b/lib_microblaze/bootm.c index 30a03ef..68edcdb 100644 --- a/lib_microblaze/bootm.c +++ b/lib_microblaze/bootm.c @@ -67,15 +67,11 @@ void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], (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; } diff --git a/lib_mips/bootm.c b/lib_mips/bootm.c index 5c46a5a..53e8e19 100644 --- a/lib_mips/bootm.c +++ b/lib_mips/bootm.c @@ -120,9 +120,6 @@ void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], linux_env_set("eth1addr", cp); } - if (!images->autostart) - return ; - /* we assume that the kernel is in place */ printf ("\nStarting kernel ...\n\n"); @@ -131,8 +128,7 @@ void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], return; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); return; } diff --git a/lib_nios2/bootm.c b/lib_nios2/bootm.c index 01f4e87..18cf773 100644 --- a/lib_nios2/bootm.c +++ b/lib_nios2/bootm.c @@ -50,9 +50,6 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } void (*kernel)(void) = (void (*)(void))ep; - if (!images->autostart) - return ; - /* For now we assume the Microtronix linux ... which only * needs to be called ;-) */ @@ -61,7 +58,6 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); return; } diff --git a/lib_ppc/bat_rw.c b/lib_ppc/bat_rw.c index 8546333..a40b377 100644 --- a/lib_ppc/bat_rw.c +++ b/lib_ppc/bat_rw.c @@ -25,9 +25,12 @@ #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); @@ -99,6 +102,9 @@ int write_bat (ppc_bat_t bat, unsigned long upper, unsigned long lower) return (-1); } + sync(); + isync(); + return (0); } diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 81803dd..cbe5592 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -277,8 +277,6 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #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 */ @@ -311,8 +309,7 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return ; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); return ; } diff --git a/lib_ppc/time.c b/lib_ppc/time.c index 2649d5f..f093a57 100644 --- a/lib_ppc/time.c +++ b/lib_ppc/time.c @@ -67,7 +67,7 @@ void udelay(unsigned long usec) } /* ------------------------------------------------------------------------- */ - +#ifndef CONFIG_NAND_SPL unsigned long ticks2usec(unsigned long ticks) { ulong tbclk = get_tbclk(); @@ -83,7 +83,7 @@ unsigned long ticks2usec(unsigned long ticks) return ((ulong)ticks); } - +#endif /* ------------------------------------------------------------------------- */ int init_timebase (void) diff --git a/lib_sh/bootm.c b/lib_sh/bootm.c index dd32a3e..4ee7ff3 100644 --- a/lib_sh/bootm.c +++ b/lib_sh/bootm.c @@ -83,9 +83,6 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } void (*kernel) (void) = (void (*)(void))ep; - if (!images->autostart) - return ; - /* Setup parameters */ memset(PARAM, 0, 0x1000); /* Clear zero page */ strcpy(COMMAND_LINE, bootargs); @@ -95,7 +92,6 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return; error: - if (images->autostart) - do_reset (cmdtp, flag, argc, argv); + do_reset (cmdtp, flag, argc, argv); return; } diff --git a/lib_sparc/bootm.c b/lib_sparc/bootm.c index 8900b2e..b1a3d98 100644 --- a/lib_sparc/bootm.c +++ b/lib_sparc/bootm.c @@ -204,9 +204,6 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], 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); @@ -220,7 +217,6 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], while (1) ; error: - if (images->autostart) - do_reset(cmdtp, flag, argc, argv); + do_reset(cmdtp, flag, argc, argv); return; } diff --git a/nand_spl/board/freescale/mpc8313erdb/Makefile b/nand_spl/board/freescale/mpc8313erdb/Makefile new file mode 100644 index 0000000..3da1b1f --- /dev/null +++ b/nand_spl/board/freescale/mpc8313erdb/Makefile @@ -0,0 +1,101 @@ +# +# (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 + +######################################################################### diff --git a/nand_spl/board/freescale/mpc8313erdb/u-boot.lds b/nand_spl/board/freescale/mpc8313erdb/u-boot.lds new file mode 100644 index 0000000..40c4145 --- /dev/null +++ b/nand_spl/board/freescale/mpc8313erdb/u-boot.lds @@ -0,0 +1,52 @@ +/* + * (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"); diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c index 563a80b..16d128f 100644 --- a/nand_spl/nand_boot.c +++ b/nand_spl/nand_boot.c @@ -20,6 +20,7 @@ #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; } @@ -38,32 +39,31 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 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; @@ -76,51 +76,45 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 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; @@ -137,7 +131,7 @@ static int nand_is_bad_block(struct mtd_info *mtd, int block) /* * Read one byte */ - if (this->read_byte(mtd) != 0xff) + if (readb(this->IO_ADDR_R) != 0xff) return 1; return 0; @@ -166,9 +160,9 @@ static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst) 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); @@ -184,35 +178,39 @@ static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst) * 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++; @@ -231,7 +229,7 @@ void nand_boot(void) 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 @@ -241,15 +239,21 @@ void nand_boot(void) 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)(); } diff --git a/nand_spl/nand_boot_fsl_elbc.c b/nand_spl/nand_boot_fsl_elbc.c new file mode 100644 index 0000000..0d2378e --- /dev/null +++ b/nand_spl/nand_boot_fsl_elbc.c @@ -0,0 +1,150 @@ +/* + * 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(); +} |