[U-Boot] [PATCH v2 1/2] i.MX6: nand: extend nandbcb command for imx6UL(L)

Firmware Configuration Block(FCB) for imx6ul(l) needs to be BCH encoded. This patch depends on [1].
[1]: https://patchwork.ozlabs.org/project/uboot/list/?series=113810
Signed-off-by: Parthiban Nallathambi pn@denx.de Acked-by: Shyam Saini shyam.saini@amarulasolutions.com ---
Notes: Changes in v2: - use kfree instead of free
arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/cmd_nandbcb.c | 72 ++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index aeb5493488..175bed601e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -74,6 +74,7 @@ config CMD_HDMIDETECT config CMD_NANDBCB bool "i.MX6 NAND Boot Control Block(BCB) command" depends on NAND && CMD_MTDPARTS + select BCH if MX6UL || MX6ULL default y if ARCH_MX6 && NAND_MXS help Unlike normal 'nand write/erase' commands, this command update diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c index 065b814b2e..e11df401e4 100644 --- a/arch/arm/mach-imx/cmd_nandbcb.c +++ b/arch/arm/mach-imx/cmd_nandbcb.c @@ -14,8 +14,10 @@
#include <asm/io.h> #include <jffs2/jffs2.h> +#include <linux/bch.h> #include <linux/mtd/mtd.h>
+#include <asm/arch/sys_proto.h> #include <asm/mach-imx/imx-nandbcb.h> #include <asm/mach-imx/imximage.cfg> #include <mxs_nand.h> @@ -25,6 +27,66 @@ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET) #define GETBIT(v, n) (((v) >> (n)) & 0x1)
+static uint8_t reverse_bit(uint8_t b) +{ + b = (b & 0xf0) >> 4 | (b & 0x0f) << 4; + b = (b & 0xcc) >> 2 | (b & 0x33) << 2; + b = (b & 0xaa) >> 1 | (b & 0x55) << 1; + + return b; +} + +static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int eccbits) +{ + int i, j, m = 13; + int blocksize = 128; + int numblocks = 8; + int ecc_buf_size = (m * eccbits + 7) / 8; + struct bch_control *bch = init_bch(m, eccbits, 0); + u8 *ecc_buf = kzalloc(ecc_buf_size, GFP_KERNEL); + u8 *tmp_buf = kzalloc(blocksize * numblocks, GFP_KERNEL); + u8 *psrc, *pdst; + + /* + * The blocks here are bit aligned. If eccbits is a multiple of 8, + * we just can copy bytes. Otherwiese we must move the blocks to + * the next free bit position. + */ + WARN_ON(eccbits % 8); + + memcpy(tmp_buf, fcb, sizeof(*fcb)); + + for (i = 0; i < numblocks; i++) { + memset(ecc_buf, 0, ecc_buf_size); + psrc = tmp_buf + i * blocksize; + pdst = buf + i * (blocksize + ecc_buf_size); + + /* copy data byte aligned to destination buf */ + memcpy(pdst, psrc, blocksize); + + /* + * imx-kobs use a modified encode_bch which reverse the + * bit order of the data before calculating bch. + * Do this in the buffer and use the bch lib here. + */ + for (j = 0; j < blocksize; j++) + psrc[j] = reverse_bit(psrc[j]); + + encode_bch(bch, psrc, blocksize, ecc_buf); + + /* reverse ecc bit */ + for (j = 0; j < ecc_buf_size; j++) + ecc_buf[j] = reverse_bit(ecc_buf[j]); + + /* Here eccbuf is byte aligned and we can just copy it */ + memcpy(pdst + blocksize, ecc_buf, ecc_buf_size); + } + + kfree(ecc_buf); + kfree(tmp_buf); + free_bch(bch); +} + static u8 calculate_parity_13_8(u8 d) { u8 p = 0; @@ -231,8 +293,14 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size, goto dbbt_data_page_err; }
- memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block)); - encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512); + if (is_mx6ul() || is_mx6ull()) { + /* 40 bit BCH, for i.MX6UL(L) */ + encode_bch_ecc(fcb_raw_page + 32, fcb, 40); + } else { + memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block)); + encode_hamming_13_8(fcb_raw_page + 12, + fcb_raw_page + 12 + 512, 512); + } /* * Set the first and second byte of OOB data to 0xFF, not 0x00. These * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since

Booting from NAND needs nandbcb and nand boot device selection
Signed-off-by: Parthiban Nallathambi pn@denx.de ---
Notes: Changes in v2: - None
board/phytec/pcl063/spl.c | 3 +++ configs/phycore_pcl063_defconfig | 1 + 2 files changed, 4 insertions(+)
diff --git a/board/phytec/pcl063/spl.c b/board/phytec/pcl063/spl.c index 6d4c827918..358156bfbc 100644 --- a/board/phytec/pcl063/spl.c +++ b/board/phytec/pcl063/spl.c @@ -197,6 +197,9 @@ void board_boot_order(u32 *spl_boot_list) case IMX6_BMODE_EMMC: boot_dev = BOOT_DEVICE_MMC2; break; + case IMX6_BMODE_NAND_MIN ... IMX6_BMODE_NAND_MAX: + boot_dev = BOOT_DEVICE_NAND; + break; default: /* Default - BOOT_DEVICE_MMC1 */ printf("Wrong board boot order\n"); diff --git a/configs/phycore_pcl063_defconfig b/configs/phycore_pcl063_defconfig index cf43b43924..c55670a8ff 100644 --- a/configs/phycore_pcl063_defconfig +++ b/configs/phycore_pcl063_defconfig @@ -27,6 +27,7 @@ CONFIG_CMD_MTD=y CONFIG_CMD_USB=y CONFIG_CMD_USB_SDP=y CONFIG_CMD_CACHE=y +CONFIG_CMD_NANDBCB=y CONFIG_MTDIDS_DEFAULT="nand0=gpmi-nand" CONFIG_MTDPARTS_DEFAULT="gpmi-nand:4m(uboot),1m(env),-(root)" CONFIG_CMD_UBI=y

