1 /*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2000 Silicon Integrated System Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17 /*
18 * Datasheet:
19 * - Name: Intel 82802AB/82802AC Firmware Hub (FWH)
20 * - URL: http://www.intel.com/design/chipsets/datashts/290658.htm
21 * - PDF: http://download.intel.com/design/chipsets/datashts/29065804.pdf
22 * - Order number: 290658-004
23 */
24
25 #include "flash.h"
26 #include "chipdrivers.h"
27
print_status_82802ab(uint8_t status)28 void print_status_82802ab(uint8_t status)
29 {
30 msg_cdbg("%s", status & 0x80 ? "Ready:" : "Busy:");
31 msg_cdbg("%s", status & 0x40 ? "BE SUSPEND:" : "BE RUN/FINISH:");
32 msg_cdbg("%s", status & 0x20 ? "BE ERROR:" : "BE OK:");
33 msg_cdbg("%s", status & 0x10 ? "PROG ERR:" : "PROG OK:");
34 msg_cdbg("%s", status & 0x8 ? "VP ERR:" : "VPP OK:");
35 msg_cdbg("%s", status & 0x4 ? "PROG SUSPEND:" : "PROG RUN/FINISH:");
36 msg_cdbg("%s", status & 0x2 ? "WP|TBL#|WP#,ABORT:" : "UNLOCK:");
37 }
38
probe_82802ab(struct flashctx * flash)39 int probe_82802ab(struct flashctx *flash)
40 {
41 chipaddr bios = flash->virtual_memory;
42 uint8_t id1, id2, flashcontent1, flashcontent2;
43 int shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED) ? 1 : 0;
44
45 /* Reset to get a clean state */
46 chip_writeb(flash, 0xFF, bios);
47 programmer_delay(10);
48
49 /* Enter ID mode */
50 chip_writeb(flash, 0x90, bios);
51 programmer_delay(10);
52
53 id1 = chip_readb(flash, bios + (0x00 << shifted));
54 id2 = chip_readb(flash, bios + (0x01 << shifted));
55
56 /* Leave ID mode */
57 chip_writeb(flash, 0xFF, bios);
58
59 programmer_delay(10);
60
61 msg_cdbg("%s: id1 0x%02x, id2 0x%02x", __func__, id1, id2);
62
63 if (!oddparity(id1))
64 msg_cdbg(", id1 parity violation");
65
66 /*
67 * Read the product ID location again. We should now see normal
68 * flash contents.
69 */
70 flashcontent1 = chip_readb(flash, bios + (0x00 << shifted));
71 flashcontent2 = chip_readb(flash, bios + (0x01 << shifted));
72
73 if (id1 == flashcontent1)
74 msg_cdbg(", id1 is normal flash content");
75 if (id2 == flashcontent2)
76 msg_cdbg(", id2 is normal flash content");
77
78 msg_cdbg("\n");
79 if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id)
80 return 0;
81
82 return 1;
83 }
84
85 /* FIXME: needs timeout */
wait_82802ab(struct flashctx * flash)86 uint8_t wait_82802ab(struct flashctx *flash)
87 {
88 uint8_t status;
89 chipaddr bios = flash->virtual_memory;
90
91 chip_writeb(flash, 0x70, bios);
92 if ((chip_readb(flash, bios) & 0x80) == 0) { // it's busy
93 while ((chip_readb(flash, bios) & 0x80) == 0) ;
94 }
95
96 status = chip_readb(flash, bios);
97
98 /* Reset to get a clean state */
99 chip_writeb(flash, 0xFF, bios);
100
101 return status;
102 }
103
erase_block_82802ab(struct flashctx * flash,unsigned int page,unsigned int pagesize)104 int erase_block_82802ab(struct flashctx *flash, unsigned int page,
105 unsigned int pagesize)
106 {
107 chipaddr bios = flash->virtual_memory;
108 uint8_t status;
109
110 // clear status register
111 chip_writeb(flash, 0x50, bios + page);
112
113 // now start it
114 chip_writeb(flash, 0x20, bios + page);
115 chip_writeb(flash, 0xd0, bios + page);
116 programmer_delay(10);
117
118 // now let's see what the register is
119 status = wait_82802ab(flash);
120 print_status_82802ab(status);
121
122 /* FIXME: Check the status register for errors. */
123 return 0;
124 }
125
126 /* chunksize is 1 */
write_82802ab(struct flashctx * flash,const uint8_t * src,unsigned int start,unsigned int len)127 int write_82802ab(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int len)
128 {
129 unsigned int i;
130 chipaddr dst = flash->virtual_memory + start;
131
132 for (i = 0; i < len; i++) {
133 /* transfer data from source to destination */
134 chip_writeb(flash, 0x40, dst);
135 chip_writeb(flash, *src++, dst++);
136 wait_82802ab(flash);
137 }
138
139 /* FIXME: Ignore errors for now. */
140 return 0;
141 }
142
unlock_28f004s5(struct flashctx * flash)143 int unlock_28f004s5(struct flashctx *flash)
144 {
145 chipaddr bios = flash->virtual_memory;
146 uint8_t mcfg, bcfg, need_unlock = 0, can_unlock = 0;
147 unsigned int i;
148
149 /* Clear status register */
150 chip_writeb(flash, 0x50, bios);
151
152 /* Read identifier codes */
153 chip_writeb(flash, 0x90, bios);
154
155 /* Read master lock-bit */
156 mcfg = chip_readb(flash, bios + 0x3);
157 msg_cdbg("master lock is ");
158 if (mcfg) {
159 msg_cdbg("locked!\n");
160 } else {
161 msg_cdbg("unlocked!\n");
162 can_unlock = 1;
163 }
164
165 /* Read block lock-bits */
166 for (i = 0; i < flash->chip->total_size * 1024; i+= (64 * 1024)) {
167 bcfg = chip_readb(flash, bios + i + 2); // read block lock config
168 msg_cdbg("block lock at %06x is %slocked!\n", i, bcfg ? "" : "un");
169 if (bcfg) {
170 need_unlock = 1;
171 }
172 }
173
174 /* Reset chip */
175 chip_writeb(flash, 0xFF, bios);
176
177 /* Unlock: clear block lock-bits, if needed */
178 if (can_unlock && need_unlock) {
179 msg_cdbg("Unlock: ");
180 chip_writeb(flash, 0x60, bios);
181 chip_writeb(flash, 0xD0, bios);
182 chip_writeb(flash, 0xFF, bios);
183 msg_cdbg("Done!\n");
184 }
185
186 /* Error: master locked or a block is locked */
187 if (!can_unlock && need_unlock) {
188 msg_cerr("At least one block is locked and lockdown is active!\n");
189 return -1;
190 }
191
192 return 0;
193 }
194
unlock_lh28f008bjt(struct flashctx * flash)195 int unlock_lh28f008bjt(struct flashctx *flash)
196 {
197 chipaddr bios = flash->virtual_memory;
198 uint8_t mcfg, bcfg;
199 uint8_t need_unlock = 0, can_unlock = 0;
200 unsigned int i;
201
202 /* Wait if chip is busy */
203 wait_82802ab(flash);
204
205 /* Read identifier codes */
206 chip_writeb(flash, 0x90, bios);
207
208 /* Read master lock-bit */
209 mcfg = chip_readb(flash, bios + 0x3);
210 msg_cdbg("master lock is ");
211 if (mcfg) {
212 msg_cdbg("locked!\n");
213 } else {
214 msg_cdbg("unlocked!\n");
215 can_unlock = 1;
216 }
217
218 /* Read block lock-bits, 8 * 8 KB + 15 * 64 KB */
219 for (i = 0; i < flash->chip->total_size * 1024;
220 i += (i >= (64 * 1024) ? 64 * 1024 : 8 * 1024)) {
221 bcfg = chip_readb(flash, bios + i + 2); /* read block lock config */
222 msg_cdbg("block lock at %06x is %slocked!\n", i,
223 bcfg ? "" : "un");
224 if (bcfg)
225 need_unlock = 1;
226 }
227
228 /* Reset chip */
229 chip_writeb(flash, 0xFF, bios);
230
231 /* Unlock: clear block lock-bits, if needed */
232 if (can_unlock && need_unlock) {
233 msg_cdbg("Unlock: ");
234 chip_writeb(flash, 0x60, bios);
235 chip_writeb(flash, 0xD0, bios);
236 chip_writeb(flash, 0xFF, bios);
237 wait_82802ab(flash);
238 msg_cdbg("Done!\n");
239 }
240
241 /* Error: master locked or a block is locked */
242 if (!can_unlock && need_unlock) {
243 msg_cerr("At least one block is locked and lockdown is active!\n");
244 return -1;
245 }
246
247 return 0;
248 }
249