[MTD] m25p80: add FAST_READ access support to M25Pxx
Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
This commit is contained in:
parent
afc4bca639
commit
2230b76b38
|
@ -77,6 +77,13 @@ config MTD_M25P80
|
||||||
if you want to specify device partitioning or to use a device which
|
if you want to specify device partitioning or to use a device which
|
||||||
doesn't support the JEDEC ID instruction.
|
doesn't support the JEDEC ID instruction.
|
||||||
|
|
||||||
|
config M25PXX_USE_FAST_READ
|
||||||
|
bool "Use FAST_READ OPCode allowing SPI CLK <= 50MHz"
|
||||||
|
depends on MTD_M25P80
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
This option enables FAST_READ access supported by ST M25Pxx.
|
||||||
|
|
||||||
config MTD_SLRAM
|
config MTD_SLRAM
|
||||||
tristate "Uncached system RAM"
|
tristate "Uncached system RAM"
|
||||||
help
|
help
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
/* Flash opcodes. */
|
/* Flash opcodes. */
|
||||||
#define OPCODE_WREN 0x06 /* Write enable */
|
#define OPCODE_WREN 0x06 /* Write enable */
|
||||||
#define OPCODE_RDSR 0x05 /* Read status register */
|
#define OPCODE_RDSR 0x05 /* Read status register */
|
||||||
#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */
|
#define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */
|
||||||
#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
|
#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
|
||||||
#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
|
#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
|
||||||
#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
|
#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
|
||||||
|
@ -52,7 +52,15 @@
|
||||||
|
|
||||||
/* Define max times to check status register before we give up. */
|
/* Define max times to check status register before we give up. */
|
||||||
#define MAX_READY_WAIT_COUNT 100000
|
#define MAX_READY_WAIT_COUNT 100000
|
||||||
|
#define CMD_SIZE 4
|
||||||
|
|
||||||
|
#ifdef CONFIG_M25PXX_USE_FAST_READ
|
||||||
|
#define OPCODE_READ OPCODE_FAST_READ
|
||||||
|
#define FAST_READ_DUMMY_BYTE 1
|
||||||
|
#else
|
||||||
|
#define OPCODE_READ OPCODE_NORM_READ
|
||||||
|
#define FAST_READ_DUMMY_BYTE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_PARTITIONS
|
#ifdef CONFIG_MTD_PARTITIONS
|
||||||
#define mtd_has_partitions() (1)
|
#define mtd_has_partitions() (1)
|
||||||
|
@ -68,7 +76,7 @@ struct m25p {
|
||||||
struct mtd_info mtd;
|
struct mtd_info mtd;
|
||||||
unsigned partitioned:1;
|
unsigned partitioned:1;
|
||||||
u8 erase_opcode;
|
u8 erase_opcode;
|
||||||
u8 command[4];
|
u8 command[CMD_SIZE + FAST_READ_DUMMY_BYTE];
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
|
static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
|
||||||
|
@ -167,7 +175,7 @@ static int erase_sector(struct m25p *flash, u32 offset)
|
||||||
flash->command[2] = offset >> 8;
|
flash->command[2] = offset >> 8;
|
||||||
flash->command[3] = offset;
|
flash->command[3] = offset;
|
||||||
|
|
||||||
spi_write(flash->spi, flash->command, sizeof(flash->command));
|
spi_write(flash->spi, flash->command, CMD_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -253,8 +261,12 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
spi_message_init(&m);
|
spi_message_init(&m);
|
||||||
memset(t, 0, (sizeof t));
|
memset(t, 0, (sizeof t));
|
||||||
|
|
||||||
|
/* NOTE:
|
||||||
|
* OPCODE_FAST_READ (if available) is faster.
|
||||||
|
* Should add 1 byte DUMMY_BYTE.
|
||||||
|
*/
|
||||||
t[0].tx_buf = flash->command;
|
t[0].tx_buf = flash->command;
|
||||||
t[0].len = sizeof(flash->command);
|
t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
|
||||||
spi_message_add_tail(&t[0], &m);
|
spi_message_add_tail(&t[0], &m);
|
||||||
|
|
||||||
t[1].rx_buf = buf;
|
t[1].rx_buf = buf;
|
||||||
|
@ -287,7 +299,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
|
||||||
spi_sync(flash->spi, &m);
|
spi_sync(flash->spi, &m);
|
||||||
|
|
||||||
*retlen = m.actual_length - sizeof(flash->command);
|
*retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;
|
||||||
|
|
||||||
mutex_unlock(&flash->lock);
|
mutex_unlock(&flash->lock);
|
||||||
|
|
||||||
|
@ -325,7 +337,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
memset(t, 0, (sizeof t));
|
memset(t, 0, (sizeof t));
|
||||||
|
|
||||||
t[0].tx_buf = flash->command;
|
t[0].tx_buf = flash->command;
|
||||||
t[0].len = sizeof(flash->command);
|
t[0].len = CMD_SIZE;
|
||||||
spi_message_add_tail(&t[0], &m);
|
spi_message_add_tail(&t[0], &m);
|
||||||
|
|
||||||
t[1].tx_buf = buf;
|
t[1].tx_buf = buf;
|
||||||
|
@ -354,7 +366,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
|
|
||||||
spi_sync(flash->spi, &m);
|
spi_sync(flash->spi, &m);
|
||||||
|
|
||||||
*retlen = m.actual_length - sizeof(flash->command);
|
*retlen = m.actual_length - CMD_SIZE;
|
||||||
} else {
|
} else {
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
|
@ -364,7 +376,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
t[1].len = page_size;
|
t[1].len = page_size;
|
||||||
spi_sync(flash->spi, &m);
|
spi_sync(flash->spi, &m);
|
||||||
|
|
||||||
*retlen = m.actual_length - sizeof(flash->command);
|
*retlen = m.actual_length - CMD_SIZE;
|
||||||
|
|
||||||
/* write everything in PAGESIZE chunks */
|
/* write everything in PAGESIZE chunks */
|
||||||
for (i = page_size; i < len; i += page_size) {
|
for (i = page_size; i < len; i += page_size) {
|
||||||
|
@ -387,8 +399,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
spi_sync(flash->spi, &m);
|
spi_sync(flash->spi, &m);
|
||||||
|
|
||||||
if (retlen)
|
if (retlen)
|
||||||
*retlen += m.actual_length
|
*retlen += m.actual_length - CMD_SIZE;
|
||||||
- sizeof(flash->command);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue