Ejemplo n.º 1
0
static int flash_toggle(struct flash_info *info, flash_sect_t sect,
		unsigned int offset, u8 cmd)
{
	void *addr;
	cfiword_t cword;
	int retval;

	addr = flash_make_addr (info, sect, offset);
	flash_make_cmd (info, cmd, &cword);

	if (bankwidth_is_1(info)) {
		retval = flash_read8(addr) != flash_read8(addr);
	} else if (bankwidth_is_2(info)) {
		retval = flash_read16(addr) != flash_read16(addr);
	} else if (bankwidth_is_4(info)) {
		retval = flash_read32(addr) != flash_read32(addr);
	} else if (bankwidth_is_8(info)) {
		retval = ( (flash_read32( addr ) != flash_read32( addr )) ||
			   (flash_read32(addr+4) != flash_read32(addr+4)) );
	} else {
		retval = 0;
	}

	return retval;
}
Ejemplo n.º 2
0
/*-----------------------------------------------------------------------
 * read a short word by swapping for ppc format.
 */
ushort flash_read_ushort(flash_info_t * info, int sect, uchar offset)
{
	uchar *addr;

	addr = flash_make_addr(info, sect, offset);
	return ((addr[(2 * info->portwidth) - 1] << 8) |
		addr[info->portwidth - 1]);

}
Ejemplo n.º 3
0
static uint8_t flash_read_uint8_t(flash_info_t * info, uint32_t offset)
{
    uint8_t *cp;

    cp = flash_make_addr(info, 0, offset);
#if defined(__LITTLE_ENDIAN)
    return (cp[0]);
#else
    return (cp[info->portwidth - 1]);
#endif
}
Ejemplo n.º 4
0
/*-----------------------------------------------------------------------
 * read a long word by picking the least significant byte of each maiximum
 * port size word. Swap for ppc format.
 */
ulong flash_read_long(flash_info_t * info, int sect, uchar offset)
{
	uchar *addr;

	addr = flash_make_addr(info, sect, offset);
	return ((addr[(2 * info->portwidth) - 1] << 24) |
		(addr[(info->portwidth) - 1] << 16) |
		(addr[(4 * info->portwidth) - 1] << 8) |
		addr[(3 * info->portwidth) - 1]);

}
Ejemplo n.º 5
0
/*-----------------------------------------------------------------------
 */
static int flash_write_cfiword(flash_info_t * info, ulong dest, cfiword_t cword)
{

	cfiptr_t ctladdr;
	cfiptr_t cptr;
	int flag;

	ctladdr.cp = flash_make_addr(info, 0, 0);
	cptr.cp = (uchar *) dest;

	/* Check if Flash is (sufficiently) erased */
	switch (info->portwidth) {
	case FLASH_CFI_8BIT:
		flag = ((cptr.cp[0] & cword.c) == cword.c);
		break;
	case FLASH_CFI_16BIT:
		flag = ((cptr.wp[0] & cword.w) == cword.w);
		break;
	case FLASH_CFI_32BIT:
		flag = ((cptr.lp[0] & cword.l) == cword.l);
		break;
	default:
		return 2;
	}
	if (!flag)
		return 2;

	/* Disable interrupts which might cause a timeout here */
	flag = disable_interrupts();

	flash_write_cmd(info, 0, 0, FLASH_CMD_CLEAR_STATUS);
	flash_write_cmd(info, 0, 0, FLASH_CMD_WRITE);

	switch (info->portwidth) {
	case FLASH_CFI_8BIT:
		cptr.cp[0] = cword.c;
		break;
	case FLASH_CFI_16BIT:
		cptr.wp[0] = cword.w;
		break;
	case FLASH_CFI_32BIT:
		cptr.lp[0] = cword.l;
		break;
	}

	/* re-enable interrupts if necessary */
	if (flag)
		enable_interrupts();

	return flash_full_status_check(info, 0, info->write_tout, "write");
}
Ejemplo n.º 6
0
static int32_t flash_detect_cfi(flash_info_t * info)
{
    cfiptr_t cptr1, cptr2, cptr3;

    for (info->portwidth = FLASH_CFI_8BIT;
         info->portwidth <= FLASH_CFI_16BIT; info->portwidth <<= 1) {
        for (info->chipwidth = FLASH_CFI_BY8;
             info->chipwidth <= info->portwidth; info->chipwidth <<= 1) {
            cptr1.cp = flash_make_addr(info, 0, FLASH_OFFSET_CFI_RESP);
            cptr2.cp = flash_make_addr(info, 0, FLASH_OFFSET_CFI_RESP + 1);
            cptr3.cp = flash_make_addr(info, 0, FLASH_OFFSET_CFI_RESP + 2);
            flash_write_cmd(info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI);
            if (flash_isequal(info, cptr1, 'Q')
                && flash_isequal(info, cptr2, 'R')
                && flash_isequal(info, cptr3, 'Y')) {
                info->interface = flash_read_uint16_t(info, 0, FLASH_OFFSET_INTERFACE);
                return 1;
            }
        }
    }
    printf("Error: CFI flah not found\n");
    return 0;
}
Ejemplo n.º 7
0
static uint16_t flash_read_uint16_t(flash_info_t * info, int32_t sect, uint32_t offset)
{
    uint8_t *addr;
    uint16_t retval;

    addr = flash_make_addr(info, sect, offset);

#if defined(__LITTLE_ENDIAN)
    retval = ((addr[(info->portwidth)] << 8) | addr[0]);
#else
    retval = (uint16_t) ((addr[(2 * info->portwidth) - 1] << 8) | addr[info->portwidth - 1]);
#endif

    return retval;
}
Ejemplo n.º 8
0
static void flash_write_cmd(flash_info_t * info, int32_t sect, uint32_t offset, uint8_t cmd)
{

    cfiptr_t addr;
    cfiword_t cword;

    addr.cp = flash_make_addr(info, sect, offset);
    flash_make_cmd(info, cmd, &cword);
    switch (info->portwidth) {
    case FLASH_CFI_8BIT:
        *addr.cp = cword.c;
        break;
    case FLASH_CFI_16BIT:
        *addr.wp = cword.w;
        break;
    }
}
Ejemplo n.º 9
0
static uint32_t flash_read_long(flash_info_t * info, int32_t sect, uint32_t offset)
{
    uint8_t *addr;
    uint32_t retval;

    addr = flash_make_addr(info, sect, offset);

#if defined(__LITTLE_ENDIAN)
    retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) |
        (addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8);
#else
    retval = (uint32_t) (addr[(2 * info->portwidth) - 1] << 24) |
        (addr[(info->portwidth) - 1] << 16) |
        (addr[(4 * info->portwidth) - 1] << 8) | addr[(3 * info->portwidth) - 1];
#endif
    return retval;
}
Ejemplo n.º 10
0
static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd)
{
	cfiptr_t cptr;
	cfiword_t cword;
	int retval;

	cptr.cp = flash_make_addr (info, sect, offset);
	flash_make_cmd (info, cmd, &cword);
	if (bankwidth_is_1(info)) {
		retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c));
	} else if (bankwidth_is_2(info)) {
		retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w));
	} else if (bankwidth_is_4(info)) {
		retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l));
	} else if (bankwidth_is_8(info)) {
		retval = ((cptr.llp[0] & cword.ll) !=
			  (cptr.llp[0] & cword.ll));
	} else
		retval = 0;

	return retval;
}
Ejemplo n.º 11
0
/*-----------------------------------------------------------------------
 */
