diff options
34 files changed, 1380 insertions, 214 deletions
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt index 1fe6dde98499..7d4c8eb775a5 100644 --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | Atmel NAND flash | 1 | Atmel NAND flash |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible : "atmel,at91rm9200-nand". | 4 | - compatible : should be "atmel,at91rm9200-nand" or "atmel,sama5d4-nand". |
| 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 |
diff --git a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt index 823d13412195..4461dc71cb10 100644 --- a/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt +++ b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | * Freescale Quad Serial Peripheral Interface(QuadSPI) | 1 | * Freescale Quad Serial Peripheral Interface(QuadSPI) |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible : Should be "fsl,vf610-qspi" | 4 | - compatible : Should be "fsl,vf610-qspi" or "fsl,imx6sx-qspi" |
| 5 | - reg : the first contains the register location and length, | 5 | - reg : the first contains the register location and length, |
| 6 | the second contains the memory mapping address and length | 6 | the second contains the memory mapping address and length |
| 7 | - reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory" | 7 | - reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory" |
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt index a011fdf61dbf..d02acaff3c35 100644 --- a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | * Freescale General-Purpose Media Interface (GPMI) | 1 | * Freescale General-Purpose Media Interface (GPMI) |
| 2 | 2 | ||
| 3 | The GPMI nand controller provides an interface to control the | 3 | The GPMI nand controller provides an interface to control the |
| 4 | NAND flash chips. We support only one NAND chip now. | 4 | NAND flash chips. |
| 5 | 5 | ||
| 6 | Required properties: | 6 | Required properties: |
| 7 | - compatible : should be "fsl,<chip>-gpmi-nand" | 7 | - compatible : should be "fsl,<chip>-gpmi-nand" |
diff --git a/Documentation/devicetree/bindings/mtd/hisi504-nand.txt b/Documentation/devicetree/bindings/mtd/hisi504-nand.txt new file mode 100644 index 000000000000..2e35f0662912 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/hisi504-nand.txt | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | Hisilicon Hip04 Soc NAND controller DT binding | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible: Should be "hisilicon,504-nfc". | ||
| 6 | - reg: The first contains base physical address and size of | ||
| 7 | NAND controller's registers. The second contains base | ||
| 8 | physical address and size of NAND controller's buffer. | ||
| 9 | - interrupts: Interrupt number for nfc. | ||
| 10 | - nand-bus-width: See nand.txt. | ||
| 11 | - nand-ecc-mode: Support none and hw ecc mode. | ||
| 12 | - #address-cells: Partition address, should be set 1. | ||
| 13 | - #size-cells: Partition size, should be set 1. | ||
| 14 | |||
| 15 | Optional properties: | ||
| 16 | |||
| 17 | - nand-ecc-strength: Number of bits to correct per ECC step. | ||
| 18 | - nand-ecc-step-size: Number of data bytes covered by a single ECC step. | ||
| 19 | |||
| 20 | The following ECC strength and step size are currently supported: | ||
| 21 | |||
| 22 | - nand-ecc-strength = <16>, nand-ecc-step-size = <1024> | ||
| 23 | |||
| 24 | Flash chip may optionally contain additional sub-nodes describing partitions of | ||
| 25 | the address space. See partition.txt for more detail. | ||
| 26 | |||
| 27 | Example: | ||
| 28 | |||
| 29 | nand: nand@4020000 { | ||
| 30 | compatible = "hisilicon,504-nfc"; | ||
| 31 | reg = <0x4020000 0x10000>, <0x5000000 0x1000>; | ||
| 32 | interrupts = <0 379 4>; | ||
| 33 | nand-bus-width = <8>; | ||
| 34 | nand-ecc-mode = "hw"; | ||
| 35 | nand-ecc-strength = <16>; | ||
| 36 | nand-ecc-step-size = <1024>; | ||
| 37 | #address-cells = <1>; | ||
| 38 | #size-cells = <1>; | ||
| 39 | |||
| 40 | partition@0 { | ||
| 41 | label = "nand_text"; | ||
| 42 | reg = <0x00000000 0x00400000>; | ||
| 43 | }; | ||
| 44 | |||
| 45 | ... | ||
| 46 | |||
| 47 | }; | ||
diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt index 6b9f680cb579..4a0a48bf4ecb 100644 --- a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt +++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt | |||
| @@ -36,6 +36,11 @@ are defined: | |||
| 36 | - vendor-id : Contains the flash chip's vendor id (1 byte). | 36 | - vendor-id : Contains the flash chip's vendor id (1 byte). |
| 37 | - device-id : Contains the flash chip's device id (1 byte). | 37 | - device-id : Contains the flash chip's device id (1 byte). |
| 38 | 38 | ||
| 39 | For ROM compatible devices (and ROM fallback from cfi-flash), the following | ||
| 40 | additional (optional) property is defined: | ||
| 41 | |||
| 42 | - erase-size : The chip's physical erase block size in bytes. | ||
| 43 | |||
| 39 | The device tree may optionally contain sub-nodes describing partitions of the | 44 | The device tree may optionally contain sub-nodes describing partitions of the |
| 40 | address space. See partition.txt for more detail. | 45 | address space. See partition.txt for more detail. |
| 41 | 46 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index ddb9ac8d32b3..cabe127fba76 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -4028,6 +4028,12 @@ S: Maintained | |||
| 4028 | F: include/linux/platform_data/video-imxfb.h | 4028 | F: include/linux/platform_data/video-imxfb.h |
| 4029 | F: drivers/video/fbdev/imxfb.c | 4029 | F: drivers/video/fbdev/imxfb.c |
| 4030 | 4030 | ||
| 4031 | FREESCALE QUAD SPI DRIVER | ||
| 4032 | M: Han Xu <han.xu@freescale.com> | ||
| 4033 | L: linux-mtd@lists.infradead.org | ||
| 4034 | S: Maintained | ||
| 4035 | F: drivers/mtd/spi-nor/fsl-quadspi.c | ||
| 4036 | |||
| 4031 | FREESCALE SOC FS_ENET DRIVER | 4037 | FREESCALE SOC FS_ENET DRIVER |
| 4032 | M: Pantelis Antoniou <pantelis.antoniou@gmail.com> | 4038 | M: Pantelis Antoniou <pantelis.antoniou@gmail.com> |
| 4033 | M: Vitaly Bordug <vbordug@ru.mvista.com> | 4039 | M: Vitaly Bordug <vbordug@ru.mvista.com> |
diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h index 986982db7c38..79cff26d8b36 100644 --- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h +++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h | |||
| @@ -27,8 +27,6 @@ struct jz_nand_platform_data { | |||
| 27 | 27 | ||
| 28 | struct nand_ecclayout *ecc_layout; | 28 | struct nand_ecclayout *ecc_layout; |
| 29 | 29 | ||
| 30 | unsigned int busy_gpio; | ||
| 31 | |||
| 32 | unsigned char banks[JZ_NAND_NUM_BANKS]; | 30 | unsigned char banks[JZ_NAND_NUM_BANKS]; |
| 33 | 31 | ||
| 34 | void (*ident_callback)(struct platform_device *, struct nand_chip *, | 32 | void (*ident_callback)(struct platform_device *, struct nand_chip *, |
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index c454525e7695..9dd051edb411 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c | |||
| @@ -140,10 +140,18 @@ static void qi_lb60_nand_ident(struct platform_device *pdev, | |||
| 140 | 140 | ||
| 141 | static struct jz_nand_platform_data qi_lb60_nand_pdata = { | 141 | static struct jz_nand_platform_data qi_lb60_nand_pdata = { |
| 142 | .ident_callback = qi_lb60_nand_ident, | 142 | .ident_callback = qi_lb60_nand_ident, |
| 143 | .busy_gpio = 94, | ||
| 144 | .banks = { 1 }, | 143 | .banks = { 1 }, |
| 145 | }; | 144 | }; |
| 146 | 145 | ||
| 146 | static struct gpiod_lookup_table qi_lb60_nand_gpio_table = { | ||
| 147 | .dev_id = "jz4740-nand.0", | ||
| 148 | .table = { | ||
| 149 | GPIO_LOOKUP("Bank C", 30, "busy", 0), | ||
| 150 | { }, | ||
| 151 | }, | ||
| 152 | }; | ||
| 153 | |||
| 154 | |||
| 147 | /* Keyboard*/ | 155 | /* Keyboard*/ |
| 148 | 156 | ||
| 149 | #define KEY_QI_QI KEY_F13 | 157 | #define KEY_QI_QI KEY_F13 |
| @@ -472,6 +480,7 @@ static int __init qi_lb60_init_platform_devices(void) | |||
| 472 | jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata; | 480 | jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata; |
| 473 | 481 | ||
| 474 | gpiod_add_lookup_table(&qi_lb60_audio_gpio_table); | 482 | gpiod_add_lookup_table(&qi_lb60_audio_gpio_table); |
| 483 | gpiod_add_lookup_table(&qi_lb60_nand_gpio_table); | ||
| 475 | 484 | ||
| 476 | jz4740_serial_device_register(); | 485 | jz4740_serial_device_register(); |
| 477 | 486 | ||
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index cc13ea5ce4d5..c0720c1ee4c9 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c | |||
| @@ -15,6 +15,8 @@ | |||
| 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 | #include <uapi/linux/magic.h> | ||
| 19 | |||
| 18 | /* | 20 | /* |
| 19 | * NAND flash on Netgear R6250 was verified to contain 15 partitions. | 21 | * 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 | 22 | * This will result in allocating too big array for some old devices, but the |
| @@ -39,7 +41,8 @@ | |||
| 39 | #define ML_MAGIC1 0x39685a42 | 41 | #define ML_MAGIC1 0x39685a42 |
| 40 | #define ML_MAGIC2 0x26594131 | 42 | #define ML_MAGIC2 0x26594131 |
| 41 | #define TRX_MAGIC 0x30524448 | 43 | #define TRX_MAGIC 0x30524448 |
| 42 | #define SQSH_MAGIC 0x71736873 /* shsq */ | 44 | #define SHSQ_MAGIC 0x71736873 /* shsq (weird ZTE H218N endianness) */ |
| 45 | #define UBI_EC_MAGIC 0x23494255 /* UBI# */ | ||
| 43 | 46 | ||
| 44 | struct trx_header { | 47 | struct trx_header { |
| 45 | uint32_t magic; | 48 | uint32_t magic; |
| @@ -50,7 +53,7 @@ struct trx_header { | |||
| 50 | uint32_t offset[3]; | 53 | uint32_t offset[3]; |
| 51 | } __packed; | 54 | } __packed; |
| 52 | 55 | ||
| 53 | static void bcm47xxpart_add_part(struct mtd_partition *part, char *name, | 56 | static void bcm47xxpart_add_part(struct mtd_partition *part, const char *name, |
| 54 | u64 offset, uint32_t mask_flags) | 57 | u64 offset, uint32_t mask_flags) |
| 55 | { | 58 | { |
| 56 | part->name = name; | 59 | part->name = name; |
| @@ -58,6 +61,26 @@ static void bcm47xxpart_add_part(struct mtd_partition *part, char *name, | |||
| 58 | part->mask_flags = mask_flags; | 61 | part->mask_flags = mask_flags; |
| 59 | } | 62 | } |
| 60 | 63 | ||
| 64 | static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, | ||
| 65 | size_t offset) | ||
| 66 | { | ||
| 67 | uint32_t buf; | ||
| 68 | size_t bytes_read; | ||
| 69 | |||
| 70 | if (mtd_read(master, offset, sizeof(buf), &bytes_read, | ||
| 71 | (uint8_t *)&buf) < 0) { | ||
| 72 | pr_err("mtd_read error while parsing (offset: 0x%X)!\n", | ||
| 73 | offset); | ||
| 74 | goto out_default; | ||
| 75 | } | ||
| 76 | |||
| 77 | if (buf == UBI_EC_MAGIC) | ||
| 78 | return "ubi"; | ||
| 79 | |||
| 80 | out_default: | ||
| 81 | return "rootfs"; | ||
| 82 | } | ||
| 83 | |||
| 61 | static int bcm47xxpart_parse(struct mtd_info *master, | 84 | static int bcm47xxpart_parse(struct mtd_info *master, |
| 62 | struct mtd_partition **pparts, | 85 | struct mtd_partition **pparts, |
| 63 | struct mtd_part_parser_data *data) | 86 | struct mtd_part_parser_data *data) |
| @@ -73,8 +96,12 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
| 73 | int last_trx_part = -1; | 96 | int last_trx_part = -1; |
| 74 | int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; | 97 | int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; |
| 75 | 98 | ||
| 76 | if (blocksize <= 0x10000) | 99 | /* |
| 77 | blocksize = 0x10000; | 100 | * Some really old flashes (like AT45DB*) had smaller erasesize-s, but |
| 101 | * partitions were aligned to at least 0x1000 anyway. | ||
| 102 | */ | ||
| 103 | if (blocksize < 0x1000) | ||
| 104 | blocksize = 0x1000; | ||
| 78 | 105 | ||
| 79 | /* Alloc */ | 106 | /* Alloc */ |
| 80 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, | 107 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, |
| @@ -186,8 +213,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
| 186 | * we want to have jffs2 (overlay) in the same mtd. | 213 | * we want to have jffs2 (overlay) in the same mtd. |
| 187 | */ | 214 | */ |
| 188 | if (trx->offset[i]) { | 215 | if (trx->offset[i]) { |
| 216 | const char *name; | ||
| 217 | |||
| 218 | name = bcm47xxpart_trx_data_part_name(master, offset + trx->offset[i]); | ||
| 189 | bcm47xxpart_add_part(&parts[curr_part++], | 219 | bcm47xxpart_add_part(&parts[curr_part++], |
| 190 | "rootfs", | 220 | name, |
| 191 | offset + trx->offset[i], | 221 | offset + trx->offset[i], |
| 192 | 0); | 222 | 0); |
| 193 | i++; | 223 | i++; |
| @@ -205,7 +235,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
| 205 | } | 235 | } |
| 206 | 236 | ||
| 207 | /* Squashfs on devices not using TRX */ | 237 | /* Squashfs on devices not using TRX */ |
| 208 | if (buf[0x000 / 4] == SQSH_MAGIC) { | 238 | if (le32_to_cpu(buf[0x000 / 4]) == SQUASHFS_MAGIC || |
| 239 | buf[0x000 / 4] == SHSQ_MAGIC) { | ||
| 209 | bcm47xxpart_add_part(&parts[curr_part++], "rootfs", | 240 | bcm47xxpart_add_part(&parts[curr_part++], "rootfs", |
| 210 | offset, 0); | 241 | offset, 0); |
| 211 | continue; | 242 | continue; |
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index 991c2a1c05d3..afb43d5e1782 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c | |||
| @@ -68,6 +68,7 @@ static struct mtd_info *map_ram_probe(struct map_info *map) | |||
| 68 | mtd->_get_unmapped_area = mapram_unmapped_area; | 68 | mtd->_get_unmapped_area = mapram_unmapped_area; |
| 69 | mtd->_read = mapram_read; | 69 | mtd->_read = mapram_read; |
| 70 | mtd->_write = mapram_write; | 70 | mtd->_write = mapram_write; |
| 71 | mtd->_panic_write = mapram_write; | ||
| 71 | mtd->_sync = mapram_nop; | 72 | mtd->_sync = mapram_nop; |
| 72 | mtd->flags = MTD_CAP_RAM; | 73 | mtd->flags = MTD_CAP_RAM; |
| 73 | mtd->writesize = 1; | 74 | mtd->writesize = 1; |
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 47a43cf7e5c6..e67f73ab44c9 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/of.h> | ||
| 14 | #include <linux/mtd/mtd.h> | 15 | #include <linux/mtd/mtd.h> |
| 15 | #include <linux/mtd/map.h> | 16 | #include <linux/mtd/map.h> |
| 16 | 17 | ||
| @@ -28,6 +29,15 @@ static struct mtd_chip_driver maprom_chipdrv = { | |||
| 28 | .module = THIS_MODULE | 29 | .module = THIS_MODULE |
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 32 | static unsigned int default_erasesize(struct map_info *map) | ||
| 33 | { | ||
| 34 | const __be32 *erase_size = NULL; | ||
| 35 | |||
| 36 | erase_size = of_get_property(map->device_node, "erase-size", NULL); | ||
| 37 | |||
| 38 | return !erase_size ? map->size : be32_to_cpu(*erase_size); | ||
| 39 | } | ||
| 40 | |||
| 31 | static struct mtd_info *map_rom_probe(struct map_info *map) | 41 | static struct mtd_info *map_rom_probe(struct map_info *map) |
| 32 | { | 42 | { |
| 33 | struct mtd_info *mtd; | 43 | struct mtd_info *mtd; |
| @@ -47,8 +57,9 @@ static struct mtd_info *map_rom_probe(struct map_info *map) | |||
| 47 | mtd->_sync = maprom_nop; | 57 | mtd->_sync = maprom_nop; |
| 48 | mtd->_erase = maprom_erase; | 58 | mtd->_erase = maprom_erase; |
| 49 | mtd->flags = MTD_CAP_ROM; | 59 | mtd->flags = MTD_CAP_ROM; |
| 50 | mtd->erasesize = map->size; | 60 | mtd->erasesize = default_erasesize(map); |
| 51 | mtd->writesize = 1; | 61 | mtd->writesize = 1; |
| 62 | mtd->writebufsize = 1; | ||
| 52 | 63 | ||
| 53 | __module_get(THIS_MODULE); | 64 | __module_get(THIS_MODULE); |
| 54 | return mtd; | 65 | return mtd; |
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 54ffe5223e64..3060025c8af4 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
| 27 | #include <linux/clk.h> | ||
| 27 | 28 | ||
| 28 | #include "serial_flash_cmds.h" | 29 | #include "serial_flash_cmds.h" |
| 29 | 30 | ||
| @@ -262,6 +263,7 @@ struct stfsm { | |||
| 262 | struct mtd_info mtd; | 263 | struct mtd_info mtd; |
| 263 | struct mutex lock; | 264 | struct mutex lock; |
| 264 | struct flash_info *info; | 265 | struct flash_info *info; |
| 266 | struct clk *clk; | ||
| 265 | 267 | ||
| 266 | uint32_t configuration; | 268 | uint32_t configuration; |
| 267 | uint32_t fifo_dir_delay; | 269 | uint32_t fifo_dir_delay; |
| @@ -663,6 +665,23 @@ static struct stfsm_seq stfsm_seq_write_status = { | |||
| 663 | SEQ_CFG_STARTSEQ), | 665 | SEQ_CFG_STARTSEQ), |
| 664 | }; | 666 | }; |
| 665 | 667 | ||
| 668 | /* Dummy sequence to read one byte of data from flash into the FIFO */ | ||
| 669 | static const struct stfsm_seq stfsm_seq_load_fifo_byte = { | ||
| 670 | .data_size = TRANSFER_SIZE(1), | ||
| 671 | .seq_opc[0] = (SEQ_OPC_PADS_1 | | ||
| 672 | SEQ_OPC_CYCLES(8) | | ||
| 673 | SEQ_OPC_OPCODE(SPINOR_OP_RDID)), | ||
| 674 | .seq = { | ||
| 675 | STFSM_INST_CMD1, | ||
| 676 | STFSM_INST_DATA_READ, | ||
| 677 | STFSM_INST_STOP, | ||
| 678 | }, | ||
| 679 | .seq_cfg = (SEQ_CFG_PADS_1 | | ||
| 680 | SEQ_CFG_READNOTWRITE | | ||
| 681 | SEQ_CFG_CSDEASSERT | | ||
| 682 | SEQ_CFG_STARTSEQ), | ||
| 683 | }; | ||
| 684 | |||
| 666 | static int stfsm_n25q_en_32bit_addr_seq(struct stfsm_seq *seq) | 685 | static int stfsm_n25q_en_32bit_addr_seq(struct stfsm_seq *seq) |
| 667 | { | 686 | { |
| 668 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | | 687 | seq->seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | |
| @@ -695,22 +714,6 @@ static inline uint32_t stfsm_fifo_available(struct stfsm *fsm) | |||
| 695 | return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; | 714 | return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; |
| 696 | } | 715 | } |
| 697 | 716 | ||
| 698 | static void stfsm_clear_fifo(struct stfsm *fsm) | ||
| 699 | { | ||
| 700 | uint32_t avail; | ||
| 701 | |||
| 702 | for (;;) { | ||
| 703 | avail = stfsm_fifo_available(fsm); | ||
| 704 | if (!avail) | ||
| 705 | break; | ||
| 706 | |||
| 707 | while (avail) { | ||
| 708 | readl(fsm->base + SPI_FAST_SEQ_DATA_REG); | ||
| 709 | avail--; | ||
| 710 | } | ||
| 711 | } | ||
| 712 | } | ||
| 713 | |||
| 714 | static inline void stfsm_load_seq(struct stfsm *fsm, | 717 | static inline void stfsm_load_seq(struct stfsm *fsm, |
| 715 | const struct stfsm_seq *seq) | 718 | const struct stfsm_seq *seq) |
| 716 | { | 719 | { |
| @@ -772,6 +775,68 @@ static void stfsm_read_fifo(struct stfsm *fsm, uint32_t *buf, uint32_t size) | |||
| 772 | } | 775 | } |
| 773 | } | 776 | } |
| 774 | 777 | ||
| 778 | /* | ||
| 779 | * Clear the data FIFO | ||
| 780 | * | ||
| 781 | * Typically, this is only required during driver initialisation, where no | ||
| 782 | * assumptions can be made regarding the state of the FIFO. | ||
| 783 | * | ||
| 784 | * The process of clearing the FIFO is complicated by fact that while it is | ||
| 785 | * possible for the FIFO to contain an arbitrary number of bytes [1], the | ||
| 786 | * SPI_FAST_SEQ_STA register only reports the number of complete 32-bit words | ||
| 787 | * present. Furthermore, data can only be drained from the FIFO by reading | ||
| 788 | * complete 32-bit words. | ||
| 789 | * | ||
| 790 | * With this in mind, a two stage process is used to the clear the FIFO: | ||
| 791 | * | ||
| 792 | * 1. Read any complete 32-bit words from the FIFO, as reported by the | ||
| 793 | * SPI_FAST_SEQ_STA register. | ||
| 794 | * | ||
| 795 | * 2. Mop up any remaining bytes. At this point, it is not known if there | ||
| 796 | * are 0, 1, 2, or 3 bytes in the FIFO. To handle all cases, a dummy FSM | ||
| 797 | * sequence is used to load one byte at a time, until a complete 32-bit | ||
| 798 | * word is formed; at most, 4 bytes will need to be loaded. | ||
| 799 | * | ||
| 800 | * [1] It is theoretically possible for the FIFO to contain an arbitrary number | ||
| 801 | * of bits. However, since there are no known use-cases that leave | ||
| 802 | * incomplete bytes in the FIFO, only words and bytes are considered here. | ||
| 803 | */ | ||
| 804 | static void stfsm_clear_fifo(struct stfsm *fsm) | ||
| 805 | { | ||
| 806 | const struct stfsm_seq *seq = &stfsm_seq_load_fifo_byte; | ||
| 807 | uint32_t words, i; | ||
| 808 | |||
| 809 | /* 1. Clear any 32-bit words */ | ||
| 810 | words = stfsm_fifo_available(fsm); | ||
| 811 | if (words) { | ||
| 812 | for (i = 0; i < words; i++) | ||
| 813 | readl(fsm->base + SPI_FAST_SEQ_DATA_REG); | ||
| 814 | dev_dbg(fsm->dev, "cleared %d words from FIFO\n", words); | ||
| 815 | } | ||
| 816 | |||
| 817 | /* | ||
| 818 | * 2. Clear any remaining bytes | ||
| 819 | * - Load the FIFO, one byte at a time, until a complete 32-bit word | ||
| 820 | * is available. | ||
| 821 | */ | ||
| 822 | for (i = 0, words = 0; i < 4 && !words; i++) { | ||
| 823 | stfsm_load_seq(fsm, seq); | ||
| 824 | stfsm_wait_seq(fsm); | ||
| 825 | words = stfsm_fifo_available(fsm); | ||
| 826 | } | ||
| 827 | |||
| 828 | /* - A single word must be available now */ | ||
| 829 | if (words != 1) { | ||
| 830 | dev_err(fsm->dev, "failed to clear bytes from the data FIFO\n"); | ||
| 831 | return; | ||
| 832 | } | ||
| 833 | |||
| 834 | /* - Read the 32-bit word */ | ||
| 835 | readl(fsm->base + SPI_FAST_SEQ_DATA_REG); | ||
| 836 | |||
| 837 | dev_dbg(fsm->dev, "cleared %d byte(s) from the data FIFO\n", 4 - i); | ||
| 838 | } | ||
| 839 | |||
| 775 | static int stfsm_write_fifo(struct stfsm *fsm, const uint32_t *buf, | 840 | static int stfsm_write_fifo(struct stfsm *fsm, const uint32_t *buf, |
| 776 | uint32_t size) | 841 | uint32_t size) |
| 777 | { | 842 | { |
| @@ -1521,11 +1586,11 @@ static int stfsm_write(struct stfsm *fsm, const uint8_t *buf, | |||
| 1521 | uint32_t size_lb; | 1586 | uint32_t size_lb; |
| 1522 | uint32_t size_mop; | 1587 | uint32_t size_mop; |
| 1523 | uint32_t tmp[4]; | 1588 | uint32_t tmp[4]; |
| 1589 | uint32_t i; | ||
| 1524 | uint32_t page_buf[FLASH_PAGESIZE_32]; | 1590 | uint32_t page_buf[FLASH_PAGESIZE_32]; |
| 1525 | uint8_t *t = (uint8_t *)&tmp; | 1591 | uint8_t *t = (uint8_t *)&tmp; |
| 1526 | const uint8_t *p; | 1592 | const uint8_t *p; |
| 1527 | int ret; | 1593 | int ret; |
| 1528 | int i; | ||
| 1529 | 1594 | ||
| 1530 | dev_dbg(fsm->dev, "writing %d bytes to 0x%08x\n", size, offset); | 1595 | dev_dbg(fsm->dev, "writing %d bytes to 0x%08x\n", size, offset); |
| 1531 | 1596 | ||
| @@ -1843,8 +1908,7 @@ static void stfsm_set_freq(struct stfsm *fsm, uint32_t spi_freq) | |||
| 1843 | uint32_t emi_freq; | 1908 | uint32_t emi_freq; |
| 1844 | uint32_t clk_div; | 1909 | uint32_t clk_div; |
| 1845 | 1910 | ||
| 1846 | /* TODO: Make this dynamic */ | 1911 | emi_freq = clk_get_rate(fsm->clk); |
| 1847 | emi_freq = STFSM_DEFAULT_EMI_FREQ; | ||
| 1848 | 1912 | ||
| 1849 | /* | 1913 | /* |
| 1850 | * Calculate clk_div - values between 2 and 128 | 1914 | * Calculate clk_div - values between 2 and 128 |
| @@ -1994,6 +2058,18 @@ static int stfsm_probe(struct platform_device *pdev) | |||
| 1994 | return PTR_ERR(fsm->base); | 2058 | return PTR_ERR(fsm->base); |
| 1995 | } | 2059 | } |
| 1996 | 2060 | ||
| 2061 | fsm->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 2062 | if (IS_ERR(fsm->clk)) { | ||
| 2063 | dev_err(fsm->dev, "Couldn't find EMI clock.\n"); | ||
| 2064 | return PTR_ERR(fsm->clk); | ||
| 2065 | } | ||
| 2066 | |||
| 2067 | ret = clk_prepare_enable(fsm->clk); | ||
| 2068 | if (ret) { | ||
| 2069 | dev_err(fsm->dev, "Failed to enable EMI clock.\n"); | ||
| 2070 | return ret; | ||
| 2071 | } | ||
| 2072 | |||
| 1997 | mutex_init(&fsm->lock); | 2073 | mutex_init(&fsm->lock); |
| 1998 | 2074 | ||
| 1999 | ret = stfsm_init(fsm); | 2075 | ret = stfsm_init(fsm); |
| @@ -2058,6 +2134,28 @@ static int stfsm_remove(struct platform_device *pdev) | |||
| 2058 | return mtd_device_unregister(&fsm->mtd); | 2134 | return mtd_device_unregister(&fsm->mtd); |
| 2059 | } | 2135 | } |
| 2060 | 2136 | ||
| 2137 | #ifdef CONFIG_PM_SLEEP | ||
| 2138 | static int stfsmfsm_suspend(struct device *dev) | ||
| 2139 | { | ||
| 2140 | struct stfsm *fsm = dev_get_drvdata(dev); | ||
| 2141 | |||
| 2142 | clk_disable_unprepare(fsm->clk); | ||
| 2143 | |||
| 2144 | return 0; | ||
| 2145 | } | ||
| 2146 | |||
| 2147 | static int stfsmfsm_resume(struct device *dev) | ||
| 2148 | { | ||
| 2149 | struct stfsm *fsm = dev_get_drvdata(dev); | ||
| 2150 | |||
| 2151 | clk_prepare_enable(fsm->clk); | ||
| 2152 | |||
| 2153 | return 0; | ||
| 2154 | } | ||
| 2155 | #endif | ||
| 2156 | |||
| 2157 | static SIMPLE_DEV_PM_OPS(stfsm_pm_ops, stfsmfsm_suspend, stfsmfsm_resume); | ||
| 2158 | |||
| 2061 | static const struct of_device_id stfsm_match[] = { | 2159 | static const struct of_device_id stfsm_match[] = { |
| 2062 | { .compatible = "st,spi-fsm", }, | 2160 | { .compatible = "st,spi-fsm", }, |
| 2063 | {}, | 2161 | {}, |
| @@ -2070,6 +2168,7 @@ static struct platform_driver stfsm_driver = { | |||
| 2070 | .driver = { | 2168 | .driver = { |
| 2071 | .name = "st-spi-fsm", | 2169 | .name = "st-spi-fsm", |
| 2072 | .of_match_table = stfsm_match, | 2170 | .of_match_table = stfsm_match, |
| 2171 | .pm = &stfsm_pm_ops, | ||
| 2073 | }, | 2172 | }, |
| 2074 | }; | 2173 | }; |
| 2075 | module_platform_driver(stfsm_driver); | 2174 | module_platform_driver(stfsm_driver); |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index f35cd2081314..ff26e979b1a1 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
| @@ -269,6 +269,16 @@ static int of_flash_probe(struct platform_device *dev) | |||
| 269 | info->list[i].mtd = obsolete_probe(dev, | 269 | info->list[i].mtd = obsolete_probe(dev, |
| 270 | &info->list[i].map); | 270 | &info->list[i].map); |
| 271 | } | 271 | } |
| 272 | |||
| 273 | /* Fall back to mapping region as ROM */ | ||
| 274 | if (!info->list[i].mtd) { | ||
| 275 | dev_warn(&dev->dev, | ||
| 276 | "do_map_probe() failed for type %s\n", | ||
| 277 | probe_type); | ||
| 278 | |||
| 279 | info->list[i].mtd = do_map_probe("map_rom", | ||
| 280 | &info->list[i].map); | ||
| 281 | } | ||
| 272 | mtd_list[i] = info->list[i].mtd; | 282 | mtd_list[i] = info->list[i].mtd; |
| 273 | 283 | ||
| 274 | err = -ENXIO; | 284 | err = -ENXIO; |
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 485ea751c7f9..bb4c14f83c75 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c | |||
| @@ -45,8 +45,6 @@ struct mtdblk_dev { | |||
| 45 | enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; | 45 | enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | static DEFINE_MUTEX(mtdblks_lock); | ||
| 49 | |||
| 50 | /* | 48 | /* |
| 51 | * Cache stuff... | 49 | * Cache stuff... |
| 52 | * | 50 | * |
| @@ -286,10 +284,8 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
| 286 | 284 | ||
| 287 | pr_debug("mtdblock_open\n"); | 285 | pr_debug("mtdblock_open\n"); |
| 288 | 286 | ||
| 289 | mutex_lock(&mtdblks_lock); | ||
| 290 | if (mtdblk->count) { | 287 | if (mtdblk->count) { |
| 291 | mtdblk->count++; | 288 | mtdblk->count++; |
| 292 | mutex_unlock(&mtdblks_lock); | ||
| 293 | return 0; | 289 | return 0; |
| 294 | } | 290 | } |
| 295 | 291 | ||
| @@ -302,8 +298,6 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
| 302 | mtdblk->cache_data = NULL; | 298 | mtdblk->cache_data = NULL; |
| 303 | } | 299 | } |
| 304 | 300 | ||
| 305 | mutex_unlock(&mtdblks_lock); | ||
| 306 | |||
| 307 | pr_debug("ok\n"); | 301 | pr_debug("ok\n"); |
| 308 | 302 | ||
| 309 | return 0; | 303 | return 0; |
| @@ -315,8 +309,6 @@ static void mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
| 315 | 309 | ||
| 316 | pr_debug("mtdblock_release\n"); | 310 | pr_debug("mtdblock_release\n"); |
| 317 | 311 | ||
| 318 | mutex_lock(&mtdblks_lock); | ||
| 319 | |||
| 320 | mutex_lock(&mtdblk->cache_mutex); | 312 | mutex_lock(&mtdblk->cache_mutex); |
| 321 | write_cached_data(mtdblk); | 313 | write_cached_data(mtdblk); |
| 322 | mutex_unlock(&mtdblk->cache_mutex); | 314 | mutex_unlock(&mtdblk->cache_mutex); |
| @@ -331,8 +323,6 @@ static void mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
| 331 | vfree(mtdblk->cache_data); | 323 | vfree(mtdblk->cache_data); |
| 332 | } | 324 | } |
| 333 | 325 | ||
| 334 | mutex_unlock(&mtdblks_lock); | ||
| 335 | |||
| 336 | pr_debug("ok\n"); | 326 | pr_debug("ok\n"); |
| 337 | } | 327 | } |
| 338 | 328 | ||
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index b9000563b9f4..d85c9468d30c 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
| @@ -311,7 +311,8 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) | |||
| 311 | devops.len = subdev->size - to; | 311 | devops.len = subdev->size - to; |
| 312 | 312 | ||
| 313 | err = mtd_write_oob(subdev, to, &devops); | 313 | err = mtd_write_oob(subdev, to, &devops); |
| 314 | ops->retlen += devops.oobretlen; | 314 | ops->retlen += devops.retlen; |
| 315 | ops->oobretlen += devops.oobretlen; | ||
| 315 | if (err) | 316 | if (err) |
| 316 | return err; | 317 | return err; |
| 317 | 318 | ||
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 4c611871d7e6..52eea932c312 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/backing-dev.h> | 37 | #include <linux/backing-dev.h> |
| 38 | #include <linux/gfp.h> | 38 | #include <linux/gfp.h> |
| 39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
| 40 | #include <linux/reboot.h> | ||
| 40 | 41 | ||
| 41 | #include <linux/mtd/mtd.h> | 42 | #include <linux/mtd/mtd.h> |
| 42 | #include <linux/mtd/partitions.h> | 43 | #include <linux/mtd/partitions.h> |
| @@ -365,6 +366,17 @@ static struct device_type mtd_devtype = { | |||
| 365 | .release = mtd_release, | 366 | .release = mtd_release, |
| 366 | }; | 367 | }; |
| 367 | 368 | ||
| 369 | static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state, | ||
| 370 | void *cmd) | ||
| 371 | { | ||
| 372 | struct mtd_info *mtd; | ||
| 373 | |||
| 374 | mtd = container_of(n, struct mtd_info, reboot_notifier); | ||
| 375 | mtd->_reboot(mtd); | ||
| 376 | |||
| 377 | return NOTIFY_DONE; | ||
| 378 | } | ||
| 379 | |||
| 368 | /** | 380 | /** |
| 369 | * add_mtd_device - register an MTD device | 381 | * add_mtd_device - register an MTD device |
| 370 | * @mtd: pointer to new MTD device info structure | 382 | * @mtd: pointer to new MTD device info structure |
| @@ -565,6 +577,19 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, | |||
| 565 | err = -ENODEV; | 577 | err = -ENODEV; |
| 566 | } | 578 | } |
| 567 | 579 | ||
| 580 | /* | ||
| 581 | * FIXME: some drivers unfortunately call this function more than once. | ||
| 582 | * So we have to check if we've already assigned the reboot notifier. | ||
| 583 | * | ||
| 584 | * Generally, we can make multiple calls work for most cases, but it | ||
| 585 | * does cause problems with parse_mtd_partitions() above (e.g., | ||
| 586 | * cmdlineparts will register partitions more than once). | ||
| 587 | */ | ||
| 588 | if (mtd->_reboot && !mtd->reboot_notifier.notifier_call) { | ||
| 589 | mtd->reboot_notifier.notifier_call = mtd_reboot_notifier; | ||
| 590 | register_reboot_notifier(&mtd->reboot_notifier); | ||
| 591 | } | ||
| 592 | |||
| 568 | return err; | 593 | return err; |
| 569 | } | 594 | } |
| 570 | EXPORT_SYMBOL_GPL(mtd_device_parse_register); | 595 | EXPORT_SYMBOL_GPL(mtd_device_parse_register); |
| @@ -579,6 +604,9 @@ int mtd_device_unregister(struct mtd_info *master) | |||
| 579 | { | 604 | { |
| 580 | int err; | 605 | int err; |
| 581 | 606 | ||
| 607 | if (master->_reboot) | ||
| 608 | unregister_reboot_notifier(&master->reboot_notifier); | ||
| 609 | |||
| 582 | err = del_mtd_partitions(master); | 610 | err = del_mtd_partitions(master); |
| 583 | if (err) | 611 | if (err) |
| 584 | return err; | 612 | return err; |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 7d0150d20432..5b76a173cd95 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
| @@ -421,7 +421,7 @@ config MTD_NAND_ORION | |||
| 421 | 421 | ||
| 422 | config MTD_NAND_FSL_ELBC | 422 | config MTD_NAND_FSL_ELBC |
| 423 | tristate "NAND support for Freescale eLBC controllers" | 423 | tristate "NAND support for Freescale eLBC controllers" |
| 424 | depends on PPC_OF | 424 | depends on PPC |
| 425 | select FSL_LBC | 425 | select FSL_LBC |
| 426 | help | 426 | help |
| 427 | Various Freescale chips, including the 8313, include a NAND Flash | 427 | Various Freescale chips, including the 8313, include a NAND Flash |
| @@ -524,4 +524,9 @@ config MTD_NAND_SUNXI | |||
| 524 | help | 524 | help |
| 525 | Enables support for NAND Flash chips on Allwinner SoCs. | 525 | Enables support for NAND Flash chips on Allwinner SoCs. |
| 526 | 526 | ||
| 527 | config MTD_NAND_HISI504 | ||
| 528 | tristate "Support for NAND controller on Hisilicon SoC Hip04" | ||
| 529 | help | ||
| 530 | Enables support for NAND controller on Hisilicon SoC Hip04. | ||
| 531 | |||
| 527 | endif # MTD_NAND | 532 | endif # MTD_NAND |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index bd38f21d2e28..582bbd05aff7 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
| @@ -51,5 +51,6 @@ 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 | obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o |
| 54 | obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o | ||
| 54 | 55 | ||
| 55 | nand-objs := nand_base.o nand_bbt.o nand_timings.o | 56 | nand-objs := nand_base.o nand_bbt.o nand_timings.o |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index f1d555cfb332..842f8fe91b56 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
| @@ -183,7 +183,7 @@ static int ams_delta_init(struct platform_device *pdev) | |||
| 183 | return -ENXIO; | 183 | return -ENXIO; |
| 184 | 184 | ||
| 185 | /* Allocate memory for MTD device structure and private data */ | 185 | /* Allocate memory for MTD device structure and private data */ |
| 186 | ams_delta_mtd = kmalloc(sizeof(struct mtd_info) + | 186 | ams_delta_mtd = kzalloc(sizeof(struct mtd_info) + |
| 187 | sizeof(struct nand_chip), GFP_KERNEL); | 187 | sizeof(struct nand_chip), GFP_KERNEL); |
| 188 | if (!ams_delta_mtd) { | 188 | if (!ams_delta_mtd) { |
| 189 | printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n"); | 189 | printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n"); |
| @@ -196,10 +196,6 @@ static int ams_delta_init(struct platform_device *pdev) | |||
| 196 | /* Get pointer to private data */ | 196 | /* Get pointer to private data */ |
| 197 | this = (struct nand_chip *) (&ams_delta_mtd[1]); | 197 | this = (struct nand_chip *) (&ams_delta_mtd[1]); |
| 198 | 198 | ||
| 199 | /* Initialize structures */ | ||
| 200 | memset(ams_delta_mtd, 0, sizeof(struct mtd_info)); | ||
| 201 | memset(this, 0, sizeof(struct nand_chip)); | ||
| 202 | |||
| 203 | /* Link the private data with the MTD structure */ | 199 | /* Link the private data with the MTD structure */ |
| 204 | ams_delta_mtd->priv = this; | 200 | ams_delta_mtd->priv = this; |
| 205 | 201 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index a345e7b2463a..d93c849b70b5 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
| @@ -63,6 +63,10 @@ module_param(on_flash_bbt, int, 0); | |||
| 63 | #include "atmel_nand_ecc.h" /* Hardware ECC registers */ | 63 | #include "atmel_nand_ecc.h" /* Hardware ECC registers */ |
| 64 | #include "atmel_nand_nfc.h" /* Nand Flash Controller definition */ | 64 | #include "atmel_nand_nfc.h" /* Nand Flash Controller definition */ |
| 65 | 65 | ||
| 66 | struct atmel_nand_caps { | ||
| 67 | bool pmecc_correct_erase_page; | ||
| 68 | }; | ||
| 69 | |||
| 66 | /* oob layout for large page size | 70 | /* oob layout for large page size |
| 67 | * bad block info is on bytes 0 and 1 | 71 | * bad block info is on bytes 0 and 1 |
| 68 | * the bytes have to be consecutives to avoid | 72 | * the bytes have to be consecutives to avoid |
| @@ -124,6 +128,7 @@ struct atmel_nand_host { | |||
| 124 | 128 | ||
| 125 | struct atmel_nfc *nfc; | 129 | struct atmel_nfc *nfc; |
| 126 | 130 | ||
| 131 | struct atmel_nand_caps *caps; | ||
| 127 | bool has_pmecc; | 132 | bool has_pmecc; |
| 128 | u8 pmecc_corr_cap; | 133 | u8 pmecc_corr_cap; |
| 129 | u16 pmecc_sector_size; | 134 | u16 pmecc_sector_size; |
| @@ -847,7 +852,11 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, | |||
| 847 | struct atmel_nand_host *host = nand_chip->priv; | 852 | struct atmel_nand_host *host = nand_chip->priv; |
| 848 | int i, err_nbr; | 853 | int i, err_nbr; |
| 849 | uint8_t *buf_pos; | 854 | uint8_t *buf_pos; |
| 850 | int total_err = 0; | 855 | int max_bitflips = 0; |
| 856 | |||
| 857 | /* If can correct bitfilps from erased page, do the normal check */ | ||
| 858 | if (host->caps->pmecc_correct_erase_page) | ||
| 859 | goto normal_check; | ||
| 851 | 860 | ||
| 852 | for (i = 0; i < nand_chip->ecc.total; i++) | 861 | for (i = 0; i < nand_chip->ecc.total; i++) |
| 853 | if (ecc[i] != 0xff) | 862 | if (ecc[i] != 0xff) |
| @@ -874,13 +883,13 @@ normal_check: | |||
| 874 | pmecc_correct_data(mtd, buf_pos, ecc, i, | 883 | pmecc_correct_data(mtd, buf_pos, ecc, i, |
| 875 | nand_chip->ecc.bytes, err_nbr); | 884 | nand_chip->ecc.bytes, err_nbr); |
| 876 | mtd->ecc_stats.corrected += err_nbr; | 885 | mtd->ecc_stats.corrected += err_nbr; |
| 877 | total_err += err_nbr; | 886 | max_bitflips = max_t(int, max_bitflips, err_nbr); |
| 878 | } | 887 | } |
| 879 | } | 888 | } |
| 880 | pmecc_stat >>= 1; | 889 | pmecc_stat >>= 1; |
| 881 | } | 890 | } |
| 882 | 891 | ||
| 883 | return total_err; | 892 | return max_bitflips; |
| 884 | } | 893 | } |
| 885 | 894 | ||
| 886 | static void pmecc_enable(struct atmel_nand_host *host, int ecc_op) | 895 | static void pmecc_enable(struct atmel_nand_host *host, int ecc_op) |
| @@ -1474,6 +1483,8 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
| 1474 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); | 1483 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); |
| 1475 | } | 1484 | } |
| 1476 | 1485 | ||
| 1486 | static const struct of_device_id atmel_nand_dt_ids[]; | ||
| 1487 | |||
| 1477 | static int atmel_of_init_port(struct atmel_nand_host *host, | 1488 | static int atmel_of_init_port(struct atmel_nand_host *host, |
| 1478 | struct device_node *np) | 1489 | struct device_node *np) |
| 1479 | { | 1490 | { |
| @@ -1483,6 +1494,9 @@ static int atmel_of_init_port(struct atmel_nand_host *host, | |||
| 1483 | struct atmel_nand_data *board = &host->board; | 1494 | struct atmel_nand_data *board = &host->board; |
| 1484 | enum of_gpio_flags flags = 0; | 1495 | enum of_gpio_flags flags = 0; |
| 1485 | 1496 | ||
| 1497 | host->caps = (struct atmel_nand_caps *) | ||
| 1498 | of_match_device(atmel_nand_dt_ids, host->dev)->data; | ||
| 1499 | |||
| 1486 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { | 1500 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { |
| 1487 | if (val >= 32) { | 1501 | if (val >= 32) { |
| 1488 | dev_err(host->dev, "invalid addr-offset %u\n", val); | 1502 | dev_err(host->dev, "invalid addr-offset %u\n", val); |
| @@ -2288,8 +2302,17 @@ static int atmel_nand_remove(struct platform_device *pdev) | |||
| 2288 | return 0; | 2302 | return 0; |
| 2289 | } | 2303 | } |
| 2290 | 2304 | ||
| 2305 | static struct atmel_nand_caps at91rm9200_caps = { | ||
| 2306 | .pmecc_correct_erase_page = false, | ||
| 2307 | }; | ||
| 2308 | |||
| 2309 | static struct atmel_nand_caps sama5d4_caps = { | ||
| 2310 | .pmecc_correct_erase_page = true, | ||
| 2311 | }; | ||
| 2312 | |||
| 2291 | static const struct of_device_id atmel_nand_dt_ids[] = { | 2313 | static const struct of_device_id atmel_nand_dt_ids[] = { |
| 2292 | { .compatible = "atmel,at91rm9200-nand" }, | 2314 | { .compatible = "atmel,at91rm9200-nand", .data = &at91rm9200_caps }, |
| 2315 | { .compatible = "atmel,sama5d4-nand", .data = &sama5d4_caps }, | ||
| 2293 | { /* sentinel */ } | 2316 | { /* sentinel */ } |
| 2294 | }; | 2317 | }; |
| 2295 | 2318 | ||
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index b3b7ca1bafb8..f44c6061536a 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
| @@ -1041,7 +1041,7 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op) | |||
| 1041 | index_addr(denali, mode | ((addr >> 16) << 8), 0x2200); | 1041 | index_addr(denali, mode | ((addr >> 16) << 8), 0x2200); |
| 1042 | 1042 | ||
| 1043 | /* 3. set memory low address bits 23:8 */ | 1043 | /* 3. set memory low address bits 23:8 */ |
| 1044 | index_addr(denali, mode | ((addr & 0xff) << 8), 0x2300); | 1044 | index_addr(denali, mode | ((addr & 0xffff) << 8), 0x2300); |
| 1045 | 1045 | ||
| 1046 | /* 4. interrupt when complete, burst len = 64 bytes */ | 1046 | /* 4. interrupt when complete, burst len = 64 bytes */ |
| 1047 | index_addr(denali, mode | 0x14000, 0x2400); | 1047 | index_addr(denali, mode | 0x14000, 0x2400); |
| @@ -1328,35 +1328,6 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
| 1328 | break; | 1328 | break; |
| 1329 | } | 1329 | } |
| 1330 | } | 1330 | } |
| 1331 | |||
| 1332 | /* stubs for ECC functions not used by the NAND core */ | ||
| 1333 | static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | ||
| 1334 | uint8_t *ecc_code) | ||
| 1335 | { | ||
| 1336 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1337 | |||
| 1338 | dev_err(denali->dev, "denali_ecc_calculate called unexpectedly\n"); | ||
| 1339 | BUG(); | ||
| 1340 | return -EIO; | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, | ||
| 1344 | uint8_t *read_ecc, uint8_t *calc_ecc) | ||
| 1345 | { | ||
| 1346 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1347 | |||
| 1348 | dev_err(denali->dev, "denali_ecc_correct called unexpectedly\n"); | ||
| 1349 | BUG(); | ||
| 1350 | return -EIO; | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | static void denali_ecc_hwctl(struct mtd_info *mtd, int mode) | ||
| 1354 | { | ||
| 1355 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1356 | |||
| 1357 | dev_err(denali->dev, "denali_ecc_hwctl called unexpectedly\n"); | ||
| 1358 | BUG(); | ||
| 1359 | } | ||
| 1360 | /* end NAND core entry points */ | 1331 | /* end NAND core entry points */ |
| 1361 | 1332 | ||
| 1362 | /* Initialization code to bring the device up to a known good state */ | 1333 | /* Initialization code to bring the device up to a known good state */ |
| @@ -1609,15 +1580,6 @@ int denali_init(struct denali_nand_info *denali) | |||
| 1609 | denali->totalblks = denali->mtd.size >> denali->nand.phys_erase_shift; | 1580 | denali->totalblks = denali->mtd.size >> denali->nand.phys_erase_shift; |
| 1610 | denali->blksperchip = denali->totalblks / denali->nand.numchips; | 1581 | denali->blksperchip = denali->totalblks / denali->nand.numchips; |
| 1611 | 1582 | ||
| 1612 | /* | ||
| 1613 | * These functions are required by the NAND core framework, otherwise, | ||
| 1614 | * the NAND core will assert. However, we don't need them, so we'll stub | ||
| 1615 | * them out. | ||
| 1616 | */ | ||
| 1617 | denali->nand.ecc.calculate = denali_ecc_calculate; | ||
| 1618 | denali->nand.ecc.correct = denali_ecc_correct; | ||
| 1619 | denali->nand.ecc.hwctl = denali_ecc_hwctl; | ||
| 1620 | |||
| 1621 | /* override the default read operations */ | 1583 | /* override the default read operations */ |
| 1622 | denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum; | 1584 | denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum; |
| 1623 | denali->nand.ecc.read_page = denali_read_page; | 1585 | denali->nand.ecc.read_page = denali_read_page; |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 4f3851a24bb2..33f3c3c54dbc 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
| @@ -1294,14 +1294,6 @@ exit_auxiliary: | |||
| 1294 | * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an | 1294 | * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an |
| 1295 | * ECC-based or raw view of the page is implicit in which function it calls | 1295 | * ECC-based or raw view of the page is implicit in which function it calls |
| 1296 | * (there is a similar pair of ECC-based/raw functions for writing). | 1296 | * (there is a similar pair of ECC-based/raw functions for writing). |
| 1297 | * | ||
| 1298 | * FIXME: The following paragraph is incorrect, now that there exist | ||
| 1299 | * ecc.read_oob_raw and ecc.write_oob_raw functions. | ||
| 1300 | * | ||
| 1301 | * Since MTD assumes the OOB is not covered by ECC, there is no pair of | ||
| 1302 | * ECC-based/raw functions for reading or or writing the OOB. The fact that the | ||
| 1303 | * caller wants an ECC-based or raw view of the page is not propagated down to | ||
| 1304 | * this driver. | ||
| 1305 | */ | 1297 | */ |
| 1306 | static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1298 | static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
| 1307 | int page) | 1299 | int page) |
| @@ -2029,7 +2021,6 @@ static int gpmi_nand_probe(struct platform_device *pdev) | |||
| 2029 | exit_nfc_init: | 2021 | exit_nfc_init: |
| 2030 | release_resources(this); | 2022 | release_resources(this); |
| 2031 | exit_acquire_resources: | 2023 | exit_acquire_resources: |
| 2032 | dev_err(this->dev, "driver registration failed: %d\n", ret); | ||
| 2033 | 2024 | ||
| 2034 | return ret; | 2025 | return ret; |
| 2035 | } | 2026 | } |
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c new file mode 100644 index 000000000000..289ad3ac3e80 --- /dev/null +++ b/drivers/mtd/nand/hisi504_nand.c | |||
| @@ -0,0 +1,891 @@ | |||
| 1 | /* | ||
| 2 | * Hisilicon NAND Flash controller driver | ||
| 3 | * | ||
| 4 | * Copyright © 2012-2014 HiSilicon Technologies Co., Ltd. | ||
| 5 | * http://www.hisilicon.com | ||
| 6 | * | ||
| 7 | * Author: Zhou Wang <wangzhou.bry@gmail.com> | ||
| 8 | * The initial developer of the original code is Zhiyong Cai | ||
| 9 | * <caizhiyong@huawei.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | */ | ||
| 21 | #include <linux/of.h> | ||
| 22 | #include <linux/of_mtd.h> | ||
| 23 | #include <linux/mtd/mtd.h> | ||
| 24 | #include <linux/sizes.h> | ||
| 25 | #include <linux/clk.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/interrupt.h> | ||
| 30 | #include <linux/mtd/nand.h> | ||
| 31 | #include <linux/dma-mapping.h> | ||
| 32 | #include <linux/platform_device.h> | ||
| 33 | #include <linux/mtd/partitions.h> | ||
| 34 | |||
| 35 | #define HINFC504_MAX_CHIP (4) | ||
| 36 | #define HINFC504_W_LATCH (5) | ||
| 37 | #define HINFC504_R_LATCH (7) | ||
| 38 | #define HINFC504_RW_LATCH (3) | ||
| 39 | |||
| 40 | #define HINFC504_NFC_TIMEOUT (2 * HZ) | ||
| 41 | #define HINFC504_NFC_PM_TIMEOUT (1 * HZ) | ||
| 42 | #define HINFC504_NFC_DMA_TIMEOUT (5 * HZ) | ||
| 43 | #define HINFC504_CHIP_DELAY (25) | ||
| 44 | |||
| 45 | #define HINFC504_REG_BASE_ADDRESS_LEN (0x100) | ||
| 46 | #define HINFC504_BUFFER_BASE_ADDRESS_LEN (2048 + 128) | ||
| 47 | |||
| 48 | #define HINFC504_ADDR_CYCLE_MASK 0x4 | ||
| 49 | |||
| 50 | #define HINFC504_CON 0x00 | ||
| 51 | #define HINFC504_CON_OP_MODE_NORMAL BIT(0) | ||
| 52 | #define HINFC504_CON_PAGEISZE_SHIFT (1) | ||
| 53 | #define HINFC504_CON_PAGESIZE_MASK (0x07) | ||
| 54 | #define HINFC504_CON_BUS_WIDTH BIT(4) | ||
| 55 | #define HINFC504_CON_READY_BUSY_SEL BIT(8) | ||
| 56 | #define HINFC504_CON_ECCTYPE_SHIFT (9) | ||
| 57 | #define HINFC504_CON_ECCTYPE_MASK (0x07) | ||
| 58 | |||
| 59 | #define HINFC504_PWIDTH 0x04 | ||
| 60 | #define SET_HINFC504_PWIDTH(_w_lcnt, _r_lcnt, _rw_hcnt) \ | ||
| 61 | ((_w_lcnt) | (((_r_lcnt) & 0x0F) << 4) | (((_rw_hcnt) & 0x0F) << 8)) | ||
| 62 | |||
| 63 | #define HINFC504_CMD 0x0C | ||
| 64 | #define HINFC504_ADDRL 0x10 | ||
| 65 | #define HINFC504_ADDRH 0x14 | ||
| 66 | #define HINFC504_DATA_NUM 0x18 | ||
| 67 | |||
| 68 | #define HINFC504_OP 0x1C | ||
| 69 | #define HINFC504_OP_READ_DATA_EN BIT(1) | ||
| 70 | #define HINFC504_OP_WAIT_READY_EN BIT(2) | ||
| 71 | #define HINFC504_OP_CMD2_EN BIT(3) | ||
| 72 | #define HINFC504_OP_WRITE_DATA_EN BIT(4) | ||
| 73 | #define HINFC504_OP_ADDR_EN BIT(5) | ||
| 74 | #define HINFC504_OP_CMD1_EN BIT(6) | ||
| 75 | #define HINFC504_OP_NF_CS_SHIFT (7) | ||
| 76 | #define HINFC504_OP_NF_CS_MASK (3) | ||
| 77 | #define HINFC504_OP_ADDR_CYCLE_SHIFT (9) | ||
| 78 | #define HINFC504_OP_ADDR_CYCLE_MASK (7) | ||
| 79 | |||
| 80 | #define HINFC504_STATUS 0x20 | ||
| 81 | #define HINFC504_READY BIT(0) | ||
| 82 | |||
| 83 | #define HINFC504_INTEN 0x24 | ||
| 84 | #define HINFC504_INTEN_DMA BIT(9) | ||
| 85 | #define HINFC504_INTEN_UE BIT(6) | ||
| 86 | #define HINFC504_INTEN_CE BIT(5) | ||
| 87 | |||
| 88 | #define HINFC504_INTS 0x28 | ||
| 89 | #define HINFC504_INTS_DMA BIT(9) | ||
| 90 | #define HINFC504_INTS_UE BIT(6) | ||
| 91 | #define HINFC504_INTS_CE BIT(5) | ||
| 92 | |||
| 93 | #define HINFC504_INTCLR 0x2C | ||
| 94 | #define HINFC504_INTCLR_DMA BIT(9) | ||
| 95 | #define HINFC504_INTCLR_UE BIT(6) | ||
| 96 | #define HINFC504_INTCLR_CE BIT(5) | ||
| 97 | |||
| 98 | #define HINFC504_ECC_STATUS 0x5C | ||
| 99 | #define HINFC504_ECC_16_BIT_SHIFT 12 | ||
| 100 | |||
| 101 | #define HINFC504_DMA_CTRL 0x60 | ||
| 102 | #define HINFC504_DMA_CTRL_DMA_START BIT(0) | ||
| 103 | #define HINFC504_DMA_CTRL_WE BIT(1) | ||
| 104 | #define HINFC504_DMA_CTRL_DATA_AREA_EN BIT(2) | ||
| 105 | #define HINFC504_DMA_CTRL_OOB_AREA_EN BIT(3) | ||
| 106 | #define HINFC504_DMA_CTRL_BURST4_EN BIT(4) | ||
| 107 | #define HINFC504_DMA_CTRL_BURST8_EN BIT(5) | ||
| 108 | #define HINFC504_DMA_CTRL_BURST16_EN BIT(6) | ||
| 109 | #define HINFC504_DMA_CTRL_ADDR_NUM_SHIFT (7) | ||
| 110 | #define HINFC504_DMA_CTRL_ADDR_NUM_MASK (1) | ||
| 111 | #define HINFC504_DMA_CTRL_CS_SHIFT (8) | ||
| 112 | #define HINFC504_DMA_CTRL_CS_MASK (0x03) | ||
| 113 | |||
| 114 | #define HINFC504_DMA_ADDR_DATA 0x64 | ||
| 115 | #define HINFC504_DMA_ADDR_OOB 0x68 | ||
| 116 | |||
| 117 | #define HINFC504_DMA_LEN 0x6C | ||
| 118 | #define HINFC504_DMA_LEN_OOB_SHIFT (16) | ||
| 119 | #define HINFC504_DMA_LEN_OOB_MASK (0xFFF) | ||
| 120 | |||
| 121 | #define HINFC504_DMA_PARA 0x70 | ||
| 122 | #define HINFC504_DMA_PARA_DATA_RW_EN BIT(0) | ||
| 123 | #define HINFC504_DMA_PARA_OOB_RW_EN BIT(1) | ||
| 124 | #define HINFC504_DMA_PARA_DATA_EDC_EN BIT(2) | ||
| 125 | #define HINFC504_DMA_PARA_OOB_EDC_EN BIT(3) | ||
| 126 | #define HINFC504_DMA_PARA_DATA_ECC_EN BIT(4) | ||
| 127 | #define HINFC504_DMA_PARA_OOB_ECC_EN BIT(5) | ||
| 128 | |||
| 129 | #define HINFC_VERSION 0x74 | ||
| 130 | #define HINFC504_LOG_READ_ADDR 0x7C | ||
| 131 | #define HINFC504_LOG_READ_LEN 0x80 | ||
| 132 | |||
| 133 | #define HINFC504_NANDINFO_LEN 0x10 | ||
| 134 | |||
| 135 | struct hinfc_host { | ||
| 136 | struct nand_chip chip; | ||
| 137 | struct mtd_info mtd; | ||
| 138 | struct device *dev; | ||
| 139 | void __iomem *iobase; | ||
| 140 | void __iomem *mmio; | ||
| 141 | struct completion cmd_complete; | ||
| 142 | unsigned int offset; | ||
| 143 | unsigned int command; | ||
| 144 | int chipselect; | ||
| 145 | unsigned int addr_cycle; | ||
| 146 | u32 addr_value[2]; | ||
| 147 | u32 cache_addr_value[2]; | ||
| 148 | char *buffer; | ||
| 149 | dma_addr_t dma_buffer; | ||
| 150 | dma_addr_t dma_oob; | ||
| 151 | int version; | ||
| 152 | unsigned int irq_status; /* interrupt status */ | ||
| 153 | }; | ||
| 154 | |||
| 155 | static inline unsigned int hinfc_read(struct hinfc_host *host, unsigned int reg) | ||
| 156 | { | ||
| 157 | return readl(host->iobase + reg); | ||
| 158 | } | ||
| 159 | |||
| 160 | static inline void hinfc_write(struct hinfc_host *host, unsigned int value, | ||
| 161 | unsigned int reg) | ||
| 162 | { | ||
| 163 | writel(value, host->iobase + reg); | ||
| 164 | } | ||
| 165 | |||
| 166 | static void wait_controller_finished(struct hinfc_host *host) | ||
| 167 | { | ||
| 168 | unsigned long timeout = jiffies + HINFC504_NFC_TIMEOUT; | ||
| 169 | int val; | ||
| 170 | |||
| 171 | while (time_before(jiffies, timeout)) { | ||
| 172 | val = hinfc_read(host, HINFC504_STATUS); | ||
| 173 | if (host->command == NAND_CMD_ERASE2) { | ||
| 174 | /* nfc is ready */ | ||
| 175 | while (!(val & HINFC504_READY)) { | ||
| 176 | usleep_range(500, 1000); | ||
| 177 | val = hinfc_read(host, HINFC504_STATUS); | ||
| 178 | } | ||
| 179 | return; | ||
| 180 | } | ||
| 181 | |||
| 182 | if (val & HINFC504_READY) | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | |||
| 186 | /* wait cmd timeout */ | ||
| 187 | dev_err(host->dev, "Wait NAND controller exec cmd timeout.\n"); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void hisi_nfc_dma_transfer(struct hinfc_host *host, int todev) | ||
| 191 | { | ||
| 192 | struct mtd_info *mtd = &host->mtd; | ||
| 193 | struct nand_chip *chip = mtd->priv; | ||
| 194 | unsigned long val; | ||
| 195 | int ret; | ||
| 196 | |||
| 197 | hinfc_write(host, host->dma_buffer, HINFC504_DMA_ADDR_DATA); | ||
| 198 | hinfc_write(host, host->dma_oob, HINFC504_DMA_ADDR_OOB); | ||
| 199 | |||
| 200 | if (chip->ecc.mode == NAND_ECC_NONE) { | ||
| 201 | hinfc_write(host, ((mtd->oobsize & HINFC504_DMA_LEN_OOB_MASK) | ||
| 202 | << HINFC504_DMA_LEN_OOB_SHIFT), HINFC504_DMA_LEN); | ||
| 203 | |||
| 204 | hinfc_write(host, HINFC504_DMA_PARA_DATA_RW_EN | ||
| 205 | | HINFC504_DMA_PARA_OOB_RW_EN, HINFC504_DMA_PARA); | ||
| 206 | } else { | ||
| 207 | if (host->command == NAND_CMD_READOOB) | ||
| 208 | hinfc_write(host, HINFC504_DMA_PARA_OOB_RW_EN | ||
| 209 | | HINFC504_DMA_PARA_OOB_EDC_EN | ||
| 210 | | HINFC504_DMA_PARA_OOB_ECC_EN, HINFC504_DMA_PARA); | ||
| 211 | else | ||
| 212 | hinfc_write(host, HINFC504_DMA_PARA_DATA_RW_EN | ||
| 213 | | HINFC504_DMA_PARA_OOB_RW_EN | ||
| 214 | | HINFC504_DMA_PARA_DATA_EDC_EN | ||
| 215 | | HINFC504_DMA_PARA_OOB_EDC_EN | ||
| 216 | | HINFC504_DMA_PARA_DATA_ECC_EN | ||
| 217 | | HINFC504_DMA_PARA_OOB_ECC_EN, HINFC504_DMA_PARA); | ||
| 218 | |||
| 219 | } | ||
| 220 | |||
| 221 | val = (HINFC504_DMA_CTRL_DMA_START | HINFC504_DMA_CTRL_BURST4_EN | ||
| 222 | | HINFC504_DMA_CTRL_BURST8_EN | HINFC504_DMA_CTRL_BURST16_EN | ||
| 223 | | HINFC504_DMA_CTRL_DATA_AREA_EN | HINFC504_DMA_CTRL_OOB_AREA_EN | ||
| 224 | | ((host->addr_cycle == 4 ? 1 : 0) | ||
| 225 | << HINFC504_DMA_CTRL_ADDR_NUM_SHIFT) | ||
| 226 | | ((host->chipselect & HINFC504_DMA_CTRL_CS_MASK) | ||
| 227 | << HINFC504_DMA_CTRL_CS_SHIFT)); | ||
| 228 | |||
| 229 | if (todev) | ||
| 230 | val |= HINFC504_DMA_CTRL_WE; | ||
| 231 | |||
| 232 | init_completion(&host->cmd_complete); | ||
| 233 | |||
| 234 | hinfc_write(host, val, HINFC504_DMA_CTRL); | ||
| 235 | ret = wait_for_completion_timeout(&host->cmd_complete, | ||
| 236 | HINFC504_NFC_DMA_TIMEOUT); | ||
| 237 | |||
| 238 | if (!ret) { | ||
| 239 | dev_err(host->dev, "DMA operation(irq) timeout!\n"); | ||
| 240 | /* sanity check */ | ||
| 241 | val = hinfc_read(host, HINFC504_DMA_CTRL); | ||
| 242 | if (!(val & HINFC504_DMA_CTRL_DMA_START)) | ||
| 243 | dev_err(host->dev, "DMA is already done but without irq ACK!\n"); | ||
| 244 | else | ||
| 245 | dev_err(host->dev, "DMA is really timeout!\n"); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | static int hisi_nfc_send_cmd_pageprog(struct hinfc_host *host) | ||
| 250 | { | ||
| 251 | host->addr_value[0] &= 0xffff0000; | ||
| 252 | |||
| 253 | hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); | ||
| 254 | hinfc_write(host, host->addr_value[1], HINFC504_ADDRH); | ||
| 255 | hinfc_write(host, NAND_CMD_PAGEPROG << 8 | NAND_CMD_SEQIN, | ||
| 256 | HINFC504_CMD); | ||
| 257 | |||
| 258 | hisi_nfc_dma_transfer(host, 1); | ||
| 259 | |||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int hisi_nfc_send_cmd_readstart(struct hinfc_host *host) | ||
| 264 | { | ||
| 265 | struct mtd_info *mtd = &host->mtd; | ||
| 266 | |||
| 267 | if ((host->addr_value[0] == host->cache_addr_value[0]) && | ||
| 268 | (host->addr_value[1] == host->cache_addr_value[1])) | ||
| 269 | return 0; | ||
| 270 | |||
| 271 | host->addr_value[0] &= 0xffff0000; | ||
| 272 | |||
| 273 | hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); | ||
| 274 | hinfc_write(host, host->addr_value[1], HINFC504_ADDRH); | ||
| 275 | hinfc_write(host, NAND_CMD_READSTART << 8 | NAND_CMD_READ0, | ||
| 276 | HINFC504_CMD); | ||
| 277 | |||
| 278 | hinfc_write(host, 0, HINFC504_LOG_READ_ADDR); | ||
| 279 | hinfc_write(host, mtd->writesize + mtd->oobsize, | ||
| 280 | HINFC504_LOG_READ_LEN); | ||
| 281 | |||
| 282 | hisi_nfc_dma_transfer(host, 0); | ||
| 283 | |||
| 284 | host->cache_addr_value[0] = host->addr_value[0]; | ||
| 285 | host->cache_addr_value[1] = host->addr_value[1]; | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int hisi_nfc_send_cmd_erase(struct hinfc_host *host) | ||
| 291 | { | ||
| 292 | hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); | ||
| 293 | hinfc_write(host, (NAND_CMD_ERASE2 << 8) | NAND_CMD_ERASE1, | ||
| 294 | HINFC504_CMD); | ||
| 295 | |||
| 296 | hinfc_write(host, HINFC504_OP_WAIT_READY_EN | ||
| 297 | | HINFC504_OP_CMD2_EN | ||
| 298 | | HINFC504_OP_CMD1_EN | ||
| 299 | | HINFC504_OP_ADDR_EN | ||
| 300 | | ((host->chipselect & HINFC504_OP_NF_CS_MASK) | ||
| 301 | << HINFC504_OP_NF_CS_SHIFT) | ||
| 302 | | ((host->addr_cycle & HINFC504_OP_ADDR_CYCLE_MASK) | ||
| 303 | << HINFC504_OP_ADDR_CYCLE_SHIFT), | ||
| 304 | HINFC504_OP); | ||
| 305 | |||
| 306 | wait_controller_finished(host); | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static int hisi_nfc_send_cmd_readid(struct hinfc_host *host) | ||
| 312 | { | ||
| 313 | hinfc_write(host, HINFC504_NANDINFO_LEN, HINFC504_DATA_NUM); | ||
| 314 | hinfc_write(host, NAND_CMD_READID, HINFC504_CMD); | ||
| 315 | hinfc_write(host, 0, HINFC504_ADDRL); | ||
| 316 | |||
| 317 | hinfc_write(host, HINFC504_OP_CMD1_EN | HINFC504_OP_ADDR_EN | ||
| 318 | | HINFC504_OP_READ_DATA_EN | ||
| 319 | | ((host->chipselect & HINFC504_OP_NF_CS_MASK) | ||
| 320 | << HINFC504_OP_NF_CS_SHIFT) | ||
| 321 | | 1 << HINFC504_OP_ADDR_CYCLE_SHIFT, HINFC504_OP); | ||
| 322 | |||
| 323 | wait_controller_finished(host); | ||
| 324 | |||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int hisi_nfc_send_cmd_status(struct hinfc_host *host) | ||
| 329 | { | ||
| 330 | hinfc_write(host, HINFC504_NANDINFO_LEN, HINFC504_DATA_NUM); | ||
| 331 | hinfc_write(host, NAND_CMD_STATUS, HINFC504_CMD); | ||
| 332 | hinfc_write(host, HINFC504_OP_CMD1_EN | ||
| 333 | | HINFC504_OP_READ_DATA_EN | ||
| 334 | | ((host->chipselect & HINFC504_OP_NF_CS_MASK) | ||
| 335 | << HINFC504_OP_NF_CS_SHIFT), | ||
| 336 | HINFC504_OP); | ||
| 337 | |||
| 338 | wait_controller_finished(host); | ||
| 339 | |||
| 340 | return 0; | ||
| 341 | } | ||
| 342 | |||
| 343 | static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect) | ||
| 344 | { | ||
| 345 | hinfc_write(host, NAND_CMD_RESET, HINFC504_CMD); | ||
| 346 | |||
| 347 | hinfc_write(host, HINFC504_OP_CMD1_EN | ||
| 348 | | ((chipselect & HINFC504_OP_NF_CS_MASK) | ||
| 349 | << HINFC504_OP_NF_CS_SHIFT) | ||
| 350 | | HINFC504_OP_WAIT_READY_EN, | ||
| 351 | HINFC504_OP); | ||
| 352 | |||
| 353 | wait_controller_finished(host); | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect) | ||
| 359 | { | ||
| 360 | struct nand_chip *chip = mtd->priv; | ||
| 361 | struct hinfc_host *host = chip->priv; | ||
| 362 | |||
| 363 | if (chipselect < 0) | ||
| 364 | return; | ||
| 365 | |||
| 366 | host->chipselect = chipselect; | ||
| 367 | } | ||
| 368 | |||
| 369 | static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd) | ||
| 370 | { | ||
| 371 | struct nand_chip *chip = mtd->priv; | ||
| 372 | struct hinfc_host *host = chip->priv; | ||
| 373 | |||
| 374 | if (host->command == NAND_CMD_STATUS) | ||
| 375 | return *(uint8_t *)(host->mmio); | ||
| 376 | |||
| 377 | host->offset++; | ||
| 378 | |||
| 379 | if (host->command == NAND_CMD_READID) | ||
| 380 | return *(uint8_t *)(host->mmio + host->offset - 1); | ||
| 381 | |||
| 382 | return *(uint8_t *)(host->buffer + host->offset - 1); | ||
| 383 | } | ||
| 384 | |||
| 385 | static u16 hisi_nfc_read_word(struct mtd_info *mtd) | ||
| 386 | { | ||
| 387 | struct nand_chip *chip = mtd->priv; | ||
| 388 | struct hinfc_host *host = chip->priv; | ||
| 389 | |||
| 390 | host->offset += 2; | ||
| 391 | return *(u16 *)(host->buffer + host->offset - 2); | ||
| 392 | } | ||
| 393 | |||
| 394 | static void | ||
| 395 | hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | ||
| 396 | { | ||
| 397 | struct nand_chip *chip = mtd->priv; | ||
| 398 | struct hinfc_host *host = chip->priv; | ||
| 399 | |||
| 400 | memcpy(host->buffer + host->offset, buf, len); | ||
| 401 | host->offset += len; | ||
| 402 | } | ||
| 403 | |||
| 404 | static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
| 405 | { | ||
| 406 | struct nand_chip *chip = mtd->priv; | ||
| 407 | struct hinfc_host *host = chip->priv; | ||
| 408 | |||
| 409 | memcpy(buf, host->buffer + host->offset, len); | ||
| 410 | host->offset += len; | ||
| 411 | } | ||
| 412 | |||
| 413 | static void set_addr(struct mtd_info *mtd, int column, int page_addr) | ||
| 414 | { | ||
| 415 | struct nand_chip *chip = mtd->priv; | ||
| 416 | struct hinfc_host *host = chip->priv; | ||
| 417 | unsigned int command = host->command; | ||
| 418 | |||
| 419 | host->addr_cycle = 0; | ||
| 420 | host->addr_value[0] = 0; | ||
| 421 | host->addr_value[1] = 0; | ||
| 422 | |||
| 423 | /* Serially input address */ | ||
| 424 | if (column != -1) { | ||
| 425 | /* Adjust columns for 16 bit buswidth */ | ||
| 426 | if (chip->options & NAND_BUSWIDTH_16 && | ||
| 427 | !nand_opcode_8bits(command)) | ||
| 428 | column >>= 1; | ||
| 429 | |||
| 430 | host->addr_value[0] = column & 0xffff; | ||
| 431 | host->addr_cycle = 2; | ||
| 432 | } | ||
| 433 | if (page_addr != -1) { | ||
| 434 | host->addr_value[0] |= (page_addr & 0xffff) | ||
| 435 | << (host->addr_cycle * 8); | ||
| 436 | host->addr_cycle += 2; | ||
| 437 | /* One more address cycle for devices > 128MiB */ | ||
| 438 | if (chip->chipsize > (128 << 20)) { | ||
| 439 | host->addr_cycle += 1; | ||
| 440 | if (host->command == NAND_CMD_ERASE1) | ||
| 441 | host->addr_value[0] |= ((page_addr >> 16) & 0xff) << 16; | ||
| 442 | else | ||
| 443 | host->addr_value[1] |= ((page_addr >> 16) & 0xff); | ||
| 444 | } | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column, | ||
| 449 | int page_addr) | ||
| 450 | { | ||
| 451 | struct nand_chip *chip = mtd->priv; | ||
| 452 | struct hinfc_host *host = chip->priv; | ||
| 453 | int is_cache_invalid = 1; | ||
| 454 | unsigned int flag = 0; | ||
| 455 | |||
| 456 | host->command = command; | ||
| 457 | |||
| 458 | switch (command) { | ||
| 459 | case NAND_CMD_READ0: | ||
| 460 | case NAND_CMD_READOOB: | ||
| 461 | if (command == NAND_CMD_READ0) | ||
| 462 | host->offset = column; | ||
| 463 | else | ||
| 464 | host->offset = column + mtd->writesize; | ||
| 465 | |||
| 466 | is_cache_invalid = 0; | ||
| 467 | set_addr(mtd, column, page_addr); | ||
| 468 | hisi_nfc_send_cmd_readstart(host); | ||
| 469 | break; | ||
| 470 | |||
| 471 | case NAND_CMD_SEQIN: | ||
| 472 | host->offset = column; | ||
| 473 | set_addr(mtd, column, page_addr); | ||
| 474 | break; | ||
| 475 | |||
| 476 | case NAND_CMD_ERASE1: | ||
| 477 | set_addr(mtd, column, page_addr); | ||
| 478 | break; | ||
| 479 | |||
| 480 | case NAND_CMD_PAGEPROG: | ||
| 481 | hisi_nfc_send_cmd_pageprog(host); | ||
| 482 | break; | ||
| 483 | |||
| 484 | case NAND_CMD_ERASE2: | ||
| 485 | hisi_nfc_send_cmd_erase(host); | ||
| 486 | break; | ||
| 487 | |||
| 488 | case NAND_CMD_READID: | ||
| 489 | host->offset = column; | ||
| 490 | memset(host->mmio, 0, 0x10); | ||
| 491 | hisi_nfc_send_cmd_readid(host); | ||
| 492 | break; | ||
| 493 | |||
| 494 | case NAND_CMD_STATUS: | ||
| 495 | flag = hinfc_read(host, HINFC504_CON); | ||
| 496 | if (chip->ecc.mode == NAND_ECC_HW) | ||
| 497 | hinfc_write(host, | ||
| 498 | flag & ~(HINFC504_CON_ECCTYPE_MASK << | ||
| 499 | HINFC504_CON_ECCTYPE_SHIFT), HINFC504_CON); | ||
| 500 | |||
| 501 | host->offset = 0; | ||
| 502 | memset(host->mmio, 0, 0x10); | ||
| 503 | hisi_nfc_send_cmd_status(host); | ||
| 504 | hinfc_write(host, flag, HINFC504_CON); | ||
| 505 | break; | ||
| 506 | |||
| 507 | case NAND_CMD_RESET: | ||
| 508 | hisi_nfc_send_cmd_reset(host, host->chipselect); | ||
| 509 | break; | ||
| 510 | |||
| 511 | default: | ||
| 512 | dev_err(host->dev, "Error: unsupported cmd(cmd=%x, col=%x, page=%x)\n", | ||
| 513 | command, column, page_addr); | ||
| 514 | } | ||
| 515 | |||
| 516 | if (is_cache_invalid) { | ||
| 517 | host->cache_addr_value[0] = ~0; | ||
| 518 | host->cache_addr_value[1] = ~0; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | static irqreturn_t hinfc_irq_handle(int irq, void *devid) | ||
| 523 | { | ||
| 524 | struct hinfc_host *host = devid; | ||
| 525 | unsigned int flag; | ||
| 526 | |||
| 527 | flag = hinfc_read(host, HINFC504_INTS); | ||
| 528 | /* store interrupts state */ | ||
| 529 | host->irq_status |= flag; | ||
| 530 | |||
| 531 | if (flag & HINFC504_INTS_DMA) { | ||
| 532 | hinfc_write(host, HINFC504_INTCLR_DMA, HINFC504_INTCLR); | ||
| 533 | complete(&host->cmd_complete); | ||
| 534 | } else if (flag & HINFC504_INTS_CE) { | ||
| 535 | hinfc_write(host, HINFC504_INTCLR_CE, HINFC504_INTCLR); | ||
| 536 | } else if (flag & HINFC504_INTS_UE) { | ||
| 537 | hinfc_write(host, HINFC504_INTCLR_UE, HINFC504_INTCLR); | ||
| 538 | } | ||
| 539 | |||
| 540 | return IRQ_HANDLED; | ||
| 541 | } | ||
| 542 | |||
| 543 | static int hisi_nand_read_page_hwecc(struct mtd_info *mtd, | ||
| 544 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) | ||
| 545 | { | ||
| 546 | struct hinfc_host *host = chip->priv; | ||
| 547 | int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc; | ||
| 548 | int stat_1, stat_2; | ||
| 549 | |||
| 550 | chip->read_buf(mtd, buf, mtd->writesize); | ||
| 551 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
| 552 | |||
| 553 | /* errors which can not be corrected by ECC */ | ||
| 554 | if (host->irq_status & HINFC504_INTS_UE) { | ||
| 555 | mtd->ecc_stats.failed++; | ||
| 556 | } else if (host->irq_status & HINFC504_INTS_CE) { | ||
| 557 | /* TODO: need add other ECC modes! */ | ||
| 558 | switch (chip->ecc.strength) { | ||
| 559 | case 16: | ||
| 560 | status_ecc = hinfc_read(host, HINFC504_ECC_STATUS) >> | ||
| 561 | HINFC504_ECC_16_BIT_SHIFT & 0x0fff; | ||
| 562 | stat_2 = status_ecc & 0x3f; | ||
| 563 | stat_1 = status_ecc >> 6 & 0x3f; | ||
| 564 | stat = stat_1 + stat_2; | ||
| 565 | stat_max = max_t(int, stat_1, stat_2); | ||
| 566 | } | ||
| 567 | mtd->ecc_stats.corrected += stat; | ||
| 568 | max_bitflips = max_t(int, max_bitflips, stat_max); | ||
| 569 | } | ||
| 570 | host->irq_status = 0; | ||
| 571 | |||
| 572 | return max_bitflips; | ||
| 573 | } | ||
| 574 | |||
| 575 | static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | ||
| 576 | int page) | ||
| 577 | { | ||
| 578 | struct hinfc_host *host = chip->priv; | ||
| 579 | |||
| 580 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | ||
| 581 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
| 582 | |||
| 583 | if (host->irq_status & HINFC504_INTS_UE) { | ||
| 584 | host->irq_status = 0; | ||
| 585 | return -EBADMSG; | ||
| 586 | } | ||
| 587 | |||
| 588 | host->irq_status = 0; | ||
| 589 | return 0; | ||
| 590 | } | ||
| 591 | |||
| 592 | static int hisi_nand_write_page_hwecc(struct mtd_info *mtd, | ||
| 593 | struct nand_chip *chip, const uint8_t *buf, int oob_required) | ||
| 594 | { | ||
| 595 | chip->write_buf(mtd, buf, mtd->writesize); | ||
| 596 | if (oob_required) | ||
| 597 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
| 598 | |||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | static void hisi_nfc_host_init(struct hinfc_host *host) | ||
| 603 | { | ||
| 604 | struct nand_chip *chip = &host->chip; | ||
| 605 | unsigned int flag = 0; | ||
| 606 | |||
| 607 | host->version = hinfc_read(host, HINFC_VERSION); | ||
| 608 | host->addr_cycle = 0; | ||
| 609 | host->addr_value[0] = 0; | ||
| 610 | host->addr_value[1] = 0; | ||
| 611 | host->cache_addr_value[0] = ~0; | ||
| 612 | host->cache_addr_value[1] = ~0; | ||
| 613 | host->chipselect = 0; | ||
| 614 | |||
| 615 | /* default page size: 2K, ecc_none. need modify */ | ||
| 616 | flag = HINFC504_CON_OP_MODE_NORMAL | HINFC504_CON_READY_BUSY_SEL | ||
| 617 | | ((0x001 & HINFC504_CON_PAGESIZE_MASK) | ||
| 618 | << HINFC504_CON_PAGEISZE_SHIFT) | ||
| 619 | | ((0x0 & HINFC504_CON_ECCTYPE_MASK) | ||
| 620 | << HINFC504_CON_ECCTYPE_SHIFT) | ||
| 621 | | ((chip->options & NAND_BUSWIDTH_16) ? | ||
| 622 | HINFC504_CON_BUS_WIDTH : 0); | ||
| 623 | hinfc_write(host, flag, HINFC504_CON); | ||
| 624 | |||
| 625 | memset(host->mmio, 0xff, HINFC504_BUFFER_BASE_ADDRESS_LEN); | ||
| 626 | |||
| 627 | hinfc_write(host, SET_HINFC504_PWIDTH(HINFC504_W_LATCH, | ||
| 628 | HINFC504_R_LATCH, HINFC504_RW_LATCH), HINFC504_PWIDTH); | ||
| 629 | |||
| 630 | /* enable DMA irq */ | ||
| 631 | hinfc_write(host, HINFC504_INTEN_DMA, HINFC504_INTEN); | ||
| 632 | } | ||
| 633 | |||
| 634 | static struct nand_ecclayout nand_ecc_2K_16bits = { | ||
| 635 | .oobavail = 6, | ||
| 636 | .oobfree = { {2, 6} }, | ||
| 637 | }; | ||
| 638 | |||
| 639 | static int hisi_nfc_ecc_probe(struct hinfc_host *host) | ||
| 640 | { | ||
| 641 | unsigned int flag; | ||
| 642 | int size, strength, ecc_bits; | ||
| 643 | struct device *dev = host->dev; | ||
| 644 | struct nand_chip *chip = &host->chip; | ||
| 645 | struct mtd_info *mtd = &host->mtd; | ||
| 646 | struct device_node *np = host->dev->of_node; | ||
| 647 | |||
| 648 | size = of_get_nand_ecc_step_size(np); | ||
| 649 | strength = of_get_nand_ecc_strength(np); | ||
| 650 | if (size != 1024) { | ||
| 651 | dev_err(dev, "error ecc size: %d\n", size); | ||
| 652 | return -EINVAL; | ||
| 653 | } | ||
| 654 | |||
| 655 | if ((size == 1024) && ((strength != 8) && (strength != 16) && | ||
| 656 | (strength != 24) && (strength != 40))) { | ||
| 657 | dev_err(dev, "ecc size and strength do not match\n"); | ||
| 658 | return -EINVAL; | ||
| 659 | } | ||
| 660 | |||
| 661 | chip->ecc.size = size; | ||
| 662 | chip->ecc.strength = strength; | ||
| 663 | |||
| 664 | chip->ecc.read_page = hisi_nand_read_page_hwecc; | ||
| 665 | chip->ecc.read_oob = hisi_nand_read_oob; | ||
| 666 | chip->ecc.write_page = hisi_nand_write_page_hwecc; | ||
| 667 | |||
| 668 | switch (chip->ecc.strength) { | ||
| 669 | case 16: | ||
| 670 | ecc_bits = 6; | ||
| 671 | if (mtd->writesize == 2048) | ||
| 672 | chip->ecc.layout = &nand_ecc_2K_16bits; | ||
| 673 | |||
| 674 | /* TODO: add more page size support */ | ||
| 675 | break; | ||
| 676 | |||
| 677 | /* TODO: add more ecc strength support */ | ||
| 678 | default: | ||
| 679 | dev_err(dev, "not support strength: %d\n", chip->ecc.strength); | ||
| 680 | return -EINVAL; | ||
| 681 | } | ||
| 682 | |||
| 683 | flag = hinfc_read(host, HINFC504_CON); | ||
| 684 | /* add ecc type configure */ | ||
| 685 | flag |= ((ecc_bits & HINFC504_CON_ECCTYPE_MASK) | ||
| 686 | << HINFC504_CON_ECCTYPE_SHIFT); | ||
| 687 | hinfc_write(host, flag, HINFC504_CON); | ||
| 688 | |||
| 689 | /* enable ecc irq */ | ||
| 690 | flag = hinfc_read(host, HINFC504_INTEN) & 0xfff; | ||
| 691 | hinfc_write(host, flag | HINFC504_INTEN_UE | HINFC504_INTEN_CE, | ||
| 692 | HINFC504_INTEN); | ||
| 693 | |||
| 694 | return 0; | ||
| 695 | } | ||
| 696 | |||
| 697 | static int hisi_nfc_probe(struct platform_device *pdev) | ||
| 698 | { | ||
| 699 | int ret = 0, irq, buswidth, flag, max_chips = HINFC504_MAX_CHIP; | ||
| 700 | struct device *dev = &pdev->dev; | ||
| 701 | struct hinfc_host *host; | ||
| 702 | struct nand_chip *chip; | ||
| 703 | struct mtd_info *mtd; | ||
| 704 | struct resource *res; | ||
| 705 | struct device_node *np = dev->of_node; | ||
| 706 | struct mtd_part_parser_data ppdata; | ||
| 707 | |||
| 708 | host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); | ||
| 709 | if (!host) | ||
| 710 | return -ENOMEM; | ||
| 711 | host->dev = dev; | ||
| 712 | |||
| 713 | platform_set_drvdata(pdev, host); | ||
| 714 | chip = &host->chip; | ||
| 715 | mtd = &host->mtd; | ||
| 716 | |||
| 717 | irq = platform_get_irq(pdev, 0); | ||
| 718 | if (irq < 0) { | ||
| 719 | dev_err(dev, "no IRQ resource defined\n"); | ||
| 720 | ret = -ENXIO; | ||
| 721 | goto err_res; | ||
| 722 | } | ||
| 723 | |||
| 724 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 725 | host->iobase = devm_ioremap_resource(dev, res); | ||
| 726 | if (IS_ERR(host->iobase)) { | ||
| 727 | ret = PTR_ERR(host->iobase); | ||
| 728 | goto err_res; | ||
| 729 | } | ||
| 730 | |||
| 731 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 732 | host->mmio = devm_ioremap_resource(dev, res); | ||
| 733 | if (IS_ERR(host->mmio)) { | ||
| 734 | ret = PTR_ERR(host->mmio); | ||
| 735 | dev_err(dev, "devm_ioremap_resource[1] fail\n"); | ||
| 736 | goto err_res; | ||
| 737 | } | ||
| 738 | |||
| 739 | mtd->priv = chip; | ||
| 740 | mtd->owner = THIS_MODULE; | ||
| 741 | mtd->name = "hisi_nand"; | ||
| 742 | mtd->dev.parent = &pdev->dev; | ||
| 743 | |||
| 744 | chip->priv = host; | ||
| 745 | chip->cmdfunc = hisi_nfc_cmdfunc; | ||
| 746 | chip->select_chip = hisi_nfc_select_chip; | ||
| 747 | chip->read_byte = hisi_nfc_read_byte; | ||
| 748 | chip->read_word = hisi_nfc_read_word; | ||
| 749 | chip->write_buf = hisi_nfc_write_buf; | ||
| 750 | chip->read_buf = hisi_nfc_read_buf; | ||
| 751 | chip->chip_delay = HINFC504_CHIP_DELAY; | ||
| 752 | |||
| 753 | chip->ecc.mode = of_get_nand_ecc_mode(np); | ||
| 754 | |||
| 755 | buswidth = of_get_nand_bus_width(np); | ||
| 756 | if (buswidth == 16) | ||
| 757 | chip->options |= NAND_BUSWIDTH_16; | ||
| 758 | |||
| 759 | hisi_nfc_host_init(host); | ||
| 760 | |||
| 761 | ret = devm_request_irq(dev, irq, hinfc_irq_handle, IRQF_DISABLED, | ||
| 762 | "nandc", host); | ||
| 763 | if (ret) { | ||
| 764 | dev_err(dev, "failed to request IRQ\n"); | ||
| 765 | goto err_res; | ||
| 766 | } | ||
| 767 | |||
| 768 | ret = nand_scan_ident(mtd, max_chips, NULL); | ||
| 769 | if (ret) { | ||
| 770 | ret = -ENODEV; | ||
| 771 | goto err_res; | ||
| 772 | } | ||
| 773 | |||
| 774 | host->buffer = dmam_alloc_coherent(dev, mtd->writesize + mtd->oobsize, | ||
| 775 | &host->dma_buffer, GFP_KERNEL); | ||
| 776 | if (!host->buffer) { | ||
| 777 | ret = -ENOMEM; | ||
| 778 | goto err_res; | ||
| 779 | } | ||
| 780 | |||
| 781 | host->dma_oob = host->dma_buffer + mtd->writesize; | ||
| 782 | memset(host->buffer, 0xff, mtd->writesize + mtd->oobsize); | ||
| 783 | |||
| 784 | flag = hinfc_read(host, HINFC504_CON); | ||
| 785 | flag &= ~(HINFC504_CON_PAGESIZE_MASK << HINFC504_CON_PAGEISZE_SHIFT); | ||
| 786 | switch (mtd->writesize) { | ||
| 787 | case 2048: | ||
| 788 | flag |= (0x001 << HINFC504_CON_PAGEISZE_SHIFT); break; | ||
| 789 | /* | ||
| 790 | * TODO: add more pagesize support, | ||
| 791 | * default pagesize has been set in hisi_nfc_host_init | ||
| 792 | */ | ||
| 793 | default: | ||
| 794 | dev_err(dev, "NON-2KB page size nand flash\n"); | ||
| 795 | ret = -EINVAL; | ||
| 796 | goto err_res; | ||
| 797 | } | ||
| 798 | hinfc_write(host, flag, HINFC504_CON); | ||
| 799 | |||
| 800 | if (chip->ecc.mode == NAND_ECC_HW) | ||
| 801 | hisi_nfc_ecc_probe(host); | ||
| 802 | |||
| 803 | ret = nand_scan_tail(mtd); | ||
| 804 | if (ret) { | ||
| 805 | dev_err(dev, "nand_scan_tail failed: %d\n", ret); | ||
| 806 | goto err_res; | ||
| 807 | } | ||
| 808 | |||
| 809 | ppdata.of_node = np; | ||
| 810 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); | ||
| 811 | if (ret) { | ||
| 812 | dev_err(dev, "Err MTD partition=%d\n", ret); | ||
| 813 | goto err_mtd; | ||
| 814 | } | ||
| 815 | |||
| 816 | return 0; | ||
| 817 | |||
| 818 | err_mtd: | ||
| 819 | nand_release(mtd); | ||
| 820 | err_res: | ||
| 821 | return ret; | ||
| 822 | } | ||
| 823 | |||
| 824 | static int hisi_nfc_remove(struct platform_device *pdev) | ||
| 825 | { | ||
| 826 | struct hinfc_host *host = platform_get_drvdata(pdev); | ||
| 827 | struct mtd_info *mtd = &host->mtd; | ||
| 828 | |||
| 829 | nand_release(mtd); | ||
| 830 | |||
| 831 | return 0; | ||
| 832 | } | ||
| 833 | |||
| 834 | #ifdef CONFIG_PM_SLEEP | ||
| 835 | static int hisi_nfc_suspend(struct device *dev) | ||
| 836 | { | ||
| 837 | struct hinfc_host *host = dev_get_drvdata(dev); | ||
| 838 | unsigned long timeout = jiffies + HINFC504_NFC_PM_TIMEOUT; | ||
| 839 | |||
| 840 | while (time_before(jiffies, timeout)) { | ||
| 841 | if (((hinfc_read(host, HINFC504_STATUS) & 0x1) == 0x0) && | ||
| 842 | (hinfc_read(host, HINFC504_DMA_CTRL) & | ||
| 843 | HINFC504_DMA_CTRL_DMA_START)) { | ||
| 844 | cond_resched(); | ||
| 845 | return 0; | ||
| 846 | } | ||
| 847 | } | ||
| 848 | |||
| 849 | dev_err(host->dev, "nand controller suspend timeout.\n"); | ||
| 850 | |||
| 851 | return -EAGAIN; | ||
| 852 | } | ||
| 853 | |||
| 854 | static int hisi_nfc_resume(struct device *dev) | ||
| 855 | { | ||
| 856 | int cs; | ||
| 857 | struct hinfc_host *host = dev_get_drvdata(dev); | ||
| 858 | struct nand_chip *chip = &host->chip; | ||
| 859 | |||
| 860 | for (cs = 0; cs < chip->numchips; cs++) | ||
| 861 | hisi_nfc_send_cmd_reset(host, cs); | ||
| 862 | hinfc_write(host, SET_HINFC504_PWIDTH(HINFC504_W_LATCH, | ||
| 863 | HINFC504_R_LATCH, HINFC504_RW_LATCH), HINFC504_PWIDTH); | ||
| 864 | |||
| 865 | return 0; | ||
| 866 | } | ||
| 867 | #endif | ||
| 868 | static SIMPLE_DEV_PM_OPS(hisi_nfc_pm_ops, hisi_nfc_suspend, hisi_nfc_resume); | ||
| 869 | |||
| 870 | static const struct of_device_id nfc_id_table[] = { | ||
| 871 | { .compatible = "hisilicon,504-nfc" }, | ||
| 872 | {} | ||
| 873 | }; | ||
| 874 | MODULE_DEVICE_TABLE(of, nfc_id_table); | ||
| 875 | |||
| 876 | static struct platform_driver hisi_nfc_driver = { | ||
| 877 | .driver = { | ||
| 878 | .name = "hisi_nand", | ||
| 879 | .of_match_table = nfc_id_table, | ||
| 880 | .pm = &hisi_nfc_pm_ops, | ||
| 881 | }, | ||
| 882 | .probe = hisi_nfc_probe, | ||
| 883 | .remove = hisi_nfc_remove, | ||
| 884 | }; | ||
| 885 | |||
| 886 | module_platform_driver(hisi_nfc_driver); | ||
| 887 | |||
| 888 | MODULE_LICENSE("GPL"); | ||
| 889 | MODULE_AUTHOR("Zhou Wang"); | ||
| 890 | MODULE_AUTHOR("Zhiyong Cai"); | ||
| 891 | MODULE_DESCRIPTION("Hisilicon Nand Flash Controller Driver"); | ||
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 1633ec9c5108..ebf2cce04cba 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c | |||
| @@ -69,7 +69,7 @@ struct jz_nand { | |||
| 69 | 69 | ||
| 70 | int selected_bank; | 70 | int selected_bank; |
| 71 | 71 | ||
| 72 | struct jz_nand_platform_data *pdata; | 72 | struct gpio_desc *busy_gpio; |
| 73 | bool is_reading; | 73 | bool is_reading; |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| @@ -131,7 +131,7 @@ static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) | |||
| 131 | static int jz_nand_dev_ready(struct mtd_info *mtd) | 131 | static int jz_nand_dev_ready(struct mtd_info *mtd) |
| 132 | { | 132 | { |
| 133 | struct jz_nand *nand = mtd_to_jz_nand(mtd); | 133 | struct jz_nand *nand = mtd_to_jz_nand(mtd); |
| 134 | return gpio_get_value_cansleep(nand->pdata->busy_gpio); | 134 | return gpiod_get_value_cansleep(nand->busy_gpio); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static void jz_nand_hwctl(struct mtd_info *mtd, int mode) | 137 | static void jz_nand_hwctl(struct mtd_info *mtd, int mode) |
| @@ -423,14 +423,12 @@ static int jz_nand_probe(struct platform_device *pdev) | |||
| 423 | if (ret) | 423 | if (ret) |
| 424 | goto err_free; | 424 | goto err_free; |
| 425 | 425 | ||
| 426 | if (pdata && gpio_is_valid(pdata->busy_gpio)) { | 426 | nand->busy_gpio = devm_gpiod_get_optional(&pdev->dev, "busy", GPIOD_IN); |
| 427 | ret = gpio_request(pdata->busy_gpio, "NAND busy pin"); | 427 | if (IS_ERR(nand->busy_gpio)) { |
| 428 | if (ret) { | 428 | ret = PTR_ERR(nand->busy_gpio); |
| 429 | dev_err(&pdev->dev, | 429 | dev_err(&pdev->dev, "Failed to request busy gpio %d\n", |
| 430 | "Failed to request busy gpio %d: %d\n", | 430 | ret); |
| 431 | pdata->busy_gpio, ret); | 431 | goto err_iounmap_mmio; |
| 432 | goto err_iounmap_mmio; | ||
| 433 | } | ||
| 434 | } | 432 | } |
| 435 | 433 | ||
| 436 | mtd = &nand->mtd; | 434 | mtd = &nand->mtd; |
| @@ -454,10 +452,9 @@ static int jz_nand_probe(struct platform_device *pdev) | |||
| 454 | chip->cmd_ctrl = jz_nand_cmd_ctrl; | 452 | chip->cmd_ctrl = jz_nand_cmd_ctrl; |
| 455 | chip->select_chip = jz_nand_select_chip; | 453 | chip->select_chip = jz_nand_select_chip; |
| 456 | 454 | ||
| 457 | if (pdata && gpio_is_valid(pdata->busy_gpio)) | 455 | if (nand->busy_gpio) |
| 458 | chip->dev_ready = jz_nand_dev_ready; | 456 | chip->dev_ready = jz_nand_dev_ready; |
| 459 | 457 | ||
| 460 | nand->pdata = pdata; | ||
| 461 | platform_set_drvdata(pdev, nand); | 458 | platform_set_drvdata(pdev, nand); |
| 462 | 459 | ||
| 463 | /* We are going to autodetect NAND chips in the banks specified in the | 460 | /* We are going to autodetect NAND chips in the banks specified in the |
| @@ -496,7 +493,7 @@ static int jz_nand_probe(struct platform_device *pdev) | |||
| 496 | } | 493 | } |
| 497 | if (chipnr == 0) { | 494 | if (chipnr == 0) { |
| 498 | dev_err(&pdev->dev, "No NAND chips found\n"); | 495 | dev_err(&pdev->dev, "No NAND chips found\n"); |
| 499 | goto err_gpio_busy; | 496 | goto err_iounmap_mmio; |
| 500 | } | 497 | } |
| 501 | 498 | ||
| 502 | if (pdata && pdata->ident_callback) { | 499 | if (pdata && pdata->ident_callback) { |
| @@ -533,9 +530,6 @@ err_unclaim_banks: | |||
| 533 | nand->bank_base[bank - 1]); | 530 | nand->bank_base[bank - 1]); |
| 534 | } | 531 | } |
| 535 | writel(0, nand->base + JZ_REG_NAND_CTRL); | 532 | writel(0, nand->base + JZ_REG_NAND_CTRL); |
| 536 | err_gpio_busy: | ||
| 537 | if (pdata && gpio_is_valid(pdata->busy_gpio)) | ||
| 538 | gpio_free(pdata->busy_gpio); | ||
| 539 | err_iounmap_mmio: | 533 | err_iounmap_mmio: |
| 540 | jz_nand_iounmap_resource(nand->mem, nand->base); | 534 | jz_nand_iounmap_resource(nand->mem, nand->base); |
| 541 | err_free: | 535 | err_free: |
| @@ -546,7 +540,6 @@ err_free: | |||
| 546 | static int jz_nand_remove(struct platform_device *pdev) | 540 | static int jz_nand_remove(struct platform_device *pdev) |
| 547 | { | 541 | { |
| 548 | struct jz_nand *nand = platform_get_drvdata(pdev); | 542 | struct jz_nand *nand = platform_get_drvdata(pdev); |
| 549 | struct jz_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
| 550 | size_t i; | 543 | size_t i; |
| 551 | 544 | ||
| 552 | nand_release(&nand->mtd); | 545 | nand_release(&nand->mtd); |
| @@ -562,8 +555,6 @@ static int jz_nand_remove(struct platform_device *pdev) | |||
| 562 | gpio_free(JZ_GPIO_MEM_CS0 + bank - 1); | 555 | gpio_free(JZ_GPIO_MEM_CS0 + bank - 1); |
| 563 | } | 556 | } |
| 564 | } | 557 | } |
| 565 | if (pdata && gpio_is_valid(pdata->busy_gpio)) | ||
| 566 | gpio_free(pdata->busy_gpio); | ||
| 567 | 558 | ||
| 568 | jz_nand_iounmap_resource(nand->mem, nand->base); | 559 | jz_nand_iounmap_resource(nand->mem, nand->base); |
| 569 | 560 | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 41585dfb206f..df7eb4ff07d1 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
| @@ -157,7 +157,6 @@ static uint8_t nand_read_byte(struct mtd_info *mtd) | |||
| 157 | 157 | ||
| 158 | /** | 158 | /** |
| 159 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip | 159 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip |
| 160 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip | ||
| 161 | * @mtd: MTD device structure | 160 | * @mtd: MTD device structure |
| 162 | * | 161 | * |
| 163 | * Default read function for 16bit buswidth with endianness conversion. | 162 | * Default read function for 16bit buswidth with endianness conversion. |
| @@ -1751,11 +1750,10 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1751 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1750 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
| 1752 | int page) | 1751 | int page) |
| 1753 | { | 1752 | { |
| 1754 | uint8_t *buf = chip->oob_poi; | ||
| 1755 | int length = mtd->oobsize; | 1753 | int length = mtd->oobsize; |
| 1756 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | 1754 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; |
| 1757 | int eccsize = chip->ecc.size; | 1755 | int eccsize = chip->ecc.size; |
| 1758 | uint8_t *bufpoi = buf; | 1756 | uint8_t *bufpoi = chip->oob_poi; |
| 1759 | int i, toread, sndrnd = 0, pos; | 1757 | int i, toread, sndrnd = 0, pos; |
| 1760 | 1758 | ||
| 1761 | chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page); | 1759 | chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page); |
| @@ -2944,6 +2942,16 @@ static void nand_resume(struct mtd_info *mtd) | |||
| 2944 | __func__); | 2942 | __func__); |
| 2945 | } | 2943 | } |
| 2946 | 2944 | ||
| 2945 | /** | ||
| 2946 | * nand_shutdown - [MTD Interface] Finish the current NAND operation and | ||
| 2947 | * prevent further operations | ||
| 2948 | * @mtd: MTD device structure | ||
| 2949 | */ | ||
| 2950 | static void nand_shutdown(struct mtd_info *mtd) | ||
| 2951 | { | ||
| 2952 | nand_get_device(mtd, FL_SHUTDOWN); | ||
| 2953 | } | ||
| 2954 | |||
| 2947 | /* Set default functions */ | 2955 | /* Set default functions */ |
| 2948 | static void nand_set_defaults(struct nand_chip *chip, int busw) | 2956 | static void nand_set_defaults(struct nand_chip *chip, int busw) |
| 2949 | { | 2957 | { |
| @@ -4028,22 +4036,24 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4028 | ecc->read_oob = nand_read_oob_std; | 4036 | ecc->read_oob = nand_read_oob_std; |
| 4029 | ecc->write_oob = nand_write_oob_std; | 4037 | ecc->write_oob = nand_write_oob_std; |
| 4030 | /* | 4038 | /* |
| 4031 | * Board driver should supply ecc.size and ecc.bytes values to | 4039 | * Board driver should supply ecc.size and ecc.strength values |
| 4032 | * select how many bits are correctable; see nand_bch_init() | 4040 | * to select how many bits are correctable. Otherwise, default |
| 4033 | * for details. Otherwise, default to 4 bits for large page | 4041 | * to 4 bits for large page devices. |
| 4034 | * devices. | ||
| 4035 | */ | 4042 | */ |
| 4036 | if (!ecc->size && (mtd->oobsize >= 64)) { | 4043 | if (!ecc->size && (mtd->oobsize >= 64)) { |
| 4037 | ecc->size = 512; | 4044 | ecc->size = 512; |
| 4038 | ecc->bytes = DIV_ROUND_UP(13 * ecc->strength, 8); | 4045 | ecc->strength = 4; |
| 4039 | } | 4046 | } |
| 4047 | |||
| 4048 | /* See nand_bch_init() for details. */ | ||
| 4049 | ecc->bytes = DIV_ROUND_UP( | ||
| 4050 | ecc->strength * fls(8 * ecc->size), 8); | ||
| 4040 | ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, | 4051 | ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, |
| 4041 | &ecc->layout); | 4052 | &ecc->layout); |
| 4042 | if (!ecc->priv) { | 4053 | if (!ecc->priv) { |
| 4043 | pr_warn("BCH ECC initialization failed!\n"); | 4054 | pr_warn("BCH ECC initialization failed!\n"); |
| 4044 | BUG(); | 4055 | BUG(); |
| 4045 | } | 4056 | } |
| 4046 | ecc->strength = ecc->bytes * 8 / fls(8 * ecc->size); | ||
| 4047 | break; | 4057 | break; |
| 4048 | 4058 | ||
| 4049 | case NAND_ECC_NONE: | 4059 | case NAND_ECC_NONE: |
| @@ -4146,6 +4156,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4146 | mtd->_unlock = NULL; | 4156 | mtd->_unlock = NULL; |
| 4147 | mtd->_suspend = nand_suspend; | 4157 | mtd->_suspend = nand_suspend; |
| 4148 | mtd->_resume = nand_resume; | 4158 | mtd->_resume = nand_resume; |
| 4159 | mtd->_reboot = nand_shutdown; | ||
| 4149 | mtd->_block_isreserved = nand_block_isreserved; | 4160 | mtd->_block_isreserved = nand_block_isreserved; |
| 4150 | mtd->_block_isbad = nand_block_isbad; | 4161 | mtd->_block_isbad = nand_block_isbad; |
| 4151 | mtd->_block_markbad = nand_block_markbad; | 4162 | mtd->_block_markbad = nand_block_markbad; |
| @@ -4161,7 +4172,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
| 4161 | * properly set. | 4172 | * properly set. |
| 4162 | */ | 4173 | */ |
| 4163 | if (!mtd->bitflip_threshold) | 4174 | if (!mtd->bitflip_threshold) |
| 4164 | mtd->bitflip_threshold = mtd->ecc_strength; | 4175 | mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4); |
| 4165 | 4176 | ||
| 4166 | /* Check, if we should skip the bad block table scan */ | 4177 | /* Check, if we should skip the bad block table scan */ |
| 4167 | if (chip->options & NAND_SKIP_BBTSCAN) | 4178 | if (chip->options & NAND_SKIP_BBTSCAN) |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index ab5bbf567439..f2324271b94e 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
| @@ -245,7 +245,6 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " | |||
| 245 | #define STATE_DATAOUT 0x00001000 /* waiting for page data output */ | 245 | #define STATE_DATAOUT 0x00001000 /* waiting for page data output */ |
| 246 | #define STATE_DATAOUT_ID 0x00002000 /* waiting for ID bytes output */ | 246 | #define STATE_DATAOUT_ID 0x00002000 /* waiting for ID bytes output */ |
| 247 | #define STATE_DATAOUT_STATUS 0x00003000 /* waiting for status output */ | 247 | #define STATE_DATAOUT_STATUS 0x00003000 /* waiting for status output */ |
| 248 | #define STATE_DATAOUT_STATUS_M 0x00004000 /* waiting for multi-plane status output */ | ||
| 249 | #define STATE_DATAOUT_MASK 0x00007000 /* data output states mask */ | 248 | #define STATE_DATAOUT_MASK 0x00007000 /* data output states mask */ |
| 250 | 249 | ||
| 251 | /* Previous operation is done, ready to accept new requests */ | 250 | /* Previous operation is done, ready to accept new requests */ |
| @@ -269,7 +268,6 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " | |||
| 269 | #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */ | 268 | #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */ |
| 270 | #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ | 269 | #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ |
| 271 | #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ | 270 | #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ |
| 272 | #define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */ | ||
| 273 | #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ | 271 | #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ |
| 274 | #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */ | 272 | #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */ |
| 275 | #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */ | 273 | #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */ |
| @@ -1096,8 +1094,6 @@ static char *get_state_name(uint32_t state) | |||
| 1096 | return "STATE_DATAOUT_ID"; | 1094 | return "STATE_DATAOUT_ID"; |
| 1097 | case STATE_DATAOUT_STATUS: | 1095 | case STATE_DATAOUT_STATUS: |
| 1098 | return "STATE_DATAOUT_STATUS"; | 1096 | return "STATE_DATAOUT_STATUS"; |
| 1099 | case STATE_DATAOUT_STATUS_M: | ||
| 1100 | return "STATE_DATAOUT_STATUS_M"; | ||
| 1101 | case STATE_READY: | 1097 | case STATE_READY: |
| 1102 | return "STATE_READY"; | 1098 | return "STATE_READY"; |
| 1103 | case STATE_UNKNOWN: | 1099 | case STATE_UNKNOWN: |
| @@ -1865,7 +1861,6 @@ static void switch_state(struct nandsim *ns) | |||
| 1865 | break; | 1861 | break; |
| 1866 | 1862 | ||
| 1867 | case STATE_DATAOUT_STATUS: | 1863 | case STATE_DATAOUT_STATUS: |
| 1868 | case STATE_DATAOUT_STATUS_M: | ||
| 1869 | ns->regs.count = ns->regs.num = 0; | 1864 | ns->regs.count = ns->regs.num = 0; |
| 1870 | break; | 1865 | break; |
| 1871 | 1866 | ||
| @@ -2005,7 +2000,6 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
| 2005 | } | 2000 | } |
| 2006 | 2001 | ||
| 2007 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS | 2002 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS |
| 2008 | || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M | ||
| 2009 | || NS_STATE(ns->state) == STATE_DATAOUT) { | 2003 | || NS_STATE(ns->state) == STATE_DATAOUT) { |
| 2010 | int row = ns->regs.row; | 2004 | int row = ns->regs.row; |
| 2011 | 2005 | ||
| @@ -2343,6 +2337,7 @@ static int __init ns_init_module(void) | |||
| 2343 | } | 2337 | } |
| 2344 | chip->ecc.mode = NAND_ECC_SOFT_BCH; | 2338 | chip->ecc.mode = NAND_ECC_SOFT_BCH; |
| 2345 | chip->ecc.size = 512; | 2339 | chip->ecc.size = 512; |
| 2340 | chip->ecc.strength = bch; | ||
| 2346 | chip->ecc.bytes = eccbytes; | 2341 | chip->ecc.bytes = eccbytes; |
| 2347 | NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size); | 2342 | NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size); |
| 2348 | } | 2343 | } |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 63f858e6bf39..60fa89939c24 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
| @@ -1048,10 +1048,9 @@ static int omap_dev_ready(struct mtd_info *mtd) | |||
| 1048 | * @mtd: MTD device structure | 1048 | * @mtd: MTD device structure |
| 1049 | * @mode: Read/Write mode | 1049 | * @mode: Read/Write mode |
| 1050 | * | 1050 | * |
| 1051 | * When using BCH, sector size is hardcoded to 512 bytes. | 1051 | * When using BCH with SW correction (i.e. no ELM), sector size is set |
| 1052 | * Using wrapping mode 6 both for reading and writing if ELM module not uses | 1052 | * to 512 bytes and we use BCH_WRAPMODE_6 wrapping mode |
| 1053 | * for error correction. | 1053 | * for both reading and writing with: |
| 1054 | * On writing, | ||
| 1055 | * eccsize0 = 0 (no additional protected byte in spare area) | 1054 | * eccsize0 = 0 (no additional protected byte in spare area) |
| 1056 | * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) | 1055 | * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) |
| 1057 | */ | 1056 | */ |
| @@ -1071,15 +1070,9 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) | |||
| 1071 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: | 1070 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: |
| 1072 | bch_type = 0; | 1071 | bch_type = 0; |
| 1073 | nsectors = 1; | 1072 | nsectors = 1; |
| 1074 | if (mode == NAND_ECC_READ) { | 1073 | wr_mode = BCH_WRAPMODE_6; |
| 1075 | wr_mode = BCH_WRAPMODE_6; | 1074 | ecc_size0 = BCH_ECC_SIZE0; |
| 1076 | ecc_size0 = BCH_ECC_SIZE0; | 1075 | ecc_size1 = BCH_ECC_SIZE1; |
| 1077 | ecc_size1 = BCH_ECC_SIZE1; | ||
| 1078 | } else { | ||
| 1079 | wr_mode = BCH_WRAPMODE_6; | ||
| 1080 | ecc_size0 = BCH_ECC_SIZE0; | ||
| 1081 | ecc_size1 = BCH_ECC_SIZE1; | ||
| 1082 | } | ||
| 1083 | break; | 1076 | break; |
| 1084 | case OMAP_ECC_BCH4_CODE_HW: | 1077 | case OMAP_ECC_BCH4_CODE_HW: |
| 1085 | bch_type = 0; | 1078 | bch_type = 0; |
| @@ -1097,15 +1090,9 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) | |||
| 1097 | case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: | 1090 | case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: |
| 1098 | bch_type = 1; | 1091 | bch_type = 1; |
| 1099 | nsectors = 1; | 1092 | nsectors = 1; |
| 1100 | if (mode == NAND_ECC_READ) { | 1093 | wr_mode = BCH_WRAPMODE_6; |
| 1101 | wr_mode = BCH_WRAPMODE_6; | 1094 | ecc_size0 = BCH_ECC_SIZE0; |
| 1102 | ecc_size0 = BCH_ECC_SIZE0; | 1095 | ecc_size1 = BCH_ECC_SIZE1; |
| 1103 | ecc_size1 = BCH_ECC_SIZE1; | ||
| 1104 | } else { | ||
| 1105 | wr_mode = BCH_WRAPMODE_6; | ||
| 1106 | ecc_size0 = BCH_ECC_SIZE0; | ||
| 1107 | ecc_size1 = BCH_ECC_SIZE1; | ||
| 1108 | } | ||
| 1109 | break; | 1096 | break; |
| 1110 | case OMAP_ECC_BCH8_CODE_HW: | 1097 | case OMAP_ECC_BCH8_CODE_HW: |
| 1111 | bch_type = 1; | 1098 | bch_type = 1; |
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index ccaa8e283388..6f93b2990d25 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c | |||
| @@ -1110,8 +1110,6 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc, | |||
| 1110 | 1110 | ||
| 1111 | switch (ecc->mode) { | 1111 | switch (ecc->mode) { |
| 1112 | case NAND_ECC_SOFT_BCH: | 1112 | case NAND_ECC_SOFT_BCH: |
| 1113 | ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * ecc->size), | ||
| 1114 | 8); | ||
| 1115 | break; | 1113 | break; |
| 1116 | case NAND_ECC_HW: | 1114 | case NAND_ECC_HW: |
| 1117 | ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np); | 1115 | ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np); |
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 51b9d6af307f..a5dfbfbebfca 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c | |||
| @@ -89,9 +89,10 @@ static int find_boot_record(struct NFTLrecord *nftl) | |||
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | /* To be safer with BIOS, also use erase mark as discriminant */ | 91 | /* To be safer with BIOS, also use erase mark as discriminant */ |
| 92 | if ((ret = nftl_read_oob(mtd, block * nftl->EraseSize + | 92 | ret = nftl_read_oob(mtd, block * nftl->EraseSize + |
| 93 | SECTORSIZE + 8, 8, &retlen, | 93 | SECTORSIZE + 8, 8, &retlen, |
| 94 | (char *)&h1) < 0)) { | 94 | (char *)&h1); |
| 95 | if (ret < 0) { | ||
| 95 | printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", | 96 | printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", |
| 96 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); | 97 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); |
| 97 | continue; | 98 | continue; |
| @@ -109,8 +110,9 @@ static int find_boot_record(struct NFTLrecord *nftl) | |||
| 109 | } | 110 | } |
| 110 | 111 | ||
| 111 | /* Finally reread to check ECC */ | 112 | /* Finally reread to check ECC */ |
| 112 | if ((ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, | 113 | ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, |
| 113 | &retlen, buf) < 0)) { | 114 | &retlen, buf); |
| 115 | if (ret < 0) { | ||
| 114 | printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", | 116 | printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", |
| 115 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); | 117 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); |
| 116 | continue; | 118 | continue; |
| @@ -228,9 +230,11 @@ device is already correct. | |||
| 228 | The new DiskOnChip driver already scanned the bad block table. Just query it. | 230 | The new DiskOnChip driver already scanned the bad block table. Just query it. |
| 229 | if ((i & (SECTORSIZE - 1)) == 0) { | 231 | if ((i & (SECTORSIZE - 1)) == 0) { |
| 230 | /* read one sector for every SECTORSIZE of blocks */ | 232 | /* read one sector for every SECTORSIZE of blocks */ |
| 231 | if ((ret = mtd->read(nftl->mbd.mtd, block * nftl->EraseSize + | 233 | ret = mtd->read(nftl->mbd.mtd, |
| 232 | i + SECTORSIZE, SECTORSIZE, &retlen, | 234 | block * nftl->EraseSize + i + |
| 233 | buf)) < 0) { | 235 | SECTORSIZE, SECTORSIZE, |
| 236 | &retlen, buf); | ||
| 237 | if (ret < 0) { | ||
| 234 | printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", | 238 | printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", |
| 235 | ret); | 239 | ret); |
| 236 | kfree(nftl->ReplUnitTable); | 240 | kfree(nftl->ReplUnitTable); |
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 39763b94f67d..1c7308c2c77d 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c | |||
| @@ -57,7 +57,9 @@ | |||
| 57 | 57 | ||
| 58 | #define QUADSPI_BUF3CR 0x1c | 58 | #define QUADSPI_BUF3CR 0x1c |
| 59 | #define QUADSPI_BUF3CR_ALLMST_SHIFT 31 | 59 | #define QUADSPI_BUF3CR_ALLMST_SHIFT 31 |
| 60 | #define QUADSPI_BUF3CR_ALLMST (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) | 60 | #define QUADSPI_BUF3CR_ALLMST_MASK (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) |
| 61 | #define QUADSPI_BUF3CR_ADATSZ_SHIFT 8 | ||
| 62 | #define QUADSPI_BUF3CR_ADATSZ_MASK (0xFF << QUADSPI_BUF3CR_ADATSZ_SHIFT) | ||
| 61 | 63 | ||
| 62 | #define QUADSPI_BFGENCR 0x20 | 64 | #define QUADSPI_BFGENCR 0x20 |
| 63 | #define QUADSPI_BFGENCR_PAR_EN_SHIFT 16 | 65 | #define QUADSPI_BFGENCR_PAR_EN_SHIFT 16 |
| @@ -198,18 +200,21 @@ struct fsl_qspi_devtype_data { | |||
| 198 | enum fsl_qspi_devtype devtype; | 200 | enum fsl_qspi_devtype devtype; |
| 199 | int rxfifo; | 201 | int rxfifo; |
| 200 | int txfifo; | 202 | int txfifo; |
| 203 | int ahb_buf_size; | ||
| 201 | }; | 204 | }; |
| 202 | 205 | ||
| 203 | static struct fsl_qspi_devtype_data vybrid_data = { | 206 | static struct fsl_qspi_devtype_data vybrid_data = { |
| 204 | .devtype = FSL_QUADSPI_VYBRID, | 207 | .devtype = FSL_QUADSPI_VYBRID, |
| 205 | .rxfifo = 128, | 208 | .rxfifo = 128, |
| 206 | .txfifo = 64 | 209 | .txfifo = 64, |
| 210 | .ahb_buf_size = 1024 | ||
| 207 | }; | 211 | }; |
| 208 | 212 | ||
| 209 | static struct fsl_qspi_devtype_data imx6sx_data = { | 213 | static struct fsl_qspi_devtype_data imx6sx_data = { |
| 210 | .devtype = FSL_QUADSPI_IMX6SX, | 214 | .devtype = FSL_QUADSPI_IMX6SX, |
| 211 | .rxfifo = 128, | 215 | .rxfifo = 128, |
| 212 | .txfifo = 512 | 216 | .txfifo = 512, |
| 217 | .ahb_buf_size = 1024 | ||
| 213 | }; | 218 | }; |
| 214 | 219 | ||
| 215 | #define FSL_QSPI_MAX_CHIP 4 | 220 | #define FSL_QSPI_MAX_CHIP 4 |
| @@ -227,6 +232,7 @@ struct fsl_qspi { | |||
| 227 | u32 nor_num; | 232 | u32 nor_num; |
| 228 | u32 clk_rate; | 233 | u32 clk_rate; |
| 229 | unsigned int chip_base_addr; /* We may support two chips. */ | 234 | unsigned int chip_base_addr; /* We may support two chips. */ |
| 235 | bool has_second_chip; | ||
| 230 | }; | 236 | }; |
| 231 | 237 | ||
| 232 | static inline int is_vybrid_qspi(struct fsl_qspi *q) | 238 | static inline int is_vybrid_qspi(struct fsl_qspi *q) |
| @@ -583,7 +589,12 @@ static void fsl_qspi_init_abh_read(struct fsl_qspi *q) | |||
| 583 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); | 589 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); |
| 584 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); | 590 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); |
| 585 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); | 591 | writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); |
| 586 | writel(QUADSPI_BUF3CR_ALLMST, base + QUADSPI_BUF3CR); | 592 | /* |
| 593 | * Set ADATSZ with the maximum AHB buffer size to improve the | ||
| 594 | * read performance. | ||
| 595 | */ | ||
| 596 | writel(QUADSPI_BUF3CR_ALLMST_MASK | ((q->devtype_data->ahb_buf_size / 8) | ||
| 597 | << QUADSPI_BUF3CR_ADATSZ_SHIFT), base + QUADSPI_BUF3CR); | ||
| 587 | 598 | ||
| 588 | /* We only use the buffer3 */ | 599 | /* We only use the buffer3 */ |
| 589 | writel(0, base + QUADSPI_BUF0IND); | 600 | writel(0, base + QUADSPI_BUF0IND); |
| @@ -783,7 +794,6 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 783 | struct spi_nor *nor; | 794 | struct spi_nor *nor; |
| 784 | struct mtd_info *mtd; | 795 | struct mtd_info *mtd; |
| 785 | int ret, i = 0; | 796 | int ret, i = 0; |
| 786 | bool has_second_chip = false; | ||
| 787 | const struct of_device_id *of_id = | 797 | const struct of_device_id *of_id = |
| 788 | of_match_device(fsl_qspi_dt_ids, &pdev->dev); | 798 | of_match_device(fsl_qspi_dt_ids, &pdev->dev); |
| 789 | 799 | ||
| @@ -798,37 +808,30 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 798 | /* find the resources */ | 808 | /* find the resources */ |
| 799 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); | 809 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); |
| 800 | q->iobase = devm_ioremap_resource(dev, res); | 810 | q->iobase = devm_ioremap_resource(dev, res); |
| 801 | if (IS_ERR(q->iobase)) { | 811 | if (IS_ERR(q->iobase)) |
| 802 | ret = PTR_ERR(q->iobase); | 812 | return PTR_ERR(q->iobase); |
| 803 | goto map_failed; | ||
| 804 | } | ||
| 805 | 813 | ||
| 806 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 814 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
| 807 | "QuadSPI-memory"); | 815 | "QuadSPI-memory"); |
| 808 | q->ahb_base = devm_ioremap_resource(dev, res); | 816 | q->ahb_base = devm_ioremap_resource(dev, res); |
| 809 | if (IS_ERR(q->ahb_base)) { | 817 | if (IS_ERR(q->ahb_base)) |
| 810 | ret = PTR_ERR(q->ahb_base); | 818 | return PTR_ERR(q->ahb_base); |
| 811 | goto map_failed; | 819 | |
| 812 | } | ||
| 813 | q->memmap_phy = res->start; | 820 | q->memmap_phy = res->start; |
| 814 | 821 | ||
| 815 | /* find the clocks */ | 822 | /* find the clocks */ |
| 816 | q->clk_en = devm_clk_get(dev, "qspi_en"); | 823 | q->clk_en = devm_clk_get(dev, "qspi_en"); |
| 817 | if (IS_ERR(q->clk_en)) { | 824 | if (IS_ERR(q->clk_en)) |
| 818 | ret = PTR_ERR(q->clk_en); | 825 | return PTR_ERR(q->clk_en); |
| 819 | goto map_failed; | ||
| 820 | } | ||
| 821 | 826 | ||
| 822 | q->clk = devm_clk_get(dev, "qspi"); | 827 | q->clk = devm_clk_get(dev, "qspi"); |
| 823 | if (IS_ERR(q->clk)) { | 828 | if (IS_ERR(q->clk)) |
| 824 | ret = PTR_ERR(q->clk); | 829 | return PTR_ERR(q->clk); |
| 825 | goto map_failed; | ||
| 826 | } | ||
| 827 | 830 | ||
| 828 | ret = clk_prepare_enable(q->clk_en); | 831 | ret = clk_prepare_enable(q->clk_en); |
| 829 | if (ret) { | 832 | if (ret) { |
| 830 | dev_err(dev, "can not enable the qspi_en clock\n"); | 833 | dev_err(dev, "can not enable the qspi_en clock\n"); |
| 831 | goto map_failed; | 834 | return ret; |
| 832 | } | 835 | } |
| 833 | 836 | ||
| 834 | ret = clk_prepare_enable(q->clk); | 837 | ret = clk_prepare_enable(q->clk); |
| @@ -860,14 +863,14 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 860 | goto irq_failed; | 863 | goto irq_failed; |
| 861 | 864 | ||
| 862 | if (of_get_property(np, "fsl,qspi-has-second-chip", NULL)) | 865 | if (of_get_property(np, "fsl,qspi-has-second-chip", NULL)) |
| 863 | has_second_chip = true; | 866 | q->has_second_chip = true; |
| 864 | 867 | ||
| 865 | /* iterate the subnodes. */ | 868 | /* iterate the subnodes. */ |
| 866 | for_each_available_child_of_node(dev->of_node, np) { | 869 | for_each_available_child_of_node(dev->of_node, np) { |
| 867 | char modalias[40]; | 870 | char modalias[40]; |
| 868 | 871 | ||
| 869 | /* skip the holes */ | 872 | /* skip the holes */ |
| 870 | if (!has_second_chip) | 873 | if (!q->has_second_chip) |
| 871 | i *= 2; | 874 | i *= 2; |
| 872 | 875 | ||
| 873 | nor = &q->nor[i]; | 876 | nor = &q->nor[i]; |
| @@ -890,24 +893,24 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 890 | 893 | ||
| 891 | ret = of_modalias_node(np, modalias, sizeof(modalias)); | 894 | ret = of_modalias_node(np, modalias, sizeof(modalias)); |
| 892 | if (ret < 0) | 895 | if (ret < 0) |
| 893 | goto map_failed; | 896 | goto irq_failed; |
| 894 | 897 | ||
| 895 | ret = of_property_read_u32(np, "spi-max-frequency", | 898 | ret = of_property_read_u32(np, "spi-max-frequency", |
| 896 | &q->clk_rate); | 899 | &q->clk_rate); |
| 897 | if (ret < 0) | 900 | if (ret < 0) |
| 898 | goto map_failed; | 901 | goto irq_failed; |
| 899 | 902 | ||
| 900 | /* set the chip address for READID */ | 903 | /* set the chip address for READID */ |
| 901 | fsl_qspi_set_base_addr(q, nor); | 904 | fsl_qspi_set_base_addr(q, nor); |
| 902 | 905 | ||
| 903 | ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD); | 906 | ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD); |
| 904 | if (ret) | 907 | if (ret) |
| 905 | goto map_failed; | 908 | goto irq_failed; |
| 906 | 909 | ||
| 907 | ppdata.of_node = np; | 910 | ppdata.of_node = np; |
| 908 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); | 911 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); |
| 909 | if (ret) | 912 | if (ret) |
| 910 | goto map_failed; | 913 | goto irq_failed; |
| 911 | 914 | ||
| 912 | /* Set the correct NOR size now. */ | 915 | /* Set the correct NOR size now. */ |
| 913 | if (q->nor_size == 0) { | 916 | if (q->nor_size == 0) { |
| @@ -939,19 +942,19 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
| 939 | 942 | ||
| 940 | clk_disable(q->clk); | 943 | clk_disable(q->clk); |
| 941 | clk_disable(q->clk_en); | 944 | clk_disable(q->clk_en); |
| 942 | dev_info(dev, "QuadSPI SPI NOR flash driver\n"); | ||
| 943 | return 0; | 945 | return 0; |
| 944 | 946 | ||
| 945 | last_init_failed: | 947 | last_init_failed: |
| 946 | for (i = 0; i < q->nor_num; i++) | 948 | for (i = 0; i < q->nor_num; i++) { |
| 949 | /* skip the holes */ | ||
| 950 | if (!q->has_second_chip) | ||
| 951 | i *= 2; | ||
| 947 | mtd_device_unregister(&q->mtd[i]); | 952 | mtd_device_unregister(&q->mtd[i]); |
| 948 | 953 | } | |
| 949 | irq_failed: | 954 | irq_failed: |
| 950 | clk_disable_unprepare(q->clk); | 955 | clk_disable_unprepare(q->clk); |
| 951 | clk_failed: | 956 | clk_failed: |
| 952 | clk_disable_unprepare(q->clk_en); | 957 | clk_disable_unprepare(q->clk_en); |
| 953 | map_failed: | ||
| 954 | dev_err(dev, "Freescale QuadSPI probe failed\n"); | ||
| 955 | return ret; | 958 | return ret; |
| 956 | } | 959 | } |
| 957 | 960 | ||
| @@ -960,8 +963,12 @@ static int fsl_qspi_remove(struct platform_device *pdev) | |||
| 960 | struct fsl_qspi *q = platform_get_drvdata(pdev); | 963 | struct fsl_qspi *q = platform_get_drvdata(pdev); |
| 961 | int i; | 964 | int i; |
| 962 | 965 | ||
| 963 | for (i = 0; i < q->nor_num; i++) | 966 | for (i = 0; i < q->nor_num; i++) { |
| 967 | /* skip the holes */ | ||
| 968 | if (!q->has_second_chip) | ||
| 969 | i *= 2; | ||
| 964 | mtd_device_unregister(&q->mtd[i]); | 970 | mtd_device_unregister(&q->mtd[i]); |
| 971 | } | ||
| 965 | 972 | ||
| 966 | /* disable the hardware */ | 973 | /* disable the hardware */ |
| 967 | writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); | 974 | writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); |
| @@ -972,6 +979,22 @@ static int fsl_qspi_remove(struct platform_device *pdev) | |||
| 972 | return 0; | 979 | return 0; |
| 973 | } | 980 | } |
| 974 | 981 | ||
| 982 | static int fsl_qspi_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 983 | { | ||
| 984 | return 0; | ||
| 985 | } | ||
| 986 | |||
| 987 | static int fsl_qspi_resume(struct platform_device *pdev) | ||
| 988 | { | ||
| 989 | struct fsl_qspi *q = platform_get_drvdata(pdev); | ||
| 990 | |||
| 991 | fsl_qspi_nor_setup(q); | ||
| 992 | fsl_qspi_set_map_addr(q); | ||
| 993 | fsl_qspi_nor_setup_last(q); | ||
| 994 | |||
| 995 | return 0; | ||
| 996 | } | ||
| 997 | |||
| 975 | static struct platform_driver fsl_qspi_driver = { | 998 | static struct platform_driver fsl_qspi_driver = { |
| 976 | .driver = { | 999 | .driver = { |
| 977 | .name = "fsl-quadspi", | 1000 | .name = "fsl-quadspi", |
| @@ -980,6 +1003,8 @@ static struct platform_driver fsl_qspi_driver = { | |||
| 980 | }, | 1003 | }, |
| 981 | .probe = fsl_qspi_probe, | 1004 | .probe = fsl_qspi_probe, |
| 982 | .remove = fsl_qspi_remove, | 1005 | .remove = fsl_qspi_remove, |
| 1006 | .suspend = fsl_qspi_suspend, | ||
| 1007 | .resume = fsl_qspi_resume, | ||
| 983 | }; | 1008 | }; |
| 984 | module_platform_driver(fsl_qspi_driver); | 1009 | module_platform_driver(fsl_qspi_driver); |
| 985 | 1010 | ||
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 0f8ec3c2d015..b6a5a0c269e1 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
| @@ -538,6 +538,7 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
| 538 | /* GigaDevice */ | 538 | /* GigaDevice */ |
| 539 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, | 539 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, |
| 540 | { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, | 540 | { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, |
| 541 | { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, | ||
| 541 | 542 | ||
| 542 | /* Intel/Numonyx -- xxxs33b */ | 543 | /* Intel/Numonyx -- xxxs33b */ |
| 543 | { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, | 544 | { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, |
| @@ -560,14 +561,14 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
| 560 | { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, | 561 | { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, |
| 561 | 562 | ||
| 562 | /* Micron */ | 563 | /* Micron */ |
| 563 | { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, | 564 | { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, |
| 564 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, | 565 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ) }, |
| 565 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, | 566 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, |
| 566 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, | 567 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, |
| 567 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, | 568 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, |
| 568 | { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, | 569 | { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 569 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, | 570 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 570 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, | 571 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, |
| 571 | 572 | ||
| 572 | /* PMC */ | 573 | /* PMC */ |
| 573 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, | 574 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, |
| @@ -891,6 +892,45 @@ static int spansion_quad_enable(struct spi_nor *nor) | |||
| 891 | return 0; | 892 | return 0; |
| 892 | } | 893 | } |
| 893 | 894 | ||
| 895 | static int micron_quad_enable(struct spi_nor *nor) | ||
| 896 | { | ||
| 897 | int ret; | ||
| 898 | u8 val; | ||
| 899 | |||
| 900 | ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); | ||
| 901 | if (ret < 0) { | ||
| 902 | dev_err(nor->dev, "error %d reading EVCR\n", ret); | ||
| 903 | return ret; | ||
| 904 | } | ||
| 905 | |||
| 906 | write_enable(nor); | ||
| 907 | |||
| 908 | /* set EVCR, enable quad I/O */ | ||
| 909 | nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON; | ||
| 910 | ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0); | ||
| 911 | if (ret < 0) { | ||
| 912 | dev_err(nor->dev, "error while writing EVCR register\n"); | ||
| 913 | return ret; | ||
| 914 | } | ||
| 915 | |||
| 916 | ret = spi_nor_wait_till_ready(nor); | ||
| 917 | if (ret) | ||
| 918 | return ret; | ||
| 919 | |||
| 920 | /* read EVCR and check it */ | ||
| 921 | ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); | ||
| 922 | if (ret < 0) { | ||
| 923 | dev_err(nor->dev, "error %d reading EVCR\n", ret); | ||
| 924 | return ret; | ||
| 925 | } | ||
| 926 | if (val & EVCR_QUAD_EN_MICRON) { | ||
| 927 | dev_err(nor->dev, "Micron EVCR Quad bit not clear\n"); | ||
| 928 | return -EINVAL; | ||
| 929 | } | ||
| 930 | |||
| 931 | return 0; | ||
| 932 | } | ||
| 933 | |||
| 894 | static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) | 934 | static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) |
| 895 | { | 935 | { |
| 896 | int status; | 936 | int status; |
| @@ -903,6 +943,13 @@ static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) | |||
| 903 | return -EINVAL; | 943 | return -EINVAL; |
| 904 | } | 944 | } |
| 905 | return status; | 945 | return status; |
| 946 | case CFI_MFR_ST: | ||
| 947 | status = micron_quad_enable(nor); | ||
| 948 | if (status) { | ||
| 949 | dev_err(nor->dev, "Micron quad-read not enabled\n"); | ||
| 950 | return -EINVAL; | ||
| 951 | } | ||
| 952 | return status; | ||
| 906 | default: | 953 | default: |
| 907 | status = spansion_quad_enable(nor); | 954 | status = spansion_quad_enable(nor); |
| 908 | if (status) { | 955 | if (status) { |
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 92e0644bf867..556de100ebd5 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c | |||
| @@ -84,11 +84,6 @@ static inline int pullbit(struct pushpull *pp) | |||
| 84 | return bit; | 84 | return bit; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static inline int pulledbits(struct pushpull *pp) | ||
| 88 | { | ||
| 89 | return pp->ofs; | ||
| 90 | } | ||
| 91 | |||
| 92 | 87 | ||
| 93 | static void init_rubin(struct rubin_state *rs, int div, int *bits) | 88 | static void init_rubin(struct rubin_state *rs, int div, int *bits) |
| 94 | { | 89 | { |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 031ff3a9a0bd..c06f5373d870 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
| @@ -227,6 +227,7 @@ struct mtd_info { | |||
| 227 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); | 227 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); |
| 228 | int (*_suspend) (struct mtd_info *mtd); | 228 | int (*_suspend) (struct mtd_info *mtd); |
| 229 | void (*_resume) (struct mtd_info *mtd); | 229 | void (*_resume) (struct mtd_info *mtd); |
| 230 | void (*_reboot) (struct mtd_info *mtd); | ||
| 230 | /* | 231 | /* |
| 231 | * If the driver is something smart, like UBI, it may need to maintain | 232 | * If the driver is something smart, like UBI, it may need to maintain |
| 232 | * its own reference counting. The below functions are only for driver. | 233 | * its own reference counting. The below functions are only for driver. |
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 63aeccf9ddc8..4720b86ee73d 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h | |||
| @@ -56,6 +56,10 @@ | |||
| 56 | /* Used for Spansion flashes only. */ | 56 | /* Used for Spansion flashes only. */ |
| 57 | #define SPINOR_OP_BRWR 0x17 /* Bank register write */ | 57 | #define SPINOR_OP_BRWR 0x17 /* Bank register write */ |
| 58 | 58 | ||
| 59 | /* Used for Micron flashes only. */ | ||
| 60 | #define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ | ||
| 61 | #define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */ | ||
| 62 | |||
| 59 | /* Status Register bits. */ | 63 | /* Status Register bits. */ |
| 60 | #define SR_WIP 1 /* Write in progress */ | 64 | #define SR_WIP 1 /* Write in progress */ |
| 61 | #define SR_WEL 2 /* Write enable latch */ | 65 | #define SR_WEL 2 /* Write enable latch */ |
| @@ -67,6 +71,9 @@ | |||
| 67 | 71 | ||
| 68 | #define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ | 72 | #define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ |
| 69 | 73 | ||
| 74 | /* Enhanced Volatile Configuration Register bits */ | ||
| 75 | #define EVCR_QUAD_EN_MICRON 0x80 /* Micron Quad I/O */ | ||
| 76 | |||
| 70 | /* Flag Status Register bits */ | 77 | /* Flag Status Register bits */ |
| 71 | #define FSR_READY 0x80 | 78 | #define FSR_READY 0x80 |
| 72 | 79 | ||
