diff options
Diffstat (limited to 'arch/avr32/boards/hammerhead/flash.c')
-rw-r--r-- | arch/avr32/boards/hammerhead/flash.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/arch/avr32/boards/hammerhead/flash.c b/arch/avr32/boards/hammerhead/flash.c new file mode 100644 index 000000000000..a98c6dd3a028 --- /dev/null +++ b/arch/avr32/boards/hammerhead/flash.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* | ||
2 | * Hammerhead board-specific flash initialization | ||
3 | * | ||
4 | * Copyright (C) 2008 Miromico AG | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/mtd/mtd.h> | ||
14 | #include <linux/mtd/partitions.h> | ||
15 | #include <linux/mtd/physmap.h> | ||
16 | #include <linux/usb/isp116x.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/delay.h> | ||
20 | |||
21 | #include <mach/portmux.h> | ||
22 | #include <mach/at32ap700x.h> | ||
23 | #include <mach/smc.h> | ||
24 | |||
25 | #include "../../mach-at32ap/clock.h" | ||
26 | #include "flash.h" | ||
27 | |||
28 | |||
29 | #define HAMMERHEAD_USB_PERIPH_GCLK0 0x40000000 | ||
30 | #define HAMMERHEAD_USB_PERIPH_CS2 0x02000000 | ||
31 | #define HAMMERHEAD_USB_PERIPH_EXTINT0 0x02000000 | ||
32 | |||
33 | #define HAMMERHEAD_FPGA_PERIPH_MOSI 0x00000002 | ||
34 | #define HAMMERHEAD_FPGA_PERIPH_SCK 0x00000020 | ||
35 | #define HAMMERHEAD_FPGA_PERIPH_EXTINT3 0x10000000 | ||
36 | |||
37 | static struct smc_timing flash_timing __initdata = { | ||
38 | .ncs_read_setup = 0, | ||
39 | .nrd_setup = 40, | ||
40 | .ncs_write_setup = 0, | ||
41 | .nwe_setup = 10, | ||
42 | |||
43 | .ncs_read_pulse = 80, | ||
44 | .nrd_pulse = 40, | ||
45 | .ncs_write_pulse = 65, | ||
46 | .nwe_pulse = 55, | ||
47 | |||
48 | .read_cycle = 120, | ||
49 | .write_cycle = 120, | ||
50 | }; | ||
51 | |||
52 | static struct smc_config flash_config __initdata = { | ||
53 | .bus_width = 2, | ||
54 | .nrd_controlled = 1, | ||
55 | .nwe_controlled = 1, | ||
56 | .byte_write = 1, | ||
57 | }; | ||
58 | |||
59 | static struct mtd_partition flash_parts[] = { | ||
60 | { | ||
61 | .name = "u-boot", | ||
62 | .offset = 0x00000000, | ||
63 | .size = 0x00020000, /* 128 KiB */ | ||
64 | .mask_flags = MTD_WRITEABLE, | ||
65 | }, | ||
66 | { | ||
67 | .name = "root", | ||
68 | .offset = 0x00020000, | ||
69 | .size = 0x007d0000, | ||
70 | }, | ||
71 | { | ||
72 | .name = "env", | ||
73 | .offset = 0x007f0000, | ||
74 | .size = 0x00010000, | ||
75 | .mask_flags = MTD_WRITEABLE, | ||
76 | }, | ||
77 | }; | ||
78 | |||
79 | static struct physmap_flash_data flash_data = { | ||
80 | .width = 2, | ||
81 | .nr_parts = ARRAY_SIZE(flash_parts), | ||
82 | .parts = flash_parts, | ||
83 | }; | ||
84 | |||
85 | static struct resource flash_resource = { | ||
86 | .start = 0x00000000, | ||
87 | .end = 0x007fffff, | ||
88 | .flags = IORESOURCE_MEM, | ||
89 | }; | ||
90 | |||
91 | static struct platform_device flash_device = { | ||
92 | .name = "physmap-flash", | ||
93 | .id = 0, | ||
94 | .resource = &flash_resource, | ||
95 | .num_resources = 1, | ||
96 | .dev = { .platform_data = &flash_data, }, | ||
97 | }; | ||
98 | |||
99 | #ifdef CONFIG_BOARD_HAMMERHEAD_USB | ||
100 | |||
101 | static struct smc_timing isp1160_timing __initdata = { | ||
102 | .ncs_read_setup = 75, | ||
103 | .nrd_setup = 75, | ||
104 | .ncs_write_setup = 75, | ||
105 | .nwe_setup = 75, | ||
106 | |||
107 | |||
108 | /* We use conservative timing settings, as the minimal settings aren't | ||
109 | stable. There may be room for tweaking. */ | ||
110 | .ncs_read_pulse = 75, /* min. 33ns */ | ||
111 | .nrd_pulse = 75, /* min. 33ns */ | ||
112 | .ncs_write_pulse = 75, /* min. 26ns */ | ||
113 | .nwe_pulse = 75, /* min. 26ns */ | ||
114 | |||
115 | .read_cycle = 225, /* min. 143ns */ | ||
116 | .write_cycle = 225, /* min. 136ns */ | ||
117 | }; | ||
118 | |||
119 | static struct smc_config isp1160_config __initdata = { | ||
120 | .bus_width = 2, | ||
121 | .nrd_controlled = 1, | ||
122 | .nwe_controlled = 1, | ||
123 | .byte_write = 0, | ||
124 | }; | ||
125 | |||
126 | /* | ||
127 | * The platform delay function is only used to enforce the strange | ||
128 | * read to write delay. This can not be configured in the SMC. All other | ||
129 | * timings are controlled by the SMC (see timings obove) | ||
130 | * So in isp116x-hcd.c we should comment out USE_PLATFORM_DELAY | ||
131 | */ | ||
132 | void isp116x_delay(struct device *dev, int delay) | ||
133 | { | ||
134 | if (delay > 150) | ||
135 | ndelay(delay - 150); | ||
136 | } | ||
137 | |||
138 | static struct isp116x_platform_data isp1160_data = { | ||
139 | .sel15Kres = 1, /* use internal downstream resistors */ | ||
140 | .oc_enable = 0, /* external overcurrent detection */ | ||
141 | .int_edge_triggered = 0, /* interrupt is level triggered */ | ||
142 | .int_act_high = 0, /* interrupt is active low */ | ||
143 | .delay = isp116x_delay, /* platform delay function */ | ||
144 | }; | ||
145 | |||
146 | static struct resource isp1160_resource[] = { | ||
147 | { | ||
148 | .start = 0x08000000, | ||
149 | .end = 0x08000001, | ||
150 | .flags = IORESOURCE_MEM, | ||
151 | }, | ||
152 | { | ||
153 | .start = 0x08000002, | ||
154 | .end = 0x08000003, | ||
155 | .flags = IORESOURCE_MEM, | ||
156 | }, | ||
157 | { | ||
158 | .start = 64, | ||
159 | .flags = IORESOURCE_IRQ, | ||
160 | }, | ||
161 | }; | ||
162 | |||
163 | static struct platform_device isp1160_device = { | ||
164 | .name = "isp116x-hcd", | ||
165 | .id = 0, | ||
166 | .resource = isp1160_resource, | ||
167 | .num_resources = 3, | ||
168 | .dev = { | ||
169 | .platform_data = &isp1160_data, | ||
170 | }, | ||
171 | }; | ||
172 | #endif | ||
173 | |||
174 | #ifdef CONFIG_BOARD_HAMMERHEAD_USB | ||
175 | static int __init hammerhead_usbh_init(void) | ||
176 | { | ||
177 | struct clk *gclk; | ||
178 | struct clk *osc; | ||
179 | |||
180 | int ret; | ||
181 | |||
182 | /* setup smc for usbh */ | ||
183 | smc_set_timing(&isp1160_config, &isp1160_timing); | ||
184 | ret = smc_set_configuration(2, &isp1160_config); | ||
185 | |||
186 | if (ret < 0) { | ||
187 | printk(KERN_ERR | ||
188 | "hammerhead: failed to set ISP1160 USBH timing\n"); | ||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | /* setup gclk0 to run from osc1 */ | ||
193 | gclk = clk_get(NULL, "gclk0"); | ||
194 | if (IS_ERR(gclk)) | ||
195 | goto err_gclk; | ||
196 | |||
197 | osc = clk_get(NULL, "osc1"); | ||
198 | if (IS_ERR(osc)) | ||
199 | goto err_osc; | ||
200 | |||
201 | if (clk_set_parent(gclk, osc)) { | ||
202 | pr_debug("hammerhead: failed to set osc1 for USBH clock\n"); | ||
203 | goto err_set_clk; | ||
204 | } | ||
205 | |||
206 | /* set clock to 6MHz */ | ||
207 | clk_set_rate(gclk, 6000000); | ||
208 | |||
209 | /* and enable */ | ||
210 | clk_enable(gclk); | ||
211 | |||
212 | /* select GCLK0 peripheral function */ | ||
213 | at32_select_periph(GPIO_PIOA_BASE, HAMMERHEAD_USB_PERIPH_GCLK0, | ||
214 | GPIO_PERIPH_A, 0); | ||
215 | |||
216 | /* enable CS2 peripheral function */ | ||
217 | at32_select_periph(GPIO_PIOE_BASE, HAMMERHEAD_USB_PERIPH_CS2, | ||
218 | GPIO_PERIPH_A, 0); | ||
219 | |||
220 | /* H_WAKEUP must be driven low */ | ||
221 | at32_select_gpio(GPIO_PIN_PA(8), AT32_GPIOF_OUTPUT); | ||
222 | |||
223 | /* Select EXTINT0 for PB25 */ | ||
224 | at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_USB_PERIPH_EXTINT0, | ||
225 | GPIO_PERIPH_A, 0); | ||
226 | |||
227 | /* register usbh device driver */ | ||
228 | platform_device_register(&isp1160_device); | ||
229 | |||
230 | err_set_clk: | ||
231 | clk_put(osc); | ||
232 | err_osc: | ||
233 | clk_put(gclk); | ||
234 | err_gclk: | ||
235 | return ret; | ||
236 | } | ||
237 | #endif | ||
238 | |||
239 | #ifdef CONFIG_BOARD_HAMMERHEAD_FPGA | ||
240 | static struct smc_timing fpga_timing __initdata = { | ||
241 | .ncs_read_setup = 16, | ||
242 | .nrd_setup = 32, | ||
243 | .ncs_read_pulse = 48, | ||
244 | .nrd_pulse = 32, | ||
245 | .read_cycle = 64, | ||
246 | |||
247 | .ncs_write_setup = 16, | ||
248 | .nwe_setup = 16, | ||
249 | .ncs_write_pulse = 32, | ||
250 | .nwe_pulse = 32, | ||
251 | .write_cycle = 64, | ||
252 | }; | ||
253 | |||
254 | static struct smc_config fpga_config __initdata = { | ||
255 | .bus_width = 4, | ||
256 | .nrd_controlled = 1, | ||
257 | .nwe_controlled = 1, | ||
258 | .byte_write = 0, | ||
259 | }; | ||
260 | |||
261 | static struct resource hh_fpga0_resource[] = { | ||
262 | { | ||
263 | .start = 0xffe00400, | ||
264 | .end = 0xffe00400 + 0x3ff, | ||
265 | .flags = IORESOURCE_MEM, | ||
266 | }, | ||
267 | { | ||
268 | .start = 4, | ||
269 | .end = 4, | ||
270 | .flags = IORESOURCE_IRQ, | ||
271 | }, | ||
272 | { | ||
273 | .start = 0x0c000000, | ||
274 | .end = 0x0c000100, | ||
275 | .flags = IORESOURCE_MEM, | ||
276 | }, | ||
277 | { | ||
278 | .start = 67, | ||
279 | .end = 67, | ||
280 | .flags = IORESOURCE_IRQ, | ||
281 | }, | ||
282 | }; | ||
283 | |||
284 | static u64 hh_fpga0_dma_mask = DMA_32BIT_MASK; | ||
285 | static struct platform_device hh_fpga0_device = { | ||
286 | .name = "hh_fpga", | ||
287 | .id = 0, | ||
288 | .dev = { | ||
289 | .dma_mask = &hh_fpga0_dma_mask, | ||
290 | .coherent_dma_mask = DMA_32BIT_MASK, | ||
291 | }, | ||
292 | .resource = hh_fpga0_resource, | ||
293 | .num_resources = ARRAY_SIZE(hh_fpga0_resource), | ||
294 | }; | ||
295 | |||
296 | static struct clk hh_fpga0_spi_clk = { | ||
297 | .name = "spi_clk", | ||
298 | .dev = &hh_fpga0_device.dev, | ||
299 | .mode = pba_clk_mode, | ||
300 | .get_rate = pba_clk_get_rate, | ||
301 | .index = 1, | ||
302 | }; | ||
303 | |||
304 | struct platform_device *__init at32_add_device_hh_fpga(void) | ||
305 | { | ||
306 | /* Select peripheral functionallity for SPI SCK and MOSI */ | ||
307 | at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_SCK, | ||
308 | GPIO_PERIPH_B, 0); | ||
309 | at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_MOSI, | ||
310 | GPIO_PERIPH_B, 0); | ||
311 | |||
312 | /* reserve all other needed gpio | ||
313 | * We have on board pull ups, so there is no need | ||
314 | * to enable gpio pull ups */ | ||
315 | /* INIT_DONE (input) */ | ||
316 | at32_select_gpio(GPIO_PIN_PB(0), 0); | ||
317 | |||
318 | /* nSTATUS (input) */ | ||
319 | at32_select_gpio(GPIO_PIN_PB(2), 0); | ||
320 | |||
321 | /* nCONFIG (output, low) */ | ||
322 | at32_select_gpio(GPIO_PIN_PB(3), AT32_GPIOF_OUTPUT); | ||
323 | |||
324 | /* CONF_DONE (input) */ | ||
325 | at32_select_gpio(GPIO_PIN_PB(4), 0); | ||
326 | |||
327 | /* Select EXTINT3 for PB28 (Interrupt from FPGA) */ | ||
328 | at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_EXTINT3, | ||
329 | GPIO_PERIPH_A, 0); | ||
330 | |||
331 | /* Get our parent clock */ | ||
332 | hh_fpga0_spi_clk.parent = clk_get(NULL, "pba"); | ||
333 | clk_put(hh_fpga0_spi_clk.parent); | ||
334 | |||
335 | /* Register clock in at32 clock tree */ | ||
336 | at32_clk_register(&hh_fpga0_spi_clk); | ||
337 | |||
338 | platform_device_register(&hh_fpga0_device); | ||
339 | return &hh_fpga0_device; | ||
340 | } | ||
341 | #endif | ||
342 | |||
343 | /* This needs to be called after the SMC has been initialized */ | ||
344 | static int __init hammerhead_flash_init(void) | ||
345 | { | ||
346 | int ret; | ||
347 | |||
348 | smc_set_timing(&flash_config, &flash_timing); | ||
349 | ret = smc_set_configuration(0, &flash_config); | ||
350 | |||
351 | if (ret < 0) { | ||
352 | printk(KERN_ERR "hammerhead: failed to set NOR flash timing\n"); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | platform_device_register(&flash_device); | ||
357 | |||
358 | #ifdef CONFIG_BOARD_HAMMERHEAD_USB | ||
359 | hammerhead_usbh_init(); | ||
360 | #endif | ||
361 | |||
362 | #ifdef CONFIG_BOARD_HAMMERHEAD_FPGA | ||
363 | /* Setup SMC for FPGA interface */ | ||
364 | smc_set_timing(&fpga_config, &fpga_timing); | ||
365 | ret = smc_set_configuration(3, &fpga_config); | ||
366 | #endif | ||
367 | |||
368 | |||
369 | if (ret < 0) { | ||
370 | printk(KERN_ERR "hammerhead: failed to set FPGA timing\n"); | ||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | device_initcall(hammerhead_flash_init); | ||