Commit faca8ff55f4a2cf45fb906cc37f44601149fc00e
Exists in
master
and in
50 other branches
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
Showing 41 changed files Side-by-side Diff
- arch/arm/cpu/armv7/am33xx/Makefile
- arch/arm/cpu/armv7/am33xx/elm.c
- arch/arm/cpu/armv7/am33xx/mem.c
- arch/arm/include/asm/arch-am33xx/elm.h
- arch/arm/include/asm/arch-am33xx/mem.h
- arch/arm/include/asm/omap_elm.h
- arch/arm/include/asm/omap_gpmc.h
- arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
- arch/powerpc/include/asm/fsl_ifc.h
- board/atmel/sama5d3xek/sama5d3xek.c
- board/ti/am335x/board.c
- doc/README.nand
- doc/README.omap3
- drivers/mtd/nand/Makefile
- drivers/mtd/nand/atmel_nand.c
- drivers/mtd/nand/fsl_ifc_nand.c
- drivers/mtd/nand/fsl_ifc_spl.c
- drivers/mtd/nand/omap_elm.c
- drivers/mtd/nand/omap_gpmc.c
- drivers/mtd/onenand/onenand_base.c
- include/configs/ASH405.h
- include/configs/C29XPCIE.h
- include/configs/MPC8572DS.h
- include/configs/T4240QDS.h
- include/configs/alpr.h
- include/configs/am335x_evm.h
- include/configs/am335x_igep0033.h
- include/configs/am3517_crane.h
- include/configs/am3517_evm.h
- include/configs/devkit8000.h
- include/configs/mcx.h
- include/configs/omap3_beagle.h
- include/configs/omap3_evm.h
- include/configs/omap3_evm_quick_nand.h
- include/configs/omap3_igep00x0.h
- include/configs/omap3_overo.h
- include/configs/siemens-am33x-common.h
- include/configs/tam3517-common.h
- include/configs/tricorder.h
- include/linux/mtd/mtd.h
- include/mtd/mtd-abi.h
arch/arm/cpu/armv7/am33xx/Makefile
arch/arm/cpu/armv7/am33xx/elm.c
1 | -/* | |
2 | - * (C) Copyright 2010-2011 Texas Instruments, <www.ti.com> | |
3 | - * Mansoor Ahamed <mansoor.ahamed@ti.com> | |
4 | - * | |
5 | - * BCH Error Location Module (ELM) support. | |
6 | - * | |
7 | - * NOTE: | |
8 | - * 1. Supports only continuous mode. Dont see need for page mode in uboot | |
9 | - * 2. Supports only syndrome polynomial 0. i.e. poly local variable is | |
10 | - * always set to ELM_DEFAULT_POLY. Dont see need for other polynomial | |
11 | - * sets in uboot | |
12 | - * | |
13 | - * SPDX-License-Identifier: GPL-2.0+ | |
14 | - */ | |
15 | - | |
16 | -#include <common.h> | |
17 | -#include <asm/io.h> | |
18 | -#include <asm/errno.h> | |
19 | -#include <asm/arch/cpu.h> | |
20 | -#include <asm/omap_gpmc.h> | |
21 | -#include <asm/arch/elm.h> | |
22 | - | |
23 | -#define ELM_DEFAULT_POLY (0) | |
24 | - | |
25 | -struct elm *elm_cfg; | |
26 | - | |
27 | -/** | |
28 | - * elm_load_syndromes - Load BCH syndromes based on nibble selection | |
29 | - * @syndrome: BCH syndrome | |
30 | - * @nibbles: | |
31 | - * @poly: Syndrome Polynomial set to use | |
32 | - * | |
33 | - * Load BCH syndromes based on nibble selection | |
34 | - */ | |
35 | -static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly) | |
36 | -{ | |
37 | - u32 *ptr; | |
38 | - u32 val; | |
39 | - | |
40 | - /* reg 0 */ | |
41 | - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[0]; | |
42 | - val = syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) | | |
43 | - (syndrome[3] << 24); | |
44 | - writel(val, ptr); | |
45 | - /* reg 1 */ | |
46 | - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[1]; | |
47 | - val = syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) | | |
48 | - (syndrome[7] << 24); | |
49 | - writel(val, ptr); | |
50 | - | |
51 | - /* BCH 8-bit with 26 nibbles (4*8=32) */ | |
52 | - if (nibbles > 13) { | |
53 | - /* reg 2 */ | |
54 | - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[2]; | |
55 | - val = syndrome[8] | (syndrome[9] << 8) | (syndrome[10] << 16) | | |
56 | - (syndrome[11] << 24); | |
57 | - writel(val, ptr); | |
58 | - /* reg 3 */ | |
59 | - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[3]; | |
60 | - val = syndrome[12] | (syndrome[13] << 8) | | |
61 | - (syndrome[14] << 16) | (syndrome[15] << 24); | |
62 | - writel(val, ptr); | |
63 | - } | |
64 | - | |
65 | - /* BCH 16-bit with 52 nibbles (7*8=56) */ | |
66 | - if (nibbles > 26) { | |
67 | - /* reg 4 */ | |
68 | - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[4]; | |
69 | - val = syndrome[16] | (syndrome[17] << 8) | | |
70 | - (syndrome[18] << 16) | (syndrome[19] << 24); | |
71 | - writel(val, ptr); | |
72 | - | |
73 | - /* reg 5 */ | |
74 | - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[5]; | |
75 | - val = syndrome[20] | (syndrome[21] << 8) | | |
76 | - (syndrome[22] << 16) | (syndrome[23] << 24); | |
77 | - writel(val, ptr); | |
78 | - | |
79 | - /* reg 6 */ | |
80 | - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]; | |
81 | - val = syndrome[24] | (syndrome[25] << 8) | | |
82 | - (syndrome[26] << 16) | (syndrome[27] << 24); | |
83 | - writel(val, ptr); | |
84 | - } | |
85 | -} | |
86 | - | |
87 | -/** | |
88 | - * elm_check_errors - Check for BCH errors and return error locations | |
89 | - * @syndrome: BCH syndrome | |
90 | - * @nibbles: | |
91 | - * @error_count: Returns number of errrors in the syndrome | |
92 | - * @error_locations: Returns error locations (in decimal) in this array | |
93 | - * | |
94 | - * Check the provided syndrome for BCH errors and return error count | |
95 | - * and locations in the array passed. Returns -1 if error is not correctable, | |
96 | - * else returns 0 | |
97 | - */ | |
98 | -int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count, | |
99 | - u32 *error_locations) | |
100 | -{ | |
101 | - u8 poly = ELM_DEFAULT_POLY; | |
102 | - s8 i; | |
103 | - u32 location_status; | |
104 | - | |
105 | - elm_load_syndromes(syndrome, nibbles, poly); | |
106 | - | |
107 | - /* start processing */ | |
108 | - writel((readl(&elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]) | |
109 | - | ELM_SYNDROME_FRAGMENT_6_SYNDROME_VALID), | |
110 | - &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]); | |
111 | - | |
112 | - /* wait for processing to complete */ | |
113 | - while ((readl(&elm_cfg->irqstatus) & (0x1 << poly)) != 0x1) | |
114 | - ; | |
115 | - /* clear status */ | |
116 | - writel((readl(&elm_cfg->irqstatus) | (0x1 << poly)), | |
117 | - &elm_cfg->irqstatus); | |
118 | - | |
119 | - /* check if correctable */ | |
120 | - location_status = readl(&elm_cfg->error_location[poly].location_status); | |
121 | - if (!(location_status & ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK)) | |
122 | - return -1; | |
123 | - | |
124 | - /* get error count */ | |
125 | - *error_count = readl(&elm_cfg->error_location[poly].location_status) & | |
126 | - ELM_LOCATION_STATUS_ECC_NB_ERRORS_MASK; | |
127 | - | |
128 | - for (i = 0; i < *error_count; i++) { | |
129 | - error_locations[i] = | |
130 | - readl(&elm_cfg->error_location[poly].error_location_x[i]); | |
131 | - } | |
132 | - | |
133 | - return 0; | |
134 | -} | |
135 | - | |
136 | - | |
137 | -/** | |
138 | - * elm_config - Configure ELM module | |
139 | - * @level: 4 / 8 / 16 bit BCH | |
140 | - * | |
141 | - * Configure ELM module based on BCH level. | |
142 | - * Set mode as continuous mode. | |
143 | - * Currently we are using only syndrome 0 and syndromes 1 to 6 are not used. | |
144 | - * Also, the mode is set only for syndrome 0 | |
145 | - */ | |
146 | -int elm_config(enum bch_level level) | |
147 | -{ | |
148 | - u32 val; | |
149 | - u8 poly = ELM_DEFAULT_POLY; | |
150 | - u32 buffer_size = 0x7FF; | |
151 | - | |
152 | - /* config size and level */ | |
153 | - val = (u32)(level) & ELM_LOCATION_CONFIG_ECC_BCH_LEVEL_MASK; | |
154 | - val |= ((buffer_size << ELM_LOCATION_CONFIG_ECC_SIZE_POS) & | |
155 | - ELM_LOCATION_CONFIG_ECC_SIZE_MASK); | |
156 | - writel(val, &elm_cfg->location_config); | |
157 | - | |
158 | - /* config continous mode */ | |
159 | - /* enable interrupt generation for syndrome polynomial set */ | |
160 | - writel((readl(&elm_cfg->irqenable) | (0x1 << poly)), | |
161 | - &elm_cfg->irqenable); | |
162 | - /* set continuous mode for the syndrome polynomial set */ | |
163 | - writel((readl(&elm_cfg->page_ctrl) & ~(0x1 << poly)), | |
164 | - &elm_cfg->page_ctrl); | |
165 | - | |
166 | - return 0; | |
167 | -} | |
168 | - | |
169 | -/** | |
170 | - * elm_reset - Do a soft reset of ELM | |
171 | - * | |
172 | - * Perform a soft reset of ELM and return after reset is done. | |
173 | - */ | |
174 | -void elm_reset(void) | |
175 | -{ | |
176 | - /* initiate reset */ | |
177 | - writel((readl(&elm_cfg->sysconfig) | ELM_SYSCONFIG_SOFTRESET), | |
178 | - &elm_cfg->sysconfig); | |
179 | - | |
180 | - /* wait for reset complete and normal operation */ | |
181 | - while ((readl(&elm_cfg->sysstatus) & ELM_SYSSTATUS_RESETDONE) != | |
182 | - ELM_SYSSTATUS_RESETDONE) | |
183 | - ; | |
184 | -} | |
185 | - | |
186 | -/** | |
187 | - * elm_init - Initialize ELM module | |
188 | - * | |
189 | - * Initialize ELM support. Currently it does only base address init | |
190 | - * and ELM reset. | |
191 | - */ | |
192 | -void elm_init(void) | |
193 | -{ | |
194 | - elm_cfg = (struct elm *)ELM_BASE; | |
195 | - elm_reset(); | |
196 | -} |
arch/arm/cpu/armv7/am33xx/mem.c
... | ... | @@ -22,18 +22,7 @@ |
22 | 22 | |
23 | 23 | struct gpmc *gpmc_cfg; |
24 | 24 | |
25 | -#if defined(CONFIG_CMD_NAND) | |
26 | -static const u32 gpmc_m_nand[GPMC_MAX_REG] = { | |
27 | - M_NAND_GPMC_CONFIG1, | |
28 | - M_NAND_GPMC_CONFIG2, | |
29 | - M_NAND_GPMC_CONFIG3, | |
30 | - M_NAND_GPMC_CONFIG4, | |
31 | - M_NAND_GPMC_CONFIG5, | |
32 | - M_NAND_GPMC_CONFIG6, 0 | |
33 | -}; | |
34 | -#endif | |
35 | 25 | |
36 | - | |
37 | 26 | void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base, |
38 | 27 | u32 size) |
39 | 28 | { |
40 | 29 | |
... | ... | @@ -61,11 +50,34 @@ |
61 | 50 | { |
62 | 51 | /* putting a blanket check on GPMC based on ZeBu for now */ |
63 | 52 | gpmc_cfg = (struct gpmc *)GPMC_BASE; |
64 | - | |
65 | -#ifdef CONFIG_CMD_NAND | |
66 | - const u32 *gpmc_config = NULL; | |
67 | - u32 base = 0; | |
53 | +#if defined(CONFIG_NOR) | |
54 | +/* configure GPMC for NOR */ | |
55 | + const u32 gpmc_regs[GPMC_MAX_REG] = { STNOR_GPMC_CONFIG1, | |
56 | + STNOR_GPMC_CONFIG2, | |
57 | + STNOR_GPMC_CONFIG3, | |
58 | + STNOR_GPMC_CONFIG4, | |
59 | + STNOR_GPMC_CONFIG5, | |
60 | + STNOR_GPMC_CONFIG6, | |
61 | + STNOR_GPMC_CONFIG7 | |
62 | + }; | |
63 | + u32 size = GPMC_SIZE_16M; | |
64 | + u32 base = CONFIG_SYS_FLASH_BASE; | |
65 | +#elif defined(CONFIG_NAND) | |
66 | +/* configure GPMC for NAND */ | |
67 | + const u32 gpmc_regs[GPMC_MAX_REG] = { M_NAND_GPMC_CONFIG1, | |
68 | + M_NAND_GPMC_CONFIG2, | |
69 | + M_NAND_GPMC_CONFIG3, | |
70 | + M_NAND_GPMC_CONFIG4, | |
71 | + M_NAND_GPMC_CONFIG5, | |
72 | + M_NAND_GPMC_CONFIG6, | |
73 | + 0 | |
74 | + }; | |
75 | + u32 size = GPMC_SIZE_256M; | |
76 | + u32 base = CONFIG_SYS_NAND_BASE; | |
77 | +#else | |
78 | + const u32 gpmc_regs[GPMC_MAX_REG] = { 0, 0, 0, 0, 0, 0, 0 }; | |
68 | 79 | u32 size = 0; |
80 | + u32 base = 0; | |
69 | 81 | #endif |
70 | 82 | /* global settings */ |
71 | 83 | writel(0x00000008, &gpmc_cfg->sysconfig); |
... | ... | @@ -81,13 +93,7 @@ |
81 | 93 | */ |
82 | 94 | writel(0, &gpmc_cfg->cs[0].config7); |
83 | 95 | sdelay(1000); |
84 | - | |
85 | -#ifdef CONFIG_CMD_NAND | |
86 | - gpmc_config = gpmc_m_nand; | |
87 | - | |
88 | - base = PISMO1_NAND_BASE; | |
89 | - size = PISMO1_NAND_SIZE; | |
90 | - enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size); | |
91 | -#endif | |
96 | + /* enable chip-select specific configurations */ | |
97 | + enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size); | |
92 | 98 | } |
arch/arm/include/asm/arch-am33xx/elm.h
1 | -/* | |
2 | - * (C) Copyright 2010-2011 Texas Instruments, <www.ti.com> | |
3 | - * Mansoor Ahamed <mansoor.ahamed@ti.com> | |
4 | - * | |
5 | - * Derived from work done by Rohit Choraria <rohitkc@ti.com> for omap3 | |
6 | - * | |
7 | - * SPDX-License-Identifier: GPL-2.0+ | |
8 | - */ | |
9 | -#ifndef __ASM_ARCH_ELM_H | |
10 | -#define __ASM_ARCH_ELM_H | |
11 | -/* | |
12 | - * ELM Module Registers | |
13 | - */ | |
14 | - | |
15 | -/* ELM registers bit fields */ | |
16 | -#define ELM_SYSCONFIG_SOFTRESET_MASK (0x2) | |
17 | -#define ELM_SYSCONFIG_SOFTRESET (0x2) | |
18 | -#define ELM_SYSSTATUS_RESETDONE_MASK (0x1) | |
19 | -#define ELM_SYSSTATUS_RESETDONE (0x1) | |
20 | -#define ELM_LOCATION_CONFIG_ECC_BCH_LEVEL_MASK (0x3) | |
21 | -#define ELM_LOCATION_CONFIG_ECC_SIZE_MASK (0x7FF0000) | |
22 | -#define ELM_LOCATION_CONFIG_ECC_SIZE_POS (16) | |
23 | -#define ELM_SYNDROME_FRAGMENT_6_SYNDROME_VALID (0x00010000) | |
24 | -#define ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK (0x100) | |
25 | -#define ELM_LOCATION_STATUS_ECC_NB_ERRORS_MASK (0x1F) | |
26 | - | |
27 | -#ifndef __ASSEMBLY__ | |
28 | - | |
29 | -enum bch_level { | |
30 | - BCH_4_BIT = 0, | |
31 | - BCH_8_BIT, | |
32 | - BCH_16_BIT | |
33 | -}; | |
34 | - | |
35 | - | |
36 | -/* BCH syndrome registers */ | |
37 | -struct syndrome { | |
38 | - u32 syndrome_fragment_x[7]; /* 0x400, 0x404.... 0x418 */ | |
39 | - u8 res1[36]; /* 0x41c */ | |
40 | -}; | |
41 | - | |
42 | -/* BCH error status & location register */ | |
43 | -struct location { | |
44 | - u32 location_status; /* 0x800 */ | |
45 | - u8 res1[124]; /* 0x804 */ | |
46 | - u32 error_location_x[16]; /* 0x880.... */ | |
47 | - u8 res2[64]; /* 0x8c0 */ | |
48 | -}; | |
49 | - | |
50 | -/* BCH ELM register map - do not try to allocate memmory for this structure. | |
51 | - * We have used plenty of reserved variables to fill the slots in the ELM | |
52 | - * register memory map. | |
53 | - * Directly initialize the struct pointer to ELM base address. | |
54 | - */ | |
55 | -struct elm { | |
56 | - u32 rev; /* 0x000 */ | |
57 | - u8 res1[12]; /* 0x004 */ | |
58 | - u32 sysconfig; /* 0x010 */ | |
59 | - u32 sysstatus; /* 0x014 */ | |
60 | - u32 irqstatus; /* 0x018 */ | |
61 | - u32 irqenable; /* 0x01c */ | |
62 | - u32 location_config; /* 0x020 */ | |
63 | - u8 res2[92]; /* 0x024 */ | |
64 | - u32 page_ctrl; /* 0x080 */ | |
65 | - u8 res3[892]; /* 0x084 */ | |
66 | - struct syndrome syndrome_fragments[8]; /* 0x400 */ | |
67 | - u8 res4[512]; /* 0x600 */ | |
68 | - struct location error_location[8]; /* 0x800 */ | |
69 | -}; | |
70 | - | |
71 | -int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count, | |
72 | - u32 *error_locations); | |
73 | -int elm_config(enum bch_level level); | |
74 | -void elm_reset(void); | |
75 | -void elm_init(void); | |
76 | -#endif /* __ASSEMBLY__ */ | |
77 | -#endif /* __ASM_ARCH_ELM_H */ |
arch/arm/include/asm/arch-am33xx/mem.h
... | ... | @@ -68,10 +68,5 @@ |
68 | 68 | #define PISMO2_NAND_CS0 7 |
69 | 69 | #define PISMO2_NAND_CS1 8 |
70 | 70 | |
71 | -/* make it readable for the gpmc_init */ | |
72 | -#define PISMO1_NOR_BASE FLASH_BASE | |
73 | -#define PISMO1_NAND_BASE CONFIG_SYS_NAND_BASE | |
74 | -#define PISMO1_NAND_SIZE GPMC_SIZE_256M | |
75 | - | |
76 | 71 | #endif /* endif _MEM_H_ */ |
arch/arm/include/asm/omap_elm.h
1 | +/* | |
2 | + * (C) Copyright 2010-2011 Texas Instruments, <www.ti.com> | |
3 | + * Mansoor Ahamed <mansoor.ahamed@ti.com> | |
4 | + * | |
5 | + * Derived from work done by Rohit Choraria <rohitkc@ti.com> for omap3 | |
6 | + * | |
7 | + * SPDX-License-Identifier: GPL-2.0+ | |
8 | + */ | |
9 | +#ifndef __ASM_ARCH_ELM_H | |
10 | +#define __ASM_ARCH_ELM_H | |
11 | +/* | |
12 | + * ELM Module Registers | |
13 | + */ | |
14 | + | |
15 | +/* ELM registers bit fields */ | |
16 | +#define ELM_SYSCONFIG_SOFTRESET_MASK (0x2) | |
17 | +#define ELM_SYSCONFIG_SOFTRESET (0x2) | |
18 | +#define ELM_SYSSTATUS_RESETDONE_MASK (0x1) | |
19 | +#define ELM_SYSSTATUS_RESETDONE (0x1) | |
20 | +#define ELM_LOCATION_CONFIG_ECC_BCH_LEVEL_MASK (0x3) | |
21 | +#define ELM_LOCATION_CONFIG_ECC_SIZE_MASK (0x7FF0000) | |
22 | +#define ELM_LOCATION_CONFIG_ECC_SIZE_POS (16) | |
23 | +#define ELM_SYNDROME_FRAGMENT_6_SYNDROME_VALID (0x00010000) | |
24 | +#define ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK (0x100) | |
25 | +#define ELM_LOCATION_STATUS_ECC_NB_ERRORS_MASK (0x1F) | |
26 | + | |
27 | +#ifndef __ASSEMBLY__ | |
28 | + | |
29 | +enum bch_level { | |
30 | + BCH_4_BIT = 0, | |
31 | + BCH_8_BIT, | |
32 | + BCH_16_BIT | |
33 | +}; | |
34 | + | |
35 | + | |
36 | +/* BCH syndrome registers */ | |
37 | +struct syndrome { | |
38 | + u32 syndrome_fragment_x[7]; /* 0x400, 0x404.... 0x418 */ | |
39 | + u8 res1[36]; /* 0x41c */ | |
40 | +}; | |
41 | + | |
42 | +/* BCH error status & location register */ | |
43 | +struct location { | |
44 | + u32 location_status; /* 0x800 */ | |
45 | + u8 res1[124]; /* 0x804 */ | |
46 | + u32 error_location_x[16]; /* 0x880.... */ | |
47 | + u8 res2[64]; /* 0x8c0 */ | |
48 | +}; | |
49 | + | |
50 | +/* BCH ELM register map - do not try to allocate memmory for this structure. | |
51 | + * We have used plenty of reserved variables to fill the slots in the ELM | |
52 | + * register memory map. | |
53 | + * Directly initialize the struct pointer to ELM base address. | |
54 | + */ | |
55 | +struct elm { | |
56 | + u32 rev; /* 0x000 */ | |
57 | + u8 res1[12]; /* 0x004 */ | |
58 | + u32 sysconfig; /* 0x010 */ | |
59 | + u32 sysstatus; /* 0x014 */ | |
60 | + u32 irqstatus; /* 0x018 */ | |
61 | + u32 irqenable; /* 0x01c */ | |
62 | + u32 location_config; /* 0x020 */ | |
63 | + u8 res2[92]; /* 0x024 */ | |
64 | + u32 page_ctrl; /* 0x080 */ | |
65 | + u8 res3[892]; /* 0x084 */ | |
66 | + struct syndrome syndrome_fragments[8]; /* 0x400 */ | |
67 | + u8 res4[512]; /* 0x600 */ | |
68 | + struct location error_location[8]; /* 0x800 */ | |
69 | +}; | |
70 | + | |
71 | +int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count, | |
72 | + u32 *error_locations); | |
73 | +int elm_config(enum bch_level level); | |
74 | +void elm_reset(void); | |
75 | +void elm_init(void); | |
76 | +#endif /* __ASSEMBLY__ */ | |
77 | +#endif /* __ASM_ARCH_ELM_H */ |
arch/arm/include/asm/omap_gpmc.h
... | ... | @@ -68,5 +68,21 @@ |
68 | 68 | } |
69 | 69 | #endif |
70 | 70 | |
71 | +enum omap_ecc { | |
72 | + /* 1-bit ECC calculation by Software, Error detection by Software */ | |
73 | + OMAP_ECC_HAM1_CODE_SW = 1, /* avoid un-initialized int can be 0x0 */ | |
74 | + /* 1-bit ECC calculation by GPMC, Error detection by Software */ | |
75 | + /* ECC layout compatible to legacy ROMCODE. */ | |
76 | + OMAP_ECC_HAM1_CODE_HW, | |
77 | + /* 4-bit ECC calculation by GPMC, Error detection by Software */ | |
78 | + OMAP_ECC_BCH4_CODE_HW_DETECTION_SW, | |
79 | + /* 4-bit ECC calculation by GPMC, Error detection by ELM */ | |
80 | + OMAP_ECC_BCH4_CODE_HW, | |
81 | + /* 8-bit ECC calculation by GPMC, Error detection by Software */ | |
82 | + OMAP_ECC_BCH8_CODE_HW_DETECTION_SW, | |
83 | + /* 8-bit ECC calculation by GPMC, Error detection by ELM */ | |
84 | + OMAP_ECC_BCH8_CODE_HW, | |
85 | +}; | |
86 | + | |
71 | 87 | #endif /* __ASM_OMAP_GPMC_H */ |
arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
... | ... | @@ -34,6 +34,9 @@ |
34 | 34 | #ifdef CONFIG_SYS_CSPR0_EXT |
35 | 35 | set_ifc_cspr_ext(IFC_CS0, CONFIG_SYS_CSPR0_EXT); |
36 | 36 | #endif |
37 | +#ifdef CONFIG_SYS_CSOR0_EXT | |
38 | + set_ifc_csor_ext(IFC_CS0, CONFIG_SYS_CSOR0_EXT); | |
39 | +#endif | |
37 | 40 | set_ifc_cspr(IFC_CS0, CONFIG_SYS_CSPR0); |
38 | 41 | set_ifc_amask(IFC_CS0, CONFIG_SYS_AMASK0); |
39 | 42 | set_ifc_csor(IFC_CS0, CONFIG_SYS_CSOR0); |
... | ... | @@ -43,6 +46,9 @@ |
43 | 46 | #ifdef CONFIG_SYS_CSPR1_EXT |
44 | 47 | set_ifc_cspr_ext(IFC_CS1, CONFIG_SYS_CSPR1_EXT); |
45 | 48 | #endif |
49 | +#ifdef CONFIG_SYS_CSOR1_EXT | |
50 | + set_ifc_csor_ext(IFC_CS1, CONFIG_SYS_CSOR1_EXT); | |
51 | +#endif | |
46 | 52 | #if defined(CONFIG_SYS_CSPR1) && defined(CONFIG_SYS_CSOR1) |
47 | 53 | set_ifc_ftim(IFC_CS1, IFC_FTIM0, CONFIG_SYS_CS1_FTIM0); |
48 | 54 | set_ifc_ftim(IFC_CS1, IFC_FTIM1, CONFIG_SYS_CS1_FTIM1); |
... | ... | @@ -57,6 +63,9 @@ |
57 | 63 | #ifdef CONFIG_SYS_CSPR2_EXT |
58 | 64 | set_ifc_cspr_ext(IFC_CS2, CONFIG_SYS_CSPR2_EXT); |
59 | 65 | #endif |
66 | +#ifdef CONFIG_SYS_CSOR2_EXT | |
67 | + set_ifc_csor_ext(IFC_CS2, CONFIG_SYS_CSOR2_EXT); | |
68 | +#endif | |
60 | 69 | #if defined(CONFIG_SYS_CSPR2) && defined(CONFIG_SYS_CSOR2) |
61 | 70 | set_ifc_ftim(IFC_CS2, IFC_FTIM0, CONFIG_SYS_CS2_FTIM0); |
62 | 71 | set_ifc_ftim(IFC_CS2, IFC_FTIM1, CONFIG_SYS_CS2_FTIM1); |
... | ... | @@ -71,6 +80,9 @@ |
71 | 80 | #ifdef CONFIG_SYS_CSPR3_EXT |
72 | 81 | set_ifc_cspr_ext(IFC_CS3, CONFIG_SYS_CSPR3_EXT); |
73 | 82 | #endif |
83 | +#ifdef CONFIG_SYS_CSOR3_EXT | |
84 | + set_ifc_csor_ext(IFC_CS3, CONFIG_SYS_CSOR3_EXT); | |
85 | +#endif | |
74 | 86 | #if defined(CONFIG_SYS_CSPR3) && defined(CONFIG_SYS_CSOR3) |
75 | 87 | set_ifc_ftim(IFC_CS3, IFC_FTIM0, CONFIG_SYS_CS3_FTIM0); |
76 | 88 | set_ifc_ftim(IFC_CS3, IFC_FTIM1, CONFIG_SYS_CS3_FTIM1); |
... | ... | @@ -85,6 +97,9 @@ |
85 | 97 | #ifdef CONFIG_SYS_CSPR4_EXT |
86 | 98 | set_ifc_cspr_ext(IFC_CS4, CONFIG_SYS_CSPR4_EXT); |
87 | 99 | #endif |
100 | +#ifdef CONFIG_SYS_CSOR4_EXT | |
101 | + set_ifc_csor_ext(IFC_CS4, CONFIG_SYS_CSOR4_EXT); | |
102 | +#endif | |
88 | 103 | #if defined(CONFIG_SYS_CSPR4) && defined(CONFIG_SYS_CSOR4) |
89 | 104 | set_ifc_ftim(IFC_CS4, IFC_FTIM0, CONFIG_SYS_CS4_FTIM0); |
90 | 105 | set_ifc_ftim(IFC_CS4, IFC_FTIM1, CONFIG_SYS_CS4_FTIM1); |
... | ... | @@ -99,6 +114,9 @@ |
99 | 114 | #ifdef CONFIG_SYS_CSPR5_EXT |
100 | 115 | set_ifc_cspr_ext(IFC_CS5, CONFIG_SYS_CSPR5_EXT); |
101 | 116 | #endif |
117 | +#ifdef CONFIG_SYS_CSOR5_EXT | |
118 | + set_ifc_csor_ext(IFC_CS5, CONFIG_SYS_CSOR5_EXT); | |
119 | +#endif | |
102 | 120 | #if defined(CONFIG_SYS_CSPR5) && defined(CONFIG_SYS_CSOR5) |
103 | 121 | set_ifc_ftim(IFC_CS5, IFC_FTIM0, CONFIG_SYS_CS5_FTIM0); |
104 | 122 | set_ifc_ftim(IFC_CS5, IFC_FTIM1, CONFIG_SYS_CS5_FTIM1); |
... | ... | @@ -113,6 +131,9 @@ |
113 | 131 | #ifdef CONFIG_SYS_CSPR6_EXT |
114 | 132 | set_ifc_cspr_ext(IFC_CS6, CONFIG_SYS_CSPR6_EXT); |
115 | 133 | #endif |
134 | +#ifdef CONFIG_SYS_CSOR6_EXT | |
135 | + set_ifc_csor_ext(IFC_CS6, CONFIG_SYS_CSOR6_EXT); | |
136 | +#endif | |
116 | 137 | #if defined(CONFIG_SYS_CSPR6) && defined(CONFIG_SYS_CSOR6) |
117 | 138 | set_ifc_ftim(IFC_CS6, IFC_FTIM0, CONFIG_SYS_CS6_FTIM0); |
118 | 139 | set_ifc_ftim(IFC_CS6, IFC_FTIM1, CONFIG_SYS_CS6_FTIM1); |
... | ... | @@ -126,6 +147,9 @@ |
126 | 147 | |
127 | 148 | #ifdef CONFIG_SYS_CSPR7_EXT |
128 | 149 | set_ifc_cspr_ext(IFC_CS7, CONFIG_SYS_CSPR7_EXT); |
150 | +#endif | |
151 | +#ifdef CONFIG_SYS_CSOR7_EXT | |
152 | + set_ifc_csor_ext(IFC_CS7, CONFIG_SYS_CSOR7_EXT); | |
129 | 153 | #endif |
130 | 154 | #if defined(CONFIG_SYS_CSPR7) && defined(CONFIG_SYS_CSOR7) |
131 | 155 | set_ifc_ftim(IFC_CS7, IFC_FTIM0, CONFIG_SYS_CS7_FTIM0); |
arch/powerpc/include/asm/fsl_ifc.h
... | ... | @@ -77,6 +77,7 @@ |
77 | 77 | #define CSOR_NAND_PGS_512 0x00000000 |
78 | 78 | #define CSOR_NAND_PGS_2K 0x00080000 |
79 | 79 | #define CSOR_NAND_PGS_4K 0x00100000 |
80 | +#define CSOR_NAND_PGS_8K 0x00180000 | |
80 | 81 | /* Spare region Size */ |
81 | 82 | #define CSOR_NAND_SPRZ_MASK 0x0000E000 |
82 | 83 | #define CSOR_NAND_SPRZ_SHIFT 13 |
... | ... | @@ -86,6 +87,7 @@ |
86 | 87 | #define CSOR_NAND_SPRZ_210 0x00006000 |
87 | 88 | #define CSOR_NAND_SPRZ_218 0x00008000 |
88 | 89 | #define CSOR_NAND_SPRZ_224 0x0000A000 |
90 | +#define CSOR_NAND_SPRZ_CSOR_EXT 0x0000C000 | |
89 | 91 | /* Pages Per Block */ |
90 | 92 | #define CSOR_NAND_PB_MASK 0x00000700 |
91 | 93 | #define CSOR_NAND_PB_SHIFT 8 |
board/atmel/sama5d3xek/sama5d3xek.c
... | ... | @@ -131,7 +131,8 @@ |
131 | 131 | |
132 | 132 | void lcd_show_board_info(void) |
133 | 133 | { |
134 | - ulong dram_size, nand_size; | |
134 | + ulong dram_size; | |
135 | + uint64_t nand_size; | |
135 | 136 | int i; |
136 | 137 | char temp[32]; |
137 | 138 | |
... | ... | @@ -150,7 +151,7 @@ |
150 | 151 | for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) |
151 | 152 | nand_size += nand_info[i].size; |
152 | 153 | #endif |
153 | - lcd_printf("%ld MB SDRAM, %ld MB NAND\n", | |
154 | + lcd_printf("%ld MB SDRAM, %lld MB NAND\n", | |
154 | 155 | dram_size >> 20, nand_size >> 20); |
155 | 156 | } |
156 | 157 | #endif /* CONFIG_LCD_INFO */ |
board/ti/am335x/board.c
... | ... | @@ -481,26 +481,14 @@ |
481 | 481 | */ |
482 | 482 | int board_init(void) |
483 | 483 | { |
484 | -#ifdef CONFIG_NOR | |
485 | - const u32 gpmc_nor[GPMC_MAX_REG] = { STNOR_GPMC_CONFIG1, | |
486 | - STNOR_GPMC_CONFIG2, STNOR_GPMC_CONFIG3, STNOR_GPMC_CONFIG4, | |
487 | - STNOR_GPMC_CONFIG5, STNOR_GPMC_CONFIG6, STNOR_GPMC_CONFIG7 }; | |
488 | -#endif | |
489 | - | |
490 | 484 | #if defined(CONFIG_HW_WATCHDOG) |
491 | 485 | hw_watchdog_init(); |
492 | 486 | #endif |
493 | 487 | |
494 | 488 | gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; |
495 | - | |
489 | +#if defined(CONFIG_NOR) || defined(CONFIG_NAND) | |
496 | 490 | gpmc_init(); |
497 | - | |
498 | -#ifdef CONFIG_NOR | |
499 | - /* Reconfigure CS0 for NOR instead of NAND. */ | |
500 | - enable_gpmc_cs_config(gpmc_nor, &gpmc_cfg->cs[0], | |
501 | - CONFIG_SYS_FLASH_BASE, GPMC_SIZE_16M); | |
502 | 491 | #endif |
503 | - | |
504 | 492 | return 0; |
505 | 493 | } |
506 | 494 |
doc/README.nand
... | ... | @@ -104,6 +104,16 @@ |
104 | 104 | CONFIG_SYS_MAX_NAND_DEVICE |
105 | 105 | The maximum number of NAND devices you want to support. |
106 | 106 | |
107 | + CONFIG_SYS_NAND_MAX_ECCPOS | |
108 | + If specified, overrides the maximum number of ECC bytes | |
109 | + supported. Useful for reducing image size, especially with SPL. | |
110 | + This must be at least 48 if nand_base.c is used. | |
111 | + | |
112 | + CONFIG_SYS_NAND_MAX_OOBFREE | |
113 | + If specified, overrides the maximum number of free OOB regions | |
114 | + supported. Useful for reducing image size, especially with SPL. | |
115 | + This must be at least 2 if nand_base.c is used. | |
116 | + | |
107 | 117 | CONFIG_SYS_NAND_MAX_CHIPS |
108 | 118 | The maximum number of NAND chips per device to be supported. |
109 | 119 | |
... | ... | @@ -168,6 +178,59 @@ |
168 | 178 | |
169 | 179 | Please convert your driver even if you don't need the extra |
170 | 180 | flexibility, so that one day we can eliminate the old mechanism. |
181 | + | |
182 | + | |
183 | + CONFIG_SYS_NAND_ONFI_DETECTION | |
184 | + Enables detection of ONFI compliant devices during probe. | |
185 | + And fetching device parameters flashed on device, by parsing | |
186 | + ONFI parameter page. | |
187 | + | |
188 | + CONFIG_BCH | |
189 | + Enables software based BCH ECC algorithm present in lib/bch.c | |
190 | + This is used by SoC platforms which do not have built-in ELM | |
191 | + hardware engine required for BCH ECC correction. | |
192 | + | |
193 | + | |
194 | +Platform specific options | |
195 | +========================= | |
196 | + CONFIG_NAND_OMAP_GPMC | |
197 | + Enables omap_gpmc.c driver for OMAPx and AMxxxx platforms. | |
198 | + GPMC controller is used for parallel NAND flash devices, and can | |
199 | + do ECC calculation (not ECC error detection) for HAM1, BCH4, BCH8 | |
200 | + and BCH16 ECC algorithms. | |
201 | + | |
202 | + CONFIG_NAND_OMAP_ELM | |
203 | + Enables omap_elm.c driver for OMAPx and AMxxxx platforms. | |
204 | + ELM controller is used for ECC error detection (not ECC calculation) | |
205 | + of BCH4, BCH8 and BCH16 ECC algorithms. | |
206 | + Some legacy platforms like OMAP3xx do not have in-built ELM h/w engine, | |
207 | + thus such SoC platforms need to depend on software library for ECC error | |
208 | + detection. However ECC calculation on such plaforms would still be | |
209 | + done by GPMC controller. | |
210 | + | |
211 | + CONFIG_NAND_OMAP_ECCSCHEME | |
212 | + On OMAP platforms, this CONFIG specifies NAND ECC scheme. | |
213 | + It can take following values: | |
214 | + OMAP_ECC_HAM1_CODE_SW | |
215 | + 1-bit Hamming code using software lib. | |
216 | + (for legacy devices only) | |
217 | + OMAP_ECC_HAM1_CODE_HW | |
218 | + 1-bit Hamming code using GPMC hardware. | |
219 | + (for legacy devices only) | |
220 | + OMAP_ECC_BCH4_CODE_HW_DETECTION_SW | |
221 | + 4-bit BCH code (unsupported) | |
222 | + OMAP_ECC_BCH4_CODE_HW | |
223 | + 4-bit BCH code (unsupported) | |
224 | + OMAP_ECC_BCH8_CODE_HW_DETECTION_SW | |
225 | + 8-bit BCH code with | |
226 | + - ecc calculation using GPMC hardware engine, | |
227 | + - error detection using software library. | |
228 | + - requires CONFIG_BCH to enable software BCH library | |
229 | + (For legacy device which do not have ELM h/w engine) | |
230 | + OMAP_ECC_BCH8_CODE_HW | |
231 | + 8-bit BCH code with | |
232 | + - ecc calculation using GPMC hardware engine, | |
233 | + - error detection using ELM hardware engine. | |
171 | 234 | |
172 | 235 | NOTE: |
173 | 236 | ===== |
doc/README.omap3
... | ... | @@ -161,8 +161,7 @@ |
161 | 161 | |
162 | 162 | To enable hardware assisted BCH8 (8-bit BCH [Bose, Chaudhuri, Hocquenghem]) on |
163 | 163 | OMAP3 devices we can use the BCH library in lib/bch.c. To do so add CONFIG_BCH |
164 | -to enable the library and CONFIG_NAND_OMAP_BCH8 to to enable hardware assisted | |
165 | -syndrom generation to your board config. | |
164 | +and set CONFIG_NAND_OMAP_ECCSCHEME=5 (refer README.nand) for selecting BCH8_SW. | |
166 | 165 | The NAND OOB layout is the same as in linux kernel, if the linux kernel BCH8 |
167 | 166 | implementation for OMAP3 works for you so the u-boot version should also. |
168 | 167 | When you require the SPL to read with BCH8 there are two more configs to |
drivers/mtd/nand/Makefile
... | ... | @@ -58,6 +58,7 @@ |
58 | 58 | obj-$(CONFIG_NAND_SPEAR) += spr_nand.o |
59 | 59 | obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o |
60 | 60 | obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o |
61 | +obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o | |
61 | 62 | obj-$(CONFIG_NAND_PLAT) += nand_plat.o |
62 | 63 | obj-$(CONFIG_NAND_DOCG4) += docg4.o |
63 | 64 |
drivers/mtd/nand/atmel_nand.c
... | ... | @@ -412,7 +412,7 @@ |
412 | 412 | } |
413 | 413 | |
414 | 414 | if (!timeout) { |
415 | - printk(KERN_ERR "atmel_nand : Timeout to calculate PMECC error location\n"); | |
415 | + dev_err(host->dev, "atmel_nand : Timeout to calculate PMECC error location\n"); | |
416 | 416 | return -1; |
417 | 417 | } |
418 | 418 | |
... | ... | @@ -452,7 +452,7 @@ |
452 | 452 | *(buf + byte_pos) ^= (1 << bit_pos); |
453 | 453 | |
454 | 454 | pos = sector_num * host->pmecc_sector_size + byte_pos; |
455 | - printk(KERN_INFO "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", | |
455 | + dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", | |
456 | 456 | pos, bit_pos, err_byte, *(buf + byte_pos)); |
457 | 457 | } else { |
458 | 458 | /* Bit flip in OOB area */ |
... | ... | @@ -462,7 +462,7 @@ |
462 | 462 | ecc[tmp] ^= (1 << bit_pos); |
463 | 463 | |
464 | 464 | pos = tmp + nand_chip->ecc.layout->eccpos[0]; |
465 | - printk(KERN_INFO "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", | |
465 | + dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", | |
466 | 466 | pos, bit_pos, err_byte, ecc[tmp]); |
467 | 467 | } |
468 | 468 | |
... | ... | @@ -500,7 +500,7 @@ |
500 | 500 | |
501 | 501 | err_nbr = pmecc_err_location(mtd); |
502 | 502 | if (err_nbr == -1) { |
503 | - printk(KERN_ERR "PMECC: Too many errors\n"); | |
503 | + dev_err(host->dev, "PMECC: Too many errors\n"); | |
504 | 504 | mtd->ecc_stats.failed++; |
505 | 505 | return -EIO; |
506 | 506 | } else { |
... | ... | @@ -544,7 +544,7 @@ |
544 | 544 | } |
545 | 545 | |
546 | 546 | if (!timeout) { |
547 | - printk(KERN_ERR "atmel_nand : Timeout to read PMECC page\n"); | |
547 | + dev_err(host->dev, "atmel_nand : Timeout to read PMECC page\n"); | |
548 | 548 | return -1; |
549 | 549 | } |
550 | 550 | |
... | ... | @@ -584,7 +584,7 @@ |
584 | 584 | } |
585 | 585 | |
586 | 586 | if (!timeout) { |
587 | - printk(KERN_ERR "atmel_nand : Timeout to read PMECC status, fail to write PMECC in oob\n"); | |
587 | + dev_err(host->dev, "atmel_nand : Timeout to read PMECC status, fail to write PMECC in oob\n"); | |
588 | 588 | goto out; |
589 | 589 | } |
590 | 590 | |
... | ... | @@ -827,6 +827,7 @@ |
827 | 827 | switch (mtd->writesize) { |
828 | 828 | case 2048: |
829 | 829 | case 4096: |
830 | + case 8192: | |
830 | 831 | host->pmecc_degree = (sector_size == 512) ? |
831 | 832 | PMECC_GF_DIMENSION_13 : PMECC_GF_DIMENSION_14; |
832 | 833 | host->pmecc_cw_len = (1 << host->pmecc_degree) - 1; |
833 | 834 | |
... | ... | @@ -840,8 +841,15 @@ |
840 | 841 | nand->ecc.steps = 1; |
841 | 842 | nand->ecc.bytes = host->pmecc_bytes_per_sector * |
842 | 843 | host->pmecc_sector_number; |
844 | + | |
845 | + if (nand->ecc.bytes > MTD_MAX_ECCPOS_ENTRIES_LARGE) { | |
846 | + dev_err(host->dev, "too large eccpos entries. max support ecc.bytes is %d\n", | |
847 | + MTD_MAX_ECCPOS_ENTRIES_LARGE); | |
848 | + return -EINVAL; | |
849 | + } | |
850 | + | |
843 | 851 | if (nand->ecc.bytes > mtd->oobsize - 2) { |
844 | - printk(KERN_ERR "No room for ECC bytes\n"); | |
852 | + dev_err(host->dev, "No room for ECC bytes\n"); | |
845 | 853 | return -EINVAL; |
846 | 854 | } |
847 | 855 | pmecc_config_ecc_layout(&atmel_pmecc_oobinfo, |
... | ... | @@ -852,7 +860,7 @@ |
852 | 860 | case 512: |
853 | 861 | case 1024: |
854 | 862 | /* TODO */ |
855 | - printk(KERN_ERR "Unsupported page size for PMECC, use Software ECC\n"); | |
863 | + dev_err(host->dev, "Unsupported page size for PMECC, use Software ECC\n"); | |
856 | 864 | default: |
857 | 865 | /* page size not handled by HW ECC */ |
858 | 866 | /* switching back to soft ECC */ |
... | ... | @@ -1035,7 +1043,7 @@ |
1035 | 1043 | /* it doesn't seems to be a freshly |
1036 | 1044 | * erased block. |
1037 | 1045 | * We can't correct so many errors */ |
1038 | - printk(KERN_WARNING "atmel_nand : multiple errors detected." | |
1046 | + dev_warn(host->dev, "atmel_nand : multiple errors detected." | |
1039 | 1047 | " Unable to correct.\n"); |
1040 | 1048 | return -EIO; |
1041 | 1049 | } |
1042 | 1050 | |
... | ... | @@ -1045,12 +1053,12 @@ |
1045 | 1053 | /* there's nothing much to do here. |
1046 | 1054 | * the bit error is on the ECC itself. |
1047 | 1055 | */ |
1048 | - printk(KERN_WARNING "atmel_nand : one bit error on ECC code." | |
1056 | + dev_warn(host->dev, "atmel_nand : one bit error on ECC code." | |
1049 | 1057 | " Nothing to correct\n"); |
1050 | 1058 | return 0; |
1051 | 1059 | } |
1052 | 1060 | |
1053 | - printk(KERN_WARNING "atmel_nand : one bit error on data." | |
1061 | + dev_warn(host->dev, "atmel_nand : one bit error on data." | |
1054 | 1062 | " (word offset in the page :" |
1055 | 1063 | " 0x%x bit offset : 0x%x)\n", |
1056 | 1064 | ecc_word, ecc_bit); |
... | ... | @@ -1062,7 +1070,7 @@ |
1062 | 1070 | /* 8 bits words */ |
1063 | 1071 | dat[ecc_word] ^= (1 << ecc_bit); |
1064 | 1072 | } |
1065 | - printk(KERN_WARNING "atmel_nand : error corrected\n"); | |
1073 | + dev_warn(host->dev, "atmel_nand : error corrected\n"); | |
1066 | 1074 | return 1; |
1067 | 1075 | } |
1068 | 1076 | |
1069 | 1077 | |
... | ... | @@ -1178,7 +1186,11 @@ |
1178 | 1186 | mtd->priv = nand; |
1179 | 1187 | nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; |
1180 | 1188 | |
1189 | +#ifdef CONFIG_NAND_ECC_BCH | |
1190 | + nand->ecc.mode = NAND_ECC_SOFT_BCH; | |
1191 | +#else | |
1181 | 1192 | nand->ecc.mode = NAND_ECC_SOFT; |
1193 | +#endif | |
1182 | 1194 | #ifdef CONFIG_SYS_NAND_DBW_16 |
1183 | 1195 | nand->options = NAND_BUSWIDTH_16; |
1184 | 1196 | #endif |
... | ... | @@ -1186,7 +1198,7 @@ |
1186 | 1198 | #ifdef CONFIG_SYS_NAND_READY_PIN |
1187 | 1199 | nand->dev_ready = at91_nand_ready; |
1188 | 1200 | #endif |
1189 | - nand->chip_delay = 20; | |
1201 | + nand->chip_delay = 75; | |
1190 | 1202 | |
1191 | 1203 | ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL); |
1192 | 1204 | if (ret) |
... | ... | @@ -1214,7 +1226,7 @@ |
1214 | 1226 | int i; |
1215 | 1227 | for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) |
1216 | 1228 | if (atmel_nand_chip_init(i, base_addr[i])) |
1217 | - printk(KERN_ERR "atmel_nand: Fail to initialize #%d chip", | |
1229 | + dev_err(host->dev, "atmel_nand: Fail to initialize #%d chip", | |
1218 | 1230 | i); |
1219 | 1231 | } |
drivers/mtd/nand/fsl_ifc_nand.c
... | ... | @@ -125,7 +125,70 @@ |
125 | 125 | .oobfree = { {2, 6}, {136, 82} }, |
126 | 126 | }; |
127 | 127 | |
128 | +/* 8192-byte page size with 4-bit ECC */ | |
129 | +static struct nand_ecclayout oob_8192_ecc4 = { | |
130 | + .eccbytes = 128, | |
131 | + .eccpos = { | |
132 | + 8, 9, 10, 11, 12, 13, 14, 15, | |
133 | + 16, 17, 18, 19, 20, 21, 22, 23, | |
134 | + 24, 25, 26, 27, 28, 29, 30, 31, | |
135 | + 32, 33, 34, 35, 36, 37, 38, 39, | |
136 | + 40, 41, 42, 43, 44, 45, 46, 47, | |
137 | + 48, 49, 50, 51, 52, 53, 54, 55, | |
138 | + 56, 57, 58, 59, 60, 61, 62, 63, | |
139 | + 64, 65, 66, 67, 68, 69, 70, 71, | |
140 | + 72, 73, 74, 75, 76, 77, 78, 79, | |
141 | + 80, 81, 82, 83, 84, 85, 86, 87, | |
142 | + 88, 89, 90, 91, 92, 93, 94, 95, | |
143 | + 96, 97, 98, 99, 100, 101, 102, 103, | |
144 | + 104, 105, 106, 107, 108, 109, 110, 111, | |
145 | + 112, 113, 114, 115, 116, 117, 118, 119, | |
146 | + 120, 121, 122, 123, 124, 125, 126, 127, | |
147 | + 128, 129, 130, 131, 132, 133, 134, 135, | |
148 | + }, | |
149 | + .oobfree = { {2, 6}, {136, 208} }, | |
150 | +}; | |
128 | 151 | |
152 | +/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */ | |
153 | +static struct nand_ecclayout oob_8192_ecc8 = { | |
154 | + .eccbytes = 256, | |
155 | + .eccpos = { | |
156 | + 8, 9, 10, 11, 12, 13, 14, 15, | |
157 | + 16, 17, 18, 19, 20, 21, 22, 23, | |
158 | + 24, 25, 26, 27, 28, 29, 30, 31, | |
159 | + 32, 33, 34, 35, 36, 37, 38, 39, | |
160 | + 40, 41, 42, 43, 44, 45, 46, 47, | |
161 | + 48, 49, 50, 51, 52, 53, 54, 55, | |
162 | + 56, 57, 58, 59, 60, 61, 62, 63, | |
163 | + 64, 65, 66, 67, 68, 69, 70, 71, | |
164 | + 72, 73, 74, 75, 76, 77, 78, 79, | |
165 | + 80, 81, 82, 83, 84, 85, 86, 87, | |
166 | + 88, 89, 90, 91, 92, 93, 94, 95, | |
167 | + 96, 97, 98, 99, 100, 101, 102, 103, | |
168 | + 104, 105, 106, 107, 108, 109, 110, 111, | |
169 | + 112, 113, 114, 115, 116, 117, 118, 119, | |
170 | + 120, 121, 122, 123, 124, 125, 126, 127, | |
171 | + 128, 129, 130, 131, 132, 133, 134, 135, | |
172 | + 136, 137, 138, 139, 140, 141, 142, 143, | |
173 | + 144, 145, 146, 147, 148, 149, 150, 151, | |
174 | + 152, 153, 154, 155, 156, 157, 158, 159, | |
175 | + 160, 161, 162, 163, 164, 165, 166, 167, | |
176 | + 168, 169, 170, 171, 172, 173, 174, 175, | |
177 | + 176, 177, 178, 179, 180, 181, 182, 183, | |
178 | + 184, 185, 186, 187, 188, 189, 190, 191, | |
179 | + 192, 193, 194, 195, 196, 197, 198, 199, | |
180 | + 200, 201, 202, 203, 204, 205, 206, 207, | |
181 | + 208, 209, 210, 211, 212, 213, 214, 215, | |
182 | + 216, 217, 218, 219, 220, 221, 222, 223, | |
183 | + 224, 225, 226, 227, 228, 229, 230, 231, | |
184 | + 232, 233, 234, 235, 236, 237, 238, 239, | |
185 | + 240, 241, 242, 243, 244, 245, 246, 247, | |
186 | + 248, 249, 250, 251, 252, 253, 254, 255, | |
187 | + 256, 257, 258, 259, 260, 261, 262, 263, | |
188 | + }, | |
189 | + .oobfree = { {2, 6}, {264, 80} }, | |
190 | +}; | |
191 | + | |
129 | 192 | /* |
130 | 193 | * Generic flash bbt descriptors |
131 | 194 | */ |
132 | 195 | |
133 | 196 | |
... | ... | @@ -428,20 +491,27 @@ |
428 | 491 | if (mtd->writesize > 512) { |
429 | 492 | nand_fcr0 = |
430 | 493 | (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) | |
431 | - (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT); | |
494 | + (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) | | |
495 | + (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT); | |
432 | 496 | |
433 | 497 | out_be32(&ifc->ifc_nand.nand_fir0, |
434 | 498 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | |
435 | 499 | (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | |
436 | 500 | (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | |
437 | 501 | (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) | |
438 | - (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT)); | |
439 | - out_be32(&ifc->ifc_nand.nand_fir1, 0); | |
502 | + (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT)); | |
503 | + out_be32(&ifc->ifc_nand.nand_fir1, | |
504 | + (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) | | |
505 | + (IFC_FIR_OP_RDSTAT << | |
506 | + IFC_NAND_FIR1_OP6_SHIFT) | | |
507 | + (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT)); | |
440 | 508 | } else { |
441 | 509 | nand_fcr0 = ((NAND_CMD_PAGEPROG << |
442 | 510 | IFC_NAND_FCR0_CMD1_SHIFT) | |
443 | 511 | (NAND_CMD_SEQIN << |
444 | - IFC_NAND_FCR0_CMD2_SHIFT)); | |
512 | + IFC_NAND_FCR0_CMD2_SHIFT) | | |
513 | + (NAND_CMD_STATUS << | |
514 | + IFC_NAND_FCR0_CMD3_SHIFT)); | |
445 | 515 | |
446 | 516 | out_be32(&ifc->ifc_nand.nand_fir0, |
447 | 517 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | |
... | ... | @@ -450,7 +520,11 @@ |
450 | 520 | (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) | |
451 | 521 | (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT)); |
452 | 522 | out_be32(&ifc->ifc_nand.nand_fir1, |
453 | - (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT)); | |
523 | + (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) | | |
524 | + (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) | | |
525 | + (IFC_FIR_OP_RDSTAT << | |
526 | + IFC_NAND_FIR1_OP7_SHIFT) | | |
527 | + (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT)); | |
454 | 528 | |
455 | 529 | if (column >= mtd->writesize) |
456 | 530 | nand_fcr0 |= |
... | ... | @@ -901,6 +975,21 @@ |
901 | 975 | |
902 | 976 | priv->bufnum_mask = 1; |
903 | 977 | break; |
978 | + | |
979 | + case CSOR_NAND_PGS_8K: | |
980 | + if ((csor & CSOR_NAND_ECC_MODE_MASK) == | |
981 | + CSOR_NAND_ECC_MODE_4) { | |
982 | + layout = &oob_8192_ecc4; | |
983 | + nand->ecc.strength = 4; | |
984 | + } else { | |
985 | + layout = &oob_8192_ecc8; | |
986 | + nand->ecc.strength = 8; | |
987 | + nand->ecc.bytes = 16; | |
988 | + } | |
989 | + | |
990 | + priv->bufnum_mask = 0; | |
991 | + break; | |
992 | + | |
904 | 993 | |
905 | 994 | default: |
906 | 995 | printf("ifc nand: bad csor %#x: bad page size\n", csor); |
drivers/mtd/nand/fsl_ifc_spl.c
... | ... | @@ -112,10 +112,13 @@ |
112 | 112 | |
113 | 113 | port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8; |
114 | 114 | |
115 | - if (csor & CSOR_NAND_PGS_4K) { | |
115 | + if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_8K) { | |
116 | + page_size = 8192; | |
117 | + bufnum_mask = 0x0; | |
118 | + } else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_4K) { | |
116 | 119 | page_size = 4096; |
117 | 120 | bufnum_mask = 0x1; |
118 | - } else if (csor & CSOR_NAND_PGS_2K) { | |
121 | + } else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_2K) { | |
119 | 122 | page_size = 2048; |
120 | 123 | bufnum_mask = 0x3; |
121 | 124 | } else { |
drivers/mtd/nand/omap_elm.c
1 | +/* | |
2 | + * (C) Copyright 2010-2011 Texas Instruments, <www.ti.com> | |
3 | + * Mansoor Ahamed <mansoor.ahamed@ti.com> | |
4 | + * | |
5 | + * BCH Error Location Module (ELM) support. | |
6 | + * | |
7 | + * NOTE: | |
8 | + * 1. Supports only continuous mode. Dont see need for page mode in uboot | |
9 | + * 2. Supports only syndrome polynomial 0. i.e. poly local variable is | |
10 | + * always set to ELM_DEFAULT_POLY. Dont see need for other polynomial | |
11 | + * sets in uboot | |
12 | + * | |
13 | + * SPDX-License-Identifier: GPL-2.0+ | |
14 | + */ | |
15 | + | |
16 | +#include <common.h> | |
17 | +#include <asm/io.h> | |
18 | +#include <asm/errno.h> | |
19 | +#include <asm/arch/cpu.h> | |
20 | +#include <asm/omap_gpmc.h> | |
21 | +#include <asm/omap_elm.h> | |
22 | + | |
23 | +#define ELM_DEFAULT_POLY (0) | |
24 | + | |
25 | +struct elm *elm_cfg; | |
26 | + | |
27 | +/** | |
28 | + * elm_load_syndromes - Load BCH syndromes based on nibble selection | |
29 | + * @syndrome: BCH syndrome | |
30 | + * @nibbles: | |
31 | + * @poly: Syndrome Polynomial set to use | |
32 | + * | |
33 | + * Load BCH syndromes based on nibble selection | |
34 | + */ | |
35 | +static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly) | |
36 | +{ | |
37 | + u32 *ptr; | |
38 | + u32 val; | |
39 | + | |
40 | + /* reg 0 */ | |
41 | + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[0]; | |
42 | + val = syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) | | |
43 | + (syndrome[3] << 24); | |
44 | + writel(val, ptr); | |
45 | + /* reg 1 */ | |
46 | + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[1]; | |
47 | + val = syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) | | |
48 | + (syndrome[7] << 24); | |
49 | + writel(val, ptr); | |
50 | + | |
51 | + /* BCH 8-bit with 26 nibbles (4*8=32) */ | |
52 | + if (nibbles > 13) { | |
53 | + /* reg 2 */ | |
54 | + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[2]; | |
55 | + val = syndrome[8] | (syndrome[9] << 8) | (syndrome[10] << 16) | | |
56 | + (syndrome[11] << 24); | |
57 | + writel(val, ptr); | |
58 | + /* reg 3 */ | |
59 | + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[3]; | |
60 | + val = syndrome[12] | (syndrome[13] << 8) | | |
61 | + (syndrome[14] << 16) | (syndrome[15] << 24); | |
62 | + writel(val, ptr); | |
63 | + } | |
64 | + | |
65 | + /* BCH 16-bit with 52 nibbles (7*8=56) */ | |
66 | + if (nibbles > 26) { | |
67 | + /* reg 4 */ | |
68 | + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[4]; | |
69 | + val = syndrome[16] | (syndrome[17] << 8) | | |
70 | + (syndrome[18] << 16) | (syndrome[19] << 24); | |
71 | + writel(val, ptr); | |
72 | + | |
73 | + /* reg 5 */ | |
74 | + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[5]; | |
75 | + val = syndrome[20] | (syndrome[21] << 8) | | |
76 | + (syndrome[22] << 16) | (syndrome[23] << 24); | |
77 | + writel(val, ptr); | |
78 | + | |
79 | + /* reg 6 */ | |
80 | + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]; | |
81 | + val = syndrome[24] | (syndrome[25] << 8) | | |
82 | + (syndrome[26] << 16) | (syndrome[27] << 24); | |
83 | + writel(val, ptr); | |
84 | + } | |
85 | +} | |
86 | + | |
87 | +/** | |
88 | + * elm_check_errors - Check for BCH errors and return error locations | |
89 | + * @syndrome: BCH syndrome | |
90 | + * @nibbles: | |
91 | + * @error_count: Returns number of errrors in the syndrome | |
92 | + * @error_locations: Returns error locations (in decimal) in this array | |
93 | + * | |
94 | + * Check the provided syndrome for BCH errors and return error count | |
95 | + * and locations in the array passed. Returns -1 if error is not correctable, | |
96 | + * else returns 0 | |
97 | + */ | |
98 | +int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count, | |
99 | + u32 *error_locations) | |
100 | +{ | |
101 | + u8 poly = ELM_DEFAULT_POLY; | |
102 | + s8 i; | |
103 | + u32 location_status; | |
104 | + | |
105 | + elm_load_syndromes(syndrome, nibbles, poly); | |
106 | + | |
107 | + /* start processing */ | |
108 | + writel((readl(&elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]) | |
109 | + | ELM_SYNDROME_FRAGMENT_6_SYNDROME_VALID), | |
110 | + &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]); | |
111 | + | |
112 | + /* wait for processing to complete */ | |
113 | + while ((readl(&elm_cfg->irqstatus) & (0x1 << poly)) != 0x1) | |
114 | + ; | |
115 | + /* clear status */ | |
116 | + writel((readl(&elm_cfg->irqstatus) | (0x1 << poly)), | |
117 | + &elm_cfg->irqstatus); | |
118 | + | |
119 | + /* check if correctable */ | |
120 | + location_status = readl(&elm_cfg->error_location[poly].location_status); | |
121 | + if (!(location_status & ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK)) | |
122 | + return -1; | |
123 | + | |
124 | + /* get error count */ | |
125 | + *error_count = readl(&elm_cfg->error_location[poly].location_status) & | |
126 | + ELM_LOCATION_STATUS_ECC_NB_ERRORS_MASK; | |
127 | + | |
128 | + for (i = 0; i < *error_count; i++) { | |
129 | + error_locations[i] = | |
130 | + readl(&elm_cfg->error_location[poly].error_location_x[i]); | |
131 | + } | |
132 | + | |
133 | + return 0; | |
134 | +} | |
135 | + | |
136 | + | |
137 | +/** | |
138 | + * elm_config - Configure ELM module | |
139 | + * @level: 4 / 8 / 16 bit BCH | |
140 | + * | |
141 | + * Configure ELM module based on BCH level. | |
142 | + * Set mode as continuous mode. | |
143 | + * Currently we are using only syndrome 0 and syndromes 1 to 6 are not used. | |
144 | + * Also, the mode is set only for syndrome 0 | |
145 | + */ | |
146 | +int elm_config(enum bch_level level) | |
147 | +{ | |
148 | + u32 val; | |
149 | + u8 poly = ELM_DEFAULT_POLY; | |
150 | + u32 buffer_size = 0x7FF; | |
151 | + | |
152 | + /* config size and level */ | |
153 | + val = (u32)(level) & ELM_LOCATION_CONFIG_ECC_BCH_LEVEL_MASK; | |
154 | + val |= ((buffer_size << ELM_LOCATION_CONFIG_ECC_SIZE_POS) & | |
155 | + ELM_LOCATION_CONFIG_ECC_SIZE_MASK); | |
156 | + writel(val, &elm_cfg->location_config); | |
157 | + | |
158 | + /* config continous mode */ | |
159 | + /* enable interrupt generation for syndrome polynomial set */ | |
160 | + writel((readl(&elm_cfg->irqenable) | (0x1 << poly)), | |
161 | + &elm_cfg->irqenable); | |
162 | + /* set continuous mode for the syndrome polynomial set */ | |
163 | + writel((readl(&elm_cfg->page_ctrl) & ~(0x1 << poly)), | |
164 | + &elm_cfg->page_ctrl); | |
165 | + | |
166 | + return 0; | |
167 | +} | |
168 | + | |
169 | +/** | |
170 | + * elm_reset - Do a soft reset of ELM | |
171 | + * | |
172 | + * Perform a soft reset of ELM and return after reset is done. | |
173 | + */ | |
174 | +void elm_reset(void) | |
175 | +{ | |
176 | + /* initiate reset */ | |
177 | + writel((readl(&elm_cfg->sysconfig) | ELM_SYSCONFIG_SOFTRESET), | |
178 | + &elm_cfg->sysconfig); | |
179 | + | |
180 | + /* wait for reset complete and normal operation */ | |
181 | + while ((readl(&elm_cfg->sysstatus) & ELM_SYSSTATUS_RESETDONE) != | |
182 | + ELM_SYSSTATUS_RESETDONE) | |
183 | + ; | |
184 | +} | |
185 | + | |
186 | +/** | |
187 | + * elm_init - Initialize ELM module | |
188 | + * | |
189 | + * Initialize ELM support. Currently it does only base address init | |
190 | + * and ELM reset. | |
191 | + */ | |
192 | +void elm_init(void) | |
193 | +{ | |
194 | + elm_cfg = (struct elm *)ELM_BASE; | |
195 | + elm_reset(); | |
196 | +} |
drivers/mtd/nand/omap_gpmc.c
... | ... | @@ -15,15 +15,13 @@ |
15 | 15 | #include <linux/bch.h> |
16 | 16 | #include <linux/compiler.h> |
17 | 17 | #include <nand.h> |
18 | -#ifdef CONFIG_AM33XX | |
19 | -#include <asm/arch/elm.h> | |
20 | -#endif | |
18 | +#include <asm/omap_elm.h> | |
21 | 19 | |
20 | +#define BADBLOCK_MARKER_LENGTH 2 | |
21 | +#define SECTOR_BYTES 512 | |
22 | + | |
22 | 23 | static uint8_t cs; |
23 | -static __maybe_unused struct nand_ecclayout hw_nand_oob = | |
24 | - GPMC_NAND_HW_ECC_LAYOUT; | |
25 | -static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob = | |
26 | - GPMC_NAND_HW_BCH8_ECC_LAYOUT; | |
24 | +static __maybe_unused struct nand_ecclayout omap_ecclayout; | |
27 | 25 | |
28 | 26 | /* |
29 | 27 | * omap_nand_hwcontrol - Set the address pointers corretly for the |
... | ... | @@ -233,6 +231,7 @@ |
233 | 231 | uint8_t type; |
234 | 232 | uint8_t nibbles; |
235 | 233 | struct bch_control *control; |
234 | + enum omap_ecc ecc_scheme; | |
236 | 235 | }; |
237 | 236 | |
238 | 237 | /* bch types */ |
239 | 238 | |
240 | 239 | |
... | ... | @@ -274,17 +273,15 @@ |
274 | 273 | { |
275 | 274 | uint32_t val; |
276 | 275 | uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1; |
277 | -#ifdef CONFIG_AM33XX | |
278 | 276 | uint32_t unused_length = 0; |
279 | -#endif | |
280 | 277 | uint32_t wr_mode = BCH_WRAPMODE_6; |
281 | 278 | struct nand_bch_priv *bch = chip->priv; |
282 | 279 | |
283 | 280 | /* Clear the ecc result registers, select ecc reg as 1 */ |
284 | 281 | writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control); |
285 | 282 | |
286 | -#ifdef CONFIG_AM33XX | |
287 | - wr_mode = BCH_WRAPMODE_1; | |
283 | + if (bch->ecc_scheme == OMAP_ECC_BCH8_CODE_HW) { | |
284 | + wr_mode = BCH_WRAPMODE_1; | |
288 | 285 | |
289 | 286 | switch (bch->nibbles) { |
290 | 287 | case ECC_BCH4_NIBBLES: |
... | ... | @@ -320,7 +317,7 @@ |
320 | 317 | val |= (unused_length << 22); |
321 | 318 | break; |
322 | 319 | } |
323 | -#else | |
320 | + } else { | |
324 | 321 | /* |
325 | 322 | * This ecc_size_config setting is for BCH sw library. |
326 | 323 | * |
... | ... | @@ -333,7 +330,7 @@ |
333 | 330 | * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) |
334 | 331 | */ |
335 | 332 | val = (32 << 22) | (0 << 12); |
336 | -#endif | |
333 | + } | |
337 | 334 | /* ecc size configuration */ |
338 | 335 | writel(val, &gpmc_cfg->ecc_size_config); |
339 | 336 | |
340 | 337 | |
... | ... | @@ -376,9 +373,9 @@ |
376 | 373 | } |
377 | 374 | |
378 | 375 | /* |
379 | - * BCH8 support (needs ELM and thus AM33xx-only) | |
376 | + * BCH support using ELM module | |
380 | 377 | */ |
381 | -#ifdef CONFIG_AM33XX | |
378 | +#ifdef CONFIG_NAND_OMAP_ELM | |
382 | 379 | /* |
383 | 380 | * omap_read_bch8_result - Read BCH result for BCH8 level |
384 | 381 | * |
385 | 382 | |
386 | 383 | |
387 | 384 | |
... | ... | @@ -631,20 +628,20 @@ |
631 | 628 | } |
632 | 629 | return 0; |
633 | 630 | } |
634 | -#endif /* CONFIG_AM33XX */ | |
631 | +#endif /* CONFIG_NAND_OMAP_ELM */ | |
635 | 632 | |
636 | 633 | /* |
637 | 634 | * OMAP3 BCH8 support (with BCH library) |
638 | 635 | */ |
639 | -#ifdef CONFIG_NAND_OMAP_BCH8 | |
636 | +#ifdef CONFIG_BCH | |
640 | 637 | /* |
641 | - * omap_calculate_ecc_bch - Read BCH ECC result | |
638 | + * omap_calculate_ecc_bch_sw - Read BCH ECC result | |
642 | 639 | * |
643 | 640 | * @mtd: MTD device structure |
644 | 641 | * @dat: The pointer to data on which ecc is computed (unused here) |
645 | 642 | * @ecc: The ECC output buffer |
646 | 643 | */ |
647 | -static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat, | |
644 | +static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, const uint8_t *dat, | |
648 | 645 | uint8_t *ecc) |
649 | 646 | { |
650 | 647 | int ret = 0; |
651 | 648 | |
... | ... | @@ -689,13 +686,13 @@ |
689 | 686 | } |
690 | 687 | |
691 | 688 | /** |
692 | - * omap_correct_data_bch - Decode received data and correct errors | |
689 | + * omap_correct_data_bch_sw - Decode received data and correct errors | |
693 | 690 | * @mtd: MTD device structure |
694 | 691 | * @data: page data |
695 | 692 | * @read_ecc: ecc read from nand flash |
696 | 693 | * @calc_ecc: ecc read from HW ECC registers |
697 | 694 | */ |
698 | -static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data, | |
695 | +static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data, | |
699 | 696 | u_char *read_ecc, u_char *calc_ecc) |
700 | 697 | { |
701 | 698 | int i, count; |
702 | 699 | |
... | ... | @@ -752,8 +749,151 @@ |
752 | 749 | chip_priv->control = NULL; |
753 | 750 | } |
754 | 751 | } |
755 | -#endif /* CONFIG_NAND_OMAP_BCH8 */ | |
752 | +#endif /* CONFIG_BCH */ | |
756 | 753 | |
754 | +/** | |
755 | + * omap_select_ecc_scheme - configures driver for particular ecc-scheme | |
756 | + * @nand: NAND chip device structure | |
757 | + * @ecc_scheme: ecc scheme to configure | |
758 | + * @pagesize: number of main-area bytes per page of NAND device | |
759 | + * @oobsize: number of OOB/spare bytes per page of NAND device | |
760 | + */ | |
761 | +static int omap_select_ecc_scheme(struct nand_chip *nand, | |
762 | + enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) { | |
763 | + struct nand_bch_priv *bch = nand->priv; | |
764 | + struct nand_ecclayout *ecclayout = nand->ecc.layout; | |
765 | + int eccsteps = pagesize / SECTOR_BYTES; | |
766 | + int i; | |
767 | + | |
768 | + switch (ecc_scheme) { | |
769 | + case OMAP_ECC_HAM1_CODE_SW: | |
770 | + debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n"); | |
771 | + /* For this ecc-scheme, ecc.bytes, ecc.layout, ... are | |
772 | + * initialized in nand_scan_tail(), so just set ecc.mode */ | |
773 | + bch_priv.control = NULL; | |
774 | + bch_priv.type = 0; | |
775 | + nand->ecc.mode = NAND_ECC_SOFT; | |
776 | + nand->ecc.layout = NULL; | |
777 | + nand->ecc.size = pagesize; | |
778 | + bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW; | |
779 | + break; | |
780 | + | |
781 | + case OMAP_ECC_HAM1_CODE_HW: | |
782 | + debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n"); | |
783 | + /* check ecc-scheme requirements before updating ecc info */ | |
784 | + if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) { | |
785 | + printf("nand: error: insufficient OOB: require=%d\n", ( | |
786 | + (3 * eccsteps) + BADBLOCK_MARKER_LENGTH)); | |
787 | + return -EINVAL; | |
788 | + } | |
789 | + bch_priv.control = NULL; | |
790 | + bch_priv.type = 0; | |
791 | + /* populate ecc specific fields */ | |
792 | + nand->ecc.mode = NAND_ECC_HW; | |
793 | + nand->ecc.strength = 1; | |
794 | + nand->ecc.size = SECTOR_BYTES; | |
795 | + nand->ecc.bytes = 3; | |
796 | + nand->ecc.hwctl = omap_enable_hwecc; | |
797 | + nand->ecc.correct = omap_correct_data; | |
798 | + nand->ecc.calculate = omap_calculate_ecc; | |
799 | + /* define ecc-layout */ | |
800 | + ecclayout->eccbytes = nand->ecc.bytes * eccsteps; | |
801 | + for (i = 0; i < ecclayout->eccbytes; i++) | |
802 | + ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH; | |
803 | + ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH; | |
804 | + ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes - | |
805 | + BADBLOCK_MARKER_LENGTH; | |
806 | + bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW; | |
807 | + break; | |
808 | + | |
809 | + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: | |
810 | +#ifdef CONFIG_BCH | |
811 | + debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n"); | |
812 | + /* check ecc-scheme requirements before updating ecc info */ | |
813 | + if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) { | |
814 | + printf("nand: error: insufficient OOB: require=%d\n", ( | |
815 | + (13 * eccsteps) + BADBLOCK_MARKER_LENGTH)); | |
816 | + return -EINVAL; | |
817 | + } | |
818 | + /* check if BCH S/W library can be used for error detection */ | |
819 | + bch_priv.control = init_bch(13, 8, 0x201b); | |
820 | + if (!bch_priv.control) { | |
821 | + printf("nand: error: could not init_bch()\n"); | |
822 | + return -ENODEV; | |
823 | + } | |
824 | + bch_priv.type = ECC_BCH8; | |
825 | + /* populate ecc specific fields */ | |
826 | + nand->ecc.mode = NAND_ECC_HW; | |
827 | + nand->ecc.strength = 8; | |
828 | + nand->ecc.size = SECTOR_BYTES; | |
829 | + nand->ecc.bytes = 13; | |
830 | + nand->ecc.hwctl = omap_enable_ecc_bch; | |
831 | + nand->ecc.correct = omap_correct_data_bch_sw; | |
832 | + nand->ecc.calculate = omap_calculate_ecc_bch_sw; | |
833 | + /* define ecc-layout */ | |
834 | + ecclayout->eccbytes = nand->ecc.bytes * eccsteps; | |
835 | + ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; | |
836 | + for (i = 1; i < ecclayout->eccbytes; i++) { | |
837 | + if (i % nand->ecc.bytes) | |
838 | + ecclayout->eccpos[i] = | |
839 | + ecclayout->eccpos[i - 1] + 1; | |
840 | + else | |
841 | + ecclayout->eccpos[i] = | |
842 | + ecclayout->eccpos[i - 1] + 2; | |
843 | + } | |
844 | + ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH; | |
845 | + ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes - | |
846 | + BADBLOCK_MARKER_LENGTH; | |
847 | + omap_hwecc_init_bch(nand, NAND_ECC_READ); | |
848 | + bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; | |
849 | + break; | |
850 | +#else | |
851 | + printf("nand: error: CONFIG_BCH required for ECC\n"); | |
852 | + return -EINVAL; | |
853 | +#endif | |
854 | + | |
855 | + case OMAP_ECC_BCH8_CODE_HW: | |
856 | +#ifdef CONFIG_NAND_OMAP_ELM | |
857 | + debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n"); | |
858 | + /* check ecc-scheme requirements before updating ecc info */ | |
859 | + if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) { | |
860 | + printf("nand: error: insufficient OOB: require=%d\n", ( | |
861 | + (14 * eccsteps) + BADBLOCK_MARKER_LENGTH)); | |
862 | + return -EINVAL; | |
863 | + } | |
864 | + /* intialize ELM for ECC error detection */ | |
865 | + elm_init(); | |
866 | + bch_priv.type = ECC_BCH8; | |
867 | + /* populate ecc specific fields */ | |
868 | + nand->ecc.mode = NAND_ECC_HW; | |
869 | + nand->ecc.strength = 8; | |
870 | + nand->ecc.size = SECTOR_BYTES; | |
871 | + nand->ecc.bytes = 14; | |
872 | + nand->ecc.hwctl = omap_enable_ecc_bch; | |
873 | + nand->ecc.correct = omap_correct_data_bch; | |
874 | + nand->ecc.calculate = omap_calculate_ecc_bch; | |
875 | + nand->ecc.read_page = omap_read_page_bch; | |
876 | + /* define ecc-layout */ | |
877 | + ecclayout->eccbytes = nand->ecc.bytes * eccsteps; | |
878 | + for (i = 0; i < ecclayout->eccbytes; i++) | |
879 | + ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH; | |
880 | + ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH; | |
881 | + ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes - | |
882 | + BADBLOCK_MARKER_LENGTH; | |
883 | + bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW; | |
884 | + break; | |
885 | +#else | |
886 | + printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n"); | |
887 | + return -EINVAL; | |
888 | +#endif | |
889 | + | |
890 | + default: | |
891 | + debug("nand: error: ecc scheme not enabled or supported\n"); | |
892 | + return -EINVAL; | |
893 | + } | |
894 | + return 0; | |
895 | +} | |
896 | + | |
757 | 897 | #ifndef CONFIG_SPL_BUILD |
758 | 898 | /* |
759 | 899 | * omap_nand_switch_ecc - switch the ECC operation between different engines |
760 | 900 | |
761 | 901 | |
762 | 902 | |
763 | 903 | |
764 | 904 | |
765 | 905 | |
766 | 906 | |
767 | 907 | |
... | ... | @@ -763,77 +903,45 @@ |
763 | 903 | * @eccstrength - the number of bits that could be corrected |
764 | 904 | * (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16) |
765 | 905 | */ |
766 | -void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength) | |
906 | +int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength) | |
767 | 907 | { |
768 | 908 | struct nand_chip *nand; |
769 | 909 | struct mtd_info *mtd; |
910 | + int err = 0; | |
770 | 911 | |
771 | 912 | if (nand_curr_device < 0 || |
772 | 913 | nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || |
773 | 914 | !nand_info[nand_curr_device].name) { |
774 | - printf("Error: Can't switch ecc, no devices available\n"); | |
775 | - return; | |
915 | + printf("nand: error: no NAND devices found\n"); | |
916 | + return -ENODEV; | |
776 | 917 | } |
777 | 918 | |
778 | 919 | mtd = &nand_info[nand_curr_device]; |
779 | 920 | nand = mtd->priv; |
780 | - | |
781 | 921 | nand->options |= NAND_OWN_BUFFERS; |
782 | - | |
783 | - /* Reset ecc interface */ | |
784 | - nand->ecc.mode = NAND_ECC_NONE; | |
785 | - nand->ecc.read_page = NULL; | |
786 | - nand->ecc.write_page = NULL; | |
787 | - nand->ecc.read_oob = NULL; | |
788 | - nand->ecc.write_oob = NULL; | |
789 | - nand->ecc.hwctl = NULL; | |
790 | - nand->ecc.correct = NULL; | |
791 | - nand->ecc.calculate = NULL; | |
792 | - nand->ecc.strength = eccstrength; | |
793 | - | |
794 | 922 | /* Setup the ecc configurations again */ |
795 | 923 | if (hardware) { |
796 | 924 | if (eccstrength == 1) { |
797 | - nand->ecc.mode = NAND_ECC_HW; | |
798 | - nand->ecc.layout = &hw_nand_oob; | |
799 | - nand->ecc.size = 512; | |
800 | - nand->ecc.bytes = 3; | |
801 | - nand->ecc.hwctl = omap_enable_hwecc; | |
802 | - nand->ecc.correct = omap_correct_data; | |
803 | - nand->ecc.calculate = omap_calculate_ecc; | |
804 | - omap_hwecc_init(nand); | |
805 | - printf("1-bit hamming HW ECC selected\n"); | |
925 | + err = omap_select_ecc_scheme(nand, | |
926 | + OMAP_ECC_HAM1_CODE_HW, | |
927 | + mtd->writesize, mtd->oobsize); | |
928 | + } else if (eccstrength == 8) { | |
929 | + err = omap_select_ecc_scheme(nand, | |
930 | + OMAP_ECC_BCH8_CODE_HW, | |
931 | + mtd->writesize, mtd->oobsize); | |
932 | + } else { | |
933 | + printf("nand: error: unsupported ECC scheme\n"); | |
934 | + return -EINVAL; | |
806 | 935 | } |
807 | -#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8) | |
808 | - else if (eccstrength == 8) { | |
809 | - nand->ecc.mode = NAND_ECC_HW; | |
810 | - nand->ecc.layout = &hw_bch8_nand_oob; | |
811 | - nand->ecc.size = 512; | |
812 | -#ifdef CONFIG_AM33XX | |
813 | - nand->ecc.bytes = 14; | |
814 | - nand->ecc.read_page = omap_read_page_bch; | |
815 | -#else | |
816 | - nand->ecc.bytes = 13; | |
817 | -#endif | |
818 | - nand->ecc.hwctl = omap_enable_ecc_bch; | |
819 | - nand->ecc.correct = omap_correct_data_bch; | |
820 | - nand->ecc.calculate = omap_calculate_ecc_bch; | |
821 | - omap_hwecc_init_bch(nand, NAND_ECC_READ); | |
822 | - printf("8-bit BCH HW ECC selected\n"); | |
823 | - } | |
824 | -#endif | |
825 | 936 | } else { |
826 | - nand->ecc.mode = NAND_ECC_SOFT; | |
827 | - /* Use mtd default settings */ | |
828 | - nand->ecc.layout = NULL; | |
829 | - nand->ecc.size = 0; | |
830 | - printf("SW ECC selected\n"); | |
937 | + err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW, | |
938 | + mtd->writesize, mtd->oobsize); | |
831 | 939 | } |
832 | 940 | |
833 | 941 | /* Update NAND handling after ECC mode switch */ |
834 | - nand_scan_tail(mtd); | |
835 | - | |
836 | - nand->options &= ~NAND_OWN_BUFFERS; | |
942 | + if (!err) | |
943 | + err = nand_scan_tail(mtd); | |
944 | + return err; | |
837 | 945 | } |
838 | 946 | #endif /* CONFIG_SPL_BUILD */ |
839 | 947 | |
... | ... | @@ -856,7 +964,7 @@ |
856 | 964 | { |
857 | 965 | int32_t gpmc_config = 0; |
858 | 966 | cs = 0; |
859 | - | |
967 | + int err = 0; | |
860 | 968 | /* |
861 | 969 | * xloader/Uboot's gpmc configuration would have configured GPMC for |
862 | 970 | * nand type of memory. The following logic scans and latches on to the |
... | ... | @@ -873,7 +981,7 @@ |
873 | 981 | cs++; |
874 | 982 | } |
875 | 983 | if (cs >= GPMC_MAX_CS) { |
876 | - printf("NAND: Unable to find NAND settings in " | |
984 | + printf("nand: error: Unable to find NAND settings in " | |
877 | 985 | "GPMC Configuration - quitting\n"); |
878 | 986 | return -ENODEV; |
879 | 987 | } |
880 | 988 | |
881 | 989 | |
882 | 990 | |
883 | 991 | |
... | ... | @@ -885,64 +993,27 @@ |
885 | 993 | |
886 | 994 | nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat; |
887 | 995 | nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd; |
888 | - | |
889 | - nand->cmd_ctrl = omap_nand_hwcontrol; | |
890 | - nand->options = NAND_NO_PADDING | NAND_CACHEPRG; | |
996 | + nand->priv = &bch_priv; | |
997 | + nand->cmd_ctrl = omap_nand_hwcontrol; | |
998 | + nand->options |= NAND_NO_PADDING | NAND_CACHEPRG; | |
891 | 999 | /* If we are 16 bit dev, our gpmc config tells us that */ |
892 | 1000 | if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000) |
893 | 1001 | nand->options |= NAND_BUSWIDTH_16; |
894 | 1002 | |
895 | 1003 | nand->chip_delay = 100; |
1004 | + nand->ecc.layout = &omap_ecclayout; | |
896 | 1005 | |
897 | -#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8) | |
898 | -#ifdef CONFIG_AM33XX | |
899 | - /* AM33xx uses the ELM */ | |
900 | - /* required in case of BCH */ | |
901 | - elm_init(); | |
1006 | + /* select ECC scheme */ | |
1007 | +#if defined(CONFIG_NAND_OMAP_ECCSCHEME) | |
1008 | + err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME, | |
1009 | + CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE); | |
902 | 1010 | #else |
903 | - /* | |
904 | - * Whereas other OMAP based SoC do not have the ELM, they use the BCH | |
905 | - * SW library. | |
906 | - */ | |
907 | - bch_priv.control = init_bch(13, 8, 0x201b /* hw polynominal */); | |
908 | - if (!bch_priv.control) { | |
909 | - puts("Could not init_bch()\n"); | |
910 | - return -ENODEV; | |
911 | - } | |
1011 | + /* pagesize and oobsize are not required to configure sw ecc-scheme */ | |
1012 | + err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW, | |
1013 | + 0, 0); | |
912 | 1014 | #endif |
913 | - /* BCH info that will be correct for SPL or overridden otherwise. */ | |
914 | - nand->priv = &bch_priv; | |
915 | -#endif | |
916 | - | |
917 | - /* Default ECC mode */ | |
918 | -#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8) | |
919 | - nand->ecc.mode = NAND_ECC_HW; | |
920 | - nand->ecc.layout = &hw_bch8_nand_oob; | |
921 | - nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; | |
922 | - nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; | |
923 | - nand->ecc.strength = 8; | |
924 | - nand->ecc.hwctl = omap_enable_ecc_bch; | |
925 | - nand->ecc.correct = omap_correct_data_bch; | |
926 | - nand->ecc.calculate = omap_calculate_ecc_bch; | |
927 | -#ifdef CONFIG_AM33XX | |
928 | - nand->ecc.read_page = omap_read_page_bch; | |
929 | -#endif | |
930 | - omap_hwecc_init_bch(nand, NAND_ECC_READ); | |
931 | -#else | |
932 | -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC) | |
933 | - nand->ecc.mode = NAND_ECC_SOFT; | |
934 | -#else | |
935 | - nand->ecc.mode = NAND_ECC_HW; | |
936 | - nand->ecc.layout = &hw_nand_oob; | |
937 | - nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; | |
938 | - nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; | |
939 | - nand->ecc.hwctl = omap_enable_hwecc; | |
940 | - nand->ecc.correct = omap_correct_data; | |
941 | - nand->ecc.calculate = omap_calculate_ecc; | |
942 | - nand->ecc.strength = 1; | |
943 | - omap_hwecc_init(nand); | |
944 | -#endif | |
945 | -#endif | |
1015 | + if (err) | |
1016 | + return err; | |
946 | 1017 | |
947 | 1018 | #ifdef CONFIG_SPL_BUILD |
948 | 1019 | if (nand->options & NAND_BUSWIDTH_16) |
drivers/mtd/onenand/onenand_base.c
... | ... | @@ -761,7 +761,8 @@ |
761 | 761 | uint8_t *oob_buf = this->oob_buf; |
762 | 762 | |
763 | 763 | free = this->ecclayout->oobfree; |
764 | - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { | |
764 | + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length; | |
765 | + i++, free++) { | |
765 | 766 | if (readcol >= lastgap) |
766 | 767 | readcol += free->offset - lastgap; |
767 | 768 | if (readend >= lastgap) |
... | ... | @@ -770,7 +771,8 @@ |
770 | 771 | } |
771 | 772 | this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); |
772 | 773 | free = this->ecclayout->oobfree; |
773 | - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { | |
774 | + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length; | |
775 | + i++, free++) { | |
774 | 776 | int free_end = free->offset + free->length; |
775 | 777 | if (free->offset < readend && free_end > readcol) { |
776 | 778 | int st = max_t(int,free->offset,readcol); |
... | ... | @@ -1356,7 +1358,8 @@ |
1356 | 1358 | unsigned int i; |
1357 | 1359 | |
1358 | 1360 | free = this->ecclayout->oobfree; |
1359 | - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { | |
1361 | + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length; | |
1362 | + i++, free++) { | |
1360 | 1363 | if (writecol >= lastgap) |
1361 | 1364 | writecol += free->offset - lastgap; |
1362 | 1365 | if (writeend >= lastgap) |
... | ... | @@ -1364,7 +1367,8 @@ |
1364 | 1367 | lastgap = free->offset + free->length; |
1365 | 1368 | } |
1366 | 1369 | free = this->ecclayout->oobfree; |
1367 | - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { | |
1370 | + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length; | |
1371 | + i++, free++) { | |
1368 | 1372 | int free_end = free->offset + free->length; |
1369 | 1373 | if (free->offset < writeend && free_end > writecol) { |
1370 | 1374 | int st = max_t(int,free->offset,writecol); |
... | ... | @@ -2750,7 +2754,8 @@ |
2750 | 2754 | * the out of band area |
2751 | 2755 | */ |
2752 | 2756 | this->ecclayout->oobavail = 0; |
2753 | - for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && | |
2757 | + | |
2758 | + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && | |
2754 | 2759 | this->ecclayout->oobfree[i].length; i++) |
2755 | 2760 | this->ecclayout->oobavail += |
2756 | 2761 | this->ecclayout->oobfree[i].length; |
include/configs/ASH405.h
... | ... | @@ -143,6 +143,8 @@ |
143 | 143 | |
144 | 144 | #define CONFIG_SYS_NAND_SKIP_BAD_DOT_I 1 /* ".i" read skips bad blocks */ |
145 | 145 | #define CONFIG_SYS_NAND_QUIET 1 |
146 | +#define CONFIG_SYS_NAND_MAX_OOBFREE 2 | |
147 | +#define CONFIG_SYS_NAND_MAX_ECCPOS 56 | |
146 | 148 | |
147 | 149 | /*----------------------------------------------------------------------- |
148 | 150 | * PCI stuff |
include/configs/C29XPCIE.h
... | ... | @@ -191,13 +191,14 @@ |
191 | 191 | | CSPR_MSEL_NAND \ |
192 | 192 | | CSPR_V) |
193 | 193 | #define CONFIG_SYS_NAND_AMASK IFC_AMASK(64*1024) |
194 | +#define CONFIG_SYS_NAND_OOBSIZE 0x00000280 /* 640b */ | |
194 | 195 | #define CONFIG_SYS_NAND_CSOR (CSOR_NAND_ECC_ENC_EN /* ECC on encode */ \ |
195 | 196 | | CSOR_NAND_ECC_DEC_EN /* ECC on decode */ \ |
196 | 197 | | CSOR_NAND_ECC_MODE_4 /* 4-bit ECC */ \ |
197 | - | CSOR_NAND_RAL_2 /* RAL = 2 Bytes */ \ | |
198 | - | CSOR_NAND_PGS_2K /* Page Size = 2k */ \ | |
199 | - | CSOR_NAND_SPRZ_64 /* Spare size = 64 */ \ | |
200 | - | CSOR_NAND_PB(64)) /* 64 Pages Per Block */ | |
198 | + | CSOR_NAND_RAL_3 /* RAL = 3 Bytes */ \ | |
199 | + | CSOR_NAND_PGS_8K /* Page Size = 8K */ \ | |
200 | + | CSOR_NAND_SPRZ_CSOR_EXT /*oob in csor_ext*/\ | |
201 | + | CSOR_NAND_PB(128)) /*128 Pages Per Block*/ | |
201 | 202 | #define CONFIG_SYS_NAND_FTIM0 (FTIM0_NAND_TCCST(0x01) | \ |
202 | 203 | FTIM0_NAND_TWP(0x0c) | \ |
203 | 204 | FTIM0_NAND_TWCHT(0x08) | \ |
... | ... | @@ -224,6 +225,7 @@ |
224 | 225 | #define CONFIG_SYS_CSPR1 CONFIG_SYS_NAND_CSPR |
225 | 226 | #define CONFIG_SYS_AMASK1 CONFIG_SYS_NAND_AMASK |
226 | 227 | #define CONFIG_SYS_CSOR1 CONFIG_SYS_NAND_CSOR |
228 | +#define CONFIG_SYS_CSOR1_EXT CONFIG_SYS_NAND_OOBSIZE | |
227 | 229 | #define CONFIG_SYS_CS1_FTIM0 CONFIG_SYS_NAND_FTIM0 |
228 | 230 | #define CONFIG_SYS_CS1_FTIM1 CONFIG_SYS_NAND_FTIM1 |
229 | 231 | #define CONFIG_SYS_CS1_FTIM2 CONFIG_SYS_NAND_FTIM2 |
include/configs/MPC8572DS.h
... | ... | @@ -322,6 +322,8 @@ |
322 | 322 | #define CONFIG_CMD_NAND 1 |
323 | 323 | #define CONFIG_NAND_FSL_ELBC 1 |
324 | 324 | #define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024) |
325 | +#define CONFIG_SYS_NAND_MAX_OOBFREE 5 | |
326 | +#define CONFIG_SYS_NAND_MAX_ECCPOS 56 | |
325 | 327 | |
326 | 328 | /* NAND boot: 4K NAND loader config */ |
327 | 329 | #define CONFIG_SYS_NAND_SPL_SIZE 0x1000 |
include/configs/T4240QDS.h
... | ... | @@ -229,6 +229,8 @@ |
229 | 229 | #define CONFIG_CMD_NAND |
230 | 230 | |
231 | 231 | #define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024) |
232 | +#define CONFIG_SYS_NAND_MAX_OOBFREE 2 | |
233 | +#define CONFIG_SYS_NAND_MAX_ECCPOS 256 | |
232 | 234 | |
233 | 235 | #if defined(CONFIG_NAND) |
234 | 236 | #define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NAND_CSPR_EXT |
include/configs/alpr.h
... | ... | @@ -324,6 +324,8 @@ |
324 | 324 | #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE + 0, CONFIG_SYS_NAND_BASE + 2, \ |
325 | 325 | CONFIG_SYS_NAND_BASE + 4, CONFIG_SYS_NAND_BASE + 6 } |
326 | 326 | #define CONFIG_SYS_NAND_QUIET_TEST 1 /* don't warn upon unknown NAND flash */ |
327 | +#define CONFIG_SYS_NAND_MAX_OOBFREE 2 | |
328 | +#define CONFIG_SYS_NAND_MAX_ECCPOS 56 | |
327 | 329 | |
328 | 330 | /*----------------------------------------------------------------------- |
329 | 331 | * External Bus Controller (EBC) Setup |
include/configs/am335x_evm.h
... | ... | @@ -220,6 +220,8 @@ |
220 | 220 | #define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/am33xx/u-boot-spl.lds" |
221 | 221 | |
222 | 222 | #ifdef CONFIG_NAND |
223 | +#define CONFIG_NAND_OMAP_GPMC | |
224 | +#define CONFIG_NAND_OMAP_ELM | |
223 | 225 | #define CONFIG_SYS_NAND_5_ADDR_CYCLE |
224 | 226 | #define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \ |
225 | 227 | CONFIG_SYS_NAND_PAGE_SIZE) |
... | ... | @@ -237,7 +239,8 @@ |
237 | 239 | |
238 | 240 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
239 | 241 | #define CONFIG_SYS_NAND_ECCBYTES 14 |
240 | - | |
242 | +#define CONFIG_SYS_NAND_ONFI_DETECTION | |
243 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW | |
241 | 244 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
242 | 245 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
243 | 246 | #endif |
include/configs/am335x_igep0033.h
... | ... | @@ -187,6 +187,7 @@ |
187 | 187 | /* NAND support */ |
188 | 188 | #define CONFIG_NAND |
189 | 189 | #define CONFIG_NAND_OMAP_GPMC |
190 | +#define CONFIG_NAND_OMAP_ELM | |
190 | 191 | #define GPMC_NAND_ECC_LP_x16_LAYOUT 1 |
191 | 192 | #define CONFIG_SYS_NAND_BASE (0x08000000) /* phys address CS0 */ |
192 | 193 | #define CONFIG_SYS_MAX_NAND_DEVICE 1 |
... | ... | @@ -263,6 +264,7 @@ |
263 | 264 | |
264 | 265 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
265 | 266 | #define CONFIG_SYS_NAND_ECCBYTES 14 |
267 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW | |
266 | 268 | |
267 | 269 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
268 | 270 |
include/configs/am3517_crane.h
... | ... | @@ -340,6 +340,7 @@ |
340 | 340 | 10, 11, 12, 13} |
341 | 341 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
342 | 342 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
343 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW | |
343 | 344 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
344 | 345 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
345 | 346 |
include/configs/am3517_evm.h
... | ... | @@ -334,6 +334,7 @@ |
334 | 334 | 10, 11, 12, 13} |
335 | 335 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
336 | 336 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
337 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW | |
337 | 338 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
338 | 339 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
339 | 340 |
include/configs/devkit8000.h
include/configs/mcx.h
... | ... | @@ -353,7 +353,6 @@ |
353 | 353 | #define CONFIG_SPL_FRAMEWORK |
354 | 354 | #define CONFIG_SPL_BOARD_INIT |
355 | 355 | #define CONFIG_SPL_NAND_SIMPLE |
356 | -#define CONFIG_SPL_NAND_SOFTECC | |
357 | 356 | |
358 | 357 | #define CONFIG_SPL_LIBCOMMON_SUPPORT |
359 | 358 | #define CONFIG_SPL_LIBDISK_SUPPORT |
... | ... | @@ -395,6 +394,7 @@ |
395 | 394 | 56, 57, 58, 59, 60, 61, 62, 63} |
396 | 395 | #define CONFIG_SYS_NAND_ECCSIZE 256 |
397 | 396 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
397 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_SW | |
398 | 398 | |
399 | 399 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
400 | 400 |
include/configs/omap3_beagle.h
... | ... | @@ -431,6 +431,7 @@ |
431 | 431 | 10, 11, 12, 13} |
432 | 432 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
433 | 433 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
434 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW | |
434 | 435 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
435 | 436 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
436 | 437 |
include/configs/omap3_evm.h
... | ... | @@ -107,6 +107,7 @@ |
107 | 107 | 10, 11, 12, 13} |
108 | 108 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
109 | 109 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
110 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW | |
110 | 111 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
111 | 112 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
112 | 113 |
include/configs/omap3_evm_quick_nand.h
... | ... | @@ -86,6 +86,7 @@ |
86 | 86 | 10, 11, 12, 13} |
87 | 87 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
88 | 88 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
89 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW | |
89 | 90 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
90 | 91 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
91 | 92 |
include/configs/omap3_igep00x0.h
... | ... | @@ -362,6 +362,7 @@ |
362 | 362 | 10, 11, 12, 13} |
363 | 363 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
364 | 364 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
365 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW | |
365 | 366 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
366 | 367 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
367 | 368 | #endif |
include/configs/omap3_overo.h
... | ... | @@ -324,6 +324,7 @@ |
324 | 324 | 10, 11, 12, 13} |
325 | 325 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
326 | 326 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
327 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW | |
327 | 328 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
328 | 329 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
329 | 330 |
include/configs/siemens-am33x-common.h
... | ... | @@ -195,6 +195,7 @@ |
195 | 195 | |
196 | 196 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
197 | 197 | #define CONFIG_SYS_NAND_ECCBYTES 14 |
198 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW | |
198 | 199 | |
199 | 200 | #define CONFIG_SYS_NAND_ECCSTEPS 4 |
200 | 201 | #define CONFIG_SYS_NAND_ECCTOTAL (CONFIG_SYS_NAND_ECCBYTES * \ |
... | ... | @@ -430,6 +431,7 @@ |
430 | 431 | "\0" |
431 | 432 | |
432 | 433 | #define CONFIG_NAND_OMAP_GPMC |
434 | +#define CONFIG_NAND_OMAP_ELM | |
433 | 435 | #define GPMC_NAND_ECC_LP_x16_LAYOUT 1 |
434 | 436 | #define CONFIG_SYS_NAND_BASE (0x08000000) /* physical address */ |
435 | 437 | /* to access nand at */ |
include/configs/tam3517-common.h
... | ... | @@ -224,7 +224,6 @@ |
224 | 224 | #define CONFIG_SPL_BOARD_INIT |
225 | 225 | #define CONFIG_SPL_CONSOLE |
226 | 226 | #define CONFIG_SPL_NAND_SIMPLE |
227 | -#define CONFIG_SPL_NAND_SOFTECC | |
228 | 227 | #define CONFIG_SPL_NAND_WORKSPACE 0x8f07f000 /* below BSS */ |
229 | 228 | |
230 | 229 | #define CONFIG_SPL_LIBCOMMON_SUPPORT |
... | ... | @@ -261,6 +260,7 @@ |
261 | 260 | 56, 57, 58, 59, 60, 61, 62, 63} |
262 | 261 | #define CONFIG_SYS_NAND_ECCSIZE 256 |
263 | 262 | #define CONFIG_SYS_NAND_ECCBYTES 3 |
263 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_SW | |
264 | 264 | |
265 | 265 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
266 | 266 |
include/configs/tricorder.h
... | ... | @@ -138,8 +138,9 @@ |
138 | 138 | |
139 | 139 | #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND */ |
140 | 140 | /* devices */ |
141 | -#define CONFIG_NAND_OMAP_BCH8 | |
142 | 141 | #define CONFIG_BCH |
142 | +#define CONFIG_SYS_NAND_MAX_OOBFREE 2 | |
143 | +#define CONFIG_SYS_NAND_MAX_ECCPOS 56 | |
143 | 144 | |
144 | 145 | /* commands to include */ |
145 | 146 | #include <config_cmd_default.h> |
... | ... | @@ -374,6 +375,7 @@ |
374 | 375 | |
375 | 376 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
376 | 377 | #define CONFIG_SYS_NAND_ECCBYTES 13 |
378 | +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW_DETECTION_SW | |
377 | 379 | |
378 | 380 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
379 | 381 |
include/linux/mtd/mtd.h
... | ... | @@ -96,6 +96,29 @@ |
96 | 96 | uint8_t *oobbuf; |
97 | 97 | }; |
98 | 98 | |
99 | +#ifdef CONFIG_SYS_NAND_MAX_OOBFREE | |
100 | +#define MTD_MAX_OOBFREE_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_OOBFREE | |
101 | +#else | |
102 | +#define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 | |
103 | +#endif | |
104 | + | |
105 | +#ifdef CONFIG_SYS_NAND_MAX_ECCPOS | |
106 | +#define MTD_MAX_ECCPOS_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_ECCPOS | |
107 | +#else | |
108 | +#define MTD_MAX_ECCPOS_ENTRIES_LARGE 640 | |
109 | +#endif | |
110 | + | |
111 | +/* | |
112 | + * ECC layout control structure. Exported to userspace for | |
113 | + * diagnosis and to allow creation of raw images | |
114 | + */ | |
115 | +struct nand_ecclayout { | |
116 | + uint32_t eccbytes; | |
117 | + uint32_t eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; | |
118 | + uint32_t oobavail; | |
119 | + struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; | |
120 | +}; | |
121 | + | |
99 | 122 | struct mtd_info { |
100 | 123 | u_char type; |
101 | 124 | u_int32_t flags; |
include/mtd/mtd-abi.h
... | ... | @@ -155,18 +155,6 @@ |
155 | 155 | uint32_t length; |
156 | 156 | }; |
157 | 157 | |
158 | -#define MTD_MAX_OOBFREE_ENTRIES 8 | |
159 | -/* | |
160 | - * ECC layout control structure. Exported to userspace for | |
161 | - * diagnosis and to allow creation of raw images | |
162 | - */ | |
163 | -struct nand_ecclayout { | |
164 | - uint32_t eccbytes; | |
165 | - uint32_t eccpos[128]; | |
166 | - uint32_t oobavail; | |
167 | - struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; | |
168 | -}; | |
169 | - | |
170 | 158 | /** |
171 | 159 | * struct mtd_ecc_stats - error correction stats |
172 | 160 | * |