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