view loadtools/flutil.c @ 275:cedf09b6b5ac

started laying the foundation for fc-fsio host utility
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 23 Feb 2014 20:27:15 +0000
parents cd12d1049f91
children f027c6fbe37e
line wrap: on
line source

/*
 * Miscellaneous utility functions for flash support
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "flash.h"

extern struct flash_bank_info flash_bank_info[2];

compute_flash_totsize_nsecs(bank)
{
	struct flash_bank_info *bi;
	struct flash_region_desc *reg;

	bi = flash_bank_info + bank;
	for (reg = bi->bank_desc->regions; reg->nsectors; reg++) {
		bi->nsectors += reg->nsectors;
		bi->total_size += reg->sector_size * reg->nsectors;
	}
}

/* the following function is used to verify that total_size is a power of 2 */
count_ones(word)
	uint32_t word;
{
	int count;

	for (count = 0; word; word >>= 1)
		count += word & 1;
	return count;
}

get_flash_sector_table(bank)
{
	struct flash_bank_info *bi;
	struct flash_region_desc *reg;
	struct sector_info *sp;
	uint32_t offset;
	int i;

	bi = flash_bank_info + bank;
	if (bi->sectors)
		return(0);
	sp = (struct sector_info *) malloc(sizeof(struct sector_info)
						* (bi->nsectors + 1));
	if (!sp) {
		fprintf(stderr,
		"unable to malloc buffer for flash bank %d sector table\n",
			bank);
		return(-1);
	}
	bi->sectors = sp;
	/* now fill it */
	offset = 0;
	for (reg = bi->bank_desc->regions; reg->nsectors; reg++) {
		for (i = 0; i < reg->nsectors; i++) {
			sp->start = offset;
			sp->size = reg->sector_size;
			sp++;
			offset += reg->sector_size;
		}
	}
	/* sanity checks */
	if (sp - bi->sectors != bi->nsectors) {
		fprintf(stderr,
	"BUG in get_flash_sector_table(): wrong # of sectors at the end\n");
		abort();
	}
	if (offset != bi->total_size) {
		fprintf(stderr,
		"BUG in get_flash_sector_table(): wrong offset at the end\n");
		abort();
	}
	/* finish */
	sp->start = 0;
	sp->size = 0;
	return(0);
}

flashcmd_sectors(argc, argv, bank)
	char **argv;
{
	struct flash_bank_info *bi;
	struct sector_info *sp;

	if (argc > 2) {
		fprintf(stderr, "error: too many arguments\n");
		return(-1);
	}
	if (get_flash_sector_table(bank) < 0)
		return(-1);
	bi = flash_bank_info + bank;
	printf("%u sectors in flash bank %d:\n", bi->nsectors, bank);
	printf("Offset    Size\n");
	for (sp = bi->sectors; sp->size; sp++)
		printf("%08lX  %lx\n", (u_long) sp->start, (u_long) sp->size);
	return(0);
}

get_flash_sector_range(bi, useroff, userlen, startp, endp)
	struct flash_bank_info *bi;
	u_long useroff, userlen;
	struct sector_info **startp, **endp;
{
	struct sector_info *sp;
	uint32_t remlen;

	for (sp = bi->sectors; sp->size; sp++)
		if (sp->start == useroff)
			break;
	if (!sp->size) {
		fprintf(stderr,
	"error: specified offset not aligned to a flash sector boundary\n");
		return(-1);
	}
	*startp = sp;
	for (remlen = userlen; remlen; ) {
		if (remlen < sp->size) {
			fprintf(stderr,
	"error: specified length not aligned to a flash sector boundary\n");
			return(-1);
		}
		remlen -= sp->size;
		sp++;
	}
	*endp = sp;
	return(0);
}

build_flashw_hex_string(bin, strbuf, nwords, m0src)
	u_char *bin;
	char *strbuf;
	int nwords, m0src;
{
	int i;
	u_char *dp;
	char *s;

	for (dp = bin, s = strbuf, i = 0; i < nwords; dp += 2, s += 4, i++) {
		if (m0src)
			sprintf(s, "%02X%02X", dp[0], dp[1]);
		else
			sprintf(s, "%02X%02X", dp[1], dp[0]);
	}
	*s = '\0';
}

flash_id_check(bank, repeat)
{
	struct flash_bank_info *bi;
	struct flash_bank_desc *bd;
	struct flash_idcheck *id;
	int stat, fail;
	uint16_t rdval;
	unsigned cnt;

	bi = flash_bank_info + bank;
	if (bi->idcheck_done && !repeat)
		return(0);
	printf("Performing flash ID check\n");
	stat = do_w16(bi->base_addr + 0xAAA, 0xAA);
	if (stat) {
bad_w16:	fprintf(stderr,
	"unexpected response to w16 in read ID cmd sequence - aborting\n");
		return(-1);
	}
	stat = do_w16(bi->base_addr + 0x554, 0x55);
	if (stat)
		goto bad_w16;
	stat = do_w16(bi->base_addr + 0xAAA, 0x90);
	if (stat)
		goto bad_w16;
	bd = bi->bank_desc;
	id = bd->idcheck_table;
	fail = 0;
	for (cnt = 0; cnt < bd->idcheck_num; cnt++) {
		stat = do_r16(bi->base_addr + id->offset, &rdval);
		if (stat)
			return(stat);	/* error msg already printed */
		printf("offset %02X: %04X -- ", (int)id->offset, (int)rdval);
		if (rdval == id->expect_val)
			printf("PASS\n");
		else {
			printf("FAIL: expected %04X\n", (int)id->expect_val);
			fail = 1;
			break;
		}
		id++;
	}
	/* reset flash to read mode */
	stat = do_w16(bi->base_addr + 0xAAA, 0xF0);
	if (stat) {
		fprintf(stderr,
	"unexpected response to w16 when resetting flash to read mode!\n");
		return(-1);
	}
	if (fail)
		return(-1);
	bi->idcheck_done = 1;
	return(0);
}