diff options
Diffstat (limited to 'post/drivers/flash.c')
| -rw-r--r-- | post/drivers/flash.c | 107 | 
1 files changed, 107 insertions, 0 deletions
| diff --git a/post/drivers/flash.c b/post/drivers/flash.c new file mode 100644 index 000000000..07eab332d --- /dev/null +++ b/post/drivers/flash.c @@ -0,0 +1,107 @@ +/* + * Parallel NOR Flash tests + * + * Copyright (c) 2005-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <malloc.h> +#include <post.h> +#include <flash.h> + +#if CONFIG_POST & CONFIG_SYS_POST_FLASH + +/* + * This code will walk over the declared sectors erasing them, + * then programming them, then verifying the written contents. + * Possible future work: + *  - verify sectors before/after are not erased/written + *  - verify partial writes (e.g. programming only middle of sector) + *  - verify the contents of the erased sector + *  - better seed pattern than 0x00..0xff + */ + +#ifndef CONFIG_SYS_POST_FLASH_NUM +# define CONFIG_SYS_POST_FLASH_NUM 0 +#endif +#if CONFIG_SYS_POST_FLASH_START >= CONFIG_SYS_POST_FLASH_END +# error "invalid flash block start/end" +#endif + +extern flash_info_t flash_info[]; + +static void *seed_src_data(void *ptr, ulong *old_len, ulong new_len) +{ +	unsigned char *p; +	ulong i; + +	p = ptr = realloc(ptr, new_len); +	if (!ptr) +		return ptr; + +	for (i = *old_len; i < new_len; ++i) +		p[i] = i; + +	*old_len = new_len; + +	return ptr; +} + +int flash_post_test(int flags) +{ +	ulong len; +	void *src; +	int ret, n, n_start, n_end; +	flash_info_t *info; + +	/* the output from the common flash layers needs help */ +	puts("\n"); + +	len = 0; +	src = NULL; +	info = &flash_info[CONFIG_SYS_POST_FLASH_NUM]; +	n_start = CONFIG_SYS_POST_FLASH_START; +	n_end = CONFIG_SYS_POST_FLASH_END; + +	for (n = n_start; n < n_end; ++n) { +		ulong s_start, s_len, s_off; + +		s_start = info->start[n]; +		s_len = flash_sector_size(info, n); +		s_off = s_start - info->start[0]; + +		src = seed_src_data(src, &len, s_len); +		if (!src) { +			printf("malloc(%#lx) failed\n", s_len); +			return 1; +		} + +		printf("\tsector %i: %#lx +%#lx", n, s_start, s_len); + +		ret = flash_erase(info, n, n + 1); +		if (ret) { +			flash_perror(ret); +			break; +		} + +		ret = write_buff(info, src, s_start, s_len); +		if (ret) { +			flash_perror(ret); +			break; +		} + +		ret = memcmp(src, (void *)s_start, s_len); +		if (ret) { +			printf(" verify failed with %i\n", ret); +			break; +		} +	} + +	free(src); + +	return ret; +} + +#endif |