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


32
void spi_prettyprint_status_register(struct flashchip *flash);
33

34
int spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr)
35 36
{
	if (it8716f_flashport)
37
		return it8716f_spi_command(writecnt, readcnt, writearr, readarr);
38 39
	else if (ich9_detected)
		return ich_spi_command(writecnt, readcnt, writearr, readarr);
40
	printf_debug("%s called, but no SPI chipset detected\n", __FUNCTION__);
41 42 43
	return 1;
}

44
static int spi_rdid(unsigned char *readarr)
45
{
46
	const unsigned char cmd[JEDEC_RDID_OUTSIZE] = {JEDEC_RDID};
47

48
	if (spi_command(JEDEC_RDID_OUTSIZE, JEDEC_RDID_INSIZE, cmd, readarr))
49
		return 1;
50
	printf_debug("RDID returned %02x %02x %02x.\n", readarr[0], readarr[1], readarr[2]);
51 52 53
	return 0;
}

54 55 56 57 58 59 60 61 62 63
static int spi_res(unsigned char *readarr)
{
	const unsigned char cmd[JEDEC_RES_OUTSIZE] = {JEDEC_RES, 0, 0, 0};

	if (spi_command(JEDEC_RES_OUTSIZE, JEDEC_RES_INSIZE, cmd, readarr))
		return 1;
	printf_debug("RES returned %02x.\n", readarr[0]);
	return 0;
}

64
void spi_write_enable()
65
{
66
	const unsigned char cmd[JEDEC_WREN_OUTSIZE] = {JEDEC_WREN};
67 68

	/* Send WREN (Write Enable) */
69
	spi_command(JEDEC_WREN_OUTSIZE, JEDEC_WREN_INSIZE, cmd, NULL);
70 71
}

72
void spi_write_disable()
73
{
74
	const unsigned char cmd[JEDEC_WRDI_OUTSIZE] = {JEDEC_WRDI};
75 76

	/* Send WRDI (Write Disable) */
77
	spi_command(JEDEC_WRDI_OUTSIZE, JEDEC_WRDI_INSIZE, cmd, NULL);
78 79
}

80
int probe_spi_rdid(struct flashchip *flash)
81 82
{
	unsigned char readarr[3];
83 84
	uint32_t manuf_id;
	uint32_t model_id;
85
	if (!spi_rdid(readarr)) {
86 87
		if (!oddparity(readarr[0]))
			printf_debug("RDID byte 0 parity violation.\n");
88 89
		/* Check if this is a continuation vendor ID */
		if (readarr[0] == 0x7f) {
90 91
			if (!oddparity(readarr[1]))
				printf_debug("RDID byte 1 parity violation.\n");
92 93 94 95 96 97
			manuf_id = (readarr[0] << 8) | readarr[1];
			model_id = readarr[2];
		} else {
			manuf_id = readarr[0];
			model_id = (readarr[1] << 8) | readarr[2];
		}
98
		printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, manuf_id, model_id);
99 100 101
		if (manuf_id == flash->manufacture_id &&
		    model_id == flash->model_id) {
			/* Print the status register to tell the
102 103
			 * user about possible write protection.
			 */
104
			spi_prettyprint_status_register(flash);
105

106
			return 1;
107
		}
108 109 110 111
		/* Test if this is a pure vendor match. */
		if (manuf_id == flash->manufacture_id &&
		    GENERIC_DEVICE_ID == flash->model_id)
			return 1;
112 113 114 115 116
	}

	return 0;
}

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
int probe_spi_res(struct flashchip *flash)
{
	unsigned char readarr[3];
	uint32_t model_id;
	if (!spi_rdid(readarr)) {
		/* Check if RDID returns 0xff 0xff 0xff, then we use RES. */
		if ((readarr[0] != 0xff) || (readarr[1] != 0xff) ||
		    (readarr[2] != 0xff))
			return 0;
	} else {
		/* We couldn't issue RDID, it's pointless to try RES. */
		return 0;
	}
	if (!spi_res(readarr)) {
		model_id = readarr[0];
		printf_debug("%s: id 0x%x\n", __FUNCTION__, model_id);
		if (model_id == flash->model_id) {
			/* Print the status register to tell the
			 * user about possible write protection.
			 */
			spi_prettyprint_status_register(flash);

			return 1;
		}
	}

	return 0;
}

146
uint8_t spi_read_status_register()
147
{
148
	const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = {JEDEC_RDSR};
149 150 151
	unsigned char readarr[1];

	/* Read Status Register */
152
	spi_command(JEDEC_RDSR_OUTSIZE, JEDEC_RDSR_INSIZE, cmd, readarr);
153 154 155
	return readarr[0];
}

156
/* Prettyprint the status register. Common definitions.
157
 */
158
void spi_prettyprint_status_register_common(uint8_t status)
159
{
160
	printf_debug("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
161
		"%sset\n", (status & (1 << 5)) ? "" : "not ");
162
	printf_debug("Chip status register: Bit 4 / Block Protect 2 (BP2) is "
163
		"%sset\n", (status & (1 << 4)) ? "" : "not ");
164
	printf_debug("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
165
		"%sset\n", (status & (1 << 3)) ? "" : "not ");
166
	printf_debug("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
167 168 169
		"%sset\n", (status & (1 << 2)) ? "" : "not ");
	printf_debug("Chip status register: Write Enable Latch (WEL) is "
		"%sset\n", (status & (1 << 1)) ? "" : "not ");
170
	printf_debug("Chip status register: Write In Progress (WIP/BUSY) is "
171 172 173
		"%sset\n", (status & (1 << 0)) ? "" : "not ");
}

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
/* Prettyprint the status register. Works for
 * ST M25P series
 * MX MX25L series
 */
void 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 ");
	spi_prettyprint_status_register_common(status);
}

/* Prettyprint the status register. Works for
 * SST 25VF016
 */
void spi_prettyprint_status_register_sst25vf016(uint8_t status)
{
192
	const char *bpt[] = {
193 194 195 196 197 198
		"none",
		"1F0000H-1FFFFFH",
		"1E0000H-1FFFFFH",
		"1C0000H-1FFFFFH",
		"180000H-1FFFFFH",
		"100000H-1FFFFFH",
199
		"all", "all"
200 201 202 203 204 205 206 207 208 209 210
	};
	printf_debug("Chip status register: Block Protect Write Disable "
		"(BPL) is %sset\n", (status & (1 << 7)) ? "" : "not ");
	printf_debug("Chip status register: Auto Address Increment Programming "
		"(AAI) is %sset\n", (status & (1 << 6)) ? "" : "not ");
	spi_prettyprint_status_register_common(status);
	printf_debug("Resulting block protection : %s\n",
		bpt[(status & 0x1c) >> 2]);
}

void spi_prettyprint_status_register(struct flashchip *flash)
211 212 213
{
	uint8_t status;

214
	status = spi_read_status_register();
215 216 217
	printf_debug("Chip status register is %02x\n", status);
	switch (flash->manufacture_id) {
	case ST_ID:
218 219 220 221
		if (((flash->model_id & 0xff00) == 0x2000) ||
		    ((flash->model_id & 0xff00) == 0x2500))
			spi_prettyprint_status_register_st_m25p(status);
		break;
222 223
	case MX_ID:
		if ((flash->model_id & 0xff00) == 0x2000)
224 225 226 227 228
			spi_prettyprint_status_register_st_m25p(status);
		break;
	case SST_ID:
		if (flash->model_id == SST_25VF016B)
			spi_prettyprint_status_register_sst25vf016(status);
229 230 231 232
		break;
	}
}
	
233
int spi_chip_erase_c7(struct flashchip *flash)
234
{
235
	const unsigned char cmd[JEDEC_CE_C7_OUTSIZE] = {JEDEC_CE_C7};
236
	
237
	spi_disable_blockprotect();
238
	spi_write_enable();
239
	/* Send CE (Chip Erase) */
240
	spi_command(JEDEC_CE_C7_OUTSIZE, JEDEC_CE_C7_INSIZE, cmd, NULL);
241 242 243
	/* Wait until the Write-In-Progress bit is cleared.
	 * This usually takes 1-85 s, so wait in 1 s steps.
	 */
244
	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
245 246 247 248
		sleep(1);
	return 0;
}

249 250 251 252 253
/* Block size is usually
 * 64k for Macronix
 * 32k for SST
 * 4-32k non-uniform for EON
 */
254
int spi_block_erase_d8(const struct flashchip *flash, unsigned long addr)
255
{
256
	unsigned char cmd[JEDEC_BE_D8_OUTSIZE] = {JEDEC_BE_D8};
257 258 259 260

	cmd[1] = (addr & 0x00ff0000) >> 16;
	cmd[2] = (addr & 0x0000ff00) >> 8;
	cmd[3] = (addr & 0x000000ff);
261
	spi_write_enable();
262
	/* Send BE (Block Erase) */
263
	spi_command(JEDEC_BE_D8_OUTSIZE, JEDEC_BE_D8_INSIZE, cmd, NULL);
264 265 266
	/* Wait until the Write-In-Progress bit is cleared.
	 * This usually takes 100-4000 ms, so wait in 100 ms steps.
	 */
267
	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
268 269 270 271 272
		usleep(100 * 1000);
	return 0;
}

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

280
	spi_write_enable();
281
	/* Send SE (Sector Erase) */
282
	spi_command(JEDEC_SE_OUTSIZE, JEDEC_SE_INSIZE, cmd, NULL);
283 284 285
	/* Wait until the Write-In-Progress bit is cleared.
	 * This usually takes 15-800 ms, so wait in 10 ms steps.
	 */
286
	while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
287 288 289 290
		usleep(10 * 1000);
	return 0;
}

291
void spi_page_program(int block, uint8_t *buf, uint8_t *bios)
292
{
293
	if (it8716f_flashport) {
294
		it8716f_spi_page_program(block, buf, bios);
295 296 297
		return;
	}
	printf_debug("%s called, but no SPI chipset detected\n", __FUNCTION__);
298 299
}

300 301 302 303 304 305
/*
 * This is according the SST25VF016 datasheet, who knows it is more
 * generic that this...
 */
void spi_write_status_register(int status)
{
306
	const unsigned char cmd[JEDEC_WRSR_OUTSIZE] = {JEDEC_WRSR, (unsigned char)status};
307 308

	/* Send WRSR (Write Status Register) */
309
	spi_command(JEDEC_WRSR_OUTSIZE, JEDEC_WRSR_INSIZE, cmd, NULL);
310 311 312 313 314 315 316 317 318 319 320 321
}

void spi_byte_program(int address, uint8_t byte)
{
	const unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE] = {JEDEC_BYTE_PROGRAM,
		(address>>16)&0xff,
		(address>>8)&0xff,
		(address>>0)&0xff,
		byte
	};

	/* Send Byte-Program */
322
	spi_command(JEDEC_BYTE_PROGRAM_OUTSIZE, JEDEC_BYTE_PROGRAM_INSIZE, cmd, NULL);
323 324 325 326 327 328
}

void spi_disable_blockprotect(void)
{
	uint8_t status;

329
	status = spi_read_status_register();
330 331 332
	/* If there is block protection in effect, unprotect it first. */
	if ((status & 0x3c) != 0) {
		printf_debug("Some block protection in effect, disabling\n");
333
		spi_write_enable();
334 335 336 337
		spi_write_status_register(status & ~0x3c);
	}
}

338
void spi_nbyte_read(int address, uint8_t *bytes, int len)
339 340
{
	const unsigned char cmd[JEDEC_READ_OUTSIZE] = {JEDEC_READ,
341 342 343
		(address >> 16) & 0xff,
		(address >> 8) & 0xff,
		(address >> 0) & 0xff,
344 345 346
	};

	/* Send Read */
347
	spi_command(JEDEC_READ_OUTSIZE, len, cmd, bytes);
348 349
}

350
int spi_chip_read(struct flashchip *flash, uint8_t *buf)
351
{
352 353
	if (it8716f_flashport)
		return it8716f_spi_chip_read(flash, buf);
354 355
	else if (ich9_detected)
		return ich_spi_read(flash, buf);
356 357
	printf_debug("%s called, but no SPI chipset detected\n", __FUNCTION__);
	return 1;
358 359
}

360 361 362 363
int spi_chip_write(struct flashchip *flash, uint8_t *buf)
{
	if (it8716f_flashport)
		return it8716f_spi_chip_write(flash, buf);
364 365
	else if (ich9_detected)
		return ich_spi_write(flash, buf);
366 367
	printf_debug("%s called, but no SPI chipset detected\n", __FUNCTION__);
	return 1;
368 369
}