aboutsummaryrefslogtreecommitdiffstats
path: root/spi.h
blob: de5b3be2e769a005c5b8fb16f76f3530d889cf15 (plain)
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
115
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2007, 2008 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
 */

#ifndef __SPI_H__
#define __SPI_H__ 1

/*
 * Contains the generic SPI headers
 */

/* Read Electronic ID */
#define JEDEC_RDID		0x9f
#define JEDEC_RDID_OUTSIZE	0x01
/* INSIZE may be 0x04 for some chips*/
#define JEDEC_RDID_INSIZE	0x03

/* Some Atmel AT25F* models have bit 3 as don't care bit in commands */
#define AT25F_RDID		0x15	/* 0x15 or 0x1d */
#define AT25F_RDID_OUTSIZE	0x01
#define AT25F_RDID_INSIZE	0x02

/* Read Electronic Manufacturer Signature */
#define JEDEC_REMS		0x90
#define JEDEC_REMS_OUTSIZE	0x04
#define JEDEC_REMS_INSIZE	0x02

/* Read Serial Flash Discoverable Parameters (SFDP) */
#define JEDEC_SFDP		0x5a
#define JEDEC_SFDP_OUTSIZE	0x05	/* 8b op, 24b addr, 8b dummy */
/*      JEDEC_SFDP_INSIZE : any length */

/* Read Electronic Signature */
#define JEDEC_RES		0xab
#define JEDEC_RES_OUTSIZE	0x04
/* INSIZE may be 0x02 for some chips*/
#define JEDEC_RES_INSIZE	0x01

/* 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

/* Chip Erase 0x60 is supported by Macronix/SST chips. */
#define JEDEC_CE_60		0x60
#define JEDEC_CE_60_OUTSIZE	0x01
#define JEDEC_CE_60_INSIZE	0x00

/* Chip Erase 0x62 is supported by Atmel AT25F chips. */
#define JEDEC_CE_62		0x62
#define JEDEC_CE_62_OUTSIZE	0x01
#define JEDEC_CE_62_INSIZE	0x00

/* Chip Erase 0xc7 is supported by SST/ST/EON/Macronix chips. */
#define JEDEC_CE_C7		0xc7
#define JEDEC_CE_C7_OUTSIZE	0x01
#define JEDEC_CE_C7_INSIZE	0x00

/* Block Erase 0x50 is supported by Atmel AT26DF chips. */
#define JEDEC_BE_50		0x50
#define JEDEC_BE_50_OUTSIZE	0x04
#define JEDEC_BE_50_INSIZE	0x00

/* Block Erase 0x52 is supported by SST and old Atmel chips. */
#define JEDEC_BE_52		0x52
#define JEDEC_BE_52_OUTSIZE	0x04
#define JEDEC_BE_52_INSIZE	0x00

/* Block Erase 0x81 is supported by Atmel AT26DF chips. */
#define JEDEC_BE_81		0x81
#define JEDEC_BE_81_OUTSIZE	0x04
#define JEDEC_BE_81_INSIZE	0x00

/* Block Erase 0xc4 is supported by Micron chips. */
#define JEDEC_BE_C4		0xc4
#define JEDEC_BE_C4_OUTSIZE	0x04
#define JEDEC_BE_C4_INSIZE	0x00

/* Block Erase 0xd8 is supported by EON/Macronix chips. */
#define JEDEC_BE_D8		0xd8
#define JEDEC_BE_D8_OUTSIZE	0x04
#define JEDEC_BE_D8_INSIZE	0x00

/* Block Erase 0xd7 is supported by PMC chips. */
#define JEDEC_BE_D7		0xd7
#define JEDEC_BE_D7_OUTSIZE	0x04
#define JEDEC_BE_D7_INSIZE	0x00

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

/* Page Erase 0xDB */
#define JEDEC_PE		0xDB
#define JEDEC_PE_OUTSIZE	0x04
#define JEDEC_PE_INSIZE		0x00

/* Read Status Register */
#define JEDEC_RDSR		0x05
#define JEDEC_RDSR_OUTSIZE	0x01
#define JEDEC_RDSR_INSIZE	0x01

/* Status Register Bits */
#define SPI_SR_WIP	(0x01 << 0)
#define SPI_SR_WEL	(0x01 << 1)
#define SPI_SR_AAI	(0x01 << 6)

/* Write Status Enable */
#define JEDEC_EWSR		0x50
#define JEDEC_EWSR_OUTSIZE	0x01
#define JEDEC_EWSR_INSIZE	0x00

