diff options
71 files changed, 3412 insertions, 1159 deletions
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index 60acf9e708ae..7458fc6df5c6 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c | |||
@@ -66,7 +66,7 @@ static DEFINE_SPINLOCK(syscon_resetreg_lock); | |||
66 | * AMBA bus | 66 | * AMBA bus |
67 | * | | 67 | * | |
68 | * +- CPU | 68 | * +- CPU |
69 | * +- NANDIF NAND Flash interface | 69 | * +- FSMC NANDIF NAND Flash interface |
70 | * +- SEMI Shared Memory interface | 70 | * +- SEMI Shared Memory interface |
71 | * +- ISP Image Signal Processor (U335 only) | 71 | * +- ISP Image Signal Processor (U335 only) |
72 | * +- CDS (U335 only) | 72 | * +- CDS (U335 only) |
@@ -726,7 +726,7 @@ static struct clk cpu_clk = { | |||
726 | }; | 726 | }; |
727 | 727 | ||
728 | static struct clk nandif_clk = { | 728 | static struct clk nandif_clk = { |
729 | .name = "NANDIF", | 729 | .name = "FSMC", |
730 | .parent = &amba_clk, | 730 | .parent = &amba_clk, |
731 | .hw_ctrld = false, | 731 | .hw_ctrld = false, |
732 | .reset = true, | 732 | .reset = true, |
@@ -1259,7 +1259,7 @@ static struct clk_lookup lookups[] = { | |||
1259 | /* Connected directly to the AMBA bus */ | 1259 | /* Connected directly to the AMBA bus */ |
1260 | DEF_LOOKUP("amba", &amba_clk), | 1260 | DEF_LOOKUP("amba", &amba_clk), |
1261 | DEF_LOOKUP("cpu", &cpu_clk), | 1261 | DEF_LOOKUP("cpu", &cpu_clk), |
1262 | DEF_LOOKUP("fsmc", &nandif_clk), | 1262 | DEF_LOOKUP("fsmc-nand", &nandif_clk), |
1263 | DEF_LOOKUP("semi", &semi_clk), | 1263 | DEF_LOOKUP("semi", &semi_clk), |
1264 | #ifdef CONFIG_MACH_U300_BS335 | 1264 | #ifdef CONFIG_MACH_U300_BS335 |
1265 | DEF_LOOKUP("isp", &isp_clk), | 1265 | DEF_LOOKUP("isp", &isp_clk), |
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index ea41c236be0f..aa53ee22438f 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c | |||
@@ -21,7 +21,8 @@ | |||
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <mach/coh901318.h> | 24 | #include <linux/mtd/nand.h> |
25 | #include <linux/mtd/fsmc.h> | ||
25 | 26 | ||
26 | #include <asm/types.h> | 27 | #include <asm/types.h> |
27 | #include <asm/setup.h> | 28 | #include <asm/setup.h> |
@@ -30,6 +31,7 @@ | |||
30 | #include <asm/mach/map.h> | 31 | #include <asm/mach/map.h> |
31 | #include <asm/mach/irq.h> | 32 | #include <asm/mach/irq.h> |
32 | 33 | ||
34 | #include <mach/coh901318.h> | ||
33 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
34 | #include <mach/syscon.h> | 36 | #include <mach/syscon.h> |
35 | #include <mach/dma_channels.h> | 37 | #include <mach/dma_channels.h> |
@@ -285,6 +287,13 @@ static struct resource rtc_resources[] = { | |||
285 | */ | 287 | */ |
286 | static struct resource fsmc_resources[] = { | 288 | static struct resource fsmc_resources[] = { |
287 | { | 289 | { |
290 | .name = "nand_data", | ||
291 | .start = U300_NAND_CS0_PHYS_BASE, | ||
292 | .end = U300_NAND_CS0_PHYS_BASE + SZ_16K - 1, | ||
293 | .flags = IORESOURCE_MEM, | ||
294 | }, | ||
295 | { | ||
296 | .name = "fsmc_regs", | ||
288 | .start = U300_NAND_IF_PHYS_BASE, | 297 | .start = U300_NAND_IF_PHYS_BASE, |
289 | .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1, | 298 | .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1, |
290 | .flags = IORESOURCE_MEM, | 299 | .flags = IORESOURCE_MEM, |
@@ -1429,11 +1438,39 @@ static struct platform_device rtc_device = { | |||
1429 | .resource = rtc_resources, | 1438 | .resource = rtc_resources, |
1430 | }; | 1439 | }; |
1431 | 1440 | ||
1432 | static struct platform_device fsmc_device = { | 1441 | static struct mtd_partition u300_partitions[] = { |
1433 | .name = "nandif", | 1442 | { |
1443 | .name = "bootrecords", | ||
1444 | .offset = 0, | ||
1445 | .size = SZ_128K, | ||
1446 | }, | ||
1447 | { | ||
1448 | .name = "free", | ||
1449 | .offset = SZ_128K, | ||
1450 | .size = 8064 * SZ_1K, | ||
1451 | }, | ||
1452 | { | ||
1453 | .name = "platform", | ||
1454 | .offset = 8192 * SZ_1K, | ||
1455 | .size = 253952 * SZ_1K, | ||
1456 | }, | ||
1457 | }; | ||
1458 | |||
1459 | static struct fsmc_nand_platform_data nand_platform_data = { | ||
1460 | .partitions = u300_partitions, | ||
1461 | .nr_partitions = ARRAY_SIZE(u300_partitions), | ||
1462 | .options = NAND_SKIP_BBTSCAN, | ||
1463 | .width = FSMC_NAND_BW8, | ||
1464 | }; | ||
1465 | |||
1466 | static struct platform_device nand_device = { | ||
1467 | .name = "fsmc-nand", | ||
1434 | .id = -1, | 1468 | .id = -1, |
1435 | .num_resources = ARRAY_SIZE(fsmc_resources), | ||
1436 | .resource = fsmc_resources, | 1469 | .resource = fsmc_resources, |
1470 | .num_resources = ARRAY_SIZE(fsmc_resources), | ||
1471 | .dev = { | ||
1472 | .platform_data = &nand_platform_data, | ||
1473 | }, | ||
1437 | }; | 1474 | }; |
1438 | 1475 | ||
1439 | static struct platform_device ave_device = { | 1476 | static struct platform_device ave_device = { |
@@ -1465,7 +1502,7 @@ static struct platform_device *platform_devs[] __initdata = { | |||
1465 | &keypad_device, | 1502 | &keypad_device, |
1466 | &rtc_device, | 1503 | &rtc_device, |
1467 | &gpio_device, | 1504 | &gpio_device, |
1468 | &fsmc_device, | 1505 | &nand_device, |
1469 | &wdog_device, | 1506 | &wdog_device, |
1470 | &ave_device | 1507 | &ave_device |
1471 | }; | 1508 | }; |
diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h index 56721a0cd2af..8b85df4c8d8f 100644 --- a/arch/arm/mach-u300/include/mach/u300-regs.h +++ b/arch/arm/mach-u300/include/mach/u300-regs.h | |||
@@ -20,11 +20,9 @@ | |||
20 | 20 | ||
21 | /* NAND Flash CS0 */ | 21 | /* NAND Flash CS0 */ |
22 | #define U300_NAND_CS0_PHYS_BASE 0x80000000 | 22 | #define U300_NAND_CS0_PHYS_BASE 0x80000000 |
23 | #define U300_NAND_CS0_VIRT_BASE 0xff040000 | ||
24 | 23 | ||
25 | /* NFIF */ | 24 | /* NFIF */ |
26 | #define U300_NAND_IF_PHYS_BASE 0x9f800000 | 25 | #define U300_NAND_IF_PHYS_BASE 0x9f800000 |
27 | #define U300_NAND_IF_VIRT_BASE 0xff030000 | ||
28 | 26 | ||
29 | /* AHB Peripherals */ | 27 | /* AHB Peripherals */ |
30 | #define U300_AHB_PER_PHYS_BASE 0xa0000000 | 28 | #define U300_AHB_PER_PHYS_BASE 0xa0000000 |
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h index 3478eae32d8a..01a8448e471c 100644 --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | |||
@@ -30,15 +30,15 @@ struct pxa3xx_nand_cmdset { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | struct pxa3xx_nand_flash { | 32 | struct pxa3xx_nand_flash { |
33 | const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ | 33 | uint32_t chip_id; |
34 | const struct pxa3xx_nand_cmdset *cmdset; | 34 | unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */ |
35 | 35 | unsigned int page_size; /* Page size in bytes (PAGE_SZ) */ | |
36 | uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ | 36 | unsigned int flash_width; /* Width of Flash memory (DWIDTH_M) */ |
37 | uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ | 37 | unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */ |
38 | uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ | 38 | unsigned int num_blocks; /* Number of physical blocks in Flash */ |
39 | uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ | 39 | |
40 | uint32_t num_blocks; /* Number of physical blocks in Flash */ | 40 | struct pxa3xx_nand_cmdset *cmdset; /* NAND command set */ |
41 | uint32_t chip_id; | 41 | struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ |
42 | }; | 42 | }; |
43 | 43 | ||
44 | struct pxa3xx_nand_platform_data { | 44 | struct pxa3xx_nand_platform_data { |
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h new file mode 100644 index 000000000000..5325084d5c48 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h | |||
@@ -0,0 +1,97 @@ | |||
1 | #ifndef __BCM963XX_TAG_H | ||
2 | #define __BCM963XX_TAG_H | ||
3 | |||
4 | #define TAGVER_LEN 4 /* Length of Tag Version */ | ||
5 | #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */ | ||
6 | #define SIG1_LEN 20 /* Company Signature 1 Length */ | ||
7 | #define SIG2_LEN 14 /* Company Signature 2 Lenght */ | ||
8 | #define BOARDID_LEN 16 /* Length of BoardId */ | ||
9 | #define ENDIANFLAG_LEN 2 /* Endian Flag Length */ | ||
10 | #define CHIPID_LEN 6 /* Chip Id Length */ | ||
11 | #define IMAGE_LEN 10 /* Length of Length Field */ | ||
12 | #define ADDRESS_LEN 12 /* Length of Address field */ | ||
13 | #define DUALFLAG_LEN 2 /* Dual Image flag Length */ | ||
14 | #define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */ | ||
15 | #define RSASIG_LEN 20 /* Length of RSA Signature in tag */ | ||
16 | #define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */ | ||
17 | #define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */ | ||
18 | #define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */ | ||
19 | #define CRC_LEN 4 /* Length of CRC in bytes */ | ||
20 | #define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */ | ||
21 | |||
22 | #define NUM_PIRELLI 2 | ||
23 | #define IMAGETAG_CRC_START 0xFFFFFFFF | ||
24 | |||
25 | #define PIRELLI_BOARDS { \ | ||
26 | "AGPF-S0", \ | ||
27 | "DWV-S0", \ | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * The broadcom firmware assumes the rootfs starts the image, | ||
32 | * therefore uses the rootfs start (flash_image_address) | ||
33 | * to determine where to flash the image. Since we have the kernel first | ||
34 | * we have to give it the kernel address, but the crc uses the length | ||
35 | * associated with this address (root_length), which is added to the kernel | ||
36 | * length (kernel_length) to determine the length of image to flash and thus | ||
37 | * needs to be rootfs + deadcode (jffs2 EOF marker) | ||
38 | */ | ||
39 | |||
40 | struct bcm_tag { | ||
41 | /* 0-3: Version of the image tag */ | ||
42 | char tag_version[TAGVER_LEN]; | ||
43 | /* 4-23: Company Line 1 */ | ||
44 | char sig_1[SIG1_LEN]; | ||
45 | /* 24-37: Company Line 2 */ | ||
46 | char sig_2[SIG2_LEN]; | ||
47 | /* 38-43: Chip this image is for */ | ||
48 | char chip_id[CHIPID_LEN]; | ||
49 | /* 44-59: Board name */ | ||
50 | char board_id[BOARDID_LEN]; | ||
51 | /* 60-61: Map endianness -- 1 BE 0 LE */ | ||
52 | char big_endian[ENDIANFLAG_LEN]; | ||
53 | /* 62-71: Total length of image */ | ||
54 | char total_length[IMAGE_LEN]; | ||
55 | /* 72-83: Address in memory of CFE */ | ||
56 | char cfe__address[ADDRESS_LEN]; | ||
57 | /* 84-93: Size of CFE */ | ||
58 | char cfe_length[IMAGE_LEN]; | ||
59 | /* 94-105: Address in memory of image start | ||
60 | * (kernel for OpenWRT, rootfs for stock firmware) | ||
61 | */ | ||
62 | char flash_image_start[ADDRESS_LEN]; | ||
63 | /* 106-115: Size of rootfs */ | ||
64 | char root_length[IMAGE_LEN]; | ||
65 | /* 116-127: Address in memory of kernel */ | ||
66 | char kernel_address[ADDRESS_LEN]; | ||
67 | /* 128-137: Size of kernel */ | ||
68 | char kernel_length[IMAGE_LEN]; | ||
69 | /* 138-139: Unused at the moment */ | ||
70 | char dual_image[DUALFLAG_LEN]; | ||
71 | /* 140-141: Unused at the moment */ | ||
72 | char inactive_flag[INACTIVEFLAG_LEN]; | ||
73 | /* 142-161: RSA Signature (not used; some vendors may use this) */ | ||
74 | char rsa_signature[RSASIG_LEN]; | ||
75 | /* 162-191: Compilation and related information (not used in OpenWrt) */ | ||
76 | char information1[TAGINFO1_LEN]; | ||
77 | /* 192-195: Version flash layout */ | ||
78 | char flash_layout_ver[FLASHLAYOUTVER_LEN]; | ||
79 | /* 196-199: kernel+rootfs CRC32 */ | ||
80 | char fskernel_crc[CRC_LEN]; | ||
81 | /* 200-215: Unused except on Alice Gate where is is information */ | ||
82 | char information2[TAGINFO2_LEN]; | ||
83 | /* 216-219: CRC32 of image less imagetag (kernel for Alice Gate) */ | ||
84 | char image_crc[CRC_LEN]; | ||
85 | /* 220-223: CRC32 of rootfs partition */ | ||
86 | char rootfs_crc[CRC_LEN]; | ||
87 | /* 224-227: CRC32 of kernel partition */ | ||
88 | char kernel_crc[CRC_LEN]; | ||
89 | /* 228-235: Unused at present */ | ||
90 | char reserved1[8]; | ||
91 | /* 236-239: CRC32 of header excluding tagVersion */ | ||
92 | char header_crc[CRC_LEN]; | ||
93 | /* 240-255: Unused at present */ | ||
94 | char reserved2[16]; | ||
95 | }; | ||
96 | |||
97 | #endif /* __BCM63XX_TAG_H */ | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c7e40b37aa65..b6447190e1a2 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -682,9 +682,12 @@ config 4xx_SOC | |||
682 | bool | 682 | bool |
683 | 683 | ||
684 | config FSL_LBC | 684 | config FSL_LBC |
685 | bool | 685 | bool "Freescale Local Bus support" |
686 | depends on FSL_SOC | ||
686 | help | 687 | help |
687 | Freescale Localbus support | 688 | Enables reporting of errors from the Freescale local bus |
689 | controller. Also contains some common code used by | ||
690 | drivers for specific local bus peripherals. | ||
688 | 691 | ||
689 | config FSL_GTM | 692 | config FSL_GTM |
690 | bool | 693 | bool |
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h index 1b5a21041f9b..5c1bf3466749 100644 --- a/arch/powerpc/include/asm/fsl_lbc.h +++ b/arch/powerpc/include/asm/fsl_lbc.h | |||
@@ -1,9 +1,10 @@ | |||
1 | /* Freescale Local Bus Controller | 1 | /* Freescale Local Bus Controller |
2 | * | 2 | * |
3 | * Copyright (c) 2006-2007 Freescale Semiconductor | 3 | * Copyright © 2006-2007, 2010 Freescale Semiconductor |
4 | * | 4 | * |
5 | * Authors: Nick Spence <nick.spence@freescale.com>, | 5 | * Authors: Nick Spence <nick.spence@freescale.com>, |
6 | * Scott Wood <scottwood@freescale.com> | 6 | * Scott Wood <scottwood@freescale.com> |
7 | * Jack Lan <jack.lan@freescale.com> | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * 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 | * it under the terms of the GNU General Public License as published by |
@@ -26,6 +27,8 @@ | |||
26 | #include <linux/compiler.h> | 27 | #include <linux/compiler.h> |
27 | #include <linux/types.h> | 28 | #include <linux/types.h> |
28 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/device.h> | ||
31 | #include <linux/spinlock.h> | ||
29 | 32 | ||
30 | struct fsl_lbc_bank { | 33 | struct fsl_lbc_bank { |
31 | __be32 br; /**< Base Register */ | 34 | __be32 br; /**< Base Register */ |
@@ -125,13 +128,23 @@ struct fsl_lbc_regs { | |||
125 | #define LTESR_ATMW 0x00800000 | 128 | #define LTESR_ATMW 0x00800000 |
126 | #define LTESR_ATMR 0x00400000 | 129 | #define LTESR_ATMR 0x00400000 |
127 | #define LTESR_CS 0x00080000 | 130 | #define LTESR_CS 0x00080000 |
131 | #define LTESR_UPM 0x00000002 | ||
128 | #define LTESR_CC 0x00000001 | 132 | #define LTESR_CC 0x00000001 |
129 | #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) | 133 | #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) |
134 | #define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \ | ||
135 | | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \ | ||
136 | | LTESR_CC) | ||
137 | #define LTESR_CLEAR 0xFFFFFFFF | ||
138 | #define LTECCR_CLEAR 0xFFFFFFFF | ||
139 | #define LTESR_STATUS LTESR_MASK | ||
140 | #define LTEIR_ENABLE LTESR_MASK | ||
141 | #define LTEDR_ENABLE 0x00000000 | ||
130 | __be32 ltedr; /**< Transfer Error Disable Register */ | 142 | __be32 ltedr; /**< Transfer Error Disable Register */ |
131 | __be32 lteir; /**< Transfer Error Interrupt Register */ | 143 | __be32 lteir; /**< Transfer Error Interrupt Register */ |
132 | __be32 lteatr; /**< Transfer Error Attributes Register */ | 144 | __be32 lteatr; /**< Transfer Error Attributes Register */ |
133 | __be32 ltear; /**< Transfer Error Address Register */ | 145 | __be32 ltear; /**< Transfer Error Address Register */ |
134 | u8 res6[0xC]; | 146 | __be32 lteccr; /**< Transfer Error ECC Register */ |
147 | u8 res6[0x8]; | ||
135 | __be32 lbcr; /**< Configuration Register */ | 148 | __be32 lbcr; /**< Configuration Register */ |
136 | #define LBCR_LDIS 0x80000000 | 149 | #define LBCR_LDIS 0x80000000 |
137 | #define LBCR_LDIS_SHIFT 31 | 150 | #define LBCR_LDIS_SHIFT 31 |
@@ -235,6 +248,7 @@ struct fsl_upm { | |||
235 | int width; | 248 | int width; |
236 | }; | 249 | }; |
237 | 250 | ||
251 | extern u32 fsl_lbc_addr(phys_addr_t addr_base); | ||
238 | extern int fsl_lbc_find(phys_addr_t addr_base); | 252 | extern int fsl_lbc_find(phys_addr_t addr_base); |
239 | extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm); | 253 | extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm); |
240 | 254 | ||
@@ -265,7 +279,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm) | |||
265 | cpu_relax(); | 279 | cpu_relax(); |
266 | } | 280 | } |
267 | 281 | ||
282 | /* overview of the fsl lbc controller */ | ||
283 | |||
284 | struct fsl_lbc_ctrl { | ||
285 | /* device info */ | ||
286 | struct device *dev; | ||
287 | struct fsl_lbc_regs __iomem *regs; | ||
288 | int irq; | ||
289 | wait_queue_head_t irq_wait; | ||
290 | spinlock_t lock; | ||
291 | void *nand; | ||
292 | |||
293 | /* status read from LTESR by irq handler */ | ||
294 | unsigned int irq_status; | ||
295 | }; | ||
296 | |||
268 | extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, | 297 | extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, |
269 | u32 mar); | 298 | u32 mar); |
299 | extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev; | ||
270 | 300 | ||
271 | #endif /* __ASM_FSL_LBC_H */ | 301 | #endif /* __ASM_FSL_LBC_H */ |
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index dceb8d1a843d..4fcb5a4e60dd 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c | |||
@@ -1,9 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Freescale LBC and UPM routines. | 2 | * Freescale LBC and UPM routines. |
3 | * | 3 | * |
4 | * Copyright (c) 2007-2008 MontaVista Software, Inc. | 4 | * Copyright © 2007-2008 MontaVista Software, Inc. |
5 | * Copyright © 2010 Freescale Semiconductor | ||
5 | * | 6 | * |
6 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | 7 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> |
8 | * Author: Jack Lan <Jack.Lan@freescale.com> | ||
9 | * Author: Roy Zang <tie-fei.zang@freescale.com> | ||
7 | * | 10 | * |
8 | * This program is free software; you can redistribute it and/or modify | 11 | * 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 | 12 | * it under the terms of the GNU General Public License as published by |
@@ -19,39 +22,37 @@ | |||
19 | #include <linux/types.h> | 22 | #include <linux/types.h> |
20 | #include <linux/io.h> | 23 | #include <linux/io.h> |
21 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/slab.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/mod_devicetable.h> | ||
22 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
23 | #include <asm/fsl_lbc.h> | 30 | #include <asm/fsl_lbc.h> |
24 | 31 | ||
25 | static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); | 32 | static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); |
26 | static struct fsl_lbc_regs __iomem *fsl_lbc_regs; | 33 | struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev; |
34 | EXPORT_SYMBOL(fsl_lbc_ctrl_dev); | ||
27 | 35 | ||
28 | static char __initdata *compat_lbc[] = { | 36 | /** |
29 | "fsl,pq2-localbus", | 37 | * fsl_lbc_addr - convert the base address |
30 | "fsl,pq2pro-localbus", | 38 | * @addr_base: base address of the memory bank |
31 | "fsl,pq3-localbus", | 39 | * |
32 | "fsl,elbc", | 40 | * This function converts a base address of lbc into the right format for the |
33 | }; | 41 | * BR register. If the SOC has eLBC then it returns 32bit physical address |
34 | 42 | * else it convers a 34bit local bus physical address to correct format of | |
35 | static int __init fsl_lbc_init(void) | 43 | * 32bit address for BR register (Example: MPC8641). |
44 | */ | ||
45 | u32 fsl_lbc_addr(phys_addr_t addr_base) | ||
36 | { | 46 | { |
37 | struct device_node *lbus; | 47 | struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node; |
38 | int i; | 48 | u32 addr = addr_base & 0xffff8000; |
39 | 49 | ||
40 | for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) { | 50 | if (of_device_is_compatible(np, "fsl,elbc")) |
41 | lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]); | 51 | return addr; |
42 | if (lbus) | ||
43 | goto found; | ||
44 | } | ||
45 | return -ENODEV; | ||
46 | 52 | ||
47 | found: | 53 | return addr | ((addr_base & 0x300000000ull) >> 19); |
48 | fsl_lbc_regs = of_iomap(lbus, 0); | ||
49 | of_node_put(lbus); | ||
50 | if (!fsl_lbc_regs) | ||
51 | return -ENOMEM; | ||
52 | return 0; | ||
53 | } | 54 | } |
54 | arch_initcall(fsl_lbc_init); | 55 | EXPORT_SYMBOL(fsl_lbc_addr); |
55 | 56 | ||
56 | /** | 57 | /** |
57 | * fsl_lbc_find - find Localbus bank | 58 | * fsl_lbc_find - find Localbus bank |
@@ -65,15 +66,17 @@ arch_initcall(fsl_lbc_init); | |||
65 | int fsl_lbc_find(phys_addr_t addr_base) | 66 | int fsl_lbc_find(phys_addr_t addr_base) |
66 | { | 67 | { |
67 | int i; | 68 | int i; |
69 | struct fsl_lbc_regs __iomem *lbc; | ||
68 | 70 | ||
69 | if (!fsl_lbc_regs) | 71 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) |
70 | return -ENODEV; | 72 | return -ENODEV; |
71 | 73 | ||
72 | for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) { | 74 | lbc = fsl_lbc_ctrl_dev->regs; |
73 | __be32 br = in_be32(&fsl_lbc_regs->bank[i].br); | 75 | for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) { |
74 | __be32 or = in_be32(&fsl_lbc_regs->bank[i].or); | 76 | __be32 br = in_be32(&lbc->bank[i].br); |
77 | __be32 or = in_be32(&lbc->bank[i].or); | ||
75 | 78 | ||
76 | if (br & BR_V && (br & or & BR_BA) == addr_base) | 79 | if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base)) |
77 | return i; | 80 | return i; |
78 | } | 81 | } |
79 | 82 | ||
@@ -94,22 +97,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm) | |||
94 | { | 97 | { |
95 | int bank; | 98 | int bank; |
96 | __be32 br; | 99 | __be32 br; |
100 | struct fsl_lbc_regs __iomem *lbc; | ||
97 | 101 | ||
98 | bank = fsl_lbc_find(addr_base); | 102 | bank = fsl_lbc_find(addr_base); |
99 | if (bank < 0) | 103 | if (bank < 0) |
100 | return bank; | 104 | return bank; |
101 | 105 | ||
102 | br = in_be32(&fsl_lbc_regs->bank[bank].br); | 106 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) |
107 | return -ENODEV; | ||
108 | |||
109 | lbc = fsl_lbc_ctrl_dev->regs; | ||
110 | br = in_be32(&lbc->bank[bank].br); | ||
103 | 111 | ||
104 | switch (br & BR_MSEL) { | 112 | switch (br & BR_MSEL) { |
105 | case BR_MS_UPMA: | 113 | case BR_MS_UPMA: |
106 | upm->mxmr = &fsl_lbc_regs->mamr; | 114 | upm->mxmr = &lbc->mamr; |
107 | break; | 115 | break; |
108 | case BR_MS_UPMB: | 116 | case BR_MS_UPMB: |
109 | upm->mxmr = &fsl_lbc_regs->mbmr; | 117 | upm->mxmr = &lbc->mbmr; |
110 | break; | 118 | break; |
111 | case BR_MS_UPMC: | 119 | case BR_MS_UPMC: |
112 | upm->mxmr = &fsl_lbc_regs->mcmr; | 120 | upm->mxmr = &lbc->mcmr; |
113 | break; | 121 | break; |
114 | default: | 122 | default: |
115 | return -EINVAL; | 123 | return -EINVAL; |
@@ -148,9 +156,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) | |||
148 | int ret = 0; | 156 | int ret = 0; |
149 | unsigned long flags; | 157 | unsigned long flags; |
150 | 158 | ||
159 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) | ||
160 | return -ENODEV; | ||
161 | |||
151 | spin_lock_irqsave(&fsl_lbc_lock, flags); | 162 | spin_lock_irqsave(&fsl_lbc_lock, flags); |
152 | 163 | ||
153 | out_be32(&fsl_lbc_regs->mar, mar); | 164 | out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar); |
154 | 165 | ||
155 | switch (upm->width) { | 166 | switch (upm->width) { |
156 | case 8: | 167 | case 8: |
@@ -172,3 +183,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) | |||
172 | return ret; | 183 | return ret; |
173 | } | 184 | } |
174 | EXPORT_SYMBOL(fsl_upm_run_pattern); | 185 | EXPORT_SYMBOL(fsl_upm_run_pattern); |
186 | |||
187 | static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl) | ||
188 | { | ||
189 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
190 | |||
191 | /* clear event registers */ | ||
192 | setbits32(&lbc->ltesr, LTESR_CLEAR); | ||
193 | out_be32(&lbc->lteatr, 0); | ||
194 | out_be32(&lbc->ltear, 0); | ||
195 | out_be32(&lbc->lteccr, LTECCR_CLEAR); | ||
196 | out_be32(&lbc->ltedr, LTEDR_ENABLE); | ||
197 | |||
198 | /* Enable interrupts for any detected events */ | ||
199 | out_be32(&lbc->lteir, LTEIR_ENABLE); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * NOTE: This interrupt is used to report localbus events of various kinds, | ||
206 | * such as transaction errors on the chipselects. | ||
207 | */ | ||
208 | |||
209 | static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data) | ||
210 | { | ||
211 | struct fsl_lbc_ctrl *ctrl = data; | ||
212 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
213 | u32 status; | ||
214 | |||
215 | status = in_be32(&lbc->ltesr); | ||
216 | if (!status) | ||
217 | return IRQ_NONE; | ||
218 | |||
219 | out_be32(&lbc->ltesr, LTESR_CLEAR); | ||
220 | out_be32(&lbc->lteatr, 0); | ||
221 | out_be32(&lbc->ltear, 0); | ||
222 | ctrl->irq_status = status; | ||
223 | |||
224 | if (status & LTESR_BM) | ||
225 | dev_err(ctrl->dev, "Local bus monitor time-out: " | ||
226 | "LTESR 0x%08X\n", status); | ||
227 | if (status & LTESR_WP) | ||
228 | dev_err(ctrl->dev, "Write protect error: " | ||
229 | "LTESR 0x%08X\n", status); | ||
230 | if (status & LTESR_ATMW) | ||
231 | dev_err(ctrl->dev, "Atomic write error: " | ||
232 | "LTESR 0x%08X\n", status); | ||
233 | if (status & LTESR_ATMR) | ||
234 | dev_err(ctrl->dev, "Atomic read error: " | ||
235 | "LTESR 0x%08X\n", status); | ||
236 | if (status & LTESR_CS) | ||
237 | dev_err(ctrl->dev, "Chip select error: " | ||
238 | "LTESR 0x%08X\n", status); | ||
239 | if (status & LTESR_UPM) | ||
240 | ; | ||
241 | if (status & LTESR_FCT) { | ||
242 | dev_err(ctrl->dev, "FCM command time-out: " | ||
243 | "LTESR 0x%08X\n", status); | ||
244 | smp_wmb(); | ||
245 | wake_up(&ctrl->irq_wait); | ||
246 | } | ||
247 | if (status & LTESR_PAR) { | ||
248 | dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: " | ||
249 | "LTESR 0x%08X\n", status); | ||
250 | smp_wmb(); | ||
251 | wake_up(&ctrl->irq_wait); | ||
252 | } | ||
253 | if (status & LTESR_CC) { | ||
254 | smp_wmb(); | ||
255 | wake_up(&ctrl->irq_wait); | ||
256 | } | ||
257 | if (status & ~LTESR_MASK) | ||
258 | dev_err(ctrl->dev, "Unknown error: " | ||
259 | "LTESR 0x%08X\n", status); | ||
260 | return IRQ_HANDLED; | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * fsl_lbc_ctrl_probe | ||
265 | * | ||
266 | * called by device layer when it finds a device matching | ||
267 | * one our driver can handled. This code allocates all of | ||
268 | * the resources needed for the controller only. The | ||
269 | * resources for the NAND banks themselves are allocated | ||
270 | * in the chip probe function. | ||
271 | */ | ||
272 | |||
273 | static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev) | ||
274 | { | ||
275 | int ret; | ||
276 | |||
277 | if (!dev->dev.of_node) { | ||
278 | dev_err(&dev->dev, "Device OF-Node is NULL"); | ||
279 | return -EFAULT; | ||
280 | } | ||
281 | |||
282 | fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL); | ||
283 | if (!fsl_lbc_ctrl_dev) | ||
284 | return -ENOMEM; | ||
285 | |||
286 | dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev); | ||
287 | |||
288 | spin_lock_init(&fsl_lbc_ctrl_dev->lock); | ||
289 | init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait); | ||
290 | |||
291 | fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0); | ||
292 | if (!fsl_lbc_ctrl_dev->regs) { | ||
293 | dev_err(&dev->dev, "failed to get memory region\n"); | ||
294 | ret = -ENODEV; | ||
295 | goto err; | ||
296 | } | ||
297 | |||
298 | fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); | ||
299 | if (fsl_lbc_ctrl_dev->irq == NO_IRQ) { | ||
300 | dev_err(&dev->dev, "failed to get irq resource\n"); | ||
301 | ret = -ENODEV; | ||
302 | goto err; | ||
303 | } | ||
304 | |||
305 | fsl_lbc_ctrl_dev->dev = &dev->dev; | ||
306 | |||
307 | ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev); | ||
308 | if (ret < 0) | ||
309 | goto err; | ||
310 | |||
311 | ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0, | ||
312 | "fsl-lbc", fsl_lbc_ctrl_dev); | ||
313 | if (ret != 0) { | ||
314 | dev_err(&dev->dev, "failed to install irq (%d)\n", | ||
315 | fsl_lbc_ctrl_dev->irq); | ||
316 | ret = fsl_lbc_ctrl_dev->irq; | ||
317 | goto err; | ||
318 | } | ||
319 | |||
320 | return 0; | ||
321 | |||
322 | err: | ||
323 | iounmap(fsl_lbc_ctrl_dev->regs); | ||
324 | kfree(fsl_lbc_ctrl_dev); | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | static const struct of_device_id fsl_lbc_match[] = { | ||
329 | { .compatible = "fsl,elbc", }, | ||
330 | { .compatible = "fsl,pq3-localbus", }, | ||
331 | { .compatible = "fsl,pq2-localbus", }, | ||
332 | { .compatible = "fsl,pq2pro-localbus", }, | ||
333 | {}, | ||
334 | }; | ||
335 | |||
336 | static struct platform_driver fsl_lbc_ctrl_driver = { | ||
337 | .driver = { | ||
338 | .name = "fsl-lbc", | ||
339 | .of_match_table = fsl_lbc_match, | ||
340 | }, | ||
341 | .probe = fsl_lbc_ctrl_probe, | ||
342 | }; | ||
343 | |||
344 | static int __init fsl_lbc_init(void) | ||
345 | { | ||
346 | return platform_driver_register(&fsl_lbc_ctrl_driver); | ||
347 | } | ||
348 | module_init(fsl_lbc_init); | ||
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 9e2b7e9e0ad9..ad9268b44416 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -1496,7 +1496,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1496 | 1496 | ||
1497 | switch (mode) { | 1497 | switch (mode) { |
1498 | case FL_WRITING: | 1498 | case FL_WRITING: |
1499 | write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); | 1499 | write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0x40) : CMD(0x41); |
1500 | break; | 1500 | break; |
1501 | case FL_OTP_WRITE: | 1501 | case FL_OTP_WRITE: |
1502 | write_cmd = CMD(0xc0); | 1502 | write_cmd = CMD(0xc0); |
@@ -1661,7 +1661,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1661 | cmd_adr = adr & ~(wbufsize-1); | 1661 | cmd_adr = adr & ~(wbufsize-1); |
1662 | 1662 | ||
1663 | /* Let's determine this according to the interleave only once */ | 1663 | /* Let's determine this according to the interleave only once */ |
1664 | write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); | 1664 | write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0xe8) : CMD(0xe9); |
1665 | 1665 | ||
1666 | mutex_lock(&chip->mutex); | 1666 | mutex_lock(&chip->mutex); |
1667 | ret = get_chip(map, chip, cmd_adr, FL_WRITING); | 1667 | ret = get_chip(map, chip, cmd_adr, FL_WRITING); |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index ba29d2f0ffd7..3b8e32d87977 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -291,6 +291,23 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param) | |||
291 | 291 | ||
292 | cfi->addr_unlock1 = 0x555; | 292 | cfi->addr_unlock1 = 0x555; |
293 | cfi->addr_unlock2 = 0x2AA; | 293 | cfi->addr_unlock2 = 0x2AA; |
294 | |||
295 | cfi->sector_erase_cmd = CMD(0x50); | ||
296 | } | ||
297 | |||
298 | static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param) | ||
299 | { | ||
300 | struct map_info *map = mtd->priv; | ||
301 | struct cfi_private *cfi = map->fldrv_priv; | ||
302 | |||
303 | fixup_sst39vf_rev_b(mtd, param); | ||
304 | |||
305 | /* | ||
306 | * CFI reports 1024 sectors (0x03ff+1) of 64KBytes (0x0100*256) where | ||
307 | * it should report a size of 8KBytes (0x0020*256). | ||
308 | */ | ||
309 | cfi->cfiq->EraseRegionInfo[0] = 0x002003ff; | ||
310 | pr_warning("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n", mtd->name); | ||
294 | } | 311 | } |
295 | 312 | ||
296 | static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) | 313 | static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) |
@@ -317,14 +334,14 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param) | |||
317 | 334 | ||
318 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ | 335 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ |
319 | static struct cfi_fixup cfi_nopri_fixup_table[] = { | 336 | static struct cfi_fixup cfi_nopri_fixup_table[] = { |
320 | { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, // SST39VF1602 | 337 | { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, /* SST39VF1602 */ |
321 | { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, // SST39VF1601 | 338 | { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, /* SST39VF1601 */ |
322 | { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, // SST39VF3202 | 339 | { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, /* SST39VF3202 */ |
323 | { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, // SST39VF3201 | 340 | { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, /* SST39VF3201 */ |
324 | { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B | 341 | { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3202B */ |
325 | { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B | 342 | { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3201B */ |
326 | { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B | 343 | { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6402B */ |
327 | { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B | 344 | { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6401B */ |
328 | { 0, 0, NULL, NULL } | 345 | { 0, 0, NULL, NULL } |
329 | }; | 346 | }; |
330 | 347 | ||
@@ -344,6 +361,10 @@ static struct cfi_fixup cfi_fixup_table[] = { | |||
344 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, }, | 361 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, }, |
345 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, }, | 362 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, }, |
346 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, }, | 363 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, }, |
364 | { CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */ | ||
365 | { CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */ | ||
366 | { CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */ | ||
367 | { CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */ | ||
347 | #if !FORCE_WORD_WRITE | 368 | #if !FORCE_WORD_WRITE |
348 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, | 369 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, |
349 | #endif | 370 | #endif |
@@ -374,6 +395,13 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi, | |||
374 | if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e && | 395 | if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e && |
375 | extp->MajorVersion == '0') | 396 | extp->MajorVersion == '0') |
376 | extp->MajorVersion = '1'; | 397 | extp->MajorVersion = '1'; |
398 | /* | ||
399 | * SST 38VF640x chips report major=0xFF / minor=0xFF. | ||
400 | */ | ||
401 | if (cfi->mfr == CFI_MFR_SST && (cfi->id >> 4) == 0x0536) { | ||
402 | extp->MajorVersion = '1'; | ||
403 | extp->MinorVersion = '0'; | ||
404 | } | ||
377 | } | 405 | } |
378 | 406 | ||
379 | struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | 407 | struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) |
@@ -545,15 +573,6 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) | |||
545 | printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); | 573 | printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); |
546 | goto setup_err; | 574 | goto setup_err; |
547 | } | 575 | } |
548 | #if 0 | ||
549 | // debug | ||
550 | for (i=0; i<mtd->numeraseregions;i++){ | ||
551 | printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", | ||
552 | i,mtd->eraseregions[i].offset, | ||
553 | mtd->eraseregions[i].erasesize, | ||
554 | mtd->eraseregions[i].numblocks); | ||
555 | } | ||
556 | #endif | ||
557 | 576 | ||
558 | __module_get(THIS_MODULE); | 577 | __module_get(THIS_MODULE); |
559 | register_reboot_notifier(&mtd->reboot_notifier); | 578 | register_reboot_notifier(&mtd->reboot_notifier); |
@@ -674,7 +693,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
674 | * there was an error (so leave the erase | 693 | * there was an error (so leave the erase |
675 | * routine to recover from it) or we trying to | 694 | * routine to recover from it) or we trying to |
676 | * use the erase-in-progress sector. */ | 695 | * use the erase-in-progress sector. */ |
677 | map_write(map, CMD(0x30), chip->in_progress_block_addr); | 696 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); |
678 | chip->state = FL_ERASING; | 697 | chip->state = FL_ERASING; |
679 | chip->oldstate = FL_READY; | 698 | chip->oldstate = FL_READY; |
680 | printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); | 699 | printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); |
@@ -727,7 +746,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
727 | switch(chip->oldstate) { | 746 | switch(chip->oldstate) { |
728 | case FL_ERASING: | 747 | case FL_ERASING: |
729 | chip->state = chip->oldstate; | 748 | chip->state = chip->oldstate; |
730 | map_write(map, CMD(0x30), chip->in_progress_block_addr); | 749 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); |
731 | chip->oldstate = FL_READY; | 750 | chip->oldstate = FL_READY; |
732 | chip->state = FL_ERASING; | 751 | chip->state = FL_ERASING; |
733 | break; | 752 | break; |
@@ -870,7 +889,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, | |||
870 | local_irq_disable(); | 889 | local_irq_disable(); |
871 | 890 | ||
872 | /* Resume the write or erase operation */ | 891 | /* Resume the write or erase operation */ |
873 | map_write(map, CMD(0x30), adr); | 892 | map_write(map, cfi->sector_erase_cmd, adr); |
874 | chip->state = oldstate; | 893 | chip->state = oldstate; |
875 | start = xip_currtime(); | 894 | start = xip_currtime(); |
876 | } else if (usec >= 1000000/HZ) { | 895 | } else if (usec >= 1000000/HZ) { |
@@ -1025,9 +1044,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi | |||
1025 | mutex_lock(&chip->mutex); | 1044 | mutex_lock(&chip->mutex); |
1026 | 1045 | ||
1027 | if (chip->state != FL_READY){ | 1046 | if (chip->state != FL_READY){ |
1028 | #if 0 | ||
1029 | printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state); | ||
1030 | #endif | ||
1031 | set_current_state(TASK_UNINTERRUPTIBLE); | 1047 | set_current_state(TASK_UNINTERRUPTIBLE); |
1032 | add_wait_queue(&chip->wq, &wait); | 1048 | add_wait_queue(&chip->wq, &wait); |
1033 | 1049 | ||
@@ -1035,10 +1051,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi | |||
1035 | 1051 | ||
1036 | schedule(); | 1052 | schedule(); |
1037 | remove_wait_queue(&chip->wq, &wait); | 1053 | remove_wait_queue(&chip->wq, &wait); |
1038 | #if 0 | ||
1039 | if(signal_pending(current)) | ||
1040 | return -EINTR; | ||
1041 | #endif | ||
1042 | timeo = jiffies + HZ; | 1054 | timeo = jiffies + HZ; |
1043 | 1055 | ||
1044 | goto retry; | 1056 | goto retry; |
@@ -1246,9 +1258,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1246 | mutex_lock(&cfi->chips[chipnum].mutex); | 1258 | mutex_lock(&cfi->chips[chipnum].mutex); |
1247 | 1259 | ||
1248 | if (cfi->chips[chipnum].state != FL_READY) { | 1260 | if (cfi->chips[chipnum].state != FL_READY) { |
1249 | #if 0 | ||
1250 | printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); | ||
1251 | #endif | ||
1252 | set_current_state(TASK_UNINTERRUPTIBLE); | 1261 | set_current_state(TASK_UNINTERRUPTIBLE); |
1253 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1262 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1254 | 1263 | ||
@@ -1256,10 +1265,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1256 | 1265 | ||
1257 | schedule(); | 1266 | schedule(); |
1258 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1267 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1259 | #if 0 | ||
1260 | if(signal_pending(current)) | ||
1261 | return -EINTR; | ||
1262 | #endif | ||
1263 | goto retry; | 1268 | goto retry; |
1264 | } | 1269 | } |
1265 | 1270 | ||
@@ -1324,9 +1329,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1324 | mutex_lock(&cfi->chips[chipnum].mutex); | 1329 | mutex_lock(&cfi->chips[chipnum].mutex); |
1325 | 1330 | ||
1326 | if (cfi->chips[chipnum].state != FL_READY) { | 1331 | if (cfi->chips[chipnum].state != FL_READY) { |
1327 | #if 0 | ||
1328 | printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); | ||
1329 | #endif | ||
1330 | set_current_state(TASK_UNINTERRUPTIBLE); | 1332 | set_current_state(TASK_UNINTERRUPTIBLE); |
1331 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1333 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1332 | 1334 | ||
@@ -1334,10 +1336,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1334 | 1336 | ||
1335 | schedule(); | 1337 | schedule(); |
1336 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1338 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1337 | #if 0 | ||
1338 | if(signal_pending(current)) | ||
1339 | return -EINTR; | ||
1340 | #endif | ||
1341 | goto retry1; | 1339 | goto retry1; |
1342 | } | 1340 | } |
1343 | 1341 | ||
@@ -1396,7 +1394,6 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1396 | 1394 | ||
1397 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1395 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1398 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | 1396 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); |
1399 | //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
1400 | 1397 | ||
1401 | /* Write Buffer Load */ | 1398 | /* Write Buffer Load */ |
1402 | map_write(map, CMD(0x25), cmd_adr); | 1399 | map_write(map, CMD(0x25), cmd_adr); |
@@ -1675,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
1675 | cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1672 | cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1676 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1673 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1677 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | 1674 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); |
1678 | map_write(map, CMD(0x30), adr); | 1675 | map_write(map, cfi->sector_erase_cmd, adr); |
1679 | 1676 | ||
1680 | chip->state = FL_ERASING; | 1677 | chip->state = FL_ERASING; |
1681 | chip->erase_suspended = 0; | 1678 | chip->erase_suspended = 0; |
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index 8f5b96aa87a0..d25535279404 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c | |||
@@ -177,6 +177,8 @@ static int __xipram cfi_chip_setup(struct map_info *map, | |||
177 | 177 | ||
178 | cfi->cfi_mode = CFI_MODE_CFI; | 178 | cfi->cfi_mode = CFI_MODE_CFI; |
179 | 179 | ||
180 | cfi->sector_erase_cmd = CMD(0x30); | ||
181 | |||
180 | /* Read the CFI info structure */ | 182 | /* Read the CFI info structure */ |
181 | xip_disable_qry(base, map, cfi); | 183 | xip_disable_qry(base, map, cfi); |
182 | for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) | 184 | for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index e503b2ca894d..360525c637d2 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
@@ -77,6 +77,13 @@ int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map, | |||
77 | cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); | 77 | cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); |
78 | if (cfi_qry_present(map, base, cfi)) | 78 | if (cfi_qry_present(map, base, cfi)) |
79 | return 1; | 79 | return 1; |
80 | /* SST 39VF640xB */ | ||
81 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | ||
82 | cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL); | ||
83 | cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL); | ||
84 | cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL); | ||
85 | if (cfi_qry_present(map, base, cfi)) | ||
86 | return 1; | ||
80 | /* QRY not found */ | 87 | /* QRY not found */ |
81 | return 0; | 88 | return 0; |
82 | } | 89 | } |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 93651865ddbe..2cf0cc6a4189 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -91,7 +91,6 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
91 | } else | 91 | } else |
92 | instr->state = MTD_ERASE_DONE; | 92 | instr->state = MTD_ERASE_DONE; |
93 | 93 | ||
94 | instr->state = MTD_ERASE_DONE; | ||
95 | mtd_erase_callback(instr); | 94 | mtd_erase_callback(instr); |
96 | return err; | 95 | return err; |
97 | } | 96 | } |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index ea22520c0406..bf5a002209bd 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -661,11 +661,14 @@ static const struct spi_device_id m25p_ids[] = { | |||
661 | { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, | 661 | { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, |
662 | { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, | 662 | { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, |
663 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, | 663 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, |
664 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K) }, | ||
664 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, | 665 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, |
665 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 666 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
666 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, | 667 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, |
667 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, | 668 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, |
668 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, | 669 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, |
670 | { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, | ||
671 | { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | ||
669 | 672 | ||
670 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ | 673 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ |
671 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, | 674 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, |
@@ -714,6 +717,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
714 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, | 717 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, |
715 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, | 718 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, |
716 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 719 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
720 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | ||
717 | 721 | ||
718 | /* Catalyst / On Semiconductor -- non-JEDEC */ | 722 | /* Catalyst / On Semiconductor -- non-JEDEC */ |
719 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, | 723 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, |
@@ -924,7 +928,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
924 | nr_parts = data->nr_parts; | 928 | nr_parts = data->nr_parts; |
925 | } | 929 | } |
926 | 930 | ||
927 | #ifdef CONFIG_OF | 931 | #ifdef CONFIG_MTD_OF_PARTS |
928 | if (nr_parts <= 0 && spi->dev.of_node) { | 932 | if (nr_parts <= 0 && spi->dev.of_node) { |
929 | nr_parts = of_mtd_parse_partitions(&spi->dev, | 933 | nr_parts = of_mtd_parse_partitions(&spi->dev, |
930 | spi->dev.of_node, &parts); | 934 | spi->dev.of_node, &parts); |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 1696bbecaa7e..52393282eaf1 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi | 15 | * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define pr_fmt(fmt) "phram: " fmt | 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
19 | 19 | ||
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 962212628f6e..a0dd7bba9481 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -251,6 +251,15 @@ config MTD_NETtel | |||
251 | help | 251 | help |
252 | Support for flash chips on NETtel/SecureEdge/SnapGear boards. | 252 | Support for flash chips on NETtel/SecureEdge/SnapGear boards. |
253 | 253 | ||
254 | config MTD_BCM963XX | ||
255 | tristate "Map driver for Broadcom BCM963xx boards" | ||
256 | depends on BCM63XX | ||
257 | select MTD_MAP_BANK_WIDTH_2 | ||
258 | select MTD_CFI_I1 | ||
259 | help | ||
260 | Support for parsing CFE image tag and creating MTD partitions on | ||
261 | Broadcom BCM63xx boards. | ||
262 | |||
254 | config MTD_DILNETPC | 263 | config MTD_DILNETPC |
255 | tristate "CFI Flash device mapped on DIL/Net PC" | 264 | tristate "CFI Flash device mapped on DIL/Net PC" |
256 | depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN | 265 | depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN |
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index f216bb573713..c7869c7a6b18 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile | |||
@@ -58,3 +58,4 @@ obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o | |||
58 | obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o | 58 | obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o |
59 | obj-$(CONFIG_MTD_VMU) += vmu-flash.o | 59 | obj-$(CONFIG_MTD_VMU) += vmu-flash.o |
60 | obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o | 60 | obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o |
61 | obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o | ||
diff --git a/drivers/mtd/maps/bcm963xx-flash.c b/drivers/mtd/maps/bcm963xx-flash.c new file mode 100644 index 000000000000..d175c120ee84 --- /dev/null +++ b/drivers/mtd/maps/bcm963xx-flash.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org> | ||
3 | * Mike Albon <malbon@openwrt.org> | ||
4 | * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/mtd/map.h> | ||
25 | #include <linux/mtd/mtd.h> | ||
26 | #include <linux/mtd/partitions.h> | ||
27 | #include <linux/vmalloc.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/io.h> | ||
30 | |||
31 | #include <asm/mach-bcm63xx/bcm963xx_tag.h> | ||
32 | |||
33 | #define BCM63XX_BUSWIDTH 2 /* Buswidth */ | ||
34 | #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ | ||
35 | |||
36 | #define PFX KBUILD_MODNAME ": " | ||
37 | |||
38 | static struct mtd_partition *parsed_parts; | ||
39 | |||
40 | static struct mtd_info *bcm963xx_mtd_info; | ||
41 | |||
42 | static struct map_info bcm963xx_map = { | ||
43 | .name = "bcm963xx", | ||
44 | .bankwidth = BCM63XX_BUSWIDTH, | ||
45 | }; | ||
46 | |||
47 | static int parse_cfe_partitions(struct mtd_info *master, | ||
48 | struct mtd_partition **pparts) | ||
49 | { | ||
50 | /* CFE, NVRAM and global Linux are always present */ | ||
51 | int nrparts = 3, curpart = 0; | ||
52 | struct bcm_tag *buf; | ||
53 | struct mtd_partition *parts; | ||
54 | int ret; | ||
55 | size_t retlen; | ||
56 | unsigned int rootfsaddr, kerneladdr, spareaddr; | ||
57 | unsigned int rootfslen, kernellen, sparelen, totallen; | ||
58 | int namelen = 0; | ||
59 | int i; | ||
60 | char *boardid; | ||
61 | char *tagversion; | ||
62 | |||
63 | /* Allocate memory for buffer */ | ||
64 | buf = vmalloc(sizeof(struct bcm_tag)); | ||
65 | if (!buf) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | /* Get the tag */ | ||
69 | ret = master->read(master, master->erasesize, sizeof(struct bcm_tag), | ||
70 | &retlen, (void *)buf); | ||
71 | if (retlen != sizeof(struct bcm_tag)) { | ||
72 | vfree(buf); | ||
73 | return -EIO; | ||
74 | } | ||
75 | |||
76 | sscanf(buf->kernel_address, "%u", &kerneladdr); | ||
77 | sscanf(buf->kernel_length, "%u", &kernellen); | ||
78 | sscanf(buf->total_length, "%u", &totallen); | ||
79 | tagversion = &(buf->tag_version[0]); | ||
80 | boardid = &(buf->board_id[0]); | ||
81 | |||
82 | printk(KERN_INFO PFX "CFE boot tag found with version %s " | ||
83 | "and board type %s\n", tagversion, boardid); | ||
84 | |||
85 | kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; | ||
86 | rootfsaddr = kerneladdr + kernellen; | ||
87 | spareaddr = roundup(totallen, master->erasesize) + master->erasesize; | ||
88 | sparelen = master->size - spareaddr - master->erasesize; | ||
89 | rootfslen = spareaddr - rootfsaddr; | ||
90 | |||
91 | /* Determine number of partitions */ | ||
92 | namelen = 8; | ||
93 | if (rootfslen > 0) { | ||
94 | nrparts++; | ||
95 | namelen += 6; | ||
96 | }; | ||
97 | if (kernellen > 0) { | ||
98 | nrparts++; | ||
99 | namelen += 6; | ||
100 | }; | ||
101 | |||
102 | /* Ask kernel for more memory */ | ||
103 | parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); | ||
104 | if (!parts) { | ||
105 | vfree(buf); | ||
106 | return -ENOMEM; | ||
107 | }; | ||
108 | |||
109 | /* Start building partition list */ | ||
110 | parts[curpart].name = "CFE"; | ||
111 | parts[curpart].offset = 0; | ||
112 | parts[curpart].size = master->erasesize; | ||
113 | curpart++; | ||
114 | |||
115 | if (kernellen > 0) { | ||
116 | parts[curpart].name = "kernel"; | ||
117 | parts[curpart].offset = kerneladdr; | ||
118 | parts[curpart].size = kernellen; | ||
119 | curpart++; | ||
120 | }; | ||
121 | |||
122 | if (rootfslen > 0) { | ||
123 | parts[curpart].name = "rootfs"; | ||
124 | parts[curpart].offset = rootfsaddr; | ||
125 | parts[curpart].size = rootfslen; | ||
126 | if (sparelen > 0) | ||
127 | parts[curpart].size += sparelen; | ||
128 | curpart++; | ||
129 | }; | ||
130 | |||
131 | parts[curpart].name = "nvram"; | ||
132 | parts[curpart].offset = master->size - master->erasesize; | ||
133 | parts[curpart].size = master->erasesize; | ||
134 | |||
135 | /* Global partition "linux" to make easy firmware upgrade */ | ||
136 | curpart++; | ||
137 | parts[curpart].name = "linux"; | ||
138 | parts[curpart].offset = parts[0].size; | ||
139 | parts[curpart].size = master->size - parts[0].size - parts[3].size; | ||
140 | |||
141 | for (i = 0; i < nrparts; i++) | ||
142 | printk(KERN_INFO PFX "Partition %d is %s offset %lx and " | ||
143 | "length %lx\n", i, parts[i].name, | ||
144 | (long unsigned int)(parts[i].offset), | ||
145 | (long unsigned int)(parts[i].size)); | ||
146 | |||
147 | printk(KERN_INFO PFX "Spare partition is %x offset and length %x\n", | ||
148 | spareaddr, sparelen); | ||
149 | *pparts = parts; | ||
150 | vfree(buf); | ||
151 | |||
152 | return nrparts; | ||
153 | }; | ||
154 | |||
155 | static int bcm963xx_detect_cfe(struct mtd_info *master) | ||
156 | { | ||
157 | int idoffset = 0x4e0; | ||
158 | static char idstring[8] = "CFE1CFE1"; | ||
159 | char buf[9]; | ||
160 | int ret; | ||
161 | size_t retlen; | ||
162 | |||
163 | ret = master->read(master, idoffset, 8, &retlen, (void *)buf); | ||
164 | buf[retlen] = 0; | ||
165 | printk(KERN_INFO PFX "Read Signature value of %s\n", buf); | ||
166 | |||
167 | return strncmp(idstring, buf, 8); | ||
168 | } | ||
169 | |||
170 | static int bcm963xx_probe(struct platform_device *pdev) | ||
171 | { | ||
172 | int err = 0; | ||
173 | int parsed_nr_parts = 0; | ||
174 | char *part_type; | ||
175 | struct resource *r; | ||
176 | |||
177 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
178 | if (!r) { | ||
179 | dev_err(&pdev->dev, "no resource supplied\n"); | ||
180 | return -ENODEV; | ||
181 | } | ||
182 | |||
183 | bcm963xx_map.phys = r->start; | ||
184 | bcm963xx_map.size = resource_size(r); | ||
185 | bcm963xx_map.virt = ioremap(r->start, resource_size(r)); | ||
186 | if (!bcm963xx_map.virt) { | ||
187 | dev_err(&pdev->dev, "failed to ioremap\n"); | ||
188 | return -EIO; | ||
189 | } | ||
190 | |||
191 | dev_info(&pdev->dev, "0x%08lx at 0x%08x\n", | ||
192 | bcm963xx_map.size, bcm963xx_map.phys); | ||
193 | |||
194 | simple_map_init(&bcm963xx_map); | ||
195 | |||
196 | bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map); | ||
197 | if (!bcm963xx_mtd_info) { | ||
198 | dev_err(&pdev->dev, "failed to probe using CFI\n"); | ||
199 | err = -EIO; | ||
200 | goto err_probe; | ||
201 | } | ||
202 | |||
203 | bcm963xx_mtd_info->owner = THIS_MODULE; | ||
204 | |||
205 | /* This is mutually exclusive */ | ||
206 | if (bcm963xx_detect_cfe(bcm963xx_mtd_info) == 0) { | ||
207 | dev_info(&pdev->dev, "CFE bootloader detected\n"); | ||
208 | if (parsed_nr_parts == 0) { | ||
209 | int ret = parse_cfe_partitions(bcm963xx_mtd_info, | ||
210 | &parsed_parts); | ||
211 | if (ret > 0) { | ||
212 | part_type = "CFE"; | ||
213 | parsed_nr_parts = ret; | ||
214 | } | ||
215 | } | ||
216 | } else { | ||
217 | dev_info(&pdev->dev, "unsupported bootloader\n"); | ||
218 | err = -ENODEV; | ||
219 | goto err_probe; | ||
220 | } | ||
221 | |||
222 | return add_mtd_partitions(bcm963xx_mtd_info, parsed_parts, | ||
223 | parsed_nr_parts); | ||
224 | |||
225 | err_probe: | ||
226 | iounmap(bcm963xx_map.virt); | ||
227 | return err; | ||
228 | } | ||
229 | |||
230 | static int bcm963xx_remove(struct platform_device *pdev) | ||
231 | { | ||
232 | if (bcm963xx_mtd_info) { | ||
233 | del_mtd_partitions(bcm963xx_mtd_info); | ||
234 | map_destroy(bcm963xx_mtd_info); | ||
235 | } | ||
236 | |||
237 | if (bcm963xx_map.virt) { | ||
238 | iounmap(bcm963xx_map.virt); | ||
239 | bcm963xx_map.virt = 0; | ||
240 | } | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static struct platform_driver bcm63xx_mtd_dev = { | ||
246 | .probe = bcm963xx_probe, | ||
247 | .remove = bcm963xx_remove, | ||
248 | .driver = { | ||
249 | .name = "bcm963xx-flash", | ||
250 | .owner = THIS_MODULE, | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static int __init bcm963xx_mtd_init(void) | ||
255 | { | ||
256 | return platform_driver_register(&bcm63xx_mtd_dev); | ||
257 | } | ||
258 | |||
259 | static void __exit bcm963xx_mtd_exit(void) | ||
260 | { | ||
261 | platform_driver_unregister(&bcm63xx_mtd_dev); | ||
262 | } | ||
263 | |||
264 | module_init(bcm963xx_mtd_init); | ||
265 | module_exit(bcm963xx_mtd_exit); | ||
266 | |||
267 | MODULE_LICENSE("GPL"); | ||
268 | MODULE_DESCRIPTION("Broadcom BCM63xx MTD driver for CFE and RedBoot"); | ||
269 | MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>"); | ||
270 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | ||
271 | MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>"); | ||
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index 32e89d773b4e..af5707a80205 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c | |||
@@ -208,10 +208,14 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev) | |||
208 | if (!state) | 208 | if (!state) |
209 | return -ENOMEM; | 209 | return -ENOMEM; |
210 | 210 | ||
211 | /* | ||
212 | * We cast start/end to known types in the boards file, so cast | ||
213 | * away their pointer types here to the known types (gpios->xxx). | ||
214 | */ | ||
211 | state->gpio_count = gpios->end; | 215 | state->gpio_count = gpios->end; |
212 | state->gpio_addrs = (void *)gpios->start; | 216 | state->gpio_addrs = (void *)(unsigned long)gpios->start; |
213 | state->gpio_values = (void *)(state + 1); | 217 | state->gpio_values = (void *)(state + 1); |
214 | state->win_size = memory->end - memory->start + 1; | 218 | state->win_size = resource_size(memory); |
215 | memset(state->gpio_values, 0xff, arr_size); | 219 | memset(state->gpio_values, 0xff, arr_size); |
216 | 220 | ||
217 | state->map.name = DRIVER_NAME; | 221 | state->map.name = DRIVER_NAME; |
@@ -221,7 +225,7 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev) | |||
221 | state->map.copy_to = gf_copy_to; | 225 | state->map.copy_to = gf_copy_to; |
222 | state->map.bankwidth = pdata->width; | 226 | state->map.bankwidth = pdata->width; |
223 | state->map.size = state->win_size * (1 << state->gpio_count); | 227 | state->map.size = state->win_size * (1 << state->gpio_count); |
224 | state->map.virt = (void __iomem *)memory->start; | 228 | state->map.virt = ioremap_nocache(memory->start, state->map.size); |
225 | state->map.phys = NO_XIP; | 229 | state->map.phys = NO_XIP; |
226 | state->map.map_priv_1 = (unsigned long)state; | 230 | state->map.map_priv_1 = (unsigned long)state; |
227 | 231 | ||
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 57a1acfe22c4..917022948399 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -640,10 +640,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
640 | } | 640 | } |
641 | dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name); | 641 | dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name); |
642 | return 0; | 642 | return 0; |
643 | |||
644 | dev_err(&dev->p_dev->dev, "CS Error, exiting\n"); | ||
645 | pcmciamtd_release(link); | ||
646 | return -ENODEV; | ||
647 | } | 643 | } |
648 | 644 | ||
649 | 645 | ||
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index ec3edf6e68b4..9861814aa027 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -50,7 +50,7 @@ static int parse_obsolete_partitions(struct platform_device *dev, | |||
50 | { | 50 | { |
51 | int i, plen, nr_parts; | 51 | int i, plen, nr_parts; |
52 | const struct { | 52 | const struct { |
53 | u32 offset, len; | 53 | __be32 offset, len; |
54 | } *part; | 54 | } *part; |
55 | const char *names; | 55 | const char *names; |
56 | 56 | ||
@@ -69,9 +69,9 @@ static int parse_obsolete_partitions(struct platform_device *dev, | |||
69 | names = of_get_property(dp, "partition-names", &plen); | 69 | names = of_get_property(dp, "partition-names", &plen); |
70 | 70 | ||
71 | for (i = 0; i < nr_parts; i++) { | 71 | for (i = 0; i < nr_parts; i++) { |
72 | info->parts[i].offset = part->offset; | 72 | info->parts[i].offset = be32_to_cpu(part->offset); |
73 | info->parts[i].size = part->len & ~1; | 73 | info->parts[i].size = be32_to_cpu(part->len) & ~1; |
74 | if (part->len & 1) /* bit 0 set signifies read only partition */ | 74 | if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */ |
75 | info->parts[i].mask_flags = MTD_WRITEABLE; | 75 | info->parts[i].mask_flags = MTD_WRITEABLE; |
76 | 76 | ||
77 | if (names && (plen > 0)) { | 77 | if (names && (plen > 0)) { |
@@ -226,11 +226,11 @@ static int __devinit of_flash_probe(struct platform_device *dev, | |||
226 | struct resource res; | 226 | struct resource res; |
227 | struct of_flash *info; | 227 | struct of_flash *info; |
228 | const char *probe_type = match->data; | 228 | const char *probe_type = match->data; |
229 | const u32 *width; | 229 | const __be32 *width; |
230 | int err; | 230 | int err; |
231 | int i; | 231 | int i; |
232 | int count; | 232 | int count; |
233 | const u32 *p; | 233 | const __be32 *p; |
234 | int reg_tuple_size; | 234 | int reg_tuple_size; |
235 | struct mtd_info **mtd_list = NULL; | 235 | struct mtd_info **mtd_list = NULL; |
236 | resource_size_t res_size; | 236 | resource_size_t res_size; |
@@ -267,9 +267,11 @@ static int __devinit of_flash_probe(struct platform_device *dev, | |||
267 | for (i = 0; i < count; i++) { | 267 | for (i = 0; i < count; i++) { |
268 | err = -ENXIO; | 268 | err = -ENXIO; |
269 | if (of_address_to_resource(dp, i, &res)) { | 269 | if (of_address_to_resource(dp, i, &res)) { |
270 | dev_err(&dev->dev, "Can't get IO address from device" | 270 | /* |
271 | " tree\n"); | 271 | * Continue with next register tuple if this |
272 | goto err_out; | 272 | * one is not mappable |
273 | */ | ||
274 | continue; | ||
273 | } | 275 | } |
274 | 276 | ||
275 | dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n", | 277 | dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n", |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 50ab431b24eb..cb20c67995d8 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -37,7 +37,6 @@ | |||
37 | 37 | ||
38 | #include "mtdcore.h" | 38 | #include "mtdcore.h" |
39 | 39 | ||
40 | static DEFINE_MUTEX(mtd_blkdevs_mutex); | ||
41 | static LIST_HEAD(blktrans_majors); | 40 | static LIST_HEAD(blktrans_majors); |
42 | static DEFINE_MUTEX(blktrans_ref_mutex); | 41 | static DEFINE_MUTEX(blktrans_ref_mutex); |
43 | 42 | ||
@@ -133,6 +132,10 @@ static int mtd_blktrans_thread(void *arg) | |||
133 | 132 | ||
134 | if (!req && !(req = blk_fetch_request(rq))) { | 133 | if (!req && !(req = blk_fetch_request(rq))) { |
135 | set_current_state(TASK_INTERRUPTIBLE); | 134 | set_current_state(TASK_INTERRUPTIBLE); |
135 | |||
136 | if (kthread_should_stop()) | ||
137 | set_current_state(TASK_RUNNING); | ||
138 | |||
136 | spin_unlock_irq(rq->queue_lock); | 139 | spin_unlock_irq(rq->queue_lock); |
137 | schedule(); | 140 | schedule(); |
138 | spin_lock_irq(rq->queue_lock); | 141 | spin_lock_irq(rq->queue_lock); |
@@ -176,54 +179,53 @@ static void mtd_blktrans_request(struct request_queue *rq) | |||
176 | static int blktrans_open(struct block_device *bdev, fmode_t mode) | 179 | static int blktrans_open(struct block_device *bdev, fmode_t mode) |
177 | { | 180 | { |
178 | struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); | 181 | struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); |
179 | int ret; | 182 | int ret = 0; |
180 | 183 | ||
181 | if (!dev) | 184 | if (!dev) |
182 | return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ | 185 | return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ |
183 | 186 | ||
184 | mutex_lock(&mtd_blkdevs_mutex); | ||
185 | mutex_lock(&dev->lock); | 187 | mutex_lock(&dev->lock); |
186 | 188 | ||
187 | if (!dev->mtd) { | 189 | if (dev->open++) |
188 | ret = -ENXIO; | ||
189 | goto unlock; | 190 | goto unlock; |
190 | } | ||
191 | 191 | ||
192 | ret = !dev->open++ && dev->tr->open ? dev->tr->open(dev) : 0; | 192 | kref_get(&dev->ref); |
193 | __module_get(dev->tr->owner); | ||
194 | |||
195 | if (dev->mtd) { | ||
196 | ret = dev->tr->open ? dev->tr->open(dev) : 0; | ||
197 | __get_mtd_device(dev->mtd); | ||
198 | } | ||
193 | 199 | ||
194 | /* Take another reference on the device so it won't go away till | ||
195 | last release */ | ||
196 | if (!ret) | ||
197 | kref_get(&dev->ref); | ||
198 | unlock: | 200 | unlock: |
199 | mutex_unlock(&dev->lock); | 201 | mutex_unlock(&dev->lock); |
200 | blktrans_dev_put(dev); | 202 | blktrans_dev_put(dev); |
201 | mutex_unlock(&mtd_blkdevs_mutex); | ||
202 | return ret; | 203 | return ret; |
203 | } | 204 | } |
204 | 205 | ||
205 | static int blktrans_release(struct gendisk *disk, fmode_t mode) | 206 | static int blktrans_release(struct gendisk *disk, fmode_t mode) |
206 | { | 207 | { |
207 | struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); | 208 | struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); |
208 | int ret = -ENXIO; | 209 | int ret = 0; |
209 | 210 | ||
210 | if (!dev) | 211 | if (!dev) |
211 | return ret; | 212 | return ret; |
212 | 213 | ||
213 | mutex_lock(&mtd_blkdevs_mutex); | ||
214 | mutex_lock(&dev->lock); | 214 | mutex_lock(&dev->lock); |
215 | 215 | ||
216 | /* Release one reference, we sure its not the last one here*/ | 216 | if (--dev->open) |
217 | kref_put(&dev->ref, blktrans_dev_release); | ||
218 | |||
219 | if (!dev->mtd) | ||
220 | goto unlock; | 217 | goto unlock; |
221 | 218 | ||
222 | ret = !--dev->open && dev->tr->release ? dev->tr->release(dev) : 0; | 219 | kref_put(&dev->ref, blktrans_dev_release); |
220 | module_put(dev->tr->owner); | ||
221 | |||
222 | if (dev->mtd) { | ||
223 | ret = dev->tr->release ? dev->tr->release(dev) : 0; | ||
224 | __put_mtd_device(dev->mtd); | ||
225 | } | ||
223 | unlock: | 226 | unlock: |
224 | mutex_unlock(&dev->lock); | 227 | mutex_unlock(&dev->lock); |
225 | blktrans_dev_put(dev); | 228 | blktrans_dev_put(dev); |
226 | mutex_unlock(&mtd_blkdevs_mutex); | ||
227 | return ret; | 229 | return ret; |
228 | } | 230 | } |
229 | 231 | ||
@@ -256,7 +258,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, | |||
256 | if (!dev) | 258 | if (!dev) |
257 | return ret; | 259 | return ret; |
258 | 260 | ||
259 | mutex_lock(&mtd_blkdevs_mutex); | ||
260 | mutex_lock(&dev->lock); | 261 | mutex_lock(&dev->lock); |
261 | 262 | ||
262 | if (!dev->mtd) | 263 | if (!dev->mtd) |
@@ -271,7 +272,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, | |||
271 | } | 272 | } |
272 | unlock: | 273 | unlock: |
273 | mutex_unlock(&dev->lock); | 274 | mutex_unlock(&dev->lock); |
274 | mutex_unlock(&mtd_blkdevs_mutex); | ||
275 | blktrans_dev_put(dev); | 275 | blktrans_dev_put(dev); |
276 | return ret; | 276 | return ret; |
277 | } | 277 | } |
@@ -385,9 +385,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
385 | 385 | ||
386 | gd->queue = new->rq; | 386 | gd->queue = new->rq; |
387 | 387 | ||
388 | __get_mtd_device(new->mtd); | ||
389 | __module_get(tr->owner); | ||
390 | |||
391 | /* Create processing thread */ | 388 | /* Create processing thread */ |
392 | /* TODO: workqueue ? */ | 389 | /* TODO: workqueue ? */ |
393 | new->thread = kthread_run(mtd_blktrans_thread, new, | 390 | new->thread = kthread_run(mtd_blktrans_thread, new, |
@@ -410,8 +407,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
410 | } | 407 | } |
411 | return 0; | 408 | return 0; |
412 | error4: | 409 | error4: |
413 | module_put(tr->owner); | ||
414 | __put_mtd_device(new->mtd); | ||
415 | blk_cleanup_queue(new->rq); | 410 | blk_cleanup_queue(new->rq); |
416 | error3: | 411 | error3: |
417 | put_disk(new->disk); | 412 | put_disk(new->disk); |
@@ -448,17 +443,15 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) | |||
448 | blk_start_queue(old->rq); | 443 | blk_start_queue(old->rq); |
449 | spin_unlock_irqrestore(&old->queue_lock, flags); | 444 | spin_unlock_irqrestore(&old->queue_lock, flags); |
450 | 445 | ||
451 | /* Ask trans driver for release to the mtd device */ | 446 | /* If the device is currently open, tell trans driver to close it, |
447 | then put mtd device, and don't touch it again */ | ||
452 | mutex_lock(&old->lock); | 448 | mutex_lock(&old->lock); |
453 | if (old->open && old->tr->release) { | 449 | if (old->open) { |
454 | old->tr->release(old); | 450 | if (old->tr->release) |
455 | old->open = 0; | 451 | old->tr->release(old); |
452 | __put_mtd_device(old->mtd); | ||
456 | } | 453 | } |
457 | 454 | ||
458 | __put_mtd_device(old->mtd); | ||
459 | module_put(old->tr->owner); | ||
460 | |||
461 | /* At that point, we don't touch the mtd anymore */ | ||
462 | old->mtd = NULL; | 455 | old->mtd = NULL; |
463 | 456 | ||
464 | mutex_unlock(&old->lock); | 457 | mutex_unlock(&old->lock); |
@@ -508,13 +501,16 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
508 | mutex_lock(&mtd_table_mutex); | 501 | mutex_lock(&mtd_table_mutex); |
509 | 502 | ||
510 | ret = register_blkdev(tr->major, tr->name); | 503 | ret = register_blkdev(tr->major, tr->name); |
511 | if (ret) { | 504 | if (ret < 0) { |
512 | printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", | 505 | printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", |
513 | tr->name, tr->major, ret); | 506 | tr->name, tr->major, ret); |
514 | mutex_unlock(&mtd_table_mutex); | 507 | mutex_unlock(&mtd_table_mutex); |
515 | return ret; | 508 | return ret; |
516 | } | 509 | } |
517 | 510 | ||
511 | if (ret) | ||
512 | tr->major = ret; | ||
513 | |||
518 | tr->blkshift = ffs(tr->blksize) - 1; | 514 | tr->blkshift = ffs(tr->blksize) - 1; |
519 | 515 | ||
520 | INIT_LIST_HEAD(&tr->devs); | 516 | INIT_LIST_HEAD(&tr->devs); |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index a34a0fe14884..4759d827e8c7 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -30,8 +30,9 @@ | |||
30 | #include <linux/backing-dev.h> | 30 | #include <linux/backing-dev.h> |
31 | #include <linux/compat.h> | 31 | #include <linux/compat.h> |
32 | #include <linux/mount.h> | 32 | #include <linux/mount.h> |
33 | 33 | #include <linux/blkpg.h> | |
34 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
35 | #include <linux/mtd/partitions.h> | ||
35 | #include <linux/mtd/map.h> | 36 | #include <linux/mtd/map.h> |
36 | 37 | ||
37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
@@ -478,6 +479,78 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, | |||
478 | return ret; | 479 | return ret; |
479 | } | 480 | } |
480 | 481 | ||
482 | /* | ||
483 | * Copies (and truncates, if necessary) data from the larger struct, | ||
484 | * nand_ecclayout, to the smaller, deprecated layout struct, | ||
485 | * nand_ecclayout_user. This is necessary only to suppport the deprecated | ||
486 | * API ioctl ECCGETLAYOUT while allowing all new functionality to use | ||
487 | * nand_ecclayout flexibly (i.e. the struct may change size in new | ||
488 | * releases without requiring major rewrites). | ||
489 | */ | ||
490 | static int shrink_ecclayout(const struct nand_ecclayout *from, | ||
491 | struct nand_ecclayout_user *to) | ||
492 | { | ||
493 | int i; | ||
494 | |||
495 | if (!from || !to) | ||
496 | return -EINVAL; | ||
497 | |||
498 | memset(to, 0, sizeof(*to)); | ||
499 | |||
500 | to->eccbytes = min((int)from->eccbytes, MTD_MAX_ECCPOS_ENTRIES); | ||
501 | for (i = 0; i < to->eccbytes; i++) | ||
502 | to->eccpos[i] = from->eccpos[i]; | ||
503 | |||
504 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { | ||
505 | if (from->oobfree[i].length == 0 && | ||
506 | from->oobfree[i].offset == 0) | ||
507 | break; | ||
508 | to->oobavail += from->oobfree[i].length; | ||
509 | to->oobfree[i] = from->oobfree[i]; | ||
510 | } | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | #ifdef CONFIG_MTD_PARTITIONS | ||
516 | static int mtd_blkpg_ioctl(struct mtd_info *mtd, | ||
517 | struct blkpg_ioctl_arg __user *arg) | ||
518 | { | ||
519 | struct blkpg_ioctl_arg a; | ||
520 | struct blkpg_partition p; | ||
521 | |||
522 | if (!capable(CAP_SYS_ADMIN)) | ||
523 | return -EPERM; | ||
524 | |||
525 | /* Only master mtd device must be used to control partitions */ | ||
526 | if (!mtd_is_master(mtd)) | ||
527 | return -EINVAL; | ||
528 | |||
529 | if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) | ||
530 | return -EFAULT; | ||
531 | |||
532 | if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) | ||
533 | return -EFAULT; | ||
534 | |||
535 | switch (a.op) { | ||
536 | case BLKPG_ADD_PARTITION: | ||
537 | |||
538 | return mtd_add_partition(mtd, p.devname, p.start, p.length); | ||
539 | |||
540 | case BLKPG_DEL_PARTITION: | ||
541 | |||
542 | if (p.pno < 0) | ||
543 | return -EINVAL; | ||
544 | |||
545 | return mtd_del_partition(mtd, p.pno); | ||
546 | |||
547 | default: | ||
548 | return -EINVAL; | ||
549 | } | ||
550 | } | ||
551 | #endif | ||
552 | |||
553 | |||
481 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | 554 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) |
482 | { | 555 | { |
483 | struct mtd_file_info *mfi = file->private_data; | 556 | struct mtd_file_info *mfi = file->private_data; |
@@ -514,6 +587,9 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
514 | if (get_user(ur_idx, &(ur->regionindex))) | 587 | if (get_user(ur_idx, &(ur->regionindex))) |
515 | return -EFAULT; | 588 | return -EFAULT; |
516 | 589 | ||
590 | if (ur_idx >= mtd->numeraseregions) | ||
591 | return -EINVAL; | ||
592 | |||
517 | kr = &(mtd->eraseregions[ur_idx]); | 593 | kr = &(mtd->eraseregions[ur_idx]); |
518 | 594 | ||
519 | if (put_user(kr->offset, &(ur->offset)) | 595 | if (put_user(kr->offset, &(ur->offset)) |
@@ -813,14 +889,23 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
813 | } | 889 | } |
814 | #endif | 890 | #endif |
815 | 891 | ||
892 | /* This ioctl is being deprecated - it truncates the ecc layout */ | ||
816 | case ECCGETLAYOUT: | 893 | case ECCGETLAYOUT: |
817 | { | 894 | { |
895 | struct nand_ecclayout_user *usrlay; | ||
896 | |||
818 | if (!mtd->ecclayout) | 897 | if (!mtd->ecclayout) |
819 | return -EOPNOTSUPP; | 898 | return -EOPNOTSUPP; |
820 | 899 | ||
821 | if (copy_to_user(argp, mtd->ecclayout, | 900 | usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL); |
822 | sizeof(struct nand_ecclayout))) | 901 | if (!usrlay) |
823 | return -EFAULT; | 902 | return -ENOMEM; |
903 | |||
904 | shrink_ecclayout(mtd->ecclayout, usrlay); | ||
905 | |||
906 | if (copy_to_user(argp, usrlay, sizeof(*usrlay))) | ||
907 | ret = -EFAULT; | ||
908 | kfree(usrlay); | ||
824 | break; | 909 | break; |
825 | } | 910 | } |
826 | 911 | ||
@@ -856,6 +941,22 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
856 | break; | 941 | break; |
857 | } | 942 | } |
858 | 943 | ||
944 | #ifdef CONFIG_MTD_PARTITIONS | ||
945 | case BLKPG: | ||
946 | { | ||
947 | ret = mtd_blkpg_ioctl(mtd, | ||
948 | (struct blkpg_ioctl_arg __user *)arg); | ||
949 | break; | ||
950 | } | ||
951 | |||
952 | case BLKRRPART: | ||
953 | { | ||
954 | /* No reread partition feature. Just return ok */ | ||
955 | ret = 0; | ||
956 | break; | ||
957 | } | ||
958 | #endif | ||
959 | |||
859 | default: | 960 | default: |
860 | ret = -ENOTTY; | 961 | ret = -ENOTTY; |
861 | } | 962 | } |
@@ -1033,7 +1134,7 @@ static const struct file_operations mtd_fops = { | |||
1033 | static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, | 1134 | static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, |
1034 | int flags, const char *dev_name, void *data) | 1135 | int flags, const char *dev_name, void *data) |
1035 | { | 1136 | { |
1036 | return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC); | 1137 | return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC); |
1037 | } | 1138 | } |
1038 | 1139 | ||
1039 | static struct file_system_type mtd_inodefs_type = { | 1140 | static struct file_system_type mtd_inodefs_type = { |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index dc6558568876..79e3689f1e16 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -29,9 +29,11 @@ | |||
29 | #include <linux/kmod.h> | 29 | #include <linux/kmod.h> |
30 | #include <linux/mtd/mtd.h> | 30 | #include <linux/mtd/mtd.h> |
31 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
32 | #include <linux/err.h> | ||
32 | 33 | ||
33 | /* Our partition linked list */ | 34 | /* Our partition linked list */ |
34 | static LIST_HEAD(mtd_partitions); | 35 | static LIST_HEAD(mtd_partitions); |
36 | static DEFINE_MUTEX(mtd_partitions_mutex); | ||
35 | 37 | ||
36 | /* Our partition node structure */ | 38 | /* Our partition node structure */ |
37 | struct mtd_part { | 39 | struct mtd_part { |
@@ -326,6 +328,12 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
326 | return res; | 328 | return res; |
327 | } | 329 | } |
328 | 330 | ||
331 | static inline void free_partition(struct mtd_part *p) | ||
332 | { | ||
333 | kfree(p->mtd.name); | ||
334 | kfree(p); | ||
335 | } | ||
336 | |||
329 | /* | 337 | /* |
330 | * This function unregisters and destroy all slave MTD objects which are | 338 | * This function unregisters and destroy all slave MTD objects which are |
331 | * attached to the given master MTD object. | 339 | * attached to the given master MTD object. |
@@ -334,33 +342,42 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
334 | int del_mtd_partitions(struct mtd_info *master) | 342 | int del_mtd_partitions(struct mtd_info *master) |
335 | { | 343 | { |
336 | struct mtd_part *slave, *next; | 344 | struct mtd_part *slave, *next; |
345 | int ret, err = 0; | ||
337 | 346 | ||
347 | mutex_lock(&mtd_partitions_mutex); | ||
338 | list_for_each_entry_safe(slave, next, &mtd_partitions, list) | 348 | list_for_each_entry_safe(slave, next, &mtd_partitions, list) |
339 | if (slave->master == master) { | 349 | if (slave->master == master) { |
350 | ret = del_mtd_device(&slave->mtd); | ||
351 | if (ret < 0) { | ||
352 | err = ret; | ||
353 | continue; | ||
354 | } | ||
340 | list_del(&slave->list); | 355 | list_del(&slave->list); |
341 | del_mtd_device(&slave->mtd); | 356 | free_partition(slave); |
342 | kfree(slave); | ||
343 | } | 357 | } |
358 | mutex_unlock(&mtd_partitions_mutex); | ||
344 | 359 | ||
345 | return 0; | 360 | return err; |
346 | } | 361 | } |
347 | EXPORT_SYMBOL(del_mtd_partitions); | 362 | EXPORT_SYMBOL(del_mtd_partitions); |
348 | 363 | ||
349 | static struct mtd_part *add_one_partition(struct mtd_info *master, | 364 | static struct mtd_part *allocate_partition(struct mtd_info *master, |
350 | const struct mtd_partition *part, int partno, | 365 | const struct mtd_partition *part, int partno, |
351 | uint64_t cur_offset) | 366 | uint64_t cur_offset) |
352 | { | 367 | { |
353 | struct mtd_part *slave; | 368 | struct mtd_part *slave; |
369 | char *name; | ||
354 | 370 | ||
355 | /* allocate the partition structure */ | 371 | /* allocate the partition structure */ |
356 | slave = kzalloc(sizeof(*slave), GFP_KERNEL); | 372 | slave = kzalloc(sizeof(*slave), GFP_KERNEL); |
357 | if (!slave) { | 373 | name = kstrdup(part->name, GFP_KERNEL); |
374 | if (!name || !slave) { | ||
358 | printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", | 375 | printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", |
359 | master->name); | 376 | master->name); |
360 | del_mtd_partitions(master); | 377 | kfree(name); |
361 | return NULL; | 378 | kfree(slave); |
379 | return ERR_PTR(-ENOMEM); | ||
362 | } | 380 | } |
363 | list_add(&slave->list, &mtd_partitions); | ||
364 | 381 | ||
365 | /* set up the MTD object for this partition */ | 382 | /* set up the MTD object for this partition */ |
366 | slave->mtd.type = master->type; | 383 | slave->mtd.type = master->type; |
@@ -371,7 +388,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, | |||
371 | slave->mtd.oobavail = master->oobavail; | 388 | slave->mtd.oobavail = master->oobavail; |
372 | slave->mtd.subpage_sft = master->subpage_sft; | 389 | slave->mtd.subpage_sft = master->subpage_sft; |
373 | 390 | ||
374 | slave->mtd.name = part->name; | 391 | slave->mtd.name = name; |
375 | slave->mtd.owner = master->owner; | 392 | slave->mtd.owner = master->owner; |
376 | slave->mtd.backing_dev_info = master->backing_dev_info; | 393 | slave->mtd.backing_dev_info = master->backing_dev_info; |
377 | 394 | ||
@@ -518,12 +535,89 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, | |||
518 | } | 535 | } |
519 | 536 | ||
520 | out_register: | 537 | out_register: |
521 | /* register our partition */ | ||
522 | add_mtd_device(&slave->mtd); | ||
523 | |||
524 | return slave; | 538 | return slave; |
525 | } | 539 | } |
526 | 540 | ||
541 | int mtd_add_partition(struct mtd_info *master, char *name, | ||
542 | long long offset, long long length) | ||
543 | { | ||
544 | struct mtd_partition part; | ||
545 | struct mtd_part *p, *new; | ||
546 | uint64_t start, end; | ||
547 | int ret = 0; | ||
548 | |||
549 | /* the direct offset is expected */ | ||
550 | if (offset == MTDPART_OFS_APPEND || | ||
551 | offset == MTDPART_OFS_NXTBLK) | ||
552 | return -EINVAL; | ||
553 | |||
554 | if (length == MTDPART_SIZ_FULL) | ||
555 | length = master->size - offset; | ||
556 | |||
557 | if (length <= 0) | ||
558 | return -EINVAL; | ||
559 | |||
560 | part.name = name; | ||
561 | part.size = length; | ||
562 | part.offset = offset; | ||
563 | part.mask_flags = 0; | ||
564 | part.ecclayout = NULL; | ||
565 | |||
566 | new = allocate_partition(master, &part, -1, offset); | ||
567 | if (IS_ERR(new)) | ||
568 | return PTR_ERR(new); | ||
569 | |||
570 | start = offset; | ||
571 | end = offset + length; | ||
572 | |||
573 | mutex_lock(&mtd_partitions_mutex); | ||
574 | list_for_each_entry(p, &mtd_partitions, list) | ||
575 | if (p->master == master) { | ||
576 | if ((start >= p->offset) && | ||
577 | (start < (p->offset + p->mtd.size))) | ||
578 | goto err_inv; | ||
579 | |||
580 | if ((end >= p->offset) && | ||
581 | (end < (p->offset + p->mtd.size))) | ||
582 | goto err_inv; | ||
583 | } | ||
584 | |||
585 | list_add(&new->list, &mtd_partitions); | ||
586 | mutex_unlock(&mtd_partitions_mutex); | ||
587 | |||
588 | add_mtd_device(&new->mtd); | ||
589 | |||
590 | return ret; | ||
591 | err_inv: | ||
592 | mutex_unlock(&mtd_partitions_mutex); | ||
593 | free_partition(new); | ||
594 | return -EINVAL; | ||
595 | } | ||
596 | EXPORT_SYMBOL_GPL(mtd_add_partition); | ||
597 | |||
598 | int mtd_del_partition(struct mtd_info *master, int partno) | ||
599 | { | ||
600 | struct mtd_part *slave, *next; | ||
601 | int ret = -EINVAL; | ||
602 | |||
603 | mutex_lock(&mtd_partitions_mutex); | ||
604 | list_for_each_entry_safe(slave, next, &mtd_partitions, list) | ||
605 | if ((slave->master == master) && | ||
606 | (slave->mtd.index == partno)) { | ||
607 | ret = del_mtd_device(&slave->mtd); | ||
608 | if (ret < 0) | ||
609 | break; | ||
610 | |||
611 | list_del(&slave->list); | ||
612 | free_partition(slave); | ||
613 | break; | ||
614 | } | ||
615 | mutex_unlock(&mtd_partitions_mutex); | ||
616 | |||
617 | return ret; | ||
618 | } | ||
619 | EXPORT_SYMBOL_GPL(mtd_del_partition); | ||
620 | |||
527 | /* | 621 | /* |
528 | * This function, given a master MTD object and a partition table, creates | 622 | * This function, given a master MTD object and a partition table, creates |
529 | * and registers slave MTD objects which are bound to the master according to | 623 | * and registers slave MTD objects which are bound to the master according to |
@@ -544,9 +638,16 @@ int add_mtd_partitions(struct mtd_info *master, | |||
544 | printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); | 638 | printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); |
545 | 639 | ||
546 | for (i = 0; i < nbparts; i++) { | 640 | for (i = 0; i < nbparts; i++) { |
547 | slave = add_one_partition(master, parts + i, i, cur_offset); | 641 | slave = allocate_partition(master, parts + i, i, cur_offset); |
548 | if (!slave) | 642 | if (IS_ERR(slave)) |
549 | return -ENOMEM; | 643 | return PTR_ERR(slave); |
644 | |||
645 | mutex_lock(&mtd_partitions_mutex); | ||
646 | list_add(&slave->list, &mtd_partitions); | ||
647 | mutex_unlock(&mtd_partitions_mutex); | ||
648 | |||
649 | add_mtd_device(&slave->mtd); | ||
650 | |||
550 | cur_offset = slave->offset + slave->mtd.size; | 651 | cur_offset = slave->offset + slave->mtd.size; |
551 | } | 652 | } |
552 | 653 | ||
@@ -618,3 +719,20 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, | |||
618 | return ret; | 719 | return ret; |
619 | } | 720 | } |
620 | EXPORT_SYMBOL_GPL(parse_mtd_partitions); | 721 | EXPORT_SYMBOL_GPL(parse_mtd_partitions); |
722 | |||
723 | int mtd_is_master(struct mtd_info *mtd) | ||
724 | { | ||
725 | struct mtd_part *part; | ||
726 | int nopart = 0; | ||
727 | |||
728 | mutex_lock(&mtd_partitions_mutex); | ||
729 | list_for_each_entry(part, &mtd_partitions, list) | ||
730 | if (&part->mtd == mtd) { | ||
731 | nopart = 1; | ||
732 | break; | ||
733 | } | ||
734 | mutex_unlock(&mtd_partitions_mutex); | ||
735 | |||
736 | return nopart; | ||
737 | } | ||
738 | EXPORT_SYMBOL_GPL(mtd_is_master); | ||
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 8b4b67c8a391..8229802b4346 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -400,13 +400,6 @@ config MTD_NAND_PXA3xx | |||
400 | This enables the driver for the NAND flash device found on | 400 | This enables the driver for the NAND flash device found on |
401 | PXA3xx processors | 401 | PXA3xx processors |
402 | 402 | ||
403 | config MTD_NAND_PXA3xx_BUILTIN | ||
404 | bool "Use builtin definitions for some NAND chips (deprecated)" | ||
405 | depends on MTD_NAND_PXA3xx | ||
406 | help | ||
407 | This enables builtin definitions for some NAND chips. This | ||
408 | is deprecated in favor of platform specific data. | ||
409 | |||
410 | config MTD_NAND_CM_X270 | 403 | config MTD_NAND_CM_X270 |
411 | tristate "Support for NAND Flash on CM-X270 modules" | 404 | tristate "Support for NAND Flash on CM-X270 modules" |
412 | depends on MACH_ARMCORE | 405 | depends on MACH_ARMCORE |
@@ -458,6 +451,7 @@ config MTD_NAND_ORION | |||
458 | config MTD_NAND_FSL_ELBC | 451 | config MTD_NAND_FSL_ELBC |
459 | tristate "NAND support for Freescale eLBC controllers" | 452 | tristate "NAND support for Freescale eLBC controllers" |
460 | depends on PPC_OF | 453 | depends on PPC_OF |
454 | select FSL_LBC | ||
461 | help | 455 | help |
462 | Various Freescale chips, including the 8313, include a NAND Flash | 456 | Various Freescale chips, including the 8313, include a NAND Flash |
463 | Controller Module with built-in hardware ECC capabilities. | 457 | Controller Module with built-in hardware ECC capabilities. |
@@ -531,4 +525,11 @@ config MTD_NAND_JZ4740 | |||
531 | help | 525 | help |
532 | Enables support for NAND Flash on JZ4740 SoC based boards. | 526 | Enables support for NAND Flash on JZ4740 SoC based boards. |
533 | 527 | ||
528 | config MTD_NAND_FSMC | ||
529 | tristate "Support for NAND on ST Micros FSMC" | ||
530 | depends on PLAT_SPEAR || PLAT_NOMADIK || MACH_U300 | ||
531 | help | ||
532 | Enables support for NAND Flash chips on the ST Microelectronics | ||
533 | Flexible Static Memory Controller (FSMC) | ||
534 | |||
534 | endif # MTD_NAND | 535 | endif # MTD_NAND |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index ac83dcdac5d6..8ad6faec72cb 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o | |||
19 | obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o | 19 | obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o |
20 | obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o | 20 | obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o |
21 | obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o | 21 | obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o |
22 | obj-$(CONFIG_MTD_NAND_FSMC) += fsmc_nand.o | ||
22 | obj-$(CONFIG_MTD_NAND_H1900) += h1910.o | 23 | obj-$(CONFIG_MTD_NAND_H1900) += h1910.o |
23 | obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o | 24 | obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o |
24 | obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o | 25 | obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 6fbeefa3a766..79947bea4d57 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -110,15 +110,6 @@ static const unsigned short bfin_nfc_pin_req[] = | |||
110 | 0}; | 110 | 0}; |
111 | 111 | ||
112 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC | 112 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC |
113 | static uint8_t bbt_pattern[] = { 0xff }; | ||
114 | |||
115 | static struct nand_bbt_descr bootrom_bbt = { | ||
116 | .options = 0, | ||
117 | .offs = 63, | ||
118 | .len = 1, | ||
119 | .pattern = bbt_pattern, | ||
120 | }; | ||
121 | |||
122 | static struct nand_ecclayout bootrom_ecclayout = { | 113 | static struct nand_ecclayout bootrom_ecclayout = { |
123 | .eccbytes = 24, | 114 | .eccbytes = 24, |
124 | .eccpos = { | 115 | .eccpos = { |
@@ -809,7 +800,6 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) | |||
809 | /* setup hardware ECC data struct */ | 800 | /* setup hardware ECC data struct */ |
810 | if (hardware_ecc) { | 801 | if (hardware_ecc) { |
811 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC | 802 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC |
812 | chip->badblock_pattern = &bootrom_bbt; | ||
813 | chip->ecc.layout = &bootrom_ecclayout; | 803 | chip->ecc.layout = &bootrom_ecclayout; |
814 | #endif | 804 | #endif |
815 | chip->read_buf = bf5xx_nand_dma_read_buf; | 805 | chip->read_buf = bf5xx_nand_dma_read_buf; |
@@ -830,6 +820,10 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) | |||
830 | goto out_err_nand_scan; | 820 | goto out_err_nand_scan; |
831 | } | 821 | } |
832 | 822 | ||
823 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC | ||
824 | chip->badblockpos = 63; | ||
825 | #endif | ||
826 | |||
833 | /* add NAND partition */ | 827 | /* add NAND partition */ |
834 | bf5xx_nand_add_partition(info); | 828 | bf5xx_nand_add_partition(info); |
835 | 829 | ||
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 8beb0d0233b5..a90fde3ede28 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -316,7 +316,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd, | |||
316 | u32 syndrome[4]; | 316 | u32 syndrome[4]; |
317 | u32 ecc_state; | 317 | u32 ecc_state; |
318 | unsigned num_errors, corrected; | 318 | unsigned num_errors, corrected; |
319 | unsigned long timeo = jiffies + msecs_to_jiffies(100); | 319 | unsigned long timeo; |
320 | 320 | ||
321 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ | 321 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ |
322 | for (i = 0; i < 10; i++) { | 322 | for (i = 0; i < 10; i++) { |
@@ -372,9 +372,11 @@ compare: | |||
372 | * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately | 372 | * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately |
373 | * begin trying to poll for the state, you may fall right out of your | 373 | * begin trying to poll for the state, you may fall right out of your |
374 | * loop without any of the correction calculations having taken place. | 374 | * loop without any of the correction calculations having taken place. |
375 | * The recommendation from the hardware team is to wait till ECC_STATE | 375 | * The recommendation from the hardware team is to initially delay as |
376 | * reads less than 4, which means ECC HW has entered correction state. | 376 | * long as ECC_STATE reads less than 4. After that, ECC HW has entered |
377 | * correction state. | ||
377 | */ | 378 | */ |
379 | timeo = jiffies + usecs_to_jiffies(100); | ||
378 | do { | 380 | do { |
379 | ecc_state = (davinci_nand_readl(info, | 381 | ecc_state = (davinci_nand_readl(info, |
380 | NANDFSR_OFFSET) >> 8) & 0x0f; | 382 | NANDFSR_OFFSET) >> 8) & 0x0f; |
@@ -733,6 +735,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
733 | * breaks userspace ioctl interface with mtd-utils. Once we | 735 | * breaks userspace ioctl interface with mtd-utils. Once we |
734 | * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used | 736 | * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used |
735 | * for the 4KiB page chips. | 737 | * for the 4KiB page chips. |
738 | * | ||
739 | * TODO: Note that nand_ecclayout has now been expanded and can | ||
740 | * hold plenty of OOB entries. | ||
736 | */ | 741 | */ |
737 | dev_warn(&pdev->dev, "no 4-bit ECC support yet " | 742 | dev_warn(&pdev->dev, "no 4-bit ECC support yet " |
738 | "for 4KiB-page NAND\n"); | 743 | "for 4KiB-page NAND\n"); |
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 532fe07cf886..8c8d3c86c0e8 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -1292,6 +1292,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1292 | read_status(denali); | 1292 | read_status(denali); |
1293 | break; | 1293 | break; |
1294 | case NAND_CMD_READID: | 1294 | case NAND_CMD_READID: |
1295 | case NAND_CMD_PARAM: | ||
1295 | reset_buf(denali); | 1296 | reset_buf(denali); |
1296 | /*sometimes ManufactureId read from register is not right | 1297 | /*sometimes ManufactureId read from register is not right |
1297 | * e.g. some of Micron MT29F32G08QAA MLC NAND chips | 1298 | * e.g. some of Micron MT29F32G08QAA MLC NAND chips |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 80de0bff6c3a..c141b07b25d1 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -1,9 +1,11 @@ | |||
1 | /* Freescale Enhanced Local Bus Controller NAND driver | 1 | /* Freescale Enhanced Local Bus Controller NAND driver |
2 | * | 2 | * |
3 | * Copyright (c) 2006-2007 Freescale Semiconductor | 3 | * Copyright © 2006-2007, 2010 Freescale Semiconductor |
4 | * | 4 | * |
5 | * Authors: Nick Spence <nick.spence@freescale.com>, | 5 | * Authors: Nick Spence <nick.spence@freescale.com>, |
6 | * Scott Wood <scottwood@freescale.com> | 6 | * Scott Wood <scottwood@freescale.com> |
7 | * Jack Lan <jack.lan@freescale.com> | ||
8 | * Roy Zang <tie-fei.zang@freescale.com> | ||
7 | * | 9 | * |
8 | * This program is free software; you can redistribute it and/or modify | 10 | * 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 | 11 | * it under the terms of the GNU General Public License as published by |
@@ -27,6 +29,7 @@ | |||
27 | #include <linux/string.h> | 29 | #include <linux/string.h> |
28 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
29 | #include <linux/of_platform.h> | 31 | #include <linux/of_platform.h> |
32 | #include <linux/platform_device.h> | ||
30 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
31 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
32 | 35 | ||
@@ -42,14 +45,12 @@ | |||
42 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ | 45 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ |
43 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ | 46 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ |
44 | 47 | ||
45 | struct fsl_elbc_ctrl; | ||
46 | |||
47 | /* mtd information per set */ | 48 | /* mtd information per set */ |
48 | 49 | ||
49 | struct fsl_elbc_mtd { | 50 | struct fsl_elbc_mtd { |
50 | struct mtd_info mtd; | 51 | struct mtd_info mtd; |
51 | struct nand_chip chip; | 52 | struct nand_chip chip; |
52 | struct fsl_elbc_ctrl *ctrl; | 53 | struct fsl_lbc_ctrl *ctrl; |
53 | 54 | ||
54 | struct device *dev; | 55 | struct device *dev; |
55 | int bank; /* Chip select bank number */ | 56 | int bank; /* Chip select bank number */ |
@@ -58,18 +59,12 @@ struct fsl_elbc_mtd { | |||
58 | unsigned int fmr; /* FCM Flash Mode Register value */ | 59 | unsigned int fmr; /* FCM Flash Mode Register value */ |
59 | }; | 60 | }; |
60 | 61 | ||
61 | /* overview of the fsl elbc controller */ | 62 | /* Freescale eLBC FCM controller infomation */ |
62 | 63 | ||
63 | struct fsl_elbc_ctrl { | 64 | struct fsl_elbc_fcm_ctrl { |
64 | struct nand_hw_control controller; | 65 | struct nand_hw_control controller; |
65 | struct fsl_elbc_mtd *chips[MAX_BANKS]; | 66 | struct fsl_elbc_mtd *chips[MAX_BANKS]; |
66 | 67 | ||
67 | /* device info */ | ||
68 | struct device *dev; | ||
69 | struct fsl_lbc_regs __iomem *regs; | ||
70 | int irq; | ||
71 | wait_queue_head_t irq_wait; | ||
72 | unsigned int irq_status; /* status read from LTESR by irq handler */ | ||
73 | u8 __iomem *addr; /* Address of assigned FCM buffer */ | 68 | u8 __iomem *addr; /* Address of assigned FCM buffer */ |
74 | unsigned int page; /* Last page written to / read from */ | 69 | unsigned int page; /* Last page written to / read from */ |
75 | unsigned int read_bytes; /* Number of bytes read during command */ | 70 | unsigned int read_bytes; /* Number of bytes read during command */ |
@@ -79,6 +74,7 @@ struct fsl_elbc_ctrl { | |||
79 | unsigned int mdr; /* UPM/FCM Data Register value */ | 74 | unsigned int mdr; /* UPM/FCM Data Register value */ |
80 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ | 75 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ |
81 | unsigned int oob; /* Non zero if operating on OOB data */ | 76 | unsigned int oob; /* Non zero if operating on OOB data */ |
77 | unsigned int counter; /* counter for the initializations */ | ||
82 | char *oob_poi; /* Place to write ECC after read back */ | 78 | char *oob_poi; /* Place to write ECC after read back */ |
83 | }; | 79 | }; |
84 | 80 | ||
@@ -164,11 +160,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |||
164 | { | 160 | { |
165 | struct nand_chip *chip = mtd->priv; | 161 | struct nand_chip *chip = mtd->priv; |
166 | struct fsl_elbc_mtd *priv = chip->priv; | 162 | struct fsl_elbc_mtd *priv = chip->priv; |
167 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 163 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
168 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 164 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
165 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
169 | int buf_num; | 166 | int buf_num; |
170 | 167 | ||
171 | ctrl->page = page_addr; | 168 | elbc_fcm_ctrl->page = page_addr; |
172 | 169 | ||
173 | out_be32(&lbc->fbar, | 170 | out_be32(&lbc->fbar, |
174 | page_addr >> (chip->phys_erase_shift - chip->page_shift)); | 171 | page_addr >> (chip->phys_erase_shift - chip->page_shift)); |
@@ -185,16 +182,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |||
185 | buf_num = page_addr & 7; | 182 | buf_num = page_addr & 7; |
186 | } | 183 | } |
187 | 184 | ||
188 | ctrl->addr = priv->vbase + buf_num * 1024; | 185 | elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024; |
189 | ctrl->index = column; | 186 | elbc_fcm_ctrl->index = column; |
190 | 187 | ||
191 | /* for OOB data point to the second half of the buffer */ | 188 | /* for OOB data point to the second half of the buffer */ |
192 | if (oob) | 189 | if (oob) |
193 | ctrl->index += priv->page_size ? 2048 : 512; | 190 | elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512; |
194 | 191 | ||
195 | dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), " | 192 | dev_vdbg(priv->dev, "set_addr: bank=%d, " |
193 | "elbc_fcm_ctrl->addr=0x%p (0x%p), " | ||
196 | "index %x, pes %d ps %d\n", | 194 | "index %x, pes %d ps %d\n", |
197 | buf_num, ctrl->addr, priv->vbase, ctrl->index, | 195 | buf_num, elbc_fcm_ctrl->addr, priv->vbase, |
196 | elbc_fcm_ctrl->index, | ||
198 | chip->phys_erase_shift, chip->page_shift); | 197 | chip->phys_erase_shift, chip->page_shift); |
199 | } | 198 | } |
200 | 199 | ||
@@ -205,18 +204,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
205 | { | 204 | { |
206 | struct nand_chip *chip = mtd->priv; | 205 | struct nand_chip *chip = mtd->priv; |
207 | struct fsl_elbc_mtd *priv = chip->priv; | 206 | struct fsl_elbc_mtd *priv = chip->priv; |
208 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 207 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
208 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
209 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 209 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
210 | 210 | ||
211 | /* Setup the FMR[OP] to execute without write protection */ | 211 | /* Setup the FMR[OP] to execute without write protection */ |
212 | out_be32(&lbc->fmr, priv->fmr | 3); | 212 | out_be32(&lbc->fmr, priv->fmr | 3); |
213 | if (ctrl->use_mdr) | 213 | if (elbc_fcm_ctrl->use_mdr) |
214 | out_be32(&lbc->mdr, ctrl->mdr); | 214 | out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr); |
215 | 215 | ||
216 | dev_vdbg(ctrl->dev, | 216 | dev_vdbg(priv->dev, |
217 | "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", | 217 | "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", |
218 | in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); | 218 | in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); |
219 | dev_vdbg(ctrl->dev, | 219 | dev_vdbg(priv->dev, |
220 | "fsl_elbc_run_command: fbar=%08x fpar=%08x " | 220 | "fsl_elbc_run_command: fbar=%08x fpar=%08x " |
221 | "fbcr=%08x bank=%d\n", | 221 | "fbcr=%08x bank=%d\n", |
222 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), | 222 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), |
@@ -229,19 +229,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
229 | /* wait for FCM complete flag or timeout */ | 229 | /* wait for FCM complete flag or timeout */ |
230 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, | 230 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, |
231 | FCM_TIMEOUT_MSECS * HZ/1000); | 231 | FCM_TIMEOUT_MSECS * HZ/1000); |
232 | ctrl->status = ctrl->irq_status; | 232 | elbc_fcm_ctrl->status = ctrl->irq_status; |
233 | |||
234 | /* store mdr value in case it was needed */ | 233 | /* store mdr value in case it was needed */ |
235 | if (ctrl->use_mdr) | 234 | if (elbc_fcm_ctrl->use_mdr) |
236 | ctrl->mdr = in_be32(&lbc->mdr); | 235 | elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr); |
237 | 236 | ||
238 | ctrl->use_mdr = 0; | 237 | elbc_fcm_ctrl->use_mdr = 0; |
239 | 238 | ||
240 | if (ctrl->status != LTESR_CC) { | 239 | if (elbc_fcm_ctrl->status != LTESR_CC) { |
241 | dev_info(ctrl->dev, | 240 | dev_info(priv->dev, |
242 | "command failed: fir %x fcr %x status %x mdr %x\n", | 241 | "command failed: fir %x fcr %x status %x mdr %x\n", |
243 | in_be32(&lbc->fir), in_be32(&lbc->fcr), | 242 | in_be32(&lbc->fir), in_be32(&lbc->fcr), |
244 | ctrl->status, ctrl->mdr); | 243 | elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr); |
245 | return -EIO; | 244 | return -EIO; |
246 | } | 245 | } |
247 | 246 | ||
@@ -251,7 +250,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
251 | static void fsl_elbc_do_read(struct nand_chip *chip, int oob) | 250 | static void fsl_elbc_do_read(struct nand_chip *chip, int oob) |
252 | { | 251 | { |
253 | struct fsl_elbc_mtd *priv = chip->priv; | 252 | struct fsl_elbc_mtd *priv = chip->priv; |
254 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 253 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
255 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 254 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
256 | 255 | ||
257 | if (priv->page_size) { | 256 | if (priv->page_size) { |
@@ -284,15 +283,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
284 | { | 283 | { |
285 | struct nand_chip *chip = mtd->priv; | 284 | struct nand_chip *chip = mtd->priv; |
286 | struct fsl_elbc_mtd *priv = chip->priv; | 285 | struct fsl_elbc_mtd *priv = chip->priv; |
287 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 286 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
287 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
288 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 288 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
289 | 289 | ||
290 | ctrl->use_mdr = 0; | 290 | elbc_fcm_ctrl->use_mdr = 0; |
291 | 291 | ||
292 | /* clear the read buffer */ | 292 | /* clear the read buffer */ |
293 | ctrl->read_bytes = 0; | 293 | elbc_fcm_ctrl->read_bytes = 0; |
294 | if (command != NAND_CMD_PAGEPROG) | 294 | if (command != NAND_CMD_PAGEPROG) |
295 | ctrl->index = 0; | 295 | elbc_fcm_ctrl->index = 0; |
296 | 296 | ||
297 | switch (command) { | 297 | switch (command) { |
298 | /* READ0 and READ1 read the entire buffer to use hardware ECC. */ | 298 | /* READ0 and READ1 read the entire buffer to use hardware ECC. */ |
@@ -301,7 +301,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
301 | 301 | ||
302 | /* fall-through */ | 302 | /* fall-through */ |
303 | case NAND_CMD_READ0: | 303 | case NAND_CMD_READ0: |
304 | dev_dbg(ctrl->dev, | 304 | dev_dbg(priv->dev, |
305 | "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" | 305 | "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" |
306 | " 0x%x, column: 0x%x.\n", page_addr, column); | 306 | " 0x%x, column: 0x%x.\n", page_addr, column); |
307 | 307 | ||
@@ -309,8 +309,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
309 | out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ | 309 | out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ |
310 | set_addr(mtd, 0, page_addr, 0); | 310 | set_addr(mtd, 0, page_addr, 0); |
311 | 311 | ||
312 | ctrl->read_bytes = mtd->writesize + mtd->oobsize; | 312 | elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; |
313 | ctrl->index += column; | 313 | elbc_fcm_ctrl->index += column; |
314 | 314 | ||
315 | fsl_elbc_do_read(chip, 0); | 315 | fsl_elbc_do_read(chip, 0); |
316 | fsl_elbc_run_command(mtd); | 316 | fsl_elbc_run_command(mtd); |
@@ -318,14 +318,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
318 | 318 | ||
319 | /* READOOB reads only the OOB because no ECC is performed. */ | 319 | /* READOOB reads only the OOB because no ECC is performed. */ |
320 | case NAND_CMD_READOOB: | 320 | case NAND_CMD_READOOB: |
321 | dev_vdbg(ctrl->dev, | 321 | dev_vdbg(priv->dev, |
322 | "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" | 322 | "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" |
323 | " 0x%x, column: 0x%x.\n", page_addr, column); | 323 | " 0x%x, column: 0x%x.\n", page_addr, column); |
324 | 324 | ||
325 | out_be32(&lbc->fbcr, mtd->oobsize - column); | 325 | out_be32(&lbc->fbcr, mtd->oobsize - column); |
326 | set_addr(mtd, column, page_addr, 1); | 326 | set_addr(mtd, column, page_addr, 1); |
327 | 327 | ||
328 | ctrl->read_bytes = mtd->writesize + mtd->oobsize; | 328 | elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; |
329 | 329 | ||
330 | fsl_elbc_do_read(chip, 1); | 330 | fsl_elbc_do_read(chip, 1); |
331 | fsl_elbc_run_command(mtd); | 331 | fsl_elbc_run_command(mtd); |
@@ -333,7 +333,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
333 | 333 | ||
334 | /* READID must read all 5 possible bytes while CEB is active */ | 334 | /* READID must read all 5 possible bytes while CEB is active */ |
335 | case NAND_CMD_READID: | 335 | case NAND_CMD_READID: |
336 | dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); | 336 | dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); |
337 | 337 | ||
338 | out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | | 338 | out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
339 | (FIR_OP_UA << FIR_OP1_SHIFT) | | 339 | (FIR_OP_UA << FIR_OP1_SHIFT) | |
@@ -341,9 +341,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
341 | out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); | 341 | out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); |
342 | /* 5 bytes for manuf, device and exts */ | 342 | /* 5 bytes for manuf, device and exts */ |
343 | out_be32(&lbc->fbcr, 5); | 343 | out_be32(&lbc->fbcr, 5); |
344 | ctrl->read_bytes = 5; | 344 | elbc_fcm_ctrl->read_bytes = 5; |
345 | ctrl->use_mdr = 1; | 345 | elbc_fcm_ctrl->use_mdr = 1; |
346 | ctrl->mdr = 0; | 346 | elbc_fcm_ctrl->mdr = 0; |
347 | 347 | ||
348 | set_addr(mtd, 0, 0, 0); | 348 | set_addr(mtd, 0, 0, 0); |
349 | fsl_elbc_run_command(mtd); | 349 | fsl_elbc_run_command(mtd); |
@@ -351,7 +351,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
351 | 351 | ||
352 | /* ERASE1 stores the block and page address */ | 352 | /* ERASE1 stores the block and page address */ |
353 | case NAND_CMD_ERASE1: | 353 | case NAND_CMD_ERASE1: |
354 | dev_vdbg(ctrl->dev, | 354 | dev_vdbg(priv->dev, |
355 | "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " | 355 | "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " |
356 | "page_addr: 0x%x.\n", page_addr); | 356 | "page_addr: 0x%x.\n", page_addr); |
357 | set_addr(mtd, 0, page_addr, 0); | 357 | set_addr(mtd, 0, page_addr, 0); |
@@ -359,7 +359,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
359 | 359 | ||
360 | /* ERASE2 uses the block and page address from ERASE1 */ | 360 | /* ERASE2 uses the block and page address from ERASE1 */ |
361 | case NAND_CMD_ERASE2: | 361 | case NAND_CMD_ERASE2: |
362 | dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); | 362 | dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); |
363 | 363 | ||
364 | out_be32(&lbc->fir, | 364 | out_be32(&lbc->fir, |
365 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | | 365 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
@@ -374,8 +374,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
374 | (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); | 374 | (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); |
375 | 375 | ||
376 | out_be32(&lbc->fbcr, 0); | 376 | out_be32(&lbc->fbcr, 0); |
377 | ctrl->read_bytes = 0; | 377 | elbc_fcm_ctrl->read_bytes = 0; |
378 | ctrl->use_mdr = 1; | 378 | elbc_fcm_ctrl->use_mdr = 1; |
379 | 379 | ||
380 | fsl_elbc_run_command(mtd); | 380 | fsl_elbc_run_command(mtd); |
381 | return; | 381 | return; |
@@ -383,14 +383,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
383 | /* SEQIN sets up the addr buffer and all registers except the length */ | 383 | /* SEQIN sets up the addr buffer and all registers except the length */ |
384 | case NAND_CMD_SEQIN: { | 384 | case NAND_CMD_SEQIN: { |
385 | __be32 fcr; | 385 | __be32 fcr; |
386 | dev_vdbg(ctrl->dev, | 386 | dev_vdbg(priv->dev, |
387 | "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " | 387 | "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " |
388 | "page_addr: 0x%x, column: 0x%x.\n", | 388 | "page_addr: 0x%x, column: 0x%x.\n", |
389 | page_addr, column); | 389 | page_addr, column); |
390 | 390 | ||
391 | ctrl->column = column; | 391 | elbc_fcm_ctrl->use_mdr = 1; |
392 | ctrl->oob = 0; | ||
393 | ctrl->use_mdr = 1; | ||
394 | 392 | ||
395 | fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | | 393 | fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | |
396 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | | 394 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | |
@@ -420,7 +418,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
420 | /* OOB area --> READOOB */ | 418 | /* OOB area --> READOOB */ |
421 | column -= mtd->writesize; | 419 | column -= mtd->writesize; |
422 | fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; | 420 | fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; |
423 | ctrl->oob = 1; | 421 | elbc_fcm_ctrl->oob = 1; |
424 | } else { | 422 | } else { |
425 | WARN_ON(column != 0); | 423 | WARN_ON(column != 0); |
426 | /* First 256 bytes --> READ0 */ | 424 | /* First 256 bytes --> READ0 */ |
@@ -429,24 +427,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
429 | } | 427 | } |
430 | 428 | ||
431 | out_be32(&lbc->fcr, fcr); | 429 | out_be32(&lbc->fcr, fcr); |
432 | set_addr(mtd, column, page_addr, ctrl->oob); | 430 | set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob); |
433 | return; | 431 | return; |
434 | } | 432 | } |
435 | 433 | ||
436 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ | 434 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ |
437 | case NAND_CMD_PAGEPROG: { | 435 | case NAND_CMD_PAGEPROG: { |
438 | int full_page; | 436 | int full_page; |
439 | dev_vdbg(ctrl->dev, | 437 | dev_vdbg(priv->dev, |
440 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " | 438 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " |
441 | "writing %d bytes.\n", ctrl->index); | 439 | "writing %d bytes.\n", elbc_fcm_ctrl->index); |
442 | 440 | ||
443 | /* if the write did not start at 0 or is not a full page | 441 | /* if the write did not start at 0 or is not a full page |
444 | * then set the exact length, otherwise use a full page | 442 | * then set the exact length, otherwise use a full page |
445 | * write so the HW generates the ECC. | 443 | * write so the HW generates the ECC. |
446 | */ | 444 | */ |
447 | if (ctrl->oob || ctrl->column != 0 || | 445 | if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || |
448 | ctrl->index != mtd->writesize + mtd->oobsize) { | 446 | elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) { |
449 | out_be32(&lbc->fbcr, ctrl->index); | 447 | out_be32(&lbc->fbcr, elbc_fcm_ctrl->index); |
450 | full_page = 0; | 448 | full_page = 0; |
451 | } else { | 449 | } else { |
452 | out_be32(&lbc->fbcr, 0); | 450 | out_be32(&lbc->fbcr, 0); |
@@ -458,21 +456,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
458 | /* Read back the page in order to fill in the ECC for the | 456 | /* Read back the page in order to fill in the ECC for the |
459 | * caller. Is this really needed? | 457 | * caller. Is this really needed? |
460 | */ | 458 | */ |
461 | if (full_page && ctrl->oob_poi) { | 459 | if (full_page && elbc_fcm_ctrl->oob_poi) { |
462 | out_be32(&lbc->fbcr, 3); | 460 | out_be32(&lbc->fbcr, 3); |
463 | set_addr(mtd, 6, page_addr, 1); | 461 | set_addr(mtd, 6, page_addr, 1); |
464 | 462 | ||
465 | ctrl->read_bytes = mtd->writesize + 9; | 463 | elbc_fcm_ctrl->read_bytes = mtd->writesize + 9; |
466 | 464 | ||
467 | fsl_elbc_do_read(chip, 1); | 465 | fsl_elbc_do_read(chip, 1); |
468 | fsl_elbc_run_command(mtd); | 466 | fsl_elbc_run_command(mtd); |
469 | 467 | ||
470 | memcpy_fromio(ctrl->oob_poi + 6, | 468 | memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6, |
471 | &ctrl->addr[ctrl->index], 3); | 469 | &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3); |
472 | ctrl->index += 3; | 470 | elbc_fcm_ctrl->index += 3; |
473 | } | 471 | } |
474 | 472 | ||
475 | ctrl->oob_poi = NULL; | 473 | elbc_fcm_ctrl->oob_poi = NULL; |
476 | return; | 474 | return; |
477 | } | 475 | } |
478 | 476 | ||
@@ -485,26 +483,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
485 | out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); | 483 | out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); |
486 | out_be32(&lbc->fbcr, 1); | 484 | out_be32(&lbc->fbcr, 1); |
487 | set_addr(mtd, 0, 0, 0); | 485 | set_addr(mtd, 0, 0, 0); |
488 | ctrl->read_bytes = 1; | 486 | elbc_fcm_ctrl->read_bytes = 1; |
489 | 487 | ||
490 | fsl_elbc_run_command(mtd); | 488 | fsl_elbc_run_command(mtd); |
491 | 489 | ||
492 | /* The chip always seems to report that it is | 490 | /* The chip always seems to report that it is |
493 | * write-protected, even when it is not. | 491 | * write-protected, even when it is not. |
494 | */ | 492 | */ |
495 | setbits8(ctrl->addr, NAND_STATUS_WP); | 493 | setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP); |
496 | return; | 494 | return; |
497 | 495 | ||
498 | /* RESET without waiting for the ready line */ | 496 | /* RESET without waiting for the ready line */ |
499 | case NAND_CMD_RESET: | 497 | case NAND_CMD_RESET: |
500 | dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); | 498 | dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); |
501 | out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); | 499 | out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); |
502 | out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); | 500 | out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); |
503 | fsl_elbc_run_command(mtd); | 501 | fsl_elbc_run_command(mtd); |
504 | return; | 502 | return; |
505 | 503 | ||
506 | default: | 504 | default: |
507 | dev_err(ctrl->dev, | 505 | dev_err(priv->dev, |
508 | "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", | 506 | "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", |
509 | command); | 507 | command); |
510 | } | 508 | } |
@@ -524,24 +522,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
524 | { | 522 | { |
525 | struct nand_chip *chip = mtd->priv; | 523 | struct nand_chip *chip = mtd->priv; |
526 | struct fsl_elbc_mtd *priv = chip->priv; | 524 | struct fsl_elbc_mtd *priv = chip->priv; |
527 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 525 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
528 | unsigned int bufsize = mtd->writesize + mtd->oobsize; | 526 | unsigned int bufsize = mtd->writesize + mtd->oobsize; |
529 | 527 | ||
530 | if (len <= 0) { | 528 | if (len <= 0) { |
531 | dev_err(ctrl->dev, "write_buf of %d bytes", len); | 529 | dev_err(priv->dev, "write_buf of %d bytes", len); |
532 | ctrl->status = 0; | 530 | elbc_fcm_ctrl->status = 0; |
533 | return; | 531 | return; |
534 | } | 532 | } |
535 | 533 | ||
536 | if ((unsigned int)len > bufsize - ctrl->index) { | 534 | if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) { |
537 | dev_err(ctrl->dev, | 535 | dev_err(priv->dev, |
538 | "write_buf beyond end of buffer " | 536 | "write_buf beyond end of buffer " |
539 | "(%d requested, %u available)\n", | 537 | "(%d requested, %u available)\n", |
540 | len, bufsize - ctrl->index); | 538 | len, bufsize - elbc_fcm_ctrl->index); |
541 | len = bufsize - ctrl->index; | 539 | len = bufsize - elbc_fcm_ctrl->index; |
542 | } | 540 | } |
543 | 541 | ||
544 | memcpy_toio(&ctrl->addr[ctrl->index], buf, len); | 542 | memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len); |
545 | /* | 543 | /* |
546 | * This is workaround for the weird elbc hangs during nand write, | 544 | * This is workaround for the weird elbc hangs during nand write, |
547 | * Scott Wood says: "...perhaps difference in how long it takes a | 545 | * Scott Wood says: "...perhaps difference in how long it takes a |
@@ -549,9 +547,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
549 | * is causing problems, and sync isn't helping for some reason." | 547 | * is causing problems, and sync isn't helping for some reason." |
550 | * Reading back the last byte helps though. | 548 | * Reading back the last byte helps though. |
551 | */ | 549 | */ |
552 | in_8(&ctrl->addr[ctrl->index] + len - 1); | 550 | in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1); |
553 | 551 | ||
554 | ctrl->index += len; | 552 | elbc_fcm_ctrl->index += len; |
555 | } | 553 | } |
556 | 554 | ||
557 | /* | 555 | /* |
@@ -562,13 +560,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd) | |||
562 | { | 560 | { |
563 | struct nand_chip *chip = mtd->priv; | 561 | struct nand_chip *chip = mtd->priv; |
564 | struct fsl_elbc_mtd *priv = chip->priv; | 562 | struct fsl_elbc_mtd *priv = chip->priv; |
565 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 563 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
566 | 564 | ||
567 | /* If there are still bytes in the FCM, then use the next byte. */ | 565 | /* If there are still bytes in the FCM, then use the next byte. */ |
568 | if (ctrl->index < ctrl->read_bytes) | 566 | if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes) |
569 | return in_8(&ctrl->addr[ctrl->index++]); | 567 | return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]); |
570 | 568 | ||
571 | dev_err(ctrl->dev, "read_byte beyond end of buffer\n"); | 569 | dev_err(priv->dev, "read_byte beyond end of buffer\n"); |
572 | return ERR_BYTE; | 570 | return ERR_BYTE; |
573 | } | 571 | } |
574 | 572 | ||
@@ -579,18 +577,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) | |||
579 | { | 577 | { |
580 | struct nand_chip *chip = mtd->priv; | 578 | struct nand_chip *chip = mtd->priv; |
581 | struct fsl_elbc_mtd *priv = chip->priv; | 579 | struct fsl_elbc_mtd *priv = chip->priv; |
582 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 580 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
583 | int avail; | 581 | int avail; |
584 | 582 | ||
585 | if (len < 0) | 583 | if (len < 0) |
586 | return; | 584 | return; |
587 | 585 | ||
588 | avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index); | 586 | avail = min((unsigned int)len, |
589 | memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail); | 587 | elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index); |
590 | ctrl->index += avail; | 588 | memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail); |
589 | elbc_fcm_ctrl->index += avail; | ||
591 | 590 | ||
592 | if (len > avail) | 591 | if (len > avail) |
593 | dev_err(ctrl->dev, | 592 | dev_err(priv->dev, |
594 | "read_buf beyond end of buffer " | 593 | "read_buf beyond end of buffer " |
595 | "(%d requested, %d available)\n", | 594 | "(%d requested, %d available)\n", |
596 | len, avail); | 595 | len, avail); |
@@ -603,30 +602,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
603 | { | 602 | { |
604 | struct nand_chip *chip = mtd->priv; | 603 | struct nand_chip *chip = mtd->priv; |
605 | struct fsl_elbc_mtd *priv = chip->priv; | 604 | struct fsl_elbc_mtd *priv = chip->priv; |
606 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 605 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
607 | int i; | 606 | int i; |
608 | 607 | ||
609 | if (len < 0) { | 608 | if (len < 0) { |
610 | dev_err(ctrl->dev, "write_buf of %d bytes", len); | 609 | dev_err(priv->dev, "write_buf of %d bytes", len); |
611 | return -EINVAL; | 610 | return -EINVAL; |
612 | } | 611 | } |
613 | 612 | ||
614 | if ((unsigned int)len > ctrl->read_bytes - ctrl->index) { | 613 | if ((unsigned int)len > |
615 | dev_err(ctrl->dev, | 614 | elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) { |
616 | "verify_buf beyond end of buffer " | 615 | dev_err(priv->dev, |
617 | "(%d requested, %u available)\n", | 616 | "verify_buf beyond end of buffer " |
618 | len, ctrl->read_bytes - ctrl->index); | 617 | "(%d requested, %u available)\n", |
618 | len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index); | ||
619 | 619 | ||
620 | ctrl->index = ctrl->read_bytes; | 620 | elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes; |
621 | return -EINVAL; | 621 | return -EINVAL; |
622 | } | 622 | } |
623 | 623 | ||
624 | for (i = 0; i < len; i++) | 624 | for (i = 0; i < len; i++) |
625 | if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i]) | 625 | if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i]) |
626 | != buf[i]) | ||
626 | break; | 627 | break; |
627 | 628 | ||
628 | ctrl->index += len; | 629 | elbc_fcm_ctrl->index += len; |
629 | return i == len && ctrl->status == LTESR_CC ? 0 : -EIO; | 630 | return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO; |
630 | } | 631 | } |
631 | 632 | ||
632 | /* This function is called after Program and Erase Operations to | 633 | /* This function is called after Program and Erase Operations to |
@@ -635,22 +636,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
635 | static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) | 636 | static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) |
636 | { | 637 | { |
637 | struct fsl_elbc_mtd *priv = chip->priv; | 638 | struct fsl_elbc_mtd *priv = chip->priv; |
638 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 639 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
639 | 640 | ||
640 | if (ctrl->status != LTESR_CC) | 641 | if (elbc_fcm_ctrl->status != LTESR_CC) |
641 | return NAND_STATUS_FAIL; | 642 | return NAND_STATUS_FAIL; |
642 | 643 | ||
643 | /* The chip always seems to report that it is | 644 | /* The chip always seems to report that it is |
644 | * write-protected, even when it is not. | 645 | * write-protected, even when it is not. |
645 | */ | 646 | */ |
646 | return (ctrl->mdr & 0xff) | NAND_STATUS_WP; | 647 | return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP; |
647 | } | 648 | } |
648 | 649 | ||
649 | static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | 650 | static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) |
650 | { | 651 | { |
651 | struct nand_chip *chip = mtd->priv; | 652 | struct nand_chip *chip = mtd->priv; |
652 | struct fsl_elbc_mtd *priv = chip->priv; | 653 | struct fsl_elbc_mtd *priv = chip->priv; |
653 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 654 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
654 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 655 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
655 | unsigned int al; | 656 | unsigned int al; |
656 | 657 | ||
@@ -665,41 +666,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
665 | priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ | 666 | priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ |
666 | (al << FMR_AL_SHIFT); | 667 | (al << FMR_AL_SHIFT); |
667 | 668 | ||
668 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n", | 669 | dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", |
669 | chip->numchips); | 670 | chip->numchips); |
670 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n", | 671 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n", |
671 | chip->chipsize); | 672 | chip->chipsize); |
672 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n", | 673 | dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", |
673 | chip->pagemask); | 674 | chip->pagemask); |
674 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n", | 675 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n", |
675 | chip->chip_delay); | 676 | chip->chip_delay); |
676 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n", | 677 | dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", |
677 | chip->badblockpos); | 678 | chip->badblockpos); |
678 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n", | 679 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", |
679 | chip->chip_shift); | 680 | chip->chip_shift); |
680 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n", | 681 | dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n", |
681 | chip->page_shift); | 682 | chip->page_shift); |
682 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", | 683 | dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", |
683 | chip->phys_erase_shift); | 684 | chip->phys_erase_shift); |
684 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n", | 685 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n", |
685 | chip->ecclayout); | 686 | chip->ecclayout); |
686 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", | 687 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", |
687 | chip->ecc.mode); | 688 | chip->ecc.mode); |
688 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", | 689 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", |
689 | chip->ecc.steps); | 690 | chip->ecc.steps); |
690 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", | 691 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", |
691 | chip->ecc.bytes); | 692 | chip->ecc.bytes); |
692 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n", | 693 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", |
693 | chip->ecc.total); | 694 | chip->ecc.total); |
694 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", | 695 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", |
695 | chip->ecc.layout); | 696 | chip->ecc.layout); |
696 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); | 697 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); |
697 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); | 698 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); |
698 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n", | 699 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", |
699 | mtd->erasesize); | 700 | mtd->erasesize); |
700 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n", | 701 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n", |
701 | mtd->writesize); | 702 | mtd->writesize); |
702 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n", | 703 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n", |
703 | mtd->oobsize); | 704 | mtd->oobsize); |
704 | 705 | ||
705 | /* adjust Option Register and ECC to match Flash page size */ | 706 | /* adjust Option Register and ECC to match Flash page size */ |
@@ -719,7 +720,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
719 | chip->badblock_pattern = &largepage_memorybased; | 720 | chip->badblock_pattern = &largepage_memorybased; |
720 | } | 721 | } |
721 | } else { | 722 | } else { |
722 | dev_err(ctrl->dev, | 723 | dev_err(priv->dev, |
723 | "fsl_elbc_init: page size %d is not supported\n", | 724 | "fsl_elbc_init: page size %d is not supported\n", |
724 | mtd->writesize); | 725 | mtd->writesize); |
725 | return -1; | 726 | return -1; |
@@ -750,18 +751,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd, | |||
750 | const uint8_t *buf) | 751 | const uint8_t *buf) |
751 | { | 752 | { |
752 | struct fsl_elbc_mtd *priv = chip->priv; | 753 | struct fsl_elbc_mtd *priv = chip->priv; |
753 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 754 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
754 | 755 | ||
755 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); | 756 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); |
756 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | 757 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
757 | 758 | ||
758 | ctrl->oob_poi = chip->oob_poi; | 759 | elbc_fcm_ctrl->oob_poi = chip->oob_poi; |
759 | } | 760 | } |
760 | 761 | ||
761 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | 762 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) |
762 | { | 763 | { |
763 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 764 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
764 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 765 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
766 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
765 | struct nand_chip *chip = &priv->chip; | 767 | struct nand_chip *chip = &priv->chip; |
766 | 768 | ||
767 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); | 769 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); |
@@ -790,7 +792,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
790 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | | 792 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | |
791 | NAND_USE_FLASH_BBT; | 793 | NAND_USE_FLASH_BBT; |
792 | 794 | ||
793 | chip->controller = &ctrl->controller; | 795 | chip->controller = &elbc_fcm_ctrl->controller; |
794 | chip->priv = priv; | 796 | chip->priv = priv; |
795 | 797 | ||
796 | chip->ecc.read_page = fsl_elbc_read_page; | 798 | chip->ecc.read_page = fsl_elbc_read_page; |
@@ -815,8 +817,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
815 | 817 | ||
816 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | 818 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) |
817 | { | 819 | { |
818 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 820 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
819 | |||
820 | nand_release(&priv->mtd); | 821 | nand_release(&priv->mtd); |
821 | 822 | ||
822 | kfree(priv->mtd.name); | 823 | kfree(priv->mtd.name); |
@@ -824,18 +825,21 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | |||
824 | if (priv->vbase) | 825 | if (priv->vbase) |
825 | iounmap(priv->vbase); | 826 | iounmap(priv->vbase); |
826 | 827 | ||
827 | ctrl->chips[priv->bank] = NULL; | 828 | elbc_fcm_ctrl->chips[priv->bank] = NULL; |
828 | kfree(priv); | 829 | kfree(priv); |
829 | 830 | kfree(elbc_fcm_ctrl); | |
830 | return 0; | 831 | return 0; |
831 | } | 832 | } |
832 | 833 | ||
833 | static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | 834 | static DEFINE_MUTEX(fsl_elbc_nand_mutex); |
834 | struct device_node *node) | 835 | |
836 | static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) | ||
835 | { | 837 | { |
836 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 838 | struct fsl_lbc_regs __iomem *lbc; |
837 | struct fsl_elbc_mtd *priv; | 839 | struct fsl_elbc_mtd *priv; |
838 | struct resource res; | 840 | struct resource res; |
841 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; | ||
842 | |||
839 | #ifdef CONFIG_MTD_PARTITIONS | 843 | #ifdef CONFIG_MTD_PARTITIONS |
840 | static const char *part_probe_types[] | 844 | static const char *part_probe_types[] |
841 | = { "cmdlinepart", "RedBoot", NULL }; | 845 | = { "cmdlinepart", "RedBoot", NULL }; |
@@ -843,11 +847,18 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
843 | #endif | 847 | #endif |
844 | int ret; | 848 | int ret; |
845 | int bank; | 849 | int bank; |
850 | struct device *dev; | ||
851 | struct device_node *node = pdev->dev.of_node; | ||
852 | |||
853 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) | ||
854 | return -ENODEV; | ||
855 | lbc = fsl_lbc_ctrl_dev->regs; | ||
856 | dev = fsl_lbc_ctrl_dev->dev; | ||
846 | 857 | ||
847 | /* get, allocate and map the memory resource */ | 858 | /* get, allocate and map the memory resource */ |
848 | ret = of_address_to_resource(node, 0, &res); | 859 | ret = of_address_to_resource(node, 0, &res); |
849 | if (ret) { | 860 | if (ret) { |
850 | dev_err(ctrl->dev, "failed to get resource\n"); | 861 | dev_err(dev, "failed to get resource\n"); |
851 | return ret; | 862 | return ret; |
852 | } | 863 | } |
853 | 864 | ||
@@ -857,11 +868,11 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
857 | (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM && | 868 | (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM && |
858 | (in_be32(&lbc->bank[bank].br) & | 869 | (in_be32(&lbc->bank[bank].br) & |
859 | in_be32(&lbc->bank[bank].or) & BR_BA) | 870 | in_be32(&lbc->bank[bank].or) & BR_BA) |
860 | == res.start) | 871 | == fsl_lbc_addr(res.start)) |
861 | break; | 872 | break; |
862 | 873 | ||
863 | if (bank >= MAX_BANKS) { | 874 | if (bank >= MAX_BANKS) { |
864 | dev_err(ctrl->dev, "address did not match any chip selects\n"); | 875 | dev_err(dev, "address did not match any chip selects\n"); |
865 | return -ENODEV; | 876 | return -ENODEV; |
866 | } | 877 | } |
867 | 878 | ||
@@ -869,14 +880,33 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
869 | if (!priv) | 880 | if (!priv) |
870 | return -ENOMEM; | 881 | return -ENOMEM; |
871 | 882 | ||
872 | ctrl->chips[bank] = priv; | 883 | mutex_lock(&fsl_elbc_nand_mutex); |
884 | if (!fsl_lbc_ctrl_dev->nand) { | ||
885 | elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL); | ||
886 | if (!elbc_fcm_ctrl) { | ||
887 | dev_err(dev, "failed to allocate memory\n"); | ||
888 | mutex_unlock(&fsl_elbc_nand_mutex); | ||
889 | ret = -ENOMEM; | ||
890 | goto err; | ||
891 | } | ||
892 | elbc_fcm_ctrl->counter++; | ||
893 | |||
894 | spin_lock_init(&elbc_fcm_ctrl->controller.lock); | ||
895 | init_waitqueue_head(&elbc_fcm_ctrl->controller.wq); | ||
896 | fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl; | ||
897 | } else { | ||
898 | elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; | ||
899 | } | ||
900 | mutex_unlock(&fsl_elbc_nand_mutex); | ||
901 | |||
902 | elbc_fcm_ctrl->chips[bank] = priv; | ||
873 | priv->bank = bank; | 903 | priv->bank = bank; |
874 | priv->ctrl = ctrl; | 904 | priv->ctrl = fsl_lbc_ctrl_dev; |
875 | priv->dev = ctrl->dev; | 905 | priv->dev = dev; |
876 | 906 | ||
877 | priv->vbase = ioremap(res.start, resource_size(&res)); | 907 | priv->vbase = ioremap(res.start, resource_size(&res)); |
878 | if (!priv->vbase) { | 908 | if (!priv->vbase) { |
879 | dev_err(ctrl->dev, "failed to map chip region\n"); | 909 | dev_err(dev, "failed to map chip region\n"); |
880 | ret = -ENOMEM; | 910 | ret = -ENOMEM; |
881 | goto err; | 911 | goto err; |
882 | } | 912 | } |
@@ -933,171 +963,53 @@ err: | |||
933 | return ret; | 963 | return ret; |
934 | } | 964 | } |
935 | 965 | ||
936 | static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) | 966 | static int fsl_elbc_nand_remove(struct platform_device *pdev) |
937 | { | 967 | { |
938 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
939 | |||
940 | /* | ||
941 | * NAND transactions can tie up the bus for a long time, so set the | ||
942 | * bus timeout to max by clearing LBCR[BMT] (highest base counter | ||
943 | * value) and setting LBCR[BMTPS] to the highest prescaler value. | ||
944 | */ | ||
945 | clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15); | ||
946 | |||
947 | /* clear event registers */ | ||
948 | setbits32(&lbc->ltesr, LTESR_NAND_MASK); | ||
949 | out_be32(&lbc->lteatr, 0); | ||
950 | |||
951 | /* Enable interrupts for any detected events */ | ||
952 | out_be32(&lbc->lteir, LTESR_NAND_MASK); | ||
953 | |||
954 | ctrl->read_bytes = 0; | ||
955 | ctrl->index = 0; | ||
956 | ctrl->addr = NULL; | ||
957 | |||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | static int fsl_elbc_ctrl_remove(struct platform_device *ofdev) | ||
962 | { | ||
963 | struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); | ||
964 | int i; | 968 | int i; |
965 | 969 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; | |
966 | for (i = 0; i < MAX_BANKS; i++) | 970 | for (i = 0; i < MAX_BANKS; i++) |
967 | if (ctrl->chips[i]) | 971 | if (elbc_fcm_ctrl->chips[i]) |
968 | fsl_elbc_chip_remove(ctrl->chips[i]); | 972 | fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]); |
969 | 973 | ||
970 | if (ctrl->irq) | 974 | mutex_lock(&fsl_elbc_nand_mutex); |
971 | free_irq(ctrl->irq, ctrl); | 975 | elbc_fcm_ctrl->counter--; |
972 | 976 | if (!elbc_fcm_ctrl->counter) { | |
973 | if (ctrl->regs) | 977 | fsl_lbc_ctrl_dev->nand = NULL; |
974 | iounmap(ctrl->regs); | 978 | kfree(elbc_fcm_ctrl); |
975 | |||
976 | dev_set_drvdata(&ofdev->dev, NULL); | ||
977 | kfree(ctrl); | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | /* NOTE: This interrupt is also used to report other localbus events, | ||
982 | * such as transaction errors on other chipselects. If we want to | ||
983 | * capture those, we'll need to move the IRQ code into a shared | ||
984 | * LBC driver. | ||
985 | */ | ||
986 | |||
987 | static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) | ||
988 | { | ||
989 | struct fsl_elbc_ctrl *ctrl = data; | ||
990 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
991 | __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK; | ||
992 | |||
993 | if (status) { | ||
994 | out_be32(&lbc->ltesr, status); | ||
995 | out_be32(&lbc->lteatr, 0); | ||
996 | |||
997 | ctrl->irq_status = status; | ||
998 | smp_wmb(); | ||
999 | wake_up(&ctrl->irq_wait); | ||
1000 | |||
1001 | return IRQ_HANDLED; | ||
1002 | } | 979 | } |
1003 | 980 | mutex_unlock(&fsl_elbc_nand_mutex); | |
1004 | return IRQ_NONE; | ||
1005 | } | ||
1006 | |||
1007 | /* fsl_elbc_ctrl_probe | ||
1008 | * | ||
1009 | * called by device layer when it finds a device matching | ||
1010 | * one our driver can handled. This code allocates all of | ||
1011 | * the resources needed for the controller only. The | ||
1012 | * resources for the NAND banks themselves are allocated | ||
1013 | * in the chip probe function. | ||
1014 | */ | ||
1015 | |||
1016 | static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev, | ||
1017 | const struct of_device_id *match) | ||
1018 | { | ||
1019 | struct device_node *child; | ||
1020 | struct fsl_elbc_ctrl *ctrl; | ||
1021 | int ret; | ||
1022 | |||
1023 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); | ||
1024 | if (!ctrl) | ||
1025 | return -ENOMEM; | ||
1026 | |||
1027 | dev_set_drvdata(&ofdev->dev, ctrl); | ||
1028 | |||
1029 | spin_lock_init(&ctrl->controller.lock); | ||
1030 | init_waitqueue_head(&ctrl->controller.wq); | ||
1031 | init_waitqueue_head(&ctrl->irq_wait); | ||
1032 | |||
1033 | ctrl->regs = of_iomap(ofdev->dev.of_node, 0); | ||
1034 | if (!ctrl->regs) { | ||
1035 | dev_err(&ofdev->dev, "failed to get memory region\n"); | ||
1036 | ret = -ENODEV; | ||
1037 | goto err; | ||
1038 | } | ||
1039 | |||
1040 | ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); | ||
1041 | if (ctrl->irq == NO_IRQ) { | ||
1042 | dev_err(&ofdev->dev, "failed to get irq resource\n"); | ||
1043 | ret = -ENODEV; | ||
1044 | goto err; | ||
1045 | } | ||
1046 | |||
1047 | ctrl->dev = &ofdev->dev; | ||
1048 | |||
1049 | ret = fsl_elbc_ctrl_init(ctrl); | ||
1050 | if (ret < 0) | ||
1051 | goto err; | ||
1052 | |||
1053 | ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl); | ||
1054 | if (ret != 0) { | ||
1055 | dev_err(&ofdev->dev, "failed to install irq (%d)\n", | ||
1056 | ctrl->irq); | ||
1057 | ret = ctrl->irq; | ||
1058 | goto err; | ||
1059 | } | ||
1060 | |||
1061 | for_each_child_of_node(ofdev->dev.of_node, child) | ||
1062 | if (of_device_is_compatible(child, "fsl,elbc-fcm-nand")) | ||
1063 | fsl_elbc_chip_probe(ctrl, child); | ||
1064 | 981 | ||
1065 | return 0; | 982 | return 0; |
1066 | 983 | ||
1067 | err: | ||
1068 | fsl_elbc_ctrl_remove(ofdev); | ||
1069 | return ret; | ||
1070 | } | 984 | } |
1071 | 985 | ||
1072 | static const struct of_device_id fsl_elbc_match[] = { | 986 | static const struct of_device_id fsl_elbc_nand_match[] = { |
1073 | { | 987 | { .compatible = "fsl,elbc-fcm-nand", }, |
1074 | .compatible = "fsl,elbc", | ||
1075 | }, | ||
1076 | {} | 988 | {} |
1077 | }; | 989 | }; |
1078 | 990 | ||
1079 | static struct of_platform_driver fsl_elbc_ctrl_driver = { | 991 | static struct platform_driver fsl_elbc_nand_driver = { |
1080 | .driver = { | 992 | .driver = { |
1081 | .name = "fsl-elbc", | 993 | .name = "fsl,elbc-fcm-nand", |
1082 | .owner = THIS_MODULE, | 994 | .owner = THIS_MODULE, |
1083 | .of_match_table = fsl_elbc_match, | 995 | .of_match_table = fsl_elbc_nand_match, |
1084 | }, | 996 | }, |
1085 | .probe = fsl_elbc_ctrl_probe, | 997 | .probe = fsl_elbc_nand_probe, |
1086 | .remove = fsl_elbc_ctrl_remove, | 998 | .remove = fsl_elbc_nand_remove, |
1087 | }; | 999 | }; |
1088 | 1000 | ||
1089 | static int __init fsl_elbc_init(void) | 1001 | static int __init fsl_elbc_nand_init(void) |
1090 | { | 1002 | { |
1091 | return of_register_platform_driver(&fsl_elbc_ctrl_driver); | 1003 | return platform_driver_register(&fsl_elbc_nand_driver); |
1092 | } | 1004 | } |
1093 | 1005 | ||
1094 | static void __exit fsl_elbc_exit(void) | 1006 | static void __exit fsl_elbc_nand_exit(void) |
1095 | { | 1007 | { |
1096 | of_unregister_platform_driver(&fsl_elbc_ctrl_driver); | 1008 | platform_driver_unregister(&fsl_elbc_nand_driver); |
1097 | } | 1009 | } |
1098 | 1010 | ||
1099 | module_init(fsl_elbc_init); | 1011 | module_init(fsl_elbc_nand_init); |
1100 | module_exit(fsl_elbc_exit); | 1012 | module_exit(fsl_elbc_nand_exit); |
1101 | 1013 | ||
1102 | MODULE_LICENSE("GPL"); | 1014 | MODULE_LICENSE("GPL"); |
1103 | MODULE_AUTHOR("Freescale"); | 1015 | MODULE_AUTHOR("Freescale"); |
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 4eff8b25e5af..efdcca94ce55 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
@@ -186,7 +186,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
186 | if (!flash_np) | 186 | if (!flash_np) |
187 | return -ENODEV; | 187 | return -ENODEV; |
188 | 188 | ||
189 | fun->mtd.name = kasprintf(GFP_KERNEL, "%x.%s", io_res->start, | 189 | fun->mtd.name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start, |
190 | flash_np->name); | 190 | flash_np->name); |
191 | if (!fun->mtd.name) { | 191 | if (!fun->mtd.name) { |
192 | ret = -ENOMEM; | 192 | ret = -ENOMEM; |
@@ -222,7 +222,7 @@ static int __devinit fun_probe(struct platform_device *ofdev, | |||
222 | { | 222 | { |
223 | struct fsl_upm_nand *fun; | 223 | struct fsl_upm_nand *fun; |
224 | struct resource io_res; | 224 | struct resource io_res; |
225 | const uint32_t *prop; | 225 | const __be32 *prop; |
226 | int rnb_gpio; | 226 | int rnb_gpio; |
227 | int ret; | 227 | int ret; |
228 | int size; | 228 | int size; |
@@ -270,7 +270,7 @@ static int __devinit fun_probe(struct platform_device *ofdev, | |||
270 | goto err1; | 270 | goto err1; |
271 | } | 271 | } |
272 | for (i = 0; i < fun->mchip_count; i++) | 272 | for (i = 0; i < fun->mchip_count; i++) |
273 | fun->mchip_offsets[i] = prop[i]; | 273 | fun->mchip_offsets[i] = be32_to_cpu(prop[i]); |
274 | } else { | 274 | } else { |
275 | fun->mchip_count = 1; | 275 | fun->mchip_count = 1; |
276 | } | 276 | } |
@@ -295,13 +295,13 @@ static int __devinit fun_probe(struct platform_device *ofdev, | |||
295 | 295 | ||
296 | prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL); | 296 | prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL); |
297 | if (prop) | 297 | if (prop) |
298 | fun->chip_delay = *prop; | 298 | fun->chip_delay = be32_to_cpup(prop); |
299 | else | 299 | else |
300 | fun->chip_delay = 50; | 300 | fun->chip_delay = 50; |
301 | 301 | ||
302 | prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size); | 302 | prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size); |
303 | if (prop && size == sizeof(uint32_t)) | 303 | if (prop && size == sizeof(uint32_t)) |
304 | fun->wait_flags = *prop; | 304 | fun->wait_flags = be32_to_cpup(prop); |
305 | else | 305 | else |
306 | fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | | 306 | fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | |
307 | FSL_UPM_WAIT_WRITE_BYTE; | 307 | FSL_UPM_WAIT_WRITE_BYTE; |
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c new file mode 100644 index 000000000000..02edfba25b0c --- /dev/null +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -0,0 +1,866 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/fsmc_nand.c | ||
3 | * | ||
4 | * ST Microelectronics | ||
5 | * Flexible Static Memory Controller (FSMC) | ||
6 | * Driver for NAND portions | ||
7 | * | ||
8 | * Copyright © 2010 ST Microelectronics | ||
9 | * Vipin Kumar <vipin.kumar@st.com> | ||
10 | * Ashish Priyadarshi | ||
11 | * | ||
12 | * Based on drivers/mtd/nand/nomadik_nand.c | ||
13 | * | ||
14 | * This file is licensed under the terms of the GNU General Public | ||
15 | * License version 2. This program is licensed "as is" without any | ||
16 | * warranty of any kind, whether express or implied. | ||
17 | */ | ||
18 | |||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/resource.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/mtd/mtd.h> | ||
27 | #include <linux/mtd/nand.h> | ||
28 | #include <linux/mtd/nand_ecc.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/mtd/partitions.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/mtd/fsmc.h> | ||
34 | #include <mtd/mtd-abi.h> | ||
35 | |||
36 | static struct nand_ecclayout fsmc_ecc1_layout = { | ||
37 | .eccbytes = 24, | ||
38 | .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52, | ||
39 | 66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116}, | ||
40 | .oobfree = { | ||
41 | {.offset = 8, .length = 8}, | ||
42 | {.offset = 24, .length = 8}, | ||
43 | {.offset = 40, .length = 8}, | ||
44 | {.offset = 56, .length = 8}, | ||
45 | {.offset = 72, .length = 8}, | ||
46 | {.offset = 88, .length = 8}, | ||
47 | {.offset = 104, .length = 8}, | ||
48 | {.offset = 120, .length = 8} | ||
49 | } | ||
50 | }; | ||
51 | |||
52 | static struct nand_ecclayout fsmc_ecc4_lp_layout = { | ||
53 | .eccbytes = 104, | ||
54 | .eccpos = { 2, 3, 4, 5, 6, 7, 8, | ||
55 | 9, 10, 11, 12, 13, 14, | ||
56 | 18, 19, 20, 21, 22, 23, 24, | ||
57 | 25, 26, 27, 28, 29, 30, | ||
58 | 34, 35, 36, 37, 38, 39, 40, | ||
59 | 41, 42, 43, 44, 45, 46, | ||
60 | 50, 51, 52, 53, 54, 55, 56, | ||
61 | 57, 58, 59, 60, 61, 62, | ||
62 | 66, 67, 68, 69, 70, 71, 72, | ||
63 | 73, 74, 75, 76, 77, 78, | ||
64 | 82, 83, 84, 85, 86, 87, 88, | ||
65 | 89, 90, 91, 92, 93, 94, | ||
66 | 98, 99, 100, 101, 102, 103, 104, | ||
67 | 105, 106, 107, 108, 109, 110, | ||
68 | 114, 115, 116, 117, 118, 119, 120, | ||
69 | 121, 122, 123, 124, 125, 126 | ||
70 | }, | ||
71 | .oobfree = { | ||
72 | {.offset = 15, .length = 3}, | ||
73 | {.offset = 31, .length = 3}, | ||
74 | {.offset = 47, .length = 3}, | ||
75 | {.offset = 63, .length = 3}, | ||
76 | {.offset = 79, .length = 3}, | ||
77 | {.offset = 95, .length = 3}, | ||
78 | {.offset = 111, .length = 3}, | ||
79 | {.offset = 127, .length = 1} | ||
80 | } | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | * ECC placement definitions in oobfree type format. | ||
85 | * There are 13 bytes of ecc for every 512 byte block and it has to be read | ||
86 | * consecutively and immediately after the 512 byte data block for hardware to | ||
87 | * generate the error bit offsets in 512 byte data. | ||
88 | * Managing the ecc bytes in the following way makes it easier for software to | ||
89 | * read ecc bytes consecutive to data bytes. This way is similar to | ||
90 | * oobfree structure maintained already in generic nand driver | ||
91 | */ | ||
92 | static struct fsmc_eccplace fsmc_ecc4_lp_place = { | ||
93 | .eccplace = { | ||
94 | {.offset = 2, .length = 13}, | ||
95 | {.offset = 18, .length = 13}, | ||
96 | {.offset = 34, .length = 13}, | ||
97 | {.offset = 50, .length = 13}, | ||
98 | {.offset = 66, .length = 13}, | ||
99 | {.offset = 82, .length = 13}, | ||
100 | {.offset = 98, .length = 13}, | ||
101 | {.offset = 114, .length = 13} | ||
102 | } | ||
103 | }; | ||
104 | |||
105 | static struct nand_ecclayout fsmc_ecc4_sp_layout = { | ||
106 | .eccbytes = 13, | ||
107 | .eccpos = { 0, 1, 2, 3, 6, 7, 8, | ||
108 | 9, 10, 11, 12, 13, 14 | ||
109 | }, | ||
110 | .oobfree = { | ||
111 | {.offset = 15, .length = 1}, | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | static struct fsmc_eccplace fsmc_ecc4_sp_place = { | ||
116 | .eccplace = { | ||
117 | {.offset = 0, .length = 4}, | ||
118 | {.offset = 6, .length = 9} | ||
119 | } | ||
120 | }; | ||
121 | |||
122 | /* | ||
123 | * Default partition tables to be used if the partition information not | ||
124 | * provided through platform data | ||
125 | */ | ||
126 | #define PARTITION(n, off, sz) {.name = n, .offset = off, .size = sz} | ||
127 | |||
128 | /* | ||
129 | * Default partition layout for small page(= 512 bytes) devices | ||
130 | * Size for "Root file system" is updated in driver based on actual device size | ||
131 | */ | ||
132 | static struct mtd_partition partition_info_16KB_blk[] = { | ||
133 | PARTITION("X-loader", 0, 4 * 0x4000), | ||
134 | PARTITION("U-Boot", 0x10000, 20 * 0x4000), | ||
135 | PARTITION("Kernel", 0x60000, 256 * 0x4000), | ||
136 | PARTITION("Root File System", 0x460000, 0), | ||
137 | }; | ||
138 | |||
139 | /* | ||
140 | * Default partition layout for large page(> 512 bytes) devices | ||
141 | * Size for "Root file system" is updated in driver based on actual device size | ||
142 | */ | ||
143 | static struct mtd_partition partition_info_128KB_blk[] = { | ||
144 | PARTITION("X-loader", 0, 4 * 0x20000), | ||
145 | PARTITION("U-Boot", 0x80000, 12 * 0x20000), | ||
146 | PARTITION("Kernel", 0x200000, 48 * 0x20000), | ||
147 | PARTITION("Root File System", 0x800000, 0), | ||
148 | }; | ||
149 | |||
150 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
151 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
152 | #endif | ||
153 | |||
154 | /** | ||
155 | * struct fsmc_nand_data - atructure for FSMC NAND device state | ||
156 | * | ||
157 | * @mtd: MTD info for a NAND flash. | ||
158 | * @nand: Chip related info for a NAND flash. | ||
159 | * @partitions: Partition info for a NAND Flash. | ||
160 | * @nr_partitions: Total number of partition of a NAND flash. | ||
161 | * | ||
162 | * @ecc_place: ECC placing locations in oobfree type format. | ||
163 | * @bank: Bank number for probed device. | ||
164 | * @clk: Clock structure for FSMC. | ||
165 | * | ||
166 | * @data_va: NAND port for Data. | ||
167 | * @cmd_va: NAND port for Command. | ||
168 | * @addr_va: NAND port for Address. | ||
169 | * @regs_va: FSMC regs base address. | ||
170 | */ | ||
171 | struct fsmc_nand_data { | ||
172 | struct mtd_info mtd; | ||
173 | struct nand_chip nand; | ||
174 | struct mtd_partition *partitions; | ||
175 | unsigned int nr_partitions; | ||
176 | |||
177 | struct fsmc_eccplace *ecc_place; | ||
178 | unsigned int bank; | ||
179 | struct clk *clk; | ||
180 | |||
181 | struct resource *resregs; | ||
182 | struct resource *rescmd; | ||
183 | struct resource *resaddr; | ||
184 | struct resource *resdata; | ||
185 | |||
186 | void __iomem *data_va; | ||
187 | void __iomem *cmd_va; | ||
188 | void __iomem *addr_va; | ||
189 | void __iomem *regs_va; | ||
190 | |||
191 | void (*select_chip)(uint32_t bank, uint32_t busw); | ||
192 | }; | ||
193 | |||
194 | /* Assert CS signal based on chipnr */ | ||
195 | static void fsmc_select_chip(struct mtd_info *mtd, int chipnr) | ||
196 | { | ||
197 | struct nand_chip *chip = mtd->priv; | ||
198 | struct fsmc_nand_data *host; | ||
199 | |||
200 | host = container_of(mtd, struct fsmc_nand_data, mtd); | ||
201 | |||
202 | switch (chipnr) { | ||
203 | case -1: | ||
204 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); | ||
205 | break; | ||
206 | case 0: | ||
207 | case 1: | ||
208 | case 2: | ||
209 | case 3: | ||
210 | if (host->select_chip) | ||
211 | host->select_chip(chipnr, | ||
212 | chip->options & NAND_BUSWIDTH_16); | ||
213 | break; | ||
214 | |||
215 | default: | ||
216 | BUG(); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * fsmc_cmd_ctrl - For facilitaing Hardware access | ||
222 | * This routine allows hardware specific access to control-lines(ALE,CLE) | ||
223 | */ | ||
224 | static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | ||
225 | { | ||
226 | struct nand_chip *this = mtd->priv; | ||
227 | struct fsmc_nand_data *host = container_of(mtd, | ||
228 | struct fsmc_nand_data, mtd); | ||
229 | struct fsmc_regs *regs = host->regs_va; | ||
230 | unsigned int bank = host->bank; | ||
231 | |||
232 | if (ctrl & NAND_CTRL_CHANGE) { | ||
233 | if (ctrl & NAND_CLE) { | ||
234 | this->IO_ADDR_R = (void __iomem *)host->cmd_va; | ||
235 | this->IO_ADDR_W = (void __iomem *)host->cmd_va; | ||
236 | } else if (ctrl & NAND_ALE) { | ||
237 | this->IO_ADDR_R = (void __iomem *)host->addr_va; | ||
238 | this->IO_ADDR_W = (void __iomem *)host->addr_va; | ||
239 | } else { | ||
240 | this->IO_ADDR_R = (void __iomem *)host->data_va; | ||
241 | this->IO_ADDR_W = (void __iomem *)host->data_va; | ||
242 | } | ||
243 | |||
244 | if (ctrl & NAND_NCE) { | ||
245 | writel(readl(®s->bank_regs[bank].pc) | FSMC_ENABLE, | ||
246 | ®s->bank_regs[bank].pc); | ||
247 | } else { | ||
248 | writel(readl(®s->bank_regs[bank].pc) & ~FSMC_ENABLE, | ||
249 | ®s->bank_regs[bank].pc); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | mb(); | ||
254 | |||
255 | if (cmd != NAND_CMD_NONE) | ||
256 | writeb(cmd, this->IO_ADDR_W); | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine | ||
261 | * | ||
262 | * This routine initializes timing parameters related to NAND memory access in | ||
263 | * FSMC registers | ||
264 | */ | ||
265 | static void __init fsmc_nand_setup(struct fsmc_regs *regs, uint32_t bank, | ||
266 | uint32_t busw) | ||
267 | { | ||
268 | uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON; | ||
269 | |||
270 | if (busw) | ||
271 | writel(value | FSMC_DEVWID_16, ®s->bank_regs[bank].pc); | ||
272 | else | ||
273 | writel(value | FSMC_DEVWID_8, ®s->bank_regs[bank].pc); | ||
274 | |||
275 | writel(readl(®s->bank_regs[bank].pc) | FSMC_TCLR_1 | FSMC_TAR_1, | ||
276 | ®s->bank_regs[bank].pc); | ||
277 | writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0, | ||
278 | ®s->bank_regs[bank].comm); | ||
279 | writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0, | ||
280 | ®s->bank_regs[bank].attrib); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers | ||
285 | */ | ||
286 | static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) | ||
287 | { | ||
288 | struct fsmc_nand_data *host = container_of(mtd, | ||
289 | struct fsmc_nand_data, mtd); | ||
290 | struct fsmc_regs *regs = host->regs_va; | ||
291 | uint32_t bank = host->bank; | ||
292 | |||
293 | writel(readl(®s->bank_regs[bank].pc) & ~FSMC_ECCPLEN_256, | ||
294 | ®s->bank_regs[bank].pc); | ||
295 | writel(readl(®s->bank_regs[bank].pc) & ~FSMC_ECCEN, | ||
296 | ®s->bank_regs[bank].pc); | ||
297 | writel(readl(®s->bank_regs[bank].pc) | FSMC_ECCEN, | ||
298 | ®s->bank_regs[bank].pc); | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * fsmc_read_hwecc_ecc4 - Hardware ECC calculator for ecc4 option supported by | ||
303 | * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction upto | ||
304 | * max of 8-bits) | ||
305 | */ | ||
306 | static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, | ||
307 | uint8_t *ecc) | ||
308 | { | ||
309 | struct fsmc_nand_data *host = container_of(mtd, | ||
310 | struct fsmc_nand_data, mtd); | ||
311 | struct fsmc_regs *regs = host->regs_va; | ||
312 | uint32_t bank = host->bank; | ||
313 | uint32_t ecc_tmp; | ||
314 | unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; | ||
315 | |||
316 | do { | ||
317 | if (readl(®s->bank_regs[bank].sts) & FSMC_CODE_RDY) | ||
318 | break; | ||
319 | else | ||
320 | cond_resched(); | ||
321 | } while (!time_after_eq(jiffies, deadline)); | ||
322 | |||
323 | ecc_tmp = readl(®s->bank_regs[bank].ecc1); | ||
324 | ecc[0] = (uint8_t) (ecc_tmp >> 0); | ||
325 | ecc[1] = (uint8_t) (ecc_tmp >> 8); | ||
326 | ecc[2] = (uint8_t) (ecc_tmp >> 16); | ||
327 | ecc[3] = (uint8_t) (ecc_tmp >> 24); | ||
328 | |||
329 | ecc_tmp = readl(®s->bank_regs[bank].ecc2); | ||
330 | ecc[4] = (uint8_t) (ecc_tmp >> 0); | ||
331 | ecc[5] = (uint8_t) (ecc_tmp >> 8); | ||
332 | ecc[6] = (uint8_t) (ecc_tmp >> 16); | ||
333 | ecc[7] = (uint8_t) (ecc_tmp >> 24); | ||
334 | |||
335 | ecc_tmp = readl(®s->bank_regs[bank].ecc3); | ||
336 | ecc[8] = (uint8_t) (ecc_tmp >> 0); | ||
337 | ecc[9] = (uint8_t) (ecc_tmp >> 8); | ||
338 | ecc[10] = (uint8_t) (ecc_tmp >> 16); | ||
339 | ecc[11] = (uint8_t) (ecc_tmp >> 24); | ||
340 | |||
341 | ecc_tmp = readl(®s->bank_regs[bank].sts); | ||
342 | ecc[12] = (uint8_t) (ecc_tmp >> 16); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by | ||
349 | * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction upto | ||
350 | * max of 1-bit) | ||
351 | */ | ||
352 | static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, | ||
353 | uint8_t *ecc) | ||
354 | { | ||
355 | struct fsmc_nand_data *host = container_of(mtd, | ||
356 | struct fsmc_nand_data, mtd); | ||
357 | struct fsmc_regs *regs = host->regs_va; | ||
358 | uint32_t bank = host->bank; | ||
359 | uint32_t ecc_tmp; | ||
360 | |||
361 | ecc_tmp = readl(®s->bank_regs[bank].ecc1); | ||
362 | ecc[0] = (uint8_t) (ecc_tmp >> 0); | ||
363 | ecc[1] = (uint8_t) (ecc_tmp >> 8); | ||
364 | ecc[2] = (uint8_t) (ecc_tmp >> 16); | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * fsmc_read_page_hwecc | ||
371 | * @mtd: mtd info structure | ||
372 | * @chip: nand chip info structure | ||
373 | * @buf: buffer to store read data | ||
374 | * @page: page number to read | ||
375 | * | ||
376 | * This routine is needed for fsmc verison 8 as reading from NAND chip has to be | ||
377 | * performed in a strict sequence as follows: | ||
378 | * data(512 byte) -> ecc(13 byte) | ||
379 | * After this read, fsmc hardware generates and reports error data bits(upto a | ||
380 | * max of 8 bits) | ||
381 | */ | ||
382 | static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | ||
383 | uint8_t *buf, int page) | ||
384 | { | ||
385 | struct fsmc_nand_data *host = container_of(mtd, | ||
386 | struct fsmc_nand_data, mtd); | ||
387 | struct fsmc_eccplace *ecc_place = host->ecc_place; | ||
388 | int i, j, s, stat, eccsize = chip->ecc.size; | ||
389 | int eccbytes = chip->ecc.bytes; | ||
390 | int eccsteps = chip->ecc.steps; | ||
391 | uint8_t *p = buf; | ||
392 | uint8_t *ecc_calc = chip->buffers->ecccalc; | ||
393 | uint8_t *ecc_code = chip->buffers->ecccode; | ||
394 | int off, len, group = 0; | ||
395 | /* | ||
396 | * ecc_oob is intentionally taken as uint16_t. In 16bit devices, we | ||
397 | * end up reading 14 bytes (7 words) from oob. The local array is | ||
398 | * to maintain word alignment | ||
399 | */ | ||
400 | uint16_t ecc_oob[7]; | ||
401 | uint8_t *oob = (uint8_t *)&ecc_oob[0]; | ||
402 | |||
403 | for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { | ||
404 | |||
405 | chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page); | ||
406 | chip->ecc.hwctl(mtd, NAND_ECC_READ); | ||
407 | chip->read_buf(mtd, p, eccsize); | ||
408 | |||
409 | for (j = 0; j < eccbytes;) { | ||
410 | off = ecc_place->eccplace[group].offset; | ||
411 | len = ecc_place->eccplace[group].length; | ||
412 | group++; | ||
413 | |||
414 | /* | ||
415 | * length is intentionally kept a higher multiple of 2 | ||
416 | * to read at least 13 bytes even in case of 16 bit NAND | ||
417 | * devices | ||
418 | */ | ||
419 | len = roundup(len, 2); | ||
420 | chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page); | ||
421 | chip->read_buf(mtd, oob + j, len); | ||
422 | j += len; | ||
423 | } | ||
424 | |||
425 | memcpy(&ecc_code[i], oob, 13); | ||
426 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | ||
427 | |||
428 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); | ||
429 | if (stat < 0) | ||
430 | mtd->ecc_stats.failed++; | ||
431 | else | ||
432 | mtd->ecc_stats.corrected += stat; | ||
433 | } | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | /* | ||
439 | * fsmc_correct_data | ||
440 | * @mtd: mtd info structure | ||
441 | * @dat: buffer of read data | ||
442 | * @read_ecc: ecc read from device spare area | ||
443 | * @calc_ecc: ecc calculated from read data | ||
444 | * | ||
445 | * calc_ecc is a 104 bit information containing maximum of 8 error | ||
446 | * offset informations of 13 bits each in 512 bytes of read data. | ||
447 | */ | ||
448 | static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat, | ||
449 | uint8_t *read_ecc, uint8_t *calc_ecc) | ||
450 | { | ||
451 | struct fsmc_nand_data *host = container_of(mtd, | ||
452 | struct fsmc_nand_data, mtd); | ||
453 | struct fsmc_regs *regs = host->regs_va; | ||
454 | unsigned int bank = host->bank; | ||
455 | uint16_t err_idx[8]; | ||
456 | uint64_t ecc_data[2]; | ||
457 | uint32_t num_err, i; | ||
458 | |||
459 | /* The calculated ecc is actually the correction index in data */ | ||
460 | memcpy(ecc_data, calc_ecc, 13); | ||
461 | |||
462 | /* | ||
463 | * ------------------- calc_ecc[] bit wise -----------|--13 bits--| | ||
464 | * |---idx[7]--|--.....-----|---idx[2]--||---idx[1]--||---idx[0]--| | ||
465 | * | ||
466 | * calc_ecc is a 104 bit information containing maximum of 8 error | ||
467 | * offset informations of 13 bits each. calc_ecc is copied into a | ||
468 | * uint64_t array and error offset indexes are populated in err_idx | ||
469 | * array | ||
470 | */ | ||
471 | for (i = 0; i < 8; i++) { | ||
472 | if (i == 4) { | ||
473 | err_idx[4] = ((ecc_data[1] & 0x1) << 12) | ecc_data[0]; | ||
474 | ecc_data[1] >>= 1; | ||
475 | continue; | ||
476 | } | ||
477 | err_idx[i] = (ecc_data[i/4] & 0x1FFF); | ||
478 | ecc_data[i/4] >>= 13; | ||
479 | } | ||
480 | |||
481 | num_err = (readl(®s->bank_regs[bank].sts) >> 10) & 0xF; | ||
482 | |||
483 | if (num_err == 0xF) | ||
484 | return -EBADMSG; | ||
485 | |||
486 | i = 0; | ||
487 | while (num_err--) { | ||
488 | change_bit(0, (unsigned long *)&err_idx[i]); | ||
489 | change_bit(1, (unsigned long *)&err_idx[i]); | ||
490 | |||
491 | if (err_idx[i] <= 512 * 8) { | ||
492 | change_bit(err_idx[i], (unsigned long *)dat); | ||
493 | i++; | ||
494 | } | ||
495 | } | ||
496 | return i; | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | * fsmc_nand_probe - Probe function | ||
501 | * @pdev: platform device structure | ||
502 | */ | ||
503 | static int __init fsmc_nand_probe(struct platform_device *pdev) | ||
504 | { | ||
505 | struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
506 | struct fsmc_nand_data *host; | ||
507 | struct mtd_info *mtd; | ||
508 | struct nand_chip *nand; | ||
509 | struct fsmc_regs *regs; | ||
510 | struct resource *res; | ||
511 | int nr_parts, ret = 0; | ||
512 | |||
513 | if (!pdata) { | ||
514 | dev_err(&pdev->dev, "platform data is NULL\n"); | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | |||
518 | /* Allocate memory for the device structure (and zero it) */ | ||
519 | host = kzalloc(sizeof(*host), GFP_KERNEL); | ||
520 | if (!host) { | ||
521 | dev_err(&pdev->dev, "failed to allocate device structure\n"); | ||
522 | return -ENOMEM; | ||
523 | } | ||
524 | |||
525 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data"); | ||
526 | if (!res) { | ||
527 | ret = -EIO; | ||
528 | goto err_probe1; | ||
529 | } | ||
530 | |||
531 | host->resdata = request_mem_region(res->start, resource_size(res), | ||
532 | pdev->name); | ||
533 | if (!host->resdata) { | ||
534 | ret = -EIO; | ||
535 | goto err_probe1; | ||
536 | } | ||
537 | |||
538 | host->data_va = ioremap(res->start, resource_size(res)); | ||
539 | if (!host->data_va) { | ||
540 | ret = -EIO; | ||
541 | goto err_probe1; | ||
542 | } | ||
543 | |||
544 | host->resaddr = request_mem_region(res->start + PLAT_NAND_ALE, | ||
545 | resource_size(res), pdev->name); | ||
546 | if (!host->resaddr) { | ||
547 | ret = -EIO; | ||
548 | goto err_probe1; | ||
549 | } | ||
550 | |||
551 | host->addr_va = ioremap(res->start + PLAT_NAND_ALE, resource_size(res)); | ||
552 | if (!host->addr_va) { | ||
553 | ret = -EIO; | ||
554 | goto err_probe1; | ||
555 | } | ||
556 | |||
557 | host->rescmd = request_mem_region(res->start + PLAT_NAND_CLE, | ||
558 | resource_size(res), pdev->name); | ||
559 | if (!host->rescmd) { | ||
560 | ret = -EIO; | ||
561 | goto err_probe1; | ||
562 | } | ||
563 | |||
564 | host->cmd_va = ioremap(res->start + PLAT_NAND_CLE, resource_size(res)); | ||
565 | if (!host->cmd_va) { | ||
566 | ret = -EIO; | ||
567 | goto err_probe1; | ||
568 | } | ||
569 | |||
570 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs"); | ||
571 | if (!res) { | ||
572 | ret = -EIO; | ||
573 | goto err_probe1; | ||
574 | } | ||
575 | |||
576 | host->resregs = request_mem_region(res->start, resource_size(res), | ||
577 | pdev->name); | ||
578 | if (!host->resregs) { | ||
579 | ret = -EIO; | ||
580 | goto err_probe1; | ||
581 | } | ||
582 | |||
583 | host->regs_va = ioremap(res->start, resource_size(res)); | ||
584 | if (!host->regs_va) { | ||
585 | ret = -EIO; | ||
586 | goto err_probe1; | ||
587 | } | ||
588 | |||
589 | host->clk = clk_get(&pdev->dev, NULL); | ||
590 | if (IS_ERR(host->clk)) { | ||
591 | dev_err(&pdev->dev, "failed to fetch block clock\n"); | ||
592 | ret = PTR_ERR(host->clk); | ||
593 | host->clk = NULL; | ||
594 | goto err_probe1; | ||
595 | } | ||
596 | |||
597 | ret = clk_enable(host->clk); | ||
598 | if (ret) | ||
599 | goto err_probe1; | ||
600 | |||
601 | host->bank = pdata->bank; | ||
602 | host->select_chip = pdata->select_bank; | ||
603 | regs = host->regs_va; | ||
604 | |||
605 | /* Link all private pointers */ | ||
606 | mtd = &host->mtd; | ||
607 | nand = &host->nand; | ||
608 | mtd->priv = nand; | ||
609 | nand->priv = host; | ||
610 | |||
611 | host->mtd.owner = THIS_MODULE; | ||
612 | nand->IO_ADDR_R = host->data_va; | ||
613 | nand->IO_ADDR_W = host->data_va; | ||
614 | nand->cmd_ctrl = fsmc_cmd_ctrl; | ||
615 | nand->chip_delay = 30; | ||
616 | |||
617 | nand->ecc.mode = NAND_ECC_HW; | ||
618 | nand->ecc.hwctl = fsmc_enable_hwecc; | ||
619 | nand->ecc.size = 512; | ||
620 | nand->options = pdata->options; | ||
621 | nand->select_chip = fsmc_select_chip; | ||
622 | |||
623 | if (pdata->width == FSMC_NAND_BW16) | ||
624 | nand->options |= NAND_BUSWIDTH_16; | ||
625 | |||
626 | fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16); | ||
627 | |||
628 | if (get_fsmc_version(host->regs_va) == FSMC_VER8) { | ||
629 | nand->ecc.read_page = fsmc_read_page_hwecc; | ||
630 | nand->ecc.calculate = fsmc_read_hwecc_ecc4; | ||
631 | nand->ecc.correct = fsmc_correct_data; | ||
632 | nand->ecc.bytes = 13; | ||
633 | } else { | ||
634 | nand->ecc.calculate = fsmc_read_hwecc_ecc1; | ||
635 | nand->ecc.correct = nand_correct_data; | ||
636 | nand->ecc.bytes = 3; | ||
637 | } | ||
638 | |||
639 | /* | ||
640 | * Scan to find existance of the device | ||
641 | */ | ||
642 | if (nand_scan_ident(&host->mtd, 1, NULL)) { | ||
643 | ret = -ENXIO; | ||
644 | dev_err(&pdev->dev, "No NAND Device found!\n"); | ||
645 | goto err_probe; | ||
646 | } | ||
647 | |||
648 | if (get_fsmc_version(host->regs_va) == FSMC_VER8) { | ||
649 | if (host->mtd.writesize == 512) { | ||
650 | nand->ecc.layout = &fsmc_ecc4_sp_layout; | ||
651 | host->ecc_place = &fsmc_ecc4_sp_place; | ||
652 | } else { | ||
653 | nand->ecc.layout = &fsmc_ecc4_lp_layout; | ||
654 | host->ecc_place = &fsmc_ecc4_lp_place; | ||
655 | } | ||
656 | } else { | ||
657 | nand->ecc.layout = &fsmc_ecc1_layout; | ||
658 | } | ||
659 | |||
660 | /* Second stage of scan to fill MTD data-structures */ | ||
661 | if (nand_scan_tail(&host->mtd)) { | ||
662 | ret = -ENXIO; | ||
663 | goto err_probe; | ||
664 | } | ||
665 | |||
666 | /* | ||
667 | * The partition information can is accessed by (in the same precedence) | ||
668 | * | ||
669 | * command line through Bootloader, | ||
670 | * platform data, | ||
671 | * default partition information present in driver. | ||
672 | */ | ||
673 | #ifdef CONFIG_MTD_PARTITIONS | ||
674 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
675 | /* | ||
676 | * Check if partition info passed via command line | ||
677 | */ | ||
678 | host->mtd.name = "nand"; | ||
679 | nr_parts = parse_mtd_partitions(&host->mtd, part_probes, | ||
680 | &host->partitions, 0); | ||
681 | if (nr_parts > 0) { | ||
682 | host->nr_partitions = nr_parts; | ||
683 | } else { | ||
684 | #endif | ||
685 | /* | ||
686 | * Check if partition info passed via command line | ||
687 | */ | ||
688 | if (pdata->partitions) { | ||
689 | host->partitions = pdata->partitions; | ||
690 | host->nr_partitions = pdata->nr_partitions; | ||
691 | } else { | ||
692 | struct mtd_partition *partition; | ||
693 | int i; | ||
694 | |||
695 | /* Select the default partitions info */ | ||
696 | switch (host->mtd.size) { | ||
697 | case 0x01000000: | ||
698 | case 0x02000000: | ||
699 | case 0x04000000: | ||
700 | host->partitions = partition_info_16KB_blk; | ||
701 | host->nr_partitions = | ||
702 | sizeof(partition_info_16KB_blk) / | ||
703 | sizeof(struct mtd_partition); | ||
704 | break; | ||
705 | case 0x08000000: | ||
706 | case 0x10000000: | ||
707 | case 0x20000000: | ||
708 | case 0x40000000: | ||
709 | host->partitions = partition_info_128KB_blk; | ||
710 | host->nr_partitions = | ||
711 | sizeof(partition_info_128KB_blk) / | ||
712 | sizeof(struct mtd_partition); | ||
713 | break; | ||
714 | default: | ||
715 | ret = -ENXIO; | ||
716 | pr_err("Unsupported NAND size\n"); | ||
717 | goto err_probe; | ||
718 | } | ||
719 | |||
720 | partition = host->partitions; | ||
721 | for (i = 0; i < host->nr_partitions; i++, partition++) { | ||
722 | if (partition->size == 0) { | ||
723 | partition->size = host->mtd.size - | ||
724 | partition->offset; | ||
725 | break; | ||
726 | } | ||
727 | } | ||
728 | } | ||
729 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
730 | } | ||
731 | #endif | ||
732 | |||
733 | if (host->partitions) { | ||
734 | ret = add_mtd_partitions(&host->mtd, host->partitions, | ||
735 | host->nr_partitions); | ||
736 | if (ret) | ||
737 | goto err_probe; | ||
738 | } | ||
739 | #else | ||
740 | dev_info(&pdev->dev, "Registering %s as whole device\n", mtd->name); | ||
741 | if (!add_mtd_device(mtd)) { | ||
742 | ret = -ENXIO; | ||
743 | goto err_probe; | ||
744 | } | ||
745 | #endif | ||
746 | |||
747 | platform_set_drvdata(pdev, host); | ||
748 | dev_info(&pdev->dev, "FSMC NAND driver registration successful\n"); | ||
749 | return 0; | ||
750 | |||
751 | err_probe: | ||
752 | clk_disable(host->clk); | ||
753 | err_probe1: | ||
754 | if (host->clk) | ||
755 | clk_put(host->clk); | ||
756 | if (host->regs_va) | ||
757 | iounmap(host->regs_va); | ||
758 | if (host->resregs) | ||
759 | release_mem_region(host->resregs->start, | ||
760 | resource_size(host->resregs)); | ||
761 | if (host->cmd_va) | ||
762 | iounmap(host->cmd_va); | ||
763 | if (host->rescmd) | ||
764 | release_mem_region(host->rescmd->start, | ||
765 | resource_size(host->rescmd)); | ||
766 | if (host->addr_va) | ||
767 | iounmap(host->addr_va); | ||
768 | if (host->resaddr) | ||
769 | release_mem_region(host->resaddr->start, | ||
770 | resource_size(host->resaddr)); | ||
771 | if (host->data_va) | ||
772 | iounmap(host->data_va); | ||
773 | if (host->resdata) | ||
774 | release_mem_region(host->resdata->start, | ||
775 | resource_size(host->resdata)); | ||
776 | |||
777 | kfree(host); | ||
778 | return ret; | ||
779 | } | ||
780 | |||
781 | /* | ||
782 | * Clean up routine | ||
783 | */ | ||
784 | static int fsmc_nand_remove(struct platform_device *pdev) | ||
785 | { | ||
786 | struct fsmc_nand_data *host = platform_get_drvdata(pdev); | ||
787 | |||
788 | platform_set_drvdata(pdev, NULL); | ||
789 | |||
790 | if (host) { | ||
791 | #ifdef CONFIG_MTD_PARTITIONS | ||
792 | del_mtd_partitions(&host->mtd); | ||
793 | #else | ||
794 | del_mtd_device(&host->mtd); | ||
795 | #endif | ||
796 | clk_disable(host->clk); | ||
797 | clk_put(host->clk); | ||
798 | |||
799 | iounmap(host->regs_va); | ||
800 | release_mem_region(host->resregs->start, | ||
801 | resource_size(host->resregs)); | ||
802 | iounmap(host->cmd_va); | ||
803 | release_mem_region(host->rescmd->start, | ||
804 | resource_size(host->rescmd)); | ||
805 | iounmap(host->addr_va); | ||
806 | release_mem_region(host->resaddr->start, | ||
807 | resource_size(host->resaddr)); | ||
808 | iounmap(host->data_va); | ||
809 | release_mem_region(host->resdata->start, | ||
810 | resource_size(host->resdata)); | ||
811 | |||
812 | kfree(host); | ||
813 | } | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | #ifdef CONFIG_PM | ||
818 | static int fsmc_nand_suspend(struct device *dev) | ||
819 | { | ||
820 | struct fsmc_nand_data *host = dev_get_drvdata(dev); | ||
821 | if (host) | ||
822 | clk_disable(host->clk); | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static int fsmc_nand_resume(struct device *dev) | ||
827 | { | ||
828 | struct fsmc_nand_data *host = dev_get_drvdata(dev); | ||
829 | if (host) | ||
830 | clk_enable(host->clk); | ||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | static const struct dev_pm_ops fsmc_nand_pm_ops = { | ||
835 | .suspend = fsmc_nand_suspend, | ||
836 | .resume = fsmc_nand_resume, | ||
837 | }; | ||
838 | #endif | ||
839 | |||
840 | static struct platform_driver fsmc_nand_driver = { | ||
841 | .remove = fsmc_nand_remove, | ||
842 | .driver = { | ||
843 | .owner = THIS_MODULE, | ||
844 | .name = "fsmc-nand", | ||
845 | #ifdef CONFIG_PM | ||
846 | .pm = &fsmc_nand_pm_ops, | ||
847 | #endif | ||
848 | }, | ||
849 | }; | ||
850 | |||
851 | static int __init fsmc_nand_init(void) | ||
852 | { | ||
853 | return platform_driver_probe(&fsmc_nand_driver, | ||
854 | fsmc_nand_probe); | ||
855 | } | ||
856 | module_init(fsmc_nand_init); | ||
857 | |||
858 | static void __exit fsmc_nand_exit(void) | ||
859 | { | ||
860 | platform_driver_unregister(&fsmc_nand_driver); | ||
861 | } | ||
862 | module_exit(fsmc_nand_exit); | ||
863 | |||
864 | MODULE_LICENSE("GPL"); | ||
865 | MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>, Ashish Priyadarshi"); | ||
866 | MODULE_DESCRIPTION("NAND driver for SPEAr Platforms"); | ||
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index df0c1da4ff49..469e649c911c 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -568,6 +568,7 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) | |||
568 | uint rcw_width; | 568 | uint rcw_width; |
569 | uint rcwh; | 569 | uint rcwh; |
570 | uint romloc, ps; | 570 | uint romloc, ps; |
571 | int ret = 0; | ||
571 | 572 | ||
572 | rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset"); | 573 | rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset"); |
573 | if (!rmnode) { | 574 | if (!rmnode) { |
@@ -579,7 +580,8 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) | |||
579 | rm = of_iomap(rmnode, 0); | 580 | rm = of_iomap(rmnode, 0); |
580 | if (!rm) { | 581 | if (!rm) { |
581 | dev_err(prv->dev, "Error mapping reset module node!\n"); | 582 | dev_err(prv->dev, "Error mapping reset module node!\n"); |
582 | return -EBUSY; | 583 | ret = -EBUSY; |
584 | goto out; | ||
583 | } | 585 | } |
584 | 586 | ||
585 | rcwh = in_be32(&rm->rcwhr); | 587 | rcwh = in_be32(&rm->rcwhr); |
@@ -628,8 +630,9 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) | |||
628 | rcw_width * 8, rcw_pagesize, | 630 | rcw_width * 8, rcw_pagesize, |
629 | rcw_sparesize); | 631 | rcw_sparesize); |
630 | iounmap(rm); | 632 | iounmap(rm); |
633 | out: | ||
631 | of_node_put(rmnode); | 634 | of_node_put(rmnode); |
632 | return 0; | 635 | return ret; |
633 | } | 636 | } |
634 | 637 | ||
635 | /* Free driver resources */ | 638 | /* Free driver resources */ |
@@ -660,7 +663,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op, | |||
660 | #endif | 663 | #endif |
661 | struct nand_chip *chip; | 664 | struct nand_chip *chip; |
662 | unsigned long regs_paddr, regs_size; | 665 | unsigned long regs_paddr, regs_size; |
663 | const uint *chips_no; | 666 | const __be32 *chips_no; |
664 | int resettime = 0; | 667 | int resettime = 0; |
665 | int retval = 0; | 668 | int retval = 0; |
666 | int rev, len; | 669 | int rev, len; |
@@ -803,7 +806,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op, | |||
803 | } | 806 | } |
804 | 807 | ||
805 | /* Detect NAND chips */ | 808 | /* Detect NAND chips */ |
806 | if (nand_scan(mtd, *chips_no)) { | 809 | if (nand_scan(mtd, be32_to_cpup(chips_no))) { |
807 | dev_err(dev, "NAND Flash not found !\n"); | 810 | dev_err(dev, "NAND Flash not found !\n"); |
808 | devm_free_irq(dev, prv->irq, mtd); | 811 | devm_free_irq(dev, prv->irq, mtd); |
809 | retval = -ENXIO; | 812 | retval = -ENXIO; |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index d551ddd9537a..1f75a1b1f7c3 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
46 | #include <linux/bitops.h> | 46 | #include <linux/bitops.h> |
47 | #include <linux/leds.h> | 47 | #include <linux/leds.h> |
48 | #include <asm/io.h> | 48 | #include <linux/io.h> |
49 | 49 | ||
50 | #ifdef CONFIG_MTD_PARTITIONS | 50 | #ifdef CONFIG_MTD_PARTITIONS |
51 | #include <linux/mtd/partitions.h> | 51 | #include <linux/mtd/partitions.h> |
@@ -59,7 +59,7 @@ static struct nand_ecclayout nand_oob_8 = { | |||
59 | {.offset = 3, | 59 | {.offset = 3, |
60 | .length = 2}, | 60 | .length = 2}, |
61 | {.offset = 6, | 61 | {.offset = 6, |
62 | .length = 2}} | 62 | .length = 2} } |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static struct nand_ecclayout nand_oob_16 = { | 65 | static struct nand_ecclayout nand_oob_16 = { |
@@ -67,7 +67,7 @@ static struct nand_ecclayout nand_oob_16 = { | |||
67 | .eccpos = {0, 1, 2, 3, 6, 7}, | 67 | .eccpos = {0, 1, 2, 3, 6, 7}, |
68 | .oobfree = { | 68 | .oobfree = { |
69 | {.offset = 8, | 69 | {.offset = 8, |
70 | . length = 8}} | 70 | . length = 8} } |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static struct nand_ecclayout nand_oob_64 = { | 73 | static struct nand_ecclayout nand_oob_64 = { |
@@ -78,7 +78,7 @@ static struct nand_ecclayout nand_oob_64 = { | |||
78 | 56, 57, 58, 59, 60, 61, 62, 63}, | 78 | 56, 57, 58, 59, 60, 61, 62, 63}, |
79 | .oobfree = { | 79 | .oobfree = { |
80 | {.offset = 2, | 80 | {.offset = 2, |
81 | .length = 38}} | 81 | .length = 38} } |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static struct nand_ecclayout nand_oob_128 = { | 84 | static struct nand_ecclayout nand_oob_128 = { |
@@ -92,7 +92,7 @@ static struct nand_ecclayout nand_oob_128 = { | |||
92 | 120, 121, 122, 123, 124, 125, 126, 127}, | 92 | 120, 121, 122, 123, 124, 125, 126, 127}, |
93 | .oobfree = { | 93 | .oobfree = { |
94 | {.offset = 2, | 94 | {.offset = 2, |
95 | .length = 78}} | 95 | .length = 78} } |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, | 98 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, |
@@ -612,7 +612,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | |||
612 | NAND_CTRL_CLE | NAND_CTRL_CHANGE); | 612 | NAND_CTRL_CLE | NAND_CTRL_CHANGE); |
613 | chip->cmd_ctrl(mtd, | 613 | chip->cmd_ctrl(mtd, |
614 | NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); | 614 | NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); |
615 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ; | 615 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) |
616 | ; | ||
616 | return; | 617 | return; |
617 | 618 | ||
618 | /* This applies to read commands */ | 619 | /* This applies to read commands */ |
@@ -718,7 +719,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
718 | NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); | 719 | NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); |
719 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, | 720 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, |
720 | NAND_NCE | NAND_CTRL_CHANGE); | 721 | NAND_NCE | NAND_CTRL_CHANGE); |
721 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ; | 722 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) |
723 | ; | ||
722 | return; | 724 | return; |
723 | 725 | ||
724 | case NAND_CMD_RNDOUT: | 726 | case NAND_CMD_RNDOUT: |
@@ -784,7 +786,7 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state) | |||
784 | spinlock_t *lock = &chip->controller->lock; | 786 | spinlock_t *lock = &chip->controller->lock; |
785 | wait_queue_head_t *wq = &chip->controller->wq; | 787 | wait_queue_head_t *wq = &chip->controller->wq; |
786 | DECLARE_WAITQUEUE(wait, current); | 788 | DECLARE_WAITQUEUE(wait, current); |
787 | retry: | 789 | retry: |
788 | spin_lock(lock); | 790 | spin_lock(lock); |
789 | 791 | ||
790 | /* Hardware controller shared among independent devices */ | 792 | /* Hardware controller shared among independent devices */ |
@@ -834,7 +836,7 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip, | |||
834 | break; | 836 | break; |
835 | } | 837 | } |
836 | mdelay(1); | 838 | mdelay(1); |
837 | } | 839 | } |
838 | } | 840 | } |
839 | 841 | ||
840 | /** | 842 | /** |
@@ -980,6 +982,7 @@ out: | |||
980 | 982 | ||
981 | return ret; | 983 | return ret; |
982 | } | 984 | } |
985 | EXPORT_SYMBOL(nand_unlock); | ||
983 | 986 | ||
984 | /** | 987 | /** |
985 | * nand_lock - [REPLACEABLE] locks all blocks present in the device | 988 | * nand_lock - [REPLACEABLE] locks all blocks present in the device |
@@ -1049,6 +1052,7 @@ out: | |||
1049 | 1052 | ||
1050 | return ret; | 1053 | return ret; |
1051 | } | 1054 | } |
1055 | EXPORT_SYMBOL(nand_lock); | ||
1052 | 1056 | ||
1053 | /** | 1057 | /** |
1054 | * nand_read_page_raw - [Intern] read raw page data without ecc | 1058 | * nand_read_page_raw - [Intern] read raw page data without ecc |
@@ -1076,8 +1080,9 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1076 | * | 1080 | * |
1077 | * We need a special oob layout and handling even when OOB isn't used. | 1081 | * We need a special oob layout and handling even when OOB isn't used. |
1078 | */ | 1082 | */ |
1079 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1083 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, |
1080 | uint8_t *buf, int page) | 1084 | struct nand_chip *chip, |
1085 | uint8_t *buf, int page) | ||
1081 | { | 1086 | { |
1082 | int eccsize = chip->ecc.size; | 1087 | int eccsize = chip->ecc.size; |
1083 | int eccbytes = chip->ecc.bytes; | 1088 | int eccbytes = chip->ecc.bytes; |
@@ -1158,7 +1163,8 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1158 | * @readlen: data length | 1163 | * @readlen: data length |
1159 | * @bufpoi: buffer to store read data | 1164 | * @bufpoi: buffer to store read data |
1160 | */ | 1165 | */ |
1161 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | 1166 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, |
1167 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | ||
1162 | { | 1168 | { |
1163 | int start_step, end_step, num_steps; | 1169 | int start_step, end_step, num_steps; |
1164 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1170 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
@@ -1166,6 +1172,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3 | |||
1166 | int data_col_addr, i, gaps = 0; | 1172 | int data_col_addr, i, gaps = 0; |
1167 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | 1173 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; |
1168 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1174 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; |
1175 | int index = 0; | ||
1169 | 1176 | ||
1170 | /* Column address wihin the page aligned to ECC size (256bytes). */ | 1177 | /* Column address wihin the page aligned to ECC size (256bytes). */ |
1171 | start_step = data_offs / chip->ecc.size; | 1178 | start_step = data_offs / chip->ecc.size; |
@@ -1204,26 +1211,30 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3 | |||
1204 | } else { | 1211 | } else { |
1205 | /* send the command to read the particular ecc bytes */ | 1212 | /* send the command to read the particular ecc bytes */ |
1206 | /* take care about buswidth alignment in read_buf */ | 1213 | /* take care about buswidth alignment in read_buf */ |
1207 | aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1); | 1214 | index = start_step * chip->ecc.bytes; |
1215 | |||
1216 | aligned_pos = eccpos[index] & ~(busw - 1); | ||
1208 | aligned_len = eccfrag_len; | 1217 | aligned_len = eccfrag_len; |
1209 | if (eccpos[start_step * chip->ecc.bytes] & (busw - 1)) | 1218 | if (eccpos[index] & (busw - 1)) |
1210 | aligned_len++; | 1219 | aligned_len++; |
1211 | if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1)) | 1220 | if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) |
1212 | aligned_len++; | 1221 | aligned_len++; |
1213 | 1222 | ||
1214 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1); | 1223 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, |
1224 | mtd->writesize + aligned_pos, -1); | ||
1215 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); | 1225 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); |
1216 | } | 1226 | } |
1217 | 1227 | ||
1218 | for (i = 0; i < eccfrag_len; i++) | 1228 | for (i = 0; i < eccfrag_len; i++) |
1219 | chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + start_step * chip->ecc.bytes]]; | 1229 | chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]]; |
1220 | 1230 | ||
1221 | p = bufpoi + data_col_addr; | 1231 | p = bufpoi + data_col_addr; |
1222 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { | 1232 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { |
1223 | int stat; | 1233 | int stat; |
1224 | 1234 | ||
1225 | stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); | 1235 | stat = chip->ecc.correct(mtd, p, |
1226 | if (stat == -1) | 1236 | &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); |
1237 | if (stat < 0) | ||
1227 | mtd->ecc_stats.failed++; | 1238 | mtd->ecc_stats.failed++; |
1228 | else | 1239 | else |
1229 | mtd->ecc_stats.corrected += stat; | 1240 | mtd->ecc_stats.corrected += stat; |
@@ -1390,7 +1401,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1390 | static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | 1401 | static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, |
1391 | struct mtd_oob_ops *ops, size_t len) | 1402 | struct mtd_oob_ops *ops, size_t len) |
1392 | { | 1403 | { |
1393 | switch(ops->mode) { | 1404 | switch (ops->mode) { |
1394 | 1405 | ||
1395 | case MTD_OOB_PLACE: | 1406 | case MTD_OOB_PLACE: |
1396 | case MTD_OOB_RAW: | 1407 | case MTD_OOB_RAW: |
@@ -1402,7 +1413,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | |||
1402 | uint32_t boffs = 0, roffs = ops->ooboffs; | 1413 | uint32_t boffs = 0, roffs = ops->ooboffs; |
1403 | size_t bytes = 0; | 1414 | size_t bytes = 0; |
1404 | 1415 | ||
1405 | for(; free->length && len; free++, len -= bytes) { | 1416 | for (; free->length && len; free++, len -= bytes) { |
1406 | /* Read request not from offset 0 ? */ | 1417 | /* Read request not from offset 0 ? */ |
1407 | if (unlikely(roffs)) { | 1418 | if (unlikely(roffs)) { |
1408 | if (roffs >= free->length) { | 1419 | if (roffs >= free->length) { |
@@ -1466,7 +1477,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1466 | buf = ops->datbuf; | 1477 | buf = ops->datbuf; |
1467 | oob = ops->oobbuf; | 1478 | oob = ops->oobbuf; |
1468 | 1479 | ||
1469 | while(1) { | 1480 | while (1) { |
1470 | bytes = min(mtd->writesize - col, readlen); | 1481 | bytes = min(mtd->writesize - col, readlen); |
1471 | aligned = (bytes == mtd->writesize); | 1482 | aligned = (bytes == mtd->writesize); |
1472 | 1483 | ||
@@ -1484,7 +1495,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1484 | ret = chip->ecc.read_page_raw(mtd, chip, | 1495 | ret = chip->ecc.read_page_raw(mtd, chip, |
1485 | bufpoi, page); | 1496 | bufpoi, page); |
1486 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) | 1497 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) |
1487 | ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi); | 1498 | ret = chip->ecc.read_subpage(mtd, chip, |
1499 | col, bytes, bufpoi); | ||
1488 | else | 1500 | else |
1489 | ret = chip->ecc.read_page(mtd, chip, bufpoi, | 1501 | ret = chip->ecc.read_page(mtd, chip, bufpoi, |
1490 | page); | 1502 | page); |
@@ -1493,7 +1505,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1493 | 1505 | ||
1494 | /* Transfer not aligned data */ | 1506 | /* Transfer not aligned data */ |
1495 | if (!aligned) { | 1507 | if (!aligned) { |
1496 | if (!NAND_SUBPAGE_READ(chip) && !oob) | 1508 | if (!NAND_SUBPAGE_READ(chip) && !oob && |
1509 | !(mtd->ecc_stats.failed - stats.failed)) | ||
1497 | chip->pagebuf = realpage; | 1510 | chip->pagebuf = realpage; |
1498 | memcpy(buf, chip->buffers->databuf + col, bytes); | 1511 | memcpy(buf, chip->buffers->databuf + col, bytes); |
1499 | } | 1512 | } |
@@ -1791,7 +1804,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1791 | realpage = (int)(from >> chip->page_shift); | 1804 | realpage = (int)(from >> chip->page_shift); |
1792 | page = realpage & chip->pagemask; | 1805 | page = realpage & chip->pagemask; |
1793 | 1806 | ||
1794 | while(1) { | 1807 | while (1) { |
1795 | sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); | 1808 | sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); |
1796 | 1809 | ||
1797 | len = min(len, readlen); | 1810 | len = min(len, readlen); |
@@ -1861,7 +1874,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1861 | 1874 | ||
1862 | nand_get_device(chip, mtd, FL_READING); | 1875 | nand_get_device(chip, mtd, FL_READING); |
1863 | 1876 | ||
1864 | switch(ops->mode) { | 1877 | switch (ops->mode) { |
1865 | case MTD_OOB_PLACE: | 1878 | case MTD_OOB_PLACE: |
1866 | case MTD_OOB_AUTO: | 1879 | case MTD_OOB_AUTO: |
1867 | case MTD_OOB_RAW: | 1880 | case MTD_OOB_RAW: |
@@ -1876,7 +1889,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1876 | else | 1889 | else |
1877 | ret = nand_do_read_ops(mtd, from, ops); | 1890 | ret = nand_do_read_ops(mtd, from, ops); |
1878 | 1891 | ||
1879 | out: | 1892 | out: |
1880 | nand_release_device(mtd); | 1893 | nand_release_device(mtd); |
1881 | return ret; | 1894 | return ret; |
1882 | } | 1895 | } |
@@ -1905,8 +1918,9 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1905 | * | 1918 | * |
1906 | * We need a special oob layout and handling even when ECC isn't checked. | 1919 | * We need a special oob layout and handling even when ECC isn't checked. |
1907 | */ | 1920 | */ |
1908 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1921 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, |
1909 | const uint8_t *buf) | 1922 | struct nand_chip *chip, |
1923 | const uint8_t *buf) | ||
1910 | { | 1924 | { |
1911 | int eccsize = chip->ecc.size; | 1925 | int eccsize = chip->ecc.size; |
1912 | int eccbytes = chip->ecc.bytes; | 1926 | int eccbytes = chip->ecc.bytes; |
@@ -2099,7 +2113,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
2099 | static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | 2113 | static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, |
2100 | struct mtd_oob_ops *ops) | 2114 | struct mtd_oob_ops *ops) |
2101 | { | 2115 | { |
2102 | switch(ops->mode) { | 2116 | switch (ops->mode) { |
2103 | 2117 | ||
2104 | case MTD_OOB_PLACE: | 2118 | case MTD_OOB_PLACE: |
2105 | case MTD_OOB_RAW: | 2119 | case MTD_OOB_RAW: |
@@ -2111,7 +2125,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | |||
2111 | uint32_t boffs = 0, woffs = ops->ooboffs; | 2125 | uint32_t boffs = 0, woffs = ops->ooboffs; |
2112 | size_t bytes = 0; | 2126 | size_t bytes = 0; |
2113 | 2127 | ||
2114 | for(; free->length && len; free++, len -= bytes) { | 2128 | for (; free->length && len; free++, len -= bytes) { |
2115 | /* Write request not from offset 0 ? */ | 2129 | /* Write request not from offset 0 ? */ |
2116 | if (unlikely(woffs)) { | 2130 | if (unlikely(woffs)) { |
2117 | if (woffs >= free->length) { | 2131 | if (woffs >= free->length) { |
@@ -2137,7 +2151,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | |||
2137 | return NULL; | 2151 | return NULL; |
2138 | } | 2152 | } |
2139 | 2153 | ||
2140 | #define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0 | 2154 | #define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0) |
2141 | 2155 | ||
2142 | /** | 2156 | /** |
2143 | * nand_do_write_ops - [Internal] NAND write with ECC | 2157 | * nand_do_write_ops - [Internal] NAND write with ECC |
@@ -2200,10 +2214,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2200 | memset(chip->oob_poi, 0xff, mtd->oobsize); | 2214 | memset(chip->oob_poi, 0xff, mtd->oobsize); |
2201 | 2215 | ||
2202 | /* Don't allow multipage oob writes with offset */ | 2216 | /* Don't allow multipage oob writes with offset */ |
2203 | if (ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) | 2217 | if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) |
2204 | return -EINVAL; | 2218 | return -EINVAL; |
2205 | 2219 | ||
2206 | while(1) { | 2220 | while (1) { |
2207 | int bytes = mtd->writesize; | 2221 | int bytes = mtd->writesize; |
2208 | int cached = writelen > bytes && page != blockmask; | 2222 | int cached = writelen > bytes && page != blockmask; |
2209 | uint8_t *wbuf = buf; | 2223 | uint8_t *wbuf = buf; |
@@ -2431,7 +2445,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
2431 | 2445 | ||
2432 | nand_get_device(chip, mtd, FL_WRITING); | 2446 | nand_get_device(chip, mtd, FL_WRITING); |
2433 | 2447 | ||
2434 | switch(ops->mode) { | 2448 | switch (ops->mode) { |
2435 | case MTD_OOB_PLACE: | 2449 | case MTD_OOB_PLACE: |
2436 | case MTD_OOB_AUTO: | 2450 | case MTD_OOB_AUTO: |
2437 | case MTD_OOB_RAW: | 2451 | case MTD_OOB_RAW: |
@@ -2446,7 +2460,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
2446 | else | 2460 | else |
2447 | ret = nand_do_write_ops(mtd, to, ops); | 2461 | ret = nand_do_write_ops(mtd, to, ops); |
2448 | 2462 | ||
2449 | out: | 2463 | out: |
2450 | nand_release_device(mtd); | 2464 | nand_release_device(mtd); |
2451 | return ret; | 2465 | return ret; |
2452 | } | 2466 | } |
@@ -2511,7 +2525,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2511 | { | 2525 | { |
2512 | int page, status, pages_per_block, ret, chipnr; | 2526 | int page, status, pages_per_block, ret, chipnr; |
2513 | struct nand_chip *chip = mtd->priv; | 2527 | struct nand_chip *chip = mtd->priv; |
2514 | loff_t rewrite_bbt[NAND_MAX_CHIPS]={0}; | 2528 | loff_t rewrite_bbt[NAND_MAX_CHIPS] = {0}; |
2515 | unsigned int bbt_masked_page = 0xffffffff; | 2529 | unsigned int bbt_masked_page = 0xffffffff; |
2516 | loff_t len; | 2530 | loff_t len; |
2517 | 2531 | ||
@@ -2632,7 +2646,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2632 | } | 2646 | } |
2633 | instr->state = MTD_ERASE_DONE; | 2647 | instr->state = MTD_ERASE_DONE; |
2634 | 2648 | ||
2635 | erase_exit: | 2649 | erase_exit: |
2636 | 2650 | ||
2637 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; | 2651 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; |
2638 | 2652 | ||
@@ -2706,7 +2720,8 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
2706 | struct nand_chip *chip = mtd->priv; | 2720 | struct nand_chip *chip = mtd->priv; |
2707 | int ret; | 2721 | int ret; |
2708 | 2722 | ||
2709 | if ((ret = nand_block_isbad(mtd, ofs))) { | 2723 | ret = nand_block_isbad(mtd, ofs); |
2724 | if (ret) { | ||
2710 | /* If it was bad already, return success and do nothing. */ | 2725 | /* If it was bad already, return success and do nothing. */ |
2711 | if (ret > 0) | 2726 | if (ret > 0) |
2712 | return 0; | 2727 | return 0; |
@@ -2787,15 +2802,115 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) | |||
2787 | } | 2802 | } |
2788 | 2803 | ||
2789 | /* | 2804 | /* |
2805 | * sanitize ONFI strings so we can safely print them | ||
2806 | */ | ||
2807 | static void sanitize_string(uint8_t *s, size_t len) | ||
2808 | { | ||
2809 | ssize_t i; | ||
2810 | |||
2811 | /* null terminate */ | ||
2812 | s[len - 1] = 0; | ||
2813 | |||
2814 | /* remove non printable chars */ | ||
2815 | for (i = 0; i < len - 1; i++) { | ||
2816 | if (s[i] < ' ' || s[i] > 127) | ||
2817 | s[i] = '?'; | ||
2818 | } | ||
2819 | |||
2820 | /* remove trailing spaces */ | ||
2821 | strim(s); | ||
2822 | } | ||
2823 | |||
2824 | static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) | ||
2825 | { | ||
2826 | int i; | ||
2827 | while (len--) { | ||
2828 | crc ^= *p++ << 8; | ||
2829 | for (i = 0; i < 8; i++) | ||
2830 | crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0); | ||
2831 | } | ||
2832 | |||
2833 | return crc; | ||
2834 | } | ||
2835 | |||
2836 | /* | ||
2837 | * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise | ||
2838 | */ | ||
2839 | static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | ||
2840 | int busw) | ||
2841 | { | ||
2842 | struct nand_onfi_params *p = &chip->onfi_params; | ||
2843 | int i; | ||
2844 | int val; | ||
2845 | |||
2846 | /* try ONFI for unknow chip or LP */ | ||
2847 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); | ||
2848 | if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || | ||
2849 | chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') | ||
2850 | return 0; | ||
2851 | |||
2852 | printk(KERN_INFO "ONFI flash detected\n"); | ||
2853 | chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); | ||
2854 | for (i = 0; i < 3; i++) { | ||
2855 | chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); | ||
2856 | if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == | ||
2857 | le16_to_cpu(p->crc)) { | ||
2858 | printk(KERN_INFO "ONFI param page %d valid\n", i); | ||
2859 | break; | ||
2860 | } | ||
2861 | } | ||
2862 | |||
2863 | if (i == 3) | ||
2864 | return 0; | ||
2865 | |||
2866 | /* check version */ | ||
2867 | val = le16_to_cpu(p->revision); | ||
2868 | if (val == 1 || val > (1 << 4)) { | ||
2869 | printk(KERN_INFO "%s: unsupported ONFI version: %d\n", | ||
2870 | __func__, val); | ||
2871 | return 0; | ||
2872 | } | ||
2873 | |||
2874 | if (val & (1 << 4)) | ||
2875 | chip->onfi_version = 22; | ||
2876 | else if (val & (1 << 3)) | ||
2877 | chip->onfi_version = 21; | ||
2878 | else if (val & (1 << 2)) | ||
2879 | chip->onfi_version = 20; | ||
2880 | else | ||
2881 | chip->onfi_version = 10; | ||
2882 | |||
2883 | sanitize_string(p->manufacturer, sizeof(p->manufacturer)); | ||
2884 | sanitize_string(p->model, sizeof(p->model)); | ||
2885 | if (!mtd->name) | ||
2886 | mtd->name = p->model; | ||
2887 | mtd->writesize = le32_to_cpu(p->byte_per_page); | ||
2888 | mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize; | ||
2889 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); | ||
2890 | chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize; | ||
2891 | busw = 0; | ||
2892 | if (le16_to_cpu(p->features) & 1) | ||
2893 | busw = NAND_BUSWIDTH_16; | ||
2894 | |||
2895 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | ||
2896 | chip->options |= (NAND_NO_READRDY | | ||
2897 | NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK; | ||
2898 | |||
2899 | return 1; | ||
2900 | } | ||
2901 | |||
2902 | /* | ||
2790 | * Get the flash and manufacturer id and lookup if the type is supported | 2903 | * Get the flash and manufacturer id and lookup if the type is supported |
2791 | */ | 2904 | */ |
2792 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | 2905 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, |
2793 | struct nand_chip *chip, | 2906 | struct nand_chip *chip, |
2794 | int busw, int *maf_id, | 2907 | int busw, |
2908 | int *maf_id, int *dev_id, | ||
2795 | struct nand_flash_dev *type) | 2909 | struct nand_flash_dev *type) |
2796 | { | 2910 | { |
2797 | int i, dev_id, maf_idx; | 2911 | int i, maf_idx; |
2798 | u8 id_data[8]; | 2912 | u8 id_data[8]; |
2913 | int ret; | ||
2799 | 2914 | ||
2800 | /* Select the device */ | 2915 | /* Select the device */ |
2801 | chip->select_chip(mtd, 0); | 2916 | chip->select_chip(mtd, 0); |
@@ -2811,7 +2926,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2811 | 2926 | ||
2812 | /* Read manufacturer and device IDs */ | 2927 | /* Read manufacturer and device IDs */ |
2813 | *maf_id = chip->read_byte(mtd); | 2928 | *maf_id = chip->read_byte(mtd); |
2814 | dev_id = chip->read_byte(mtd); | 2929 | *dev_id = chip->read_byte(mtd); |
2815 | 2930 | ||
2816 | /* Try again to make sure, as some systems the bus-hold or other | 2931 | /* Try again to make sure, as some systems the bus-hold or other |
2817 | * interface concerns can cause random data which looks like a | 2932 | * interface concerns can cause random data which looks like a |
@@ -2821,15 +2936,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2821 | 2936 | ||
2822 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 2937 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
2823 | 2938 | ||
2824 | /* Read entire ID string */ | 2939 | for (i = 0; i < 2; i++) |
2825 | |||
2826 | for (i = 0; i < 8; i++) | ||
2827 | id_data[i] = chip->read_byte(mtd); | 2940 | id_data[i] = chip->read_byte(mtd); |
2828 | 2941 | ||
2829 | if (id_data[0] != *maf_id || id_data[1] != dev_id) { | 2942 | if (id_data[0] != *maf_id || id_data[1] != *dev_id) { |
2830 | printk(KERN_INFO "%s: second ID read did not match " | 2943 | printk(KERN_INFO "%s: second ID read did not match " |
2831 | "%02x,%02x against %02x,%02x\n", __func__, | 2944 | "%02x,%02x against %02x,%02x\n", __func__, |
2832 | *maf_id, dev_id, id_data[0], id_data[1]); | 2945 | *maf_id, *dev_id, id_data[0], id_data[1]); |
2833 | return ERR_PTR(-ENODEV); | 2946 | return ERR_PTR(-ENODEV); |
2834 | } | 2947 | } |
2835 | 2948 | ||
@@ -2837,8 +2950,23 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2837 | type = nand_flash_ids; | 2950 | type = nand_flash_ids; |
2838 | 2951 | ||
2839 | for (; type->name != NULL; type++) | 2952 | for (; type->name != NULL; type++) |
2840 | if (dev_id == type->id) | 2953 | if (*dev_id == type->id) |
2841 | break; | 2954 | break; |
2955 | |||
2956 | chip->onfi_version = 0; | ||
2957 | if (!type->name || !type->pagesize) { | ||
2958 | /* Check is chip is ONFI compliant */ | ||
2959 | ret = nand_flash_detect_onfi(mtd, chip, busw); | ||
2960 | if (ret) | ||
2961 | goto ident_done; | ||
2962 | } | ||
2963 | |||
2964 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | ||
2965 | |||
2966 | /* Read entire ID string */ | ||
2967 | |||
2968 | for (i = 0; i < 8; i++) | ||
2969 | id_data[i] = chip->read_byte(mtd); | ||
2842 | 2970 | ||
2843 | if (!type->name) | 2971 | if (!type->name) |
2844 | return ERR_PTR(-ENODEV); | 2972 | return ERR_PTR(-ENODEV); |
@@ -2848,8 +2976,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2848 | 2976 | ||
2849 | chip->chipsize = (uint64_t)type->chipsize << 20; | 2977 | chip->chipsize = (uint64_t)type->chipsize << 20; |
2850 | 2978 | ||
2851 | /* Newer devices have all the information in additional id bytes */ | 2979 | if (!type->pagesize && chip->init_size) { |
2852 | if (!type->pagesize) { | 2980 | /* set the pagesize, oobsize, erasesize by the driver*/ |
2981 | busw = chip->init_size(mtd, chip, id_data); | ||
2982 | } else if (!type->pagesize) { | ||
2853 | int extid; | 2983 | int extid; |
2854 | /* The 3rd id byte holds MLC / multichip data */ | 2984 | /* The 3rd id byte holds MLC / multichip data */ |
2855 | chip->cellinfo = id_data[2]; | 2985 | chip->cellinfo = id_data[2]; |
@@ -2859,7 +2989,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2859 | /* | 2989 | /* |
2860 | * Field definitions are in the following datasheets: | 2990 | * Field definitions are in the following datasheets: |
2861 | * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) | 2991 | * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) |
2862 | * New style (6 byte ID): Samsung K9GAG08U0D (p.40) | 2992 | * New style (6 byte ID): Samsung K9GBG08U0M (p.40) |
2863 | * | 2993 | * |
2864 | * Check for wraparound + Samsung ID + nonzero 6th byte | 2994 | * Check for wraparound + Samsung ID + nonzero 6th byte |
2865 | * to decide what to do. | 2995 | * to decide what to do. |
@@ -2872,7 +3002,20 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2872 | mtd->writesize = 2048 << (extid & 0x03); | 3002 | mtd->writesize = 2048 << (extid & 0x03); |
2873 | extid >>= 2; | 3003 | extid >>= 2; |
2874 | /* Calc oobsize */ | 3004 | /* Calc oobsize */ |
2875 | mtd->oobsize = (extid & 0x03) == 0x01 ? 128 : 218; | 3005 | switch (extid & 0x03) { |
3006 | case 1: | ||
3007 | mtd->oobsize = 128; | ||
3008 | break; | ||
3009 | case 2: | ||
3010 | mtd->oobsize = 218; | ||
3011 | break; | ||
3012 | case 3: | ||
3013 | mtd->oobsize = 400; | ||
3014 | break; | ||
3015 | default: | ||
3016 | mtd->oobsize = 436; | ||
3017 | break; | ||
3018 | } | ||
2876 | extid >>= 2; | 3019 | extid >>= 2; |
2877 | /* Calc blocksize */ | 3020 | /* Calc blocksize */ |
2878 | mtd->erasesize = (128 * 1024) << | 3021 | mtd->erasesize = (128 * 1024) << |
@@ -2900,7 +3043,35 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2900 | mtd->writesize = type->pagesize; | 3043 | mtd->writesize = type->pagesize; |
2901 | mtd->oobsize = mtd->writesize / 32; | 3044 | mtd->oobsize = mtd->writesize / 32; |
2902 | busw = type->options & NAND_BUSWIDTH_16; | 3045 | busw = type->options & NAND_BUSWIDTH_16; |
3046 | |||
3047 | /* | ||
3048 | * Check for Spansion/AMD ID + repeating 5th, 6th byte since | ||
3049 | * some Spansion chips have erasesize that conflicts with size | ||
3050 | * listed in nand_ids table | ||
3051 | * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) | ||
3052 | */ | ||
3053 | if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && | ||
3054 | id_data[5] == 0x00 && id_data[6] == 0x00 && | ||
3055 | id_data[7] == 0x00 && mtd->writesize == 512) { | ||
3056 | mtd->erasesize = 128 * 1024; | ||
3057 | mtd->erasesize <<= ((id_data[3] & 0x03) << 1); | ||
3058 | } | ||
2903 | } | 3059 | } |
3060 | /* Get chip options, preserve non chip based options */ | ||
3061 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | ||
3062 | chip->options |= type->options & NAND_CHIPOPTIONS_MSK; | ||
3063 | |||
3064 | /* Check if chip is a not a samsung device. Do not clear the | ||
3065 | * options for chips which are not having an extended id. | ||
3066 | */ | ||
3067 | if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) | ||
3068 | chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; | ||
3069 | ident_done: | ||
3070 | |||
3071 | /* | ||
3072 | * Set chip as a default. Board drivers can override it, if necessary | ||
3073 | */ | ||
3074 | chip->options |= NAND_NO_AUTOINCR; | ||
2904 | 3075 | ||
2905 | /* Try to identify manufacturer */ | 3076 | /* Try to identify manufacturer */ |
2906 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { | 3077 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { |
@@ -2915,7 +3086,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2915 | if (busw != (chip->options & NAND_BUSWIDTH_16)) { | 3086 | if (busw != (chip->options & NAND_BUSWIDTH_16)) { |
2916 | printk(KERN_INFO "NAND device: Manufacturer ID:" | 3087 | printk(KERN_INFO "NAND device: Manufacturer ID:" |
2917 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, | 3088 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, |
2918 | dev_id, nand_manuf_ids[maf_idx].name, mtd->name); | 3089 | *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); |
2919 | printk(KERN_WARNING "NAND bus width %d instead %d bit\n", | 3090 | printk(KERN_WARNING "NAND bus width %d instead %d bit\n", |
2920 | (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, | 3091 | (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, |
2921 | busw ? 16 : 8); | 3092 | busw ? 16 : 8); |
@@ -2931,8 +3102,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2931 | ffs(mtd->erasesize) - 1; | 3102 | ffs(mtd->erasesize) - 1; |
2932 | if (chip->chipsize & 0xffffffff) | 3103 | if (chip->chipsize & 0xffffffff) |
2933 | chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; | 3104 | chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; |
2934 | else | 3105 | else { |
2935 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; | 3106 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)); |
3107 | chip->chip_shift += 32 - 1; | ||
3108 | } | ||
2936 | 3109 | ||
2937 | /* Set the bad block position */ | 3110 | /* Set the bad block position */ |
2938 | if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) | 3111 | if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) |
@@ -2940,27 +3113,12 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2940 | else | 3113 | else |
2941 | chip->badblockpos = NAND_SMALL_BADBLOCK_POS; | 3114 | chip->badblockpos = NAND_SMALL_BADBLOCK_POS; |
2942 | 3115 | ||
2943 | /* Get chip options, preserve non chip based options */ | ||
2944 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | ||
2945 | chip->options |= type->options & NAND_CHIPOPTIONS_MSK; | ||
2946 | |||
2947 | /* | ||
2948 | * Set chip as a default. Board drivers can override it, if necessary | ||
2949 | */ | ||
2950 | chip->options |= NAND_NO_AUTOINCR; | ||
2951 | |||
2952 | /* Check if chip is a not a samsung device. Do not clear the | ||
2953 | * options for chips which are not having an extended id. | ||
2954 | */ | ||
2955 | if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) | ||
2956 | chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; | ||
2957 | |||
2958 | /* | 3116 | /* |
2959 | * Bad block marker is stored in the last page of each block | 3117 | * Bad block marker is stored in the last page of each block |
2960 | * on Samsung and Hynix MLC devices; stored in first two pages | 3118 | * on Samsung and Hynix MLC devices; stored in first two pages |
2961 | * of each block on Micron devices with 2KiB pages and on | 3119 | * of each block on Micron devices with 2KiB pages and on |
2962 | * SLC Samsung, Hynix, and AMD/Spansion. All others scan only | 3120 | * SLC Samsung, Hynix, Toshiba and AMD/Spansion. All others scan |
2963 | * the first page. | 3121 | * only the first page. |
2964 | */ | 3122 | */ |
2965 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 3123 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
2966 | (*maf_id == NAND_MFR_SAMSUNG || | 3124 | (*maf_id == NAND_MFR_SAMSUNG || |
@@ -2969,6 +3127,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2969 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 3127 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
2970 | (*maf_id == NAND_MFR_SAMSUNG || | 3128 | (*maf_id == NAND_MFR_SAMSUNG || |
2971 | *maf_id == NAND_MFR_HYNIX || | 3129 | *maf_id == NAND_MFR_HYNIX || |
3130 | *maf_id == NAND_MFR_TOSHIBA || | ||
2972 | *maf_id == NAND_MFR_AMD)) || | 3131 | *maf_id == NAND_MFR_AMD)) || |
2973 | (mtd->writesize == 2048 && | 3132 | (mtd->writesize == 2048 && |
2974 | *maf_id == NAND_MFR_MICRON)) | 3133 | *maf_id == NAND_MFR_MICRON)) |
@@ -2994,9 +3153,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2994 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) | 3153 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) |
2995 | chip->cmdfunc = nand_command_lp; | 3154 | chip->cmdfunc = nand_command_lp; |
2996 | 3155 | ||
3156 | /* TODO onfi flash name */ | ||
2997 | printk(KERN_INFO "NAND device: Manufacturer ID:" | 3157 | printk(KERN_INFO "NAND device: Manufacturer ID:" |
2998 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, | 3158 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, |
2999 | nand_manuf_ids[maf_idx].name, type->name); | 3159 | nand_manuf_ids[maf_idx].name, |
3160 | chip->onfi_version ? type->name : chip->onfi_params.model); | ||
3000 | 3161 | ||
3001 | return type; | 3162 | return type; |
3002 | } | 3163 | } |
@@ -3015,7 +3176,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
3015 | int nand_scan_ident(struct mtd_info *mtd, int maxchips, | 3176 | int nand_scan_ident(struct mtd_info *mtd, int maxchips, |
3016 | struct nand_flash_dev *table) | 3177 | struct nand_flash_dev *table) |
3017 | { | 3178 | { |
3018 | int i, busw, nand_maf_id; | 3179 | int i, busw, nand_maf_id, nand_dev_id; |
3019 | struct nand_chip *chip = mtd->priv; | 3180 | struct nand_chip *chip = mtd->priv; |
3020 | struct nand_flash_dev *type; | 3181 | struct nand_flash_dev *type; |
3021 | 3182 | ||
@@ -3025,7 +3186,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3025 | nand_set_defaults(chip, busw); | 3186 | nand_set_defaults(chip, busw); |
3026 | 3187 | ||
3027 | /* Read the flash type */ | 3188 | /* Read the flash type */ |
3028 | type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, table); | 3189 | type = nand_get_flash_type(mtd, chip, busw, |
3190 | &nand_maf_id, &nand_dev_id, table); | ||
3029 | 3191 | ||
3030 | if (IS_ERR(type)) { | 3192 | if (IS_ERR(type)) { |
3031 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) | 3193 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) |
@@ -3043,7 +3205,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3043 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 3205 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
3044 | /* Read manufacturer and device IDs */ | 3206 | /* Read manufacturer and device IDs */ |
3045 | if (nand_maf_id != chip->read_byte(mtd) || | 3207 | if (nand_maf_id != chip->read_byte(mtd) || |
3046 | type->id != chip->read_byte(mtd)) | 3208 | nand_dev_id != chip->read_byte(mtd)) |
3047 | break; | 3209 | break; |
3048 | } | 3210 | } |
3049 | if (i > 1) | 3211 | if (i > 1) |
@@ -3055,6 +3217,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3055 | 3217 | ||
3056 | return 0; | 3218 | return 0; |
3057 | } | 3219 | } |
3220 | EXPORT_SYMBOL(nand_scan_ident); | ||
3058 | 3221 | ||
3059 | 3222 | ||
3060 | /** | 3223 | /** |
@@ -3219,7 +3382,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3219 | * mode | 3382 | * mode |
3220 | */ | 3383 | */ |
3221 | chip->ecc.steps = mtd->writesize / chip->ecc.size; | 3384 | chip->ecc.steps = mtd->writesize / chip->ecc.size; |
3222 | if(chip->ecc.steps * chip->ecc.size != mtd->writesize) { | 3385 | if (chip->ecc.steps * chip->ecc.size != mtd->writesize) { |
3223 | printk(KERN_WARNING "Invalid ecc parameters\n"); | 3386 | printk(KERN_WARNING "Invalid ecc parameters\n"); |
3224 | BUG(); | 3387 | BUG(); |
3225 | } | 3388 | } |
@@ -3231,7 +3394,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3231 | */ | 3394 | */ |
3232 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && | 3395 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && |
3233 | !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { | 3396 | !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { |
3234 | switch(chip->ecc.steps) { | 3397 | switch (chip->ecc.steps) { |
3235 | case 2: | 3398 | case 2: |
3236 | mtd->subpage_sft = 1; | 3399 | mtd->subpage_sft = 1; |
3237 | break; | 3400 | break; |
@@ -3283,10 +3446,11 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3283 | /* Build bad block table */ | 3446 | /* Build bad block table */ |
3284 | return chip->scan_bbt(mtd); | 3447 | return chip->scan_bbt(mtd); |
3285 | } | 3448 | } |
3449 | EXPORT_SYMBOL(nand_scan_tail); | ||
3286 | 3450 | ||
3287 | /* is_module_text_address() isn't exported, and it's mostly a pointless | 3451 | /* is_module_text_address() isn't exported, and it's mostly a pointless |
3288 | test if this is a module _anyway_ -- they'd have to try _really_ hard | 3452 | * test if this is a module _anyway_ -- they'd have to try _really_ hard |
3289 | to call us from in-kernel code if the core NAND support is modular. */ | 3453 | * to call us from in-kernel code if the core NAND support is modular. */ |
3290 | #ifdef MODULE | 3454 | #ifdef MODULE |
3291 | #define caller_is_module() (1) | 3455 | #define caller_is_module() (1) |
3292 | #else | 3456 | #else |
@@ -3322,6 +3486,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
3322 | ret = nand_scan_tail(mtd); | 3486 | ret = nand_scan_tail(mtd); |
3323 | return ret; | 3487 | return ret; |
3324 | } | 3488 | } |
3489 | EXPORT_SYMBOL(nand_scan); | ||
3325 | 3490 | ||
3326 | /** | 3491 | /** |
3327 | * nand_release - [NAND Interface] Free resources held by the NAND device | 3492 | * nand_release - [NAND Interface] Free resources held by the NAND device |
@@ -3348,12 +3513,6 @@ void nand_release(struct mtd_info *mtd) | |||
3348 | & NAND_BBT_DYNAMICSTRUCT) | 3513 | & NAND_BBT_DYNAMICSTRUCT) |
3349 | kfree(chip->badblock_pattern); | 3514 | kfree(chip->badblock_pattern); |
3350 | } | 3515 | } |
3351 | |||
3352 | EXPORT_SYMBOL_GPL(nand_lock); | ||
3353 | EXPORT_SYMBOL_GPL(nand_unlock); | ||
3354 | EXPORT_SYMBOL_GPL(nand_scan); | ||
3355 | EXPORT_SYMBOL_GPL(nand_scan_ident); | ||
3356 | EXPORT_SYMBOL_GPL(nand_scan_tail); | ||
3357 | EXPORT_SYMBOL_GPL(nand_release); | 3516 | EXPORT_SYMBOL_GPL(nand_release); |
3358 | 3517 | ||
3359 | static int __init nand_base_init(void) | 3518 | static int __init nand_base_init(void) |
@@ -3371,5 +3530,6 @@ module_init(nand_base_init); | |||
3371 | module_exit(nand_base_exit); | 3530 | module_exit(nand_base_exit); |
3372 | 3531 | ||
3373 | MODULE_LICENSE("GPL"); | 3532 | MODULE_LICENSE("GPL"); |
3374 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); | 3533 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>"); |
3534 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); | ||
3375 | MODULE_DESCRIPTION("Generic NAND flash driver code"); | 3535 | MODULE_DESCRIPTION("Generic NAND flash driver code"); |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 5fedf4a74f16..586b981f0e61 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -13,28 +13,37 @@ | |||
13 | * Description: | 13 | * Description: |
14 | * | 14 | * |
15 | * When nand_scan_bbt is called, then it tries to find the bad block table | 15 | * When nand_scan_bbt is called, then it tries to find the bad block table |
16 | * depending on the options in the bbt descriptor(s). If a bbt is found | 16 | * depending on the options in the BBT descriptor(s). If no flash based BBT |
17 | * then the contents are read and the memory based bbt is created. If a | 17 | * (NAND_USE_FLASH_BBT) is specified then the device is scanned for factory |
18 | * mirrored bbt is selected then the mirror is searched too and the | 18 | * marked good / bad blocks. This information is used to create a memory BBT. |
19 | * versions are compared. If the mirror has a greater version number | 19 | * Once a new bad block is discovered then the "factory" information is updated |
20 | * than the mirror bbt is used to build the memory based bbt. | 20 | * on the device. |
21 | * If a flash based BBT is specified then the function first tries to find the | ||
22 | * BBT on flash. If a BBT is found then the contents are read and the memory | ||
23 | * based BBT is created. If a mirrored BBT is selected then the mirror is | ||
24 | * searched too and the versions are compared. If the mirror has a greater | ||
25 | * version number than the mirror BBT is used to build the memory based BBT. | ||
21 | * If the tables are not versioned, then we "or" the bad block information. | 26 | * If the tables are not versioned, then we "or" the bad block information. |
22 | * If one of the bbt's is out of date or does not exist it is (re)created. | 27 | * If one of the BBTs is out of date or does not exist it is (re)created. |
23 | * If no bbt exists at all then the device is scanned for factory marked | 28 | * If no BBT exists at all then the device is scanned for factory marked |
24 | * good / bad blocks and the bad block tables are created. | 29 | * good / bad blocks and the bad block tables are created. |
25 | * | 30 | * |
26 | * For manufacturer created bbts like the one found on M-SYS DOC devices | 31 | * For manufacturer created BBTs like the one found on M-SYS DOC devices |
27 | * the bbt is searched and read but never created | 32 | * the BBT is searched and read but never created |
28 | * | 33 | * |
29 | * The autogenerated bad block table is located in the last good blocks | 34 | * The auto generated bad block table is located in the last good blocks |
30 | * of the device. The table is mirrored, so it can be updated eventually. | 35 | * of the device. The table is mirrored, so it can be updated eventually. |
31 | * The table is marked in the oob area with an ident pattern and a version | 36 | * The table is marked in the OOB area with an ident pattern and a version |
32 | * number which indicates which of both tables is more up to date. | 37 | * number which indicates which of both tables is more up to date. If the NAND |
38 | * controller needs the complete OOB area for the ECC information then the | ||
39 | * option NAND_USE_FLASH_BBT_NO_OOB should be used: it moves the ident pattern | ||
40 | * and the version byte into the data area and the OOB area will remain | ||
41 | * untouched. | ||
33 | * | 42 | * |
34 | * The table uses 2 bits per block | 43 | * The table uses 2 bits per block |
35 | * 11b: block is good | 44 | * 11b: block is good |
36 | * 00b: block is factory marked bad | 45 | * 00b: block is factory marked bad |
37 | * 01b, 10b: block is marked bad due to wear | 46 | * 01b, 10b: block is marked bad due to wear |
38 | * | 47 | * |
39 | * The memory bad block table uses the following scheme: | 48 | * The memory bad block table uses the following scheme: |
40 | * 00b: block is good | 49 | * 00b: block is good |
@@ -59,6 +68,16 @@ | |||
59 | #include <linux/delay.h> | 68 | #include <linux/delay.h> |
60 | #include <linux/vmalloc.h> | 69 | #include <linux/vmalloc.h> |
61 | 70 | ||
71 | static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = memcmp(buf, td->pattern, td->len); | ||
76 | if (!ret) | ||
77 | return ret; | ||
78 | return -1; | ||
79 | } | ||
80 | |||
62 | /** | 81 | /** |
63 | * check_pattern - [GENERIC] check if a pattern is in the buffer | 82 | * check_pattern - [GENERIC] check if a pattern is in the buffer |
64 | * @buf: the buffer to search | 83 | * @buf: the buffer to search |
@@ -77,6 +96,9 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc | |||
77 | int i, end = 0; | 96 | int i, end = 0; |
78 | uint8_t *p = buf; | 97 | uint8_t *p = buf; |
79 | 98 | ||
99 | if (td->options & NAND_BBT_NO_OOB) | ||
100 | return check_pattern_no_oob(buf, td); | ||
101 | |||
80 | end = paglen + td->offs; | 102 | end = paglen + td->offs; |
81 | if (td->options & NAND_BBT_SCANEMPTY) { | 103 | if (td->options & NAND_BBT_SCANEMPTY) { |
82 | for (i = 0; i < end; i++) { | 104 | for (i = 0; i < end; i++) { |
@@ -156,32 +178,63 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) | |||
156 | } | 178 | } |
157 | 179 | ||
158 | /** | 180 | /** |
181 | * add_marker_len - compute the length of the marker in data area | ||
182 | * @td: BBT descriptor used for computation | ||
183 | * | ||
184 | * The length will be 0 if the markeris located in OOB area. | ||
185 | */ | ||
186 | static u32 add_marker_len(struct nand_bbt_descr *td) | ||
187 | { | ||
188 | u32 len; | ||
189 | |||
190 | if (!(td->options & NAND_BBT_NO_OOB)) | ||
191 | return 0; | ||
192 | |||
193 | len = td->len; | ||
194 | if (td->options & NAND_BBT_VERSION) | ||
195 | len++; | ||
196 | return len; | ||
197 | } | ||
198 | |||
199 | /** | ||
159 | * read_bbt - [GENERIC] Read the bad block table starting from page | 200 | * read_bbt - [GENERIC] Read the bad block table starting from page |
160 | * @mtd: MTD device structure | 201 | * @mtd: MTD device structure |
161 | * @buf: temporary buffer | 202 | * @buf: temporary buffer |
162 | * @page: the starting page | 203 | * @page: the starting page |
163 | * @num: the number of bbt descriptors to read | 204 | * @num: the number of bbt descriptors to read |
164 | * @bits: number of bits per block | 205 | * @td: the bbt describtion table |
165 | * @offs: offset in the memory table | 206 | * @offs: offset in the memory table |
166 | * @reserved_block_code: Pattern to identify reserved blocks | ||
167 | * | 207 | * |
168 | * Read the bad block table starting from page. | 208 | * Read the bad block table starting from page. |
169 | * | 209 | * |
170 | */ | 210 | */ |
171 | static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, | 211 | static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, |
172 | int bits, int offs, int reserved_block_code) | 212 | struct nand_bbt_descr *td, int offs) |
173 | { | 213 | { |
174 | int res, i, j, act = 0; | 214 | int res, i, j, act = 0; |
175 | struct nand_chip *this = mtd->priv; | 215 | struct nand_chip *this = mtd->priv; |
176 | size_t retlen, len, totlen; | 216 | size_t retlen, len, totlen; |
177 | loff_t from; | 217 | loff_t from; |
218 | int bits = td->options & NAND_BBT_NRBITS_MSK; | ||
178 | uint8_t msk = (uint8_t) ((1 << bits) - 1); | 219 | uint8_t msk = (uint8_t) ((1 << bits) - 1); |
220 | u32 marker_len; | ||
221 | int reserved_block_code = td->reserved_block_code; | ||
179 | 222 | ||
180 | totlen = (num * bits) >> 3; | 223 | totlen = (num * bits) >> 3; |
224 | marker_len = add_marker_len(td); | ||
181 | from = ((loff_t) page) << this->page_shift; | 225 | from = ((loff_t) page) << this->page_shift; |
182 | 226 | ||
183 | while (totlen) { | 227 | while (totlen) { |
184 | len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); | 228 | len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); |
229 | if (marker_len) { | ||
230 | /* | ||
231 | * In case the BBT marker is not in the OOB area it | ||
232 | * will be just in the first page. | ||
233 | */ | ||
234 | len -= marker_len; | ||
235 | from += marker_len; | ||
236 | marker_len = 0; | ||
237 | } | ||
185 | res = mtd->read(mtd, from, len, &retlen, buf); | 238 | res = mtd->read(mtd, from, len, &retlen, buf); |
186 | if (res < 0) { | 239 | if (res < 0) { |
187 | if (retlen != len) { | 240 | if (retlen != len) { |
@@ -238,20 +291,21 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
238 | { | 291 | { |
239 | struct nand_chip *this = mtd->priv; | 292 | struct nand_chip *this = mtd->priv; |
240 | int res = 0, i; | 293 | int res = 0, i; |
241 | int bits; | ||
242 | 294 | ||
243 | bits = td->options & NAND_BBT_NRBITS_MSK; | ||
244 | if (td->options & NAND_BBT_PERCHIP) { | 295 | if (td->options & NAND_BBT_PERCHIP) { |
245 | int offs = 0; | 296 | int offs = 0; |
246 | for (i = 0; i < this->numchips; i++) { | 297 | for (i = 0; i < this->numchips; i++) { |
247 | if (chip == -1 || chip == i) | 298 | if (chip == -1 || chip == i) |
248 | res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code); | 299 | res = read_bbt(mtd, buf, td->pages[i], |
300 | this->chipsize >> this->bbt_erase_shift, | ||
301 | td, offs); | ||
249 | if (res) | 302 | if (res) |
250 | return res; | 303 | return res; |
251 | offs += this->chipsize >> (this->bbt_erase_shift + 2); | 304 | offs += this->chipsize >> (this->bbt_erase_shift + 2); |
252 | } | 305 | } |
253 | } else { | 306 | } else { |
254 | res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code); | 307 | res = read_bbt(mtd, buf, td->pages[0], |
308 | mtd->size >> this->bbt_erase_shift, td, 0); | ||
255 | if (res) | 309 | if (res) |
256 | return res; | 310 | return res; |
257 | } | 311 | } |
@@ -259,9 +313,25 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
259 | } | 313 | } |
260 | 314 | ||
261 | /* | 315 | /* |
316 | * BBT marker is in the first page, no OOB. | ||
317 | */ | ||
318 | static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | ||
319 | struct nand_bbt_descr *td) | ||
320 | { | ||
321 | size_t retlen; | ||
322 | size_t len; | ||
323 | |||
324 | len = td->len; | ||
325 | if (td->options & NAND_BBT_VERSION) | ||
326 | len++; | ||
327 | |||
328 | return mtd->read(mtd, offs, len, &retlen, buf); | ||
329 | } | ||
330 | |||
331 | /* | ||
262 | * Scan read raw data from flash | 332 | * Scan read raw data from flash |
263 | */ | 333 | */ |
264 | static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | 334 | static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, |
265 | size_t len) | 335 | size_t len) |
266 | { | 336 | { |
267 | struct mtd_oob_ops ops; | 337 | struct mtd_oob_ops ops; |
@@ -294,6 +364,15 @@ static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | |||
294 | return 0; | 364 | return 0; |
295 | } | 365 | } |
296 | 366 | ||
367 | static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | ||
368 | size_t len, struct nand_bbt_descr *td) | ||
369 | { | ||
370 | if (td->options & NAND_BBT_NO_OOB) | ||
371 | return scan_read_raw_data(mtd, buf, offs, td); | ||
372 | else | ||
373 | return scan_read_raw_oob(mtd, buf, offs, len); | ||
374 | } | ||
375 | |||
297 | /* | 376 | /* |
298 | * Scan write data with oob to flash | 377 | * Scan write data with oob to flash |
299 | */ | 378 | */ |
@@ -312,6 +391,15 @@ static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, | |||
312 | return mtd->write_oob(mtd, offs, &ops); | 391 | return mtd->write_oob(mtd, offs, &ops); |
313 | } | 392 | } |
314 | 393 | ||
394 | static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) | ||
395 | { | ||
396 | u32 ver_offs = td->veroffs; | ||
397 | |||
398 | if (!(td->options & NAND_BBT_NO_OOB)) | ||
399 | ver_offs += mtd->writesize; | ||
400 | return ver_offs; | ||
401 | } | ||
402 | |||
315 | /** | 403 | /** |
316 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page | 404 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page |
317 | * @mtd: MTD device structure | 405 | * @mtd: MTD device structure |
@@ -331,8 +419,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, | |||
331 | /* Read the primary version, if available */ | 419 | /* Read the primary version, if available */ |
332 | if (td->options & NAND_BBT_VERSION) { | 420 | if (td->options & NAND_BBT_VERSION) { |
333 | scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, | 421 | scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, |
334 | mtd->writesize); | 422 | mtd->writesize, td); |
335 | td->version[0] = buf[mtd->writesize + td->veroffs]; | 423 | td->version[0] = buf[bbt_get_ver_offs(mtd, td)]; |
336 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", | 424 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", |
337 | td->pages[0], td->version[0]); | 425 | td->pages[0], td->version[0]); |
338 | } | 426 | } |
@@ -340,8 +428,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, | |||
340 | /* Read the mirror version, if available */ | 428 | /* Read the mirror version, if available */ |
341 | if (md && (md->options & NAND_BBT_VERSION)) { | 429 | if (md && (md->options & NAND_BBT_VERSION)) { |
342 | scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, | 430 | scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, |
343 | mtd->writesize); | 431 | mtd->writesize, td); |
344 | md->version[0] = buf[mtd->writesize + md->veroffs]; | 432 | md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; |
345 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", | 433 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", |
346 | md->pages[0], md->version[0]); | 434 | md->pages[0], md->version[0]); |
347 | } | 435 | } |
@@ -357,7 +445,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, | |||
357 | { | 445 | { |
358 | int ret, j; | 446 | int ret, j; |
359 | 447 | ||
360 | ret = scan_read_raw(mtd, buf, offs, readlen); | 448 | ret = scan_read_raw_oob(mtd, buf, offs, readlen); |
361 | if (ret) | 449 | if (ret) |
362 | return ret; | 450 | return ret; |
363 | 451 | ||
@@ -464,6 +552,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
464 | for (i = startblock; i < numblocks;) { | 552 | for (i = startblock; i < numblocks;) { |
465 | int ret; | 553 | int ret; |
466 | 554 | ||
555 | BUG_ON(bd->options & NAND_BBT_NO_OOB); | ||
556 | |||
467 | if (bd->options & NAND_BBT_SCANALLPAGES) | 557 | if (bd->options & NAND_BBT_SCANALLPAGES) |
468 | ret = scan_block_full(mtd, bd, from, buf, readlen, | 558 | ret = scan_block_full(mtd, bd, from, buf, readlen, |
469 | scanlen, len); | 559 | scanlen, len); |
@@ -545,11 +635,12 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
545 | loff_t offs = (loff_t)actblock << this->bbt_erase_shift; | 635 | loff_t offs = (loff_t)actblock << this->bbt_erase_shift; |
546 | 636 | ||
547 | /* Read first page */ | 637 | /* Read first page */ |
548 | scan_read_raw(mtd, buf, offs, mtd->writesize); | 638 | scan_read_raw(mtd, buf, offs, mtd->writesize, td); |
549 | if (!check_pattern(buf, scanlen, mtd->writesize, td)) { | 639 | if (!check_pattern(buf, scanlen, mtd->writesize, td)) { |
550 | td->pages[i] = actblock << blocktopage; | 640 | td->pages[i] = actblock << blocktopage; |
551 | if (td->options & NAND_BBT_VERSION) { | 641 | if (td->options & NAND_BBT_VERSION) { |
552 | td->version[i] = buf[mtd->writesize + td->veroffs]; | 642 | offs = bbt_get_ver_offs(mtd, td); |
643 | td->version[i] = buf[offs]; | ||
553 | } | 644 | } |
554 | break; | 645 | break; |
555 | } | 646 | } |
@@ -733,12 +824,26 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
733 | memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); | 824 | memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); |
734 | ooboffs = len + (pageoffs * mtd->oobsize); | 825 | ooboffs = len + (pageoffs * mtd->oobsize); |
735 | 826 | ||
827 | } else if (td->options & NAND_BBT_NO_OOB) { | ||
828 | ooboffs = 0; | ||
829 | offs = td->len; | ||
830 | /* the version byte */ | ||
831 | if (td->options & NAND_BBT_VERSION) | ||
832 | offs++; | ||
833 | /* Calc length */ | ||
834 | len = (size_t) (numblocks >> sft); | ||
835 | len += offs; | ||
836 | /* Make it page aligned ! */ | ||
837 | len = ALIGN(len, mtd->writesize); | ||
838 | /* Preset the buffer with 0xff */ | ||
839 | memset(buf, 0xff, len); | ||
840 | /* Pattern is located at the begin of first page */ | ||
841 | memcpy(buf, td->pattern, td->len); | ||
736 | } else { | 842 | } else { |
737 | /* Calc length */ | 843 | /* Calc length */ |
738 | len = (size_t) (numblocks >> sft); | 844 | len = (size_t) (numblocks >> sft); |
739 | /* Make it page aligned ! */ | 845 | /* Make it page aligned ! */ |
740 | len = (len + (mtd->writesize - 1)) & | 846 | len = ALIGN(len, mtd->writesize); |
741 | ~(mtd->writesize - 1); | ||
742 | /* Preset the buffer with 0xff */ | 847 | /* Preset the buffer with 0xff */ |
743 | memset(buf, 0xff, len + | 848 | memset(buf, 0xff, len + |
744 | (len >> this->page_shift)* mtd->oobsize); | 849 | (len >> this->page_shift)* mtd->oobsize); |
@@ -772,7 +877,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
772 | if (res < 0) | 877 | if (res < 0) |
773 | goto outerr; | 878 | goto outerr; |
774 | 879 | ||
775 | res = scan_write_bbt(mtd, to, len, buf, &buf[len]); | 880 | res = scan_write_bbt(mtd, to, len, buf, |
881 | td->options & NAND_BBT_NO_OOB ? NULL : | ||
882 | &buf[len]); | ||
776 | if (res < 0) | 883 | if (res < 0) |
777 | goto outerr; | 884 | goto outerr; |
778 | 885 | ||
@@ -892,7 +999,8 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
892 | continue; | 999 | continue; |
893 | 1000 | ||
894 | /* Create the table in memory by scanning the chip(s) */ | 1001 | /* Create the table in memory by scanning the chip(s) */ |
895 | create_bbt(mtd, buf, bd, chipsel); | 1002 | if (!(this->options & NAND_CREATE_EMPTY_BBT)) |
1003 | create_bbt(mtd, buf, bd, chipsel); | ||
896 | 1004 | ||
897 | td->version[i] = 1; | 1005 | td->version[i] = 1; |
898 | if (md) | 1006 | if (md) |
@@ -983,6 +1091,49 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
983 | } | 1091 | } |
984 | 1092 | ||
985 | /** | 1093 | /** |
1094 | * verify_bbt_descr - verify the bad block description | ||
1095 | * @bd: the table to verify | ||
1096 | * | ||
1097 | * This functions performs a few sanity checks on the bad block description | ||
1098 | * table. | ||
1099 | */ | ||
1100 | static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) | ||
1101 | { | ||
1102 | struct nand_chip *this = mtd->priv; | ||
1103 | u32 pattern_len = bd->len; | ||
1104 | u32 bits = bd->options & NAND_BBT_NRBITS_MSK; | ||
1105 | u32 table_size; | ||
1106 | |||
1107 | if (!bd) | ||
1108 | return; | ||
1109 | BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) && | ||
1110 | !(this->options & NAND_USE_FLASH_BBT)); | ||
1111 | BUG_ON(!bits); | ||
1112 | |||
1113 | if (bd->options & NAND_BBT_VERSION) | ||
1114 | pattern_len++; | ||
1115 | |||
1116 | if (bd->options & NAND_BBT_NO_OOB) { | ||
1117 | BUG_ON(!(this->options & NAND_USE_FLASH_BBT)); | ||
1118 | BUG_ON(!(this->options & NAND_USE_FLASH_BBT_NO_OOB)); | ||
1119 | BUG_ON(bd->offs); | ||
1120 | if (bd->options & NAND_BBT_VERSION) | ||
1121 | BUG_ON(bd->veroffs != bd->len); | ||
1122 | BUG_ON(bd->options & NAND_BBT_SAVECONTENT); | ||
1123 | } | ||
1124 | |||
1125 | if (bd->options & NAND_BBT_PERCHIP) | ||
1126 | table_size = this->chipsize >> this->bbt_erase_shift; | ||
1127 | else | ||
1128 | table_size = mtd->size >> this->bbt_erase_shift; | ||
1129 | table_size >>= 3; | ||
1130 | table_size *= bits; | ||
1131 | if (bd->options & NAND_BBT_NO_OOB) | ||
1132 | table_size += pattern_len; | ||
1133 | BUG_ON(table_size > (1 << this->bbt_erase_shift)); | ||
1134 | } | ||
1135 | |||
1136 | /** | ||
986 | * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) | 1137 | * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) |
987 | * @mtd: MTD device structure | 1138 | * @mtd: MTD device structure |
988 | * @bd: descriptor for the good/bad block search pattern | 1139 | * @bd: descriptor for the good/bad block search pattern |
@@ -1023,6 +1174,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1023 | } | 1174 | } |
1024 | return res; | 1175 | return res; |
1025 | } | 1176 | } |
1177 | verify_bbt_descr(mtd, td); | ||
1178 | verify_bbt_descr(mtd, md); | ||
1026 | 1179 | ||
1027 | /* Allocate a temporary buffer for one eraseblock incl. oob */ | 1180 | /* Allocate a temporary buffer for one eraseblock incl. oob */ |
1028 | len = (1 << this->bbt_erase_shift); | 1181 | len = (1 << this->bbt_erase_shift); |
@@ -1166,6 +1319,26 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1166 | .pattern = mirror_pattern | 1319 | .pattern = mirror_pattern |
1167 | }; | 1320 | }; |
1168 | 1321 | ||
1322 | static struct nand_bbt_descr bbt_main_no_bbt_descr = { | ||
1323 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
1324 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP | ||
1325 | | NAND_BBT_NO_OOB, | ||
1326 | .len = 4, | ||
1327 | .veroffs = 4, | ||
1328 | .maxblocks = 4, | ||
1329 | .pattern = bbt_pattern | ||
1330 | }; | ||
1331 | |||
1332 | static struct nand_bbt_descr bbt_mirror_no_bbt_descr = { | ||
1333 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
1334 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP | ||
1335 | | NAND_BBT_NO_OOB, | ||
1336 | .len = 4, | ||
1337 | .veroffs = 4, | ||
1338 | .maxblocks = 4, | ||
1339 | .pattern = mirror_pattern | ||
1340 | }; | ||
1341 | |||
1169 | #define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ | 1342 | #define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ |
1170 | NAND_BBT_SCANBYTE1AND6) | 1343 | NAND_BBT_SCANBYTE1AND6) |
1171 | /** | 1344 | /** |
@@ -1236,8 +1409,13 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1236 | if (this->options & NAND_USE_FLASH_BBT) { | 1409 | if (this->options & NAND_USE_FLASH_BBT) { |
1237 | /* Use the default pattern descriptors */ | 1410 | /* Use the default pattern descriptors */ |
1238 | if (!this->bbt_td) { | 1411 | if (!this->bbt_td) { |
1239 | this->bbt_td = &bbt_main_descr; | 1412 | if (this->options & NAND_USE_FLASH_BBT_NO_OOB) { |
1240 | this->bbt_md = &bbt_mirror_descr; | 1413 | this->bbt_td = &bbt_main_no_bbt_descr; |
1414 | this->bbt_md = &bbt_mirror_no_bbt_descr; | ||
1415 | } else { | ||
1416 | this->bbt_td = &bbt_main_descr; | ||
1417 | this->bbt_md = &bbt_mirror_descr; | ||
1418 | } | ||
1241 | } | 1419 | } |
1242 | if (!this->badblock_pattern) { | 1420 | if (!this->badblock_pattern) { |
1243 | this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased; | 1421 | this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased; |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index c65f19074bc8..00cf1b0d6053 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -75,9 +75,13 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
75 | 75 | ||
76 | /*512 Megabit */ | 76 | /*512 Megabit */ |
77 | {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, | 77 | {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, |
78 | {"NAND 64MiB 1,8V 8-bit", 0xA0, 0, 64, 0, LP_OPTIONS}, | ||
78 | {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, | 79 | {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, |
80 | {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0, LP_OPTIONS}, | ||
79 | {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, | 81 | {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, |
82 | {"NAND 64MiB 1,8V 16-bit", 0xB0, 0, 64, 0, LP_OPTIONS16}, | ||
80 | {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, | 83 | {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, |
84 | {"NAND 64MiB 3,3V 16-bit", 0xC0, 0, 64, 0, LP_OPTIONS16}, | ||
81 | 85 | ||
82 | /* 1 Gigabit */ | 86 | /* 1 Gigabit */ |
83 | {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, | 87 | {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, |
@@ -112,7 +116,34 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
112 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, | 116 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, |
113 | 117 | ||
114 | /* 32 Gigabit */ | 118 | /* 32 Gigabit */ |
119 | {"NAND 4GiB 1,8V 8-bit", 0xA7, 0, 4096, 0, LP_OPTIONS}, | ||
115 | {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, | 120 | {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, |
121 | {"NAND 4GiB 1,8V 16-bit", 0xB7, 0, 4096, 0, LP_OPTIONS16}, | ||
122 | {"NAND 4GiB 3,3V 16-bit", 0xC7, 0, 4096, 0, LP_OPTIONS16}, | ||
123 | |||
124 | /* 64 Gigabit */ | ||
125 | {"NAND 8GiB 1,8V 8-bit", 0xAE, 0, 8192, 0, LP_OPTIONS}, | ||
126 | {"NAND 8GiB 3,3V 8-bit", 0xDE, 0, 8192, 0, LP_OPTIONS}, | ||
127 | {"NAND 8GiB 1,8V 16-bit", 0xBE, 0, 8192, 0, LP_OPTIONS16}, | ||
128 | {"NAND 8GiB 3,3V 16-bit", 0xCE, 0, 8192, 0, LP_OPTIONS16}, | ||
129 | |||
130 | /* 128 Gigabit */ | ||
131 | {"NAND 16GiB 1,8V 8-bit", 0x1A, 0, 16384, 0, LP_OPTIONS}, | ||
132 | {"NAND 16GiB 3,3V 8-bit", 0x3A, 0, 16384, 0, LP_OPTIONS}, | ||
133 | {"NAND 16GiB 1,8V 16-bit", 0x2A, 0, 16384, 0, LP_OPTIONS16}, | ||
134 | {"NAND 16GiB 3,3V 16-bit", 0x4A, 0, 16384, 0, LP_OPTIONS16}, | ||
135 | |||
136 | /* 256 Gigabit */ | ||
137 | {"NAND 32GiB 1,8V 8-bit", 0x1C, 0, 32768, 0, LP_OPTIONS}, | ||
138 | {"NAND 32GiB 3,3V 8-bit", 0x3C, 0, 32768, 0, LP_OPTIONS}, | ||
139 | {"NAND 32GiB 1,8V 16-bit", 0x2C, 0, 32768, 0, LP_OPTIONS16}, | ||
140 | {"NAND 32GiB 3,3V 16-bit", 0x4C, 0, 32768, 0, LP_OPTIONS16}, | ||
141 | |||
142 | /* 512 Gigabit */ | ||
143 | {"NAND 64GiB 1,8V 8-bit", 0x1E, 0, 65536, 0, LP_OPTIONS}, | ||
144 | {"NAND 64GiB 3,3V 8-bit", 0x3E, 0, 65536, 0, LP_OPTIONS}, | ||
145 | {"NAND 64GiB 1,8V 16-bit", 0x2E, 0, 65536, 0, LP_OPTIONS16}, | ||
146 | {"NAND 64GiB 3,3V 16-bit", 0x4E, 0, 65536, 0, LP_OPTIONS16}, | ||
116 | 147 | ||
117 | /* | 148 | /* |
118 | * Renesas AND 1 Gigabit. Those chips do not support extended id and | 149 | * Renesas AND 1 Gigabit. Those chips do not support extended id and |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index c25648bb5793..a6a73aab1253 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -107,6 +107,7 @@ static char *gravepages = NULL; | |||
107 | static unsigned int rptwear = 0; | 107 | static unsigned int rptwear = 0; |
108 | static unsigned int overridesize = 0; | 108 | static unsigned int overridesize = 0; |
109 | static char *cache_file = NULL; | 109 | static char *cache_file = NULL; |
110 | static unsigned int bbt; | ||
110 | 111 | ||
111 | module_param(first_id_byte, uint, 0400); | 112 | module_param(first_id_byte, uint, 0400); |
112 | module_param(second_id_byte, uint, 0400); | 113 | module_param(second_id_byte, uint, 0400); |
@@ -130,6 +131,7 @@ module_param(gravepages, charp, 0400); | |||
130 | module_param(rptwear, uint, 0400); | 131 | module_param(rptwear, uint, 0400); |
131 | module_param(overridesize, uint, 0400); | 132 | module_param(overridesize, uint, 0400); |
132 | module_param(cache_file, charp, 0400); | 133 | module_param(cache_file, charp, 0400); |
134 | module_param(bbt, uint, 0400); | ||
133 | 135 | ||
134 | MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); | 136 | MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); |
135 | MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); | 137 | MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); |
@@ -162,6 +164,7 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I | |||
162 | "The size is specified in erase blocks and as the exponent of a power of two" | 164 | "The size is specified in erase blocks and as the exponent of a power of two" |
163 | " e.g. 5 means a size of 32 erase blocks"); | 165 | " e.g. 5 means a size of 32 erase blocks"); |
164 | MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory"); | 166 | MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory"); |
167 | MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in data area"); | ||
165 | 168 | ||
166 | /* The largest possible page size */ | 169 | /* The largest possible page size */ |
167 | #define NS_LARGEST_PAGE_SIZE 4096 | 170 | #define NS_LARGEST_PAGE_SIZE 4096 |
@@ -2264,6 +2267,18 @@ static int __init ns_init_module(void) | |||
2264 | /* and 'badblocks' parameters to work */ | 2267 | /* and 'badblocks' parameters to work */ |
2265 | chip->options |= NAND_SKIP_BBTSCAN; | 2268 | chip->options |= NAND_SKIP_BBTSCAN; |
2266 | 2269 | ||
2270 | switch (bbt) { | ||
2271 | case 2: | ||
2272 | chip->options |= NAND_USE_FLASH_BBT_NO_OOB; | ||
2273 | case 1: | ||
2274 | chip->options |= NAND_USE_FLASH_BBT; | ||
2275 | case 0: | ||
2276 | break; | ||
2277 | default: | ||
2278 | NS_ERR("bbt has to be 0..2\n"); | ||
2279 | retval = -EINVAL; | ||
2280 | goto error; | ||
2281 | } | ||
2267 | /* | 2282 | /* |
2268 | * Perform minimum nandsim structure initialization to handle | 2283 | * Perform minimum nandsim structure initialization to handle |
2269 | * the initial ID read command correctly | 2284 | * the initial ID read command correctly |
@@ -2321,10 +2336,10 @@ static int __init ns_init_module(void) | |||
2321 | if ((retval = init_nandsim(nsmtd)) != 0) | 2336 | if ((retval = init_nandsim(nsmtd)) != 0) |
2322 | goto err_exit; | 2337 | goto err_exit; |
2323 | 2338 | ||
2324 | if ((retval = parse_badblocks(nand, nsmtd)) != 0) | 2339 | if ((retval = nand_default_bbt(nsmtd)) != 0) |
2325 | goto err_exit; | 2340 | goto err_exit; |
2326 | 2341 | ||
2327 | if ((retval = nand_default_bbt(nsmtd)) != 0) | 2342 | if ((retval = parse_badblocks(nand, nsmtd)) != 0) |
2328 | goto err_exit; | 2343 | goto err_exit; |
2329 | 2344 | ||
2330 | /* Register NAND partitions */ | 2345 | /* Register NAND partitions */ |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 510554e6c115..c9ae0a5023b6 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -229,7 +229,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev, | |||
229 | const struct of_device_id *match) | 229 | const struct of_device_id *match) |
230 | { | 230 | { |
231 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 231 | struct ndfc_controller *ndfc = &ndfc_ctrl; |
232 | const u32 *reg; | 232 | const __be32 *reg; |
233 | u32 ccr; | 233 | u32 ccr; |
234 | int err, len; | 234 | int err, len; |
235 | 235 | ||
@@ -244,7 +244,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev, | |||
244 | dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); | 244 | dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); |
245 | return -ENOENT; | 245 | return -ENOENT; |
246 | } | 246 | } |
247 | ndfc->chip_select = reg[0]; | 247 | ndfc->chip_select = be32_to_cpu(reg[0]); |
248 | 248 | ||
249 | ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); | 249 | ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); |
250 | if (!ndfc->ndfcbase) { | 250 | if (!ndfc->ndfcbase) { |
@@ -257,7 +257,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev, | |||
257 | /* It is ok if ccr does not exist - just default to 0 */ | 257 | /* It is ok if ccr does not exist - just default to 0 */ |
258 | reg = of_get_property(ofdev->dev.of_node, "ccr", NULL); | 258 | reg = of_get_property(ofdev->dev.of_node, "ccr", NULL); |
259 | if (reg) | 259 | if (reg) |
260 | ccr |= *reg; | 260 | ccr |= be32_to_cpup(reg); |
261 | 261 | ||
262 | out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); | 262 | out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); |
263 | 263 | ||
@@ -265,7 +265,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev, | |||
265 | reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL); | 265 | reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL); |
266 | if (reg) { | 266 | if (reg) { |
267 | int offset = NDFC_BCFG0 + (ndfc->chip_select << 2); | 267 | int offset = NDFC_BCFG0 + (ndfc->chip_select << 2); |
268 | out_be32(ndfc->ndfcbase + offset, *reg); | 268 | out_be32(ndfc->ndfcbase + offset, be32_to_cpup(reg)); |
269 | } | 269 | } |
270 | 270 | ||
271 | err = ndfc_chip_init(ndfc, ofdev->dev.of_node); | 271 | err = ndfc_chip_init(ndfc, ofdev->dev.of_node); |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 513e0a76a4a7..cd41c58b5bbd 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -111,11 +111,11 @@ static int use_dma = 1; | |||
111 | module_param(use_dma, bool, 0); | 111 | module_param(use_dma, bool, 0); |
112 | MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); | 112 | MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); |
113 | #else | 113 | #else |
114 | const int use_dma; | 114 | static const int use_dma; |
115 | #endif | 115 | #endif |
116 | #else | 116 | #else |
117 | const int use_prefetch; | 117 | const int use_prefetch; |
118 | const int use_dma; | 118 | static const int use_dma; |
119 | #endif | 119 | #endif |
120 | 120 | ||
121 | struct omap_nand_info { | 121 | struct omap_nand_info { |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4d01cda68844..17f8518cc5eb 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -117,7 +117,7 @@ struct pxa3xx_nand_info { | |||
117 | struct nand_chip nand_chip; | 117 | struct nand_chip nand_chip; |
118 | 118 | ||
119 | struct platform_device *pdev; | 119 | struct platform_device *pdev; |
120 | const struct pxa3xx_nand_flash *flash_info; | 120 | struct pxa3xx_nand_cmdset *cmdset; |
121 | 121 | ||
122 | struct clk *clk; | 122 | struct clk *clk; |
123 | void __iomem *mmio_base; | 123 | void __iomem *mmio_base; |
@@ -131,6 +131,7 @@ struct pxa3xx_nand_info { | |||
131 | int drcmr_cmd; | 131 | int drcmr_cmd; |
132 | 132 | ||
133 | unsigned char *data_buff; | 133 | unsigned char *data_buff; |
134 | unsigned char *oob_buff; | ||
134 | dma_addr_t data_buff_phys; | 135 | dma_addr_t data_buff_phys; |
135 | size_t data_buff_size; | 136 | size_t data_buff_size; |
136 | int data_dma_ch; | 137 | int data_dma_ch; |
@@ -149,7 +150,8 @@ struct pxa3xx_nand_info { | |||
149 | int use_ecc; /* use HW ECC ? */ | 150 | int use_ecc; /* use HW ECC ? */ |
150 | int use_dma; /* use DMA ? */ | 151 | int use_dma; /* use DMA ? */ |
151 | 152 | ||
152 | size_t data_size; /* data size in FIFO */ | 153 | unsigned int page_size; /* page size of attached chip */ |
154 | unsigned int data_size; /* data size in FIFO */ | ||
153 | int retcode; | 155 | int retcode; |
154 | struct completion cmd_complete; | 156 | struct completion cmd_complete; |
155 | 157 | ||
@@ -158,6 +160,10 @@ struct pxa3xx_nand_info { | |||
158 | uint32_t ndcb1; | 160 | uint32_t ndcb1; |
159 | uint32_t ndcb2; | 161 | uint32_t ndcb2; |
160 | 162 | ||
163 | /* timing calcuted from setting */ | ||
164 | uint32_t ndtr0cs0; | ||
165 | uint32_t ndtr1cs0; | ||
166 | |||
161 | /* calculated from pxa3xx_nand_flash data */ | 167 | /* calculated from pxa3xx_nand_flash data */ |
162 | size_t oob_size; | 168 | size_t oob_size; |
163 | size_t read_id_bytes; | 169 | size_t read_id_bytes; |
@@ -174,23 +180,7 @@ MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); | |||
174 | * Default NAND flash controller configuration setup by the | 180 | * Default NAND flash controller configuration setup by the |
175 | * bootloader. This configuration is used only when pdata->keep_config is set | 181 | * bootloader. This configuration is used only when pdata->keep_config is set |
176 | */ | 182 | */ |
177 | static struct pxa3xx_nand_timing default_timing; | 183 | static struct pxa3xx_nand_cmdset default_cmdset = { |
178 | static struct pxa3xx_nand_flash default_flash; | ||
179 | |||
180 | static struct pxa3xx_nand_cmdset smallpage_cmdset = { | ||
181 | .read1 = 0x0000, | ||
182 | .read2 = 0x0050, | ||
183 | .program = 0x1080, | ||
184 | .read_status = 0x0070, | ||
185 | .read_id = 0x0090, | ||
186 | .erase = 0xD060, | ||
187 | .reset = 0x00FF, | ||
188 | .lock = 0x002A, | ||
189 | .unlock = 0x2423, | ||
190 | .lock_status = 0x007A, | ||
191 | }; | ||
192 | |||
193 | static struct pxa3xx_nand_cmdset largepage_cmdset = { | ||
194 | .read1 = 0x3000, | 184 | .read1 = 0x3000, |
195 | .read2 = 0x0050, | 185 | .read2 = 0x0050, |
196 | .program = 0x1080, | 186 | .program = 0x1080, |
@@ -203,142 +193,27 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = { | |||
203 | .lock_status = 0x007A, | 193 | .lock_status = 0x007A, |
204 | }; | 194 | }; |
205 | 195 | ||
206 | #ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN | 196 | static struct pxa3xx_nand_timing timing[] = { |
207 | static struct pxa3xx_nand_timing samsung512MbX16_timing = { | 197 | { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, |
208 | .tCH = 10, | 198 | { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, |
209 | .tCS = 0, | 199 | { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, |
210 | .tWH = 20, | 200 | { 10, 35, 15, 25, 15, 25, 25000, 60, 10, }, |
211 | .tWP = 40, | ||
212 | .tRH = 30, | ||
213 | .tRP = 40, | ||
214 | .tR = 11123, | ||
215 | .tWHR = 110, | ||
216 | .tAR = 10, | ||
217 | }; | ||
218 | |||
219 | static struct pxa3xx_nand_flash samsung512MbX16 = { | ||
220 | .timing = &samsung512MbX16_timing, | ||
221 | .cmdset = &smallpage_cmdset, | ||
222 | .page_per_block = 32, | ||
223 | .page_size = 512, | ||
224 | .flash_width = 16, | ||
225 | .dfc_width = 16, | ||
226 | .num_blocks = 4096, | ||
227 | .chip_id = 0x46ec, | ||
228 | }; | ||
229 | |||
230 | static struct pxa3xx_nand_flash samsung2GbX8 = { | ||
231 | .timing = &samsung512MbX16_timing, | ||
232 | .cmdset = &smallpage_cmdset, | ||
233 | .page_per_block = 64, | ||
234 | .page_size = 2048, | ||
235 | .flash_width = 8, | ||
236 | .dfc_width = 8, | ||
237 | .num_blocks = 2048, | ||
238 | .chip_id = 0xdaec, | ||
239 | }; | 201 | }; |
240 | 202 | ||
241 | static struct pxa3xx_nand_flash samsung32GbX8 = { | 203 | static struct pxa3xx_nand_flash builtin_flash_types[] = { |
242 | .timing = &samsung512MbX16_timing, | 204 | { 0, 0, 2048, 8, 8, 0, &default_cmdset, &timing[0] }, |
243 | .cmdset = &smallpage_cmdset, | 205 | { 0x46ec, 32, 512, 16, 16, 4096, &default_cmdset, &timing[1] }, |
244 | .page_per_block = 128, | 206 | { 0xdaec, 64, 2048, 8, 8, 2048, &default_cmdset, &timing[1] }, |
245 | .page_size = 4096, | 207 | { 0xd7ec, 128, 4096, 8, 8, 8192, &default_cmdset, &timing[1] }, |
246 | .flash_width = 8, | 208 | { 0xa12c, 64, 2048, 8, 8, 1024, &default_cmdset, &timing[2] }, |
247 | .dfc_width = 8, | 209 | { 0xb12c, 64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] }, |
248 | .num_blocks = 8192, | 210 | { 0xdc2c, 64, 2048, 8, 8, 4096, &default_cmdset, &timing[2] }, |
249 | .chip_id = 0xd7ec, | 211 | { 0xcc2c, 64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] }, |
212 | { 0xba20, 64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] }, | ||
250 | }; | 213 | }; |
251 | 214 | ||
252 | static struct pxa3xx_nand_timing micron_timing = { | 215 | /* Define a default flash type setting serve as flash detecting only */ |
253 | .tCH = 10, | 216 | #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) |
254 | .tCS = 25, | ||
255 | .tWH = 15, | ||
256 | .tWP = 25, | ||
257 | .tRH = 15, | ||
258 | .tRP = 30, | ||
259 | .tR = 25000, | ||
260 | .tWHR = 60, | ||
261 | .tAR = 10, | ||
262 | }; | ||
263 | |||
264 | static struct pxa3xx_nand_flash micron1GbX8 = { | ||
265 | .timing = µn_timing, | ||
266 | .cmdset = &largepage_cmdset, | ||
267 | .page_per_block = 64, | ||
268 | .page_size = 2048, | ||
269 | .flash_width = 8, | ||
270 | .dfc_width = 8, | ||
271 | .num_blocks = 1024, | ||
272 | .chip_id = 0xa12c, | ||
273 | }; | ||
274 | |||
275 | static struct pxa3xx_nand_flash micron1GbX16 = { | ||
276 | .timing = µn_timing, | ||
277 | .cmdset = &largepage_cmdset, | ||
278 | .page_per_block = 64, | ||
279 | .page_size = 2048, | ||
280 | .flash_width = 16, | ||
281 | .dfc_width = 16, | ||
282 | .num_blocks = 1024, | ||
283 | .chip_id = 0xb12c, | ||
284 | }; | ||
285 | |||
286 | static struct pxa3xx_nand_flash micron4GbX8 = { | ||
287 | .timing = µn_timing, | ||
288 | .cmdset = &largepage_cmdset, | ||
289 | .page_per_block = 64, | ||
290 | .page_size = 2048, | ||
291 | .flash_width = 8, | ||
292 | .dfc_width = 8, | ||
293 | .num_blocks = 4096, | ||
294 | .chip_id = 0xdc2c, | ||
295 | }; | ||
296 | |||
297 | static struct pxa3xx_nand_flash micron4GbX16 = { | ||
298 | .timing = µn_timing, | ||
299 | .cmdset = &largepage_cmdset, | ||
300 | .page_per_block = 64, | ||
301 | .page_size = 2048, | ||
302 | .flash_width = 16, | ||
303 | .dfc_width = 16, | ||
304 | .num_blocks = 4096, | ||
305 | .chip_id = 0xcc2c, | ||
306 | }; | ||
307 | |||
308 | static struct pxa3xx_nand_timing stm2GbX16_timing = { | ||
309 | .tCH = 10, | ||
310 | .tCS = 35, | ||
311 | .tWH = 15, | ||
312 | .tWP = 25, | ||
313 | .tRH = 15, | ||
314 | .tRP = 25, | ||
315 | .tR = 25000, | ||
316 | .tWHR = 60, | ||
317 | .tAR = 10, | ||
318 | }; | ||
319 | |||
320 | static struct pxa3xx_nand_flash stm2GbX16 = { | ||
321 | .timing = &stm2GbX16_timing, | ||
322 | .cmdset = &largepage_cmdset, | ||
323 | .page_per_block = 64, | ||
324 | .page_size = 2048, | ||
325 | .flash_width = 16, | ||
326 | .dfc_width = 16, | ||
327 | .num_blocks = 2048, | ||
328 | .chip_id = 0xba20, | ||
329 | }; | ||
330 | |||
331 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { | ||
332 | &samsung512MbX16, | ||
333 | &samsung2GbX8, | ||
334 | &samsung32GbX8, | ||
335 | µn1GbX8, | ||
336 | µn1GbX16, | ||
337 | µn4GbX8, | ||
338 | µn4GbX16, | ||
339 | &stm2GbX16, | ||
340 | }; | ||
341 | #endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ | ||
342 | 217 | ||
343 | #define NDTR0_tCH(c) (min((c), 7) << 19) | 218 | #define NDTR0_tCH(c) (min((c), 7) << 19) |
344 | #define NDTR0_tCS(c) (min((c), 7) << 16) | 219 | #define NDTR0_tCS(c) (min((c), 7) << 16) |
@@ -351,23 +226,9 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = { | |||
351 | #define NDTR1_tWHR(c) (min((c), 15) << 4) | 226 | #define NDTR1_tWHR(c) (min((c), 15) << 4) |
352 | #define NDTR1_tAR(c) (min((c), 15) << 0) | 227 | #define NDTR1_tAR(c) (min((c), 15) << 0) |
353 | 228 | ||
354 | #define tCH_NDTR0(r) (((r) >> 19) & 0x7) | ||
355 | #define tCS_NDTR0(r) (((r) >> 16) & 0x7) | ||
356 | #define tWH_NDTR0(r) (((r) >> 11) & 0x7) | ||
357 | #define tWP_NDTR0(r) (((r) >> 8) & 0x7) | ||
358 | #define tRH_NDTR0(r) (((r) >> 3) & 0x7) | ||
359 | #define tRP_NDTR0(r) (((r) >> 0) & 0x7) | ||
360 | |||
361 | #define tR_NDTR1(r) (((r) >> 16) & 0xffff) | ||
362 | #define tWHR_NDTR1(r) (((r) >> 4) & 0xf) | ||
363 | #define tAR_NDTR1(r) (((r) >> 0) & 0xf) | ||
364 | |||
365 | /* convert nano-seconds to nand flash controller clock cycles */ | 229 | /* convert nano-seconds to nand flash controller clock cycles */ |
366 | #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) | 230 | #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) |
367 | 231 | ||
368 | /* convert nand flash controller clock cycles to nano-seconds */ | ||
369 | #define cycle2ns(c, clk) ((((c) + 1) * 1000000 + clk / 500) / (clk / 1000)) | ||
370 | |||
371 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | 232 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, |
372 | const struct pxa3xx_nand_timing *t) | 233 | const struct pxa3xx_nand_timing *t) |
373 | { | 234 | { |
@@ -385,6 +246,8 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | |||
385 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | | 246 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | |
386 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); | 247 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); |
387 | 248 | ||
249 | info->ndtr0cs0 = ndtr0; | ||
250 | info->ndtr1cs0 = ndtr1; | ||
388 | nand_writel(info, NDTR0CS0, ndtr0); | 251 | nand_writel(info, NDTR0CS0, ndtr0); |
389 | nand_writel(info, NDTR1CS0, ndtr1); | 252 | nand_writel(info, NDTR1CS0, ndtr1); |
390 | } | 253 | } |
@@ -408,23 +271,31 @@ static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event) | |||
408 | return -ETIMEDOUT; | 271 | return -ETIMEDOUT; |
409 | } | 272 | } |
410 | 273 | ||
411 | static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | 274 | static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) |
412 | uint16_t cmd, int column, int page_addr) | ||
413 | { | 275 | { |
414 | const struct pxa3xx_nand_flash *f = info->flash_info; | 276 | int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; |
415 | const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; | ||
416 | 277 | ||
417 | /* calculate data size */ | 278 | info->data_size = info->page_size; |
418 | switch (f->page_size) { | 279 | if (!oob_enable) { |
280 | info->oob_size = 0; | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | switch (info->page_size) { | ||
419 | case 2048: | 285 | case 2048: |
420 | info->data_size = (info->use_ecc) ? 2088 : 2112; | 286 | info->oob_size = (info->use_ecc) ? 40 : 64; |
421 | break; | 287 | break; |
422 | case 512: | 288 | case 512: |
423 | info->data_size = (info->use_ecc) ? 520 : 528; | 289 | info->oob_size = (info->use_ecc) ? 8 : 16; |
424 | break; | 290 | break; |
425 | default: | ||
426 | return -EINVAL; | ||
427 | } | 291 | } |
292 | } | ||
293 | |||
294 | static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | ||
295 | uint16_t cmd, int column, int page_addr) | ||
296 | { | ||
297 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; | ||
298 | pxa3xx_set_datasize(info); | ||
428 | 299 | ||
429 | /* generate values for NDCBx registers */ | 300 | /* generate values for NDCBx registers */ |
430 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | 301 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); |
@@ -463,12 +334,13 @@ static int prepare_erase_cmd(struct pxa3xx_nand_info *info, | |||
463 | 334 | ||
464 | static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) | 335 | static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) |
465 | { | 336 | { |
466 | const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset; | 337 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
467 | 338 | ||
468 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | 339 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); |
469 | info->ndcb1 = 0; | 340 | info->ndcb1 = 0; |
470 | info->ndcb2 = 0; | 341 | info->ndcb2 = 0; |
471 | 342 | ||
343 | info->oob_size = 0; | ||
472 | if (cmd == cmdset->read_id) { | 344 | if (cmd == cmdset->read_id) { |
473 | info->ndcb0 |= NDCB0_CMD_TYPE(3); | 345 | info->ndcb0 |= NDCB0_CMD_TYPE(3); |
474 | info->data_size = 8; | 346 | info->data_size = 8; |
@@ -537,6 +409,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
537 | case STATE_PIO_WRITING: | 409 | case STATE_PIO_WRITING: |
538 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, | 410 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, |
539 | DIV_ROUND_UP(info->data_size, 4)); | 411 | DIV_ROUND_UP(info->data_size, 4)); |
412 | if (info->oob_size > 0) | ||
413 | __raw_writesl(info->mmio_base + NDDB, info->oob_buff, | ||
414 | DIV_ROUND_UP(info->oob_size, 4)); | ||
540 | 415 | ||
541 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | 416 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); |
542 | 417 | ||
@@ -549,6 +424,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
549 | case STATE_PIO_READING: | 424 | case STATE_PIO_READING: |
550 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, | 425 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, |
551 | DIV_ROUND_UP(info->data_size, 4)); | 426 | DIV_ROUND_UP(info->data_size, 4)); |
427 | if (info->oob_size > 0) | ||
428 | __raw_readsl(info->mmio_base + NDDB, info->oob_buff, | ||
429 | DIV_ROUND_UP(info->oob_size, 4)); | ||
552 | break; | 430 | break; |
553 | default: | 431 | default: |
554 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | 432 | printk(KERN_ERR "%s: invalid state %d\n", __func__, |
@@ -563,7 +441,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
563 | static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) | 441 | static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) |
564 | { | 442 | { |
565 | struct pxa_dma_desc *desc = info->data_desc; | 443 | struct pxa_dma_desc *desc = info->data_desc; |
566 | int dma_len = ALIGN(info->data_size, 32); | 444 | int dma_len = ALIGN(info->data_size + info->oob_size, 32); |
567 | 445 | ||
568 | desc->ddadr = DDADR_STOP; | 446 | desc->ddadr = DDADR_STOP; |
569 | desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; | 447 | desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; |
@@ -700,8 +578,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
700 | int column, int page_addr) | 578 | int column, int page_addr) |
701 | { | 579 | { |
702 | struct pxa3xx_nand_info *info = mtd->priv; | 580 | struct pxa3xx_nand_info *info = mtd->priv; |
703 | const struct pxa3xx_nand_flash *flash_info = info->flash_info; | 581 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
704 | const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; | ||
705 | int ret; | 582 | int ret; |
706 | 583 | ||
707 | info->use_dma = (use_dma) ? 1 : 0; | 584 | info->use_dma = (use_dma) ? 1 : 0; |
@@ -925,8 +802,7 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, | |||
925 | 802 | ||
926 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) | 803 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) |
927 | { | 804 | { |
928 | const struct pxa3xx_nand_flash *f = info->flash_info; | 805 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
929 | const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; | ||
930 | uint32_t ndcr; | 806 | uint32_t ndcr; |
931 | uint8_t id_buff[8]; | 807 | uint8_t id_buff[8]; |
932 | 808 | ||
@@ -968,7 +844,9 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
968 | return -EINVAL; | 844 | return -EINVAL; |
969 | 845 | ||
970 | /* calculate flash information */ | 846 | /* calculate flash information */ |
971 | info->oob_size = (f->page_size == 2048) ? 64 : 16; | 847 | info->cmdset = f->cmdset; |
848 | info->page_size = f->page_size; | ||
849 | info->oob_buff = info->data_buff + f->page_size; | ||
972 | info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; | 850 | info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; |
973 | 851 | ||
974 | /* calculate addressing information */ | 852 | /* calculate addressing information */ |
@@ -992,49 +870,20 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
992 | info->reg_ndcr = ndcr; | 870 | info->reg_ndcr = ndcr; |
993 | 871 | ||
994 | pxa3xx_nand_set_timing(info, f->timing); | 872 | pxa3xx_nand_set_timing(info, f->timing); |
995 | info->flash_info = f; | ||
996 | return 0; | 873 | return 0; |
997 | } | 874 | } |
998 | 875 | ||
999 | static void pxa3xx_nand_detect_timing(struct pxa3xx_nand_info *info, | ||
1000 | struct pxa3xx_nand_timing *t) | ||
1001 | { | ||
1002 | unsigned long nand_clk = clk_get_rate(info->clk); | ||
1003 | uint32_t ndtr0 = nand_readl(info, NDTR0CS0); | ||
1004 | uint32_t ndtr1 = nand_readl(info, NDTR1CS0); | ||
1005 | |||
1006 | t->tCH = cycle2ns(tCH_NDTR0(ndtr0), nand_clk); | ||
1007 | t->tCS = cycle2ns(tCS_NDTR0(ndtr0), nand_clk); | ||
1008 | t->tWH = cycle2ns(tWH_NDTR0(ndtr0), nand_clk); | ||
1009 | t->tWP = cycle2ns(tWP_NDTR0(ndtr0), nand_clk); | ||
1010 | t->tRH = cycle2ns(tRH_NDTR0(ndtr0), nand_clk); | ||
1011 | t->tRP = cycle2ns(tRP_NDTR0(ndtr0), nand_clk); | ||
1012 | |||
1013 | t->tR = cycle2ns(tR_NDTR1(ndtr1), nand_clk); | ||
1014 | t->tWHR = cycle2ns(tWHR_NDTR1(ndtr1), nand_clk); | ||
1015 | t->tAR = cycle2ns(tAR_NDTR1(ndtr1), nand_clk); | ||
1016 | } | ||
1017 | |||
1018 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | 876 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) |
1019 | { | 877 | { |
1020 | uint32_t ndcr = nand_readl(info, NDCR); | 878 | uint32_t ndcr = nand_readl(info, NDCR); |
1021 | struct nand_flash_dev *type = NULL; | 879 | struct nand_flash_dev *type = NULL; |
1022 | uint32_t id = -1; | 880 | uint32_t id = -1, page_per_block, num_blocks; |
1023 | int i; | 881 | int i; |
1024 | 882 | ||
1025 | default_flash.page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32; | 883 | page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32; |
1026 | default_flash.page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; | 884 | info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; |
1027 | default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8; | ||
1028 | default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; | ||
1029 | |||
1030 | if (default_flash.page_size == 2048) | ||
1031 | default_flash.cmdset = &largepage_cmdset; | ||
1032 | else | ||
1033 | default_flash.cmdset = &smallpage_cmdset; | ||
1034 | |||
1035 | /* set info fields needed to __readid */ | 885 | /* set info fields needed to __readid */ |
1036 | info->flash_info = &default_flash; | 886 | info->read_id_bytes = (info->page_size == 2048) ? 4 : 2; |
1037 | info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; | ||
1038 | info->reg_ndcr = ndcr; | 887 | info->reg_ndcr = ndcr; |
1039 | 888 | ||
1040 | if (__readid(info, &id)) | 889 | if (__readid(info, &id)) |
@@ -1053,21 +902,20 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | |||
1053 | return -ENODEV; | 902 | return -ENODEV; |
1054 | 903 | ||
1055 | /* fill the missing flash information */ | 904 | /* fill the missing flash information */ |
1056 | i = __ffs(default_flash.page_per_block * default_flash.page_size); | 905 | i = __ffs(page_per_block * info->page_size); |
1057 | default_flash.num_blocks = type->chipsize << (20 - i); | 906 | num_blocks = type->chipsize << (20 - i); |
1058 | |||
1059 | info->oob_size = (default_flash.page_size == 2048) ? 64 : 16; | ||
1060 | 907 | ||
1061 | /* calculate addressing information */ | 908 | /* calculate addressing information */ |
1062 | info->col_addr_cycles = (default_flash.page_size == 2048) ? 2 : 1; | 909 | info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1; |
1063 | 910 | ||
1064 | if (default_flash.num_blocks * default_flash.page_per_block > 65536) | 911 | if (num_blocks * page_per_block > 65536) |
1065 | info->row_addr_cycles = 3; | 912 | info->row_addr_cycles = 3; |
1066 | else | 913 | else |
1067 | info->row_addr_cycles = 2; | 914 | info->row_addr_cycles = 2; |
1068 | 915 | ||
1069 | pxa3xx_nand_detect_timing(info, &default_timing); | 916 | info->ndtr0cs0 = nand_readl(info, NDTR0CS0); |
1070 | default_flash.timing = &default_timing; | 917 | info->ndtr1cs0 = nand_readl(info, NDTR1CS0); |
918 | info->cmdset = &default_cmdset; | ||
1071 | 919 | ||
1072 | return 0; | 920 | return 0; |
1073 | } | 921 | } |
@@ -1083,38 +931,29 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, | |||
1083 | if (pxa3xx_nand_detect_config(info) == 0) | 931 | if (pxa3xx_nand_detect_config(info) == 0) |
1084 | return 0; | 932 | return 0; |
1085 | 933 | ||
1086 | for (i = 0; i<pdata->num_flash; ++i) { | 934 | /* we use default timing to detect id */ |
1087 | f = pdata->flash + i; | 935 | f = DEFAULT_FLASH_TYPE; |
1088 | 936 | pxa3xx_nand_config_flash(info, f); | |
1089 | if (pxa3xx_nand_config_flash(info, f)) | 937 | if (__readid(info, &id)) |
1090 | continue; | 938 | goto fail_detect; |
1091 | 939 | ||
1092 | if (__readid(info, &id)) | 940 | for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) { |
1093 | continue; | 941 | /* we first choose the flash definition from platfrom */ |
1094 | 942 | if (i < pdata->num_flash) | |
1095 | if (id == f->chip_id) | 943 | f = pdata->flash + i; |
1096 | return 0; | 944 | else |
1097 | } | 945 | f = &builtin_flash_types[i - pdata->num_flash + 1]; |
1098 | 946 | if (f->chip_id == id) { | |
1099 | #ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN | 947 | dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id); |
1100 | for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { | 948 | pxa3xx_nand_config_flash(info, f); |
1101 | |||
1102 | f = builtin_flash_types[i]; | ||
1103 | |||
1104 | if (pxa3xx_nand_config_flash(info, f)) | ||
1105 | continue; | ||
1106 | |||
1107 | if (__readid(info, &id)) | ||
1108 | continue; | ||
1109 | |||
1110 | if (id == f->chip_id) | ||
1111 | return 0; | 949 | return 0; |
950 | } | ||
1112 | } | 951 | } |
1113 | #endif | ||
1114 | 952 | ||
1115 | dev_warn(&info->pdev->dev, | 953 | dev_warn(&info->pdev->dev, |
1116 | "failed to detect configured nand flash; found %04x instead of\n", | 954 | "failed to detect configured nand flash; found %04x instead of\n", |
1117 | id); | 955 | id); |
956 | fail_detect: | ||
1118 | return -ENODEV; | 957 | return -ENODEV; |
1119 | } | 958 | } |
1120 | 959 | ||
@@ -1177,10 +1016,9 @@ static struct nand_ecclayout hw_largepage_ecclayout = { | |||
1177 | static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | 1016 | static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, |
1178 | struct pxa3xx_nand_info *info) | 1017 | struct pxa3xx_nand_info *info) |
1179 | { | 1018 | { |
1180 | const struct pxa3xx_nand_flash *f = info->flash_info; | ||
1181 | struct nand_chip *this = &info->nand_chip; | 1019 | struct nand_chip *this = &info->nand_chip; |
1182 | 1020 | ||
1183 | this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; | 1021 | this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; |
1184 | 1022 | ||
1185 | this->waitfunc = pxa3xx_nand_waitfunc; | 1023 | this->waitfunc = pxa3xx_nand_waitfunc; |
1186 | this->select_chip = pxa3xx_nand_select_chip; | 1024 | this->select_chip = pxa3xx_nand_select_chip; |
@@ -1196,9 +1034,9 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | |||
1196 | this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; | 1034 | this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; |
1197 | this->ecc.calculate = pxa3xx_nand_ecc_calculate; | 1035 | this->ecc.calculate = pxa3xx_nand_ecc_calculate; |
1198 | this->ecc.correct = pxa3xx_nand_ecc_correct; | 1036 | this->ecc.correct = pxa3xx_nand_ecc_correct; |
1199 | this->ecc.size = f->page_size; | 1037 | this->ecc.size = info->page_size; |
1200 | 1038 | ||
1201 | if (f->page_size == 2048) | 1039 | if (info->page_size == 2048) |
1202 | this->ecc.layout = &hw_largepage_ecclayout; | 1040 | this->ecc.layout = &hw_largepage_ecclayout; |
1203 | else | 1041 | else |
1204 | this->ecc.layout = &hw_smallpage_ecclayout; | 1042 | this->ecc.layout = &hw_smallpage_ecclayout; |
@@ -1411,9 +1249,11 @@ static int pxa3xx_nand_resume(struct platform_device *pdev) | |||
1411 | struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); | 1249 | struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); |
1412 | struct pxa3xx_nand_info *info = mtd->priv; | 1250 | struct pxa3xx_nand_info *info = mtd->priv; |
1413 | 1251 | ||
1252 | nand_writel(info, NDTR0CS0, info->ndtr0cs0); | ||
1253 | nand_writel(info, NDTR1CS0, info->ndtr1cs0); | ||
1414 | clk_enable(info->clk); | 1254 | clk_enable(info->clk); |
1415 | 1255 | ||
1416 | return pxa3xx_nand_config_flash(info, info->flash_info); | 1256 | return 0; |
1417 | } | 1257 | } |
1418 | #else | 1258 | #else |
1419 | #define pxa3xx_nand_suspend NULL | 1259 | #define pxa3xx_nand_suspend NULL |
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 5169ca6a66bc..d9d7efbc77cc 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -757,11 +757,6 @@ static irqreturn_t r852_irq(int irq, void *data) | |||
757 | 757 | ||
758 | spin_lock_irqsave(&dev->irqlock, flags); | 758 | spin_lock_irqsave(&dev->irqlock, flags); |
759 | 759 | ||
760 | /* We can recieve shared interrupt while pci is suspended | ||
761 | in that case reads will return 0xFFFFFFFF.... */ | ||
762 | if (dev->insuspend) | ||
763 | goto out; | ||
764 | |||
765 | /* handle card detection interrupts first */ | 760 | /* handle card detection interrupts first */ |
766 | card_status = r852_read_reg(dev, R852_CARD_IRQ_STA); | 761 | card_status = r852_read_reg(dev, R852_CARD_IRQ_STA); |
767 | r852_write_reg(dev, R852_CARD_IRQ_STA, card_status); | 762 | r852_write_reg(dev, R852_CARD_IRQ_STA, card_status); |
@@ -1035,7 +1030,6 @@ void r852_shutdown(struct pci_dev *pci_dev) | |||
1035 | int r852_suspend(struct device *device) | 1030 | int r852_suspend(struct device *device) |
1036 | { | 1031 | { |
1037 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); | 1032 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); |
1038 | unsigned long flags; | ||
1039 | 1033 | ||
1040 | if (dev->ctlreg & R852_CTL_CARDENABLE) | 1034 | if (dev->ctlreg & R852_CTL_CARDENABLE) |
1041 | return -EBUSY; | 1035 | return -EBUSY; |
@@ -1047,43 +1041,22 @@ int r852_suspend(struct device *device) | |||
1047 | r852_disable_irqs(dev); | 1041 | r852_disable_irqs(dev); |
1048 | r852_engine_disable(dev); | 1042 | r852_engine_disable(dev); |
1049 | 1043 | ||
1050 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1051 | dev->insuspend = 1; | ||
1052 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1053 | |||
1054 | /* At that point, even if interrupt handler is running, it will quit */ | ||
1055 | /* So wait for this to happen explictly */ | ||
1056 | synchronize_irq(dev->irq); | ||
1057 | |||
1058 | /* If card was pulled off just during the suspend, which is very | 1044 | /* If card was pulled off just during the suspend, which is very |
1059 | unlikely, we will remove it on resume, it too late now | 1045 | unlikely, we will remove it on resume, it too late now |
1060 | anyway... */ | 1046 | anyway... */ |
1061 | dev->card_unstable = 0; | 1047 | dev->card_unstable = 0; |
1062 | 1048 | return 0; | |
1063 | pci_save_state(to_pci_dev(device)); | ||
1064 | return pci_prepare_to_sleep(to_pci_dev(device)); | ||
1065 | } | 1049 | } |
1066 | 1050 | ||
1067 | int r852_resume(struct device *device) | 1051 | int r852_resume(struct device *device) |
1068 | { | 1052 | { |
1069 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); | 1053 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); |
1070 | unsigned long flags; | ||
1071 | |||
1072 | /* Turn on the hardware */ | ||
1073 | pci_back_from_sleep(to_pci_dev(device)); | ||
1074 | pci_restore_state(to_pci_dev(device)); | ||
1075 | 1054 | ||
1076 | r852_disable_irqs(dev); | 1055 | r852_disable_irqs(dev); |
1077 | r852_card_update_present(dev); | 1056 | r852_card_update_present(dev); |
1078 | r852_engine_disable(dev); | 1057 | r852_engine_disable(dev); |
1079 | 1058 | ||
1080 | 1059 | ||
1081 | /* Now its safe for IRQ to run */ | ||
1082 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1083 | dev->insuspend = 0; | ||
1084 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1085 | |||
1086 | |||
1087 | /* If card status changed, just do the work */ | 1060 | /* If card status changed, just do the work */ |
1088 | if (dev->card_detected != dev->card_registred) { | 1061 | if (dev->card_detected != dev->card_registred) { |
1089 | dbg("card was %s during low power state", | 1062 | dbg("card was %s during low power state", |
@@ -1121,7 +1094,6 @@ MODULE_DEVICE_TABLE(pci, r852_pci_id_tbl); | |||
1121 | 1094 | ||
1122 | SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume); | 1095 | SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume); |
1123 | 1096 | ||
1124 | |||
1125 | static struct pci_driver r852_pci_driver = { | 1097 | static struct pci_driver r852_pci_driver = { |
1126 | .name = DRV_NAME, | 1098 | .name = DRV_NAME, |
1127 | .id_table = r852_pci_id_tbl, | 1099 | .id_table = r852_pci_id_tbl, |
diff --git a/drivers/mtd/nand/r852.h b/drivers/mtd/nand/r852.h index 8096cc280c73..e6a21d9d22c6 100644 --- a/drivers/mtd/nand/r852.h +++ b/drivers/mtd/nand/r852.h | |||
@@ -140,8 +140,6 @@ struct r852_device { | |||
140 | /* interrupt handling */ | 140 | /* interrupt handling */ |
141 | spinlock_t irqlock; /* IRQ protecting lock */ | 141 | spinlock_t irqlock; /* IRQ protecting lock */ |
142 | int irq; /* irq num */ | 142 | int irq; /* irq num */ |
143 | int insuspend; /* device is suspended */ | ||
144 | |||
145 | /* misc */ | 143 | /* misc */ |
146 | void *tmp_buffer; /* temporary buffer */ | 144 | void *tmp_buffer; /* temporary buffer */ |
147 | uint8_t ctlreg; /* cached contents of control reg */ | 145 | uint8_t ctlreg; /* cached contents of control reg */ |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 7bd171eefd21..a996718fa6b0 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c | |||
@@ -44,7 +44,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev, | |||
44 | pp = NULL; | 44 | pp = NULL; |
45 | i = 0; | 45 | i = 0; |
46 | while ((pp = of_get_next_child(node, pp))) { | 46 | while ((pp = of_get_next_child(node, pp))) { |
47 | const u32 *reg; | 47 | const __be32 *reg; |
48 | int len; | 48 | int len; |
49 | 49 | ||
50 | reg = of_get_property(pp, "reg", &len); | 50 | reg = of_get_property(pp, "reg", &len); |
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 3f32289fdbb5..4dbd0f58eebf 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig | |||
@@ -32,10 +32,11 @@ config MTD_ONENAND_OMAP2 | |||
32 | 32 | ||
33 | config MTD_ONENAND_SAMSUNG | 33 | config MTD_ONENAND_SAMSUNG |
34 | tristate "OneNAND on Samsung SOC controller support" | 34 | tristate "OneNAND on Samsung SOC controller support" |
35 | depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 | 35 | depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310 |
36 | help | 36 | help |
37 | Support for a OneNAND flash device connected to an Samsung SOC | 37 | Support for a OneNAND flash device connected to an Samsung SOC. |
38 | S3C64XX/S5PC1XX controller. | 38 | S3C64XX/S5PC100 use command mapping method. |
39 | S5PC110/S5PC210 use generic OneNAND method. | ||
39 | 40 | ||
40 | config MTD_ONENAND_OTP | 41 | config MTD_ONENAND_OTP |
41 | bool "OneNAND OTP Support" | 42 | bool "OneNAND OTP Support" |
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index a2bb520286f8..6b3a875647c9 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -3365,18 +3365,19 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, | |||
3365 | static void onenand_check_features(struct mtd_info *mtd) | 3365 | static void onenand_check_features(struct mtd_info *mtd) |
3366 | { | 3366 | { |
3367 | struct onenand_chip *this = mtd->priv; | 3367 | struct onenand_chip *this = mtd->priv; |
3368 | unsigned int density, process; | 3368 | unsigned int density, process, numbufs; |
3369 | 3369 | ||
3370 | /* Lock scheme depends on density and process */ | 3370 | /* Lock scheme depends on density and process */ |
3371 | density = onenand_get_density(this->device_id); | 3371 | density = onenand_get_density(this->device_id); |
3372 | process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; | 3372 | process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; |
3373 | numbufs = this->read_word(this->base + ONENAND_REG_NUM_BUFFERS) >> 8; | ||
3373 | 3374 | ||
3374 | /* Lock scheme */ | 3375 | /* Lock scheme */ |
3375 | switch (density) { | 3376 | switch (density) { |
3376 | case ONENAND_DEVICE_DENSITY_4Gb: | 3377 | case ONENAND_DEVICE_DENSITY_4Gb: |
3377 | if (ONENAND_IS_DDP(this)) | 3378 | if (ONENAND_IS_DDP(this)) |
3378 | this->options |= ONENAND_HAS_2PLANE; | 3379 | this->options |= ONENAND_HAS_2PLANE; |
3379 | else | 3380 | else if (numbufs == 1) |
3380 | this->options |= ONENAND_HAS_4KB_PAGE; | 3381 | this->options |= ONENAND_HAS_4KB_PAGE; |
3381 | 3382 | ||
3382 | case ONENAND_DEVICE_DENSITY_2Gb: | 3383 | case ONENAND_DEVICE_DENSITY_2Gb: |
@@ -4027,7 +4028,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
4027 | mtd->ecclayout = this->ecclayout; | 4028 | mtd->ecclayout = this->ecclayout; |
4028 | 4029 | ||
4029 | /* Fill in remaining MTD driver data */ | 4030 | /* Fill in remaining MTD driver data */ |
4030 | mtd->type = MTD_NANDFLASH; | 4031 | mtd->type = ONENAND_IS_MLC(this) ? MTD_MLCNANDFLASH : MTD_NANDFLASH; |
4031 | mtd->flags = MTD_CAP_NANDFLASH; | 4032 | mtd->flags = MTD_CAP_NANDFLASH; |
4032 | mtd->erase = onenand_erase; | 4033 | mtd->erase = onenand_erase; |
4033 | mtd->point = NULL; | 4034 | mtd->point = NULL; |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index a460f1b748c2..0de7a05e6de0 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/mtd/onenand.h> | 22 | #include <linux/mtd/onenand.h> |
23 | #include <linux/mtd/partitions.h> | 23 | #include <linux/mtd/partitions.h> |
24 | #include <linux/dma-mapping.h> | 24 | #include <linux/dma-mapping.h> |
25 | #include <linux/interrupt.h> | ||
25 | 26 | ||
26 | #include <asm/mach/flash.h> | 27 | #include <asm/mach/flash.h> |
27 | #include <plat/regs-onenand.h> | 28 | #include <plat/regs-onenand.h> |
@@ -58,7 +59,7 @@ enum soc_type { | |||
58 | #define MAP_11 (0x3) | 59 | #define MAP_11 (0x3) |
59 | 60 | ||
60 | #define S3C64XX_CMD_MAP_SHIFT 24 | 61 | #define S3C64XX_CMD_MAP_SHIFT 24 |
61 | #define S5PC1XX_CMD_MAP_SHIFT 26 | 62 | #define S5PC100_CMD_MAP_SHIFT 26 |
62 | 63 | ||
63 | #define S3C6400_FBA_SHIFT 10 | 64 | #define S3C6400_FBA_SHIFT 10 |
64 | #define S3C6400_FPA_SHIFT 4 | 65 | #define S3C6400_FPA_SHIFT 4 |
@@ -81,6 +82,17 @@ enum soc_type { | |||
81 | #define S5PC110_DMA_TRANS_CMD 0x418 | 82 | #define S5PC110_DMA_TRANS_CMD 0x418 |
82 | #define S5PC110_DMA_TRANS_STATUS 0x41C | 83 | #define S5PC110_DMA_TRANS_STATUS 0x41C |
83 | #define S5PC110_DMA_TRANS_DIR 0x420 | 84 | #define S5PC110_DMA_TRANS_DIR 0x420 |
85 | #define S5PC110_INTC_DMA_CLR 0x1004 | ||
86 | #define S5PC110_INTC_ONENAND_CLR 0x1008 | ||
87 | #define S5PC110_INTC_DMA_MASK 0x1024 | ||
88 | #define S5PC110_INTC_ONENAND_MASK 0x1028 | ||
89 | #define S5PC110_INTC_DMA_PEND 0x1044 | ||
90 | #define S5PC110_INTC_ONENAND_PEND 0x1048 | ||
91 | #define S5PC110_INTC_DMA_STATUS 0x1064 | ||
92 | #define S5PC110_INTC_ONENAND_STATUS 0x1068 | ||
93 | |||
94 | #define S5PC110_INTC_DMA_TD (1 << 24) | ||
95 | #define S5PC110_INTC_DMA_TE (1 << 16) | ||
84 | 96 | ||
85 | #define S5PC110_DMA_CFG_SINGLE (0x0 << 16) | 97 | #define S5PC110_DMA_CFG_SINGLE (0x0 << 16) |
86 | #define S5PC110_DMA_CFG_4BURST (0x2 << 16) | 98 | #define S5PC110_DMA_CFG_4BURST (0x2 << 16) |
@@ -134,6 +146,7 @@ struct s3c_onenand { | |||
134 | void __iomem *dma_addr; | 146 | void __iomem *dma_addr; |
135 | struct resource *dma_res; | 147 | struct resource *dma_res; |
136 | unsigned long phys_base; | 148 | unsigned long phys_base; |
149 | struct completion complete; | ||
137 | #ifdef CONFIG_MTD_PARTITIONS | 150 | #ifdef CONFIG_MTD_PARTITIONS |
138 | struct mtd_partition *parts; | 151 | struct mtd_partition *parts; |
139 | #endif | 152 | #endif |
@@ -191,7 +204,7 @@ static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val) | |||
191 | 204 | ||
192 | static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val) | 205 | static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val) |
193 | { | 206 | { |
194 | return (type << S5PC1XX_CMD_MAP_SHIFT) | val; | 207 | return (type << S5PC100_CMD_MAP_SHIFT) | val; |
195 | } | 208 | } |
196 | 209 | ||
197 | static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa) | 210 | static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa) |
@@ -531,10 +544,13 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area, | |||
531 | return 0; | 544 | return 0; |
532 | } | 545 | } |
533 | 546 | ||
534 | static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | 547 | static int (*s5pc110_dma_ops)(void *dst, void *src, size_t count, int direction); |
548 | |||
549 | static int s5pc110_dma_poll(void *dst, void *src, size_t count, int direction) | ||
535 | { | 550 | { |
536 | void __iomem *base = onenand->dma_addr; | 551 | void __iomem *base = onenand->dma_addr; |
537 | int status; | 552 | int status; |
553 | unsigned long timeout; | ||
538 | 554 | ||
539 | writel(src, base + S5PC110_DMA_SRC_ADDR); | 555 | writel(src, base + S5PC110_DMA_SRC_ADDR); |
540 | writel(dst, base + S5PC110_DMA_DST_ADDR); | 556 | writel(dst, base + S5PC110_DMA_DST_ADDR); |
@@ -552,6 +568,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | |||
552 | 568 | ||
553 | writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD); | 569 | writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD); |
554 | 570 | ||
571 | /* | ||
572 | * There's no exact timeout values at Spec. | ||
573 | * In real case it takes under 1 msec. | ||
574 | * So 20 msecs are enough. | ||
575 | */ | ||
576 | timeout = jiffies + msecs_to_jiffies(20); | ||
577 | |||
555 | do { | 578 | do { |
556 | status = readl(base + S5PC110_DMA_TRANS_STATUS); | 579 | status = readl(base + S5PC110_DMA_TRANS_STATUS); |
557 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { | 580 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { |
@@ -559,13 +582,68 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | |||
559 | base + S5PC110_DMA_TRANS_CMD); | 582 | base + S5PC110_DMA_TRANS_CMD); |
560 | return -EIO; | 583 | return -EIO; |
561 | } | 584 | } |
562 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); | 585 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD) && |
586 | time_before(jiffies, timeout)); | ||
563 | 587 | ||
564 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); | 588 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); |
565 | 589 | ||
566 | return 0; | 590 | return 0; |
567 | } | 591 | } |
568 | 592 | ||
593 | static irqreturn_t s5pc110_onenand_irq(int irq, void *data) | ||
594 | { | ||
595 | void __iomem *base = onenand->dma_addr; | ||
596 | int status, cmd = 0; | ||
597 | |||
598 | status = readl(base + S5PC110_INTC_DMA_STATUS); | ||
599 | |||
600 | if (likely(status & S5PC110_INTC_DMA_TD)) | ||
601 | cmd = S5PC110_DMA_TRANS_CMD_TDC; | ||
602 | |||
603 | if (unlikely(status & S5PC110_INTC_DMA_TE)) | ||
604 | cmd = S5PC110_DMA_TRANS_CMD_TEC; | ||
605 | |||
606 | writel(cmd, base + S5PC110_DMA_TRANS_CMD); | ||
607 | writel(status, base + S5PC110_INTC_DMA_CLR); | ||
608 | |||
609 | if (!onenand->complete.done) | ||
610 | complete(&onenand->complete); | ||
611 | |||
612 | return IRQ_HANDLED; | ||
613 | } | ||
614 | |||
615 | static int s5pc110_dma_irq(void *dst, void *src, size_t count, int direction) | ||
616 | { | ||
617 | void __iomem *base = onenand->dma_addr; | ||
618 | int status; | ||
619 | |||
620 | status = readl(base + S5PC110_INTC_DMA_MASK); | ||
621 | if (status) { | ||
622 | status &= ~(S5PC110_INTC_DMA_TD | S5PC110_INTC_DMA_TE); | ||
623 | writel(status, base + S5PC110_INTC_DMA_MASK); | ||
624 | } | ||
625 | |||
626 | writel(src, base + S5PC110_DMA_SRC_ADDR); | ||
627 | writel(dst, base + S5PC110_DMA_DST_ADDR); | ||
628 | |||
629 | if (direction == S5PC110_DMA_DIR_READ) { | ||
630 | writel(S5PC110_DMA_SRC_CFG_READ, base + S5PC110_DMA_SRC_CFG); | ||
631 | writel(S5PC110_DMA_DST_CFG_READ, base + S5PC110_DMA_DST_CFG); | ||
632 | } else { | ||
633 | writel(S5PC110_DMA_SRC_CFG_WRITE, base + S5PC110_DMA_SRC_CFG); | ||
634 | writel(S5PC110_DMA_DST_CFG_WRITE, base + S5PC110_DMA_DST_CFG); | ||
635 | } | ||
636 | |||
637 | writel(count, base + S5PC110_DMA_TRANS_SIZE); | ||
638 | writel(direction, base + S5PC110_DMA_TRANS_DIR); | ||
639 | |||
640 | writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD); | ||
641 | |||
642 | wait_for_completion_timeout(&onenand->complete, msecs_to_jiffies(20)); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
569 | static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | 647 | static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, |
570 | unsigned char *buffer, int offset, size_t count) | 648 | unsigned char *buffer, int offset, size_t count) |
571 | { | 649 | { |
@@ -573,7 +651,8 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
573 | void __iomem *p; | 651 | void __iomem *p; |
574 | void *buf = (void *) buffer; | 652 | void *buf = (void *) buffer; |
575 | dma_addr_t dma_src, dma_dst; | 653 | dma_addr_t dma_src, dma_dst; |
576 | int err; | 654 | int err, page_dma = 0; |
655 | struct device *dev = &onenand->pdev->dev; | ||
577 | 656 | ||
578 | p = this->base + area; | 657 | p = this->base + area; |
579 | if (ONENAND_CURRENT_BUFFERRAM(this)) { | 658 | if (ONENAND_CURRENT_BUFFERRAM(this)) { |
@@ -597,21 +676,27 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
597 | page = vmalloc_to_page(buf); | 676 | page = vmalloc_to_page(buf); |
598 | if (!page) | 677 | if (!page) |
599 | goto normal; | 678 | goto normal; |
600 | buf = page_address(page) + ((size_t) buf & ~PAGE_MASK); | ||
601 | } | ||
602 | 679 | ||
603 | /* DMA routine */ | 680 | page_dma = 1; |
604 | dma_src = onenand->phys_base + (p - this->base); | 681 | /* DMA routine */ |
605 | dma_dst = dma_map_single(&onenand->pdev->dev, | 682 | dma_src = onenand->phys_base + (p - this->base); |
606 | buf, count, DMA_FROM_DEVICE); | 683 | dma_dst = dma_map_page(dev, page, 0, count, DMA_FROM_DEVICE); |
607 | if (dma_mapping_error(&onenand->pdev->dev, dma_dst)) { | 684 | } else { |
608 | dev_err(&onenand->pdev->dev, | 685 | /* DMA routine */ |
609 | "Couldn't map a %d byte buffer for DMA\n", count); | 686 | dma_src = onenand->phys_base + (p - this->base); |
687 | dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE); | ||
688 | } | ||
689 | if (dma_mapping_error(dev, dma_dst)) { | ||
690 | dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count); | ||
610 | goto normal; | 691 | goto normal; |
611 | } | 692 | } |
612 | err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src, | 693 | err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src, |
613 | count, S5PC110_DMA_DIR_READ); | 694 | count, S5PC110_DMA_DIR_READ); |
614 | dma_unmap_single(&onenand->pdev->dev, dma_dst, count, DMA_FROM_DEVICE); | 695 | |
696 | if (page_dma) | ||
697 | dma_unmap_page(dev, dma_dst, count, DMA_FROM_DEVICE); | ||
698 | else | ||
699 | dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE); | ||
615 | 700 | ||
616 | if (!err) | 701 | if (!err) |
617 | return 0; | 702 | return 0; |
@@ -759,7 +844,6 @@ static void s3c_onenand_setup(struct mtd_info *mtd) | |||
759 | onenand->cmd_map = s5pc1xx_cmd_map; | 844 | onenand->cmd_map = s5pc1xx_cmd_map; |
760 | } else if (onenand->type == TYPE_S5PC110) { | 845 | } else if (onenand->type == TYPE_S5PC110) { |
761 | /* Use generic onenand functions */ | 846 | /* Use generic onenand functions */ |
762 | onenand->cmd_map = s5pc1xx_cmd_map; | ||
763 | this->read_bufferram = s5pc110_read_bufferram; | 847 | this->read_bufferram = s5pc110_read_bufferram; |
764 | this->chip_probe = s5pc110_chip_probe; | 848 | this->chip_probe = s5pc110_chip_probe; |
765 | return; | 849 | return; |
@@ -904,6 +988,20 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
904 | } | 988 | } |
905 | 989 | ||
906 | onenand->phys_base = onenand->base_res->start; | 990 | onenand->phys_base = onenand->base_res->start; |
991 | |||
992 | s5pc110_dma_ops = s5pc110_dma_poll; | ||
993 | /* Interrupt support */ | ||
994 | r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
995 | if (r) { | ||
996 | init_completion(&onenand->complete); | ||
997 | s5pc110_dma_ops = s5pc110_dma_irq; | ||
998 | err = request_irq(r->start, s5pc110_onenand_irq, | ||
999 | IRQF_SHARED, "onenand", &onenand); | ||
1000 | if (err) { | ||
1001 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
1002 | goto scan_failed; | ||
1003 | } | ||
1004 | } | ||
907 | } | 1005 | } |
908 | 1006 | ||
909 | if (onenand_scan(mtd, 1)) { | 1007 | if (onenand_scan(mtd, 1)) { |
@@ -1000,7 +1098,7 @@ static int s3c_pm_ops_suspend(struct device *dev) | |||
1000 | struct onenand_chip *this = mtd->priv; | 1098 | struct onenand_chip *this = mtd->priv; |
1001 | 1099 | ||
1002 | this->wait(mtd, FL_PM_SUSPENDED); | 1100 | this->wait(mtd, FL_PM_SUSPENDED); |
1003 | return mtd->suspend(mtd); | 1101 | return 0; |
1004 | } | 1102 | } |
1005 | 1103 | ||
1006 | static int s3c_pm_ops_resume(struct device *dev) | 1104 | static int s3c_pm_ops_resume(struct device *dev) |
@@ -1009,7 +1107,6 @@ static int s3c_pm_ops_resume(struct device *dev) | |||
1009 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 1107 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
1010 | struct onenand_chip *this = mtd->priv; | 1108 | struct onenand_chip *this = mtd->priv; |
1011 | 1109 | ||
1012 | mtd->resume(mtd); | ||
1013 | this->unlock_all(mtd); | 1110 | this->unlock_all(mtd); |
1014 | return 0; | 1111 | return 0; |
1015 | } | 1112 | } |
diff --git a/drivers/mtd/sm_ftl.h b/drivers/mtd/sm_ftl.h index e30e48e7f63d..43bb7300785b 100644 --- a/drivers/mtd/sm_ftl.h +++ b/drivers/mtd/sm_ftl.h | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | struct ftl_zone { | 22 | struct ftl_zone { |
23 | int initialized; | 23 | bool initialized; |
24 | int16_t *lba_to_phys_table; /* LBA to physical table */ | 24 | int16_t *lba_to_phys_table; /* LBA to physical table */ |
25 | struct kfifo free_sectors; /* queue of free sectors */ | 25 | struct kfifo free_sectors; /* queue of free sectors */ |
26 | }; | 26 | }; |
@@ -37,8 +37,8 @@ struct sm_ftl { | |||
37 | int zone_count; /* number of zones */ | 37 | int zone_count; /* number of zones */ |
38 | int max_lba; /* maximum lba in a zone */ | 38 | int max_lba; /* maximum lba in a zone */ |
39 | int smallpagenand; /* 256 bytes/page nand */ | 39 | int smallpagenand; /* 256 bytes/page nand */ |
40 | int readonly; /* is FS readonly */ | 40 | bool readonly; /* is FS readonly */ |
41 | int unstable; | 41 | bool unstable; |
42 | int cis_block; /* CIS block location */ | 42 | int cis_block; /* CIS block location */ |
43 | int cis_boffset; /* CIS offset in the block */ | 43 | int cis_boffset; /* CIS offset in the block */ |
44 | int cis_page_offset; /* CIS offset in the page */ | 44 | int cis_page_offset; /* CIS offset in the page */ |
@@ -49,7 +49,7 @@ struct sm_ftl { | |||
49 | int cache_zone; /* zone of cached block */ | 49 | int cache_zone; /* zone of cached block */ |
50 | unsigned char *cache_data; /* cached block data */ | 50 | unsigned char *cache_data; /* cached block data */ |
51 | long unsigned int cache_data_invalid_bitmap; | 51 | long unsigned int cache_data_invalid_bitmap; |
52 | int cache_clean; | 52 | bool cache_clean; |
53 | struct work_struct flush_work; | 53 | struct work_struct flush_work; |
54 | struct timer_list timer; | 54 | struct timer_list timer; |
55 | 55 | ||
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index a906f538d11c..85c6be2db02f 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c | |||
@@ -23,7 +23,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, | |||
23 | static inline struct jffs2_inode_cache * | 23 | static inline struct jffs2_inode_cache * |
24 | first_inode_chain(int *i, struct jffs2_sb_info *c) | 24 | first_inode_chain(int *i, struct jffs2_sb_info *c) |
25 | { | 25 | { |
26 | for (; *i < INOCACHE_HASHSIZE; (*i)++) { | 26 | for (; *i < c->inocache_hashsize; (*i)++) { |
27 | if (c->inocache_list[*i]) | 27 | if (c->inocache_list[*i]) |
28 | return c->inocache_list[*i]; | 28 | return c->inocache_list[*i]; |
29 | } | 29 | } |
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index 617a1e5694c1..de4247021d25 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c | |||
@@ -103,7 +103,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
103 | spin_unlock(&jffs2_compressor_list_lock); | 103 | spin_unlock(&jffs2_compressor_list_lock); |
104 | *datalen = orig_slen; | 104 | *datalen = orig_slen; |
105 | *cdatalen = orig_dlen; | 105 | *cdatalen = orig_dlen; |
106 | compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL); | 106 | compr_ret = this->compress(data_in, output_buf, datalen, cdatalen); |
107 | spin_lock(&jffs2_compressor_list_lock); | 107 | spin_lock(&jffs2_compressor_list_lock); |
108 | this->usecount--; | 108 | this->usecount--; |
109 | if (!compr_ret) { | 109 | if (!compr_ret) { |
@@ -152,7 +152,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
152 | spin_unlock(&jffs2_compressor_list_lock); | 152 | spin_unlock(&jffs2_compressor_list_lock); |
153 | *datalen = orig_slen; | 153 | *datalen = orig_slen; |
154 | *cdatalen = orig_dlen; | 154 | *cdatalen = orig_dlen; |
155 | compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL); | 155 | compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen); |
156 | spin_lock(&jffs2_compressor_list_lock); | 156 | spin_lock(&jffs2_compressor_list_lock); |
157 | this->usecount--; | 157 | this->usecount--; |
158 | if (!compr_ret) { | 158 | if (!compr_ret) { |
@@ -220,7 +220,7 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
220 | if (comprtype == this->compr) { | 220 | if (comprtype == this->compr) { |
221 | this->usecount++; | 221 | this->usecount++; |
222 | spin_unlock(&jffs2_compressor_list_lock); | 222 | spin_unlock(&jffs2_compressor_list_lock); |
223 | ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL); | 223 | ret = this->decompress(cdata_in, data_out, cdatalen, datalen); |
224 | spin_lock(&jffs2_compressor_list_lock); | 224 | spin_lock(&jffs2_compressor_list_lock); |
225 | if (ret) { | 225 | if (ret) { |
226 | printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); | 226 | printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); |
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index e471a9106fd9..13bb7597ab39 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h | |||
@@ -49,9 +49,9 @@ struct jffs2_compressor { | |||
49 | char *name; | 49 | char *name; |
50 | char compr; /* JFFS2_COMPR_XXX */ | 50 | char compr; /* JFFS2_COMPR_XXX */ |
51 | int (*compress)(unsigned char *data_in, unsigned char *cpage_out, | 51 | int (*compress)(unsigned char *data_in, unsigned char *cpage_out, |
52 | uint32_t *srclen, uint32_t *destlen, void *model); | 52 | uint32_t *srclen, uint32_t *destlen); |
53 | int (*decompress)(unsigned char *cdata_in, unsigned char *data_out, | 53 | int (*decompress)(unsigned char *cdata_in, unsigned char *data_out, |
54 | uint32_t cdatalen, uint32_t datalen, void *model); | 54 | uint32_t cdatalen, uint32_t datalen); |
55 | int usecount; | 55 | int usecount; |
56 | int disabled; /* if set the compressor won't compress */ | 56 | int disabled; /* if set the compressor won't compress */ |
57 | unsigned char *compr_buf; /* used by size compr. mode */ | 57 | unsigned char *compr_buf; /* used by size compr. mode */ |
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c index ed25ae7c98eb..af186ee674d8 100644 --- a/fs/jffs2/compr_lzo.c +++ b/fs/jffs2/compr_lzo.c | |||
@@ -42,7 +42,7 @@ static int __init alloc_workspace(void) | |||
42 | } | 42 | } |
43 | 43 | ||
44 | static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, | 44 | static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, |
45 | uint32_t *sourcelen, uint32_t *dstlen, void *model) | 45 | uint32_t *sourcelen, uint32_t *dstlen) |
46 | { | 46 | { |
47 | size_t compress_size; | 47 | size_t compress_size; |
48 | int ret; | 48 | int ret; |
@@ -67,7 +67,7 @@ static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, | |||
67 | } | 67 | } |
68 | 68 | ||
69 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, | 69 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, |
70 | uint32_t srclen, uint32_t destlen, void *model) | 70 | uint32_t srclen, uint32_t destlen) |
71 | { | 71 | { |
72 | size_t dl = destlen; | 72 | size_t dl = destlen; |
73 | int ret; | 73 | int ret; |
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 9696ad9ef5f7..16a5047903a6 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c | |||
@@ -31,8 +31,7 @@ | |||
31 | /* _compress returns the compressed size, -1 if bigger */ | 31 | /* _compress returns the compressed size, -1 if bigger */ |
32 | static int jffs2_rtime_compress(unsigned char *data_in, | 32 | static int jffs2_rtime_compress(unsigned char *data_in, |
33 | unsigned char *cpage_out, | 33 | unsigned char *cpage_out, |
34 | uint32_t *sourcelen, uint32_t *dstlen, | 34 | uint32_t *sourcelen, uint32_t *dstlen) |
35 | void *model) | ||
36 | { | 35 | { |
37 | short positions[256]; | 36 | short positions[256]; |
38 | int outpos = 0; | 37 | int outpos = 0; |
@@ -73,8 +72,7 @@ static int jffs2_rtime_compress(unsigned char *data_in, | |||
73 | 72 | ||
74 | static int jffs2_rtime_decompress(unsigned char *data_in, | 73 | static int jffs2_rtime_decompress(unsigned char *data_in, |
75 | unsigned char *cpage_out, | 74 | unsigned char *cpage_out, |
76 | uint32_t srclen, uint32_t destlen, | 75 | uint32_t srclen, uint32_t destlen) |
77 | void *model) | ||
78 | { | 76 | { |
79 | short positions[256]; | 77 | short positions[256]; |
80 | int outpos = 0; | 78 | int outpos = 0; |
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index a12b4f763373..9e7cec808c4c 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c | |||
@@ -298,7 +298,7 @@ static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, | |||
298 | #if 0 | 298 | #if 0 |
299 | /* _compress returns the compressed size, -1 if bigger */ | 299 | /* _compress returns the compressed size, -1 if bigger */ |
300 | int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, | 300 | int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, |
301 | uint32_t *sourcelen, uint32_t *dstlen, void *model) | 301 | uint32_t *sourcelen, uint32_t *dstlen) |
302 | { | 302 | { |
303 | return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, | 303 | return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, |
304 | cpage_out, sourcelen, dstlen); | 304 | cpage_out, sourcelen, dstlen); |
@@ -306,8 +306,7 @@ int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, | |||
306 | #endif | 306 | #endif |
307 | static int jffs2_dynrubin_compress(unsigned char *data_in, | 307 | static int jffs2_dynrubin_compress(unsigned char *data_in, |
308 | unsigned char *cpage_out, | 308 | unsigned char *cpage_out, |
309 | uint32_t *sourcelen, uint32_t *dstlen, | 309 | uint32_t *sourcelen, uint32_t *dstlen) |
310 | void *model) | ||
311 | { | 310 | { |
312 | int bits[8]; | 311 | int bits[8]; |
313 | unsigned char histo[256]; | 312 | unsigned char histo[256]; |
@@ -387,8 +386,7 @@ static void rubin_do_decompress(int bit_divider, int *bits, | |||
387 | 386 | ||
388 | static int jffs2_rubinmips_decompress(unsigned char *data_in, | 387 | static int jffs2_rubinmips_decompress(unsigned char *data_in, |
389 | unsigned char *cpage_out, | 388 | unsigned char *cpage_out, |
390 | uint32_t sourcelen, uint32_t dstlen, | 389 | uint32_t sourcelen, uint32_t dstlen) |
391 | void *model) | ||
392 | { | 390 | { |
393 | rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, | 391 | rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, |
394 | cpage_out, sourcelen, dstlen); | 392 | cpage_out, sourcelen, dstlen); |
@@ -397,8 +395,7 @@ static int jffs2_rubinmips_decompress(unsigned char *data_in, | |||
397 | 395 | ||
398 | static int jffs2_dynrubin_decompress(unsigned char *data_in, | 396 | static int jffs2_dynrubin_decompress(unsigned char *data_in, |
399 | unsigned char *cpage_out, | 397 | unsigned char *cpage_out, |
400 | uint32_t sourcelen, uint32_t dstlen, | 398 | uint32_t sourcelen, uint32_t dstlen) |
401 | void *model) | ||
402 | { | 399 | { |
403 | int bits[8]; | 400 | int bits[8]; |
404 | int c; | 401 | int c; |
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 97fc45de6f81..fd05a0b9431d 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c | |||
@@ -68,8 +68,7 @@ static void free_workspaces(void) | |||
68 | 68 | ||
69 | static int jffs2_zlib_compress(unsigned char *data_in, | 69 | static int jffs2_zlib_compress(unsigned char *data_in, |
70 | unsigned char *cpage_out, | 70 | unsigned char *cpage_out, |
71 | uint32_t *sourcelen, uint32_t *dstlen, | 71 | uint32_t *sourcelen, uint32_t *dstlen) |
72 | void *model) | ||
73 | { | 72 | { |
74 | int ret; | 73 | int ret; |
75 | 74 | ||
@@ -136,8 +135,7 @@ static int jffs2_zlib_compress(unsigned char *data_in, | |||
136 | 135 | ||
137 | static int jffs2_zlib_decompress(unsigned char *data_in, | 136 | static int jffs2_zlib_decompress(unsigned char *data_in, |
138 | unsigned char *cpage_out, | 137 | unsigned char *cpage_out, |
139 | uint32_t srclen, uint32_t destlen, | 138 | uint32_t srclen, uint32_t destlen) |
140 | void *model) | ||
141 | { | 139 | { |
142 | int ret; | 140 | int ret; |
143 | int wbits = MAX_WBITS; | 141 | int wbits = MAX_WBITS; |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 79121aa5858b..92978658ed18 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -367,7 +367,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
367 | } | 367 | } |
368 | 368 | ||
369 | /* We use f->target field to store the target path. */ | 369 | /* We use f->target field to store the target path. */ |
370 | f->target = kmalloc(targetlen + 1, GFP_KERNEL); | 370 | f->target = kmemdup(target, targetlen + 1, GFP_KERNEL); |
371 | if (!f->target) { | 371 | if (!f->target) { |
372 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); | 372 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); |
373 | mutex_unlock(&f->sem); | 373 | mutex_unlock(&f->sem); |
@@ -376,7 +376,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
376 | goto fail; | 376 | goto fail; |
377 | } | 377 | } |
378 | 378 | ||
379 | memcpy(f->target, target, targetlen + 1); | ||
380 | D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); | 379 | D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); |
381 | 380 | ||
382 | /* No data here. Only a metadata node, which will be | 381 | /* No data here. Only a metadata node, which will be |
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index abac961f617b..e513f1913c15 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c | |||
@@ -151,7 +151,7 @@ int jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) | |||
151 | } | 151 | } |
152 | 152 | ||
153 | /* Be nice */ | 153 | /* Be nice */ |
154 | yield(); | 154 | cond_resched(); |
155 | mutex_lock(&c->erase_free_sem); | 155 | mutex_lock(&c->erase_free_sem); |
156 | spin_lock(&c->erase_completion_lock); | 156 | spin_lock(&c->erase_completion_lock); |
157 | } | 157 | } |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index d9beb06e6fca..e896e67767eb 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -474,6 +474,25 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i | |||
474 | return inode; | 474 | return inode; |
475 | } | 475 | } |
476 | 476 | ||
477 | static int calculate_inocache_hashsize(uint32_t flash_size) | ||
478 | { | ||
479 | /* | ||
480 | * Pick a inocache hash size based on the size of the medium. | ||
481 | * Count how many megabytes we're dealing with, apply a hashsize twice | ||
482 | * that size, but rounding down to the usual big powers of 2. And keep | ||
483 | * to sensible bounds. | ||
484 | */ | ||
485 | |||
486 | int size_mb = flash_size / 1024 / 1024; | ||
487 | int hashsize = (size_mb * 2) & ~0x3f; | ||
488 | |||
489 | if (hashsize < INOCACHE_HASHSIZE_MIN) | ||
490 | return INOCACHE_HASHSIZE_MIN; | ||
491 | if (hashsize > INOCACHE_HASHSIZE_MAX) | ||
492 | return INOCACHE_HASHSIZE_MAX; | ||
493 | |||
494 | return hashsize; | ||
495 | } | ||
477 | 496 | ||
478 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | 497 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) |
479 | { | 498 | { |
@@ -520,7 +539,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | |||
520 | if (ret) | 539 | if (ret) |
521 | return ret; | 540 | return ret; |
522 | 541 | ||
523 | c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); | 542 | c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size); |
543 | c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); | ||
524 | if (!c->inocache_list) { | 544 | if (!c->inocache_list) { |
525 | ret = -ENOMEM; | 545 | ret = -ENOMEM; |
526 | goto out_wbuf; | 546 | goto out_wbuf; |
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 846a79452497..31dce611337c 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
@@ -219,13 +219,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
219 | if (!list_empty(&c->erase_complete_list) || | 219 | if (!list_empty(&c->erase_complete_list) || |
220 | !list_empty(&c->erase_pending_list)) { | 220 | !list_empty(&c->erase_pending_list)) { |
221 | spin_unlock(&c->erase_completion_lock); | 221 | spin_unlock(&c->erase_completion_lock); |
222 | mutex_unlock(&c->alloc_sem); | ||
222 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n")); | 223 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n")); |
223 | if (jffs2_erase_pending_blocks(c, 1)) { | 224 | if (jffs2_erase_pending_blocks(c, 1)) |
224 | mutex_unlock(&c->alloc_sem); | ||
225 | return 0; | 225 | return 0; |
226 | } | 226 | |
227 | D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n")); | 227 | D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n")); |
228 | spin_lock(&c->erase_completion_lock); | 228 | spin_lock(&c->erase_completion_lock); |
229 | mutex_lock(&c->alloc_sem); | ||
229 | } | 230 | } |
230 | 231 | ||
231 | /* First, work out which block we're garbage-collecting */ | 232 | /* First, work out which block we're garbage-collecting */ |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 6784bc89add1..f864005de64c 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -100,6 +100,7 @@ struct jffs2_sb_info { | |||
100 | wait_queue_head_t erase_wait; /* For waiting for erases to complete */ | 100 | wait_queue_head_t erase_wait; /* For waiting for erases to complete */ |
101 | 101 | ||
102 | wait_queue_head_t inocache_wq; | 102 | wait_queue_head_t inocache_wq; |
103 | int inocache_hashsize; | ||
103 | struct jffs2_inode_cache **inocache_list; | 104 | struct jffs2_inode_cache **inocache_list; |
104 | spinlock_t inocache_lock; | 105 | spinlock_t inocache_lock; |
105 | 106 | ||
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index af02bd138469..5e03233c2363 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
@@ -420,7 +420,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t | |||
420 | { | 420 | { |
421 | struct jffs2_inode_cache *ret; | 421 | struct jffs2_inode_cache *ret; |
422 | 422 | ||
423 | ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; | 423 | ret = c->inocache_list[ino % c->inocache_hashsize]; |
424 | while (ret && ret->ino < ino) { | 424 | while (ret && ret->ino < ino) { |
425 | ret = ret->next; | 425 | ret = ret->next; |
426 | } | 426 | } |
@@ -441,7 +441,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new | |||
441 | 441 | ||
442 | dbg_inocache("add %p (ino #%u)\n", new, new->ino); | 442 | dbg_inocache("add %p (ino #%u)\n", new, new->ino); |
443 | 443 | ||
444 | prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; | 444 | prev = &c->inocache_list[new->ino % c->inocache_hashsize]; |
445 | 445 | ||
446 | while ((*prev) && (*prev)->ino < new->ino) { | 446 | while ((*prev) && (*prev)->ino < new->ino) { |
447 | prev = &(*prev)->next; | 447 | prev = &(*prev)->next; |
@@ -462,7 +462,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) | |||
462 | dbg_inocache("del %p (ino #%u)\n", old, old->ino); | 462 | dbg_inocache("del %p (ino #%u)\n", old, old->ino); |
463 | spin_lock(&c->inocache_lock); | 463 | spin_lock(&c->inocache_lock); |
464 | 464 | ||
465 | prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; | 465 | prev = &c->inocache_list[old->ino % c->inocache_hashsize]; |
466 | 466 | ||
467 | while ((*prev) && (*prev)->ino < old->ino) { | 467 | while ((*prev) && (*prev)->ino < old->ino) { |
468 | prev = &(*prev)->next; | 468 | prev = &(*prev)->next; |
@@ -487,7 +487,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c) | |||
487 | int i; | 487 | int i; |
488 | struct jffs2_inode_cache *this, *next; | 488 | struct jffs2_inode_cache *this, *next; |
489 | 489 | ||
490 | for (i=0; i<INOCACHE_HASHSIZE; i++) { | 490 | for (i=0; i < c->inocache_hashsize; i++) { |
491 | this = c->inocache_list[i]; | 491 | this = c->inocache_list[i]; |
492 | while (this) { | 492 | while (this) { |
493 | next = this->next; | 493 | next = this->next; |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 523a91691052..5a53d9bdb2b5 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -199,7 +199,8 @@ struct jffs2_inode_cache { | |||
199 | #define RAWNODE_CLASS_XATTR_DATUM 1 | 199 | #define RAWNODE_CLASS_XATTR_DATUM 1 |
200 | #define RAWNODE_CLASS_XATTR_REF 2 | 200 | #define RAWNODE_CLASS_XATTR_REF 2 |
201 | 201 | ||
202 | #define INOCACHE_HASHSIZE 128 | 202 | #define INOCACHE_HASHSIZE_MIN 128 |
203 | #define INOCACHE_HASHSIZE_MAX 1024 | ||
203 | 204 | ||
204 | #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size) | 205 | #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size) |
205 | 206 | ||
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 46f870d1cc36..b632dddcb482 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "summary.h" | 20 | #include "summary.h" |
21 | #include "debug.h" | 21 | #include "debug.h" |
22 | 22 | ||
23 | #define DEFAULT_EMPTY_SCAN_SIZE 1024 | 23 | #define DEFAULT_EMPTY_SCAN_SIZE 256 |
24 | 24 | ||
25 | #define noisy_printk(noise, args...) do { \ | 25 | #define noisy_printk(noise, args...) do { \ |
26 | if (*(noise)) { \ | 26 | if (*(noise)) { \ |
@@ -435,7 +435,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
435 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { | 435 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { |
436 | struct jffs2_unknown_node *node; | 436 | struct jffs2_unknown_node *node; |
437 | struct jffs2_unknown_node crcnode; | 437 | struct jffs2_unknown_node crcnode; |
438 | uint32_t ofs, prevofs; | 438 | uint32_t ofs, prevofs, max_ofs; |
439 | uint32_t hdr_crc, buf_ofs, buf_len; | 439 | uint32_t hdr_crc, buf_ofs, buf_len; |
440 | int err; | 440 | int err; |
441 | int noise = 0; | 441 | int noise = 0; |
@@ -550,12 +550,12 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
550 | 550 | ||
551 | /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ | 551 | /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ |
552 | ofs = 0; | 552 | ofs = 0; |
553 | 553 | max_ofs = EMPTY_SCAN_SIZE(c->sector_size); | |
554 | /* Scan only 4KiB of 0xFF before declaring it's empty */ | 554 | /* Scan only EMPTY_SCAN_SIZE of 0xFF before declaring it's empty */ |
555 | while(ofs < EMPTY_SCAN_SIZE(c->sector_size) && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) | 555 | while(ofs < max_ofs && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) |
556 | ofs += 4; | 556 | ofs += 4; |
557 | 557 | ||
558 | if (ofs == EMPTY_SCAN_SIZE(c->sector_size)) { | 558 | if (ofs == max_ofs) { |
559 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | 559 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER |
560 | if (jffs2_cleanmarker_oob(c)) { | 560 | if (jffs2_cleanmarker_oob(c)) { |
561 | /* scan oob, take care of cleanmarker */ | 561 | /* scan oob, take care of cleanmarker */ |
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 7fa20beb2ab9..57cc0e63714f 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h | |||
@@ -84,7 +84,7 @@ struct nand_bbt_descr { | |||
84 | #define NAND_BBT_PERCHIP 0x00000080 | 84 | #define NAND_BBT_PERCHIP 0x00000080 |
85 | /* bbt has a version counter at offset veroffs */ | 85 | /* bbt has a version counter at offset veroffs */ |
86 | #define NAND_BBT_VERSION 0x00000100 | 86 | #define NAND_BBT_VERSION 0x00000100 |
87 | /* Create a bbt if none axists */ | 87 | /* Create a bbt if none exists */ |
88 | #define NAND_BBT_CREATE 0x00000200 | 88 | #define NAND_BBT_CREATE 0x00000200 |
89 | /* Search good / bad pattern through all pages of a block */ | 89 | /* Search good / bad pattern through all pages of a block */ |
90 | #define NAND_BBT_SCANALLPAGES 0x00000400 | 90 | #define NAND_BBT_SCANALLPAGES 0x00000400 |
@@ -102,6 +102,8 @@ struct nand_bbt_descr { | |||
102 | #define NAND_BBT_SCANBYTE1AND6 0x00100000 | 102 | #define NAND_BBT_SCANBYTE1AND6 0x00100000 |
103 | /* The nand_bbt_descr was created dynamicaly and must be freed */ | 103 | /* The nand_bbt_descr was created dynamicaly and must be freed */ |
104 | #define NAND_BBT_DYNAMICSTRUCT 0x00200000 | 104 | #define NAND_BBT_DYNAMICSTRUCT 0x00200000 |
105 | /* The bad block table does not OOB for marker */ | ||
106 | #define NAND_BBT_NO_OOB 0x00400000 | ||
105 | 107 | ||
106 | /* The maximum number of blocks to scan for a bbt */ | 108 | /* The maximum number of blocks to scan for a bbt */ |
107 | #define NAND_BBT_SCAN_MAXBLOCKS 4 | 109 | #define NAND_BBT_SCAN_MAXBLOCKS 4 |
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index d2118b0eac9a..4dd0c2cd7659 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h | |||
@@ -289,6 +289,7 @@ struct cfi_private { | |||
289 | must be of the same type. */ | 289 | must be of the same type. */ |
290 | int mfr, id; | 290 | int mfr, id; |
291 | int numchips; | 291 | int numchips; |
292 | map_word sector_erase_cmd; | ||
292 | unsigned long chipshift; /* Because they're of the same type */ | 293 | unsigned long chipshift; /* Because they're of the same type */ |
293 | const char *im_name; /* inter_module name for cmdset_setup */ | 294 | const char *im_name; /* inter_module name for cmdset_setup */ |
294 | struct flchip chips[0]; /* per-chip data structure for each chip */ | 295 | struct flchip chips[0]; /* per-chip data structure for each chip */ |
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h new file mode 100644 index 000000000000..5d2556700ec2 --- /dev/null +++ b/include/linux/mtd/fsmc.h | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * incude/mtd/fsmc.h | ||
3 | * | ||
4 | * ST Microelectronics | ||
5 | * Flexible Static Memory Controller (FSMC) | ||
6 | * platform data interface and header file | ||
7 | * | ||
8 | * Copyright © 2010 ST Microelectronics | ||
9 | * Vipin Kumar <vipin.kumar@st.com> | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public | ||
12 | * License version 2. This program is licensed "as is" without any | ||
13 | * warranty of any kind, whether express or implied. | ||
14 | */ | ||
15 | |||
16 | #ifndef __MTD_FSMC_H | ||
17 | #define __MTD_FSMC_H | ||
18 | |||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/mtd/physmap.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/mtd/partitions.h> | ||
23 | #include <asm/param.h> | ||
24 | |||
25 | #define FSMC_NAND_BW8 1 | ||
26 | #define FSMC_NAND_BW16 2 | ||
27 | |||
28 | /* | ||
29 | * The placement of the Command Latch Enable (CLE) and | ||
30 | * Address Latch Enable (ALE) is twised around in the | ||
31 | * SPEAR310 implementation. | ||
32 | */ | ||
33 | #if defined(CONFIG_MACH_SPEAR310) | ||
34 | #define PLAT_NAND_CLE (1 << 17) | ||
35 | #define PLAT_NAND_ALE (1 << 16) | ||
36 | #else | ||
37 | #define PLAT_NAND_CLE (1 << 16) | ||
38 | #define PLAT_NAND_ALE (1 << 17) | ||
39 | #endif | ||
40 | |||
41 | #define FSMC_MAX_NOR_BANKS 4 | ||
42 | #define FSMC_MAX_NAND_BANKS 4 | ||
43 | |||
44 | #define FSMC_FLASH_WIDTH8 1 | ||
45 | #define FSMC_FLASH_WIDTH16 2 | ||
46 | |||
47 | struct fsmc_nor_bank_regs { | ||
48 | uint32_t ctrl; | ||
49 | uint32_t ctrl_tim; | ||
50 | }; | ||
51 | |||
52 | /* ctrl register definitions */ | ||
53 | #define BANK_ENABLE (1 << 0) | ||
54 | #define MUXED (1 << 1) | ||
55 | #define NOR_DEV (2 << 2) | ||
56 | #define WIDTH_8 (0 << 4) | ||
57 | #define WIDTH_16 (1 << 4) | ||
58 | #define RSTPWRDWN (1 << 6) | ||
59 | #define WPROT (1 << 7) | ||
60 | #define WRT_ENABLE (1 << 12) | ||
61 | #define WAIT_ENB (1 << 13) | ||
62 | |||
63 | /* ctrl_tim register definitions */ | ||
64 | |||
65 | struct fsms_nand_bank_regs { | ||
66 | uint32_t pc; | ||
67 | uint32_t sts; | ||
68 | uint32_t comm; | ||
69 | uint32_t attrib; | ||
70 | uint32_t ioata; | ||
71 | uint32_t ecc1; | ||
72 | uint32_t ecc2; | ||
73 | uint32_t ecc3; | ||
74 | }; | ||
75 | |||
76 | #define FSMC_NOR_REG_SIZE 0x40 | ||
77 | |||
78 | struct fsmc_regs { | ||
79 | struct fsmc_nor_bank_regs nor_bank_regs[FSMC_MAX_NOR_BANKS]; | ||
80 | uint8_t reserved_1[0x40 - 0x20]; | ||
81 | struct fsms_nand_bank_regs bank_regs[FSMC_MAX_NAND_BANKS]; | ||
82 | uint8_t reserved_2[0xfe0 - 0xc0]; | ||
83 | uint32_t peripid0; /* 0xfe0 */ | ||
84 | uint32_t peripid1; /* 0xfe4 */ | ||
85 | uint32_t peripid2; /* 0xfe8 */ | ||
86 | uint32_t peripid3; /* 0xfec */ | ||
87 | uint32_t pcellid0; /* 0xff0 */ | ||
88 | uint32_t pcellid1; /* 0xff4 */ | ||
89 | uint32_t pcellid2; /* 0xff8 */ | ||
90 | uint32_t pcellid3; /* 0xffc */ | ||
91 | }; | ||
92 | |||
93 | #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) | ||
94 | |||
95 | /* pc register definitions */ | ||
96 | #define FSMC_RESET (1 << 0) | ||
97 | #define FSMC_WAITON (1 << 1) | ||
98 | #define FSMC_ENABLE (1 << 2) | ||
99 | #define FSMC_DEVTYPE_NAND (1 << 3) | ||
100 | #define FSMC_DEVWID_8 (0 << 4) | ||
101 | #define FSMC_DEVWID_16 (1 << 4) | ||
102 | #define FSMC_ECCEN (1 << 6) | ||
103 | #define FSMC_ECCPLEN_512 (0 << 7) | ||
104 | #define FSMC_ECCPLEN_256 (1 << 7) | ||
105 | #define FSMC_TCLR_1 (1 << 9) | ||
106 | #define FSMC_TAR_1 (1 << 13) | ||
107 | |||
108 | /* sts register definitions */ | ||
109 | #define FSMC_CODE_RDY (1 << 15) | ||
110 | |||
111 | /* comm register definitions */ | ||
112 | #define FSMC_TSET_0 (0 << 0) | ||
113 | #define FSMC_TWAIT_6 (6 << 8) | ||
114 | #define FSMC_THOLD_4 (4 << 16) | ||
115 | #define FSMC_THIZ_1 (1 << 24) | ||
116 | |||
117 | /* peripid2 register definitions */ | ||
118 | #define FSMC_REVISION_MSK (0xf) | ||
119 | #define FSMC_REVISION_SHFT (0x4) | ||
120 | |||
121 | #define FSMC_VER1 1 | ||
122 | #define FSMC_VER2 2 | ||
123 | #define FSMC_VER3 3 | ||
124 | #define FSMC_VER4 4 | ||
125 | #define FSMC_VER5 5 | ||
126 | #define FSMC_VER6 6 | ||
127 | #define FSMC_VER7 7 | ||
128 | #define FSMC_VER8 8 | ||
129 | |||
130 | static inline uint32_t get_fsmc_version(struct fsmc_regs *regs) | ||
131 | { | ||
132 | return (readl(®s->peripid2) >> FSMC_REVISION_SHFT) & | ||
133 | FSMC_REVISION_MSK; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * There are 13 bytes of ecc for every 512 byte block in FSMC version 8 | ||
138 | * and it has to be read consecutively and immediately after the 512 | ||
139 | * byte data block for hardware to generate the error bit offsets | ||
140 | * Managing the ecc bytes in the following way is easier. This way is | ||
141 | * similar to oobfree structure maintained already in u-boot nand driver | ||
142 | */ | ||
143 | #define MAX_ECCPLACE_ENTRIES 32 | ||
144 | |||
145 | struct fsmc_nand_eccplace { | ||
146 | uint8_t offset; | ||
147 | uint8_t length; | ||
148 | }; | ||
149 | |||
150 | struct fsmc_eccplace { | ||
151 | struct fsmc_nand_eccplace eccplace[MAX_ECCPLACE_ENTRIES]; | ||
152 | }; | ||
153 | |||
154 | /** | ||
155 | * fsmc_nand_platform_data - platform specific NAND controller config | ||
156 | * @partitions: partition table for the platform, use a default fallback | ||
157 | * if this is NULL | ||
158 | * @nr_partitions: the number of partitions in the previous entry | ||
159 | * @options: different options for the driver | ||
160 | * @width: bus width | ||
161 | * @bank: default bank | ||
162 | * @select_bank: callback to select a certain bank, this is | ||
163 | * platform-specific. If the controller only supports one bank | ||
164 | * this may be set to NULL | ||
165 | */ | ||
166 | struct fsmc_nand_platform_data { | ||
167 | struct mtd_partition *partitions; | ||
168 | unsigned int nr_partitions; | ||
169 | unsigned int options; | ||
170 | unsigned int width; | ||
171 | unsigned int bank; | ||
172 | void (*select_bank)(uint32_t bank, uint32_t busw); | ||
173 | }; | ||
174 | |||
175 | extern int __init fsmc_nor_init(struct platform_device *pdev, | ||
176 | unsigned long base, uint32_t bank, uint32_t width); | ||
177 | extern void __init fsmc_init_board_info(struct platform_device *pdev, | ||
178 | struct mtd_partition *partitions, unsigned int nr_partitions, | ||
179 | unsigned int width); | ||
180 | |||
181 | #endif /* __MTD_FSMC_H */ | ||
diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h index 64ee53ce95a9..02cd5f9b79b8 100644 --- a/include/linux/mtd/inftl.h +++ b/include/linux/mtd/inftl.h | |||
@@ -37,14 +37,14 @@ struct INFTLrecord { | |||
37 | __u16 firstEUN; | 37 | __u16 firstEUN; |
38 | __u16 lastEUN; | 38 | __u16 lastEUN; |
39 | __u16 numfreeEUNs; | 39 | __u16 numfreeEUNs; |
40 | __u16 LastFreeEUN; /* To speed up finding a free EUN */ | 40 | __u16 LastFreeEUN; /* To speed up finding a free EUN */ |
41 | int head,sect,cyl; | 41 | int head,sect,cyl; |
42 | __u16 *PUtable; /* Physical Unit Table */ | 42 | __u16 *PUtable; /* Physical Unit Table */ |
43 | __u16 *VUtable; /* Virtual Unit Table */ | 43 | __u16 *VUtable; /* Virtual Unit Table */ |
44 | unsigned int nb_blocks; /* number of physical blocks */ | 44 | unsigned int nb_blocks; /* number of physical blocks */ |
45 | unsigned int nb_boot_blocks; /* number of blocks used by the bios */ | 45 | unsigned int nb_boot_blocks; /* number of blocks used by the bios */ |
46 | struct erase_info instr; | 46 | struct erase_info instr; |
47 | struct nand_ecclayout oobinfo; | 47 | struct nand_ecclayout oobinfo; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | int INFTL_mount(struct INFTLrecord *s); | 50 | int INFTL_mount(struct INFTLrecord *s); |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 8485e42a9b09..fe8d77ebec13 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -110,6 +110,21 @@ struct mtd_oob_ops { | |||
110 | uint8_t *oobbuf; | 110 | uint8_t *oobbuf; |
111 | }; | 111 | }; |
112 | 112 | ||
113 | #define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 | ||
114 | #define MTD_MAX_ECCPOS_ENTRIES_LARGE 448 | ||
115 | /* | ||
116 | * Internal ECC layout control structure. For historical reasons, there is a | ||
117 | * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained | ||
118 | * for export to user-space via the ECCGETLAYOUT ioctl. | ||
119 | * nand_ecclayout should be expandable in the future simply by the above macros. | ||
120 | */ | ||
121 | struct nand_ecclayout { | ||
122 | __u32 eccbytes; | ||
123 | __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; | ||
124 | __u32 oobavail; | ||
125 | struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; | ||
126 | }; | ||
127 | |||
113 | struct mtd_info { | 128 | struct mtd_info { |
114 | u_char type; | 129 | u_char type; |
115 | uint32_t flags; | 130 | uint32_t flags; |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 102e12c58cb3..63e17d01fde9 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -27,15 +27,17 @@ | |||
27 | struct mtd_info; | 27 | struct mtd_info; |
28 | struct nand_flash_dev; | 28 | struct nand_flash_dev; |
29 | /* Scan and identify a NAND device */ | 29 | /* Scan and identify a NAND device */ |
30 | extern int nand_scan (struct mtd_info *mtd, int max_chips); | 30 | extern int nand_scan(struct mtd_info *mtd, int max_chips); |
31 | /* Separate phases of nand_scan(), allowing board driver to intervene | 31 | /* |
32 | * and override command or ECC setup according to flash type */ | 32 | * Separate phases of nand_scan(), allowing board driver to intervene |
33 | * and override command or ECC setup according to flash type. | ||
34 | */ | ||
33 | extern int nand_scan_ident(struct mtd_info *mtd, int max_chips, | 35 | extern int nand_scan_ident(struct mtd_info *mtd, int max_chips, |
34 | struct nand_flash_dev *table); | 36 | struct nand_flash_dev *table); |
35 | extern int nand_scan_tail(struct mtd_info *mtd); | 37 | extern int nand_scan_tail(struct mtd_info *mtd); |
36 | 38 | ||
37 | /* Free resources held by the NAND device */ | 39 | /* Free resources held by the NAND device */ |
38 | extern void nand_release (struct mtd_info *mtd); | 40 | extern void nand_release(struct mtd_info *mtd); |
39 | 41 | ||
40 | /* Internal helper for board drivers which need to override command function */ | 42 | /* Internal helper for board drivers which need to override command function */ |
41 | extern void nand_wait_ready(struct mtd_info *mtd); | 43 | extern void nand_wait_ready(struct mtd_info *mtd); |
@@ -49,12 +51,13 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |||
49 | /* The maximum number of NAND chips in an array */ | 51 | /* The maximum number of NAND chips in an array */ |
50 | #define NAND_MAX_CHIPS 8 | 52 | #define NAND_MAX_CHIPS 8 |
51 | 53 | ||
52 | /* This constant declares the max. oobsize / page, which | 54 | /* |
55 | * This constant declares the max. oobsize / page, which | ||
53 | * is supported now. If you add a chip with bigger oobsize/page | 56 | * is supported now. If you add a chip with bigger oobsize/page |
54 | * adjust this accordingly. | 57 | * adjust this accordingly. |
55 | */ | 58 | */ |
56 | #define NAND_MAX_OOBSIZE 256 | 59 | #define NAND_MAX_OOBSIZE 576 |
57 | #define NAND_MAX_PAGESIZE 4096 | 60 | #define NAND_MAX_PAGESIZE 8192 |
58 | 61 | ||
59 | /* | 62 | /* |
60 | * Constants for hardware specific CLE/ALE/NCE function | 63 | * Constants for hardware specific CLE/ALE/NCE function |
@@ -88,6 +91,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |||
88 | #define NAND_CMD_RNDIN 0x85 | 91 | #define NAND_CMD_RNDIN 0x85 |
89 | #define NAND_CMD_READID 0x90 | 92 | #define NAND_CMD_READID 0x90 |
90 | #define NAND_CMD_ERASE2 0xd0 | 93 | #define NAND_CMD_ERASE2 0xd0 |
94 | #define NAND_CMD_PARAM 0xec | ||
91 | #define NAND_CMD_RESET 0xff | 95 | #define NAND_CMD_RESET 0xff |
92 | 96 | ||
93 | #define NAND_CMD_LOCK 0x2a | 97 | #define NAND_CMD_LOCK 0x2a |
@@ -152,9 +156,10 @@ typedef enum { | |||
152 | #define NAND_GET_DEVICE 0x80 | 156 | #define NAND_GET_DEVICE 0x80 |
153 | 157 | ||
154 | 158 | ||
155 | /* Option constants for bizarre disfunctionality and real | 159 | /* |
156 | * features | 160 | * Option constants for bizarre disfunctionality and real |
157 | */ | 161 | * features. |
162 | */ | ||
158 | /* Chip can not auto increment pages */ | 163 | /* Chip can not auto increment pages */ |
159 | #define NAND_NO_AUTOINCR 0x00000001 | 164 | #define NAND_NO_AUTOINCR 0x00000001 |
160 | /* Buswitdh is 16 bit */ | 165 | /* Buswitdh is 16 bit */ |
@@ -165,19 +170,27 @@ typedef enum { | |||
165 | #define NAND_CACHEPRG 0x00000008 | 170 | #define NAND_CACHEPRG 0x00000008 |
166 | /* Chip has copy back function */ | 171 | /* Chip has copy back function */ |
167 | #define NAND_COPYBACK 0x00000010 | 172 | #define NAND_COPYBACK 0x00000010 |
168 | /* AND Chip which has 4 banks and a confusing page / block | 173 | /* |
169 | * assignment. See Renesas datasheet for further information */ | 174 | * AND Chip which has 4 banks and a confusing page / block |
175 | * assignment. See Renesas datasheet for further information. | ||
176 | */ | ||
170 | #define NAND_IS_AND 0x00000020 | 177 | #define NAND_IS_AND 0x00000020 |
171 | /* Chip has a array of 4 pages which can be read without | 178 | /* |
172 | * additional ready /busy waits */ | 179 | * Chip has a array of 4 pages which can be read without |
180 | * additional ready /busy waits. | ||
181 | */ | ||
173 | #define NAND_4PAGE_ARRAY 0x00000040 | 182 | #define NAND_4PAGE_ARRAY 0x00000040 |
174 | /* Chip requires that BBT is periodically rewritten to prevent | 183 | /* |
184 | * Chip requires that BBT is periodically rewritten to prevent | ||
175 | * bits from adjacent blocks from 'leaking' in altering data. | 185 | * bits from adjacent blocks from 'leaking' in altering data. |
176 | * This happens with the Renesas AG-AND chips, possibly others. */ | 186 | * This happens with the Renesas AG-AND chips, possibly others. |
187 | */ | ||
177 | #define BBT_AUTO_REFRESH 0x00000080 | 188 | #define BBT_AUTO_REFRESH 0x00000080 |
178 | /* Chip does not require ready check on read. True | 189 | /* |
190 | * Chip does not require ready check on read. True | ||
179 | * for all large page devices, as they do not support | 191 | * for all large page devices, as they do not support |
180 | * autoincrement.*/ | 192 | * autoincrement. |
193 | */ | ||
181 | #define NAND_NO_READRDY 0x00000100 | 194 | #define NAND_NO_READRDY 0x00000100 |
182 | /* Chip does not allow subpage writes */ | 195 | /* Chip does not allow subpage writes */ |
183 | #define NAND_NO_SUBPAGE_WRITE 0x00000200 | 196 | #define NAND_NO_SUBPAGE_WRITE 0x00000200 |
@@ -205,16 +218,27 @@ typedef enum { | |||
205 | #define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) | 218 | #define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) |
206 | 219 | ||
207 | /* Non chip related options */ | 220 | /* Non chip related options */ |
208 | /* Use a flash based bad block table. This option is passed to the | 221 | /* |
209 | * default bad block table function. */ | 222 | * Use a flash based bad block table. OOB identifier is saved in OOB area. |
223 | * This option is passed to the default bad block table function. | ||
224 | */ | ||
210 | #define NAND_USE_FLASH_BBT 0x00010000 | 225 | #define NAND_USE_FLASH_BBT 0x00010000 |
211 | /* This option skips the bbt scan during initialization. */ | 226 | /* This option skips the bbt scan during initialization. */ |
212 | #define NAND_SKIP_BBTSCAN 0x00020000 | 227 | #define NAND_SKIP_BBTSCAN 0x00020000 |
213 | /* This option is defined if the board driver allocates its own buffers | 228 | /* |
214 | (e.g. because it needs them DMA-coherent */ | 229 | * This option is defined if the board driver allocates its own buffers |
230 | * (e.g. because it needs them DMA-coherent). | ||
231 | */ | ||
215 | #define NAND_OWN_BUFFERS 0x00040000 | 232 | #define NAND_OWN_BUFFERS 0x00040000 |
216 | /* Chip may not exist, so silence any errors in scan */ | 233 | /* Chip may not exist, so silence any errors in scan */ |
217 | #define NAND_SCAN_SILENT_NODEV 0x00080000 | 234 | #define NAND_SCAN_SILENT_NODEV 0x00080000 |
235 | /* | ||
236 | * If passed additionally to NAND_USE_FLASH_BBT then BBT code will not touch | ||
237 | * the OOB area. | ||
238 | */ | ||
239 | #define NAND_USE_FLASH_BBT_NO_OOB 0x00100000 | ||
240 | /* Create an empty BBT with no vendor information if the BBT is available */ | ||
241 | #define NAND_CREATE_EMPTY_BBT 0x00200000 | ||
218 | 242 | ||
219 | /* Options set by nand scan */ | 243 | /* Options set by nand scan */ |
220 | /* Nand scan has allocated controller struct */ | 244 | /* Nand scan has allocated controller struct */ |
@@ -227,15 +251,80 @@ typedef enum { | |||
227 | /* Keep gcc happy */ | 251 | /* Keep gcc happy */ |
228 | struct nand_chip; | 252 | struct nand_chip; |
229 | 253 | ||
254 | struct nand_onfi_params { | ||
255 | /* rev info and features block */ | ||
256 | /* 'O' 'N' 'F' 'I' */ | ||
257 | u8 sig[4]; | ||
258 | __le16 revision; | ||
259 | __le16 features; | ||
260 | __le16 opt_cmd; | ||
261 | u8 reserved[22]; | ||
262 | |||
263 | /* manufacturer information block */ | ||
264 | char manufacturer[12]; | ||
265 | char model[20]; | ||
266 | u8 jedec_id; | ||
267 | __le16 date_code; | ||
268 | u8 reserved2[13]; | ||
269 | |||
270 | /* memory organization block */ | ||
271 | __le32 byte_per_page; | ||
272 | __le16 spare_bytes_per_page; | ||
273 | __le32 data_bytes_per_ppage; | ||
274 | __le16 spare_bytes_per_ppage; | ||
275 | __le32 pages_per_block; | ||
276 | __le32 blocks_per_lun; | ||
277 | u8 lun_count; | ||
278 | u8 addr_cycles; | ||
279 | u8 bits_per_cell; | ||
280 | __le16 bb_per_lun; | ||
281 | __le16 block_endurance; | ||
282 | u8 guaranteed_good_blocks; | ||
283 | __le16 guaranteed_block_endurance; | ||
284 | u8 programs_per_page; | ||
285 | u8 ppage_attr; | ||
286 | u8 ecc_bits; | ||
287 | u8 interleaved_bits; | ||
288 | u8 interleaved_ops; | ||
289 | u8 reserved3[13]; | ||
290 | |||
291 | /* electrical parameter block */ | ||
292 | u8 io_pin_capacitance_max; | ||
293 | __le16 async_timing_mode; | ||
294 | __le16 program_cache_timing_mode; | ||
295 | __le16 t_prog; | ||
296 | __le16 t_bers; | ||
297 | __le16 t_r; | ||
298 | __le16 t_ccs; | ||
299 | __le16 src_sync_timing_mode; | ||
300 | __le16 src_ssync_features; | ||
301 | __le16 clk_pin_capacitance_typ; | ||
302 | __le16 io_pin_capacitance_typ; | ||
303 | __le16 input_pin_capacitance_typ; | ||
304 | u8 input_pin_capacitance_max; | ||
305 | u8 driver_strenght_support; | ||
306 | __le16 t_int_r; | ||
307 | __le16 t_ald; | ||
308 | u8 reserved4[7]; | ||
309 | |||
310 | /* vendor */ | ||
311 | u8 reserved5[90]; | ||
312 | |||
313 | __le16 crc; | ||
314 | } __attribute__((packed)); | ||
315 | |||
316 | #define ONFI_CRC_BASE 0x4F4E | ||
317 | |||
230 | /** | 318 | /** |
231 | * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices | 319 | * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices |
232 | * @lock: protection lock | 320 | * @lock: protection lock |
233 | * @active: the mtd device which holds the controller currently | 321 | * @active: the mtd device which holds the controller currently |
234 | * @wq: wait queue to sleep on if a NAND operation is in progress | 322 | * @wq: wait queue to sleep on if a NAND operation is in |
235 | * used instead of the per chip wait queue when a hw controller is available | 323 | * progress used instead of the per chip wait queue |
324 | * when a hw controller is available. | ||
236 | */ | 325 | */ |
237 | struct nand_hw_control { | 326 | struct nand_hw_control { |
238 | spinlock_t lock; | 327 | spinlock_t lock; |
239 | struct nand_chip *active; | 328 | struct nand_chip *active; |
240 | wait_queue_head_t wq; | 329 | wait_queue_head_t wq; |
241 | }; | 330 | }; |
@@ -256,51 +345,42 @@ struct nand_hw_control { | |||
256 | * @correct: function for ecc correction, matching to ecc generator (sw/hw) | 345 | * @correct: function for ecc correction, matching to ecc generator (sw/hw) |
257 | * @read_page_raw: function to read a raw page without ECC | 346 | * @read_page_raw: function to read a raw page without ECC |
258 | * @write_page_raw: function to write a raw page without ECC | 347 | * @write_page_raw: function to write a raw page without ECC |
259 | * @read_page: function to read a page according to the ecc generator requirements | 348 | * @read_page: function to read a page according to the ecc generator |
349 | * requirements. | ||
260 | * @read_subpage: function to read parts of the page covered by ECC. | 350 | * @read_subpage: function to read parts of the page covered by ECC. |
261 | * @write_page: function to write a page according to the ecc generator requirements | 351 | * @write_page: function to write a page according to the ecc generator |
352 | * requirements. | ||
262 | * @read_oob: function to read chip OOB data | 353 | * @read_oob: function to read chip OOB data |
263 | * @write_oob: function to write chip OOB data | 354 | * @write_oob: function to write chip OOB data |
264 | */ | 355 | */ |
265 | struct nand_ecc_ctrl { | 356 | struct nand_ecc_ctrl { |
266 | nand_ecc_modes_t mode; | 357 | nand_ecc_modes_t mode; |
267 | int steps; | 358 | int steps; |
268 | int size; | 359 | int size; |
269 | int bytes; | 360 | int bytes; |
270 | int total; | 361 | int total; |
271 | int prepad; | 362 | int prepad; |
272 | int postpad; | 363 | int postpad; |
273 | struct nand_ecclayout *layout; | 364 | struct nand_ecclayout *layout; |
274 | void (*hwctl)(struct mtd_info *mtd, int mode); | 365 | void (*hwctl)(struct mtd_info *mtd, int mode); |
275 | int (*calculate)(struct mtd_info *mtd, | 366 | int (*calculate)(struct mtd_info *mtd, const uint8_t *dat, |
276 | const uint8_t *dat, | 367 | uint8_t *ecc_code); |
277 | uint8_t *ecc_code); | 368 | int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, |
278 | int (*correct)(struct mtd_info *mtd, uint8_t *dat, | 369 | uint8_t *calc_ecc); |
279 | uint8_t *read_ecc, | 370 | int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, |
280 | uint8_t *calc_ecc); | 371 | uint8_t *buf, int page); |
281 | int (*read_page_raw)(struct mtd_info *mtd, | 372 | void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, |
282 | struct nand_chip *chip, | 373 | const uint8_t *buf); |
283 | uint8_t *buf, int page); | 374 | int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, |
284 | void (*write_page_raw)(struct mtd_info *mtd, | 375 | uint8_t *buf, int page); |
285 | struct nand_chip *chip, | 376 | int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, |
286 | const uint8_t *buf); | 377 | uint32_t offs, uint32_t len, uint8_t *buf); |
287 | int (*read_page)(struct mtd_info *mtd, | 378 | void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, |
288 | struct nand_chip *chip, | 379 | const uint8_t *buf); |
289 | uint8_t *buf, int page); | 380 | int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page, |
290 | int (*read_subpage)(struct mtd_info *mtd, | 381 | int sndcmd); |
291 | struct nand_chip *chip, | 382 | int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip, |
292 | uint32_t offs, uint32_t len, | 383 | int page); |
293 | uint8_t *buf); | ||
294 | void (*write_page)(struct mtd_info *mtd, | ||
295 | struct nand_chip *chip, | ||
296 | const uint8_t *buf); | ||
297 | int (*read_oob)(struct mtd_info *mtd, | ||
298 | struct nand_chip *chip, | ||
299 | int page, | ||
300 | int sndcmd); | ||
301 | int (*write_oob)(struct mtd_info *mtd, | ||
302 | struct nand_chip *chip, | ||
303 | int page); | ||
304 | }; | 384 | }; |
305 | 385 | ||
306 | /** | 386 | /** |
@@ -320,102 +400,132 @@ struct nand_buffers { | |||
320 | 400 | ||
321 | /** | 401 | /** |
322 | * struct nand_chip - NAND Private Flash Chip Data | 402 | * struct nand_chip - NAND Private Flash Chip Data |
323 | * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device | 403 | * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the |
324 | * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device | 404 | * flash device |
405 | * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the | ||
406 | * flash device. | ||
325 | * @read_byte: [REPLACEABLE] read one byte from the chip | 407 | * @read_byte: [REPLACEABLE] read one byte from the chip |
326 | * @read_word: [REPLACEABLE] read one word from the chip | 408 | * @read_word: [REPLACEABLE] read one word from the chip |
327 | * @write_buf: [REPLACEABLE] write data from the buffer to the chip | 409 | * @write_buf: [REPLACEABLE] write data from the buffer to the chip |
328 | * @read_buf: [REPLACEABLE] read data from the chip into the buffer | 410 | * @read_buf: [REPLACEABLE] read data from the chip into the buffer |
329 | * @verify_buf: [REPLACEABLE] verify buffer contents against the chip data | 411 | * @verify_buf: [REPLACEABLE] verify buffer contents against the chip |
412 | * data. | ||
330 | * @select_chip: [REPLACEABLE] select chip nr | 413 | * @select_chip: [REPLACEABLE] select chip nr |
331 | * @block_bad: [REPLACEABLE] check, if the block is bad | 414 | * @block_bad: [REPLACEABLE] check, if the block is bad |
332 | * @block_markbad: [REPLACEABLE] mark the block bad | 415 | * @block_markbad: [REPLACEABLE] mark the block bad |
333 | * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling | 416 | * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling |
334 | * ALE/CLE/nCE. Also used to write command and address | 417 | * ALE/CLE/nCE. Also used to write command and address |
335 | * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line | 418 | * @init_size: [BOARDSPECIFIC] hardwarespecific funtion for setting |
336 | * If set to NULL no access to ready/busy is available and the ready/busy information | 419 | * mtd->oobsize, mtd->writesize and so on. |
337 | * is read from the chip status register | 420 | * @id_data contains the 8 bytes values of NAND_CMD_READID. |
338 | * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip | 421 | * Return with the bus width. |
339 | * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready | 422 | * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing |
423 | * device ready/busy line. If set to NULL no access to | ||
424 | * ready/busy is available and the ready/busy information | ||
425 | * is read from the chip status register. | ||
426 | * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing | ||
427 | * commands to the chip. | ||
428 | * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on | ||
429 | * ready. | ||
340 | * @ecc: [BOARDSPECIFIC] ecc control ctructure | 430 | * @ecc: [BOARDSPECIFIC] ecc control ctructure |
341 | * @buffers: buffer structure for read/write | 431 | * @buffers: buffer structure for read/write |
342 | * @hwcontrol: platform-specific hardware control structure | 432 | * @hwcontrol: platform-specific hardware control structure |
343 | * @ops: oob operation operands | 433 | * @ops: oob operation operands |
344 | * @erase_cmd: [INTERN] erase command write function, selectable due to AND support | 434 | * @erase_cmd: [INTERN] erase command write function, selectable due |
435 | * to AND support. | ||
345 | * @scan_bbt: [REPLACEABLE] function to scan bad block table | 436 | * @scan_bbt: [REPLACEABLE] function to scan bad block table |
346 | * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) | 437 | * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering |
438 | * data from array to read regs (tR). | ||
347 | * @state: [INTERN] the current state of the NAND device | 439 | * @state: [INTERN] the current state of the NAND device |
348 | * @oob_poi: poison value buffer | 440 | * @oob_poi: poison value buffer |
349 | * @page_shift: [INTERN] number of address bits in a page (column address bits) | 441 | * @page_shift: [INTERN] number of address bits in a page (column |
442 | * address bits). | ||
350 | * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock | 443 | * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock |
351 | * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry | 444 | * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry |
352 | * @chip_shift: [INTERN] number of address bits in one chip | 445 | * @chip_shift: [INTERN] number of address bits in one chip |
353 | * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about | 446 | * @options: [BOARDSPECIFIC] various chip options. They can partly |
354 | * special functionality. See the defines for further explanation | 447 | * be set to inform nand_scan about special functionality. |
355 | * @badblockpos: [INTERN] position of the bad block marker in the oob area | 448 | * See the defines for further explanation. |
449 | * @badblockpos: [INTERN] position of the bad block marker in the oob | ||
450 | * area. | ||
356 | * @cellinfo: [INTERN] MLC/multichip data from chip ident | 451 | * @cellinfo: [INTERN] MLC/multichip data from chip ident |
357 | * @numchips: [INTERN] number of physical chips | 452 | * @numchips: [INTERN] number of physical chips |
358 | * @chipsize: [INTERN] the size of one chip for multichip arrays | 453 | * @chipsize: [INTERN] the size of one chip for multichip arrays |
359 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 | 454 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 |
360 | * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf | 455 | * @pagebuf: [INTERN] holds the pagenumber which is currently in |
456 | * data_buf. | ||
361 | * @subpagesize: [INTERN] holds the subpagesize | 457 | * @subpagesize: [INTERN] holds the subpagesize |
458 | * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded), | ||
459 | * non 0 if ONFI supported. | ||
460 | * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is | ||
461 | * supported, 0 otherwise. | ||
362 | * @ecclayout: [REPLACEABLE] the default ecc placement scheme | 462 | * @ecclayout: [REPLACEABLE] the default ecc placement scheme |
363 | * @bbt: [INTERN] bad block table pointer | 463 | * @bbt: [INTERN] bad block table pointer |
364 | * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup | 464 | * @bbt_td: [REPLACEABLE] bad block table descriptor for flash |
465 | * lookup. | ||
365 | * @bbt_md: [REPLACEABLE] bad block table mirror descriptor | 466 | * @bbt_md: [REPLACEABLE] bad block table mirror descriptor |
366 | * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan | 467 | * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial |
367 | * @controller: [REPLACEABLE] a pointer to a hardware controller structure | 468 | * bad block scan. |
368 | * which is shared among multiple independend devices | 469 | * @controller: [REPLACEABLE] a pointer to a hardware controller |
470 | * structure which is shared among multiple independend | ||
471 | * devices. | ||
369 | * @priv: [OPTIONAL] pointer to private chip date | 472 | * @priv: [OPTIONAL] pointer to private chip date |
370 | * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks | 473 | * @errstat: [OPTIONAL] hardware specific function to perform |
371 | * (determine if errors are correctable) | 474 | * additional error status checks (determine if errors are |
475 | * correctable). | ||
372 | * @write_page: [REPLACEABLE] High-level page write function | 476 | * @write_page: [REPLACEABLE] High-level page write function |
373 | */ | 477 | */ |
374 | 478 | ||
375 | struct nand_chip { | 479 | struct nand_chip { |
376 | void __iomem *IO_ADDR_R; | 480 | void __iomem *IO_ADDR_R; |
377 | void __iomem *IO_ADDR_W; | 481 | void __iomem *IO_ADDR_W; |
378 | 482 | ||
379 | uint8_t (*read_byte)(struct mtd_info *mtd); | 483 | uint8_t (*read_byte)(struct mtd_info *mtd); |
380 | u16 (*read_word)(struct mtd_info *mtd); | 484 | u16 (*read_word)(struct mtd_info *mtd); |
381 | void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); | 485 | void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); |
382 | void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); | 486 | void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); |
383 | int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); | 487 | int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); |
384 | void (*select_chip)(struct mtd_info *mtd, int chip); | 488 | void (*select_chip)(struct mtd_info *mtd, int chip); |
385 | int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); | 489 | int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); |
386 | int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); | 490 | int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); |
387 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, | 491 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); |
388 | unsigned int ctrl); | 492 | int (*init_size)(struct mtd_info *mtd, struct nand_chip *this, |
389 | int (*dev_ready)(struct mtd_info *mtd); | 493 | u8 *id_data); |
390 | void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); | 494 | int (*dev_ready)(struct mtd_info *mtd); |
391 | int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); | 495 | void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, |
392 | void (*erase_cmd)(struct mtd_info *mtd, int page); | 496 | int page_addr); |
393 | int (*scan_bbt)(struct mtd_info *mtd); | 497 | int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); |
394 | int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); | 498 | void (*erase_cmd)(struct mtd_info *mtd, int page); |
395 | int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, | 499 | int (*scan_bbt)(struct mtd_info *mtd); |
396 | const uint8_t *buf, int page, int cached, int raw); | 500 | int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, |
397 | 501 | int status, int page); | |
398 | int chip_delay; | 502 | int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, |
399 | unsigned int options; | 503 | const uint8_t *buf, int page, int cached, int raw); |
400 | 504 | ||
401 | int page_shift; | 505 | int chip_delay; |
402 | int phys_erase_shift; | 506 | unsigned int options; |
403 | int bbt_erase_shift; | 507 | |
404 | int chip_shift; | 508 | int page_shift; |
405 | int numchips; | 509 | int phys_erase_shift; |
406 | uint64_t chipsize; | 510 | int bbt_erase_shift; |
407 | int pagemask; | 511 | int chip_shift; |
408 | int pagebuf; | 512 | int numchips; |
409 | int subpagesize; | 513 | uint64_t chipsize; |
410 | uint8_t cellinfo; | 514 | int pagemask; |
411 | int badblockpos; | 515 | int pagebuf; |
412 | int badblockbits; | 516 | int subpagesize; |
413 | 517 | uint8_t cellinfo; | |
414 | flstate_t state; | 518 | int badblockpos; |
415 | 519 | int badblockbits; | |
416 | uint8_t *oob_poi; | 520 | |
417 | struct nand_hw_control *controller; | 521 | int onfi_version; |
418 | struct nand_ecclayout *ecclayout; | 522 | struct nand_onfi_params onfi_params; |
523 | |||
524 | flstate_t state; | ||
525 | |||
526 | uint8_t *oob_poi; | ||
527 | struct nand_hw_control *controller; | ||
528 | struct nand_ecclayout *ecclayout; | ||
419 | 529 | ||
420 | struct nand_ecc_ctrl ecc; | 530 | struct nand_ecc_ctrl ecc; |
421 | struct nand_buffers *buffers; | 531 | struct nand_buffers *buffers; |
@@ -423,13 +533,13 @@ struct nand_chip { | |||
423 | 533 | ||
424 | struct mtd_oob_ops ops; | 534 | struct mtd_oob_ops ops; |
425 | 535 | ||
426 | uint8_t *bbt; | 536 | uint8_t *bbt; |
427 | struct nand_bbt_descr *bbt_td; | 537 | struct nand_bbt_descr *bbt_td; |
428 | struct nand_bbt_descr *bbt_md; | 538 | struct nand_bbt_descr *bbt_md; |
429 | 539 | ||
430 | struct nand_bbt_descr *badblock_pattern; | 540 | struct nand_bbt_descr *badblock_pattern; |
431 | 541 | ||
432 | void *priv; | 542 | void *priv; |
433 | }; | 543 | }; |
434 | 544 | ||
435 | /* | 545 | /* |
@@ -473,7 +583,7 @@ struct nand_flash_dev { | |||
473 | */ | 583 | */ |
474 | struct nand_manufacturers { | 584 | struct nand_manufacturers { |
475 | int id; | 585 | int id; |
476 | char * name; | 586 | char *name; |
477 | }; | 587 | }; |
478 | 588 | ||
479 | extern struct nand_flash_dev nand_flash_ids[]; | 589 | extern struct nand_flash_dev nand_flash_ids[]; |
@@ -486,7 +596,7 @@ extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); | |||
486 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | 596 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, |
487 | int allowbbt); | 597 | int allowbbt); |
488 | extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | 598 | extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, |
489 | size_t * retlen, uint8_t * buf); | 599 | size_t *retlen, uint8_t *buf); |
490 | 600 | ||
491 | /** | 601 | /** |
492 | * struct platform_nand_chip - chip level device structure | 602 | * struct platform_nand_chip - chip level device structure |
@@ -502,17 +612,16 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
502 | * @priv: hardware controller specific settings | 612 | * @priv: hardware controller specific settings |
503 | */ | 613 | */ |
504 | struct platform_nand_chip { | 614 | struct platform_nand_chip { |
505 | int nr_chips; | 615 | int nr_chips; |
506 | int chip_offset; | 616 | int chip_offset; |
507 | int nr_partitions; | 617 | int nr_partitions; |
508 | struct mtd_partition *partitions; | 618 | struct mtd_partition *partitions; |
509 | struct nand_ecclayout *ecclayout; | 619 | struct nand_ecclayout *ecclayout; |
510 | int chip_delay; | 620 | int chip_delay; |
511 | unsigned int options; | 621 | unsigned int options; |
512 | const char **part_probe_types; | 622 | const char **part_probe_types; |
513 | void (*set_parts)(uint64_t size, | 623 | void (*set_parts)(uint64_t size, struct platform_nand_chip *chip); |
514 | struct platform_nand_chip *chip); | 624 | void *priv; |
515 | void *priv; | ||
516 | }; | 625 | }; |
517 | 626 | ||
518 | /* Keep gcc happy */ | 627 | /* Keep gcc happy */ |
@@ -534,18 +643,15 @@ struct platform_device; | |||
534 | * All fields are optional and depend on the hardware driver requirements | 643 | * All fields are optional and depend on the hardware driver requirements |
535 | */ | 644 | */ |
536 | struct platform_nand_ctrl { | 645 | struct platform_nand_ctrl { |
537 | int (*probe)(struct platform_device *pdev); | 646 | int (*probe)(struct platform_device *pdev); |
538 | void (*remove)(struct platform_device *pdev); | 647 | void (*remove)(struct platform_device *pdev); |
539 | void (*hwcontrol)(struct mtd_info *mtd, int cmd); | 648 | void (*hwcontrol)(struct mtd_info *mtd, int cmd); |
540 | int (*dev_ready)(struct mtd_info *mtd); | 649 | int (*dev_ready)(struct mtd_info *mtd); |
541 | void (*select_chip)(struct mtd_info *mtd, int chip); | 650 | void (*select_chip)(struct mtd_info *mtd, int chip); |
542 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, | 651 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); |
543 | unsigned int ctrl); | 652 | void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); |
544 | void (*write_buf)(struct mtd_info *mtd, | 653 | void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); |
545 | const uint8_t *buf, int len); | 654 | void *priv; |
546 | void (*read_buf)(struct mtd_info *mtd, | ||
547 | uint8_t *buf, int len); | ||
548 | void *priv; | ||
549 | }; | 655 | }; |
550 | 656 | ||
551 | /** | 657 | /** |
@@ -554,8 +660,8 @@ struct platform_nand_ctrl { | |||
554 | * @ctrl: controller level device structure | 660 | * @ctrl: controller level device structure |
555 | */ | 661 | */ |
556 | struct platform_nand_data { | 662 | struct platform_nand_data { |
557 | struct platform_nand_chip chip; | 663 | struct platform_nand_chip chip; |
558 | struct platform_nand_ctrl ctrl; | 664 | struct platform_nand_ctrl ctrl; |
559 | }; | 665 | }; |
560 | 666 | ||
561 | /* Some helpers to access the data structures */ | 667 | /* Some helpers to access the data structures */ |
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 274b6196091d..2b54316591d2 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h | |||
@@ -39,7 +39,7 @@ struct mtd_partition { | |||
39 | uint64_t size; /* partition size */ | 39 | uint64_t size; /* partition size */ |
40 | uint64_t offset; /* offset within the master MTD space */ | 40 | uint64_t offset; /* offset within the master MTD space */ |
41 | uint32_t mask_flags; /* master MTD flags to mask out for this partition */ | 41 | uint32_t mask_flags; /* master MTD flags to mask out for this partition */ |
42 | struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ | 42 | struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only) */ |
43 | }; | 43 | }; |
44 | 44 | ||
45 | #define MTDPART_OFS_NXTBLK (-2) | 45 | #define MTDPART_OFS_NXTBLK (-2) |
@@ -89,4 +89,9 @@ static inline int mtd_has_cmdlinepart(void) { return 1; } | |||
89 | static inline int mtd_has_cmdlinepart(void) { return 0; } | 89 | static inline int mtd_has_cmdlinepart(void) { return 0; } |
90 | #endif | 90 | #endif |
91 | 91 | ||
92 | int mtd_is_master(struct mtd_info *mtd); | ||
93 | int mtd_add_partition(struct mtd_info *master, char *name, | ||
94 | long long offset, long long length); | ||
95 | int mtd_del_partition(struct mtd_info *master, int partno); | ||
96 | |||
92 | #endif | 97 | #endif |
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 4debb4514634..2f7d45bcbd24 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h | |||
@@ -52,6 +52,7 @@ struct mtd_oob_buf64 { | |||
52 | #define MTD_NANDFLASH 4 | 52 | #define MTD_NANDFLASH 4 |
53 | #define MTD_DATAFLASH 6 | 53 | #define MTD_DATAFLASH 6 |
54 | #define MTD_UBIVOLUME 7 | 54 | #define MTD_UBIVOLUME 7 |
55 | #define MTD_MLCNANDFLASH 8 | ||
55 | 56 | ||
56 | #define MTD_WRITEABLE 0x400 /* Device is writeable */ | 57 | #define MTD_WRITEABLE 0x400 /* Device is writeable */ |
57 | #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ | 58 | #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ |
@@ -119,7 +120,7 @@ struct otp_info { | |||
119 | #define OTPGETREGIONCOUNT _IOW('M', 14, int) | 120 | #define OTPGETREGIONCOUNT _IOW('M', 14, int) |
120 | #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) | 121 | #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) |
121 | #define OTPLOCK _IOR('M', 16, struct otp_info) | 122 | #define OTPLOCK _IOR('M', 16, struct otp_info) |
122 | #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) | 123 | #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout_user) |
123 | #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) | 124 | #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) |
124 | #define MTDFILEMODE _IO('M', 19) | 125 | #define MTDFILEMODE _IO('M', 19) |
125 | #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) | 126 | #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) |
@@ -144,13 +145,18 @@ struct nand_oobfree { | |||
144 | }; | 145 | }; |
145 | 146 | ||
146 | #define MTD_MAX_OOBFREE_ENTRIES 8 | 147 | #define MTD_MAX_OOBFREE_ENTRIES 8 |
148 | #define MTD_MAX_ECCPOS_ENTRIES 64 | ||
147 | /* | 149 | /* |
148 | * ECC layout control structure. Exported to userspace for | 150 | * OBSOLETE: ECC layout control structure. Exported to user-space via ioctl |
149 | * diagnosis and to allow creation of raw images | 151 | * ECCGETLAYOUT for backwards compatbility and should not be mistaken as a |
152 | * complete set of ECC information. The ioctl truncates the larger internal | ||
153 | * structure to retain binary compatibility with the static declaration of the | ||
154 | * ioctl. Note that the "MTD_MAX_..._ENTRIES" macros represent the max size of | ||
155 | * the user struct, not the MAX size of the internal struct nand_ecclayout. | ||
150 | */ | 156 | */ |
151 | struct nand_ecclayout { | 157 | struct nand_ecclayout_user { |
152 | __u32 eccbytes; | 158 | __u32 eccbytes; |
153 | __u32 eccpos[64]; | 159 | __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES]; |
154 | __u32 oobavail; | 160 | __u32 oobavail; |
155 | struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; | 161 | struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; |
156 | }; | 162 | }; |
diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h index aa3c2f86a913..83327c808c86 100644 --- a/include/mtd/mtd-user.h +++ b/include/mtd/mtd-user.h | |||
@@ -29,6 +29,6 @@ typedef struct mtd_info_user mtd_info_t; | |||
29 | typedef struct erase_info_user erase_info_t; | 29 | typedef struct erase_info_user erase_info_t; |
30 | typedef struct region_info_user region_info_t; | 30 | typedef struct region_info_user region_info_t; |
31 | typedef struct nand_oobinfo nand_oobinfo_t; | 31 | typedef struct nand_oobinfo nand_oobinfo_t; |
32 | typedef struct nand_ecclayout nand_ecclayout_t; | 32 | typedef struct nand_ecclayout_user nand_ecclayout_t; |
33 | 33 | ||
34 | #endif /* __MTD_USER_H__ */ | 34 | #endif /* __MTD_USER_H__ */ |