aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/arm/mach-omap
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/arm/mach-omap')
-rw-r--r--arch/arm/mach-omap/Kconfig221
-rw-r--r--arch/arm/mach-omap/Makefile40
-rw-r--r--arch/arm/mach-omap/Makefile.boot4
-rw-r--r--arch/arm/mach-omap/board-generic.c98
-rw-r--r--arch/arm/mach-omap/board-h2.c187
-rw-r--r--arch/arm/mach-omap/board-h3.c205
-rw-r--r--arch/arm/mach-omap/board-innovator.c280
-rw-r--r--arch/arm/mach-omap/board-netstar.c151
-rw-r--r--arch/arm/mach-omap/board-osk.c169
-rw-r--r--arch/arm/mach-omap/board-perseus2.c189
-rw-r--r--arch/arm/mach-omap/board-voiceblue.c256
-rw-r--r--arch/arm/mach-omap/clock.c1076
-rw-r--r--arch/arm/mach-omap/clock.h112
-rw-r--r--arch/arm/mach-omap/common.c549
-rw-r--r--arch/arm/mach-omap/common.h36
-rw-r--r--arch/arm/mach-omap/dma.c1086
-rw-r--r--arch/arm/mach-omap/fpga.c188
-rw-r--r--arch/arm/mach-omap/gpio.c762
-rw-r--r--arch/arm/mach-omap/irq.c219
-rw-r--r--arch/arm/mach-omap/leds-h2p2-debug.c144
-rw-r--r--arch/arm/mach-omap/leds-innovator.c103
-rw-r--r--arch/arm/mach-omap/leds-osk.c198
-rw-r--r--arch/arm/mach-omap/leds.c61
-rw-r--r--arch/arm/mach-omap/leds.h3
-rw-r--r--arch/arm/mach-omap/mcbsp.c685
-rw-r--r--arch/arm/mach-omap/mux.c163
-rw-r--r--arch/arm/mach-omap/ocpi.c114
-rw-r--r--arch/arm/mach-omap/pm.c628
-rw-r--r--arch/arm/mach-omap/sleep.S314
-rw-r--r--arch/arm/mach-omap/time.c384
-rw-r--r--arch/arm/mach-omap/usb.c594
31 files changed, 9219 insertions, 0 deletions
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
new file mode 100644
index 000000000000..9e42efa66b2b
--- /dev/null
+++ b/arch/arm/mach-omap/Kconfig
@@ -0,0 +1,221 @@
1if ARCH_OMAP
2
3menu "TI OMAP Implementations"
4
5comment "OMAP Core Type"
6
7config ARCH_OMAP730
8 depends on ARCH_OMAP
9 bool "OMAP730 Based System"
10 select ARCH_OMAP_OTG
11
12config ARCH_OMAP1510
13 depends on ARCH_OMAP
14 default y
15 bool "OMAP1510 Based System"
16
17config ARCH_OMAP16XX
18 depends on ARCH_OMAP
19 bool "OMAP16XX Based System"
20 select ARCH_OMAP_OTG
21
22config ARCH_OMAP_OTG
23 bool
24
25comment "OMAP Board Type"
26
27config MACH_OMAP_INNOVATOR
28 bool "TI Innovator"
29 depends on ARCH_OMAP1510 || ARCH_OMAP16XX
30 help
31 TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
32 have such a board.
33
34config MACH_OMAP_H2
35 bool "TI H2 Support"
36 depends on ARCH_OMAP16XX
37 help
38 TI OMAP 1610/1611B H2 board support. Say Y here if you have such
39 a board.
40
41config MACH_OMAP_H3
42 bool "TI H3 Support"
43 depends on ARCH_OMAP16XX
44 help
45 TI OMAP 1710 H3 board support. Say Y here if you have such
46 a board.
47
48config MACH_OMAP_H4
49 bool "TI H4 Support"
50 depends on ARCH_OMAP16XX
51 help
52 TI OMAP 1610 H4 board support. Say Y here if you have such
53 a board.
54
55config MACH_OMAP_OSK
56 bool "TI OSK Support"
57 depends on ARCH_OMAP16XX
58 help
59 TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
60 if you have such a board.
61
62config MACH_OMAP_PERSEUS2
63 bool "TI Perseus2"
64 depends on ARCH_OMAP730
65 help
66 Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
67 a board.
68
69config MACH_VOICEBLUE
70 bool "Voiceblue"
71 depends on ARCH_OMAP1510
72 help
73 Support for Voiceblue GSM/VoIP gateway. Say Y here if you have such
74 board.
75
76config MACH_NETSTAR
77 bool "NetStar"
78 depends on ARCH_OMAP1510
79 help
80 Support for NetStar PBX. Say Y here if you have such a board.
81
82config MACH_OMAP_GENERIC
83 bool "Generic OMAP board"
84 depends on ARCH_OMAP1510 || ARCH_OMAP16XX
85 help
86 Support for generic OMAP-1510, 1610 or 1710 board with
87 no FPGA. Can be used as template for porting Linux to
88 custom OMAP boards. Say Y here if you have a custom
89 board.
90
91comment "OMAP Feature Selections"
92
93#config OMAP_BOOT_TAG
94# bool "OMAP bootloader information passing"
95# depends on ARCH_OMAP
96# default n
97# help
98# Say Y, if you have a bootloader which passes information
99# about your board and its peripheral configuration.
100
101config OMAP_MUX
102 bool "OMAP multiplexing support"
103 depends on ARCH_OMAP
104 default y
105 help
106 Pin multiplexing support for OMAP boards. If your bootloader
107 sets the multiplexing correctly, say N. Otherwise, or if unsure,
108 say Y.
109
110config OMAP_MUX_DEBUG
111 bool "Multiplexing debug output"
112 depends on OMAP_MUX
113 default n
114 help
115 Makes the multiplexing functions print out a lot of debug info.
116 This is useful if you want to find out the correct values of the
117 multiplexing registers.
118
119config OMAP_MUX_WARNINGS
120 bool "Warn about pins the bootloader didn't set up"
121 depends on OMAP_MUX
122 default y
123 help
124 Choose Y here to warn whenever driver initialization logic needs
125 to change the pin multiplexing setup. When there are no warnings
126 printed, it's safe to deselect OMAP_MUX for your product.
127
128choice
129 prompt "System timer"
130 default OMAP_MPU_TIMER
131
132config OMAP_MPU_TIMER
133 bool "Use mpu timer"
134 help
135 Select this option if you want to use the OMAP mpu timer. This
136 timer provides more intra-tick resolution than the 32KHz timer,
137 but consumes more power.
138
139config OMAP_32K_TIMER
140 bool "Use 32KHz timer"
141 depends on ARCH_OMAP16XX
142 help
143 Select this option if you want to enable the OMAP 32KHz timer.
144 This timer saves power compared to the OMAP_MPU_TIMER, and has
145 support for no tick during idle. The 32KHz timer provides less
146 intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
147 currently only available for OMAP-16xx.
148
149endchoice
150
151config OMAP_32K_TIMER_HZ
152 int "Kernel internal timer frequency for 32KHz timer"
153 range 32 1024
154 depends on OMAP_32K_TIMER
155 default "128"
156 help
157 Kernel internal timer frequency should be a divisor of 32768,
158 such as 64 or 128.
159
160choice
161 prompt "Low-level debug console UART"
162 depends on ARCH_OMAP
163 default OMAP_LL_DEBUG_UART1
164
165config OMAP_LL_DEBUG_UART1
166 bool "UART1"
167
168config OMAP_LL_DEBUG_UART2
169 bool "UART2"
170
171config OMAP_LL_DEBUG_UART3
172 bool "UART3"
173
174endchoice
175
176config OMAP_ARM_195MHZ
177 bool "OMAP ARM 195 MHz CPU"
178 depends on ARCH_OMAP730
179 help
180 Enable 195MHz clock for OMAP CPU. If unsure, say N.
181
182config OMAP_ARM_192MHZ
183 bool "OMAP ARM 192 MHz CPU"
184 depends on ARCH_OMAP16XX
185 help
186 Enable 192MHz clock for OMAP CPU. If unsure, say N.
187
188config OMAP_ARM_182MHZ
189 bool "OMAP ARM 182 MHz CPU"
190 depends on ARCH_OMAP730
191 help
192 Enable 182MHz clock for OMAP CPU. If unsure, say N.
193
194config OMAP_ARM_168MHZ
195 bool "OMAP ARM 168 MHz CPU"
196 depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
197 help
198 Enable 168MHz clock for OMAP CPU. If unsure, say N.
199
200config OMAP_ARM_120MHZ
201 bool "OMAP ARM 120 MHz CPU"
202 depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
203 help
204 Enable 120MHz clock for OMAP CPU. If unsure, say N.
205
206config OMAP_ARM_60MHZ
207 bool "OMAP ARM 60 MHz CPU"
208 depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
209 default y
210 help
211 Enable 60MHz clock for OMAP CPU. If unsure, say Y.
212
213config OMAP_ARM_30MHZ
214 bool "OMAP ARM 30 MHz CPU"
215 depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
216 help
217 Enable 30MHz clock for OMAP CPU. If unsure, say N.
218
219endmenu
220
221endif
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
new file mode 100644
index 000000000000..4cafb11d2c02
--- /dev/null
+++ b/arch/arm/mach-omap/Makefile
@@ -0,0 +1,40 @@
1#
2# Makefile for the linux kernel.
3#
4
5# Common support
6obj-y := common.o time.o irq.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o
7obj-m :=
8obj-n :=
9obj- :=
10led-y := leds.o
11
12# Specific board support
13obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o
14obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
15obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
16obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
17obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
18obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
19obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
20obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o
21
22# OCPI interconnect support for 1710, 1610 and 5912
23obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
24
25# LEDs support
26led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
27led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
28led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o
29obj-$(CONFIG_LEDS) += $(led-y)
30
31# Power Management
32obj-$(CONFIG_PM) += pm.o sleep.o
33
34ifeq ($(CONFIG_ARCH_OMAP1510),y)
35# Innovator-1510 FPGA
36obj-$(CONFIG_MACH_OMAP_INNOVATOR) += fpga.o
37endif
38
39# kgdb support
40obj-$(CONFIG_KGDB_SERIAL) += kgdb-serial.o
diff --git a/arch/arm/mach-omap/Makefile.boot b/arch/arm/mach-omap/Makefile.boot
new file mode 100644
index 000000000000..fee1a6a15b54
--- /dev/null
+++ b/arch/arm/mach-omap/Makefile.boot
@@ -0,0 +1,4 @@
1 zreladdr-y := 0x10008000
2params_phys-y := 0x10000100
3initrd_phys-y := 0x10800000
4
diff --git a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c
new file mode 100644
index 000000000000..2102a2cd1013
--- /dev/null
+++ b/arch/arm/mach-omap/board-generic.c
@@ -0,0 +1,98 @@
1/*
2 * linux/arch/arm/mach-omap/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
30#include "common.h"
31
32static int __initdata generic_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
33
34static void __init omap_generic_init_irq(void)
35{
36 omap_init_irq();
37}
38
39/* assume no Mini-AB port */
40
41#ifdef CONFIG_ARCH_OMAP1510
42static struct omap_usb_config generic1510_usb_config __initdata = {
43 .register_host = 1,
44 .register_dev = 1,
45 .hmc_mode = 16,
46 .pins[0] = 3,
47};
48#endif
49
50#if defined(CONFIG_ARCH_OMAP16XX)
51static struct omap_usb_config generic1610_usb_config __initdata = {
52 .register_host = 1,
53 .register_dev = 1,
54 .hmc_mode = 16,
55 .pins[0] = 6,
56};
57#endif
58
59static struct omap_board_config_kernel generic_config[] = {
60 { OMAP_TAG_USB, NULL },
61};
62
63static void __init omap_generic_init(void)
64{
65 /*
66 * Make sure the serial ports are muxed on at this point.
67 * You have to mux them off in device drivers later on
68 * if not needed.
69 */
70#ifdef CONFIG_ARCH_OMAP1510
71 if (cpu_is_omap1510()) {
72 generic_config[0].data = &generic1510_usb_config;
73 }
74#endif
75#if defined(CONFIG_ARCH_OMAP16XX)
76 if (!cpu_is_omap1510()) {
77 generic_config[0].data = &generic1610_usb_config;
78 }
79#endif
80 omap_board_config = generic_config;
81 omap_board_config_size = ARRAY_SIZE(generic_config);
82 omap_serial_init(generic_serial_ports);
83}
84
85static void __init omap_generic_map_io(void)
86{
87 omap_map_io();
88}
89
90MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
91 MAINTAINER("Tony Lindgren <tony@atomide.com>")
92 BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
93 BOOT_PARAMS(0x10000100)
94 MAPIO(omap_generic_map_io)
95 INITIRQ(omap_generic_init_irq)
96 INIT_MACHINE(omap_generic_init)
97 .timer = &omap_timer,
98MACHINE_END
diff --git a/arch/arm/mach-omap/board-h2.c b/arch/arm/mach-omap/board-h2.c
new file mode 100644
index 000000000000..1f067830d1fc
--- /dev/null
+++ b/arch/arm/mach-omap/board-h2.c
@@ -0,0 +1,187 @@
1/*
2 * linux/arch/arm/mach-omap/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
39#include "common.h"
40
41extern int omap_gpio_init(void);
42
43static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
44
45static struct mtd_partition h2_partitions[] = {
46 /* bootloader (U-Boot, etc) in first sector */
47 {
48 .name = "bootloader",
49 .offset = 0,
50 .size = SZ_128K,
51 .mask_flags = MTD_WRITEABLE, /* force read-only */
52 },
53 /* bootloader params in the next sector */
54 {
55 .name = "params",
56 .offset = MTDPART_OFS_APPEND,
57 .size = SZ_128K,
58 .mask_flags = 0,
59 },
60 /* kernel */
61 {
62 .name = "kernel",
63 .offset = MTDPART_OFS_APPEND,
64 .size = SZ_2M,
65 .mask_flags = 0
66 },
67 /* file system */
68 {
69 .name = "filesystem",
70 .offset = MTDPART_OFS_APPEND,
71 .size = MTDPART_SIZ_FULL,
72 .mask_flags = 0
73 }
74};
75
76static struct flash_platform_data h2_flash_data = {
77 .map_name = "cfi_probe",
78 .width = 2,
79 .parts = h2_partitions,
80 .nr_parts = ARRAY_SIZE(h2_partitions),
81};
82
83static struct resource h2_flash_resource = {
84 .start = OMAP_CS2B_PHYS,
85 .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1,
86 .flags = IORESOURCE_MEM,
87};
88
89static struct platform_device h2_flash_device = {
90 .name = "omapflash",
91 .id = 0,
92 .dev = {
93 .platform_data = &h2_flash_data,
94 },
95 .num_resources = 1,
96 .resource = &h2_flash_resource,
97};
98
99static struct resource h2_smc91x_resources[] = {
100 [0] = {
101 .start = OMAP1610_ETHR_START, /* Physical */
102 .end = OMAP1610_ETHR_START + 0xf,
103 .flags = IORESOURCE_MEM,
104 },
105 [1] = {
106 .start = OMAP_GPIO_IRQ(0),
107 .end = OMAP_GPIO_IRQ(0),
108 .flags = IORESOURCE_IRQ,
109 },
110};
111
112static struct platform_device h2_smc91x_device = {
113 .name = "smc91x",
114 .id = 0,
115 .num_resources = ARRAY_SIZE(h2_smc91x_resources),
116 .resource = h2_smc91x_resources,
117};
118
119static struct platform_device *h2_devices[] __initdata = {
120 &h2_flash_device,
121 &h2_smc91x_device,
122};
123
124static void __init h2_init_smc91x(void)
125{
126 if ((omap_request_gpio(0)) < 0) {
127 printk("Error requesting gpio 0 for smc91x irq\n");
128 return;
129 }
130 omap_set_gpio_edge_ctrl(0, OMAP_GPIO_FALLING_EDGE);
131}
132
133void h2_init_irq(void)
134{
135 omap_init_irq();
136 omap_gpio_init();
137 h2_init_smc91x();
138}
139
140static struct omap_usb_config h2_usb_config __initdata = {
141 /* usb1 has a Mini-AB port and external isp1301 transceiver */
142 .otg = 2,
143
144#ifdef CONFIG_USB_GADGET_OMAP
145 .hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled
146 // .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback)
147#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
148 /* needs OTG cable, or NONSTANDARD (B-to-MiniB) */
149 .hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled
150#endif
151
152 .pins[1] = 3,
153};
154
155static struct omap_mmc_config h2_mmc_config __initdata = {
156 .mmc_blocks = 1,
157 .mmc1_power_pin = -1, /* tps65010 gpio3 */
158 .mmc1_switch_pin = OMAP_MPUIO(1),
159};
160
161static struct omap_board_config_kernel h2_config[] = {
162 { OMAP_TAG_USB, &h2_usb_config },
163 { OMAP_TAG_MMC, &h2_mmc_config },
164};
165
166static void __init h2_init(void)
167{
168 platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
169 omap_board_config = h2_config;
170 omap_board_config_size = ARRAY_SIZE(h2_config);
171}
172
173static void __init h2_map_io(void)
174{
175 omap_map_io();
176 omap_serial_init(h2_serial_ports);
177}
178
179MACHINE_START(OMAP_H2, "TI-H2")
180 MAINTAINER("Imre Deak <imre.deak@nokia.com>")
181 BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
182 BOOT_PARAMS(0x10000100)
183 MAPIO(h2_map_io)
184 INITIRQ(h2_init_irq)
185 INIT_MACHINE(h2_init)
186 .timer = &omap_timer,
187MACHINE_END
diff --git a/arch/arm/mach-omap/board-h3.c b/arch/arm/mach-omap/board-h3.c
new file mode 100644
index 000000000000..486a5a006c9a
--- /dev/null
+++ b/arch/arm/mach-omap/board-h3.c
@@ -0,0 +1,205 @@
1/*
2 * linux/arch/arm/mach-omap/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
41#include "common.h"
42
43extern int omap_gpio_init(void);
44
45static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
46
47static struct mtd_partition h3_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 /* 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 h3_flash_data = {
79 .map_name = "cfi_probe",
80 .width = 2,
81 .parts = h3_partitions,
82 .nr_parts = ARRAY_SIZE(h3_partitions),
83};
84
85static struct resource h3_flash_resource = {
86 .start = OMAP_CS2B_PHYS,
87 .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1,
88 .flags = IORESOURCE_MEM,
89};
90
91static struct platform_device flash_device = {
92 .name = "omapflash",
93 .id = 0,
94 .dev = {
95 .platform_data = &h3_flash_data,
96 },
97 .num_resources = 1,
98 .resource = &h3_flash_resource,
99};
100
101static struct resource smc91x_resources[] = {
102 [0] = {
103 .start = OMAP1710_ETHR_START, /* Physical */
104 .end = OMAP1710_ETHR_START + 0xf,
105 .flags = IORESOURCE_MEM,
106 },
107 [1] = {
108 .start = OMAP_GPIO_IRQ(40),
109 .end = OMAP_GPIO_IRQ(40),
110 .flags = IORESOURCE_IRQ,
111 },
112};
113
114static struct platform_device smc91x_device = {
115 .name = "smc91x",
116 .id = 0,
117 .num_resources = ARRAY_SIZE(smc91x_resources),
118 .resource = smc91x_resources,
119};
120
121#define GPTIMER_BASE 0xFFFB1400
122#define GPTIMER_REGS(x) (0xFFFB1400 + (x * 0x800))
123#define GPTIMER_REGS_SIZE 0x46
124
125static struct resource intlat_resources[] = {
126 [0] = {
127 .start = GPTIMER_REGS(0), /* Physical */
128 .end = GPTIMER_REGS(0) + GPTIMER_REGS_SIZE,
129 .flags = IORESOURCE_MEM,
130 },
131 [1] = {
132 .start = INT_1610_GPTIMER1,
133 .end = INT_1610_GPTIMER1,
134 .flags = IORESOURCE_IRQ,
135 },
136};
137
138static struct platform_device intlat_device = {
139 .name = "omap_intlat",
140 .id = 0,
141 .num_resources = ARRAY_SIZE(intlat_resources),
142 .resource = intlat_resources,
143};
144
145static struct platform_device *devices[] __initdata = {
146 &flash_device,
147 &smc91x_device,
148 &intlat_device,
149};
150
151static struct omap_usb_config h3_usb_config __initdata = {
152 /* usb1 has a Mini-AB port and external isp1301 transceiver */
153 .otg = 2,
154
155#ifdef CONFIG_USB_GADGET_OMAP
156 .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */
157#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
158 /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
159 .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */
160#endif
161
162 .pins[1] = 3,
163};
164
165static struct omap_board_config_kernel h3_config[] = {
166 { OMAP_TAG_USB, &h3_usb_config },
167};
168
169static void __init h3_init(void)
170{
171 (void) platform_add_devices(devices, ARRAY_SIZE(devices));
172}
173
174static void __init h3_init_smc91x(void)
175{
176 omap_cfg_reg(W15_1710_GPIO40);
177 if (omap_request_gpio(40) < 0) {
178 printk("Error requesting gpio 40 for smc91x irq\n");
179 return;
180 }
181 omap_set_gpio_edge_ctrl(40, OMAP_GPIO_FALLING_EDGE);
182}
183
184void h3_init_irq(void)
185{
186 omap_init_irq();
187 omap_gpio_init();
188 h3_init_smc91x();
189}
190
191static void __init h3_map_io(void)
192{
193 omap_map_io();
194 omap_serial_init(h3_serial_ports);
195}
196
197MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
198 MAINTAINER("Texas Instruments, Inc.")
199 BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
200 BOOT_PARAMS(0x10000100)
201 MAPIO(h3_map_io)
202 INITIRQ(h3_init_irq)
203 INIT_MACHINE(h3_init)
204 .timer = &omap_timer,
205MACHINE_END
diff --git a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c
new file mode 100644
index 000000000000..57cf4da88d55
--- /dev/null
+++ b/arch/arm/mach-omap/board-innovator.c
@@ -0,0 +1,280 @@
1/*
2 * linux/arch/arm/mach-omap/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
37#include "common.h"
38
39static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
40
41static struct mtd_partition innovator_partitions[] = {
42 /* bootloader (U-Boot, etc) in first sector */
43 {
44 .name = "bootloader",
45 .offset = 0,
46 .size = SZ_128K,
47 .mask_flags = MTD_WRITEABLE, /* force read-only */
48 },
49 /* bootloader params in the next sector */
50 {
51 .name = "params",
52 .offset = MTDPART_OFS_APPEND,
53 .size = SZ_128K,
54 .mask_flags = 0,
55 },
56 /* kernel */
57 {
58 .name = "kernel",
59 .offset = MTDPART_OFS_APPEND,
60 .size = SZ_2M,
61 .mask_flags = 0
62 },
63 /* rest of flash1 is a file system */
64 {
65 .name = "rootfs",
66 .offset = MTDPART_OFS_APPEND,
67 .size = SZ_16M - SZ_2M - 2 * SZ_128K,
68 .mask_flags = 0
69 },
70 /* file system */
71 {
72 .name = "filesystem",
73 .offset = MTDPART_OFS_APPEND,
74 .size = MTDPART_SIZ_FULL,
75 .mask_flags = 0
76 }
77};
78
79static struct flash_platform_data innovator_flash_data = {
80 .map_name = "cfi_probe",
81 .width = 2,
82 .parts = innovator_partitions,
83 .nr_parts = ARRAY_SIZE(innovator_partitions),
84};
85
86static struct resource innovator_flash_resource = {
87 .start = OMAP_CS0_PHYS,
88 .end = OMAP_CS0_PHYS + SZ_32M - 1,
89 .flags = IORESOURCE_MEM,
90};
91
92static struct platform_device innovator_flash_device = {
93 .name = "omapflash",
94 .id = 0,
95 .dev = {
96 .platform_data = &innovator_flash_data,
97 },
98 .num_resources = 1,
99 .resource = &innovator_flash_resource,
100};
101
102#ifdef CONFIG_ARCH_OMAP1510
103
104/* Only FPGA needs to be mapped here. All others are done with ioremap */
105static struct map_desc innovator1510_io_desc[] __initdata = {
106{ OMAP1510_FPGA_BASE, OMAP1510_FPGA_START, OMAP1510_FPGA_SIZE,
107 MT_DEVICE },
108};
109
110static struct resource innovator1510_smc91x_resources[] = {
111 [0] = {
112 .start = OMAP1510_FPGA_ETHR_START, /* Physical */
113 .end = OMAP1510_FPGA_ETHR_START + 0xf,
114 .flags = IORESOURCE_MEM,
115 },
116 [1] = {
117 .start = OMAP1510_INT_ETHER,
118 .end = OMAP1510_INT_ETHER,
119 .flags = IORESOURCE_IRQ,
120 },
121};
122
123static struct platform_device innovator1510_smc91x_device = {
124 .name = "smc91x",
125 .id = 0,
126 .num_resources = ARRAY_SIZE(innovator1510_smc91x_resources),
127 .resource = innovator1510_smc91x_resources,
128};
129
130static struct platform_device *innovator1510_devices[] __initdata = {
131 &innovator_flash_device,
132 &innovator1510_smc91x_device,
133};
134
135#endif /* CONFIG_ARCH_OMAP1510 */
136
137#ifdef CONFIG_ARCH_OMAP16XX
138
139static struct resource innovator1610_smc91x_resources[] = {
140 [0] = {
141 .start = INNOVATOR1610_ETHR_START, /* Physical */
142 .end = INNOVATOR1610_ETHR_START + 0xf,
143 .flags = IORESOURCE_MEM,
144 },
145 [1] = {
146 .start = OMAP_GPIO_IRQ(0),
147 .end = OMAP_GPIO_IRQ(0),
148 .flags = IORESOURCE_IRQ,
149 },
150};
151
152static struct platform_device innovator1610_smc91x_device = {
153 .name = "smc91x",
154 .id = 0,
155 .num_resources = ARRAY_SIZE(innovator1610_smc91x_resources),
156 .resource = innovator1610_smc91x_resources,
157};
158
159static struct platform_device *innovator1610_devices[] __initdata = {
160 &innovator_flash_device,
161 &innovator1610_smc91x_device,
162};
163
164#endif /* CONFIG_ARCH_OMAP16XX */
165
166static void __init innovator_init_smc91x(void)
167{
168 if (cpu_is_omap1510()) {
169 fpga_write(fpga_read(OMAP1510_FPGA_RST) & ~1,
170 OMAP1510_FPGA_RST);
171 udelay(750);
172 } else {
173 if ((omap_request_gpio(0)) < 0) {
174 printk("Error requesting gpio 0 for smc91x irq\n");
175 return;
176 }
177 omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE);
178 }
179}
180
181void innovator_init_irq(void)
182{
183 omap_init_irq();
184 omap_gpio_init();
185#ifdef CONFIG_ARCH_OMAP1510
186 if (cpu_is_omap1510()) {
187 omap1510_fpga_init_irq();
188 }
189#endif
190 innovator_init_smc91x();
191}
192
193#ifdef CONFIG_ARCH_OMAP1510
194static struct omap_usb_config innovator1510_usb_config __initdata = {
195 /* for bundled non-standard host and peripheral cables */
196 .hmc_mode = 4,
197
198 .register_host = 1,
199 .pins[1] = 6,
200 .pins[2] = 6, /* Conflicts with UART2 */
201
202 .register_dev = 1,
203 .pins[0] = 2,
204};
205#endif
206
207#ifdef CONFIG_ARCH_OMAP16XX
208static struct omap_usb_config h2_usb_config __initdata = {
209 /* usb1 has a Mini-AB port and external isp1301 transceiver */
210 .otg = 2,
211
212#ifdef CONFIG_USB_GADGET_OMAP
213 .hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled
214 // .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback)
215#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
216 /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
217 .hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled
218#endif
219
220 .pins[1] = 3,
221};
222#endif
223
224static struct omap_board_config_kernel innovator_config[] = {
225 { OMAP_TAG_USB, NULL },
226};
227
228static void __init innovator_init(void)
229{
230#ifdef CONFIG_ARCH_OMAP1510
231 if (cpu_is_omap1510()) {
232 platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
233 }
234#endif
235#ifdef CONFIG_ARCH_OMAP16XX
236 if (!cpu_is_omap1510()) {
237 platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
238 }
239#endif
240
241#ifdef CONFIG_ARCH_OMAP1510
242 if (cpu_is_omap1510())
243 innovator_config[0].data = &innovator1510_usb_config;
244#endif
245#ifdef CONFIG_ARCH_OMAP16XX
246 if (cpu_is_omap1610())
247 innovator_config[0].data = &h2_usb_config;
248#endif
249 omap_board_config = innovator_config;
250 omap_board_config_size = ARRAY_SIZE(innovator_config);
251}
252
253static void __init innovator_map_io(void)
254{
255 omap_map_io();
256
257#ifdef CONFIG_ARCH_OMAP1510
258 if (cpu_is_omap1510()) {
259 iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
260 udelay(10); /* Delay needed for FPGA */
261
262 /* Dump the Innovator FPGA rev early - useful info for support. */
263 printk("Innovator FPGA Rev %d.%d Board Rev %d\n",
264 fpga_read(OMAP1510_FPGA_REV_HIGH),
265 fpga_read(OMAP1510_FPGA_REV_LOW),
266 fpga_read(OMAP1510_FPGA_BOARD_REV));
267 }
268#endif
269 omap_serial_init(innovator_serial_ports);
270}
271
272MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
273 MAINTAINER("MontaVista Software, Inc.")
274 BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
275 BOOT_PARAMS(0x10000100)
276 MAPIO(innovator_map_io)
277 INITIRQ(innovator_init_irq)
278 INIT_MACHINE(innovator_init)
279 .timer = &omap_timer,
280MACHINE_END
diff --git a/arch/arm/mach-omap/board-netstar.c b/arch/arm/mach-omap/board-netstar.c
new file mode 100644
index 000000000000..54acbd215c4b
--- /dev/null
+++ b/arch/arm/mach-omap/board-netstar.c
@@ -0,0 +1,151 @@
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
30#include "common.h"
31
32extern void __init omap_init_time(void);
33extern int omap_gpio_init(void);
34
35static struct resource netstar_smc91x_resources[] = {
36 [0] = {
37 .start = OMAP_CS1_PHYS + 0x300,
38 .end = OMAP_CS1_PHYS + 0x300 + 16,
39 .flags = IORESOURCE_MEM,
40 },
41 [1] = {
42 .start = OMAP_GPIO_IRQ(8),
43 .end = OMAP_GPIO_IRQ(8),
44 .flags = IORESOURCE_IRQ,
45 },
46};
47
48static struct platform_device netstar_smc91x_device = {
49 .name = "smc91x",
50 .id = 0,
51 .num_resources = ARRAY_SIZE(netstar_smc91x_resources),
52 .resource = netstar_smc91x_resources,
53};
54
55static struct platform_device *netstar_devices[] __initdata = {
56 &netstar_smc91x_device,
57};
58
59static void __init netstar_init_irq(void)
60{
61 omap_init_irq();
62 omap_gpio_init();
63}
64
65static void __init netstar_init(void)
66{
67 /* green LED */
68 omap_request_gpio(4);
69 omap_set_gpio_direction(4, 0);
70 /* smc91x reset */
71 omap_request_gpio(7);
72 omap_set_gpio_direction(7, 0);
73 omap_set_gpio_dataout(7, 1);
74 udelay(2); /* wait at least 100ns */
75 omap_set_gpio_dataout(7, 0);
76 mdelay(50); /* 50ms until PHY ready */
77 /* smc91x interrupt pin */
78 omap_request_gpio(8);
79 omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE);
80
81 omap_request_gpio(12);
82 omap_request_gpio(13);
83 omap_request_gpio(14);
84 omap_request_gpio(15);
85 omap_set_gpio_edge_ctrl(12, OMAP_GPIO_FALLING_EDGE);
86 omap_set_gpio_edge_ctrl(13, OMAP_GPIO_FALLING_EDGE);
87 omap_set_gpio_edge_ctrl(14, OMAP_GPIO_FALLING_EDGE);
88 omap_set_gpio_edge_ctrl(15, OMAP_GPIO_FALLING_EDGE);
89
90 platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices));
91
92 /* Switch on green LED */
93 omap_set_gpio_dataout(4, 0);
94 /* Switch off red LED */
95 omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */
96 omap_writeb(0x80, OMAP_LPG1_LCR);
97}
98
99static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
100
101static void __init netstar_map_io(void)
102{
103 omap_map_io();
104 omap_serial_init(omap_serial_ports);
105}
106
107#define MACHINE_PANICED 1
108#define MACHINE_REBOOTING 2
109#define MACHINE_REBOOT 4
110static unsigned long machine_state;
111
112static int panic_event(struct notifier_block *this, unsigned long event,
113 void *ptr)
114{
115 if (test_and_set_bit(MACHINE_PANICED, &machine_state))
116 return NOTIFY_DONE;
117
118 /* Switch off green LED */
119 omap_set_gpio_dataout(4, 1);
120 /* Flash red LED */
121 omap_writeb(0x78, OMAP_LPG1_LCR);
122 omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */
123
124 return NOTIFY_DONE;
125}
126
127static struct notifier_block panic_block = {
128 .notifier_call = panic_event,
129};
130
131static int __init netstar_late_init(void)
132{
133 /* TODO: Setup front panel switch here */
134
135 /* Setup panic notifier */
136 notifier_chain_register(&panic_notifier_list, &panic_block);
137
138 return 0;
139}
140
141postcore_initcall(netstar_late_init);
142
143MACHINE_START(NETSTAR, "NetStar OMAP5910")
144 MAINTAINER("Ladislav Michl <michl@2n.cz>")
145 BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
146 BOOT_PARAMS(0x10000100)
147 MAPIO(netstar_map_io)
148 INITIRQ(netstar_init_irq)
149 INIT_MACHINE(netstar_init)
150 .timer = &omap_timer,
151MACHINE_END
diff --git a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c
new file mode 100644
index 000000000000..a951fc82459b
--- /dev/null
+++ b/arch/arm/mach-omap/board-osk.c
@@ -0,0 +1,169 @@
1/*
2 * linux/arch/arm/mach-omap/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
43#include "common.h"
44
45static struct map_desc osk5912_io_desc[] __initdata = {
46{ OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
47 MT_DEVICE },
48};
49
50static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
51
52static struct resource osk5912_smc91x_resources[] = {
53 [0] = {
54 .start = OMAP_OSK_ETHR_START, /* Physical */
55 .end = OMAP_OSK_ETHR_START + 0xf,
56 .flags = IORESOURCE_MEM,
57 },
58 [1] = {
59 .start = OMAP_GPIO_IRQ(0),
60 .end = OMAP_GPIO_IRQ(0),
61 .flags = IORESOURCE_IRQ,
62 },
63};
64
65static struct platform_device osk5912_smc91x_device = {
66 .name = "smc91x",
67 .id = -1,
68 .num_resources = ARRAY_SIZE(osk5912_smc91x_resources),
69 .resource = osk5912_smc91x_resources,
70};
71
72static struct resource osk5912_cf_resources[] = {
73 [0] = {
74 .start = OMAP_GPIO_IRQ(62),
75 .end = OMAP_GPIO_IRQ(62),
76 .flags = IORESOURCE_IRQ,
77 },
78};
79
80static struct platform_device osk5912_cf_device = {
81 .name = "omap_cf",
82 .id = -1,
83 .dev = {
84 .platform_data = (void *) 2 /* CS2 */,
85 },
86 .num_resources = ARRAY_SIZE(osk5912_cf_resources),
87 .resource = osk5912_cf_resources,
88};
89
90static struct platform_device *osk5912_devices[] __initdata = {
91 &osk5912_smc91x_device,
92 &osk5912_cf_device,
93};
94
95static void __init osk_init_smc91x(void)
96{
97 if ((omap_request_gpio(0)) < 0) {
98 printk("Error requesting gpio 0 for smc91x irq\n");
99 return;
100 }
101 omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE);
102
103 /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */
104 EMIFS_CCS(1) |= 0x2;
105}
106
107static void __init osk_init_cf(void)
108{
109 omap_cfg_reg(M7_1610_GPIO62);
110 if ((omap_request_gpio(62)) < 0) {
111 printk("Error requesting gpio 62 for CF irq\n");
112 return;
113 }
114 /* it's really active-low */
115 omap_set_gpio_edge_ctrl(62, OMAP_GPIO_FALLING_EDGE);
116}
117
118void osk_init_irq(void)
119{
120 omap_init_irq();
121 omap_gpio_init();
122 osk_init_smc91x();
123 osk_init_cf();
124}
125
126static struct omap_usb_config osk_usb_config __initdata = {
127 /* has usb host connector (A) ... for development it can also
128 * be used, with a NONSTANDARD gender-bending cable/dongle, as
129 * a peripheral.
130 */
131#ifdef CONFIG_USB_GADGET_OMAP
132 .register_dev = 1,
133 .hmc_mode = 0,
134#else
135 .register_host = 1,
136 .hmc_mode = 16,
137 .rwc = 1,
138#endif
139 .pins[0] = 2,
140};
141
142static struct omap_board_config_kernel osk_config[] = {
143 { OMAP_TAG_USB, &osk_usb_config },
144};
145
146static void __init osk_init(void)
147{
148 platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
149 omap_board_config = osk_config;
150 omap_board_config_size = ARRAY_SIZE(osk_config);
151 USB_TRANSCEIVER_CTRL_REG |= (3 << 1);
152}
153
154static void __init osk_map_io(void)
155{
156 omap_map_io();
157 iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
158 omap_serial_init(osk_serial_ports);
159}
160
161MACHINE_START(OMAP_OSK, "TI-OSK")
162 MAINTAINER("Dirk Behme <dirk.behme@de.bosch.com>")
163 BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
164 BOOT_PARAMS(0x10000100)
165 MAPIO(osk_map_io)
166 INITIRQ(osk_init_irq)
167 INIT_MACHINE(osk_init)
168 .timer = &omap_timer,
169MACHINE_END
diff --git a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c
new file mode 100644
index 000000000000..64515aeb49cf
--- /dev/null
+++ b/arch/arm/mach-omap/board-perseus2.c
@@ -0,0 +1,189 @@
1/*
2 * linux/arch/arm/mach-omap/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
31#include "common.h"
32
33static struct resource smc91x_resources[] = {
34 [0] = {
35 .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */
36 .end = H2P2_DBG_FPGA_ETHR_START + 0xf,
37 .flags = IORESOURCE_MEM,
38 },
39 [1] = {
40 .start = INT_730_MPU_EXT_NIRQ,
41 .end = 0,
42 .flags = IORESOURCE_IRQ,
43 },
44};
45
46static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0};
47
48static struct mtd_partition p2_partitions[] = {
49 /* bootloader (U-Boot, etc) in first sector */
50 {
51 .name = "bootloader",
52 .offset = 0,
53 .size = SZ_128K,
54 .mask_flags = MTD_WRITEABLE, /* force read-only */
55 },
56 /* bootloader params in the next sector */
57 {
58 .name = "params",
59 .offset = MTDPART_OFS_APPEND,
60 .size = SZ_128K,
61 .mask_flags = 0,
62 },
63 /* kernel */
64 {
65 .name = "kernel",
66 .offset = MTDPART_OFS_APPEND,
67 .size = SZ_2M,
68 .mask_flags = 0
69 },
70 /* rest of flash is a file system */
71 {
72 .name = "rootfs",
73 .offset = MTDPART_OFS_APPEND,
74 .size = MTDPART_SIZ_FULL,
75 .mask_flags = 0
76 },
77};
78
79static struct flash_platform_data p2_flash_data = {
80 .map_name = "cfi_probe",
81 .width = 2,
82 .parts = p2_partitions,
83 .nr_parts = ARRAY_SIZE(p2_partitions),
84};
85
86static struct resource p2_flash_resource = {
87 .start = OMAP_FLASH_0_START,
88 .end = OMAP_FLASH_0_START + OMAP_FLASH_0_SIZE - 1,
89 .flags = IORESOURCE_MEM,
90};
91
92static struct platform_device p2_flash_device = {
93 .name = "omapflash",
94 .id = 0,
95 .dev = {
96 .platform_data = &p2_flash_data,
97 },
98 .num_resources = 1,
99 .resource = &p2_flash_resource,
100};
101
102static struct platform_device smc91x_device = {
103 .name = "smc91x",
104 .id = 0,
105 .num_resources = ARRAY_SIZE(smc91x_resources),
106 .resource = smc91x_resources,
107};
108
109static struct platform_device *devices[] __initdata = {
110 &p2_flash_device,
111 &smc91x_device,
112};
113
114static void __init omap_perseus2_init(void)
115{
116 (void) platform_add_devices(devices, ARRAY_SIZE(devices));
117}
118
119static void __init perseus2_init_smc91x(void)
120{
121 fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
122 mdelay(50);
123 fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
124 H2P2_DBG_FPGA_LAN_RESET);
125 mdelay(50);
126}
127
128void omap_perseus2_init_irq(void)
129{
130 omap_init_irq();
131 omap_gpio_init();
132 perseus2_init_smc91x();
133}
134
135/* Only FPGA needs to be mapped here. All others are done with ioremap */
136static struct map_desc omap_perseus2_io_desc[] __initdata = {
137 {H2P2_DBG_FPGA_BASE, H2P2_DBG_FPGA_START, H2P2_DBG_FPGA_SIZE,
138 MT_DEVICE},
139};
140
141static void __init omap_perseus2_map_io(void)
142{
143 omap_map_io();
144 iotable_init(omap_perseus2_io_desc,
145 ARRAY_SIZE(omap_perseus2_io_desc));
146
147 /* Early, board-dependent init */
148
149 /*
150 * Hold GSM Reset until needed
151 */
152 omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL);
153
154 /*
155 * UARTs -> done automagically by 8250 driver
156 */
157
158 /*
159 * CSx timings, GPIO Mux ... setup
160 */
161
162 /* Flash: CS0 timings setup */
163 omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0);
164 omap_writel(0x00000088, OMAP730_FLASH_ACFG_0);
165
166 /*
167 * Ethernet support trough the debug board
168 * CS1 timings setup
169 */
170 omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1);
171 omap_writel(0x00000000, OMAP730_FLASH_ACFG_1);
172
173 /*
174 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
175 * It is used as the Ethernet controller interrupt
176 */
177 omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9);
178 omap_serial_init(p2_serial_ports);
179}
180
181MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
182 MAINTAINER("Kevin Hilman <kjh@hilman.org>")
183 BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
184 BOOT_PARAMS(0x10000100)
185 MAPIO(omap_perseus2_map_io)
186 INITIRQ(omap_perseus2_init_irq)
187 INIT_MACHINE(omap_perseus2_init)
188 .timer = &omap_timer,
189MACHINE_END
diff --git a/arch/arm/mach-omap/board-voiceblue.c b/arch/arm/mach-omap/board-voiceblue.c
new file mode 100644
index 000000000000..f1a5bffac666
--- /dev/null
+++ b/arch/arm/mach-omap/board-voiceblue.c
@@ -0,0 +1,256 @@
1/*
2 * linux/arch/arm/mach-omap/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
35#include "common.h"
36
37extern void omap_init_time(void);
38extern int omap_gpio_init(void);
39
40static struct plat_serial8250_port voiceblue_ports[] = {
41 {
42 .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x40000),
43 .irq = OMAP_GPIO_IRQ(12),
44 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
45 .iotype = UPIO_MEM,
46 .regshift = 1,
47 .uartclk = 3686400,
48 },
49 {
50 .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x50000),
51 .irq = OMAP_GPIO_IRQ(13),
52 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
53 .iotype = UPIO_MEM,
54 .regshift = 1,
55 .uartclk = 3686400,
56 },
57 {
58 .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x60000),
59 .irq = OMAP_GPIO_IRQ(14),
60 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
61 .iotype = UPIO_MEM,
62 .regshift = 1,
63 .uartclk = 3686400,
64 },
65 {
66 .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x70000),
67 .irq = OMAP_GPIO_IRQ(15),
68 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
69 .iotype = UPIO_MEM,
70 .regshift = 1,
71 .uartclk = 3686400,
72 },
73 { },
74};
75
76static struct platform_device serial_device = {
77 .name = "serial8250",
78 .id = 1,
79 .dev = {
80 .platform_data = voiceblue_ports,
81 },
82};
83
84static int __init ext_uart_init(void)
85{
86 return platform_device_register(&serial_device);
87}
88arch_initcall(ext_uart_init);
89
90static struct resource voiceblue_smc91x_resources[] = {
91 [0] = {
92 .start = OMAP_CS2_PHYS + 0x300,
93 .end = OMAP_CS2_PHYS + 0x300 + 16,
94 .flags = IORESOURCE_MEM,
95 },
96 [1] = {
97 .start = OMAP_GPIO_IRQ(8),
98 .end = OMAP_GPIO_IRQ(8),
99 .flags = IORESOURCE_IRQ,
100 },
101};
102
103static struct platform_device voiceblue_smc91x_device = {
104 .name = "smc91x",
105 .id = 0,
106 .num_resources = ARRAY_SIZE(voiceblue_smc91x_resources),
107 .resource = voiceblue_smc91x_resources,
108};
109
110static struct platform_device *voiceblue_devices[] __initdata = {
111 &voiceblue_smc91x_device,
112};
113
114static struct omap_usb_config voiceblue_usb_config __initdata = {
115 .hmc_mode = 3,
116 .register_host = 1,
117 .register_dev = 1,
118 .pins[0] = 2,
119 .pins[1] = 6,
120 .pins[2] = 6,
121};
122
123static struct omap_board_config_kernel voiceblue_config[] = {
124 { OMAP_TAG_USB, &voiceblue_usb_config },
125};
126
127static void __init voiceblue_init_irq(void)
128{
129 omap_init_irq();
130 omap_gpio_init();
131}
132
133static void __init voiceblue_init(void)
134{
135 /* There is a good chance board is going up, so enable Power LED
136 * (it is connected through invertor) */
137 omap_writeb(0x00, OMAP_LPG1_LCR);
138 /* Watchdog */
139 omap_request_gpio(0);
140 /* smc91x reset */
141 omap_request_gpio(7);
142 omap_set_gpio_direction(7, 0);
143 omap_set_gpio_dataout(7, 1);
144 udelay(2); /* wait at least 100ns */
145 omap_set_gpio_dataout(7, 0);
146 mdelay(50); /* 50ms until PHY ready */
147 /* smc91x interrupt pin */
148 omap_request_gpio(8);
149 omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE);
150 /* 16C554 reset*/
151 omap_request_gpio(6);
152 omap_set_gpio_direction(6, 0);
153 omap_set_gpio_dataout(6, 0);
154 /* 16C554 interrupt pins */
155 omap_request_gpio(12);
156 omap_request_gpio(13);
157 omap_request_gpio(14);
158 omap_request_gpio(15);
159 omap_set_gpio_edge_ctrl(12, OMAP_GPIO_RISING_EDGE);
160 omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE);
161 omap_set_gpio_edge_ctrl(14, OMAP_GPIO_RISING_EDGE);
162 omap_set_gpio_edge_ctrl(15, OMAP_GPIO_RISING_EDGE);
163
164 platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
165 omap_board_config = voiceblue_config;
166 omap_board_config_size = ARRAY_SIZE(voiceblue_config);
167}
168
169static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
170
171static void __init voiceblue_map_io(void)
172{
173 omap_map_io();
174 omap_serial_init(omap_serial_ports);
175}
176
177#define MACHINE_PANICED 1
178#define MACHINE_REBOOTING 2
179#define MACHINE_REBOOT 4
180static unsigned long machine_state;
181
182static int panic_event(struct notifier_block *this, unsigned long event,
183 void *ptr)
184{
185 if (test_and_set_bit(MACHINE_PANICED, &machine_state))
186 return NOTIFY_DONE;
187
188 /* Flash Power LED
189 * (TODO: Enable clock right way (enabled in bootloader already)) */
190 omap_writeb(0x78, OMAP_LPG1_LCR);
191
192 return NOTIFY_DONE;
193}
194
195static struct notifier_block panic_block = {
196 .notifier_call = panic_event,
197};
198
199static int __init setup_notifier(void)
200{
201 /* Setup panic notifier */
202 notifier_chain_register(&panic_notifier_list, &panic_block);
203
204 return 0;
205}
206
207postcore_initcall(setup_notifier);
208
209static int wdt_gpio_state;
210
211void voiceblue_wdt_enable(void)
212{
213 omap_set_gpio_direction(0, 0);
214 omap_set_gpio_dataout(0, 0);
215 omap_set_gpio_dataout(0, 1);
216 omap_set_gpio_dataout(0, 0);
217 wdt_gpio_state = 0;
218}
219
220void voiceblue_wdt_disable(void)
221{
222 omap_set_gpio_dataout(0, 0);
223 omap_set_gpio_dataout(0, 1);
224 omap_set_gpio_dataout(0, 0);
225 omap_set_gpio_direction(0, 1);
226}
227
228void voiceblue_wdt_ping(void)
229{
230 if (test_bit(MACHINE_REBOOT, &machine_state))
231 return;
232
233 wdt_gpio_state = !wdt_gpio_state;
234 omap_set_gpio_dataout(0, wdt_gpio_state);
235}
236
237void voiceblue_reset(void)
238{
239 set_bit(MACHINE_REBOOT, &machine_state);
240 voiceblue_wdt_enable();
241 while (1) ;
242}
243
244EXPORT_SYMBOL(voiceblue_wdt_enable);
245EXPORT_SYMBOL(voiceblue_wdt_disable);
246EXPORT_SYMBOL(voiceblue_wdt_ping);
247
248MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
249 MAINTAINER("Ladislav Michl <michl@2n.cz>")
250 BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
251 BOOT_PARAMS(0x10000100)
252 MAPIO(voiceblue_map_io)
253 INITIRQ(voiceblue_init_irq)
254 INIT_MACHINE(voiceblue_init)
255 .timer = &omap_timer,
256MACHINE_END
diff --git a/arch/arm/mach-omap/clock.c b/arch/arm/mach-omap/clock.c
new file mode 100644
index 000000000000..e91186b5341a
--- /dev/null
+++ b/arch/arm/mach-omap/clock.c
@@ -0,0 +1,1076 @@
1/*
2 * linux/arch/arm/mach-omap/clock.c
3 *
4 * Copyright (C) 2004 Nokia corporation
5 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/list.h>
14#include <linux/errno.h>
15#include <linux/err.h>
16
17#include <asm/semaphore.h>
18#include <asm/hardware/clock.h>
19#include <asm/arch/board.h>
20#include <asm/arch/usb.h>
21
22#include "clock.h"
23
24static LIST_HEAD(clocks);
25static DECLARE_MUTEX(clocks_sem);
26static DEFINE_SPINLOCK(clockfw_lock);
27static void propagate_rate(struct clk * clk);
28/* External clock (MCLK & BCLK) functions */
29static int set_ext_clk_rate(struct clk * clk, unsigned long rate);
30static long round_ext_clk_rate(struct clk * clk, unsigned long rate);
31static void init_ext_clk(struct clk * clk);
32/* MPU virtual clock functions */
33static int select_table_rate(struct clk * clk, unsigned long rate);
34static long round_to_table_rate(struct clk * clk, unsigned long rate);
35void clk_setdpll(__u16, __u16);
36
37struct mpu_rate rate_table[] = {
38 /* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL
39 * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv
40 */
41#if defined(CONFIG_OMAP_ARM_216MHZ)
42 { 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */
43#endif
44#if defined(CONFIG_OMAP_ARM_195MHZ)
45 { 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */
46#endif
47#if defined(CONFIG_OMAP_ARM_192MHZ)
48 { 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */
49 { 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */
50 { 96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */
51 { 48000000, 12000000, 192000000, 0x0ccf, 0x2810 }, /* 4/4/4/4/8/8 */
52 { 24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */
53#endif
54#if defined(CONFIG_OMAP_ARM_182MHZ)
55 { 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */
56#endif
57#if defined(CONFIG_OMAP_ARM_168MHZ)
58 { 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */
59#endif
60#if defined(CONFIG_OMAP_ARM_150MHZ)
61 { 150000000, 12000000, 150000000, 0x150a, 0x2cb0 }, /* 0/0/1/1/2/2 */
62#endif
63#if defined(CONFIG_OMAP_ARM_120MHZ)
64 { 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */
65#endif
66#if defined(CONFIG_OMAP_ARM_96MHZ)
67 { 96000000, 12000000, 96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */
68#endif
69#if defined(CONFIG_OMAP_ARM_60MHZ)
70 { 60000000, 12000000, 60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */
71#endif
72#if defined(CONFIG_OMAP_ARM_30MHZ)
73 { 30000000, 12000000, 60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */
74#endif
75 { 0, 0, 0, 0, 0 },
76};
77
78
79static void ckctl_recalc(struct clk * clk)
80{
81 int dsor;
82
83 /* Calculate divisor encoded as 2-bit exponent */
84 dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
85 if (unlikely(clk->rate == clk->parent->rate / dsor))
86 return; /* No change, quick exit */
87 clk->rate = clk->parent->rate / dsor;
88
89 if (unlikely(clk->flags & RATE_PROPAGATES))
90 propagate_rate(clk);
91}
92
93
94static void followparent_recalc(struct clk * clk)
95{
96 clk->rate = clk->parent->rate;
97}
98
99
100static void watchdog_recalc(struct clk * clk)
101{
102 clk->rate = clk->parent->rate / 14;
103}
104
105
106static struct clk ck_ref = {
107 .name = "ck_ref",
108 .rate = 12000000,
109 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
110 ALWAYS_ENABLED,
111};
112
113static struct clk ck_dpll1 = {
114 .name = "ck_dpll1",
115 .parent = &ck_ref,
116 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
117 RATE_PROPAGATES | ALWAYS_ENABLED,
118};
119
120static struct clk ck_dpll1out = {
121 .name = "ck_dpll1out",
122 .parent = &ck_dpll1,
123 .flags = CLOCK_IN_OMAP16XX,
124 .enable_reg = ARM_IDLECT2,
125 .enable_bit = EN_CKOUT_ARM,
126 .recalc = &followparent_recalc,
127};
128
129static struct clk arm_ck = {
130 .name = "arm_ck",
131 .parent = &ck_dpll1,
132 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
133 RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
134 .rate_offset = CKCTL_ARMDIV_OFFSET,
135 .recalc = &ckctl_recalc,
136};
137
138static struct clk armper_ck = {
139 .name = "armper_ck",
140 .parent = &ck_dpll1,
141 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
142 RATE_CKCTL,
143 .enable_reg = ARM_IDLECT2,
144 .enable_bit = EN_PERCK,
145 .rate_offset = CKCTL_PERDIV_OFFSET,
146 .recalc = &ckctl_recalc,
147};
148
149static struct clk arm_gpio_ck = {
150 .name = "arm_gpio_ck",
151 .parent = &ck_dpll1,
152 .flags = CLOCK_IN_OMAP1510,
153 .enable_reg = ARM_IDLECT2,
154 .enable_bit = EN_GPIOCK,
155 .recalc = &followparent_recalc,
156};
157
158static struct clk armxor_ck = {
159 .name = "armxor_ck",
160 .parent = &ck_ref,
161 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
162 .enable_reg = ARM_IDLECT2,
163 .enable_bit = EN_XORPCK,
164 .recalc = &followparent_recalc,
165};
166
167static struct clk armtim_ck = {
168 .name = "armtim_ck",
169 .parent = &ck_ref,
170 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
171 .enable_reg = ARM_IDLECT2,
172 .enable_bit = EN_TIMCK,
173 .recalc = &followparent_recalc,
174};
175
176static struct clk armwdt_ck = {
177 .name = "armwdt_ck",
178 .parent = &ck_ref,
179 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
180 .enable_reg = ARM_IDLECT2,
181 .enable_bit = EN_WDTCK,
182 .recalc = &watchdog_recalc,
183};
184
185static struct clk arminth_ck16xx = {
186 .name = "arminth_ck",
187 .parent = &arm_ck,
188 .flags = CLOCK_IN_OMAP16XX,
189 .recalc = &followparent_recalc,
190 /* Note: On 16xx the frequency can be divided by 2 by programming
191 * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
192 *
193 * 1510 version is in TC clocks.
194 */
195};
196
197static struct clk dsp_ck = {
198 .name = "dsp_ck",
199 .parent = &ck_dpll1,
200 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
201 RATE_CKCTL,
202 .enable_reg = ARM_CKCTL,
203 .enable_bit = EN_DSPCK,
204 .rate_offset = CKCTL_DSPDIV_OFFSET,
205 .recalc = &ckctl_recalc,
206};
207
208static struct clk dspmmu_ck = {
209 .name = "dspmmu_ck",
210 .parent = &ck_dpll1,
211 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
212 RATE_CKCTL | ALWAYS_ENABLED,
213 .rate_offset = CKCTL_DSPMMUDIV_OFFSET,
214 .recalc = &ckctl_recalc,
215};
216
217static struct clk tc_ck = {
218 .name = "tc_ck",
219 .parent = &ck_dpll1,
220 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 |
221 RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
222 .rate_offset = CKCTL_TCDIV_OFFSET,
223 .recalc = &ckctl_recalc,
224};
225
226static struct clk arminth_ck1510 = {
227 .name = "arminth_ck",
228 .parent = &tc_ck,
229 .flags = CLOCK_IN_OMAP1510,
230 .recalc = &followparent_recalc,
231 /* Note: On 1510 the frequency follows TC_CK
232 *
233 * 16xx version is in MPU clocks.
234 */
235};
236
237static struct clk tipb_ck = {
238 .name = "tibp_ck",
239 .parent = &tc_ck,
240 .flags = CLOCK_IN_OMAP1510,
241 .recalc = &followparent_recalc,
242};
243
244static struct clk l3_ocpi_ck = {
245 .name = "l3_ocpi_ck",
246 .parent = &tc_ck,
247 .flags = CLOCK_IN_OMAP16XX,
248 .enable_reg = ARM_IDLECT3,
249 .enable_bit = EN_OCPI_CK,
250 .recalc = &followparent_recalc,
251};
252
253static struct clk tc1_ck = {
254 .name = "tc1_ck",
255 .parent = &tc_ck,
256 .flags = CLOCK_IN_OMAP16XX,
257 .enable_reg = ARM_IDLECT3,
258 .enable_bit = EN_TC1_CK,
259 .recalc = &followparent_recalc,
260};
261
262static struct clk tc2_ck = {
263 .name = "tc2_ck",
264 .parent = &tc_ck,
265 .flags = CLOCK_IN_OMAP16XX,
266 .enable_reg = ARM_IDLECT3,
267 .enable_bit = EN_TC2_CK,
268 .recalc = &followparent_recalc,
269};
270
271static struct clk dma_ck = {
272 .name = "dma_ck",
273 .parent = &tc_ck,
274 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
275 .recalc = &followparent_recalc,
276};
277
278static struct clk dma_lcdfree_ck = {
279 .name = "dma_lcdfree_ck",
280 .parent = &tc_ck,
281 .flags = CLOCK_IN_OMAP16XX,
282 .recalc = &followparent_recalc,
283};
284
285static struct clk api_ck = {
286 .name = "api_ck",
287 .parent = &tc_ck,
288 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
289 .enable_reg = ARM_IDLECT2,
290 .enable_bit = EN_APICK,
291 .recalc = &followparent_recalc,
292};
293
294static struct clk lb_ck = {
295 .name = "lb_ck",
296 .parent = &tc_ck,
297 .flags = CLOCK_IN_OMAP1510,
298 .enable_reg = ARM_IDLECT2,
299 .enable_bit = EN_LBCK,
300 .recalc = &followparent_recalc,
301};
302
303static struct clk rhea1_ck = {
304 .name = "rhea1_ck",
305 .parent = &tc_ck,
306 .flags = CLOCK_IN_OMAP16XX,
307 .recalc = &followparent_recalc,
308};
309
310static struct clk rhea2_ck = {
311 .name = "rhea2_ck",
312 .parent = &tc_ck,
313 .flags = CLOCK_IN_OMAP16XX,
314 .recalc = &followparent_recalc,
315};
316
317static struct clk lcd_ck = {
318 .name = "lcd_ck",
319 .parent = &ck_dpll1,
320 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 |
321 RATE_CKCTL,
322 .enable_reg = ARM_IDLECT2,
323 .enable_bit = EN_LCDCK,
324 .rate_offset = CKCTL_LCDDIV_OFFSET,
325 .recalc = &ckctl_recalc,
326};
327
328static struct clk uart1_ck = {
329 .name = "uart1_ck",
330 /* Direct from ULPD, no parent */
331 .rate = 48000000,
332 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
333 RATE_FIXED | ENABLE_REG_32BIT,
334 .enable_reg = MOD_CONF_CTRL_0,
335 .enable_bit = 29,
336 /* (Only on 1510)
337 * The "enable bit" actually chooses between 48MHz and 12MHz.
338 */
339};
340
341static struct clk uart2_ck = {
342 .name = "uart2_ck",
343 /* Direct from ULPD, no parent */
344 .rate = 48000000,
345 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
346 RATE_FIXED | ENABLE_REG_32BIT,
347 .enable_reg = MOD_CONF_CTRL_0,
348 .enable_bit = 30,
349 /* (for both 1510 and 16xx)
350 * The "enable bit" actually chooses between 48MHz and 12MHz/32kHz.
351 */
352};
353
354static struct clk uart3_ck = {
355 .name = "uart3_ck",
356 /* Direct from ULPD, no parent */
357 .rate = 48000000,
358 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
359 RATE_FIXED | ENABLE_REG_32BIT,
360 .enable_reg = MOD_CONF_CTRL_0,
361 .enable_bit = 31,
362 /* (Only on 1510)
363 * The "enable bit" actually chooses between 48MHz and 12MHz.
364 */
365};
366
367static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
368 .name = "usb_clko",
369 /* Direct from ULPD, no parent */
370 .rate = 6000000,
371 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
372 RATE_FIXED | ENABLE_REG_32BIT,
373 .enable_reg = ULPD_CLOCK_CTRL,
374 .enable_bit = USB_MCLK_EN_BIT,
375};
376
377static struct clk usb_hhc_ck1510 = {
378 .name = "usb_hhc_ck",
379 /* Direct from ULPD, no parent */
380 .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
381 .flags = CLOCK_IN_OMAP1510 |
382 RATE_FIXED | ENABLE_REG_32BIT,
383 .enable_reg = MOD_CONF_CTRL_0,
384 .enable_bit = USB_HOST_HHC_UHOST_EN,
385};
386
387static struct clk usb_hhc_ck16xx = {
388 .name = "usb_hhc_ck",
389 /* Direct from ULPD, no parent */
390 .rate = 48000000,
391 /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
392 .flags = CLOCK_IN_OMAP16XX |
393 RATE_FIXED | ENABLE_REG_32BIT,
394 .enable_reg = OTG_BASE + 0x08 /* OTG_SYSCON_2 */,
395 .enable_bit = 8 /* UHOST_EN */,
396};
397
398static struct clk mclk_1510 = {
399 .name = "mclk",
400 /* Direct from ULPD, no parent. May be enabled by ext hardware. */
401 .rate = 12000000,
402 .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
403};
404
405static struct clk mclk_16xx = {
406 .name = "mclk",
407 /* Direct from ULPD, no parent. May be enabled by ext hardware. */
408 .flags = CLOCK_IN_OMAP16XX,
409 .enable_reg = COM_CLK_DIV_CTRL_SEL,
410 .enable_bit = COM_ULPD_PLL_CLK_REQ,
411 .set_rate = &set_ext_clk_rate,
412 .round_rate = &round_ext_clk_rate,
413 .init = &init_ext_clk,
414};
415
416static struct clk bclk_1510 = {
417 .name = "bclk",
418 /* Direct from ULPD, no parent. May be enabled by ext hardware. */
419 .rate = 12000000,
420 .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
421};
422
423static struct clk bclk_16xx = {
424 .name = "bclk",
425 /* Direct from ULPD, no parent. May be enabled by ext hardware. */
426 .flags = CLOCK_IN_OMAP16XX,
427 .enable_reg = SWD_CLK_DIV_CTRL_SEL,
428 .enable_bit = SWD_ULPD_PLL_CLK_REQ,
429 .set_rate = &set_ext_clk_rate,
430 .round_rate = &round_ext_clk_rate,
431 .init = &init_ext_clk,
432};
433
434static struct clk mmc1_ck = {
435 .name = "mmc1_ck",
436 /* Functional clock is direct from ULPD, interface clock is ARMPER */
437 .parent = &armper_ck,
438 .rate = 48000000,
439 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
440 RATE_FIXED | ENABLE_REG_32BIT,
441 .enable_reg = MOD_CONF_CTRL_0,
442 .enable_bit = 23,
443};
444
445static struct clk mmc2_ck = {
446 .name = "mmc2_ck",
447 /* Functional clock is direct from ULPD, interface clock is ARMPER */
448 .parent = &armper_ck,
449 .rate = 48000000,
450 .flags = CLOCK_IN_OMAP16XX |
451 RATE_FIXED | ENABLE_REG_32BIT,
452 .enable_reg = MOD_CONF_CTRL_0,
453 .enable_bit = 20,
454};
455
456static struct clk virtual_ck_mpu = {
457 .name = "mpu",
458 .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
459 VIRTUAL_CLOCK | ALWAYS_ENABLED,
460 .parent = &arm_ck, /* Is smarter alias for */
461 .recalc = &followparent_recalc,
462 .set_rate = &select_table_rate,
463 .round_rate = &round_to_table_rate,
464};
465
466
467static struct clk * onchip_clks[] = {
468 /* non-ULPD clocks */
469 &ck_ref,
470 &ck_dpll1,
471 /* CK_GEN1 clocks */
472 &ck_dpll1out,
473 &arm_ck,
474 &armper_ck,
475 &arm_gpio_ck,
476 &armxor_ck,
477 &armtim_ck,
478 &armwdt_ck,
479 &arminth_ck1510, &arminth_ck16xx,
480 /* CK_GEN2 clocks */
481 &dsp_ck,
482 &dspmmu_ck,
483 /* CK_GEN3 clocks */
484 &tc_ck,
485 &tipb_ck,
486 &l3_ocpi_ck,
487 &tc1_ck,
488 &tc2_ck,
489 &dma_ck,
490 &dma_lcdfree_ck,
491 &api_ck,
492 &lb_ck,
493 &rhea1_ck,
494 &rhea2_ck,
495 &lcd_ck,
496 /* ULPD clocks */
497 &uart1_ck,
498 &uart2_ck,
499 &uart3_ck,
500 &usb_clko,
501 &usb_hhc_ck1510, &usb_hhc_ck16xx,
502 &mclk_1510, &mclk_16xx,
503 &bclk_1510, &bclk_16xx,
504 &mmc1_ck,
505 &mmc2_ck,
506 /* Virtual clocks */
507 &virtual_ck_mpu,
508};
509
510struct clk *clk_get(struct device *dev, const char *id)
511{
512 struct clk *p, *clk = ERR_PTR(-ENOENT);
513
514 down(&clocks_sem);
515 list_for_each_entry(p, &clocks, node) {
516 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
517 clk = p;
518 break;
519 }
520 }
521 up(&clocks_sem);
522
523 return clk;
524}
525EXPORT_SYMBOL(clk_get);
526
527
528void clk_put(struct clk *clk)
529{
530 if (clk && !IS_ERR(clk))
531 module_put(clk->owner);
532}
533EXPORT_SYMBOL(clk_put);
534
535
536int __clk_enable(struct clk *clk)
537{
538 __u16 regval16;
539 __u32 regval32;
540
541 if (clk->flags & ALWAYS_ENABLED)
542 return 0;
543
544 if (unlikely(clk->enable_reg == 0)) {
545 printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
546 clk->name);
547 return 0;
548 }
549
550 if (clk->flags & ENABLE_REG_32BIT) {
551 regval32 = omap_readl(clk->enable_reg);
552 regval32 |= (1 << clk->enable_bit);
553 omap_writel(regval32, clk->enable_reg);
554 } else {
555 regval16 = omap_readw(clk->enable_reg);
556 regval16 |= (1 << clk->enable_bit);
557 omap_writew(regval16, clk->enable_reg);
558 }
559
560 return 0;
561}
562
563
564void __clk_disable(struct clk *clk)
565{
566 __u16 regval16;
567 __u32 regval32;
568
569 if (clk->enable_reg == 0)
570 return;
571
572 if (clk->flags & ENABLE_REG_32BIT) {
573 regval32 = omap_readl(clk->enable_reg);
574 regval32 &= ~(1 << clk->enable_bit);
575 omap_writel(regval32, clk->enable_reg);
576 } else {
577 regval16 = omap_readw(clk->enable_reg);
578 regval16 &= ~(1 << clk->enable_bit);
579 omap_writew(regval16, clk->enable_reg);
580 }
581}
582
583
584void __clk_unuse(struct clk *clk)
585{
586 if (clk->usecount > 0 && !(--clk->usecount)) {
587 __clk_disable(clk);
588 if (likely(clk->parent))
589 __clk_unuse(clk->parent);
590 }
591}
592
593
594int __clk_use(struct clk *clk)
595{
596 int ret = 0;
597 if (clk->usecount++ == 0) {
598 if (likely(clk->parent))
599 ret = __clk_use(clk->parent);
600
601 if (unlikely(ret != 0)) {
602 clk->usecount--;
603 return ret;
604 }
605
606 ret = __clk_enable(clk);
607
608 if (unlikely(ret != 0) && clk->parent) {
609 __clk_unuse(clk->parent);
610 clk->usecount--;
611 }
612 }
613
614 return ret;
615}
616
617
618int clk_enable(struct clk *clk)
619{
620 unsigned long flags;
621 int ret;
622
623 spin_lock_irqsave(&clockfw_lock, flags);
624 ret = __clk_enable(clk);
625 spin_unlock_irqrestore(&clockfw_lock, flags);
626 return ret;
627}
628EXPORT_SYMBOL(clk_enable);
629
630
631void clk_disable(struct clk *clk)
632{
633 unsigned long flags;
634
635 spin_lock_irqsave(&clockfw_lock, flags);
636 __clk_disable(clk);
637 spin_unlock_irqrestore(&clockfw_lock, flags);
638}
639EXPORT_SYMBOL(clk_disable);
640
641
642int clk_use(struct clk *clk)
643{
644 unsigned long flags;
645 int ret = 0;
646
647 spin_lock_irqsave(&clockfw_lock, flags);
648 ret = __clk_use(clk);
649 spin_unlock_irqrestore(&clockfw_lock, flags);
650 return ret;
651}
652EXPORT_SYMBOL(clk_use);
653
654
655void clk_unuse(struct clk *clk)
656{
657 unsigned long flags;
658
659 spin_lock_irqsave(&clockfw_lock, flags);
660 __clk_unuse(clk);
661 spin_unlock_irqrestore(&clockfw_lock, flags);
662}
663EXPORT_SYMBOL(clk_unuse);
664
665
666int clk_get_usecount(struct clk *clk)
667{
668 return clk->usecount;
669}
670EXPORT_SYMBOL(clk_get_usecount);
671
672
673unsigned long clk_get_rate(struct clk *clk)
674{
675 return clk->rate;
676}
677EXPORT_SYMBOL(clk_get_rate);
678
679
680static __u16 verify_ckctl_value(__u16 newval)
681{
682 /* This function checks for following limitations set
683 * by the hardware (all conditions must be true):
684 * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
685 * ARM_CK >= TC_CK
686 * DSP_CK >= TC_CK
687 * DSPMMU_CK >= TC_CK
688 *
689 * In addition following rules are enforced:
690 * LCD_CK <= TC_CK
691 * ARMPER_CK <= TC_CK
692 *
693 * However, maximum frequencies are not checked for!
694 */
695 __u8 per_exp;
696 __u8 lcd_exp;
697 __u8 arm_exp;
698 __u8 dsp_exp;
699 __u8 tc_exp;
700 __u8 dspmmu_exp;
701
702 per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
703 lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
704 arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
705 dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
706 tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
707 dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
708
709 if (dspmmu_exp < dsp_exp)
710 dspmmu_exp = dsp_exp;
711 if (dspmmu_exp > dsp_exp+1)
712 dspmmu_exp = dsp_exp+1;
713 if (tc_exp < arm_exp)
714 tc_exp = arm_exp;
715 if (tc_exp < dspmmu_exp)
716 tc_exp = dspmmu_exp;
717 if (tc_exp > lcd_exp)
718 lcd_exp = tc_exp;
719 if (tc_exp > per_exp)
720 per_exp = tc_exp;
721
722 newval &= 0xf000;
723 newval |= per_exp << CKCTL_PERDIV_OFFSET;
724 newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
725 newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
726 newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
727 newval |= tc_exp << CKCTL_TCDIV_OFFSET;
728 newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
729
730 return newval;
731}
732
733
734static int calc_dsor_exp(struct clk *clk, unsigned long rate)
735{
736 /* Note: If target frequency is too low, this function will return 4,
737 * which is invalid value. Caller must check for this value and act
738 * accordingly.
739 *
740 * Note: This function does not check for following limitations set
741 * by the hardware (all conditions must be true):
742 * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
743 * ARM_CK >= TC_CK
744 * DSP_CK >= TC_CK
745 * DSPMMU_CK >= TC_CK
746 */
747 unsigned long realrate;
748 struct clk * parent;
749 unsigned dsor_exp;
750
751 if (unlikely(!(clk->flags & RATE_CKCTL)))
752 return -EINVAL;
753
754 parent = clk->parent;
755 if (unlikely(parent == 0))
756 return -EIO;
757
758 realrate = parent->rate;
759 for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
760 if (realrate <= rate)
761 break;
762
763 realrate /= 2;
764 }
765
766 return dsor_exp;
767}
768
769long clk_round_rate(struct clk *clk, unsigned long rate)
770{
771 int dsor_exp;
772
773 if (clk->flags & RATE_FIXED)
774 return clk->rate;
775
776 if (clk->flags & RATE_CKCTL) {
777 dsor_exp = calc_dsor_exp(clk, rate);
778 if (dsor_exp < 0)
779 return dsor_exp;
780 if (dsor_exp > 3)
781 dsor_exp = 3;
782 return clk->parent->rate / (1 << dsor_exp);
783 }
784
785 if(clk->round_rate != 0)
786 return clk->round_rate(clk, rate);
787
788 return clk->rate;
789}
790EXPORT_SYMBOL(clk_round_rate);
791
792
793static void propagate_rate(struct clk * clk)
794{
795 struct clk ** clkp;
796
797 for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
798 if (likely((*clkp)->parent != clk)) continue;
799 if (likely((*clkp)->recalc))
800 (*clkp)->recalc(*clkp);
801 }
802}
803
804
805static int select_table_rate(struct clk * clk, unsigned long rate)
806{
807 /* Find the highest supported frequency <= rate and switch to it */
808 struct mpu_rate * ptr;
809
810 if (clk != &virtual_ck_mpu)
811 return -EINVAL;
812
813 for (ptr = rate_table; ptr->rate; ptr++) {
814 if (ptr->xtal != ck_ref.rate)
815 continue;
816
817 /* DPLL1 cannot be reprogrammed without risking system crash */
818 if (likely(ck_dpll1.rate!=0) && ptr->pll_rate != ck_dpll1.rate)
819 continue;
820
821 /* Can check only after xtal frequency check */
822 if (ptr->rate <= rate)
823 break;
824 }
825
826 if (!ptr->rate)
827 return -EINVAL;
828
829 if (unlikely(ck_dpll1.rate == 0)) {
830 omap_writew(ptr->dpllctl_val, DPLL_CTL);
831 ck_dpll1.rate = ptr->pll_rate;
832 }
833 omap_writew(ptr->ckctl_val, ARM_CKCTL);
834 propagate_rate(&ck_dpll1);
835 return 0;
836}
837
838
839static long round_to_table_rate(struct clk * clk, unsigned long rate)
840{
841 /* Find the highest supported frequency <= rate */
842 struct mpu_rate * ptr;
843 long highest_rate;
844
845 if (clk != &virtual_ck_mpu)
846 return -EINVAL;
847
848 highest_rate = -EINVAL;
849
850 for (ptr = rate_table; ptr->rate; ptr++) {
851 if (ptr->xtal != ck_ref.rate)
852 continue;
853
854 highest_rate = ptr->rate;
855
856 /* Can check only after xtal frequency check */
857 if (ptr->rate <= rate)
858 break;
859 }
860
861 return highest_rate;
862}
863
864
865int clk_set_rate(struct clk *clk, unsigned long rate)
866{
867 int ret = -EINVAL;
868 int dsor_exp;
869 __u16 regval;
870 unsigned long flags;
871
872 if (clk->flags & RATE_CKCTL) {
873 dsor_exp = calc_dsor_exp(clk, rate);
874 if (dsor_exp > 3)
875 dsor_exp = -EINVAL;
876 if (dsor_exp < 0)
877 return dsor_exp;
878
879 spin_lock_irqsave(&clockfw_lock, flags);
880 regval = omap_readw(ARM_CKCTL);
881 regval &= ~(3 << clk->rate_offset);
882 regval |= dsor_exp << clk->rate_offset;
883 regval = verify_ckctl_value(regval);
884 omap_writew(regval, ARM_CKCTL);
885 clk->rate = clk->parent->rate / (1 << dsor_exp);
886 spin_unlock_irqrestore(&clockfw_lock, flags);
887 ret = 0;
888 } else if(clk->set_rate != 0) {
889 spin_lock_irqsave(&clockfw_lock, flags);
890 ret = clk->set_rate(clk, rate);
891 spin_unlock_irqrestore(&clockfw_lock, flags);
892 }
893
894 if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
895 propagate_rate(clk);
896
897 return ret;
898}
899EXPORT_SYMBOL(clk_set_rate);
900
901
902static unsigned calc_ext_dsor(unsigned long rate)
903{
904 unsigned dsor;
905
906 /* MCLK and BCLK divisor selection is not linear:
907 * freq = 96MHz / dsor
908 *
909 * RATIO_SEL range: dsor <-> RATIO_SEL
910 * 0..6: (RATIO_SEL+2) <-> (dsor-2)
911 * 6..48: (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6)
912 * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
913 * can not be used.
914 */
915 for (dsor = 2; dsor < 96; ++dsor) {
916 if ((dsor & 1) && dsor > 8)
917 continue;
918 if (rate >= 96000000 / dsor)
919 break;
920 }
921 return dsor;
922}
923
924
925static int set_ext_clk_rate(struct clk * clk, unsigned long rate)
926{
927 unsigned dsor;
928 __u16 ratio_bits;
929
930 dsor = calc_ext_dsor(rate);
931 clk->rate = 96000000 / dsor;
932 if (dsor > 8)
933 ratio_bits = ((dsor - 8) / 2 + 6) << 2;
934 else
935 ratio_bits = (dsor - 2) << 2;
936
937 ratio_bits |= omap_readw(clk->enable_reg) & ~0xfd;
938 omap_writew(ratio_bits, clk->enable_reg);
939
940 return 0;
941}
942
943
944static long round_ext_clk_rate(struct clk * clk, unsigned long rate)
945{
946 return 96000000 / calc_ext_dsor(rate);
947}
948
949
950static void init_ext_clk(struct clk * clk)
951{
952 unsigned dsor;
953 __u16 ratio_bits;
954
955 /* Determine current rate and ensure clock is based on 96MHz APLL */
956 ratio_bits = omap_readw(clk->enable_reg) & ~1;
957 omap_writew(ratio_bits, clk->enable_reg);
958
959 ratio_bits = (ratio_bits & 0xfc) >> 2;
960 if (ratio_bits > 6)
961 dsor = (ratio_bits - 6) * 2 + 8;
962 else
963 dsor = ratio_bits + 2;
964
965 clk-> rate = 96000000 / dsor;
966}
967
968
969int clk_register(struct clk *clk)
970{
971 down(&clocks_sem);
972 list_add(&clk->node, &clocks);
973 if (clk->init)
974 clk->init(clk);
975 up(&clocks_sem);
976 return 0;
977}
978EXPORT_SYMBOL(clk_register);
979
980void clk_unregister(struct clk *clk)
981{
982 down(&clocks_sem);
983 list_del(&clk->node);
984 up(&clocks_sem);
985}
986EXPORT_SYMBOL(clk_unregister);
987
988
989
990int __init clk_init(void)
991{
992 struct clk ** clkp;
993 const struct omap_clock_config *info;
994 int crystal_type = 0; /* Default 12 MHz */
995
996 for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
997 if (((*clkp)->flags &CLOCK_IN_OMAP1510) && cpu_is_omap1510()) {
998 clk_register(*clkp);
999 continue;
1000 }
1001
1002 if (((*clkp)->flags &CLOCK_IN_OMAP16XX) && cpu_is_omap16xx()) {
1003 clk_register(*clkp);
1004 continue;
1005 }
1006
1007 if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) {
1008 clk_register(*clkp);
1009 continue;
1010 }
1011 }
1012
1013 info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
1014 if (info != NULL) {
1015 if (!cpu_is_omap1510())
1016 crystal_type = info->system_clock_type;
1017 }
1018
1019#if defined(CONFIG_ARCH_OMAP730)
1020 ck_ref.rate = 13000000;
1021#elif defined(CONFIG_ARCH_OMAP16XX)
1022 if (crystal_type == 2)
1023 ck_ref.rate = 19200000;
1024#endif
1025
1026 /* We want to be in syncronous scalable mode */
1027 omap_writew(0x1000, ARM_SYSST);
1028
1029 /* Find the highest supported frequency and enable it */
1030 if (select_table_rate(&virtual_ck_mpu, ~0)) {
1031 printk(KERN_ERR "System frequencies not set. Check your config.\n");
1032 /* Guess sane values (60MHz) */
1033 omap_writew(0x2290, DPLL_CTL);
1034 omap_writew(0x1005, ARM_CKCTL);
1035 ck_dpll1.rate = 60000000;
1036 propagate_rate(&ck_dpll1);
1037 printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): %ld/%ld/%ld\n",
1038 ck_ref.rate, ck_dpll1.rate, arm_ck.rate);
1039 }
1040
1041 /* Cache rates for clocks connected to ck_ref (not dpll1) */
1042 propagate_rate(&ck_ref);
1043
1044#ifdef CONFIG_MACH_OMAP_PERSEUS2
1045 /* Select slicer output as OMAP input clock */
1046 omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
1047#endif
1048
1049 /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
1050 omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
1051
1052 /* Put DSP/MPUI into reset until needed */
1053 omap_writew(0, ARM_RSTCT1);
1054 omap_writew(1, ARM_RSTCT2);
1055 omap_writew(0x400, ARM_IDLECT1);
1056
1057 /*
1058 * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
1059 * of the ARM_IDLECT2 register must be set to zero. The power-on
1060 * default value of this bit is one.
1061 */
1062 omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */
1063
1064 /*
1065 * Only enable those clocks we will need, let the drivers
1066 * enable other clocks as necessary
1067 */
1068 clk_use(&armper_ck);
1069 clk_use(&armxor_ck);
1070 clk_use(&armtim_ck);
1071
1072 if (cpu_is_omap1510())
1073 clk_enable(&arm_gpio_ck);
1074
1075 return 0;
1076}
diff --git a/arch/arm/mach-omap/clock.h b/arch/arm/mach-omap/clock.h
new file mode 100644
index 000000000000..08c0ddde1835
--- /dev/null
+++ b/arch/arm/mach-omap/clock.h
@@ -0,0 +1,112 @@
1/*
2 * linux/arch/arm/mach-omap/clock.h
3 *
4 * Copyright (C) 2004 Nokia corporation
5 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
6 * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
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#ifndef __ARCH_ARM_OMAP_CLOCK_H
14#define __ARCH_ARM_OMAP_CLOCK_H
15
16struct module;
17
18struct clk {
19 struct list_head node;
20 struct module *owner;
21 const char *name;
22 struct clk *parent;
23 unsigned long rate;
24 __s8 usecount;
25 __u16 flags;
26 __u32 enable_reg;
27 __u8 enable_bit;
28 __u8 rate_offset;
29 void (*recalc)(struct clk *);
30 int (*set_rate)(struct clk *, unsigned long);
31 long (*round_rate)(struct clk *, unsigned long);
32 void (*init)(struct clk *);
33};
34
35
36struct mpu_rate {
37 unsigned long rate;
38 unsigned long xtal;
39 unsigned long pll_rate;
40 __u16 ckctl_val;
41 __u16 dpllctl_val;
42};
43
44
45/* Clock flags */
46#define RATE_CKCTL 1
47#define RATE_FIXED 2
48#define RATE_PROPAGATES 4
49#define VIRTUAL_CLOCK 8
50#define ALWAYS_ENABLED 16
51#define ENABLE_REG_32BIT 32
52#define CLOCK_IN_OMAP16XX 64
53#define CLOCK_IN_OMAP1510 128
54#define CLOCK_IN_OMAP730 256
55
56/* ARM_CKCTL bit shifts */
57#define CKCTL_PERDIV_OFFSET 0
58#define CKCTL_LCDDIV_OFFSET 2
59#define CKCTL_ARMDIV_OFFSET 4
60#define CKCTL_DSPDIV_OFFSET 6
61#define CKCTL_TCDIV_OFFSET 8
62#define CKCTL_DSPMMUDIV_OFFSET 10
63/*#define ARM_TIMXO 12*/
64#define EN_DSPCK 13
65/*#define ARM_INTHCK_SEL 14*/ /* Divide-by-2 for mpu inth_ck */
66
67/* ARM_IDLECT1 bit shifts */
68/*#define IDLWDT_ARM 0*/
69/*#define IDLXORP_ARM 1*/
70/*#define IDLPER_ARM 2*/
71/*#define IDLLCD_ARM 3*/
72/*#define IDLLB_ARM 4*/
73/*#define IDLHSAB_ARM 5*/
74/*#define IDLIF_ARM 6*/
75/*#define IDLDPLL_ARM 7*/
76/*#define IDLAPI_ARM 8*/
77/*#define IDLTIM_ARM 9*/
78/*#define SETARM_IDLE 11*/
79
80/* ARM_IDLECT2 bit shifts */
81#define EN_WDTCK 0
82#define EN_XORPCK 1
83#define EN_PERCK 2
84#define EN_LCDCK 3
85#define EN_LBCK 4 /* Not on 1610/1710 */
86/*#define EN_HSABCK 5*/
87#define EN_APICK 6
88#define EN_TIMCK 7
89#define DMACK_REQ 8
90#define EN_GPIOCK 9 /* Not on 1610/1710 */
91/*#define EN_LBFREECK 10*/
92#define EN_CKOUT_ARM 11
93
94/* ARM_IDLECT3 bit shifts */
95#define EN_OCPI_CK 0
96#define EN_TC1_CK 2
97#define EN_TC2_CK 4
98
99/* Various register defines for clock controls scattered around OMAP chip */
100#define USB_MCLK_EN_BIT 4 /* In ULPD_CLKC_CTRL */
101#define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */
102#define SWD_ULPD_PLL_CLK_REQ 1 /* In SWD_CLK_DIV_CTRL_SEL */
103#define COM_ULPD_PLL_CLK_REQ 1 /* In COM_CLK_DIV_CTRL_SEL */
104#define SWD_CLK_DIV_CTRL_SEL 0xfffe0874
105#define COM_CLK_DIV_CTRL_SEL 0xfffe0878
106
107
108int clk_register(struct clk *clk);
109void clk_unregister(struct clk *clk);
110int clk_init(void);
111
112#endif
diff --git a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c
new file mode 100644
index 000000000000..265cde48586f
--- /dev/null
+++ b/arch/arm/mach-omap/common.c
@@ -0,0 +1,549 @@
1/*
2 * linux/arch/arm/mach-omap/common.c
3 *
4 * Code common to all OMAP machines.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/config.h>
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/delay.h>
15#include <linux/pm.h>
16#include <linux/console.h>
17#include <linux/serial.h>
18#include <linux/tty.h>
19#include <linux/serial_8250.h>
20#include <linux/serial_reg.h>
21
22#include <asm/hardware.h>
23#include <asm/system.h>
24#include <asm/pgtable.h>
25#include <asm/mach/map.h>
26#include <asm/hardware/clock.h>
27#include <asm/io.h>
28#include <asm/mach-types.h>
29
30#include <asm/arch/board.h>
31#include <asm/arch/mux.h>
32#include <asm/arch/fpga.h>
33
34#include "clock.h"
35
36#define DEBUG 1
37
38struct omap_id {
39 u16 jtag_id; /* Used to determine OMAP type */
40 u8 die_rev; /* Processor revision */
41 u32 omap_id; /* OMAP revision */
42 u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */
43};
44
45/* Register values to detect the OMAP version */
46static struct omap_id omap_ids[] __initdata = {
47 { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
48 { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
49 { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
50 { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
51 { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
52 { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00},
53 { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00},
54 { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
55 { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
56 { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000},
57 { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00},
58 { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00},
59 { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300},
60 { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300},
61 { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300},
62 { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000},
63 { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000},
64 { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000},
65};
66
67/*
68 * Get OMAP type from PROD_ID.
69 * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM.
70 * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense.
71 * Undocumented register in TEST BLOCK is used as fallback; This seems to
72 * work on 1510, 1610 & 1710. The official way hopefully will work in future
73 * processors.
74 */
75static u16 __init omap_get_jtag_id(void)
76{
77 u32 prod_id, omap_id;
78
79 prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
80 omap_id = omap_readl(OMAP32_ID_1);
81
82 /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */
83 if (((prod_id >> 20) == 0) || (prod_id == omap_id))
84 prod_id = 0;
85 else
86 prod_id &= 0xffff;
87
88 if (prod_id)
89 return prod_id;
90
91 /* Use OMAP32_ID_1 as fallback */
92 prod_id = ((omap_id >> 12) & 0xffff);
93
94 return prod_id;
95}
96
97/*
98 * Get OMAP revision from DIE_REV.
99 * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID.
100 * Undocumented register in the TEST BLOCK is used as fallback.
101 * REVISIT: This does not seem to work on 1510
102 */
103static u8 __init omap_get_die_rev(void)
104{
105 u32 die_rev;
106
107 die_rev = omap_readl(OMAP_DIE_ID_1);
108
109 /* Check for broken OMAP_DIE_ID on early 1710 */
110 if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id())
111 die_rev = 0;
112
113 die_rev = (die_rev >> 17) & 0xf;
114 if (die_rev)
115 return die_rev;
116
117 die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf;
118
119 return die_rev;
120}
121
122static void __init omap_check_revision(void)
123{
124 int i;
125 u16 jtag_id;
126 u8 die_rev;
127 u32 omap_id;
128 u8 cpu_type;
129
130 jtag_id = omap_get_jtag_id();
131 die_rev = omap_get_die_rev();
132 omap_id = omap_readl(OMAP32_ID_0);
133
134#ifdef DEBUG
135 printk("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0));
136 printk("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n",
137 omap_readl(OMAP_DIE_ID_1),
138 (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf);
139 printk("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0));
140 printk("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n",
141 omap_readl(OMAP_PRODUCTION_ID_1),
142 omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff);
143 printk("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0));
144 printk("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1));
145 printk("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev);
146#endif
147
148 system_serial_high = omap_readl(OMAP_DIE_ID_0);
149 system_serial_low = omap_readl(OMAP_DIE_ID_1);
150
151 /* First check only the major version in a safe way */
152 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
153 if (jtag_id == (omap_ids[i].jtag_id)) {
154 system_rev = omap_ids[i].type;
155 break;
156 }
157 }
158
159 /* Check if we can find the die revision */
160 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
161 if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) {
162 system_rev = omap_ids[i].type;
163 break;
164 }
165 }
166
167 /* Finally check also the omap_id */
168 for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
169 if (jtag_id == omap_ids[i].jtag_id
170 && die_rev == omap_ids[i].die_rev
171 && omap_id == omap_ids[i].omap_id) {
172 system_rev = omap_ids[i].type;
173 break;
174 }
175 }
176
177 /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */
178 cpu_type = system_rev >> 24;
179
180 switch (cpu_type) {
181 case 0x07:
182 system_rev |= 0x07;
183 break;
184 case 0x15:
185 system_rev |= 0x15;
186 break;
187 case 0x16:
188 case 0x17:
189 system_rev |= 0x16;
190 break;
191 case 0x24:
192 system_rev |= 0x24;
193 break;
194 default:
195 printk("Unknown OMAP cpu type: 0x%02x\n", cpu_type);
196 }
197
198 printk("OMAP%04x", system_rev >> 16);
199 if ((system_rev >> 8) & 0xff)
200 printk("%x", (system_rev >> 8) & 0xff);
201 printk(" revision %i handled as %02xxx id: %08x%08x\n",
202 die_rev, system_rev & 0xff, system_serial_low,
203 system_serial_high);
204}
205
206/*
207 * ----------------------------------------------------------------------------
208 * OMAP I/O mapping
209 *
210 * The machine specific code may provide the extra mapping besides the
211 * default mapping provided here.
212 * ----------------------------------------------------------------------------
213 */
214
215static struct map_desc omap_io_desc[] __initdata = {
216 { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
217};
218
219#ifdef CONFIG_ARCH_OMAP730
220static struct map_desc omap730_io_desc[] __initdata = {
221 { OMAP730_DSP_BASE, OMAP730_DSP_START, OMAP730_DSP_SIZE, MT_DEVICE },
222 { OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE },
223 { OMAP730_SRAM_BASE, OMAP730_SRAM_START, OMAP730_SRAM_SIZE, MT_DEVICE }
224};
225#endif
226
227#ifdef CONFIG_ARCH_OMAP1510
228static struct map_desc omap1510_io_desc[] __initdata = {
229 { OMAP1510_DSP_BASE, OMAP1510_DSP_START, OMAP1510_DSP_SIZE, MT_DEVICE },
230 { OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE },
231 { OMAP1510_SRAM_BASE, OMAP1510_SRAM_START, OMAP1510_SRAM_SIZE, MT_DEVICE }
232};
233#endif
234
235#if defined(CONFIG_ARCH_OMAP16XX)
236static struct map_desc omap1610_io_desc[] __initdata = {
237 { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
238 { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
239 { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE }
240};
241
242static struct map_desc omap5912_io_desc[] __initdata = {
243 { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE },
244 { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
245/*
246 * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page
247 * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped.
248 * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte
249 * can be used.
250 */
251 { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE }
252};
253#endif
254
255static int initialized = 0;
256
257static void __init _omap_map_io(void)
258{
259 initialized = 1;
260
261 /* We have to initialize the IO space mapping before we can run
262 * cpu_is_omapxxx() macros. */
263 iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
264 omap_check_revision();
265
266#ifdef CONFIG_ARCH_OMAP730
267 if (cpu_is_omap730()) {
268 iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
269 }
270#endif
271#ifdef CONFIG_ARCH_OMAP1510
272 if (cpu_is_omap1510()) {
273 iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
274 }
275#endif
276#if defined(CONFIG_ARCH_OMAP16XX)
277 if (cpu_is_omap1610() || cpu_is_omap1710()) {
278 iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
279 }
280 if (cpu_is_omap5912()) {
281 iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
282 }
283#endif
284
285 /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
286 * on a Posted Write in the TIPB Bridge".
287 */
288 omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL);
289 omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL);
290
291 /* Must init clocks early to assure that timer interrupt works
292 */
293 clk_init();
294}
295
296/*
297 * This should only get called from board specific init
298 */
299void omap_map_io(void)
300{
301 if (!initialized)
302 _omap_map_io();
303}
304
305static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
306 int offset)
307{
308 offset <<= up->regshift;
309 return (unsigned int)__raw_readb(up->membase + offset);
310}
311
312static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset,
313 int value)
314{
315 offset <<= p->regshift;
316 __raw_writeb(value, p->membase + offset);
317}
318
319/*
320 * Internal UARTs need to be initialized for the 8250 autoconfig to work
321 * properly. Note that the TX watermark initialization may not be needed
322 * once the 8250.c watermark handling code is merged.
323 */
324static void __init omap_serial_reset(struct plat_serial8250_port *p)
325{
326 omap_serial_outp(p, UART_OMAP_MDR1, 0x07); /* disable UART */
327 omap_serial_outp(p, UART_OMAP_SCR, 0x08); /* TX watermark */
328 omap_serial_outp(p, UART_OMAP_MDR1, 0x00); /* enable UART */
329
330 if (!cpu_is_omap1510()) {
331 omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
332 while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01));
333 }
334}
335
336static struct plat_serial8250_port serial_platform_data[] = {
337 {
338 .membase = (char*)IO_ADDRESS(OMAP_UART1_BASE),
339 .mapbase = (unsigned long)OMAP_UART1_BASE,
340 .irq = INT_UART1,
341 .flags = UPF_BOOT_AUTOCONF,
342 .iotype = UPIO_MEM,
343 .regshift = 2,
344 .uartclk = OMAP16XX_BASE_BAUD * 16,
345 },
346 {
347 .membase = (char*)IO_ADDRESS(OMAP_UART2_BASE),
348 .mapbase = (unsigned long)OMAP_UART2_BASE,
349 .irq = INT_UART2,
350 .flags = UPF_BOOT_AUTOCONF,
351 .iotype = UPIO_MEM,
352 .regshift = 2,
353 .uartclk = OMAP16XX_BASE_BAUD * 16,
354 },
355 {
356 .membase = (char*)IO_ADDRESS(OMAP_UART3_BASE),
357 .mapbase = (unsigned long)OMAP_UART3_BASE,
358 .irq = INT_UART3,
359 .flags = UPF_BOOT_AUTOCONF,
360 .iotype = UPIO_MEM,
361 .regshift = 2,
362 .uartclk = OMAP16XX_BASE_BAUD * 16,
363 },
364 { },
365};
366
367static struct platform_device serial_device = {
368 .name = "serial8250",
369 .id = 0,
370 .dev = {
371 .platform_data = serial_platform_data,
372 },
373};
374
375/*
376 * Note that on Innovator-1510 UART2 pins conflict with USB2.
377 * By default UART2 does not work on Innovator-1510 if you have
378 * USB OHCI enabled. To use UART2, you must disable USB2 first.
379 */
380void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
381{
382 int i;
383
384 if (cpu_is_omap730()) {
385 serial_platform_data[0].regshift = 0;
386 serial_platform_data[1].regshift = 0;
387 serial_platform_data[0].irq = INT_730_UART_MODEM_1;
388 serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2;
389 }
390
391 if (cpu_is_omap1510()) {
392 serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
393 serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
394 serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
395 }
396
397 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
398 unsigned char reg;
399
400 if (ports[i] == 0) {
401 serial_platform_data[i].membase = 0;
402 serial_platform_data[i].mapbase = 0;
403 continue;
404 }
405
406 switch (i) {
407 case 0:
408 if (cpu_is_omap1510()) {
409 omap_cfg_reg(UART1_TX);
410 omap_cfg_reg(UART1_RTS);
411 if (machine_is_omap_innovator()) {
412 reg = fpga_read(OMAP1510_FPGA_POWER);
413 reg |= OMAP1510_FPGA_PCR_COM1_EN;
414 fpga_write(reg, OMAP1510_FPGA_POWER);
415 udelay(10);
416 }
417 }
418 break;
419 case 1:
420 if (cpu_is_omap1510()) {
421 omap_cfg_reg(UART2_TX);
422 omap_cfg_reg(UART2_RTS);
423 if (machine_is_omap_innovator()) {
424 reg = fpga_read(OMAP1510_FPGA_POWER);
425 reg |= OMAP1510_FPGA_PCR_COM2_EN;
426 fpga_write(reg, OMAP1510_FPGA_POWER);
427 udelay(10);
428 }
429 }
430 break;
431 case 2:
432 if (cpu_is_omap1510()) {
433 omap_cfg_reg(UART3_TX);
434 omap_cfg_reg(UART3_RX);
435 }
436 if (cpu_is_omap1710()) {
437 clk_enable(clk_get(0, "uart3_ck"));
438 }
439 break;
440 }
441 omap_serial_reset(&serial_platform_data[i]);
442 }
443}
444
445static int __init omap_init(void)
446{
447 return platform_device_register(&serial_device);
448}
449arch_initcall(omap_init);
450
451#define NO_LENGTH_CHECK 0xffffffff
452
453extern int omap_bootloader_tag_len;
454extern u8 omap_bootloader_tag[];
455
456struct omap_board_config_kernel *omap_board_config;
457int omap_board_config_size = 0;
458
459static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
460{
461 struct omap_board_config_kernel *kinfo = NULL;
462 int i;
463
464#ifdef CONFIG_OMAP_BOOT_TAG
465 struct omap_board_config_entry *info = NULL;
466
467 if (omap_bootloader_tag_len > 4)
468 info = (struct omap_board_config_entry *) omap_bootloader_tag;
469 while (info != NULL) {
470 u8 *next;
471
472 if (info->tag == tag) {
473 if (skip == 0)
474 break;
475 skip--;
476 }
477
478 if ((info->len & 0x03) != 0) {
479 /* We bail out to avoid an alignment fault */
480 printk(KERN_ERR "OMAP peripheral config: Length (%d) not word-aligned (tag %04x)\n",
481 info->len, info->tag);
482 return NULL;
483 }
484 next = (u8 *) info + sizeof(*info) + info->len;
485 if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
486 info = NULL;
487 else
488 info = (struct omap_board_config_entry *) next;
489 }
490 if (info != NULL) {
491 /* Check the length as a lame attempt to check for
492 * binary inconsistancy. */
493 if (len != NO_LENGTH_CHECK) {
494 /* Word-align len */
495 if (len & 0x03)
496 len = (len + 3) & ~0x03;
497 if (info->len != len) {
498 printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
499 tag, len, info->len);
500 return NULL;
501 }
502 }
503 if (len_out != NULL)
504 *len_out = info->len;
505 return info->data;
506 }
507#endif
508 /* Try to find the config from the board-specific structures
509 * in the kernel. */
510 for (i = 0; i < omap_board_config_size; i++) {
511 if (omap_board_config[i].tag == tag) {
512 kinfo = &omap_board_config[i];
513 break;
514 }
515 }
516 if (kinfo == NULL)
517 return NULL;
518 return kinfo->data;
519}
520
521const void *__omap_get_config(u16 tag, size_t len, int nr)
522{
523 return get_config(tag, len, nr, NULL);
524}
525EXPORT_SYMBOL(__omap_get_config);
526
527const void *omap_get_var_config(u16 tag, size_t *len)
528{
529 return get_config(tag, NO_LENGTH_CHECK, 0, len);
530}
531EXPORT_SYMBOL(omap_get_var_config);
532
533static int __init omap_add_serial_console(void)
534{
535 const struct omap_uart_config *info;
536
537 info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
538 if (info != NULL && info->console_uart) {
539 static char speed[11], *opt = NULL;
540
541 if (info->console_speed) {
542 snprintf(speed, sizeof(speed), "%u", info->console_speed);
543 opt = speed;
544 }
545 return add_preferred_console("ttyS", info->console_uart - 1, opt);
546 }
547 return 0;
548}
549console_initcall(omap_add_serial_console);
diff --git a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h
new file mode 100644
index 000000000000..9f62858c0df4
--- /dev/null
+++ b/arch/arm/mach-omap/common.h
@@ -0,0 +1,36 @@
1/*
2 * linux/arch/arm/mach-omap/common.h
3 *
4 * Header for code common to all OMAP machines.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
14 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
17 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
20 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#ifndef __ARCH_ARM_MACH_OMAP_COMMON_H
28#define __ARCH_ARM_MACH_OMAP_COMMON_H
29
30struct sys_timer;
31
32extern void omap_map_io(void);
33extern struct sys_timer omap_timer;
34extern void omap_serial_init(int ports[]);
35
36#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
diff --git a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c
new file mode 100644
index 000000000000..7a9ebe80d6f8
--- /dev/null
+++ b/arch/arm/mach-omap/dma.c
@@ -0,0 +1,1086 @@
1/*
2 * linux/arch/arm/omap/dma.c
3 *
4 * Copyright (C) 2003 Nokia Corporation
5 * Author: Juha Yrjölä <juha.yrjola@nokia.com>
6 * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
7 * Graphics DMA and LCD DMA graphics tranformations
8 * by Imre Deak <imre.deak@nokia.com>
9 * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
10 *
11 * Support functions for the OMAP internal DMA channels.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/sched.h>
22#include <linux/spinlock.h>
23#include <linux/errno.h>
24#include <linux/interrupt.h>
25
26#include <asm/system.h>
27#include <asm/irq.h>
28#include <asm/hardware.h>
29#include <asm/dma.h>
30#include <asm/io.h>
31
32#include <asm/arch/tc.h>
33
34#define OMAP_DMA_ACTIVE 0x01
35
36#define OMAP_DMA_CCR_EN (1 << 7)
37
38#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
39
40static int enable_1510_mode = 0;
41
42struct omap_dma_lch {
43 int next_lch;
44 int dev_id;
45 u16 saved_csr;
46 u16 enabled_irqs;
47 const char *dev_name;
48 void (* callback)(int lch, u16 ch_status, void *data);
49 void *data;
50 long flags;
51};
52
53static int dma_chan_count;
54
55static spinlock_t dma_chan_lock;
56static struct omap_dma_lch dma_chan[OMAP_LOGICAL_DMA_CH_COUNT];
57
58const static u8 dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = {
59 INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
60 INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
61 INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10,
62 INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13,
63 INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD
64};
65
66static inline int get_gdma_dev(int req)
67{
68 u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
69 int shift = ((req - 1) % 5) * 6;
70
71 return ((omap_readl(reg) >> shift) & 0x3f) + 1;
72}
73
74static inline void set_gdma_dev(int req, int dev)
75{
76 u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
77 int shift = ((req - 1) % 5) * 6;
78 u32 l;
79
80 l = omap_readl(reg);
81 l &= ~(0x3f << shift);
82 l |= (dev - 1) << shift;
83 omap_writel(l, reg);
84}
85
86static void clear_lch_regs(int lch)
87{
88 int i;
89 u32 lch_base = OMAP_DMA_BASE + lch * 0x40;
90
91 for (i = 0; i < 0x2c; i += 2)
92 omap_writew(0, lch_base + i);
93}
94
95void omap_set_dma_priority(int dst_port, int priority)
96{
97 unsigned long reg;
98 u32 l;
99
100 switch (dst_port) {
101 case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */
102 reg = OMAP_TC_OCPT1_PRIOR;
103 break;
104 case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */
105 reg = OMAP_TC_OCPT2_PRIOR;
106 break;
107 case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */
108 reg = OMAP_TC_EMIFF_PRIOR;
109 break;
110 case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */
111 reg = OMAP_TC_EMIFS_PRIOR;
112 break;
113 default:
114 BUG();
115 return;
116 }
117 l = omap_readl(reg);
118 l &= ~(0xf << 8);
119 l |= (priority & 0xf) << 8;
120 omap_writel(l, reg);
121}
122
123void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
124 int frame_count, int sync_mode)
125{
126 u16 w;
127
128 w = omap_readw(OMAP_DMA_CSDP(lch));
129 w &= ~0x03;
130 w |= data_type;
131 omap_writew(w, OMAP_DMA_CSDP(lch));
132
133 w = omap_readw(OMAP_DMA_CCR(lch));
134 w &= ~(1 << 5);
135 if (sync_mode == OMAP_DMA_SYNC_FRAME)
136 w |= 1 << 5;
137 omap_writew(w, OMAP_DMA_CCR(lch));
138
139 w = omap_readw(OMAP_DMA_CCR2(lch));
140 w &= ~(1 << 2);
141 if (sync_mode == OMAP_DMA_SYNC_BLOCK)
142 w |= 1 << 2;
143 omap_writew(w, OMAP_DMA_CCR2(lch));
144
145 omap_writew(elem_count, OMAP_DMA_CEN(lch));
146 omap_writew(frame_count, OMAP_DMA_CFN(lch));
147
148}
149void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
150{
151 u16 w;
152
153 BUG_ON(omap_dma_in_1510_mode());
154
155 w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03;
156 switch (mode) {
157 case OMAP_DMA_CONSTANT_FILL:
158 w |= 0x01;
159 break;
160 case OMAP_DMA_TRANSPARENT_COPY:
161 w |= 0x02;
162 break;
163 case OMAP_DMA_COLOR_DIS:
164 break;
165 default:
166 BUG();
167 }
168 omap_writew(w, OMAP_DMA_CCR2(lch));
169
170 w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f;
171 /* Default is channel type 2D */
172 if (mode) {
173 omap_writew((u16)color, OMAP_DMA_COLOR_L(lch));
174 omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch));
175 w |= 1; /* Channel type G */
176 }
177 omap_writew(w, OMAP_DMA_LCH_CTRL(lch));
178}
179
180
181void omap_set_dma_src_params(int lch, int src_port, int src_amode,
182 unsigned long src_start)
183{
184 u16 w;
185
186 w = omap_readw(OMAP_DMA_CSDP(lch));
187 w &= ~(0x1f << 2);
188 w |= src_port << 2;
189 omap_writew(w, OMAP_DMA_CSDP(lch));
190
191 w = omap_readw(OMAP_DMA_CCR(lch));
192 w &= ~(0x03 << 12);
193 w |= src_amode << 12;
194 omap_writew(w, OMAP_DMA_CCR(lch));
195
196 omap_writew(src_start >> 16, OMAP_DMA_CSSA_U(lch));
197 omap_writew(src_start, OMAP_DMA_CSSA_L(lch));
198}
199
200void omap_set_dma_src_index(int lch, int eidx, int fidx)
201{
202 omap_writew(eidx, OMAP_DMA_CSEI(lch));
203 omap_writew(fidx, OMAP_DMA_CSFI(lch));
204}
205
206void omap_set_dma_src_data_pack(int lch, int enable)
207{
208 u16 w;
209
210 w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(1 << 6);
211 w |= enable ? (1 << 6) : 0;
212 omap_writew(w, OMAP_DMA_CSDP(lch));
213}
214
215void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
216{
217 u16 w;
218
219 w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 7);
220 switch (burst_mode) {
221 case OMAP_DMA_DATA_BURST_DIS:
222 break;
223 case OMAP_DMA_DATA_BURST_4:
224 w |= (0x01 << 7);
225 break;
226 case OMAP_DMA_DATA_BURST_8:
227 /* not supported by current hardware
228 * w |= (0x03 << 7);
229 * fall through
230 */
231 default:
232 BUG();
233 }
234 omap_writew(w, OMAP_DMA_CSDP(lch));
235}
236
237void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
238 unsigned long dest_start)
239{
240 u16 w;
241
242 w = omap_readw(OMAP_DMA_CSDP(lch));
243 w &= ~(0x1f << 9);
244 w |= dest_port << 9;
245 omap_writew(w, OMAP_DMA_CSDP(lch));
246
247 w = omap_readw(OMAP_DMA_CCR(lch));
248 w &= ~(0x03 << 14);
249 w |= dest_amode << 14;
250 omap_writew(w, OMAP_DMA_CCR(lch));
251
252 omap_writew(dest_start >> 16, OMAP_DMA_CDSA_U(lch));
253 omap_writew(dest_start, OMAP_DMA_CDSA_L(lch));
254}
255
256void omap_set_dma_dest_index(int lch, int eidx, int fidx)
257{
258 omap_writew(eidx, OMAP_DMA_CDEI(lch));
259 omap_writew(fidx, OMAP_DMA_CDFI(lch));
260}
261
262void omap_set_dma_dest_data_pack(int lch, int enable)
263{
264 u16 w;
265
266 w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(1 << 13);
267 w |= enable ? (1 << 13) : 0;
268 omap_writew(w, OMAP_DMA_CSDP(lch));
269}
270
271void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
272{
273 u16 w;
274
275 w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 14);
276 switch (burst_mode) {
277 case OMAP_DMA_DATA_BURST_DIS:
278 break;
279 case OMAP_DMA_DATA_BURST_4:
280 w |= (0x01 << 14);
281 break;
282 case OMAP_DMA_DATA_BURST_8:
283 w |= (0x03 << 14);
284 break;
285 default:
286 printk(KERN_ERR "Invalid DMA burst mode\n");
287 BUG();
288 return;
289 }
290 omap_writew(w, OMAP_DMA_CSDP(lch));
291}
292
293static inline void init_intr(int lch)
294{
295 u16 w;
296
297 /* Read CSR to make sure it's cleared. */
298 w = omap_readw(OMAP_DMA_CSR(lch));
299 /* Enable some nice interrupts. */
300 omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch));
301 dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
302}
303
304static inline void enable_lnk(int lch)
305{
306 u16 w;
307
308 /* Clear the STOP_LNK bits */
309 w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
310 w &= ~(1 << 14);
311 omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
312
313 /* And set the ENABLE_LNK bits */
314 if (dma_chan[lch].next_lch != -1)
315 omap_writew(dma_chan[lch].next_lch | (1 << 15),
316 OMAP_DMA_CLNK_CTRL(lch));
317}
318
319static inline void disable_lnk(int lch)
320{
321 u16 w;
322
323 /* Disable interrupts */
324 omap_writew(0, OMAP_DMA_CICR(lch));
325
326 /* Set the STOP_LNK bit */
327 w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
328 w |= (1 << 14);
329 w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
330
331 dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
332}
333
334void omap_start_dma(int lch)
335{
336 u16 w;
337
338 if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
339 int next_lch, cur_lch;
340 char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT];
341
342 dma_chan_link_map[lch] = 1;
343 /* Set the link register of the first channel */
344 enable_lnk(lch);
345
346 memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
347 cur_lch = dma_chan[lch].next_lch;
348 do {
349 next_lch = dma_chan[cur_lch].next_lch;
350
351 /* The loop case: we've been here already */
352 if (dma_chan_link_map[cur_lch])
353 break;
354 /* Mark the current channel */
355 dma_chan_link_map[cur_lch] = 1;
356
357 enable_lnk(cur_lch);
358 init_intr(cur_lch);
359
360 cur_lch = next_lch;
361 } while (next_lch != -1);
362 }
363
364 init_intr(lch);
365
366 w = omap_readw(OMAP_DMA_CCR(lch));
367 w |= OMAP_DMA_CCR_EN;
368 omap_writew(w, OMAP_DMA_CCR(lch));
369 dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
370}
371
372void omap_stop_dma(int lch)
373{
374 u16 w;
375
376 if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
377 int next_lch, cur_lch = lch;
378 char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT];
379
380 memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
381 do {
382 /* The loop case: we've been here already */
383 if (dma_chan_link_map[cur_lch])
384 break;
385 /* Mark the current channel */
386 dma_chan_link_map[cur_lch] = 1;
387
388 disable_lnk(cur_lch);
389
390 next_lch = dma_chan[cur_lch].next_lch;
391 cur_lch = next_lch;
392 } while (next_lch != -1);
393
394 return;
395 }
396 /* Disable all interrupts on the channel */
397 omap_writew(0, OMAP_DMA_CICR(lch));
398
399 w = omap_readw(OMAP_DMA_CCR(lch));
400 w &= ~OMAP_DMA_CCR_EN;
401 omap_writew(w, OMAP_DMA_CCR(lch));
402 dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
403}
404
405void omap_enable_dma_irq(int lch, u16 bits)
406{
407 dma_chan[lch].enabled_irqs |= bits;
408}
409
410void omap_disable_dma_irq(int lch, u16 bits)
411{
412 dma_chan[lch].enabled_irqs &= ~bits;
413}
414
415static int dma_handle_ch(int ch)
416{
417 u16 csr;
418
419 if (enable_1510_mode && ch >= 6) {
420 csr = dma_chan[ch].saved_csr;
421 dma_chan[ch].saved_csr = 0;
422 } else
423 csr = omap_readw(OMAP_DMA_CSR(ch));
424 if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
425 dma_chan[ch + 6].saved_csr = csr >> 7;
426 csr &= 0x7f;
427 }
428 if (!csr)
429 return 0;
430 if (unlikely(dma_chan[ch].dev_id == -1)) {
431 printk(KERN_WARNING "Spurious interrupt from DMA channel %d (CSR %04x)\n",
432 ch, csr);
433 return 0;
434 }
435 if (unlikely(csr & OMAP_DMA_TOUT_IRQ))
436 printk(KERN_WARNING "DMA timeout with device %d\n", dma_chan[ch].dev_id);
437 if (unlikely(csr & OMAP_DMA_DROP_IRQ))
438 printk(KERN_WARNING "DMA synchronization event drop occurred with device %d\n",
439 dma_chan[ch].dev_id);
440 if (likely(csr & OMAP_DMA_BLOCK_IRQ))
441 dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
442 if (likely(dma_chan[ch].callback != NULL))
443 dma_chan[ch].callback(ch, csr, dma_chan[ch].data);
444 return 1;
445}
446
447static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
448{
449 int ch = ((int) dev_id) - 1;
450 int handled = 0;
451
452 for (;;) {
453 int handled_now = 0;
454
455 handled_now += dma_handle_ch(ch);
456 if (enable_1510_mode && dma_chan[ch + 6].saved_csr)
457 handled_now += dma_handle_ch(ch + 6);
458 if (!handled_now)
459 break;
460 handled += handled_now;
461 }
462
463 return handled ? IRQ_HANDLED : IRQ_NONE;
464}
465
466int omap_request_dma(int dev_id, const char *dev_name,
467 void (* callback)(int lch, u16 ch_status, void *data),
468 void *data, int *dma_ch_out)
469{
470 int ch, free_ch = -1;
471 unsigned long flags;
472 struct omap_dma_lch *chan;
473
474 spin_lock_irqsave(&dma_chan_lock, flags);
475 for (ch = 0; ch < dma_chan_count; ch++) {
476 if (free_ch == -1 && dma_chan[ch].dev_id == -1) {
477 free_ch = ch;
478 if (dev_id == 0)
479 break;
480 }
481 }
482 if (free_ch == -1) {
483 spin_unlock_irqrestore(&dma_chan_lock, flags);
484 return -EBUSY;
485 }
486 chan = dma_chan + free_ch;
487 chan->dev_id = dev_id;
488 clear_lch_regs(free_ch);
489 spin_unlock_irqrestore(&dma_chan_lock, flags);
490
491 chan->dev_id = dev_id;
492 chan->dev_name = dev_name;
493 chan->callback = callback;
494 chan->data = data;
495 chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
496
497 if (cpu_is_omap16xx()) {
498 /* If the sync device is set, configure it dynamically. */
499 if (dev_id != 0) {
500 set_gdma_dev(free_ch + 1, dev_id);
501 dev_id = free_ch + 1;
502 }
503 /* Disable the 1510 compatibility mode and set the sync device
504 * id. */
505 omap_writew(dev_id | (1 << 10), OMAP_DMA_CCR(free_ch));
506 } else {
507 omap_writew(dev_id, OMAP_DMA_CCR(free_ch));
508 }
509 *dma_ch_out = free_ch;
510
511 return 0;
512}
513
514void omap_free_dma(int ch)
515{
516 unsigned long flags;
517
518 spin_lock_irqsave(&dma_chan_lock, flags);
519 if (dma_chan[ch].dev_id == -1) {
520 printk("omap_dma: trying to free nonallocated DMA channel %d\n", ch);
521 spin_unlock_irqrestore(&dma_chan_lock, flags);
522 return;
523 }
524 dma_chan[ch].dev_id = -1;
525 spin_unlock_irqrestore(&dma_chan_lock, flags);
526
527 /* Disable all DMA interrupts for the channel. */
528 omap_writew(0, OMAP_DMA_CICR(ch));
529 /* Make sure the DMA transfer is stopped. */
530 omap_writew(0, OMAP_DMA_CCR(ch));
531}
532
533int omap_dma_in_1510_mode(void)
534{
535 return enable_1510_mode;
536}
537
538/*
539 * lch_queue DMA will start right after lch_head one is finished.
540 * For this DMA link to start, you still need to start (see omap_start_dma)
541 * the first one. That will fire up the entire queue.
542 */
543void omap_dma_link_lch (int lch_head, int lch_queue)
544{
545 if (omap_dma_in_1510_mode()) {
546 printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
547 BUG();
548 return;
549 }
550
551 if ((dma_chan[lch_head].dev_id == -1) ||
552 (dma_chan[lch_queue].dev_id == -1)) {
553 printk(KERN_ERR "omap_dma: trying to link non requested channels\n");
554 dump_stack();
555 }
556
557 dma_chan[lch_head].next_lch = lch_queue;
558}
559
560/*
561 * Once the DMA queue is stopped, we can destroy it.
562 */
563void omap_dma_unlink_lch (int lch_head, int lch_queue)
564{
565 if (omap_dma_in_1510_mode()) {
566 printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
567 BUG();
568 return;
569 }
570
571 if (dma_chan[lch_head].next_lch != lch_queue ||
572 dma_chan[lch_head].next_lch == -1) {
573 printk(KERN_ERR "omap_dma: trying to unlink non linked channels\n");
574 dump_stack();
575 }
576
577
578 if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) ||
579 (dma_chan[lch_head].flags & OMAP_DMA_ACTIVE)) {
580 printk(KERN_ERR "omap_dma: You need to stop the DMA channels before unlinking\n");
581 dump_stack();
582 }
583
584 dma_chan[lch_head].next_lch = -1;
585}
586
587
588static struct lcd_dma_info {
589 spinlock_t lock;
590 int reserved;
591 void (* callback)(u16 status, void *data);
592 void *cb_data;
593
594 int active;
595 unsigned long addr, size;
596 int rotate, data_type, xres, yres;
597 int vxres;
598 int mirror;
599 int xscale, yscale;
600 int ext_ctrl;
601 int src_port;
602 int single_transfer;
603} lcd_dma;
604
605void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
606 int data_type)
607{
608 lcd_dma.addr = addr;
609 lcd_dma.data_type = data_type;
610 lcd_dma.xres = fb_xres;
611 lcd_dma.yres = fb_yres;
612}
613
614void omap_set_lcd_dma_src_port(int port)
615{
616 lcd_dma.src_port = port;
617}
618
619void omap_set_lcd_dma_ext_controller(int external)
620{
621 lcd_dma.ext_ctrl = external;
622}
623
624void omap_set_lcd_dma_single_transfer(int single)
625{
626 lcd_dma.single_transfer = single;
627}
628
629
630void omap_set_lcd_dma_b1_rotation(int rotate)
631{
632 if (omap_dma_in_1510_mode()) {
633 printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n");
634 BUG();
635 return;
636 }
637 lcd_dma.rotate = rotate;
638}
639
640void omap_set_lcd_dma_b1_mirror(int mirror)
641{
642 if (omap_dma_in_1510_mode()) {
643 printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n");
644 BUG();
645 }
646 lcd_dma.mirror = mirror;
647}
648
649void omap_set_lcd_dma_b1_vxres(unsigned long vxres)
650{
651 if (omap_dma_in_1510_mode()) {
652 printk(KERN_ERR "DMA virtual resulotion is not supported "
653 "in 1510 mode\n");
654 BUG();
655 }
656 lcd_dma.vxres = vxres;
657}
658
659void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale)
660{
661 if (omap_dma_in_1510_mode()) {
662 printk(KERN_ERR "DMA scale is not supported in 1510 mode\n");
663 BUG();
664 }
665 lcd_dma.xscale = xscale;
666 lcd_dma.yscale = yscale;
667}
668
669static void set_b1_regs(void)
670{
671 unsigned long top, bottom;
672 int es;
673 u16 w;
674 unsigned long en, fn;
675 long ei, fi;
676 unsigned long vxres;
677 unsigned int xscale, yscale;
678
679 switch (lcd_dma.data_type) {
680 case OMAP_DMA_DATA_TYPE_S8:
681 es = 1;
682 break;
683 case OMAP_DMA_DATA_TYPE_S16:
684 es = 2;
685 break;
686 case OMAP_DMA_DATA_TYPE_S32:
687 es = 4;
688 break;
689 default:
690 BUG();
691 return;
692 }
693
694 vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres;
695 xscale = lcd_dma.xscale ? lcd_dma.xscale : 1;
696 yscale = lcd_dma.yscale ? lcd_dma.yscale : 1;
697 BUG_ON(vxres < lcd_dma.xres);
698#define PIXADDR(x,y) (lcd_dma.addr + ((y) * vxres * yscale + (x) * xscale) * es)
699#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1)
700 switch (lcd_dma.rotate) {
701 case 0:
702 if (!lcd_dma.mirror) {
703 top = PIXADDR(0, 0);
704 bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
705 /* 1510 DMA requires the bottom address to be 2 more
706 * than the actual last memory access location. */
707 if (omap_dma_in_1510_mode() &&
708 lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32)
709 bottom += 2;
710 ei = PIXSTEP(0, 0, 1, 0);
711 fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1);
712 } else {
713 top = PIXADDR(lcd_dma.xres - 1, 0);
714 bottom = PIXADDR(0, lcd_dma.yres - 1);
715 ei = PIXSTEP(1, 0, 0, 0);
716 fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1);
717 }
718 en = lcd_dma.xres;
719 fn = lcd_dma.yres;
720 break;
721 case 90:
722 if (!lcd_dma.mirror) {
723 top = PIXADDR(0, lcd_dma.yres - 1);
724 bottom = PIXADDR(lcd_dma.xres - 1, 0);
725 ei = PIXSTEP(0, 1, 0, 0);
726 fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1);
727 } else {
728 top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
729 bottom = PIXADDR(0, 0);
730 ei = PIXSTEP(0, 1, 0, 0);
731 fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1);
732 }
733 en = lcd_dma.yres;
734 fn = lcd_dma.xres;
735 break;
736 case 180:
737 if (!lcd_dma.mirror) {
738 top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
739 bottom = PIXADDR(0, 0);
740 ei = PIXSTEP(1, 0, 0, 0);
741 fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0);
742 } else {
743 top = PIXADDR(0, lcd_dma.yres - 1);
744 bottom = PIXADDR(lcd_dma.xres - 1, 0);
745 ei = PIXSTEP(0, 0, 1, 0);
746 fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0);
747 }
748 en = lcd_dma.xres;
749 fn = lcd_dma.yres;
750 break;
751 case 270:
752 if (!lcd_dma.mirror) {
753 top = PIXADDR(lcd_dma.xres - 1, 0);
754 bottom = PIXADDR(0, lcd_dma.yres - 1);
755 ei = PIXSTEP(0, 0, 0, 1);
756 fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0);
757 } else {
758 top = PIXADDR(0, 0);
759 bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
760 ei = PIXSTEP(0, 0, 0, 1);
761 fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0);
762 }
763 en = lcd_dma.yres;
764 fn = lcd_dma.xres;
765 break;
766 default:
767 BUG();
768 return; /* Supress warning about uninitialized vars */
769 }
770
771 if (omap_dma_in_1510_mode()) {
772 omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U);
773 omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L);
774 omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U);
775 omap_writew(bottom, OMAP1510_DMA_LCD_BOT_F1_L);
776
777 return;
778 }
779
780 /* 1610 regs */
781 omap_writew(top >> 16, OMAP1610_DMA_LCD_TOP_B1_U);
782 omap_writew(top, OMAP1610_DMA_LCD_TOP_B1_L);
783 omap_writew(bottom >> 16, OMAP1610_DMA_LCD_BOT_B1_U);
784 omap_writew(bottom, OMAP1610_DMA_LCD_BOT_B1_L);
785
786 omap_writew(en, OMAP1610_DMA_LCD_SRC_EN_B1);
787 omap_writew(fn, OMAP1610_DMA_LCD_SRC_FN_B1);
788
789 w = omap_readw(OMAP1610_DMA_LCD_CSDP);
790 w &= ~0x03;
791 w |= lcd_dma.data_type;
792 omap_writew(w, OMAP1610_DMA_LCD_CSDP);
793
794 w = omap_readw(OMAP1610_DMA_LCD_CTRL);
795 /* Always set the source port as SDRAM for now*/
796 w &= ~(0x03 << 6);
797 if (lcd_dma.ext_ctrl)
798 w |= 1 << 8;
799 else
800 w &= ~(1 << 8);
801 if (lcd_dma.callback != NULL)
802 w |= 1 << 1; /* Block interrupt enable */
803 else
804 w &= ~(1 << 1);
805 omap_writew(w, OMAP1610_DMA_LCD_CTRL);
806
807 if (!(lcd_dma.rotate || lcd_dma.mirror ||
808 lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale))
809 return;
810
811 w = omap_readw(OMAP1610_DMA_LCD_CCR);
812 /* Set the double-indexed addressing mode */
813 w |= (0x03 << 12);
814 omap_writew(w, OMAP1610_DMA_LCD_CCR);
815
816 omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1);
817 omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U);
818 omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L);
819}
820
821static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
822{
823 u16 w;
824
825 w = omap_readw(OMAP1610_DMA_LCD_CTRL);
826 if (unlikely(!(w & (1 << 3)))) {
827 printk(KERN_WARNING "Spurious LCD DMA IRQ\n");
828 return IRQ_NONE;
829 }
830 /* Ack the IRQ */
831 w |= (1 << 3);
832 omap_writew(w, OMAP1610_DMA_LCD_CTRL);
833 lcd_dma.active = 0;
834 if (lcd_dma.callback != NULL)
835 lcd_dma.callback(w, lcd_dma.cb_data);
836
837 return IRQ_HANDLED;
838}
839
840int omap_request_lcd_dma(void (* callback)(u16 status, void *data),
841 void *data)
842{
843 spin_lock_irq(&lcd_dma.lock);
844 if (lcd_dma.reserved) {
845 spin_unlock_irq(&lcd_dma.lock);
846 printk(KERN_ERR "LCD DMA channel already reserved\n");
847 BUG();
848 return -EBUSY;
849 }
850 lcd_dma.reserved = 1;
851 spin_unlock_irq(&lcd_dma.lock);
852 lcd_dma.callback = callback;
853 lcd_dma.cb_data = data;
854 lcd_dma.active = 0;
855 lcd_dma.single_transfer = 0;
856 lcd_dma.rotate = 0;
857 lcd_dma.vxres = 0;
858 lcd_dma.mirror = 0;
859 lcd_dma.xscale = 0;
860 lcd_dma.yscale = 0;
861 lcd_dma.ext_ctrl = 0;
862 lcd_dma.src_port = 0;
863
864 return 0;
865}
866
867void omap_free_lcd_dma(void)
868{
869 spin_lock(&lcd_dma.lock);
870 if (!lcd_dma.reserved) {
871 spin_unlock(&lcd_dma.lock);
872 printk(KERN_ERR "LCD DMA is not reserved\n");
873 BUG();
874 return;
875 }
876 if (!enable_1510_mode)
877 omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR);
878 lcd_dma.reserved = 0;
879 spin_unlock(&lcd_dma.lock);
880}
881
882void omap_enable_lcd_dma(void)
883{
884 u16 w;
885
886 /* Set the Enable bit only if an external controller is
887 * connected. Otherwise the OMAP internal controller will
888 * start the transfer when it gets enabled.
889 */
890 if (enable_1510_mode || !lcd_dma.ext_ctrl)
891 return;
892 w = omap_readw(OMAP1610_DMA_LCD_CCR);
893 w |= 1 << 7;
894 omap_writew(w, OMAP1610_DMA_LCD_CCR);
895 lcd_dma.active = 1;
896}
897
898void omap_setup_lcd_dma(void)
899{
900 BUG_ON(lcd_dma.active);
901 if (!enable_1510_mode) {
902 /* Set some reasonable defaults */
903 omap_writew(0x5440, OMAP1610_DMA_LCD_CCR);
904 omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP);
905 omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL);
906 }
907 set_b1_regs();
908 if (!enable_1510_mode) {
909 u16 w;
910
911 w = omap_readw(OMAP1610_DMA_LCD_CCR);
912 /* If DMA was already active set the end_prog bit to have
913 * the programmed register set loaded into the active
914 * register set.
915 */
916 w |= 1 << 11; /* End_prog */
917 if (!lcd_dma.single_transfer)
918 w |= (3 << 8); /* Auto_init, repeat */
919 omap_writew(w, OMAP1610_DMA_LCD_CCR);
920 }
921}
922
923void omap_stop_lcd_dma(void)
924{
925 lcd_dma.active = 0;
926 if (!enable_1510_mode && lcd_dma.ext_ctrl)
927 omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~(1 << 7),
928 OMAP1610_DMA_LCD_CCR);
929}
930
931/*
932 * Clears any DMA state so the DMA engine is ready to restart with new buffers
933 * through omap_start_dma(). Any buffers in flight are discarded.
934 */
935void omap_clear_dma(int lch)
936{
937 unsigned long flags;
938 int status;
939
940 local_irq_save(flags);
941 omap_writew(omap_readw(OMAP_DMA_CCR(lch)) & ~OMAP_DMA_CCR_EN,
942 OMAP_DMA_CCR(lch));
943 status = OMAP_DMA_CSR(lch); /* clear pending interrupts */
944 local_irq_restore(flags);
945}
946
947/*
948 * Returns current physical source address for the given DMA channel.
949 * If the channel is running the caller must disable interrupts prior calling
950 * this function and process the returned value before re-enabling interrupt to
951 * prevent races with the interrupt handler. Note that in continuous mode there
952 * is a chance for CSSA_L register overflow inbetween the two reads resulting
953 * in incorrect return value.
954 */
955dma_addr_t omap_get_dma_src_pos(int lch)
956{
957 return (dma_addr_t) (OMAP_DMA_CSSA_L(lch) |
958 (OMAP_DMA_CSSA_U(lch) << 16));
959}
960
961/*
962 * Returns current physical destination address for the given DMA channel.
963 * If the channel is running the caller must disable interrupts prior calling
964 * this function and process the returned value before re-enabling interrupt to
965 * prevent races with the interrupt handler. Note that in continuous mode there
966 * is a chance for CDSA_L register overflow inbetween the two reads resulting
967 * in incorrect return value.
968 */
969dma_addr_t omap_get_dma_dst_pos(int lch)
970{
971 return (dma_addr_t) (OMAP_DMA_CDSA_L(lch) |
972 (OMAP_DMA_CDSA_U(lch) << 16));
973}
974
975static int __init omap_init_dma(void)
976{
977 int ch, r;
978
979 if (cpu_is_omap1510()) {
980 printk(KERN_INFO "DMA support for OMAP1510 initialized\n");
981 dma_chan_count = 9;
982 enable_1510_mode = 1;
983 } else if (cpu_is_omap16xx() || cpu_is_omap730()) {
984 printk(KERN_INFO "OMAP DMA hardware version %d\n",
985 omap_readw(OMAP_DMA_HW_ID));
986 printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
987 (omap_readw(OMAP_DMA_CAPS_0_U) << 16) | omap_readw(OMAP_DMA_CAPS_0_L),
988 (omap_readw(OMAP_DMA_CAPS_1_U) << 16) | omap_readw(OMAP_DMA_CAPS_1_L),
989 omap_readw(OMAP_DMA_CAPS_2), omap_readw(OMAP_DMA_CAPS_3),
990 omap_readw(OMAP_DMA_CAPS_4));
991 if (!enable_1510_mode) {
992 u16 w;
993
994 /* Disable OMAP 3.0/3.1 compatibility mode. */
995 w = omap_readw(OMAP_DMA_GSCR);
996 w |= 1 << 3;
997 omap_writew(w, OMAP_DMA_GSCR);
998 dma_chan_count = 16;
999 } else
1000 dma_chan_count = 9;
1001 } else {
1002 dma_chan_count = 0;
1003 return 0;
1004 }
1005
1006 memset(&lcd_dma, 0, sizeof(lcd_dma));
1007 spin_lock_init(&lcd_dma.lock);
1008 spin_lock_init(&dma_chan_lock);
1009 memset(&dma_chan, 0, sizeof(dma_chan));
1010
1011 for (ch = 0; ch < dma_chan_count; ch++) {
1012 dma_chan[ch].dev_id = -1;
1013 dma_chan[ch].next_lch = -1;
1014
1015 if (ch >= 6 && enable_1510_mode)
1016 continue;
1017
1018 /* request_irq() doesn't like dev_id (ie. ch) being zero,
1019 * so we have to kludge around this. */
1020 r = request_irq(dma_irq[ch], dma_irq_handler, 0, "DMA",
1021 (void *) (ch + 1));
1022 if (r != 0) {
1023 int i;
1024
1025 printk(KERN_ERR "unable to request IRQ %d for DMA (error %d)\n",
1026 dma_irq[ch], r);
1027 for (i = 0; i < ch; i++)
1028 free_irq(dma_irq[i], (void *) (i + 1));
1029 return r;
1030 }
1031 }
1032 r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, "LCD DMA", NULL);
1033 if (r != 0) {
1034 int i;
1035
1036 printk(KERN_ERR "unable to request IRQ for LCD DMA (error %d)\n", r);
1037 for (i = 0; i < dma_chan_count; i++)
1038 free_irq(dma_irq[i], (void *) (i + 1));
1039 return r;
1040 }
1041 return 0;
1042}
1043
1044arch_initcall(omap_init_dma);
1045
1046
1047EXPORT_SYMBOL(omap_get_dma_src_pos);
1048EXPORT_SYMBOL(omap_get_dma_dst_pos);
1049EXPORT_SYMBOL(omap_clear_dma);
1050EXPORT_SYMBOL(omap_set_dma_priority);
1051EXPORT_SYMBOL(omap_request_dma);
1052EXPORT_SYMBOL(omap_free_dma);
1053EXPORT_SYMBOL(omap_start_dma);
1054EXPORT_SYMBOL(omap_stop_dma);
1055EXPORT_SYMBOL(omap_enable_dma_irq);
1056EXPORT_SYMBOL(omap_disable_dma_irq);
1057
1058EXPORT_SYMBOL(omap_set_dma_transfer_params);
1059EXPORT_SYMBOL(omap_set_dma_color_mode);
1060
1061EXPORT_SYMBOL(omap_set_dma_src_params);
1062EXPORT_SYMBOL(omap_set_dma_src_index);
1063EXPORT_SYMBOL(omap_set_dma_src_data_pack);
1064EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
1065
1066EXPORT_SYMBOL(omap_set_dma_dest_params);
1067EXPORT_SYMBOL(omap_set_dma_dest_index);
1068EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
1069EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
1070
1071EXPORT_SYMBOL(omap_dma_link_lch);
1072EXPORT_SYMBOL(omap_dma_unlink_lch);
1073
1074EXPORT_SYMBOL(omap_request_lcd_dma);
1075EXPORT_SYMBOL(omap_free_lcd_dma);
1076EXPORT_SYMBOL(omap_enable_lcd_dma);
1077EXPORT_SYMBOL(omap_setup_lcd_dma);
1078EXPORT_SYMBOL(omap_stop_lcd_dma);
1079EXPORT_SYMBOL(omap_set_lcd_dma_b1);
1080EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
1081EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
1082EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation);
1083EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres);
1084EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale);
1085EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror);
1086
diff --git a/arch/arm/mach-omap/fpga.c b/arch/arm/mach-omap/fpga.c
new file mode 100644
index 000000000000..7c08f6c2e1d0
--- /dev/null
+++ b/arch/arm/mach-omap/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-omap/gpio.c b/arch/arm/mach-omap/gpio.c
new file mode 100644
index 000000000000..9045dfd469ad
--- /dev/null
+++ b/arch/arm/mach-omap/gpio.c
@@ -0,0 +1,762 @@
1/*
2 * linux/arch/arm/mach-omap/gpio.c
3 *
4 * Support functions for OMAP GPIO
5 *
6 * Copyright (C) 2003 Nokia Corporation
7 * Written by Juha Yrjölä <juha.yrjola@nokia.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/init.h>
16#include <linux/module.h>
17#include <linux/sched.h>
18#include <linux/interrupt.h>
19#include <linux/ptrace.h>
20
21#include <asm/hardware.h>
22#include <asm/irq.h>
23#include <asm/arch/irqs.h>
24#include <asm/arch/gpio.h>
25#include <asm/mach/irq.h>
26
27#include <asm/io.h>
28
29/*
30 * OMAP1510 GPIO registers
31 */
32#define OMAP1510_GPIO_BASE 0xfffce000
33#define OMAP1510_GPIO_DATA_INPUT 0x00
34#define OMAP1510_GPIO_DATA_OUTPUT 0x04
35#define OMAP1510_GPIO_DIR_CONTROL 0x08
36#define OMAP1510_GPIO_INT_CONTROL 0x0c
37#define OMAP1510_GPIO_INT_MASK 0x10
38#define OMAP1510_GPIO_INT_STATUS 0x14
39#define OMAP1510_GPIO_PIN_CONTROL 0x18
40
41#define OMAP1510_IH_GPIO_BASE 64
42
43/*
44 * OMAP1610 specific GPIO registers
45 */
46#define OMAP1610_GPIO1_BASE 0xfffbe400
47#define OMAP1610_GPIO2_BASE 0xfffbec00
48#define OMAP1610_GPIO3_BASE 0xfffbb400
49#define OMAP1610_GPIO4_BASE 0xfffbbc00
50#define OMAP1610_GPIO_REVISION 0x0000
51#define OMAP1610_GPIO_SYSCONFIG 0x0010
52#define OMAP1610_GPIO_SYSSTATUS 0x0014
53#define OMAP1610_GPIO_IRQSTATUS1 0x0018
54#define OMAP1610_GPIO_IRQENABLE1 0x001c
55#define OMAP1610_GPIO_DATAIN 0x002c
56#define OMAP1610_GPIO_DATAOUT 0x0030
57#define OMAP1610_GPIO_DIRECTION 0x0034
58#define OMAP1610_GPIO_EDGE_CTRL1 0x0038
59#define OMAP1610_GPIO_EDGE_CTRL2 0x003c
60#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
61#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0
62#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc
63#define OMAP1610_GPIO_SET_DATAOUT 0x00f0
64
65/*
66 * OMAP730 specific GPIO registers
67 */
68#define OMAP730_GPIO1_BASE 0xfffbc000
69#define OMAP730_GPIO2_BASE 0xfffbc800
70#define OMAP730_GPIO3_BASE 0xfffbd000
71#define OMAP730_GPIO4_BASE 0xfffbd800
72#define OMAP730_GPIO5_BASE 0xfffbe000
73#define OMAP730_GPIO6_BASE 0xfffbe800
74#define OMAP730_GPIO_DATA_INPUT 0x00
75#define OMAP730_GPIO_DATA_OUTPUT 0x04
76#define OMAP730_GPIO_DIR_CONTROL 0x08
77#define OMAP730_GPIO_INT_CONTROL 0x0c
78#define OMAP730_GPIO_INT_MASK 0x10
79#define OMAP730_GPIO_INT_STATUS 0x14
80
81#define OMAP_MPUIO_MASK (~OMAP_MAX_GPIO_LINES & 0xff)
82
83struct gpio_bank {
84 u32 base;
85 u16 irq;
86 u16 virtual_irq_start;
87 u8 method;
88 u32 reserved_map;
89 spinlock_t lock;
90};
91
92#define METHOD_MPUIO 0
93#define METHOD_GPIO_1510 1
94#define METHOD_GPIO_1610 2
95#define METHOD_GPIO_730 3
96
97#if defined(CONFIG_ARCH_OMAP16XX)
98static struct gpio_bank gpio_bank_1610[5] = {
99 { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO},
100 { OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 },
101 { OMAP1610_GPIO2_BASE, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16, METHOD_GPIO_1610 },
102 { OMAP1610_GPIO3_BASE, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32, METHOD_GPIO_1610 },
103 { OMAP1610_GPIO4_BASE, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48, METHOD_GPIO_1610 },
104};
105#endif
106
107#ifdef CONFIG_ARCH_OMAP1510
108static struct gpio_bank gpio_bank_1510[2] = {
109 { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO },
110 { OMAP1510_GPIO_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1510 }
111};
112#endif
113
114#ifdef CONFIG_ARCH_OMAP730
115static struct gpio_bank gpio_bank_730[7] = {
116 { OMAP_MPUIO_BASE, INT_730_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO },
117 { OMAP730_GPIO1_BASE, INT_730_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 },
118 { OMAP730_GPIO2_BASE, INT_730_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_730 },
119 { OMAP730_GPIO3_BASE, INT_730_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_730 },
120 { OMAP730_GPIO4_BASE, INT_730_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_730 },
121 { OMAP730_GPIO5_BASE, INT_730_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_730 },
122 { OMAP730_GPIO6_BASE, INT_730_GPIO_BANK6, IH_GPIO_BASE + 160, METHOD_GPIO_730 },
123};
124#endif
125
126static struct gpio_bank *gpio_bank;
127static int gpio_bank_count;
128
129static inline struct gpio_bank *get_gpio_bank(int gpio)
130{
131#ifdef CONFIG_ARCH_OMAP1510
132 if (cpu_is_omap1510()) {
133 if (OMAP_GPIO_IS_MPUIO(gpio))
134 return &gpio_bank[0];
135 return &gpio_bank[1];
136 }
137#endif
138#if defined(CONFIG_ARCH_OMAP16XX)
139 if (cpu_is_omap16xx()) {
140 if (OMAP_GPIO_IS_MPUIO(gpio))
141 return &gpio_bank[0];
142 return &gpio_bank[1 + (gpio >> 4)];
143 }
144#endif
145#ifdef CONFIG_ARCH_OMAP730
146 if (cpu_is_omap730()) {
147 if (OMAP_GPIO_IS_MPUIO(gpio))
148 return &gpio_bank[0];
149 return &gpio_bank[1 + (gpio >> 5)];
150 }
151#endif
152}
153
154static inline int get_gpio_index(int gpio)
155{
156 if (cpu_is_omap730())
157 return gpio & 0x1f;
158 else
159 return gpio & 0x0f;
160}
161
162static inline int gpio_valid(int gpio)
163{
164 if (gpio < 0)
165 return -1;
166 if (OMAP_GPIO_IS_MPUIO(gpio)) {
167 if ((gpio & OMAP_MPUIO_MASK) > 16)
168 return -1;
169 return 0;
170 }
171#ifdef CONFIG_ARCH_OMAP1510
172 if (cpu_is_omap1510() && gpio < 16)
173 return 0;
174#endif
175#if defined(CONFIG_ARCH_OMAP16XX)
176 if ((cpu_is_omap16xx()) && gpio < 64)
177 return 0;
178#endif
179#ifdef CONFIG_ARCH_OMAP730
180 if (cpu_is_omap730() && gpio < 192)
181 return 0;
182#endif
183 return -1;
184}
185
186static int check_gpio(int gpio)
187{
188 if (unlikely(gpio_valid(gpio)) < 0) {
189 printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);
190 dump_stack();
191 return -1;
192 }
193 return 0;
194}
195
196static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
197{
198 u32 reg = bank->base;
199 u32 l;
200
201 switch (bank->method) {
202 case METHOD_MPUIO:
203 reg += OMAP_MPUIO_IO_CNTL;
204 break;
205 case METHOD_GPIO_1510:
206 reg += OMAP1510_GPIO_DIR_CONTROL;
207 break;
208 case METHOD_GPIO_1610:
209 reg += OMAP1610_GPIO_DIRECTION;
210 break;
211 case METHOD_GPIO_730:
212 reg += OMAP730_GPIO_DIR_CONTROL;
213 break;
214 }
215 l = __raw_readl(reg);
216 if (is_input)
217 l |= 1 << gpio;
218 else
219 l &= ~(1 << gpio);
220 __raw_writel(l, reg);
221}
222
223void omap_set_gpio_direction(int gpio, int is_input)
224{
225 struct gpio_bank *bank;
226
227 if (check_gpio(gpio) < 0)
228 return;
229 bank = get_gpio_bank(gpio);
230 spin_lock(&bank->lock);
231 _set_gpio_direction(bank, get_gpio_index(gpio), is_input);
232 spin_unlock(&bank->lock);
233}
234
235static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
236{
237 u32 reg = bank->base;
238 u32 l = 0;
239
240 switch (bank->method) {
241 case METHOD_MPUIO:
242 reg += OMAP_MPUIO_OUTPUT;
243 l = __raw_readl(reg);
244 if (enable)
245 l |= 1 << gpio;
246 else
247 l &= ~(1 << gpio);
248 break;
249 case METHOD_GPIO_1510:
250 reg += OMAP1510_GPIO_DATA_OUTPUT;
251 l = __raw_readl(reg);
252 if (enable)
253 l |= 1 << gpio;
254 else
255 l &= ~(1 << gpio);
256 break;
257 case METHOD_GPIO_1610:
258 if (enable)
259 reg += OMAP1610_GPIO_SET_DATAOUT;
260 else
261 reg += OMAP1610_GPIO_CLEAR_DATAOUT;
262 l = 1 << gpio;
263 break;
264 case METHOD_GPIO_730:
265 reg += OMAP730_GPIO_DATA_OUTPUT;
266 l = __raw_readl(reg);
267 if (enable)
268 l |= 1 << gpio;
269 else
270 l &= ~(1 << gpio);
271 break;
272 default:
273 BUG();
274 return;
275 }
276 __raw_writel(l, reg);
277}
278
279void omap_set_gpio_dataout(int gpio, int enable)
280{
281 struct gpio_bank *bank;
282
283 if (check_gpio(gpio) < 0)
284 return;
285 bank = get_gpio_bank(gpio);
286 spin_lock(&bank->lock);
287 _set_gpio_dataout(bank, get_gpio_index(gpio), enable);
288 spin_unlock(&bank->lock);
289}
290
291int omap_get_gpio_datain(int gpio)
292{
293 struct gpio_bank *bank;
294 u32 reg;
295
296 if (check_gpio(gpio) < 0)
297 return -1;
298 bank = get_gpio_bank(gpio);
299 reg = bank->base;
300 switch (bank->method) {
301 case METHOD_MPUIO:
302 reg += OMAP_MPUIO_INPUT_LATCH;
303 break;
304 case METHOD_GPIO_1510:
305 reg += OMAP1510_GPIO_DATA_INPUT;
306 break;
307 case METHOD_GPIO_1610:
308 reg += OMAP1610_GPIO_DATAIN;
309 break;
310 case METHOD_GPIO_730:
311 reg += OMAP730_GPIO_DATA_INPUT;
312 break;
313 default:
314 BUG();
315 return -1;
316 }
317 return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
318}
319
320static void _set_gpio_edge_ctrl(struct gpio_bank *bank, int gpio, int edge)
321{
322 u32 reg = bank->base;
323 u32 l;
324
325 switch (bank->method) {
326 case METHOD_MPUIO:
327 reg += OMAP_MPUIO_GPIO_INT_EDGE;
328 l = __raw_readl(reg);
329 if (edge == OMAP_GPIO_RISING_EDGE)
330 l |= 1 << gpio;
331 else
332 l &= ~(1 << gpio);
333 __raw_writel(l, reg);
334 break;
335 case METHOD_GPIO_1510:
336 reg += OMAP1510_GPIO_INT_CONTROL;
337 l = __raw_readl(reg);
338 if (edge == OMAP_GPIO_RISING_EDGE)
339 l |= 1 << gpio;
340 else
341 l &= ~(1 << gpio);
342 __raw_writel(l, reg);
343 break;
344 case METHOD_GPIO_1610:
345 edge &= 0x03;
346 if (gpio & 0x08)
347 reg += OMAP1610_GPIO_EDGE_CTRL2;
348 else
349 reg += OMAP1610_GPIO_EDGE_CTRL1;
350 gpio &= 0x07;
351 l = __raw_readl(reg);
352 l &= ~(3 << (gpio << 1));
353 l |= edge << (gpio << 1);
354 __raw_writel(l, reg);
355 break;
356 case METHOD_GPIO_730:
357 reg += OMAP730_GPIO_INT_CONTROL;
358 l = __raw_readl(reg);
359 if (edge == OMAP_GPIO_RISING_EDGE)
360 l |= 1 << gpio;
361 else
362 l &= ~(1 << gpio);
363 __raw_writel(l, reg);
364 break;
365 default:
366 BUG();
367 return;
368 }
369}
370
371void omap_set_gpio_edge_ctrl(int gpio, int edge)
372{
373 struct gpio_bank *bank;
374
375 if (check_gpio(gpio) < 0)
376 return;
377 bank = get_gpio_bank(gpio);
378 spin_lock(&bank->lock);
379 _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), edge);
380 spin_unlock(&bank->lock);
381}
382
383
384static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio)
385{
386 u32 reg = bank->base, l;
387
388 switch (bank->method) {
389 case METHOD_MPUIO:
390 l = __raw_readl(reg + OMAP_MPUIO_GPIO_INT_EDGE);
391 return (l & (1 << gpio)) ?
392 OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
393 case METHOD_GPIO_1510:
394 l = __raw_readl(reg + OMAP1510_GPIO_INT_CONTROL);
395 return (l & (1 << gpio)) ?
396 OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
397 case METHOD_GPIO_1610:
398 if (gpio & 0x08)
399 reg += OMAP1610_GPIO_EDGE_CTRL2;
400 else
401 reg += OMAP1610_GPIO_EDGE_CTRL1;
402 return (__raw_readl(reg) >> ((gpio & 0x07) << 1)) & 0x03;
403 case METHOD_GPIO_730:
404 l = __raw_readl(reg + OMAP730_GPIO_INT_CONTROL);
405 return (l & (1 << gpio)) ?
406 OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE;
407 default:
408 BUG();
409 return -1;
410 }
411}
412
413static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
414{
415 u32 reg = bank->base;
416
417 switch (bank->method) {
418 case METHOD_MPUIO:
419 /* MPUIO irqstatus is reset by reading the status register,
420 * so do nothing here */
421 return;
422 case METHOD_GPIO_1510:
423 reg += OMAP1510_GPIO_INT_STATUS;
424 break;
425 case METHOD_GPIO_1610:
426 reg += OMAP1610_GPIO_IRQSTATUS1;
427 break;
428 case METHOD_GPIO_730:
429 reg += OMAP730_GPIO_INT_STATUS;
430 break;
431 default:
432 BUG();
433 return;
434 }
435 __raw_writel(gpio_mask, reg);
436}
437
438static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
439{
440 _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
441}
442
443static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
444{
445 u32 reg = bank->base;
446 u32 l;
447
448 switch (bank->method) {
449 case METHOD_MPUIO:
450 reg += OMAP_MPUIO_GPIO_MASKIT;
451 l = __raw_readl(reg);
452 if (enable)
453 l &= ~(gpio_mask);
454 else
455 l |= gpio_mask;
456 break;
457 case METHOD_GPIO_1510:
458 reg += OMAP1510_GPIO_INT_MASK;
459 l = __raw_readl(reg);
460 if (enable)
461 l &= ~(gpio_mask);
462 else
463 l |= gpio_mask;
464 break;
465 case METHOD_GPIO_1610:
466 if (enable)
467 reg += OMAP1610_GPIO_SET_IRQENABLE1;
468 else
469 reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
470 l = gpio_mask;
471 break;
472 case METHOD_GPIO_730:
473 reg += OMAP730_GPIO_INT_MASK;
474 l = __raw_readl(reg);
475 if (enable)
476 l &= ~(gpio_mask);
477 else
478 l |= gpio_mask;
479 break;
480 default:
481 BUG();
482 return;
483 }
484 __raw_writel(l, reg);
485}
486
487static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
488{
489 _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
490}
491
492int omap_request_gpio(int gpio)
493{
494 struct gpio_bank *bank;
495
496 if (check_gpio(gpio) < 0)
497 return -EINVAL;
498
499 bank = get_gpio_bank(gpio);
500 spin_lock(&bank->lock);
501 if (unlikely(bank->reserved_map & (1 << get_gpio_index(gpio)))) {
502 printk(KERN_ERR "omap-gpio: GPIO %d is already reserved!\n", gpio);
503 dump_stack();
504 spin_unlock(&bank->lock);
505 return -1;
506 }
507 bank->reserved_map |= (1 << get_gpio_index(gpio));
508#ifdef CONFIG_ARCH_OMAP1510
509 if (bank->method == METHOD_GPIO_1510) {
510 u32 reg;
511
512 /* Claim the pin for the ARM */
513 reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
514 __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg);
515 }
516#endif
517 spin_unlock(&bank->lock);
518
519 return 0;
520}
521
522void omap_free_gpio(int gpio)
523{
524 struct gpio_bank *bank;
525
526 if (check_gpio(gpio) < 0)
527 return;
528 bank = get_gpio_bank(gpio);
529 spin_lock(&bank->lock);
530 if (unlikely(!(bank->reserved_map & (1 << get_gpio_index(gpio))))) {
531 printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio);
532 dump_stack();
533 spin_unlock(&bank->lock);
534 return;
535 }
536 bank->reserved_map &= ~(1 << get_gpio_index(gpio));
537 _set_gpio_direction(bank, get_gpio_index(gpio), 1);
538 _set_gpio_irqenable(bank, gpio, 0);
539 _clear_gpio_irqstatus(bank, gpio);
540 spin_unlock(&bank->lock);
541}
542
543/*
544 * We need to unmask the GPIO bank interrupt as soon as possible to
545 * avoid missing GPIO interrupts for other lines in the bank.
546 * Then we need to mask-read-clear-unmask the triggered GPIO lines
547 * in the bank to avoid missing nested interrupts for a GPIO line.
548 * If we wait to unmask individual GPIO lines in the bank after the
549 * line's interrupt handler has been run, we may miss some nested
550 * interrupts.
551 */
552static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
553 struct pt_regs *regs)
554{
555 u32 isr_reg = 0;
556 u32 isr;
557 unsigned int gpio_irq;
558 struct gpio_bank *bank;
559
560 desc->chip->ack(irq);
561
562 bank = (struct gpio_bank *) desc->data;
563 if (bank->method == METHOD_MPUIO)
564 isr_reg = bank->base + OMAP_MPUIO_GPIO_INT;
565#ifdef CONFIG_ARCH_OMAP1510
566 if (bank->method == METHOD_GPIO_1510)
567 isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
568#endif
569#if defined(CONFIG_ARCH_OMAP16XX)
570 if (bank->method == METHOD_GPIO_1610)
571 isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
572#endif
573#ifdef CONFIG_ARCH_OMAP730
574 if (bank->method == METHOD_GPIO_730)
575 isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
576#endif
577
578 isr = __raw_readl(isr_reg);
579 _enable_gpio_irqbank(bank, isr, 0);
580 _clear_gpio_irqbank(bank, isr);
581 _enable_gpio_irqbank(bank, isr, 1);
582 desc->chip->unmask(irq);
583
584 if (unlikely(!isr))
585 return;
586
587 gpio_irq = bank->virtual_irq_start;
588 for (; isr != 0; isr >>= 1, gpio_irq++) {
589 struct irqdesc *d;
590 if (!(isr & 1))
591 continue;
592 d = irq_desc + gpio_irq;
593 d->handle(gpio_irq, d, regs);
594 }
595}
596
597static void gpio_ack_irq(unsigned int irq)
598{
599 unsigned int gpio = irq - IH_GPIO_BASE;
600 struct gpio_bank *bank = get_gpio_bank(gpio);
601
602 _clear_gpio_irqstatus(bank, gpio);
603}
604
605static void gpio_mask_irq(unsigned int irq)
606{
607 unsigned int gpio = irq - IH_GPIO_BASE;
608 struct gpio_bank *bank = get_gpio_bank(gpio);
609
610 _set_gpio_irqenable(bank, gpio, 0);
611}
612
613static void gpio_unmask_irq(unsigned int irq)
614{
615 unsigned int gpio = irq - IH_GPIO_BASE;
616 struct gpio_bank *bank = get_gpio_bank(gpio);
617
618 if (_get_gpio_edge_ctrl(bank, get_gpio_index(gpio)) == OMAP_GPIO_NO_EDGE) {
619 printk(KERN_ERR "OMAP GPIO %d: trying to enable GPIO IRQ while no edge is set\n",
620 gpio);
621 _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE);
622 }
623 _set_gpio_irqenable(bank, gpio, 1);
624}
625
626static void mpuio_ack_irq(unsigned int irq)
627{
628 /* The ISR is reset automatically, so do nothing here. */
629}
630
631static void mpuio_mask_irq(unsigned int irq)
632{
633 unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
634 struct gpio_bank *bank = get_gpio_bank(gpio);
635
636 _set_gpio_irqenable(bank, gpio, 0);
637}
638
639static void mpuio_unmask_irq(unsigned int irq)
640{
641 unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
642 struct gpio_bank *bank = get_gpio_bank(gpio);
643
644 _set_gpio_irqenable(bank, gpio, 1);
645}
646
647static struct irqchip gpio_irq_chip = {
648 .ack = gpio_ack_irq,
649 .mask = gpio_mask_irq,
650 .unmask = gpio_unmask_irq,
651};
652
653static struct irqchip mpuio_irq_chip = {
654 .ack = mpuio_ack_irq,
655 .mask = mpuio_mask_irq,
656 .unmask = mpuio_unmask_irq
657};
658
659static int initialized = 0;
660
661static int __init _omap_gpio_init(void)
662{
663 int i;
664 struct gpio_bank *bank;
665
666 initialized = 1;
667
668#ifdef CONFIG_ARCH_OMAP1510
669 if (cpu_is_omap1510()) {
670 printk(KERN_INFO "OMAP1510 GPIO hardware\n");
671 gpio_bank_count = 2;
672 gpio_bank = gpio_bank_1510;
673 }
674#endif
675#if defined(CONFIG_ARCH_OMAP16XX)
676 if (cpu_is_omap16xx()) {
677 int rev;
678
679 gpio_bank_count = 5;
680 gpio_bank = gpio_bank_1610;
681 rev = omap_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION);
682 printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
683 (rev >> 4) & 0x0f, rev & 0x0f);
684 }
685#endif
686#ifdef CONFIG_ARCH_OMAP730
687 if (cpu_is_omap730()) {
688 printk(KERN_INFO "OMAP730 GPIO hardware\n");
689 gpio_bank_count = 7;
690 gpio_bank = gpio_bank_730;
691 }
692#endif
693 for (i = 0; i < gpio_bank_count; i++) {
694 int j, gpio_count = 16;
695
696 bank = &gpio_bank[i];
697 bank->reserved_map = 0;
698 bank->base = IO_ADDRESS(bank->base);
699 spin_lock_init(&bank->lock);
700 if (bank->method == METHOD_MPUIO) {
701 omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT);
702 }
703#ifdef CONFIG_ARCH_OMAP1510
704 if (bank->method == METHOD_GPIO_1510) {
705 __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK);
706 __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
707 }
708#endif
709#if defined(CONFIG_ARCH_OMAP16XX)
710 if (bank->method == METHOD_GPIO_1610) {
711 __raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
712 __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
713 }
714#endif
715#ifdef CONFIG_ARCH_OMAP730
716 if (bank->method == METHOD_GPIO_730) {
717 __raw_writel(0xffffffff, bank->base + OMAP730_GPIO_INT_MASK);
718 __raw_writel(0x00000000, bank->base + OMAP730_GPIO_INT_STATUS);
719
720 gpio_count = 32; /* 730 has 32-bit GPIOs */
721 }
722#endif
723 for (j = bank->virtual_irq_start;
724 j < bank->virtual_irq_start + gpio_count; j++) {
725 if (bank->method == METHOD_MPUIO)
726 set_irq_chip(j, &mpuio_irq_chip);
727 else
728 set_irq_chip(j, &gpio_irq_chip);
729 set_irq_handler(j, do_simple_IRQ);
730 set_irq_flags(j, IRQF_VALID);
731 }
732 set_irq_chained_handler(bank->irq, gpio_irq_handler);
733 set_irq_data(bank->irq, bank);
734 }
735
736 /* Enable system clock for GPIO module.
737 * The CAM_CLK_CTRL *is* really the right place. */
738 if (cpu_is_omap1610() || cpu_is_omap1710())
739 omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
740
741 return 0;
742}
743
744/*
745 * This may get called early from board specific init
746 */
747int omap_gpio_init(void)
748{
749 if (!initialized)
750 return _omap_gpio_init();
751 else
752 return 0;
753}
754
755EXPORT_SYMBOL(omap_request_gpio);
756EXPORT_SYMBOL(omap_free_gpio);
757EXPORT_SYMBOL(omap_set_gpio_direction);
758EXPORT_SYMBOL(omap_set_gpio_dataout);
759EXPORT_SYMBOL(omap_get_gpio_datain);
760EXPORT_SYMBOL(omap_set_gpio_edge_ctrl);
761
762arch_initcall(omap_gpio_init);
diff --git a/arch/arm/mach-omap/irq.c b/arch/arm/mach-omap/irq.c
new file mode 100644
index 000000000000..f01c99266a86
--- /dev/null
+++ b/arch/arm/mach-omap/irq.c
@@ -0,0 +1,219 @@
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};
60
61static unsigned int irq_bank_count = 0;
62static struct omap_irq_bank *irq_banks;
63
64static inline unsigned int irq_bank_readl(int bank, int offset)
65{
66 return omap_readl(irq_banks[bank].base_reg + offset);
67}
68
69static inline void irq_bank_writel(unsigned long value, int bank, int offset)
70{
71 omap_writel(value, irq_banks[bank].base_reg + offset);
72}
73
74static void omap_ack_irq(unsigned int irq)
75{
76 if (irq > 31)
77 omap_writel(0x1, OMAP_IH2_BASE + IRQ_CONTROL_REG_OFFSET);
78
79 omap_writel(0x1, OMAP_IH1_BASE + IRQ_CONTROL_REG_OFFSET);
80}
81
82static void omap_mask_irq(unsigned int irq)
83{
84 int bank = IRQ_BANK(irq);
85 u32 l;
86
87 l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
88 l |= 1 << IRQ_BIT(irq);
89 omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
90}
91
92static void omap_unmask_irq(unsigned int irq)
93{
94 int bank = IRQ_BANK(irq);
95 u32 l;
96
97 l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
98 l &= ~(1 << IRQ_BIT(irq));
99 omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
100}
101
102static void omap_mask_ack_irq(unsigned int irq)
103{
104 omap_mask_irq(irq);
105 omap_ack_irq(irq);
106}
107
108/*
109 * Allows tuning the IRQ type and priority
110 *
111 * NOTE: There is currently no OMAP fiq handler for Linux. Read the
112 * mailing list threads on FIQ handlers if you are planning to
113 * add a FIQ handler for OMAP.
114 */
115static void omap_irq_set_cfg(int irq, int fiq, int priority, int trigger)
116{
117 signed int bank;
118 unsigned long val, offset;
119
120 bank = IRQ_BANK(irq);
121 /* FIQ is only available on bank 0 interrupts */
122 fiq = bank ? 0 : (fiq & 0x1);
123 val = fiq | ((priority & 0x1f) << 2) | ((trigger & 0x1) << 1);
124 offset = IRQ_ILR0_REG_OFFSET + IRQ_BIT(irq) * 0x4;
125 irq_bank_writel(val, bank, offset);
126}
127
128#ifdef CONFIG_ARCH_OMAP730
129static struct omap_irq_bank omap730_irq_banks[] = {
130 { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f },
131 { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 },
132 { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 },
133};
134#endif
135
136#ifdef CONFIG_ARCH_OMAP1510
137static struct omap_irq_bank omap1510_irq_banks[] = {
138 { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff },
139 { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed },
140};
141#endif
142
143#if defined(CONFIG_ARCH_OMAP16XX)
144
145static struct omap_irq_bank omap1610_irq_banks[] = {
146 { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f },
147 { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd },
148 { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xfffff7ff },
149 { .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff },
150};
151#endif
152
153static struct irqchip omap_irq_chip = {
154 .ack = omap_mask_ack_irq,
155 .mask = omap_mask_irq,
156 .unmask = omap_unmask_irq,
157};
158
159void __init omap_init_irq(void)
160{
161 int i, j;
162
163#ifdef CONFIG_ARCH_OMAP730
164 if (cpu_is_omap730()) {
165 irq_banks = omap730_irq_banks;
166 irq_bank_count = ARRAY_SIZE(omap730_irq_banks);
167 }
168#endif
169#ifdef CONFIG_ARCH_OMAP1510
170 if (cpu_is_omap1510()) {
171 irq_banks = omap1510_irq_banks;
172 irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
173 }
174#endif
175#if defined(CONFIG_ARCH_OMAP16XX)
176 if (cpu_is_omap16xx()) {
177 irq_banks = omap1610_irq_banks;
178 irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
179 }
180#endif
181 printk("Total of %i interrupts in %i interrupt banks\n",
182 irq_bank_count * 32, irq_bank_count);
183
184 /* Mask and clear all interrupts */
185 for (i = 0; i < irq_bank_count; i++) {
186 irq_bank_writel(~0x0, i, IRQ_MIR_REG_OFFSET);
187 irq_bank_writel(0x0, i, IRQ_ITR_REG_OFFSET);
188 }
189
190 /* Clear any pending interrupts */
191 irq_bank_writel(0x03, 0, IRQ_CONTROL_REG_OFFSET);
192 irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET);
193
194 /* Enable interrupts in global mask */
195 if (cpu_is_omap730()) {
196 irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET);
197 }
198
199 /* Install the interrupt handlers for each bank */
200 for (i = 0; i < irq_bank_count; i++) {
201 for (j = i * 32; j < (i + 1) * 32; j++) {
202 int irq_trigger;
203
204 irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j);
205 omap_irq_set_cfg(j, 0, 0, irq_trigger);
206
207 set_irq_chip(j, &omap_irq_chip);
208 set_irq_handler(j, do_level_IRQ);
209 set_irq_flags(j, IRQF_VALID);
210 }
211 }
212
213 /* Unmask level 2 handler */
214 if (cpu_is_omap730()) {
215 omap_unmask_irq(INT_730_IH2_IRQ);
216 } else {
217 omap_unmask_irq(INT_IH2_IRQ);
218 }
219}
diff --git a/arch/arm/mach-omap/leds-h2p2-debug.c b/arch/arm/mach-omap/leds-h2p2-debug.c
new file mode 100644
index 000000000000..6e98290cca5c
--- /dev/null
+++ b/arch/arm/mach-omap/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-omap/leds-innovator.c b/arch/arm/mach-omap/leds-innovator.c
new file mode 100644
index 000000000000..8043b7d0f66e
--- /dev/null
+++ b/arch/arm/mach-omap/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-omap/leds-osk.c b/arch/arm/mach-omap/leds-osk.c
new file mode 100644
index 000000000000..f5177f430793
--- /dev/null
+++ b/arch/arm/mach-omap/leds-osk.c
@@ -0,0 +1,198 @@
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#ifdef CONFIG_LEDS_TIMER
133 case led_timer:
134 hw_led_state ^= TIMER_LED;
135 mistral_setled();
136 break;
137#endif
138
139#ifdef CONFIG_LEDS_CPU
140 case led_idle_start:
141 hw_led_state |= IDLE_LED;
142 mistral_setled();
143 break;
144
145 case led_idle_end:
146 hw_led_state &= ~IDLE_LED;
147 mistral_setled();
148 break;
149#endif
150
151#endif /* CONFIG_FB_OMAP */
152
153 /* "green" == tps LED1 (leftmost, normally power-good)
154 * works only with DC adapter, not on battery power!
155 */
156 case led_green_on:
157 if (led_state & LED_STATE_CLAIMED)
158 hw_led_state |= GREEN_LED;
159 break;
160 case led_green_off:
161 if (led_state & LED_STATE_CLAIMED)
162 hw_led_state &= ~GREEN_LED;
163 break;
164
165 /* "amber" == tps LED2 (middle) */
166 case led_amber_on:
167 if (led_state & LED_STATE_CLAIMED)
168 hw_led_state |= AMBER_LED;
169 break;
170 case led_amber_off:
171 if (led_state & LED_STATE_CLAIMED)
172 hw_led_state &= ~AMBER_LED;
173 break;
174
175 /* "red" == LED on tps gpio3 (rightmost) */
176 case led_red_on:
177 if (led_state & LED_STATE_CLAIMED)
178 hw_led_state |= RED_LED;
179 break;
180 case led_red_off:
181 if (led_state & LED_STATE_CLAIMED)
182 hw_led_state &= ~RED_LED;
183 break;
184
185 default:
186 break;
187 }
188
189 leds ^= hw_led_state;
190 leds &= TPS_LEDS;
191 if (leds && (led_state & LED_STATE_CLAIMED)) {
192 tps_leds_change |= leds;
193 schedule_work(&work);
194 }
195
196done:
197 local_irq_restore(flags);
198}
diff --git a/arch/arm/mach-omap/leds.c b/arch/arm/mach-omap/leds.c
new file mode 100644
index 000000000000..8ab21fe98e1b
--- /dev/null
+++ b/arch/arm/mach-omap/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-omap/leds.h b/arch/arm/mach-omap/leds.h
new file mode 100644
index 000000000000..a1e9fedc376c
--- /dev/null
+++ b/arch/arm/mach-omap/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-omap/mcbsp.c b/arch/arm/mach-omap/mcbsp.c
new file mode 100644
index 000000000000..7c4ad7713091
--- /dev/null
+++ b/arch/arm/mach-omap/mcbsp.c
@@ -0,0 +1,685 @@
1/*
2 * linux/arch/arm/omap/mcbsp.c
3 *
4 * Copyright (C) 2004 Nokia Corporation
5 * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
6 *
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 * Multichannel mode not supported.
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/device.h>
18#include <linux/wait.h>
19#include <linux/completion.h>
20#include <linux/interrupt.h>
21#include <linux/err.h>
22
23#include <asm/delay.h>
24#include <asm/io.h>
25#include <asm/irq.h>
26
27#include <asm/arch/dma.h>
28#include <asm/arch/mux.h>
29#include <asm/arch/irqs.h>
30#include <asm/arch/mcbsp.h>
31
32#include <asm/hardware/clock.h>
33
34#ifdef CONFIG_MCBSP_DEBUG
35#define DBG(x...) printk(x)
36#else
37#define DBG(x...) do { } while (0)
38#endif
39
40struct omap_mcbsp {
41 u32 io_base;
42 u8 id;
43 u8 free;
44 omap_mcbsp_word_length rx_word_length;
45 omap_mcbsp_word_length tx_word_length;
46
47 /* IRQ based TX/RX */
48 int rx_irq;
49 int tx_irq;
50
51 /* DMA stuff */
52 u8 dma_rx_sync;
53 short dma_rx_lch;
54 u8 dma_tx_sync;
55 short dma_tx_lch;
56
57 /* Completion queues */
58 struct completion tx_irq_completion;
59 struct completion rx_irq_completion;
60 struct completion tx_dma_completion;
61 struct completion rx_dma_completion;
62
63 spinlock_t lock;
64};
65
66static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
67static struct clk *mcbsp_dsp_ck = 0;
68static struct clk *mcbsp_api_ck = 0;
69
70
71static void omap_mcbsp_dump_reg(u8 id)
72{
73 DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);
74 DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));
75 DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));
76 DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));
77 DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));
78 DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));
79 DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));
80 DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));
81 DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));
82 DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));
83 DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));
84 DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));
85 DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));
86 DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));
87 DBG("***********************\n");
88}
89
90
91static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
92{
93 struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
94
95 DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));
96
97 complete(&mcbsp_tx->tx_irq_completion);
98 return IRQ_HANDLED;
99}
100
101static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
102{
103 struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id);
104
105 DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));
106
107 complete(&mcbsp_rx->rx_irq_completion);
108 return IRQ_HANDLED;
109}
110
111
112static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
113{
114 struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
115
116 DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));
117
118 /* We can free the channels */
119 omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
120 mcbsp_dma_tx->dma_tx_lch = -1;
121
122 complete(&mcbsp_dma_tx->tx_dma_completion);
123}
124
125static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
126{
127 struct omap_mcbsp * mcbsp_dma_rx = (struct omap_mcbsp *)(data);
128
129 DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));
130
131 /* We can free the channels */
132 omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
133 mcbsp_dma_rx->dma_rx_lch = -1;
134
135 complete(&mcbsp_dma_rx->rx_dma_completion);
136}
137
138
139/*
140 * omap_mcbsp_config simply write a config to the
141 * appropriate McBSP.
142 * You either call this function or set the McBSP registers
143 * by yourself before calling omap_mcbsp_start().
144 */
145
146void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config)
147{
148 u32 io_base = mcbsp[id].io_base;
149
150 DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id+1, io_base);
151
152 /* We write the given config */
153 OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
154 OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1);
155 OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2);
156 OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1);
157 OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2);
158 OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
159 OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
160 OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
161 OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
162 OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
163 OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
164}
165
166
167
168static int omap_mcbsp_check(unsigned int id)
169{
170 if (cpu_is_omap730()) {
171 if (id > OMAP_MAX_MCBSP_COUNT - 1) {
172 printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
173 return -1;
174 }
175 return 0;
176 }
177
178 if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
179 if (id > OMAP_MAX_MCBSP_COUNT) {
180 printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
181 return -1;
182 }
183 return 0;
184 }
185
186 return -1;
187}
188
189#define EN_XORPCK 1
190#define DSP_RSTCT2 0xe1008014
191
192static void omap_mcbsp_dsp_request(void)
193{
194 if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
195 omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)),
196 ARM_RSTCT1);
197 clk_enable(mcbsp_dsp_ck);
198 clk_enable(mcbsp_api_ck);
199
200 /* enable 12MHz clock to mcbsp 1 & 3 */
201 __raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK),
202 DSP_IDLECT2);
203 __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
204 DSP_RSTCT2);
205 }
206}
207
208static void omap_mcbsp_dsp_free(void)
209{
210 /* Useless for now */
211}
212
213
214int omap_mcbsp_request(unsigned int id)
215{
216 int err;
217
218 if (omap_mcbsp_check(id) < 0)
219 return -EINVAL;
220
221 /*
222 * On 1510, 1610 and 1710, McBSP1 and McBSP3
223 * are DSP public peripherals.
224 */
225 if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
226 omap_mcbsp_dsp_request();
227
228 spin_lock(&mcbsp[id].lock);
229 if (!mcbsp[id].free) {
230 printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
231 spin_unlock(&mcbsp[id].lock);
232 return -1;
233 }
234
235 mcbsp[id].free = 0;
236 spin_unlock(&mcbsp[id].lock);
237
238 /* We need to get IRQs here */
239 err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
240 "McBSP",
241 (void *) (&mcbsp[id]));
242 if (err != 0) {
243 printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
244 mcbsp[id].tx_irq, mcbsp[id].id);
245 return err;
246 }
247
248 init_completion(&(mcbsp[id].tx_irq_completion));
249
250
251 err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
252 "McBSP",
253 (void *) (&mcbsp[id]));
254 if (err != 0) {
255 printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
256 mcbsp[id].rx_irq, mcbsp[id].id);
257 free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
258 return err;
259 }
260
261 init_completion(&(mcbsp[id].rx_irq_completion));
262 return 0;
263
264}
265
266void omap_mcbsp_free(unsigned int id)
267{
268 if (omap_mcbsp_check(id) < 0)
269 return;
270
271 if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
272 omap_mcbsp_dsp_free();
273
274 spin_lock(&mcbsp[id].lock);
275 if (mcbsp[id].free) {
276 printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1);
277 spin_unlock(&mcbsp[id].lock);
278 return;
279 }
280
281 mcbsp[id].free = 1;
282 spin_unlock(&mcbsp[id].lock);
283
284 /* Free IRQs */
285 free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
286 free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
287}
288
289/*
290 * Here we start the McBSP, by enabling the sample
291 * generator, both transmitter and receivers,
292 * and the frame sync.
293 */
294void omap_mcbsp_start(unsigned int id)
295{
296 u32 io_base;
297 u16 w;
298
299 if (omap_mcbsp_check(id) < 0)
300 return;
301
302 io_base = mcbsp[id].io_base;
303
304 mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7);
305 mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7);
306
307 /* Start the sample generator */
308 w = OMAP_MCBSP_READ(io_base, SPCR2);
309 OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
310
311 /* Enable transmitter and receiver */
312 w = OMAP_MCBSP_READ(io_base, SPCR2);
313 OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
314
315 w = OMAP_MCBSP_READ(io_base, SPCR1);
316 OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
317
318 udelay(100);
319
320 /* Start frame sync */
321 w = OMAP_MCBSP_READ(io_base, SPCR2);
322 OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
323
324 /* Dump McBSP Regs */
325 omap_mcbsp_dump_reg(id);
326
327}
328
329void omap_mcbsp_stop(unsigned int id)
330{
331 u32 io_base;
332 u16 w;
333
334 if (omap_mcbsp_check(id) < 0)
335 return;
336
337 io_base = mcbsp[id].io_base;
338
339 /* Reset transmitter */
340 w = OMAP_MCBSP_READ(io_base, SPCR2);
341 OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
342
343 /* Reset receiver */
344 w = OMAP_MCBSP_READ(io_base, SPCR1);
345 OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
346
347 /* Reset the sample rate generator */
348 w = OMAP_MCBSP_READ(io_base, SPCR2);
349 OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
350}
351
352
353/*
354 * IRQ based word transmission.
355 */
356void omap_mcbsp_xmit_word(unsigned int id, u32 word)
357{
358 u32 io_base;
359 omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;
360
361 if (omap_mcbsp_check(id) < 0)
362 return;
363
364 io_base = mcbsp[id].io_base;
365
366 wait_for_completion(&(mcbsp[id].tx_irq_completion));
367
368 if (word_length > OMAP_MCBSP_WORD_16)
369 OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
370 OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
371}
372
373u32 omap_mcbsp_recv_word(unsigned int id)
374{
375 u32 io_base;
376 u16 word_lsb, word_msb = 0;
377 omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;
378
379 if (omap_mcbsp_check(id) < 0)
380 return -EINVAL;
381
382 io_base = mcbsp[id].io_base;
383
384 wait_for_completion(&(mcbsp[id].rx_irq_completion));
385
386 if (word_length > OMAP_MCBSP_WORD_16)
387 word_msb = OMAP_MCBSP_READ(io_base, DRR2);
388 word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
389
390 return (word_lsb | (word_msb << 16));
391}
392
393
394/*
395 * Simple DMA based buffer rx/tx routines.
396 * Nothing fancy, just a single buffer tx/rx through DMA.
397 * The DMA resources are released once the transfer is done.
398 * For anything fancier, you should use your own customized DMA
399 * routines and callbacks.
400 */
401int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
402{
403 int dma_tx_ch;
404
405 if (omap_mcbsp_check(id) < 0)
406 return -EINVAL;
407
408 if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback,
409 &mcbsp[id],
410 &dma_tx_ch)) {
411 printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1);
412 return -EAGAIN;
413 }
414 mcbsp[id].dma_tx_lch = dma_tx_ch;
415
416 DBG("TX DMA on channel %d\n", dma_tx_ch);
417
418 init_completion(&(mcbsp[id].tx_dma_completion));
419
420 omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
421 OMAP_DMA_DATA_TYPE_S16,
422 length >> 1, 1,
423 OMAP_DMA_SYNC_ELEMENT);
424
425 omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
426 OMAP_DMA_PORT_TIPB,
427 OMAP_DMA_AMODE_CONSTANT,
428 mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1);
429
430 omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
431 OMAP_DMA_PORT_EMIFF,
432 OMAP_DMA_AMODE_POST_INC,
433 buffer);
434
435 omap_start_dma(mcbsp[id].dma_tx_lch);
436 wait_for_completion(&(mcbsp[id].tx_dma_completion));
437 return 0;
438}
439
440
441int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
442{
443 int dma_rx_ch;
444
445 if (omap_mcbsp_check(id) < 0)
446 return -EINVAL;
447
448 if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback,
449 &mcbsp[id],
450 &dma_rx_ch)) {
451 printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1);
452 return -EAGAIN;
453 }
454 mcbsp[id].dma_rx_lch = dma_rx_ch;
455
456 DBG("RX DMA on channel %d\n", dma_rx_ch);
457
458 init_completion(&(mcbsp[id].rx_dma_completion));
459
460 omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
461 OMAP_DMA_DATA_TYPE_S16,
462 length >> 1, 1,
463 OMAP_DMA_SYNC_ELEMENT);
464
465 omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
466 OMAP_DMA_PORT_TIPB,
467 OMAP_DMA_AMODE_CONSTANT,
468 mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1);
469
470 omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
471 OMAP_DMA_PORT_EMIFF,
472 OMAP_DMA_AMODE_POST_INC,
473 buffer);
474
475 omap_start_dma(mcbsp[id].dma_rx_lch);
476 wait_for_completion(&(mcbsp[id].rx_dma_completion));
477 return 0;
478}
479
480
481/*
482 * SPI wrapper.
483 * Since SPI setup is much simpler than the generic McBSP one,
484 * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
485 * Once this is done, you can call omap_mcbsp_start().
486 */
487void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg)
488{
489 struct omap_mcbsp_reg_cfg mcbsp_cfg;
490
491 if (omap_mcbsp_check(id) < 0)
492 return;
493
494 memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
495
496 /* SPI has only one frame */
497 mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
498 mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
499
500 /* Clock stop mode */
501 if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
502 mcbsp_cfg.spcr1 |= (1 << 12);
503 else
504 mcbsp_cfg.spcr1 |= (3 << 11);
505
506 /* Set clock parities */
507 if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
508 mcbsp_cfg.pcr0 |= CLKRP;
509 else
510 mcbsp_cfg.pcr0 &= ~CLKRP;
511
512 if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
513 mcbsp_cfg.pcr0 &= ~CLKXP;
514 else
515 mcbsp_cfg.pcr0 |= CLKXP;
516
517 /* Set SCLKME to 0 and CLKSM to 1 */
518 mcbsp_cfg.pcr0 &= ~SCLKME;
519 mcbsp_cfg.srgr2 |= CLKSM;
520
521 /* Set FSXP */
522 if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
523 mcbsp_cfg.pcr0 &= ~FSXP;
524 else
525 mcbsp_cfg.pcr0 |= FSXP;
526
527 if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
528 mcbsp_cfg.pcr0 |= CLKXM;
529 mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1);
530 mcbsp_cfg.pcr0 |= FSXM;
531 mcbsp_cfg.srgr2 &= ~FSGM;
532 mcbsp_cfg.xcr2 |= XDATDLY(1);
533 mcbsp_cfg.rcr2 |= RDATDLY(1);
534 }
535 else {
536 mcbsp_cfg.pcr0 &= ~CLKXM;
537 mcbsp_cfg.srgr1 |= CLKGDV(1);
538 mcbsp_cfg.pcr0 &= ~FSXM;
539 mcbsp_cfg.xcr2 &= ~XDATDLY(3);
540 mcbsp_cfg.rcr2 &= ~RDATDLY(3);
541 }
542
543 mcbsp_cfg.xcr2 &= ~XPHASE;
544 mcbsp_cfg.rcr2 &= ~RPHASE;
545
546 omap_mcbsp_config(id, &mcbsp_cfg);
547}
548
549
550/*
551 * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
552 * 730 has only 2 McBSP, and both of them are MPU peripherals.
553 */
554struct omap_mcbsp_info {
555 u32 virt_base;
556 u8 dma_rx_sync, dma_tx_sync;
557 u16 rx_irq, tx_irq;
558};
559
560#ifdef CONFIG_ARCH_OMAP730
561static const struct omap_mcbsp_info mcbsp_730[] = {
562 [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),
563 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
564 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
565 .rx_irq = INT_730_McBSP1RX,
566 .tx_irq = INT_730_McBSP1TX },
567 [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),
568 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
569 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
570 .rx_irq = INT_730_McBSP2RX,
571 .tx_irq = INT_730_McBSP2TX },
572};
573#endif
574
575#ifdef CONFIG_ARCH_OMAP1510
576static const struct omap_mcbsp_info mcbsp_1510[] = {
577 [0] = { .virt_base = OMAP1510_MCBSP1_BASE,
578 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
579 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
580 .rx_irq = INT_McBSP1RX,
581 .tx_irq = INT_McBSP1TX },
582 [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),
583 .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
584 .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
585 .rx_irq = INT_1510_SPI_RX,
586 .tx_irq = INT_1510_SPI_TX },
587 [2] = { .virt_base = OMAP1510_MCBSP3_BASE,
588 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
589 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
590 .rx_irq = INT_McBSP3RX,
591 .tx_irq = INT_McBSP3TX },
592};
593#endif
594
595#if defined(CONFIG_ARCH_OMAP16XX)
596static const struct omap_mcbsp_info mcbsp_1610[] = {
597 [0] = { .virt_base = OMAP1610_MCBSP1_BASE,
598 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
599 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
600 .rx_irq = INT_McBSP1RX,
601 .tx_irq = INT_McBSP1TX },
602 [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),
603 .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
604 .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
605 .rx_irq = INT_1610_McBSP2_RX,
606 .tx_irq = INT_1610_McBSP2_TX },
607 [2] = { .virt_base = OMAP1610_MCBSP3_BASE,
608 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
609 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
610 .rx_irq = INT_McBSP3RX,
611 .tx_irq = INT_McBSP3TX },
612};
613#endif
614
615static int __init omap_mcbsp_init(void)
616{
617 int mcbsp_count = 0, i;
618 static const struct omap_mcbsp_info *mcbsp_info;
619
620 printk("Initializing OMAP McBSP system\n");
621
622 mcbsp_dsp_ck = clk_get(0, "dsp_ck");
623 if (IS_ERR(mcbsp_dsp_ck)) {
624 printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
625 return PTR_ERR(mcbsp_dsp_ck);
626 }
627 mcbsp_api_ck = clk_get(0, "api_ck");
628 if (IS_ERR(mcbsp_dsp_ck)) {
629 printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");
630 return PTR_ERR(mcbsp_api_ck);
631 }
632
633#ifdef CONFIG_ARCH_OMAP730
634 if (cpu_is_omap730()) {
635 mcbsp_info = mcbsp_730;
636 mcbsp_count = ARRAY_SIZE(mcbsp_730);
637 }
638#endif
639#ifdef CONFIG_ARCH_OMAP1510
640 if (cpu_is_omap1510()) {
641 mcbsp_info = mcbsp_1510;
642 mcbsp_count = ARRAY_SIZE(mcbsp_1510);
643 }
644#endif
645#if defined(CONFIG_ARCH_OMAP16XX)
646 if (cpu_is_omap1610() || cpu_is_omap1710()) {
647 mcbsp_info = mcbsp_1610;
648 mcbsp_count = ARRAY_SIZE(mcbsp_1610);
649 }
650#endif
651 for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
652 if (i >= mcbsp_count) {
653 mcbsp[i].io_base = 0;
654 mcbsp[i].free = 0;
655 continue;
656 }
657 mcbsp[i].id = i + 1;
658 mcbsp[i].free = 1;
659 mcbsp[i].dma_tx_lch = -1;
660 mcbsp[i].dma_rx_lch = -1;
661
662 mcbsp[i].io_base = mcbsp_info[i].virt_base;
663 mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
664 mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
665 mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
666 mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;
667 spin_lock_init(&mcbsp[i].lock);
668 }
669
670 return 0;
671}
672
673
674arch_initcall(omap_mcbsp_init);
675
676EXPORT_SYMBOL(omap_mcbsp_config);
677EXPORT_SYMBOL(omap_mcbsp_request);
678EXPORT_SYMBOL(omap_mcbsp_free);
679EXPORT_SYMBOL(omap_mcbsp_start);
680EXPORT_SYMBOL(omap_mcbsp_stop);
681EXPORT_SYMBOL(omap_mcbsp_xmit_word);
682EXPORT_SYMBOL(omap_mcbsp_recv_word);
683EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
684EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
685EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
diff --git a/arch/arm/mach-omap/mux.c b/arch/arm/mach-omap/mux.c
new file mode 100644
index 000000000000..bcf3c6e5ecd0
--- /dev/null
+++ b/arch/arm/mach-omap/mux.c
@@ -0,0 +1,163 @@
1/*
2 * linux/arch/arm/mach-omap/mux.c
3 *
4 * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h
5 *
6 * Copyright (C) 2003 Nokia Corporation
7 *
8 * Written by Tony Lindgren <tony.lindgren@nokia.com>
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 as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25#include <linux/config.h>
26#include <linux/module.h>
27#include <linux/init.h>
28#include <asm/system.h>
29#include <asm/io.h>
30#include <linux/spinlock.h>
31
32#define __MUX_C__
33#include <asm/arch/mux.h>
34
35#ifdef CONFIG_OMAP_MUX
36
37/*
38 * Sets the Omap MUX and PULL_DWN registers based on the table
39 */
40int __init_or_module
41omap_cfg_reg(const reg_cfg_t reg_cfg)
42{
43 static DEFINE_SPINLOCK(mux_spin_lock);
44
45 unsigned long flags;
46 reg_cfg_set *cfg;
47 unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
48 pull_orig = 0, pull = 0;
49 unsigned int mask, warn = 0;
50
51 if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
52 printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
53 return -EINVAL;
54 }
55
56 cfg = &reg_cfg_table[reg_cfg];
57
58 /*
59 * We do a pretty long section here with lock on, but pin muxing
60 * should only happen on driver init for each driver, so it's not time
61 * critical.
62 */
63 spin_lock_irqsave(&mux_spin_lock, flags);
64
65 /* Check the mux register in question */
66 if (cfg->mux_reg) {
67 unsigned tmp1, tmp2;
68
69 reg_orig = omap_readl(cfg->mux_reg);
70
71 /* The mux registers always seem to be 3 bits long */
72 mask = (0x7 << cfg->mask_offset);
73 tmp1 = reg_orig & mask;
74 reg = reg_orig & ~mask;
75
76 tmp2 = (cfg->mask << cfg->mask_offset);
77 reg |= tmp2;
78
79 if (tmp1 != tmp2)
80 warn = 1;
81
82 omap_writel(reg, cfg->mux_reg);
83 }
84
85 /* Check for pull up or pull down selection on 1610 */
86 if (!cpu_is_omap1510()) {
87 if (cfg->pu_pd_reg && cfg->pull_val) {
88 pu_pd_orig = omap_readl(cfg->pu_pd_reg);
89 mask = 1 << cfg->pull_bit;
90
91 if (cfg->pu_pd_val) {
92 if (!(pu_pd_orig & mask))
93 warn = 1;
94 /* Use pull up */
95 pu_pd = pu_pd_orig | mask;
96 } else {
97 if (pu_pd_orig & mask)
98 warn = 1;
99 /* Use pull down */
100 pu_pd = pu_pd_orig & ~mask;
101 }
102 omap_writel(pu_pd, cfg->pu_pd_reg);
103 }
104 }
105
106 /* Check for an associated pull down register */
107 if (cfg->pull_reg) {
108 pull_orig = omap_readl(cfg->pull_reg);
109 mask = 1 << cfg->pull_bit;
110
111 if (cfg->pull_val) {
112 if (pull_orig & mask)
113 warn = 1;
114 /* Low bit = pull enabled */
115 pull = pull_orig & ~mask;
116 } else {
117 if (!(pull_orig & mask))
118 warn = 1;
119 /* High bit = pull disabled */
120 pull = pull_orig | mask;
121 }
122
123 omap_writel(pull, cfg->pull_reg);
124 }
125
126 if (warn) {
127#ifdef CONFIG_OMAP_MUX_WARNINGS
128 printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
129#endif
130 }
131
132#ifdef CONFIG_OMAP_MUX_DEBUG
133 if (cfg->debug || warn) {
134 printk("MUX: Setting register %s\n", cfg->name);
135 printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
136 cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
137
138 if (!cpu_is_omap1510()) {
139 if (cfg->pu_pd_reg && cfg->pull_val) {
140 printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
141 cfg->pu_pd_name, cfg->pu_pd_reg,
142 pu_pd_orig, pu_pd);
143 }
144 }
145
146 if (cfg->pull_reg)
147 printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
148 cfg->pull_name, cfg->pull_reg, pull_orig, pull);
149 }
150#endif
151
152 spin_unlock_irqrestore(&mux_spin_lock, flags);
153
154#ifdef CONFIG_OMAP_MUX_ERRORS
155 return warn ? -ETXTBSY : 0;
156#else
157 return 0;
158#endif
159}
160
161EXPORT_SYMBOL(omap_cfg_reg);
162
163#endif /* CONFIG_OMAP_MUX */
diff --git a/arch/arm/mach-omap/ocpi.c b/arch/arm/mach-omap/ocpi.c
new file mode 100644
index 000000000000..c9ced134a75d
--- /dev/null
+++ b/arch/arm/mach-omap/ocpi.c
@@ -0,0 +1,114 @@
1/*
2 * linux/arch/arm/mach-omap/ocpi.c
3 *
4 * Minimal OCP bus support for omap16xx
5 *
6 * Copyright (C) 2003 - 2005 Nokia Corporation
7 * Written by Tony Lindgren <tony@atomide.com>
8 *
9 * Modified for clock framework by Paul Mundt <paul.mundt@nokia.com>.
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 as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26#include <linux/config.h>
27#include <linux/module.h>
28#include <linux/version.h>
29#include <linux/types.h>
30#include <linux/errno.h>
31#include <linux/kernel.h>
32#include <linux/init.h>
33#include <linux/spinlock.h>
34#include <linux/err.h>
35
36#include <asm/io.h>
37#include <asm/hardware/clock.h>
38#include <asm/arch/hardware.h>
39
40#define OCPI_BASE 0xfffec320
41#define OCPI_FAULT (OCPI_BASE + 0x00)
42#define OCPI_CMD_FAULT (OCPI_BASE + 0x04)
43#define OCPI_SINT0 (OCPI_BASE + 0x08)
44#define OCPI_TABORT (OCPI_BASE + 0x0c)
45#define OCPI_SINT1 (OCPI_BASE + 0x10)
46#define OCPI_PROT (OCPI_BASE + 0x14)
47#define OCPI_SEC (OCPI_BASE + 0x18)
48
49/* USB OHCI OCPI access error registers */
50#define HOSTUEADDR 0xfffba0e0
51#define HOSTUESTATUS 0xfffba0e4
52
53static struct clk *ocpi_ck;
54
55/*
56 * Enables device access to OMAP buses via the OCPI bridge
57 * FIXME: Add locking
58 */
59int ocpi_enable(void)
60{
61 unsigned int val;
62
63 if (!cpu_is_omap16xx())
64 return -ENODEV;
65
66 /* Make sure there's clock for OCPI */
67 clk_enable(ocpi_ck);
68
69 /* Enable access for OHCI in OCPI */
70 val = omap_readl(OCPI_PROT);
71 val &= ~0xff;
72 //val &= (1 << 0); /* Allow access only to EMIFS */
73 omap_writel(val, OCPI_PROT);
74
75 val = omap_readl(OCPI_SEC);
76 val &= ~0xff;
77 omap_writel(val, OCPI_SEC);
78
79 return 0;
80}
81EXPORT_SYMBOL(ocpi_enable);
82
83static int __init omap_ocpi_init(void)
84{
85 if (!cpu_is_omap16xx())
86 return -ENODEV;
87
88 ocpi_ck = clk_get(NULL, "l3_ocpi_ck");
89 if (IS_ERR(ocpi_ck))
90 return PTR_ERR(ocpi_ck);
91
92 clk_use(ocpi_ck);
93 ocpi_enable();
94 printk("OMAP OCPI interconnect driver loaded\n");
95
96 return 0;
97}
98
99static void __exit omap_ocpi_exit(void)
100{
101 /* REVISIT: Disable OCPI */
102
103 if (!cpu_is_omap16xx())
104 return;
105
106 clk_unuse(ocpi_ck);
107 clk_put(ocpi_ck);
108}
109
110MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
111MODULE_DESCRIPTION("OMAP OCPI bus controller module");
112MODULE_LICENSE("GPL");
113module_init(omap_ocpi_init);
114module_exit(omap_ocpi_exit);
diff --git a/arch/arm/mach-omap/pm.c b/arch/arm/mach-omap/pm.c
new file mode 100644
index 000000000000..00fac155df2a
--- /dev/null
+++ b/arch/arm/mach-omap/pm.c
@@ -0,0 +1,628 @@
1/*
2 * linux/arch/arm/mach-omap/pm.c
3 *
4 * OMAP Power Management Routines
5 *
6 * Original code for the SA11x0:
7 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
8 *
9 * Modified for the PXA250 by Nicolas Pitre:
10 * Copyright (c) 2002 Monta Vista Software, Inc.
11 *
12 * Modified for the OMAP1510 by David Singleton:
13 * Copyright (c) 2002 Monta Vista Software, Inc.
14 *
15 * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version.
21 *
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
25 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * You should have received a copy of the GNU General Public License along
34 * with this program; if not, write to the Free Software Foundation, Inc.,
35 * 675 Mass Ave, Cambridge, MA 02139, USA.
36 */
37
38#include <linux/pm.h>
39#include <linux/sched.h>
40#include <linux/proc_fs.h>
41#include <linux/pm.h>
42
43#include <asm/io.h>
44#include <asm/mach-types.h>
45#include <asm/arch/omap16xx.h>
46#include <asm/arch/pm.h>
47#include <asm/arch/mux.h>
48#include <asm/arch/tc.h>
49#include <asm/arch/tps65010.h>
50
51#include "clock.h"
52
53static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
54static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
55static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
56static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
57
58/*
59 * Let's power down on idle, but only if we are really
60 * idle, because once we start down the path of
61 * going idle we continue to do idle even if we get
62 * a clock tick interrupt . .
63 */
64void omap_pm_idle(void)
65{
66 int (*func_ptr)(void) = 0;
67 unsigned int mask32 = 0;
68
69 /*
70 * If the DSP is being used let's just idle the CPU, the overhead
71 * to wake up from Big Sleep is big, milliseconds versus micro
72 * seconds for wait for interrupt.
73 */
74
75 local_irq_disable();
76 local_fiq_disable();
77 if (need_resched()) {
78 local_fiq_enable();
79 local_irq_enable();
80 return;
81 }
82 mask32 = omap_readl(ARM_SYSST);
83 local_fiq_enable();
84 local_irq_enable();
85
86#if defined(CONFIG_OMAP_32K_TIMER) && defined(CONFIG_NO_IDLE_HZ)
87 /* Override timer to use VST for the next cycle */
88 omap_32k_timer_next_vst_interrupt();
89#endif
90
91 if ((mask32 & DSP_IDLE) == 0) {
92 __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
93 } else {
94
95 if (cpu_is_omap1510()) {
96 func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
97 } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
98 func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
99 } else if (cpu_is_omap5912()) {
100 func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
101 }
102
103 func_ptr();
104 }
105}
106
107/*
108 * Configuration of the wakeup event is board specific. For the
109 * moment we put it into this helper function. Later it may move
110 * to board specific files.
111 */
112static void omap_pm_wakeup_setup(void)
113{
114 /*
115 * Enable ARM XOR clock and release peripheral from reset by
116 * writing 1 to PER_EN bit in ARM_RSTCT2, this is required
117 * for UART configuration to use UART2 to wake up.
118 */
119
120 omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
121 omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
122 omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
123
124 /*
125 * Turn off all interrupts except L1-2nd level cascade,
126 * and the L2 wakeup interrupts: keypad and UART2.
127 */
128
129 omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
130
131 if (cpu_is_omap1510()) {
132 omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR);
133 }
134
135 if (cpu_is_omap16xx()) {
136 omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
137
138 omap_writel(~0x0, OMAP_IH2_1_MIR);
139 omap_writel(~0x0, OMAP_IH2_2_MIR);
140 omap_writel(~0x0, OMAP_IH2_3_MIR);
141 }
142
143 /* New IRQ agreement */
144 omap_writel(1, OMAP_IH1_CONTROL);
145
146 /* external PULL to down, bit 22 = 0 */
147 omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
148}
149
150void omap_pm_suspend(void)
151{
152 unsigned int mask32 = 0;
153 unsigned long arg0 = 0, arg1 = 0;
154 int (*func_ptr)(unsigned short, unsigned short) = 0;
155 unsigned short save_dsp_idlect2;
156
157 printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev);
158
159 if (machine_is_omap_osk()) {
160 /* Stop LED1 (D9) blink */
161 tps65010_set_led(LED1, OFF);
162 }
163
164 /*
165 * Step 1: turn off interrupts
166 */
167
168 local_irq_disable();
169 local_fiq_disable();
170
171 /*
172 * Step 2: save registers
173 *
174 * The omap is a strange/beautiful device. The caches, memory
175 * and register state are preserved across power saves.
176 * We have to save and restore very little register state to
177 * idle the omap.
178 *
179 * Save interrupt, MPUI, ARM and UPLD control registers.
180 */
181
182 if (cpu_is_omap1510()) {
183 MPUI1510_SAVE(OMAP_IH1_MIR);
184 MPUI1510_SAVE(OMAP_IH2_MIR);
185 MPUI1510_SAVE(MPUI_CTRL);
186 MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
187 MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
188 MPUI1510_SAVE(EMIFS_CONFIG);
189 MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
190 } else if (cpu_is_omap16xx()) {
191 MPUI1610_SAVE(OMAP_IH1_MIR);
192 MPUI1610_SAVE(OMAP_IH2_0_MIR);
193 MPUI1610_SAVE(OMAP_IH2_1_MIR);
194 MPUI1610_SAVE(OMAP_IH2_2_MIR);
195 MPUI1610_SAVE(OMAP_IH2_3_MIR);
196 MPUI1610_SAVE(MPUI_CTRL);
197 MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
198 MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
199 MPUI1610_SAVE(EMIFS_CONFIG);
200 MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
201 }
202
203 ARM_SAVE(ARM_CKCTL);
204 ARM_SAVE(ARM_IDLECT1);
205 ARM_SAVE(ARM_IDLECT2);
206 ARM_SAVE(ARM_EWUPCT);
207 ARM_SAVE(ARM_RSTCT1);
208 ARM_SAVE(ARM_RSTCT2);
209 ARM_SAVE(ARM_SYSST);
210 ULPD_SAVE(ULPD_CLOCK_CTRL);
211 ULPD_SAVE(ULPD_STATUS_REQ);
212
213 /*
214 * Step 3: LOW_PWR signal enabling
215 *
216 * Allow the LOW_PWR signal to be visible on MPUIO5 ball.
217 */
218 if (cpu_is_omap1510()) {
219 /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
220 omap_writew(omap_readw(ULPD_POWER_CTRL) |
221 OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
222 } else if (cpu_is_omap16xx()) {
223 /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
224 omap_writew(omap_readw(ULPD_POWER_CTRL) |
225 OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
226 }
227
228 /* configure LOW_PWR pin */
229 omap_cfg_reg(T20_1610_LOW_PWR);
230
231 /*
232 * Step 4: OMAP DSP Shutdown
233 */
234
235 /* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */
236 omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE,
237 ARM_RSTCT1);
238
239 /* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */
240 omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG);
241
242 /* Set EN_DSPCK = 0, stop DSP block clock */
243 omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL);
244
245 /* Stop any DSP domain clocks */
246 omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
247 save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
248 __raw_writew(0, DSP_IDLECT2);
249
250 /*
251 * Step 5: Wakeup Event Setup
252 */
253
254 omap_pm_wakeup_setup();
255
256 /*
257 * Step 6a: ARM and Traffic controller shutdown
258 *
259 * Step 6 starts here with clock and watchdog disable
260 */
261
262 /* stop clocks */
263 mask32 = omap_readl(ARM_IDLECT2);
264 mask32 &= ~(1<<EN_WDTCK); /* bit 0 -> 0 (WDT clock) */
265 mask32 |= (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
266 mask32 &= ~(1<<EN_PERCK); /* bit 2 -> 0 (MPUPER_CK clock) */
267 mask32 &= ~(1<<EN_LCDCK); /* bit 3 -> 0 (LCDC clock) */
268 mask32 &= ~(1<<EN_LBCK); /* bit 4 -> 0 (local bus clock) */
269 mask32 |= (1<<EN_APICK); /* bit 6 -> 1 (MPUI clock) */
270 mask32 &= ~(1<<EN_TIMCK); /* bit 7 -> 0 (MPU timer clock) */
271 mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
272 mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
273 omap_writel(mask32, ARM_IDLECT2);
274
275 /* disable ARM watchdog */
276 omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
277 omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
278
279 /*
280 * Step 6b: ARM and Traffic controller shutdown
281 *
282 * Step 6 continues here. Prepare jump to power management
283 * assembly code in internal SRAM.
284 *
285 * Since the omap_cpu_suspend routine has been copied to
286 * SRAM, we'll do an indirect procedure call to it and pass the
287 * contents of arm_idlect1 and arm_idlect2 so it can restore
288 * them when it wakes up and it will return.
289 */
290
291 arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
292 arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
293
294 if (cpu_is_omap1510()) {
295 func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
296 } else if (cpu_is_omap1610() || cpu_is_omap1710()) {
297 func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
298 } else if (cpu_is_omap5912()) {
299 func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
300 }
301
302 /*
303 * Step 6c: ARM and Traffic controller shutdown
304 *
305 * Jump to assembly code. The processor will stay there
306 * until wake up.
307 */
308
309 func_ptr(arg0, arg1);
310
311 /*
312 * If we are here, processor is woken up!
313 */
314
315 if (cpu_is_omap1510()) {
316 /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
317 omap_writew(omap_readw(ULPD_POWER_CTRL) &
318 ~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
319 } else if (cpu_is_omap16xx()) {
320 /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
321 omap_writew(omap_readw(ULPD_POWER_CTRL) &
322 ~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
323 }
324
325
326 /* Restore DSP clocks */
327 omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
328 __raw_writew(save_dsp_idlect2, DSP_IDLECT2);
329 ARM_RESTORE(ARM_IDLECT2);
330
331 /*
332 * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
333 */
334
335 ARM_RESTORE(ARM_CKCTL);
336 ARM_RESTORE(ARM_EWUPCT);
337 ARM_RESTORE(ARM_RSTCT1);
338 ARM_RESTORE(ARM_RSTCT2);
339 ARM_RESTORE(ARM_SYSST);
340 ULPD_RESTORE(ULPD_CLOCK_CTRL);
341 ULPD_RESTORE(ULPD_STATUS_REQ);
342
343 if (cpu_is_omap1510()) {
344 MPUI1510_RESTORE(MPUI_CTRL);
345 MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
346 MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
347 MPUI1510_RESTORE(EMIFS_CONFIG);
348 MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
349 MPUI1510_RESTORE(OMAP_IH1_MIR);
350 MPUI1510_RESTORE(OMAP_IH2_MIR);
351 } else if (cpu_is_omap16xx()) {
352 MPUI1610_RESTORE(MPUI_CTRL);
353 MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
354 MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
355 MPUI1610_RESTORE(EMIFS_CONFIG);
356 MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
357
358 MPUI1610_RESTORE(OMAP_IH1_MIR);
359 MPUI1610_RESTORE(OMAP_IH2_0_MIR);
360 MPUI1610_RESTORE(OMAP_IH2_1_MIR);
361 MPUI1610_RESTORE(OMAP_IH2_2_MIR);
362 MPUI1610_RESTORE(OMAP_IH2_3_MIR);
363 }
364
365 /*
366 * Reenable interrupts
367 */
368
369 local_irq_enable();
370 local_fiq_enable();
371
372 printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
373
374 if (machine_is_omap_osk()) {
375 /* Let LED1 (D9) blink again */
376 tps65010_set_led(LED1, BLINK);
377 }
378}
379
380#if defined(DEBUG) && defined(CONFIG_PROC_FS)
381static int g_read_completed;
382
383/*
384 * Read system PM registers for debugging
385 */
386static int omap_pm_read_proc(
387 char *page_buffer,
388 char **my_first_byte,
389 off_t virtual_start,
390 int length,
391 int *eof,
392 void *data)
393{
394 int my_buffer_offset = 0;
395 char * const my_base = page_buffer;
396
397 ARM_SAVE(ARM_CKCTL);
398 ARM_SAVE(ARM_IDLECT1);
399 ARM_SAVE(ARM_IDLECT2);
400 ARM_SAVE(ARM_EWUPCT);
401 ARM_SAVE(ARM_RSTCT1);
402 ARM_SAVE(ARM_RSTCT2);
403 ARM_SAVE(ARM_SYSST);
404
405 ULPD_SAVE(ULPD_IT_STATUS);
406 ULPD_SAVE(ULPD_CLOCK_CTRL);
407 ULPD_SAVE(ULPD_SOFT_REQ);
408 ULPD_SAVE(ULPD_STATUS_REQ);
409 ULPD_SAVE(ULPD_DPLL_CTRL);
410 ULPD_SAVE(ULPD_POWER_CTRL);
411
412 if (cpu_is_omap1510()) {
413 MPUI1510_SAVE(MPUI_CTRL);
414 MPUI1510_SAVE(MPUI_DSP_STATUS);
415 MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
416 MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
417 MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
418 MPUI1510_SAVE(EMIFS_CONFIG);
419 } else if (cpu_is_omap16xx()) {
420 MPUI1610_SAVE(MPUI_CTRL);
421 MPUI1610_SAVE(MPUI_DSP_STATUS);
422 MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
423 MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
424 MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
425 MPUI1610_SAVE(EMIFS_CONFIG);
426 }
427
428 if (virtual_start == 0) {
429 g_read_completed = 0;
430
431 my_buffer_offset += sprintf(my_base + my_buffer_offset,
432 "ARM_CKCTL_REG: 0x%-8x \n"
433 "ARM_IDLECT1_REG: 0x%-8x \n"
434 "ARM_IDLECT2_REG: 0x%-8x \n"
435 "ARM_EWUPCT_REG: 0x%-8x \n"
436 "ARM_RSTCT1_REG: 0x%-8x \n"
437 "ARM_RSTCT2_REG: 0x%-8x \n"
438 "ARM_SYSST_REG: 0x%-8x \n"
439 "ULPD_IT_STATUS_REG: 0x%-4x \n"
440 "ULPD_CLOCK_CTRL_REG: 0x%-4x \n"
441 "ULPD_SOFT_REQ_REG: 0x%-4x \n"
442 "ULPD_DPLL_CTRL_REG: 0x%-4x \n"
443 "ULPD_STATUS_REQ_REG: 0x%-4x \n"
444 "ULPD_POWER_CTRL_REG: 0x%-4x \n",
445 ARM_SHOW(ARM_CKCTL),
446 ARM_SHOW(ARM_IDLECT1),
447 ARM_SHOW(ARM_IDLECT2),
448 ARM_SHOW(ARM_EWUPCT),
449 ARM_SHOW(ARM_RSTCT1),
450 ARM_SHOW(ARM_RSTCT2),
451 ARM_SHOW(ARM_SYSST),
452 ULPD_SHOW(ULPD_IT_STATUS),
453 ULPD_SHOW(ULPD_CLOCK_CTRL),
454 ULPD_SHOW(ULPD_SOFT_REQ),
455 ULPD_SHOW(ULPD_DPLL_CTRL),
456 ULPD_SHOW(ULPD_STATUS_REQ),
457 ULPD_SHOW(ULPD_POWER_CTRL));
458
459 if (cpu_is_omap1510()) {
460 my_buffer_offset += sprintf(my_base + my_buffer_offset,
461 "MPUI1510_CTRL_REG 0x%-8x \n"
462 "MPUI1510_DSP_STATUS_REG: 0x%-8x \n"
463 "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
464 "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n"
465 "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n"
466 "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n",
467 MPUI1510_SHOW(MPUI_CTRL),
468 MPUI1510_SHOW(MPUI_DSP_STATUS),
469 MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
470 MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
471 MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
472 MPUI1510_SHOW(EMIFS_CONFIG));
473 } else if (cpu_is_omap16xx()) {
474 my_buffer_offset += sprintf(my_base + my_buffer_offset,
475 "MPUI1610_CTRL_REG 0x%-8x \n"
476 "MPUI1610_DSP_STATUS_REG: 0x%-8x \n"
477 "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
478 "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n"
479 "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n"
480 "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n",
481 MPUI1610_SHOW(MPUI_CTRL),
482 MPUI1610_SHOW(MPUI_DSP_STATUS),
483 MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
484 MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
485 MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
486 MPUI1610_SHOW(EMIFS_CONFIG));
487 }
488
489 g_read_completed++;
490 } else if (g_read_completed >= 1) {
491 *eof = 1;
492 return 0;
493 }
494 g_read_completed++;
495
496 *my_first_byte = page_buffer;
497 return my_buffer_offset;
498}
499
500static void omap_pm_init_proc(void)
501{
502 struct proc_dir_entry *entry;
503
504 entry = create_proc_read_entry("driver/omap_pm",
505 S_IWUSR | S_IRUGO, NULL,
506 omap_pm_read_proc, 0);
507}
508
509#endif /* DEBUG && CONFIG_PROC_FS */
510
511/*
512 * omap_pm_prepare - Do preliminary suspend work.
513 * @state: suspend state we're entering.
514 *
515 */
516//#include <asm/arch/hardware.h>
517
518static int omap_pm_prepare(suspend_state_t state)
519{
520 int error = 0;
521
522 switch (state)
523 {
524 case PM_SUSPEND_STANDBY:
525 case PM_SUSPEND_MEM:
526 break;
527
528 case PM_SUSPEND_DISK:
529 return -ENOTSUPP;
530
531 default:
532 return -EINVAL;
533 }
534
535 return error;
536}
537
538
539/*
540 * omap_pm_enter - Actually enter a sleep state.
541 * @state: State we're entering.
542 *
543 */
544
545static int omap_pm_enter(suspend_state_t state)
546{
547 switch (state)
548 {
549 case PM_SUSPEND_STANDBY:
550 case PM_SUSPEND_MEM:
551 omap_pm_suspend();
552 break;
553
554 case PM_SUSPEND_DISK:
555 return -ENOTSUPP;
556
557 default:
558 return -EINVAL;
559 }
560
561 return 0;
562}
563
564
565/**
566 * omap_pm_finish - Finish up suspend sequence.
567 * @state: State we're coming out of.
568 *
569 * This is called after we wake back up (or if entering the sleep state
570 * failed).
571 */
572
573static int omap_pm_finish(suspend_state_t state)
574{
575 return 0;
576}
577
578
579struct pm_ops omap_pm_ops ={
580 .pm_disk_mode = 0,
581 .prepare = omap_pm_prepare,
582 .enter = omap_pm_enter,
583 .finish = omap_pm_finish,
584};
585
586static int __init omap_pm_init(void)
587{
588 printk("Power Management for TI OMAP.\n");
589 pm_idle = omap_pm_idle;
590 /*
591 * We copy the assembler sleep/wakeup routines to SRAM.
592 * These routines need to be in SRAM as that's the only
593 * memory the MPU can see when it wakes up.
594 */
595
596#ifdef CONFIG_ARCH_OMAP1510
597 if (cpu_is_omap1510()) {
598 memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
599 omap1510_idle_loop_suspend,
600 omap1510_idle_loop_suspend_sz);
601 memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
602 omap1510_cpu_suspend_sz);
603 } else
604#endif
605 if (cpu_is_omap1610() || cpu_is_omap1710()) {
606 memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
607 omap1610_idle_loop_suspend,
608 omap1610_idle_loop_suspend_sz);
609 memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
610 omap1610_cpu_suspend_sz);
611 } else if (cpu_is_omap5912()) {
612 memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
613 omap1610_idle_loop_suspend,
614 omap1610_idle_loop_suspend_sz);
615 memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
616 omap1610_cpu_suspend_sz);
617 }
618
619 pm_set_ops(&omap_pm_ops);
620
621#if defined(DEBUG) && defined(CONFIG_PROC_FS)
622 omap_pm_init_proc();
623#endif
624
625 return 0;
626}
627__initcall(omap_pm_init);
628
diff --git a/arch/arm/mach-omap/sleep.S b/arch/arm/mach-omap/sleep.S
new file mode 100644
index 000000000000..4d426d105828
--- /dev/null
+++ b/arch/arm/mach-omap/sleep.S
@@ -0,0 +1,314 @@
1/*
2 * linux/arch/arm/mach-omap/sleep.S
3 *
4 * Low-level OMAP1510/1610 sleep/wakeUp support
5 *
6 * Initial SA1110 code:
7 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
8 *
9 * Adapted for PXA by Nicolas Pitre:
10 * Copyright (c) 2002 Monta Vista Software, Inc.
11 *
12 * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
18 *
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * You should have received a copy of the GNU General Public License along
31 * with this program; if not, write to the Free Software Foundation, Inc.,
32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 */
34
35#include <linux/config.h>
36#include <linux/linkage.h>
37#include <asm/assembler.h>
38#include <asm/arch/io.h>
39#include <asm/arch/pm.h>
40
41 .text
42
43/*
44 * Forces OMAP into idle state
45 *
46 * omapXXXX_idle_loop_suspend()
47 *
48 * Note: This code get's copied to internal SRAM at boot. When the OMAP
49 * wakes up it continues execution at the point it went to sleep.
50 *
51 * Note: Because of slightly different configuration values we have
52 * processor specific functions here.
53 */
54
55#ifdef CONFIG_ARCH_OMAP1510
56ENTRY(omap1510_idle_loop_suspend)
57
58 stmfd sp!, {r0 - r12, lr} @ save registers on stack
59
60 @ load base address of ARM_IDLECT1 and ARM_IDLECT2
61 mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
62 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
63 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
64
65 @ turn off clock domains
66 @ get ARM_IDLECT2 into r2
67 ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
68 mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
69 orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
70 strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
71
72 @ request ARM idle
73 @ get ARM_IDLECT1 into r1
74 ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
75 orr r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff
76 strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
77
78 mov r5, #IDLE_WAIT_CYCLES & 0xff
79 orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
80l_1510: subs r5, r5, #1
81 bne l_1510
82/*
83 * Let's wait for the next clock tick to wake us up.
84 */
85 mov r0, #0
86 mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
87/*
88 * omap1510_idle_loop_suspend()'s resume point.
89 *
90 * It will just start executing here, so we'll restore stuff from the
91 * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
92 */
93
94 @ restore ARM_IDLECT1 and ARM_IDLECT2 and return
95 @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
96 strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
97 strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
98
99 ldmfd sp!, {r0 - r12, pc} @ restore regs and return
100
101ENTRY(omap1510_idle_loop_suspend_sz)
102 .word . - omap1510_idle_loop_suspend
103#endif /* CONFIG_ARCH_OMAP1510 */
104
105#if defined(CONFIG_ARCH_OMAP16XX)
106ENTRY(omap1610_idle_loop_suspend)
107
108 stmfd sp!, {r0 - r12, lr} @ save registers on stack
109
110 @ load base address of ARM_IDLECT1 and ARM_IDLECT2
111 mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
112 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
113 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
114
115 @ turn off clock domains
116 @ get ARM_IDLECT2 into r2
117 ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
118 mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
119 orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
120 strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
121
122 @ request ARM idle
123 @ get ARM_IDLECT1 into r1
124 ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
125 orr r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff
126 strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
127
128 mov r5, #IDLE_WAIT_CYCLES & 0xff
129 orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
130l_1610: subs r5, r5, #1
131 bne l_1610
132/*
133 * Let's wait for the next clock tick to wake us up.
134 */
135 mov r0, #0
136 mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
137/*
138 * omap1610_idle_loop_suspend()'s resume point.
139 *
140 * It will just start executing here, so we'll restore stuff from the
141 * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
142 */
143
144 @ restore ARM_IDLECT1 and ARM_IDLECT2 and return
145 @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
146 strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
147 strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
148
149 ldmfd sp!, {r0 - r12, pc} @ restore regs and return
150
151ENTRY(omap1610_idle_loop_suspend_sz)
152 .word . - omap1610_idle_loop_suspend
153#endif /* CONFIG_ARCH_OMAP16XX */
154
155/*
156 * Forces OMAP into deep sleep state
157 *
158 * omapXXXX_cpu_suspend()
159 *
160 * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
161 * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
162 * in register r1.
163 *
164 * Note: This code get's copied to internal SRAM at boot. When the OMAP
165 * wakes up it continues execution at the point it went to sleep.
166 *
167 * Note: Because of errata work arounds we have processor specific functions
168 * here. They are mostly the same, but slightly different.
169 *
170 */
171
172#ifdef CONFIG_ARCH_OMAP1510
173ENTRY(omap1510_cpu_suspend)
174
175 @ save registers on stack
176 stmfd sp!, {r0 - r12, lr}
177
178 @ load base address of Traffic Controller
179 mov r4, #TCMIF_ASM_BASE & 0xff000000
180 orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
181 orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
182
183 @ work around errata of OMAP1510 PDE bit for TC shut down
184 @ clear PDE bit
185 ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
186 bic r5, r5, #PDE_BIT & 0xff
187 str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
188
189 @ set PWD_EN bit
190 and r5, r5, #PWD_EN_BIT & 0xff
191 str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
192
193 @ prepare to put SDRAM into self-refresh manually
194 ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
195 orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
196 orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
197 str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
198
199 @ prepare to put EMIFS to Sleep
200 ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
201 orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
202 str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
203
204 @ load base address of ARM_IDLECT1 and ARM_IDLECT2
205 mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
206 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
207 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
208
209 @ turn off clock domains
210 mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
211 orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
212 strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
213
214 @ request ARM idle
215 mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
216 orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
217 strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
218
219 mov r5, #IDLE_WAIT_CYCLES & 0xff
220 orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
221l_1510_2:
222 subs r5, r5, #1
223 bne l_1510_2
224/*
225 * Let's wait for the next wake up event to wake us up. r0 can't be
226 * used here because r0 holds ARM_IDLECT1
227 */
228 mov r2, #0
229 mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
230/*
231 * omap1510_cpu_suspend()'s resume point.
232 *
233 * It will just start executing here, so we'll restore stuff from the
234 * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
235 */
236 strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
237 strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
238
239 @ restore regs and return
240 ldmfd sp!, {r0 - r12, pc}
241
242ENTRY(omap1510_cpu_suspend_sz)
243 .word . - omap1510_cpu_suspend
244#endif /* CONFIG_ARCH_OMAP1510 */
245
246#if defined(CONFIG_ARCH_OMAP16XX)
247ENTRY(omap1610_cpu_suspend)
248
249 @ save registers on stack
250 stmfd sp!, {r0 - r12, lr}
251
252 @ load base address of Traffic Controller
253 mov r4, #TCMIF_ASM_BASE & 0xff000000
254 orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
255 orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
256
257 @ prepare to put SDRAM into self-refresh manually
258 ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
259 orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
260 orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
261 str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
262
263 @ prepare to put EMIFS to Sleep
264 ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
265 orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
266 str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
267
268 @ load base address of ARM_IDLECT1 and ARM_IDLECT2
269 mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
270 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
271 orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
272
273 @ turn off clock domains
274 mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
275 orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
276 strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
277
278 @ work around errata of OMAP1610/5912. Enable (!) peripheral
279 @ clock to let the chip go into deep sleep
280 ldrh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
281 orr r5,r5, #EN_PERCK_BIT & 0xff
282 strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
283
284 @ request ARM idle
285 mov r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff
286 orr r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00
287 strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
288
289 mov r5, #IDLE_WAIT_CYCLES & 0xff
290 orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
291l_1610_2:
292 subs r5, r5, #1
293 bne l_1610_2
294/*
295 * Let's wait for the next wake up event to wake us up. r0 can't be
296 * used here because r0 holds ARM_IDLECT1
297 */
298 mov r2, #0
299 mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
300/*
301 * omap1610_cpu_suspend()'s resume point.
302 *
303 * It will just start executing here, so we'll restore stuff from the
304 * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
305 */
306 strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
307 strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
308
309 @ restore regs and return
310 ldmfd sp!, {r0 - r12, pc}
311
312ENTRY(omap1610_cpu_suspend_sz)
313 .word . - omap1610_cpu_suspend
314#endif /* CONFIG_ARCH_OMAP16XX */
diff --git a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c
new file mode 100644
index 000000000000..4205fdcb632c
--- /dev/null
+++ b/arch/arm/mach-omap/time.c
@@ -0,0 +1,384 @@
1/*
2 * linux/arch/arm/mach-omap/time.c
3 *
4 * OMAP Timers
5 *
6 * Copyright (C) 2004 Nokia Corporation
7 * Partial timer rewrite and additional VST 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_TIMER1_BASE (0xfffec500)
62#define OMAP_MPU_TIMER2_BASE (0xfffec600)
63#define OMAP_MPU_TIMER3_BASE (0xfffec700)
64#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
65#define OMAP_MPU_TIMER_OFFSET 0x100
66
67#define MPU_TIMER_FREE (1 << 6)
68#define MPU_TIMER_CLOCK_ENABLE (1 << 5)
69#define MPU_TIMER_AR (1 << 1)
70#define MPU_TIMER_ST (1 << 0)
71
72/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
73 * converted to use kHz by Kevin Hilman */
74/* convert from cycles(64bits) => nanoseconds (64bits)
75 * basic equation:
76 * ns = cycles / (freq / ns_per_sec)
77 * ns = cycles * (ns_per_sec / freq)
78 * ns = cycles * (10^9 / (cpu_khz * 10^3))
79 * ns = cycles * (10^6 / cpu_khz)
80 *
81 * Then we use scaling math (suggested by george at mvista.com) to get:
82 * ns = cycles * (10^6 * SC / cpu_khz / SC
83 * ns = cycles * cyc2ns_scale / SC
84 *
85 * And since SC is a constant power of two, we can convert the div
86 * into a shift.
87 * -johnstul at us.ibm.com "math is hard, lets go shopping!"
88 */
89static unsigned long cyc2ns_scale;
90#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
91
92static inline void set_cyc2ns_scale(unsigned long cpu_khz)
93{
94 cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
95}
96
97static inline unsigned long long cycles_2_ns(unsigned long long cyc)
98{
99 return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
100}
101
102/*
103 * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
104 * will break. On P2, the timer count rate is 6.5 MHz after programming PTV
105 * with 0. This divides the 13MHz input by 2, and is undocumented.
106 */
107#ifdef CONFIG_MACH_OMAP_PERSEUS2
108/* REVISIT: This ifdef construct should be replaced by a query to clock
109 * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz.
110 */
111#define MPU_TICKS_PER_SEC (13000000 / 2)
112#else
113#define MPU_TICKS_PER_SEC (12000000 / 2)
114#endif
115
116#define MPU_TIMER_TICK_PERIOD ((MPU_TICKS_PER_SEC / HZ) - 1)
117
118typedef struct {
119 u32 cntl; /* CNTL_TIMER, R/W */
120 u32 load_tim; /* LOAD_TIM, W */
121 u32 read_tim; /* READ_TIM, R */
122} omap_mpu_timer_regs_t;
123
124#define omap_mpu_timer_base(n) \
125((volatile omap_mpu_timer_regs_t*)IO_ADDRESS(OMAP_MPU_TIMER_BASE + \
126 (n)*OMAP_MPU_TIMER_OFFSET))
127
128static inline unsigned long omap_mpu_timer_read(int nr)
129{
130 volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
131 return timer->read_tim;
132}
133
134static inline void omap_mpu_timer_start(int nr, unsigned long load_val)
135{
136 volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
137
138 timer->cntl = MPU_TIMER_CLOCK_ENABLE;
139 udelay(1);
140 timer->load_tim = load_val;
141 udelay(1);
142 timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST);
143}
144
145unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
146{
147 unsigned long long nsec;
148
149 nsec = cycles_2_ns((unsigned long long)nr_ticks);
150 return (unsigned long)nsec / 1000;
151}
152
153/*
154 * Last processed system timer interrupt
155 */
156static unsigned long omap_mpu_timer_last = 0;
157
158/*
159 * Returns elapsed usecs since last system timer interrupt
160 */
161static unsigned long omap_mpu_timer_gettimeoffset(void)
162{
163 unsigned long now = 0 - omap_mpu_timer_read(0);
164 unsigned long elapsed = now - omap_mpu_timer_last;
165
166 return omap_mpu_timer_ticks_to_usecs(elapsed);
167}
168
169/*
170 * Elapsed time between interrupts is calculated using timer0.
171 * Latency during the interrupt is calculated using timer1.
172 * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz).
173 */
174static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id,
175 struct pt_regs *regs)
176{
177 unsigned long now, latency;
178
179 write_seqlock(&xtime_lock);
180 now = 0 - omap_mpu_timer_read(0);
181 latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1);
182 omap_mpu_timer_last = now - latency;
183 timer_tick(regs);
184 write_sequnlock(&xtime_lock);
185
186 return IRQ_HANDLED;
187}
188
189static struct irqaction omap_mpu_timer_irq = {
190 .name = "mpu timer",
191 .flags = SA_INTERRUPT,
192 .handler = omap_mpu_timer_interrupt
193};
194
195static unsigned long omap_mpu_timer1_overflows;
196static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id,
197 struct pt_regs *regs)
198{
199 omap_mpu_timer1_overflows++;
200 return IRQ_HANDLED;
201}
202
203static struct irqaction omap_mpu_timer1_irq = {
204 .name = "mpu timer1 overflow",
205 .flags = SA_INTERRUPT,
206 .handler = omap_mpu_timer1_interrupt
207};
208
209static __init void omap_init_mpu_timer(void)
210{
211 set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
212 omap_timer.offset = omap_mpu_timer_gettimeoffset;
213 setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
214 setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
215 omap_mpu_timer_start(0, 0xffffffff);
216 omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
217}
218
219/*
220 * Scheduler clock - returns current time in nanosec units.
221 */
222unsigned long long sched_clock(void)
223{
224 unsigned long ticks = 0 - omap_mpu_timer_read(0);
225 unsigned long long ticks64;
226
227 ticks64 = omap_mpu_timer1_overflows;
228 ticks64 <<= 32;
229 ticks64 |= ticks;
230
231 return cycles_2_ns(ticks64);
232}
233#endif /* CONFIG_OMAP_MPU_TIMER */
234
235#ifdef CONFIG_OMAP_32K_TIMER
236
237#ifdef CONFIG_ARCH_OMAP1510
238#error OMAP 32KHz timer does not currently work on 1510!
239#endif
240
241/*
242 * ---------------------------------------------------------------------------
243 * 32KHz OS timer
244 *
245 * This currently works only on 16xx, as 1510 does not have the continuous
246 * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
247 * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
248 * on 1510 would be possible, but the timer would not be as accurate as
249 * with the 32KHz synchronized timer.
250 * ---------------------------------------------------------------------------
251 */
252#define OMAP_32K_TIMER_BASE 0xfffb9000
253#define OMAP_32K_TIMER_CR 0x08
254#define OMAP_32K_TIMER_TVR 0x00
255#define OMAP_32K_TIMER_TCR 0x04
256
257#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
258
259/*
260 * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
261 * so with HZ = 100, TVR = 327.68.
262 */
263#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
264#define MAX_SKIP_JIFFIES 25
265#define TIMER_32K_SYNCHRONIZED 0xfffbc410
266
267#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
268 (((nr_jiffies) * (clock_rate)) / HZ)
269
270static inline void omap_32k_timer_write(int val, int reg)
271{
272 omap_writew(val, reg + OMAP_32K_TIMER_BASE);
273}
274
275static inline unsigned long omap_32k_timer_read(int reg)
276{
277 return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff;
278}
279
280/*
281 * The 32KHz synchronized timer is an additional timer on 16xx.
282 * It is always running.
283 */
284static inline unsigned long omap_32k_sync_timer_read(void)
285{
286 return omap_readl(TIMER_32K_SYNCHRONIZED);
287}
288
289static inline void omap_32k_timer_start(unsigned long load_val)
290{
291 omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR);
292 omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR);
293}
294
295static inline void omap_32k_timer_stop(void)
296{
297 omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR);
298}
299
300/*
301 * Rounds down to nearest usec
302 */
303static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
304{
305 return (ticks_32k * 5*5*5*5*5*5) >> 9;
306}
307
308static unsigned long omap_32k_last_tick = 0;
309
310/*
311 * Returns elapsed usecs since last 32k timer interrupt
312 */
313static unsigned long omap_32k_timer_gettimeoffset(void)
314{
315 unsigned long now = omap_32k_sync_timer_read();
316 return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
317}
318
319/*
320 * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
321 * function is also called from other interrupts to remove latency
322 * issues with dynamic tick. In the dynamic tick case, we need to lock
323 * with irqsave.
324 */
325static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
326 struct pt_regs *regs)
327{
328 unsigned long flags;
329 unsigned long now;
330
331 write_seqlock_irqsave(&xtime_lock, flags);
332 now = omap_32k_sync_timer_read();
333
334 while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
335 omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
336 timer_tick(regs);
337 }
338
339 /* Restart timer so we don't drift off due to modulo or dynamic tick.
340 * By default we program the next timer to be continuous to avoid
341 * latencies during high system load. During dynamic tick operation the
342 * continuous timer can be overridden from pm_idle to be longer.
343 */
344 omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
345 write_sequnlock_irqrestore(&xtime_lock, flags);
346
347 return IRQ_HANDLED;
348}
349
350static struct irqaction omap_32k_timer_irq = {
351 .name = "32KHz timer",
352 .flags = SA_INTERRUPT,
353 .handler = omap_32k_timer_interrupt
354};
355
356static __init void omap_init_32k_timer(void)
357{
358 setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
359 omap_timer.offset = omap_32k_timer_gettimeoffset;
360 omap_32k_last_tick = omap_32k_sync_timer_read();
361 omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
362}
363#endif /* CONFIG_OMAP_32K_TIMER */
364
365/*
366 * ---------------------------------------------------------------------------
367 * Timer initialization
368 * ---------------------------------------------------------------------------
369 */
370void __init omap_timer_init(void)
371{
372#if defined(CONFIG_OMAP_MPU_TIMER)
373 omap_init_mpu_timer();
374#elif defined(CONFIG_OMAP_32K_TIMER)
375 omap_init_32k_timer();
376#else
377#error No system timer selected in Kconfig!
378#endif
379}
380
381struct sys_timer omap_timer = {
382 .init = omap_timer_init,
383 .offset = NULL, /* Initialized later */
384};
diff --git a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c
new file mode 100644
index 000000000000..6e805d451d0e
--- /dev/null
+++ b/arch/arm/mach-omap/usb.c
@@ -0,0 +1,594 @@
1/*
2 * arch/arm/mach-omap/usb.c -- platform level USB initialization
3 *
4 * Copyright (C) 2004 Texas Instruments, Inc.
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 as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#undef DEBUG
22
23#include <linux/config.h>
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/types.h>
27#include <linux/errno.h>
28#include <linux/init.h>
29#include <linux/device.h>
30#include <linux/usb_otg.h>
31
32#include <asm/io.h>
33#include <asm/irq.h>
34#include <asm/system.h>
35#include <asm/hardware.h>
36#include <asm/mach-types.h>
37
38#include <asm/arch/mux.h>
39#include <asm/arch/usb.h>
40#include <asm/arch/board.h>
41
42/* These routines should handle the standard chip-specific modes
43 * for usb0/1/2 ports, covering basic mux and transceiver setup.
44 * Call omap_usb_init() once, from INIT_MACHINE().
45 *
46 * Some board-*.c files will need to set up additional mux options,
47 * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
48 */
49
50/* TESTED ON:
51 * - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables
52 * - 5912 OSK OHCI (with usb0 standard-A), standard A-to-B cables
53 * - 5912 OSK UDC, with *nonstandard* A-to-A cable
54 * - 1510 Innovator UDC with bundled usb0 cable
55 * - 1510 Innovator OHCI with bundled usb1/usb2 cable
56 * - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS
57 * - 1710 custom development board using alternate pin group
58 * - 1710 H3 (with usb1 mini-AB) using standard Mini-B or OTG cables
59 */
60
61/*-------------------------------------------------------------------------*/
62
63#ifdef CONFIG_ARCH_OMAP_OTG
64
65static struct otg_transceiver *xceiv;
66
67/**
68 * otg_get_transceiver - find the (single) OTG transceiver driver
69 *
70 * Returns the transceiver driver, after getting a refcount to it; or
71 * null if there is no such transceiver. The caller is responsible for
72 * releasing that count.
73 */
74struct otg_transceiver *otg_get_transceiver(void)
75{
76 if (xceiv)
77 get_device(xceiv->dev);
78 return xceiv;
79}
80EXPORT_SYMBOL(otg_get_transceiver);
81
82int otg_set_transceiver(struct otg_transceiver *x)
83{
84 if (xceiv && x)
85 return -EBUSY;
86 xceiv = x;
87 return 0;
88}
89EXPORT_SYMBOL(otg_set_transceiver);
90
91#endif
92
93/*-------------------------------------------------------------------------*/
94
95static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
96{
97 u32 syscon1 = 0;
98
99 if (nwires == 0) {
100 if (!cpu_is_omap15xx()) {
101 /* pulldown D+/D- */
102 USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
103 }
104 return 0;
105 }
106
107 if (is_device)
108 omap_cfg_reg(W4_USB_PUEN);
109
110 /* internal transceiver */
111 if (nwires == 2) {
112 // omap_cfg_reg(P9_USB_DP);
113 // omap_cfg_reg(R8_USB_DM);
114
115 if (cpu_is_omap15xx()) {
116 /* This works on 1510-Innovator */
117 return 0;
118 }
119
120 /* NOTES:
121 * - peripheral should configure VBUS detection!
122 * - only peripherals may use the internal D+/D- pulldowns
123 * - OTG support on this port not yet written
124 */
125
126 USB_TRANSCEIVER_CTRL_REG &= ~(7 << 4);
127 if (!is_device)
128 USB_TRANSCEIVER_CTRL_REG |= (3 << 1);
129
130 return 3 << 16;
131 }
132
133 /* alternate pin config, external transceiver */
134 if (cpu_is_omap15xx()) {
135 printk(KERN_ERR "no usb0 alt pin config on 15xx\n");
136 return 0;
137 }
138
139 omap_cfg_reg(V6_USB0_TXD);
140 omap_cfg_reg(W9_USB0_TXEN);
141 omap_cfg_reg(W5_USB0_SE0);
142
143 /* NOTE: SPEED and SUSP aren't configured here */
144
145 if (nwires != 3)
146 omap_cfg_reg(Y5_USB0_RCV);
147 if (nwires != 6)
148 USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
149
150 switch (nwires) {
151 case 3:
152 syscon1 = 2;
153 break;
154 case 4:
155 syscon1 = 1;
156 break;
157 case 6:
158 syscon1 = 3;
159 omap_cfg_reg(AA9_USB0_VP);
160 omap_cfg_reg(R9_USB0_VM);
161 USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
162 break;
163 default:
164 printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
165 0, nwires);
166 }
167 return syscon1 << 16;
168}
169
170static u32 __init omap_usb1_init(unsigned nwires)
171{
172 u32 syscon1 = 0;
173
174 if (nwires != 6 && !cpu_is_omap15xx())
175 USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
176 if (nwires == 0)
177 return 0;
178
179 /* external transceiver */
180 omap_cfg_reg(USB1_TXD);
181 omap_cfg_reg(USB1_TXEN);
182 if (cpu_is_omap15xx()) {
183 omap_cfg_reg(USB1_SEO);
184 omap_cfg_reg(USB1_SPEED);
185 // SUSP
186 } else if (cpu_is_omap1610() || cpu_is_omap5912()) {
187 omap_cfg_reg(W13_1610_USB1_SE0);
188 omap_cfg_reg(R13_1610_USB1_SPEED);
189 // SUSP
190 } else if (cpu_is_omap1710()) {
191 omap_cfg_reg(R13_1710_USB1_SE0);
192 // SUSP
193 } else {
194 pr_debug("usb unrecognized\n");
195 }
196 if (nwires != 3)
197 omap_cfg_reg(USB1_RCV);
198
199 switch (nwires) {
200 case 3:
201 syscon1 = 2;
202 break;
203 case 4:
204 syscon1 = 1;
205 break;
206 case 6:
207 syscon1 = 3;
208 omap_cfg_reg(USB1_VP);
209 omap_cfg_reg(USB1_VM);
210 if (!cpu_is_omap15xx())
211 USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
212 break;
213 default:
214 printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
215 1, nwires);
216 }
217 return syscon1 << 20;
218}
219
220static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
221{
222 u32 syscon1 = 0;
223
224 /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */
225 if (alt_pingroup || nwires == 0)
226 return 0;
227 if (nwires != 6 && !cpu_is_omap15xx())
228 USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
229
230 /* external transceiver */
231 if (cpu_is_omap15xx()) {
232 omap_cfg_reg(USB2_TXD);
233 omap_cfg_reg(USB2_TXEN);
234 omap_cfg_reg(USB2_SEO);
235 if (nwires != 3)
236 omap_cfg_reg(USB2_RCV);
237 /* there is no USB2_SPEED */
238 } else if (cpu_is_omap16xx()) {
239 omap_cfg_reg(V6_USB2_TXD);
240 omap_cfg_reg(W9_USB2_TXEN);
241 omap_cfg_reg(W5_USB2_SE0);
242 if (nwires != 3)
243 omap_cfg_reg(Y5_USB2_RCV);
244 // FIXME omap_cfg_reg(USB2_SPEED);
245 } else {
246 pr_debug("usb unrecognized\n");
247 }
248 // omap_cfg_reg(USB2_SUSP);
249
250 switch (nwires) {
251 case 3:
252 syscon1 = 2;
253 break;
254 case 4:
255 syscon1 = 1;
256 break;
257 case 6:
258 syscon1 = 3;
259 if (cpu_is_omap15xx()) {
260 omap_cfg_reg(USB2_VP);
261 omap_cfg_reg(USB2_VM);
262 } else {
263 omap_cfg_reg(AA9_USB2_VP);
264 omap_cfg_reg(R9_USB2_VM);
265 USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
266 }
267 break;
268 default:
269 printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
270 2, nwires);
271 }
272 return syscon1 << 24;
273}
274
275/*-------------------------------------------------------------------------*/
276
277#if defined(CONFIG_USB_GADGET_OMAP) || \
278 defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) || \
279 (defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG))
280static void usb_release(struct device *dev)
281{
282 /* normally not freed */
283}
284#endif
285
286#ifdef CONFIG_USB_GADGET_OMAP
287
288static struct resource udc_resources[] = {
289 /* order is significant! */
290 { /* registers */
291 .start = IO_ADDRESS(UDC_BASE),
292 .end = IO_ADDRESS(UDC_BASE + 0xff),
293 .flags = IORESOURCE_MEM,
294 }, { /* general IRQ */
295 .start = IH2_BASE + 20,
296 .flags = IORESOURCE_IRQ,
297 }, { /* PIO IRQ */
298 .start = IH2_BASE + 30,
299 .flags = IORESOURCE_IRQ,
300 }, { /* SOF IRQ */
301 .start = IH2_BASE + 29,
302 .flags = IORESOURCE_IRQ,
303 },
304};
305
306static u64 udc_dmamask = ~(u32)0;
307
308static struct platform_device udc_device = {
309 .name = "omap_udc",
310 .id = -1,
311 .dev = {
312 .release = usb_release,
313 .dma_mask = &udc_dmamask,
314 .coherent_dma_mask = 0xffffffff,
315 },
316 .num_resources = ARRAY_SIZE(udc_resources),
317 .resource = udc_resources,
318};
319
320#endif
321
322#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
323
324/* The dmamask must be set for OHCI to work */
325static u64 ohci_dmamask = ~(u32)0;
326
327static struct resource ohci_resources[] = {
328 {
329 .start = OMAP_OHCI_BASE,
330 .end = OMAP_OHCI_BASE + 4096,
331 .flags = IORESOURCE_MEM,
332 },
333 {
334 .start = INT_USB_HHC_1,
335 .flags = IORESOURCE_IRQ,
336 },
337};
338
339static struct platform_device ohci_device = {
340 .name = "ohci",
341 .id = -1,
342 .dev = {
343 .release = usb_release,
344 .dma_mask = &ohci_dmamask,
345 .coherent_dma_mask = 0xffffffff,
346 },
347 .num_resources = ARRAY_SIZE(ohci_resources),
348 .resource = ohci_resources,
349};
350
351#endif
352
353#if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG)
354
355static struct resource otg_resources[] = {
356 /* order is significant! */
357 {
358 .start = IO_ADDRESS(OTG_BASE),
359 .end = IO_ADDRESS(OTG_BASE + 0xff),
360 .flags = IORESOURCE_MEM,
361 }, {
362 .start = IH2_BASE + 8,
363 .flags = IORESOURCE_IRQ,
364 },
365};
366
367static struct platform_device otg_device = {
368 .name = "omap_otg",
369 .id = -1,
370 .dev = {
371 .release = usb_release,
372 },
373 .num_resources = ARRAY_SIZE(otg_resources),
374 .resource = otg_resources,
375};
376
377#endif
378
379/*-------------------------------------------------------------------------*/
380
381#define ULPD_CLOCK_CTRL_REG __REG16(ULPD_CLOCK_CTRL)
382#define ULPD_SOFT_REQ_REG __REG16(ULPD_SOFT_REQ)
383
384
385// FIXME correct answer depends on hmc_mode,
386// as does any nonzero value for config->otg port number
387#ifdef CONFIG_USB_GADGET_OMAP
388#define is_usb0_device(config) 1
389#else
390#define is_usb0_device(config) 0
391#endif
392
393/*-------------------------------------------------------------------------*/
394
395#ifdef CONFIG_ARCH_OMAP_OTG
396
397void __init
398omap_otg_init(struct omap_usb_config *config)
399{
400 u32 syscon = OTG_SYSCON_1_REG & 0xffff;
401 int status;
402 int alt_pingroup = 0;
403
404 /* NOTE: no bus or clock setup (yet?) */
405
406 syscon = OTG_SYSCON_1_REG & 0xffff;
407 if (!(syscon & OTG_RESET_DONE))
408 pr_debug("USB resets not complete?\n");
409
410 // OTG_IRQ_EN_REG = 0;
411
412 /* pin muxing and transceiver pinouts */
413 if (config->pins[0] > 2) /* alt pingroup 2 */
414 alt_pingroup = 1;
415 syscon |= omap_usb0_init(config->pins[0], is_usb0_device(config));
416 syscon |= omap_usb1_init(config->pins[1]);
417 syscon |= omap_usb2_init(config->pins[2], alt_pingroup);
418 pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
419 OTG_SYSCON_1_REG = syscon;
420
421 syscon = config->hmc_mode;
422 syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */;
423#ifdef CONFIG_USB_OTG
424 if (config->otg)
425 syscon |= OTG_EN;
426#endif
427 pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG);
428 pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon);
429 OTG_SYSCON_2_REG = syscon;
430
431 printk("USB: hmc %d", config->hmc_mode);
432 if (alt_pingroup)
433 printk(", usb2 alt %d wires", config->pins[2]);
434 else if (config->pins[0])
435 printk(", usb0 %d wires%s", config->pins[0],
436 is_usb0_device(config) ? " (dev)" : "");
437 if (config->pins[1])
438 printk(", usb1 %d wires", config->pins[1]);
439 if (!alt_pingroup && config->pins[2])
440 printk(", usb2 %d wires", config->pins[2]);
441 if (config->otg)
442 printk(", Mini-AB on usb%d", config->otg - 1);
443 printk("\n");
444
445 /* leave USB clocks/controllers off until needed */
446 ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ;
447 ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN;
448 ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK;
449 syscon = OTG_SYSCON_1_REG;
450 syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
451
452#ifdef CONFIG_USB_GADGET_OMAP
453 if (config->otg || config->register_dev) {
454 syscon &= ~DEV_IDLE_EN;
455 udc_device.dev.platform_data = config;
456 /* FIXME patch IRQ numbers for omap730 */
457 status = platform_device_register(&udc_device);
458 if (status)
459 pr_debug("can't register UDC device, %d\n", status);
460 }
461#endif
462
463#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
464 if (config->otg || config->register_host) {
465 syscon &= ~HST_IDLE_EN;
466 ohci_device.dev.platform_data = config;
467 if (cpu_is_omap730())
468 ohci_resources[1].start = INT_730_USB_HHC_1;
469 status = platform_device_register(&ohci_device);
470 if (status)
471 pr_debug("can't register OHCI device, %d\n", status);
472 }
473#endif
474
475#ifdef CONFIG_USB_OTG
476 if (config->otg) {
477 syscon &= ~OTG_IDLE_EN;
478 otg_device.dev.platform_data = config;
479 if (cpu_is_omap730())
480 otg_resources[1].start = INT_730_USB_OTG;
481 status = platform_device_register(&otg_device);
482 if (status)
483 pr_debug("can't register OTG device, %d\n", status);
484 }
485#endif
486 pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
487 OTG_SYSCON_1_REG = syscon;
488
489 status = 0;
490}
491
492#else
493static inline void omap_otg_init(struct omap_usb_config *config) {}
494#endif
495
496/*-------------------------------------------------------------------------*/
497
498#ifdef CONFIG_ARCH_OMAP1510
499
500#define ULPD_DPLL_CTRL_REG __REG16(ULPD_DPLL_CTRL)
501#define DPLL_IOB (1 << 13)
502#define DPLL_PLL_ENABLE (1 << 4)
503#define DPLL_LOCK (1 << 0)
504
505#define ULPD_APLL_CTRL_REG __REG16(ULPD_APLL_CTRL)
506#define APLL_NDPLL_SWITCH (1 << 0)
507
508
509static void __init omap_1510_usb_init(struct omap_usb_config *config)
510{
511 int status;
512 unsigned int val;
513
514 omap_usb0_init(config->pins[0], is_usb0_device(config));
515 omap_usb1_init(config->pins[1]);
516 omap_usb2_init(config->pins[2], 0);
517
518 val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1);
519 val |= (config->hmc_mode << 1);
520 omap_writel(val, MOD_CONF_CTRL_0);
521
522 printk("USB: hmc %d", config->hmc_mode);
523 if (config->pins[0])
524 printk(", usb0 %d wires%s", config->pins[0],
525 is_usb0_device(config) ? " (dev)" : "");
526 if (config->pins[1])
527 printk(", usb1 %d wires", config->pins[1]);
528 if (config->pins[2])
529 printk(", usb2 %d wires", config->pins[2]);
530 printk("\n");
531
532 /* use DPLL for 48 MHz function clock */
533 pr_debug("APLL %04x DPLL %04x REQ %04x\n", ULPD_APLL_CTRL_REG,
534 ULPD_DPLL_CTRL_REG, ULPD_SOFT_REQ_REG);
535 ULPD_APLL_CTRL_REG &= ~APLL_NDPLL_SWITCH;
536 ULPD_DPLL_CTRL_REG |= DPLL_IOB | DPLL_PLL_ENABLE;
537 ULPD_SOFT_REQ_REG |= SOFT_UDC_REQ | SOFT_DPLL_REQ;
538 while (!(ULPD_DPLL_CTRL_REG & DPLL_LOCK))
539 cpu_relax();
540
541#ifdef CONFIG_USB_GADGET_OMAP
542 if (config->register_dev) {
543 udc_device.dev.platform_data = config;
544 status = platform_device_register(&udc_device);
545 if (status)
546 pr_debug("can't register UDC device, %d\n", status);
547 /* udc driver gates 48MHz by D+ pullup */
548 }
549#endif
550
551#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
552 if (config->register_host) {
553 ohci_device.dev.platform_data = config;
554 status = platform_device_register(&ohci_device);
555 if (status)
556 pr_debug("can't register OHCI device, %d\n", status);
557 /* hcd explicitly gates 48MHz */
558 }
559#endif
560}
561
562#else
563static inline void omap_1510_usb_init(struct omap_usb_config *config) {}
564#endif
565
566/*-------------------------------------------------------------------------*/
567
568static struct omap_usb_config platform_data;
569
570static int __init
571omap_usb_init(void)
572{
573 const struct omap_usb_config *config;
574
575 config = omap_get_config(OMAP_TAG_USB, struct omap_usb_config);
576 if (config == NULL) {
577 printk(KERN_ERR "USB: No board-specific "
578 "platform config found\n");
579 return -ENODEV;
580 }
581 platform_data = *config;
582
583 if (cpu_is_omap730() || cpu_is_omap16xx())
584 omap_otg_init(&platform_data);
585 else if (cpu_is_omap15xx())
586 omap_1510_usb_init(&platform_data);
587 else {
588 printk(KERN_ERR "USB: No init for your chip yet\n");
589 return -ENODEV;
590 }
591 return 0;
592}
593
594subsys_initcall(omap_usb_init);