diff options
Diffstat (limited to 'drivers')
87 files changed, 4132 insertions, 2544 deletions
diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c index c3748b414c27..0322df9dc249 100644 --- a/drivers/memory/atmel-ebi.c +++ b/drivers/memory/atmel-ebi.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/of_device.h> | 18 | #include <linux/of_device.h> |
| 19 | #include <linux/regmap.h> | 19 | #include <linux/regmap.h> |
| 20 | #include <soc/at91/atmel-sfr.h> | ||
| 20 | 21 | ||
| 21 | struct atmel_ebi_dev_config { | 22 | struct atmel_ebi_dev_config { |
| 22 | int cs; | 23 | int cs; |
| @@ -36,6 +37,7 @@ struct atmel_ebi_dev { | |||
| 36 | struct atmel_ebi_caps { | 37 | struct atmel_ebi_caps { |
| 37 | unsigned int available_cs; | 38 | unsigned int available_cs; |
| 38 | unsigned int ebi_csa_offs; | 39 | unsigned int ebi_csa_offs; |
| 40 | const char *regmap_name; | ||
| 39 | void (*get_config)(struct atmel_ebi_dev *ebid, | 41 | void (*get_config)(struct atmel_ebi_dev *ebid, |
| 40 | struct atmel_ebi_dev_config *conf); | 42 | struct atmel_ebi_dev_config *conf); |
| 41 | int (*xlate_config)(struct atmel_ebi_dev *ebid, | 43 | int (*xlate_config)(struct atmel_ebi_dev *ebid, |
| @@ -47,7 +49,7 @@ struct atmel_ebi_caps { | |||
| 47 | 49 | ||
| 48 | struct atmel_ebi { | 50 | struct atmel_ebi { |
| 49 | struct clk *clk; | 51 | struct clk *clk; |
| 50 | struct regmap *matrix; | 52 | struct regmap *regmap; |
| 51 | struct { | 53 | struct { |
| 52 | struct regmap *regmap; | 54 | struct regmap *regmap; |
| 53 | struct clk *clk; | 55 | struct clk *clk; |
| @@ -357,7 +359,7 @@ static int atmel_ebi_dev_setup(struct atmel_ebi *ebi, struct device_node *np, | |||
| 357 | * one "atmel,smc-" property is present. | 359 | * one "atmel,smc-" property is present. |
| 358 | */ | 360 | */ |
| 359 | if (ebi->caps->ebi_csa_offs && apply) | 361 | if (ebi->caps->ebi_csa_offs && apply) |
| 360 | regmap_update_bits(ebi->matrix, | 362 | regmap_update_bits(ebi->regmap, |
| 361 | ebi->caps->ebi_csa_offs, | 363 | ebi->caps->ebi_csa_offs, |
| 362 | BIT(cs), 0); | 364 | BIT(cs), 0); |
| 363 | 365 | ||
| @@ -372,6 +374,7 @@ static int atmel_ebi_dev_setup(struct atmel_ebi *ebi, struct device_node *np, | |||
| 372 | static const struct atmel_ebi_caps at91sam9260_ebi_caps = { | 374 | static const struct atmel_ebi_caps at91sam9260_ebi_caps = { |
| 373 | .available_cs = 0xff, | 375 | .available_cs = 0xff, |
| 374 | .ebi_csa_offs = AT91SAM9260_MATRIX_EBICSA, | 376 | .ebi_csa_offs = AT91SAM9260_MATRIX_EBICSA, |
| 377 | .regmap_name = "atmel,matrix", | ||
| 375 | .get_config = at91sam9_ebi_get_config, | 378 | .get_config = at91sam9_ebi_get_config, |
| 376 | .xlate_config = atmel_ebi_xslate_smc_config, | 379 | .xlate_config = atmel_ebi_xslate_smc_config, |
| 377 | .apply_config = at91sam9_ebi_apply_config, | 380 | .apply_config = at91sam9_ebi_apply_config, |
| @@ -380,6 +383,7 @@ static const struct atmel_ebi_caps at91sam9260_ebi_caps = { | |||
| 380 | static const struct atmel_ebi_caps at91sam9261_ebi_caps = { | 383 | static const struct atmel_ebi_caps at91sam9261_ebi_caps = { |
| 381 | .available_cs = 0xff, | 384 | .available_cs = 0xff, |
| 382 | .ebi_csa_offs = AT91SAM9261_MATRIX_EBICSA, | 385 | .ebi_csa_offs = AT91SAM9261_MATRIX_EBICSA, |
| 386 | .regmap_name = "atmel,matrix", | ||
| 383 | .get_config = at91sam9_ebi_get_config, | 387 | .get_config = at91sam9_ebi_get_config, |
| 384 | .xlate_config = atmel_ebi_xslate_smc_config, | 388 | .xlate_config = atmel_ebi_xslate_smc_config, |
| 385 | .apply_config = at91sam9_ebi_apply_config, | 389 | .apply_config = at91sam9_ebi_apply_config, |
| @@ -388,6 +392,7 @@ static const struct atmel_ebi_caps at91sam9261_ebi_caps = { | |||
| 388 | static const struct atmel_ebi_caps at91sam9263_ebi0_caps = { | 392 | static const struct atmel_ebi_caps at91sam9263_ebi0_caps = { |
| 389 | .available_cs = 0x3f, | 393 | .available_cs = 0x3f, |
| 390 | .ebi_csa_offs = AT91SAM9263_MATRIX_EBI0CSA, | 394 | .ebi_csa_offs = AT91SAM9263_MATRIX_EBI0CSA, |
| 395 | .regmap_name = "atmel,matrix", | ||
| 391 | .get_config = at91sam9_ebi_get_config, | 396 | .get_config = at91sam9_ebi_get_config, |
| 392 | .xlate_config = atmel_ebi_xslate_smc_config, | 397 | .xlate_config = atmel_ebi_xslate_smc_config, |
| 393 | .apply_config = at91sam9_ebi_apply_config, | 398 | .apply_config = at91sam9_ebi_apply_config, |
| @@ -396,6 +401,7 @@ static const struct atmel_ebi_caps at91sam9263_ebi0_caps = { | |||
| 396 | static const struct atmel_ebi_caps at91sam9263_ebi1_caps = { | 401 | static const struct atmel_ebi_caps at91sam9263_ebi1_caps = { |
| 397 | .available_cs = 0x7, | 402 | .available_cs = 0x7, |
| 398 | .ebi_csa_offs = AT91SAM9263_MATRIX_EBI1CSA, | 403 | .ebi_csa_offs = AT91SAM9263_MATRIX_EBI1CSA, |
| 404 | .regmap_name = "atmel,matrix", | ||
| 399 | .get_config = at91sam9_ebi_get_config, | 405 | .get_config = at91sam9_ebi_get_config, |
| 400 | .xlate_config = atmel_ebi_xslate_smc_config, | 406 | .xlate_config = atmel_ebi_xslate_smc_config, |
| 401 | .apply_config = at91sam9_ebi_apply_config, | 407 | .apply_config = at91sam9_ebi_apply_config, |
| @@ -404,6 +410,7 @@ static const struct atmel_ebi_caps at91sam9263_ebi1_caps = { | |||
| 404 | static const struct atmel_ebi_caps at91sam9rl_ebi_caps = { | 410 | static const struct atmel_ebi_caps at91sam9rl_ebi_caps = { |
| 405 | .available_cs = 0x3f, | 411 | .available_cs = 0x3f, |
| 406 | .ebi_csa_offs = AT91SAM9RL_MATRIX_EBICSA, | 412 | .ebi_csa_offs = AT91SAM9RL_MATRIX_EBICSA, |
| 413 | .regmap_name = "atmel,matrix", | ||
| 407 | .get_config = at91sam9_ebi_get_config, | 414 | .get_config = at91sam9_ebi_get_config, |
| 408 | .xlate_config = atmel_ebi_xslate_smc_config, | 415 | .xlate_config = atmel_ebi_xslate_smc_config, |
| 409 | .apply_config = at91sam9_ebi_apply_config, | 416 | .apply_config = at91sam9_ebi_apply_config, |
| @@ -412,6 +419,7 @@ static const struct atmel_ebi_caps at91sam9rl_ebi_caps = { | |||
| 412 | static const struct atmel_ebi_caps at91sam9g45_ebi_caps = { | 419 | static const struct atmel_ebi_caps at91sam9g45_ebi_caps = { |
| 413 | .available_cs = 0x3f, | 420 | .available_cs = 0x3f, |
| 414 | .ebi_csa_offs = AT91SAM9G45_MATRIX_EBICSA, | 421 | .ebi_csa_offs = AT91SAM9G45_MATRIX_EBICSA, |
| 422 | .regmap_name = "atmel,matrix", | ||
| 415 | .get_config = at91sam9_ebi_get_config, | 423 | .get_config = at91sam9_ebi_get_config, |
| 416 | .xlate_config = atmel_ebi_xslate_smc_config, | 424 | .xlate_config = atmel_ebi_xslate_smc_config, |
| 417 | .apply_config = at91sam9_ebi_apply_config, | 425 | .apply_config = at91sam9_ebi_apply_config, |
| @@ -420,6 +428,7 @@ static const struct atmel_ebi_caps at91sam9g45_ebi_caps = { | |||
| 420 | static const struct atmel_ebi_caps at91sam9x5_ebi_caps = { | 428 | static const struct atmel_ebi_caps at91sam9x5_ebi_caps = { |
| 421 | .available_cs = 0x3f, | 429 | .available_cs = 0x3f, |
| 422 | .ebi_csa_offs = AT91SAM9X5_MATRIX_EBICSA, | 430 | .ebi_csa_offs = AT91SAM9X5_MATRIX_EBICSA, |
| 431 | .regmap_name = "atmel,matrix", | ||
| 423 | .get_config = at91sam9_ebi_get_config, | 432 | .get_config = at91sam9_ebi_get_config, |
| 424 | .xlate_config = atmel_ebi_xslate_smc_config, | 433 | .xlate_config = atmel_ebi_xslate_smc_config, |
| 425 | .apply_config = at91sam9_ebi_apply_config, | 434 | .apply_config = at91sam9_ebi_apply_config, |
| @@ -432,6 +441,15 @@ static const struct atmel_ebi_caps sama5d3_ebi_caps = { | |||
| 432 | .apply_config = sama5_ebi_apply_config, | 441 | .apply_config = sama5_ebi_apply_config, |
| 433 | }; | 442 | }; |
| 434 | 443 | ||
| 444 | static const struct atmel_ebi_caps sam9x60_ebi_caps = { | ||
| 445 | .available_cs = 0x3f, | ||
| 446 | .ebi_csa_offs = AT91_SFR_CCFG_EBICSA, | ||
| 447 | .regmap_name = "microchip,sfr", | ||
| 448 | .get_config = at91sam9_ebi_get_config, | ||
| 449 | .xlate_config = atmel_ebi_xslate_smc_config, | ||
| 450 | .apply_config = at91sam9_ebi_apply_config, | ||
| 451 | }; | ||
| 452 | |||
| 435 | static const struct of_device_id atmel_ebi_id_table[] = { | 453 | static const struct of_device_id atmel_ebi_id_table[] = { |
| 436 | { | 454 | { |
| 437 | .compatible = "atmel,at91sam9260-ebi", | 455 | .compatible = "atmel,at91sam9260-ebi", |
| @@ -465,6 +483,10 @@ static const struct of_device_id atmel_ebi_id_table[] = { | |||
| 465 | .compatible = "atmel,sama5d3-ebi", | 483 | .compatible = "atmel,sama5d3-ebi", |
| 466 | .data = &sama5d3_ebi_caps, | 484 | .data = &sama5d3_ebi_caps, |
| 467 | }, | 485 | }, |
| 486 | { | ||
| 487 | .compatible = "microchip,sam9x60-ebi", | ||
| 488 | .data = &sam9x60_ebi_caps, | ||
| 489 | }, | ||
| 468 | { /* sentinel */ } | 490 | { /* sentinel */ } |
| 469 | }; | 491 | }; |
| 470 | 492 | ||
| @@ -543,13 +565,14 @@ static int atmel_ebi_probe(struct platform_device *pdev) | |||
| 543 | 565 | ||
| 544 | /* | 566 | /* |
| 545 | * The sama5d3 does not provide an EBICSA register and thus does need | 567 | * The sama5d3 does not provide an EBICSA register and thus does need |
| 546 | * to access the matrix registers. | 568 | * to access it. |
| 547 | */ | 569 | */ |
| 548 | if (ebi->caps->ebi_csa_offs) { | 570 | if (ebi->caps->ebi_csa_offs) { |
| 549 | ebi->matrix = | 571 | ebi->regmap = |
| 550 | syscon_regmap_lookup_by_phandle(np, "atmel,matrix"); | 572 | syscon_regmap_lookup_by_phandle(np, |
| 551 | if (IS_ERR(ebi->matrix)) | 573 | ebi->caps->regmap_name); |
| 552 | return PTR_ERR(ebi->matrix); | 574 | if (IS_ERR(ebi->regmap)) |
| 575 | return PTR_ERR(ebi->regmap); | ||
| 553 | } | 576 | } |
| 554 | 577 | ||
| 555 | ret = of_property_read_u32(np, "#address-cells", &val); | 578 | ret = of_property_read_u32(np, "#address-cells", &val); |
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 79a8ff542883..fb31a7f649a3 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
| @@ -60,22 +60,6 @@ config MTD_CMDLINE_PARTS | |||
| 60 | 60 | ||
| 61 | If unsure, say 'N'. | 61 | If unsure, say 'N'. |
| 62 | 62 | ||
| 63 | config MTD_AFS_PARTS | ||
| 64 | tristate "ARM Firmware Suite partition parsing" | ||
| 65 | depends on (ARM || ARM64) | ||
| 66 | help | ||
| 67 | The ARM Firmware Suite allows the user to divide flash devices into | ||
| 68 | multiple 'images'. Each such image has a header containing its name | ||
| 69 | and offset/size etc. | ||
| 70 | |||
| 71 | If you need code which can detect and parse these tables, and | ||
| 72 | register MTD 'partitions' corresponding to each image detected, | ||
| 73 | enable this option. | ||
| 74 | |||
| 75 | You will still need the parsing functions to be called by the driver | ||
| 76 | for your particular device. It won't happen automatically. The | ||
| 77 | 'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example. | ||
| 78 | |||
| 79 | config MTD_OF_PARTS | 63 | config MTD_OF_PARTS |
| 80 | tristate "OpenFirmware partitioning information support" | 64 | tristate "OpenFirmware partitioning information support" |
| 81 | default y | 65 | default y |
| @@ -94,6 +78,7 @@ config MTD_BCM63XX_PARTS | |||
| 94 | tristate "BCM63XX CFE partitioning support" | 78 | tristate "BCM63XX CFE partitioning support" |
| 95 | depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST | 79 | depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST |
| 96 | select CRC32 | 80 | select CRC32 |
| 81 | select MTD_PARSER_IMAGETAG | ||
| 97 | help | 82 | help |
| 98 | This provides partition parsing for BCM63xx devices with CFE | 83 | This provides partition parsing for BCM63xx devices with CFE |
| 99 | bootloaders. | 84 | bootloaders. |
| @@ -230,12 +215,11 @@ config SSFDC | |||
| 230 | This enables read only access to SmartMedia formatted NAND | 215 | This enables read only access to SmartMedia formatted NAND |
| 231 | flash. You can mount it with FAT file system. | 216 | flash. You can mount it with FAT file system. |
| 232 | 217 | ||
| 233 | |||
| 234 | config SM_FTL | 218 | config SM_FTL |
| 235 | tristate "SmartMedia/xD new translation layer" | 219 | tristate "SmartMedia/xD new translation layer" |
| 236 | depends on BLOCK | 220 | depends on BLOCK |
| 237 | select MTD_BLKDEVS | 221 | select MTD_BLKDEVS |
| 238 | select MTD_NAND_ECC | 222 | select MTD_NAND_ECC_SW_HAMMING |
| 239 | help | 223 | help |
| 240 | This enables EXPERIMENTAL R/W support for SmartMedia/xD | 224 | This enables EXPERIMENTAL R/W support for SmartMedia/xD |
| 241 | FTL (Flash translation layer). | 225 | FTL (Flash translation layer). |
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 58fc327a5276..806287e80e84 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile | |||
| @@ -9,7 +9,6 @@ mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o | |||
| 9 | 9 | ||
| 10 | obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o | 10 | obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o |
| 11 | obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o | 11 | obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o |
| 12 | obj-$(CONFIG_MTD_AFS_PARTS) += afs.o | ||
| 13 | obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o | 12 | obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o |
| 14 | obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o | 13 | obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o |
| 15 | obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o | 14 | obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o |
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c deleted file mode 100644 index d61b7edfc938..000000000000 --- a/drivers/mtd/afs.c +++ /dev/null | |||
| @@ -1,266 +0,0 @@ | |||
| 1 | /*====================================================================== | ||
| 2 | |||
| 3 | drivers/mtd/afs.c: ARM Flash Layout/Partitioning | ||
| 4 | |||
| 5 | Copyright © 2000 ARM Limited | ||
| 6 | |||
| 7 | This program is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 2 of the License, or | ||
| 10 | (at your option) any later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software | ||
| 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | |||
| 21 | This is access code for flashes using ARM's flash partitioning | ||
| 22 | standards. | ||
| 23 | |||
| 24 | ======================================================================*/ | ||
| 25 | |||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/types.h> | ||
| 28 | #include <linux/kernel.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/string.h> | ||
| 31 | #include <linux/init.h> | ||
| 32 | |||
| 33 | #include <linux/mtd/mtd.h> | ||
| 34 | #include <linux/mtd/map.h> | ||
| 35 | #include <linux/mtd/partitions.h> | ||
| 36 | |||
| 37 | #define AFSV1_FOOTER_MAGIC 0xA0FFFF9F | ||
| 38 | |||
| 39 | struct footer_v1 { | ||
| 40 | u32 image_info_base; /* Address of first word of ImageFooter */ | ||
| 41 | u32 image_start; /* Start of area reserved by this footer */ | ||
| 42 | u32 signature; /* 'Magic' number proves it's a footer */ | ||
| 43 | u32 type; /* Area type: ARM Image, SIB, customer */ | ||
| 44 | u32 checksum; /* Just this structure */ | ||
| 45 | }; | ||
| 46 | |||
| 47 | struct image_info_v1 { | ||
| 48 | u32 bootFlags; /* Boot flags, compression etc. */ | ||
| 49 | u32 imageNumber; /* Unique number, selects for boot etc. */ | ||
| 50 | u32 loadAddress; /* Address program should be loaded to */ | ||
| 51 | u32 length; /* Actual size of image */ | ||
| 52 | u32 address; /* Image is executed from here */ | ||
| 53 | char name[16]; /* Null terminated */ | ||
| 54 | u32 headerBase; /* Flash Address of any stripped header */ | ||
| 55 | u32 header_length; /* Length of header in memory */ | ||
| 56 | u32 headerType; /* AIF, RLF, s-record etc. */ | ||
| 57 | u32 checksum; /* Image checksum (inc. this struct) */ | ||
| 58 | }; | ||
| 59 | |||
| 60 | static u32 word_sum(void *words, int num) | ||
| 61 | { | ||
| 62 | u32 *p = words; | ||
| 63 | u32 sum = 0; | ||
| 64 | |||
| 65 | while (num--) | ||
| 66 | sum += *p++; | ||
| 67 | |||
| 68 | return sum; | ||
| 69 | } | ||
| 70 | |||
| 71 | static int | ||
| 72 | afs_read_footer_v1(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, | ||
| 73 | u_int off, u_int mask) | ||
| 74 | { | ||
| 75 | struct footer_v1 fs; | ||
| 76 | u_int ptr = off + mtd->erasesize - sizeof(fs); | ||
| 77 | size_t sz; | ||
| 78 | int ret; | ||
| 79 | |||
| 80 | ret = mtd_read(mtd, ptr, sizeof(fs), &sz, (u_char *)&fs); | ||
| 81 | if (ret >= 0 && sz != sizeof(fs)) | ||
| 82 | ret = -EINVAL; | ||
| 83 | |||
| 84 | if (ret < 0) { | ||
| 85 | printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", | ||
| 86 | ptr, ret); | ||
| 87 | return ret; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Does it contain the magic number? | ||
| 92 | */ | ||
| 93 | if (fs.signature != AFSV1_FOOTER_MAGIC) | ||
| 94 | return 0; | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Check the checksum. | ||
| 98 | */ | ||
| 99 | if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff) | ||
| 100 | return 0; | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Don't touch the SIB. | ||
| 104 | */ | ||
| 105 | if (fs.type == 2) | ||
| 106 | return 0; | ||
| 107 | |||
| 108 | *iis_start = fs.image_info_base & mask; | ||
| 109 | *img_start = fs.image_start & mask; | ||
| 110 | |||
| 111 | /* | ||
| 112 | * Check the image info base. This can not | ||
| 113 | * be located after the footer structure. | ||
| 114 | */ | ||
| 115 | if (*iis_start >= ptr) | ||
| 116 | return 0; | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Check the start of this image. The image | ||
| 120 | * data can not be located after this block. | ||
| 121 | */ | ||
| 122 | if (*img_start > off) | ||
| 123 | return 0; | ||
| 124 | |||
| 125 | return 1; | ||
| 126 | } | ||
| 127 | |||
| 128 | static int | ||
| 129 | afs_read_iis_v1(struct mtd_info *mtd, struct image_info_v1 *iis, u_int ptr) | ||
| 130 | { | ||
| 131 | size_t sz; | ||
| 132 | int ret, i; | ||
| 133 | |||
| 134 | memset(iis, 0, sizeof(*iis)); | ||
| 135 | ret = mtd_read(mtd, ptr, sizeof(*iis), &sz, (u_char *)iis); | ||
| 136 | if (ret < 0) | ||
| 137 | goto failed; | ||
| 138 | |||
| 139 | if (sz != sizeof(*iis)) { | ||
| 140 | ret = -EINVAL; | ||
| 141 | goto failed; | ||
| 142 | } | ||
| 143 | |||
| 144 | ret = 0; | ||
| 145 | |||
| 146 | /* | ||
| 147 | * Validate the name - it must be NUL terminated. | ||
| 148 | */ | ||
| 149 | for (i = 0; i < sizeof(iis->name); i++) | ||
| 150 | if (iis->name[i] == '\0') | ||
| 151 | break; | ||
| 152 | |||
| 153 | if (i < sizeof(iis->name)) | ||
| 154 | ret = 1; | ||
| 155 | |||
| 156 | return ret; | ||
| 157 | |||
| 158 | failed: | ||
| 159 | printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", | ||
| 160 | ptr, ret); | ||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | |||
| 164 | static int parse_afs_partitions(struct mtd_info *mtd, | ||
| 165 | const struct mtd_partition **pparts, | ||
| 166 | struct mtd_part_parser_data *data) | ||
| 167 | { | ||
| 168 | struct mtd_partition *parts; | ||
| 169 | u_int mask, off, idx, sz; | ||
| 170 | int ret = 0; | ||
| 171 | char *str; | ||
| 172 | |||
| 173 | /* | ||
| 174 | * This is the address mask; we use this to mask off out of | ||
| 175 | * range address bits. | ||
| 176 | */ | ||
| 177 | mask = mtd->size - 1; | ||
| 178 | |||
| 179 | /* | ||
| 180 | * First, calculate the size of the array we need for the | ||
| 181 | * partition information. We include in this the size of | ||
| 182 | * the strings. | ||
| 183 | */ | ||
| 184 | for (idx = off = sz = 0; off < mtd->size; off += mtd->erasesize) { | ||
| 185 | struct image_info_v1 iis; | ||
| 186 | u_int iis_ptr, img_ptr; | ||
| 187 | |||
| 188 | ret = afs_read_footer_v1(mtd, &img_ptr, &iis_ptr, off, mask); | ||
| 189 | if (ret < 0) | ||
| 190 | break; | ||
| 191 | if (ret) { | ||
| 192 | ret = afs_read_iis_v1(mtd, &iis, iis_ptr); | ||
| 193 | if (ret < 0) | ||
| 194 | break; | ||
| 195 | if (ret == 0) | ||
| 196 | continue; | ||
| 197 | |||
| 198 | sz += sizeof(struct mtd_partition); | ||
| 199 | sz += strlen(iis.name) + 1; | ||
| 200 | idx += 1; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | if (!sz) | ||
| 205 | return ret; | ||
| 206 | |||
| 207 | parts = kzalloc(sz, GFP_KERNEL); | ||
| 208 | if (!parts) | ||
| 209 | return -ENOMEM; | ||
| 210 | |||
| 211 | str = (char *)(parts + idx); | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Identify the partitions | ||
| 215 | */ | ||
| 216 | for (idx = off = 0; off < mtd->size; off += mtd->erasesize) { | ||
| 217 | struct image_info_v1 iis; | ||
| 218 | u_int iis_ptr, img_ptr; | ||
| 219 | |||
| 220 | /* Read the footer. */ | ||
| 221 | ret = afs_read_footer_v1(mtd, &img_ptr, &iis_ptr, off, mask); | ||
| 222 | if (ret < 0) | ||
| 223 | break; | ||
| 224 | if (ret == 0) | ||
| 225 | continue; | ||
| 226 | |||
| 227 | /* Read the image info block */ | ||
| 228 | ret = afs_read_iis_v1(mtd, &iis, iis_ptr); | ||
| 229 | if (ret < 0) | ||
| 230 | break; | ||
| 231 | if (ret == 0) | ||
| 232 | continue; | ||
| 233 | |||
| 234 | strcpy(str, iis.name); | ||
| 235 | |||
| 236 | parts[idx].name = str; | ||
| 237 | parts[idx].size = (iis.length + mtd->erasesize - 1) & ~(mtd->erasesize - 1); | ||
| 238 | parts[idx].offset = img_ptr; | ||
| 239 | parts[idx].mask_flags = 0; | ||
| 240 | |||
| 241 | printk(" mtd%d: at 0x%08x, %5lluKiB, %8u, %s\n", | ||
| 242 | idx, img_ptr, parts[idx].size / 1024, | ||
| 243 | iis.imageNumber, str); | ||
| 244 | |||
| 245 | idx += 1; | ||
| 246 | str = str + strlen(iis.name) + 1; | ||
| 247 | } | ||
| 248 | |||
| 249 | if (!idx) { | ||
| 250 | kfree(parts); | ||
| 251 | parts = NULL; | ||
| 252 | } | ||
| 253 | |||
| 254 | *pparts = parts; | ||
| 255 | return idx ? idx : ret; | ||
| 256 | } | ||
| 257 | |||
| 258 | static struct mtd_part_parser afs_parser = { | ||
| 259 | .parse_fn = parse_afs_partitions, | ||
| 260 | .name = "afs", | ||
| 261 | }; | ||
| 262 | module_mtd_part_parser(afs_parser); | ||
| 263 | |||
| 264 | MODULE_AUTHOR("ARM Ltd"); | ||
| 265 | MODULE_DESCRIPTION("ARM Firmware Suite partition parser"); | ||
| 266 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 41d1d3149c61..b2bd04764e95 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
| 35 | #include <linux/mtd/mtd.h> | 35 | #include <linux/mtd/mtd.h> |
| 36 | #include <linux/mtd/partitions.h> | 36 | #include <linux/mtd/partitions.h> |
| 37 | #include <linux/of.h> | ||
| 37 | 38 | ||
| 38 | #define BCM963XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */ | 39 | #define BCM963XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */ |
| 39 | 40 | ||
| @@ -93,51 +94,19 @@ static int bcm63xx_read_nvram(struct mtd_info *master, | |||
| 93 | return 0; | 94 | return 0; |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | static int bcm63xx_read_image_tag(struct mtd_info *master, const char *name, | 97 | static const char * const bcm63xx_cfe_part_types[] = { |
| 97 | loff_t tag_offset, struct bcm_tag *buf) | 98 | "bcm963xx-imagetag", |
| 98 | { | 99 | NULL, |
| 99 | int ret; | 100 | }; |
| 100 | size_t retlen; | ||
| 101 | u32 computed_crc; | ||
| 102 | |||
| 103 | ret = mtd_read(master, tag_offset, sizeof(*buf), &retlen, (void *)buf); | ||
| 104 | if (ret) | ||
| 105 | return ret; | ||
| 106 | |||
| 107 | if (retlen != sizeof(*buf)) | ||
| 108 | return -EIO; | ||
| 109 | |||
| 110 | computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf, | ||
| 111 | offsetof(struct bcm_tag, header_crc)); | ||
| 112 | if (computed_crc == buf->header_crc) { | ||
| 113 | STR_NULL_TERMINATE(buf->board_id); | ||
| 114 | STR_NULL_TERMINATE(buf->tag_version); | ||
| 115 | |||
| 116 | pr_info("%s: CFE image tag found at 0x%llx with version %s, board type %s\n", | ||
| 117 | name, tag_offset, buf->tag_version, buf->board_id); | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | pr_warn("%s: CFE image tag at 0x%llx CRC invalid (expected %08x, actual %08x)\n", | ||
| 123 | name, tag_offset, buf->header_crc, computed_crc); | ||
| 124 | return 1; | ||
| 125 | } | ||
| 126 | 101 | ||
| 127 | static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master, | 102 | static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master, |
| 128 | const struct mtd_partition **pparts, struct bcm963xx_nvram *nvram) | 103 | const struct mtd_partition **pparts, struct bcm963xx_nvram *nvram) |
| 129 | { | 104 | { |
| 130 | /* CFE, NVRAM and global Linux are always present */ | ||
| 131 | int nrparts = 3, curpart = 0; | ||
| 132 | struct bcm_tag *buf = NULL; | ||
| 133 | struct mtd_partition *parts; | 105 | struct mtd_partition *parts; |
| 134 | int ret; | 106 | int nrparts = 3, curpart = 0; |
| 135 | unsigned int rootfsaddr, kerneladdr, spareaddr; | ||
| 136 | unsigned int rootfslen, kernellen, sparelen, totallen; | ||
| 137 | unsigned int cfelen, nvramlen; | 107 | unsigned int cfelen, nvramlen; |
| 138 | unsigned int cfe_erasesize; | 108 | unsigned int cfe_erasesize; |
| 139 | int i; | 109 | int i; |
| 140 | bool rootfs_first = false; | ||
| 141 | 110 | ||
| 142 | cfe_erasesize = max_t(uint32_t, master->erasesize, | 111 | cfe_erasesize = max_t(uint32_t, master->erasesize, |
| 143 | BCM963XX_CFE_BLOCK_SIZE); | 112 | BCM963XX_CFE_BLOCK_SIZE); |
| @@ -146,83 +115,9 @@ static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master, | |||
| 146 | nvramlen = nvram->psi_size * SZ_1K; | 115 | nvramlen = nvram->psi_size * SZ_1K; |
| 147 | nvramlen = roundup(nvramlen, cfe_erasesize); | 116 | nvramlen = roundup(nvramlen, cfe_erasesize); |
| 148 | 117 | ||
| 149 | buf = vmalloc(sizeof(struct bcm_tag)); | ||
| 150 | if (!buf) | ||
| 151 | return -ENOMEM; | ||
| 152 | |||
| 153 | /* Get the tag */ | ||
| 154 | ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf); | ||
| 155 | if (!ret) { | ||
| 156 | STR_NULL_TERMINATE(buf->flash_image_start); | ||
| 157 | if (kstrtouint(buf->flash_image_start, 10, &rootfsaddr) || | ||
| 158 | rootfsaddr < BCM963XX_EXTENDED_SIZE) { | ||
| 159 | pr_err("invalid rootfs address: %*ph\n", | ||
| 160 | (int)sizeof(buf->flash_image_start), | ||
| 161 | buf->flash_image_start); | ||
| 162 | goto invalid_tag; | ||
| 163 | } | ||
| 164 | |||
| 165 | STR_NULL_TERMINATE(buf->kernel_address); | ||
| 166 | if (kstrtouint(buf->kernel_address, 10, &kerneladdr) || | ||
| 167 | kerneladdr < BCM963XX_EXTENDED_SIZE) { | ||
| 168 | pr_err("invalid kernel address: %*ph\n", | ||
| 169 | (int)sizeof(buf->kernel_address), | ||
| 170 | buf->kernel_address); | ||
| 171 | goto invalid_tag; | ||
| 172 | } | ||
| 173 | |||
| 174 | STR_NULL_TERMINATE(buf->kernel_length); | ||
| 175 | if (kstrtouint(buf->kernel_length, 10, &kernellen)) { | ||
| 176 | pr_err("invalid kernel length: %*ph\n", | ||
| 177 | (int)sizeof(buf->kernel_length), | ||
| 178 | buf->kernel_length); | ||
| 179 | goto invalid_tag; | ||
| 180 | } | ||
| 181 | |||
| 182 | STR_NULL_TERMINATE(buf->total_length); | ||
| 183 | if (kstrtouint(buf->total_length, 10, &totallen)) { | ||
| 184 | pr_err("invalid total length: %*ph\n", | ||
| 185 | (int)sizeof(buf->total_length), | ||
| 186 | buf->total_length); | ||
| 187 | goto invalid_tag; | ||
| 188 | } | ||
| 189 | |||
| 190 | kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE; | ||
| 191 | rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE; | ||
| 192 | spareaddr = roundup(totallen, master->erasesize) + cfelen; | ||
| 193 | |||
| 194 | if (rootfsaddr < kerneladdr) { | ||
| 195 | /* default Broadcom layout */ | ||
| 196 | rootfslen = kerneladdr - rootfsaddr; | ||
| 197 | rootfs_first = true; | ||
| 198 | } else { | ||
| 199 | /* OpenWrt layout */ | ||
| 200 | rootfsaddr = kerneladdr + kernellen; | ||
| 201 | rootfslen = spareaddr - rootfsaddr; | ||
| 202 | } | ||
| 203 | } else if (ret > 0) { | ||
| 204 | invalid_tag: | ||
| 205 | kernellen = 0; | ||
| 206 | rootfslen = 0; | ||
| 207 | rootfsaddr = 0; | ||
| 208 | spareaddr = cfelen; | ||
| 209 | } else { | ||
| 210 | goto out; | ||
| 211 | } | ||
| 212 | sparelen = master->size - spareaddr - nvramlen; | ||
| 213 | |||
| 214 | /* Determine number of partitions */ | ||
| 215 | if (rootfslen > 0) | ||
| 216 | nrparts++; | ||
| 217 | |||
| 218 | if (kernellen > 0) | ||
| 219 | nrparts++; | ||
| 220 | |||
| 221 | parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); | 118 | parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); |
| 222 | if (!parts) { | 119 | if (!parts) |
| 223 | ret = -ENOMEM; | 120 | return -ENOMEM; |
| 224 | goto out; | ||
| 225 | } | ||
| 226 | 121 | ||
| 227 | /* Start building partition list */ | 122 | /* Start building partition list */ |
| 228 | parts[curpart].name = "CFE"; | 123 | parts[curpart].name = "CFE"; |
| @@ -230,30 +125,6 @@ invalid_tag: | |||
| 230 | parts[curpart].size = cfelen; | 125 | parts[curpart].size = cfelen; |
| 231 | curpart++; | 126 | curpart++; |
| 232 | 127 | ||
| 233 | if (kernellen > 0) { | ||
| 234 | int kernelpart = curpart; | ||
| 235 | |||
| 236 | if (rootfslen > 0 && rootfs_first) | ||
| 237 | kernelpart++; | ||
| 238 | parts[kernelpart].name = "kernel"; | ||
| 239 | parts[kernelpart].offset = kerneladdr; | ||
| 240 | parts[kernelpart].size = kernellen; | ||
| 241 | curpart++; | ||
| 242 | } | ||
| 243 | |||
| 244 | if (rootfslen > 0) { | ||
| 245 | int rootfspart = curpart; | ||
| 246 | |||
| 247 | if (kernellen > 0 && rootfs_first) | ||
| 248 | rootfspart--; | ||
| 249 | parts[rootfspart].name = "rootfs"; | ||
| 250 | parts[rootfspart].offset = rootfsaddr; | ||
| 251 | parts[rootfspart].size = rootfslen; | ||
| 252 | if (sparelen > 0 && !rootfs_first) | ||
| 253 | parts[rootfspart].size += sparelen; | ||
| 254 | curpart++; | ||
| 255 | } | ||
| 256 | |||
| 257 | parts[curpart].name = "nvram"; | 128 | parts[curpart].name = "nvram"; |
| 258 | parts[curpart].offset = master->size - nvramlen; | 129 | parts[curpart].offset = master->size - nvramlen; |
| 259 | parts[curpart].size = nvramlen; | 130 | parts[curpart].size = nvramlen; |
| @@ -263,22 +134,13 @@ invalid_tag: | |||
| 263 | parts[curpart].name = "linux"; | 134 | parts[curpart].name = "linux"; |
| 264 | parts[curpart].offset = cfelen; | 135 | parts[curpart].offset = cfelen; |
| 265 | parts[curpart].size = master->size - cfelen - nvramlen; | 136 | parts[curpart].size = master->size - cfelen - nvramlen; |
| 137 | parts[curpart].types = bcm63xx_cfe_part_types; | ||
| 266 | 138 | ||
| 267 | for (i = 0; i < nrparts; i++) | 139 | for (i = 0; i < nrparts; i++) |
| 268 | pr_info("Partition %d is %s offset %llx and length %llx\n", i, | 140 | pr_info("Partition %d is %s offset %llx and length %llx\n", i, |
| 269 | parts[i].name, parts[i].offset, parts[i].size); | 141 | parts[i].name, parts[i].offset, parts[i].size); |
| 270 | 142 | ||
| 271 | pr_info("Spare partition is offset %x and length %x\n", spareaddr, | ||
| 272 | sparelen); | ||
| 273 | |||
| 274 | *pparts = parts; | 143 | *pparts = parts; |
| 275 | ret = 0; | ||
| 276 | |||
| 277 | out: | ||
| 278 | vfree(buf); | ||
| 279 | |||
| 280 | if (ret) | ||
| 281 | return ret; | ||
| 282 | 144 | ||
| 283 | return nrparts; | 145 | return nrparts; |
| 284 | } | 146 | } |
| @@ -311,9 +173,16 @@ out: | |||
| 311 | return ret; | 173 | return ret; |
| 312 | }; | 174 | }; |
| 313 | 175 | ||
| 176 | static const struct of_device_id parse_bcm63xx_cfe_match_table[] = { | ||
| 177 | { .compatible = "brcm,bcm963xx-cfe-nor-partitions" }, | ||
| 178 | {}, | ||
| 179 | }; | ||
| 180 | MODULE_DEVICE_TABLE(of, parse_bcm63xx_cfe_match_table); | ||
| 181 | |||
| 314 | static struct mtd_part_parser bcm63xx_cfe_parser = { | 182 | static struct mtd_part_parser bcm63xx_cfe_parser = { |
| 315 | .parse_fn = bcm63xx_parse_cfe_partitions, | 183 | .parse_fn = bcm63xx_parse_cfe_partitions, |
| 316 | .name = "bcm63xxpart", | 184 | .name = "bcm63xxpart", |
| 185 | .of_match_table = parse_bcm63xx_cfe_match_table, | ||
| 317 | }; | 186 | }; |
| 318 | module_mtd_part_parser(bcm63xx_cfe_parser); | 187 | module_mtd_part_parser(bcm63xx_cfe_parser); |
| 319 | 188 | ||
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 7b7286b4d81e..c8fa5906bdf9 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
| @@ -869,6 +869,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
| 869 | /* Only if there's no operation suspended... */ | 869 | /* Only if there's no operation suspended... */ |
| 870 | if (mode == FL_READY && chip->oldstate == FL_READY) | 870 | if (mode == FL_READY && chip->oldstate == FL_READY) |
| 871 | return 0; | 871 | return 0; |
| 872 | /* fall through */ | ||
| 872 | 873 | ||
| 873 | default: | 874 | default: |
| 874 | sleep: | 875 | sleep: |
| @@ -2751,6 +2752,7 @@ static void cfi_amdstd_sync (struct mtd_info *mtd) | |||
| 2751 | * as the whole point is that nobody can do anything | 2752 | * as the whole point is that nobody can do anything |
| 2752 | * with the chip now anyway. | 2753 | * with the chip now anyway. |
| 2753 | */ | 2754 | */ |
| 2755 | /* fall through */ | ||
| 2754 | case FL_SYNCING: | 2756 | case FL_SYNCING: |
| 2755 | mutex_unlock(&chip->mutex); | 2757 | mutex_unlock(&chip->mutex); |
| 2756 | break; | 2758 | break; |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index 6f16552cd59f..e3b266ee06af 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
| @@ -109,10 +109,13 @@ map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi | |||
| 109 | case 8: | 109 | case 8: |
| 110 | onecmd |= (onecmd << (chip_mode * 32)); | 110 | onecmd |= (onecmd << (chip_mode * 32)); |
| 111 | #endif | 111 | #endif |
| 112 | /* fall through */ | ||
| 112 | case 4: | 113 | case 4: |
| 113 | onecmd |= (onecmd << (chip_mode * 16)); | 114 | onecmd |= (onecmd << (chip_mode * 16)); |
| 115 | /* fall through */ | ||
| 114 | case 2: | 116 | case 2: |
| 115 | onecmd |= (onecmd << (chip_mode * 8)); | 117 | onecmd |= (onecmd << (chip_mode * 8)); |
| 118 | /* fall through */ | ||
| 116 | case 1: | 119 | case 1: |
| 117 | ; | 120 | ; |
| 118 | } | 121 | } |
| @@ -162,10 +165,13 @@ unsigned long cfi_merge_status(map_word val, struct map_info *map, | |||
| 162 | case 8: | 165 | case 8: |
| 163 | res |= (onestat >> (chip_mode * 32)); | 166 | res |= (onestat >> (chip_mode * 32)); |
| 164 | #endif | 167 | #endif |
| 168 | /* fall through */ | ||
| 165 | case 4: | 169 | case 4: |
| 166 | res |= (onestat >> (chip_mode * 16)); | 170 | res |= (onestat >> (chip_mode * 16)); |
| 171 | /* fall through */ | ||
| 167 | case 2: | 172 | case 2: |
| 168 | res |= (onestat >> (chip_mode * 8)); | 173 | res |= (onestat >> (chip_mode * 8)); |
| 174 | /* fall through */ | ||
| 169 | case 1: | 175 | case 1: |
| 170 | ; | 176 | ; |
| 171 | } | 177 | } |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index aa983422aa97..f9258d666846 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
| @@ -207,7 +207,7 @@ comment "Disk-On-Chip Device Drivers" | |||
| 207 | config MTD_DOCG3 | 207 | config MTD_DOCG3 |
| 208 | tristate "M-Systems Disk-On-Chip G3" | 208 | tristate "M-Systems Disk-On-Chip G3" |
| 209 | select BCH | 209 | select BCH |
| 210 | select BCH_CONST_PARAMS if !MTD_NAND_BCH | 210 | select BCH_CONST_PARAMS if !MTD_NAND_ECC_SW_BCH |
| 211 | select BITREVERSE | 211 | select BITREVERSE |
| 212 | help | 212 | help |
| 213 | This provides an MTD device driver for the M-Systems DiskOnChip | 213 | This provides an MTD device driver for the M-Systems DiskOnChip |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 9ee04b5f9311..8a8627c30aed 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
| @@ -147,8 +147,10 @@ static int parse_num64(uint64_t *num64, char *token) | |||
| 147 | switch (token[len - 2]) { | 147 | switch (token[len - 2]) { |
| 148 | case 'G': | 148 | case 'G': |
| 149 | shift += 10; | 149 | shift += 10; |
| 150 | /* fall through */ | ||
| 150 | case 'M': | 151 | case 'M': |
| 151 | shift += 10; | 152 | shift += 10; |
| 153 | /* fall through */ | ||
| 152 | case 'k': | 154 | case 'k': |
| 153 | shift += 10; | 155 | shift += 10; |
| 154 | token[len - 2] = 0; | 156 | token[len - 2] = 0; |
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index b13557fe52bd..76a4c73e100e 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c | |||
| @@ -318,6 +318,7 @@ static int chip_ready(struct map_info *map, struct flchip *chip, int mode) | |||
| 318 | /* Only if there's no operation suspended... */ | 318 | /* Only if there's no operation suspended... */ |
| 319 | if (mode == FL_READY && chip->oldstate == FL_READY) | 319 | if (mode == FL_READY && chip->oldstate == FL_READY) |
| 320 | return 0; | 320 | return 0; |
| 321 | /* fall through */ | ||
| 321 | 322 | ||
| 322 | default: | 323 | default: |
| 323 | sleep: | 324 | sleep: |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index e0cf869c8544..544ed1931843 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
| @@ -10,7 +10,7 @@ config MTD_COMPLEX_MAPPINGS | |||
| 10 | 10 | ||
| 11 | config MTD_PHYSMAP | 11 | config MTD_PHYSMAP |
| 12 | tristate "Flash device in physical memory map" | 12 | tristate "Flash device in physical memory map" |
| 13 | depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM || MTD_LPDDR | 13 | depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM || MTD_RAM || MTD_LPDDR |
| 14 | help | 14 | help |
| 15 | This provides a 'mapping' driver which allows the NOR Flash and | 15 | This provides a 'mapping' driver which allows the NOR Flash and |
| 16 | ROM driver code to communicate with chips which are mapped | 16 | ROM driver code to communicate with chips which are mapped |
diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index d9a3e4bebe5d..21b556afc305 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c | |||
| @@ -132,6 +132,8 @@ static void physmap_set_addr_gpios(struct physmap_flash_info *info, | |||
| 132 | 132 | ||
| 133 | gpiod_set_value(info->gpios->desc[i], !!(BIT(i) & ofs)); | 133 | gpiod_set_value(info->gpios->desc[i], !!(BIT(i) & ofs)); |
| 134 | } | 134 | } |
| 135 | |||
| 136 | info->gpio_values = ofs; | ||
| 135 | } | 137 | } |
| 136 | 138 | ||
| 137 | #define win_mask(order) (BIT(order) - 1) | 139 | #define win_mask(order) (BIT(order) - 1) |
diff --git a/drivers/mtd/maps/physmap-gemini.c b/drivers/mtd/maps/physmap-gemini.c index 60775b208fc9..a289c8b5cabf 100644 --- a/drivers/mtd/maps/physmap-gemini.c +++ b/drivers/mtd/maps/physmap-gemini.c | |||
| @@ -86,7 +86,7 @@ static void gemini_flash_disable_pins(void) | |||
| 86 | static map_word __xipram gemini_flash_map_read(struct map_info *map, | 86 | static map_word __xipram gemini_flash_map_read(struct map_info *map, |
| 87 | unsigned long ofs) | 87 | unsigned long ofs) |
| 88 | { | 88 | { |
| 89 | map_word __xipram ret; | 89 | map_word ret; |
| 90 | 90 | ||
| 91 | gemini_flash_enable_pins(); | 91 | gemini_flash_enable_pins(); |
| 92 | ret = inline_map_read(map, ofs); | 92 | ret = inline_map_read(map, ofs); |
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index aef030ca8601..de4c46318abb 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c | |||
| @@ -31,13 +31,7 @@ | |||
| 31 | #define MAP_NAME "ram" | 31 | #define MAP_NAME "ram" |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | /* | 34 | static struct map_info uclinux_ram_map = { |
| 35 | * Blackfin uses uclinux_ram_map during startup, so it must not be static. | ||
| 36 | * Provide a dummy declaration to make sparse happy. | ||
| 37 | */ | ||
| 38 | extern struct map_info uclinux_ram_map; | ||
| 39 | |||
| 40 | struct map_info uclinux_ram_map = { | ||
| 41 | .name = MAP_NAME, | 35 | .name = MAP_NAME, |
| 42 | .size = 0, | 36 | .size = 0, |
| 43 | }; | 37 | }; |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 37f174ccbcec..dfa241ad018b 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
| @@ -572,7 +572,7 @@ static ssize_t mtd_partition_offset_show(struct device *dev, | |||
| 572 | { | 572 | { |
| 573 | struct mtd_info *mtd = dev_get_drvdata(dev); | 573 | struct mtd_info *mtd = dev_get_drvdata(dev); |
| 574 | struct mtd_part *part = mtd_to_part(mtd); | 574 | struct mtd_part *part = mtd_to_part(mtd); |
| 575 | return snprintf(buf, PAGE_SIZE, "%lld\n", part->offset); | 575 | return snprintf(buf, PAGE_SIZE, "%llu\n", part->offset); |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | static DEVICE_ATTR(offset, S_IRUGO, mtd_partition_offset_show, NULL); | 578 | static DEVICE_ATTR(offset, S_IRUGO, mtd_partition_offset_show, NULL); |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 9033215e62ea..495751ed3fd7 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
| @@ -2,6 +2,5 @@ config MTD_NAND_CORE | |||
| 2 | tristate | 2 | tristate |
| 3 | 3 | ||
| 4 | source "drivers/mtd/nand/onenand/Kconfig" | 4 | source "drivers/mtd/nand/onenand/Kconfig" |
| 5 | |||
| 6 | source "drivers/mtd/nand/raw/Kconfig" | 5 | source "drivers/mtd/nand/raw/Kconfig" |
| 7 | source "drivers/mtd/nand/spi/Kconfig" | 6 | source "drivers/mtd/nand/spi/Kconfig" |
diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c index 9c9f8936b63b..b6de955ac8bf 100644 --- a/drivers/mtd/nand/core.c +++ b/drivers/mtd/nand/core.c | |||
| @@ -174,6 +174,40 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo) | |||
| 174 | EXPORT_SYMBOL_GPL(nanddev_mtd_erase); | 174 | EXPORT_SYMBOL_GPL(nanddev_mtd_erase); |
| 175 | 175 | ||
| 176 | /** | 176 | /** |
| 177 | * nanddev_mtd_max_bad_blocks() - Get the maximum number of bad eraseblock on | ||
| 178 | * a specific region of the NAND device | ||
| 179 | * @mtd: MTD device | ||
| 180 | * @offs: offset of the NAND region | ||
| 181 | * @len: length of the NAND region | ||
| 182 | * | ||
| 183 | * Default implementation for mtd->_max_bad_blocks(). Only works if | ||
| 184 | * nand->memorg.max_bad_eraseblocks_per_lun is > 0. | ||
| 185 | * | ||
| 186 | * Return: a positive number encoding the maximum number of eraseblocks on a | ||
| 187 | * portion of memory, a negative error code otherwise. | ||
| 188 | */ | ||
| 189 | int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len) | ||
| 190 | { | ||
| 191 | struct nand_device *nand = mtd_to_nanddev(mtd); | ||
| 192 | struct nand_pos pos, end; | ||
| 193 | unsigned int max_bb = 0; | ||
| 194 | |||
| 195 | if (!nand->memorg.max_bad_eraseblocks_per_lun) | ||
| 196 | return -ENOTSUPP; | ||
| 197 | |||
| 198 | nanddev_offs_to_pos(nand, offs, &pos); | ||
| 199 | nanddev_offs_to_pos(nand, offs + len, &end); | ||
| 200 | |||
| 201 | for (nanddev_offs_to_pos(nand, offs, &pos); | ||
| 202 | nanddev_pos_cmp(&pos, &end) < 0; | ||
| 203 | nanddev_pos_next_lun(nand, &pos)) | ||
| 204 | max_bb += nand->memorg.max_bad_eraseblocks_per_lun; | ||
| 205 | |||
| 206 | return max_bb; | ||
| 207 | } | ||
| 208 | EXPORT_SYMBOL_GPL(nanddev_mtd_max_bad_blocks); | ||
| 209 | |||
| 210 | /** | ||
| 177 | * nanddev_init() - Initialize a NAND device | 211 | * nanddev_init() - Initialize a NAND device |
| 178 | * @nand: NAND device | 212 | * @nand: NAND device |
| 179 | * @ops: NAND device operations | 213 | * @ops: NAND device operations |
diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c index 4ca4b194e7d7..f41d76248550 100644 --- a/drivers/mtd/nand/onenand/onenand_base.c +++ b/drivers/mtd/nand/onenand/onenand_base.c | |||
| @@ -2458,7 +2458,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
| 2458 | bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | 2458 | bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); |
| 2459 | 2459 | ||
| 2460 | /* We write two bytes, so we don't have to mess with 16-bit access */ | 2460 | /* We write two bytes, so we don't have to mess with 16-bit access */ |
| 2461 | ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); | 2461 | ofs += mtd->oobsize + (this->badblockpos & ~0x01); |
| 2462 | /* FIXME : What to do when marking SLC block in partition | 2462 | /* FIXME : What to do when marking SLC block in partition |
| 2463 | * with MLC erasesize? For now, it is not advisable to | 2463 | * with MLC erasesize? For now, it is not advisable to |
| 2464 | * create partitions containing both SLC and MLC regions. | 2464 | * create partitions containing both SLC and MLC regions. |
| @@ -3967,6 +3967,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
| 3967 | if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING)) | 3967 | if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING)) |
| 3968 | this->unlock_all(mtd); | 3968 | this->unlock_all(mtd); |
| 3969 | 3969 | ||
| 3970 | /* Set the bad block marker position */ | ||
| 3971 | this->badblockpos = ONENAND_BADBLOCK_POS; | ||
| 3972 | |||
| 3970 | ret = this->scan_bbt(mtd); | 3973 | ret = this->scan_bbt(mtd); |
| 3971 | if ((!FLEXONENAND(this)) || ret) | 3974 | if ((!FLEXONENAND(this)) || ret) |
| 3972 | return ret; | 3975 | return ret; |
diff --git a/drivers/mtd/nand/onenand/onenand_bbt.c b/drivers/mtd/nand/onenand/onenand_bbt.c index dde20487937d..57c31c81be18 100644 --- a/drivers/mtd/nand/onenand/onenand_bbt.c +++ b/drivers/mtd/nand/onenand/onenand_bbt.c | |||
| @@ -190,9 +190,6 @@ static int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
| 190 | if (!bbm->bbt) | 190 | if (!bbm->bbt) |
| 191 | return -ENOMEM; | 191 | return -ENOMEM; |
| 192 | 192 | ||
| 193 | /* Set the bad block position */ | ||
| 194 | bbm->badblockpos = ONENAND_BADBLOCK_POS; | ||
| 195 | |||
| 196 | /* Set erase shift */ | 193 | /* Set erase shift */ |
| 197 | bbm->bbt_erase_shift = this->erase_shift; | 194 | bbm->bbt_erase_shift = this->erase_shift; |
| 198 | 195 | ||
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index e604625e2dfa..0500c42f31cb 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig | |||
| @@ -1,34 +1,29 @@ | |||
| 1 | config MTD_NAND_ECC | 1 | config MTD_NAND_ECC_SW_HAMMING |
| 2 | tristate | 2 | tristate |
| 3 | 3 | ||
| 4 | config MTD_NAND_ECC_SMC | 4 | config MTD_NAND_ECC_SW_HAMMING_SMC |
| 5 | bool "NAND ECC Smart Media byte order" | 5 | bool "NAND ECC Smart Media byte order" |
| 6 | depends on MTD_NAND_ECC | 6 | depends on MTD_NAND_ECC_SW_HAMMING |
| 7 | default n | 7 | default n |
| 8 | help | 8 | help |
| 9 | Software ECC according to the Smart Media Specification. | 9 | Software ECC according to the Smart Media Specification. |
| 10 | The original Linux implementation had byte 0 and 1 swapped. | 10 | The original Linux implementation had byte 0 and 1 swapped. |
| 11 | 11 | ||
| 12 | 12 | menuconfig MTD_RAW_NAND | |
| 13 | menuconfig MTD_NAND | ||
| 14 | tristate "Raw/Parallel NAND Device Support" | 13 | tristate "Raw/Parallel NAND Device Support" |
| 15 | depends on MTD | 14 | depends on MTD |
| 16 | select MTD_NAND_ECC | 15 | select MTD_NAND_CORE |
| 16 | select MTD_NAND_ECC_SW_HAMMING | ||
| 17 | help | 17 | help |
| 18 | This enables support for accessing all type of raw/parallel | 18 | This enables support for accessing all type of raw/parallel |
| 19 | NAND flash devices. For further information see | 19 | NAND flash devices. For further information see |
| 20 | <http://www.linux-mtd.infradead.org/doc/nand.html>. | 20 | <http://www.linux-mtd.infradead.org/doc/nand.html>. |
| 21 | 21 | ||
| 22 | if MTD_NAND | 22 | if MTD_RAW_NAND |
| 23 | 23 | ||
| 24 | config MTD_NAND_BCH | 24 | config MTD_NAND_ECC_SW_BCH |
| 25 | tristate | ||
| 26 | select BCH | ||
| 27 | depends on MTD_NAND_ECC_BCH | ||
| 28 | default MTD_NAND | ||
| 29 | |||
| 30 | config MTD_NAND_ECC_BCH | ||
| 31 | bool "Support software BCH ECC" | 25 | bool "Support software BCH ECC" |
| 26 | select BCH | ||
| 32 | default n | 27 | default n |
| 33 | help | 28 | help |
| 34 | This enables support for software BCH error correction. Binary BCH | 29 | This enables support for software BCH error correction. Binary BCH |
| @@ -36,15 +31,13 @@ config MTD_NAND_ECC_BCH | |||
| 36 | ECC codes. They are used with NAND devices requiring more than 1 bit | 31 | ECC codes. They are used with NAND devices requiring more than 1 bit |
| 37 | of error correction. | 32 | of error correction. |
| 38 | 33 | ||
| 39 | config MTD_SM_COMMON | 34 | comment "Raw/parallel NAND flash controllers" |
| 40 | tristate | ||
| 41 | default n | ||
| 42 | 35 | ||
| 43 | config MTD_NAND_DENALI | 36 | config MTD_NAND_DENALI |
| 44 | tristate | 37 | tristate |
| 45 | 38 | ||
| 46 | config MTD_NAND_DENALI_PCI | 39 | config MTD_NAND_DENALI_PCI |
| 47 | tristate "Support Denali NAND controller on Intel Moorestown" | 40 | tristate "Denali NAND controller on Intel Moorestown" |
| 48 | select MTD_NAND_DENALI | 41 | select MTD_NAND_DENALI |
| 49 | depends on PCI | 42 | depends on PCI |
| 50 | help | 43 | help |
| @@ -52,31 +45,22 @@ config MTD_NAND_DENALI_PCI | |||
| 52 | Denali NAND controller core. | 45 | Denali NAND controller core. |
| 53 | 46 | ||
| 54 | config MTD_NAND_DENALI_DT | 47 | config MTD_NAND_DENALI_DT |
| 55 | tristate "Support Denali NAND controller as a DT device" | 48 | tristate "Denali NAND controller as a DT device" |
| 56 | select MTD_NAND_DENALI | 49 | select MTD_NAND_DENALI |
| 57 | depends on HAS_DMA && HAVE_CLK && OF | 50 | depends on HAS_DMA && HAVE_CLK && OF |
| 58 | help | 51 | help |
| 59 | Enable the driver for NAND flash on platforms using a Denali NAND | 52 | Enable the driver for NAND flash on platforms using a Denali NAND |
| 60 | controller as a DT device. | 53 | controller as a DT device. |
| 61 | 54 | ||
| 62 | config MTD_NAND_GPIO | ||
| 63 | tristate "GPIO assisted NAND Flash driver" | ||
| 64 | depends on GPIOLIB || COMPILE_TEST | ||
| 65 | depends on HAS_IOMEM | ||
| 66 | help | ||
| 67 | This enables a NAND flash driver where control signals are | ||
| 68 | connected to GPIO pins, and commands and data are communicated | ||
| 69 | via a memory mapped interface. | ||
| 70 | |||
| 71 | config MTD_NAND_AMS_DELTA | 55 | config MTD_NAND_AMS_DELTA |
| 72 | tristate "NAND Flash device on Amstrad E3" | 56 | tristate "Amstrad E3 NAND controller" |
| 73 | depends on MACH_AMS_DELTA || COMPILE_TEST | 57 | depends on MACH_AMS_DELTA || COMPILE_TEST |
| 74 | default y | 58 | default y |
| 75 | help | 59 | help |
| 76 | Support for NAND flash on Amstrad E3 (Delta). | 60 | Support for NAND flash on Amstrad E3 (Delta). |
| 77 | 61 | ||
| 78 | config MTD_NAND_OMAP2 | 62 | config MTD_NAND_OMAP2 |
| 79 | tristate "NAND Flash device on OMAP2, OMAP3, OMAP4 and Keystone" | 63 | tristate "OMAP2, OMAP3, OMAP4 and Keystone NAND controller" |
| 80 | depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || COMPILE_TEST | 64 | depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || COMPILE_TEST |
| 81 | depends on HAS_IOMEM | 65 | depends on HAS_IOMEM |
| 82 | help | 66 | help |
| @@ -98,18 +82,6 @@ config MTD_NAND_OMAP_BCH | |||
| 98 | config MTD_NAND_OMAP_BCH_BUILD | 82 | config MTD_NAND_OMAP_BCH_BUILD |
| 99 | def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH | 83 | def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH |
| 100 | 84 | ||
| 101 | config MTD_NAND_RICOH | ||
| 102 | tristate "Ricoh xD card reader" | ||
| 103 | default n | ||
| 104 | depends on PCI | ||
| 105 | select MTD_SM_COMMON | ||
| 106 | help | ||
| 107 | Enable support for Ricoh R5C852 xD card reader | ||
| 108 | You also need to enable ether | ||
| 109 | NAND SSFDC (SmartMedia) read only translation layer' or new | ||
| 110 | expermental, readwrite | ||
| 111 | 'SmartMedia/xD new translation layer' | ||
| 112 | |||
| 113 | config MTD_NAND_AU1550 | 85 | config MTD_NAND_AU1550 |
| 114 | tristate "Au1550/1200 NAND support" | 86 | tristate "Au1550/1200 NAND support" |
| 115 | depends on MIPS_ALCHEMY | 87 | depends on MIPS_ALCHEMY |
| @@ -117,8 +89,15 @@ config MTD_NAND_AU1550 | |||
| 117 | This enables the driver for the NAND flash controller on the | 89 | This enables the driver for the NAND flash controller on the |
| 118 | AMD/Alchemy 1550 SOC. | 90 | AMD/Alchemy 1550 SOC. |
| 119 | 91 | ||
| 92 | config MTD_NAND_NDFC | ||
| 93 | tristate "IBM/MCC 4xx NAND controller" | ||
| 94 | depends on 4xx | ||
| 95 | select MTD_NAND_ECC_SW_HAMMING_SMC | ||
| 96 | help | ||
| 97 | NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs | ||
| 98 | |||
| 120 | config MTD_NAND_S3C2410 | 99 | config MTD_NAND_S3C2410 |
| 121 | tristate "NAND Flash support for Samsung S3C SoCs" | 100 | tristate "Samsung S3C NAND controller" |
| 122 | depends on ARCH_S3C24XX || ARCH_S3C64XX | 101 | depends on ARCH_S3C24XX || ARCH_S3C64XX |
| 123 | help | 102 | help |
| 124 | This enables the NAND flash controller on the S3C24xx and S3C64xx | 103 | This enables the NAND flash controller on the S3C24xx and S3C64xx |
| @@ -128,18 +107,11 @@ config MTD_NAND_S3C2410 | |||
| 128 | must advertise a platform_device for the driver to attach. | 107 | must advertise a platform_device for the driver to attach. |
| 129 | 108 | ||
| 130 | config MTD_NAND_S3C2410_DEBUG | 109 | config MTD_NAND_S3C2410_DEBUG |
| 131 | bool "Samsung S3C NAND driver debug" | 110 | bool "Samsung S3C NAND controller debug" |
| 132 | depends on MTD_NAND_S3C2410 | 111 | depends on MTD_NAND_S3C2410 |
| 133 | help | 112 | help |
| 134 | Enable debugging of the S3C NAND driver | 113 | Enable debugging of the S3C NAND driver |
| 135 | 114 | ||
| 136 | config MTD_NAND_NDFC | ||
| 137 | tristate "NDFC NanD Flash Controller" | ||
| 138 | depends on 4xx | ||
| 139 | select MTD_NAND_ECC_SMC | ||
| 140 | help | ||
| 141 | NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs | ||
| 142 | |||
| 143 | config MTD_NAND_S3C2410_CLKSTOP | 115 | config MTD_NAND_S3C2410_CLKSTOP |
| 144 | bool "Samsung S3C NAND IDLE clock stop" | 116 | bool "Samsung S3C NAND IDLE clock stop" |
| 145 | depends on MTD_NAND_S3C2410 | 117 | depends on MTD_NAND_S3C2410 |
| @@ -151,89 +123,19 @@ config MTD_NAND_S3C2410_CLKSTOP | |||
| 151 | approximately 5mA of power when there is nothing happening. | 123 | approximately 5mA of power when there is nothing happening. |
| 152 | 124 | ||
| 153 | config MTD_NAND_TANGO | 125 | config MTD_NAND_TANGO |
| 154 | tristate "NAND Flash support for Tango chips" | 126 | tristate "Tango NAND controller" |
| 155 | depends on ARCH_TANGO || COMPILE_TEST | 127 | depends on ARCH_TANGO || COMPILE_TEST |
| 156 | depends on HAS_IOMEM | 128 | depends on HAS_IOMEM |
| 157 | help | 129 | help |
| 158 | Enables the NAND Flash controller on Tango chips. | 130 | Enables the NAND Flash controller on Tango chips. |
| 159 | 131 | ||
| 160 | config MTD_NAND_DISKONCHIP | ||
| 161 | tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation)" | ||
| 162 | depends on HAS_IOMEM | ||
| 163 | select REED_SOLOMON | ||
| 164 | select REED_SOLOMON_DEC16 | ||
| 165 | help | ||
| 166 | This is a reimplementation of M-Systems DiskOnChip 2000, | ||
| 167 | Millennium and Millennium Plus as a standard NAND device driver, | ||
| 168 | as opposed to the earlier self-contained MTD device drivers. | ||
| 169 | This should enable, among other things, proper JFFS2 operation on | ||
| 170 | these devices. | ||
| 171 | |||
| 172 | config MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
| 173 | bool "Advanced detection options for DiskOnChip" | ||
| 174 | depends on MTD_NAND_DISKONCHIP | ||
| 175 | help | ||
| 176 | This option allows you to specify nonstandard address at which to | ||
| 177 | probe for a DiskOnChip, or to change the detection options. You | ||
| 178 | are unlikely to need any of this unless you are using LinuxBIOS. | ||
| 179 | Say 'N'. | ||
| 180 | |||
| 181 | config MTD_NAND_DISKONCHIP_PROBE_ADDRESS | ||
| 182 | hex "Physical address of DiskOnChip" if MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
| 183 | depends on MTD_NAND_DISKONCHIP | ||
| 184 | default "0" | ||
| 185 | help | ||
| 186 | By default, the probe for DiskOnChip devices will look for a | ||
| 187 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | ||
| 188 | This option allows you to specify a single address at which to probe | ||
| 189 | for the device, which is useful if you have other devices in that | ||
| 190 | range which get upset when they are probed. | ||
| 191 | |||
| 192 | (Note that on PowerPC, the normal probe will only check at | ||
| 193 | 0xE4000000.) | ||
| 194 | |||
| 195 | Normally, you should leave this set to zero, to allow the probe at | ||
| 196 | the normal addresses. | ||
| 197 | |||
| 198 | config MTD_NAND_DISKONCHIP_PROBE_HIGH | ||
| 199 | bool "Probe high addresses" | ||
| 200 | depends on MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
| 201 | help | ||
| 202 | By default, the probe for DiskOnChip devices will look for a | ||
| 203 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | ||
| 204 | This option changes to make it probe between 0xFFFC8000 and | ||
| 205 | 0xFFFEE000. Unless you are using LinuxBIOS, this is unlikely to be | ||
| 206 | useful to you. Say 'N'. | ||
| 207 | |||
| 208 | config MTD_NAND_DISKONCHIP_BBTWRITE | ||
| 209 | bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP" | ||
| 210 | depends on MTD_NAND_DISKONCHIP | ||
| 211 | help | ||
| 212 | On DiskOnChip devices shipped with the INFTL filesystem (Millennium | ||
| 213 | and 2000 TSOP/Alon), Linux reserves some space at the end of the | ||
| 214 | device for the Bad Block Table (BBT). If you have existing INFTL | ||
| 215 | data on your device (created by non-Linux tools such as M-Systems' | ||
| 216 | DOS drivers), your data might overlap the area Linux wants to use for | ||
| 217 | the BBT. If this is a concern for you, leave this option disabled and | ||
| 218 | Linux will not write BBT data into this area. | ||
| 219 | The downside of leaving this option disabled is that if bad blocks | ||
| 220 | are detected by Linux, they will not be recorded in the BBT, which | ||
| 221 | could cause future problems. | ||
| 222 | Once you enable this option, new filesystems (INFTL or others, created | ||
| 223 | in Linux or other operating systems) will not use the reserved area. | ||
| 224 | The only reason not to enable this option is to prevent damage to | ||
| 225 | preexisting filesystems. | ||
| 226 | Even if you leave this disabled, you can enable BBT writes at module | ||
| 227 | load time (assuming you build diskonchip as a module) with the module | ||
| 228 | parameter "inftl_bbt_write=1". | ||
| 229 | |||
| 230 | config MTD_NAND_SHARPSL | 132 | config MTD_NAND_SHARPSL |
| 231 | tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" | 133 | tristate "Sharp SL Series (C7xx + others) NAND controller" |
| 232 | depends on ARCH_PXA || COMPILE_TEST | 134 | depends on ARCH_PXA || COMPILE_TEST |
| 233 | depends on HAS_IOMEM | 135 | depends on HAS_IOMEM |
| 234 | 136 | ||
| 235 | config MTD_NAND_CAFE | 137 | config MTD_NAND_CAFE |
| 236 | tristate "NAND support for OLPC CAFÉ chip" | 138 | tristate "OLPC CAFÉ NAND controller" |
| 237 | depends on PCI | 139 | depends on PCI |
| 238 | select REED_SOLOMON | 140 | select REED_SOLOMON |
| 239 | select REED_SOLOMON_DEC16 | 141 | select REED_SOLOMON_DEC16 |
| @@ -242,7 +144,7 @@ config MTD_NAND_CAFE | |||
| 242 | laptop. | 144 | laptop. |
| 243 | 145 | ||
| 244 | config MTD_NAND_CS553X | 146 | config MTD_NAND_CS553X |
| 245 | tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" | 147 | tristate "CS5535/CS5536 (AMD Geode companion) NAND controller" |
| 246 | depends on X86_32 | 148 | depends on X86_32 |
| 247 | depends on !UML && HAS_IOMEM | 149 | depends on !UML && HAS_IOMEM |
| 248 | help | 150 | help |
| @@ -256,7 +158,7 @@ config MTD_NAND_CS553X | |||
| 256 | If you say "m", the module will be called cs553x_nand. | 158 | If you say "m", the module will be called cs553x_nand. |
| 257 | 159 | ||
| 258 | config MTD_NAND_ATMEL | 160 | config MTD_NAND_ATMEL |
| 259 | tristate "Support for NAND Flash / SmartMedia on AT91" | 161 | tristate "Atmel AT91 NAND Flash/SmartMedia NAND controller" |
| 260 | depends on ARCH_AT91 || COMPILE_TEST | 162 | depends on ARCH_AT91 || COMPILE_TEST |
| 261 | depends on HAS_IOMEM | 163 | depends on HAS_IOMEM |
| 262 | select GENERIC_ALLOCATOR | 164 | select GENERIC_ALLOCATOR |
| @@ -265,8 +167,17 @@ config MTD_NAND_ATMEL | |||
| 265 | Enables support for NAND Flash / Smart Media Card interface | 167 | Enables support for NAND Flash / Smart Media Card interface |
| 266 | on Atmel AT91 processors. | 168 | on Atmel AT91 processors. |
| 267 | 169 | ||
| 170 | config MTD_NAND_ORION | ||
| 171 | tristate "Marvell Orion NAND controller" | ||
| 172 | depends on PLAT_ORION | ||
| 173 | help | ||
| 174 | This enables the NAND flash controller on Orion machines. | ||
| 175 | |||
| 176 | No board specific support is done by this driver, each board | ||
| 177 | must advertise a platform_device for the driver to attach. | ||
| 178 | |||
| 268 | config MTD_NAND_MARVELL | 179 | config MTD_NAND_MARVELL |
| 269 | tristate "NAND controller support on Marvell boards" | 180 | tristate "Marvell EBU NAND controller" |
| 270 | depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU || \ | 181 | depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU || \ |
| 271 | COMPILE_TEST | 182 | COMPILE_TEST |
| 272 | depends on HAS_IOMEM | 183 | depends on HAS_IOMEM |
| @@ -278,7 +189,7 @@ config MTD_NAND_MARVELL | |||
| 278 | - 64-bit Aramda platforms (7k, 8k) (NFCv2) | 189 | - 64-bit Aramda platforms (7k, 8k) (NFCv2) |
| 279 | 190 | ||
| 280 | config MTD_NAND_SLC_LPC32XX | 191 | config MTD_NAND_SLC_LPC32XX |
| 281 | tristate "NXP LPC32xx SLC Controller" | 192 | tristate "NXP LPC32xx SLC NAND controller" |
| 282 | depends on ARCH_LPC32XX || COMPILE_TEST | 193 | depends on ARCH_LPC32XX || COMPILE_TEST |
| 283 | depends on HAS_IOMEM | 194 | depends on HAS_IOMEM |
| 284 | help | 195 | help |
| @@ -290,7 +201,7 @@ config MTD_NAND_SLC_LPC32XX | |||
| 290 | by the SLC NAND controller. | 201 | by the SLC NAND controller. |
| 291 | 202 | ||
| 292 | config MTD_NAND_MLC_LPC32XX | 203 | config MTD_NAND_MLC_LPC32XX |
| 293 | tristate "NXP LPC32xx MLC Controller" | 204 | tristate "NXP LPC32xx MLC NAND controller" |
| 294 | depends on ARCH_LPC32XX || COMPILE_TEST | 205 | depends on ARCH_LPC32XX || COMPILE_TEST |
| 295 | depends on HAS_IOMEM | 206 | depends on HAS_IOMEM |
| 296 | help | 207 | help |
| @@ -302,38 +213,23 @@ config MTD_NAND_MLC_LPC32XX | |||
| 302 | by the MLC NAND controller. | 213 | by the MLC NAND controller. |
| 303 | 214 | ||
| 304 | config MTD_NAND_CM_X270 | 215 | config MTD_NAND_CM_X270 |
| 305 | tristate "Support for NAND Flash on CM-X270 modules" | 216 | tristate "CM-X270 modules NAND controller" |
| 306 | depends on MACH_ARMCORE | 217 | depends on MACH_ARMCORE |
| 307 | 218 | ||
| 308 | config MTD_NAND_PASEMI | 219 | config MTD_NAND_PASEMI |
| 309 | tristate "NAND support for PA Semi PWRficient" | 220 | tristate "PA Semi PWRficient NAND controller" |
| 310 | depends on PPC_PASEMI | 221 | depends on PPC_PASEMI |
| 311 | help | 222 | help |
| 312 | Enables support for NAND Flash interface on PA Semi PWRficient | 223 | Enables support for NAND Flash interface on PA Semi PWRficient |
| 313 | based boards | 224 | based boards |
| 314 | 225 | ||
| 315 | config MTD_NAND_TMIO | 226 | config MTD_NAND_TMIO |
| 316 | tristate "NAND Flash device on Toshiba Mobile IO Controller" | 227 | tristate "Toshiba Mobile IO NAND controller" |
| 317 | depends on MFD_TMIO | 228 | depends on MFD_TMIO |
| 318 | help | 229 | help |
| 319 | Support for NAND flash connected to a Toshiba Mobile IO | 230 | Support for NAND flash connected to a Toshiba Mobile IO |
| 320 | Controller in some PDAs, including the Sharp SL6000x. | 231 | Controller in some PDAs, including the Sharp SL6000x. |
| 321 | 232 | ||
| 322 | config MTD_NAND_NANDSIM | ||
| 323 | tristate "Support for NAND Flash Simulator" | ||
| 324 | help | ||
| 325 | The simulator may simulate various NAND flash chips for the | ||
| 326 | MTD nand layer. | ||
| 327 | |||
| 328 | config MTD_NAND_GPMI_NAND | ||
| 329 | tristate "GPMI NAND Flash Controller driver" | ||
| 330 | depends on MXS_DMA | ||
| 331 | help | ||
| 332 | Enables NAND Flash support for IMX23, IMX28 or IMX6. | ||
| 333 | The GPMI controller is very powerful, with the help of BCH | ||
| 334 | module, it can do the hardware ECC. The GPMI supports several | ||
| 335 | NAND flashs at the same time. | ||
| 336 | |||
| 337 | config MTD_NAND_BRCMNAND | 233 | config MTD_NAND_BRCMNAND |
| 338 | tristate "Broadcom STB NAND controller" | 234 | tristate "Broadcom STB NAND controller" |
| 339 | depends on ARM || ARM64 || MIPS || COMPILE_TEST | 235 | depends on ARM || ARM64 || MIPS || COMPILE_TEST |
| @@ -344,7 +240,7 @@ config MTD_NAND_BRCMNAND | |||
| 344 | BCM3xxx, BCM63xxx, iProc/Cygnus and more. | 240 | BCM3xxx, BCM63xxx, iProc/Cygnus and more. |
| 345 | 241 | ||
| 346 | config MTD_NAND_BCM47XXNFLASH | 242 | config MTD_NAND_BCM47XXNFLASH |
| 347 | tristate "Support for NAND flash on BCM4706 BCMA bus" | 243 | tristate "BCM4706 BCMA NAND controller" |
| 348 | depends on BCMA_NFLASH | 244 | depends on BCMA_NFLASH |
| 349 | depends on BCMA | 245 | depends on BCMA |
| 350 | help | 246 | help |
| @@ -352,32 +248,31 @@ config MTD_NAND_BCM47XXNFLASH | |||
| 352 | registered by bcma as platform devices. This enables driver for | 248 | registered by bcma as platform devices. This enables driver for |
| 353 | NAND flash memories. For now only BCM4706 is supported. | 249 | NAND flash memories. For now only BCM4706 is supported. |
| 354 | 250 | ||
| 355 | config MTD_NAND_PLATFORM | 251 | config MTD_NAND_OXNAS |
| 356 | tristate "Support for generic platform NAND driver" | 252 | tristate "Oxford Semiconductor NAND controller" |
| 253 | depends on ARCH_OXNAS || COMPILE_TEST | ||
| 357 | depends on HAS_IOMEM | 254 | depends on HAS_IOMEM |
| 358 | help | 255 | help |
| 359 | This implements a generic NAND driver for on-SOC platform | 256 | This enables the NAND flash controller on Oxford Semiconductor SoCs. |
| 360 | devices. You will need to provide platform-specific functions | ||
| 361 | via platform_data. | ||
| 362 | 257 | ||
| 363 | config MTD_NAND_ORION | 258 | config MTD_NAND_MPC5121_NFC |
| 364 | tristate "NAND Flash support for Marvell Orion SoC" | 259 | tristate "MPC5121 NAND controller" |
| 365 | depends on PLAT_ORION | 260 | depends on PPC_MPC512x |
| 366 | help | 261 | help |
| 367 | This enables the NAND flash controller on Orion machines. | 262 | This enables the driver for the NAND flash controller on the |
| 368 | 263 | MPC5121 SoC. | |
| 369 | No board specific support is done by this driver, each board | ||
| 370 | must advertise a platform_device for the driver to attach. | ||
| 371 | 264 | ||
| 372 | config MTD_NAND_OXNAS | 265 | config MTD_NAND_GPMI_NAND |
| 373 | tristate "NAND Flash support for Oxford Semiconductor SoC" | 266 | tristate "Freescale GPMI NAND controller" |
| 374 | depends on ARCH_OXNAS || COMPILE_TEST | 267 | depends on MXS_DMA |
| 375 | depends on HAS_IOMEM | ||
| 376 | help | 268 | help |
| 377 | This enables the NAND flash controller on Oxford Semiconductor SoCs. | 269 | Enables NAND Flash support for IMX23, IMX28 or IMX6. |
| 270 | The GPMI controller is very powerful, with the help of BCH | ||
| 271 | module, it can do the hardware ECC. The GPMI supports several | ||
| 272 | NAND flashs at the same time. | ||
| 378 | 273 | ||
| 379 | config MTD_NAND_FSL_ELBC | 274 | config MTD_NAND_FSL_ELBC |
| 380 | tristate "NAND support for Freescale eLBC controllers" | 275 | tristate "Freescale eLBC NAND controller" |
| 381 | depends on FSL_SOC | 276 | depends on FSL_SOC |
| 382 | select FSL_LBC | 277 | select FSL_LBC |
| 383 | help | 278 | help |
| @@ -387,7 +282,7 @@ config MTD_NAND_FSL_ELBC | |||
| 387 | external NAND devices. | 282 | external NAND devices. |
| 388 | 283 | ||
| 389 | config MTD_NAND_FSL_IFC | 284 | config MTD_NAND_FSL_IFC |
| 390 | tristate "NAND support for Freescale IFC controller" | 285 | tristate "Freescale IFC NAND controller" |
| 391 | depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST | 286 | depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST |
| 392 | depends on HAS_IOMEM | 287 | depends on HAS_IOMEM |
| 393 | select FSL_IFC | 288 | select FSL_IFC |
| @@ -399,22 +294,15 @@ config MTD_NAND_FSL_IFC | |||
| 399 | external NAND devices. | 294 | external NAND devices. |
| 400 | 295 | ||
| 401 | config MTD_NAND_FSL_UPM | 296 | config MTD_NAND_FSL_UPM |
| 402 | tristate "Support for NAND on Freescale UPM" | 297 | tristate "Freescale UPM NAND controller" |
| 403 | depends on PPC_83xx || PPC_85xx | 298 | depends on PPC_83xx || PPC_85xx |
| 404 | select FSL_LBC | 299 | select FSL_LBC |
| 405 | help | 300 | help |
| 406 | Enables support for NAND Flash chips wired onto Freescale PowerPC | 301 | Enables support for NAND Flash chips wired onto Freescale PowerPC |
| 407 | processor localbus with User-Programmable Machine support. | 302 | processor localbus with User-Programmable Machine support. |
| 408 | 303 | ||
| 409 | config MTD_NAND_MPC5121_NFC | ||
| 410 | tristate "MPC5121 built-in NAND Flash Controller support" | ||
| 411 | depends on PPC_MPC512x | ||
| 412 | help | ||
| 413 | This enables the driver for the NAND flash controller on the | ||
| 414 | MPC5121 SoC. | ||
| 415 | |||
| 416 | config MTD_NAND_VF610_NFC | 304 | config MTD_NAND_VF610_NFC |
| 417 | tristate "Support for Freescale NFC for VF610/MPC5125" | 305 | tristate "Freescale VF610/MPC5125 NAND controller" |
| 418 | depends on (SOC_VF610 || COMPILE_TEST) | 306 | depends on (SOC_VF610 || COMPILE_TEST) |
| 419 | depends on HAS_IOMEM | 307 | depends on HAS_IOMEM |
| 420 | help | 308 | help |
| @@ -426,7 +314,7 @@ config MTD_NAND_VF610_NFC | |||
| 426 | device tree. | 314 | device tree. |
| 427 | 315 | ||
| 428 | config MTD_NAND_MXC | 316 | config MTD_NAND_MXC |
| 429 | tristate "MXC NAND support" | 317 | tristate "Freescale MXC NAND controller" |
| 430 | depends on ARCH_MXC || COMPILE_TEST | 318 | depends on ARCH_MXC || COMPILE_TEST |
| 431 | depends on HAS_IOMEM | 319 | depends on HAS_IOMEM |
| 432 | help | 320 | help |
| @@ -434,7 +322,7 @@ config MTD_NAND_MXC | |||
| 434 | MXC processors. | 322 | MXC processors. |
| 435 | 323 | ||
| 436 | config MTD_NAND_SH_FLCTL | 324 | config MTD_NAND_SH_FLCTL |
| 437 | tristate "Support for NAND on Renesas SuperH FLCTL" | 325 | tristate "Renesas SuperH FLCTL NAND controller" |
| 438 | depends on SUPERH || COMPILE_TEST | 326 | depends on SUPERH || COMPILE_TEST |
| 439 | depends on HAS_IOMEM | 327 | depends on HAS_IOMEM |
| 440 | help | 328 | help |
| @@ -442,7 +330,7 @@ config MTD_NAND_SH_FLCTL | |||
| 442 | for NAND Flash using FLCTL. | 330 | for NAND Flash using FLCTL. |
| 443 | 331 | ||
| 444 | config MTD_NAND_DAVINCI | 332 | config MTD_NAND_DAVINCI |
| 445 | tristate "Support NAND on DaVinci/Keystone SoC" | 333 | tristate "DaVinci/Keystone NAND controller" |
| 446 | depends on ARCH_DAVINCI || (ARCH_KEYSTONE && TI_AEMIF) || COMPILE_TEST | 334 | depends on ARCH_DAVINCI || (ARCH_KEYSTONE && TI_AEMIF) || COMPILE_TEST |
| 447 | depends on HAS_IOMEM | 335 | depends on HAS_IOMEM |
| 448 | help | 336 | help |
| @@ -450,42 +338,30 @@ config MTD_NAND_DAVINCI | |||
| 450 | DaVinci/Keystone processors. | 338 | DaVinci/Keystone processors. |
| 451 | 339 | ||
| 452 | config MTD_NAND_TXX9NDFMC | 340 | config MTD_NAND_TXX9NDFMC |
| 453 | tristate "NAND Flash support for TXx9 SoC" | 341 | tristate "TXx9 NAND controller" |
| 454 | depends on SOC_TX4938 || SOC_TX4939 || COMPILE_TEST | 342 | depends on SOC_TX4938 || SOC_TX4939 || COMPILE_TEST |
| 455 | depends on HAS_IOMEM | 343 | depends on HAS_IOMEM |
| 456 | help | 344 | help |
| 457 | This enables the NAND flash controller on the TXx9 SoCs. | 345 | This enables the NAND flash controller on the TXx9 SoCs. |
| 458 | 346 | ||
| 459 | config MTD_NAND_SOCRATES | 347 | config MTD_NAND_SOCRATES |
| 460 | tristate "Support for NAND on Socrates board" | 348 | tristate "Socrates NAND controller" |
| 461 | depends on SOCRATES | 349 | depends on SOCRATES |
| 462 | help | 350 | help |
| 463 | Enables support for NAND Flash chips wired onto Socrates board. | 351 | Enables support for NAND Flash chips wired onto Socrates board. |
| 464 | 352 | ||
| 465 | config MTD_NAND_NUC900 | 353 | config MTD_NAND_NUC900 |
| 466 | tristate "Support for NAND on Nuvoton NUC9xx/w90p910 evaluation boards." | 354 | tristate "Nuvoton NUC9xx/w90p910 NAND controller" |
| 467 | depends on ARCH_W90X900 || COMPILE_TEST | 355 | depends on ARCH_W90X900 || COMPILE_TEST |
| 468 | depends on HAS_IOMEM | 356 | depends on HAS_IOMEM |
| 469 | help | 357 | help |
| 470 | This enables the driver for the NAND Flash on evaluation board based | 358 | This enables the driver for the NAND Flash on evaluation board based |
| 471 | on w90p910 / NUC9xx. | 359 | on w90p910 / NUC9xx. |
| 472 | 360 | ||
| 473 | config MTD_NAND_JZ4740 | 361 | source "drivers/mtd/nand/raw/ingenic/Kconfig" |
| 474 | tristate "Support for JZ4740 SoC NAND controller" | ||
| 475 | depends on MACH_JZ4740 || COMPILE_TEST | ||
| 476 | depends on HAS_IOMEM | ||
| 477 | help | ||
| 478 | Enables support for NAND Flash on JZ4740 SoC based boards. | ||
| 479 | |||
| 480 | config MTD_NAND_JZ4780 | ||
| 481 | tristate "Support for NAND on JZ4780 SoC" | ||
| 482 | depends on JZ4780_NEMC | ||
| 483 | help | ||
| 484 | Enables support for NAND Flash connected to the NEMC on JZ4780 SoC | ||
| 485 | based boards, using the BCH controller for hardware error correction. | ||
| 486 | 362 | ||
| 487 | config MTD_NAND_FSMC | 363 | config MTD_NAND_FSMC |
| 488 | tristate "Support for NAND on ST Micros FSMC" | 364 | tristate "ST Micros FSMC NAND controller" |
| 489 | depends on OF && HAS_IOMEM | 365 | depends on OF && HAS_IOMEM |
| 490 | depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300 || \ | 366 | depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300 || \ |
| 491 | COMPILE_TEST | 367 | COMPILE_TEST |
| @@ -494,28 +370,28 @@ config MTD_NAND_FSMC | |||
| 494 | Flexible Static Memory Controller (FSMC) | 370 | Flexible Static Memory Controller (FSMC) |
| 495 | 371 | ||
| 496 | config MTD_NAND_XWAY | 372 | config MTD_NAND_XWAY |
| 497 | bool "Support for NAND on Lantiq XWAY SoC" | 373 | bool "Lantiq XWAY NAND controller" |
| 498 | depends on LANTIQ && SOC_TYPE_XWAY | 374 | depends on LANTIQ && SOC_TYPE_XWAY |
| 499 | help | 375 | help |
| 500 | Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached | 376 | Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached |
| 501 | to the External Bus Unit (EBU). | 377 | to the External Bus Unit (EBU). |
| 502 | 378 | ||
| 503 | config MTD_NAND_SUNXI | 379 | config MTD_NAND_SUNXI |
| 504 | tristate "Support for NAND on Allwinner SoCs" | 380 | tristate "Allwinner NAND controller" |
| 505 | depends on ARCH_SUNXI || COMPILE_TEST | 381 | depends on ARCH_SUNXI || COMPILE_TEST |
| 506 | depends on HAS_IOMEM | 382 | depends on HAS_IOMEM |
| 507 | help | 383 | help |
| 508 | Enables support for NAND Flash chips on Allwinner SoCs. | 384 | Enables support for NAND Flash chips on Allwinner SoCs. |
| 509 | 385 | ||
| 510 | config MTD_NAND_HISI504 | 386 | config MTD_NAND_HISI504 |
| 511 | tristate "Support for NAND controller on Hisilicon SoC Hip04" | 387 | tristate "Hisilicon Hip04 NAND controller" |
| 512 | depends on ARCH_HISI || COMPILE_TEST | 388 | depends on ARCH_HISI || COMPILE_TEST |
| 513 | depends on HAS_IOMEM | 389 | depends on HAS_IOMEM |
| 514 | help | 390 | help |
| 515 | Enables support for NAND controller on Hisilicon SoC Hip04. | 391 | Enables support for NAND controller on Hisilicon SoC Hip04. |
| 516 | 392 | ||
| 517 | config MTD_NAND_QCOM | 393 | config MTD_NAND_QCOM |
| 518 | tristate "Support for NAND on QCOM SoCs" | 394 | tristate "QCOM NAND controller" |
| 519 | depends on ARCH_QCOM || COMPILE_TEST | 395 | depends on ARCH_QCOM || COMPILE_TEST |
| 520 | depends on HAS_IOMEM | 396 | depends on HAS_IOMEM |
| 521 | help | 397 | help |
| @@ -523,7 +399,7 @@ config MTD_NAND_QCOM | |||
| 523 | controller. This controller is found on IPQ806x SoC. | 399 | controller. This controller is found on IPQ806x SoC. |
| 524 | 400 | ||
| 525 | config MTD_NAND_MTK | 401 | config MTD_NAND_MTK |
| 526 | tristate "Support for NAND controller on MTK SoCs" | 402 | tristate "MTK NAND controller" |
| 527 | depends on ARCH_MEDIATEK || COMPILE_TEST | 403 | depends on ARCH_MEDIATEK || COMPILE_TEST |
| 528 | depends on HAS_IOMEM | 404 | depends on HAS_IOMEM |
| 529 | help | 405 | help |
| @@ -531,7 +407,7 @@ config MTD_NAND_MTK | |||
| 531 | This controller is found on mt27xx, mt81xx, mt65xx SoCs. | 407 | This controller is found on mt27xx, mt81xx, mt65xx SoCs. |
| 532 | 408 | ||
| 533 | config MTD_NAND_TEGRA | 409 | config MTD_NAND_TEGRA |
| 534 | tristate "Support for NAND controller on NVIDIA Tegra" | 410 | tristate "NVIDIA Tegra NAND controller" |
| 535 | depends on ARCH_TEGRA || COMPILE_TEST | 411 | depends on ARCH_TEGRA || COMPILE_TEST |
| 536 | depends on HAS_IOMEM | 412 | depends on HAS_IOMEM |
| 537 | help | 413 | help |
| @@ -558,4 +434,115 @@ config MTD_NAND_MESON | |||
| 558 | Enables support for NAND controller on Amlogic's Meson SoCs. | 434 | Enables support for NAND controller on Amlogic's Meson SoCs. |
| 559 | This controller is found on Meson SoCs. | 435 | This controller is found on Meson SoCs. |
| 560 | 436 | ||
| 561 | endif # MTD_NAND | 437 | config MTD_NAND_GPIO |
| 438 | tristate "GPIO assisted NAND controller" | ||
| 439 | depends on GPIOLIB || COMPILE_TEST | ||
| 440 | depends on HAS_IOMEM | ||
| 441 | help | ||
| 442 | This enables a NAND flash driver where control signals are | ||
| 443 | connected to GPIO pins, and commands and data are communicated | ||
| 444 | via a memory mapped interface. | ||
| 445 | |||
| 446 | config MTD_NAND_PLATFORM | ||
| 447 | tristate "Generic NAND controller" | ||
| 448 | depends on HAS_IOMEM | ||
| 449 | help | ||
| 450 | This implements a generic NAND driver for on-SOC platform | ||
| 451 | devices. You will need to provide platform-specific functions | ||
| 452 | via platform_data. | ||
| 453 | |||
| 454 | comment "Misc" | ||
| 455 | |||
| 456 | config MTD_SM_COMMON | ||
| 457 | tristate | ||
| 458 | default n | ||
| 459 | |||
| 460 | config MTD_NAND_NANDSIM | ||
| 461 | tristate "Support for NAND Flash Simulator" | ||
| 462 | help | ||
| 463 | The simulator may simulate various NAND flash chips for the | ||
| 464 | MTD nand layer. | ||
| 465 | |||
| 466 | config MTD_NAND_RICOH | ||
| 467 | tristate "Ricoh xD card reader" | ||
| 468 | default n | ||
| 469 | depends on PCI | ||
| 470 | select MTD_SM_COMMON | ||
| 471 | help | ||
| 472 | Enable support for Ricoh R5C852 xD card reader | ||
| 473 | You also need to enable ether | ||
| 474 | NAND SSFDC (SmartMedia) read only translation layer' or new | ||
| 475 | expermental, readwrite | ||
| 476 | 'SmartMedia/xD new translation layer' | ||
| 477 | |||
| 478 | config MTD_NAND_DISKONCHIP | ||
| 479 | tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation)" | ||
| 480 | depends on HAS_IOMEM | ||
| 481 | select REED_SOLOMON | ||
| 482 | select REED_SOLOMON_DEC16 | ||
| 483 | help | ||
| 484 | This is a reimplementation of M-Systems DiskOnChip 2000, | ||
| 485 | Millennium and Millennium Plus as a standard NAND device driver, | ||
| 486 | as opposed to the earlier self-contained MTD device drivers. | ||
| 487 | This should enable, among other things, proper JFFS2 operation on | ||
| 488 | these devices. | ||
| 489 | |||
| 490 | config MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
| 491 | bool "Advanced detection options for DiskOnChip" | ||
| 492 | depends on MTD_NAND_DISKONCHIP | ||
| 493 | help | ||
| 494 | This option allows you to specify nonstandard address at which to | ||
| 495 | probe for a DiskOnChip, or to change the detection options. You | ||
| 496 | are unlikely to need any of this unless you are using LinuxBIOS. | ||
| 497 | Say 'N'. | ||
| 498 | |||
| 499 | config MTD_NAND_DISKONCHIP_PROBE_ADDRESS | ||
| 500 | hex "Physical address of DiskOnChip" if MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
| 501 | depends on MTD_NAND_DISKONCHIP | ||
| 502 | default "0" | ||
| 503 | help | ||
| 504 | By default, the probe for DiskOnChip devices will look for a | ||
| 505 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | ||
| 506 | This option allows you to specify a single address at which to probe | ||
| 507 | for the device, which is useful if you have other devices in that | ||
| 508 | range which get upset when they are probed. | ||
| 509 | |||
| 510 | (Note that on PowerPC, the normal probe will only check at | ||
| 511 | 0xE4000000.) | ||
| 512 | |||
| 513 | Normally, you should leave this set to zero, to allow the probe at | ||
| 514 | the normal addresses. | ||
| 515 | |||
| 516 | config MTD_NAND_DISKONCHIP_PROBE_HIGH | ||
| 517 | bool "Probe high addresses" | ||
| 518 | depends on MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
| 519 | help | ||
| 520 | By default, the probe for DiskOnChip devices will look for a | ||
| 521 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | ||
| 522 | This option changes to make it probe between 0xFFFC8000 and | ||
| 523 | 0xFFFEE000. Unless you are using LinuxBIOS, this is unlikely to be | ||
| 524 | useful to you. Say 'N'. | ||
| 525 | |||
| 526 | config MTD_NAND_DISKONCHIP_BBTWRITE | ||
| 527 | bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP" | ||
| 528 | depends on MTD_NAND_DISKONCHIP | ||
| 529 | help | ||
| 530 | On DiskOnChip devices shipped with the INFTL filesystem (Millennium | ||
| 531 | and 2000 TSOP/Alon), Linux reserves some space at the end of the | ||
| 532 | device for the Bad Block Table (BBT). If you have existing INFTL | ||
| 533 | data on your device (created by non-Linux tools such as M-Systems' | ||
| 534 | DOS drivers), your data might overlap the area Linux wants to use for | ||
| 535 | the BBT. If this is a concern for you, leave this option disabled and | ||
| 536 | Linux will not write BBT data into this area. | ||
| 537 | The downside of leaving this option disabled is that if bad blocks | ||
| 538 | are detected by Linux, they will not be recorded in the BBT, which | ||
| 539 | could cause future problems. | ||
| 540 | Once you enable this option, new filesystems (INFTL or others, created | ||
| 541 | in Linux or other operating systems) will not use the reserved area. | ||
| 542 | The only reason not to enable this option is to prevent damage to | ||
| 543 | preexisting filesystems. | ||
| 544 | Even if you leave this disabled, you can enable BBT writes at module | ||
| 545 | load time (assuming you build diskonchip as a module) with the module | ||
| 546 | parameter "inftl_bbt_write=1". | ||
| 547 | |||
| 548 | endif # MTD_RAW_NAND | ||
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index 5a5a72f0793e..efaf5cd25edc 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | ||
| 3 | obj-$(CONFIG_MTD_NAND) += nand.o | 3 | obj-$(CONFIG_MTD_RAW_NAND) += nand.o |
| 4 | obj-$(CONFIG_MTD_NAND_ECC) += nand_ecc.o | 4 | obj-$(CONFIG_MTD_NAND_ECC_SW_HAMMING) += nand_ecc.o |
| 5 | obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o | 5 | nand-$(CONFIG_MTD_NAND_ECC_SW_BCH) += nand_bch.o |
| 6 | obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o | 6 | obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o |
| 7 | 7 | ||
| 8 | obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o | 8 | obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o |
| @@ -45,8 +45,7 @@ obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o | |||
| 45 | obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o | 45 | obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o |
| 46 | obj-$(CONFIG_MTD_NAND_VF610_NFC) += vf610_nfc.o | 46 | obj-$(CONFIG_MTD_NAND_VF610_NFC) += vf610_nfc.o |
| 47 | obj-$(CONFIG_MTD_NAND_RICOH) += r852.o | 47 | obj-$(CONFIG_MTD_NAND_RICOH) += r852.o |
| 48 | obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o | 48 | obj-y += ingenic/ |
| 49 | obj-$(CONFIG_MTD_NAND_JZ4780) += jz4780_nand.o jz4780_bch.o | ||
| 50 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ | 49 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ |
| 51 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o | 50 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o |
| 52 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ | 51 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ |
diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 5781fcf6b76c..8d6be90a6fe8 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Copyright 2017 ATMEL | 3 | * Copyright 2017 ATMEL |
| 3 | * Copyright 2017 Free Electrons | 4 | * Copyright 2017 Free Electrons |
| @@ -29,10 +30,6 @@ | |||
| 29 | * Add Nand Flash Controller support for SAMA5 SoC | 30 | * Add Nand Flash Controller support for SAMA5 SoC |
| 30 | * Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com) | 31 | * Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com) |
| 31 | * | 32 | * |
| 32 | * This program is free software; you can redistribute it and/or modify | ||
| 33 | * it under the terms of the GNU General Public License version 2 as | ||
| 34 | * published by the Free Software Foundation. | ||
| 35 | * | ||
| 36 | * A few words about the naming convention in this file. This convention | 33 | * A few words about the naming convention in this file. This convention |
| 37 | * applies to structure and function names. | 34 | * applies to structure and function names. |
| 38 | * | 35 | * |
| @@ -65,6 +62,7 @@ | |||
| 65 | #include <linux/iopoll.h> | 62 | #include <linux/iopoll.h> |
| 66 | #include <linux/platform_device.h> | 63 | #include <linux/platform_device.h> |
| 67 | #include <linux/regmap.h> | 64 | #include <linux/regmap.h> |
| 65 | #include <soc/at91/atmel-sfr.h> | ||
| 68 | 66 | ||
| 69 | #include "pmecc.h" | 67 | #include "pmecc.h" |
| 70 | 68 | ||
| @@ -211,6 +209,7 @@ struct atmel_nand_controller_caps { | |||
| 211 | bool legacy_of_bindings; | 209 | bool legacy_of_bindings; |
| 212 | u32 ale_offs; | 210 | u32 ale_offs; |
| 213 | u32 cle_offs; | 211 | u32 cle_offs; |
| 212 | const char *ebi_csa_regmap_name; | ||
| 214 | const struct atmel_nand_controller_ops *ops; | 213 | const struct atmel_nand_controller_ops *ops; |
| 215 | }; | 214 | }; |
| 216 | 215 | ||
| @@ -231,10 +230,15 @@ to_nand_controller(struct nand_controller *ctl) | |||
| 231 | return container_of(ctl, struct atmel_nand_controller, base); | 230 | return container_of(ctl, struct atmel_nand_controller, base); |
| 232 | } | 231 | } |
| 233 | 232 | ||
| 233 | struct atmel_smc_nand_ebi_csa_cfg { | ||
| 234 | u32 offs; | ||
| 235 | u32 nfd0_on_d16; | ||
| 236 | }; | ||
| 237 | |||
| 234 | struct atmel_smc_nand_controller { | 238 | struct atmel_smc_nand_controller { |
| 235 | struct atmel_nand_controller base; | 239 | struct atmel_nand_controller base; |
| 236 | struct regmap *matrix; | 240 | struct regmap *ebi_csa_regmap; |
| 237 | unsigned int ebi_csa_offs; | 241 | struct atmel_smc_nand_ebi_csa_cfg *ebi_csa; |
| 238 | }; | 242 | }; |
| 239 | 243 | ||
| 240 | static inline struct atmel_smc_nand_controller * | 244 | static inline struct atmel_smc_nand_controller * |
| @@ -1068,15 +1072,15 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip) | |||
| 1068 | req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; | 1072 | req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; |
| 1069 | else if (chip->ecc.strength) | 1073 | else if (chip->ecc.strength) |
| 1070 | req.ecc.strength = chip->ecc.strength; | 1074 | req.ecc.strength = chip->ecc.strength; |
| 1071 | else if (chip->ecc_strength_ds) | 1075 | else if (chip->base.eccreq.strength) |
| 1072 | req.ecc.strength = chip->ecc_strength_ds; | 1076 | req.ecc.strength = chip->base.eccreq.strength; |
| 1073 | else | 1077 | else |
| 1074 | req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; | 1078 | req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH; |
| 1075 | 1079 | ||
| 1076 | if (chip->ecc.size) | 1080 | if (chip->ecc.size) |
| 1077 | req.ecc.sectorsize = chip->ecc.size; | 1081 | req.ecc.sectorsize = chip->ecc.size; |
| 1078 | else if (chip->ecc_step_ds) | 1082 | else if (chip->base.eccreq.step_size) |
| 1079 | req.ecc.sectorsize = chip->ecc_step_ds; | 1083 | req.ecc.sectorsize = chip->base.eccreq.step_size; |
| 1080 | else | 1084 | else |
| 1081 | req.ecc.sectorsize = ATMEL_PMECC_SECTOR_SIZE_AUTO; | 1085 | req.ecc.sectorsize = ATMEL_PMECC_SECTOR_SIZE_AUTO; |
| 1082 | 1086 | ||
| @@ -1507,13 +1511,20 @@ static void atmel_smc_nand_init(struct atmel_nand_controller *nc, | |||
| 1507 | atmel_nand_init(nc, nand); | 1511 | atmel_nand_init(nc, nand); |
| 1508 | 1512 | ||
| 1509 | smc_nc = to_smc_nand_controller(chip->controller); | 1513 | smc_nc = to_smc_nand_controller(chip->controller); |
| 1510 | if (!smc_nc->matrix) | 1514 | if (!smc_nc->ebi_csa_regmap) |
| 1511 | return; | 1515 | return; |
| 1512 | 1516 | ||
| 1513 | /* Attach the CS to the NAND Flash logic. */ | 1517 | /* Attach the CS to the NAND Flash logic. */ |
| 1514 | for (i = 0; i < nand->numcs; i++) | 1518 | for (i = 0; i < nand->numcs; i++) |
| 1515 | regmap_update_bits(smc_nc->matrix, smc_nc->ebi_csa_offs, | 1519 | regmap_update_bits(smc_nc->ebi_csa_regmap, |
| 1520 | smc_nc->ebi_csa->offs, | ||
| 1516 | BIT(nand->cs[i].id), BIT(nand->cs[i].id)); | 1521 | BIT(nand->cs[i].id), BIT(nand->cs[i].id)); |
| 1522 | |||
| 1523 | if (smc_nc->ebi_csa->nfd0_on_d16) | ||
| 1524 | regmap_update_bits(smc_nc->ebi_csa_regmap, | ||
| 1525 | smc_nc->ebi_csa->offs, | ||
| 1526 | smc_nc->ebi_csa->nfd0_on_d16, | ||
| 1527 | smc_nc->ebi_csa->nfd0_on_d16); | ||
| 1517 | } | 1528 | } |
| 1518 | 1529 | ||
| 1519 | static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc, | 1530 | static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc, |
| @@ -1797,7 +1808,7 @@ static int atmel_nand_controller_add_nands(struct atmel_nand_controller *nc) | |||
| 1797 | 1808 | ||
| 1798 | ret = of_property_read_u32(np, "#size-cells", &val); | 1809 | ret = of_property_read_u32(np, "#size-cells", &val); |
| 1799 | if (ret) { | 1810 | if (ret) { |
| 1800 | dev_err(dev, "missing #address-cells property\n"); | 1811 | dev_err(dev, "missing #size-cells property\n"); |
| 1801 | return ret; | 1812 | return ret; |
| 1802 | } | 1813 | } |
| 1803 | 1814 | ||
| @@ -1833,34 +1844,71 @@ static void atmel_nand_controller_cleanup(struct atmel_nand_controller *nc) | |||
| 1833 | clk_put(nc->mck); | 1844 | clk_put(nc->mck); |
| 1834 | } | 1845 | } |
| 1835 | 1846 | ||
| 1836 | static const struct of_device_id atmel_matrix_of_ids[] = { | 1847 | static const struct atmel_smc_nand_ebi_csa_cfg at91sam9260_ebi_csa = { |
| 1848 | .offs = AT91SAM9260_MATRIX_EBICSA, | ||
| 1849 | }; | ||
| 1850 | |||
| 1851 | static const struct atmel_smc_nand_ebi_csa_cfg at91sam9261_ebi_csa = { | ||
| 1852 | .offs = AT91SAM9261_MATRIX_EBICSA, | ||
| 1853 | }; | ||
| 1854 | |||
| 1855 | static const struct atmel_smc_nand_ebi_csa_cfg at91sam9263_ebi_csa = { | ||
| 1856 | .offs = AT91SAM9263_MATRIX_EBI0CSA, | ||
| 1857 | }; | ||
| 1858 | |||
| 1859 | static const struct atmel_smc_nand_ebi_csa_cfg at91sam9rl_ebi_csa = { | ||
| 1860 | .offs = AT91SAM9RL_MATRIX_EBICSA, | ||
| 1861 | }; | ||
| 1862 | |||
| 1863 | static const struct atmel_smc_nand_ebi_csa_cfg at91sam9g45_ebi_csa = { | ||
| 1864 | .offs = AT91SAM9G45_MATRIX_EBICSA, | ||
| 1865 | }; | ||
| 1866 | |||
| 1867 | static const struct atmel_smc_nand_ebi_csa_cfg at91sam9n12_ebi_csa = { | ||
| 1868 | .offs = AT91SAM9N12_MATRIX_EBICSA, | ||
| 1869 | }; | ||
| 1870 | |||
| 1871 | static const struct atmel_smc_nand_ebi_csa_cfg at91sam9x5_ebi_csa = { | ||
| 1872 | .offs = AT91SAM9X5_MATRIX_EBICSA, | ||
| 1873 | }; | ||
| 1874 | |||
| 1875 | static const struct atmel_smc_nand_ebi_csa_cfg sam9x60_ebi_csa = { | ||
| 1876 | .offs = AT91_SFR_CCFG_EBICSA, | ||
| 1877 | .nfd0_on_d16 = AT91_SFR_CCFG_NFD0_ON_D16, | ||
| 1878 | }; | ||
| 1879 | |||
| 1880 | static const struct of_device_id atmel_ebi_csa_regmap_of_ids[] = { | ||
| 1837 | { | 1881 | { |
| 1838 | .compatible = "atmel,at91sam9260-matrix", | 1882 | .compatible = "atmel,at91sam9260-matrix", |
| 1839 | .data = (void *)AT91SAM9260_MATRIX_EBICSA, | 1883 | .data = &at91sam9260_ebi_csa, |
| 1840 | }, | 1884 | }, |
| 1841 | { | 1885 | { |
| 1842 | .compatible = "atmel,at91sam9261-matrix", | 1886 | .compatible = "atmel,at91sam9261-matrix", |
| 1843 | .data = (void *)AT91SAM9261_MATRIX_EBICSA, | 1887 | .data = &at91sam9261_ebi_csa, |
| 1844 | }, | 1888 | }, |
| 1845 | { | 1889 | { |
| 1846 | .compatible = "atmel,at91sam9263-matrix", | 1890 | .compatible = "atmel,at91sam9263-matrix", |
| 1847 | .data = (void *)AT91SAM9263_MATRIX_EBI0CSA, | 1891 | .data = &at91sam9263_ebi_csa, |
| 1848 | }, | 1892 | }, |
| 1849 | { | 1893 | { |
| 1850 | .compatible = "atmel,at91sam9rl-matrix", | 1894 | .compatible = "atmel,at91sam9rl-matrix", |
| 1851 | .data = (void *)AT91SAM9RL_MATRIX_EBICSA, | 1895 | .data = &at91sam9rl_ebi_csa, |
| 1852 | }, | 1896 | }, |
| 1853 | { | 1897 | { |
| 1854 | .compatible = "atmel,at91sam9g45-matrix", | 1898 | .compatible = "atmel,at91sam9g45-matrix", |
| 1855 | .data = (void *)AT91SAM9G45_MATRIX_EBICSA, | 1899 | .data = &at91sam9g45_ebi_csa, |
| 1856 | }, | 1900 | }, |
| 1857 | { | 1901 | { |
| 1858 | .compatible = "atmel,at91sam9n12-matrix", | 1902 | .compatible = "atmel,at91sam9n12-matrix", |
| 1859 | .data = (void *)AT91SAM9N12_MATRIX_EBICSA, | 1903 | .data = &at91sam9n12_ebi_csa, |
| 1860 | }, | 1904 | }, |
| 1861 | { | 1905 | { |
| 1862 | .compatible = "atmel,at91sam9x5-matrix", | 1906 | .compatible = "atmel,at91sam9x5-matrix", |
| 1863 | .data = (void *)AT91SAM9X5_MATRIX_EBICSA, | 1907 | .data = &at91sam9x5_ebi_csa, |
| 1908 | }, | ||
| 1909 | { | ||
| 1910 | .compatible = "microchip,sam9x60-sfr", | ||
| 1911 | .data = &sam9x60_ebi_csa, | ||
| 1864 | }, | 1912 | }, |
| 1865 | { /* sentinel */ }, | 1913 | { /* sentinel */ }, |
| 1866 | }; | 1914 | }; |
| @@ -1982,37 +2030,38 @@ atmel_smc_nand_controller_init(struct atmel_smc_nand_controller *nc) | |||
| 1982 | struct device_node *np; | 2030 | struct device_node *np; |
| 1983 | int ret; | 2031 | int ret; |
| 1984 | 2032 | ||
| 1985 | /* We do not retrieve the matrix syscon when parsing old DTs. */ | 2033 | /* We do not retrieve the EBICSA regmap when parsing old DTs. */ |
| 1986 | if (nc->base.caps->legacy_of_bindings) | 2034 | if (nc->base.caps->legacy_of_bindings) |
| 1987 | return 0; | 2035 | return 0; |
| 1988 | 2036 | ||
| 1989 | np = of_parse_phandle(dev->parent->of_node, "atmel,matrix", 0); | 2037 | np = of_parse_phandle(dev->parent->of_node, |
| 2038 | nc->base.caps->ebi_csa_regmap_name, 0); | ||
| 1990 | if (!np) | 2039 | if (!np) |
| 1991 | return 0; | 2040 | return 0; |
| 1992 | 2041 | ||
| 1993 | match = of_match_node(atmel_matrix_of_ids, np); | 2042 | match = of_match_node(atmel_ebi_csa_regmap_of_ids, np); |
| 1994 | if (!match) { | 2043 | if (!match) { |
| 1995 | of_node_put(np); | 2044 | of_node_put(np); |
| 1996 | return 0; | 2045 | return 0; |
| 1997 | } | 2046 | } |
| 1998 | 2047 | ||
| 1999 | nc->matrix = syscon_node_to_regmap(np); | 2048 | nc->ebi_csa_regmap = syscon_node_to_regmap(np); |
| 2000 | of_node_put(np); | 2049 | of_node_put(np); |
| 2001 | if (IS_ERR(nc->matrix)) { | 2050 | if (IS_ERR(nc->ebi_csa_regmap)) { |
| 2002 | ret = PTR_ERR(nc->matrix); | 2051 | ret = PTR_ERR(nc->ebi_csa_regmap); |
| 2003 | dev_err(dev, "Could not get Matrix regmap (err = %d)\n", ret); | 2052 | dev_err(dev, "Could not get EBICSA regmap (err = %d)\n", ret); |
| 2004 | return ret; | 2053 | return ret; |
| 2005 | } | 2054 | } |
| 2006 | 2055 | ||
| 2007 | nc->ebi_csa_offs = (uintptr_t)match->data; | 2056 | nc->ebi_csa = (struct atmel_smc_nand_ebi_csa_cfg *)match->data; |
| 2008 | 2057 | ||
| 2009 | /* | 2058 | /* |
| 2010 | * The at91sam9263 has 2 EBIs, if the NAND controller is under EBI1 | 2059 | * The at91sam9263 has 2 EBIs, if the NAND controller is under EBI1 |
| 2011 | * add 4 to ->ebi_csa_offs. | 2060 | * add 4 to ->ebi_csa->offs. |
| 2012 | */ | 2061 | */ |
| 2013 | if (of_device_is_compatible(dev->parent->of_node, | 2062 | if (of_device_is_compatible(dev->parent->of_node, |
| 2014 | "atmel,at91sam9263-ebi1")) | 2063 | "atmel,at91sam9263-ebi1")) |
| 2015 | nc->ebi_csa_offs += 4; | 2064 | nc->ebi_csa->offs += 4; |
| 2016 | 2065 | ||
| 2017 | return 0; | 2066 | return 0; |
| 2018 | } | 2067 | } |
| @@ -2341,6 +2390,7 @@ static const struct atmel_nand_controller_ops at91rm9200_nc_ops = { | |||
| 2341 | static const struct atmel_nand_controller_caps atmel_rm9200_nc_caps = { | 2390 | static const struct atmel_nand_controller_caps atmel_rm9200_nc_caps = { |
| 2342 | .ale_offs = BIT(21), | 2391 | .ale_offs = BIT(21), |
| 2343 | .cle_offs = BIT(22), | 2392 | .cle_offs = BIT(22), |
| 2393 | .ebi_csa_regmap_name = "atmel,matrix", | ||
| 2344 | .ops = &at91rm9200_nc_ops, | 2394 | .ops = &at91rm9200_nc_ops, |
| 2345 | }; | 2395 | }; |
| 2346 | 2396 | ||
| @@ -2355,12 +2405,14 @@ static const struct atmel_nand_controller_ops atmel_smc_nc_ops = { | |||
| 2355 | static const struct atmel_nand_controller_caps atmel_sam9260_nc_caps = { | 2405 | static const struct atmel_nand_controller_caps atmel_sam9260_nc_caps = { |
| 2356 | .ale_offs = BIT(21), | 2406 | .ale_offs = BIT(21), |
| 2357 | .cle_offs = BIT(22), | 2407 | .cle_offs = BIT(22), |
| 2408 | .ebi_csa_regmap_name = "atmel,matrix", | ||
| 2358 | .ops = &atmel_smc_nc_ops, | 2409 | .ops = &atmel_smc_nc_ops, |
| 2359 | }; | 2410 | }; |
| 2360 | 2411 | ||
| 2361 | static const struct atmel_nand_controller_caps atmel_sam9261_nc_caps = { | 2412 | static const struct atmel_nand_controller_caps atmel_sam9261_nc_caps = { |
| 2362 | .ale_offs = BIT(22), | 2413 | .ale_offs = BIT(22), |
| 2363 | .cle_offs = BIT(21), | 2414 | .cle_offs = BIT(21), |
| 2415 | .ebi_csa_regmap_name = "atmel,matrix", | ||
| 2364 | .ops = &atmel_smc_nc_ops, | 2416 | .ops = &atmel_smc_nc_ops, |
| 2365 | }; | 2417 | }; |
| 2366 | 2418 | ||
| @@ -2368,6 +2420,15 @@ static const struct atmel_nand_controller_caps atmel_sam9g45_nc_caps = { | |||
| 2368 | .has_dma = true, | 2420 | .has_dma = true, |
| 2369 | .ale_offs = BIT(21), | 2421 | .ale_offs = BIT(21), |
| 2370 | .cle_offs = BIT(22), | 2422 | .cle_offs = BIT(22), |
| 2423 | .ebi_csa_regmap_name = "atmel,matrix", | ||
| 2424 | .ops = &atmel_smc_nc_ops, | ||
| 2425 | }; | ||
| 2426 | |||
| 2427 | static const struct atmel_nand_controller_caps microchip_sam9x60_nc_caps = { | ||
| 2428 | .has_dma = true, | ||
| 2429 | .ale_offs = BIT(21), | ||
| 2430 | .cle_offs = BIT(22), | ||
| 2431 | .ebi_csa_regmap_name = "microchip,sfr", | ||
| 2371 | .ops = &atmel_smc_nc_ops, | 2432 | .ops = &atmel_smc_nc_ops, |
| 2372 | }; | 2433 | }; |
| 2373 | 2434 | ||
| @@ -2415,6 +2476,10 @@ static const struct of_device_id atmel_nand_controller_of_ids[] = { | |||
| 2415 | .compatible = "atmel,sama5d3-nand-controller", | 2476 | .compatible = "atmel,sama5d3-nand-controller", |
| 2416 | .data = &atmel_sama5_nc_caps, | 2477 | .data = &atmel_sama5_nc_caps, |
| 2417 | }, | 2478 | }, |
| 2479 | { | ||
| 2480 | .compatible = "microchip,sam9x60-nand-controller", | ||
| 2481 | .data = µchip_sam9x60_nc_caps, | ||
| 2482 | }, | ||
| 2418 | /* Support for old/deprecated bindings: */ | 2483 | /* Support for old/deprecated bindings: */ |
| 2419 | { | 2484 | { |
| 2420 | .compatible = "atmel,at91rm9200-nand", | 2485 | .compatible = "atmel,at91rm9200-nand", |
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c index 9d3997840889..cbb023bf00f7 100644 --- a/drivers/mtd/nand/raw/atmel/pmecc.c +++ b/drivers/mtd/nand/raw/atmel/pmecc.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Copyright 2017 ATMEL | 3 | * Copyright 2017 ATMEL |
| 3 | * Copyright 2017 Free Electrons | 4 | * Copyright 2017 Free Electrons |
| @@ -28,10 +29,6 @@ | |||
| 28 | * Add Nand Flash Controller support for SAMA5 SoC | 29 | * Add Nand Flash Controller support for SAMA5 SoC |
| 29 | * Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com) | 30 | * Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com) |
| 30 | * | 31 | * |
| 31 | * This program is free software; you can redistribute it and/or modify | ||
| 32 | * it under the terms of the GNU General Public License version 2 as | ||
| 33 | * published by the Free Software Foundation. | ||
| 34 | * | ||
| 35 | * The PMECC is an hardware assisted BCH engine, which means part of the | 32 | * The PMECC is an hardware assisted BCH engine, which means part of the |
| 36 | * ECC algorithm is left to the software. The hardware/software repartition | 33 | * ECC algorithm is left to the software. The hardware/software repartition |
| 37 | * is explained in the "PMECC Controller Functional Description" chapter in | 34 | * is explained in the "PMECC Controller Functional Description" chapter in |
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.h b/drivers/mtd/nand/raw/atmel/pmecc.h index 808f1be0d6ad..7851c05126cf 100644 --- a/drivers/mtd/nand/raw/atmel/pmecc.h +++ b/drivers/mtd/nand/raw/atmel/pmecc.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * © Copyright 2016 ATMEL | 3 | * © Copyright 2016 ATMEL |
| 3 | * © Copyright 2016 Free Electrons | 4 | * © Copyright 2016 Free Electrons |
| @@ -28,11 +29,6 @@ | |||
| 28 | * | 29 | * |
| 29 | * Add Nand Flash Controller support for SAMA5 SoC | 30 | * Add Nand Flash Controller support for SAMA5 SoC |
| 30 | * © Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com) | 31 | * © Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com) |
| 31 | * | ||
| 32 | * This program is free software; you can redistribute it and/or modify | ||
| 33 | * it under the terms of the GNU General Public License version 2 as | ||
| 34 | * published by the Free Software Foundation. | ||
| 35 | * | ||
| 36 | */ | 32 | */ |
| 37 | 33 | ||
| 38 | #ifndef ATMEL_PMECC_H | 34 | #ifndef ATMEL_PMECC_H |
diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index a37cbfe56567..a53ffb3d64b0 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | |||
| @@ -428,7 +428,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) | |||
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | /* Configure FLASH */ | 430 | /* Configure FLASH */ |
| 431 | chipsize = b47n->nand_chip.chipsize >> 20; | 431 | chipsize = nanddev_target_size(&b47n->nand_chip.base) >> 20; |
| 432 | tbits = ffs(chipsize); /* find first bit set */ | 432 | tbits = ffs(chipsize); /* find first bit set */ |
| 433 | if (!tbits || tbits != fls(chipsize)) { | 433 | if (!tbits || tbits != fls(chipsize)) { |
| 434 | pr_err("Invalid flash size: 0x%lX\n", chipsize); | 434 | pr_err("Invalid flash size: 0x%lX\n", chipsize); |
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 482c6f093f99..ce0b8ffc7812 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c | |||
| @@ -1676,11 +1676,8 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, | |||
| 1676 | int page = addr >> chip->page_shift; | 1676 | int page = addr >> chip->page_shift; |
| 1677 | int ret; | 1677 | int ret; |
| 1678 | 1678 | ||
| 1679 | if (!buf) { | 1679 | if (!buf) |
| 1680 | buf = chip->data_buf; | 1680 | buf = nand_get_data_buf(chip); |
| 1681 | /* Invalidate page cache */ | ||
| 1682 | chip->pagebuf = -1; | ||
| 1683 | } | ||
| 1684 | 1681 | ||
| 1685 | sas = mtd->oobsize / chip->ecc.steps; | 1682 | sas = mtd->oobsize / chip->ecc.steps; |
| 1686 | 1683 | ||
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 24aeafc67cd4..3102ddbd8abd 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * NAND Flash Controller Device Driver | 3 | * NAND Flash Controller Device Driver |
| 4 | * Copyright © 2009-2010, Intel Corporation and its suppliers. | 4 | * Copyright © 2009-2010, Intel Corporation and its suppliers. |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2017 Socionext Inc. | 6 | * Copyright (c) 2017-2019 Socionext Inc. |
| 7 | * Reworked by Masahiro Yamada <yamada.masahiro@socionext.com> | 7 | * Reworked by Masahiro Yamada <yamada.masahiro@socionext.com> |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| @@ -40,11 +40,16 @@ | |||
| 40 | #define DENALI_BANK(denali) ((denali)->active_bank << 24) | 40 | #define DENALI_BANK(denali) ((denali)->active_bank << 24) |
| 41 | 41 | ||
| 42 | #define DENALI_INVALID_BANK -1 | 42 | #define DENALI_INVALID_BANK -1 |
| 43 | #define DENALI_NR_BANKS 4 | ||
| 44 | 43 | ||
| 45 | static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) | 44 | static struct denali_chip *to_denali_chip(struct nand_chip *chip) |
| 46 | { | 45 | { |
| 47 | return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand); | 46 | return container_of(chip, struct denali_chip, chip); |
| 47 | } | ||
| 48 | |||
| 49 | static struct denali_controller *to_denali_controller(struct nand_chip *chip) | ||
| 50 | { | ||
| 51 | return container_of(chip->controller, struct denali_controller, | ||
| 52 | controller); | ||
| 48 | } | 53 | } |
| 49 | 54 | ||
| 50 | /* | 55 | /* |
| @@ -52,12 +57,12 @@ static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) | |||
| 52 | * type, bank, block, and page address). The slave data is the actual data to | 57 | * type, bank, block, and page address). The slave data is the actual data to |
| 53 | * be transferred. This mode requires 28 bits of address region allocated. | 58 | * be transferred. This mode requires 28 bits of address region allocated. |
| 54 | */ | 59 | */ |
| 55 | static u32 denali_direct_read(struct denali_nand_info *denali, u32 addr) | 60 | static u32 denali_direct_read(struct denali_controller *denali, u32 addr) |
| 56 | { | 61 | { |
| 57 | return ioread32(denali->host + addr); | 62 | return ioread32(denali->host + addr); |
| 58 | } | 63 | } |
| 59 | 64 | ||
| 60 | static void denali_direct_write(struct denali_nand_info *denali, u32 addr, | 65 | static void denali_direct_write(struct denali_controller *denali, u32 addr, |
| 61 | u32 data) | 66 | u32 data) |
| 62 | { | 67 | { |
| 63 | iowrite32(data, denali->host + addr); | 68 | iowrite32(data, denali->host + addr); |
| @@ -69,77 +74,62 @@ static void denali_direct_write(struct denali_nand_info *denali, u32 addr, | |||
| 69 | * control information and transferred data are latched by the registers in | 74 | * control information and transferred data are latched by the registers in |
| 70 | * the translation module. | 75 | * the translation module. |
| 71 | */ | 76 | */ |
| 72 | static u32 denali_indexed_read(struct denali_nand_info *denali, u32 addr) | 77 | static u32 denali_indexed_read(struct denali_controller *denali, u32 addr) |
| 73 | { | 78 | { |
| 74 | iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); | 79 | iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); |
| 75 | return ioread32(denali->host + DENALI_INDEXED_DATA); | 80 | return ioread32(denali->host + DENALI_INDEXED_DATA); |
| 76 | } | 81 | } |
| 77 | 82 | ||
| 78 | static void denali_indexed_write(struct denali_nand_info *denali, u32 addr, | 83 | static void denali_indexed_write(struct denali_controller *denali, u32 addr, |
| 79 | u32 data) | 84 | u32 data) |
| 80 | { | 85 | { |
| 81 | iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); | 86 | iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); |
| 82 | iowrite32(data, denali->host + DENALI_INDEXED_DATA); | 87 | iowrite32(data, denali->host + DENALI_INDEXED_DATA); |
| 83 | } | 88 | } |
| 84 | 89 | ||
| 85 | /* | 90 | static void denali_enable_irq(struct denali_controller *denali) |
| 86 | * Use the configuration feature register to determine the maximum number of | ||
| 87 | * banks that the hardware supports. | ||
| 88 | */ | ||
| 89 | static void denali_detect_max_banks(struct denali_nand_info *denali) | ||
| 90 | { | ||
| 91 | uint32_t features = ioread32(denali->reg + FEATURES); | ||
| 92 | |||
| 93 | denali->max_banks = 1 << FIELD_GET(FEATURES__N_BANKS, features); | ||
| 94 | |||
| 95 | /* the encoding changed from rev 5.0 to 5.1 */ | ||
| 96 | if (denali->revision < 0x0501) | ||
| 97 | denali->max_banks <<= 1; | ||
| 98 | } | ||
| 99 | |||
| 100 | static void denali_enable_irq(struct denali_nand_info *denali) | ||
| 101 | { | 91 | { |
| 102 | int i; | 92 | int i; |
| 103 | 93 | ||
| 104 | for (i = 0; i < DENALI_NR_BANKS; i++) | 94 | for (i = 0; i < denali->nbanks; i++) |
| 105 | iowrite32(U32_MAX, denali->reg + INTR_EN(i)); | 95 | iowrite32(U32_MAX, denali->reg + INTR_EN(i)); |
| 106 | iowrite32(GLOBAL_INT_EN_FLAG, denali->reg + GLOBAL_INT_ENABLE); | 96 | iowrite32(GLOBAL_INT_EN_FLAG, denali->reg + GLOBAL_INT_ENABLE); |
| 107 | } | 97 | } |
| 108 | 98 | ||
| 109 | static void denali_disable_irq(struct denali_nand_info *denali) | 99 | static void denali_disable_irq(struct denali_controller *denali) |
| 110 | { | 100 | { |
| 111 | int i; | 101 | int i; |
| 112 | 102 | ||
| 113 | for (i = 0; i < DENALI_NR_BANKS; i++) | 103 | for (i = 0; i < denali->nbanks; i++) |
| 114 | iowrite32(0, denali->reg + INTR_EN(i)); | 104 | iowrite32(0, denali->reg + INTR_EN(i)); |
| 115 | iowrite32(0, denali->reg + GLOBAL_INT_ENABLE); | 105 | iowrite32(0, denali->reg + GLOBAL_INT_ENABLE); |
| 116 | } | 106 | } |
| 117 | 107 | ||
| 118 | static void denali_clear_irq(struct denali_nand_info *denali, | 108 | static void denali_clear_irq(struct denali_controller *denali, |
| 119 | int bank, uint32_t irq_status) | 109 | int bank, u32 irq_status) |
| 120 | { | 110 | { |
| 121 | /* write one to clear bits */ | 111 | /* write one to clear bits */ |
| 122 | iowrite32(irq_status, denali->reg + INTR_STATUS(bank)); | 112 | iowrite32(irq_status, denali->reg + INTR_STATUS(bank)); |
| 123 | } | 113 | } |
| 124 | 114 | ||
| 125 | static void denali_clear_irq_all(struct denali_nand_info *denali) | 115 | static void denali_clear_irq_all(struct denali_controller *denali) |
| 126 | { | 116 | { |
| 127 | int i; | 117 | int i; |
| 128 | 118 | ||
| 129 | for (i = 0; i < DENALI_NR_BANKS; i++) | 119 | for (i = 0; i < denali->nbanks; i++) |
| 130 | denali_clear_irq(denali, i, U32_MAX); | 120 | denali_clear_irq(denali, i, U32_MAX); |
| 131 | } | 121 | } |
| 132 | 122 | ||
| 133 | static irqreturn_t denali_isr(int irq, void *dev_id) | 123 | static irqreturn_t denali_isr(int irq, void *dev_id) |
| 134 | { | 124 | { |
| 135 | struct denali_nand_info *denali = dev_id; | 125 | struct denali_controller *denali = dev_id; |
| 136 | irqreturn_t ret = IRQ_NONE; | 126 | irqreturn_t ret = IRQ_NONE; |
| 137 | uint32_t irq_status; | 127 | u32 irq_status; |
| 138 | int i; | 128 | int i; |
| 139 | 129 | ||
| 140 | spin_lock(&denali->irq_lock); | 130 | spin_lock(&denali->irq_lock); |
| 141 | 131 | ||
| 142 | for (i = 0; i < DENALI_NR_BANKS; i++) { | 132 | for (i = 0; i < denali->nbanks; i++) { |
| 143 | irq_status = ioread32(denali->reg + INTR_STATUS(i)); | 133 | irq_status = ioread32(denali->reg + INTR_STATUS(i)); |
| 144 | if (irq_status) | 134 | if (irq_status) |
| 145 | ret = IRQ_HANDLED; | 135 | ret = IRQ_HANDLED; |
| @@ -160,7 +150,7 @@ static irqreturn_t denali_isr(int irq, void *dev_id) | |||
| 160 | return ret; | 150 | return ret; |
| 161 | } | 151 | } |
| 162 | 152 | ||
| 163 | static void denali_reset_irq(struct denali_nand_info *denali) | 153 | static void denali_reset_irq(struct denali_controller *denali) |
| 164 | { | 154 | { |
| 165 | unsigned long flags; | 155 | unsigned long flags; |
| 166 | 156 | ||
| @@ -170,11 +160,10 @@ static void denali_reset_irq(struct denali_nand_info *denali) | |||
| 170 | spin_unlock_irqrestore(&denali->irq_lock, flags); | 160 | spin_unlock_irqrestore(&denali->irq_lock, flags); |
| 171 | } | 161 | } |
| 172 | 162 | ||
| 173 | static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, | 163 | static u32 denali_wait_for_irq(struct denali_controller *denali, u32 irq_mask) |
| 174 | uint32_t irq_mask) | ||
| 175 | { | 164 | { |
| 176 | unsigned long time_left, flags; | 165 | unsigned long time_left, flags; |
| 177 | uint32_t irq_status; | 166 | u32 irq_status; |
| 178 | 167 | ||
| 179 | spin_lock_irqsave(&denali->irq_lock, flags); | 168 | spin_lock_irqsave(&denali->irq_lock, flags); |
| 180 | 169 | ||
| @@ -201,128 +190,259 @@ static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, | |||
| 201 | return denali->irq_status; | 190 | return denali->irq_status; |
| 202 | } | 191 | } |
| 203 | 192 | ||
| 204 | static void denali_read_buf(struct nand_chip *chip, uint8_t *buf, int len) | 193 | static void denali_select_target(struct nand_chip *chip, int cs) |
| 205 | { | 194 | { |
| 195 | struct denali_controller *denali = to_denali_controller(chip); | ||
| 196 | struct denali_chip_sel *sel = &to_denali_chip(chip)->sels[cs]; | ||
| 206 | struct mtd_info *mtd = nand_to_mtd(chip); | 197 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 207 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 208 | u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); | ||
| 209 | int i; | ||
| 210 | 198 | ||
| 211 | for (i = 0; i < len; i++) | 199 | denali->active_bank = sel->bank; |
| 212 | buf[i] = denali->host_read(denali, addr); | 200 | |
| 201 | iowrite32(1 << (chip->phys_erase_shift - chip->page_shift), | ||
| 202 | denali->reg + PAGES_PER_BLOCK); | ||
| 203 | iowrite32(chip->options & NAND_BUSWIDTH_16 ? 1 : 0, | ||
| 204 | denali->reg + DEVICE_WIDTH); | ||
| 205 | iowrite32(mtd->writesize, denali->reg + DEVICE_MAIN_AREA_SIZE); | ||
| 206 | iowrite32(mtd->oobsize, denali->reg + DEVICE_SPARE_AREA_SIZE); | ||
| 207 | iowrite32(chip->options & NAND_ROW_ADDR_3 ? | ||
| 208 | 0 : TWO_ROW_ADDR_CYCLES__FLAG, | ||
| 209 | denali->reg + TWO_ROW_ADDR_CYCLES); | ||
| 210 | iowrite32(FIELD_PREP(ECC_CORRECTION__ERASE_THRESHOLD, 1) | | ||
| 211 | FIELD_PREP(ECC_CORRECTION__VALUE, chip->ecc.strength), | ||
| 212 | denali->reg + ECC_CORRECTION); | ||
| 213 | iowrite32(chip->ecc.size, denali->reg + CFG_DATA_BLOCK_SIZE); | ||
| 214 | iowrite32(chip->ecc.size, denali->reg + CFG_LAST_DATA_BLOCK_SIZE); | ||
| 215 | iowrite32(chip->ecc.steps, denali->reg + CFG_NUM_DATA_BLOCKS); | ||
| 216 | |||
| 217 | if (chip->options & NAND_KEEP_TIMINGS) | ||
| 218 | return; | ||
| 219 | |||
| 220 | /* update timing registers unless NAND_KEEP_TIMINGS is set */ | ||
| 221 | iowrite32(sel->hwhr2_and_we_2_re, denali->reg + TWHR2_AND_WE_2_RE); | ||
| 222 | iowrite32(sel->tcwaw_and_addr_2_data, | ||
| 223 | denali->reg + TCWAW_AND_ADDR_2_DATA); | ||
| 224 | iowrite32(sel->re_2_we, denali->reg + RE_2_WE); | ||
| 225 | iowrite32(sel->acc_clks, denali->reg + ACC_CLKS); | ||
| 226 | iowrite32(sel->rdwr_en_lo_cnt, denali->reg + RDWR_EN_LO_CNT); | ||
| 227 | iowrite32(sel->rdwr_en_hi_cnt, denali->reg + RDWR_EN_HI_CNT); | ||
| 228 | iowrite32(sel->cs_setup_cnt, denali->reg + CS_SETUP_CNT); | ||
| 229 | iowrite32(sel->re_2_re, denali->reg + RE_2_RE); | ||
| 213 | } | 230 | } |
| 214 | 231 | ||
| 215 | static void denali_write_buf(struct nand_chip *chip, const uint8_t *buf, | 232 | static int denali_change_column(struct nand_chip *chip, unsigned int offset, |
| 216 | int len) | 233 | void *buf, unsigned int len, bool write) |
| 217 | { | 234 | { |
| 218 | struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); | 235 | if (write) |
| 219 | u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); | 236 | return nand_change_write_column_op(chip, offset, buf, len, |
| 220 | int i; | 237 | false); |
| 221 | 238 | else | |
| 222 | for (i = 0; i < len; i++) | 239 | return nand_change_read_column_op(chip, offset, buf, len, |
| 223 | denali->host_write(denali, addr, buf[i]); | 240 | false); |
| 224 | } | 241 | } |
| 225 | 242 | ||
| 226 | static void denali_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) | 243 | static int denali_payload_xfer(struct nand_chip *chip, void *buf, bool write) |
| 227 | { | 244 | { |
| 228 | struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); | 245 | struct denali_controller *denali = to_denali_controller(chip); |
| 229 | u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); | 246 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 230 | uint16_t *buf16 = (uint16_t *)buf; | 247 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 231 | int i; | 248 | int writesize = mtd->writesize; |
| 249 | int oob_skip = denali->oob_skip_bytes; | ||
| 250 | int ret, i, pos, len; | ||
| 251 | |||
| 252 | for (i = 0; i < ecc->steps; i++) { | ||
| 253 | pos = i * (ecc->size + ecc->bytes); | ||
| 254 | len = ecc->size; | ||
| 255 | |||
| 256 | if (pos >= writesize) { | ||
| 257 | pos += oob_skip; | ||
| 258 | } else if (pos + len > writesize) { | ||
| 259 | /* This chunk overwraps the BBM area. Must be split */ | ||
| 260 | ret = denali_change_column(chip, pos, buf, | ||
| 261 | writesize - pos, write); | ||
| 262 | if (ret) | ||
| 263 | return ret; | ||
| 264 | |||
| 265 | buf += writesize - pos; | ||
| 266 | len -= writesize - pos; | ||
| 267 | pos = writesize + oob_skip; | ||
| 268 | } | ||
| 269 | |||
| 270 | ret = denali_change_column(chip, pos, buf, len, write); | ||
| 271 | if (ret) | ||
| 272 | return ret; | ||
| 232 | 273 | ||
| 233 | for (i = 0; i < len / 2; i++) | 274 | buf += len; |
| 234 | buf16[i] = denali->host_read(denali, addr); | 275 | } |
| 276 | |||
| 277 | return 0; | ||
| 235 | } | 278 | } |
| 236 | 279 | ||
| 237 | static void denali_write_buf16(struct nand_chip *chip, const uint8_t *buf, | 280 | static int denali_oob_xfer(struct nand_chip *chip, void *buf, bool write) |
| 238 | int len) | ||
| 239 | { | 281 | { |
| 240 | struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); | 282 | struct denali_controller *denali = to_denali_controller(chip); |
| 241 | u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); | 283 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 242 | const uint16_t *buf16 = (const uint16_t *)buf; | 284 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 243 | int i; | 285 | int writesize = mtd->writesize; |
| 286 | int oobsize = mtd->oobsize; | ||
| 287 | int oob_skip = denali->oob_skip_bytes; | ||
| 288 | int ret, i, pos, len; | ||
| 244 | 289 | ||
| 245 | for (i = 0; i < len / 2; i++) | 290 | /* BBM at the beginning of the OOB area */ |
| 246 | denali->host_write(denali, addr, buf16[i]); | 291 | ret = denali_change_column(chip, writesize, buf, oob_skip, write); |
| 292 | if (ret) | ||
| 293 | return ret; | ||
| 294 | |||
| 295 | buf += oob_skip; | ||
| 296 | |||
| 297 | for (i = 0; i < ecc->steps; i++) { | ||
| 298 | pos = ecc->size + i * (ecc->size + ecc->bytes); | ||
| 299 | |||
| 300 | if (i == ecc->steps - 1) | ||
| 301 | /* The last chunk includes OOB free */ | ||
| 302 | len = writesize + oobsize - pos - oob_skip; | ||
| 303 | else | ||
| 304 | len = ecc->bytes; | ||
| 305 | |||
| 306 | if (pos >= writesize) { | ||
| 307 | pos += oob_skip; | ||
| 308 | } else if (pos + len > writesize) { | ||
| 309 | /* This chunk overwraps the BBM area. Must be split */ | ||
| 310 | ret = denali_change_column(chip, pos, buf, | ||
| 311 | writesize - pos, write); | ||
| 312 | if (ret) | ||
| 313 | return ret; | ||
| 314 | |||
| 315 | buf += writesize - pos; | ||
| 316 | len -= writesize - pos; | ||
| 317 | pos = writesize + oob_skip; | ||
| 318 | } | ||
| 319 | |||
| 320 | ret = denali_change_column(chip, pos, buf, len, write); | ||
| 321 | if (ret) | ||
| 322 | return ret; | ||
| 323 | |||
| 324 | buf += len; | ||
| 325 | } | ||
| 326 | |||
| 327 | return 0; | ||
| 247 | } | 328 | } |
| 248 | 329 | ||
| 249 | static uint8_t denali_read_byte(struct nand_chip *chip) | 330 | static int denali_read_raw(struct nand_chip *chip, void *buf, void *oob_buf, |
| 331 | int page) | ||
| 250 | { | 332 | { |
| 251 | uint8_t byte; | 333 | int ret; |
| 334 | |||
| 335 | if (!buf && !oob_buf) | ||
| 336 | return -EINVAL; | ||
| 252 | 337 | ||
| 253 | denali_read_buf(chip, &byte, 1); | 338 | ret = nand_read_page_op(chip, page, 0, NULL, 0); |
| 339 | if (ret) | ||
| 340 | return ret; | ||
| 254 | 341 | ||
| 255 | return byte; | 342 | if (buf) { |
| 343 | ret = denali_payload_xfer(chip, buf, false); | ||
| 344 | if (ret) | ||
| 345 | return ret; | ||
| 346 | } | ||
| 347 | |||
| 348 | if (oob_buf) { | ||
| 349 | ret = denali_oob_xfer(chip, oob_buf, false); | ||
| 350 | if (ret) | ||
| 351 | return ret; | ||
| 352 | } | ||
| 353 | |||
| 354 | return 0; | ||
| 256 | } | 355 | } |
| 257 | 356 | ||
| 258 | static void denali_write_byte(struct nand_chip *chip, uint8_t byte) | 357 | static int denali_write_raw(struct nand_chip *chip, const void *buf, |
| 358 | const void *oob_buf, int page) | ||
| 259 | { | 359 | { |
| 260 | denali_write_buf(chip, &byte, 1); | 360 | int ret; |
| 361 | |||
| 362 | if (!buf && !oob_buf) | ||
| 363 | return -EINVAL; | ||
| 364 | |||
| 365 | ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0); | ||
| 366 | if (ret) | ||
| 367 | return ret; | ||
| 368 | |||
| 369 | if (buf) { | ||
| 370 | ret = denali_payload_xfer(chip, (void *)buf, true); | ||
| 371 | if (ret) | ||
| 372 | return ret; | ||
| 373 | } | ||
| 374 | |||
| 375 | if (oob_buf) { | ||
| 376 | ret = denali_oob_xfer(chip, (void *)oob_buf, true); | ||
| 377 | if (ret) | ||
| 378 | return ret; | ||
| 379 | } | ||
| 380 | |||
| 381 | return nand_prog_page_end_op(chip); | ||
| 261 | } | 382 | } |
| 262 | 383 | ||
| 263 | static void denali_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) | 384 | static int denali_read_page_raw(struct nand_chip *chip, u8 *buf, |
| 385 | int oob_required, int page) | ||
| 264 | { | 386 | { |
| 265 | struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); | 387 | return denali_read_raw(chip, buf, oob_required ? chip->oob_poi : NULL, |
| 266 | uint32_t type; | 388 | page); |
| 389 | } | ||
| 267 | 390 | ||
| 268 | if (ctrl & NAND_CLE) | 391 | static int denali_write_page_raw(struct nand_chip *chip, const u8 *buf, |
| 269 | type = DENALI_MAP11_CMD; | 392 | int oob_required, int page) |
| 270 | else if (ctrl & NAND_ALE) | 393 | { |
| 271 | type = DENALI_MAP11_ADDR; | 394 | return denali_write_raw(chip, buf, oob_required ? chip->oob_poi : NULL, |
| 272 | else | 395 | page); |
| 273 | return; | 396 | } |
| 274 | 397 | ||
| 275 | /* | 398 | static int denali_read_oob(struct nand_chip *chip, int page) |
| 276 | * Some commands are followed by chip->legacy.waitfunc. | 399 | { |
| 277 | * irq_status must be cleared here to catch the R/B# interrupt later. | 400 | return denali_read_raw(chip, NULL, chip->oob_poi, page); |
| 278 | */ | 401 | } |
| 279 | if (ctrl & NAND_CTRL_CHANGE) | ||
| 280 | denali_reset_irq(denali); | ||
| 281 | 402 | ||
| 282 | denali->host_write(denali, DENALI_BANK(denali) | type, dat); | 403 | static int denali_write_oob(struct nand_chip *chip, int page) |
| 404 | { | ||
| 405 | return denali_write_raw(chip, NULL, chip->oob_poi, page); | ||
| 283 | } | 406 | } |
| 284 | 407 | ||
| 285 | static int denali_check_erased_page(struct mtd_info *mtd, | 408 | static int denali_check_erased_page(struct nand_chip *chip, u8 *buf, |
| 286 | struct nand_chip *chip, uint8_t *buf, | ||
| 287 | unsigned long uncor_ecc_flags, | 409 | unsigned long uncor_ecc_flags, |
| 288 | unsigned int max_bitflips) | 410 | unsigned int max_bitflips) |
| 289 | { | 411 | { |
| 290 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 412 | struct denali_controller *denali = to_denali_controller(chip); |
| 291 | uint8_t *ecc_code = chip->oob_poi + denali->oob_skip_bytes; | 413 | struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; |
| 292 | int ecc_steps = chip->ecc.steps; | 414 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 293 | int ecc_size = chip->ecc.size; | 415 | u8 *ecc_code = chip->oob_poi + denali->oob_skip_bytes; |
| 294 | int ecc_bytes = chip->ecc.bytes; | ||
| 295 | int i, stat; | 416 | int i, stat; |
| 296 | 417 | ||
| 297 | for (i = 0; i < ecc_steps; i++) { | 418 | for (i = 0; i < ecc->steps; i++) { |
| 298 | if (!(uncor_ecc_flags & BIT(i))) | 419 | if (!(uncor_ecc_flags & BIT(i))) |
| 299 | continue; | 420 | continue; |
| 300 | 421 | ||
| 301 | stat = nand_check_erased_ecc_chunk(buf, ecc_size, | 422 | stat = nand_check_erased_ecc_chunk(buf, ecc->size, ecc_code, |
| 302 | ecc_code, ecc_bytes, | 423 | ecc->bytes, NULL, 0, |
| 303 | NULL, 0, | 424 | ecc->strength); |
| 304 | chip->ecc.strength); | ||
| 305 | if (stat < 0) { | 425 | if (stat < 0) { |
| 306 | mtd->ecc_stats.failed++; | 426 | ecc_stats->failed++; |
| 307 | } else { | 427 | } else { |
| 308 | mtd->ecc_stats.corrected += stat; | 428 | ecc_stats->corrected += stat; |
| 309 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | 429 | max_bitflips = max_t(unsigned int, max_bitflips, stat); |
| 310 | } | 430 | } |
| 311 | 431 | ||
| 312 | buf += ecc_size; | 432 | buf += ecc->size; |
| 313 | ecc_code += ecc_bytes; | 433 | ecc_code += ecc->bytes; |
| 314 | } | 434 | } |
| 315 | 435 | ||
| 316 | return max_bitflips; | 436 | return max_bitflips; |
| 317 | } | 437 | } |
| 318 | 438 | ||
| 319 | static int denali_hw_ecc_fixup(struct mtd_info *mtd, | 439 | static int denali_hw_ecc_fixup(struct nand_chip *chip, |
| 320 | struct denali_nand_info *denali, | ||
| 321 | unsigned long *uncor_ecc_flags) | 440 | unsigned long *uncor_ecc_flags) |
| 322 | { | 441 | { |
| 323 | struct nand_chip *chip = mtd_to_nand(mtd); | 442 | struct denali_controller *denali = to_denali_controller(chip); |
| 443 | struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; | ||
| 324 | int bank = denali->active_bank; | 444 | int bank = denali->active_bank; |
| 325 | uint32_t ecc_cor; | 445 | u32 ecc_cor; |
| 326 | unsigned int max_bitflips; | 446 | unsigned int max_bitflips; |
| 327 | 447 | ||
| 328 | ecc_cor = ioread32(denali->reg + ECC_COR_INFO(bank)); | 448 | ecc_cor = ioread32(denali->reg + ECC_COR_INFO(bank)); |
| @@ -346,23 +466,24 @@ static int denali_hw_ecc_fixup(struct mtd_info *mtd, | |||
| 346 | * Unfortunately, we can not know the total number of corrected bits in | 466 | * Unfortunately, we can not know the total number of corrected bits in |
| 347 | * the page. Increase the stats by max_bitflips. (compromised solution) | 467 | * the page. Increase the stats by max_bitflips. (compromised solution) |
| 348 | */ | 468 | */ |
| 349 | mtd->ecc_stats.corrected += max_bitflips; | 469 | ecc_stats->corrected += max_bitflips; |
| 350 | 470 | ||
| 351 | return max_bitflips; | 471 | return max_bitflips; |
| 352 | } | 472 | } |
| 353 | 473 | ||
| 354 | static int denali_sw_ecc_fixup(struct mtd_info *mtd, | 474 | static int denali_sw_ecc_fixup(struct nand_chip *chip, |
| 355 | struct denali_nand_info *denali, | 475 | unsigned long *uncor_ecc_flags, u8 *buf) |
| 356 | unsigned long *uncor_ecc_flags, uint8_t *buf) | ||
| 357 | { | 476 | { |
| 358 | unsigned int ecc_size = denali->nand.ecc.size; | 477 | struct denali_controller *denali = to_denali_controller(chip); |
| 478 | struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; | ||
| 479 | unsigned int ecc_size = chip->ecc.size; | ||
| 359 | unsigned int bitflips = 0; | 480 | unsigned int bitflips = 0; |
| 360 | unsigned int max_bitflips = 0; | 481 | unsigned int max_bitflips = 0; |
| 361 | uint32_t err_addr, err_cor_info; | 482 | u32 err_addr, err_cor_info; |
| 362 | unsigned int err_byte, err_sector, err_device; | 483 | unsigned int err_byte, err_sector, err_device; |
| 363 | uint8_t err_cor_value; | 484 | u8 err_cor_value; |
| 364 | unsigned int prev_sector = 0; | 485 | unsigned int prev_sector = 0; |
| 365 | uint32_t irq_status; | 486 | u32 irq_status; |
| 366 | 487 | ||
| 367 | denali_reset_irq(denali); | 488 | denali_reset_irq(denali); |
| 368 | 489 | ||
| @@ -404,7 +525,7 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd, | |||
| 404 | /* correct the ECC error */ | 525 | /* correct the ECC error */ |
| 405 | flips_in_byte = hweight8(buf[offset] ^ err_cor_value); | 526 | flips_in_byte = hweight8(buf[offset] ^ err_cor_value); |
| 406 | buf[offset] ^= err_cor_value; | 527 | buf[offset] ^= err_cor_value; |
| 407 | mtd->ecc_stats.corrected += flips_in_byte; | 528 | ecc_stats->corrected += flips_in_byte; |
| 408 | bitflips += flips_in_byte; | 529 | bitflips += flips_in_byte; |
| 409 | 530 | ||
| 410 | max_bitflips = max(max_bitflips, bitflips); | 531 | max_bitflips = max(max_bitflips, bitflips); |
| @@ -424,10 +545,10 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd, | |||
| 424 | return max_bitflips; | 545 | return max_bitflips; |
| 425 | } | 546 | } |
| 426 | 547 | ||
| 427 | static void denali_setup_dma64(struct denali_nand_info *denali, | 548 | static void denali_setup_dma64(struct denali_controller *denali, |
| 428 | dma_addr_t dma_addr, int page, int write) | 549 | dma_addr_t dma_addr, int page, bool write) |
| 429 | { | 550 | { |
| 430 | uint32_t mode; | 551 | u32 mode; |
| 431 | const int page_count = 1; | 552 | const int page_count = 1; |
| 432 | 553 | ||
| 433 | mode = DENALI_MAP10 | DENALI_BANK(denali) | page; | 554 | mode = DENALI_MAP10 | DENALI_BANK(denali) | page; |
| @@ -439,7 +560,8 @@ static void denali_setup_dma64(struct denali_nand_info *denali, | |||
| 439 | * burst len = 64 bytes, the number of pages | 560 | * burst len = 64 bytes, the number of pages |
| 440 | */ | 561 | */ |
| 441 | denali->host_write(denali, mode, | 562 | denali->host_write(denali, mode, |
| 442 | 0x01002000 | (64 << 16) | (write << 8) | page_count); | 563 | 0x01002000 | (64 << 16) | |
| 564 | (write ? BIT(8) : 0) | page_count); | ||
| 443 | 565 | ||
| 444 | /* 2. set memory low address */ | 566 | /* 2. set memory low address */ |
| 445 | denali->host_write(denali, mode, lower_32_bits(dma_addr)); | 567 | denali->host_write(denali, mode, lower_32_bits(dma_addr)); |
| @@ -448,10 +570,10 @@ static void denali_setup_dma64(struct denali_nand_info *denali, | |||
| 448 | denali->host_write(denali, mode, upper_32_bits(dma_addr)); | 570 | denali->host_write(denali, mode, upper_32_bits(dma_addr)); |
| 449 | } | 571 | } |
| 450 | 572 | ||
| 451 | static void denali_setup_dma32(struct denali_nand_info *denali, | 573 | static void denali_setup_dma32(struct denali_controller *denali, |
| 452 | dma_addr_t dma_addr, int page, int write) | 574 | dma_addr_t dma_addr, int page, bool write) |
| 453 | { | 575 | { |
| 454 | uint32_t mode; | 576 | u32 mode; |
| 455 | const int page_count = 1; | 577 | const int page_count = 1; |
| 456 | 578 | ||
| 457 | mode = DENALI_MAP10 | DENALI_BANK(denali); | 579 | mode = DENALI_MAP10 | DENALI_BANK(denali); |
| @@ -460,7 +582,7 @@ static void denali_setup_dma32(struct denali_nand_info *denali, | |||
| 460 | 582 | ||
| 461 | /* 1. setup transfer type and # of pages */ | 583 | /* 1. setup transfer type and # of pages */ |
| 462 | denali->host_write(denali, mode | page, | 584 | denali->host_write(denali, mode | page, |
| 463 | 0x2000 | (write << 8) | page_count); | 585 | 0x2000 | (write ? BIT(8) : 0) | page_count); |
| 464 | 586 | ||
| 465 | /* 2. set memory high address bits 23:8 */ | 587 | /* 2. set memory high address bits 23:8 */ |
| 466 | denali->host_write(denali, mode | ((dma_addr >> 16) << 8), 0x2200); | 588 | denali->host_write(denali, mode | ((dma_addr >> 16) << 8), 0x2200); |
| @@ -472,12 +594,11 @@ static void denali_setup_dma32(struct denali_nand_info *denali, | |||
| 472 | denali->host_write(denali, mode | 0x14000, 0x2400); | 594 | denali->host_write(denali, mode | 0x14000, 0x2400); |
| 473 | } | 595 | } |
| 474 | 596 | ||
| 475 | static int denali_pio_read(struct denali_nand_info *denali, void *buf, | 597 | static int denali_pio_read(struct denali_controller *denali, u32 *buf, |
| 476 | size_t size, int page) | 598 | size_t size, int page) |
| 477 | { | 599 | { |
| 478 | u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; | 600 | u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; |
| 479 | uint32_t *buf32 = (uint32_t *)buf; | 601 | u32 irq_status, ecc_err_mask; |
| 480 | uint32_t irq_status, ecc_err_mask; | ||
| 481 | int i; | 602 | int i; |
| 482 | 603 | ||
| 483 | if (denali->caps & DENALI_CAP_HW_ECC_FIXUP) | 604 | if (denali->caps & DENALI_CAP_HW_ECC_FIXUP) |
| @@ -488,7 +609,7 @@ static int denali_pio_read(struct denali_nand_info *denali, void *buf, | |||
| 488 | denali_reset_irq(denali); | 609 | denali_reset_irq(denali); |
| 489 | 610 | ||
| 490 | for (i = 0; i < size / 4; i++) | 611 | for (i = 0; i < size / 4; i++) |
| 491 | *buf32++ = denali->host_read(denali, addr); | 612 | buf[i] = denali->host_read(denali, addr); |
| 492 | 613 | ||
| 493 | irq_status = denali_wait_for_irq(denali, INTR__PAGE_XFER_INC); | 614 | irq_status = denali_wait_for_irq(denali, INTR__PAGE_XFER_INC); |
| 494 | if (!(irq_status & INTR__PAGE_XFER_INC)) | 615 | if (!(irq_status & INTR__PAGE_XFER_INC)) |
| @@ -500,29 +621,29 @@ static int denali_pio_read(struct denali_nand_info *denali, void *buf, | |||
| 500 | return irq_status & ecc_err_mask ? -EBADMSG : 0; | 621 | return irq_status & ecc_err_mask ? -EBADMSG : 0; |
| 501 | } | 622 | } |
| 502 | 623 | ||
| 503 | static int denali_pio_write(struct denali_nand_info *denali, | 624 | static int denali_pio_write(struct denali_controller *denali, const u32 *buf, |
| 504 | const void *buf, size_t size, int page) | 625 | size_t size, int page) |
| 505 | { | 626 | { |
| 506 | u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; | 627 | u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; |
| 507 | const uint32_t *buf32 = (uint32_t *)buf; | 628 | u32 irq_status; |
| 508 | uint32_t irq_status; | ||
| 509 | int i; | 629 | int i; |
| 510 | 630 | ||
| 511 | denali_reset_irq(denali); | 631 | denali_reset_irq(denali); |
| 512 | 632 | ||
| 513 | for (i = 0; i < size / 4; i++) | 633 | for (i = 0; i < size / 4; i++) |
| 514 | denali->host_write(denali, addr, *buf32++); | 634 | denali->host_write(denali, addr, buf[i]); |
| 515 | 635 | ||
| 516 | irq_status = denali_wait_for_irq(denali, | 636 | irq_status = denali_wait_for_irq(denali, |
| 517 | INTR__PROGRAM_COMP | INTR__PROGRAM_FAIL); | 637 | INTR__PROGRAM_COMP | |
| 638 | INTR__PROGRAM_FAIL); | ||
| 518 | if (!(irq_status & INTR__PROGRAM_COMP)) | 639 | if (!(irq_status & INTR__PROGRAM_COMP)) |
| 519 | return -EIO; | 640 | return -EIO; |
| 520 | 641 | ||
| 521 | return 0; | 642 | return 0; |
| 522 | } | 643 | } |
| 523 | 644 | ||
| 524 | static int denali_pio_xfer(struct denali_nand_info *denali, void *buf, | 645 | static int denali_pio_xfer(struct denali_controller *denali, void *buf, |
| 525 | size_t size, int page, int write) | 646 | size_t size, int page, bool write) |
| 526 | { | 647 | { |
| 527 | if (write) | 648 | if (write) |
| 528 | return denali_pio_write(denali, buf, size, page); | 649 | return denali_pio_write(denali, buf, size, page); |
| @@ -530,11 +651,11 @@ static int denali_pio_xfer(struct denali_nand_info *denali, void *buf, | |||
| 530 | return denali_pio_read(denali, buf, size, page); | 651 | return denali_pio_read(denali, buf, size, page); |
| 531 | } | 652 | } |
| 532 | 653 | ||
| 533 | static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, | 654 | static int denali_dma_xfer(struct denali_controller *denali, void *buf, |
| 534 | size_t size, int page, int write) | 655 | size_t size, int page, bool write) |
| 535 | { | 656 | { |
| 536 | dma_addr_t dma_addr; | 657 | dma_addr_t dma_addr; |
| 537 | uint32_t irq_mask, irq_status, ecc_err_mask; | 658 | u32 irq_mask, irq_status, ecc_err_mask; |
| 538 | enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 659 | enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
| 539 | int ret = 0; | 660 | int ret = 0; |
| 540 | 661 | ||
| @@ -587,12 +708,12 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, | |||
| 587 | return ret; | 708 | return ret; |
| 588 | } | 709 | } |
| 589 | 710 | ||
| 590 | static int denali_data_xfer(struct denali_nand_info *denali, void *buf, | 711 | static int denali_page_xfer(struct nand_chip *chip, void *buf, size_t size, |
| 591 | size_t size, int page, int raw, int write) | 712 | int page, bool write) |
| 592 | { | 713 | { |
| 593 | iowrite32(raw ? 0 : ECC_ENABLE__FLAG, denali->reg + ECC_ENABLE); | 714 | struct denali_controller *denali = to_denali_controller(chip); |
| 594 | iowrite32(raw ? TRANSFER_SPARE_REG__FLAG : 0, | 715 | |
| 595 | denali->reg + TRANSFER_SPARE_REG); | 716 | denali_select_target(chip, chip->cur_cs); |
| 596 | 717 | ||
| 597 | if (denali->dma_avail) | 718 | if (denali->dma_avail) |
| 598 | return denali_dma_xfer(denali, buf, size, page, write); | 719 | return denali_dma_xfer(denali, buf, size, page, write); |
| @@ -600,180 +721,23 @@ static int denali_data_xfer(struct denali_nand_info *denali, void *buf, | |||
| 600 | return denali_pio_xfer(denali, buf, size, page, write); | 721 | return denali_pio_xfer(denali, buf, size, page, write); |
| 601 | } | 722 | } |
| 602 | 723 | ||
| 603 | static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip, | 724 | static int denali_read_page(struct nand_chip *chip, u8 *buf, |
| 604 | int page, int write) | ||
| 605 | { | ||
| 606 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 607 | int writesize = mtd->writesize; | ||
| 608 | int oobsize = mtd->oobsize; | ||
| 609 | uint8_t *bufpoi = chip->oob_poi; | ||
| 610 | int ecc_steps = chip->ecc.steps; | ||
| 611 | int ecc_size = chip->ecc.size; | ||
| 612 | int ecc_bytes = chip->ecc.bytes; | ||
| 613 | int oob_skip = denali->oob_skip_bytes; | ||
| 614 | size_t size = writesize + oobsize; | ||
| 615 | int i, pos, len; | ||
| 616 | |||
| 617 | /* BBM at the beginning of the OOB area */ | ||
| 618 | if (write) | ||
| 619 | nand_prog_page_begin_op(chip, page, writesize, bufpoi, | ||
| 620 | oob_skip); | ||
| 621 | else | ||
| 622 | nand_read_page_op(chip, page, writesize, bufpoi, oob_skip); | ||
| 623 | bufpoi += oob_skip; | ||
| 624 | |||
| 625 | /* OOB ECC */ | ||
| 626 | for (i = 0; i < ecc_steps; i++) { | ||
| 627 | pos = ecc_size + i * (ecc_size + ecc_bytes); | ||
| 628 | len = ecc_bytes; | ||
| 629 | |||
| 630 | if (pos >= writesize) | ||
| 631 | pos += oob_skip; | ||
| 632 | else if (pos + len > writesize) | ||
| 633 | len = writesize - pos; | ||
| 634 | |||
| 635 | if (write) | ||
| 636 | nand_change_write_column_op(chip, pos, bufpoi, len, | ||
| 637 | false); | ||
| 638 | else | ||
| 639 | nand_change_read_column_op(chip, pos, bufpoi, len, | ||
| 640 | false); | ||
| 641 | bufpoi += len; | ||
| 642 | if (len < ecc_bytes) { | ||
| 643 | len = ecc_bytes - len; | ||
| 644 | if (write) | ||
| 645 | nand_change_write_column_op(chip, writesize + | ||
| 646 | oob_skip, bufpoi, | ||
| 647 | len, false); | ||
| 648 | else | ||
| 649 | nand_change_read_column_op(chip, writesize + | ||
| 650 | oob_skip, bufpoi, | ||
| 651 | len, false); | ||
| 652 | bufpoi += len; | ||
| 653 | } | ||
| 654 | } | ||
| 655 | |||
| 656 | /* OOB free */ | ||
| 657 | len = oobsize - (bufpoi - chip->oob_poi); | ||
| 658 | if (write) | ||
| 659 | nand_change_write_column_op(chip, size - len, bufpoi, len, | ||
| 660 | false); | ||
| 661 | else | ||
| 662 | nand_change_read_column_op(chip, size - len, bufpoi, len, | ||
| 663 | false); | ||
| 664 | } | ||
| 665 | |||
| 666 | static int denali_read_page_raw(struct nand_chip *chip, uint8_t *buf, | ||
| 667 | int oob_required, int page) | ||
| 668 | { | ||
| 669 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 670 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 671 | int writesize = mtd->writesize; | ||
| 672 | int oobsize = mtd->oobsize; | ||
| 673 | int ecc_steps = chip->ecc.steps; | ||
| 674 | int ecc_size = chip->ecc.size; | ||
| 675 | int ecc_bytes = chip->ecc.bytes; | ||
| 676 | void *tmp_buf = denali->buf; | ||
| 677 | int oob_skip = denali->oob_skip_bytes; | ||
| 678 | size_t size = writesize + oobsize; | ||
| 679 | int ret, i, pos, len; | ||
| 680 | |||
| 681 | ret = denali_data_xfer(denali, tmp_buf, size, page, 1, 0); | ||
| 682 | if (ret) | ||
| 683 | return ret; | ||
| 684 | |||
| 685 | /* Arrange the buffer for syndrome payload/ecc layout */ | ||
| 686 | if (buf) { | ||
| 687 | for (i = 0; i < ecc_steps; i++) { | ||
| 688 | pos = i * (ecc_size + ecc_bytes); | ||
| 689 | len = ecc_size; | ||
| 690 | |||
| 691 | if (pos >= writesize) | ||
| 692 | pos += oob_skip; | ||
| 693 | else if (pos + len > writesize) | ||
| 694 | len = writesize - pos; | ||
| 695 | |||
| 696 | memcpy(buf, tmp_buf + pos, len); | ||
| 697 | buf += len; | ||
| 698 | if (len < ecc_size) { | ||
| 699 | len = ecc_size - len; | ||
| 700 | memcpy(buf, tmp_buf + writesize + oob_skip, | ||
| 701 | len); | ||
| 702 | buf += len; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | } | ||
| 706 | |||
| 707 | if (oob_required) { | ||
| 708 | uint8_t *oob = chip->oob_poi; | ||
| 709 | |||
| 710 | /* BBM at the beginning of the OOB area */ | ||
| 711 | memcpy(oob, tmp_buf + writesize, oob_skip); | ||
| 712 | oob += oob_skip; | ||
| 713 | |||
| 714 | /* OOB ECC */ | ||
| 715 | for (i = 0; i < ecc_steps; i++) { | ||
| 716 | pos = ecc_size + i * (ecc_size + ecc_bytes); | ||
| 717 | len = ecc_bytes; | ||
| 718 | |||
| 719 | if (pos >= writesize) | ||
| 720 | pos += oob_skip; | ||
| 721 | else if (pos + len > writesize) | ||
| 722 | len = writesize - pos; | ||
| 723 | |||
| 724 | memcpy(oob, tmp_buf + pos, len); | ||
| 725 | oob += len; | ||
| 726 | if (len < ecc_bytes) { | ||
| 727 | len = ecc_bytes - len; | ||
| 728 | memcpy(oob, tmp_buf + writesize + oob_skip, | ||
| 729 | len); | ||
| 730 | oob += len; | ||
| 731 | } | ||
| 732 | } | ||
| 733 | |||
| 734 | /* OOB free */ | ||
| 735 | len = oobsize - (oob - chip->oob_poi); | ||
| 736 | memcpy(oob, tmp_buf + size - len, len); | ||
| 737 | } | ||
| 738 | |||
| 739 | return 0; | ||
| 740 | } | ||
| 741 | |||
| 742 | static int denali_read_oob(struct nand_chip *chip, int page) | ||
| 743 | { | ||
| 744 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 745 | |||
| 746 | denali_oob_xfer(mtd, chip, page, 0); | ||
| 747 | |||
| 748 | return 0; | ||
| 749 | } | ||
| 750 | |||
| 751 | static int denali_write_oob(struct nand_chip *chip, int page) | ||
| 752 | { | ||
| 753 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 754 | |||
| 755 | denali_oob_xfer(mtd, chip, page, 1); | ||
| 756 | |||
| 757 | return nand_prog_page_end_op(chip); | ||
| 758 | } | ||
| 759 | |||
| 760 | static int denali_read_page(struct nand_chip *chip, uint8_t *buf, | ||
| 761 | int oob_required, int page) | 725 | int oob_required, int page) |
| 762 | { | 726 | { |
| 727 | struct denali_controller *denali = to_denali_controller(chip); | ||
| 763 | struct mtd_info *mtd = nand_to_mtd(chip); | 728 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 764 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 765 | unsigned long uncor_ecc_flags = 0; | 729 | unsigned long uncor_ecc_flags = 0; |
| 766 | int stat = 0; | 730 | int stat = 0; |
| 767 | int ret; | 731 | int ret; |
| 768 | 732 | ||
| 769 | ret = denali_data_xfer(denali, buf, mtd->writesize, page, 0, 0); | 733 | ret = denali_page_xfer(chip, buf, mtd->writesize, page, false); |
| 770 | if (ret && ret != -EBADMSG) | 734 | if (ret && ret != -EBADMSG) |
| 771 | return ret; | 735 | return ret; |
| 772 | 736 | ||
| 773 | if (denali->caps & DENALI_CAP_HW_ECC_FIXUP) | 737 | if (denali->caps & DENALI_CAP_HW_ECC_FIXUP) |
| 774 | stat = denali_hw_ecc_fixup(mtd, denali, &uncor_ecc_flags); | 738 | stat = denali_hw_ecc_fixup(chip, &uncor_ecc_flags); |
| 775 | else if (ret == -EBADMSG) | 739 | else if (ret == -EBADMSG) |
| 776 | stat = denali_sw_ecc_fixup(mtd, denali, &uncor_ecc_flags, buf); | 740 | stat = denali_sw_ecc_fixup(chip, &uncor_ecc_flags, buf); |
| 777 | 741 | ||
| 778 | if (stat < 0) | 742 | if (stat < 0) |
| 779 | return stat; | 743 | return stat; |
| @@ -783,130 +747,32 @@ static int denali_read_page(struct nand_chip *chip, uint8_t *buf, | |||
| 783 | if (ret) | 747 | if (ret) |
| 784 | return ret; | 748 | return ret; |
| 785 | 749 | ||
| 786 | stat = denali_check_erased_page(mtd, chip, buf, | 750 | stat = denali_check_erased_page(chip, buf, |
| 787 | uncor_ecc_flags, stat); | 751 | uncor_ecc_flags, stat); |
| 788 | } | 752 | } |
| 789 | 753 | ||
| 790 | return stat; | 754 | return stat; |
| 791 | } | 755 | } |
| 792 | 756 | ||
| 793 | static int denali_write_page_raw(struct nand_chip *chip, const uint8_t *buf, | 757 | static int denali_write_page(struct nand_chip *chip, const u8 *buf, |
| 794 | int oob_required, int page) | ||
| 795 | { | ||
| 796 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 797 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 798 | int writesize = mtd->writesize; | ||
| 799 | int oobsize = mtd->oobsize; | ||
| 800 | int ecc_steps = chip->ecc.steps; | ||
| 801 | int ecc_size = chip->ecc.size; | ||
| 802 | int ecc_bytes = chip->ecc.bytes; | ||
| 803 | void *tmp_buf = denali->buf; | ||
| 804 | int oob_skip = denali->oob_skip_bytes; | ||
| 805 | size_t size = writesize + oobsize; | ||
| 806 | int i, pos, len; | ||
| 807 | |||
| 808 | /* | ||
| 809 | * Fill the buffer with 0xff first except the full page transfer. | ||
| 810 | * This simplifies the logic. | ||
| 811 | */ | ||
| 812 | if (!buf || !oob_required) | ||
| 813 | memset(tmp_buf, 0xff, size); | ||
| 814 | |||
| 815 | /* Arrange the buffer for syndrome payload/ecc layout */ | ||
| 816 | if (buf) { | ||
| 817 | for (i = 0; i < ecc_steps; i++) { | ||
| 818 | pos = i * (ecc_size + ecc_bytes); | ||
| 819 | len = ecc_size; | ||
| 820 | |||
| 821 | if (pos >= writesize) | ||
| 822 | pos += oob_skip; | ||
| 823 | else if (pos + len > writesize) | ||
| 824 | len = writesize - pos; | ||
| 825 | |||
| 826 | memcpy(tmp_buf + pos, buf, len); | ||
| 827 | buf += len; | ||
| 828 | if (len < ecc_size) { | ||
| 829 | len = ecc_size - len; | ||
| 830 | memcpy(tmp_buf + writesize + oob_skip, buf, | ||
| 831 | len); | ||
| 832 | buf += len; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | } | ||
| 836 | |||
| 837 | if (oob_required) { | ||
| 838 | const uint8_t *oob = chip->oob_poi; | ||
| 839 | |||
| 840 | /* BBM at the beginning of the OOB area */ | ||
| 841 | memcpy(tmp_buf + writesize, oob, oob_skip); | ||
| 842 | oob += oob_skip; | ||
| 843 | |||
| 844 | /* OOB ECC */ | ||
| 845 | for (i = 0; i < ecc_steps; i++) { | ||
| 846 | pos = ecc_size + i * (ecc_size + ecc_bytes); | ||
| 847 | len = ecc_bytes; | ||
| 848 | |||
| 849 | if (pos >= writesize) | ||
| 850 | pos += oob_skip; | ||
| 851 | else if (pos + len > writesize) | ||
| 852 | len = writesize - pos; | ||
| 853 | |||
| 854 | memcpy(tmp_buf + pos, oob, len); | ||
| 855 | oob += len; | ||
| 856 | if (len < ecc_bytes) { | ||
| 857 | len = ecc_bytes - len; | ||
| 858 | memcpy(tmp_buf + writesize + oob_skip, oob, | ||
| 859 | len); | ||
| 860 | oob += len; | ||
| 861 | } | ||
| 862 | } | ||
| 863 | |||
| 864 | /* OOB free */ | ||
| 865 | len = oobsize - (oob - chip->oob_poi); | ||
| 866 | memcpy(tmp_buf + size - len, oob, len); | ||
| 867 | } | ||
| 868 | |||
| 869 | return denali_data_xfer(denali, tmp_buf, size, page, 1, 1); | ||
| 870 | } | ||
| 871 | |||
| 872 | static int denali_write_page(struct nand_chip *chip, const uint8_t *buf, | ||
| 873 | int oob_required, int page) | 758 | int oob_required, int page) |
| 874 | { | 759 | { |
| 875 | struct mtd_info *mtd = nand_to_mtd(chip); | 760 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 876 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 877 | 761 | ||
| 878 | return denali_data_xfer(denali, (void *)buf, mtd->writesize, | 762 | return denali_page_xfer(chip, (void *)buf, mtd->writesize, page, true); |
| 879 | page, 0, 1); | ||
| 880 | } | ||
| 881 | |||
| 882 | static void denali_select_chip(struct nand_chip *chip, int cs) | ||
| 883 | { | ||
| 884 | struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); | ||
| 885 | |||
| 886 | denali->active_bank = cs; | ||
| 887 | } | ||
| 888 | |||
| 889 | static int denali_waitfunc(struct nand_chip *chip) | ||
| 890 | { | ||
| 891 | struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); | ||
| 892 | uint32_t irq_status; | ||
| 893 | |||
| 894 | /* R/B# pin transitioned from low to high? */ | ||
| 895 | irq_status = denali_wait_for_irq(denali, INTR__INT_ACT); | ||
| 896 | |||
| 897 | return irq_status & INTR__INT_ACT ? 0 : NAND_STATUS_FAIL; | ||
| 898 | } | 763 | } |
| 899 | 764 | ||
| 900 | static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | 765 | static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, |
| 901 | const struct nand_data_interface *conf) | 766 | const struct nand_data_interface *conf) |
| 902 | { | 767 | { |
| 903 | struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); | 768 | struct denali_controller *denali = to_denali_controller(chip); |
| 769 | struct denali_chip_sel *sel; | ||
| 904 | const struct nand_sdr_timings *timings; | 770 | const struct nand_sdr_timings *timings; |
| 905 | unsigned long t_x, mult_x; | 771 | unsigned long t_x, mult_x; |
| 906 | int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data; | 772 | int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data; |
| 907 | int rdwr_en_lo, rdwr_en_hi, rdwr_en_lo_hi, cs_setup; | 773 | int rdwr_en_lo, rdwr_en_hi, rdwr_en_lo_hi, cs_setup; |
| 908 | int addr_2_data_mask; | 774 | int addr_2_data_mask; |
| 909 | uint32_t tmp; | 775 | u32 tmp; |
| 910 | 776 | ||
| 911 | timings = nand_get_sdr_timings(conf); | 777 | timings = nand_get_sdr_timings(conf); |
| 912 | if (IS_ERR(timings)) | 778 | if (IS_ERR(timings)) |
| @@ -929,6 +795,8 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 929 | if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) | 795 | if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) |
| 930 | return 0; | 796 | return 0; |
| 931 | 797 | ||
| 798 | sel = &to_denali_chip(chip)->sels[chipnr]; | ||
| 799 | |||
| 932 | /* tREA -> ACC_CLKS */ | 800 | /* tREA -> ACC_CLKS */ |
| 933 | acc_clks = DIV_ROUND_UP(timings->tREA_max, t_x); | 801 | acc_clks = DIV_ROUND_UP(timings->tREA_max, t_x); |
| 934 | acc_clks = min_t(int, acc_clks, ACC_CLKS__VALUE); | 802 | acc_clks = min_t(int, acc_clks, ACC_CLKS__VALUE); |
| @@ -936,7 +804,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 936 | tmp = ioread32(denali->reg + ACC_CLKS); | 804 | tmp = ioread32(denali->reg + ACC_CLKS); |
| 937 | tmp &= ~ACC_CLKS__VALUE; | 805 | tmp &= ~ACC_CLKS__VALUE; |
| 938 | tmp |= FIELD_PREP(ACC_CLKS__VALUE, acc_clks); | 806 | tmp |= FIELD_PREP(ACC_CLKS__VALUE, acc_clks); |
| 939 | iowrite32(tmp, denali->reg + ACC_CLKS); | 807 | sel->acc_clks = tmp; |
| 940 | 808 | ||
| 941 | /* tRWH -> RE_2_WE */ | 809 | /* tRWH -> RE_2_WE */ |
| 942 | re_2_we = DIV_ROUND_UP(timings->tRHW_min, t_x); | 810 | re_2_we = DIV_ROUND_UP(timings->tRHW_min, t_x); |
| @@ -945,7 +813,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 945 | tmp = ioread32(denali->reg + RE_2_WE); | 813 | tmp = ioread32(denali->reg + RE_2_WE); |
| 946 | tmp &= ~RE_2_WE__VALUE; | 814 | tmp &= ~RE_2_WE__VALUE; |
| 947 | tmp |= FIELD_PREP(RE_2_WE__VALUE, re_2_we); | 815 | tmp |= FIELD_PREP(RE_2_WE__VALUE, re_2_we); |
| 948 | iowrite32(tmp, denali->reg + RE_2_WE); | 816 | sel->re_2_we = tmp; |
| 949 | 817 | ||
| 950 | /* tRHZ -> RE_2_RE */ | 818 | /* tRHZ -> RE_2_RE */ |
| 951 | re_2_re = DIV_ROUND_UP(timings->tRHZ_max, t_x); | 819 | re_2_re = DIV_ROUND_UP(timings->tRHZ_max, t_x); |
| @@ -954,7 +822,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 954 | tmp = ioread32(denali->reg + RE_2_RE); | 822 | tmp = ioread32(denali->reg + RE_2_RE); |
| 955 | tmp &= ~RE_2_RE__VALUE; | 823 | tmp &= ~RE_2_RE__VALUE; |
| 956 | tmp |= FIELD_PREP(RE_2_RE__VALUE, re_2_re); | 824 | tmp |= FIELD_PREP(RE_2_RE__VALUE, re_2_re); |
| 957 | iowrite32(tmp, denali->reg + RE_2_RE); | 825 | sel->re_2_re = tmp; |
| 958 | 826 | ||
| 959 | /* | 827 | /* |
| 960 | * tCCS, tWHR -> WE_2_RE | 828 | * tCCS, tWHR -> WE_2_RE |
| @@ -968,7 +836,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 968 | tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE); | 836 | tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE); |
| 969 | tmp &= ~TWHR2_AND_WE_2_RE__WE_2_RE; | 837 | tmp &= ~TWHR2_AND_WE_2_RE__WE_2_RE; |
| 970 | tmp |= FIELD_PREP(TWHR2_AND_WE_2_RE__WE_2_RE, we_2_re); | 838 | tmp |= FIELD_PREP(TWHR2_AND_WE_2_RE__WE_2_RE, we_2_re); |
| 971 | iowrite32(tmp, denali->reg + TWHR2_AND_WE_2_RE); | 839 | sel->hwhr2_and_we_2_re = tmp; |
| 972 | 840 | ||
| 973 | /* tADL -> ADDR_2_DATA */ | 841 | /* tADL -> ADDR_2_DATA */ |
| 974 | 842 | ||
| @@ -983,7 +851,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 983 | tmp = ioread32(denali->reg + TCWAW_AND_ADDR_2_DATA); | 851 | tmp = ioread32(denali->reg + TCWAW_AND_ADDR_2_DATA); |
| 984 | tmp &= ~TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA; | 852 | tmp &= ~TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA; |
| 985 | tmp |= FIELD_PREP(TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA, addr_2_data); | 853 | tmp |= FIELD_PREP(TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA, addr_2_data); |
| 986 | iowrite32(tmp, denali->reg + TCWAW_AND_ADDR_2_DATA); | 854 | sel->tcwaw_and_addr_2_data = tmp; |
| 987 | 855 | ||
| 988 | /* tREH, tWH -> RDWR_EN_HI_CNT */ | 856 | /* tREH, tWH -> RDWR_EN_HI_CNT */ |
| 989 | rdwr_en_hi = DIV_ROUND_UP(max(timings->tREH_min, timings->tWH_min), | 857 | rdwr_en_hi = DIV_ROUND_UP(max(timings->tREH_min, timings->tWH_min), |
| @@ -993,7 +861,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 993 | tmp = ioread32(denali->reg + RDWR_EN_HI_CNT); | 861 | tmp = ioread32(denali->reg + RDWR_EN_HI_CNT); |
| 994 | tmp &= ~RDWR_EN_HI_CNT__VALUE; | 862 | tmp &= ~RDWR_EN_HI_CNT__VALUE; |
| 995 | tmp |= FIELD_PREP(RDWR_EN_HI_CNT__VALUE, rdwr_en_hi); | 863 | tmp |= FIELD_PREP(RDWR_EN_HI_CNT__VALUE, rdwr_en_hi); |
| 996 | iowrite32(tmp, denali->reg + RDWR_EN_HI_CNT); | 864 | sel->rdwr_en_hi_cnt = tmp; |
| 997 | 865 | ||
| 998 | /* tRP, tWP -> RDWR_EN_LO_CNT */ | 866 | /* tRP, tWP -> RDWR_EN_LO_CNT */ |
| 999 | rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x); | 867 | rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x); |
| @@ -1006,7 +874,7 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 1006 | tmp = ioread32(denali->reg + RDWR_EN_LO_CNT); | 874 | tmp = ioread32(denali->reg + RDWR_EN_LO_CNT); |
| 1007 | tmp &= ~RDWR_EN_LO_CNT__VALUE; | 875 | tmp &= ~RDWR_EN_LO_CNT__VALUE; |
| 1008 | tmp |= FIELD_PREP(RDWR_EN_LO_CNT__VALUE, rdwr_en_lo); | 876 | tmp |= FIELD_PREP(RDWR_EN_LO_CNT__VALUE, rdwr_en_lo); |
| 1009 | iowrite32(tmp, denali->reg + RDWR_EN_LO_CNT); | 877 | sel->rdwr_en_lo_cnt = tmp; |
| 1010 | 878 | ||
| 1011 | /* tCS, tCEA -> CS_SETUP_CNT */ | 879 | /* tCS, tCEA -> CS_SETUP_CNT */ |
| 1012 | cs_setup = max3((int)DIV_ROUND_UP(timings->tCS_min, t_x) - rdwr_en_lo, | 880 | cs_setup = max3((int)DIV_ROUND_UP(timings->tCS_min, t_x) - rdwr_en_lo, |
| @@ -1017,39 +885,11 @@ static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, | |||
| 1017 | tmp = ioread32(denali->reg + CS_SETUP_CNT); | 885 | tmp = ioread32(denali->reg + CS_SETUP_CNT); |
| 1018 | tmp &= ~CS_SETUP_CNT__VALUE; | 886 | tmp &= ~CS_SETUP_CNT__VALUE; |
| 1019 | tmp |= FIELD_PREP(CS_SETUP_CNT__VALUE, cs_setup); | 887 | tmp |= FIELD_PREP(CS_SETUP_CNT__VALUE, cs_setup); |
| 1020 | iowrite32(tmp, denali->reg + CS_SETUP_CNT); | 888 | sel->cs_setup_cnt = tmp; |
| 1021 | 889 | ||
| 1022 | return 0; | 890 | return 0; |
| 1023 | } | 891 | } |
| 1024 | 892 | ||
| 1025 | static void denali_hw_init(struct denali_nand_info *denali) | ||
| 1026 | { | ||
| 1027 | /* | ||
| 1028 | * The REVISION register may not be reliable. Platforms are allowed to | ||
| 1029 | * override it. | ||
| 1030 | */ | ||
| 1031 | if (!denali->revision) | ||
| 1032 | denali->revision = swab16(ioread32(denali->reg + REVISION)); | ||
| 1033 | |||
| 1034 | /* | ||
| 1035 | * Set how many bytes should be skipped before writing data in OOB. | ||
| 1036 | * If a non-zero value has already been set (by firmware or something), | ||
| 1037 | * just use it. Otherwise, set the driver default. | ||
| 1038 | */ | ||
| 1039 | denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); | ||
| 1040 | if (!denali->oob_skip_bytes) { | ||
| 1041 | denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; | ||
| 1042 | iowrite32(denali->oob_skip_bytes, | ||
| 1043 | denali->reg + SPARE_AREA_SKIP_BYTES); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | denali_detect_max_banks(denali); | ||
| 1047 | iowrite32(0x0F, denali->reg + RB_PIN_ENABLED); | ||
| 1048 | iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); | ||
| 1049 | |||
| 1050 | iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | int denali_calc_ecc_bytes(int step_size, int strength) | 893 | int denali_calc_ecc_bytes(int step_size, int strength) |
| 1054 | { | 894 | { |
| 1055 | /* BCH code. Denali requires ecc.bytes to be multiple of 2 */ | 895 | /* BCH code. Denali requires ecc.bytes to be multiple of 2 */ |
| @@ -1060,10 +900,10 @@ EXPORT_SYMBOL(denali_calc_ecc_bytes); | |||
| 1060 | static int denali_ooblayout_ecc(struct mtd_info *mtd, int section, | 900 | static int denali_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 1061 | struct mtd_oob_region *oobregion) | 901 | struct mtd_oob_region *oobregion) |
| 1062 | { | 902 | { |
| 1063 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1064 | struct nand_chip *chip = mtd_to_nand(mtd); | 903 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 904 | struct denali_controller *denali = to_denali_controller(chip); | ||
| 1065 | 905 | ||
| 1066 | if (section) | 906 | if (section > 0) |
| 1067 | return -ERANGE; | 907 | return -ERANGE; |
| 1068 | 908 | ||
| 1069 | oobregion->offset = denali->oob_skip_bytes; | 909 | oobregion->offset = denali->oob_skip_bytes; |
| @@ -1075,10 +915,10 @@ static int denali_ooblayout_ecc(struct mtd_info *mtd, int section, | |||
| 1075 | static int denali_ooblayout_free(struct mtd_info *mtd, int section, | 915 | static int denali_ooblayout_free(struct mtd_info *mtd, int section, |
| 1076 | struct mtd_oob_region *oobregion) | 916 | struct mtd_oob_region *oobregion) |
| 1077 | { | 917 | { |
| 1078 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1079 | struct nand_chip *chip = mtd_to_nand(mtd); | 918 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 919 | struct denali_controller *denali = to_denali_controller(chip); | ||
| 1080 | 920 | ||
| 1081 | if (section) | 921 | if (section > 0) |
| 1082 | return -ERANGE; | 922 | return -ERANGE; |
| 1083 | 923 | ||
| 1084 | oobregion->offset = chip->ecc.total + denali->oob_skip_bytes; | 924 | oobregion->offset = chip->ecc.total + denali->oob_skip_bytes; |
| @@ -1092,10 +932,13 @@ static const struct mtd_ooblayout_ops denali_ooblayout_ops = { | |||
| 1092 | .free = denali_ooblayout_free, | 932 | .free = denali_ooblayout_free, |
| 1093 | }; | 933 | }; |
| 1094 | 934 | ||
| 1095 | static int denali_multidev_fixup(struct denali_nand_info *denali) | 935 | static int denali_multidev_fixup(struct nand_chip *chip) |
| 1096 | { | 936 | { |
| 1097 | struct nand_chip *chip = &denali->nand; | 937 | struct denali_controller *denali = to_denali_controller(chip); |
| 1098 | struct mtd_info *mtd = nand_to_mtd(chip); | 938 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 939 | struct nand_memory_organization *memorg; | ||
| 940 | |||
| 941 | memorg = nanddev_get_memorg(&chip->base); | ||
| 1099 | 942 | ||
| 1100 | /* | 943 | /* |
| 1101 | * Support for multi device: | 944 | * Support for multi device: |
| @@ -1125,11 +968,12 @@ static int denali_multidev_fixup(struct denali_nand_info *denali) | |||
| 1125 | } | 968 | } |
| 1126 | 969 | ||
| 1127 | /* 2 chips in parallel */ | 970 | /* 2 chips in parallel */ |
| 971 | memorg->pagesize <<= 1; | ||
| 972 | memorg->oobsize <<= 1; | ||
| 1128 | mtd->size <<= 1; | 973 | mtd->size <<= 1; |
| 1129 | mtd->erasesize <<= 1; | 974 | mtd->erasesize <<= 1; |
| 1130 | mtd->writesize <<= 1; | 975 | mtd->writesize <<= 1; |
| 1131 | mtd->oobsize <<= 1; | 976 | mtd->oobsize <<= 1; |
| 1132 | chip->chipsize <<= 1; | ||
| 1133 | chip->page_shift += 1; | 977 | chip->page_shift += 1; |
| 1134 | chip->phys_erase_shift += 1; | 978 | chip->phys_erase_shift += 1; |
| 1135 | chip->bbt_erase_shift += 1; | 979 | chip->bbt_erase_shift += 1; |
| @@ -1145,38 +989,10 @@ static int denali_multidev_fixup(struct denali_nand_info *denali) | |||
| 1145 | 989 | ||
| 1146 | static int denali_attach_chip(struct nand_chip *chip) | 990 | static int denali_attach_chip(struct nand_chip *chip) |
| 1147 | { | 991 | { |
| 992 | struct denali_controller *denali = to_denali_controller(chip); | ||
| 1148 | struct mtd_info *mtd = nand_to_mtd(chip); | 993 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 1149 | struct denali_nand_info *denali = mtd_to_denali(mtd); | ||
| 1150 | int ret; | 994 | int ret; |
| 1151 | 995 | ||
| 1152 | if (ioread32(denali->reg + FEATURES) & FEATURES__DMA) | ||
| 1153 | denali->dma_avail = 1; | ||
| 1154 | |||
| 1155 | if (denali->dma_avail) { | ||
| 1156 | int dma_bit = denali->caps & DENALI_CAP_DMA_64BIT ? 64 : 32; | ||
| 1157 | |||
| 1158 | ret = dma_set_mask(denali->dev, DMA_BIT_MASK(dma_bit)); | ||
| 1159 | if (ret) { | ||
| 1160 | dev_info(denali->dev, | ||
| 1161 | "Failed to set DMA mask. Disabling DMA.\n"); | ||
| 1162 | denali->dma_avail = 0; | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | if (denali->dma_avail) { | ||
| 1167 | chip->options |= NAND_USE_BOUNCE_BUFFER; | ||
| 1168 | chip->buf_align = 16; | ||
| 1169 | if (denali->caps & DENALI_CAP_DMA_64BIT) | ||
| 1170 | denali->setup_dma = denali_setup_dma64; | ||
| 1171 | else | ||
| 1172 | denali->setup_dma = denali_setup_dma32; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | chip->bbt_options |= NAND_BBT_USE_FLASH; | ||
| 1176 | chip->bbt_options |= NAND_BBT_NO_OOB; | ||
| 1177 | chip->ecc.mode = NAND_ECC_HW_SYNDROME; | ||
| 1178 | chip->options |= NAND_NO_SUBPAGE_WRITE; | ||
| 1179 | |||
| 1180 | ret = nand_ecc_choose_conf(chip, denali->ecc_caps, | 996 | ret = nand_ecc_choose_conf(chip, denali->ecc_caps, |
| 1181 | mtd->oobsize - denali->oob_skip_bytes); | 997 | mtd->oobsize - denali->oob_skip_bytes); |
| 1182 | if (ret) { | 998 | if (ret) { |
| @@ -1188,123 +1004,230 @@ static int denali_attach_chip(struct nand_chip *chip) | |||
| 1188 | "chosen ECC settings: step=%d, strength=%d, bytes=%d\n", | 1004 | "chosen ECC settings: step=%d, strength=%d, bytes=%d\n", |
| 1189 | chip->ecc.size, chip->ecc.strength, chip->ecc.bytes); | 1005 | chip->ecc.size, chip->ecc.strength, chip->ecc.bytes); |
| 1190 | 1006 | ||
| 1191 | iowrite32(FIELD_PREP(ECC_CORRECTION__ERASE_THRESHOLD, 1) | | 1007 | ret = denali_multidev_fixup(chip); |
| 1192 | FIELD_PREP(ECC_CORRECTION__VALUE, chip->ecc.strength), | 1008 | if (ret) |
| 1193 | denali->reg + ECC_CORRECTION); | 1009 | return ret; |
| 1194 | iowrite32(mtd->erasesize / mtd->writesize, | ||
| 1195 | denali->reg + PAGES_PER_BLOCK); | ||
| 1196 | iowrite32(chip->options & NAND_BUSWIDTH_16 ? 1 : 0, | ||
| 1197 | denali->reg + DEVICE_WIDTH); | ||
| 1198 | iowrite32(chip->options & NAND_ROW_ADDR_3 ? 0 : TWO_ROW_ADDR_CYCLES__FLAG, | ||
| 1199 | denali->reg + TWO_ROW_ADDR_CYCLES); | ||
| 1200 | iowrite32(mtd->writesize, denali->reg + DEVICE_MAIN_AREA_SIZE); | ||
| 1201 | iowrite32(mtd->oobsize, denali->reg + DEVICE_SPARE_AREA_SIZE); | ||
| 1202 | 1010 | ||
| 1203 | iowrite32(chip->ecc.size, denali->reg + CFG_DATA_BLOCK_SIZE); | 1011 | return 0; |
| 1204 | iowrite32(chip->ecc.size, denali->reg + CFG_LAST_DATA_BLOCK_SIZE); | 1012 | } |
| 1205 | /* chip->ecc.steps is set by nand_scan_tail(); not available here */ | ||
| 1206 | iowrite32(mtd->writesize / chip->ecc.size, | ||
| 1207 | denali->reg + CFG_NUM_DATA_BLOCKS); | ||
| 1208 | 1013 | ||
| 1209 | mtd_set_ooblayout(mtd, &denali_ooblayout_ops); | 1014 | static void denali_exec_in8(struct denali_controller *denali, u32 type, |
| 1015 | u8 *buf, unsigned int len) | ||
| 1016 | { | ||
| 1017 | int i; | ||
| 1210 | 1018 | ||
| 1211 | if (chip->options & NAND_BUSWIDTH_16) { | 1019 | for (i = 0; i < len; i++) |
| 1212 | chip->legacy.read_buf = denali_read_buf16; | 1020 | buf[i] = denali->host_read(denali, type | DENALI_BANK(denali)); |
| 1213 | chip->legacy.write_buf = denali_write_buf16; | 1021 | } |
| 1214 | } else { | 1022 | |
| 1215 | chip->legacy.read_buf = denali_read_buf; | 1023 | static void denali_exec_in16(struct denali_controller *denali, u32 type, |
| 1216 | chip->legacy.write_buf = denali_write_buf; | 1024 | u8 *buf, unsigned int len) |
| 1025 | { | ||
| 1026 | u32 data; | ||
| 1027 | int i; | ||
| 1028 | |||
| 1029 | for (i = 0; i < len; i += 2) { | ||
| 1030 | data = denali->host_read(denali, type | DENALI_BANK(denali)); | ||
| 1031 | /* bit 31:24 and 15:8 are used for DDR */ | ||
| 1032 | buf[i] = data; | ||
| 1033 | buf[i + 1] = data >> 16; | ||
| 1217 | } | 1034 | } |
| 1218 | chip->ecc.read_page = denali_read_page; | 1035 | } |
| 1219 | chip->ecc.read_page_raw = denali_read_page_raw; | ||
| 1220 | chip->ecc.write_page = denali_write_page; | ||
| 1221 | chip->ecc.write_page_raw = denali_write_page_raw; | ||
| 1222 | chip->ecc.read_oob = denali_read_oob; | ||
| 1223 | chip->ecc.write_oob = denali_write_oob; | ||
| 1224 | 1036 | ||
| 1225 | ret = denali_multidev_fixup(denali); | 1037 | static void denali_exec_in(struct denali_controller *denali, u32 type, |
| 1226 | if (ret) | 1038 | u8 *buf, unsigned int len, bool width16) |
| 1227 | return ret; | 1039 | { |
| 1040 | if (width16) | ||
| 1041 | denali_exec_in16(denali, type, buf, len); | ||
| 1042 | else | ||
| 1043 | denali_exec_in8(denali, type, buf, len); | ||
| 1044 | } | ||
| 1228 | 1045 | ||
| 1229 | /* | 1046 | static void denali_exec_out8(struct denali_controller *denali, u32 type, |
| 1230 | * This buffer is DMA-mapped by denali_{read,write}_page_raw. Do not | 1047 | const u8 *buf, unsigned int len) |
| 1231 | * use devm_kmalloc() because the memory allocated by devm_ does not | 1048 | { |
| 1232 | * guarantee DMA-safe alignment. | 1049 | int i; |
| 1233 | */ | ||
| 1234 | denali->buf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL); | ||
| 1235 | if (!denali->buf) | ||
| 1236 | return -ENOMEM; | ||
| 1237 | 1050 | ||
| 1238 | return 0; | 1051 | for (i = 0; i < len; i++) |
| 1052 | denali->host_write(denali, type | DENALI_BANK(denali), buf[i]); | ||
| 1239 | } | 1053 | } |
| 1240 | 1054 | ||
| 1241 | static void denali_detach_chip(struct nand_chip *chip) | 1055 | static void denali_exec_out16(struct denali_controller *denali, u32 type, |
| 1056 | const u8 *buf, unsigned int len) | ||
| 1242 | { | 1057 | { |
| 1243 | struct mtd_info *mtd = nand_to_mtd(chip); | 1058 | int i; |
| 1244 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1059 | |
| 1060 | for (i = 0; i < len; i += 2) | ||
| 1061 | denali->host_write(denali, type | DENALI_BANK(denali), | ||
| 1062 | buf[i + 1] << 16 | buf[i]); | ||
| 1063 | } | ||
| 1245 | 1064 | ||
| 1246 | kfree(denali->buf); | 1065 | static void denali_exec_out(struct denali_controller *denali, u32 type, |
| 1066 | const u8 *buf, unsigned int len, bool width16) | ||
| 1067 | { | ||
| 1068 | if (width16) | ||
| 1069 | denali_exec_out16(denali, type, buf, len); | ||
| 1070 | else | ||
| 1071 | denali_exec_out8(denali, type, buf, len); | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static int denali_exec_waitrdy(struct denali_controller *denali) | ||
| 1075 | { | ||
| 1076 | u32 irq_stat; | ||
| 1077 | |||
| 1078 | /* R/B# pin transitioned from low to high? */ | ||
| 1079 | irq_stat = denali_wait_for_irq(denali, INTR__INT_ACT); | ||
| 1080 | |||
| 1081 | /* Just in case nand_operation has multiple NAND_OP_WAITRDY_INSTR. */ | ||
| 1082 | denali_reset_irq(denali); | ||
| 1083 | |||
| 1084 | return irq_stat & INTR__INT_ACT ? 0 : -EIO; | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | static int denali_exec_instr(struct nand_chip *chip, | ||
| 1088 | const struct nand_op_instr *instr) | ||
| 1089 | { | ||
| 1090 | struct denali_controller *denali = to_denali_controller(chip); | ||
| 1091 | |||
| 1092 | switch (instr->type) { | ||
| 1093 | case NAND_OP_CMD_INSTR: | ||
| 1094 | denali_exec_out8(denali, DENALI_MAP11_CMD, | ||
| 1095 | &instr->ctx.cmd.opcode, 1); | ||
| 1096 | return 0; | ||
| 1097 | case NAND_OP_ADDR_INSTR: | ||
| 1098 | denali_exec_out8(denali, DENALI_MAP11_ADDR, | ||
| 1099 | instr->ctx.addr.addrs, | ||
| 1100 | instr->ctx.addr.naddrs); | ||
| 1101 | return 0; | ||
| 1102 | case NAND_OP_DATA_IN_INSTR: | ||
| 1103 | denali_exec_in(denali, DENALI_MAP11_DATA, | ||
| 1104 | instr->ctx.data.buf.in, | ||
| 1105 | instr->ctx.data.len, | ||
| 1106 | !instr->ctx.data.force_8bit && | ||
| 1107 | chip->options & NAND_BUSWIDTH_16); | ||
| 1108 | return 0; | ||
| 1109 | case NAND_OP_DATA_OUT_INSTR: | ||
| 1110 | denali_exec_out(denali, DENALI_MAP11_DATA, | ||
| 1111 | instr->ctx.data.buf.out, | ||
| 1112 | instr->ctx.data.len, | ||
| 1113 | !instr->ctx.data.force_8bit && | ||
| 1114 | chip->options & NAND_BUSWIDTH_16); | ||
| 1115 | return 0; | ||
| 1116 | case NAND_OP_WAITRDY_INSTR: | ||
| 1117 | return denali_exec_waitrdy(denali); | ||
| 1118 | default: | ||
| 1119 | WARN_ONCE(1, "unsupported NAND instruction type: %d\n", | ||
| 1120 | instr->type); | ||
| 1121 | |||
| 1122 | return -EINVAL; | ||
| 1123 | } | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | static int denali_exec_op(struct nand_chip *chip, | ||
| 1127 | const struct nand_operation *op, bool check_only) | ||
| 1128 | { | ||
| 1129 | int i, ret; | ||
| 1130 | |||
| 1131 | if (check_only) | ||
| 1132 | return 0; | ||
| 1133 | |||
| 1134 | denali_select_target(chip, op->cs); | ||
| 1135 | |||
| 1136 | /* | ||
| 1137 | * Some commands contain NAND_OP_WAITRDY_INSTR. | ||
| 1138 | * irq must be cleared here to catch the R/B# interrupt there. | ||
| 1139 | */ | ||
| 1140 | denali_reset_irq(to_denali_controller(chip)); | ||
| 1141 | |||
| 1142 | for (i = 0; i < op->ninstrs; i++) { | ||
| 1143 | ret = denali_exec_instr(chip, &op->instrs[i]); | ||
| 1144 | if (ret) | ||
| 1145 | return ret; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | return 0; | ||
| 1247 | } | 1149 | } |
| 1248 | 1150 | ||
| 1249 | static const struct nand_controller_ops denali_controller_ops = { | 1151 | static const struct nand_controller_ops denali_controller_ops = { |
| 1250 | .attach_chip = denali_attach_chip, | 1152 | .attach_chip = denali_attach_chip, |
| 1251 | .detach_chip = denali_detach_chip, | 1153 | .exec_op = denali_exec_op, |
| 1252 | .setup_data_interface = denali_setup_data_interface, | 1154 | .setup_data_interface = denali_setup_data_interface, |
| 1253 | }; | 1155 | }; |
| 1254 | 1156 | ||
| 1255 | int denali_init(struct denali_nand_info *denali) | 1157 | int denali_chip_init(struct denali_controller *denali, |
| 1158 | struct denali_chip *dchip) | ||
| 1256 | { | 1159 | { |
| 1257 | struct nand_chip *chip = &denali->nand; | 1160 | struct nand_chip *chip = &dchip->chip; |
| 1258 | struct mtd_info *mtd = nand_to_mtd(chip); | 1161 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 1259 | u32 features = ioread32(denali->reg + FEATURES); | 1162 | struct denali_chip *dchip2; |
| 1260 | int ret; | 1163 | int i, j, ret; |
| 1261 | 1164 | ||
| 1262 | mtd->dev.parent = denali->dev; | 1165 | chip->controller = &denali->controller; |
| 1263 | denali_hw_init(denali); | ||
| 1264 | 1166 | ||
| 1265 | init_completion(&denali->complete); | 1167 | /* sanity checks for bank numbers */ |
| 1266 | spin_lock_init(&denali->irq_lock); | 1168 | for (i = 0; i < dchip->nsels; i++) { |
| 1169 | unsigned int bank = dchip->sels[i].bank; | ||
| 1267 | 1170 | ||
| 1268 | denali_clear_irq_all(denali); | 1171 | if (bank >= denali->nbanks) { |
| 1172 | dev_err(denali->dev, "unsupported bank %d\n", bank); | ||
| 1173 | return -EINVAL; | ||
| 1174 | } | ||
| 1269 | 1175 | ||
| 1270 | ret = devm_request_irq(denali->dev, denali->irq, denali_isr, | 1176 | for (j = 0; j < i; j++) { |
| 1271 | IRQF_SHARED, DENALI_NAND_NAME, denali); | 1177 | if (bank == dchip->sels[j].bank) { |
| 1272 | if (ret) { | 1178 | dev_err(denali->dev, |
| 1273 | dev_err(denali->dev, "Unable to request IRQ\n"); | 1179 | "bank %d is assigned twice in the same chip\n", |
| 1274 | return ret; | 1180 | bank); |
| 1275 | } | 1181 | return -EINVAL; |
| 1182 | } | ||
| 1183 | } | ||
| 1276 | 1184 | ||
| 1277 | denali_enable_irq(denali); | 1185 | list_for_each_entry(dchip2, &denali->chips, node) { |
| 1186 | for (j = 0; j < dchip2->nsels; j++) { | ||
| 1187 | if (bank == dchip2->sels[j].bank) { | ||
| 1188 | dev_err(denali->dev, | ||
| 1189 | "bank %d is already used\n", | ||
| 1190 | bank); | ||
| 1191 | return -EINVAL; | ||
| 1192 | } | ||
| 1193 | } | ||
| 1194 | } | ||
| 1195 | } | ||
| 1278 | 1196 | ||
| 1279 | denali->active_bank = DENALI_INVALID_BANK; | 1197 | mtd->dev.parent = denali->dev; |
| 1280 | 1198 | ||
| 1281 | nand_set_flash_node(chip, denali->dev->of_node); | 1199 | /* |
| 1282 | /* Fallback to the default name if DT did not give "label" property */ | 1200 | * Fallback to the default name if DT did not give "label" property. |
| 1283 | if (!mtd->name) | 1201 | * Use "label" property if multiple chips are connected. |
| 1202 | */ | ||
| 1203 | if (!mtd->name && list_empty(&denali->chips)) | ||
| 1284 | mtd->name = "denali-nand"; | 1204 | mtd->name = "denali-nand"; |
| 1285 | 1205 | ||
| 1286 | chip->legacy.select_chip = denali_select_chip; | 1206 | if (denali->dma_avail) { |
| 1287 | chip->legacy.read_byte = denali_read_byte; | 1207 | chip->options |= NAND_USE_BOUNCE_BUFFER; |
| 1288 | chip->legacy.write_byte = denali_write_byte; | 1208 | chip->buf_align = 16; |
| 1289 | chip->legacy.cmd_ctrl = denali_cmd_ctrl; | ||
| 1290 | chip->legacy.waitfunc = denali_waitfunc; | ||
| 1291 | |||
| 1292 | if (features & FEATURES__INDEX_ADDR) { | ||
| 1293 | denali->host_read = denali_indexed_read; | ||
| 1294 | denali->host_write = denali_indexed_write; | ||
| 1295 | } else { | ||
| 1296 | denali->host_read = denali_direct_read; | ||
| 1297 | denali->host_write = denali_direct_write; | ||
| 1298 | } | 1209 | } |
| 1299 | 1210 | ||
| 1300 | /* clk rate info is needed for setup_data_interface */ | 1211 | /* clk rate info is needed for setup_data_interface */ |
| 1301 | if (!denali->clk_rate || !denali->clk_x_rate) | 1212 | if (!denali->clk_rate || !denali->clk_x_rate) |
| 1302 | chip->options |= NAND_KEEP_TIMINGS; | 1213 | chip->options |= NAND_KEEP_TIMINGS; |
| 1303 | 1214 | ||
| 1304 | chip->legacy.dummy_controller.ops = &denali_controller_ops; | 1215 | chip->bbt_options |= NAND_BBT_USE_FLASH; |
| 1305 | ret = nand_scan(chip, denali->max_banks); | 1216 | chip->bbt_options |= NAND_BBT_NO_OOB; |
| 1217 | chip->options |= NAND_NO_SUBPAGE_WRITE; | ||
| 1218 | chip->ecc.mode = NAND_ECC_HW_SYNDROME; | ||
| 1219 | chip->ecc.read_page = denali_read_page; | ||
| 1220 | chip->ecc.write_page = denali_write_page; | ||
| 1221 | chip->ecc.read_page_raw = denali_read_page_raw; | ||
| 1222 | chip->ecc.write_page_raw = denali_write_page_raw; | ||
| 1223 | chip->ecc.read_oob = denali_read_oob; | ||
| 1224 | chip->ecc.write_oob = denali_write_oob; | ||
| 1225 | |||
| 1226 | mtd_set_ooblayout(mtd, &denali_ooblayout_ops); | ||
| 1227 | |||
| 1228 | ret = nand_scan(chip, dchip->nsels); | ||
| 1306 | if (ret) | 1229 | if (ret) |
| 1307 | goto disable_irq; | 1230 | return ret; |
| 1308 | 1231 | ||
| 1309 | ret = mtd_device_register(mtd, NULL, 0); | 1232 | ret = mtd_device_register(mtd, NULL, 0); |
| 1310 | if (ret) { | 1233 | if (ret) { |
| @@ -1312,20 +1235,111 @@ int denali_init(struct denali_nand_info *denali) | |||
| 1312 | goto cleanup_nand; | 1235 | goto cleanup_nand; |
| 1313 | } | 1236 | } |
| 1314 | 1237 | ||
| 1238 | list_add_tail(&dchip->node, &denali->chips); | ||
| 1239 | |||
| 1315 | return 0; | 1240 | return 0; |
| 1316 | 1241 | ||
| 1317 | cleanup_nand: | 1242 | cleanup_nand: |
| 1318 | nand_cleanup(chip); | 1243 | nand_cleanup(chip); |
| 1319 | disable_irq: | ||
| 1320 | denali_disable_irq(denali); | ||
| 1321 | 1244 | ||
| 1322 | return ret; | 1245 | return ret; |
| 1323 | } | 1246 | } |
| 1247 | EXPORT_SYMBOL_GPL(denali_chip_init); | ||
| 1248 | |||
| 1249 | int denali_init(struct denali_controller *denali) | ||
| 1250 | { | ||
| 1251 | u32 features = ioread32(denali->reg + FEATURES); | ||
| 1252 | int ret; | ||
| 1253 | |||
| 1254 | nand_controller_init(&denali->controller); | ||
| 1255 | denali->controller.ops = &denali_controller_ops; | ||
| 1256 | init_completion(&denali->complete); | ||
| 1257 | spin_lock_init(&denali->irq_lock); | ||
| 1258 | INIT_LIST_HEAD(&denali->chips); | ||
| 1259 | denali->active_bank = DENALI_INVALID_BANK; | ||
| 1260 | |||
| 1261 | /* | ||
| 1262 | * The REVISION register may not be reliable. Platforms are allowed to | ||
| 1263 | * override it. | ||
| 1264 | */ | ||
| 1265 | if (!denali->revision) | ||
| 1266 | denali->revision = swab16(ioread32(denali->reg + REVISION)); | ||
| 1267 | |||
| 1268 | denali->nbanks = 1 << FIELD_GET(FEATURES__N_BANKS, features); | ||
| 1269 | |||
| 1270 | /* the encoding changed from rev 5.0 to 5.1 */ | ||
| 1271 | if (denali->revision < 0x0501) | ||
| 1272 | denali->nbanks <<= 1; | ||
| 1273 | |||
| 1274 | if (features & FEATURES__DMA) | ||
| 1275 | denali->dma_avail = true; | ||
| 1276 | |||
| 1277 | if (denali->dma_avail) { | ||
| 1278 | int dma_bit = denali->caps & DENALI_CAP_DMA_64BIT ? 64 : 32; | ||
| 1279 | |||
| 1280 | ret = dma_set_mask(denali->dev, DMA_BIT_MASK(dma_bit)); | ||
| 1281 | if (ret) { | ||
| 1282 | dev_info(denali->dev, | ||
| 1283 | "Failed to set DMA mask. Disabling DMA.\n"); | ||
| 1284 | denali->dma_avail = false; | ||
| 1285 | } | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | if (denali->dma_avail) { | ||
| 1289 | if (denali->caps & DENALI_CAP_DMA_64BIT) | ||
| 1290 | denali->setup_dma = denali_setup_dma64; | ||
| 1291 | else | ||
| 1292 | denali->setup_dma = denali_setup_dma32; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | if (features & FEATURES__INDEX_ADDR) { | ||
| 1296 | denali->host_read = denali_indexed_read; | ||
| 1297 | denali->host_write = denali_indexed_write; | ||
| 1298 | } else { | ||
| 1299 | denali->host_read = denali_direct_read; | ||
| 1300 | denali->host_write = denali_direct_write; | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | /* | ||
| 1304 | * Set how many bytes should be skipped before writing data in OOB. | ||
| 1305 | * If a non-zero value has already been set (by firmware or something), | ||
| 1306 | * just use it. Otherwise, set the driver's default. | ||
| 1307 | */ | ||
| 1308 | denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); | ||
| 1309 | if (!denali->oob_skip_bytes) { | ||
| 1310 | denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; | ||
| 1311 | iowrite32(denali->oob_skip_bytes, | ||
| 1312 | denali->reg + SPARE_AREA_SKIP_BYTES); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | iowrite32(0, denali->reg + TRANSFER_SPARE_REG); | ||
| 1316 | iowrite32(GENMASK(denali->nbanks - 1, 0), denali->reg + RB_PIN_ENABLED); | ||
| 1317 | iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); | ||
| 1318 | iowrite32(ECC_ENABLE__FLAG, denali->reg + ECC_ENABLE); | ||
| 1319 | iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); | ||
| 1320 | |||
| 1321 | denali_clear_irq_all(denali); | ||
| 1322 | |||
| 1323 | ret = devm_request_irq(denali->dev, denali->irq, denali_isr, | ||
| 1324 | IRQF_SHARED, DENALI_NAND_NAME, denali); | ||
| 1325 | if (ret) { | ||
| 1326 | dev_err(denali->dev, "Unable to request IRQ\n"); | ||
| 1327 | return ret; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | denali_enable_irq(denali); | ||
| 1331 | |||
| 1332 | return 0; | ||
| 1333 | } | ||
| 1324 | EXPORT_SYMBOL(denali_init); | 1334 | EXPORT_SYMBOL(denali_init); |
| 1325 | 1335 | ||
| 1326 | void denali_remove(struct denali_nand_info *denali) | 1336 | void denali_remove(struct denali_controller *denali) |
| 1327 | { | 1337 | { |
| 1328 | nand_release(&denali->nand); | 1338 | struct denali_chip *dchip; |
| 1339 | |||
| 1340 | list_for_each_entry(dchip, &denali->chips, node) | ||
| 1341 | nand_release(&dchip->chip); | ||
| 1342 | |||
| 1329 | denali_disable_irq(denali); | 1343 | denali_disable_irq(denali); |
| 1330 | } | 1344 | } |
| 1331 | EXPORT_SYMBOL(denali_remove); | 1345 | EXPORT_SYMBOL(denali_remove); |
diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h index c8c2620fc736..e5cdcda56d14 100644 --- a/drivers/mtd/nand/raw/denali.h +++ b/drivers/mtd/nand/raw/denali.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/bits.h> | 10 | #include <linux/bits.h> |
| 11 | #include <linux/completion.h> | 11 | #include <linux/completion.h> |
| 12 | #include <linux/list.h> | ||
| 12 | #include <linux/mtd/rawnand.h> | 13 | #include <linux/mtd/rawnand.h> |
| 13 | #include <linux/spinlock_types.h> | 14 | #include <linux/spinlock_types.h> |
| 14 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| @@ -290,38 +291,108 @@ | |||
| 290 | #define CHNL_ACTIVE__CHANNEL2 BIT(2) | 291 | #define CHNL_ACTIVE__CHANNEL2 BIT(2) |
| 291 | #define CHNL_ACTIVE__CHANNEL3 BIT(3) | 292 | #define CHNL_ACTIVE__CHANNEL3 BIT(3) |
| 292 | 293 | ||
| 293 | struct denali_nand_info { | 294 | /** |
| 294 | struct nand_chip nand; | 295 | * struct denali_chip_sel - per-CS data of Denali NAND |
| 295 | unsigned long clk_rate; /* core clock rate */ | 296 | * |
| 296 | unsigned long clk_x_rate; /* bus interface clock rate */ | 297 | * @bank: bank id of the controller this CS is connected to |
| 297 | int active_bank; /* currently selected bank */ | 298 | * @hwhr2_and_we_2_re: value of timing register HWHR2_AND_WE_2_RE |
| 299 | * @tcwaw_and_addr_2_data: value of timing register TCWAW_AND_ADDR_2_DATA | ||
| 300 | * @re_2_we: value of timing register RE_2_WE | ||
| 301 | * @acc_clks: value of timing register ACC_CLKS | ||
| 302 | * @rdwr_en_lo_cnt: value of timing register RDWR_EN_LO_CNT | ||
| 303 | * @rdwr_en_hi_cnt: value of timing register RDWR_EN_HI_CNT | ||
| 304 | * @cs_setup_cnt: value of timing register CS_SETUP_CNT | ||
| 305 | * @re_2_re: value of timing register RE_2_RE | ||
| 306 | */ | ||
| 307 | struct denali_chip_sel { | ||
| 308 | int bank; | ||
| 309 | u32 hwhr2_and_we_2_re; | ||
| 310 | u32 tcwaw_and_addr_2_data; | ||
| 311 | u32 re_2_we; | ||
| 312 | u32 acc_clks; | ||
| 313 | u32 rdwr_en_lo_cnt; | ||
| 314 | u32 rdwr_en_hi_cnt; | ||
| 315 | u32 cs_setup_cnt; | ||
| 316 | u32 re_2_re; | ||
| 317 | }; | ||
| 318 | |||
| 319 | /** | ||
| 320 | * struct denali_chip - per-chip data of Denali NAND | ||
| 321 | * | ||
| 322 | * @chip: base NAND chip structure | ||
| 323 | * @node: node to be used to associate this chip with the controller | ||
| 324 | * @nsels: the number of CS lines of this chip | ||
| 325 | * @sels: the array of per-cs data | ||
| 326 | */ | ||
| 327 | struct denali_chip { | ||
| 328 | struct nand_chip chip; | ||
| 329 | struct list_head node; | ||
| 330 | unsigned int nsels; | ||
| 331 | struct denali_chip_sel sels[0]; | ||
| 332 | }; | ||
| 333 | |||
| 334 | /** | ||
| 335 | * struct denali_controller - Denali NAND controller data | ||
| 336 | * | ||
| 337 | * @controller: base NAND controller structure | ||
| 338 | * @dev: device | ||
| 339 | * @chips: the list of chips attached to this controller | ||
| 340 | * @clk_rate: frequency of core clock | ||
| 341 | * @clk_x_rate: frequency of bus interface clock | ||
| 342 | * @reg: base of Register Interface | ||
| 343 | * @host: base of Host Data/Command interface | ||
| 344 | * @complete: completion used to wait for interrupts | ||
| 345 | * @irq: interrupt number | ||
| 346 | * @irq_mask: interrupt bits the controller is waiting for | ||
| 347 | * @irq_status: interrupt bits of events that have happened | ||
| 348 | * @irq_lock: lock to protect @irq_mask and @irq_status | ||
| 349 | * @dma_avail: set if DMA engine is available | ||
| 350 | * @devs_per_cs: number of devices connected in parallel | ||
| 351 | * @oob_skip_bytes: number of bytes in OOB skipped by the ECC engine | ||
| 352 | * @active_bank: active bank id | ||
| 353 | * @nbanks: the number of banks supported by this controller | ||
| 354 | * @revision: IP revision | ||
| 355 | * @caps: controller capabilities that cannot be detected run-time | ||
| 356 | * @ecc_caps: ECC engine capabilities | ||
| 357 | * @host_read: callback for read access of Host Data/Command Interface | ||
| 358 | * @host_write: callback for write access of Host Data/Command Interface | ||
| 359 | * @setup_dma: callback for setup of the Data DMA | ||
| 360 | */ | ||
| 361 | struct denali_controller { | ||
| 362 | struct nand_controller controller; | ||
| 298 | struct device *dev; | 363 | struct device *dev; |
| 299 | void __iomem *reg; /* Register Interface */ | 364 | struct list_head chips; |
| 300 | void __iomem *host; /* Host Data/Command Interface */ | 365 | unsigned long clk_rate; |
| 366 | unsigned long clk_x_rate; | ||
| 367 | void __iomem *reg; | ||
| 368 | void __iomem *host; | ||
| 301 | struct completion complete; | 369 | struct completion complete; |
| 302 | spinlock_t irq_lock; /* protect irq_mask and irq_status */ | ||
| 303 | u32 irq_mask; /* interrupts we are waiting for */ | ||
| 304 | u32 irq_status; /* interrupts that have happened */ | ||
| 305 | int irq; | 370 | int irq; |
| 306 | void *buf; /* for syndrome layout conversion */ | 371 | u32 irq_mask; |
| 307 | int dma_avail; /* can support DMA? */ | 372 | u32 irq_status; |
| 308 | int devs_per_cs; /* devices connected in parallel */ | 373 | spinlock_t irq_lock; |
| 309 | int oob_skip_bytes; /* number of bytes reserved for BBM */ | 374 | bool dma_avail; |
| 310 | int max_banks; | 375 | int devs_per_cs; |
| 311 | unsigned int revision; /* IP revision */ | 376 | int oob_skip_bytes; |
| 312 | unsigned int caps; /* IP capability (or quirk) */ | 377 | int active_bank; |
| 378 | int nbanks; | ||
| 379 | unsigned int revision; | ||
| 380 | unsigned int caps; | ||
| 313 | const struct nand_ecc_caps *ecc_caps; | 381 | const struct nand_ecc_caps *ecc_caps; |
| 314 | u32 (*host_read)(struct denali_nand_info *denali, u32 addr); | 382 | u32 (*host_read)(struct denali_controller *denali, u32 addr); |
| 315 | void (*host_write)(struct denali_nand_info *denali, u32 addr, u32 data); | 383 | void (*host_write)(struct denali_controller *denali, u32 addr, |
| 316 | void (*setup_dma)(struct denali_nand_info *denali, dma_addr_t dma_addr, | 384 | u32 data); |
| 317 | int page, int write); | 385 | void (*setup_dma)(struct denali_controller *denali, dma_addr_t dma_addr, |
| 386 | int page, bool write); | ||
| 318 | }; | 387 | }; |
| 319 | 388 | ||
| 320 | #define DENALI_CAP_HW_ECC_FIXUP BIT(0) | 389 | #define DENALI_CAP_HW_ECC_FIXUP BIT(0) |
| 321 | #define DENALI_CAP_DMA_64BIT BIT(1) | 390 | #define DENALI_CAP_DMA_64BIT BIT(1) |
| 322 | 391 | ||
| 323 | int denali_calc_ecc_bytes(int step_size, int strength); | 392 | int denali_calc_ecc_bytes(int step_size, int strength); |
| 324 | int denali_init(struct denali_nand_info *denali); | 393 | int denali_chip_init(struct denali_controller *denali, |
| 325 | void denali_remove(struct denali_nand_info *denali); | 394 | struct denali_chip *dchip); |
| 395 | int denali_init(struct denali_controller *denali); | ||
| 396 | void denali_remove(struct denali_controller *denali); | ||
| 326 | 397 | ||
| 327 | #endif /* __DENALI_H__ */ | 398 | #endif /* __DENALI_H__ */ |
diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c index 0b5ae2418815..5e14836f6bd5 100644 --- a/drivers/mtd/nand/raw/denali_dt.c +++ b/drivers/mtd/nand/raw/denali_dt.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | #include "denali.h" | 18 | #include "denali.h" |
| 19 | 19 | ||
| 20 | struct denali_dt { | 20 | struct denali_dt { |
| 21 | struct denali_nand_info denali; | 21 | struct denali_controller controller; |
| 22 | struct clk *clk; /* core clock */ | 22 | struct clk *clk; /* core clock */ |
| 23 | struct clk *clk_x; /* bus interface clock */ | 23 | struct clk *clk_x; /* bus interface clock */ |
| 24 | struct clk *clk_ecc; /* ECC circuit clock */ | 24 | struct clk *clk_ecc; /* ECC circuit clock */ |
| @@ -71,19 +71,92 @@ static const struct of_device_id denali_nand_dt_ids[] = { | |||
| 71 | }; | 71 | }; |
| 72 | MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); | 72 | MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); |
| 73 | 73 | ||
| 74 | static int denali_dt_chip_init(struct denali_controller *denali, | ||
| 75 | struct device_node *chip_np) | ||
| 76 | { | ||
| 77 | struct denali_chip *dchip; | ||
| 78 | u32 bank; | ||
| 79 | int nsels, i, ret; | ||
| 80 | |||
| 81 | nsels = of_property_count_u32_elems(chip_np, "reg"); | ||
| 82 | if (nsels < 0) | ||
| 83 | return nsels; | ||
| 84 | |||
| 85 | dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels), | ||
| 86 | GFP_KERNEL); | ||
| 87 | if (!dchip) | ||
| 88 | return -ENOMEM; | ||
| 89 | |||
| 90 | dchip->nsels = nsels; | ||
| 91 | |||
| 92 | for (i = 0; i < nsels; i++) { | ||
| 93 | ret = of_property_read_u32_index(chip_np, "reg", i, &bank); | ||
| 94 | if (ret) | ||
| 95 | return ret; | ||
| 96 | |||
| 97 | dchip->sels[i].bank = bank; | ||
| 98 | |||
| 99 | nand_set_flash_node(&dchip->chip, chip_np); | ||
| 100 | } | ||
| 101 | |||
| 102 | return denali_chip_init(denali, dchip); | ||
| 103 | } | ||
| 104 | |||
| 105 | /* Backward compatibility for old platforms */ | ||
| 106 | static int denali_dt_legacy_chip_init(struct denali_controller *denali) | ||
| 107 | { | ||
| 108 | struct denali_chip *dchip; | ||
| 109 | int nsels, i; | ||
| 110 | |||
| 111 | nsels = denali->nbanks; | ||
| 112 | |||
| 113 | dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels), | ||
| 114 | GFP_KERNEL); | ||
| 115 | if (!dchip) | ||
| 116 | return -ENOMEM; | ||
| 117 | |||
| 118 | dchip->nsels = nsels; | ||
| 119 | |||
| 120 | for (i = 0; i < nsels; i++) | ||
| 121 | dchip->sels[i].bank = i; | ||
| 122 | |||
| 123 | nand_set_flash_node(&dchip->chip, denali->dev->of_node); | ||
| 124 | |||
| 125 | return denali_chip_init(denali, dchip); | ||
| 126 | } | ||
| 127 | |||
| 128 | /* | ||
| 129 | * Check the DT binding. | ||
| 130 | * The new binding expects chip subnodes in the controller node. | ||
| 131 | * So, #address-cells = <1>; #size-cells = <0>; are required. | ||
| 132 | * Check the #size-cells to distinguish the binding. | ||
| 133 | */ | ||
| 134 | static bool denali_dt_is_legacy_binding(struct device_node *np) | ||
| 135 | { | ||
| 136 | u32 cells; | ||
| 137 | int ret; | ||
| 138 | |||
| 139 | ret = of_property_read_u32(np, "#size-cells", &cells); | ||
| 140 | if (ret) | ||
| 141 | return true; | ||
| 142 | |||
| 143 | return cells != 0; | ||
| 144 | } | ||
| 145 | |||
| 74 | static int denali_dt_probe(struct platform_device *pdev) | 146 | static int denali_dt_probe(struct platform_device *pdev) |
| 75 | { | 147 | { |
| 76 | struct device *dev = &pdev->dev; | 148 | struct device *dev = &pdev->dev; |
| 77 | struct resource *res; | 149 | struct resource *res; |
| 78 | struct denali_dt *dt; | 150 | struct denali_dt *dt; |
| 79 | const struct denali_dt_data *data; | 151 | const struct denali_dt_data *data; |
| 80 | struct denali_nand_info *denali; | 152 | struct denali_controller *denali; |
| 153 | struct device_node *np; | ||
| 81 | int ret; | 154 | int ret; |
| 82 | 155 | ||
| 83 | dt = devm_kzalloc(dev, sizeof(*dt), GFP_KERNEL); | 156 | dt = devm_kzalloc(dev, sizeof(*dt), GFP_KERNEL); |
| 84 | if (!dt) | 157 | if (!dt) |
| 85 | return -ENOMEM; | 158 | return -ENOMEM; |
| 86 | denali = &dt->denali; | 159 | denali = &dt->controller; |
| 87 | 160 | ||
| 88 | data = of_device_get_match_data(dev); | 161 | data = of_device_get_match_data(dev); |
| 89 | if (data) { | 162 | if (data) { |
| @@ -140,9 +213,26 @@ static int denali_dt_probe(struct platform_device *pdev) | |||
| 140 | if (ret) | 213 | if (ret) |
| 141 | goto out_disable_clk_ecc; | 214 | goto out_disable_clk_ecc; |
| 142 | 215 | ||
| 216 | if (denali_dt_is_legacy_binding(dev->of_node)) { | ||
| 217 | ret = denali_dt_legacy_chip_init(denali); | ||
| 218 | if (ret) | ||
| 219 | goto out_remove_denali; | ||
| 220 | } else { | ||
| 221 | for_each_child_of_node(dev->of_node, np) { | ||
| 222 | ret = denali_dt_chip_init(denali, np); | ||
| 223 | if (ret) { | ||
| 224 | of_node_put(np); | ||
| 225 | goto out_remove_denali; | ||
| 226 | } | ||
| 227 | } | ||
| 228 | } | ||
| 229 | |||
| 143 | platform_set_drvdata(pdev, dt); | 230 | platform_set_drvdata(pdev, dt); |
| 231 | |||
| 144 | return 0; | 232 | return 0; |
| 145 | 233 | ||
| 234 | out_remove_denali: | ||
| 235 | denali_remove(denali); | ||
| 146 | out_disable_clk_ecc: | 236 | out_disable_clk_ecc: |
| 147 | clk_disable_unprepare(dt->clk_ecc); | 237 | clk_disable_unprepare(dt->clk_ecc); |
| 148 | out_disable_clk_x: | 238 | out_disable_clk_x: |
| @@ -157,7 +247,7 @@ static int denali_dt_remove(struct platform_device *pdev) | |||
| 157 | { | 247 | { |
| 158 | struct denali_dt *dt = platform_get_drvdata(pdev); | 248 | struct denali_dt *dt = platform_get_drvdata(pdev); |
| 159 | 249 | ||
| 160 | denali_remove(&dt->denali); | 250 | denali_remove(&dt->controller); |
| 161 | clk_disable_unprepare(dt->clk_ecc); | 251 | clk_disable_unprepare(dt->clk_ecc); |
| 162 | clk_disable_unprepare(dt->clk_x); | 252 | clk_disable_unprepare(dt->clk_x); |
| 163 | clk_disable_unprepare(dt->clk); | 253 | clk_disable_unprepare(dt->clk); |
diff --git a/drivers/mtd/nand/raw/denali_pci.c b/drivers/mtd/nand/raw/denali_pci.c index 48e9ac54ad53..d62aa5271753 100644 --- a/drivers/mtd/nand/raw/denali_pci.c +++ b/drivers/mtd/nand/raw/denali_pci.c | |||
| @@ -29,10 +29,11 @@ NAND_ECC_CAPS_SINGLE(denali_pci_ecc_caps, denali_calc_ecc_bytes, 512, 8, 15); | |||
| 29 | 29 | ||
| 30 | static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 30 | static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
| 31 | { | 31 | { |
| 32 | int ret; | ||
| 33 | resource_size_t csr_base, mem_base; | 32 | resource_size_t csr_base, mem_base; |
| 34 | unsigned long csr_len, mem_len; | 33 | unsigned long csr_len, mem_len; |
| 35 | struct denali_nand_info *denali; | 34 | struct denali_controller *denali; |
| 35 | struct denali_chip *dchip; | ||
| 36 | int nsels, ret, i; | ||
| 36 | 37 | ||
| 37 | denali = devm_kzalloc(&dev->dev, sizeof(*denali), GFP_KERNEL); | 38 | denali = devm_kzalloc(&dev->dev, sizeof(*denali), GFP_KERNEL); |
| 38 | if (!denali) | 39 | if (!denali) |
| @@ -64,7 +65,6 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 64 | denali->dev = &dev->dev; | 65 | denali->dev = &dev->dev; |
| 65 | denali->irq = dev->irq; | 66 | denali->irq = dev->irq; |
| 66 | denali->ecc_caps = &denali_pci_ecc_caps; | 67 | denali->ecc_caps = &denali_pci_ecc_caps; |
| 67 | denali->nand.ecc.options |= NAND_ECC_MAXIMIZE; | ||
| 68 | denali->clk_rate = 50000000; /* 50 MHz */ | 68 | denali->clk_rate = 50000000; /* 50 MHz */ |
| 69 | denali->clk_x_rate = 200000000; /* 200 MHz */ | 69 | denali->clk_x_rate = 200000000; /* 200 MHz */ |
| 70 | 70 | ||
| @@ -84,27 +84,49 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 84 | if (!denali->host) { | 84 | if (!denali->host) { |
| 85 | dev_err(&dev->dev, "Spectra: ioremap_nocache failed!"); | 85 | dev_err(&dev->dev, "Spectra: ioremap_nocache failed!"); |
| 86 | ret = -ENOMEM; | 86 | ret = -ENOMEM; |
| 87 | goto failed_remap_reg; | 87 | goto out_unmap_reg; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | ret = denali_init(denali); | 90 | ret = denali_init(denali); |
| 91 | if (ret) | 91 | if (ret) |
| 92 | goto failed_remap_mem; | 92 | goto out_unmap_host; |
| 93 | |||
| 94 | nsels = denali->nbanks; | ||
| 95 | |||
| 96 | dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels), | ||
| 97 | GFP_KERNEL); | ||
| 98 | if (!dchip) { | ||
| 99 | ret = -ENOMEM; | ||
| 100 | goto out_remove_denali; | ||
| 101 | } | ||
| 102 | |||
| 103 | dchip->chip.ecc.options |= NAND_ECC_MAXIMIZE; | ||
| 104 | |||
| 105 | dchip->nsels = nsels; | ||
| 106 | |||
| 107 | for (i = 0; i < nsels; i++) | ||
| 108 | dchip->sels[i].bank = i; | ||
| 109 | |||
| 110 | ret = denali_chip_init(denali, dchip); | ||
| 111 | if (ret) | ||
| 112 | goto out_remove_denali; | ||
| 93 | 113 | ||
| 94 | pci_set_drvdata(dev, denali); | 114 | pci_set_drvdata(dev, denali); |
| 95 | 115 | ||
| 96 | return 0; | 116 | return 0; |
| 97 | 117 | ||
| 98 | failed_remap_mem: | 118 | out_remove_denali: |
| 119 | denali_remove(denali); | ||
| 120 | out_unmap_host: | ||
| 99 | iounmap(denali->host); | 121 | iounmap(denali->host); |
| 100 | failed_remap_reg: | 122 | out_unmap_reg: |
| 101 | iounmap(denali->reg); | 123 | iounmap(denali->reg); |
| 102 | return ret; | 124 | return ret; |
| 103 | } | 125 | } |
| 104 | 126 | ||
| 105 | static void denali_pci_remove(struct pci_dev *dev) | 127 | static void denali_pci_remove(struct pci_dev *dev) |
| 106 | { | 128 | { |
| 107 | struct denali_nand_info *denali = pci_get_drvdata(dev); | 129 | struct denali_controller *denali = pci_get_drvdata(dev); |
| 108 | 130 | ||
| 109 | denali_remove(denali); | 131 | denali_remove(denali); |
| 110 | iounmap(denali->reg); | 132 | iounmap(denali->reg); |
diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 53f57e0f007e..f430c4bf0323 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c | |||
| @@ -1028,6 +1028,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio | |||
| 1028 | { | 1028 | { |
| 1029 | struct nand_chip *this = mtd_to_nand(mtd); | 1029 | struct nand_chip *this = mtd_to_nand(mtd); |
| 1030 | struct doc_priv *doc = nand_get_controller_data(this); | 1030 | struct doc_priv *doc = nand_get_controller_data(this); |
| 1031 | struct nand_memory_organization *memorg; | ||
| 1031 | int ret = 0; | 1032 | int ret = 0; |
| 1032 | u_char *buf; | 1033 | u_char *buf; |
| 1033 | struct NFTLMediaHeader *mh; | 1034 | struct NFTLMediaHeader *mh; |
| @@ -1036,6 +1037,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio | |||
| 1036 | unsigned blocks, maxblocks; | 1037 | unsigned blocks, maxblocks; |
| 1037 | int offs, numheaders; | 1038 | int offs, numheaders; |
| 1038 | 1039 | ||
| 1040 | memorg = nanddev_get_memorg(&this->base); | ||
| 1041 | |||
| 1039 | buf = kmalloc(mtd->writesize, GFP_KERNEL); | 1042 | buf = kmalloc(mtd->writesize, GFP_KERNEL); |
| 1040 | if (!buf) { | 1043 | if (!buf) { |
| 1041 | return 0; | 1044 | return 0; |
| @@ -1082,6 +1085,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio | |||
| 1082 | implementation of the NAND layer. */ | 1085 | implementation of the NAND layer. */ |
| 1083 | if (mh->UnitSizeFactor != 0xff) { | 1086 | if (mh->UnitSizeFactor != 0xff) { |
| 1084 | this->bbt_erase_shift += (0xff - mh->UnitSizeFactor); | 1087 | this->bbt_erase_shift += (0xff - mh->UnitSizeFactor); |
| 1088 | memorg->pages_per_eraseblock <<= (0xff - mh->UnitSizeFactor); | ||
| 1085 | mtd->erasesize <<= (0xff - mh->UnitSizeFactor); | 1089 | mtd->erasesize <<= (0xff - mh->UnitSizeFactor); |
| 1086 | pr_info("Setting virtual erase size to %d\n", mtd->erasesize); | 1090 | pr_info("Setting virtual erase size to %d\n", mtd->erasesize); |
| 1087 | blocks = mtd->size >> this->bbt_erase_shift; | 1091 | blocks = mtd->size >> this->bbt_erase_shift; |
| @@ -1287,7 +1291,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) | |||
| 1287 | struct doc_priv *doc = nand_get_controller_data(this); | 1291 | struct doc_priv *doc = nand_get_controller_data(this); |
| 1288 | struct mtd_partition parts[5]; | 1292 | struct mtd_partition parts[5]; |
| 1289 | 1293 | ||
| 1290 | if (this->numchips > doc->chips_per_floor) { | 1294 | if (nanddev_ntargets(&this->base) > doc->chips_per_floor) { |
| 1291 | pr_err("Multi-floor INFTL devices not yet supported.\n"); | 1295 | pr_err("Multi-floor INFTL devices not yet supported.\n"); |
| 1292 | return -EIO; | 1296 | return -EIO; |
| 1293 | } | 1297 | } |
| @@ -1477,6 +1481,7 @@ static int __init doc_probe(unsigned long physadr) | |||
| 1477 | break; | 1481 | break; |
| 1478 | case DOC_ChipID_DocMilPlus32: | 1482 | case DOC_ChipID_DocMilPlus32: |
| 1479 | pr_err("DiskOnChip Millennium Plus 32MB is not supported, ignoring.\n"); | 1483 | pr_err("DiskOnChip Millennium Plus 32MB is not supported, ignoring.\n"); |
| 1484 | /* fall through */ | ||
| 1480 | default: | 1485 | default: |
| 1481 | ret = -ENODEV; | 1486 | ret = -ENODEV; |
| 1482 | goto notfound; | 1487 | goto notfound; |
diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 70f0d2b450ea..423828ff68e6 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c | |||
| @@ -355,6 +355,15 @@ static void fsl_elbc_cmdfunc(struct nand_chip *chip, unsigned int command, | |||
| 355 | fsl_elbc_run_command(mtd); | 355 | fsl_elbc_run_command(mtd); |
| 356 | return; | 356 | return; |
| 357 | 357 | ||
| 358 | /* RNDOUT moves the pointer inside the page */ | ||
| 359 | case NAND_CMD_RNDOUT: | ||
| 360 | dev_dbg(priv->dev, | ||
| 361 | "fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n", | ||
| 362 | column); | ||
| 363 | |||
| 364 | elbc_fcm_ctrl->index = column; | ||
| 365 | return; | ||
| 366 | |||
| 358 | /* READOOB reads only the OOB because no ECC is performed. */ | 367 | /* READOOB reads only the OOB because no ECC is performed. */ |
| 359 | case NAND_CMD_READOOB: | 368 | case NAND_CMD_READOOB: |
| 360 | dev_vdbg(priv->dev, | 369 | dev_vdbg(priv->dev, |
| @@ -635,79 +644,6 @@ static int fsl_elbc_wait(struct nand_chip *chip) | |||
| 635 | return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP; | 644 | return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP; |
| 636 | } | 645 | } |
| 637 | 646 | ||
| 638 | static int fsl_elbc_attach_chip(struct nand_chip *chip) | ||
| 639 | { | ||
| 640 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 641 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); | ||
| 642 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; | ||
| 643 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
| 644 | unsigned int al; | ||
| 645 | |||
| 646 | /* calculate FMR Address Length field */ | ||
| 647 | al = 0; | ||
| 648 | if (chip->pagemask & 0xffff0000) | ||
| 649 | al++; | ||
| 650 | if (chip->pagemask & 0xff000000) | ||
| 651 | al++; | ||
| 652 | |||
| 653 | priv->fmr |= al << FMR_AL_SHIFT; | ||
| 654 | |||
| 655 | dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", | ||
| 656 | chip->numchips); | ||
| 657 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n", | ||
| 658 | chip->chipsize); | ||
| 659 | dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", | ||
| 660 | chip->pagemask); | ||
| 661 | dev_dbg(priv->dev, "fsl_elbc_init: nand->legacy.chip_delay = %d\n", | ||
| 662 | chip->legacy.chip_delay); | ||
| 663 | dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", | ||
| 664 | chip->badblockpos); | ||
| 665 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", | ||
| 666 | chip->chip_shift); | ||
| 667 | dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n", | ||
| 668 | chip->page_shift); | ||
| 669 | dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", | ||
| 670 | chip->phys_erase_shift); | ||
| 671 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", | ||
| 672 | chip->ecc.mode); | ||
| 673 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", | ||
| 674 | chip->ecc.steps); | ||
| 675 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", | ||
| 676 | chip->ecc.bytes); | ||
| 677 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", | ||
| 678 | chip->ecc.total); | ||
| 679 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->ooblayout = %p\n", | ||
| 680 | mtd->ooblayout); | ||
| 681 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); | ||
| 682 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); | ||
| 683 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", | ||
| 684 | mtd->erasesize); | ||
| 685 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n", | ||
| 686 | mtd->writesize); | ||
| 687 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n", | ||
| 688 | mtd->oobsize); | ||
| 689 | |||
| 690 | /* adjust Option Register and ECC to match Flash page size */ | ||
| 691 | if (mtd->writesize == 512) { | ||
| 692 | priv->page_size = 0; | ||
| 693 | clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); | ||
| 694 | } else if (mtd->writesize == 2048) { | ||
| 695 | priv->page_size = 1; | ||
| 696 | setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); | ||
| 697 | } else { | ||
| 698 | dev_err(priv->dev, | ||
| 699 | "fsl_elbc_init: page size %d is not supported\n", | ||
| 700 | mtd->writesize); | ||
| 701 | return -ENOTSUPP; | ||
| 702 | } | ||
| 703 | |||
| 704 | return 0; | ||
| 705 | } | ||
| 706 | |||
| 707 | static const struct nand_controller_ops fsl_elbc_controller_ops = { | ||
| 708 | .attach_chip = fsl_elbc_attach_chip, | ||
| 709 | }; | ||
| 710 | |||
| 711 | static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf, | 647 | static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf, |
| 712 | int oob_required, int page) | 648 | int oob_required, int page) |
| 713 | { | 649 | { |
| @@ -794,27 +730,116 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
| 794 | chip->controller = &elbc_fcm_ctrl->controller; | 730 | chip->controller = &elbc_fcm_ctrl->controller; |
| 795 | nand_set_controller_data(chip, priv); | 731 | nand_set_controller_data(chip, priv); |
| 796 | 732 | ||
| 797 | chip->ecc.read_page = fsl_elbc_read_page; | 733 | return 0; |
| 798 | chip->ecc.write_page = fsl_elbc_write_page; | 734 | } |
| 799 | chip->ecc.write_subpage = fsl_elbc_write_subpage; | 735 | |
| 800 | 736 | static int fsl_elbc_attach_chip(struct nand_chip *chip) | |
| 801 | /* If CS Base Register selects full hardware ECC then use it */ | 737 | { |
| 802 | if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == | 738 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 803 | BR_DECC_CHK_GEN) { | 739 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
| 804 | chip->ecc.mode = NAND_ECC_HW; | 740 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
| 805 | mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); | 741 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
| 806 | chip->ecc.size = 512; | 742 | unsigned int al; |
| 807 | chip->ecc.bytes = 3; | 743 | |
| 808 | chip->ecc.strength = 1; | 744 | switch (chip->ecc.mode) { |
| 745 | /* | ||
| 746 | * if ECC was not chosen in DT, decide whether to use HW or SW ECC from | ||
| 747 | * CS Base Register | ||
| 748 | */ | ||
| 749 | case NAND_ECC_NONE: | ||
| 750 | /* If CS Base Register selects full hardware ECC then use it */ | ||
| 751 | if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == | ||
| 752 | BR_DECC_CHK_GEN) { | ||
| 753 | chip->ecc.read_page = fsl_elbc_read_page; | ||
| 754 | chip->ecc.write_page = fsl_elbc_write_page; | ||
| 755 | chip->ecc.write_subpage = fsl_elbc_write_subpage; | ||
| 756 | |||
| 757 | chip->ecc.mode = NAND_ECC_HW; | ||
| 758 | mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); | ||
| 759 | chip->ecc.size = 512; | ||
| 760 | chip->ecc.bytes = 3; | ||
| 761 | chip->ecc.strength = 1; | ||
| 762 | } else { | ||
| 763 | /* otherwise fall back to default software ECC */ | ||
| 764 | chip->ecc.mode = NAND_ECC_SOFT; | ||
| 765 | chip->ecc.algo = NAND_ECC_HAMMING; | ||
| 766 | } | ||
| 767 | break; | ||
| 768 | |||
| 769 | /* if SW ECC was chosen in DT, we do not need to set anything here */ | ||
| 770 | case NAND_ECC_SOFT: | ||
| 771 | break; | ||
| 772 | |||
| 773 | /* should we also implement NAND_ECC_HW to do as the code above? */ | ||
| 774 | default: | ||
| 775 | return -EINVAL; | ||
| 776 | } | ||
| 777 | |||
| 778 | /* calculate FMR Address Length field */ | ||
| 779 | al = 0; | ||
| 780 | if (chip->pagemask & 0xffff0000) | ||
| 781 | al++; | ||
| 782 | if (chip->pagemask & 0xff000000) | ||
| 783 | al++; | ||
| 784 | |||
| 785 | priv->fmr |= al << FMR_AL_SHIFT; | ||
| 786 | |||
| 787 | dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", | ||
| 788 | nanddev_ntargets(&chip->base)); | ||
| 789 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n", | ||
| 790 | nanddev_target_size(&chip->base)); | ||
| 791 | dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", | ||
| 792 | chip->pagemask); | ||
| 793 | dev_dbg(priv->dev, "fsl_elbc_init: nand->legacy.chip_delay = %d\n", | ||
| 794 | chip->legacy.chip_delay); | ||
| 795 | dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", | ||
| 796 | chip->badblockpos); | ||
| 797 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", | ||
| 798 | chip->chip_shift); | ||
| 799 | dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n", | ||
| 800 | chip->page_shift); | ||
| 801 | dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", | ||
| 802 | chip->phys_erase_shift); | ||
| 803 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", | ||
| 804 | chip->ecc.mode); | ||
| 805 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", | ||
| 806 | chip->ecc.steps); | ||
| 807 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", | ||
| 808 | chip->ecc.bytes); | ||
| 809 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", | ||
| 810 | chip->ecc.total); | ||
| 811 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->ooblayout = %p\n", | ||
| 812 | mtd->ooblayout); | ||
| 813 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); | ||
| 814 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); | ||
| 815 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", | ||
| 816 | mtd->erasesize); | ||
| 817 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n", | ||
| 818 | mtd->writesize); | ||
| 819 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n", | ||
| 820 | mtd->oobsize); | ||
| 821 | |||
| 822 | /* adjust Option Register and ECC to match Flash page size */ | ||
| 823 | if (mtd->writesize == 512) { | ||
| 824 | priv->page_size = 0; | ||
| 825 | clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); | ||
| 826 | } else if (mtd->writesize == 2048) { | ||
| 827 | priv->page_size = 1; | ||
| 828 | setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); | ||
| 809 | } else { | 829 | } else { |
| 810 | /* otherwise fall back to default software ECC */ | 830 | dev_err(priv->dev, |
| 811 | chip->ecc.mode = NAND_ECC_SOFT; | 831 | "fsl_elbc_init: page size %d is not supported\n", |
| 812 | chip->ecc.algo = NAND_ECC_HAMMING; | 832 | mtd->writesize); |
| 833 | return -ENOTSUPP; | ||
| 813 | } | 834 | } |
| 814 | 835 | ||
| 815 | return 0; | 836 | return 0; |
| 816 | } | 837 | } |
| 817 | 838 | ||
| 839 | static const struct nand_controller_ops fsl_elbc_controller_ops = { | ||
| 840 | .attach_chip = fsl_elbc_attach_chip, | ||
| 841 | }; | ||
| 842 | |||
| 818 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | 843 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) |
| 819 | { | 844 | { |
| 820 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; | 845 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index e65d274399f9..04a3dcd675bf 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c | |||
| @@ -722,9 +722,9 @@ static int fsl_ifc_attach_chip(struct nand_chip *chip) | |||
| 722 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); | 722 | struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); |
| 723 | 723 | ||
| 724 | dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__, | 724 | dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__, |
| 725 | chip->numchips); | 725 | nanddev_ntargets(&chip->base)); |
| 726 | dev_dbg(priv->dev, "%s: nand->chipsize = %lld\n", __func__, | 726 | dev_dbg(priv->dev, "%s: nand->chipsize = %lld\n", __func__, |
| 727 | chip->chipsize); | 727 | nanddev_target_size(&chip->base)); |
| 728 | dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__, | 728 | dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__, |
| 729 | chip->pagemask); | 729 | chip->pagemask); |
| 730 | dev_dbg(priv->dev, "%s: nand->legacy.chip_delay = %d\n", __func__, | 730 | dev_dbg(priv->dev, "%s: nand->legacy.chip_delay = %d\n", __func__, |
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c index a4768df5083f..a8b26d2e793c 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c | |||
| @@ -157,8 +157,7 @@ int gpmi_init(struct gpmi_nand_data *this) | |||
| 157 | * Reset BCH here, too. We got failures otherwise :( | 157 | * Reset BCH here, too. We got failures otherwise :( |
| 158 | * See later BCH reset for explanation of MX23 and MX28 handling | 158 | * See later BCH reset for explanation of MX23 and MX28 handling |
| 159 | */ | 159 | */ |
| 160 | ret = gpmi_reset_block(r->bch_regs, | 160 | ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this)); |
| 161 | GPMI_IS_MX23(this) || GPMI_IS_MX28(this)); | ||
| 162 | if (ret) | 161 | if (ret) |
| 163 | goto err_out; | 162 | goto err_out; |
| 164 | 163 | ||
| @@ -266,8 +265,7 @@ int bch_set_geometry(struct gpmi_nand_data *this) | |||
| 266 | * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. | 265 | * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. |
| 267 | * and MX28. | 266 | * and MX28. |
| 268 | */ | 267 | */ |
| 269 | ret = gpmi_reset_block(r->bch_regs, | 268 | ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this)); |
| 270 | GPMI_IS_MX23(this) || GPMI_IS_MX28(this)); | ||
| 271 | if (ret) | 269 | if (ret) |
| 272 | goto err_out; | 270 | goto err_out; |
| 273 | 271 | ||
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index ed405c9434fe..40df20d1adf5 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | |||
| @@ -171,7 +171,7 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this) | |||
| 171 | struct bch_geometry *geo = &this->bch_geometry; | 171 | struct bch_geometry *geo = &this->bch_geometry; |
| 172 | 172 | ||
| 173 | /* Do the sanity check. */ | 173 | /* Do the sanity check. */ |
| 174 | if (GPMI_IS_MX23(this) || GPMI_IS_MX28(this)) { | 174 | if (GPMI_IS_MXS(this)) { |
| 175 | /* The mx23/mx28 only support the GF13. */ | 175 | /* The mx23/mx28 only support the GF13. */ |
| 176 | if (geo->gf_len == 14) | 176 | if (geo->gf_len == 14) |
| 177 | return false; | 177 | return false; |
| @@ -204,7 +204,8 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this, | |||
| 204 | default: | 204 | default: |
| 205 | dev_err(this->dev, | 205 | dev_err(this->dev, |
| 206 | "unsupported nand chip. ecc bits : %d, ecc size : %d\n", | 206 | "unsupported nand chip. ecc bits : %d, ecc size : %d\n", |
| 207 | chip->ecc_strength_ds, chip->ecc_step_ds); | 207 | chip->base.eccreq.strength, |
| 208 | chip->base.eccreq.step_size); | ||
| 208 | return -EINVAL; | 209 | return -EINVAL; |
| 209 | } | 210 | } |
| 210 | geo->ecc_chunk_size = ecc_step; | 211 | geo->ecc_chunk_size = ecc_step; |
| @@ -417,11 +418,13 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this) | |||
| 417 | 418 | ||
| 418 | if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")) | 419 | if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")) |
| 419 | || legacy_set_geometry(this)) { | 420 | || legacy_set_geometry(this)) { |
| 420 | if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) | 421 | if (!(chip->base.eccreq.strength > 0 && |
| 422 | chip->base.eccreq.step_size > 0)) | ||
| 421 | return -EINVAL; | 423 | return -EINVAL; |
| 422 | 424 | ||
| 423 | return set_geometry_by_ecc_info(this, chip->ecc_strength_ds, | 425 | return set_geometry_by_ecc_info(this, |
| 424 | chip->ecc_step_ds); | 426 | chip->base.eccreq.strength, |
| 427 | chip->base.eccreq.step_size); | ||
| 425 | } | 428 | } |
| 426 | 429 | ||
| 427 | return 0; | 430 | return 0; |
| @@ -1602,7 +1605,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) | |||
| 1602 | unsigned int search_area_size_in_strides; | 1605 | unsigned int search_area_size_in_strides; |
| 1603 | unsigned int stride; | 1606 | unsigned int stride; |
| 1604 | unsigned int page; | 1607 | unsigned int page; |
| 1605 | uint8_t *buffer = chip->data_buf; | 1608 | u8 *buffer = nand_get_data_buf(chip); |
| 1606 | int saved_chip_number; | 1609 | int saved_chip_number; |
| 1607 | int found_an_ncb_fingerprint = false; | 1610 | int found_an_ncb_fingerprint = false; |
| 1608 | 1611 | ||
| @@ -1664,7 +1667,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) | |||
| 1664 | unsigned int block; | 1667 | unsigned int block; |
| 1665 | unsigned int stride; | 1668 | unsigned int stride; |
| 1666 | unsigned int page; | 1669 | unsigned int page; |
| 1667 | uint8_t *buffer = chip->data_buf; | 1670 | u8 *buffer = nand_get_data_buf(chip); |
| 1668 | int saved_chip_number; | 1671 | int saved_chip_number; |
| 1669 | int status; | 1672 | int status; |
| 1670 | 1673 | ||
| @@ -1753,7 +1756,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this) | |||
| 1753 | dev_dbg(dev, "Transcribing bad block marks...\n"); | 1756 | dev_dbg(dev, "Transcribing bad block marks...\n"); |
| 1754 | 1757 | ||
| 1755 | /* Compute the number of blocks in the entire medium. */ | 1758 | /* Compute the number of blocks in the entire medium. */ |
| 1756 | block_count = chip->chipsize >> chip->phys_erase_shift; | 1759 | block_count = nanddev_eraseblocks_per_target(&chip->base); |
| 1757 | 1760 | ||
| 1758 | /* | 1761 | /* |
| 1759 | * Loop over all the blocks in the medium, transcribing block marks as | 1762 | * Loop over all the blocks in the medium, transcribing block marks as |
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h index d0b79bac2728..a804a4a5bd46 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h | |||
| @@ -207,4 +207,5 @@ void gpmi_copy_bits(u8 *dst, size_t dst_bit_off, | |||
| 207 | 207 | ||
| 208 | #define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6SX(x) || \ | 208 | #define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6SX(x) || \ |
| 209 | GPMI_IS_MX7D(x)) | 209 | GPMI_IS_MX7D(x)) |
| 210 | #define GPMI_IS_MXS(x) (GPMI_IS_MX23(x) || GPMI_IS_MX28(x)) | ||
| 210 | #endif | 211 | #endif |
diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index f3f9aa160cff..e4526fff9da4 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c | |||
| @@ -849,7 +849,7 @@ static int hisi_nfc_resume(struct device *dev) | |||
| 849 | struct hinfc_host *host = dev_get_drvdata(dev); | 849 | struct hinfc_host *host = dev_get_drvdata(dev); |
| 850 | struct nand_chip *chip = &host->chip; | 850 | struct nand_chip *chip = &host->chip; |
| 851 | 851 | ||
| 852 | for (cs = 0; cs < chip->numchips; cs++) | 852 | for (cs = 0; cs < nanddev_ntargets(&chip->base); cs++) |
| 853 | hisi_nfc_send_cmd_reset(host, cs); | 853 | hisi_nfc_send_cmd_reset(host, cs); |
| 854 | hinfc_write(host, SET_HINFC504_PWIDTH(HINFC504_W_LATCH, | 854 | hinfc_write(host, SET_HINFC504_PWIDTH(HINFC504_W_LATCH, |
| 855 | HINFC504_R_LATCH, HINFC504_RW_LATCH), HINFC504_PWIDTH); | 855 | HINFC504_R_LATCH, HINFC504_RW_LATCH), HINFC504_PWIDTH); |
diff --git a/drivers/mtd/nand/raw/ingenic/Kconfig b/drivers/mtd/nand/raw/ingenic/Kconfig new file mode 100644 index 000000000000..7cfc77021154 --- /dev/null +++ b/drivers/mtd/nand/raw/ingenic/Kconfig | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | config MTD_NAND_JZ4740 | ||
| 2 | tristate "JZ4740 NAND controller" | ||
| 3 | depends on MACH_JZ4740 || COMPILE_TEST | ||
| 4 | depends on HAS_IOMEM | ||
| 5 | help | ||
| 6 | Enables support for NAND Flash on JZ4740 SoC based boards. | ||
| 7 | |||
| 8 | config MTD_NAND_JZ4780 | ||
| 9 | tristate "JZ4780 NAND controller" | ||
| 10 | depends on JZ4780_NEMC | ||
| 11 | help | ||
| 12 | Enables support for NAND Flash connected to the NEMC on JZ4780 SoC | ||
| 13 | based boards, using the BCH controller for hardware error correction. | ||
| 14 | |||
| 15 | if MTD_NAND_JZ4780 | ||
| 16 | |||
| 17 | config MTD_NAND_INGENIC_ECC | ||
| 18 | tristate | ||
| 19 | |||
| 20 | config MTD_NAND_JZ4740_ECC | ||
| 21 | tristate "Hardware BCH support for JZ4740 SoC" | ||
| 22 | select MTD_NAND_INGENIC_ECC | ||
| 23 | help | ||
| 24 | Enable this driver to support the Reed-Solomon error-correction | ||
| 25 | hardware present on the JZ4740 SoC from Ingenic. | ||
| 26 | |||
| 27 | This driver can also be built as a module. If so, the module | ||
| 28 | will be called jz4740-ecc. | ||
| 29 | |||
| 30 | config MTD_NAND_JZ4725B_BCH | ||
| 31 | tristate "Hardware BCH support for JZ4725B SoC" | ||
| 32 | select MTD_NAND_INGENIC_ECC | ||
| 33 | help | ||
| 34 | Enable this driver to support the BCH error-correction hardware | ||
| 35 | present on the JZ4725B SoC from Ingenic. | ||
| 36 | |||
| 37 | This driver can also be built as a module. If so, the module | ||
| 38 | will be called jz4725b-bch. | ||
| 39 | |||
| 40 | config MTD_NAND_JZ4780_BCH | ||
| 41 | tristate "Hardware BCH support for JZ4780 SoC" | ||
| 42 | select MTD_NAND_INGENIC_ECC | ||
| 43 | help | ||
| 44 | Enable this driver to support the BCH error-correction hardware | ||
| 45 | present on the JZ4780 SoC from Ingenic. | ||
| 46 | |||
| 47 | This driver can also be built as a module. If so, the module | ||
| 48 | will be called jz4780-bch. | ||
| 49 | |||
| 50 | endif # MTD_NAND_JZ4780 | ||
diff --git a/drivers/mtd/nand/raw/ingenic/Makefile b/drivers/mtd/nand/raw/ingenic/Makefile new file mode 100644 index 000000000000..ab2c5f47e5b7 --- /dev/null +++ b/drivers/mtd/nand/raw/ingenic/Makefile | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o | ||
| 2 | obj-$(CONFIG_MTD_NAND_JZ4780) += ingenic_nand.o | ||
| 3 | |||
| 4 | obj-$(CONFIG_MTD_NAND_INGENIC_ECC) += ingenic_ecc.o | ||
| 5 | obj-$(CONFIG_MTD_NAND_JZ4740_ECC) += jz4740_ecc.o | ||
| 6 | obj-$(CONFIG_MTD_NAND_JZ4725B_BCH) += jz4725b_bch.o | ||
| 7 | obj-$(CONFIG_MTD_NAND_JZ4780_BCH) += jz4780_bch.o | ||
diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c new file mode 100644 index 000000000000..d3e085c5685a --- /dev/null +++ b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * JZ47xx ECC common code | ||
| 4 | * | ||
| 5 | * Copyright (c) 2015 Imagination Technologies | ||
| 6 | * Author: Alex Smith <alex.smith@imgtec.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/clk.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/of_platform.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | |||
| 15 | #include "ingenic_ecc.h" | ||
| 16 | |||
| 17 | /** | ||
| 18 | * ingenic_ecc_calculate() - calculate ECC for a data buffer | ||
| 19 | * @ecc: ECC device. | ||
| 20 | * @params: ECC parameters. | ||
| 21 | * @buf: input buffer with raw data. | ||
| 22 | * @ecc_code: output buffer with ECC. | ||
| 23 | * | ||
| 24 | * Return: 0 on success, -ETIMEDOUT if timed out while waiting for ECC | ||
| 25 | * controller. | ||
| 26 | */ | ||
| 27 | int ingenic_ecc_calculate(struct ingenic_ecc *ecc, | ||
| 28 | struct ingenic_ecc_params *params, | ||
| 29 | const u8 *buf, u8 *ecc_code) | ||
| 30 | { | ||
| 31 | return ecc->ops->calculate(ecc, params, buf, ecc_code); | ||
| 32 | } | ||
| 33 | EXPORT_SYMBOL(ingenic_ecc_calculate); | ||
| 34 | |||
| 35 | /** | ||
| 36 | * ingenic_ecc_correct() - detect and correct bit errors | ||
| 37 | * @ecc: ECC device. | ||
| 38 | * @params: ECC parameters. | ||
| 39 | * @buf: raw data read from the chip. | ||
| 40 | * @ecc_code: ECC read from the chip. | ||
| 41 | * | ||
| 42 | * Given the raw data and the ECC read from the NAND device, detects and | ||
| 43 | * corrects errors in the data. | ||
| 44 | * | ||
| 45 | * Return: the number of bit errors corrected, -EBADMSG if there are too many | ||
| 46 | * errors to correct or -ETIMEDOUT if we timed out waiting for the controller. | ||
| 47 | */ | ||
| 48 | int ingenic_ecc_correct(struct ingenic_ecc *ecc, | ||
| 49 | struct ingenic_ecc_params *params, | ||
| 50 | u8 *buf, u8 *ecc_code) | ||
| 51 | { | ||
| 52 | return ecc->ops->correct(ecc, params, buf, ecc_code); | ||
| 53 | } | ||
| 54 | EXPORT_SYMBOL(ingenic_ecc_correct); | ||
| 55 | |||
| 56 | /** | ||
| 57 | * ingenic_ecc_get() - get the ECC controller device | ||
| 58 | * @np: ECC device tree node. | ||
| 59 | * | ||
| 60 | * Gets the ECC controller device from the specified device tree node. The | ||
| 61 | * device must be released with ingenic_ecc_release() when it is no longer being | ||
| 62 | * used. | ||
| 63 | * | ||
| 64 | * Return: a pointer to ingenic_ecc, errors are encoded into the pointer. | ||
| 65 | * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. | ||
| 66 | */ | ||
| 67 | static struct ingenic_ecc *ingenic_ecc_get(struct device_node *np) | ||
| 68 | { | ||
| 69 | struct platform_device *pdev; | ||
| 70 | struct ingenic_ecc *ecc; | ||
| 71 | |||
| 72 | pdev = of_find_device_by_node(np); | ||
| 73 | if (!pdev || !platform_get_drvdata(pdev)) | ||
| 74 | return ERR_PTR(-EPROBE_DEFER); | ||
| 75 | |||
| 76 | get_device(&pdev->dev); | ||
| 77 | |||
| 78 | ecc = platform_get_drvdata(pdev); | ||
| 79 | clk_prepare_enable(ecc->clk); | ||
| 80 | |||
| 81 | return ecc; | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * of_ingenic_ecc_get() - get the ECC controller from a DT node | ||
| 86 | * @of_node: the node that contains an ecc-engine property. | ||
| 87 | * | ||
| 88 | * Get the ecc-engine property from the given device tree | ||
| 89 | * node and pass it to ingenic_ecc_get to do the work. | ||
| 90 | * | ||
| 91 | * Return: a pointer to ingenic_ecc, errors are encoded into the pointer. | ||
| 92 | * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. | ||
| 93 | */ | ||
| 94 | struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *of_node) | ||
| 95 | { | ||
| 96 | struct ingenic_ecc *ecc = NULL; | ||
| 97 | struct device_node *np; | ||
| 98 | |||
| 99 | np = of_parse_phandle(of_node, "ecc-engine", 0); | ||
| 100 | |||
| 101 | /* | ||
| 102 | * If the ecc-engine property is not found, check for the deprecated | ||
| 103 | * ingenic,bch-controller property | ||
| 104 | */ | ||
| 105 | if (!np) | ||
| 106 | np = of_parse_phandle(of_node, "ingenic,bch-controller", 0); | ||
| 107 | |||
| 108 | if (np) { | ||
| 109 | ecc = ingenic_ecc_get(np); | ||
| 110 | of_node_put(np); | ||
| 111 | } | ||
| 112 | return ecc; | ||
| 113 | } | ||
| 114 | EXPORT_SYMBOL(of_ingenic_ecc_get); | ||
| 115 | |||
| 116 | /** | ||
| 117 | * ingenic_ecc_release() - release the ECC controller device | ||
| 118 | * @ecc: ECC device. | ||
| 119 | */ | ||
| 120 | void ingenic_ecc_release(struct ingenic_ecc *ecc) | ||
| 121 | { | ||
| 122 | clk_disable_unprepare(ecc->clk); | ||
| 123 | put_device(ecc->dev); | ||
| 124 | } | ||
| 125 | EXPORT_SYMBOL(ingenic_ecc_release); | ||
| 126 | |||
| 127 | int ingenic_ecc_probe(struct platform_device *pdev) | ||
| 128 | { | ||
| 129 | struct device *dev = &pdev->dev; | ||
| 130 | struct ingenic_ecc *ecc; | ||
| 131 | struct resource *res; | ||
| 132 | |||
| 133 | ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); | ||
| 134 | if (!ecc) | ||
| 135 | return -ENOMEM; | ||
| 136 | |||
| 137 | ecc->ops = device_get_match_data(dev); | ||
| 138 | if (!ecc->ops) | ||
| 139 | return -EINVAL; | ||
| 140 | |||
| 141 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 142 | ecc->base = devm_ioremap_resource(dev, res); | ||
| 143 | if (IS_ERR(ecc->base)) | ||
| 144 | return PTR_ERR(ecc->base); | ||
| 145 | |||
| 146 | ecc->ops->disable(ecc); | ||
| 147 | |||
| 148 | ecc->clk = devm_clk_get(dev, NULL); | ||
| 149 | if (IS_ERR(ecc->clk)) { | ||
| 150 | dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(ecc->clk)); | ||
| 151 | return PTR_ERR(ecc->clk); | ||
| 152 | } | ||
| 153 | |||
| 154 | mutex_init(&ecc->lock); | ||
| 155 | |||
| 156 | ecc->dev = dev; | ||
| 157 | platform_set_drvdata(pdev, ecc); | ||
| 158 | |||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | EXPORT_SYMBOL(ingenic_ecc_probe); | ||
| 162 | |||
| 163 | MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>"); | ||
| 164 | MODULE_AUTHOR("Harvey Hunt <harveyhuntnexus@gmail.com>"); | ||
| 165 | MODULE_DESCRIPTION("Ingenic ECC common driver"); | ||
| 166 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h new file mode 100644 index 000000000000..2cda439b5e11 --- /dev/null +++ b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef __DRIVERS_MTD_NAND_INGENIC_ECC_INTERNAL_H__ | ||
| 3 | #define __DRIVERS_MTD_NAND_INGENIC_ECC_INTERNAL_H__ | ||
| 4 | |||
| 5 | #include <linux/compiler_types.h> | ||
| 6 | #include <linux/err.h> | ||
| 7 | #include <linux/mutex.h> | ||
| 8 | #include <linux/types.h> | ||
| 9 | #include <uapi/asm-generic/errno-base.h> | ||
| 10 | |||
| 11 | struct clk; | ||
| 12 | struct device; | ||
| 13 | struct ingenic_ecc; | ||
| 14 | struct platform_device; | ||
| 15 | |||
| 16 | /** | ||
| 17 | * struct ingenic_ecc_params - ECC parameters | ||
| 18 | * @size: data bytes per ECC step. | ||
| 19 | * @bytes: ECC bytes per step. | ||
| 20 | * @strength: number of correctable bits per ECC step. | ||
| 21 | */ | ||
| 22 | struct ingenic_ecc_params { | ||
| 23 | int size; | ||
| 24 | int bytes; | ||
| 25 | int strength; | ||
| 26 | }; | ||
| 27 | |||
| 28 | #if IS_ENABLED(CONFIG_MTD_NAND_INGENIC_ECC) | ||
| 29 | int ingenic_ecc_calculate(struct ingenic_ecc *ecc, | ||
| 30 | struct ingenic_ecc_params *params, | ||
| 31 | const u8 *buf, u8 *ecc_code); | ||
| 32 | int ingenic_ecc_correct(struct ingenic_ecc *ecc, | ||
| 33 | struct ingenic_ecc_params *params, u8 *buf, | ||
| 34 | u8 *ecc_code); | ||
| 35 | |||
| 36 | void ingenic_ecc_release(struct ingenic_ecc *ecc); | ||
| 37 | struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np); | ||
| 38 | #else /* CONFIG_MTD_NAND_INGENIC_ECC */ | ||
| 39 | int ingenic_ecc_calculate(struct ingenic_ecc *ecc, | ||
| 40 | struct ingenic_ecc_params *params, | ||
| 41 | const u8 *buf, u8 *ecc_code) | ||
| 42 | { | ||
| 43 | return -ENODEV; | ||
| 44 | } | ||
| 45 | |||
| 46 | int ingenic_ecc_correct(struct ingenic_ecc *ecc, | ||
| 47 | struct ingenic_ecc_params *params, u8 *buf, | ||
| 48 | u8 *ecc_code) | ||
| 49 | { | ||
| 50 | return -ENODEV; | ||
| 51 | } | ||
| 52 | |||
| 53 | void ingenic_ecc_release(struct ingenic_ecc *ecc) | ||
| 54 | { | ||
| 55 | } | ||
| 56 | |||
| 57 | struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np) | ||
| 58 | { | ||
| 59 | return ERR_PTR(-ENODEV); | ||
| 60 | } | ||
| 61 | #endif /* CONFIG_MTD_NAND_INGENIC_ECC */ | ||
| 62 | |||
| 63 | struct ingenic_ecc_ops { | ||
| 64 | void (*disable)(struct ingenic_ecc *ecc); | ||
| 65 | int (*calculate)(struct ingenic_ecc *ecc, | ||
| 66 | struct ingenic_ecc_params *params, | ||
| 67 | const u8 *buf, u8 *ecc_code); | ||
| 68 | int (*correct)(struct ingenic_ecc *ecc, | ||
| 69 | struct ingenic_ecc_params *params, | ||
| 70 | u8 *buf, u8 *ecc_code); | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct ingenic_ecc { | ||
| 74 | struct device *dev; | ||
| 75 | const struct ingenic_ecc_ops *ops; | ||
| 76 | void __iomem *base; | ||
| 77 | struct clk *clk; | ||
| 78 | struct mutex lock; | ||
| 79 | }; | ||
| 80 | |||
| 81 | int ingenic_ecc_probe(struct platform_device *pdev); | ||
| 82 | |||
| 83 | #endif /* __DRIVERS_MTD_NAND_INGENIC_ECC_INTERNAL_H__ */ | ||
diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand.c new file mode 100644 index 000000000000..d7b7c0f13909 --- /dev/null +++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand.c | |||
| @@ -0,0 +1,530 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Ingenic JZ47xx NAND driver | ||
| 4 | * | ||
| 5 | * Copyright (c) 2015 Imagination Technologies | ||
| 6 | * Author: Alex Smith <alex.smith@imgtec.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/delay.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/io.h> | ||
| 12 | #include <linux/list.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/of.h> | ||
| 15 | #include <linux/of_address.h> | ||
| 16 | #include <linux/of_device.h> | ||
| 17 | #include <linux/gpio/consumer.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/mtd/mtd.h> | ||
| 21 | #include <linux/mtd/rawnand.h> | ||
| 22 | #include <linux/mtd/partitions.h> | ||
| 23 | |||
| 24 | #include <linux/jz4780-nemc.h> | ||
| 25 | |||
| 26 | #include "ingenic_ecc.h" | ||
| 27 | |||
| 28 | #define DRV_NAME "ingenic-nand" | ||
| 29 | |||
| 30 | /* Command delay when there is no R/B pin. */ | ||
| 31 | #define RB_DELAY_US 100 | ||
| 32 | |||
| 33 | struct jz_soc_info { | ||
| 34 | unsigned long data_offset; | ||
| 35 | unsigned long addr_offset; | ||
| 36 | unsigned long cmd_offset; | ||
| 37 | const struct mtd_ooblayout_ops *oob_layout; | ||
| 38 | }; | ||
| 39 | |||
| 40 | struct ingenic_nand_cs { | ||
| 41 | unsigned int bank; | ||
| 42 | void __iomem *base; | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct ingenic_nfc { | ||
| 46 | struct device *dev; | ||
| 47 | struct ingenic_ecc *ecc; | ||
| 48 | const struct jz_soc_info *soc_info; | ||
| 49 | struct nand_controller controller; | ||
| 50 | unsigned int num_banks; | ||
| 51 | struct list_head chips; | ||
| 52 | int selected; | ||
| 53 | struct ingenic_nand_cs cs[]; | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct ingenic_nand { | ||
| 57 | struct nand_chip chip; | ||
| 58 | struct list_head chip_list; | ||
| 59 | |||
| 60 | struct gpio_desc *busy_gpio; | ||
| 61 | struct gpio_desc *wp_gpio; | ||
| 62 | unsigned int reading: 1; | ||
| 63 | }; | ||
| 64 | |||
| 65 | static inline struct ingenic_nand *to_ingenic_nand(struct mtd_info *mtd) | ||
| 66 | { | ||
| 67 | return container_of(mtd_to_nand(mtd), struct ingenic_nand, chip); | ||
| 68 | } | ||
| 69 | |||
| 70 | static inline struct ingenic_nfc *to_ingenic_nfc(struct nand_controller *ctrl) | ||
| 71 | { | ||
| 72 | return container_of(ctrl, struct ingenic_nfc, controller); | ||
| 73 | } | ||
| 74 | |||
| 75 | static int qi_lb60_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 76 | struct mtd_oob_region *oobregion) | ||
| 77 | { | ||
| 78 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 79 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 80 | |||
| 81 | if (section || !ecc->total) | ||
| 82 | return -ERANGE; | ||
| 83 | |||
| 84 | oobregion->length = ecc->total; | ||
| 85 | oobregion->offset = 12; | ||
| 86 | |||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int qi_lb60_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 91 | struct mtd_oob_region *oobregion) | ||
| 92 | { | ||
| 93 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 94 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 95 | |||
| 96 | if (section) | ||
| 97 | return -ERANGE; | ||
| 98 | |||
| 99 | oobregion->length = mtd->oobsize - ecc->total - 12; | ||
| 100 | oobregion->offset = 12 + ecc->total; | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | const struct mtd_ooblayout_ops qi_lb60_ooblayout_ops = { | ||
| 106 | .ecc = qi_lb60_ooblayout_ecc, | ||
| 107 | .free = qi_lb60_ooblayout_free, | ||
| 108 | }; | ||
| 109 | |||
| 110 | static int jz4725b_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 111 | struct mtd_oob_region *oobregion) | ||
| 112 | { | ||
| 113 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 114 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 115 | |||
| 116 | if (section || !ecc->total) | ||
| 117 | return -ERANGE; | ||
| 118 | |||
| 119 | oobregion->length = ecc->total; | ||
| 120 | oobregion->offset = 3; | ||
| 121 | |||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | static int jz4725b_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 126 | struct mtd_oob_region *oobregion) | ||
| 127 | { | ||
| 128 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 129 | struct nand_ecc_ctrl *ecc = &chip->ecc; | ||
| 130 | |||
| 131 | if (section) | ||
| 132 | return -ERANGE; | ||
| 133 | |||
| 134 | oobregion->length = mtd->oobsize - ecc->total - 3; | ||
| 135 | oobregion->offset = 3 + ecc->total; | ||
| 136 | |||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static const struct mtd_ooblayout_ops jz4725b_ooblayout_ops = { | ||
| 141 | .ecc = jz4725b_ooblayout_ecc, | ||
| 142 | .free = jz4725b_ooblayout_free, | ||
| 143 | }; | ||
| 144 | |||
| 145 | static void ingenic_nand_select_chip(struct nand_chip *chip, int chipnr) | ||
| 146 | { | ||
| 147 | struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); | ||
| 148 | struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller); | ||
| 149 | struct ingenic_nand_cs *cs; | ||
| 150 | |||
| 151 | /* Ensure the currently selected chip is deasserted. */ | ||
| 152 | if (chipnr == -1 && nfc->selected >= 0) { | ||
| 153 | cs = &nfc->cs[nfc->selected]; | ||
| 154 | jz4780_nemc_assert(nfc->dev, cs->bank, false); | ||
| 155 | } | ||
| 156 | |||
| 157 | nfc->selected = chipnr; | ||
| 158 | } | ||
| 159 | |||
| 160 | static void ingenic_nand_cmd_ctrl(struct nand_chip *chip, int cmd, | ||
| 161 | unsigned int ctrl) | ||
| 162 | { | ||
| 163 | struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); | ||
| 164 | struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller); | ||
| 165 | struct ingenic_nand_cs *cs; | ||
| 166 | |||
| 167 | if (WARN_ON(nfc->selected < 0)) | ||
| 168 | return; | ||
| 169 | |||
| 170 | cs = &nfc->cs[nfc->selected]; | ||
| 171 | |||
| 172 | jz4780_nemc_assert(nfc->dev, cs->bank, ctrl & NAND_NCE); | ||
| 173 | |||
| 174 | if (cmd == NAND_CMD_NONE) | ||
| 175 | return; | ||
| 176 | |||
| 177 | if (ctrl & NAND_ALE) | ||
| 178 | writeb(cmd, cs->base + nfc->soc_info->addr_offset); | ||
| 179 | else if (ctrl & NAND_CLE) | ||
| 180 | writeb(cmd, cs->base + nfc->soc_info->cmd_offset); | ||
| 181 | } | ||
| 182 | |||
| 183 | static int ingenic_nand_dev_ready(struct nand_chip *chip) | ||
| 184 | { | ||
| 185 | struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); | ||
| 186 | |||
| 187 | return !gpiod_get_value_cansleep(nand->busy_gpio); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void ingenic_nand_ecc_hwctl(struct nand_chip *chip, int mode) | ||
| 191 | { | ||
| 192 | struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); | ||
| 193 | |||
| 194 | nand->reading = (mode == NAND_ECC_READ); | ||
| 195 | } | ||
| 196 | |||
| 197 | static int ingenic_nand_ecc_calculate(struct nand_chip *chip, const u8 *dat, | ||
| 198 | u8 *ecc_code) | ||
| 199 | { | ||
| 200 | struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); | ||
| 201 | struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller); | ||
| 202 | struct ingenic_ecc_params params; | ||
| 203 | |||
| 204 | /* | ||
| 205 | * Don't need to generate the ECC when reading, the ECC engine does it | ||
| 206 | * for us as part of decoding/correction. | ||
| 207 | */ | ||
| 208 | if (nand->reading) | ||
| 209 | return 0; | ||
| 210 | |||
| 211 | params.size = nand->chip.ecc.size; | ||
| 212 | params.bytes = nand->chip.ecc.bytes; | ||
| 213 | params.strength = nand->chip.ecc.strength; | ||
| 214 | |||
| 215 | return ingenic_ecc_calculate(nfc->ecc, ¶ms, dat, ecc_code); | ||
| 216 | } | ||
| 217 | |||
| 218 | static int ingenic_nand_ecc_correct(struct nand_chip *chip, u8 *dat, | ||
| 219 | u8 *read_ecc, u8 *calc_ecc) | ||
| 220 | { | ||
| 221 | struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); | ||
| 222 | struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller); | ||
| 223 | struct ingenic_ecc_params params; | ||
| 224 | |||
| 225 | params.size = nand->chip.ecc.size; | ||
| 226 | params.bytes = nand->chip.ecc.bytes; | ||
| 227 | params.strength = nand->chip.ecc.strength; | ||
| 228 | |||
| 229 | return ingenic_ecc_correct(nfc->ecc, ¶ms, dat, read_ecc); | ||
| 230 | } | ||
| 231 | |||
| 232 | static int ingenic_nand_attach_chip(struct nand_chip *chip) | ||
| 233 | { | ||
| 234 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 235 | struct ingenic_nfc *nfc = to_ingenic_nfc(chip->controller); | ||
| 236 | int eccbytes; | ||
| 237 | |||
| 238 | if (chip->ecc.strength == 4) { | ||
| 239 | /* JZ4740 uses 9 bytes of ECC to correct maximum 4 errors */ | ||
| 240 | chip->ecc.bytes = 9; | ||
| 241 | } else { | ||
| 242 | chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) * | ||
| 243 | (chip->ecc.strength / 8); | ||
| 244 | } | ||
| 245 | |||
| 246 | switch (chip->ecc.mode) { | ||
| 247 | case NAND_ECC_HW: | ||
| 248 | if (!nfc->ecc) { | ||
| 249 | dev_err(nfc->dev, "HW ECC selected, but ECC controller not found\n"); | ||
| 250 | return -ENODEV; | ||
| 251 | } | ||
| 252 | |||
| 253 | chip->ecc.hwctl = ingenic_nand_ecc_hwctl; | ||
| 254 | chip->ecc.calculate = ingenic_nand_ecc_calculate; | ||
| 255 | chip->ecc.correct = ingenic_nand_ecc_correct; | ||
| 256 | /* fall through */ | ||
| 257 | case NAND_ECC_SOFT: | ||
| 258 | dev_info(nfc->dev, "using %s (strength %d, size %d, bytes %d)\n", | ||
| 259 | (nfc->ecc) ? "hardware ECC" : "software ECC", | ||
| 260 | chip->ecc.strength, chip->ecc.size, chip->ecc.bytes); | ||
| 261 | break; | ||
| 262 | case NAND_ECC_NONE: | ||
| 263 | dev_info(nfc->dev, "not using ECC\n"); | ||
| 264 | break; | ||
| 265 | default: | ||
| 266 | dev_err(nfc->dev, "ECC mode %d not supported\n", | ||
| 267 | chip->ecc.mode); | ||
| 268 | return -EINVAL; | ||
| 269 | } | ||
| 270 | |||
| 271 | /* The NAND core will generate the ECC layout for SW ECC */ | ||
| 272 | if (chip->ecc.mode != NAND_ECC_HW) | ||
| 273 | return 0; | ||
| 274 | |||
| 275 | /* Generate ECC layout. ECC codes are right aligned in the OOB area. */ | ||
| 276 | eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes; | ||
| 277 | |||
| 278 | if (eccbytes > mtd->oobsize - 2) { | ||
| 279 | dev_err(nfc->dev, | ||
| 280 | "invalid ECC config: required %d ECC bytes, but only %d are available", | ||
| 281 | eccbytes, mtd->oobsize - 2); | ||
| 282 | return -EINVAL; | ||
| 283 | } | ||
| 284 | |||
| 285 | /* | ||
| 286 | * The generic layout for BBT markers will most likely overlap with our | ||
| 287 | * ECC bytes in the OOB, so move the BBT markers outside the OOB area. | ||
| 288 | */ | ||
| 289 | if (chip->bbt_options & NAND_BBT_USE_FLASH) | ||
| 290 | chip->bbt_options |= NAND_BBT_NO_OOB; | ||
| 291 | |||
| 292 | /* For legacy reasons we use a different layout on the qi,lb60 board. */ | ||
| 293 | if (of_machine_is_compatible("qi,lb60")) | ||
| 294 | mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops); | ||
| 295 | else | ||
| 296 | mtd_set_ooblayout(mtd, nfc->soc_info->oob_layout); | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | static const struct nand_controller_ops ingenic_nand_controller_ops = { | ||
| 302 | .attach_chip = ingenic_nand_attach_chip, | ||
| 303 | }; | ||
| 304 | |||
| 305 | static int ingenic_nand_init_chip(struct platform_device *pdev, | ||
| 306 | struct ingenic_nfc *nfc, | ||
| 307 | struct device_node *np, | ||
| 308 | unsigned int chipnr) | ||
| 309 | { | ||
| 310 | struct device *dev = &pdev->dev; | ||
| 311 | struct ingenic_nand *nand; | ||
| 312 | struct ingenic_nand_cs *cs; | ||
| 313 | struct resource *res; | ||
| 314 | struct nand_chip *chip; | ||
| 315 | struct mtd_info *mtd; | ||
| 316 | const __be32 *reg; | ||
| 317 | int ret = 0; | ||
| 318 | |||
| 319 | cs = &nfc->cs[chipnr]; | ||
| 320 | |||
| 321 | reg = of_get_property(np, "reg", NULL); | ||
| 322 | if (!reg) | ||
| 323 | return -EINVAL; | ||
| 324 | |||
| 325 | cs->bank = be32_to_cpu(*reg); | ||
| 326 | |||
| 327 | jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND); | ||
| 328 | |||
| 329 | res = platform_get_resource(pdev, IORESOURCE_MEM, chipnr); | ||
| 330 | cs->base = devm_ioremap_resource(dev, res); | ||
| 331 | if (IS_ERR(cs->base)) | ||
| 332 | return PTR_ERR(cs->base); | ||
| 333 | |||
| 334 | nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL); | ||
| 335 | if (!nand) | ||
| 336 | return -ENOMEM; | ||
| 337 | |||
| 338 | nand->busy_gpio = devm_gpiod_get_optional(dev, "rb", GPIOD_IN); | ||
| 339 | |||
| 340 | if (IS_ERR(nand->busy_gpio)) { | ||
| 341 | ret = PTR_ERR(nand->busy_gpio); | ||
| 342 | dev_err(dev, "failed to request busy GPIO: %d\n", ret); | ||
| 343 | return ret; | ||
| 344 | } else if (nand->busy_gpio) { | ||
| 345 | nand->chip.legacy.dev_ready = ingenic_nand_dev_ready; | ||
| 346 | } | ||
| 347 | |||
| 348 | nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); | ||
| 349 | |||
| 350 | if (IS_ERR(nand->wp_gpio)) { | ||
| 351 | ret = PTR_ERR(nand->wp_gpio); | ||
| 352 | dev_err(dev, "failed to request WP GPIO: %d\n", ret); | ||
| 353 | return ret; | ||
| 354 | } | ||
| 355 | |||
| 356 | chip = &nand->chip; | ||
| 357 | mtd = nand_to_mtd(chip); | ||
| 358 | mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), | ||
| 359 | cs->bank); | ||
| 360 | if (!mtd->name) | ||
| 361 | return -ENOMEM; | ||
| 362 | mtd->dev.parent = dev; | ||
| 363 | |||
| 364 | chip->legacy.IO_ADDR_R = cs->base + nfc->soc_info->data_offset; | ||
| 365 | chip->legacy.IO_ADDR_W = cs->base + nfc->soc_info->data_offset; | ||
| 366 | chip->legacy.chip_delay = RB_DELAY_US; | ||
| 367 | chip->options = NAND_NO_SUBPAGE_WRITE; | ||
| 368 | chip->legacy.select_chip = ingenic_nand_select_chip; | ||
| 369 | chip->legacy.cmd_ctrl = ingenic_nand_cmd_ctrl; | ||
| 370 | chip->ecc.mode = NAND_ECC_HW; | ||
| 371 | chip->controller = &nfc->controller; | ||
| 372 | nand_set_flash_node(chip, np); | ||
| 373 | |||
| 374 | chip->controller->ops = &ingenic_nand_controller_ops; | ||
| 375 | ret = nand_scan(chip, 1); | ||
| 376 | if (ret) | ||
| 377 | return ret; | ||
| 378 | |||
| 379 | ret = mtd_device_register(mtd, NULL, 0); | ||
| 380 | if (ret) { | ||
| 381 | nand_release(chip); | ||
| 382 | return ret; | ||
| 383 | } | ||
| 384 | |||
| 385 | list_add_tail(&nand->chip_list, &nfc->chips); | ||
| 386 | |||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | static void ingenic_nand_cleanup_chips(struct ingenic_nfc *nfc) | ||
| 391 | { | ||
| 392 | struct ingenic_nand *chip; | ||
| 393 | |||
| 394 | while (!list_empty(&nfc->chips)) { | ||
| 395 | chip = list_first_entry(&nfc->chips, | ||
| 396 | struct ingenic_nand, chip_list); | ||
| 397 | nand_release(&chip->chip); | ||
| 398 | list_del(&chip->chip_list); | ||
| 399 | } | ||
| 400 | } | ||
| 401 | |||
| 402 | static int ingenic_nand_init_chips(struct ingenic_nfc *nfc, | ||
| 403 | struct platform_device *pdev) | ||
| 404 | { | ||
| 405 | struct device *dev = &pdev->dev; | ||
| 406 | struct device_node *np; | ||
| 407 | int i = 0; | ||
| 408 | int ret; | ||
| 409 | int num_chips = of_get_child_count(dev->of_node); | ||
| 410 | |||
| 411 | if (num_chips > nfc->num_banks) { | ||
| 412 | dev_err(dev, "found %d chips but only %d banks\n", | ||
| 413 | num_chips, nfc->num_banks); | ||
| 414 | return -EINVAL; | ||
| 415 | } | ||
| 416 | |||
| 417 | for_each_child_of_node(dev->of_node, np) { | ||
| 418 | ret = ingenic_nand_init_chip(pdev, nfc, np, i); | ||
| 419 | if (ret) { | ||
| 420 | ingenic_nand_cleanup_chips(nfc); | ||
| 421 | return ret; | ||
| 422 | } | ||
| 423 | |||
| 424 | i++; | ||
| 425 | } | ||
| 426 | |||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | static int ingenic_nand_probe(struct platform_device *pdev) | ||
| 431 | { | ||
| 432 | struct device *dev = &pdev->dev; | ||
| 433 | unsigned int num_banks; | ||
| 434 | struct ingenic_nfc *nfc; | ||
| 435 | int ret; | ||
| 436 | |||
| 437 | num_banks = jz4780_nemc_num_banks(dev); | ||
| 438 | if (num_banks == 0) { | ||
| 439 | dev_err(dev, "no banks found\n"); | ||
| 440 | return -ENODEV; | ||
| 441 | } | ||
| 442 | |||
| 443 | nfc = devm_kzalloc(dev, struct_size(nfc, cs, num_banks), GFP_KERNEL); | ||
| 444 | if (!nfc) | ||
| 445 | return -ENOMEM; | ||
| 446 | |||
| 447 | nfc->soc_info = device_get_match_data(dev); | ||
| 448 | if (!nfc->soc_info) | ||
| 449 | return -EINVAL; | ||
| 450 | |||
| 451 | /* | ||
| 452 | * Check for ECC HW before we call nand_scan_ident, to prevent us from | ||
| 453 | * having to call it again if the ECC driver returns -EPROBE_DEFER. | ||
| 454 | */ | ||
| 455 | nfc->ecc = of_ingenic_ecc_get(dev->of_node); | ||
| 456 | if (IS_ERR(nfc->ecc)) | ||
| 457 | return PTR_ERR(nfc->ecc); | ||
| 458 | |||
| 459 | nfc->dev = dev; | ||
| 460 | nfc->num_banks = num_banks; | ||
| 461 | |||
| 462 | nand_controller_init(&nfc->controller); | ||
| 463 | INIT_LIST_HEAD(&nfc->chips); | ||
| 464 | |||
| 465 | ret = ingenic_nand_init_chips(nfc, pdev); | ||
| 466 | if (ret) { | ||
| 467 | if (nfc->ecc) | ||
| 468 | ingenic_ecc_release(nfc->ecc); | ||
| 469 | return ret; | ||
| 470 | } | ||
| 471 | |||
| 472 | platform_set_drvdata(pdev, nfc); | ||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | static int ingenic_nand_remove(struct platform_device *pdev) | ||
| 477 | { | ||
| 478 | struct ingenic_nfc *nfc = platform_get_drvdata(pdev); | ||
| 479 | |||
| 480 | if (nfc->ecc) | ||
| 481 | ingenic_ecc_release(nfc->ecc); | ||
| 482 | |||
| 483 | ingenic_nand_cleanup_chips(nfc); | ||
| 484 | |||
| 485 | return 0; | ||
| 486 | } | ||
| 487 | |||
| 488 | static const struct jz_soc_info jz4740_soc_info = { | ||
| 489 | .data_offset = 0x00000000, | ||
| 490 | .cmd_offset = 0x00008000, | ||
| 491 | .addr_offset = 0x00010000, | ||
| 492 | .oob_layout = &nand_ooblayout_lp_ops, | ||
| 493 | }; | ||
| 494 | |||
| 495 | static const struct jz_soc_info jz4725b_soc_info = { | ||
| 496 | .data_offset = 0x00000000, | ||
| 497 | .cmd_offset = 0x00008000, | ||
| 498 | .addr_offset = 0x00010000, | ||
| 499 | .oob_layout = &jz4725b_ooblayout_ops, | ||
| 500 | }; | ||
| 501 | |||
| 502 | static const struct jz_soc_info jz4780_soc_info = { | ||
| 503 | .data_offset = 0x00000000, | ||
| 504 | .cmd_offset = 0x00400000, | ||
| 505 | .addr_offset = 0x00800000, | ||
| 506 | .oob_layout = &nand_ooblayout_lp_ops, | ||
| 507 | }; | ||
| 508 | |||
| 509 | static const struct of_device_id ingenic_nand_dt_match[] = { | ||
| 510 | { .compatible = "ingenic,jz4740-nand", .data = &jz4740_soc_info }, | ||
| 511 | { .compatible = "ingenic,jz4725b-nand", .data = &jz4725b_soc_info }, | ||
| 512 | { .compatible = "ingenic,jz4780-nand", .data = &jz4780_soc_info }, | ||
| 513 | {}, | ||
| 514 | }; | ||
| 515 | MODULE_DEVICE_TABLE(of, ingenic_nand_dt_match); | ||
| 516 | |||
| 517 | static struct platform_driver ingenic_nand_driver = { | ||
| 518 | .probe = ingenic_nand_probe, | ||
| 519 | .remove = ingenic_nand_remove, | ||
| 520 | .driver = { | ||
| 521 | .name = DRV_NAME, | ||
| 522 | .of_match_table = of_match_ptr(ingenic_nand_dt_match), | ||
| 523 | }, | ||
| 524 | }; | ||
| 525 | module_platform_driver(ingenic_nand_driver); | ||
| 526 | |||
| 527 | MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>"); | ||
| 528 | MODULE_AUTHOR("Harvey Hunt <harveyhuntnexus@gmail.com>"); | ||
| 529 | MODULE_DESCRIPTION("Ingenic JZ47xx NAND driver"); | ||
| 530 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mtd/nand/raw/ingenic/jz4725b_bch.c b/drivers/mtd/nand/raw/ingenic/jz4725b_bch.c new file mode 100644 index 000000000000..6c852eae09cf --- /dev/null +++ b/drivers/mtd/nand/raw/ingenic/jz4725b_bch.c | |||
| @@ -0,0 +1,295 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * JZ4725B BCH controller driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net> | ||
| 6 | * | ||
| 7 | * Based on jz4780_bch.c | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/bitops.h> | ||
| 11 | #include <linux/device.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/iopoll.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/mutex.h> | ||
| 16 | #include <linux/of_platform.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | |||
| 19 | #include "ingenic_ecc.h" | ||
| 20 | |||
| 21 | #define BCH_BHCR 0x0 | ||
| 22 | #define BCH_BHCSR 0x4 | ||
| 23 | #define BCH_BHCCR 0x8 | ||
| 24 | #define BCH_BHCNT 0xc | ||
| 25 | #define BCH_BHDR 0x10 | ||
| 26 | #define BCH_BHPAR0 0x14 | ||
| 27 | #define BCH_BHERR0 0x28 | ||
| 28 | #define BCH_BHINT 0x24 | ||
| 29 | #define BCH_BHINTES 0x3c | ||
| 30 | #define BCH_BHINTEC 0x40 | ||
| 31 | #define BCH_BHINTE 0x38 | ||
| 32 | |||
| 33 | #define BCH_BHCR_ENCE BIT(3) | ||
| 34 | #define BCH_BHCR_BSEL BIT(2) | ||
| 35 | #define BCH_BHCR_INIT BIT(1) | ||
| 36 | #define BCH_BHCR_BCHE BIT(0) | ||
| 37 | |||
| 38 | #define BCH_BHCNT_DEC_COUNT_SHIFT 16 | ||
| 39 | #define BCH_BHCNT_DEC_COUNT_MASK (0x3ff << BCH_BHCNT_DEC_COUNT_SHIFT) | ||
| 40 | #define BCH_BHCNT_ENC_COUNT_SHIFT 0 | ||
| 41 | #define BCH_BHCNT_ENC_COUNT_MASK (0x3ff << BCH_BHCNT_ENC_COUNT_SHIFT) | ||
| 42 | |||
| 43 | #define BCH_BHERR_INDEX0_SHIFT 0 | ||
| 44 | #define BCH_BHERR_INDEX0_MASK (0x1fff << BCH_BHERR_INDEX0_SHIFT) | ||
| 45 | #define BCH_BHERR_INDEX1_SHIFT 16 | ||
| 46 | #define BCH_BHERR_INDEX1_MASK (0x1fff << BCH_BHERR_INDEX1_SHIFT) | ||
| 47 | |||
| 48 | #define BCH_BHINT_ERRC_SHIFT 28 | ||
| 49 | #define BCH_BHINT_ERRC_MASK (0xf << BCH_BHINT_ERRC_SHIFT) | ||
| 50 | #define BCH_BHINT_TERRC_SHIFT 16 | ||
| 51 | #define BCH_BHINT_TERRC_MASK (0x7f << BCH_BHINT_TERRC_SHIFT) | ||
| 52 | #define BCH_BHINT_ALL_0 BIT(5) | ||
| 53 | #define BCH_BHINT_ALL_F BIT(4) | ||
| 54 | #define BCH_BHINT_DECF BIT(3) | ||
| 55 | #define BCH_BHINT_ENCF BIT(2) | ||
| 56 | #define BCH_BHINT_UNCOR BIT(1) | ||
| 57 | #define BCH_BHINT_ERR BIT(0) | ||
| 58 | |||
| 59 | /* Timeout for BCH calculation/correction. */ | ||
| 60 | #define BCH_TIMEOUT_US 100000 | ||
| 61 | |||
| 62 | static inline void jz4725b_bch_config_set(struct ingenic_ecc *bch, u32 cfg) | ||
| 63 | { | ||
| 64 | writel(cfg, bch->base + BCH_BHCSR); | ||
| 65 | } | ||
| 66 | |||
| 67 | static inline void jz4725b_bch_config_clear(struct ingenic_ecc *bch, u32 cfg) | ||
| 68 | { | ||
| 69 | writel(cfg, bch->base + BCH_BHCCR); | ||
| 70 | } | ||
| 71 | |||
| 72 | static int jz4725b_bch_reset(struct ingenic_ecc *bch, | ||
| 73 | struct ingenic_ecc_params *params, bool calc_ecc) | ||
| 74 | { | ||
| 75 | u32 reg, max_value; | ||
| 76 | |||
| 77 | /* Clear interrupt status. */ | ||
| 78 | writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT); | ||
| 79 | |||
| 80 | /* Initialise and enable BCH. */ | ||
| 81 | jz4725b_bch_config_clear(bch, 0x1f); | ||
| 82 | jz4725b_bch_config_set(bch, BCH_BHCR_BCHE); | ||
| 83 | |||
| 84 | if (params->strength == 8) | ||
| 85 | jz4725b_bch_config_set(bch, BCH_BHCR_BSEL); | ||
| 86 | else | ||
| 87 | jz4725b_bch_config_clear(bch, BCH_BHCR_BSEL); | ||
| 88 | |||
| 89 | if (calc_ecc) /* calculate ECC from data */ | ||
| 90 | jz4725b_bch_config_set(bch, BCH_BHCR_ENCE); | ||
| 91 | else /* correct data from ECC */ | ||
| 92 | jz4725b_bch_config_clear(bch, BCH_BHCR_ENCE); | ||
| 93 | |||
| 94 | jz4725b_bch_config_set(bch, BCH_BHCR_INIT); | ||
| 95 | |||
| 96 | max_value = BCH_BHCNT_ENC_COUNT_MASK >> BCH_BHCNT_ENC_COUNT_SHIFT; | ||
| 97 | if (params->size > max_value) | ||
| 98 | return -EINVAL; | ||
| 99 | |||
| 100 | max_value = BCH_BHCNT_DEC_COUNT_MASK >> BCH_BHCNT_DEC_COUNT_SHIFT; | ||
| 101 | if (params->size + params->bytes > max_value) | ||
| 102 | return -EINVAL; | ||
| 103 | |||
| 104 | /* Set up BCH count register. */ | ||
| 105 | reg = params->size << BCH_BHCNT_ENC_COUNT_SHIFT; | ||
| 106 | reg |= (params->size + params->bytes) << BCH_BHCNT_DEC_COUNT_SHIFT; | ||
| 107 | writel(reg, bch->base + BCH_BHCNT); | ||
| 108 | |||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | static void jz4725b_bch_disable(struct ingenic_ecc *bch) | ||
| 113 | { | ||
| 114 | /* Clear interrupts */ | ||
| 115 | writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT); | ||
| 116 | |||
| 117 | /* Disable the hardware */ | ||
| 118 | jz4725b_bch_config_clear(bch, BCH_BHCR_BCHE); | ||
| 119 | } | ||
| 120 | |||
| 121 | static void jz4725b_bch_write_data(struct ingenic_ecc *bch, const u8 *buf, | ||
| 122 | size_t size) | ||
| 123 | { | ||
| 124 | while (size--) | ||
| 125 | writeb(*buf++, bch->base + BCH_BHDR); | ||
| 126 | } | ||
| 127 | |||
| 128 | static void jz4725b_bch_read_parity(struct ingenic_ecc *bch, u8 *buf, | ||
| 129 | size_t size) | ||
| 130 | { | ||
| 131 | size_t size32 = size / sizeof(u32); | ||
| 132 | size_t size8 = size % sizeof(u32); | ||
| 133 | u32 *dest32; | ||
| 134 | u8 *dest8; | ||
| 135 | u32 val, offset = 0; | ||
| 136 | |||
| 137 | dest32 = (u32 *)buf; | ||
| 138 | while (size32--) { | ||
| 139 | *dest32++ = readl_relaxed(bch->base + BCH_BHPAR0 + offset); | ||
| 140 | offset += sizeof(u32); | ||
| 141 | } | ||
| 142 | |||
| 143 | dest8 = (u8 *)dest32; | ||
| 144 | val = readl_relaxed(bch->base + BCH_BHPAR0 + offset); | ||
| 145 | switch (size8) { | ||
| 146 | case 3: | ||
| 147 | dest8[2] = (val >> 16) & 0xff; | ||
| 148 | /* fall-through */ | ||
| 149 | case 2: | ||
| 150 | dest8[1] = (val >> 8) & 0xff; | ||
| 151 | /* fall-through */ | ||
| 152 | case 1: | ||
| 153 | dest8[0] = val & 0xff; | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | static int jz4725b_bch_wait_complete(struct ingenic_ecc *bch, unsigned int irq, | ||
| 159 | u32 *status) | ||
| 160 | { | ||
| 161 | u32 reg; | ||
| 162 | int ret; | ||
| 163 | |||
| 164 | /* | ||
| 165 | * While we could use interrupts here and sleep until the operation | ||
| 166 | * completes, the controller works fairly quickly (usually a few | ||
| 167 | * microseconds) and so the overhead of sleeping until we get an | ||
| 168 | * interrupt quite noticeably decreases performance. | ||
| 169 | */ | ||
| 170 | ret = readl_relaxed_poll_timeout(bch->base + BCH_BHINT, reg, | ||
| 171 | reg & irq, 0, BCH_TIMEOUT_US); | ||
| 172 | if (ret) | ||
| 173 | return ret; | ||
| 174 | |||
| 175 | if (status) | ||
| 176 | *status = reg; | ||
| 177 | |||
| 178 | writel(reg, bch->base + BCH_BHINT); | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | static int jz4725b_calculate(struct ingenic_ecc *bch, | ||
| 184 | struct ingenic_ecc_params *params, | ||
| 185 | const u8 *buf, u8 *ecc_code) | ||
| 186 | { | ||
| 187 | int ret; | ||
| 188 | |||
| 189 | mutex_lock(&bch->lock); | ||
| 190 | |||
| 191 | ret = jz4725b_bch_reset(bch, params, true); | ||
| 192 | if (ret) { | ||
| 193 | dev_err(bch->dev, "Unable to init BCH with given parameters\n"); | ||
| 194 | goto out_disable; | ||
| 195 | } | ||
| 196 | |||
| 197 | jz4725b_bch_write_data(bch, buf, params->size); | ||
| 198 | |||
| 199 | ret = jz4725b_bch_wait_complete(bch, BCH_BHINT_ENCF, NULL); | ||
| 200 | if (ret) { | ||
| 201 | dev_err(bch->dev, "timed out while calculating ECC\n"); | ||
| 202 | goto out_disable; | ||
| 203 | } | ||
| 204 | |||
| 205 | jz4725b_bch_read_parity(bch, ecc_code, params->bytes); | ||
| 206 | |||
| 207 | out_disable: | ||
| 208 | jz4725b_bch_disable(bch); | ||
| 209 | mutex_unlock(&bch->lock); | ||
| 210 | |||
| 211 | return ret; | ||
| 212 | } | ||
| 213 | |||
| 214 | static int jz4725b_correct(struct ingenic_ecc *bch, | ||
| 215 | struct ingenic_ecc_params *params, | ||
| 216 | u8 *buf, u8 *ecc_code) | ||
| 217 | { | ||
| 218 | u32 reg, errors, bit; | ||
| 219 | unsigned int i; | ||
| 220 | int ret; | ||
| 221 | |||
| 222 | mutex_lock(&bch->lock); | ||
| 223 | |||
| 224 | ret = jz4725b_bch_reset(bch, params, false); | ||
| 225 | if (ret) { | ||
| 226 | dev_err(bch->dev, "Unable to init BCH with given parameters\n"); | ||
| 227 | goto out; | ||
| 228 | } | ||
| 229 | |||
| 230 | jz4725b_bch_write_data(bch, buf, params->size); | ||
| 231 | jz4725b_bch_write_data(bch, ecc_code, params->bytes); | ||
| 232 | |||
| 233 | ret = jz4725b_bch_wait_complete(bch, BCH_BHINT_DECF, ®); | ||
| 234 | if (ret) { | ||
| 235 | dev_err(bch->dev, "timed out while correcting data\n"); | ||
| 236 | goto out; | ||
| 237 | } | ||
| 238 | |||
| 239 | if (reg & (BCH_BHINT_ALL_F | BCH_BHINT_ALL_0)) { | ||
| 240 | /* Data and ECC is all 0xff or 0x00 - nothing to correct */ | ||
| 241 | ret = 0; | ||
| 242 | goto out; | ||
| 243 | } | ||
| 244 | |||
| 245 | if (reg & BCH_BHINT_UNCOR) { | ||
| 246 | /* Uncorrectable ECC error */ | ||
| 247 | ret = -EBADMSG; | ||
| 248 | goto out; | ||
| 249 | } | ||
| 250 | |||
| 251 | errors = (reg & BCH_BHINT_ERRC_MASK) >> BCH_BHINT_ERRC_SHIFT; | ||
| 252 | |||
| 253 | /* Correct any detected errors. */ | ||
| 254 | for (i = 0; i < errors; i++) { | ||
| 255 | if (i & 1) { | ||
| 256 | bit = (reg & BCH_BHERR_INDEX1_MASK) >> BCH_BHERR_INDEX1_SHIFT; | ||
| 257 | } else { | ||
| 258 | reg = readl(bch->base + BCH_BHERR0 + (i * 4)); | ||
| 259 | bit = (reg & BCH_BHERR_INDEX0_MASK) >> BCH_BHERR_INDEX0_SHIFT; | ||
| 260 | } | ||
| 261 | |||
| 262 | buf[(bit >> 3)] ^= BIT(bit & 0x7); | ||
| 263 | } | ||
| 264 | |||
| 265 | out: | ||
| 266 | jz4725b_bch_disable(bch); | ||
| 267 | mutex_unlock(&bch->lock); | ||
| 268 | |||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 272 | static const struct ingenic_ecc_ops jz4725b_bch_ops = { | ||
| 273 | .disable = jz4725b_bch_disable, | ||
| 274 | .calculate = jz4725b_calculate, | ||
| 275 | .correct = jz4725b_correct, | ||
| 276 | }; | ||
| 277 | |||
| 278 | static const struct of_device_id jz4725b_bch_dt_match[] = { | ||
| 279 | { .compatible = "ingenic,jz4725b-bch", .data = &jz4725b_bch_ops }, | ||
| 280 | {}, | ||
| 281 | }; | ||
| 282 | MODULE_DEVICE_TABLE(of, jz4725b_bch_dt_match); | ||
| 283 | |||
| 284 | static struct platform_driver jz4725b_bch_driver = { | ||
| 285 | .probe = ingenic_ecc_probe, | ||
| 286 | .driver = { | ||
| 287 | .name = "jz4725b-bch", | ||
| 288 | .of_match_table = jz4725b_bch_dt_match, | ||
| 289 | }, | ||
| 290 | }; | ||
| 291 | module_platform_driver(jz4725b_bch_driver); | ||
| 292 | |||
| 293 | MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); | ||
| 294 | MODULE_DESCRIPTION("Ingenic JZ4725B BCH controller driver"); | ||
| 295 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mtd/nand/raw/ingenic/jz4740_ecc.c b/drivers/mtd/nand/raw/ingenic/jz4740_ecc.c new file mode 100644 index 000000000000..13fea645c7f0 --- /dev/null +++ b/drivers/mtd/nand/raw/ingenic/jz4740_ecc.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * JZ4740 ECC controller driver | ||
| 4 | * | ||
| 5 | * Copyright (c) 2019 Paul Cercueil <paul@crapouillou.net> | ||
| 6 | * | ||
| 7 | * based on jz4740-nand.c | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/bitops.h> | ||
| 11 | #include <linux/device.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/of_platform.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | |||
| 17 | #include "ingenic_ecc.h" | ||
| 18 | |||
| 19 | #define JZ_REG_NAND_ECC_CTRL 0x00 | ||
| 20 | #define JZ_REG_NAND_DATA 0x04 | ||
| 21 | #define JZ_REG_NAND_PAR0 0x08 | ||
| 22 | #define JZ_REG_NAND_PAR1 0x0C | ||
| 23 | #define JZ_REG_NAND_PAR2 0x10 | ||
| 24 | #define JZ_REG_NAND_IRQ_STAT 0x14 | ||
| 25 | #define JZ_REG_NAND_IRQ_CTRL 0x18 | ||
| 26 | #define JZ_REG_NAND_ERR(x) (0x1C + ((x) << 2)) | ||
| 27 | |||
| 28 | #define JZ_NAND_ECC_CTRL_PAR_READY BIT(4) | ||
| 29 | #define JZ_NAND_ECC_CTRL_ENCODING BIT(3) | ||
| 30 | #define JZ_NAND_ECC_CTRL_RS BIT(2) | ||
| 31 | #define JZ_NAND_ECC_CTRL_RESET BIT(1) | ||
| 32 | #define JZ_NAND_ECC_CTRL_ENABLE BIT(0) | ||
| 33 | |||
| 34 | #define JZ_NAND_STATUS_ERR_COUNT (BIT(31) | BIT(30) | BIT(29)) | ||
| 35 | #define JZ_NAND_STATUS_PAD_FINISH BIT(4) | ||
| 36 | #define JZ_NAND_STATUS_DEC_FINISH BIT(3) | ||
| 37 | #define JZ_NAND_STATUS_ENC_FINISH BIT(2) | ||
| 38 | #define JZ_NAND_STATUS_UNCOR_ERROR BIT(1) | ||
| 39 | #define JZ_NAND_STATUS_ERROR BIT(0) | ||
| 40 | |||
| 41 | static const uint8_t empty_block_ecc[] = { | ||
| 42 | 0xcd, 0x9d, 0x90, 0x58, 0xf4, 0x8b, 0xff, 0xb7, 0x6f | ||
| 43 | }; | ||
| 44 | |||
| 45 | static void jz4740_ecc_reset(struct ingenic_ecc *ecc, bool calc_ecc) | ||
| 46 | { | ||
| 47 | uint32_t reg; | ||
| 48 | |||
| 49 | /* Clear interrupt status */ | ||
| 50 | writel(0, ecc->base + JZ_REG_NAND_IRQ_STAT); | ||
| 51 | |||
| 52 | /* Initialize and enable ECC hardware */ | ||
| 53 | reg = readl(ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 54 | reg |= JZ_NAND_ECC_CTRL_RESET; | ||
| 55 | reg |= JZ_NAND_ECC_CTRL_ENABLE; | ||
| 56 | reg |= JZ_NAND_ECC_CTRL_RS; | ||
| 57 | if (calc_ecc) /* calculate ECC from data */ | ||
| 58 | reg |= JZ_NAND_ECC_CTRL_ENCODING; | ||
| 59 | else /* correct data from ECC */ | ||
| 60 | reg &= ~JZ_NAND_ECC_CTRL_ENCODING; | ||
| 61 | |||
| 62 | writel(reg, ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 63 | } | ||
| 64 | |||
| 65 | static int jz4740_ecc_calculate(struct ingenic_ecc *ecc, | ||
| 66 | struct ingenic_ecc_params *params, | ||
| 67 | const u8 *buf, u8 *ecc_code) | ||
| 68 | { | ||
| 69 | uint32_t reg, status; | ||
| 70 | unsigned int timeout = 1000; | ||
| 71 | int i; | ||
| 72 | |||
| 73 | jz4740_ecc_reset(ecc, true); | ||
| 74 | |||
| 75 | do { | ||
| 76 | status = readl(ecc->base + JZ_REG_NAND_IRQ_STAT); | ||
| 77 | } while (!(status & JZ_NAND_STATUS_ENC_FINISH) && --timeout); | ||
| 78 | |||
| 79 | if (timeout == 0) | ||
| 80 | return -ETIMEDOUT; | ||
| 81 | |||
| 82 | reg = readl(ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 83 | reg &= ~JZ_NAND_ECC_CTRL_ENABLE; | ||
| 84 | writel(reg, ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 85 | |||
| 86 | for (i = 0; i < params->bytes; ++i) | ||
| 87 | ecc_code[i] = readb(ecc->base + JZ_REG_NAND_PAR0 + i); | ||
| 88 | |||
| 89 | /* | ||
| 90 | * If the written data is completely 0xff, we also want to write 0xff as | ||
| 91 | * ECC, otherwise we will get in trouble when doing subpage writes. | ||
| 92 | */ | ||
| 93 | if (memcmp(ecc_code, empty_block_ecc, ARRAY_SIZE(empty_block_ecc)) == 0) | ||
| 94 | memset(ecc_code, 0xff, ARRAY_SIZE(empty_block_ecc)); | ||
| 95 | |||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | static void jz_nand_correct_data(uint8_t *buf, int index, int mask) | ||
| 100 | { | ||
| 101 | int offset = index & 0x7; | ||
| 102 | uint16_t data; | ||
| 103 | |||
| 104 | index += (index >> 3); | ||
| 105 | |||
| 106 | data = buf[index]; | ||
| 107 | data |= buf[index + 1] << 8; | ||
| 108 | |||
| 109 | mask ^= (data >> offset) & 0x1ff; | ||
| 110 | data &= ~(0x1ff << offset); | ||
| 111 | data |= (mask << offset); | ||
| 112 | |||
| 113 | buf[index] = data & 0xff; | ||
| 114 | buf[index + 1] = (data >> 8) & 0xff; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int jz4740_ecc_correct(struct ingenic_ecc *ecc, | ||
| 118 | struct ingenic_ecc_params *params, | ||
| 119 | u8 *buf, u8 *ecc_code) | ||
| 120 | { | ||
| 121 | int i, error_count, index; | ||
| 122 | uint32_t reg, status, error; | ||
| 123 | unsigned int timeout = 1000; | ||
| 124 | |||
| 125 | jz4740_ecc_reset(ecc, false); | ||
| 126 | |||
| 127 | for (i = 0; i < params->bytes; ++i) | ||
| 128 | writeb(ecc_code[i], ecc->base + JZ_REG_NAND_PAR0 + i); | ||
| 129 | |||
| 130 | reg = readl(ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 131 | reg |= JZ_NAND_ECC_CTRL_PAR_READY; | ||
| 132 | writel(reg, ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 133 | |||
| 134 | do { | ||
| 135 | status = readl(ecc->base + JZ_REG_NAND_IRQ_STAT); | ||
| 136 | } while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout); | ||
| 137 | |||
| 138 | if (timeout == 0) | ||
| 139 | return -ETIMEDOUT; | ||
| 140 | |||
| 141 | reg = readl(ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 142 | reg &= ~JZ_NAND_ECC_CTRL_ENABLE; | ||
| 143 | writel(reg, ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 144 | |||
| 145 | if (status & JZ_NAND_STATUS_ERROR) { | ||
| 146 | if (status & JZ_NAND_STATUS_UNCOR_ERROR) | ||
| 147 | return -EBADMSG; | ||
| 148 | |||
| 149 | error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29; | ||
| 150 | |||
| 151 | for (i = 0; i < error_count; ++i) { | ||
| 152 | error = readl(ecc->base + JZ_REG_NAND_ERR(i)); | ||
| 153 | index = ((error >> 16) & 0x1ff) - 1; | ||
| 154 | if (index >= 0 && index < params->size) | ||
| 155 | jz_nand_correct_data(buf, index, error & 0x1ff); | ||
| 156 | } | ||
| 157 | |||
| 158 | return error_count; | ||
| 159 | } | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static void jz4740_ecc_disable(struct ingenic_ecc *ecc) | ||
| 165 | { | ||
| 166 | u32 reg; | ||
| 167 | |||
| 168 | writel(0, ecc->base + JZ_REG_NAND_IRQ_STAT); | ||
| 169 | reg = readl(ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 170 | reg &= ~JZ_NAND_ECC_CTRL_ENABLE; | ||
| 171 | writel(reg, ecc->base + JZ_REG_NAND_ECC_CTRL); | ||
| 172 | } | ||
| 173 | |||
| 174 | static const struct ingenic_ecc_ops jz4740_ecc_ops = { | ||
| 175 | .disable = jz4740_ecc_disable, | ||
| 176 | .calculate = jz4740_ecc_calculate, | ||
| 177 | .correct = jz4740_ecc_correct, | ||
| 178 | }; | ||
| 179 | |||
| 180 | static const struct of_device_id jz4740_ecc_dt_match[] = { | ||
| 181 | { .compatible = "ingenic,jz4740-ecc", .data = &jz4740_ecc_ops }, | ||
| 182 | {}, | ||
| 183 | }; | ||
| 184 | MODULE_DEVICE_TABLE(of, jz4740_ecc_dt_match); | ||
| 185 | |||
| 186 | static struct platform_driver jz4740_ecc_driver = { | ||
| 187 | .probe = ingenic_ecc_probe, | ||
| 188 | .driver = { | ||
| 189 | .name = "jz4740-ecc", | ||
| 190 | .of_match_table = jz4740_ecc_dt_match, | ||
| 191 | }, | ||
| 192 | }; | ||
| 193 | module_platform_driver(jz4740_ecc_driver); | ||
| 194 | |||
| 195 | MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); | ||
| 196 | MODULE_DESCRIPTION("Ingenic JZ4740 ECC controller driver"); | ||
| 197 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/ingenic/jz4740_nand.c index 9526d5b23c80..f759f1672855 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/ingenic/jz4740_nand.c | |||
| @@ -313,8 +313,11 @@ static int jz_nand_detect_bank(struct platform_device *pdev, | |||
| 313 | uint32_t ctrl; | 313 | uint32_t ctrl; |
| 314 | struct nand_chip *chip = &nand->chip; | 314 | struct nand_chip *chip = &nand->chip; |
| 315 | struct mtd_info *mtd = nand_to_mtd(chip); | 315 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 316 | struct nand_memory_organization *memorg; | ||
| 316 | u8 id[2]; | 317 | u8 id[2]; |
| 317 | 318 | ||
| 319 | memorg = nanddev_get_memorg(&chip->base); | ||
| 320 | |||
| 318 | /* Request I/O resource. */ | 321 | /* Request I/O resource. */ |
| 319 | sprintf(res_name, "bank%d", bank); | 322 | sprintf(res_name, "bank%d", bank); |
| 320 | ret = jz_nand_ioremap_resource(pdev, res_name, | 323 | ret = jz_nand_ioremap_resource(pdev, res_name, |
| @@ -351,8 +354,8 @@ static int jz_nand_detect_bank(struct platform_device *pdev, | |||
| 351 | } | 354 | } |
| 352 | 355 | ||
| 353 | /* Update size of the MTD. */ | 356 | /* Update size of the MTD. */ |
| 354 | chip->numchips++; | 357 | memorg->ntargets++; |
| 355 | mtd->size += chip->chipsize; | 358 | mtd->size += nanddev_target_size(&chip->base); |
| 356 | } | 359 | } |
| 357 | 360 | ||
| 358 | dev_info(&pdev->dev, "Found chip %zu on bank %i\n", chipnr, bank); | 361 | dev_info(&pdev->dev, "Found chip %zu on bank %i\n", chipnr, bank); |
diff --git a/drivers/mtd/nand/raw/jz4780_bch.c b/drivers/mtd/nand/raw/ingenic/jz4780_bch.c index c5f74ed85862..079266a0d6cf 100644 --- a/drivers/mtd/nand/raw/jz4780_bch.c +++ b/drivers/mtd/nand/raw/ingenic/jz4780_bch.c | |||
| @@ -1,28 +1,22 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * JZ4780 BCH controller | 3 | * JZ4780 BCH controller driver |
| 3 | * | 4 | * |
| 4 | * Copyright (c) 2015 Imagination Technologies | 5 | * Copyright (c) 2015 Imagination Technologies |
| 5 | * Author: Alex Smith <alex.smith@imgtec.com> | 6 | * Author: Alex Smith <alex.smith@imgtec.com> |
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published | ||
| 9 | * by the Free Software Foundation. | ||
| 10 | */ | 7 | */ |
| 11 | 8 | ||
| 12 | #include <linux/bitops.h> | 9 | #include <linux/bitops.h> |
| 13 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
| 14 | #include <linux/delay.h> | 11 | #include <linux/device.h> |
| 15 | #include <linux/init.h> | 12 | #include <linux/io.h> |
| 16 | #include <linux/iopoll.h> | 13 | #include <linux/iopoll.h> |
| 17 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 18 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_platform.h> | 16 | #include <linux/of_platform.h> |
| 21 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 22 | #include <linux/sched.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | 18 | ||
| 25 | #include "jz4780_bch.h" | 19 | #include "ingenic_ecc.h" |
| 26 | 20 | ||
| 27 | #define BCH_BHCR 0x0 | 21 | #define BCH_BHCR 0x0 |
| 28 | #define BCH_BHCCR 0x8 | 22 | #define BCH_BHCCR 0x8 |
| @@ -65,15 +59,8 @@ | |||
| 65 | /* Timeout for BCH calculation/correction. */ | 59 | /* Timeout for BCH calculation/correction. */ |
| 66 | #define BCH_TIMEOUT_US 100000 | 60 | #define BCH_TIMEOUT_US 100000 |
| 67 | 61 | ||
| 68 | struct jz4780_bch { | 62 | static void jz4780_bch_reset(struct ingenic_ecc *bch, |
| 69 | struct device *dev; | 63 | struct ingenic_ecc_params *params, bool encode) |
| 70 | void __iomem *base; | ||
| 71 | struct clk *clk; | ||
| 72 | struct mutex lock; | ||
| 73 | }; | ||
| 74 | |||
| 75 | static void jz4780_bch_init(struct jz4780_bch *bch, | ||
| 76 | struct jz4780_bch_params *params, bool encode) | ||
| 77 | { | 64 | { |
| 78 | u32 reg; | 65 | u32 reg; |
| 79 | 66 | ||
| @@ -93,13 +80,13 @@ static void jz4780_bch_init(struct jz4780_bch *bch, | |||
| 93 | writel(reg, bch->base + BCH_BHCR); | 80 | writel(reg, bch->base + BCH_BHCR); |
| 94 | } | 81 | } |
| 95 | 82 | ||
| 96 | static void jz4780_bch_disable(struct jz4780_bch *bch) | 83 | static void jz4780_bch_disable(struct ingenic_ecc *bch) |
| 97 | { | 84 | { |
| 98 | writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT); | 85 | writel(readl(bch->base + BCH_BHINT), bch->base + BCH_BHINT); |
| 99 | writel(BCH_BHCR_BCHE, bch->base + BCH_BHCCR); | 86 | writel(BCH_BHCR_BCHE, bch->base + BCH_BHCCR); |
| 100 | } | 87 | } |
| 101 | 88 | ||
| 102 | static void jz4780_bch_write_data(struct jz4780_bch *bch, const void *buf, | 89 | static void jz4780_bch_write_data(struct ingenic_ecc *bch, const void *buf, |
| 103 | size_t size) | 90 | size_t size) |
| 104 | { | 91 | { |
| 105 | size_t size32 = size / sizeof(u32); | 92 | size_t size32 = size / sizeof(u32); |
| @@ -116,7 +103,7 @@ static void jz4780_bch_write_data(struct jz4780_bch *bch, const void *buf, | |||
| 116 | writeb(*src8++, bch->base + BCH_BHDR); | 103 | writeb(*src8++, bch->base + BCH_BHDR); |
| 117 | } | 104 | } |
| 118 | 105 | ||
| 119 | static void jz4780_bch_read_parity(struct jz4780_bch *bch, void *buf, | 106 | static void jz4780_bch_read_parity(struct ingenic_ecc *bch, void *buf, |
| 120 | size_t size) | 107 | size_t size) |
| 121 | { | 108 | { |
| 122 | size_t size32 = size / sizeof(u32); | 109 | size_t size32 = size / sizeof(u32); |
| @@ -146,7 +133,7 @@ static void jz4780_bch_read_parity(struct jz4780_bch *bch, void *buf, | |||
| 146 | } | 133 | } |
| 147 | } | 134 | } |
| 148 | 135 | ||
| 149 | static bool jz4780_bch_wait_complete(struct jz4780_bch *bch, unsigned int irq, | 136 | static bool jz4780_bch_wait_complete(struct ingenic_ecc *bch, unsigned int irq, |
| 150 | u32 *status) | 137 | u32 *status) |
| 151 | { | 138 | { |
| 152 | u32 reg; | 139 | u32 reg; |
| @@ -170,23 +157,15 @@ static bool jz4780_bch_wait_complete(struct jz4780_bch *bch, unsigned int irq, | |||
| 170 | return true; | 157 | return true; |
| 171 | } | 158 | } |
| 172 | 159 | ||
| 173 | /** | 160 | static int jz4780_calculate(struct ingenic_ecc *bch, |
| 174 | * jz4780_bch_calculate() - calculate ECC for a data buffer | 161 | struct ingenic_ecc_params *params, |
| 175 | * @bch: BCH device. | 162 | const u8 *buf, u8 *ecc_code) |
| 176 | * @params: BCH parameters. | ||
| 177 | * @buf: input buffer with raw data. | ||
| 178 | * @ecc_code: output buffer with ECC. | ||
| 179 | * | ||
| 180 | * Return: 0 on success, -ETIMEDOUT if timed out while waiting for BCH | ||
| 181 | * controller. | ||
| 182 | */ | ||
| 183 | int jz4780_bch_calculate(struct jz4780_bch *bch, struct jz4780_bch_params *params, | ||
| 184 | const u8 *buf, u8 *ecc_code) | ||
| 185 | { | 163 | { |
| 186 | int ret = 0; | 164 | int ret = 0; |
| 187 | 165 | ||
| 188 | mutex_lock(&bch->lock); | 166 | mutex_lock(&bch->lock); |
| 189 | jz4780_bch_init(bch, params, true); | 167 | |
| 168 | jz4780_bch_reset(bch, params, true); | ||
| 190 | jz4780_bch_write_data(bch, buf, params->size); | 169 | jz4780_bch_write_data(bch, buf, params->size); |
| 191 | 170 | ||
| 192 | if (jz4780_bch_wait_complete(bch, BCH_BHINT_ENCF, NULL)) { | 171 | if (jz4780_bch_wait_complete(bch, BCH_BHINT_ENCF, NULL)) { |
| @@ -200,30 +179,17 @@ int jz4780_bch_calculate(struct jz4780_bch *bch, struct jz4780_bch_params *param | |||
| 200 | mutex_unlock(&bch->lock); | 179 | mutex_unlock(&bch->lock); |
| 201 | return ret; | 180 | return ret; |
| 202 | } | 181 | } |
| 203 | EXPORT_SYMBOL(jz4780_bch_calculate); | 182 | |
| 204 | 183 | static int jz4780_correct(struct ingenic_ecc *bch, | |
| 205 | /** | 184 | struct ingenic_ecc_params *params, |
| 206 | * jz4780_bch_correct() - detect and correct bit errors | 185 | u8 *buf, u8 *ecc_code) |
| 207 | * @bch: BCH device. | ||
| 208 | * @params: BCH parameters. | ||
| 209 | * @buf: raw data read from the chip. | ||
| 210 | * @ecc_code: ECC read from the chip. | ||
| 211 | * | ||
| 212 | * Given the raw data and the ECC read from the NAND device, detects and | ||
| 213 | * corrects errors in the data. | ||
| 214 | * | ||
| 215 | * Return: the number of bit errors corrected, -EBADMSG if there are too many | ||
| 216 | * errors to correct or -ETIMEDOUT if we timed out waiting for the controller. | ||
| 217 | */ | ||
| 218 | int jz4780_bch_correct(struct jz4780_bch *bch, struct jz4780_bch_params *params, | ||
| 219 | u8 *buf, u8 *ecc_code) | ||
| 220 | { | 186 | { |
| 221 | u32 reg, mask, index; | 187 | u32 reg, mask, index; |
| 222 | int i, ret, count; | 188 | int i, ret, count; |
| 223 | 189 | ||
| 224 | mutex_lock(&bch->lock); | 190 | mutex_lock(&bch->lock); |
| 225 | 191 | ||
| 226 | jz4780_bch_init(bch, params, false); | 192 | jz4780_bch_reset(bch, params, false); |
| 227 | jz4780_bch_write_data(bch, buf, params->size); | 193 | jz4780_bch_write_data(bch, buf, params->size); |
| 228 | jz4780_bch_write_data(bch, ecc_code, params->bytes); | 194 | jz4780_bch_write_data(bch, ecc_code, params->bytes); |
| 229 | 195 | ||
| @@ -262,110 +228,30 @@ out: | |||
| 262 | mutex_unlock(&bch->lock); | 228 | mutex_unlock(&bch->lock); |
| 263 | return ret; | 229 | return ret; |
| 264 | } | 230 | } |
| 265 | EXPORT_SYMBOL(jz4780_bch_correct); | ||
| 266 | |||
| 267 | /** | ||
| 268 | * jz4780_bch_get() - get the BCH controller device | ||
| 269 | * @np: BCH device tree node. | ||
| 270 | * | ||
| 271 | * Gets the BCH controller device from the specified device tree node. The | ||
| 272 | * device must be released with jz4780_bch_release() when it is no longer being | ||
| 273 | * used. | ||
| 274 | * | ||
| 275 | * Return: a pointer to jz4780_bch, errors are encoded into the pointer. | ||
| 276 | * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. | ||
| 277 | */ | ||
| 278 | static struct jz4780_bch *jz4780_bch_get(struct device_node *np) | ||
| 279 | { | ||
| 280 | struct platform_device *pdev; | ||
| 281 | struct jz4780_bch *bch; | ||
| 282 | |||
| 283 | pdev = of_find_device_by_node(np); | ||
| 284 | if (!pdev) | ||
| 285 | return ERR_PTR(-EPROBE_DEFER); | ||
| 286 | |||
| 287 | bch = platform_get_drvdata(pdev); | ||
| 288 | if (!bch) { | ||
| 289 | put_device(&pdev->dev); | ||
| 290 | return ERR_PTR(-EPROBE_DEFER); | ||
| 291 | } | ||
| 292 | |||
| 293 | clk_prepare_enable(bch->clk); | ||
| 294 | |||
| 295 | return bch; | ||
| 296 | } | ||
| 297 | |||
| 298 | /** | ||
| 299 | * of_jz4780_bch_get() - get the BCH controller from a DT node | ||
| 300 | * @of_node: the node that contains a bch-controller property. | ||
| 301 | * | ||
| 302 | * Get the bch-controller property from the given device tree | ||
| 303 | * node and pass it to jz4780_bch_get to do the work. | ||
| 304 | * | ||
| 305 | * Return: a pointer to jz4780_bch, errors are encoded into the pointer. | ||
| 306 | * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. | ||
| 307 | */ | ||
| 308 | struct jz4780_bch *of_jz4780_bch_get(struct device_node *of_node) | ||
| 309 | { | ||
| 310 | struct jz4780_bch *bch = NULL; | ||
| 311 | struct device_node *np; | ||
| 312 | |||
| 313 | np = of_parse_phandle(of_node, "ingenic,bch-controller", 0); | ||
| 314 | |||
| 315 | if (np) { | ||
| 316 | bch = jz4780_bch_get(np); | ||
| 317 | of_node_put(np); | ||
| 318 | } | ||
| 319 | return bch; | ||
| 320 | } | ||
| 321 | EXPORT_SYMBOL(of_jz4780_bch_get); | ||
| 322 | |||
| 323 | /** | ||
| 324 | * jz4780_bch_release() - release the BCH controller device | ||
| 325 | * @bch: BCH device. | ||
| 326 | */ | ||
| 327 | void jz4780_bch_release(struct jz4780_bch *bch) | ||
| 328 | { | ||
| 329 | clk_disable_unprepare(bch->clk); | ||
| 330 | put_device(bch->dev); | ||
| 331 | } | ||
| 332 | EXPORT_SYMBOL(jz4780_bch_release); | ||
| 333 | 231 | ||
| 334 | static int jz4780_bch_probe(struct platform_device *pdev) | 232 | static int jz4780_bch_probe(struct platform_device *pdev) |
| 335 | { | 233 | { |
| 336 | struct device *dev = &pdev->dev; | 234 | struct ingenic_ecc *bch; |
| 337 | struct jz4780_bch *bch; | 235 | int ret; |
| 338 | struct resource *res; | ||
| 339 | |||
| 340 | bch = devm_kzalloc(dev, sizeof(*bch), GFP_KERNEL); | ||
| 341 | if (!bch) | ||
| 342 | return -ENOMEM; | ||
| 343 | |||
| 344 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 345 | bch->base = devm_ioremap_resource(dev, res); | ||
| 346 | if (IS_ERR(bch->base)) | ||
| 347 | return PTR_ERR(bch->base); | ||
| 348 | |||
| 349 | jz4780_bch_disable(bch); | ||
| 350 | 236 | ||
| 351 | bch->clk = devm_clk_get(dev, NULL); | 237 | ret = ingenic_ecc_probe(pdev); |
| 352 | if (IS_ERR(bch->clk)) { | 238 | if (ret) |
| 353 | dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(bch->clk)); | 239 | return ret; |
| 354 | return PTR_ERR(bch->clk); | ||
| 355 | } | ||
| 356 | 240 | ||
| 241 | bch = platform_get_drvdata(pdev); | ||
| 357 | clk_set_rate(bch->clk, BCH_CLK_RATE); | 242 | clk_set_rate(bch->clk, BCH_CLK_RATE); |
| 358 | 243 | ||
| 359 | mutex_init(&bch->lock); | ||
| 360 | |||
| 361 | bch->dev = dev; | ||
| 362 | platform_set_drvdata(pdev, bch); | ||
| 363 | |||
| 364 | return 0; | 244 | return 0; |
| 365 | } | 245 | } |
| 366 | 246 | ||
| 247 | static const struct ingenic_ecc_ops jz4780_bch_ops = { | ||
| 248 | .disable = jz4780_bch_disable, | ||
| 249 | .calculate = jz4780_calculate, | ||
| 250 | .correct = jz4780_correct, | ||
| 251 | }; | ||
| 252 | |||
| 367 | static const struct of_device_id jz4780_bch_dt_match[] = { | 253 | static const struct of_device_id jz4780_bch_dt_match[] = { |
| 368 | { .compatible = "ingenic,jz4780-bch" }, | 254 | { .compatible = "ingenic,jz4780-bch", .data = &jz4780_bch_ops }, |
| 369 | {}, | 255 | {}, |
| 370 | }; | 256 | }; |
| 371 | MODULE_DEVICE_TABLE(of, jz4780_bch_dt_match); | 257 | MODULE_DEVICE_TABLE(of, jz4780_bch_dt_match); |
diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index fbf6ca015cd7..cba6fe7dd8c4 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h | |||
| @@ -76,6 +76,7 @@ extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops; | |||
| 76 | 76 | ||
| 77 | /* Core functions */ | 77 | /* Core functions */ |
| 78 | const struct nand_manufacturer *nand_get_manufacturer(u8 id); | 78 | const struct nand_manufacturer *nand_get_manufacturer(u8 id); |
| 79 | int nand_bbm_get_next_page(struct nand_chip *chip, int page); | ||
| 79 | int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); | 80 | int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); |
| 80 | int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, | 81 | int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, |
| 81 | int allowbbt); | 82 | int allowbbt); |
| @@ -110,7 +111,7 @@ static inline int nand_exec_op(struct nand_chip *chip, | |||
| 110 | if (!nand_has_exec_op(chip)) | 111 | if (!nand_has_exec_op(chip)) |
| 111 | return -ENOTSUPP; | 112 | return -ENOTSUPP; |
| 112 | 113 | ||
| 113 | if (WARN_ON(op->cs >= chip->numchips)) | 114 | if (WARN_ON(op->cs >= nanddev_ntargets(&chip->base))) |
| 114 | return -EINVAL; | 115 | return -EINVAL; |
| 115 | 116 | ||
| 116 | return chip->controller->ops->exec_op(chip, op, false); | 117 | return chip->controller->ops->exec_op(chip, op, false); |
diff --git a/drivers/mtd/nand/raw/jz4780_bch.h b/drivers/mtd/nand/raw/jz4780_bch.h deleted file mode 100644 index bf4718088a3a..000000000000 --- a/drivers/mtd/nand/raw/jz4780_bch.h +++ /dev/null | |||
| @@ -1,43 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * JZ4780 BCH controller | ||
| 3 | * | ||
| 4 | * Copyright (c) 2015 Imagination Technologies | ||
| 5 | * Author: Alex Smith <alex.smith@imgtec.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published | ||
| 9 | * by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef __DRIVERS_MTD_NAND_JZ4780_BCH_H__ | ||
| 13 | #define __DRIVERS_MTD_NAND_JZ4780_BCH_H__ | ||
| 14 | |||
| 15 | #include <linux/types.h> | ||
| 16 | |||
| 17 | struct device; | ||
| 18 | struct device_node; | ||
| 19 | struct jz4780_bch; | ||
| 20 | |||
| 21 | /** | ||
| 22 | * struct jz4780_bch_params - BCH parameters | ||
| 23 | * @size: data bytes per ECC step. | ||
| 24 | * @bytes: ECC bytes per step. | ||
| 25 | * @strength: number of correctable bits per ECC step. | ||
| 26 | */ | ||
| 27 | struct jz4780_bch_params { | ||
| 28 | int size; | ||
| 29 | int bytes; | ||
| 30 | int strength; | ||
| 31 | }; | ||
| 32 | |||
| 33 | int jz4780_bch_calculate(struct jz4780_bch *bch, | ||
| 34 | struct jz4780_bch_params *params, | ||
| 35 | const u8 *buf, u8 *ecc_code); | ||
| 36 | int jz4780_bch_correct(struct jz4780_bch *bch, | ||
| 37 | struct jz4780_bch_params *params, u8 *buf, | ||
| 38 | u8 *ecc_code); | ||
| 39 | |||
| 40 | void jz4780_bch_release(struct jz4780_bch *bch); | ||
| 41 | struct jz4780_bch *of_jz4780_bch_get(struct device_node *np); | ||
| 42 | |||
| 43 | #endif /* __DRIVERS_MTD_NAND_JZ4780_BCH_H__ */ | ||
diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c deleted file mode 100644 index 22e58975f0d5..000000000000 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ /dev/null | |||
| @@ -1,415 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * JZ4780 NAND driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2015 Imagination Technologies | ||
| 5 | * Author: Alex Smith <alex.smith@imgtec.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published | ||
| 9 | * by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/list.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/of_address.h> | ||
| 19 | #include <linux/gpio/consumer.h> | ||
| 20 | #include <linux/platform_device.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/mtd/mtd.h> | ||
| 23 | #include <linux/mtd/rawnand.h> | ||
| 24 | #include <linux/mtd/partitions.h> | ||
| 25 | |||
| 26 | #include <linux/jz4780-nemc.h> | ||
| 27 | |||
| 28 | #include "jz4780_bch.h" | ||
| 29 | |||
| 30 | #define DRV_NAME "jz4780-nand" | ||
| 31 | |||
| 32 | #define OFFSET_DATA 0x00000000 | ||
| 33 | #define OFFSET_CMD 0x00400000 | ||
| 34 | #define OFFSET_ADDR 0x00800000 | ||
| 35 | |||
| 36 | /* Command delay when there is no R/B pin. */ | ||
| 37 | #define RB_DELAY_US 100 | ||
| 38 | |||
| 39 | struct jz4780_nand_cs { | ||
| 40 | unsigned int bank; | ||
| 41 | void __iomem *base; | ||
| 42 | }; | ||
| 43 | |||
| 44 | struct jz4780_nand_controller { | ||
| 45 | struct device *dev; | ||
| 46 | struct jz4780_bch *bch; | ||
| 47 | struct nand_controller controller; | ||
| 48 | unsigned int num_banks; | ||
| 49 | struct list_head chips; | ||
| 50 | int selected; | ||
| 51 | struct jz4780_nand_cs cs[]; | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct jz4780_nand_chip { | ||
| 55 | struct nand_chip chip; | ||
| 56 | struct list_head chip_list; | ||
| 57 | |||
| 58 | struct gpio_desc *busy_gpio; | ||
| 59 | struct gpio_desc *wp_gpio; | ||
| 60 | unsigned int reading: 1; | ||
| 61 | }; | ||
| 62 | |||
| 63 | static inline struct jz4780_nand_chip *to_jz4780_nand_chip(struct mtd_info *mtd) | ||
| 64 | { | ||
| 65 | return container_of(mtd_to_nand(mtd), struct jz4780_nand_chip, chip); | ||
| 66 | } | ||
| 67 | |||
| 68 | static inline struct jz4780_nand_controller | ||
| 69 | *to_jz4780_nand_controller(struct nand_controller *ctrl) | ||
| 70 | { | ||
| 71 | return container_of(ctrl, struct jz4780_nand_controller, controller); | ||
| 72 | } | ||
| 73 | |||
| 74 | static void jz4780_nand_select_chip(struct nand_chip *chip, int chipnr) | ||
| 75 | { | ||
| 76 | struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); | ||
| 77 | struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); | ||
| 78 | struct jz4780_nand_cs *cs; | ||
| 79 | |||
| 80 | /* Ensure the currently selected chip is deasserted. */ | ||
| 81 | if (chipnr == -1 && nfc->selected >= 0) { | ||
| 82 | cs = &nfc->cs[nfc->selected]; | ||
| 83 | jz4780_nemc_assert(nfc->dev, cs->bank, false); | ||
| 84 | } | ||
| 85 | |||
| 86 | nfc->selected = chipnr; | ||
| 87 | } | ||
| 88 | |||
| 89 | static void jz4780_nand_cmd_ctrl(struct nand_chip *chip, int cmd, | ||
| 90 | unsigned int ctrl) | ||
| 91 | { | ||
| 92 | struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); | ||
| 93 | struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); | ||
| 94 | struct jz4780_nand_cs *cs; | ||
| 95 | |||
| 96 | if (WARN_ON(nfc->selected < 0)) | ||
| 97 | return; | ||
| 98 | |||
| 99 | cs = &nfc->cs[nfc->selected]; | ||
| 100 | |||
| 101 | jz4780_nemc_assert(nfc->dev, cs->bank, ctrl & NAND_NCE); | ||
| 102 | |||
| 103 | if (cmd == NAND_CMD_NONE) | ||
| 104 | return; | ||
| 105 | |||
| 106 | if (ctrl & NAND_ALE) | ||
| 107 | writeb(cmd, cs->base + OFFSET_ADDR); | ||
| 108 | else if (ctrl & NAND_CLE) | ||
| 109 | writeb(cmd, cs->base + OFFSET_CMD); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int jz4780_nand_dev_ready(struct nand_chip *chip) | ||
| 113 | { | ||
| 114 | struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); | ||
| 115 | |||
| 116 | return !gpiod_get_value_cansleep(nand->busy_gpio); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void jz4780_nand_ecc_hwctl(struct nand_chip *chip, int mode) | ||
| 120 | { | ||
| 121 | struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); | ||
| 122 | |||
| 123 | nand->reading = (mode == NAND_ECC_READ); | ||
| 124 | } | ||
| 125 | |||
| 126 | static int jz4780_nand_ecc_calculate(struct nand_chip *chip, const u8 *dat, | ||
| 127 | u8 *ecc_code) | ||
| 128 | { | ||
| 129 | struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); | ||
| 130 | struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); | ||
| 131 | struct jz4780_bch_params params; | ||
| 132 | |||
| 133 | /* | ||
| 134 | * Don't need to generate the ECC when reading, BCH does it for us as | ||
| 135 | * part of decoding/correction. | ||
| 136 | */ | ||
| 137 | if (nand->reading) | ||
| 138 | return 0; | ||
| 139 | |||
| 140 | params.size = nand->chip.ecc.size; | ||
| 141 | params.bytes = nand->chip.ecc.bytes; | ||
| 142 | params.strength = nand->chip.ecc.strength; | ||
| 143 | |||
| 144 | return jz4780_bch_calculate(nfc->bch, ¶ms, dat, ecc_code); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int jz4780_nand_ecc_correct(struct nand_chip *chip, u8 *dat, | ||
| 148 | u8 *read_ecc, u8 *calc_ecc) | ||
| 149 | { | ||
| 150 | struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); | ||
| 151 | struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); | ||
| 152 | struct jz4780_bch_params params; | ||
| 153 | |||
| 154 | params.size = nand->chip.ecc.size; | ||
| 155 | params.bytes = nand->chip.ecc.bytes; | ||
| 156 | params.strength = nand->chip.ecc.strength; | ||
| 157 | |||
| 158 | return jz4780_bch_correct(nfc->bch, ¶ms, dat, read_ecc); | ||
| 159 | } | ||
| 160 | |||
| 161 | static int jz4780_nand_attach_chip(struct nand_chip *chip) | ||
| 162 | { | ||
| 163 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 164 | struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller); | ||
| 165 | int eccbytes; | ||
| 166 | |||
| 167 | chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) * | ||
| 168 | (chip->ecc.strength / 8); | ||
| 169 | |||
| 170 | switch (chip->ecc.mode) { | ||
| 171 | case NAND_ECC_HW: | ||
| 172 | if (!nfc->bch) { | ||
| 173 | dev_err(nfc->dev, | ||
| 174 | "HW BCH selected, but BCH controller not found\n"); | ||
| 175 | return -ENODEV; | ||
| 176 | } | ||
| 177 | |||
| 178 | chip->ecc.hwctl = jz4780_nand_ecc_hwctl; | ||
| 179 | chip->ecc.calculate = jz4780_nand_ecc_calculate; | ||
| 180 | chip->ecc.correct = jz4780_nand_ecc_correct; | ||
| 181 | /* fall through */ | ||
| 182 | case NAND_ECC_SOFT: | ||
| 183 | dev_info(nfc->dev, "using %s (strength %d, size %d, bytes %d)\n", | ||
| 184 | (nfc->bch) ? "hardware BCH" : "software ECC", | ||
| 185 | chip->ecc.strength, chip->ecc.size, chip->ecc.bytes); | ||
| 186 | break; | ||
| 187 | case NAND_ECC_NONE: | ||
| 188 | dev_info(nfc->dev, "not using ECC\n"); | ||
| 189 | break; | ||
| 190 | default: | ||
| 191 | dev_err(nfc->dev, "ECC mode %d not supported\n", | ||
| 192 | chip->ecc.mode); | ||
| 193 | return -EINVAL; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* The NAND core will generate the ECC layout for SW ECC */ | ||
| 197 | if (chip->ecc.mode != NAND_ECC_HW) | ||
| 198 | return 0; | ||
| 199 | |||
| 200 | /* Generate ECC layout. ECC codes are right aligned in the OOB area. */ | ||
| 201 | eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes; | ||
| 202 | |||
| 203 | if (eccbytes > mtd->oobsize - 2) { | ||
| 204 | dev_err(nfc->dev, | ||
| 205 | "invalid ECC config: required %d ECC bytes, but only %d are available", | ||
| 206 | eccbytes, mtd->oobsize - 2); | ||
| 207 | return -EINVAL; | ||
| 208 | } | ||
| 209 | |||
| 210 | mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); | ||
| 211 | |||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | static const struct nand_controller_ops jz4780_nand_controller_ops = { | ||
| 216 | .attach_chip = jz4780_nand_attach_chip, | ||
| 217 | }; | ||
| 218 | |||
| 219 | static int jz4780_nand_init_chip(struct platform_device *pdev, | ||
| 220 | struct jz4780_nand_controller *nfc, | ||
| 221 | struct device_node *np, | ||
| 222 | unsigned int chipnr) | ||
| 223 | { | ||
| 224 | struct device *dev = &pdev->dev; | ||
| 225 | struct jz4780_nand_chip *nand; | ||
| 226 | struct jz4780_nand_cs *cs; | ||
| 227 | struct resource *res; | ||
| 228 | struct nand_chip *chip; | ||
| 229 | struct mtd_info *mtd; | ||
| 230 | const __be32 *reg; | ||
| 231 | int ret = 0; | ||
| 232 | |||
| 233 | cs = &nfc->cs[chipnr]; | ||
| 234 | |||
| 235 | reg = of_get_property(np, "reg", NULL); | ||
| 236 | if (!reg) | ||
| 237 | return -EINVAL; | ||
| 238 | |||
| 239 | cs->bank = be32_to_cpu(*reg); | ||
| 240 | |||
| 241 | jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND); | ||
| 242 | |||
| 243 | res = platform_get_resource(pdev, IORESOURCE_MEM, chipnr); | ||
| 244 | cs->base = devm_ioremap_resource(dev, res); | ||
| 245 | if (IS_ERR(cs->base)) | ||
| 246 | return PTR_ERR(cs->base); | ||
| 247 | |||
| 248 | nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL); | ||
| 249 | if (!nand) | ||
| 250 | return -ENOMEM; | ||
| 251 | |||
| 252 | nand->busy_gpio = devm_gpiod_get_optional(dev, "rb", GPIOD_IN); | ||
| 253 | |||
| 254 | if (IS_ERR(nand->busy_gpio)) { | ||
| 255 | ret = PTR_ERR(nand->busy_gpio); | ||
| 256 | dev_err(dev, "failed to request busy GPIO: %d\n", ret); | ||
| 257 | return ret; | ||
| 258 | } else if (nand->busy_gpio) { | ||
| 259 | nand->chip.legacy.dev_ready = jz4780_nand_dev_ready; | ||
| 260 | } | ||
| 261 | |||
| 262 | nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); | ||
| 263 | |||
| 264 | if (IS_ERR(nand->wp_gpio)) { | ||
| 265 | ret = PTR_ERR(nand->wp_gpio); | ||
| 266 | dev_err(dev, "failed to request WP GPIO: %d\n", ret); | ||
| 267 | return ret; | ||
| 268 | } | ||
| 269 | |||
| 270 | chip = &nand->chip; | ||
| 271 | mtd = nand_to_mtd(chip); | ||
| 272 | mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), | ||
| 273 | cs->bank); | ||
| 274 | if (!mtd->name) | ||
| 275 | return -ENOMEM; | ||
| 276 | mtd->dev.parent = dev; | ||
| 277 | |||
| 278 | chip->legacy.IO_ADDR_R = cs->base + OFFSET_DATA; | ||
| 279 | chip->legacy.IO_ADDR_W = cs->base + OFFSET_DATA; | ||
| 280 | chip->legacy.chip_delay = RB_DELAY_US; | ||
| 281 | chip->options = NAND_NO_SUBPAGE_WRITE; | ||
| 282 | chip->legacy.select_chip = jz4780_nand_select_chip; | ||
| 283 | chip->legacy.cmd_ctrl = jz4780_nand_cmd_ctrl; | ||
| 284 | chip->ecc.mode = NAND_ECC_HW; | ||
| 285 | chip->controller = &nfc->controller; | ||
| 286 | nand_set_flash_node(chip, np); | ||
| 287 | |||
| 288 | chip->controller->ops = &jz4780_nand_controller_ops; | ||
| 289 | ret = nand_scan(chip, 1); | ||
| 290 | if (ret) | ||
| 291 | return ret; | ||
| 292 | |||
| 293 | ret = mtd_device_register(mtd, NULL, 0); | ||
| 294 | if (ret) { | ||
| 295 | nand_release(chip); | ||
| 296 | return ret; | ||
| 297 | } | ||
| 298 | |||
| 299 | list_add_tail(&nand->chip_list, &nfc->chips); | ||
| 300 | |||
| 301 | return 0; | ||
| 302 | } | ||
| 303 | |||
| 304 | static void jz4780_nand_cleanup_chips(struct jz4780_nand_controller *nfc) | ||
| 305 | { | ||
| 306 | struct jz4780_nand_chip *chip; | ||
| 307 | |||
| 308 | while (!list_empty(&nfc->chips)) { | ||
| 309 | chip = list_first_entry(&nfc->chips, struct jz4780_nand_chip, chip_list); | ||
| 310 | nand_release(&chip->chip); | ||
| 311 | list_del(&chip->chip_list); | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | static int jz4780_nand_init_chips(struct jz4780_nand_controller *nfc, | ||
| 316 | struct platform_device *pdev) | ||
| 317 | { | ||
| 318 | struct device *dev = &pdev->dev; | ||
| 319 | struct device_node *np; | ||
| 320 | int i = 0; | ||
| 321 | int ret; | ||
| 322 | int num_chips = of_get_child_count(dev->of_node); | ||
| 323 | |||
| 324 | if (num_chips > nfc->num_banks) { | ||
| 325 | dev_err(dev, "found %d chips but only %d banks\n", num_chips, nfc->num_banks); | ||
| 326 | return -EINVAL; | ||
| 327 | } | ||
| 328 | |||
| 329 | for_each_child_of_node(dev->of_node, np) { | ||
| 330 | ret = jz4780_nand_init_chip(pdev, nfc, np, i); | ||
| 331 | if (ret) { | ||
| 332 | jz4780_nand_cleanup_chips(nfc); | ||
| 333 | return ret; | ||
| 334 | } | ||
| 335 | |||
| 336 | i++; | ||
| 337 | } | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | |||
| 342 | static int jz4780_nand_probe(struct platform_device *pdev) | ||
| 343 | { | ||
| 344 | struct device *dev = &pdev->dev; | ||
| 345 | unsigned int num_banks; | ||
| 346 | struct jz4780_nand_controller *nfc; | ||
| 347 | int ret; | ||
| 348 | |||
| 349 | num_banks = jz4780_nemc_num_banks(dev); | ||
| 350 | if (num_banks == 0) { | ||
| 351 | dev_err(dev, "no banks found\n"); | ||
| 352 | return -ENODEV; | ||
| 353 | } | ||
| 354 | |||
| 355 | nfc = devm_kzalloc(dev, struct_size(nfc, cs, num_banks), GFP_KERNEL); | ||
| 356 | if (!nfc) | ||
| 357 | return -ENOMEM; | ||
| 358 | |||
| 359 | /* | ||
| 360 | * Check for BCH HW before we call nand_scan_ident, to prevent us from | ||
| 361 | * having to call it again if the BCH driver returns -EPROBE_DEFER. | ||
| 362 | */ | ||
| 363 | nfc->bch = of_jz4780_bch_get(dev->of_node); | ||
| 364 | if (IS_ERR(nfc->bch)) | ||
| 365 | return PTR_ERR(nfc->bch); | ||
| 366 | |||
| 367 | nfc->dev = dev; | ||
| 368 | nfc->num_banks = num_banks; | ||
| 369 | |||
| 370 | nand_controller_init(&nfc->controller); | ||
| 371 | INIT_LIST_HEAD(&nfc->chips); | ||
| 372 | |||
| 373 | ret = jz4780_nand_init_chips(nfc, pdev); | ||
| 374 | if (ret) { | ||
| 375 | if (nfc->bch) | ||
| 376 | jz4780_bch_release(nfc->bch); | ||
| 377 | return ret; | ||
| 378 | } | ||
| 379 | |||
| 380 | platform_set_drvdata(pdev, nfc); | ||
| 381 | return 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | static int jz4780_nand_remove(struct platform_device *pdev) | ||
| 385 | { | ||
| 386 | struct jz4780_nand_controller *nfc = platform_get_drvdata(pdev); | ||
| 387 | |||
| 388 | if (nfc->bch) | ||
| 389 | jz4780_bch_release(nfc->bch); | ||
| 390 | |||
| 391 | jz4780_nand_cleanup_chips(nfc); | ||
| 392 | |||
| 393 | return 0; | ||
| 394 | } | ||
| 395 | |||
| 396 | static const struct of_device_id jz4780_nand_dt_match[] = { | ||
| 397 | { .compatible = "ingenic,jz4780-nand" }, | ||
| 398 | {}, | ||
| 399 | }; | ||
| 400 | MODULE_DEVICE_TABLE(of, jz4780_nand_dt_match); | ||
| 401 | |||
| 402 | static struct platform_driver jz4780_nand_driver = { | ||
| 403 | .probe = jz4780_nand_probe, | ||
| 404 | .remove = jz4780_nand_remove, | ||
| 405 | .driver = { | ||
| 406 | .name = DRV_NAME, | ||
| 407 | .of_match_table = of_match_ptr(jz4780_nand_dt_match), | ||
| 408 | }, | ||
| 409 | }; | ||
| 410 | module_platform_driver(jz4780_nand_driver); | ||
| 411 | |||
| 412 | MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>"); | ||
| 413 | MODULE_AUTHOR("Harvey Hunt <harveyhuntnexus@gmail.com>"); | ||
| 414 | MODULE_DESCRIPTION("Ingenic JZ4780 NAND driver"); | ||
| 415 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index d984538980e2..fc49e13d81ec 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c | |||
| @@ -1083,12 +1083,11 @@ static int marvell_nfc_hw_ecc_hmg_read_page(struct nand_chip *chip, u8 *buf, | |||
| 1083 | */ | 1083 | */ |
| 1084 | static int marvell_nfc_hw_ecc_hmg_read_oob_raw(struct nand_chip *chip, int page) | 1084 | static int marvell_nfc_hw_ecc_hmg_read_oob_raw(struct nand_chip *chip, int page) |
| 1085 | { | 1085 | { |
| 1086 | /* Invalidate page cache */ | 1086 | u8 *buf = nand_get_data_buf(chip); |
| 1087 | chip->pagebuf = -1; | ||
| 1088 | 1087 | ||
| 1089 | marvell_nfc_select_target(chip, chip->cur_cs); | 1088 | marvell_nfc_select_target(chip, chip->cur_cs); |
| 1090 | return marvell_nfc_hw_ecc_hmg_do_read_page(chip, chip->data_buf, | 1089 | return marvell_nfc_hw_ecc_hmg_do_read_page(chip, buf, chip->oob_poi, |
| 1091 | chip->oob_poi, true, page); | 1090 | true, page); |
| 1092 | } | 1091 | } |
| 1093 | 1092 | ||
| 1094 | /* Hamming write helpers */ | 1093 | /* Hamming write helpers */ |
| @@ -1179,15 +1178,13 @@ static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct nand_chip *chip, | |||
| 1179 | int page) | 1178 | int page) |
| 1180 | { | 1179 | { |
| 1181 | struct mtd_info *mtd = nand_to_mtd(chip); | 1180 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 1181 | u8 *buf = nand_get_data_buf(chip); | ||
| 1182 | 1182 | ||
| 1183 | /* Invalidate page cache */ | 1183 | memset(buf, 0xFF, mtd->writesize); |
| 1184 | chip->pagebuf = -1; | ||
| 1185 | |||
| 1186 | memset(chip->data_buf, 0xFF, mtd->writesize); | ||
| 1187 | 1184 | ||
| 1188 | marvell_nfc_select_target(chip, chip->cur_cs); | 1185 | marvell_nfc_select_target(chip, chip->cur_cs); |
| 1189 | return marvell_nfc_hw_ecc_hmg_do_write_page(chip, chip->data_buf, | 1186 | return marvell_nfc_hw_ecc_hmg_do_write_page(chip, buf, chip->oob_poi, |
| 1190 | chip->oob_poi, true, page); | 1187 | true, page); |
| 1191 | } | 1188 | } |
| 1192 | 1189 | ||
| 1193 | /* BCH read helpers */ | 1190 | /* BCH read helpers */ |
| @@ -1434,18 +1431,16 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, | |||
| 1434 | 1431 | ||
| 1435 | static int marvell_nfc_hw_ecc_bch_read_oob_raw(struct nand_chip *chip, int page) | 1432 | static int marvell_nfc_hw_ecc_bch_read_oob_raw(struct nand_chip *chip, int page) |
| 1436 | { | 1433 | { |
| 1437 | /* Invalidate page cache */ | 1434 | u8 *buf = nand_get_data_buf(chip); |
| 1438 | chip->pagebuf = -1; | ||
| 1439 | 1435 | ||
| 1440 | return chip->ecc.read_page_raw(chip, chip->data_buf, true, page); | 1436 | return chip->ecc.read_page_raw(chip, buf, true, page); |
| 1441 | } | 1437 | } |
| 1442 | 1438 | ||
| 1443 | static int marvell_nfc_hw_ecc_bch_read_oob(struct nand_chip *chip, int page) | 1439 | static int marvell_nfc_hw_ecc_bch_read_oob(struct nand_chip *chip, int page) |
| 1444 | { | 1440 | { |
| 1445 | /* Invalidate page cache */ | 1441 | u8 *buf = nand_get_data_buf(chip); |
| 1446 | chip->pagebuf = -1; | ||
| 1447 | 1442 | ||
| 1448 | return chip->ecc.read_page(chip, chip->data_buf, true, page); | 1443 | return chip->ecc.read_page(chip, buf, true, page); |
| 1449 | } | 1444 | } |
| 1450 | 1445 | ||
| 1451 | /* BCH write helpers */ | 1446 | /* BCH write helpers */ |
| @@ -1619,25 +1614,21 @@ static int marvell_nfc_hw_ecc_bch_write_oob_raw(struct nand_chip *chip, | |||
| 1619 | int page) | 1614 | int page) |
| 1620 | { | 1615 | { |
| 1621 | struct mtd_info *mtd = nand_to_mtd(chip); | 1616 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 1617 | u8 *buf = nand_get_data_buf(chip); | ||
| 1622 | 1618 | ||
| 1623 | /* Invalidate page cache */ | 1619 | memset(buf, 0xFF, mtd->writesize); |
| 1624 | chip->pagebuf = -1; | ||
| 1625 | |||
| 1626 | memset(chip->data_buf, 0xFF, mtd->writesize); | ||
| 1627 | 1620 | ||
| 1628 | return chip->ecc.write_page_raw(chip, chip->data_buf, true, page); | 1621 | return chip->ecc.write_page_raw(chip, buf, true, page); |
| 1629 | } | 1622 | } |
| 1630 | 1623 | ||
| 1631 | static int marvell_nfc_hw_ecc_bch_write_oob(struct nand_chip *chip, int page) | 1624 | static int marvell_nfc_hw_ecc_bch_write_oob(struct nand_chip *chip, int page) |
| 1632 | { | 1625 | { |
| 1633 | struct mtd_info *mtd = nand_to_mtd(chip); | 1626 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 1627 | u8 *buf = nand_get_data_buf(chip); | ||
| 1634 | 1628 | ||
| 1635 | /* Invalidate page cache */ | 1629 | memset(buf, 0xFF, mtd->writesize); |
| 1636 | chip->pagebuf = -1; | ||
| 1637 | |||
| 1638 | memset(chip->data_buf, 0xFF, mtd->writesize); | ||
| 1639 | 1630 | ||
| 1640 | return chip->ecc.write_page(chip, chip->data_buf, true, page); | 1631 | return chip->ecc.write_page(chip, buf, true, page); |
| 1641 | } | 1632 | } |
| 1642 | 1633 | ||
| 1643 | /* NAND framework ->exec_op() hooks and related helpers */ | 1634 | /* NAND framework ->exec_op() hooks and related helpers */ |
| @@ -2257,9 +2248,9 @@ static int marvell_nand_ecc_init(struct mtd_info *mtd, | |||
| 2257 | int ret; | 2248 | int ret; |
| 2258 | 2249 | ||
| 2259 | if (ecc->mode != NAND_ECC_NONE && (!ecc->size || !ecc->strength)) { | 2250 | if (ecc->mode != NAND_ECC_NONE && (!ecc->size || !ecc->strength)) { |
| 2260 | if (chip->ecc_step_ds && chip->ecc_strength_ds) { | 2251 | if (chip->base.eccreq.step_size && chip->base.eccreq.strength) { |
| 2261 | ecc->size = chip->ecc_step_ds; | 2252 | ecc->size = chip->base.eccreq.step_size; |
| 2262 | ecc->strength = chip->ecc_strength_ds; | 2253 | ecc->strength = chip->base.eccreq.strength; |
| 2263 | } else { | 2254 | } else { |
| 2264 | dev_info(nfc->dev, | 2255 | dev_info(nfc->dev, |
| 2265 | "No minimum ECC strength, using 1b/512B\n"); | 2256 | "No minimum ECC strength, using 1b/512B\n"); |
| @@ -2989,7 +2980,7 @@ static int __maybe_unused marvell_nfc_resume(struct device *dev) | |||
| 2989 | 2980 | ||
| 2990 | /* | 2981 | /* |
| 2991 | * Reset nfc->selected_chip so the next command will cause the timing | 2982 | * Reset nfc->selected_chip so the next command will cause the timing |
| 2992 | * registers to be restored in marvell_nfc_select_chip(). | 2983 | * registers to be restored in marvell_nfc_select_target(). |
| 2993 | */ | 2984 | */ |
| 2994 | nfc->selected_chip = NULL; | 2985 | nfc->selected_chip = NULL; |
| 2995 | 2986 | ||
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 3e8aa71407b5..ea57ddcec41e 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c | |||
| @@ -400,7 +400,7 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) | |||
| 400 | cfg |= NFC_RB_IRQ_EN; | 400 | cfg |= NFC_RB_IRQ_EN; |
| 401 | writel(cfg, nfc->reg_base + NFC_REG_CFG); | 401 | writel(cfg, nfc->reg_base + NFC_REG_CFG); |
| 402 | 402 | ||
| 403 | init_completion(&nfc->completion); | 403 | reinit_completion(&nfc->completion); |
| 404 | 404 | ||
| 405 | /* use the max erase time as the maximum clock for waiting R/B */ | 405 | /* use the max erase time as the maximum clock for waiting R/B */ |
| 406 | cmd = NFC_CMD_RB | NFC_CMD_RB_INT | 406 | cmd = NFC_CMD_RB | NFC_CMD_RB_INT |
| @@ -470,15 +470,15 @@ static int meson_nfc_ecc_correct(struct nand_chip *nand, u32 *bitflips, | |||
| 470 | return ret; | 470 | return ret; |
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | static int meson_nfc_dma_buffer_setup(struct nand_chip *nand, u8 *databuf, | 473 | static int meson_nfc_dma_buffer_setup(struct nand_chip *nand, void *databuf, |
| 474 | int datalen, u8 *infobuf, int infolen, | 474 | int datalen, void *infobuf, int infolen, |
| 475 | enum dma_data_direction dir) | 475 | enum dma_data_direction dir) |
| 476 | { | 476 | { |
| 477 | struct meson_nfc *nfc = nand_get_controller_data(nand); | 477 | struct meson_nfc *nfc = nand_get_controller_data(nand); |
| 478 | u32 cmd; | 478 | u32 cmd; |
| 479 | int ret = 0; | 479 | int ret = 0; |
| 480 | 480 | ||
| 481 | nfc->daddr = dma_map_single(nfc->dev, (void *)databuf, datalen, dir); | 481 | nfc->daddr = dma_map_single(nfc->dev, databuf, datalen, dir); |
| 482 | ret = dma_mapping_error(nfc->dev, nfc->daddr); | 482 | ret = dma_mapping_error(nfc->dev, nfc->daddr); |
| 483 | if (ret) { | 483 | if (ret) { |
| 484 | dev_err(nfc->dev, "DMA mapping error\n"); | 484 | dev_err(nfc->dev, "DMA mapping error\n"); |
| @@ -528,10 +528,13 @@ static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) | |||
| 528 | u8 *info; | 528 | u8 *info; |
| 529 | 529 | ||
| 530 | info = kzalloc(PER_INFO_BYTE, GFP_KERNEL); | 530 | info = kzalloc(PER_INFO_BYTE, GFP_KERNEL); |
| 531 | if (!info) | ||
| 532 | return -ENOMEM; | ||
| 533 | |||
| 531 | ret = meson_nfc_dma_buffer_setup(nand, buf, len, info, | 534 | ret = meson_nfc_dma_buffer_setup(nand, buf, len, info, |
| 532 | PER_INFO_BYTE, DMA_FROM_DEVICE); | 535 | PER_INFO_BYTE, DMA_FROM_DEVICE); |
| 533 | if (ret) | 536 | if (ret) |
| 534 | return ret; | 537 | goto out; |
| 535 | 538 | ||
| 536 | cmd = NFC_CMD_N2M | (len & GENMASK(5, 0)); | 539 | cmd = NFC_CMD_N2M | (len & GENMASK(5, 0)); |
| 537 | writel(cmd, nfc->reg_base + NFC_REG_CMD); | 540 | writel(cmd, nfc->reg_base + NFC_REG_CMD); |
| @@ -539,6 +542,8 @@ static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) | |||
| 539 | meson_nfc_drain_cmd(nfc); | 542 | meson_nfc_drain_cmd(nfc); |
| 540 | meson_nfc_wait_cmd_finish(nfc, 1000); | 543 | meson_nfc_wait_cmd_finish(nfc, 1000); |
| 541 | meson_nfc_dma_buffer_release(nand, len, PER_INFO_BYTE, DMA_FROM_DEVICE); | 544 | meson_nfc_dma_buffer_release(nand, len, PER_INFO_BYTE, DMA_FROM_DEVICE); |
| 545 | |||
| 546 | out: | ||
| 542 | kfree(info); | 547 | kfree(info); |
| 543 | 548 | ||
| 544 | return ret; | 549 | return ret; |
| @@ -640,7 +645,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand, | |||
| 640 | return ret; | 645 | return ret; |
| 641 | 646 | ||
| 642 | ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf, | 647 | ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf, |
| 643 | data_len, (u8 *)meson_chip->info_buf, | 648 | data_len, meson_chip->info_buf, |
| 644 | info_len, DMA_TO_DEVICE); | 649 | info_len, DMA_TO_DEVICE); |
| 645 | if (ret) | 650 | if (ret) |
| 646 | return ret; | 651 | return ret; |
| @@ -724,7 +729,7 @@ static int meson_nfc_read_page_sub(struct nand_chip *nand, | |||
| 724 | return ret; | 729 | return ret; |
| 725 | 730 | ||
| 726 | ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf, | 731 | ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf, |
| 727 | data_len, (u8 *)meson_chip->info_buf, | 732 | data_len, meson_chip->info_buf, |
| 728 | info_len, DMA_FROM_DEVICE); | 733 | info_len, DMA_FROM_DEVICE); |
| 729 | if (ret) | 734 | if (ret) |
| 730 | return ret; | 735 | return ret; |
| @@ -1183,6 +1188,8 @@ static int meson_nand_attach_chip(struct nand_chip *nand) | |||
| 1183 | return -EINVAL; | 1188 | return -EINVAL; |
| 1184 | } | 1189 | } |
| 1185 | 1190 | ||
| 1191 | mtd_set_ooblayout(mtd, &meson_ooblayout_ops); | ||
| 1192 | |||
| 1186 | ret = meson_nand_bch_mode(nand); | 1193 | ret = meson_nand_bch_mode(nand); |
| 1187 | if (ret) | 1194 | if (ret) |
| 1188 | return -EINVAL; | 1195 | return -EINVAL; |
| @@ -1226,17 +1233,13 @@ meson_nfc_nand_chip_init(struct device *dev, | |||
| 1226 | int ret, i; | 1233 | int ret, i; |
| 1227 | u32 tmp, nsels; | 1234 | u32 tmp, nsels; |
| 1228 | 1235 | ||
| 1229 | if (!of_get_property(np, "reg", &nsels)) | 1236 | nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32)); |
| 1230 | return -EINVAL; | ||
| 1231 | |||
| 1232 | nsels /= sizeof(u32); | ||
| 1233 | if (!nsels || nsels > MAX_CE_NUM) { | 1237 | if (!nsels || nsels > MAX_CE_NUM) { |
| 1234 | dev_err(dev, "invalid register property size\n"); | 1238 | dev_err(dev, "invalid register property size\n"); |
| 1235 | return -EINVAL; | 1239 | return -EINVAL; |
| 1236 | } | 1240 | } |
| 1237 | 1241 | ||
| 1238 | meson_chip = devm_kzalloc(dev, | 1242 | meson_chip = devm_kzalloc(dev, struct_size(meson_chip, sels, nsels), |
| 1239 | sizeof(*meson_chip) + (nsels * sizeof(u8)), | ||
| 1240 | GFP_KERNEL); | 1243 | GFP_KERNEL); |
| 1241 | if (!meson_chip) | 1244 | if (!meson_chip) |
| 1242 | return -ENOMEM; | 1245 | return -ENOMEM; |
| @@ -1377,6 +1380,7 @@ static int meson_nfc_probe(struct platform_device *pdev) | |||
| 1377 | 1380 | ||
| 1378 | nand_controller_init(&nfc->controller); | 1381 | nand_controller_init(&nfc->controller); |
| 1379 | INIT_LIST_HEAD(&nfc->chips); | 1382 | INIT_LIST_HEAD(&nfc->chips); |
| 1383 | init_completion(&nfc->completion); | ||
| 1380 | 1384 | ||
| 1381 | nfc->dev = dev; | 1385 | nfc->dev = dev; |
| 1382 | 1386 | ||
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 2c0e09187773..b17619f30b1b 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c | |||
| @@ -1197,8 +1197,8 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd) | |||
| 1197 | /* if optional dt settings not present */ | 1197 | /* if optional dt settings not present */ |
| 1198 | if (!nand->ecc.size || !nand->ecc.strength) { | 1198 | if (!nand->ecc.size || !nand->ecc.strength) { |
| 1199 | /* use datasheet requirements */ | 1199 | /* use datasheet requirements */ |
| 1200 | nand->ecc.strength = nand->ecc_strength_ds; | 1200 | nand->ecc.strength = nand->base.eccreq.strength; |
| 1201 | nand->ecc.size = nand->ecc_step_ds; | 1201 | nand->ecc.size = nand->base.eccreq.step_size; |
| 1202 | 1202 | ||
| 1203 | /* | 1203 | /* |
| 1204 | * align eccstrength and eccsize | 1204 | * align eccstrength and eccsize |
diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c index 890c5b43e03c..6217555c19a6 100644 --- a/drivers/mtd/nand/raw/nand_amd.c +++ b/drivers/mtd/nand/raw/nand_amd.c | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | static void amd_nand_decode_id(struct nand_chip *chip) | 20 | static void amd_nand_decode_id(struct nand_chip *chip) |
| 21 | { | 21 | { |
| 22 | struct mtd_info *mtd = nand_to_mtd(chip); | 22 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 23 | struct nand_memory_organization *memorg; | ||
| 24 | |||
| 25 | memorg = nanddev_get_memorg(&chip->base); | ||
| 23 | 26 | ||
| 24 | nand_decode_ext_id(chip); | 27 | nand_decode_ext_id(chip); |
| 25 | 28 | ||
| @@ -31,16 +34,24 @@ static void amd_nand_decode_id(struct nand_chip *chip) | |||
| 31 | */ | 34 | */ |
| 32 | if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 && | 35 | if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 && |
| 33 | chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 && | 36 | chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 && |
| 34 | mtd->writesize == 512) { | 37 | memorg->pagesize == 512) { |
| 35 | mtd->erasesize = 128 * 1024; | 38 | memorg->pages_per_eraseblock = 256; |
| 36 | mtd->erasesize <<= ((chip->id.data[3] & 0x03) << 1); | 39 | memorg->pages_per_eraseblock <<= ((chip->id.data[3] & 0x03) << 1); |
| 40 | mtd->erasesize = memorg->pages_per_eraseblock * | ||
| 41 | memorg->pagesize; | ||
| 37 | } | 42 | } |
| 38 | } | 43 | } |
| 39 | 44 | ||
| 40 | static int amd_nand_init(struct nand_chip *chip) | 45 | static int amd_nand_init(struct nand_chip *chip) |
| 41 | { | 46 | { |
| 42 | if (nand_is_slc(chip)) | 47 | if (nand_is_slc(chip)) |
| 43 | chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; | 48 | /* |
| 49 | * According to the datasheet of some Cypress SLC NANDs, | ||
| 50 | * the bad block markers can be in the first, second or last | ||
| 51 | * page of a block. So let's check all three locations. | ||
| 52 | */ | ||
| 53 | chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE | | ||
| 54 | NAND_BBM_LASTPAGE; | ||
| 44 | 55 | ||
| 45 | return 0; | 56 | return 0; |
| 46 | } | 57 | } |
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index ddd396e93e32..2cf71060d6f8 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c | |||
| @@ -240,10 +240,10 @@ static int check_offs_len(struct nand_chip *chip, loff_t ofs, uint64_t len) | |||
| 240 | void nand_select_target(struct nand_chip *chip, unsigned int cs) | 240 | void nand_select_target(struct nand_chip *chip, unsigned int cs) |
| 241 | { | 241 | { |
| 242 | /* | 242 | /* |
| 243 | * cs should always lie between 0 and chip->numchips, when that's not | 243 | * cs should always lie between 0 and nanddev_ntargets(), when that's |
| 244 | * the case it's a bug and the caller should be fixed. | 244 | * not the case it's a bug and the caller should be fixed. |
| 245 | */ | 245 | */ |
| 246 | if (WARN_ON(cs > chip->numchips)) | 246 | if (WARN_ON(cs > nanddev_ntargets(&chip->base))) |
| 247 | return; | 247 | return; |
| 248 | 248 | ||
| 249 | chip->cur_cs = cs; | 249 | chip->cur_cs = cs; |
| @@ -283,6 +283,31 @@ static void nand_release_device(struct nand_chip *chip) | |||
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | /** | 285 | /** |
| 286 | * nand_bbm_get_next_page - Get the next page for bad block markers | ||
| 287 | * @chip: NAND chip object | ||
| 288 | * @page: First page to start checking for bad block marker usage | ||
| 289 | * | ||
| 290 | * Returns an integer that corresponds to the page offset within a block, for | ||
| 291 | * a page that is used to store bad block markers. If no more pages are | ||
| 292 | * available, -EINVAL is returned. | ||
| 293 | */ | ||
| 294 | int nand_bbm_get_next_page(struct nand_chip *chip, int page) | ||
| 295 | { | ||
| 296 | struct mtd_info *mtd = nand_to_mtd(chip); | ||
| 297 | int last_page = ((mtd->erasesize - mtd->writesize) >> | ||
| 298 | chip->page_shift) & chip->pagemask; | ||
| 299 | |||
| 300 | if (page == 0 && chip->options & NAND_BBM_FIRSTPAGE) | ||
| 301 | return 0; | ||
| 302 | else if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE) | ||
| 303 | return 1; | ||
| 304 | else if (page <= last_page && chip->options & NAND_BBM_LASTPAGE) | ||
| 305 | return last_page; | ||
| 306 | |||
| 307 | return -EINVAL; | ||
| 308 | } | ||
| 309 | |||
| 310 | /** | ||
| 286 | * nand_block_bad - [DEFAULT] Read bad block marker from the chip | 311 | * nand_block_bad - [DEFAULT] Read bad block marker from the chip |
| 287 | * @chip: NAND chip object | 312 | * @chip: NAND chip object |
| 288 | * @ofs: offset from device start | 313 | * @ofs: offset from device start |
| @@ -291,18 +316,15 @@ static void nand_release_device(struct nand_chip *chip) | |||
| 291 | */ | 316 | */ |
| 292 | static int nand_block_bad(struct nand_chip *chip, loff_t ofs) | 317 | static int nand_block_bad(struct nand_chip *chip, loff_t ofs) |
| 293 | { | 318 | { |
| 294 | struct mtd_info *mtd = nand_to_mtd(chip); | 319 | int first_page, page_offset; |
| 295 | int page, page_end, res; | 320 | int res; |
| 296 | u8 bad; | 321 | u8 bad; |
| 297 | 322 | ||
| 298 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) | 323 | first_page = (int)(ofs >> chip->page_shift) & chip->pagemask; |
| 299 | ofs += mtd->erasesize - mtd->writesize; | 324 | page_offset = nand_bbm_get_next_page(chip, 0); |
| 300 | |||
| 301 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; | ||
| 302 | page_end = page + (chip->bbt_options & NAND_BBT_SCAN2NDPAGE ? 2 : 1); | ||
| 303 | 325 | ||
| 304 | for (; page < page_end; page++) { | 326 | while (page_offset >= 0) { |
| 305 | res = chip->ecc.read_oob(chip, page); | 327 | res = chip->ecc.read_oob(chip, first_page + page_offset); |
| 306 | if (res < 0) | 328 | if (res < 0) |
| 307 | return res; | 329 | return res; |
| 308 | 330 | ||
| @@ -314,6 +336,8 @@ static int nand_block_bad(struct nand_chip *chip, loff_t ofs) | |||
| 314 | res = hweight8(bad) < chip->badblockbits; | 336 | res = hweight8(bad) < chip->badblockbits; |
| 315 | if (res) | 337 | if (res) |
| 316 | return res; | 338 | return res; |
| 339 | |||
| 340 | page_offset = nand_bbm_get_next_page(chip, page_offset + 1); | ||
| 317 | } | 341 | } |
| 318 | 342 | ||
| 319 | return 0; | 343 | return 0; |
| @@ -459,8 +483,8 @@ static int nand_do_write_oob(struct nand_chip *chip, loff_t to, | |||
| 459 | } | 483 | } |
| 460 | 484 | ||
| 461 | /* Invalidate the page cache, if we write to the cached page */ | 485 | /* Invalidate the page cache, if we write to the cached page */ |
| 462 | if (page == chip->pagebuf) | 486 | if (page == chip->pagecache.page) |
| 463 | chip->pagebuf = -1; | 487 | chip->pagecache.page = -1; |
| 464 | 488 | ||
| 465 | nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops); | 489 | nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops); |
| 466 | 490 | ||
| @@ -493,7 +517,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs) | |||
| 493 | struct mtd_info *mtd = nand_to_mtd(chip); | 517 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 494 | struct mtd_oob_ops ops; | 518 | struct mtd_oob_ops ops; |
| 495 | uint8_t buf[2] = { 0, 0 }; | 519 | uint8_t buf[2] = { 0, 0 }; |
| 496 | int ret = 0, res, i = 0; | 520 | int ret = 0, res, page_offset; |
| 497 | 521 | ||
| 498 | memset(&ops, 0, sizeof(ops)); | 522 | memset(&ops, 0, sizeof(ops)); |
| 499 | ops.oobbuf = buf; | 523 | ops.oobbuf = buf; |
| @@ -506,17 +530,18 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs) | |||
| 506 | } | 530 | } |
| 507 | ops.mode = MTD_OPS_PLACE_OOB; | 531 | ops.mode = MTD_OPS_PLACE_OOB; |
| 508 | 532 | ||
| 509 | /* Write to first/last page(s) if necessary */ | 533 | page_offset = nand_bbm_get_next_page(chip, 0); |
| 510 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) | 534 | |
| 511 | ofs += mtd->erasesize - mtd->writesize; | 535 | while (page_offset >= 0) { |
| 512 | do { | 536 | res = nand_do_write_oob(chip, |
| 513 | res = nand_do_write_oob(chip, ofs, &ops); | 537 | ofs + (page_offset * mtd->writesize), |
| 538 | &ops); | ||
| 539 | |||
| 514 | if (!ret) | 540 | if (!ret) |
| 515 | ret = res; | 541 | ret = res; |
| 516 | 542 | ||
| 517 | i++; | 543 | page_offset = nand_bbm_get_next_page(chip, page_offset + 1); |
| 518 | ofs += mtd->writesize; | 544 | } |
| 519 | } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); | ||
| 520 | 545 | ||
| 521 | return ret; | 546 | return ret; |
| 522 | } | 547 | } |
| @@ -3173,7 +3198,7 @@ static int nand_do_read_ops(struct nand_chip *chip, loff_t from, | |||
| 3173 | use_bufpoi = 0; | 3198 | use_bufpoi = 0; |
| 3174 | 3199 | ||
| 3175 | /* Is the current page in the buffer? */ | 3200 | /* Is the current page in the buffer? */ |
| 3176 | if (realpage != chip->pagebuf || oob) { | 3201 | if (realpage != chip->pagecache.page || oob) { |
| 3177 | bufpoi = use_bufpoi ? chip->data_buf : buf; | 3202 | bufpoi = use_bufpoi ? chip->data_buf : buf; |
| 3178 | 3203 | ||
| 3179 | if (use_bufpoi && aligned) | 3204 | if (use_bufpoi && aligned) |
| @@ -3199,7 +3224,7 @@ read_retry: | |||
| 3199 | if (ret < 0) { | 3224 | if (ret < 0) { |
| 3200 | if (use_bufpoi) | 3225 | if (use_bufpoi) |
| 3201 | /* Invalidate page cache */ | 3226 | /* Invalidate page cache */ |
| 3202 | chip->pagebuf = -1; | 3227 | chip->pagecache.page = -1; |
| 3203 | break; | 3228 | break; |
| 3204 | } | 3229 | } |
| 3205 | 3230 | ||
| @@ -3208,11 +3233,11 @@ read_retry: | |||
| 3208 | if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && | 3233 | if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && |
| 3209 | !(mtd->ecc_stats.failed - ecc_failures) && | 3234 | !(mtd->ecc_stats.failed - ecc_failures) && |
| 3210 | (ops->mode != MTD_OPS_RAW)) { | 3235 | (ops->mode != MTD_OPS_RAW)) { |
| 3211 | chip->pagebuf = realpage; | 3236 | chip->pagecache.page = realpage; |
| 3212 | chip->pagebuf_bitflips = ret; | 3237 | chip->pagecache.bitflips = ret; |
| 3213 | } else { | 3238 | } else { |
| 3214 | /* Invalidate page cache */ | 3239 | /* Invalidate page cache */ |
| 3215 | chip->pagebuf = -1; | 3240 | chip->pagecache.page = -1; |
| 3216 | } | 3241 | } |
| 3217 | memcpy(buf, chip->data_buf + col, bytes); | 3242 | memcpy(buf, chip->data_buf + col, bytes); |
| 3218 | } | 3243 | } |
| @@ -3252,7 +3277,7 @@ read_retry: | |||
| 3252 | memcpy(buf, chip->data_buf + col, bytes); | 3277 | memcpy(buf, chip->data_buf + col, bytes); |
| 3253 | buf += bytes; | 3278 | buf += bytes; |
| 3254 | max_bitflips = max_t(unsigned int, max_bitflips, | 3279 | max_bitflips = max_t(unsigned int, max_bitflips, |
| 3255 | chip->pagebuf_bitflips); | 3280 | chip->pagecache.bitflips); |
| 3256 | } | 3281 | } |
| 3257 | 3282 | ||
| 3258 | readlen -= bytes; | 3283 | readlen -= bytes; |
| @@ -3973,9 +3998,9 @@ static int nand_do_write_ops(struct nand_chip *chip, loff_t to, | |||
| 3973 | page = realpage & chip->pagemask; | 3998 | page = realpage & chip->pagemask; |
| 3974 | 3999 | ||
| 3975 | /* Invalidate the page cache, when we write to the cached page */ | 4000 | /* Invalidate the page cache, when we write to the cached page */ |
| 3976 | if (to <= ((loff_t)chip->pagebuf << chip->page_shift) && | 4001 | if (to <= ((loff_t)chip->pagecache.page << chip->page_shift) && |
| 3977 | ((loff_t)chip->pagebuf << chip->page_shift) < (to + ops->len)) | 4002 | ((loff_t)chip->pagecache.page << chip->page_shift) < (to + ops->len)) |
| 3978 | chip->pagebuf = -1; | 4003 | chip->pagecache.page = -1; |
| 3979 | 4004 | ||
| 3980 | /* Don't allow multipage oob writes with offset */ | 4005 | /* Don't allow multipage oob writes with offset */ |
| 3981 | if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) { | 4006 | if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) { |
| @@ -4004,10 +4029,9 @@ static int nand_do_write_ops(struct nand_chip *chip, loff_t to, | |||
| 4004 | __func__, buf); | 4029 | __func__, buf); |
| 4005 | if (part_pagewr) | 4030 | if (part_pagewr) |
| 4006 | bytes = min_t(int, bytes - column, writelen); | 4031 | bytes = min_t(int, bytes - column, writelen); |
| 4007 | chip->pagebuf = -1; | 4032 | wbuf = nand_get_data_buf(chip); |
| 4008 | memset(chip->data_buf, 0xff, mtd->writesize); | 4033 | memset(wbuf, 0xff, mtd->writesize); |
| 4009 | memcpy(&chip->data_buf[column], buf, bytes); | 4034 | memcpy(&wbuf[column], buf, bytes); |
| 4010 | wbuf = chip->data_buf; | ||
| 4011 | } | 4035 | } |
| 4012 | 4036 | ||
| 4013 | if (unlikely(oob)) { | 4037 | if (unlikely(oob)) { |
| @@ -4197,9 +4221,9 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, | |||
| 4197 | * Invalidate the page cache, if we erase the block which | 4221 | * Invalidate the page cache, if we erase the block which |
| 4198 | * contains the current cached page. | 4222 | * contains the current cached page. |
| 4199 | */ | 4223 | */ |
| 4200 | if (page <= chip->pagebuf && chip->pagebuf < | 4224 | if (page <= chip->pagecache.page && chip->pagecache.page < |
| 4201 | (page + pages_per_block)) | 4225 | (page + pages_per_block)) |
| 4202 | chip->pagebuf = -1; | 4226 | chip->pagecache.page = -1; |
| 4203 | 4227 | ||
| 4204 | ret = nand_erase_op(chip, (page & chip->pagemask) >> | 4228 | ret = nand_erase_op(chip, (page & chip->pagemask) >> |
| 4205 | (chip->phys_erase_shift - chip->page_shift)); | 4229 | (chip->phys_erase_shift - chip->page_shift)); |
| @@ -4299,42 +4323,6 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
| 4299 | } | 4323 | } |
| 4300 | 4324 | ||
| 4301 | /** | 4325 | /** |
| 4302 | * nand_max_bad_blocks - [MTD Interface] Max number of bad blocks for an mtd | ||
| 4303 | * @mtd: MTD device structure | ||
| 4304 | * @ofs: offset relative to mtd start | ||
| 4305 | * @len: length of mtd | ||
| 4306 | */ | ||
| 4307 | static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len) | ||
| 4308 | { | ||
| 4309 | struct nand_chip *chip = mtd_to_nand(mtd); | ||
| 4310 | u32 part_start_block; | ||
| 4311 | u32 part_end_block; | ||
| 4312 | u32 part_start_die; | ||
| 4313 | u32 part_end_die; | ||
| 4314 | |||
| 4315 | /* | ||
| 4316 | * max_bb_per_die and blocks_per_die used to determine | ||
| 4317 | * the maximum bad block count. | ||
| 4318 | */ | ||
| 4319 | if (!chip->max_bb_per_die || !chip->blocks_per_die) | ||
| 4320 | return -ENOTSUPP; | ||
| 4321 | |||
| 4322 | /* Get the start and end of the partition in erase blocks. */ | ||
| 4323 | part_start_block = mtd_div_by_eb(ofs, mtd); | ||
| 4324 | part_end_block = mtd_div_by_eb(len, mtd) + part_start_block - 1; | ||
| 4325 | |||
| 4326 | /* Get the start and end LUNs of the partition. */ | ||
| 4327 | part_start_die = part_start_block / chip->blocks_per_die; | ||
| 4328 | part_end_die = part_end_block / chip->blocks_per_die; | ||
| 4329 | |||
| 4330 | /* | ||
| 4331 | * Look up the bad blocks per unit and multiply by the number of units | ||
| 4332 | * that the partition spans. | ||
| 4333 | */ | ||
| 4334 | return chip->max_bb_per_die * (part_end_die - part_start_die + 1); | ||
| 4335 | } | ||
| 4336 | |||
| 4337 | /** | ||
| 4338 | * nand_suspend - [MTD Interface] Suspend the NAND flash | 4326 | * nand_suspend - [MTD Interface] Suspend the NAND flash |
| 4339 | * @mtd: MTD device structure | 4327 | * @mtd: MTD device structure |
| 4340 | */ | 4328 | */ |
| @@ -4485,21 +4473,29 @@ static int nand_get_bits_per_cell(u8 cellinfo) | |||
| 4485 | */ | 4473 | */ |
| 4486 | void nand_decode_ext_id(struct nand_chip *chip) | 4474 | void nand_decode_ext_id(struct nand_chip *chip) |
| 4487 | { | 4475 | { |
| 4476 | struct nand_memory_organization *memorg; | ||
| 4488 | struct mtd_info *mtd = nand_to_mtd(chip); | 4477 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 4489 | int extid; | 4478 | int extid; |
| 4490 | u8 *id_data = chip->id.data; | 4479 | u8 *id_data = chip->id.data; |
| 4480 | |||
| 4481 | memorg = nanddev_get_memorg(&chip->base); | ||
| 4482 | |||
| 4491 | /* The 3rd id byte holds MLC / multichip data */ | 4483 | /* The 3rd id byte holds MLC / multichip data */ |
| 4492 | chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); | 4484 | memorg->bits_per_cell = nand_get_bits_per_cell(id_data[2]); |
| 4493 | /* The 4th id byte is the important one */ | 4485 | /* The 4th id byte is the important one */ |
| 4494 | extid = id_data[3]; | 4486 | extid = id_data[3]; |
| 4495 | 4487 | ||
| 4496 | /* Calc pagesize */ | 4488 | /* Calc pagesize */ |
| 4497 | mtd->writesize = 1024 << (extid & 0x03); | 4489 | memorg->pagesize = 1024 << (extid & 0x03); |
| 4490 | mtd->writesize = memorg->pagesize; | ||
| 4498 | extid >>= 2; | 4491 | extid >>= 2; |
| 4499 | /* Calc oobsize */ | 4492 | /* Calc oobsize */ |
| 4500 | mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); | 4493 | memorg->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); |
| 4494 | mtd->oobsize = memorg->oobsize; | ||
| 4501 | extid >>= 2; | 4495 | extid >>= 2; |
| 4502 | /* Calc blocksize. Blocksize is multiples of 64KiB */ | 4496 | /* Calc blocksize. Blocksize is multiples of 64KiB */ |
| 4497 | memorg->pages_per_eraseblock = ((64 * 1024) << (extid & 0x03)) / | ||
| 4498 | memorg->pagesize; | ||
| 4503 | mtd->erasesize = (64 * 1024) << (extid & 0x03); | 4499 | mtd->erasesize = (64 * 1024) << (extid & 0x03); |
| 4504 | extid >>= 2; | 4500 | extid >>= 2; |
| 4505 | /* Get buswidth information */ | 4501 | /* Get buswidth information */ |
| @@ -4516,13 +4512,19 @@ EXPORT_SYMBOL_GPL(nand_decode_ext_id); | |||
| 4516 | static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type) | 4512 | static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type) |
| 4517 | { | 4513 | { |
| 4518 | struct mtd_info *mtd = nand_to_mtd(chip); | 4514 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 4515 | struct nand_memory_organization *memorg; | ||
| 4516 | |||
| 4517 | memorg = nanddev_get_memorg(&chip->base); | ||
| 4519 | 4518 | ||
| 4519 | memorg->pages_per_eraseblock = type->erasesize / type->pagesize; | ||
| 4520 | mtd->erasesize = type->erasesize; | 4520 | mtd->erasesize = type->erasesize; |
| 4521 | mtd->writesize = type->pagesize; | 4521 | memorg->pagesize = type->pagesize; |
| 4522 | mtd->oobsize = mtd->writesize / 32; | 4522 | mtd->writesize = memorg->pagesize; |
| 4523 | memorg->oobsize = memorg->pagesize / 32; | ||
| 4524 | mtd->oobsize = memorg->oobsize; | ||
| 4523 | 4525 | ||
| 4524 | /* All legacy ID NAND are small-page, SLC */ | 4526 | /* All legacy ID NAND are small-page, SLC */ |
| 4525 | chip->bits_per_cell = 1; | 4527 | memorg->bits_per_cell = 1; |
| 4526 | } | 4528 | } |
| 4527 | 4529 | ||
| 4528 | /* | 4530 | /* |
| @@ -4536,9 +4538,9 @@ static void nand_decode_bbm_options(struct nand_chip *chip) | |||
| 4536 | 4538 | ||
| 4537 | /* Set the bad block position */ | 4539 | /* Set the bad block position */ |
| 4538 | if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16)) | 4540 | if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16)) |
| 4539 | chip->badblockpos = NAND_LARGE_BADBLOCK_POS; | 4541 | chip->badblockpos = NAND_BBM_POS_LARGE; |
| 4540 | else | 4542 | else |
| 4541 | chip->badblockpos = NAND_SMALL_BADBLOCK_POS; | 4543 | chip->badblockpos = NAND_BBM_POS_SMALL; |
| 4542 | } | 4544 | } |
| 4543 | 4545 | ||
| 4544 | static inline bool is_full_id_nand(struct nand_flash_dev *type) | 4546 | static inline bool is_full_id_nand(struct nand_flash_dev *type) |
| @@ -4550,18 +4552,28 @@ static bool find_full_id_nand(struct nand_chip *chip, | |||
| 4550 | struct nand_flash_dev *type) | 4552 | struct nand_flash_dev *type) |
| 4551 | { | 4553 | { |
| 4552 | struct mtd_info *mtd = nand_to_mtd(chip); | 4554 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 4555 | struct nand_memory_organization *memorg; | ||
| 4553 | u8 *id_data = chip->id.data; | 4556 | u8 *id_data = chip->id.data; |
| 4554 | 4557 | ||
| 4558 | memorg = nanddev_get_memorg(&chip->base); | ||
| 4559 | |||
| 4555 | if (!strncmp(type->id, id_data, type->id_len)) { | 4560 | if (!strncmp(type->id, id_data, type->id_len)) { |
| 4556 | mtd->writesize = type->pagesize; | 4561 | memorg->pagesize = type->pagesize; |
| 4562 | mtd->writesize = memorg->pagesize; | ||
| 4563 | memorg->pages_per_eraseblock = type->erasesize / | ||
| 4564 | type->pagesize; | ||
| 4557 | mtd->erasesize = type->erasesize; | 4565 | mtd->erasesize = type->erasesize; |
| 4558 | mtd->oobsize = type->oobsize; | 4566 | memorg->oobsize = type->oobsize; |
| 4559 | 4567 | mtd->oobsize = memorg->oobsize; | |
| 4560 | chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); | 4568 | |
| 4561 | chip->chipsize = (uint64_t)type->chipsize << 20; | 4569 | memorg->bits_per_cell = nand_get_bits_per_cell(id_data[2]); |
| 4570 | memorg->eraseblocks_per_lun = | ||
| 4571 | DIV_ROUND_DOWN_ULL((u64)type->chipsize << 20, | ||
| 4572 | memorg->pagesize * | ||
| 4573 | memorg->pages_per_eraseblock); | ||
| 4562 | chip->options |= type->options; | 4574 | chip->options |= type->options; |
| 4563 | chip->ecc_strength_ds = NAND_ECC_STRENGTH(type); | 4575 | chip->base.eccreq.strength = NAND_ECC_STRENGTH(type); |
| 4564 | chip->ecc_step_ds = NAND_ECC_STEP(type); | 4576 | chip->base.eccreq.step_size = NAND_ECC_STEP(type); |
| 4565 | chip->onfi_timing_mode_default = | 4577 | chip->onfi_timing_mode_default = |
| 4566 | type->onfi_timing_mode_default; | 4578 | type->onfi_timing_mode_default; |
| 4567 | 4579 | ||
| @@ -4587,8 +4599,12 @@ static void nand_manufacturer_detect(struct nand_chip *chip) | |||
| 4587 | */ | 4599 | */ |
| 4588 | if (chip->manufacturer.desc && chip->manufacturer.desc->ops && | 4600 | if (chip->manufacturer.desc && chip->manufacturer.desc->ops && |
| 4589 | chip->manufacturer.desc->ops->detect) { | 4601 | chip->manufacturer.desc->ops->detect) { |
| 4602 | struct nand_memory_organization *memorg; | ||
| 4603 | |||
| 4604 | memorg = nanddev_get_memorg(&chip->base); | ||
| 4605 | |||
| 4590 | /* The 3rd id byte holds MLC / multichip data */ | 4606 | /* The 3rd id byte holds MLC / multichip data */ |
| 4591 | chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]); | 4607 | memorg->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]); |
| 4592 | chip->manufacturer.desc->ops->detect(chip); | 4608 | chip->manufacturer.desc->ops->detect(chip); |
| 4593 | } else { | 4609 | } else { |
| 4594 | nand_decode_ext_id(chip); | 4610 | nand_decode_ext_id(chip); |
| @@ -4637,9 +4653,20 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) | |||
| 4637 | { | 4653 | { |
| 4638 | const struct nand_manufacturer *manufacturer; | 4654 | const struct nand_manufacturer *manufacturer; |
| 4639 | struct mtd_info *mtd = nand_to_mtd(chip); | 4655 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 4656 | struct nand_memory_organization *memorg; | ||
| 4640 | int busw, ret; | 4657 | int busw, ret; |
| 4641 | u8 *id_data = chip->id.data; | 4658 | u8 *id_data = chip->id.data; |
| 4642 | u8 maf_id, dev_id; | 4659 | u8 maf_id, dev_id; |
| 4660 | u64 targetsize; | ||
| 4661 | |||
| 4662 | /* | ||
| 4663 | * Let's start by initializing memorg fields that might be left | ||
| 4664 | * unassigned by the ID-based detection logic. | ||
| 4665 | */ | ||
| 4666 | memorg = nanddev_get_memorg(&chip->base); | ||
| 4667 | memorg->planes_per_lun = 1; | ||
| 4668 | memorg->luns_per_target = 1; | ||
| 4669 | memorg->ntargets = 1; | ||
| 4643 | 4670 | ||
| 4644 | /* | 4671 | /* |
| 4645 | * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) | 4672 | * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) |
| @@ -4735,8 +4762,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) | |||
| 4735 | if (!chip->parameters.model) | 4762 | if (!chip->parameters.model) |
| 4736 | return -ENOMEM; | 4763 | return -ENOMEM; |
| 4737 | 4764 | ||
| 4738 | chip->chipsize = (uint64_t)type->chipsize << 20; | ||
| 4739 | |||
| 4740 | if (!type->pagesize) | 4765 | if (!type->pagesize) |
| 4741 | nand_manufacturer_detect(chip); | 4766 | nand_manufacturer_detect(chip); |
| 4742 | else | 4767 | else |
| @@ -4745,6 +4770,11 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) | |||
| 4745 | /* Get chip options */ | 4770 | /* Get chip options */ |
| 4746 | chip->options |= type->options; | 4771 | chip->options |= type->options; |
| 4747 | 4772 | ||
| 4773 | memorg->eraseblocks_per_lun = | ||
| 4774 | DIV_ROUND_DOWN_ULL((u64)type->chipsize << 20, | ||
| 4775 | memorg->pagesize * | ||
| 4776 | memorg->pages_per_eraseblock); | ||
| 4777 | |||
| 4748 | ident_done: | 4778 | ident_done: |
| 4749 | if (!mtd->name) | 4779 | if (!mtd->name) |
| 4750 | mtd->name = chip->parameters.model; | 4780 | mtd->name = chip->parameters.model; |
| @@ -4773,14 +4803,15 @@ ident_done: | |||
| 4773 | /* Calculate the address shift from the page size */ | 4803 | /* Calculate the address shift from the page size */ |
| 4774 | chip->page_shift = ffs(mtd->writesize) - 1; | 4804 | chip->page_shift = ffs(mtd->writesize) - 1; |
| 4775 | /* Convert chipsize to number of pages per chip -1 */ | 4805 | /* Convert chipsize to number of pages per chip -1 */ |
| 4776 | chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; | 4806 | targetsize = nanddev_target_size(&chip->base); |
| 4807 | chip->pagemask = (targetsize >> chip->page_shift) - 1; | ||
| 4777 | 4808 | ||
| 4778 | chip->bbt_erase_shift = chip->phys_erase_shift = | 4809 | chip->bbt_erase_shift = chip->phys_erase_shift = |
| 4779 | ffs(mtd->erasesize) - 1; | 4810 | ffs(mtd->erasesize) - 1; |
| 4780 | if (chip->chipsize & 0xffffffff) | 4811 | if (targetsize & 0xffffffff) |
| 4781 | chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; | 4812 | chip->chip_shift = ffs((unsigned)targetsize) - 1; |
| 4782 | else { | 4813 | else { |
| 4783 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)); | 4814 | chip->chip_shift = ffs((unsigned)(targetsize >> 32)); |
| 4784 | chip->chip_shift += 32 - 1; | 4815 | chip->chip_shift += 32 - 1; |
| 4785 | } | 4816 | } |
| 4786 | 4817 | ||
| @@ -4796,7 +4827,7 @@ ident_done: | |||
| 4796 | pr_info("%s %s\n", nand_manufacturer_name(manufacturer), | 4827 | pr_info("%s %s\n", nand_manufacturer_name(manufacturer), |
| 4797 | chip->parameters.model); | 4828 | chip->parameters.model); |
| 4798 | pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", | 4829 | pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", |
| 4799 | (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", | 4830 | (int)(targetsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", |
| 4800 | mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); | 4831 | mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); |
| 4801 | return 0; | 4832 | return 0; |
| 4802 | 4833 | ||
| @@ -4971,10 +5002,13 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, | |||
| 4971 | struct nand_flash_dev *table) | 5002 | struct nand_flash_dev *table) |
| 4972 | { | 5003 | { |
| 4973 | struct mtd_info *mtd = nand_to_mtd(chip); | 5004 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 5005 | struct nand_memory_organization *memorg; | ||
| 4974 | int nand_maf_id, nand_dev_id; | 5006 | int nand_maf_id, nand_dev_id; |
| 4975 | unsigned int i; | 5007 | unsigned int i; |
| 4976 | int ret; | 5008 | int ret; |
| 4977 | 5009 | ||
| 5010 | memorg = nanddev_get_memorg(&chip->base); | ||
| 5011 | |||
| 4978 | /* Assume all dies are deselected when we enter nand_scan_ident(). */ | 5012 | /* Assume all dies are deselected when we enter nand_scan_ident(). */ |
| 4979 | chip->cur_cs = -1; | 5013 | chip->cur_cs = -1; |
| 4980 | 5014 | ||
| @@ -4990,12 +5024,6 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, | |||
| 4990 | if (!mtd->name && mtd->dev.parent) | 5024 | if (!mtd->name && mtd->dev.parent) |
| 4991 | mtd->name = dev_name(mtd->dev.parent); | 5025 | mtd->name = dev_name(mtd->dev.parent); |
| 4992 | 5026 | ||
| 4993 | /* | ||
| 4994 | * Start with chips->numchips = maxchips to let nand_select_target() do | ||
| 4995 | * its job. chip->numchips will be adjusted after. | ||
| 4996 | */ | ||
| 4997 | chip->numchips = maxchips; | ||
| 4998 | |||
| 4999 | /* Set the default functions */ | 5027 | /* Set the default functions */ |
| 5000 | nand_set_defaults(chip); | 5028 | nand_set_defaults(chip); |
| 5001 | 5029 | ||
| @@ -5042,8 +5070,8 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, | |||
| 5042 | pr_info("%d chips detected\n", i); | 5070 | pr_info("%d chips detected\n", i); |
| 5043 | 5071 | ||
| 5044 | /* Store the number of chips and calc total size for mtd */ | 5072 | /* Store the number of chips and calc total size for mtd */ |
| 5045 | chip->numchips = i; | 5073 | memorg->ntargets = i; |
| 5046 | mtd->size = i * chip->chipsize; | 5074 | mtd->size = i * nanddev_target_size(&chip->base); |
| 5047 | 5075 | ||
| 5048 | return 0; | 5076 | return 0; |
| 5049 | } | 5077 | } |
| @@ -5078,13 +5106,13 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip) | |||
| 5078 | ecc->bytes = 3; | 5106 | ecc->bytes = 3; |
| 5079 | ecc->strength = 1; | 5107 | ecc->strength = 1; |
| 5080 | 5108 | ||
| 5081 | if (IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)) | 5109 | if (IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)) |
| 5082 | ecc->options |= NAND_ECC_SOFT_HAMMING_SM_ORDER; | 5110 | ecc->options |= NAND_ECC_SOFT_HAMMING_SM_ORDER; |
| 5083 | 5111 | ||
| 5084 | return 0; | 5112 | return 0; |
| 5085 | case NAND_ECC_BCH: | 5113 | case NAND_ECC_BCH: |
| 5086 | if (!mtd_nand_has_bch()) { | 5114 | if (!mtd_nand_has_bch()) { |
| 5087 | WARN(1, "CONFIG_MTD_NAND_ECC_BCH not enabled\n"); | 5115 | WARN(1, "CONFIG_MTD_NAND_ECC_SW_BCH not enabled\n"); |
| 5088 | return -EINVAL; | 5116 | return -EINVAL; |
| 5089 | } | 5117 | } |
| 5090 | ecc->calculate = nand_bch_calculate_ecc; | 5118 | ecc->calculate = nand_bch_calculate_ecc; |
| @@ -5224,8 +5252,8 @@ nand_match_ecc_req(struct nand_chip *chip, | |||
| 5224 | { | 5252 | { |
| 5225 | struct mtd_info *mtd = nand_to_mtd(chip); | 5253 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 5226 | const struct nand_ecc_step_info *stepinfo; | 5254 | const struct nand_ecc_step_info *stepinfo; |
| 5227 | int req_step = chip->ecc_step_ds; | 5255 | int req_step = chip->base.eccreq.step_size; |
| 5228 | int req_strength = chip->ecc_strength_ds; | 5256 | int req_strength = chip->base.eccreq.strength; |
| 5229 | int req_corr, step_size, strength, nsteps, ecc_bytes, ecc_bytes_total; | 5257 | int req_corr, step_size, strength, nsteps, ecc_bytes, ecc_bytes_total; |
| 5230 | int best_step, best_strength, best_ecc_bytes; | 5258 | int best_step, best_strength, best_ecc_bytes; |
| 5231 | int best_ecc_bytes_total = INT_MAX; | 5259 | int best_ecc_bytes_total = INT_MAX; |
| @@ -5418,7 +5446,7 @@ static bool nand_ecc_strength_good(struct nand_chip *chip) | |||
| 5418 | struct nand_ecc_ctrl *ecc = &chip->ecc; | 5446 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
| 5419 | int corr, ds_corr; | 5447 | int corr, ds_corr; |
| 5420 | 5448 | ||
| 5421 | if (ecc->size == 0 || chip->ecc_step_ds == 0) | 5449 | if (ecc->size == 0 || chip->base.eccreq.step_size == 0) |
| 5422 | /* Not enough information */ | 5450 | /* Not enough information */ |
| 5423 | return true; | 5451 | return true; |
| 5424 | 5452 | ||
| @@ -5427,11 +5455,56 @@ static bool nand_ecc_strength_good(struct nand_chip *chip) | |||
| 5427 | * the correction density. | 5455 | * the correction density. |
| 5428 | */ | 5456 | */ |
| 5429 | corr = (mtd->writesize * ecc->strength) / ecc->size; | 5457 | corr = (mtd->writesize * ecc->strength) / ecc->size; |
| 5430 | ds_corr = (mtd->writesize * chip->ecc_strength_ds) / chip->ecc_step_ds; | 5458 | ds_corr = (mtd->writesize * chip->base.eccreq.strength) / |
| 5459 | chip->base.eccreq.step_size; | ||
| 5431 | 5460 | ||
| 5432 | return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds; | 5461 | return corr >= ds_corr && ecc->strength >= chip->base.eccreq.strength; |
| 5433 | } | 5462 | } |
| 5434 | 5463 | ||
| 5464 | static int rawnand_erase(struct nand_device *nand, const struct nand_pos *pos) | ||
| 5465 | { | ||
| 5466 | struct nand_chip *chip = container_of(nand, struct nand_chip, | ||
| 5467 | base); | ||
| 5468 | unsigned int eb = nanddev_pos_to_row(nand, pos); | ||
| 5469 | int ret; | ||
| 5470 | |||
| 5471 | eb >>= nand->rowconv.eraseblock_addr_shift; | ||
| 5472 | |||
| 5473 | nand_select_target(chip, pos->target); | ||
| 5474 | ret = nand_erase_op(chip, eb); | ||
| 5475 | nand_deselect_target(chip); | ||
| 5476 | |||
| 5477 | return ret; | ||
| 5478 | } | ||
| 5479 | |||
| 5480 | static int rawnand_markbad(struct nand_device *nand, | ||
| 5481 | const struct nand_pos *pos) | ||
| 5482 | { | ||
| 5483 | struct nand_chip *chip = container_of(nand, struct nand_chip, | ||
| 5484 | base); | ||
| 5485 | |||
| 5486 | return nand_markbad_bbm(chip, nanddev_pos_to_offs(nand, pos)); | ||
| 5487 | } | ||
| 5488 | |||
| 5489 | static bool rawnand_isbad(struct nand_device *nand, const struct nand_pos *pos) | ||
| 5490 | { | ||
| 5491 | struct nand_chip *chip = container_of(nand, struct nand_chip, | ||
| 5492 | base); | ||
| 5493 | int ret; | ||
| 5494 | |||
| 5495 | nand_select_target(chip, pos->target); | ||
| 5496 | ret = nand_isbad_bbm(chip, nanddev_pos_to_offs(nand, pos)); | ||
| 5497 | nand_deselect_target(chip); | ||
| 5498 | |||
| 5499 | return ret; | ||
| 5500 | } | ||
| 5501 | |||
| 5502 | static const struct nand_ops rawnand_ops = { | ||
| 5503 | .erase = rawnand_erase, | ||
| 5504 | .markbad = rawnand_markbad, | ||
| 5505 | .isbad = rawnand_isbad, | ||
| 5506 | }; | ||
| 5507 | |||
| 5435 | /** | 5508 | /** |
| 5436 | * nand_scan_tail - Scan for the NAND device | 5509 | * nand_scan_tail - Scan for the NAND device |
| 5437 | * @chip: NAND chip object | 5510 | * @chip: NAND chip object |
| @@ -5687,7 +5760,7 @@ static int nand_scan_tail(struct nand_chip *chip) | |||
| 5687 | chip->subpagesize = mtd->writesize >> mtd->subpage_sft; | 5760 | chip->subpagesize = mtd->writesize >> mtd->subpage_sft; |
| 5688 | 5761 | ||
| 5689 | /* Invalidate the pagebuffer reference */ | 5762 | /* Invalidate the pagebuffer reference */ |
| 5690 | chip->pagebuf = -1; | 5763 | chip->pagecache.page = -1; |
| 5691 | 5764 | ||
| 5692 | /* Large page NAND with SOFT_ECC should support subpage reads */ | 5765 | /* Large page NAND with SOFT_ECC should support subpage reads */ |
| 5693 | switch (ecc->mode) { | 5766 | switch (ecc->mode) { |
| @@ -5700,10 +5773,15 @@ static int nand_scan_tail(struct nand_chip *chip) | |||
| 5700 | break; | 5773 | break; |
| 5701 | } | 5774 | } |
| 5702 | 5775 | ||
| 5776 | ret = nanddev_init(&chip->base, &rawnand_ops, mtd->owner); | ||
| 5777 | if (ret) | ||
| 5778 | goto err_nand_manuf_cleanup; | ||
| 5779 | |||
| 5780 | /* Adjust the MTD_CAP_ flags when NAND_ROM is set. */ | ||
| 5781 | if (chip->options & NAND_ROM) | ||
| 5782 | mtd->flags = MTD_CAP_ROM; | ||
| 5783 | |||
| 5703 | /* Fill in remaining MTD driver data */ | 5784 | /* Fill in remaining MTD driver data */ |
| 5704 | mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH; | ||
| 5705 | mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM : | ||
| 5706 | MTD_CAP_NANDFLASH; | ||
| 5707 | mtd->_erase = nand_erase; | 5785 | mtd->_erase = nand_erase; |
| 5708 | mtd->_point = NULL; | 5786 | mtd->_point = NULL; |
| 5709 | mtd->_unpoint = NULL; | 5787 | mtd->_unpoint = NULL; |
| @@ -5719,8 +5797,7 @@ static int nand_scan_tail(struct nand_chip *chip) | |||
| 5719 | mtd->_block_isreserved = nand_block_isreserved; | 5797 | mtd->_block_isreserved = nand_block_isreserved; |
| 5720 | mtd->_block_isbad = nand_block_isbad; | 5798 | mtd->_block_isbad = nand_block_isbad; |
| 5721 | mtd->_block_markbad = nand_block_markbad; | 5799 | mtd->_block_markbad = nand_block_markbad; |
| 5722 | mtd->_max_bad_blocks = nand_max_bad_blocks; | 5800 | mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks; |
| 5723 | mtd->writebufsize = mtd->writesize; | ||
| 5724 | 5801 | ||
| 5725 | /* | 5802 | /* |
| 5726 | * Initialize bitflip_threshold to its default prior scan_bbt() call. | 5803 | * Initialize bitflip_threshold to its default prior scan_bbt() call. |
| @@ -5733,13 +5810,13 @@ static int nand_scan_tail(struct nand_chip *chip) | |||
| 5733 | /* Initialize the ->data_interface field. */ | 5810 | /* Initialize the ->data_interface field. */ |
| 5734 | ret = nand_init_data_interface(chip); | 5811 | ret = nand_init_data_interface(chip); |
| 5735 | if (ret) | 5812 | if (ret) |
| 5736 | goto err_nand_manuf_cleanup; | 5813 | goto err_nanddev_cleanup; |
| 5737 | 5814 | ||
| 5738 | /* Enter fastest possible mode on all dies. */ | 5815 | /* Enter fastest possible mode on all dies. */ |
| 5739 | for (i = 0; i < chip->numchips; i++) { | 5816 | for (i = 0; i < nanddev_ntargets(&chip->base); i++) { |
| 5740 | ret = nand_setup_data_interface(chip, i); | 5817 | ret = nand_setup_data_interface(chip, i); |
| 5741 | if (ret) | 5818 | if (ret) |
| 5742 | goto err_nand_manuf_cleanup; | 5819 | goto err_nanddev_cleanup; |
| 5743 | } | 5820 | } |
| 5744 | 5821 | ||
| 5745 | /* Check, if we should skip the bad block table scan */ | 5822 | /* Check, if we should skip the bad block table scan */ |
| @@ -5749,11 +5826,14 @@ static int nand_scan_tail(struct nand_chip *chip) | |||
| 5749 | /* Build bad block table */ | 5826 | /* Build bad block table */ |
| 5750 | ret = nand_create_bbt(chip); | 5827 | ret = nand_create_bbt(chip); |
| 5751 | if (ret) | 5828 | if (ret) |
| 5752 | goto err_nand_manuf_cleanup; | 5829 | goto err_nanddev_cleanup; |
| 5753 | 5830 | ||
| 5754 | return 0; | 5831 | return 0; |
| 5755 | 5832 | ||
| 5756 | 5833 | ||
| 5834 | err_nanddev_cleanup: | ||
| 5835 | nanddev_cleanup(&chip->base); | ||
| 5836 | |||
| 5757 | err_nand_manuf_cleanup: | 5837 | err_nand_manuf_cleanup: |
| 5758 | nand_manufacturer_cleanup(chip); | 5838 | nand_manufacturer_cleanup(chip); |
| 5759 | 5839 | ||
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index 19a2b563acdf..fd3c10216eda 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c | |||
| @@ -264,18 +264,19 @@ static int read_abs_bbt(struct nand_chip *this, uint8_t *buf, | |||
| 264 | struct nand_bbt_descr *td, int chip) | 264 | struct nand_bbt_descr *td, int chip) |
| 265 | { | 265 | { |
| 266 | struct mtd_info *mtd = nand_to_mtd(this); | 266 | struct mtd_info *mtd = nand_to_mtd(this); |
| 267 | u64 targetsize = nanddev_target_size(&this->base); | ||
| 267 | int res = 0, i; | 268 | int res = 0, i; |
| 268 | 269 | ||
| 269 | if (td->options & NAND_BBT_PERCHIP) { | 270 | if (td->options & NAND_BBT_PERCHIP) { |
| 270 | int offs = 0; | 271 | int offs = 0; |
| 271 | for (i = 0; i < this->numchips; i++) { | 272 | for (i = 0; i < nanddev_ntargets(&this->base); i++) { |
| 272 | if (chip == -1 || chip == i) | 273 | if (chip == -1 || chip == i) |
| 273 | res = read_bbt(this, buf, td->pages[i], | 274 | res = read_bbt(this, buf, td->pages[i], |
| 274 | this->chipsize >> this->bbt_erase_shift, | 275 | targetsize >> this->bbt_erase_shift, |
| 275 | td, offs); | 276 | td, offs); |
| 276 | if (res) | 277 | if (res) |
| 277 | return res; | 278 | return res; |
| 278 | offs += this->chipsize >> this->bbt_erase_shift; | 279 | offs += targetsize >> this->bbt_erase_shift; |
| 279 | } | 280 | } |
| 280 | } else { | 281 | } else { |
| 281 | res = read_bbt(this, buf, td->pages[0], | 282 | res = read_bbt(this, buf, td->pages[0], |
| @@ -415,11 +416,12 @@ static void read_abs_bbts(struct nand_chip *this, uint8_t *buf, | |||
| 415 | 416 | ||
| 416 | /* Scan a given block partially */ | 417 | /* Scan a given block partially */ |
| 417 | static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd, | 418 | static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd, |
| 418 | loff_t offs, uint8_t *buf, int numpages) | 419 | loff_t offs, uint8_t *buf) |
| 419 | { | 420 | { |
| 420 | struct mtd_info *mtd = nand_to_mtd(this); | 421 | struct mtd_info *mtd = nand_to_mtd(this); |
| 422 | |||
| 421 | struct mtd_oob_ops ops; | 423 | struct mtd_oob_ops ops; |
| 422 | int j, ret; | 424 | int ret, page_offset; |
| 423 | 425 | ||
| 424 | ops.ooblen = mtd->oobsize; | 426 | ops.ooblen = mtd->oobsize; |
| 425 | ops.oobbuf = buf; | 427 | ops.oobbuf = buf; |
| @@ -427,12 +429,15 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd, | |||
| 427 | ops.datbuf = NULL; | 429 | ops.datbuf = NULL; |
| 428 | ops.mode = MTD_OPS_PLACE_OOB; | 430 | ops.mode = MTD_OPS_PLACE_OOB; |
| 429 | 431 | ||
| 430 | for (j = 0; j < numpages; j++) { | 432 | page_offset = nand_bbm_get_next_page(this, 0); |
| 433 | |||
| 434 | while (page_offset >= 0) { | ||
| 431 | /* | 435 | /* |
| 432 | * Read the full oob until read_oob is fixed to handle single | 436 | * Read the full oob until read_oob is fixed to handle single |
| 433 | * byte reads for 16 bit buswidth. | 437 | * byte reads for 16 bit buswidth. |
| 434 | */ | 438 | */ |
| 435 | ret = mtd_read_oob(mtd, offs, &ops); | 439 | ret = mtd_read_oob(mtd, offs + (page_offset * mtd->writesize), |
| 440 | &ops); | ||
| 436 | /* Ignore ECC errors when checking for BBM */ | 441 | /* Ignore ECC errors when checking for BBM */ |
| 437 | if (ret && !mtd_is_bitflip_or_eccerr(ret)) | 442 | if (ret && !mtd_is_bitflip_or_eccerr(ret)) |
| 438 | return ret; | 443 | return ret; |
| @@ -440,8 +445,9 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd, | |||
| 440 | if (check_short_pattern(buf, bd)) | 445 | if (check_short_pattern(buf, bd)) |
| 441 | return 1; | 446 | return 1; |
| 442 | 447 | ||
| 443 | offs += mtd->writesize; | 448 | page_offset = nand_bbm_get_next_page(this, page_offset + 1); |
| 444 | } | 449 | } |
| 450 | |||
| 445 | return 0; | 451 | return 0; |
| 446 | } | 452 | } |
| 447 | 453 | ||
| @@ -459,43 +465,35 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd, | |||
| 459 | static int create_bbt(struct nand_chip *this, uint8_t *buf, | 465 | static int create_bbt(struct nand_chip *this, uint8_t *buf, |
| 460 | struct nand_bbt_descr *bd, int chip) | 466 | struct nand_bbt_descr *bd, int chip) |
| 461 | { | 467 | { |
| 468 | u64 targetsize = nanddev_target_size(&this->base); | ||
| 462 | struct mtd_info *mtd = nand_to_mtd(this); | 469 | struct mtd_info *mtd = nand_to_mtd(this); |
| 463 | int i, numblocks, numpages; | 470 | int i, numblocks, startblock; |
| 464 | int startblock; | ||
| 465 | loff_t from; | 471 | loff_t from; |
| 466 | 472 | ||
| 467 | pr_info("Scanning device for bad blocks\n"); | 473 | pr_info("Scanning device for bad blocks\n"); |
| 468 | 474 | ||
| 469 | if (bd->options & NAND_BBT_SCAN2NDPAGE) | ||
| 470 | numpages = 2; | ||
| 471 | else | ||
| 472 | numpages = 1; | ||
| 473 | |||
| 474 | if (chip == -1) { | 475 | if (chip == -1) { |
| 475 | numblocks = mtd->size >> this->bbt_erase_shift; | 476 | numblocks = mtd->size >> this->bbt_erase_shift; |
| 476 | startblock = 0; | 477 | startblock = 0; |
| 477 | from = 0; | 478 | from = 0; |
| 478 | } else { | 479 | } else { |
| 479 | if (chip >= this->numchips) { | 480 | if (chip >= nanddev_ntargets(&this->base)) { |
| 480 | pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n", | 481 | pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n", |
| 481 | chip + 1, this->numchips); | 482 | chip + 1, nanddev_ntargets(&this->base)); |
| 482 | return -EINVAL; | 483 | return -EINVAL; |
| 483 | } | 484 | } |
| 484 | numblocks = this->chipsize >> this->bbt_erase_shift; | 485 | numblocks = targetsize >> this->bbt_erase_shift; |
| 485 | startblock = chip * numblocks; | 486 | startblock = chip * numblocks; |
| 486 | numblocks += startblock; | 487 | numblocks += startblock; |
| 487 | from = (loff_t)startblock << this->bbt_erase_shift; | 488 | from = (loff_t)startblock << this->bbt_erase_shift; |
| 488 | } | 489 | } |
| 489 | 490 | ||
| 490 | if (this->bbt_options & NAND_BBT_SCANLASTPAGE) | ||
| 491 | from += mtd->erasesize - (mtd->writesize * numpages); | ||
| 492 | |||
| 493 | for (i = startblock; i < numblocks; i++) { | 491 | for (i = startblock; i < numblocks; i++) { |
| 494 | int ret; | 492 | int ret; |
| 495 | 493 | ||
| 496 | BUG_ON(bd->options & NAND_BBT_NO_OOB); | 494 | BUG_ON(bd->options & NAND_BBT_NO_OOB); |
| 497 | 495 | ||
| 498 | ret = scan_block_fast(this, bd, from, buf, numpages); | 496 | ret = scan_block_fast(this, bd, from, buf); |
| 499 | if (ret < 0) | 497 | if (ret < 0) |
| 500 | return ret; | 498 | return ret; |
| 501 | 499 | ||
| @@ -529,6 +527,7 @@ static int create_bbt(struct nand_chip *this, uint8_t *buf, | |||
| 529 | static int search_bbt(struct nand_chip *this, uint8_t *buf, | 527 | static int search_bbt(struct nand_chip *this, uint8_t *buf, |
| 530 | struct nand_bbt_descr *td) | 528 | struct nand_bbt_descr *td) |
| 531 | { | 529 | { |
| 530 | u64 targetsize = nanddev_target_size(&this->base); | ||
| 532 | struct mtd_info *mtd = nand_to_mtd(this); | 531 | struct mtd_info *mtd = nand_to_mtd(this); |
| 533 | int i, chips; | 532 | int i, chips; |
| 534 | int startblock, block, dir; | 533 | int startblock, block, dir; |
| @@ -547,8 +546,8 @@ static int search_bbt(struct nand_chip *this, uint8_t *buf, | |||
| 547 | 546 | ||
| 548 | /* Do we have a bbt per chip? */ | 547 | /* Do we have a bbt per chip? */ |
| 549 | if (td->options & NAND_BBT_PERCHIP) { | 548 | if (td->options & NAND_BBT_PERCHIP) { |
| 550 | chips = this->numchips; | 549 | chips = nanddev_ntargets(&this->base); |
| 551 | bbtblocks = this->chipsize >> this->bbt_erase_shift; | 550 | bbtblocks = targetsize >> this->bbt_erase_shift; |
| 552 | startblock &= bbtblocks - 1; | 551 | startblock &= bbtblocks - 1; |
| 553 | } else { | 552 | } else { |
| 554 | chips = 1; | 553 | chips = 1; |
| @@ -576,7 +575,7 @@ static int search_bbt(struct nand_chip *this, uint8_t *buf, | |||
| 576 | break; | 575 | break; |
| 577 | } | 576 | } |
| 578 | } | 577 | } |
| 579 | startblock += this->chipsize >> this->bbt_erase_shift; | 578 | startblock += targetsize >> this->bbt_erase_shift; |
| 580 | } | 579 | } |
| 581 | /* Check, if we found a bbt for each requested chip */ | 580 | /* Check, if we found a bbt for each requested chip */ |
| 582 | for (i = 0; i < chips; i++) { | 581 | for (i = 0; i < chips; i++) { |
| @@ -626,6 +625,7 @@ static void search_read_bbts(struct nand_chip *this, uint8_t *buf, | |||
| 626 | static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td, | 625 | static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td, |
| 627 | struct nand_bbt_descr *md, int chip) | 626 | struct nand_bbt_descr *md, int chip) |
| 628 | { | 627 | { |
| 628 | u64 targetsize = nanddev_target_size(&this->base); | ||
| 629 | int startblock, dir, page, numblocks, i; | 629 | int startblock, dir, page, numblocks, i; |
| 630 | 630 | ||
| 631 | /* | 631 | /* |
| @@ -637,9 +637,9 @@ static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td, | |||
| 637 | return td->pages[chip] >> | 637 | return td->pages[chip] >> |
| 638 | (this->bbt_erase_shift - this->page_shift); | 638 | (this->bbt_erase_shift - this->page_shift); |
| 639 | 639 | ||
| 640 | numblocks = (int)(this->chipsize >> this->bbt_erase_shift); | 640 | numblocks = (int)(targetsize >> this->bbt_erase_shift); |
| 641 | if (!(td->options & NAND_BBT_PERCHIP)) | 641 | if (!(td->options & NAND_BBT_PERCHIP)) |
| 642 | numblocks *= this->numchips; | 642 | numblocks *= nanddev_ntargets(&this->base); |
| 643 | 643 | ||
| 644 | /* | 644 | /* |
| 645 | * Automatic placement of the bad block table. Search direction | 645 | * Automatic placement of the bad block table. Search direction |
| @@ -717,6 +717,7 @@ static int write_bbt(struct nand_chip *this, uint8_t *buf, | |||
| 717 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, | 717 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, |
| 718 | int chipsel) | 718 | int chipsel) |
| 719 | { | 719 | { |
| 720 | u64 targetsize = nanddev_target_size(&this->base); | ||
| 720 | struct mtd_info *mtd = nand_to_mtd(this); | 721 | struct mtd_info *mtd = nand_to_mtd(this); |
| 721 | struct erase_info einfo; | 722 | struct erase_info einfo; |
| 722 | int i, res, chip = 0; | 723 | int i, res, chip = 0; |
| @@ -737,10 +738,10 @@ static int write_bbt(struct nand_chip *this, uint8_t *buf, | |||
| 737 | rcode = 0xff; | 738 | rcode = 0xff; |
| 738 | /* Write bad block table per chip rather than per device? */ | 739 | /* Write bad block table per chip rather than per device? */ |
| 739 | if (td->options & NAND_BBT_PERCHIP) { | 740 | if (td->options & NAND_BBT_PERCHIP) { |
| 740 | numblocks = (int)(this->chipsize >> this->bbt_erase_shift); | 741 | numblocks = (int)(targetsize >> this->bbt_erase_shift); |
| 741 | /* Full device write or specific chip? */ | 742 | /* Full device write or specific chip? */ |
| 742 | if (chipsel == -1) { | 743 | if (chipsel == -1) { |
| 743 | nrchips = this->numchips; | 744 | nrchips = nanddev_ntargets(&this->base); |
| 744 | } else { | 745 | } else { |
| 745 | nrchips = chipsel + 1; | 746 | nrchips = chipsel + 1; |
| 746 | chip = chipsel; | 747 | chip = chipsel; |
| @@ -901,7 +902,9 @@ static int write_bbt(struct nand_chip *this, uint8_t *buf, | |||
| 901 | static inline int nand_memory_bbt(struct nand_chip *this, | 902 | static inline int nand_memory_bbt(struct nand_chip *this, |
| 902 | struct nand_bbt_descr *bd) | 903 | struct nand_bbt_descr *bd) |
| 903 | { | 904 | { |
| 904 | return create_bbt(this, this->data_buf, bd, -1); | 905 | u8 *pagebuf = nand_get_data_buf(this); |
| 906 | |||
| 907 | return create_bbt(this, pagebuf, bd, -1); | ||
| 905 | } | 908 | } |
| 906 | 909 | ||
| 907 | /** | 910 | /** |
| @@ -925,7 +928,7 @@ static int check_create(struct nand_chip *this, uint8_t *buf, | |||
| 925 | 928 | ||
| 926 | /* Do we have a bbt per chip? */ | 929 | /* Do we have a bbt per chip? */ |
| 927 | if (td->options & NAND_BBT_PERCHIP) | 930 | if (td->options & NAND_BBT_PERCHIP) |
| 928 | chips = this->numchips; | 931 | chips = nanddev_ntargets(&this->base); |
| 929 | else | 932 | else |
| 930 | chips = 1; | 933 | chips = 1; |
| 931 | 934 | ||
| @@ -1097,14 +1100,15 @@ static int nand_update_bbt(struct nand_chip *this, loff_t offs) | |||
| 1097 | */ | 1100 | */ |
| 1098 | static void mark_bbt_region(struct nand_chip *this, struct nand_bbt_descr *td) | 1101 | static void mark_bbt_region(struct nand_chip *this, struct nand_bbt_descr *td) |
| 1099 | { | 1102 | { |
| 1103 | u64 targetsize = nanddev_target_size(&this->base); | ||
| 1100 | struct mtd_info *mtd = nand_to_mtd(this); | 1104 | struct mtd_info *mtd = nand_to_mtd(this); |
| 1101 | int i, j, chips, block, nrblocks, update; | 1105 | int i, j, chips, block, nrblocks, update; |
| 1102 | uint8_t oldval; | 1106 | uint8_t oldval; |
| 1103 | 1107 | ||
| 1104 | /* Do we have a bbt per chip? */ | 1108 | /* Do we have a bbt per chip? */ |
| 1105 | if (td->options & NAND_BBT_PERCHIP) { | 1109 | if (td->options & NAND_BBT_PERCHIP) { |
| 1106 | chips = this->numchips; | 1110 | chips = nanddev_ntargets(&this->base); |
| 1107 | nrblocks = (int)(this->chipsize >> this->bbt_erase_shift); | 1111 | nrblocks = (int)(targetsize >> this->bbt_erase_shift); |
| 1108 | } else { | 1112 | } else { |
| 1109 | chips = 1; | 1113 | chips = 1; |
| 1110 | nrblocks = (int)(mtd->size >> this->bbt_erase_shift); | 1114 | nrblocks = (int)(mtd->size >> this->bbt_erase_shift); |
| @@ -1157,6 +1161,7 @@ static void mark_bbt_region(struct nand_chip *this, struct nand_bbt_descr *td) | |||
| 1157 | */ | 1161 | */ |
| 1158 | static void verify_bbt_descr(struct nand_chip *this, struct nand_bbt_descr *bd) | 1162 | static void verify_bbt_descr(struct nand_chip *this, struct nand_bbt_descr *bd) |
| 1159 | { | 1163 | { |
| 1164 | u64 targetsize = nanddev_target_size(&this->base); | ||
| 1160 | struct mtd_info *mtd = nand_to_mtd(this); | 1165 | struct mtd_info *mtd = nand_to_mtd(this); |
| 1161 | u32 pattern_len; | 1166 | u32 pattern_len; |
| 1162 | u32 bits; | 1167 | u32 bits; |
| @@ -1185,7 +1190,7 @@ static void verify_bbt_descr(struct nand_chip *this, struct nand_bbt_descr *bd) | |||
| 1185 | } | 1190 | } |
| 1186 | 1191 | ||
| 1187 | if (bd->options & NAND_BBT_PERCHIP) | 1192 | if (bd->options & NAND_BBT_PERCHIP) |
| 1188 | table_size = this->chipsize >> this->bbt_erase_shift; | 1193 | table_size = targetsize >> this->bbt_erase_shift; |
| 1189 | else | 1194 | else |
| 1190 | table_size = mtd->size >> this->bbt_erase_shift; | 1195 | table_size = mtd->size >> this->bbt_erase_shift; |
| 1191 | table_size >>= 3; | 1196 | table_size >>= 3; |
diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c index 96f039a83bc8..3338c68aaaf1 100644 --- a/drivers/mtd/nand/raw/nand_esmt.c +++ b/drivers/mtd/nand/raw/nand_esmt.c | |||
| @@ -14,20 +14,20 @@ static void esmt_nand_decode_id(struct nand_chip *chip) | |||
| 14 | 14 | ||
| 15 | /* Extract ECC requirements from 5th id byte. */ | 15 | /* Extract ECC requirements from 5th id byte. */ |
| 16 | if (chip->id.len >= 5 && nand_is_slc(chip)) { | 16 | if (chip->id.len >= 5 && nand_is_slc(chip)) { |
| 17 | chip->ecc_step_ds = 512; | 17 | chip->base.eccreq.step_size = 512; |
| 18 | switch (chip->id.data[4] & 0x3) { | 18 | switch (chip->id.data[4] & 0x3) { |
| 19 | case 0x0: | 19 | case 0x0: |
| 20 | chip->ecc_strength_ds = 4; | 20 | chip->base.eccreq.strength = 4; |
| 21 | break; | 21 | break; |
| 22 | case 0x1: | 22 | case 0x1: |
| 23 | chip->ecc_strength_ds = 2; | 23 | chip->base.eccreq.strength = 2; |
| 24 | break; | 24 | break; |
| 25 | case 0x2: | 25 | case 0x2: |
| 26 | chip->ecc_strength_ds = 1; | 26 | chip->base.eccreq.strength = 1; |
| 27 | break; | 27 | break; |
| 28 | default: | 28 | default: |
| 29 | WARN(1, "Could not get ECC info"); | 29 | WARN(1, "Could not get ECC info"); |
| 30 | chip->ecc_step_ds = 0; | 30 | chip->base.eccreq.step_size = 0; |
| 31 | break; | 31 | break; |
| 32 | } | 32 | } |
| 33 | } | 33 | } |
| @@ -36,7 +36,14 @@ static void esmt_nand_decode_id(struct nand_chip *chip) | |||
| 36 | static int esmt_nand_init(struct nand_chip *chip) | 36 | static int esmt_nand_init(struct nand_chip *chip) |
| 37 | { | 37 | { |
| 38 | if (nand_is_slc(chip)) | 38 | if (nand_is_slc(chip)) |
| 39 | chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; | 39 | /* |
| 40 | * It is known that some ESMT SLC NANDs have been shipped | ||
| 41 | * with the factory bad block markers in the first or last page | ||
| 42 | * of the block, instead of the first or second page. To be on | ||
| 43 | * the safe side, let's check all three locations. | ||
| 44 | */ | ||
| 45 | chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE | | ||
| 46 | NAND_BBM_LASTPAGE; | ||
| 40 | 47 | ||
| 41 | return 0; | 48 | return 0; |
| 42 | } | 49 | } |
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 343f477362d1..7c600c4d5ec8 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c | |||
| @@ -418,24 +418,27 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip, | |||
| 418 | bool valid_jedecid) | 418 | bool valid_jedecid) |
| 419 | { | 419 | { |
| 420 | struct mtd_info *mtd = nand_to_mtd(chip); | 420 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 421 | struct nand_memory_organization *memorg; | ||
| 421 | u8 oobsize; | 422 | u8 oobsize; |
| 422 | 423 | ||
| 424 | memorg = nanddev_get_memorg(&chip->base); | ||
| 425 | |||
| 423 | oobsize = ((chip->id.data[3] >> 2) & 0x3) | | 426 | oobsize = ((chip->id.data[3] >> 2) & 0x3) | |
| 424 | ((chip->id.data[3] >> 4) & 0x4); | 427 | ((chip->id.data[3] >> 4) & 0x4); |
| 425 | 428 | ||
| 426 | if (valid_jedecid) { | 429 | if (valid_jedecid) { |
| 427 | switch (oobsize) { | 430 | switch (oobsize) { |
| 428 | case 0: | 431 | case 0: |
| 429 | mtd->oobsize = 2048; | 432 | memorg->oobsize = 2048; |
| 430 | break; | 433 | break; |
| 431 | case 1: | 434 | case 1: |
| 432 | mtd->oobsize = 1664; | 435 | memorg->oobsize = 1664; |
| 433 | break; | 436 | break; |
| 434 | case 2: | 437 | case 2: |
| 435 | mtd->oobsize = 1024; | 438 | memorg->oobsize = 1024; |
| 436 | break; | 439 | break; |
| 437 | case 3: | 440 | case 3: |
| 438 | mtd->oobsize = 640; | 441 | memorg->oobsize = 640; |
| 439 | break; | 442 | break; |
| 440 | default: | 443 | default: |
| 441 | /* | 444 | /* |
| @@ -450,25 +453,25 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip, | |||
| 450 | } else { | 453 | } else { |
| 451 | switch (oobsize) { | 454 | switch (oobsize) { |
| 452 | case 0: | 455 | case 0: |
| 453 | mtd->oobsize = 128; | 456 | memorg->oobsize = 128; |
| 454 | break; | 457 | break; |
| 455 | case 1: | 458 | case 1: |
| 456 | mtd->oobsize = 224; | 459 | memorg->oobsize = 224; |
| 457 | break; | 460 | break; |
| 458 | case 2: | 461 | case 2: |
| 459 | mtd->oobsize = 448; | 462 | memorg->oobsize = 448; |
| 460 | break; | 463 | break; |
| 461 | case 3: | 464 | case 3: |
| 462 | mtd->oobsize = 64; | 465 | memorg->oobsize = 64; |
| 463 | break; | 466 | break; |
| 464 | case 4: | 467 | case 4: |
| 465 | mtd->oobsize = 32; | 468 | memorg->oobsize = 32; |
| 466 | break; | 469 | break; |
| 467 | case 5: | 470 | case 5: |
| 468 | mtd->oobsize = 16; | 471 | memorg->oobsize = 16; |
| 469 | break; | 472 | break; |
| 470 | case 6: | 473 | case 6: |
| 471 | mtd->oobsize = 640; | 474 | memorg->oobsize = 640; |
| 472 | break; | 475 | break; |
| 473 | default: | 476 | default: |
| 474 | /* | 477 | /* |
| @@ -492,8 +495,10 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip, | |||
| 492 | * the actual OOB size for this chip is: 640 * 16k / 8k). | 495 | * the actual OOB size for this chip is: 640 * 16k / 8k). |
| 493 | */ | 496 | */ |
| 494 | if (chip->id.data[1] == 0xde) | 497 | if (chip->id.data[1] == 0xde) |
| 495 | mtd->oobsize *= mtd->writesize / SZ_8K; | 498 | memorg->oobsize *= memorg->pagesize / SZ_8K; |
| 496 | } | 499 | } |
| 500 | |||
| 501 | mtd->oobsize = memorg->oobsize; | ||
| 497 | } | 502 | } |
| 498 | 503 | ||
| 499 | static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, | 504 | static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, |
| @@ -503,30 +508,30 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, | |||
| 503 | 508 | ||
| 504 | if (valid_jedecid) { | 509 | if (valid_jedecid) { |
| 505 | /* Reference: H27UCG8T2E datasheet */ | 510 | /* Reference: H27UCG8T2E datasheet */ |
| 506 | chip->ecc_step_ds = 1024; | 511 | chip->base.eccreq.step_size = 1024; |
| 507 | 512 | ||
| 508 | switch (ecc_level) { | 513 | switch (ecc_level) { |
| 509 | case 0: | 514 | case 0: |
| 510 | chip->ecc_step_ds = 0; | 515 | chip->base.eccreq.step_size = 0; |
| 511 | chip->ecc_strength_ds = 0; | 516 | chip->base.eccreq.strength = 0; |
| 512 | break; | 517 | break; |
| 513 | case 1: | 518 | case 1: |
| 514 | chip->ecc_strength_ds = 4; | 519 | chip->base.eccreq.strength = 4; |
| 515 | break; | 520 | break; |
| 516 | case 2: | 521 | case 2: |
| 517 | chip->ecc_strength_ds = 24; | 522 | chip->base.eccreq.strength = 24; |
| 518 | break; | 523 | break; |
| 519 | case 3: | 524 | case 3: |
| 520 | chip->ecc_strength_ds = 32; | 525 | chip->base.eccreq.strength = 32; |
| 521 | break; | 526 | break; |
| 522 | case 4: | 527 | case 4: |
| 523 | chip->ecc_strength_ds = 40; | 528 | chip->base.eccreq.strength = 40; |
| 524 | break; | 529 | break; |
| 525 | case 5: | 530 | case 5: |
| 526 | chip->ecc_strength_ds = 50; | 531 | chip->base.eccreq.strength = 50; |
| 527 | break; | 532 | break; |
| 528 | case 6: | 533 | case 6: |
| 529 | chip->ecc_strength_ds = 60; | 534 | chip->base.eccreq.strength = 60; |
| 530 | break; | 535 | break; |
| 531 | default: | 536 | default: |
| 532 | /* | 537 | /* |
| @@ -547,14 +552,14 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, | |||
| 547 | if (nand_tech < 3) { | 552 | if (nand_tech < 3) { |
| 548 | /* > 26nm, reference: H27UBG8T2A datasheet */ | 553 | /* > 26nm, reference: H27UBG8T2A datasheet */ |
| 549 | if (ecc_level < 5) { | 554 | if (ecc_level < 5) { |
| 550 | chip->ecc_step_ds = 512; | 555 | chip->base.eccreq.step_size = 512; |
| 551 | chip->ecc_strength_ds = 1 << ecc_level; | 556 | chip->base.eccreq.strength = 1 << ecc_level; |
| 552 | } else if (ecc_level < 7) { | 557 | } else if (ecc_level < 7) { |
| 553 | if (ecc_level == 5) | 558 | if (ecc_level == 5) |
| 554 | chip->ecc_step_ds = 2048; | 559 | chip->base.eccreq.step_size = 2048; |
| 555 | else | 560 | else |
| 556 | chip->ecc_step_ds = 1024; | 561 | chip->base.eccreq.step_size = 1024; |
| 557 | chip->ecc_strength_ds = 24; | 562 | chip->base.eccreq.strength = 24; |
| 558 | } else { | 563 | } else { |
| 559 | /* | 564 | /* |
| 560 | * We should never reach this case, but if that | 565 | * We should never reach this case, but if that |
| @@ -567,14 +572,14 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, | |||
| 567 | } else { | 572 | } else { |
| 568 | /* <= 26nm, reference: H27UBG8T2B datasheet */ | 573 | /* <= 26nm, reference: H27UBG8T2B datasheet */ |
| 569 | if (!ecc_level) { | 574 | if (!ecc_level) { |
| 570 | chip->ecc_step_ds = 0; | 575 | chip->base.eccreq.step_size = 0; |
| 571 | chip->ecc_strength_ds = 0; | 576 | chip->base.eccreq.strength = 0; |
| 572 | } else if (ecc_level < 5) { | 577 | } else if (ecc_level < 5) { |
| 573 | chip->ecc_step_ds = 512; | 578 | chip->base.eccreq.step_size = 512; |
| 574 | chip->ecc_strength_ds = 1 << (ecc_level - 1); | 579 | chip->base.eccreq.strength = 1 << (ecc_level - 1); |
| 575 | } else { | 580 | } else { |
| 576 | chip->ecc_step_ds = 1024; | 581 | chip->base.eccreq.step_size = 1024; |
| 577 | chip->ecc_strength_ds = 24 + | 582 | chip->base.eccreq.strength = 24 + |
| 578 | (8 * (ecc_level - 5)); | 583 | (8 * (ecc_level - 5)); |
| 579 | } | 584 | } |
| 580 | } | 585 | } |
| @@ -587,7 +592,7 @@ static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip, | |||
| 587 | u8 nand_tech; | 592 | u8 nand_tech; |
| 588 | 593 | ||
| 589 | /* We need scrambling on all TLC NANDs*/ | 594 | /* We need scrambling on all TLC NANDs*/ |
| 590 | if (chip->bits_per_cell > 2) | 595 | if (nanddev_bits_per_cell(&chip->base) > 2) |
| 591 | chip->options |= NAND_NEED_SCRAMBLING; | 596 | chip->options |= NAND_NEED_SCRAMBLING; |
| 592 | 597 | ||
| 593 | /* And on MLC NANDs with sub-3xnm process */ | 598 | /* And on MLC NANDs with sub-3xnm process */ |
| @@ -609,9 +614,12 @@ static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip, | |||
| 609 | static void hynix_nand_decode_id(struct nand_chip *chip) | 614 | static void hynix_nand_decode_id(struct nand_chip *chip) |
| 610 | { | 615 | { |
| 611 | struct mtd_info *mtd = nand_to_mtd(chip); | 616 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 617 | struct nand_memory_organization *memorg; | ||
| 612 | bool valid_jedecid; | 618 | bool valid_jedecid; |
| 613 | u8 tmp; | 619 | u8 tmp; |
| 614 | 620 | ||
| 621 | memorg = nanddev_get_memorg(&chip->base); | ||
| 622 | |||
| 615 | /* | 623 | /* |
| 616 | * Exclude all SLC NANDs from this advanced detection scheme. | 624 | * Exclude all SLC NANDs from this advanced detection scheme. |
| 617 | * According to the ranges defined in several datasheets, it might | 625 | * According to the ranges defined in several datasheets, it might |
| @@ -625,7 +633,8 @@ static void hynix_nand_decode_id(struct nand_chip *chip) | |||
| 625 | } | 633 | } |
| 626 | 634 | ||
| 627 | /* Extract pagesize */ | 635 | /* Extract pagesize */ |
| 628 | mtd->writesize = 2048 << (chip->id.data[3] & 0x03); | 636 | memorg->pagesize = 2048 << (chip->id.data[3] & 0x03); |
| 637 | mtd->writesize = memorg->pagesize; | ||
| 629 | 638 | ||
| 630 | tmp = (chip->id.data[3] >> 4) & 0x3; | 639 | tmp = (chip->id.data[3] >> 4) & 0x3; |
| 631 | /* | 640 | /* |
| @@ -635,12 +644,19 @@ static void hynix_nand_decode_id(struct nand_chip *chip) | |||
| 635 | * The only exception is when ID[3][4:5] == 3 and ID[3][7] == 0, in | 644 | * The only exception is when ID[3][4:5] == 3 and ID[3][7] == 0, in |
| 636 | * this case the erasesize is set to 768KiB. | 645 | * this case the erasesize is set to 768KiB. |
| 637 | */ | 646 | */ |
| 638 | if (chip->id.data[3] & 0x80) | 647 | if (chip->id.data[3] & 0x80) { |
| 648 | memorg->pages_per_eraseblock = (SZ_1M << tmp) / | ||
| 649 | memorg->pagesize; | ||
| 639 | mtd->erasesize = SZ_1M << tmp; | 650 | mtd->erasesize = SZ_1M << tmp; |
| 640 | else if (tmp == 3) | 651 | } else if (tmp == 3) { |
| 652 | memorg->pages_per_eraseblock = (SZ_512K + SZ_256K) / | ||
| 653 | memorg->pagesize; | ||
| 641 | mtd->erasesize = SZ_512K + SZ_256K; | 654 | mtd->erasesize = SZ_512K + SZ_256K; |
| 642 | else | 655 | } else { |
| 656 | memorg->pages_per_eraseblock = (SZ_128K << tmp) / | ||
| 657 | memorg->pagesize; | ||
| 643 | mtd->erasesize = SZ_128K << tmp; | 658 | mtd->erasesize = SZ_128K << tmp; |
| 659 | } | ||
| 644 | 660 | ||
| 645 | /* | 661 | /* |
| 646 | * Modern Toggle DDR NANDs have a valid JEDECID even though they are | 662 | * Modern Toggle DDR NANDs have a valid JEDECID even though they are |
| @@ -672,9 +688,9 @@ static int hynix_nand_init(struct nand_chip *chip) | |||
| 672 | int ret; | 688 | int ret; |
| 673 | 689 | ||
| 674 | if (!nand_is_slc(chip)) | 690 | if (!nand_is_slc(chip)) |
| 675 | chip->bbt_options |= NAND_BBT_SCANLASTPAGE; | 691 | chip->options |= NAND_BBM_LASTPAGE; |
| 676 | else | 692 | else |
| 677 | chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; | 693 | chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; |
| 678 | 694 | ||
| 679 | hynix = kzalloc(sizeof(*hynix), GFP_KERNEL); | 695 | hynix = kzalloc(sizeof(*hynix), GFP_KERNEL); |
| 680 | if (!hynix) | 696 | if (!hynix) |
diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c index 38b5dc22cb30..9b540e76f84f 100644 --- a/drivers/mtd/nand/raw/nand_jedec.c +++ b/drivers/mtd/nand/raw/nand_jedec.c | |||
| @@ -22,12 +22,15 @@ | |||
| 22 | int nand_jedec_detect(struct nand_chip *chip) | 22 | int nand_jedec_detect(struct nand_chip *chip) |
| 23 | { | 23 | { |
| 24 | struct mtd_info *mtd = nand_to_mtd(chip); | 24 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 25 | struct nand_memory_organization *memorg; | ||
| 25 | struct nand_jedec_params *p; | 26 | struct nand_jedec_params *p; |
| 26 | struct jedec_ecc_info *ecc; | 27 | struct jedec_ecc_info *ecc; |
| 27 | int jedec_version = 0; | 28 | int jedec_version = 0; |
| 28 | char id[5]; | 29 | char id[5]; |
| 29 | int i, val, ret; | 30 | int i, val, ret; |
| 30 | 31 | ||
| 32 | memorg = nanddev_get_memorg(&chip->base); | ||
| 33 | |||
| 31 | /* Try JEDEC for unknown chip or LP */ | 34 | /* Try JEDEC for unknown chip or LP */ |
| 32 | ret = nand_readid_op(chip, 0x40, id, sizeof(id)); | 35 | ret = nand_readid_op(chip, 0x40, id, sizeof(id)); |
| 33 | if (ret || strncmp(id, "JEDEC", sizeof(id))) | 36 | if (ret || strncmp(id, "JEDEC", sizeof(id))) |
| @@ -81,18 +84,24 @@ int nand_jedec_detect(struct nand_chip *chip) | |||
| 81 | goto free_jedec_param_page; | 84 | goto free_jedec_param_page; |
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | mtd->writesize = le32_to_cpu(p->byte_per_page); | 87 | memorg->pagesize = le32_to_cpu(p->byte_per_page); |
| 88 | mtd->writesize = memorg->pagesize; | ||
| 85 | 89 | ||
| 86 | /* Please reference to the comment for nand_flash_detect_onfi. */ | 90 | /* Please reference to the comment for nand_flash_detect_onfi. */ |
| 87 | mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); | 91 | memorg->pages_per_eraseblock = |
| 88 | mtd->erasesize *= mtd->writesize; | 92 | 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); |
| 93 | mtd->erasesize = memorg->pages_per_eraseblock * memorg->pagesize; | ||
| 94 | |||
| 95 | memorg->oobsize = le16_to_cpu(p->spare_bytes_per_page); | ||
| 96 | mtd->oobsize = memorg->oobsize; | ||
| 89 | 97 | ||
| 90 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); | 98 | memorg->luns_per_target = p->lun_count; |
| 99 | memorg->planes_per_lun = 1 << p->multi_plane_addr; | ||
| 91 | 100 | ||
| 92 | /* Please reference to the comment for nand_flash_detect_onfi. */ | 101 | /* Please reference to the comment for nand_flash_detect_onfi. */ |
| 93 | chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); | 102 | memorg->eraseblocks_per_lun = |
| 94 | chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; | 103 | 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); |
| 95 | chip->bits_per_cell = p->bits_per_cell; | 104 | memorg->bits_per_cell = p->bits_per_cell; |
| 96 | 105 | ||
| 97 | if (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS) | 106 | if (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS) |
| 98 | chip->options |= NAND_BUSWIDTH_16; | 107 | chip->options |= NAND_BUSWIDTH_16; |
| @@ -101,8 +110,8 @@ int nand_jedec_detect(struct nand_chip *chip) | |||
| 101 | ecc = &p->ecc_info[0]; | 110 | ecc = &p->ecc_info[0]; |
| 102 | 111 | ||
| 103 | if (ecc->codeword_size >= 9) { | 112 | if (ecc->codeword_size >= 9) { |
| 104 | chip->ecc_strength_ds = ecc->ecc_bits; | 113 | chip->base.eccreq.strength = ecc->ecc_bits; |
| 105 | chip->ecc_step_ds = 1 << ecc->codeword_size; | 114 | chip->base.eccreq.step_size = 1 << ecc->codeword_size; |
| 106 | } else { | 115 | } else { |
| 107 | pr_warn("Invalid codeword size\n"); | 116 | pr_warn("Invalid codeword size\n"); |
| 108 | } | 117 | } |
diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c index 47d8cda547cf..e287e71347c5 100644 --- a/drivers/mtd/nand/raw/nand_macronix.c +++ b/drivers/mtd/nand/raw/nand_macronix.c | |||
| @@ -62,7 +62,7 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip) | |||
| 62 | static int macronix_nand_init(struct nand_chip *chip) | 62 | static int macronix_nand_init(struct nand_chip *chip) |
| 63 | { | 63 | { |
| 64 | if (nand_is_slc(chip)) | 64 | if (nand_is_slc(chip)) |
| 65 | chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; | 65 | chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; |
| 66 | 66 | ||
| 67 | macronix_nand_fix_broken_get_timings(chip); | 67 | macronix_nand_fix_broken_get_timings(chip); |
| 68 | 68 | ||
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c index b85e1c13b79e..cbd4f09ac178 100644 --- a/drivers/mtd/nand/raw/nand_micron.c +++ b/drivers/mtd/nand/raw/nand_micron.c | |||
| @@ -385,13 +385,13 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip) | |||
| 385 | if (!chip->parameters.onfi) | 385 | if (!chip->parameters.onfi) |
| 386 | return MICRON_ON_DIE_UNSUPPORTED; | 386 | return MICRON_ON_DIE_UNSUPPORTED; |
| 387 | 387 | ||
| 388 | if (chip->bits_per_cell != 1) | 388 | if (nanddev_bits_per_cell(&chip->base) != 1) |
| 389 | return MICRON_ON_DIE_UNSUPPORTED; | 389 | return MICRON_ON_DIE_UNSUPPORTED; |
| 390 | 390 | ||
| 391 | /* | 391 | /* |
| 392 | * We only support on-die ECC of 4/512 or 8/512 | 392 | * We only support on-die ECC of 4/512 or 8/512 |
| 393 | */ | 393 | */ |
| 394 | if (chip->ecc_strength_ds != 4 && chip->ecc_strength_ds != 8) | 394 | if (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8) |
| 395 | return MICRON_ON_DIE_UNSUPPORTED; | 395 | return MICRON_ON_DIE_UNSUPPORTED; |
| 396 | 396 | ||
| 397 | /* 0x2 means on-die ECC is available. */ | 397 | /* 0x2 means on-die ECC is available. */ |
| @@ -424,7 +424,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip) | |||
| 424 | /* | 424 | /* |
| 425 | * We only support on-die ECC of 4/512 or 8/512 | 425 | * We only support on-die ECC of 4/512 or 8/512 |
| 426 | */ | 426 | */ |
| 427 | if (chip->ecc_strength_ds != 4 && chip->ecc_strength_ds != 8) | 427 | if (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8) |
| 428 | return MICRON_ON_DIE_UNSUPPORTED; | 428 | return MICRON_ON_DIE_UNSUPPORTED; |
| 429 | 429 | ||
| 430 | return MICRON_ON_DIE_SUPPORTED; | 430 | return MICRON_ON_DIE_SUPPORTED; |
| @@ -448,7 +448,7 @@ static int micron_nand_init(struct nand_chip *chip) | |||
| 448 | goto err_free_manuf_data; | 448 | goto err_free_manuf_data; |
| 449 | 449 | ||
| 450 | if (mtd->writesize == 2048) | 450 | if (mtd->writesize == 2048) |
| 451 | chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; | 451 | chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; |
| 452 | 452 | ||
| 453 | ondie = micron_supports_on_die_ecc(chip); | 453 | ondie = micron_supports_on_die_ecc(chip); |
| 454 | 454 | ||
| @@ -479,7 +479,7 @@ static int micron_nand_init(struct nand_chip *chip) | |||
| 479 | * That's not needed for 8-bit ECC, because the status expose | 479 | * That's not needed for 8-bit ECC, because the status expose |
| 480 | * a better approximation of the number of bitflips in a page. | 480 | * a better approximation of the number of bitflips in a page. |
| 481 | */ | 481 | */ |
| 482 | if (chip->ecc_strength_ds == 4) { | 482 | if (chip->base.eccreq.strength == 4) { |
| 483 | micron->ecc.rawbuf = kmalloc(mtd->writesize + | 483 | micron->ecc.rawbuf = kmalloc(mtd->writesize + |
| 484 | mtd->oobsize, | 484 | mtd->oobsize, |
| 485 | GFP_KERNEL); | 485 | GFP_KERNEL); |
| @@ -489,16 +489,16 @@ static int micron_nand_init(struct nand_chip *chip) | |||
| 489 | } | 489 | } |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | if (chip->ecc_strength_ds == 4) | 492 | if (chip->base.eccreq.strength == 4) |
| 493 | mtd_set_ooblayout(mtd, | 493 | mtd_set_ooblayout(mtd, |
| 494 | µn_nand_on_die_4_ooblayout_ops); | 494 | µn_nand_on_die_4_ooblayout_ops); |
| 495 | else | 495 | else |
| 496 | mtd_set_ooblayout(mtd, | 496 | mtd_set_ooblayout(mtd, |
| 497 | µn_nand_on_die_8_ooblayout_ops); | 497 | µn_nand_on_die_8_ooblayout_ops); |
| 498 | 498 | ||
| 499 | chip->ecc.bytes = chip->ecc_strength_ds * 2; | 499 | chip->ecc.bytes = chip->base.eccreq.strength * 2; |
| 500 | chip->ecc.size = 512; | 500 | chip->ecc.size = 512; |
| 501 | chip->ecc.strength = chip->ecc_strength_ds; | 501 | chip->ecc.strength = chip->base.eccreq.strength; |
| 502 | chip->ecc.algo = NAND_ECC_BCH; | 502 | chip->ecc.algo = NAND_ECC_BCH; |
| 503 | chip->ecc.read_page = micron_nand_read_page_on_die_ecc; | 503 | chip->ecc.read_page = micron_nand_read_page_on_die_ecc; |
| 504 | chip->ecc.write_page = micron_nand_write_page_on_die_ecc; | 504 | chip->ecc.write_page = micron_nand_write_page_on_die_ecc; |
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c index d8184cf591ad..0b879bd0a68c 100644 --- a/drivers/mtd/nand/raw/nand_onfi.c +++ b/drivers/mtd/nand/raw/nand_onfi.c | |||
| @@ -94,8 +94,8 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip, | |||
| 94 | goto ext_out; | 94 | goto ext_out; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | chip->ecc_strength_ds = ecc->ecc_bits; | 97 | chip->base.eccreq.strength = ecc->ecc_bits; |
| 98 | chip->ecc_step_ds = 1 << ecc->codeword_size; | 98 | chip->base.eccreq.step_size = 1 << ecc->codeword_size; |
| 99 | ret = 0; | 99 | ret = 0; |
| 100 | 100 | ||
| 101 | ext_out: | 101 | ext_out: |
| @@ -140,12 +140,15 @@ static void nand_bit_wise_majority(const void **srcbufs, | |||
| 140 | int nand_onfi_detect(struct nand_chip *chip) | 140 | int nand_onfi_detect(struct nand_chip *chip) |
| 141 | { | 141 | { |
| 142 | struct mtd_info *mtd = nand_to_mtd(chip); | 142 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 143 | struct nand_memory_organization *memorg; | ||
| 143 | struct nand_onfi_params *p; | 144 | struct nand_onfi_params *p; |
| 144 | struct onfi_params *onfi; | 145 | struct onfi_params *onfi; |
| 145 | int onfi_version = 0; | 146 | int onfi_version = 0; |
| 146 | char id[4]; | 147 | char id[4]; |
| 147 | int i, ret, val; | 148 | int i, ret, val; |
| 148 | 149 | ||
| 150 | memorg = nanddev_get_memorg(&chip->base); | ||
| 151 | |||
| 149 | /* Try ONFI for unknown chip or LP */ | 152 | /* Try ONFI for unknown chip or LP */ |
| 150 | ret = nand_readid_op(chip, 0x20, id, sizeof(id)); | 153 | ret = nand_readid_op(chip, 0x20, id, sizeof(id)); |
| 151 | if (ret || strncmp(id, "ONFI", 4)) | 154 | if (ret || strncmp(id, "ONFI", 4)) |
| @@ -221,32 +224,36 @@ int nand_onfi_detect(struct nand_chip *chip) | |||
| 221 | goto free_onfi_param_page; | 224 | goto free_onfi_param_page; |
| 222 | } | 225 | } |
| 223 | 226 | ||
| 224 | mtd->writesize = le32_to_cpu(p->byte_per_page); | 227 | memorg->pagesize = le32_to_cpu(p->byte_per_page); |
| 228 | mtd->writesize = memorg->pagesize; | ||
| 225 | 229 | ||
| 226 | /* | 230 | /* |
| 227 | * pages_per_block and blocks_per_lun may not be a power-of-2 size | 231 | * pages_per_block and blocks_per_lun may not be a power-of-2 size |
| 228 | * (don't ask me who thought of this...). MTD assumes that these | 232 | * (don't ask me who thought of this...). MTD assumes that these |
| 229 | * dimensions will be power-of-2, so just truncate the remaining area. | 233 | * dimensions will be power-of-2, so just truncate the remaining area. |
| 230 | */ | 234 | */ |
| 231 | mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); | 235 | memorg->pages_per_eraseblock = |
| 232 | mtd->erasesize *= mtd->writesize; | 236 | 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); |
| 237 | mtd->erasesize = memorg->pages_per_eraseblock * memorg->pagesize; | ||
| 233 | 238 | ||
| 234 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); | 239 | memorg->oobsize = le16_to_cpu(p->spare_bytes_per_page); |
| 240 | mtd->oobsize = memorg->oobsize; | ||
| 235 | 241 | ||
| 236 | /* See erasesize comment */ | 242 | memorg->luns_per_target = p->lun_count; |
| 237 | chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); | 243 | memorg->planes_per_lun = 1 << p->interleaved_bits; |
| 238 | chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; | ||
| 239 | chip->bits_per_cell = p->bits_per_cell; | ||
| 240 | 244 | ||
| 241 | chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun); | 245 | /* See erasesize comment */ |
| 242 | chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun); | 246 | memorg->eraseblocks_per_lun = |
| 247 | 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); | ||
| 248 | memorg->max_bad_eraseblocks_per_lun = le32_to_cpu(p->blocks_per_lun); | ||
| 249 | memorg->bits_per_cell = p->bits_per_cell; | ||
| 243 | 250 | ||
| 244 | if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS) | 251 | if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS) |
| 245 | chip->options |= NAND_BUSWIDTH_16; | 252 | chip->options |= NAND_BUSWIDTH_16; |
| 246 | 253 | ||
| 247 | if (p->ecc_bits != 0xff) { | 254 | if (p->ecc_bits != 0xff) { |
| 248 | chip->ecc_strength_ds = p->ecc_bits; | 255 | chip->base.eccreq.strength = p->ecc_bits; |
| 249 | chip->ecc_step_ds = 512; | 256 | chip->base.eccreq.step_size = 512; |
| 250 | } else if (onfi_version >= 21 && | 257 | } else if (onfi_version >= 21 && |
| 251 | (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) { | 258 | (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) { |
| 252 | 259 | ||
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c index e46d4c492ad8..5552ce20ede0 100644 --- a/drivers/mtd/nand/raw/nand_samsung.c +++ b/drivers/mtd/nand/raw/nand_samsung.c | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | static void samsung_nand_decode_id(struct nand_chip *chip) | 20 | static void samsung_nand_decode_id(struct nand_chip *chip) |
| 21 | { | 21 | { |
| 22 | struct mtd_info *mtd = nand_to_mtd(chip); | 22 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 23 | struct nand_memory_organization *memorg; | ||
| 24 | |||
| 25 | memorg = nanddev_get_memorg(&chip->base); | ||
| 23 | 26 | ||
| 24 | /* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */ | 27 | /* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */ |
| 25 | if (chip->id.len == 6 && !nand_is_slc(chip) && | 28 | if (chip->id.len == 6 && !nand_is_slc(chip) && |
| @@ -27,29 +30,30 @@ static void samsung_nand_decode_id(struct nand_chip *chip) | |||
| 27 | u8 extid = chip->id.data[3]; | 30 | u8 extid = chip->id.data[3]; |
| 28 | 31 | ||
| 29 | /* Get pagesize */ | 32 | /* Get pagesize */ |
| 30 | mtd->writesize = 2048 << (extid & 0x03); | 33 | memorg->pagesize = 2048 << (extid & 0x03); |
| 34 | mtd->writesize = memorg->pagesize; | ||
| 31 | 35 | ||
| 32 | extid >>= 2; | 36 | extid >>= 2; |
| 33 | 37 | ||
| 34 | /* Get oobsize */ | 38 | /* Get oobsize */ |
| 35 | switch (((extid >> 2) & 0x4) | (extid & 0x3)) { | 39 | switch (((extid >> 2) & 0x4) | (extid & 0x3)) { |
| 36 | case 1: | 40 | case 1: |
| 37 | mtd->oobsize = 128; | 41 | memorg->oobsize = 128; |
| 38 | break; | 42 | break; |
| 39 | case 2: | 43 | case 2: |
| 40 | mtd->oobsize = 218; | 44 | memorg->oobsize = 218; |
| 41 | break; | 45 | break; |
| 42 | case 3: | 46 | case 3: |
| 43 | mtd->oobsize = 400; | 47 | memorg->oobsize = 400; |
| 44 | break; | 48 | break; |
| 45 | case 4: | 49 | case 4: |
| 46 | mtd->oobsize = 436; | 50 | memorg->oobsize = 436; |
| 47 | break; | 51 | break; |
| 48 | case 5: | 52 | case 5: |
| 49 | mtd->oobsize = 512; | 53 | memorg->oobsize = 512; |
| 50 | break; | 54 | break; |
| 51 | case 6: | 55 | case 6: |
| 52 | mtd->oobsize = 640; | 56 | memorg->oobsize = 640; |
| 53 | break; | 57 | break; |
| 54 | default: | 58 | default: |
| 55 | /* | 59 | /* |
| @@ -62,31 +66,37 @@ static void samsung_nand_decode_id(struct nand_chip *chip) | |||
| 62 | break; | 66 | break; |
| 63 | } | 67 | } |
| 64 | 68 | ||
| 69 | mtd->oobsize = memorg->oobsize; | ||
| 70 | |||
| 65 | /* Get blocksize */ | 71 | /* Get blocksize */ |
| 66 | extid >>= 2; | 72 | extid >>= 2; |
| 73 | memorg->pages_per_eraseblock = (128 * 1024) << | ||
| 74 | (((extid >> 1) & 0x04) | | ||
| 75 | (extid & 0x03)) / | ||
| 76 | memorg->pagesize; | ||
| 67 | mtd->erasesize = (128 * 1024) << | 77 | mtd->erasesize = (128 * 1024) << |
| 68 | (((extid >> 1) & 0x04) | (extid & 0x03)); | 78 | (((extid >> 1) & 0x04) | (extid & 0x03)); |
| 69 | 79 | ||
| 70 | /* Extract ECC requirements from 5th id byte*/ | 80 | /* Extract ECC requirements from 5th id byte*/ |
| 71 | extid = (chip->id.data[4] >> 4) & 0x07; | 81 | extid = (chip->id.data[4] >> 4) & 0x07; |
| 72 | if (extid < 5) { | 82 | if (extid < 5) { |
| 73 | chip->ecc_step_ds = 512; | 83 | chip->base.eccreq.step_size = 512; |
| 74 | chip->ecc_strength_ds = 1 << extid; | 84 | chip->base.eccreq.strength = 1 << extid; |
| 75 | } else { | 85 | } else { |
| 76 | chip->ecc_step_ds = 1024; | 86 | chip->base.eccreq.step_size = 1024; |
| 77 | switch (extid) { | 87 | switch (extid) { |
| 78 | case 5: | 88 | case 5: |
| 79 | chip->ecc_strength_ds = 24; | 89 | chip->base.eccreq.strength = 24; |
| 80 | break; | 90 | break; |
| 81 | case 6: | 91 | case 6: |
| 82 | chip->ecc_strength_ds = 40; | 92 | chip->base.eccreq.strength = 40; |
| 83 | break; | 93 | break; |
| 84 | case 7: | 94 | case 7: |
| 85 | chip->ecc_strength_ds = 60; | 95 | chip->base.eccreq.strength = 60; |
| 86 | break; | 96 | break; |
| 87 | default: | 97 | default: |
| 88 | WARN(1, "Could not decode ECC info"); | 98 | WARN(1, "Could not decode ECC info"); |
| 89 | chip->ecc_step_ds = 0; | 99 | chip->base.eccreq.step_size = 0; |
| 90 | } | 100 | } |
| 91 | } | 101 | } |
| 92 | } else { | 102 | } else { |
| @@ -96,8 +106,8 @@ static void samsung_nand_decode_id(struct nand_chip *chip) | |||
| 96 | switch (chip->id.data[1]) { | 106 | switch (chip->id.data[1]) { |
| 97 | /* K9F4G08U0D-S[I|C]B0(T00) */ | 107 | /* K9F4G08U0D-S[I|C]B0(T00) */ |
| 98 | case 0xDC: | 108 | case 0xDC: |
| 99 | chip->ecc_step_ds = 512; | 109 | chip->base.eccreq.step_size = 512; |
| 100 | chip->ecc_strength_ds = 1; | 110 | chip->base.eccreq.strength = 1; |
| 101 | break; | 111 | break; |
| 102 | 112 | ||
| 103 | /* K9F1G08U0E 21nm chips do not support subpage write */ | 113 | /* K9F1G08U0E 21nm chips do not support subpage write */ |
| @@ -121,9 +131,9 @@ static int samsung_nand_init(struct nand_chip *chip) | |||
| 121 | chip->options |= NAND_SAMSUNG_LP_OPTIONS; | 131 | chip->options |= NAND_SAMSUNG_LP_OPTIONS; |
| 122 | 132 | ||
| 123 | if (!nand_is_slc(chip)) | 133 | if (!nand_is_slc(chip)) |
| 124 | chip->bbt_options |= NAND_BBT_SCANLASTPAGE; | 134 | chip->options |= NAND_BBM_LASTPAGE; |
| 125 | else | 135 | else |
| 126 | chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; | 136 | chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; |
| 127 | 137 | ||
| 128 | return 0; | 138 | return 0; |
| 129 | } | 139 | } |
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index d068163b64b3..74ffcae48726 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c | |||
| @@ -101,6 +101,9 @@ static void toshiba_nand_benand_init(struct nand_chip *chip) | |||
| 101 | static void toshiba_nand_decode_id(struct nand_chip *chip) | 101 | static void toshiba_nand_decode_id(struct nand_chip *chip) |
| 102 | { | 102 | { |
| 103 | struct mtd_info *mtd = nand_to_mtd(chip); | 103 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 104 | struct nand_memory_organization *memorg; | ||
| 105 | |||
| 106 | memorg = nanddev_get_memorg(&chip->base); | ||
| 104 | 107 | ||
| 105 | nand_decode_ext_id(chip); | 108 | nand_decode_ext_id(chip); |
| 106 | 109 | ||
| @@ -114,8 +117,10 @@ static void toshiba_nand_decode_id(struct nand_chip *chip) | |||
| 114 | */ | 117 | */ |
| 115 | if (chip->id.len >= 6 && nand_is_slc(chip) && | 118 | if (chip->id.len >= 6 && nand_is_slc(chip) && |
| 116 | (chip->id.data[5] & 0x7) == 0x6 /* 24nm */ && | 119 | (chip->id.data[5] & 0x7) == 0x6 /* 24nm */ && |
| 117 | !(chip->id.data[4] & 0x80) /* !BENAND */) | 120 | !(chip->id.data[4] & 0x80) /* !BENAND */) { |
| 118 | mtd->oobsize = 32 * mtd->writesize >> 9; | 121 | memorg->oobsize = 32 * memorg->pagesize >> 9; |
| 122 | mtd->oobsize = memorg->oobsize; | ||
| 123 | } | ||
| 119 | 124 | ||
| 120 | /* | 125 | /* |
| 121 | * Extract ECC requirements from 6th id byte. | 126 | * Extract ECC requirements from 6th id byte. |
| @@ -125,20 +130,20 @@ static void toshiba_nand_decode_id(struct nand_chip *chip) | |||
| 125 | * - 24nm: 8 bit ECC for each 512Byte is required. | 130 | * - 24nm: 8 bit ECC for each 512Byte is required. |
| 126 | */ | 131 | */ |
| 127 | if (chip->id.len >= 6 && nand_is_slc(chip)) { | 132 | if (chip->id.len >= 6 && nand_is_slc(chip)) { |
| 128 | chip->ecc_step_ds = 512; | 133 | chip->base.eccreq.step_size = 512; |
| 129 | switch (chip->id.data[5] & 0x7) { | 134 | switch (chip->id.data[5] & 0x7) { |
| 130 | case 0x4: | 135 | case 0x4: |
| 131 | chip->ecc_strength_ds = 1; | 136 | chip->base.eccreq.strength = 1; |
| 132 | break; | 137 | break; |
| 133 | case 0x5: | 138 | case 0x5: |
| 134 | chip->ecc_strength_ds = 4; | 139 | chip->base.eccreq.strength = 4; |
| 135 | break; | 140 | break; |
| 136 | case 0x6: | 141 | case 0x6: |
| 137 | chip->ecc_strength_ds = 8; | 142 | chip->base.eccreq.strength = 8; |
| 138 | break; | 143 | break; |
| 139 | default: | 144 | default: |
| 140 | WARN(1, "Could not get ECC info"); | 145 | WARN(1, "Could not get ECC info"); |
| 141 | chip->ecc_step_ds = 0; | 146 | chip->base.eccreq.step_size = 0; |
| 142 | break; | 147 | break; |
| 143 | } | 148 | } |
| 144 | } | 149 | } |
| @@ -147,7 +152,7 @@ static void toshiba_nand_decode_id(struct nand_chip *chip) | |||
| 147 | static int toshiba_nand_init(struct nand_chip *chip) | 152 | static int toshiba_nand_init(struct nand_chip *chip) |
| 148 | { | 153 | { |
| 149 | if (nand_is_slc(chip)) | 154 | if (nand_is_slc(chip)) |
| 150 | chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; | 155 | chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; |
| 151 | 156 | ||
| 152 | /* Check that chip is BENAND and ECC mode is on-die */ | 157 | /* Check that chip is BENAND and ECC mode is on-die */ |
| 153 | if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE && | 158 | if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE && |
diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index 933d1a629c51..df63fa564082 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c | |||
| @@ -298,6 +298,8 @@ union ns_mem { | |||
| 298 | * The structure which describes all the internal simulator data. | 298 | * The structure which describes all the internal simulator data. |
| 299 | */ | 299 | */ |
| 300 | struct nandsim { | 300 | struct nandsim { |
| 301 | struct nand_chip chip; | ||
| 302 | struct nand_controller base; | ||
| 301 | struct mtd_partition partitions[CONFIG_NANDSIM_MAX_PARTS]; | 303 | struct mtd_partition partitions[CONFIG_NANDSIM_MAX_PARTS]; |
| 302 | unsigned int nbparts; | 304 | unsigned int nbparts; |
| 303 | 305 | ||
| @@ -644,9 +646,6 @@ static int __init init_nandsim(struct mtd_info *mtd) | |||
| 644 | return -EIO; | 646 | return -EIO; |
| 645 | } | 647 | } |
| 646 | 648 | ||
| 647 | /* Force mtd to not do delays */ | ||
| 648 | chip->legacy.chip_delay = 0; | ||
| 649 | |||
| 650 | /* Initialize the NAND flash parameters */ | 649 | /* Initialize the NAND flash parameters */ |
| 651 | ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8; | 650 | ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8; |
| 652 | ns->geom.totsz = mtd->size; | 651 | ns->geom.totsz = mtd->size; |
| @@ -2076,24 +2075,6 @@ static void ns_nand_write_byte(struct nand_chip *chip, u_char byte) | |||
| 2076 | return; | 2075 | return; |
| 2077 | } | 2076 | } |
| 2078 | 2077 | ||
| 2079 | static void ns_hwcontrol(struct nand_chip *chip, int cmd, unsigned int bitmask) | ||
| 2080 | { | ||
| 2081 | struct nandsim *ns = nand_get_controller_data(chip); | ||
| 2082 | |||
| 2083 | ns->lines.cle = bitmask & NAND_CLE ? 1 : 0; | ||
| 2084 | ns->lines.ale = bitmask & NAND_ALE ? 1 : 0; | ||
| 2085 | ns->lines.ce = bitmask & NAND_NCE ? 1 : 0; | ||
| 2086 | |||
| 2087 | if (cmd != NAND_CMD_NONE) | ||
| 2088 | ns_nand_write_byte(chip, cmd); | ||
| 2089 | } | ||
| 2090 | |||
| 2091 | static int ns_device_ready(struct nand_chip *chip) | ||
| 2092 | { | ||
| 2093 | NS_DBG("device_ready\n"); | ||
| 2094 | return 1; | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | static void ns_nand_write_buf(struct nand_chip *chip, const u_char *buf, | 2078 | static void ns_nand_write_buf(struct nand_chip *chip, const u_char *buf, |
| 2098 | int len) | 2079 | int len) |
| 2099 | { | 2080 | { |
| @@ -2145,7 +2126,7 @@ static void ns_nand_read_buf(struct nand_chip *chip, u_char *buf, int len) | |||
| 2145 | int i; | 2126 | int i; |
| 2146 | 2127 | ||
| 2147 | for (i = 0; i < len; i++) | 2128 | for (i = 0; i < len; i++) |
| 2148 | buf[i] = chip->legacy.read_byte(chip); | 2129 | buf[i] = ns_nand_read_byte(chip); |
| 2149 | 2130 | ||
| 2150 | return; | 2131 | return; |
| 2151 | } | 2132 | } |
| @@ -2168,6 +2149,46 @@ static void ns_nand_read_buf(struct nand_chip *chip, u_char *buf, int len) | |||
| 2168 | return; | 2149 | return; |
| 2169 | } | 2150 | } |
| 2170 | 2151 | ||
| 2152 | static int ns_exec_op(struct nand_chip *chip, const struct nand_operation *op, | ||
| 2153 | bool check_only) | ||
| 2154 | { | ||
| 2155 | int i; | ||
| 2156 | unsigned int op_id; | ||
| 2157 | const struct nand_op_instr *instr = NULL; | ||
| 2158 | struct nandsim *ns = nand_get_controller_data(chip); | ||
| 2159 | |||
| 2160 | ns->lines.ce = 1; | ||
| 2161 | |||
| 2162 | for (op_id = 0; op_id < op->ninstrs; op_id++) { | ||
| 2163 | instr = &op->instrs[op_id]; | ||
| 2164 | ns->lines.cle = 0; | ||
| 2165 | ns->lines.ale = 0; | ||
| 2166 | |||
| 2167 | switch (instr->type) { | ||
| 2168 | case NAND_OP_CMD_INSTR: | ||
| 2169 | ns->lines.cle = 1; | ||
| 2170 | ns_nand_write_byte(chip, instr->ctx.cmd.opcode); | ||
| 2171 | break; | ||
| 2172 | case NAND_OP_ADDR_INSTR: | ||
| 2173 | ns->lines.ale = 1; | ||
| 2174 | for (i = 0; i < instr->ctx.addr.naddrs; i++) | ||
| 2175 | ns_nand_write_byte(chip, instr->ctx.addr.addrs[i]); | ||
| 2176 | break; | ||
| 2177 | case NAND_OP_DATA_IN_INSTR: | ||
| 2178 | ns_nand_read_buf(chip, instr->ctx.data.buf.in, instr->ctx.data.len); | ||
| 2179 | break; | ||
| 2180 | case NAND_OP_DATA_OUT_INSTR: | ||
| 2181 | ns_nand_write_buf(chip, instr->ctx.data.buf.out, instr->ctx.data.len); | ||
| 2182 | break; | ||
| 2183 | case NAND_OP_WAITRDY_INSTR: | ||
| 2184 | /* we are always ready */ | ||
| 2185 | break; | ||
| 2186 | } | ||
| 2187 | } | ||
| 2188 | |||
| 2189 | return 0; | ||
| 2190 | } | ||
| 2191 | |||
| 2171 | static int ns_attach_chip(struct nand_chip *chip) | 2192 | static int ns_attach_chip(struct nand_chip *chip) |
| 2172 | { | 2193 | { |
| 2173 | unsigned int eccsteps, eccbytes; | 2194 | unsigned int eccsteps, eccbytes; |
| @@ -2208,6 +2229,7 @@ static int ns_attach_chip(struct nand_chip *chip) | |||
| 2208 | 2229 | ||
| 2209 | static const struct nand_controller_ops ns_controller_ops = { | 2230 | static const struct nand_controller_ops ns_controller_ops = { |
| 2210 | .attach_chip = ns_attach_chip, | 2231 | .attach_chip = ns_attach_chip, |
| 2232 | .exec_op = ns_exec_op, | ||
| 2211 | }; | 2233 | }; |
| 2212 | 2234 | ||
| 2213 | /* | 2235 | /* |
| @@ -2216,7 +2238,7 @@ static const struct nand_controller_ops ns_controller_ops = { | |||
| 2216 | static int __init ns_init_module(void) | 2238 | static int __init ns_init_module(void) |
| 2217 | { | 2239 | { |
| 2218 | struct nand_chip *chip; | 2240 | struct nand_chip *chip; |
| 2219 | struct nandsim *nand; | 2241 | struct nandsim *ns; |
| 2220 | int retval = -ENOMEM, i; | 2242 | int retval = -ENOMEM, i; |
| 2221 | 2243 | ||
| 2222 | if (bus_width != 8 && bus_width != 16) { | 2244 | if (bus_width != 8 && bus_width != 16) { |
| @@ -2224,25 +2246,15 @@ static int __init ns_init_module(void) | |||
| 2224 | return -EINVAL; | 2246 | return -EINVAL; |
| 2225 | } | 2247 | } |
| 2226 | 2248 | ||
| 2227 | /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ | 2249 | ns = kzalloc(sizeof(struct nandsim), GFP_KERNEL); |
| 2228 | chip = kzalloc(sizeof(struct nand_chip) + sizeof(struct nandsim), | 2250 | if (!ns) { |
| 2229 | GFP_KERNEL); | ||
| 2230 | if (!chip) { | ||
| 2231 | NS_ERR("unable to allocate core structures.\n"); | 2251 | NS_ERR("unable to allocate core structures.\n"); |
| 2232 | return -ENOMEM; | 2252 | return -ENOMEM; |
| 2233 | } | 2253 | } |
| 2254 | chip = &ns->chip; | ||
| 2234 | nsmtd = nand_to_mtd(chip); | 2255 | nsmtd = nand_to_mtd(chip); |
| 2235 | nand = (struct nandsim *)(chip + 1); | 2256 | nand_set_controller_data(chip, (void *)ns); |
| 2236 | nand_set_controller_data(chip, (void *)nand); | ||
| 2237 | 2257 | ||
| 2238 | /* | ||
| 2239 | * Register simulator's callbacks. | ||
| 2240 | */ | ||
| 2241 | chip->legacy.cmd_ctrl = ns_hwcontrol; | ||
| 2242 | chip->legacy.read_byte = ns_nand_read_byte; | ||
| 2243 | chip->legacy.dev_ready = ns_device_ready; | ||
| 2244 | chip->legacy.write_buf = ns_nand_write_buf; | ||
| 2245 | chip->legacy.read_buf = ns_nand_read_buf; | ||
| 2246 | chip->ecc.mode = NAND_ECC_SOFT; | 2258 | chip->ecc.mode = NAND_ECC_SOFT; |
| 2247 | chip->ecc.algo = NAND_ECC_HAMMING; | 2259 | chip->ecc.algo = NAND_ECC_HAMMING; |
| 2248 | /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ | 2260 | /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ |
| @@ -2251,9 +2263,11 @@ static int __init ns_init_module(void) | |||
| 2251 | 2263 | ||
| 2252 | switch (bbt) { | 2264 | switch (bbt) { |
| 2253 | case 2: | 2265 | case 2: |
| 2254 | chip->bbt_options |= NAND_BBT_NO_OOB; | 2266 | chip->bbt_options |= NAND_BBT_NO_OOB; |
| 2267 | /* fall through */ | ||
| 2255 | case 1: | 2268 | case 1: |
| 2256 | chip->bbt_options |= NAND_BBT_USE_FLASH; | 2269 | chip->bbt_options |= NAND_BBT_USE_FLASH; |
| 2270 | /* fall through */ | ||
| 2257 | case 0: | 2271 | case 0: |
| 2258 | break; | 2272 | break; |
| 2259 | default: | 2273 | default: |
| @@ -2266,19 +2280,19 @@ static int __init ns_init_module(void) | |||
| 2266 | * the initial ID read command correctly | 2280 | * the initial ID read command correctly |
| 2267 | */ | 2281 | */ |
| 2268 | if (id_bytes[6] != 0xFF || id_bytes[7] != 0xFF) | 2282 | if (id_bytes[6] != 0xFF || id_bytes[7] != 0xFF) |
| 2269 | nand->geom.idbytes = 8; | 2283 | ns->geom.idbytes = 8; |
| 2270 | else if (id_bytes[4] != 0xFF || id_bytes[5] != 0xFF) | 2284 | else if (id_bytes[4] != 0xFF || id_bytes[5] != 0xFF) |
| 2271 | nand->geom.idbytes = 6; | 2285 | ns->geom.idbytes = 6; |
| 2272 | else if (id_bytes[2] != 0xFF || id_bytes[3] != 0xFF) | 2286 | else if (id_bytes[2] != 0xFF || id_bytes[3] != 0xFF) |
| 2273 | nand->geom.idbytes = 4; | 2287 | ns->geom.idbytes = 4; |
| 2274 | else | 2288 | else |
| 2275 | nand->geom.idbytes = 2; | 2289 | ns->geom.idbytes = 2; |
| 2276 | nand->regs.status = NS_STATUS_OK(nand); | 2290 | ns->regs.status = NS_STATUS_OK(ns); |
| 2277 | nand->nxstate = STATE_UNKNOWN; | 2291 | ns->nxstate = STATE_UNKNOWN; |
| 2278 | nand->options |= OPT_PAGE512; /* temporary value */ | 2292 | ns->options |= OPT_PAGE512; /* temporary value */ |
| 2279 | memcpy(nand->ids, id_bytes, sizeof(nand->ids)); | 2293 | memcpy(ns->ids, id_bytes, sizeof(ns->ids)); |
| 2280 | if (bus_width == 16) { | 2294 | if (bus_width == 16) { |
| 2281 | nand->busw = 16; | 2295 | ns->busw = 16; |
| 2282 | chip->options |= NAND_BUSWIDTH_16; | 2296 | chip->options |= NAND_BUSWIDTH_16; |
| 2283 | } | 2297 | } |
| 2284 | 2298 | ||
| @@ -2293,7 +2307,10 @@ static int __init ns_init_module(void) | |||
| 2293 | if ((retval = parse_gravepages()) != 0) | 2307 | if ((retval = parse_gravepages()) != 0) |
| 2294 | goto error; | 2308 | goto error; |
| 2295 | 2309 | ||
| 2296 | chip->legacy.dummy_controller.ops = &ns_controller_ops; | 2310 | nand_controller_init(&ns->base); |
| 2311 | ns->base.ops = &ns_controller_ops; | ||
| 2312 | chip->controller = &ns->base; | ||
| 2313 | |||
| 2297 | retval = nand_scan(chip, 1); | 2314 | retval = nand_scan(chip, 1); |
| 2298 | if (retval) { | 2315 | if (retval) { |
| 2299 | NS_ERR("Could not scan NAND Simulator device\n"); | 2316 | NS_ERR("Could not scan NAND Simulator device\n"); |
| @@ -2302,16 +2319,23 @@ static int __init ns_init_module(void) | |||
| 2302 | 2319 | ||
| 2303 | if (overridesize) { | 2320 | if (overridesize) { |
| 2304 | uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize; | 2321 | uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize; |
| 2322 | struct nand_memory_organization *memorg; | ||
| 2323 | u64 targetsize; | ||
| 2324 | |||
| 2325 | memorg = nanddev_get_memorg(&chip->base); | ||
| 2326 | |||
| 2305 | if (new_size >> overridesize != nsmtd->erasesize) { | 2327 | if (new_size >> overridesize != nsmtd->erasesize) { |
| 2306 | NS_ERR("overridesize is too big\n"); | 2328 | NS_ERR("overridesize is too big\n"); |
| 2307 | retval = -EINVAL; | 2329 | retval = -EINVAL; |
| 2308 | goto err_exit; | 2330 | goto err_exit; |
| 2309 | } | 2331 | } |
| 2332 | |||
| 2310 | /* N.B. This relies on nand_scan not doing anything with the size before we change it */ | 2333 | /* N.B. This relies on nand_scan not doing anything with the size before we change it */ |
| 2311 | nsmtd->size = new_size; | 2334 | nsmtd->size = new_size; |
| 2312 | chip->chipsize = new_size; | 2335 | memorg->eraseblocks_per_lun = 1 << overridesize; |
| 2336 | targetsize = nanddev_target_size(&chip->base); | ||
| 2313 | chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1; | 2337 | chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1; |
| 2314 | chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; | 2338 | chip->pagemask = (targetsize >> chip->page_shift) - 1; |
| 2315 | } | 2339 | } |
| 2316 | 2340 | ||
| 2317 | if ((retval = setup_wear_reporting(nsmtd)) != 0) | 2341 | if ((retval = setup_wear_reporting(nsmtd)) != 0) |
| @@ -2323,27 +2347,27 @@ static int __init ns_init_module(void) | |||
| 2323 | if ((retval = nand_create_bbt(chip)) != 0) | 2347 | if ((retval = nand_create_bbt(chip)) != 0) |
| 2324 | goto err_exit; | 2348 | goto err_exit; |
| 2325 | 2349 | ||
| 2326 | if ((retval = parse_badblocks(nand, nsmtd)) != 0) | 2350 | if ((retval = parse_badblocks(ns, nsmtd)) != 0) |
| 2327 | goto err_exit; | 2351 | goto err_exit; |
| 2328 | 2352 | ||
| 2329 | /* Register NAND partitions */ | 2353 | /* Register NAND partitions */ |
| 2330 | retval = mtd_device_register(nsmtd, &nand->partitions[0], | 2354 | retval = mtd_device_register(nsmtd, &ns->partitions[0], |
| 2331 | nand->nbparts); | 2355 | ns->nbparts); |
| 2332 | if (retval != 0) | 2356 | if (retval != 0) |
| 2333 | goto err_exit; | 2357 | goto err_exit; |
| 2334 | 2358 | ||
| 2335 | if ((retval = nandsim_debugfs_create(nand)) != 0) | 2359 | if ((retval = nandsim_debugfs_create(ns)) != 0) |
| 2336 | goto err_exit; | 2360 | goto err_exit; |
| 2337 | 2361 | ||
| 2338 | return 0; | 2362 | return 0; |
| 2339 | 2363 | ||
| 2340 | err_exit: | 2364 | err_exit: |
| 2341 | free_nandsim(nand); | 2365 | free_nandsim(ns); |
| 2342 | nand_release(chip); | 2366 | nand_release(chip); |
| 2343 | for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i) | 2367 | for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) |
| 2344 | kfree(nand->partitions[i].name); | 2368 | kfree(ns->partitions[i].name); |
| 2345 | error: | 2369 | error: |
| 2346 | kfree(chip); | 2370 | kfree(ns); |
| 2347 | free_lists(); | 2371 | free_lists(); |
| 2348 | 2372 | ||
| 2349 | return retval; | 2373 | return retval; |
| @@ -2364,7 +2388,7 @@ static void __exit ns_cleanup_module(void) | |||
| 2364 | nand_release(chip); /* Unregister driver */ | 2388 | nand_release(chip); /* Unregister driver */ |
| 2365 | for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) | 2389 | for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) |
| 2366 | kfree(ns->partitions[i].name); | 2390 | kfree(ns->partitions[i].name); |
| 2367 | kfree(mtd_to_nand(nsmtd)); /* Free other structures */ | 2391 | kfree(ns); /* Free other structures */ |
| 2368 | free_lists(); | 2392 | free_lists(); |
| 2369 | } | 2393 | } |
| 2370 | 2394 | ||
diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 38b1994e7ed3..56fa84029482 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c | |||
| @@ -192,8 +192,9 @@ static void nuc900_nand_command_lp(struct nand_chip *chip, | |||
| 192 | return; | 192 | return; |
| 193 | 193 | ||
| 194 | case NAND_CMD_READ0: | 194 | case NAND_CMD_READ0: |
| 195 | |||
| 196 | write_cmd_reg(nand, NAND_CMD_READSTART); | 195 | write_cmd_reg(nand, NAND_CMD_READSTART); |
| 196 | /* fall through */ | ||
| 197 | |||
| 197 | default: | 198 | default: |
| 198 | 199 | ||
| 199 | if (!chip->legacy.dev_ready) { | 200 | if (!chip->legacy.dev_ready) { |
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 8f280a2962c8..a9a275342a41 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c | |||
| @@ -1725,9 +1725,9 @@ static bool omap2_nand_ecc_check(struct omap_nand_info *info) | |||
| 1725 | break; | 1725 | break; |
| 1726 | } | 1726 | } |
| 1727 | 1727 | ||
| 1728 | if (ecc_needs_bch && !IS_ENABLED(CONFIG_MTD_NAND_ECC_BCH)) { | 1728 | if (ecc_needs_bch && !IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH)) { |
| 1729 | dev_err(&info->pdev->dev, | 1729 | dev_err(&info->pdev->dev, |
| 1730 | "CONFIG_MTD_NAND_ECC_BCH not enabled\n"); | 1730 | "CONFIG_MTD_NAND_ECC_SW_BCH not enabled\n"); |
| 1731 | return false; | 1731 | return false; |
| 1732 | } | 1732 | } |
| 1733 | if (ecc_needs_omap_bch && !IS_ENABLED(CONFIG_MTD_NAND_OMAP_BCH)) { | 1733 | if (ecc_needs_omap_bch && !IS_ENABLED(CONFIG_MTD_NAND_OMAP_BCH)) { |
diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index a3f32f939cc1..94c6401ef32f 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c | |||
| @@ -465,11 +465,13 @@ static int elm_context_save(struct elm_info *info) | |||
| 465 | ELM_SYNDROME_FRAGMENT_5 + offset); | 465 | ELM_SYNDROME_FRAGMENT_5 + offset); |
| 466 | regs->elm_syndrome_fragment_4[i] = elm_read_reg(info, | 466 | regs->elm_syndrome_fragment_4[i] = elm_read_reg(info, |
| 467 | ELM_SYNDROME_FRAGMENT_4 + offset); | 467 | ELM_SYNDROME_FRAGMENT_4 + offset); |
| 468 | /* fall through */ | ||
| 468 | case BCH8_ECC: | 469 | case BCH8_ECC: |
| 469 | regs->elm_syndrome_fragment_3[i] = elm_read_reg(info, | 470 | regs->elm_syndrome_fragment_3[i] = elm_read_reg(info, |
| 470 | ELM_SYNDROME_FRAGMENT_3 + offset); | 471 | ELM_SYNDROME_FRAGMENT_3 + offset); |
| 471 | regs->elm_syndrome_fragment_2[i] = elm_read_reg(info, | 472 | regs->elm_syndrome_fragment_2[i] = elm_read_reg(info, |
| 472 | ELM_SYNDROME_FRAGMENT_2 + offset); | 473 | ELM_SYNDROME_FRAGMENT_2 + offset); |
| 474 | /* fall through */ | ||
| 473 | case BCH4_ECC: | 475 | case BCH4_ECC: |
| 474 | regs->elm_syndrome_fragment_1[i] = elm_read_reg(info, | 476 | regs->elm_syndrome_fragment_1[i] = elm_read_reg(info, |
| 475 | ELM_SYNDROME_FRAGMENT_1 + offset); | 477 | ELM_SYNDROME_FRAGMENT_1 + offset); |
| @@ -511,11 +513,13 @@ static int elm_context_restore(struct elm_info *info) | |||
| 511 | regs->elm_syndrome_fragment_5[i]); | 513 | regs->elm_syndrome_fragment_5[i]); |
| 512 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_4 + offset, | 514 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_4 + offset, |
| 513 | regs->elm_syndrome_fragment_4[i]); | 515 | regs->elm_syndrome_fragment_4[i]); |
| 516 | /* fall through */ | ||
| 514 | case BCH8_ECC: | 517 | case BCH8_ECC: |
| 515 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_3 + offset, | 518 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_3 + offset, |
| 516 | regs->elm_syndrome_fragment_3[i]); | 519 | regs->elm_syndrome_fragment_3[i]); |
| 517 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_2 + offset, | 520 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_2 + offset, |
| 518 | regs->elm_syndrome_fragment_2[i]); | 521 | regs->elm_syndrome_fragment_2[i]); |
| 522 | /* fall through */ | ||
| 519 | case BCH4_ECC: | 523 | case BCH4_ECC: |
| 520 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_1 + offset, | 524 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_1 + offset, |
| 521 | regs->elm_syndrome_fragment_1[i]); | 525 | regs->elm_syndrome_fragment_1[i]); |
diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 920e7375084f..6ead55e05b80 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c | |||
| @@ -1680,14 +1680,12 @@ check_for_erased_page(struct qcom_nand_host *host, u8 *data_buf, | |||
| 1680 | u8 *cw_data_buf, *cw_oob_buf; | 1680 | u8 *cw_data_buf, *cw_oob_buf; |
| 1681 | int cw, data_size, oob_size, ret = 0; | 1681 | int cw, data_size, oob_size, ret = 0; |
| 1682 | 1682 | ||
| 1683 | if (!data_buf) { | 1683 | if (!data_buf) |
| 1684 | data_buf = chip->data_buf; | 1684 | data_buf = nand_get_data_buf(chip); |
| 1685 | chip->pagebuf = -1; | ||
| 1686 | } | ||
| 1687 | 1685 | ||
| 1688 | if (!oob_buf) { | 1686 | if (!oob_buf) { |
| 1687 | nand_get_data_buf(chip); | ||
| 1689 | oob_buf = chip->oob_poi; | 1688 | oob_buf = chip->oob_poi; |
| 1690 | chip->pagebuf = -1; | ||
| 1691 | } | 1689 | } |
| 1692 | 1690 | ||
| 1693 | for_each_set_bit(cw, &uncorrectable_cws, ecc->steps) { | 1691 | for_each_set_bit(cw, &uncorrectable_cws, ecc->steps) { |
diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index cf6b1be1cf9c..e509c93737c4 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c | |||
| @@ -101,14 +101,12 @@ static const struct mtd_ooblayout_ops flctl_4secc_oob_largepage_ops = { | |||
| 101 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 101 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
| 102 | 102 | ||
| 103 | static struct nand_bbt_descr flctl_4secc_smallpage = { | 103 | static struct nand_bbt_descr flctl_4secc_smallpage = { |
| 104 | .options = NAND_BBT_SCAN2NDPAGE, | ||
| 105 | .offs = 11, | 104 | .offs = 11, |
| 106 | .len = 1, | 105 | .len = 1, |
| 107 | .pattern = scan_ff_pattern, | 106 | .pattern = scan_ff_pattern, |
| 108 | }; | 107 | }; |
| 109 | 108 | ||
| 110 | static struct nand_bbt_descr flctl_4secc_largepage = { | 109 | static struct nand_bbt_descr flctl_4secc_largepage = { |
| 111 | .options = NAND_BBT_SCAN2NDPAGE, | ||
| 112 | .offs = 0, | 110 | .offs = 0, |
| 113 | .len = 2, | 111 | .len = 2, |
| 114 | .pattern = scan_ff_pattern, | 112 | .pattern = scan_ff_pattern, |
| @@ -986,6 +984,7 @@ static void flctl_read_buf(struct nand_chip *chip, uint8_t *buf, int len) | |||
| 986 | 984 | ||
| 987 | static int flctl_chip_attach_chip(struct nand_chip *chip) | 985 | static int flctl_chip_attach_chip(struct nand_chip *chip) |
| 988 | { | 986 | { |
| 987 | u64 targetsize = nanddev_target_size(&chip->base); | ||
| 989 | struct mtd_info *mtd = nand_to_mtd(chip); | 988 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 990 | struct sh_flctl *flctl = mtd_to_flctl(mtd); | 989 | struct sh_flctl *flctl = mtd_to_flctl(mtd); |
| 991 | 990 | ||
| @@ -998,11 +997,11 @@ static int flctl_chip_attach_chip(struct nand_chip *chip) | |||
| 998 | 997 | ||
| 999 | if (mtd->writesize == 512) { | 998 | if (mtd->writesize == 512) { |
| 1000 | flctl->page_size = 0; | 999 | flctl->page_size = 0; |
| 1001 | if (chip->chipsize > (32 << 20)) { | 1000 | if (targetsize > (32 << 20)) { |
| 1002 | /* big than 32MB */ | 1001 | /* big than 32MB */ |
| 1003 | flctl->rw_ADRCNT = ADRCNT_4; | 1002 | flctl->rw_ADRCNT = ADRCNT_4; |
| 1004 | flctl->erase_ADRCNT = ADRCNT_3; | 1003 | flctl->erase_ADRCNT = ADRCNT_3; |
| 1005 | } else if (chip->chipsize > (2 << 16)) { | 1004 | } else if (targetsize > (2 << 16)) { |
| 1006 | /* big than 128KB */ | 1005 | /* big than 128KB */ |
| 1007 | flctl->rw_ADRCNT = ADRCNT_3; | 1006 | flctl->rw_ADRCNT = ADRCNT_3; |
| 1008 | flctl->erase_ADRCNT = ADRCNT_2; | 1007 | flctl->erase_ADRCNT = ADRCNT_2; |
| @@ -1012,11 +1011,11 @@ static int flctl_chip_attach_chip(struct nand_chip *chip) | |||
| 1012 | } | 1011 | } |
| 1013 | } else { | 1012 | } else { |
| 1014 | flctl->page_size = 1; | 1013 | flctl->page_size = 1; |
| 1015 | if (chip->chipsize > (128 << 20)) { | 1014 | if (targetsize > (128 << 20)) { |
| 1016 | /* big than 128MB */ | 1015 | /* big than 128MB */ |
| 1017 | flctl->rw_ADRCNT = ADRCNT2_E; | 1016 | flctl->rw_ADRCNT = ADRCNT2_E; |
| 1018 | flctl->erase_ADRCNT = ADRCNT_3; | 1017 | flctl->erase_ADRCNT = ADRCNT_3; |
| 1019 | } else if (chip->chipsize > (8 << 16)) { | 1018 | } else if (targetsize > (8 << 16)) { |
| 1020 | /* big than 512KB */ | 1019 | /* big than 512KB */ |
| 1021 | flctl->rw_ADRCNT = ADRCNT_4; | 1020 | flctl->rw_ADRCNT = ADRCNT_4; |
| 1022 | flctl->erase_ADRCNT = ADRCNT_2; | 1021 | flctl->erase_ADRCNT = ADRCNT_2; |
| @@ -1178,6 +1177,8 @@ static int flctl_probe(struct platform_device *pdev) | |||
| 1178 | if (pdata->flcmncr_val & SEL_16BIT) | 1177 | if (pdata->flcmncr_val & SEL_16BIT) |
| 1179 | nand->options |= NAND_BUSWIDTH_16; | 1178 | nand->options |= NAND_BUSWIDTH_16; |
| 1180 | 1179 | ||
| 1180 | nand->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; | ||
| 1181 | |||
| 1181 | pm_runtime_enable(&pdev->dev); | 1182 | pm_runtime_enable(&pdev->dev); |
| 1182 | pm_runtime_resume(&pdev->dev); | 1183 | pm_runtime_resume(&pdev->dev); |
| 1183 | 1184 | ||
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 4282bc477761..b021a5720b42 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c | |||
| @@ -42,7 +42,8 @@ | |||
| 42 | #define NFC_REG_CMD 0x0024 | 42 | #define NFC_REG_CMD 0x0024 |
| 43 | #define NFC_REG_RCMD_SET 0x0028 | 43 | #define NFC_REG_RCMD_SET 0x0028 |
| 44 | #define NFC_REG_WCMD_SET 0x002C | 44 | #define NFC_REG_WCMD_SET 0x002C |
| 45 | #define NFC_REG_IO_DATA 0x0030 | 45 | #define NFC_REG_A10_IO_DATA 0x0030 |
| 46 | #define NFC_REG_A23_IO_DATA 0x0300 | ||
| 46 | #define NFC_REG_ECC_CTL 0x0034 | 47 | #define NFC_REG_ECC_CTL 0x0034 |
| 47 | #define NFC_REG_ECC_ST 0x0038 | 48 | #define NFC_REG_ECC_ST 0x0038 |
| 48 | #define NFC_REG_DEBUG 0x003C | 49 | #define NFC_REG_DEBUG 0x003C |
| @@ -200,6 +201,22 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand) | |||
| 200 | return container_of(nand, struct sunxi_nand_chip, nand); | 201 | return container_of(nand, struct sunxi_nand_chip, nand); |
| 201 | } | 202 | } |
| 202 | 203 | ||
| 204 | /* | ||
| 205 | * NAND Controller capabilities structure: stores NAND controller capabilities | ||
| 206 | * for distinction between compatible strings. | ||
| 207 | * | ||
| 208 | * @sram_through_ahb: On A23, we choose to access the internal RAM through AHB | ||
| 209 | * instead of MBUS (less configuration). A10, A10s, A13 and | ||
| 210 | * A20 use the MBUS but no extra configuration is needed. | ||
| 211 | * @reg_io_data: I/O data register | ||
| 212 | * @dma_maxburst: DMA maxburst | ||
| 213 | */ | ||
| 214 | struct sunxi_nfc_caps { | ||
| 215 | bool sram_through_ahb; | ||
| 216 | unsigned int reg_io_data; | ||
| 217 | unsigned int dma_maxburst; | ||
| 218 | }; | ||
| 219 | |||
| 203 | /** | 220 | /** |
| 204 | * struct sunxi_nfc - stores sunxi NAND controller information | 221 | * struct sunxi_nfc - stores sunxi NAND controller information |
| 205 | * | 222 | * |
| @@ -228,6 +245,7 @@ struct sunxi_nfc { | |||
| 228 | struct list_head chips; | 245 | struct list_head chips; |
| 229 | struct completion complete; | 246 | struct completion complete; |
| 230 | struct dma_chan *dmac; | 247 | struct dma_chan *dmac; |
| 248 | const struct sunxi_nfc_caps *caps; | ||
| 231 | }; | 249 | }; |
| 232 | 250 | ||
| 233 | static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_controller *ctrl) | 251 | static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_controller *ctrl) |
| @@ -350,10 +368,29 @@ static int sunxi_nfc_dma_op_prepare(struct sunxi_nfc *nfc, const void *buf, | |||
| 350 | goto err_unmap_buf; | 368 | goto err_unmap_buf; |
| 351 | } | 369 | } |
| 352 | 370 | ||
| 353 | writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD, | 371 | /* |
| 354 | nfc->regs + NFC_REG_CTL); | 372 | * On A23, we suppose the "internal RAM" (p.12 of the NFC user manual) |
| 373 | * refers to the NAND controller's internal SRAM. This memory is mapped | ||
| 374 | * and so is accessible from the AHB. It seems that it can also be | ||
| 375 | * accessed by the MBUS. MBUS accesses are mandatory when using the | ||
| 376 | * internal DMA instead of the external DMA engine. | ||
| 377 | * | ||
| 378 | * During DMA I/O operation, either we access this memory from the AHB | ||
| 379 | * by clearing the NFC_RAM_METHOD bit, or we set the bit and use the | ||
| 380 | * MBUS. In this case, we should also configure the MBUS DMA length | ||
| 381 | * NFC_REG_MDMA_CNT(0xC4) to be chunksize * nchunks. NAND I/O over MBUS | ||
| 382 | * are also limited to 32kiB pages. | ||
| 383 | */ | ||
| 384 | if (nfc->caps->sram_through_ahb) | ||
| 385 | writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD, | ||
| 386 | nfc->regs + NFC_REG_CTL); | ||
| 387 | else | ||
| 388 | writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD, | ||
| 389 | nfc->regs + NFC_REG_CTL); | ||
| 390 | |||
| 355 | writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM); | 391 | writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM); |
| 356 | writel(chunksize, nfc->regs + NFC_REG_CNT); | 392 | writel(chunksize, nfc->regs + NFC_REG_CNT); |
| 393 | |||
| 357 | dmat = dmaengine_submit(dmad); | 394 | dmat = dmaengine_submit(dmad); |
| 358 | 395 | ||
| 359 | ret = dma_submit_error(dmat); | 396 | ret = dma_submit_error(dmat); |
| @@ -1313,20 +1350,19 @@ pio_fallback: | |||
| 1313 | 1350 | ||
| 1314 | static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *nand, int page) | 1351 | static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *nand, int page) |
| 1315 | { | 1352 | { |
| 1316 | nand->pagebuf = -1; | 1353 | u8 *buf = nand_get_data_buf(nand); |
| 1317 | 1354 | ||
| 1318 | return nand->ecc.read_page(nand, nand->data_buf, 1, page); | 1355 | return nand->ecc.read_page(nand, buf, 1, page); |
| 1319 | } | 1356 | } |
| 1320 | 1357 | ||
| 1321 | static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *nand, int page) | 1358 | static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *nand, int page) |
| 1322 | { | 1359 | { |
| 1323 | struct mtd_info *mtd = nand_to_mtd(nand); | 1360 | struct mtd_info *mtd = nand_to_mtd(nand); |
| 1361 | u8 *buf = nand_get_data_buf(nand); | ||
| 1324 | int ret; | 1362 | int ret; |
| 1325 | 1363 | ||
| 1326 | nand->pagebuf = -1; | 1364 | memset(buf, 0xff, mtd->writesize); |
| 1327 | 1365 | ret = nand->ecc.write_page(nand, buf, 1, page); | |
| 1328 | memset(nand->data_buf, 0xff, mtd->writesize); | ||
| 1329 | ret = nand->ecc.write_page(nand, nand->data_buf, 1, page); | ||
| 1330 | if (ret) | 1366 | if (ret) |
| 1331 | return ret; | 1367 | return ret; |
| 1332 | 1368 | ||
| @@ -1724,8 +1760,8 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand) | |||
| 1724 | nand->options |= NAND_SUBPAGE_READ; | 1760 | nand->options |= NAND_SUBPAGE_READ; |
| 1725 | 1761 | ||
| 1726 | if (!ecc->size) { | 1762 | if (!ecc->size) { |
| 1727 | ecc->size = nand->ecc_step_ds; | 1763 | ecc->size = nand->base.eccreq.step_size; |
| 1728 | ecc->strength = nand->ecc_strength_ds; | 1764 | ecc->strength = nand->base.eccreq.strength; |
| 1729 | } | 1765 | } |
| 1730 | 1766 | ||
| 1731 | if (!ecc->size || !ecc->strength) | 1767 | if (!ecc->size || !ecc->strength) |
| @@ -2088,6 +2124,12 @@ static int sunxi_nfc_probe(struct platform_device *pdev) | |||
| 2088 | goto out_mod_clk_unprepare; | 2124 | goto out_mod_clk_unprepare; |
| 2089 | } | 2125 | } |
| 2090 | 2126 | ||
| 2127 | nfc->caps = of_device_get_match_data(&pdev->dev); | ||
| 2128 | if (!nfc->caps) { | ||
| 2129 | ret = -EINVAL; | ||
| 2130 | goto out_ahb_reset_reassert; | ||
| 2131 | } | ||
| 2132 | |||
| 2091 | ret = sunxi_nfc_rst(nfc); | 2133 | ret = sunxi_nfc_rst(nfc); |
| 2092 | if (ret) | 2134 | if (ret) |
| 2093 | goto out_ahb_reset_reassert; | 2135 | goto out_ahb_reset_reassert; |
| @@ -2102,12 +2144,12 @@ static int sunxi_nfc_probe(struct platform_device *pdev) | |||
| 2102 | if (nfc->dmac) { | 2144 | if (nfc->dmac) { |
| 2103 | struct dma_slave_config dmac_cfg = { }; | 2145 | struct dma_slave_config dmac_cfg = { }; |
| 2104 | 2146 | ||
| 2105 | dmac_cfg.src_addr = r->start + NFC_REG_IO_DATA; | 2147 | dmac_cfg.src_addr = r->start + nfc->caps->reg_io_data; |
| 2106 | dmac_cfg.dst_addr = dmac_cfg.src_addr; | 2148 | dmac_cfg.dst_addr = dmac_cfg.src_addr; |
| 2107 | dmac_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 2149 | dmac_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
| 2108 | dmac_cfg.dst_addr_width = dmac_cfg.src_addr_width; | 2150 | dmac_cfg.dst_addr_width = dmac_cfg.src_addr_width; |
| 2109 | dmac_cfg.src_maxburst = 4; | 2151 | dmac_cfg.src_maxburst = nfc->caps->dma_maxburst; |
| 2110 | dmac_cfg.dst_maxburst = 4; | 2152 | dmac_cfg.dst_maxburst = nfc->caps->dma_maxburst; |
| 2111 | dmaengine_slave_config(nfc->dmac, &dmac_cfg); | 2153 | dmaengine_slave_config(nfc->dmac, &dmac_cfg); |
| 2112 | } else { | 2154 | } else { |
| 2113 | dev_warn(dev, "failed to request rxtx DMA channel\n"); | 2155 | dev_warn(dev, "failed to request rxtx DMA channel\n"); |
| @@ -2152,8 +2194,26 @@ static int sunxi_nfc_remove(struct platform_device *pdev) | |||
| 2152 | return 0; | 2194 | return 0; |
| 2153 | } | 2195 | } |
| 2154 | 2196 | ||
| 2197 | static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = { | ||
| 2198 | .reg_io_data = NFC_REG_A10_IO_DATA, | ||
| 2199 | .dma_maxburst = 4, | ||
| 2200 | }; | ||
| 2201 | |||
| 2202 | static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = { | ||
| 2203 | .sram_through_ahb = true, | ||
| 2204 | .reg_io_data = NFC_REG_A23_IO_DATA, | ||
| 2205 | .dma_maxburst = 8, | ||
| 2206 | }; | ||
| 2207 | |||
| 2155 | static const struct of_device_id sunxi_nfc_ids[] = { | 2208 | static const struct of_device_id sunxi_nfc_ids[] = { |
| 2156 | { .compatible = "allwinner,sun4i-a10-nand" }, | 2209 | { |
| 2210 | .compatible = "allwinner,sun4i-a10-nand", | ||
| 2211 | .data = &sunxi_nfc_a10_caps, | ||
| 2212 | }, | ||
| 2213 | { | ||
| 2214 | .compatible = "allwinner,sun8i-a23-nand-controller", | ||
| 2215 | .data = &sunxi_nfc_a23_caps, | ||
| 2216 | }, | ||
| 2157 | { /* sentinel */ } | 2217 | { /* sentinel */ } |
| 2158 | }; | 2218 | }; |
| 2159 | MODULE_DEVICE_TABLE(of, sunxi_nfc_ids); | 2219 | MODULE_DEVICE_TABLE(of, sunxi_nfc_ids); |
diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index 13be32c38194..3cc9a4c41443 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c | |||
| @@ -853,7 +853,7 @@ static int tegra_nand_get_strength(struct nand_chip *chip, const int *strength, | |||
| 853 | } else { | 853 | } else { |
| 854 | strength_sel = strength[i]; | 854 | strength_sel = strength[i]; |
| 855 | 855 | ||
| 856 | if (strength_sel < chip->ecc_strength_ds) | 856 | if (strength_sel < chip->base.eccreq.strength) |
| 857 | continue; | 857 | continue; |
| 858 | } | 858 | } |
| 859 | 859 | ||
| @@ -917,9 +917,9 @@ static int tegra_nand_attach_chip(struct nand_chip *chip) | |||
| 917 | chip->ecc.mode = NAND_ECC_HW; | 917 | chip->ecc.mode = NAND_ECC_HW; |
| 918 | chip->ecc.size = 512; | 918 | chip->ecc.size = 512; |
| 919 | chip->ecc.steps = mtd->writesize / chip->ecc.size; | 919 | chip->ecc.steps = mtd->writesize / chip->ecc.size; |
| 920 | if (chip->ecc_step_ds != 512) { | 920 | if (chip->base.eccreq.step_size != 512) { |
| 921 | dev_err(ctrl->dev, "Unsupported step size %d\n", | 921 | dev_err(ctrl->dev, "Unsupported step size %d\n", |
| 922 | chip->ecc_step_ds); | 922 | chip->base.eccreq.step_size); |
| 923 | return -EINVAL; | 923 | return -EINVAL; |
| 924 | } | 924 | } |
| 925 | 925 | ||
| @@ -950,7 +950,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip) | |||
| 950 | if (ret < 0) { | 950 | if (ret < 0) { |
| 951 | dev_err(ctrl->dev, | 951 | dev_err(ctrl->dev, |
| 952 | "No valid strength found, minimum %d\n", | 952 | "No valid strength found, minimum %d\n", |
| 953 | chip->ecc_strength_ds); | 953 | chip->base.eccreq.strength); |
| 954 | return ret; | 954 | return ret; |
| 955 | } | 955 | } |
| 956 | 956 | ||
diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index a662ca1970e5..6d43ddb3332f 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c | |||
| @@ -850,6 +850,9 @@ static int vf610_nfc_probe(struct platform_device *pdev) | |||
| 850 | } | 850 | } |
| 851 | 851 | ||
| 852 | of_id = of_match_device(vf610_nfc_dt_ids, &pdev->dev); | 852 | of_id = of_match_device(vf610_nfc_dt_ids, &pdev->dev); |
| 853 | if (!of_id) | ||
| 854 | return -ENODEV; | ||
| 855 | |||
| 853 | nfc->variant = (enum vf610_nfc_variant)of_id->data; | 856 | nfc->variant = (enum vf610_nfc_variant)of_id->data; |
| 854 | 857 | ||
| 855 | for_each_available_child_of_node(nfc->dev->of_node, child) { | 858 | for_each_available_child_of_node(nfc->dev->of_node, child) { |
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index fa87ae28cdfe..4c15bb58c623 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c | |||
| @@ -19,21 +19,6 @@ | |||
| 19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
| 20 | #include <linux/spi/spi-mem.h> | 20 | #include <linux/spi/spi-mem.h> |
| 21 | 21 | ||
| 22 | static void spinand_cache_op_adjust_colum(struct spinand_device *spinand, | ||
| 23 | const struct nand_page_io_req *req, | ||
| 24 | u16 *column) | ||
| 25 | { | ||
| 26 | struct nand_device *nand = spinand_to_nand(spinand); | ||
| 27 | unsigned int shift; | ||
| 28 | |||
| 29 | if (nand->memorg.planes_per_lun < 2) | ||
| 30 | return; | ||
| 31 | |||
| 32 | /* The plane number is passed in MSB just above the column address */ | ||
| 33 | shift = fls(nand->memorg.pagesize); | ||
| 34 | *column |= req->pos.plane << shift; | ||
| 35 | } | ||
| 36 | |||
| 37 | static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) | 22 | static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) |
| 38 | { | 23 | { |
| 39 | struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg, | 24 | struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg, |
| @@ -227,27 +212,21 @@ static int spinand_load_page_op(struct spinand_device *spinand, | |||
| 227 | static int spinand_read_from_cache_op(struct spinand_device *spinand, | 212 | static int spinand_read_from_cache_op(struct spinand_device *spinand, |
| 228 | const struct nand_page_io_req *req) | 213 | const struct nand_page_io_req *req) |
| 229 | { | 214 | { |
| 230 | struct spi_mem_op op = *spinand->op_templates.read_cache; | ||
| 231 | struct nand_device *nand = spinand_to_nand(spinand); | 215 | struct nand_device *nand = spinand_to_nand(spinand); |
| 232 | struct mtd_info *mtd = nanddev_to_mtd(nand); | 216 | struct mtd_info *mtd = nanddev_to_mtd(nand); |
| 233 | struct nand_page_io_req adjreq = *req; | 217 | struct spi_mem_dirmap_desc *rdesc; |
| 234 | unsigned int nbytes = 0; | 218 | unsigned int nbytes = 0; |
| 235 | void *buf = NULL; | 219 | void *buf = NULL; |
| 236 | u16 column = 0; | 220 | u16 column = 0; |
| 237 | int ret; | 221 | ssize_t ret; |
| 238 | 222 | ||
| 239 | if (req->datalen) { | 223 | if (req->datalen) { |
| 240 | adjreq.datalen = nanddev_page_size(nand); | ||
| 241 | adjreq.dataoffs = 0; | ||
| 242 | adjreq.databuf.in = spinand->databuf; | ||
| 243 | buf = spinand->databuf; | 224 | buf = spinand->databuf; |
| 244 | nbytes = adjreq.datalen; | 225 | nbytes = nanddev_page_size(nand); |
| 226 | column = 0; | ||
| 245 | } | 227 | } |
| 246 | 228 | ||
| 247 | if (req->ooblen) { | 229 | if (req->ooblen) { |
| 248 | adjreq.ooblen = nanddev_per_page_oobsize(nand); | ||
| 249 | adjreq.ooboffs = 0; | ||
| 250 | adjreq.oobbuf.in = spinand->oobbuf; | ||
| 251 | nbytes += nanddev_per_page_oobsize(nand); | 230 | nbytes += nanddev_per_page_oobsize(nand); |
| 252 | if (!buf) { | 231 | if (!buf) { |
| 253 | buf = spinand->oobbuf; | 232 | buf = spinand->oobbuf; |
| @@ -255,28 +234,19 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, | |||
| 255 | } | 234 | } |
| 256 | } | 235 | } |
| 257 | 236 | ||
| 258 | spinand_cache_op_adjust_colum(spinand, &adjreq, &column); | 237 | rdesc = spinand->dirmaps[req->pos.plane].rdesc; |
| 259 | op.addr.val = column; | ||
| 260 | 238 | ||
| 261 | /* | ||
| 262 | * Some controllers are limited in term of max RX data size. In this | ||
| 263 | * case, just repeat the READ_CACHE operation after updating the | ||
| 264 | * column. | ||
| 265 | */ | ||
| 266 | while (nbytes) { | 239 | while (nbytes) { |
| 267 | op.data.buf.in = buf; | 240 | ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf); |
| 268 | op.data.nbytes = nbytes; | 241 | if (ret < 0) |
| 269 | ret = spi_mem_adjust_op_size(spinand->spimem, &op); | ||
| 270 | if (ret) | ||
| 271 | return ret; | 242 | return ret; |
| 272 | 243 | ||
| 273 | ret = spi_mem_exec_op(spinand->spimem, &op); | 244 | if (!ret || ret > nbytes) |
| 274 | if (ret) | 245 | return -EIO; |
| 275 | return ret; | ||
| 276 | 246 | ||
| 277 | buf += op.data.nbytes; | 247 | nbytes -= ret; |
| 278 | nbytes -= op.data.nbytes; | 248 | column += ret; |
| 279 | op.addr.val += op.data.nbytes; | 249 | buf += ret; |
| 280 | } | 250 | } |
| 281 | 251 | ||
| 282 | if (req->datalen) | 252 | if (req->datalen) |
| @@ -300,14 +270,12 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, | |||
| 300 | static int spinand_write_to_cache_op(struct spinand_device *spinand, | 270 | static int spinand_write_to_cache_op(struct spinand_device *spinand, |
| 301 | const struct nand_page_io_req *req) | 271 | const struct nand_page_io_req *req) |
| 302 | { | 272 | { |
| 303 | struct spi_mem_op op = *spinand->op_templates.write_cache; | ||
| 304 | struct nand_device *nand = spinand_to_nand(spinand); | 273 | struct nand_device *nand = spinand_to_nand(spinand); |
| 305 | struct mtd_info *mtd = nanddev_to_mtd(nand); | 274 | struct mtd_info *mtd = nanddev_to_mtd(nand); |
| 306 | struct nand_page_io_req adjreq = *req; | 275 | struct spi_mem_dirmap_desc *wdesc; |
| 276 | unsigned int nbytes, column = 0; | ||
| 307 | void *buf = spinand->databuf; | 277 | void *buf = spinand->databuf; |
| 308 | unsigned int nbytes; | 278 | ssize_t ret; |
| 309 | u16 column = 0; | ||
| 310 | int ret; | ||
| 311 | 279 | ||
| 312 | /* | 280 | /* |
| 313 | * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset | 281 | * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset |
| @@ -318,12 +286,6 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, | |||
| 318 | */ | 286 | */ |
| 319 | nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); | 287 | nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); |
| 320 | memset(spinand->databuf, 0xff, nbytes); | 288 | memset(spinand->databuf, 0xff, nbytes); |
| 321 | adjreq.dataoffs = 0; | ||
| 322 | adjreq.datalen = nanddev_page_size(nand); | ||
| 323 | adjreq.databuf.out = spinand->databuf; | ||
| 324 | adjreq.ooblen = nanddev_per_page_oobsize(nand); | ||
| 325 | adjreq.ooboffs = 0; | ||
| 326 | adjreq.oobbuf.out = spinand->oobbuf; | ||
| 327 | 289 | ||
| 328 | if (req->datalen) | 290 | if (req->datalen) |
| 329 | memcpy(spinand->databuf + req->dataoffs, req->databuf.out, | 291 | memcpy(spinand->databuf + req->dataoffs, req->databuf.out, |
| @@ -340,42 +302,19 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, | |||
| 340 | req->ooblen); | 302 | req->ooblen); |
| 341 | } | 303 | } |
| 342 | 304 | ||
| 343 | spinand_cache_op_adjust_colum(spinand, &adjreq, &column); | 305 | wdesc = spinand->dirmaps[req->pos.plane].wdesc; |
| 344 | 306 | ||
| 345 | op = *spinand->op_templates.write_cache; | ||
| 346 | op.addr.val = column; | ||
| 347 | |||
| 348 | /* | ||
| 349 | * Some controllers are limited in term of max TX data size. In this | ||
| 350 | * case, split the operation into one LOAD CACHE and one or more | ||
| 351 | * LOAD RANDOM CACHE. | ||
| 352 | */ | ||
| 353 | while (nbytes) { | 307 | while (nbytes) { |
| 354 | op.data.buf.out = buf; | 308 | ret = spi_mem_dirmap_write(wdesc, column, nbytes, buf); |
| 355 | op.data.nbytes = nbytes; | 309 | if (ret < 0) |
| 356 | |||
| 357 | ret = spi_mem_adjust_op_size(spinand->spimem, &op); | ||
| 358 | if (ret) | ||
| 359 | return ret; | ||
| 360 | |||
| 361 | ret = spi_mem_exec_op(spinand->spimem, &op); | ||
| 362 | if (ret) | ||
| 363 | return ret; | 310 | return ret; |
| 364 | 311 | ||
| 365 | buf += op.data.nbytes; | 312 | if (!ret || ret > nbytes) |
| 366 | nbytes -= op.data.nbytes; | 313 | return -EIO; |
| 367 | op.addr.val += op.data.nbytes; | ||
| 368 | 314 | ||
| 369 | /* | 315 | nbytes -= ret; |
| 370 | * We need to use the RANDOM LOAD CACHE operation if there's | 316 | column += ret; |
| 371 | * more than one iteration, because the LOAD operation might | 317 | buf += ret; |
| 372 | * reset the cache to 0xff. | ||
| 373 | */ | ||
| 374 | if (nbytes) { | ||
| 375 | column = op.addr.val; | ||
| 376 | op = *spinand->op_templates.update_cache; | ||
| 377 | op.addr.val = column; | ||
| 378 | } | ||
| 379 | } | 318 | } |
| 380 | 319 | ||
| 381 | return 0; | 320 | return 0; |
| @@ -755,6 +694,59 @@ static int spinand_mtd_block_isreserved(struct mtd_info *mtd, loff_t offs) | |||
| 755 | return ret; | 694 | return ret; |
| 756 | } | 695 | } |
| 757 | 696 | ||
| 697 | static int spinand_create_dirmap(struct spinand_device *spinand, | ||
| 698 | unsigned int plane) | ||
| 699 | { | ||
| 700 | struct nand_device *nand = spinand_to_nand(spinand); | ||
| 701 | struct spi_mem_dirmap_info info = { | ||
| 702 | .length = nanddev_page_size(nand) + | ||
| 703 | nanddev_per_page_oobsize(nand), | ||
| 704 | }; | ||
| 705 | struct spi_mem_dirmap_desc *desc; | ||
| 706 | |||
| 707 | /* The plane number is passed in MSB just above the column address */ | ||
| 708 | info.offset = plane << fls(nand->memorg.pagesize); | ||
| 709 | |||
| 710 | info.op_tmpl = *spinand->op_templates.update_cache; | ||
| 711 | desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, | ||
| 712 | spinand->spimem, &info); | ||
| 713 | if (IS_ERR(desc)) | ||
| 714 | return PTR_ERR(desc); | ||
| 715 | |||
| 716 | spinand->dirmaps[plane].wdesc = desc; | ||
| 717 | |||
| 718 | info.op_tmpl = *spinand->op_templates.read_cache; | ||
| 719 | desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, | ||
| 720 | spinand->spimem, &info); | ||
| 721 | if (IS_ERR(desc)) | ||
| 722 | return PTR_ERR(desc); | ||
| 723 | |||
| 724 | spinand->dirmaps[plane].rdesc = desc; | ||
| 725 | |||
| 726 | return 0; | ||
| 727 | } | ||
| 728 | |||
| 729 | static int spinand_create_dirmaps(struct spinand_device *spinand) | ||
| 730 | { | ||
| 731 | struct nand_device *nand = spinand_to_nand(spinand); | ||
| 732 | int i, ret; | ||
| 733 | |||
| 734 | spinand->dirmaps = devm_kzalloc(&spinand->spimem->spi->dev, | ||
| 735 | sizeof(*spinand->dirmaps) * | ||
| 736 | nand->memorg.planes_per_lun, | ||
| 737 | GFP_KERNEL); | ||
| 738 | if (!spinand->dirmaps) | ||
| 739 | return -ENOMEM; | ||
| 740 | |||
| 741 | for (i = 0; i < nand->memorg.planes_per_lun; i++) { | ||
| 742 | ret = spinand_create_dirmap(spinand, i); | ||
| 743 | if (ret) | ||
| 744 | return ret; | ||
| 745 | } | ||
| 746 | |||
| 747 | return 0; | ||
| 748 | } | ||
| 749 | |||
| 758 | static const struct nand_ops spinand_ops = { | 750 | static const struct nand_ops spinand_ops = { |
| 759 | .erase = spinand_erase, | 751 | .erase = spinand_erase, |
| 760 | .markbad = spinand_markbad, | 752 | .markbad = spinand_markbad, |
| @@ -1012,6 +1004,14 @@ static int spinand_init(struct spinand_device *spinand) | |||
| 1012 | goto err_free_bufs; | 1004 | goto err_free_bufs; |
| 1013 | } | 1005 | } |
| 1014 | 1006 | ||
| 1007 | ret = spinand_create_dirmaps(spinand); | ||
| 1008 | if (ret) { | ||
| 1009 | dev_err(dev, | ||
| 1010 | "Failed to create direct mappings for read/write operations (err = %d)\n", | ||
| 1011 | ret); | ||
| 1012 | goto err_manuf_cleanup; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | /* After power up, all blocks are locked, so unlock them here. */ | 1015 | /* After power up, all blocks are locked, so unlock them here. */ |
| 1016 | for (i = 0; i < nand->memorg.ntargets; i++) { | 1016 | for (i = 0; i < nand->memorg.ntargets; i++) { |
| 1017 | ret = spinand_select_target(spinand, i); | 1017 | ret = spinand_select_target(spinand, i); |
| @@ -1037,6 +1037,7 @@ static int spinand_init(struct spinand_device *spinand) | |||
| 1037 | mtd->_block_markbad = spinand_mtd_block_markbad; | 1037 | mtd->_block_markbad = spinand_mtd_block_markbad; |
| 1038 | mtd->_block_isreserved = spinand_mtd_block_isreserved; | 1038 | mtd->_block_isreserved = spinand_mtd_block_isreserved; |
| 1039 | mtd->_erase = spinand_mtd_erase; | 1039 | mtd->_erase = spinand_mtd_erase; |
| 1040 | mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks; | ||
| 1040 | 1041 | ||
| 1041 | if (spinand->eccinfo.ooblayout) | 1042 | if (spinand->eccinfo.ooblayout) |
| 1042 | mtd_set_ooblayout(mtd, spinand->eccinfo.ooblayout); | 1043 | mtd_set_ooblayout(mtd, spinand->eccinfo.ooblayout); |
diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c index 0b49d8264bef..e5586390026a 100644 --- a/drivers/mtd/nand/spi/gigadevice.c +++ b/drivers/mtd/nand/spi/gigadevice.c | |||
| @@ -162,7 +162,7 @@ static const struct mtd_ooblayout_ops gd5fxgq4uexxg_ooblayout = { | |||
| 162 | 162 | ||
| 163 | static const struct spinand_info gigadevice_spinand_table[] = { | 163 | static const struct spinand_info gigadevice_spinand_table[] = { |
| 164 | SPINAND_INFO("GD5F1GQ4xA", 0xF1, | 164 | SPINAND_INFO("GD5F1GQ4xA", 0xF1, |
| 165 | NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), | 165 | NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), |
| 166 | NAND_ECCREQ(8, 512), | 166 | NAND_ECCREQ(8, 512), |
| 167 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 167 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 168 | &write_cache_variants, | 168 | &write_cache_variants, |
| @@ -171,7 +171,7 @@ static const struct spinand_info gigadevice_spinand_table[] = { | |||
| 171 | SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, | 171 | SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, |
| 172 | gd5fxgq4xa_ecc_get_status)), | 172 | gd5fxgq4xa_ecc_get_status)), |
| 173 | SPINAND_INFO("GD5F2GQ4xA", 0xF2, | 173 | SPINAND_INFO("GD5F2GQ4xA", 0xF2, |
| 174 | NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), | 174 | NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), |
| 175 | NAND_ECCREQ(8, 512), | 175 | NAND_ECCREQ(8, 512), |
| 176 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 176 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 177 | &write_cache_variants, | 177 | &write_cache_variants, |
| @@ -180,7 +180,7 @@ static const struct spinand_info gigadevice_spinand_table[] = { | |||
| 180 | SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, | 180 | SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, |
| 181 | gd5fxgq4xa_ecc_get_status)), | 181 | gd5fxgq4xa_ecc_get_status)), |
| 182 | SPINAND_INFO("GD5F4GQ4xA", 0xF4, | 182 | SPINAND_INFO("GD5F4GQ4xA", 0xF4, |
| 183 | NAND_MEMORG(1, 2048, 64, 64, 4096, 1, 1, 1), | 183 | NAND_MEMORG(1, 2048, 64, 64, 4096, 40, 1, 1, 1), |
| 184 | NAND_ECCREQ(8, 512), | 184 | NAND_ECCREQ(8, 512), |
| 185 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 185 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 186 | &write_cache_variants, | 186 | &write_cache_variants, |
| @@ -189,7 +189,7 @@ static const struct spinand_info gigadevice_spinand_table[] = { | |||
| 189 | SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, | 189 | SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, |
| 190 | gd5fxgq4xa_ecc_get_status)), | 190 | gd5fxgq4xa_ecc_get_status)), |
| 191 | SPINAND_INFO("GD5F1GQ4UExxG", 0xd1, | 191 | SPINAND_INFO("GD5F1GQ4UExxG", 0xd1, |
| 192 | NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), | 192 | NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), |
| 193 | NAND_ECCREQ(8, 512), | 193 | NAND_ECCREQ(8, 512), |
| 194 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 194 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 195 | &write_cache_variants, | 195 | &write_cache_variants, |
diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index d16b57081c95..6502727049a8 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c | |||
| @@ -100,7 +100,7 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand, | |||
| 100 | 100 | ||
| 101 | static const struct spinand_info macronix_spinand_table[] = { | 101 | static const struct spinand_info macronix_spinand_table[] = { |
| 102 | SPINAND_INFO("MX35LF1GE4AB", 0x12, | 102 | SPINAND_INFO("MX35LF1GE4AB", 0x12, |
| 103 | NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), | 103 | NAND_MEMORG(1, 2048, 64, 64, 1024, 40, 1, 1, 1), |
| 104 | NAND_ECCREQ(4, 512), | 104 | NAND_ECCREQ(4, 512), |
| 105 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 105 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 106 | &write_cache_variants, | 106 | &write_cache_variants, |
| @@ -109,7 +109,7 @@ static const struct spinand_info macronix_spinand_table[] = { | |||
| 109 | SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, | 109 | SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, |
| 110 | mx35lf1ge4ab_ecc_get_status)), | 110 | mx35lf1ge4ab_ecc_get_status)), |
| 111 | SPINAND_INFO("MX35LF2GE4AB", 0x22, | 111 | SPINAND_INFO("MX35LF2GE4AB", 0x22, |
| 112 | NAND_MEMORG(1, 2048, 64, 64, 2048, 2, 1, 1), | 112 | NAND_MEMORG(1, 2048, 64, 64, 2048, 20, 2, 1, 1), |
| 113 | NAND_ECCREQ(4, 512), | 113 | NAND_ECCREQ(4, 512), |
| 114 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 114 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 115 | &write_cache_variants, | 115 | &write_cache_variants, |
diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c index 9c4381d6847b..7d7b1f7fcf71 100644 --- a/drivers/mtd/nand/spi/micron.c +++ b/drivers/mtd/nand/spi/micron.c | |||
| @@ -92,7 +92,7 @@ static int mt29f2g01abagd_ecc_get_status(struct spinand_device *spinand, | |||
| 92 | 92 | ||
| 93 | static const struct spinand_info micron_spinand_table[] = { | 93 | static const struct spinand_info micron_spinand_table[] = { |
| 94 | SPINAND_INFO("MT29F2G01ABAGD", 0x24, | 94 | SPINAND_INFO("MT29F2G01ABAGD", 0x24, |
| 95 | NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1), | 95 | NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), |
| 96 | NAND_ECCREQ(8, 512), | 96 | NAND_ECCREQ(8, 512), |
| 97 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 97 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 98 | &write_cache_variants, | 98 | &write_cache_variants, |
diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c index db8021da45b5..1cb3760ff779 100644 --- a/drivers/mtd/nand/spi/toshiba.c +++ b/drivers/mtd/nand/spi/toshiba.c | |||
| @@ -96,7 +96,7 @@ static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand, | |||
| 96 | static const struct spinand_info toshiba_spinand_table[] = { | 96 | static const struct spinand_info toshiba_spinand_table[] = { |
| 97 | /* 3.3V 1Gb */ | 97 | /* 3.3V 1Gb */ |
| 98 | SPINAND_INFO("TC58CVG0S3", 0xC2, | 98 | SPINAND_INFO("TC58CVG0S3", 0xC2, |
| 99 | NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), | 99 | NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), |
| 100 | NAND_ECCREQ(8, 512), | 100 | NAND_ECCREQ(8, 512), |
| 101 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 101 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 102 | &write_cache_variants, | 102 | &write_cache_variants, |
| @@ -106,7 +106,7 @@ static const struct spinand_info toshiba_spinand_table[] = { | |||
| 106 | tc58cxgxsx_ecc_get_status)), | 106 | tc58cxgxsx_ecc_get_status)), |
| 107 | /* 3.3V 2Gb */ | 107 | /* 3.3V 2Gb */ |
| 108 | SPINAND_INFO("TC58CVG1S3", 0xCB, | 108 | SPINAND_INFO("TC58CVG1S3", 0xCB, |
| 109 | NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), | 109 | NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), |
| 110 | NAND_ECCREQ(8, 512), | 110 | NAND_ECCREQ(8, 512), |
| 111 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 111 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 112 | &write_cache_variants, | 112 | &write_cache_variants, |
| @@ -116,7 +116,7 @@ static const struct spinand_info toshiba_spinand_table[] = { | |||
| 116 | tc58cxgxsx_ecc_get_status)), | 116 | tc58cxgxsx_ecc_get_status)), |
| 117 | /* 3.3V 4Gb */ | 117 | /* 3.3V 4Gb */ |
| 118 | SPINAND_INFO("TC58CVG2S0", 0xCD, | 118 | SPINAND_INFO("TC58CVG2S0", 0xCD, |
| 119 | NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), | 119 | NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), |
| 120 | NAND_ECCREQ(8, 512), | 120 | NAND_ECCREQ(8, 512), |
| 121 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 121 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 122 | &write_cache_variants, | 122 | &write_cache_variants, |
| @@ -126,7 +126,7 @@ static const struct spinand_info toshiba_spinand_table[] = { | |||
| 126 | tc58cxgxsx_ecc_get_status)), | 126 | tc58cxgxsx_ecc_get_status)), |
| 127 | /* 1.8V 1Gb */ | 127 | /* 1.8V 1Gb */ |
| 128 | SPINAND_INFO("TC58CYG0S3", 0xB2, | 128 | SPINAND_INFO("TC58CYG0S3", 0xB2, |
| 129 | NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), | 129 | NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), |
| 130 | NAND_ECCREQ(8, 512), | 130 | NAND_ECCREQ(8, 512), |
| 131 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 131 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 132 | &write_cache_variants, | 132 | &write_cache_variants, |
| @@ -136,7 +136,7 @@ static const struct spinand_info toshiba_spinand_table[] = { | |||
| 136 | tc58cxgxsx_ecc_get_status)), | 136 | tc58cxgxsx_ecc_get_status)), |
| 137 | /* 1.8V 2Gb */ | 137 | /* 1.8V 2Gb */ |
| 138 | SPINAND_INFO("TC58CYG1S3", 0xBB, | 138 | SPINAND_INFO("TC58CYG1S3", 0xBB, |
| 139 | NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), | 139 | NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), |
| 140 | NAND_ECCREQ(8, 512), | 140 | NAND_ECCREQ(8, 512), |
| 141 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 141 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 142 | &write_cache_variants, | 142 | &write_cache_variants, |
| @@ -146,7 +146,7 @@ static const struct spinand_info toshiba_spinand_table[] = { | |||
| 146 | tc58cxgxsx_ecc_get_status)), | 146 | tc58cxgxsx_ecc_get_status)), |
| 147 | /* 1.8V 4Gb */ | 147 | /* 1.8V 4Gb */ |
| 148 | SPINAND_INFO("TC58CYG2S0", 0xBD, | 148 | SPINAND_INFO("TC58CYG2S0", 0xBD, |
| 149 | NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), | 149 | NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), |
| 150 | NAND_ECCREQ(8, 512), | 150 | NAND_ECCREQ(8, 512), |
| 151 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 151 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 152 | &write_cache_variants, | 152 | &write_cache_variants, |
diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index 5d944580b898..a6c17e0cace8 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c | |||
| @@ -76,7 +76,7 @@ static int w25m02gv_select_target(struct spinand_device *spinand, | |||
| 76 | 76 | ||
| 77 | static const struct spinand_info winbond_spinand_table[] = { | 77 | static const struct spinand_info winbond_spinand_table[] = { |
| 78 | SPINAND_INFO("W25M02GV", 0xAB, | 78 | SPINAND_INFO("W25M02GV", 0xAB, |
| 79 | NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 2), | 79 | NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2), |
| 80 | NAND_ECCREQ(1, 512), | 80 | NAND_ECCREQ(1, 512), |
| 81 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 81 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 82 | &write_cache_variants, | 82 | &write_cache_variants, |
| @@ -85,7 +85,7 @@ static const struct spinand_info winbond_spinand_table[] = { | |||
| 85 | SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), | 85 | SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), |
| 86 | SPINAND_SELECT_TARGET(w25m02gv_select_target)), | 86 | SPINAND_SELECT_TARGET(w25m02gv_select_target)), |
| 87 | SPINAND_INFO("W25N01GV", 0xAA, | 87 | SPINAND_INFO("W25N01GV", 0xAA, |
| 88 | NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), | 88 | NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), |
| 89 | NAND_ECCREQ(1, 512), | 89 | NAND_ECCREQ(1, 512), |
| 90 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, | 90 | SPINAND_INFO_OP_VARIANTS(&read_cache_variants, |
| 91 | &write_cache_variants, | 91 | &write_cache_variants, |
diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index fccf1950e92d..bc201327dda0 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig | |||
| @@ -1,3 +1,30 @@ | |||
| 1 | config MTD_PARSER_IMAGETAG | ||
| 2 | tristate "Parser for BCM963XX Image Tag format partitions" | ||
| 3 | depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST | ||
| 4 | select CRC32 | ||
| 5 | help | ||
| 6 | Image Tag is the firmware header used by broadcom on their xDSL line | ||
| 7 | of devices. It is used to describe the offsets and lengths of kernel | ||
| 8 | and rootfs partitions. | ||
| 9 | This driver adds support for parsing a partition with an Image Tag | ||
| 10 | header and creates up to two partitions, kernel and rootfs. | ||
| 11 | |||
| 12 | config MTD_AFS_PARTS | ||
| 13 | tristate "ARM Firmware Suite partition parsing" | ||
| 14 | depends on (ARM || ARM64) | ||
| 15 | help | ||
| 16 | The ARM Firmware Suite allows the user to divide flash devices into | ||
| 17 | multiple 'images'. Each such image has a header containing its name | ||
| 18 | and offset/size etc. | ||
| 19 | |||
| 20 | If you need code which can detect and parse these tables, and | ||
| 21 | register MTD 'partitions' corresponding to each image detected, | ||
| 22 | enable this option. | ||
| 23 | |||
| 24 | You will still need the parsing functions to be called by the driver | ||
| 25 | for your particular device. It won't happen automatically. The | ||
| 26 | 'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example. | ||
| 27 | |||
| 1 | config MTD_PARSER_TRX | 28 | config MTD_PARSER_TRX |
| 2 | tristate "Parser for TRX format partitions" | 29 | tristate "Parser for TRX format partitions" |
| 3 | depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST) | 30 | depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST) |
diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile index d8418bf6804a..cddc8f35a856 100644 --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o | ||
| 2 | obj-$(CONFIG_MTD_AFS_PARTS) += afs.o | ||
| 1 | obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o | 3 | obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o |
| 2 | obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o | 4 | obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o |
| 3 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o | 5 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o |
diff --git a/drivers/mtd/parsers/afs.c b/drivers/mtd/parsers/afs.c new file mode 100644 index 000000000000..0c730024f806 --- /dev/null +++ b/drivers/mtd/parsers/afs.c | |||
| @@ -0,0 +1,410 @@ | |||
| 1 | /*====================================================================== | ||
| 2 | |||
| 3 | drivers/mtd/afs.c: ARM Flash Layout/Partitioning | ||
| 4 | |||
| 5 | Copyright © 2000 ARM Limited | ||
| 6 | Copyright (C) 2019 Linus Walleij | ||
| 7 | |||
| 8 | This program is free software; you can redistribute it and/or modify | ||
| 9 | it under the terms of the GNU General Public License as published by | ||
| 10 | the Free Software Foundation; either version 2 of the License, or | ||
| 11 | (at your option) any later version. | ||
| 12 | |||
| 13 | This program is distributed in the hope that it will be useful, | ||
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | GNU General Public License for more details. | ||
| 17 | |||
| 18 | You should have received a copy of the GNU General Public License | ||
| 19 | along with this program; if not, write to the Free Software | ||
| 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | |||
| 22 | This is access code for flashes using ARM's flash partitioning | ||
| 23 | standards. | ||
| 24 | |||
| 25 | ======================================================================*/ | ||
| 26 | |||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/types.h> | ||
| 29 | #include <linux/kernel.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/string.h> | ||
| 32 | #include <linux/init.h> | ||
| 33 | |||
| 34 | #include <linux/mtd/mtd.h> | ||
| 35 | #include <linux/mtd/map.h> | ||
| 36 | #include <linux/mtd/partitions.h> | ||
| 37 | |||
| 38 | #define AFSV1_FOOTER_MAGIC 0xA0FFFF9F | ||
| 39 | #define AFSV2_FOOTER_MAGIC1 0x464C5348 /* "FLSH" */ | ||
| 40 | #define AFSV2_FOOTER_MAGIC2 0x464F4F54 /* "FOOT" */ | ||
| 41 | |||
| 42 | struct footer_v1 { | ||
| 43 | u32 image_info_base; /* Address of first word of ImageFooter */ | ||
| 44 | u32 image_start; /* Start of area reserved by this footer */ | ||
| 45 | u32 signature; /* 'Magic' number proves it's a footer */ | ||
| 46 | u32 type; /* Area type: ARM Image, SIB, customer */ | ||
| 47 | u32 checksum; /* Just this structure */ | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct image_info_v1 { | ||
| 51 | u32 bootFlags; /* Boot flags, compression etc. */ | ||
| 52 | u32 imageNumber; /* Unique number, selects for boot etc. */ | ||
| 53 | u32 loadAddress; /* Address program should be loaded to */ | ||
| 54 | u32 length; /* Actual size of image */ | ||
| 55 | u32 address; /* Image is executed from here */ | ||
| 56 | char name[16]; /* Null terminated */ | ||
| 57 | u32 headerBase; /* Flash Address of any stripped header */ | ||
| 58 | u32 header_length; /* Length of header in memory */ | ||
| 59 | u32 headerType; /* AIF, RLF, s-record etc. */ | ||
| 60 | u32 checksum; /* Image checksum (inc. this struct) */ | ||
| 61 | }; | ||
| 62 | |||
| 63 | static u32 word_sum(void *words, int num) | ||
| 64 | { | ||
| 65 | u32 *p = words; | ||
| 66 | u32 sum = 0; | ||
| 67 | |||
| 68 | while (num--) | ||
| 69 | sum += *p++; | ||
| 70 | |||
| 71 | return sum; | ||
| 72 | } | ||
| 73 | |||
| 74 | static u32 word_sum_v2(u32 *p, u32 num) | ||
| 75 | { | ||
| 76 | u32 sum = 0; | ||
| 77 | int i; | ||
| 78 | |||
| 79 | for (i = 0; i < num; i++) { | ||
| 80 | u32 val; | ||
| 81 | |||
| 82 | val = p[i]; | ||
| 83 | if (val > ~sum) | ||
| 84 | sum++; | ||
| 85 | sum += val; | ||
| 86 | } | ||
| 87 | return ~sum; | ||
| 88 | } | ||
| 89 | |||
| 90 | static bool afs_is_v1(struct mtd_info *mtd, u_int off) | ||
| 91 | { | ||
| 92 | /* The magic is 12 bytes from the end of the erase block */ | ||
| 93 | u_int ptr = off + mtd->erasesize - 12; | ||
| 94 | u32 magic; | ||
| 95 | size_t sz; | ||
| 96 | int ret; | ||
| 97 | |||
| 98 | ret = mtd_read(mtd, ptr, 4, &sz, (u_char *)&magic); | ||
| 99 | if (ret < 0) { | ||
| 100 | printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", | ||
| 101 | ptr, ret); | ||
| 102 | return false; | ||
| 103 | } | ||
| 104 | if (ret >= 0 && sz != 4) | ||
| 105 | return false; | ||
| 106 | |||
| 107 | return (magic == AFSV1_FOOTER_MAGIC); | ||
| 108 | } | ||
| 109 | |||
| 110 | static bool afs_is_v2(struct mtd_info *mtd, u_int off) | ||
| 111 | { | ||
| 112 | /* The magic is the 8 last bytes of the erase block */ | ||
| 113 | u_int ptr = off + mtd->erasesize - 8; | ||
| 114 | u32 foot[2]; | ||
| 115 | size_t sz; | ||
| 116 | int ret; | ||
| 117 | |||
| 118 | ret = mtd_read(mtd, ptr, 8, &sz, (u_char *)foot); | ||
| 119 | if (ret < 0) { | ||
| 120 | printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", | ||
| 121 | ptr, ret); | ||
| 122 | return false; | ||
| 123 | } | ||
| 124 | if (ret >= 0 && sz != 8) | ||
| 125 | return false; | ||
| 126 | |||
| 127 | return (foot[0] == AFSV2_FOOTER_MAGIC1 && | ||
| 128 | foot[1] == AFSV2_FOOTER_MAGIC2); | ||
| 129 | } | ||
| 130 | |||
| 131 | static int afs_parse_v1_partition(struct mtd_info *mtd, | ||
| 132 | u_int off, struct mtd_partition *part) | ||
| 133 | { | ||
| 134 | struct footer_v1 fs; | ||
| 135 | struct image_info_v1 iis; | ||
| 136 | u_int mask; | ||
| 137 | /* | ||
| 138 | * Static checks cannot see that we bail out if we have an error | ||
| 139 | * reading the footer. | ||
| 140 | */ | ||
| 141 | u_int uninitialized_var(iis_ptr); | ||
| 142 | u_int uninitialized_var(img_ptr); | ||
| 143 | u_int ptr; | ||
| 144 | size_t sz; | ||
| 145 | int ret; | ||
| 146 | int i; | ||
| 147 | |||
| 148 | /* | ||
| 149 | * This is the address mask; we use this to mask off out of | ||
| 150 | * range address bits. | ||
| 151 | */ | ||
| 152 | mask = mtd->size - 1; | ||
| 153 | |||
| 154 | ptr = off + mtd->erasesize - sizeof(fs); | ||
| 155 | ret = mtd_read(mtd, ptr, sizeof(fs), &sz, (u_char *)&fs); | ||
| 156 | if (ret >= 0 && sz != sizeof(fs)) | ||
| 157 | ret = -EINVAL; | ||
| 158 | if (ret < 0) { | ||
| 159 | printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", | ||
| 160 | ptr, ret); | ||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | /* | ||
| 164 | * Check the checksum. | ||
| 165 | */ | ||
| 166 | if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff) | ||
| 167 | return -EINVAL; | ||
| 168 | |||
| 169 | /* | ||
| 170 | * Hide the SIB (System Information Block) | ||
| 171 | */ | ||
| 172 | if (fs.type == 2) | ||
| 173 | return 0; | ||
| 174 | |||
| 175 | iis_ptr = fs.image_info_base & mask; | ||
| 176 | img_ptr = fs.image_start & mask; | ||
| 177 | |||
| 178 | /* | ||
| 179 | * Check the image info base. This can not | ||
| 180 | * be located after the footer structure. | ||
| 181 | */ | ||
| 182 | if (iis_ptr >= ptr) | ||
| 183 | return 0; | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Check the start of this image. The image | ||
| 187 | * data can not be located after this block. | ||
| 188 | */ | ||
| 189 | if (img_ptr > off) | ||
| 190 | return 0; | ||
| 191 | |||
| 192 | /* Read the image info block */ | ||
| 193 | memset(&iis, 0, sizeof(iis)); | ||
| 194 | ret = mtd_read(mtd, iis_ptr, sizeof(iis), &sz, (u_char *)&iis); | ||
| 195 | if (ret < 0) { | ||
| 196 | printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", | ||
| 197 | iis_ptr, ret); | ||
| 198 | return -EINVAL; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (sz != sizeof(iis)) | ||
| 202 | return -EINVAL; | ||
| 203 | |||
| 204 | /* | ||
| 205 | * Validate the name - it must be NUL terminated. | ||
| 206 | */ | ||
| 207 | for (i = 0; i < sizeof(iis.name); i++) | ||
| 208 | if (iis.name[i] == '\0') | ||
| 209 | break; | ||
| 210 | if (i > sizeof(iis.name)) | ||
| 211 | return -EINVAL; | ||
| 212 | |||
| 213 | part->name = kstrdup(iis.name, GFP_KERNEL); | ||
| 214 | if (!part->name) | ||
| 215 | return -ENOMEM; | ||
| 216 | |||
| 217 | part->size = (iis.length + mtd->erasesize - 1) & ~(mtd->erasesize - 1); | ||
| 218 | part->offset = img_ptr; | ||
| 219 | part->mask_flags = 0; | ||
| 220 | |||
| 221 | printk(" mtd: at 0x%08x, %5lluKiB, %8u, %s\n", | ||
| 222 | img_ptr, part->size / 1024, | ||
| 223 | iis.imageNumber, part->name); | ||
| 224 | |||
| 225 | return 0; | ||
| 226 | } | ||
| 227 | |||
| 228 | static int afs_parse_v2_partition(struct mtd_info *mtd, | ||
| 229 | u_int off, struct mtd_partition *part) | ||
| 230 | { | ||
| 231 | u_int ptr; | ||
| 232 | u32 footer[12]; | ||
| 233 | u32 imginfo[36]; | ||
| 234 | char *name; | ||
| 235 | u32 version; | ||
| 236 | u32 entrypoint; | ||
| 237 | u32 attributes; | ||
| 238 | u32 region_count; | ||
| 239 | u32 block_start; | ||
| 240 | u32 block_end; | ||
| 241 | u32 crc; | ||
| 242 | size_t sz; | ||
| 243 | int ret; | ||
| 244 | int i; | ||
| 245 | int pad = 0; | ||
| 246 | |||
| 247 | pr_debug("Parsing v2 partition @%08x-%08x\n", | ||
| 248 | off, off + mtd->erasesize); | ||
| 249 | |||
| 250 | /* First read the footer */ | ||
| 251 | ptr = off + mtd->erasesize - sizeof(footer); | ||
| 252 | ret = mtd_read(mtd, ptr, sizeof(footer), &sz, (u_char *)footer); | ||
| 253 | if ((ret < 0) || (ret >= 0 && sz != sizeof(footer))) { | ||
| 254 | pr_err("AFS: mtd read failed at 0x%x: %d\n", | ||
| 255 | ptr, ret); | ||
| 256 | return -EIO; | ||
| 257 | } | ||
| 258 | name = (char *) &footer[0]; | ||
| 259 | version = footer[9]; | ||
| 260 | ptr = off + mtd->erasesize - sizeof(footer) - footer[8]; | ||
| 261 | |||
| 262 | pr_debug("found image \"%s\", version %08x, info @%08x\n", | ||
| 263 | name, version, ptr); | ||
| 264 | |||
| 265 | /* Then read the image information */ | ||
| 266 | ret = mtd_read(mtd, ptr, sizeof(imginfo), &sz, (u_char *)imginfo); | ||
| 267 | if ((ret < 0) || (ret >= 0 && sz != sizeof(imginfo))) { | ||
| 268 | pr_err("AFS: mtd read failed at 0x%x: %d\n", | ||
| 269 | ptr, ret); | ||
| 270 | return -EIO; | ||
| 271 | } | ||
| 272 | |||
| 273 | /* 32bit platforms have 4 bytes padding */ | ||
| 274 | crc = word_sum_v2(&imginfo[1], 34); | ||
| 275 | if (!crc) { | ||
| 276 | pr_debug("Padding 1 word (4 bytes)\n"); | ||
| 277 | pad = 1; | ||
| 278 | } else { | ||
| 279 | /* 64bit platforms have 8 bytes padding */ | ||
| 280 | crc = word_sum_v2(&imginfo[2], 34); | ||
| 281 | if (!crc) { | ||
| 282 | pr_debug("Padding 2 words (8 bytes)\n"); | ||
| 283 | pad = 2; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | if (crc) { | ||
| 287 | pr_err("AFS: bad checksum on v2 image info: %08x\n", crc); | ||
| 288 | return -EINVAL; | ||
| 289 | } | ||
| 290 | entrypoint = imginfo[pad]; | ||
| 291 | attributes = imginfo[pad+1]; | ||
| 292 | region_count = imginfo[pad+2]; | ||
| 293 | block_start = imginfo[20]; | ||
| 294 | block_end = imginfo[21]; | ||
| 295 | |||
| 296 | pr_debug("image entry=%08x, attr=%08x, regions=%08x, " | ||
| 297 | "bs=%08x, be=%08x\n", | ||
| 298 | entrypoint, attributes, region_count, | ||
| 299 | block_start, block_end); | ||
| 300 | |||
| 301 | for (i = 0; i < region_count; i++) { | ||
| 302 | u32 region_load_addr = imginfo[pad + 3 + i*4]; | ||
| 303 | u32 region_size = imginfo[pad + 4 + i*4]; | ||
| 304 | u32 region_offset = imginfo[pad + 5 + i*4]; | ||
| 305 | u32 region_start; | ||
| 306 | u32 region_end; | ||
| 307 | |||
| 308 | pr_debug(" region %d: address: %08x, size: %08x, " | ||
| 309 | "offset: %08x\n", | ||
| 310 | i, | ||
| 311 | region_load_addr, | ||
| 312 | region_size, | ||
| 313 | region_offset); | ||
| 314 | |||
| 315 | region_start = off + region_offset; | ||
| 316 | region_end = region_start + region_size; | ||
| 317 | /* Align partition to end of erase block */ | ||
| 318 | region_end += (mtd->erasesize - 1); | ||
| 319 | region_end &= ~(mtd->erasesize -1); | ||
| 320 | pr_debug(" partition start = %08x, partition end = %08x\n", | ||
| 321 | region_start, region_end); | ||
| 322 | |||
| 323 | /* Create one partition per region */ | ||
| 324 | part->name = kstrdup(name, GFP_KERNEL); | ||
| 325 | if (!part->name) | ||
| 326 | return -ENOMEM; | ||
| 327 | part->offset = region_start; | ||
| 328 | part->size = region_end - region_start; | ||
| 329 | part->mask_flags = 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | |||
| 335 | static int parse_afs_partitions(struct mtd_info *mtd, | ||
| 336 | const struct mtd_partition **pparts, | ||
| 337 | struct mtd_part_parser_data *data) | ||
| 338 | { | ||
| 339 | struct mtd_partition *parts; | ||
| 340 | u_int off, sz; | ||
| 341 | int ret = 0; | ||
| 342 | int i; | ||
| 343 | |||
| 344 | /* Count the partitions by looping over all erase blocks */ | ||
| 345 | for (i = off = sz = 0; off < mtd->size; off += mtd->erasesize) { | ||
| 346 | if (afs_is_v1(mtd, off)) { | ||
| 347 | sz += sizeof(struct mtd_partition); | ||
| 348 | i += 1; | ||
| 349 | } | ||
| 350 | if (afs_is_v2(mtd, off)) { | ||
| 351 | sz += sizeof(struct mtd_partition); | ||
| 352 | i += 1; | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | if (!i) | ||
| 357 | return 0; | ||
| 358 | |||
| 359 | parts = kzalloc(sz, GFP_KERNEL); | ||
| 360 | if (!parts) | ||
| 361 | return -ENOMEM; | ||
| 362 | |||
| 363 | /* | ||
| 364 | * Identify the partitions | ||
| 365 | */ | ||
| 366 | for (i = off = 0; off < mtd->size; off += mtd->erasesize) { | ||
| 367 | if (afs_is_v1(mtd, off)) { | ||
| 368 | ret = afs_parse_v1_partition(mtd, off, &parts[i]); | ||
| 369 | if (ret) | ||
| 370 | goto out_free_parts; | ||
| 371 | i++; | ||
| 372 | } | ||
| 373 | if (afs_is_v2(mtd, off)) { | ||
| 374 | ret = afs_parse_v2_partition(mtd, off, &parts[i]); | ||
| 375 | if (ret) | ||
| 376 | goto out_free_parts; | ||
| 377 | i++; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | *pparts = parts; | ||
| 382 | return i; | ||
| 383 | |||
| 384 | out_free_parts: | ||
| 385 | while (i >= 0) { | ||
| 386 | if (parts[i].name) | ||
| 387 | kfree(parts[i].name); | ||
| 388 | i--; | ||
| 389 | } | ||
| 390 | kfree(parts); | ||
| 391 | *pparts = NULL; | ||
| 392 | return ret; | ||
| 393 | } | ||
| 394 | |||
| 395 | static const struct of_device_id mtd_parser_afs_of_match_table[] = { | ||
| 396 | { .compatible = "arm,arm-firmware-suite" }, | ||
| 397 | {}, | ||
| 398 | }; | ||
| 399 | MODULE_DEVICE_TABLE(of, mtd_parser_afs_of_match_table); | ||
| 400 | |||
| 401 | static struct mtd_part_parser afs_parser = { | ||
| 402 | .parse_fn = parse_afs_partitions, | ||
| 403 | .name = "afs", | ||
| 404 | .of_match_table = mtd_parser_afs_of_match_table, | ||
| 405 | }; | ||
| 406 | module_mtd_part_parser(afs_parser); | ||
| 407 | |||
| 408 | MODULE_AUTHOR("ARM Ltd"); | ||
| 409 | MODULE_DESCRIPTION("ARM Firmware Suite partition parser"); | ||
| 410 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/parsers/parser_imagetag.c b/drivers/mtd/parsers/parser_imagetag.c new file mode 100644 index 000000000000..9537c183a3be --- /dev/null +++ b/drivers/mtd/parsers/parser_imagetag.c | |||
| @@ -0,0 +1,222 @@ | |||
| 1 | /* | ||
| 2 | * BCM63XX CFE image tag parser | ||
| 3 | * | ||
| 4 | * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org> | ||
| 5 | * Mike Albon <malbon@openwrt.org> | ||
| 6 | * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net> | ||
| 7 | * Copyright © 2011-2013 Jonas Gorski <jonas.gorski@gmail.com> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 17 | |||
| 18 | #include <linux/bcm963xx_tag.h> | ||
| 19 | #include <linux/crc32.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/sizes.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/vmalloc.h> | ||
| 25 | #include <linux/mtd/mtd.h> | ||
| 26 | #include <linux/mtd/partitions.h> | ||
| 27 | #include <linux/of.h> | ||
| 28 | |||
| 29 | /* Ensure strings read from flash structs are null terminated */ | ||
| 30 | #define STR_NULL_TERMINATE(x) \ | ||
| 31 | do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0) | ||
| 32 | |||
| 33 | static int bcm963xx_read_imagetag(struct mtd_info *master, const char *name, | ||
| 34 | loff_t tag_offset, struct bcm_tag *buf) | ||
| 35 | { | ||
| 36 | int ret; | ||
| 37 | size_t retlen; | ||
| 38 | u32 computed_crc; | ||
| 39 | |||
| 40 | ret = mtd_read(master, tag_offset, sizeof(*buf), &retlen, (void *)buf); | ||
| 41 | if (ret) | ||
| 42 | return ret; | ||
| 43 | |||
| 44 | if (retlen != sizeof(*buf)) | ||
| 45 | return -EIO; | ||
| 46 | |||
| 47 | computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf, | ||
| 48 | offsetof(struct bcm_tag, header_crc)); | ||
| 49 | if (computed_crc == buf->header_crc) { | ||
| 50 | STR_NULL_TERMINATE(buf->board_id); | ||
| 51 | STR_NULL_TERMINATE(buf->tag_version); | ||
| 52 | |||
| 53 | pr_info("%s: CFE image tag found at 0x%llx with version %s, board type %s\n", | ||
| 54 | name, tag_offset, buf->tag_version, buf->board_id); | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | pr_warn("%s: CFE image tag at 0x%llx CRC invalid (expected %08x, actual %08x)\n", | ||
| 60 | name, tag_offset, buf->header_crc, computed_crc); | ||
| 61 | return -EINVAL; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int bcm963xx_parse_imagetag_partitions(struct mtd_info *master, | ||
| 65 | const struct mtd_partition **pparts, | ||
| 66 | struct mtd_part_parser_data *data) | ||
| 67 | { | ||
| 68 | /* CFE, NVRAM and global Linux are always present */ | ||
| 69 | int nrparts = 0, curpart = 0; | ||
| 70 | struct bcm_tag *buf = NULL; | ||
| 71 | struct mtd_partition *parts; | ||
| 72 | int ret; | ||
| 73 | unsigned int rootfsaddr, kerneladdr, spareaddr, offset; | ||
| 74 | unsigned int rootfslen, kernellen, sparelen, totallen; | ||
| 75 | int i; | ||
| 76 | bool rootfs_first = false; | ||
| 77 | |||
| 78 | buf = vmalloc(sizeof(struct bcm_tag)); | ||
| 79 | if (!buf) | ||
| 80 | return -ENOMEM; | ||
| 81 | |||
| 82 | /* Get the tag */ | ||
| 83 | ret = bcm963xx_read_imagetag(master, "rootfs", 0, buf); | ||
| 84 | if (!ret) { | ||
| 85 | STR_NULL_TERMINATE(buf->flash_image_start); | ||
| 86 | if (kstrtouint(buf->flash_image_start, 10, &rootfsaddr) || | ||
| 87 | rootfsaddr < BCM963XX_EXTENDED_SIZE) { | ||
| 88 | pr_err("invalid rootfs address: %*ph\n", | ||
| 89 | (int)sizeof(buf->flash_image_start), | ||
| 90 | buf->flash_image_start); | ||
| 91 | goto out; | ||
| 92 | } | ||
| 93 | |||
| 94 | STR_NULL_TERMINATE(buf->kernel_address); | ||
| 95 | if (kstrtouint(buf->kernel_address, 10, &kerneladdr) || | ||
| 96 | kerneladdr < BCM963XX_EXTENDED_SIZE) { | ||
| 97 | pr_err("invalid kernel address: %*ph\n", | ||
| 98 | (int)sizeof(buf->kernel_address), | ||
| 99 | buf->kernel_address); | ||
| 100 | goto out; | ||
| 101 | } | ||
| 102 | |||
| 103 | STR_NULL_TERMINATE(buf->kernel_length); | ||
| 104 | if (kstrtouint(buf->kernel_length, 10, &kernellen)) { | ||
| 105 | pr_err("invalid kernel length: %*ph\n", | ||
| 106 | (int)sizeof(buf->kernel_length), | ||
| 107 | buf->kernel_length); | ||
| 108 | goto out; | ||
| 109 | } | ||
| 110 | |||
| 111 | STR_NULL_TERMINATE(buf->total_length); | ||
| 112 | if (kstrtouint(buf->total_length, 10, &totallen)) { | ||
| 113 | pr_err("invalid total length: %*ph\n", | ||
| 114 | (int)sizeof(buf->total_length), | ||
| 115 | buf->total_length); | ||
| 116 | goto out; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Addresses are flash absolute, so convert to partition | ||
| 121 | * relative addresses. Assume either kernel or rootfs will | ||
| 122 | * directly follow the image tag. | ||
| 123 | */ | ||
| 124 | if (rootfsaddr < kerneladdr) | ||
| 125 | offset = rootfsaddr - sizeof(struct bcm_tag); | ||
| 126 | else | ||
| 127 | offset = kerneladdr - sizeof(struct bcm_tag); | ||
| 128 | |||
| 129 | kerneladdr = kerneladdr - offset; | ||
| 130 | rootfsaddr = rootfsaddr - offset; | ||
| 131 | spareaddr = roundup(totallen, master->erasesize); | ||
| 132 | |||
| 133 | if (rootfsaddr < kerneladdr) { | ||
| 134 | /* default Broadcom layout */ | ||
| 135 | rootfslen = kerneladdr - rootfsaddr; | ||
| 136 | rootfs_first = true; | ||
| 137 | } else { | ||
| 138 | /* OpenWrt layout */ | ||
| 139 | rootfsaddr = kerneladdr + kernellen; | ||
| 140 | rootfslen = spareaddr - rootfsaddr; | ||
| 141 | } | ||
| 142 | } else { | ||
| 143 | goto out; | ||
| 144 | } | ||
| 145 | sparelen = master->size - spareaddr; | ||
| 146 | |||
| 147 | /* Determine number of partitions */ | ||
| 148 | if (rootfslen > 0) | ||
| 149 | nrparts++; | ||
| 150 | |||
| 151 | if (kernellen > 0) | ||
| 152 | nrparts++; | ||
| 153 | |||
| 154 | parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); | ||
| 155 | if (!parts) { | ||
| 156 | ret = -ENOMEM; | ||
| 157 | goto out; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* Start building partition list */ | ||
| 161 | if (kernellen > 0) { | ||
| 162 | int kernelpart = curpart; | ||
| 163 | |||
| 164 | if (rootfslen > 0 && rootfs_first) | ||
| 165 | kernelpart++; | ||
| 166 | parts[kernelpart].name = "kernel"; | ||
| 167 | parts[kernelpart].offset = kerneladdr; | ||
| 168 | parts[kernelpart].size = kernellen; | ||
| 169 | curpart++; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (rootfslen > 0) { | ||
| 173 | int rootfspart = curpart; | ||
| 174 | |||
| 175 | if (kernellen > 0 && rootfs_first) | ||
| 176 | rootfspart--; | ||
| 177 | parts[rootfspart].name = "rootfs"; | ||
| 178 | parts[rootfspart].offset = rootfsaddr; | ||
| 179 | parts[rootfspart].size = rootfslen; | ||
| 180 | if (sparelen > 0 && !rootfs_first) | ||
| 181 | parts[rootfspart].size += sparelen; | ||
| 182 | curpart++; | ||
| 183 | } | ||
| 184 | |||
| 185 | for (i = 0; i < nrparts; i++) | ||
| 186 | pr_info("Partition %d is %s offset %llx and length %llx\n", i, | ||
| 187 | parts[i].name, parts[i].offset, parts[i].size); | ||
| 188 | |||
| 189 | pr_info("Spare partition is offset %x and length %x\n", spareaddr, | ||
| 190 | sparelen); | ||
| 191 | |||
| 192 | *pparts = parts; | ||
| 193 | ret = 0; | ||
| 194 | |||
| 195 | out: | ||
| 196 | vfree(buf); | ||
| 197 | |||
| 198 | if (ret) | ||
| 199 | return ret; | ||
| 200 | |||
| 201 | return nrparts; | ||
| 202 | } | ||
| 203 | |||
| 204 | static const struct of_device_id parse_bcm963xx_imagetag_match_table[] = { | ||
| 205 | { .compatible = "brcm,bcm963xx-imagetag" }, | ||
| 206 | {}, | ||
| 207 | }; | ||
| 208 | MODULE_DEVICE_TABLE(of, parse_bcm963xx_imagetag_match_table); | ||
| 209 | |||
| 210 | static struct mtd_part_parser bcm963xx_imagetag_parser = { | ||
| 211 | .parse_fn = bcm963xx_parse_imagetag_partitions, | ||
| 212 | .name = "bcm963xx-imagetag", | ||
| 213 | .of_match_table = parse_bcm963xx_imagetag_match_table, | ||
| 214 | }; | ||
| 215 | module_mtd_part_parser(bcm963xx_imagetag_parser); | ||
| 216 | |||
| 217 | MODULE_LICENSE("GPL"); | ||
| 218 | MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>"); | ||
| 219 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | ||
| 220 | MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>"); | ||
| 221 | MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com>"); | ||
| 222 | MODULE_DESCRIPTION("MTD parser for BCM963XX CFE Image Tag partitions"); | ||
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 89227b1d036a..e0955a98a0f4 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c | |||
| @@ -222,17 +222,17 @@ static int sm_correct_sector(uint8_t *buffer, struct sm_oob *oob) | |||
| 222 | uint8_t ecc[3]; | 222 | uint8_t ecc[3]; |
| 223 | 223 | ||
| 224 | __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc, | 224 | __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc, |
| 225 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 225 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 226 | if (__nand_correct_data(buffer, ecc, oob->ecc1, SM_SMALL_PAGE, | 226 | if (__nand_correct_data(buffer, ecc, oob->ecc1, SM_SMALL_PAGE, |
| 227 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)) < 0) | 227 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)) < 0) |
| 228 | return -EIO; | 228 | return -EIO; |
| 229 | 229 | ||
| 230 | buffer += SM_SMALL_PAGE; | 230 | buffer += SM_SMALL_PAGE; |
| 231 | 231 | ||
| 232 | __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc, | 232 | __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc, |
| 233 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 233 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 234 | if (__nand_correct_data(buffer, ecc, oob->ecc2, SM_SMALL_PAGE, | 234 | if (__nand_correct_data(buffer, ecc, oob->ecc2, SM_SMALL_PAGE, |
| 235 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)) < 0) | 235 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)) < 0) |
| 236 | return -EIO; | 236 | return -EIO; |
| 237 | return 0; | 237 | return 0; |
| 238 | } | 238 | } |
| @@ -399,11 +399,11 @@ restart: | |||
| 399 | if (ftl->smallpagenand) { | 399 | if (ftl->smallpagenand) { |
| 400 | __nand_calculate_ecc(buf + boffset, SM_SMALL_PAGE, | 400 | __nand_calculate_ecc(buf + boffset, SM_SMALL_PAGE, |
| 401 | oob.ecc1, | 401 | oob.ecc1, |
| 402 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 402 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 403 | 403 | ||
| 404 | __nand_calculate_ecc(buf + boffset + SM_SMALL_PAGE, | 404 | __nand_calculate_ecc(buf + boffset + SM_SMALL_PAGE, |
| 405 | SM_SMALL_PAGE, oob.ecc2, | 405 | SM_SMALL_PAGE, oob.ecc2, |
| 406 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 406 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 407 | } | 407 | } |
| 408 | if (!sm_write_sector(ftl, zone, block, boffset, | 408 | if (!sm_write_sector(ftl, zone, block, boffset, |
| 409 | buf + boffset, &oob)) | 409 | buf + boffset, &oob)) |
diff --git a/drivers/mtd/spi-nor/intel-spi-pci.c b/drivers/mtd/spi-nor/intel-spi-pci.c index 872b40922608..bfbfc17ed6aa 100644 --- a/drivers/mtd/spi-nor/intel-spi-pci.c +++ b/drivers/mtd/spi-nor/intel-spi-pci.c | |||
| @@ -63,6 +63,7 @@ static void intel_spi_pci_remove(struct pci_dev *pdev) | |||
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static const struct pci_device_id intel_spi_pci_ids[] = { | 65 | static const struct pci_device_id intel_spi_pci_ids[] = { |
| 66 | { PCI_VDEVICE(INTEL, 0x02a4), (unsigned long)&bxt_info }, | ||
| 66 | { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info }, | 67 | { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info }, |
| 67 | { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, | 68 | { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, |
| 68 | { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, | 69 | { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, |
diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index af0a22019516..d60cbf23d9aa 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c | |||
| @@ -632,6 +632,10 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, | |||
| 632 | while (len > 0) { | 632 | while (len > 0) { |
| 633 | block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); | 633 | block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); |
| 634 | 634 | ||
| 635 | /* Read cannot cross 4K boundary */ | ||
| 636 | block_size = min_t(loff_t, from + block_size, | ||
| 637 | round_up(from + 1, SZ_4K)) - from; | ||
| 638 | |||
| 635 | writel(from, ispi->base + FADDR); | 639 | writel(from, ispi->base + FADDR); |
| 636 | 640 | ||
| 637 | val = readl(ispi->base + HSFSTS_CTL); | 641 | val = readl(ispi->base + HSFSTS_CTL); |
| @@ -685,6 +689,10 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, | |||
| 685 | while (len > 0) { | 689 | while (len > 0) { |
| 686 | block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); | 690 | block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); |
| 687 | 691 | ||
| 692 | /* Write cannot cross 4K boundary */ | ||
| 693 | block_size = min_t(loff_t, to + block_size, | ||
| 694 | round_up(to + 1, SZ_4K)) - to; | ||
| 695 | |||
| 688 | writel(to, ispi->base + FADDR); | 696 | writel(to, ispi->base + FADDR); |
| 689 | 697 | ||
| 690 | val = readl(ispi->base + HSFSTS_CTL); | 698 | val = readl(ispi->base + HSFSTS_CTL); |
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index fae147452aff..73172d7f512b 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
| @@ -744,7 +744,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, | |||
| 744 | u8 erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; | 744 | u8 erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; |
| 745 | 745 | ||
| 746 | /* | 746 | /* |
| 747 | * Erase types are ordered by size, with the biggest erase type at | 747 | * Erase types are ordered by size, with the smallest erase type at |
| 748 | * index 0. | 748 | * index 0. |
| 749 | */ | 749 | */ |
| 750 | for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { | 750 | for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { |
| @@ -1905,7 +1905,9 @@ static const struct flash_info spi_nor_ids[] = { | |||
| 1905 | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1905 | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1906 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) }, | 1906 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) }, |
| 1907 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1907 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1908 | { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1908 | { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256, |
| 1909 | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | | ||
| 1910 | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) }, | ||
| 1909 | { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, | 1911 | { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, |
| 1910 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, | 1912 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, |
| 1911 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 1913 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
| @@ -2071,8 +2073,8 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) | |||
| 2071 | return &spi_nor_ids[tmp]; | 2073 | return &spi_nor_ids[tmp]; |
| 2072 | } | 2074 | } |
| 2073 | } | 2075 | } |
| 2074 | dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", | 2076 | dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n", |
| 2075 | id[0], id[1], id[2]); | 2077 | SPI_NOR_MAX_ID_LEN, id); |
| 2076 | return ERR_PTR(-ENODEV); | 2078 | return ERR_PTR(-ENODEV); |
| 2077 | } | 2079 | } |
| 2078 | 2080 | ||
diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c index c71523e94580..73b06304c975 100644 --- a/drivers/mtd/tests/mtd_nandecctest.c +++ b/drivers/mtd/tests/mtd_nandecctest.c | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | * or detected. | 21 | * or detected. |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #if IS_ENABLED(CONFIG_MTD_NAND) | 24 | #if IS_ENABLED(CONFIG_MTD_RAW_NAND) |
| 25 | 25 | ||
| 26 | struct nand_ecc_test { | 26 | struct nand_ecc_test { |
| 27 | const char *name; | 27 | const char *name; |
| @@ -122,9 +122,9 @@ static int no_bit_error_verify(void *error_data, void *error_ecc, | |||
| 122 | int ret; | 122 | int ret; |
| 123 | 123 | ||
| 124 | __nand_calculate_ecc(error_data, size, calc_ecc, | 124 | __nand_calculate_ecc(error_data, size, calc_ecc, |
| 125 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 125 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 126 | ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, | 126 | ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, |
| 127 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 127 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 128 | if (ret == 0 && !memcmp(correct_data, error_data, size)) | 128 | if (ret == 0 && !memcmp(correct_data, error_data, size)) |
| 129 | return 0; | 129 | return 0; |
| 130 | 130 | ||
| @@ -152,9 +152,9 @@ static int single_bit_error_correct(void *error_data, void *error_ecc, | |||
| 152 | int ret; | 152 | int ret; |
| 153 | 153 | ||
| 154 | __nand_calculate_ecc(error_data, size, calc_ecc, | 154 | __nand_calculate_ecc(error_data, size, calc_ecc, |
| 155 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 155 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 156 | ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, | 156 | ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, |
| 157 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 157 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 158 | if (ret == 1 && !memcmp(correct_data, error_data, size)) | 158 | if (ret == 1 && !memcmp(correct_data, error_data, size)) |
| 159 | return 0; | 159 | return 0; |
| 160 | 160 | ||
| @@ -189,9 +189,9 @@ static int double_bit_error_detect(void *error_data, void *error_ecc, | |||
| 189 | int ret; | 189 | int ret; |
| 190 | 190 | ||
| 191 | __nand_calculate_ecc(error_data, size, calc_ecc, | 191 | __nand_calculate_ecc(error_data, size, calc_ecc, |
| 192 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 192 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 193 | ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, | 193 | ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, |
| 194 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 194 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 195 | 195 | ||
| 196 | return (ret == -EBADMSG) ? 0 : -EINVAL; | 196 | return (ret == -EBADMSG) ? 0 : -EINVAL; |
| 197 | } | 197 | } |
| @@ -266,7 +266,7 @@ static int nand_ecc_test_run(const size_t size) | |||
| 266 | 266 | ||
| 267 | prandom_bytes(correct_data, size); | 267 | prandom_bytes(correct_data, size); |
| 268 | __nand_calculate_ecc(correct_data, size, correct_ecc, | 268 | __nand_calculate_ecc(correct_data, size, correct_ecc, |
| 269 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); | 269 | IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)); |
| 270 | 270 | ||
| 271 | for (i = 0; i < ARRAY_SIZE(nand_ecc_test); i++) { | 271 | for (i = 0; i < ARRAY_SIZE(nand_ecc_test); i++) { |
| 272 | nand_ecc_test[i].prepare(error_data, error_ecc, | 272 | nand_ecc_test[i].prepare(error_data, error_ecc, |
