diff --git a/storage/imx6ull-flash/README.md b/storage/imx6ull-flash/README.md index ec0896590..64809198b 100644 --- a/storage/imx6ull-flash/README.md +++ b/storage/imx6ull-flash/README.md @@ -76,7 +76,7 @@ Analogue to flashdrv_write, but ignores metadata. Analogue to flashdrv_read, but ignores metadata. - extern void flashdrv_init(void); + extern int flashdrv_init(void); Library and NAND controler initialization. diff --git a/storage/imx6ull-flash/flashdev.c b/storage/imx6ull-flash/flashdev.c index 9b27895f6..e34aec92d 100644 --- a/storage/imx6ull-flash/flashdev.c +++ b/storage/imx6ull-flash/flashdev.c @@ -600,7 +600,7 @@ int flashdev_init(storage_t *strg) } strg->dev->ctx->dma = flashdrv_dmanew(); - if (strg->dev->ctx->dma == MAP_FAILED) { + if (strg->dev->ctx->dma == NULL) { free(strg->dev->ctx); free(strg->dev); return -ENOMEM; diff --git a/storage/imx6ull-flash/flashdrv.c b/storage/imx6ull-flash/flashdrv.c index 457435791..3316c8afd 100644 --- a/storage/imx6ull-flash/flashdrv.c +++ b/storage/imx6ull-flash/flashdrv.c @@ -211,7 +211,7 @@ struct { handle_t intbch, intdma, intgpmi; unsigned rawmetasz; /* user metadata + ECC16 metadata bytes */ - int result, bch_status, bch_done; + volatile int result, bch_status, bch_done; uint8_t *uncached_buf; flashdrv_info_t info; @@ -263,6 +263,9 @@ static void dma_sequence(dma_t *prev, dma_t *next) static void dma_run(dma_t *dma, int channel) { + /* Synchronize memory before running DMA */ + __asm__ volatile("dsb"); + *(flashdrv_common.dma + apbh_ch0_nxtcmdar + channel * apbh_next_channel) = (uint32_t)va2pa(dma); *(flashdrv_common.dma + apbh_ch0_sema + channel * apbh_next_channel) = 1; } @@ -445,7 +448,13 @@ static void flashdrv_setDevClock(int dev, int state) flashdrv_dma_t *flashdrv_dmanew(void) { - flashdrv_dma_t *dma = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_NULL, 0); + flashdrv_dma_t *dma; + + dma = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_CONTIGUOUS, 0); + if (dma == MAP_FAILED) { + return NULL; + } + dma->last = NULL; dma->first = NULL; @@ -705,6 +714,7 @@ int flashdrv_write(flashdrv_dma_t *dma, uint32_t paddr, void *data, char *aux) int chip = 0, channel = 0, sz; char addr[5] = { 0 }; int skipMeta = 0, err; + uint32_t tmp; memcpy(addr + 2, &paddr, 3); if (data == NULL) { @@ -732,18 +742,24 @@ int flashdrv_write(flashdrv_dma_t *dma, uint32_t paddr, void *data, char *aux) if (data == NULL) { /* Trick BCH controller into thinking that the whole page consists of just the metadata block */ - *(flashdrv_common.bch + bch_flash0layout0) &= ~(0xff << 24); - - *(flashdrv_common.bch + bch_flash0layout1) &= ~(0xffff << 16); - *(flashdrv_common.bch + bch_flash0layout1) |= flashdrv_common.rawmetasz << 16; + tmp = *(flashdrv_common.bch + bch_flash0layout0); + tmp &= ~(0xffu << 24); + *(flashdrv_common.bch + bch_flash0layout0) = tmp; + + tmp = *(flashdrv_common.bch + bch_flash0layout1); + tmp &= ~(0xffffu << 16); + tmp |= flashdrv_common.rawmetasz << 16; + *(flashdrv_common.bch + bch_flash0layout1) = tmp; } else if (skipMeta) { /* Perform partial page programming (don't change metadata and its ECC) */ memset(aux, 0xff, flashdrv_common.rawmetasz); /* Treat metadata and its ECC as raw byte area without ECC */ - *(flashdrv_common.bch + bch_flash0layout0) &= ~(0x1fff << 11); - *(flashdrv_common.bch + bch_flash0layout0) |= flashdrv_common.rawmetasz << 16; + tmp = *(flashdrv_common.bch + bch_flash0layout0); + tmp &= ~(0x1fff << 11); + tmp |= flashdrv_common.rawmetasz << 16; + *(flashdrv_common.bch + bch_flash0layout0) = tmp; } flashdrv_common.result = 1; @@ -757,14 +773,20 @@ int flashdrv_write(flashdrv_dma_t *dma, uint32_t paddr, void *data, char *aux) err = flashdrv_common.result; if (data == NULL) { - *(flashdrv_common.bch + bch_flash0layout0) |= 8 << 24; - - *(flashdrv_common.bch + bch_flash0layout1) &= ~(0xffff << 16); - *(flashdrv_common.bch + bch_flash0layout1) |= (flashdrv_common.info.writesz + flashdrv_common.info.metasz) << 16; + tmp = *(flashdrv_common.bch + bch_flash0layout0); + tmp |= (8 << 24); + *(flashdrv_common.bch + bch_flash0layout0) = tmp; + + tmp = *(flashdrv_common.bch + bch_flash0layout1); + tmp &= ~(0xffffu << 16); + tmp |= (flashdrv_common.info.writesz + flashdrv_common.info.metasz) << 16; + *(flashdrv_common.bch + bch_flash0layout1) = tmp; } else if (skipMeta) { - *(flashdrv_common.bch + bch_flash0layout0) &= ~(0x1fff << 11); - *(flashdrv_common.bch + bch_flash0layout0) |= 16 << 16 | 8 << 11; + tmp = *(flashdrv_common.bch + bch_flash0layout0); + tmp &= ~(0x1fff << 11); + tmp |= (16 << 16) | (8 << 11); + *(flashdrv_common.bch + bch_flash0layout0) = tmp; } mutexUnlock(flashdrv_common.mutex); @@ -991,16 +1013,6 @@ int flashdrv_markbad(flashdrv_dma_t *dma, uint32_t paddr) } -void flashdrv_rundma(flashdrv_dma_t *dma) -{ - int channel = 0; - - mutexLock(flashdrv_common.mutex); - dma_run((dma_t *)dma->first, channel); - mutexUnlock(flashdrv_common.mutex); -} - - static void setup_flash_info(void) { flash_id_t *flash_id = (flash_id_t *)flashdrv_common.uncached_buf; @@ -1044,13 +1056,42 @@ static void setup_flash_info(void) } -void flashdrv_init(void) +int flashdrv_init(void) { - flashdrv_common.dma = mmap(NULL, 2 * _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE, OID_PHYSMEM, 0x1804000); - flashdrv_common.gpmi = mmap(NULL, 2 * _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE, OID_PHYSMEM, 0x1806000); - flashdrv_common.bch = mmap(NULL, 4 * _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE, OID_PHYSMEM, 0x1808000); - flashdrv_common.mux = mmap(NULL, 4 * _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE, OID_PHYSMEM, 0x20e0000); - flashdrv_common.uncached_buf = mmap(NULL, 2 * _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_CONTIGUOUS, 0); + flashdrv_common.dma = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE, OID_PHYSMEM, 0x1804000); + if (flashdrv_common.dma == MAP_FAILED) { + return -ENOMEM; + } + + flashdrv_common.gpmi = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE, OID_PHYSMEM, 0x1806000); + if (flashdrv_common.gpmi == MAP_FAILED) { + munmap((void *)flashdrv_common.dma, _PAGE_SIZE); + return -ENOMEM; + } + + flashdrv_common.bch = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE, OID_PHYSMEM, 0x1808000); + if (flashdrv_common.bch == MAP_FAILED) { + munmap((void *)flashdrv_common.gpmi, _PAGE_SIZE); + munmap((void *)flashdrv_common.dma, _PAGE_SIZE); + return -ENOMEM; + } + + flashdrv_common.mux = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE, OID_PHYSMEM, 0x20e0000); + if (flashdrv_common.mux == MAP_FAILED) { + munmap((void *)flashdrv_common.bch, _PAGE_SIZE); + munmap((void *)flashdrv_common.gpmi, _PAGE_SIZE); + munmap((void *)flashdrv_common.dma, _PAGE_SIZE); + return -ENOMEM; + } + + flashdrv_common.uncached_buf = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_CONTIGUOUS, 0); + if (flashdrv_common.uncached_buf == MAP_FAILED) { + munmap((void *)flashdrv_common.mux, _PAGE_SIZE); + munmap((void *)flashdrv_common.bch, _PAGE_SIZE); + munmap((void *)flashdrv_common.gpmi, _PAGE_SIZE); + munmap((void *)flashdrv_common.dma, _PAGE_SIZE); + return -ENOMEM; + } /* 16 bytes of user metadada + ECC16 * bits per parity level (13) / 8 = 26 bytes for ECC */ flashdrv_common.rawmetasz = 16 + 26; @@ -1122,6 +1163,8 @@ void flashdrv_init(void) *(flashdrv_common.bch + bch_flash0layout1) = (flashdrv_common.info.writesz + flashdrv_common.info.metasz) << 16 | 7 << 11 | 0 << 10 | 128; interrupt(32 + 15, bch_irqHandler, NULL, flashdrv_common.bch_cond, &flashdrv_common.intbch); + + return EOK; } diff --git a/storage/imx6ull-flash/flashsrv.c b/storage/imx6ull-flash/flashsrv.c index 9cd8c6bab..5362dca64 100644 --- a/storage/imx6ull-flash/flashsrv.c +++ b/storage/imx6ull-flash/flashsrv.c @@ -744,7 +744,11 @@ static int flashsrv_nandInit(void) storage_t *strg; /* Initialize nand flash driver */ - flashdrv_init(); + err = flashdrv_init(); + if (err < 0) { + LOG_ERROR("failed to initialize driver, err: %d", err); + return err; + } strg = calloc(1, sizeof(storage_t)); if (strg == NULL) { diff --git a/storage/imx6ull-flash/imx6ull-flash-test.c b/storage/imx6ull-flash/imx6ull-flash-test.c index e690e01ab..694cb796c 100644 --- a/storage/imx6ull-flash/imx6ull-flash-test.c +++ b/storage/imx6ull-flash/imx6ull-flash-test.c @@ -135,7 +135,7 @@ int flip_bits(unsigned int n, unsigned int nblock, unsigned int start, unsigned if (!n) return EOK; - if ((dma = flashdrv_dmanew()) == MAP_FAILED) { + if ((dma = flashdrv_dmanew()) == NULL) { err = -ENOMEM; printf("dmanew() failed, err: %d\n", err); return err; @@ -239,7 +239,7 @@ void test_bootrom(void) const unsigned int seed = 0xaa55aa55; /* Use fixed rand() seed (so we could revert the bit flips by running the test again) */ flashdrv_dma_t *dma; - if ((dma = flashdrv_dmanew()) == MAP_FAILED) { + if ((dma = flashdrv_dmanew()) == NULL) { printf("dmanew() failed, err: %d\n", -ENOMEM); return; } @@ -407,7 +407,7 @@ void test_ecc(void) size_t boffs, blen; int i, err; - if ((dma = flashdrv_dmanew()) == MAP_FAILED) { + if ((dma = flashdrv_dmanew()) == NULL) { printf("dmanew() failed, err: %d\n", -ENOMEM); return; } @@ -689,10 +689,17 @@ void test_write_fcb(void) int err; data = mmap(NULL, pagemapsz, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_CONTIGUOUS, 0); - if (data == MAP_FAILED) - FAIL("failed to mmap data buffer\n"); + if (data == MAP_FAILED) { + printf("mmap() failed, err: %d\n", -ENOMEM); + return; + } dma = flashdrv_dmanew(); + if (dma == NULL) { + printf("dmanew() failed, err: %d\n", -ENOMEM); + munmap(data, pagemapsz); + return; + } #if 1 memcpy(data, fcb, FLASHDRV_PAGESZ); @@ -728,10 +735,17 @@ void test_meta(void) meta = data + _PAGE_SIZE; aux = (flashdrv_meta_t *)meta; - if (data == MAP_FAILED) - FAIL("failed to mmap data buffer\n"); + if (data == MAP_FAILED) { + printf("mmap() failed, err: %d\n", -ENOMEM); + return; + } dma = flashdrv_dmanew(); + if (dma == NULL) { + printf("dmanew() failed, err: %d\n", -ENOMEM); + munmap(data, pagemapsz); + return; + } if ((err = flashdrv_erase(dma, paddr) < 0)) printf("erase() failed: %d\n", err); @@ -864,10 +878,17 @@ void test_badblocks(void) int total_read_fails = 0, total_bad_blocks = 0; data = mmap(NULL, pagemapsz, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_CONTIGUOUS, 0); - if (data == MAP_FAILED) - FAIL("failed to mmap data buffer\n"); + if (data == MAP_FAILED) { + printf("mmap() failed, err: %d\n", -ENOMEM); + return; + } dma = flashdrv_dmanew(); + if (dma == NULL) { + printf("dmanew() failed, err: %d\n", -ENOMEM); + munmap(data, pagemapsz); + return; + } #if 0 /* uncomment to create fake badblock */ flashdrv_markbad(dma, 1337 * 64); @@ -933,7 +954,7 @@ void test_read_disturb(void) unsigned int i, j, k; int err, done; - if ((dma = flashdrv_dmanew()) == MAP_FAILED) { + if ((dma = flashdrv_dmanew()) == NULL) { printf("dmanew() failed, err: %d\n", -ENOMEM); return; } @@ -1026,8 +1047,18 @@ void test_stress_one_block(void) flashdrv_meta_t *m; dma = flashdrv_dmanew(); + if (dma == NULL) { + printf("dmanew() failed, err: %d\n", -ENOMEM); + return; + } data = mmap(NULL, pagemapsz, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_CONTIGUOUS, 0); + if (data == MAP_FAILED) { + printf("mmap() failed: %d\n", -ENOMEM); + flashdrv_dmadestroy(dma); + return; + } + meta = data + _PAGE_SIZE; m = (flashdrv_meta_t *)meta; @@ -1311,11 +1342,18 @@ void test_write_read_erase(void) unsigned int blockno; data = mmap(NULL, pagemapsz, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_CONTIGUOUS, 0); - if (data == MAP_FAILED) - FAIL("failed to mmap data buffers\n"); + if (data == MAP_FAILED) { + printf("mmap() failed, err: %d\n", -ENOMEM); + return; + } meta = data + _PAGE_SIZE; dma = flashdrv_dmanew(); + if (dma == NULL) { + printf("dmanew() failed, err: %d\n", -ENOMEM); + munmap(data, pagemapsz); + return; + } for (blockno = 0; blockno < TOTAL_BLOCKS_CNT; ++blockno) test_single_block(dma, blockno, data, meta); @@ -1332,11 +1370,18 @@ void test_write_read_erase_raw(void) unsigned int blockno; data = mmap(NULL, pagemapsz, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_CONTIGUOUS, 0); - if (data == MAP_FAILED) - FAIL("failed to mmap data buffers\n"); + if (data == MAP_FAILED) { + printf("mmap() failed, err: %d\n", -ENOMEM); + return; + } meta = data + _PAGE_SIZE; dma = flashdrv_dmanew(); + if (dma == NULL) { + printf("dmanew() failed, err: %d\n", -ENOMEM); + munmap(data, pagemapsz); + return; + } /* check every erease block (read first page metadata as RAW to omit ECC checks) */ for (blockno = 0; blockno < TOTAL_BLOCKS_CNT; ++blockno) { @@ -1353,22 +1398,30 @@ void test_write_read_erase_raw(void) void test_3(void) { - void *buffer = mmap(NULL, 16 * _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_PHYSMEM, 0x900000); + void *buffer; flashdrv_dma_t *dma; int err; - memset(buffer, 0, 16 * _PAGE_SIZE); + printf("creating\n"); + buffer = mmap(NULL, 16 * _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_UNCACHED, OID_PHYSMEM, 0x900000); + if (buffer == MAP_FAILED) { + printf("mmap() failed, err: %d\n", -ENOMEM); + return; + } + + dma = flashdrv_dmanew(); + if (dma == NULL) { + printf("dmanew() failed, err: %d\n", -ENOMEM); + munmap(buffer, 16 * _PAGE_SIZE); + return; + } + memset(buffer, 0, 16 * _PAGE_SIZE); for (int i = 0; i < 0x1000; ++i) { ((char *)buffer)[i] = 0xb2; ((char *)buffer)[0x1000 + i] = 0x8a; } - - printf("creating\n"); - - dma = flashdrv_dmanew(); - printf("reset\n"); flashdrv_reset(dma); @@ -1403,7 +1456,6 @@ void test_3(void) printf("%d\n", err); - printf("readraw "); err = flashdrv_readraw(dma, 0, buffer + 0x9000, FLASHDRV_PAGESZ); printf("%d\n", err); @@ -1421,8 +1473,10 @@ void test_3(void) err = flashdrv_read(dma, 0, buffer + 0xd000, buffer + 0xe000); printf("%d\n", err); - printf("done\n"); + + flashdrv_dmadestroy(dma); + munmap(buffer, 16 * _PAGE_SIZE); } diff --git a/storage/imx6ull-flash/imx6ull-flashdrv.h b/storage/imx6ull-flash/imx6ull-flashdrv.h index a42f26b9a..5fdcd8d7e 100644 --- a/storage/imx6ull-flash/imx6ull-flashdrv.h +++ b/storage/imx6ull-flash/imx6ull-flashdrv.h @@ -92,7 +92,7 @@ extern int flashdrv_isbad(flashdrv_dma_t *dma, uint32_t paddr); extern int flashdrv_markbad(flashdrv_dma_t *dma, uint32_t paddr); -extern void flashdrv_init(void); +extern int flashdrv_init(void); extern const flashdrv_info_t *flashdrv_info(void);