int jz_sfc_set_address_mode(struct spi_flash *flash, int on) { unsigned char cmd[3]; unsigned int buf = 0; int err = 0; if(flash->addr_size == 4){ cmd[0] = CMD_WREN; if(on == 1){ cmd[1] = CMD_EN4B; }else{ cmd[1] = CMD_EX4B; } cmd[2] = CMD_RDSR; sfc_send_cmd(&cmd[0],0,0,0,0,0,1); sfc_send_cmd(&cmd[1],0,0,0,0,0,1); sfc_send_cmd(&cmd[2], 1,0,0,0,1,0); sfc_read_data(&buf, 1); while(buf & CMD_SR_WIP) { sfc_send_cmd(&cmd[2], 1,0,0,0,1,0); sfc_read_data(&buf, 1); } } return 0; }
static void jz_sfcnand_ext_init(void ) { unsigned char cmd[COMMAND_MAX_LENGTH]; unsigned int x=0; /* disable write protect */ unsigned int add; cmd[0]=0x1f;//get feature add=0xa0; sfc_send_cmd(&cmd[0],1,add,1,0,1,1); sfc_nand_write_data(&x,1); cmd[0]=0x1f;//get feature add=0xb0; x=0x10; sfc_send_cmd(&cmd[0],1,add,1,0,1,1); sfc_nand_write_data(&x,1); x=0; cmd[0]=CMD_GET_FEATURE;//get feature add=0xa0; sfc_send_cmd(&cmd[0],1,add,1,0,1,0); sfc_nand_read_data(&x,1); x=x&0x000000ff; printf("read status 0xa0 : %x\n", x); x=0; cmd[0]=CMD_GET_FEATURE;//get feature add=0xb0; sfc_send_cmd(&cmd[0],1,add,1,0,1,0); sfc_nand_read_data(&x,1); x=x&0x000000ff; printf("read status 0xb0 : %x\n", x); }
static int sfcnand_read_oob(struct mtd_info *mtd,loff_t addr,struct mtd_oob_ops *ops) { int len = ops->ooblen; int column = mtd->writesize; unsigned char cmd[COMMAND_MAX_LENGTH]; volatile unsigned int read_buf; int page_size = mtd->writesize; int page = addr / page_size; u_char *buffer = ops->oobbuf; /* the paraterms is * cmd , len, addr,addr_len * dummy_byte, daten * dir 0,read 1.write * * */ cmd[0] = CMD_PARD;//write en sfc_send_cmd(&cmd[0],0,page,3,0,0,0); udelay(t_read); cmd[0]=CMD_GET_FEATURE;//get feature sfc_send_cmd(&cmd[0],1,FEATURE_ADDR,1,0,1,0); sfc_nand_read_data(&read_buf,1); while(read_buf & 0x1) { cmd[0]=CMD_GET_FEATURE;//get feature sfc_send_cmd(&cmd[0],1,FEATURE_ADDR,1,0,1,0); sfc_nand_read_data(&read_buf,1); } if((read_buf & 0x30) == 0x20) { printf("%s %d read error pageid = %d!!!\n",__func__,__LINE__,page); return 1; } switch(column_cmdaddr_bits){ case 24: cmd[0]=CMD_R_CACHE;//get feature column=(column<<8)&0xffffff00; sfc_send_cmd(&cmd[0],len,column,3,0,1,0); sfc_nand_read_data(buffer,len); break; case 32: cmd[0]=CMD_FR_CACHE;//get feature column=(column<<8)&0xffffff00; sfc_send_cmd(&cmd[0],len,column,4,0,1,0); sfc_nand_read_data(buffer,len); break; default: printk("can't support the column addr format !!!\n"); break; } return 0; }
int sfc_nand_erase(struct mtd_info *mtd,int addr) { unsigned char cmd[COMMAND_MAX_LENGTH]; int erase_cmd; int page = addr / mtd->writesize; int block_size = mtd->erasesize; switch(block_size){ case 4 * 1024: erase_cmd = CMD_ERASE_4K; break; case 32 * 1024: erase_cmd = CMD_ERASE_32K; break; case 64 * 1024: erase_cmd = CMD_ERASE_64K; break; case 128 * 1024: erase_cmd = CMD_ERASE_128K; break; default: printf("WARNING: don't support the erase size !\n"); break; } /* the paraterms is * cmd , len, addr,addr_len * dummy_byte, daten * dir 0,read 1.write * * */ volatile unsigned int x; cmd[0] = CMD_WREN;//write en sfc_send_cmd(&cmd[0],0,0,0,0,0,0); memset(cmd,COMMAND_MAX_LENGTH,0); cmd[0]=erase_cmd;//erase sfc_send_cmd(&cmd[0],0,page,3,0,0,0); memset(cmd,COMMAND_MAX_LENGTH,0); cmd[0]=CMD_GET_FEATURE;//get feature sfc_send_cmd(&cmd[0],1,0xc0,1,0,1,0); sfc_nand_read_data(&x,1); x=x&0x000000ff; while(x & 0x1) { x=0; sfc_send_cmd(&cmd[0],1,0xc0,1,0,1,0); sfc_nand_read_data(&x,1); } if(x & E_FAIL) return -1; return 0; }
int jz_sfc_chip_erase() { /* the paraterms is * cmd , len, addr,addr_len * dummy_byte, daten * dir * * */ unsigned char cmd[6]; cmd[0] = CMD_WREN; cmd[1] = CMD_ERASE_CE; cmd[5] = CMD_RDSR; unsigned int buf = 0; int err = 0; if(sfc_is_init == 0){ err = sfc_init(); if(err < 0){ printf("the quad mode is not support\n"); return -1; } } if(sfc_quad_mode == 1){ if(quad_mode_is_set == 0){ sfc_set_quad_mode(); } } jz_sfc_writel(1 << 2,SFC_TRIG); sfc_send_cmd(&cmd[0],0,0,0,0,0,1); sfc_send_cmd(&cmd[1],0,0,0,0,0,1); sfc_send_cmd(&cmd[5], 1,0,0,0,1,0); sfc_read_data(&buf, 1); printf("sfc start chip erase\n"); while(buf & CMD_SR_WIP) { sfc_send_cmd(&cmd[5], 1,0,0,0,1,0); sfc_read_data(&buf, 1); } printf("########## chip erase ok ######### \n"); return 0; }
int jz_sfc_read(struct spi_flash *flash, u32 offset, size_t len, void *data) { unsigned char cmd[5]; unsigned long read_len; unsigned int words_of_len = 0; unsigned int i; jz_sfc_set_address_mode(flash,1); if(sfc_quad_mode == 1){ cmd[0] = quad_mode->cmd_read; mode = quad_mode->sfc_mode; }else{ cmd[0] = CMD_READ; mode = TRAN_SPI_STANDARD; } for(i = 0; i < flash->addr_size; i++){ cmd[i + 1] = offset >> (flash->addr_size - i - 1) * 8; } read_len = flash->size - offset; if(len < read_len) read_len = len; /* the paraterms is * cmd , len, addr,addr_len * dummy_byte, daten * dir * * */ if(sfc_quad_mode == 1){ sfc_send_cmd(&cmd[0],read_len,offset,flash->addr_size,quad_mode->dummy_byte,1,0); }else{ sfc_send_cmd(&cmd[0],read_len,offset,flash->addr_size,0,1,0); } // dump_sfc_reg(); sfc_read_data(data, len); jz_sfc_set_address_mode(flash,0); return 0; }
int sfc_nand_read_page(u_char *buffer,int page,int column,size_t rlen) { unsigned char cmd[COMMAND_MAX_LENGTH]; volatile unsigned int read_buf; cmd[0]=CMD_PARD;// sfc_send_cmd(&cmd[0],0,page,3,0,0,0); cmd[0]=CMD_GET_FEATURE;//get feature sfc_send_cmd(&cmd[0],1,FEATURE_ADDR,1,0,1,0); sfc_nand_read_data(&read_buf,1); // printf("read_buf=%08x\n",read_buf); while(read_buf & 0x1) { cmd[0]=CMD_GET_FEATURE;//get feature sfc_send_cmd(&cmd[0],1,FEATURE_ADDR,1,0,1,0); sfc_nand_read_data(&read_buf,1); } if((read_buf & 0x30) == 0x20) { printf("%s %d read error pageid = %d!!!\n",__func__,__LINE__,page); return -1; } switch(column_cmdaddr_bits){ case 24: cmd[0]=CMD_R_CACHE;//get feature column=(column<<8)&0xffffff00; sfc_send_cmd(&cmd[0],rlen,column,3,0,1,0); sfc_nand_read_data(buffer,rlen); break; case 32: cmd[0]=CMD_FR_CACHE;//get feature column=(column<<8)&0xffffff00; sfc_send_cmd(&cmd[0],rlen,column,4,0,1,0); sfc_nand_read_data(buffer,rlen); break; default: printk("can't support the column addr format !!!\n"); break; } return 0; }
void sfc_nor_RDID(unsigned int *idcode) { /* the paraterms is * cmd , len, addr,addr_len * dummy_byte, daten * dir * * */ unsigned char cmd[1]; // unsigned char chip_id[4]; unsigned int chip_id = 0; cmd[0] = CMD_RDID; sfc_send_cmd(&cmd[0],3,0,0,0,1,0); sfc_read_data(&chip_id, 1); // *idcode = chip_id[0]; *idcode = chip_id & 0x00ffffff; }
static int sfcnand_write_oob(struct mtd_info *mtd,loff_t addr,struct mtd_oob_ops *ops) { unsigned char cmd[COMMAND_MAX_LENGTH]; int page = addr / mtd->writesize; int ret; cmd[0]=CMD_PARD;//get feature sfc_send_cmd(&cmd[0],0,page,3,0,0,0); udelay(t_read); ret = sfc_nand_write(mtd,addr,mtd->writesize,ops->ooblen,ops->oobbuf); if(ret){ printf("WARNING: Mark bad block fail !\n"); return -1; } return 0; }
void sfc_set_quad_mode() { /* the paraterms is * cmd , len, addr,addr_len * dummy_byte, daten * dir * * */ unsigned char cmd[5]; unsigned int buf = 0; unsigned int tmp = 0; int i = 10; if(quad_mode != NULL){ cmd[0] = CMD_WREN; cmd[1] = quad_mode->WRSR_CMD; cmd[2] = quad_mode->RDSR_CMD; cmd[3] = CMD_RDSR; sfc_send_cmd(&cmd[0],0,0,0,0,0,1); sfc_send_cmd(&cmd[1],quad_mode->WD_DATE_SIZE,0,0,0,1,1); sfc_write_data(&quad_mode->WRSR_DATE,1); sfc_send_cmd(&cmd[3],1,0,0,0,1,0); sfc_read_data(&tmp, 1); while(tmp & CMD_SR_WIP) { sfc_send_cmd(&cmd[3],1,0,0,0,1,0); sfc_read_data(&tmp, 1); } sfc_send_cmd(&cmd[2], quad_mode->RD_DATE_SIZE,0,0,0,1,0); sfc_read_data(&buf, 1); while(!(buf & quad_mode->RDSR_DATE)&&((i--) > 0)) { sfc_send_cmd(&cmd[2], quad_mode->RD_DATE_SIZE,0,0,0,1,0); sfc_read_data(&buf, 1); } quad_mode_is_set = 1; printf("set quad mode is enable.the buf = %x\n",buf); }else{ printf("the quad_mode is NULL,the nor flash id we not support\n"); } }
static int jz_sfc_read_norflash_params(struct spi_flash *flash, u32 offset, size_t len, void *data) { unsigned char cmd[5]; unsigned long read_len; unsigned int i; cmd[0] = CMD_READ; mode = TRAN_SPI_STANDARD; for(i = 0; i < flash->addr_size; i++){ cmd[i + 1] = offset >> (flash->addr_size - i - 1) * 8; } read_len = flash->size - offset; if(len < read_len) read_len = len; sfc_send_cmd(&cmd[0],read_len,offset,flash->addr_size,0,1,0); sfc_read_data(data, len); return 0; }
static int sfc_nand_write(struct mtd_info *mtd,loff_t addr,int column,size_t len,u_char *buf) { unsigned char state, cmd[COMMAND_MAX_LENGTH]; int page_size = mtd->writesize; int page;// = addr / page_size; int wlen,i,write_num; int ops_len; u_char *buffer = buf; page = addr/page_size; write_num = (len + page_size - 1) / page_size; for(i = 0; i < write_num; i++) { if(len >= page_size) wlen = page_size; else wlen = len; /* the paraterms is * cmd , datelen, *addr,addr_len * dummy_byte, daten * dir 0,read 1.write * * */ cmd[0]=CMD_PRO_LOAD;//get feature sfc_send_cmd(&cmd[0],wlen,column,2,0,1,1); ops_len = wlen; /* while(ops_len) { if(ops_len > FIFI_THRESHOLD) { sfc_nand_write_data(buffer,FIFI_THRESHOLD); buffer += FIFI_THRESHOLD; ops_len -= FIFI_THRESHOLD; } else { sfc_nand_write_data(buffer,ops_len); buffer += ops_len; ops_len = 0; } }*/ sfc_nand_write_data(buffer,ops_len); buffer += ops_len; cmd[0] = CMD_WREN; sfc_send_cmd(&cmd[0],0,0,0,0,0,0); cmd[0] = CMD_PE; sfc_send_cmd(&cmd[0],0,page,3,0,0,0); udelay(t_write); state=0; cmd[0] = CMD_GET_FEATURE; sfc_send_cmd(&cmd[0],1,FEATURE_ADDR,1,0,1,0); sfc_nand_read_data(&state,1); while(state & 0x1) /////////////////////////////////////////// { cmd[0] = CMD_GET_FEATURE; sfc_send_cmd(&cmd[0],1,FEATURE_ADDR,1,0,1,0); sfc_nand_read_data(&state,1); } if(state & P_FAIL){ printf("WARNING: write fail !\n"); return (len - i * wlen); } len -= wlen; page++; } return 0; }
int jz_sfc_erase(struct spi_flash *flash, u32 offset, size_t len) { unsigned long erase_size; unsigned char cmd[7]; unsigned int buf = 0, i; jz_sfc_set_address_mode(flash,1); if((len >= 0x10000)&&((offset % 0x10000) == 0)){ erase_size = 0x10000; }else if((len >= 0x8000)&&((offset % 0x8000) == 0)){ erase_size = 0x8000; }else{ erase_size = 0x1000; } if(len % erase_size != 0){ len = len - (len % erase_size) + erase_size; } // // if (len % erase_size) { // printf("Erase offset/length not multiple of erase size\n"); // return -1; // } cmd[0] = CMD_WREN; switch(erase_size) { case 0x1000 : cmd[1] = CMD_ERASE_4K; break; case 0x8000 : cmd[1] = CMD_ERASE_32K; break; case 0x10000 : cmd[1] = CMD_ERASE_64K; break; default: printf("unknown erase size !\n"); return -1; } cmd[flash->addr_size + 2] = CMD_RDSR; while(len > 0) { for(i = 0; i < flash->addr_size; i++){ cmd[i+2] = offset >> (flash->addr_size - i - 1) * 8; } // printf("erase %x %x %x %x %x %x %x \n", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], offset); /* the paraterms is * cmd , len, addr,addr_len * dummy_byte, daten * dir * * */ sfc_send_cmd(&cmd[0],0,0,0,0,0,1); sfc_send_cmd(&cmd[1],0,offset,flash->addr_size,0,0,1); sfc_send_cmd(&cmd[flash->addr_size + 2], 1,0,0,0,1,0); sfc_read_data(&buf, 1); while(buf & CMD_SR_WIP) { sfc_send_cmd(&cmd[flash->addr_size + 2], 1,0,0,0,1,0); sfc_read_data(&buf, 1); } offset += erase_size; len -= erase_size; } jz_sfc_set_address_mode(flash,0); return 0; }
int jz_sfc_write(struct spi_flash *flash, u32 offset, size_t length, const void *buf) { unsigned char cmd[7]; unsigned tmp = 0; int chunk_len, actual, i; unsigned long byte_addr; unsigned char *send_buf = (unsigned char *)buf; unsigned int pagelen = 0,len = 0,retlen = 0; jz_sfc_set_address_mode(flash,1); if (offset + length > flash->size) { printf("Data write overflow this chip\n"); return -1; } cmd[0] = CMD_WREN; if(sfc_quad_mode == 1){ cmd[1] = CMD_QPP; mode = TRAN_SPI_QUAD; }else{ cmd[1] = CMD_PP; mode = TRAN_SPI_STANDARD; } cmd[flash->addr_size + 2] = CMD_RDSR; while (length) { if (length >= flash->page_size) pagelen = 0; else pagelen = length % flash->page_size; /* the paraterms is * cmd , len, addr,addr_len * dummy_byte, daten * dir * * */ sfc_send_cmd(&cmd[0],0,0,0,0,0,1); if (!pagelen || pagelen > flash->page_size) len = flash->page_size; else len = pagelen; if (offset % flash->page_size + len > flash->page_size) len -= offset % flash->page_size + len - flash->page_size; for(i = 0; i < flash->addr_size; i++){ cmd[i+2] = offset >> (flash->addr_size - i - 1) * 8; } sfc_send_cmd(&cmd[1], len,offset,flash->addr_size,0,1,1); // dump_sfc_reg(); sfc_write_data(send_buf ,len); retlen = len; /*polling*/ sfc_send_cmd(&cmd[flash->addr_size + 2],1,0,0,0,1,0); sfc_read_data(&tmp, 1); while(tmp & CMD_SR_WIP) { sfc_send_cmd(&cmd[flash->addr_size + 2],1,0,0,0,1,0); sfc_read_data(&tmp, 1); } if (!retlen) { printf("spi nor write failed\n"); return -1; } offset += retlen; send_buf += retlen; length -= retlen; } jz_sfc_set_address_mode(flash,0); return 0; }