コード例 #1
0
ファイル: flashSflashDrvLib.c プロジェクト: ariavie/bcm
LOCAL int
flashWrite(int sectorNum, char *buff, unsigned int offset, unsigned int count)
{
    unsigned char *curBuffPtr, *sectorOffsetPtr;
    unsigned int len = count;
    int bytes;

    curBuffPtr = (unsigned char *)buff;
    sectorOffsetPtr = (unsigned char *)((sectorNum * FLASH_SECTOR_SIZE) + offset);

    /* Write holding block */
    while (len) {
        if ((bytes = sflash_write(sih, cc, (unsigned int)sectorOffsetPtr, len, curBuffPtr)) < 0) {
            printf("flashWrite(): Failed: Sector %d, address 0x%x\n",
                sectorNum, (int)sectorOffsetPtr);
            return (ERROR);
        }

        /* Polling until command completion. Returns zero when complete. */
        while (sflash_poll(sih, cc, (unsigned int)sectorOffsetPtr));

        sectorOffsetPtr += bytes;
        len -= bytes;
        curBuffPtr += bytes;
    }

    return (OK);
}
コード例 #2
0
ファイル: sflash.c プロジェクト: Cribstone/linino
static int
sflash_mtd_poll(struct sflash_mtd *sflash, unsigned int offset, int timeout)
{
	int now = jiffies;
	int ret = 0;

	for (;;) {
		if (!sflash_poll(sflash->sbh, sflash->cc, offset)) {
			ret = 0;
			break;
		}
		if (time_after(jiffies, now + timeout)) {
			printk(KERN_ERR "sflash: timeout\n");
			ret = -ETIMEDOUT;
			break;
		}
		if (current->need_resched) {
			set_current_state(TASK_UNINTERRUPTIBLE);
			schedule_timeout(timeout / 10);
		} else
			udelay(1);
	}

	return ret;
}
コード例 #3
0
ファイル: flashSflashDrvLib.c プロジェクト: ariavie/bcm
LOCAL int
flashEraseDevices(volatile unsigned char *sectorBasePtr)
{
    int ret = 0;

    if (flashVerbose) {
        printf("Erasing Sector @ 0x%08x\n",(unsigned int)sectorBasePtr);
    }

    /* Erase block */
    if ((ret = sflash_erase(sih, cc, (unsigned int)sectorBasePtr)) < 0) {
        return (ERROR);
    }

    /* Polling until command completion. Returns zero when complete. */
    while (sflash_poll(sih, cc, (unsigned int)sectorBasePtr));

    if (flashVerbose > 1)
        printf("flashEraseDevices(): all devices erased\n");

    return (OK);
}
コード例 #4
0
/*
 * writes the appropriate range of flash, a NULL buf simply erases
 * the region of flash
 */
