Nand flash driver for bcm47xx wnr3500lv2

I've decided to pause this project as I can't figure out why reads keep getting corrupted with my ported driver.
I've put up my work at https://github.com/ErikAndren/linux-kernel-wnr3500lv2-nand

Feel free to pick up the work if anyone is interested.
I'll try to help out best as I can.

thank you very much. good job.
we will continue to work on it. It's very difficult for me

I'm trying a new strategy: first boot on a USB drive, then have an easier development on the nand driver with access to the serial consol and possibility to insmod and rmmod very fast and do other tests.

As the current kernel does not power up USB host I've soldered this wire to power up my usb drive:

3500lv2
3500lv22

I now need to reconfigure a good kernel with USB drive suport, ext4 support, rootwait and root=/dev/sda. And get my hands back on tftp.

This will also have the advantage to be able to see if the wifi driver works or not before we go any further.

I can confirm that it's possible to boot openwrt on a USB drive with this soldering trick! And I can confirm that by default wifi does not work:

BusyBox v1.28.3 () built-in shell (ash)

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 OpenWrt 18.06.1, r7258-5eb055306f
 -----------------------------------------------------
=== WARNING! =====================================
There is no root password defined on this device!
Use the "passwd" command to set up a new password
in order to prevent unauthorized SSH logins.
--------------------------------------------------
root@OpenWrt:/# 
root@OpenWrt:/# 
root@OpenWrt:/# ifconfig -a
br-lan    Link encap:Ethernet  HWaddr 00:90:4C:01:E0:01  
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fdc0:54f5:3dad::1/60 Scope:Global
          inet6 addr: fe80::290:4cff:fe01:e001/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:1414 (1.3 KiB)

eth0      Link encap:Ethernet  HWaddr 00:90:4C:01:E0:01  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:10 errors:0 dropped:0 overruns:0 frame:0
          TX packets:15 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1152 (1.1 KiB)  TX bytes:1930 (1.8 KiB)
          Interrupt:4 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:64 errors:0 dropped:0 overruns:0 frame:0
          TX packets:64 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4352 (4.2 KiB)  TX bytes:4352 (4.2 KiB)

On the other hand the Ethernet/switch networking works correctly:

port 8 is the router, port 0 is wan, and port 1-4 are lan.

Hello,

I have spent some time making the WNR5300LV2 work with @a.limousin.

Since the DD-WRT version is (partialy) working I started from there. The Idea was to use the DD-WRT's 3.10 Kernel withing the build of the last OpenWRT.

Once the external kernel build succeed, the nand support has been tested by loading the system with an initrd in order to have common tools: ash, network support. On this first step the nandflash driver has been tested.

Some configuration after, OpenWRT did boot the nand over the squashfs generated, on this step I have been able to check the full support for Network, Wifi, LED.

To go further, I needed to have a the ability to store the configuration. I patched the kernel 3.10 with overlayfs and rename the MTD partition accordingly in order to have the overlay partition configure at startup.

At this point the system was stable but the write partition still was on tmpfs. The nandflash driver do not manage the OOB metadata require to have a jffs2 partition on the NAND for the overlayfs.

Since then I have been looking the brcmnand_47xx.c driver, that was not working for read.
I finally found something that make the driver working:

diff --git a/src/linux/universal/linux-3.10/drivers/mtd/bcm947xx/nand/brcmnand_47xx.c b/src/linux/universal/linux-3.10/drivers/mtd/bcm947xx/nand/brcmnand_47xx.c
index 996dbf0..7538051 100644
--- a/src/linux/universal/linux-3.10/drivers/mtd/bcm947xx/nand/brcmnand_47xx.c
+++ b/src/linux/universal/linux-3.10/drivers/mtd/bcm947xx/nand/brcmnand_47xx.c
@@ -783,7 +785,7 @@ brcmnand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_c
 
        ret = brcmnand_do_read_ops(mtd, from, &chip->ops);
 
-       *retlen = ops.retlen;
+       *retlen = chip->ops.retlen;
 
        brcmnand_release_device(mtd);

After that I have been able to create a partition on the brcmnand driver in order to have the rootfs_data with OOB and jffs2.

