diff options
Diffstat (limited to 'arch/arm')
44 files changed, 2835 insertions, 186 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0d8fac3b0371..d7c0984d4a86 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -354,6 +354,7 @@ config ARCH_SA1100 | |||
354 | config ARCH_S3C2410 | 354 | config ARCH_S3C2410 |
355 | bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" | 355 | bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" |
356 | select GENERIC_GPIO | 356 | select GENERIC_GPIO |
357 | select GENERIC_TIME | ||
357 | help | 358 | help |
358 | Samsung S3C2410X CPU based systems, such as the Simtec Electronics | 359 | Samsung S3C2410X CPU based systems, such as the Simtec Electronics |
359 | BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or | 360 | BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ab9f2d4bd04e..00ea4305ad5d 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -47,8 +47,13 @@ comma = , | |||
47 | # Note that GCC does not numerically define an architecture version | 47 | # Note that GCC does not numerically define an architecture version |
48 | # macro, but instead defines a whole series of macros which makes | 48 | # macro, but instead defines a whole series of macros which makes |
49 | # testing for a specific architecture or later rather impossible. | 49 | # testing for a specific architecture or later rather impossible. |
50 | arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7a,-march=armv5t -Wa$(comma)-march=armv7a) | ||
50 | arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) | 51 | arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) |
52 | # Only override the compiler option if ARMv6. The ARMv6K extensions are | ||
53 | # always available in ARMv7 | ||
54 | ifeq ($(CONFIG_CPU_32v6),y) | ||
51 | arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) | 55 | arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) |
56 | endif | ||
52 | arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) | 57 | arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) |
53 | arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t | 58 | arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t |
54 | arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 | 59 | arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 |
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index 0119c0d5f978..5d78ffb8a9a7 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S | |||
@@ -33,7 +33,7 @@ | |||
33 | * numbers for r1. | 33 | * numbers for r1. |
34 | * | 34 | * |
35 | */ | 35 | */ |
36 | __INIT | 36 | .section ".text.head", "ax" |
37 | .type stext, %function | 37 | .type stext, %function |
38 | ENTRY(stext) | 38 | ENTRY(stext) |
39 | msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode | 39 | msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 1d35edacc011..41f98b4ba2ee 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -73,7 +73,7 @@ | |||
73 | * crap here - that's what the boot loader (or in extreme, well justified | 73 | * crap here - that's what the boot loader (or in extreme, well justified |
74 | * circumstances, zImage) is for. | 74 | * circumstances, zImage) is for. |
75 | */ | 75 | */ |
76 | __INIT | 76 | .section ".text.head", "ax" |
77 | .type stext, %function | 77 | .type stext, %function |
78 | ENTRY(stext) | 78 | ENTRY(stext) |
79 | msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode | 79 | msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode |
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c index a00cca0000bd..bd4ef53bc6b9 100644 --- a/arch/arm/kernel/init_task.c +++ b/arch/arm/kernel/init_task.c | |||
@@ -31,7 +31,7 @@ EXPORT_SYMBOL(init_mm); | |||
31 | * The things we do for performance.. | 31 | * The things we do for performance.. |
32 | */ | 32 | */ |
33 | union thread_union init_thread_union | 33 | union thread_union init_thread_union |
34 | __attribute__((__section__(".init.task"))) = | 34 | __attribute__((__section__(".data.init_task"))) = |
35 | { INIT_THREAD_INFO(init_task) }; | 35 | { INIT_THREAD_INFO(init_task) }; |
36 | 36 | ||
37 | /* | 37 | /* |
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 1b061583408e..79b7e5cf5416 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c | |||
@@ -116,8 +116,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, | |||
116 | 116 | ||
117 | offset += sym->st_value - loc; | 117 | offset += sym->st_value - loc; |
118 | if (offset & 3 || | 118 | if (offset & 3 || |
119 | offset <= (s32)0xfc000000 || | 119 | offset <= (s32)0xfe000000 || |
120 | offset >= (s32)0x04000000) { | 120 | offset >= (s32)0x02000000) { |
121 | printk(KERN_ERR | 121 | printk(KERN_ERR |
122 | "%s: relocation out of range, section " | 122 | "%s: relocation out of range, section " |
123 | "%d reloc %d sym '%s'\n", module->name, | 123 | "%d reloc %d sym '%s'\n", module->name, |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 070bcb7a6306..1b76d87fa335 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -486,7 +486,7 @@ static void ipi_timer(void) | |||
486 | } | 486 | } |
487 | 487 | ||
488 | #ifdef CONFIG_LOCAL_TIMERS | 488 | #ifdef CONFIG_LOCAL_TIMERS |
489 | asmlinkage void do_local_timer(struct pt_regs *regs) | 489 | asmlinkage void __exception do_local_timer(struct pt_regs *regs) |
490 | { | 490 | { |
491 | struct pt_regs *old_regs = set_irq_regs(regs); | 491 | struct pt_regs *old_regs = set_irq_regs(regs); |
492 | int cpu = smp_processor_id(); | 492 | int cpu = smp_processor_id(); |
@@ -551,7 +551,7 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
551 | * | 551 | * |
552 | * Bit 0 - Inter-processor function call | 552 | * Bit 0 - Inter-processor function call |
553 | */ | 553 | */ |
554 | asmlinkage void do_IPI(struct pt_regs *regs) | 554 | asmlinkage void __exception do_IPI(struct pt_regs *regs) |
555 | { | 555 | { |
556 | unsigned int cpu = smp_processor_id(); | 556 | unsigned int cpu = smp_processor_id(); |
557 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | 557 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 6be67296f333..e4156e7868ce 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -23,11 +23,15 @@ SECTIONS | |||
23 | #else | 23 | #else |
24 | . = PAGE_OFFSET + TEXT_OFFSET; | 24 | . = PAGE_OFFSET + TEXT_OFFSET; |
25 | #endif | 25 | #endif |
26 | .init : { /* Init code and data */ | 26 | .text.head : { |
27 | _stext = .; | 27 | _stext = .; |
28 | _sinittext = .; | 28 | _sinittext = .; |
29 | *(.text.head) | ||
30 | } | ||
31 | |||
32 | .init : { /* Init code and data */ | ||
29 | *(.init.text) | 33 | *(.init.text) |
30 | _einittext = .; | 34 | _einittext = .; |
31 | __proc_info_begin = .; | 35 | __proc_info_begin = .; |
32 | *(.proc.info.init) | 36 | *(.proc.info.init) |
33 | __proc_info_end = .; | 37 | __proc_info_end = .; |
@@ -119,7 +123,7 @@ SECTIONS | |||
119 | * first, the init task union, aligned | 123 | * first, the init task union, aligned |
120 | * to an 8192 byte boundary. | 124 | * to an 8192 byte boundary. |
121 | */ | 125 | */ |
122 | *(.init.task) | 126 | *(.data.init_task) |
123 | 127 | ||
124 | #ifdef CONFIG_XIP_KERNEL | 128 | #ifdef CONFIG_XIP_KERNEL |
125 | . = ALIGN(4096); | 129 | . = ALIGN(4096); |
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index c7e229b00f6e..856c681ebbbc 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig | |||
@@ -22,6 +22,7 @@ comment "OMAP Board Type" | |||
22 | config MACH_OMAP_INNOVATOR | 22 | config MACH_OMAP_INNOVATOR |
23 | bool "TI Innovator" | 23 | bool "TI Innovator" |
24 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) | 24 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) |
25 | select OMAP_MCBSP | ||
25 | help | 26 | help |
26 | TI OMAP 1510 or 1610 Innovator board support. Say Y here if you | 27 | TI OMAP 1510 or 1610 Innovator board support. Say Y here if you |
27 | have such a board. | 28 | have such a board. |
@@ -29,6 +30,7 @@ config MACH_OMAP_INNOVATOR | |||
29 | config MACH_OMAP_H2 | 30 | config MACH_OMAP_H2 |
30 | bool "TI H2 Support" | 31 | bool "TI H2 Support" |
31 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | 32 | depends on ARCH_OMAP1 && ARCH_OMAP16XX |
33 | select OMAP_MCBSP | ||
32 | help | 34 | help |
33 | TI OMAP 1610/1611B H2 board support. Say Y here if you have such | 35 | TI OMAP 1610/1611B H2 board support. Say Y here if you have such |
34 | a board. | 36 | a board. |
@@ -36,6 +38,7 @@ config MACH_OMAP_H2 | |||
36 | config MACH_OMAP_H3 | 38 | config MACH_OMAP_H3 |
37 | bool "TI H3 Support" | 39 | bool "TI H3 Support" |
38 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | 40 | depends on ARCH_OMAP1 && ARCH_OMAP16XX |
41 | select GPIOEXPANDER_OMAP | ||
39 | help | 42 | help |
40 | TI OMAP 1710 H3 board support. Say Y here if you have such | 43 | TI OMAP 1710 H3 board support. Say Y here if you have such |
41 | a board. | 44 | a board. |
@@ -43,7 +46,7 @@ config MACH_OMAP_H3 | |||
43 | config MACH_OMAP_OSK | 46 | config MACH_OMAP_OSK |
44 | bool "TI OSK Support" | 47 | bool "TI OSK Support" |
45 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | 48 | depends on ARCH_OMAP1 && ARCH_OMAP16XX |
46 | select TPS65010 | 49 | select OMAP_MCBSP |
47 | help | 50 | help |
48 | TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here | 51 | TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here |
49 | if you have such a board. | 52 | if you have such a board. |
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 7165f74f78da..a8b9a00cea22 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile | |||
@@ -37,4 +37,3 @@ led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o | |||
37 | led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o | 37 | led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o |
38 | led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o | 38 | led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o |
39 | obj-$(CONFIG_LEDS) += $(led-y) | 39 | obj-$(CONFIG_LEDS) += $(led-y) |
40 | |||
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index 62e42c7a628e..f65baa95986e 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c | |||
@@ -246,7 +246,7 @@ static void __init fsample_init_smc91x(void) | |||
246 | mdelay(50); | 246 | mdelay(50); |
247 | } | 247 | } |
248 | 248 | ||
249 | void omap_fsample_init_irq(void) | 249 | static void __init omap_fsample_init_irq(void) |
250 | { | 250 | { |
251 | omap1_init_common_hw(); | 251 | omap1_init_common_hw(); |
252 | omap_init_irq(); | 252 | omap_init_irq(); |
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 9d2346fb68f4..7b260b7c537b 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c | |||
@@ -455,7 +455,7 @@ static void __init h3_init_smc91x(void) | |||
455 | } | 455 | } |
456 | } | 456 | } |
457 | 457 | ||
458 | void h3_init_irq(void) | 458 | static void __init h3_init_irq(void) |
459 | { | 459 | { |
460 | omap1_init_common_hw(); | 460 | omap1_init_common_hw(); |
461 | omap_init_irq(); | 461 | omap_init_irq(); |
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index cb00530ad279..7e63a41e37c6 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c | |||
@@ -308,7 +308,7 @@ static void __init innovator_init_smc91x(void) | |||
308 | } | 308 | } |
309 | } | 309 | } |
310 | 310 | ||
311 | void innovator_init_irq(void) | 311 | static void __init innovator_init_irq(void) |
312 | { | 312 | { |
313 | omap1_init_common_hw(); | 313 | omap1_init_common_hw(); |
314 | omap_init_irq(); | 314 | omap_init_irq(); |
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index fa4be962df67..1d5c8d509722 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c | |||
@@ -246,7 +246,7 @@ static void __init perseus2_init_smc91x(void) | |||
246 | mdelay(50); | 246 | mdelay(50); |
247 | } | 247 | } |
248 | 248 | ||
249 | void omap_perseus2_init_irq(void) | 249 | static void __init omap_perseus2_init_irq(void) |
250 | { | 250 | { |
251 | omap1_init_common_hw(); | 251 | omap1_init_common_hw(); |
252 | omap_init_irq(); | 252 | omap_init_irq(); |
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 6dcd10ab4496..da8a3ac47e13 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c | |||
@@ -24,35 +24,6 @@ | |||
24 | #include <asm/arch/mux.h> | 24 | #include <asm/arch/mux.h> |
25 | #include <asm/arch/gpio.h> | 25 | #include <asm/arch/gpio.h> |
26 | 26 | ||
27 | #if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE) | ||
28 | |||
29 | static u64 irda_dmamask = 0xffffffff; | ||
30 | |||
31 | static struct platform_device omap1610ir_device = { | ||
32 | .name = "omap1610-ir", | ||
33 | .id = -1, | ||
34 | .dev = { | ||
35 | .dma_mask = &irda_dmamask, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | static void omap_init_irda(void) | ||
40 | { | ||
41 | /* FIXME define and use a boot tag, members something like: | ||
42 | * u8 uart; // uart1, or uart3 | ||
43 | * ... but driver only handles uart3 for now | ||
44 | * s16 fir_sel; // gpio for SIR vs FIR | ||
45 | * ... may prefer a callback for SIR/MIR/FIR mode select; | ||
46 | * while h2 uses a GPIO, H3 uses a gpio expander | ||
47 | */ | ||
48 | if (machine_is_omap_h2() | ||
49 | || machine_is_omap_h3()) | ||
50 | (void) platform_device_register(&omap1610ir_device); | ||
51 | } | ||
52 | #else | ||
53 | static inline void omap_init_irda(void) {} | ||
54 | #endif | ||
55 | |||
56 | /*-------------------------------------------------------------------------*/ | 27 | /*-------------------------------------------------------------------------*/ |
57 | 28 | ||
58 | #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) | 29 | #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) |
@@ -90,6 +61,45 @@ static void omap_init_rtc(void) | |||
90 | static inline void omap_init_rtc(void) {} | 61 | static inline void omap_init_rtc(void) {} |
91 | #endif | 62 | #endif |
92 | 63 | ||
64 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) | ||
65 | |||
66 | #if defined(CONFIG_ARCH_OMAP15XX) | ||
67 | # define OMAP1_MBOX_SIZE 0x23 | ||
68 | # define INT_DSP_MAILBOX1 INT_1510_DSP_MAILBOX1 | ||
69 | #elif defined(CONFIG_ARCH_OMAP16XX) | ||
70 | # define OMAP1_MBOX_SIZE 0x2f | ||
71 | # define INT_DSP_MAILBOX1 INT_1610_DSP_MAILBOX1 | ||
72 | #endif | ||
73 | |||
74 | #define OMAP1_MBOX_BASE IO_ADDRESS(OMAP16XX_MAILBOX_BASE) | ||
75 | |||
76 | static struct resource mbox_resources[] = { | ||
77 | { | ||
78 | .start = OMAP1_MBOX_BASE, | ||
79 | .end = OMAP1_MBOX_BASE + OMAP1_MBOX_SIZE, | ||
80 | .flags = IORESOURCE_MEM, | ||
81 | }, | ||
82 | { | ||
83 | .start = INT_DSP_MAILBOX1, | ||
84 | .flags = IORESOURCE_IRQ, | ||
85 | }, | ||
86 | }; | ||
87 | |||
88 | static struct platform_device mbox_device = { | ||
89 | .name = "mailbox", | ||
90 | .id = -1, | ||
91 | .num_resources = ARRAY_SIZE(mbox_resources), | ||
92 | .resource = mbox_resources, | ||
93 | }; | ||
94 | |||
95 | static inline void omap_init_mbox(void) | ||
96 | { | ||
97 | platform_device_register(&mbox_device); | ||
98 | } | ||
99 | #else | ||
100 | static inline void omap_init_mbox(void) { } | ||
101 | #endif | ||
102 | |||
93 | #if defined(CONFIG_OMAP_STI) | 103 | #if defined(CONFIG_OMAP_STI) |
94 | 104 | ||
95 | #define OMAP1_STI_BASE IO_ADDRESS(0xfffea000) | 105 | #define OMAP1_STI_BASE IO_ADDRESS(0xfffea000) |
@@ -154,7 +164,8 @@ static int __init omap1_init_devices(void) | |||
154 | /* please keep these calls, and their implementations above, | 164 | /* please keep these calls, and their implementations above, |
155 | * in alphabetical order so they're easier to sort through. | 165 | * in alphabetical order so they're easier to sort through. |
156 | */ | 166 | */ |
157 | omap_init_irda(); | 167 | |
168 | omap_init_mbox(); | ||
158 | omap_init_rtc(); | 169 | omap_init_rtc(); |
159 | omap_init_sti(); | 170 | omap_init_sti(); |
160 | 171 | ||
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c index fab8b0b27cfb..81c4e738506c 100644 --- a/arch/arm/mach-omap1/io.c +++ b/arch/arm/mach-omap1/io.c | |||
@@ -17,11 +17,11 @@ | |||
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | #include <asm/arch/mux.h> | 18 | #include <asm/arch/mux.h> |
19 | #include <asm/arch/tc.h> | 19 | #include <asm/arch/tc.h> |
20 | #include <asm/arch/omapfb.h> | ||
21 | 20 | ||
22 | extern int omap1_clk_init(void); | 21 | extern int omap1_clk_init(void); |
23 | extern void omap_check_revision(void); | 22 | extern void omap_check_revision(void); |
24 | extern void omap_sram_init(void); | 23 | extern void omap_sram_init(void); |
24 | extern void omapfb_reserve_sdram(void); | ||
25 | 25 | ||
26 | /* | 26 | /* |
27 | * The machine specific code may provide the extra mapping besides the | 27 | * The machine specific code may provide the extra mapping besides the |
@@ -121,7 +121,7 @@ void __init omap1_map_common_io(void) | |||
121 | #endif | 121 | #endif |
122 | 122 | ||
123 | omap_sram_init(); | 123 | omap_sram_init(); |
124 | omapfb_reserve_mem(); | 124 | omapfb_reserve_sdram(); |
125 | } | 125 | } |
126 | 126 | ||
127 | /* | 127 | /* |
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c new file mode 100644 index 000000000000..d3abf5609902 --- /dev/null +++ b/arch/arm/mach-omap1/mailbox.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * Mailbox reservation modules for DSP | ||
3 | * | ||
4 | * Copyright (C) 2006 Nokia Corporation | ||
5 | * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/resource.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <asm/arch/mailbox.h> | ||
17 | #include <asm/arch/irqs.h> | ||
18 | #include <asm/io.h> | ||
19 | |||
20 | #define MAILBOX_ARM2DSP1 0x00 | ||
21 | #define MAILBOX_ARM2DSP1b 0x04 | ||
22 | #define MAILBOX_DSP2ARM1 0x08 | ||
23 | #define MAILBOX_DSP2ARM1b 0x0c | ||
24 | #define MAILBOX_DSP2ARM2 0x10 | ||
25 | #define MAILBOX_DSP2ARM2b 0x14 | ||
26 | #define MAILBOX_ARM2DSP1_Flag 0x18 | ||
27 | #define MAILBOX_DSP2ARM1_Flag 0x1c | ||
28 | #define MAILBOX_DSP2ARM2_Flag 0x20 | ||
29 | |||
30 | unsigned long mbox_base; | ||
31 | |||
32 | struct omap_mbox1_fifo { | ||
33 | unsigned long cmd; | ||
34 | unsigned long data; | ||
35 | unsigned long flag; | ||
36 | }; | ||
37 | |||
38 | struct omap_mbox1_priv { | ||
39 | struct omap_mbox1_fifo tx_fifo; | ||
40 | struct omap_mbox1_fifo rx_fifo; | ||
41 | }; | ||
42 | |||
43 | static inline int mbox_read_reg(unsigned int reg) | ||
44 | { | ||
45 | return __raw_readw(mbox_base + reg); | ||
46 | } | ||
47 | |||
48 | static inline void mbox_write_reg(unsigned int val, unsigned int reg) | ||
49 | { | ||
50 | __raw_writew(val, mbox_base + reg); | ||
51 | } | ||
52 | |||
53 | /* msg */ | ||
54 | static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox) | ||
55 | { | ||
56 | struct omap_mbox1_fifo *fifo = | ||
57 | &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; | ||
58 | mbox_msg_t msg; | ||
59 | |||
60 | msg = mbox_read_reg(fifo->data); | ||
61 | msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16; | ||
62 | |||
63 | return msg; | ||
64 | } | ||
65 | |||
66 | static inline void | ||
67 | omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) | ||
68 | { | ||
69 | struct omap_mbox1_fifo *fifo = | ||
70 | &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo; | ||
71 | |||
72 | mbox_write_reg(msg & 0xffff, fifo->data); | ||
73 | mbox_write_reg(msg >> 16, fifo->cmd); | ||
74 | } | ||
75 | |||
76 | static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox) | ||
77 | { | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox) | ||
82 | { | ||
83 | struct omap_mbox1_fifo *fifo = | ||
84 | &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; | ||
85 | |||
86 | return (mbox_read_reg(fifo->flag)); | ||
87 | } | ||
88 | |||
89 | /* irq */ | ||
90 | static inline void | ||
91 | omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) | ||
92 | { | ||
93 | if (irq == IRQ_RX) | ||
94 | enable_irq(mbox->irq); | ||
95 | } | ||
96 | |||
97 | static inline void | ||
98 | omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) | ||
99 | { | ||
100 | if (irq == IRQ_RX) | ||
101 | disable_irq(mbox->irq); | ||
102 | } | ||
103 | |||
104 | static inline int | ||
105 | omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) | ||
106 | { | ||
107 | if (irq == IRQ_TX) | ||
108 | return 0; | ||
109 | return 1; | ||
110 | } | ||
111 | |||
112 | static struct omap_mbox_ops omap1_mbox_ops = { | ||
113 | .type = OMAP_MBOX_TYPE1, | ||
114 | .fifo_read = omap1_mbox_fifo_read, | ||
115 | .fifo_write = omap1_mbox_fifo_write, | ||
116 | .fifo_empty = omap1_mbox_fifo_empty, | ||
117 | .fifo_full = omap1_mbox_fifo_full, | ||
118 | .enable_irq = omap1_mbox_enable_irq, | ||
119 | .disable_irq = omap1_mbox_disable_irq, | ||
120 | .is_irq = omap1_mbox_is_irq, | ||
121 | }; | ||
122 | |||
123 | /* FIXME: the following struct should be created automatically by the user id */ | ||
124 | |||
125 | /* DSP */ | ||
126 | static struct omap_mbox1_priv omap1_mbox_dsp_priv = { | ||
127 | .tx_fifo = { | ||
128 | .cmd = MAILBOX_ARM2DSP1b, | ||
129 | .data = MAILBOX_ARM2DSP1, | ||
130 | .flag = MAILBOX_ARM2DSP1_Flag, | ||
131 | }, | ||
132 | .rx_fifo = { | ||
133 | .cmd = MAILBOX_DSP2ARM1b, | ||
134 | .data = MAILBOX_DSP2ARM1, | ||
135 | .flag = MAILBOX_DSP2ARM1_Flag, | ||
136 | }, | ||
137 | }; | ||
138 | |||
139 | struct omap_mbox mbox_dsp_info = { | ||
140 | .name = "dsp", | ||
141 | .ops = &omap1_mbox_ops, | ||
142 | .priv = &omap1_mbox_dsp_priv, | ||
143 | }; | ||
144 | EXPORT_SYMBOL(mbox_dsp_info); | ||
145 | |||
146 | static int __init omap1_mbox_probe(struct platform_device *pdev) | ||
147 | { | ||
148 | struct resource *res; | ||
149 | int ret = 0; | ||
150 | |||
151 | if (pdev->num_resources != 2) { | ||
152 | dev_err(&pdev->dev, "invalid number of resources: %d\n", | ||
153 | pdev->num_resources); | ||
154 | return -ENODEV; | ||
155 | } | ||
156 | |||
157 | /* MBOX base */ | ||
158 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
159 | if (unlikely(!res)) { | ||
160 | dev_err(&pdev->dev, "invalid mem resource\n"); | ||
161 | return -ENODEV; | ||
162 | } | ||
163 | mbox_base = res->start; | ||
164 | |||
165 | /* DSP IRQ */ | ||
166 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
167 | if (unlikely(!res)) { | ||
168 | dev_err(&pdev->dev, "invalid irq resource\n"); | ||
169 | return -ENODEV; | ||
170 | } | ||
171 | mbox_dsp_info.irq = res->start; | ||
172 | |||
173 | ret = omap_mbox_register(&mbox_dsp_info); | ||
174 | |||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | static int omap1_mbox_remove(struct platform_device *pdev) | ||
179 | { | ||
180 | omap_mbox_unregister(&mbox_dsp_info); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static struct platform_driver omap1_mbox_driver = { | ||
186 | .probe = omap1_mbox_probe, | ||
187 | .remove = omap1_mbox_remove, | ||
188 | .driver = { | ||
189 | .name = "mailbox", | ||
190 | }, | ||
191 | }; | ||
192 | |||
193 | static int __init omap1_mbox_init(void) | ||
194 | { | ||
195 | return platform_driver_register(&omap1_mbox_driver); | ||
196 | } | ||
197 | |||
198 | static void __exit omap1_mbox_exit(void) | ||
199 | { | ||
200 | platform_driver_unregister(&omap1_mbox_driver); | ||
201 | } | ||
202 | |||
203 | module_init(omap1_mbox_init); | ||
204 | module_exit(omap1_mbox_exit); | ||
205 | |||
206 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index aab97ccf1e63..7393109f5c30 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -9,6 +9,7 @@ config ARCH_OMAP2420 | |||
9 | bool "OMAP2420 support" | 9 | bool "OMAP2420 support" |
10 | depends on ARCH_OMAP24XX | 10 | depends on ARCH_OMAP24XX |
11 | select OMAP_DM_TIMER | 11 | select OMAP_DM_TIMER |
12 | select ARCH_OMAP_OTG | ||
12 | 13 | ||
13 | comment "OMAP Board Type" | 14 | comment "OMAP Board Type" |
14 | depends on ARCH_OMAP2 | 15 | depends on ARCH_OMAP2 |
@@ -20,6 +21,7 @@ config MACH_OMAP_GENERIC | |||
20 | config MACH_OMAP_H4 | 21 | config MACH_OMAP_H4 |
21 | bool "OMAP 2420 H4 board" | 22 | bool "OMAP 2420 H4 board" |
22 | depends on ARCH_OMAP2 && ARCH_OMAP24XX | 23 | depends on ARCH_OMAP2 && ARCH_OMAP24XX |
24 | select OMAP_DEBUG_LEDS if LEDS || LEDS_OMAP_DEBUG | ||
23 | 25 | ||
24 | config MACH_OMAP_APOLLON | 26 | config MACH_OMAP_APOLLON |
25 | bool "OMAP 2420 Apollon board" | 27 | bool "OMAP 2420 Apollon board" |
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 1e7ed6d22ca9..452193f01531 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c | |||
@@ -266,12 +266,26 @@ static struct platform_device h4_lcd_device = { | |||
266 | .id = -1, | 266 | .id = -1, |
267 | }; | 267 | }; |
268 | 268 | ||
269 | static struct resource h4_led_resources[] = { | ||
270 | [0] = { | ||
271 | .flags = IORESOURCE_MEM, | ||
272 | }, | ||
273 | }; | ||
274 | |||
275 | static struct platform_device h4_led_device = { | ||
276 | .name = "omap_dbg_led", | ||
277 | .id = -1, | ||
278 | .num_resources = ARRAY_SIZE(h4_led_resources), | ||
279 | .resource = h4_led_resources, | ||
280 | }; | ||
281 | |||
269 | static struct platform_device *h4_devices[] __initdata = { | 282 | static struct platform_device *h4_devices[] __initdata = { |
270 | &h4_smc91x_device, | 283 | &h4_smc91x_device, |
271 | &h4_flash_device, | 284 | &h4_flash_device, |
272 | &h4_irda_device, | 285 | &h4_irda_device, |
273 | &h4_kp_device, | 286 | &h4_kp_device, |
274 | &h4_lcd_device, | 287 | &h4_lcd_device, |
288 | &h4_led_device, | ||
275 | }; | 289 | }; |
276 | 290 | ||
277 | static inline void __init h4_init_smc91x(void) | 291 | static inline void __init h4_init_smc91x(void) |
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index aa4322451e8b..52ec2f2d6360 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <asm/arch/mux.h> | 24 | #include <asm/arch/mux.h> |
25 | #include <asm/arch/gpio.h> | 25 | #include <asm/arch/gpio.h> |
26 | 26 | ||
27 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | 27 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) |
28 | 28 | ||
29 | #define OMAP2_I2C_BASE2 0x48072000 | 29 | #define OMAP2_I2C_BASE2 0x48072000 |
30 | #define OMAP2_I2C_INT2 57 | 30 | #define OMAP2_I2C_INT2 57 |
@@ -42,8 +42,8 @@ static struct resource i2c_resources2[] = { | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | static struct platform_device omap_i2c_device2 = { | 44 | static struct platform_device omap_i2c_device2 = { |
45 | .name = "i2c_omap", | 45 | .name = "i2c_omap", |
46 | .id = 2, | 46 | .id = 2, |
47 | .num_resources = ARRAY_SIZE(i2c_resources2), | 47 | .num_resources = ARRAY_SIZE(i2c_resources2), |
48 | .resource = i2c_resources2, | 48 | .resource = i2c_resources2, |
49 | }; | 49 | }; |
@@ -66,6 +66,40 @@ static void omap_init_i2c(void) {} | |||
66 | 66 | ||
67 | #endif | 67 | #endif |
68 | 68 | ||
69 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) | ||
70 | #define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) | ||
71 | |||
72 | static struct resource mbox_resources[] = { | ||
73 | { | ||
74 | .start = OMAP2_MBOX_BASE, | ||
75 | .end = OMAP2_MBOX_BASE + 0x11f, | ||
76 | .flags = IORESOURCE_MEM, | ||
77 | }, | ||
78 | { | ||
79 | .start = INT_24XX_MAIL_U0_MPU, | ||
80 | .flags = IORESOURCE_IRQ, | ||
81 | }, | ||
82 | { | ||
83 | .start = INT_24XX_MAIL_U3_MPU, | ||
84 | .flags = IORESOURCE_IRQ, | ||
85 | }, | ||
86 | }; | ||
87 | |||
88 | static struct platform_device mbox_device = { | ||
89 | .name = "mailbox", | ||
90 | .id = -1, | ||
91 | .num_resources = ARRAY_SIZE(mbox_resources), | ||
92 | .resource = mbox_resources, | ||
93 | }; | ||
94 | |||
95 | static inline void omap_init_mbox(void) | ||
96 | { | ||
97 | platform_device_register(&mbox_device); | ||
98 | } | ||
99 | #else | ||
100 | static inline void omap_init_mbox(void) { } | ||
101 | #endif | ||
102 | |||
69 | #if defined(CONFIG_OMAP_STI) | 103 | #if defined(CONFIG_OMAP_STI) |
70 | 104 | ||
71 | #define OMAP2_STI_BASE IO_ADDRESS(0x48068000) | 105 | #define OMAP2_STI_BASE IO_ADDRESS(0x48068000) |
@@ -111,29 +145,45 @@ static inline void omap_init_sti(void) {} | |||
111 | #define OMAP2_MCSPI1_BASE 0x48098000 | 145 | #define OMAP2_MCSPI1_BASE 0x48098000 |
112 | #define OMAP2_MCSPI2_BASE 0x4809a000 | 146 | #define OMAP2_MCSPI2_BASE 0x4809a000 |
113 | 147 | ||
114 | /* FIXME: use resources instead */ | ||
115 | |||
116 | static struct omap2_mcspi_platform_config omap2_mcspi1_config = { | 148 | static struct omap2_mcspi_platform_config omap2_mcspi1_config = { |
117 | .base = io_p2v(OMAP2_MCSPI1_BASE), | ||
118 | .num_cs = 4, | 149 | .num_cs = 4, |
119 | }; | 150 | }; |
120 | 151 | ||
152 | static struct resource omap2_mcspi1_resources[] = { | ||
153 | { | ||
154 | .start = OMAP2_MCSPI1_BASE, | ||
155 | .end = OMAP2_MCSPI1_BASE + 0xff, | ||
156 | .flags = IORESOURCE_MEM, | ||
157 | }, | ||
158 | }; | ||
159 | |||
121 | struct platform_device omap2_mcspi1 = { | 160 | struct platform_device omap2_mcspi1 = { |
122 | .name = "omap2_mcspi", | 161 | .name = "omap2_mcspi", |
123 | .id = 1, | 162 | .id = 1, |
163 | .num_resources = ARRAY_SIZE(omap2_mcspi1_resources), | ||
164 | .resource = omap2_mcspi1_resources, | ||
124 | .dev = { | 165 | .dev = { |
125 | .platform_data = &omap2_mcspi1_config, | 166 | .platform_data = &omap2_mcspi1_config, |
126 | }, | 167 | }, |
127 | }; | 168 | }; |
128 | 169 | ||
129 | static struct omap2_mcspi_platform_config omap2_mcspi2_config = { | 170 | static struct omap2_mcspi_platform_config omap2_mcspi2_config = { |
130 | .base = io_p2v(OMAP2_MCSPI2_BASE), | ||
131 | .num_cs = 2, | 171 | .num_cs = 2, |
132 | }; | 172 | }; |
133 | 173 | ||
174 | static struct resource omap2_mcspi2_resources[] = { | ||
175 | { | ||
176 | .start = OMAP2_MCSPI2_BASE, | ||
177 | .end = OMAP2_MCSPI2_BASE + 0xff, | ||
178 | .flags = IORESOURCE_MEM, | ||
179 | }, | ||
180 | }; | ||
181 | |||
134 | struct platform_device omap2_mcspi2 = { | 182 | struct platform_device omap2_mcspi2 = { |
135 | .name = "omap2_mcspi", | 183 | .name = "omap2_mcspi", |
136 | .id = 2, | 184 | .id = 2, |
185 | .num_resources = ARRAY_SIZE(omap2_mcspi2_resources), | ||
186 | .resource = omap2_mcspi2_resources, | ||
137 | .dev = { | 187 | .dev = { |
138 | .platform_data = &omap2_mcspi2_config, | 188 | .platform_data = &omap2_mcspi2_config, |
139 | }, | 189 | }, |
@@ -157,10 +207,10 @@ static int __init omap2_init_devices(void) | |||
157 | * in alphabetical order so they're easier to sort through. | 207 | * in alphabetical order so they're easier to sort through. |
158 | */ | 208 | */ |
159 | omap_init_i2c(); | 209 | omap_init_i2c(); |
210 | omap_init_mbox(); | ||
160 | omap_init_mcspi(); | 211 | omap_init_mcspi(); |
161 | omap_init_sti(); | 212 | omap_init_sti(); |
162 | 213 | ||
163 | return 0; | 214 | return 0; |
164 | } | 215 | } |
165 | arch_initcall(omap2_init_devices); | 216 | arch_initcall(omap2_init_devices); |
166 | |||
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index d8f57824423f..54c836a98456 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -246,14 +246,22 @@ static int gpmc_cs_mem_enabled(int cs) | |||
246 | return l & (1 << 6); | 246 | return l & (1 << 6); |
247 | } | 247 | } |
248 | 248 | ||
249 | static void gpmc_cs_set_reserved(int cs, int reserved) | 249 | int gpmc_cs_set_reserved(int cs, int reserved) |
250 | { | 250 | { |
251 | if (cs > GPMC_CS_NUM) | ||
252 | return -ENODEV; | ||
253 | |||
251 | gpmc_cs_map &= ~(1 << cs); | 254 | gpmc_cs_map &= ~(1 << cs); |
252 | gpmc_cs_map |= (reserved ? 1 : 0) << cs; | 255 | gpmc_cs_map |= (reserved ? 1 : 0) << cs; |
256 | |||
257 | return 0; | ||
253 | } | 258 | } |
254 | 259 | ||
255 | static int gpmc_cs_reserved(int cs) | 260 | int gpmc_cs_reserved(int cs) |
256 | { | 261 | { |
262 | if (cs > GPMC_CS_NUM) | ||
263 | return -ENODEV; | ||
264 | |||
257 | return gpmc_cs_map & (1 << cs); | 265 | return gpmc_cs_map & (1 << cs); |
258 | } | 266 | } |
259 | 267 | ||
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index a0728c33e5d9..82dc70f6b779 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c | |||
@@ -27,6 +27,7 @@ extern void omap_sram_init(void); | |||
27 | extern int omap2_clk_init(void); | 27 | extern int omap2_clk_init(void); |
28 | extern void omap2_check_revision(void); | 28 | extern void omap2_check_revision(void); |
29 | extern void gpmc_init(void); | 29 | extern void gpmc_init(void); |
30 | extern void omapfb_reserve_sdram(void); | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * The machine specific code may provide the extra mapping besides the | 33 | * The machine specific code may provide the extra mapping besides the |
@@ -40,9 +41,21 @@ static struct map_desc omap2_io_desc[] __initdata = { | |||
40 | .type = MT_DEVICE | 41 | .type = MT_DEVICE |
41 | }, | 42 | }, |
42 | { | 43 | { |
43 | .virtual = L4_24XX_VIRT, | 44 | .virtual = DSP_MEM_24XX_VIRT, |
44 | .pfn = __phys_to_pfn(L4_24XX_PHYS), | 45 | .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS), |
45 | .length = L4_24XX_SIZE, | 46 | .length = DSP_MEM_24XX_SIZE, |
47 | .type = MT_DEVICE | ||
48 | }, | ||
49 | { | ||
50 | .virtual = DSP_IPI_24XX_VIRT, | ||
51 | .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS), | ||
52 | .length = DSP_IPI_24XX_SIZE, | ||
53 | .type = MT_DEVICE | ||
54 | }, | ||
55 | { | ||
56 | .virtual = DSP_MMU_24XX_VIRT, | ||
57 | .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS), | ||
58 | .length = DSP_MMU_24XX_SIZE, | ||
46 | .type = MT_DEVICE | 59 | .type = MT_DEVICE |
47 | } | 60 | } |
48 | }; | 61 | }; |
@@ -60,7 +73,7 @@ void __init omap2_map_common_io(void) | |||
60 | 73 | ||
61 | omap2_check_revision(); | 74 | omap2_check_revision(); |
62 | omap_sram_init(); | 75 | omap_sram_init(); |
63 | omapfb_reserve_mem(); | 76 | omapfb_reserve_sdram(); |
64 | } | 77 | } |
65 | 78 | ||
66 | void __init omap2_init_common_hw(void) | 79 | void __init omap2_init_common_hw(void) |
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c new file mode 100644 index 000000000000..b03cd06e055b --- /dev/null +++ b/arch/arm/mach-omap2/mailbox.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * Mailbox reservation modules for OMAP2 | ||
3 | * | ||
4 | * Copyright (C) 2006 Nokia Corporation | ||
5 | * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | ||
6 | * and Paul Mundt <paul.mundt@nokia.com> | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/clk.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <asm/arch/mailbox.h> | ||
18 | #include <asm/arch/irqs.h> | ||
19 | #include <asm/io.h> | ||
20 | |||
21 | #define MAILBOX_REVISION 0x00 | ||
22 | #define MAILBOX_SYSCONFIG 0x10 | ||
23 | #define MAILBOX_SYSSTATUS 0x14 | ||
24 | #define MAILBOX_MESSAGE_0 0x40 | ||
25 | #define MAILBOX_MESSAGE_1 0x44 | ||
26 | #define MAILBOX_MESSAGE_2 0x48 | ||
27 | #define MAILBOX_MESSAGE_3 0x4c | ||
28 | #define MAILBOX_MESSAGE_4 0x50 | ||
29 | #define MAILBOX_MESSAGE_5 0x54 | ||
30 | #define MAILBOX_FIFOSTATUS_0 0x80 | ||
31 | #define MAILBOX_FIFOSTATUS_1 0x84 | ||
32 | #define MAILBOX_FIFOSTATUS_2 0x88 | ||
33 | #define MAILBOX_FIFOSTATUS_3 0x8c | ||
34 | #define MAILBOX_FIFOSTATUS_4 0x90 | ||
35 | #define MAILBOX_FIFOSTATUS_5 0x94 | ||
36 | #define MAILBOX_MSGSTATUS_0 0xc0 | ||
37 | #define MAILBOX_MSGSTATUS_1 0xc4 | ||
38 | #define MAILBOX_MSGSTATUS_2 0xc8 | ||
39 | #define MAILBOX_MSGSTATUS_3 0xcc | ||
40 | #define MAILBOX_MSGSTATUS_4 0xd0 | ||
41 | #define MAILBOX_MSGSTATUS_5 0xd4 | ||
42 | #define MAILBOX_IRQSTATUS_0 0x100 | ||
43 | #define MAILBOX_IRQENABLE_0 0x104 | ||
44 | #define MAILBOX_IRQSTATUS_1 0x108 | ||
45 | #define MAILBOX_IRQENABLE_1 0x10c | ||
46 | #define MAILBOX_IRQSTATUS_2 0x110 | ||
47 | #define MAILBOX_IRQENABLE_2 0x114 | ||
48 | #define MAILBOX_IRQSTATUS_3 0x118 | ||
49 | #define MAILBOX_IRQENABLE_3 0x11c | ||
50 | |||
51 | static unsigned long mbox_base; | ||
52 | |||
53 | #define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1)) | ||
54 | #define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n))) | ||
55 | |||
56 | struct omap_mbox2_fifo { | ||
57 | unsigned long msg; | ||
58 | unsigned long fifo_stat; | ||
59 | unsigned long msg_stat; | ||
60 | }; | ||
61 | |||
62 | struct omap_mbox2_priv { | ||
63 | struct omap_mbox2_fifo tx_fifo; | ||
64 | struct omap_mbox2_fifo rx_fifo; | ||
65 | unsigned long irqenable; | ||
66 | unsigned long irqstatus; | ||
67 | u32 newmsg_bit; | ||
68 | u32 notfull_bit; | ||
69 | }; | ||
70 | |||
71 | static struct clk *mbox_ick_handle; | ||
72 | |||
73 | static inline unsigned int mbox_read_reg(unsigned int reg) | ||
74 | { | ||
75 | return __raw_readl(mbox_base + reg); | ||
76 | } | ||
77 | |||
78 | static inline void mbox_write_reg(unsigned int val, unsigned int reg) | ||
79 | { | ||
80 | __raw_writel(val, mbox_base + reg); | ||
81 | } | ||
82 | |||
83 | /* Mailbox H/W preparations */ | ||
84 | static inline int omap2_mbox_startup(struct omap_mbox *mbox) | ||
85 | { | ||
86 | unsigned int l; | ||
87 | |||
88 | mbox_ick_handle = clk_get(NULL, "mailboxes_ick"); | ||
89 | if (IS_ERR(mbox_ick_handle)) { | ||
90 | printk("Could not get mailboxes_ick\n"); | ||
91 | return -ENODEV; | ||
92 | } | ||
93 | clk_enable(mbox_ick_handle); | ||
94 | |||
95 | /* set smart-idle & autoidle */ | ||
96 | l = mbox_read_reg(MAILBOX_SYSCONFIG); | ||
97 | l |= 0x00000011; | ||
98 | mbox_write_reg(l, MAILBOX_SYSCONFIG); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static inline void omap2_mbox_shutdown(struct omap_mbox *mbox) | ||
104 | { | ||
105 | clk_disable(mbox_ick_handle); | ||
106 | clk_put(mbox_ick_handle); | ||
107 | } | ||
108 | |||
109 | /* Mailbox FIFO handle functions */ | ||
110 | static inline mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox) | ||
111 | { | ||
112 | struct omap_mbox2_fifo *fifo = | ||
113 | &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; | ||
114 | return (mbox_msg_t) mbox_read_reg(fifo->msg); | ||
115 | } | ||
116 | |||
117 | static inline void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) | ||
118 | { | ||
119 | struct omap_mbox2_fifo *fifo = | ||
120 | &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; | ||
121 | mbox_write_reg(msg, fifo->msg); | ||
122 | } | ||
123 | |||
124 | static inline int omap2_mbox_fifo_empty(struct omap_mbox *mbox) | ||
125 | { | ||
126 | struct omap_mbox2_fifo *fifo = | ||
127 | &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; | ||
128 | return (mbox_read_reg(fifo->msg_stat) == 0); | ||
129 | } | ||
130 | |||
131 | static inline int omap2_mbox_fifo_full(struct omap_mbox *mbox) | ||
132 | { | ||
133 | struct omap_mbox2_fifo *fifo = | ||
134 | &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; | ||
135 | return (mbox_read_reg(fifo->fifo_stat)); | ||
136 | } | ||
137 | |||
138 | /* Mailbox IRQ handle functions */ | ||
139 | static inline void omap2_mbox_enable_irq(struct omap_mbox *mbox, | ||
140 | omap_mbox_type_t irq) | ||
141 | { | ||
142 | struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; | ||
143 | u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; | ||
144 | |||
145 | l = mbox_read_reg(p->irqenable); | ||
146 | l |= bit; | ||
147 | mbox_write_reg(l, p->irqenable); | ||
148 | } | ||
149 | |||
150 | static inline void omap2_mbox_disable_irq(struct omap_mbox *mbox, | ||
151 | omap_mbox_type_t irq) | ||
152 | { | ||
153 | struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; | ||
154 | u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; | ||
155 | |||
156 | l = mbox_read_reg(p->irqenable); | ||
157 | l &= ~bit; | ||
158 | mbox_write_reg(l, p->irqenable); | ||
159 | } | ||
160 | |||
161 | static inline void omap2_mbox_ack_irq(struct omap_mbox *mbox, | ||
162 | omap_mbox_type_t irq) | ||
163 | { | ||
164 | struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; | ||
165 | u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; | ||
166 | |||
167 | mbox_write_reg(bit, p->irqstatus); | ||
168 | } | ||
169 | |||
170 | static inline int omap2_mbox_is_irq(struct omap_mbox *mbox, | ||
171 | omap_mbox_type_t irq) | ||
172 | { | ||
173 | struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; | ||
174 | u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; | ||
175 | u32 enable = mbox_read_reg(p->irqenable); | ||
176 | u32 status = mbox_read_reg(p->irqstatus); | ||
177 | |||
178 | return (enable & status & bit); | ||
179 | } | ||
180 | |||
181 | static struct omap_mbox_ops omap2_mbox_ops = { | ||
182 | .type = OMAP_MBOX_TYPE2, | ||
183 | .startup = omap2_mbox_startup, | ||
184 | .shutdown = omap2_mbox_shutdown, | ||
185 | .fifo_read = omap2_mbox_fifo_read, | ||
186 | .fifo_write = omap2_mbox_fifo_write, | ||
187 | .fifo_empty = omap2_mbox_fifo_empty, | ||
188 | .fifo_full = omap2_mbox_fifo_full, | ||
189 | .enable_irq = omap2_mbox_enable_irq, | ||
190 | .disable_irq = omap2_mbox_disable_irq, | ||
191 | .ack_irq = omap2_mbox_ack_irq, | ||
192 | .is_irq = omap2_mbox_is_irq, | ||
193 | }; | ||
194 | |||
195 | /* | ||
196 | * MAILBOX 0: ARM -> DSP, | ||
197 | * MAILBOX 1: ARM <- DSP. | ||
198 | * MAILBOX 2: ARM -> IVA, | ||
199 | * MAILBOX 3: ARM <- IVA. | ||
200 | */ | ||
201 | |||
202 | /* FIXME: the following structs should be filled automatically by the user id */ | ||
203 | |||
204 | /* DSP */ | ||
205 | static struct omap_mbox2_priv omap2_mbox_dsp_priv = { | ||
206 | .tx_fifo = { | ||
207 | .msg = MAILBOX_MESSAGE_0, | ||
208 | .fifo_stat = MAILBOX_FIFOSTATUS_0, | ||
209 | }, | ||
210 | .rx_fifo = { | ||
211 | .msg = MAILBOX_MESSAGE_1, | ||
212 | .msg_stat = MAILBOX_MSGSTATUS_1, | ||
213 | }, | ||
214 | .irqenable = MAILBOX_IRQENABLE_0, | ||
215 | .irqstatus = MAILBOX_IRQSTATUS_0, | ||
216 | .notfull_bit = MAILBOX_IRQ_NOTFULL(0), | ||
217 | .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), | ||
218 | }; | ||
219 | |||
220 | struct omap_mbox mbox_dsp_info = { | ||
221 | .name = "dsp", | ||
222 | .ops = &omap2_mbox_ops, | ||
223 | .priv = &omap2_mbox_dsp_priv, | ||
224 | }; | ||
225 | EXPORT_SYMBOL(mbox_dsp_info); | ||
226 | |||
227 | /* IVA */ | ||
228 | static struct omap_mbox2_priv omap2_mbox_iva_priv = { | ||
229 | .tx_fifo = { | ||
230 | .msg = MAILBOX_MESSAGE_2, | ||
231 | .fifo_stat = MAILBOX_FIFOSTATUS_2, | ||
232 | }, | ||
233 | .rx_fifo = { | ||
234 | .msg = MAILBOX_MESSAGE_3, | ||
235 | .msg_stat = MAILBOX_MSGSTATUS_3, | ||
236 | }, | ||
237 | .irqenable = MAILBOX_IRQENABLE_3, | ||
238 | .irqstatus = MAILBOX_IRQSTATUS_3, | ||
239 | .notfull_bit = MAILBOX_IRQ_NOTFULL(2), | ||
240 | .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), | ||
241 | }; | ||
242 | |||
243 | static struct omap_mbox mbox_iva_info = { | ||
244 | .name = "iva", | ||
245 | .ops = &omap2_mbox_ops, | ||
246 | .priv = &omap2_mbox_iva_priv, | ||
247 | }; | ||
248 | |||
249 | static int __init omap2_mbox_probe(struct platform_device *pdev) | ||
250 | { | ||
251 | struct resource *res; | ||
252 | int ret = 0; | ||
253 | |||
254 | if (pdev->num_resources != 3) { | ||
255 | dev_err(&pdev->dev, "invalid number of resources: %d\n", | ||
256 | pdev->num_resources); | ||
257 | return -ENODEV; | ||
258 | } | ||
259 | |||
260 | /* MBOX base */ | ||
261 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
262 | if (unlikely(!res)) { | ||
263 | dev_err(&pdev->dev, "invalid mem resource\n"); | ||
264 | return -ENODEV; | ||
265 | } | ||
266 | mbox_base = res->start; | ||
267 | |||
268 | /* DSP IRQ */ | ||
269 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
270 | if (unlikely(!res)) { | ||
271 | dev_err(&pdev->dev, "invalid irq resource\n"); | ||
272 | return -ENODEV; | ||
273 | } | ||
274 | mbox_dsp_info.irq = res->start; | ||
275 | |||
276 | ret = omap_mbox_register(&mbox_dsp_info); | ||
277 | |||
278 | /* IVA IRQ */ | ||
279 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||
280 | if (unlikely(!res)) { | ||
281 | dev_err(&pdev->dev, "invalid irq resource\n"); | ||
282 | return -ENODEV; | ||
283 | } | ||
284 | mbox_iva_info.irq = res->start; | ||
285 | |||
286 | ret = omap_mbox_register(&mbox_iva_info); | ||
287 | |||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int omap2_mbox_remove(struct platform_device *pdev) | ||
292 | { | ||
293 | omap_mbox_unregister(&mbox_dsp_info); | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static struct platform_driver omap2_mbox_driver = { | ||
298 | .probe = omap2_mbox_probe, | ||
299 | .remove = omap2_mbox_remove, | ||
300 | .driver = { | ||
301 | .name = "mailbox", | ||
302 | }, | ||
303 | }; | ||
304 | |||
305 | static int __init omap2_mbox_init(void) | ||
306 | { | ||
307 | return platform_driver_register(&omap2_mbox_driver); | ||
308 | } | ||
309 | |||
310 | static void __exit omap2_mbox_exit(void) | ||
311 | { | ||
312 | platform_driver_unregister(&omap2_mbox_driver); | ||
313 | } | ||
314 | |||
315 | module_init(omap2_mbox_init); | ||
316 | module_exit(omap2_mbox_exit); | ||
317 | |||
318 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index e684e9b38216..b81391a4e374 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -366,6 +366,19 @@ config CPU_32v6K | |||
366 | enabled will not boot on processors with do not support these | 366 | enabled will not boot on processors with do not support these |
367 | instructions. | 367 | instructions. |
368 | 368 | ||
369 | # ARMv7 | ||
370 | config CPU_V7 | ||
371 | bool "Support ARM V7 processor" | ||
372 | depends on ARCH_INTEGRATOR | ||
373 | select CPU_32v6K | ||
374 | select CPU_32v7 | ||
375 | select CPU_ABRT_EV7 | ||
376 | select CPU_CACHE_V7 | ||
377 | select CPU_CACHE_VIPT | ||
378 | select CPU_CP15_MMU | ||
379 | select CPU_COPY_V6 if MMU | ||
380 | select CPU_TLB_V6 if MMU | ||
381 | |||
369 | # Figure out what processor architecture version we should be using. | 382 | # Figure out what processor architecture version we should be using. |
370 | # This defines the compiler instruction set which depends on the machine type. | 383 | # This defines the compiler instruction set which depends on the machine type. |
371 | config CPU_32v3 | 384 | config CPU_32v3 |
@@ -391,6 +404,9 @@ config CPU_32v5 | |||
391 | config CPU_32v6 | 404 | config CPU_32v6 |
392 | bool | 405 | bool |
393 | 406 | ||
407 | config CPU_32v7 | ||
408 | bool | ||
409 | |||
394 | # The abort model | 410 | # The abort model |
395 | config CPU_ABRT_NOMMU | 411 | config CPU_ABRT_NOMMU |
396 | bool | 412 | bool |
@@ -413,6 +429,9 @@ config CPU_ABRT_EV5TJ | |||
413 | config CPU_ABRT_EV6 | 429 | config CPU_ABRT_EV6 |
414 | bool | 430 | bool |
415 | 431 | ||
432 | config CPU_ABRT_EV7 | ||
433 | bool | ||
434 | |||
416 | # The cache model | 435 | # The cache model |
417 | config CPU_CACHE_V3 | 436 | config CPU_CACHE_V3 |
418 | bool | 437 | bool |
@@ -429,6 +448,9 @@ config CPU_CACHE_V4WB | |||
429 | config CPU_CACHE_V6 | 448 | config CPU_CACHE_V6 |
430 | bool | 449 | bool |
431 | 450 | ||
451 | config CPU_CACHE_V7 | ||
452 | bool | ||
453 | |||
432 | config CPU_CACHE_VIVT | 454 | config CPU_CACHE_VIVT |
433 | bool | 455 | bool |
434 | 456 | ||
@@ -503,7 +525,7 @@ comment "Processor Features" | |||
503 | 525 | ||
504 | config ARM_THUMB | 526 | config ARM_THUMB |
505 | bool "Support Thumb user binaries" | 527 | bool "Support Thumb user binaries" |
506 | depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 | 528 | depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7 |
507 | default y | 529 | default y |
508 | help | 530 | help |
509 | Say Y if you want to include kernel support for running user space | 531 | Say Y if you want to include kernel support for running user space |
@@ -578,9 +600,15 @@ config CPU_CACHE_ROUND_ROBIN | |||
578 | Say Y here to use the predictable round-robin cache replacement | 600 | Say Y here to use the predictable round-robin cache replacement |
579 | policy. Unless you specifically require this or are unsure, say N. | 601 | policy. Unless you specifically require this or are unsure, say N. |
580 | 602 | ||
603 | config CPU_L2CACHE_DISABLE | ||
604 | bool "Disable level 2 cache" | ||
605 | depends on CPU_V7 | ||
606 | help | ||
607 | Say Y here to disable the level 2 cache. If unsure, say N. | ||
608 | |||
581 | config CPU_BPREDICT_DISABLE | 609 | config CPU_BPREDICT_DISABLE |
582 | bool "Disable branch prediction" | 610 | bool "Disable branch prediction" |
583 | depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 | 611 | depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7 |
584 | help | 612 | help |
585 | Say Y here to disable branch prediction. If unsure, say N. | 613 | Say Y here to disable branch prediction. If unsure, say N. |
586 | 614 | ||
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 2f8b95947774..b5bd335ff14a 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -24,12 +24,14 @@ obj-$(CONFIG_CPU_ABRT_LV4T) += abort-lv4t.o | |||
24 | obj-$(CONFIG_CPU_ABRT_EV5T) += abort-ev5t.o | 24 | obj-$(CONFIG_CPU_ABRT_EV5T) += abort-ev5t.o |
25 | obj-$(CONFIG_CPU_ABRT_EV5TJ) += abort-ev5tj.o | 25 | obj-$(CONFIG_CPU_ABRT_EV5TJ) += abort-ev5tj.o |
26 | obj-$(CONFIG_CPU_ABRT_EV6) += abort-ev6.o | 26 | obj-$(CONFIG_CPU_ABRT_EV6) += abort-ev6.o |
27 | obj-$(CONFIG_CPU_ABRT_EV7) += abort-ev7.o | ||
27 | 28 | ||
28 | obj-$(CONFIG_CPU_CACHE_V3) += cache-v3.o | 29 | obj-$(CONFIG_CPU_CACHE_V3) += cache-v3.o |
29 | obj-$(CONFIG_CPU_CACHE_V4) += cache-v4.o | 30 | obj-$(CONFIG_CPU_CACHE_V4) += cache-v4.o |
30 | obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o | 31 | obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o |
31 | obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o | 32 | obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o |
32 | obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o | 33 | obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o |
34 | obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o | ||
33 | 35 | ||
34 | obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o | 36 | obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o |
35 | obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o | 37 | obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o |
@@ -66,5 +68,6 @@ obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o | |||
66 | obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o | 68 | obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o |
67 | obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o | 69 | obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o |
68 | obj-$(CONFIG_CPU_V6) += proc-v6.o | 70 | obj-$(CONFIG_CPU_V6) += proc-v6.o |
71 | obj-$(CONFIG_CPU_V7) += proc-v7.o | ||
69 | 72 | ||
70 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o | 73 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o |
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S new file mode 100644 index 000000000000..eb90bce38e14 --- /dev/null +++ b/arch/arm/mm/abort-ev7.S | |||
@@ -0,0 +1,32 @@ | |||
1 | #include <linux/linkage.h> | ||
2 | #include <asm/assembler.h> | ||
3 | /* | ||
4 | * Function: v7_early_abort | ||
5 | * | ||
6 | * Params : r2 = address of aborted instruction | ||
7 | * : r3 = saved SPSR | ||
8 | * | ||
9 | * Returns : r0 = address of abort | ||
10 | * : r1 = FSR, bit 11 = write | ||
11 | * : r2-r8 = corrupted | ||
12 | * : r9 = preserved | ||
13 | * : sp = pointer to registers | ||
14 | * | ||
15 | * Purpose : obtain information about current aborted instruction. | ||
16 | */ | ||
17 | .align 5 | ||
18 | ENTRY(v7_early_abort) | ||
19 | /* | ||
20 | * The effect of data aborts on on the exclusive access monitor are | ||
21 | * UNPREDICTABLE. Do a CLREX to clear the state | ||
22 | */ | ||
23 | clrex | ||
24 | |||
25 | mrc p15, 0, r1, c5, c0, 0 @ get FSR | ||
26 | mrc p15, 0, r0, c6, c0, 0 @ get FAR | ||
27 | |||
28 | /* | ||
29 | * V6 code adjusts the returned DFSR. | ||
30 | * New designs should not need to patch up faults. | ||
31 | */ | ||
32 | mov pc, lr | ||
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S new file mode 100644 index 000000000000..35ffc4d95997 --- /dev/null +++ b/arch/arm/mm/cache-v7.S | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/cache-v7.S | ||
3 | * | ||
4 | * Copyright (C) 2001 Deep Blue Solutions Ltd. | ||
5 | * Copyright (C) 2005 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This is the "shell" of the ARMv7 processor support. | ||
12 | */ | ||
13 | #include <linux/linkage.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <asm/assembler.h> | ||
16 | |||
17 | #include "proc-macros.S" | ||
18 | |||
19 | /* | ||
20 | * v7_flush_dcache_all() | ||
21 | * | ||
22 | * Flush the whole D-cache. | ||
23 | * | ||
24 | * Corrupted registers: r0-r5, r7, r9-r11 | ||
25 | * | ||
26 | * - mm - mm_struct describing address space | ||
27 | */ | ||
28 | ENTRY(v7_flush_dcache_all) | ||
29 | mrc p15, 1, r0, c0, c0, 1 @ read clidr | ||
30 | ands r3, r0, #0x7000000 @ extract loc from clidr | ||
31 | mov r3, r3, lsr #23 @ left align loc bit field | ||
32 | beq finished @ if loc is 0, then no need to clean | ||
33 | mov r10, #0 @ start clean at cache level 0 | ||
34 | loop1: | ||
35 | add r2, r10, r10, lsr #1 @ work out 3x current cache level | ||
36 | mov r1, r0, lsr r2 @ extract cache type bits from clidr | ||
37 | and r1, r1, #7 @ mask of the bits for current cache only | ||
38 | cmp r1, #2 @ see what cache we have at this level | ||
39 | blt skip @ skip if no cache, or just i-cache | ||
40 | mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr | ||
41 | isb @ isb to sych the new cssr&csidr | ||
42 | mrc p15, 1, r1, c0, c0, 0 @ read the new csidr | ||
43 | and r2, r1, #7 @ extract the length of the cache lines | ||
44 | add r2, r2, #4 @ add 4 (line length offset) | ||
45 | ldr r4, =0x3ff | ||
46 | ands r4, r4, r1, lsr #3 @ find maximum number on the way size | ||
47 | clz r5, r4 @ find bit position of way size increment | ||
48 | ldr r7, =0x7fff | ||
49 | ands r7, r7, r1, lsr #13 @ extract max number of the index size | ||
50 | loop2: | ||
51 | mov r9, r4 @ create working copy of max way size | ||
52 | loop3: | ||
53 | orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 | ||
54 | orr r11, r11, r7, lsl r2 @ factor index number into r11 | ||
55 | mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way | ||
56 | subs r9, r9, #1 @ decrement the way | ||
57 | bge loop3 | ||
58 | subs r7, r7, #1 @ decrement the index | ||
59 | bge loop2 | ||
60 | skip: | ||
61 | add r10, r10, #2 @ increment cache number | ||
62 | cmp r3, r10 | ||
63 | bgt loop1 | ||
64 | finished: | ||
65 | mov r10, #0 @ swith back to cache level 0 | ||
66 | mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr | ||
67 | isb | ||
68 | mov pc, lr | ||
69 | |||
70 | /* | ||
71 | * v7_flush_cache_all() | ||
72 | * | ||
73 | * Flush the entire cache system. | ||
74 | * The data cache flush is now achieved using atomic clean / invalidates | ||
75 | * working outwards from L1 cache. This is done using Set/Way based cache | ||
76 | * maintainance instructions. | ||
77 | * The instruction cache can still be invalidated back to the point of | ||
78 | * unification in a single instruction. | ||
79 | * | ||
80 | */ | ||
81 | ENTRY(v7_flush_kern_cache_all) | ||
82 | stmfd sp!, {r4-r5, r7, r9-r11, lr} | ||
83 | bl v7_flush_dcache_all | ||
84 | mov r0, #0 | ||
85 | mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate | ||
86 | ldmfd sp!, {r4-r5, r7, r9-r11, lr} | ||
87 | mov pc, lr | ||
88 | |||
89 | /* | ||
90 | * v7_flush_cache_all() | ||
91 | * | ||
92 | * Flush all TLB entries in a particular address space | ||
93 | * | ||
94 | * - mm - mm_struct describing address space | ||
95 | */ | ||
96 | ENTRY(v7_flush_user_cache_all) | ||
97 | /*FALLTHROUGH*/ | ||
98 | |||
99 | /* | ||
100 | * v7_flush_cache_range(start, end, flags) | ||
101 | * | ||
102 | * Flush a range of TLB entries in the specified address space. | ||
103 | * | ||
104 | * - start - start address (may not be aligned) | ||
105 | * - end - end address (exclusive, may not be aligned) | ||
106 | * - flags - vm_area_struct flags describing address space | ||
107 | * | ||
108 | * It is assumed that: | ||
109 | * - we have a VIPT cache. | ||
110 | */ | ||
111 | ENTRY(v7_flush_user_cache_range) | ||
112 | mov pc, lr | ||
113 | |||
114 | /* | ||
115 | * v7_coherent_kern_range(start,end) | ||
116 | * | ||
117 | * Ensure that the I and D caches are coherent within specified | ||
118 | * region. This is typically used when code has been written to | ||
119 | * a memory region, and will be executed. | ||
120 | * | ||
121 | * - start - virtual start address of region | ||
122 | * - end - virtual end address of region | ||
123 | * | ||
124 | * It is assumed that: | ||
125 | * - the Icache does not read data from the write buffer | ||
126 | */ | ||
127 | ENTRY(v7_coherent_kern_range) | ||
128 | /* FALLTHROUGH */ | ||
129 | |||
130 | /* | ||
131 | * v7_coherent_user_range(start,end) | ||
132 | * | ||
133 | * Ensure that the I and D caches are coherent within specified | ||
134 | * region. This is typically used when code has been written to | ||
135 | * a memory region, and will be executed. | ||
136 | * | ||
137 | * - start - virtual start address of region | ||
138 | * - end - virtual end address of region | ||
139 | * | ||
140 | * It is assumed that: | ||
141 | * - the Icache does not read data from the write buffer | ||
142 | */ | ||
143 | ENTRY(v7_coherent_user_range) | ||
144 | dcache_line_size r2, r3 | ||
145 | sub r3, r2, #1 | ||
146 | bic r0, r0, r3 | ||
147 | 1: mcr p15, 0, r0, c7, c11, 1 @ clean D line to the point of unification | ||
148 | dsb | ||
149 | mcr p15, 0, r0, c7, c5, 1 @ invalidate I line | ||
150 | add r0, r0, r2 | ||
151 | cmp r0, r1 | ||
152 | blo 1b | ||
153 | mov r0, #0 | ||
154 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB | ||
155 | dsb | ||
156 | isb | ||
157 | mov pc, lr | ||
158 | |||
159 | /* | ||
160 | * v7_flush_kern_dcache_page(kaddr) | ||
161 | * | ||
162 | * Ensure that the data held in the page kaddr is written back | ||
163 | * to the page in question. | ||
164 | * | ||
165 | * - kaddr - kernel address (guaranteed to be page aligned) | ||
166 | */ | ||
167 | ENTRY(v7_flush_kern_dcache_page) | ||
168 | dcache_line_size r2, r3 | ||
169 | add r1, r0, #PAGE_SZ | ||
170 | 1: | ||
171 | mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line | ||
172 | add r0, r0, r2 | ||
173 | cmp r0, r1 | ||
174 | blo 1b | ||
175 | dsb | ||
176 | mov pc, lr | ||
177 | |||
178 | /* | ||
179 | * v7_dma_inv_range(start,end) | ||
180 | * | ||
181 | * Invalidate the data cache within the specified region; we will | ||
182 | * be performing a DMA operation in this region and we want to | ||
183 | * purge old data in the cache. | ||
184 | * | ||
185 | * - start - virtual start address of region | ||
186 | * - end - virtual end address of region | ||
187 | */ | ||
188 | ENTRY(v7_dma_inv_range) | ||
189 | dcache_line_size r2, r3 | ||
190 | sub r3, r2, #1 | ||
191 | tst r0, r3 | ||
192 | bic r0, r0, r3 | ||
193 | mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line | ||
194 | |||
195 | tst r1, r3 | ||
196 | bic r1, r1, r3 | ||
197 | mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D / U line | ||
198 | 1: | ||
199 | mcr p15, 0, r0, c7, c6, 1 @ invalidate D / U line | ||
200 | add r0, r0, r2 | ||
201 | cmp r0, r1 | ||
202 | blo 1b | ||
203 | dsb | ||
204 | mov pc, lr | ||
205 | |||
206 | /* | ||
207 | * v7_dma_clean_range(start,end) | ||
208 | * - start - virtual start address of region | ||
209 | * - end - virtual end address of region | ||
210 | */ | ||
211 | ENTRY(v7_dma_clean_range) | ||
212 | dcache_line_size r2, r3 | ||
213 | sub r3, r2, #1 | ||
214 | bic r0, r0, r3 | ||
215 | 1: | ||
216 | mcr p15, 0, r0, c7, c10, 1 @ clean D / U line | ||
217 | add r0, r0, r2 | ||
218 | cmp r0, r1 | ||
219 | blo 1b | ||
220 | dsb | ||
221 | mov pc, lr | ||
222 | |||
223 | /* | ||
224 | * v7_dma_flush_range(start,end) | ||
225 | * - start - virtual start address of region | ||
226 | * - end - virtual end address of region | ||
227 | */ | ||
228 | ENTRY(v7_dma_flush_range) | ||
229 | dcache_line_size r2, r3 | ||
230 | sub r3, r2, #1 | ||
231 | bic r0, r0, r3 | ||
232 | 1: | ||
233 | mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line | ||
234 | add r0, r0, r2 | ||
235 | cmp r0, r1 | ||
236 | blo 1b | ||
237 | dsb | ||
238 | mov pc, lr | ||
239 | |||
240 | __INITDATA | ||
241 | |||
242 | .type v7_cache_fns, #object | ||
243 | ENTRY(v7_cache_fns) | ||
244 | .long v7_flush_kern_cache_all | ||
245 | .long v7_flush_user_cache_all | ||
246 | .long v7_flush_user_cache_range | ||
247 | .long v7_coherent_kern_range | ||
248 | .long v7_coherent_user_range | ||
249 | .long v7_flush_kern_dcache_page | ||
250 | .long v7_dma_inv_range | ||
251 | .long v7_dma_clean_range | ||
252 | .long v7_dma_flush_range | ||
253 | .size v7_cache_fns, . - v7_cache_fns | ||
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 9da43a0fdcdf..fc84fcc74380 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c | |||
@@ -14,7 +14,8 @@ | |||
14 | #include <asm/mmu_context.h> | 14 | #include <asm/mmu_context.h> |
15 | #include <asm/tlbflush.h> | 15 | #include <asm/tlbflush.h> |
16 | 16 | ||
17 | unsigned int cpu_last_asid = { 1 << ASID_BITS }; | 17 | static DEFINE_SPINLOCK(cpu_asid_lock); |
18 | unsigned int cpu_last_asid = ASID_FIRST_VERSION; | ||
18 | 19 | ||
19 | /* | 20 | /* |
20 | * We fork()ed a process, and we need a new context for the child | 21 | * We fork()ed a process, and we need a new context for the child |
@@ -31,15 +32,16 @@ void __new_context(struct mm_struct *mm) | |||
31 | { | 32 | { |
32 | unsigned int asid; | 33 | unsigned int asid; |
33 | 34 | ||
35 | spin_lock(&cpu_asid_lock); | ||
34 | asid = ++cpu_last_asid; | 36 | asid = ++cpu_last_asid; |
35 | if (asid == 0) | 37 | if (asid == 0) |
36 | asid = cpu_last_asid = 1 << ASID_BITS; | 38 | asid = cpu_last_asid = ASID_FIRST_VERSION; |
37 | 39 | ||
38 | /* | 40 | /* |
39 | * If we've used up all our ASIDs, we need | 41 | * If we've used up all our ASIDs, we need |
40 | * to start a new version and flush the TLB. | 42 | * to start a new version and flush the TLB. |
41 | */ | 43 | */ |
42 | if ((asid & ~ASID_MASK) == 0) { | 44 | if (unlikely((asid & ~ASID_MASK) == 0)) { |
43 | asid = ++cpu_last_asid; | 45 | asid = ++cpu_last_asid; |
44 | /* set the reserved ASID before flushing the TLB */ | 46 | /* set the reserved ASID before flushing the TLB */ |
45 | asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n" | 47 | asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n" |
@@ -47,7 +49,16 @@ void __new_context(struct mm_struct *mm) | |||
47 | : "r" (0)); | 49 | : "r" (0)); |
48 | isb(); | 50 | isb(); |
49 | flush_tlb_all(); | 51 | flush_tlb_all(); |
52 | if (icache_is_vivt_asid_tagged()) { | ||
53 | asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" | ||
54 | "mcr p15, 0, %0, c7, c5, 6 @ flush BTAC/BTB\n" | ||
55 | : | ||
56 | : "r" (0)); | ||
57 | dsb(); | ||
58 | } | ||
50 | } | 59 | } |
60 | spin_unlock(&cpu_asid_lock); | ||
51 | 61 | ||
62 | mm->cpu_vm_mask = cpumask_of_cpu(smp_processor_id()); | ||
52 | mm->context.id = asid; | 63 | mm->context.id = asid; |
53 | } | 64 | } |
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 9e2c89eb2115..b13150052a76 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S | |||
@@ -59,3 +59,15 @@ | |||
59 | .word \ucset | 59 | .word \ucset |
60 | #endif | 60 | #endif |
61 | .endm | 61 | .endm |
62 | |||
63 | /* | ||
64 | * cache_line_size - get the cache line size from the CSIDR register | ||
65 | * (available on ARMv7+). It assumes that the CSSR register was configured | ||
66 | * to access the L1 data cache CSIDR. | ||
67 | */ | ||
68 | .macro dcache_line_size, reg, tmp | ||
69 | mrc p15, 1, \tmp, c0, c0, 0 @ read CSIDR | ||
70 | and \tmp, \tmp, #7 @ cache line size encoding | ||
71 | mov \reg, #16 @ size offset | ||
72 | mov \reg, \reg, lsl \tmp @ actual cache line size | ||
73 | .endm | ||
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S new file mode 100644 index 000000000000..dd823dd4a374 --- /dev/null +++ b/arch/arm/mm/proc-v7.S | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mm/proc-v7.S | ||
3 | * | ||
4 | * Copyright (C) 2001 Deep Blue Solutions Ltd. | ||
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 | * This is the "shell" of the ARMv7 processor support. | ||
11 | */ | ||
12 | #include <linux/linkage.h> | ||
13 | #include <asm/assembler.h> | ||
14 | #include <asm/asm-offsets.h> | ||
15 | #include <asm/elf.h> | ||
16 | #include <asm/pgtable-hwdef.h> | ||
17 | #include <asm/pgtable.h> | ||
18 | |||
19 | #include "proc-macros.S" | ||
20 | |||
21 | #define TTB_C (1 << 0) | ||
22 | #define TTB_S (1 << 1) | ||
23 | #define TTB_RGN_OC_WT (2 << 3) | ||
24 | #define TTB_RGN_OC_WB (3 << 3) | ||
25 | |||
26 | ENTRY(cpu_v7_proc_init) | ||
27 | mov pc, lr | ||
28 | |||
29 | ENTRY(cpu_v7_proc_fin) | ||
30 | mov pc, lr | ||
31 | |||
32 | /* | ||
33 | * cpu_v7_reset(loc) | ||
34 | * | ||
35 | * Perform a soft reset of the system. Put the CPU into the | ||
36 | * same state as it would be if it had been reset, and branch | ||
37 | * to what would be the reset vector. | ||
38 | * | ||
39 | * - loc - location to jump to for soft reset | ||
40 | * | ||
41 | * It is assumed that: | ||
42 | */ | ||
43 | .align 5 | ||
44 | ENTRY(cpu_v7_reset) | ||
45 | mov pc, r0 | ||
46 | |||
47 | /* | ||
48 | * cpu_v7_do_idle() | ||
49 | * | ||
50 | * Idle the processor (eg, wait for interrupt). | ||
51 | * | ||
52 | * IRQs are already disabled. | ||
53 | */ | ||
54 | ENTRY(cpu_v7_do_idle) | ||
55 | .long 0xe320f003 @ ARM V7 WFI instruction | ||
56 | mov pc, lr | ||
57 | |||
58 | ENTRY(cpu_v7_dcache_clean_area) | ||
59 | #ifndef TLB_CAN_READ_FROM_L1_CACHE | ||
60 | dcache_line_size r2, r3 | ||
61 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
62 | add r0, r0, r2 | ||
63 | subs r1, r1, r2 | ||
64 | bhi 1b | ||
65 | dsb | ||
66 | #endif | ||
67 | mov pc, lr | ||
68 | |||
69 | /* | ||
70 | * cpu_v7_switch_mm(pgd_phys, tsk) | ||
71 | * | ||
72 | * Set the translation table base pointer to be pgd_phys | ||
73 | * | ||
74 | * - pgd_phys - physical address of new TTB | ||
75 | * | ||
76 | * It is assumed that: | ||
77 | * - we are not using split page tables | ||
78 | */ | ||
79 | ENTRY(cpu_v7_switch_mm) | ||
80 | mov r2, #0 | ||
81 | ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id | ||
82 | orr r0, r0, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB | ||
83 | mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID | ||
84 | isb | ||
85 | 1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 | ||
86 | isb | ||
87 | mcr p15, 0, r1, c13, c0, 1 @ set context ID | ||
88 | isb | ||
89 | mov pc, lr | ||
90 | |||
91 | /* | ||
92 | * cpu_v7_set_pte_ext(ptep, pte) | ||
93 | * | ||
94 | * Set a level 2 translation table entry. | ||
95 | * | ||
96 | * - ptep - pointer to level 2 translation table entry | ||
97 | * (hardware version is stored at -1024 bytes) | ||
98 | * - pte - PTE value to store | ||
99 | * - ext - value for extended PTE bits | ||
100 | * | ||
101 | * Permissions: | ||
102 | * YUWD APX AP1 AP0 SVC User | ||
103 | * 0xxx 0 0 0 no acc no acc | ||
104 | * 100x 1 0 1 r/o no acc | ||
105 | * 10x0 1 0 1 r/o no acc | ||
106 | * 1011 0 0 1 r/w no acc | ||
107 | * 110x 0 1 0 r/w r/o | ||
108 | * 11x0 0 1 0 r/w r/o | ||
109 | * 1111 0 1 1 r/w r/w | ||
110 | */ | ||
111 | ENTRY(cpu_v7_set_pte_ext) | ||
112 | str r1, [r0], #-2048 @ linux version | ||
113 | |||
114 | bic r3, r1, #0x000003f0 | ||
115 | bic r3, r3, #0x00000003 | ||
116 | orr r3, r3, r2 | ||
117 | orr r3, r3, #PTE_EXT_AP0 | 2 | ||
118 | |||
119 | tst r1, #L_PTE_WRITE | ||
120 | tstne r1, #L_PTE_DIRTY | ||
121 | orreq r3, r3, #PTE_EXT_APX | ||
122 | |||
123 | tst r1, #L_PTE_USER | ||
124 | orrne r3, r3, #PTE_EXT_AP1 | ||
125 | tstne r3, #PTE_EXT_APX | ||
126 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | ||
127 | |||
128 | tst r1, #L_PTE_YOUNG | ||
129 | biceq r3, r3, #PTE_EXT_APX | PTE_EXT_AP_MASK | ||
130 | |||
131 | tst r1, #L_PTE_EXEC | ||
132 | orreq r3, r3, #PTE_EXT_XN | ||
133 | |||
134 | tst r1, #L_PTE_PRESENT | ||
135 | moveq r3, #0 | ||
136 | |||
137 | str r3, [r0] | ||
138 | mcr p15, 0, r0, c7, c10, 1 @ flush_pte | ||
139 | mov pc, lr | ||
140 | |||
141 | cpu_v7_name: | ||
142 | .ascii "ARMv7 Processor" | ||
143 | .align | ||
144 | |||
145 | .section ".text.init", #alloc, #execinstr | ||
146 | |||
147 | /* | ||
148 | * __v7_setup | ||
149 | * | ||
150 | * Initialise TLB, Caches, and MMU state ready to switch the MMU | ||
151 | * on. Return in r0 the new CP15 C1 control register setting. | ||
152 | * | ||
153 | * We automatically detect if we have a Harvard cache, and use the | ||
154 | * Harvard cache control instructions insead of the unified cache | ||
155 | * control instructions. | ||
156 | * | ||
157 | * This should be able to cover all ARMv7 cores. | ||
158 | * | ||
159 | * It is assumed that: | ||
160 | * - cache type register is implemented | ||
161 | */ | ||
162 | __v7_setup: | ||
163 | adr r12, __v7_setup_stack @ the local stack | ||
164 | stmia r12, {r0-r5, r7, r9, r11, lr} | ||
165 | bl v7_flush_dcache_all | ||
166 | ldmia r12, {r0-r5, r7, r9, r11, lr} | ||
167 | mov r10, #0 | ||
168 | #ifdef HARVARD_CACHE | ||
169 | mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate | ||
170 | #endif | ||
171 | dsb | ||
172 | mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs | ||
173 | mcr p15, 0, r10, c2, c0, 2 @ TTB control register | ||
174 | orr r4, r4, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB | ||
175 | mcr p15, 0, r4, c2, c0, 0 @ load TTB0 | ||
176 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 | ||
177 | mov r10, #0x1f @ domains 0, 1 = manager | ||
178 | mcr p15, 0, r10, c3, c0, 0 @ load domain access register | ||
179 | #ifndef CONFIG_CPU_L2CACHE_DISABLE | ||
180 | @ L2 cache configuration in the L2 aux control register | ||
181 | mrc p15, 1, r10, c9, c0, 2 | ||
182 | bic r10, r10, #(1 << 16) @ L2 outer cache | ||
183 | mcr p15, 1, r10, c9, c0, 2 | ||
184 | @ L2 cache is enabled in the aux control register | ||
185 | mrc p15, 0, r10, c1, c0, 1 | ||
186 | orr r10, r10, #2 | ||
187 | mcr p15, 0, r10, c1, c0, 1 | ||
188 | #endif | ||
189 | mrc p15, 0, r0, c1, c0, 0 @ read control register | ||
190 | ldr r10, cr1_clear @ get mask for bits to clear | ||
191 | bic r0, r0, r10 @ clear bits them | ||
192 | ldr r10, cr1_set @ get mask for bits to set | ||
193 | orr r0, r0, r10 @ set them | ||
194 | mov pc, lr @ return to head.S:__ret | ||
195 | |||
196 | /* | ||
197 | * V X F I D LR | ||
198 | * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM | ||
199 | * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced | ||
200 | * 0 110 0011 1.00 .111 1101 < we want | ||
201 | */ | ||
202 | .type cr1_clear, #object | ||
203 | .type cr1_set, #object | ||
204 | cr1_clear: | ||
205 | .word 0x0120c302 | ||
206 | cr1_set: | ||
207 | .word 0x00c0387d | ||
208 | |||
209 | __v7_setup_stack: | ||
210 | .space 4 * 11 @ 11 registers | ||
211 | |||
212 | .type v7_processor_functions, #object | ||
213 | ENTRY(v7_processor_functions) | ||
214 | .word v7_early_abort | ||
215 | .word cpu_v7_proc_init | ||
216 | .word cpu_v7_proc_fin | ||
217 | .word cpu_v7_reset | ||
218 | .word cpu_v7_do_idle | ||
219 | .word cpu_v7_dcache_clean_area | ||
220 | .word cpu_v7_switch_mm | ||
221 | .word cpu_v7_set_pte_ext | ||
222 | .size v7_processor_functions, . - v7_processor_functions | ||
223 | |||
224 | .type cpu_arch_name, #object | ||
225 | cpu_arch_name: | ||
226 | .asciz "armv7" | ||
227 | .size cpu_arch_name, . - cpu_arch_name | ||
228 | |||
229 | .type cpu_elf_name, #object | ||
230 | cpu_elf_name: | ||
231 | .asciz "v7" | ||
232 | .size cpu_elf_name, . - cpu_elf_name | ||
233 | .align | ||
234 | |||
235 | .section ".proc.info.init", #alloc, #execinstr | ||
236 | |||
237 | /* | ||
238 | * Match any ARMv7 processor core. | ||
239 | */ | ||
240 | .type __v7_proc_info, #object | ||
241 | __v7_proc_info: | ||
242 | .long 0x000f0000 @ Required ID value | ||
243 | .long 0x000f0000 @ Mask for ID | ||
244 | .long PMD_TYPE_SECT | \ | ||
245 | PMD_SECT_BUFFERABLE | \ | ||
246 | PMD_SECT_CACHEABLE | \ | ||
247 | PMD_SECT_AP_WRITE | \ | ||
248 | PMD_SECT_AP_READ | ||
249 | .long PMD_TYPE_SECT | \ | ||
250 | PMD_SECT_XN | \ | ||
251 | PMD_SECT_AP_WRITE | \ | ||
252 | PMD_SECT_AP_READ | ||
253 | b __v7_setup | ||
254 | .long cpu_arch_name | ||
255 | .long cpu_elf_name | ||
256 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP | ||
257 | .long cpu_v7_name | ||
258 | .long v7_processor_functions | ||
259 | .long v6wbi_tlb_fns | ||
260 | .long v6_user_fns | ||
261 | .long v7_cache_fns | ||
262 | .size __v7_proc_info, . - __v7_proc_info | ||
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 9e8d21eca4ec..cfc69f3842fd 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -20,6 +20,11 @@ endchoice | |||
20 | 20 | ||
21 | comment "OMAP Feature Selections" | 21 | comment "OMAP Feature Selections" |
22 | 22 | ||
23 | config OMAP_DEBUG_LEDS | ||
24 | bool | ||
25 | help | ||
26 | For debug card leds on TI reference boards. | ||
27 | |||
23 | config OMAP_RESET_CLOCKS | 28 | config OMAP_RESET_CLOCKS |
24 | bool "Reset unused clocks during boot" | 29 | bool "Reset unused clocks during boot" |
25 | depends on ARCH_OMAP | 30 | depends on ARCH_OMAP |
@@ -58,6 +63,14 @@ config OMAP_MUX_WARNINGS | |||
58 | to change the pin multiplexing setup. When there are no warnings | 63 | to change the pin multiplexing setup. When there are no warnings |
59 | printed, it's safe to deselect OMAP_MUX for your product. | 64 | printed, it's safe to deselect OMAP_MUX for your product. |
60 | 65 | ||
66 | config OMAP_MCBSP | ||
67 | bool "McBSP support" | ||
68 | depends on ARCH_OMAP | ||
69 | default y | ||
70 | help | ||
71 | Say Y here if you want support for the OMAP Multichannel | ||
72 | Buffered Serial Port. | ||
73 | |||
61 | choice | 74 | choice |
62 | prompt "System timer" | 75 | prompt "System timer" |
63 | default OMAP_MPU_TIMER | 76 | default OMAP_MPU_TIMER |
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 2896b4546411..41a3c1cf3bd4 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile | |||
@@ -3,7 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o | 6 | obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o \ |
7 | usb.o fb.o | ||
7 | obj-m := | 8 | obj-m := |
8 | obj-n := | 9 | obj-n := |
9 | obj- := | 10 | obj- := |
@@ -16,4 +17,4 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o | |||
16 | 17 | ||
17 | obj-$(CONFIG_CPU_FREQ) += cpu-omap.o | 18 | obj-$(CONFIG_CPU_FREQ) += cpu-omap.o |
18 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o | 19 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o |
19 | 20 | obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o | |
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index f1179ad4be1b..0a603242f367 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c | |||
@@ -33,6 +33,41 @@ static DEFINE_SPINLOCK(clockfw_lock); | |||
33 | 33 | ||
34 | static struct clk_functions *arch_clock; | 34 | static struct clk_functions *arch_clock; |
35 | 35 | ||
36 | #ifdef CONFIG_PM_DEBUG | ||
37 | |||
38 | static void print_parents(struct clk *clk) | ||
39 | { | ||
40 | struct clk *p; | ||
41 | int printed = 0; | ||
42 | |||
43 | list_for_each_entry(p, &clocks, node) { | ||
44 | if (p->parent == clk && p->usecount) { | ||
45 | if (!clk->usecount && !printed) { | ||
46 | printk("MISMATCH: %s\n", clk->name); | ||
47 | printed = 1; | ||
48 | } | ||
49 | printk("\t%-15s\n", p->name); | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | void clk_print_usecounts(void) | ||
55 | { | ||
56 | unsigned long flags; | ||
57 | struct clk *p; | ||
58 | |||
59 | spin_lock_irqsave(&clockfw_lock, flags); | ||
60 | list_for_each_entry(p, &clocks, node) { | ||
61 | if (p->usecount) | ||
62 | printk("%-15s: %d\n", p->name, p->usecount); | ||
63 | print_parents(p); | ||
64 | |||
65 | } | ||
66 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
67 | } | ||
68 | |||
69 | #endif | ||
70 | |||
36 | /*------------------------------------------------------------------------- | 71 | /*------------------------------------------------------------------------- |
37 | * Standard clock functions defined in include/linux/clk.h | 72 | * Standard clock functions defined in include/linux/clk.h |
38 | *-------------------------------------------------------------------------*/ | 73 | *-------------------------------------------------------------------------*/ |
@@ -249,6 +284,8 @@ void followparent_recalc(struct clk *clk) | |||
249 | return; | 284 | return; |
250 | 285 | ||
251 | clk->rate = clk->parent->rate; | 286 | clk->rate = clk->parent->rate; |
287 | if (unlikely(clk->flags & RATE_PROPAGATES)) | ||
288 | propagate_rate(clk); | ||
252 | } | 289 | } |
253 | 290 | ||
254 | /* Propagate rate to children */ | 291 | /* Propagate rate to children */ |
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index fecd3d625995..dd8708ad0a71 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c | |||
@@ -93,8 +93,12 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) | |||
93 | * in the kernel. */ | 93 | * in the kernel. */ |
94 | for (i = 0; i < omap_board_config_size; i++) { | 94 | for (i = 0; i < omap_board_config_size; i++) { |
95 | if (omap_board_config[i].tag == tag) { | 95 | if (omap_board_config[i].tag == tag) { |
96 | kinfo = &omap_board_config[i]; | 96 | if (skip == 0) { |
97 | break; | 97 | kinfo = &omap_board_config[i]; |
98 | break; | ||
99 | } else { | ||
100 | skip--; | ||
101 | } | ||
98 | } | 102 | } |
99 | } | 103 | } |
100 | if (kinfo == NULL) | 104 | if (kinfo == NULL) |
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c new file mode 100644 index 000000000000..9128a80d228f --- /dev/null +++ b/arch/arm/plat-omap/debug-leds.c | |||
@@ -0,0 +1,314 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/debug-leds.c | ||
3 | * | ||
4 | * Copyright 2003 by Texas Instruments Incorporated | ||
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 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/leds.h> | ||
14 | |||
15 | #include <asm/io.h> | ||
16 | #include <asm/hardware.h> | ||
17 | #include <asm/leds.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/mach-types.h> | ||
20 | |||
21 | #include <asm/arch/fpga.h> | ||
22 | #include <asm/arch/gpio.h> | ||
23 | |||
24 | |||
25 | /* Many OMAP development platforms reuse the same "debug board"; these | ||
26 | * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the | ||
27 | * debug board (all green), accessed through FPGA registers. | ||
28 | * | ||
29 | * The "surfer" expansion board and H2 sample board also have two-color | ||
30 | * green+red LEDs (in parallel), used here for timer and idle indicators | ||
31 | * in preference to the ones on the debug board, for a "Disco LED" effect. | ||
32 | * | ||
33 | * This driver exports either the original ARM LED API, the new generic | ||
34 | * one, or both. | ||
35 | */ | ||
36 | |||
37 | static spinlock_t lock; | ||
38 | static struct h2p2_dbg_fpga __iomem *fpga; | ||
39 | static u16 led_state, hw_led_state; | ||
40 | |||
41 | |||
42 | #ifdef CONFIG_LEDS_OMAP_DEBUG | ||
43 | #define new_led_api() 1 | ||
44 | #else | ||
45 | #define new_led_api() 0 | ||
46 | #endif | ||
47 | |||
48 | |||
49 | /*-------------------------------------------------------------------------*/ | ||
50 | |||
51 | /* original ARM debug LED API: | ||
52 | * - timer and idle leds (some boards use non-FPGA leds here); | ||
53 | * - up to 4 generic leds, easily accessed in-kernel (any context) | ||
54 | */ | ||
55 | |||
56 | #define GPIO_LED_RED 3 | ||
57 | #define GPIO_LED_GREEN OMAP_MPUIO(4) | ||
58 | |||
59 | #define LED_STATE_ENABLED 0x01 | ||
60 | #define LED_STATE_CLAIMED 0x02 | ||
61 | #define LED_TIMER_ON 0x04 | ||
62 | |||
63 | #define GPIO_IDLE GPIO_LED_GREEN | ||
64 | #define GPIO_TIMER GPIO_LED_RED | ||
65 | |||
66 | static void h2p2_dbg_leds_event(led_event_t evt) | ||
67 | { | ||
68 | unsigned long flags; | ||
69 | |||
70 | spin_lock_irqsave(&lock, flags); | ||
71 | |||
72 | if (!(led_state & LED_STATE_ENABLED) && evt != led_start) | ||
73 | goto done; | ||
74 | |||
75 | switch (evt) { | ||
76 | case led_start: | ||
77 | if (fpga) | ||
78 | led_state |= LED_STATE_ENABLED; | ||
79 | break; | ||
80 | |||
81 | case led_stop: | ||
82 | case led_halted: | ||
83 | /* all leds off during suspend or shutdown */ | ||
84 | |||
85 | if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) { | ||
86 | omap_set_gpio_dataout(GPIO_TIMER, 0); | ||
87 | omap_set_gpio_dataout(GPIO_IDLE, 0); | ||
88 | } | ||
89 | |||
90 | __raw_writew(~0, &fpga->leds); | ||
91 | led_state &= ~LED_STATE_ENABLED; | ||
92 | goto done; | ||
93 | |||
94 | case led_claim: | ||
95 | led_state |= LED_STATE_CLAIMED; | ||
96 | hw_led_state = 0; | ||
97 | break; | ||
98 | |||
99 | case led_release: | ||
100 | led_state &= ~LED_STATE_CLAIMED; | ||
101 | break; | ||
102 | |||
103 | #ifdef CONFIG_LEDS_TIMER | ||
104 | case led_timer: | ||
105 | led_state ^= LED_TIMER_ON; | ||
106 | |||
107 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
108 | hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; | ||
109 | else { | ||
110 | omap_set_gpio_dataout(GPIO_TIMER, | ||
111 | led_state & LED_TIMER_ON); | ||
112 | goto done; | ||
113 | } | ||
114 | |||
115 | break; | ||
116 | #endif | ||
117 | |||
118 | #ifdef CONFIG_LEDS_CPU | ||
119 | /* LED lit iff busy */ | ||
120 | case led_idle_start: | ||
121 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
122 | hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; | ||
123 | else { | ||
124 | omap_set_gpio_dataout(GPIO_IDLE, 1); | ||
125 | goto done; | ||
126 | } | ||
127 | |||
128 | break; | ||
129 | |||
130 | case led_idle_end: | ||
131 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
132 | hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; | ||
133 | else { | ||
134 | omap_set_gpio_dataout(GPIO_IDLE, 0); | ||
135 | goto done; | ||
136 | } | ||
137 | |||
138 | break; | ||
139 | #endif | ||
140 | |||
141 | case led_green_on: | ||
142 | hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; | ||
143 | break; | ||
144 | case led_green_off: | ||
145 | hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; | ||
146 | break; | ||
147 | |||
148 | case led_amber_on: | ||
149 | hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; | ||
150 | break; | ||
151 | case led_amber_off: | ||
152 | hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; | ||
153 | break; | ||
154 | |||
155 | case led_red_on: | ||
156 | hw_led_state |= H2P2_DBG_FPGA_LED_RED; | ||
157 | break; | ||
158 | case led_red_off: | ||
159 | hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; | ||
160 | break; | ||
161 | |||
162 | case led_blue_on: | ||
163 | hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; | ||
164 | break; | ||
165 | case led_blue_off: | ||
166 | hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; | ||
167 | break; | ||
168 | |||
169 | default: | ||
170 | break; | ||
171 | } | ||
172 | |||
173 | |||
174 | /* | ||
175 | * Actually burn the LEDs | ||
176 | */ | ||
177 | if (led_state & LED_STATE_ENABLED) | ||
178 | __raw_writew(~hw_led_state, &fpga->leds); | ||
179 | |||
180 | done: | ||
181 | spin_unlock_irqrestore(&lock, flags); | ||
182 | } | ||
183 | |||
184 | /*-------------------------------------------------------------------------*/ | ||
185 | |||
186 | /* "new" LED API | ||
187 | * - with syfs access and generic triggering | ||
188 | * - not readily accessible to in-kernel drivers | ||
189 | */ | ||
190 | |||
191 | struct dbg_led { | ||
192 | struct led_classdev cdev; | ||
193 | u16 mask; | ||
194 | }; | ||
195 | |||
196 | static struct dbg_led dbg_leds[] = { | ||
197 | /* REVISIT at least H2 uses different timer & cpu leds... */ | ||
198 | #ifndef CONFIG_LEDS_TIMER | ||
199 | { .mask = 1 << 0, .cdev.name = "d4:green", | ||
200 | .cdev.default_trigger = "heartbeat", }, | ||
201 | #endif | ||
202 | #ifndef CONFIG_LEDS_CPU | ||
203 | { .mask = 1 << 1, .cdev.name = "d5:green", }, /* !idle */ | ||
204 | #endif | ||
205 | { .mask = 1 << 2, .cdev.name = "d6:green", }, | ||
206 | { .mask = 1 << 3, .cdev.name = "d7:green", }, | ||
207 | |||
208 | { .mask = 1 << 4, .cdev.name = "d8:green", }, | ||
209 | { .mask = 1 << 5, .cdev.name = "d9:green", }, | ||
210 | { .mask = 1 << 6, .cdev.name = "d10:green", }, | ||
211 | { .mask = 1 << 7, .cdev.name = "d11:green", }, | ||
212 | |||
213 | { .mask = 1 << 8, .cdev.name = "d12:green", }, | ||
214 | { .mask = 1 << 9, .cdev.name = "d13:green", }, | ||
215 | { .mask = 1 << 10, .cdev.name = "d14:green", }, | ||
216 | { .mask = 1 << 11, .cdev.name = "d15:green", }, | ||
217 | |||
218 | #ifndef CONFIG_LEDS | ||
219 | { .mask = 1 << 12, .cdev.name = "d16:green", }, | ||
220 | { .mask = 1 << 13, .cdev.name = "d17:green", }, | ||
221 | { .mask = 1 << 14, .cdev.name = "d18:green", }, | ||
222 | { .mask = 1 << 15, .cdev.name = "d19:green", }, | ||
223 | #endif | ||
224 | }; | ||
225 | |||
226 | static void | ||
227 | fpga_led_set(struct led_classdev *cdev, enum led_brightness value) | ||
228 | { | ||
229 | struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); | ||
230 | unsigned long flags; | ||
231 | |||
232 | spin_lock_irqsave(&lock, flags); | ||
233 | if (value == LED_OFF) | ||
234 | hw_led_state &= ~led->mask; | ||
235 | else | ||
236 | hw_led_state |= led->mask; | ||
237 | __raw_writew(~hw_led_state, &fpga->leds); | ||
238 | spin_unlock_irqrestore(&lock, flags); | ||
239 | } | ||
240 | |||
241 | static void __init newled_init(struct device *dev) | ||
242 | { | ||
243 | unsigned i; | ||
244 | struct dbg_led *led; | ||
245 | int status; | ||
246 | |||
247 | for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) { | ||
248 | led->cdev.brightness_set = fpga_led_set; | ||
249 | status = led_classdev_register(dev, &led->cdev); | ||
250 | if (status < 0) | ||
251 | break; | ||
252 | } | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | |||
257 | /*-------------------------------------------------------------------------*/ | ||
258 | |||
259 | static int /* __init */ fpga_probe(struct platform_device *pdev) | ||
260 | { | ||
261 | struct resource *iomem; | ||
262 | |||
263 | spin_lock_init(&lock); | ||
264 | |||
265 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
266 | if (!iomem) | ||
267 | return -ENODEV; | ||
268 | |||
269 | fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); | ||
270 | __raw_writew(~0, &fpga->leds); | ||
271 | |||
272 | #ifdef CONFIG_LEDS | ||
273 | leds_event = h2p2_dbg_leds_event; | ||
274 | leds_event(led_start); | ||
275 | #endif | ||
276 | |||
277 | if (new_led_api()) { | ||
278 | newled_init(&pdev->dev); | ||
279 | } | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int fpga_suspend_late(struct platform_device *pdev, pm_message_t mesg) | ||
285 | { | ||
286 | __raw_writew(~0, &fpga->leds); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int fpga_resume_early(struct platform_device *pdev) | ||
291 | { | ||
292 | __raw_writew(~hw_led_state, &fpga->leds); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | |||
297 | static struct platform_driver led_driver = { | ||
298 | .driver.name = "omap_dbg_led", | ||
299 | .probe = fpga_probe, | ||
300 | .suspend_late = fpga_suspend_late, | ||
301 | .resume_early = fpga_resume_early, | ||
302 | }; | ||
303 | |||
304 | static int __init fpga_init(void) | ||
305 | { | ||
306 | if (machine_is_omap_h4() | ||
307 | || machine_is_omap_h3() | ||
308 | || machine_is_omap_h2() | ||
309 | || machine_is_omap_perseus2() | ||
310 | ) | ||
311 | return platform_driver_register(&led_driver); | ||
312 | return 0; | ||
313 | } | ||
314 | fs_initcall(fpga_init); | ||
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index eeb33fed6f7c..c5dab1d6417e 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c | |||
@@ -25,7 +25,71 @@ | |||
25 | #include <asm/arch/gpio.h> | 25 | #include <asm/arch/gpio.h> |
26 | #include <asm/arch/menelaus.h> | 26 | #include <asm/arch/menelaus.h> |
27 | 27 | ||
28 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | 28 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) |
29 | |||
30 | #include "../plat-omap/dsp/dsp_common.h" | ||
31 | |||
32 | static struct dsp_platform_data dsp_pdata = { | ||
33 | .kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list), | ||
34 | }; | ||
35 | |||
36 | static struct resource omap_dsp_resources[] = { | ||
37 | { | ||
38 | .name = "dsp_mmu", | ||
39 | .start = -1, | ||
40 | .flags = IORESOURCE_IRQ, | ||
41 | }, | ||
42 | }; | ||
43 | |||
44 | static struct platform_device omap_dsp_device = { | ||
45 | .name = "dsp", | ||
46 | .id = -1, | ||
47 | .num_resources = ARRAY_SIZE(omap_dsp_resources), | ||
48 | .resource = omap_dsp_resources, | ||
49 | .dev = { | ||
50 | .platform_data = &dsp_pdata, | ||
51 | }, | ||
52 | }; | ||
53 | |||
54 | static inline void omap_init_dsp(void) | ||
55 | { | ||
56 | struct resource *res; | ||
57 | int irq; | ||
58 | |||
59 | if (cpu_is_omap15xx()) | ||
60 | irq = INT_1510_DSP_MMU; | ||
61 | else if (cpu_is_omap16xx()) | ||
62 | irq = INT_1610_DSP_MMU; | ||
63 | else if (cpu_is_omap24xx()) | ||
64 | irq = INT_24XX_DSP_MMU; | ||
65 | |||
66 | res = platform_get_resource_byname(&omap_dsp_device, | ||
67 | IORESOURCE_IRQ, "dsp_mmu"); | ||
68 | res->start = irq; | ||
69 | |||
70 | platform_device_register(&omap_dsp_device); | ||
71 | } | ||
72 | |||
73 | int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev) | ||
74 | { | ||
75 | static DEFINE_MUTEX(dsp_pdata_lock); | ||
76 | |||
77 | mutex_init(&kdev->lock); | ||
78 | |||
79 | mutex_lock(&dsp_pdata_lock); | ||
80 | list_add_tail(&kdev->entry, &dsp_pdata.kdev_list); | ||
81 | mutex_unlock(&dsp_pdata_lock); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | EXPORT_SYMBOL(dsp_kfunc_device_register); | ||
86 | |||
87 | #else | ||
88 | static inline void omap_init_dsp(void) { } | ||
89 | #endif /* CONFIG_OMAP_DSP */ | ||
90 | |||
91 | /*-------------------------------------------------------------------------*/ | ||
92 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | ||
29 | 93 | ||
30 | #define OMAP1_I2C_BASE 0xfffb3800 | 94 | #define OMAP1_I2C_BASE 0xfffb3800 |
31 | #define OMAP2_I2C_BASE1 0x48070000 | 95 | #define OMAP2_I2C_BASE1 0x48070000 |
@@ -48,8 +112,8 @@ static struct resource i2c_resources1[] = { | |||
48 | /* DMA not used; works around erratum writing to non-empty i2c fifo */ | 112 | /* DMA not used; works around erratum writing to non-empty i2c fifo */ |
49 | 113 | ||
50 | static struct platform_device omap_i2c_device1 = { | 114 | static struct platform_device omap_i2c_device1 = { |
51 | .name = "i2c_omap", | 115 | .name = "i2c_omap", |
52 | .id = 1, | 116 | .id = 1, |
53 | .num_resources = ARRAY_SIZE(i2c_resources1), | 117 | .num_resources = ARRAY_SIZE(i2c_resources1), |
54 | .resource = i2c_resources1, | 118 | .resource = i2c_resources1, |
55 | }; | 119 | }; |
@@ -376,7 +440,7 @@ static inline void omap_init_wdt(void) {} | |||
376 | 440 | ||
377 | /*-------------------------------------------------------------------------*/ | 441 | /*-------------------------------------------------------------------------*/ |
378 | 442 | ||
379 | #if defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE) | 443 | #if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) |
380 | 444 | ||
381 | #ifdef CONFIG_ARCH_OMAP24XX | 445 | #ifdef CONFIG_ARCH_OMAP24XX |
382 | #define OMAP_RNG_BASE 0x480A0000 | 446 | #define OMAP_RNG_BASE 0x480A0000 |
@@ -436,6 +500,7 @@ static int __init omap_init_devices(void) | |||
436 | /* please keep these calls, and their implementations above, | 500 | /* please keep these calls, and their implementations above, |
437 | * in alphabetical order so they're easier to sort through. | 501 | * in alphabetical order so they're easier to sort through. |
438 | */ | 502 | */ |
503 | omap_init_dsp(); | ||
439 | omap_init_i2c(); | 504 | omap_init_i2c(); |
440 | omap_init_kp(); | 505 | omap_init_kp(); |
441 | omap_init_mmc(); | 506 | omap_init_mmc(); |
@@ -446,4 +511,3 @@ static int __init omap_init_devices(void) | |||
446 | return 0; | 511 | return 0; |
447 | } | 512 | } |
448 | arch_initcall(omap_init_devices); | 513 | arch_initcall(omap_init_devices); |
449 | |||
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index f3f84fbf8b87..2d86b106ff3e 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -925,10 +925,17 @@ static int omap2_dma_handle_ch(int ch) | |||
925 | { | 925 | { |
926 | u32 status = OMAP_DMA_CSR_REG(ch); | 926 | u32 status = OMAP_DMA_CSR_REG(ch); |
927 | 927 | ||
928 | if (!status) | 928 | if (!status) { |
929 | if (printk_ratelimit()) | ||
930 | printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); | ||
929 | return 0; | 931 | return 0; |
930 | if (unlikely(dma_chan[ch].dev_id == -1)) | 932 | } |
933 | if (unlikely(dma_chan[ch].dev_id == -1)) { | ||
934 | if (printk_ratelimit()) | ||
935 | printk(KERN_WARNING "IRQ %04x for non-allocated DMA" | ||
936 | "channel %d\n", status, ch); | ||
931 | return 0; | 937 | return 0; |
938 | } | ||
932 | if (unlikely(status & OMAP_DMA_DROP_IRQ)) | 939 | if (unlikely(status & OMAP_DMA_DROP_IRQ)) |
933 | printk(KERN_INFO | 940 | printk(KERN_INFO |
934 | "DMA synchronization event drop occurred with device " | 941 | "DMA synchronization event drop occurred with device " |
@@ -959,11 +966,15 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) | |||
959 | int i; | 966 | int i; |
960 | 967 | ||
961 | val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); | 968 | val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); |
962 | 969 | if (val == 0) { | |
963 | for (i = 1; i <= OMAP_LOGICAL_DMA_CH_COUNT; i++) { | 970 | if (printk_ratelimit()) |
964 | int active = val & (1 << (i - 1)); | 971 | printk(KERN_WARNING "Spurious DMA IRQ\n"); |
965 | if (active) | 972 | return IRQ_HANDLED; |
966 | omap2_dma_handle_ch(i - 1); | 973 | } |
974 | for (i = 0; i < OMAP_LOGICAL_DMA_CH_COUNT && val != 0; i++) { | ||
975 | if (val & 1) | ||
976 | omap2_dma_handle_ch(i); | ||
977 | val >>= 1; | ||
967 | } | 978 | } |
968 | 979 | ||
969 | return IRQ_HANDLED; | 980 | return IRQ_HANDLED; |
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 659619f235ca..36073dfaa4db 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -372,7 +372,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | |||
372 | 372 | ||
373 | /* When the functional clock disappears, too quick writes seem to | 373 | /* When the functional clock disappears, too quick writes seem to |
374 | * cause an abort. */ | 374 | * cause an abort. */ |
375 | __delay(15000); | 375 | __delay(150000); |
376 | } | 376 | } |
377 | 377 | ||
378 | #endif | 378 | #endif |
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index 56acb8720f78..4493bcff5172 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c | |||
@@ -1,3 +1,26 @@ | |||
1 | /* | ||
2 | * File: arch/arm/plat-omap/fb.c | ||
3 | * | ||
4 | * Framebuffer device registration for TI OMAP platforms | ||
5 | * | ||
6 | * Copyright (C) 2006 Nokia Corporation | ||
7 | * Author: Imre Deak <imre.deak@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
1 | #include <linux/module.h> | 24 | #include <linux/module.h> |
2 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
3 | #include <linux/init.h> | 26 | #include <linux/init.h> |
@@ -16,6 +39,8 @@ | |||
16 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) | 39 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) |
17 | 40 | ||
18 | static struct omapfb_platform_data omapfb_config; | 41 | static struct omapfb_platform_data omapfb_config; |
42 | static int config_invalid; | ||
43 | static int configured_regions; | ||
19 | 44 | ||
20 | static u64 omap_fb_dma_mask = ~(u32)0; | 45 | static u64 omap_fb_dma_mask = ~(u32)0; |
21 | 46 | ||
@@ -30,39 +55,270 @@ static struct platform_device omap_fb_device = { | |||
30 | .num_resources = 0, | 55 | .num_resources = 0, |
31 | }; | 56 | }; |
32 | 57 | ||
33 | /* called from map_io */ | 58 | static inline int ranges_overlap(unsigned long start1, unsigned long size1, |
34 | void omapfb_reserve_mem(void) | 59 | unsigned long start2, unsigned long size2) |
35 | { | 60 | { |
36 | const struct omap_fbmem_config *fbmem_conf; | 61 | return (start1 >= start2 && start1 < start2 + size2) || |
62 | (start2 >= start1 && start2 < start1 + size1); | ||
63 | } | ||
37 | 64 | ||
38 | omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start; | 65 | static inline int range_included(unsigned long start1, unsigned long size1, |
39 | omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size; | 66 | unsigned long start2, unsigned long size2) |
67 | { | ||
68 | return start1 >= start2 && start1 + size1 <= start2 + size2; | ||
69 | } | ||
40 | 70 | ||
41 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
42 | 71 | ||
43 | if (fbmem_conf != NULL) { | 72 | /* Check if there is an overlapping region. */ |
44 | /* indicate that the bootloader already initialized the | 73 | static int fbmem_region_reserved(unsigned long start, size_t size) |
45 | * fb device, so we'll skip that part in the fb driver | 74 | { |
46 | */ | 75 | struct omapfb_mem_region *rg; |
47 | omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start; | 76 | int i; |
48 | omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size; | 77 | |
49 | if (fbmem_conf->fb_sdram_size) { | 78 | rg = &omapfb_config.mem_desc.region[0]; |
50 | pr_info("Reserving %u bytes SDRAM for frame buffer\n", | 79 | for (i = 0; i < OMAPFB_PLANE_NUM; i++, rg++) { |
51 | fbmem_conf->fb_sdram_size); | 80 | if (!rg->paddr) |
52 | reserve_bootmem(fbmem_conf->fb_sdram_start, | 81 | /* Empty slot. */ |
53 | fbmem_conf->fb_sdram_size); | 82 | continue; |
83 | if (ranges_overlap(start, size, rg->paddr, rg->size)) | ||
84 | return 1; | ||
85 | } | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Get the region_idx`th region from board config/ATAG and convert it to | ||
91 | * our internal format. | ||
92 | */ | ||
93 | static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg) | ||
94 | { | ||
95 | const struct omap_fbmem_config *conf; | ||
96 | u32 paddr; | ||
97 | |||
98 | conf = omap_get_nr_config(OMAP_TAG_FBMEM, | ||
99 | struct omap_fbmem_config, region_idx); | ||
100 | if (conf == NULL) | ||
101 | return -ENOENT; | ||
102 | |||
103 | paddr = conf->start; | ||
104 | /* | ||
105 | * Low bits encode the page allocation mode, if high bits | ||
106 | * are zero. Otherwise we need a page aligned fixed | ||
107 | * address. | ||
108 | */ | ||
109 | memset(rg, 0, sizeof(*rg)); | ||
110 | rg->type = paddr & ~PAGE_MASK; | ||
111 | rg->paddr = paddr & PAGE_MASK; | ||
112 | rg->size = PAGE_ALIGN(conf->size); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type, | ||
117 | unsigned long mem_start, | ||
118 | unsigned long mem_size) | ||
119 | { | ||
120 | /* | ||
121 | * Check if the configuration specifies the type explicitly. | ||
122 | * type = 0 && paddr = 0, a default don't care case maps to | ||
123 | * the SDRAM type. | ||
124 | */ | ||
125 | if (rg->type || (!rg->type && !rg->paddr)) | ||
126 | return 0; | ||
127 | if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) { | ||
128 | rg->type = mem_type; | ||
129 | return 0; | ||
130 | } | ||
131 | /* Can't determine it. */ | ||
132 | return -1; | ||
133 | } | ||
134 | |||
135 | static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg, | ||
136 | unsigned long start_avail, unsigned size_avail) | ||
137 | { | ||
138 | unsigned long paddr = rg->paddr; | ||
139 | size_t size = rg->size; | ||
140 | |||
141 | if (rg->type > OMAPFB_MEMTYPE_MAX) { | ||
142 | printk(KERN_ERR | ||
143 | "Invalid start address for FB region %d\n", region_idx); | ||
144 | return -EINVAL; | ||
145 | } | ||
146 | |||
147 | if (!rg->size) { | ||
148 | printk(KERN_ERR "Zero size for FB region %d\n", region_idx); | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | |||
152 | if (!paddr) | ||
153 | /* Allocate this dynamically, leave paddr 0 for now. */ | ||
154 | return 0; | ||
155 | |||
156 | /* | ||
157 | * Fixed region for the given RAM range. Check if it's already | ||
158 | * reserved by the FB code or someone else. | ||
159 | */ | ||
160 | if (fbmem_region_reserved(paddr, size) || | ||
161 | !range_included(paddr, size, start_avail, size_avail)) { | ||
162 | printk(KERN_ERR "Trying to use reserved memory " | ||
163 | "for FB region %d\n", region_idx); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Called from map_io. We need to call to this early enough so that we | ||
172 | * can reserve the fixed SDRAM regions before VM could get hold of them. | ||
173 | */ | ||
174 | void omapfb_reserve_sdram(void) | ||
175 | { | ||
176 | struct bootmem_data *bdata; | ||
177 | unsigned long sdram_start, sdram_size; | ||
178 | unsigned long reserved; | ||
179 | int i; | ||
180 | |||
181 | if (config_invalid) | ||
182 | return; | ||
183 | |||
184 | bdata = NODE_DATA(0)->bdata; | ||
185 | sdram_start = bdata->node_boot_start; | ||
186 | sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; | ||
187 | reserved = 0; | ||
188 | for (i = 0; ; i++) { | ||
189 | struct omapfb_mem_region rg; | ||
190 | |||
191 | if (get_fbmem_region(i, &rg) < 0) | ||
192 | break; | ||
193 | if (i == OMAPFB_PLANE_NUM) { | ||
194 | printk(KERN_ERR | ||
195 | "Extraneous FB mem configuration entries\n"); | ||
196 | config_invalid = 1; | ||
197 | return; | ||
54 | } | 198 | } |
199 | /* Check if it's our memory type. */ | ||
200 | if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SDRAM, | ||
201 | sdram_start, sdram_size) < 0 || | ||
202 | (rg.type != OMAPFB_MEMTYPE_SDRAM)) | ||
203 | continue; | ||
204 | BUG_ON(omapfb_config.mem_desc.region[i].size); | ||
205 | if (check_fbmem_region(i, &rg, sdram_start, sdram_size) < 0) { | ||
206 | config_invalid = 1; | ||
207 | return; | ||
208 | } | ||
209 | if (rg.paddr) | ||
210 | reserve_bootmem(rg.paddr, rg.size); | ||
211 | reserved += rg.size; | ||
212 | omapfb_config.mem_desc.region[i] = rg; | ||
213 | configured_regions++; | ||
55 | } | 214 | } |
215 | omapfb_config.mem_desc.region_cnt = i; | ||
216 | if (reserved) | ||
217 | pr_info("Reserving %lu bytes SDRAM for frame buffer\n", | ||
218 | reserved); | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Called at sram init time, before anything is pushed to the SRAM stack. | ||
223 | * Because of the stack scheme, we will allocate everything from the | ||
224 | * start of the lowest address region to the end of SRAM. This will also | ||
225 | * include padding for page alignment and possible holes between regions. | ||
226 | * | ||
227 | * As opposed to the SDRAM case, we'll also do any dynamic allocations at | ||
228 | * this point, since the driver built as a module would have problem with | ||
229 | * freeing / reallocating the regions. | ||
230 | */ | ||
231 | unsigned long omapfb_reserve_sram(unsigned long sram_pstart, | ||
232 | unsigned long sram_vstart, | ||
233 | unsigned long sram_size, | ||
234 | unsigned long pstart_avail, | ||
235 | unsigned long size_avail) | ||
236 | { | ||
237 | struct omapfb_mem_region rg; | ||
238 | unsigned long pend_avail; | ||
239 | unsigned long reserved; | ||
240 | int i; | ||
241 | |||
242 | if (config_invalid) | ||
243 | return 0; | ||
244 | |||
245 | reserved = 0; | ||
246 | pend_avail = pstart_avail + size_avail; | ||
247 | for (i = 0; ; i++) { | ||
248 | if (get_fbmem_region(i, &rg) < 0) | ||
249 | break; | ||
250 | if (i == OMAPFB_PLANE_NUM) { | ||
251 | printk(KERN_ERR | ||
252 | "Extraneous FB mem configuration entries\n"); | ||
253 | config_invalid = 1; | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | /* Check if it's our memory type. */ | ||
258 | if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SRAM, | ||
259 | sram_pstart, sram_size) < 0 || | ||
260 | (rg.type != OMAPFB_MEMTYPE_SRAM)) | ||
261 | continue; | ||
262 | BUG_ON(omapfb_config.mem_desc.region[i].size); | ||
263 | |||
264 | if (check_fbmem_region(i, &rg, pstart_avail, size_avail) < 0) { | ||
265 | config_invalid = 1; | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | if (!rg.paddr) { | ||
270 | /* Dynamic allocation */ | ||
271 | if ((size_avail & PAGE_MASK) < rg.size) { | ||
272 | printk("Not enough SRAM for FB region %d\n", | ||
273 | i); | ||
274 | config_invalid = 1; | ||
275 | return 0; | ||
276 | } | ||
277 | size_avail = (size_avail - rg.size) & PAGE_MASK; | ||
278 | rg.paddr = pstart_avail + size_avail; | ||
279 | } | ||
280 | /* Reserve everything above the start of the region. */ | ||
281 | if (pend_avail - rg.paddr > reserved) | ||
282 | reserved = pend_avail - rg.paddr; | ||
283 | size_avail = pend_avail - reserved - pstart_avail; | ||
284 | |||
285 | /* | ||
286 | * We have a kernel mapping for this already, so the | ||
287 | * driver won't have to make one. | ||
288 | */ | ||
289 | rg.vaddr = (void *)(sram_vstart + rg.paddr - sram_pstart); | ||
290 | omapfb_config.mem_desc.region[i] = rg; | ||
291 | configured_regions++; | ||
292 | } | ||
293 | omapfb_config.mem_desc.region_cnt = i; | ||
294 | if (reserved) | ||
295 | pr_info("Reserving %lu bytes SRAM for frame buffer\n", | ||
296 | reserved); | ||
297 | return reserved; | ||
298 | } | ||
299 | |||
300 | void omapfb_set_ctrl_platform_data(void *data) | ||
301 | { | ||
302 | omapfb_config.ctrl_platform_data = data; | ||
56 | } | 303 | } |
57 | 304 | ||
58 | static inline int omap_init_fb(void) | 305 | static inline int omap_init_fb(void) |
59 | { | 306 | { |
60 | const struct omap_lcd_config *conf; | 307 | const struct omap_lcd_config *conf; |
61 | 308 | ||
309 | if (config_invalid) | ||
310 | return 0; | ||
311 | if (configured_regions != omapfb_config.mem_desc.region_cnt) { | ||
312 | printk(KERN_ERR "Invalid FB mem configuration entries\n"); | ||
313 | return 0; | ||
314 | } | ||
62 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); | 315 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); |
63 | if (conf == NULL) | 316 | if (conf == NULL) { |
317 | if (configured_regions) | ||
318 | /* FB mem config, but no LCD config? */ | ||
319 | printk(KERN_ERR "Missing LCD configuration\n"); | ||
64 | return 0; | 320 | return 0; |
65 | 321 | } | |
66 | omapfb_config.lcd = *conf; | 322 | omapfb_config.lcd = *conf; |
67 | 323 | ||
68 | return platform_device_register(&omap_fb_device); | 324 | return platform_device_register(&omap_fb_device); |
@@ -72,7 +328,16 @@ arch_initcall(omap_init_fb); | |||
72 | 328 | ||
73 | #else | 329 | #else |
74 | 330 | ||
75 | void omapfb_reserve_mem(void) {} | 331 | void omapfb_reserve_sdram(void) {} |
332 | unsigned long omapfb_reserve_sram(unsigned long sram_pstart, | ||
333 | unsigned long sram_vstart, | ||
334 | unsigned long sram_size, | ||
335 | unsigned long start_avail, | ||
336 | unsigned long size_avail) | ||
337 | { | ||
338 | return 0; | ||
339 | } | ||
340 | |||
76 | 341 | ||
77 | #endif | 342 | #endif |
78 | 343 | ||
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 9dc6d3617bdb..337455dfe64d 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/sched.h> | ||
17 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
18 | #include <linux/sysdev.h> | 17 | #include <linux/sysdev.h> |
19 | #include <linux/err.h> | 18 | #include <linux/err.h> |
@@ -1545,7 +1544,7 @@ void omap2_gpio_resume_after_retention(void) | |||
1545 | * This may get called early from board specific init | 1544 | * This may get called early from board specific init |
1546 | * for boards that have interrupts routed via FPGA. | 1545 | * for boards that have interrupts routed via FPGA. |
1547 | */ | 1546 | */ |
1548 | int omap_gpio_init(void) | 1547 | int __init omap_gpio_init(void) |
1549 | { | 1548 | { |
1550 | if (!initialized) | 1549 | if (!initialized) |
1551 | return _omap_gpio_init(); | 1550 | return _omap_gpio_init(); |
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c new file mode 100644 index 000000000000..de7e6ef48bd0 --- /dev/null +++ b/arch/arm/plat-omap/mailbox.c | |||
@@ -0,0 +1,509 @@ | |||
1 | /* | ||
2 | * OMAP mailbox driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Nokia Corporation. All rights reserved. | ||
5 | * | ||
6 | * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com> | ||
7 | * Restructured by Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/init.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/blkdev.h> | ||
31 | #include <linux/err.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/arch/mailbox.h> | ||
35 | #include "mailbox.h" | ||
36 | |||
37 | static struct omap_mbox *mboxes; | ||
38 | static DEFINE_RWLOCK(mboxes_lock); | ||
39 | |||
40 | /* Mailbox Sequence Bit function */ | ||
41 | void omap_mbox_init_seq(struct omap_mbox *mbox) | ||
42 | { | ||
43 | mbox_seq_init(mbox); | ||
44 | } | ||
45 | EXPORT_SYMBOL(omap_mbox_init_seq); | ||
46 | |||
47 | /* | ||
48 | * message sender | ||
49 | */ | ||
50 | static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) | ||
51 | { | ||
52 | int ret = 0, i = 1000; | ||
53 | |||
54 | while (mbox_fifo_full(mbox)) { | ||
55 | if (mbox->ops->type == OMAP_MBOX_TYPE2) | ||
56 | return -1; | ||
57 | if (--i == 0) | ||
58 | return -1; | ||
59 | udelay(1); | ||
60 | } | ||
61 | |||
62 | if (arg && mbox->txq->callback) { | ||
63 | ret = mbox->txq->callback(arg); | ||
64 | if (ret) | ||
65 | goto out; | ||
66 | } | ||
67 | |||
68 | mbox_seq_toggle(mbox, &msg); | ||
69 | mbox_fifo_write(mbox, msg); | ||
70 | out: | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) | ||
75 | { | ||
76 | struct request *rq; | ||
77 | struct request_queue *q = mbox->txq->queue; | ||
78 | int ret = 0; | ||
79 | |||
80 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | ||
81 | if (unlikely(!rq)) { | ||
82 | ret = -ENOMEM; | ||
83 | goto fail; | ||
84 | } | ||
85 | |||
86 | rq->data = (void *)msg; | ||
87 | blk_insert_request(q, rq, 0, arg); | ||
88 | |||
89 | schedule_work(&mbox->txq->work); | ||
90 | fail: | ||
91 | return ret; | ||
92 | } | ||
93 | EXPORT_SYMBOL(omap_mbox_msg_send); | ||
94 | |||
95 | static void mbox_tx_work(struct work_struct *work) | ||
96 | { | ||
97 | int ret; | ||
98 | struct request *rq; | ||
99 | struct omap_mbox_queue *mq = container_of(work, | ||
100 | struct omap_mbox_queue, work); | ||
101 | struct omap_mbox *mbox = mq->queue->queuedata; | ||
102 | struct request_queue *q = mbox->txq->queue; | ||
103 | |||
104 | while (1) { | ||
105 | spin_lock(q->queue_lock); | ||
106 | rq = elv_next_request(q); | ||
107 | spin_unlock(q->queue_lock); | ||
108 | |||
109 | if (!rq) | ||
110 | break; | ||
111 | |||
112 | ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special); | ||
113 | if (ret) { | ||
114 | enable_mbox_irq(mbox, IRQ_TX); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | spin_lock(q->queue_lock); | ||
119 | blkdev_dequeue_request(rq); | ||
120 | end_that_request_last(rq, 0); | ||
121 | spin_unlock(q->queue_lock); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Message receiver(workqueue) | ||
127 | */ | ||
128 | static void mbox_rx_work(struct work_struct *work) | ||
129 | { | ||
130 | struct omap_mbox_queue *mq = | ||
131 | container_of(work, struct omap_mbox_queue, work); | ||
132 | struct omap_mbox *mbox = mq->queue->queuedata; | ||
133 | struct request_queue *q = mbox->rxq->queue; | ||
134 | struct request *rq; | ||
135 | mbox_msg_t msg; | ||
136 | unsigned long flags; | ||
137 | |||
138 | if (mbox->rxq->callback == NULL) { | ||
139 | sysfs_notify(&mbox->dev.kobj, NULL, "mbox"); | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | while (1) { | ||
144 | spin_lock_irqsave(q->queue_lock, flags); | ||
145 | rq = elv_next_request(q); | ||
146 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
147 | if (!rq) | ||
148 | break; | ||
149 | |||
150 | msg = (mbox_msg_t) rq->data; | ||
151 | |||
152 | spin_lock_irqsave(q->queue_lock, flags); | ||
153 | blkdev_dequeue_request(rq); | ||
154 | end_that_request_last(rq, 0); | ||
155 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
156 | |||
157 | mbox->rxq->callback((void *)msg); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Mailbox interrupt handler | ||
163 | */ | ||
164 | static void mbox_txq_fn(request_queue_t * q) | ||
165 | { | ||
166 | } | ||
167 | |||
168 | static void mbox_rxq_fn(request_queue_t * q) | ||
169 | { | ||
170 | } | ||
171 | |||
172 | static void __mbox_tx_interrupt(struct omap_mbox *mbox) | ||
173 | { | ||
174 | disable_mbox_irq(mbox, IRQ_TX); | ||
175 | ack_mbox_irq(mbox, IRQ_TX); | ||
176 | schedule_work(&mbox->txq->work); | ||
177 | } | ||
178 | |||
179 | static void __mbox_rx_interrupt(struct omap_mbox *mbox) | ||
180 | { | ||
181 | struct request *rq; | ||
182 | mbox_msg_t msg; | ||
183 | request_queue_t *q = mbox->rxq->queue; | ||
184 | |||
185 | disable_mbox_irq(mbox, IRQ_RX); | ||
186 | |||
187 | while (!mbox_fifo_empty(mbox)) { | ||
188 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | ||
189 | if (unlikely(!rq)) | ||
190 | goto nomem; | ||
191 | |||
192 | msg = mbox_fifo_read(mbox); | ||
193 | rq->data = (void *)msg; | ||
194 | |||
195 | if (unlikely(mbox_seq_test(mbox, msg))) { | ||
196 | pr_info("mbox: Illegal seq bit!(%08x)\n", msg); | ||
197 | if (mbox->err_notify) | ||
198 | mbox->err_notify(); | ||
199 | } | ||
200 | |||
201 | blk_insert_request(q, rq, 0, NULL); | ||
202 | if (mbox->ops->type == OMAP_MBOX_TYPE1) | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | /* no more messages in the fifo. clear IRQ source. */ | ||
207 | ack_mbox_irq(mbox, IRQ_RX); | ||
208 | enable_mbox_irq(mbox, IRQ_RX); | ||
209 | nomem: | ||
210 | schedule_work(&mbox->rxq->work); | ||
211 | } | ||
212 | |||
213 | static irqreturn_t mbox_interrupt(int irq, void *p) | ||
214 | { | ||
215 | struct omap_mbox *mbox = (struct omap_mbox *)p; | ||
216 | |||
217 | if (is_mbox_irq(mbox, IRQ_TX)) | ||
218 | __mbox_tx_interrupt(mbox); | ||
219 | |||
220 | if (is_mbox_irq(mbox, IRQ_RX)) | ||
221 | __mbox_rx_interrupt(mbox); | ||
222 | |||
223 | return IRQ_HANDLED; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * sysfs files | ||
228 | */ | ||
229 | static ssize_t | ||
230 | omap_mbox_write(struct device *dev, struct device_attribute *attr, | ||
231 | const char * buf, size_t count) | ||
232 | { | ||
233 | int ret; | ||
234 | mbox_msg_t *p = (mbox_msg_t *)buf; | ||
235 | struct omap_mbox *mbox = dev_get_drvdata(dev); | ||
236 | |||
237 | for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) { | ||
238 | ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL); | ||
239 | if (ret) | ||
240 | return -EAGAIN; | ||
241 | p++; | ||
242 | } | ||
243 | |||
244 | return (size_t)((char *)p - buf); | ||
245 | } | ||
246 | |||
247 | static ssize_t | ||
248 | omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) | ||
249 | { | ||
250 | unsigned long flags; | ||
251 | struct request *rq; | ||
252 | mbox_msg_t *p = (mbox_msg_t *) buf; | ||
253 | struct omap_mbox *mbox = dev_get_drvdata(dev); | ||
254 | struct request_queue *q = mbox->rxq->queue; | ||
255 | |||
256 | while (1) { | ||
257 | spin_lock_irqsave(q->queue_lock, flags); | ||
258 | rq = elv_next_request(q); | ||
259 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
260 | |||
261 | if (!rq) | ||
262 | break; | ||
263 | |||
264 | *p = (mbox_msg_t) rq->data; | ||
265 | |||
266 | spin_lock_irqsave(q->queue_lock, flags); | ||
267 | blkdev_dequeue_request(rq); | ||
268 | end_that_request_last(rq, 0); | ||
269 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
270 | |||
271 | if (unlikely(mbox_seq_test(mbox, *p))) { | ||
272 | pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); | ||
273 | continue; | ||
274 | } | ||
275 | p++; | ||
276 | } | ||
277 | |||
278 | pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); | ||
279 | |||
280 | return (size_t) ((char *)p - buf); | ||
281 | } | ||
282 | |||
283 | static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write); | ||
284 | |||
285 | static ssize_t mbox_show(struct class *class, char *buf) | ||
286 | { | ||
287 | return sprintf(buf, "mbox"); | ||
288 | } | ||
289 | |||
290 | static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); | ||
291 | |||
292 | static struct class omap_mbox_class = { | ||
293 | .name = "omap_mbox", | ||
294 | }; | ||
295 | |||
296 | static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, | ||
297 | request_fn_proc * proc, | ||
298 | void (*work) (struct work_struct *)) | ||
299 | { | ||
300 | request_queue_t *q; | ||
301 | struct omap_mbox_queue *mq; | ||
302 | |||
303 | mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); | ||
304 | if (!mq) | ||
305 | return NULL; | ||
306 | |||
307 | spin_lock_init(&mq->lock); | ||
308 | |||
309 | q = blk_init_queue(proc, &mq->lock); | ||
310 | if (!q) | ||
311 | goto error; | ||
312 | q->queuedata = mbox; | ||
313 | mq->queue = q; | ||
314 | |||
315 | INIT_WORK(&mq->work, work); | ||
316 | |||
317 | return mq; | ||
318 | error: | ||
319 | kfree(mq); | ||
320 | return NULL; | ||
321 | } | ||
322 | |||
323 | static void mbox_queue_free(struct omap_mbox_queue *q) | ||
324 | { | ||
325 | blk_cleanup_queue(q->queue); | ||
326 | kfree(q); | ||
327 | } | ||
328 | |||
329 | static int omap_mbox_init(struct omap_mbox *mbox) | ||
330 | { | ||
331 | int ret; | ||
332 | struct omap_mbox_queue *mq; | ||
333 | |||
334 | if (likely(mbox->ops->startup)) { | ||
335 | ret = mbox->ops->startup(mbox); | ||
336 | if (unlikely(ret)) | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | mbox->dev.class = &omap_mbox_class; | ||
341 | strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN); | ||
342 | dev_set_drvdata(&mbox->dev, mbox); | ||
343 | |||
344 | ret = device_register(&mbox->dev); | ||
345 | if (unlikely(ret)) | ||
346 | goto fail_device_reg; | ||
347 | |||
348 | ret = device_create_file(&mbox->dev, &dev_attr_mbox); | ||
349 | if (unlikely(ret)) { | ||
350 | printk(KERN_ERR | ||
351 | "device_create_file failed: %d\n", ret); | ||
352 | goto fail_create_mbox; | ||
353 | } | ||
354 | |||
355 | ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, | ||
356 | mbox->name, mbox); | ||
357 | if (unlikely(ret)) { | ||
358 | printk(KERN_ERR | ||
359 | "failed to register mailbox interrupt:%d\n", ret); | ||
360 | goto fail_request_irq; | ||
361 | } | ||
362 | enable_mbox_irq(mbox, IRQ_RX); | ||
363 | |||
364 | mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work); | ||
365 | if (!mq) { | ||
366 | ret = -ENOMEM; | ||
367 | goto fail_alloc_txq; | ||
368 | } | ||
369 | mbox->txq = mq; | ||
370 | |||
371 | mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work); | ||
372 | if (!mq) { | ||
373 | ret = -ENOMEM; | ||
374 | goto fail_alloc_rxq; | ||
375 | } | ||
376 | mbox->rxq = mq; | ||
377 | |||
378 | return 0; | ||
379 | |||
380 | fail_alloc_rxq: | ||
381 | mbox_queue_free(mbox->txq); | ||
382 | fail_alloc_txq: | ||
383 | free_irq(mbox->irq, mbox); | ||
384 | fail_request_irq: | ||
385 | device_remove_file(&mbox->dev, &dev_attr_mbox); | ||
386 | fail_create_mbox: | ||
387 | device_unregister(&mbox->dev); | ||
388 | fail_device_reg: | ||
389 | if (unlikely(mbox->ops->shutdown)) | ||
390 | mbox->ops->shutdown(mbox); | ||
391 | |||
392 | return ret; | ||
393 | } | ||
394 | |||
395 | static void omap_mbox_fini(struct omap_mbox *mbox) | ||
396 | { | ||
397 | mbox_queue_free(mbox->txq); | ||
398 | mbox_queue_free(mbox->rxq); | ||
399 | |||
400 | free_irq(mbox->irq, mbox); | ||
401 | device_remove_file(&mbox->dev, &dev_attr_mbox); | ||
402 | class_unregister(&omap_mbox_class); | ||
403 | |||
404 | if (unlikely(mbox->ops->shutdown)) | ||
405 | mbox->ops->shutdown(mbox); | ||
406 | } | ||
407 | |||
408 | static struct omap_mbox **find_mboxes(const char *name) | ||
409 | { | ||
410 | struct omap_mbox **p; | ||
411 | |||
412 | for (p = &mboxes; *p; p = &(*p)->next) { | ||
413 | if (strcmp((*p)->name, name) == 0) | ||
414 | break; | ||
415 | } | ||
416 | |||
417 | return p; | ||
418 | } | ||
419 | |||
420 | struct omap_mbox *omap_mbox_get(const char *name) | ||
421 | { | ||
422 | struct omap_mbox *mbox; | ||
423 | int ret; | ||
424 | |||
425 | read_lock(&mboxes_lock); | ||
426 | mbox = *(find_mboxes(name)); | ||
427 | if (mbox == NULL) { | ||
428 | read_unlock(&mboxes_lock); | ||
429 | return ERR_PTR(-ENOENT); | ||
430 | } | ||
431 | |||
432 | read_unlock(&mboxes_lock); | ||
433 | |||
434 | ret = omap_mbox_init(mbox); | ||
435 | if (ret) | ||
436 | return ERR_PTR(-ENODEV); | ||
437 | |||
438 | return mbox; | ||
439 | } | ||
440 | EXPORT_SYMBOL(omap_mbox_get); | ||
441 | |||
442 | void omap_mbox_put(struct omap_mbox *mbox) | ||
443 | { | ||
444 | omap_mbox_fini(mbox); | ||
445 | } | ||
446 | EXPORT_SYMBOL(omap_mbox_put); | ||
447 | |||
448 | int omap_mbox_register(struct omap_mbox *mbox) | ||
449 | { | ||
450 | int ret = 0; | ||
451 | struct omap_mbox **tmp; | ||
452 | |||
453 | if (!mbox) | ||
454 | return -EINVAL; | ||
455 | if (mbox->next) | ||
456 | return -EBUSY; | ||
457 | |||
458 | write_lock(&mboxes_lock); | ||
459 | tmp = find_mboxes(mbox->name); | ||
460 | if (*tmp) | ||
461 | ret = -EBUSY; | ||
462 | else | ||
463 | *tmp = mbox; | ||
464 | write_unlock(&mboxes_lock); | ||
465 | |||
466 | return ret; | ||
467 | } | ||
468 | EXPORT_SYMBOL(omap_mbox_register); | ||
469 | |||
470 | int omap_mbox_unregister(struct omap_mbox *mbox) | ||
471 | { | ||
472 | struct omap_mbox **tmp; | ||
473 | |||
474 | write_lock(&mboxes_lock); | ||
475 | tmp = &mboxes; | ||
476 | while (*tmp) { | ||
477 | if (mbox == *tmp) { | ||
478 | *tmp = mbox->next; | ||
479 | mbox->next = NULL; | ||
480 | write_unlock(&mboxes_lock); | ||
481 | return 0; | ||
482 | } | ||
483 | tmp = &(*tmp)->next; | ||
484 | } | ||
485 | write_unlock(&mboxes_lock); | ||
486 | |||
487 | return -EINVAL; | ||
488 | } | ||
489 | EXPORT_SYMBOL(omap_mbox_unregister); | ||
490 | |||
491 | static int __init omap_mbox_class_init(void) | ||
492 | { | ||
493 | int ret = class_register(&omap_mbox_class); | ||
494 | if (!ret) | ||
495 | ret = class_create_file(&omap_mbox_class, &class_attr_mbox); | ||
496 | |||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | static void __exit omap_mbox_class_exit(void) | ||
501 | { | ||
502 | class_remove_file(&omap_mbox_class, &class_attr_mbox); | ||
503 | class_unregister(&omap_mbox_class); | ||
504 | } | ||
505 | |||
506 | subsys_initcall(omap_mbox_class_init); | ||
507 | module_exit(omap_mbox_class_exit); | ||
508 | |||
509 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/arm/plat-omap/mailbox.h b/arch/arm/plat-omap/mailbox.h new file mode 100644 index 000000000000..67c6740b8ad5 --- /dev/null +++ b/arch/arm/plat-omap/mailbox.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * Mailbox internal functions | ||
3 | * | ||
4 | * Copyright (C) 2006 Nokia Corporation | ||
5 | * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | |||
12 | #ifndef __ARCH_ARM_PLAT_MAILBOX_H | ||
13 | #define __ARCH_ARM_PLAT_MAILBOX_H | ||
14 | |||
15 | /* | ||
16 | * Mailbox sequence bit API | ||
17 | */ | ||
18 | #if defined(CONFIG_ARCH_OMAP1) | ||
19 | # define MBOX_USE_SEQ_BIT | ||
20 | #elif defined(CONFIG_ARCH_OMAP2) | ||
21 | # define MBOX_USE_SEQ_BIT | ||
22 | #endif | ||
23 | |||
24 | #ifdef MBOX_USE_SEQ_BIT | ||
25 | /* seq_rcv should be initialized with any value other than | ||
26 | * 0 and 1 << 31, to allow either value for the first | ||
27 | * message. */ | ||
28 | static inline void mbox_seq_init(struct omap_mbox *mbox) | ||
29 | { | ||
30 | /* any value other than 0 and 1 << 31 */ | ||
31 | mbox->seq_rcv = 0xffffffff; | ||
32 | } | ||
33 | |||
34 | static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) | ||
35 | { | ||
36 | /* add seq_snd to msg */ | ||
37 | *msg = (*msg & 0x7fffffff) | mbox->seq_snd; | ||
38 | /* flip seq_snd */ | ||
39 | mbox->seq_snd ^= 1 << 31; | ||
40 | } | ||
41 | |||
42 | static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) | ||
43 | { | ||
44 | mbox_msg_t seq = msg & (1 << 31); | ||
45 | if (seq == mbox->seq_rcv) | ||
46 | return -1; | ||
47 | mbox->seq_rcv = seq; | ||
48 | return 0; | ||
49 | } | ||
50 | #else | ||
51 | static inline void mbox_seq_init(struct omap_mbox *mbox) | ||
52 | { | ||
53 | } | ||
54 | static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) | ||
55 | { | ||
56 | } | ||
57 | static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) | ||
58 | { | ||
59 | return 0; | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | /* Mailbox FIFO handle functions */ | ||
64 | static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) | ||
65 | { | ||
66 | return mbox->ops->fifo_read(mbox); | ||
67 | } | ||
68 | static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) | ||
69 | { | ||
70 | mbox->ops->fifo_write(mbox, msg); | ||
71 | } | ||
72 | static inline int mbox_fifo_empty(struct omap_mbox *mbox) | ||
73 | { | ||
74 | return mbox->ops->fifo_empty(mbox); | ||
75 | } | ||
76 | static inline int mbox_fifo_full(struct omap_mbox *mbox) | ||
77 | { | ||
78 | return mbox->ops->fifo_full(mbox); | ||
79 | } | ||
80 | |||
81 | /* Mailbox IRQ handle functions */ | ||
82 | static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
83 | { | ||
84 | mbox->ops->enable_irq(mbox, irq); | ||
85 | } | ||
86 | static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
87 | { | ||
88 | mbox->ops->disable_irq(mbox, irq); | ||
89 | } | ||
90 | static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
91 | { | ||
92 | if (mbox->ops->ack_irq) | ||
93 | mbox->ops->ack_irq(mbox, irq); | ||
94 | } | ||
95 | static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
96 | { | ||
97 | return mbox->ops->is_irq(mbox, irq); | ||
98 | } | ||
99 | |||
100 | #endif /* __ARCH_ARM_PLAT_MAILBOX_H */ | ||
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 19014b2ff4c6..bc46f33aede3 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c | |||
@@ -46,14 +46,19 @@ | |||
46 | 46 | ||
47 | #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) | 47 | #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) |
48 | 48 | ||
49 | static unsigned long omap_sram_start; | ||
49 | static unsigned long omap_sram_base; | 50 | static unsigned long omap_sram_base; |
50 | static unsigned long omap_sram_size; | 51 | static unsigned long omap_sram_size; |
51 | static unsigned long omap_sram_ceil; | 52 | static unsigned long omap_sram_ceil; |
52 | 53 | ||
53 | unsigned long omap_fb_sram_start; | 54 | extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart, |
54 | unsigned long omap_fb_sram_size; | 55 | unsigned long sram_vstart, |
56 | unsigned long sram_size, | ||
57 | unsigned long pstart_avail, | ||
58 | unsigned long size_avail); | ||
55 | 59 | ||
56 | /* Depending on the target RAMFS firewall setup, the public usable amount of | 60 | /* |
61 | * Depending on the target RAMFS firewall setup, the public usable amount of | ||
57 | * SRAM varies. The default accessable size for all device types is 2k. A GP | 62 | * SRAM varies. The default accessable size for all device types is 2k. A GP |
58 | * device allows ARM11 but not other initators for full size. This | 63 | * device allows ARM11 but not other initators for full size. This |
59 | * functionality seems ok until some nice security API happens. | 64 | * functionality seems ok until some nice security API happens. |
@@ -77,32 +82,6 @@ static int is_sram_locked(void) | |||
77 | return 1; /* assume locked with no PPA or security driver */ | 82 | return 1; /* assume locked with no PPA or security driver */ |
78 | } | 83 | } |
79 | 84 | ||
80 | void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, | ||
81 | unsigned long *start, unsigned long *size) | ||
82 | { | ||
83 | const struct omap_fbmem_config *fbmem_conf; | ||
84 | |||
85 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
86 | if (fbmem_conf != NULL) { | ||
87 | *start = fbmem_conf->fb_sram_start; | ||
88 | *size = fbmem_conf->fb_sram_size; | ||
89 | } else { | ||
90 | *size = 0; | ||
91 | *start = 0; | ||
92 | } | ||
93 | |||
94 | if (*size && ( | ||
95 | *start < start_avail || | ||
96 | *start + *size > start_avail + size_avail)) { | ||
97 | printk(KERN_ERR "invalid FB SRAM configuration\n"); | ||
98 | *start = start_avail; | ||
99 | *size = size_avail; | ||
100 | } | ||
101 | |||
102 | if (*size) | ||
103 | pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); | ||
104 | } | ||
105 | |||
106 | /* | 85 | /* |
107 | * The amount of SRAM depends on the core type. | 86 | * The amount of SRAM depends on the core type. |
108 | * Note that we cannot try to test for SRAM here because writes | 87 | * Note that we cannot try to test for SRAM here because writes |
@@ -111,16 +90,16 @@ void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, | |||
111 | */ | 90 | */ |
112 | void __init omap_detect_sram(void) | 91 | void __init omap_detect_sram(void) |
113 | { | 92 | { |
114 | unsigned long sram_start; | 93 | unsigned long reserved; |
115 | 94 | ||
116 | if (cpu_is_omap24xx()) { | 95 | if (cpu_is_omap24xx()) { |
117 | if (is_sram_locked()) { | 96 | if (is_sram_locked()) { |
118 | omap_sram_base = OMAP2_SRAM_PUB_VA; | 97 | omap_sram_base = OMAP2_SRAM_PUB_VA; |
119 | sram_start = OMAP2_SRAM_PUB_PA; | 98 | omap_sram_start = OMAP2_SRAM_PUB_PA; |
120 | omap_sram_size = 0x800; /* 2K */ | 99 | omap_sram_size = 0x800; /* 2K */ |
121 | } else { | 100 | } else { |
122 | omap_sram_base = OMAP2_SRAM_VA; | 101 | omap_sram_base = OMAP2_SRAM_VA; |
123 | sram_start = OMAP2_SRAM_PA; | 102 | omap_sram_start = OMAP2_SRAM_PA; |
124 | if (cpu_is_omap242x()) | 103 | if (cpu_is_omap242x()) |
125 | omap_sram_size = 0xa0000; /* 640K */ | 104 | omap_sram_size = 0xa0000; /* 640K */ |
126 | else if (cpu_is_omap243x()) | 105 | else if (cpu_is_omap243x()) |
@@ -128,7 +107,7 @@ void __init omap_detect_sram(void) | |||
128 | } | 107 | } |
129 | } else { | 108 | } else { |
130 | omap_sram_base = OMAP1_SRAM_VA; | 109 | omap_sram_base = OMAP1_SRAM_VA; |
131 | sram_start = OMAP1_SRAM_PA; | 110 | omap_sram_start = OMAP1_SRAM_PA; |
132 | 111 | ||
133 | if (cpu_is_omap730()) | 112 | if (cpu_is_omap730()) |
134 | omap_sram_size = 0x32000; /* 200K */ | 113 | omap_sram_size = 0x32000; /* 200K */ |
@@ -144,12 +123,11 @@ void __init omap_detect_sram(void) | |||
144 | omap_sram_size = 0x4000; | 123 | omap_sram_size = 0x4000; |
145 | } | 124 | } |
146 | } | 125 | } |
147 | get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, | 126 | reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base, |
148 | omap_sram_size - SRAM_BOOTLOADER_SZ, | 127 | omap_sram_size, |
149 | &omap_fb_sram_start, &omap_fb_sram_size); | 128 | omap_sram_start + SRAM_BOOTLOADER_SZ, |
150 | if (omap_fb_sram_size) | 129 | omap_sram_size - SRAM_BOOTLOADER_SZ); |
151 | omap_sram_size -= sram_start + omap_sram_size - | 130 | omap_sram_size -= reserved; |
152 | omap_fb_sram_start; | ||
153 | omap_sram_ceil = omap_sram_base + omap_sram_size; | 131 | omap_sram_ceil = omap_sram_base + omap_sram_size; |
154 | } | 132 | } |
155 | 133 | ||
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index 7e8096809be2..25489aafb113 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c | |||
@@ -37,9 +37,27 @@ | |||
37 | #include <asm/arch/usb.h> | 37 | #include <asm/arch/usb.h> |
38 | #include <asm/arch/board.h> | 38 | #include <asm/arch/board.h> |
39 | 39 | ||
40 | #ifdef CONFIG_ARCH_OMAP1 | ||
41 | |||
42 | #define INT_USB_IRQ_GEN IH2_BASE + 20 | ||
43 | #define INT_USB_IRQ_NISO IH2_BASE + 30 | ||
44 | #define INT_USB_IRQ_ISO IH2_BASE + 29 | ||
45 | #define INT_USB_IRQ_HGEN INT_USB_HHC_1 | ||
46 | #define INT_USB_IRQ_OTG IH2_BASE + 8 | ||
47 | |||
48 | #else | ||
49 | |||
50 | #define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN | ||
51 | #define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO | ||
52 | #define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO | ||
53 | #define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN | ||
54 | #define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG | ||
55 | |||
56 | #endif | ||
57 | |||
58 | |||
40 | /* These routines should handle the standard chip-specific modes | 59 | /* These routines should handle the standard chip-specific modes |
41 | * for usb0/1/2 ports, covering basic mux and transceiver setup. | 60 | * for usb0/1/2 ports, covering basic mux and transceiver setup. |
42 | * Call omap_usb_init() once, from INIT_MACHINE(). | ||
43 | * | 61 | * |
44 | * Some board-*.c files will need to set up additional mux options, | 62 | * Some board-*.c files will need to set up additional mux options, |
45 | * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. | 63 | * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. |
@@ -96,19 +114,26 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) | |||
96 | { | 114 | { |
97 | u32 syscon1 = 0; | 115 | u32 syscon1 = 0; |
98 | 116 | ||
117 | if (cpu_is_omap24xx()) | ||
118 | CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL); | ||
119 | |||
99 | if (nwires == 0) { | 120 | if (nwires == 0) { |
100 | if (!cpu_is_omap15xx()) { | 121 | if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { |
101 | /* pulldown D+/D- */ | 122 | /* pulldown D+/D- */ |
102 | USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); | 123 | USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); |
103 | } | 124 | } |
104 | return 0; | 125 | return 0; |
105 | } | 126 | } |
106 | 127 | ||
107 | if (is_device) | 128 | if (is_device) { |
108 | omap_cfg_reg(W4_USB_PUEN); | 129 | if (cpu_is_omap24xx()) |
130 | omap_cfg_reg(J20_24XX_USB0_PUEN); | ||
131 | else | ||
132 | omap_cfg_reg(W4_USB_PUEN); | ||
133 | } | ||
109 | 134 | ||
110 | /* internal transceiver */ | 135 | /* internal transceiver (unavailable on 17xx, 24xx) */ |
111 | if (nwires == 2) { | 136 | if (!cpu_class_is_omap2() && nwires == 2) { |
112 | // omap_cfg_reg(P9_USB_DP); | 137 | // omap_cfg_reg(P9_USB_DP); |
113 | // omap_cfg_reg(R8_USB_DM); | 138 | // omap_cfg_reg(R8_USB_DM); |
114 | 139 | ||
@@ -136,29 +161,50 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) | |||
136 | return 0; | 161 | return 0; |
137 | } | 162 | } |
138 | 163 | ||
139 | omap_cfg_reg(V6_USB0_TXD); | 164 | if (cpu_is_omap24xx()) { |
140 | omap_cfg_reg(W9_USB0_TXEN); | 165 | omap_cfg_reg(K18_24XX_USB0_DAT); |
141 | omap_cfg_reg(W5_USB0_SE0); | 166 | omap_cfg_reg(K19_24XX_USB0_TXEN); |
167 | omap_cfg_reg(J14_24XX_USB0_SE0); | ||
168 | if (nwires != 3) | ||
169 | omap_cfg_reg(J18_24XX_USB0_RCV); | ||
170 | } else { | ||
171 | omap_cfg_reg(V6_USB0_TXD); | ||
172 | omap_cfg_reg(W9_USB0_TXEN); | ||
173 | omap_cfg_reg(W5_USB0_SE0); | ||
174 | if (nwires != 3) | ||
175 | omap_cfg_reg(Y5_USB0_RCV); | ||
176 | } | ||
142 | 177 | ||
143 | /* NOTE: SPEED and SUSP aren't configured here */ | 178 | /* NOTE: SPEED and SUSP aren't configured here. OTG hosts |
179 | * may be able to use I2C requests to set those bits along | ||
180 | * with VBUS switching and overcurrent detction. | ||
181 | */ | ||
144 | 182 | ||
145 | if (nwires != 3) | 183 | if (cpu_class_is_omap1() && nwires != 6) |
146 | omap_cfg_reg(Y5_USB0_RCV); | ||
147 | if (nwires != 6) | ||
148 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; | 184 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; |
149 | 185 | ||
150 | switch (nwires) { | 186 | switch (nwires) { |
151 | case 3: | 187 | case 3: |
152 | syscon1 = 2; | 188 | syscon1 = 2; |
189 | if (cpu_is_omap24xx()) | ||
190 | CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); | ||
153 | break; | 191 | break; |
154 | case 4: | 192 | case 4: |
155 | syscon1 = 1; | 193 | syscon1 = 1; |
194 | if (cpu_is_omap24xx()) | ||
195 | CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); | ||
156 | break; | 196 | break; |
157 | case 6: | 197 | case 6: |
158 | syscon1 = 3; | 198 | syscon1 = 3; |
159 | omap_cfg_reg(AA9_USB0_VP); | 199 | if (cpu_is_omap24xx()) { |
160 | omap_cfg_reg(R9_USB0_VM); | 200 | omap_cfg_reg(J19_24XX_USB0_VP); |
161 | USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; | 201 | omap_cfg_reg(K20_24XX_USB0_VM); |
202 | CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR); | ||
203 | } else { | ||
204 | omap_cfg_reg(AA9_USB0_VP); | ||
205 | omap_cfg_reg(R9_USB0_VM); | ||
206 | USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; | ||
207 | } | ||
162 | break; | 208 | break; |
163 | default: | 209 | default: |
164 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", | 210 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", |
@@ -171,14 +217,22 @@ static u32 __init omap_usb1_init(unsigned nwires) | |||
171 | { | 217 | { |
172 | u32 syscon1 = 0; | 218 | u32 syscon1 = 0; |
173 | 219 | ||
174 | if (nwires != 6 && !cpu_is_omap15xx()) | 220 | if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) |
175 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; | 221 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; |
222 | if (cpu_is_omap24xx()) | ||
223 | CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL); | ||
224 | |||
176 | if (nwires == 0) | 225 | if (nwires == 0) |
177 | return 0; | 226 | return 0; |
178 | 227 | ||
179 | /* external transceiver */ | 228 | /* external transceiver */ |
180 | omap_cfg_reg(USB1_TXD); | 229 | if (cpu_class_is_omap1()) { |
181 | omap_cfg_reg(USB1_TXEN); | 230 | omap_cfg_reg(USB1_TXD); |
231 | omap_cfg_reg(USB1_TXEN); | ||
232 | if (nwires != 3) | ||
233 | omap_cfg_reg(USB1_RCV); | ||
234 | } | ||
235 | |||
182 | if (cpu_is_omap15xx()) { | 236 | if (cpu_is_omap15xx()) { |
183 | omap_cfg_reg(USB1_SEO); | 237 | omap_cfg_reg(USB1_SEO); |
184 | omap_cfg_reg(USB1_SPEED); | 238 | omap_cfg_reg(USB1_SPEED); |
@@ -190,20 +244,38 @@ static u32 __init omap_usb1_init(unsigned nwires) | |||
190 | } else if (cpu_is_omap1710()) { | 244 | } else if (cpu_is_omap1710()) { |
191 | omap_cfg_reg(R13_1710_USB1_SE0); | 245 | omap_cfg_reg(R13_1710_USB1_SE0); |
192 | // SUSP | 246 | // SUSP |
247 | } else if (cpu_is_omap24xx()) { | ||
248 | /* NOTE: board-specific code must set up pin muxing for usb1, | ||
249 | * since each signal could come out on either of two balls. | ||
250 | */ | ||
193 | } else { | 251 | } else { |
194 | pr_debug("usb unrecognized\n"); | 252 | pr_debug("usb%d cpu unrecognized\n", 1); |
253 | return 0; | ||
195 | } | 254 | } |
196 | if (nwires != 3) | ||
197 | omap_cfg_reg(USB1_RCV); | ||
198 | 255 | ||
199 | switch (nwires) { | 256 | switch (nwires) { |
257 | case 2: | ||
258 | if (!cpu_is_omap24xx()) | ||
259 | goto bad; | ||
260 | /* NOTE: board-specific code must override this setting if | ||
261 | * this TLL link is not using DP/DM | ||
262 | */ | ||
263 | syscon1 = 1; | ||
264 | CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL); | ||
265 | break; | ||
200 | case 3: | 266 | case 3: |
201 | syscon1 = 2; | 267 | syscon1 = 2; |
268 | if (cpu_is_omap24xx()) | ||
269 | CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); | ||
202 | break; | 270 | break; |
203 | case 4: | 271 | case 4: |
204 | syscon1 = 1; | 272 | syscon1 = 1; |
273 | if (cpu_is_omap24xx()) | ||
274 | CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); | ||
205 | break; | 275 | break; |
206 | case 6: | 276 | case 6: |
277 | if (cpu_is_omap24xx()) | ||
278 | goto bad; | ||
207 | syscon1 = 3; | 279 | syscon1 = 3; |
208 | omap_cfg_reg(USB1_VP); | 280 | omap_cfg_reg(USB1_VP); |
209 | omap_cfg_reg(USB1_VM); | 281 | omap_cfg_reg(USB1_VM); |
@@ -211,6 +283,7 @@ static u32 __init omap_usb1_init(unsigned nwires) | |||
211 | USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; | 283 | USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; |
212 | break; | 284 | break; |
213 | default: | 285 | default: |
286 | bad: | ||
214 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", | 287 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", |
215 | 1, nwires); | 288 | 1, nwires); |
216 | } | 289 | } |
@@ -221,10 +294,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) | |||
221 | { | 294 | { |
222 | u32 syscon1 = 0; | 295 | u32 syscon1 = 0; |
223 | 296 | ||
224 | /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */ | 297 | if (cpu_is_omap24xx()) { |
298 | CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL) | ||
299 | | USBT2TLL5PI); | ||
300 | alt_pingroup = 0; | ||
301 | } | ||
302 | |||
303 | /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ | ||
225 | if (alt_pingroup || nwires == 0) | 304 | if (alt_pingroup || nwires == 0) |
226 | return 0; | 305 | return 0; |
227 | if (nwires != 6 && !cpu_is_omap15xx()) | 306 | |
307 | if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) | ||
228 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; | 308 | USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; |
229 | 309 | ||
230 | /* external transceiver */ | 310 | /* external transceiver */ |
@@ -242,19 +322,54 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) | |||
242 | if (nwires != 3) | 322 | if (nwires != 3) |
243 | omap_cfg_reg(Y5_USB2_RCV); | 323 | omap_cfg_reg(Y5_USB2_RCV); |
244 | // FIXME omap_cfg_reg(USB2_SPEED); | 324 | // FIXME omap_cfg_reg(USB2_SPEED); |
325 | } else if (cpu_is_omap24xx()) { | ||
326 | omap_cfg_reg(Y11_24XX_USB2_DAT); | ||
327 | omap_cfg_reg(AA10_24XX_USB2_SE0); | ||
328 | if (nwires > 2) | ||
329 | omap_cfg_reg(AA12_24XX_USB2_TXEN); | ||
330 | if (nwires > 3) | ||
331 | omap_cfg_reg(AA6_24XX_USB2_RCV); | ||
245 | } else { | 332 | } else { |
246 | pr_debug("usb unrecognized\n"); | 333 | pr_debug("usb%d cpu unrecognized\n", 1); |
334 | return 0; | ||
247 | } | 335 | } |
248 | // omap_cfg_reg(USB2_SUSP); | 336 | // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP); |
249 | 337 | ||
250 | switch (nwires) { | 338 | switch (nwires) { |
339 | case 2: | ||
340 | if (!cpu_is_omap24xx()) | ||
341 | goto bad; | ||
342 | /* NOTE: board-specific code must override this setting if | ||
343 | * this TLL link is not using DP/DM | ||
344 | */ | ||
345 | syscon1 = 1; | ||
346 | CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL); | ||
347 | break; | ||
251 | case 3: | 348 | case 3: |
252 | syscon1 = 2; | 349 | syscon1 = 2; |
350 | if (cpu_is_omap24xx()) | ||
351 | CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); | ||
253 | break; | 352 | break; |
254 | case 4: | 353 | case 4: |
255 | syscon1 = 1; | 354 | syscon1 = 1; |
355 | if (cpu_is_omap24xx()) | ||
356 | CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); | ||
357 | break; | ||
358 | case 5: | ||
359 | if (!cpu_is_omap24xx()) | ||
360 | goto bad; | ||
361 | omap_cfg_reg(AA4_24XX_USB2_TLLSE0); | ||
362 | /* NOTE: board-specific code must override this setting if | ||
363 | * this TLL link is not using DP/DM. Something must also | ||
364 | * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} | ||
365 | */ | ||
366 | syscon1 = 3; | ||
367 | CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL) | ||
368 | | USBT2TLL5PI; | ||
256 | break; | 369 | break; |
257 | case 6: | 370 | case 6: |
371 | if (cpu_is_omap24xx()) | ||
372 | goto bad; | ||
258 | syscon1 = 3; | 373 | syscon1 = 3; |
259 | if (cpu_is_omap15xx()) { | 374 | if (cpu_is_omap15xx()) { |
260 | omap_cfg_reg(USB2_VP); | 375 | omap_cfg_reg(USB2_VP); |
@@ -266,6 +381,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) | |||
266 | } | 381 | } |
267 | break; | 382 | break; |
268 | default: | 383 | default: |
384 | bad: | ||
269 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", | 385 | printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", |
270 | 2, nwires); | 386 | 2, nwires); |
271 | } | 387 | } |
@@ -294,13 +410,13 @@ static struct resource udc_resources[] = { | |||
294 | .end = UDC_BASE + 0xff, | 410 | .end = UDC_BASE + 0xff, |
295 | .flags = IORESOURCE_MEM, | 411 | .flags = IORESOURCE_MEM, |
296 | }, { /* general IRQ */ | 412 | }, { /* general IRQ */ |
297 | .start = IH2_BASE + 20, | 413 | .start = INT_USB_IRQ_GEN, |
298 | .flags = IORESOURCE_IRQ, | 414 | .flags = IORESOURCE_IRQ, |
299 | }, { /* PIO IRQ */ | 415 | }, { /* PIO IRQ */ |
300 | .start = IH2_BASE + 30, | 416 | .start = INT_USB_IRQ_NISO, |
301 | .flags = IORESOURCE_IRQ, | 417 | .flags = IORESOURCE_IRQ, |
302 | }, { /* SOF IRQ */ | 418 | }, { /* SOF IRQ */ |
303 | .start = IH2_BASE + 29, | 419 | .start = INT_USB_IRQ_ISO, |
304 | .flags = IORESOURCE_IRQ, | 420 | .flags = IORESOURCE_IRQ, |
305 | }, | 421 | }, |
306 | }; | 422 | }; |
@@ -329,11 +445,11 @@ static u64 ohci_dmamask = ~(u32)0; | |||
329 | static struct resource ohci_resources[] = { | 445 | static struct resource ohci_resources[] = { |
330 | { | 446 | { |
331 | .start = OMAP_OHCI_BASE, | 447 | .start = OMAP_OHCI_BASE, |
332 | .end = OMAP_OHCI_BASE + 4096 - 1, | 448 | .end = OMAP_OHCI_BASE + 0xff, |
333 | .flags = IORESOURCE_MEM, | 449 | .flags = IORESOURCE_MEM, |
334 | }, | 450 | }, |
335 | { | 451 | { |
336 | .start = INT_USB_HHC_1, | 452 | .start = INT_USB_IRQ_HGEN, |
337 | .flags = IORESOURCE_IRQ, | 453 | .flags = IORESOURCE_IRQ, |
338 | }, | 454 | }, |
339 | }; | 455 | }; |
@@ -361,7 +477,7 @@ static struct resource otg_resources[] = { | |||
361 | .end = OTG_BASE + 0xff, | 477 | .end = OTG_BASE + 0xff, |
362 | .flags = IORESOURCE_MEM, | 478 | .flags = IORESOURCE_MEM, |
363 | }, { | 479 | }, { |
364 | .start = IH2_BASE + 8, | 480 | .start = INT_USB_IRQ_OTG, |
365 | .flags = IORESOURCE_IRQ, | 481 | .flags = IORESOURCE_IRQ, |
366 | }, | 482 | }, |
367 | }; | 483 | }; |
@@ -385,7 +501,7 @@ static struct platform_device otg_device = { | |||
385 | 501 | ||
386 | 502 | ||
387 | // FIXME correct answer depends on hmc_mode, | 503 | // FIXME correct answer depends on hmc_mode, |
388 | // as does any nonzero value for config->otg port number | 504 | // as does (on omap1) any nonzero value for config->otg port number |
389 | #ifdef CONFIG_USB_GADGET_OMAP | 505 | #ifdef CONFIG_USB_GADGET_OMAP |
390 | #define is_usb0_device(config) 1 | 506 | #define is_usb0_device(config) 1 |
391 | #else | 507 | #else |
@@ -426,12 +542,13 @@ omap_otg_init(struct omap_usb_config *config) | |||
426 | if (config->otg) | 542 | if (config->otg) |
427 | syscon |= OTG_EN; | 543 | syscon |= OTG_EN; |
428 | #endif | 544 | #endif |
429 | pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); | 545 | if (cpu_class_is_omap1()) |
546 | pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); | ||
430 | pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); | 547 | pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); |
431 | OTG_SYSCON_2_REG = syscon; | 548 | OTG_SYSCON_2_REG = syscon; |
432 | 549 | ||
433 | printk("USB: hmc %d", config->hmc_mode); | 550 | printk("USB: hmc %d", config->hmc_mode); |
434 | if (alt_pingroup) | 551 | if (!alt_pingroup) |
435 | printk(", usb2 alt %d wires", config->pins[2]); | 552 | printk(", usb2 alt %d wires", config->pins[2]); |
436 | else if (config->pins[0]) | 553 | else if (config->pins[0]) |
437 | printk(", usb0 %d wires%s", config->pins[0], | 554 | printk(", usb0 %d wires%s", config->pins[0], |
@@ -444,10 +561,12 @@ omap_otg_init(struct omap_usb_config *config) | |||
444 | printk(", Mini-AB on usb%d", config->otg - 1); | 561 | printk(", Mini-AB on usb%d", config->otg - 1); |
445 | printk("\n"); | 562 | printk("\n"); |
446 | 563 | ||
447 | /* leave USB clocks/controllers off until needed */ | 564 | if (cpu_class_is_omap1()) { |
448 | ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; | 565 | /* leave USB clocks/controllers off until needed */ |
449 | ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; | 566 | ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; |
450 | ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; | 567 | ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; |
568 | ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; | ||
569 | } | ||
451 | syscon = OTG_SYSCON_1_REG; | 570 | syscon = OTG_SYSCON_1_REG; |
452 | syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; | 571 | syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; |
453 | 572 | ||
@@ -585,7 +704,7 @@ omap_usb_init(void) | |||
585 | } | 704 | } |
586 | platform_data = *config; | 705 | platform_data = *config; |
587 | 706 | ||
588 | if (cpu_is_omap730() || cpu_is_omap16xx()) | 707 | if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx()) |
589 | omap_otg_init(&platform_data); | 708 | omap_otg_init(&platform_data); |
590 | else if (cpu_is_omap15xx()) | 709 | else if (cpu_is_omap15xx()) |
591 | omap_1510_usb_init(&platform_data); | 710 | omap_1510_usb_init(&platform_data); |