Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Sami Nurmenniemi
u-boot-stm32
Commits
84a54a92
Commit
84a54a92
authored
Feb 04, 2013
by
Vladimir Skvortsov
Browse files
RT #82124. Add support for Atmel AT25DF641-MWH-T SPI flash.
parent
4b660ce7
Changes
2
Hide whitespace changes
Inline
Side-by-side
drivers/mtd/spi/atmel.c
View file @
84a54a92
...
...
@@ -25,6 +25,20 @@
#define AT45_STATUS_P2_PAGE_SIZE (1 << 0)
#define AT45_STATUS_READY (1 << 7)
/* AT25-specific commands */
#define CMD_AT25_WRITE_SR 0x01
#define CMD_AT25_BYTEPAGE_PROGRAM 0x02
#define CMD_AT25_READ_STATUS 0x05
#define CMD_AT25_WREN 0x06
#define CMD_AT25_ERASE_BLOCK_4K 0x20
#define CMD_AT25_ERASE_BLOCK_32K 0x52
#define CMD_AT25_ERASE_BLOCK_64K 0xD8
/* AT25 status register bits */
#define AT25_STATUS_BUSY (1 << 0)
#define AT25_ERASE_BLOCK_SIZE 0x1000
/* 4-Kbytes */
/* DataFlash family IDs, as obtained from the second idcode byte */
#define DF_FAMILY_AT26F 0
#define DF_FAMILY_AT45 1
...
...
@@ -109,6 +123,14 @@ static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
.
nr_sectors
=
32
,
.
name
=
"AT45DB642D"
,
},
{
.
idcode1
=
0x48
,
.
l2_page_size
=
8
,
.
pages_per_block
=
16
,
.
blocks_per_sector
=
16
,
.
nr_sectors
=
128
,
.
name
=
"AT25DF641"
,
},
};
static
int
at45_wait_ready
(
struct
spi_flash
*
flash
,
unsigned
long
timeout
)
...
...
@@ -464,6 +486,170 @@ out:
return
ret
;
}
/*
* TODO: This impementation of flash operations for AT25 and AT26 family chips is
* similar to other implemented in spansion.c and stmicro.c and should get unified ...
*/
static
int
at25_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_AT25_READ_STATUS
,
&
status
,
sizeof
(
status
));
if
(
ret
)
return
-
1
;
if
((
status
&
AT25_STATUS_BUSY
)
==
0
)
break
;
}
while
(
get_timer
(
timebase
)
<
timeout
);
if
((
status
&
AT25_STATUS_BUSY
)
==
0
)
return
0
;
/* Timed out */
return
-
1
;
}
static
int
dataflash_write_at25
(
struct
spi_flash
*
flash
,
u32
offset
,
size_t
len
,
const
void
*
buf
)
{
struct
atmel_spi_flash
*
asf
=
to_atmel_spi_flash
(
flash
);
unsigned
long
page_size
;
u32
addr
=
offset
;
size_t
chunk_len
;
size_t
actual
;
int
ret
;
u8
cmd
[
4
];
/*
* TODO: This function currently uses only page buffer #1. We can
* speed this up by using both buffers and loading one buffer while
* the other is being programmed into main memory.
*/
page_size
=
(
1
<<
asf
->
params
->
l2_page_size
);
ret
=
spi_claim_bus
(
flash
->
spi
);
if
(
ret
)
{
debug
(
"SF: Unable to claim SPI bus
\n
"
);
return
ret
;
}
for
(
actual
=
0
;
actual
<
len
;
actual
+=
chunk_len
)
{
chunk_len
=
min
(
len
-
actual
,
page_size
-
(
addr
%
page_size
));
/* Use the same address bits for both commands */
cmd
[
0
]
=
CMD_AT25_BYTEPAGE_PROGRAM
;
cmd
[
1
]
=
addr
>>
16
;
cmd
[
2
]
=
addr
>>
8
;
cmd
[
3
]
=
addr
;
ret
=
spi_flash_cmd
(
flash
->
spi
,
CMD_AT25_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: Loading AT25 buffer failed
\n
"
);
goto
out
;
}
ret
=
at25_wait_ready
(
flash
,
SPI_FLASH_PROG_TIMEOUT
);
if
(
ret
<
0
)
{
debug
(
"SF: AT25 page programming timed out
\n
"
);
goto
out
;
}
addr
+=
chunk_len
;
}
debug
(
"SF: AT25: Successfully programmed %zu bytes @ 0x%x
\n
"
,
len
,
offset
);
ret
=
0
;
out:
spi_release_bus
(
flash
->
spi
);
return
ret
;
}
int
dataflash_erase_at25
(
struct
spi_flash
*
flash
,
u32
offset
,
size_t
len
)
{
struct
atmel_spi_flash
*
asf
=
to_atmel_spi_flash
(
flash
);
unsigned
long
block_size
;
size_t
actual
;
int
ret
;
u8
cmd
[
4
];
/*
* TODO: This function currently uses 4K block erase only. We can
* probably speed things up by using 32K and 64K erase block sizes.
*/
block_size
=
(
1
<<
asf
->
params
->
l2_page_size
)
*
asf
->
params
->
pages_per_block
;
if
(
block_size
!=
AT25_ERASE_BLOCK_SIZE
)
{
/* support only 4K block size */
return
-
1
;
}
if
(
offset
%
block_size
||
len
%
block_size
)
{
debug
(
"SF: Erase offset/length not multiple of page size
\n
"
);
return
-
1
;
}
cmd
[
0
]
=
CMD_AT25_ERASE_BLOCK_4K
;
cmd
[
3
]
=
0x00
;
ret
=
spi_claim_bus
(
flash
->
spi
);
if
(
ret
)
{
debug
(
"SF: Unable to claim SPI bus
\n
"
);
return
ret
;
}
for
(
actual
=
0
;
actual
<
len
;
actual
+=
block_size
)
{
cmd
[
1
]
=
offset
>>
16
;
cmd
[
2
]
=
offset
>>
8
;
ret
=
spi_flash_cmd
(
flash
->
spi
,
CMD_AT25_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: AT25 page erase failed
\n
"
);
goto
out
;
}
ret
=
at25_wait_ready
(
flash
,
SPI_FLASH_PAGE_ERASE_TIMEOUT
);
if
(
ret
<
0
)
{
debug
(
"SF: AT25 page erase timed out
\n
"
);
goto
out
;
}
offset
+=
block_size
;
}
debug
(
"SF: AT25: Successfully erased %zu bytes @ 0x%x
\n
"
,
len
,
offset
);
ret
=
0
;
out:
spi_release_bus
(
flash
->
spi
);
return
ret
;
}
struct
spi_flash
*
spi_flash_probe_atmel
(
struct
spi_slave
*
spi
,
u8
*
idcode
)
{
const
struct
atmel_spi_flash_params
*
params
;
...
...
@@ -473,6 +659,7 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
unsigned
int
i
;
int
ret
;
u8
status
;
u8
cmd
[
2
];
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
atmel_spi_flash_table
);
i
++
)
{
params
=
&
atmel_spi_flash_table
[
i
];
...
...
@@ -529,6 +716,21 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
case
DF_FAMILY_AT26F
:
case
DF_FAMILY_AT26DF
:
asf
->
flash
.
read
=
dataflash_read_fast_p2
;
asf
->
flash
.
write
=
dataflash_write_at25
;
asf
->
flash
.
erase
=
dataflash_erase_at25
;
/* clear sectors protection bits */
ret
=
spi_flash_cmd
(
spi
,
CMD_AT25_WREN
,
NULL
,
0
);
if
(
ret
!=
0
)
{
goto
err
;
}
cmd
[
0
]
=
CMD_AT25_WRITE_SR
;
cmd
[
1
]
=
0
;
ret
=
spi_flash_cmd_write
(
spi
,
cmd
,
2
,
NULL
,
0
);
if
(
ret
!=
0
)
{
goto
err
;
}
break
;
default:
...
...
include/configs/sf2-dev-kit.h
View file @
84a54a92
...
...
@@ -123,8 +123,8 @@
#define CONFIG_MEM_NVM_UBOOT_OFF (128 * 1024)
#endif
#define CONFIG_MEM_RAM_BASE
0x20000000
#define CONFIG_MEM_RAM_LEN
(16 * 1024)
#define CONFIG_MEM_RAM_BASE 0x20000000
#define CONFIG_MEM_RAM_LEN (16 * 1024)
#define CONFIG_MEM_RAM_BUF_LEN (32 * 1024)
#define CONFIG_MEM_MALLOC_LEN (12 * 1024)
#define CONFIG_MEM_STACK_LEN (4 * 1024)
...
...
@@ -138,8 +138,8 @@
* Configuration of the external memory
*/
#define CONFIG_NR_DRAM_BANKS 1
#define CONFIG_SYS_RAM_BASE
0xA0000000
#define CONFIG_SYS_RAM_SIZE
(1
6 * 1024 * 1024)
#define CONFIG_SYS_RAM_BASE 0xA0000000
#define CONFIG_SYS_RAM_SIZE
(25
6 * 1024 * 1024)
/*
* Configuration of the external Flash
...
...
@@ -147,23 +147,52 @@
*/
#define CONFIG_SYS_NO_FLASH
/*
* Configure the SPI contoler device driver
* FIFO Size is 64K, but leave 5 bytes for cmd[] + addr[]
*/
#define CONFIG_M2S_SPI 1
#define CONFIG_SPI_MAX_XF_LEN 65530
/*
* Configure SPI Flash
*/
#define CONFIG_SPI_FLASH 1
#define CONFIG_SPI_FLASH_ATMEL 1
#define CONFIG_SPI_FLASH_BUS 0
#define CONFIG_SPI_FLASH_CS 0
#define CONFIG_SPI_FLASH_MODE 3
#define CONFIG_SPI_FLASH_SPEED (CONFIG_SYS_M2S_SYSREF / 4)
#define CONFIG_SF_DEFAULT_SPEED CONFIG_SPI_FLASH_SPEED
#define CONFIG_SF_DEFAULT_MODE CONFIG_SPI_FLASH_MODE
/*
* U-boot environment configuration
*/
#define CONFIG_ENV_IS_NOWHERE 1
#define CONFIG_ENV_SIZE 0x1000
#define CONFIG_ENV_IS_IN_SPI_FLASH 1
#define CONFIG_ENV_SECT_SIZE 0x1000
#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
#define CONFIG_ENV_OFFSET 0x0
#define CONFIG_ENV_SPI_BUS CONFIG_SPI_FLASH_BUS
#define CONFIG_ENV_SPI_CS CONFIG_SPI_FLASH_CS
#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SPI_FLASH_SPEED
#define CONFIG_ENV_SPI_MODE CONFIG_SPI_FLASH_MODE
#define CONFIG_INFERNO 1
#define CONFIG_ENV_OVERWRITE 1
/*
* Serial console configuration: MSS UART1
*/
#define CONFIG_SYS_NS16550
1
#define CONFIG_SYS_NS16550 1
#undef CONFIG_NS16550_MIN_FUNCTIONS
#define CONFIG_SYS_NS16550_SERIAL 1
#define CONFIG_SYS_NS16550_REG_SIZE (-4)
#define CONFIG_SYS_NS16550_CLK clock_get(CLOCK_PCLK1)
#define CONFIG_CONS_INDEX
2
#define CONFIG_CONS_INDEX 2
#define CONFIG_SYS_NS16550_COM2 0x40010000
#define CONFIG_BAUDRATE
115200
#define CONFIG_BAUDRATE 115200
#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
/*
...
...
@@ -255,22 +284,22 @@
/*
* Short-cuts to some useful commands (macros)
*/
#define CONFIG_EXTRA_ENV_SETTINGS
\
"loadaddr=" MK_STR(UIMAGE_LOADADDR) "\0"
\
"image=networking.uImage\0"
\
"spiaddr=" MK_STR(CONFIG_ENV_IMG_OFFSET) "\0"
\
"spisize=400000\0"
\
#define CONFIG_EXTRA_ENV_SETTINGS \
"loadaddr=" MK_STR(UIMAGE_LOADADDR) "\0" \
"image=networking.uImage\0" \
"spiaddr=" MK_STR(CONFIG_ENV_IMG_OFFSET) "\0" \
"spisize=400000\0" \
"spiprobe=sf probe " MK_STR(CONFIG_SPI_FLASH_BUS) "\0" \
"addip=setenv bootargs ${bootargs}"
\
" ip=${ipaddr}:${serverip}:${gatewayip}:"
\
"${netmask}:${hostname}:eth0:off\0"
\
"flashboot=run addip;run spiprobe;"
\
" sf read ${loadaddr} ${spiaddr} ${spisize};"
\
" bootm ${loadaddr}\0"
\
"addip=setenv bootargs ${bootargs}" \
" ip=${ipaddr}:${serverip}:${gatewayip}:" \
"${netmask}:${hostname}:eth0:off\0" \
"flashboot=run addip;run spiprobe;" \
" sf read ${loadaddr} ${spiaddr} ${spisize};" \
" bootm ${loadaddr}\0" \
"netboot=tftp ${loadaddr} ${image};run addip;bootm\0" \
"update=tftp ${loadaddr} ${image};run spiprobe;"
\
" sf erase ${spiaddr} ${filesize};"
\
" sf write ${loadaddr} ${spiaddr} ${filesize};"
\
"update=tftp ${loadaddr} ${image};run spiprobe;" \
" sf erase ${spiaddr} ${filesize};" \
" sf write ${loadaddr} ${spiaddr} ${filesize};" \
" setenv spisize 0x${filesize}; saveenv\0"
/*
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment