ich.c 20.6 KB
Newer Older
S
Simon Glass 已提交
1 2 3
/*
 * Copyright (c) 2011-12 The Chromium OS Authors.
 *
4
 * SPDX-License-Identifier:	GPL-2.0+
S
Simon Glass 已提交
5 6 7 8 9
 *
 * This file is derived from the flashrom project.
 */

#include <common.h>
10
#include <dm.h>
11
#include <errno.h>
S
Simon Glass 已提交
12 13 14 15 16 17 18 19 20 21 22
#include <malloc.h>
#include <spi.h>
#include <pci.h>
#include <pci_ids.h>
#include <asm/io.h>

#include "ich.h"

#define SPI_OPCODE_WREN      0x06
#define SPI_OPCODE_FAST_READ 0x0b

23
struct ich_spi_platdata {
S
Simon Glass 已提交
24 25
	pci_dev_t dev;		/* PCI device number */
	int ich_version;	/* Controller version, 7 or 9 */
26
	bool use_sbase;		/* Use SBASE instead of RCB */
27 28 29
};

struct ich_spi_priv {
S
Simon Glass 已提交
30 31
	int ichspi_lock;
	int locked;
32
	int opmenu;
S
Simon Glass 已提交
33 34
	int menubytes;
	void *base;		/* Base of register set */
35 36 37 38
	int preop;
	int optype;
	int addr;
	int data;
S
Simon Glass 已提交
39
	unsigned databytes;
40 41 42
	int status;
	int control;
	int bbar;
S
Simon Glass 已提交
43
	uint32_t *pr;		/* only for ich9 */
44
	int speed;		/* pointer to speed control */
S
Simon Glass 已提交
45
	ulong max_speed;	/* Maximum bus speed in MHz */
46 47
	ulong cur_speed;	/* Current bus speed */
	struct spi_trans trans;	/* current transaction in progress */
S
Simon Glass 已提交
48 49
};

50
static u8 ich_readb(struct ich_spi_priv *priv, int reg)
S
Simon Glass 已提交
51
{
52
	u8 value = readb(priv->base + reg);
S
Simon Glass 已提交
53

54
	debug("read %2.2x from %4.4x\n", value, reg);
S
Simon Glass 已提交
55 56 57 58

	return value;
}

59
static u16 ich_readw(struct ich_spi_priv *priv, int reg)
S
Simon Glass 已提交
60
{
61
	u16 value = readw(priv->base + reg);
S
Simon Glass 已提交
62

63
	debug("read %4.4x from %4.4x\n", value, reg);
S
Simon Glass 已提交
64 65 66 67

	return value;
}

68
static u32 ich_readl(struct ich_spi_priv *priv, int reg)
S
Simon Glass 已提交
69
{
70
	u32 value = readl(priv->base + reg);
S
Simon Glass 已提交
71

72
	debug("read %8.8x from %4.4x\n", value, reg);
S
Simon Glass 已提交
73 74 75 76

	return value;
}

77
static void ich_writeb(struct ich_spi_priv *priv, u8 value, int reg)
S
Simon Glass 已提交
78
{
79 80
	writeb(value, priv->base + reg);
	debug("wrote %2.2x to %4.4x\n", value, reg);
S
Simon Glass 已提交
81 82
}

83
static void ich_writew(struct ich_spi_priv *priv, u16 value, int reg)
S
Simon Glass 已提交
84
{
85 86
	writew(value, priv->base + reg);
	debug("wrote %4.4x to %4.4x\n", value, reg);
S
Simon Glass 已提交
87 88
}

89
static void ich_writel(struct ich_spi_priv *priv, u32 value, int reg)
S
Simon Glass 已提交
90
{
91 92
	writel(value, priv->base + reg);
	debug("wrote %8.8x to %4.4x\n", value, reg);
S
Simon Glass 已提交
93 94
}

95 96
static void write_reg(struct ich_spi_priv *priv, const void *value,
		      int dest_reg, uint32_t size)
S
Simon Glass 已提交
97
{
98
	memcpy_toio(priv->base + dest_reg, value, size);
S
Simon Glass 已提交
99 100
}

101 102
static void read_reg(struct ich_spi_priv *priv, int src_reg, void *value,
		     uint32_t size)
S
Simon Glass 已提交
103
{
104
	memcpy_fromio(value, priv->base + src_reg, size);
S
Simon Glass 已提交
105 106
}

107
static void ich_set_bbar(struct ich_spi_priv *ctlr, uint32_t minaddr)
S
Simon Glass 已提交
108 109 110 111 112
{
	const uint32_t bbar_mask = 0x00ffff00;
	uint32_t ichspi_bbar;

	minaddr &= bbar_mask;
113
	ichspi_bbar = ich_readl(ctlr, ctlr->bbar) & ~bbar_mask;
S
Simon Glass 已提交
114
	ichspi_bbar |= minaddr;
115
	ich_writel(ctlr, ichspi_bbar, ctlr->bbar);
S
Simon Glass 已提交
116 117 118 119 120 121 122 123 124
}

/*
 * Check if this device ID matches one of supported Intel PCH devices.
 *
 * Return the ICH version if there is a match, or zero otherwise.
 */
static int get_ich_version(uint16_t device_id)
{
125
	if (device_id == PCI_DEVICE_ID_INTEL_TGP_LPC ||
B
Bin Meng 已提交
126 127
	    device_id == PCI_DEVICE_ID_INTEL_ITC_LPC ||
	    device_id == PCI_DEVICE_ID_INTEL_QRK_ILB)
S
Simon Glass 已提交
128 129 130 131 132
		return 7;

	if ((device_id >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
	     device_id <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX) ||
	    (device_id >= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN &&
133
	     device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX) ||
134 135
	    device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC ||
	    device_id == PCI_DEVICE_ID_INTEL_LYNXPOINT_LPC)
S
Simon Glass 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
		return 9;

	return 0;
}

/* @return 1 if the SPI flash supports the 33MHz speed */
static int ich9_can_do_33mhz(pci_dev_t dev)
{
	u32 fdod, speed;

	/* Observe SPI Descriptor Component Section 0 */
	pci_write_config_dword(dev, 0xb0, 0x1000);

	/* Extract the Write/Erase SPI Frequency from descriptor */
	pci_read_config_dword(dev, 0xb4, &fdod);

	/* Bits 23:21 have the fast read clock frequency, 0=20MHz, 1=33MHz */
	speed = (fdod >> 21) & 7;

	return speed == 1;
}

158
static int ich_find_spi_controller(struct ich_spi_platdata *ich)
S
Simon Glass 已提交
159 160 161 162 163 164
{
	int last_bus = pci_last_busno();
	int bus;

	if (last_bus == -1) {
		debug("No PCI busses?\n");
165
		return -ENODEV;
S
Simon Glass 已提交
166 167 168 169 170 171 172 173 174 175 176 177 178
	}

	for (bus = 0; bus <= last_bus; bus++) {
		uint16_t vendor_id, device_id;
		uint32_t ids;
		pci_dev_t dev;

		dev = PCI_BDF(bus, 31, 0);
		pci_read_config_dword(dev, 0, &ids);
		vendor_id = ids;
		device_id = ids >> 16;

		if (vendor_id == PCI_VENDOR_ID_INTEL) {
179 180 181 182 183
			ich->dev = dev;
			ich->ich_version = get_ich_version(device_id);
			if (device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
				ich->use_sbase = true;
			return ich->ich_version == 0 ? -ENODEV : 0;
S
Simon Glass 已提交
184 185 186 187
		}
	}

	debug("ICH SPI: No ICH found.\n");
188
	return -ENODEV;
S
Simon Glass 已提交
189 190
}

191 192
static int ich_init_controller(struct ich_spi_platdata *plat,
			       struct ich_spi_priv *ctlr)
S
Simon Glass 已提交
193 194 195
{
	uint8_t *rcrb; /* Root Complex Register Block */
	uint32_t rcba; /* Root Complex Base Address */
196 197
	uint32_t sbase_addr;
	uint8_t *sbase;
S
Simon Glass 已提交
198

199
	pci_read_config_dword(plat->dev, 0xf0, &rcba);
S
Simon Glass 已提交
200 201
	/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */
	rcrb = (uint8_t *)(rcba & 0xffffc000);
202 203

	/* SBASE is similar */
204
	pci_read_config_dword(plat->dev, 0x54, &sbase_addr);
205 206
	sbase = (uint8_t *)(sbase_addr & 0xfffffe00);

207
	if (plat->ich_version == 7) {
S
Simon Glass 已提交
208 209 210
		struct ich7_spi_regs *ich7_spi;

		ich7_spi = (struct ich7_spi_regs *)(rcrb + 0x3020);
211 212
		ctlr->ichspi_lock = readw(&ich7_spi->spis) & SPIS_LOCK;
		ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
S
Simon Glass 已提交
213
		ctlr->menubytes = sizeof(ich7_spi->opmenu);
214 215 216
		ctlr->optype = offsetof(struct ich7_spi_regs, optype);
		ctlr->addr = offsetof(struct ich7_spi_regs, spia);
		ctlr->data = offsetof(struct ich7_spi_regs, spid);
S
Simon Glass 已提交
217
		ctlr->databytes = sizeof(ich7_spi->spid);
218 219 220 221
		ctlr->status = offsetof(struct ich7_spi_regs, spis);
		ctlr->control = offsetof(struct ich7_spi_regs, spic);
		ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
		ctlr->preop = offsetof(struct ich7_spi_regs, preop);
S
Simon Glass 已提交
222
		ctlr->base = ich7_spi;
223
	} else if (plat->ich_version == 9) {
S
Simon Glass 已提交
224 225
		struct ich9_spi_regs *ich9_spi;

226
		if (plat->use_sbase)
227 228 229
			ich9_spi = (struct ich9_spi_regs *)sbase;
		else
			ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
230 231
		ctlr->ichspi_lock = readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
		ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
S
Simon Glass 已提交
232
		ctlr->menubytes = sizeof(ich9_spi->opmenu);
233 234 235
		ctlr->optype = offsetof(struct ich9_spi_regs, optype);
		ctlr->addr = offsetof(struct ich9_spi_regs, faddr);
		ctlr->data = offsetof(struct ich9_spi_regs, fdata);
S
Simon Glass 已提交
236
		ctlr->databytes = sizeof(ich9_spi->fdata);
237 238 239 240 241
		ctlr->status = offsetof(struct ich9_spi_regs, ssfs);
		ctlr->control = offsetof(struct ich9_spi_regs, ssfc);
		ctlr->speed = ctlr->control + 2;
		ctlr->bbar = offsetof(struct ich9_spi_regs, bbar);
		ctlr->preop = offsetof(struct ich9_spi_regs, preop);
S
Simon Glass 已提交
242 243 244
		ctlr->pr = &ich9_spi->pr[0];
		ctlr->base = ich9_spi;
	} else {
245 246 247
		debug("ICH SPI: Unrecognised ICH version %d\n",
		      plat->ich_version);
		return -EINVAL;
S
Simon Glass 已提交
248 249 250 251
	}

	/* Work out the maximum speed we can support */
	ctlr->max_speed = 20000000;
252
	if (plat->ich_version == 9 && ich9_can_do_33mhz(plat->dev))
S
Simon Glass 已提交
253
		ctlr->max_speed = 33000000;
254
	debug("ICH SPI: Version %d detected at %p, speed %ld\n",
255
	      plat->ich_version, ctlr->base, ctlr->max_speed);
S
Simon Glass 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306

	ich_set_bbar(ctlr, 0);

	return 0;
}

static inline void spi_use_out(struct spi_trans *trans, unsigned bytes)
{
	trans->out += bytes;
	trans->bytesout -= bytes;
}

static inline void spi_use_in(struct spi_trans *trans, unsigned bytes)
{
	trans->in += bytes;
	trans->bytesin -= bytes;
}

static void spi_setup_type(struct spi_trans *trans, int data_bytes)
{
	trans->type = 0xFF;

	/* Try to guess spi type from read/write sizes. */
	if (trans->bytesin == 0) {
		if (trans->bytesout + data_bytes > 4)
			/*
			 * If bytesin = 0 and bytesout > 4, we presume this is
			 * a write data operation, which is accompanied by an
			 * address.
			 */
			trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
		else
			trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
		return;
	}

	if (trans->bytesout == 1) {	/* and bytesin is > 0 */
		trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
		return;
	}

	if (trans->bytesout == 4)	/* and bytesin is > 0 */
		trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;

	/* Fast read command is called with 5 bytes instead of 4 */
	if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) {
		trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
		--trans->bytesout;
	}
}

307
static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans)
S
Simon Glass 已提交
308 309
{
	uint16_t optypes;
310
	uint8_t opmenu[ctlr->menubytes];
S
Simon Glass 已提交
311 312 313

	trans->opcode = trans->out[0];
	spi_use_out(trans, 1);
314
	if (!ctlr->ichspi_lock) {
S
Simon Glass 已提交
315
		/* The lock is off, so just use index 0. */
316 317
		ich_writeb(ctlr, trans->opcode, ctlr->opmenu);
		optypes = ich_readw(ctlr, ctlr->optype);
S
Simon Glass 已提交
318
		optypes = (optypes & 0xfffc) | (trans->type & 0x3);
319
		ich_writew(ctlr, optypes, ctlr->optype);
S
Simon Glass 已提交
320 321 322 323 324 325 326 327 328 329
		return 0;
	} else {
		/* The lock is on. See if what we need is on the menu. */
		uint8_t optype;
		uint16_t opcode_index;

		/* Write Enable is handled as atomic prefix */
		if (trans->opcode == SPI_OPCODE_WREN)
			return 0;

330 331
		read_reg(ctlr, ctlr->opmenu, opmenu, sizeof(opmenu));
		for (opcode_index = 0; opcode_index < ctlr->menubytes;
S
Simon Glass 已提交
332 333 334 335 336
				opcode_index++) {
			if (opmenu[opcode_index] == trans->opcode)
				break;
		}

337
		if (opcode_index == ctlr->menubytes) {
S
Simon Glass 已提交
338 339
			printf("ICH SPI: Opcode %x not found\n",
			       trans->opcode);
340
			return -EINVAL;
S
Simon Glass 已提交
341 342
		}

343
		optypes = ich_readw(ctlr, ctlr->optype);
S
Simon Glass 已提交
344 345 346 347 348 349 350 351 352 353
		optype = (optypes >> (opcode_index * 2)) & 0x3;
		if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS &&
		    optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS &&
		    trans->bytesout >= 3) {
			/* We guessed wrong earlier. Fix it up. */
			trans->type = optype;
		}
		if (optype != trans->type) {
			printf("ICH SPI: Transaction doesn't fit type %d\n",
			       optype);
354
			return -ENOSPC;
S
Simon Glass 已提交
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
		}
		return opcode_index;
	}
}

static int spi_setup_offset(struct spi_trans *trans)
{
	/* Separate the SPI address and data. */
	switch (trans->type) {
	case SPI_OPCODE_TYPE_READ_NO_ADDRESS:
	case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS:
		return 0;
	case SPI_OPCODE_TYPE_READ_WITH_ADDRESS:
	case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS:
		trans->offset = ((uint32_t)trans->out[0] << 16) |
				((uint32_t)trans->out[1] << 8) |
				((uint32_t)trans->out[2] << 0);
		spi_use_out(trans, 3);
		return 1;
	default:
		printf("Unrecognized SPI transaction type %#x\n", trans->type);
376
		return -EPROTO;
S
Simon Glass 已提交
377 378 379 380 381
	}
}

/*
 * Wait for up to 6s til status register bit(s) turn 1 (in case wait_til_set
Y
York Sun 已提交
382
 * below is true) or 0. In case the wait was for the bit(s) to set - write
S
Simon Glass 已提交
383 384 385 386
 * those bits back, which would cause resetting them.
 *
 * Return the last read status value on success or -1 on failure.
 */
387 388
static int ich_status_poll(struct ich_spi_priv *ctlr, u16 bitmask,
			   int wait_til_set)
S
Simon Glass 已提交
389 390 391 392 393
{
	int timeout = 600000; /* This will result in 6s */
	u16 status = 0;

	while (timeout--) {
394
		status = ich_readw(ctlr, ctlr->status);
S
Simon Glass 已提交
395
		if (wait_til_set ^ ((status & bitmask) == 0)) {
396 397 398 399
			if (wait_til_set) {
				ich_writew(ctlr, status & bitmask,
					   ctlr->status);
			}
S
Simon Glass 已提交
400 401 402 403 404 405 406
			return status;
		}
		udelay(10);
	}

	printf("ICH SPI: SCIP timeout, read %x, expected %x\n",
	       status, bitmask);
407
	return -ETIMEDOUT;
S
Simon Glass 已提交
408 409
}

410 411
static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
			const void *dout, void *din, unsigned long flags)
S
Simon Glass 已提交
412
{
413
	struct udevice *bus = dev_get_parent(dev);
414
	struct ich_spi_platdata *plat = dev_get_platdata(bus);
415
	struct ich_spi_priv *ctlr = dev_get_priv(bus);
S
Simon Glass 已提交
416 417 418 419 420
	uint16_t control;
	int16_t opcode_index;
	int with_address;
	int status;
	int bytes = bitlen / 8;
421
	struct spi_trans *trans = &ctlr->trans;
S
Simon Glass 已提交
422 423
	unsigned type = flags & (SPI_XFER_BEGIN | SPI_XFER_END);
	int using_cmd = 0;
424
	int ret;
S
Simon Glass 已提交
425

426
	/* We don't support writing partial bytes */
S
Simon Glass 已提交
427 428
	if (bitlen % 8) {
		debug("ICH SPI: Accessing partial bytes not supported\n");
429
		return -EPROTONOSUPPORT;
S
Simon Glass 已提交
430 431 432 433 434 435 436 437 438 439 440 441 442
	}

	/* An empty end transaction can be ignored */
	if (type == SPI_XFER_END && !dout && !din)
		return 0;

	if (type & SPI_XFER_BEGIN)
		memset(trans, '\0', sizeof(*trans));

	/* Dp we need to come back later to finish it? */
	if (dout && type == SPI_XFER_BEGIN) {
		if (bytes > ICH_MAX_CMD_LEN) {
			debug("ICH SPI: Command length limit exceeded\n");
443
			return -ENOSPC;
S
Simon Glass 已提交
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
		}
		memcpy(trans->cmd, dout, bytes);
		trans->cmd_len = bytes;
		debug("ICH SPI: Saved %d bytes\n", bytes);
		return 0;
	}

	/*
	 * We process a 'middle' spi_xfer() call, which has no
	 * SPI_XFER_BEGIN/END, as an independent transaction as if it had
	 * an end. We therefore repeat the command. This is because ICH
	 * seems to have no support for this, or because interest (in digging
	 * out the details and creating a special case in the code) is low.
	 */
	if (trans->cmd_len) {
		trans->out = trans->cmd;
		trans->bytesout = trans->cmd_len;
		using_cmd = 1;
		debug("ICH SPI: Using %d bytes\n", trans->cmd_len);
	} else {
		trans->out = dout;
		trans->bytesout = dout ? bytes : 0;
	}

	trans->in = din;
	trans->bytesin = din ? bytes : 0;

	/* There has to always at least be an opcode. */
	if (!trans->bytesout) {
		debug("ICH SPI: No opcode for transfer\n");
474
		return -EPROTO;
S
Simon Glass 已提交
475 476
	}

477 478 479
	ret = ich_status_poll(ctlr, SPIS_SCIP, 0);
	if (ret < 0)
		return ret;
S
Simon Glass 已提交
480

481 482 483 484
	if (plat->ich_version == 7)
		ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
	else
		ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
S
Simon Glass 已提交
485 486

	spi_setup_type(trans, using_cmd ? bytes : 0);
487
	opcode_index = spi_setup_opcode(ctlr, trans);
S
Simon Glass 已提交
488
	if (opcode_index < 0)
489
		return -EINVAL;
S
Simon Glass 已提交
490 491
	with_address = spi_setup_offset(trans);
	if (with_address < 0)
492
		return -EINVAL;
S
Simon Glass 已提交
493 494 495 496 497 498 499

	if (trans->opcode == SPI_OPCODE_WREN) {
		/*
		 * Treat Write Enable as Atomic Pre-Op if possible
		 * in order to prevent the Management Engine from
		 * issuing a transaction between WREN and DATA.
		 */
500 501
		if (!ctlr->ichspi_lock)
			ich_writew(ctlr, trans->opcode, ctlr->preop);
S
Simon Glass 已提交
502 503 504
		return 0;
	}

505
	if (ctlr->speed && ctlr->max_speed >= 33000000) {
S
Simon Glass 已提交
506 507
		int byte;

508 509
		byte = ich_readb(ctlr, ctlr->speed);
		if (ctlr->cur_speed >= 33000000)
S
Simon Glass 已提交
510 511 512
			byte |= SSFC_SCF_33MHZ;
		else
			byte &= ~SSFC_SCF_33MHZ;
513
		ich_writeb(ctlr, byte, ctlr->speed);
S
Simon Glass 已提交
514 515 516 517 518 519 520 521 522 523
	}

	/* See if we have used up the command data */
	if (using_cmd && dout && bytes) {
		trans->out = dout;
		trans->bytesout = bytes;
		debug("ICH SPI: Moving to data, %d bytes\n", bytes);
	}

	/* Preset control fields */
524
	control = ich_readw(ctlr, ctlr->control);
S
Simon Glass 已提交
525 526 527 528
	control &= ~SSFC_RESERVED;
	control = SPIC_SCGO | ((opcode_index & 0x07) << 4);

	/* Issue atomic preop cycle if needed */
529
	if (ich_readw(ctlr, ctlr->preop))
S
Simon Glass 已提交
530 531 532 533
		control |= SPIC_ACS;

	if (!trans->bytesout && !trans->bytesin) {
		/* SPI addresses are 24 bit only */
534 535 536 537
		if (with_address) {
			ich_writel(ctlr, trans->offset & 0x00FFFFFF,
				   ctlr->addr);
		}
S
Simon Glass 已提交
538 539 540 541 542 543
		/*
		 * This is a 'no data' command (like Write Enable), its
		 * bitesout size was 1, decremented to zero while executing
		 * spi_setup_opcode() above. Tell the chip to send the
		 * command.
		 */
544
		ich_writew(ctlr, control, ctlr->control);
S
Simon Glass 已提交
545 546

		/* wait for the result */
547 548 549
		status = ich_status_poll(ctlr, SPIS_CDS | SPIS_FCERR, 1);
		if (status < 0)
			return status;
S
Simon Glass 已提交
550 551 552

		if (status & SPIS_FCERR) {
			debug("ICH SPI: Command transaction error\n");
553
			return -EIO;
S
Simon Glass 已提交
554 555 556 557 558 559 560 561 562 563 564 565
		}

		return 0;
	}

	/*
	 * Check if this is a write command atempting to transfer more bytes
	 * than the controller can handle. Iterations for writes are not
	 * supported here because each SPI write command needs to be preceded
	 * and followed by other SPI commands, and this sequence is controlled
	 * by the SPI chip driver.
	 */
566
	if (trans->bytesout > ctlr->databytes) {
S
Simon Glass 已提交
567
		debug("ICH SPI: Too much to write. This should be prevented by the driver's max_write_size?\n");
568
		return -EPROTO;
S
Simon Glass 已提交
569 570 571 572 573 574 575 576 577 578
	}

	/*
	 * Read or write up to databytes bytes at a time until everything has
	 * been sent.
	 */
	while (trans->bytesout || trans->bytesin) {
		uint32_t data_length;

		/* SPI addresses are 24 bit only */
579
		ich_writel(ctlr, trans->offset & 0x00FFFFFF, ctlr->addr);
S
Simon Glass 已提交
580 581

		if (trans->bytesout)
582
			data_length = min(trans->bytesout, ctlr->databytes);
S
Simon Glass 已提交
583
		else
584
			data_length = min(trans->bytesin, ctlr->databytes);
S
Simon Glass 已提交
585 586 587

		/* Program data into FDATA0 to N */
		if (trans->bytesout) {
588
			write_reg(ctlr, trans->out, ctlr->data, data_length);
S
Simon Glass 已提交
589 590 591 592 593 594
			spi_use_out(trans, data_length);
			if (with_address)
				trans->offset += data_length;
		}

		/* Add proper control fields' values */
595
		control &= ~((ctlr->databytes - 1) << 8);
S
Simon Glass 已提交
596 597 598 599
		control |= SPIC_DS;
		control |= (data_length - 1) << 8;

		/* write it */
600
		ich_writew(ctlr, control, ctlr->control);
S
Simon Glass 已提交
601 602

		/* Wait for Cycle Done Status or Flash Cycle Error. */
603 604 605
		status = ich_status_poll(ctlr, SPIS_CDS | SPIS_FCERR, 1);
		if (status < 0)
			return status;
S
Simon Glass 已提交
606 607

		if (status & SPIS_FCERR) {
608
			debug("ICH SPI: Data transaction error %x\n", status);
609
			return -EIO;
S
Simon Glass 已提交
610 611 612
		}

		if (trans->bytesin) {
613
			read_reg(ctlr, ctlr->data, trans->in, data_length);
S
Simon Glass 已提交
614 615 616 617 618 619 620
			spi_use_in(trans, data_length);
			if (with_address)
				trans->offset += data_length;
		}
	}

	/* Clear atomic preop now that xfer is done */
621
	ich_writew(ctlr, 0, ctlr->preop);
S
Simon Glass 已提交
622 623 624 625 626 627 628 629 630 631

	return 0;
}

/*
 * This uses the SPI controller from the Intel Cougar Point and Panther Point
 * PCH to write-protect portions of the SPI flash until reboot. The changes
 * don't actually take effect until the HSFS[FLOCKDN] bit is set, but that's
 * done elsewhere.
 */
632 633
int spi_write_protect_region(struct udevice *dev, uint32_t lower_limit,
			     uint32_t length, int hint)
S
Simon Glass 已提交
634
{
635 636
	struct udevice *bus = dev->parent;
	struct ich_spi_priv *ctlr = dev_get_priv(bus);
S
Simon Glass 已提交
637 638 639
	uint32_t tmplong;
	uint32_t upper_limit;

640
	if (!ctlr->pr) {
S
Simon Glass 已提交
641 642
		printf("%s: operation not supported on this chipset\n",
		       __func__);
643
		return -ENOSYS;
S
Simon Glass 已提交
644 645 646 647 648 649 650
	}

	if (length == 0 ||
	    lower_limit > (0xFFFFFFFFUL - length) + 1 ||
	    hint < 0 || hint > 4) {
		printf("%s(0x%x, 0x%x, %d): invalid args\n", __func__,
		       lower_limit, length, hint);
651
		return -EPERM;
S
Simon Glass 已提交
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
	}

	upper_limit = lower_limit + length - 1;

	/*
	 * Determine bits to write, as follows:
	 *  31     Write-protection enable (includes erase operation)
	 *  30:29  reserved
	 *  28:16  Upper Limit (FLA address bits 24:12, with 11:0 == 0xfff)
	 *  15     Read-protection enable
	 *  14:13  reserved
	 *  12:0   Lower Limit (FLA address bits 24:12, with 11:0 == 0x000)
	 */
	tmplong = 0x80000000 |
		((upper_limit & 0x01fff000) << 4) |
		((lower_limit & 0x01fff000) >> 12);

	printf("%s: writing 0x%08x to %p\n", __func__, tmplong,
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
	       &ctlr->pr[hint]);
	ctlr->pr[hint] = tmplong;

	return 0;
}

static int ich_spi_probe(struct udevice *bus)
{
	struct ich_spi_platdata *plat = dev_get_platdata(bus);
	struct ich_spi_priv *priv = dev_get_priv(bus);
	uint8_t bios_cntl;
	int ret;

	ret = ich_init_controller(plat, priv);
	if (ret)
		return ret;
	/*
	 * Disable the BIOS write protect so write commands are allowed.  On
	 * v9, deassert SMM BIOS Write Protect Disable.
	 */
	if (plat->use_sbase) {
		struct ich9_spi_regs *ich9_spi;

		ich9_spi = priv->base;
		bios_cntl = ich_readb(priv, ich9_spi->bcr);
		bios_cntl &= ~(1 << 5);	/* clear Enable InSMM_STS (EISS) */
		bios_cntl |= 1;		/* Write Protect Disable (WPD) */
		ich_writeb(priv, bios_cntl, ich9_spi->bcr);
	} else {
		pci_read_config_byte(plat->dev, 0xdc, &bios_cntl);
		if (plat->ich_version == 9)
			bios_cntl &= ~(1 << 5);
		pci_write_config_byte(plat->dev, 0xdc, bios_cntl | 0x1);
	}

	priv->cur_speed = priv->max_speed;

	return 0;
}

static int ich_spi_ofdata_to_platdata(struct udevice *bus)
{
	struct ich_spi_platdata *plat = dev_get_platdata(bus);
	int ret;

	ret = ich_find_spi_controller(plat);
	if (ret)
		return ret;
S
Simon Glass 已提交
718 719 720

	return 0;
}
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787

static int ich_spi_set_speed(struct udevice *bus, uint speed)
{
	struct ich_spi_priv *priv = dev_get_priv(bus);

	priv->cur_speed = speed;

	return 0;
}

static int ich_spi_set_mode(struct udevice *bus, uint mode)
{
	debug("%s: mode=%d\n", __func__, mode);

	return 0;
}

static int ich_spi_child_pre_probe(struct udevice *dev)
{
	struct udevice *bus = dev_get_parent(dev);
	struct ich_spi_platdata *plat = dev_get_platdata(bus);
	struct ich_spi_priv *priv = dev_get_priv(bus);
	struct spi_slave *slave = dev_get_parentdata(dev);

	/*
	 * Yes this controller can only write a small number of bytes at
	 * once! The limit is typically 64 bytes.
	 */
	slave->max_write_size = priv->databytes;
	/*
	 * ICH 7 SPI controller only supports array read command
	 * and byte program command for SST flash
	 */
	if (plat->ich_version == 7) {
		slave->op_mode_rx = SPI_OPM_RX_AS;
		slave->op_mode_tx = SPI_OPM_TX_BP;
	}

	return 0;
}

static const struct dm_spi_ops ich_spi_ops = {
	.xfer		= ich_spi_xfer,
	.set_speed	= ich_spi_set_speed,
	.set_mode	= ich_spi_set_mode,
	/*
	 * cs_info is not needed, since we require all chip selects to be
	 * in the device tree explicitly
	 */
};

static const struct udevice_id ich_spi_ids[] = {
	{ .compatible = "intel,ich-spi" },
	{ }
};

U_BOOT_DRIVER(ich_spi) = {
	.name	= "ich_spi",
	.id	= UCLASS_SPI,
	.of_match = ich_spi_ids,
	.ops	= &ich_spi_ops,
	.ofdata_to_platdata = ich_spi_ofdata_to_platdata,
	.platdata_auto_alloc_size = sizeof(struct ich_spi_platdata),
	.priv_auto_alloc_size = sizeof(struct ich_spi_priv),
	.child_pre_probe = ich_spi_child_pre_probe,
	.probe	= ich_spi_probe,
};