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