📄 skgespi.c
字号:
* return: * 0 - if successful * 1 - if fails * * END_MANUAL_ENTRY() */static int spi_yuk2_sst_write_dword(unsigned long address, /* address to write to */unsigned long value) /* new value to be written */{ unsigned long spi_ctrl_reg; unsigned long verify_value; unsigned long i; for (i = 0; i < 4; i++) { spi_yuk2_write_enable(); /* write spi address */ spi_out32(SPI_Y2_ADDRESS_REG, address + i); /* write the new value */ spi_out32(SPI_Y2_DATA_REG, (value >> i*8) & 0x000000ff); /* execute the spi write command */ spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg); spi_ctrl_reg &= ~SPI_Y2_CMD_MASK; spi_ctrl_reg |= SPI_Y2_WR; spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg); /* wait for write to finish */ SPI_Y2_WAIT_SE_FINISH_WR(); verify_value = spi_yuk2_read_dword(address); /* verify if write was successful*/ if ( ((verify_value >> i*8) & 0x000000ff) != ((value >> i*8) & 0x000000ff) ) { fl_print("\n*** SPI data write error at address 0x%08x, ","is 0x%08x, should 0x%08x\n", address + i, ((verify_value >> i*8) & 0x000000ff), ((value >> i*8) & 0x000000ff)); return 1; } } return 0;}/* * BEGIN_MANUAL_ENTRY() * * int spi_yuk2_sst_clear_write_protection() * * Clear the write protection bits for SST flash types because * they are set by default. * * Uses: * * IN: * * return: * nothing * * END_MANUAL_ENTRY() */void spi_yuk2_sst_clear_write_protection(){ unsigned long spi_ctrl_reg; unsigned long op; unsigned long addr; unsigned char status; spi_in32(SPI_Y2_OPCODE_REG1, &op); op &= 0xffff00ff; op |= 0x00000100; spi_out32(SPI_Y2_OPCODE_REG1, op); spi_in32(SPI_Y2_OPCODE_REG2, &op); op &= 0xffffff00; op |= 0x00000050; spi_out32(SPI_Y2_OPCODE_REG2, op); /* execute write status register enable command */ spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg); spi_ctrl_reg &= ~SPI_Y2_CMD_MASK; spi_ctrl_reg |= SPI_Y2_WEN; spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg); /* wait for the SPI to finish RD operation */ SPI_Y2_WAIT_SE_FINISH_CMD(); spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg); status = (unsigned char)(spi_ctrl_reg & 0xfffffff3); addr = ((unsigned long)status | (unsigned long)(status << 8) | (unsigned long)(status << 16) | (unsigned long)(status << 24)); /* write spi address */ spi_out32(SPI_Y2_ADDRESS_REG, addr); /* write the new value */ spi_out32(SPI_Y2_DATA_REG, addr); /* execute the write status register command */ spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg); spi_ctrl_reg &= ~SPI_Y2_CMD_MASK; spi_ctrl_reg |= SPI_Y2_RD; spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg); /* wait for the SPI to finish RD operation */ SPI_Y2_WAIT_SE_FINISH_CMD(); spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);}/* * BEGIN_MANUAL_ENTRY() * * static void spi_yuk2_erase_sector( * unsigned long sector_num) * * This function will erase the sector specified allowing thus data to be written * * Uses: * * IN: * * return: * nothing * * END_MANUAL_ENTRY() */static void spi_yuk2_erase_sector(unsigned long sector_num) /* sector to be erased */{ unsigned long spi_ctrl_reg; spi_yuk2_write_enable(); /* write sector start address */ spi_out32(SPI_Y2_ADDRESS_REG, spi_yuk2_dev_table[spi_yuk2_dev].sector_size * sector_num); /* execute erase sector command */ spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg); spi_ctrl_reg &= ~SPI_Y2_CMD_MASK; spi_ctrl_reg |= SPI_Y2_SERS; spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg); SPI_Y2_WAIT_SE_FINISH_WR();}/* * BEGIN_MANUAL_ENTRY() * * void spi_yuk2_erase_chip() * * This function will erase the complete SPI EPROM chip * * Uses: * * IN: * * return: * nothing * * END_MANUAL_ENTRY() */void spi_yuk2_erase_chip(){ unsigned long spi_ctrl_reg; spi_yuk2_write_enable(); /* execute erase chip command */ spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg); spi_ctrl_reg &= ~SPI_Y2_CMD_MASK; spi_ctrl_reg |= SPI_Y2_CERS; spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg); SPI_Y2_WAIT_SE_FINISH_WR();}/* * BEGIN_MANUAL_ENTRY() * * unsigned short spi_yuk2_read_chip_id() * * Read SPI vendor and device id * * Uses: * * IN: * * return: * The lower byte containes the device id and the upper the vendor id * * END_MANUAL_ENTRY() */unsigned short spi_yuk2_read_chip_id(){ unsigned short chip_id_local; unsigned long spi_ctrl_reg = 0; unsigned long opcode_reg1; /* for Yukon-Extreme SPI issue */ spi_out32(SPI_Y2_CONTROL_REG, 0x00); /* * set read id opcode for flash currently selected */ spi_in32(SPI_Y2_OPCODE_REG1, &opcode_reg1); opcode_reg1 &= 0xff00ffffL; opcode_reg1 |= (((unsigned long)spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read_id) << 16); spi_out32(SPI_Y2_OPCODE_REG1, opcode_reg1); /* * read spi control register */ spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg); spi_ctrl_reg &= ~(SPI_Y2_CMD_MASK | SPI_Y2_RDID_PROT); /* select protocol for chip id read out */ if( spi_yuk2_dev_table[spi_yuk2_dev].set_protocol ) { spi_ctrl_reg |= SPI_Y2_RDID_PROT; } /* execute read chip id command */ spi_ctrl_reg |= SPI_Y2_RDID; spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg); SPI_Y2_WAIT_SE_FINISH_CMD(); spi_in16(SPI_Y2_VENDOR_DEVICE_ID_REG, &chip_id_local); return (chip_id_local);}/* * BEGIN_MANUAL_ENTRY() * * int spi_yuk2_get_dev_index(void) * * Identify the SPI device and return its device * table index * * Uses: * * IN: * * return: * -1 unknown or no flash device * >=0 flash device table index * * END_MANUAL_ENTRY() */#ifdef USE_ASF_DASH_FWint spi_yuk2_get_dev_index(){ unsigned short spi_chip_id; unsigned char man_id; unsigned char dev_id; unsigned int i; /* search for flash in device table */ for(i = 0; i < (sizeof(spi_yuk2_dev_table) / sizeof(spi_yuk2_dev_table[0])); i++) { if (chip_id != CHIP_ID_YUKON_EC_U && chip_id != CHIP_ID_YUKON_EX && (i == 0 || i == 1)) { continue; } spi_yuk2_dev = i; spi_chip_id = spi_yuk2_read_chip_id(); man_id = (unsigned char)((spi_chip_id & SPI_Y2_MAN_ID_MASK) >> 8); dev_id = (unsigned char)(spi_chip_id & SPI_Y2_DEV_ID_MASK); if(spi_yuk2_dev_table[i].man_id == man_id && spi_yuk2_dev_table[i].dev_id == dev_id) { fl_print("\nFlash Device\t: %s ", spi_yuk2_dev_table[i].dev_name); fl_print("(VID 0x%2.2x, ", man_id); fl_print("DID 0x%2.2x)\n", dev_id); return(i); } } spi_yuk2_dev = -1; return(-1);}#elseint spi_yuk2_get_dev_index(){ unsigned short chip_id_local; unsigned char man_id; unsigned char dev_id; int i; /* search for flash in device table */ for(i = 0; i < (sizeof(spi_yuk2_dev_table) / sizeof(spi_yuk2_dev_table[0])); i++) { spi_yuk2_dev = i; chip_id_local = spi_yuk2_read_chip_id(); man_id = (unsigned char)((chip_id_local & SPI_Y2_MAN_ID_MASK) >> 8); dev_id = (unsigned char)(chip_id_local & SPI_Y2_DEV_ID_MASK); if(spi_yuk2_dev_table[i].man_id == man_id && spi_yuk2_dev_table[i].dev_id == dev_id) { fl_print("\nFlash Device %s found\n", spi_yuk2_dev_table[i].dev_name); fl_print(" - Vendor ID : 0x%2.2x \n", man_id); fl_print(" - Device ID : 0x%2.2x \n", dev_id); return(i); } } spi_yuk2_dev = -1; return(-1);}#endif/* * BEGIN_MANUAL_ENTRY() * * static int spi_yuk2_flash_erase(unsigned long off,unsigned long len) * * Erase all sectors of the flash prom affected by the address * range denoted by parameters "off" (address offset) and "len" * (length of address range). * * Uses: spi_in32, spi_out32, spi_in8, spi_timer * * IN: * off: start offset in flash eprom for erase * len: length in flash eprom for erase * (all necessary sectors will be erased) * * return: * 0 Success * 1 Timeout * * END_MANUAL_ENTRY() */static int spi_yuk2_flash_erase(unsigned long off,unsigned long len){ unsigned long flash_size; unsigned long i; unsigned long start_sector; unsigned long end_sector; if(len == 0) { return(0); } flash_size = spi_yuk2_dev_table[spi_yuk2_dev].sector_size * spi_yuk2_dev_table[spi_yuk2_dev].sector_num; /* * flash size is smaller than address range which * should be erased --> don't erase flash. */ if ((off+len-1) > flash_size) { return(1); } /* * Erase complete flash if all sectors of flash are affected */ if(len > (spi_yuk2_dev_table[spi_yuk2_dev].sector_size * (spi_yuk2_dev_table[spi_yuk2_dev].sector_num - 1))) { spi_yuk2_erase_chip(); } /* * Erase all affected sectors */ else { start_sector = off / spi_yuk2_dev_table[spi_yuk2_dev].sector_size; end_sector = (off + len - 1) / spi_yuk2_dev_table[spi_yuk2_dev].sector_size; for (i = start_sector; i <= end_sector; i++) { spi_yuk2_erase_sector(i); } } return(0);}/* * BEGIN_MANUAL_ENTRY() * * static int spi_yuk2_flash_manage( * unsigned char *data, * unsigned long off, * unsigned long len, * int flag) * * Read, Verify or Write SPI Eprom * * Uses: spi_in32, spi_out32, spi_in8, spi_out8, spi_in16, spi_out16, spi_timer * * IN: * data data buffer * off start offset in flash eprom for operation * len length in flash eprom * flag SPI_READ * SPI_VERIFY * SPI_WRITE * * return: * 0 Success * 1 Timeout * * END_MANUAL_ENTRY() */#ifdef USE_ASF_DASH_FWstatic int spi_yuk2_flash_manage(unsigned char huge *data,unsigned long off,unsigned long len,int flag){ unsigned long addr; unsigned long spi_data; unsigned long huge *spi_data_ptr; unsigned long progress; unsigned long last_progress; int ret = 0; unsigned char ChipId,ChipRev,ByteVal; // assert(!(off&3)); len = (len + 3) & ~3; spi_in8(B2_CHIP_ID, &ChipId); spi_in8(B2_MAC_CFG, &ChipRev); ChipRev = (unsigned char)((ChipRev & CFG_CHIP_R_MSK) >> 4); if ((ChipId == CHIP_ID_YUKON_EX) && (ChipRev != CHIP_REV_YU_EX_A0) && (spi_yuk2_dev_table[spi_yuk2_dev].sector_size * spi_yuk2_dev_table[spi_yuk2_dev].sector_num >= 0x40000)) { spi_in8(SPI_CFG, &ByteVal); ByteVal |= SPI_CFG_A17_GATE; spi_out8(SPI_CFG, ByteVal); } progress = last_progress = 0; for (addr = off, spi_data_ptr = (unsigned long huge *)data; addr < off + len; addr+=4, spi_data_ptr++) { progress = ((addr - off) * 100) / len; if((progress - last_progress) >= 10) { fl_print("."); last_progress += 10; } switch (flag) { case SPI_READ: /* Read a dword from SPI flash */ *(spi_data_ptr) = spi_yuk2_read_dword(addr); break; case SPI_VERIFY: /* Read and verify dword from SPI flash */ spi_data = spi_yuk2_read_dword(addr); if (spi_data != *(spi_data_ptr)) { fl_print("\n*** SPI data verify error at address 0x%08lx, ", "is %x, should %x\n", addr, spi_data, *(spi_data_ptr)); ret = 1; } break; case SPI_WRITE:#if 0#ifndef SK_DIAG /* * Flash-only adapters only support * Flash sector sizes of 4096 bytes */ if (max_faddr == 0x1000) { if (ModifiedPages[addr >> 12] != (unsigned char)1) {#if 0 if ((addr % 4096) == 0) { fl_print("not writing to sector %d\n",addr >> 12); }#endif continue; } }#endif /* !SK_DIAG */#endif /* Write a dword to SPI flash */ if (spi_yuk2_dev_table[spi_yuk2_dev].man_id == SPI_MAN_ID_SST) { ret = spi_yuk2_sst_write_dword(addr, *(spi_data_ptr)); } else { ret = spi_yuk2_write_dword(addr, *(spi_data_ptr)); } break; } if (ret) { break; } } fl_print("."); return(ret);}#elsestatic int spi_yuk2_flash_manage(unsigned char *data,unsigned long off,unsigned long len,int flag){ unsigned long addr; unsigned long spi_data; unsigned int *spi_data_ptr; int ret = 0; len = (len + 3) & ~3; for (addr = off, spi_data_ptr = (unsigned int *)data; addr < off + len; addr+=4, spi_data_ptr++) { switch (flag) { case SPI_READ: /* Read a dword from SPI flash */ *(spi_data_ptr) = spi_yuk2_read_dword(addr); break; case SPI_VERIFY: /* Read and verify dword from SPI flash */ spi_data = spi_yuk2_read_dword(addr); break; if (spi_data != *(spi_data_ptr)) { fl_print("\n*** SPI data verify error at address 0x%08lx, ","is %x, should %x\n", addr, spi_data, *(spi_data_ptr)); ret = 1; } break; case SPI_WRITE: /* Write a dword to SPI flash */ if (spi_yuk2_dev_table[spi_yuk2_dev].man_id == SPI_MAN_ID_SST) { ret = spi_yuk2_sst_write_dword(addr, *(spi_data_ptr)); } else { ret = spi_yuk2_write_dword(addr, *(spi_data_ptr)); } break; } if (ret) { break; } } return(ret);}#endif/* * BEGIN_MANUAL_ENTRY() * * static int spi_yuk2_update_config( * unsigned char *data, * unsigned long off, * unsigned long len) * * Update part of config area * * Uses: spi_flash_manage, spi_flash_erase * * IN: * data data buffer * off start offset in flash eprom (config area) for operation * len length of changing data * * return: * 0 Success * 1 Timeout * * END_MANUAL_ENTRY() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -