LK: Add support to write on modem partition
Modem nand layout is different from Android nand layout. This change
updates lk nand driver to write on modem nand partitions.
diff --git a/platform/msm_shared/nand.c b/platform/msm_shared/nand.c
index 6e5a86f..40b080c 100755
--- a/platform/msm_shared/nand.c
+++ b/platform/msm_shared/nand.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -69,6 +69,8 @@
#define NAND_CFG1_RAW 0x5045D
static unsigned CFG0, CFG1;
+static unsigned CFG0_M, CFG1_M;
+static unsigned CFG0_A, CFG1_A;
#define CFG1_WIDE_FLASH (1U << 1)
@@ -137,6 +139,19 @@
/* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash */
/* Note: The First row will be filled at runtime during ONFI probe */
};
+static void set_nand_configuration(char type)
+{
+ if(type == TYPE_MODEM_PARTITION)
+ {
+ CFG0 = CFG0_M;
+ CFG1 = CFG1_M;
+ }
+ else
+ {
+ CFG0 = CFG0_A;
+ CFG1 = CFG1_A;
+ }
+}
static void flash_nand_read_id(dmov_s *cmdlist, unsigned *ptrlist)
{
@@ -525,6 +540,11 @@
unsigned n;
unsigned cwperpage;
cwperpage = (flash_pagesize >> 9);
+ unsigned modem_partition = 0;
+ if (CFG0 == CFG0_M)
+ {
+ modem_partition = 1;
+ }
data->cmd = NAND_CMD_PRG_PAGE;
data->addr0 = page << 16;
@@ -544,7 +564,10 @@
/* GO bit for the EXEC register */
data->exec = 1;
- data->ecc_cfg = 0x203;
+ if (modem_partition)
+ data->ecc_cfg = 0x1FF;
+ else
+ data->ecc_cfg = 0x203;
/* save existing ecc config */
cmd->cmd = CMD_OCB;
@@ -581,15 +604,20 @@
cmd->cmd = 0;
cmd->dst = NAND_FLASH_BUFFER;
if (!raw_mode){
- cmd->src = addr + n * 516;
- cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
+ if(modem_partition){
+ cmd->src = addr + n * 512;
+ cmd->len = 512;
+ }else{
+ cmd->src = addr + n * 516;
+ cmd->len = ((n < (cwperpage - 1)) ? 516 : (512 - ((cwperpage - 1) << 2)));
+ }
}else{
cmd->src = addr;
cmd->len = 528;
}
cmd++;
- if ((n == (cwperpage - 1)) && (!raw_mode)) {
+ if ((n == (cwperpage - 1)) && (!raw_mode) && (!modem_partition)) {
/* write extra data */
cmd->cmd = 0;
cmd->src = spareaddr;
@@ -677,30 +705,33 @@
static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist)
{
+ static unsigned CFG0_TMP, CFG1_TMP;
cmdlist[0].cmd = CMD_OCB;
cmdlist[0].src = NAND_DEV0_CFG0;
- cmdlist[0].dst = paddr(&CFG0);
+ cmdlist[0].dst = paddr(&CFG0_TMP);
cmdlist[0].len = 4;
cmdlist[1].cmd = CMD_OCU | CMD_LC;
cmdlist[1].src = NAND_DEV0_CFG1;
- cmdlist[1].dst = paddr(&CFG1);
+ cmdlist[1].dst = paddr(&CFG1_TMP);
cmdlist[1].len = 4;
*ptrlist = (paddr(cmdlist) >> 3) | CMD_PTR_LP;
dmov_exec_cmdptr(DMOV_NAND_CHAN, ptrlist);
- if((CFG0 == 0) || (CFG1 == 0)) {
+ if((CFG0_TMP == 0) || (CFG1_TMP == 0)) {
return -1;
}
+ CFG0_A = CFG0_TMP;
+ CFG1_A = CFG1_TMP;
if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
nand_cfg1 |= CFG1_WIDE_FLASH;
}
dprintf(INFO, "nandcfg: %x %x (initial)\n", CFG0, CFG1);
- CFG0 = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
+ CFG0_A = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
| (516 << 9) /* 516 user data bytes */
| (10 << 19) /* 10 parity bytes */
| (5 << 27) /* 5 address cycles */
@@ -708,7 +739,7 @@
| (1 << 31) /* Send read cmd */
/* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */
| ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) : (1 << 23));
- CFG1 = (0 << 0) /* Enable ecc */
+ CFG1_A = (0 << 0) /* Enable ecc */
| (7 << 2) /* 8 recovery cycles */
| (0 << 5) /* Allow CS deassertion */
| ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
@@ -716,8 +747,28 @@
| (2 << 17) /* 6 cycle tWB/tRB */
| (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
- dprintf(INFO, "nandcfg: %x %x (used)\n", CFG0, CFG1);
+ dprintf(INFO, "nandcfg(Apps): %x %x (used)\n", CFG0_A, CFG1_A);
+ CFG0_M = CFG0_TMP;
+ CFG1_M = CFG1_TMP;
+ if (flash_info.type == FLASH_16BIT_NAND_DEVICE) {
+ nand_cfg1 |= CFG1_WIDE_FLASH;
+ }
+ CFG0_M = (((flash_pagesize >> 9) - 1) << 6) /* 4/8 cw/pg for 2/4k */
+ | (512 << 9) /* 512 user data bytes */
+ | (10 << 19) /* 10 parity bytes */
+ | (5 << 27) /* 5 address cycles */
+ | (0 << 30) /* Do not read status before data */
+ | (1 << 31) /* Send read cmd */
+ | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (4 << 23) : (5 << 23));
+ CFG1_M = (0 << 0) /* Enable ecc */
+ | (7 << 2) /* 8 recovery cycles */
+ | (0 << 5) /* Allow CS deassertion */
+ | ((flash_pagesize - (528 * ((flash_pagesize >> 9) - 1)) + 1) << 6) /* Bad block marker location */
+ | (0 << 16) /* Bad block in user data area */
+ | (2 << 17) /* 6 cycle tWB/tRB */
+ | (nand_cfg1 & CFG1_WIDE_FLASH); /* preserve wide flash flag */
+ dprintf(INFO, "nandcfg(Modem): %x %x (used)\n", CFG0_M, CFG1_M);
return 0;
}
@@ -2244,6 +2295,7 @@
unsigned block = ptn->start;
unsigned count = ptn->length;
+ set_nand_configuration(ptn->type);
while(count-- > 0) {
if(flash_erase_block(flash_cmdlist, flash_ptrlist, block * 64)) {
dprintf(INFO, "cannot erase @ %d (bad block?)\n", block);
@@ -2267,6 +2319,9 @@
int result = 0;
int isbad = 0;
+ ASSERT(ptn->type == TYPE_APPS_PARTITION);
+ set_nand_configuration(TYPE_APPS_PARTITION);
+
if(offset & (flash_pagesize - 1))
return -1;
@@ -2323,6 +2378,13 @@
unsigned n;
int r;
+ if ((flash_info.type == FLASH_ONENAND_DEVICE) && (ptn->type == TYPE_MODEM_PARTITION))
+ {
+ dprintf(CRITICAL, "flash_write_image: feature not supported\n");
+ return -1;
+ }
+
+ set_nand_configuration(ptn->type);
for(n = 0; n < 16; n++) spare[n] = 0xffffffff;
while(bytes > 0) {
@@ -2356,7 +2418,9 @@
if(flash_erase_block(flash_cmdlist, flash_ptrlist, page)) {
dprintf(INFO, "flash_write_image: erase failure @ page %d\n", page);
}
- flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
+ if (ptn->type != TYPE_MODEM_PARTITION) {
+ flash_mark_badblock(flash_cmdlist, flash_ptrlist, page);
+ }
dprintf(INFO, "flash_write_image: restart write @ page %d (src %d)\n", page, image - (const unsigned char *)data);
page += 64;
continue;