int
sflash_commit(si_t *sih, chipcregs_t *cc, uint offset, uint len, const uchar *buf)
{
	struct sflash *sfl;
	uchar *block = NULL, *cur_ptr, *blk_ptr;
	uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder;
	uint blk_offset, blk_len, copied;
	int bytes, ret = 0;
	osl_t *osh;

	ASSERT(sih);

	osh = si_osh(sih);

	/* Check address range */
	if (len <= 0)
		return 0;

	sfl = &sflash;
	if ((offset + len) > sfl->size)
		return -1;

	blocksize = sfl->blocksize;
	mask = blocksize - 1;

	/* Allocate a block of mem */
	if (!(block = MALLOC(osh, blocksize)))
		return -1;

	while (len) {
		/* Align offset */
		cur_offset = offset & ~mask;
		cur_length = blocksize;
		cur_ptr = block;

		remainder = blocksize - (offset & mask);
		if (len < remainder)
			cur_retlen = len;
		else
			cur_retlen = remainder;

		/* buf == NULL means erase only */
		if (buf) {
			/* Copy existing data into holding block if necessary */
			if ((offset & mask) || (len < blocksize)) {
				blk_offset = cur_offset;
				blk_len = cur_length;
				blk_ptr = cur_ptr;

				/* Copy entire block */
				while (blk_len) {
					copied = sflash_read(sih, cc, blk_offset, blk_len, blk_ptr);
					blk_offset += copied;
					blk_len -= copied;
					blk_ptr += copied;
				}
			}

			/* Copy input data into holding block */
			memcpy(cur_ptr + (offset & mask), buf, cur_retlen);
		}

		/* Erase block */
		if ((ret = sflash_erase(sih, cc, (uint) cur_offset)) < 0)
			goto done;
		while (sflash_poll(sih, cc, (uint) cur_offset));

		/* buf == NULL means erase only */
		if (!buf) {
			offset += cur_retlen;
			len -= cur_retlen;
			continue;
		}

		/* Write holding block */
		while (cur_length > 0) {
			if ((bytes = sflash_write(sih, cc,
			                          (uint) cur_offset,
			                          (uint) cur_length,
			                          (uchar *) cur_ptr)) < 0) {
				ret = bytes;
				goto done;
			}
			while (sflash_poll(sih, cc, (uint) cur_offset));
			cur_offset += bytes;
			cur_length -= bytes;
			cur_ptr += bytes;
		}

		offset += cur_retlen;
		len -= cur_retlen;
		buf += cur_retlen;
	}

	ret = len;
done:
	if (block)
		MFREE(osh, block, blocksize);
	return ret;
}
コード例 #5
0
int
sflash_write(si_t *sih, chipcregs_t *cc, uint offset, uint length, const uchar *buffer)
{
	struct sflash *sfl;
	uint off = offset, len = length;
	const uint8 *buf = buffer;
	uint8 data;
	int ret = 0, ntry = 0;
	bool is4712b0;
	uint32 page, byte, mask;
	osl_t *osh;

	ASSERT(sih);

	osh = si_osh(sih);

	if (!len)
		return 0;

	sfl = &sflash;
	if ((off + len) > sfl->size)
		return -22;

	switch (sfl->type) {
	case SFLASH_ST:
		is4712b0 = (CHIPID(sih->chip) == BCM4712_CHIP_ID) && (CHIPREV(sih->chiprev) == 3);
		/* Enable writes */
retry:		sflash_cmd(osh, cc, SFLASH_ST_WREN);
		off = offset;
		len = length;
		buf = buffer;
		ntry++;
		if (is4712b0) {
			mask = 1 << 14;
			W_REG(osh, &cc->flashaddress, off);
			data = GET_BYTE(buf);
			buf++;
			W_REG(osh, &cc->flashdata, data);
			/* Set chip select */
			OR_REG(osh, &cc->gpioout, mask);
			/* Issue a page program with the first byte */
			sflash_cmd(osh, cc, SFLASH_ST_PP);
			ret = 1;
			off++;
			len--;
			while (len > 0) {
				if ((off & 255) == 0) {
					/* Page boundary, drop cs and return */
					AND_REG(osh, &cc->gpioout, ~mask);
					OSL_DELAY(1);
					if (!sflash_poll(sih, cc, off)) {
						/* Flash rejected command */
						if (ntry <= ST_RETRIES)
							goto retry;
						else
							return -11;
					}
					return ret;
				} else {
					/* Write single byte */
					data = GET_BYTE(buf);
					buf++;
					sflash_cmd(osh, cc, data);
				}
				ret++;
				off++;
				len--;
			}
			/* All done, drop cs */
			AND_REG(osh, &cc->gpioout, ~mask);
			OSL_DELAY(1);
			if (!sflash_poll(sih, cc, off)) {
				/* Flash rejected command */
				if (ntry <= ST_RETRIES)
					goto retry;
				else
					return -12;
			}
		} else if (sih->ccrev >= 20) {
			W_REG(osh, &cc->flashaddress, off);
			data = GET_BYTE(buf);
			buf++;
			W_REG(osh, &cc->flashdata, data);
			/* Issue a page program with CSA bit set */
			sflash_cmd(osh, cc, SFLASH_ST_CSA | SFLASH_ST_PP);
			ret = 1;
			off++;
			len--;
			while (len > 0) {
				if ((off & 255) == 0) {
					/* Page boundary, poll droping cs and return */
					W_REG(NULL, &cc->flashcontrol, 0);
					OSL_DELAY(1);
					if (sflash_poll(sih, cc, off) == 0) {
						/* Flash rejected command */
						SFL_MSG(("sflash: pp rejected, ntry: %d,"
						         " off: %d/%d, len: %d/%d, ret:"
						         "%d\n", ntry, off, offset, len,
						         length, ret));
						if (ntry <= ST_RETRIES)
							goto retry;
						else
							return -11;
					}
					return ret;
				} else {
					/* Write single byte */
					data = GET_BYTE(buf);
					buf++;
					sflash_cmd(osh, cc, SFLASH_ST_CSA | data);
				}
				ret++;
				off++;
				len--;
			}
			/* All done, drop cs & poll */
			W_REG(NULL, &cc->flashcontrol, 0);
			OSL_DELAY(1);
			if (sflash_poll(sih, cc, off) == 0) {
				/* Flash rejected command */
				SFL_MSG(("sflash: pp rejected, ntry: %d, off: %d/%d,"
				         " len: %d/%d, ret: %d\n",
				         ntry, off, offset, len, length, ret));
				if (ntry <= ST_RETRIES)
					goto retry;
				else
					return -12;
			}
		} else {
			ret = 1;
			W_REG(osh, &cc->flashaddress, off);
			data = GET_BYTE(buf);
			buf++;
			W_REG(osh, &cc->flashdata, data);
			/* Page program */
			sflash_cmd(osh, cc, SFLASH_ST_PP);
		}
		break;
	case SFLASH_AT:
		mask = sfl->blocksize - 1;
		page = (off & ~mask) << 1;
		byte = off & mask;
		/* Read main memory page into buffer 1 */
		if (byte || (len < sfl->blocksize)) {
			W_REG(osh, &cc->flashaddress, page);
			sflash_cmd(osh, cc, SFLASH_AT_BUF1_LOAD);
			/* 250 us for AT45DB321B */
			SPINWAIT(sflash_poll(sih, cc, off), 1000);
			ASSERT(!sflash_poll(sih, cc, off));
		}
		/* Write into buffer 1 */
		for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
			W_REG(osh, &cc->flashaddress, byte++);
			W_REG(osh, &cc->flashdata, *buf++);
			sflash_cmd(osh, cc, SFLASH_AT_BUF1_WRITE);
		}
		/* Write buffer 1 into main memory page */
		W_REG(osh, &cc->flashaddress, page);
		sflash_cmd(osh, cc, SFLASH_AT_BUF1_PROGRAM);
		break;
	}

	return ret;
}
コード例 #6
0
ファイル: sflash.c プロジェクト: ariavie/bcm
int
sflash_write(si_t *sih, chipcregs_t *cc, uint offset, uint length, const uchar *buffer)
{
    struct sflash *sfl;
    uint off = offset, len = length;
#if SFLASH_ST_PAGE_MODE_WRITE
    int tryn = 0;
#else /* !SFLASH_ST_PAGE_MODE_WRITE */
    uint quot = 0, remain = 0, wlen = 0;
    uint32 reg_val = 0;
#endif /* SFLASH_ST_PAGE_MODE_WRITE */
    const uchar *buf = buffer;
    int ret = 0;
    uint32 page, byte, mask;
    osl_t *osh;
    
    ASSERT(sih);
    
    osh = si_osh(sih);
    
    if (!len)
        return 0;
    
    sfl = &sflash;
    if ((off + len) > sfl->size)
        return -22;
    
    switch (sfl->type) {
    case SFLASH_ST:
#if SFLASH_ST_PAGE_MODE_WRITE
          /* Enable writes */
retry:      sflash_cmd(osh, cc, SFLASH_ST_WREN);
          off = offset;
          len = length;
          buf = buffer;
          tryn++;
          if (sih->ccrev >= 20) {
              W_REG(osh, &cc->sflashaddress, off);
              W_REG(osh, &cc->sflashdata, *buf++);
              /* Issue a page program with CSA bit set */
              sflash_cmd(osh, cc, SFLASH_ST_CSA | SFLASH_ST_PP);
              ret = 1;
              off++;
              len--;
              while (len > 0) {
                  if ((off & 255) == 0) {
                      /* Page boundary, poll droping cs and return */
                      W_REG(osh, &cc->sflashcontrol, 0);
                      OSL_DELAY(1);
                      if (sflash_poll(sih, cc, offset) != 0) {
                          /* Flash rejected command */
                          SFL_MSG(("sflash: pp rejected, tryn: %d,"
                                   " off: %d/%d, len: %d/%d, ret:"
                                   "%d\n", tryn, off, offset, len,
                                   length, ret));
                          if (tryn <= ST_RETRIES)
                              goto retry;
                          else
                              return -11;
                      }
                      return ret;
                  } else {
                      /* Write single byte */
                      sflash_cmd(osh, cc, SFLASH_ST_CSA | *buf++);
                  }
                  ret++;
                  off++;
                  len--;
              }
              /* All done, drop cs & poll */
              W_REG(osh, &cc->sflashcontrol, 0);
              OSL_DELAY(1);
              if (sflash_poll(sih, cc, offset) != 0) {
                  /* Flash rejected command */
                  SFL_MSG(("sflash: pp rejected, tryn: %d, off: %d/%d,"
                           " len: %d/%d, ret: %d\n",
                           tryn, off, offset, len, length, ret));
                  if (tryn <= ST_RETRIES)
                      goto retry;
                  else
                      return -12;
              }
          } else {
              ret = 1;
              W_REG(osh, &cc->sflashaddress, off);
              W_REG(osh, &cc->sflashdata, *buf);
              /* Page program */
              sflash_cmd(osh, cc, SFLASH_ST_PP);
          }
#else /* !SFLASH_ST_PAGE_MODE_WRITE */
          off = offset;
          len = length;
          buf = buffer;
          if (sih->ccrev >= 20) {
              ret = 0;
              while (len > 0) {
                  /* Enable writes */
                  sflash_cmd(osh, cc, SFLASH_ST_WREN);
                  /* Drop cs before starting a page program */
                  W_REG(osh, &cc->sflashcontrol, 0);

                  W_REG(osh, &cc->sflashaddress, off);
                  quot = (len / 4);
                  remain = (len % 4);
                  if (quot != 0) { /* len >= 4 bytes */
                      wlen = 4;
                      reg_val = (*buf << 24);
                      buf++;
                      reg_val |= (*buf << 16);
                      buf++;
                      reg_val |= (*buf << 8);
                      buf++;
                      reg_val |= (*buf);
                      buf++;
                      W_REG(osh, &cc->sflashdata, reg_val);
                      /* Issue a page program with CSA bit set : opcode+3 addres & 4 data bytes */
                      sflash_cmd(osh, cc, (SFLASH_ST_CSA | SFLASH_ST_PP3A4D));
                  } else { /* len < 4 bytes */
                      wlen = 1;
                      W_REG(osh, &cc->sflashdata, *buf++);
                      /* Issue a page program with CSA bit set : opcode+3 addres & 1 data bytes */
                      sflash_cmd(osh, cc, (SFLASH_ST_CSA | SFLASH_ST_PP));
                  }
                  ret += wlen;
                  off += wlen;
                  len -= wlen;

                  /* A page program done(1 or 4 data bytes), drop cs & poll */
                  W_REG(osh, &cc->sflashcontrol, 0);
                  while (sflash_poll(sih, cc, offset) != 0) {
                      /* Poll until command completion */
                  }

                  /* Page boundary and return for 256 bytes write */
                  if ((off & 255) == 0) {
                      return ret;
                  }
              }
          } else {
              /* Enable writes */
              sflash_cmd(osh, cc, SFLASH_ST_WREN);
              ret = 1;
              W_REG(osh, &cc->sflashaddress, off);
              W_REG(osh, &cc->sflashdata, *buf);
              /* Page program */
              sflash_cmd(osh, cc, SFLASH_ST_PP);
          }
#endif  /* SFLASH_ST_PAGE_MODE_WRITE */
          break;
    case SFLASH_AT:
          mask = sfl->blocksize - 1;
          page = (off & ~mask) << 1;
          byte = off & mask;
          /* Read main memory page into buffer 1 */
          if (byte || (len < sfl->blocksize)) {
              W_REG(osh, &cc->sflashaddress, page);
              sflash_cmd(osh, cc, SFLASH_AT_BUF1_LOAD);
              /* 250 us for AT45DB321B */
              SPINWAIT(sflash_poll(sih, cc, offset), 1000);
              ASSERT(!sflash_poll(sih, cc, offset));
          }
          /* Write into buffer 1 */
          for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
              W_REG(osh, &cc->sflashaddress, byte++);
              W_REG(osh, &cc->sflashdata, *buf++);
              sflash_cmd(osh, cc, SFLASH_AT_BUF1_WRITE);
          }
          /* Write buffer 1 into main memory page */
          W_REG(osh, &cc->sflashaddress, page);
          sflash_cmd(osh, cc, SFLASH_AT_BUF1_PROGRAM);
          break;
    }
    
    return ret;
}
コード例 #7
0
ファイル: sflash.c プロジェクト: NieHao/Tomato-RAF
/* Write len bytes starting at offset into buf. Returns number of bytes
 * written. Caller should poll for completion.
 */
