Пример #1
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;
}
Пример #2
0
static int smi_erase_sector(struct flash_bank *bank, int sector)
{
	struct target *target = bank->target;
	struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
	uint32_t io_base = stmsmi_info->io_base;
	uint32_t cmd;
	int retval;

	retval = smi_write_enable(bank);
	if (retval != ERROR_OK)
		return retval;

	/* Switch to SW mode to send sector erase command */
	SMI_SET_SW_MODE();

	/* clear transmit finished flag */
	SMI_CLEAR_TFF();

	/* send SPI command "block erase" */
	cmd = erase_command(stmsmi_info, bank->sectors[sector].offset);
	SMI_WRITE_REG(SMI_TR, cmd);
	SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_SEND | SMI_TX_LEN_4);

	/* Poll transmit finished flag */
	SMI_POLL_TFF(SMI_CMD_TIMEOUT);

	/* poll WIP for end of self timed Sector Erase cycle */
	retval = wait_till_ready(bank, SMI_MAX_TIMEOUT);
	if (retval != ERROR_OK)
		return retval;

	return ERROR_OK;
}
Пример #3
0
/**
 * spinand_erase_block--to erase a page with:
 * @block_id: the physical block location to erase.
 *
 * Description:
 *   The commands used here are 0x06 and 0xd8--indicating an erase
 *   command to erase one block--64 pages
 *   It will first to enable the write enable bit (0x06 command),
 *   and then send the 0xd8 erase command
 *   Poll to wait for the tERS time to complete the tranaction.
 */
static int spinand_erase_block(struct spi_device *spi_nand, u16 block_id)
{
	int retval;
	u8 status = 0;

	retval = spinand_write_enable(spi_nand);
	if (wait_till_ready(spi_nand))
		dev_err(&spi_nand->dev, "wait timedout!!!\n");

	retval = spinand_erase_block_erase(spi_nand, block_id);
	while (1) {
		retval = spinand_read_status(spi_nand, &status);
		if (retval < 0) {
			dev_err(&spi_nand->dev,
					"error %d reading status register\n",
					(int) retval);
			return retval;
		}

		if ((status & STATUS_OIP_MASK) == STATUS_READY) {
			if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL) {
				dev_err(&spi_nand->dev,
					"erase error, block %d\n", block_id);
				return -1;
			} else
				break;
		}
	}
	return 0;
}
Пример #4
0
/*
 * Write an address range to the nor chip.  Data must be written in
 * FLASH_PAGESIZE chunks.  The address range may be any size provided
 * it is within the physical boundaries.
 */
static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
	size_t *retlen, const u_char *buf)
{
	struct spi_nor *nor = mtd_to_spi_nor(mtd);
	u32 page_offset, page_size, i;
	int ret;

	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);

	ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE);
	if (ret)
		return ret;

	/* Wait until finished previous write command. */
	ret = wait_till_ready(nor);
	if (ret)
		goto write_err;

	write_enable(nor);

	page_offset = to & (nor->page_size - 1);

	/* do all the bytes fit onto one page? */
	if (page_offset + len <= nor->page_size) {
		nor->write(nor, to, len, retlen, buf);
	} else {
		/* the size of data remaining on the first page */
		page_size = nor->page_size - page_offset;
		nor->write(nor, to, page_size, retlen, buf);

		/* write everything in nor->page_size chunks */
		for (i = page_size; i < len; i += page_size) {
			page_size = len - i;
			if (page_size > nor->page_size)
				page_size = nor->page_size;

			wait_till_ready(nor);
			write_enable(nor);

			nor->write(nor, to + i, page_size, retlen, buf + i);
		}
	}

write_err:
	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
	return 0;
}
Пример #5
0
/*
 * spinand_read_page-to read a page with:
 * @page_id: the physical page number
 * @offset:  the location from 0 to 2111
 * @len:     number of bytes to read
 * @rbuf:    read buffer to hold @len bytes
 *
 * Description:
 *   The read includes two commands to the Nand: 0x13 and 0x03 commands
 *   Poll to read status to wait for tRD time.
 */
static int spinand_read_page(struct spi_device *spi_nand, u16 page_id,
		u16 offset, u16 len, u8 *rbuf)
{
	int ret;
	u8 status = 0;

#ifdef CONFIG_MTD_SPINAND_ONDIEECC
	if (enable_read_hw_ecc) {
		if (spinand_enable_ecc(spi_nand) < 0)
			dev_err(&spi_nand->dev, "enable HW ECC failed!");
	}
#endif
	ret = spinand_read_page_to_cache(spi_nand, page_id);
	if (ret < 0)
		return ret;

	if (wait_till_ready(spi_nand))
		dev_err(&spi_nand->dev, "WAIT timedout!!!\n");

	while (1) {
		ret = spinand_read_status(spi_nand, &status);
		if (ret < 0) {
			dev_err(&spi_nand->dev,
					"err %d read status register\n", ret);
			return ret;
		}

		if ((status & STATUS_OIP_MASK) == STATUS_READY) {
			if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) {
				dev_err(&spi_nand->dev, "ecc error, page=%d\n",
						page_id);
				return 0;
			}
			break;
		}
	}

	ret = spinand_read_from_cache(spi_nand, page_id, offset, len, rbuf);
	if (ret < 0) {
		dev_err(&spi_nand->dev, "read from cache failed!!\n");
		return ret;
	}

#ifdef CONFIG_MTD_SPINAND_ONDIEECC
	if (enable_read_hw_ecc) {
		ret = spinand_disable_ecc(spi_nand);
		if (ret < 0) {
			dev_err(&spi_nand->dev, "disable ecc failed!!\n");
			return ret;
		}
		enable_read_hw_ecc = 0;
	}
#endif
	return ret;
}
Пример #6
0
static int ath79_erase_sector(struct flash_bank *bank, int sector)
{
	int retval = ath79_write_enable(bank);

	if (retval != ERROR_OK)
		return retval;

	/* send SPI command "block erase" */
	retval = erase_command(bank, sector);
	if (retval != ERROR_OK)
		return retval;

	/* poll WIP for end of self timed Sector Erase cycle */
	return wait_till_ready(bank, ATH79_MAX_TIMEOUT);
}
Пример #7
0
/*
 * spinand_reset- send RESET command "0xff" to the Nand device.
 */
static void spinand_reset(struct spi_device *spi_nand)
{
	struct spinand_cmd cmd = {0};

	cmd.cmd = CMD_RESET;

	if (spinand_cmd(spi_nand, &cmd) < 0)
		pr_info("spinand reset failed!\n");

	/* elapse 1ms before issuing any other command */
	udelay(1000);

	if (wait_till_ready(spi_nand))
		dev_err(&spi_nand->dev, "wait timedout!\n");
}
Пример #8
0
/*
 * Erase the whole flash memory
 *
 * Returns 0 if successful, non-zero otherwise.
 */
static int erase_chip(struct spi_nor *nor)
{
	int ret;

	dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10));

	/* Wait until finished previous write command. */
	ret = wait_till_ready(nor);
	if (ret)
		return ret;

	/* Send write enable, then erase commands. */
	write_enable(nor);

	return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0);
}
Пример #9
0
static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
	struct spi_nor *nor = mtd_to_spi_nor(mtd);
	uint32_t offset = ofs;
	uint8_t status_old, status_new;
	int ret = 0;

	ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK);
	if (ret)
		return ret;

	/* Wait until finished previous command */
	ret = wait_till_ready(nor);
	if (ret)
		goto err;

	status_old = read_sr(nor);

	if (offset+len > mtd->size - (mtd->size / 64))
		status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0);
	else if (offset+len > mtd->size - (mtd->size / 32))
		status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0;
	else if (offset+len > mtd->size - (mtd->size / 16))
		status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1;
	else if (offset+len > mtd->size - (mtd->size / 8))
		status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
	else if (offset+len > mtd->size - (mtd->size / 4))
		status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2;
	else if (offset+len > mtd->size - (mtd->size / 2))
		status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
	else
		status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;

	/* Only modify protection if it will not lock other areas */
	if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) <
				(status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
		write_enable(nor);
		ret = write_sr(nor, status_new);
		if (ret)
			goto err;
	}

err:
	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
	return ret;
}
Пример #10
0
/*
 * Erase the whole flash memory
 *
 * Returns 0 if successful, non-zero otherwise.
 */
static int erase_chip(struct m25p *flash)
{
	DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n",
			flash->spi->dev.bus_id, __func__,
			flash->mtd.size / 1024);

	/* Wait until finished previous write command. */
	if (wait_till_ready(flash))
		return 1;

	/* Send write enable, then erase commands. */
	write_enable(flash);

	/* Set up command buffer. */
	flash->command[0] = OPCODE_CHIP_ERASE;

	spi_write(flash->spi, flash->command, 1);

	return 0;
}
Пример #11
0
static int macronix_quad_enable(struct spi_nor *nor)
{
	int ret, val;

	val = read_sr(nor);
	write_enable(nor);

	nor->cmd_buf[0] = val | SR_QUAD_EN_MX;
	nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0);

	if (wait_till_ready(nor))
		return 1;

	ret = read_sr(nor);
	if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) {
		dev_err(nor->dev, "Macronix Quad bit not set\n");
		return -EINVAL;
	}

	return 0;
}
Пример #12
0
/* On exit, SW mode is kept */
static int read_flash_id(struct flash_bank *bank, uint32_t *id)
{
	struct target *target = bank->target;
	struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
	uint32_t io_base = stmsmi_info->io_base;
	int retval;

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

	/* poll WIP */
	retval = wait_till_ready(bank, SMI_PROBE_TIMEOUT);
	if (retval != ERROR_OK)
		return retval;

	/* enter in SW mode */
	SMI_SET_SW_MODE();

	/* clear transmit finished flag */
	SMI_CLEAR_TFF();

	/* Send SPI command "read ID" */
	SMI_WRITE_REG(SMI_TR, SMI_READ_ID);
	SMI_WRITE_REG(SMI_CR2,
		stmsmi_info->bank_num | SMI_SEND | SMI_RX_LEN_3 | SMI_TX_LEN_1);

	/* Poll transmit finished flag */
	SMI_POLL_TFF(SMI_CMD_TIMEOUT);

	/* clear transmit finished flag */
	SMI_CLEAR_TFF();

	/* read ID from Receive Register */
	*id = SMI_READ_REG(SMI_RR) & 0x00ffffff;
	return ERROR_OK;
}
Пример #13
0
/*
 * Erase one sector of flash memory at offset ``offset'' which is any
 * address within the sector which should be erased.
 *
 * Returns 0 if successful, non-zero otherwise.
 */
static int erase_sector(struct m25p *flash, u32 offset)
{
	DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
			flash->spi->dev.bus_id, __FUNCTION__,
			flash->mtd.erasesize / 1024, offset);

	/* Wait until finished previous write command. */
	if (wait_till_ready(flash))
		return 1;

	/* Send write enable, then erase commands. */
	write_enable(flash);

	/* Set up command buffer. */
	flash->command[0] = flash->erase_opcode;
	flash->command[1] = offset >> 16;
	flash->command[2] = offset >> 8;
	flash->command[3] = offset;

	spi_write(flash->spi, flash->command, sizeof(flash->command));

	return 0;
}
Пример #14
0
Файл: robot.c Проект: pd0wm/epo2
// dir1 = curdir, dir2 = destdir
 void makeTurn(int dir1, int dir2, int curX, int curY)
 {
 	int rotation = 0;
 	rotation = dir2 - dir1;
 	if (rotation > 2)
 		rotation -= 4;
 	if (rotation < -2)
 		rotation += 4;

 	int penaltyLeft = 0, penaltyRight = 0;

 	if (curX == 0 && curY == 0) {
 		if (curDir == WEST) penaltyLeft = -1;
 		else if (curDir == SOUTH) penaltyRight = -1;
 	} else if (curX == 0 && curY == 4) {
 		if (curDir == NORTH) penaltyLeft = -1;
 		else if (curDir == WEST) penaltyRight = -1;
 	} else if (curX == 4 && curY == 0) {
 		if (curDir == SOUTH) penaltyLeft = -1;
 		else if (curDir == EAST) penaltyRight = -1;
 	} else if (curX == 4 && curY == 4) {
 		if (curDir == EAST) penaltyLeft = -1;
 		else if (curDir == NORTH) penaltyRight = -1;
 	}

	if (rotation < 0) { //turn left
		printf("Turn left %d\r\n", abs(rotation)+penaltyLeft);
		// getchar();
		setCommand(new_sck, TURN, 1, abs(rotation)+penaltyLeft, 0);
	} else if (rotation > 0) {//turn right
		printf("Turn right %d\r\n", rotation+penaltyRight);
		// getchar();
		setCommand(new_sck, TURN, 2, rotation+penaltyRight, 0);
	}
	wait_till_ready(new_sck);
}
Пример #15
0
static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
		size_t *retlen, const u_char *buf)
{
	struct spi_nor *nor = mtd_to_spi_nor(mtd);
	size_t actual;
	int ret;

	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);

	ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE);
	if (ret)
		return ret;

	/* Wait until finished previous write command. */
	ret = wait_till_ready(nor);
	if (ret)
		goto time_out;

	write_enable(nor);

	nor->sst_write_second = false;

	actual = to % 2;
	/* Start write from odd address. */
	if (actual) {
		nor->program_opcode = SPINOR_OP_BP;

		/* write one byte. */
		nor->write(nor, to, 1, retlen, buf);
		ret = wait_till_ready(nor);
		if (ret)
			goto time_out;
	}
	to += actual;

	/* Write out most of the data here. */
	for (; actual < len - 1; actual += 2) {
		nor->program_opcode = SPINOR_OP_AAI_WP;

		/* write two bytes. */
		nor->write(nor, to, 2, retlen, buf + actual);
		ret = wait_till_ready(nor);
		if (ret)
			goto time_out;
		to += 2;
		nor->sst_write_second = true;
	}
	nor->sst_write_second = false;

	write_disable(nor);
	ret = wait_till_ready(nor);
	if (ret)
		goto time_out;

	/* Write out trailing byte if it exists. */
	if (actual != len) {
		write_enable(nor);

		nor->program_opcode = SPINOR_OP_BP;
		nor->write(nor, to, 1, retlen, buf + actual);

		ret = wait_till_ready(nor);
		if (ret)
			goto time_out;
		write_disable(nor);
	}
time_out:
	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
	return ret;
}
Пример #16
0
/**
 * Second main function
 * @return
 */