For now I am stuck with this issue : JFFS2 driver writes some information on the OOB, like the magic bitmask: 0x19 0x85, but they do not appear on the nand data itself. Unfortunately the mount_root binary is looking for the magic bitmask on the data.

In order to try a bit further, I tweaked the mount_root binary to accept 0xFFFFFFFF data as JFFS2, This has given some result for testing but it is not stable as the JFFS2 gets CRC errors, and sometime goes on infinite loop and the board reboot.

[   14.870000] jffs2: error: (807) jffs2_do_read_inode_internal: CRC failed for read_inode of inode 120 at physical 0
[   14.880000] jffs2: Returned error for crccheck of ino #120. Expect badness...

I am missing some knowledge on OOB NAND driver and JFFS2. The firmware from netgear has a JFFS2 partition when I boot from it, so there must be something missing somewhere.

This is a small summary, I can give more details, just ask.

Regards,

@leo5593
Thank's

Ok so if I understand you well you try to run a dd-wrt kernel with an openwrt filesystem, and did not try to port drivers to openwrt kernel as we attempted before? This will probably bring some issues, won't it?

Hi,

To be precise, I build the 3.10 kernel within the make of the openwrt image.
I did had some build issues that were corrected.
The nand filesystem apart, the system is working well with this configuration, network and wifi.

@leo5593

Thank's a lot for your replies!

What do you call "the 3.10 kernel"? Do you mean kernel comming from dd-wrt source tree?

Which openwrt filesystem did you use? BarrierBreaker (14.04) was based on 3.10, but It's starting to be pretty old.

Yes the kernel from DD-WRT with the latest version of OpenWRT : 18.06

From the previous post :

The Idea was to use the DD-WRT's 3.10 Kernel within the build of the last OpenWRT

OK sorry about that, I read too fast.
No sure if it is feasible to get a fully working openwrt 18.06 with and old kernel like 3.10 ?

FWIW, I am picking up here and will see about getting brcmnand to work on the WNR3500L v2 (47186 SoC), once there is progress I will get it committed to OpenWrt directly for others to use.

3 Likes

So far I have been able to get the upstream brcmnand driver to probe, recognize the NAND chip, scan for bad blocks and get me to an initramfs prompt where I can try to read/write to/from the device.

One thing that I have not been able to figure out yet is how we are supposed to read out of the NAND cache. The BCMA_CC_NAND_CACHE_DATA acts as a FIFO whereby every time you read from it, it pops 4 bytes out of the cache, and so on and so forth. Conversely BCMA_CC_NAND_CACHE_ADDR gets incremented by 4 every time a read of BCMA_CC_NAND_CACHE_ADDR happens.

The code can be found here for others to try:

Here is an example of what this gives me, the same data gets repeated 4 times, it is possible that we are not properly selecting the NAND address to read from, which would also explain why were are not able to read the ONFI parameter page from this chip but instead we fallback to the classic ID based decoding.

