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; }
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; }
/** * 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; }
/* * 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; }
/* * 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; }
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); }
/* * 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"); }
/* * 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); }
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; }
/* * 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; }
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; }
/* 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; }
/* * 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; }
// 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); }
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; }
/** * 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; }
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; }
/* * 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; }
/* 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; }
/* * 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; }
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); } }
/** * 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; }
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); }
/* * 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; }
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; }