diff loadtools/ltflash.c @ 400:f027c6fbe37e

fc-loadtool flash: first round of refactoring for CFI
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 15 Jun 2014 20:05:54 +0000
parents cd12d1049f91
children 7ceeec049be4
line wrap: on
line diff
--- a/loadtools/ltflash.c	Sun Jun 15 00:47:06 2014 +0000
+++ b/loadtools/ltflash.c	Sun Jun 15 20:05:54 2014 +0000
@@ -1,6 +1,6 @@
 /*
- * In this module we are going to implement the flash operation commands
- * of fc-loadtool.
+ * This module contains the "core" of fc-loadtool flash operations;
+ * fl*.c modules contain the rest.
  */
 
 #include <sys/types.h>
@@ -13,11 +13,12 @@
 
 /* K5A32xx device description */
 
-static struct flash_region_desc k5a32xx_topboot_regions[] = {
-	/* 4 MiB total, 64 KiB sectors except for the boot block of 8x 8 KiB */
-	{0x10000, 63},
-	{0x2000, 8},
-	{0, 0}		/* array terminator */
+static struct cfi_info k5a32xx_topboot_hardcfi = {
+	.cmdset_style	= 2,
+	.total_size	= 0x400000,
+	.nregions	= 2,
+	.regions	= {0x10000, 63, 0x2000, 8},
+	.total_sectors	= 71
 };
 
 static struct flash_idcheck k5a32xx_topboot_idcheck[2] = {
@@ -26,23 +27,25 @@
 };
 
 static struct flash_bank_desc k5a32xx_topboot_bankdesc = {
-	k5a32xx_topboot_regions, 0xFFF00000, k5a32xx_topboot_idcheck, 2
+	0x400000, &k5a32xx_topboot_hardcfi, k5a32xx_topboot_idcheck, 2
 };
 
 /* S{29,71}PL129N device description */
 
-static struct flash_region_desc pl129n_ce1_regions[] = {
-	/* 4 sectors of 64 KiB each at the beginning, then 256 KiB sectors */
-	{0x10000, 4},
-	{0x40000, 31},
-	{0, 0}		/* array terminator */
+static struct cfi_info pl129n_ce1_hardcfi = {
+	.cmdset_style	= 2,
+	.total_size	= 0x800000,
+	.nregions	= 2,
+	.regions	= {0x10000, 4, 0x40000, 31},
+	.total_sectors	= 35
 };
 
-static struct flash_region_desc pl129n_ce2_regions[] = {
-	/* the other way around now */
-	{0x40000, 31},
-	{0x10000, 4},
-	{0, 0}		/* array terminator */
+static struct cfi_info pl129n_ce2_hardcfi = {
+	.cmdset_style	= 2,
+	.total_size	= 0x800000,
+	.nregions	= 2,
+	.regions	= {0x40000, 31, 0x10000, 4},
+	.total_sectors	= 35
 };
 
 static struct flash_idcheck pl129n_idcheck[4] = {
@@ -53,8 +56,8 @@
 };
 
 static struct flash_bank_desc pl129n_banks[2] = {
-	{pl129n_ce1_regions, 0xFFFC0000, pl129n_idcheck, 4},
-	{pl129n_ce2_regions, 0xFFFC0000, pl129n_idcheck, 4}
+	{0x800000, &pl129n_ce1_hardcfi, pl129n_idcheck, 4},
+	{0x800000, &pl129n_ce2_hardcfi, pl129n_idcheck, 4}
 };
 
 /* list of supported flash devices */
@@ -130,20 +133,14 @@
 		}
 		/* the rest comes from the flash device type */
 		bi->bank_desc = selected_flash_device->bank_desc + bank;
-		compute_flash_totsize_nsecs(bank);
-		if (count_ones(bi->total_size) != 1) {
-			fprintf(stderr,
-"fc-loadtool internal bug: flash bank %d size for %s is not a power of 2\n",
-				bank, selected_flash_device->name);
-			exit(1);
-		}
-		if (bi->base_addr & (bi->total_size - 1)) {
+		if (bi->base_addr & (bi->bank_desc->align_size - 1)) {
 			fprintf(stderr,
 "%s line %d: flash bank %d base addr is not aligned to the bank size (0x%lx)\n",
 				filename_for_errs, lineno_for_errs, bank,
-				(u_long) bi->total_size);
+				(u_long) bi->bank_desc->align_size);
 			exit(1);
 		}
+		bi->cfi = bi->bank_desc->hard_cfi;
 	}
 	while (isspace(*cp))
 		cp++;
@@ -171,20 +168,22 @@
 	offset = strtoul(argv[2], &strtoul_endp, 16);
 	if (*strtoul_endp)
 		goto inv;
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
 	bi = flash_bank_info + bank;
-	if (offset >= bi->total_size) {
+	if (offset >= bi->cfi->total_size) {
 		fprintf(stderr,
 		"error: specified offset exceeds flash bank size (0x%lx)\n",
-			(u_long) bi->total_size);
+			(u_long) bi->cfi->total_size);
 		return(-1);
 	}
 	len = strtoul(argv[3], &strtoul_endp, 16);
 	if (*strtoul_endp)
 		goto inv;
-	if (len > bi->total_size - offset) {
+	if (len > bi->cfi->total_size - offset) {
 		fprintf(stderr,
 	"error: specified offset+length exceed flash bank size (0x%lx)\n",
-			(u_long) bi->total_size);
+			(u_long) bi->cfi->total_size);
 		return(-1);
 	}
 	sprintf(targ_start, "%lx", (u_long) bi->base_addr + offset);
@@ -212,20 +211,22 @@
 			argv[0], argv[1]);
 		return(-1);
 	}
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
 	bi = flash_bank_info + bank;
 	if (argc >= 4) {
 		offset = strtoul(argv[3], &strtoul_endp, 16);
 		if (*strtoul_endp)
 			goto inv;
-		if (offset >= bi->total_size) {
+		if (offset >= bi->cfi->total_size) {
 			fprintf(stderr,
 		"error: specified offset exceeds flash bank size (0x%lx)\n",
-				(u_long) bi->total_size);
+				(u_long) bi->cfi->total_size);
 			return(-1);
 		}
 	} else
 		offset = 0;
