Skip to content

Commit 7298335

Browse files
miquelraynalgregkh
authored andcommitted
mtd: spinand: Create an array of operation templates
[ Upstream commit 4080150 ] Currently, the SPI NAND core implementation directly calls macros to get the various operations in shape. These macros are specific to the bus interface, currently only supporting the single SDR interface (any command following the 1S-XX-XX pattern). Introducing support for other bus interfaces (such as octal DTR) would mean that every user of these macros should become aware of the current bus interface and act accordingly, picking up and adapting to the current configuration. This would add quite a bit of boilerplate, be repetitive as well as error prone in case we miss one occurrence. Instead, let's create a table with all SPI NAND memory operations that are currently supported. We initialize them with the same single SDR _OP macros as before. This opens the possibility for users of the individual macros to make use of these templates instead. This way, when we will add another bus interface, we can just switch to another set of templates and all users will magically fill in their spi_mem_op structures with the correct ops. The existing read, write and update cache variants are also moved in this template array, which is barely noticeable by callers as we also add a structure member pointing to it. Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Stable-dep-of: 25a915f ("mtd: spinand: winbond: Clarify when to enable the HS bit") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent d5de6d3 commit 7298335

3 files changed

Lines changed: 64 additions & 21 deletions

File tree

drivers/mtd/nand/spi/core.c

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,9 @@ static int spinand_init_quad_enable(struct spinand_device *spinand)
184184
if (!(spinand->flags & SPINAND_HAS_QE_BIT))
185185
return 0;
186186

187-
if (spinand->op_templates.read_cache->data.buswidth == 4 ||
188-
spinand->op_templates.write_cache->data.buswidth == 4 ||
189-
spinand->op_templates.update_cache->data.buswidth == 4)
187+
if (spinand->op_templates->read_cache->data.buswidth == 4 ||
188+
spinand->op_templates->write_cache->data.buswidth == 4 ||
189+
spinand->op_templates->update_cache->data.buswidth == 4)
190190
enable = true;
191191

192192
return spinand_upd_cfg(spinand, CFG_QUAD_ENABLE,
@@ -1162,15 +1162,15 @@ static int spinand_create_dirmap(struct spinand_device *spinand,
11621162
info.offset = plane << fls(nand->memorg.pagesize);
11631163

11641164
info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
1165-
info.op_tmpl = *spinand->op_templates.update_cache;
1165+
info.op_tmpl = *spinand->op_templates->update_cache;
11661166
desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
11671167
spinand->spimem, &info);
11681168
if (IS_ERR(desc))
11691169
return PTR_ERR(desc);
11701170

11711171
spinand->dirmaps[plane].wdesc = desc;
11721172

1173-
info.op_tmpl = *spinand->op_templates.read_cache;
1173+
info.op_tmpl = *spinand->op_templates->read_cache;
11741174
desc = spinand_create_rdesc(spinand, &info);
11751175
if (IS_ERR(desc))
11761176
return PTR_ERR(desc);
@@ -1185,7 +1185,7 @@ static int spinand_create_dirmap(struct spinand_device *spinand,
11851185
}
11861186

11871187
info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
1188-
info.op_tmpl = *spinand->op_templates.update_cache;
1188+
info.op_tmpl = *spinand->op_templates->update_cache;
11891189
info.op_tmpl.data.ecc = true;
11901190
desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
11911191
spinand->spimem, &info);
@@ -1194,7 +1194,7 @@ static int spinand_create_dirmap(struct spinand_device *spinand,
11941194

11951195
spinand->dirmaps[plane].wdesc_ecc = desc;
11961196

1197-
info.op_tmpl = *spinand->op_templates.read_cache;
1197+
info.op_tmpl = *spinand->op_templates->read_cache;
11981198
info.op_tmpl.data.ecc = true;
11991199
desc = spinand_create_rdesc(spinand, &info);
12001200
if (IS_ERR(desc))
@@ -1330,6 +1330,22 @@ static void spinand_manufacturer_cleanup(struct spinand_device *spinand)
13301330
return spinand->manufacturer->ops->cleanup(spinand);
13311331
}
13321332

