blob: 79967972b94150bf8d8b5a5579bee5fdbd031fee [file] [log] [blame]
Dominik Geyerb46acba2008-05-16 12:55:55 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2008 Stefan Wildemann <stefan.wildemann@kontron.com>
5 * Copyright (C) 2008 Claus Gindhart <claus.gindhart@kontron.com>
6 * Copyright (C) 2008 Dominik Geyer <dominik.geyer@kontron.com>
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24/*
25 * This module is designed for supporting the devices
26 * ST M25P40
27 * ST M25P80
28 * ST M25P16
29 * ST M25P32 already tested
30 * ST M25P64
31 * AT 25DF321 already tested
32 *
33 */
34
35#include <stdio.h>
36#include <string.h>
37#include <stdint.h>
38#include <sys/mman.h>
39#include <pci/pci.h>
40#include "flash.h"
41#include "spi.h"
42
43#define MAXDATABYTES 0x40
44
45/*ICH9 controller register definition*/
46#define REG_FADDR 0x08 /* 32 Bits */
47#define REG_FDATA0 0x10 /* 64 Bytes */
48#define REG_SSFS 0x90 /* 08 Bits */
49#define SSFS_SCIP 0x00000001
50#define SSFS_CDS 0x00000004
51#define SSFS_FCERR 0x00000008
52#define SSFS_AEL 0x00000010
53#define REG_SSFC 0x91 /* 24 Bits */
54#define SSFC_SCGO 0x00000200
55#define SSFC_ACS 0x00000400
56#define SSFC_SPOP 0x00000800
57#define SSFC_COP 0x00001000
58#define SSFC_DBC 0x00010000
59#define SSFC_DS 0x00400000
60#define SSFC_SME 0x00800000
61#define SSFC_SCF 0x01000000
62#define SSFC_SCF_20MHZ 0x00000000
63#define SSFC_SCF_33MHZ 0x01000000
64#define REG_PREOP 0x94 /* 16 Bits */
65#define REG_OPTYPE 0x96 /* 16 Bits */
66#define REG_OPMENU 0x98 /* 64 BITS */
67
68// ICH9R SPI commands
69#define SPI_OPCODE_TYPE_READ_NO_ADDRESS 0
70#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS 1
71#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS 2
72#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS 3
73
74
75typedef struct _OPCODE {
76 uint8_t opcode; //This commands spi opcode
77 uint8_t spi_type; //This commands spi type
78 uint8_t atomic; //Use preop: (0: none, 1: preop0, 2: preop1
79} OPCODE;
80
81/* Opcode definition:
82 * Preop 1: Write Enable
83 * Preop 2: Write Status register enable
84 *
85 * OP 0: Write address
86 * OP 1: Read Address
87 * OP 2: ERASE block
88 * OP 3: Read Status register
89 * OP 4: Read ID
90 * OP 5: Write Status register
91 * OP 6: chip private (read JDEC id)
92 * OP 7: Chip erase
93 */
94typedef struct _OPCODES {
95 uint8_t preop[2];
96 OPCODE opcode[8];
97} OPCODES;
98
99
100static OPCODES *curopcodes=NULL;
101
102
103/* HW access functions */
104static inline uint32_t REGREAD32(int X)
105{
106 volatile uint32_t regval;
107 regval = *(volatile uint32_t *)((uint8_t *)ich_spibar + X);
108 return regval;
109}
110
111#define REGWRITE32(X,Y) (*(uint32_t *)((uint8_t *)ich_spibar+X)=Y)
112#define REGWRITE16(X,Y) (*(uint16_t *)((uint8_t *)ich_spibar+X)=Y)
113#define REGWRITE8(X,Y) (*(uint8_t *)((uint8_t *)ich_spibar+X)=Y)
114
115
116/* Common SPI functions */
117static int program_opcodes(OPCODES * op);
118static int run_opcode(uint8_t nr, OPCODE op, uint32_t offset, uint8_t datalength, uint8_t * data);
119static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int Offset);
120static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes, int Offset);
121static int ich_spi_erase_block(struct flashchip *flash, int offset);
122
123
124OPCODES O_ST_M25P = {
125 {
126 JEDEC_WREN,
127 0
128 },
129 {
130 {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 1}, // Write Byte
131 {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data
132 {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 1}, // Erase Sector
133 {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg
134 {JEDEC_RES, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Resume Deep Power-Down
135 {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 1}, // Write Status Register
136 {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID
137 {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 1}, // Bulk erase
138 }
139};
140
141
142int program_opcodes(OPCODES * op)
143{
144 uint8_t a;
145 uint16_t temp16;
146 uint32_t temp32;
147
148 /* Program Prefix Opcodes */
149 temp16 = 0;
150 /* 0:7 Prefix Opcode 1 */
151 temp16 = (op->preop[0]);
152 /* 8:16 Prefix Opcode 2 */
153 temp16 |= ((uint16_t) op->preop[1]) << 8;
154 REGWRITE16(REG_PREOP, temp16);
155
156 /*Program Opcode Types 0 - 7 */
157 temp16 = 0;
158 for (a = 0; a < 8; a++) {
159 temp16 |= ((uint16_t) op->opcode[a].spi_type) << (a * 2);
160 }
161 REGWRITE16(REG_OPTYPE, temp16);
162
163 /*Program Allowable Opcodes 0 - 3 */
164 temp32 = 0;
165 for (a = 0; a < 4; a++) {
166 temp32 |= ((uint32_t) op->opcode[a].opcode) << (a * 8);
167 }
168 REGWRITE32(REG_OPMENU, temp32);
169
170 /*Program Allowable Opcodes 4 - 7 */
171 temp32 = 0;
172 for (a = 4; a < 8; a++) {
173 temp32 |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);
174 }
175 REGWRITE32(REG_OPMENU + 4, temp32);
176
177 return 0;
178}
179
180int run_opcode(uint8_t nr, OPCODE op, uint32_t offset, uint8_t datalength,
181 uint8_t * data)
182{
183 int write_cmd = 0;
184 uint32_t temp32;
185 uint32_t a;
186
187 /* Is it a write command? */
188 if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
189 || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
190 write_cmd = 1;
191 }
192
193 /* Programm Offset in Flash into FADDR */
194 REGWRITE32(REG_FADDR, (offset & 0x00FFFFFF)); /*SPI addresses are 24 BIT only */
195
196 /* Program data into FDATA0 to N */
197 if (write_cmd && (datalength != 0)) {
198 temp32 = 0;
199 for (a = 0; a < datalength; a++) {
200 if ((a % 4) == 0) {
201 temp32 = 0;
202 }
203
204 temp32 |= ((uint32_t) data[a]) << ((a % 4) * 8);
205
206 if ((a % 4) == 3) {
207 REGWRITE32(REG_FDATA0 + (a - (a % 4)), temp32);
208 }
209 }
210 if (((a - 1) % 4) != 3) {
211 REGWRITE32(REG_FDATA0 + ((a - 1) - ((a - 1) % 4)),
212 temp32);
213 }
214
215 }
216
217 /* Assemble SSFS + SSFC */
218 temp32 = 0;
219
220 /* clear error status registers */
221 temp32 |= (SSFS_CDS + SSFS_FCERR);
222 /* USE 20 MhZ */
223 temp32 |= SSFC_SCF_20MHZ;
224
225 if (datalength != 0) {
226 uint32_t datatemp;
227 temp32 |= SSFC_DS;
228 datatemp = ((uint32_t) ((datalength - 1) & 0x3f)) << (8 + 8);
229 temp32 |= datatemp;
230 }
231
232 /* Select opcode */
233 temp32 |= ((uint32_t) (nr & 0x07)) << (8 + 4);
234
235 /* Handle Atomic */
236 if (op.atomic != 0) {
237 /* Select atomic command */
238 temp32 |= SSFC_ACS;
239 /* Selct prefix opcode */
240 if ((op.atomic - 1) == 1) {
241 /*Select prefix opcode 2 */
242 temp32 |= SSFC_SPOP;
243 }
244 }
245
246 /* Start */
247 temp32 |= SSFC_SCGO;
248
249 /* write it */
250 REGWRITE32(REG_SSFS, temp32);
251
252 /*wait for cycle complete */
253 while ((REGREAD32(REG_SSFS) & SSFS_CDS) == 0) {
254 /*TODO; Do something that this can't lead into an endless loop. but some
255 * commands may cause this to be last more than 30 seconds */
256 }
257
258 if ((REGREAD32(REG_SSFS) & SSFS_FCERR) != 0) {
259 printf_debug("Transaction error!\n");
260 return 1;
261 }
262
263 if ((!write_cmd) && (datalength != 0)) {
264 for (a = 0; a < datalength; a++) {
265 if ((a % 4) == 0) {
266 temp32 = REGREAD32(REG_FDATA0 + (a));
267 }
268
269 data[a] =
270 (temp32 & (((uint32_t) 0xff) << ((a % 4) * 8))) >>
271 ((a % 4) * 8);
272 }
273 }
274
275 return 0;
276}
277
278
279static int ich_spi_erase_block(struct flashchip *flash, int offset)
280{
281 printf_debug("Spi_Erase,Offset=%d,sectors=%d\n", offset, 1);
282
283 if (run_opcode(2, curopcodes->opcode[2], offset, 0, NULL) != 0) {
284 printf_debug("Error erasing sector at 0x%x", offset);
285 return -1;
286 }
287
288 printf("DONE BLOCK 0x%x\n", offset);
289
290 return 0;
291}
292
293static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int Offset)
294{
295 int page_size = flash->page_size;
296 uint32_t remaining = flash->page_size;
297 int a;
298
299 printf_debug("Spi_Read,Offset=%d,number=%d,buf=%p\n", Offset, page_size, buf);
300
301 for (a = 0; a < page_size; a += MAXDATABYTES) {
302 if (remaining < MAXDATABYTES) {
303
304 if (run_opcode
305 (1, curopcodes->opcode[1],
306 Offset + (page_size - remaining), remaining,
307 &buf[page_size - remaining]) != 0) {
308 printf_debug("Error reading");
309 return 1;
310 }
311 remaining = 0;
312 } else {
313 if (run_opcode
314 (1, curopcodes->opcode[1],
315 Offset + (page_size - remaining), MAXDATABYTES,
316 &buf[page_size - remaining]) != 0) {
317 printf_debug("Error reading");
318 return 1;
319 }
320 remaining -= MAXDATABYTES;
321 }
322 }
323
324 return 0;
325}
326
327static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
328 int Offset)
329{
330 int page_size = flash->page_size;
331 uint32_t remaining = page_size;
332 int a;
333
334 printf_debug("write_page_ichspi,Offset=%d,number=%d,buf=%p\n", Offset, page_size,
335 bytes);
336
337 for (a = 0; a < page_size; a += MAXDATABYTES) {
338 if (remaining < MAXDATABYTES) {
339 if (run_opcode
340 (0, curopcodes->opcode[0],
341 Offset + (page_size - remaining), remaining,
342 &bytes[page_size - remaining]) != 0) {
343 printf_debug("Error writing");
344 return 1;
345 }
346 remaining = 0;
347 } else {
348 if (run_opcode
349 (0, curopcodes->opcode[0],
350 Offset + (page_size - remaining), MAXDATABYTES,
351 &bytes[page_size - remaining]) != 0) {
352 printf_debug("Error writing");
353 return 1;
354 }
355 remaining -= MAXDATABYTES;
356 }
357 }
358
359 return 0;
360}
361
362
363int ich_spi_read(struct flashchip *flash, uint8_t * buf)
364{
365 int i, rc = 0;
366 int total_size = flash->total_size * 1024;
367 int page_size = flash->page_size;
368
369 for (i = 0; (i < total_size / page_size) && (rc == 0); i++) {
370 rc = ich_spi_read_page(flash, (void *)(buf + i * page_size),
371 i * page_size);
372 }
373
374 return rc;
375}
376
377
378int ich_spi_write(struct flashchip *flash, uint8_t * buf)
379{
380 int i, j, rc = 0;
381 int total_size = flash->total_size * 1024;
382 int page_size = flash->page_size;
383 int erase_size = 64 * 1024;
384
385 spi_disable_blockprotect();
386
387 printf("Programming page: \n");
388
389 for (i = 0; i < total_size / erase_size; i++) {
390 rc = ich_spi_erase_block(flash, i * erase_size);
391 if (rc) {
392 printf("Error erasing block at 0x%x\n", i);
393 break;
394 }
395
396 for (j = 0; j < erase_size / page_size; j++) {
397 ich_spi_write_page(flash, (void *)(buf + (i * erase_size) + (j * page_size)),
398 (i * erase_size) + (j * page_size));
399 }
400 }
401
402 printf("\n");
403
404 return rc;
405}
406
407int ich_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr)
408{
409 int a;
410 int opcode_index = -1;
411 const unsigned char cmd = *writearr;
412 OPCODE *opcode;
413 uint32_t addr = 0;
414 uint8_t *data;
415 int count;
416
417 /* program opcodes if not already done */
418 if (curopcodes == NULL) {
419 printf_debug("Programming OPCODES\n");
420 curopcodes=&O_ST_M25P;
421 program_opcodes(curopcodes);
422 }
423
424 /* find cmd in opcodes-table */
425 for (a = 0; a < 8; a++) {
426 if ((curopcodes->opcode[a]).opcode == cmd) {
427 opcode_index = a;
428 break;
429 }
430 }
431
432 /* unknown / not programmed command */
433 if (opcode_index == -1) {
434 printf_debug("Invalid OPCODE 0x%02x\n", cmd);
435 return 1;
436 }
437
438 opcode = &(curopcodes->opcode[opcode_index]);
439
440 /* if opcode-type requires an address */
441 if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS ||
442 opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
443 addr = (writearr[1]<<16) |
444 (writearr[2]<<8) |
445 (writearr[3]<<0);
446 }
447
448 /* translate read/write array/count */
449 if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) {
450 data = (uint8_t*)(writearr+1);
451 count = writecnt-1;
452 }
453 else if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
454 data = (uint8_t*)(writearr+4);
455 count = writecnt-4;
456 }
457 else {
458 data = (uint8_t*)readarr;
459 count = readcnt;
460 }
461
462 if (run_opcode(opcode_index, *opcode, addr, count, data) != 0) {
463 printf_debug("run OPCODE 0x%02x failed\n", opcode->opcode);
464 return 1;
465 }
466
467 return 0;
468}