Esempio n. 1
0
/* Read the status register of the external SPI flash chip. */
static int read_status_reg(struct flash_bank *bank, uint32_t *status)
{
	struct target *target = bank->target;
	struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
	uint32_t ssp_base = lpcspifi_info->ssp_base;
	uint32_t io_base = lpcspifi_info->io_base;
	uint32_t value;
	int retval = ERROR_OK;

	retval = ssp_setcs(target, io_base, 0);
	if (retval == ERROR_OK)
		retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_STATUS);
	if (retval == ERROR_OK)
		retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
	if (retval == ERROR_OK)
		retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
	/* Dummy write to clock in the register */
	if (retval == ERROR_OK)
		retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
	if (retval == ERROR_OK)
		retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
	if (retval == ERROR_OK)
		retval = ssp_setcs(target, io_base, 1);

	if (retval == ERROR_OK)
		retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
	if (retval == ERROR_OK)
		*status = value;

	return retval;
}
Esempio n. 2
0
/* Poll the SSP busy flag. When this comes back as 0, the transfer is complete
 * and the controller is idle. */
static int poll_ssp_busy(struct target *target, uint32_t ssp_base, int timeout)
{
	long long endtime;
	uint32_t value;
	int retval;

	retval = ssp_read_reg(target, ssp_base, SSP_SR, &value);
	if ((retval == ERROR_OK) && (value & SSP_BSY) == 0)
		return ERROR_OK;
	else if (retval != ERROR_OK)
		return retval;

	endtime = timeval_ms() + timeout;
	do {
		alive_sleep(1);
		retval = ssp_read_reg(target, ssp_base, SSP_SR, &value);
		if ((retval == ERROR_OK) && (value & SSP_BSY) == 0)
			return ERROR_OK;
		else if (retval != ERROR_OK)
			return retval;
	} while (timeval_ms() < endtime);

	LOG_ERROR("Timeout while polling BSY");
	return ERROR_FLASH_OPERATION_FAILED;
}
Esempio n. 3
0
static int lpcspifi_bulk_erase(struct flash_bank *bank)
{
	struct target *target = bank->target;
	struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
	uint32_t ssp_base = lpcspifi_info->ssp_base;
	uint32_t io_base = lpcspifi_info->io_base;
	uint32_t value;
	int retval = ERROR_OK;

	retval = lpcspifi_set_sw_mode(bank);

	if (retval == ERROR_OK)
		retval = lpcspifi_write_enable(bank);

	/* send SPI command "bulk erase" */
	if (retval == ERROR_OK)
		ssp_setcs(target, io_base, 0);
	if (retval == ERROR_OK)
		retval = ssp_write_reg(target, ssp_base, SSP_DATA, lpcspifi_info->dev->chip_erase_cmd);
	if (retval == ERROR_OK)
		retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
	if (retval == ERROR_OK)
		retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
	if (retval == ERROR_OK)
		retval = ssp_setcs(target, io_base, 1);

	/* poll flash BSY for self-timed bulk erase */
	if (retval == ERROR_OK)
		retval = wait_till_ready(bank, bank->num_sectors*SSP_MAX_TIMEOUT);

	return retval;
}
Esempio n. 4
0
/* Send "write enable" command to SPI flash chip. */
static int lpcspifi_write_enable(struct flash_bank *bank)
{
	struct target *target = bank->target;
	struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
	uint32_t ssp_base = lpcspifi_info->ssp_base;
	uint32_t io_base = lpcspifi_info->io_base;
	uint32_t status, value;
	int retval = ERROR_OK;

	retval = ssp_setcs(target, io_base, 0);
	if (retval == ERROR_OK)
		retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_WRITE_ENABLE);
	if (retval == ERROR_OK)
		retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
	if (retval == ERROR_OK)
		retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
	if (retval == ERROR_OK)
		retval = ssp_setcs(target, io_base, 1);

	/* read flash status register */
	if (retval == ERROR_OK)
		retval = read_status_reg(bank, &status);
	if (retval != ERROR_OK)
		return retval;

	/* Check write enabled */
	if ((status & SPIFLASH_WE_BIT) == 0) {
		LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
		return ERROR_FAIL;
	}

	return retval;
}
Esempio n. 5
0
/**
 * ssp_get_clkdiv - get SSP clock divider
 */
static u32 ssp_get_scr(struct ssp_device *ssp)
{
	u32 sscr0 = ssp_read_reg(ssp, SSCR0);
	u32 div;

	if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP)
		div = ((sscr0 >> 8) & 0xff) * 2 + 2;
	else
Esempio n. 6
0
/**
 * ssp_set_clkdiv - set SSP clock divider
 * @div: serial clock rate divider
 */
static void ssp_set_scr(struct ssp_device *ssp, u32 div)
{
	u32 sscr0 = ssp_read_reg(ssp, SSCR0);

	if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP) {
		sscr0 &= ~0x0000ff00;
		sscr0 |= ((div - 2)/2) << 8; /* 2..512 */
	} else {
		sscr0 &= ~0x000fff00;
		sscr0 |= (div - 1) << 8;     /* 1..4096 */
	}
	ssp_write_reg(ssp, SSCR0, sscr0);
}
Esempio n. 7
0
static void dump_registers(struct ssp_device *ssp)
{
	dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
		 ssp_read_reg(ssp, SSCR0), ssp_read_reg(ssp, SSCR1),
		 ssp_read_reg(ssp, SSTO));

	dev_dbg(&ssp->pdev->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n",
		 ssp_read_reg(ssp, SSPSP), ssp_read_reg(ssp, SSSR),
		 ssp_read_reg(ssp, SSACD));
}
Esempio n. 8
0
/* On exit, SW mode is kept */
static int lpcspifi_read_flash_id(struct flash_bank *bank, uint32_t *id)
{
	struct target *target = bank->target;
	struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
	uint32_t ssp_base = lpcspifi_info->ssp_base;
	uint32_t io_base = lpcspifi_info->io_base;
	uint32_t value;
	uint8_t id_buf[3];
	int retval;

	if (target->state != TARGET_HALTED) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	LOG_DEBUG("Getting ID");
	retval = lpcspifi_set_sw_mode(bank);
	if (retval != ERROR_OK)
		return retval;

	/* poll WIP */
	if (retval == ERROR_OK)
		retval = wait_till_ready(bank, SSP_PROBE_TIMEOUT);

	/* Send SPI command "read ID" */
	if (retval == ERROR_OK)
		retval = ssp_setcs(target, io_base, 0);
	if (retval == ERROR_OK)
		retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_ID);
	if (retval == ERROR_OK)
		retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
	if (retval == ERROR_OK)
		retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);

	/* Dummy write to clock in data */
	if (retval == ERROR_OK)
		retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
	if (retval == ERROR_OK)
		retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
	if (retval == ERROR_OK)
		retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
	if (retval == ERROR_OK)
		id_buf[0] = value;

	/* Dummy write to clock in data */
	if (retval == ERROR_OK)
		retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
	if (retval == ERROR_OK)
		retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
	if (retval == ERROR_OK)
		retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
	if (retval == ERROR_OK)
		id_buf[1] = value;

	/* Dummy write to clock in data */
	if (retval == ERROR_OK)
		retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
	if (retval == ERROR_OK)
		retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
	if (retval == ERROR_OK)
		retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
	if (retval == ERROR_OK)
		id_buf[2] = value;

	if (retval == ERROR_OK)
		retval = ssp_setcs(target, io_base, 1);
	if (retval == ERROR_OK)
		*id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0];

	return retval;
}