]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/board-apollon.c
Merge branch 'omap-fixes'
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / board-apollon.c
1 /*
2  * linux/arch/arm/mach-omap2/board-apollon.c
3  *
4  * Copyright (C) 2005-2008 Samsung Electronics
5  * Author: Kyungmin Park <kyungmin.park@samsung.com>
6  *
7  * Modified from mach-omap2/board-h4.c
8  *
9  * Code for apollon OMAP2 board. Should work on many OMAP2 systems where
10  * the bootloader passes the board-specific data to the kernel.
11  * Do not put any board specific code to this file; create a new machine
12  * type if you need custom low-level initializations.
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License version 2 as
16  * published by the Free Software Foundation.
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/platform_device.h>
22 #include <linux/mtd/mtd.h>
23 #include <linux/mtd/partitions.h>
24 #include <linux/mtd/onenand.h>
25 #include <linux/irq.h>
26 #include <linux/interrupt.h>
27 #include <linux/delay.h>
28 #include <linux/leds.h>
29 #include <linux/err.h>
30 #include <linux/clk.h>
31 #include <linux/spi/spi.h>
32 #include <linux/spi/tsc210x.h>
33
34 #include <asm/io.h>
35 #include <mach/hardware.h>
36 #include <asm/mach-types.h>
37 #include <asm/mach/arch.h>
38 #include <asm/mach/flash.h>
39
40 #include <mach/gpio.h>
41 #include <mach/led.h>
42 #include <mach/mux.h>
43 #include <mach/usb.h>
44 #include <mach/board.h>
45 #include <mach/common.h>
46 #include <mach/gpmc.h>
47
48 /* LED & Switch macros */
49 #define LED0_GPIO13             13
50 #define LED1_GPIO14             14
51 #define LED2_GPIO15             15
52 #define LED3_GPIO92             92
53 #define LED4_GPIO93             93
54
55 #define APOLLON_FLASH_CS        0
56 #define APOLLON_ETH_CS          1
57 #define APOLLON_NOR_CS          3
58 #define APOLLON_ETHR_GPIO_IRQ   74
59
60 #define APOLLON_ONENAND_CS2_ADDRESS     (0x00000e40 | (0x10000000 >> 24))
61 #define APOLLON_EXT_CS3_ADDRESS         (0x00000c40 | (0x18000000 >> 24))
62
63 extern apollon_mmc_init(void);
64
65 int apollon_plus(void)
66 {
67         /* The apollon plus has IDCODE revision 5 */
68         return omap_rev() & 0xc0;
69 }
70
71 static struct mtd_partition apollon_partitions[] = {
72         {
73                 .name           = "X-Loader + U-Boot",
74                 .offset         = 0,
75                 .size           = SZ_128K,
76                 .mask_flags     = MTD_WRITEABLE,
77         },
78         {
79                 .name           = "params",
80                 .offset         = MTDPART_OFS_APPEND,
81                 .size           = SZ_128K,
82         },
83         {
84                 .name           = "kernel",
85                 .offset         = MTDPART_OFS_APPEND,
86                 .size           = SZ_2M,
87         },
88         {
89                 .name           = "rootfs",
90                 .offset         = MTDPART_OFS_APPEND,
91                 .size           = SZ_16M,
92         },
93         {
94                 .name           = "filesystem00",
95                 .offset         = MTDPART_OFS_APPEND,
96                 .size           = SZ_32M,
97         },
98         {
99                 .name           = "filesystem01",
100                 .offset         = MTDPART_OFS_APPEND,
101                 .size           = MTDPART_SIZ_FULL,
102         },
103 };
104
105 static struct flash_platform_data apollon_flash_data = {
106         .parts          = apollon_partitions,
107         .nr_parts       = ARRAY_SIZE(apollon_partitions),
108 };
109
110 static struct resource apollon_flash_resource[] = {
111         [0] = {
112                 .flags          = IORESOURCE_MEM,
113         },
114 };
115
116 static struct platform_device apollon_onenand_device = {
117         .name           = "onenand",
118         .id             = -1,
119         .dev            = {
120                 .platform_data  = &apollon_flash_data,
121         },
122         .num_resources  = ARRAY_SIZE(apollon_flash_resource),
123         .resource       = apollon_flash_resource,
124 };
125
126 static struct mtd_partition apollon_nor_partitions[] = {
127         {
128                 .name           = "U-Boot",
129                 .offset         = 0,
130                 .size           = SZ_128K,
131                 .mask_flags     = MTD_WRITEABLE,
132         },
133         {
134                 .name           = "params",
135                 .offset         = MTDPART_OFS_APPEND,
136                 .size           = SZ_128K,
137         },
138         {
139                 .name           = "kernel",
140                 .offset         = MTDPART_OFS_APPEND,
141                 .size           = SZ_2M,
142         },
143         {
144                 .name           = "rootfs",
145                 .offset         = MTDPART_OFS_APPEND,
146                 .size           = SZ_4M - SZ_256K,
147         },
148         {
149                 .name           = "application",
150                 .offset         = MTDPART_OFS_APPEND,
151                 .size           = SZ_8M + SZ_2M,
152         },
153         {
154                 .name           = "reserved",
155                 .offset         = MTDPART_OFS_APPEND,
156                 .size           = MTDPART_SIZ_FULL,
157         },
158 };
159
160 static struct flash_platform_data apollon_nor_data = {
161         .map_name               = "cfi_probe",
162         .width          = 2,
163         .parts          = apollon_nor_partitions,
164         .nr_parts       = ARRAY_SIZE(apollon_nor_partitions),
165 };
166
167 static struct resource apollon_nor_resource[] = {
168         [0] = {
169                 .flags  = IORESOURCE_MEM,
170         }
171 };
172
173 static struct platform_device apollon_nor_device = {
174         .name           = "omapflash",
175         .id             = -1,
176         .dev            = {
177                 .platform_data  = &apollon_nor_data,
178         },
179         .num_resources  = ARRAY_SIZE(apollon_nor_resource),
180         .resource       = apollon_nor_resource,
181 };
182
183 static void __init apollon_flash_init(void)
184 {
185         unsigned long base;
186
187         if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) {
188                 printk(KERN_ERR "Cannot request OneNAND GPMC CS\n");
189                 return;
190         }
191         apollon_flash_resource[0].start = base;
192         apollon_flash_resource[0].end   = base + SZ_128K - 1;
193
194         if (gpmc_cs_request(APOLLON_NOR_CS, SZ_32M, &base) < 0) {
195                 printk(KERN_ERR "Cannot request NOR GPMC CS\n");
196                 return;
197         }
198         apollon_nor_resource[0].start = base;
199         apollon_nor_resource[0].end   = base + SZ_32M - 1;
200 }
201
202 static struct resource apollon_smc91x_resources[] = {
203         [0] = {
204                 .flags  = IORESOURCE_MEM,
205         },
206         [1] = {
207                 .start  = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
208                 .end    = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
209                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
210         },
211 };
212
213 static struct platform_device apollon_smc91x_device = {
214         .name           = "smc91x",
215         .id             = -1,
216         .num_resources  = ARRAY_SIZE(apollon_smc91x_resources),
217         .resource       = apollon_smc91x_resources,
218 };
219
220 static struct platform_device apollon_lcd_device = {
221         .name           = "apollon_lcd",
222         .id             = -1,
223 };
224
225 static struct gpio_led apollon_led_config[] = {
226         {
227                 .name                   = "d2",
228                 .gpio                   = LED0_GPIO13,
229                 .default_trigger        = "heartbeat",
230         },
231         {
232                 .name                   = "d3",
233                 .gpio                   = LED1_GPIO14,
234         },
235         {
236                 .name                   = "d4",
237                 .gpio                   = LED2_GPIO15,
238         },
239         {
240                 .name                   = "d5",
241                 .gpio                   = LED3_GPIO92,
242         },
243         {
244                 .name                   = "d6",
245                 .gpio                   = LED4_GPIO93,
246         },
247 };
248
249 static struct gpio_led_platform_data apollon_led_data = {
250         .num_leds       = ARRAY_SIZE(apollon_led_config),
251         .leds           = apollon_led_config,
252 };
253
254 static struct platform_device apollon_led_device = {
255         .name           = "leds-gpio",
256         .id             = -1,
257         .dev            = {
258                 .platform_data  = &apollon_led_data,
259         },
260 };
261
262 static struct platform_device *apollon_devices[] __initdata = {
263         &apollon_onenand_device,
264         &apollon_nor_device,
265         &apollon_smc91x_device,
266         &apollon_lcd_device,
267         &apollon_led_device,
268 };
269
270 static inline void __init apollon_init_smc91x(void)
271 {
272         unsigned long base;
273         unsigned int rate;
274         struct clk *gpmc_fck;
275         int eth_cs;
276
277         gpmc_fck = clk_get(NULL, "gpmc_fck");   /* Always on ENABLE_ON_INIT */
278         if (IS_ERR(gpmc_fck)) {
279                 WARN_ON(1);
280                 return;
281         }
282
283         clk_enable(gpmc_fck);
284         rate = clk_get_rate(gpmc_fck);
285
286         eth_cs = APOLLON_ETH_CS;
287
288         /* Make sure CS1 timings are correct */
289         gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
290
291         if (rate >= 160000000) {
292                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
293                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
294                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
295                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
296                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
297         } else if (rate >= 130000000) {
298                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
299                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
300                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
301                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
302                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
303         } else {/* rate = 100000000 */
304                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
305                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
306                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
307                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
308                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
309         }
310
311         if (gpmc_cs_request(eth_cs, SZ_16M, &base) < 0) {
312                 printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
313                 goto out;
314         }
315         apollon_smc91x_resources[0].start = base + 0x300;
316         apollon_smc91x_resources[0].end   = base + 0x30f;
317         udelay(100);
318
319         omap_cfg_reg(W4__24XX_GPIO74);
320         if (gpio_request(APOLLON_ETHR_GPIO_IRQ, "SMC91x irq") < 0) {
321                 printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
322                         APOLLON_ETHR_GPIO_IRQ);
323                 gpmc_cs_free(eth_cs);
324                 goto out;
325         }
326         gpio_direction_input(APOLLON_ETHR_GPIO_IRQ);
327
328 out:
329         clk_disable(gpmc_fck);
330         clk_put(gpmc_fck);
331 }
332
333 static void __init omap_apollon_init_irq(void)
334 {
335         omap2_init_common_hw(NULL);
336         omap_init_irq();
337         omap_gpio_init();
338         apollon_init_smc91x();
339 }
340
341 static struct tsc210x_config tsc_platform_data = {
342         .use_internal           = 1,
343         .monitor                = TSC_TEMP,
344         .mclk                   = "sys_clkout",
345 };
346
347 static struct spi_board_info apollon_spi_board_info[] = {
348         [0] = {
349                 .modalias       = "tsc2101",
350                 .irq            = OMAP_GPIO_IRQ(85),
351                 .bus_num        = 1,
352                 .chip_select    = 0,
353                 .mode           = SPI_MODE_1,
354                 .max_speed_hz   = 6000000,
355                 .platform_data  = &tsc_platform_data,
356         },
357 };
358
359 static struct omap_uart_config apollon_uart_config __initdata = {
360         .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2),
361 };
362
363 static struct omap_usb_config apollon_usb_config __initdata = {
364         .register_dev   = 1,
365         .hmc_mode       = 0x14, /* 0:dev 1:host1 2:disable */
366
367         .pins[0]        = 6,
368 };
369
370 static struct omap_lcd_config apollon_lcd_config __initdata = {
371         .ctrl_name      = "internal",
372 };
373
374 static struct omap_board_config_kernel apollon_config[] __initdata = {
375         { OMAP_TAG_UART,        &apollon_uart_config },
376         { OMAP_TAG_LCD,         &apollon_lcd_config },
377 };
378
379 static void __init apollon_led_init(void)
380 {
381         /* LED0 - AA10 */
382         omap_cfg_reg(AA10_242X_GPIO13);
383         /* LED1  - AA6 */
384         omap_cfg_reg(AA6_242X_GPIO14);
385         /* LED2  - AA4 */
386         omap_cfg_reg(AA4_242X_GPIO15);
387
388         if (apollon_plus()) {
389                 /* LED3 - M15 */
390                 omap_cfg_reg(M15_24XX_GPIO92);
391                 /* LED4 - P20 */
392                 omap_cfg_reg(P20_24XX_GPIO93);
393         } else
394                 apollon_led_data.num_leds = 3;
395 }
396
397 static void __init apollon_usb_init(void)
398 {
399         /* USB device */
400         /* DEVICE_SUSPEND */
401         omap_cfg_reg(P21_242X_GPIO12);
402         gpio_request(12, "USB suspend");
403         gpio_direction_output(12, 0);
404         omap_usb_init(&apollon_usb_config);
405 }
406
407 static void __init apollon_tsc_init(void)
408 {
409         /* TSC2101 */
410         omap_cfg_reg(N15_24XX_GPIO85);
411         gpio_request(85, "tsc2101 irq");
412         gpio_direction_input(85);
413
414         omap_cfg_reg(W14_24XX_SYS_CLKOUT);      /* mclk */
415 }
416
417 static void __init apollon_cs_init(void)
418 {
419         unsigned long base;
420         unsigned int rate;
421         struct clk *l3ck;
422         u32 value;
423         int cs, sync = 0;
424
425         l3ck = clk_get(NULL, "core_l3_ck");
426         if (IS_ERR(l3ck))
427                 rate = 100000000;
428         else
429                 rate = clk_get_rate(l3ck);
430
431         /* CS2: OneNAND */
432         cs = 2;
433         value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG1);
434         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, value);
435         value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG2);
436         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, value);
437         value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG3);
438         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, value);
439         value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG4);
440         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, value);
441         value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG5);
442         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, value);
443         value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG6);
444         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, value);
445
446         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, APOLLON_ONENAND_CS2_ADDRESS);
447
448         /* CS3: External NOR */
449         cs = APOLLON_NOR_CS;
450         if (rate >= 160000000) {
451                 sync = 1;
452                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0xe5011211);
453                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00090b01);
454                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00020201);
455                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x09030b03);
456                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x010a0a0c);
457                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000);
458         } else if (rate >= 130000000) {
459                 /* Not yet know ... Use the async values */
460                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0x00021201);
461                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00121601);
462                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00040401);
463                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x12061605);
464                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x01151317);
465                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000);
466         } else {/* rate = 100000000 */
467                 sync = 1;
468                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0xe1001202);
469                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00151501);
470                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00050501);
471                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x0e070e07);
472                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x01131F1F);
473                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000);
474         }
475
476         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, APOLLON_EXT_CS3_ADDRESS);
477
478         if (gpmc_cs_request(cs, SZ_32M, &base) < 0) {
479                 printk(KERN_ERR "Failed to request GPMC CS for external\n");
480                 return;
481         }
482
483         /* Synchronous mode */
484         if (sync) {
485                 void __iomem *addr = ioremap(base, SZ_32M);
486                 writew(0xaa, addr + 0xaaa);
487                 writew(0x55, addr + 0x554);
488                 writew(0xc0, addr + 0x24aaa);
489                 iounmap(addr);
490         }
491
492         gpmc_cs_free(cs);
493 }
494
495 static void __init omap_apollon_init(void)
496 {
497         apollon_cs_init();
498         apollon_led_init();
499         apollon_flash_init();
500         apollon_usb_init();
501         apollon_tsc_init();
502
503         /*
504          * Make sure the serial ports are muxed on at this point.
505          * You have to mux them off in device drivers later on
506          * if not needed.
507          */
508         platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
509         omap_board_config = apollon_config;
510         omap_board_config_size = ARRAY_SIZE(apollon_config);
511         omap_serial_init();
512         omap_register_i2c_bus(1, 100, NULL, 0);
513         omap_register_i2c_bus(2, 100, NULL, 0);
514
515         spi_register_board_info(apollon_spi_board_info,
516                                 ARRAY_SIZE(apollon_spi_board_info));
517
518         apollon_mmc_init();
519 }
520
521 static void __init omap_apollon_map_io(void)
522 {
523         omap2_set_globals_242x();
524         omap2_map_common_io();
525 }
526
527 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
528         /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
529         .phys_io        = 0x48000000,
530         .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
531         .boot_params    = 0x80000100,
532         .map_io         = omap_apollon_map_io,
533         .init_irq       = omap_apollon_init_irq,
534         .init_machine   = omap_apollon_init,
535         .timer          = &omap_timer,
536 MACHINE_END