i28f128.c revision 1.1 1 /* $NetBSD: i28f128.c,v 1.1 2003/05/01 07:02:01 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
140 /* dst must be aligned to block boundary. */
141 if (I28F128_BLOCK_MASK & (u_int32_t) dst)
142 return -1;
143
144 if (memcmp(dst, src, I28F128_BLOCK_SIZE) == 0)
145 return 0;
146
147 if ((status = block_erase(dst)) != 0)
148 return status;
149
150 p = src;
151 q = dst;
152 fence = p + (I28F128_BLOCK_SIZE >> 1);
153 do {
154 #ifdef USE_TWIDDLE
155 if (((u_int32_t) q % 4096) == 0)
156 twiddle();
157 #endif
158 if ((status = word_program(q++, *p++)) != 0)
159 return status;
160 } while (p < fence);
161
162 return 0;
163 }
164
165 int
166 i28f128_region_write(void *dst, const void *src, size_t len)
167 {
168 int status;
169 const u_int16_t *p = src;
170 u_int16_t *q = dst;
171
172 /* dst must be aligned to block boundary. */
173 if (I28F128_BLOCK_MASK & (u_int32_t) dst)
174 return -1;
175
176 while (len >= I28F128_BLOCK_SIZE) {
177 if ((status = block_write(q, p)) != 0)
178 return status;
179 putchar('b');
180 p += I28F128_BLOCK_SIZE >> 1;
181 q += I28F128_BLOCK_SIZE >> 1;
182 len -= I28F128_BLOCK_SIZE;
183 }
184
185 if (len > 0) {
186 if (memcmp(p, q, len) == 0)
187 return 0;
188 if ((status = block_erase(q)) != 0)
189 return status;
190 for (; len > 0; len -= 2) {
191 #ifdef USE_TWIDDLE
192 if (((u_int32_t) q % 4096) == 0)
193 twiddle();
194 #endif
195 if ((status = word_program(q++, *p++)) != 0)
196 return status;
197 }
198 printf("w");
199 }
200
201 putchar('\n');
202 return 0;
203 }
204