root@(none):/# hexdump -C /tmp/flash.bin
00000000  67 70 6f 31 3d 30 78 35  35 35 35 00 73 62 2f 31  |gpo1=0x5555.sb/1|
00000010  2f 6d 63 73 32 67 70 6f  32 3d 30 78 35 35 35 35  |/mcs2gpo2=0x5555|
00000020  00 73 62 2f 31 2f 6d 63  73 32 67 70 6f 33 3d 30  |.sb/1/mcs2gpo3=0|
00000030  78 35 35 35 35 00 73 62  2f 31 2f 6d 63 73 32 67  |x5555.sb/1/mcs2g|
00000040  70 6f 34 3d 30 78 37 37  37 37 00 73 62 2f 31 2f  |po4=0x7777.sb/1/|
00000050  6d 63 73 32 67 70 6f 35  3d 30 78 37 37 37 37 00  |mcs2gpo5=0x7777.|
00000060  73 62 2f 31 2f 6d 63 73  32 67 70 6f 36 3d 30 78  |sb/1/mcs2gpo6=0x|
00000070  37 37 37 37 00 73 62 2f  31 2f 6d 63 73 32 67 70  |7777.sb/1/mcs2gp|
00000080  6f 37 3d 30 78 37 37 37  37 00 73 62 2f 31 2f 63  |o7=0x7777.sb/1/c|
00000090  64 64 70 6f 3d 30 78 30  00 73 62 2f 31 2f 73 74  |ddpo=0x0.sb/1/st|
000000a0  62 63 70 6f 3d 30 78 30  00 73 62 2f 31 2f 62 77  |bcpo=0x0.sb/1/bw|
000000b0  34 30 70 6f 3d 30 78 30  00 73 62 2f 31 2f 62 77  |40po=0x0.sb/1/bw|
000000c0  64 75 70 70 6f 3d 30 78  30 00 73 62 2f 31 2f 63  |duppo=0x0.sb/1/c|
000000d0  63 6f 64 65 3d 30 00 73  62 2f 31 2f 72 65 67 72  |code=0.sb/1/regr|
000000e0  65 76 3d 30 00 73 62 2f  31 2f 6c 65 64 62 68 30  |ev=0.sb/1/ledbh0|
000000f0  3d 30 78 38 32 00 73 62  2f 31 2f 6c 65 64 62 68  |=0x82.sb/1/ledbh|
00000100  31 3d 31 31 00 73 62 2f  31 2f 6c 65 64 62 68 32  |1=11.sb/1/ledbh2|
00000110  3d 31 31 00 73 62 2f 31  2f 6c 65 64 62 68 33 3d  |=11.sb/1/ledbh3=|
00000120  31 31 00 73 62 2f 31 2f  6c 65 64 64 63 3d 30 78  |11.sb/1/leddc=0x|
00000130  66 66 66 66 00 62 6f 6f  74 5f 77 61 69 74 3d 6f  |ffff.boot_wait=o|
00000140  66 66 00 77 61 69 74 5f  74 69 6d 65 3d 33 00 72  |ff.wait_time=3.r|
00000150  65 73 65 74 5f 67 70 69  6f 3d 34 00 67 70 69 6f  |eset_gpio=4.gpio|
00000160  35 3d 72 6f 62 6f 5f 72  65 73 65 74 00 77 61 74  |5=robo_reset.wat|
00000170  63 68 64 6f 67 3d 33 30  30 30 00 73 62 2f 31 2f  |chdog=3000.sb/1/|
00000180  74 65 6d 70 73 5f 70 65  72 69 6f 64 3d 35 00 73  |temps_period=5.s|
00000190  62 2f 31 2f 74 65 6d 70  74 68 72 65 73 68 3d 31  |b/1/tempthresh=1|
000001a0  32 30 00 73 62 2f 31 2f  74 65 6d 70 73 5f 68 79  |20.sb/1/temps_hy|
000001b0  73 74 65 72 65 73 69 73  3d 35 00 77 6c 5f 6d 73  |steresis=5.wl_ms|
000001c0  67 6c 65 76 65 6c 3d 30  78 31 00 00 00 00 00 00  |glevel=0x1......|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200  67 70 6f 31 3d 30 78 35  35 35 35 00 73 62 2f 31  |gpo1=0x5555.sb/1|
00000210  2f 6d 63 73 32 67 70 6f  32 3d 30 78 35 35 35 35  |/mcs2gpo2=0x5555|
00000220  00 73 62 2f 31 2f 6d 63  73 32 67 70 6f 33 3d 30  |.sb/1/mcs2gpo3=0|
00000230  78 35 35 35 35 00 73 62  2f 31 2f 6d 63 73 32 67  |x5555.sb/1/mcs2g|
00000240  70 6f 34 3d 30 78 37 37  37 37 00 73 62 2f 31 2f  |po4=0x7777.sb/1/|
00000250  6d 63 73 32 67 70 6f 35  3d 30 78 37 37 37 37 00  |mcs2gpo5=0x7777.|
00000260  73 62 2f 31 2f 6d 63 73  32 67 70 6f 36 3d 30 78  |sb/1/mcs2gpo6=0x|
00000270  37 37 37 37 00 73 62 2f  31 2f 6d 63 73 32 67 70  |7777.sb/1/mcs2gp|
00000280  6f 37 3d 30 78 37 37 37  37 00 73 62 2f 31 2f 63  |o7=0x7777.sb/1/c|
00000290  64 64 70 6f 3d 30 78 30  00 73 62 2f 31 2f 73 74  |ddpo=0x0.sb/1/st|
000002a0  62 63 70 6f 3d 30 78 30  00 73 62 2f 31 2f 62 77  |bcpo=0x0.sb/1/bw|
000002b0  34 30 70 6f 3d 30 78 30  00 73 62 2f 31 2f 62 77  |40po=0x0.sb/1/bw|
000002c0  64 75 70 70 6f 3d 30 78  30 00 73 62 2f 31 2f 63  |duppo=0x0.sb/1/c|
000002d0  63 6f 64 65 3d 30 00 73  62 2f 31 2f 72 65 67 72  |code=0.sb/1/regr|
000002e0  65 76 3d 30 00 73 62 2f  31 2f 6c 65 64 62 68 30  |ev=0.sb/1/ledbh0|
000002f0  3d 30 78 38 32 00 73 62  2f 31 2f 6c 65 64 62 68  |=0x82.sb/1/ledbh|
00000300  31 3d 31 31 00 73 62 2f  31 2f 6c 65 64 62 68 32  |1=11.sb/1/ledbh2|
00000310  3d 31 31 00 73 62 2f 31  2f 6c 65 64 62 68 33 3d  |=11.sb/1/ledbh3=|
00000320  31 31 00 73 62 2f 31 2f  6c 65 64 64 63 3d 30 78  |11.sb/1/leddc=0x|
00000330  66 66 66 66 00 62 6f 6f  74 5f 77 61 69 74 3d 6f  |ffff.boot_wait=o|
00000340  66 66 00 77 61 69 74 5f  74 69 6d 65 3d 33 00 72  |ff.wait_time=3.r|
00000350  65 73 65 74 5f 67 70 69  6f 3d 34 00 67 70 69 6f  |eset_gpio=4.gpio|
00000360  35 3d 72 6f 62 6f 5f 72  65 73 65 74 00 77 61 74  |5=robo_reset.wat|
00000370  63 68 64 6f 67 3d 33 30  30 30 00 73 62 2f 31 2f  |chdog=3000.sb/1/|
00000380  74 65 6d 70 73 5f 70 65  72 69 6f 64 3d 35 00 73  |temps_period=5.s|
00000390  62 2f 31 2f 74 65 6d 70  74 68 72 65 73 68 3d 31  |b/1/tempthresh=1|
000003a0  32 30 00 73 62 2f 31 2f  74 65 6d 70 73 5f 68 79  |20.sb/1/temps_hy|
000003b0  73 74 65 72 65 73 69 73  3d 35 00 77 6c 5f 6d 73  |steresis=5.wl_ms|
000003c0  67 6c 65 76 65 6c 3d 30  78 31 00 00 00 00 00 00  |glevel=0x1......|
000003d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