static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd)
{
	cfiptr_t cptr;
	cfiword_t cword;
	int retval;
	cptr.cp = flash_make_addr(info, sect, offset);
	flash_make_cmd(info, cmd, &cword);
	switch (info->portwidth) {
	case FLASH_CFI_8BIT:
		retval = ((cptr.cp[0] & cword.c) == cword.c);
		break;
	case FLASH_CFI_16BIT:
		retval = ((cptr.wp[0] & cword.w) == cword.w);
		break;
	case FLASH_CFI_32BIT:
		retval = ((cptr.lp[0] & cword.l) == cword.l);
		break;
	default:
		retval = 0;
		break;
	}
	return retval;
}
Ejemplo n.º 12
0
static uint32_t flash_get_size(uint32_t base, int32_t banknum)
{
    flash_info_t *info = &flash_info[banknum];
    int32_t i, j;
    int32_t sect_cnt;
    uint32_t sector;
    uint32_t tmp;
    int32_t size_ratio;
    uint8_t num_erase_regions;
    int32_t erase_region_size;
    int32_t erase_region_count;
    cfiptr_t cptr;

    info->start[0] = base;

    if (flash_detect_cfi(info)) {
        info->vendor = flash_read_uint16_t(info, 0, FLASH_OFFSET_PRIMARY_VENDOR);
        switch (info->vendor) {
        case CFI_CMDSET_INTEL_STANDARD:
        case CFI_CMDSET_INTEL_EXTENDED:
        default:
            info->cmd_reset = FLASH_CMD_RESET;
            break;
        case CFI_CMDSET_AMD_STANDARD:
        case CFI_CMDSET_AMD_EXTENDED:
            info->cmd_reset = AMD_CMD_RESET;
            break;
        }

        size_ratio = info->portwidth / info->chipwidth;
        if ((info->interface == FLASH_CFI_X8X16)
            && (info->chipwidth == FLASH_CFI_BY8)) {
            size_ratio >>= 1;
        }
        num_erase_regions = flash_read_uint8_t(info, FLASH_OFFSET_NUM_ERASE_REGIONS);
        sect_cnt = 0;
        sector = base;
        for (i = 0; i < num_erase_regions; i++) {
            if (i > NUM_ERASE_REGIONS) {
                printf("%d erase regions found, only %d used\n",
                       num_erase_regions, NUM_ERASE_REGIONS);
                break;
            }
            tmp = flash_read_long(info, 0, FLASH_OFFSET_ERASE_REGIONS + i * 4);
            erase_region_size = (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
            tmp >>= 16;
            erase_region_count = (tmp & 0xffff) + 1;
            for (j = 0; j < erase_region_count; j++) {
                info->start[sect_cnt] = sector;
                sector += (erase_region_size * size_ratio);

                switch (info->vendor) {
                case CFI_CMDSET_INTEL_EXTENDED:
                case CFI_CMDSET_INTEL_STANDARD:
                    cptr.cp = flash_make_addr(info, sect_cnt, FLASH_OFFSET_PROTECT);
                    info->protect[sect_cnt] = flash_isset(info, cptr, FLASH_STATUS_PROTECT);
                    break;
                default:
                    info->protect[sect_cnt] = 0;    /* default: not protected */
                }

                sect_cnt++;
            }
        }

        info->sector_count = sect_cnt;
        /* multiply the size by the number of chips */
        info->size = (1 << flash_read_uint8_t(info, FLASH_OFFSET_SIZE)) * size_ratio;
        info->buffer_size = (1 << flash_read_uint16_t(info, 0, FLASH_OFFSET_BUFFER_SIZE));
        tmp = 1 << flash_read_uint8_t(info, FLASH_OFFSET_ETOUT);
        info->erase_blk_tout = (tmp * (1 << flash_read_uint8_t(info, FLASH_OFFSET_EMAX_TOUT)));

        info->erase_chip_tout = info->erase_blk_tout * info->sector_count;
        tmp = 1 << flash_read_uint8_t(info, FLASH_OFFSET_WBTOUT);
        info->buffer_write_tout = (tmp * (1 << flash_read_uint8_t(info, FLASH_OFFSET_WBMAX_TOUT)));
        tmp = 1 << flash_read_uint8_t(info, FLASH_OFFSET_WTOUT);
        info->write_tout = (tmp * (1 << flash_read_uint8_t(info, FLASH_OFFSET_WMAX_TOUT))) / 1000;
        info->flash_id = FLASH_MAN_CFI;
        if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
            info->portwidth >>= 1;
        }
Ejemplo n.º 13
0
/*-----------------------------------------------------------------------
 * read a character at a port width address
 */
inline uchar flash_read_uchar(flash_info_t * info, uchar offset)
{
	uchar *cp;
	cp = flash_make_addr(info, 0, offset);
	return (cp[info->portwidth - 1]);
}