Skip to content

Commit 003fe4b

Browse files
JaimeLiaoTWmiquelraynal
authored andcommitted
mtd: rawnand: Support for sequential cache reads
Add support for sequential cache reads for controllers using the generic core helpers for their fast read/write helpers. Sequential reads may reduce the overhead when accessing physically continuous data by loading in cache the next page while the previous page gets sent out on the NAND bus. The ONFI specification provides the following additional commands to handle sequential cached reads: * 0x31 - READ CACHE SEQUENTIAL: Requires the NAND chip to load the next page into cache while keeping the current cache available for host reads. * 0x3F - READ CACHE END: Tells the NAND chip this is the end of the sequential cache read, the current cache shall remain accessible for the host but no more internal cache loading operation is required. On the bus, a multi page read operation is currently handled like this: 00 -- ADDR1 -- 30 -- WAIT_RDY (tR+tRR) -- DATA1_IN 00 -- ADDR2 -- 30 -- WAIT_RDY (tR+tRR) -- DATA2_IN 00 -- ADDR3 -- 30 -- WAIT_RDY (tR+tRR) -- DATA3_IN Sequential cached reads may instead be achieved with: 00 -- ADDR1 -- 30 -- WAIT_RDY (tR) -- \ 31 -- WAIT_RDY (tRCBSY+tRR) -- DATA1_IN \ 31 -- WAIT_RDY (tRCBSY+tRR) -- DATA2_IN \ 3F -- WAIT_RDY (tRCBSY+tRR) -- DATA3_IN Below are the read speed test results with regular reads and sequential cached reads, on NXP i.MX6 VAR-SOM-SOLO in mapping mode with a NAND chip characterized with the following timings: * tR: 20 µs * tRCBSY: 5 µs * tRR: 20 ns and the following geometry: * device size: 2 MiB * eraseblock size: 128 kiB * page size: 2 kiB ============= Normal read @ 33MHz ================= mtd_speedtest: eraseblock read speed is 15633 KiB/s mtd_speedtest: page read speed is 15515 KiB/s mtd_speedtest: 2 page read speed is 15398 KiB/s =================================================== ========= Sequential cache read @ 33MHz =========== mtd_speedtest: eraseblock read speed is 18285 KiB/s mtd_speedtest: page read speed is 15875 KiB/s mtd_speedtest: 2 page read speed is 16253 KiB/s =================================================== We observe an overall speed improvement of about 5% when reading 2 pages, up to 15% when reading an entire block. This is due to the ~14us gain on each additional page read (tR - (tRCBSY + tRR)). Co-developed-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: JaimeLiao <jaimeliao.tw@gmail.com> Tested-by: Liao Jaime <jaimeliao.tw@gmail.com> Link: https://lore.kernel.org/linux-mtd/20230112093637.987838-4-miquel.raynal@bootlin.com
1 parent b1f9ffb commit 003fe4b

2 files changed

Lines changed: 124 additions & 4 deletions

File tree

drivers/mtd/nand/raw/nand_base.c

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,73 @@ static int nand_lp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
12081208
return nand_exec_op(chip, &op);
12091209
}
12101210

