ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / arm / mach-omap / common.c
1 /*
2  * linux/arch/arm/mach-omap/common.c
3  *
4  * Code common to all OMAP machines.
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 #include <linux/config.h>
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/delay.h>
15 #include <linux/pm.h>
16 #include <linux/console.h>
17
18 #include <asm/hardware.h>
19 #include <asm/system.h>
20 #include <asm/pgtable.h>
21 #include <asm/mach/map.h>
22 #include <asm/arch/clocks.h>
23 #include <asm/arch/board.h>
24 #include <asm/io.h>
25
26 /*
27  * ----------------------------------------------------------------------------
28  * OMAP I/O mapping
29  *
30  * The machine specific code may provide the extra mapping besides the
31  * default mapping provided here.
32  * ----------------------------------------------------------------------------
33  */
34
35 static struct map_desc omap_io_desc[] __initdata = {
36  { IO_VIRT,             IO_PHYS,             IO_SIZE,              MT_DEVICE },
37 };
38
39 #ifdef CONFIG_ARCH_OMAP730
40 static struct map_desc omap730_io_desc[] __initdata = {
41  { OMAP730_DSP_BASE,    OMAP730_DSP_START,    OMAP730_DSP_SIZE,    MT_DEVICE },
42  { OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE },
43  { OMAP730_SRAM_BASE,   OMAP730_SRAM_START,   OMAP730_SRAM_SIZE,   MT_DEVICE }
44 };
45 #endif
46
47 #ifdef CONFIG_ARCH_OMAP1510
48 static struct map_desc omap1510_io_desc[] __initdata = {
49  { OMAP1510_DSP_BASE,    OMAP1510_DSP_START,    OMAP1510_DSP_SIZE,    MT_DEVICE },
50  { OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE },
51  { OMAP1510_SRAM_BASE,   OMAP1510_SRAM_START,   OMAP1510_SRAM_SIZE,   MT_DEVICE }
52 };
53 #endif
54
55 #ifdef CONFIG_ARCH_OMAP1610
56 static struct map_desc omap1610_io_desc[] __initdata = {
57  { OMAP1610_DSP_BASE,    OMAP1610_DSP_START,    OMAP1610_DSP_SIZE,    MT_DEVICE },
58  { OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
59  { OMAP1610_SRAM_BASE,   OMAP1610_SRAM_START,   OMAP1610_SRAM_SIZE,   MT_DEVICE }
60 };
61 #endif
62
63 #ifdef CONFIG_ARCH_OMAP5912
64 static struct map_desc omap5912_io_desc[] __initdata = {
65  { OMAP5912_DSP_BASE,    OMAP5912_DSP_START,    OMAP5912_DSP_SIZE,    MT_DEVICE },
66  { OMAP5912_DSPREG_BASE, OMAP5912_DSPREG_START, OMAP5912_DSPREG_SIZE, MT_DEVICE },
67  { OMAP5912_SRAM_BASE,   OMAP5912_SRAM_START,   OMAP5912_SRAM_SIZE,   MT_DEVICE }
68 };
69 #endif
70
71 static int initialized = 0;
72
73 static void __init _omap_map_io(void)
74 {
75         initialized = 1;
76
77         /* We have to initialize the IO space mapping before we can run
78          * cpu_is_omapxxx() macros. */
79         iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
80
81 #ifdef CONFIG_ARCH_OMAP730
82         if (cpu_is_omap730()) {
83                 iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
84         }
85 #endif
86 #ifdef CONFIG_ARCH_OMAP1510
87         if (cpu_is_omap1510()) {
88                 iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
89         }
90 #endif
91 #ifdef CONFIG_ARCH_OMAP1610
92         if (cpu_is_omap1610()) {
93                 iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
94         }
95 #endif
96 #ifdef CONFIG_ARCH_OMAP5912
97         if (cpu_is_omap5912()) {
98                 iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
99         }
100 #endif
101
102         /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
103          * on a Posted Write in the TIPB Bridge".
104          */
105         omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL_REG);
106         omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL_REG);
107
108         /* Must init clocks early to assure that timer interrupt works
109          */
110         init_ck();
111 }
112
113 /*
114  * This should only get called from board specific init
115  */
116 void omap_map_io(void)
117 {
118         if (!initialized)
119                 _omap_map_io();
120 }
121
122 extern int omap_bootloader_tag_len;
123 extern u8 omap_bootloader_tag[];
124
125 const void *__omap_get_per_info(u16 tag, size_t len)
126 {
127         struct omap_board_info_entry *info = NULL;
128
129 #ifdef CONFIG_OMAP_BOOT_TAG
130         if (omap_bootloader_tag_len > 4)
131                 info = (struct omap_board_info_entry *) omap_bootloader_tag;
132         while (info != NULL) {
133                 u8 *next;
134
135                 if (info->tag == tag)
136                         break;
137
138                 next = (u8 *) info + sizeof(*info) + info->len;
139                 if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
140                         info = NULL;
141                 else
142                         info = (struct omap_board_info_entry *) next;
143         }
144 #endif
145         if (info == NULL)
146                 return NULL;
147         if (info->len != len) {
148                 printk(KERN_ERR "OMAP per_info: Length mismatch with tag %x (want %d, got %d)\n",
149                        tag, len, info->len);
150                 return NULL;
151         }
152
153         return info->data;
154 }
155 EXPORT_SYMBOL(__omap_get_per_info);
156
157 static int __init omap_add_serial_console(void)
158 {
159         const struct omap_uart_info *info;
160
161         info = omap_get_per_info(OMAP_TAG_UART, struct omap_uart_info);
162         if (info != NULL && info->console_uart) {
163                 static char speed[11], *opt = NULL;
164
165                 if (info->console_speed) {
166                         snprintf(speed, sizeof(speed), "%u", info->console_speed);
167                         opt = speed;
168                 }
169                 return add_preferred_console("ttyS", info->console_uart - 1, opt);
170         }
171         return 0;
172 }
173 console_initcall(omap_add_serial_console);