# BRCM_VERSION=3
[bcm963xx.git] / kernel / linux / 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 #ifdef CONFIG_ARCH_OMAP1610
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 #ifdef CONFIG_ARCH_OMAP1610
151         if (cpu_is_omap1610()) {
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 const void *__omap_get_per_info(u16 tag, size_t len)
185 {
186         struct omap_board_info_entry *info = NULL;
187
188 #ifdef CONFIG_OMAP_BOOT_TAG
189         if (omap_bootloader_tag_len > 4)
190                 info = (struct omap_board_info_entry *) omap_bootloader_tag;
191         while (info != NULL) {
192                 u8 *next;
193
194                 if (info->tag == tag)
195                         break;
196
197                 next = (u8 *) info + sizeof(*info) + info->len;
198                 if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
199                         info = NULL;
200                 else
201                         info = (struct omap_board_info_entry *) next;
202         }
203 #endif
204         if (info == NULL)
205                 return NULL;
206         if (info->len != len) {
207                 printk(KERN_ERR "OMAP per_info: Length mismatch with tag %x (want %d, got %d)\n",
208                        tag, len, info->len);
209                 return NULL;
210         }
211
212         return info->data;
213 }
214 EXPORT_SYMBOL(__omap_get_per_info);
215
216 static int __init omap_add_serial_console(void)
217 {
218         const struct omap_uart_info *info;
219
220         info = omap_get_per_info(OMAP_TAG_UART, struct omap_uart_info);
221         if (info != NULL && info->console_uart) {
222                 static char speed[11], *opt = NULL;
223
224                 if (info->console_speed) {
225                         snprintf(speed, sizeof(speed), "%u", info->console_speed);
226                         opt = speed;
227                 }
228                 return add_preferred_console("ttyS", info->console_uart - 1, opt);
229         }
230         return 0;
231 }
232 console_initcall(omap_add_serial_console);