-	maxlen = bi->total_size - offset;
+	maxlen = bi->cfi->total_size - offset;
 	if (argc >= 5) {
 		dumplen = strtoul(argv[4], &strtoul_endp, 16);
 		if (*strtoul_endp)
@@ -233,7 +234,7 @@
 		if (dumplen > maxlen) {
 			fprintf(stderr,
 	"error: specified offset+length exceed flash bank size (0x%lx)\n",
-				(u_long) bi->total_size);
+				(u_long) bi->cfi->total_size);
 			return(-1);
 		}
 	} else
@@ -271,8 +272,11 @@
 	bi = flash_bank_info + bank;
 	printf("Flash device type: %s\n", selected_flash_device->name);
 	printf("Bank %d base address: %08lX\n", bank, (u_long) bi->base_addr);
-	printf("Bank %d total size: %lx\n", bank, (u_long) bi->total_size);
-	printf("Sectors in bank %d: %u\n", bank, bi->nsectors);
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	printf("Bank %d total size: %lx\n", bank, (u_long) bi->cfi->total_size);
+	printf("Sectors in bank %d: %u (%u regions)\n", bank,
+		bi->cfi->total_sectors, bi->cfi->nregions);
 	flash_id_check(bank, 1);
 	if (selected_flash_device->nbanks == 2 && !bank)
 	    printf("\nFlash device has 2 banks; flash2 command available\n");
@@ -285,8 +289,15 @@
 	char *targv[4], targ_base[10];
 	int stat;
 
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	if (flash_bank_info[bank].cfi->cmdset_style != 2) {
+		fprintf(stderr,
+"error: this command is currently only implemented for AMD-style flash\n");
+		return(-1);
+	}
 	if (argc != 4) {
-inv:		fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n",
+		fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n",
 			argv[0], argv[1]);
 		return(-1);
 	}