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