Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mtd: spinand: Create an array of operation templates

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>

+64 -21
+28 -10
drivers/mtd/nand/spi/core.c
··· 184 184 if (!(spinand->flags & SPINAND_HAS_QE_BIT)) 185 185 return 0; 186 186 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) 190 190 enable = true; 191 191 192 192 return spinand_upd_cfg(spinand, CFG_QUAD_ENABLE, ··· 1154 1154 info.offset = plane << fls(nand->memorg.pagesize); 1155 1155 1156 1156 info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); 1157 - info.op_tmpl = *spinand->op_templates.update_cache; 1157 + info.op_tmpl = *spinand->op_templates->update_cache; 1158 1158 desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, 1159 1159 spinand->spimem, &info); 1160 1160 if (IS_ERR(desc)) ··· 1162 1162 1163 1163 spinand->dirmaps[plane].wdesc = desc; 1164 1164 1165 - info.op_tmpl = *spinand->op_templates.read_cache; 1165 + info.op_tmpl = *spinand->op_templates->read_cache; 1166 1166 desc = spinand_create_rdesc(spinand, &info); 1167 1167 if (IS_ERR(desc)) 1168 1168 return PTR_ERR(desc); ··· 1177 1177 } 1178 1178 1179 1179 info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); 1180 - info.op_tmpl = *spinand->op_templates.update_cache; 1180 + info.op_tmpl = *spinand->op_templates->update_cache; 1181 1181 info.op_tmpl.data.ecc = true; 1182 1182 desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, 1183 1183 spinand->spimem, &info); ··· 1186 1186 1187 1187 spinand->dirmaps[plane].wdesc_ecc = desc; 1188 1188 1189 - info.op_tmpl = *spinand->op_templates.read_cache; 1189 + info.op_tmpl = *spinand->op_templates->read_cache; 1190 1190 info.op_tmpl.data.ecc = true; 1191 1191 desc = spinand_create_rdesc(spinand, &info); 1192 1192 if (IS_ERR(desc)) ··· 1324 1324 return spinand->manufacturer->ops->cleanup(spinand); 1325 1325 } 1326 1326 1327 + static void spinand_init_ssdr_templates(struct spinand_device *spinand) 1328 + { 1329 + struct spinand_mem_ops *tmpl = &spinand->ssdr_op_templates; 1330 + 1331 + tmpl->reset = (struct spi_mem_op)SPINAND_RESET_1S_0_0_OP; 1332 + tmpl->readid = (struct spi_mem_op)SPINAND_READID_1S_1S_1S_OP(0, 0, NULL, 0); 1333 + tmpl->wr_en = (struct spi_mem_op)SPINAND_WR_EN_1S_0_0_OP; 1334 + tmpl->wr_dis = (struct spi_mem_op)SPINAND_WR_DIS_1S_0_0_OP; 1335 + tmpl->set_feature = (struct spi_mem_op)SPINAND_SET_FEATURE_1S_1S_1S_OP(0, NULL); 1336 + tmpl->get_feature = (struct spi_mem_op)SPINAND_GET_FEATURE_1S_1S_1S_OP(0, NULL); 1337 + tmpl->blk_erase = (struct spi_mem_op)SPINAND_BLK_ERASE_1S_1S_0_OP(0); 1338 + tmpl->page_read = (struct spi_mem_op)SPINAND_PAGE_READ_1S_1S_0_OP(0); 1339 + tmpl->prog_exec = (struct spi_mem_op)SPINAND_PROG_EXEC_1S_1S_0_OP(0); 1340 + spinand->op_templates = &spinand->ssdr_op_templates; 1341 + } 1342 + 1327 1343 static const struct spi_mem_op * 1328 1344 spinand_select_op_variant(struct spinand_device *spinand, 1329 1345 const struct spinand_op_variants *variants) ··· 1435 1419 if (!op) 1436 1420 return -EOPNOTSUPP; 1437 1421 1438 - spinand->op_templates.read_cache = op; 1422 + spinand->ssdr_op_templates.read_cache = op; 1439 1423 1440 1424 op = spinand_select_op_variant(spinand, 1441 1425 info->op_variants.write_cache); 1442 1426 if (!op) 1443 1427 return -EOPNOTSUPP; 1444 1428 1445 - spinand->op_templates.write_cache = op; 1429 + spinand->ssdr_op_templates.write_cache = op; 1446 1430 1447 1431 op = spinand_select_op_variant(spinand, 1448 1432 info->op_variants.update_cache); 1449 1433 if (!op) 1450 1434 return -EOPNOTSUPP; 1451 1435 1452 - spinand->op_templates.update_cache = op; 1436 + spinand->ssdr_op_templates.update_cache = op; 1453 1437 1454 1438 return 0; 1455 1439 } ··· 1563 1547 spinand->scratchbuf = kzalloc(SPINAND_MAX_ID_LEN, GFP_KERNEL); 1564 1548 if (!spinand->scratchbuf) 1565 1549 return -ENOMEM; 1550 + 1551 + spinand_init_ssdr_templates(spinand); 1566 1552 1567 1553 ret = spinand_detect(spinand); 1568 1554 if (ret)
+2 -2
drivers/mtd/nand/spi/winbond.c
··· 291 291 u8 sr4; 292 292 int ret; 293 293 294 - op = spinand->op_templates.read_cache; 294 + op = spinand->op_templates->read_cache; 295 295 if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) 296 296 hs = false; 297 297 else if (op->cmd.buswidth == 1 && op->addr.buswidth == 1 && ··· 355 355 u8 io_mode; 356 356 int ret; 357 357 358 - op = spinand->op_templates.read_cache; 358 + op = spinand->op_templates->read_cache; 359 359 360 360 single = (op->cmd.buswidth == 1 && op->addr.buswidth == 1 && op->data.buswidth == 1); 361 361 dtr = (op->cmd.dtr || op->addr.dtr || op->data.dtr);
+34 -9
include/linux/mtd/spinand.h
··· 601 601 }; 602 602 603 603 /** 604 + * struct spinand_mem_ops - SPI NAND memory operations 605 + * @reset: reset op template 606 + * @readid: read ID op template 607 + * @wr_en: write enable op template 608 + * @wr_dis: write disable op template 609 + * @set_feature: set feature op template 610 + * @get_feature: get feature op template 611 + * @blk_erase: blk erase op template 612 + * @page_read: page read op template 613 + * @prog_exec: prog exec op template 614 + * @read_cache: read cache op template 615 + * @write_cache: write cache op template 616 + * @update_cache: update cache op template 617 + */ 618 + struct spinand_mem_ops { 619 + struct spi_mem_op reset; 620 + struct spi_mem_op readid; 621 + struct spi_mem_op wr_en; 622 + struct spi_mem_op wr_dis; 623 + struct spi_mem_op set_feature; 624 + struct spi_mem_op get_feature; 625 + struct spi_mem_op blk_erase; 626 + struct spi_mem_op page_read; 627 + struct spi_mem_op prog_exec; 628 + const struct spi_mem_op *read_cache; 629 + const struct spi_mem_op *write_cache; 630 + const struct spi_mem_op *update_cache; 631 + }; 632 + 633 + /** 604 634 * struct spinand_device - SPI NAND device instance 605 635 * @base: NAND device instance 606 636 * @spimem: pointer to the SPI mem object 607 637 * @lock: lock used to serialize accesses to the NAND 608 638 * @id: NAND ID as returned by READ_ID 609 639 * @flags: NAND flags 610 - * @op_templates: various SPI mem op templates 611 - * @op_templates.read_cache: read cache op template 612 - * @op_templates.write_cache: write cache op template 613 - * @op_templates.update_cache: update cache op template 640 + * @ssdr_op_templates: Templates for all single SDR SPI mem operations 641 + * @op_templates: Templates for all SPI mem operations 614 642 * @select_target: select a specific target/die. Usually called before sending 615 643 * a command addressing a page or an eraseblock embedded in 616 644 * this die. Only required if your chip exposes several dies ··· 672 644 struct spinand_id id; 673 645 u32 flags; 674 646 675 - struct { 676 - const struct spi_mem_op *read_cache; 677 - const struct spi_mem_op *write_cache; 678 - const struct spi_mem_op *update_cache; 679 - } op_templates; 647 + struct spinand_mem_ops ssdr_op_templates; 648 + struct spinand_mem_ops *op_templates; 680 649 681 650 struct spinand_dirmap *dirmaps; 682 651