int
sflash_write(chipcregs_t *cc, uint offset, uint len, const uchar *buf)
{
	struct sflash *sfl;
	int ret = 0;
	bool is4712b0;
	uint32 page, byte, mask;

	if (!len)
		return 0;

	if ((offset + len) > sflash.size)
		return -22;

	sfl = &sflash;
	switch (sfl->type) {
	case SFLASH_ST:
		mask = R_REG(NULL, &cc->chipid);
		is4712b0 = (((mask & CID_ID_MASK) == BCM4712_CHIP_ID) &&
		            ((mask & CID_REV_MASK) == (3 << CID_REV_SHIFT)));
		/* Enable writes */
		sflash_cmd(cc, SFLASH_ST_WREN);
		if (is4712b0) {
			mask = 1 << 14;
			W_REG(NULL, &cc->flashaddress, offset);
			W_REG(NULL, &cc->flashdata, *buf++);
			/* Set chip select */
			OR_REG(NULL, &cc->gpioout, mask);
			/* Issue a page program with the first byte */
			sflash_cmd(cc, SFLASH_ST_PP);
			ret = 1;
			offset++;
			len--;
			while (len > 0) {
				if ((offset & 255) == 0) {
					/* Page boundary, drop cs and return */
					AND_REG(NULL, &cc->gpioout, ~mask);
					if (!sflash_poll(cc, offset)) {
						/* Flash rejected command */
						return -11;
					}
					return ret;
				} else {
					/* Write single byte */
					sflash_cmd(cc, *buf++);
				}
				ret++;
				offset++;
				len--;
			}
			/* All done, drop cs if needed */
			if ((offset & 255) != 1) {
				/* Drop cs */
				AND_REG(NULL, &cc->gpioout, ~mask);
				if (!sflash_poll(cc, offset)) {
					/* Flash rejected command */
					return -12;
				}
			}
		} else {
			ret = 1;
			W_REG(NULL, &cc->flashaddress, offset);
			W_REG(NULL, &cc->flashdata, *buf);
		/* Page program */
		sflash_cmd(cc, SFLASH_ST_PP);
		}
		break;
	case SFLASH_AT:
		mask = sfl->blocksize - 1;
		page = (offset & ~mask) << 1;
		byte = offset & mask;
		/* Read main memory page into buffer 1 */
		if (byte || (len < sfl->blocksize)) {
			W_REG(NULL, &cc->flashaddress, page);
			sflash_cmd(cc, SFLASH_AT_BUF1_LOAD);
			/* 250 us for AT45DB321B */
			SPINWAIT(sflash_poll(cc, offset), 1000);
			ASSERT(!sflash_poll(cc, offset));
		}
		/* Write into buffer 1 */
		for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
			W_REG(NULL, &cc->flashaddress, byte++);
			W_REG(NULL, &cc->flashdata, *buf++);
			sflash_cmd(cc, SFLASH_AT_BUF1_WRITE);
		}
		/* Write buffer 1 into main memory page */
		W_REG(NULL, &cc->flashaddress, page);
		sflash_cmd(cc, SFLASH_AT_BUF1_PROGRAM);
		break;
	}

	return ret;
}