b60bc0e767230d6649eed97a4509e3361a25e60e
[coreboot.git] / util / flashrom / ichspi.c
1 /*
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  * Copyright (C) 2008 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
22  *
23  */
24
25 /*
26  * This module is designed for supporting the devices
27  * ST M25P40
28  * ST M25P80
29  * ST M25P16
30  * ST M25P32 already tested
31  * ST M25P64
32  * AT 25DF321 already tested
33  *
34  */
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdint.h>
39 #include <sys/mman.h>
40 #include <pci/pci.h>
41 #include "flash.h"
42 #include "spi.h"
43
44 /* ICH9 controller register definition */
45 #define ICH9_REG_FADDR         0x08     /* 32 Bits */
46 #define ICH9_REG_FDATA0                0x10     /* 64 Bytes */
47
48 #define ICH9_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
54 #define ICH9_REG_SSFC          0x91     /* 24 Bits */
55 #define SSFC_SCGO               0x00000200
56 #define SSFC_ACS                0x00000400
57 #define SSFC_SPOP               0x00000800
58 #define SSFC_COP                0x00001000
59 #define SSFC_DBC                0x00010000
60 #define SSFC_DS                 0x00400000
61 #define SSFC_SME                0x00800000
62 #define SSFC_SCF                0x01000000
63 #define SSFC_SCF_20MHZ 0x00000000
64 #define SSFC_SCF_33MHZ 0x01000000
65
66 #define ICH9_REG_PREOP         0x94     /* 16 Bits */
67 #define ICH9_REG_OPTYPE                0x96     /* 16 Bits */
68 #define ICH9_REG_OPMENU                0x98     /* 64 Bits */
69
70 // ICH9R SPI commands
71 #define SPI_OPCODE_TYPE_READ_NO_ADDRESS     0
72 #define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS    1
73 #define SPI_OPCODE_TYPE_READ_WITH_ADDRESS   2
74 #define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS  3
75
76 // ICH7 registers
77 #define ICH7_REG_SPIS          0x00     /* 16 Bits */
78 #define SPIS_SCIP              0x00000001
79 #define SPIS_CDS               0x00000004
80 #define SPIS_FCERR             0x00000008
81
82 /* VIA SPI is compatible with ICH7, but maxdata
83    to transfer is 16 bytes.
84
85    DATA byte count on ICH7 is 8:13, on VIA 8:11
86
87    bit 12 is port select CS0 CS1
88    bit 13 is FAST READ enable
89    bit 7  is used with fast read and one shot controls CS de-assert?
90 */
91
92 #define ICH7_REG_SPIC          0x02     /* 16 Bits */
93 #define SPIC_SCGO              0x0002
94 #define SPIC_ACS               0x0004
95 #define SPIC_SPOP              0x0008
96 #define SPIC_DS                0x4000
97
98 #define ICH7_REG_SPIA          0x04     /* 32 Bits */
99 #define ICH7_REG_SPID0         0x08     /* 64 Bytes */
100 #define ICH7_REG_PREOP         0x54     /* 16 Bits */
101 #define ICH7_REG_OPTYPE                0x56     /* 16 Bits */
102 #define ICH7_REG_OPMENU                0x58     /* 64 Bits */
103
104 /* ICH SPI configuration lock-down. May be set during chipset enabling. */
105 int ichspi_lock = 0;
106
107 typedef struct _OPCODE {
108         uint8_t opcode;         //This commands spi opcode
109         uint8_t spi_type;       //This commands spi type
110         uint8_t atomic;         //Use preop: (0: none, 1: preop0, 2: preop1
111 } OPCODE;
112
113 /* Opcode definition:
114  * Preop 1: Write Enable
115  * Preop 2: Write Status register enable
116  *
117  * OP 0: Write address
118  * OP 1: Read Address
119  * OP 2: ERASE block
120  * OP 3: Read Status register
121  * OP 4: Read ID
122  * OP 5: Write Status register
123  * OP 6: chip private (read JDEC id)
124  * OP 7: Chip erase
125  */
126 typedef struct _OPCODES {
127         uint8_t preop[2];
128         OPCODE opcode[8];
129 } OPCODES;
130
131 static OPCODES *curopcodes = NULL;
132
133 /* HW access functions */
134 static inline uint32_t REGREAD32(int X)
135 {
136         volatile uint32_t regval;
137         regval = *(volatile uint32_t *)((uint8_t *) spibar + X);
138         return regval;
139 }
140
141 static inline uint16_t REGREAD16(int X)
142 {
143         volatile uint16_t regval;
144         regval = *(volatile uint16_t *)((uint8_t *) spibar + X);
145         return regval;
146 }
147
148 #define REGWRITE32(X,Y) (*(uint32_t *)((uint8_t *)spibar+X)=Y)
149 #define REGWRITE16(X,Y) (*(uint16_t *)((uint8_t *)spibar+X)=Y)
150 #define REGWRITE8(X,Y)  (*(uint8_t *)((uint8_t *)spibar+X)=Y)
151
152 /* Common SPI functions */
153 static inline int find_opcode(OPCODES *op, uint8_t opcode);
154 static inline int find_preop(OPCODES *op, uint8_t preop);
155 static int generate_opcodes(OPCODES * op);
156 static int program_opcodes(OPCODES * op);
157 static int run_opcode(OPCODE op, uint32_t offset,
158                       uint8_t datalength, uint8_t * data);
159 static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf,
160                              int offset, int maxdata);
161 static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
162                               int offset, int maxdata);
163
164 /* for pairing opcodes with their required preop */
165 struct preop_opcode_pair {
166         uint8_t preop;
167         uint8_t opcode;
168 };
169
170 struct preop_opcode_pair pops[] = {
171         {JEDEC_WREN, JEDEC_BYTE_PROGRAM},
172         {JEDEC_WREN, JEDEC_SE}, /* sector erase */
173         {JEDEC_WREN, JEDEC_BE_52}, /* block erase */
174         {JEDEC_WREN, JEDEC_BE_D8}, /* block erase */
175         {JEDEC_WREN, JEDEC_CE_60}, /* chip erase */
176         {JEDEC_WREN, JEDEC_CE_C7}, /* chip erase */
177         {JEDEC_EWSR, JEDEC_WRSR},
178         {0,}
179 };
180
181 OPCODES O_ST_M25P = {
182         {
183          JEDEC_WREN,
184          0},
185         {
186          {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 1},   // Write Byte
187          {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0},    // Read Data
188          {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 1},  // Erase Sector
189          {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0},      // Read Device Status Reg
190          {JEDEC_RES, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0},     // Resume Deep Power-Down
191          {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 1},     // Write Status Register
192          {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0},      // Read JDEC ID
193          {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 1},    // Bulk erase
194          }
195 };
196
197 OPCODES O_EXISTING = {};
198
199 static inline int find_opcode(OPCODES *op, uint8_t opcode)
200 {
201         int a;
202
203         for (a = 0; a < 8; a++) {
204                 if (op->opcode[a].opcode == opcode)
205                         return a;
206         }
207
208         return -1;
209 }
210
211 static inline int find_preop(OPCODES *op, uint8_t preop)
212 {
213         int a;
214
215         for (a = 0; a < 2; a++) {
216                 if (op->preop[a] == preop)
217                         return a;
218         }
219
220         return -1;
221 }
222
223 static int generate_opcodes(OPCODES * op)
224 {
225         int a, b, i;
226         uint16_t preop, optype;
227         uint32_t opmenu[2];
228
229         if (op == NULL) {
230                 printf_debug("\n%s: null OPCODES pointer!\n", __FUNCTION__);
231                 return -1;
232         }
233
234         switch (flashbus) {
235         case BUS_TYPE_ICH7_SPI:
236         case BUS_TYPE_VIA_SPI:
237                 preop = REGREAD16(ICH7_REG_PREOP);
238                 optype = REGREAD16(ICH7_REG_OPTYPE);
239                 opmenu[0] = REGREAD32(ICH7_REG_OPMENU);
240                 opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4);
241                 break;
242         case BUS_TYPE_ICH9_SPI:
243                 preop = REGREAD16(ICH9_REG_PREOP);
244                 optype = REGREAD16(ICH9_REG_OPTYPE);
245                 opmenu[0] = REGREAD32(ICH9_REG_OPMENU);
246                 opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4);
247                 break;
248         default:
249                 printf_debug("%s: unsupported chipset\n", __FUNCTION__);
250                 return -1;
251         }
252
253         op->preop[0] = (uint8_t) preop;
254         op->preop[1] = (uint8_t) (preop >> 8);
255
256         for (a = 0; a < 8; a++) {
257                 op->opcode[a].spi_type = (uint8_t) (optype & 0x3);
258                 optype >>= 2;
259         }
260
261         for (a = 0; a < 4; a++) {
262                 op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff);
263                 opmenu[0] >>= 8;
264         }
265
266         for (a = 4; a < 8; a++) {
267                 op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff);
268                 opmenu[1] >>= 8;
269         }
270
271         /* atomic (link opcode with required pre-op) */
272         for (a = 4; a < 8; a++)
273                 op->opcode[a].atomic = 0;
274
275         for (i = 0; pops[i].opcode; i++) {
276                 a = find_opcode(op, pops[i].opcode);
277                 b = find_preop(op, pops[i].preop);
278                 if ((a != -1) && (b != -1))
279                         op->opcode[a].atomic = (uint8_t) ++b;
280         }
281
282         return 0;
283 }
284
285 int program_opcodes(OPCODES * op)
286 {
287         uint8_t a;
288         uint16_t preop, optype;
289         uint32_t opmenu[2];
290
291         /* Program Prefix Opcodes */
292         preop = 0;
293         /* 0:7 Prefix Opcode 1 */
294         preop = (op->preop[0]);
295         /* 8:16 Prefix Opcode 2 */
296         preop |= ((uint16_t) op->preop[1]) << 8;
297
298         /* Program Opcode Types 0 - 7 */
299         optype = 0;
300         for (a = 0; a < 8; a++) {
301                 optype |= ((uint16_t) op->opcode[a].spi_type) << (a * 2);
302         }
303
304         /* Program Allowable Opcodes 0 - 3 */
305         opmenu[0] = 0;
306         for (a = 0; a < 4; a++) {
307                 opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8);
308         }
309
310         /*Program Allowable Opcodes 4 - 7 */
311         opmenu[1] = 0;
312         for (a = 4; a < 8; a++) {
313                 opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);
314         }
315
316         switch (flashbus) {
317         case BUS_TYPE_ICH7_SPI:
318         case BUS_TYPE_VIA_SPI:
319                 REGWRITE16(ICH7_REG_PREOP, preop);
320                 REGWRITE16(ICH7_REG_OPTYPE, optype);
321                 REGWRITE32(ICH7_REG_OPMENU, opmenu[0]);
322                 REGWRITE32(ICH7_REG_OPMENU + 4, opmenu[1]);
323                 break;
324         case BUS_TYPE_ICH9_SPI:
325                 REGWRITE16(ICH9_REG_PREOP, preop);
326                 REGWRITE16(ICH9_REG_OPTYPE, optype);
327                 REGWRITE32(ICH9_REG_OPMENU, opmenu[0]);
328                 REGWRITE32(ICH9_REG_OPMENU + 4, opmenu[1]);
329                 break;
330         default:
331                 printf_debug("%s: unsupported chipset\n", __FUNCTION__);
332                 return -1;
333         }
334
335         return 0;
336 }
337
338 /* This function generates OPCODES from or programs OPCODES to ICH according to
339  * the chipset's SPI configuration lock.
340  *
341  * It should be called before ICH sends any spi command.
342  */
343 int ich_init_opcodes()
344 {
345         int rc = 0;
346         OPCODES *curopcodes_done;
347
348         if (curopcodes)
349                 return 0;
350
351         if (ichspi_lock) {
352                 printf_debug("Generating OPCODES... ");
353                 curopcodes_done = &O_EXISTING;
354                 rc = generate_opcodes(curopcodes_done);
355         } else {
356                 printf_debug("Programming OPCODES... ");
357                 curopcodes_done = &O_ST_M25P;
358                 rc = program_opcodes(curopcodes_done);
359         }
360
361         if (rc) {
362                 curopcodes = NULL;
363                 printf_debug("failed\n");
364                 return 1;
365         } else {
366                 curopcodes = curopcodes_done;
367                 printf_debug("done\n");
368                 return 0;
369         }
370 }
371
372 static int ich7_run_opcode(OPCODE op, uint32_t offset,
373                            uint8_t datalength, uint8_t * data, int maxdata)
374 {
375         int write_cmd = 0;
376         int timeout;
377         uint32_t temp32 = 0;
378         uint16_t temp16;
379         uint32_t a;
380         uint64_t opmenu;
381         int opcode_index;
382
383         /* Is it a write command? */
384         if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
385             || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
386                 write_cmd = 1;
387         }
388
389         /* Programm Offset in Flash into FADDR */
390         REGWRITE32(ICH7_REG_SPIA, (offset & 0x00FFFFFF));       /* SPI addresses are 24 BIT only */
391
392         /* Program data into FDATA0 to N */
393         if (write_cmd && (datalength != 0)) {
394                 temp32 = 0;
395                 for (a = 0; a < datalength; a++) {
396                         if ((a % 4) == 0) {
397                                 temp32 = 0;
398                         }
399
400                         temp32 |= ((uint32_t) data[a]) << ((a % 4) * 8);
401
402                         if ((a % 4) == 3) {
403                                 REGWRITE32(ICH7_REG_SPID0 + (a - (a % 4)),
404                                            temp32);
405                         }
406                 }
407                 if (((a - 1) % 4) != 3) {
408                         REGWRITE32(ICH7_REG_SPID0 +
409                                    ((a - 1) - ((a - 1) % 4)), temp32);
410                 }
411
412         }
413
414         /* Assemble SPIS */
415         temp16 = 0;
416         /* clear error status registers */
417         temp16 |= (SPIS_CDS + SPIS_FCERR);
418         REGWRITE16(ICH7_REG_SPIS, temp16);
419
420         /* Assemble SPIC */
421         temp16 = 0;
422
423         if (datalength != 0) {
424                 temp16 |= SPIC_DS;
425                 temp16 |= ((uint32_t) ((datalength - 1) & (maxdata - 1))) << 8;
426         }
427
428         /* Select opcode */
429         opmenu = REGREAD32(ICH7_REG_OPMENU);
430         opmenu |= ((uint64_t)REGREAD32(ICH7_REG_OPMENU + 4)) << 32;
431
432         for (opcode_index=0; opcode_index<8; opcode_index++) {
433                 if((opmenu & 0xff) == op.opcode) {
434                         break;
435                 }
436                 opmenu >>= 8;
437         }
438         if (opcode_index == 8) {
439                 printf_debug("Opcode %x not found.\n", op.opcode);
440                 return 1;
441         }
442         temp16 |= ((uint16_t) (opcode_index & 0x07)) << 4;
443
444         /* Handle Atomic */
445         if (op.atomic != 0) {
446                 /* Select atomic command */
447                 temp16 |= SPIC_ACS;
448                 /* Select prefix opcode */
449                 if ((op.atomic - 1) == 1) {
450                         /*Select prefix opcode 2 */
451                         temp16 |= SPIC_SPOP;
452                 }
453         }
454
455         /* Start */
456         temp16 |= SPIC_SCGO;
457
458         /* write it */
459         REGWRITE16(ICH7_REG_SPIC, temp16);
460
461         /* wait for cycle complete */
462         timeout = 1000 * 60;    // 60s is a looong timeout.
463         while (((REGREAD16(ICH7_REG_SPIS) & SPIS_CDS) == 0) && --timeout) {
464                 myusec_delay(1000);
465         }
466         if (!timeout) {
467                 printf_debug("timeout\n");
468         }
469
470         if ((REGREAD16(ICH7_REG_SPIS) & SPIS_FCERR) != 0) {
471                 printf_debug("Transaction error!\n");
472                 return 1;
473         }
474
475         if ((!write_cmd) && (datalength != 0)) {
476                 for (a = 0; a < datalength; a++) {
477                         if ((a % 4) == 0) {
478                                 temp32 = REGREAD32(ICH7_REG_SPID0 + (a));
479                         }
480
481                         data[a] =
482                             (temp32 & (((uint32_t) 0xff) << ((a % 4) * 8)))
483                             >> ((a % 4) * 8);
484                 }
485         }
486
487         return 0;
488 }
489
490 static int ich9_run_opcode(OPCODE op, uint32_t offset,
491                            uint8_t datalength, uint8_t * data)
492 {
493         int write_cmd = 0;
494         int timeout;
495         uint32_t temp32;
496         uint32_t a;
497         uint64_t opmenu;
498         int opcode_index;
499
500         /* Is it a write command? */
501         if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
502             || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
503                 write_cmd = 1;
504         }
505
506         /* Programm Offset in Flash into FADDR */
507         REGWRITE32(ICH9_REG_FADDR, (offset & 0x00FFFFFF));      /* SPI addresses are 24 BIT only */
508
509         /* Program data into FDATA0 to N */
510         if (write_cmd && (datalength != 0)) {
511                 temp32 = 0;
512                 for (a = 0; a < datalength; a++) {
513                         if ((a % 4) == 0) {
514                                 temp32 = 0;
515                         }
516
517                         temp32 |= ((uint32_t) data[a]) << ((a % 4) * 8);
518
519                         if ((a % 4) == 3) {
520                                 REGWRITE32(ICH9_REG_FDATA0 + (a - (a % 4)),
521                                            temp32);
522                         }
523                 }
524                 if (((a - 1) % 4) != 3) {
525                         REGWRITE32(ICH9_REG_FDATA0 +
526                                    ((a - 1) - ((a - 1) % 4)), temp32);
527                 }
528
529         }
530
531         /* Assemble SSFS + SSFC */
532         temp32 = 0;
533
534         /* clear error status registers */
535         temp32 |= (SSFS_CDS + SSFS_FCERR);
536         /* USE 20 MhZ */
537         temp32 |= SSFC_SCF_20MHZ;
538
539         if (datalength != 0) {
540                 uint32_t datatemp;
541                 temp32 |= SSFC_DS;
542                 datatemp = ((uint32_t) ((datalength - 1) & 0x3f)) << (8 + 8);
543                 temp32 |= datatemp;
544         }
545
546         /* Select opcode */
547         opmenu = REGREAD32(ICH9_REG_OPMENU);
548         opmenu |= ((uint64_t)REGREAD32(ICH9_REG_OPMENU + 4)) << 32;
549
550         for (opcode_index=0; opcode_index<8; opcode_index++) {
551                 if((opmenu & 0xff) == op.opcode) {
552                         break;
553                 }
554                 opmenu >>= 8;
555         }
556         if (opcode_index == 8) {
557                 printf_debug("Opcode %x not found.\n", op.opcode);
558                 return 1;
559         }
560         temp32 |= ((uint32_t) (opcode_index & 0x07)) << (8 + 4);
561
562         /* Handle Atomic */
563         if (op.atomic != 0) {
564                 /* Select atomic command */
565                 temp32 |= SSFC_ACS;
566                 /* Selct prefix opcode */
567                 if ((op.atomic - 1) == 1) {
568                         /*Select prefix opcode 2 */
569                         temp32 |= SSFC_SPOP;
570                 }
571         }
572
573         /* Start */
574         temp32 |= SSFC_SCGO;
575
576         /* write it */
577         REGWRITE32(ICH9_REG_SSFS, temp32);
578
579         /*wait for cycle complete */
580         timeout = 1000 * 60;    // 60s is a looong timeout.
581         while (((REGREAD32(ICH9_REG_SSFS) & SSFS_CDS) == 0) && --timeout) {
582                 myusec_delay(1000);
583         }
584         if (!timeout) {
585                 printf_debug("timeout\n");
586         }
587
588         if ((REGREAD32(ICH9_REG_SSFS) & SSFS_FCERR) != 0) {
589                 printf_debug("Transaction error!\n");
590                 return 1;
591         }
592
593         if ((!write_cmd) && (datalength != 0)) {
594                 for (a = 0; a < datalength; a++) {
595                         if ((a % 4) == 0) {
596                                 temp32 = REGREAD32(ICH9_REG_FDATA0 + (a));
597                         }
598
599                         data[a] =
600                             (temp32 & (((uint32_t) 0xff) << ((a % 4) * 8)))
601                             >> ((a % 4) * 8);
602                 }
603         }
604
605         return 0;
606 }
607
608 static int run_opcode(OPCODE op, uint32_t offset,
609                       uint8_t datalength, uint8_t * data)
610 {
611         switch (flashbus) {
612         case BUS_TYPE_VIA_SPI:
613                 return ich7_run_opcode(op, offset, datalength, data, 16);
614         case BUS_TYPE_ICH7_SPI:
615                 return ich7_run_opcode(op, offset, datalength, data, 64);
616         case BUS_TYPE_ICH9_SPI:
617                 return ich9_run_opcode(op, offset, datalength, data);
618         default:
619                 printf_debug("%s: unsupported chipset\n", __FUNCTION__);
620         }
621
622         /* If we ever get here, something really weird happened */
623         return -1;
624 }
625
626 static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf, int offset,
627                              int maxdata)
628 {
629         int page_size = flash->page_size;
630         uint32_t remaining = flash->page_size;
631         int a;
632
633         printf_debug("ich_spi_read_page: offset=%d, number=%d, buf=%p\n",
634                      offset, page_size, buf);
635
636         for (a = 0; a < page_size; a += maxdata) {
637                 if (remaining < maxdata) {
638
639                         if (spi_nbyte_read(offset + (page_size - remaining),
640                                 &buf[page_size - remaining], remaining)) {
641                                 printf_debug("Error reading");
642                                 return 1;
643                         }
644                         remaining = 0;
645                 } else {
646                         if (spi_nbyte_read(offset + (page_size - remaining),
647                                 &buf[page_size - remaining], maxdata)) {
648                                 printf_debug("Error reading");
649                                 return 1;
650                         }
651                         remaining -= maxdata;
652                 }
653         }
654
655         return 0;
656 }
657
658 static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
659                               int offset, int maxdata)
660 {
661         int page_size = flash->page_size;
662         uint32_t remaining = page_size;
663         int a;
664
665         printf_debug("ich_spi_write_page: offset=%d, number=%d, buf=%p\n",
666                      offset, page_size, bytes);
667
668         for (a = 0; a < page_size; a += maxdata) {
669                 if (remaining < maxdata) {
670                         if (run_opcode
671                             (curopcodes->opcode[0],
672                              offset + (page_size - remaining), remaining,
673                              &bytes[page_size - remaining]) != 0) {
674                                 printf_debug("Error writing");
675                                 return 1;
676                         }
677                         remaining = 0;
678                 } else {
679                         if (run_opcode
680                             (curopcodes->opcode[0],
681                              offset + (page_size - remaining), maxdata,
682                              &bytes[page_size - remaining]) != 0) {
683                                 printf_debug("Error writing");
684                                 return 1;
685                         }
686                         remaining -= maxdata;
687                 }
688         }
689
690         return 0;
691 }
692
693 int ich_spi_read(struct flashchip *flash, uint8_t * buf)
694 {
695         int i, rc = 0;
696         int total_size = flash->total_size * 1024;
697         int page_size = flash->page_size;
698         int maxdata = 64;
699
700         if (flashbus == BUS_TYPE_VIA_SPI) {
701                 maxdata = 16;
702         }
703
704         for (i = 0; (i < total_size / page_size) && (rc == 0); i++) {
705                 rc = ich_spi_read_page(flash, (void *)(buf + i * page_size),
706                                        i * page_size, maxdata);
707         }
708
709         return rc;
710 }
711
712 int ich_spi_write(struct flashchip *flash, uint8_t * buf)
713 {
714         int i, j, rc = 0;
715         int total_size = flash->total_size * 1024;
716         int page_size = flash->page_size;
717         int erase_size = 64 * 1024;
718         int maxdata = 64;
719
720         spi_disable_blockprotect();
721
722         printf("Programming page: \n");
723
724         for (i = 0; i < total_size / erase_size; i++) {
725                 /* FIMXE: call the chip-specific spi_block_erase_XX instead.
726                  * For this, we need to add a block erase function to
727                  * struct flashchip.
728                  */
729                 rc = spi_block_erase_d8(flash, i * erase_size);
730                 if (rc) {
731                         printf("Error erasing block at 0x%x\n", i);
732                         break;
733                 }
734
735                 if (flashbus == BUS_TYPE_VIA_SPI)
736                         maxdata = 16;
737
738                 for (j = 0; j < erase_size / page_size; j++) {
739                         ich_spi_write_page(flash,
740                            (void *)(buf + (i * erase_size) + (j * page_size)),
741                            (i * erase_size) + (j * page_size), maxdata);
742                 }
743         }
744
745         printf("\n");
746
747         return rc;
748 }
749
750 int ich_spi_command(unsigned int writecnt, unsigned int readcnt,
751                     const unsigned char *writearr, unsigned char *readarr)
752 {
753         int a;
754         int opcode_index = -1;
755         const unsigned char cmd = *writearr;
756         OPCODE *opcode;
757         uint32_t addr = 0;
758         uint8_t *data;
759         int count;
760
761         /* find cmd in opcodes-table */
762         for (a = 0; a < 8; a++) {
763                 if ((curopcodes->opcode[a]).opcode == cmd) {
764                         opcode_index = a;
765                         break;
766                 }
767         }
768
769         /* unknown / not programmed command */
770         if (opcode_index == -1) {
771                 printf_debug("Invalid OPCODE 0x%02x\n", cmd);
772                 return 1;
773         }
774
775         opcode = &(curopcodes->opcode[opcode_index]);
776
777         /* if opcode-type requires an address */
778         if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS ||
779             opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
780                 addr = (writearr[1] << 16) |
781                     (writearr[2] << 8) | (writearr[3] << 0);
782         }
783
784         /* translate read/write array/count */
785         if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) {
786                 data = (uint8_t *) (writearr + 1);
787                 count = writecnt - 1;
788         } else if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
789                 data = (uint8_t *) (writearr + 4);
790                 count = writecnt - 4;
791         } else {
792                 data = (uint8_t *) readarr;
793                 count = readcnt;
794         }
795
796         if (run_opcode(*opcode, addr, count, data) != 0) {
797                 printf_debug("run OPCODE 0x%02x failed\n", opcode->opcode);
798                 return 1;
799         }
800
801         return 0;
802 }