aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap')
-rw-r--r--arch/arm/mach-omap/common.c420
-rw-r--r--arch/arm/mach-omap/common.h2
2 files changed, 4 insertions, 418 deletions
diff --git a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c
index 265cde48586f..b6a5b39e7e88 100644
--- a/arch/arm/mach-omap/common.c
+++ b/arch/arm/mach-omap/common.c
@@ -33,421 +33,6 @@
33 33
34#include "clock.h" 34#include "clock.h"
35 35
36#define DEBUG 1
37
38struct omap_id {
39 u16 jtag_id; /* Used to determine OMAP type */
40 u8 die_rev; /* Processor revision */
41 u32 omap_id; /* OMAP revision */
42 u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */
43};
44
45/* Register values to detect the OMAP version */
46static struct omap_id omap_ids[] __initdata = {
47 { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
48 { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
49 { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
50 { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
51 { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
52 { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00},
53 { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00},
54 { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
55 { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
56 { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000},
57 { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00},
58 { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00},
59 { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300},
60 { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300},
61 { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300},
62 { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000},
63 { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000},
64 { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000},
65};
66
67/*
68 * Get OMAP type from PROD_ID.
69 * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM.
70 * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense.
71 * Undocumented register in TEST BLOCK is used as fallback; This seems to
72 * work on 1510, 1610 & 1710. The official way hopefully will work in future
73 * processors.
74 */
75static u16 __init omap_get_jtag_id(void)
76{
77 u32 prod_id, omap_id;
78
79 prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
80 omap_id = omap_readl(OMAP32_ID_1);
81
82 /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */
83 if (((prod_id >> 20) == 0) || (prod_id == omap_id))
84 prod_id = 0;
85 else
86 prod_id &= 0xffff;
87
88 if (prod_id)
89 return prod_id;
90
91 /* Use OMAP32_ID_1 as fallback */
92 prod_id = ((omap_id >> 12) & 0xffff);
93
94 return prod_id;
95}
96
97/*
98 * Get OMAP revision from DIE_REV.
99 * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID.
100 * Undocumented register in the TEST BLOCK is used as fallback.
101 * REVISIT: This does not seem to work on 1510
102 */
103static u8 __init omap_get_die_rev(void)
104{
105 u32 die_rev;
106
107 die_rev = omap_readl(OMAP_DIE_ID_1);
108
109 /* Check for broken OMAP_DIE_ID on early 1710 */
110 if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id())
111 die_rev = 0;
112
113 die_rev = (die_rev >> 17) & 0xf;
114 if (die_rev)
115 return die_rev;
116
117 die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf;
118
119 return die_rev;
120}
121
122static void __init omap_check_revision(void)
123{
124 int i;
125 u16 jtag_id;
126 u8 die_rev;
127 u32 omap_id;
128 u8 cpu_type;
129
130 jtag_id = omap_get_jtag_id();
131 die_rev = omap_get_die_rev();
132 omap_id = omap_readl(OMAP32_ID_0);
133
134#ifdef DEBUG
135 printk("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0));
136 printk("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n",
137 omap_readl(OMAP_DIE_ID_1),
138 (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf);
139 printk("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0));
140 printk("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n",
141 omap_readl(OMAP_PRODUCTION_ID_1),
142 omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff);
143 printk("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0));
144 printk("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1));
145 printk("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev);
146#endif
147
148 system_serial_high = omap_readl(OMAP_DIE_ID_0);
149 system_serial_low = omap_readl(OMAP_DIE_ID_1);
150
151 /* First check only the major version in a safe way */
152 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
153 if (jtag_id == (omap_ids[i].jtag_id)) {
154 system_rev = omap_ids[i].type;
155 break;
156 }
157 }
158
159 /* Check if we can find the die revision */
160 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
161 if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) {
162 system_rev = omap_ids[i].type;
163 break;
164 }
165 }
166
167 /* Finally check also the omap_id */
168 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
169 if (jtag_id == omap_ids[i].jtag_id
170 && die_rev == omap_ids[i].die_rev
171 && omap_id == omap_ids[i].omap_id) {
172 system_rev = omap_ids[i].type;
173 break;
174 }
175 }
176
177 /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */
178 cpu_type = system_rev >> 24;
179
180 switch (cpu_type) {
181 case 0x07:
182 system_rev |= 0x07;
183 break;
184 case 0x15:
185 system_rev |= 0x15;
186 break;
187 case 0x16:
188 case 0x17:
189 system_rev |= 0x16;
190 break;
191 case 0x24:
192 system_rev |= 0x24;
193 break;
194 default:
195 printk("Unknown OMAP cpu type: 0x%02x\n", cpu_type);
196 }
197
198 printk("OMAP%04x", system_rev >> 16);
199 if ((system_rev >> 8) & 0xff)
200 printk("%x", (system_rev >> 8) & 0xff);
201 printk(" revision %i handled as %02xxx id: %08x%08x\n",
202 die_rev, system_rev & 0xff, system_serial_low,
203 system_serial_high);
204}
205
206/*
207 * ----------------------------------------------------------------------------
208 * OMAP I/O mapping
209 *
210 * The machine specific code may provide the extra mapping besides the
211 * default mapping provided here.
212 * ----------------------------------------------------------------------------
213 */
214
215static struct map_desc omap_io_desc[] __initdata = {
216 { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
217};
218
219#ifdef CONFIG_ARCH_OMAP730
220static struct map_desc omap730_io_desc[] __initdata = {
221 { OMAP730_DSP_BASE, OMAP730_DSP_START, OMAP730_DSP_SIZE, MT_DEVICE },
222 { OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE },
223 { OMAP730_SRAM_BASE, OMAP730_SRAM_START, OMAP730_SRAM_SIZE, MT_DEVICE }
224};
225#endif
226
227#ifdef CONFIG_ARCH_OMAP1510
228static struct map_desc omap1510_io_desc[] __initdata = {
229 { OMAP1510_DSP_BASE, OMAP1510_DSP_START, OMAP1510_DSP_SIZE, MT_DEVICE },
230 { OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE },
231 { OMAP1510_SRAM_BASE, OMAP1510_SRAM_START, OMAP1510_SRAM_SIZE, MT_DEVICE }
232};
233#endif
234
235#if defined(CONFIG_ARCH_OMAP16XX)
236static struct map_desc omap1610_io_desc[] __initdata = {
237 { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
238 { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
239 { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE }
240};
241
242static struct map_desc omap5912_io_desc[] __initdata = {
243 { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
244 { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
245/*
246 * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page
247 * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped.
248 * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte
249 * can be used.
250 */
251 { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE }
252};
253#endif
254
255static int initialized = 0;
256
257static void __init _omap_map_io(void)
258{
259 initialized = 1;
260
261 /* We have to initialize the IO space mapping before we can run
262 * cpu_is_omapxxx() macros. */
263 iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
264 omap_check_revision();
265
266#ifdef CONFIG_ARCH_OMAP730
267 if (cpu_is_omap730()) {
268 iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
269 }
270#endif
271#ifdef CONFIG_ARCH_OMAP1510
272 if (cpu_is_omap1510()) {
273 iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
274 }
275#endif
276#if defined(CONFIG_ARCH_OMAP16XX)
277 if (cpu_is_omap1610() || cpu_is_omap1710()) {
278 iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
279 }
280 if (cpu_is_omap5912()) {
281 iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
282 }
283#endif
284
285 /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
286 * on a Posted Write in the TIPB Bridge".
287 */
288 omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL);
289 omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL);
290
291 /* Must init clocks early to assure that timer interrupt works
292 */
293 clk_init();
294}
295
296/*
297 * This should only get called from board specific init
298 */
299void omap_map_io(void)
300{
301 if (!initialized)
302 _omap_map_io();
303}
304
305static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
306 int offset)
307{
308 offset <<= up->regshift;
309 return (unsigned int)__raw_readb(up->membase + offset);
310}
311
312static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset,
313 int value)
314{
315 offset <<= p->regshift;
316 __raw_writeb(value, p->membase + offset);
317}
318
319/*
320 * Internal UARTs need to be initialized for the 8250 autoconfig to work
321 * properly. Note that the TX watermark initialization may not be needed
322 * once the 8250.c watermark handling code is merged.
323 */
324static void __init omap_serial_reset(struct plat_serial8250_port *p)
325{
326 omap_serial_outp(p, UART_OMAP_MDR1, 0x07); /* disable UART */
327 omap_serial_outp(p, UART_OMAP_SCR, 0x08); /* TX watermark */
328 omap_serial_outp(p, UART_OMAP_MDR1, 0x00); /* enable UART */
329
330 if (!cpu_is_omap1510()) {
331 omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
332 while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01));
333 }
334}
335
336static struct plat_serial8250_port serial_platform_data[] = {
337 {
338 .membase = (char*)IO_ADDRESS(OMAP_UART1_BASE),
339 .mapbase = (unsigned long)OMAP_UART1_BASE,
340 .irq = INT_UART1,
341 .flags = UPF_BOOT_AUTOCONF,
342 .iotype = UPIO_MEM,
343 .regshift = 2,
344 .uartclk = OMAP16XX_BASE_BAUD * 16,
345 },
346 {
347 .membase = (char*)IO_ADDRESS(OMAP_UART2_BASE),
348 .mapbase = (unsigned long)OMAP_UART2_BASE,
349 .irq = INT_UART2,
350 .flags = UPF_BOOT_AUTOCONF,
351 .iotype = UPIO_MEM,
352 .regshift = 2,
353 .uartclk = OMAP16XX_BASE_BAUD * 16,
354 },
355 {
356 .membase = (char*)IO_ADDRESS(OMAP_UART3_BASE),
357 .mapbase = (unsigned long)OMAP_UART3_BASE,
358 .irq = INT_UART3,
359 .flags = UPF_BOOT_AUTOCONF,
360 .iotype = UPIO_MEM,
361 .regshift = 2,
362 .uartclk = OMAP16XX_BASE_BAUD * 16,
363 },
364 { },
365};
366
367static struct platform_device serial_device = {
368 .name = "serial8250",
369 .id = 0,
370 .dev = {
371 .platform_data = serial_platform_data,
372 },
373};
374
375/*
376 * Note that on Innovator-1510 UART2 pins conflict with USB2.
377 * By default UART2 does not work on Innovator-1510 if you have
378 * USB OHCI enabled. To use UART2, you must disable USB2 first.
379 */
380void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
381{
382 int i;
383
384 if (cpu_is_omap730()) {
385 serial_platform_data[0].regshift = 0;
386 serial_platform_data[1].regshift = 0;
387 serial_platform_data[0].irq = INT_730_UART_MODEM_1;
388 serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2;
389 }
390
391 if (cpu_is_omap1510()) {
392 serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
393 serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
394 serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
395 }
396
397 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
398 unsigned char reg;
399
400 if (ports[i] == 0) {
401 serial_platform_data[i].membase = 0;
402 serial_platform_data[i].mapbase = 0;
403 continue;
404 }
405
406 switch (i) {
407 case 0:
408 if (cpu_is_omap1510()) {
409 omap_cfg_reg(UART1_TX);
410 omap_cfg_reg(UART1_RTS);
411 if (machine_is_omap_innovator()) {
412 reg = fpga_read(OMAP1510_FPGA_POWER);
413 reg |= OMAP1510_FPGA_PCR_COM1_EN;
414 fpga_write(reg, OMAP1510_FPGA_POWER);
415 udelay(10);
416 }
417 }
418 break;
419 case 1:
420 if (cpu_is_omap1510()) {
421 omap_cfg_reg(UART2_TX);
422 omap_cfg_reg(UART2_RTS);
423 if (machine_is_omap_innovator()) {
424 reg = fpga_read(OMAP1510_FPGA_POWER);
425 reg |= OMAP1510_FPGA_PCR_COM2_EN;
426 fpga_write(reg, OMAP1510_FPGA_POWER);
427 udelay(10);
428 }
429 }
430 break;
431 case 2:
432 if (cpu_is_omap1510()) {
433 omap_cfg_reg(UART3_TX);
434 omap_cfg_reg(UART3_RX);
435 }
436 if (cpu_is_omap1710()) {
437 clk_enable(clk_get(0, "uart3_ck"));
438 }
439 break;
440 }
441 omap_serial_reset(&serial_platform_data[i]);
442 }
443}
444
445static int __init omap_init(void)
446{
447 return platform_device_register(&serial_device);
448}
449arch_initcall(omap_init);
450
451#define NO_LENGTH_CHECK 0xffffffff 36#define NO_LENGTH_CHECK 0xffffffff
452 37
453extern int omap_bootloader_tag_len; 38extern int omap_bootloader_tag_len;
@@ -532,9 +117,10 @@ EXPORT_SYMBOL(omap_get_var_config);
532 117
533static int __init omap_add_serial_console(void) 118static int __init omap_add_serial_console(void)
534{ 119{
535 const struct omap_uart_config *info; 120 const struct omap_serial_console_config *info;
536 121
537 info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config); 122 info = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
123 struct omap_serial_console_config);
538 if (info != NULL && info->console_uart) { 124 if (info != NULL && info->console_uart) {
539 static char speed[11], *opt = NULL; 125 static char speed[11], *opt = NULL;
540 126
diff --git a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h
index 9f62858c0df4..bb257344f52d 100644
--- a/arch/arm/mach-omap/common.h
+++ b/arch/arm/mach-omap/common.h
@@ -29,7 +29,7 @@
29 29
30struct sys_timer; 30struct sys_timer;
31 31
32extern void omap_map_io(void); 32extern void omap_map_common_io(void);
33extern struct sys_timer omap_timer; 33extern struct sys_timer omap_timer;
34extern void omap_serial_init(int ports[]); 34extern void omap_serial_init(int ports[]);
35 35