int spi_flash_write_aml(struct spi_flash *flash,u32 offset, size_t len, const void *buf){ struct spi_slave *spi = flash->spi; int ret; unsigned temp_addr; int temp_length; temp_addr = offset; temp_length = len; unsigned flags; while(temp_length>0){ flags=(temp_addr & 0xffffff)|( (temp_length>=32?32:temp_length) << SPI_FLASH_BYTES_LEN); spi_flash_adr_write(spi, flags); flags=SPI_XFER_WRITECACHE; spi_xfer(spi,(temp_length>=32?32:temp_length)*8,buf,NULL,flags); flags=(1<<SPI_FLASH_WREN); spi_flash_cmd(spi,flags,NULL,0); flags=(1<<SPI_FLASH_PP); spi_flash_cmd(spi,flags,NULL,0); ret=1; while ( (ret&1) == 1 ){ flags=1<<SPI_FLASH_RDSR; spi_flash_cmd(spi,flags,&ret,2); //2 byte status } temp_addr += (temp_length>=32?32:temp_length); buf += (temp_length>=32?32:temp_length); temp_length -= (temp_length>=32?32:temp_length); } #ifdef SPI_WRITE_PROTECT spi_enable_write_protect(); #endif return 0; }
int spi_flash_cmd_write_status_config(u8 *srcr) { u8 cmd; int ret; size_t cmd_len = 1; size_t data_len = 2; ret = spi_flash_cmd(CMD_WRITE_ENABLE, NULL, 0); if (ret < 0) { print("SF: enabling write failed\n"); return ret; } cmd = CMD_WRITE_STATUS; ret = spi_flash_read_write(&cmd, cmd_len, srcr, NULL, data_len); if (ret) { print("SF: fail to write status and config register\n"); return ret; } ret = spi_flash_cmd_poll_bit(SPI_FLASH_PROG_TIMEOUT, CMD_READ_STATUS, STATUS_WIP); if (ret < 0) { print("SF: write status register timed out\n"); return ret; } return 0; }
int spi_flash_read_aml(struct spi_flash *flash,u32 offset, size_t len, void *buf){ struct spi_slave *spi = flash->spi; //int ret; u32 temp_addr; int temp_length; temp_addr = offset; temp_length = len; unsigned flags; /* 0x400000 ~ 0x7fffff */ if(temp_addr + len > 0x400000 && temp_addr < 0x400000){ flags=SPI_XFER_END|SPI_XFER_COPY; spi_xfer(spi,(0x400000-temp_addr)*8,&temp_addr,buf,flags); buf += (0x400000-temp_addr); temp_length = len - (0x400000-temp_addr); temp_addr = 0x400000; } /* 0x000000 ~ 0x3fffff */ else if(temp_addr < 0x400000){ flags=SPI_XFER_END|SPI_XFER_COPY; spi_xfer(spi,temp_length*8,&temp_addr,buf,flags); return 0; } spi_claim_bus(spi); /*FIXME for spi_xfer release bus*/ while(temp_length>0){ flags=(temp_addr & 0xffffff)|( (temp_length>=32?32:temp_length) << SPI_FLASH_BYTES_LEN); spi_flash_adr_write(spi, flags); flags=(1<<SPI_FLASH_READ); spi_flash_cmd(spi,flags,NULL,0); flags=SPI_XFER_READCACHE; spi_xfer(spi,(temp_length>=32?32:temp_length)*8,NULL,buf,flags); temp_addr += (temp_length>=32?32:temp_length); buf += (temp_length>=32?32:temp_length); temp_length -= (temp_length>=32?32:temp_length); } return 0; }
struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) { const struct stmicro_spi_flash_params *params; struct spi_flash *flash; unsigned int i; if (idcode[0] == 0xff) { i = spi_flash_cmd(spi, CMD_M25PXX_RES, idcode, 4); if (i) return NULL; if ((idcode[3] & 0xf0) == 0x10) { idcode[0] = 0x20; idcode[1] = 0x20; idcode[2] = idcode[3] + 1; } else return NULL; } for (i = 0; i < ARRAY_SIZE(stmicro_spi_flash_table); i++) { params = &stmicro_spi_flash_table[i]; if (params->idcode1 == idcode[2]) { break; } } if (i == ARRAY_SIZE(stmicro_spi_flash_table)) { debug("SF: Unsupported STMicro ID %02x\n", idcode[1]); return NULL; } flash = malloc(sizeof(*flash)); if (!flash) { debug("SF: Failed to allocate memory\n"); return NULL; } flash->spi = spi; flash->name = params->name; flash->write = spi_flash_cmd_write_multi; flash->erase = stmicro_erase; flash->read = spi_flash_cmd_read_fast; flash->page_size = params->page_size; flash->sector_size = params->page_size * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; flash->addr_cycles=params->addr_cycles; /* In first prove remove HW protection */ if(params->protected) stmicro_protect(flash, 0); return flash; }
void spi_init(void) { u8 idcode[5]; int ret; u8 cr, sr, srcr[2]; /* QSPI initialize */ writeb(0x08, ®s->spcr); writeb(0x00, ®s->sslp); writeb(0x06, ®s->sppcr); writeb(0x02, ®s->spbr); writeb(0x00, ®s->spdcr); writeb(0x00, ®s->spckd); writeb(0x00, ®s->sslnd); writeb(0x00, ®s->spnd); writew(0xe084, ®s->spcmd0); writew(0x8084, ®s->spcmd0); writeb(0xc0, ®s->spbfcr); writeb(0x30, ®s->spbfcr); writeb(0x00, ®s->spscr); writeb(0x48, ®s->spcr); /* Read the ID codes */ ret = spi_flash_cmd(CMD_READ_ID, idcode, sizeof(idcode)); if (ret) print("spi read id failed\n"); /* enable quad transfer */ spi_flash_cmd(CMD_READ_STATUS, &sr, 1); spi_flash_cmd(CMD_READ_CONFIG, &cr, 1); cr |= 0x02; srcr[0] = sr; srcr[1] = cr; if (spi_flash_cmd_write_status_config(srcr) < 0) print("spi_flash_cmd_write_status_config failed\n"); }
static int stmicro_protect(struct spi_flash *flash, int enable) { int ret; u8 cmd[2]; ret = spi_claim_bus(flash->spi); if (ret) { debug("SF: Unable to claim SPI bus\n"); return ret; } ret = 0; cmd[0] = CMD_M25PXX_WRSR; if (enable == 1) cmd[1] = STM_SRWD | STM_PROTECT_ALL; else cmd[1] = STM_SRWD; ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0); if (ret < 0) { debug("SF: Enabling Write failed\n"); return ret; } ret = spi_flash_cmd_write(flash->spi, cmd, 2, NULL, 0); if (ret < 0) { debug("SF: STMicro Write Status Register failed\n"); return ret; } ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); if (ret < 0) { debug("SF: STMicro page programming timed out\n"); return ret; } spi_release_bus(flash->spi); return ret; }
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) { struct spi_slave *spi; struct spi_flash *flash; int ret; u8 idcode[5]; spi = spi_setup_slave(bus, cs, max_hz, spi_mode); if (!spi) { debug("SF: Failed to set up slave\n"); return NULL; } ret = spi_claim_bus(spi); if (ret) { debug("SF: Failed to claim SPI bus: %d\n", ret); goto err_claim_bus; } /* Read the ID codes */ ret = spi_flash_cmd(spi, CMD_READ_ID, &idcode, sizeof(idcode)); if (ret) goto err_read_id; debug("SF: Got idcode %02x %02x %02x %02x %02x\n", idcode[0], idcode[1], idcode[2], idcode[3], idcode[4]); switch (idcode[0]) { #ifdef CONFIG_SPI_FLASH_SPANSION case 0x01: flash = spi_flash_probe_spansion(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_ATMEL case 0x1F: flash = spi_flash_probe_atmel(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_ESMT case 0x8c: flash = spi_flash_probe_esmt(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_MACRONIX case 0xc2: flash = spi_flash_probe_macronix(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_WINBOND case 0xef: flash = spi_flash_probe_winbond(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_GIGABYTE case 0xc8: flash = spi_flash_probe_gigabyte(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_STMICRO case 0x20: flash = spi_flash_probe_stmicro(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_SST case 0xBF: flash = spi_flash_probe_sst(spi, idcode); break; #endif default: debug("SF: Unsupported manufacturer %02X\n", idcode[0]); flash = NULL; break; } if (!flash) goto err_manufacturer_probe; spi_release_bus(spi); return flash; err_manufacturer_probe: err_read_id: spi_release_bus(spi); err_claim_bus: spi_free_slave(spi); return NULL; }
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) { struct spi_slave *spi; struct spi_flash *flash = NULL; int ret, i, shift; u8 idcode[IDCODE_LEN], *idp; spi = spi_setup_slave(bus, cs, max_hz, spi_mode); if (!spi) { printf("SF: Failed to set up slave\n"); return NULL; } ret = spi_claim_bus(spi); if (ret) { debug("SF: Failed to claim SPI bus: %d\n", ret); goto err_claim_bus; } /* Read the ID codes */ ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); if (ret) goto err_read_id; #ifdef DEBUG printf("SF: Got idcodes\n"); print_buffer(0, idcode, 1, sizeof(idcode), 0); #endif /* count the number of continuation bytes */ for (shift = 0, idp = idcode; shift < IDCODE_CONT_LEN && *idp == 0x7f; ++shift, ++idp) continue; /* search the table for matches in shift and id */ for (i = 0; i < ARRAY_SIZE(flashes); ++i) if (flashes[i].shift == shift && flashes[i].idcode == *idp) { /* we have a match, call probe */ flash = flashes[i].probe(spi, idp); if (flash) break; } if (!flash) { printf("SF: Unsupported manufacturer %02x\n", *idp); goto err_manufacturer_probe; } spi_release_bus(spi); return flash; err_manufacturer_probe: err_read_id: spi_release_bus(spi); err_claim_bus: spi_free_slave(spi); return NULL; }
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) { struct spi_slave *spi; struct spi_flash *flash; int ret; u8 idcode[3]; spi = spi_setup_slave(bus, cs, max_hz, spi_mode); if (!spi) { debug("SF: Failed to set up slave\n"); return NULL; } ret = spi_claim_bus(spi); if (ret) { debug("SF: Failed to claim SPI bus: %d\n", ret); goto err_claim_bus; } /* Read the ID codes */ ret=spi_flash_cmd(spi,1<<SPI_FLASH_RDID,&idcode, sizeof(idcode)); if (ret) goto err_read_id; debug("SF: Got idcode %02x %02x %02x\n", idcode[0], idcode[1], idcode[2]); switch (idcode[0]) { #ifdef CONFIG_SPI_FLASH_ESMT case 0x8c: flash = spi_flash_probe_esmt(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_MACRONIX case 0xc2: flash=spi_flash_probe_mxic(spi,idcode); break; #endif #ifdef CONFIG_SPI_FLASH_SST case 0xbf: flash=spi_flash_probe_sst(spi,idcode); break; #endif #ifdef CONFIG_SPI_FLASH_SPANSION case 0x01: flash = spi_flash_probe_spansion(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_ATMEL case 0x1F: flash = spi_flash_probe_atmel(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_WINBOND case 0xef: flash = spi_flash_probe_winbond(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_STMICRO case 0x20: flash = spi_flash_probe_stmicro(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_EON: case 0x1c: flash = spi_flash_probe_eon(spi, idcode); break; #endif default: debug("SF: Unsupported manufacturer %02X\n", idcode[0]); flash = NULL; break; } if (!flash) goto err_manufacturer_probe; #ifdef SPI_WRITE_PROTECT if(spi_check_write_protect()) printf("\nSPI NOR Flash have write protect!!!\n"); else{ printf("\nSPI NOR Flash NO write protect!!!, So I will enable it...\n"); spi_enable_write_protect(); } #endif spi_release_bus(spi); return flash; err_manufacturer_probe: err_read_id: spi_release_bus(spi); err_claim_bus: spi_free_slave(spi); return NULL; }
/** * spi_enable_quad_bit - Enable the QUAD bit for SPI flash * * This function will enable the quad bit in flash using * the QSPI controller. Supports only spansion. * * @spi : SPI slave structure */ void spi_enable_quad_bit(struct spi_slave *spi) { int ret; u8 idcode[5]; u8 rdid_cmd = 0x9f; /* RDID */ u8 rcr_data = 0; u8 rcr_cmd = 0x35; /* RCR */ u8 rdsr_cmd = 0x05; /* RDSR */ u8 wren_cmd = 0x06; /* WREN */ ret = spi_flash_cmd(spi, rdid_cmd, &idcode, sizeof(idcode)); if (ret) { debug("SF error: Failed read RDID\n"); return; } if ((idcode[0] == 0x01) || (idcode[0] == 0xef)) { /* Read config register */ ret = spi_flash_cmd_read(spi, &rcr_cmd, sizeof(rcr_cmd), &rcr_data, sizeof(rcr_data)); if (ret) { debug("SF error: Failed read RCR\n"); return; } if (rcr_data & 0x2) debug("QUAD bit is already set..\n"); else { debug("QUAD bit needs to be set ..\n"); /* Write enable */ ret = spi_flash_cmd(spi, wren_cmd, NULL, 0); if (ret) { debug("SF error: Failed write WREN\n"); return; } /* Write QUAD bit */ xqspips_write_quad_bit((void *)XPSS_QSPI_BASEADDR); /* Read RDSR */ do { ret = spi_flash_cmd_read(spi, &rdsr_cmd, sizeof(rdsr_cmd), &rcr_data, sizeof(rcr_data)); } while ((ret == 0) && (rcr_data != 0)); /* Read config register */ ret = spi_flash_cmd_read(spi, &rcr_cmd, sizeof(rcr_cmd), &rcr_data, sizeof(rcr_data)); if (!(rcr_data & 0x2)) { printf("SF error: Fail to set QUAD enable bit" " 0x%x\n", rcr_data); return; } else debug("SF: QUAD enable bit is set 0x%x\n", rcr_data); } } else debug("SF: QUAD bit not enabled for 0x%x SPI flash\n", idcode[0]); return; }