1*74a4d8c2SCharles.Forsyth 2*74a4d8c2SCharles.Forsythenum { 3*74a4d8c2SCharles.Forsyth DQ7 = I(0x80), 4*74a4d8c2SCharles.Forsyth DQ6 = I(0x40), 5*74a4d8c2SCharles.Forsyth DQ5 = I(0x20), 6*74a4d8c2SCharles.Forsyth DQ4 = I(0x10), 7*74a4d8c2SCharles.Forsyth DQ3 = I(0x08), 8*74a4d8c2SCharles.Forsyth DQ2 = I(0x04), 9*74a4d8c2SCharles.Forsyth DQ1 = I(0x02), 10*74a4d8c2SCharles.Forsyth DQ0 = I(0x01), 11*74a4d8c2SCharles.Forsyth}; 12*74a4d8c2SCharles.Forsyth 13*74a4d8c2SCharles.Forsyth/* 14*74a4d8c2SCharles.Forsyth * intel algorithm 15*74a4d8c2SCharles.Forsyth */ 16*74a4d8c2SCharles.Forsyth 17*74a4d8c2SCharles.Forsythenum { 18*74a4d8c2SCharles.Forsyth ReadID = I(0x90), 19*74a4d8c2SCharles.Forsyth ClearStatus = I(0x50), 20*74a4d8c2SCharles.Forsyth ReadStatus = I(0x70), 21*74a4d8c2SCharles.Forsyth Program = I(0x40), 22*74a4d8c2SCharles.Forsyth BlockErase = I(0x20), 23*74a4d8c2SCharles.Forsyth Confirm = I(0xD0), 24*74a4d8c2SCharles.Forsyth}; 25*74a4d8c2SCharles.Forsyth 26*74a4d8c2SCharles.Forsyth#define DPRINT if(0)print 27*74a4d8c2SCharles.Forsyth#define EPRINT if(1)print 28*74a4d8c2SCharles.Forsyth 29*74a4d8c2SCharles.Forsythstatic char* 30*74a4d8c2SCharles.Forsythintelwait(Flash *f, void *p, ulong ticks) 31*74a4d8c2SCharles.Forsyth{ 32*74a4d8c2SCharles.Forsyth ulong csr, mask; 33*74a4d8c2SCharles.Forsyth 34*74a4d8c2SCharles.Forsyth ticks += m->ticks+1; 35*74a4d8c2SCharles.Forsyth mask = f->cmask; 36*74a4d8c2SCharles.Forsyth for(;;){ 37*74a4d8c2SCharles.Forsyth if(f->width == 2) 38*74a4d8c2SCharles.Forsyth csr = *(ushort*)p; 39*74a4d8c2SCharles.Forsyth else 40*74a4d8c2SCharles.Forsyth csr = *(ulong*)p; 41*74a4d8c2SCharles.Forsyth if((csr & mask) == (DQ7 & mask)) 42*74a4d8c2SCharles.Forsyth break; 43*74a4d8c2SCharles.Forsyth sched(); 44*74a4d8c2SCharles.Forsyth if(m->ticks >= ticks) 45*74a4d8c2SCharles.Forsyth return "flash write timed out"; 46*74a4d8c2SCharles.Forsyth } 47*74a4d8c2SCharles.Forsyth if(csr & (DQ5|DQ4|DQ3|DQ1)){ 48*74a4d8c2SCharles.Forsyth EPRINT("flash: error: %8.8lux %8.8lux\n", p, csr); 49*74a4d8c2SCharles.Forsyth if(csr & DQ1) 50*74a4d8c2SCharles.Forsyth return "flash block locked"; 51*74a4d8c2SCharles.Forsyth if(csr & DQ3) 52*74a4d8c2SCharles.Forsyth return "low flash programming voltage"; 53*74a4d8c2SCharles.Forsyth return Eio; 54*74a4d8c2SCharles.Forsyth } 55*74a4d8c2SCharles.Forsyth return nil; 56*74a4d8c2SCharles.Forsyth} 57*74a4d8c2SCharles.Forsyth 58*74a4d8c2SCharles.Forsythstatic int 59*74a4d8c2SCharles.Forsythintelerase(Flash *f, Flashregion *r, ulong addr) 60*74a4d8c2SCharles.Forsyth{ 61*74a4d8c2SCharles.Forsyth int s; 62*74a4d8c2SCharles.Forsyth char *e; 63*74a4d8c2SCharles.Forsyth 64*74a4d8c2SCharles.Forsyth DPRINT("flash: erase zone %8.8lux\n", addr); 65*74a4d8c2SCharles.Forsyth if(addr & (r->erasesize-1)) 66*74a4d8c2SCharles.Forsyth return -1; /* bad zone */ 67*74a4d8c2SCharles.Forsyth if(f->width == 2){ 68*74a4d8c2SCharles.Forsyth ushort *p = (ushort*)((ulong)f->addr + addr); 69*74a4d8c2SCharles.Forsyth s = splhi(); 70*74a4d8c2SCharles.Forsyth *p = BlockErase & f->cmask; 71*74a4d8c2SCharles.Forsyth *p = Confirm & f->cmask; 72*74a4d8c2SCharles.Forsyth splx(s); 73*74a4d8c2SCharles.Forsyth e = intelwait(f, p, MS2TK(8*1000)); 74*74a4d8c2SCharles.Forsyth *p = ClearStatus & f->cmask; 75*74a4d8c2SCharles.Forsyth *p = ReadArray & f->cmask; 76*74a4d8c2SCharles.Forsyth }else{ 77*74a4d8c2SCharles.Forsyth ulong *p = (ulong*)((ulong)f->addr + addr); 78*74a4d8c2SCharles.Forsyth s = splhi(); 79*74a4d8c2SCharles.Forsyth *p = BlockErase & f->cmask; 80*74a4d8c2SCharles.Forsyth *p = Confirm & f->cmask; 81*74a4d8c2SCharles.Forsyth splx(s); 82*74a4d8c2SCharles.Forsyth e = intelwait(f, p, MS2TK(8*1000)); 83*74a4d8c2SCharles.Forsyth *p = ClearStatus & f->cmask; 84*74a4d8c2SCharles.Forsyth *p = ReadArray & f->cmask; 85*74a4d8c2SCharles.Forsyth } 86*74a4d8c2SCharles.Forsyth if(e != nil) 87*74a4d8c2SCharles.Forsyth error(e); 88*74a4d8c2SCharles.Forsyth return 0; 89*74a4d8c2SCharles.Forsyth} 90*74a4d8c2SCharles.Forsyth 91*74a4d8c2SCharles.Forsythstatic int 92*74a4d8c2SCharles.Forsythintelwrite2(Flash *f, ulong offset, void *buf, long n) 93*74a4d8c2SCharles.Forsyth{ 94*74a4d8c2SCharles.Forsyth ushort *a, *v; 95*74a4d8c2SCharles.Forsyth ulong w; 96*74a4d8c2SCharles.Forsyth int s; 97*74a4d8c2SCharles.Forsyth char *e; 98*74a4d8c2SCharles.Forsyth 99*74a4d8c2SCharles.Forsyth if(((ulong)f->addr|offset|n)&(f->width-1)) 100*74a4d8c2SCharles.Forsyth return -1; 101*74a4d8c2SCharles.Forsyth a = (ushort*)((ulong)f->addr + offset); 102*74a4d8c2SCharles.Forsyth n /= f->width; 103*74a4d8c2SCharles.Forsyth v = buf; 104*74a4d8c2SCharles.Forsyth if(waserror()){ 105*74a4d8c2SCharles.Forsyth *a = ClearStatus & f->cmask; 106*74a4d8c2SCharles.Forsyth *a = ReadArray & f->cmask; 107*74a4d8c2SCharles.Forsyth nexterror(); 108*74a4d8c2SCharles.Forsyth } 109*74a4d8c2SCharles.Forsyth for(; --n >= 0; v++, a++){ 110*74a4d8c2SCharles.Forsyth w = *a; 111*74a4d8c2SCharles.Forsyth DPRINT("flash: write %p %#ulx -> %#lux\n", a, w, (ulong)*v); 112*74a4d8c2SCharles.Forsyth if(w == *v) 113*74a4d8c2SCharles.Forsyth continue; /* already set */ 114*74a4d8c2SCharles.Forsyth if(~w & *v) 115*74a4d8c2SCharles.Forsyth error("flash not erased"); 116*74a4d8c2SCharles.Forsyth s = splhi(); 117*74a4d8c2SCharles.Forsyth *a = Program & f->cmask; /* program */ 118*74a4d8c2SCharles.Forsyth *a = *v; 119*74a4d8c2SCharles.Forsyth splx(s); 120*74a4d8c2SCharles.Forsyth microdelay(8); 121*74a4d8c2SCharles.Forsyth e = intelwait(f, a, 5); 122*74a4d8c2SCharles.Forsyth *a = ClearStatus & f->cmask; 123*74a4d8c2SCharles.Forsyth *a = ReadArray & f->cmask; 124*74a4d8c2SCharles.Forsyth if(e != nil) 125*74a4d8c2SCharles.Forsyth error(e); 126*74a4d8c2SCharles.Forsyth w = *a; 127*74a4d8c2SCharles.Forsyth if(w != *v){ 128*74a4d8c2SCharles.Forsyth EPRINT("flash: write %p %#8.8lux -> %#8.8lux failed\n", a, w, (ulong)*v); 129*74a4d8c2SCharles.Forsyth error(Eio); 130*74a4d8c2SCharles.Forsyth } 131*74a4d8c2SCharles.Forsyth } 132*74a4d8c2SCharles.Forsyth poperror(); 133*74a4d8c2SCharles.Forsyth return 0; 134*74a4d8c2SCharles.Forsyth} 135*74a4d8c2SCharles.Forsyth 136*74a4d8c2SCharles.Forsythstatic int 137*74a4d8c2SCharles.Forsythintelwrite4(Flash *f, ulong offset, void *buf, long n) 138*74a4d8c2SCharles.Forsyth{ 139*74a4d8c2SCharles.Forsyth ulong *a, *v; 140*74a4d8c2SCharles.Forsyth ulong w; 141*74a4d8c2SCharles.Forsyth int s; 142*74a4d8c2SCharles.Forsyth char *e; 143*74a4d8c2SCharles.Forsyth 144*74a4d8c2SCharles.Forsyth if(((ulong)f->addr|offset|n)&(f->width-1)) 145*74a4d8c2SCharles.Forsyth return -1; 146*74a4d8c2SCharles.Forsyth a = (ulong*)((ulong)f->addr + offset); 147*74a4d8c2SCharles.Forsyth n /= f->width; 148*74a4d8c2SCharles.Forsyth v = buf; 149*74a4d8c2SCharles.Forsyth if(waserror()){ 150*74a4d8c2SCharles.Forsyth *a = ClearStatus & f->cmask; 151*74a4d8c2SCharles.Forsyth *a = ReadArray & f->cmask; 152*74a4d8c2SCharles.Forsyth nexterror(); 153*74a4d8c2SCharles.Forsyth } 154*74a4d8c2SCharles.Forsyth for(; --n >= 0; v++, a++){ 155*74a4d8c2SCharles.Forsyth w = *a; 156*74a4d8c2SCharles.Forsyth DPRINT("flash: write %p %#ulx -> %#lux\n", a, w, (ulong)*v); 157*74a4d8c2SCharles.Forsyth if(w == *v) 158*74a4d8c2SCharles.Forsyth continue; /* already set */ 159*74a4d8c2SCharles.Forsyth if(~w & *v) 160*74a4d8c2SCharles.Forsyth error("flash not erased"); 161*74a4d8c2SCharles.Forsyth s = splhi(); 162*74a4d8c2SCharles.Forsyth *a = Program; /* program */ 163*74a4d8c2SCharles.Forsyth *a = *v; 164*74a4d8c2SCharles.Forsyth splx(s); 165*74a4d8c2SCharles.Forsyth microdelay(8); 166*74a4d8c2SCharles.Forsyth e = intelwait(f, a, 5); 167*74a4d8c2SCharles.Forsyth *a = ClearStatus & f->cmask; 168*74a4d8c2SCharles.Forsyth *a = ReadArray & f->cmask; 169*74a4d8c2SCharles.Forsyth if(e != nil) 170*74a4d8c2SCharles.Forsyth error(e); 171*74a4d8c2SCharles.Forsyth w = *a; 172*74a4d8c2SCharles.Forsyth if(w != *v){ 173*74a4d8c2SCharles.Forsyth EPRINT("flash: write %p %#8.8lux -> %#8.8lux failed\n", a, w, *v); 174*74a4d8c2SCharles.Forsyth error(Eio); 175*74a4d8c2SCharles.Forsyth } 176*74a4d8c2SCharles.Forsyth } 177*74a4d8c2SCharles.Forsyth poperror(); 178*74a4d8c2SCharles.Forsyth return 0; 179*74a4d8c2SCharles.Forsyth} 180