Exemple #1
0
static vsf_err_t cfi_wait_busy(struct dal_info_t *info, uint64_t address)
{
	uint32_t cur_status = 0, orig_status = 0;
	struct cfi_drv_param_t *param = (struct cfi_drv_param_t *)info->param;
	uint8_t data_width = param->nor_info.common_info.data_width / 8;
	
	cfi_read(info, (uint32_t)address, data_width, (uint8_t *)&orig_status, 1);
	
	do {
		cfi_read(info, 0, data_width, (uint8_t *)&cur_status, 1);
		interfaces->peripheral_commit();
		
		if ((cur_status ^ orig_status) & 0x0040)
		{
			if (cur_status & 0x0020)
			{
				cfi_read(info, 0, data_width, (uint8_t *)&orig_status, 1);
				cfi_read(info, 0, data_width, (uint8_t *)&cur_status, 1);
				interfaces->peripheral_commit();
				return ((cur_status ^ orig_status) & 0x0040) ?
							VSFERR_FAIL : VSFERR_NONE;
			}
		}
		else
		{
			break;
		}
		
		orig_status = cur_status;
	} while (1);
	return VSFERR_NONE;
}
Exemple #2
0
/* check for QRY.
   in: interleave,type,mode
   ret: table index, <0 for error
 */
static inline int qry_present(struct map_info *map, __u32 base,
				struct cfi_private *cfi)
{
	int osf = cfi->interleave * cfi->device_type;	// scale factor

	if (cfi_read(map,base+osf*0x10)==cfi_build_cmd('Q',map,cfi) &&
	    cfi_read(map,base+osf*0x11)==cfi_build_cmd('R',map,cfi) &&
	    cfi_read(map,base+osf*0x12)==cfi_build_cmd('Y',map,cfi))
		return 1;	// ok !

	return 0; 	// nothing found
}
Exemple #3
0
static vsf_err_t cfi_drv_eraseall_nb_isready(struct dal_info_t *info)
{
	uint32_t val1 = 0, val2 = 0;
	struct cfi_drv_param_t *param = (struct cfi_drv_param_t *)info->param;
	uint8_t data_width = param->nor_info.common_info.data_width / 8;
	
	cfi_read(info, 0x0000 << 1, data_width, (uint8_t *)&val1, 1);
	cfi_read(info, 0x0000 << 1, data_width, (uint8_t *)&val2, 1);
	interfaces->peripheral_commit();
	
	return (((val1 ^ val2) & 0x0040) == 0) ? VSFERR_NONE : VSFERR_NOT_READY;
}
Exemple #4
0
static vsf_err_t cfi_drv_eraseblock_nb_isready(struct dal_info_t *info, 
												uint64_t address)
{
	uint32_t val1 = 0, val2 = 0;
	struct sst32hfxx_drv_param_t *param = (struct sst32hfxx_drv_param_t *)info->param;
	uint8_t data_width = param->nor_info.common_info.data_width / 8;
	
	REFERENCE_PARAMETER(address);
	
	cfi_read(info, 0x0000 << 1, data_width, (uint8_t *)&val1, 1);
	cfi_read(info, 0x0000 << 1, data_width, (uint8_t *)&val2, 1);
	interfaces->peripheral_commit();
	
	return (((val1 ^ val2) & 0x0040) == 0) ? VSFERR_NONE : VSFERR_NOT_READY;
}
Exemple #5
0
static vsf_err_t cfi_drv_readblock_nb(struct dal_info_t *info, uint64_t address, 
									uint8_t *buff)
{
	uint32_t count, i, cur_count;
	struct cfi_drv_param_t *param = (struct cfi_drv_param_t *)info->param;
	uint8_t data_width = param->nor_info.common_info.data_width / 8;
	struct mal_info_t *mal_info = (struct mal_info_t *)info->extra;
	
	if (mal_info->read_page_size)
	{
		count = (uint32_t)mal_info->read_page_size / data_width;
	}
	else
	{
		count = (uint32_t)mal_info->capacity.block_size / data_width;
	}
	
	i = 0;
	while (i < count)
	{
		cur_count = (count > 1024) ? 1024 : count;
		cfi_read(info, (uint32_t)address, data_width, buff, cur_count);
		address += cur_count * data_width;
		buff += cur_count * data_width;
		i += cur_count;
	}
	return interfaces->peripheral_commit();
}
Exemple #6
0
static int
cfi_wait_ready(struct cfi_softc *sc, u_int ofs, u_int timeout)
{
	int done, error;
	uint32_t st0 = 0, st = 0;

	done = 0;
	error = 0;
	timeout *= 10;
	while (!done && !error && timeout) {
		DELAY(100);
		timeout--;

		switch (sc->sc_cmdset) {
		case CFI_VEND_INTEL_ECS:
		case CFI_VEND_INTEL_SCS:
			st = cfi_read(sc, ofs);
			done = (st & CFI_INTEL_STATUS_WSMS);
			if (done) {
				/* NB: bit 0 is reserved */
				st &= ~(CFI_INTEL_XSTATUS_RSVD |
					CFI_INTEL_STATUS_WSMS |
					CFI_INTEL_STATUS_RSVD);
				if (st & CFI_INTEL_STATUS_DPS)
					error = EPERM;
				else if (st & CFI_INTEL_STATUS_PSLBS)
					error = EIO;
				else if (st & CFI_INTEL_STATUS_ECLBS)
					error = ENXIO;
				else if (st)
					error = EACCES;
			}
			break;
		case CFI_VEND_AMD_SCS:
		case CFI_VEND_AMD_ECS:
			st0 = cfi_read(sc, ofs);
			st = cfi_read(sc, ofs);
			done = ((st & 0x40) == (st0 & 0x40)) ? 1 : 0;
			break;
		}
	}
	if (!done && !error)
		error = ETIMEDOUT;
	if (error)
		printf("\nerror=%d (st 0x%x st0 0x%x)\n", error, st, st0);
	return (error);
}
Exemple #7
0
static vsf_err_t cfi_drv_writeblock_nb_isready(struct dal_info_t *info, 
											uint64_t address, uint8_t *buff)
{
	uint32_t status = 0, verify_data;
	struct mal_info_t *mal_info = (struct mal_info_t *)info->extra;
	struct cfi_drv_param_t *param = (struct cfi_drv_param_t *)info->param;
	uint8_t data_width = param->nor_info.common_info.data_width / 8;
	uint32_t write_page_size = mal_info->write_page_size;
	
	cfi_read(info, (uint32_t)address + write_page_size - data_width, data_width,
				(uint8_t *)&status, 1);
	interfaces->peripheral_commit();
	
	switch (data_width)
	{
	case 1:
		verify_data = buff[write_page_size - 1];
		break;
	case 2:
		verify_data = ((uint16_t *)buff)[write_page_size / 2 - 1];
		break;
	case 4:
		verify_data = ((uint32_t *)buff)[write_page_size / 4 - 1];
		break;
	default:
		return VSFERR_FAIL;
	}
	
	if (verify_data == status)
	{
		return VSFERR_NONE;
	}
	else if ((status & 0x20) || (status & 0x02))
	{
		cfi_read(info, (uint32_t)address + write_page_size - data_width, 
					data_width, (uint8_t *)&status, 1);
		if (interfaces->peripheral_commit() || 
			(verify_data != status))
		{
			return VSFERR_FAIL;
		}
		return VSFERR_NONE;
	}
	
	return VSFERR_NOT_READY;
}
Exemple #8
0
static void
cfi_disk_read(struct cfi_softc *sc, struct bio *bp)
{
	long resid;

	KASSERT(sc->sc_width == 1 || sc->sc_width == 2 || sc->sc_width == 4,
	    ("sc_width %d", sc->sc_width));

	if (sc->sc_writing) {
		bp->bio_error = cfi_block_finish(sc);
		if (bp->bio_error) {
			bp->bio_flags |= BIO_ERROR;
			goto done;
		}
	}
	if (bp->bio_offset > sc->sc_size) {
		bp->bio_flags |= BIO_ERROR;
		bp->bio_error = EIO;
		goto done;
	}
	resid = bp->bio_bcount;
	if (sc->sc_width == 1) {
		uint8_t *dp = (uint8_t *)bp->bio_data;
		while (resid > 0 && bp->bio_offset < sc->sc_size) {
			*dp++ = cfi_read(sc, bp->bio_offset);
			bp->bio_offset += 1, resid -= 1;
		}
	} else if (sc->sc_width == 2) {
		uint16_t *dp = (uint16_t *)bp->bio_data;
		while (resid > 0 && bp->bio_offset < sc->sc_size) {
			*dp++ = cfi_read(sc, bp->bio_offset);
			bp->bio_offset += 2, resid -= 2;
		}
	} else {
		uint32_t *dp = (uint32_t *)bp->bio_data;
		while (resid > 0 && bp->bio_offset < sc->sc_size) {
			*dp++ = cfi_read(sc, bp->bio_offset);
			bp->bio_offset += 4, resid -= 4;
		}
	}
	bp->bio_resid = resid;
done:
	biodone(bp);
}
Exemple #9
0
uint8_t
cfi_read_qry(struct cfi_softc *sc, u_int ofs)
{
	uint8_t val;
 
	cfi_write(sc, CFI_QRY_CMD_ADDR * sc->sc_width, CFI_QRY_CMD_DATA); 
	val = cfi_read(sc, ofs * sc->sc_width);
	cfi_write(sc, 0, CFI_BCS_READ_ARRAY);
	return (val);
} 
Exemple #10
0
static vsf_err_t cfi_drv_getinfo(struct dal_info_t *info)
{
	uint32_t manufacturer_id = 0, device_id = 0;
	struct sst32hfxx_drv_info_t *pinfo = (struct sst32hfxx_drv_info_t *)info->info;
	struct sst32hfxx_drv_param_t *param = (struct sst32hfxx_drv_param_t *)info->param;
	uint8_t data_width = param->nor_info.common_info.data_width / 8;
	
	cfi_write_cmd(info, 0xAA, data_width, 0x5555 << 1);
	cfi_write_cmd(info, 0x55, data_width, 0x2AAA << 1);
	cfi_write_cmd(info, 0x90, data_width, 0x5555 << 1);
	
	cfi_read(info, 0x0000 << 1, data_width, (uint8_t *)&manufacturer_id, 1);
	cfi_read(info, 0x0001 << 1, data_width, (uint8_t *)&device_id, 1);
	interfaces->peripheral_commit();
	pinfo->manufacturer_id = (uint8_t)manufacturer_id;
	pinfo->device_id = (uint16_t)device_id;

	cfi_write_cmd(info, 0xAA, data_width, 0x5555 << 1);
	cfi_write_cmd(info, 0x55, data_width, 0x2AAA << 1);
	cfi_write_cmd(info, 0xF0, data_width, 0x5555 << 1);
	return VSFERR_NONE;
}
Exemple #11
0
void cfi_test() {
    struct cfi *cfi;
    char test_buff[2] = {0x2c,0x04};
    char read_buff[2];
    int addr;
    int i;
    
    delay(5 * 1000);

    printf("cfi test ...\n");

    cfi_init(0);  
    
    cfi = &cfid[0];
    
    addr = 0xf80000;
    for(i=0;i<256;i++) {
        cfi_erase(0, addr, cfi->sectsiz);
        cfi_write(0, addr + 0x01fe, 2, test_buff);  
        cfi_write(0, addr + 0x01fc, 2, test_buff);  
        addr += cfi->sectsiz;
    }

    addr = 0xf80000;
    for(i=0;i<256;i++) {
        cfi_read(0, addr + 0x01fe, 2, read_buff);
        if ((read_buff[0] != 0x2c) || (read_buff[1] != 0x04)) {
            printf("error block %d\n",i);
        }
        cfi_read(0, addr + 0x01fc, 2, read_buff);
        if ((read_buff[0] != 0x2c) || (read_buff[1] != 0x04)) {
            printf("error block %d\n",i);
        }
        addr += cfi->sectsiz;
    }

    printf("finish");
}
Exemple #12
0
static vsf_err_t cfi_drv_getinfo(struct dal_info_t *info)
{
	uint8_t cfi_info8[256];
	uint16_t *cfi_info16 = (uint16_t *)cfi_info8;
	uint32_t *cfi_info32 = (uint32_t *)cfi_info8;
	uint32_t manufacturer_id = 0;
	struct cfi_drv_info_t *pinfo = (struct cfi_drv_info_t *)info->info;
	struct mal_info_t *cfi_mal_info = (struct mal_info_t *)info->extra;
	struct cfi_drv_param_t *param = (struct cfi_drv_param_t *)info->param;
	uint8_t data_width = param->nor_info.common_info.data_width / 8;
	
	cfi_write_cmd(info, 0xAA, data_width, 0x0555 << 1);
	cfi_write_cmd(info, 0x55, data_width, 0x02AA << 1);
	cfi_write_cmd(info, 0x90, data_width, 0x0555 << 1);
	
	cfi_read(info, 0x0000 << 1, data_width, (uint8_t *)&manufacturer_id, 1);
	cfi_read(info, 0x0001 << 1, data_width, (uint8_t *)&pinfo->device_id[0], 1);
	cfi_read(info, 0x000E << 1, data_width, (uint8_t *)&pinfo->device_id[1], 1);
	cfi_read(info, 0x000F << 1, data_width, (uint8_t *)&pinfo->device_id[2], 1);
	interfaces->peripheral_commit();
	
	pinfo->manufacturer_id = (uint8_t)manufacturer_id;
	pinfo->device_id[0] = LE_TO_SYS_U16(pinfo->device_id[0]);
	pinfo->device_id[1] = LE_TO_SYS_U16(pinfo->device_id[1]);
	pinfo->device_id[2] = LE_TO_SYS_U16(pinfo->device_id[2]);
	
	cfi_write_cmd(info, 0xAA, data_width, 0x0555 << 1);
	cfi_write_cmd(info, 0x55, data_width, 0x02AA << 1);
	cfi_write_cmd(info, 0xF0, data_width, 0);
	
	cfi_write_cmd(info, 0x98, data_width, 0x0055 << 1);
	cfi_read(info, 0x0010 << 1, data_width, (uint8_t *)cfi_info8, 
				sizeof(cfi_info8) / data_width);
	if (interfaces->peripheral_commit() || 
		((1 == data_width) && 
			((cfi_info8[0] != 'Q') || (cfi_info8[1] != 'R') || 
			(cfi_info8[2] != 'Y'))) || 
		((2 == data_width) && 
			((cfi_info16[0] != 'Q') || (cfi_info16[1] != 'R') || 
			(cfi_info16[2] != 'Y'))) || 
		((4 == data_width) && 
			((cfi_info32[0] != 'Q') || (cfi_info32[1] != 'R') || 
			(cfi_info32[2] != 'Y'))))
	{
		return VSFERR_FAIL;
	}
	if (!cfi_mal_info->capacity.block_number || 
		!cfi_mal_info->capacity.block_size)
	{
		switch (data_width)
		{
		case 1:
			cfi_mal_info->capacity.block_number = cfi_info8[0x1D] + 1;
			cfi_mal_info->capacity.block_size = 
						((uint64_t)1 << cfi_info8[0x17]) / (cfi_info8[0x1D] + 1);
			break;
		case 2:
			cfi_mal_info->capacity.block_number = cfi_info16[0x1D] + 1;
			cfi_mal_info->capacity.block_size = 
						((uint64_t)1 << cfi_info16[0x17]) / (cfi_info16[0x1D] + 1);
			break;
		case 4:
			cfi_mal_info->capacity.block_number = cfi_info32[0x1D] + 1;
			cfi_mal_info->capacity.block_size = 
						((uint64_t)1 << cfi_info32[0x17]) / (cfi_info32[0x1D] + 1);
			break;
		default:
			return VSFERR_FAIL;
		}
	}
	switch (data_width)
	{
	case 1:
		cfi_mal_info->write_page_size = 1 << cfi_info8[0x1A];
		break;
	case 2:
		cfi_mal_info->write_page_size = 1 << cfi_info16[0x1A];
		break;
	case 4:
		cfi_mal_info->write_page_size = 1 << cfi_info32[0x1A];
		break;
	default:
		return VSFERR_FAIL;
	}
	cfi_mal_info->erase_page_size = (uint32_t)cfi_mal_info->capacity.block_size;
	
	cfi_write_cmd(info, 0xAA, data_width, 0x0555 << 1);
	cfi_write_cmd(info, 0x55, data_width, 0x02AA << 1);
	cfi_write_cmd(info, 0xF0, data_width, 0);
	return VSFERR_NONE;
}