1211+
static int nand_lp_exec_cont_read_page_op(struct nand_chip *chip, unsigned int page,
1212+
unsigned int offset_in_page, void *buf,
1213+
unsigned int len, bool check_only)
1214+
{
1215+
const struct nand_interface_config *conf =
1216+
nand_get_interface_config(chip);
1217+
u8 addrs[5];
1218+
struct nand_op_instr start_instrs[] = {
1219+
NAND_OP_CMD(NAND_CMD_READ0, 0),
1220+
NAND_OP_ADDR(4, addrs, 0),
1221+
NAND_OP_CMD(NAND_CMD_READSTART, NAND_COMMON_TIMING_NS(conf, tWB_max)),
1222+
NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tR_max), 0),
1223+
NAND_OP_CMD(NAND_CMD_READCACHESEQ, NAND_COMMON_TIMING_NS(conf, tWB_max)),
1224+
NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tR_max),
1225+
NAND_COMMON_TIMING_NS(conf, tRR_min)),
1226+
NAND_OP_DATA_IN(len, buf, 0),
1227+
};
1228+
struct nand_op_instr cont_instrs[] = {
1229+
NAND_OP_CMD(page == chip->cont_read.last_page ?
1230+
NAND_CMD_READCACHEEND : NAND_CMD_READCACHESEQ,
1231+
NAND_COMMON_TIMING_NS(conf, tWB_max)),
1232+
NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tR_max),
1233+
NAND_COMMON_TIMING_NS(conf, tRR_min)),
1234+
NAND_OP_DATA_IN(len, buf, 0),
1235+
};
1236+
struct nand_operation start_op = NAND_OPERATION(chip->cur_cs, start_instrs);
1237+
struct nand_operation cont_op = NAND_OPERATION(chip->cur_cs, cont_instrs);
1238+
int ret;
1239+
1240+
if (!len) {
1241+
start_op.ninstrs--;
1242+
cont_op.ninstrs--;
1243+
}
1244+
1245+
ret = nand_fill_column_cycles(chip, addrs, offset_in_page);
1246+
if (ret < 0)
1247+
return ret;
1248+
1249+
addrs[2] = page;
1250+
addrs[3] = page >> 8;
1251+
1252+
if (chip->options & NAND_ROW_ADDR_3) {
1253+
addrs[4] = page >> 16;
1254+
start_instrs[1].ctx.addr.naddrs++;
1255+
}
1256+
1257+
/* Check if cache reads are supported */
1258+
if (check_only) {
1259+
if (nand_check_op(chip, &start_op) || nand_check_op(chip, &cont_op))
1260+
return -EOPNOTSUPP;
1261+
1262+
return 0;
1263+
}
1264+
1265+
if (page == chip->cont_read.first_page)
1266+
return nand_exec_op(chip, &start_op);
1267+
else
1268+
return nand_exec_op(chip, &cont_op);
1269+
}
1270+
1271+
static bool rawnand_cont_read_ongoing(struct nand_chip *chip, unsigned int page)
1272+
{
1273+
return chip->cont_read.ongoing &&
1274+
page >= chip->cont_read.first_page &&
1275+
page <= chip->cont_read.last_page;
1276+
}
1277+
12111278
/**
12121279
* nand_read_page_op - Do a READ PAGE operation
12131280
* @chip: The NAND chip
@@ -1233,10 +1300,16 @@ int nand_read_page_op(struct nand_chip *chip, unsigned int page,
12331300
return -EINVAL;
12341301

12351302
if (nand_has_exec_op(chip)) {
1236-
if (mtd->writesize > 512)
1237-
return nand_lp_exec_read_page_op(chip, page,
1238-
offset_in_page, buf,
1239-
len);
1303+
if (mtd->writesize > 512) {
1304+
if (rawnand_cont_read_ongoing(chip, page))
1305+
return nand_lp_exec_cont_read_page_op(chip, page,
1306+
offset_in_page,
1307+
buf, len, false);
1308+
else
1309+
return nand_lp_exec_read_page_op(chip, page,
1310+
offset_in_page, buf,
1311+
len);
1312+
}
12401313

12411314
return nand_sp_exec_read_page_op(chip, page, offset_in_page,
12421315
buf, len);
@@ -3353,6 +3426,27 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
33533426
return NULL;
33543427
}
33553428

3429+
static void rawnand_enable_cont_reads(struct nand_chip *chip, unsigned int page,
3430+
u32 readlen, int col)
3431+
{
3432+
struct mtd_info *mtd = nand_to_mtd(chip);
3433+
3434+
if (!chip->controller->supported_op.cont_read)
3435+
return;
3436+
3437+
if ((col && col + readlen < (3 * mtd->writesize)) ||
3438+
(!col && readlen < (2 * mtd->writesize))) {
3439+
chip->cont_read.ongoing = false;
3440+
return;
3441+
}
3442+
3443+
chip->cont_read.ongoing = true;
3444+
chip->cont_read.first_page = page;
3445+
if (col)
3446+
chip->cont_read.first_page++;
3447+
chip->cont_read.last_page = page + ((readlen >> chip->page_shift) & chip->pagemask);
3448+
}
3449+
33563450
/**
33573451
* nand_setup_read_retry - [INTERN] Set the READ RETRY mode
33583452
* @chip: NAND chip object
@@ -3426,6 +3520,8 @@ static int nand_do_read_ops(struct nand_chip *chip, loff_t from,
34263520
oob = ops->oobbuf;
34273521
oob_required = oob ? 1 : 0;
34283522

3523+
rawnand_enable_cont_reads(chip, page, readlen, col);
3524+
34293525
while (1) {
34303526
struct mtd_ecc_stats ecc_stats = mtd->ecc_stats;
34313527

@@ -5009,12 +5105,27 @@ static void rawnand_early_check_supported_ops(struct nand_chip *chip)
50095105
rawnand_check_data_only_read_support(chip);
50105106
}
50115107

5108+
static void rawnand_check_cont_read_support(struct nand_chip *chip)
5109+
{
5110+
struct mtd_info *mtd = nand_to_mtd(chip);
5111+
5112+
if (chip->read_retries)
5113+
return;
5114+
5115+
if (!nand_lp_exec_cont_read_page_op(chip, 0, 0, NULL,
5116+
mtd->writesize, true))
5117+
chip->controller->supported_op.cont_read = 1;
5118+
}
5119+
50125120
static void rawnand_late_check_supported_ops(struct nand_chip *chip)
50135121
{
50145122
/* The supported_op fields should not be set by individual drivers */
5123+
WARN_ON_ONCE(chip->controller->supported_op.cont_read);
50155124

50165125
if (!nand_has_exec_op(chip))
50175126
return;
5127+
5128+
rawnand_check_cont_read_support(chip);
50185129
}
50195130

50205131
/*

include/linux/mtd/rawnand.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ struct gpio_desc;
6767

6868
/* Extended commands for large page devices */
6969
#define NAND_CMD_READSTART 0x30
70+
#define NAND_CMD_READCACHESEQ 0x31
71+
#define NAND_CMD_READCACHEEND 0x3f
7072
#define NAND_CMD_RNDOUTSTART 0xE0
7173
#define NAND_CMD_CACHEDPROG 0x15
7274

@@ -1099,12 +1101,14 @@ struct nand_controller_ops {
10991101
* @supported_op.data_only_read: The controller supports reading more data from
11001102
* the bus without restarting an entire read operation nor
11011103
* changing the column.
1104+
* @supported_op.cont_read: The controller supports sequential cache reads.
11021105
*/
11031106
struct nand_controller {
11041107
struct mutex lock;
11051108
const struct nand_controller_ops *ops;
11061109
struct {
11071110
unsigned int data_only_read: 1;
1111+
unsigned int cont_read: 1;
11081112
} supported_op;
11091113
};
11101114

@@ -1308,6 +1312,11 @@ struct nand_chip {
13081312
int read_retries;
13091313
struct nand_secure_region *secure_regions;
13101314
u8 nr_secure_regions;
1315+
struct {
1316+
bool ongoing;
1317+
unsigned int first_page;
1318+
unsigned int last_page;
1319+
} cont_read;
13111320

13121321
/* Externals */
13131322
struct nand_controller *controller;

0 commit comments

Comments
 (0)