Subject: [PATCH v2 2/2] imx: pcl063: add nand boot support
Booting from NAND needs nandbcb and nand boot device selection
Signed-off-by: Parthiban Nallathambi pn@denx.de
Notes: Changes in v2: - None
board/phytec/pcl063/spl.c | 3 +++ configs/phycore_pcl063_defconfig | 1 + 2 files changed, 4 insertions(+)
diff --git a/board/phytec/pcl063/spl.c b/board/phytec/pcl063/spl.c index 6d4c827918..358156bfbc 100644 --- a/board/phytec/pcl063/spl.c +++ b/board/phytec/pcl063/spl.c @@ -197,6 +197,9 @@ void board_boot_order(u32 *spl_boot_list) case IMX6_BMODE_EMMC: boot_dev = BOOT_DEVICE_MMC2; break;
- case IMX6_BMODE_NAND_MIN ... IMX6_BMODE_NAND_MAX:
boot_dev = BOOT_DEVICE_NAND;
default: /* Default - BOOT_DEVICE_MMC1 */ printf("Wrong board boot order\n");break;
diff --git a/configs/phycore_pcl063_defconfig b/configs/phycore_pcl063_defconfig index cf43b43924..c55670a8ff 100644 --- a/configs/phycore_pcl063_defconfig +++ b/configs/phycore_pcl063_defconfig @@ -27,6 +27,7 @@ CONFIG_CMD_MTD=y CONFIG_CMD_USB=y CONFIG_CMD_USB_SDP=y CONFIG_CMD_CACHE=y +CONFIG_CMD_NANDBCB=y CONFIG_MTDIDS_DEFAULT="nand0=gpmi-nand" CONFIG_MTDPARTS_DEFAULT="gpmi-nand:4m(uboot),1m(env),-(root)" CONFIG_CMD_UBI=y
Reviewed-by: Peng Fan peng.fan@nxp.com
-- 2.21.0

