big cosmetic offensive on flashrom. (trivial)
[coreboot.git] / util / flashrom / sst28sf040.c
1 /*
2  * sst28sf040.c: driver for SST28SF040C flash models.
3  *
4  *
5  * Copyright 2000 Silicon Integrated System Corporation
6  * Copyright 2005 coresystems GmbH <stepan@openbios.org>
7  *
8  *      This program is free software; you can redistribute it and/or modify
9  *      it under the terms of the GNU General Public License as published by
10  *      the Free Software Foundation; either version 2 of the License, or
11  *      (at your option) any later version.
12  *
13  *      This program is distributed in the hope that it will be useful,
14  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *      GNU General Public License for more details.
17  *
18  *      You should have received a copy of the GNU General Public License
19  *      along with this program; if not, write to the Free Software
20  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  *
23  * Reference:
24  *      4 MEgabit (512K x 8) SuperFlash EEPROM, SST28SF040 data sheet
25  *
26  */
27
28 #include <stdio.h>
29 #include <stdint.h>
30 #include "flash.h"
31 #include "jedec.h"
32 #include "debug.h"
33
34 #define AUTO_PG_ERASE1          0x20
35 #define AUTO_PG_ERASE2          0xD0
36 #define AUTO_PGRM               0x10
37 #define CHIP_ERASE              0x30
38 #define RESET                   0xFF
39 #define READ_ID                 0x90
40
41 static __inline__ void protect_28sf040(volatile uint8_t *bios)
42 {
43         /* ask compiler not to optimize this */
44         volatile uint8_t tmp;
45
46         tmp = *(volatile uint8_t *)(bios + 0x1823);
47         tmp = *(volatile uint8_t *)(bios + 0x1820);
48         tmp = *(volatile uint8_t *)(bios + 0x1822);
49         tmp = *(volatile uint8_t *)(bios + 0x0418);
50         tmp = *(volatile uint8_t *)(bios + 0x041B);
51         tmp = *(volatile uint8_t *)(bios + 0x0419);
52         tmp = *(volatile uint8_t *)(bios + 0x040A);
53 }
54
55 static __inline__ void unprotect_28sf040(volatile uint8_t *bios)
56 {
57         /* ask compiler not to optimize this */
58         volatile uint8_t tmp;
59
60         tmp = *(volatile uint8_t *)(bios + 0x1823);
61         tmp = *(volatile uint8_t *)(bios + 0x1820);
62         tmp = *(volatile uint8_t *)(bios + 0x1822);
63         tmp = *(volatile uint8_t *)(bios + 0x0418);
64         tmp = *(volatile uint8_t *)(bios + 0x041B);
65         tmp = *(volatile uint8_t *)(bios + 0x0419);
66         tmp = *(volatile uint8_t *)(bios + 0x041A);
67 }
68
69 static __inline__ int erase_sector_28sf040(volatile uint8_t *bios,
70                                            unsigned long address)
71 {
72         *bios = AUTO_PG_ERASE1;
73         *(bios + address) = AUTO_PG_ERASE2;
74
75         /* wait for Toggle bit ready         */
76         toggle_ready_jedec(bios);
77
78         return (0);
79 }
80
81 static __inline__ int write_sector_28sf040(volatile uint8_t *bios,
82                                            uint8_t *src,
83                                            volatile uint8_t *dst,
84                                            unsigned int page_size)
85 {
86         int i;
87
88         for (i = 0; i < page_size; i++) {
89                 /* transfer data from source to destination */
90                 if (*src == 0xFF) {
91                         dst++, src++;
92                         /* If the data is 0xFF, don't program it */
93                         continue;
94                 }
95                 /*issue AUTO PROGRAM command */
96                 *dst = AUTO_PGRM;
97                 *dst++ = *src++;
98
99                 /* wait for Toggle bit ready */
100                 toggle_ready_jedec(bios);
101         }
102
103         return (0);
104 }
105
106 int probe_28sf040(struct flashchip *flash)
107 {
108         volatile uint8_t *bios = flash->virtual_memory;
109         uint8_t id1, id2, tmp;
110
111         /* save the value at the beginning of the Flash */
112         tmp = *bios;
113
114         *bios = RESET;
115         myusec_delay(10);
116
117         *bios = READ_ID;
118         myusec_delay(10);
119         id1 = *(volatile uint8_t *)bios;
120         myusec_delay(10);
121         id2 = *(volatile uint8_t *)(bios + 0x01);
122
123         *bios = RESET;
124         myusec_delay(10);
125
126         printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
127         if (id1 == flash->manufacture_id && id2 == flash->model_id)
128                 return 1;
129
130         /* if there is no SST28SF040, restore the original value */
131         *bios = tmp;
132         return 0;
133 }
134
135 int erase_28sf040(struct flashchip *flash)
136 {
137         volatile uint8_t *bios = flash->virtual_memory;
138
139         unprotect_28sf040(bios);
140         *bios = CHIP_ERASE;
141         *bios = CHIP_ERASE;
142         protect_28sf040(bios);
143
144         myusec_delay(10);
145         toggle_ready_jedec(bios);
146
147         return (0);
148 }
149
150 int write_28sf040(struct flashchip *flash, uint8_t *buf)
151 {
152         int i;
153         int total_size = flash->total_size * 1024;
154         int page_size = flash->page_size;
155         volatile uint8_t *bios = flash->virtual_memory;
156
157         unprotect_28sf040(bios);
158
159         printf("Programming Page: ");
160         for (i = 0; i < total_size / page_size; i++) {
161                 /* erase the page before programming */
162                 erase_sector_28sf040(bios, i * page_size);
163
164                 /* write to the sector */
165                 printf("%04d at address: 0x%08x", i, i * page_size);
166                 write_sector_28sf040(bios, buf + i * page_size,
167                                      bios + i * page_size, page_size);
168                 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");
169         }
170         printf("\n");
171
172         protect_28sf040(bios);
173
174         return (0);
175 }