1333+
static void spinand_init_ssdr_templates(struct spinand_device *spinand)
1334+
{
1335+
struct spinand_mem_ops *tmpl = &spinand->ssdr_op_templates;
1336+
1337+
tmpl->reset = (struct spi_mem_op)SPINAND_RESET_1S_0_0_OP;
1338+
tmpl->readid = (struct spi_mem_op)SPINAND_READID_1S_1S_1S_OP(0, 0, NULL, 0);
1339+
tmpl->wr_en = (struct spi_mem_op)SPINAND_WR_EN_1S_0_0_OP;
1340+
tmpl->wr_dis = (struct spi_mem_op)SPINAND_WR_DIS_1S_0_0_OP;
1341+
tmpl->set_feature = (struct spi_mem_op)SPINAND_SET_FEATURE_1S_1S_1S_OP(0, NULL);
1342+
tmpl->get_feature = (struct spi_mem_op)SPINAND_GET_FEATURE_1S_1S_1S_OP(0, NULL);
1343+
tmpl->blk_erase = (struct spi_mem_op)SPINAND_BLK_ERASE_1S_1S_0_OP(0);
1344+
tmpl->page_read = (struct spi_mem_op)SPINAND_PAGE_READ_1S_1S_0_OP(0);
1345+
tmpl->prog_exec = (struct spi_mem_op)SPINAND_PROG_EXEC_1S_1S_0_OP(0);
1346+
spinand->op_templates = &spinand->ssdr_op_templates;
1347+
}
1348+
13331349
static const struct spi_mem_op *
13341350
spinand_select_op_variant(struct spinand_device *spinand,
13351351
const struct spinand_op_variants *variants)
@@ -1425,21 +1441,21 @@ int spinand_match_and_init(struct spinand_device *spinand,
14251441
if (!op)
14261442
return -ENOTSUPP;
14271443

1428-
spinand->op_templates.read_cache = op;
1444+
spinand->ssdr_op_templates.read_cache = op;
14291445

14301446
op = spinand_select_op_variant(spinand,
14311447
info->op_variants.write_cache);
14321448
if (!op)
14331449
return -ENOTSUPP;
14341450

1435-
spinand->op_templates.write_cache = op;
1451+
spinand->ssdr_op_templates.write_cache = op;
14361452

14371453
op = spinand_select_op_variant(spinand,
14381454
info->op_variants.update_cache);
14391455
if (!op)
14401456
return -ENOTSUPP;
14411457

1442-
spinand->op_templates.update_cache = op;
1458+
spinand->ssdr_op_templates.update_cache = op;
14431459

14441460
return 0;
14451461
}
@@ -1554,6 +1570,8 @@ static int spinand_init(struct spinand_device *spinand)
15541570
if (!spinand->scratchbuf)
15551571
return -ENOMEM;
15561572

1573+
spinand_init_ssdr_templates(spinand);
1574+
15571575
ret = spinand_detect(spinand);
15581576
if (ret)
15591577
goto err_free_bufs;

drivers/mtd/nand/spi/winbond.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ static int w25n0xjw_hs_cfg(struct spinand_device *spinand)
291291
u8 sr4;
292292
int ret;
293293

294-
op = spinand->op_templates.read_cache;
294+
op = spinand->op_templates->read_cache;
295295
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
296296
hs = false;
297297
else if (op->cmd.buswidth == 1 && op->addr.buswidth == 1 &&
@@ -355,7 +355,7 @@ static int w35n0xjw_vcr_cfg(struct spinand_device *spinand)
355355
u8 io_mode;
356356
int ret;
357357

358-
op = spinand->op_templates.read_cache;
358+
op = spinand->op_templates->read_cache;
359359

360360
single = (op->cmd.buswidth == 1 && op->addr.buswidth == 1 && op->data.buswidth == 1);
361361
dtr = (op->cmd.dtr || op->addr.dtr || op->data.dtr);

include/linux/mtd/spinand.h

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -604,17 +604,45 @@ struct spinand_dirmap {
604604
struct spi_mem_dirmap_desc *rdesc_ecc;
605605
};
606606

607+
/**
608+
* struct spinand_mem_ops - SPI NAND memory operations
609+
* @reset: reset op template
610+
* @readid: read ID op template
611+
* @wr_en: write enable op template
612+
* @wr_dis: write disable op template
613+
* @set_feature: set feature op template
614+
* @get_feature: get feature op template
615+
* @blk_erase: blk erase op template
616+
* @page_read: page read op template
617+
* @prog_exec: prog exec op template
618+
* @read_cache: read cache op template
619+
* @write_cache: write cache op template
620+
* @update_cache: update cache op template
621+
*/
622+
struct spinand_mem_ops {
623+
struct spi_mem_op reset;
624+
struct spi_mem_op readid;
625+
struct spi_mem_op wr_en;
626+
struct spi_mem_op wr_dis;
627+
struct spi_mem_op set_feature;
628+
struct spi_mem_op get_feature;
629+
struct spi_mem_op blk_erase;
630+
struct spi_mem_op page_read;
631+
struct spi_mem_op prog_exec;
632+
const struct spi_mem_op *read_cache;
633+
const struct spi_mem_op *write_cache;
634+
const struct spi_mem_op *update_cache;
635+
};
636+
607637
/**
608638
* struct spinand_device - SPI NAND device instance
609639
* @base: NAND device instance
610640
* @spimem: pointer to the SPI mem object
611641
* @lock: lock used to serialize accesses to the NAND
612642
* @id: NAND ID as returned by READ_ID
613643
* @flags: NAND flags
614-
* @op_templates: various SPI mem op templates
615-
* @op_templates.read_cache: read cache op template
616-
* @op_templates.write_cache: write cache op template
617-
* @op_templates.update_cache: update cache op template
644+
* @ssdr_op_templates: Templates for all single SDR SPI mem operations
645+
* @op_templates: Templates for all SPI mem operations
618646
* @select_target: select a specific target/die. Usually called before sending
619647
* a command addressing a page or an eraseblock embedded in
620648
* this die. Only required if your chip exposes several dies
@@ -648,11 +676,8 @@ struct spinand_device {
648676
struct spinand_id id;
649677
u32 flags;
650678

651-
struct {
652-
const struct spi_mem_op *read_cache;
653-
const struct spi_mem_op *write_cache;
654-
const struct spi_mem_op *update_cache;
655-
} op_templates;
679+
struct spinand_mem_ops ssdr_op_templates;
680+
struct spinand_mem_ops *op_templates;
656681

657682
struct spinand_dirmap *dirmaps;
658683

0 commit comments

Comments
 (0)