| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- From fb9ed0ef6f0ba6b6535c64dcfcf45c161723e56f Mon Sep 17 00:00:00 2001
- From: Daniel Schwierzeck <[email protected]>
- Date: Tue, 6 Nov 2012 19:31:38 +0100
- Subject: sf: add generic support for 4-byte address mode
- Signed-off-by: Daniel Schwierzeck <[email protected]>
- --- a/drivers/mtd/spi/spi_flash.c
- +++ b/drivers/mtd/spi/spi_flash.c
- @@ -18,19 +18,35 @@
- static void spi_flash_addr(struct spi_flash *flash, u32 addr, u8 *cmd, u8 *cmd_len)
- {
- /* cmd[0] is actual command */
- - cmd[1] = addr >> 16;
- - cmd[2] = addr >> 8;
- - cmd[3] = addr >> 0;
- - *cmd_len = 4;
- + if (spi_flash_use_4byte_mode(flash)) {
- + cmd[1] = addr >> 24;
- + cmd[2] = addr >> 16;
- + cmd[3] = addr >> 8;
- + cmd[4] = addr >> 0;
- + *cmd_len = 5;
- + } else {
- + cmd[1] = addr >> 16;
- + cmd[2] = addr >> 8;
- + cmd[3] = addr >> 0;
- + *cmd_len = 4;
- + }
- }
-
- static void spi_flash_page_addr(struct spi_flash *flash, u32 page_addr, u32 byte_addr, u8 *cmd, u8 *cmd_len)
- {
- /* cmd[0] is actual command */
- - cmd[1] = page_addr >> 8;
- - cmd[2] = page_addr >> 0;
- - cmd[3] = byte_addr;
- - *cmd_len = 4;
- + if (spi_flash_use_4byte_mode(flash)) {
- + cmd[1] = page_addr >> 16;
- + cmd[2] = page_addr >> 8;
- + cmd[3] = page_addr >> 0;
- + cmd[4] = byte_addr;
- + *cmd_len = 5;
- + } else {
- + cmd[1] = page_addr >> 8;
- + cmd[2] = page_addr >> 0;
- + cmd[3] = byte_addr;
- + *cmd_len = 4;
- + }
- }
-
- static int spi_flash_read_write(struct spi_slave *spi,
- @@ -81,7 +97,7 @@ int spi_flash_cmd_write_multi(struct spi
- unsigned long page_addr, byte_addr, page_size;
- size_t chunk_len, actual;
- int ret;
- - u8 cmd[4], cmd_len;
- + u8 cmd[5], cmd_len;
-
- page_size = flash->page_size;
- page_addr = offset / page_size;
- @@ -99,8 +115,8 @@ int spi_flash_cmd_write_multi(struct spi
-
- spi_flash_page_addr(flash, page_addr, byte_addr, cmd, &cmd_len);
-
- - debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
- - buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
- + debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x%02x } chunk_len = %zu\n",
- + buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], chunk_len);
-
- ret = spi_flash_cmd_write_enable(flash);
- if (ret < 0) {
- @@ -146,7 +162,7 @@ int spi_flash_read_common(struct spi_fla
- int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
- size_t len, void *data)
- {
- - u8 cmd[5], cmd_len;
- + u8 cmd[6], cmd_len;
-
- cmd[0] = CMD_READ_ARRAY_FAST;
- spi_flash_addr(flash, offset, cmd, &cmd_len);
- @@ -202,7 +218,7 @@ int spi_flash_cmd_erase(struct spi_flash
- {
- u32 start, end, erase_size;
- int ret;
- - u8 cmd[4], cmd_len;
- + u8 cmd[5], cmd_len;
-
- erase_size = flash->sector_size;
- if (offset % erase_size || len % erase_size) {
- @@ -227,8 +243,8 @@ int spi_flash_cmd_erase(struct spi_flash
- spi_flash_addr(flash, offset, cmd, &cmd_len);
- offset += erase_size;
-
- - debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
- - cmd[2], cmd[3], offset);
- + debug("SF: erase %2x %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
- + cmd[2], cmd[3], cmd[4], offset);
-
- ret = spi_flash_cmd_write_enable(flash);
- if (ret)
- @@ -409,6 +425,12 @@ int spi_flash_probe_spl(struct spi_flash
- goto err_manufacturer_probe;
- }
-
- + ret = spi_flash_set_4byte_mode(flash);
- + if (ret) {
- + debug("SF: Failed to enable 4 byte mode: %d\n", ret);
- + goto err_manufacturer_probe;
- + }
- +
- spi_release_bus(spi);
-
- return 0;
- --- a/drivers/mtd/spi/spi_flash_internal.h
- +++ b/drivers/mtd/spi/spi_flash_internal.h
- @@ -97,6 +97,31 @@ int spi_flash_cmd_wait_ready(struct spi_
- /* Erase sectors. */
- int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len);
-
- +#ifdef CONFIG_SPI_FLASH_4BYTE_MODE
- +static inline int spi_flash_use_4byte_mode(struct spi_flash *flash)
- +{
- + return NULL != flash->set_4byte_mode;
- +}
- +
- +static inline int spi_flash_set_4byte_mode(struct spi_flash *flash)
- +{
- + if (spi_flash_use_4byte_mode(flash))
- + return flash->set_4byte_mode(flash);
- +
- + return 0;
- +}
- +#else
- +static inline int spi_flash_use_4byte_mode(struct spi_flash *flash)
- +{
- + return 0;
- +}
- +
- +static inline int spi_flash_set_4byte_mode(struct spi_flash *flash)
- +{
- + return 0;
- +}
- +#endif
- +
- /* Manufacturer-specific probe functions */
- int spi_flash_probe_spansion(struct spi_flash *flash, u8 *idcode);
- int spi_flash_probe_atmel(struct spi_flash *flash, u8 *idcode);
- --- a/include/spi_flash.h
- +++ b/include/spi_flash.h
- @@ -46,6 +46,9 @@ struct spi_flash {
- size_t len, const void *buf);
- int (*erase)(struct spi_flash *flash, u32 offset,
- size_t len);
- +#ifdef CONFIG_SPI_FLASH_4BYTE_MODE
- + int (*set_4byte_mode)(struct spi_flash *flash);
- +#endif
- };
-
- struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
|