MTD changes for 4.14:

General updates:
  * Constify pci_device_id in various drivers
  * Constify device_type
  * Remove pad control code from the Gemini driver
  * Use %pOF to print OF node full_name
  * Various fixes in the physmap_of driver
  * Remove unused vars in mtdswap
  * Check devm_kzalloc() return value in the spear_smi driver
  * Check clk_prepare_enable() return code in the st_spi_fsm driver
  * Create per MTD device debugfs enties
 
 NAND updates, from Boris Brezillon:
  * Fix memory leaks in the core
  * Remove unused NAND locking support
  * Rename nand.h into rawnand.h (preparing support for spi NANDs)
  * Use NAND_MAX_ID_LEN where appropriate
  * Fix support for 20nm Hynix chips
  * Fix support for Samsung and Hynix SLC NANDs
  * Various cleanup, improvements and fixes in the qcom driver
  * Fixes for bugs detected by various static code analysis tools
  * Fix mxc ooblayout definition
  * Add a new part_parsers to tmio and sharpsl platform data in order to
    define a custom list of partition parsers
  * Request the reset line in exclusive mode in the sunxi driver
  * Fix a build error in the orion-nand driver when compiled for ARMv4
  * Allow 64-bit mvebu platforms to select the PXA3XX driver
 
 SPI NOR updates, from Cyrille Pitchen and Marek Vasut:
  * add support to the JEDEC JESD216B specification (SFDP tables).
  * add support to the Intel Denverton SPI flash controller.
  * fix error recovery for Spansion/Cypress SPI NOR memories.
  * fix 4-byte address management for the Aspeed SPI controller.
  * add support to some Microchip SST26 memory parts
  * remove unneeded pinctrl header Write a message for tag:
 -----BEGIN PGP SIGNATURE-----
 
 iQJABAABCAAqBQJZrav6Ixxib3Jpcy5icmV6aWxsb25AZnJlZS1lbGVjdHJvbnMu
 Y29tAAoJEGXtNgF+CLcABwkP/joDrq09RIC9n5gP+ubJe6O1jKvNWDd6bIVXD3Ke
 73R0a0ANwwWlNYWTChTdrb8UeewVS1bzutyy5O2Sbdb6Jc6s7xkfQDTsbET2HWOK
 S7Lt/zjlC6/6cow59B6h43PGS6wmIFaZD3K+70sGhvFnV8epVUzS2Aa783xS8LXm
 so2djZOdUYnW+yE0eho24VQR6nS4YP4Vc+7Mm9skjU0ifjB9mJiWRkzoQnqIgORO
 M+Iab+qjDs9KR/edWh6mZtnvjps0VSW4I40YsClpcgIn550w1DSXe4u6/8Nk+2Bp
 gfrALls91gob0ocxmEdIyLID+M0410HcN/Lvh36nw+tkkGTaXf0D6mkqzdKNrZ3w
 yz+UV9uf19kr1c6zFGcCvUlD0btn9KT+F2legnhgURtwUyDFQcaYQlkpDIeEzUMV
 ZrtzKbSE2v9810YKXjtCnseewdP+Eph/ewN6ODX5yg/fs8K0fyQYTRtYYM50U69X
 md8zznBBDPhJVu5T2Of7my9V1SxvCP8a7LrKjAXuFHpZ/CHiPe+QOWBgG2L+zXXT
 e10/rTg7T2pcyKpBvL/3/mCYeJ+Iup3lKT1EHGCXcKnLGecVgOsbvdG+JnvQMI2J
 FLmu1exvrzi0Gcrs/05hqwyUvkHZ5FB1a+heNOtmQ+h1U0ElXqILyu7brzghupRe
 3phO
 =UgCd
 -----END PGP SIGNATURE-----

Merge tag 'for-linus-20170904' of git://git.infradead.org/linux-mtd

Pull MTD updates from Boris Brezillon:
 "General updates:
   - Constify pci_device_id in various drivers
   - Constify device_type
   - Remove pad control code from the Gemini driver
   - Use %pOF to print OF node full_name
   - Various fixes in the physmap_of driver
   - Remove unused vars in mtdswap
   - Check devm_kzalloc() return value in the spear_smi driver
   - Check clk_prepare_enable() return code in the st_spi_fsm driver
   - Create per MTD device debugfs enties

  NAND updates, from Boris Brezillon:
   - Fix memory leaks in the core
   - Remove unused NAND locking support
   - Rename nand.h into rawnand.h (preparing support for spi NANDs)
   - Use NAND_MAX_ID_LEN where appropriate
   - Fix support for 20nm Hynix chips
   - Fix support for Samsung and Hynix SLC NANDs
   - Various cleanup, improvements and fixes in the qcom driver
   - Fixes for bugs detected by various static code analysis tools
   - Fix mxc ooblayout definition
   - Add a new part_parsers to tmio and sharpsl platform data in order
     to define a custom list of partition parsers
   - Request the reset line in exclusive mode in the sunxi driver
   - Fix a build error in the orion-nand driver when compiled for ARMv4
   - Allow 64-bit mvebu platforms to select the PXA3XX driver

  SPI NOR updates, from Cyrille Pitchen and Marek Vasut:
   - add support to the JEDEC JESD216B specification (SFDP tables).
   - add support to the Intel Denverton SPI flash controller.
   - fix error recovery for Spansion/Cypress SPI NOR memories.
   - fix 4-byte address management for the Aspeed SPI controller.
   - add support to some Microchip SST26 memory parts
   - remove unneeded pinctrl header Write a message for tag:"

* tag 'for-linus-20170904' of git://git.infradead.org/linux-mtd: (74 commits)
  mtd: nand: complain loudly when chip->bits_per_cell is not correctly initialized
  mtd: nand: make Samsung SLC NAND usable again
  mtd: nand: tmio: Register partitions using the parsers
  mfd: tmio: Add partition parsers platform data
  mtd: nand: sharpsl: Register partitions using the parsers
  mtd: nand: sharpsl: Add partition parsers platform data
  mtd: nand: qcom: Support for IPQ8074 QPIC NAND controller
  mtd: nand: qcom: support for IPQ4019 QPIC NAND controller
  dt-bindings: qcom_nandc: IPQ8074 QPIC NAND documentation
  dt-bindings: qcom_nandc: IPQ4019 QPIC NAND documentation
  dt-bindings: qcom_nandc: fix the ipq806x device tree example
  mtd: nand: qcom: support for different DEV_CMD register offsets
  mtd: nand: qcom: QPIC data descriptors handling
  mtd: nand: qcom: enable BAM or ADM mode
  mtd: nand: qcom: erased codeword detection configuration
  mtd: nand: qcom: support for read location registers
  mtd: nand: qcom: support for passing flags in DMA helper functions
  mtd: nand: qcom: add BAM DMA descriptor handling
  mtd: nand: qcom: allocate BAM transaction
  mtd: nand: qcom: DMA mapping support for register read buffer
  ...
This commit is contained in:
Linus Torvalds 2017-09-09 14:48:21 -07:00
commit a59e57da49
162 changed files with 2113 additions and 765 deletions

View file

@ -1809,37 +1809,22 @@ static int dbg_protection_show(struct seq_file *s, void *p)
}
DEBUGFS_RO_ATTR(protection, dbg_protection_show);
static int __init doc_dbg_register(struct docg3 *docg3)
static void __init doc_dbg_register(struct mtd_info *floor)
{
struct dentry *root, *entry;
struct dentry *root = floor->dbg.dfs_dir;
struct docg3 *docg3 = floor->priv;
root = debugfs_create_dir("docg3", NULL);
if (!root)
return -ENOMEM;
if (IS_ERR_OR_NULL(root))
return;
entry = debugfs_create_file("flashcontrol", S_IRUSR, root, docg3,
&flashcontrol_fops);
if (entry)
entry = debugfs_create_file("asic_mode", S_IRUSR, root,
docg3, &asic_mode_fops);
if (entry)
entry = debugfs_create_file("device_id", S_IRUSR, root,
docg3, &device_id_fops);
if (entry)
entry = debugfs_create_file("protection", S_IRUSR, root,
docg3, &protection_fops);
if (entry) {
docg3->debugfs_root = root;
return 0;
} else {
debugfs_remove_recursive(root);
return -ENOMEM;
}
}
static void doc_dbg_unregister(struct docg3 *docg3)
{
debugfs_remove_recursive(docg3->debugfs_root);
debugfs_create_file("docg3_flashcontrol", S_IRUSR, root, docg3,
&flashcontrol_fops);
debugfs_create_file("docg3_asic_mode", S_IRUSR, root, docg3,
&asic_mode_fops);
debugfs_create_file("docg3_device_id", S_IRUSR, root, docg3,
&device_id_fops);
debugfs_create_file("docg3_protection", S_IRUSR, root, docg3,
&protection_fops);
}
/**
@ -2114,6 +2099,8 @@ static int __init docg3_probe(struct platform_device *pdev)
0);
if (ret)
goto err_probe;
doc_dbg_register(cascade->floors[floor]);
}
ret = doc_register_sysfs(pdev, cascade);
@ -2121,7 +2108,6 @@ static int __init docg3_probe(struct platform_device *pdev)
goto err_probe;
platform_set_drvdata(pdev, cascade);
doc_dbg_register(cascade->floors[0]->priv);
return 0;
notfound:
@ -2148,7 +2134,6 @@ static int docg3_release(struct platform_device *pdev)
int floor;
doc_unregister_sysfs(pdev, cascade);
doc_dbg_unregister(docg3);
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
if (cascade->floors[floor])
doc_release_device(cascade->floors[floor]);

View file

@ -299,7 +299,6 @@ struct docg3_cascade {
* @oob_autoecc: if 1, use only bytes 0-7, 15, and fill the others with HW ECC
* if 0, use all the 16 bytes.
* @oob_write_buf: prepared OOB for next page_write
* @debugfs_root: debugfs root node
*/
struct docg3 {
struct device *dev;
@ -312,7 +311,6 @@ struct docg3 {
loff_t oob_write_ofs;
int oob_autoecc;
u8 oob_write_buf[DOC_LAYOUT_OOB_SIZE];
struct dentry *debugfs_root;
};
#define doc_err(fmt, arg...) dev_err(docg3->dev, (fmt), ## arg)

View file

@ -775,6 +775,8 @@ static int spear_smi_probe_config_dt(struct platform_device *pdev,
pdata->board_flash_info = devm_kzalloc(&pdev->dev,
sizeof(*pdata->board_flash_info),
GFP_KERNEL);
if (!pdata->board_flash_info)
return -ENOMEM;
/* Fill structs for each subnode (flash device) */
while ((pp = of_get_next_child(np, pp))) {

View file

@ -2073,15 +2073,17 @@ static int stfsm_probe(struct platform_device *pdev)
ret = stfsm_init(fsm);
if (ret) {
dev_err(&pdev->dev, "Failed to initialise FSM Controller\n");
return ret;
goto err_clk_unprepare;
}
stfsm_fetch_platform_configs(pdev);
/* Detect SPI FLASH device */
info = stfsm_jedec_probe(fsm);
if (!info)
return -ENODEV;
if (!info) {
ret = -ENODEV;
goto err_clk_unprepare;
}
fsm->info = info;
/* Use device size to determine address width */
@ -2095,11 +2097,11 @@ static int stfsm_probe(struct platform_device *pdev)
if (info->config) {
ret = info->config(fsm);
if (ret)
return ret;
goto err_clk_unprepare;
} else {
ret = stfsm_prepare_rwe_seqs_default(fsm);
if (ret)
return ret;
goto err_clk_unprepare;
}
fsm->mtd.name = info->name;
@ -2124,6 +2126,10 @@ static int stfsm_probe(struct platform_device *pdev)
fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10));
return mtd_device_register(&fsm->mtd, NULL, 0);
err_clk_unprepare:
clk_disable_unprepare(fsm->clk);
return ret;
}
static int stfsm_remove(struct platform_device *pdev)
@ -2147,9 +2153,7 @@ static int stfsmfsm_resume(struct device *dev)
{
struct stfsm *fsm = dev_get_drvdata(dev);
clk_prepare_enable(fsm->clk);
return 0;
return clk_prepare_enable(fsm->clk);
}
#endif

