Пример #1
0
/*
 * The IXP4xx expansion bus only allows 16-bit wide acceses
 * when attached to a 16-bit wide device (such as the 28F128J3A),
 * so we can't just memcpy_fromio().
 */
static void ixp4xx_copy_from(struct map_info *map, void *to,
                             unsigned long from, ssize_t len)
{
    u8 *dest = (u8 *) to;
    void __iomem *src = map->virt + from;

    if (len <= 0)
        return;

    if (from & 1) {
        *dest++ = BYTE1(flash_read16(src-1));
        src++;
        --len;
    }

    while (len >= 2) {
        u16 data = flash_read16(src);
        *dest++ = BYTE0(data);
        *dest++ = BYTE1(data);
        src += 2;
        len -= 2;
    }

    if (len > 0)
        *dest++ = BYTE0(flash_read16(src));
}
Пример #2
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;
}
Пример #3
0
/* Internal: retrieve intel protection data */
__ramtext
static int get_intel_protection(void *base_addr,
				uint16_t * lockp, uint8_t protp[8])
{
	int i;

	/* check args */
	if (!lockp) {
		return -EINVAL;
	}
	if (!protp) {
		return -EINVAL;
	}

	/* enter read id mode */
	flash_write_cmd(base_addr, CFI_CMD_READ_ID);

	/* get lock */
	*lockp = flash_read16(base_addr, CFI_OFFSET_INTEL_PROTECTION);

	/* get data */
	for (i = 0; i < 8; i++) {
		protp[i] = flash_read16(base_addr, CFI_OFFSET_INTEL_PROTECTION + 1 + i);
	}

	/* leave read id mode */
	flash_write_cmd(base_addr, CFI_CMD_RESET);

	return 0;
}
Пример #4
0
/* Internal: retrieve manufacturer and device id from id space */
__ramtext
static int get_id(void *base_addr,
		  uint16_t * manufacturer_id, uint16_t * device_id)
{
	flash_write_cmd(base_addr, CFI_CMD_READ_ID);

	*manufacturer_id = flash_read16(base_addr, CFI_OFFSET_MANUFACTURER_ID);
	*device_id = flash_read16(base_addr, CFI_OFFSET_DEVICE_ID);

	flash_write_cmd(base_addr, CFI_CMD_RESET);

	return 0;
}
Пример #5
0
static int amd_flash_write_cfibuffer(struct flash_info *info, unsigned long dest,
		const u8 *cp, int len)
{
	flash_sect_t sector;
	int cnt;
	void *src = (void *)cp;
	void *dst = (void *)dest;
	cfiword_t cword;

	sector = find_sector (info, dest);

	flash_unlock_seq(info);
	flash_make_cmd (info, AMD_CMD_WRITE_TO_BUFFER, &cword);
	flash_write_word(info, cword, (void *)dest);

	if (bankwidth_is_1(info)) {
		cnt = len;
		flash_write_cmd(info, sector, 0, (u32)cnt - 1);
		while (cnt-- > 0) {
			flash_write8(flash_read8(src), dst);
			src += 1, dst += 1;
		}
	} else if (bankwidth_is_2(info)) {
		cnt = len >> 1;
		flash_write_cmd(info, sector, 0, (u32)cnt - 1);
		while (cnt-- > 0) {
			flash_write16(flash_read16(src), dst);
			src += 2, dst += 2;
		}
	} else if (bankwidth_is_4(info)) {
Пример #6
0
__ramtext
int flash_block_erase(flash_t * flash, uint32_t block_offset)
{
	const void *base_addr = flash->f_base;

	if (block_offset >= flash->f_size) {
		return -EINVAL;
	}

	if (flash_protected(block_offset)) {
		return -EPERM;
	}

	printf("Erasing block 0x%08lx...", block_offset);

	void *block_addr = ((uint8_t *) base_addr) + block_offset;

	flash_write_cmd(base_addr, CFI_CMD_CLEAR_STATUS);

	flash_write_cmd(block_addr, CFI_CMD_BLOCK_ERASE);
	flash_write_cmd(block_addr, CFI_CMD_ERASE_CONFIRM);

	flash_write_cmd(base_addr, CFI_CMD_READ_STATUS);
	uint16_t status;
	do {
		status = flash_read16(base_addr, 0);
	} while (!(status & CFI_STATUS_READY));

	int res = 0;
	if (status & CFI_STATUS_ERASE_ERROR) {
		puts("error: ");
		if (status & CFI_STATUS_VPP_LOW) {
			puts("vpp insufficient\n");
			res = -EFAULT;
		} else if (status & CFI_STATUS_LOCKED_ERROR) {
			puts("block is lock-protected\n");
			res = -EPERM;
		} else {
			puts("unknown fault\n");
			res = -EFAULT;
		}
	} else {
		puts("done\n");
	}

	flash_write_cmd(base_addr, CFI_CMD_RESET);

	return res;

}
Пример #7
0
/* Internal: retrieve cfi query response data */
__ramtext
static int get_query(void *base_addr, struct cfi_query *query)
{
	int res = 0;
	unsigned int i;

	flash_write_cmd(base_addr, CFI_CMD_CFI);

	for (i = 0; i < sizeof(struct cfi_query); i++) {
		uint16_t byte =
			flash_read16(base_addr, CFI_OFFSET_CFI_RESP + i);
		*(((volatile unsigned char *)query) + i) = byte;
	}

	if (query->qry[0] != 'Q' || query->qry[1] != 'R' || query->qry[2] != 'Y') {
		res = -ENOENT;
	}

	flash_write_cmd(base_addr, CFI_CMD_RESET);

	return res;
}
Пример #8
0
__ramtext
int flash_program(flash_t * flash, uint32_t dst, void *src, uint32_t nbytes)
{
	const void *base_addr = flash->f_base;
	int res = 0;
	uint32_t i;

	/* check destination bounds */
	if (dst >= flash->f_size) {
		return -EINVAL;
	}
	if (dst + nbytes > flash->f_size) {
		return -EINVAL;
	}

	/* check alignments */
	if (((uint32_t) src) % 2) {
		return -EINVAL;
	}
	if (dst % 2) {
		return -EINVAL;
	}
	if (nbytes % 2) {
		return -EINVAL;
	}

	/* check permissions */
	if (flash_protected(dst)) {
		return -EPERM;
	}

	/* say something */
	printf("Programming %lu bytes to 0x%08lx from 0x%p...", nbytes, dst, src);

	/* clear status register */
	flash_write_cmd(base_addr, CFI_CMD_CLEAR_STATUS);

	/* write the words */
	puts("writing...");
	for (i = 0; i < nbytes; i += 2) {
		uint16_t *src_addr = (uint16_t *) (src + i);
		uint16_t *dst_addr = (uint16_t *) (base_addr + dst + i);

		uint16_t data = *src_addr;

		flash_write_cmd(dst_addr, CFI_CMD_WRITE);
		flash_write_cmd(dst_addr, data);

		flash_write_cmd(base_addr, CFI_CMD_READ_STATUS);
		uint16_t status;
		do {
			status = flash_read16(base_addr, 0);
		} while (!(status & CFI_STATUS_READY));

		if (status & CFI_STATUS_PROGRAM_ERROR) {
			puts("error: ");
			if (status & CFI_STATUS_VPP_LOW) {
				puts("vpp insufficient");
				res = -EFAULT;
			} else if (status & CFI_STATUS_LOCKED_ERROR) {
				puts("block is lock-protected");
				res = -EPERM;
			} else {
				puts("unknown fault");
				res = -EFAULT;
			}
			goto err_reset;
		}
	}

	flash_write_cmd(base_addr, CFI_CMD_RESET);

	/* verify the result */
	puts("verifying...");
	for (i = 0; i < nbytes; i += 2) {
		uint16_t *src_addr = (uint16_t *) (src + i);
		uint16_t *dst_addr = (uint16_t *) (base_addr + dst + i);
		if (*src_addr != *dst_addr) {
			puts("error: verification failed");
			res = -EFAULT;
			goto err;
		}
	}

	puts("done\n");

	return res;

 err_reset:
	flash_write_cmd(base_addr, CFI_CMD_RESET);

 err:
	printf(" at offset 0x%lx\n", i);

	return res;
}
Пример #9
0
static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
{
    map_word val;
    val.x[0] = flash_read16(map->virt + ofs);
    return val;
}