Subject: [PATCH v2 1/2] i.MX6: nand: extend nandbcb command for imx6UL(L)
Firmware Configuration Block(FCB) for imx6ul(l) needs to be BCH encoded. This patch depends on [1].
work.ozlabs.org%2Fproject%2Fuboot%2Flist%2F%3Fseries%3D113810& data=02%7C01%7Cpeng.fan%40nxp.com%7Cd3b7409c0d254724d28508d727 e5c283%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637021740 084139651&sdata=SxaieXR9bG3ChctaPrpYBI6yqXOD6blKSu6tjP0qccE%3 D&reserved=0
Signed-off-by: Parthiban Nallathambi pn@denx.de Acked-by: Shyam Saini shyam.saini@amarulasolutions.com
Acked-by: Peng Fan peng.fan@nxp.com
Notes: Changes in v2: - use kfree instead of free
arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/cmd_nandbcb.c | 72 ++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index aeb5493488..175bed601e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -74,6 +74,7 @@ config CMD_HDMIDETECT config CMD_NANDBCB bool "i.MX6 NAND Boot Control Block(BCB) command" depends on NAND && CMD_MTDPARTS
- select BCH if MX6UL || MX6ULL default y if ARCH_MX6 && NAND_MXS help Unlike normal 'nand write/erase' commands, this command update
diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c index 065b814b2e..e11df401e4 100644 --- a/arch/arm/mach-imx/cmd_nandbcb.c +++ b/arch/arm/mach-imx/cmd_nandbcb.c @@ -14,8 +14,10 @@
#include <asm/io.h> #include <jffs2/jffs2.h> +#include <linux/bch.h> #include <linux/mtd/mtd.h>
+#include <asm/arch/sys_proto.h> #include <asm/mach-imx/imx-nandbcb.h> #include <asm/mach-imx/imximage.cfg> #include <mxs_nand.h> @@ -25,6 +27,66 @@ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET) #define GETBIT(v, n) (((v) >> (n)) & 0x1)
+static uint8_t reverse_bit(uint8_t b) +{
- b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
- b = (b & 0xcc) >> 2 | (b & 0x33) << 2;
- b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
- return b;
+}
+static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int +eccbits) {
- int i, j, m = 13;
- int blocksize = 128;
- int numblocks = 8;
- int ecc_buf_size = (m * eccbits + 7) / 8;
- struct bch_control *bch = init_bch(m, eccbits, 0);
- u8 *ecc_buf = kzalloc(ecc_buf_size, GFP_KERNEL);
- u8 *tmp_buf = kzalloc(blocksize * numblocks, GFP_KERNEL);
- u8 *psrc, *pdst;
- /*
* The blocks here are bit aligned. If eccbits is a multiple of 8,
* we just can copy bytes. Otherwiese we must move the blocks to
* the next free bit position.
*/
- WARN_ON(eccbits % 8);
- memcpy(tmp_buf, fcb, sizeof(*fcb));
- for (i = 0; i < numblocks; i++) {
memset(ecc_buf, 0, ecc_buf_size);
psrc = tmp_buf + i * blocksize;
pdst = buf + i * (blocksize + ecc_buf_size);
/* copy data byte aligned to destination buf */
memcpy(pdst, psrc, blocksize);
/*
* imx-kobs use a modified encode_bch which reverse the
* bit order of the data before calculating bch.
* Do this in the buffer and use the bch lib here.
*/
for (j = 0; j < blocksize; j++)
psrc[j] = reverse_bit(psrc[j]);
encode_bch(bch, psrc, blocksize, ecc_buf);
/* reverse ecc bit */
for (j = 0; j < ecc_buf_size; j++)
ecc_buf[j] = reverse_bit(ecc_buf[j]);
/* Here eccbuf is byte aligned and we can just copy it */
memcpy(pdst + blocksize, ecc_buf, ecc_buf_size);
- }
- kfree(ecc_buf);
- kfree(tmp_buf);
- free_bch(bch);
+}
static u8 calculate_parity_13_8(u8 d) { u8 p = 0; @@ -231,8 +293,14 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size, goto dbbt_data_page_err; }
- memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
- encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512,
512);
- if (is_mx6ul() || is_mx6ull()) {
/* 40 bit BCH, for i.MX6UL(L) */
encode_bch_ecc(fcb_raw_page + 32, fcb, 40);
- } else {
memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
encode_hamming_13_8(fcb_raw_page + 12,
fcb_raw_page + 12 + 512, 512);
- } /*
- Set the first and second byte of OOB data to 0xFF, not 0x00. These
- bytes are used as the Manufacturers Bad Block Marker (MBBM).
Since
2.21.0

Hi Parthiban,
On 23/08/19 18:19, Parthiban Nallathambi wrote:
Firmware Configuration Block(FCB) for imx6ul(l) needs to be BCH encoded. This patch depends on [1].
Why does it depend on this if it is just defoconfig for a board ?
Signed-off-by: Parthiban Nallathambi pn@denx.de Acked-by: Shyam Saini shyam.saini@amarulasolutions.com
Notes: Changes in v2: - use kfree instead of free
arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/cmd_nandbcb.c | 72 ++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index aeb5493488..175bed601e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -74,6 +74,7 @@ config CMD_HDMIDETECT config CMD_NANDBCB bool "i.MX6 NAND Boot Control Block(BCB) command" depends on NAND && CMD_MTDPARTS
- select BCH if MX6UL || MX6ULL
This eems to break all i.MX6 boards (not UL(L)) using NAND. In fact, I get these errors:
Building current source for 1 boards (1 thread, 8 jobs per thread) arm: + pfla02 +arch/arm/mach-imx/built-in.o: In function `encode_bch_ecc': +arch/arm/mach-imx/cmd_nandbcb.c:45: undefined reference to `init_bch' +arch/arm/mach-imx/cmd_nandbcb.c:75: undefined reference to `encode_bch' +arch/arm/mach-imx/cmd_nandbcb.c:87: undefined reference to `free_bch' +arm-poky-linux-gnueabi-ld.bfd: BFD (GNU Binutils) 2.28.0.20170307 assertion fail ../../bfd/elf32-arm.c:9512 +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 0 0 1 /1 pfla02
Can you check this please ? I temporary remove the patch from -next branch.
Best regards, Stefano Babic
default y if ARCH_MX6 && NAND_MXS help Unlike normal 'nand write/erase' commands, this command update diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c index 065b814b2e..e11df401e4 100644 --- a/arch/arm/mach-imx/cmd_nandbcb.c +++ b/arch/arm/mach-imx/cmd_nandbcb.c @@ -14,8 +14,10 @@
#include <asm/io.h> #include <jffs2/jffs2.h> +#include <linux/bch.h> #include <linux/mtd/mtd.h>
+#include <asm/arch/sys_proto.h> #include <asm/mach-imx/imx-nandbcb.h> #include <asm/mach-imx/imximage.cfg> #include <mxs_nand.h> @@ -25,6 +27,66 @@ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET) #define GETBIT(v, n) (((v) >> (n)) & 0x1)
+static uint8_t reverse_bit(uint8_t b) +{
- b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
- b = (b & 0xcc) >> 2 | (b & 0x33) << 2;
- b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
- return b;
+}
+static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int eccbits) +{
- int i, j, m = 13;
- int blocksize = 128;
- int numblocks = 8;
- int ecc_buf_size = (m * eccbits + 7) / 8;
- struct bch_control *bch = init_bch(m, eccbits, 0);
- u8 *ecc_buf = kzalloc(ecc_buf_size, GFP_KERNEL);
- u8 *tmp_buf = kzalloc(blocksize * numblocks, GFP_KERNEL);
- u8 *psrc, *pdst;
- /*
* The blocks here are bit aligned. If eccbits is a multiple of 8,
* we just can copy bytes. Otherwiese we must move the blocks to
* the next free bit position.
*/
- WARN_ON(eccbits % 8);
- memcpy(tmp_buf, fcb, sizeof(*fcb));
- for (i = 0; i < numblocks; i++) {
memset(ecc_buf, 0, ecc_buf_size);
psrc = tmp_buf + i * blocksize;
pdst = buf + i * (blocksize + ecc_buf_size);
/* copy data byte aligned to destination buf */
memcpy(pdst, psrc, blocksize);
/*
* imx-kobs use a modified encode_bch which reverse the
* bit order of the data before calculating bch.
* Do this in the buffer and use the bch lib here.
*/
for (j = 0; j < blocksize; j++)
psrc[j] = reverse_bit(psrc[j]);
encode_bch(bch, psrc, blocksize, ecc_buf);
/* reverse ecc bit */
for (j = 0; j < ecc_buf_size; j++)
ecc_buf[j] = reverse_bit(ecc_buf[j]);
/* Here eccbuf is byte aligned and we can just copy it */
memcpy(pdst + blocksize, ecc_buf, ecc_buf_size);
- }
- kfree(ecc_buf);
- kfree(tmp_buf);
- free_bch(bch);
+}
static u8 calculate_parity_13_8(u8 d) { u8 p = 0; @@ -231,8 +293,14 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size, goto dbbt_data_page_err; }
- memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
- encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
- if (is_mx6ul() || is_mx6ull()) {
/* 40 bit BCH, for i.MX6UL(L) */
encode_bch_ecc(fcb_raw_page + 32, fcb, 40);
- } else {
memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
encode_hamming_13_8(fcb_raw_page + 12,
fcb_raw_page + 12 + 512, 512);
- } /*
- Set the first and second byte of OOB data to 0xFF, not 0x00. These
- bytes are used as the Manufacturers Bad Block Marker (MBBM). Since

Hi Stefano,
On 10/7/19 6:06 PM, Stefano Babic wrote:
Hi Parthiban,
On 23/08/19 18:19, Parthiban Nallathambi wrote:
Firmware Configuration Block(FCB) for imx6ul(l) needs to be BCH encoded. This patch depends on [1].
Why does it depend on this if it is just defoconfig for a board ?
The patch series was nandbcb inclusion, but this is already merged in u-boot. patchwork query shows only the pending merger now.
As the nandbcb is already in mainline, this patch should apply fine.
Thanks, Parthiban N
Signed-off-by: Parthiban Nallathambi pn@denx.de Acked-by: Shyam Saini shyam.saini@amarulasolutions.com
Notes: Changes in v2: - use kfree instead of free
arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/cmd_nandbcb.c | 72 ++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index aeb5493488..175bed601e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -74,6 +74,7 @@ config CMD_HDMIDETECT config CMD_NANDBCB bool "i.MX6 NAND Boot Control Block(BCB) command" depends on NAND && CMD_MTDPARTS
- select BCH if MX6UL || MX6ULL
This eems to break all i.MX6 boards (not UL(L)) using NAND. In fact, I get these errors:
Building current source for 1 boards (1 thread, 8 jobs per thread) arm: + pfla02 +arch/arm/mach-imx/built-in.o: In function `encode_bch_ecc': +arch/arm/mach-imx/cmd_nandbcb.c:45: undefined reference to `init_bch' +arch/arm/mach-imx/cmd_nandbcb.c:75: undefined reference to `encode_bch' +arch/arm/mach-imx/cmd_nandbcb.c:87: undefined reference to `free_bch' +arm-poky-linux-gnueabi-ld.bfd: BFD (GNU Binutils) 2.28.0.20170307 assertion fail ../../bfd/elf32-arm.c:9512 +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 0 0 1 /1 pfla02
Can you check this please ? I temporary remove the patch from -next branch.
Best regards, Stefano Babic
default y if ARCH_MX6 && NAND_MXS help Unlike normal 'nand write/erase' commands, this command update diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c index 065b814b2e..e11df401e4 100644 --- a/arch/arm/mach-imx/cmd_nandbcb.c +++ b/arch/arm/mach-imx/cmd_nandbcb.c @@ -14,8 +14,10 @@
#include <asm/io.h> #include <jffs2/jffs2.h> +#include <linux/bch.h> #include <linux/mtd/mtd.h>
+#include <asm/arch/sys_proto.h> #include <asm/mach-imx/imx-nandbcb.h> #include <asm/mach-imx/imximage.cfg> #include <mxs_nand.h> @@ -25,6 +27,66 @@ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET) #define GETBIT(v, n) (((v) >> (n)) & 0x1)
+static uint8_t reverse_bit(uint8_t b) +{
- b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
- b = (b & 0xcc) >> 2 | (b & 0x33) << 2;
- b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
- return b;
+}
+static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int eccbits) +{
- int i, j, m = 13;
- int blocksize = 128;
- int numblocks = 8;
- int ecc_buf_size = (m * eccbits + 7) / 8;
- struct bch_control *bch = init_bch(m, eccbits, 0);
- u8 *ecc_buf = kzalloc(ecc_buf_size, GFP_KERNEL);
- u8 *tmp_buf = kzalloc(blocksize * numblocks, GFP_KERNEL);
- u8 *psrc, *pdst;
- /*
* The blocks here are bit aligned. If eccbits is a multiple of 8,
* we just can copy bytes. Otherwiese we must move the blocks to
* the next free bit position.
*/
- WARN_ON(eccbits % 8);
- memcpy(tmp_buf, fcb, sizeof(*fcb));
- for (i = 0; i < numblocks; i++) {
memset(ecc_buf, 0, ecc_buf_size);
psrc = tmp_buf + i * blocksize;
pdst = buf + i * (blocksize + ecc_buf_size);
/* copy data byte aligned to destination buf */
memcpy(pdst, psrc, blocksize);
/*
* imx-kobs use a modified encode_bch which reverse the
* bit order of the data before calculating bch.
* Do this in the buffer and use the bch lib here.
*/
for (j = 0; j < blocksize; j++)
psrc[j] = reverse_bit(psrc[j]);
encode_bch(bch, psrc, blocksize, ecc_buf);
/* reverse ecc bit */
for (j = 0; j < ecc_buf_size; j++)
ecc_buf[j] = reverse_bit(ecc_buf[j]);
/* Here eccbuf is byte aligned and we can just copy it */
memcpy(pdst + blocksize, ecc_buf, ecc_buf_size);
- }
- kfree(ecc_buf);
- kfree(tmp_buf);
- free_bch(bch);
+}
static u8 calculate_parity_13_8(u8 d) { u8 p = 0; @@ -231,8 +293,14 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size, goto dbbt_data_page_err; }
- memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
- encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
- if (is_mx6ul() || is_mx6ull()) {
/* 40 bit BCH, for i.MX6UL(L) */
encode_bch_ecc(fcb_raw_page + 32, fcb, 40);
- } else {
memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
encode_hamming_13_8(fcb_raw_page + 12,
fcb_raw_page + 12 + 512, 512);
- } /*
- Set the first and second byte of OOB data to 0xFF, not 0x00. These
- bytes are used as the Manufacturers Bad Block Marker (MBBM). Since

On 08/10/19 10:12, Parthiban Nallathambi wrote:
Hi Stefano,
On 10/7/19 6:06 PM, Stefano Babic wrote:
Hi Parthiban,
On 23/08/19 18:19, Parthiban Nallathambi wrote:
Firmware Configuration Block(FCB) for imx6ul(l) needs to be BCH encoded. This patch depends on [1].
Why does it depend on this if it is just defoconfig for a board ?
The patch series was nandbcb inclusion, but this is already merged in u-boot. patchwork query shows only the pending merger now.
As the nandbcb is already in mainline, this patch should apply fine.
Please read the whole e-mail. Issue is not that patch cannot be applied, issue is that it breaks several boards. All i.MX6 boards with NAND - check again:
Building current source for 1 boards (1 thread, 8 jobs per thread) arm: + pfla02 +arch/arm/mach-imx/built-in.o: In function `encode_bch_ecc': +arch/arm/mach-imx/cmd_nandbcb.c:45: undefined reference to `init_bch' +arch/arm/mach-imx/cmd_nandbcb.c:75: undefined reference to `encode_bch' +arch/arm/mach-imx/cmd_nandbcb.c:87: undefined reference to `free_bch' +arm-poky-linux-gnueabi-ld.bfd: BFD (GNU Binutils) 2.28.0.20170307 assertion fail ../../bfd/elf32-arm.c:9512 +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 0 0 1 /1 pfla02
The same happens to other boards, too.
Best regards, Stefano Babic
Thanks, Parthiban N
Signed-off-by: Parthiban Nallathambi pn@denx.de Acked-by: Shyam Saini shyam.saini@amarulasolutions.com
Notes: Changes in v2: - use kfree instead of free
arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/cmd_nandbcb.c | 72 ++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index aeb5493488..175bed601e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -74,6 +74,7 @@ config CMD_HDMIDETECT config CMD_NANDBCB bool "i.MX6 NAND Boot Control Block(BCB) command" depends on NAND && CMD_MTDPARTS
- select BCH if MX6UL || MX6ULL
This eems to break all i.MX6 boards (not UL(L)) using NAND. In fact, I get these errors:
Building current source for 1 boards (1 thread, 8 jobs per thread) arm: + pfla02 +arch/arm/mach-imx/built-in.o: In function `encode_bch_ecc': +arch/arm/mach-imx/cmd_nandbcb.c:45: undefined reference to `init_bch' +arch/arm/mach-imx/cmd_nandbcb.c:75: undefined reference to `encode_bch' +arch/arm/mach-imx/cmd_nandbcb.c:87: undefined reference to `free_bch' +arm-poky-linux-gnueabi-ld.bfd: BFD (GNU Binutils) 2.28.0.20170307 assertion fail ../../bfd/elf32-arm.c:9512 +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 0 0 1 /1 pfla02
Can you check this please ? I temporary remove the patch from -next branch.
Best regards, Stefano Babic
default y if ARCH_MX6 && NAND_MXS help Unlike normal 'nand write/erase' commands, this command update diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c index 065b814b2e..e11df401e4 100644 --- a/arch/arm/mach-imx/cmd_nandbcb.c +++ b/arch/arm/mach-imx/cmd_nandbcb.c @@ -14,8 +14,10 @@
#include <asm/io.h> #include <jffs2/jffs2.h> +#include <linux/bch.h> #include <linux/mtd/mtd.h>
+#include <asm/arch/sys_proto.h> #include <asm/mach-imx/imx-nandbcb.h> #include <asm/mach-imx/imximage.cfg> #include <mxs_nand.h> @@ -25,6 +27,66 @@ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET) #define GETBIT(v, n) (((v) >> (n)) & 0x1)
+static uint8_t reverse_bit(uint8_t b) +{
- b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
- b = (b & 0xcc) >> 2 | (b & 0x33) << 2;
- b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
- return b;
+}
+static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int eccbits) +{
- int i, j, m = 13;
- int blocksize = 128;
- int numblocks = 8;
- int ecc_buf_size = (m * eccbits + 7) / 8;
- struct bch_control *bch = init_bch(m, eccbits, 0);
- u8 *ecc_buf = kzalloc(ecc_buf_size, GFP_KERNEL);
- u8 *tmp_buf = kzalloc(blocksize * numblocks, GFP_KERNEL);
- u8 *psrc, *pdst;
- /*
* The blocks here are bit aligned. If eccbits is a multiple of 8,
* we just can copy bytes. Otherwiese we must move the blocks to
* the next free bit position.
*/
- WARN_ON(eccbits % 8);
- memcpy(tmp_buf, fcb, sizeof(*fcb));
- for (i = 0; i < numblocks; i++) {
memset(ecc_buf, 0, ecc_buf_size);
psrc = tmp_buf + i * blocksize;
pdst = buf + i * (blocksize + ecc_buf_size);
/* copy data byte aligned to destination buf */
memcpy(pdst, psrc, blocksize);
/*
* imx-kobs use a modified encode_bch which reverse the
* bit order of the data before calculating bch.
* Do this in the buffer and use the bch lib here.
*/
for (j = 0; j < blocksize; j++)
psrc[j] = reverse_bit(psrc[j]);
encode_bch(bch, psrc, blocksize, ecc_buf);
/* reverse ecc bit */
for (j = 0; j < ecc_buf_size; j++)
ecc_buf[j] = reverse_bit(ecc_buf[j]);
/* Here eccbuf is byte aligned and we can just copy it */
memcpy(pdst + blocksize, ecc_buf, ecc_buf_size);
- }
- kfree(ecc_buf);
- kfree(tmp_buf);
- free_bch(bch);
+}
static u8 calculate_parity_13_8(u8 d) { u8 p = 0; @@ -231,8 +293,14 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size, goto dbbt_data_page_err; }
- memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
- encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
- if (is_mx6ul() || is_mx6ull()) {
/* 40 bit BCH, for i.MX6UL(L) */
encode_bch_ecc(fcb_raw_page + 32, fcb, 40);
- } else {
memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
encode_hamming_13_8(fcb_raw_page + 12,
fcb_raw_page + 12 + 512, 512);
- } /*
- Set the first and second byte of OOB data to 0xFF, not 0x00. These
- bytes are used as the Manufacturers Bad Block Marker (MBBM). Since

Hello Stefano,
On 10/8/19 10:23 AM, Stefano Babic wrote:
On 08/10/19 10:12, Parthiban Nallathambi wrote:
Hi Stefano,
On 10/7/19 6:06 PM, Stefano Babic wrote:
Hi Parthiban,
On 23/08/19 18:19, Parthiban Nallathambi wrote:
Firmware Configuration Block(FCB) for imx6ul(l) needs to be BCH encoded. This patch depends on [1].
Why does it depend on this if it is just defoconfig for a board ?
The patch series was nandbcb inclusion, but this is already merged in u-boot. patchwork query shows only the pending merger now.
As the nandbcb is already in mainline, this patch should apply fine.
Please read the whole e-mail. Issue is not that patch cannot be applied, issue is that it breaks several boards. All i.MX6 boards with NAND - check again:
Building current source for 1 boards (1 thread, 8 jobs per thread) arm: + pfla02 +arch/arm/mach-imx/built-in.o: In function `encode_bch_ecc': +arch/arm/mach-imx/cmd_nandbcb.c:45: undefined reference to `init_bch' +arch/arm/mach-imx/cmd_nandbcb.c:75: undefined reference to `encode_bch' +arch/arm/mach-imx/cmd_nandbcb.c:87: undefined reference to `free_bch' +arm-poky-linux-gnueabi-ld.bfd: BFD (GNU Binutils) 2.28.0.20170307 assertion fail ../../bfd/elf32-arm.c:9512 +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 0 0 1 /1 pfla02
The same happens to other boards, too.
I missed this. Will send v3 with conditionally including BCH in source as well.
Thanks, Parthiban N
Best regards, Stefano Babic
Thanks, Parthiban N
Signed-off-by: Parthiban Nallathambi pn@denx.de Acked-by: Shyam Saini shyam.saini@amarulasolutions.com
Notes: Changes in v2: - use kfree instead of free
arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/cmd_nandbcb.c | 72 ++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index aeb5493488..175bed601e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -74,6 +74,7 @@ config CMD_HDMIDETECT config CMD_NANDBCB bool "i.MX6 NAND Boot Control Block(BCB) command" depends on NAND && CMD_MTDPARTS
- select BCH if MX6UL || MX6ULL
This eems to break all i.MX6 boards (not UL(L)) using NAND. In fact, I get these errors:
Building current source for 1 boards (1 thread, 8 jobs per thread) arm: + pfla02 +arch/arm/mach-imx/built-in.o: In function `encode_bch_ecc': +arch/arm/mach-imx/cmd_nandbcb.c:45: undefined reference to `init_bch' +arch/arm/mach-imx/cmd_nandbcb.c:75: undefined reference to `encode_bch' +arch/arm/mach-imx/cmd_nandbcb.c:87: undefined reference to `free_bch' +arm-poky-linux-gnueabi-ld.bfd: BFD (GNU Binutils) 2.28.0.20170307 assertion fail ../../bfd/elf32-arm.c:9512 +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 0 0 1 /1 pfla02
Can you check this please ? I temporary remove the patch from -next branch.
Best regards, Stefano Babic
default y if ARCH_MX6 && NAND_MXS help Unlike normal 'nand write/erase' commands, this command update diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c index 065b814b2e..e11df401e4 100644 --- a/arch/arm/mach-imx/cmd_nandbcb.c +++ b/arch/arm/mach-imx/cmd_nandbcb.c @@ -14,8 +14,10 @@
#include <asm/io.h> #include <jffs2/jffs2.h> +#include <linux/bch.h> #include <linux/mtd/mtd.h>
+#include <asm/arch/sys_proto.h> #include <asm/mach-imx/imx-nandbcb.h> #include <asm/mach-imx/imximage.cfg> #include <mxs_nand.h> @@ -25,6 +27,66 @@ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET) #define GETBIT(v, n) (((v) >> (n)) & 0x1)
+static uint8_t reverse_bit(uint8_t b) +{
- b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
- b = (b & 0xcc) >> 2 | (b & 0x33) << 2;
- b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
- return b;
+}
+static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int eccbits) +{
- int i, j, m = 13;
- int blocksize = 128;
- int numblocks = 8;
- int ecc_buf_size = (m * eccbits + 7) / 8;
- struct bch_control *bch = init_bch(m, eccbits, 0);
- u8 *ecc_buf = kzalloc(ecc_buf_size, GFP_KERNEL);
- u8 *tmp_buf = kzalloc(blocksize * numblocks, GFP_KERNEL);
- u8 *psrc, *pdst;
- /*
* The blocks here are bit aligned. If eccbits is a multiple of 8,
* we just can copy bytes. Otherwiese we must move the blocks to
* the next free bit position.
*/
- WARN_ON(eccbits % 8);
- memcpy(tmp_buf, fcb, sizeof(*fcb));
- for (i = 0; i < numblocks; i++) {
memset(ecc_buf, 0, ecc_buf_size);
psrc = tmp_buf + i * blocksize;
pdst = buf + i * (blocksize + ecc_buf_size);
/* copy data byte aligned to destination buf */
memcpy(pdst, psrc, blocksize);
/*
* imx-kobs use a modified encode_bch which reverse the
* bit order of the data before calculating bch.
* Do this in the buffer and use the bch lib here.
*/
for (j = 0; j < blocksize; j++)
psrc[j] = reverse_bit(psrc[j]);
encode_bch(bch, psrc, blocksize, ecc_buf);
/* reverse ecc bit */
for (j = 0; j < ecc_buf_size; j++)
ecc_buf[j] = reverse_bit(ecc_buf[j]);
/* Here eccbuf is byte aligned and we can just copy it */
memcpy(pdst + blocksize, ecc_buf, ecc_buf_size);
- }
- kfree(ecc_buf);
- kfree(tmp_buf);
- free_bch(bch);
+}
- static u8 calculate_parity_13_8(u8 d) { u8 p = 0;
@@ -231,8 +293,14 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size, goto dbbt_data_page_err; }
- memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
- encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
- if (is_mx6ul() || is_mx6ull()) {
/* 40 bit BCH, for i.MX6UL(L) */
encode_bch_ecc(fcb_raw_page + 32, fcb, 40);
- } else {
memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
encode_hamming_13_8(fcb_raw_page + 12,
fcb_raw_page + 12 + 512, 512);
- } /*
- Set the first and second byte of OOB data to 0xFF, not 0x00. These
- bytes are used as the Manufacturers Bad Block Marker (MBBM). Since

On 18/10/19 11:43, Parthiban Nallathambi wrote:
Hello Stefano,
On 10/8/19 10:23 AM, Stefano Babic wrote:
On 08/10/19 10:12, Parthiban Nallathambi wrote:
Hi Stefano,
On 10/7/19 6:06 PM, Stefano Babic wrote:
Hi Parthiban,
On 23/08/19 18:19, Parthiban Nallathambi wrote:
Firmware Configuration Block(FCB) for imx6ul(l) needs to be BCH encoded. This patch depends on [1].
Why does it depend on this if it is just defoconfig for a board ?
The patch series was nandbcb inclusion, but this is already merged in u-boot. patchwork query shows only the pending merger now.
As the nandbcb is already in mainline, this patch should apply fine.
Please read the whole e-mail. Issue is not that patch cannot be applied, issue is that it breaks several boards. All i.MX6 boards with NAND - check again:
Building current source for 1 boards (1 thread, 8 jobs per thread) arm: + pfla02 +arch/arm/mach-imx/built-in.o: In function `encode_bch_ecc': +arch/arm/mach-imx/cmd_nandbcb.c:45: undefined reference to `init_bch' +arch/arm/mach-imx/cmd_nandbcb.c:75: undefined reference to `encode_bch' +arch/arm/mach-imx/cmd_nandbcb.c:87: undefined reference to `free_bch' +arm-poky-linux-gnueabi-ld.bfd: BFD (GNU Binutils) 2.28.0.20170307 assertion fail ../../bfd/elf32-arm.c:9512 +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 0 0 1 /1 pfla02
The same happens to other boards, too.
I missed this. Will send v3 with conditionally including BCH in source as well.
ok, thanks !
Stefano
Thanks, Parthiban N
Best regards, Stefano Babic
Thanks, Parthiban N
Signed-off-by: Parthiban Nallathambi pn@denx.de Acked-by: Shyam Saini shyam.saini@amarulasolutions.com
Notes: Changes in v2: - use kfree instead of free
arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/cmd_nandbcb.c | 72 ++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index aeb5493488..175bed601e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -74,6 +74,7 @@ config CMD_HDMIDETECT config CMD_NANDBCB bool "i.MX6 NAND Boot Control Block(BCB) command" depends on NAND && CMD_MTDPARTS + select BCH if MX6UL || MX6ULL
This eems to break all i.MX6 boards (not UL(L)) using NAND. In fact, I get these errors:
Building current source for 1 boards (1 thread, 8 jobs per thread) arm: + pfla02 +arch/arm/mach-imx/built-in.o: In function `encode_bch_ecc': +arch/arm/mach-imx/cmd_nandbcb.c:45: undefined reference to `init_bch' +arch/arm/mach-imx/cmd_nandbcb.c:75: undefined reference to `encode_bch' +arch/arm/mach-imx/cmd_nandbcb.c:87: undefined reference to `free_bch' +arm-poky-linux-gnueabi-ld.bfd: BFD (GNU Binutils) 2.28.0.20170307 assertion fail ../../bfd/elf32-arm.c:9512 +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 0 0 1 /1 pfla02
Can you check this please ? I temporary remove the patch from -next branch.
Best regards, Stefano Babic
default y if ARCH_MX6 && NAND_MXS help Unlike normal 'nand write/erase' commands, this command update diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c index 065b814b2e..e11df401e4 100644 --- a/arch/arm/mach-imx/cmd_nandbcb.c +++ b/arch/arm/mach-imx/cmd_nandbcb.c @@ -14,8 +14,10 @@ #include <asm/io.h> #include <jffs2/jffs2.h> +#include <linux/bch.h> #include <linux/mtd/mtd.h> +#include <asm/arch/sys_proto.h> #include <asm/mach-imx/imx-nandbcb.h> #include <asm/mach-imx/imximage.cfg> #include <mxs_nand.h> @@ -25,6 +27,66 @@ #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET) #define GETBIT(v, n) (((v) >> (n)) & 0x1) +static uint8_t reverse_bit(uint8_t b) +{ + b = (b & 0xf0) >> 4 | (b & 0x0f) << 4; + b = (b & 0xcc) >> 2 | (b & 0x33) << 2; + b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
+ return b; +}
+static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int eccbits) +{ + int i, j, m = 13; + int blocksize = 128; + int numblocks = 8; + int ecc_buf_size = (m * eccbits + 7) / 8; + struct bch_control *bch = init_bch(m, eccbits, 0); + u8 *ecc_buf = kzalloc(ecc_buf_size, GFP_KERNEL); + u8 *tmp_buf = kzalloc(blocksize * numblocks, GFP_KERNEL); + u8 *psrc, *pdst;
+ /* + * The blocks here are bit aligned. If eccbits is a multiple of 8, + * we just can copy bytes. Otherwiese we must move the blocks to + * the next free bit position. + */ + WARN_ON(eccbits % 8);
+ memcpy(tmp_buf, fcb, sizeof(*fcb));
+ for (i = 0; i < numblocks; i++) { + memset(ecc_buf, 0, ecc_buf_size); + psrc = tmp_buf + i * blocksize; + pdst = buf + i * (blocksize + ecc_buf_size);
+ /* copy data byte aligned to destination buf */ + memcpy(pdst, psrc, blocksize);
+ /* + * imx-kobs use a modified encode_bch which reverse the + * bit order of the data before calculating bch. + * Do this in the buffer and use the bch lib here. + */ + for (j = 0; j < blocksize; j++) + psrc[j] = reverse_bit(psrc[j]);
+ encode_bch(bch, psrc, blocksize, ecc_buf);
+ /* reverse ecc bit */ + for (j = 0; j < ecc_buf_size; j++) + ecc_buf[j] = reverse_bit(ecc_buf[j]);
+ /* Here eccbuf is byte aligned and we can just copy it */ + memcpy(pdst + blocksize, ecc_buf, ecc_buf_size); + }
+ kfree(ecc_buf); + kfree(tmp_buf); + free_bch(bch); +}
static u8 calculate_parity_13_8(u8 d) { u8 p = 0; @@ -231,8 +293,14 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size, goto dbbt_data_page_err; } - memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block)); - encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512); + if (is_mx6ul() || is_mx6ull()) { + /* 40 bit BCH, for i.MX6UL(L) */ + encode_bch_ecc(fcb_raw_page + 32, fcb, 40); + } else { + memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block)); + encode_hamming_13_8(fcb_raw_page + 12, + fcb_raw_page + 12 + 512, 512); + } /* * Set the first and second byte of OOB data to 0xFF, not 0x00. These * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
participants (3)
-
Parthiban Nallathambi
-
Peng Fan
-
Stefano Babic