ichspi.c 22.8 KB
Newer Older
1 2 3 4 5 6
/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2008 Stefan Wildemann <stefan.wildemann@kontron.com>
 * Copyright (C) 2008 Claus Gindhart <claus.gindhart@kontron.com>
 * Copyright (C) 2008 Dominik Geyer <dominik.geyer@kontron.com>
Stefan Reinauer's avatar
Stefan Reinauer committed
7
 * Copyright (C) 2008 coresystems GmbH <info@coresystems.de>
8
 * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

/*
 * This module is designed for supporting the devices
 * ST M25P40
 * ST M25P80
 * ST M25P16
 * ST M25P32 already tested
 * ST M25P64
 * AT 25DF321 already tested
 *
 */

36 37
#if defined(__i386__) || defined(__x86_64__)

38 39
#include <string.h>
#include "flash.h"
40
#include "chipdrivers.h"
41 42
#include "spi.h"

Stefan Reinauer's avatar
Stefan Reinauer committed
43 44 45 46 47
/* ICH9 controller register definition */
#define ICH9_REG_FADDR         0x08	/* 32 Bits */
#define ICH9_REG_FDATA0                0x10	/* 64 Bytes */

#define ICH9_REG_SSFS          0x90	/* 08 Bits */
48 49 50 51
#define SSFS_SCIP		0x00000001
#define SSFS_CDS		0x00000004
#define SSFS_FCERR		0x00000008
#define SSFS_AEL		0x00000010
Stefan Reinauer's avatar
Stefan Reinauer committed
52 53

#define ICH9_REG_SSFC          0x91	/* 24 Bits */
54 55 56 57 58 59 60 61 62 63
#define SSFC_SCGO		0x00000200
#define SSFC_ACS		0x00000400
#define SSFC_SPOP		0x00000800
#define SSFC_COP		0x00001000
#define SSFC_DBC		0x00010000
#define SSFC_DS			0x00400000
#define SSFC_SME		0x00800000
#define SSFC_SCF		0x01000000
#define SSFC_SCF_20MHZ 0x00000000
#define SSFC_SCF_33MHZ 0x01000000
Stefan Reinauer's avatar
Stefan Reinauer committed
64 65 66 67

#define ICH9_REG_PREOP         0x94	/* 16 Bits */
#define ICH9_REG_OPTYPE                0x96	/* 16 Bits */
#define ICH9_REG_OPMENU                0x98	/* 64 Bits */
68 69 70 71 72 73 74

// ICH9R SPI commands
#define SPI_OPCODE_TYPE_READ_NO_ADDRESS     0
#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS    1
#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS   2
#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS  3

Stefan Reinauer's avatar
Stefan Reinauer committed
75 76 77 78 79 80
// ICH7 registers
#define ICH7_REG_SPIS          0x00	/* 16 Bits */
#define SPIS_SCIP              0x00000001
#define SPIS_CDS               0x00000004
#define SPIS_FCERR             0x00000008

81 82 83 84 85 86 87 88 89 90
/* VIA SPI is compatible with ICH7, but maxdata
   to transfer is 16 bytes.

   DATA byte count on ICH7 is 8:13, on VIA 8:11

   bit 12 is port select CS0 CS1
   bit 13 is FAST READ enable
   bit 7  is used with fast read and one shot controls CS de-assert?
*/

Stefan Reinauer's avatar
Stefan Reinauer committed
91 92 93 94
#define ICH7_REG_SPIC          0x02	/* 16 Bits */
#define SPIC_SCGO              0x0002
#define SPIC_ACS               0x0004
#define SPIC_SPOP              0x0008
95
#define SPIC_DS                0x4000
Stefan Reinauer's avatar
Stefan Reinauer committed
96 97 98 99 100 101 102

#define ICH7_REG_SPIA          0x04	/* 32 Bits */
#define ICH7_REG_SPID0         0x08	/* 64 Bytes */
#define ICH7_REG_PREOP         0x54	/* 16 Bits */
#define ICH7_REG_OPTYPE                0x56	/* 16 Bits */
#define ICH7_REG_OPMENU                0x58	/* 64 Bits */

103 104 105
/* ICH SPI configuration lock-down. May be set during chipset enabling. */
int ichspi_lock = 0;

106 107
uint32_t ichspi_bbar = 0;

108 109 110 111 112 113
typedef struct _OPCODE {
	uint8_t opcode;		//This commands spi opcode
	uint8_t spi_type;	//This commands spi type
	uint8_t atomic;		//Use preop: (0: none, 1: preop0, 2: preop1
} OPCODE;

114
/* Suggested opcode definition:
115 116 117 118 119 120 121 122 123
 * Preop 1: Write Enable
 * Preop 2: Write Status register enable
 *
 * OP 0: Write address
 * OP 1: Read Address
 * OP 2: ERASE block
 * OP 3: Read Status register
 * OP 4: Read ID
 * OP 5: Write Status register
124
 * OP 6: chip private (read JEDEC id)
125 126 127 128 129 130 131
 * OP 7: Chip erase
 */
typedef struct _OPCODES {
	uint8_t preop[2];
	OPCODE opcode[8];
} OPCODES;

132
static OPCODES *curopcodes = NULL;
133 134

/* HW access functions */
135
static uint32_t REGREAD32(int X)
136
{
137
	return mmio_readl(spibar + X);
Stefan Reinauer's avatar
Stefan Reinauer committed
138 139
}

140
static uint16_t REGREAD16(int X)
Stefan Reinauer's avatar
Stefan Reinauer committed
141
{
142
	return mmio_readw(spibar + X);
143 144
}

145 146 147
#define REGWRITE32(X,Y) mmio_writel(Y, spibar+X)
#define REGWRITE16(X,Y) mmio_writew(Y, spibar+X)
#define REGWRITE8(X,Y)  mmio_writeb(Y, spibar+X)
148 149

/* Common SPI functions */
150 151
static int find_opcode(OPCODES *op, uint8_t opcode);
static int find_preop(OPCODES *op, uint8_t preop);
FENG yu ning's avatar
FENG yu ning committed
152
static int generate_opcodes(OPCODES * op);
153
static int program_opcodes(OPCODES * op);
154
static int run_opcode(OPCODE op, uint32_t offset,
155
		      uint8_t datalength, uint8_t * data);
156

FENG yu ning's avatar
FENG yu ning committed
157 158 159 160 161 162
/* for pairing opcodes with their required preop */
struct preop_opcode_pair {
	uint8_t preop;
	uint8_t opcode;
};

163
/* List of opcodes which need preopcodes and matching preopcodes. Unused. */
FENG yu ning's avatar
FENG yu ning committed
164 165 166 167 168 169 170
struct preop_opcode_pair pops[] = {
	{JEDEC_WREN, JEDEC_BYTE_PROGRAM},
	{JEDEC_WREN, JEDEC_SE}, /* sector erase */
	{JEDEC_WREN, JEDEC_BE_52}, /* block erase */
	{JEDEC_WREN, JEDEC_BE_D8}, /* block erase */
	{JEDEC_WREN, JEDEC_CE_60}, /* chip erase */
	{JEDEC_WREN, JEDEC_CE_C7}, /* chip erase */
171 172
	 /* FIXME: WRSR requires either EWSR or WREN depending on chip type. */
	{JEDEC_WREN, JEDEC_WRSR},
FENG yu ning's avatar
FENG yu ning committed
173 174 175 176
	{JEDEC_EWSR, JEDEC_WRSR},
	{0,}
};

177 178 179
/* Reasonable default configuration. Needs ad-hoc modifications if we
 * encounter unlisted opcodes. Fun.
 */
180 181 182
OPCODES O_ST_M25P = {
	{
	 JEDEC_WREN,
183 184
	 JEDEC_EWSR,
	},
185
	{
186
	 {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0},	// Write Byte
187
	 {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0},	// Read Data
188
	 {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0},	// Erase Sector
189
	 {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0},	// Read Device Status Reg
190
	 {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0},	// Read Electronic Manufacturer Signature
191
	 {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0},	// Write Status Register
192
	 {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0},	// Read JDEC ID
193 194
	 {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0},	// Bulk erase
	}
195 196
};

197 198
OPCODES O_EXISTING = {};

199
static int find_opcode(OPCODES *op, uint8_t opcode)
200 201 202 203 204 205 206 207 208 209 210
{
	int a;

	for (a = 0; a < 8; a++) {
		if (op->opcode[a].opcode == opcode)
			return a;
	}

	return -1;
}

211
static int find_preop(OPCODES *op, uint8_t preop)
212 213 214 215 216 217 218 219 220 221 222
{
	int a;

	for (a = 0; a < 2; a++) {
		if (op->preop[a] == preop)
			return a;
	}

	return -1;
}

