Cosmetic fixes (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
32 #define AUTO_PG_ERASE1          0x20
33 #define AUTO_PG_ERASE2          0xD0
34 #define AUTO_PGRM               0x10
35 #define CHIP_ERASE              0x30
36 #define RESET                   0xFF
37 #define READ_ID                 0x90
38
39 static __inline__ void protect_28sf040(volatile uint8_t *bios)
40 {
41         /* ask compiler not to optimize this */
42         volatile uint8_t tmp;
43
44         tmp = *(volatile uint8_t *)(bios + 0x1823);
45         tmp = *(volatile uint8_t *)(bios + 0x1820);
46         tmp = *(volatile uint8_t *)(bios + 0x1822);
47         tmp = *(volatile uint8_t *)(bios + 0x0418);
48         tmp = *(volatile uint8_t *)(bios + 0x041B);
49         tmp = *(volatile uint8_t *)(bios + 0x0419);
50         tmp = *(volatile uint8_t *)(bios + 0x040A);
51 }
52
53 static __inline__ void unprotect_28sf040(volatile uint8_t *bios)
54 {
55         /* ask compiler not to optimize this */
56         volatile uint8_t tmp;
57
58         tmp = *(volatile uint8_t *)(bios + 0x1823);
59         tmp = *(volatile uint8_t *)(bios + 0x1820);
60         tmp = *(volatile uint8_t *)(bios + 0x1822);
61         tmp = *(volatile uint8_t *)(bios + 0x0418);
62         tmp = *(volatile uint8_t *)(bios + 0x041B);
63         tmp = *(volatile uint8_t *)(bios + 0x0419);
64         tmp = *(volatile uint8_t *)(bios + 0x041A);
65 }
66
67 static __inline__ int erase_sector_28sf040(volatile uint8_t *bios,
68                                            unsigned long address)
69 {
70         *bios = AUTO_PG_ERASE1;
71         *(bios + address) = AUTO_PG_ERASE2;
72
73         /* wait for Toggle bit ready         */
74         toggle_ready_jedec(bios);
75
76         return 0;
77 }
78
79 static __inline__ int write_sector_28sf040(volatile uint8_t *bios,
80                                            uint8_t *src,
81                                            volatile uint8_t *dst,
82                                            unsigned int page_size)
83 {
84         int i;
85
86         for (i = 0; i < page_size; i++) {
87                 /* transfer data from source to destination */
88                 if (*src == 0xFF) {
89                         dst++, src++;
90                         /* If the data is 0xFF, don't program it */
91                         continue;
92                 }
93                 /*issue AUTO PROGRAM command */
94                 *dst = AUTO_PGRM;
95                 *dst++ = *src++;
96
97                 /* wait for Toggle bit ready */
98                 toggle_ready_jedec(bios);
99         }
100
101         return 0;
102 }
103
104 int probe_28sf040(struct flashchip *flash)
105 {
106         volatile uint8_t *bios = flash->virtual_memory;
107         uint8_t id1, id2;
108
109         *bios = RESET;
110         myusec_delay(10);
111
112         *bios = READ_ID;
113         myusec_delay(10);
114         id1 = *(volatile uint8_t *)bios;
115         myusec_delay(10);
116         id2 = *(volatile uint8_t *)(bios + 0x01);
117
118         *bios = RESET;
119         myusec_delay(10);
120
121         printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
122         if (id1 == flash->manufacture_id && id2 == flash->model_id)
123                 return 1;
124
125         return 0;
126 }
127
128 int erase_28sf040(struct flashchip *flash)
129 {
130         volatile uint8_t *bios = flash->virtual_memory;
131
132         unprotect_28sf040(bios);
133         *bios = CHIP_ERASE;
134         *bios = CHIP_ERASE;
135         protect_28sf040(bios);
136
137         myusec_delay(10);
138         toggle_ready_jedec(bios);
139
140         return 0;
141 }
142
143 int write_28sf040(struct flashchip *flash, uint8_t *buf)
144 {
145         int i;
146         int total_size = flash->total_size * 1024;
147         int page_size = flash->page_size;
148         volatile uint8_t *bios = flash->virtual_memory;
149
150         unprotect_28sf040(bios);
151
152         printf("Programming Page: ");
153         for (i = 0; i < total_size / page_size; i++) {
154                 /* erase the page before programming */
155                 erase_sector_28sf040(bios, i * page_size);
156
157                 /* write to the sector */
158                 printf("%04d at address: 0x%08x", i, i * page_size);
159                 write_sector_28sf040(bios, buf + i * page_size,
160                                      bios + i * page_size, page_size);
161                 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");
162         }
163         printf("\n");
164
165         protect_28sf040(bios);
166
167         return 0;
168 }