📄 pflash.c
字号:
if ((ret = cfi_chip_setup(h, pcfi)) != RM_OK) return ret; // Reset cfi_send_cmd(h, pcfi->buswidth, 0xf0, 0, pcfi->gbus_address); // internal settings: command set 0002 if (pcfi->ident.primary_id == 0x2) cfi_cmdset_0002(pcfi); return RM_OK;}static RMstatus cfi_query_present(struct gbus *h, RMuint32 base, RMuint32 bwidth){ RMuint32 c1=cfi_read(h, base + cfi_build_cmd_addr(0x10), bwidth) == cfi_build_cmd('Q',bwidth), c2=cfi_read(h, base + cfi_build_cmd_addr(0x11), bwidth) == cfi_build_cmd('R',bwidth), c3=cfi_read(h, base + cfi_build_cmd_addr(0x12), bwidth) == cfi_build_cmd('Y',bwidth); // garbled by sdio --- force true return (c1&c2&c3) ? RM_OK:RM_NOT_FOUND;}static RMstatus cfi_chip_setup(struct gbus *h, cfi_info *pcfi){ RMuint32 i; RMuint32 num_erase_regions = cfi_read(h, pcfi->gbus_address + cfi_build_cmd_addr(0x2c), pcfi->buswidth); RMuint32 start; if (num_erase_regions == 0) return RM_NOT_SUPPORTED; for (i = 0; i < (sizeof pcfi->ident) - (sizeof pcfi->ident.erase_region_info) + (num_erase_regions * 4); ++i) { ((RMuint8 *) &pcfi->ident)[i] = cfi_read(h, pcfi->gbus_address + cfi_build_cmd_addr(0x10 + i), pcfi->buswidth); } //((RMuint8 *) &pcfi->ident)[0]='Q'; //((RMuint8 *) &pcfi->ident)[1]='R'; if (pcfi->ident.primary_id != 0x2) /* Not using command set 0002 */ RMDBGLOG((LOCALDBG,"warning: not using command set 0002\n")); for (i = 0, start = 0; i < num_erase_regions; ++i) { pcfi->erase_regions[i].start = start; pcfi->erase_regions[i].size = 0x100 * ((pcfi->ident.erase_region_info[i] >> 16) & 0xffff); pcfi->erase_regions[i].blocks = (pcfi->ident.erase_region_info[i] & 0xffff) + 1; start += pcfi->erase_regions[i].size * pcfi->erase_regions[i].blocks; } pcfi->size = 1 << pcfi->ident.device_size; return RM_OK;}static void cfi_cmdset_0002(cfi_info *pcfi){ switch (CFIDEV_DEVTYPE) { case 1 : pcfi->addr_unlock1 = 0x555; pcfi->addr_unlock2 = 0x2aa; break; case 2 : pcfi->addr_unlock1 = 0xaaa; if (pcfi->buswidth == CFIDEV_BUSWIDTH_8) pcfi->addr_unlock2 = 0x555; else //(CFIDEV_BUSWIDTH_16 ) pcfi->addr_unlock2 = 0x554; break; case 4 : pcfi->addr_unlock1 = 0x1555; pcfi->addr_unlock2 = 0xaaa; break; }}//otherstatic RMint32 flash_erase_oneblock(struct gbus *h, cfi_info *pcfi, RMuint32 addr,void(*cb_usleep)(struct gbus *,RMuint32)){ cfi_send_cmd(h, pcfi->buswidth, 0xaa, pcfi->addr_unlock1, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x55, pcfi->addr_unlock2, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x80, pcfi->addr_unlock1, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0xaa, pcfi->addr_unlock1, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x55, pcfi->addr_unlock2, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x30, addr - pcfi->gbus_address, pcfi->gbus_address); if ( flash_use_DQX ) dqx_wait(h, addr, pcfi->buswidth, 0xff, 1000*(1<<pcfi->ident.timeout_block_erase), cb_usleep); else { if(pcfi->ident.timeout_block_erase > 0) (*cb_usleep)(h,1000*(1 << pcfi->ident.timeout_block_erase)); else //not support pcfi->ident.timeout_block_erase. (*cb_usleep)(h,2*1000*1000); // 2 sec } if ((cfi_read(h, addr, pcfi->buswidth) & 0xff) != 0xff) return RM_ERROR; return RM_OK;}// writing :suppose 16 bits writingstatic RMstatus flash_writable(struct gbus *h, RMuint32 addr, RMint32 len){ RMint32 i; while (addr & 0x3) { if ( gbus_read_remapped_uint8(h, addr++) != 0xff) { RMDBGLOG((DISABLE,"Unwritable: 0x%x = 0x%x\n",addr-1,gbus_read_remapped_uint8(h, addr-1))); return RM_ERROR; } --len; } for (i = 0; i < (len-3); i+=4, addr+=4) { if ( gbus_read_remapped_uint32(h, addr) != 0xffffffff) { RMDBGLOG((DISABLE,"Unwritable: 0x%x = 0x%x\n",addr,gbus_read_remapped_uint32(h, addr))); return RM_ERROR; } } while ((len & 0x3) > 0) { if ( gbus_read_remapped_uint8(h, addr++) != 0xff) { RMDBGLOG((DISABLE,"Unwritable: 0x%x = 0x%x\n",addr-1,gbus_read_remapped_uint8(h, addr-1))); return RM_ERROR; } --len; } return RM_OK;}static RMstatus flash_write_onebyte(struct gbus *h, cfi_info *pcfi, RMuint32 addr, RMuint32 data, void(*cb_usleep)(struct gbus *,RMuint32)){ RMuint32 curdata; RMuint32 olddata=0, newaddr=0, newdata=0; if(pcfi->buswidth == CFIDEV_BUSWIDTH_8) { newaddr = addr; olddata = curdata = cfi_read(h, newaddr, pcfi->buswidth); newdata = data; } else if (pcfi->buswidth == CFIDEV_BUSWIDTH_16) { newaddr = addr & ~0x01; curdata = cfi_read(h, newaddr, pcfi->buswidth); if (addr & 0x01) { olddata = (curdata & 0xff00) >> 8; newdata = (curdata & 0x00ff) | ((data & 0xff) << 8); } else { olddata = (curdata & 0x00ff); newdata = (curdata & 0xff00) | (data & 0xff); } } if (~olddata & data) return RM_ERROR; cfi_send_cmd(h, pcfi->buswidth, 0xaa, pcfi->addr_unlock1, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x55, pcfi->addr_unlock2, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0xa0, pcfi->addr_unlock1, pcfi->gbus_address); cfi_write(h, pcfi->buswidth, newdata, newaddr); if( flash_use_DQX ) dqx_wait(h, newaddr, pcfi->buswidth, newdata, 1<<pcfi->ident.timeout_single_write, cb_usleep); else (*cb_usleep)(h, 1 << pcfi->ident.timeout_single_write); if (cfi_read(h, newaddr, pcfi->buswidth) != newdata) return RM_ERROR; return RM_OK;}static RMstatus flash_write_data_internal(struct gbus *h, RMuint32 addr, RMuint16 *data, RMint32 nwords, cfi_info *pcfi, void(*cb_usleep)(struct gbus*,RMuint32)){ RMint32 i;#ifdef CFIDEV_UNLOCK_BYPASS cfi_send_cmd(h, pcfi->buswidth, 0xaa, pcfi->addr_unlock1, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x55, pcfi->addr_unlock2, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x20, pcfi->addr_unlock1, pcfi->gbus_address); if (pcfi->buswidth == CFIDEV_BUSWIDTH_8) { for (i = 0; i < (nwords << 1); ++i) { cfi_send_cmd(h, pcfi->buswidth, 0xa0, 0, pcfi->gbus_address); cfi_write(h, pcfi->buswidth, ((RMuint8 *) data)[i], addr + i); if(flash_use_DQX) dqx_wait(h, addr + i, pcfi->buswidth, ((unsigned char *)data)[i], 1<<pcfi->ident.timeout_single_write, cb_usleep); else (*cb_usleep)(h, (1<<pcfi->ident.timeout_single_write)); if (cfi_read(h, addr + i, pcfi->buswidth) != ((unsigned char *)data)[i]) return RM_ERROR; } } else if (pcfi->buswidth == CFIDEV_BUSWIDTH_16) { for (i = 0; i < nwords; ++i) { cfi_send_cmd(h, pcfi->buswidth, 0xa0, 0, pcfi->gbus_address); cfi_write(h, pcfi->buswidth, data[i], addr + (i << 1)); if(flash_use_DQX) dqx_wait(h, addr + (i<<1), pcfi->buswidth, data[i], 1<<pcfi->ident.timeout_single_write, cb_usleep); else (*cb_usleep)(h, (1<<pcfi->ident.timeout_single_write)); if (cfi_read(h, addr + (i<<1), pcfi->buswidth) != data[i]) return RM_ERROR; } } cfi_send_cmd(h, pcfi->buswidth, 0x90, 0, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x00, 0, pcfi->gbus_address);#else //CFIDEV_UNLOCK_BYPASS if (pcfi->buswidth == CFIDEV_BUSWIDTH_8) { for (i = 0; i < (nwords << 1); ++i) { cfi_send_cmd(h, pcfi->buswidth, 0xaa, pcfi->addr_unlock1, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x55, pcfi->addr_unlock2, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0xa0, pcfi->addr_unlock1, pcfi->gbus_address); cfi_write(h, pcfi->buswidth, ((RMuint8 *) data)[i], addr + i); if(flash_use_DQX) dqx_wait(h, addr + i, pcfi->buswidth, ((unsigned char *)data)[i], 1<<pcfi->ident.timeout_single_write, cb_usleep); else (*cb_usleep)(h, (1<<pcfi->ident.timeout_single_write)); if (cfi_read(h, addr + i, pcfi->buswidth) != ((unsigned char *)data)[i]) return RM_ERROR; } } else if (pcfi->buswidth == CFIDEV_BUSWIDTH_16) { for (i = 0; i < nwords; ++i) { cfi_send_cmd(h, pcfi->buswidth, 0xaa, pcfi->addr_unlock1, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0x55, pcfi->addr_unlock2, pcfi->gbus_address); cfi_send_cmd(h, pcfi->buswidth, 0xa0, pcfi->addr_unlock1, pcfi->gbus_address); cfi_write(h, pcfi->buswidth, data[i], addr + (i << 1)); if(flash_use_DQX) dqx_wait(h, addr + (i<<1), pcfi->buswidth, ((unsigned char *)data)[i], 1<<pcfi->ident.timeout_single_write, cb_usleep); else (*cb_usleep)(h, (1<<pcfi->ident.timeout_single_write)); if (cfi_read(h, addr + (i<<1), pcfi->buswidth) != ((unsigned char *)data)[i]) return RM_ERROR; } }#endif //CFIDEV_UNLOCK_BYPASS return RM_OK;}//// miscellaneous//#if (defined _DEBUG) || (defined YAMON)static char *cfi_get_idname(RMuint32 vendor){ switch (vendor) { case CFI_PRIMARY_ID_NULL : return "None"; case CFI_PRIMARY_ID_INTEL_EXT : return "Intel/Sharp Extended"; case CFI_PRIMARY_ID_AMD_STD : return "AMD/Fujitsu Standard"; case CFI_PRIMARY_ID_INTEL_STD : return "Intel/Sharp Standard"; case CFI_PRIMARY_ID_AMD_EXT : return "AMD/Fujitsu Extended"; case CFI_PRIMARY_ID_MITSUBISHI_STD : return "Mitsubishi Standard"; case CFI_PRIMARY_ID_MITSUBISHI_EXT : return "Mitsubishi Extended"; case CFI_PRIMARY_ID_SST : return "Page Write Command Set"; case CFI_PRIMARY_ID_RESERVED : return "Not Allowed / Reserved for Future Use"; default: return "Unknown"; }}#endifstatic void flash_list(cfi_info *pcfi){ RMint32 j; RMDBGLOG((ENABLE,"Parallel Flash address: 0x%x, bus width: %d\n", pcfi->gbus_address, pcfi->buswidth)); RMDBGLOG((ENABLE," ID : %s\n", cfi_get_idname(pcfi->ident.primary_id))); RMDBGLOG((ENABLE," Size : %d KB (0x%x)\n", pcfi->size >> 10, pcfi->size)); RMDBGLOG((ENABLE," Buffer Size : %d\n", pcfi->ident.max_multibyte_write)); RMDBGLOG((ENABLE," Regions : %d\n", pcfi->ident.num_erase_regions)); for (j = 0; j < pcfi->ident.num_erase_regions; ++j) { RMDBGLOG((ENABLE," %d : 0x%x - 0x%x * 0x%x\n", j, pcfi->erase_regions[j].start, pcfi->erase_regions[j].size, pcfi->erase_regions[j].blocks)); }#if 0 RMDBGLOG((ENABLE,"\n")); RMDBGLOG((ENABLE," timeout_single_write(typical*max)(us) : ")); if(pcfi->ident.timeout_single_write) RMDBGLOG((ENABLE,"%d * %d\n", 1<<pcfi->ident.timeout_single_write, 1<<pcfi->ident.max_timeout_single_write)); else RMDBGLOG((ENABLE,"not supported\n")); RMDBGLOG((ENABLE," timeout_block_erase(typical*max)(ms) : ")); if(pcfi->ident.timeout_block_erase) RMDBGLOG((ENABLE,"%d * %d\n", 1<<pcfi->ident.timeout_block_erase, 1<<pcfi->ident.max_timeout_block_erase)); else RMDBGLOG((ENABLE,"not supported\n")); RMDBGLOG((ENABLE," timeout_chip_erase(typical*max)(ms) : ")); if(pcfi->ident.timeout_chip_erase) RMDBGLOG((ENABLE,"%d * %d\n", 1<<pcfi->ident.timeout_chip_erase, 1<<pcfi->ident.max_timeout_chip_erase)); else RMDBGLOG((ENABLE,"not supported\n"));#endif}#ifdef YAMON //emdbg.c#define RM_MAX_STRING 512extern int vsprintf(char *buf, const char *fmt, va_list ap);#ifndef RMDBGLOG_implementationvoid RMDBGLOG_implementation(RMbool active,const RMascii *filename,RMint32 line,const RMascii *text,...){ if (active) { va_list ap; char str[RM_MAX_STRING]; //snprintf((char *)str,RM_MAX_STRING,"[%s:%ld] ",(char *)filename,line); va_start(ap, text); //vsnprintf((char *)(str+strlen(str)), RM_MAX_STRING-strlen(str), text, ap); vsprintf((char *)(str), text, ap); va_end(ap); //fprintf(stderr,str); emprintk("%s",str); }}#endif // RMDBGLOG_implementation#ifndef RMDBGPRINT_implementationvoid RMDBGPRINT_implementation(RMbool active,const RMascii *filename,RMint32 line,const RMascii *text,...){ if (active) { va_list ap; char str[RM_MAX_STRING]; va_start(ap, text); //vsnprintf((char *)str,RM_MAX_STRING,text,ap); vsprintf((char *)str,text,ap); va_end(ap); //fprintf(stderr,str); emprintk("%s",str); }}#endif // RMDBGPRINT_implementation#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -