vserver 1.9.3
[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 revision check
29  *
30  * Since we use the cpu_is_omapnnnn() macros, there's a chance that a board
31  * switches to an updated core. We want to print out the OMAP revision early.
32  *
33  * We use the system_serial registers for the revision information so we
34  * can see it in /proc/cpuinfo.
35  *
36  * If the OMAP detection gets more complicated, we may want to expand this
37  * to store the OMAP version and replace the current cpu_is_omapnnnn() macros.
38  *
39  * ----------------------------------------------------------------------------
40  */
41 static void __init omap_check_revision(void)
42 {
43         system_serial_high = omap_readl(OMAP_ID_BASE);
44         system_serial_low = OMAP_ID_REG;
45         system_rev = (OMAP_ID_REG >> ID_SHIFT) & ID_MASK;
46
47         printk("OMAP revision: %d.%d (0x%08x) id: 0x%08x detected as OMAP-",
48                (system_serial_high >> 20) & 0xf,
49                (system_serial_high >> 16) & 0xf,
50                system_serial_high, system_serial_low);
51
52         switch (system_rev) {
53         case OMAP_ID_730:
54                 printk("730\n");
55                 system_rev = 0x730;
56                 break;
57         case OMAP_ID_1510:
58                 printk("1510\n");
59                 system_rev = 0x1510;
60                 break;
61         case OMAP_ID_1610:
62                 printk("1610\n");
63                 system_rev = 0x1610;
64                 break;
65         case OMAP_ID_1710:
66                 printk("1710\n");
67                 system_rev = 0x1710;
68                 break;
69         case OMAP_ID_5912:
70                 printk("5912/1611B\n");
71                 system_rev = 0x5912;
72                 break;
73         default:
74                 printk("unknown, please add support!\n");
75         }
76 }
77
78 /*
79  * ----------------------------------------------------------------------------
80  * OMAP I/O mapping
81  *
82  * The machine specific code may provide the extra mapping besides the
83  * default mapping provided here.
84  * ----------------------------------------------------------------------------
85  */
86
87 static struct map_desc omap_io_desc[] __initdata = {
88  { IO_VIRT,             IO_PHYS,             IO_SIZE,              MT_DEVICE },
89 };
90
91 #ifdef CONFIG_ARCH_OMAP730
92 static struct map_desc omap730_io_desc[] __initdata = {
93  { OMAP730_DSP_BASE,    OMAP730_DSP_START,    OMAP730_DSP_SIZE,    MT_DEVICE },
94  { OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE },
95  { OMAP730_SRAM_BASE,   OMAP730_SRAM_START,   OMAP730_SRAM_SIZE,   MT_DEVICE }
96 };
97 #endif
98
99 #ifdef CONFIG_ARCH_OMAP1510
100 static struct map_desc omap1510_io_desc[] __initdata = {
101  { OMAP1510_DSP_BASE,    OMAP1510_DSP_START,    OMAP1510_DSP_SIZE,    MT_DEVICE },
102  { OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE },
103  { OMAP1510_SRAM_BASE,   OMAP1510_SRAM_START,   OMAP1510_SRAM_SIZE,   MT_DEVICE }
104 };
105 #endif
106
107 #if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
108 static struct map_desc omap1610_io_desc[] __initdata = {
109  { OMAP1610_DSP_BASE,    OMAP1610_DSP_START,    OMAP1610_DSP_SIZE,    MT_DEVICE },
110  { OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
111  { OMAP1610_SRAM_BASE,   OMAP1610_SRAM_START,   OMAP1610_SRAM_SIZE,   MT_DEVICE }
112 };
113 #endif
114
115 #ifdef CONFIG_ARCH_OMAP5912
116 static struct map_desc omap5912_io_desc[] __initdata = {
117  { OMAP5912_DSP_BASE,    OMAP5912_DSP_START,    OMAP5912_DSP_SIZE,    MT_DEVICE },
118  { OMAP5912_DSPREG_BASE, OMAP5912_DSPREG_START, OMAP5912_DSPREG_SIZE, MT_DEVICE },
119 /*
120  * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page
121  * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped.
122  * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte
123  * can be used.
124  */
125  { OMAP5912_SRAM_BASE,   OMAP5912_SRAM_START,   OMAP5912_SRAM_SIZE + 0x800,   MT_DEVICE }
126 };
127 #endif
128
129 static int initialized = 0;
130
131 static void __init _omap_map_io(void)
132 {
133         initialized = 1;
134
135         /* We have to initialize the IO space mapping before we can run
136          * cpu_is_omapxxx() macros. */
137         iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
138         omap_check_revision();
139
140 #ifdef CONFIG_ARCH_OMAP730
141         if (cpu_is_omap730()) {
142                 iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
143         }
144 #endif
145 #ifdef CONFIG_ARCH_OMAP1510
146         if (cpu_is_omap1510()) {
147                 iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
148         }
149 #endif
150 #if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
151         if (cpu_is_omap1610() || cpu_is_omap1710()) {
152                 iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
153         }
154 #endif
155 #ifdef CONFIG_ARCH_OMAP5912
156         if (cpu_is_omap5912()) {
157                 iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
158         }
159 #endif
160
161         /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
162          * on a Posted Write in the TIPB Bridge".
163          */
164         omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL);
165         omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL);
166
167         /* Must init clocks early to assure that timer interrupt works
168          */
169         init_ck();
170 }
171
172 /*
173  * This should only get called from board specific init
174  */
175 void omap_map_io(void)
176 {
177         if (!initialized)
178                 _omap_map_io();
179 }
180
181 extern int omap_bootloader_tag_len;
182 extern u8 omap_bootloader_tag[];
183
184 struct omap_board_config_kernel *omap_board_config;
185 int omap_board_config_size = 0;
186
187 const void *__omap_get_config(u16 tag, size_t len)
188 {
189         struct omap_board_config_entry *info = NULL;
190         struct omap_board_config_kernel *kinfo = NULL;
191         int i;
192
193 #ifdef CONFIG_OMAP_BOOT_TAG
194         if (omap_bootloader_tag_len > 4)
195                 info = (struct omap_board_config_entry *) omap_bootloader_tag;
196         while (info != NULL) {
197                 u8 *next;
198
199                 if (info->tag == tag)
200                         break;
201
202                 next = (u8 *) info + sizeof(*info) + info->len;
203                 if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
204                         info = NULL;
205                 else
206                         info = (struct omap_board_config_entry *) next;
207         }
208         if (info != NULL) {
209                 /* Check the length as a lame attempt to check for
210                  * binary inconsistancy. */
211                 if (info->len != len) {
212                         printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
213                                tag, len, info->len);
214                         return NULL;
215                 }
216                 return info->data;
217         }
218 #endif
219         /* Try to find the config from the board-specific structures
220          * in the kernel. */
221         for (i = 0; i < omap_board_config_size; i++) {
222                 if (omap_board_config[i].tag == tag) {
223                         kinfo = &omap_board_config[i];
224                         break;
225                 }
226         }
227         if (kinfo == NULL)
228                 return NULL;
229         return kinfo->data;
230 }
231 EXPORT_SYMBOL(__omap_get_config);
232
233 static int __init omap_add_serial_console(void)
234 {
235         const struct omap_uart_config *info;
236
237         info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
238         if (info != NULL && info->console_uart) {
239                 static char speed[11], *opt = NULL;
240
241                 if (info->console_speed) {
242                         snprintf(speed, sizeof(speed), "%u", info->console_speed);
243                         opt = speed;
244                 }
245                 return add_preferred_console("ttyS", info->console_uart - 1, opt);
246         }
247         return 0;
248 }
249 console_initcall(omap_add_serial_console);