summaryrefslogtreecommitdiff
path: root/include/spi_nor.h
blob: f0c379cd4386e9aaaad1fa9c07944a9eb043e060 (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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/* Copyright 2015 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* SPI Serial NOR Flash driver module for Chrome EC */

#ifndef __CROS_EC_SPI_NOR_H
#define __CROS_EC_SPI_NOR_H

#include "common.h"
#include "console.h"
#include "shared_mem.h"
#include "task.h"
#include "util.h"

/* Driver compatibility requirements based on JEDEC SFDP support:
 *
 * Parameter     | SFDP v1.(5+)     | SFDP v1.0 | All others
 * ============================================================================
 * Capacity      | N/A              | N/A       | Uses instantiated default
 *               --------------------------------------------------------------
 *               | The capacity must be less than 4GiB for compatibility.
 * ----------------------------------------------------------------------------
 * Page Size     | N/A              | 1B or 64B | Uses instantiated default
 * ----------------------------------------------------------------------------
 * Erase Opcodes | 4KiB Erase with an opcode of 0x20 is always required.
 * ----------------------------------------------------------------------------
 * 4B Addressing | 4B addressing mode must be supported if the part is larger
 *               | than 16MiB. 4B mode entry will be attempted through opcode
 *               | 0xB7 and exit through 0xE9 where writes are enabled for both
 *               | in case it is required
 * ----------------------------------------------------------------------------
 */

/* Boards which use SPI NOR devices must provide enum spi_device indexing all
 * spi_device_t's in the board.h file. */
enum spi_device;

struct spi_nor_device_t {
	/* Name of the Serial NOR Flash device. */
	const char *name;

	/* Index of the SPI controller which this device is connected
	 * through.
	 */
	const enum spi_device spi_controller;

	/* Maximum timeout per command in microseconds. */
	const uint32_t timeout_usec;

	/* when instantiating this device, the initialization values for the
	 * following fields will be the default values. Note that the values
	 * below may change on the fly based on device state and SFDP
	 * discovery. */
	uint32_t capacity;
	size_t page_size;
	int in_4b_addressing_mode;
};

extern struct spi_nor_device_t spi_nor_devices[];
extern const unsigned int spi_nor_devices_used;

/* Industry standard Serial NOR Flash opcodes. All other opcodes are part
 * specific and require SFDP discovery. */
#define SPI_NOR_OPCODE_WRITE_STATUS  0x01 /* Write Status Register (1 Byte) */
#define SPI_NOR_OPCODE_PAGE_PROGRAM  0x02 /* Page program */
#define SPI_NOR_OPCODE_SLOW_READ     0x03 /* Read data (low frequency) */
#define SPI_NOR_OPCODE_WRITE_DISABLE 0x04
#define SPI_NOR_OPCODE_READ_STATUS   0x05 /* Read Status Register */
#define SPI_NOR_OPCODE_WRITE_ENABLE  0x06
#define SPI_NOR_OPCODE_FAST_READ     0x0b /* Read data (high frequency) */
#define SPI_NOR_OPCODE_SFDP          0x5a /* Read JEDEC SFDP */
#define SPI_NOR_OPCODE_JEDEC_ID      0x9f /* Read JEDEC ID */
#define SPI_NOR_OPCODE_WREAR         0xc5 /* Write extended address register */
#define SPI_NOR_OPCODE_CHIP_ERASE    0xc7 /* Erase whole flash chip */
#define SPI_NOR_OPCODE_RDEAR         0xc8 /* Read extended address register */

/* Flags for SPI_NOR_OPCODE_READ_STATUS */
#define SPI_NOR_STATUS_REGISTER_WIP BIT(0)  /* Write in progres */
#define SPI_NOR_STATUS_REGISTER_WEL BIT(1)  /* Write enabled latch */

/* If needed in the future this driver can be extended to discover SFDP
 * advertised erase sizes and opcodes for SFDP v1.0+. */
#define SPI_NOR_DRIVER_SPECIFIED_OPCODE_4KIB_ERASE  0x20
#define SPI_NOR_DRIVER_SPECIFIED_OPCODE_64KIB_ERASE 0xd8

/* If needed in the future this driver can be extended to discover 4B entry and
 * exit methods for SFDP v1.5+. */
#define SPI_NOR_DRIVER_SPECIFIED_OPCODE_ENTER_4B 0xb7
#define SPI_NOR_DRIVER_SPECIFIED_OPCODE_EXIT_4B  0xe9

/* JEDEC JEP106AR specifies 9 Manufacturer ID banks, read 12 to be sure. */
#define SPI_NOR_JEDEC_ID_BANKS 12

/**
 * Initialize the module, assumes the Serial NOR Flash devices are currently
 * all available for initialization. As part of the initialization the driver
 * will check if the part has a compatible SFDP Basic Flash Parameter table
 * and update the part's page_size, capacity, and forces the addressing mode.
 * Parts with more than 16MiB of capacity are initialized into 4B addressing
 * and parts with less are initialized into 3B addressing mode.
 *
 * WARNING: This must successfully return before invoking any other Serial NOR
 * Flash APIs.
 */
int spi_nor_init(void);

/**
 * Forces the Serial NOR Flash device to enter (or exit) 4 Byte addressing mode.
 *
 * WARNING:
 * 1) In 3 Byte addressing mode only 16MiB of Serial NOR Flash is accessible.
 * 2) If there's a second SPI controller communicating with this Serial
 *    NOR Flash part on the board, the user is responsible for ensuring
 *    addressing mode compatibility and cooperation.
 * 3) The user must ensure that multiple users do not trample on each other
 *    by having multiple parties changing the device's addressing mode.
 *
 * @param spi_nor_device The Serial NOR Flash device to use.
 * @param enter_4b_addressing_mode Whether to enter (1) or exit (0) 4B mode.
 * @return ec_error_list (non-zero on error and timeout).
 */
int spi_nor_set_4b_mode(struct spi_nor_device_t *spi_nor_device,
			int enter_4b_addressing_mode);

/**
 * Read JEDEC Identifier.
 *
 * @param spi_nor_device The Serial NOR Flash device to use.
 * @param size Number of Bytes to read.
 * @param data Destination buffer for data.
 * @return ec_error_list (non-zero on error and timeout).
 */
int spi_nor_read_jedec_id(const struct spi_nor_device_t *spi_nor_device,
			  size_t size, uint8_t *data);

/**
 * Read from the Serial NOR Flash device.
 *
 * @param spi_nor_device The Serial NOR Flash device to use.
 * @param offset Flash offset to read.
 * @param size Number of Bytes to read.
 * @param data Destination buffer for data.
 * @return ec_error_list (non-zero on error and timeout).
 */
int spi_nor_read(const struct spi_nor_device_t *spi_nor_device,
		 uint32_t offset, size_t size, uint8_t *data);

/**
 * Erase flash on the Serial Flash Device.
 *
 * @param spi_nor_device The Serial NOR Flash device to use.
 * @param offset Flash offset to erase, must be aligned to the minimum physical
 *               erase size.
 * @param size Number of Bytes to erase, must be a multiple of the the minimum
 *             physical erase size.
 * @return ec_error_list (non-zero on error and timeout).
 */
int spi_nor_erase(const struct spi_nor_device_t *spi_nor_device,
		  uint32_t offset, size_t size);

/**
 * Write to the Serial NOR Flash device. Assumes already erased.
 *
 * @param spi_nor_device The Serial NOR Flash device to use.
 * @param offset Flash offset to write.
 * @param size Number of Bytes to write.
 * @param data Data to write to flash.
 * @return ec_error_list (non-zero on error and timeout).
 */
int spi_nor_write(const struct spi_nor_device_t *spi_nor_device,
		  uint32_t offset, size_t size, const uint8_t *data);

/**
 * Write to the extended address register.
 * @param  spi_nor_device The Serial NOR Flash device to use.
 * @param  value          The value to write.
 * @return                ec_error_list (non-zero on error and timeout).
 */
int spi_nor_write_ear(const struct spi_nor_device_t *spi_nor_device,
		      const uint8_t value);


#endif  /* __CROS_EC_SPI_NOR_H */