/* Write Status Register */
#define JEDEC_WRSR		0x01
#define JEDEC_WRSR_OUTSIZE	0x02
#define JEDEC_WRSR_INSIZE	0x00

/* Read the memory */
#define JEDEC_READ		0x03
#define JEDEC_READ_OUTSIZE	0x04
/*      JEDEC_READ_INSIZE : any length */

/* Write memory byte */
#define JEDEC_BYTE_PROGRAM		0x02
#define JEDEC_BYTE_PROGRAM_OUTSIZE	0x05
#define JEDEC_BYTE_PROGRAM_INSIZE	0x00

/* Write AAI word (SST25VF080B) */
#define JEDEC_AAI_WORD_PROGRAM			0xad
#define JEDEC_AAI_WORD_PROGRAM_OUTSIZE		0x06
#define JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE	0x03
#define JEDEC_AAI_WORD_PROGRAM_INSIZE		0x00

/* Error codes */
#define SPI_GENERIC_ERROR	-1
#define SPI_INVALID_OPCODE	-2
#define SPI_INVALID_ADDRESS	-3
#define SPI_INVALID_LENGTH	-4
#define SPI_FLASHROM_BUG	-5
#define SPI_PROGRAMMER_ERROR	-6

#endif		/* !__SPI_H__ */
an>) && !result; cmds++) { result = spi_send_command(flash, cmds->writecnt, cmds->readcnt, cmds->writearr, cmds->readarr); } return result; } int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) { unsigned int max_data = flash->mst->spi.max_data_read; if (max_data == MAX_DATA_UNSPECIFIED) { msg_perr("%s called, but SPI read chunk size not defined " "on this hardware. Please report a bug at " "flashrom@flashrom.org\n", __func__); return 1; } return spi_read_chunked(flash, buf, start, len, max_data); } int default_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) { unsigned int max_data = flash->mst->spi.max_data_write; if (max_data == MAX_DATA_UNSPECIFIED) { msg_perr("%s called, but SPI write chunk size not defined " "on this hardware. Please report a bug at " "flashrom@flashrom.org\n", __func__); return 1; } return spi_write_chunked(flash, buf, start, len, max_data); } int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) { unsigned int addrbase = 0; /* Check if the chip fits between lowest valid and highest possible * address. Highest possible address with the current SPI implementation * means 0xffffff, the highest unsigned 24bit number. */ addrbase = spi_get_valid_read_addr(flash); if (addrbase + flash->chip->total_size * 1024 > (1 << 24)) { msg_perr("Flash chip size exceeds the allowed access window. "); msg_perr("Read will probably fail.\n"); /* Try to get the best alignment subject to constraints. */ addrbase = (1 << 24) - flash->chip->total_size * 1024; } /* Check if alignment is native (at least the largest power of two which * is a factor of the mapped size of the chip). */ if (ffs(flash->chip->total_size * 1024) > (ffs(addrbase) ? : 33)) { msg_perr("Flash chip is not aligned natively in the allowed " "access window.\n"); msg_perr("Read will probably return garbage.\n"); } return flash->mst->spi.read(flash, buf, addrbase + start, len); } /* * Program chip using page (256 bytes) programming. * Some SPI masters can't do this, they use single byte programming instead. * The redirect to single byte programming is achieved by setting * .write_256 = spi_chip_write_1 */ /* real chunksize is up to 256, logical chunksize is 256 */ int spi_chip_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) { return flash->mst->spi.write_256(flash, buf, start, len); } /* * Get the lowest allowed address for read accesses. This often happens to * be the lowest allowed address for all commands which take an address. * This is a master limitation. */ uint32_t spi_get_valid_read_addr(struct flashctx *flash) { switch (flash->mst->spi.type) { #if CONFIG_INTERNAL == 1 #if defined(__i386__) || defined(__x86_64__) case SPI_CONTROLLER_ICH7: case SPI_CONTROLLER_ICH9: /* Return BBAR for ICH chipsets. */ return ichspi_bbar; #endif #endif default: return 0; } } int spi_aai_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) { return flash->mst->spi.write_aai(flash, buf, start, len); } int register_spi_master(const struct spi_master *mst) { struct registered_master rmst; if (!mst->write_aai || !mst->write_256 || !mst->read || !mst->command || !mst->multicommand || ((mst->command == default_spi_send_command) && (mst->multicommand == default_spi_send_multicommand))) { msg_perr("%s called with incomplete master definition. " "Please report a bug at flashrom@flashrom.org\n", __func__); return ERROR_FLASHROM_BUG; } rmst.buses_supported = BUS_SPI; rmst.spi = *mst; return register_master(&rmst); }