int main_2() {
	// Initializations
	Position start, destination;
	Path_element *path = NULL;

	Path_element *robot_path;
	int x, y;



#ifdef CHALLENGE_AB
	int initial_facing_direction;
	int i;
	static int first_run = 1;

	if (first_run) {
		first_run = 0;

		// Get which places to user wants to visit
		getPlacesToVisit();
	}


	// Reset no_total_path_possible
	no_total_path_possible = 0;
#endif

	// Unvisit all places
	unvisitAll();

	// Seed the rand() function
	srand(time(NULL));
#ifdef CHALLENGE_AB
	// Randomize facing direction
	initial_facing_direction = NORTH;// = rand() % 4 + 1;
#endif

	// Initialize grid
	generateGrid();

#if MINES_ACTIVE == 1
	// Create mines
	// createMines();
	//	removeConnection(0,0,1,0);
	//	removeConnection(1,0,2,0);
	//	removeConnection(0,2,1,2);
	//	removeConnection(2,2,3,2);
	//	removeConnection(3,3,4,3);
	//	removeConnection(0,0,0,1);
	//	removeConnection(1,0,1,1);
	//	removeConnection(1,3,1,4);
	//	removeConnection(2,1,2,2);
	//	removeConnection(2,3,2,4);
	//	removeConnection(3,0,3,1);
	//	removeConnection(4,0,4,1);
	//	removeConnection(4,1,4,2);

	//	removeConnection(0,0,0,1);
	//	removeConnection(1,3,1,2);
	//	removeConnection(2,2,2,3);
	//	removeConnection(4,1,4,2);
#endif

	// Define the start position in the bottom left
	start.x = destination.x = 1;
	start.y = destination.y = 0;

#if MINES_ACTIVE == 1
	// Discover mines at start location
	// discoverMines(start.x, start.y);
#endif

#ifdef CHALLENGE_AB
	int key, q;
	goto go2;
	frombeginning2:
	cls_2();
	printf("Place the robot at the beginning, type '1' to continue...\n");
	key = 0;
	while (!key) { scanf("%d",&key); }
	go2:

	curDir = 0;

	setCommand(new_sck, MOVE, 1, 1, 0);
	wait_till_ready(new_sck);

	setCommand(new_sck, POS, 0, start.x+1, start.y+1);
	wait_till_ready(new_sck);

	// Get first destination
	destination.x = places_to_visit[getTargetPlace(start.x, start.y, initial_facing_direction, 0)][0];
	destination.y = places_to_visit[getTargetPlace(start.x, start.y, initial_facing_direction, 0)][1];

	// Create the robot_path linked list
	robot_path = malloc(sizeof (Path_element));
	robot_path->x = start.x;
	robot_path->y = start.y;
	robot_path->facing_direction = initial_facing_direction;
	robot_path->next = NULL;

	for (q = 0; q < NUM_NODES; q++) getNodeById(q)->mark = 0;

	// Mark places to visit
		for (i = 0; i < NUMBER_OF_PLACES_TO_VISIT; i++) {
			if (!places_to_visit[i][2])
				grid[places_to_visit[i][0]][places_to_visit[i][1]]->mark = 49 + i;
		}

	// Find initial path
		path = findShortestPath(start.x, start.y, initial_facing_direction, destination.x, destination.y);

	// If path == NULL, there was no path found
		if (!path || no_total_path_possible) {
		// Clear screen, print the grid, display a message, sleep for a while and then rerun the program
			cls_2();
			printGrid(robot_path);
			printf("\nCouldn't find a intial path...\n");
		// getchar();
		// main();
			return 0;
		}

	// Record start
		x = start.x;
		y = start.y;

	// Display first move
		cls_2();
		printGrid(robot_path);
	// getchar();
		int moveCorrect = 1;

		while (1) {
			if (kbhit()) goto frombeginning2;

			if (moveCorrect) path = path->next;
		// addToEndOfPath(&robot_path, path->x, path->y);
			if (x == path->x && y == path->y) {
				path = path->next;
			}

			int prevfd = path->facing_direction;

			if (makeMove(x,y,path->x,path->y)) {
				moveCorrect = 1;
				x = path->x;
				y = path->y;


			} else {
				printf("Returned mine between (%d,%d)<curr pos> and (%d,%d)\n",x,y,path->x,path->y);
				removeConnection(x,y,path->x,path->y);
				moveCorrect = 0;

			// prevfd = reverseDirection(prevfd);
			}


		// Move and save position and step weight, also add the position to the path
			if (moveCorrect) {
				path = path->next;
				addToEndOfPath(&robot_path, x, y);
			}

		// printf("VISIT\n");
			visit(x, y);
		// printf("VISITED ALL PLACES\n");
			if (visitedAllPlaces()) break;

		// printf("getTargetPlace\n");

 		// Get destination
			destination.x = places_to_visit[getTargetPlace(x, y, prevfd, 0)][0];
			destination.y = places_to_visit[getTargetPlace(x, y, prevfd, 0)][1];



// #if MINES_ACTIVE == 1
		// Check for mines
		// discoverMines(x, y);

		// Now filter combs for discovered mines

// #endif
		// Calculate new path, mines couldve changed something
// printf("New path %d,%d  %d  %d, %d\n",x,y,prevfd,destination.x,destination.y);

			path = findShortestPath(
			                        x, y,
			                        prevfd,
			                        destination.x,
			                        destination.y
			                        );

		// printf("kay\n");

		// If path == NULL, there was no path found
			if (!path || no_total_path_possible) {
				cls_2();
				printGrid(robot_path);
				printf("Could not find a path!\n");
				getchar();
				return 0;
			}

						// Display path and add step weight to path weight
			cls_2();
			printGrid(robot_path);
			getTargetPlace(x, y, path->facing_direction, DEBUG);
						// getchar();
		}

				// #if MINES_ACTIVE == 1
				// 	// Reveal mines
				// 	revealMines();
// #endif

	// Display final screen
		cls_2();
		printGrid(robot_path);
		printf("\nDone.\n");
		getchar();
#endif

#ifdef CHALLENGE_C
	// Find initial path
	int *combs;
	int index;
	int q;


	// clear grid markings


	// Some unreadable shit which makes things work like they should
	cls_2();
	printf("Press enter to start...\n"); getchar();
	int antiMine = 0;
	rerun:
	goto go3;
	antimine:
	antiMine = 1;
	go3:
	stepsTakenSize = 0;
	index = 0;
	int key;
	goto go2;
	frombeginning:
	cls_2();
	printf("Place the robot at the beginning, type '1' to continue, '9' to restart or '5' to restart in anti-mine mode...\n");
	key = 0;
	while (key==0) { scanf("%d",&key); }
	if(key==9) goto rerun;
	if(key==5) goto antimine;
	go2:

	curDir = 0;

	setCommand(new_sck, MOVE, 1, 1, 0);
	wait_till_ready(new_sck);

	for (q = 0; q < NUM_NODES; q++) getNodeById(q)->mark = 0;

		robot_path = malloc(sizeof (Path_element));
	robot_path->x = start.x;
	robot_path->y = start.y;
	robot_path->next = NULL;

	cls_2();
	printGrid(robot_path);

	setCommand(new_sck, POS, 0, start.x+1, start.y+1);
	wait_till_ready(new_sck);

	x = start.x;
	y = start.y;

	// Find initial path
	combs = exploreArea(grid[start.x][start.y]->id);



	// If path == NULL, there was no path found
	if (!combs) {
		// Clear screen, print the grid, display a message, sleep for a while and then rerun the program
		printf("\nCouldn't find a intial path...\n");
		getchar();
		// main();
		return 0;
	}

	while (1) {
		// Start by removing the path walked from the current combs
		int i;//, fins = 1;

		for (i = 0; combs[i] != -2; i+=2) {
			if (inStepsTaken(combs[i],combs[i+1])) {
				combs[i] = combs[i+1] = -1;
			}
		}
		// Check if there is a comb available
		if (combs[index] == -1) {
			index += 2;
			continue;
		}

		if (combs[index] == -2) break;

		// First walk to first node
		int nodeNow = combs[index];
		int nodeTo = combs[index+1];

		//printf

		path = findShortestPath(x, y,
		                        (path?path->facing_direction:NORTH),
			// 1,
		                        getNodeById(nodeNow)->positionGrid.x,
		                        getNodeById(nodeNow)->positionGrid.y);

		int failed = 0;
		int intcpt = 0;

		while (!(x == getNodeById(nodeNow)->positionGrid.x && y == getNodeById(nodeNow)->positionGrid.y)) {
			if (kbhit()) goto frombeginning;

			if (path && x == path->x && y == path->y) path = path->next;
			else if (!path) {
				printf("FAIL!\n");
				getchar();
				intcpt = 1;
				failed = 1;
				break;
			}

			// printf("Making first MOVE!\n");
			if (makeMove(x,y,path->x,path->y)) {

				stepTaken(grid[x][y]->id,grid[path->x][path->y]->id);
				// printf("Step correct! (from %d to %d)\n", grid[x][y]->id,grid[path->x][path->y]->id);getchar();
				x = path->x;
				y = path->y;
				path = path->next;
				addToEndOfPath(&robot_path, x, y);
			} else {
				if (antiMine) goto frombeginning;
				removeConnection(x,y,path->x,path->y);
				failed = 1;
				break;
			}

			cls_2();
			printGrid(robot_path);
		}

	if (failed) { // Soooo it failed, boohoo.
		if (!intcpt) islandSN(grid[x][y]->id);
			//cls_2();
		printf("Recalculating...\n");
		combs = exploreArea(grid[x][y]->id);
		index = 0;


		cls_2();
		printGrid(robot_path);
		continue;
	}

		// Okay now walk to second node

	path = findShortestPath(x, y,
	                        (path?path->facing_direction:NORTH),
	                        getNodeById(nodeTo)->positionGrid.x,
	                        getNodeById(nodeTo)->positionGrid.y);

	while (!(x == getNodeById(nodeTo)->positionGrid.x && y == getNodeById(nodeTo)->positionGrid.y)) {
		if (kbhit()) goto frombeginning;

		if (path && x == path->x && y == path->y) path = path->next;
		else if (!path) {
			printf("FAIL!\n");
			getchar();
			intcpt = 1;
			failed = 1;
			break;
		}

		if (makeMove(x,y,path->x,path->y)) {
			stepTaken(grid[x][y]->id,grid[path->x][path->y]->id);
				// printf("Step correct! (from %d to %d)\n", grid[x][y]->id,grid[path->x][path->y]->id);getchar();
			x = path->x;
			y = path->y;
			path = path->next;
			addToEndOfPath(&robot_path, x, y);
		} else {
			if (antiMine) goto frombeginning;
			removeConnection(x,y,path->x,path->y);
			failed = 1;
			break;
		}

		cls_2();
		printGrid(robot_path);
	}

		if (failed) { // Soooo it failed, boohoo.
			if (!intcpt) islandSN(grid[x][y]->id);
			//cls_2();
			printf("Recalculating...\n");
			combs = exploreArea(grid[x][y]->id);
			index = 0;
			// islandSN(grid[x][y]->id);

			cls_2();
			printGrid(robot_path);
			continue;
		}

		// Guess everything went okay
		index += 2;
	}

	printf("Aaaaaaaaaaaaaand we're done, type '1' to rerun and '5' to rerun in anti-mine mode!\n");
	key = 0;
	while (key==0) { scanf("%d",&key); }
	if (key==1)	goto rerun;
	else if(key==5) goto antimine;

#endif

	return EXIT_SUCCESS;
}
Пример #17
0
Файл: robot.c Проект: pd0wm/epo2
int makeMove(int x1, int y1, int x2, int y2)
{
	int val1;
	printf("Making move from (%d,%d) to (%d,%d)\n", x1, y1, x2, y2);
	setCommand(new_sck, MINE, 1, 0, 0);

	// getchar();
	// Dafuq why would you call me?!
	if(x1==x2 && y1==y2)
		return 1;

	// (if needed) Turn and make the move
	int dir = findDirection(x1, y1, x2, y2);
	makeTurn(curDir, dir, x1, y1);
	// update direction
	curDir = dir;
	printf("Dir set to %d\n", dir);
	// getchar();

	// Make 2 moves
	setCommand(new_sck, MOVE, 1, 2, 0);
	wait_till_ready(new_sck);

	printf("Check for mine\n");
	getCommand(new_sck, sckfd, MINE, 1, &val1, NULL);
	// A mine was found, we're not on our destination
	if (val1 == 1) {

		//wait_till_ready(new_sck);
		printf("Mine found!\n");
		// getchar();


		// Move in reverse
		setCommand(new_sck, MOVE, 1, 4, 0);
		wait_till_ready(new_sck);

		setCommand(new_sck, MINE, 1, 0, 0);


		dir=curDir;
		return 0;
	}
	// We're on the destination
	else {
		printf("No mine found!\n");
		// Check wether we are heading to our final destination
		if(isPlaceToVisit(x2, y2)) {
			// Turn into exit

			#ifdef SMART_VISIT
			if (x2 == 4){
				if (curDir != EAST) {
					makeTurn(curDir, EAST, x1, y1);
					curDir = EAST;
				}
			}else if(x2 == 0){
				if (curDir != WEST) {
					makeTurn(curDir, WEST, x1, y1);
					curDir = WEST;
				}
			}else if(y2 == 0){
				if (curDir != SOUTH) {
					makeTurn(curDir, SOUTH, x1, y1);
					curDir = SOUTH;
				}
			}else if(y2 == 4){
				if (curDir != NORTH) {
					makeTurn(curDir, NORTH, x1, y1);
					curDir = NORTH;
				}
			}
			#else
			if (x2 == 4){
				makeTurn(curDir, EAST, x1, y1);
				curDir = WEST;
			}else if(x2 == 0){
				makeTurn(curDir, WEST, x1, y1);
				curDir = EAST;
			}else if(y2 == 0){
				makeTurn(curDir, SOUTH, x1, y1);
				curDir = NORTH;
			}else if(y2 == 4){
				makeTurn(curDir, NORTH, x1, y1);
				curDir = SOUTH;
			}
				// Move until white is seen by sensor
			setCommand(new_sck, MOVE, 1, 3, 0);
			wait_till_ready(new_sck);
				// Draai 180 graden
			setCommand(new_sck, TURN, 2, 1, 0);
			wait_till_ready(new_sck);
				// Ga weer terug naar kruispunt
			setCommand(new_sck, MOVE, 1, 1, 0);
			wait_till_ready(new_sck);
			#endif
		}
		return 1;
	}
	return 0;
}
Пример #18
0
/*
 * Read an address range from the flash chip.  The address range
 * may be any size provided it is within the physical boundaries.
 */
static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
	size_t *retlen, u_char *buf)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	struct spi_transfer t[2];
	struct spi_message m;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
			flash->spi->dev.bus_id, __func__, "from",
			(u32)from, len);

	/* sanity checks */
	if (!len)
		return 0;

	if (from + len > flash->mtd.size)
		return -EINVAL;

	spi_message_init(&m);
	memset(t, 0, (sizeof t));

	/* NOTE:
	 * OPCODE_FAST_READ (if available) is faster.
	 * Should add 1 byte DUMMY_BYTE.
	 */
	t[0].tx_buf = flash->command;
	t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
	spi_message_add_tail(&t[0], &m);

	t[1].rx_buf = buf;
	t[1].len = len;
	spi_message_add_tail(&t[1], &m);

	/* Byte count starts at zero. */
	if (retlen)
		*retlen = 0;

	mutex_lock(&flash->lock);

	/* Wait till previous write/erase is done. */
	if (wait_till_ready(flash)) {
		/* REVISIT status return?? */
		mutex_unlock(&flash->lock);
		return 1;
	}

	/* FIXME switch to OPCODE_FAST_READ.  It's required for higher
	 * clocks; and at this writing, every chip this driver handles
	 * supports that opcode.
	 */

	/* Set up the write data buffer. */
	flash->command[0] = OPCODE_READ;
	flash->command[1] = from >> 16;
	flash->command[2] = from >> 8;
	flash->command[3] = from;

	spi_sync(flash->spi, &m);

	*retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;

	mutex_unlock(&flash->lock);

	return 0;
}
Пример #19
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;
}
Пример #20
0
/*
 * Write an address range to the flash chip.  Data must be written in
 * FLASH_PAGESIZE chunks.  The address range may be any size provided
 * it is within the physical boundaries.
 */
static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
	size_t *retlen, const u_char *buf)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	u32 page_offset, page_size;
	struct spi_transfer t[2];
	struct spi_message m;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
			flash->spi->dev.bus_id, __func__, "to",
			(u32)to, len);

	if (retlen)
		*retlen = 0;

	/* sanity checks */
	if (!len)
		return(0);

	if (to + len > flash->mtd.size)
		return -EINVAL;

	spi_message_init(&m);
	memset(t, 0, (sizeof t));

	t[0].tx_buf = flash->command;
	t[0].len = CMD_SIZE;
	spi_message_add_tail(&t[0], &m);

	t[1].tx_buf = buf;
	spi_message_add_tail(&t[1], &m);

	mutex_lock(&flash->lock);

	/* Wait until finished previous write command. */
	if (wait_till_ready(flash)) {
		mutex_unlock(&flash->lock);
		return 1;
	}

	write_enable(flash);

	/* Set up the opcode in the write buffer. */
	flash->command[0] = OPCODE_PP;
	flash->command[1] = to >> 16;
	flash->command[2] = to >> 8;
	flash->command[3] = to;

	/* what page do we start with? */
	page_offset = to % FLASH_PAGESIZE;

	/* do all the bytes fit onto one page? */
	if (page_offset + len <= FLASH_PAGESIZE) {
		t[1].len = len;

		spi_sync(flash->spi, &m);

		*retlen = m.actual_length - CMD_SIZE;
	} else {
		u32 i;

		/* the size of data remaining on the first page */
		page_size = FLASH_PAGESIZE - page_offset;

		t[1].len = page_size;
		spi_sync(flash->spi, &m);

		*retlen = m.actual_length - CMD_SIZE;

		/* write everything in PAGESIZE chunks */
		for (i = page_size; i < len; i += page_size) {
			page_size = len - i;
			if (page_size > FLASH_PAGESIZE)
				page_size = FLASH_PAGESIZE;

			/* write the next page to flash */
			flash->command[1] = (to + i) >> 16;
			flash->command[2] = (to + i) >> 8;
			flash->command[3] = (to + i);

			t[1].tx_buf = buf + i;
			t[1].len = page_size;

			wait_till_ready(flash);

			write_enable(flash);

			spi_sync(flash->spi, &m);

			if (retlen)
				*retlen += m.actual_length - CMD_SIZE;
		}
	}

	mutex_unlock(&flash->lock);

	return 0;
}
Пример #21
0
static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
		int column, int page)
{
	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
	struct spinand_info *info = (struct spinand_info *)chip->priv;
	struct spinand_state *state = (struct spinand_state *)info->priv;

	switch (command) {
	/*
	 * READ0 - read in first  0x800 bytes
	 */
	case NAND_CMD_READ1:
	case NAND_CMD_READ0:
		state->buf_ptr = 0;
		spinand_read_page(info->spi, page, 0x0, 0x840, state->buf);
		break;
	/* READOOB reads only the OOB because no ECC is performed. */
	case NAND_CMD_READOOB:
		state->buf_ptr = 0;
		spinand_read_page(info->spi, page, 0x800, 0x40, state->buf);
		break;
	case NAND_CMD_RNDOUT:
		state->buf_ptr = column;
		break;
	case NAND_CMD_READID:
		state->buf_ptr = 0;
		spinand_read_id(info->spi, (u8 *)state->buf);
		break;
	case NAND_CMD_PARAM:
		state->buf_ptr = 0;
		break;
	/* ERASE1 stores the block and page address */
	case NAND_CMD_ERASE1:
		spinand_erase_block(info->spi, page);
		break;
	/* ERASE2 uses the block and page address from ERASE1 */
	case NAND_CMD_ERASE2:
		break;
	/* SEQIN sets up the addr buffer and all registers except the length */
	case NAND_CMD_SEQIN:
		state->col = column;
		state->row = page;
		state->buf_ptr = 0;
		break;
	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
	case NAND_CMD_PAGEPROG:
		spinand_program_page(info->spi, state->row, state->col,
				state->buf_ptr, state->buf);
		break;
	case NAND_CMD_STATUS:
		spinand_get_otp(info->spi, state->buf);
		if (!(state->buf[0] & 0x80))
			state->buf[0] = 0x80;
		state->buf_ptr = 0;
		break;
	/* RESET command */
	case NAND_CMD_RESET:
		if (wait_till_ready(info->spi))
			dev_err(&info->spi->dev, "WAIT timedout!!!\n");
		/* a minimum of 250us must elapse before issuing RESET cmd*/
		udelay(250);
		spinand_reset(info->spi);
		break;
	default:
		dev_err(&mtd->dev, "Unknown CMD: 0x%x\n", command);
	}
}
Пример #22
0
/**
 * spinand_program_page--to write a page with:
 * @page_id: the physical page location to write the page.
 * @offset:  the location from the cache starting from 0 to 2111
 * @len:     the number of bytes to write
 * @wbuf:    the buffer to hold the number of bytes
 *
 * Description:
 *   The commands used here are 0x06, 0x84, and 0x10--indicating that
 *   the write enable is first sent, the write cache command, and the
 *   write execute command.
 *   Poll to wait for the tPROG time to finish the transaction.
 */
static int spinand_program_page(struct spi_device *spi_nand,
		u16 page_id, u16 offset, u16 len, u8 *buf)
{
	int retval;
	u8 status = 0;
	uint8_t *wbuf;
#ifdef CONFIG_MTD_SPINAND_ONDIEECC
	unsigned int i, j;

	enable_read_hw_ecc = 0;
	wbuf = devm_kzalloc(&spi_nand->dev, CACHE_BUF, GFP_KERNEL);
	spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf);

	for (i = offset, j = 0; i < len; i++, j++)
		wbuf[i] &= buf[j];

	if (enable_hw_ecc) {
		retval = spinand_enable_ecc(spi_nand);
		if (retval < 0) {
			dev_err(&spi_nand->dev, "enable ecc failed!!\n");
			return retval;
		}
	}
#else
	wbuf = buf;
#endif
	retval = spinand_write_enable(spi_nand);
	if (retval < 0) {
		dev_err(&spi_nand->dev, "write enable failed!!\n");
		return retval;
	}
	if (wait_till_ready(spi_nand))
		dev_err(&spi_nand->dev, "wait timedout!!!\n");

	retval = spinand_program_data_to_cache(spi_nand, page_id,
			offset, len, wbuf);
	if (retval < 0)
		return retval;
	retval = spinand_program_execute(spi_nand, page_id);
	if (retval < 0)
		return retval;
	while (1) {
		retval = spinand_read_status(spi_nand, &status);
		if (retval < 0) {
			dev_err(&spi_nand->dev,
					"error %d reading status register\n",
					retval);
			return retval;
		}

		if ((status & STATUS_OIP_MASK) == STATUS_READY) {
			if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) {
				dev_err(&spi_nand->dev,
					"program error, page %d\n", page_id);
				return -1;
			} else
				break;
		}
	}
#ifdef CONFIG_MTD_SPINAND_ONDIEECC
	if (enable_hw_ecc) {
		retval = spinand_disable_ecc(spi_nand);
		if (retval < 0) {
			dev_err(&spi_nand->dev, "disable ecc failed!!\n");
			return retval;
		}
		enable_hw_ecc = 0;
	}
#endif

	return 0;
}
Пример #23
0
static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
		size_t *retlen, const u_char *buf)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	struct spi_transfer t[2];
	struct spi_message m;
	size_t actual;
	int cmd_sz, ret;

	if (retlen)
		*retlen = 0;

	/* sanity checks */
	if (!len)
		return 0;

	if (to + len > flash->mtd.size)
		return -EINVAL;

	spi_message_init(&m);
	memset(t, 0, (sizeof t));

	t[0].tx_buf = flash->command;
	t[0].len = CMD_SIZE;
	spi_message_add_tail(&t[0], &m);

	t[1].tx_buf = buf;
	spi_message_add_tail(&t[1], &m);

	mutex_lock(&flash->lock);

	/* Wait until finished previous write command. */
	ret = wait_till_ready(flash);
	if (ret)
		goto time_out;

	write_enable(flash);

	actual = to % 2;
	/* Start write from odd address. */
	if (actual) {
		flash->command[0] = OPCODE_BP;
		flash->command[1] = to >> 16;
		flash->command[2] = to >> 8;
		flash->command[3] = to;

		/* write one byte. */
		t[1].len = 1;
		spi_sync(flash->spi, &m);
		ret = wait_till_ready(flash);
		if (ret)
			goto time_out;
		*retlen += m.actual_length - CMD_SIZE;
	}
	to += actual;

	flash->command[0] = OPCODE_AAI_WP;
	flash->command[1] = to >> 16;
	flash->command[2] = to >> 8;
	flash->command[3] = to;

	cmd_sz = CMD_SIZE;
	for (; actual < len - 1; actual += 2) {
		t[0].len = cmd_sz;
		/* write two bytes. */
		t[1].len = 2;
		t[1].tx_buf = buf + actual;

		spi_sync(flash->spi, &m);
		ret = wait_till_ready(flash);
		if (ret)
			goto time_out;
		*retlen += m.actual_length - cmd_sz;
		cmd_sz = 1;
		to += 2;
	}
	write_disable(flash);
	ret = wait_till_ready(flash);
	if (ret)
		goto time_out;

	if (actual != len) {
		write_enable(flash);
		flash->command[0] = OPCODE_BP;
		flash->command[1] = to >> 16;
		flash->command[2] = to >> 8;
		flash->command[3] = to;
		t[0].len = CMD_SIZE;
		t[1].len = 1;
		t[1].tx_buf = buf + actual;

		spi_sync(flash->spi, &m);
		ret = wait_till_ready(flash);
		if (ret)
			goto time_out;
		*retlen += m.actual_length - CMD_SIZE;
		write_disable(flash);
	}
Пример #24
0
/*
 * Erase an address range on the flash chip.  The address range may extend
 * one or more erase sectors.  Return an error is there is a problem erasing.
 */
static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	u32 addr,len;
	uint64_t tmpdiv;
	int rem, rem1;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
			flash->spi->dev.bus_id, __FUNCTION__, "at",
			(u32)instr->addr, instr->len);

	/* sanity checks */
	if (instr->addr + instr->len > device_size(&(flash->mtd)))
		return -EINVAL;
	tmpdiv = (uint64_t) instr->addr;
 	rem = do_div(tmpdiv, mtd->erasesize);
	tmpdiv = (uint64_t) instr->len;
	rem1 = do_div(tmpdiv, mtd->erasesize);
	if (rem != 0 || rem1 != 0) {
		return -EINVAL;
	}

	addr = instr->addr;
	len = instr->len;

	mutex_lock(&flash->lock);

	/* REVISIT in some cases we could speed up erasing large regions
	 * by using OPCODE_SE instead of OPCODE_BE_4K
	 */

	/* now erase those sectors */
	while (len) {
#ifdef CONFIG_MIPS_BRCM97XXX
		/* BSPI remaps each 4MB segment */
		if (erase_sector(flash, (addr + 0x400000) & 0xffffff)) {
#else
		if (erase_sector(flash, addr)) {
#endif
			instr->state = MTD_ERASE_FAILED;
			mutex_unlock(&flash->lock);
			return -EIO;
		}

		addr += mtd->erasesize;
		len -= mtd->erasesize;
	}

	mutex_unlock(&flash->lock);

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

	return 0;
}

/*
 * Read an address range from the flash chip.  The address range
 * may be any size provided it is within the physical boundaries.
 */
static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
	size_t *retlen, u_char *buf)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	struct spi_transfer t[2];
	struct spi_message m;
	size_t total_len = len;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
			flash->spi->dev.bus_id, __FUNCTION__, "from",
			(u32)from, len);

	/* sanity checks */
	if (!len)
		return 0;

	if (from + len > device_size(&(flash->mtd)))
		return -EINVAL;

	if (retlen)
		*retlen = 0;

	total_len = len;
	while(total_len) {
		len = total_len;

#if 0 //defined(BRCM_SPI_SS_WAR)
	/*
	 * For testing purposes only - read 12 bytes at a time:
	 *
	 * 3548a0 MSPI has a 12-byte limit (PR42350).
	 * MSPI emulated via BSPI has no such limit.
	 * In production BSPI is always used because it is much faster.
	 */
		if(len > 12)
			len = 12;
#endif
#ifdef CONFIG_MIPS_BRCM97XXX
		/* don't cross a 4MB boundary due to remapping */
		len = min(len, (0x400000 - ((u32)from & 0x3fffff)));
#endif
		spi_message_init(&m);
		memset(t, 0, (sizeof t));

		t[0].tx_buf = flash->command;
		t[0].len = sizeof(flash->command);
		spi_message_add_tail(&t[0], &m);

		t[1].rx_buf = buf;
		t[1].len = len;
		spi_message_add_tail(&t[1], &m);

		/* Byte count starts at zero. */

		mutex_lock(&flash->lock);

		/* Wait till previous write/erase is done. */
		if (wait_till_ready(flash)) {
			/* REVISIT status return?? */
			mutex_unlock(&flash->lock);
			return 1;
		}

		/* FIXME switch to OPCODE_FAST_READ.  It's required for higher
		 * clocks; and at this writing, every chip this driver handles
		 * supports that opcode.
		 */

		/* Set up the write data buffer. */
		flash->command[0] = OPCODE_READ;
#ifdef CONFIG_MIPS_BRCM97XXX
		/* BSPI remaps each 4MB segment */
		flash->command[1] = ((from >> 16) + 0x40) & 0xff;
#else
		flash->command[1] = from >> 16;
#endif
		flash->command[2] = from >> 8;
		flash->command[3] = from;

		spi_sync(flash->spi, &m);

		*retlen += m.actual_length - sizeof(flash->command);

		mutex_unlock(&flash->lock);

		from += len;
		buf += len;
		total_len -= len;
	}

	return 0;
}

/*
 * Write an address range to the flash chip.  Data must be written in
 * FLASH_PAGESIZE chunks.  The address range may be any size provided
 * it is within the physical boundaries.
 */
static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
	size_t *retlen, const u_char *buf)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	u32 page_offset, page_size;
	struct spi_transfer t[2];
	struct spi_message m;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
			flash->spi->dev.bus_id, __FUNCTION__, "to",
			(u32)to, len);

	if (retlen)
		*retlen = 0;

	/* sanity checks */
	if (!len)
		return(0);

	if (to + len > device_size(&(flash->mtd)))
		return -EINVAL;
#ifdef BRCM_SPI_SS_WAR
	if(len > 12)
		return -EIO;
#endif

	spi_message_init(&m);
	memset(t, 0, (sizeof t));

	t[0].tx_buf = flash->command;
	t[0].len = sizeof(flash->command);
	spi_message_add_tail(&t[0], &m);

	t[1].tx_buf = buf;
	spi_message_add_tail(&t[1], &m);

	mutex_lock(&flash->lock);

	/* Wait until finished previous write command. */
	if (wait_till_ready(flash))
		return 1;

	write_enable(flash);

	/* Set up the opcode in the write buffer. */
	flash->command[0] = OPCODE_PP;
#ifdef CONFIG_MIPS_BRCM97XXX
	/* BSPI remaps each 4MB segment */
	flash->command[1] = ((to >> 16) + 0x40) & 0xff;
#else
	flash->command[1] = to >> 16;
#endif
	flash->command[2] = to >> 8;
	flash->command[3] = to;

	/* what page do we start with? */
	page_offset = to % FLASH_PAGESIZE;

	/* do all the bytes fit onto one page? */
	if (page_offset + len <= FLASH_PAGESIZE) {
		t[1].len = len;

		spi_sync(flash->spi, &m);

		*retlen = m.actual_length - sizeof(flash->command);
	} else {
		u32 i;

		/* the size of data remaining on the first page */
		page_size = FLASH_PAGESIZE - page_offset;

		t[1].len = page_size;
		spi_sync(flash->spi, &m);

		*retlen = m.actual_length - sizeof(flash->command);

		/* write everything in PAGESIZE chunks */
		for (i = page_size; i < len; i += page_size) {
			page_size = len - i;
			if (page_size > FLASH_PAGESIZE)
				page_size = FLASH_PAGESIZE;

			/* write the next page to flash */
#ifdef CONFIG_MIPS_BRCM97XXX
			/* BSPI remaps each 4MB segment */
			flash->command[1] = (((to + i) >> 16) + 0x40) & 0xff;
#else
			flash->command[1] = (to + i) >> 16;
#endif
			flash->command[2] = (to + i) >> 8;
			flash->command[3] = (to + i);

			t[1].tx_buf = buf + i;
			t[1].len = page_size;

			wait_till_ready(flash);

			write_enable(flash);

			spi_sync(flash->spi, &m);

			if (retlen)
				*retlen += m.actual_length
					- sizeof(flash->command);
		}
	}

	mutex_unlock(&flash->lock);

	return 0;
}


/****************************************************************************/

/*
 * SPI device driver setup and teardown
 */

struct flash_info {
	char		*name;

	/* JEDEC id zero means "no ID" (most older chips); otherwise it has
	 * a high byte of zero plus three data bytes: the manufacturer id,
	 * then a two byte device id.
	 */
	u32		jedec_id;

	/* The size listed here is what works with OPCODE_SE, which isn't
	 * necessarily called a "sector" by the vendor.
	 */
	unsigned	sector_size;
	u16		n_sectors;

	u16		flags;
#define	SECT_4K		0x01		/* OPCODE_BE_4K works uniformly */
};


/* NOTE: double check command sets and memory organization when you add
 * more flash chips.  This current list focusses on newer chips, which
 * have been converging on command sets which including JEDEC ID.
 */
static struct flash_info __devinitdata m25p_data [] = {

	/* Atmel -- some are (confusingly) marketed as "DataFlash" */
	{ "at25fs010",  0x1f6601, 32 * 1024, 4, SECT_4K, },
	{ "at25fs040",  0x1f6604, 64 * 1024, 8, SECT_4K, },

