Commit 66bfbd2c5b35dc81edce0c24843c476161ab5978

Authored by Philip, Avinash
1 parent 370630359c
Exists in master

arm:omap:am33xx - GPMC timings

Default timing causes issues with OOB data corruption on reading and
causes UBIFS torture test. To resolve the above issue, NAND was tested
with different timings and optimal timings were adapted after repeated
tests and trials.

Signed-off-by: Philip, Avinash <avinashphilip@ti.com>

Showing 1 changed file with 26 additions and 2 deletions Inline Diff

arch/arm/mach-omap2/board-flash.c
1 /* 1 /*
2 * board-flash.c 2 * board-flash.c
3 * Modified from mach-omap2/board-3430sdp-flash.c 3 * Modified from mach-omap2/board-3430sdp-flash.c
4 * 4 *
5 * Copyright (C) 2009 Nokia Corporation 5 * Copyright (C) 2009 Nokia Corporation
6 * Copyright (C) 2009 Texas Instruments 6 * Copyright (C) 2009 Texas Instruments
7 * 7 *
8 * Vimal Singh <vimalsingh@ti.com> 8 * Vimal Singh <vimalsingh@ti.com>
9 * 9 *
10 * 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
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15 #include <linux/kernel.h> 15 #include <linux/kernel.h>
16 #include <linux/platform_device.h> 16 #include <linux/platform_device.h>
17 #include <linux/mtd/physmap.h> 17 #include <linux/mtd/physmap.h>
18 #include <linux/io.h> 18 #include <linux/io.h>
19 #include <plat/irqs.h> 19 #include <plat/irqs.h>
20 20
21 #include <plat/gpmc.h> 21 #include <plat/gpmc.h>
22 #include <plat/nand.h> 22 #include <plat/nand.h>
23 #include <plat/onenand.h> 23 #include <plat/onenand.h>
24 #include <plat/tc.h> 24 #include <plat/tc.h>
25 25
26 #include "board-flash.h" 26 #include "board-flash.h"
27 27
28 #define REG_FPGA_REV 0x10 28 #define REG_FPGA_REV 0x10
29 #define REG_FPGA_DIP_SWITCH_INPUT2 0x60 29 #define REG_FPGA_DIP_SWITCH_INPUT2 0x60
30 #define MAX_SUPPORTED_GPMC_CONFIG 3 30 #define MAX_SUPPORTED_GPMC_CONFIG 3
31 31
32 #define DEBUG_BASE 0x08000000 /* debug board */ 32 #define DEBUG_BASE 0x08000000 /* debug board */
33 33
34 /* various memory sizes */ 34 /* various memory sizes */
35 #define FLASH_SIZE_SDPV1 SZ_64M /* NOR flash (64 Meg aligned) */ 35 #define FLASH_SIZE_SDPV1 SZ_64M /* NOR flash (64 Meg aligned) */
36 #define FLASH_SIZE_SDPV2 SZ_128M /* NOR flash (256 Meg aligned) */ 36 #define FLASH_SIZE_SDPV2 SZ_128M /* NOR flash (256 Meg aligned) */
37 37
38 static struct physmap_flash_data board_nor_data = { 38 static struct physmap_flash_data board_nor_data = {
39 .width = 2, 39 .width = 2,
40 }; 40 };
41 41
42 static struct resource board_nor_resource = { 42 static struct resource board_nor_resource = {
43 .flags = IORESOURCE_MEM, 43 .flags = IORESOURCE_MEM,
44 }; 44 };
45 45
46 static struct platform_device board_nor_device = { 46 static struct platform_device board_nor_device = {
47 .name = "physmap-flash", 47 .name = "physmap-flash",
48 .id = 0, 48 .id = 0,
49 .dev = { 49 .dev = {
50 .platform_data = &board_nor_data, 50 .platform_data = &board_nor_data,
51 }, 51 },
52 .num_resources = 1, 52 .num_resources = 1,
53 .resource = &board_nor_resource, 53 .resource = &board_nor_resource,
54 }; 54 };
55 55
56 static void 56 static void
57 __init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) 57 __init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
58 { 58 {
59 int err; 59 int err;
60 60
61 board_nor_data.parts = nor_parts; 61 board_nor_data.parts = nor_parts;
62 board_nor_data.nr_parts = nr_parts; 62 board_nor_data.nr_parts = nr_parts;
63 63
64 /* Configure start address and size of NOR device */ 64 /* Configure start address and size of NOR device */
65 if (omap_rev() >= OMAP3430_REV_ES1_0) { 65 if (omap_rev() >= OMAP3430_REV_ES1_0) {
66 err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1, 66 err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1,
67 (unsigned long *)&board_nor_resource.start); 67 (unsigned long *)&board_nor_resource.start);
68 board_nor_resource.end = board_nor_resource.start 68 board_nor_resource.end = board_nor_resource.start
69 + FLASH_SIZE_SDPV2 - 1; 69 + FLASH_SIZE_SDPV2 - 1;
70 } else { 70 } else {
71 err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1, 71 err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1,
72 (unsigned long *)&board_nor_resource.start); 72 (unsigned long *)&board_nor_resource.start);
73 board_nor_resource.end = board_nor_resource.start 73 board_nor_resource.end = board_nor_resource.start
74 + FLASH_SIZE_SDPV1 - 1; 74 + FLASH_SIZE_SDPV1 - 1;
75 } 75 }
76 if (err < 0) { 76 if (err < 0) {
77 pr_err("NOR: Can't request GPMC CS\n"); 77 pr_err("NOR: Can't request GPMC CS\n");
78 return; 78 return;
79 } 79 }
80 if (platform_device_register(&board_nor_device) < 0) 80 if (platform_device_register(&board_nor_device) < 0)
81 pr_err("Unable to register NOR device\n"); 81 pr_err("Unable to register NOR device\n");
82 } 82 }
83 83
84 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \ 84 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
85 defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) 85 defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
86 static struct omap_onenand_platform_data board_onenand_data = { 86 static struct omap_onenand_platform_data board_onenand_data = {
87 .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */ 87 .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */
88 }; 88 };
89 89
90 static void 90 static void
91 __init board_onenand_init(struct mtd_partition *onenand_parts, 91 __init board_onenand_init(struct mtd_partition *onenand_parts,
92 u8 nr_parts, u8 cs) 92 u8 nr_parts, u8 cs)
93 { 93 {
94 board_onenand_data.cs = cs; 94 board_onenand_data.cs = cs;
95 board_onenand_data.parts = onenand_parts; 95 board_onenand_data.parts = onenand_parts;
96 board_onenand_data.nr_parts = nr_parts; 96 board_onenand_data.nr_parts = nr_parts;
97 97
98 gpmc_onenand_init(&board_onenand_data); 98 gpmc_onenand_init(&board_onenand_data);
99 } 99 }
100 #else 100 #else
101 static void 101 static void
102 __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) 102 __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
103 { 103 {
104 } 104 }
105 #endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */ 105 #endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
106 106
107 #if defined(CONFIG_MTD_NAND_OMAP2) || \ 107 #if defined(CONFIG_MTD_NAND_OMAP2) || \
108 defined(CONFIG_MTD_NAND_OMAP2_MODULE) 108 defined(CONFIG_MTD_NAND_OMAP2_MODULE)
109 109
110 /* Note that all values in this struct are in nanoseconds */ 110 /* Note that all values in this struct are in nanoseconds */
111 static struct gpmc_timings nand_timings = { 111 static struct gpmc_timings nand_timings = {
112 112
113 .sync_clk = 0, 113 .sync_clk = 0,
114 114
115 .cs_on = 0, 115 .cs_on = 0,
116 .cs_rd_off = 36, 116 .cs_rd_off = 36,
117 .cs_wr_off = 36, 117 .cs_wr_off = 36,
118 118
119 .adv_on = 6, 119 .adv_on = 6,
120 .adv_rd_off = 24, 120 .adv_rd_off = 24,
121 .adv_wr_off = 36, 121 .adv_wr_off = 36,
122 122
123 .we_off = 30, 123 .we_off = 30,
124 .oe_off = 48, 124 .oe_off = 48,
125 125
126 .access = 54, 126 .access = 54,
127 .rd_cycle = 72, 127 .rd_cycle = 72,
128 .wr_cycle = 72, 128 .wr_cycle = 72,
129 129
130 .wr_access = 30, 130 .wr_access = 30,
131 .wr_data_mux_bus = 0, 131 .wr_data_mux_bus = 0,
132 }; 132 };
133 133
134 static struct gpmc_timings am335x_nand_timings = {
135
136 .sync_clk = 0,
137
138 .cs_on = 0,
139 .cs_rd_off = 44,
140 .cs_wr_off = 44,
141
142 .adv_on = 6,
143 .adv_rd_off = 34,
144 .adv_wr_off = 44,
145
146 .we_off = 40,
147 .oe_off = 54,
148
149 .access = 64,
150 .rd_cycle = 82,
151 .wr_cycle = 82,
152
153 .wr_access = 40,
154 .wr_data_mux_bus = 0,
155 };
156
134 static struct omap_nand_platform_data board_nand_data = { 157 static struct omap_nand_platform_data board_nand_data = {
135 .gpmc_t = &nand_timings, 158 .gpmc_t = &nand_timings,
136 }; 159 };
137 160
138 void 161 void
139 __init board_nand_init(struct mtd_partition *nand_parts, 162 __init board_nand_init(struct mtd_partition *nand_parts,
140 u8 nr_parts, u8 cs, int nand_type) 163 u8 nr_parts, u8 cs, int nand_type)
141 { 164 {
142 board_nand_data.cs = cs; 165 board_nand_data.cs = cs;
143 board_nand_data.parts = nand_parts; 166 board_nand_data.parts = nand_parts;
144 board_nand_data.nr_parts = nr_parts; 167 board_nand_data.nr_parts = nr_parts;
145 board_nand_data.devsize = nand_type; 168 board_nand_data.devsize = nand_type;
146 169
147 board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; 170 board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
148 board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; 171 board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
149 172
150 if (cpu_is_am335x()) { 173 if (cpu_is_am335x()) {
151 board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW; 174 board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW;
152 board_nand_data.xfer_type = NAND_OMAP_PREFETCH_POLLED; 175 board_nand_data.xfer_type = NAND_OMAP_PREFETCH_POLLED;
176 board_nand_data.gpmc_t = &am335x_nand_timings;
153 } 177 }
154 178
155 gpmc_nand_init(&board_nand_data); 179 gpmc_nand_init(&board_nand_data);
156 } 180 }
157 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ 181 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
158 182
159 /** 183 /**
160 * get_gpmc0_type - Reads the FPGA DIP_SWITCH_INPUT_REGISTER2 to get 184 * get_gpmc0_type - Reads the FPGA DIP_SWITCH_INPUT_REGISTER2 to get
161 * the various cs values. 185 * the various cs values.
162 */ 186 */
163 static u8 get_gpmc0_type(void) 187 static u8 get_gpmc0_type(void)
164 { 188 {
165 u8 cs = 0; 189 u8 cs = 0;
166 void __iomem *fpga_map_addr; 190 void __iomem *fpga_map_addr;
167 191
168 fpga_map_addr = ioremap(DEBUG_BASE, 4096); 192 fpga_map_addr = ioremap(DEBUG_BASE, 4096);
169 if (!fpga_map_addr) 193 if (!fpga_map_addr)
170 return -ENOMEM; 194 return -ENOMEM;
171 195
172 if (!(__raw_readw(fpga_map_addr + REG_FPGA_REV))) 196 if (!(__raw_readw(fpga_map_addr + REG_FPGA_REV)))
173 /* we dont have an DEBUG FPGA??? */ 197 /* we dont have an DEBUG FPGA??? */
174 /* Depend on #defines!! default to strata boot return param */ 198 /* Depend on #defines!! default to strata boot return param */
175 goto unmap; 199 goto unmap;
176 200
177 /* S8-DIP-OFF = 1, S8-DIP-ON = 0 */ 201 /* S8-DIP-OFF = 1, S8-DIP-ON = 0 */
178 cs = __raw_readw(fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2) & 0xf; 202 cs = __raw_readw(fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2) & 0xf;
179 203
180 /* ES2.0 SDP's onwards 4 dip switches are provided for CS */ 204 /* ES2.0 SDP's onwards 4 dip switches are provided for CS */
181 if (omap_rev() >= OMAP3430_REV_ES1_0) 205 if (omap_rev() >= OMAP3430_REV_ES1_0)
182 /* change (S8-1:4=DS-2:0) to (S8-4:1=DS-2:0) */ 206 /* change (S8-1:4=DS-2:0) to (S8-4:1=DS-2:0) */
183 cs = ((cs & 8) >> 3) | ((cs & 4) >> 1) | 207 cs = ((cs & 8) >> 3) | ((cs & 4) >> 1) |
184 ((cs & 2) << 1) | ((cs & 1) << 3); 208 ((cs & 2) << 1) | ((cs & 1) << 3);
185 else 209 else
186 /* change (S8-1:3=DS-2:0) to (S8-3:1=DS-2:0) */ 210 /* change (S8-1:3=DS-2:0) to (S8-3:1=DS-2:0) */
187 cs = ((cs & 4) >> 2) | (cs & 2) | ((cs & 1) << 2); 211 cs = ((cs & 4) >> 2) | (cs & 2) | ((cs & 1) << 2);
188 unmap: 212 unmap:
189 iounmap(fpga_map_addr); 213 iounmap(fpga_map_addr);
190 return cs; 214 return cs;
191 } 215 }
192 216
193 /** 217 /**
194 * board_flash_init - Identify devices connected to GPMC and register. 218 * board_flash_init - Identify devices connected to GPMC and register.
195 * 219 *
196 * @return - void. 220 * @return - void.
197 */ 221 */
198 void board_flash_init(struct flash_partitions partition_info[], 222 void board_flash_init(struct flash_partitions partition_info[],
199 char chip_sel_board[][GPMC_CS_NUM], int nand_type) 223 char chip_sel_board[][GPMC_CS_NUM], int nand_type)
200 { 224 {
201 u8 cs = 0; 225 u8 cs = 0;
202 u8 norcs = GPMC_CS_NUM + 1; 226 u8 norcs = GPMC_CS_NUM + 1;
203 u8 nandcs = GPMC_CS_NUM + 1; 227 u8 nandcs = GPMC_CS_NUM + 1;
204 u8 onenandcs = GPMC_CS_NUM + 1; 228 u8 onenandcs = GPMC_CS_NUM + 1;
205 u8 idx; 229 u8 idx;
206 unsigned char *config_sel = NULL; 230 unsigned char *config_sel = NULL;
207 231
208 /* REVISIT: Is this return correct idx for 2430 SDP? 232 /* REVISIT: Is this return correct idx for 2430 SDP?
209 * for which cs configuration matches for 2430 SDP? 233 * for which cs configuration matches for 2430 SDP?
210 */ 234 */
211 idx = get_gpmc0_type(); 235 idx = get_gpmc0_type();
212 if (idx >= MAX_SUPPORTED_GPMC_CONFIG) { 236 if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
213 pr_err("%s: Invalid chip select: %d\n", __func__, cs); 237 pr_err("%s: Invalid chip select: %d\n", __func__, cs);
214 return; 238 return;
215 } 239 }
216 config_sel = (unsigned char *)(chip_sel_board[idx]); 240 config_sel = (unsigned char *)(chip_sel_board[idx]);
217 241
218 while (cs < GPMC_CS_NUM) { 242 while (cs < GPMC_CS_NUM) {
219 switch (config_sel[cs]) { 243 switch (config_sel[cs]) {
220 case PDC_NOR: 244 case PDC_NOR:
221 if (norcs > GPMC_CS_NUM) 245 if (norcs > GPMC_CS_NUM)
222 norcs = cs; 246 norcs = cs;
223 break; 247 break;
224 case PDC_NAND: 248 case PDC_NAND:
225 if (nandcs > GPMC_CS_NUM) 249 if (nandcs > GPMC_CS_NUM)
226 nandcs = cs; 250 nandcs = cs;
227 break; 251 break;
228 case PDC_ONENAND: 252 case PDC_ONENAND:
229 if (onenandcs > GPMC_CS_NUM) 253 if (onenandcs > GPMC_CS_NUM)
230 onenandcs = cs; 254 onenandcs = cs;
231 break; 255 break;
232 }; 256 };
233 cs++; 257 cs++;
234 } 258 }
235 259
236 if (norcs > GPMC_CS_NUM) 260 if (norcs > GPMC_CS_NUM)
237 pr_err("NOR: Unable to find configuration in GPMC\n"); 261 pr_err("NOR: Unable to find configuration in GPMC\n");
238 else 262 else
239 board_nor_init(partition_info[0].parts, 263 board_nor_init(partition_info[0].parts,
240 partition_info[0].nr_parts, norcs); 264 partition_info[0].nr_parts, norcs);
241 265
242 if (onenandcs > GPMC_CS_NUM) 266 if (onenandcs > GPMC_CS_NUM)
243 pr_err("OneNAND: Unable to find configuration in GPMC\n"); 267 pr_err("OneNAND: Unable to find configuration in GPMC\n");
244 else 268 else
245 board_onenand_init(partition_info[1].parts, 269 board_onenand_init(partition_info[1].parts,
246 partition_info[1].nr_parts, onenandcs); 270 partition_info[1].nr_parts, onenandcs);
247 271
248 if (nandcs > GPMC_CS_NUM) 272 if (nandcs > GPMC_CS_NUM)
249 pr_err("NAND: Unable to find configuration in GPMC\n"); 273 pr_err("NAND: Unable to find configuration in GPMC\n");
250 else 274 else
251 board_nand_init(partition_info[2].parts, 275 board_nand_init(partition_info[2].parts,
252 partition_info[2].nr_parts, nandcs, nand_type); 276 partition_info[2].nr_parts, nandcs, nand_type);
253 } 277 }
254 278