Example #1
0
static int
spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf)
{
	u8 *read_addr;

   	/* sanity checks */
   	if (!len) return (0);
   	if (from + len > mtd->size) return (-EINVAL);

   	/* we always read len bytes */
   	*retlen = len;

	if (!spiflash_wait_ready(FL_READING))
		return -EINTR;
	read_addr = (u8 *)(spidata->readaddr + from);
	memcpy(buf, read_addr, len);
	spiflash_done();

   	return 0;
}
Example #2
0
static int
spiflash_erase (struct mtd_info *mtd,struct erase_info *instr)
{
	struct opcodes *ptr_opcode;
	u32 temp, reg;

   	/* sanity checks */
   	if (instr->addr + instr->len > mtd->size) return (-EINVAL);

	if (!spiflash_wait_ready(FL_ERASING))
		return -EINTR;

	spiflash_sendcmd(SPI_WRITE_ENABLE, 0);
	busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0);
	reg = spiflash_regread32(SPI_FLASH_CTL);

	ptr_opcode = &stm_opcodes[SPI_SECTOR_ERASE];
	temp = ((__u32)instr->addr << 8) | (__u32)(ptr_opcode->code);
	spiflash_regwrite32(SPI_FLASH_OPCODE, temp);

	reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | SPI_CTL_START;
	spiflash_regwrite32(SPI_FLASH_CTL, reg);

	/* this will take some time */
	spin_unlock_bh(&spidata->mutex);
	msleep(800);
	spin_lock_bh(&spidata->mutex);

	busy_wait(spiflash_sendcmd(SPI_RD_STATUS, 0) & SPI_STATUS_WIP, 20);
	spiflash_done();

   	instr->state = MTD_ERASE_DONE;
	mtd_erase_callback(instr);

   	return 0;
}
Example #3
0
    return 0;
}

int
spiflash_read(const struct hal_flash *hal_flash_dev, uint32_t addr, void *buf,
        uint32_t len)
{
    int err = 0;
    uint8_t cmd[] = { SPIFLASH_READ,
        (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)(addr) };
    struct spiflash_dev *dev;

    dev = (struct spiflash_dev *)hal_flash_dev;

    err = spiflash_wait_ready(dev, 100);
    if (!err) {
        spiflash_cs_activate(dev);

        /* Send command + address */
        hal_spi_txrx(dev->spi_num, cmd, NULL, sizeof cmd);
        /* For security mostly, do not output random data, fill it with FF */
        memset(buf, 0xFF, len);
        /* Tx buf does not matter, for simplicity pass read buffer */
        hal_spi_txrx(dev->spi_num, buf, buf, len);

        spiflash_cs_deactivate(dev);
    }

    return 0;
}
Example #4
0
static int
spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
{
	u32 opcode, bytes_left;

   	*retlen = 0;

   	/* sanity checks */
   	if (!len) return (0);
   	if (to + len > mtd->size) return (-EINVAL);

	opcode = stm_opcodes[SPI_PAGE_PROGRAM].code;
	bytes_left = len;

	do {
		u32 xact_len, reg, page_offset, spi_data = 0;

		xact_len = MIN(bytes_left, sizeof(__u32));

		/* 32-bit writes cannot span across a page boundary
		 * (256 bytes). This types of writes require two page
		 * program operations to handle it correctly. The STM part
		 * will write the overflow data to the beginning of the
		 * current page as opposed to the subsequent page.
		 */
		page_offset = (to & (STM_PAGE_SIZE - 1)) + xact_len;

		if (page_offset > STM_PAGE_SIZE) {
			xact_len -= (page_offset - STM_PAGE_SIZE);
		}

		if (!spiflash_wait_ready(FL_WRITING))
			return -EINTR;

		spiflash_sendcmd(SPI_WRITE_ENABLE, 0);
		switch (xact_len) {
			case 1:
			 	spi_data = (u32) ((u8) *buf);
				break;
			case 2:
				spi_data = (buf[1] << 8) | buf[0];
				break;
			case 3:
				spi_data = (buf[2] << 16) | (buf[1] << 8) | buf[0];
				break;
			case 4:
				spi_data = (buf[3] << 24) | (buf[2] << 16) |
							(buf[1] << 8) | buf[0];
				break;
			default:
				spi_data = 0;
				break;
		}

		spiflash_regwrite32(SPI_FLASH_DATA, spi_data);
		opcode = (opcode & SPI_OPCODE_MASK) | ((__u32)to << 8);
		spiflash_regwrite32(SPI_FLASH_OPCODE, opcode);

		reg = spiflash_regread32(SPI_FLASH_CTL);
		reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | (xact_len + 4) | SPI_CTL_START;
		spiflash_regwrite32(SPI_FLASH_CTL, reg);

		/* give the chip some time before we start busy waiting */
		spin_unlock_bh(&spidata->mutex);
		schedule();
		spin_lock_bh(&spidata->mutex);

		busy_wait(spiflash_sendcmd(SPI_RD_STATUS, 0) & SPI_STATUS_WIP, 0);
		spiflash_done();

		bytes_left -= xact_len;
		to += xact_len;
		buf += xact_len;

   		*retlen += xact_len;
	} while (bytes_left != 0);

   	return 0;
}