	{ "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },

	{ "at26f004",   0x1f0400, 64 * 1024, 8, SECT_4K, },
	{ "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
	{ "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
	{ "at26df321",  0x1f4701, 64 * 1024, 64, SECT_4K, },

	/* Spansion -- single (large) sector size only, at least
	 * for the chips listed here (without boot sectors).
	 */
	{ "s25sl004a", 0x010212, 64 * 1024, 8, },
	{ "s25sl008a", 0x010213, 64 * 1024, 16, },
	{ "s25sl016a", 0x010214, 64 * 1024, 32, },
	{ "s25sl032a", 0x010215, 64 * 1024, 64, },
	{ "s25sl064a", 0x010216, 64 * 1024, 128, },
#ifdef CONFIG_MIPS_BRCM97XXX
	{ "s25fl128p", 0x012018, 64 * 1024, 256, },
#endif

	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
	{ "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
	{ "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
	{ "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
	{ "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },

	/* ST Microelectronics -- newer production may have feature updates */
	{ "m25p05",  0x202010,  32 * 1024, 2, },
	{ "m25p10",  0x202011,  32 * 1024, 4, },
	{ "m25p20",  0x202012,  64 * 1024, 4, },
	{ "m25p40",  0x202013,  64 * 1024, 8, },
#ifndef CONFIG_MIPS_BRCM97XXX
	/* ID 0 is detected when there's nothing on the bus */
	{ "m25p80",         0,  64 * 1024, 16, },
#endif
	{ "m25p16",  0x202015,  64 * 1024, 32, },
	{ "m25p32",  0x202016,  64 * 1024, 64, },
	{ "m25p64",  0x202017,  64 * 1024, 128, },
	{ "m25p128", 0x202018, 256 * 1024, 64, },

	{ "m45pe80", 0x204014,  64 * 1024, 16, },
	{ "m45pe16", 0x204015,  64 * 1024, 32, },

	{ "m25pe80", 0x208014,  64 * 1024, 16, },
	{ "m25pe16", 0x208015,  64 * 1024, 32, SECT_4K, },

	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
	{ "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
	{ "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
	{ "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
	{ "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
	{ "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
	{ "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
	{ "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
};

static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
{
	int			tmp;
	u8			code = OPCODE_RDID;
	u8			id[3];
	u32			jedec;
	struct flash_info	*info;

	/* JEDEC also defines an optional "extended device information"
	 * string for after vendor-specific data, after the three bytes
	 * we use here.  Supporting some chips might require using it.
	 */
	tmp = spi_write_then_read(spi, &code, 1, id, 3);
	if (tmp < 0) {
		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
			spi->dev.bus_id, tmp);
		return NULL;
	}
	jedec = id[0];
	jedec = jedec << 8;
	jedec |= id[1];
	jedec = jedec << 8;
	jedec |= id[2];

	for (tmp = 0, info = m25p_data;
			tmp < ARRAY_SIZE(m25p_data);
			tmp++, info++) {
		if (info->jedec_id == jedec)
			return info;
	}
	dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
	return NULL;
}
Пример #25
0
int _i2c_firmware_update_dp703(struct scaler_private_data *scaler)
{
	int i=0,j=0,k=0,m=0;
	int fail = 0;
	int result = 0;
	int err_count = 0;
	
	//Step 1: Stop MPU and Reset SPI
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xbc, 0xc0);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xbc, 0x40); //stop MPU
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x03); //set WP pin high
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x04); // Write-Disable
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x00);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x05);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x02); // set WP pin low
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//Step 2: Chip Erase
	//enable write status register
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x03);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x50); // Enable-Write-Status-Register
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x00);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x05);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x02);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//disable all protection
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x03);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x01); //Write-Status-Register
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x00); //Status Register
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x01);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x05);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x02);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//wait for SPI module ready
	result = wait_till_ready(scaler, PAGE2_ADDRESS, 0x9e, 0x0c);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
		
	for(i=0; i<3; i++)
	{
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x05); // 0x05 RDSR; command of flash
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x00); // command length
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x01); // trigger read
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		
		result = wait_till_ready(scaler, PAGE2_ADDRESS, 0x93, 0x01);// wait for SPI command done
		if(!result)
		break;
	}

	if(i >= 3)
	return result;
	
	//enable DP701 mapping function
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x03);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xda, 0xaa);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xda, 0x55);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
		
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xda, 0x50);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xda, 0x41);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xda, 0x52);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xda, 0x44);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//write enable
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x03);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x06); // Write-Enable command
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x00);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x05);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x02);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//chip erase
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x03);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x60); //chip erase command
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x00);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x05);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//wait for SPI interface ready
	result = wait_till_ready(scaler, PAGE2_ADDRESS,0x9e, 0x0c);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//wait for SPI ROM until not busy
	for(i=0; i<3; i++)
	{
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x05); // 0x05 RDSR; Read-Status-Register
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x00); // command length
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x01); // trigger read
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		result = wait_till_ready(scaler, PAGE2_ADDRESS, 0x93, 0x01);// wait for SPI command done
		if(!result)
		break;
	}

	if(i >= 3)
	return result;
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x02);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//Step 3: Load F/W to SPI ROM
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x82, 0x20);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	msleep(100);
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x82, 0x00);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	for(k=0;k<16;k++) //1Mbytes SPI ROM Size (16 banks)
	{
		for(j=0; j<256; j++)
		{
			result = WriteReg(scaler, PAGE2_ADDRESS, 0x8e, j);
			if(result)
			{
				printk("%s:line=%d, error\n",__func__, __LINE__);
				return result;

			}
			
			result = WriteReg(scaler, PAGE2_ADDRESS, 0x8f, k);
			if(result)
			{
				printk("%s:line=%d, error\n",__func__, __LINE__);
				return result;

			}
			
			for( i = 0; i <256; i++ )
			{
				result = WriteReg(scaler, PAGE7_ADDRESS, i, binary_data_dp703[(k<<16) + (j<<8) + i]); //
				if(result)
				{
					printk("%s:line=%d, error\n",__func__, __LINE__);
					return result;

				}
				// maybe should add some delay here
			}
		}
	}
	
	//Step 4: Verify SPI ROM
	fail=0;
	for(k=0;k<16;k++) //1Mbytes SPI ROM Size (16 banks)
	{
		for(j=0;j<256;j++) //read SPI ROM data to ReadHex
		{
			result = WriteReg(scaler, PAGE2_ADDRESS, 0x8e, j);
			if(result)
			{
				printk("%s:line=%d, error\n",__func__, __LINE__);
				return result;

			}
			
			result = WriteReg(scaler, PAGE2_ADDRESS, 0x8f, k);
			if(result)
			{
				printk("%s:line=%d, error\n",__func__, __LINE__);
				return result;

			}
			
			result = ReadPage(scaler, PAGE7_ADDRESS, 0, 256, &binary_data_dp703_read[(k<<16) + (j<<8)]);
			if(result)
			{
				printk("%s:line=%d, error\n",__func__, __LINE__);
				return result;

			}
		}

		err_count = 0;
		for(m=0; m<65536; m++)
		{ 
			if(binary_data_dp703_read[m + (k<<16)] != binary_data_dp703[m + (k<<16)])
			{
				err_count ++;	
				printk("%d:0x%x,0x%x ", m + (k<<16), binary_data_dp703[m + (k<<16)], binary_data_dp703_read[m + (k<<16)]);
				if((m%6) == 0)
				printk("\n");	
			}
		}

		if(err_count > 0)
		{
			printk("%s:err_count=%d\n",__func__, err_count);
			return -1;
		}
		
	}
	
	//Step 5: Enable Write Protection
	//write enable
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x03);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x50); // Enable-Write-Status-Register
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x00);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x05);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x02);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//enable write register protection
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x03);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x01); //write status register value
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x8C); //protect BPL/BP0/BP1
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x01);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x05);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xb0, 0x02);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
	
	//wait for SPI module ready
	result = wait_till_ready(scaler, PAGE2_ADDRESS, 0x9e, 0x0c);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}
		
	for(i=0; i<3; i++)
	{
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x90, 0x05); // 0x05 RDSR; command of flash
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x92, 0x00); // command length
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		
		result = WriteReg(scaler, PAGE2_ADDRESS, 0x93, 0x01); // trigger read
		if(result)
		{
			printk("%s:line=%d, error\n",__func__, __LINE__);
			return result;

		}
		result = wait_till_ready(scaler, PAGE2_ADDRESS, 0x93, 0x01);// wait for SPI command done
		if(!result)
		break;
	}	//disable DP701 mapping function
	
	if(i >= 3)
	return result;
	
	result = WriteReg(scaler, PAGE2_ADDRESS, 0xda, 0x00);
	if(result)
	{
		printk("%s:line=%d, error\n",__func__, __LINE__);
		return result;

	}

	return result;
}