Thank you so much for your work!

Helllo,

It has been a while, but form what I remember, I was stuck with the usage of ubifs. The nand was accessible but the ubi driver in order to manage wear leveling and bad bloc had something missing in the driver. It was with the 3.10 kernel from DD-WRT and the file system was not use on this platform.

I might dig up the router form the closet and give it an other try.

Regards,

I found the problem to be that the command register where the command value must be written is not left shifted by 24 like what brcmnand.c currently does in brcmnand_cmd_shift() but instead requires no shifting. This is a departure from Broadcom STB chips that do require that command shifting. After removing the shifting for the 3.4 controller, I was able to read from flash correctly and confirmed that the md5sum of all partitions using the stock firmware produce the same md5sum when read using the branch posted above.

Now it's time to see if the bcm47xxpart partition parser will pick up the partitions.

Now putting together a branch against OpenWrt's trunk for a working image using squashfs+jffs2, supporting LEDs and buttons.

2 Likes

Amazing, thank's so much, for your talent! :slight_smile:
We all failed at this, but you didn't!

Thanks! Here is the pull request:

the only thing I have not figured out is whether there is a GPIO to enable/disable the USB port, using GPIO12 (same as WNR3500LV1) does not appear to make it work, but maybe there is some additional USB PHY initialization that we are missing.

1 Like

Small off topic, if I may: do you confirm that unfortunatly there is still no solution ahead for wifi driver? (Which would make the device fully usable).