MTD device changes: Aside from the platform_driver::remove() switch, two

misc issues got fixed.
 
 SPI-NAND changes:
 A load of fixes to Winbond manufacturer driver have been done, plus a
 structure constification.
 
 Raw NAND changes:
 The GPMI driver has been improved on the power management side.
 The Davinci driver has been cleaned up.
 A leak in the Atmel driver plus some typos in the core have been fixed.
 
 SPI NOR changes:
 Introduce byte swap support for 8D-8D-8D mode and a user for it:
 macronix. SPI NOR flashes may swap the bytes on a 16-bit boundary when
 configured in Octal DTR mode. For such cases the byte order is
 propagated through SPI MEM to the SPI controllers so that the
 controllers swap the bytes back at runtime. This avoids breaking the
 boot sequence because of the endianness problems that appear when the
 bootloaders use 1-1-1 and the kernel uses 8D-8D-8D with byte swap
 support. Along with the SPI MEM byte swap support we queue a patch for
 the SPI MXIC controller that swaps the bytes back at runtime.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAmc/WusACgkQJWrqGEe9
 VoR0Zgf/admMDFN51dtkz950bnOkZfot/4uLgUQCDenhbugHrom7KWQ6+oh1+HSN
 9EAjLoLNQzq4vxKx1WoI/99iJO86zg/DiyVD3nQidv9JkqHRDp2t13ZLclr4gGyW
 Kh1lDQ+9GwpB8CQQnxVaPL39NjjqR3RiEfEP/1fVgGYQvCt4yedhVsDT3WThJeVb
 1n7l54RBpZji88mT0chFB9CoSLnzrYZFh2MvzJaW/i1v02yZLXHFxFiKiKo+WysY
 FGQTY3x0j20H2Ib8RSP7ECegvNb1HtfIxAPsTIqDBGbrA+ahvBr0J/XxX3NbV3RT
 Ee4rXqL257zH9dC9Rr1LJAZCqiyx7w==
 =p+y9
 -----END PGP SIGNATURE-----

Merge tag 'mtd/for-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull MTD updates from Miquel Raynal:
 "MTD device changes:
   - switch platform_driver back to remove()
   - misc fixes

  SPI-NAND changes:
   - a load of fixes to Winbond manufacturer driver
   - structure constification

  Raw NAND changes:
   - improve the power management of the GPMI driver
   - Davinci driver clean-ups
   - fix leak in the Atmel driver
   - fix some typos in the core

  SPI NOR changes:
   - Introduce byte swap support for 8D-8D-8D mode and a user for it:
     macronix.

     SPI NOR flashes may swap the bytes on a 16-bit boundary when
     configured in Octal DTR mode. For such cases the byte order is
     propagated through SPI MEM to the SPI controllers so that the
     controllers swap the bytes back at runtime. This avoids breaking
     the boot sequence because of the endianness problems that appear
     when the bootloaders use 1-1-1 and the kernel uses 8D-8D-8D with
     byte swap support. Along with the SPI MEM byte swap support we
     queue a patch for the SPI MXIC controller that swaps the bytes back
     at runtime"

* tag 'mtd/for-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (25 commits)
  mtd: spi-nor: core: replace dummy buswidth from addr to data
  mtd: spi-nor: winbond: add "w/ and w/o SFDP" comment
  mtd: spi-nor: spansion: Use nor->addr_nbytes in octal DTR mode in RD_ANY_REG_OP
  mtd: Switch back to struct platform_driver::remove()
  mtd: cfi_cmdset_0002: remove redundant assignment to variable ret
  mtd: spinand: Constify struct nand_ecc_engine_ops
  MAINTAINERS: add mailing list for GPMI NAND driver
  mtd: spinand: winbond: Sort the devices
  mtd: spinand: winbond: Ignore the last ID characters
  mtd: spinand: winbond: Fix 512GW, 01GW, 01JW and 02JW ECC information
  mtd: spinand: winbond: Fix 512GW and 02JW OOB layout
  mtd: nand: raw: gpmi: improve power management handling
  mtd: nand: raw: gpmi: switch to SYSTEM_SLEEP_PM_OPS
  mtd: rawnand: davinci: use generic device property helpers
  mtd: rawnand: davinci: break the line correctly
  mtd: rawnand: davinci: order headers alphabetically
  mtd: rawnand: atmel: Fix possible memory leak
  mtd: rawnand: Correct multiple typos in comments
  mtd: hyperbus: rpc-if: Add missing MODULE_DEVICE_TABLE
  mtd: spi-nor: add support for Macronix Octal flash
  ...
This commit is contained in:
Linus Torvalds 2024-11-22 17:06:59 -08:00
commit d0c9a21c8e
98 changed files with 368 additions and 226 deletions

View File

@ -9056,6 +9056,7 @@ F: drivers/net/ethernet/freescale/gianfar*
FREESCALE GPMI NAND DRIVER
M: Han Xu <han.xu@nxp.com>
L: imx@lists.linux.dev
L: linux-mtd@lists.infradead.org
S: Maintained
F: drivers/mtd/nand/raw/gpmi-nand/*

View File

@ -1779,10 +1779,8 @@ static int __xipram do_write_oneword_retry(struct map_info *map,
map_write(map, CMD(0xF0), chip->start);
/* FIXME - should have reset delay before continuing */
if (++retry_cnt <= MAX_RETRIES) {
ret = 0;
if (++retry_cnt <= MAX_RETRIES)
goto retry;
}
}
xip_enable(map, chip, adr);

View File

@ -367,7 +367,7 @@ static void bcm47xxsflash_bcma_remove(struct platform_device *pdev)
static struct platform_driver bcma_sflash_driver = {
.probe = bcm47xxsflash_bcma_probe,
.remove_new = bcm47xxsflash_bcma_remove,
.remove = bcm47xxsflash_bcma_remove,
.driver = {
.name = "bcma_sflash",
},

View File

@ -2075,7 +2075,7 @@ static struct platform_driver g3_driver = {
},
.suspend = docg3_suspend,
.resume = docg3_resume,
.remove_new = docg3_release,
.remove = docg3_release,
};
module_platform_driver_probe(g3_driver, docg3_probe);

View File

@ -399,7 +399,7 @@ static void phram_remove(struct platform_device *pdev)
static struct platform_driver phram_driver = {
.probe = phram_probe,
.remove_new = phram_remove,
.remove = phram_remove,
.driver = {
.name = "phram",
.of_match_table = of_match_ptr(phram_of_match),

View File

@ -286,7 +286,7 @@ static struct platform_driver powernv_flash_driver = {
.name = "powernv_flash",
.of_match_table = powernv_flash_match,
},
.remove_new = powernv_flash_release,
.remove = powernv_flash_release,
.probe = powernv_flash_probe,
};

View File

@ -1093,7 +1093,7 @@ static struct platform_driver spear_smi_driver = {
.pm = &spear_smi_pm_ops,
},
.probe = spear_smi_probe,
.remove_new = spear_smi_remove,
.remove = spear_smi_remove,
};
module_platform_driver(spear_smi_driver);

View File

@ -2132,7 +2132,7 @@ MODULE_DEVICE_TABLE(of, stfsm_match);
static struct platform_driver stfsm_driver = {
.probe = stfsm_probe,
.remove_new = stfsm_remove,
.remove = stfsm_remove,
.driver = {
.name = "st-spi-fsm",
.of_match_table = stfsm_match,

View File

@ -254,7 +254,7 @@ MODULE_DEVICE_TABLE(of, am654_hbmc_dt_ids);
static struct platform_driver am654_hbmc_platform_driver = {
.probe = am654_hbmc_probe,
.remove_new = am654_hbmc_remove,
.remove = am654_hbmc_remove,
.driver = {
.name = "hbmc-am654",
.of_match_table = am654_hbmc_dt_ids,

View File

@ -163,9 +163,16 @@ static void rpcif_hb_remove(struct platform_device *pdev)
pm_runtime_disable(hyperbus->rpc.dev);
}
static const struct platform_device_id rpc_if_hyperflash_id_table[] = {
{ .name = "rpc-if-hyperflash" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, rpc_if_hyperflash_id_table);
static struct platform_driver rpcif_platform_driver = {
.probe = rpcif_hb_probe,
.remove_new = rpcif_hb_remove,
.remove = rpcif_hb_remove,
.id_table = rpc_if_hyperflash_id_table,
.driver = {
.name = "rpc-if-hyperflash",
},

View File

@ -487,7 +487,7 @@ static struct platform_driver lpddr2_nvm_drv = {
.name = "lpddr2_nvm",
},
.probe = lpddr2_nvm_probe,
.remove_new = lpddr2_nvm_remove,
.remove = lpddr2_nvm_remove,
};
module_platform_driver(lpddr2_nvm_drv);

View File

@ -184,7 +184,7 @@ MODULE_DEVICE_TABLE(of, ltq_mtd_match);
static struct platform_driver ltq_mtd_driver = {
.probe = ltq_mtd_probe,
.remove_new = ltq_mtd_remove,
.remove = ltq_mtd_remove,
.driver = {
.name = "ltq-nor",
.of_match_table = ltq_mtd_match,

View File

@ -621,7 +621,7 @@ static void physmap_flash_shutdown(struct platform_device *dev)
static struct platform_driver physmap_flash_driver = {
.probe = physmap_flash_probe,
.remove_new = physmap_flash_remove,
.remove = physmap_flash_remove,
.shutdown = physmap_flash_shutdown,
.driver = {
.name = "physmap-flash",

View File

@ -205,7 +205,7 @@ MODULE_ALIAS("platform:mtd-ram");
static struct platform_driver platram_driver = {
.probe = platram_probe,
.remove_new = platram_remove,
.remove = platram_remove,
.driver = {
.name = "mtd-ram",
},

View File

@ -128,7 +128,7 @@ static struct platform_driver pxa2xx_flash_driver = {
.name = "pxa2xx-flash",
},
.probe = pxa2xx_flash_probe,
.remove_new = pxa2xx_flash_remove,
.remove = pxa2xx_flash_remove,
.shutdown = pxa2xx_flash_shutdown,
};

View File

@ -293,7 +293,7 @@ static void sa1100_mtd_remove(struct platform_device *pdev)
static struct platform_driver sa1100_mtd_driver = {
.probe = sa1100_mtd_probe,
.remove_new = sa1100_mtd_remove,
.remove = sa1100_mtd_remove,
.driver = {
.name = "sa1100-mtd",
},

View File

@ -149,7 +149,7 @@ static struct platform_driver uflash_driver = {
.of_match_table = uflash_match,
},
.probe = uflash_probe,
.remove_new = uflash_remove,
.remove = uflash_remove,
};
module_platform_driver(uflash_driver);

View File

@ -723,21 +723,21 @@ static int mxic_ecc_finish_io_req_pipelined(struct nand_device *nand,
return ret;
}
static struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
static const struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
.init_ctx = mxic_ecc_init_ctx_external,
.cleanup_ctx = mxic_ecc_cleanup_ctx,
.prepare_io_req = mxic_ecc_prepare_io_req_external,
.finish_io_req = mxic_ecc_finish_io_req_external,
};
static struct nand_ecc_engine_ops mxic_ecc_engine_pipelined_ops = {
static const struct nand_ecc_engine_ops mxic_ecc_engine_pipelined_ops = {
.init_ctx = mxic_ecc_init_ctx_pipelined,
.cleanup_ctx = mxic_ecc_cleanup_ctx,
.prepare_io_req = mxic_ecc_prepare_io_req_pipelined,
.finish_io_req = mxic_ecc_finish_io_req_pipelined,
};
struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
const struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
{
return &mxic_ecc_engine_pipelined_ops;
}
@ -869,7 +869,7 @@ static struct platform_driver mxic_ecc_driver = {
.of_match_table = mxic_ecc_of_ids,
},
.probe = mxic_ecc_probe,
.remove_new = mxic_ecc_remove,
.remove = mxic_ecc_remove,
};
module_platform_driver(mxic_ecc_driver);

View File

@ -384,7 +384,7 @@ static int nand_ecc_sw_bch_finish_io_req(struct nand_device *nand,
return max_bitflips;
}
static struct nand_ecc_engine_ops nand_ecc_sw_bch_engine_ops = {
static const struct nand_ecc_engine_ops nand_ecc_sw_bch_engine_ops = {
.init_ctx = nand_ecc_sw_bch_init_ctx,
.cleanup_ctx = nand_ecc_sw_bch_cleanup_ctx,
.prepare_io_req = nand_ecc_sw_bch_prepare_io_req,

View File

@ -638,7 +638,7 @@ static int nand_ecc_sw_hamming_finish_io_req(struct nand_device *nand,
return max_bitflips;
}
static struct nand_ecc_engine_ops nand_ecc_sw_hamming_engine_ops = {
static const struct nand_ecc_engine_ops nand_ecc_sw_hamming_engine_ops = {
.init_ctx = nand_ecc_sw_hamming_init_ctx,
.cleanup_ctx = nand_ecc_sw_hamming_cleanup_ctx,
.prepare_io_req = nand_ecc_sw_hamming_prepare_io_req,

View File

@ -104,7 +104,7 @@ static struct platform_driver generic_onenand_driver = {
.name = DRIVER_NAME,
},
.probe = generic_onenand_probe,
.remove_new = generic_onenand_remove,
.remove = generic_onenand_remove,
};
module_platform_driver(generic_onenand_driver);

View File

@ -593,7 +593,7 @@ MODULE_DEVICE_TABLE(of, omap2_onenand_id_table);
static struct platform_driver omap2_onenand_driver = {
.probe = omap2_onenand_probe,
.remove_new = omap2_onenand_remove,
.remove = omap2_onenand_remove,
.shutdown = omap2_onenand_shutdown,
.driver = {
.name = DRIVER_NAME,

View File

@ -991,7 +991,7 @@ static struct platform_driver s3c_onenand_driver = {
},
.id_table = s3c_onenand_driver_ids,
.probe = s3c_onenand_probe,
.remove_new = s3c_onenand_remove,
.remove = s3c_onenand_remove,
};
module_platform_driver(s3c_onenand_driver);

View File

@ -432,7 +432,7 @@ MODULE_DEVICE_TABLE(platform, gpio_nand_plat_id_table);
static struct platform_driver gpio_nand_driver = {
.probe = gpio_nand_probe,
.remove_new = gpio_nand_remove,
.remove = gpio_nand_remove,
.id_table = gpio_nand_plat_id_table,
.driver = {
.name = "ams-delta-nand",

View File

@ -1500,7 +1500,7 @@ static struct platform_driver anfc_driver = {
.of_match_table = anfc_ids,
},
.probe = anfc_probe,
.remove_new = anfc_remove,
.remove = anfc_remove,
};
module_platform_driver(anfc_driver);

View File

@ -2663,7 +2663,7 @@ static struct platform_driver atmel_nand_controller_driver = {
.pm = &atmel_nand_controller_pm_ops,
},
.probe = atmel_nand_controller_probe,
.remove_new = atmel_nand_controller_remove,
.remove = atmel_nand_controller_remove,
};
module_platform_driver(atmel_nand_controller_driver);

View File

@ -362,7 +362,7 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
size = ALIGN(size, sizeof(s32));
size += (req->ecc.strength + 1) * sizeof(s32) * 3;
user = kzalloc(size, GFP_KERNEL);
user = devm_kzalloc(pmecc->dev, size, GFP_KERNEL);
if (!user)
return ERR_PTR(-ENOMEM);
@ -408,12 +408,6 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
}
EXPORT_SYMBOL_GPL(atmel_pmecc_create_user);
void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user)
{
kfree(user);
}
EXPORT_SYMBOL_GPL(atmel_pmecc_destroy_user);
static int get_strength(struct atmel_pmecc_user *user)
{
const int *strengths = user->pmecc->caps->strengths;

View File

@ -55,8 +55,6 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct device *dev);
struct atmel_pmecc_user *
atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
struct atmel_pmecc_user_req *req);
void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
void atmel_pmecc_reset(struct atmel_pmecc *pmecc);
int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
void atmel_pmecc_disable(struct atmel_pmecc_user *user);

View File

@ -357,7 +357,7 @@ static struct platform_driver au1550nd_driver = {
.name = "au1550-nand",
},
.probe = au1550nd_probe,
.remove_new = au1550nd_remove,
.remove = au1550nd_remove,
};
module_platform_driver(au1550nd_driver);

View File

@ -70,7 +70,7 @@ static void bcm47xxnflash_remove(struct platform_device *pdev)
static struct platform_driver bcm47xxnflash_driver = {
.probe = bcm47xxnflash_probe,
.remove_new = bcm47xxnflash_remove,
.remove = bcm47xxnflash_remove,
.driver = {
.name = "bcma_nflash",
},

View File

@ -117,7 +117,7 @@ MODULE_DEVICE_TABLE(of, bcm6368_nand_of_match);
static struct platform_driver bcm6368_nand_driver = {
.probe = bcm6368_nand_probe,
.remove_new = brcmnand_remove,
.remove = brcmnand_remove,
.driver = {
.name = "bcm6368_nand",
.pm = &brcmnand_pm_ops,

View File

@ -119,7 +119,7 @@ static int brcmnand_bcma_nand_probe(struct platform_device *pdev)
static struct platform_driver brcmnand_bcma_nand_driver = {
.probe = brcmnand_bcma_nand_probe,
.remove_new = brcmnand_remove,
.remove = brcmnand_remove,
.driver = {
.name = "bcma_brcmnand",
.pm = &brcmnand_pm_ops,

View File

@ -112,7 +112,7 @@ MODULE_DEVICE_TABLE(of, bcmbca_nand_of_match);
static struct platform_driver bcmbca_nand_driver = {
.probe = bcmbca_nand_probe,
.remove_new = brcmnand_remove,
.remove = brcmnand_remove,
.driver = {
.name = "bcmbca_nand",
.pm = &brcmnand_pm_ops,

View File

@ -1561,7 +1561,7 @@ static int write_oob_to_regs(struct brcmnand_controller *ctrl, int i,
(oob[j + 2] << 8) |
(oob[j + 3] << 0));
/* handle the remaing bytes */
/* handle the remaining bytes */
while (j < tbytes)
plast[k++] = oob[j++];

View File

@ -23,7 +23,7 @@ static int brcmstb_nand_probe(struct platform_device *pdev)
static struct platform_driver brcmstb_nand_driver = {
.probe = brcmstb_nand_probe,
.remove_new = brcmnand_remove,
.remove = brcmnand_remove,
.driver = {
.name = "brcmstb_nand",
.pm = &brcmnand_pm_ops,

View File

@ -134,7 +134,7 @@ MODULE_DEVICE_TABLE(of, iproc_nand_of_match);
static struct platform_driver iproc_nand_driver = {
.probe = iproc_nand_probe,
.remove_new = brcmnand_remove,
.remove = brcmnand_remove,
.driver = {
.name = "iproc_nand",
.pm = &brcmnand_pm_ops,

View File

@ -1891,7 +1891,7 @@ static int cadence_nand_read_buf(struct cdns_nand_ctrl *cdns_ctrl,
int len_in_words = (data_dma_width == 4) ? len >> 2 : len >> 3;
/* read alingment data */
/* read alignment data */
if (data_dma_width == 4)
ioread32_rep(cdns_ctrl->io.virt, buf, len_in_words);
#ifdef CONFIG_64BIT
@ -3055,7 +3055,7 @@ static void cadence_nand_dt_remove(struct platform_device *ofdev)
static struct platform_driver cadence_nand_dt_driver = {
.probe = cadence_nand_dt_probe,
.remove_new = cadence_nand_dt_remove,
.remove = cadence_nand_dt_remove,
.driver = {
.name = "cadence-nand-controller",
.of_match_table = cadence_nand_dt_ids,

View File

@ -26,7 +26,7 @@
#define NR_CS553X_CONTROLLERS 4
#define MSR_DIVIL_GLD_CAP 0x51400000 /* DIVIL capabilitiies */
#define MSR_DIVIL_GLD_CAP 0x51400000 /* DIVIL capabilities */
#define CAP_CS5535 0x2df000ULL
#define CAP_CS5536 0x5df500ULL

View File

@ -10,15 +10,15 @@
* Dirk Behme <Dirk.Behme@gmail.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/iopoll.h>
#include <linux/mtd/rawnand.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/rawnand.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/of.h>
#define NRCSR_OFFSET 0x00
#define NANDFCR_OFFSET 0x60
@ -487,10 +487,10 @@ static const struct of_device_id davinci_nand_of_match[] = {
};
MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
static struct davinci_nand_pdata
*nand_davinci_get_pdata(struct platform_device *pdev)
static struct davinci_nand_pdata *
nand_davinci_get_pdata(struct platform_device *pdev)
{
if (!dev_get_platdata(&pdev->dev) && pdev->dev.of_node) {
if (!dev_get_platdata(&pdev->dev)) {
struct davinci_nand_pdata *pdata;
const char *mode;
u32 prop;
@ -501,23 +501,24 @@ static struct davinci_nand_pdata
pdev->dev.platform_data = pdata;
if (!pdata)
return ERR_PTR(-ENOMEM);
if (!of_property_read_u32(pdev->dev.of_node,
"ti,davinci-chipselect", &prop))
if (!device_property_read_u32(&pdev->dev,
"ti,davinci-chipselect", &prop))
pdata->core_chipsel = prop;
else
return ERR_PTR(-EINVAL);
if (!of_property_read_u32(pdev->dev.of_node,
"ti,davinci-mask-ale", &prop))
if (!device_property_read_u32(&pdev->dev,
"ti,davinci-mask-ale", &prop))
pdata->mask_ale = prop;
if (!of_property_read_u32(pdev->dev.of_node,
"ti,davinci-mask-cle", &prop))
if (!device_property_read_u32(&pdev->dev,
"ti,davinci-mask-cle", &prop))
pdata->mask_cle = prop;
if (!of_property_read_u32(pdev->dev.of_node,
"ti,davinci-mask-chipsel", &prop))
if (!device_property_read_u32(&pdev->dev,
"ti,davinci-mask-chipsel", &prop))
pdata->mask_chipsel = prop;
if (!of_property_read_string(pdev->dev.of_node,
"ti,davinci-ecc-mode", &mode)) {
if (!device_property_read_string(&pdev->dev,
"ti,davinci-ecc-mode",
&mode)) {
if (!strncmp("none", mode, 4))
pdata->engine_type = NAND_ECC_ENGINE_TYPE_NONE;
if (!strncmp("soft", mode, 4))
@ -525,16 +526,17 @@ static struct davinci_nand_pdata
if (!strncmp("hw", mode, 2))
pdata->engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
}
if (!of_property_read_u32(pdev->dev.of_node,
"ti,davinci-ecc-bits", &prop))
if (!device_property_read_u32(&pdev->dev,
"ti,davinci-ecc-bits", &prop))
pdata->ecc_bits = prop;
if (!of_property_read_u32(pdev->dev.of_node,
"ti,davinci-nand-buswidth", &prop) && prop == 16)
if (!device_property_read_u32(&pdev->dev,
"ti,davinci-nand-buswidth",
&prop) && prop == 16)
pdata->options |= NAND_BUSWIDTH_16;
if (of_property_read_bool(pdev->dev.of_node,
"ti,davinci-nand-use-bbt"))
if (device_property_read_bool(&pdev->dev,
"ti,davinci-nand-use-bbt"))
pdata->bbt_options = NAND_BBT_USE_FLASH;
/*
@ -548,17 +550,15 @@ static struct davinci_nand_pdata
* then use "ti,davinci-nand" as the compatible in your
* device-tree file.
*/
if (of_device_is_compatible(pdev->dev.of_node,
"ti,keystone-nand")) {
if (device_is_compatible(&pdev->dev, "ti,keystone-nand"))
pdata->options |= NAND_NO_SUBPAGE_WRITE;
}
}
return dev_get_platdata(&pdev->dev);
}
#else
static struct davinci_nand_pdata
*nand_davinci_get_pdata(struct platform_device *pdev)
static struct davinci_nand_pdata *
nand_davinci_get_pdata(struct platform_device *pdev)
{
return dev_get_platdata(&pdev->dev);
}
@ -901,7 +901,7 @@ static void nand_davinci_remove(struct platform_device *pdev)
static struct platform_driver nand_davinci_driver = {
.probe = nand_davinci_probe,
.remove_new = nand_davinci_remove,
.remove = nand_davinci_remove,
.driver = {
.name = "davinci_nand",
.of_match_table = of_match_ptr(davinci_nand_of_match),

View File

@ -225,7 +225,7 @@ static void denali_dt_remove(struct platform_device *pdev)
static struct platform_driver denali_dt_driver = {
.probe = denali_dt_probe,
.remove_new = denali_dt_remove,
.remove = denali_dt_remove,
.driver = {
.name = "denali-nand-dt",
.of_match_table = denali_nand_dt_ids,

View File

@ -999,7 +999,7 @@ static struct platform_driver fsl_elbc_nand_driver = {
.of_match_table = fsl_elbc_nand_match,
},
.probe = fsl_elbc_nand_probe,
.remove_new = fsl_elbc_nand_remove,
.remove = fsl_elbc_nand_remove,
};
module_platform_driver(fsl_elbc_nand_driver);

View File

@ -1130,7 +1130,7 @@ static struct platform_driver fsl_ifc_nand_driver = {
.of_match_table = fsl_ifc_nand_match,
},
.probe = fsl_ifc_nand_probe,
.remove_new = fsl_ifc_nand_remove,
.remove = fsl_ifc_nand_remove,
};
module_platform_driver(fsl_ifc_nand_driver);

View File

@ -259,7 +259,7 @@ static struct platform_driver of_fun_driver = {
.of_match_table = of_fun_match,
},
.probe = fun_probe,
.remove_new = fun_remove,
.remove = fun_remove,
};
module_platform_driver(of_fun_driver);

View File

@ -1221,7 +1221,7 @@ static const struct of_device_id fsmc_nand_id_table[] = {
MODULE_DEVICE_TABLE(of, fsmc_nand_id_table);
static struct platform_driver fsmc_nand_driver = {
.remove_new = fsmc_nand_remove,
.remove = fsmc_nand_remove,
.driver = {
.name = "fsmc-nand",
.of_match_table = fsmc_nand_id_table,

View File

@ -392,7 +392,7 @@ static int gpio_nand_probe(struct platform_device *pdev)
static struct platform_driver gpio_nand_driver = {
.probe = gpio_nand_probe,
.remove_new = gpio_nand_remove,
.remove = gpio_nand_remove,
.driver = {
.name = "gpio-nand",
.of_match_table = of_match_ptr(gpio_nand_id_table),

View File

@ -15,6 +15,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>
#include <linux/dma/mxs-dma.h>
#include "gpmi-nand.h"
#include "gpmi-regs.h"
@ -737,9 +738,8 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
if (ret)
return ret;
ret = pm_runtime_get_sync(this->dev);
ret = pm_runtime_resume_and_get(this->dev);
if (ret < 0) {
pm_runtime_put_autosuspend(this->dev);
return ret;
}
@ -2761,15 +2761,9 @@ static int gpmi_nand_probe(struct platform_device *pdev)
if (ret)
goto exit_acquire_resources;
ret = __gpmi_enable_clk(this, true);
if (ret)
goto exit_acquire_resources;
pm_runtime_enable(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
ret = gpmi_init(this);
if (ret)
@ -2779,15 +2773,12 @@ static int gpmi_nand_probe(struct platform_device *pdev)
if (ret)
goto exit_nfc_init;
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
dev_info(this->dev, "driver registered.\n");
return 0;
exit_nfc_init:
pm_runtime_put(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
release_resources(this);
exit_acquire_resources:
@ -2801,23 +2792,23 @@ static void gpmi_nand_remove(struct platform_device *pdev)
struct nand_chip *chip = &this->nand;
int ret;
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
ret = mtd_device_unregister(nand_to_mtd(chip));
WARN_ON(ret);
nand_cleanup(chip);
gpmi_free_dma_buffer(this);
release_resources(this);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
}
#ifdef CONFIG_PM_SLEEP
static int gpmi_pm_suspend(struct device *dev)
{
struct gpmi_nand_data *this = dev_get_drvdata(dev);
int ret;
release_dma_channels(this);
return 0;
pinctrl_pm_select_sleep_state(dev);
ret = pm_runtime_force_suspend(dev);
return ret;
}
static int gpmi_pm_resume(struct device *dev)
@ -2825,9 +2816,13 @@ static int gpmi_pm_resume(struct device *dev)
struct gpmi_nand_data *this = dev_get_drvdata(dev);
int ret;
ret = acquire_dma_channels(this);
if (ret < 0)
ret = pm_runtime_force_resume(dev);
if (ret) {
dev_err(this->dev, "Error in resume %d\n", ret);
return ret;
}
pinctrl_pm_select_default_state(dev);
/* re-init the GPMI registers */
ret = gpmi_init(this);
@ -2849,35 +2844,45 @@ static int gpmi_pm_resume(struct device *dev)
return 0;
}
#endif /* CONFIG_PM_SLEEP */
static int __maybe_unused gpmi_runtime_suspend(struct device *dev)
#define gpmi_enable_clk(x) __gpmi_enable_clk(x, true)
#define gpmi_disable_clk(x) __gpmi_enable_clk(x, false)
static int gpmi_runtime_suspend(struct device *dev)
{
struct gpmi_nand_data *this = dev_get_drvdata(dev);
return __gpmi_enable_clk(this, false);
gpmi_disable_clk(this);
return 0;
}
static int __maybe_unused gpmi_runtime_resume(struct device *dev)
static int gpmi_runtime_resume(struct device *dev)
{
struct gpmi_nand_data *this = dev_get_drvdata(dev);
int ret;
ret = gpmi_enable_clk(this);
if (ret)
return ret;
return 0;
return __gpmi_enable_clk(this, true);
}
static const struct dev_pm_ops gpmi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume)
SET_RUNTIME_PM_OPS(gpmi_runtime_suspend, gpmi_runtime_resume, NULL)
SYSTEM_SLEEP_PM_OPS(gpmi_pm_suspend, gpmi_pm_resume)
RUNTIME_PM_OPS(gpmi_runtime_suspend, gpmi_runtime_resume, NULL)
};
static struct platform_driver gpmi_nand_driver = {
.driver = {
.name = "gpmi-nand",
.pm = &gpmi_pm_ops,
.pm = pm_ptr(&gpmi_pm_ops),
.of_match_table = gpmi_nand_id_table,
},
.probe = gpmi_nand_probe,
.remove_new = gpmi_nand_remove,
.probe = gpmi_nand_probe,
.remove = gpmi_nand_remove,
};
module_platform_driver(gpmi_nand_driver);

View File

@ -858,7 +858,7 @@ static struct platform_driver hisi_nfc_driver = {
.pm = &hisi_nfc_pm_ops,
},
.probe = hisi_nfc_probe,
.remove_new = hisi_nfc_remove,
.remove = hisi_nfc_remove,
};
module_platform_driver(hisi_nfc_driver);

View File

@ -549,7 +549,7 @@ MODULE_DEVICE_TABLE(of, ingenic_nand_dt_match);
static struct platform_driver ingenic_nand_driver = {
.probe = ingenic_nand_probe,
.remove_new = ingenic_nand_remove,
.remove = ingenic_nand_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = ingenic_nand_dt_match,

View File

@ -728,7 +728,7 @@ MODULE_DEVICE_TABLE(of, ebu_nand_match);
static struct platform_driver ebu_nand_driver = {
.probe = ebu_nand_probe,
.remove_new = ebu_nand_remove,
.remove = ebu_nand_remove,
.driver = {
.name = "intel-nand-controller",
.of_match_table = ebu_nand_match,

View File

@ -891,7 +891,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
static struct platform_driver lpc32xx_nand_driver = {
.probe = lpc32xx_nand_probe,
.remove_new = lpc32xx_nand_remove,
.remove = lpc32xx_nand_remove,
.resume = pm_ptr(lpc32xx_nand_resume),
.suspend = pm_ptr(lpc32xx_nand_suspend),
.driver = {

View File

@ -1010,7 +1010,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
static struct platform_driver lpc32xx_nand_driver = {
.probe = lpc32xx_nand_probe,
.remove_new = lpc32xx_nand_remove,
.remove = lpc32xx_nand_remove,
.resume = pm_ptr(lpc32xx_nand_resume),
.suspend = pm_ptr(lpc32xx_nand_suspend),
.driver = {

View File

@ -3183,7 +3183,7 @@ static struct platform_driver marvell_nfc_driver = {
},
.id_table = marvell_nfc_platform_ids,
.probe = marvell_nfc_probe,
.remove_new = marvell_nfc_remove,
.remove = marvell_nfc_remove,
};
module_platform_driver(marvell_nfc_driver);

View File

@ -1621,7 +1621,7 @@ static void meson_nfc_remove(struct platform_device *pdev)
static struct platform_driver meson_nfc_driver = {
.probe = meson_nfc_probe,
.remove_new = meson_nfc_remove,
.remove = meson_nfc_remove,
.driver = {
.name = "meson-nand",
.of_match_table = meson_nfc_id_table,

View File

@ -835,7 +835,7 @@ MODULE_DEVICE_TABLE(of, mpc5121_nfc_match);
static struct platform_driver mpc5121_nfc_driver = {
.probe = mpc5121_nfc_probe,
.remove_new = mpc5121_nfc_remove,
.remove = mpc5121_nfc_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = mpc5121_nfc_match,

View File

@ -1640,7 +1640,7 @@ static SIMPLE_DEV_PM_OPS(mtk_nfc_pm_ops, mtk_nfc_suspend, mtk_nfc_resume);
static struct platform_driver mtk_nfc_driver = {
.probe = mtk_nfc_probe,
.remove_new = mtk_nfc_remove,
.remove = mtk_nfc_remove,
.driver = {
.name = MTK_NAME,
.of_match_table = mtk_nfc_id_table,

View File

@ -1824,7 +1824,7 @@ static struct platform_driver mxcnd_driver = {
.of_match_table = mxcnd_dt_ids,
},
.probe = mxcnd_probe,
.remove_new = mxcnd_remove,
.remove = mxcnd_remove,
};
module_platform_driver(mxcnd_driver);

View File

@ -574,7 +574,7 @@ MODULE_DEVICE_TABLE(of, mxic_nfc_of_ids);
static struct platform_driver mxic_nfc_driver = {
.probe = mxic_nfc_probe,
.remove_new = mxic_nfc_remove,
.remove = mxic_nfc_remove,
.driver = {
.name = "mxic-nfc",
.of_match_table = mxic_nfc_of_ids,

View File

@ -113,7 +113,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip)
rand_otp = of_property_read_bool(dn, "mxic,enable-randomizer-otp");
mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
/* Subpage write is prohibited in randomizer operatoin */
/* Subpage write is prohibited in randomizer operation */
if (rand_otp && chip->options & NAND_NO_SUBPAGE_WRITE &&
mxic->reliability_func & MACRONIX_RANDOMIZER_BIT) {
if (p->supports_set_get_features) {

View File

@ -266,7 +266,7 @@ static struct platform_driver ndfc_driver = {
.of_match_table = ndfc_match,
},
.probe = ndfc_probe,
.remove_new = ndfc_remove,
.remove = ndfc_remove,
};
module_platform_driver(ndfc_driver);

View File

@ -2291,7 +2291,7 @@ MODULE_DEVICE_TABLE(of, omap_nand_ids);
static struct platform_driver omap_nand_driver = {
.probe = omap_nand_probe,
.remove_new = omap_nand_remove,
.remove = omap_nand_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = omap_nand_ids,

View File

@ -560,7 +560,7 @@ static struct platform_driver elm_driver = {
.pm = &elm_pm_ops,
},
.probe = elm_probe,
.remove_new = elm_remove,
.remove = elm_remove,
};
module_platform_driver(elm_driver);

View File

@ -214,7 +214,7 @@ MODULE_DEVICE_TABLE(of, orion_nand_of_match_table);
#endif
static struct platform_driver orion_nand_driver = {
.remove_new = orion_nand_remove,
.remove = orion_nand_remove,
.driver = {
.name = "orion_nand",
.of_match_table = of_match_ptr(orion_nand_of_match_table),

View File

@ -237,7 +237,7 @@ static struct platform_driver pasemi_nand_driver =
.of_match_table = pasemi_nand_match,
},
.probe = pasemi_nand_probe,
.remove_new = pasemi_nand_remove,
.remove = pasemi_nand_remove,
};
module_platform_driver(pasemi_nand_driver);

View File

@ -187,7 +187,7 @@ static const struct mtd_ooblayout_ops pl35x_ecc_ooblayout16_ops = {
.free = pl35x_ecc_ooblayout16_free,
};
/* Generic flash bbt decriptors */
/* Generic flash bbt descriptors */
static u8 bbt_pattern[] = { 'B', 'b', 't', '0' };
static u8 mirror_pattern[] = { '1', 't', 'b', 'B' };
@ -1184,7 +1184,7 @@ MODULE_DEVICE_TABLE(of, pl35x_nand_of_match);
static struct platform_driver pl35x_nandc_driver = {
.probe = pl35x_nand_probe,
.remove_new = pl35x_nand_remove,
.remove = pl35x_nand_remove,
.driver = {
.name = PL35X_NANDC_DRIVER_NAME,
.of_match_table = pl35x_nand_of_match,

View File

@ -144,7 +144,7 @@ MODULE_DEVICE_TABLE(of, plat_nand_match);
static struct platform_driver plat_nand_driver = {
.probe = plat_nand_probe,
.remove_new = plat_nand_remove,
.remove = plat_nand_remove,
.driver = {
.name = "gen_nand",
.of_match_table = plat_nand_match,

View File

@ -3535,8 +3535,8 @@ static struct platform_driver qcom_nandc_driver = {
.name = "qcom-nandc",
.of_match_table = qcom_nandc_of_match,
},
.probe = qcom_nandc_probe,
.remove_new = qcom_nandc_remove,
.probe = qcom_nandc_probe,
.remove = qcom_nandc_remove,
};
module_platform_driver(qcom_nandc_driver);

View File

@ -335,7 +335,7 @@ static void r852_cmdctl(struct nand_chip *chip, int dat, unsigned int ctrl)
else
dev->ctlreg &= ~R852_CTL_WRITE;
/* when write is stareted, enable write access */
/* when write is started, enable write access */
if (dat == NAND_CMD_ERASE1)
dev->ctlreg |= R852_CTL_WRITE;
@ -372,7 +372,7 @@ static int r852_wait(struct nand_chip *chip)
nand_status_op(chip, &status);
/* Unfortunelly, no way to send detailed error status... */
/* Unfortunately, no way to send detailed error status... */
if (dev->dma_error) {
status |= NAND_STATUS_FAIL;
dev->dma_error = 0;

View File

@ -1402,7 +1402,7 @@ static struct platform_driver rnandc_driver = {
.of_match_table = rnandc_id_table,
},
.probe = rnandc_probe,
.remove_new = rnandc_remove,
.remove = rnandc_remove,
};
module_platform_driver(rnandc_driver);

View File

@ -1477,7 +1477,7 @@ static const struct dev_pm_ops rk_nfc_pm_ops = {
static struct platform_driver rk_nfc_driver = {
.probe = rk_nfc_probe,
.remove_new = rk_nfc_remove,
.remove = rk_nfc_remove,
.driver = {
.name = "rockchip-nfc",
.of_match_table = rk_nfc_id_table,

View File

@ -1213,7 +1213,7 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
static struct platform_driver s3c24xx_nand_driver = {
.probe = s3c24xx_nand_probe,
.remove_new = s3c24xx_nand_remove,
.remove = s3c24xx_nand_remove,
.suspend = s3c24xx_nand_suspend,
.resume = s3c24xx_nand_resume,
.id_table = s3c24xx_driver_ids,

View File

@ -1216,7 +1216,7 @@ static void flctl_remove(struct platform_device *pdev)
static struct platform_driver flctl_driver = {
.probe = flctl_probe,
.remove_new = flctl_remove,
.remove = flctl_remove,
.driver = {
.name = "sh_flctl",
.of_match_table = of_flctl_match,

View File

@ -234,7 +234,7 @@ static struct platform_driver sharpsl_nand_driver = {
.name = "sharpsl-nand",
},
.probe = sharpsl_nand_probe,
.remove_new = sharpsl_nand_remove,
.remove = sharpsl_nand_remove,
};
module_platform_driver(sharpsl_nand_driver);

View File

@ -52,8 +52,8 @@ static const struct mtd_ooblayout_ops oob_sm_ops = {
.free = oob_sm_ooblayout_free,
};
/* NOTE: This layout is not compatabable with SmartMedia, */
/* because the 256 byte devices have page depenent oob layout */
/* NOTE: This layout is not compatible with SmartMedia, */
/* because the 256 byte devices have page dependent oob layout */
/* However it does preserve the bad block markers */
/* If you use smftl, it will bypass this and work correctly */
/* If you not, then you break SmartMedia compliance anyway */

View File

@ -231,7 +231,7 @@ static struct platform_driver socrates_nand_driver = {
.of_match_table = socrates_nand_match,
},
.probe = socrates_nand_probe,
.remove_new = socrates_nand_remove,
.remove = socrates_nand_remove,
};
module_platform_driver(socrates_nand_driver);

View File

@ -2147,7 +2147,7 @@ MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match);
static struct platform_driver stm32_fmc2_nfc_driver = {
.probe = stm32_fmc2_nfc_probe,
.remove_new = stm32_fmc2_nfc_remove,
.remove = stm32_fmc2_nfc_remove,
.driver = {
.name = "stm32_fmc2_nfc",
.of_match_table = stm32_fmc2_nfc_match,

View File

@ -2196,7 +2196,7 @@ static struct platform_driver sunxi_nfc_driver = {
.of_match_table = sunxi_nfc_ids,
},
.probe = sunxi_nfc_probe,
.remove_new = sunxi_nfc_remove,
.remove = sunxi_nfc_remove,
};
module_platform_driver(sunxi_nfc_driver);

View File

@ -213,7 +213,7 @@ static struct platform_driver ts72xx_nand_driver = {
.of_match_table = ts72xx_id_table,
},
.probe = ts72xx_nand_probe,
.remove_new = ts72xx_nand_remove,
.remove = ts72xx_nand_remove,
};
module_platform_driver(ts72xx_nand_driver);

View File

@ -1279,7 +1279,7 @@ static struct platform_driver tegra_nand_driver = {
.pm = &tegra_nand_pm,
},
.probe = tegra_nand_probe,
.remove_new = tegra_nand_remove,
.remove = tegra_nand_remove,
};
module_platform_driver(tegra_nand_driver);

View File

@ -405,7 +405,7 @@ static int txx9ndfmc_resume(struct platform_device *dev)
static struct platform_driver txx9ndfmc_driver = {
.probe = txx9ndfmc_probe,
.remove_new = txx9ndfmc_remove,
.remove = txx9ndfmc_remove,
.resume = txx9ndfmc_resume,
.driver = {
.name = "txx9ndfmc",

View File

@ -941,7 +941,7 @@ static struct platform_driver vf610_nfc_driver = {
.pm = &vf610_nfc_pm_ops,
},
.probe = vf610_nfc_probe,
.remove_new = vf610_nfc_remove,
.remove = vf610_nfc_remove,
};
module_platform_driver(vf610_nfc_driver);

View File

@ -256,7 +256,7 @@ static const struct of_device_id xway_nand_match[] = {
static struct platform_driver xway_nand_driver = {
.probe = xway_nand_probe,
.remove_new = xway_nand_remove,
.remove = xway_nand_remove,
.driver = {
.name = "lantiq,nand-xway",
.of_match_table = xway_nand_match,

View File

@ -337,7 +337,7 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand,
return ret;
}
static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = {
static const struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = {
.init_ctx = spinand_ondie_ecc_init_ctx,
.cleanup_ctx = spinand_ondie_ecc_cleanup_ctx,
.prepare_io_req = spinand_ondie_ecc_prepare_io_req,

View File

@ -161,7 +161,55 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
}
static const struct spinand_info winbond_spinand_table[] = {
SPINAND_INFO("W25M02GV",
/* 512M-bit densities */
SPINAND_INFO("W25N512GW", /* 1.8V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x20),
NAND_MEMORG(1, 2048, 64, 64, 512, 10, 1, 1, 1),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
/* 1G-bit densities */
SPINAND_INFO("W25N01GV", /* 3.3V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
SPINAND_INFO("W25N01GW", /* 1.8V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
SPINAND_INFO("W25N01JW", /* high-speed 1.8V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbc, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
SPINAND_INFO("W25N01KV", /* 3.3V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),
NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n01kv_ooblayout, w25n02kv_ecc_get_status)),
/* 2G-bit densities */
SPINAND_INFO("W25M02GV", /* 2x1G-bit 3.3V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
NAND_ECCREQ(1, 512),
@ -171,25 +219,16 @@ static const struct spinand_info winbond_spinand_table[] = {
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
SPINAND_SELECT_TARGET(w25m02gv_select_target)),
SPINAND_INFO("W25N01GV",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
SPINAND_INFO("W25N02JW", /* high-speed 1.8V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbf, 0x22),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 2, 1),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
SPINAND_INFO("W25N01KV",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),
NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n01kv_ooblayout, w25n02kv_ecc_get_status)),
SPINAND_INFO("W25N02KV",
SPINAND_INFO("W25N02KV", /* 3.3V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
NAND_ECCREQ(8, 512),
@ -198,34 +237,7 @@ static const struct spinand_info winbond_spinand_table[] = {
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
SPINAND_INFO("W25N01JW",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbc, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, w25n02kv_ecc_get_status)),
SPINAND_INFO("W25N02JWZEIF",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbf, 0x22),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 2, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
SPINAND_INFO("W25N512GW",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x20),
NAND_MEMORG(1, 2048, 64, 64, 512, 10, 1, 1, 1),
NAND_ECCREQ(4, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
SPINAND_INFO("W25N02KWZEIR",
SPINAND_INFO("W25N02KW", /* 1.8V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x22),
NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
NAND_ECCREQ(8, 512),
@ -234,18 +246,19 @@ static const struct spinand_info winbond_spinand_table[] = {
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
SPINAND_INFO("W25N01GWZEIG",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x21),
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
NAND_ECCREQ(4, 512),
/* 4G-bit densities */
SPINAND_INFO("W25N04KV", /* 3.3V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, w25n02kv_ecc_get_status)),
SPINAND_INFO("W25N04KV",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1),
SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
SPINAND_INFO("W25N04KW", /* 1.8V */
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x23),
NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 1, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,

View File

@ -488,7 +488,7 @@ static struct platform_driver hisi_spi_nor_driver = {
.of_match_table = hisi_spi_nor_dt_ids,
},
.probe = hisi_spi_nor_probe,
.remove_new = hisi_spi_nor_remove,
.remove = hisi_spi_nor_remove,
};
module_platform_driver(hisi_spi_nor_driver);

View File

@ -446,7 +446,7 @@ MODULE_DEVICE_TABLE(of, nxp_spifi_match);
static struct platform_driver nxp_spifi_driver = {
.probe = nxp_spifi_probe,
.remove_new = nxp_spifi_remove,
.remove = nxp_spifi_remove,
.driver = {
.name = "nxp-spifi",
.of_match_table = nxp_spifi_match,

View File

@ -89,7 +89,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto);
if (op->dummy.nbytes)
op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto);
op->dummy.buswidth = spi_nor_get_protocol_data_nbits(proto);
if (op->data.nbytes)
op->data.buswidth = spi_nor_get_protocol_data_nbits(proto);
@ -113,6 +113,9 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
op->cmd.opcode = (op->cmd.opcode << 8) | ext;
op->cmd.nbytes = 2;
}
if (proto == SNOR_PROTO_8_8_8_DTR && nor->flags & SNOR_F_SWAP16)
op->data.swap16 = true;
}
/**

View File

@ -140,6 +140,7 @@ enum spi_nor_option_flags {
SNOR_F_RWW = BIT(14),
SNOR_F_ECC = BIT(15),
SNOR_F_NO_WP = BIT(16),
SNOR_F_SWAP16 = BIT(17),
};
struct spi_nor_read_command {

View File

@ -8,6 +8,23 @@
#include "core.h"
#define MXIC_NOR_OP_RD_CR2 0x71 /* Read configuration register 2 opcode */
#define MXIC_NOR_OP_WR_CR2 0x72 /* Write configuration register 2 opcode */
#define MXIC_NOR_ADDR_CR2_MODE 0x00000000 /* CR2 address for setting spi/sopi/dopi mode */
#define MXIC_NOR_ADDR_CR2_DC 0x00000300 /* CR2 address for setting dummy cycles */
#define MXIC_NOR_REG_DOPI_EN 0x2 /* Enable Octal DTR */
#define MXIC_NOR_REG_SPI_EN 0x0 /* Enable SPI */
/* Convert dummy cycles to bit pattern */
#define MXIC_NOR_REG_DC(p) \
((20 - (p)) >> 1)
#define MXIC_NOR_WR_CR2(addr, ndata, buf) \
SPI_MEM_OP(SPI_MEM_OP_CMD(MXIC_NOR_OP_WR_CR2, 0), \
SPI_MEM_OP_ADDR(4, addr, 0), \
SPI_MEM_OP_NO_DUMMY, \
SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
static int
mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
@ -182,9 +199,88 @@ static const struct flash_info macronix_nor_parts[] = {
.name = "mx25l3255e",
.size = SZ_4M,
.no_sfdp_flags = SECT_4K,
}
},
/*
* This spares us of adding new flash entries for flashes that can be
* initialized solely based on the SFDP data, but still need the
* manufacturer hooks to set parameters that can't be discovered at SFDP
* parsing time.
*/
{ .id = SNOR_ID(0xc2) }
};
static int macronix_nor_octal_dtr_en(struct spi_nor *nor)
{
struct spi_mem_op op;
u8 *buf = nor->bouncebuf, i;
int ret;
/* Use dummy cycles which is parse by SFDP and convert to bit pattern. */
buf[0] = MXIC_NOR_REG_DC(nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].num_wait_states);
op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_DC, 1, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
if (ret)
return ret;
/* Set the octal and DTR enable bits. */
buf[0] = MXIC_NOR_REG_DOPI_EN;
op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 1, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
if (ret)
return ret;
/* Read flash ID to make sure the switch was successful. */
ret = spi_nor_read_id(nor, 4, 4, buf, SNOR_PROTO_8_8_8_DTR);
if (ret) {
dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
return ret;
}
/* Macronix SPI-NOR flash 8D-8D-8D read ID would get 6 bytes data A-A-B-B-C-C */
for (i = 0; i < nor->info->id->len; i++)
if (buf[i * 2] != buf[(i * 2) + 1] || buf[i * 2] != nor->info->id->bytes[i])
return -EINVAL;
return 0;
}
static int macronix_nor_octal_dtr_dis(struct spi_nor *nor)
{
struct spi_mem_op op;
u8 *buf = nor->bouncebuf;
int ret;
/*
* The register is 1-byte wide, but 1-byte transactions are not
* allowed in 8D-8D-8D mode. Since there is no register at the
* next location, just initialize the value to 0 and let the
* transaction go on.
*/
buf[0] = MXIC_NOR_REG_SPI_EN;
buf[1] = 0x0;
op = (struct spi_mem_op)MXIC_NOR_WR_CR2(MXIC_NOR_ADDR_CR2_MODE, 2, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
if (ret)
return ret;
/* Read flash ID to make sure the switch was successful. */
ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
if (ret) {
dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
return ret;
}
if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))
return -EINVAL;
return 0;
}
static int macronix_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
{
return enable ? macronix_nor_octal_dtr_en(nor) : macronix_nor_octal_dtr_dis(nor);
}
static void macronix_nor_default_init(struct spi_nor *nor)
{
nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
@ -194,6 +290,7 @@ static int macronix_nor_late_init(struct spi_nor *nor)
{
if (!nor->params->set_4byte_addr_mode)
nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
nor->params->set_octal_dtr = macronix_nor_set_octal_dtr;
return 0;
}

View File

@ -671,6 +671,10 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
return -EOPNOTSUPP;
}
/* Byte order in 8D-8D-8D mode */
if (bfpt.dwords[SFDP_DWORD(18)] & BFPT_DWORD18_BYTE_ORDER_SWAPPED)
nor->flags |= SNOR_F_SWAP16;
return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt);
}

View File

@ -130,6 +130,7 @@ struct sfdp_bfpt {
#define BFPT_DWORD18_CMD_EXT_INV (0x1UL << 29) /* Invert */
#define BFPT_DWORD18_CMD_EXT_RES (0x2UL << 29) /* Reserved */
#define BFPT_DWORD18_CMD_EXT_16B (0x3UL << 29) /* 16-bit opcode */
#define BFPT_DWORD18_BYTE_ORDER_SWAPPED BIT(31) /* Byte order swapped in 8D-8D-8D mode */
struct sfdp_parameter_header {
u8 id_lsb;

View File

@ -106,6 +106,7 @@ static int cypress_nor_sr_ready_and_clear_reg(struct spi_nor *nor, u64 addr)
int ret;
if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
op.addr.nbytes = nor->addr_nbytes;
op.dummy.nbytes = params->rdsr_dummy;
op.data.nbytes = 2;
}

View File

@ -129,6 +129,7 @@ static const struct flash_info winbond_nor_parts[] = {
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
}, {
.id = SNOR_ID(0xef, 0x40, 0x18),
/* Flavors w/ and w/o SFDP. */
.name = "w25q128",
.size = SZ_16M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,

View File

@ -172,6 +172,9 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
if (!spi_mem_controller_is_capable(ctlr, dtr))
return false;
if (op->data.swap16 && !spi_mem_controller_is_capable(ctlr, swap16))
return false;
if (op->cmd.nbytes != 2)
return false;
} else {

View File

@ -776,7 +776,7 @@ static int mtk_snand_ecc_finish_io_req(struct nand_device *nand,
return snf->ecc_stats.failed ? -EBADMSG : snf->ecc_stats.bitflips;
}
static struct nand_ecc_engine_ops mtk_snfi_ecc_engine_ops = {
static const struct nand_ecc_engine_ops mtk_snfi_ecc_engine_ops = {
.init_ctx = mtk_snand_ecc_init_ctx,
.cleanup_ctx = mtk_snand_ecc_cleanup_ctx,
.prepare_io_req = mtk_snand_ecc_prepare_io_req,

View File

@ -294,7 +294,8 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic)
mxic->regs + HC_CFG);
}
static u32 mxic_spi_prep_hc_cfg(struct spi_device *spi, u32 flags)
static u32 mxic_spi_prep_hc_cfg(struct spi_device *spi, u32 flags,
bool swap16)
{
int nio = 1;
@ -305,6 +306,11 @@ static u32 mxic_spi_prep_hc_cfg(struct spi_device *spi, u32 flags)
else if (spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
nio = 2;
if (swap16)
flags &= ~HC_CFG_DATA_PASS;
else
flags |= HC_CFG_DATA_PASS;
return flags | HC_CFG_NIO(nio) |
HC_CFG_TYPE(spi_get_chipselect(spi, 0), HC_CFG_TYPE_SPI_NOR) |
HC_CFG_SLV_ACT(spi_get_chipselect(spi, 0)) | HC_CFG_IDLE_SIO_LVL(1);
@ -397,7 +403,8 @@ static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
return -EINVAL;
writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0), mxic->regs + HC_CFG);
writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0, desc->info.op_tmpl.data.swap16),
mxic->regs + HC_CFG);
writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl, len),
mxic->regs + LRD_CFG);
@ -441,7 +448,8 @@ static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
return -EINVAL;
writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0), mxic->regs + HC_CFG);
writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0, desc->info.op_tmpl.data.swap16),
mxic->regs + HC_CFG);
writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl, len),
mxic->regs + LWR_CFG);
@ -518,7 +526,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
if (ret)
return ret;
writel(mxic_spi_prep_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN),
writel(mxic_spi_prep_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN, op->data.swap16),
mxic->regs + HC_CFG);
writel(HC_EN_BIT, mxic->regs + HC_EN);
@ -573,6 +581,7 @@ static const struct spi_controller_mem_ops mxic_spi_mem_ops = {
static const struct spi_controller_mem_caps mxic_spi_mem_caps = {
.dtr = true,
.ecc = true,
.swap16 = true,
};
static void mxic_spi_set_cs(struct spi_device *spi, bool lvl)
@ -640,7 +649,7 @@ static int mxic_spi_transfer_one(struct spi_controller *host,
/* ECC wrapper */
static int mxic_spi_mem_ecc_init_ctx(struct nand_device *nand)
{
struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
const struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
struct mxic_spi *mxic = nand->ecc.engine->priv;
mxic->ecc.use_pipelined_conf = true;
@ -650,7 +659,7 @@ static int mxic_spi_mem_ecc_init_ctx(struct nand_device *nand)
static void mxic_spi_mem_ecc_cleanup_ctx(struct nand_device *nand)
{
struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
const struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
struct mxic_spi *mxic = nand->ecc.engine->priv;
mxic->ecc.use_pipelined_conf = false;
@ -661,7 +670,7 @@ static void mxic_spi_mem_ecc_cleanup_ctx(struct nand_device *nand)
static int mxic_spi_mem_ecc_prepare_io_req(struct nand_device *nand,
struct nand_page_io_req *req)
{
struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
const struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
return ops->prepare_io_req(nand, req);
}
@ -669,12 +678,12 @@ static int mxic_spi_mem_ecc_prepare_io_req(struct nand_device *nand,
static int mxic_spi_mem_ecc_finish_io_req(struct nand_device *nand,
struct nand_page_io_req *req)
{
struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
const struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
return ops->finish_io_req(nand, req);
}
static struct nand_ecc_engine_ops mxic_spi_mem_ecc_engine_pipelined_ops = {
static const struct nand_ecc_engine_ops mxic_spi_mem_ecc_engine_pipelined_ops = {
.init_ctx = mxic_spi_mem_ecc_init_ctx,
.cleanup_ctx = mxic_spi_mem_ecc_cleanup_ctx,
.prepare_io_req = mxic_spi_mem_ecc_prepare_io_req,

View File

@ -16,7 +16,7 @@ struct mxic_ecc_engine;
#if IS_ENABLED(CONFIG_MTD_NAND_ECC_MXIC) && IS_REACHABLE(CONFIG_MTD_NAND_CORE)
struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void);
const struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void);
struct nand_ecc_engine *mxic_ecc_get_pipelined_engine(struct platform_device *spi_pdev);
void mxic_ecc_put_pipelined_engine(struct nand_ecc_engine *eng);
int mxic_ecc_process_data_pipelined(struct nand_ecc_engine *eng,
@ -24,7 +24,7 @@ int mxic_ecc_process_data_pipelined(struct nand_ecc_engine *eng,
#else /* !CONFIG_MTD_NAND_ECC_MXIC */
static inline struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
static inline const struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
{
return NULL;
}

View File

@ -293,7 +293,7 @@ enum nand_ecc_engine_integration {
struct nand_ecc_engine {
struct device *dev;
struct list_head node;
struct nand_ecc_engine_ops *ops;
const struct nand_ecc_engine_ops *ops;
enum nand_ecc_engine_integration integration;
void *priv;
};

View File

@ -90,6 +90,8 @@ enum spi_mem_data_dir {
* @data.buswidth: number of IO lanes used to send/receive the data
* @data.dtr: whether the data should be sent in DTR mode or not
* @data.ecc: whether error correction is required or not
* @data.swap16: whether the byte order of 16-bit words is swapped when read
* or written in Octal DTR mode compared to STR mode.
* @data.dir: direction of the transfer
* @data.nbytes: number of data bytes to send/receive. Can be zero if the
* operation does not involve transferring data
@ -124,7 +126,8 @@ struct spi_mem_op {
u8 buswidth;
u8 dtr : 1;
u8 ecc : 1;
u8 __pad : 6;
u8 swap16 : 1;
u8 __pad : 5;
enum spi_mem_data_dir dir;
unsigned int nbytes;
union {
@ -297,10 +300,13 @@ struct spi_controller_mem_ops {
* struct spi_controller_mem_caps - SPI memory controller capabilities
* @dtr: Supports DTR operations
* @ecc: Supports operations with error correction
* @swap16: Supports swapping bytes on a 16 bit boundary when configured in
* Octal DTR
*/
struct spi_controller_mem_caps {
bool dtr;
bool ecc;
bool swap16;
};
#define spi_mem_controller_is_capable(ctlr, cap) \