xref: /inferno-os/os/port/flashintel (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
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