i28f128.c revision 1.2 1 /* $NetBSD: i28f128.c,v 1.2 2003/06/15 08:50:05 igy Exp $ */
2
3 /*
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Naoto Shimazaki of YOKOGAWA Electric Corporation.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Flash Memory Writer
41 */
42
43 #include <lib/libsa/stand.h>
44
45 #include "extern.h"
46
47 #include "i28f128reg.h"
48
49 #define USE_TWIDDLE
50
51 /*
52 * XXX
53 * this function is too much specific for the device.
54 */
55 int
56 i28f128_probe(void *base)
57 {
58 static const u_int8_t vendor_code[] = {
59 0x89, /* manufacturer code: intel */
60 0x18, /* device code: 28F128 */
61 };
62
63 static const u_int8_t idstr[] = {
64 'Q', 'R', 'Y',
65 0x01, 0x00,
66 0x31, 0x00,
67 0xff
68 };
69
70 int i;
71
72 /* start Common Flash Interface Query */
73 REGWRITE_2(base, 0, 0x98);
74
75 /* read CFI Query ID string */
76 for (i = 0; idstr[i] != 0xff; i++) {
77 if (REGREAD_2(base, (0x10 + i) << 1) != idstr[i])
78 return 1;
79 }
80
81 /* read manufacturer code and device code */
82 if (REGREAD_2(base, 0x00) != vendor_code[0])
83 return 1;
84 if (REGREAD_2(base, 0x02) != vendor_code[1])
85 return 1;
86
87 REGWRITE_2(base, 0, 0xff);
88 return 0;
89 }
90
91 static int
92 block_erase(void *addr)
93 {
94 int status;
95
96 REGWRITE_2(addr, 0, I28F128_BLK_ERASE_1ST);
97 REGWRITE_2(addr, 0, I28F128_BLK_ERASE_2ND);
98
99 do {
100 status = REGREAD_2(addr, 0);
101 } while (!ISSET(status, I28F128_S_READY));
102
103 REGWRITE_2(addr, 0, I28F128_CLEAR_STATUS);
104 REGWRITE_2(addr, 0, I28F128_RESET);
105
106 return status & (I28F128_S_ERASE_SUSPEND
107 | I28F128_S_ERASE_ERROR
108 | I28F128_S_BLOCK_LOCKED);
109 }
110
111 static int
112 word_program(void *addr, u_int16_t data)
113 {
114 int status;
115
116 REGWRITE_2(addr, 0, I28F128_WORDBYTE_PROG);
117 REGWRITE_2(addr, 0, data);
118
119 do {
120 status = REGREAD_2(addr, 0);
121 } while (!ISSET(status, I28F128_S_READY));
122
123 REGWRITE_2(addr, 0, I28F128_CLEAR_STATUS);
124 REGWRITE_2(addr, 0, I28F128_RESET);
125
126 return status & (I28F128_S_PROG_ERROR
127 | I28F128_S_LOW_VOLTAGE
128 | I28F128_S_PROG_SUSPEND
129 | I28F128_S_BLOCK_LOCKED);
130 }
131
132 static int
133 block_write(void *dst, const void *src)
134 {
135 int status;
136 const u_int16_t *p;
137 u_int16_t *q;
138 const u_int16_t *fence;
139 int i;
140 const int wbuf_count = I28F128_WBUF_SIZE >> 1;
141
142 /* dst must be aligned to block boundary. */
143 if (I28F128_BLOCK_MASK & (u_int32_t) dst)
144 return -1;
145
146 if (memcmp(dst, src, I28F128_BLOCK_SIZE) == 0)
147 return 0;
148
149 if ((status = block_erase(dst)) != 0)
150 return status;
151
152 p = src;
153 q = dst;
154 fence = p + (I28F128_BLOCK_SIZE >> 1);
155 do {
156 do {
157 REGWRITE_2(dst, 0, I28F128_WRITE_BUFFER);
158 status = REGREAD_2(dst, 0);
159 } while (!ISSET(status, I28F128_XS_BUF_AVAIL));
160
161 REGWRITE_2(dst, 0, wbuf_count - 1);
162
163 for (i = wbuf_count; i > 0; i--, p++, q++)
164 REGWRITE_2(q, 0, *p);
165
166 REGWRITE_2(dst, 0, I28F128_WBUF_CONFIRM);
167
168 do {
169 REGWRITE_2(dst, 0, I28F128_READ_STATUS);
170 status = REGREAD_2(dst, 0);
171 } while (!(status & I28F128_S_READY));
172
173 } while (p < fence);
174
175 REGWRITE_2(dst, 0, I28F128_CLEAR_STATUS);
176 REGWRITE_2(dst, 0, I28F128_RESET);
177
178 return 0;
179 }
180
181 int
182 i28f128_region_write(void *dst, const void *src, size_t len)
183 {
184 int status;
185 const u_int16_t *p = src;
186 u_int16_t *q = dst;
187
188 /* dst must be aligned to block boundary. */
189 if (I28F128_BLOCK_MASK & (u_int32_t) dst)
190 return -1;
191
192 while (len >= I28F128_BLOCK_SIZE) {
193 if ((status = block_write(q, p)) != 0)
194 return status;
195 putchar('b');
196 p += I28F128_BLOCK_SIZE >> 1;
197 q += I28F128_BLOCK_SIZE >> 1;
198 len -= I28F128_BLOCK_SIZE;
199 }
200
201 if (len > 0) {
202 if (memcmp(p, q, len) == 0)
203 return 0;
204 if ((status = block_erase(q)) != 0)
205 return status;
206 for (; len > 0; len -= 2) {
207 #ifdef USE_TWIDDLE
208 if (((u_int32_t) q % 4096) == 0)
209 twiddle();
210 #endif
211 if ((status = word_program(q++, *p++)) != 0)
212 return status;
213 }
214 printf("w");
215 }
216
217 putchar('\n');
218 return 0;
219 }
220