223
/* Create a struct OPCODES based on what we find in the locked down chipset. */
FENG yu ning's avatar
FENG yu ning committed
224
static int generate_opcodes(OPCODES * op)
225
{
226
	int a;
227 228 229 230
	uint16_t preop, optype;
	uint32_t opmenu[2];

	if (op == NULL) {
231
		msg_perr("\n%s: null OPCODES pointer!\n", __func__);
232 233 234
		return -1;
	}

235 236 237
	switch (spi_controller) {
	case SPI_CONTROLLER_ICH7:
	case SPI_CONTROLLER_VIA:
238 239 240 241 242
		preop = REGREAD16(ICH7_REG_PREOP);
		optype = REGREAD16(ICH7_REG_OPTYPE);
		opmenu[0] = REGREAD32(ICH7_REG_OPMENU);
		opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4);
		break;
243
	case SPI_CONTROLLER_ICH9:
244 245 246 247 248 249
		preop = REGREAD16(ICH9_REG_PREOP);
		optype = REGREAD16(ICH9_REG_OPTYPE);
		opmenu[0] = REGREAD32(ICH9_REG_OPMENU);
		opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4);
		break;
	default:
250
		msg_perr("%s: unsupported chipset\n", __func__);
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
		return -1;
	}

	op->preop[0] = (uint8_t) preop;
	op->preop[1] = (uint8_t) (preop >> 8);

	for (a = 0; a < 8; a++) {
		op->opcode[a].spi_type = (uint8_t) (optype & 0x3);
		optype >>= 2;
	}

	for (a = 0; a < 4; a++) {
		op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff);
		opmenu[0] >>= 8;
	}

	for (a = 4; a < 8; a++) {
		op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff);
		opmenu[1] >>= 8;
	}

272 273
	/* No preopcodes used by default. */
	for (a = 0; a < 8; a++)
274 275 276 277 278
		op->opcode[a].atomic = 0;

	return 0;
}

279 280 281
int program_opcodes(OPCODES * op)
{
	uint8_t a;
282 283
	uint16_t preop, optype;
	uint32_t opmenu[2];
284 285 286

	/* Program Prefix Opcodes */
	/* 0:7 Prefix Opcode 1 */
287
	preop = (op->preop[0]);
288
	/* 8:16 Prefix Opcode 2 */
289
	preop |= ((uint16_t) op->preop[1]) << 8;
290

Stefan Reinauer's avatar
Stefan Reinauer committed
291
	/* Program Opcode Types 0 - 7 */
292
	optype = 0;
293
	for (a = 0; a < 8; a++) {
294
		optype |= ((uint16_t) op->opcode[a].spi_type) << (a * 2);
295
	}
296

Stefan Reinauer's avatar
Stefan Reinauer committed
297
	/* Program Allowable Opcodes 0 - 3 */
298
	opmenu[0] = 0;
299
	for (a = 0; a < 4; a++) {
300
		opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8);
Stefan Reinauer's avatar
Stefan Reinauer committed
301 302
	}

303
	/*Program Allowable Opcodes 4 - 7 */
304
	opmenu[1] = 0;
305
	for (a = 4; a < 8; a++) {
306
		opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);
Stefan Reinauer's avatar
Stefan Reinauer committed
307 308
	}

309
	msg_pdbg("\n%s: preop=%04x optype=%04x opmenu=%08x%08x\n", __func__, preop, optype, opmenu[0], opmenu[1]);
310 311 312
	switch (spi_controller) {
	case SPI_CONTROLLER_ICH7:
	case SPI_CONTROLLER_VIA:
313 314 315 316 317
		REGWRITE16(ICH7_REG_PREOP, preop);
		REGWRITE16(ICH7_REG_OPTYPE, optype);
		REGWRITE32(ICH7_REG_OPMENU, opmenu[0]);
		REGWRITE32(ICH7_REG_OPMENU + 4, opmenu[1]);
		break;
318
	case SPI_CONTROLLER_ICH9:
319 320 321 322 323 324
		REGWRITE16(ICH9_REG_PREOP, preop);
		REGWRITE16(ICH9_REG_OPTYPE, optype);
		REGWRITE32(ICH9_REG_OPMENU, opmenu[0]);
		REGWRITE32(ICH9_REG_OPMENU + 4, opmenu[1]);
		break;
	default:
325
		msg_perr("%s: unsupported chipset\n", __func__);
326
		return -1;
Stefan Reinauer's avatar
Stefan Reinauer committed
327 328 329 330 331
	}

	return 0;
}

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
/*
 * Try to set BBAR (BIOS Base Address Register), but read back the value in case
 * it didn't stick.
 */
void ich_set_bbar(uint32_t minaddr)
{
	switch (spi_controller) {
	case SPI_CONTROLLER_ICH7:
		mmio_writel(minaddr, spibar + 0x50);
		ichspi_bbar = mmio_readl(spibar + 0x50);
		/* We don't have any option except complaining. */
		if (ichspi_bbar != minaddr)
			msg_perr("Setting BBAR failed!\n");
		break;
	case SPI_CONTROLLER_ICH9:
		mmio_writel(minaddr, spibar + 0xA0);
		ichspi_bbar = mmio_readl(spibar + 0xA0);
		/* We don't have any option except complaining. */
		if (ichspi_bbar != minaddr)
			msg_perr("Setting BBAR failed!\n");
		break;
	default:
		/* Not sure if BBAR actually exists on VIA. */
		msg_pdbg("Setting BBAR is not implemented for VIA yet.\n");
		break;
	}
}

FENG yu ning's avatar
FENG yu ning committed
360 361
/* This function generates OPCODES from or programs OPCODES to ICH according to
 * the chipset's SPI configuration lock.
362
 *
FENG yu ning's avatar
FENG yu ning committed
363
 * It should be called before ICH sends any spi command.
364
 */
365
int ich_init_opcodes(void)
366 367 368 369 370 371 372 373
{
	int rc = 0;
	OPCODES *curopcodes_done;

	if (curopcodes)
		return 0;

	if (ichspi_lock) {
374
		msg_pdbg("Reading OPCODES... ");
375
		curopcodes_done = &O_EXISTING;
FENG yu ning's avatar
FENG yu ning committed
376
		rc = generate_opcodes(curopcodes_done);
377
	} else {
378
		msg_pdbg("Programming OPCODES... ");
379 380
		curopcodes_done = &O_ST_M25P;
		rc = program_opcodes(curopcodes_done);
381 382 383 384 385
		/* Technically not part of opcode init, but it allows opcodes
		 * to run without transaction errors by setting the lowest
		 * allowed address to zero.
		 */
		ich_set_bbar(0);
386 387 388 389
	}

	if (rc) {
		curopcodes = NULL;
390
		msg_perr("failed\n");
391 392 393
		return 1;
	} else {
		curopcodes = curopcodes_done;
394
		msg_pdbg("done\n");
395 396 397 398
		return 0;
	}
}

399
static int ich7_run_opcode(OPCODE op, uint32_t offset,
400
			   uint8_t datalength, uint8_t * data, int maxdata)
Stefan Reinauer's avatar
Stefan Reinauer committed
401 402 403
{
	int write_cmd = 0;
	int timeout;
404
	uint32_t temp32 = 0;
Stefan Reinauer's avatar
Stefan Reinauer committed
405 406
	uint16_t temp16;
	uint32_t a;
407 408
	uint64_t opmenu;
	int opcode_index;
Stefan Reinauer's avatar
Stefan Reinauer committed
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451

	/* Is it a write command? */
	if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
	    || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
		write_cmd = 1;
	}

	/* Programm Offset in Flash into FADDR */
	REGWRITE32(ICH7_REG_SPIA, (offset & 0x00FFFFFF));	/* SPI addresses are 24 BIT only */

	/* Program data into FDATA0 to N */
	if (write_cmd && (datalength != 0)) {
		temp32 = 0;
		for (a = 0; a < datalength; a++) {
			if ((a % 4) == 0) {
				temp32 = 0;
			}

			temp32 |= ((uint32_t) data[a]) << ((a % 4) * 8);

			if ((a % 4) == 3) {
				REGWRITE32(ICH7_REG_SPID0 + (a - (a % 4)),
					   temp32);
			}
		}
		if (((a - 1) % 4) != 3) {
			REGWRITE32(ICH7_REG_SPID0 +
				   ((a - 1) - ((a - 1) % 4)), temp32);
		}

	}

	/* Assemble SPIS */
	temp16 = 0;
	/* clear error status registers */
	temp16 |= (SPIS_CDS + SPIS_FCERR);
	REGWRITE16(ICH7_REG_SPIS, temp16);

	/* Assemble SPIC */
	temp16 = 0;

	if (datalength != 0) {
		temp16 |= SPIC_DS;
452
		temp16 |= ((uint32_t) ((datalength - 1) & (maxdata - 1))) << 8;
Stefan Reinauer's avatar
Stefan Reinauer committed
453 454 455
	}

	/* Select opcode */
456 457 458
	opmenu = REGREAD32(ICH7_REG_OPMENU);
	opmenu |= ((uint64_t)REGREAD32(ICH7_REG_OPMENU + 4)) << 32;

459 460
	for (opcode_index = 0; opcode_index < 8; opcode_index++) {
		if ((opmenu & 0xff) == op.opcode) {
461 462 463 464 465
			break;
		}
		opmenu >>= 8;
	}
	if (opcode_index == 8) {
466
		msg_pdbg("Opcode %x not found.\n", op.opcode);
467 468 469
		return 1;
	}
	temp16 |= ((uint16_t) (opcode_index & 0x07)) << 4;
Stefan Reinauer's avatar
Stefan Reinauer committed
470 471

	/* Handle Atomic */
472 473 474 475 476 477 478
	switch (op.atomic) {
	case 2:
		/* Select second preop. */
		temp16 |= SPIC_SPOP;
		/* And fall through. */
	case 1:
		/* Atomic command (preop+op) */
Stefan Reinauer's avatar
Stefan Reinauer committed
479
		temp16 |= SPIC_ACS;
480
		break;
Stefan Reinauer's avatar
Stefan Reinauer committed
481 482 483 484 485 486 487 488 489
	}

	/* Start */
	temp16 |= SPIC_SCGO;

	/* write it */
	REGWRITE16(ICH7_REG_SPIC, temp16);

	/* wait for cycle complete */
490
	timeout = 100 * 1000 * 60;	// 60s is a looong timeout.
Stefan Reinauer's avatar
Stefan Reinauer committed
491
	while (((REGREAD16(ICH7_REG_SPIS) & SPIS_CDS) == 0) && --timeout) {
492
		programmer_delay(10);
Stefan Reinauer's avatar
Stefan Reinauer committed
493 494
	}
	if (!timeout) {
495
		msg_perr("timeout\n");
Stefan Reinauer's avatar
Stefan Reinauer committed
496 497
	}

498
	/* FIXME: make sure we do not needlessly cause transaction errors. */
Stefan Reinauer's avatar
Stefan Reinauer committed
499
	if ((REGREAD16(ICH7_REG_SPIS) & SPIS_FCERR) != 0) {
500
		msg_pdbg("Transaction error!\n");
Stefan Reinauer's avatar
Stefan Reinauer committed
501 502 503 504 505 506 507 508 509 510 511 512 513
		return 1;
	}

	if ((!write_cmd) && (datalength != 0)) {
		for (a = 0; a < datalength; a++) {
			if ((a % 4) == 0) {
				temp32 = REGREAD32(ICH7_REG_SPID0 + (a));
			}

			data[a] =
			    (temp32 & (((uint32_t) 0xff) << ((a % 4) * 8)))
			    >> ((a % 4) * 8);
		}
514 515 516 517 518
	}

	return 0;
}

519
static int ich9_run_opcode(OPCODE op, uint32_t offset,
Stefan Reinauer's avatar
Stefan Reinauer committed
520
			   uint8_t datalength, uint8_t * data)
521 522
{
	int write_cmd = 0;
523
	int timeout;
524 525
	uint32_t temp32;
	uint32_t a;
526 527
	uint64_t opmenu;
	int opcode_index;
528 529 530 531 532 533 534 535

	/* Is it a write command? */
	if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
	    || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
		write_cmd = 1;
	}

	/* Programm Offset in Flash into FADDR */
Stefan Reinauer's avatar
Stefan Reinauer committed
536
	REGWRITE32(ICH9_REG_FADDR, (offset & 0x00FFFFFF));	/* SPI addresses are 24 BIT only */
537 538 539 540 541 542 543 544 545 546 547 548

	/* Program data into FDATA0 to N */
	if (write_cmd && (datalength != 0)) {
		temp32 = 0;
		for (a = 0; a < datalength; a++) {
			if ((a % 4) == 0) {
				temp32 = 0;
			}

			temp32 |= ((uint32_t) data[a]) << ((a % 4) * 8);

			if ((a % 4) == 3) {
Stefan Reinauer's avatar
Stefan Reinauer committed
549 550
				REGWRITE32(ICH9_REG_FDATA0 + (a - (a % 4)),
					   temp32);
551 552 553
			}
		}
		if (((a - 1) % 4) != 3) {
Stefan Reinauer's avatar
Stefan Reinauer committed
554 555
			REGWRITE32(ICH9_REG_FDATA0 +
				   ((a - 1) - ((a - 1) % 4)), temp32);
556 557 558 559 560 561 562 563
		}
	}

	/* Assemble SSFS + SSFC */
	temp32 = 0;

	/* clear error status registers */
	temp32 |= (SSFS_CDS + SSFS_FCERR);
564
	/* Use 20 MHz */
565 566 567 568 569 570 571 572 573 574
	temp32 |= SSFC_SCF_20MHZ;

	if (datalength != 0) {
		uint32_t datatemp;
		temp32 |= SSFC_DS;
		datatemp = ((uint32_t) ((datalength - 1) & 0x3f)) << (8 + 8);
		temp32 |= datatemp;
	}

	/* Select opcode */
575 576 577
	opmenu = REGREAD32(ICH9_REG_OPMENU);
	opmenu |= ((uint64_t)REGREAD32(ICH9_REG_OPMENU + 4)) << 32;

578 579
	for (opcode_index = 0; opcode_index < 8; opcode_index++) {
		if ((opmenu & 0xff) == op.opcode) {
580 581 582 583 584
			break;
		}
		opmenu >>= 8;
	}
	if (opcode_index == 8) {
585
		msg_pdbg("Opcode %x not found.\n", op.opcode);
586 587 588
		return 1;
	}
	temp32 |= ((uint32_t) (opcode_index & 0x07)) << (8 + 4);
589 590

	/* Handle Atomic */
591 592 593 594 595 596 597
	switch (op.atomic) {
	case 2:
		/* Select second preop. */
		temp32 |= SSFC_SPOP;
		/* And fall through. */
	case 1:
		/* Atomic command (preop+op) */
598
		temp32 |= SSFC_ACS;
599
		break;
600 601 602 603 604 605
	}

	/* Start */
	temp32 |= SSFC_SCGO;

	/* write it */
Stefan Reinauer's avatar
Stefan Reinauer committed
606
	REGWRITE32(ICH9_REG_SSFS, temp32);
607 608

	/*wait for cycle complete */
609
	timeout = 100 * 1000 * 60;	// 60s is a looong timeout.
610
	while (((REGREAD32(ICH9_REG_SSFS) & SSFS_CDS) == 0) && --timeout) {
611
		programmer_delay(10);
612 613
	}
	if (!timeout) {
614
		msg_perr("timeout\n");
615 616
	}

617
	/* FIXME make sure we do not needlessly cause transaction errors. */
Stefan Reinauer's avatar
Stefan Reinauer committed
618
	if ((REGREAD32(ICH9_REG_SSFS) & SSFS_FCERR) != 0) {
619
		msg_pdbg("Transaction error!\n");
620 621 622 623 624 625
		return 1;
	}

	if ((!write_cmd) && (datalength != 0)) {
		for (a = 0; a < datalength; a++) {
			if ((a % 4) == 0) {
Stefan Reinauer's avatar
Stefan Reinauer committed
626
				temp32 = REGREAD32(ICH9_REG_FDATA0 + (a));
627 628 629
			}

			data[a] =
Stefan Reinauer's avatar
Stefan Reinauer committed
630 631
			    (temp32 & (((uint32_t) 0xff) << ((a % 4) * 8)))
			    >> ((a % 4) * 8);
632 633 634 635 636 637
		}
	}

	return 0;
}

638
static int run_opcode(OPCODE op, uint32_t offset,
Stefan Reinauer's avatar
Stefan Reinauer committed
639 640
		      uint8_t datalength, uint8_t * data)
{
641 642
	switch (spi_controller) {
	case SPI_CONTROLLER_VIA:
643
		if (datalength > 16) {
644
			msg_perr("%s: Internal command size error for "
645 646
				"opcode 0x%02x, got datalength=%i, want <=16\n",
				__func__, op.opcode, datalength);
647
			return SPI_INVALID_LENGTH;
648
		}
649
		return ich7_run_opcode(op, offset, datalength, data, 16);
650
	case SPI_CONTROLLER_ICH7:
651
		if (datalength > 64) {
652
			msg_perr("%s: Internal command size error for "
653 654
				"opcode 0x%02x, got datalength=%i, want <=16\n",
				__func__, op.opcode, datalength);
655
			return SPI_INVALID_LENGTH;
656
		}
657
		return ich7_run_opcode(op, offset, datalength, data, 64);
658
	case SPI_CONTROLLER_ICH9:
659
		if (datalength > 64) {
660
			msg_perr("%s: Internal command size error for "
661 662
				"opcode 0x%02x, got datalength=%i, want <=16\n",
				__func__, op.opcode, datalength);
663
			return SPI_INVALID_LENGTH;
664
		}
665
		return ich9_run_opcode(op, offset, datalength, data);
666
	default:
667
		msg_perr("%s: unsupported chipset\n", __func__);
668
	}
Stefan Reinauer's avatar
Stefan Reinauer committed
669 670 671 672 673

	/* If we ever get here, something really weird happened */
	return -1;
}

674
int ich_spi_read(struct flashchip *flash, uint8_t * buf, int start, int len)
675
{
676 677
	int maxdata = 64;

678
	if (spi_controller == SPI_CONTROLLER_VIA)
679
		maxdata = 16;
680

681
	return spi_read_chunked(flash, buf, start, len, maxdata);
682 683
}

684
int ich_spi_write_256(struct flashchip *flash, uint8_t * buf)
685
{
686
	int i, ret = 0;
687 688
	int total_size = flash->total_size * 1024;
	int erase_size = 64 * 1024;
689
	int maxdata = 64;
690

691 692 693
	if (spi_controller == SPI_CONTROLLER_VIA)
		maxdata = 16;

694
	spi_disable_blockprotect();
695
	/* Erase first */
696
	msg_pinfo("Erasing flash before programming... ");
697
	if (erase_flash(flash)) {
698
		msg_perr("ERASE FAILED!\n");
699 700
		return -1;
	}
701
	msg_pinfo("done.\n");
702

703
	msg_pinfo("Programming page: \n");
704
	for (i = 0; i < total_size / erase_size; i++) {
705 706 707 708
		ret = spi_write_chunked(flash, buf + (i * erase_size),
					i * erase_size, erase_size, maxdata);
		if (ret)
			break;
709 710
	}

711
	msg_pinfo("\n");
712

713
	return ret;
714 715
}

716
int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
717
		    const unsigned char *writearr, unsigned char *readarr)
718
{
719
	int result;
720 721 722 723 724 725 726 727
	int opcode_index = -1;
	const unsigned char cmd = *writearr;
	OPCODE *opcode;
	uint32_t addr = 0;
	uint8_t *data;
	int count;

	/* find cmd in opcodes-table */
728
	opcode_index = find_opcode(curopcodes, cmd);
729
	if (opcode_index == -1) {
730 731 732
		/* FIXME: Reprogram opcodes if possible. Autodetect type of
		 * opcode by checking readcnt/writecnt.
		 */
733
		msg_pdbg("Invalid OPCODE 0x%02x\n", cmd);
734
		return SPI_INVALID_OPCODE;
735 736 737 738
	}

	opcode = &(curopcodes->opcode[opcode_index]);

739 740 741 742 743 744 745 746 747
	/* The following valid writecnt/readcnt combinations exist:
	 * writecnt  = 4, readcnt >= 0
	 * writecnt  = 1, readcnt >= 0
	 * writecnt >= 4, readcnt  = 0
	 * writecnt >= 1, readcnt  = 0
	 * writecnt >= 1 is guaranteed for all commands.
	 */
	if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS) &&
	    (writecnt != 4)) {
748
		msg_perr("%s: Internal command size error for opcode "
749 750 751 752 753 754
			"0x%02x, got writecnt=%i, want =4\n", __func__, cmd,
			writecnt);
		return SPI_INVALID_LENGTH;
	}
	if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_NO_ADDRESS) &&
	    (writecnt != 1)) {
755
		msg_perr("%s: Internal command size error for opcode "
756 757 758 759 760 761
			"0x%02x, got writecnt=%i, want =1\n", __func__, cmd,
			writecnt);
		return SPI_INVALID_LENGTH;
	}
	if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) &&
	    (writecnt < 4)) {
762
		msg_perr("%s: Internal command size error for opcode "
763 764 765 766 767 768 769
			"0x%02x, got writecnt=%i, want >=4\n", __func__, cmd,
			writecnt);
		return SPI_INVALID_LENGTH;
	}
	if (((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
	     (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) &&
	    (readcnt)) {
770
		msg_perr("%s: Internal command size error for opcode "
771 772 773 774 775
			"0x%02x, got readcnt=%i, want =0\n", __func__, cmd,
			readcnt);
		return SPI_INVALID_LENGTH;
	}

776 777 778
	/* if opcode-type requires an address */
	if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS ||
	    opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
779 780
		addr = (writearr[1] << 16) |
		    (writearr[2] << 8) | (writearr[3] << 0);
781 782 783 784 785 786 787 788 789 790 791 792 793
		switch (spi_controller) {
		case SPI_CONTROLLER_ICH7:
		case SPI_CONTROLLER_ICH9:
			if (addr < ichspi_bbar) {
				msg_perr("%s: Address 0x%06x below allowed "
					 "range 0x%06x-0xffffff\n", __func__,
					 addr, ichspi_bbar);
				return SPI_INVALID_ADDRESS;
			}
			break;
		default:
			break;
		}
794
	}
795

796 797
	/* translate read/write array/count */
	if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) {
798 799 800 801 802 803 804
		data = (uint8_t *) (writearr + 1);
		count = writecnt - 1;
	} else if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
		data = (uint8_t *) (writearr + 4);
		count = writecnt - 4;
	} else {
		data = (uint8_t *) readarr;
805 806
		count = readcnt;
	}
807

808 809
	result = run_opcode(*opcode, addr, count, data);
	if (result) {
810
		msg_pdbg("run OPCODE 0x%02x failed\n", opcode->opcode);
811 812
	}

813
	return result;
814
}
815

816
int ich_spi_send_multicommand(struct spi_command *cmds)
817 818
{
	int ret = 0;
819
	int i;
820 821 822
	int oppos, preoppos;
	for (; (cmds->writecnt || cmds->readcnt) && !ret; cmds++) {
		if ((cmds + 1)->writecnt || (cmds + 1)->readcnt) {
823
			/* Next command is valid. */
824 825
			preoppos = find_preop(curopcodes, cmds->writearr[0]);
			oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]);
826 827 828 829 830 831 832 833 834
			if ((oppos == -1) && (preoppos != -1)) {
				/* Current command is listed as preopcode in
				 * ICH struct OPCODES, but next command is not
				 * listed as opcode in that struct.
				 * Check for command sanity, then
				 * try to reprogram the ICH opcode list.
				 */
				if (find_preop(curopcodes,
					       (cmds + 1)->writearr[0]) != -1) {
835
					msg_perr("%s: Two subsequent "
836 837 838 839 840 841 842 843 844 845 846
						"preopcodes 0x%02x and 0x%02x, "
						"ignoring the first.\n",
						__func__, cmds->writearr[0],
						(cmds + 1)->writearr[0]);
					continue;
				}
				/* If the chipset is locked down, we'll fail
				 * during execution of the next command anyway.
				 * No need to bother with fixups.
				 */
				if (!ichspi_lock) {
847
					msg_pdbg("%s: FIXME: Add on-the-fly"
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
						     " reprogramming of the "
						     "chipset opcode list.\n",
						     __func__);
				 	/* FIXME: Reprogram opcode menu.
					 * Find a less-useful opcode, replace it
					 * with the wanted opcode, detect optype
					 * and reprogram the opcode menu.
					 * Update oppos so the next if-statement
					 * can do something useful.
					 */
					//curopcodes.opcode[lessusefulindex] = (cmds + 1)->writearr[0]);
					//update_optypes(curopcodes);
					//program_opcodes(curopcodes);
					//oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]);
					continue;
				}
			}
			if ((oppos != -1) && (preoppos != -1)) {
				/* Current command is listed as preopcode in
				 * ICH struct OPCODES and next command is listed
				 * as opcode in that struct. Match them up.
				 */
				curopcodes->opcode[oppos].atomic = preoppos + 1;
871
				continue;
872 873 874 875 876
			}
			/* If none of the above if-statements about oppos or
			 * preoppos matched, this is a normal opcode.
			 */
		}
877 878
		ret = ich_spi_send_command(cmds->writecnt, cmds->readcnt,
					   cmds->writearr, cmds->readarr);
879 880 881
		/* Reset the type of all opcodes to non-atomic. */
		for (i = 0; i < 8; i++)
			curopcodes->opcode[i].atomic = 0;
882 883 884
	}
	return ret;
}
885 886

#endif