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 | ||
7d7e1eba | 20 | #include <plat/cpu.h> |
c2798e93 VS |
21 | #include <plat/gpmc.h> |
22 | #include <plat/nand.h> | |
23 | #include <plat/onenand.h> | |
24 | #include <plat/tc.h> | |
04aeae77 MK |
25 | |
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 */ | |
106 | static struct gpmc_timings nand_timings = { | |
107 | ||
108 | .sync_clk = 0, | |
109 | ||
110 | .cs_on = 0, | |
111 | .cs_rd_off = 36, | |
112 | .cs_wr_off = 36, | |
113 | ||
114 | .adv_on = 6, | |
115 | .adv_rd_off = 24, | |
116 | .adv_wr_off = 36, | |
117 | ||
118 | .we_off = 30, | |
119 | .oe_off = 48, | |
120 | ||
121 | .access = 54, | |
122 | .rd_cycle = 72, | |
123 | .wr_cycle = 72, | |
124 | ||
125 | .wr_access = 30, | |
126 | .wr_data_mux_bus = 0, | |
127 | }; | |
128 | ||
13d6b73c | 129 | static struct omap_nand_platform_data board_nand_data = { |
c2798e93 | 130 | .gpmc_t = &nand_timings, |
c2798e93 VS |
131 | }; |
132 | ||
13d6b73c | 133 | void |
d5ce2b65 SG |
134 | __init board_nand_init(struct mtd_partition *nand_parts, |
135 | u8 nr_parts, u8 cs, int nand_type) | |
c2798e93 | 136 | { |
13d6b73c SG |
137 | board_nand_data.cs = cs; |
138 | board_nand_data.parts = nand_parts; | |
d5ce2b65 SG |
139 | board_nand_data.nr_parts = nr_parts; |
140 | board_nand_data.devsize = nand_type; | |
c2798e93 | 141 | |
f3d73f36 | 142 | board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; |
13d6b73c | 143 | gpmc_nand_init(&board_nand_data); |
c2798e93 | 144 | } |
c2798e93 VS |
145 | #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ |
146 | ||
147 | /** | |
148 | * get_gpmc0_type - Reads the FPGA DIP_SWITCH_INPUT_REGISTER2 to get | |
149 | * the various cs values. | |
150 | */ | |
151 | static u8 get_gpmc0_type(void) | |
152 | { | |
153 | u8 cs = 0; | |
154 | void __iomem *fpga_map_addr; | |
155 | ||
156 | fpga_map_addr = ioremap(DEBUG_BASE, 4096); | |
157 | if (!fpga_map_addr) | |
158 | return -ENOMEM; | |
159 | ||
160 | if (!(__raw_readw(fpga_map_addr + REG_FPGA_REV))) | |
161 | /* we dont have an DEBUG FPGA??? */ | |
162 | /* Depend on #defines!! default to strata boot return param */ | |
163 | goto unmap; | |
164 | ||
165 | /* S8-DIP-OFF = 1, S8-DIP-ON = 0 */ | |
166 | cs = __raw_readw(fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2) & 0xf; | |
167 | ||
168 | /* ES2.0 SDP's onwards 4 dip switches are provided for CS */ | |
169 | if (omap_rev() >= OMAP3430_REV_ES1_0) | |
170 | /* change (S8-1:4=DS-2:0) to (S8-4:1=DS-2:0) */ | |
171 | cs = ((cs & 8) >> 3) | ((cs & 4) >> 1) | | |
172 | ((cs & 2) << 1) | ((cs & 1) << 3); | |
173 | else | |
174 | /* change (S8-1:3=DS-2:0) to (S8-3:1=DS-2:0) */ | |
175 | cs = ((cs & 4) >> 2) | (cs & 2) | ((cs & 1) << 2); | |
176 | unmap: | |
177 | iounmap(fpga_map_addr); | |
178 | return cs; | |
179 | } | |
180 | ||
181 | /** | |
f69eefd1 | 182 | * board_flash_init - Identify devices connected to GPMC and register. |
c2798e93 VS |
183 | * |
184 | * @return - void. | |
185 | */ | |
d1589f09 | 186 | void __init board_flash_init(struct flash_partitions partition_info[], |
d5ce2b65 | 187 | char chip_sel_board[][GPMC_CS_NUM], int nand_type) |
c2798e93 VS |
188 | { |
189 | u8 cs = 0; | |
190 | u8 norcs = GPMC_CS_NUM + 1; | |
191 | u8 nandcs = GPMC_CS_NUM + 1; | |
192 | u8 onenandcs = GPMC_CS_NUM + 1; | |
193 | u8 idx; | |
194 | unsigned char *config_sel = NULL; | |
195 | ||
196 | /* REVISIT: Is this return correct idx for 2430 SDP? | |
197 | * for which cs configuration matches for 2430 SDP? | |
198 | */ | |
199 | idx = get_gpmc0_type(); | |
200 | if (idx >= MAX_SUPPORTED_GPMC_CONFIG) { | |
adc5430b | 201 | pr_err("%s: Invalid chip select: %d\n", __func__, cs); |
c2798e93 VS |
202 | return; |
203 | } | |
13d6b73c | 204 | config_sel = (unsigned char *)(chip_sel_board[idx]); |
c2798e93 VS |
205 | |
206 | while (cs < GPMC_CS_NUM) { | |
207 | switch (config_sel[cs]) { | |
208 | case PDC_NOR: | |
209 | if (norcs > GPMC_CS_NUM) | |
210 | norcs = cs; | |
211 | break; | |
212 | case PDC_NAND: | |
213 | if (nandcs > GPMC_CS_NUM) | |
214 | nandcs = cs; | |
215 | break; | |
216 | case PDC_ONENAND: | |
217 | if (onenandcs > GPMC_CS_NUM) | |
218 | onenandcs = cs; | |
219 | break; | |
220 | }; | |
221 | cs++; | |
222 | } | |
223 | ||
224 | if (norcs > GPMC_CS_NUM) | |
adc5430b | 225 | pr_err("NOR: Unable to find configuration in GPMC\n"); |
c2798e93 | 226 | else |
13d6b73c SG |
227 | board_nor_init(partition_info[0].parts, |
228 | partition_info[0].nr_parts, norcs); | |
c2798e93 VS |
229 | |
230 | if (onenandcs > GPMC_CS_NUM) | |
adc5430b | 231 | pr_err("OneNAND: Unable to find configuration in GPMC\n"); |
c2798e93 | 232 | else |
13d6b73c SG |
233 | board_onenand_init(partition_info[1].parts, |
234 | partition_info[1].nr_parts, onenandcs); | |
c2798e93 VS |
235 | |
236 | if (nandcs > GPMC_CS_NUM) | |
adc5430b | 237 | pr_err("NAND: Unable to find configuration in GPMC\n"); |
c2798e93 | 238 | else |
13d6b73c | 239 | board_nand_init(partition_info[2].parts, |
d5ce2b65 | 240 | partition_info[2].nr_parts, nandcs, nand_type); |
c2798e93 | 241 | } |