aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap1
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap1')
-rw-r--r--arch/arm/mach-omap1/Kconfig144
-rw-r--r--arch/arm/mach-omap1/Makefile30
-rw-r--r--arch/arm/mach-omap1/Makefile.boot3
-rw-r--r--arch/arm/mach-omap1/board-generic.c99
-rw-r--r--arch/arm/mach-omap1/board-h2.c188
-rw-r--r--arch/arm/mach-omap1/board-h3.c206
-rw-r--r--arch/arm/mach-omap1/board-innovator.c281
-rw-r--r--arch/arm/mach-omap1/board-netstar.c152
-rw-r--r--arch/arm/mach-omap1/board-osk.c170
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c190
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c257
-rw-r--r--arch/arm/mach-omap1/fpga.c188
-rw-r--r--arch/arm/mach-omap1/id.c188
-rw-r--r--arch/arm/mach-omap1/io.c115
-rw-r--r--arch/arm/mach-omap1/irq.c234
-rw-r--r--arch/arm/mach-omap1/leds-h2p2-debug.c144
-rw-r--r--arch/arm/mach-omap1/leds-innovator.c103
-rw-r--r--arch/arm/mach-omap1/leds-osk.c194
-rw-r--r--arch/arm/mach-omap1/leds.c61
-rw-r--r--arch/arm/mach-omap1/leds.h3
-rw-r--r--arch/arm/mach-omap1/serial.c200
-rw-r--r--arch/arm/mach-omap1/time.c436
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 @@
1comment "OMAP Core Type"
2 depends on ARCH_OMAP1
3
4config ARCH_OMAP730
5 depends on ARCH_OMAP1
6 bool "OMAP730 Based System"
7 select ARCH_OMAP_OTG
8
9config ARCH_OMAP1510
10 depends on ARCH_OMAP1
11 default y
12 bool "OMAP1510 Based System"
13
14config ARCH_OMAP16XX
15 depends on ARCH_OMAP1
16 bool "OMAP16xx Based System"
17 select ARCH_OMAP_OTG
18
19comment "OMAP Board Type"
20 depends on ARCH_OMAP1
21
22config 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
29config 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
36config 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
43config 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
50config 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
57config 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
64config 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
70config 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
79comment "OMAP CPU Speed"
80 depends on ARCH_OMAP1
81
82config 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
90config 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
96config 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
102config 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
108config 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
114config 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
120config 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
126config 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
132config 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
139config 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
6obj-y := io.o id.o irq.o time.o serial.o
7led-y := leds.o
8
9# Specific board support
10obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o
11obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
12obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
13obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
14obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
15obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
16obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
17obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o
18
19ifeq ($(CONFIG_ARCH_OMAP1510),y)
20# Innovator-1510 FPGA
21obj-$(CONFIG_MACH_OMAP_INNOVATOR) += fpga.o
22endif
23
24# LEDs support
25led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
26led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
27led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o
28led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o
29obj-$(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
2params_phys-y := 0x10000100
3initrd_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
31static int __initdata generic_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
32
33static 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
41static 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)
50static 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
58static struct omap_board_config_kernel generic_config[] = {
59 { OMAP_TAG_USB, NULL },
60};
61
62static 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
84static void __init omap_generic_map_io(void)
85{
86 omap_map_common_io()
87}
88
89MACHINE_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,
99MACHINE_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
40extern int omap_gpio_init(void);
41
42static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
43
44static 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
75static 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
82static 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
88static 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
98static 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
111static 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
118static struct platform_device *h2_devices[] __initdata = {
119 &h2_flash_device,
120 &h2_smc91x_device,
121};
122
123static 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
132void h2_init_irq(void)
133{
134 omap_init_irq();
135 omap_gpio_init();
136 h2_init_smc91x();
137}
138
139static 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
154static 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
160static struct omap_board_config_kernel h2_config[] = {
161 { OMAP_TAG_USB, &h2_usb_config },
162 { OMAP_TAG_MMC, &h2_mmc_config },
163};
164
165static 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
172static void __init h2_map_io(void)
173{
174 omap_map_common_io();
175 omap_serial_init(h2_serial_ports);
176}
177
178MACHINE_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,
188MACHINE_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
42extern int omap_gpio_init(void);
43
44static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
45
46static 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
77static 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
84static 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
90static 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
100static 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
113static 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
124static 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
137static 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
144static struct platform_device *devices[] __initdata = {
145 &flash_device,
146 &smc91x_device,
147 &intlat_device,
148};
149
150static 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
164static struct omap_board_config_kernel h3_config[] = {
165 { OMAP_TAG_USB, &h3_usb_config },
166};
167
168static void __init h3_init(void)
169{
170 (void) platform_add_devices(devices, ARRAY_SIZE(devices));
171}
172
173static 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
183void h3_init_irq(void)
184{
185 omap_init_irq();
186 omap_gpio_init();
187 h3_init_smc91x();
188}
189
190static void __init h3_map_io(void)
191{
192 omap_map_common_io();
193 omap_serial_init(h3_serial_ports);
194}
195
196MACHINE_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,
206MACHINE_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
38static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
39
40static 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
78static 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
85static struct resource innovator_flash_resource = {
86 .start = OMAP_CS0_PHYS,
87 .end = OMAP_CS0_PHYS + SZ_32M - 1,
88 .flags = IORESOURCE_MEM,
89};
90
91static 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 */
104static struct map_desc innovator1510_io_desc[] __initdata = {
105{ OMAP1510_FPGA_BASE, OMAP1510_FPGA_START, OMAP1510_FPGA_SIZE,
106 MT_DEVICE },
107};
108
109static 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
122static 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
129static 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
138static 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
151static 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
158static struct platform_device *innovator1610_devices[] __initdata = {
159 &innovator_flash_device,
160 &innovator1610_smc91x_device,
161};
162
163#endif /* CONFIG_ARCH_OMAP16XX */
164
165static 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
180void 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
193static 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
207static 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
223static struct omap_board_config_kernel innovator_config[] = {
224 { OMAP_TAG_USB, NULL },
225};
226
227static 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
252static 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
271MACHINE_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,
281MACHINE_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
31extern void __init omap_init_time(void);
32extern int omap_gpio_init(void);
33
34static 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
47static 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
54static struct platform_device *netstar_devices[] __initdata = {
55 &netstar_smc91x_device,
56};
57
58static void __init netstar_init_irq(void)
59{
60 omap_init_irq();
61 omap_gpio_init();
62}
63
64static 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
98static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
99
100static 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
109static unsigned long machine_state;
110
111static 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
126static struct notifier_block panic_block = {
127 .notifier_call = panic_event,
128};
129
130static 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
140postcore_initcall(netstar_late_init);
141
142MACHINE_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,
152MACHINE_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
44static 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
49static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
50
51static 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
64static 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
71static 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
79static 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
89static struct platform_device *osk5912_devices[] __initdata = {
90 &osk5912_smc91x_device,
91 &osk5912_cf_device,
92};
93
94static 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
106static 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
117void osk_init_irq(void)
118{
119 omap_init_irq();
120 omap_gpio_init();
121 osk_init_smc91x();
122 osk_init_cf();
123}
124
125static 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
141static struct omap_board_config_kernel osk_config[] = {
142 { OMAP_TAG_USB, &osk_usb_config },
143};
144
145static 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
153static 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
160MACHINE_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,
170MACHINE_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
32static 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
45static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0};
46
47static 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
78static 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
85static 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
91static 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
101static struct platform_device smc91x_device = {
102 .name = "smc91x",
103 .id = 0,
104 .num_resources = ARRAY_SIZE(smc91x_resources),
105 .resource = smc91x_resources,
106};
107
108static struct platform_device *devices[] __initdata = {
109 &p2_flash_device,
110 &smc91x_device,
111};
112
113static void __init omap_perseus2_init(void)
114{
115 (void) platform_add_devices(devices, ARRAY_SIZE(devices));
116}
117
118static 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
127void 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 */
135static 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
140static 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
180MACHINE_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,
190MACHINE_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
36extern void omap_init_time(void);
37extern int omap_gpio_init(void);
38
39static 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
75static struct platform_device serial_device = {
76 .name = "serial8250",
77 .id = 1,
78 .dev = {
79 .platform_data = voiceblue_ports,
80 },
81};
82
83static int __init ext_uart_init(void)
84{
85 return platform_device_register(&serial_device);
86}
87arch_initcall(ext_uart_init);
88
89static 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
102static 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
109static struct platform_device *voiceblue_devices[] __initdata = {
110 &voiceblue_smc91x_device,
111};
112
113static 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
122static struct omap_board_config_kernel voiceblue_config[] = {
123 { OMAP_TAG_USB, &voiceblue_usb_config },
124};
125
126static void __init voiceblue_init_irq(void)
127{
128 omap_init_irq();
129 omap_gpio_init();
130}
131
132static 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
168static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
169
170static 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
179static unsigned long machine_state;
180
181static 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
194static struct notifier_block panic_block = {
195 .notifier_call = panic_event,
196};
197
198static 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
206postcore_initcall(setup_notifier);
207
208static int wdt_gpio_state;
209
210void 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
219void 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
227void 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
236void voiceblue_reset(void)
237{
238 set_bit(MACHINE_REBOOT, &machine_state);
239 voiceblue_wdt_enable();
240 while (1) ;
241}
242
243EXPORT_SYMBOL(voiceblue_wdt_enable);
244EXPORT_SYMBOL(voiceblue_wdt_disable);
245EXPORT_SYMBOL(voiceblue_wdt_ping);
246
247MACHINE_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,
257MACHINE_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
34static 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
50static 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
62static void fpga_ack_irq(unsigned int irq)
63{
64 /* Don't need to explicitly ACK FPGA interrupts */
65}
66
67static 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
82static void fpga_mask_ack_irq(unsigned int irq)
83{
84 fpga_mask_irq(irq);
85 fpga_ack_irq(irq);
86}
87
88void 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
110static 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
117static 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 */
146void 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
188EXPORT_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
21struct 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 */
29static 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 */
58static 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 */
86static 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
105void __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
20extern int clk_init(void);
21extern 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 */
27static struct map_desc omap_io_desc[] __initdata = {
28 { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
29};
30
31#ifdef CONFIG_ARCH_OMAP730
32static 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
40static 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)
48static 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
54static 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
67static int initialized = 0;
68
69static 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 */
111void 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
56struct omap_irq_bank {
57 unsigned long base_reg;
58 unsigned long trigger_map;
59 unsigned long wake_enable;
60};
61
62static unsigned int irq_bank_count = 0;
63static struct omap_irq_bank *irq_banks;
64
65static inline unsigned int irq_bank_readl(int bank, int offset)
66{
67 return omap_readl(irq_banks[bank].base_reg + offset);
68}
69
70static 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
75static 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
83static 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
93static 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
103static void omap_mask_ack_irq(unsigned int irq)
104{
105 omap_mask_irq(irq);
106 omap_ack_irq(irq);
107}
108
109static 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 */
129static 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
143static 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
151static 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
159static 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
167static 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
174void __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
41void 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
142done:
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
17static unsigned int led_state;
18static unsigned int hw_led_state;
19
20void 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)
22static 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 */
29static 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
37static u8 tps_leds_change;
38
39static 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
65static 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
77static 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
94void 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
192done:
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
17static int __init
18omap_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 @@
1extern void innovator_leds_event(led_event_t evt);
2extern void h2p2_dbg_leds_event(led_event_t evt);
3extern 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
29static struct clk * uart1_ck = NULL;
30static struct clk * uart2_ck = NULL;
31static struct clk * uart3_ck = NULL;
32
33static 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
40static 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 */
52static 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
64static 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
95static 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 */
108void __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
196static int __init omap_init(void)
197{
198 return platform_device_register(&serial_device);
199}
200arch_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
52struct 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 */
81static unsigned long cyc2ns_scale;
82#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
83
84static inline void set_cyc2ns_scale(unsigned long cpu_khz)
85{
86 cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
87}
88
89static 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
110typedef 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
120static 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
126static 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
137unsigned 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 */
148static unsigned long omap_mpu_timer_last = 0;
149
150/*
151 * Returns elapsed usecs since last system timer interrupt
152 */
153static 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 */
166static 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
181static struct irqaction omap_mpu_timer_irq = {
182 .name = "mpu timer",
183 .flags = SA_INTERRUPT | SA_TIMER,
184 .handler = omap_mpu_timer_interrupt,
185};
186
187static unsigned long omap_mpu_timer1_overflows;
188static 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
195static struct irqaction omap_mpu_timer1_irq = {
196 .name = "mpu timer1 overflow",
197 .flags = SA_INTERRUPT,
198 .handler = omap_mpu_timer1_interrupt,
199};
200
201static __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 */
214unsigned 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)
255static 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
268static inline void omap_32k_timer_write(int val, int reg)
269{
270 omap_writew(val, reg + OMAP_32K_TIMER_BASE);
271}
272
273static 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 */
282static inline unsigned long omap_32k_sync_timer_read(void)
283{
284 return omap_readl(TIMER_32K_SYNCHRONIZED);
285}
286
287static 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
293static 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 */
301static 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
306static unsigned long omap_32k_last_tick = 0;
307
308/*
309 * Returns elapsed usecs since last 32k timer interrupt
310 */
311static 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 */
323static 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 */
369void omap_32k_timer_reprogram(unsigned long next_tick)
370{
371 omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
372}
373
374static struct irqaction omap_32k_timer_irq;
375extern struct timer_update_handler timer_update;
376
377static 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
383static int omap_32k_timer_disable_dyn_tick(void)
384{
385 omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
386 return 0;
387}
388
389static 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
397static struct irqaction omap_32k_timer_irq = {
398 .name = "32KHz timer",
399 .flags = SA_INTERRUPT | SA_TIMER,
400 .handler = omap_32k_timer_interrupt,
401};
402
403static __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 */
422static 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
433struct sys_timer omap_timer = {
434 .init = omap_timer_init,
435 .offset = NULL, /* Initialized later */
436};