2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * Copyright 2008, Network Appliance Inc.
6 * Jason McMullan <mcmullan@netapp.com>
8 * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
9 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
11 * See file CREDITS for list of people who contributed to this
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 #include <spi_flash.h>
34 #include "spi_flash_internal.h"
36 /* M25Pxx-specific commands */
37 #define CMD_M25PXX_WREN 0x06 /* Write Enable */
38 #define CMD_M25PXX_WRDI 0x04 /* Write Disable */
39 #define CMD_M25PXX_RDSR 0x05 /* Read Status Register */
40 #define CMD_M25PXX_WRSR 0x01 /* Write Status Register */
41 #define CMD_M25PXX_READ 0x03 /* Read Data Bytes */
42 #define CMD_M25PXX_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
43 #define CMD_M25PXX_PP 0x02 /* Page Program */
44 #define CMD_M25PXX_SE 0xd8 /* Sector Erase */
45 #define CMD_M25PXX_BE 0xc7 /* Bulk Erase */
46 #define CMD_M25PXX_DP 0xb9 /* Deep Power-down */
47 #define CMD_M25PXX_RES 0xab /* Release from DP, and Read Signature */
49 #define STM_ID_M25P16 0x15
50 #define STM_ID_M25P20 0x12
51 #define STM_ID_M25P32 0x16
52 #define STM_ID_M25P40 0x13
53 #define STM_ID_M25P64 0x17
54 #define STM_ID_M25P80 0x14
55 #define STM_ID_M25P128 0x18
57 #define STMICRO_SR_WIP (1 << 0) /* Write-in-Progress */
59 struct stmicro_spi_flash_params
{
67 struct stmicro_spi_flash
{
68 const struct stmicro_spi_flash_params
*params
;
69 struct spi_flash flash
;
72 static inline struct stmicro_spi_flash
*to_stmicro_spi_flash(struct spi_flash
75 return container_of(flash
, struct stmicro_spi_flash
, flash
);
78 static const struct stmicro_spi_flash_params stmicro_spi_flash_table
[] = {
80 .idcode1
= STM_ID_M25P16
,
82 .pages_per_sector
= 256,
87 .idcode1
= STM_ID_M25P20
,
89 .pages_per_sector
= 256,
94 .idcode1
= STM_ID_M25P32
,
96 .pages_per_sector
= 256,
101 .idcode1
= STM_ID_M25P40
,
103 .pages_per_sector
= 256,
108 .idcode1
= STM_ID_M25P64
,
110 .pages_per_sector
= 256,
115 .idcode1
= STM_ID_M25P80
,
117 .pages_per_sector
= 256,
122 .idcode1
= STM_ID_M25P128
,
124 .pages_per_sector
= 1024,
130 static int stmicro_wait_ready(struct spi_flash
*flash
, unsigned long timeout
)
132 struct spi_slave
*spi
= flash
->spi
;
133 unsigned long timebase
;
136 u8 cmd
[4] = { CMD_M25PXX_RDSR
, 0xff, 0xff, 0xff };
138 ret
= spi_xfer(spi
, 32, &cmd
[0], NULL
, SPI_XFER_BEGIN
);
140 debug("SF: Failed to send command %02x: %d\n", cmd
, ret
);
144 timebase
= get_timer(0);
146 ret
= spi_xfer(spi
, 8, NULL
, &status
, 0);
150 if ((status
& STMICRO_SR_WIP
) == 0)
153 } while (get_timer(timebase
) < timeout
);
155 spi_xfer(spi
, 0, NULL
, NULL
, SPI_XFER_END
);
157 if ((status
& STMICRO_SR_WIP
) == 0)
164 static int stmicro_read_fast(struct spi_flash
*flash
,
165 u32 offset
, size_t len
, void *buf
)
167 struct stmicro_spi_flash
*stm
= to_stmicro_spi_flash(flash
);
168 unsigned long page_addr
;
169 unsigned long page_size
;
172 page_size
= stm
->params
->page_size
;
173 page_addr
= offset
/ page_size
;
175 cmd
[0] = CMD_READ_ARRAY_FAST
;
176 cmd
[1] = page_addr
>> 8;
178 cmd
[3] = offset
% page_size
;
181 return spi_flash_read_common(flash
, cmd
, sizeof(cmd
), buf
, len
);
184 static int stmicro_write(struct spi_flash
*flash
,
185 u32 offset
, size_t len
, const void *buf
)
187 struct stmicro_spi_flash
*stm
= to_stmicro_spi_flash(flash
);
188 unsigned long page_addr
;
189 unsigned long byte_addr
;
190 unsigned long page_size
;
196 page_size
= stm
->params
->page_size
;
197 page_addr
= offset
/ page_size
;
198 byte_addr
= offset
% page_size
;
200 ret
= spi_claim_bus(flash
->spi
);
202 debug("SF: Unable to claim SPI bus\n");
207 for (actual
= 0; actual
< len
; actual
+= chunk_len
) {
208 chunk_len
= min(len
- actual
, page_size
- byte_addr
);
210 cmd
[0] = CMD_M25PXX_PP
;
211 cmd
[1] = page_addr
>> 8;
216 ("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n",
217 buf
+ actual
, cmd
[0], cmd
[1], cmd
[2], cmd
[3], chunk_len
);
219 ret
= spi_flash_cmd(flash
->spi
, CMD_M25PXX_WREN
, NULL
, 0);
221 debug("SF: Enabling Write failed\n");
225 ret
= spi_flash_cmd_write(flash
->spi
, cmd
, 4,
226 buf
+ actual
, chunk_len
);
228 debug("SF: STMicro Page Program failed\n");
232 ret
= stmicro_wait_ready(flash
, SPI_FLASH_PROG_TIMEOUT
);
234 debug("SF: STMicro page programming timed out\n");
242 debug("SF: STMicro: Successfully programmed %u bytes @ 0x%x\n",
245 spi_release_bus(flash
->spi
);
249 int stmicro_erase(struct spi_flash
*flash
, u32 offset
, size_t len
)
251 struct stmicro_spi_flash
*stm
= to_stmicro_spi_flash(flash
);
252 unsigned long sector_size
;
258 * This function currently uses sector erase only.
259 * probably speed things up by using bulk erase
263 sector_size
= stm
->params
->page_size
* stm
->params
->pages_per_sector
;
265 if (offset
% sector_size
|| len
% sector_size
) {
266 debug("SF: Erase offset/length not multiple of sector size\n");
271 cmd
[0] = CMD_M25PXX_SE
;
275 ret
= spi_claim_bus(flash
->spi
);
277 debug("SF: Unable to claim SPI bus\n");
282 for (actual
= 0; actual
< len
; actual
++) {
283 cmd
[1] = (offset
/ sector_size
) + actual
;
285 ret
= spi_flash_cmd(flash
->spi
, CMD_M25PXX_WREN
, NULL
, 0);
287 debug("SF: Enabling Write failed\n");
291 ret
= spi_flash_cmd_write(flash
->spi
, cmd
, 4, NULL
, 0);
293 debug("SF: STMicro page erase failed\n");
297 /* Up to 2 seconds */
298 ret
= stmicro_wait_ready(flash
, 2 * CONFIG_SYS_HZ
);
300 debug("SF: STMicro page erase timed out\n");
305 debug("SF: STMicro: Successfully erased %u bytes @ 0x%x\n",
306 len
* sector_size
, offset
);
308 spi_release_bus(flash
->spi
);
312 struct spi_flash
*spi_flash_probe_stmicro(struct spi_slave
*spi
, u8
* idcode
)
314 const struct stmicro_spi_flash_params
*params
;
315 struct stmicro_spi_flash
*stm
;
320 ret
= spi_flash_cmd(spi
, CMD_READ_ID
, id
, sizeof(id
));
324 for (i
= 0; i
< ARRAY_SIZE(stmicro_spi_flash_table
); i
++) {
325 params
= &stmicro_spi_flash_table
[i
];
326 if (params
->idcode1
== idcode
[2]) {
331 if (i
== ARRAY_SIZE(stmicro_spi_flash_table
)) {
332 debug("SF: Unsupported STMicro ID %02x\n", id
[1]);
336 stm
= malloc(sizeof(struct stmicro_spi_flash
));
338 debug("SF: Failed to allocate memory\n");
342 stm
->params
= params
;
343 stm
->flash
.spi
= spi
;
344 stm
->flash
.name
= params
->name
;
346 stm
->flash
.write
= stmicro_write
;
347 stm
->flash
.erase
= stmicro_erase
;
348 stm
->flash
.read
= stmicro_read_fast
;
349 stm
->flash
.size
= params
->page_size
* params
->pages_per_sector
350 * params
->nr_sectors
;
352 debug("SF: Detected %s with page size %u, total %u bytes\n",
353 params
->name
, params
->page_size
, stm
->flash
.size
);