diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-17 12:59:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-17 12:59:26 -0500 |
commit | d6666be6f0c43efb9475d1d35fbef9f8be61b7b1 (patch) | |
tree | f544aec1dfdffa0c6b6d381f8e6710cad7e16074 | |
parent | 0ea90b9e79cff66934119e6dd8fa8e9d0f7d005a (diff) | |
parent | 68f29815034e9dc9ed53cad85946c32b07adc8cc (diff) |
Merge tag 'for-linus-20141215' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris:
"Summary:
- Add device tree support for DoC3
- SPI NOR:
Refactoring, for better layering between spi-nor.c and its
driver users (e.g., m25p80.c)
New flash device support
Support 6-byte ID strings
- NAND:
New NAND driver for Allwinner SoC's (sunxi)
GPMI NAND: add support for raw (no ECC) access, for testing
purposes
Add ATO manufacturer ID
A few odd driver fixes
- MTD tests:
Allow testers to compensate for OOB bitflips in oobtest
Fix a torturetest regression
- nandsim: Support longer ID byte strings
And more"
* tag 'for-linus-20141215' of git://git.infradead.org/linux-mtd: (63 commits)
mtd: tests: abort torturetest on erase errors
mtd: physmap_of: fix potential NULL dereference
mtd: spi-nor: allow NULL as chip name and try to auto detect it
mtd: nand: gpmi: add raw oob access functions
mtd: nand: gpmi: add proper raw access support
mtd: nand: gpmi: add gpmi_copy_bits function
mtd: spi-nor: factor out write_enable() for erase commands
mtd: spi-nor: add support for s25fl128s
mtd: spi-nor: remove the jedec_id/ext_id
mtd: spi-nor: add id/id_len for flash_info{}
mtd: nand: correct the comment of function nand_block_isreserved()
jffs2: Drop bogus if in comment
mtd: atmel_nand: replace memcpy32_toio/memcpy32_fromio with memcpy
mtd: cafe_nand: drop duplicate .write_page implementation
mtd: m25p80: Add support for serial flash Spansion S25FL132K
MTD: m25p80: fix inconsistency in m25p_ids compared to spi_nor_ids
mtd: spi-nor: improve wait-till-ready timeout loop
mtd: delete unnecessary checks before two function calls
mtd: nand: omap: Fix NAND enumeration on 3430 LDP
mtd: nand: add ATO manufacturer info
...
42 files changed, 2414 insertions, 472 deletions
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt index 6edc3b616e98..1fe6dde98499 100644 --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt | |||
@@ -5,7 +5,9 @@ Required properties: | |||
5 | - reg : should specify localbus address and size used for the chip, | 5 | - reg : should specify localbus address and size used for the chip, |
6 | and hardware ECC controller if available. | 6 | and hardware ECC controller if available. |
7 | If the hardware ECC is PMECC, it should contain address and size for | 7 | If the hardware ECC is PMECC, it should contain address and size for |
8 | PMECC, PMECC Error Location controller and ROM which has lookup tables. | 8 | PMECC and PMECC Error Location controller. |
9 | The PMECC lookup table address and size in ROM is optional. If not | ||
10 | specified, driver will build it in runtime. | ||
9 | - atmel,nand-addr-offset : offset for the address latch. | 11 | - atmel,nand-addr-offset : offset for the address latch. |
10 | - atmel,nand-cmd-offset : offset for the command latch. | 12 | - atmel,nand-cmd-offset : offset for the command latch. |
11 | - #address-cells, #size-cells : Must be present if the device has sub-nodes | 13 | - #address-cells, #size-cells : Must be present if the device has sub-nodes |
@@ -27,7 +29,7 @@ Optional properties: | |||
27 | are: 512, 1024. | 29 | are: 512, 1024. |
28 | - atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM | 30 | - atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM |
29 | for different sector size. First one is for sector size 512, the next is for | 31 | for different sector size. First one is for sector size 512, the next is for |
30 | sector size 1024. | 32 | sector size 1024. If not specified, driver will build the table in runtime. |
31 | - nand-bus-width : 8 or 16 bus width if not present 8 | 33 | - nand-bus-width : 8 or 16 bus width if not present 8 |
32 | - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false | 34 | - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false |
33 | - Nand Flash Controller(NFC) is a slave driver under Atmel nand flash | 35 | - Nand Flash Controller(NFC) is a slave driver under Atmel nand flash |
diff --git a/Documentation/devicetree/bindings/mtd/diskonchip.txt b/Documentation/devicetree/bindings/mtd/diskonchip.txt new file mode 100644 index 000000000000..3e13bfdbea5b --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/diskonchip.txt | |||
@@ -0,0 +1,15 @@ | |||
1 | M-Systems and Sandisk DiskOnChip devices | ||
2 | |||
3 | M-System DiskOnChip G3 | ||
4 | ====================== | ||
5 | The Sandisk (formerly M-Systems) docg3 is a nand device of 64M to 256MB. | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: should be "m-systems,diskonchip-g3" | ||
9 | - reg: register base and size | ||
10 | |||
11 | Example: | ||
12 | docg3: flash@0 { | ||
13 | compatible = "m-systems,diskonchip-g3"; | ||
14 | reg = <0x0 0x2000>; | ||
15 | }; | ||
diff --git a/Documentation/devicetree/bindings/mtd/gpio-control-nand.txt b/Documentation/devicetree/bindings/mtd/gpio-control-nand.txt index 36ef07d3c90f..af8915b41ccf 100644 --- a/Documentation/devicetree/bindings/mtd/gpio-control-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpio-control-nand.txt | |||
@@ -11,8 +11,8 @@ Required properties: | |||
11 | are made in native endianness. | 11 | are made in native endianness. |
12 | - #address-cells, #size-cells : Must be present if the device has sub-nodes | 12 | - #address-cells, #size-cells : Must be present if the device has sub-nodes |
13 | representing partitions. | 13 | representing partitions. |
14 | - gpios : specifies the gpio pins to control the NAND device. nwp is an | 14 | - gpios : Specifies the GPIO pins to control the NAND device. The order of |
15 | optional gpio and may be set to 0 if not present. | 15 | GPIO references is: RDY, nCE, ALE, CLE, and an optional nWP. |
16 | 16 | ||
17 | Optional properties: | 17 | Optional properties: |
18 | - bank-width : Width (in bytes) of the device. If not present, the width | 18 | - bank-width : Width (in bytes) of the device. If not present, the width |
@@ -35,11 +35,11 @@ gpio-nand@1,0 { | |||
35 | reg = <1 0x0000 0x2>; | 35 | reg = <1 0x0000 0x2>; |
36 | #address-cells = <1>; | 36 | #address-cells = <1>; |
37 | #size-cells = <1>; | 37 | #size-cells = <1>; |
38 | gpios = <&banka 1 0 /* rdy */ | 38 | gpios = <&banka 1 0>, /* RDY */ |
39 | &banka 2 0 /* nce */ | 39 | <&banka 2 0>, /* nCE */ |
40 | &banka 3 0 /* ale */ | 40 | <&banka 3 0>, /* ALE */ |
41 | &banka 4 0 /* cle */ | 41 | <&banka 4 0>, /* CLE */ |
42 | 0 /* nwp */>; | 42 | <0>; /* nWP */ |
43 | 43 | ||
44 | partition@0 { | 44 | partition@0 { |
45 | ... | 45 | ... |
diff --git a/Documentation/devicetree/bindings/mtd/sunxi-nand.txt b/Documentation/devicetree/bindings/mtd/sunxi-nand.txt new file mode 100644 index 000000000000..0273adb8638c --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/sunxi-nand.txt | |||
@@ -0,0 +1,45 @@ | |||
1 | Allwinner NAND Flash Controller (NFC) | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "allwinner,sun4i-a10-nand". | ||
5 | - reg : shall contain registers location and length for data and reg. | ||
6 | - interrupts : shall define the nand controller interrupt. | ||
7 | - #address-cells: shall be set to 1. Encode the nand CS. | ||
8 | - #size-cells : shall be set to 0. | ||
9 | - clocks : shall reference nand controller clocks. | ||
10 | - clock-names : nand controller internal clock names. Shall contain : | ||
11 | * "ahb" : AHB gating clock | ||
12 | * "mod" : nand controller clock | ||
13 | |||
14 | Optional children nodes: | ||
15 | Children nodes represent the available nand chips. | ||
16 | |||
17 | Optional properties: | ||
18 | - allwinner,rb : shall contain the native Ready/Busy ids. | ||
19 | or | ||
20 | - rb-gpios : shall contain the gpios used as R/B pins. | ||
21 | - nand-ecc-mode : one of the supported ECC modes ("hw", "hw_syndrome", "soft", | ||
22 | "soft_bch" or "none") | ||
23 | |||
24 | see Documentation/devicetree/mtd/nand.txt for generic bindings. | ||
25 | |||
26 | |||
27 | Examples: | ||
28 | nfc: nand@01c03000 { | ||
29 | compatible = "allwinner,sun4i-a10-nand"; | ||
30 | reg = <0x01c03000 0x1000>; | ||
31 | interrupts = <0 37 1>; | ||
32 | clocks = <&ahb_gates 13>, <&nand_clk>; | ||
33 | clock-names = "ahb", "mod"; | ||
34 | #address-cells = <1>; | ||
35 | #size-cells = <0>; | ||
36 | pinctrl-names = "default"; | ||
37 | pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>; | ||
38 | status = "okay"; | ||
39 | |||
40 | nand@0 { | ||
41 | reg = <0>; | ||
42 | allwinner,rb = <0>; | ||
43 | nand-ecc-mode = "soft_bch"; | ||
44 | }; | ||
45 | }; | ||
diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c index 3d5d792d5cb2..410c39749872 100644 --- a/drivers/memory/fsl_ifc.c +++ b/drivers/memory/fsl_ifc.c | |||
@@ -61,7 +61,7 @@ int fsl_ifc_find(phys_addr_t addr_base) | |||
61 | if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) | 61 | if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) |
62 | return -ENODEV; | 62 | return -ENODEV; |
63 | 63 | ||
64 | for (i = 0; i < ARRAY_SIZE(fsl_ifc_ctrl_dev->regs->cspr_cs); i++) { | 64 | for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) { |
65 | u32 cspr = in_be32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); | 65 | u32 cspr = in_be32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); |
66 | if (cspr & CSPR_V && (cspr & CSPR_BA) == | 66 | if (cspr & CSPR_V && (cspr & CSPR_BA) == |
67 | convert_ifc_address(addr_base)) | 67 | convert_ifc_address(addr_base)) |
@@ -213,7 +213,7 @@ static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data) | |||
213 | static int fsl_ifc_ctrl_probe(struct platform_device *dev) | 213 | static int fsl_ifc_ctrl_probe(struct platform_device *dev) |
214 | { | 214 | { |
215 | int ret = 0; | 215 | int ret = 0; |
216 | 216 | int version, banks; | |
217 | 217 | ||
218 | dev_info(&dev->dev, "Freescale Integrated Flash Controller\n"); | 218 | dev_info(&dev->dev, "Freescale Integrated Flash Controller\n"); |
219 | 219 | ||
@@ -231,6 +231,15 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) | |||
231 | goto err; | 231 | goto err; |
232 | } | 232 | } |
233 | 233 | ||
234 | version = ioread32be(&fsl_ifc_ctrl_dev->regs->ifc_rev) & | ||
235 | FSL_IFC_VERSION_MASK; | ||
236 | banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; | ||
237 | dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", | ||
238 | version >> 24, (version >> 16) & 0xf, banks); | ||
239 | |||
240 | fsl_ifc_ctrl_dev->version = version; | ||
241 | fsl_ifc_ctrl_dev->banks = banks; | ||
242 | |||
234 | /* get the Controller level irq */ | 243 | /* get the Controller level irq */ |
235 | fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); | 244 | fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); |
236 | if (fsl_ifc_ctrl_dev->irq == NO_IRQ) { | 245 | if (fsl_ifc_ctrl_dev->irq == NO_IRQ) { |
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 94b821042d9d..71fea895ce38 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -133,7 +133,7 @@ config MTD_OF_PARTS | |||
133 | help | 133 | help |
134 | This provides a partition parsing function which derives | 134 | This provides a partition parsing function which derives |
135 | the partition map from the children of the flash node, | 135 | the partition map from the children of the flash node, |
136 | as described in Documentation/devicetree/booting-without-of.txt. | 136 | as described in Documentation/devicetree/bindings/mtd/partition.txt. |
137 | 137 | ||
138 | config MTD_AR7_PARTS | 138 | config MTD_AR7_PARTS |
139 | tristate "TI AR7 partitioning support" | 139 | tristate "TI AR7 partitioning support" |
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index 8057f52a45b7..cc13ea5ce4d5 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c | |||
@@ -15,8 +15,12 @@ | |||
15 | #include <linux/mtd/mtd.h> | 15 | #include <linux/mtd/mtd.h> |
16 | #include <linux/mtd/partitions.h> | 16 | #include <linux/mtd/partitions.h> |
17 | 17 | ||
18 | /* 10 parts were found on sflash on Netgear WNDR4500 */ | 18 | /* |
19 | #define BCM47XXPART_MAX_PARTS 12 | 19 | * NAND flash on Netgear R6250 was verified to contain 15 partitions. |
20 | * This will result in allocating too big array for some old devices, but the | ||
21 | * memory will be freed soon anyway (see mtd_device_parse_register). | ||
22 | */ | ||
23 | #define BCM47XXPART_MAX_PARTS 20 | ||
20 | 24 | ||
21 | /* | 25 | /* |
22 | * Amount of bytes we read when analyzing each block of flash memory. | 26 | * Amount of bytes we read when analyzing each block of flash memory. |
@@ -168,18 +172,26 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
168 | i++; | 172 | i++; |
169 | } | 173 | } |
170 | 174 | ||
171 | bcm47xxpart_add_part(&parts[curr_part++], "linux", | 175 | if (trx->offset[i]) { |
172 | offset + trx->offset[i], 0); | 176 | bcm47xxpart_add_part(&parts[curr_part++], |
173 | i++; | 177 | "linux", |
178 | offset + trx->offset[i], | ||
179 | 0); | ||
180 | i++; | ||
181 | } | ||
174 | 182 | ||
175 | /* | 183 | /* |
176 | * Pure rootfs size is known and can be calculated as: | 184 | * Pure rootfs size is known and can be calculated as: |
177 | * trx->length - trx->offset[i]. We don't fill it as | 185 | * trx->length - trx->offset[i]. We don't fill it as |
178 | * we want to have jffs2 (overlay) in the same mtd. | 186 | * we want to have jffs2 (overlay) in the same mtd. |
179 | */ | 187 | */ |
180 | bcm47xxpart_add_part(&parts[curr_part++], "rootfs", | 188 | if (trx->offset[i]) { |
181 | offset + trx->offset[i], 0); | 189 | bcm47xxpart_add_part(&parts[curr_part++], |
182 | i++; | 190 | "rootfs", |
191 | offset + trx->offset[i], | ||
192 | 0); | ||
193 | i++; | ||
194 | } | ||
183 | 195 | ||
184 | last_trx_part = curr_part - 1; | 196 | last_trx_part = curr_part - 1; |
185 | 197 | ||
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 3096f3ded3ad..286b97a304cf 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -2654,8 +2654,7 @@ static void cfi_intelext_destroy(struct mtd_info *mtd) | |||
2654 | kfree(cfi); | 2654 | kfree(cfi); |
2655 | for (i = 0; i < mtd->numeraseregions; i++) { | 2655 | for (i = 0; i < mtd->numeraseregions; i++) { |
2656 | region = &mtd->eraseregions[i]; | 2656 | region = &mtd->eraseregions[i]; |
2657 | if (region->lockmap) | 2657 | kfree(region->lockmap); |
2658 | kfree(region->lockmap); | ||
2659 | } | 2658 | } |
2660 | kfree(mtd->eraseregions); | 2659 | kfree(mtd->eraseregions); |
2661 | } | 2660 | } |
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 72346048532d..448ce42f951e 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/of.h> | ||
25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
26 | #include <linux/string.h> | 27 | #include <linux/string.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
@@ -1655,22 +1656,21 @@ static int dbg_flashctrl_show(struct seq_file *s, void *p) | |||
1655 | { | 1656 | { |
1656 | struct docg3 *docg3 = (struct docg3 *)s->private; | 1657 | struct docg3 *docg3 = (struct docg3 *)s->private; |
1657 | 1658 | ||
1658 | int pos = 0; | ||
1659 | u8 fctrl; | 1659 | u8 fctrl; |
1660 | 1660 | ||
1661 | mutex_lock(&docg3->cascade->lock); | 1661 | mutex_lock(&docg3->cascade->lock); |
1662 | fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | 1662 | fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); |
1663 | mutex_unlock(&docg3->cascade->lock); | 1663 | mutex_unlock(&docg3->cascade->lock); |
1664 | 1664 | ||
1665 | pos += seq_printf(s, | 1665 | seq_printf(s, "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n", |
1666 | "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n", | 1666 | fctrl, |
1667 | fctrl, | 1667 | fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-", |
1668 | fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-", | 1668 | fctrl & DOC_CTRL_CE ? "active" : "inactive", |
1669 | fctrl & DOC_CTRL_CE ? "active" : "inactive", | 1669 | fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-", |
1670 | fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-", | 1670 | fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-", |
1671 | fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-", | 1671 | fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready"); |
1672 | fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready"); | 1672 | |
1673 | return pos; | 1673 | return 0; |
1674 | } | 1674 | } |
1675 | DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show); | 1675 | DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show); |
1676 | 1676 | ||
@@ -1678,58 +1678,56 @@ static int dbg_asicmode_show(struct seq_file *s, void *p) | |||
1678 | { | 1678 | { |
1679 | struct docg3 *docg3 = (struct docg3 *)s->private; | 1679 | struct docg3 *docg3 = (struct docg3 *)s->private; |
1680 | 1680 | ||
1681 | int pos = 0, pctrl, mode; | 1681 | int pctrl, mode; |
1682 | 1682 | ||
1683 | mutex_lock(&docg3->cascade->lock); | 1683 | mutex_lock(&docg3->cascade->lock); |
1684 | pctrl = doc_register_readb(docg3, DOC_ASICMODE); | 1684 | pctrl = doc_register_readb(docg3, DOC_ASICMODE); |
1685 | mode = pctrl & 0x03; | 1685 | mode = pctrl & 0x03; |
1686 | mutex_unlock(&docg3->cascade->lock); | 1686 | mutex_unlock(&docg3->cascade->lock); |
1687 | 1687 | ||
1688 | pos += seq_printf(s, | 1688 | seq_printf(s, |
1689 | "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (", | 1689 | "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (", |
1690 | pctrl, | 1690 | pctrl, |
1691 | pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0, | 1691 | pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0, |
1692 | pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0, | 1692 | pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0, |
1693 | pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0, | 1693 | pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0, |
1694 | pctrl & DOC_ASICMODE_MDWREN ? 1 : 0, | 1694 | pctrl & DOC_ASICMODE_MDWREN ? 1 : 0, |
1695 | pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0, | 1695 | pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0, |
1696 | mode >> 1, mode & 0x1); | 1696 | mode >> 1, mode & 0x1); |
1697 | 1697 | ||
1698 | switch (mode) { | 1698 | switch (mode) { |
1699 | case DOC_ASICMODE_RESET: | 1699 | case DOC_ASICMODE_RESET: |
1700 | pos += seq_puts(s, "reset"); | 1700 | seq_puts(s, "reset"); |
1701 | break; | 1701 | break; |
1702 | case DOC_ASICMODE_NORMAL: | 1702 | case DOC_ASICMODE_NORMAL: |
1703 | pos += seq_puts(s, "normal"); | 1703 | seq_puts(s, "normal"); |
1704 | break; | 1704 | break; |
1705 | case DOC_ASICMODE_POWERDOWN: | 1705 | case DOC_ASICMODE_POWERDOWN: |
1706 | pos += seq_puts(s, "powerdown"); | 1706 | seq_puts(s, "powerdown"); |
1707 | break; | 1707 | break; |
1708 | } | 1708 | } |
1709 | pos += seq_puts(s, ")\n"); | 1709 | seq_puts(s, ")\n"); |
1710 | return pos; | 1710 | return 0; |
1711 | } | 1711 | } |
1712 | DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show); | 1712 | DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show); |
1713 | 1713 | ||
1714 | static int dbg_device_id_show(struct seq_file *s, void *p) | 1714 | static int dbg_device_id_show(struct seq_file *s, void *p) |
1715 | { | 1715 | { |
1716 | struct docg3 *docg3 = (struct docg3 *)s->private; | 1716 | struct docg3 *docg3 = (struct docg3 *)s->private; |
1717 | int pos = 0; | ||
1718 | int id; | 1717 | int id; |
1719 | 1718 | ||
1720 | mutex_lock(&docg3->cascade->lock); | 1719 | mutex_lock(&docg3->cascade->lock); |
1721 | id = doc_register_readb(docg3, DOC_DEVICESELECT); | 1720 | id = doc_register_readb(docg3, DOC_DEVICESELECT); |
1722 | mutex_unlock(&docg3->cascade->lock); | 1721 | mutex_unlock(&docg3->cascade->lock); |
1723 | 1722 | ||
1724 | pos += seq_printf(s, "DeviceId = %d\n", id); | 1723 | seq_printf(s, "DeviceId = %d\n", id); |
1725 | return pos; | 1724 | return 0; |
1726 | } | 1725 | } |
1727 | DEBUGFS_RO_ATTR(device_id, dbg_device_id_show); | 1726 | DEBUGFS_RO_ATTR(device_id, dbg_device_id_show); |
1728 | 1727 | ||
1729 | static int dbg_protection_show(struct seq_file *s, void *p) | 1728 | static int dbg_protection_show(struct seq_file *s, void *p) |
1730 | { | 1729 | { |
1731 | struct docg3 *docg3 = (struct docg3 *)s->private; | 1730 | struct docg3 *docg3 = (struct docg3 *)s->private; |
1732 | int pos = 0; | ||
1733 | int protect, dps0, dps0_low, dps0_high, dps1, dps1_low, dps1_high; | 1731 | int protect, dps0, dps0_low, dps0_high, dps1, dps1_low, dps1_high; |
1734 | 1732 | ||
1735 | mutex_lock(&docg3->cascade->lock); | 1733 | mutex_lock(&docg3->cascade->lock); |
@@ -1742,45 +1740,40 @@ static int dbg_protection_show(struct seq_file *s, void *p) | |||
1742 | dps1_high = doc_register_readw(docg3, DOC_DPS1_ADDRHIGH); | 1740 | dps1_high = doc_register_readw(docg3, DOC_DPS1_ADDRHIGH); |
1743 | mutex_unlock(&docg3->cascade->lock); | 1741 | mutex_unlock(&docg3->cascade->lock); |
1744 | 1742 | ||
1745 | pos += seq_printf(s, "Protection = 0x%02x (", | 1743 | seq_printf(s, "Protection = 0x%02x (", protect); |
1746 | protect); | ||
1747 | if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK) | 1744 | if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK) |
1748 | pos += seq_puts(s, "FOUNDRY_OTP_LOCK,"); | 1745 | seq_puts(s, "FOUNDRY_OTP_LOCK,"); |
1749 | if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK) | 1746 | if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK) |
1750 | pos += seq_puts(s, "CUSTOMER_OTP_LOCK,"); | 1747 | seq_puts(s, "CUSTOMER_OTP_LOCK,"); |
1751 | if (protect & DOC_PROTECT_LOCK_INPUT) | 1748 | if (protect & DOC_PROTECT_LOCK_INPUT) |
1752 | pos += seq_puts(s, "LOCK_INPUT,"); | 1749 | seq_puts(s, "LOCK_INPUT,"); |
1753 | if (protect & DOC_PROTECT_STICKY_LOCK) | 1750 | if (protect & DOC_PROTECT_STICKY_LOCK) |
1754 | pos += seq_puts(s, "STICKY_LOCK,"); | 1751 | seq_puts(s, "STICKY_LOCK,"); |
1755 | if (protect & DOC_PROTECT_PROTECTION_ENABLED) | 1752 | if (protect & DOC_PROTECT_PROTECTION_ENABLED) |
1756 | pos += seq_puts(s, "PROTECTION ON,"); | 1753 | seq_puts(s, "PROTECTION ON,"); |
1757 | if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK) | 1754 | if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK) |
1758 | pos += seq_puts(s, "IPL_DOWNLOAD_LOCK,"); | 1755 | seq_puts(s, "IPL_DOWNLOAD_LOCK,"); |
1759 | if (protect & DOC_PROTECT_PROTECTION_ERROR) | 1756 | if (protect & DOC_PROTECT_PROTECTION_ERROR) |
1760 | pos += seq_puts(s, "PROTECT_ERR,"); | 1757 | seq_puts(s, "PROTECT_ERR,"); |
1761 | else | 1758 | else |
1762 | pos += seq_puts(s, "NO_PROTECT_ERR"); | 1759 | seq_puts(s, "NO_PROTECT_ERR"); |
1763 | pos += seq_puts(s, ")\n"); | 1760 | seq_puts(s, ")\n"); |
1764 | 1761 | ||
1765 | pos += seq_printf(s, "DPS0 = 0x%02x : " | 1762 | seq_printf(s, "DPS0 = 0x%02x : Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", |
1766 | "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, " | 1763 | dps0, dps0_low, dps0_high, |
1767 | "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", | 1764 | !!(dps0 & DOC_DPS_OTP_PROTECTED), |
1768 | dps0, dps0_low, dps0_high, | 1765 | !!(dps0 & DOC_DPS_READ_PROTECTED), |
1769 | !!(dps0 & DOC_DPS_OTP_PROTECTED), | 1766 | !!(dps0 & DOC_DPS_WRITE_PROTECTED), |
1770 | !!(dps0 & DOC_DPS_READ_PROTECTED), | 1767 | !!(dps0 & DOC_DPS_HW_LOCK_ENABLED), |
1771 | !!(dps0 & DOC_DPS_WRITE_PROTECTED), | 1768 | !!(dps0 & DOC_DPS_KEY_OK)); |
1772 | !!(dps0 & DOC_DPS_HW_LOCK_ENABLED), | 1769 | seq_printf(s, "DPS1 = 0x%02x : Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", |
1773 | !!(dps0 & DOC_DPS_KEY_OK)); | 1770 | dps1, dps1_low, dps1_high, |
1774 | pos += seq_printf(s, "DPS1 = 0x%02x : " | 1771 | !!(dps1 & DOC_DPS_OTP_PROTECTED), |
1775 | "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, " | 1772 | !!(dps1 & DOC_DPS_READ_PROTECTED), |
1776 | "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", | 1773 | !!(dps1 & DOC_DPS_WRITE_PROTECTED), |
1777 | dps1, dps1_low, dps1_high, | 1774 | !!(dps1 & DOC_DPS_HW_LOCK_ENABLED), |
1778 | !!(dps1 & DOC_DPS_OTP_PROTECTED), | 1775 | !!(dps1 & DOC_DPS_KEY_OK)); |
1779 | !!(dps1 & DOC_DPS_READ_PROTECTED), | 1776 | return 0; |
1780 | !!(dps1 & DOC_DPS_WRITE_PROTECTED), | ||
1781 | !!(dps1 & DOC_DPS_HW_LOCK_ENABLED), | ||
1782 | !!(dps1 & DOC_DPS_KEY_OK)); | ||
1783 | return pos; | ||
1784 | } | 1777 | } |
1785 | DEBUGFS_RO_ATTR(protection, dbg_protection_show); | 1778 | DEBUGFS_RO_ATTR(protection, dbg_protection_show); |
1786 | 1779 | ||
@@ -2126,9 +2119,18 @@ static int __exit docg3_release(struct platform_device *pdev) | |||
2126 | return 0; | 2119 | return 0; |
2127 | } | 2120 | } |
2128 | 2121 | ||
2122 | #ifdef CONFIG_OF | ||
2123 | static struct of_device_id docg3_dt_ids[] = { | ||
2124 | { .compatible = "m-systems,diskonchip-g3" }, | ||
2125 | {} | ||
2126 | }; | ||
2127 | MODULE_DEVICE_TABLE(of, docg3_dt_ids); | ||
2128 | #endif | ||
2129 | |||
2129 | static struct platform_driver g3_driver = { | 2130 | static struct platform_driver g3_driver = { |
2130 | .driver = { | 2131 | .driver = { |
2131 | .name = "docg3", | 2132 | .name = "docg3", |
2133 | .of_match_table = of_match_ptr(docg3_dt_ids), | ||
2132 | }, | 2134 | }, |
2133 | .suspend = docg3_suspend, | 2135 | .suspend = docg3_suspend, |
2134 | .resume = docg3_resume, | 2136 | .resume = docg3_resume, |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index ed827cf894e4..85e35467fba6 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -128,13 +128,10 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, | |||
128 | struct spi_device *spi = flash->spi; | 128 | struct spi_device *spi = flash->spi; |
129 | struct spi_transfer t[2]; | 129 | struct spi_transfer t[2]; |
130 | struct spi_message m; | 130 | struct spi_message m; |
131 | int dummy = nor->read_dummy; | 131 | unsigned int dummy = nor->read_dummy; |
132 | int ret; | ||
133 | 132 | ||
134 | /* Wait till previous write/erase is done. */ | 133 | /* convert the dummy cycles to the number of bytes */ |
135 | ret = nor->wait_till_ready(nor); | 134 | dummy /= 8; |
136 | if (ret) | ||
137 | return ret; | ||
138 | 135 | ||
139 | spi_message_init(&m); | 136 | spi_message_init(&m); |
140 | memset(t, 0, (sizeof t)); | 137 | memset(t, 0, (sizeof t)); |
@@ -160,21 +157,10 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, | |||
160 | static int m25p80_erase(struct spi_nor *nor, loff_t offset) | 157 | static int m25p80_erase(struct spi_nor *nor, loff_t offset) |
161 | { | 158 | { |
162 | struct m25p *flash = nor->priv; | 159 | struct m25p *flash = nor->priv; |
163 | int ret; | ||
164 | 160 | ||
165 | dev_dbg(nor->dev, "%dKiB at 0x%08x\n", | 161 | dev_dbg(nor->dev, "%dKiB at 0x%08x\n", |
166 | flash->mtd.erasesize / 1024, (u32)offset); | 162 | flash->mtd.erasesize / 1024, (u32)offset); |
167 | 163 | ||
168 | /* Wait until finished previous write command. */ | ||
169 | ret = nor->wait_till_ready(nor); | ||
170 | if (ret) | ||
171 | return ret; | ||
172 | |||
173 | /* Send write enable, then erase commands. */ | ||
174 | ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); | ||
175 | if (ret) | ||
176 | return ret; | ||
177 | |||
178 | /* Set up command buffer. */ | 164 | /* Set up command buffer. */ |
179 | flash->command[0] = nor->erase_opcode; | 165 | flash->command[0] = nor->erase_opcode; |
180 | m25p_addr2cmd(nor, offset, flash->command); | 166 | m25p_addr2cmd(nor, offset, flash->command); |
@@ -260,7 +246,6 @@ static int m25p_remove(struct spi_device *spi) | |||
260 | return mtd_device_unregister(&flash->mtd); | 246 | return mtd_device_unregister(&flash->mtd); |
261 | } | 247 | } |
262 | 248 | ||
263 | |||
264 | /* | 249 | /* |
265 | * XXX This needs to be kept in sync with spi_nor_ids. We can't share | 250 | * XXX This needs to be kept in sync with spi_nor_ids. We can't share |
266 | * it with spi-nor, because if this is built as a module then modpost | 251 | * it with spi-nor, because if this is built as a module then modpost |
@@ -287,7 +272,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
287 | {"s25fl512s"}, {"s70fl01gs"}, {"s25sl12800"}, {"s25sl12801"}, | 272 | {"s25fl512s"}, {"s70fl01gs"}, {"s25sl12800"}, {"s25sl12801"}, |
288 | {"s25fl129p0"}, {"s25fl129p1"}, {"s25sl004a"}, {"s25sl008a"}, | 273 | {"s25fl129p0"}, {"s25fl129p1"}, {"s25sl004a"}, {"s25sl008a"}, |
289 | {"s25sl016a"}, {"s25sl032a"}, {"s25sl064a"}, {"s25fl008k"}, | 274 | {"s25sl016a"}, {"s25sl032a"}, {"s25sl064a"}, {"s25fl008k"}, |
290 | {"s25fl016k"}, {"s25fl064k"}, | 275 | {"s25fl016k"}, {"s25fl064k"}, {"s25fl132k"}, |
291 | {"sst25vf040b"},{"sst25vf080b"},{"sst25vf016b"},{"sst25vf032b"}, | 276 | {"sst25vf040b"},{"sst25vf080b"},{"sst25vf016b"},{"sst25vf032b"}, |
292 | {"sst25vf064c"},{"sst25wf512"}, {"sst25wf010"}, {"sst25wf020"}, | 277 | {"sst25vf064c"},{"sst25wf512"}, {"sst25wf010"}, {"sst25wf020"}, |
293 | {"sst25wf040"}, | 278 | {"sst25wf040"}, |
@@ -300,17 +285,16 @@ static const struct spi_device_id m25p_ids[] = { | |||
300 | {"m45pe10"}, {"m45pe80"}, {"m45pe16"}, | 285 | {"m45pe10"}, {"m45pe80"}, {"m45pe16"}, |
301 | {"m25pe20"}, {"m25pe80"}, {"m25pe16"}, | 286 | {"m25pe20"}, {"m25pe80"}, {"m25pe16"}, |
302 | {"m25px16"}, {"m25px32"}, {"m25px32-s0"}, {"m25px32-s1"}, | 287 | {"m25px16"}, {"m25px32"}, {"m25px32-s0"}, {"m25px32-s1"}, |
303 | {"m25px64"}, | 288 | {"m25px64"}, {"m25px80"}, |
304 | {"w25x10"}, {"w25x20"}, {"w25x40"}, {"w25x80"}, | 289 | {"w25x10"}, {"w25x20"}, {"w25x40"}, {"w25x80"}, |
305 | {"w25x16"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, | 290 | {"w25x16"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, |
306 | {"w25x64"}, {"w25q64"}, {"w25q128"}, {"w25q80"}, | 291 | {"w25x64"}, {"w25q64"}, {"w25q80"}, {"w25q80bl"}, |
307 | {"w25q80bl"}, {"w25q128"}, {"w25q256"}, {"cat25c11"}, | 292 | {"w25q128"}, {"w25q256"}, {"cat25c11"}, |
308 | {"cat25c03"}, {"cat25c09"}, {"cat25c17"}, {"cat25128"}, | 293 | {"cat25c03"}, {"cat25c09"}, {"cat25c17"}, {"cat25128"}, |
309 | { }, | 294 | { }, |
310 | }; | 295 | }; |
311 | MODULE_DEVICE_TABLE(spi, m25p_ids); | 296 | MODULE_DEVICE_TABLE(spi, m25p_ids); |
312 | 297 | ||
313 | |||
314 | static struct spi_driver m25p80_driver = { | 298 | static struct spi_driver m25p80_driver = { |
315 | .driver = { | 299 | .driver = { |
316 | .name = "m25p80", | 300 | .name = "m25p80", |
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index dd22ce2cc9ad..0099aba72a8b 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -149,7 +149,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
149 | { | 149 | { |
150 | struct dataflash *priv = mtd->priv; | 150 | struct dataflash *priv = mtd->priv; |
151 | struct spi_device *spi = priv->spi; | 151 | struct spi_device *spi = priv->spi; |
152 | struct spi_transfer x = { .tx_dma = 0, }; | 152 | struct spi_transfer x = { }; |
153 | struct spi_message msg; | 153 | struct spi_message msg; |
154 | unsigned blocksize = priv->page_size << 3; | 154 | unsigned blocksize = priv->page_size << 3; |
155 | uint8_t *command; | 155 | uint8_t *command; |
@@ -235,7 +235,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
235 | size_t *retlen, u_char *buf) | 235 | size_t *retlen, u_char *buf) |
236 | { | 236 | { |
237 | struct dataflash *priv = mtd->priv; | 237 | struct dataflash *priv = mtd->priv; |
238 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | 238 | struct spi_transfer x[2] = { }; |
239 | struct spi_message msg; | 239 | struct spi_message msg; |
240 | unsigned int addr; | 240 | unsigned int addr; |
241 | uint8_t *command; | 241 | uint8_t *command; |
@@ -301,7 +301,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
301 | { | 301 | { |
302 | struct dataflash *priv = mtd->priv; | 302 | struct dataflash *priv = mtd->priv; |
303 | struct spi_device *spi = priv->spi; | 303 | struct spi_device *spi = priv->spi; |
304 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | 304 | struct spi_transfer x[2] = { }; |
305 | struct spi_message msg; | 305 | struct spi_message msg; |
306 | unsigned int pageaddr, addr, offset, writelen; | 306 | unsigned int pageaddr, addr, offset, writelen; |
307 | size_t remaining = len; | 307 | size_t remaining = len; |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index effd9a4ef7ee..8b66e52ca3cc 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
19 | 19 | ||
20 | #include <asm/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index f02603e1bfeb..708b7e8c8b18 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
@@ -812,8 +812,7 @@ static int __init init_pmc551(void) | |||
812 | } | 812 | } |
813 | 813 | ||
814 | /* Exited early, reference left over */ | 814 | /* Exited early, reference left over */ |
815 | if (PCI_Device) | 815 | pci_dev_put(PCI_Device); |
816 | pci_dev_put(PCI_Device); | ||
817 | 816 | ||
818 | if (!pmc551list) { | 817 | if (!pmc551list) { |
819 | printk(KERN_NOTICE "pmc551: not detected\n"); | 818 | printk(KERN_NOTICE "pmc551: not detected\n"); |
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 487e64f411a5..1388c8d7f309 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c | |||
@@ -518,7 +518,7 @@ void INFTL_dumpVUchains(struct INFTLrecord *s) | |||
518 | pr_debug("INFTL Virtual Unit Chains:\n"); | 518 | pr_debug("INFTL Virtual Unit Chains:\n"); |
519 | for (logical = 0; logical < s->nb_blocks; logical++) { | 519 | for (logical = 0; logical < s->nb_blocks; logical++) { |
520 | block = s->VUtable[logical]; | 520 | block = s->VUtable[logical]; |
521 | if (block > s->nb_blocks) | 521 | if (block >= s->nb_blocks) |
522 | continue; | 522 | continue; |
523 | pr_debug(" LOGICAL %d --> %d ", logical, block); | 523 | pr_debug(" LOGICAL %d --> %d ", logical, block); |
524 | for (i = 0; i < s->nb_blocks; i++) { | 524 | for (i = 0; i < s->nb_blocks; i++) { |
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index 6ea51e549045..41730feeace8 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c | |||
@@ -126,7 +126,6 @@ static const char * const part_probe_types[] = { | |||
126 | 126 | ||
127 | static int bfin_flash_probe(struct platform_device *pdev) | 127 | static int bfin_flash_probe(struct platform_device *pdev) |
128 | { | 128 | { |
129 | int ret; | ||
130 | struct physmap_flash_data *pdata = dev_get_platdata(&pdev->dev); | 129 | struct physmap_flash_data *pdata = dev_get_platdata(&pdev->dev); |
131 | struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 130 | struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
132 | struct resource *flash_ambctl = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 131 | struct resource *flash_ambctl = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 991d0cb871f0..f35cd2081314 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -47,14 +47,12 @@ static int of_flash_remove(struct platform_device *dev) | |||
47 | return 0; | 47 | return 0; |
48 | dev_set_drvdata(&dev->dev, NULL); | 48 | dev_set_drvdata(&dev->dev, NULL); |
49 | 49 | ||
50 | if (info->cmtd != info->list[0].mtd) { | 50 | if (info->cmtd) { |
51 | mtd_device_unregister(info->cmtd); | 51 | mtd_device_unregister(info->cmtd); |
52 | mtd_concat_destroy(info->cmtd); | 52 | if (info->cmtd != info->list[0].mtd) |
53 | mtd_concat_destroy(info->cmtd); | ||
53 | } | 54 | } |
54 | 55 | ||
55 | if (info->cmtd) | ||
56 | mtd_device_unregister(info->cmtd); | ||
57 | |||
58 | for (i = 0; i < info->list_size; i++) { | 56 | for (i = 0; i < info->list_size; i++) { |
59 | if (info->list[i].mtd) | 57 | if (info->list[i].mtd) |
60 | map_destroy(info->list[i].mtd); | 58 | map_destroy(info->list[i].mtd); |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index dd10646982ae..7d0150d20432 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -75,10 +75,12 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR | |||
75 | boards, the scratch register is at 0xFF108018. | 75 | boards, the scratch register is at 0xFF108018. |
76 | 76 | ||
77 | config MTD_NAND_GPIO | 77 | config MTD_NAND_GPIO |
78 | tristate "GPIO NAND Flash driver" | 78 | tristate "GPIO assisted NAND Flash driver" |
79 | depends on GPIOLIB | 79 | depends on GPIOLIB |
80 | help | 80 | help |
81 | This enables a GPIO based NAND flash driver. | 81 | This enables a NAND flash driver where control signals are |
82 | connected to GPIO pins, and commands and data are communicated | ||
83 | via a memory mapped interface. | ||
82 | 84 | ||
83 | config MTD_NAND_AMS_DELTA | 85 | config MTD_NAND_AMS_DELTA |
84 | tristate "NAND Flash device on Amstrad E3" | 86 | tristate "NAND Flash device on Amstrad E3" |
@@ -516,4 +518,10 @@ config MTD_NAND_XWAY | |||
516 | Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached | 518 | Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached |
517 | to the External Bus Unit (EBU). | 519 | to the External Bus Unit (EBU). |
518 | 520 | ||
521 | config MTD_NAND_SUNXI | ||
522 | tristate "Support for NAND on Allwinner SoCs" | ||
523 | depends on ARCH_SUNXI | ||
524 | help | ||
525 | Enables support for NAND Flash chips on Allwinner SoCs. | ||
526 | |||
519 | endif # MTD_NAND | 527 | endif # MTD_NAND |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 9c847e469ca7..bd38f21d2e28 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -50,5 +50,6 @@ obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o | |||
50 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ | 50 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ |
51 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o | 51 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o |
52 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ | 52 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ |
53 | obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o | ||
53 | 54 | ||
54 | nand-objs := nand_base.o nand_bbt.o nand_timings.o | 55 | nand-objs := nand_base.o nand_bbt.o nand_timings.o |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 84c38f3c65b0..a345e7b2463a 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -92,7 +92,7 @@ static struct nand_ecclayout atmel_oobinfo_small = { | |||
92 | struct atmel_nfc { | 92 | struct atmel_nfc { |
93 | void __iomem *base_cmd_regs; | 93 | void __iomem *base_cmd_regs; |
94 | void __iomem *hsmc_regs; | 94 | void __iomem *hsmc_regs; |
95 | void __iomem *sram_bank0; | 95 | void *sram_bank0; |
96 | dma_addr_t sram_bank0_phys; | 96 | dma_addr_t sram_bank0_phys; |
97 | bool use_nfc_sram; | 97 | bool use_nfc_sram; |
98 | bool write_by_sram; | 98 | bool write_by_sram; |
@@ -105,7 +105,7 @@ struct atmel_nfc { | |||
105 | struct completion comp_xfer_done; | 105 | struct completion comp_xfer_done; |
106 | 106 | ||
107 | /* Point to the sram bank which include readed data via NFC */ | 107 | /* Point to the sram bank which include readed data via NFC */ |
108 | void __iomem *data_in_sram; | 108 | void *data_in_sram; |
109 | bool will_write_sram; | 109 | bool will_write_sram; |
110 | }; | 110 | }; |
111 | static struct atmel_nfc nand_nfc; | 111 | static struct atmel_nfc nand_nfc; |
@@ -127,6 +127,7 @@ struct atmel_nand_host { | |||
127 | bool has_pmecc; | 127 | bool has_pmecc; |
128 | u8 pmecc_corr_cap; | 128 | u8 pmecc_corr_cap; |
129 | u16 pmecc_sector_size; | 129 | u16 pmecc_sector_size; |
130 | bool has_no_lookup_table; | ||
130 | u32 pmecc_lookup_table_offset; | 131 | u32 pmecc_lookup_table_offset; |
131 | u32 pmecc_lookup_table_offset_512; | 132 | u32 pmecc_lookup_table_offset_512; |
132 | u32 pmecc_lookup_table_offset_1024; | 133 | u32 pmecc_lookup_table_offset_1024; |
@@ -256,26 +257,6 @@ static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd) | |||
256 | return res; | 257 | return res; |
257 | } | 258 | } |
258 | 259 | ||
259 | static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) | ||
260 | { | ||
261 | int i; | ||
262 | u32 *t = trg; | ||
263 | const __iomem u32 *s = src; | ||
264 | |||
265 | for (i = 0; i < (size >> 2); i++) | ||
266 | *t++ = readl_relaxed(s++); | ||
267 | } | ||
268 | |||
269 | static void memcpy32_toio(void __iomem *trg, const void *src, int size) | ||
270 | { | ||
271 | int i; | ||
272 | u32 __iomem *t = trg; | ||
273 | const u32 *s = src; | ||
274 | |||
275 | for (i = 0; i < (size >> 2); i++) | ||
276 | writel_relaxed(*s++, t++); | ||
277 | } | ||
278 | |||
279 | /* | 260 | /* |
280 | * Minimal-overhead PIO for data access. | 261 | * Minimal-overhead PIO for data access. |
281 | */ | 262 | */ |
@@ -285,7 +266,7 @@ static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) | |||
285 | struct atmel_nand_host *host = nand_chip->priv; | 266 | struct atmel_nand_host *host = nand_chip->priv; |
286 | 267 | ||
287 | if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { | 268 | if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { |
288 | memcpy32_fromio(buf, host->nfc->data_in_sram, len); | 269 | memcpy(buf, host->nfc->data_in_sram, len); |
289 | host->nfc->data_in_sram += len; | 270 | host->nfc->data_in_sram += len; |
290 | } else { | 271 | } else { |
291 | __raw_readsb(nand_chip->IO_ADDR_R, buf, len); | 272 | __raw_readsb(nand_chip->IO_ADDR_R, buf, len); |
@@ -298,7 +279,7 @@ static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) | |||
298 | struct atmel_nand_host *host = nand_chip->priv; | 279 | struct atmel_nand_host *host = nand_chip->priv; |
299 | 280 | ||
300 | if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { | 281 | if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { |
301 | memcpy32_fromio(buf, host->nfc->data_in_sram, len); | 282 | memcpy(buf, host->nfc->data_in_sram, len); |
302 | host->nfc->data_in_sram += len; | 283 | host->nfc->data_in_sram += len; |
303 | } else { | 284 | } else { |
304 | __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); | 285 | __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); |
@@ -1112,12 +1093,66 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host, | |||
1112 | return 0; | 1093 | return 0; |
1113 | } | 1094 | } |
1114 | 1095 | ||
1096 | static inline int deg(unsigned int poly) | ||
1097 | { | ||
1098 | /* polynomial degree is the most-significant bit index */ | ||
1099 | return fls(poly) - 1; | ||
1100 | } | ||
1101 | |||
1102 | static int build_gf_tables(int mm, unsigned int poly, | ||
1103 | int16_t *index_of, int16_t *alpha_to) | ||
1104 | { | ||
1105 | unsigned int i, x = 1; | ||
1106 | const unsigned int k = 1 << deg(poly); | ||
1107 | unsigned int nn = (1 << mm) - 1; | ||
1108 | |||
1109 | /* primitive polynomial must be of degree m */ | ||
1110 | if (k != (1u << mm)) | ||
1111 | return -EINVAL; | ||
1112 | |||
1113 | for (i = 0; i < nn; i++) { | ||
1114 | alpha_to[i] = x; | ||
1115 | index_of[x] = i; | ||
1116 | if (i && (x == 1)) | ||
1117 | /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */ | ||
1118 | return -EINVAL; | ||
1119 | x <<= 1; | ||
1120 | if (x & k) | ||
1121 | x ^= poly; | ||
1122 | } | ||
1123 | alpha_to[nn] = 1; | ||
1124 | index_of[0] = 0; | ||
1125 | |||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | static uint16_t *create_lookup_table(struct device *dev, int sector_size) | ||
1130 | { | ||
1131 | int degree = (sector_size == 512) ? | ||
1132 | PMECC_GF_DIMENSION_13 : | ||
1133 | PMECC_GF_DIMENSION_14; | ||
1134 | unsigned int poly = (sector_size == 512) ? | ||
1135 | PMECC_GF_13_PRIMITIVE_POLY : | ||
1136 | PMECC_GF_14_PRIMITIVE_POLY; | ||
1137 | int table_size = (sector_size == 512) ? | ||
1138 | PMECC_LOOKUP_TABLE_SIZE_512 : | ||
1139 | PMECC_LOOKUP_TABLE_SIZE_1024; | ||
1140 | |||
1141 | int16_t *addr = devm_kzalloc(dev, 2 * table_size * sizeof(uint16_t), | ||
1142 | GFP_KERNEL); | ||
1143 | if (addr && build_gf_tables(degree, poly, addr, addr + table_size)) | ||
1144 | return NULL; | ||
1145 | |||
1146 | return addr; | ||
1147 | } | ||
1148 | |||
1115 | static int atmel_pmecc_nand_init_params(struct platform_device *pdev, | 1149 | static int atmel_pmecc_nand_init_params(struct platform_device *pdev, |
1116 | struct atmel_nand_host *host) | 1150 | struct atmel_nand_host *host) |
1117 | { | 1151 | { |
1118 | struct mtd_info *mtd = &host->mtd; | 1152 | struct mtd_info *mtd = &host->mtd; |
1119 | struct nand_chip *nand_chip = &host->nand_chip; | 1153 | struct nand_chip *nand_chip = &host->nand_chip; |
1120 | struct resource *regs, *regs_pmerr, *regs_rom; | 1154 | struct resource *regs, *regs_pmerr, *regs_rom; |
1155 | uint16_t *galois_table; | ||
1121 | int cap, sector_size, err_no; | 1156 | int cap, sector_size, err_no; |
1122 | 1157 | ||
1123 | err_no = pmecc_choose_ecc(host, &cap, §or_size); | 1158 | err_no = pmecc_choose_ecc(host, &cap, §or_size); |
@@ -1163,8 +1198,24 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1163 | regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); | 1198 | regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); |
1164 | host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev, regs_rom); | 1199 | host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev, regs_rom); |
1165 | if (IS_ERR(host->pmecc_rom_base)) { | 1200 | if (IS_ERR(host->pmecc_rom_base)) { |
1166 | err_no = PTR_ERR(host->pmecc_rom_base); | 1201 | if (!host->has_no_lookup_table) |
1167 | goto err; | 1202 | /* Don't display the information again */ |
1203 | dev_err(host->dev, "Can not get I/O resource for ROM, will build a lookup table in runtime!\n"); | ||
1204 | |||
1205 | host->has_no_lookup_table = true; | ||
1206 | } | ||
1207 | |||
1208 | if (host->has_no_lookup_table) { | ||
1209 | /* Build the look-up table in runtime */ | ||
1210 | galois_table = create_lookup_table(host->dev, sector_size); | ||
1211 | if (!galois_table) { | ||
1212 | dev_err(host->dev, "Failed to build a lookup table in runtime!\n"); | ||
1213 | err_no = -EINVAL; | ||
1214 | goto err; | ||
1215 | } | ||
1216 | |||
1217 | host->pmecc_rom_base = (void __iomem *)galois_table; | ||
1218 | host->pmecc_lookup_table_offset = 0; | ||
1168 | } | 1219 | } |
1169 | 1220 | ||
1170 | nand_chip->ecc.size = sector_size; | 1221 | nand_chip->ecc.size = sector_size; |
@@ -1501,8 +1552,10 @@ static int atmel_of_init_port(struct atmel_nand_host *host, | |||
1501 | 1552 | ||
1502 | if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset", | 1553 | if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset", |
1503 | offset, 2) != 0) { | 1554 | offset, 2) != 0) { |
1504 | dev_err(host->dev, "Cannot get PMECC lookup table offset\n"); | 1555 | dev_err(host->dev, "Cannot get PMECC lookup table offset, will build a lookup table in runtime.\n"); |
1505 | return -EINVAL; | 1556 | host->has_no_lookup_table = true; |
1557 | /* Will build a lookup table and initialize the offset later */ | ||
1558 | return 0; | ||
1506 | } | 1559 | } |
1507 | if (!offset[0] && !offset[1]) { | 1560 | if (!offset[0] && !offset[1]) { |
1508 | dev_err(host->dev, "Invalid PMECC lookup table offset\n"); | 1561 | dev_err(host->dev, "Invalid PMECC lookup table offset\n"); |
@@ -1899,7 +1952,7 @@ static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1899 | int cfg, len; | 1952 | int cfg, len; |
1900 | int status = 0; | 1953 | int status = 0; |
1901 | struct atmel_nand_host *host = chip->priv; | 1954 | struct atmel_nand_host *host = chip->priv; |
1902 | void __iomem *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host); | 1955 | void *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host); |
1903 | 1956 | ||
1904 | /* Subpage write is not supported */ | 1957 | /* Subpage write is not supported */ |
1905 | if (offset || (data_len < mtd->writesize)) | 1958 | if (offset || (data_len < mtd->writesize)) |
@@ -1910,14 +1963,14 @@ static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1910 | if (use_dma) { | 1963 | if (use_dma) { |
1911 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0) | 1964 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0) |
1912 | /* Fall back to use cpu copy */ | 1965 | /* Fall back to use cpu copy */ |
1913 | memcpy32_toio(sram, buf, len); | 1966 | memcpy(sram, buf, len); |
1914 | } else { | 1967 | } else { |
1915 | memcpy32_toio(sram, buf, len); | 1968 | memcpy(sram, buf, len); |
1916 | } | 1969 | } |
1917 | 1970 | ||
1918 | cfg = nfc_readl(host->nfc->hsmc_regs, CFG); | 1971 | cfg = nfc_readl(host->nfc->hsmc_regs, CFG); |
1919 | if (unlikely(raw) && oob_required) { | 1972 | if (unlikely(raw) && oob_required) { |
1920 | memcpy32_toio(sram + len, chip->oob_poi, mtd->oobsize); | 1973 | memcpy(sram + len, chip->oob_poi, mtd->oobsize); |
1921 | len += mtd->oobsize; | 1974 | len += mtd->oobsize; |
1922 | nfc_writel(host->nfc->hsmc_regs, CFG, cfg | NFC_CFG_WSPARE); | 1975 | nfc_writel(host->nfc->hsmc_regs, CFG, cfg | NFC_CFG_WSPARE); |
1923 | } else { | 1976 | } else { |
@@ -2260,7 +2313,8 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev) | |||
2260 | 2313 | ||
2261 | nfc_sram = platform_get_resource(pdev, IORESOURCE_MEM, 2); | 2314 | nfc_sram = platform_get_resource(pdev, IORESOURCE_MEM, 2); |
2262 | if (nfc_sram) { | 2315 | if (nfc_sram) { |
2263 | nfc->sram_bank0 = devm_ioremap_resource(&pdev->dev, nfc_sram); | 2316 | nfc->sram_bank0 = (void * __force) |
2317 | devm_ioremap_resource(&pdev->dev, nfc_sram); | ||
2264 | if (IS_ERR(nfc->sram_bank0)) { | 2318 | if (IS_ERR(nfc->sram_bank0)) { |
2265 | dev_warn(&pdev->dev, "Fail to ioremap the NFC sram with error: %ld. So disable NFC sram.\n", | 2319 | dev_warn(&pdev->dev, "Fail to ioremap the NFC sram with error: %ld. So disable NFC sram.\n", |
2266 | PTR_ERR(nfc->sram_bank0)); | 2320 | PTR_ERR(nfc->sram_bank0)); |
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h index 8a1e9a686759..d4035e335ad8 100644 --- a/drivers/mtd/nand/atmel_nand_ecc.h +++ b/drivers/mtd/nand/atmel_nand_ecc.h | |||
@@ -142,6 +142,10 @@ | |||
142 | #define PMECC_GF_DIMENSION_13 13 | 142 | #define PMECC_GF_DIMENSION_13 13 |
143 | #define PMECC_GF_DIMENSION_14 14 | 143 | #define PMECC_GF_DIMENSION_14 14 |
144 | 144 | ||
145 | /* Primitive Polynomial used by PMECC */ | ||
146 | #define PMECC_GF_13_PRIMITIVE_POLY 0x201b | ||
147 | #define PMECC_GF_14_PRIMITIVE_POLY 0x4443 | ||
148 | |||
145 | #define PMECC_LOOKUP_TABLE_SIZE_512 0x2000 | 149 | #define PMECC_LOOKUP_TABLE_SIZE_512 0x2000 |
146 | #define PMECC_LOOKUP_TABLE_SIZE_1024 0x4000 | 150 | #define PMECC_LOOKUP_TABLE_SIZE_1024 0x4000 |
147 | 151 | ||
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 4e66726da9aa..9a0f45f1d932 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -529,50 +529,6 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd, | |||
529 | return 0; | 529 | return 0; |
530 | } | 530 | } |
531 | 531 | ||
532 | static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | ||
533 | uint32_t offset, int data_len, const uint8_t *buf, | ||
534 | int oob_required, int page, int cached, int raw) | ||
535 | { | ||
536 | int status; | ||
537 | |||
538 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | ||
539 | |||
540 | if (unlikely(raw)) | ||
541 | status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required); | ||
542 | else | ||
543 | status = chip->ecc.write_page(mtd, chip, buf, oob_required); | ||
544 | |||
545 | if (status < 0) | ||
546 | return status; | ||
547 | |||
548 | /* | ||
549 | * Cached progamming disabled for now, Not sure if its worth the | ||
550 | * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s) | ||
551 | */ | ||
552 | cached = 0; | ||
553 | |||
554 | if (!cached || !(chip->options & NAND_CACHEPRG)) { | ||
555 | |||
556 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
557 | status = chip->waitfunc(mtd, chip); | ||
558 | /* | ||
559 | * See if operation failed and additional status checks are | ||
560 | * available | ||
561 | */ | ||
562 | if ((status & NAND_STATUS_FAIL) && (chip->errstat)) | ||
563 | status = chip->errstat(mtd, chip, FL_WRITING, status, | ||
564 | page); | ||
565 | |||
566 | if (status & NAND_STATUS_FAIL) | ||
567 | return -EIO; | ||
568 | } else { | ||
569 | chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1); | ||
570 | status = chip->waitfunc(mtd, chip); | ||
571 | } | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | 532 | static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) |
577 | { | 533 | { |
578 | return 0; | 534 | return 0; |
@@ -800,7 +756,6 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
800 | cafe->nand.ecc.hwctl = (void *)cafe_nand_bug; | 756 | cafe->nand.ecc.hwctl = (void *)cafe_nand_bug; |
801 | cafe->nand.ecc.calculate = (void *)cafe_nand_bug; | 757 | cafe->nand.ecc.calculate = (void *)cafe_nand_bug; |
802 | cafe->nand.ecc.correct = (void *)cafe_nand_bug; | 758 | cafe->nand.ecc.correct = (void *)cafe_nand_bug; |
803 | cafe->nand.write_page = cafe_nand_write_page; | ||
804 | cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel; | 759 | cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel; |
805 | cafe->nand.ecc.write_oob = cafe_nand_write_oob; | 760 | cafe->nand.ecc.write_oob = cafe_nand_write_oob; |
806 | cafe->nand.ecc.read_page = cafe_nand_read_page; | 761 | cafe->nand.ecc.read_page = cafe_nand_read_page; |
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index b9ef7a6bba42..4c05f4f6a5c6 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/mtd/nand_ecc.h> | 31 | #include <linux/mtd/nand_ecc.h> |
32 | #include <linux/fsl_ifc.h> | 32 | #include <linux/fsl_ifc.h> |
33 | 33 | ||
34 | #define FSL_IFC_V1_1_0 0x01010000 | ||
35 | #define ERR_BYTE 0xFF /* Value returned for read | 34 | #define ERR_BYTE 0xFF /* Value returned for read |
36 | bytes when read failed */ | 35 | bytes when read failed */ |
37 | #define IFC_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait | 36 | #define IFC_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait |
@@ -877,7 +876,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
877 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; | 876 | struct fsl_ifc_regs __iomem *ifc = ctrl->regs; |
878 | struct nand_chip *chip = &priv->chip; | 877 | struct nand_chip *chip = &priv->chip; |
879 | struct nand_ecclayout *layout; | 878 | struct nand_ecclayout *layout; |
880 | u32 csor, ver; | 879 | u32 csor; |
881 | 880 | ||
882 | /* Fill in fsl_ifc_mtd structure */ | 881 | /* Fill in fsl_ifc_mtd structure */ |
883 | priv->mtd.priv = chip; | 882 | priv->mtd.priv = chip; |
@@ -984,8 +983,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
984 | chip->ecc.mode = NAND_ECC_SOFT; | 983 | chip->ecc.mode = NAND_ECC_SOFT; |
985 | } | 984 | } |
986 | 985 | ||
987 | ver = ioread32be(&ifc->ifc_rev); | 986 | if (ctrl->version == FSL_IFC_VERSION_1_1_0) |
988 | if (ver == FSL_IFC_V1_1_0) | ||
989 | fsl_ifc_sram_init(priv); | 987 | fsl_ifc_sram_init(priv); |
990 | 988 | ||
991 | return 0; | 989 | return 0; |
@@ -1045,12 +1043,12 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) | |||
1045 | } | 1043 | } |
1046 | 1044 | ||
1047 | /* find which chip select it is connected to */ | 1045 | /* find which chip select it is connected to */ |
1048 | for (bank = 0; bank < FSL_IFC_BANK_COUNT; bank++) { | 1046 | for (bank = 0; bank < fsl_ifc_ctrl_dev->banks; bank++) { |
1049 | if (match_bank(ifc, bank, res.start)) | 1047 | if (match_bank(ifc, bank, res.start)) |
1050 | break; | 1048 | break; |
1051 | } | 1049 | } |
1052 | 1050 | ||
1053 | if (bank >= FSL_IFC_BANK_COUNT) { | 1051 | if (bank >= fsl_ifc_ctrl_dev->banks) { |
1054 | dev_err(&dev->dev, "%s: address did not match any chip selects\n", | 1052 | dev_err(&dev->dev, "%s: address did not match any chip selects\n", |
1055 | __func__); | 1053 | __func__); |
1056 | return -ENODEV; | 1054 | return -ENODEV; |
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index 918283999a4b..73c4048c3a56 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c | |||
@@ -8,7 +8,9 @@ | |||
8 | * | 8 | * |
9 | * © 2004 Simtec Electronics | 9 | * © 2004 Simtec Electronics |
10 | * | 10 | * |
11 | * Device driver for NAND connected via GPIO | 11 | * Device driver for NAND flash that uses a memory mapped interface to |
12 | * read/write the NAND commands and data, and GPIO pins for control signals | ||
13 | * (the DT binding refers to this as "GPIO assisted NAND flash") | ||
12 | * | 14 | * |
13 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2 as | 16 | * it under the terms of the GNU General Public License version 2 as |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 87e658ce23ef..27f272ed502a 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c | |||
@@ -1353,3 +1353,156 @@ int gpmi_read_page(struct gpmi_nand_data *this, | |||
1353 | set_dma_type(this, DMA_FOR_READ_ECC_PAGE); | 1353 | set_dma_type(this, DMA_FOR_READ_ECC_PAGE); |
1354 | return start_dma_with_bch_irq(this, desc); | 1354 | return start_dma_with_bch_irq(this, desc); |
1355 | } | 1355 | } |
1356 | |||
1357 | /** | ||
1358 | * gpmi_copy_bits - copy bits from one memory region to another | ||
1359 | * @dst: destination buffer | ||
1360 | * @dst_bit_off: bit offset we're starting to write at | ||
1361 | * @src: source buffer | ||
1362 | * @src_bit_off: bit offset we're starting to read from | ||
1363 | * @nbits: number of bits to copy | ||
1364 | * | ||
1365 | * This functions copies bits from one memory region to another, and is used by | ||
1366 | * the GPMI driver to copy ECC sections which are not guaranteed to be byte | ||
1367 | * aligned. | ||
1368 | * | ||
1369 | * src and dst should not overlap. | ||
1370 | * | ||
1371 | */ | ||
1372 | void gpmi_copy_bits(u8 *dst, size_t dst_bit_off, | ||
1373 | const u8 *src, size_t src_bit_off, | ||
1374 | size_t nbits) | ||
1375 | { | ||
1376 | size_t i; | ||
1377 | size_t nbytes; | ||
1378 | u32 src_buffer = 0; | ||
1379 | size_t bits_in_src_buffer = 0; | ||
1380 | |||
1381 | if (!nbits) | ||
1382 | return; | ||
1383 | |||
1384 | /* | ||
1385 | * Move src and dst pointers to the closest byte pointer and store bit | ||
1386 | * offsets within a byte. | ||
1387 | */ | ||
1388 | src += src_bit_off / 8; | ||
1389 | src_bit_off %= 8; | ||
1390 | |||
1391 | dst += dst_bit_off / 8; | ||
1392 | dst_bit_off %= 8; | ||
1393 | |||
1394 | /* | ||
1395 | * Initialize the src_buffer value with bits available in the first | ||
1396 | * byte of data so that we end up with a byte aligned src pointer. | ||
1397 | */ | ||
1398 | if (src_bit_off) { | ||
1399 | src_buffer = src[0] >> src_bit_off; | ||
1400 | if (nbits >= (8 - src_bit_off)) { | ||
1401 | bits_in_src_buffer += 8 - src_bit_off; | ||
1402 | } else { | ||
1403 | src_buffer &= GENMASK(nbits - 1, 0); | ||
1404 | bits_in_src_buffer += nbits; | ||
1405 | } | ||
1406 | nbits -= bits_in_src_buffer; | ||
1407 | src++; | ||
1408 | } | ||
1409 | |||
1410 | /* Calculate the number of bytes that can be copied from src to dst. */ | ||
1411 | nbytes = nbits / 8; | ||
1412 | |||
1413 | /* Try to align dst to a byte boundary. */ | ||
1414 | if (dst_bit_off) { | ||
1415 | if (bits_in_src_buffer < (8 - dst_bit_off) && nbytes) { | ||
1416 | src_buffer |= src[0] << bits_in_src_buffer; | ||
1417 | bits_in_src_buffer += 8; | ||
1418 | src++; | ||
1419 | nbytes--; | ||
1420 | } | ||
1421 | |||
1422 | if (bits_in_src_buffer >= (8 - dst_bit_off)) { | ||
1423 | dst[0] &= GENMASK(dst_bit_off - 1, 0); | ||
1424 | dst[0] |= src_buffer << dst_bit_off; | ||
1425 | src_buffer >>= (8 - dst_bit_off); | ||
1426 | bits_in_src_buffer -= (8 - dst_bit_off); | ||
1427 | dst_bit_off = 0; | ||
1428 | dst++; | ||
1429 | if (bits_in_src_buffer > 7) { | ||
1430 | bits_in_src_buffer -= 8; | ||
1431 | dst[0] = src_buffer; | ||
1432 | dst++; | ||
1433 | src_buffer >>= 8; | ||
1434 | } | ||
1435 | } | ||
1436 | } | ||
1437 | |||
1438 | if (!bits_in_src_buffer && !dst_bit_off) { | ||
1439 | /* | ||
1440 | * Both src and dst pointers are byte aligned, thus we can | ||
1441 | * just use the optimized memcpy function. | ||
1442 | */ | ||
1443 | if (nbytes) | ||
1444 | memcpy(dst, src, nbytes); | ||
1445 | } else { | ||
1446 | /* | ||
1447 | * src buffer is not byte aligned, hence we have to copy each | ||
1448 | * src byte to the src_buffer variable before extracting a byte | ||
1449 | * to store in dst. | ||
1450 | */ | ||
1451 | for (i = 0; i < nbytes; i++) { | ||
1452 | src_buffer |= src[i] << bits_in_src_buffer; | ||
1453 | dst[i] = src_buffer; | ||
1454 | src_buffer >>= 8; | ||
1455 | } | ||
1456 | } | ||
1457 | /* Update dst and src pointers */ | ||
1458 | dst += nbytes; | ||
1459 | src += nbytes; | ||
1460 | |||
1461 | /* | ||
1462 | * nbits is the number of remaining bits. It should not exceed 8 as | ||
1463 | * we've already copied as much bytes as possible. | ||
1464 | */ | ||
1465 | nbits %= 8; | ||
1466 | |||
1467 | /* | ||
1468 | * If there's no more bits to copy to the destination and src buffer | ||
1469 | * was already byte aligned, then we're done. | ||
1470 | */ | ||
1471 | if (!nbits && !bits_in_src_buffer) | ||
1472 | return; | ||
1473 | |||
1474 | /* Copy the remaining bits to src_buffer */ | ||
1475 | if (nbits) | ||
1476 | src_buffer |= (*src & GENMASK(nbits - 1, 0)) << | ||
1477 | bits_in_src_buffer; | ||
1478 | bits_in_src_buffer += nbits; | ||
1479 | |||
1480 | /* | ||
1481 | * In case there were not enough bits to get a byte aligned dst buffer | ||
1482 | * prepare the src_buffer variable to match the dst organization (shift | ||
1483 | * src_buffer by dst_bit_off and retrieve the least significant bits | ||
1484 | * from dst). | ||
1485 | */ | ||
1486 | if (dst_bit_off) | ||
1487 | src_buffer = (src_buffer << dst_bit_off) | | ||
1488 | (*dst & GENMASK(dst_bit_off - 1, 0)); | ||
1489 | bits_in_src_buffer += dst_bit_off; | ||
1490 | |||
1491 | /* | ||
1492 | * Keep most significant bits from dst if we end up with an unaligned | ||
1493 | * number of bits. | ||
1494 | */ | ||
1495 | nbytes = bits_in_src_buffer / 8; | ||
1496 | if (bits_in_src_buffer % 8) { | ||
1497 | src_buffer |= (dst[nbytes] & | ||
1498 | GENMASK(7, bits_in_src_buffer % 8)) << | ||
1499 | (nbytes * 8); | ||
1500 | nbytes++; | ||
1501 | } | ||
1502 | |||
1503 | /* Copy the remaining bytes to dst */ | ||
1504 | for (i = 0; i < nbytes; i++) { | ||
1505 | dst[i] = src_buffer; | ||
1506 | src_buffer >>= 8; | ||
1507 | } | ||
1508 | } | ||
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 959cb9b70310..4f3851a24bb2 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -791,6 +791,7 @@ static void gpmi_free_dma_buffer(struct gpmi_nand_data *this) | |||
791 | this->page_buffer_phys); | 791 | this->page_buffer_phys); |
792 | kfree(this->cmd_buffer); | 792 | kfree(this->cmd_buffer); |
793 | kfree(this->data_buffer_dma); | 793 | kfree(this->data_buffer_dma); |
794 | kfree(this->raw_buffer); | ||
794 | 795 | ||
795 | this->cmd_buffer = NULL; | 796 | this->cmd_buffer = NULL; |
796 | this->data_buffer_dma = NULL; | 797 | this->data_buffer_dma = NULL; |
@@ -837,6 +838,9 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) | |||
837 | if (!this->page_buffer_virt) | 838 | if (!this->page_buffer_virt) |
838 | goto error_alloc; | 839 | goto error_alloc; |
839 | 840 | ||
841 | this->raw_buffer = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL); | ||
842 | if (!this->raw_buffer) | ||
843 | goto error_alloc; | ||
840 | 844 | ||
841 | /* Slice up the page buffer. */ | 845 | /* Slice up the page buffer. */ |
842 | this->payload_virt = this->page_buffer_virt; | 846 | this->payload_virt = this->page_buffer_virt; |
@@ -1347,6 +1351,199 @@ gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) | |||
1347 | return status & NAND_STATUS_FAIL ? -EIO : 0; | 1351 | return status & NAND_STATUS_FAIL ? -EIO : 0; |
1348 | } | 1352 | } |
1349 | 1353 | ||
1354 | /* | ||
1355 | * This function reads a NAND page without involving the ECC engine (no HW | ||
1356 | * ECC correction). | ||
1357 | * The tricky part in the GPMI/BCH controller is that it stores ECC bits | ||
1358 | * inline (interleaved with payload DATA), and do not align data chunk on | ||
1359 | * byte boundaries. | ||
1360 | * We thus need to take care moving the payload data and ECC bits stored in the | ||
1361 | * page into the provided buffers, which is why we're using gpmi_copy_bits. | ||
1362 | * | ||
1363 | * See set_geometry_by_ecc_info inline comments to have a full description | ||
1364 | * of the layout used by the GPMI controller. | ||
1365 | */ | ||
1366 | static int gpmi_ecc_read_page_raw(struct mtd_info *mtd, | ||
1367 | struct nand_chip *chip, uint8_t *buf, | ||
1368 | int oob_required, int page) | ||
1369 | { | ||
1370 | struct gpmi_nand_data *this = chip->priv; | ||
1371 | struct bch_geometry *nfc_geo = &this->bch_geometry; | ||
1372 | int eccsize = nfc_geo->ecc_chunk_size; | ||
1373 | int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len; | ||
1374 | u8 *tmp_buf = this->raw_buffer; | ||
1375 | size_t src_bit_off; | ||
1376 | size_t oob_bit_off; | ||
1377 | size_t oob_byte_off; | ||
1378 | uint8_t *oob = chip->oob_poi; | ||
1379 | int step; | ||
1380 | |||
1381 | chip->read_buf(mtd, tmp_buf, | ||
1382 | mtd->writesize + mtd->oobsize); | ||
1383 | |||
1384 | /* | ||
1385 | * If required, swap the bad block marker and the data stored in the | ||
1386 | * metadata section, so that we don't wrongly consider a block as bad. | ||
1387 | * | ||
1388 | * See the layout description for a detailed explanation on why this | ||
1389 | * is needed. | ||
1390 | */ | ||
1391 | if (this->swap_block_mark) { | ||
1392 | u8 swap = tmp_buf[0]; | ||
1393 | |||
1394 | tmp_buf[0] = tmp_buf[mtd->writesize]; | ||
1395 | tmp_buf[mtd->writesize] = swap; | ||
1396 | } | ||
1397 | |||
1398 | /* | ||
1399 | * Copy the metadata section into the oob buffer (this section is | ||
1400 | * guaranteed to be aligned on a byte boundary). | ||
1401 | */ | ||
1402 | if (oob_required) | ||
1403 | memcpy(oob, tmp_buf, nfc_geo->metadata_size); | ||
1404 | |||
1405 | oob_bit_off = nfc_geo->metadata_size * 8; | ||
1406 | src_bit_off = oob_bit_off; | ||
1407 | |||
1408 | /* Extract interleaved payload data and ECC bits */ | ||
1409 | for (step = 0; step < nfc_geo->ecc_chunk_count; step++) { | ||
1410 | if (buf) | ||
1411 | gpmi_copy_bits(buf, step * eccsize * 8, | ||
1412 | tmp_buf, src_bit_off, | ||
1413 | eccsize * 8); | ||
1414 | src_bit_off += eccsize * 8; | ||
1415 | |||
1416 | /* Align last ECC block to align a byte boundary */ | ||
1417 | if (step == nfc_geo->ecc_chunk_count - 1 && | ||
1418 | (oob_bit_off + eccbits) % 8) | ||
1419 | eccbits += 8 - ((oob_bit_off + eccbits) % 8); | ||
1420 | |||
1421 | if (oob_required) | ||
1422 | gpmi_copy_bits(oob, oob_bit_off, | ||
1423 | tmp_buf, src_bit_off, | ||
1424 | eccbits); | ||
1425 | |||
1426 | src_bit_off += eccbits; | ||
1427 | oob_bit_off += eccbits; | ||
1428 | } | ||
1429 | |||
1430 | if (oob_required) { | ||
1431 | oob_byte_off = oob_bit_off / 8; | ||
1432 | |||
1433 | if (oob_byte_off < mtd->oobsize) | ||
1434 | memcpy(oob + oob_byte_off, | ||
1435 | tmp_buf + mtd->writesize + oob_byte_off, | ||
1436 | mtd->oobsize - oob_byte_off); | ||
1437 | } | ||
1438 | |||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1442 | /* | ||
1443 | * This function writes a NAND page without involving the ECC engine (no HW | ||
1444 | * ECC generation). | ||
1445 | * The tricky part in the GPMI/BCH controller is that it stores ECC bits | ||
1446 | * inline (interleaved with payload DATA), and do not align data chunk on | ||
1447 | * byte boundaries. | ||
1448 | * We thus need to take care moving the OOB area at the right place in the | ||
1449 | * final page, which is why we're using gpmi_copy_bits. | ||
1450 | * | ||
1451 | * See set_geometry_by_ecc_info inline comments to have a full description | ||
1452 | * of the layout used by the GPMI controller. | ||
1453 | */ | ||
1454 | static int gpmi_ecc_write_page_raw(struct mtd_info *mtd, | ||
1455 | struct nand_chip *chip, | ||
1456 | const uint8_t *buf, | ||
1457 | int oob_required) | ||
1458 | { | ||
1459 | struct gpmi_nand_data *this = chip->priv; | ||
1460 | struct bch_geometry *nfc_geo = &this->bch_geometry; | ||
1461 | int eccsize = nfc_geo->ecc_chunk_size; | ||
1462 | int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len; | ||
1463 | u8 *tmp_buf = this->raw_buffer; | ||
1464 | uint8_t *oob = chip->oob_poi; | ||
1465 | size_t dst_bit_off; | ||
1466 | size_t oob_bit_off; | ||
1467 | size_t oob_byte_off; | ||
1468 | int step; | ||
1469 | |||
1470 | /* | ||
1471 | * Initialize all bits to 1 in case we don't have a buffer for the | ||
1472 | * payload or oob data in order to leave unspecified bits of data | ||
1473 | * to their initial state. | ||
1474 | */ | ||
1475 | if (!buf || !oob_required) | ||
1476 | memset(tmp_buf, 0xff, mtd->writesize + mtd->oobsize); | ||
1477 | |||
1478 | /* | ||
1479 | * First copy the metadata section (stored in oob buffer) at the | ||
1480 | * beginning of the page, as imposed by the GPMI layout. | ||
1481 | */ | ||
1482 | memcpy(tmp_buf, oob, nfc_geo->metadata_size); | ||
1483 | oob_bit_off = nfc_geo->metadata_size * 8; | ||
1484 | dst_bit_off = oob_bit_off; | ||
1485 | |||
1486 | /* Interleave payload data and ECC bits */ | ||
1487 | for (step = 0; step < nfc_geo->ecc_chunk_count; step++) { | ||
1488 | if (buf) | ||
1489 | gpmi_copy_bits(tmp_buf, dst_bit_off, | ||
1490 | buf, step * eccsize * 8, eccsize * 8); | ||
1491 | dst_bit_off += eccsize * 8; | ||
1492 | |||
1493 | /* Align last ECC block to align a byte boundary */ | ||
1494 | if (step == nfc_geo->ecc_chunk_count - 1 && | ||
1495 | (oob_bit_off + eccbits) % 8) | ||
1496 | eccbits += 8 - ((oob_bit_off + eccbits) % 8); | ||
1497 | |||
1498 | if (oob_required) | ||
1499 | gpmi_copy_bits(tmp_buf, dst_bit_off, | ||
1500 | oob, oob_bit_off, eccbits); | ||
1501 | |||
1502 | dst_bit_off += eccbits; | ||
1503 | oob_bit_off += eccbits; | ||
1504 | } | ||
1505 | |||
1506 | oob_byte_off = oob_bit_off / 8; | ||
1507 | |||
1508 | if (oob_required && oob_byte_off < mtd->oobsize) | ||
1509 | memcpy(tmp_buf + mtd->writesize + oob_byte_off, | ||
1510 | oob + oob_byte_off, mtd->oobsize - oob_byte_off); | ||
1511 | |||
1512 | /* | ||
1513 | * If required, swap the bad block marker and the first byte of the | ||
1514 | * metadata section, so that we don't modify the bad block marker. | ||
1515 | * | ||
1516 | * See the layout description for a detailed explanation on why this | ||
1517 | * is needed. | ||
1518 | */ | ||
1519 | if (this->swap_block_mark) { | ||
1520 | u8 swap = tmp_buf[0]; | ||
1521 | |||
1522 | tmp_buf[0] = tmp_buf[mtd->writesize]; | ||
1523 | tmp_buf[mtd->writesize] = swap; | ||
1524 | } | ||
1525 | |||
1526 | chip->write_buf(mtd, tmp_buf, mtd->writesize + mtd->oobsize); | ||
1527 | |||
1528 | return 0; | ||
1529 | } | ||
1530 | |||
1531 | static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
1532 | int page) | ||
1533 | { | ||
1534 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | ||
1535 | |||
1536 | return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page); | ||
1537 | } | ||
1538 | |||
1539 | static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
1540 | int page) | ||
1541 | { | ||
1542 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page); | ||
1543 | |||
1544 | return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1); | ||
1545 | } | ||
1546 | |||
1350 | static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) | 1547 | static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) |
1351 | { | 1548 | { |
1352 | struct nand_chip *chip = mtd->priv; | 1549 | struct nand_chip *chip = mtd->priv; |
@@ -1664,6 +1861,10 @@ static int gpmi_init_last(struct gpmi_nand_data *this) | |||
1664 | ecc->write_page = gpmi_ecc_write_page; | 1861 | ecc->write_page = gpmi_ecc_write_page; |
1665 | ecc->read_oob = gpmi_ecc_read_oob; | 1862 | ecc->read_oob = gpmi_ecc_read_oob; |
1666 | ecc->write_oob = gpmi_ecc_write_oob; | 1863 | ecc->write_oob = gpmi_ecc_write_oob; |
1864 | ecc->read_page_raw = gpmi_ecc_read_page_raw; | ||
1865 | ecc->write_page_raw = gpmi_ecc_write_page_raw; | ||
1866 | ecc->read_oob_raw = gpmi_ecc_read_oob_raw; | ||
1867 | ecc->write_oob_raw = gpmi_ecc_write_oob_raw; | ||
1667 | ecc->mode = NAND_ECC_HW; | 1868 | ecc->mode = NAND_ECC_HW; |
1668 | ecc->size = bch_geo->ecc_chunk_size; | 1869 | ecc->size = bch_geo->ecc_chunk_size; |
1669 | ecc->strength = bch_geo->ecc_strength; | 1870 | ecc->strength = bch_geo->ecc_strength; |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index 32c6ba49f986..544062f65020 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h | |||
@@ -189,6 +189,8 @@ struct gpmi_nand_data { | |||
189 | void *auxiliary_virt; | 189 | void *auxiliary_virt; |
190 | dma_addr_t auxiliary_phys; | 190 | dma_addr_t auxiliary_phys; |
191 | 191 | ||
192 | void *raw_buffer; | ||
193 | |||
192 | /* DMA channels */ | 194 | /* DMA channels */ |
193 | #define DMA_CHANS 8 | 195 | #define DMA_CHANS 8 |
194 | struct dma_chan *dma_chans[DMA_CHANS]; | 196 | struct dma_chan *dma_chans[DMA_CHANS]; |
@@ -290,6 +292,10 @@ extern int gpmi_send_page(struct gpmi_nand_data *, | |||
290 | extern int gpmi_read_page(struct gpmi_nand_data *, | 292 | extern int gpmi_read_page(struct gpmi_nand_data *, |
291 | dma_addr_t payload, dma_addr_t auxiliary); | 293 | dma_addr_t payload, dma_addr_t auxiliary); |
292 | 294 | ||
295 | void gpmi_copy_bits(u8 *dst, size_t dst_bit_off, | ||
296 | const u8 *src, size_t src_bit_off, | ||
297 | size_t nbits); | ||
298 | |||
293 | /* BCH : Status Block Completion Codes */ | 299 | /* BCH : Status Block Completion Codes */ |
294 | #define STATUS_GOOD 0x00 | 300 | #define STATUS_GOOD 0x00 |
295 | #define STATUS_ERASED 0xff | 301 | #define STATUS_ERASED 0xff |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index e1d56beeca79..a8f550fec35e 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -280,14 +280,10 @@ static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) | |||
280 | *t++ = __raw_readl(s++); | 280 | *t++ = __raw_readl(s++); |
281 | } | 281 | } |
282 | 282 | ||
283 | static void memcpy32_toio(void __iomem *trg, const void *src, int size) | 283 | static inline void memcpy32_toio(void __iomem *trg, const void *src, int size) |
284 | { | 284 | { |
285 | int i; | 285 | /* __iowrite32_copy use 32bit size values so divide by 4 */ |
286 | u32 __iomem *t = trg; | 286 | __iowrite32_copy(trg, src, size / 4); |
287 | const u32 *s = src; | ||
288 | |||
289 | for (i = 0; i < (size >> 2); i++) | ||
290 | __raw_writel(*s++, t++); | ||
291 | } | 287 | } |
292 | 288 | ||
293 | static int check_int_v3(struct mxc_nand_host *host) | 289 | static int check_int_v3(struct mxc_nand_host *host) |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5b5c62712814..41585dfb206f 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -485,11 +485,11 @@ static int nand_check_wp(struct mtd_info *mtd) | |||
485 | } | 485 | } |
486 | 486 | ||
487 | /** | 487 | /** |
488 | * nand_block_checkbad - [GENERIC] Check if a block is marked bad | 488 | * nand_block_isreserved - [GENERIC] Check if a block is marked reserved. |
489 | * @mtd: MTD device structure | 489 | * @mtd: MTD device structure |
490 | * @ofs: offset from device start | 490 | * @ofs: offset from device start |
491 | * | 491 | * |
492 | * Check if the block is mark as reserved. | 492 | * Check if the block is marked as reserved. |
493 | */ | 493 | */ |
494 | static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs) | 494 | static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs) |
495 | { | 495 | { |
@@ -720,7 +720,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
720 | 720 | ||
721 | /* | 721 | /* |
722 | * Program and erase have their own busy handlers status, sequential | 722 | * Program and erase have their own busy handlers status, sequential |
723 | * in, and deplete1 need no delay. | 723 | * in and status need no delay. |
724 | */ | 724 | */ |
725 | switch (command) { | 725 | switch (command) { |
726 | 726 | ||
@@ -3765,9 +3765,9 @@ ident_done: | |||
3765 | pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | 3765 | pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, |
3766 | type->name); | 3766 | type->name); |
3767 | 3767 | ||
3768 | pr_info("%dMiB, %s, page size: %d, OOB size: %d\n", | 3768 | pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", |
3769 | (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", | 3769 | (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", |
3770 | mtd->writesize, mtd->oobsize); | 3770 | mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); |
3771 | return type; | 3771 | return type; |
3772 | } | 3772 | } |
3773 | 3773 | ||
@@ -4035,7 +4035,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4035 | */ | 4035 | */ |
4036 | if (!ecc->size && (mtd->oobsize >= 64)) { | 4036 | if (!ecc->size && (mtd->oobsize >= 64)) { |
4037 | ecc->size = 512; | 4037 | ecc->size = 512; |
4038 | ecc->bytes = 7; | 4038 | ecc->bytes = DIV_ROUND_UP(13 * ecc->strength, 8); |
4039 | } | 4039 | } |
4040 | ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, | 4040 | ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, |
4041 | &ecc->layout); | 4041 | &ecc->layout); |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index fbde89105245..dd620c19c619 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -178,6 +178,7 @@ struct nand_manufacturers nand_manuf_ids[] = { | |||
178 | {NAND_MFR_EON, "Eon"}, | 178 | {NAND_MFR_EON, "Eon"}, |
179 | {NAND_MFR_SANDISK, "SanDisk"}, | 179 | {NAND_MFR_SANDISK, "SanDisk"}, |
180 | {NAND_MFR_INTEL, "Intel"}, | 180 | {NAND_MFR_INTEL, "Intel"}, |
181 | {NAND_MFR_ATO, "ATO"}, | ||
181 | {0x0, "Unknown"} | 182 | {0x0, "Unknown"} |
182 | }; | 183 | }; |
183 | 184 | ||
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 7dc1dd28d896..ab5bbf567439 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -87,10 +87,6 @@ | |||
87 | #define CONFIG_NANDSIM_MAX_PARTS 32 | 87 | #define CONFIG_NANDSIM_MAX_PARTS 32 |
88 | #endif | 88 | #endif |
89 | 89 | ||
90 | static uint first_id_byte = CONFIG_NANDSIM_FIRST_ID_BYTE; | ||
91 | static uint second_id_byte = CONFIG_NANDSIM_SECOND_ID_BYTE; | ||
92 | static uint third_id_byte = CONFIG_NANDSIM_THIRD_ID_BYTE; | ||
93 | static uint fourth_id_byte = CONFIG_NANDSIM_FOURTH_ID_BYTE; | ||
94 | static uint access_delay = CONFIG_NANDSIM_ACCESS_DELAY; | 90 | static uint access_delay = CONFIG_NANDSIM_ACCESS_DELAY; |
95 | static uint programm_delay = CONFIG_NANDSIM_PROGRAMM_DELAY; | 91 | static uint programm_delay = CONFIG_NANDSIM_PROGRAMM_DELAY; |
96 | static uint erase_delay = CONFIG_NANDSIM_ERASE_DELAY; | 92 | static uint erase_delay = CONFIG_NANDSIM_ERASE_DELAY; |
@@ -111,11 +107,19 @@ static unsigned int overridesize = 0; | |||
111 | static char *cache_file = NULL; | 107 | static char *cache_file = NULL; |
112 | static unsigned int bbt; | 108 | static unsigned int bbt; |
113 | static unsigned int bch; | 109 | static unsigned int bch; |
110 | static u_char id_bytes[8] = { | ||
111 | [0] = CONFIG_NANDSIM_FIRST_ID_BYTE, | ||
112 | [1] = CONFIG_NANDSIM_SECOND_ID_BYTE, | ||
113 | [2] = CONFIG_NANDSIM_THIRD_ID_BYTE, | ||
114 | [3] = CONFIG_NANDSIM_FOURTH_ID_BYTE, | ||
115 | [4 ... 7] = 0xFF, | ||
116 | }; | ||
114 | 117 | ||
115 | module_param(first_id_byte, uint, 0400); | 118 | module_param_array(id_bytes, byte, NULL, 0400); |
116 | module_param(second_id_byte, uint, 0400); | 119 | module_param_named(first_id_byte, id_bytes[0], byte, 0400); |
117 | module_param(third_id_byte, uint, 0400); | 120 | module_param_named(second_id_byte, id_bytes[1], byte, 0400); |
118 | module_param(fourth_id_byte, uint, 0400); | 121 | module_param_named(third_id_byte, id_bytes[2], byte, 0400); |
122 | module_param_named(fourth_id_byte, id_bytes[3], byte, 0400); | ||
119 | module_param(access_delay, uint, 0400); | 123 | module_param(access_delay, uint, 0400); |
120 | module_param(programm_delay, uint, 0400); | 124 | module_param(programm_delay, uint, 0400); |
121 | module_param(erase_delay, uint, 0400); | 125 | module_param(erase_delay, uint, 0400); |
@@ -136,10 +140,11 @@ module_param(cache_file, charp, 0400); | |||
136 | module_param(bbt, uint, 0400); | 140 | module_param(bbt, uint, 0400); |
137 | module_param(bch, uint, 0400); | 141 | module_param(bch, uint, 0400); |
138 | 142 | ||
139 | MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); | 143 | MODULE_PARM_DESC(id_bytes, "The ID bytes returned by NAND Flash 'read ID' command"); |
140 | MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); | 144 | MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID) (obsolete)"); |
141 | MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command"); | 145 | MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID) (obsolete)"); |
142 | MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command"); | 146 | MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command (obsolete)"); |
147 | MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command (obsolete)"); | ||
143 | MODULE_PARM_DESC(access_delay, "Initial page access delay (microseconds)"); | 148 | MODULE_PARM_DESC(access_delay, "Initial page access delay (microseconds)"); |
144 | MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds"); | 149 | MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds"); |
145 | MODULE_PARM_DESC(erase_delay, "Sector erase delay (milliseconds)"); | 150 | MODULE_PARM_DESC(erase_delay, "Sector erase delay (milliseconds)"); |
@@ -304,7 +309,7 @@ struct nandsim { | |||
304 | unsigned int nbparts; | 309 | unsigned int nbparts; |
305 | 310 | ||
306 | uint busw; /* flash chip bus width (8 or 16) */ | 311 | uint busw; /* flash chip bus width (8 or 16) */ |
307 | u_char ids[4]; /* chip's ID bytes */ | 312 | u_char ids[8]; /* chip's ID bytes */ |
308 | uint32_t options; /* chip's characteristic bits */ | 313 | uint32_t options; /* chip's characteristic bits */ |
309 | uint32_t state; /* current chip state */ | 314 | uint32_t state; /* current chip state */ |
310 | uint32_t nxstate; /* next expected state */ | 315 | uint32_t nxstate; /* next expected state */ |
@@ -2279,17 +2284,18 @@ static int __init ns_init_module(void) | |||
2279 | * Perform minimum nandsim structure initialization to handle | 2284 | * Perform minimum nandsim structure initialization to handle |
2280 | * the initial ID read command correctly | 2285 | * the initial ID read command correctly |
2281 | */ | 2286 | */ |
2282 | if (third_id_byte != 0xFF || fourth_id_byte != 0xFF) | 2287 | if (id_bytes[6] != 0xFF || id_bytes[7] != 0xFF) |
2288 | nand->geom.idbytes = 8; | ||
2289 | else if (id_bytes[4] != 0xFF || id_bytes[5] != 0xFF) | ||
2290 | nand->geom.idbytes = 6; | ||
2291 | else if (id_bytes[2] != 0xFF || id_bytes[3] != 0xFF) | ||
2283 | nand->geom.idbytes = 4; | 2292 | nand->geom.idbytes = 4; |
2284 | else | 2293 | else |
2285 | nand->geom.idbytes = 2; | 2294 | nand->geom.idbytes = 2; |
2286 | nand->regs.status = NS_STATUS_OK(nand); | 2295 | nand->regs.status = NS_STATUS_OK(nand); |
2287 | nand->nxstate = STATE_UNKNOWN; | 2296 | nand->nxstate = STATE_UNKNOWN; |
2288 | nand->options |= OPT_PAGE512; /* temporary value */ | 2297 | nand->options |= OPT_PAGE512; /* temporary value */ |
2289 | nand->ids[0] = first_id_byte; | 2298 | memcpy(nand->ids, id_bytes, sizeof(nand->ids)); |
2290 | nand->ids[1] = second_id_byte; | ||
2291 | nand->ids[2] = third_id_byte; | ||
2292 | nand->ids[3] = fourth_id_byte; | ||
2293 | if (bus_width == 16) { | 2299 | if (bus_width == 16) { |
2294 | nand->busw = 16; | 2300 | nand->busw = 16; |
2295 | chip->options |= NAND_BUSWIDTH_16; | 2301 | chip->options |= NAND_BUSWIDTH_16; |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 6d74b56dd9f6..63f858e6bf39 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -144,11 +144,13 @@ static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, | |||
144 | 0xac, 0x6b, 0xff, 0x99, 0x7b}; | 144 | 0xac, 0x6b, 0xff, 0x99, 0x7b}; |
145 | static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; | 145 | static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; |
146 | 146 | ||
147 | /* oob info generated runtime depending on ecc algorithm and layout selected */ | 147 | /* Shared among all NAND instances to synchronize access to the ECC Engine */ |
148 | static struct nand_ecclayout omap_oobinfo; | 148 | static struct nand_hw_control omap_gpmc_controller = { |
149 | .lock = __SPIN_LOCK_UNLOCKED(omap_gpmc_controller.lock), | ||
150 | .wq = __WAIT_QUEUE_HEAD_INITIALIZER(omap_gpmc_controller.wq), | ||
151 | }; | ||
149 | 152 | ||
150 | struct omap_nand_info { | 153 | struct omap_nand_info { |
151 | struct nand_hw_control controller; | ||
152 | struct omap_nand_platform_data *pdata; | 154 | struct omap_nand_platform_data *pdata; |
153 | struct mtd_info mtd; | 155 | struct mtd_info mtd; |
154 | struct nand_chip nand; | 156 | struct nand_chip nand; |
@@ -168,6 +170,8 @@ struct omap_nand_info { | |||
168 | u_char *buf; | 170 | u_char *buf; |
169 | int buf_len; | 171 | int buf_len; |
170 | struct gpmc_nand_regs reg; | 172 | struct gpmc_nand_regs reg; |
173 | /* generated at runtime depending on ECC algorithm and layout selected */ | ||
174 | struct nand_ecclayout oobinfo; | ||
171 | /* fields specific for BCHx_HW ECC scheme */ | 175 | /* fields specific for BCHx_HW ECC scheme */ |
172 | struct device *elm_dev; | 176 | struct device *elm_dev; |
173 | struct device_node *of_node; | 177 | struct device_node *of_node; |
@@ -1686,9 +1690,6 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1686 | 1690 | ||
1687 | platform_set_drvdata(pdev, info); | 1691 | platform_set_drvdata(pdev, info); |
1688 | 1692 | ||
1689 | spin_lock_init(&info->controller.lock); | ||
1690 | init_waitqueue_head(&info->controller.wq); | ||
1691 | |||
1692 | info->pdev = pdev; | 1693 | info->pdev = pdev; |
1693 | info->gpmc_cs = pdata->cs; | 1694 | info->gpmc_cs = pdata->cs; |
1694 | info->reg = pdata->reg; | 1695 | info->reg = pdata->reg; |
@@ -1708,7 +1709,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1708 | 1709 | ||
1709 | info->phys_base = res->start; | 1710 | info->phys_base = res->start; |
1710 | 1711 | ||
1711 | nand_chip->controller = &info->controller; | 1712 | nand_chip->controller = &omap_gpmc_controller; |
1712 | 1713 | ||
1713 | nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; | 1714 | nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; |
1714 | nand_chip->cmd_ctrl = omap_hwcontrol; | 1715 | nand_chip->cmd_ctrl = omap_hwcontrol; |
@@ -1741,13 +1742,6 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1741 | goto return_error; | 1742 | goto return_error; |
1742 | } | 1743 | } |
1743 | 1744 | ||
1744 | /* check for small page devices */ | ||
1745 | if ((mtd->oobsize < 64) && (pdata->ecc_opt != OMAP_ECC_HAM1_CODE_HW)) { | ||
1746 | dev_err(&info->pdev->dev, "small page devices are not supported\n"); | ||
1747 | err = -EINVAL; | ||
1748 | goto return_error; | ||
1749 | } | ||
1750 | |||
1751 | /* re-populate low-level callbacks based on xfer modes */ | 1745 | /* re-populate low-level callbacks based on xfer modes */ |
1752 | switch (pdata->xfer_type) { | 1746 | switch (pdata->xfer_type) { |
1753 | case NAND_OMAP_PREFETCH_POLLED: | 1747 | case NAND_OMAP_PREFETCH_POLLED: |
@@ -1840,7 +1834,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1840 | } | 1834 | } |
1841 | 1835 | ||
1842 | /* populate MTD interface based on ECC scheme */ | 1836 | /* populate MTD interface based on ECC scheme */ |
1843 | ecclayout = &omap_oobinfo; | 1837 | ecclayout = &info->oobinfo; |
1844 | switch (info->ecc_opt) { | 1838 | switch (info->ecc_opt) { |
1845 | case OMAP_ECC_HAM1_CODE_SW: | 1839 | case OMAP_ECC_HAM1_CODE_SW: |
1846 | nand_chip->ecc.mode = NAND_ECC_SOFT; | 1840 | nand_chip->ecc.mode = NAND_ECC_SOFT; |
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index c53e36956bff..c3c6d305caa7 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/mtd/partitions.h> | 19 | #include <linux/mtd/partitions.h> |
20 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <asm/sizes.h> | 23 | #include <asm/sizes.h> |
24 | #include <linux/platform_data/mtd-orion_nand.h> | 24 | #include <linux/platform_data/mtd-orion_nand.h> |
25 | 25 | ||
@@ -85,33 +85,24 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
85 | int ret = 0; | 85 | int ret = 0; |
86 | u32 val = 0; | 86 | u32 val = 0; |
87 | 87 | ||
88 | nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); | 88 | nc = devm_kzalloc(&pdev->dev, |
89 | if (!nc) { | 89 | sizeof(struct nand_chip) + sizeof(struct mtd_info), |
90 | ret = -ENOMEM; | 90 | GFP_KERNEL); |
91 | goto no_res; | 91 | if (!nc) |
92 | } | 92 | return -ENOMEM; |
93 | mtd = (struct mtd_info *)(nc + 1); | 93 | mtd = (struct mtd_info *)(nc + 1); |
94 | 94 | ||
95 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 95 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
96 | if (!res) { | 96 | io_base = devm_ioremap_resource(&pdev->dev, res); |
97 | ret = -ENODEV; | ||
98 | goto no_res; | ||
99 | } | ||
100 | 97 | ||
101 | io_base = ioremap(res->start, resource_size(res)); | 98 | if (IS_ERR(io_base)) |
102 | if (!io_base) { | 99 | return PTR_ERR(io_base); |
103 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
104 | ret = -EIO; | ||
105 | goto no_res; | ||
106 | } | ||
107 | 100 | ||
108 | if (pdev->dev.of_node) { | 101 | if (pdev->dev.of_node) { |
109 | board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data), | 102 | board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data), |
110 | GFP_KERNEL); | 103 | GFP_KERNEL); |
111 | if (!board) { | 104 | if (!board) |
112 | ret = -ENOMEM; | 105 | return -ENOMEM; |
113 | goto no_res; | ||
114 | } | ||
115 | if (!of_property_read_u32(pdev->dev.of_node, "cle", &val)) | 106 | if (!of_property_read_u32(pdev->dev.of_node, "cle", &val)) |
116 | board->cle = (u8)val; | 107 | board->cle = (u8)val; |
117 | else | 108 | else |
@@ -185,9 +176,6 @@ no_dev: | |||
185 | clk_disable_unprepare(clk); | 176 | clk_disable_unprepare(clk); |
186 | clk_put(clk); | 177 | clk_put(clk); |
187 | } | 178 | } |
188 | iounmap(io_base); | ||
189 | no_res: | ||
190 | kfree(nc); | ||
191 | 179 | ||
192 | return ret; | 180 | return ret; |
193 | } | 181 | } |
@@ -195,15 +183,10 @@ no_res: | |||
195 | static int orion_nand_remove(struct platform_device *pdev) | 183 | static int orion_nand_remove(struct platform_device *pdev) |
196 | { | 184 | { |
197 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 185 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
198 | struct nand_chip *nc = mtd->priv; | ||
199 | struct clk *clk; | 186 | struct clk *clk; |
200 | 187 | ||
201 | nand_release(mtd); | 188 | nand_release(mtd); |
202 | 189 | ||
203 | iounmap(nc->IO_ADDR_W); | ||
204 | |||
205 | kfree(nc); | ||
206 | |||
207 | clk = clk_get(&pdev->dev, NULL); | 190 | clk = clk_get(&pdev->dev, NULL); |
208 | if (!IS_ERR(clk)) { | 191 | if (!IS_ERR(clk)) { |
209 | clk_disable_unprepare(clk); | 192 | clk_disable_unprepare(clk); |
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c new file mode 100644 index 000000000000..ccaa8e283388 --- /dev/null +++ b/drivers/mtd/nand/sunxi_nand.c | |||
@@ -0,0 +1,1432 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Boris BREZILLON <b.brezillon.dev@gmail.com> | ||
3 | * | ||
4 | * Derived from: | ||
5 | * https://github.com/yuq/sunxi-nfc-mtd | ||
6 | * Copyright (C) 2013 Qiang Yu <yuq825@gmail.com> | ||
7 | * | ||
8 | * https://github.com/hno/Allwinner-Info | ||
9 | * Copyright (C) 2013 Henrik Nordström <Henrik Nordström> | ||
10 | * | ||
11 | * Copyright (C) 2013 Dmitriy B. <rzk333@gmail.com> | ||
12 | * Copyright (C) 2013 Sergey Lapin <slapin@ossfans.org> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | */ | ||
24 | |||
25 | #include <linux/dma-mapping.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/moduleparam.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/of.h> | ||
31 | #include <linux/of_device.h> | ||
32 | #include <linux/of_gpio.h> | ||
33 | #include <linux/of_mtd.h> | ||
34 | #include <linux/mtd/mtd.h> | ||
35 | #include <linux/mtd/nand.h> | ||
36 | #include <linux/mtd/partitions.h> | ||
37 | #include <linux/clk.h> | ||
38 | #include <linux/delay.h> | ||
39 | #include <linux/dmaengine.h> | ||
40 | #include <linux/gpio.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <linux/io.h> | ||
43 | |||
44 | #define NFC_REG_CTL 0x0000 | ||
45 | #define NFC_REG_ST 0x0004 | ||
46 | #define NFC_REG_INT 0x0008 | ||
47 | #define NFC_REG_TIMING_CTL 0x000C | ||
48 | #define NFC_REG_TIMING_CFG 0x0010 | ||
49 | #define NFC_REG_ADDR_LOW 0x0014 | ||
50 | #define NFC_REG_ADDR_HIGH 0x0018 | ||
51 | #define NFC_REG_SECTOR_NUM 0x001C | ||
52 | #define NFC_REG_CNT 0x0020 | ||
53 | #define NFC_REG_CMD 0x0024 | ||
54 | #define NFC_REG_RCMD_SET 0x0028 | ||
55 | #define NFC_REG_WCMD_SET 0x002C | ||
56 | #define NFC_REG_IO_DATA 0x0030 | ||
57 | #define NFC_REG_ECC_CTL 0x0034 | ||
58 | #define NFC_REG_ECC_ST 0x0038 | ||
59 | #define NFC_REG_DEBUG 0x003C | ||
60 | #define NFC_REG_ECC_CNT0 0x0040 | ||
61 | #define NFC_REG_ECC_CNT1 0x0044 | ||
62 | #define NFC_REG_ECC_CNT2 0x0048 | ||
63 | #define NFC_REG_ECC_CNT3 0x004c | ||
64 | #define NFC_REG_USER_DATA_BASE 0x0050 | ||
65 | #define NFC_REG_SPARE_AREA 0x00A0 | ||
66 | #define NFC_RAM0_BASE 0x0400 | ||
67 | #define NFC_RAM1_BASE 0x0800 | ||
68 | |||
69 | /* define bit use in NFC_CTL */ | ||
70 | #define NFC_EN BIT(0) | ||
71 | #define NFC_RESET BIT(1) | ||
72 | #define NFC_BUS_WIDYH BIT(2) | ||
73 | #define NFC_RB_SEL BIT(3) | ||
74 | #define NFC_CE_SEL GENMASK(26, 24) | ||
75 | #define NFC_CE_CTL BIT(6) | ||
76 | #define NFC_CE_CTL1 BIT(7) | ||
77 | #define NFC_PAGE_SIZE GENMASK(11, 8) | ||
78 | #define NFC_SAM BIT(12) | ||
79 | #define NFC_RAM_METHOD BIT(14) | ||
80 | #define NFC_DEBUG_CTL BIT(31) | ||
81 | |||
82 | /* define bit use in NFC_ST */ | ||
83 | #define NFC_RB_B2R BIT(0) | ||
84 | #define NFC_CMD_INT_FLAG BIT(1) | ||
85 | #define NFC_DMA_INT_FLAG BIT(2) | ||
86 | #define NFC_CMD_FIFO_STATUS BIT(3) | ||
87 | #define NFC_STA BIT(4) | ||
88 | #define NFC_NATCH_INT_FLAG BIT(5) | ||
89 | #define NFC_RB_STATE0 BIT(8) | ||
90 | #define NFC_RB_STATE1 BIT(9) | ||
91 | #define NFC_RB_STATE2 BIT(10) | ||
92 | #define NFC_RB_STATE3 BIT(11) | ||
93 | |||
94 | /* define bit use in NFC_INT */ | ||
95 | #define NFC_B2R_INT_ENABLE BIT(0) | ||
96 | #define NFC_CMD_INT_ENABLE BIT(1) | ||
97 | #define NFC_DMA_INT_ENABLE BIT(2) | ||
98 | #define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \ | ||
99 | NFC_CMD_INT_ENABLE | \ | ||
100 | NFC_DMA_INT_ENABLE) | ||
101 | |||
102 | /* define bit use in NFC_CMD */ | ||
103 | #define NFC_CMD_LOW_BYTE GENMASK(7, 0) | ||
104 | #define NFC_CMD_HIGH_BYTE GENMASK(15, 8) | ||
105 | #define NFC_ADR_NUM GENMASK(18, 16) | ||
106 | #define NFC_SEND_ADR BIT(19) | ||
107 | #define NFC_ACCESS_DIR BIT(20) | ||
108 | #define NFC_DATA_TRANS BIT(21) | ||
109 | #define NFC_SEND_CMD1 BIT(22) | ||
110 | #define NFC_WAIT_FLAG BIT(23) | ||
111 | #define NFC_SEND_CMD2 BIT(24) | ||
112 | #define NFC_SEQ BIT(25) | ||
113 | #define NFC_DATA_SWAP_METHOD BIT(26) | ||
114 | #define NFC_ROW_AUTO_INC BIT(27) | ||
115 | #define NFC_SEND_CMD3 BIT(28) | ||
116 | #define NFC_SEND_CMD4 BIT(29) | ||
117 | #define NFC_CMD_TYPE GENMASK(31, 30) | ||
118 | |||
119 | /* define bit use in NFC_RCMD_SET */ | ||
120 | #define NFC_READ_CMD GENMASK(7, 0) | ||
121 | #define NFC_RANDOM_READ_CMD0 GENMASK(15, 8) | ||
122 | #define NFC_RANDOM_READ_CMD1 GENMASK(23, 16) | ||
123 | |||
124 | /* define bit use in NFC_WCMD_SET */ | ||
125 | #define NFC_PROGRAM_CMD GENMASK(7, 0) | ||
126 | #define NFC_RANDOM_WRITE_CMD GENMASK(15, 8) | ||
127 | #define NFC_READ_CMD0 GENMASK(23, 16) | ||
128 | #define NFC_READ_CMD1 GENMASK(31, 24) | ||
129 | |||
130 | /* define bit use in NFC_ECC_CTL */ | ||
131 | #define NFC_ECC_EN BIT(0) | ||
132 | #define NFC_ECC_PIPELINE BIT(3) | ||
133 | #define NFC_ECC_EXCEPTION BIT(4) | ||
134 | #define NFC_ECC_BLOCK_SIZE BIT(5) | ||
135 | #define NFC_RANDOM_EN BIT(9) | ||
136 | #define NFC_RANDOM_DIRECTION BIT(10) | ||
137 | #define NFC_ECC_MODE_SHIFT 12 | ||
138 | #define NFC_ECC_MODE GENMASK(15, 12) | ||
139 | #define NFC_RANDOM_SEED GENMASK(30, 16) | ||
140 | |||
141 | #define NFC_DEFAULT_TIMEOUT_MS 1000 | ||
142 | |||
143 | #define NFC_SRAM_SIZE 1024 | ||
144 | |||
145 | #define NFC_MAX_CS 7 | ||
146 | |||
147 | /* | ||
148 | * Ready/Busy detection type: describes the Ready/Busy detection modes | ||
149 | * | ||
150 | * @RB_NONE: no external detection available, rely on STATUS command | ||
151 | * and software timeouts | ||
152 | * @RB_NATIVE: use sunxi NAND controller Ready/Busy support. The Ready/Busy | ||
153 | * pin of the NAND flash chip must be connected to one of the | ||
154 | * native NAND R/B pins (those which can be muxed to the NAND | ||
155 | * Controller) | ||
156 | * @RB_GPIO: use a simple GPIO to handle Ready/Busy status. The Ready/Busy | ||
157 | * pin of the NAND flash chip must be connected to a GPIO capable | ||
158 | * pin. | ||
159 | */ | ||
160 | enum sunxi_nand_rb_type { | ||
161 | RB_NONE, | ||
162 | RB_NATIVE, | ||
163 | RB_GPIO, | ||
164 | }; | ||
165 | |||
166 | /* | ||
167 | * Ready/Busy structure: stores information related to Ready/Busy detection | ||
168 | * | ||
169 | * @type: the Ready/Busy detection mode | ||
170 | * @info: information related to the R/B detection mode. Either a gpio | ||
171 | * id or a native R/B id (those supported by the NAND controller). | ||
172 | */ | ||
173 | struct sunxi_nand_rb { | ||
174 | enum sunxi_nand_rb_type type; | ||
175 | union { | ||
176 | int gpio; | ||
177 | int nativeid; | ||
178 | } info; | ||
179 | }; | ||
180 | |||
181 | /* | ||
182 | * Chip Select structure: stores information related to NAND Chip Select | ||
183 | * | ||
184 | * @cs: the NAND CS id used to communicate with a NAND Chip | ||
185 | * @rb: the Ready/Busy description | ||
186 | */ | ||
187 | struct sunxi_nand_chip_sel { | ||
188 | u8 cs; | ||
189 | struct sunxi_nand_rb rb; | ||
190 | }; | ||
191 | |||
192 | /* | ||
193 | * sunxi HW ECC infos: stores information related to HW ECC support | ||
194 | * | ||
195 | * @mode: the sunxi ECC mode field deduced from ECC requirements | ||
196 | * @layout: the OOB layout depending on the ECC requirements and the | ||
197 | * selected ECC mode | ||
198 | */ | ||
199 | struct sunxi_nand_hw_ecc { | ||
200 | int mode; | ||
201 | struct nand_ecclayout layout; | ||
202 | }; | ||
203 | |||
204 | /* | ||
205 | * NAND chip structure: stores NAND chip device related information | ||
206 | * | ||
207 | * @node: used to store NAND chips into a list | ||
208 | * @nand: base NAND chip structure | ||
209 | * @mtd: base MTD structure | ||
210 | * @clk_rate: clk_rate required for this NAND chip | ||
211 | * @selected: current active CS | ||
212 | * @nsels: number of CS lines required by the NAND chip | ||
213 | * @sels: array of CS lines descriptions | ||
214 | */ | ||
215 | struct sunxi_nand_chip { | ||
216 | struct list_head node; | ||
217 | struct nand_chip nand; | ||
218 | struct mtd_info mtd; | ||
219 | unsigned long clk_rate; | ||
220 | int selected; | ||
221 | int nsels; | ||
222 | struct sunxi_nand_chip_sel sels[0]; | ||
223 | }; | ||
224 | |||
225 | static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand) | ||
226 | { | ||
227 | return container_of(nand, struct sunxi_nand_chip, nand); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * NAND Controller structure: stores sunxi NAND controller information | ||
232 | * | ||
233 | * @controller: base controller structure | ||
234 | * @dev: parent device (used to print error messages) | ||
235 | * @regs: NAND controller registers | ||
236 | * @ahb_clk: NAND Controller AHB clock | ||
237 | * @mod_clk: NAND Controller mod clock | ||
238 | * @assigned_cs: bitmask describing already assigned CS lines | ||
239 | * @clk_rate: NAND controller current clock rate | ||
240 | * @chips: a list containing all the NAND chips attached to | ||
241 | * this NAND controller | ||
242 | * @complete: a completion object used to wait for NAND | ||
243 | * controller events | ||
244 | */ | ||
245 | struct sunxi_nfc { | ||
246 | struct nand_hw_control controller; | ||
247 | struct device *dev; | ||
248 | void __iomem *regs; | ||
249 | struct clk *ahb_clk; | ||
250 | struct clk *mod_clk; | ||
251 | unsigned long assigned_cs; | ||
252 | unsigned long clk_rate; | ||
253 | struct list_head chips; | ||
254 | struct completion complete; | ||
255 | }; | ||
256 | |||
257 | static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl) | ||
258 | { | ||
259 | return container_of(ctrl, struct sunxi_nfc, controller); | ||
260 | } | ||
261 | |||
262 | static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id) | ||
263 | { | ||
264 | struct sunxi_nfc *nfc = dev_id; | ||
265 | u32 st = readl(nfc->regs + NFC_REG_ST); | ||
266 | u32 ien = readl(nfc->regs + NFC_REG_INT); | ||
267 | |||
268 | if (!(ien & st)) | ||
269 | return IRQ_NONE; | ||
270 | |||
271 | if ((ien & st) == ien) | ||
272 | complete(&nfc->complete); | ||
273 | |||
274 | writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST); | ||
275 | writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT); | ||
276 | |||
277 | return IRQ_HANDLED; | ||
278 | } | ||
279 | |||
280 | static int sunxi_nfc_wait_int(struct sunxi_nfc *nfc, u32 flags, | ||
281 | unsigned int timeout_ms) | ||
282 | { | ||
283 | init_completion(&nfc->complete); | ||
284 | |||
285 | writel(flags, nfc->regs + NFC_REG_INT); | ||
286 | |||
287 | if (!timeout_ms) | ||
288 | timeout_ms = NFC_DEFAULT_TIMEOUT_MS; | ||
289 | |||
290 | if (!wait_for_completion_timeout(&nfc->complete, | ||
291 | msecs_to_jiffies(timeout_ms))) { | ||
292 | dev_err(nfc->dev, "wait interrupt timedout\n"); | ||
293 | return -ETIMEDOUT; | ||
294 | } | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc) | ||
300 | { | ||
301 | unsigned long timeout = jiffies + | ||
302 | msecs_to_jiffies(NFC_DEFAULT_TIMEOUT_MS); | ||
303 | |||
304 | do { | ||
305 | if (!(readl(nfc->regs + NFC_REG_ST) & NFC_CMD_FIFO_STATUS)) | ||
306 | return 0; | ||
307 | } while (time_before(jiffies, timeout)); | ||
308 | |||
309 | dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n"); | ||
310 | return -ETIMEDOUT; | ||
311 | } | ||
312 | |||
313 | static int sunxi_nfc_rst(struct sunxi_nfc *nfc) | ||
314 | { | ||
315 | unsigned long timeout = jiffies + | ||
316 | msecs_to_jiffies(NFC_DEFAULT_TIMEOUT_MS); | ||
317 | |||
318 | writel(0, nfc->regs + NFC_REG_ECC_CTL); | ||
319 | writel(NFC_RESET, nfc->regs + NFC_REG_CTL); | ||
320 | |||
321 | do { | ||
322 | if (!(readl(nfc->regs + NFC_REG_CTL) & NFC_RESET)) | ||
323 | return 0; | ||
324 | } while (time_before(jiffies, timeout)); | ||
325 | |||
326 | dev_err(nfc->dev, "wait for NAND controller reset timedout\n"); | ||
327 | return -ETIMEDOUT; | ||
328 | } | ||
329 | |||
330 | static int sunxi_nfc_dev_ready(struct mtd_info *mtd) | ||
331 | { | ||
332 | struct nand_chip *nand = mtd->priv; | ||
333 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | ||
334 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | ||
335 | struct sunxi_nand_rb *rb; | ||
336 | unsigned long timeo = (sunxi_nand->nand.state == FL_ERASING ? 400 : 20); | ||
337 | int ret; | ||
338 | |||
339 | if (sunxi_nand->selected < 0) | ||
340 | return 0; | ||
341 | |||
342 | rb = &sunxi_nand->sels[sunxi_nand->selected].rb; | ||
343 | |||
344 | switch (rb->type) { | ||
345 | case RB_NATIVE: | ||
346 | ret = !!(readl(nfc->regs + NFC_REG_ST) & | ||
347 | (NFC_RB_STATE0 << rb->info.nativeid)); | ||
348 | if (ret) | ||
349 | break; | ||
350 | |||
351 | sunxi_nfc_wait_int(nfc, NFC_RB_B2R, timeo); | ||
352 | ret = !!(readl(nfc->regs + NFC_REG_ST) & | ||
353 | (NFC_RB_STATE0 << rb->info.nativeid)); | ||
354 | break; | ||
355 | case RB_GPIO: | ||
356 | ret = gpio_get_value(rb->info.gpio); | ||
357 | break; | ||
358 | case RB_NONE: | ||
359 | default: | ||
360 | ret = 0; | ||
361 | dev_err(nfc->dev, "cannot check R/B NAND status!\n"); | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) | ||
369 | { | ||
370 | struct nand_chip *nand = mtd->priv; | ||
371 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | ||
372 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | ||
373 | struct sunxi_nand_chip_sel *sel; | ||
374 | u32 ctl; | ||
375 | |||
376 | if (chip > 0 && chip >= sunxi_nand->nsels) | ||
377 | return; | ||
378 | |||
379 | if (chip == sunxi_nand->selected) | ||
380 | return; | ||
381 | |||
382 | ctl = readl(nfc->regs + NFC_REG_CTL) & | ||
383 | ~(NFC_CE_SEL | NFC_RB_SEL | NFC_EN); | ||
384 | |||
385 | if (chip >= 0) { | ||
386 | sel = &sunxi_nand->sels[chip]; | ||
387 | |||
388 | ctl |= (sel->cs << 24) | NFC_EN | | ||
389 | (((nand->page_shift - 10) & 0xf) << 8); | ||
390 | if (sel->rb.type == RB_NONE) { | ||
391 | nand->dev_ready = NULL; | ||
392 | } else { | ||
393 | nand->dev_ready = sunxi_nfc_dev_ready; | ||
394 | if (sel->rb.type == RB_NATIVE) | ||
395 | ctl |= (sel->rb.info.nativeid << 3); | ||
396 | } | ||
397 | |||
398 | writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA); | ||
399 | |||
400 | if (nfc->clk_rate != sunxi_nand->clk_rate) { | ||
401 | clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate); | ||
402 | nfc->clk_rate = sunxi_nand->clk_rate; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | writel(ctl, nfc->regs + NFC_REG_CTL); | ||
407 | |||
408 | sunxi_nand->selected = chip; | ||
409 | } | ||
410 | |||
411 | static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
412 | { | ||
413 | struct nand_chip *nand = mtd->priv; | ||
414 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | ||
415 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | ||
416 | int ret; | ||
417 | int cnt; | ||
418 | int offs = 0; | ||
419 | u32 tmp; | ||
420 | |||
421 | while (len > offs) { | ||
422 | cnt = min(len - offs, NFC_SRAM_SIZE); | ||
423 | |||
424 | ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); | ||
425 | if (ret) | ||
426 | break; | ||
427 | |||
428 | writel(cnt, nfc->regs + NFC_REG_CNT); | ||
429 | tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; | ||
430 | writel(tmp, nfc->regs + NFC_REG_CMD); | ||
431 | |||
432 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | ||
433 | if (ret) | ||
434 | break; | ||
435 | |||
436 | if (buf) | ||
437 | memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE, | ||
438 | cnt); | ||
439 | offs += cnt; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, | ||
444 | int len) | ||
445 | { | ||
446 | struct nand_chip *nand = mtd->priv; | ||
447 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | ||
448 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | ||
449 | int ret; | ||
450 | int cnt; | ||
451 | int offs = 0; | ||
452 | u32 tmp; | ||
453 | |||
454 | while (len > offs) { | ||
455 | cnt = min(len - offs, NFC_SRAM_SIZE); | ||
456 | |||
457 | ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); | ||
458 | if (ret) | ||
459 | break; | ||
460 | |||
461 | writel(cnt, nfc->regs + NFC_REG_CNT); | ||
462 | memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt); | ||
463 | tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | | ||
464 | NFC_ACCESS_DIR; | ||
465 | writel(tmp, nfc->regs + NFC_REG_CMD); | ||
466 | |||
467 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | ||
468 | if (ret) | ||
469 | break; | ||
470 | |||
471 | offs += cnt; | ||
472 | } | ||
473 | } | ||
474 | |||
475 | static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd) | ||
476 | { | ||
477 | uint8_t ret; | ||
478 | |||
479 | sunxi_nfc_read_buf(mtd, &ret, 1); | ||
480 | |||
481 | return ret; | ||
482 | } | ||
483 | |||
484 | static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, | ||
485 | unsigned int ctrl) | ||
486 | { | ||
487 | struct nand_chip *nand = mtd->priv; | ||
488 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | ||
489 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | ||
490 | int ret; | ||
491 | u32 tmp; | ||
492 | |||
493 | ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); | ||
494 | if (ret) | ||
495 | return; | ||
496 | |||
497 | if (ctrl & NAND_CTRL_CHANGE) { | ||
498 | tmp = readl(nfc->regs + NFC_REG_CTL); | ||
499 | if (ctrl & NAND_NCE) | ||
500 | tmp |= NFC_CE_CTL; | ||
501 | else | ||
502 | tmp &= ~NFC_CE_CTL; | ||
503 | writel(tmp, nfc->regs + NFC_REG_CTL); | ||
504 | } | ||
505 | |||
506 | if (dat == NAND_CMD_NONE) | ||
507 | return; | ||
508 | |||
509 | if (ctrl & NAND_CLE) { | ||
510 | writel(NFC_SEND_CMD1 | dat, nfc->regs + NFC_REG_CMD); | ||
511 | } else { | ||
512 | writel(dat, nfc->regs + NFC_REG_ADDR_LOW); | ||
513 | writel(NFC_SEND_ADR, nfc->regs + NFC_REG_CMD); | ||
514 | } | ||
515 | |||
516 | sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | ||
517 | } | ||
518 | |||
519 | static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, | ||
520 | struct nand_chip *chip, uint8_t *buf, | ||
521 | int oob_required, int page) | ||
522 | { | ||
523 | struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller); | ||
524 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
525 | struct nand_ecclayout *layout = ecc->layout; | ||
526 | struct sunxi_nand_hw_ecc *data = ecc->priv; | ||
527 | unsigned int max_bitflips = 0; | ||
528 | int offset; | ||
529 | int ret; | ||
530 | u32 tmp; | ||
531 | int i; | ||
532 | int cnt; | ||
533 | |||
534 | tmp = readl(nfc->regs + NFC_REG_ECC_CTL); | ||
535 | tmp &= ~(NFC_ECC_MODE | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE); | ||
536 | tmp |= NFC_ECC_EN | (data->mode << NFC_ECC_MODE_SHIFT) | | ||
537 | NFC_ECC_EXCEPTION; | ||
538 | |||
539 | writel(tmp, nfc->regs + NFC_REG_ECC_CTL); | ||
540 | |||
541 | for (i = 0; i < ecc->steps; i++) { | ||
542 | if (i) | ||
543 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, i * ecc->size, -1); | ||
544 | |||
545 | offset = mtd->writesize + layout->eccpos[i * ecc->bytes] - 4; | ||
546 | |||
547 | chip->read_buf(mtd, NULL, ecc->size); | ||
548 | |||
549 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1); | ||
550 | |||
551 | ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); | ||
552 | if (ret) | ||
553 | return ret; | ||
554 | |||
555 | tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | (1 << 30); | ||
556 | writel(tmp, nfc->regs + NFC_REG_CMD); | ||
557 | |||
558 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | ||
559 | if (ret) | ||
560 | return ret; | ||
561 | |||
562 | memcpy_fromio(buf + (i * ecc->size), | ||
563 | nfc->regs + NFC_RAM0_BASE, ecc->size); | ||
564 | |||
565 | if (readl(nfc->regs + NFC_REG_ECC_ST) & 0x1) { | ||
566 | mtd->ecc_stats.failed++; | ||
567 | } else { | ||
568 | tmp = readl(nfc->regs + NFC_REG_ECC_CNT0) & 0xff; | ||
569 | mtd->ecc_stats.corrected += tmp; | ||
570 | max_bitflips = max_t(unsigned int, max_bitflips, tmp); | ||
571 | } | ||
572 | |||
573 | if (oob_required) { | ||
574 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1); | ||
575 | |||
576 | ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); | ||
577 | if (ret) | ||
578 | return ret; | ||
579 | |||
580 | offset -= mtd->writesize; | ||
581 | chip->read_buf(mtd, chip->oob_poi + offset, | ||
582 | ecc->bytes + 4); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | if (oob_required) { | ||
587 | cnt = ecc->layout->oobfree[ecc->steps].length; | ||
588 | if (cnt > 0) { | ||
589 | offset = mtd->writesize + | ||
590 | ecc->layout->oobfree[ecc->steps].offset; | ||
591 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1); | ||
592 | offset -= mtd->writesize; | ||
593 | chip->read_buf(mtd, chip->oob_poi + offset, cnt); | ||
594 | } | ||
595 | } | ||
596 | |||
597 | tmp = readl(nfc->regs + NFC_REG_ECC_CTL); | ||
598 | tmp &= ~NFC_ECC_EN; | ||
599 | |||
600 | writel(tmp, nfc->regs + NFC_REG_ECC_CTL); | ||
601 | |||
602 | return max_bitflips; | ||
603 | } | ||
604 | |||
605 | static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, | ||
606 | struct nand_chip *chip, | ||
607 | const uint8_t *buf, int oob_required) | ||
608 | { | ||
609 | struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller); | ||
610 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
611 | struct nand_ecclayout *layout = ecc->layout; | ||
612 | struct sunxi_nand_hw_ecc *data = ecc->priv; | ||
613 | int offset; | ||
614 | int ret; | ||
615 | u32 tmp; | ||
616 | int i; | ||
617 | int cnt; | ||
618 | |||
619 | tmp = readl(nfc->regs + NFC_REG_ECC_CTL); | ||
620 | tmp &= ~(NFC_ECC_MODE | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE); | ||
621 | tmp |= NFC_ECC_EN | (data->mode << NFC_ECC_MODE_SHIFT) | | ||
622 | NFC_ECC_EXCEPTION; | ||
623 | |||
624 | writel(tmp, nfc->regs + NFC_REG_ECC_CTL); | ||
625 | |||
626 | for (i = 0; i < ecc->steps; i++) { | ||
627 | if (i) | ||
628 | chip->cmdfunc(mtd, NAND_CMD_RNDIN, i * ecc->size, -1); | ||
629 | |||
630 | chip->write_buf(mtd, buf + (i * ecc->size), ecc->size); | ||
631 | |||
632 | offset = layout->eccpos[i * ecc->bytes] - 4 + mtd->writesize; | ||
633 | |||
634 | /* Fill OOB data in */ | ||
635 | if (oob_required) { | ||
636 | tmp = 0xffffffff; | ||
637 | memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, &tmp, | ||
638 | 4); | ||
639 | } else { | ||
640 | memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, | ||
641 | chip->oob_poi + offset - mtd->writesize, | ||
642 | 4); | ||
643 | } | ||
644 | |||
645 | chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset, -1); | ||
646 | |||
647 | ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); | ||
648 | if (ret) | ||
649 | return ret; | ||
650 | |||
651 | tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | | ||
652 | (1 << 30); | ||
653 | writel(tmp, nfc->regs + NFC_REG_CMD); | ||
654 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | ||
655 | if (ret) | ||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | if (oob_required) { | ||
660 | cnt = ecc->layout->oobfree[i].length; | ||
661 | if (cnt > 0) { | ||
662 | offset = mtd->writesize + | ||
663 | ecc->layout->oobfree[i].offset; | ||
664 | chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset, -1); | ||
665 | offset -= mtd->writesize; | ||
666 | chip->write_buf(mtd, chip->oob_poi + offset, cnt); | ||
667 | } | ||
668 | } | ||
669 | |||
670 | tmp = readl(nfc->regs + NFC_REG_ECC_CTL); | ||
671 | tmp &= ~NFC_ECC_EN; | ||
672 | |||
673 | writel(tmp, nfc->regs + NFC_REG_ECC_CTL); | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd, | ||
679 | struct nand_chip *chip, | ||
680 | uint8_t *buf, int oob_required, | ||
681 | int page) | ||
682 | { | ||
683 | struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller); | ||
684 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
685 | struct sunxi_nand_hw_ecc *data = ecc->priv; | ||
686 | unsigned int max_bitflips = 0; | ||
687 | uint8_t *oob = chip->oob_poi; | ||
688 | int offset = 0; | ||
689 | int ret; | ||
690 | int cnt; | ||
691 | u32 tmp; | ||
692 | int i; | ||
693 | |||
694 | tmp = readl(nfc->regs + NFC_REG_ECC_CTL); | ||
695 | tmp &= ~(NFC_ECC_MODE | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE); | ||
696 | tmp |= NFC_ECC_EN | (data->mode << NFC_ECC_MODE_SHIFT) | | ||
697 | NFC_ECC_EXCEPTION; | ||
698 | |||
699 | writel(tmp, nfc->regs + NFC_REG_ECC_CTL); | ||
700 | |||
701 | for (i = 0; i < ecc->steps; i++) { | ||
702 | chip->read_buf(mtd, NULL, ecc->size); | ||
703 | |||
704 | tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | (1 << 30); | ||
705 | writel(tmp, nfc->regs + NFC_REG_CMD); | ||
706 | |||
707 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | ||
708 | if (ret) | ||
709 | return ret; | ||
710 | |||
711 | memcpy_fromio(buf, nfc->regs + NFC_RAM0_BASE, ecc->size); | ||
712 | buf += ecc->size; | ||
713 | offset += ecc->size; | ||
714 | |||
715 | if (readl(nfc->regs + NFC_REG_ECC_ST) & 0x1) { | ||
716 | mtd->ecc_stats.failed++; | ||
717 | } else { | ||
718 | tmp = readl(nfc->regs + NFC_REG_ECC_CNT0) & 0xff; | ||
719 | mtd->ecc_stats.corrected += tmp; | ||
720 | max_bitflips = max_t(unsigned int, max_bitflips, tmp); | ||
721 | } | ||
722 | |||
723 | if (oob_required) { | ||
724 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1); | ||
725 | chip->read_buf(mtd, oob, ecc->bytes + ecc->prepad); | ||
726 | oob += ecc->bytes + ecc->prepad; | ||
727 | } | ||
728 | |||
729 | offset += ecc->bytes + ecc->prepad; | ||
730 | } | ||
731 | |||
732 | if (oob_required) { | ||
733 | cnt = mtd->oobsize - (oob - chip->oob_poi); | ||
734 | if (cnt > 0) { | ||
735 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1); | ||
736 | chip->read_buf(mtd, oob, cnt); | ||
737 | } | ||
738 | } | ||
739 | |||
740 | writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN, | ||
741 | nfc->regs + NFC_REG_ECC_CTL); | ||
742 | |||
743 | return max_bitflips; | ||
744 | } | ||
745 | |||
746 | static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd, | ||
747 | struct nand_chip *chip, | ||
748 | const uint8_t *buf, | ||
749 | int oob_required) | ||
750 | { | ||
751 | struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller); | ||
752 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
753 | struct sunxi_nand_hw_ecc *data = ecc->priv; | ||
754 | uint8_t *oob = chip->oob_poi; | ||
755 | int offset = 0; | ||
756 | int ret; | ||
757 | int cnt; | ||
758 | u32 tmp; | ||
759 | int i; | ||
760 | |||
761 | tmp = readl(nfc->regs + NFC_REG_ECC_CTL); | ||
762 | tmp &= ~(NFC_ECC_MODE | NFC_ECC_PIPELINE | NFC_ECC_BLOCK_SIZE); | ||
763 | tmp |= NFC_ECC_EN | (data->mode << NFC_ECC_MODE_SHIFT) | | ||
764 | NFC_ECC_EXCEPTION; | ||
765 | |||
766 | writel(tmp, nfc->regs + NFC_REG_ECC_CTL); | ||
767 | |||
768 | for (i = 0; i < ecc->steps; i++) { | ||
769 | chip->write_buf(mtd, buf + (i * ecc->size), ecc->size); | ||
770 | offset += ecc->size; | ||
771 | |||
772 | /* Fill OOB data in */ | ||
773 | if (oob_required) { | ||
774 | tmp = 0xffffffff; | ||
775 | memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, &tmp, | ||
776 | 4); | ||
777 | } else { | ||
778 | memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, oob, | ||
779 | 4); | ||
780 | } | ||
781 | |||
782 | tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | | ||
783 | (1 << 30); | ||
784 | writel(tmp, nfc->regs + NFC_REG_CMD); | ||
785 | |||
786 | ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); | ||
787 | if (ret) | ||
788 | return ret; | ||
789 | |||
790 | offset += ecc->bytes + ecc->prepad; | ||
791 | oob += ecc->bytes + ecc->prepad; | ||
792 | } | ||
793 | |||
794 | if (oob_required) { | ||
795 | cnt = mtd->oobsize - (oob - chip->oob_poi); | ||
796 | if (cnt > 0) { | ||
797 | chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset, -1); | ||
798 | chip->write_buf(mtd, oob, cnt); | ||
799 | } | ||
800 | } | ||
801 | |||
802 | tmp = readl(nfc->regs + NFC_REG_ECC_CTL); | ||
803 | tmp &= ~NFC_ECC_EN; | ||
804 | |||
805 | writel(tmp, nfc->regs + NFC_REG_ECC_CTL); | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, | ||
811 | const struct nand_sdr_timings *timings) | ||
812 | { | ||
813 | u32 min_clk_period = 0; | ||
814 | |||
815 | /* T1 <=> tCLS */ | ||
816 | if (timings->tCLS_min > min_clk_period) | ||
817 | min_clk_period = timings->tCLS_min; | ||
818 | |||
819 | /* T2 <=> tCLH */ | ||
820 | if (timings->tCLH_min > min_clk_period) | ||
821 | min_clk_period = timings->tCLH_min; | ||
822 | |||
823 | /* T3 <=> tCS */ | ||
824 | if (timings->tCS_min > min_clk_period) | ||
825 | min_clk_period = timings->tCS_min; | ||
826 | |||
827 | /* T4 <=> tCH */ | ||
828 | if (timings->tCH_min > min_clk_period) | ||
829 | min_clk_period = timings->tCH_min; | ||
830 | |||
831 | /* T5 <=> tWP */ | ||
832 | if (timings->tWP_min > min_clk_period) | ||
833 | min_clk_period = timings->tWP_min; | ||
834 | |||
835 | /* T6 <=> tWH */ | ||
836 | if (timings->tWH_min > min_clk_period) | ||
837 | min_clk_period = timings->tWH_min; | ||
838 | |||
839 | /* T7 <=> tALS */ | ||
840 | if (timings->tALS_min > min_clk_period) | ||
841 | min_clk_period = timings->tALS_min; | ||
842 | |||
843 | /* T8 <=> tDS */ | ||
844 | if (timings->tDS_min > min_clk_period) | ||
845 | min_clk_period = timings->tDS_min; | ||
846 | |||
847 | /* T9 <=> tDH */ | ||
848 | if (timings->tDH_min > min_clk_period) | ||
849 | min_clk_period = timings->tDH_min; | ||
850 | |||
851 | /* T10 <=> tRR */ | ||
852 | if (timings->tRR_min > (min_clk_period * 3)) | ||
853 | min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3); | ||
854 | |||
855 | /* T11 <=> tALH */ | ||
856 | if (timings->tALH_min > min_clk_period) | ||
857 | min_clk_period = timings->tALH_min; | ||
858 | |||
859 | /* T12 <=> tRP */ | ||
860 | if (timings->tRP_min > min_clk_period) | ||
861 | min_clk_period = timings->tRP_min; | ||
862 | |||
863 | /* T13 <=> tREH */ | ||
864 | if (timings->tREH_min > min_clk_period) | ||
865 | min_clk_period = timings->tREH_min; | ||
866 | |||
867 | /* T14 <=> tRC */ | ||
868 | if (timings->tRC_min > (min_clk_period * 2)) | ||
869 | min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2); | ||
870 | |||
871 | /* T15 <=> tWC */ | ||
872 | if (timings->tWC_min > (min_clk_period * 2)) | ||
873 | min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2); | ||
874 | |||
875 | |||
876 | /* Convert min_clk_period from picoseconds to nanoseconds */ | ||
877 | min_clk_period = DIV_ROUND_UP(min_clk_period, 1000); | ||
878 | |||
879 | /* | ||
880 | * Convert min_clk_period into a clk frequency, then get the | ||
881 | * appropriate rate for the NAND controller IP given this formula | ||
882 | * (specified in the datasheet): | ||
883 | * nand clk_rate = 2 * min_clk_rate | ||
884 | */ | ||
885 | chip->clk_rate = (2 * NSEC_PER_SEC) / min_clk_period; | ||
886 | |||
887 | /* TODO: configure T16-T19 */ | ||
888 | |||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip, | ||
893 | struct device_node *np) | ||
894 | { | ||
895 | const struct nand_sdr_timings *timings; | ||
896 | int ret; | ||
897 | int mode; | ||
898 | |||
899 | mode = onfi_get_async_timing_mode(&chip->nand); | ||
900 | if (mode == ONFI_TIMING_MODE_UNKNOWN) { | ||
901 | mode = chip->nand.onfi_timing_mode_default; | ||
902 | } else { | ||
903 | uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {}; | ||
904 | |||
905 | mode = fls(mode) - 1; | ||
906 | if (mode < 0) | ||
907 | mode = 0; | ||
908 | |||
909 | feature[0] = mode; | ||
910 | ret = chip->nand.onfi_set_features(&chip->mtd, &chip->nand, | ||
911 | ONFI_FEATURE_ADDR_TIMING_MODE, | ||
912 | feature); | ||
913 | if (ret) | ||
914 | return ret; | ||
915 | } | ||
916 | |||
917 | timings = onfi_async_timing_mode_to_sdr_timings(mode); | ||
918 | if (IS_ERR(timings)) | ||
919 | return PTR_ERR(timings); | ||
920 | |||
921 | return sunxi_nand_chip_set_timings(chip, timings); | ||
922 | } | ||
923 | |||
924 | static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, | ||
925 | struct nand_ecc_ctrl *ecc, | ||
926 | struct device_node *np) | ||
927 | { | ||
928 | static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 }; | ||
929 | struct nand_chip *nand = mtd->priv; | ||
930 | struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); | ||
931 | struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); | ||
932 | struct sunxi_nand_hw_ecc *data; | ||
933 | struct nand_ecclayout *layout; | ||
934 | int nsectors; | ||
935 | int ret; | ||
936 | int i; | ||
937 | |||
938 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
939 | if (!data) | ||
940 | return -ENOMEM; | ||
941 | |||
942 | /* Add ECC info retrieval from DT */ | ||
943 | for (i = 0; i < ARRAY_SIZE(strengths); i++) { | ||
944 | if (ecc->strength <= strengths[i]) | ||
945 | break; | ||
946 | } | ||
947 | |||
948 | if (i >= ARRAY_SIZE(strengths)) { | ||
949 | dev_err(nfc->dev, "unsupported strength\n"); | ||
950 | ret = -ENOTSUPP; | ||
951 | goto err; | ||
952 | } | ||
953 | |||
954 | data->mode = i; | ||
955 | |||
956 | /* HW ECC always request ECC bytes for 1024 bytes blocks */ | ||
957 | ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8); | ||
958 | |||
959 | /* HW ECC always work with even numbers of ECC bytes */ | ||
960 | ecc->bytes = ALIGN(ecc->bytes, 2); | ||
961 | |||
962 | layout = &data->layout; | ||
963 | nsectors = mtd->writesize / ecc->size; | ||
964 | |||
965 | if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) { | ||
966 | ret = -EINVAL; | ||
967 | goto err; | ||
968 | } | ||
969 | |||
970 | layout->eccbytes = (ecc->bytes * nsectors); | ||
971 | |||
972 | ecc->layout = layout; | ||
973 | ecc->priv = data; | ||
974 | |||
975 | return 0; | ||
976 | |||
977 | err: | ||
978 | kfree(data); | ||
979 | |||
980 | return ret; | ||
981 | } | ||
982 | |||
983 | static void sunxi_nand_hw_common_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc) | ||
984 | { | ||
985 | kfree(ecc->priv); | ||
986 | } | ||
987 | |||
988 | static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, | ||
989 | struct nand_ecc_ctrl *ecc, | ||
990 | struct device_node *np) | ||
991 | { | ||
992 | struct nand_ecclayout *layout; | ||
993 | int nsectors; | ||
994 | int i, j; | ||
995 | int ret; | ||
996 | |||
997 | ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np); | ||
998 | if (ret) | ||
999 | return ret; | ||
1000 | |||
1001 | ecc->read_page = sunxi_nfc_hw_ecc_read_page; | ||
1002 | ecc->write_page = sunxi_nfc_hw_ecc_write_page; | ||
1003 | layout = ecc->layout; | ||
1004 | nsectors = mtd->writesize / ecc->size; | ||
1005 | |||
1006 | for (i = 0; i < nsectors; i++) { | ||
1007 | if (i) { | ||
1008 | layout->oobfree[i].offset = | ||
1009 | layout->oobfree[i - 1].offset + | ||
1010 | layout->oobfree[i - 1].length + | ||
1011 | ecc->bytes; | ||
1012 | layout->oobfree[i].length = 4; | ||
1013 | } else { | ||
1014 | /* | ||
1015 | * The first 2 bytes are used for BB markers, hence we | ||
1016 | * only have 2 bytes available in the first user data | ||
1017 | * section. | ||
1018 | */ | ||
1019 | layout->oobfree[i].length = 2; | ||
1020 | layout->oobfree[i].offset = 2; | ||
1021 | } | ||
1022 | |||
1023 | for (j = 0; j < ecc->bytes; j++) | ||
1024 | layout->eccpos[(ecc->bytes * i) + j] = | ||
1025 | layout->oobfree[i].offset + | ||
1026 | layout->oobfree[i].length + j; | ||
1027 | } | ||
1028 | |||
1029 | if (mtd->oobsize > (ecc->bytes + 4) * nsectors) { | ||
1030 | layout->oobfree[nsectors].offset = | ||
1031 | layout->oobfree[nsectors - 1].offset + | ||
1032 | layout->oobfree[nsectors - 1].length + | ||
1033 | ecc->bytes; | ||
1034 | layout->oobfree[nsectors].length = mtd->oobsize - | ||
1035 | ((ecc->bytes + 4) * nsectors); | ||
1036 | } | ||
1037 | |||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1041 | static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd, | ||
1042 | struct nand_ecc_ctrl *ecc, | ||
1043 | struct device_node *np) | ||
1044 | { | ||
1045 | struct nand_ecclayout *layout; | ||
1046 | int nsectors; | ||
1047 | int i; | ||
1048 | int ret; | ||
1049 | |||
1050 | ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np); | ||
1051 | if (ret) | ||
1052 | return ret; | ||
1053 | |||
1054 | ecc->prepad = 4; | ||
1055 | ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page; | ||
1056 | ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page; | ||
1057 | |||
1058 | layout = ecc->layout; | ||
1059 | nsectors = mtd->writesize / ecc->size; | ||
1060 | |||
1061 | for (i = 0; i < (ecc->bytes * nsectors); i++) | ||
1062 | layout->eccpos[i] = i; | ||
1063 | |||
1064 | layout->oobfree[0].length = mtd->oobsize - i; | ||
1065 | layout->oobfree[0].offset = i; | ||
1066 | |||
1067 | return 0; | ||
1068 | } | ||
1069 | |||
1070 | static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc) | ||
1071 | { | ||
1072 | switch (ecc->mode) { | ||
1073 | case NAND_ECC_HW: | ||
1074 | case NAND_ECC_HW_SYNDROME: | ||
1075 | sunxi_nand_hw_common_ecc_ctrl_cleanup(ecc); | ||
1076 | break; | ||
1077 | case NAND_ECC_NONE: | ||
1078 | kfree(ecc->layout); | ||
1079 | default: | ||
1080 | break; | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc, | ||
1085 | struct device_node *np) | ||
1086 | { | ||
1087 | struct nand_chip *nand = mtd->priv; | ||
1088 | int strength; | ||
1089 | int blk_size; | ||
1090 | int ret; | ||
1091 | |||
1092 | blk_size = of_get_nand_ecc_step_size(np); | ||
1093 | strength = of_get_nand_ecc_strength(np); | ||
1094 | if (blk_size > 0 && strength > 0) { | ||
1095 | ecc->size = blk_size; | ||
1096 | ecc->strength = strength; | ||
1097 | } else { | ||
1098 | ecc->size = nand->ecc_step_ds; | ||
1099 | ecc->strength = nand->ecc_strength_ds; | ||
1100 | } | ||
1101 | |||
1102 | if (!ecc->size || !ecc->strength) | ||
1103 | return -EINVAL; | ||
1104 | |||
1105 | ecc->mode = NAND_ECC_HW; | ||
1106 | |||
1107 | ret = of_get_nand_ecc_mode(np); | ||
1108 | if (ret >= 0) | ||
1109 | ecc->mode = ret; | ||
1110 | |||
1111 | switch (ecc->mode) { | ||
1112 | case NAND_ECC_SOFT_BCH: | ||
1113 | ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * ecc->size), | ||
1114 | 8); | ||
1115 | break; | ||
1116 | case NAND_ECC_HW: | ||
1117 | ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np); | ||
1118 | if (ret) | ||
1119 | return ret; | ||
1120 | break; | ||
1121 | case NAND_ECC_HW_SYNDROME: | ||
1122 | ret = sunxi_nand_hw_syndrome_ecc_ctrl_init(mtd, ecc, np); | ||
1123 | if (ret) | ||
1124 | return ret; | ||
1125 | break; | ||
1126 | case NAND_ECC_NONE: | ||
1127 | ecc->layout = kzalloc(sizeof(*ecc->layout), GFP_KERNEL); | ||
1128 | if (!ecc->layout) | ||
1129 | return -ENOMEM; | ||
1130 | ecc->layout->oobfree[0].length = mtd->oobsize; | ||
1131 | case NAND_ECC_SOFT: | ||
1132 | break; | ||
1133 | default: | ||
1134 | return -EINVAL; | ||
1135 | } | ||
1136 | |||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, | ||
1141 | struct device_node *np) | ||
1142 | { | ||
1143 | const struct nand_sdr_timings *timings; | ||
1144 | struct sunxi_nand_chip *chip; | ||
1145 | struct mtd_part_parser_data ppdata; | ||
1146 | struct mtd_info *mtd; | ||
1147 | struct nand_chip *nand; | ||
1148 | int nsels; | ||
1149 | int ret; | ||
1150 | int i; | ||
1151 | u32 tmp; | ||
1152 | |||
1153 | if (!of_get_property(np, "reg", &nsels)) | ||
1154 | return -EINVAL; | ||
1155 | |||
1156 | nsels /= sizeof(u32); | ||
1157 | if (!nsels) { | ||
1158 | dev_err(dev, "invalid reg property size\n"); | ||
1159 | return -EINVAL; | ||
1160 | } | ||
1161 | |||
1162 | chip = devm_kzalloc(dev, | ||
1163 | sizeof(*chip) + | ||
1164 | (nsels * sizeof(struct sunxi_nand_chip_sel)), | ||
1165 | GFP_KERNEL); | ||
1166 | if (!chip) { | ||
1167 | dev_err(dev, "could not allocate chip\n"); | ||
1168 | return -ENOMEM; | ||
1169 | } | ||
1170 | |||
1171 | chip->nsels = nsels; | ||
1172 | chip->selected = -1; | ||
1173 | |||
1174 | for (i = 0; i < nsels; i++) { | ||
1175 | ret = of_property_read_u32_index(np, "reg", i, &tmp); | ||
1176 | if (ret) { | ||
1177 | dev_err(dev, "could not retrieve reg property: %d\n", | ||
1178 | ret); | ||
1179 | return ret; | ||
1180 | } | ||
1181 | |||
1182 | if (tmp > NFC_MAX_CS) { | ||
1183 | dev_err(dev, | ||
1184 | "invalid reg value: %u (max CS = 7)\n", | ||
1185 | tmp); | ||
1186 | return -EINVAL; | ||
1187 | } | ||
1188 | |||
1189 | if (test_and_set_bit(tmp, &nfc->assigned_cs)) { | ||
1190 | dev_err(dev, "CS %d already assigned\n", tmp); | ||
1191 | return -EINVAL; | ||
1192 | } | ||
1193 | |||
1194 | chip->sels[i].cs = tmp; | ||
1195 | |||
1196 | if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) && | ||
1197 | tmp < 2) { | ||
1198 | chip->sels[i].rb.type = RB_NATIVE; | ||
1199 | chip->sels[i].rb.info.nativeid = tmp; | ||
1200 | } else { | ||
1201 | ret = of_get_named_gpio(np, "rb-gpios", i); | ||
1202 | if (ret >= 0) { | ||
1203 | tmp = ret; | ||
1204 | chip->sels[i].rb.type = RB_GPIO; | ||
1205 | chip->sels[i].rb.info.gpio = tmp; | ||
1206 | ret = devm_gpio_request(dev, tmp, "nand-rb"); | ||
1207 | if (ret) | ||
1208 | return ret; | ||
1209 | |||
1210 | ret = gpio_direction_input(tmp); | ||
1211 | if (ret) | ||
1212 | return ret; | ||
1213 | } else { | ||
1214 | chip->sels[i].rb.type = RB_NONE; | ||
1215 | } | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | timings = onfi_async_timing_mode_to_sdr_timings(0); | ||
1220 | if (IS_ERR(timings)) { | ||
1221 | ret = PTR_ERR(timings); | ||
1222 | dev_err(dev, | ||
1223 | "could not retrieve timings for ONFI mode 0: %d\n", | ||
1224 | ret); | ||
1225 | return ret; | ||
1226 | } | ||
1227 | |||
1228 | ret = sunxi_nand_chip_set_timings(chip, timings); | ||
1229 | if (ret) { | ||
1230 | dev_err(dev, "could not configure chip timings: %d\n", ret); | ||
1231 | return ret; | ||
1232 | } | ||
1233 | |||
1234 | nand = &chip->nand; | ||
1235 | /* Default tR value specified in the ONFI spec (chapter 4.15.1) */ | ||
1236 | nand->chip_delay = 200; | ||
1237 | nand->controller = &nfc->controller; | ||
1238 | nand->select_chip = sunxi_nfc_select_chip; | ||
1239 | nand->cmd_ctrl = sunxi_nfc_cmd_ctrl; | ||
1240 | nand->read_buf = sunxi_nfc_read_buf; | ||
1241 | nand->write_buf = sunxi_nfc_write_buf; | ||
1242 | nand->read_byte = sunxi_nfc_read_byte; | ||
1243 | |||
1244 | if (of_get_nand_on_flash_bbt(np)) | ||
1245 | nand->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; | ||
1246 | |||
1247 | mtd = &chip->mtd; | ||
1248 | mtd->dev.parent = dev; | ||
1249 | mtd->priv = nand; | ||
1250 | mtd->owner = THIS_MODULE; | ||
1251 | |||
1252 | ret = nand_scan_ident(mtd, nsels, NULL); | ||
1253 | if (ret) | ||
1254 | return ret; | ||
1255 | |||
1256 | ret = sunxi_nand_chip_init_timings(chip, np); | ||
1257 | if (ret) { | ||
1258 | dev_err(dev, "could not configure chip timings: %d\n", ret); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | ret = sunxi_nand_ecc_init(mtd, &nand->ecc, np); | ||
1263 | if (ret) { | ||
1264 | dev_err(dev, "ECC init failed: %d\n", ret); | ||
1265 | return ret; | ||
1266 | } | ||
1267 | |||
1268 | ret = nand_scan_tail(mtd); | ||
1269 | if (ret) { | ||
1270 | dev_err(dev, "nand_scan_tail failed: %d\n", ret); | ||
1271 | return ret; | ||
1272 | } | ||
1273 | |||
1274 | ppdata.of_node = np; | ||
1275 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); | ||
1276 | if (ret) { | ||
1277 | dev_err(dev, "failed to register mtd device: %d\n", ret); | ||
1278 | nand_release(mtd); | ||
1279 | return ret; | ||
1280 | } | ||
1281 | |||
1282 | list_add_tail(&chip->node, &nfc->chips); | ||
1283 | |||
1284 | return 0; | ||
1285 | } | ||
1286 | |||
1287 | static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc) | ||
1288 | { | ||
1289 | struct device_node *np = dev->of_node; | ||
1290 | struct device_node *nand_np; | ||
1291 | int nchips = of_get_child_count(np); | ||
1292 | int ret; | ||
1293 | |||
1294 | if (nchips > 8) { | ||
1295 | dev_err(dev, "too many NAND chips: %d (max = 8)\n", nchips); | ||
1296 | return -EINVAL; | ||
1297 | } | ||
1298 | |||
1299 | for_each_child_of_node(np, nand_np) { | ||
1300 | ret = sunxi_nand_chip_init(dev, nfc, nand_np); | ||
1301 | if (ret) | ||
1302 | return ret; | ||
1303 | } | ||
1304 | |||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc) | ||
1309 | { | ||
1310 | struct sunxi_nand_chip *chip; | ||
1311 | |||
1312 | while (!list_empty(&nfc->chips)) { | ||
1313 | chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip, | ||
1314 | node); | ||
1315 | nand_release(&chip->mtd); | ||
1316 | sunxi_nand_ecc_cleanup(&chip->nand.ecc); | ||
1317 | } | ||
1318 | } | ||
1319 | |||
1320 | static int sunxi_nfc_probe(struct platform_device *pdev) | ||
1321 | { | ||
1322 | struct device *dev = &pdev->dev; | ||
1323 | struct resource *r; | ||
1324 | struct sunxi_nfc *nfc; | ||
1325 | int irq; | ||
1326 | int ret; | ||
1327 | |||
1328 | nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); | ||
1329 | if (!nfc) | ||
1330 | return -ENOMEM; | ||
1331 | |||
1332 | nfc->dev = dev; | ||
1333 | spin_lock_init(&nfc->controller.lock); | ||
1334 | init_waitqueue_head(&nfc->controller.wq); | ||
1335 | INIT_LIST_HEAD(&nfc->chips); | ||
1336 | |||
1337 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1338 | nfc->regs = devm_ioremap_resource(dev, r); | ||
1339 | if (IS_ERR(nfc->regs)) | ||
1340 | return PTR_ERR(nfc->regs); | ||
1341 | |||
1342 | irq = platform_get_irq(pdev, 0); | ||
1343 | if (irq < 0) { | ||
1344 | dev_err(dev, "failed to retrieve irq\n"); | ||
1345 | return irq; | ||
1346 | } | ||
1347 | |||
1348 | nfc->ahb_clk = devm_clk_get(dev, "ahb"); | ||
1349 | if (IS_ERR(nfc->ahb_clk)) { | ||
1350 | dev_err(dev, "failed to retrieve ahb clk\n"); | ||
1351 | return PTR_ERR(nfc->ahb_clk); | ||
1352 | } | ||
1353 | |||
1354 | ret = clk_prepare_enable(nfc->ahb_clk); | ||
1355 | if (ret) | ||
1356 | return ret; | ||
1357 | |||
1358 | nfc->mod_clk = devm_clk_get(dev, "mod"); | ||
1359 | if (IS_ERR(nfc->mod_clk)) { | ||
1360 | dev_err(dev, "failed to retrieve mod clk\n"); | ||
1361 | ret = PTR_ERR(nfc->mod_clk); | ||
1362 | goto out_ahb_clk_unprepare; | ||
1363 | } | ||
1364 | |||
1365 | ret = clk_prepare_enable(nfc->mod_clk); | ||
1366 | if (ret) | ||
1367 | goto out_ahb_clk_unprepare; | ||
1368 | |||
1369 | ret = sunxi_nfc_rst(nfc); | ||
1370 | if (ret) | ||
1371 | goto out_mod_clk_unprepare; | ||
1372 | |||
1373 | writel(0, nfc->regs + NFC_REG_INT); | ||
1374 | ret = devm_request_irq(dev, irq, sunxi_nfc_interrupt, | ||
1375 | 0, "sunxi-nand", nfc); | ||
1376 | if (ret) | ||
1377 | goto out_mod_clk_unprepare; | ||
1378 | |||
1379 | platform_set_drvdata(pdev, nfc); | ||
1380 | |||
1381 | /* | ||
1382 | * TODO: replace these magic values with proper flags as soon as we | ||
1383 | * know what they are encoding. | ||
1384 | */ | ||
1385 | writel(0x100, nfc->regs + NFC_REG_TIMING_CTL); | ||
1386 | writel(0x7ff, nfc->regs + NFC_REG_TIMING_CFG); | ||
1387 | |||
1388 | ret = sunxi_nand_chips_init(dev, nfc); | ||
1389 | if (ret) { | ||
1390 | dev_err(dev, "failed to init nand chips\n"); | ||
1391 | goto out_mod_clk_unprepare; | ||
1392 | } | ||
1393 | |||
1394 | return 0; | ||
1395 | |||
1396 | out_mod_clk_unprepare: | ||
1397 | clk_disable_unprepare(nfc->mod_clk); | ||
1398 | out_ahb_clk_unprepare: | ||
1399 | clk_disable_unprepare(nfc->ahb_clk); | ||
1400 | |||
1401 | return ret; | ||
1402 | } | ||
1403 | |||
1404 | static int sunxi_nfc_remove(struct platform_device *pdev) | ||
1405 | { | ||
1406 | struct sunxi_nfc *nfc = platform_get_drvdata(pdev); | ||
1407 | |||
1408 | sunxi_nand_chips_cleanup(nfc); | ||
1409 | |||
1410 | return 0; | ||
1411 | } | ||
1412 | |||
1413 | static const struct of_device_id sunxi_nfc_ids[] = { | ||
1414 | { .compatible = "allwinner,sun4i-a10-nand" }, | ||
1415 | { /* sentinel */ } | ||
1416 | }; | ||
1417 | MODULE_DEVICE_TABLE(of, sunxi_nfc_ids); | ||
1418 | |||
1419 | static struct platform_driver sunxi_nfc_driver = { | ||
1420 | .driver = { | ||
1421 | .name = "sunxi_nand", | ||
1422 | .of_match_table = sunxi_nfc_ids, | ||
1423 | }, | ||
1424 | .probe = sunxi_nfc_probe, | ||
1425 | .remove = sunxi_nfc_remove, | ||
1426 | }; | ||
1427 | module_platform_driver(sunxi_nfc_driver); | ||
1428 | |||
1429 | MODULE_LICENSE("GPL v2"); | ||
1430 | MODULE_AUTHOR("Boris BREZILLON"); | ||
1431 | MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver"); | ||
1432 | MODULE_ALIAS("platform:sunxi_nand"); | ||
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 2fb07eced2ba..39763b94f67d 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c | |||
@@ -719,16 +719,10 @@ static int fsl_qspi_read(struct spi_nor *nor, loff_t from, | |||
719 | { | 719 | { |
720 | struct fsl_qspi *q = nor->priv; | 720 | struct fsl_qspi *q = nor->priv; |
721 | u8 cmd = nor->read_opcode; | 721 | u8 cmd = nor->read_opcode; |
722 | int ret; | ||
723 | 722 | ||
724 | dev_dbg(q->dev, "cmd [%x],read from (0x%p, 0x%.8x, 0x%.8x),len:%d\n", | 723 | dev_dbg(q->dev, "cmd [%x],read from (0x%p, 0x%.8x, 0x%.8x),len:%d\n", |
725 | cmd, q->ahb_base, q->chip_base_addr, (unsigned int)from, len); | 724 | cmd, q->ahb_base, q->chip_base_addr, (unsigned int)from, len); |
726 | 725 | ||
727 | /* Wait until the previous command is finished. */ | ||
728 | ret = nor->wait_till_ready(nor); | ||
729 | if (ret) | ||
730 | return ret; | ||
731 | |||
732 | /* Read out the data directly from the AHB buffer.*/ | 726 | /* Read out the data directly from the AHB buffer.*/ |
733 | memcpy(buf, q->ahb_base + q->chip_base_addr + from, len); | 727 | memcpy(buf, q->ahb_base + q->chip_base_addr + from, len); |
734 | 728 | ||
@@ -744,16 +738,6 @@ static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs) | |||
744 | dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n", | 738 | dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n", |
745 | nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs); | 739 | nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs); |
746 | 740 | ||
747 | /* Wait until finished previous write command. */ | ||
748 | ret = nor->wait_till_ready(nor); | ||
749 | if (ret) | ||
750 | return ret; | ||
751 | |||
752 | /* Send write enable, then erase commands. */ | ||
753 | ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); | ||
754 | if (ret) | ||
755 | return ret; | ||
756 | |||
757 | ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0); | 741 | ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0); |
758 | if (ret) | 742 | if (ret) |
759 | return ret; | 743 | return ret; |
@@ -849,9 +833,8 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
849 | 833 | ||
850 | ret = clk_prepare_enable(q->clk); | 834 | ret = clk_prepare_enable(q->clk); |
851 | if (ret) { | 835 | if (ret) { |
852 | clk_disable_unprepare(q->clk_en); | ||
853 | dev_err(dev, "can not enable the qspi clock\n"); | 836 | dev_err(dev, "can not enable the qspi clock\n"); |
854 | goto map_failed; | 837 | goto clk_failed; |
855 | } | 838 | } |
856 | 839 | ||
857 | /* find the irq */ | 840 | /* find the irq */ |
@@ -905,7 +888,8 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
905 | nor->prepare = fsl_qspi_prep; | 888 | nor->prepare = fsl_qspi_prep; |
906 | nor->unprepare = fsl_qspi_unprep; | 889 | nor->unprepare = fsl_qspi_unprep; |
907 | 890 | ||
908 | if (of_modalias_node(np, modalias, sizeof(modalias)) < 0) | 891 | ret = of_modalias_node(np, modalias, sizeof(modalias)); |
892 | if (ret < 0) | ||
909 | goto map_failed; | 893 | goto map_failed; |
910 | 894 | ||
911 | ret = of_property_read_u32(np, "spi-max-frequency", | 895 | ret = of_property_read_u32(np, "spi-max-frequency", |
@@ -964,6 +948,7 @@ last_init_failed: | |||
964 | 948 | ||
965 | irq_failed: | 949 | irq_failed: |
966 | clk_disable_unprepare(q->clk); | 950 | clk_disable_unprepare(q->clk); |
951 | clk_failed: | ||
967 | clk_disable_unprepare(q->clk_en); | 952 | clk_disable_unprepare(q->clk_en); |
968 | map_failed: | 953 | map_failed: |
969 | dev_err(dev, "Freescale QuadSPI probe failed\n"); | 954 | dev_err(dev, "Freescale QuadSPI probe failed\n"); |
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index c51ee52386a7..0f8ec3c2d015 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
@@ -26,7 +26,38 @@ | |||
26 | /* Define max times to check status register before we give up. */ | 26 | /* Define max times to check status register before we give up. */ |
27 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ | 27 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ |
28 | 28 | ||
29 | #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) | 29 | #define SPI_NOR_MAX_ID_LEN 6 |
30 | |||
31 | struct flash_info { | ||
32 | /* | ||
33 | * This array stores the ID bytes. | ||
34 | * The first three bytes are the JEDIC ID. | ||
35 | * JEDEC ID zero means "no ID" (mostly older chips). | ||
36 | */ | ||
37 | u8 id[SPI_NOR_MAX_ID_LEN]; | ||
38 | u8 id_len; | ||
39 | |||
40 | /* The size listed here is what works with SPINOR_OP_SE, which isn't | ||
41 | * necessarily called a "sector" by the vendor. | ||
42 | */ | ||
43 | unsigned sector_size; | ||
44 | u16 n_sectors; | ||
45 | |||
46 | u16 page_size; | ||
47 | u16 addr_width; | ||
48 | |||
49 | u16 flags; | ||
50 | #define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ | ||
51 | #define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ | ||
52 | #define SST_WRITE 0x04 /* use SST byte programming */ | ||
53 | #define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ | ||
54 | #define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ | ||
55 | #define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ | ||
56 | #define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ | ||
57 | #define USE_FSR 0x80 /* use flag status register */ | ||
58 | }; | ||
59 | |||
60 | #define JEDEC_MFR(info) ((info)->id[0]) | ||
30 | 61 | ||
31 | static const struct spi_device_id *spi_nor_match_id(const char *name); | 62 | static const struct spi_device_id *spi_nor_match_id(const char *name); |
32 | 63 | ||
@@ -98,7 +129,7 @@ static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) | |||
98 | case SPI_NOR_FAST: | 129 | case SPI_NOR_FAST: |
99 | case SPI_NOR_DUAL: | 130 | case SPI_NOR_DUAL: |
100 | case SPI_NOR_QUAD: | 131 | case SPI_NOR_QUAD: |
101 | return 1; | 132 | return 8; |
102 | case SPI_NOR_NORMAL: | 133 | case SPI_NOR_NORMAL: |
103 | return 0; | 134 | return 0; |
104 | } | 135 | } |
@@ -138,13 +169,14 @@ static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) | |||
138 | } | 169 | } |
139 | 170 | ||
140 | /* Enable/disable 4-byte addressing mode. */ | 171 | /* Enable/disable 4-byte addressing mode. */ |
141 | static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) | 172 | static inline int set_4byte(struct spi_nor *nor, struct flash_info *info, |
173 | int enable) | ||
142 | { | 174 | { |
143 | int status; | 175 | int status; |
144 | bool need_wren = false; | 176 | bool need_wren = false; |
145 | u8 cmd; | 177 | u8 cmd; |
146 | 178 | ||
147 | switch (JEDEC_MFR(jedec_id)) { | 179 | switch (JEDEC_MFR(info)) { |
148 | case CFI_MFR_ST: /* Micron, actually */ | 180 | case CFI_MFR_ST: /* Micron, actually */ |
149 | /* Some Micron need WREN command; all will accept it */ | 181 | /* Some Micron need WREN command; all will accept it */ |
150 | need_wren = true; | 182 | need_wren = true; |
@@ -165,81 +197,74 @@ static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) | |||
165 | return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); | 197 | return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); |
166 | } | 198 | } |
167 | } | 199 | } |
168 | 200 | static inline int spi_nor_sr_ready(struct spi_nor *nor) | |
169 | static int spi_nor_wait_till_ready(struct spi_nor *nor) | ||
170 | { | 201 | { |
171 | unsigned long deadline; | 202 | int sr = read_sr(nor); |
172 | int sr; | 203 | if (sr < 0) |
173 | 204 | return sr; | |
174 | deadline = jiffies + MAX_READY_WAIT_JIFFIES; | 205 | else |
175 | 206 | return !(sr & SR_WIP); | |
176 | do { | 207 | } |
177 | cond_resched(); | ||
178 | 208 | ||
179 | sr = read_sr(nor); | 209 | static inline int spi_nor_fsr_ready(struct spi_nor *nor) |
180 | if (sr < 0) | 210 | { |
181 | break; | 211 | int fsr = read_fsr(nor); |
182 | else if (!(sr & SR_WIP)) | 212 | if (fsr < 0) |
183 | return 0; | 213 | return fsr; |
184 | } while (!time_after_eq(jiffies, deadline)); | 214 | else |
215 | return fsr & FSR_READY; | ||
216 | } | ||
185 | 217 | ||
186 | return -ETIMEDOUT; | 218 | static int spi_nor_ready(struct spi_nor *nor) |
219 | { | ||
220 | int sr, fsr; | ||
221 | sr = spi_nor_sr_ready(nor); | ||
222 | if (sr < 0) | ||
223 | return sr; | ||
224 | fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; | ||
225 | if (fsr < 0) | ||
226 | return fsr; | ||
227 | return sr && fsr; | ||
187 | } | 228 | } |
188 | 229 | ||
189 | static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) | 230 | /* |
231 | * Service routine to read status register until ready, or timeout occurs. | ||
232 | * Returns non-zero if error. | ||
233 | */ | ||
234 | static int spi_nor_wait_till_ready(struct spi_nor *nor) | ||
190 | { | 235 | { |
191 | unsigned long deadline; | 236 | unsigned long deadline; |
192 | int sr; | 237 | int timeout = 0, ret; |
193 | int fsr; | ||
194 | 238 | ||
195 | deadline = jiffies + MAX_READY_WAIT_JIFFIES; | 239 | deadline = jiffies + MAX_READY_WAIT_JIFFIES; |
196 | 240 | ||
197 | do { | 241 | while (!timeout) { |
242 | if (time_after_eq(jiffies, deadline)) | ||
243 | timeout = 1; | ||
244 | |||
245 | ret = spi_nor_ready(nor); | ||
246 | if (ret < 0) | ||
247 | return ret; | ||
248 | if (ret) | ||
249 | return 0; | ||
250 | |||
198 | cond_resched(); | 251 | cond_resched(); |
252 | } | ||
199 | 253 | ||
200 | sr = read_sr(nor); | 254 | dev_err(nor->dev, "flash operation timed out\n"); |
201 | if (sr < 0) { | ||
202 | break; | ||
203 | } else if (!(sr & SR_WIP)) { | ||
204 | fsr = read_fsr(nor); | ||
205 | if (fsr < 0) | ||
206 | break; | ||
207 | if (fsr & FSR_READY) | ||
208 | return 0; | ||
209 | } | ||
210 | } while (!time_after_eq(jiffies, deadline)); | ||
211 | 255 | ||
212 | return -ETIMEDOUT; | 256 | return -ETIMEDOUT; |
213 | } | 257 | } |
214 | 258 | ||
215 | /* | 259 | /* |
216 | * Service routine to read status register until ready, or timeout occurs. | ||
217 | * Returns non-zero if error. | ||
218 | */ | ||
219 | static int wait_till_ready(struct spi_nor *nor) | ||
220 | { | ||
221 | return nor->wait_till_ready(nor); | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Erase the whole flash memory | 260 | * Erase the whole flash memory |
226 | * | 261 | * |
227 | * Returns 0 if successful, non-zero otherwise. | 262 | * Returns 0 if successful, non-zero otherwise. |
228 | */ | 263 | */ |
229 | static int erase_chip(struct spi_nor *nor) | 264 | static int erase_chip(struct spi_nor *nor) |
230 | { | 265 | { |
231 | int ret; | ||
232 | |||
233 | dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); | 266 | dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); |
234 | 267 | ||
235 | /* Wait until finished previous write command. */ | ||
236 | ret = wait_till_ready(nor); | ||
237 | if (ret) | ||
238 | return ret; | ||
239 | |||
240 | /* Send write enable, then erase commands. */ | ||
241 | write_enable(nor); | ||
242 | |||
243 | return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); | 268 | return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); |
244 | } | 269 | } |
245 | 270 | ||
@@ -294,11 +319,17 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
294 | 319 | ||
295 | /* whole-chip erase? */ | 320 | /* whole-chip erase? */ |
296 | if (len == mtd->size) { | 321 | if (len == mtd->size) { |
322 | write_enable(nor); | ||
323 | |||
297 | if (erase_chip(nor)) { | 324 | if (erase_chip(nor)) { |
298 | ret = -EIO; | 325 | ret = -EIO; |
299 | goto erase_err; | 326 | goto erase_err; |
300 | } | 327 | } |
301 | 328 | ||
329 | ret = spi_nor_wait_till_ready(nor); | ||
330 | if (ret) | ||
331 | goto erase_err; | ||
332 | |||
302 | /* REVISIT in some cases we could speed up erasing large regions | 333 | /* REVISIT in some cases we could speed up erasing large regions |
303 | * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up | 334 | * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up |
304 | * to use "small sector erase", but that's not always optimal. | 335 | * to use "small sector erase", but that's not always optimal. |
@@ -307,6 +338,8 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
307 | /* "sector"-at-a-time erase */ | 338 | /* "sector"-at-a-time erase */ |
308 | } else { | 339 | } else { |
309 | while (len) { | 340 | while (len) { |
341 | write_enable(nor); | ||
342 | |||
310 | if (nor->erase(nor, addr)) { | 343 | if (nor->erase(nor, addr)) { |
311 | ret = -EIO; | 344 | ret = -EIO; |
312 | goto erase_err; | 345 | goto erase_err; |
@@ -314,9 +347,15 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
314 | 347 | ||
315 | addr += mtd->erasesize; | 348 | addr += mtd->erasesize; |
316 | len -= mtd->erasesize; | 349 | len -= mtd->erasesize; |
350 | |||
351 | ret = spi_nor_wait_till_ready(nor); | ||
352 | if (ret) | ||
353 | goto erase_err; | ||
317 | } | 354 | } |
318 | } | 355 | } |
319 | 356 | ||
357 | write_disable(nor); | ||
358 | |||
320 | spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); | 359 | spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); |
321 | 360 | ||
322 | instr->state = MTD_ERASE_DONE; | 361 | instr->state = MTD_ERASE_DONE; |
@@ -341,11 +380,6 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
341 | if (ret) | 380 | if (ret) |
342 | return ret; | 381 | return ret; |
343 | 382 | ||
344 | /* Wait until finished previous command */ | ||
345 | ret = wait_till_ready(nor); | ||
346 | if (ret) | ||
347 | goto err; | ||
348 | |||
349 | status_old = read_sr(nor); | 383 | status_old = read_sr(nor); |
350 | 384 | ||
351 | if (offset < mtd->size - (mtd->size / 2)) | 385 | if (offset < mtd->size - (mtd->size / 2)) |
@@ -388,11 +422,6 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
388 | if (ret) | 422 | if (ret) |
389 | return ret; | 423 | return ret; |
390 | 424 | ||
391 | /* Wait until finished previous command */ | ||
392 | ret = wait_till_ready(nor); | ||
393 | if (ret) | ||
394 | goto err; | ||
395 | |||
396 | status_old = read_sr(nor); | 425 | status_old = read_sr(nor); |
397 | 426 | ||
398 | if (offset+len > mtd->size - (mtd->size / 64)) | 427 | if (offset+len > mtd->size - (mtd->size / 64)) |
@@ -424,38 +453,34 @@ err: | |||
424 | return ret; | 453 | return ret; |
425 | } | 454 | } |
426 | 455 | ||
427 | struct flash_info { | 456 | /* Used when the "_ext_id" is two bytes at most */ |
428 | /* JEDEC id zero means "no ID" (most older chips); otherwise it has | ||
429 | * a high byte of zero plus three data bytes: the manufacturer id, | ||
430 | * then a two byte device id. | ||
431 | */ | ||
432 | u32 jedec_id; | ||
433 | u16 ext_id; | ||
434 | |||
435 | /* The size listed here is what works with SPINOR_OP_SE, which isn't | ||
436 | * necessarily called a "sector" by the vendor. | ||
437 | */ | ||
438 | unsigned sector_size; | ||
439 | u16 n_sectors; | ||
440 | |||
441 | u16 page_size; | ||
442 | u16 addr_width; | ||
443 | |||
444 | u16 flags; | ||
445 | #define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ | ||
446 | #define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ | ||
447 | #define SST_WRITE 0x04 /* use SST byte programming */ | ||
448 | #define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ | ||
449 | #define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ | ||
450 | #define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ | ||
451 | #define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ | ||
452 | #define USE_FSR 0x80 /* use flag status register */ | ||
453 | }; | ||
454 | |||
455 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | 457 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ |
456 | ((kernel_ulong_t)&(struct flash_info) { \ | 458 | ((kernel_ulong_t)&(struct flash_info) { \ |
457 | .jedec_id = (_jedec_id), \ | 459 | .id = { \ |
458 | .ext_id = (_ext_id), \ | 460 | ((_jedec_id) >> 16) & 0xff, \ |
461 | ((_jedec_id) >> 8) & 0xff, \ | ||
462 | (_jedec_id) & 0xff, \ | ||
463 | ((_ext_id) >> 8) & 0xff, \ | ||
464 | (_ext_id) & 0xff, \ | ||
465 | }, \ | ||
466 | .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ | ||
467 | .sector_size = (_sector_size), \ | ||
468 | .n_sectors = (_n_sectors), \ | ||
469 | .page_size = 256, \ | ||
470 | .flags = (_flags), \ | ||
471 | }) | ||
472 | |||
473 | #define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | ||
474 | ((kernel_ulong_t)&(struct flash_info) { \ | ||
475 | .id = { \ | ||
476 | ((_jedec_id) >> 16) & 0xff, \ | ||
477 | ((_jedec_id) >> 8) & 0xff, \ | ||
478 | (_jedec_id) & 0xff, \ | ||
479 | ((_ext_id) >> 16) & 0xff, \ | ||
480 | ((_ext_id) >> 8) & 0xff, \ | ||
481 | (_ext_id) & 0xff, \ | ||
482 | }, \ | ||
483 | .id_len = 6, \ | ||
459 | .sector_size = (_sector_size), \ | 484 | .sector_size = (_sector_size), \ |
460 | .n_sectors = (_n_sectors), \ | 485 | .n_sectors = (_n_sectors), \ |
461 | .page_size = 256, \ | 486 | .page_size = 256, \ |
@@ -507,6 +532,9 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
507 | { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, | 532 | { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, |
508 | { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, | 533 | { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, |
509 | 534 | ||
535 | /* Fujitsu */ | ||
536 | { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, | ||
537 | |||
510 | /* GigaDevice */ | 538 | /* GigaDevice */ |
511 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, | 539 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, |
512 | { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, | 540 | { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, |
@@ -532,6 +560,7 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
532 | { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, | 560 | { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, |
533 | 561 | ||
534 | /* Micron */ | 562 | /* Micron */ |
563 | { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, | ||
535 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, | 564 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, |
536 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, | 565 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, |
537 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, | 566 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, |
@@ -556,6 +585,7 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
556 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, | 585 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, |
557 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 586 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
558 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, | 587 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, |
588 | { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, | ||
559 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, | 589 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, |
560 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, | 590 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, |
561 | { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, | 591 | { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, |
@@ -566,6 +596,7 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
566 | { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, | 596 | { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, |
567 | { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, | 597 | { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, |
568 | { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | 598 | { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
599 | { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, 0) }, | ||
569 | 600 | ||
570 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ | 601 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ |
571 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, | 602 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, |
@@ -577,6 +608,7 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
577 | { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, | 608 | { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, |
578 | { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, | 609 | { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, |
579 | { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, | 610 | { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, |
611 | { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, | ||
580 | 612 | ||
581 | /* ST Microelectronics -- newer production may have feature updates */ | 613 | /* ST Microelectronics -- newer production may have feature updates */ |
582 | { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, | 614 | { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, |
@@ -588,7 +620,6 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
588 | { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, | 620 | { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, |
589 | { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, | 621 | { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, |
590 | { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, | 622 | { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, |
591 | { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, | ||
592 | 623 | ||
593 | { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, | 624 | { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, |
594 | { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, | 625 | { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, |
@@ -643,32 +674,24 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
643 | static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) | 674 | static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) |
644 | { | 675 | { |
645 | int tmp; | 676 | int tmp; |
646 | u8 id[5]; | 677 | u8 id[SPI_NOR_MAX_ID_LEN]; |
647 | u32 jedec; | ||
648 | u16 ext_jedec; | ||
649 | struct flash_info *info; | 678 | struct flash_info *info; |
650 | 679 | ||
651 | tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, 5); | 680 | tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); |
652 | if (tmp < 0) { | 681 | if (tmp < 0) { |
653 | dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); | 682 | dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); |
654 | return ERR_PTR(tmp); | 683 | return ERR_PTR(tmp); |
655 | } | 684 | } |
656 | jedec = id[0]; | ||
657 | jedec = jedec << 8; | ||
658 | jedec |= id[1]; | ||
659 | jedec = jedec << 8; | ||
660 | jedec |= id[2]; | ||
661 | |||
662 | ext_jedec = id[3] << 8 | id[4]; | ||
663 | 685 | ||
664 | for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { | 686 | for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { |
665 | info = (void *)spi_nor_ids[tmp].driver_data; | 687 | info = (void *)spi_nor_ids[tmp].driver_data; |
666 | if (info->jedec_id == jedec) { | 688 | if (info->id_len) { |
667 | if (info->ext_id == 0 || info->ext_id == ext_jedec) | 689 | if (!memcmp(info->id, id, info->id_len)) |
668 | return &spi_nor_ids[tmp]; | 690 | return &spi_nor_ids[tmp]; |
669 | } | 691 | } |
670 | } | 692 | } |
671 | dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec); | 693 | dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n", |
694 | id[0], id[1], id[2]); | ||
672 | return ERR_PTR(-ENODEV); | 695 | return ERR_PTR(-ENODEV); |
673 | } | 696 | } |
674 | 697 | ||
@@ -703,11 +726,6 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
703 | if (ret) | 726 | if (ret) |
704 | return ret; | 727 | return ret; |
705 | 728 | ||
706 | /* Wait until finished previous write command. */ | ||
707 | ret = wait_till_ready(nor); | ||
708 | if (ret) | ||
709 | goto time_out; | ||
710 | |||
711 | write_enable(nor); | 729 | write_enable(nor); |
712 | 730 | ||
713 | nor->sst_write_second = false; | 731 | nor->sst_write_second = false; |
@@ -719,7 +737,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
719 | 737 | ||
720 | /* write one byte. */ | 738 | /* write one byte. */ |
721 | nor->write(nor, to, 1, retlen, buf); | 739 | nor->write(nor, to, 1, retlen, buf); |
722 | ret = wait_till_ready(nor); | 740 | ret = spi_nor_wait_till_ready(nor); |
723 | if (ret) | 741 | if (ret) |
724 | goto time_out; | 742 | goto time_out; |
725 | } | 743 | } |
@@ -731,7 +749,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
731 | 749 | ||
732 | /* write two bytes. */ | 750 | /* write two bytes. */ |
733 | nor->write(nor, to, 2, retlen, buf + actual); | 751 | nor->write(nor, to, 2, retlen, buf + actual); |
734 | ret = wait_till_ready(nor); | 752 | ret = spi_nor_wait_till_ready(nor); |
735 | if (ret) | 753 | if (ret) |
736 | goto time_out; | 754 | goto time_out; |
737 | to += 2; | 755 | to += 2; |
@@ -740,7 +758,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
740 | nor->sst_write_second = false; | 758 | nor->sst_write_second = false; |
741 | 759 | ||
742 | write_disable(nor); | 760 | write_disable(nor); |
743 | ret = wait_till_ready(nor); | 761 | ret = spi_nor_wait_till_ready(nor); |
744 | if (ret) | 762 | if (ret) |
745 | goto time_out; | 763 | goto time_out; |
746 | 764 | ||
@@ -751,7 +769,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
751 | nor->program_opcode = SPINOR_OP_BP; | 769 | nor->program_opcode = SPINOR_OP_BP; |
752 | nor->write(nor, to, 1, retlen, buf + actual); | 770 | nor->write(nor, to, 1, retlen, buf + actual); |
753 | 771 | ||
754 | ret = wait_till_ready(nor); | 772 | ret = spi_nor_wait_till_ready(nor); |
755 | if (ret) | 773 | if (ret) |
756 | goto time_out; | 774 | goto time_out; |
757 | write_disable(nor); | 775 | write_disable(nor); |
@@ -779,11 +797,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
779 | if (ret) | 797 | if (ret) |
780 | return ret; | 798 | return ret; |
781 | 799 | ||
782 | /* Wait until finished previous write command. */ | ||
783 | ret = wait_till_ready(nor); | ||
784 | if (ret) | ||
785 | goto write_err; | ||
786 | |||
787 | write_enable(nor); | 800 | write_enable(nor); |
788 | 801 | ||
789 | page_offset = to & (nor->page_size - 1); | 802 | page_offset = to & (nor->page_size - 1); |
@@ -802,16 +815,20 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
802 | if (page_size > nor->page_size) | 815 | if (page_size > nor->page_size) |
803 | page_size = nor->page_size; | 816 | page_size = nor->page_size; |
804 | 817 | ||
805 | wait_till_ready(nor); | 818 | ret = spi_nor_wait_till_ready(nor); |
819 | if (ret) | ||
820 | goto write_err; | ||
821 | |||
806 | write_enable(nor); | 822 | write_enable(nor); |
807 | 823 | ||
808 | nor->write(nor, to + i, page_size, retlen, buf + i); | 824 | nor->write(nor, to + i, page_size, retlen, buf + i); |
809 | } | 825 | } |
810 | } | 826 | } |
811 | 827 | ||
828 | ret = spi_nor_wait_till_ready(nor); | ||
812 | write_err: | 829 | write_err: |
813 | spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); | 830 | spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); |
814 | return 0; | 831 | return ret; |
815 | } | 832 | } |
816 | 833 | ||
817 | static int macronix_quad_enable(struct spi_nor *nor) | 834 | static int macronix_quad_enable(struct spi_nor *nor) |
@@ -824,7 +841,7 @@ static int macronix_quad_enable(struct spi_nor *nor) | |||
824 | nor->cmd_buf[0] = val | SR_QUAD_EN_MX; | 841 | nor->cmd_buf[0] = val | SR_QUAD_EN_MX; |
825 | nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); | 842 | nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); |
826 | 843 | ||
827 | if (wait_till_ready(nor)) | 844 | if (spi_nor_wait_till_ready(nor)) |
828 | return 1; | 845 | return 1; |
829 | 846 | ||
830 | ret = read_sr(nor); | 847 | ret = read_sr(nor); |
@@ -874,11 +891,11 @@ static int spansion_quad_enable(struct spi_nor *nor) | |||
874 | return 0; | 891 | return 0; |
875 | } | 892 | } |
876 | 893 | ||
877 | static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) | 894 | static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) |
878 | { | 895 | { |
879 | int status; | 896 | int status; |
880 | 897 | ||
881 | switch (JEDEC_MFR(jedec_id)) { | 898 | switch (JEDEC_MFR(info)) { |
882 | case CFI_MFR_MACRONIX: | 899 | case CFI_MFR_MACRONIX: |
883 | status = macronix_quad_enable(nor); | 900 | status = macronix_quad_enable(nor); |
884 | if (status) { | 901 | if (status) { |
@@ -904,11 +921,6 @@ static int spi_nor_check(struct spi_nor *nor) | |||
904 | return -EINVAL; | 921 | return -EINVAL; |
905 | } | 922 | } |
906 | 923 | ||
907 | if (!nor->read_id) | ||
908 | nor->read_id = spi_nor_read_id; | ||
909 | if (!nor->wait_till_ready) | ||
910 | nor->wait_till_ready = spi_nor_wait_till_ready; | ||
911 | |||
912 | return 0; | 924 | return 0; |
913 | } | 925 | } |
914 | 926 | ||
@@ -926,16 +938,24 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) | |||
926 | if (ret) | 938 | if (ret) |
927 | return ret; | 939 | return ret; |
928 | 940 | ||
929 | id = spi_nor_match_id(name); | 941 | /* Try to auto-detect if chip name wasn't specified */ |
930 | if (!id) | 942 | if (!name) |
943 | id = spi_nor_read_id(nor); | ||
944 | else | ||
945 | id = spi_nor_match_id(name); | ||
946 | if (IS_ERR_OR_NULL(id)) | ||
931 | return -ENOENT; | 947 | return -ENOENT; |
932 | 948 | ||
933 | info = (void *)id->driver_data; | 949 | info = (void *)id->driver_data; |
934 | 950 | ||
935 | if (info->jedec_id) { | 951 | /* |
952 | * If caller has specified name of flash model that can normally be | ||
953 | * detected using JEDEC, let's verify it. | ||
954 | */ | ||
955 | if (name && info->id_len) { | ||
936 | const struct spi_device_id *jid; | 956 | const struct spi_device_id *jid; |
937 | 957 | ||
938 | jid = nor->read_id(nor); | 958 | jid = spi_nor_read_id(nor); |
939 | if (IS_ERR(jid)) { | 959 | if (IS_ERR(jid)) { |
940 | return PTR_ERR(jid); | 960 | return PTR_ERR(jid); |
941 | } else if (jid != id) { | 961 | } else if (jid != id) { |
@@ -960,9 +980,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) | |||
960 | * up with the software protection bits set | 980 | * up with the software protection bits set |
961 | */ | 981 | */ |
962 | 982 | ||
963 | if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || | 983 | if (JEDEC_MFR(info) == CFI_MFR_ATMEL || |
964 | JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || | 984 | JEDEC_MFR(info) == CFI_MFR_INTEL || |
965 | JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { | 985 | JEDEC_MFR(info) == CFI_MFR_SST) { |
966 | write_enable(nor); | 986 | write_enable(nor); |
967 | write_sr(nor, 0); | 987 | write_sr(nor, 0); |
968 | } | 988 | } |
@@ -977,7 +997,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) | |||
977 | mtd->_read = spi_nor_read; | 997 | mtd->_read = spi_nor_read; |
978 | 998 | ||
979 | /* nor protection support for STmicro chips */ | 999 | /* nor protection support for STmicro chips */ |
980 | if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { | 1000 | if (JEDEC_MFR(info) == CFI_MFR_ST) { |
981 | mtd->_lock = spi_nor_lock; | 1001 | mtd->_lock = spi_nor_lock; |
982 | mtd->_unlock = spi_nor_unlock; | 1002 | mtd->_unlock = spi_nor_unlock; |
983 | } | 1003 | } |
@@ -988,9 +1008,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) | |||
988 | else | 1008 | else |
989 | mtd->_write = spi_nor_write; | 1009 | mtd->_write = spi_nor_write; |
990 | 1010 | ||
991 | if ((info->flags & USE_FSR) && | 1011 | if (info->flags & USE_FSR) |
992 | nor->wait_till_ready == spi_nor_wait_till_ready) | 1012 | nor->flags |= SNOR_F_USE_FSR; |
993 | nor->wait_till_ready = spi_nor_wait_till_fsr_ready; | ||
994 | 1013 | ||
995 | #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS | 1014 | #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS |
996 | /* prefer "small sector" erase if possible */ | 1015 | /* prefer "small sector" erase if possible */ |
@@ -1031,7 +1050,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) | |||
1031 | 1050 | ||
1032 | /* Quad/Dual-read mode takes precedence over fast/normal */ | 1051 | /* Quad/Dual-read mode takes precedence over fast/normal */ |
1033 | if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { | 1052 | if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { |
1034 | ret = set_quad_mode(nor, info->jedec_id); | 1053 | ret = set_quad_mode(nor, info); |
1035 | if (ret) { | 1054 | if (ret) { |
1036 | dev_err(dev, "quad mode not supported\n"); | 1055 | dev_err(dev, "quad mode not supported\n"); |
1037 | return ret; | 1056 | return ret; |
@@ -1067,7 +1086,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) | |||
1067 | else if (mtd->size > 0x1000000) { | 1086 | else if (mtd->size > 0x1000000) { |
1068 | /* enable 4-byte addressing if the device exceeds 16MiB */ | 1087 | /* enable 4-byte addressing if the device exceeds 16MiB */ |
1069 | nor->addr_width = 4; | 1088 | nor->addr_width = 4; |
1070 | if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { | 1089 | if (JEDEC_MFR(info) == CFI_MFR_AMD) { |
1071 | /* Dedicated 4-byte command set */ | 1090 | /* Dedicated 4-byte command set */ |
1072 | switch (nor->flash_read) { | 1091 | switch (nor->flash_read) { |
1073 | case SPI_NOR_QUAD: | 1092 | case SPI_NOR_QUAD: |
@@ -1088,7 +1107,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) | |||
1088 | nor->erase_opcode = SPINOR_OP_SE_4B; | 1107 | nor->erase_opcode = SPINOR_OP_SE_4B; |
1089 | mtd->erasesize = info->sector_size; | 1108 | mtd->erasesize = info->sector_size; |
1090 | } else | 1109 | } else |
1091 | set_4byte(nor, info->jedec_id, 1); | 1110 | set_4byte(nor, info, 1); |
1092 | } else { | 1111 | } else { |
1093 | nor->addr_width = 3; | 1112 | nor->addr_width = 3; |
1094 | } | 1113 | } |
diff --git a/drivers/mtd/tests/oobtest.c b/drivers/mtd/tests/oobtest.c index dc4f9602b97e..5e061186eab1 100644 --- a/drivers/mtd/tests/oobtest.c +++ b/drivers/mtd/tests/oobtest.c | |||
@@ -34,8 +34,11 @@ | |||
34 | #include "mtd_test.h" | 34 | #include "mtd_test.h" |
35 | 35 | ||
36 | static int dev = -EINVAL; | 36 | static int dev = -EINVAL; |
37 | static int bitflip_limit; | ||
37 | module_param(dev, int, S_IRUGO); | 38 | module_param(dev, int, S_IRUGO); |
38 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 39 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
40 | module_param(bitflip_limit, int, S_IRUGO); | ||
41 | MODULE_PARM_DESC(bitflip_limit, "Max. allowed bitflips per page"); | ||
39 | 42 | ||
40 | static struct mtd_info *mtd; | 43 | static struct mtd_info *mtd; |
41 | static unsigned char *readbuf; | 44 | static unsigned char *readbuf; |
@@ -115,12 +118,36 @@ static int write_whole_device(void) | |||
115 | return 0; | 118 | return 0; |
116 | } | 119 | } |
117 | 120 | ||
121 | /* | ||
122 | * Display the address, offset and data bytes at comparison failure. | ||
123 | * Return number of bitflips encountered. | ||
124 | */ | ||
125 | static size_t memcmpshow(loff_t addr, const void *cs, const void *ct, size_t count) | ||
126 | { | ||
127 | const unsigned char *su1, *su2; | ||
128 | int res; | ||
129 | size_t i = 0; | ||
130 | size_t bitflips = 0; | ||
131 | |||
132 | for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--, i++) { | ||
133 | res = *su1 ^ *su2; | ||
134 | if (res) { | ||
135 | pr_info("error @addr[0x%lx:0x%zx] 0x%x -> 0x%x diff 0x%x\n", | ||
136 | (unsigned long)addr, i, *su1, *su2, res); | ||
137 | bitflips += hweight8(res); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | return bitflips; | ||
142 | } | ||
143 | |||
118 | static int verify_eraseblock(int ebnum) | 144 | static int verify_eraseblock(int ebnum) |
119 | { | 145 | { |
120 | int i; | 146 | int i; |
121 | struct mtd_oob_ops ops; | 147 | struct mtd_oob_ops ops; |
122 | int err = 0; | 148 | int err = 0; |
123 | loff_t addr = (loff_t)ebnum * mtd->erasesize; | 149 | loff_t addr = (loff_t)ebnum * mtd->erasesize; |
150 | size_t bitflips; | ||
124 | 151 | ||
125 | prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt); | 152 | prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt); |
126 | for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { | 153 | for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { |
@@ -139,8 +166,11 @@ static int verify_eraseblock(int ebnum) | |||
139 | errcnt += 1; | 166 | errcnt += 1; |
140 | return err ? err : -1; | 167 | return err ? err : -1; |
141 | } | 168 | } |
142 | if (memcmp(readbuf, writebuf + (use_len_max * i) + use_offset, | 169 | |
143 | use_len)) { | 170 | bitflips = memcmpshow(addr, readbuf, |
171 | writebuf + (use_len_max * i) + use_offset, | ||
172 | use_len); | ||
173 | if (bitflips > bitflip_limit) { | ||
144 | pr_err("error: verify failed at %#llx\n", | 174 | pr_err("error: verify failed at %#llx\n", |
145 | (long long)addr); | 175 | (long long)addr); |
146 | errcnt += 1; | 176 | errcnt += 1; |
@@ -148,7 +178,10 @@ static int verify_eraseblock(int ebnum) | |||
148 | pr_err("error: too many errors\n"); | 178 | pr_err("error: too many errors\n"); |
149 | return -1; | 179 | return -1; |
150 | } | 180 | } |
181 | } else if (bitflips) { | ||
182 | pr_info("ignoring error as within bitflip_limit\n"); | ||
151 | } | 183 | } |
184 | |||
152 | if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) { | 185 | if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) { |
153 | int k; | 186 | int k; |
154 | 187 | ||
@@ -167,9 +200,10 @@ static int verify_eraseblock(int ebnum) | |||
167 | errcnt += 1; | 200 | errcnt += 1; |
168 | return err ? err : -1; | 201 | return err ? err : -1; |
169 | } | 202 | } |
170 | if (memcmp(readbuf + use_offset, | 203 | bitflips = memcmpshow(addr, readbuf + use_offset, |
171 | writebuf + (use_len_max * i) + use_offset, | 204 | writebuf + (use_len_max * i) + use_offset, |
172 | use_len)) { | 205 | use_len); |
206 | if (bitflips > bitflip_limit) { | ||
173 | pr_err("error: verify failed at %#llx\n", | 207 | pr_err("error: verify failed at %#llx\n", |
174 | (long long)addr); | 208 | (long long)addr); |
175 | errcnt += 1; | 209 | errcnt += 1; |
@@ -177,7 +211,10 @@ static int verify_eraseblock(int ebnum) | |||
177 | pr_err("error: too many errors\n"); | 211 | pr_err("error: too many errors\n"); |
178 | return -1; | 212 | return -1; |
179 | } | 213 | } |
214 | } else if (bitflips) { | ||
215 | pr_info("ignoring error as within bitflip_limit\n"); | ||
180 | } | 216 | } |
217 | |||
181 | for (k = 0; k < use_offset; ++k) | 218 | for (k = 0; k < use_offset; ++k) |
182 | if (readbuf[k] != 0xff) { | 219 | if (readbuf[k] != 0xff) { |
183 | pr_err("error: verify 0xff " | 220 | pr_err("error: verify 0xff " |
@@ -216,6 +253,9 @@ static int verify_eraseblock_in_one_go(int ebnum) | |||
216 | int err = 0; | 253 | int err = 0; |
217 | loff_t addr = (loff_t)ebnum * mtd->erasesize; | 254 | loff_t addr = (loff_t)ebnum * mtd->erasesize; |
218 | size_t len = mtd->ecclayout->oobavail * pgcnt; | 255 | size_t len = mtd->ecclayout->oobavail * pgcnt; |
256 | size_t oobavail = mtd->ecclayout->oobavail; | ||
257 | size_t bitflips; | ||
258 | int i; | ||
219 | 259 | ||
220 | prandom_bytes_state(&rnd_state, writebuf, len); | 260 | prandom_bytes_state(&rnd_state, writebuf, len); |
221 | ops.mode = MTD_OPS_AUTO_OOB; | 261 | ops.mode = MTD_OPS_AUTO_OOB; |
@@ -226,6 +266,8 @@ static int verify_eraseblock_in_one_go(int ebnum) | |||
226 | ops.ooboffs = 0; | 266 | ops.ooboffs = 0; |
227 | ops.datbuf = NULL; | 267 | ops.datbuf = NULL; |
228 | ops.oobbuf = readbuf; | 268 | ops.oobbuf = readbuf; |
269 | |||
270 | /* read entire block's OOB at one go */ | ||
229 | err = mtd_read_oob(mtd, addr, &ops); | 271 | err = mtd_read_oob(mtd, addr, &ops); |
230 | if (err || ops.oobretlen != len) { | 272 | if (err || ops.oobretlen != len) { |
231 | pr_err("error: readoob failed at %#llx\n", | 273 | pr_err("error: readoob failed at %#llx\n", |
@@ -233,13 +275,21 @@ static int verify_eraseblock_in_one_go(int ebnum) | |||
233 | errcnt += 1; | 275 | errcnt += 1; |
234 | return err ? err : -1; | 276 | return err ? err : -1; |
235 | } | 277 | } |
236 | if (memcmp(readbuf, writebuf, len)) { | 278 | |
237 | pr_err("error: verify failed at %#llx\n", | 279 | /* verify one page OOB at a time for bitflip per page limit check */ |
238 | (long long)addr); | 280 | for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) { |
239 | errcnt += 1; | 281 | bitflips = memcmpshow(addr, readbuf + (i * oobavail), |
240 | if (errcnt > 1000) { | 282 | writebuf + (i * oobavail), oobavail); |
241 | pr_err("error: too many errors\n"); | 283 | if (bitflips > bitflip_limit) { |
242 | return -1; | 284 | pr_err("error: verify failed at %#llx\n", |
285 | (long long)addr); | ||
286 | errcnt += 1; | ||
287 | if (errcnt > 1000) { | ||
288 | pr_err("error: too many errors\n"); | ||
289 | return -1; | ||
290 | } | ||
291 | } else if (bitflips) { | ||
292 | pr_info("ignoring error as within bitflip_limit\n"); | ||
243 | } | 293 | } |
244 | } | 294 | } |
245 | 295 | ||
@@ -610,7 +660,8 @@ static int __init mtd_oobtest_init(void) | |||
610 | err = mtd_read_oob(mtd, addr, &ops); | 660 | err = mtd_read_oob(mtd, addr, &ops); |
611 | if (err) | 661 | if (err) |
612 | goto out; | 662 | goto out; |
613 | if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) { | 663 | if (memcmpshow(addr, readbuf, writebuf, |
664 | mtd->ecclayout->oobavail * 2)) { | ||
614 | pr_err("error: verify failed at %#llx\n", | 665 | pr_err("error: verify failed at %#llx\n", |
615 | (long long)addr); | 666 | (long long)addr); |
616 | errcnt += 1; | 667 | errcnt += 1; |
diff --git a/drivers/mtd/tests/torturetest.c b/drivers/mtd/tests/torturetest.c index eeab96973cf0..b55bc52a1340 100644 --- a/drivers/mtd/tests/torturetest.c +++ b/drivers/mtd/tests/torturetest.c | |||
@@ -264,7 +264,9 @@ static int __init tort_init(void) | |||
264 | int i; | 264 | int i; |
265 | void *patt; | 265 | void *patt; |
266 | 266 | ||
267 | mtdtest_erase_good_eraseblocks(mtd, bad_ebs, eb, ebcnt); | 267 | err = mtdtest_erase_good_eraseblocks(mtd, bad_ebs, eb, ebcnt); |
268 | if (err) | ||
269 | goto out; | ||
268 | 270 | ||
269 | /* Check if the eraseblocks contain only 0xFF bytes */ | 271 | /* Check if the eraseblocks contain only 0xFF bytes */ |
270 | if (check) { | 272 | if (check) { |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 386303dca382..dddbde4f56f4 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -224,7 +224,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
224 | 224 | ||
225 | dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw)); | 225 | dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw)); |
226 | 226 | ||
227 | /* If a node has zero dsize, we only have to keep if it if it might be the | 227 | /* If a node has zero dsize, we only have to keep it if it might be the |
228 | node with highest version -- i.e. the one which will end up as f->metadata. | 228 | node with highest version -- i.e. the one which will end up as f->metadata. |
229 | Note that such nodes won't be REF_UNCHECKED since there are no data to | 229 | Note that such nodes won't be REF_UNCHECKED since there are no data to |
230 | check anyway. */ | 230 | check anyway. */ |
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index c522d098bb4f..bc5385471a6e 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c | |||
@@ -844,6 +844,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
844 | /* Write out summary information - called from jffs2_do_reserve_space */ | 844 | /* Write out summary information - called from jffs2_do_reserve_space */ |
845 | 845 | ||
846 | int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | 846 | int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) |
847 | __must_hold(&c->erase_completion_block) | ||
847 | { | 848 | { |
848 | int datasize, infosize, padsize; | 849 | int datasize, infosize, padsize; |
849 | struct jffs2_eraseblock *jeb; | 850 | struct jffs2_eraseblock *jeb; |
diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h index 84d60cb841b1..bf0321eabbda 100644 --- a/include/linux/fsl_ifc.h +++ b/include/linux/fsl_ifc.h | |||
@@ -29,7 +29,16 @@ | |||
29 | #include <linux/of_platform.h> | 29 | #include <linux/of_platform.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | 31 | ||
32 | #define FSL_IFC_BANK_COUNT 4 | 32 | /* |
33 | * The actual number of banks implemented depends on the IFC version | ||
34 | * - IFC version 1.0 implements 4 banks. | ||
35 | * - IFC version 1.1 onward implements 8 banks. | ||
36 | */ | ||
37 | #define FSL_IFC_BANK_COUNT 8 | ||
38 | |||
39 | #define FSL_IFC_VERSION_MASK 0x0F0F0000 | ||
40 | #define FSL_IFC_VERSION_1_0_0 0x01000000 | ||
41 | #define FSL_IFC_VERSION_1_1_0 0x01010000 | ||
33 | 42 | ||
34 | /* | 43 | /* |
35 | * CSPR - Chip Select Property Register | 44 | * CSPR - Chip Select Property Register |
@@ -776,23 +785,23 @@ struct fsl_ifc_regs { | |||
776 | __be32 cspr; | 785 | __be32 cspr; |
777 | u32 res2; | 786 | u32 res2; |
778 | } cspr_cs[FSL_IFC_BANK_COUNT]; | 787 | } cspr_cs[FSL_IFC_BANK_COUNT]; |
779 | u32 res3[0x19]; | 788 | u32 res3[0xd]; |
780 | struct { | 789 | struct { |
781 | __be32 amask; | 790 | __be32 amask; |
782 | u32 res4[0x2]; | 791 | u32 res4[0x2]; |
783 | } amask_cs[FSL_IFC_BANK_COUNT]; | 792 | } amask_cs[FSL_IFC_BANK_COUNT]; |
784 | u32 res5[0x18]; | 793 | u32 res5[0xc]; |
785 | struct { | 794 | struct { |
786 | __be32 csor; | 795 | __be32 csor; |
787 | __be32 csor_ext; | 796 | __be32 csor_ext; |
788 | u32 res6; | 797 | u32 res6; |
789 | } csor_cs[FSL_IFC_BANK_COUNT]; | 798 | } csor_cs[FSL_IFC_BANK_COUNT]; |
790 | u32 res7[0x18]; | 799 | u32 res7[0xc]; |
791 | struct { | 800 | struct { |
792 | __be32 ftim[4]; | 801 | __be32 ftim[4]; |
793 | u32 res8[0x8]; | 802 | u32 res8[0x8]; |
794 | } ftim_cs[FSL_IFC_BANK_COUNT]; | 803 | } ftim_cs[FSL_IFC_BANK_COUNT]; |
795 | u32 res9[0x60]; | 804 | u32 res9[0x30]; |
796 | __be32 rb_stat; | 805 | __be32 rb_stat; |
797 | u32 res10[0x2]; | 806 | u32 res10[0x2]; |
798 | __be32 ifc_gcr; | 807 | __be32 ifc_gcr; |
@@ -827,6 +836,8 @@ struct fsl_ifc_ctrl { | |||
827 | int nand_irq; | 836 | int nand_irq; |
828 | spinlock_t lock; | 837 | spinlock_t lock; |
829 | void *nand; | 838 | void *nand; |
839 | int version; | ||
840 | int banks; | ||
830 | 841 | ||
831 | u32 nand_stat; | 842 | u32 nand_stat; |
832 | wait_queue_head_t nand_wait; | 843 | wait_queue_head_t nand_wait; |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index e4d451e4600b..3d4ea7eb2b68 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -455,8 +455,21 @@ struct nand_hw_control { | |||
455 | * be provided if an hardware ECC is available | 455 | * be provided if an hardware ECC is available |
456 | * @calculate: function for ECC calculation or readback from ECC hardware | 456 | * @calculate: function for ECC calculation or readback from ECC hardware |
457 | * @correct: function for ECC correction, matching to ECC generator (sw/hw) | 457 | * @correct: function for ECC correction, matching to ECC generator (sw/hw) |
458 | * @read_page_raw: function to read a raw page without ECC | 458 | * @read_page_raw: function to read a raw page without ECC. This function |
459 | * @write_page_raw: function to write a raw page without ECC | 459 | * should hide the specific layout used by the ECC |
460 | * controller and always return contiguous in-band and | ||
461 | * out-of-band data even if they're not stored | ||
462 | * contiguously on the NAND chip (e.g. | ||
463 | * NAND_ECC_HW_SYNDROME interleaves in-band and | ||
464 | * out-of-band data). | ||
465 | * @write_page_raw: function to write a raw page without ECC. This function | ||
466 | * should hide the specific layout used by the ECC | ||
467 | * controller and consider the passed data as contiguous | ||
468 | * in-band and out-of-band data. ECC controller is | ||
469 | * responsible for doing the appropriate transformations | ||
470 | * to adapt to its specific layout (e.g. | ||
471 | * NAND_ECC_HW_SYNDROME interleaves in-band and | ||
472 | * out-of-band data). | ||
460 | * @read_page: function to read a page according to the ECC generator | 473 | * @read_page: function to read a page according to the ECC generator |
461 | * requirements; returns maximum number of bitflips corrected in | 474 | * requirements; returns maximum number of bitflips corrected in |
462 | * any single ECC step, 0 if bitflips uncorrectable, -EIO hw error | 475 | * any single ECC step, 0 if bitflips uncorrectable, -EIO hw error |
@@ -723,6 +736,7 @@ struct nand_chip { | |||
723 | #define NAND_MFR_EON 0x92 | 736 | #define NAND_MFR_EON 0x92 |
724 | #define NAND_MFR_SANDISK 0x45 | 737 | #define NAND_MFR_SANDISK 0x45 |
725 | #define NAND_MFR_INTEL 0x89 | 738 | #define NAND_MFR_INTEL 0x89 |
739 | #define NAND_MFR_ATO 0x9b | ||
726 | 740 | ||
727 | /* The maximum expected count of bytes in the NAND ID sequence */ | 741 | /* The maximum expected count of bytes in the NAND ID sequence */ |
728 | #define NAND_MAX_ID_LEN 8 | 742 | #define NAND_MAX_ID_LEN 8 |
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 046a0a2e4c4e..63aeccf9ddc8 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h | |||
@@ -116,6 +116,10 @@ enum spi_nor_ops { | |||
116 | SPI_NOR_OPS_UNLOCK, | 116 | SPI_NOR_OPS_UNLOCK, |
117 | }; | 117 | }; |
118 | 118 | ||
119 | enum spi_nor_option_flags { | ||
120 | SNOR_F_USE_FSR = BIT(0), | ||
121 | }; | ||
122 | |||
119 | /** | 123 | /** |
120 | * struct spi_nor - Structure for defining a the SPI NOR layer | 124 | * struct spi_nor - Structure for defining a the SPI NOR layer |
121 | * @mtd: point to a mtd_info structure | 125 | * @mtd: point to a mtd_info structure |
@@ -129,6 +133,7 @@ enum spi_nor_ops { | |||
129 | * @program_opcode: the program opcode | 133 | * @program_opcode: the program opcode |
130 | * @flash_read: the mode of the read | 134 | * @flash_read: the mode of the read |
131 | * @sst_write_second: used by the SST write operation | 135 | * @sst_write_second: used by the SST write operation |
136 | * @flags: flag options for the current SPI-NOR (SNOR_F_*) | ||
132 | * @cfg: used by the read_xfer/write_xfer | 137 | * @cfg: used by the read_xfer/write_xfer |
133 | * @cmd_buf: used by the write_reg | 138 | * @cmd_buf: used by the write_reg |
134 | * @prepare: [OPTIONAL] do some preparations for the | 139 | * @prepare: [OPTIONAL] do some preparations for the |
@@ -139,9 +144,6 @@ enum spi_nor_ops { | |||
139 | * @write_xfer: [OPTIONAL] the writefundamental primitive | 144 | * @write_xfer: [OPTIONAL] the writefundamental primitive |
140 | * @read_reg: [DRIVER-SPECIFIC] read out the register | 145 | * @read_reg: [DRIVER-SPECIFIC] read out the register |
141 | * @write_reg: [DRIVER-SPECIFIC] write data to the register | 146 | * @write_reg: [DRIVER-SPECIFIC] write data to the register |
142 | * @read_id: [REPLACEABLE] read out the ID data, and find | ||
143 | * the proper spi_device_id | ||
144 | * @wait_till_ready: [REPLACEABLE] wait till the NOR becomes ready | ||
145 | * @read: [DRIVER-SPECIFIC] read data from the SPI NOR | 147 | * @read: [DRIVER-SPECIFIC] read data from the SPI NOR |
146 | * @write: [DRIVER-SPECIFIC] write data to the SPI NOR | 148 | * @write: [DRIVER-SPECIFIC] write data to the SPI NOR |
147 | * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR | 149 | * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR |
@@ -160,6 +162,7 @@ struct spi_nor { | |||
160 | u8 program_opcode; | 162 | u8 program_opcode; |
161 | enum read_mode flash_read; | 163 | enum read_mode flash_read; |
162 | bool sst_write_second; | 164 | bool sst_write_second; |
165 | u32 flags; | ||
163 | struct spi_nor_xfer_cfg cfg; | 166 | struct spi_nor_xfer_cfg cfg; |
164 | u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; | 167 | u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; |
165 | 168 | ||
@@ -172,8 +175,6 @@ struct spi_nor { | |||
172 | int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); | 175 | int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); |
173 | int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len, | 176 | int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len, |
174 | int write_enable); | 177 | int write_enable); |
175 | const struct spi_device_id *(*read_id)(struct spi_nor *nor); | ||
176 | int (*wait_till_ready)(struct spi_nor *nor); | ||
177 | 178 | ||
178 | int (*read)(struct spi_nor *nor, loff_t from, | 179 | int (*read)(struct spi_nor *nor, loff_t from, |
179 | size_t len, size_t *retlen, u_char *read_buf); | 180 | size_t len, size_t *retlen, u_char *read_buf); |