static void print_pkt_16(u16 *pkt, u32 len);
// globals
-static int nand_flash_index = -1;
static int g_ecc_enable = true;
static int g_spare_only_read_ok = true;
-static int g_nfc_debug_level = NFC_DEBUG_NONE;
+static int g_nfc_debug_level = NFC_DEBUG_DEF;
static bool g_nfc_debug_measure = false;
static bool g_is_2k_page = false;
static unsigned int g_block_offset;
#endif
{
u32 id[2];
+
+ nfc_printf(NFC_DEBUG_MIN, "%s@%d data=%p\n", __FUNCTION__, __LINE__, data);
+
read_nflash_id(&id[0], 0);
- nfc_printf(NFC_DEBUG_MAX, "%s(ID=0x%02x: 0x%02x, 0x%02x, 0x%02x)\n", __FUNCTION__,
+ nfc_printf(NFC_DEBUG_MIN, "%s(ID=0x%02x: 0x%02x, 0x%02x, 0x%02x)\n", __FUNCTION__,
id[0] & 0xff, (id[0] >> 8) & 0xff, (id[0] >> 16) & 0xff, id[0] >> 24);
- memcpy(data, id, sizeof(id));
+ if (data != NULL) {
+ nfc_printf(NFC_DEBUG_MAX, "%s@%d copy flash ID from %p to %p\n",
+ __FUNCTION__, __LINE__, &id[0], data);
+ memcpy(data, id, sizeof(id));
+ }
+ nfc_printf(NFC_DEBUG_MAX, "%s@%d %p\n", __FUNCTION__, __LINE__,
+ __builtin_return_address(0));
}
#ifndef MXCFLASH_SELECT_MULTI
void mxc_flash_enable(void *start, void *end)
{
flash_addr_t s = (unsigned long)start & MXC_NAND_ADDR_MASK;
- flash_addr_t e = (unsigned long)end & MXC_NAND_ADDR_MASK;
+ flash_addr_t e = ((unsigned long)end - 1) & MXC_NAND_ADDR_MASK;
if (flash_enable++ == 0) {
flash_region_start = s;
void mxc_flash_disable(void *start, void *end)
{
flash_addr_t s = (unsigned long)start & MXC_NAND_ADDR_MASK;
- flash_addr_t e = (unsigned long)end & MXC_NAND_ADDR_MASK;
+ flash_addr_t e = ((unsigned long)end - 1) & MXC_NAND_ADDR_MASK;
if (flash_enable) {
if (--flash_enable == 0) {
u32 id[2];
int i;
+#if 0
+ return FLASH_ERR_DRV_WRONG_PART;
+#endif
nfc_printf(NFC_DEBUG_MAX, "%s()\n", __FUNCTION__);
if (nfc_iomux_setup)
NFC_CMD_INPUT(FLASH_Reset);
// Look through table for device data
+ nfc_printf(NFC_DEBUG_MAX, "%s@%d %p\n", __FUNCTION__, __LINE__, &id[0]);
flash_dev_query(&id[0]);
+ nfc_printf(NFC_DEBUG_MAX, "%s@%d\n", __FUNCTION__, __LINE__);
+
flash_dev_info = supported_devices;
for (i = 0; i < NUM_DEVICES; i++) {
if ((flash_dev_info->device_id == (id[0] & 0xffff)) &&
break;
flash_dev_info++;
}
+ nfc_printf(NFC_DEBUG_MAX, "%s@%d\n", __FUNCTION__, __LINE__);
// Did we find the device? If not, return error.
if (NUM_DEVICES == i) {
return FLASH_ERR_DRV_WRONG_PART;
}
- nand_flash_index = i;
mxcnfc_init_ok = true;
if (NF_PG_SZ == 2048) {
__FUNCTION__, i, NUM_DEVICES, flash_dev_info->device_id);
if (nfc_setup) {
+ nfc_printf(NFC_DEBUG_MAX, "%s@%d\n", __FUNCTION__, __LINE__);
g_nfc_version = nfc_setup(NF_PG_SZ / num_of_nand_chips, flash_dev_info->port_size,
flash_dev_info->type, num_of_nand_chips);
}
+ nfc_printf(NFC_DEBUG_MAX, "%s@%d\n", __FUNCTION__, __LINE__);
diag_printf1("NFC version: %02x\n", g_nfc_version);
- if (g_nfc_version == MXC_NFC_V3) {
+ if (g_nfc_version >= MXC_NFC_V3) {
for (i = 2; i <= NUM_OF_CS_LINES; i++) {
u32 id_tmp[2];
read_nflash_id(&id_tmp[0], i - 1);
if (!nfc_verify_addr(dst, len)) {
return;
}
+ diag_printf1("Copying %u byte from %p..%p to flash buffer %08lx..%08lx\n",
+ len, bp, bp + len - 1, dst, dst + len - 1);
if (dst & 1) {
store_byte(d, 1, *bp);
d++;
{
volatile u32 *ptr = (volatile u32*)NAND_MAIN_BUF0;
- nfc_printf(NFC_DEBUG_MIN, "%s: read flash id from chip %d @ %p\n",
+ nfc_printf(NFC_DEBUG_MIN, "%s: read flash id from chip %d @ %p\n",
__FUNCTION__, cs_line, ptr);
+#if 0
+#if 1
+ {
+ int i;
+ const int nwords = 512 >> 2;
+
+ for (i = 0; i < 8; i++) {
+ int j;
+
+ for (j = 0; j < nwords; j++) {
+ ptr[i * nwords + j] = 0xdeadbeef;
+ }
+ }
+ }
+#else
+ {
+ int i;
+ const int nwords = 512 >> 2;
+
+ for (i = 0; i < 8; i++) {
+ int j;
+ for (j = 0; j < nwords; j++) {
+ id[i * nwords + j] = 0xdeadbeef;
+ }
+ }
+ }
+#endif
+#endif
NFC_PRESET(MXC_UNLOCK_BLK_END);
NFC_SET_NFC_ACTIVE_CS(cs_line);
NFC_CMD_INPUT(FLASH_Read_ID);
start_nfc_addr_ops(FLASH_Read_ID, 0, 0, 0, cs_line, num_of_nand_chips);
NFC_DATA_OUTPUT(RAM_BUF_0, FDO_FLASH_ID, g_ecc_enable);
- *id++ = *ptr++;
- *id++ = *ptr++;
+ *id++ = *ptr++;
+ *id++ = *ptr++;
}
static void mark_blk_bad(unsigned int block, unsigned char *buf,
enum blk_bad_type bad_type)
{
- unsigned int off = block >> 2; // byte offset - each byte can hold status for 4 blocks
- unsigned int sft = (block & 3) << 1; // bit shift 0, 2, 4, 6
+ unsigned int off = block >> 2; // byte offset - each byte can hold status for 4 blocks
+ unsigned int sft = (block & 3) << 1; // bit shift 0, 2, 4, 6
unsigned char val = buf[off];
if (block > NF_BLK_CNT) {
u16 flash_status, i;
u32 pg_no, pg_off;
- if (g_nfc_version == MXC_NFC_V3) {
+ if (g_nfc_version >= MXC_NFC_V3) {
// combine the two commands for erase
- writel((FLASH_Start_Erase << 8) | FLASH_Block_Erase, NAND_CMD_REG);
+ nfc_reg_write((FLASH_Start_Erase << 8) | FLASH_Block_Erase, NAND_CMD_REG);
pg_no = ra / NF_PG_SZ;
pg_off = ra % NF_PG_SZ;
for (i = 0; i < num_of_nand_chips; i++) {
start_nfc_addr_ops(FLASH_Block_Erase, pg_no, pg_off, 1, i, num_of_nand_chips);
// start auto-erase
- writel(NAND_LAUNCH_AUTO_ERASE, NAND_LAUNCH_REG);
+ nfc_reg_write(NAND_LAUNCH_AUTO_ERASE, NAND_LAUNCH_REG);
wait_op_done();
pg_off = 0;
}
buf += NF_PG_SZ;
}
if (len != 0) {
+ diag_printf1("Clearing flash buffer from %p..%p\n", g_page_buf + len - 1,
+ g_page_buf + NF_PG_SZ - 1);
memset(g_page_buf + len, 0xFF, NF_PG_SZ - len);
+ diag_printf1("Copying partial page from %p..%p to %p..%p\n",
+ buf, buf + len - 1, g_page_buf, g_page_buf + len);
memcpy(g_page_buf, buf, len);
if (nfc_write_pg_random(ra / NF_PG_SZ, ra % NF_PG_SZ, g_page_buf, 0) != 0) {
num_of_nand_chips = temp;
}
if (nfc_erase_blk(addr) != 0) {
diag_printf("\n** Error: Failed to erase block %u at addr 0x%08llx\n",
- blk, (u64)addr);
+ blk, (u64)addr);
mark_blk_bad(blk, g_bbt, BLK_BAD_RUNTIME);
// we don't need to update the table immediately here since even
// with power loss now, we should see the same erase error again.
}
diag_printf1("%s(0x%x, 0x%x, %d)\n", __FUNCTION__, pg_no, pg_off, ecc_force);
+ if (g_nfc_version != MXC_NFC_V1) {
+ int i;
- switch (g_nfc_version & 0xf0) {
- case MXC_NFC_V3:
+ for (i = 1; i < NFC_SPARE_BUF_SZ / 16; i++) {
+ memcpy((void *)(NAND_SPAR_BUF0 + i * NFC_SPARE_BUF_SZ),
+ (void *)(NAND_SPAR_BUF0 + i * 16), 16);
+ }
+ }
+ if (g_nfc_version >= MXC_NFC_V3) {
/* Check if Page size is greater than NFC buffer */
do {
+ rba = nfc_reg_read(NAND_CONFIGURATION1_REG);
+ if ((rba >> 4) & 0x7) {
+ nfc_reg_write(rba & ~0x70, NAND_CONFIGURATION1_REG);
+ }
if (write_count <= NFC_BUFSIZE) {
// No need to worry about the spare area
nfc_buf_write(NAND_MAIN_BUF0, buf, write_count);
buf += NFC_BUFSIZE;
}
// combine the two commands for program
- writel((FLASH_Program << 8) | FLASH_Send_Data, NAND_CMD_REG);
+ nfc_reg_write((FLASH_Program << 8) | FLASH_Send_Data, NAND_CMD_REG);
for (i = start_point; i < num_of_nand_chips; i++) {
rba = rba_count * ((NF_PG_SZ / num_of_nand_chips) / 512);
}
// For ECC
- v = readl(NFC_FLASH_CONFIG2_REG) & ~NFC_FLASH_CONFIG2_ECC_EN;
+ v = nfc_reg_read(NFC_FLASH_CONFIG2_REG) & ~NFC_FLASH_CONFIG2_ECC_EN;
// setup config2 register for ECC enable or not
write_nfc_ip_reg(v | ecc, NFC_FLASH_CONFIG2_REG);
start_nfc_addr_ops(FLASH_Program, pg_no, pg_off, 0, i, num_of_nand_chips);
// start auto-program
- writel(NAND_LAUNCH_AUTO_PROG, NAND_LAUNCH_REG);
+ nfc_reg_write(NAND_LAUNCH_AUTO_PROG, NAND_LAUNCH_REG);
if (i < (num_of_nand_chips - i))
wait_for_auto_prog_done();
else
wait_op_done();
pg_off = 0;
rba_count++;
+ rba = nfc_reg_read(NAND_CONFIGURATION1_REG);
+ }
+ flash_status = NFC_STATUS_READ();
+ // check I/O bit 0 to see if it is 0 for success
+ if ((flash_status & ((0x1 << num_of_nand_chips) - 1)) != 0) {
+ return -1;
}
start_point = i;
} while (write_count > 0);
- flash_status = NFC_STATUS_READ();
- // check I/O bit 0 to see if it is 0 for success
- if ((flash_status & ((0x1 << num_of_nand_chips) - 1)) != 0) {
- return -1;
- }
- break;
- default:
- if (g_nfc_version != MXC_NFC_V1) {
- int i;
-
- for (i = 1; i < NFC_SPARE_BUF_SZ / 16; i++) {
- memcpy((void *)(NAND_SPAR_BUF0 + i * NFC_SPARE_BUF_SZ),
- (void *)(NAND_SPAR_BUF0 + i * 16), 16);
- }
- }
+ } else {
nfc_buf_write(NAND_MAIN_BUF0, buf, NF_PG_SZ);
#ifdef BARKER_CODE_SWAP_LOC
// To replace the data at offset MXC_NAND_BOOT_LOAD_BARKER with
if (pg_no == 0) {
diag_printf("\n[INFO]: copy data at 0x%x to spare area and set it to 0x%x\n",
BARKER_CODE_SWAP_LOC, BARKER_CODE_VAL);
- writel(readl(NFC_BASE + BARKER_CODE_SWAP_LOC), NAND_SPAR_BUF0);
+ nfc_reg_write(nfc_reg_read(NFC_BASE + BARKER_CODE_SWAP_LOC), NAND_SPAR_BUF0);
// todo: set BARKER_CODE_VAL and BARKER_CODE_SWAP_LOC for skye, etc.
- writel(BARKER_CODE_VAL, NFC_BASE + BARKER_CODE_SWAP_LOC);
+ nfc_reg_write(BARKER_CODE_VAL, NFC_BASE + BARKER_CODE_SWAP_LOC);
}
#endif
NFC_CMD_INPUT(FLASH_Send_Data);
return 0;
}
-#ifndef NFC_V3_0
+#ifdef NFC_V3_0
+/*
+ * Do a page read at random address
+ *
+ * @param pg_no page number offset from 0
+ * @param pg_off byte offset within the page
+ * @param ecc_force can force ecc to be off. Otherwise, by default it is on
+ * unless the page offset is non-zero
+ * @param cs_line indicates which NAND of interleaved NAND devices is used
+ *
+ * @return 0 if successful; non-zero otherwise
+ */
+static int nfc_read_pg_random(u32 pg_no, u32 pg_off, u32 ecc_force, u32 cs_line, u32 num_of_chips)
+{
+ u32 ecc = NFC_FLASH_CONFIG2_ECC_EN;
+ u32 v, res = 0;
+ int i;
+
+ // clear the NAND_STATUS_SUM_REG register
+ nfc_reg_write(0, NAND_STATUS_SUM_REG);
+
+ // the 2nd condition is to test for unaligned page address -- ecc has to be off.
+ if (ecc_force == ECC_FORCE_OFF || pg_off != 0 ) {
+ ecc = 0;
+ }
+
+ // Take care of config1 for RBA and SP_EN
+ v = nfc_reg_read(NAND_CONFIGURATION1_REG) & ~0x71;
+ nfc_reg_write(v, NAND_CONFIGURATION1_REG);
+
+ // For ECC
+ v = nfc_reg_read(NFC_FLASH_CONFIG2_REG) & ~NFC_FLASH_CONFIG2_ECC_EN;
+ // setup config2 register for ECC enable or not
+ write_nfc_ip_reg(v | ecc, NFC_FLASH_CONFIG2_REG);
+
+ start_nfc_addr_ops(FLASH_Read_Mode1, pg_no, pg_off, 0, cs_line, num_of_chips);
+
+ if (g_is_2k_page || g_is_4k_page) {
+ // combine the two commands for 2k/4k page read
+ nfc_reg_write((FLASH_Read_Mode1_LG << 8) | FLASH_Read_Mode1, NAND_CMD_REG);
+ } else {
+ // just one command is enough for 512 page
+ nfc_reg_write(FLASH_Read_Mode1, NAND_CMD_REG);
+ }
+
+ // start auto-read
+ nfc_reg_write(NAND_LAUNCH_AUTO_READ, NAND_LAUNCH_REG);
+ wait_op_done();
+
+ for (i = 1; i < NFC_SPARE_BUF_SZ / 16; i++) {
+ memcpy((void *)(NAND_SPAR_BUF0 + i * 16),
+ (void *)(NAND_SPAR_BUF0 + i * NFC_SPARE_BUF_SZ), 16);
+ }
+ v = nfc_reg_read(NAND_STATUS_SUM_REG);
+ // test for CS0 ECC error from the STATUS_SUM register
+ if ((v & (0x0100 << cs_line)) != 0) {
+ // clear the status
+ nfc_reg_write(v & ~(0x0100 << cs_line), NAND_STATUS_SUM_REG);
+ diag_printf("ECC error from NAND_STATUS_SUM_REG(0x%08lx) = 0x%08x\n",
+ NAND_STATUS_SUM_REG, v);
+ diag_printf("NAND_ECC_STATUS_RESULT_REG(0x%08lx) = 0x%08x\n", NAND_ECC_STATUS_RESULT_REG,
+ nfc_reg_read(NAND_ECC_STATUS_RESULT_REG));
+ res = -1;
+ }
+ return res;
+}
+#else
// for version V1 and V2 of NFC
static int nfc_read_pg_random(u32 pg_no, u32 pg_off, u32 ecc_force, u32 cs_line,
u32 num_of_nand_chips)
NFC_DATA_OUTPUT(RAM_BUF_3, FDO_PAGE_SPARE, ecc);
}
if (ecc) {
- t1 = readl(ECC_STATUS_RESULT_REG);
+ t1 = nfc_reg_read(ECC_STATUS_RESULT_REG);
if (g_is_2k_page || g_is_4k_page) {
t2 = (t1 >> 4) & 0xF;
t3 = (t1 >> 8) & 0xF;
// This is needed for certain platforms
if (pg_no == 0) {
diag_printf("\n[INFO]: copy back data from spare to 0x%x\n", BARKER_CODE_SWAP_LOC);
- writel(readl(NAND_SPAR_BUF0), NFC_BASE + BARKER_CODE_SWAP_LOC);
+ nfc_reg_write(nfc_reg_read(NAND_SPAR_BUF0), NFC_BASE + BARKER_CODE_SWAP_LOC);
}
#endif
ecc = 0;
}
+ if (g_nfc_version != MXC_NFC_V1) {
+ int i;
+
+ for (i = NFC_SPARE_BUF_SZ / 16 - 1; i >= 0; i--) {
+ memcpy((void *)(NAND_SPAR_BUF0 + i * NFC_SPARE_BUF_SZ),
+ (void *)(NAND_SPAR_BUF0 + i * 16), 16);
+ }
+ }
if (g_nfc_version == MXC_NFC_V3) {
int i;
u32 v;
u32 start_point = 0, rba, rba_count = 0;
+ rba = nfc_reg_read(NAND_CONFIGURATION1_REG);
+ if ((rba >> 4) & 0x7) {
+ nfc_reg_write(rba & ~0x70, NAND_CONFIGURATION1_REG);
+ }
// combine the two commands for program
- writel((FLASH_Program << 8) | FLASH_Send_Data, NAND_CMD_REG);
+ nfc_reg_write((FLASH_Program << 8) | FLASH_Send_Data, NAND_CMD_REG);
for (i = start_point; i < num_of_nand_chips; i++) {
rba = rba_count * ((NF_PG_SZ / num_of_nand_chips) / 512);
}
// For ECC
- v = readl(NFC_FLASH_CONFIG2_REG) & ~NFC_FLASH_CONFIG2_ECC_EN;
+ v = nfc_reg_read(NFC_FLASH_CONFIG2_REG) & ~NFC_FLASH_CONFIG2_ECC_EN;
// setup config2 register for ECC enable or not
write_nfc_ip_reg(v | ecc, NFC_FLASH_CONFIG2_REG);
start_nfc_addr_ops(FLASH_Program, pg_no, pg_off, 0, i, num_of_nand_chips);
// start auto-program
- writel(NAND_LAUNCH_AUTO_PROG, NAND_LAUNCH_REG);
+ nfc_reg_write(NAND_LAUNCH_AUTO_PROG, NAND_LAUNCH_REG);
if (i < (num_of_nand_chips - i))
wait_for_auto_prog_done();
else
pg_off = 0;
rba_count++;
}
- start_point = i;
flash_status = NFC_STATUS_READ();
- } else {
- if (g_nfc_version != MXC_NFC_V1) {
- int i;
-
- for (i = NFC_SPARE_BUF_SZ / 16 - 1; i >= 0; i--) {
- memcpy((void *)(NAND_SPAR_BUF0 + i * NFC_SPARE_BUF_SZ),
- (void *)(NAND_SPAR_BUF0 + i * 16), 16);
- }
+ // check I/O bit 0 to see if it is 0 for success
+ if ((flash_status & ((0x1 << num_of_nand_chips) - 1)) != 0) {
+ return -1;
}
+ rba = nfc_reg_read(NAND_CONFIGURATION1_REG);
+ start_point = i;
+ } else {
NFC_CMD_INPUT(FLASH_Send_Data);
start_nfc_addr_ops(FLASH_Program, pg_no, pg_off, 0, 0, num_of_nand_chips);
NFC_CMD_INPUT(FLASH_Program);
flash_status = NFC_STATUS_READ();
- }
- if ((flash_status & 0x1) != 0) {
- diag_printf("** Error: failed to program page %u at addr 0x%08llx\n",
- pg_no, (u64)pg_no * NF_PG_SZ + pg_off);
- return -1;
+ if ((flash_status & 0x1) != 0) {
+ diag_printf("** Error: failed to program page %u at addr 0x%08llx\n",
+ pg_no, (u64)pg_no * NF_PG_SZ + pg_off);
+ return -1;
+ }
}
return 0;
}
return;
}
+ diag_printf1("Enabling flash from %p..%p\n", (u8 *)ra, (u8 *)ra + len - 1);
+ FLASH_Enable((u8 *)ra, (u8 *)ra + len);
if (force_erase_set == true) {
diag_printf("Force erase ...");
nfc_erase_region(ra, len, 0, 1);
} else {
nfc_erase_region(ra, len, 1, 1);
}
+ FLASH_Disable((u8 *)ra, (u8 *)ra + len);
diag_printf("\n");
}
{
u32 i, j = 0;
- if (nand_flash_index == -1) {
- diag_printf("Can't find valid NAND flash: %d\n", __LINE__);
- return;
- }
-
diag_printf("\nType:\t\t %s\n", NF_VEND_INFO);
diag_printf("Total size:\t 0x%08x bytes (%d MiB)\n", NF_DEV_SZ, NF_DEV_SZ / SZ_1M);
diag_printf("Total blocks:\t 0x%x (%d)\n", NF_BLK_CNT, NF_BLK_CNT);
static void do_nand_cmds(int argc, char *argv[])
{
struct cmd *cmd;
+#if 0
+ unsigned long ctrl, l2, sid, cs;
+ unsigned int d, i;
+
+ HAL_FLASH_CACHES_OFF(d, i);
+ diag_printf("DCACHE: %d ICACHE: %d\n", d, i);
+ HAL_FLASH_CACHES_ON(d, i);
+
+ asm volatile(
+ "MRC p15, 0, %0, c1, c0, 0;"
+ "MRC p15, 0, %1, c1, c0, 1;"
+ "MRC p15, 1, %2, c0, c0, 7;"
+ "MRC p15, 1, %3, c0, c0, 0;"
+ : "=r"(ctrl), "=r"(l2), "=r"(sid), "=r"(cs)
+ );
+
+ diag_printf("ctrl: %08lx aux: %08lx sid: %08lx cs: %08lx\n", ctrl, l2, sid, cs);
+#endif
if (!mxcnfc_init_ok) {
+ flash_hwr_init();
+ if (!mxcnfc_init_ok) {
#ifdef CYGHWR_DEVS_FLASH_MXC_MULTI
- diag_printf("Warning: NAND flash hasn't been initialized. Try \"factive nand\" first\n\n");
+ diag_printf("Warning: NAND flash hasn't been initialized. Try \"factive nand\" first\n\n");
#else
- diag_printf("Error: NAND flash hasn't been initialized\n");
+ diag_printf("Error: NAND flash hasn't been initialized\n");
#endif
- return;
+ return;
+ }
}
if (argc < 2) {