X-Git-Url: https://hackdaworld.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=betty%2Fflash.c;fp=betty%2Fflash.c;h=8d9c02a92e0685b2f878b3b7b6b341fe01a30f75;hb=5da509dc909c60d63c5fba98e7ced43040eb6827;hp=0000000000000000000000000000000000000000;hpb=b4ca71fc214ba3c58cec25661ba1f81cf7b1b871;p=my-code%2Farm.git diff --git a/betty/flash.c b/betty/flash.c new file mode 100644 index 0000000..8d9c02a --- /dev/null +++ b/betty/flash.c @@ -0,0 +1,230 @@ +/* + * flash.c - low level flash handling + * + * author: hackbard@hackdaworld.org + * + */ + +#include "flash.h" + +/* + * sector addresses + */ +static unsigned long sector_address[19]={ + 0x00000,0x02000,0x03000,0x04000,0x08000, + 0x10000,0x18000, + 0x20000,0x28000, + 0x30000,0x38000, + 0x40000,0x48000, + 0x50000,0x58000, + 0x60000,0x68000, + 0x70000,0x78000 +}; + +/* + * functions + */ + +void flash_init(void) { + + /* + * idle clocks between rad & write: 0+1 + * length of read access: 1+3 + * bls lines high during write access + * length of write access: 0+1 + * no write protect, no burst-rom + * 16 bit data width + */ + + BCFG0=0x10000420; // flash 1 + BCFG2=0x10000420; // flash 2 + + /* + * p3.27: write enable + * p3.25: chip select 2 + * p2.15 - p2.8: data bus + * a[1:15] -> address lines + */ + + PINSEL2=(PINSEL2&P2MASK)|(1<<8); + PINSEL2=(PINSEL2&P2MASK&~((1<<15)|(1<<14)))|(1<<14); + PINSEL2=(PINSEL2&P2MASK&~((1<<5)|(1<<4)))|(1<<4); + PINSEL2=(PINSEL2&P2MASK)|(1<<24); + PINSEL2=(PINSEL2&P2MASK&~((1<<27)|(1<<26)|(1<<25)))|(1<<27)|(1<<26); +} + +void flash_reset(u8 bank) { + + if((bank!='0')&(bank!='2')) + return; + + if(bank=='0') + FLASH_B0F=0xf0; + else + FLASH_B2F=0xf0; +} + +void flash_sector_erase(u8 bank,u8 sector) { + + u32 a18_12; + + if(sector>18) + return; + a18_12=sector_address[sector]<<1; + + switch(bank) { + case '0': + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + FLASH_B0F555=0x80; + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + *((volatile u16 *)(FLASH_BANK0|a18_12))=0x30; + break; + case '2': + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + FLASH_B2F555=0x80; + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + *((volatile u16 *)(FLASH_BANK2|a18_12))=0x30; + break; + default: + return; + } + + return; +} + +void flash_chip_erase(u8 bank) { + + u8 status; + + if((bank!='0')&(bank!='2')) + return; + + if(bank=='0') { + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + FLASH_B0F555=0x80; + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + FLASH_B0F555=0x10; + } + else { + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + FLASH_B2F555=0x80; + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + FLASH_B2F555=0x10; + } + + while(1) { + if(bank=='0') + status=FLASH_B0F; + else + status=FLASH_B2F; + if(status&0x80) + break; + } +} + +void flash_unlock_bypass(u8 bank) { + + if((bank!='0')&(bank!='2')) + return; + + if(bank=='0') { + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + FLASH_B0F555=0x20; + } + else { + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + FLASH_B2F555=0x20; + } +} + +void flash_unlock_bypass_reset(u8 bank) { + + if((bank!='0')&(bank!='2')) + return; + + if(bank=='0') { + FLASH_B0F=0x90; + FLASH_B0F=0x00; + } + else { + FLASH_B2F=0x90; + FLASH_B2F=0x00; + } +} + +int flash_write_word(u32 addr,u16 data) { + + u16 check; + + if(data==0xffff) + return 0; + + *((unsigned volatile short *)addr)=0xa0; + *((unsigned volatile short *)addr)=data; + while(1) { + check=*((unsigned short *)addr); + if((data&0x80)==(check&0x80)) + break; + } + if(data!=check) + return -1; + + return 0; +} + +#define flash_read_word(addr,data) *(data)=*((unsigned volatile short *)(addr)) + +int flash_write_buf(u32 addr,u16 *buf,int len) { + + int cnt,ret; + u8 bank; + + /* len must be a multiple of 2 */ + if(len&0x1) + return -1; + + /* decide the bank */ + if(addr<0x82000000) + bank='0'; + else + bank='2'; + + /* unlock */ + flash_unlock_bypass(bank); + + /* write the data */ + ret=0; + for(cnt=0;cnt