ichspi.c 22.4 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
void *ich_spibar = NULL;

110 111 112 113 114 115
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;

116
/* Suggested opcode definition:
117 118 119 120 121 122 123 124 125
 * 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
126
 * OP 6: chip private (read JEDEC id)
127 128 129 130 131 132 133
 * OP 7: Chip erase
 */
typedef struct _OPCODES {
	uint8_t preop[2];
	OPCODE opcode[8];
} OPCODES;

134
static OPCODES *curopcodes = NULL;
135 136

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

142
static uint16_t REGREAD16(int X)
Stefan Reinauer's avatar
Stefan Reinauer committed
143
{
144
	return mmio_readw(ich_spibar + X);
145 146
}

147 148 149
#define REGWRITE32(X,Y) mmio_writel(Y, ich_spibar+X)
#define REGWRITE16(X,Y) mmio_writew(Y, ich_spibar+X)
#define REGWRITE8(X,Y)  mmio_writeb(Y, ich_spibar+X)
150 151

/* Common SPI functions */
152 153
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
154
static int generate_opcodes(OPCODES * op);
155
static int program_opcodes(OPCODES * op);
156
static int run_opcode(OPCODE op, uint32_t offset,
157
		      uint8_t datalength, uint8_t * data);
158

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

165
/* List of opcodes which need preopcodes and matching preopcodes. Unused. */
166
const struct preop_opcode_pair pops[] = {
FENG yu ning's avatar
FENG yu ning committed
167 168 169 170 171 172
	{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 */
173 174
	 /* FIXME: WRSR requires either EWSR or WREN depending on chip type. */
	{JEDEC_WREN, JEDEC_WRSR},
FENG yu ning's avatar
FENG yu ning committed
175 176 177 178
	{JEDEC_EWSR, JEDEC_WRSR},
	{0,}
};

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

199
static OPCODES O_EXISTING = {};
200

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

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

	return -1;
}

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

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

	return -1;
}

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

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

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

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

	return 0;
}

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

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

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

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

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

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

	return 0;
}

334 335 336 337 338 339 340 341
/*
 * 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:
342 343
		mmio_writel(minaddr, ich_spibar + 0x50);
		ichspi_bbar = mmio_readl(ich_spibar + 0x50);
344 345 346 347 348
		/* We don't have any option except complaining. */
		if (ichspi_bbar != minaddr)
			msg_perr("Setting BBAR failed!\n");
		break;
	case SPI_CONTROLLER_ICH9:
349 350
		mmio_writel(minaddr, ich_spibar + 0xA0);
		ichspi_bbar = mmio_readl(ich_spibar + 0xA0);
351 352 353 354 355 356 357 358 359 360 361
		/* 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
362 363
/* This function generates OPCODES from or programs OPCODES to ICH according to
 * the chipset's SPI configuration lock.
364
 *
FENG yu ning's avatar
FENG yu ning committed
365
 * It should be called before ICH sends any spi command.
366
 */
367
int ich_init_opcodes(void)
368 369 370 371 372 373 374 375
{
	int rc = 0;
	OPCODES *curopcodes_done;

	if (curopcodes)
		return 0;

	if (ichspi_lock) {
376
		msg_pdbg("Reading OPCODES... ");
377
		curopcodes_done = &O_EXISTING;
FENG yu ning's avatar
FENG yu ning committed
378
		rc = generate_opcodes(curopcodes_done);
379
	} else {
380
		msg_pdbg("Programming OPCODES... ");
381 382
		curopcodes_done = &O_ST_M25P;
		rc = program_opcodes(curopcodes_done);
383 384 385 386 387
		/* 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);
388 389 390 391
	}

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

401
static int ich7_run_opcode(OPCODE op, uint32_t offset,
402
			   uint8_t datalength, uint8_t * data, int maxdata)
Stefan Reinauer's avatar
Stefan Reinauer committed
403 404 405
{
	int write_cmd = 0;
	int timeout;
406
	uint32_t temp32 = 0;
Stefan Reinauer's avatar
Stefan Reinauer committed
407 408
	uint16_t temp16;
	uint32_t a;
409 410
	uint64_t opmenu;
	int opcode_index;
Stefan Reinauer's avatar
Stefan Reinauer committed
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 452 453

	/* 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;
454
		temp16 |= ((uint32_t) ((datalength - 1) & (maxdata - 1))) << 8;
Stefan Reinauer's avatar
Stefan Reinauer committed
455 456 457
	}

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

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

	/* Handle Atomic */
474 475 476 477 478 479 480
	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
481
		temp16 |= SPIC_ACS;
482
		break;
Stefan Reinauer's avatar
Stefan Reinauer committed
483 484 485 486 487 488 489 490 491
	}

	/* Start */
	temp16 |= SPIC_SCGO;

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

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

500
	/* FIXME: make sure we do not needlessly cause transaction errors. */
Stefan Reinauer's avatar
Stefan Reinauer committed
501
	if ((REGREAD16(ICH7_REG_SPIS) & SPIS_FCERR) != 0) {
502
		msg_pdbg("Transaction error!\n");
Stefan Reinauer's avatar
Stefan Reinauer committed
503 504 505 506 507 508 509 510 511 512 513 514 515
		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);
		}
516 517 518 519 520
	}

	return 0;
}

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

	/* 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
538
	REGWRITE32(ICH9_REG_FADDR, (offset & 0x00FFFFFF));	/* SPI addresses are 24 BIT only */
539 540 541 542 543 544 545 546 547 548 549 550

	/* 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
551 552
				REGWRITE32(ICH9_REG_FDATA0 + (a - (a % 4)),
					   temp32);
553 554 555
			}
		}
		if (((a - 1) % 4) != 3) {
Stefan Reinauer's avatar
Stefan Reinauer committed
556 557
			REGWRITE32(ICH9_REG_FDATA0 +
				   ((a - 1) - ((a - 1) % 4)), temp32);
558 559 560 561 562 563 564 565
		}
	}

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

	/* clear error status registers */
	temp32 |= (SSFS_CDS + SSFS_FCERR);
566
	/* Use 20 MHz */
567 568 569 570 571 572 573 574 575 576
	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 */
577 578 579
	opmenu = REGREAD32(ICH9_REG_OPMENU);
	opmenu |= ((uint64_t)REGREAD32(ICH9_REG_OPMENU + 4)) << 32;

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

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

	/* Start */
	temp32 |= SSFC_SCGO;

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

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

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

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

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

	return 0;
}

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

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

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

680
	if (spi_controller == SPI_CONTROLLER_VIA)
681
		maxdata = 16;
682

683
	return spi_read_chunked(flash, buf, start, len, maxdata);
684 685
}

686
int ich_spi_write_256(struct flashchip *flash, uint8_t * buf, int start, int len)
687
{
688
	int maxdata = 64;
689

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

693
	spi_disable_blockprotect();
694
	return spi_write_chunked(flash, buf, start, len, maxdata);
695 696
}

697
int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
698
		    const unsigned char *writearr, unsigned char *readarr)
699
{
700
	int result;
701 702 703 704 705 706 707 708
	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 */
709
	opcode_index = find_opcode(curopcodes, cmd);
710
	if (opcode_index == -1) {
711 712 713
		/* FIXME: Reprogram opcodes if possible. Autodetect type of
		 * opcode by checking readcnt/writecnt.
		 */
714
		msg_pdbg("Invalid OPCODE 0x%02x\n", cmd);
715
		return SPI_INVALID_OPCODE;
716 717 718 719
	}

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

720 721 722 723 724 725 726 727 728
	/* 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)) {
729
		msg_perr("%s: Internal command size error for opcode "
730 731 732 733 734 735
			"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)) {
736
		msg_perr("%s: Internal command size error for opcode "
737 738 739 740 741 742
			"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)) {
743
		msg_perr("%s: Internal command size error for opcode "
744 745 746 747 748 749 750
			"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)) {
751
		msg_perr("%s: Internal command size error for opcode "
752 753 754 755 756
			"0x%02x, got readcnt=%i, want =0\n", __func__, cmd,
			readcnt);
		return SPI_INVALID_LENGTH;
	}

757 758 759
	/* 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) {
760 761
		addr = (writearr[1] << 16) |
		    (writearr[2] << 8) | (writearr[3] << 0);
762 763 764 765 766 767 768 769 770 771 772 773 774
		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;
		}
775
	}
776

777 778
	/* translate read/write array/count */
	if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) {
779 780 781 782 783 784 785
		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;
786 787
		count = readcnt;
	}
788

789 790
	result = run_opcode(*opcode, addr, count, data);
	if (result) {
791
		msg_pdbg("run OPCODE 0x%02x failed\n", opcode->opcode);
792 793
	}

794
	return result;
795
}
796

797
int ich_spi_send_multicommand(struct spi_command *cmds)
798 799
{
	int ret = 0;
800
	int i;
801 802 803
	int oppos, preoppos;
	for (; (cmds->writecnt || cmds->readcnt) && !ret; cmds++) {
		if ((cmds + 1)->writecnt || (cmds + 1)->readcnt) {
804
			/* Next command is valid. */
805 806
			preoppos = find_preop(curopcodes, cmds->writearr[0]);
			oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]);
807 808 809 810 811 812 813 814 815
			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) {
816
					msg_perr("%s: Two subsequent "
817 818 819 820 821 822 823 824 825 826 827
						"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) {
828
					msg_pdbg("%s: FIXME: Add on-the-fly"
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
						     " 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;
852
				continue;
853 854 855 856 857
			}
			/* If none of the above if-statements about oppos or
			 * preoppos matched, this is a normal opcode.
			 */
		}
858 859
		ret = ich_spi_send_command(cmds->writecnt, cmds->readcnt,
					   cmds->writearr, cmds->readarr);
860 861 862
		/* Reset the type of all opcodes to non-atomic. */
		for (i = 0; i < 8; i++)
			curopcodes->opcode[i].atomic = 0;
863 864 865
	}
	return ret;
}
866 867

#endif