Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OS
U-Boot.Mirror
提交
ca41ef30
U
U-Boot.Mirror
项目概览
OS
/
U-Boot.Mirror
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
U-Boot.Mirror
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ca41ef30
编写于
4月 03, 2009
作者:
W
Wolfgang Denk
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'sf' of
git://git.denx.de/u-boot-blackfin
上级
0d8cb9c0
d9596ffb
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
780 addition
and
20 deletion
+780
-20
drivers/mtd/spi/Makefile
drivers/mtd/spi/Makefile
+2
-0
drivers/mtd/spi/atmel.c
drivers/mtd/spi/atmel.c
+49
-1
drivers/mtd/spi/spansion.c
drivers/mtd/spi/spansion.c
+350
-0
drivers/mtd/spi/spi_flash.c
drivers/mtd/spi/spi_flash.c
+9
-4
drivers/mtd/spi/spi_flash_internal.h
drivers/mtd/spi/spi_flash_internal.h
+7
-3
drivers/mtd/spi/sst.c
drivers/mtd/spi/sst.c
+358
-0
drivers/mtd/spi/stmicro.c
drivers/mtd/spi/stmicro.c
+5
-12
未找到文件。
drivers/mtd/spi/Makefile
浏览文件 @
ca41ef30
...
...
@@ -27,6 +27,8 @@ LIB := $(obj)libspi_flash.a
COBJS-$(CONFIG_SPI_FLASH)
+=
spi_flash.o
COBJS-$(CONFIG_SPI_FLASH_ATMEL)
+=
atmel.o
COBJS-$(CONFIG_SPI_FLASH_SPANSION)
+=
spansion.o
COBJS-$(CONFIG_SPI_FLASH_SST)
+=
sst.o
COBJS-$(CONFIG_SPI_FLASH_STMICRO)
+=
stmicro.o
COBJS
:=
$
(
COBJS-y
)
...
...
drivers/mtd/spi/atmel.c
浏览文件 @
ca41ef30
...
...
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Atmel Corporation
*/
#define DEBUG
#include <common.h>
#include <malloc.h>
#include <spi_flash.h>
...
...
@@ -52,6 +52,54 @@ to_atmel_spi_flash(struct spi_flash *flash)
}
static
const
struct
atmel_spi_flash_params
atmel_spi_flash_table
[]
=
{
{
.
idcode1
=
0x22
,
.
l2_page_size
=
8
,
.
pages_per_block
=
8
,
.
blocks_per_sector
=
16
,
.
nr_sectors
=
4
,
.
name
=
"AT45DB011D"
,
},
{
.
idcode1
=
0x23
,
.
l2_page_size
=
8
,
.
pages_per_block
=
8
,
.
blocks_per_sector
=
16
,
.
nr_sectors
=
8
,
.
name
=
"AT45DB021D"
,
},
{
.
idcode1
=
0x24
,
.
l2_page_size
=
8
,
.
pages_per_block
=
8
,
.
blocks_per_sector
=
32
,
.
nr_sectors
=
8
,
.
name
=
"AT45DB041D"
,
},
{
.
idcode1
=
0x25
,
.
l2_page_size
=
8
,
.
pages_per_block
=
8
,
.
blocks_per_sector
=
32
,
.
nr_sectors
=
16
,
.
name
=
"AT45DB081D"
,
},
{
.
idcode1
=
0x26
,
.
l2_page_size
=
9
,
.
pages_per_block
=
8
,
.
blocks_per_sector
=
32
,
.
nr_sectors
=
16
,
.
name
=
"AT45DB161D"
,
},
{
.
idcode1
=
0x27
,
.
l2_page_size
=
9
,
.
pages_per_block
=
8
,
.
blocks_per_sector
=
64
,
.
nr_sectors
=
64
,
.
name
=
"AT45DB321D"
,
},
{
.
idcode1
=
0x28
,
.
l2_page_size
=
10
,
...
...
drivers/mtd/spi/spansion.c
0 → 100644
浏览文件 @
ca41ef30
/*
* Copyright (C) 2009 Freescale Semiconductor, Inc.
*
* Author: Mingkai Hu (Mingkai.hu@freescale.com)
* Based on stmicro.c by Wolfgang Denk (wd@denx.de),
* TsiChung Liew (Tsi-Chung.Liew@freescale.com),
* and Jason McMullan (mcmullan@netapp.com)
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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; either version 2 of
* the License, or (at your option) any later version.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <malloc.h>
#include <spi_flash.h>
#include "spi_flash_internal.h"
/* S25FLxx-specific commands */
#define CMD_S25FLXX_READ 0x03
/* Read Data Bytes */
#define CMD_S25FLXX_FAST_READ 0x0b
/* Read Data Bytes at Higher Speed */
#define CMD_S25FLXX_READID 0x90
/* Read Manufacture ID and Device ID */
#define CMD_S25FLXX_WREN 0x06
/* Write Enable */
#define CMD_S25FLXX_WRDI 0x04
/* Write Disable */
#define CMD_S25FLXX_RDSR 0x05
/* Read Status Register */
#define CMD_S25FLXX_WRSR 0x01
/* Write Status Register */
#define CMD_S25FLXX_PP 0x02
/* Page Program */
#define CMD_S25FLXX_SE 0xd8
/* Sector Erase */
#define CMD_S25FLXX_BE 0xc7
/* Bulk Erase */
#define CMD_S25FLXX_DP 0xb9
/* Deep Power-down */
#define CMD_S25FLXX_RES 0xab
/* Release from DP, and Read Signature */
#define SPSN_ID_S25FL008A 0x0213
#define SPSN_ID_S25FL016A 0x0214
#define SPSN_ID_S25FL032A 0x0215
#define SPSN_ID_S25FL064A 0x0216
#define SPSN_ID_S25FL128P 0x2018
#define SPSN_EXT_ID_S25FL128P_256KB 0x0300
#define SPSN_EXT_ID_S25FL128P_64KB 0x0301
#define SPANSION_SR_WIP (1 << 0)
/* Write-in-Progress */
struct
spansion_spi_flash_params
{
u16
idcode1
;
u16
idcode2
;
u16
page_size
;
u16
pages_per_sector
;
u16
nr_sectors
;
const
char
*
name
;
};
struct
spansion_spi_flash
{
struct
spi_flash
flash
;
const
struct
spansion_spi_flash_params
*
params
;
};
static
inline
struct
spansion_spi_flash
*
to_spansion_spi_flash
(
struct
spi_flash
*
flash
)
{
return
container_of
(
flash
,
struct
spansion_spi_flash
,
flash
);
}
static
const
struct
spansion_spi_flash_params
spansion_spi_flash_table
[]
=
{
{
.
idcode1
=
SPSN_ID_S25FL008A
,
.
idcode2
=
0
,
.
page_size
=
256
,
.
pages_per_sector
=
256
,
.
nr_sectors
=
16
,
.
name
=
"S25FL008A"
,
},
{
.
idcode1
=
SPSN_ID_S25FL016A
,
.
idcode2
=
0
,
.
page_size
=
256
,
.
pages_per_sector
=
256
,
.
nr_sectors
=
32
,
.
name
=
"S25FL016A"
,
},
{
.
idcode1
=
SPSN_ID_S25FL032A
,
.
idcode2
=
0
,
.
page_size
=
256
,
.
pages_per_sector
=
256
,
.
nr_sectors
=
64
,
.
name
=
"S25FL032A"
,
},
{
.
idcode1
=
SPSN_ID_S25FL064A
,
.
idcode2
=
0
,
.
page_size
=
256
,
.
pages_per_sector
=
256
,
.
nr_sectors
=
128
,
.
name
=
"S25FL064A"
,
},
{
.
idcode1
=
SPSN_ID_S25FL128P
,
.
idcode2
=
SPSN_EXT_ID_S25FL128P_64KB
,
.
page_size
=
256
,
.
pages_per_sector
=
256
,
.
nr_sectors
=
256
,
.
name
=
"S25FL128P_64K"
,
},
{
.
idcode1
=
SPSN_ID_S25FL128P
,
.
idcode2
=
SPSN_EXT_ID_S25FL128P_256KB
,
.
page_size
=
256
,
.
pages_per_sector
=
1024
,
.
nr_sectors
=
64
,
.
name
=
"S25FL128P_256K"
,
},
};
static
int
spansion_wait_ready
(
struct
spi_flash
*
flash
,
unsigned
long
timeout
)
{
struct
spi_slave
*
spi
=
flash
->
spi
;
unsigned
long
timebase
;
int
ret
;
u8
status
;
timebase
=
get_timer
(
0
);
do
{
ret
=
spi_flash_cmd
(
spi
,
CMD_S25FLXX_RDSR
,
&
status
,
sizeof
(
status
));
if
(
ret
)
return
-
1
;
if
((
status
&
SPANSION_SR_WIP
)
==
0
)
break
;
}
while
(
get_timer
(
timebase
)
<
timeout
);
if
((
status
&
SPANSION_SR_WIP
)
==
0
)
return
0
;
/* Timed out */
return
-
1
;
}
static
int
spansion_read_fast
(
struct
spi_flash
*
flash
,
u32
offset
,
size_t
len
,
void
*
buf
)
{
struct
spansion_spi_flash
*
spsn
=
to_spansion_spi_flash
(
flash
);
unsigned
long
page_addr
;
unsigned
long
page_size
;
u8
cmd
[
5
];
page_size
=
spsn
->
params
->
page_size
;
page_addr
=
offset
/
page_size
;
cmd
[
0
]
=
CMD_READ_ARRAY_FAST
;
cmd
[
1
]
=
page_addr
>>
8
;
cmd
[
2
]
=
page_addr
;
cmd
[
3
]
=
offset
%
page_size
;
cmd
[
4
]
=
0x00
;
debug
(
"READ: 0x%x => cmd = { 0x%02x 0x%02x%02x%02x%02x } len = 0x%x
\n
"
,
offset
,
cmd
[
0
],
cmd
[
1
],
cmd
[
2
],
cmd
[
3
],
cmd
[
4
],
len
);
return
spi_flash_read_common
(
flash
,
cmd
,
sizeof
(
cmd
),
buf
,
len
);
}
static
int
spansion_write
(
struct
spi_flash
*
flash
,
u32
offset
,
size_t
len
,
const
void
*
buf
)
{
struct
spansion_spi_flash
*
spsn
=
to_spansion_spi_flash
(
flash
);
unsigned
long
page_addr
;
unsigned
long
byte_addr
;
unsigned
long
page_size
;
size_t
chunk_len
;
size_t
actual
;
int
ret
;
u8
cmd
[
4
];
page_size
=
spsn
->
params
->
page_size
;
page_addr
=
offset
/
page_size
;
byte_addr
=
offset
%
page_size
;
ret
=
spi_claim_bus
(
flash
->
spi
);
if
(
ret
)
{
debug
(
"SF: Unable to claim SPI bus
\n
"
);
return
ret
;
}
ret
=
0
;
for
(
actual
=
0
;
actual
<
len
;
actual
+=
chunk_len
)
{
chunk_len
=
min
(
len
-
actual
,
page_size
-
byte_addr
);
cmd
[
0
]
=
CMD_S25FLXX_PP
;
cmd
[
1
]
=
page_addr
>>
8
;
cmd
[
2
]
=
page_addr
;
cmd
[
3
]
=
byte_addr
;
debug
(
"PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d
\n
"
,
buf
+
actual
,
cmd
[
0
],
cmd
[
1
],
cmd
[
2
],
cmd
[
3
],
chunk_len
);
ret
=
spi_flash_cmd
(
flash
->
spi
,
CMD_S25FLXX_WREN
,
NULL
,
0
);
if
(
ret
<
0
)
{
debug
(
"SF: Enabling Write failed
\n
"
);
break
;
}
ret
=
spi_flash_cmd_write
(
flash
->
spi
,
cmd
,
4
,
buf
+
actual
,
chunk_len
);
if
(
ret
<
0
)
{
debug
(
"SF: SPANSION Page Program failed
\n
"
);
break
;
}
ret
=
spansion_wait_ready
(
flash
,
SPI_FLASH_PROG_TIMEOUT
);
if
(
ret
<
0
)
{
debug
(
"SF: SPANSION page programming timed out
\n
"
);
break
;
}
page_addr
++
;
byte_addr
=
0
;
}
debug
(
"SF: SPANSION: Successfully programmed %u bytes @ 0x%x
\n
"
,
len
,
offset
);
spi_release_bus
(
flash
->
spi
);
return
ret
;
}
int
spansion_erase
(
struct
spi_flash
*
flash
,
u32
offset
,
size_t
len
)
{
struct
spansion_spi_flash
*
spsn
=
to_spansion_spi_flash
(
flash
);
unsigned
long
sector_size
;
size_t
actual
;
int
ret
;
u8
cmd
[
4
];
/*
* This function currently uses sector erase only.
* probably speed things up by using bulk erase
* when possible.
*/
sector_size
=
spsn
->
params
->
page_size
*
spsn
->
params
->
pages_per_sector
;
if
(
offset
%
sector_size
||
len
%
sector_size
)
{
debug
(
"SF: Erase offset/length not multiple of sector size
\n
"
);
return
-
1
;
}
len
/=
sector_size
;
cmd
[
0
]
=
CMD_S25FLXX_SE
;
cmd
[
2
]
=
0x00
;
cmd
[
3
]
=
0x00
;
ret
=
spi_claim_bus
(
flash
->
spi
);
if
(
ret
)
{
debug
(
"SF: Unable to claim SPI bus
\n
"
);
return
ret
;
}
ret
=
0
;
for
(
actual
=
0
;
actual
<
len
;
actual
++
)
{
cmd
[
1
]
=
(
offset
/
sector_size
)
+
actual
;
ret
=
spi_flash_cmd
(
flash
->
spi
,
CMD_S25FLXX_WREN
,
NULL
,
0
);
if
(
ret
<
0
)
{
debug
(
"SF: Enabling Write failed
\n
"
);
break
;
}
ret
=
spi_flash_cmd_write
(
flash
->
spi
,
cmd
,
4
,
NULL
,
0
);
if
(
ret
<
0
)
{
debug
(
"SF: SPANSION page erase failed
\n
"
);
break
;
}
/* Up to 2 seconds */
ret
=
spansion_wait_ready
(
flash
,
SPI_FLASH_PAGE_ERASE_TIMEOUT
);
if
(
ret
<
0
)
{
debug
(
"SF: SPANSION page erase timed out
\n
"
);
break
;
}
}
debug
(
"SF: SPANSION: Successfully erased %u bytes @ 0x%x
\n
"
,
len
*
sector_size
,
offset
);
spi_release_bus
(
flash
->
spi
);
return
ret
;
}
struct
spi_flash
*
spi_flash_probe_spansion
(
struct
spi_slave
*
spi
,
u8
*
idcode
)
{
const
struct
spansion_spi_flash_params
*
params
;
struct
spansion_spi_flash
*
spsn
;
unsigned
int
i
;
unsigned
short
jedec
,
ext_jedec
;
jedec
=
idcode
[
1
]
<<
8
|
idcode
[
2
];
ext_jedec
=
idcode
[
3
]
<<
8
|
idcode
[
4
];
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
spansion_spi_flash_table
);
i
++
)
{
params
=
&
spansion_spi_flash_table
[
i
];
if
(
params
->
idcode1
==
jedec
)
{
if
(
params
->
idcode2
==
ext_jedec
)
break
;
}
}
if
(
i
==
ARRAY_SIZE
(
spansion_spi_flash_table
))
{
debug
(
"SF: Unsupported SPANSION ID %04x %04x
\n
"
,
jedec
,
ext_jedec
);
return
NULL
;
}
spsn
=
malloc
(
sizeof
(
struct
spansion_spi_flash
));
if
(
!
spsn
)
{
debug
(
"SF: Failed to allocate memory
\n
"
);
return
NULL
;
}
spsn
->
params
=
params
;
spsn
->
flash
.
spi
=
spi
;
spsn
->
flash
.
name
=
params
->
name
;
spsn
->
flash
.
write
=
spansion_write
;
spsn
->
flash
.
erase
=
spansion_erase
;
spsn
->
flash
.
read
=
spansion_read_fast
;
spsn
->
flash
.
size
=
params
->
page_size
*
params
->
pages_per_sector
*
params
->
nr_sectors
;
debug
(
"SF: Detected %s with page size %u, total %u bytes
\n
"
,
params
->
name
,
params
->
page_size
,
spsn
->
flash
.
size
);
return
&
spsn
->
flash
;
}
drivers/mtd/spi/spi_flash.c
浏览文件 @
ca41ef30
...
...
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Atmel Corporation
*/
#define DEBUG
#include <common.h>
#include <malloc.h>
#include <spi.h>
...
...
@@ -101,7 +101,7 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
struct
spi_slave
*
spi
;
struct
spi_flash
*
flash
;
int
ret
;
u8
idcode
[
3
];
u8
idcode
[
5
];
spi
=
spi_setup_slave
(
bus
,
cs
,
max_hz
,
spi_mode
);
if
(
!
spi
)
{
...
...
@@ -120,8 +120,8 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
if
(
ret
)
goto
err_read_id
;
debug
(
"SF: Got idcode %02x %02x %02x
\n
"
,
idcode
[
0
],
idcode
[
1
],
idcode
[
2
]);
debug
(
"SF: Got idcode %02x %02x %02x
%02x %02x
\n
"
,
idcode
[
0
],
idcode
[
1
],
idcode
[
2
]
,
idcode
[
3
],
idcode
[
4
]
);
switch
(
idcode
[
0
])
{
#ifdef CONFIG_SPI_FLASH_SPANSION
...
...
@@ -138,6 +138,11 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
case
0x20
:
flash
=
spi_flash_probe_stmicro
(
spi
,
idcode
);
break
;
#endif
#ifdef CONFIG_SPI_FLASH_SST
case
0xBF
:
flash
=
spi_flash_probe_sst
(
spi
,
idcode
);
break
;
#endif
default:
debug
(
"SF: Unsupported manufacturer %02X
\n
"
,
idcode
[
0
]);
...
...
drivers/mtd/spi/spi_flash_internal.h
浏览文件 @
ca41ef30
...
...
@@ -4,9 +4,12 @@
* Copyright (C) 2008 Atmel Corporation
*/
/* Common parameters */
#define SPI_FLASH_PROG_TIMEOUT ((10 * CONFIG_SYS_HZ) / 1000)
#define SPI_FLASH_PAGE_ERASE_TIMEOUT ((50 * CONFIG_SYS_HZ) / 1000)
/* Common parameters -- kind of high, but they should only occur when there
* is a problem (and well your system already is broken), so err on the side
* of caution in case we're dealing with slower SPI buses and/or processors.
*/
#define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ)
#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ)
#define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ)
/* Common commands */
...
...
@@ -43,4 +46,5 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
/* Manufacturer-specific probe functions */
struct
spi_flash
*
spi_flash_probe_spansion
(
struct
spi_slave
*
spi
,
u8
*
idcode
);
struct
spi_flash
*
spi_flash_probe_atmel
(
struct
spi_slave
*
spi
,
u8
*
idcode
);
struct
spi_flash
*
spi_flash_probe_sst
(
struct
spi_slave
*
spi
,
u8
*
idcode
);
struct
spi_flash
*
spi_flash_probe_stmicro
(
struct
spi_slave
*
spi
,
u8
*
idcode
);
drivers/mtd/spi/sst.c
0 → 100644
浏览文件 @
ca41ef30
/*
* Driver for SST serial flashes
*
* (C) Copyright 2000-2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
* Copyright 2008, Network Appliance Inc.
* Jason McMullan <mcmullan@netapp.com>
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
* Copyright (c) 2008-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <common.h>
#include <malloc.h>
#include <spi_flash.h>
#include "spi_flash_internal.h"
#define CMD_SST_WREN 0x06
/* Write Enable */
#define CMD_SST_WRDI 0x04
/* Write Disable */
#define CMD_SST_RDSR 0x05
/* Read Status Register */
#define CMD_SST_WRSR 0x01
/* Write Status Register */
#define CMD_SST_READ 0x03
/* Read Data Bytes */
#define CMD_SST_FAST_READ 0x0b
/* Read Data Bytes at Higher Speed */
#define CMD_SST_BP 0x02
/* Byte Program */
#define CMD_SST_AAI_WP 0xAD
/* Auto Address Increment Word Program */
#define CMD_SST_SE 0x20
/* Sector Erase */
#define SST_SR_WIP (1 << 0)
/* Write-in-Progress */
#define SST_SR_WEL (1 << 1)
/* Write enable */
#define SST_SR_BP0 (1 << 2)
/* Block Protection 0 */
#define SST_SR_BP1 (1 << 3)
/* Block Protection 1 */
#define SST_SR_BP2 (1 << 4)
/* Block Protection 2 */
#define SST_SR_AAI (1 << 6)
/* Addressing mode */
#define SST_SR_BPL (1 << 7)
/* BP bits lock */
struct
sst_spi_flash_params
{
u8
idcode1
;
u16
nr_sectors
;
const
char
*
name
;
};
struct
sst_spi_flash
{
struct
spi_flash
flash
;
const
struct
sst_spi_flash_params
*
params
;
};
static
inline
struct
sst_spi_flash
*
to_sst_spi_flash
(
struct
spi_flash
*
flash
)
{
return
container_of
(
flash
,
struct
sst_spi_flash
,
flash
);
}
#define SST_SECTOR_SIZE (4 * 1024)
static
const
struct
sst_spi_flash_params
sst_spi_flash_table
[]
=
{
{
.
idcode1
=
0x01
,
.
nr_sectors
=
128
,
.
name
=
"SST25WF512"
,
},{
.
idcode1
=
0x02
,
.
nr_sectors
=
256
,
.
name
=
"SST25WF010"
,
},{
.
idcode1
=
0x03
,
.
nr_sectors
=
512
,
.
name
=
"SST25WF020"
,
},{
.
idcode1
=
0x04
,
.
nr_sectors
=
1024
,
.
name
=
"SST25WF040"
,
},
};
static
int
sst_wait_ready
(
struct
spi_flash
*
flash
,
unsigned
long
timeout
)
{
struct
spi_slave
*
spi
=
flash
->
spi
;
unsigned
long
timebase
;
int
ret
;
u8
byte
=
CMD_SST_RDSR
;
ret
=
spi_xfer
(
spi
,
sizeof
(
byte
)
*
8
,
&
byte
,
NULL
,
SPI_XFER_BEGIN
);
if
(
ret
)
{
debug
(
"SF: Failed to send command %02x: %d
\n
"
,
byte
,
ret
);
return
ret
;
}
timebase
=
get_timer
(
0
);
do
{
ret
=
spi_xfer
(
spi
,
sizeof
(
byte
)
*
8
,
NULL
,
&
byte
,
0
);
if
(
ret
)
break
;
if
((
byte
&
SST_SR_WIP
)
==
0
)
break
;
}
while
(
get_timer
(
timebase
)
<
timeout
);
spi_xfer
(
spi
,
0
,
NULL
,
NULL
,
SPI_XFER_END
);
if
(
!
ret
&&
(
byte
&
SST_SR_WIP
)
!=
0
)
ret
=
-
1
;
if
(
ret
)
debug
(
"SF: sst wait for ready timed out
\n
"
);
return
ret
;
}
static
int
sst_enable_writing
(
struct
spi_flash
*
flash
)
{
int
ret
=
spi_flash_cmd
(
flash
->
spi
,
CMD_SST_WREN
,
NULL
,
0
);
if
(
ret
)
debug
(
"SF: Enabling Write failed
\n
"
);
return
ret
;
}
static
int
sst_disable_writing
(
struct
spi_flash
*
flash
)
{
int
ret
=
spi_flash_cmd
(
flash
->
spi
,
CMD_SST_WRDI
,
NULL
,
0
);
if
(
ret
)
debug
(
"SF: Disabling Write failed
\n
"
);
return
ret
;
}
static
int
sst_read_fast
(
struct
spi_flash
*
flash
,
u32
offset
,
size_t
len
,
void
*
buf
)
{
u8
cmd
[
5
]
=
{
CMD_READ_ARRAY_FAST
,
offset
>>
16
,
offset
>>
8
,
offset
,
0x00
,
};
return
spi_flash_read_common
(
flash
,
cmd
,
sizeof
(
cmd
),
buf
,
len
);
}
static
int
sst_byte_write
(
struct
spi_flash
*
flash
,
u32
offset
,
const
void
*
buf
)
{
int
ret
;
u8
cmd
[
4
]
=
{
CMD_SST_BP
,
offset
>>
16
,
offset
>>
8
,
offset
,
};
debug
(
"BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }
\n
"
,
spi_w8r8
(
flash
->
spi
,
CMD_SST_RDSR
),
buf
,
cmd
[
0
],
offset
);
ret
=
sst_enable_writing
(
flash
);
if
(
ret
)
return
ret
;
ret
=
spi_flash_cmd_write
(
flash
->
spi
,
cmd
,
sizeof
(
cmd
),
buf
,
1
);
if
(
ret
)
return
ret
;
return
sst_wait_ready
(
flash
,
SPI_FLASH_PROG_TIMEOUT
);
}
static
int
sst_write
(
struct
spi_flash
*
flash
,
u32
offset
,
size_t
len
,
const
void
*
buf
)
{
size_t
actual
,
cmd_len
;
int
ret
;
u8
cmd
[
4
];
ret
=
spi_claim_bus
(
flash
->
spi
);
if
(
ret
)
{
debug
(
"SF: Unable to claim SPI bus
\n
"
);
return
ret
;
}
/* If the data is not word aligned, write out leading single byte */
actual
=
offset
%
2
;
if
(
actual
)
{
ret
=
sst_byte_write
(
flash
,
offset
,
buf
);
if
(
ret
)
goto
done
;
}
offset
+=
actual
;
ret
=
sst_enable_writing
(
flash
);
if
(
ret
)
goto
done
;
cmd_len
=
4
;
cmd
[
0
]
=
CMD_SST_AAI_WP
;
cmd
[
1
]
=
offset
>>
16
;
cmd
[
2
]
=
offset
>>
8
;
cmd
[
3
]
=
offset
;
for
(;
actual
<
len
-
1
;
actual
+=
2
)
{
debug
(
"WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }
\n
"
,
spi_w8r8
(
flash
->
spi
,
CMD_SST_RDSR
),
buf
+
actual
,
cmd
[
0
],
offset
);
ret
=
spi_flash_cmd_write
(
flash
->
spi
,
cmd
,
cmd_len
,
buf
+
actual
,
2
);
if
(
ret
)
{
debug
(
"SF: sst word program failed
\n
"
);
break
;
}
ret
=
sst_wait_ready
(
flash
,
SPI_FLASH_PROG_TIMEOUT
);
if
(
ret
)
break
;
cmd_len
=
1
;
offset
+=
2
;
}
if
(
!
ret
)
ret
=
sst_disable_writing
(
flash
);
/* If there is a single trailing byte, write it out */
if
(
!
ret
&&
actual
!=
len
)
ret
=
sst_byte_write
(
flash
,
offset
,
buf
+
actual
);
done:
debug
(
"SF: sst: program %s %zu bytes @ 0x%zx
\n
"
,
ret
?
"failure"
:
"success"
,
len
,
offset
-
actual
);
spi_release_bus
(
flash
->
spi
);
return
ret
;
}
int
sst_erase
(
struct
spi_flash
*
flash
,
u32
offset
,
size_t
len
)
{
unsigned
long
sector_size
;
u32
start
,
end
;
int
ret
;
u8
cmd
[
4
];
/*
* This function currently uses sector erase only.
* Probably speed things up by using bulk erase
* when possible.
*/
sector_size
=
SST_SECTOR_SIZE
;
if
(
offset
%
sector_size
)
{
debug
(
"SF: Erase offset not multiple of sector size
\n
"
);
return
-
1
;
}
ret
=
spi_claim_bus
(
flash
->
spi
);
if
(
ret
)
{
debug
(
"SF: Unable to claim SPI bus
\n
"
);
return
ret
;
}
cmd
[
0
]
=
CMD_SST_SE
;
cmd
[
3
]
=
0
;
start
=
offset
;
end
=
start
+
len
;
ret
=
0
;
while
(
offset
<
end
)
{
cmd
[
1
]
=
offset
>>
16
;
cmd
[
2
]
=
offset
>>
8
;
offset
+=
sector_size
;
debug
(
"SF: erase %2x %2x %2x %2x (%x)
\n
"
,
cmd
[
0
],
cmd
[
1
],
cmd
[
2
],
cmd
[
3
],
offset
);
ret
=
sst_enable_writing
(
flash
);
if
(
ret
)
break
;
ret
=
spi_flash_cmd_write
(
flash
->
spi
,
cmd
,
sizeof
(
cmd
),
NULL
,
0
);
if
(
ret
)
{
debug
(
"SF: sst page erase failed
\n
"
);
break
;
}
ret
=
sst_wait_ready
(
flash
,
SPI_FLASH_PAGE_ERASE_TIMEOUT
);
if
(
ret
)
break
;
}
debug
(
"SF: sst: Successfully erased %lu bytes @ 0x%x
\n
"
,
len
*
sector_size
,
start
);
spi_release_bus
(
flash
->
spi
);
return
ret
;
}
static
int
sst_unlock
(
struct
spi_flash
*
flash
)
{
int
ret
;
u8
cmd
,
status
;
ret
=
sst_enable_writing
(
flash
);
if
(
ret
)
return
ret
;
cmd
=
CMD_SST_WRSR
;
status
=
0
;
ret
=
spi_flash_cmd_write
(
flash
->
spi
,
&
cmd
,
1
,
&
status
,
1
);
if
(
ret
)
debug
(
"SF: Unable to set status byte
\n
"
);
debug
(
"SF: sst: status = %x
\n
"
,
spi_w8r8
(
flash
->
spi
,
CMD_SST_RDSR
));
return
ret
;
}
struct
spi_flash
*
spi_flash_probe_sst
(
struct
spi_slave
*
spi
,
u8
*
idcode
)
{
const
struct
sst_spi_flash_params
*
params
;
struct
sst_spi_flash
*
stm
;
size_t
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
sst_spi_flash_table
);
++
i
)
{
params
=
&
sst_spi_flash_table
[
i
];
if
(
params
->
idcode1
==
idcode
[
2
])
break
;
}
if
(
i
==
ARRAY_SIZE
(
sst_spi_flash_table
))
{
debug
(
"SF: Unsupported SST ID %02x
\n
"
,
idcode
[
1
]);
return
NULL
;
}
stm
=
malloc
(
sizeof
(
*
stm
));
if
(
!
stm
)
{
debug
(
"SF: Failed to allocate memory
\n
"
);
return
NULL
;
}
stm
->
params
=
params
;
stm
->
flash
.
spi
=
spi
;
stm
->
flash
.
name
=
params
->
name
;
stm
->
flash
.
write
=
sst_write
;
stm
->
flash
.
erase
=
sst_erase
;
stm
->
flash
.
read
=
sst_read_fast
;
stm
->
flash
.
size
=
SST_SECTOR_SIZE
*
params
->
nr_sectors
;
debug
(
"SF: Detected %s with page size %u, total %u bytes
\n
"
,
params
->
name
,
SST_SECTOR_SIZE
,
stm
->
flash
.
size
);
/* Flash powers up read-only, so clear BP# bits */
sst_unlock
(
&
stm
->
flash
);
return
&
stm
->
flash
;
}
drivers/mtd/spi/stmicro.c
浏览文件 @
ca41ef30
...
...
@@ -133,12 +133,12 @@ static int stmicro_wait_ready(struct spi_flash *flash, unsigned long timeout)
struct
spi_slave
*
spi
=
flash
->
spi
;
unsigned
long
timebase
;
int
ret
;
u8
cmd
=
CMD_M25PXX_RDSR
;
u8
status
;
u8
cmd
[
4
]
=
{
CMD_M25PXX_RDSR
,
0xff
,
0xff
,
0xff
};
ret
=
spi_xfer
(
spi
,
32
,
&
cmd
[
0
]
,
NULL
,
SPI_XFER_BEGIN
);
ret
=
spi_xfer
(
spi
,
8
,
&
cmd
,
NULL
,
SPI_XFER_BEGIN
);
if
(
ret
)
{
debug
(
"SF: Failed to send command %02x: %d
\n
"
,
cmd
[
0
]
,
ret
);
debug
(
"SF: Failed to send command %02x: %d
\n
"
,
cmd
,
ret
);
return
ret
;
}
...
...
@@ -295,8 +295,7 @@ int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
break
;
}
/* Up to 2 seconds */
ret
=
stmicro_wait_ready
(
flash
,
2
*
CONFIG_SYS_HZ
);
ret
=
stmicro_wait_ready
(
flash
,
SPI_FLASH_PAGE_ERASE_TIMEOUT
);
if
(
ret
<
0
)
{
debug
(
"SF: STMicro page erase timed out
\n
"
);
break
;
...
...
@@ -315,12 +314,6 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
const
struct
stmicro_spi_flash_params
*
params
;
struct
stmicro_spi_flash
*
stm
;
unsigned
int
i
;
int
ret
;
u8
id
[
3
];
ret
=
spi_flash_cmd
(
spi
,
CMD_READ_ID
,
id
,
sizeof
(
id
));
if
(
ret
)
return
NULL
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
stmicro_spi_flash_table
);
i
++
)
{
params
=
&
stmicro_spi_flash_table
[
i
];
...
...
@@ -330,7 +323,7 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
}
if
(
i
==
ARRAY_SIZE
(
stmicro_spi_flash_table
))
{
debug
(
"SF: Unsupported STMicro ID %02x
\n
"
,
id
[
1
]);
debug
(
"SF: Unsupported STMicro ID %02x
\n
"
,
id
code
[
1
]);
return
NULL
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录