spi.c 11.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2007 Carl-Daniel Hailfinger
 *
 * 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; version 2 of the License.
 *
 * 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
 */

/*
 * Contains the generic SPI framework
 */

#include <stdio.h>
#include <pci/pci.h>
#include <stdint.h>
#include <string.h>
#include "flash.h"

#define ITE_SUPERIO_PORT1	0x2e
#define ITE_SUPERIO_PORT2	0x4e

33
/* Read Electronic ID */
34 35 36 37
#define JEDEC_RDID	{0x9f}
#define JEDEC_RDID_OUTSIZE	0x01
#define JEDEC_RDID_INSIZE	0x03

38 39 40 41 42 43 44 45 46 47
/* Write Enable */
#define JEDEC_WREN	{0x06}
#define JEDEC_WREN_OUTSIZE	0x01
#define JEDEC_WREN_INSIZE	0x00

/* Write Disable */
#define JEDEC_WRDI	{0x04}
#define JEDEC_WRDI_OUTSIZE	0x01
#define JEDEC_WRDI_INSIZE	0x00

48
/* Chip Erase 0x60 is supported by Macronix/SST chips. */
49 50 51
#define JEDEC_CE_60	{0x60};
#define JEDEC_CE_60_OUTSIZE	0x01
#define JEDEC_CE_60_INSIZE	0x00
52

53 54 55 56
/* Chip Erase 0xc7 is supported by ST/EON/Macronix chips. */
#define JEDEC_CE_C7	{0xc7};
#define JEDEC_CE_C7_OUTSIZE	0x01
#define JEDEC_CE_C7_INSIZE	0x00
57

58
/* Block Erase 0x52 is supported by SST chips. */
59 60 61
#define JEDEC_BE_52	{0x52};
#define JEDEC_BE_52_OUTSIZE	0x04
#define JEDEC_BE_52_INSIZE	0x00
62 63

/* Block Erase 0xd8 is supported by EON/Macronix chips. */
64 65 66
#define JEDEC_BE_D8	{0xd8};
#define JEDEC_BE_D8_OUTSIZE	0x04
#define JEDEC_BE_D8_INSIZE	0x00
67 68 69 70 71 72

/* Sector Erase 0x20 is supported by Macronix/SST chips. */
#define JEDEC_SE	{0x20};
#define JEDEC_SE_OUTSIZE	0x04
#define JEDEC_SE_INSIZE	0x00

73 74 75 76 77 78 79
/* Read Status Register */
#define JEDEC_RDSR	{0x05};
#define JEDEC_RDSR_OUTSIZE	0x01
#define JEDEC_RDSR_INSIZE	0x01
#define JEDEC_RDSR_BIT_WIP	(0x01 << 0)

uint16_t it8716f_flashport = 0;
80

81 82
void generic_spi_prettyprint_status_register(struct flashchip *flash);

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
/* Generic Super I/O helper functions */
uint8_t regval(uint16_t port, uint8_t reg)
{
	outb(reg, port);
	return inb(port + 1);
}

void regwrite(uint16_t port, uint8_t reg, uint8_t val)
{
	outb(reg, port);
	outb(val, port + 1);
}

/* Helper functions for most recent ITE IT87xx Super I/O chips */
#define CHIP_ID_BYTE1_REG	0x20
#define CHIP_ID_BYTE2_REG	0x21
static void enter_conf_mode_ite(uint16_t port)
{
	outb(0x87, port);
	outb(0x01, port);
	outb(0x55, port);
	if (port == ITE_SUPERIO_PORT1)
		outb(0x55, port);
	else
		outb(0xaa, port);
}

static void exit_conf_mode_ite(uint16_t port)
{
	regwrite(port, 0x02, 0x02);
}

115
static uint16_t find_ite_spi_flash_port(uint16_t port)
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
{
	uint8_t tmp = 0;
	uint16_t id, flashport = 0;

	enter_conf_mode_ite(port);

	id = regval(port, CHIP_ID_BYTE1_REG) << 8;
	id |= regval(port, CHIP_ID_BYTE2_REG);

	/* TODO: Handle more IT87xx if they support flash translation */
	if (id == 0x8716) {
		/* NOLDN, reg 0x24, mask out lowest bit (suspend) */
		tmp = regval(port, 0x24) & 0xFE;
		printf("Serial flash segment 0x%08x-0x%08x %sabled\n",
			0xFFFE0000, 0xFFFFFFFF, (tmp & 1 << 1) ? "en" : "dis");
		printf("Serial flash segment 0x%08x-0x%08x %sabled\n",
			0x000E0000, 0x000FFFFF, (tmp & 1 << 1) ? "en" : "dis");
		printf("Serial flash segment 0x%08x-0x%08x %sabled\n",
			0xFFEE0000, 0xFFEFFFFF, (tmp & 1 << 2) ? "en" : "dis");
		printf("Serial flash segment 0x%08x-0x%08x %sabled\n",
			0xFFF80000, 0xFFFEFFFF, (tmp & 1 << 3) ? "en" : "dis");
		printf("LPC write to serial flash %sabled\n",
			(tmp & 1 << 4) ? "en" : "dis");
		printf("serial flash pin %i\n",	(tmp & 1 << 5) ? 87 : 29);
		/* LDN 0x7, reg 0x64/0x65 */
		regwrite(port, 0x07, 0x7);
		flashport = regval(port, 0x64) << 8;
		flashport |= regval(port, 0x65);
	}
	exit_conf_mode_ite(port);
	return flashport;
}

149 150 151 152 153 154 155 156
int it87xx_probe_spi_flash(const char *name)
{
	it8716f_flashport = find_ite_spi_flash_port(ITE_SUPERIO_PORT1);
	if (!it8716f_flashport)
		it8716f_flashport = find_ite_spi_flash_port(ITE_SUPERIO_PORT2);
	return (!it8716f_flashport);
}

157 158 159 160 161 162
/* The IT8716F only supports commands with length 1,2,4,5 bytes including
   command byte and can not read more than 3 bytes from the device.
   This function expects writearr[0] to be the first byte sent to the device,
   whereas the IT8716F splits commands internally into address and non-address
   commands with the address in inverse wire order. That's why the register
   ordering in case 4 and 5 may seem strange. */
163
static int it8716f_spi_command(uint16_t port, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr)
164 165
{
	uint8_t busy, writeenc;
166 167
	int i;

168 169 170 171
	do {
		busy = inb(port) & 0x80;
	} while (busy);
	if (readcnt > 3) {
172
		printf("%s called with unsupported readcnt %i.\n",
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
			__FUNCTION__, readcnt);
		return 1;
	}
	switch (writecnt) {
	case 1:
		outb(writearr[0], port + 1);
		writeenc = 0x0;
		break;
	case 2:
		outb(writearr[0], port + 1);
		outb(writearr[1], port + 7);
		writeenc = 0x1;
		break;
	case 4:
		outb(writearr[0], port + 1);
		outb(writearr[1], port + 4);
		outb(writearr[2], port + 3);
		outb(writearr[3], port + 2);
		writeenc = 0x2;
		break;
	case 5:
		outb(writearr[0], port + 1);
		outb(writearr[1], port + 4);
		outb(writearr[2], port + 3);
		outb(writearr[3], port + 2);
		outb(writearr[4], port + 7);
		writeenc = 0x3;
		break;
	default:
202
		printf("%s called with unsupported writecnt %i.\n",
203 204 205 206
			__FUNCTION__, writecnt);
		return 1;
	}
	/* Start IO, 33MHz, readcnt input bytes, writecnt output bytes. Note:
207
	 * We can't use writecnt directly, but have to use a strange encoding.
208 209 210 211 212
	 */ 
	outb((0x5 << 4) | ((readcnt & 0x3) << 2) | (writeenc), port);
	do {
		busy = inb(port) & 0x80;
	} while (busy);
213 214 215 216 217

	for (i = 0; i < readcnt; i++) {
		readarr[i] = inb(port + 5 + i);
	}

218 219 220
	return 0;
}

221
int generic_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr)
222 223 224
{
	if (it8716f_flashport)
		return it8716f_spi_command(it8716f_flashport, writecnt, readcnt, writearr, readarr);
225
	printf_debug("%s called, but no SPI chipset detected\n", __FUNCTION__);
226 227 228 229
	return 1;
}

static int generic_spi_rdid(unsigned char *readarr)
230 231 232
{
	const unsigned char cmd[] = JEDEC_RDID;

233
	if (generic_spi_command(JEDEC_RDID_OUTSIZE, JEDEC_RDID_INSIZE, cmd, readarr))
234
		return 1;
235
	printf_debug("RDID returned %02x %02x %02x.\n", readarr[0], readarr[1], readarr[2]);
236 237 238
	return 0;
}

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
void generic_spi_write_enable()
{
	const unsigned char cmd[] = JEDEC_WREN;

	/* Send WREN (Write Enable) */
	generic_spi_command(JEDEC_WREN_OUTSIZE, JEDEC_WREN_INSIZE, cmd, NULL);

}

void generic_spi_write_disable()
{
	const unsigned char cmd[] = JEDEC_WRDI;

	/* Send WRDI (Write Disable) */
	generic_spi_command(JEDEC_WRDI_OUTSIZE, JEDEC_WRDI_INSIZE, cmd, NULL);
}

256 257 258 259 260
int probe_spi(struct flashchip *flash)
{
	unsigned char readarr[3];
	uint8_t manuf_id;
	uint16_t model_id;
261
	if (!generic_spi_rdid(readarr)) {
262 263 264
		manuf_id = readarr[0];
		model_id = (readarr[1] << 8) | readarr[2];
		printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, manuf_id, model_id);
265 266 267
		if (manuf_id == flash->manufacture_id &&
		    model_id == flash->model_id) {
			/* Print the status register to tell the
268 269 270 271
			 * user about possible write protection.
			 */
			generic_spi_prettyprint_status_register(flash);

272
			return 1;
273
		}
274 275 276 277
		/* Test if this is a pure vendor match. */
		if (manuf_id == flash->manufacture_id &&
		    GENERIC_DEVICE_ID == flash->model_id)
			return 1;
278 279 280 281 282
	}

	return 0;
}

283 284 285 286 287 288 289 290 291 292
uint8_t generic_spi_read_status_register()
{
	const unsigned char cmd[] = JEDEC_RDSR;
	unsigned char readarr[1];

	/* Read Status Register */
	generic_spi_command(JEDEC_RDSR_OUTSIZE, JEDEC_RDSR_INSIZE, cmd, readarr);
	return readarr[0];
}

293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
/* Prettyprint the status register. Works for
 * ST M25P series
 * MX MX25L series
 */
void generic_spi_prettyprint_status_register_st_m25p(uint8_t status)
{
	printf_debug("Chip status register: Status Register Write Disable "
		"(SRWD) is %sset\n", (status & (1 << 7)) ? "" : "not ");
	printf_debug("Chip status register: Bit 6 is "
		"%sset\n", (status & (1 << 6)) ? "" : "not ");
	printf_debug("Chip status register: Bit 5 is "
		"%sset\n", (status & (1 << 5)) ? "" : "not ");
	printf_debug("Chip status register: Block Protect 2 (BP2) is "
		"%sset\n", (status & (1 << 4)) ? "" : "not ");
	printf_debug("Chip status register: Block Protect 1 (BP1) is "
		"%sset\n", (status & (1 << 3)) ? "" : "not ");
	printf_debug("Chip status register: Block Protect 0 (BP0) is "
		"%sset\n", (status & (1 << 2)) ? "" : "not ");
	printf_debug("Chip status register: Write Enable Latch (WEL) is "
		"%sset\n", (status & (1 << 1)) ? "" : "not ");
	printf_debug("Chip status register: Write In Progress (WIP) is "
		"%sset\n", (status & (1 << 0)) ? "" : "not ");
}

void generic_spi_prettyprint_status_register(struct flashchip *flash)
{
	uint8_t status;

	status = generic_spi_read_status_register();
	printf_debug("Chip status register is %02x\n", status);
	switch (flash->manufacture_id) {
	case ST_ID:
	case MX_ID:
		if ((flash->model_id & 0xff00) == 0x2000)
			generic_spi_prettyprint_status_register_st_m25p(status);
		break;
	}
}
	
332
int generic_spi_chip_erase_c7(struct flashchip *flash)
333
{
334
	const unsigned char cmd[] = JEDEC_CE_C7;
335
	
336 337
	generic_spi_write_enable();
	/* Send CE (Chip Erase) */
338
	generic_spi_command(JEDEC_CE_C7_OUTSIZE, JEDEC_CE_C7_INSIZE, cmd, NULL);
339 340 341
	/* Wait until the Write-In-Progress bit is cleared.
	 * This usually takes 1-85 s, so wait in 1 s steps.
	 */
342 343 344 345 346
	while (generic_spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
		sleep(1);
	return 0;
}

347 348 349 350 351
/* Block size is usually
 * 64k for Macronix
 * 32k for SST
 * 4-32k non-uniform for EON
 */
352
int generic_spi_block_erase_d8(const struct flashchip *flash, unsigned long addr)
353
{
354
	unsigned char cmd[JEDEC_BE_D8_OUTSIZE] = JEDEC_BE_D8;
355 356 357 358 359 360

	cmd[1] = (addr & 0x00ff0000) >> 16;
	cmd[2] = (addr & 0x0000ff00) >> 8;
	cmd[3] = (addr & 0x000000ff);
	generic_spi_write_enable();
	/* Send BE (Block Erase) */
361
	generic_spi_command(JEDEC_BE_D8_OUTSIZE, JEDEC_BE_D8_INSIZE, cmd, NULL);
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
	/* Wait until the Write-In-Progress bit is cleared.
	 * This usually takes 100-4000 ms, so wait in 100 ms steps.
	 */
	while (generic_spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
		usleep(100 * 1000);
	return 0;
}

/* Sector size is usually 4k, though Macronix eliteflash has 64k */
int generic_spi_sector_erase(const struct flashchip *flash, unsigned long addr)
{
	unsigned char cmd[JEDEC_SE_OUTSIZE] = JEDEC_SE;
	cmd[1] = (addr & 0x00ff0000) >> 16;
	cmd[2] = (addr & 0x0000ff00) >> 8;
	cmd[3] = (addr & 0x000000ff);

	generic_spi_write_enable();
	/* Send SE (Sector Erase) */
	generic_spi_command(JEDEC_SE_OUTSIZE, JEDEC_SE_INSIZE, cmd, NULL);
	/* Wait until the Write-In-Progress bit is cleared.
	 * This usually takes 15-800 ms, so wait in 10 ms steps.
	 */
	while (generic_spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
		usleep(10 * 1000);
	return 0;
}

/* Page size is usually 256 bytes */
390 391 392 393 394 395 396 397 398 399
void it8716f_spi_page_program(int block, uint8_t *buf, uint8_t *bios) {
	int i;

	generic_spi_write_enable();
	outb(0x06 , it8716f_flashport + 1);
	outb((3 << 4), it8716f_flashport);
	for (i = 0; i < 256; i++) {
		bios[256 * block + i] = buf[256 * block + i];
	}
	outb(0, it8716f_flashport);
400 401 402
	/* Wait until the Write-In-Progress bit is cleared.
	 * This usually takes 1-10 ms, so wait in 1 ms steps.
	 */
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
	while (generic_spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
		usleep(1000);
}

void generic_spi_page_program(int block, uint8_t *buf, uint8_t *bios)
{
	if (it8716f_flashport)
		it8716f_spi_page_program(block, buf, bios);
}

int generic_spi_chip_write(struct flashchip *flash, uint8_t *buf) {
	int total_size = 1024 * flash->total_size;
	int i;
	for (i = 0; i < total_size / 256; i++) {
		generic_spi_page_program(i, buf, (uint8_t *)flash->virtual_memory);
	}
	return 0;
}