Cosmetic fixes (trivial).
[coreboot.git] / util / flashrom / jedec.c
1 /*
2  * jedec.c: driver for programming JEDEC standard flash parts
3  *
4  *
5  * Copyright 2000 Silicon Integrated System Corporation
6  * Copyright 2006 Giampiero Giancipoli <gianci@email.it>
7  * Copyright 2006 coresystems GmbH <info@coresystems.de>
8  *
9  *      This program is free software; you can redistribute it and/or modify
10  *      it under the terms of the GNU General Public License as published by
11  *      the Free Software Foundation; either version 2 of the License, or
12  *      (at your option) any later version.
13  *
14  *      This program is distributed in the hope that it will be useful,
15  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *      GNU General Public License for more details.
18  *
19  *      You should have received a copy of the GNU General Public License
20  *      along with this program; if not, write to the Free Software
21  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  *
24  * Reference:
25  *
26  */
27
28 #include <stdio.h>
29 #include <stdint.h>
30 #include "flash.h"
31
32 #define MAX_REFLASH_TRIES 0x10
33
34 void toggle_ready_jedec(volatile uint8_t *dst)
35 {
36         unsigned int i = 0;
37         uint8_t tmp1, tmp2;
38
39         tmp1 = *dst & 0x40;
40
41         while (i++ < 0xFFFFFFF) {
42                 tmp2 = *dst & 0x40;
43                 if (tmp1 == tmp2) {
44                         break;
45                 }
46                 tmp1 = tmp2;
47         }
48 }
49
50 void data_polling_jedec(volatile uint8_t *dst, uint8_t data)
51 {
52         unsigned int i = 0;
53         uint8_t tmp;
54
55         data &= 0x80;
56
57         while (i++ < 0xFFFFFFF) {
58                 tmp = *dst & 0x80;
59                 if (tmp == data) {
60                         break;
61                 }
62         }
63 }
64
65 void unprotect_jedec(volatile uint8_t *bios)
66 {
67         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
68         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
69         *(volatile uint8_t *)(bios + 0x5555) = 0x80;
70         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
71         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
72         *(volatile uint8_t *)(bios + 0x5555) = 0x20;
73
74         usleep(200);
75 }
76
77 void protect_jedec(volatile uint8_t *bios)
78 {
79         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
80         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
81         *(volatile uint8_t *)(bios + 0x5555) = 0xA0;
82
83         usleep(200);
84 }
85
86 int probe_jedec(struct flashchip *flash)
87 {
88         volatile uint8_t *bios = flash->virtual_memory;
89         uint8_t id1, id2;
90
91         /* Issue JEDEC Product ID Entry command */
92         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
93         myusec_delay(10);
94         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
95         myusec_delay(10);
96         *(volatile uint8_t *)(bios + 0x5555) = 0x90;
97         myusec_delay(10);
98
99         /* Read product ID */
100         id1 = *(volatile uint8_t *)bios;
101         id2 = *(volatile uint8_t *)(bios + 0x01);
102
103         /* Issue JEDEC Product ID Exit command */
104         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
105         myusec_delay(10);
106         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
107         myusec_delay(10);
108         *(volatile uint8_t *)(bios + 0x5555) = 0xF0;
109         myusec_delay(10);
110
111         printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
112         if (id1 == flash->manufacture_id && id2 == flash->model_id)
113                 return 1;
114
115         return 0;
116 }
117
118 int erase_sector_jedec(volatile uint8_t *bios, unsigned int page)
119 {
120         /*  Issue the Sector Erase command   */
121         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
122         myusec_delay(10);
123         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
124         myusec_delay(10);
125         *(volatile uint8_t *)(bios + 0x5555) = 0x80;
126         myusec_delay(10);
127
128         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
129         myusec_delay(10);
130         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
131         myusec_delay(10);
132         *(volatile uint8_t *)(bios + page) = 0x30;
133         myusec_delay(10);
134
135         /* wait for Toggle bit ready         */
136         toggle_ready_jedec(bios);
137
138         return 0;
139 }
140
141 int erase_block_jedec(volatile uint8_t *bios, unsigned int block)
142 {
143         /*  Issue the Sector Erase command   */
144         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
145         myusec_delay(10);
146         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
147         myusec_delay(10);
148         *(volatile uint8_t *)(bios + 0x5555) = 0x80;
149         myusec_delay(10);
150
151         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
152         myusec_delay(10);
153         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
154         myusec_delay(10);
155         *(volatile uint8_t *)(bios + block) = 0x50;
156         myusec_delay(10);
157
158         /* wait for Toggle bit ready         */
159         toggle_ready_jedec(bios);
160
161         return 0;
162 }
163
164 int erase_chip_jedec(struct flashchip *flash)
165 {
166         volatile uint8_t *bios = flash->virtual_memory;
167
168         /*  Issue the JEDEC Chip Erase command   */
169         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
170         myusec_delay(10);
171         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
172         myusec_delay(10);
173         *(volatile uint8_t *)(bios + 0x5555) = 0x80;
174         myusec_delay(10);
175
176         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
177         myusec_delay(10);
178         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
179         myusec_delay(10);
180         *(volatile uint8_t *)(bios + 0x5555) = 0x10;
181         myusec_delay(10);
182
183         toggle_ready_jedec(bios);
184
185         return 0;
186 }
187
188 int write_page_write_jedec(volatile uint8_t *bios, uint8_t *src,
189                            volatile uint8_t *dst, int page_size)
190 {
191         int i, tried = 0, start_index = 0, ok;
192         volatile uint8_t *d = dst;
193         uint8_t *s = src;
194
195 retry:
196         /* Issue JEDEC Data Unprotect comand */
197         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
198         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
199         *(volatile uint8_t *)(bios + 0x5555) = 0xA0;
200
201         /* transfer data from source to destination */
202         for (i = start_index; i < page_size; i++) {
203                 /* If the data is 0xFF, don't program it */
204                 if (*src != 0xFF)
205                         *dst = *src;
206                 dst++;
207                 src++;
208         }
209
210         toggle_ready_jedec(dst - 1);
211
212         dst = d;
213         src = s;
214         ok = 1;
215         for (i = 0; i < page_size; i++) {
216                 if (*dst != *src) {
217                         ok = 0;
218                         break;
219                 }
220                 dst++;
221                 src++;
222         }
223
224         if (!ok && tried++ < MAX_REFLASH_TRIES) {
225                 start_index = i;
226                 goto retry;
227         }
228         if (!ok) {
229                 fprintf(stderr, " page %d failed!\n",
230                         (unsigned int)(d - bios) / page_size);
231         }
232         return !ok;
233 }
234
235 int write_byte_program_jedec(volatile uint8_t *bios, uint8_t *src,
236                              volatile uint8_t *dst)
237 {
238         int tried = 0, ok = 1;
239
240         /* If the data is 0xFF, don't program it */
241         if (*src == 0xFF) {
242                 return -1;
243         }
244
245 retry:
246         /* Issue JEDEC Byte Program command */
247         *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
248         *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
249         *(volatile uint8_t *)(bios + 0x5555) = 0xA0;
250
251         /* transfer data from source to destination */
252         *dst = *src;
253         toggle_ready_jedec(bios);
254
255         if (*dst != *src && tried++ < MAX_REFLASH_TRIES) {
256                 goto retry;
257         }
258
259         if (tried >= MAX_REFLASH_TRIES)
260                 ok = 0;
261
262         return !ok;
263 }
264
265 int write_sector_jedec(volatile uint8_t *bios, uint8_t *src,
266                        volatile uint8_t *dst, unsigned int page_size)
267 {
268         int i;
269
270         for (i = 0; i < page_size; i++) {
271                 write_byte_program_jedec(bios, src, dst);
272                 dst++, src++;
273         }
274
275         return 0;
276 }
277
278 int write_jedec(struct flashchip *flash, uint8_t *buf)
279 {
280         int i;
281         int total_size = flash->total_size * 1024;
282         int page_size = flash->page_size;
283         volatile uint8_t *bios = flash->virtual_memory;
284
285         erase_chip_jedec(flash);
286         // dumb check if erase was successful.
287         for (i = 0; i < total_size; i++) {
288                 if (bios[i] != (uint8_t) 0xff) {
289                         printf("ERASE FAILED\n");
290                         return -1;
291                 }
292         }
293
294         printf("Programming Page: ");
295         for (i = 0; i < total_size / page_size; i++) {
296                 printf("%04d at address: 0x%08x", i, i * page_size);
297                 write_page_write_jedec(bios, buf + i * page_size,
298                                        bios + i * page_size, page_size);
299                 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
300         }
301         printf("\n");
302         protect_jedec(bios);
303
304         return 0;
305 }