View file

@ -33,7 +33,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nftl.h>
#include <linux/mtd/inftl.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/uaccess.h>
#include <asm/errno.h>
#include <asm/io.h>

View file

@ -296,7 +296,7 @@ static void amd76xrom_remove_one(struct pci_dev *pdev)
amd76xrom_cleanup(window);
}
static struct pci_device_id amd76xrom_pci_tbl[] = {
static const struct pci_device_id amd76xrom_pci_tbl[] = {
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440,
@ -319,7 +319,7 @@ static struct pci_driver amd76xrom_driver = {
static int __init init_amd76xrom(void)
{
struct pci_dev *pdev;
struct pci_device_id *id;
const struct pci_device_id *id;
pdev = NULL;
for(id = amd76xrom_pci_tbl; id->vendor; id++) {
pdev = pci_get_device(id->vendor, id->device, NULL);

View file

@ -326,7 +326,7 @@ static void ck804xrom_remove_one(struct pci_dev *pdev)
ck804xrom_cleanup(window);
}
static struct pci_device_id ck804xrom_pci_tbl[] = {
static const struct pci_device_id ck804xrom_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0051), .driver_data = DEV_CK804 },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0360), .driver_data = DEV_MCP55 },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0361), .driver_data = DEV_MCP55 },
@ -353,7 +353,7 @@ static struct pci_driver ck804xrom_driver = {
static int __init init_ck804xrom(void)
{
struct pci_dev *pdev;
struct pci_device_id *id;
const struct pci_device_id *id;
int retVal;
pdev = NULL;

View file

@ -384,7 +384,7 @@ static void esb2rom_remove_one(struct pci_dev *pdev)
esb2rom_cleanup(window);
}
static struct pci_device_id esb2rom_pci_tbl[] = {
static const struct pci_device_id esb2rom_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
@ -414,7 +414,7 @@ static struct pci_driver esb2rom_driver = {
static int __init init_esb2rom(void)
{
struct pci_dev *pdev;
struct pci_device_id *id;
const struct pci_device_id *id;
int retVal;
pdev = NULL;

View file

@ -323,7 +323,7 @@ static void ichxrom_remove_one(struct pci_dev *pdev)
ichxrom_cleanup(window);
}
static struct pci_device_id ichxrom_pci_tbl[] = {
static const struct pci_device_id ichxrom_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
@ -351,7 +351,7 @@ static struct pci_driver ichxrom_driver = {
static int __init init_ichxrom(void)
{
struct pci_dev *pdev;
struct pci_device_id *id;
const struct pci_device_id *id;
pdev = NULL;
for (id = ichxrom_pci_tbl; id->vendor; id++) {

View file

@ -170,7 +170,7 @@ static int vr_nor_init_maps(struct vr_nor_mtd *p)
return err;
}
static struct pci_device_id vr_nor_pci_ids[] = {
static const struct pci_device_id vr_nor_pci_ids[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x500D)},
{0,}
};

View file

@ -228,7 +228,7 @@ static struct mtd_pci_info intel_dc21285_info = {
* PCI device ID table
*/
static struct pci_device_id mtd_pci_ids[] = {
static const struct pci_device_id mtd_pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x530d,

View file

@ -178,8 +178,8 @@ static int of_flash_probe(struct platform_device *dev)
*/
p = of_get_property(dp, "reg", &count);
if (!p || count % reg_tuple_size != 0) {
dev_err(&dev->dev, "Malformed reg property on %s\n",
dev->dev.of_node->full_name);
dev_err(&dev->dev, "Malformed reg property on %pOF\n",
dev->dev.of_node);
err = -EINVAL;
goto err_flash_remove;
}
@ -235,10 +235,10 @@ static int of_flash_probe(struct platform_device *dev)
err = of_flash_probe_gemini(dev, dp, &info->list[i].map);
if (err)
return err;
goto err_out;
err = of_flash_probe_versatile(dev, dp, &info->list[i].map);
if (err)
return err;
goto err_out;
err = -ENOMEM;
info->list[i].map.virt = ioremap(info->list[i].map.phys,

View file

@ -43,13 +43,6 @@
#define FLASH_PARALLEL_HIGH_PIN_CNT (1 << 20) /* else low pin cnt */
/* Miscellaneous Control Register */
#define GLOBAL_MISC_CTRL 0x30
#define FLASH_PADS_MASK 0x07
#define NAND_PADS_DISABLE BIT(2)
#define PFLASH_PADS_DISABLE BIT(1)
#define SFLASH_PADS_DISABLE BIT(0)
static const struct of_device_id syscon_match[] = {
{ .compatible = "cortina,gemini-syscon" },
{ },
@ -102,15 +95,6 @@ int of_flash_probe_gemini(struct platform_device *pdev,
map->bankwidth * 8);
}
/* Activate parallel (NOR flash) mode */
ret = regmap_update_bits(rmap, GLOBAL_MISC_CTRL,
FLASH_PADS_MASK,
SFLASH_PADS_DISABLE | NAND_PADS_DISABLE);
if (ret) {
dev_err(dev, "unable to set up physmap pads\n");
return -ENODEV;
}
dev_info(&pdev->dev, "initialized Gemini-specific physmap control\n");
return 0;

View file

@ -97,7 +97,7 @@ static const struct of_device_id ebi_match[] = {
static int ap_flash_init(struct platform_device *pdev)
{
struct device_node *ebi;
static void __iomem *ebi_base;
void __iomem *ebi_base;
u32 val;
int ret;

View file

@ -55,8 +55,8 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp)
/* Non-CFI userflash device-- once I find one we
* can work on supporting it.
*/
printk(KERN_ERR PFX "Unsupported device at %s, 0x%llx\n",
dp->full_name, (unsigned long long)op->resource[0].start);
printk(KERN_ERR PFX "Unsupported device at %pOF, 0x%llx\n",
dp, (unsigned long long)op->resource[0].start);
return -ENODEV;
}

View file

@ -40,6 +40,7 @@
#include <linux/slab.h>
#include <linux/reboot.h>
#include <linux/leds.h>
#include <linux/debugfs.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
@ -339,7 +340,7 @@ static struct attribute *mtd_attrs[] = {
};
ATTRIBUTE_GROUPS(mtd);
static struct device_type mtd_devtype = {
static const struct device_type mtd_devtype = {
.name = "mtd",
.groups = mtd_groups,
.release = mtd_release,
@ -477,6 +478,8 @@ int mtd_pairing_groups(struct mtd_info *mtd)
}
EXPORT_SYMBOL_GPL(mtd_pairing_groups);
static struct dentry *dfs_dir_mtd;
/**
* add_mtd_device - register an MTD device
* @mtd: pointer to new MTD device info structure
@ -552,6 +555,14 @@ int add_mtd_device(struct mtd_info *mtd)
if (error)
goto fail_added;
if (!IS_ERR_OR_NULL(dfs_dir_mtd)) {
mtd->dbg.dfs_dir = debugfs_create_dir(dev_name(&mtd->dev), dfs_dir_mtd);
if (IS_ERR_OR_NULL(mtd->dbg.dfs_dir)) {
pr_debug("mtd device %s won't show data in debugfs\n",
dev_name(&mtd->dev));
}
}
device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL,
"mtd%dro", i);
@ -594,6 +605,8 @@ int del_mtd_device(struct mtd_info *mtd)
mutex_lock(&mtd_table_mutex);
debugfs_remove_recursive(mtd->dbg.dfs_dir);
if (idr_find(&mtd_idr, mtd->index) != mtd) {
ret = -ENODEV;
goto out_error;
@ -1811,6 +1824,8 @@ static int __init init_mtd(void)
if (ret)
goto out_procfs;
dfs_dir_mtd = debugfs_create_dir("mtd", NULL);
return 0;
out_procfs:
@ -1826,6 +1841,7 @@ err_reg:
static void __exit cleanup_mtd(void)
{
debugfs_remove_recursive(dfs_dir_mtd);
cleanup_mtdchar();
if (proc_mtd)
remove_proc_entry("mtd", NULL);

View file

@ -138,8 +138,6 @@ struct mtdswap_dev {
char *page_buf;
char *oob_buf;
struct dentry *debugfs_root;
};
struct mtdswap_oobdata {
@ -1315,29 +1313,19 @@ static const struct file_operations mtdswap_fops = {
static int mtdswap_add_debugfs(struct mtdswap_dev *d)
{
struct gendisk *gd = d->mbd_dev->disk;
struct device *dev = disk_to_dev(gd);
struct dentry *root;
struct dentry *root = d->mtd->dbg.dfs_dir;
struct dentry *dent;
root = debugfs_create_dir(gd->disk_name, NULL);
if (IS_ERR(root))
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;
if (!root) {
dev_err(dev, "failed to initialize debugfs\n");
if (IS_ERR_OR_NULL(root))
return -1;
}
d->debugfs_root = root;
dent = debugfs_create_file("stats", S_IRUSR, root, d,
dent = debugfs_create_file("mtdswap_stats", S_IRUSR, root, d,
&mtdswap_fops);
if (!dent) {
dev_err(d->dev, "debugfs_create_file failed\n");
debugfs_remove_recursive(root);
d->debugfs_root = NULL;
return -1;
}
@ -1540,7 +1528,6 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev)
{
struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
debugfs_remove_recursive(d->debugfs_root);
del_mtd_blktrans_dev(dev);
mtdswap_cleanup(d);
kfree(d);

View file

@ -315,7 +315,7 @@ config MTD_NAND_ATMEL
config MTD_NAND_PXA3xx
tristate "NAND support on PXA3xx and Armada 370/XP"
depends on PXA3xx || ARCH_MMP || PLAT_ORION
depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU
help
This enables the driver for the NAND flash device found on
PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).

View file

@ -20,7 +20,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/gpio.h>
#include <linux/platform_data/gpio-omap.h>

View file

@ -59,7 +59,7 @@
#include <linux/mfd/syscon/atmel-matrix.h>
#include <linux/mfd/syscon/atmel-smc.h>
#include <linux/module.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
@ -2091,8 +2091,8 @@ atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc)
}
nc->irq = of_irq_get(nand_np, 0);
if (nc->irq < 0) {
ret = nc->irq;
if (nc->irq <= 0) {
ret = nc->irq ?: -ENXIO;
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get IRQ number (err = %d)\n",
ret);
@ -2183,11 +2183,12 @@ atmel_hsmc_nand_controller_init(struct atmel_hsmc_nand_controller *nc)
nc->irq = of_irq_get(np, 0);
of_node_put(np);
if (nc->irq < 0) {
if (nc->irq != -EPROBE_DEFER)
if (nc->irq <= 0) {
ret = nc->irq ?: -ENXIO;
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get IRQ number (err = %d)\n",
nc->irq);
return nc->irq;
ret);
return ret;
}
np = of_parse_phandle(dev->of_node, "atmel,nfc-io", 0);

View file

@ -47,7 +47,7 @@
#include <linux/genalloc.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>

View file

@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/platform_device.h>
#include <asm/io.h>

View file

@ -6,7 +6,7 @@
#endif
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
struct bcm47xxnflash {
struct bcma_drv_cc *cc;

View file

@ -49,7 +49,7 @@
#include <linux/bitops.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>

View file

@ -29,7 +29,7 @@
#include <linux/bitops.h>
#include <linux/mm.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/of.h>
#include <linux/of_platform.h>

View file

@ -13,7 +13,7 @@
#include <linux/device.h>
#undef DEBUG
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/rslib.h>
#include <linux/pci.h>

View file

@ -18,7 +18,7 @@
* CM-X270 board.
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/slab.h>
#include <linux/gpio.h>

View file

@ -24,7 +24,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>

View file

@ -29,7 +29,7 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/slab.h>
#include <linux/of_device.h>

View file

@ -21,7 +21,7 @@
#define __DENALI_H__
#include <linux/bitops.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#define DEVICE_RESET 0x0
#define DEVICE_RESET__BANK(bank) BIT(bank)

View file

@ -118,7 +118,9 @@ static int denali_dt_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "no clk available\n");
return PTR_ERR(dt->clk);
}
clk_prepare_enable(dt->clk);
ret = clk_prepare_enable(dt->clk);
if (ret)
return ret;
denali->clk_x_rate = clk_get_rate(dt->clk);

View file

@ -27,7 +27,7 @@
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/doc2000.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/inftl.h>

View file

@ -41,7 +41,7 @@
#include <linux/bitops.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/bch.h>
#include <linux/bitrev.h>
#include <linux/jiffies.h>

View file

@ -34,7 +34,7 @@
#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>

View file

@ -26,7 +26,7 @@
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/fsl_ifc.h>

View file

@ -14,7 +14,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/mtd.h>

View file

@ -28,7 +28,7 @@
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/platform_device.h>
#include <linux/of.h>

View file

@ -26,7 +26,7 @@
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand-gpio.h>
#include <linux/of.h>

View file

@ -17,7 +17,7 @@
#ifndef __DRIVERS_MTD_NAND_GPMI_NAND_H
#define __DRIVERS_MTD_NAND_GPMI_NAND_H
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>

View file

@ -26,7 +26,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/mtd/partitions.h>

View file

@ -20,7 +20,7 @@
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/gpio.h>

View file

@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/jz4780-nemc.h>

View file

@ -27,7 +27,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <linux/err.h>
@ -705,7 +705,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
res = -ENOENT;
goto err_exit1;
}
clk_prepare_enable(host->clk);
res = clk_prepare_enable(host->clk);
if (res)
goto err_exit1;
nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
nand_chip->dev_ready = lpc32xx_nand_device_ready;
@ -846,9 +848,12 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
static int lpc32xx_nand_resume(struct platform_device *pdev)
{
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
int ret;
/* Re-enable NAND clock */
clk_prepare_enable(host->clk);
ret = clk_prepare_enable(host->clk);
if (ret)
return ret;
/* Fresh init of NAND controller */
lpc32xx_nand_setup(host);

View file

@ -23,7 +23,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <linux/err.h>
@ -840,7 +840,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
res = -ENOENT;
goto err_exit1;
}
clk_prepare_enable(host->clk);
res = clk_prepare_enable(host->clk);
if (res)
goto err_exit1;
/* Set NAND IO addresses and command/ready functions */
chip->IO_ADDR_R = SLC_DATA(host->io_base);
@ -972,9 +974,12 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
static int lpc32xx_nand_resume(struct platform_device *pdev)
{
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
int ret;
/* Re-enable NAND clock */
clk_prepare_enable(host->clk);
ret = clk_prepare_enable(host->clk);
if (ret)
return ret;
/* Fresh init of NAND controller */
lpc32xx_nand_setup(host);

View file

@ -33,7 +33,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/of_address.h>
#include <linux/of_device.h>

View file

@ -464,8 +464,8 @@ static int mtk_ecc_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "failed to get irq\n");
return -EINVAL;
dev_err(dev, "failed to get irq: %d\n", irq);
return irq;
}
ret = dma_set_mask(dev, DMA_BIT_MASK(32));

View file

@ -19,7 +19,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/mtd.h>
#include <linux/module.h>
#include <linux/iopoll.h>

View file

@ -22,7 +22,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/interrupt.h>
#include <linux/device.h>
@ -876,6 +876,8 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
}
}
#define MXC_V1_ECCBYTES 5
static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
@ -885,7 +887,7 @@ static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
return -ERANGE;
oobregion->offset = (section * 16) + 6;
oobregion->length = nand_chip->ecc.bytes;
oobregion->length = MXC_V1_ECCBYTES;
return 0;
}
@ -907,8 +909,7 @@ static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
oobregion->length = 4;
}
} else {
oobregion->offset = ((section - 1) * 16) +
nand_chip->ecc.bytes + 6;
oobregion->offset = ((section - 1) * 16) + MXC_V1_ECCBYTES + 6;
if (section < nand_chip->ecc.steps)
oobregion->length = (section * 16) + 6 -
oobregion->offset;

View file

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
static void amd_nand_decode_id(struct nand_chip *chip)
{

View file

@ -39,7 +39,7 @@
#include <linux/nmi.h>
#include <linux/types.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/nand_bch.h>
#include <linux/interrupt.h>
@ -1247,179 +1247,6 @@ int nand_reset(struct nand_chip *chip, int chipnr)
return 0;
}
/**
* __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
* @mtd: mtd info
* @ofs: offset to start unlock from
* @len: length to unlock
* @invert:
* - when = 0, unlock the range of blocks within the lower and
* upper boundary address
* - when = 1, unlock the range of blocks outside the boundaries
* of the lower and upper boundary address
*
* Returs unlock status.
*/
static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
uint64_t len, int invert)
{
int ret = 0;
int status, page;
struct nand_chip *chip = mtd_to_nand(mtd);
/* Submit address of first page to unlock */
page = ofs >> chip->page_shift;
chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask);
/* Submit address of last page to unlock */
page = (ofs + len) >> chip->page_shift;
chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1,
(page | invert) & chip->pagemask);
/* Call wait ready function */
status = chip->waitfunc(mtd, chip);
/* See if device thinks it succeeded */
if (status & NAND_STATUS_FAIL) {
pr_debug("%s: error status = 0x%08x\n",
__func__, status);
ret = -EIO;
}
return ret;
}
/**
* nand_unlock - [REPLACEABLE] unlocks specified locked blocks
* @mtd: mtd info
* @ofs: offset to start unlock from
* @len: length to unlock
*
* Returns unlock status.
*/
int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret = 0;
int chipnr;
struct nand_chip *chip = mtd_to_nand(mtd);
pr_debug("%s: start = 0x%012llx, len = %llu\n",
__func__, (unsigned long long)ofs, len);
if (check_offs_len(mtd, ofs, len))
return -EINVAL;
/* Align to last block address if size addresses end of the device */
if (ofs + len == mtd->size)
len -= mtd->erasesize;
nand_get_device(mtd, FL_UNLOCKING);
/* Shift to get chip number */
chipnr = ofs >> chip->chip_shift;
/*
* Reset the chip.
* If we want to check the WP through READ STATUS and check the bit 7
* we must reset the chip
* some operation can also clear the bit 7 of status register
* eg. erase/program a locked block
*/
nand_reset(chip, chipnr);
chip->select_chip(mtd, chipnr);
/* Check, if it is write protected */
if (nand_check_wp(mtd)) {
pr_debug("%s: device is write protected!\n",
__func__);
ret = -EIO;
goto out;
}
ret = __nand_unlock(mtd, ofs, len, 0);
out:
chip->select_chip(mtd, -1);
nand_release_device(mtd);
return ret;
}
EXPORT_SYMBOL(nand_unlock);
/**
* nand_lock - [REPLACEABLE] locks all blocks present in the device
* @mtd: mtd info
* @ofs: offset to start unlock from
* @len: length to unlock
*
* This feature is not supported in many NAND parts. 'Micron' NAND parts do
* have this feature, but it allows only to lock all blocks, not for specified
* range for block. Implementing 'lock' feature by making use of 'unlock', for
* now.
*
* Returns lock status.
*/
int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret = 0;
int chipnr, status, page;
struct nand_chip *chip = mtd_to_nand(mtd);
pr_debug("%s: start = 0x%012llx, len = %llu\n",
__func__, (unsigned long long)ofs, len);
if (check_offs_len(mtd, ofs, len))
return -EINVAL;
nand_get_device(mtd, FL_LOCKING);
/* Shift to get chip number */
chipnr = ofs >> chip->chip_shift;
/*
* Reset the chip.
* If we want to check the WP through READ STATUS and check the bit 7
* we must reset the chip
* some operation can also clear the bit 7 of status register
* eg. erase/program a locked block
*/
nand_reset(chip, chipnr);
chip->select_chip(mtd, chipnr);
/* Check, if it is write protected */
if (nand_check_wp(mtd)) {
pr_debug("%s: device is write protected!\n",
__func__);
status = MTD_ERASE_FAILED;
ret = -EIO;
goto out;
}
/* Submit address of first page to lock */
page = ofs >> chip->page_shift;
chip->cmdfunc(mtd, NAND_CMD_LOCK, -1, page & chip->pagemask);
/* Call wait ready function */
status = chip->waitfunc(mtd, chip);
/* See if device thinks it succeeded */
if (status & NAND_STATUS_FAIL) {
pr_debug("%s: error status = 0x%08x\n",
__func__, status);
ret = -EIO;
goto out;
}
ret = __nand_unlock(mtd, ofs, len, 0x1);
out:
chip->select_chip(mtd, -1);
nand_release_device(mtd);
return ret;
}
EXPORT_SYMBOL(nand_lock);
/**
* nand_check_erased_buf - check if a buffer contains (almost) only 0xff data
* @buf: buffer to test
@ -3993,10 +3820,13 @@ static void nand_manufacturer_detect(struct nand_chip *chip)
* nand_decode_ext_id() otherwise.
*/
if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
chip->manufacturer.desc->ops->detect)
chip->manufacturer.desc->ops->detect) {
/* The 3rd id byte holds MLC / multichip data */
chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
chip->manufacturer.desc->ops->detect(chip);
else
} else {
nand_decode_ext_id(chip);
}
}
/*
@ -4036,7 +3866,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
const struct nand_manufacturer *manufacturer;
struct mtd_info *mtd = nand_to_mtd(chip);
int busw;
int i, ret;
int i;
u8 *id_data = chip->id.data;
u8 maf_id, dev_id;
@ -4066,7 +3896,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read entire ID string */
for (i = 0; i < 8; i++)
for (i = 0; i < ARRAY_SIZE(chip->id.data); i++)
id_data[i] = chip->read_byte(mtd);
if (id_data[0] != maf_id || id_data[1] != dev_id) {
@ -4075,7 +3905,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
return -ENODEV;
}
chip->id.len = nand_id_len(id_data, 8);
chip->id.len = nand_id_len(id_data, ARRAY_SIZE(chip->id.data));
/* Try to identify manufacturer */
manufacturer = nand_get_manufacturer(maf_id);
@ -4177,10 +4007,6 @@ ident_done:
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
chip->cmdfunc = nand_command_lp;
ret = nand_manufacturer_init(chip);
if (ret)
return ret;
pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
maf_id, dev_id);
@ -4388,23 +4214,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
return ret;
}
/* Initialize the ->data_interface field. */
ret = nand_init_data_interface(chip);
if (ret)
goto err_nand_init;
/*
* Setup the data interface correctly on the chip and controller side.
* This explicit call to nand_setup_data_interface() is only required
* for the first die, because nand_reset() has been called before
* ->data_interface and ->default_onfi_timing_mode were set.
* For the other dies, nand_reset() will automatically switch to the
* best mode for us.
*/
ret = nand_setup_data_interface(chip, 0);
if (ret)
goto err_nand_init;
nand_maf_id = chip->id.data[0];
nand_dev_id = chip->id.data[1];
@ -4434,12 +4243,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
mtd->size = i * chip->chipsize;
return 0;
err_nand_init:
/* Free manufacturer priv data. */
nand_manufacturer_cleanup(chip);
return ret;
}
EXPORT_SYMBOL(nand_scan_ident);
@ -4826,55 +4629,60 @@ int nand_scan_tail(struct mtd_info *mtd)
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_ecc_ctrl *ecc = &chip->ecc;
struct nand_buffers *nbuf = NULL;
int ret;
int ret, i;
/* New bad blocks should be marked in OOB, flash-based BBT, or both */
if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
!(chip->bbt_options & NAND_BBT_USE_FLASH))) {
ret = -EINVAL;
goto err_ident;
return -EINVAL;
}
if (invalid_ecc_page_accessors(chip)) {
pr_err("Invalid ECC page accessors setup\n");
ret = -EINVAL;
goto err_ident;
return -EINVAL;
}
if (!(chip->options & NAND_OWN_BUFFERS)) {
nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
if (!nbuf) {
ret = -ENOMEM;
goto err_ident;
}
if (!nbuf)
return -ENOMEM;
nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
if (!nbuf->ecccalc) {
ret = -ENOMEM;
goto err_free;
goto err_free_nbuf;
}
nbuf->ecccode = kmalloc(mtd->oobsize, GFP_KERNEL);
if (!nbuf->ecccode) {
ret = -ENOMEM;
goto err_free;
goto err_free_nbuf;
}
nbuf->databuf = kmalloc(mtd->writesize + mtd->oobsize,
GFP_KERNEL);
if (!nbuf->databuf) {
ret = -ENOMEM;
goto err_free;
goto err_free_nbuf;
}
chip->buffers = nbuf;
} else {
if (!chip->buffers) {
ret = -ENOMEM;
goto err_ident;
}
} else if (!chip->buffers) {
return -ENOMEM;
}
/*
* FIXME: some NAND manufacturer drivers expect the first die to be
* selected when manufacturer->init() is called. They should be fixed
* to explictly select the relevant die when interacting with the NAND
* chip.
*/
chip->select_chip(mtd, 0);
ret = nand_manufacturer_init(chip);
chip->select_chip(mtd, -1);
if (ret)
goto err_free_nbuf;
/* Set the internal oob buffer location, just after the page data */
chip->oob_poi = chip->buffers->databuf + mtd->writesize;
@ -4896,7 +4704,7 @@ int nand_scan_tail(struct mtd_info *mtd)
WARN(1, "No oob scheme defined for oobsize %d\n",
mtd->oobsize);
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
}
@ -4911,7 +4719,7 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!ecc->calculate || !ecc->correct || !ecc->hwctl) {
WARN(1, "No ECC functions supplied; hardware ECC not possible\n");
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
if (!ecc->read_page)
ecc->read_page = nand_read_page_hwecc_oob_first;
@ -4943,7 +4751,7 @@ int nand_scan_tail(struct mtd_info *mtd)
ecc->write_page == nand_write_page_hwecc)) {
WARN(1, "No ECC functions supplied; hardware ECC not possible\n");
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
/* Use standard syndrome read/write page function? */
if (!ecc->read_page)
@ -4963,7 +4771,7 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!ecc->strength) {
WARN(1, "Driver must set ecc.strength when using hardware ECC\n");
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
break;
}
@ -4976,7 +4784,7 @@ int nand_scan_tail(struct mtd_info *mtd)
ret = nand_set_ecc_soft_ops(mtd);
if (ret) {
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
break;
@ -4984,7 +4792,7 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!ecc->read_page || !ecc->write_page) {
WARN(1, "No ECC functions supplied; on-die ECC not possible\n");
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
if (!ecc->read_oob)
ecc->read_oob = nand_read_oob_std;
@ -5008,7 +4816,7 @@ int nand_scan_tail(struct mtd_info *mtd)
default:
WARN(1, "Invalid NAND_ECC_MODE %d\n", ecc->mode);
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
/* For many systems, the standard OOB write also works for raw */
@ -5029,13 +4837,13 @@ int nand_scan_tail(struct mtd_info *mtd)
if (ecc->steps * ecc->size != mtd->writesize) {
WARN(1, "Invalid ECC parameters\n");
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
ecc->total = ecc->steps * ecc->bytes;
if (ecc->total > mtd->oobsize) {
WARN(1, "Total number of ECC bytes exceeded oobsize\n");
ret = -EINVAL;
goto err_free;
goto err_nand_manuf_cleanup;
}
/*
@ -5117,6 +4925,21 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!mtd->bitflip_threshold)
mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4);
/* Initialize the ->data_interface field. */
ret = nand_init_data_interface(chip);
if (ret)
goto err_nand_manuf_cleanup;
/* Enter fastest possible mode on all dies. */
for (i = 0; i < chip->numchips; i++) {
chip->select_chip(mtd, i);
ret = nand_setup_data_interface(chip, i);
chip->select_chip(mtd, -1);
if (ret)
goto err_nand_data_iface_cleanup;
}
/* Check, if we should skip the bad block table scan */
if (chip->options & NAND_SKIP_BBTSCAN)
return 0;
@ -5124,10 +4947,17 @@ int nand_scan_tail(struct mtd_info *mtd)
/* Build bad block table */
ret = chip->scan_bbt(mtd);
if (ret)
goto err_free;
goto err_nand_data_iface_cleanup;
return 0;
err_free:
err_nand_data_iface_cleanup:
nand_release_data_interface(chip);
err_nand_manuf_cleanup:
nand_manufacturer_cleanup(chip);
err_free_nbuf:
if (nbuf) {
kfree(nbuf->databuf);
kfree(nbuf->ecccode);
@ -5135,12 +4965,6 @@ err_free:
kfree(nbuf);
}
err_ident:
/* Clean up nand_scan_ident(). */
/* Free manufacturer priv data. */
nand_manufacturer_cleanup(chip);
return ret;
}
EXPORT_SYMBOL(nand_scan_tail);

View file

@ -61,7 +61,7 @@
#include <linux/types.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/bbm.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/vmalloc.h>

View file

@ -25,7 +25,7 @@
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_bch.h>
#include <linux/bch.h>

View file

@ -43,7 +43,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <asm/byteorder.h>
#else

View file

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/sizes.h>
#include <linux/slab.h>
@ -477,7 +477,7 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip,
* The ECC requirements field meaning depends on the
* NAND technology.
*/
u8 nand_tech = chip->id.data[5] & 0x3;
u8 nand_tech = chip->id.data[5] & 0x7;
if (nand_tech < 3) {
/* > 26nm, reference: H27UBG8T2A datasheet */
@ -533,7 +533,7 @@ static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip,
if (nand_tech > 0)
chip->options |= NAND_NEED_SCRAMBLING;
} else {
nand_tech = chip->id.data[5] & 0x3;
nand_tech = chip->id.data[5] & 0x7;
/* < 32nm */
if (nand_tech > 2)

View file

@ -6,7 +6,7 @@
* published by the Free Software Foundation.
*
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/sizes.h>
#define LP_OPTIONS 0

View file

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
static int macronix_nand_init(struct nand_chip *chip)
{

View file

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
/*
* Special Micron status bit that indicates when the block has been

View file

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
static void samsung_nand_decode_id(struct nand_chip *chip)
{

View file

@ -11,7 +11,7 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
static const struct nand_data_interface onfi_sdr_timings[] = {
/* Mode 0 */

View file

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
static void toshiba_nand_decode_id(struct nand_chip *chip)
{

View file

@ -33,7 +33,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_bch.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
@ -287,11 +287,6 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should "
/* Maximum page cache pages needed to read or write a NAND page to the cache_file */
#define NS_MAX_HELD_PAGES 16
struct nandsim_debug_info {
struct dentry *dfs_root;
struct dentry *dfs_wear_report;
};
/*
* A union to represent flash memory contents and flash buffer.
*/
@ -370,8 +365,6 @@ struct nandsim {
void *file_buf;
struct page *held_pages[NS_MAX_HELD_PAGES];
int held_cnt;
struct nandsim_debug_info dbg;
};
/*
@ -524,39 +517,23 @@ static const struct file_operations dfs_fops = {
*/
static int nandsim_debugfs_create(struct nandsim *dev)
{
struct nandsim_debug_info *dbg = &dev->dbg;
struct dentry *root = nsmtd->dbg.dfs_dir;
struct dentry *dent;
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;
dent = debugfs_create_dir("nandsim", NULL);
if (!dent) {
NS_ERR("cannot create \"nandsim\" debugfs directory\n");
return -ENODEV;
}
dbg->dfs_root = dent;
if (IS_ERR_OR_NULL(root))
return -1;
dent = debugfs_create_file("wear_report", S_IRUSR,
dbg->dfs_root, dev, &dfs_fops);
if (!dent)
goto out_remove;
dbg->dfs_wear_report = dent;
dent = debugfs_create_file("nandsim_wear_report", S_IRUSR,
root, dev, &dfs_fops);
if (IS_ERR_OR_NULL(dent)) {
NS_ERR("cannot create \"nandsim_wear_report\" debugfs entry\n");
return -1;
}
return 0;
out_remove:
debugfs_remove_recursive(dbg->dfs_root);
return -ENODEV;
}
/**
* nandsim_debugfs_remove - destroy all debugfs files
*/
static void nandsim_debugfs_remove(struct nandsim *ns)
{
if (IS_ENABLED(CONFIG_DEBUG_FS))
debugfs_remove_recursive(ns->dbg.dfs_root);
}
/*
@ -2352,9 +2329,6 @@ static int __init ns_init_module(void)
if ((retval = setup_wear_reporting(nsmtd)) != 0)
goto err_exit;
if ((retval = nandsim_debugfs_create(nand)) != 0)
goto err_exit;
if ((retval = init_nandsim(nsmtd)) != 0)
goto err_exit;
@ -2370,10 +2344,12 @@ static int __init ns_init_module(void)
if (retval != 0)
goto err_exit;
if ((retval = nandsim_debugfs_create(nand)) != 0)
goto err_exit;
return 0;
err_exit:
nandsim_debugfs_remove(nand);
free_nandsim(nand);
nand_release(nsmtd);
for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i)
@ -2396,7 +2372,6 @@ static void __exit ns_cleanup_module(void)
struct nandsim *ns = nand_get_controller_data(chip);
int i;
nandsim_debugfs_remove(ns);
free_nandsim(ns); /* Free nandsim private resources */
nand_release(nsmtd); /* Unregister driver */
for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)

View file

@ -22,7 +22,7 @@
*
*/
#include <linux/module.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/ndfc.h>

View file

@ -19,7 +19,7 @@
#include <linux/err.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#define REG_FMICSR 0x00

View file

@ -18,7 +18,7 @@
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/omap-dma.h>
#include <linux/io.h>

View file

@ -15,7 +15,7 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <linux/err.h>
@ -54,13 +54,16 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
void __iomem *io_base = chip->IO_ADDR_R;
#if __LINUX_ARM_ARCH__ >= 5
uint64_t *buf64;
#endif
int i = 0;
while (len && (unsigned long)buf & 7) {
*buf++ = readb(io_base);
len--;
}
#if __LINUX_ARM_ARCH__ >= 5
buf64 = (uint64_t *)buf;
while (i < len/8) {
/*
@ -74,6 +77,10 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
buf64[i++] = x;
}
i *= 8;
#else
readsl(io_base, buf, len/4);
i = len / 4 * 4;
#endif
while (i < len)
buf[i++] = readb(io_base);
}

View file

@ -21,7 +21,7 @@
#include <linux/clk.h>
#include <linux/reset.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/of.h>
@ -112,14 +112,19 @@ static int oxnas_nand_probe(struct platform_device *pdev)
if (count > 1)
return -EINVAL;
clk_prepare_enable(oxnas->clk);
err = clk_prepare_enable(oxnas->clk);
if (err)
return err;
device_reset_optional(&pdev->dev);
for_each_child_of_node(np, nand_np) {
chip = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip),
GFP_KERNEL);
if (!chip)
return -ENOMEM;
if (!chip) {
err = -ENOMEM;
goto err_clk_unprepare;
}
chip->controller = &oxnas->base;
@ -139,12 +144,12 @@ static int oxnas_nand_probe(struct platform_device *pdev)
/* Scan to find existence of the device */
err = nand_scan(mtd, 1);
if (err)
return err;
goto err_clk_unprepare;
err = mtd_device_register(mtd, NULL, 0);
if (err) {
nand_release(mtd);
return err;
goto err_clk_unprepare;
}
oxnas->chips[nchips] = chip;
@ -152,12 +157,18 @@ static int oxnas_nand_probe(struct platform_device *pdev)
}
/* Exit if no chips found */
if (!nchips)
return -ENODEV;
if (!nchips) {
err = -ENODEV;
goto err_clk_unprepare;
}
platform_set_drvdata(pdev, oxnas);
return 0;
err_clk_unprepare:
clk_disable_unprepare(oxnas->clk);
return err;
}
static int oxnas_nand_remove(struct platform_device *pdev)

View file

@ -25,7 +25,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>

View file

@ -15,7 +15,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
struct plat_nand_data {

View file

@ -21,7 +21,7 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/iopoll.h>

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
#include <linux/pci.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/spinlock.h>

View file

@ -43,7 +43,7 @@
#include <linux/of_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>

View file

@ -38,7 +38,7 @@
#include <linux/string.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/sh_flctl.h>
@ -411,7 +411,7 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,
dma_addr = dma_map_single(chan->device->dev, buf, len, dir);
if (dma_addr)
if (!dma_mapping_error(chan->device->dev, dma_addr))
desc = dmaengine_prep_slave_single(chan, dma_addr, len,
tr_dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
@ -1141,8 +1141,8 @@ static int flctl_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "failed to get flste irq data\n");
return -ENXIO;
dev_err(&pdev->dev, "failed to get flste irq data: %d\n", irq);
return irq;
}
ret = devm_request_irq(&pdev->dev, irq, flctl_handle_flste, IRQF_SHARED,

View file

@ -17,7 +17,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/sharpsl.h>
@ -183,7 +183,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
/* Register the partitions */
mtd->name = "sharpsl-nand";
err = mtd_device_parse_register(mtd, NULL, NULL,
err = mtd_device_parse_register(mtd, data->part_parsers, NULL,
data->partitions, data->nr_partitions);
if (err)
goto err_add;

View file

@ -7,7 +7,7 @@
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/module.h>
#include <linux/sizes.h>
#include "sm_common.h"

View file

@ -13,7 +13,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>

View file

@ -31,7 +31,7 @@
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <linux/delay.h>
@ -2212,7 +2212,7 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
if (ret)
goto out_ahb_clk_unprepare;
nfc->reset = devm_reset_control_get_optional(dev, "ahb");
nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
if (IS_ERR(nfc->reset)) {
ret = PTR_ERR(nfc->reset);
goto out_mod_clk_unprepare;

View file

@ -11,7 +11,7 @@
#include <linux/clk.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>

View file

@ -34,7 +34,7 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/slab.h>
@ -440,7 +440,9 @@ static int tmio_probe(struct platform_device *dev)
goto err_irq;
/* Register the partitions */
retval = mtd_device_parse_register(mtd, NULL, NULL,
retval = mtd_device_parse_register(mtd,
data ? data->part_parsers : NULL,
NULL,
data ? data->partition : NULL,
data ? data->num_partitions : 0);
if (!retval)

View file

@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/io.h>

View file

@ -31,10 +31,9 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@ -814,12 +813,14 @@ static int vf610_nfc_suspend(struct device *dev)
static int vf610_nfc_resume(struct device *dev)
{
int err;
struct mtd_info *mtd = dev_get_drvdata(dev);
struct vf610_nfc *nfc = mtd_to_nfc(mtd);
pinctrl_pm_select_default_state(dev);
clk_prepare_enable(nfc->clk);
err = clk_prepare_enable(nfc->clk);
if (err)
return err;
vf610_nfc_preinit_controller(nfc);
vf610_nfc_init_controller(nfc);

View file

@ -7,7 +7,7 @@
* Copyright © 2016 Hauke Mehrtens <hauke@hauke-m.de>
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>

View file

@ -34,7 +34,7 @@
#include <linux/kmod.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nftl.h>
#include <linux/mtd/blktrans.h>

View file

@ -25,7 +25,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nftl.h>
#define SECTORSIZE 512

View file

@ -50,8 +50,8 @@ static int parse_ofpart_partitions(struct mtd_info *master,
* when using another parser), so don't be louder than
* KERN_DEBUG
*/
pr_debug("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n",
master->name, mtd_node->full_name);
pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n",
master->name, mtd_node);
ofpart_node = mtd_node;
dedicated = false;
} else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) {
@ -87,9 +87,9 @@ static int parse_ofpart_partitions(struct mtd_info *master,
reg = of_get_property(pp, "reg", &len);
if (!reg) {
if (dedicated) {
pr_debug("%s: ofpart partition %s (%s) missing reg property.\n",
master->name, pp->full_name,
mtd_node->full_name);
pr_debug("%s: ofpart partition %pOF (%pOF) missing reg property.\n",
master->name, pp,
mtd_node);
goto ofpart_fail;
} else {
nr_parts--;
@ -100,9 +100,9 @@ static int parse_ofpart_partitions(struct mtd_info *master,
a_cells = of_n_addr_cells(pp);
s_cells = of_n_size_cells(pp);
if (len / 4 != a_cells + s_cells) {
pr_debug("%s: ofpart partition %s (%s) error parsing reg property.\n",
master->name, pp->full_name,
mtd_node->full_name);
pr_debug("%s: ofpart partition %pOF (%pOF) error parsing reg property.\n",
master->name, pp,
mtd_node);
goto ofpart_fail;
}
@ -131,8 +131,8 @@ static int parse_ofpart_partitions(struct mtd_info *master,
return nr_parts;
ofpart_fail:
pr_err("%s: error parsing ofpart partition %s (%s)\n",
master->name, pp->full_name, mtd_node->full_name);
pr_err("%s: error parsing ofpart partition %pOF (%pOF)\n",
master->name, pp, mtd_node);
ret = -EINVAL;
ofpart_none:
of_node_put(pp);
@ -166,8 +166,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
if (!part)
return 0; /* No partitions found */
pr_warn("Device tree uses obsolete partition map binding: %s\n",
dp->full_name);
pr_warn("Device tree uses obsolete partition map binding: %pOF\n", dp);
nr_parts = plen / sizeof(part[0]);

View file

@ -89,6 +89,22 @@ config SPI_NXP_SPIFI
config SPI_INTEL_SPI
tristate
config SPI_INTEL_SPI_PCI
tristate "Intel PCH/PCU SPI flash PCI driver" if EXPERT
depends on X86 && PCI
select SPI_INTEL_SPI
help
This enables PCI support for the Intel PCH/PCU SPI controller in
master mode. This controller is present in modern Intel hardware
and is used to hold BIOS and other persistent settings. Using
this driver it is possible to upgrade BIOS directly from Linux.
Say N here unless you know what you are doing. Overwriting the
SPI flash may render the system unbootable.
To compile this driver as a module, choose M here: the module
will be called intel-spi-pci.
config SPI_INTEL_SPI_PLATFORM
tristate "Intel PCH/PCU SPI flash platform driver" if EXPERT
depends on X86

View file

@ -7,5 +7,6 @@ obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o
obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o
obj-$(CONFIG_SPI_STM32_QUADSPI) += stm32-quadspi.o
obj-$(CONFIG_SPI_STM32_QUADSPI) += stm32-quadspi.o

View file

@ -621,19 +621,18 @@ static void aspeed_smc_chip_set_type(struct aspeed_smc_chip *chip, int type)
}
/*
* The AST2500 FMC flash controller should be strapped by hardware, or
* autodetected, but the AST2500 SPI flash needs to be set.
* The first chip of the AST2500 FMC flash controller is strapped by
* hardware, or autodetected, but other chips need to be set. Enforce
* the 4B setting for all chips.
*/
static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip)
{
struct aspeed_smc_controller *controller = chip->controller;
u32 reg;
if (chip->controller->info == &spi_2500_info) {
reg = readl(controller->regs + CE_CONTROL_REG);
reg |= 1 << chip->cs;
writel(reg, controller->regs + CE_CONTROL_REG);
}
reg = readl(controller->regs + CE_CONTROL_REG);
reg |= 1 << chip->cs;
writel(reg, controller->regs + CE_CONTROL_REG);
}
/*

View file

@ -35,7 +35,6 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.h>
/* QSPI register offsets */
#define QSPI_CR 0x0000 /* Control Register */

View file

@ -355,16 +355,16 @@ static int hisi_spi_nor_register(struct device_node *np,
ret = of_property_read_u32(np, "reg", &priv->chipselect);
if (ret) {
dev_err(dev, "There's no reg property for %s\n",
np->full_name);
dev_err(dev, "There's no reg property for %pOF\n",
np);
return ret;
}
ret = of_property_read_u32(np, "spi-max-frequency",
&priv->clkrate);
if (ret) {
dev_err(dev, "There's no spi-max-frequency property for %s\n",
np->full_name);
dev_err(dev, "There's no spi-max-frequency property for %pOF\n",
np);
return ret;
}
priv->host = host;

View file

@ -0,0 +1,82 @@
/*
* Intel PCH/PCU SPI flash PCI driver.
*
* Copyright (C) 2016, Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "intel-spi.h"
#define BCR 0xdc
#define BCR_WPD BIT(0)
static const struct intel_spi_boardinfo bxt_info = {
.type = INTEL_SPI_BXT,
};
static int intel_spi_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct intel_spi_boardinfo *info;
struct intel_spi *ispi;
u32 bcr;
int ret;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
info = devm_kmemdup(&pdev->dev, (void *)id->driver_data, sizeof(*info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
/* Try to make the chip read/write */
pci_read_config_dword(pdev, BCR, &bcr);
if (!(bcr & BCR_WPD)) {
bcr |= BCR_WPD;
pci_write_config_dword(pdev, BCR, bcr);
pci_read_config_dword(pdev, BCR, &bcr);
}
info->writeable = !!(bcr & BCR_WPD);
ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
if (IS_ERR(ispi))
return PTR_ERR(ispi);
pci_set_drvdata(pdev, ispi);
return 0;
}
static void intel_spi_pci_remove(struct pci_dev *pdev)
{
intel_spi_remove(pci_get_drvdata(pdev));
}
static const struct pci_device_id intel_spi_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
{ },
};
MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids);
static struct pci_driver intel_spi_pci_driver = {
.name = "intel-spi",
.id_table = intel_spi_pci_ids,
.probe = intel_spi_pci_probe,
.remove = intel_spi_pci_remove,
};
module_pci_driver(intel_spi_pci_driver);
MODULE_DESCRIPTION("Intel PCH/PCU SPI flash PCI driver");
MODULE_AUTHOR("Mika Westerberg <[email protected]>");
MODULE_LICENSE("GPL v2");

View file

@ -24,7 +24,6 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>

View file

@ -17,6 +17,7 @@
#include <linux/mutex.h>
#include <linux/math64.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/of_platform.h>
@ -86,6 +87,8 @@ struct flash_info {
* to support memory size above 128Mib.
*/
#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */
#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */
#define USE_CLSR BIT(14) /* use CLSR command */
};
#define JEDEC_MFR(info) ((info)->id[0])
@ -306,8 +309,18 @@ static inline int spi_nor_sr_ready(struct spi_nor *nor)
int sr = read_sr(nor);
if (sr < 0)
return sr;
else
return !(sr & SR_WIP);
if (nor->flags & SNOR_F_USE_CLSR && sr & (SR_E_ERR | SR_P_ERR)) {
if (sr & SR_E_ERR)
dev_err(nor->dev, "Erase Error occurred\n");
else
dev_err(nor->dev, "Programming Error occurred\n");
nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0);
return -EIO;
}
return !(sr & SR_WIP);
}
static inline int spi_nor_fsr_ready(struct spi_nor *nor)
@ -1041,15 +1054,15 @@ static const struct flash_info spi_nor_ids[] = {
*/
{ "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
{ "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
{ "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
{ "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
{ "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
{ "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
{ "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
{ "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
@ -1079,6 +1092,7 @@ static const struct flash_info spi_nor_ids[] = {
{ "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
{ "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
{ "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
/* ST Microelectronics -- newer production may have feature updates */
{ "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) },
@ -1380,6 +1394,16 @@ write_err:
return ret;
}
/**
* macronix_quad_enable() - set QE bit in Status Register.
* @nor: pointer to a 'struct spi_nor'
*
* Set the Quad Enable (QE) bit in the Status Register.
*
* bit 6 of the Status Register is the QE bit for Macronix like QSPI memories.
*
* Return: 0 on success, -errno otherwise.
*/
static int macronix_quad_enable(struct spi_nor *nor)
{
int ret, val;
@ -1413,22 +1437,13 @@ static int macronix_quad_enable(struct spi_nor *nor)
* second byte will be written to the configuration register.
* Return negative if error occurred.
*/
static int write_sr_cr(struct spi_nor *nor, u16 val)
{
nor->cmd_buf[0] = val & 0xff;
nor->cmd_buf[1] = (val >> 8);
return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2);
}
static int spansion_quad_enable(struct spi_nor *nor)
static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr)
{
int ret;
int quad_en = CR_QUAD_EN_SPAN << 8;
write_enable(nor);
ret = write_sr_cr(nor, quad_en);
ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2);
if (ret < 0) {
dev_err(nor->dev,
"error while writing configuration register\n");
@ -1442,6 +1457,41 @@ static int spansion_quad_enable(struct spi_nor *nor)
return ret;
}
return 0;
}
/**
* spansion_quad_enable() - set QE bit in Configuraiton Register.
* @nor: pointer to a 'struct spi_nor'
*
* Set the Quad Enable (QE) bit in the Configuration Register.
* This function is kept for legacy purpose because it has been used for a
* long time without anybody complaining but it should be considered as
* deprecated and maybe buggy.
* First, this function doesn't care about the previous values of the Status
* and Configuration Registers when it sets the QE bit (bit 1) in the
* Configuration Register: all other bits are cleared, which may have unwanted
* side effects like removing some block protections.
* Secondly, it uses the Read Configuration Register (35h) instruction though
* some very old and few memories don't support this instruction. If a pull-up
* resistor is present on the MISO/IO1 line, we might still be able to pass the
* "read back" test because the QSPI memory doesn't recognize the command,
* so leaves the MISO/IO1 line state unchanged, hence read_cr() returns 0xFF.
*
* bit 1 of the Configuration Register is the QE bit for Spansion like QSPI
* memories.
*
* Return: 0 on success, -errno otherwise.
*/
static int spansion_quad_enable(struct spi_nor *nor)
{
u8 sr_cr[2] = {0, CR_QUAD_EN_SPAN};
int ret;
ret = write_sr_cr(nor, sr_cr);
if (ret)
return ret;
/* read back and check it */
ret = read_cr(nor);
if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
@ -1452,6 +1502,140 @@ static int spansion_quad_enable(struct spi_nor *nor)
return 0;
}
/**
* spansion_no_read_cr_quad_enable() - set QE bit in Configuration Register.
* @nor: pointer to a 'struct spi_nor'
*
* Set the Quad Enable (QE) bit in the Configuration Register.
* This function should be used with QSPI memories not supporting the Read
* Configuration Register (35h) instruction.
*
* bit 1 of the Configuration Register is the QE bit for Spansion like QSPI
* memories.
*
* Return: 0 on success, -errno otherwise.
*/
static int spansion_no_read_cr_quad_enable(struct spi_nor *nor)
{
u8 sr_cr[2];
int ret;
/* Keep the current value of the Status Register. */
ret = read_sr(nor);
if (ret < 0) {
dev_err(nor->dev, "error while reading status register\n");
return -EINVAL;
}
sr_cr[0] = ret;
sr_cr[1] = CR_QUAD_EN_SPAN;
return write_sr_cr(nor, sr_cr);
}
/**
* spansion_read_cr_quad_enable() - set QE bit in Configuration Register.
* @nor: pointer to a 'struct spi_nor'
*
* Set the Quad Enable (QE) bit in the Configuration Register.
* This function should be used with QSPI memories supporting the Read
* Configuration Register (35h) instruction.
*
* bit 1 of the Configuration Register is the QE bit for Spansion like QSPI
* memories.
*
* Return: 0 on success, -errno otherwise.
*/
static int spansion_read_cr_quad_enable(struct spi_nor *nor)
{
struct device *dev = nor->dev;
u8 sr_cr[2];
int ret;
/* Check current Quad Enable bit value. */
ret = read_cr(nor);
if (ret < 0) {
dev_err(dev, "error while reading configuration register\n");
return -EINVAL;
}
if (ret & CR_QUAD_EN_SPAN)
return 0;
sr_cr[1] = ret | CR_QUAD_EN_SPAN;
/* Keep the current value of the Status Register. */
ret = read_sr(nor);
if (ret < 0) {
dev_err(dev, "error while reading status register\n");
return -EINVAL;
}
sr_cr[0] = ret;
ret = write_sr_cr(nor, sr_cr);
if (ret)
return ret;
/* Read back and check it. */
ret = read_cr(nor);
if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
dev_err(nor->dev, "Spansion Quad bit not set\n");
return -EINVAL;
}
return 0;
}
/**
* sr2_bit7_quad_enable() - set QE bit in Status Register 2.
* @nor: pointer to a 'struct spi_nor'
*
* Set the Quad Enable (QE) bit in the Status Register 2.
*
* This is one of the procedures to set the QE bit described in the SFDP
* (JESD216 rev B) specification but no manufacturer using this procedure has
* been identified yet, hence the name of the function.
*
* Return: 0 on success, -errno otherwise.
*/
static int sr2_bit7_quad_enable(struct spi_nor *nor)
{
u8 sr2;
int ret;
/* Check current Quad Enable bit value. */
ret = nor->read_reg(nor, SPINOR_OP_RDSR2, &sr2, 1);
if (ret)
return ret;
if (sr2 & SR2_QUAD_EN_BIT7)
return 0;
/* Update the Quad Enable bit. */
sr2 |= SR2_QUAD_EN_BIT7;
write_enable(nor);
ret = nor->write_reg(nor, SPINOR_OP_WRSR2, &sr2, 1);
if (ret < 0) {
dev_err(nor->dev, "error while writing status register 2\n");
return -EINVAL;
}
ret = spi_nor_wait_till_ready(nor);
if (ret < 0) {
dev_err(nor->dev, "timeout while writing status register 2\n");
return ret;
}
/* Read back and check it. */
ret = nor->read_reg(nor, SPINOR_OP_RDSR2, &sr2, 1);
if (!(ret > 0 && (sr2 & SR2_QUAD_EN_BIT7))) {
dev_err(nor->dev, "SR2 Quad bit not set\n");
return -EINVAL;
}
return 0;
}
static int spi_nor_check(struct spi_nor *nor)
{
if (!nor->dev || !nor->read || !nor->write ||
@ -1591,6 +1775,560 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
pp->proto = proto;
}
/*
* Serial Flash Discoverable Parameters (SFDP) parsing.
*/
/**
* spi_nor_read_sfdp() - read Serial Flash Discoverable Parameters.
* @nor: pointer to a 'struct spi_nor'
* @addr: offset in the SFDP area to start reading data from
* @len: number of bytes to read
* @buf: buffer where the SFDP data are copied into
*
* Whatever the actual numbers of bytes for address and dummy cycles are
* for (Fast) Read commands, the Read SFDP (5Ah) instruction is always
* followed by a 3-byte address and 8 dummy clock cycles.
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
size_t len, void *buf)
{
u8 addr_width, read_opcode, read_dummy;
int ret;
read_opcode = nor->read_opcode;
addr_width = nor->addr_width;
read_dummy = nor->read_dummy;
nor->read_opcode = SPINOR_OP_RDSFDP;
nor->addr_width = 3;
nor->read_dummy = 8;
while (len) {
ret = nor->read(nor, addr, len, (u8 *)buf);
if (!ret || ret > len) {
ret = -EIO;
goto read_err;
}
if (ret < 0)
goto read_err;
buf += ret;
addr += ret;
len -= ret;
}
ret = 0;
read_err:
nor->read_opcode = read_opcode;
nor->addr_width = addr_width;
nor->read_dummy = read_dummy;
return ret;
}
struct sfdp_parameter_header {
u8 id_lsb;
u8 minor;
u8 major;
u8 length; /* in double words */
u8 parameter_table_pointer[3]; /* byte address */
u8 id_msb;
};
#define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb)
#define SFDP_PARAM_HEADER_PTP(p) \
(((p)->parameter_table_pointer[2] << 16) | \
((p)->parameter_table_pointer[1] << 8) | \
((p)->parameter_table_pointer[0] << 0))
#define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */
#define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */
#define SFDP_SIGNATURE 0x50444653U
#define SFDP_JESD216_MAJOR 1
#define SFDP_JESD216_MINOR 0
#define SFDP_JESD216A_MINOR 5
#define SFDP_JESD216B_MINOR 6
struct sfdp_header {
u32 signature; /* Ox50444653U <=> "SFDP" */
u8 minor;
u8 major;
u8 nph; /* 0-base number of parameter headers */
u8 unused;
/* Basic Flash Parameter Table. */
struct sfdp_parameter_header bfpt_header;
};
/* Basic Flash Parameter Table */
/*
* JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs.
* They are indexed from 1 but C arrays are indexed from 0.
*/
#define BFPT_DWORD(i) ((i) - 1)
#define BFPT_DWORD_MAX 16
/* The first version of JESB216 defined only 9 DWORDs. */
#define BFPT_DWORD_MAX_JESD216 9
/* 1st DWORD. */
#define BFPT_DWORD1_FAST_READ_1_1_2 BIT(16)
#define BFPT_DWORD1_ADDRESS_BYTES_MASK GENMASK(18, 17)
#define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY (0x0UL << 17)
#define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4 (0x1UL << 17)
#define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY (0x2UL << 17)
#define BFPT_DWORD1_DTR BIT(19)
#define BFPT_DWORD1_FAST_READ_1_2_2 BIT(20)
#define BFPT_DWORD1_FAST_READ_1_4_4 BIT(21)
#define BFPT_DWORD1_FAST_READ_1_1_4 BIT(22)
/* 5th DWORD. */
#define BFPT_DWORD5_FAST_READ_2_2_2 BIT(0)
#define BFPT_DWORD5_FAST_READ_4_4_4 BIT(4)
/* 11th DWORD. */
#define BFPT_DWORD11_PAGE_SIZE_SHIFT 4
#define BFPT_DWORD11_PAGE_SIZE_MASK GENMASK(7, 4)
/* 15th DWORD. */
/*
* (from JESD216 rev B)
* Quad Enable Requirements (QER):
* - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4
* reads based on instruction. DQ3/HOLD# functions are hold during
* instruction phase.
* - 001b: QE is bit 1 of status register 2. It is set via Write Status with
* two data bytes where bit 1 of the second byte is one.
* [...]
* Writing only one byte to the status register has the side-effect of
* clearing status register 2, including the QE bit. The 100b code is
* used if writing one byte to the status register does not modify
* status register 2.
* - 010b: QE is bit 6 of status register 1. It is set via Write Status with
* one data byte where bit 6 is one.
* [...]
* - 011b: QE is bit 7 of status register 2. It is set via Write status
* register 2 instruction 3Eh with one data byte where bit 7 is one.
* [...]
* The status register 2 is read using instruction 3Fh.
* - 100b: QE is bit 1 of status register 2. It is set via Write Status with
* two data bytes where bit 1 of the second byte is one.
* [...]
* In contrast to the 001b code, writing one byte to the status
* register does not modify status register 2.
* - 101b: QE is bit 1 of status register 2. Status register 1 is read using
* Read Status instruction 05h. Status register2 is read using
* instruction 35h. QE is set via Writ Status instruction 01h with
* two data bytes where bit 1 of the second byte is one.
* [...]
*/
#define BFPT_DWORD15_QER_MASK GENMASK(22, 20)
#define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */
#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY (0x1UL << 20)
#define BFPT_DWORD15_QER_SR1_BIT6 (0x2UL << 20) /* Macronix */
#define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20)
#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20)
#define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
struct sfdp_bfpt {
u32 dwords[BFPT_DWORD_MAX];
};
/* Fast Read settings. */
static inline void
spi_nor_set_read_settings_from_bfpt(struct spi_nor_read_command *read,
u16 half,
enum spi_nor_protocol proto)
{
read->num_mode_clocks = (half >> 5) & 0x07;
read->num_wait_states = (half >> 0) & 0x1f;
read->opcode = (half >> 8) & 0xff;
read->proto = proto;
}
struct sfdp_bfpt_read {
/* The Fast Read x-y-z hardware capability in params->hwcaps.mask. */
u32 hwcaps;
/*
* The <supported_bit> bit in <supported_dword> BFPT DWORD tells us
* whether the Fast Read x-y-z command is supported.
*/
u32 supported_dword;
u32 supported_bit;
/*
* The half-word at offset <setting_shift> in <setting_dword> BFPT DWORD
* encodes the op code, the number of mode clocks and the number of wait
* states to be used by Fast Read x-y-z command.
*/
u32 settings_dword;
u32 settings_shift;
/* The SPI protocol for this Fast Read x-y-z command. */
enum spi_nor_protocol proto;
};
static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = {
/* Fast Read 1-1-2 */
{
SNOR_HWCAPS_READ_1_1_2,
BFPT_DWORD(1), BIT(16), /* Supported bit */
BFPT_DWORD(4), 0, /* Settings */
SNOR_PROTO_1_1_2,
},
/* Fast Read 1-2-2 */
{
SNOR_HWCAPS_READ_1_2_2,
BFPT_DWORD(1), BIT(20), /* Supported bit */
BFPT_DWORD(4), 16, /* Settings */
SNOR_PROTO_1_2_2,
},
/* Fast Read 2-2-2 */
{
SNOR_HWCAPS_READ_2_2_2,
BFPT_DWORD(5), BIT(0), /* Supported bit */
BFPT_DWORD(6), 16, /* Settings */
SNOR_PROTO_2_2_2,
},
/* Fast Read 1-1-4 */
{
SNOR_HWCAPS_READ_1_1_4,
BFPT_DWORD(1), BIT(22), /* Supported bit */
BFPT_DWORD(3), 16, /* Settings */
SNOR_PROTO_1_1_4,
},
/* Fast Read 1-4-4 */
{
SNOR_HWCAPS_READ_1_4_4,
BFPT_DWORD(1), BIT(21), /* Supported bit */
BFPT_DWORD(3), 0, /* Settings */
SNOR_PROTO_1_4_4,
},
/* Fast Read 4-4-4 */
{
SNOR_HWCAPS_READ_4_4_4,
BFPT_DWORD(5), BIT(4), /* Supported bit */
BFPT_DWORD(7), 16, /* Settings */
SNOR_PROTO_4_4_4,
},
};
struct sfdp_bfpt_erase {
/*
* The half-word at offset <shift> in DWORD <dwoard> encodes the
* op code and erase sector size to be used by Sector Erase commands.
*/
u32 dword;
u32 shift;
};
static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = {
/* Erase Type 1 in DWORD8 bits[15:0] */
{BFPT_DWORD(8), 0},
/* Erase Type 2 in DWORD8 bits[31:16] */
{BFPT_DWORD(8), 16},
/* Erase Type 3 in DWORD9 bits[15:0] */
{BFPT_DWORD(9), 0},
/* Erase Type 4 in DWORD9 bits[31:16] */
{BFPT_DWORD(9), 16},
};
static int spi_nor_hwcaps_read2cmd(u32 hwcaps);
/**
* spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table.
* @nor: pointer to a 'struct spi_nor'
* @bfpt_header: pointer to the 'struct sfdp_parameter_header' describing
* the Basic Flash Parameter Table length and version
* @params: pointer to the 'struct spi_nor_flash_parameter' to be
* filled
*
* The Basic Flash Parameter Table is the main and only mandatory table as
* defined by the SFDP (JESD216) specification.
* It provides us with the total size (memory density) of the data array and
* the number of address bytes for Fast Read, Page Program and Sector Erase
* commands.
* For Fast READ commands, it also gives the number of mode clock cycles and
* wait states (regrouped in the number of dummy clock cycles) for each
* supported instruction op code.
* For Page Program, the page size is now available since JESD216 rev A, however
* the supported instruction op codes are still not provided.
* For Sector Erase commands, this table stores the supported instruction op
* codes and the associated sector sizes.
* Finally, the Quad Enable Requirements (QER) are also available since JESD216
* rev A. The QER bits encode the manufacturer dependent procedure to be
* executed to set the Quad Enable (QE) bit in some internal register of the
* Quad SPI memory. Indeed the QE bit, when it exists, must be set before
* sending any Quad SPI command to the memory. Actually, setting the QE bit
* tells the memory to reassign its WP# and HOLD#/RESET# pins to functions IO2
* and IO3 hence enabling 4 (Quad) I/O lines.
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_parse_bfpt(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
struct spi_nor_flash_parameter *params)
{
struct mtd_info *mtd = &nor->mtd;
struct sfdp_bfpt bfpt;
size_t len;
int i, cmd, err;
u32 addr;
u16 half;
/* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */
if (bfpt_header->length < BFPT_DWORD_MAX_JESD216)
return -EINVAL;
/* Read the Basic Flash Parameter Table. */
len = min_t(size_t, sizeof(bfpt),
bfpt_header->length * sizeof(u32));
addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
memset(&bfpt, 0, sizeof(bfpt));
err = spi_nor_read_sfdp(nor, addr, len, &bfpt);
if (err < 0)
return err;
/* Fix endianness of the BFPT DWORDs. */
for (i = 0; i < BFPT_DWORD_MAX; i++)
bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]);
/* Number of address bytes. */
switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY:
nor->addr_width = 3;
break;
case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY:
nor->addr_width = 4;
break;
default:
break;
}
/* Flash Memory Density (in bits). */
params->size = bfpt.dwords[BFPT_DWORD(2)];
if (params->size & BIT(31)) {
params->size &= ~BIT(31);
params->size = 1ULL << params->size;
} else {
params->size++;
}
params->size >>= 3; /* Convert to bytes. */
/* Fast Read settings. */
for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_reads); i++) {
const struct sfdp_bfpt_read *rd = &sfdp_bfpt_reads[i];
struct spi_nor_read_command *read;
if (!(bfpt.dwords[rd->supported_dword] & rd->supported_bit)) {
params->hwcaps.mask &= ~rd->hwcaps;
continue;
}
params->hwcaps.mask |= rd->hwcaps;
cmd = spi_nor_hwcaps_read2cmd(rd->hwcaps);
read = &params->reads[cmd];
half = bfpt.dwords[rd->settings_dword] >> rd->settings_shift;
spi_nor_set_read_settings_from_bfpt(read, half, rd->proto);
}
/* Sector Erase settings. */
for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) {
const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i];
u32 erasesize;
u8 opcode;
half = bfpt.dwords[er->dword] >> er->shift;
erasesize = half & 0xff;
/* erasesize == 0 means this Erase Type is not supported. */
if (!erasesize)
continue;
erasesize = 1U << erasesize;
opcode = (half >> 8) & 0xff;
#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
if (erasesize == SZ_4K) {
nor->erase_opcode = opcode;
mtd->erasesize = erasesize;
break;
}
#endif
if (!mtd->erasesize || mtd->erasesize < erasesize) {
nor->erase_opcode = opcode;
mtd->erasesize = erasesize;
}
}
/* Stop here if not JESD216 rev A or later. */
if (bfpt_header->length < BFPT_DWORD_MAX)
return 0;
/* Page size: this field specifies 'N' so the page size = 2^N bytes. */
params->page_size = bfpt.dwords[BFPT_DWORD(11)];
params->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK;
params->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT;
params->page_size = 1U << params->page_size;
/* Quad Enable Requirements. */
switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) {
case BFPT_DWORD15_QER_NONE:
params->quad_enable = NULL;
break;
case BFPT_DWORD15_QER_SR2_BIT1_BUGGY:
case BFPT_DWORD15_QER_SR2_BIT1_NO_RD:
params->quad_enable = spansion_no_read_cr_quad_enable;
break;
case BFPT_DWORD15_QER_SR1_BIT6:
params->quad_enable = macronix_quad_enable;
break;
case BFPT_DWORD15_QER_SR2_BIT7:
params->quad_enable = sr2_bit7_quad_enable;
break;
case BFPT_DWORD15_QER_SR2_BIT1:
params->quad_enable = spansion_read_cr_quad_enable;
break;
default:
return -EINVAL;
}
return 0;
}
/**
* spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
* @nor: pointer to a 'struct spi_nor'
* @params: pointer to the 'struct spi_nor_flash_parameter' to be
* filled
*
* The Serial Flash Discoverable Parameters are described by the JEDEC JESD216
* specification. This is a standard which tends to supported by almost all
* (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at
* runtime the main parameters needed to perform basic SPI flash operations such
* as Fast Read, Page Program or Sector Erase commands.
*
* Return: 0 on success, -errno otherwise.
*/
static int spi_nor_parse_sfdp(struct spi_nor *nor,
struct spi_nor_flash_parameter *params)
{
const struct sfdp_parameter_header *param_header, *bfpt_header;
struct sfdp_parameter_header *param_headers = NULL;
struct sfdp_header header;
struct device *dev = nor->dev;
size_t psize;
int i, err;
/* Get the SFDP header. */
err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header);
if (err < 0)
return err;
/* Check the SFDP header version. */
if (le32_to_cpu(header.signature) != SFDP_SIGNATURE ||
header.major != SFDP_JESD216_MAJOR ||
header.minor < SFDP_JESD216_MINOR)
return -EINVAL;
/*
* Verify that the first and only mandatory parameter header is a
* Basic Flash Parameter Table header as specified in JESD216.
*/
bfpt_header = &header.bfpt_header;
if (SFDP_PARAM_HEADER_ID(bfpt_header) != SFDP_BFPT_ID ||
bfpt_header->major != SFDP_JESD216_MAJOR)
return -EINVAL;
/*
* Allocate memory then read all parameter headers with a single
* Read SFDP command. These parameter headers will actually be parsed
* twice: a first time to get the latest revision of the basic flash
* parameter table, then a second time to handle the supported optional
* tables.
* Hence we read the parameter headers once for all to reduce the
* processing time. Also we use kmalloc() instead of devm_kmalloc()
* because we don't need to keep these parameter headers: the allocated
* memory is always released with kfree() before exiting this function.
*/
if (header.nph) {
psize = header.nph * sizeof(*param_headers);
param_headers = kmalloc(psize, GFP_KERNEL);
if (!param_headers)
return -ENOMEM;
err = spi_nor_read_sfdp(nor, sizeof(header),
psize, param_headers);
if (err < 0) {
dev_err(dev, "failed to read SFDP parameter headers\n");
goto exit;
}
}
/*
* Check other parameter headers to get the latest revision of
* the basic flash parameter table.
*/
for (i = 0; i < header.nph; i++) {
param_header = &param_headers[i];
if (SFDP_PARAM_HEADER_ID(param_header) == SFDP_BFPT_ID &&
param_header->major == SFDP_JESD216_MAJOR &&
(param_header->minor > bfpt_header->minor ||
(param_header->minor == bfpt_header->minor &&
param_header->length > bfpt_header->length)))
bfpt_header = param_header;
}
err = spi_nor_parse_bfpt(nor, bfpt_header, params);
if (err)
goto exit;
/* Parse other parameter headers. */
for (i = 0; i < header.nph; i++) {
param_header = &param_headers[i];
switch (SFDP_PARAM_HEADER_ID(param_header)) {
case SFDP_SECTOR_MAP_ID:
dev_info(dev, "non-uniform erase sector maps are not supported yet.\n");
break;
default:
break;
}
if (err)
goto exit;
}
exit:
kfree(param_headers);
return err;
}
static int spi_nor_init_params(struct spi_nor *nor,
const struct flash_info *info,
struct spi_nor_flash_parameter *params)
@ -1646,11 +2384,28 @@ static int spi_nor_init_params(struct spi_nor *nor,
break;
default:
/* Kept only for backward compatibility purpose. */
params->quad_enable = spansion_quad_enable;
break;
}
}
/* Override the parameters with data read from SFDP tables. */
nor->addr_width = 0;
nor->mtd.erasesize = 0;
if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) &&
!(info->flags & SPI_NOR_SKIP_SFDP)) {
struct spi_nor_flash_parameter sfdp_params;
memcpy(&sfdp_params, params, sizeof(sfdp_params));
if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
nor->addr_width = 0;
nor->mtd.erasesize = 0;
} else {
memcpy(params, &sfdp_params, sizeof(*params));
}
}
return 0;
}
@ -1762,6 +2517,10 @@ static int spi_nor_select_erase(struct spi_nor *nor,
{
struct mtd_info *mtd = &nor->mtd;
/* Do nothing if already configured from SFDP. */
if (mtd->erasesize)
return 0;
#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
/* prefer "small sector" erase if possible */
if (info->flags & SECT_4K) {
@ -1960,6 +2719,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
nor->flags |= SNOR_F_HAS_SR_TB;
if (info->flags & NO_CHIP_ERASE)
nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
if (info->flags & USE_CLSR)
nor->flags |= SNOR_F_USE_CLSR;
if (info->flags & SPI_NOR_NO_ERASE)
mtd->flags |= MTD_NO_ERASE;
@ -1994,9 +2755,11 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
if (ret)
return ret;
if (info->addr_width)
if (nor->addr_width) {
/* already configured from SFDP */
} else if (info->addr_width) {
nor->addr_width = info->addr_width;
else if (mtd->size > 0x1000000) {
} else if (mtd->size > 0x1000000) {
/* enable 4-byte addressing if the device exceeds 16MiB */
nor->addr_width = 4;
if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||

View file

@ -16,7 +16,7 @@
#include <linux/slab.h>
#include <linux/hdreg.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/blktrans.h>
struct ssfdcr_record {

View file

@ -47,7 +47,7 @@
#include <linux/moduleparam.h>
#include <linux/mtd/mtd.h>
#include <linux/err.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/rawnand.h>
#include <linux/slab.h>
#include "mtd_test.h"