diff options
Diffstat (limited to 'arch/arm/mach-omap1')
-rw-r--r-- | arch/arm/mach-omap1/Kconfig | 144 | ||||
-rw-r--r-- | arch/arm/mach-omap1/Makefile | 30 | ||||
-rw-r--r-- | arch/arm/mach-omap1/Makefile.boot | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap1/board-generic.c | 99 | ||||
-rw-r--r-- | arch/arm/mach-omap1/board-h2.c | 188 | ||||
-rw-r--r-- | arch/arm/mach-omap1/board-h3.c | 206 | ||||
-rw-r--r-- | arch/arm/mach-omap1/board-innovator.c | 281 | ||||
-rw-r--r-- | arch/arm/mach-omap1/board-netstar.c | 152 | ||||
-rw-r--r-- | arch/arm/mach-omap1/board-osk.c | 170 | ||||
-rw-r--r-- | arch/arm/mach-omap1/board-perseus2.c | 190 | ||||
-rw-r--r-- | arch/arm/mach-omap1/board-voiceblue.c | 257 | ||||
-rw-r--r-- | arch/arm/mach-omap1/fpga.c | 188 | ||||
-rw-r--r-- | arch/arm/mach-omap1/id.c | 188 | ||||
-rw-r--r-- | arch/arm/mach-omap1/io.c | 115 | ||||
-rw-r--r-- | arch/arm/mach-omap1/irq.c | 234 | ||||
-rw-r--r-- | arch/arm/mach-omap1/leds-h2p2-debug.c | 144 | ||||
-rw-r--r-- | arch/arm/mach-omap1/leds-innovator.c | 103 | ||||
-rw-r--r-- | arch/arm/mach-omap1/leds-osk.c | 194 | ||||
-rw-r--r-- | arch/arm/mach-omap1/leds.c | 61 | ||||
-rw-r--r-- | arch/arm/mach-omap1/leds.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap1/serial.c | 200 | ||||
-rw-r--r-- | arch/arm/mach-omap1/time.c | 436 |
22 files changed, 3586 insertions, 0 deletions
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig new file mode 100644 index 000000000000..7408ac94f771 --- /dev/null +++ b/arch/arm/mach-omap1/Kconfig | |||
@@ -0,0 +1,144 @@ | |||
1 | comment "OMAP Core Type" | ||
2 | depends on ARCH_OMAP1 | ||
3 | |||
4 | config ARCH_OMAP730 | ||
5 | depends on ARCH_OMAP1 | ||
6 | bool "OMAP730 Based System" | ||
7 | select ARCH_OMAP_OTG | ||
8 | |||
9 | config ARCH_OMAP1510 | ||
10 | depends on ARCH_OMAP1 | ||
11 | default y | ||
12 | bool "OMAP1510 Based System" | ||
13 | |||
14 | config ARCH_OMAP16XX | ||
15 | depends on ARCH_OMAP1 | ||
16 | bool "OMAP16xx Based System" | ||
17 | select ARCH_OMAP_OTG | ||
18 | |||
19 | comment "OMAP Board Type" | ||
20 | depends on ARCH_OMAP1 | ||
21 | |||
22 | config MACH_OMAP_INNOVATOR | ||
23 | bool "TI Innovator" | ||
24 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX) | ||
25 | help | ||
26 | TI OMAP 1510 or 1610 Innovator board support. Say Y here if you | ||
27 | have such a board. | ||
28 | |||
29 | config MACH_OMAP_H2 | ||
30 | bool "TI H2 Support" | ||
31 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | ||
32 | help | ||
33 | TI OMAP 1610/1611B H2 board support. Say Y here if you have such | ||
34 | a board. | ||
35 | |||
36 | config MACH_OMAP_H3 | ||
37 | bool "TI H3 Support" | ||
38 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | ||
39 | help | ||
40 | TI OMAP 1710 H3 board support. Say Y here if you have such | ||
41 | a board. | ||
42 | |||
43 | config MACH_OMAP_OSK | ||
44 | bool "TI OSK Support" | ||
45 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | ||
46 | help | ||
47 | TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here | ||
48 | if you have such a board. | ||
49 | |||
50 | config MACH_OMAP_PERSEUS2 | ||
51 | bool "TI Perseus2" | ||
52 | depends on ARCH_OMAP1 && ARCH_OMAP730 | ||
53 | help | ||
54 | Support for TI OMAP 730 Perseus2 board. Say Y here if you have such | ||
55 | a board. | ||
56 | |||
57 | config MACH_VOICEBLUE | ||
58 | bool "Voiceblue" | ||
59 | depends on ARCH_OMAP1 && ARCH_OMAP1510 | ||
60 | help | ||
61 | Support for Voiceblue GSM/VoIP gateway. Say Y here if you have | ||
62 | such a board. | ||
63 | |||
64 | config MACH_NETSTAR | ||
65 | bool "NetStar" | ||
66 | depends on ARCH_OMAP1 && ARCH_OMAP1510 | ||
67 | help | ||
68 | Support for NetStar PBX. Say Y here if you have such a board. | ||
69 | |||
70 | config MACH_OMAP_GENERIC | ||
71 | bool "Generic OMAP board" | ||
72 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX) | ||
73 | help | ||
74 | Support for generic OMAP-1510, 1610 or 1710 board with | ||
75 | no FPGA. Can be used as template for porting Linux to | ||
76 | custom OMAP boards. Say Y here if you have a custom | ||
77 | board. | ||
78 | |||
79 | comment "OMAP CPU Speed" | ||
80 | depends on ARCH_OMAP1 | ||
81 | |||
82 | config OMAP_CLOCKS_SET_BY_BOOTLOADER | ||
83 | bool "OMAP clocks set by bootloader" | ||
84 | depends on ARCH_OMAP1 | ||
85 | help | ||
86 | Enable this option to prevent the kernel from overriding the clock | ||
87 | frequencies programmed by bootloader for MPU, DSP, MMUs, TC, | ||
88 | internal LCD controller and MPU peripherals. | ||
89 | |||
90 | config OMAP_ARM_216MHZ | ||
91 | bool "OMAP ARM 216 MHz CPU (1710 only)" | ||
92 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | ||
93 | help | ||
94 | Enable 216 MHz clock for OMAP1710 CPU. If unsure, say N. | ||
95 | |||
96 | config OMAP_ARM_195MHZ | ||
97 | bool "OMAP ARM 195 MHz CPU" | ||
98 | depends on ARCH_OMAP1 && ARCH_OMAP730 | ||
99 | help | ||
100 | Enable 195MHz clock for OMAP CPU. If unsure, say N. | ||
101 | |||
102 | config OMAP_ARM_192MHZ | ||
103 | bool "OMAP ARM 192 MHz CPU" | ||
104 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | ||
105 | help | ||
106 | Enable 192MHz clock for OMAP CPU. If unsure, say N. | ||
107 | |||
108 | config OMAP_ARM_182MHZ | ||
109 | bool "OMAP ARM 182 MHz CPU" | ||
110 | depends on ARCH_OMAP1 && ARCH_OMAP730 | ||
111 | help | ||
112 | Enable 182MHz clock for OMAP CPU. If unsure, say N. | ||
113 | |||
114 | config OMAP_ARM_168MHZ | ||
115 | bool "OMAP ARM 168 MHz CPU" | ||
116 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730) | ||
117 | help | ||
118 | Enable 168MHz clock for OMAP CPU. If unsure, say N. | ||
119 | |||
120 | config OMAP_ARM_150MHZ | ||
121 | bool "OMAP ARM 150 MHz CPU" | ||
122 | depends on ARCH_OMAP1 && ARCH_OMAP1510 | ||
123 | help | ||
124 | Enable 150MHz clock for OMAP CPU. If unsure, say N. | ||
125 | |||
126 | config OMAP_ARM_120MHZ | ||
127 | bool "OMAP ARM 120 MHz CPU" | ||
128 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730) | ||
129 | help | ||
130 | Enable 120MHz clock for OMAP CPU. If unsure, say N. | ||
131 | |||
132 | config OMAP_ARM_60MHZ | ||
133 | bool "OMAP ARM 60 MHz CPU" | ||
134 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730) | ||
135 | default y | ||
136 | help | ||
137 | Enable 60MHz clock for OMAP CPU. If unsure, say Y. | ||
138 | |||
139 | config OMAP_ARM_30MHZ | ||
140 | bool "OMAP ARM 30 MHz CPU" | ||
141 | depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730) | ||
142 | help | ||
143 | Enable 30MHz clock for OMAP CPU. If unsure, say N. | ||
144 | |||
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile new file mode 100644 index 000000000000..d386fd913f0c --- /dev/null +++ b/arch/arm/mach-omap1/Makefile | |||
@@ -0,0 +1,30 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | # Common support | ||
6 | obj-y := io.o id.o irq.o time.o serial.o | ||
7 | led-y := leds.o | ||
8 | |||
9 | # Specific board support | ||
10 | obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o | ||
11 | obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o | ||
12 | obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o | ||
13 | obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o | ||
14 | obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o | ||
15 | obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o | ||
16 | obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o | ||
17 | obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o | ||
18 | |||
19 | ifeq ($(CONFIG_ARCH_OMAP1510),y) | ||
20 | # Innovator-1510 FPGA | ||
21 | obj-$(CONFIG_MACH_OMAP_INNOVATOR) += fpga.o | ||
22 | endif | ||
23 | |||
24 | # LEDs support | ||
25 | led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o | ||
26 | led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o | ||
27 | led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o | ||
28 | led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o | ||
29 | obj-$(CONFIG_LEDS) += $(led-y) | ||
30 | |||
diff --git a/arch/arm/mach-omap1/Makefile.boot b/arch/arm/mach-omap1/Makefile.boot new file mode 100644 index 000000000000..292d56c5a888 --- /dev/null +++ b/arch/arm/mach-omap1/Makefile.boot | |||
@@ -0,0 +1,3 @@ | |||
1 | zreladdr-y := 0x10008000 | ||
2 | params_phys-y := 0x10000100 | ||
3 | initrd_phys-y := 0x10800000 | ||
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c new file mode 100644 index 000000000000..122796ebe8f5 --- /dev/null +++ b/arch/arm/mach-omap1/board-generic.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-generic.c | ||
3 | * | ||
4 | * Modified from board-innovator1510.c | ||
5 | * | ||
6 | * Code for generic OMAP board. Should work on many OMAP systems where | ||
7 | * the device drivers take care of all the necessary hardware initialization. | ||
8 | * Do not put any board specific code to this file; create a new machine | ||
9 | * type if you need custom low-level initializations. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/device.h> | ||
19 | |||
20 | #include <asm/hardware.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/mach/arch.h> | ||
23 | #include <asm/mach/map.h> | ||
24 | |||
25 | #include <asm/arch/gpio.h> | ||
26 | #include <asm/arch/mux.h> | ||
27 | #include <asm/arch/usb.h> | ||
28 | #include <asm/arch/board.h> | ||
29 | #include <asm/arch/common.h> | ||
30 | |||
31 | static int __initdata generic_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
32 | |||
33 | static void __init omap_generic_init_irq(void) | ||
34 | { | ||
35 | omap_init_irq(); | ||
36 | } | ||
37 | |||
38 | /* assume no Mini-AB port */ | ||
39 | |||
40 | #ifdef CONFIG_ARCH_OMAP1510 | ||
41 | static struct omap_usb_config generic1510_usb_config __initdata = { | ||
42 | .register_host = 1, | ||
43 | .register_dev = 1, | ||
44 | .hmc_mode = 16, | ||
45 | .pins[0] = 3, | ||
46 | }; | ||
47 | #endif | ||
48 | |||
49 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
50 | static struct omap_usb_config generic1610_usb_config __initdata = { | ||
51 | .register_host = 1, | ||
52 | .register_dev = 1, | ||
53 | .hmc_mode = 16, | ||
54 | .pins[0] = 6, | ||
55 | }; | ||
56 | #endif | ||
57 | |||
58 | static struct omap_board_config_kernel generic_config[] = { | ||
59 | { OMAP_TAG_USB, NULL }, | ||
60 | }; | ||
61 | |||
62 | static void __init omap_generic_init(void) | ||
63 | { | ||
64 | /* | ||
65 | * Make sure the serial ports are muxed on at this point. | ||
66 | * You have to mux them off in device drivers later on | ||
67 | * if not needed. | ||
68 | */ | ||
69 | #ifdef CONFIG_ARCH_OMAP1510 | ||
70 | if (cpu_is_omap1510()) { | ||
71 | generic_config[0].data = &generic1510_usb_config; | ||
72 | } | ||
73 | #endif | ||
74 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
75 | if (!cpu_is_omap1510()) { | ||
76 | generic_config[0].data = &generic1610_usb_config; | ||
77 | } | ||
78 | #endif | ||
79 | omap_board_config = generic_config; | ||
80 | omap_board_config_size = ARRAY_SIZE(generic_config); | ||
81 | omap_serial_init(generic_serial_ports); | ||
82 | } | ||
83 | |||
84 | static void __init omap_generic_map_io(void) | ||
85 | { | ||
86 | omap_map_common_io() | ||
87 | } | ||
88 | |||
89 | MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") | ||
90 | /* Maintainer: Tony Lindgren <tony@atomide.com> */ | ||
91 | .phys_ram = 0x10000000, | ||
92 | .phys_io = 0xfff00000, | ||
93 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
94 | .boot_params = 0x10000100, | ||
95 | .map_io = omap_generic_map_io, | ||
96 | .init_irq = omap_generic_init_irq, | ||
97 | .init_machine = omap_generic_init, | ||
98 | .timer = &omap_timer, | ||
99 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c new file mode 100644 index 000000000000..f4983ee95ab4 --- /dev/null +++ b/arch/arm/mach-omap1/board-h2.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-h2.c | ||
3 | * | ||
4 | * Board specific inits for OMAP-1610 H2 | ||
5 | * | ||
6 | * Copyright (C) 2001 RidgeRun, Inc. | ||
7 | * Author: Greg Lonnon <glonnon@ridgerun.com> | ||
8 | * | ||
9 | * Copyright (C) 2002 MontaVista Software, Inc. | ||
10 | * | ||
11 | * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6 | ||
12 | * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com> | ||
13 | * | ||
14 | * H2 specific changes and cleanup | ||
15 | * Copyright (C) 2004 Nokia Corporation by Imre Deak <imre.deak@nokia.com> | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License version 2 as | ||
19 | * published by the Free Software Foundation. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/mtd/mtd.h> | ||
27 | #include <linux/mtd/partitions.h> | ||
28 | |||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <asm/mach/arch.h> | ||
32 | #include <asm/mach/flash.h> | ||
33 | #include <asm/mach/map.h> | ||
34 | |||
35 | #include <asm/arch/gpio.h> | ||
36 | #include <asm/arch/tc.h> | ||
37 | #include <asm/arch/usb.h> | ||
38 | #include <asm/arch/common.h> | ||
39 | |||
40 | extern int omap_gpio_init(void); | ||
41 | |||
42 | static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
43 | |||
44 | static struct mtd_partition h2_partitions[] = { | ||
45 | /* bootloader (U-Boot, etc) in first sector */ | ||
46 | { | ||
47 | .name = "bootloader", | ||
48 | .offset = 0, | ||
49 | .size = SZ_128K, | ||
50 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
51 | }, | ||
52 | /* bootloader params in the next sector */ | ||
53 | { | ||
54 | .name = "params", | ||
55 | .offset = MTDPART_OFS_APPEND, | ||
56 | .size = SZ_128K, | ||
57 | .mask_flags = 0, | ||
58 | }, | ||
59 | /* kernel */ | ||
60 | { | ||
61 | .name = "kernel", | ||
62 | .offset = MTDPART_OFS_APPEND, | ||
63 | .size = SZ_2M, | ||
64 | .mask_flags = 0 | ||
65 | }, | ||
66 | /* file system */ | ||
67 | { | ||
68 | .name = "filesystem", | ||
69 | .offset = MTDPART_OFS_APPEND, | ||
70 | .size = MTDPART_SIZ_FULL, | ||
71 | .mask_flags = 0 | ||
72 | } | ||
73 | }; | ||
74 | |||
75 | static struct flash_platform_data h2_flash_data = { | ||
76 | .map_name = "cfi_probe", | ||
77 | .width = 2, | ||
78 | .parts = h2_partitions, | ||
79 | .nr_parts = ARRAY_SIZE(h2_partitions), | ||
80 | }; | ||
81 | |||
82 | static struct resource h2_flash_resource = { | ||
83 | .start = OMAP_CS2B_PHYS, | ||
84 | .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1, | ||
85 | .flags = IORESOURCE_MEM, | ||
86 | }; | ||
87 | |||
88 | static struct platform_device h2_flash_device = { | ||
89 | .name = "omapflash", | ||
90 | .id = 0, | ||
91 | .dev = { | ||
92 | .platform_data = &h2_flash_data, | ||
93 | }, | ||
94 | .num_resources = 1, | ||
95 | .resource = &h2_flash_resource, | ||
96 | }; | ||
97 | |||
98 | static struct resource h2_smc91x_resources[] = { | ||
99 | [0] = { | ||
100 | .start = OMAP1610_ETHR_START, /* Physical */ | ||
101 | .end = OMAP1610_ETHR_START + 0xf, | ||
102 | .flags = IORESOURCE_MEM, | ||
103 | }, | ||
104 | [1] = { | ||
105 | .start = OMAP_GPIO_IRQ(0), | ||
106 | .end = OMAP_GPIO_IRQ(0), | ||
107 | .flags = IORESOURCE_IRQ, | ||
108 | }, | ||
109 | }; | ||
110 | |||
111 | static struct platform_device h2_smc91x_device = { | ||
112 | .name = "smc91x", | ||
113 | .id = 0, | ||
114 | .num_resources = ARRAY_SIZE(h2_smc91x_resources), | ||
115 | .resource = h2_smc91x_resources, | ||
116 | }; | ||
117 | |||
118 | static struct platform_device *h2_devices[] __initdata = { | ||
119 | &h2_flash_device, | ||
120 | &h2_smc91x_device, | ||
121 | }; | ||
122 | |||
123 | static void __init h2_init_smc91x(void) | ||
124 | { | ||
125 | if ((omap_request_gpio(0)) < 0) { | ||
126 | printk("Error requesting gpio 0 for smc91x irq\n"); | ||
127 | return; | ||
128 | } | ||
129 | omap_set_gpio_edge_ctrl(0, OMAP_GPIO_FALLING_EDGE); | ||
130 | } | ||
131 | |||
132 | void h2_init_irq(void) | ||
133 | { | ||
134 | omap_init_irq(); | ||
135 | omap_gpio_init(); | ||
136 | h2_init_smc91x(); | ||
137 | } | ||
138 | |||
139 | static struct omap_usb_config h2_usb_config __initdata = { | ||
140 | /* usb1 has a Mini-AB port and external isp1301 transceiver */ | ||
141 | .otg = 2, | ||
142 | |||
143 | #ifdef CONFIG_USB_GADGET_OMAP | ||
144 | .hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled | ||
145 | // .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback) | ||
146 | #elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) | ||
147 | /* needs OTG cable, or NONSTANDARD (B-to-MiniB) */ | ||
148 | .hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled | ||
149 | #endif | ||
150 | |||
151 | .pins[1] = 3, | ||
152 | }; | ||
153 | |||
154 | static struct omap_mmc_config h2_mmc_config __initdata = { | ||
155 | .mmc_blocks = 1, | ||
156 | .mmc1_power_pin = -1, /* tps65010 gpio3 */ | ||
157 | .mmc1_switch_pin = OMAP_MPUIO(1), | ||
158 | }; | ||
159 | |||
160 | static struct omap_board_config_kernel h2_config[] = { | ||
161 | { OMAP_TAG_USB, &h2_usb_config }, | ||
162 | { OMAP_TAG_MMC, &h2_mmc_config }, | ||
163 | }; | ||
164 | |||
165 | static void __init h2_init(void) | ||
166 | { | ||
167 | platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); | ||
168 | omap_board_config = h2_config; | ||
169 | omap_board_config_size = ARRAY_SIZE(h2_config); | ||
170 | } | ||
171 | |||
172 | static void __init h2_map_io(void) | ||
173 | { | ||
174 | omap_map_common_io(); | ||
175 | omap_serial_init(h2_serial_ports); | ||
176 | } | ||
177 | |||
178 | MACHINE_START(OMAP_H2, "TI-H2") | ||
179 | /* Maintainer: Imre Deak <imre.deak@nokia.com> */ | ||
180 | .phys_ram = 0x10000000, | ||
181 | .phys_io = 0xfff00000, | ||
182 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
183 | .boot_params = 0x10000100, | ||
184 | .map_io = h2_map_io, | ||
185 | .init_irq = h2_init_irq, | ||
186 | .init_machine = h2_init, | ||
187 | .timer = &omap_timer, | ||
188 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c new file mode 100644 index 000000000000..7cd419d61b40 --- /dev/null +++ b/arch/arm/mach-omap1/board-h3.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-h3.c | ||
3 | * | ||
4 | * This file contains OMAP1710 H3 specific code. | ||
5 | * | ||
6 | * Copyright (C) 2004 Texas Instruments, Inc. | ||
7 | * Copyright (C) 2002 MontaVista Software, Inc. | ||
8 | * Copyright (C) 2001 RidgeRun, Inc. | ||
9 | * Author: RidgeRun, Inc. | ||
10 | * Greg Lonnon (glonnon@ridgerun.com) or info@ridgerun.com | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/config.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/major.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/mtd/mtd.h> | ||
25 | #include <linux/mtd/partitions.h> | ||
26 | |||
27 | #include <asm/setup.h> | ||
28 | #include <asm/page.h> | ||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <asm/mach/arch.h> | ||
32 | #include <asm/mach/flash.h> | ||
33 | #include <asm/mach/map.h> | ||
34 | |||
35 | #include <asm/arch/gpio.h> | ||
36 | #include <asm/arch/irqs.h> | ||
37 | #include <asm/arch/mux.h> | ||
38 | #include <asm/arch/tc.h> | ||
39 | #include <asm/arch/usb.h> | ||
40 | #include <asm/arch/common.h> | ||
41 | |||
42 | extern int omap_gpio_init(void); | ||
43 | |||
44 | static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
45 | |||
46 | static struct mtd_partition h3_partitions[] = { | ||
47 | /* bootloader (U-Boot, etc) in first sector */ | ||
48 | { | ||
49 | .name = "bootloader", | ||
50 | .offset = 0, | ||
51 | .size = SZ_128K, | ||
52 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
53 | }, | ||
54 | /* bootloader params in the next sector */ | ||
55 | { | ||
56 | .name = "params", | ||
57 | .offset = MTDPART_OFS_APPEND, | ||
58 | .size = SZ_128K, | ||
59 | .mask_flags = 0, | ||
60 | }, | ||
61 | /* kernel */ | ||
62 | { | ||
63 | .name = "kernel", | ||
64 | .offset = MTDPART_OFS_APPEND, | ||
65 | .size = SZ_2M, | ||
66 | .mask_flags = 0 | ||
67 | }, | ||
68 | /* file system */ | ||
69 | { | ||
70 | .name = "filesystem", | ||
71 | .offset = MTDPART_OFS_APPEND, | ||
72 | .size = MTDPART_SIZ_FULL, | ||
73 | .mask_flags = 0 | ||
74 | } | ||
75 | }; | ||
76 | |||
77 | static struct flash_platform_data h3_flash_data = { | ||
78 | .map_name = "cfi_probe", | ||
79 | .width = 2, | ||
80 | .parts = h3_partitions, | ||
81 | .nr_parts = ARRAY_SIZE(h3_partitions), | ||
82 | }; | ||
83 | |||
84 | static struct resource h3_flash_resource = { | ||
85 | .start = OMAP_CS2B_PHYS, | ||
86 | .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1, | ||
87 | .flags = IORESOURCE_MEM, | ||
88 | }; | ||
89 | |||
90 | static struct platform_device flash_device = { | ||
91 | .name = "omapflash", | ||
92 | .id = 0, | ||
93 | .dev = { | ||
94 | .platform_data = &h3_flash_data, | ||
95 | }, | ||
96 | .num_resources = 1, | ||
97 | .resource = &h3_flash_resource, | ||
98 | }; | ||
99 | |||
100 | static struct resource smc91x_resources[] = { | ||
101 | [0] = { | ||
102 | .start = OMAP1710_ETHR_START, /* Physical */ | ||
103 | .end = OMAP1710_ETHR_START + 0xf, | ||
104 | .flags = IORESOURCE_MEM, | ||
105 | }, | ||
106 | [1] = { | ||
107 | .start = OMAP_GPIO_IRQ(40), | ||
108 | .end = OMAP_GPIO_IRQ(40), | ||
109 | .flags = IORESOURCE_IRQ, | ||
110 | }, | ||
111 | }; | ||
112 | |||
113 | static struct platform_device smc91x_device = { | ||
114 | .name = "smc91x", | ||
115 | .id = 0, | ||
116 | .num_resources = ARRAY_SIZE(smc91x_resources), | ||
117 | .resource = smc91x_resources, | ||
118 | }; | ||
119 | |||
120 | #define GPTIMER_BASE 0xFFFB1400 | ||
121 | #define GPTIMER_REGS(x) (0xFFFB1400 + (x * 0x800)) | ||
122 | #define GPTIMER_REGS_SIZE 0x46 | ||
123 | |||
124 | static struct resource intlat_resources[] = { | ||
125 | [0] = { | ||
126 | .start = GPTIMER_REGS(0), /* Physical */ | ||
127 | .end = GPTIMER_REGS(0) + GPTIMER_REGS_SIZE, | ||
128 | .flags = IORESOURCE_MEM, | ||
129 | }, | ||
130 | [1] = { | ||
131 | .start = INT_1610_GPTIMER1, | ||
132 | .end = INT_1610_GPTIMER1, | ||
133 | .flags = IORESOURCE_IRQ, | ||
134 | }, | ||
135 | }; | ||
136 | |||
137 | static struct platform_device intlat_device = { | ||
138 | .name = "omap_intlat", | ||
139 | .id = 0, | ||
140 | .num_resources = ARRAY_SIZE(intlat_resources), | ||
141 | .resource = intlat_resources, | ||
142 | }; | ||
143 | |||
144 | static struct platform_device *devices[] __initdata = { | ||
145 | &flash_device, | ||
146 | &smc91x_device, | ||
147 | &intlat_device, | ||
148 | }; | ||
149 | |||
150 | static struct omap_usb_config h3_usb_config __initdata = { | ||
151 | /* usb1 has a Mini-AB port and external isp1301 transceiver */ | ||
152 | .otg = 2, | ||
153 | |||
154 | #ifdef CONFIG_USB_GADGET_OMAP | ||
155 | .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */ | ||
156 | #elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) | ||
157 | /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */ | ||
158 | .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */ | ||
159 | #endif | ||
160 | |||
161 | .pins[1] = 3, | ||
162 | }; | ||
163 | |||
164 | static struct omap_board_config_kernel h3_config[] = { | ||
165 | { OMAP_TAG_USB, &h3_usb_config }, | ||
166 | }; | ||
167 | |||
168 | static void __init h3_init(void) | ||
169 | { | ||
170 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
171 | } | ||
172 | |||
173 | static void __init h3_init_smc91x(void) | ||
174 | { | ||
175 | omap_cfg_reg(W15_1710_GPIO40); | ||
176 | if (omap_request_gpio(40) < 0) { | ||
177 | printk("Error requesting gpio 40 for smc91x irq\n"); | ||
178 | return; | ||
179 | } | ||
180 | omap_set_gpio_edge_ctrl(40, OMAP_GPIO_FALLING_EDGE); | ||
181 | } | ||
182 | |||
183 | void h3_init_irq(void) | ||
184 | { | ||
185 | omap_init_irq(); | ||
186 | omap_gpio_init(); | ||
187 | h3_init_smc91x(); | ||
188 | } | ||
189 | |||
190 | static void __init h3_map_io(void) | ||
191 | { | ||
192 | omap_map_common_io(); | ||
193 | omap_serial_init(h3_serial_ports); | ||
194 | } | ||
195 | |||
196 | MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") | ||
197 | /* Maintainer: Texas Instruments, Inc. */ | ||
198 | .phys_ram = 0x10000000, | ||
199 | .phys_io = 0xfff00000, | ||
200 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
201 | .boot_params = 0x10000100, | ||
202 | .map_io = h3_map_io, | ||
203 | .init_irq = h3_init_irq, | ||
204 | .init_machine = h3_init, | ||
205 | .timer = &omap_timer, | ||
206 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c new file mode 100644 index 000000000000..91de60a91ef8 --- /dev/null +++ b/arch/arm/mach-omap1/board-innovator.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-innovator.c | ||
3 | * | ||
4 | * Board specific inits for OMAP-1510 and OMAP-1610 Innovator | ||
5 | * | ||
6 | * Copyright (C) 2001 RidgeRun, Inc. | ||
7 | * Author: Greg Lonnon <glonnon@ridgerun.com> | ||
8 | * | ||
9 | * Copyright (C) 2002 MontaVista Software, Inc. | ||
10 | * | ||
11 | * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6 | ||
12 | * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/mtd/mtd.h> | ||
24 | #include <linux/mtd/partitions.h> | ||
25 | |||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include <asm/mach/arch.h> | ||
29 | #include <asm/mach/flash.h> | ||
30 | #include <asm/mach/map.h> | ||
31 | |||
32 | #include <asm/arch/fpga.h> | ||
33 | #include <asm/arch/gpio.h> | ||
34 | #include <asm/arch/tc.h> | ||
35 | #include <asm/arch/usb.h> | ||
36 | #include <asm/arch/common.h> | ||
37 | |||
38 | static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
39 | |||
40 | static struct mtd_partition innovator_partitions[] = { | ||
41 | /* bootloader (U-Boot, etc) in first sector */ | ||
42 | { | ||
43 | .name = "bootloader", | ||
44 | .offset = 0, | ||
45 | .size = SZ_128K, | ||
46 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
47 | }, | ||
48 | /* bootloader params in the next sector */ | ||
49 | { | ||
50 | .name = "params", | ||
51 | .offset = MTDPART_OFS_APPEND, | ||
52 | .size = SZ_128K, | ||
53 | .mask_flags = 0, | ||
54 | }, | ||
55 | /* kernel */ | ||
56 | { | ||
57 | .name = "kernel", | ||
58 | .offset = MTDPART_OFS_APPEND, | ||
59 | .size = SZ_2M, | ||
60 | .mask_flags = 0 | ||
61 | }, | ||
62 | /* rest of flash1 is a file system */ | ||
63 | { | ||
64 | .name = "rootfs", | ||
65 | .offset = MTDPART_OFS_APPEND, | ||
66 | .size = SZ_16M - SZ_2M - 2 * SZ_128K, | ||
67 | .mask_flags = 0 | ||
68 | }, | ||
69 | /* file system */ | ||
70 | { | ||
71 | .name = "filesystem", | ||
72 | .offset = MTDPART_OFS_APPEND, | ||
73 | .size = MTDPART_SIZ_FULL, | ||
74 | .mask_flags = 0 | ||
75 | } | ||
76 | }; | ||
77 | |||
78 | static struct flash_platform_data innovator_flash_data = { | ||
79 | .map_name = "cfi_probe", | ||
80 | .width = 2, | ||
81 | .parts = innovator_partitions, | ||
82 | .nr_parts = ARRAY_SIZE(innovator_partitions), | ||
83 | }; | ||
84 | |||
85 | static struct resource innovator_flash_resource = { | ||
86 | .start = OMAP_CS0_PHYS, | ||
87 | .end = OMAP_CS0_PHYS + SZ_32M - 1, | ||
88 | .flags = IORESOURCE_MEM, | ||
89 | }; | ||
90 | |||
91 | static struct platform_device innovator_flash_device = { | ||
92 | .name = "omapflash", | ||
93 | .id = 0, | ||
94 | .dev = { | ||
95 | .platform_data = &innovator_flash_data, | ||
96 | }, | ||
97 | .num_resources = 1, | ||
98 | .resource = &innovator_flash_resource, | ||
99 | }; | ||
100 | |||
101 | #ifdef CONFIG_ARCH_OMAP1510 | ||
102 | |||
103 | /* Only FPGA needs to be mapped here. All others are done with ioremap */ | ||
104 | static struct map_desc innovator1510_io_desc[] __initdata = { | ||
105 | { OMAP1510_FPGA_BASE, OMAP1510_FPGA_START, OMAP1510_FPGA_SIZE, | ||
106 | MT_DEVICE }, | ||
107 | }; | ||
108 | |||
109 | static struct resource innovator1510_smc91x_resources[] = { | ||
110 | [0] = { | ||
111 | .start = OMAP1510_FPGA_ETHR_START, /* Physical */ | ||
112 | .end = OMAP1510_FPGA_ETHR_START + 0xf, | ||
113 | .flags = IORESOURCE_MEM, | ||
114 | }, | ||
115 | [1] = { | ||
116 | .start = OMAP1510_INT_ETHER, | ||
117 | .end = OMAP1510_INT_ETHER, | ||
118 | .flags = IORESOURCE_IRQ, | ||
119 | }, | ||
120 | }; | ||
121 | |||
122 | static struct platform_device innovator1510_smc91x_device = { | ||
123 | .name = "smc91x", | ||
124 | .id = 0, | ||
125 | .num_resources = ARRAY_SIZE(innovator1510_smc91x_resources), | ||
126 | .resource = innovator1510_smc91x_resources, | ||
127 | }; | ||
128 | |||
129 | static struct platform_device *innovator1510_devices[] __initdata = { | ||
130 | &innovator_flash_device, | ||
131 | &innovator1510_smc91x_device, | ||
132 | }; | ||
133 | |||
134 | #endif /* CONFIG_ARCH_OMAP1510 */ | ||
135 | |||
136 | #ifdef CONFIG_ARCH_OMAP16XX | ||
137 | |||
138 | static struct resource innovator1610_smc91x_resources[] = { | ||
139 | [0] = { | ||
140 | .start = INNOVATOR1610_ETHR_START, /* Physical */ | ||
141 | .end = INNOVATOR1610_ETHR_START + 0xf, | ||
142 | .flags = IORESOURCE_MEM, | ||
143 | }, | ||
144 | [1] = { | ||
145 | .start = OMAP_GPIO_IRQ(0), | ||
146 | .end = OMAP_GPIO_IRQ(0), | ||
147 | .flags = IORESOURCE_IRQ, | ||
148 | }, | ||
149 | }; | ||
150 | |||
151 | static struct platform_device innovator1610_smc91x_device = { | ||
152 | .name = "smc91x", | ||
153 | .id = 0, | ||
154 | .num_resources = ARRAY_SIZE(innovator1610_smc91x_resources), | ||
155 | .resource = innovator1610_smc91x_resources, | ||
156 | }; | ||
157 | |||
158 | static struct platform_device *innovator1610_devices[] __initdata = { | ||
159 | &innovator_flash_device, | ||
160 | &innovator1610_smc91x_device, | ||
161 | }; | ||
162 | |||
163 | #endif /* CONFIG_ARCH_OMAP16XX */ | ||
164 | |||
165 | static void __init innovator_init_smc91x(void) | ||
166 | { | ||
167 | if (cpu_is_omap1510()) { | ||
168 | fpga_write(fpga_read(OMAP1510_FPGA_RST) & ~1, | ||
169 | OMAP1510_FPGA_RST); | ||
170 | udelay(750); | ||
171 | } else { | ||
172 | if ((omap_request_gpio(0)) < 0) { | ||
173 | printk("Error requesting gpio 0 for smc91x irq\n"); | ||
174 | return; | ||
175 | } | ||
176 | omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | void innovator_init_irq(void) | ||
181 | { | ||
182 | omap_init_irq(); | ||
183 | omap_gpio_init(); | ||
184 | #ifdef CONFIG_ARCH_OMAP1510 | ||
185 | if (cpu_is_omap1510()) { | ||
186 | omap1510_fpga_init_irq(); | ||
187 | } | ||
188 | #endif | ||
189 | innovator_init_smc91x(); | ||
190 | } | ||
191 | |||
192 | #ifdef CONFIG_ARCH_OMAP1510 | ||
193 | static struct omap_usb_config innovator1510_usb_config __initdata = { | ||
194 | /* for bundled non-standard host and peripheral cables */ | ||
195 | .hmc_mode = 4, | ||
196 | |||
197 | .register_host = 1, | ||
198 | .pins[1] = 6, | ||
199 | .pins[2] = 6, /* Conflicts with UART2 */ | ||
200 | |||
201 | .register_dev = 1, | ||
202 | .pins[0] = 2, | ||
203 | }; | ||
204 | #endif | ||
205 | |||
206 | #ifdef CONFIG_ARCH_OMAP16XX | ||
207 | static struct omap_usb_config h2_usb_config __initdata = { | ||
208 | /* usb1 has a Mini-AB port and external isp1301 transceiver */ | ||
209 | .otg = 2, | ||
210 | |||
211 | #ifdef CONFIG_USB_GADGET_OMAP | ||
212 | .hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled | ||
213 | // .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback) | ||
214 | #elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) | ||
215 | /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */ | ||
216 | .hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled | ||
217 | #endif | ||
218 | |||
219 | .pins[1] = 3, | ||
220 | }; | ||
221 | #endif | ||
222 | |||
223 | static struct omap_board_config_kernel innovator_config[] = { | ||
224 | { OMAP_TAG_USB, NULL }, | ||
225 | }; | ||
226 | |||
227 | static void __init innovator_init(void) | ||
228 | { | ||
229 | #ifdef CONFIG_ARCH_OMAP1510 | ||
230 | if (cpu_is_omap1510()) { | ||
231 | platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices)); | ||
232 | } | ||
233 | #endif | ||
234 | #ifdef CONFIG_ARCH_OMAP16XX | ||
235 | if (!cpu_is_omap1510()) { | ||
236 | platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices)); | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | #ifdef CONFIG_ARCH_OMAP1510 | ||
241 | if (cpu_is_omap1510()) | ||
242 | innovator_config[0].data = &innovator1510_usb_config; | ||
243 | #endif | ||
244 | #ifdef CONFIG_ARCH_OMAP16XX | ||
245 | if (cpu_is_omap1610()) | ||
246 | innovator_config[0].data = &h2_usb_config; | ||
247 | #endif | ||
248 | omap_board_config = innovator_config; | ||
249 | omap_board_config_size = ARRAY_SIZE(innovator_config); | ||
250 | } | ||
251 | |||
252 | static void __init innovator_map_io(void) | ||
253 | { | ||
254 | omap_map_common_io(); | ||
255 | |||
256 | #ifdef CONFIG_ARCH_OMAP1510 | ||
257 | if (cpu_is_omap1510()) { | ||
258 | iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc)); | ||
259 | udelay(10); /* Delay needed for FPGA */ | ||
260 | |||
261 | /* Dump the Innovator FPGA rev early - useful info for support. */ | ||
262 | printk("Innovator FPGA Rev %d.%d Board Rev %d\n", | ||
263 | fpga_read(OMAP1510_FPGA_REV_HIGH), | ||
264 | fpga_read(OMAP1510_FPGA_REV_LOW), | ||
265 | fpga_read(OMAP1510_FPGA_BOARD_REV)); | ||
266 | } | ||
267 | #endif | ||
268 | omap_serial_init(innovator_serial_ports); | ||
269 | } | ||
270 | |||
271 | MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") | ||
272 | /* Maintainer: MontaVista Software, Inc. */ | ||
273 | .phys_ram = 0x10000000, | ||
274 | .phys_io = 0xfff00000, | ||
275 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
276 | .boot_params = 0x10000100, | ||
277 | .map_io = innovator_map_io, | ||
278 | .init_irq = innovator_init_irq, | ||
279 | .init_machine = innovator_init, | ||
280 | .timer = &omap_timer, | ||
281 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c new file mode 100644 index 000000000000..6750b2014092 --- /dev/null +++ b/arch/arm/mach-omap1/board-netstar.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * Modified from board-generic.c | ||
3 | * | ||
4 | * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz> | ||
5 | * | ||
6 | * Code for Netstar OMAP board. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/delay.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/notifier.h> | ||
19 | #include <linux/reboot.h> | ||
20 | |||
21 | #include <asm/hardware.h> | ||
22 | #include <asm/mach-types.h> | ||
23 | #include <asm/mach/arch.h> | ||
24 | #include <asm/mach/map.h> | ||
25 | |||
26 | #include <asm/arch/gpio.h> | ||
27 | #include <asm/arch/mux.h> | ||
28 | #include <asm/arch/usb.h> | ||
29 | #include <asm/arch/common.h> | ||
30 | |||
31 | extern void __init omap_init_time(void); | ||
32 | extern int omap_gpio_init(void); | ||
33 | |||
34 | static struct resource netstar_smc91x_resources[] = { | ||
35 | [0] = { | ||
36 | .start = OMAP_CS1_PHYS + 0x300, | ||
37 | .end = OMAP_CS1_PHYS + 0x300 + 16, | ||
38 | .flags = IORESOURCE_MEM, | ||
39 | }, | ||
40 | [1] = { | ||
41 | .start = OMAP_GPIO_IRQ(8), | ||
42 | .end = OMAP_GPIO_IRQ(8), | ||
43 | .flags = IORESOURCE_IRQ, | ||
44 | }, | ||
45 | }; | ||
46 | |||
47 | static struct platform_device netstar_smc91x_device = { | ||
48 | .name = "smc91x", | ||
49 | .id = 0, | ||
50 | .num_resources = ARRAY_SIZE(netstar_smc91x_resources), | ||
51 | .resource = netstar_smc91x_resources, | ||
52 | }; | ||
53 | |||
54 | static struct platform_device *netstar_devices[] __initdata = { | ||
55 | &netstar_smc91x_device, | ||
56 | }; | ||
57 | |||
58 | static void __init netstar_init_irq(void) | ||
59 | { | ||
60 | omap_init_irq(); | ||
61 | omap_gpio_init(); | ||
62 | } | ||
63 | |||
64 | static void __init netstar_init(void) | ||
65 | { | ||
66 | /* green LED */ | ||
67 | omap_request_gpio(4); | ||
68 | omap_set_gpio_direction(4, 0); | ||
69 | /* smc91x reset */ | ||
70 | omap_request_gpio(7); | ||
71 | omap_set_gpio_direction(7, 0); | ||
72 | omap_set_gpio_dataout(7, 1); | ||
73 | udelay(2); /* wait at least 100ns */ | ||
74 | omap_set_gpio_dataout(7, 0); | ||
75 | mdelay(50); /* 50ms until PHY ready */ | ||
76 | /* smc91x interrupt pin */ | ||
77 | omap_request_gpio(8); | ||
78 | omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE); | ||
79 | |||
80 | omap_request_gpio(12); | ||
81 | omap_request_gpio(13); | ||
82 | omap_request_gpio(14); | ||
83 | omap_request_gpio(15); | ||
84 | omap_set_gpio_edge_ctrl(12, OMAP_GPIO_FALLING_EDGE); | ||
85 | omap_set_gpio_edge_ctrl(13, OMAP_GPIO_FALLING_EDGE); | ||
86 | omap_set_gpio_edge_ctrl(14, OMAP_GPIO_FALLING_EDGE); | ||
87 | omap_set_gpio_edge_ctrl(15, OMAP_GPIO_FALLING_EDGE); | ||
88 | |||
89 | platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices)); | ||
90 | |||
91 | /* Switch on green LED */ | ||
92 | omap_set_gpio_dataout(4, 0); | ||
93 | /* Switch off red LED */ | ||
94 | omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */ | ||
95 | omap_writeb(0x80, OMAP_LPG1_LCR); | ||
96 | } | ||
97 | |||
98 | static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
99 | |||
100 | static void __init netstar_map_io(void) | ||
101 | { | ||
102 | omap_map_common_io(); | ||
103 | omap_serial_init(omap_serial_ports); | ||
104 | } | ||
105 | |||
106 | #define MACHINE_PANICED 1 | ||
107 | #define MACHINE_REBOOTING 2 | ||
108 | #define MACHINE_REBOOT 4 | ||
109 | static unsigned long machine_state; | ||
110 | |||
111 | static int panic_event(struct notifier_block *this, unsigned long event, | ||
112 | void *ptr) | ||
113 | { | ||
114 | if (test_and_set_bit(MACHINE_PANICED, &machine_state)) | ||
115 | return NOTIFY_DONE; | ||
116 | |||
117 | /* Switch off green LED */ | ||
118 | omap_set_gpio_dataout(4, 1); | ||
119 | /* Flash red LED */ | ||
120 | omap_writeb(0x78, OMAP_LPG1_LCR); | ||
121 | omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */ | ||
122 | |||
123 | return NOTIFY_DONE; | ||
124 | } | ||
125 | |||
126 | static struct notifier_block panic_block = { | ||
127 | .notifier_call = panic_event, | ||
128 | }; | ||
129 | |||
130 | static int __init netstar_late_init(void) | ||
131 | { | ||
132 | /* TODO: Setup front panel switch here */ | ||
133 | |||
134 | /* Setup panic notifier */ | ||
135 | notifier_chain_register(&panic_notifier_list, &panic_block); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | postcore_initcall(netstar_late_init); | ||
141 | |||
142 | MACHINE_START(NETSTAR, "NetStar OMAP5910") | ||
143 | /* Maintainer: Ladislav Michl <michl@2n.cz> */ | ||
144 | .phys_ram = 0x10000000, | ||
145 | .phys_io = 0xfff00000, | ||
146 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
147 | .boot_params = 0x10000100, | ||
148 | .map_io = netstar_map_io, | ||
149 | .init_irq = netstar_init_irq, | ||
150 | .init_machine = netstar_init, | ||
151 | .timer = &omap_timer, | ||
152 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c new file mode 100644 index 000000000000..6844e536c698 --- /dev/null +++ b/arch/arm/mach-omap1/board-osk.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-osk.c | ||
3 | * | ||
4 | * Board specific init for OMAP5912 OSK | ||
5 | * | ||
6 | * Written by Dirk Behme <dirk.behme@de.bosch.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
14 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
15 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
16 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
17 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
18 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
19 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License along | ||
25 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
26 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | */ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/device.h> | ||
32 | |||
33 | #include <asm/hardware.h> | ||
34 | #include <asm/mach-types.h> | ||
35 | #include <asm/mach/arch.h> | ||
36 | #include <asm/mach/map.h> | ||
37 | |||
38 | #include <asm/arch/gpio.h> | ||
39 | #include <asm/arch/usb.h> | ||
40 | #include <asm/arch/mux.h> | ||
41 | #include <asm/arch/tc.h> | ||
42 | #include <asm/arch/common.h> | ||
43 | |||
44 | static struct map_desc osk5912_io_desc[] __initdata = { | ||
45 | { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE, | ||
46 | MT_DEVICE }, | ||
47 | }; | ||
48 | |||
49 | static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0}; | ||
50 | |||
51 | static struct resource osk5912_smc91x_resources[] = { | ||
52 | [0] = { | ||
53 | .start = OMAP_OSK_ETHR_START, /* Physical */ | ||
54 | .end = OMAP_OSK_ETHR_START + 0xf, | ||
55 | .flags = IORESOURCE_MEM, | ||
56 | }, | ||
57 | [1] = { | ||
58 | .start = OMAP_GPIO_IRQ(0), | ||
59 | .end = OMAP_GPIO_IRQ(0), | ||
60 | .flags = IORESOURCE_IRQ, | ||
61 | }, | ||
62 | }; | ||
63 | |||
64 | static struct platform_device osk5912_smc91x_device = { | ||
65 | .name = "smc91x", | ||
66 | .id = -1, | ||
67 | .num_resources = ARRAY_SIZE(osk5912_smc91x_resources), | ||
68 | .resource = osk5912_smc91x_resources, | ||
69 | }; | ||
70 | |||
71 | static struct resource osk5912_cf_resources[] = { | ||
72 | [0] = { | ||
73 | .start = OMAP_GPIO_IRQ(62), | ||
74 | .end = OMAP_GPIO_IRQ(62), | ||
75 | .flags = IORESOURCE_IRQ, | ||
76 | }, | ||
77 | }; | ||
78 | |||
79 | static struct platform_device osk5912_cf_device = { | ||
80 | .name = "omap_cf", | ||
81 | .id = -1, | ||
82 | .dev = { | ||
83 | .platform_data = (void *) 2 /* CS2 */, | ||
84 | }, | ||
85 | .num_resources = ARRAY_SIZE(osk5912_cf_resources), | ||
86 | .resource = osk5912_cf_resources, | ||
87 | }; | ||
88 | |||
89 | static struct platform_device *osk5912_devices[] __initdata = { | ||
90 | &osk5912_smc91x_device, | ||
91 | &osk5912_cf_device, | ||
92 | }; | ||
93 | |||
94 | static void __init osk_init_smc91x(void) | ||
95 | { | ||
96 | if ((omap_request_gpio(0)) < 0) { | ||
97 | printk("Error requesting gpio 0 for smc91x irq\n"); | ||
98 | return; | ||
99 | } | ||
100 | omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE); | ||
101 | |||
102 | /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ | ||
103 | EMIFS_CCS(1) |= 0x2; | ||
104 | } | ||
105 | |||
106 | static void __init osk_init_cf(void) | ||
107 | { | ||
108 | omap_cfg_reg(M7_1610_GPIO62); | ||
109 | if ((omap_request_gpio(62)) < 0) { | ||
110 | printk("Error requesting gpio 62 for CF irq\n"); | ||
111 | return; | ||
112 | } | ||
113 | /* it's really active-low */ | ||
114 | omap_set_gpio_edge_ctrl(62, OMAP_GPIO_FALLING_EDGE); | ||
115 | } | ||
116 | |||
117 | void osk_init_irq(void) | ||
118 | { | ||
119 | omap_init_irq(); | ||
120 | omap_gpio_init(); | ||
121 | osk_init_smc91x(); | ||
122 | osk_init_cf(); | ||
123 | } | ||
124 | |||
125 | static struct omap_usb_config osk_usb_config __initdata = { | ||
126 | /* has usb host connector (A) ... for development it can also | ||
127 | * be used, with a NONSTANDARD gender-bending cable/dongle, as | ||
128 | * a peripheral. | ||
129 | */ | ||
130 | #ifdef CONFIG_USB_GADGET_OMAP | ||
131 | .register_dev = 1, | ||
132 | .hmc_mode = 0, | ||
133 | #else | ||
134 | .register_host = 1, | ||
135 | .hmc_mode = 16, | ||
136 | .rwc = 1, | ||
137 | #endif | ||
138 | .pins[0] = 2, | ||
139 | }; | ||
140 | |||
141 | static struct omap_board_config_kernel osk_config[] = { | ||
142 | { OMAP_TAG_USB, &osk_usb_config }, | ||
143 | }; | ||
144 | |||
145 | static void __init osk_init(void) | ||
146 | { | ||
147 | platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); | ||
148 | omap_board_config = osk_config; | ||
149 | omap_board_config_size = ARRAY_SIZE(osk_config); | ||
150 | USB_TRANSCEIVER_CTRL_REG |= (3 << 1); | ||
151 | } | ||
152 | |||
153 | static void __init osk_map_io(void) | ||
154 | { | ||
155 | omap_map_common_io(); | ||
156 | iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc)); | ||
157 | omap_serial_init(osk_serial_ports); | ||
158 | } | ||
159 | |||
160 | MACHINE_START(OMAP_OSK, "TI-OSK") | ||
161 | /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */ | ||
162 | .phys_ram = 0x10000000, | ||
163 | .phys_io = 0xfff00000, | ||
164 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
165 | .boot_params = 0x10000100, | ||
166 | .map_io = osk_map_io, | ||
167 | .init_irq = osk_init_irq, | ||
168 | .init_machine = osk_init, | ||
169 | .timer = &omap_timer, | ||
170 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c new file mode 100644 index 000000000000..213317392d9b --- /dev/null +++ b/arch/arm/mach-omap1/board-perseus2.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-perseus2.c | ||
3 | * | ||
4 | * Modified from board-generic.c | ||
5 | * | ||
6 | * Original OMAP730 support by Jean Pihet <j-pihet@ti.com> | ||
7 | * Updated for 2.6 by Kevin Hilman <kjh@hilman.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/mtd/mtd.h> | ||
19 | #include <linux/mtd/partitions.h> | ||
20 | |||
21 | #include <asm/hardware.h> | ||
22 | #include <asm/mach-types.h> | ||
23 | #include <asm/mach/arch.h> | ||
24 | #include <asm/mach/flash.h> | ||
25 | #include <asm/mach/map.h> | ||
26 | |||
27 | #include <asm/arch/gpio.h> | ||
28 | #include <asm/arch/mux.h> | ||
29 | #include <asm/arch/fpga.h> | ||
30 | #include <asm/arch/common.h> | ||
31 | |||
32 | static struct resource smc91x_resources[] = { | ||
33 | [0] = { | ||
34 | .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ | ||
35 | .end = H2P2_DBG_FPGA_ETHR_START + 0xf, | ||
36 | .flags = IORESOURCE_MEM, | ||
37 | }, | ||
38 | [1] = { | ||
39 | .start = INT_730_MPU_EXT_NIRQ, | ||
40 | .end = 0, | ||
41 | .flags = IORESOURCE_IRQ, | ||
42 | }, | ||
43 | }; | ||
44 | |||
45 | static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0}; | ||
46 | |||
47 | static struct mtd_partition p2_partitions[] = { | ||
48 | /* bootloader (U-Boot, etc) in first sector */ | ||
49 | { | ||
50 | .name = "bootloader", | ||
51 | .offset = 0, | ||
52 | .size = SZ_128K, | ||
53 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
54 | }, | ||
55 | /* bootloader params in the next sector */ | ||
56 | { | ||
57 | .name = "params", | ||
58 | .offset = MTDPART_OFS_APPEND, | ||
59 | .size = SZ_128K, | ||
60 | .mask_flags = 0, | ||
61 | }, | ||
62 | /* kernel */ | ||
63 | { | ||
64 | .name = "kernel", | ||
65 | .offset = MTDPART_OFS_APPEND, | ||
66 | .size = SZ_2M, | ||
67 | .mask_flags = 0 | ||
68 | }, | ||
69 | /* rest of flash is a file system */ | ||
70 | { | ||
71 | .name = "rootfs", | ||
72 | .offset = MTDPART_OFS_APPEND, | ||
73 | .size = MTDPART_SIZ_FULL, | ||
74 | .mask_flags = 0 | ||
75 | }, | ||
76 | }; | ||
77 | |||
78 | static struct flash_platform_data p2_flash_data = { | ||
79 | .map_name = "cfi_probe", | ||
80 | .width = 2, | ||
81 | .parts = p2_partitions, | ||
82 | .nr_parts = ARRAY_SIZE(p2_partitions), | ||
83 | }; | ||
84 | |||
85 | static struct resource p2_flash_resource = { | ||
86 | .start = OMAP_FLASH_0_START, | ||
87 | .end = OMAP_FLASH_0_START + OMAP_FLASH_0_SIZE - 1, | ||
88 | .flags = IORESOURCE_MEM, | ||
89 | }; | ||
90 | |||
91 | static struct platform_device p2_flash_device = { | ||
92 | .name = "omapflash", | ||
93 | .id = 0, | ||
94 | .dev = { | ||
95 | .platform_data = &p2_flash_data, | ||
96 | }, | ||
97 | .num_resources = 1, | ||
98 | .resource = &p2_flash_resource, | ||
99 | }; | ||
100 | |||
101 | static struct platform_device smc91x_device = { | ||
102 | .name = "smc91x", | ||
103 | .id = 0, | ||
104 | .num_resources = ARRAY_SIZE(smc91x_resources), | ||
105 | .resource = smc91x_resources, | ||
106 | }; | ||
107 | |||
108 | static struct platform_device *devices[] __initdata = { | ||
109 | &p2_flash_device, | ||
110 | &smc91x_device, | ||
111 | }; | ||
112 | |||
113 | static void __init omap_perseus2_init(void) | ||
114 | { | ||
115 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
116 | } | ||
117 | |||
118 | static void __init perseus2_init_smc91x(void) | ||
119 | { | ||
120 | fpga_write(1, H2P2_DBG_FPGA_LAN_RESET); | ||
121 | mdelay(50); | ||
122 | fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1, | ||
123 | H2P2_DBG_FPGA_LAN_RESET); | ||
124 | mdelay(50); | ||
125 | } | ||
126 | |||
127 | void omap_perseus2_init_irq(void) | ||
128 | { | ||
129 | omap_init_irq(); | ||
130 | omap_gpio_init(); | ||
131 | perseus2_init_smc91x(); | ||
132 | } | ||
133 | |||
134 | /* Only FPGA needs to be mapped here. All others are done with ioremap */ | ||
135 | static struct map_desc omap_perseus2_io_desc[] __initdata = { | ||
136 | {H2P2_DBG_FPGA_BASE, H2P2_DBG_FPGA_START, H2P2_DBG_FPGA_SIZE, | ||
137 | MT_DEVICE}, | ||
138 | }; | ||
139 | |||
140 | static void __init omap_perseus2_map_io(void) | ||
141 | { | ||
142 | omap_map_common_io(); | ||
143 | iotable_init(omap_perseus2_io_desc, | ||
144 | ARRAY_SIZE(omap_perseus2_io_desc)); | ||
145 | |||
146 | /* Early, board-dependent init */ | ||
147 | |||
148 | /* | ||
149 | * Hold GSM Reset until needed | ||
150 | */ | ||
151 | omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL); | ||
152 | |||
153 | /* | ||
154 | * UARTs -> done automagically by 8250 driver | ||
155 | */ | ||
156 | |||
157 | /* | ||
158 | * CSx timings, GPIO Mux ... setup | ||
159 | */ | ||
160 | |||
161 | /* Flash: CS0 timings setup */ | ||
162 | omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0); | ||
163 | omap_writel(0x00000088, OMAP730_FLASH_ACFG_0); | ||
164 | |||
165 | /* | ||
166 | * Ethernet support trough the debug board | ||
167 | * CS1 timings setup | ||
168 | */ | ||
169 | omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1); | ||
170 | omap_writel(0x00000000, OMAP730_FLASH_ACFG_1); | ||
171 | |||
172 | /* | ||
173 | * Configure MPU_EXT_NIRQ IO in IO_CONF9 register, | ||
174 | * It is used as the Ethernet controller interrupt | ||
175 | */ | ||
176 | omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9); | ||
177 | omap_serial_init(p2_serial_ports); | ||
178 | } | ||
179 | |||
180 | MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") | ||
181 | /* Maintainer: Kevin Hilman <kjh@hilman.org> */ | ||
182 | .phys_ram = 0x10000000, | ||
183 | .phys_io = 0xfff00000, | ||
184 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
185 | .boot_params = 0x10000100, | ||
186 | .map_io = omap_perseus2_map_io, | ||
187 | .init_irq = omap_perseus2_init_irq, | ||
188 | .init_machine = omap_perseus2_init, | ||
189 | .timer = &omap_timer, | ||
190 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c new file mode 100644 index 000000000000..e42281988990 --- /dev/null +++ b/arch/arm/mach-omap1/board-voiceblue.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-voiceblue.c | ||
3 | * | ||
4 | * Modified from board-generic.c | ||
5 | * | ||
6 | * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz> | ||
7 | * | ||
8 | * Code for OMAP5910 based VoiceBlue board (VoIP to GSM gateway). | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/delay.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/notifier.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/serial_8250.h> | ||
23 | #include <linux/serial_reg.h> | ||
24 | |||
25 | #include <asm/hardware.h> | ||
26 | #include <asm/mach-types.h> | ||
27 | #include <asm/mach/arch.h> | ||
28 | #include <asm/mach/map.h> | ||
29 | |||
30 | #include <asm/arch/gpio.h> | ||
31 | #include <asm/arch/tc.h> | ||
32 | #include <asm/arch/mux.h> | ||
33 | #include <asm/arch/usb.h> | ||
34 | #include <asm/arch/common.h> | ||
35 | |||
36 | extern void omap_init_time(void); | ||
37 | extern int omap_gpio_init(void); | ||
38 | |||
39 | static struct plat_serial8250_port voiceblue_ports[] = { | ||
40 | { | ||
41 | .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x40000), | ||
42 | .irq = OMAP_GPIO_IRQ(12), | ||
43 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | ||
44 | .iotype = UPIO_MEM, | ||
45 | .regshift = 1, | ||
46 | .uartclk = 3686400, | ||
47 | }, | ||
48 | { | ||
49 | .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x50000), | ||
50 | .irq = OMAP_GPIO_IRQ(13), | ||
51 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | ||
52 | .iotype = UPIO_MEM, | ||
53 | .regshift = 1, | ||
54 | .uartclk = 3686400, | ||
55 | }, | ||
56 | { | ||
57 | .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x60000), | ||
58 | .irq = OMAP_GPIO_IRQ(14), | ||
59 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | ||
60 | .iotype = UPIO_MEM, | ||
61 | .regshift = 1, | ||
62 | .uartclk = 3686400, | ||
63 | }, | ||
64 | { | ||
65 | .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x70000), | ||
66 | .irq = OMAP_GPIO_IRQ(15), | ||
67 | .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, | ||
68 | .iotype = UPIO_MEM, | ||
69 | .regshift = 1, | ||
70 | .uartclk = 3686400, | ||
71 | }, | ||
72 | { }, | ||
73 | }; | ||
74 | |||
75 | static struct platform_device serial_device = { | ||
76 | .name = "serial8250", | ||
77 | .id = 1, | ||
78 | .dev = { | ||
79 | .platform_data = voiceblue_ports, | ||
80 | }, | ||
81 | }; | ||
82 | |||
83 | static int __init ext_uart_init(void) | ||
84 | { | ||
85 | return platform_device_register(&serial_device); | ||
86 | } | ||
87 | arch_initcall(ext_uart_init); | ||
88 | |||
89 | static struct resource voiceblue_smc91x_resources[] = { | ||
90 | [0] = { | ||
91 | .start = OMAP_CS2_PHYS + 0x300, | ||
92 | .end = OMAP_CS2_PHYS + 0x300 + 16, | ||
93 | .flags = IORESOURCE_MEM, | ||
94 | }, | ||
95 | [1] = { | ||
96 | .start = OMAP_GPIO_IRQ(8), | ||
97 | .end = OMAP_GPIO_IRQ(8), | ||
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | static struct platform_device voiceblue_smc91x_device = { | ||
103 | .name = "smc91x", | ||
104 | .id = 0, | ||
105 | .num_resources = ARRAY_SIZE(voiceblue_smc91x_resources), | ||
106 | .resource = voiceblue_smc91x_resources, | ||
107 | }; | ||
108 | |||
109 | static struct platform_device *voiceblue_devices[] __initdata = { | ||
110 | &voiceblue_smc91x_device, | ||
111 | }; | ||
112 | |||
113 | static struct omap_usb_config voiceblue_usb_config __initdata = { | ||
114 | .hmc_mode = 3, | ||
115 | .register_host = 1, | ||
116 | .register_dev = 1, | ||
117 | .pins[0] = 2, | ||
118 | .pins[1] = 6, | ||
119 | .pins[2] = 6, | ||
120 | }; | ||
121 | |||
122 | static struct omap_board_config_kernel voiceblue_config[] = { | ||
123 | { OMAP_TAG_USB, &voiceblue_usb_config }, | ||
124 | }; | ||
125 | |||
126 | static void __init voiceblue_init_irq(void) | ||
127 | { | ||
128 | omap_init_irq(); | ||
129 | omap_gpio_init(); | ||
130 | } | ||
131 | |||
132 | static void __init voiceblue_init(void) | ||
133 | { | ||
134 | /* There is a good chance board is going up, so enable Power LED | ||
135 | * (it is connected through invertor) */ | ||
136 | omap_writeb(0x00, OMAP_LPG1_LCR); | ||
137 | /* Watchdog */ | ||
138 | omap_request_gpio(0); | ||
139 | /* smc91x reset */ | ||
140 | omap_request_gpio(7); | ||
141 | omap_set_gpio_direction(7, 0); | ||
142 | omap_set_gpio_dataout(7, 1); | ||
143 | udelay(2); /* wait at least 100ns */ | ||
144 | omap_set_gpio_dataout(7, 0); | ||
145 | mdelay(50); /* 50ms until PHY ready */ | ||
146 | /* smc91x interrupt pin */ | ||
147 | omap_request_gpio(8); | ||
148 | omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE); | ||
149 | /* 16C554 reset*/ | ||
150 | omap_request_gpio(6); | ||
151 | omap_set_gpio_direction(6, 0); | ||
152 | omap_set_gpio_dataout(6, 0); | ||
153 | /* 16C554 interrupt pins */ | ||
154 | omap_request_gpio(12); | ||
155 | omap_request_gpio(13); | ||
156 | omap_request_gpio(14); | ||
157 | omap_request_gpio(15); | ||
158 | omap_set_gpio_edge_ctrl(12, OMAP_GPIO_RISING_EDGE); | ||
159 | omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE); | ||
160 | omap_set_gpio_edge_ctrl(14, OMAP_GPIO_RISING_EDGE); | ||
161 | omap_set_gpio_edge_ctrl(15, OMAP_GPIO_RISING_EDGE); | ||
162 | |||
163 | platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices)); | ||
164 | omap_board_config = voiceblue_config; | ||
165 | omap_board_config_size = ARRAY_SIZE(voiceblue_config); | ||
166 | } | ||
167 | |||
168 | static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | ||
169 | |||
170 | static void __init voiceblue_map_io(void) | ||
171 | { | ||
172 | omap_map_common_io(); | ||
173 | omap_serial_init(omap_serial_ports); | ||
174 | } | ||
175 | |||
176 | #define MACHINE_PANICED 1 | ||
177 | #define MACHINE_REBOOTING 2 | ||
178 | #define MACHINE_REBOOT 4 | ||
179 | static unsigned long machine_state; | ||
180 | |||
181 | static int panic_event(struct notifier_block *this, unsigned long event, | ||
182 | void *ptr) | ||
183 | { | ||
184 | if (test_and_set_bit(MACHINE_PANICED, &machine_state)) | ||
185 | return NOTIFY_DONE; | ||
186 | |||
187 | /* Flash Power LED | ||
188 | * (TODO: Enable clock right way (enabled in bootloader already)) */ | ||
189 | omap_writeb(0x78, OMAP_LPG1_LCR); | ||
190 | |||
191 | return NOTIFY_DONE; | ||
192 | } | ||
193 | |||
194 | static struct notifier_block panic_block = { | ||
195 | .notifier_call = panic_event, | ||
196 | }; | ||
197 | |||
198 | static int __init setup_notifier(void) | ||
199 | { | ||
200 | /* Setup panic notifier */ | ||
201 | notifier_chain_register(&panic_notifier_list, &panic_block); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | postcore_initcall(setup_notifier); | ||
207 | |||
208 | static int wdt_gpio_state; | ||
209 | |||
210 | void voiceblue_wdt_enable(void) | ||
211 | { | ||
212 | omap_set_gpio_direction(0, 0); | ||
213 | omap_set_gpio_dataout(0, 0); | ||
214 | omap_set_gpio_dataout(0, 1); | ||
215 | omap_set_gpio_dataout(0, 0); | ||
216 | wdt_gpio_state = 0; | ||
217 | } | ||
218 | |||
219 | void voiceblue_wdt_disable(void) | ||
220 | { | ||
221 | omap_set_gpio_dataout(0, 0); | ||
222 | omap_set_gpio_dataout(0, 1); | ||
223 | omap_set_gpio_dataout(0, 0); | ||
224 | omap_set_gpio_direction(0, 1); | ||
225 | } | ||
226 | |||
227 | void voiceblue_wdt_ping(void) | ||
228 | { | ||
229 | if (test_bit(MACHINE_REBOOT, &machine_state)) | ||
230 | return; | ||
231 | |||
232 | wdt_gpio_state = !wdt_gpio_state; | ||
233 | omap_set_gpio_dataout(0, wdt_gpio_state); | ||
234 | } | ||
235 | |||
236 | void voiceblue_reset(void) | ||
237 | { | ||
238 | set_bit(MACHINE_REBOOT, &machine_state); | ||
239 | voiceblue_wdt_enable(); | ||
240 | while (1) ; | ||
241 | } | ||
242 | |||
243 | EXPORT_SYMBOL(voiceblue_wdt_enable); | ||
244 | EXPORT_SYMBOL(voiceblue_wdt_disable); | ||
245 | EXPORT_SYMBOL(voiceblue_wdt_ping); | ||
246 | |||
247 | MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910") | ||
248 | /* Maintainer: Ladislav Michl <michl@2n.cz> */ | ||
249 | .phys_ram = 0x10000000, | ||
250 | .phys_io = 0xfff00000, | ||
251 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
252 | .boot_params = 0x10000100, | ||
253 | .map_io = voiceblue_map_io, | ||
254 | .init_irq = voiceblue_init_irq, | ||
255 | .init_machine = voiceblue_init, | ||
256 | .timer = &omap_timer, | ||
257 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c new file mode 100644 index 000000000000..7c08f6c2e1d0 --- /dev/null +++ b/arch/arm/mach-omap1/fpga.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/fpga.c | ||
3 | * | ||
4 | * Interrupt handler for OMAP-1510 Innovator FPGA | ||
5 | * | ||
6 | * Copyright (C) 2001 RidgeRun, Inc. | ||
7 | * Author: Greg Lonnon <glonnon@ridgerun.com> | ||
8 | * | ||
9 | * Copyright (C) 2002 MontaVista Software, Inc. | ||
10 | * | ||
11 | * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6 | ||
12 | * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/device.h> | ||
24 | #include <linux/errno.h> | ||
25 | |||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/mach/irq.h> | ||
30 | |||
31 | #include <asm/arch/fpga.h> | ||
32 | #include <asm/arch/gpio.h> | ||
33 | |||
34 | static void fpga_mask_irq(unsigned int irq) | ||
35 | { | ||
36 | irq -= OMAP1510_IH_FPGA_BASE; | ||
37 | |||
38 | if (irq < 8) | ||
39 | __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | ||
40 | & ~(1 << irq)), OMAP1510_FPGA_IMR_LO); | ||
41 | else if (irq < 16) | ||
42 | __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_HI) | ||
43 | & ~(1 << (irq - 8))), OMAP1510_FPGA_IMR_HI); | ||
44 | else | ||
45 | __raw_writeb((__raw_readb(INNOVATOR_FPGA_IMR2) | ||
46 | & ~(1 << (irq - 16))), INNOVATOR_FPGA_IMR2); | ||
47 | } | ||
48 | |||
49 | |||
50 | static inline u32 get_fpga_unmasked_irqs(void) | ||
51 | { | ||
52 | return | ||
53 | ((__raw_readb(OMAP1510_FPGA_ISR_LO) & | ||
54 | __raw_readb(OMAP1510_FPGA_IMR_LO))) | | ||
55 | ((__raw_readb(OMAP1510_FPGA_ISR_HI) & | ||
56 | __raw_readb(OMAP1510_FPGA_IMR_HI)) << 8) | | ||
57 | ((__raw_readb(INNOVATOR_FPGA_ISR2) & | ||
58 | __raw_readb(INNOVATOR_FPGA_IMR2)) << 16); | ||
59 | } | ||
60 | |||
61 | |||
62 | static void fpga_ack_irq(unsigned int irq) | ||
63 | { | ||
64 | /* Don't need to explicitly ACK FPGA interrupts */ | ||
65 | } | ||
66 | |||
67 | static void fpga_unmask_irq(unsigned int irq) | ||
68 | { | ||
69 | irq -= OMAP1510_IH_FPGA_BASE; | ||
70 | |||
71 | if (irq < 8) | ||
72 | __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | (1 << irq)), | ||
73 | OMAP1510_FPGA_IMR_LO); | ||
74 | else if (irq < 16) | ||
75 | __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_HI) | ||
76 | | (1 << (irq - 8))), OMAP1510_FPGA_IMR_HI); | ||
77 | else | ||
78 | __raw_writeb((__raw_readb(INNOVATOR_FPGA_IMR2) | ||
79 | | (1 << (irq - 16))), INNOVATOR_FPGA_IMR2); | ||
80 | } | ||
81 | |||
82 | static void fpga_mask_ack_irq(unsigned int irq) | ||
83 | { | ||
84 | fpga_mask_irq(irq); | ||
85 | fpga_ack_irq(irq); | ||
86 | } | ||
87 | |||
88 | void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc, | ||
89 | struct pt_regs *regs) | ||
90 | { | ||
91 | struct irqdesc *d; | ||
92 | u32 stat; | ||
93 | int fpga_irq; | ||
94 | |||
95 | stat = get_fpga_unmasked_irqs(); | ||
96 | |||
97 | if (!stat) | ||
98 | return; | ||
99 | |||
100 | for (fpga_irq = OMAP1510_IH_FPGA_BASE; | ||
101 | (fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat; | ||
102 | fpga_irq++, stat >>= 1) { | ||
103 | if (stat & 1) { | ||
104 | d = irq_desc + fpga_irq; | ||
105 | d->handle(fpga_irq, d, regs); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static struct irqchip omap_fpga_irq_ack = { | ||
111 | .ack = fpga_mask_ack_irq, | ||
112 | .mask = fpga_mask_irq, | ||
113 | .unmask = fpga_unmask_irq, | ||
114 | }; | ||
115 | |||
116 | |||
117 | static struct irqchip omap_fpga_irq = { | ||
118 | .ack = fpga_ack_irq, | ||
119 | .mask = fpga_mask_irq, | ||
120 | .unmask = fpga_unmask_irq, | ||
121 | }; | ||
122 | |||
123 | /* | ||
124 | * All of the FPGA interrupt request inputs except for the touchscreen are | ||
125 | * edge-sensitive; the touchscreen is level-sensitive. The edge-sensitive | ||
126 | * interrupts are acknowledged as a side-effect of reading the interrupt | ||
127 | * status register from the FPGA. The edge-sensitive interrupt inputs | ||
128 | * cause a problem with level interrupt requests, such as Ethernet. The | ||
129 | * problem occurs when a level interrupt request is asserted while its | ||
130 | * interrupt input is masked in the FPGA, which results in a missed | ||
131 | * interrupt. | ||
132 | * | ||
133 | * In an attempt to workaround the problem with missed interrupts, the | ||
134 | * mask_ack routine for all of the FPGA interrupts has been changed from | ||
135 | * fpga_mask_ack_irq() to fpga_ack_irq() so that the specific FPGA interrupt | ||
136 | * being serviced is left unmasked. We can do this because the FPGA cascade | ||
137 | * interrupt is installed with the SA_INTERRUPT flag, which leaves all | ||
138 | * interrupts masked at the CPU while an FPGA interrupt handler executes. | ||
139 | * | ||
140 | * Limited testing indicates that this workaround appears to be effective | ||
141 | * for the smc9194 Ethernet driver used on the Innovator. It should work | ||
142 | * on other FPGA interrupts as well, but any drivers that explicitly mask | ||
143 | * interrupts at the interrupt controller via disable_irq/enable_irq | ||
144 | * could pose a problem. | ||
145 | */ | ||
146 | void omap1510_fpga_init_irq(void) | ||
147 | { | ||
148 | int i; | ||
149 | |||
150 | __raw_writeb(0, OMAP1510_FPGA_IMR_LO); | ||
151 | __raw_writeb(0, OMAP1510_FPGA_IMR_HI); | ||
152 | __raw_writeb(0, INNOVATOR_FPGA_IMR2); | ||
153 | |||
154 | for (i = OMAP1510_IH_FPGA_BASE; i < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS); i++) { | ||
155 | |||
156 | if (i == OMAP1510_INT_FPGA_TS) { | ||
157 | /* | ||
158 | * The touchscreen interrupt is level-sensitive, so | ||
159 | * we'll use the regular mask_ack routine for it. | ||
160 | */ | ||
161 | set_irq_chip(i, &omap_fpga_irq_ack); | ||
162 | } | ||
163 | else { | ||
164 | /* | ||
165 | * All FPGA interrupts except the touchscreen are | ||
166 | * edge-sensitive, so we won't mask them. | ||
167 | */ | ||
168 | set_irq_chip(i, &omap_fpga_irq); | ||
169 | } | ||
170 | |||
171 | set_irq_handler(i, do_edge_IRQ); | ||
172 | set_irq_flags(i, IRQF_VALID); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * The FPGA interrupt line is connected to GPIO13. Claim this pin for | ||
177 | * the ARM. | ||
178 | * | ||
179 | * NOTE: For general GPIO/MPUIO access and interrupts, please see | ||
180 | * gpio.[ch] | ||
181 | */ | ||
182 | omap_request_gpio(13); | ||
183 | omap_set_gpio_direction(13, 1); | ||
184 | omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE); | ||
185 | set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux); | ||
186 | } | ||
187 | |||
188 | EXPORT_SYMBOL(omap1510_fpga_init_irq); | ||
diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c new file mode 100644 index 000000000000..986c3b7e09bb --- /dev/null +++ b/arch/arm/mach-omap1/id.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/id.c | ||
3 | * | ||
4 | * OMAP1 CPU identification code | ||
5 | * | ||
6 | * Copyright (C) 2004 Nokia Corporation | ||
7 | * Written by Tony Lindgren <tony@atomide.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <asm/io.h> | ||
20 | |||
21 | struct omap_id { | ||
22 | u16 jtag_id; /* Used to determine OMAP type */ | ||
23 | u8 die_rev; /* Processor revision */ | ||
24 | u32 omap_id; /* OMAP revision */ | ||
25 | u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */ | ||
26 | }; | ||
27 | |||
28 | /* Register values to detect the OMAP version */ | ||
29 | static struct omap_id omap_ids[] __initdata = { | ||
30 | { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, | ||
31 | { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, | ||
32 | { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, | ||
33 | { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000}, | ||
34 | { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000}, | ||
35 | { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00}, | ||
36 | { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00}, | ||
37 | { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, | ||
38 | { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, | ||
39 | { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000}, | ||
40 | { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00}, | ||
41 | { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00}, | ||
42 | { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300}, | ||
43 | { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300}, | ||
44 | { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300}, | ||
45 | { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000}, | ||
46 | { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000}, | ||
47 | { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000}, | ||
48 | }; | ||
49 | |||
50 | /* | ||
51 | * Get OMAP type from PROD_ID. | ||
52 | * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM. | ||
53 | * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense. | ||
54 | * Undocumented register in TEST BLOCK is used as fallback; This seems to | ||
55 | * work on 1510, 1610 & 1710. The official way hopefully will work in future | ||
56 | * processors. | ||
57 | */ | ||
58 | static u16 __init omap_get_jtag_id(void) | ||
59 | { | ||
60 | u32 prod_id, omap_id; | ||
61 | |||
62 | prod_id = omap_readl(OMAP_PRODUCTION_ID_1); | ||
63 | omap_id = omap_readl(OMAP32_ID_1); | ||
64 | |||
65 | /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */ | ||
66 | if (((prod_id >> 20) == 0) || (prod_id == omap_id)) | ||
67 | prod_id = 0; | ||
68 | else | ||
69 | prod_id &= 0xffff; | ||
70 | |||
71 | if (prod_id) | ||
72 | return prod_id; | ||
73 | |||
74 | /* Use OMAP32_ID_1 as fallback */ | ||
75 | prod_id = ((omap_id >> 12) & 0xffff); | ||
76 | |||
77 | return prod_id; | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Get OMAP revision from DIE_REV. | ||
82 | * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID. | ||
83 | * Undocumented register in the TEST BLOCK is used as fallback. | ||
84 | * REVISIT: This does not seem to work on 1510 | ||
85 | */ | ||
86 | static u8 __init omap_get_die_rev(void) | ||
87 | { | ||
88 | u32 die_rev; | ||
89 | |||
90 | die_rev = omap_readl(OMAP_DIE_ID_1); | ||
91 | |||
92 | /* Check for broken OMAP_DIE_ID on early 1710 */ | ||
93 | if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id()) | ||
94 | die_rev = 0; | ||
95 | |||
96 | die_rev = (die_rev >> 17) & 0xf; | ||
97 | if (die_rev) | ||
98 | return die_rev; | ||
99 | |||
100 | die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf; | ||
101 | |||
102 | return die_rev; | ||
103 | } | ||
104 | |||
105 | void __init omap_check_revision(void) | ||
106 | { | ||
107 | int i; | ||
108 | u16 jtag_id; | ||
109 | u8 die_rev; | ||
110 | u32 omap_id; | ||
111 | u8 cpu_type; | ||
112 | |||
113 | jtag_id = omap_get_jtag_id(); | ||
114 | die_rev = omap_get_die_rev(); | ||
115 | omap_id = omap_readl(OMAP32_ID_0); | ||
116 | |||
117 | #ifdef DEBUG | ||
118 | printk("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0)); | ||
119 | printk("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n", | ||
120 | omap_readl(OMAP_DIE_ID_1), | ||
121 | (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf); | ||
122 | printk("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0)); | ||
123 | printk("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n", | ||
124 | omap_readl(OMAP_PRODUCTION_ID_1), | ||
125 | omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff); | ||
126 | printk("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0)); | ||
127 | printk("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1)); | ||
128 | printk("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev); | ||
129 | #endif | ||
130 | |||
131 | system_serial_high = omap_readl(OMAP_DIE_ID_0); | ||
132 | system_serial_low = omap_readl(OMAP_DIE_ID_1); | ||
133 | |||
134 | /* First check only the major version in a safe way */ | ||
135 | for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { | ||
136 | if (jtag_id == (omap_ids[i].jtag_id)) { | ||
137 | system_rev = omap_ids[i].type; | ||
138 | break; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* Check if we can find the die revision */ | ||
143 | for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { | ||
144 | if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) { | ||
145 | system_rev = omap_ids[i].type; | ||
146 | break; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | /* Finally check also the omap_id */ | ||
151 | for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { | ||
152 | if (jtag_id == omap_ids[i].jtag_id | ||
153 | && die_rev == omap_ids[i].die_rev | ||
154 | && omap_id == omap_ids[i].omap_id) { | ||
155 | system_rev = omap_ids[i].type; | ||
156 | break; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */ | ||
161 | cpu_type = system_rev >> 24; | ||
162 | |||
163 | switch (cpu_type) { | ||
164 | case 0x07: | ||
165 | system_rev |= 0x07; | ||
166 | break; | ||
167 | case 0x15: | ||
168 | system_rev |= 0x15; | ||
169 | break; | ||
170 | case 0x16: | ||
171 | case 0x17: | ||
172 | system_rev |= 0x16; | ||
173 | break; | ||
174 | case 0x24: | ||
175 | system_rev |= 0x24; | ||
176 | break; | ||
177 | default: | ||
178 | printk("Unknown OMAP cpu type: 0x%02x\n", cpu_type); | ||
179 | } | ||
180 | |||
181 | printk("OMAP%04x", system_rev >> 16); | ||
182 | if ((system_rev >> 8) & 0xff) | ||
183 | printk("%x", (system_rev >> 8) & 0xff); | ||
184 | printk(" revision %i handled as %02xxx id: %08x%08x\n", | ||
185 | die_rev, system_rev & 0xff, system_serial_low, | ||
186 | system_serial_high); | ||
187 | } | ||
188 | |||
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c new file mode 100644 index 000000000000..207df0fe934d --- /dev/null +++ b/arch/arm/mach-omap1/io.c | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/io.c | ||
3 | * | ||
4 | * OMAP1 I/O mapping code | ||
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/config.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | |||
16 | #include <asm/mach/map.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/arch/tc.h> | ||
19 | |||
20 | extern int clk_init(void); | ||
21 | extern void omap_check_revision(void); | ||
22 | |||
23 | /* | ||
24 | * The machine specific code may provide the extra mapping besides the | ||
25 | * default mapping provided here. | ||
26 | */ | ||
27 | static struct map_desc omap_io_desc[] __initdata = { | ||
28 | { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE }, | ||
29 | }; | ||
30 | |||
31 | #ifdef CONFIG_ARCH_OMAP730 | ||
32 | static struct map_desc omap730_io_desc[] __initdata = { | ||
33 | { OMAP730_DSP_BASE, OMAP730_DSP_START, OMAP730_DSP_SIZE, MT_DEVICE }, | ||
34 | { OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE }, | ||
35 | { OMAP730_SRAM_BASE, OMAP730_SRAM_START, OMAP730_SRAM_SIZE, MT_DEVICE } | ||
36 | }; | ||
37 | #endif | ||
38 | |||
39 | #ifdef CONFIG_ARCH_OMAP1510 | ||
40 | static struct map_desc omap1510_io_desc[] __initdata = { | ||
41 | { OMAP1510_DSP_BASE, OMAP1510_DSP_START, OMAP1510_DSP_SIZE, MT_DEVICE }, | ||
42 | { OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE }, | ||
43 | { OMAP1510_SRAM_BASE, OMAP1510_SRAM_START, OMAP1510_SRAM_SIZE, MT_DEVICE } | ||
44 | }; | ||
45 | #endif | ||
46 | |||
47 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
48 | static struct map_desc omap1610_io_desc[] __initdata = { | ||
49 | { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE }, | ||
50 | { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE }, | ||
51 | { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE } | ||
52 | }; | ||
53 | |||
54 | static struct map_desc omap5912_io_desc[] __initdata = { | ||
55 | { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE }, | ||
56 | { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE }, | ||
57 | /* | ||
58 | * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page | ||
59 | * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped. | ||
60 | * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte | ||
61 | * can be used. | ||
62 | */ | ||
63 | { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE } | ||
64 | }; | ||
65 | #endif | ||
66 | |||
67 | static int initialized = 0; | ||
68 | |||
69 | static void __init _omap_map_io(void) | ||
70 | { | ||
71 | initialized = 1; | ||
72 | |||
73 | /* We have to initialize the IO space mapping before we can run | ||
74 | * cpu_is_omapxxx() macros. */ | ||
75 | iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc)); | ||
76 | omap_check_revision(); | ||
77 | |||
78 | #ifdef CONFIG_ARCH_OMAP730 | ||
79 | if (cpu_is_omap730()) { | ||
80 | iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc)); | ||
81 | } | ||
82 | #endif | ||
83 | #ifdef CONFIG_ARCH_OMAP1510 | ||
84 | if (cpu_is_omap1510()) { | ||
85 | iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc)); | ||
86 | } | ||
87 | #endif | ||
88 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
89 | if (cpu_is_omap1610() || cpu_is_omap1710()) { | ||
90 | iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc)); | ||
91 | } | ||
92 | if (cpu_is_omap5912()) { | ||
93 | iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc)); | ||
94 | } | ||
95 | #endif | ||
96 | |||
97 | /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort | ||
98 | * on a Posted Write in the TIPB Bridge". | ||
99 | */ | ||
100 | omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL); | ||
101 | omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL); | ||
102 | |||
103 | /* Must init clocks early to assure that timer interrupt works | ||
104 | */ | ||
105 | clk_init(); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * This should only get called from board specific init | ||
110 | */ | ||
111 | void omap_map_common_io(void) | ||
112 | { | ||
113 | if (!initialized) | ||
114 | _omap_map_io(); | ||
115 | } | ||
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c new file mode 100644 index 000000000000..a11b6d807352 --- /dev/null +++ b/arch/arm/mach-omap1/irq.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/irq.c | ||
3 | * | ||
4 | * Interrupt handler for all OMAP boards | ||
5 | * | ||
6 | * Copyright (C) 2004 Nokia Corporation | ||
7 | * Written by Tony Lindgren <tony@atomide.com> | ||
8 | * Major cleanups by Juha Yrjölä <juha.yrjola@nokia.com> | ||
9 | * | ||
10 | * Completely re-written to support various OMAP chips with bank specific | ||
11 | * interrupt handlers. | ||
12 | * | ||
13 | * Some snippets of the code taken from the older OMAP interrupt handler | ||
14 | * Copyright (C) 2001 RidgeRun, Inc. Greg Lonnon <glonnon@ridgerun.com> | ||
15 | * | ||
16 | * GPIO interrupt handler moved to gpio.c by Juha Yrjola | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or modify it | ||
19 | * under the terms of the GNU General Public License as published by the | ||
20 | * Free Software Foundation; either version 2 of the License, or (at your | ||
21 | * option) any later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
24 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
26 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
29 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
30 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * You should have received a copy of the GNU General Public License along | ||
35 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
36 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
37 | */ | ||
38 | |||
39 | #include <linux/config.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/module.h> | ||
42 | #include <linux/sched.h> | ||
43 | #include <linux/interrupt.h> | ||
44 | #include <linux/ptrace.h> | ||
45 | |||
46 | #include <asm/hardware.h> | ||
47 | #include <asm/irq.h> | ||
48 | #include <asm/mach/irq.h> | ||
49 | #include <asm/arch/gpio.h> | ||
50 | |||
51 | #include <asm/io.h> | ||
52 | |||
53 | #define IRQ_BANK(irq) ((irq) >> 5) | ||
54 | #define IRQ_BIT(irq) ((irq) & 0x1f) | ||
55 | |||
56 | struct omap_irq_bank { | ||
57 | unsigned long base_reg; | ||
58 | unsigned long trigger_map; | ||
59 | unsigned long wake_enable; | ||
60 | }; | ||
61 | |||
62 | static unsigned int irq_bank_count = 0; | ||
63 | static struct omap_irq_bank *irq_banks; | ||
64 | |||
65 | static inline unsigned int irq_bank_readl(int bank, int offset) | ||
66 | { | ||
67 | return omap_readl(irq_banks[bank].base_reg + offset); | ||
68 | } | ||
69 | |||
70 | static inline void irq_bank_writel(unsigned long value, int bank, int offset) | ||
71 | { | ||
72 | omap_writel(value, irq_banks[bank].base_reg + offset); | ||
73 | } | ||
74 | |||
75 | static void omap_ack_irq(unsigned int irq) | ||
76 | { | ||
77 | if (irq > 31) | ||
78 | omap_writel(0x1, OMAP_IH2_BASE + IRQ_CONTROL_REG_OFFSET); | ||
79 | |||
80 | omap_writel(0x1, OMAP_IH1_BASE + IRQ_CONTROL_REG_OFFSET); | ||
81 | } | ||
82 | |||
83 | static void omap_mask_irq(unsigned int irq) | ||
84 | { | ||
85 | int bank = IRQ_BANK(irq); | ||
86 | u32 l; | ||
87 | |||
88 | l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET); | ||
89 | l |= 1 << IRQ_BIT(irq); | ||
90 | omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET); | ||
91 | } | ||
92 | |||
93 | static void omap_unmask_irq(unsigned int irq) | ||
94 | { | ||
95 | int bank = IRQ_BANK(irq); | ||
96 | u32 l; | ||
97 | |||
98 | l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET); | ||
99 | l &= ~(1 << IRQ_BIT(irq)); | ||
100 | omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET); | ||
101 | } | ||
102 | |||
103 | static void omap_mask_ack_irq(unsigned int irq) | ||
104 | { | ||
105 | omap_mask_irq(irq); | ||
106 | omap_ack_irq(irq); | ||
107 | } | ||
108 | |||
109 | static int omap_wake_irq(unsigned int irq, unsigned int enable) | ||
110 | { | ||
111 | int bank = IRQ_BANK(irq); | ||
112 | |||
113 | if (enable) | ||
114 | irq_banks[bank].wake_enable |= IRQ_BIT(irq); | ||
115 | else | ||
116 | irq_banks[bank].wake_enable &= ~IRQ_BIT(irq); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | |||
122 | /* | ||
123 | * Allows tuning the IRQ type and priority | ||
124 | * | ||
125 | * NOTE: There is currently no OMAP fiq handler for Linux. Read the | ||
126 | * mailing list threads on FIQ handlers if you are planning to | ||
127 | * add a FIQ handler for OMAP. | ||
128 | */ | ||
129 | static void omap_irq_set_cfg(int irq, int fiq, int priority, int trigger) | ||
130 | { | ||
131 | signed int bank; | ||
132 | unsigned long val, offset; | ||
133 | |||
134 | bank = IRQ_BANK(irq); | ||
135 | /* FIQ is only available on bank 0 interrupts */ | ||
136 | fiq = bank ? 0 : (fiq & 0x1); | ||
137 | val = fiq | ((priority & 0x1f) << 2) | ((trigger & 0x1) << 1); | ||
138 | offset = IRQ_ILR0_REG_OFFSET + IRQ_BIT(irq) * 0x4; | ||
139 | irq_bank_writel(val, bank, offset); | ||
140 | } | ||
141 | |||
142 | #ifdef CONFIG_ARCH_OMAP730 | ||
143 | static struct omap_irq_bank omap730_irq_banks[] = { | ||
144 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f }, | ||
145 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 }, | ||
146 | { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 }, | ||
147 | }; | ||
148 | #endif | ||
149 | |||
150 | #ifdef CONFIG_ARCH_OMAP1510 | ||
151 | static struct omap_irq_bank omap1510_irq_banks[] = { | ||
152 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff }, | ||
153 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed }, | ||
154 | }; | ||
155 | #endif | ||
156 | |||
157 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
158 | |||
159 | static struct omap_irq_bank omap1610_irq_banks[] = { | ||
160 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f }, | ||
161 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd }, | ||
162 | { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xffffb7ff }, | ||
163 | { .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff }, | ||
164 | }; | ||
165 | #endif | ||
166 | |||
167 | static struct irqchip omap_irq_chip = { | ||
168 | .ack = omap_mask_ack_irq, | ||
169 | .mask = omap_mask_irq, | ||
170 | .unmask = omap_unmask_irq, | ||
171 | .wake = omap_wake_irq, | ||
172 | }; | ||
173 | |||
174 | void __init omap_init_irq(void) | ||
175 | { | ||
176 | int i, j; | ||
177 | |||
178 | #ifdef CONFIG_ARCH_OMAP730 | ||
179 | if (cpu_is_omap730()) { | ||
180 | irq_banks = omap730_irq_banks; | ||
181 | irq_bank_count = ARRAY_SIZE(omap730_irq_banks); | ||
182 | } | ||
183 | #endif | ||
184 | #ifdef CONFIG_ARCH_OMAP1510 | ||
185 | if (cpu_is_omap1510()) { | ||
186 | irq_banks = omap1510_irq_banks; | ||
187 | irq_bank_count = ARRAY_SIZE(omap1510_irq_banks); | ||
188 | } | ||
189 | #endif | ||
190 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
191 | if (cpu_is_omap16xx()) { | ||
192 | irq_banks = omap1610_irq_banks; | ||
193 | irq_bank_count = ARRAY_SIZE(omap1610_irq_banks); | ||
194 | } | ||
195 | #endif | ||
196 | printk("Total of %i interrupts in %i interrupt banks\n", | ||
197 | irq_bank_count * 32, irq_bank_count); | ||
198 | |||
199 | /* Mask and clear all interrupts */ | ||
200 | for (i = 0; i < irq_bank_count; i++) { | ||
201 | irq_bank_writel(~0x0, i, IRQ_MIR_REG_OFFSET); | ||
202 | irq_bank_writel(0x0, i, IRQ_ITR_REG_OFFSET); | ||
203 | } | ||
204 | |||
205 | /* Clear any pending interrupts */ | ||
206 | irq_bank_writel(0x03, 0, IRQ_CONTROL_REG_OFFSET); | ||
207 | irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET); | ||
208 | |||
209 | /* Enable interrupts in global mask */ | ||
210 | if (cpu_is_omap730()) { | ||
211 | irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET); | ||
212 | } | ||
213 | |||
214 | /* Install the interrupt handlers for each bank */ | ||
215 | for (i = 0; i < irq_bank_count; i++) { | ||
216 | for (j = i * 32; j < (i + 1) * 32; j++) { | ||
217 | int irq_trigger; | ||
218 | |||
219 | irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j); | ||
220 | omap_irq_set_cfg(j, 0, 0, irq_trigger); | ||
221 | |||
222 | set_irq_chip(j, &omap_irq_chip); | ||
223 | set_irq_handler(j, do_level_IRQ); | ||
224 | set_irq_flags(j, IRQF_VALID); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | /* Unmask level 2 handler */ | ||
229 | if (cpu_is_omap730()) { | ||
230 | omap_unmask_irq(INT_730_IH2_IRQ); | ||
231 | } else { | ||
232 | omap_unmask_irq(INT_IH2_IRQ); | ||
233 | } | ||
234 | } | ||
diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c new file mode 100644 index 000000000000..6e98290cca5c --- /dev/null +++ b/arch/arm/mach-omap1/leds-h2p2-debug.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/leds-h2p2-debug.c | ||
3 | * | ||
4 | * Copyright 2003 by Texas Instruments Incorporated | ||
5 | * | ||
6 | * There are 16 LEDs on the debug board (all green); four may be used | ||
7 | * for logical 'green', 'amber', 'red', and 'blue' (after "claiming"). | ||
8 | * | ||
9 | * The "surfer" expansion board and H2 sample board also have two-color | ||
10 | * green+red LEDs (in parallel), used here for timer and idle indicators. | ||
11 | */ | ||
12 | #include <linux/config.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel_stat.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/version.h> | ||
17 | |||
18 | #include <asm/io.h> | ||
19 | #include <asm/hardware.h> | ||
20 | #include <asm/leds.h> | ||
21 | #include <asm/system.h> | ||
22 | |||
23 | #include <asm/arch/fpga.h> | ||
24 | #include <asm/arch/gpio.h> | ||
25 | |||
26 | #include "leds.h" | ||
27 | |||
28 | |||
29 | #define GPIO_LED_RED 3 | ||
30 | #define GPIO_LED_GREEN OMAP_MPUIO(4) | ||
31 | |||
32 | |||
33 | #define LED_STATE_ENABLED 0x01 | ||
34 | #define LED_STATE_CLAIMED 0x02 | ||
35 | #define LED_TIMER_ON 0x04 | ||
36 | |||
37 | #define GPIO_IDLE GPIO_LED_GREEN | ||
38 | #define GPIO_TIMER GPIO_LED_RED | ||
39 | |||
40 | |||
41 | void h2p2_dbg_leds_event(led_event_t evt) | ||
42 | { | ||
43 | unsigned long flags; | ||
44 | |||
45 | static struct h2p2_dbg_fpga __iomem *fpga; | ||
46 | static u16 led_state, hw_led_state; | ||
47 | |||
48 | local_irq_save(flags); | ||
49 | |||
50 | if (!(led_state & LED_STATE_ENABLED) && evt != led_start) | ||
51 | goto done; | ||
52 | |||
53 | switch (evt) { | ||
54 | case led_start: | ||
55 | if (!fpga) | ||
56 | fpga = ioremap(H2P2_DBG_FPGA_START, | ||
57 | H2P2_DBG_FPGA_SIZE); | ||
58 | if (fpga) { | ||
59 | led_state |= LED_STATE_ENABLED; | ||
60 | __raw_writew(~0, &fpga->leds); | ||
61 | } | ||
62 | break; | ||
63 | |||
64 | case led_stop: | ||
65 | case led_halted: | ||
66 | /* all leds off during suspend or shutdown */ | ||
67 | omap_set_gpio_dataout(GPIO_TIMER, 0); | ||
68 | omap_set_gpio_dataout(GPIO_IDLE, 0); | ||
69 | __raw_writew(~0, &fpga->leds); | ||
70 | led_state &= ~LED_STATE_ENABLED; | ||
71 | if (evt == led_halted) { | ||
72 | iounmap(fpga); | ||
73 | fpga = NULL; | ||
74 | } | ||
75 | goto done; | ||
76 | |||
77 | case led_claim: | ||
78 | led_state |= LED_STATE_CLAIMED; | ||
79 | hw_led_state = 0; | ||
80 | break; | ||
81 | |||
82 | case led_release: | ||
83 | led_state &= ~LED_STATE_CLAIMED; | ||
84 | break; | ||
85 | |||
86 | #ifdef CONFIG_LEDS_TIMER | ||
87 | case led_timer: | ||
88 | led_state ^= LED_TIMER_ON; | ||
89 | omap_set_gpio_dataout(GPIO_TIMER, led_state & LED_TIMER_ON); | ||
90 | goto done; | ||
91 | #endif | ||
92 | |||
93 | #ifdef CONFIG_LEDS_CPU | ||
94 | case led_idle_start: | ||
95 | omap_set_gpio_dataout(GPIO_IDLE, 1); | ||
96 | goto done; | ||
97 | |||
98 | case led_idle_end: | ||
99 | omap_set_gpio_dataout(GPIO_IDLE, 0); | ||
100 | goto done; | ||
101 | #endif | ||
102 | |||
103 | case led_green_on: | ||
104 | hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; | ||
105 | break; | ||
106 | case led_green_off: | ||
107 | hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; | ||
108 | break; | ||
109 | |||
110 | case led_amber_on: | ||
111 | hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; | ||
112 | break; | ||
113 | case led_amber_off: | ||
114 | hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; | ||
115 | break; | ||
116 | |||
117 | case led_red_on: | ||
118 | hw_led_state |= H2P2_DBG_FPGA_LED_RED; | ||
119 | break; | ||
120 | case led_red_off: | ||
121 | hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; | ||
122 | break; | ||
123 | |||
124 | case led_blue_on: | ||
125 | hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; | ||
126 | break; | ||
127 | case led_blue_off: | ||
128 | hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; | ||
129 | break; | ||
130 | |||
131 | default: | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | |||
136 | /* | ||
137 | * Actually burn the LEDs | ||
138 | */ | ||
139 | if (led_state & LED_STATE_CLAIMED) | ||
140 | __raw_writew(~hw_led_state, &fpga->leds); | ||
141 | |||
142 | done: | ||
143 | local_irq_restore(flags); | ||
144 | } | ||
diff --git a/arch/arm/mach-omap1/leds-innovator.c b/arch/arm/mach-omap1/leds-innovator.c new file mode 100644 index 000000000000..8043b7d0f66e --- /dev/null +++ b/arch/arm/mach-omap1/leds-innovator.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/leds-innovator.c | ||
3 | */ | ||
4 | #include <linux/config.h> | ||
5 | #include <linux/init.h> | ||
6 | |||
7 | #include <asm/hardware.h> | ||
8 | #include <asm/leds.h> | ||
9 | #include <asm/system.h> | ||
10 | |||
11 | #include "leds.h" | ||
12 | |||
13 | |||
14 | #define LED_STATE_ENABLED 1 | ||
15 | #define LED_STATE_CLAIMED 2 | ||
16 | |||
17 | static unsigned int led_state; | ||
18 | static unsigned int hw_led_state; | ||
19 | |||
20 | void innovator_leds_event(led_event_t evt) | ||
21 | { | ||
22 | unsigned long flags; | ||
23 | |||
24 | local_irq_save(flags); | ||
25 | |||
26 | switch (evt) { | ||
27 | case led_start: | ||
28 | hw_led_state = 0; | ||
29 | led_state = LED_STATE_ENABLED; | ||
30 | break; | ||
31 | |||
32 | case led_stop: | ||
33 | led_state &= ~LED_STATE_ENABLED; | ||
34 | hw_led_state = 0; | ||
35 | break; | ||
36 | |||
37 | case led_claim: | ||
38 | led_state |= LED_STATE_CLAIMED; | ||
39 | hw_led_state = 0; | ||
40 | break; | ||
41 | |||
42 | case led_release: | ||
43 | led_state &= ~LED_STATE_CLAIMED; | ||
44 | hw_led_state = 0; | ||
45 | break; | ||
46 | |||
47 | #ifdef CONFIG_LEDS_TIMER | ||
48 | case led_timer: | ||
49 | if (!(led_state & LED_STATE_CLAIMED)) | ||
50 | hw_led_state ^= 0; | ||
51 | break; | ||
52 | #endif | ||
53 | |||
54 | #ifdef CONFIG_LEDS_CPU | ||
55 | case led_idle_start: | ||
56 | if (!(led_state & LED_STATE_CLAIMED)) | ||
57 | hw_led_state |= 0; | ||
58 | break; | ||
59 | |||
60 | case led_idle_end: | ||
61 | if (!(led_state & LED_STATE_CLAIMED)) | ||
62 | hw_led_state &= ~0; | ||
63 | break; | ||
64 | #endif | ||
65 | |||
66 | case led_halted: | ||
67 | break; | ||
68 | |||
69 | case led_green_on: | ||
70 | if (led_state & LED_STATE_CLAIMED) | ||
71 | hw_led_state &= ~0; | ||
72 | break; | ||
73 | |||
74 | case led_green_off: | ||
75 | if (led_state & LED_STATE_CLAIMED) | ||
76 | hw_led_state |= 0; | ||
77 | break; | ||
78 | |||
79 | case led_amber_on: | ||
80 | break; | ||
81 | |||
82 | case led_amber_off: | ||
83 | break; | ||
84 | |||
85 | case led_red_on: | ||
86 | if (led_state & LED_STATE_CLAIMED) | ||
87 | hw_led_state &= ~0; | ||
88 | break; | ||
89 | |||
90 | case led_red_off: | ||
91 | if (led_state & LED_STATE_CLAIMED) | ||
92 | hw_led_state |= 0; | ||
93 | break; | ||
94 | |||
95 | default: | ||
96 | break; | ||
97 | } | ||
98 | |||
99 | if (led_state & LED_STATE_ENABLED) | ||
100 | ; | ||
101 | |||
102 | local_irq_restore(flags); | ||
103 | } | ||
diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c new file mode 100644 index 000000000000..4a0e8b9d4fc3 --- /dev/null +++ b/arch/arm/mach-omap1/leds-osk.c | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/leds-osk.c | ||
3 | * | ||
4 | * LED driver for OSK, and optionally Mistral QVGA, boards | ||
5 | */ | ||
6 | #include <linux/config.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/workqueue.h> | ||
9 | |||
10 | #include <asm/hardware.h> | ||
11 | #include <asm/leds.h> | ||
12 | #include <asm/system.h> | ||
13 | |||
14 | #include <asm/arch/gpio.h> | ||
15 | #include <asm/arch/tps65010.h> | ||
16 | |||
17 | #include "leds.h" | ||
18 | |||
19 | |||
20 | #define LED_STATE_ENABLED (1 << 0) | ||
21 | #define LED_STATE_CLAIMED (1 << 1) | ||
22 | static u8 led_state; | ||
23 | |||
24 | #define GREEN_LED (1 << 0) /* TPS65010 LED1 */ | ||
25 | #define AMBER_LED (1 << 1) /* TPS65010 LED2 */ | ||
26 | #define RED_LED (1 << 2) /* TPS65010 GPIO2 */ | ||
27 | #define TIMER_LED (1 << 3) /* Mistral board */ | ||
28 | #define IDLE_LED (1 << 4) /* Mistral board */ | ||
29 | static u8 hw_led_state; | ||
30 | |||
31 | |||
32 | /* TPS65010 leds are changed using i2c -- from a task context. | ||
33 | * Using one of these for the "idle" LED would be impractical... | ||
34 | */ | ||
35 | #define TPS_LEDS (GREEN_LED | RED_LED | AMBER_LED) | ||
36 | |||
37 | static u8 tps_leds_change; | ||
38 | |||
39 | static void tps_work(void *unused) | ||
40 | { | ||
41 | for (;;) { | ||
42 | u8 leds; | ||
43 | |||
44 | local_irq_disable(); | ||
45 | leds = tps_leds_change; | ||
46 | tps_leds_change = 0; | ||
47 | local_irq_enable(); | ||
48 | |||
49 | if (!leds) | ||
50 | break; | ||
51 | |||
52 | /* careful: the set_led() value is on/off/blink */ | ||
53 | if (leds & GREEN_LED) | ||
54 | tps65010_set_led(LED1, !!(hw_led_state & GREEN_LED)); | ||
55 | if (leds & AMBER_LED) | ||
56 | tps65010_set_led(LED2, !!(hw_led_state & AMBER_LED)); | ||
57 | |||
58 | /* the gpio led doesn't have that issue */ | ||
59 | if (leds & RED_LED) | ||
60 | tps65010_set_gpio_out_value(GPIO2, | ||
61 | !(hw_led_state & RED_LED)); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | static DECLARE_WORK(work, tps_work, NULL); | ||
66 | |||
67 | #ifdef CONFIG_FB_OMAP | ||
68 | |||
69 | /* For now, all system indicators require the Mistral board, since that | ||
70 | * LED can be manipulated without a task context. This LED is either red, | ||
71 | * or green, but not both; it can't give the full "disco led" effect. | ||
72 | */ | ||
73 | |||
74 | #define GPIO_LED_RED 3 | ||
75 | #define GPIO_LED_GREEN OMAP_MPUIO(4) | ||
76 | |||
77 | static void mistral_setled(void) | ||
78 | { | ||
79 | int red = 0; | ||
80 | int green = 0; | ||
81 | |||
82 | if (hw_led_state & TIMER_LED) | ||
83 | red = 1; | ||
84 | else if (hw_led_state & IDLE_LED) | ||
85 | green = 1; | ||
86 | // else both sides are disabled | ||
87 | |||
88 | omap_set_gpio_dataout(GPIO_LED_GREEN, green); | ||
89 | omap_set_gpio_dataout(GPIO_LED_RED, red); | ||
90 | } | ||
91 | |||
92 | #endif | ||
93 | |||
94 | void osk_leds_event(led_event_t evt) | ||
95 | { | ||
96 | unsigned long flags; | ||
97 | u16 leds; | ||
98 | |||
99 | local_irq_save(flags); | ||
100 | |||
101 | if (!(led_state & LED_STATE_ENABLED) && evt != led_start) | ||
102 | goto done; | ||
103 | |||
104 | leds = hw_led_state; | ||
105 | switch (evt) { | ||
106 | case led_start: | ||
107 | led_state |= LED_STATE_ENABLED; | ||
108 | hw_led_state = 0; | ||
109 | leds = ~0; | ||
110 | break; | ||
111 | |||
112 | case led_halted: | ||
113 | case led_stop: | ||
114 | led_state &= ~LED_STATE_ENABLED; | ||
115 | hw_led_state = 0; | ||
116 | // NOTE: work may still be pending!! | ||
117 | break; | ||
118 | |||
119 | case led_claim: | ||
120 | led_state |= LED_STATE_CLAIMED; | ||
121 | hw_led_state = 0; | ||
122 | leds = ~0; | ||
123 | break; | ||
124 | |||
125 | case led_release: | ||
126 | led_state &= ~LED_STATE_CLAIMED; | ||
127 | hw_led_state = 0; | ||
128 | break; | ||
129 | |||
130 | #ifdef CONFIG_FB_OMAP | ||
131 | |||
132 | case led_timer: | ||
133 | hw_led_state ^= TIMER_LED; | ||
134 | mistral_setled(); | ||
135 | break; | ||
136 | |||
137 | case led_idle_start: | ||
138 | hw_led_state |= IDLE_LED; | ||
139 | mistral_setled(); | ||
140 | break; | ||
141 | |||
142 | case led_idle_end: | ||
143 | hw_led_state &= ~IDLE_LED; | ||
144 | mistral_setled(); | ||
145 | break; | ||
146 | |||
147 | #endif /* CONFIG_FB_OMAP */ | ||
148 | |||
149 | /* "green" == tps LED1 (leftmost, normally power-good) | ||
150 | * works only with DC adapter, not on battery power! | ||
151 | */ | ||
152 | case led_green_on: | ||
153 | if (led_state & LED_STATE_CLAIMED) | ||
154 | hw_led_state |= GREEN_LED; | ||
155 | break; | ||
156 | case led_green_off: | ||
157 | if (led_state & LED_STATE_CLAIMED) | ||
158 | hw_led_state &= ~GREEN_LED; | ||
159 | break; | ||
160 | |||
161 | /* "amber" == tps LED2 (middle) */ | ||
162 | case led_amber_on: | ||
163 | if (led_state & LED_STATE_CLAIMED) | ||
164 | hw_led_state |= AMBER_LED; | ||
165 | break; | ||
166 | case led_amber_off: | ||
167 | if (led_state & LED_STATE_CLAIMED) | ||
168 | hw_led_state &= ~AMBER_LED; | ||
169 | break; | ||
170 | |||
171 | /* "red" == LED on tps gpio3 (rightmost) */ | ||
172 | case led_red_on: | ||
173 | if (led_state & LED_STATE_CLAIMED) | ||
174 | hw_led_state |= RED_LED; | ||
175 | break; | ||
176 | case led_red_off: | ||
177 | if (led_state & LED_STATE_CLAIMED) | ||
178 | hw_led_state &= ~RED_LED; | ||
179 | break; | ||
180 | |||
181 | default: | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | leds ^= hw_led_state; | ||
186 | leds &= TPS_LEDS; | ||
187 | if (leds && (led_state & LED_STATE_CLAIMED)) { | ||
188 | tps_leds_change |= leds; | ||
189 | schedule_work(&work); | ||
190 | } | ||
191 | |||
192 | done: | ||
193 | local_irq_restore(flags); | ||
194 | } | ||
diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c new file mode 100644 index 000000000000..8ab21fe98e1b --- /dev/null +++ b/arch/arm/mach-omap1/leds.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/leds.c | ||
3 | * | ||
4 | * OMAP LEDs dispatcher | ||
5 | */ | ||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/init.h> | ||
8 | |||
9 | #include <asm/leds.h> | ||
10 | #include <asm/mach-types.h> | ||
11 | |||
12 | #include <asm/arch/gpio.h> | ||
13 | #include <asm/arch/mux.h> | ||
14 | |||
15 | #include "leds.h" | ||
16 | |||
17 | static int __init | ||
18 | omap_leds_init(void) | ||
19 | { | ||
20 | if (machine_is_omap_innovator()) | ||
21 | leds_event = innovator_leds_event; | ||
22 | |||
23 | else if (machine_is_omap_h2() || machine_is_omap_perseus2()) | ||
24 | leds_event = h2p2_dbg_leds_event; | ||
25 | |||
26 | else if (machine_is_omap_osk()) | ||
27 | leds_event = osk_leds_event; | ||
28 | |||
29 | else | ||
30 | return -1; | ||
31 | |||
32 | if (machine_is_omap_h2() | ||
33 | || machine_is_omap_perseus2() | ||
34 | || machine_is_omap_osk()) { | ||
35 | |||
36 | /* LED1/LED2 pins can be used as GPIO (as done here), or by | ||
37 | * the LPG (works even in deep sleep!), to drive a bicolor | ||
38 | * LED on the H2 sample board, and another on the H2/P2 | ||
39 | * "surfer" expansion board. | ||
40 | * | ||
41 | * The same pins drive a LED on the OSK Mistral board, but | ||
42 | * that's a different kind of LED (just one color at a time). | ||
43 | */ | ||
44 | omap_cfg_reg(P18_1610_GPIO3); | ||
45 | if (omap_request_gpio(3) == 0) | ||
46 | omap_set_gpio_direction(3, 0); | ||
47 | else | ||
48 | printk(KERN_WARNING "LED: can't get GPIO3/red?\n"); | ||
49 | |||
50 | omap_cfg_reg(MPUIO4); | ||
51 | if (omap_request_gpio(OMAP_MPUIO(4)) == 0) | ||
52 | omap_set_gpio_direction(OMAP_MPUIO(4), 0); | ||
53 | else | ||
54 | printk(KERN_WARNING "LED: can't get MPUIO4/green?\n"); | ||
55 | } | ||
56 | |||
57 | leds_event(led_start); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | __initcall(omap_leds_init); | ||
diff --git a/arch/arm/mach-omap1/leds.h b/arch/arm/mach-omap1/leds.h new file mode 100644 index 000000000000..a1e9fedc376c --- /dev/null +++ b/arch/arm/mach-omap1/leds.h | |||
@@ -0,0 +1,3 @@ | |||
1 | extern void innovator_leds_event(led_event_t evt); | ||
2 | extern void h2p2_dbg_leds_event(led_event_t evt); | ||
3 | extern void osk_leds_event(led_event_t evt); | ||
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c new file mode 100644 index 000000000000..214e5d17c8b5 --- /dev/null +++ b/arch/arm/mach-omap1/serial.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/id.c | ||
3 | * | ||
4 | * OMAP1 CPU identification code | ||
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/config.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/serial.h> | ||
17 | #include <linux/tty.h> | ||
18 | #include <linux/serial_8250.h> | ||
19 | #include <linux/serial_reg.h> | ||
20 | |||
21 | #include <asm/io.h> | ||
22 | #include <asm/mach-types.h> | ||
23 | #include <asm/hardware/clock.h> | ||
24 | |||
25 | #include <asm/arch/board.h> | ||
26 | #include <asm/arch/mux.h> | ||
27 | #include <asm/arch/fpga.h> | ||
28 | |||
29 | static struct clk * uart1_ck = NULL; | ||
30 | static struct clk * uart2_ck = NULL; | ||
31 | static struct clk * uart3_ck = NULL; | ||
32 | |||
33 | static inline unsigned int omap_serial_in(struct plat_serial8250_port *up, | ||
34 | int offset) | ||
35 | { | ||
36 | offset <<= up->regshift; | ||
37 | return (unsigned int)__raw_readb(up->membase + offset); | ||
38 | } | ||
39 | |||
40 | static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset, | ||
41 | int value) | ||
42 | { | ||
43 | offset <<= p->regshift; | ||
44 | __raw_writeb(value, p->membase + offset); | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * Internal UARTs need to be initialized for the 8250 autoconfig to work | ||
49 | * properly. Note that the TX watermark initialization may not be needed | ||
50 | * once the 8250.c watermark handling code is merged. | ||
51 | */ | ||
52 | static void __init omap_serial_reset(struct plat_serial8250_port *p) | ||
53 | { | ||
54 | omap_serial_outp(p, UART_OMAP_MDR1, 0x07); /* disable UART */ | ||
55 | omap_serial_outp(p, UART_OMAP_SCR, 0x08); /* TX watermark */ | ||
56 | omap_serial_outp(p, UART_OMAP_MDR1, 0x00); /* enable UART */ | ||
57 | |||
58 | if (!cpu_is_omap1510()) { | ||
59 | omap_serial_outp(p, UART_OMAP_SYSC, 0x01); | ||
60 | while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01)); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static struct plat_serial8250_port serial_platform_data[] = { | ||
65 | { | ||
66 | .membase = (char*)IO_ADDRESS(OMAP_UART1_BASE), | ||
67 | .mapbase = (unsigned long)OMAP_UART1_BASE, | ||
68 | .irq = INT_UART1, | ||
69 | .flags = UPF_BOOT_AUTOCONF, | ||
70 | .iotype = UPIO_MEM, | ||
71 | .regshift = 2, | ||
72 | .uartclk = OMAP16XX_BASE_BAUD * 16, | ||
73 | }, | ||
74 | { | ||
75 | .membase = (char*)IO_ADDRESS(OMAP_UART2_BASE), | ||
76 | .mapbase = (unsigned long)OMAP_UART2_BASE, | ||
77 | .irq = INT_UART2, | ||
78 | .flags = UPF_BOOT_AUTOCONF, | ||
79 | .iotype = UPIO_MEM, | ||
80 | .regshift = 2, | ||
81 | .uartclk = OMAP16XX_BASE_BAUD * 16, | ||
82 | }, | ||
83 | { | ||
84 | .membase = (char*)IO_ADDRESS(OMAP_UART3_BASE), | ||
85 | .mapbase = (unsigned long)OMAP_UART3_BASE, | ||
86 | .irq = INT_UART3, | ||
87 | .flags = UPF_BOOT_AUTOCONF, | ||
88 | .iotype = UPIO_MEM, | ||
89 | .regshift = 2, | ||
90 | .uartclk = OMAP16XX_BASE_BAUD * 16, | ||
91 | }, | ||
92 | { }, | ||
93 | }; | ||
94 | |||
95 | static struct platform_device serial_device = { | ||
96 | .name = "serial8250", | ||
97 | .id = 0, | ||
98 | .dev = { | ||
99 | .platform_data = serial_platform_data, | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | /* | ||
104 | * Note that on Innovator-1510 UART2 pins conflict with USB2. | ||
105 | * By default UART2 does not work on Innovator-1510 if you have | ||
106 | * USB OHCI enabled. To use UART2, you must disable USB2 first. | ||
107 | */ | ||
108 | void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS]) | ||
109 | { | ||
110 | int i; | ||
111 | |||
112 | if (cpu_is_omap730()) { | ||
113 | serial_platform_data[0].regshift = 0; | ||
114 | serial_platform_data[1].regshift = 0; | ||
115 | serial_platform_data[0].irq = INT_730_UART_MODEM_1; | ||
116 | serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2; | ||
117 | } | ||
118 | |||
119 | if (cpu_is_omap1510()) { | ||
120 | serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16; | ||
121 | serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16; | ||
122 | serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16; | ||
123 | } | ||
124 | |||
125 | for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { | ||
126 | unsigned char reg; | ||
127 | |||
128 | if (ports[i] == 0) { | ||
129 | serial_platform_data[i].membase = NULL; | ||
130 | serial_platform_data[i].mapbase = 0; | ||
131 | continue; | ||
132 | } | ||
133 | |||
134 | switch (i) { | ||
135 | case 0: | ||
136 | uart1_ck = clk_get(NULL, "uart1_ck"); | ||
137 | if (IS_ERR(uart1_ck)) | ||
138 | printk("Could not get uart1_ck\n"); | ||
139 | else { | ||
140 | clk_use(uart1_ck); | ||
141 | if (cpu_is_omap1510()) | ||
142 | clk_set_rate(uart1_ck, 12000000); | ||
143 | } | ||
144 | if (cpu_is_omap1510()) { | ||
145 | omap_cfg_reg(UART1_TX); | ||
146 | omap_cfg_reg(UART1_RTS); | ||
147 | if (machine_is_omap_innovator()) { | ||
148 | reg = fpga_read(OMAP1510_FPGA_POWER); | ||
149 | reg |= OMAP1510_FPGA_PCR_COM1_EN; | ||
150 | fpga_write(reg, OMAP1510_FPGA_POWER); | ||
151 | udelay(10); | ||
152 | } | ||
153 | } | ||
154 | break; | ||
155 | case 1: | ||
156 | uart2_ck = clk_get(NULL, "uart2_ck"); | ||
157 | if (IS_ERR(uart2_ck)) | ||
158 | printk("Could not get uart2_ck\n"); | ||
159 | else { | ||
160 | clk_use(uart2_ck); | ||
161 | if (cpu_is_omap1510()) | ||
162 | clk_set_rate(uart2_ck, 12000000); | ||
163 | else | ||
164 | clk_set_rate(uart2_ck, 48000000); | ||
165 | } | ||
166 | if (cpu_is_omap1510()) { | ||
167 | omap_cfg_reg(UART2_TX); | ||
168 | omap_cfg_reg(UART2_RTS); | ||
169 | if (machine_is_omap_innovator()) { | ||
170 | reg = fpga_read(OMAP1510_FPGA_POWER); | ||
171 | reg |= OMAP1510_FPGA_PCR_COM2_EN; | ||
172 | fpga_write(reg, OMAP1510_FPGA_POWER); | ||
173 | udelay(10); | ||
174 | } | ||
175 | } | ||
176 | break; | ||
177 | case 2: | ||
178 | uart3_ck = clk_get(NULL, "uart3_ck"); | ||
179 | if (IS_ERR(uart3_ck)) | ||
180 | printk("Could not get uart3_ck\n"); | ||
181 | else { | ||
182 | clk_use(uart3_ck); | ||
183 | if (cpu_is_omap1510()) | ||
184 | clk_set_rate(uart3_ck, 12000000); | ||
185 | } | ||
186 | if (cpu_is_omap1510()) { | ||
187 | omap_cfg_reg(UART3_TX); | ||
188 | omap_cfg_reg(UART3_RX); | ||
189 | } | ||
190 | break; | ||
191 | } | ||
192 | omap_serial_reset(&serial_platform_data[i]); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static int __init omap_init(void) | ||
197 | { | ||
198 | return platform_device_register(&serial_device); | ||
199 | } | ||
200 | arch_initcall(omap_init); | ||
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c new file mode 100644 index 000000000000..d540539c9bbb --- /dev/null +++ b/arch/arm/mach-omap1/time.c | |||
@@ -0,0 +1,436 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/time.c | ||
3 | * | ||
4 | * OMAP Timers | ||
5 | * | ||
6 | * Copyright (C) 2004 Nokia Corporation | ||
7 | * Partial timer rewrite and additional dynamic tick timer support by | ||
8 | * Tony Lindgen <tony@atomide.com> and | ||
9 | * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
10 | * | ||
11 | * MPU timer code based on the older MPU timer code for OMAP | ||
12 | * Copyright (C) 2000 RidgeRun, Inc. | ||
13 | * Author: Greg Lonnon <glonnon@ridgerun.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2 of the License, or (at your | ||
18 | * option) any later version. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
23 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
26 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
29 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License along | ||
32 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
33 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
34 | */ | ||
35 | |||
36 | #include <linux/config.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/sched.h> | ||
42 | #include <linux/spinlock.h> | ||
43 | |||
44 | #include <asm/system.h> | ||
45 | #include <asm/hardware.h> | ||
46 | #include <asm/io.h> | ||
47 | #include <asm/leds.h> | ||
48 | #include <asm/irq.h> | ||
49 | #include <asm/mach/irq.h> | ||
50 | #include <asm/mach/time.h> | ||
51 | |||
52 | struct sys_timer omap_timer; | ||
53 | |||
54 | #ifdef CONFIG_OMAP_MPU_TIMER | ||
55 | |||
56 | /* | ||
57 | * --------------------------------------------------------------------------- | ||
58 | * MPU timer | ||
59 | * --------------------------------------------------------------------------- | ||
60 | */ | ||
61 | #define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE | ||
62 | #define OMAP_MPU_TIMER_OFFSET 0x100 | ||
63 | |||
64 | /* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c, | ||
65 | * converted to use kHz by Kevin Hilman */ | ||
66 | /* convert from cycles(64bits) => nanoseconds (64bits) | ||
67 | * basic equation: | ||
68 | * ns = cycles / (freq / ns_per_sec) | ||
69 | * ns = cycles * (ns_per_sec / freq) | ||
70 | * ns = cycles * (10^9 / (cpu_khz * 10^3)) | ||
71 | * ns = cycles * (10^6 / cpu_khz) | ||
72 | * | ||
73 | * Then we use scaling math (suggested by george at mvista.com) to get: | ||
74 | * ns = cycles * (10^6 * SC / cpu_khz / SC | ||
75 | * ns = cycles * cyc2ns_scale / SC | ||
76 | * | ||
77 | * And since SC is a constant power of two, we can convert the div | ||
78 | * into a shift. | ||
79 | * -johnstul at us.ibm.com "math is hard, lets go shopping!" | ||
80 | */ | ||
81 | static unsigned long cyc2ns_scale; | ||
82 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ | ||
83 | |||
84 | static inline void set_cyc2ns_scale(unsigned long cpu_khz) | ||
85 | { | ||
86 | cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; | ||
87 | } | ||
88 | |||
89 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) | ||
90 | { | ||
91 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs | ||
96 | * will break. On P2, the timer count rate is 6.5 MHz after programming PTV | ||
97 | * with 0. This divides the 13MHz input by 2, and is undocumented. | ||
98 | */ | ||
99 | #ifdef CONFIG_MACH_OMAP_PERSEUS2 | ||
100 | /* REVISIT: This ifdef construct should be replaced by a query to clock | ||
101 | * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz. | ||
102 | */ | ||
103 | #define MPU_TICKS_PER_SEC (13000000 / 2) | ||
104 | #else | ||
105 | #define MPU_TICKS_PER_SEC (12000000 / 2) | ||
106 | #endif | ||
107 | |||
108 | #define MPU_TIMER_TICK_PERIOD ((MPU_TICKS_PER_SEC / HZ) - 1) | ||
109 | |||
110 | typedef struct { | ||
111 | u32 cntl; /* CNTL_TIMER, R/W */ | ||
112 | u32 load_tim; /* LOAD_TIM, W */ | ||
113 | u32 read_tim; /* READ_TIM, R */ | ||
114 | } omap_mpu_timer_regs_t; | ||
115 | |||
116 | #define omap_mpu_timer_base(n) \ | ||
117 | ((volatile omap_mpu_timer_regs_t*)IO_ADDRESS(OMAP_MPU_TIMER_BASE + \ | ||
118 | (n)*OMAP_MPU_TIMER_OFFSET)) | ||
119 | |||
120 | static inline unsigned long omap_mpu_timer_read(int nr) | ||
121 | { | ||
122 | volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); | ||
123 | return timer->read_tim; | ||
124 | } | ||
125 | |||
126 | static inline void omap_mpu_timer_start(int nr, unsigned long load_val) | ||
127 | { | ||
128 | volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); | ||
129 | |||
130 | timer->cntl = MPU_TIMER_CLOCK_ENABLE; | ||
131 | udelay(1); | ||
132 | timer->load_tim = load_val; | ||
133 | udelay(1); | ||
134 | timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST); | ||
135 | } | ||
136 | |||
137 | unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks) | ||
138 | { | ||
139 | unsigned long long nsec; | ||
140 | |||
141 | nsec = cycles_2_ns((unsigned long long)nr_ticks); | ||
142 | return (unsigned long)nsec / 1000; | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Last processed system timer interrupt | ||
147 | */ | ||
148 | static unsigned long omap_mpu_timer_last = 0; | ||
149 | |||
150 | /* | ||
151 | * Returns elapsed usecs since last system timer interrupt | ||
152 | */ | ||
153 | static unsigned long omap_mpu_timer_gettimeoffset(void) | ||
154 | { | ||
155 | unsigned long now = 0 - omap_mpu_timer_read(0); | ||
156 | unsigned long elapsed = now - omap_mpu_timer_last; | ||
157 | |||
158 | return omap_mpu_timer_ticks_to_usecs(elapsed); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Elapsed time between interrupts is calculated using timer0. | ||
163 | * Latency during the interrupt is calculated using timer1. | ||
164 | * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz). | ||
165 | */ | ||
166 | static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id, | ||
167 | struct pt_regs *regs) | ||
168 | { | ||
169 | unsigned long now, latency; | ||
170 | |||
171 | write_seqlock(&xtime_lock); | ||
172 | now = 0 - omap_mpu_timer_read(0); | ||
173 | latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1); | ||
174 | omap_mpu_timer_last = now - latency; | ||
175 | timer_tick(regs); | ||
176 | write_sequnlock(&xtime_lock); | ||
177 | |||
178 | return IRQ_HANDLED; | ||
179 | } | ||
180 | |||
181 | static struct irqaction omap_mpu_timer_irq = { | ||
182 | .name = "mpu timer", | ||
183 | .flags = SA_INTERRUPT | SA_TIMER, | ||
184 | .handler = omap_mpu_timer_interrupt, | ||
185 | }; | ||
186 | |||
187 | static unsigned long omap_mpu_timer1_overflows; | ||
188 | static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id, | ||
189 | struct pt_regs *regs) | ||
190 | { | ||
191 | omap_mpu_timer1_overflows++; | ||
192 | return IRQ_HANDLED; | ||
193 | } | ||
194 | |||
195 | static struct irqaction omap_mpu_timer1_irq = { | ||
196 | .name = "mpu timer1 overflow", | ||
197 | .flags = SA_INTERRUPT, | ||
198 | .handler = omap_mpu_timer1_interrupt, | ||
199 | }; | ||
200 | |||
201 | static __init void omap_init_mpu_timer(void) | ||
202 | { | ||
203 | set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000); | ||
204 | omap_timer.offset = omap_mpu_timer_gettimeoffset; | ||
205 | setup_irq(INT_TIMER1, &omap_mpu_timer1_irq); | ||
206 | setup_irq(INT_TIMER2, &omap_mpu_timer_irq); | ||
207 | omap_mpu_timer_start(0, 0xffffffff); | ||
208 | omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD); | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Scheduler clock - returns current time in nanosec units. | ||
213 | */ | ||
214 | unsigned long long sched_clock(void) | ||
215 | { | ||
216 | unsigned long ticks = 0 - omap_mpu_timer_read(0); | ||
217 | unsigned long long ticks64; | ||
218 | |||
219 | ticks64 = omap_mpu_timer1_overflows; | ||
220 | ticks64 <<= 32; | ||
221 | ticks64 |= ticks; | ||
222 | |||
223 | return cycles_2_ns(ticks64); | ||
224 | } | ||
225 | #endif /* CONFIG_OMAP_MPU_TIMER */ | ||
226 | |||
227 | #ifdef CONFIG_OMAP_32K_TIMER | ||
228 | |||
229 | #ifdef CONFIG_ARCH_OMAP1510 | ||
230 | #error OMAP 32KHz timer does not currently work on 1510! | ||
231 | #endif | ||
232 | |||
233 | /* | ||
234 | * --------------------------------------------------------------------------- | ||
235 | * 32KHz OS timer | ||
236 | * | ||
237 | * This currently works only on 16xx, as 1510 does not have the continuous | ||
238 | * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track | ||
239 | * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer | ||
240 | * on 1510 would be possible, but the timer would not be as accurate as | ||
241 | * with the 32KHz synchronized timer. | ||
242 | * --------------------------------------------------------------------------- | ||
243 | */ | ||
244 | #define OMAP_32K_TIMER_BASE 0xfffb9000 | ||
245 | #define OMAP_32K_TIMER_CR 0x08 | ||
246 | #define OMAP_32K_TIMER_TVR 0x00 | ||
247 | #define OMAP_32K_TIMER_TCR 0x04 | ||
248 | |||
249 | #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) | ||
250 | #if (32768 % HZ) != 0 | ||
251 | /* We cannot ignore modulo. | ||
252 | * Potential error can be as high as several percent. | ||
253 | */ | ||
254 | #define OMAP_32K_TICK_MODULO (32768 % HZ) | ||
255 | static unsigned modulo_count = 0; /* Counts 1/HZ units */ | ||
256 | #endif | ||
257 | |||
258 | /* | ||
259 | * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1 | ||
260 | * so with HZ = 100, TVR = 327.68. | ||
261 | */ | ||
262 | #define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1) | ||
263 | #define TIMER_32K_SYNCHRONIZED 0xfffbc410 | ||
264 | |||
265 | #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ | ||
266 | (((nr_jiffies) * (clock_rate)) / HZ) | ||
267 | |||
268 | static inline void omap_32k_timer_write(int val, int reg) | ||
269 | { | ||
270 | omap_writew(val, reg + OMAP_32K_TIMER_BASE); | ||
271 | } | ||
272 | |||
273 | static inline unsigned long omap_32k_timer_read(int reg) | ||
274 | { | ||
275 | return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * The 32KHz synchronized timer is an additional timer on 16xx. | ||
280 | * It is always running. | ||
281 | */ | ||
282 | static inline unsigned long omap_32k_sync_timer_read(void) | ||
283 | { | ||
284 | return omap_readl(TIMER_32K_SYNCHRONIZED); | ||
285 | } | ||
286 | |||
287 | static inline void omap_32k_timer_start(unsigned long load_val) | ||
288 | { | ||
289 | omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR); | ||
290 | omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR); | ||
291 | } | ||
292 | |||
293 | static inline void omap_32k_timer_stop(void) | ||
294 | { | ||
295 | omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR); | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Rounds down to nearest usec | ||
300 | */ | ||
301 | static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k) | ||
302 | { | ||
303 | return (ticks_32k * 5*5*5*5*5*5) >> 9; | ||
304 | } | ||
305 | |||
306 | static unsigned long omap_32k_last_tick = 0; | ||
307 | |||
308 | /* | ||
309 | * Returns elapsed usecs since last 32k timer interrupt | ||
310 | */ | ||
311 | static unsigned long omap_32k_timer_gettimeoffset(void) | ||
312 | { | ||
313 | unsigned long now = omap_32k_sync_timer_read(); | ||
314 | return omap_32k_ticks_to_usecs(now - omap_32k_last_tick); | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this | ||
319 | * function is also called from other interrupts to remove latency | ||
320 | * issues with dynamic tick. In the dynamic tick case, we need to lock | ||
321 | * with irqsave. | ||
322 | */ | ||
323 | static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, | ||
324 | struct pt_regs *regs) | ||
325 | { | ||
326 | unsigned long flags; | ||
327 | unsigned long now; | ||
328 | |||
329 | write_seqlock_irqsave(&xtime_lock, flags); | ||
330 | now = omap_32k_sync_timer_read(); | ||
331 | |||
332 | while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { | ||
333 | #ifdef OMAP_32K_TICK_MODULO | ||
334 | /* Modulo addition may put omap_32k_last_tick ahead of now | ||
335 | * and cause unwanted repetition of the while loop. | ||
336 | */ | ||
337 | if (unlikely(now - omap_32k_last_tick == ~0)) | ||
338 | break; | ||
339 | |||
340 | modulo_count += OMAP_32K_TICK_MODULO; | ||
341 | if (modulo_count > HZ) { | ||
342 | ++omap_32k_last_tick; | ||
343 | modulo_count -= HZ; | ||
344 | } | ||
345 | #endif | ||
346 | omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; | ||
347 | timer_tick(regs); | ||
348 | } | ||
349 | |||
350 | /* Restart timer so we don't drift off due to modulo or dynamic tick. | ||
351 | * By default we program the next timer to be continuous to avoid | ||
352 | * latencies during high system load. During dynamic tick operation the | ||
353 | * continuous timer can be overridden from pm_idle to be longer. | ||
354 | */ | ||
355 | omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now); | ||
356 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
357 | |||
358 | return IRQ_HANDLED; | ||
359 | } | ||
360 | |||
361 | #ifdef CONFIG_NO_IDLE_HZ | ||
362 | /* | ||
363 | * Programs the next timer interrupt needed. Called when dynamic tick is | ||
364 | * enabled, and to reprogram the ticks to skip from pm_idle. Note that | ||
365 | * we can keep the timer continuous, and don't need to set it to run in | ||
366 | * one-shot mode. This is because the timer will get reprogrammed again | ||
367 | * after next interrupt. | ||
368 | */ | ||
369 | void omap_32k_timer_reprogram(unsigned long next_tick) | ||
370 | { | ||
371 | omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1); | ||
372 | } | ||
373 | |||
374 | static struct irqaction omap_32k_timer_irq; | ||
375 | extern struct timer_update_handler timer_update; | ||
376 | |||
377 | static int omap_32k_timer_enable_dyn_tick(void) | ||
378 | { | ||
379 | /* No need to reprogram timer, just use the next interrupt */ | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int omap_32k_timer_disable_dyn_tick(void) | ||
384 | { | ||
385 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static struct dyn_tick_timer omap_dyn_tick_timer = { | ||
390 | .enable = omap_32k_timer_enable_dyn_tick, | ||
391 | .disable = omap_32k_timer_disable_dyn_tick, | ||
392 | .reprogram = omap_32k_timer_reprogram, | ||
393 | .handler = omap_32k_timer_interrupt, | ||
394 | }; | ||
395 | #endif /* CONFIG_NO_IDLE_HZ */ | ||
396 | |||
397 | static struct irqaction omap_32k_timer_irq = { | ||
398 | .name = "32KHz timer", | ||
399 | .flags = SA_INTERRUPT | SA_TIMER, | ||
400 | .handler = omap_32k_timer_interrupt, | ||
401 | }; | ||
402 | |||
403 | static __init void omap_init_32k_timer(void) | ||
404 | { | ||
405 | |||
406 | #ifdef CONFIG_NO_IDLE_HZ | ||
407 | omap_timer.dyn_tick = &omap_dyn_tick_timer; | ||
408 | #endif | ||
409 | |||
410 | setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); | ||
411 | omap_timer.offset = omap_32k_timer_gettimeoffset; | ||
412 | omap_32k_last_tick = omap_32k_sync_timer_read(); | ||
413 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | ||
414 | } | ||
415 | #endif /* CONFIG_OMAP_32K_TIMER */ | ||
416 | |||
417 | /* | ||
418 | * --------------------------------------------------------------------------- | ||
419 | * Timer initialization | ||
420 | * --------------------------------------------------------------------------- | ||
421 | */ | ||
422 | static void __init omap_timer_init(void) | ||
423 | { | ||
424 | #if defined(CONFIG_OMAP_MPU_TIMER) | ||
425 | omap_init_mpu_timer(); | ||
426 | #elif defined(CONFIG_OMAP_32K_TIMER) | ||
427 | omap_init_32k_timer(); | ||
428 | #else | ||
429 | #error No system timer selected in Kconfig! | ||
430 | #endif | ||
431 | } | ||
432 | |||
433 | struct sys_timer omap_timer = { | ||
434 | .init = omap_timer_init, | ||
435 | .offset = NULL, /* Initialized later */ | ||
436 | }; | ||