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