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/app/aboot/aboot.c b/app/aboot/aboot.c
index 6d6cf1c..3eac025 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -90,6 +90,8 @@
 {
 	struct atag_ptbl_entry atag_ptn;
 
+	if (ptn->type == TYPE_MODEM_PARTITION)
+		return;
 	memcpy(atag_ptn.name, ptn->name, 16);
 	atag_ptn.name[15] = '\0';
 	atag_ptn.offset = ptn->start;
@@ -104,6 +106,7 @@
 		void *ramdisk, unsigned ramdisk_size)
 {
 	unsigned *ptr = tags;
+	unsigned pcount = 0;
 	void (*entry)(unsigned,unsigned,unsigned*) = kernel;
 	struct ptable *ptable;
 	int cmdline_len = 0;
@@ -126,7 +129,13 @@
 		/* Skip NAND partition ATAGS for eMMC boot */
 		if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
 			int i;
-			*ptr++ = 2 + (ptable->count * (sizeof(struct atag_ptbl_entry) /
+			for(i=0; i < ptable->count; i++) {
+				struct ptentry *ptn;
+				ptn =  ptable_get(ptable, i);
+				if (ptn->type == TYPE_APPS_PARTITION)
+					pcount++;
+			}
+			*ptr++ = 2 + (pcount * (sizeof(struct atag_ptbl_entry) /
 						       sizeof(unsigned)));
 			*ptr++ = 0x4d534d70;
 			for (i = 0; i < ptable->count; ++i)
diff --git a/include/lib/ptable.h b/include/lib/ptable.h
index 0883b8c..07fbf80 100644
--- a/include/lib/ptable.h
+++ b/include/lib/ptable.h
@@ -2,6 +2,8 @@
  * Copyright (c) 2008, Google Inc.
  * 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
  * are met:
@@ -34,14 +36,20 @@
  * (flash erase units)
  */
 #define MAX_PTENTRY_NAME	16
-#define MAX_PTABLE_PARTS	16
+#define MAX_PTABLE_PARTS	32
 
+#define TYPE_MODEM_PARTITION	1
+#define TYPE_APPS_PARTITION	0
+#define PERM_NON_WRITEABLE	0
+#define PERM_WRITEABLE		1
 struct ptentry
 {
 	char name[MAX_PTENTRY_NAME];
 	unsigned start;
 	unsigned length;
 	unsigned flags;
+	char type;
+	char perm;
 };
 
 struct ptable
@@ -53,7 +61,7 @@
 /* tools to populate and query the partition table */
 void ptable_init(struct ptable *ptable);
 void ptable_add(struct ptable *ptable, char *name, unsigned start,
-		unsigned length, unsigned flags);
+		unsigned length, unsigned flags, char type, char perm);
 struct ptentry *ptable_find(struct ptable *ptable, const char *name);
 struct ptentry *ptable_get(struct ptable *ptable, int n);
 int ptable_size(struct ptable *ptable);
diff --git a/lib/ptable/ptable.c b/lib/ptable/ptable.c
index 9648ef5..3ddf5fa 100644
--- a/lib/ptable/ptable.c
+++ b/lib/ptable/ptable.c
@@ -2,6 +2,8 @@
  * Copyright (C) 2008 The Android Open Source Project
  * 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
  * are met:
@@ -38,8 +40,11 @@
 	memset(ptable, 0, sizeof(struct ptable));
 }
 
+char* ptype[] = {"Apps", "Modem"};
+char* pperm[] = {"No", "Yes"};
+
 void ptable_add(struct ptable *ptable, char *name, unsigned start,
-		unsigned length, unsigned flags)
+		unsigned length, unsigned flags, char type, char perm)
 {
 	struct ptentry *ptn;
 
@@ -50,6 +55,8 @@
 	ptn->start = start;
 	ptn->length = length;
 	ptn->flags = flags;
+	ptn->type = type;
+	ptn->perm = perm;
 }
 
 void ptable_dump(struct ptable *ptable)
@@ -60,8 +67,8 @@
 	for (i = 0; i < ptable->count; ++i) {
 		ptn = &ptable->parts[i];
 		dprintf(INFO, "ptn %d name='%s' start=%08x len=%08x "
-			"flags=%08x\n", i, ptn->name, ptn->start, ptn->length,
-			ptn->flags);
+			"flags=%08x type=%s Writable=%s\n", i, ptn->name, ptn->start, ptn->length,
+			ptn->flags, ptype[ptn->type], pperm[ptn->perm]);
 	}
 }
 
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;
diff --git a/platform/msm_shared/smem_ptable.c b/platform/msm_shared/smem_ptable.c
index 1e07532..de4422d 100644
--- a/platform/msm_shared/smem_ptable.c
+++ b/platform/msm_shared/smem_ptable.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2009, Google Inc.
  * 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
  * are met:
@@ -31,6 +33,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <platform/iomap.h>
+#include <lib/ptable.h>
 
 #include "smem.h"
 
@@ -100,3 +103,33 @@
 {
 	return smem_apps_flash_start;
 }
+
+void smem_add_modem_partitions(struct ptable *flash_ptable)
+{
+	int i;
+
+	if (smem_ptable.magic[0] != _SMEM_PTABLE_MAGIC_1 ||
+	    smem_ptable.magic[1] != _SMEM_PTABLE_MAGIC_2)
+		return;
+
+	for (i = 0; i < 16; i++)
+	{
+		char * token;
+		char * pname = NULL;
+		struct smem_ptn *p = &smem_ptable.parts[i];
+			if (p->name[0] == '\0')
+				continue;
+		token = strtok(p->name, ":");
+		while (token)
+		{
+			pname = token;
+			token = strtok (NULL, ":");
+		}
+		if(pname)
+		{
+			ptable_add(flash_ptable, pname, p->start,
+				   p->size, 0, TYPE_MODEM_PARTITION, PERM_WRITEABLE);
+		}
+	}
+}
+
diff --git a/target/msm7625_ffa/init.c b/target/msm7625_ffa/init.c
index 546cc02..e686d5b 100644
--- a/target/msm7625_ffa/init.c
+++ b/target/msm7625_ffa/init.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2009, 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
@@ -119,9 +119,11 @@
 		if ((len == 0) && (i == num_parts - 1))
 			len = flash_info->num_blocks - offset - ptn->start;
 		ptable_add(&flash_ptable, ptn->name, offset + ptn->start,
-			   len, ptn->flags);
+			   len, ptn->flags, TYPE_APPS_PARTITION, PERM_WRITEABLE);
 	}
 
+	smem_add_modem_partitions(&flash_ptable);
+
 	ptable_dump(&flash_ptable);
 	flash_set_ptable(&flash_ptable);
 }
diff --git a/target/msm7625_surf/init.c b/target/msm7625_surf/init.c
index 9bdd729..01a8a46 100644
--- a/target/msm7625_surf/init.c
+++ b/target/msm7625_surf/init.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2009, 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
@@ -119,9 +119,11 @@
 		if ((len == 0) && (i == num_parts - 1))
 			len = flash_info->num_blocks - offset - ptn->start;
 		ptable_add(&flash_ptable, ptn->name, offset + ptn->start,
-			   len, ptn->flags);
+			   len, ptn->flags, TYPE_APPS_PARTITION, PERM_WRITEABLE);
 	}
 
+	smem_add_modem_partitions(&flash_ptable);
+
 	ptable_dump(&flash_ptable);
 	flash_set_ptable(&flash_ptable);
 }
diff --git a/target/msm7627_ffa/init.c b/target/msm7627_ffa/init.c
index 02d4de9..6c9ea7d 100644
--- a/target/msm7627_ffa/init.c
+++ b/target/msm7627_ffa/init.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2009, 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
@@ -152,9 +152,11 @@
 			next_ptr_start_adr = ptn->start + ptn->length;
 		}
 		ptable_add(&flash_ptable, ptn->name, offset + ptn->start,
-			   len, ptn->flags);
+			   len, ptn->flags, TYPE_APPS_PARTITION, PERM_WRITEABLE);
 	}
 
+	smem_add_modem_partitions(&flash_ptable);
+
 	ptable_dump(&flash_ptable);
 	flash_set_ptable(&flash_ptable);
 }
diff --git a/target/msm7627_surf/init.c b/target/msm7627_surf/init.c
index 89451cb..9014e2d 100644
--- a/target/msm7627_surf/init.c
+++ b/target/msm7627_surf/init.c
@@ -157,9 +157,11 @@
 			next_ptr_start_adr = ptn->start + ptn->length;
 		}
 		ptable_add(&flash_ptable, ptn->name, offset + ptn->start,
-			   len, ptn->flags);
+			   len, ptn->flags, TYPE_APPS_PARTITION, PERM_WRITEABLE);
 	}
 
+	smem_add_modem_partitions(&flash_ptable);
+
 	ptable_dump(&flash_ptable);
 	flash_set_ptable(&flash_ptable);
 }
diff --git a/target/msm7630_surf/init.c b/target/msm7630_surf/init.c
index 132fe66..75ac749 100644
--- a/target/msm7630_surf/init.c
+++ b/target/msm7630_surf/init.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2009, 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
@@ -165,9 +165,11 @@
 			next_ptr_start_adr = ptn->start + ptn->length;
 		}
 		ptable_add(&flash_ptable, ptn->name, offset + ptn->start,
-			   len, ptn->flags);
+			   len, ptn->flags, TYPE_APPS_PARTITION, PERM_WRITEABLE);
 	}
 
+	smem_add_modem_partitions(&flash_ptable);
+
 	ptable_dump(&flash_ptable);
 	flash_set_ptable(&flash_ptable);
 }
diff --git a/target/qsd8250_ffa/init.c b/target/qsd8250_ffa/init.c
index 7eb10e8..b44014d 100644
--- a/target/qsd8250_ffa/init.c
+++ b/target/qsd8250_ffa/init.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2009, 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
@@ -144,9 +144,11 @@
 			next_ptr_start_adr = ptn->start + ptn->length;
 		}
 		ptable_add(&flash_ptable, ptn->name, offset + ptn->start,
-			   len, ptn->flags);
+			   len, ptn->flags, TYPE_APPS_PARTITION, PERM_WRITEABLE);
 	}
 
+	smem_add_modem_partitions(&flash_ptable);
+
 	ptable_dump(&flash_ptable);
 	flash_set_ptable(&flash_ptable);
 }
diff --git a/target/qsd8250_surf/init.c b/target/qsd8250_surf/init.c
index 08c5470..0b3b0cd 100644
--- a/target/qsd8250_surf/init.c
+++ b/target/qsd8250_surf/init.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2009, 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
@@ -143,9 +143,11 @@
 			next_ptr_start_adr = ptn->start + ptn->length;
 		}
 		ptable_add(&flash_ptable, ptn->name, offset + ptn->start,
-			   len, ptn->flags);
+			   len, ptn->flags, TYPE_APPS_PARTITION, PERM_WRITEABLE);
 	}
 
+	smem_add_modem_partitions(&flash_ptable);
+
 	ptable_dump(&flash_ptable);
 	flash_set_ptable(&flash_ptable);
 }