ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /os/port/flashcfi8.c/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/flashif.h"
/*
* Common Flash Interface (1x8 and 2x8)
*/
/* interleaved flash has chips at even and odd word addresses */
#define I(x) (((x)<<24)|((x)<<16)|((x)<<8)|(x))
enum {
ReadArray = I(0xFF),
ReadQuery = I(0x98),
};
/* TO DO: flash amd */
#include "flashintel"
static int
cfiget1(Flash *f, ulong a)
{
ulong v;
v = flashget(f, a);
//iprint("%.8lux->%.4ux\n", a, v);
return v & 0xFF;
}
static int
cfiget2(Flash *f, ulong i)
{
return (cfiget1(f, i+1)<<8) | cfiget1(f, i);
}
static int
cfiquery(Flash *f)
{
Flashregion *r;
ulong addr;
int i;
flashput(f, 0x55, ReadQuery);
if(!(cfiget1(f, 0x10) == 'Q' && cfiget1(f, 0x11) == 'R' && cfiget1(f, 0x12) == 'Y')) /* TO DO: detect interleave */
return 0;
f->alg = cfiget2(f, 0x13);
i = cfiget1(f, 0x27);
if(i > 0 && i < 32)
i = 1<<i;
else
i = 0;
f->devsize = i;
f->size = f->devsize;
if(f->interleave)
f->size *= 2;
i = cfiget2(f, 0x2A);
if(i > 0 && i < 32)
i = 1<<i;
else
i = 0;
f->maxwb = i;
f->nr = cfiget1(f, 0x2C);
if(f->nr != 0){
addr = 0;
for(i=0; i<f->nr; i++){
r = &f->regions[i];
r->n = cfiget2(f, 0x2D+4*i)+1;
r->erasesize = cfiget2(f, 0x2D+2+4*i)*256;
if(r->erasesize == 0)
r->erasesize = 128;
if(f->interleave)
r->erasesize *= 2; /* TO DO */
r->start = addr;
r->end = r->start + r->n*r->erasesize;
}
if(1){
iprint("cfi: devsize=%lud maxwb=%d\n", f->devsize, f->maxwb);
for(i=0; i<f->nr; i++){
r = &f->regions[i];
iprint("flash %d: %d %lud %8.8lux %8.8lux\n", i, r->n, r->erasesize, r->start, r->end);
}
}
}else{
f->nr = 1;
f->regions[0] = (Flashregion){1, 0, f->devsize, f->devsize, 0};
}
return 1;
}
static int
reset(Flash *f)
{
if(f->xip)
return -1; /* can't use this interface if executing from flash */
if(f->width == 0)
f->width = 1;
if(!cfiquery(f) && f->bshift==0)
f->bshift = 1; /* try this */
if(!cfiquery(f) || f->alg != 1 && f->alg != 3){
if(f->alg == 2){
print("amd algorithm\n");
goto ok;
}
/* apparently not CFI: try to reset to read mode before return */
flashput(f, 0x55, ClearStatus);
flashput(f, 0x55, ReadArray);
return -1;
}
ok:
switch(f->width){
case 1:
f->cmask = 0x00FF;
break;
case 2:
f->cmask = 0xFFFF;
break;
case 4:
f->cmask = 0xFFFFFFFF;
break;
}
flashput(f, 0x55, ClearStatus);
flashput(f, 0x55, ReadID);
f->id = cfiget1(f, 0x00);
f->devid = cfiget1(f, 0x01);
flashput(f, 0x55, ClearStatus);
flashput(f, 0x55, ReadArray);
f->erasezone = nil;
f->suspend = nil;
f->resume = nil;
return 0;
}
void
flashcfi8link(void)
{
addflashcard("cfi8", reset);
}