summaryrefslogtreecommitdiffstats
path: root/libflash/libflash-priv.h
blob: e59d829a2f7cde9b97f9695ae1931f6b5c0397d7 (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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/* Copyright 2013-2014 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __LIBFLASH_PRIV_H
#define __LIBFLASH_PRIV_H

#include <ccan/endian/endian.h>
#include <ccan/array_size/array_size.h>
#include <ccan/container_of/container_of.h>

/* Flash commands */
#define CMD_WRSR		0x01	/* Write Status Register (also config. on Macronix) */
#define CMD_PP			0x02	/* Page Program */
#define CMD_READ		0x03	/* READ */
#define CMD_WRDI		0x04	/* Write Disable */
#define CMD_RDSR		0x05	/* Read Status Register */
#define CMD_WREN		0x06	/* Write Enable */
#define CMD_RDCR		0x15	/* Read configuration register (Macronix) */
#define CMD_SE			0x20	/* Sector (4K) Erase */
#define CMD_RDSCUR		0x2b	/* Read Security Register (Macronix) */
#define CMD_BE32K		0x52	/* Block (32K) Erase */
#define CMD_RDSFDP		0x5a	/* Read SFDP JEDEC info */
#define CMD_CE			0x60	/* Chip Erase (Macronix/Winbond) */
#define CMD_MIC_WREVCONF	0x61	/* Micron Write Enhanced Volatile Config */
#define CMD_MIC_RDEVCONF       	0x65	/* Micron Read Enhanced Volatile Config */
#define CMD_MIC_RDFLST		0x70	/* Micron Read Flag Status */
#define CMD_MIC_WRVCONF		0x81	/* Micron Write Volatile Config */
#define CMD_MIC_RDVCONF		0x85	/* Micron Read Volatile Config */
#define CMD_RDID		0x9f	/* Read JEDEC ID */
#define CMD_EN4B		0xb7	/* Enable 4B addresses */
#define CMD_MIC_BULK_ERASE	0xc7	/* Micron Bulk Erase */
#define CMD_BE			0xd8	/* Block (64K) Erase */
#define CMD_RDDPB		0xe0	/* Read dynamic protection (Macronix) */
#define CMD_RDSPB		0xe2	/* Read static protection (Macronix) */
#define CMD_EX4B		0xe9	/* Exit 4B addresses */

/* Flash status bits */
#define STAT_WIP	0x01
#define STAT_WEN	0x02

/* This isn't exposed to clients but is to controllers */
struct flash_info {
	uint32_t	id;
	uint32_t	size;
	uint32_t	flags;
#define FL_ERASE_4K	0x00000001	/* Supports 4k erase */
#define FL_ERASE_32K	0x00000002	/* Supports 32k erase */
#define FL_ERASE_64K	0x00000004	/* Supports 64k erase */
#define FL_ERASE_CHIP	0x00000008	/* Supports 0x60 cmd chip erase */
#define FL_ERASE_BULK	0x00000010	/* Supports 0xc7 cmd bulk erase */
#define FL_MICRON_BUGS	0x00000020	/* Various micron bug workarounds */
#define FL_ERASE_ALL	(FL_ERASE_4K | FL_ERASE_32K | FL_ERASE_64K | \
			 FL_ERASE_CHIP)
#define FL_CAN_4B	0x00000010	/* Supports 4b mode */
	const char	*name;
};

/* Flash controller, return negative values for errors */
struct spi_flash_ctrl {
	/*
	 * The controller can provide basically two interfaces,
	 * either a fairly high level one and a lower level one.
	 *
	 * If all functions of the high level interface are
	 * implemented then the low level one is optional. A
	 * controller can implement some of the high level one
	 * in which case the missing ones will be handled by
	 * libflash using the low level interface.
	 *
	 * There are also some common functions.
	 */

	/* **************************************************
	 *             Misc / common functions
	 * **************************************************/

	/*
	 * - setup(ctrl, tsize)
	 *
	 * Provides the controller with an option to configure itself
	 * based on the specific flash type. It can also override some
	 * settings in the info block such as available erase sizes etc...
	 * which can be needed for high level controllers. It can also
	 * override the total flash size.
	 */
	int (*setup)(struct spi_flash_ctrl *ctrl, uint32_t *tsize);

	/*
	 * - set_4b(ctrl, enable)
	 *
	 *  enable    : Switch to 4bytes (true) or 3bytes (false) address mode
	 *
	 * Set the controller's address size. If the controller doesn't
	 * implement the low level command interface, then this must also
	 * configure the flash chip itself. Otherwise, libflash will do it.
	 *
	 * Note that if this isn't implemented, then libflash might still
	 * try to switch large flash chips to 4b mode if the low level cmd
	 * interface is implemented. It will then also stop using the high
	 * level command interface since it's assumed that it cannot handle
	 * 4b addresses.
	 */
	int (*set_4b)(struct spi_flash_ctrl *ctrl, bool enable);



	/* **************************************************
	 *             High level interface
	 * **************************************************/

	/*
	 * Read chip ID. This can return up to 16 bytes though the
	 * current libflash will only use 3 (room for things like
	 * extended micron stuff).
	 *
	 * id_size is set on entry to the buffer size and need to
	 * be adjusted to the actual ID size read.
	 *
	 * If NULL, libflash will use cmd_rd to send normal RDID (0x9f)
	 * command.
	 */
	int (*chip_id)(struct spi_flash_ctrl *ctrl, uint8_t *id_buf,
		       uint32_t *id_size);

	/*
	 * Read from flash. There is no specific constraint on
	 * alignment or size other than not reading outside of
	 * the chip.
	 *
	 * If NULL, libflash will use cmd_rd to send normal
	 * READ (0x03) commands.
	 */
	int (*read)(struct spi_flash_ctrl *ctrl, uint32_t addr, void *buf,
		    uint32_t size);

	/*
	 * Write to flash. There is no specific constraint on
	 * alignment or size other than not reading outside of
	 * the chip. The driver is responsible for handling
	 * 256-bytes page alignment and to send the write enable
	 * commands when needed.
	 *
	 * If absent, libflash will use cmd_wr to send WREN (0x06)
	 * and PP (0x02) commands.
	 *
	 * Note: This does not need to handle erasing. libflash
	 * will ensure that this is never used for changing a bit
	 * value from 0 to 1.
	 */
	int (*write)(struct spi_flash_ctrl *ctrl, uint32_t addr,
		     const void *buf, uint32_t size);

	/*
	 * Erase. This will be called for erasing a portion of
	 * the flash using a granularity (alignment of start and
	 * size) that is no less than the smallest supported
	 * erase size in the info block (*). The driver is
	 * responsible to send write enable commands when needed.
	 *
	 * If absent, libflash will use cmd_wr to send WREN (0x06)
	 * and either of SE (0x20), BE32K (0x52) or BE (0xd8)
	 * based on what the flash chip supports.
	 *
	 * (*) Note: This is called with addr=0 and size=0xffffffff
	 * in which case this is used as a "chip erase". Return
	 * FLASH_ERR_CHIP_ER_NOT_SUPPORTED if not supported. Some
	 * future version of libflash might then emulate it using
	 * normal erase commands.
	 */
	int (*erase)(struct spi_flash_ctrl *ctrl, uint32_t addr,
		     uint32_t size);

	/* **************************************************
	 *             Low level interface
	 * **************************************************/

	/* Note: For commands with no data, libflash will might use
	 *       either cmd_rd or cmd_wr.
	 */
	
	/*
	 * - cmd_rd(ctrl, cmd, has_addr, address, buffer, size);
	 *
	 *   cmd      : command opcode
	 *   has_addr : send an address after the command
	 *   address  : address to send
	 *   buffer   : buffer for additional data to read (or NULL)
	 *   size     : size of additional data read (or NULL)
	 *
	 * Sends a command and optionally read additional data
	 */
	int (*cmd_rd)(struct spi_flash_ctrl *ctrl, uint8_t cmd,
		      bool has_addr, uint32_t addr, void *buffer,
		      uint32_t size);
	/*
	 * - cmd_wr(ctrl, cmd, has_addr, address, buffer, size);
	 *
	 *   cmd      : command opcode
	 *   has_addr : send an address after the command
	 *   address  : address to send
	 *   buffer   : buffer for additional data to write (or NULL)
	 *   size     : size of additional data write (or NULL)
	 *
	 * Sends a command and optionally write additional data
	 */
	int (*cmd_wr)(struct spi_flash_ctrl *ctrl, uint8_t cmd,
		      bool has_addr, uint32_t addr, const void *buffer,
		      uint32_t size);

	/* The core will establish this at init, after chip ID has
	 * been probed
	 */
	struct flash_info *finfo;

	void *priv;
};

extern int fl_wren(struct spi_flash_ctrl *ct);
extern int fl_read_stat(struct spi_flash_ctrl *ct, uint8_t *stat);
extern int fl_sync_wait_idle(struct spi_flash_ctrl *ct);

#endif /* LIBFLASH_PRIV_H */
OpenPOWER on IntegriCloud