diff options
-rw-r--r-- | arch/arm/mach-omap/Kconfig | 99 | ||||
-rw-r--r-- | arch/arm/mach-omap/Makefile | 16 | ||||
-rw-r--r-- | arch/arm/mach-omap/common.c | 135 | ||||
-rw-r--r-- | arch/arm/mach-omap/common.h | 36 | ||||
-rw-r--r-- | arch/arm/mach-omap/dma.c | 1086 | ||||
-rw-r--r-- | arch/arm/mach-omap/gpio.c | 762 | ||||
-rw-r--r-- | arch/arm/mach-omap/mcbsp.c | 685 | ||||
-rw-r--r-- | arch/arm/mach-omap/mux.c | 163 | ||||
-rw-r--r-- | arch/arm/mach-omap/ocpi.c | 114 | ||||
-rw-r--r-- | arch/arm/mach-omap/pm.c | 632 | ||||
-rw-r--r-- | arch/arm/mach-omap/sleep.S | 314 | ||||
-rw-r--r-- | arch/arm/mach-omap/usb.c | 593 |
12 files changed, 0 insertions, 4635 deletions
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig deleted file mode 100644 index a72fe55b513..00000000000 --- a/arch/arm/mach-omap/Kconfig +++ /dev/null @@ -1,99 +0,0 @@ -if ARCH_OMAP - -menu "TI OMAP Implementations" - -config ARCH_OMAP_OTG - bool - -choice - prompt "OMAP System Type" - default ARCH_OMAP1 - -config ARCH_OMAP1 - bool "TI OMAP1" - -config ARCH_OMAP2 - bool "TI OMAP2" - -endchoice - -comment "OMAP Feature Selections" - -config OMAP_MUX - bool "OMAP multiplexing support" - depends on ARCH_OMAP - default y - help - Pin multiplexing support for OMAP boards. If your bootloader - sets the multiplexing correctly, say N. Otherwise, or if unsure, - say Y. - -config OMAP_MUX_DEBUG - bool "Multiplexing debug output" - depends on OMAP_MUX - default n - help - Makes the multiplexing functions print out a lot of debug info. - This is useful if you want to find out the correct values of the - multiplexing registers. - -config OMAP_MUX_WARNINGS - bool "Warn about pins the bootloader didn't set up" - depends on OMAP_MUX - default y - help - Choose Y here to warn whenever driver initialization logic needs - to change the pin multiplexing setup. When there are no warnings - printed, it's safe to deselect OMAP_MUX for your product. - -choice - prompt "System timer" - default OMAP_MPU_TIMER - -config OMAP_MPU_TIMER - bool "Use mpu timer" - help - Select this option if you want to use the OMAP mpu timer. This - timer provides more intra-tick resolution than the 32KHz timer, - but consumes more power. - -config OMAP_32K_TIMER - bool "Use 32KHz timer" - depends on ARCH_OMAP16XX - help - Select this option if you want to enable the OMAP 32KHz timer. - This timer saves power compared to the OMAP_MPU_TIMER, and has - support for no tick during idle. The 32KHz timer provides less - intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is - currently only available for OMAP-16xx. - -endchoice - -config OMAP_32K_TIMER_HZ - int "Kernel internal timer frequency for 32KHz timer" - range 32 1024 - depends on OMAP_32K_TIMER - default "128" - help - Kernel internal timer frequency should be a divisor of 32768, - such as 64 or 128. - -choice - prompt "Low-level debug console UART" - depends on ARCH_OMAP - default OMAP_LL_DEBUG_UART1 - -config OMAP_LL_DEBUG_UART1 - bool "UART1" - -config OMAP_LL_DEBUG_UART2 - bool "UART2" - -config OMAP_LL_DEBUG_UART3 - bool "UART3" - -endchoice - -endmenu - -endif diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile deleted file mode 100644 index 3be25ebfc45..00000000000 --- a/arch/arm/mach-omap/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Common support -obj-y := common.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o -obj-m := -obj-n := -obj- := - -# OCPI interconnect support for 1710, 1610 and 5912 -obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o - -# Power Management -obj-$(CONFIG_PM) += pm.o sleep.o - diff --git a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c deleted file mode 100644 index b6a5b39e7e8..00000000000 --- a/arch/arm/mach-omap/common.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * linux/arch/arm/mach-omap/common.c - * - * Code common to all OMAP machines. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/config.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/pm.h> -#include <linux/console.h> -#include <linux/serial.h> -#include <linux/tty.h> -#include <linux/serial_8250.h> -#include <linux/serial_reg.h> - -#include <asm/hardware.h> -#include <asm/system.h> -#include <asm/pgtable.h> -#include <asm/mach/map.h> -#include <asm/hardware/clock.h> -#include <asm/io.h> -#include <asm/mach-types.h> - -#include <asm/arch/board.h> -#include <asm/arch/mux.h> -#include <asm/arch/fpga.h> - -#include "clock.h" - -#define NO_LENGTH_CHECK 0xffffffff - -extern int omap_bootloader_tag_len; -extern u8 omap_bootloader_tag[]; - -struct omap_board_config_kernel *omap_board_config; -int omap_board_config_size = 0; - -static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) -{ - struct omap_board_config_kernel *kinfo = NULL; - int i; - -#ifdef CONFIG_OMAP_BOOT_TAG - struct omap_board_config_entry *info = NULL; - - if (omap_bootloader_tag_len > 4) - info = (struct omap_board_config_entry *) omap_bootloader_tag; - while (info != NULL) { - u8 *next; - - if (info->tag == tag) { - if (skip == 0) - break; - skip--; - } - - if ((info->len & 0x03) != 0) { - /* We bail out to avoid an alignment fault */ - printk(KERN_ERR "OMAP peripheral config: Length (%d) not word-aligned (tag %04x)\n", - info->len, info->tag); - return NULL; - } - next = (u8 *) info + sizeof(*info) + info->len; - if (next >= omap_bootloader_tag + omap_bootloader_tag_len) - info = NULL; - else - info = (struct omap_board_config_entry *) next; - } - if (info != NULL) { - /* Check the length as a lame attempt to check for - * binary inconsistancy. */ - if (len != NO_LENGTH_CHECK) { - /* Word-align len */ - if (len & 0x03) - len = (len + 3) & ~0x03; - if (info->len != len) { - printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n", - tag, len, info->len); - return NULL; - } - } - if (len_out != NULL) - *len_out = info->len; - return info->data; - } -#endif - /* Try to find the config from the board-specific structures - * in the kernel. */ - for (i = 0; i < omap_board_config_size; i++) { - if (omap_board_config[i].tag == tag) { - kinfo = &omap_board_config[i]; - break; - } - } - if (kinfo == NULL) - return NULL; - return kinfo->data; -} - -const void *__omap_get_config(u16 tag, size_t len, int nr) -{ - return get_config(tag, len, nr, NULL); -} -EXPORT_SYMBOL(__omap_get_config); - -const void *omap_get_var_config(u16 tag, size_t *len) -{ - return get_config(tag, NO_LENGTH_CHECK, 0, len); -} -EXPORT_SYMBOL(omap_get_var_config); - -static int __init omap_add_serial_console(void) -{ - const struct omap_serial_console_config *info; - - info = omap_get_config(OMAP_TAG_SERIAL_CONSOLE, - struct omap_serial_console_config); - if (info != NULL && info->console_uart) { - static char speed[11], *opt = NULL; - - if (info->console_speed) { - snprintf(speed, sizeof(speed), "%u", info->console_speed); - opt = speed; - } - return add_preferred_console("ttyS", info->console_uart - 1, opt); - } - return 0; -} -console_initcall(omap_add_serial_console); diff --git a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h deleted file mode 100644 index bb257344f52..00000000000 --- a/arch/arm/mach-omap/common.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * linux/arch/arm/mach-omap/common.h - * - * Header for code common to all OMAP machines. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ARCH_ARM_MACH_OMAP_COMMON_H -#define __ARCH_ARM_MACH_OMAP_COMMON_H - -struct sys_timer; - -extern void omap_map_common_io(void); -extern struct sys_timer omap_timer; -extern void omap_serial_init(int ports[]); - -#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ diff --git a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c deleted file mode 100644 index 7a9ebe80d6f..00000000000 --- a/arch/arm/mach-omap/dma.c +++ /dev/null @@ -1,1086 +0,0 @@ -/* - * linux/arch/arm/omap/dma.c - * - * Copyright (C) 2003 Nokia Corporation - * Author: Juha Yrjölä <juha.yrjola@nokia.com> - * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> - * Graphics DMA and LCD DMA graphics tranformations - * by Imre Deak <imre.deak@nokia.com> - * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. - * - * Support functions for the OMAP internal DMA channels. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/errno.h> -#include <linux/interrupt.h> - -#include <asm/system.h> -#include <asm/irq.h> -#include <asm/hardware.h> -#include <asm/dma.h> -#include <asm/io.h> - -#include <asm/arch/tc.h> - -#define OMAP_DMA_ACTIVE 0x01 - -#define OMAP_DMA_CCR_EN (1 << 7) - -#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) - -static int enable_1510_mode = 0; - -struct omap_dma_lch { - int next_lch; - int dev_id; - u16 saved_csr; - u16 enabled_irqs; - const char *dev_name; - void (* callback)(int lch, u16 ch_status, void *data); - void *data; - long flags; -}; - -static int dma_chan_count; - -static spinlock_t dma_chan_lock; -static struct omap_dma_lch dma_chan[OMAP_LOGICAL_DMA_CH_COUNT]; - -const static u8 dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = { - INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3, - INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7, - INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10, - INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13, - INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD -}; - -static inline int get_gdma_dev(int req) -{ - u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4; - int shift = ((req - 1) % 5) * 6; - - return ((omap_readl(reg) >> shift) & 0x3f) + 1; -} - -static inline void set_gdma_dev(int req, int dev) -{ - u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4; - int shift = ((req - 1) % 5) * 6; - u32 l; - - l = omap_readl(reg); - l &= ~(0x3f << shift); - l |= (dev - 1) << shift; - omap_writel(l, reg); -} - -static void clear_lch_regs(int lch) -{ - int i; - u32 lch_base = OMAP_DMA_BASE + lch * 0x40; - - for (i = 0; i < 0x2c; i += 2) - omap_writew(0, lch_base + i); -} - -void omap_set_dma_priority(int dst_port, int priority) -{ - unsigned long reg; - u32 l; - - switch (dst_port) { - case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */ - reg = OMAP_TC_OCPT1_PRIOR; - break; - case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */ - reg = OMAP_TC_OCPT2_PRIOR; - break; - case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */ - reg = OMAP_TC_EMIFF_PRIOR; - break; - case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */ - reg = OMAP_TC_EMIFS_PRIOR; - break; - default: - BUG(); - return; - } - l = omap_readl(reg); - l &= ~(0xf << 8); - l |= (priority & 0xf) << 8; - omap_writel(l, reg); -} - -void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, - int frame_count, int sync_mode) -{ - u16 w; - - w = omap_readw(OMAP_DMA_CSDP(lch)); - w &= ~0x03; - w |= data_type; - omap_writew(w, OMAP_DMA_CSDP(lch)); - - w = omap_readw(OMAP_DMA_CCR(lch)); - w &= ~(1 << 5); - if (sync_mode == OMAP_DMA_SYNC_FRAME) - w |= 1 << 5; - omap_writew(w, OMAP_DMA_CCR(lch)); - - w = omap_readw(OMAP_DMA_CCR2(lch)); - w &= ~(1 << 2); - if (sync_mode == OMAP_DMA_SYNC_BLOCK) - w |= 1 << 2; - omap_writew(w, OMAP_DMA_CCR2(lch)); - - omap_writew(elem_count, OMAP_DMA_CEN(lch)); - omap_writew(frame_count, OMAP_DMA_CFN(lch)); - -} -void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) -{ - u16 w; - - BUG_ON(omap_dma_in_1510_mode()); - - w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03; - switch (mode) { - case OMAP_DMA_CONSTANT_FILL: - w |= 0x01; - break; - case OMAP_DMA_TRANSPARENT_COPY: - w |= 0x02; - break; - case OMAP_DMA_COLOR_DIS: - break; - default: - BUG(); - } - omap_writew(w, OMAP_DMA_CCR2(lch)); - - w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f; - /* Default is channel type 2D */ - if (mode) { - omap_writew((u16)color, OMAP_DMA_COLOR_L(lch)); - omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch)); - w |= 1; /* Channel type G */ - } - omap_writew(w, OMAP_DMA_LCH_CTRL(lch)); -} - - -void omap_set_dma_src_params(int lch, int src_port, int src_amode, - unsigned long src_start) -{ - u16 w; - - w = omap_readw(OMAP_DMA_CSDP(lch)); - w &= ~(0x1f << 2); - w |= src_port << 2; - omap_writew(w, OMAP_DMA_CSDP(lch)); - - w = omap_readw(OMAP_DMA_CCR(lch)); - w &= ~(0x03 << 12); - w |= src_amode << 12; - omap_writew(w, OMAP_DMA_CCR(lch)); - - omap_writew(src_start >> 16, OMAP_DMA_CSSA_U(lch)); - omap_writew(src_start, OMAP_DMA_CSSA_L(lch)); -} - -void omap_set_dma_src_index(int lch, int eidx, int fidx) -{ - omap_writew(eidx, OMAP_DMA_CSEI(lch)); - omap_writew(fidx, OMAP_DMA_CSFI(lch)); -} - -void omap_set_dma_src_data_pack(int lch, int enable) -{ - u16 w; - - w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(1 << 6); - w |= enable ? (1 << 6) : 0; - omap_writew(w, OMAP_DMA_CSDP(lch)); -} - -void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) -{ - u16 w; - - w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 7); - switch (burst_mode) { - case OMAP_DMA_DATA_BURST_DIS: - break; - case OMAP_DMA_DATA_BURST_4: - w |= (0x01 << 7); - break; - case OMAP_DMA_DATA_BURST_8: - /* not supported by current hardware - * w |= (0x03 << 7); - * fall through - */ - default: - BUG(); - } - omap_writew(w, OMAP_DMA_CSDP(lch)); -} - -void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, - unsigned long dest_start) -{ - u16 w; - - w = omap_readw(OMAP_DMA_CSDP(lch)); - w &= ~(0x1f << 9); - w |= dest_port << 9; - omap_writew(w, OMAP_DMA_CSDP(lch)); - - w = omap_readw(OMAP_DMA_CCR(lch)); - w &= ~(0x03 << 14); - w |= dest_amode << 14; - omap_writew(w, OMAP_DMA_CCR(lch)); - - omap_writew(dest_start >> 16, OMAP_DMA_CDSA_U(lch)); - omap_writew(dest_start, OMAP_DMA_CDSA_L(lch)); -} - -void omap_set_dma_dest_index(int lch, int eidx, int fidx) -{ - omap_writew(eidx, OMAP_DMA_CDEI(lch)); - omap_writew(fidx, OMAP_DMA_CDFI(lch)); -} - -void omap_set_dma_dest_data_pack(int lch, int enable) -{ - u16 w; - - w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(1 << 13); - w |= enable ? (1 << 13) : 0; - omap_writew(w, OMAP_DMA_CSDP(lch)); -} - -void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) -{ - u16 w; - - w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 14); - switch (burst_mode) { - case OMAP_DMA_DATA_BURST_DIS: - break; - case OMAP_DMA_DATA_BURST_4: - w |= (0x01 << 14); - break; - case OMAP_DMA_DATA_BURST_8: - w |= (0x03 << 14); - break; - default: - printk(KERN_ERR "Invalid DMA burst mode\n"); - BUG(); - return; - } - omap_writew(w, OMAP_DMA_CSDP(lch)); -} - -static inline void init_intr(int lch) -{ - u16 w; - - /* Read CSR to make sure it's cleared. */ - w = omap_readw(OMAP_DMA_CSR(lch)); - /* Enable some nice interrupts. */ - omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch)); - dma_chan[lch].flags |= OMAP_DMA_ACTIVE; -} - -static inline void enable_lnk(int lch) -{ - u16 w; - - /* Clear the STOP_LNK bits */ - w = omap_readw(OMAP_DMA_CLNK_CTRL(lch)); - w &= ~(1 << 14); - omap_writew(w, OMAP_DMA_CLNK_CTRL(lch)); - - /* And set the ENABLE_LNK bits */ - if (dma_chan[lch].next_lch != -1) - omap_writew(dma_chan[lch].next_lch | (1 << 15), - OMAP_DMA_CLNK_CTRL(lch)); -} - -static inline void disable_lnk(int lch) -{ - u16 w; - - /* Disable interrupts */ - omap_writew(0, OMAP_DMA_CICR(lch)); - - /* Set the STOP_LNK bit */ - w = omap_readw(OMAP_DMA_CLNK_CTRL(lch)); - w |= (1 << 14); - w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch)); - - dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; -} - -void omap_start_dma(int lch) -{ - u16 w; - - if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { - int next_lch, cur_lch; - char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; - - dma_chan_link_map[lch] = 1; - /* Set the link register of the first channel */ - enable_lnk(lch); - - memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map)); - cur_lch = dma_chan[lch].next_lch; - do { - next_lch = dma_chan[cur_lch].next_lch; - - /* The loop case: we've been here already */ - if (dma_chan_link_map[cur_lch]) - break; - /* Mark the current channel */ - dma_chan_link_map[cur_lch] = 1; - - enable_lnk(cur_lch); - init_intr(cur_lch); - - cur_lch = next_lch; - } while (next_lch != -1); - } - - init_intr(lch); - - w = omap_readw(OMAP_DMA_CCR(lch)); - w |= OMAP_DMA_CCR_EN; - omap_writew(w, OMAP_DMA_CCR(lch)); - dma_chan[lch].flags |= OMAP_DMA_ACTIVE; -} - -void omap_stop_dma(int lch) -{ - u16 w; - - if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { - int next_lch, cur_lch = lch; - char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; - - memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map)); - do { - /* The loop case: we've been here already */ - if (dma_chan_link_map[cur_lch]) - break; - /* Mark the current channel */ - dma_chan_link_map[cur_lch] = 1; - - disable_lnk(cur_lch); - - next_lch = dma_chan[cur_lch].next_lch; - cur_lch = next_lch; - } while (next_lch != -1); - - return; - } - /* Disable all interrupts on the channel */ - omap_writew(0, OMAP_DMA_CICR(lch)); - - w = omap_readw(OMAP_DMA_CCR(lch)); - w &= ~OMAP_DMA_CCR_EN; - omap_writew(w, OMAP_DMA_CCR(lch)); - dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; -} - -void omap_enable_dma_irq(int lch, u16 bits) -{ - dma_chan[lch].enabled_irqs |= bits; -} - -void omap_disable_dma_irq(int lch, u16 bits) -{ - dma_chan[lch].enabled_irqs &= ~bits; -} - -static int dma_handle_ch(int ch) -{ - u16 csr; - - if (enable_1510_mode && ch >= 6) { - csr = dma_chan[ch].saved_csr; - dma_chan[ch].saved_csr = 0; - } else - csr = omap_readw(OMAP_DMA_CSR(ch)); - if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { - dma_chan[ch + 6].saved_csr = csr >> 7; - csr &= 0x7f; - } - if (!csr) - return 0; - if (unlikely(dma_chan[ch].dev_id == -1)) { - printk(KERN_WARNING "Spurious interrupt from DMA channel %d (CSR %04x)\n", - ch, csr); - return 0; - } - if (unlikely(csr & OMAP_DMA_TOUT_IRQ)) - printk(KERN_WARNING "DMA timeout with device %d\n", dma_chan[ch].dev_id); - if (unlikely(csr & OMAP_DMA_DROP_IRQ)) - printk(KERN_WARNING "DMA synchronization event drop occurred with device %d\n", - dma_chan[ch].dev_id); - if (likely(csr & OMAP_DMA_BLOCK_IRQ)) - dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; - if (likely(dma_chan[ch].callback != NULL)) - dma_chan[ch].callback(ch, csr, dma_chan[ch].data); - return 1; -} - -static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - int ch = ((int) dev_id) - 1; - int handled = 0; - - for (;;) { - int handled_now = 0; - - handled_now += dma_handle_ch(ch); - if (enable_1510_mode && dma_chan[ch + 6].saved_csr) - handled_now += dma_handle_ch(ch + 6); - if (!handled_now) - break; - handled += handled_now; - } - - return handled ? IRQ_HANDLED : IRQ_NONE; -} - -int omap_request_dma(int dev_id, const char *dev_name, - void (* callback)(int lch, u16 ch_status, void *data), - void *data, int *dma_ch_out) -{ - int ch, free_ch = -1; - unsigned long flags; - struct omap_dma_lch *chan; - - spin_lock_irqsave(&dma_chan_lock, flags); - for (ch = 0; ch < dma_chan_count; ch++) { - if (free_ch == -1 && dma_chan[ch].dev_id == -1) { - free_ch = ch; - if (dev_id == 0) - break; - } - } - if (free_ch == -1) { - spin_unlock_irqrestore(&dma_chan_lock, flags); - return -EBUSY; - } - chan = dma_chan + free_ch; - chan->dev_id = dev_id; - clear_lch_regs(free_ch); - spin_unlock_irqrestore(&dma_chan_lock, flags); - - chan->dev_id = dev_id; - chan->dev_name = dev_name; - chan->callback = callback; - chan->data = data; - chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; - - if (cpu_is_omap16xx()) { - /* If the sync device is set, configure it dynamically. */ - if (dev_id != 0) { - set_gdma_dev(free_ch + 1, dev_id); - dev_id = free_ch + 1; - } - /* Disable the 1510 compatibility mode and set the sync device - * id. */ - omap_writew(dev_id | (1 << 10), OMAP_DMA_CCR(free_ch)); - } else { - omap_writew(dev_id, OMAP_DMA_CCR(free_ch)); - } - *dma_ch_out = free_ch; - - return 0; -} - -void omap_free_dma(int ch) -{ - unsigned long flags; - - spin_lock_irqsave(&dma_chan_lock, flags); - if (dma_chan[ch].dev_id == -1) { - printk("omap_dma: trying to free nonallocated DMA channel %d\n", ch); - spin_unlock_irqrestore(&dma_chan_lock, flags); - return; - } - dma_chan[ch].dev_id = -1; - spin_unlock_irqrestore(&dma_chan_lock, flags); - - /* Disable all DMA interrupts for the channel. */ - omap_writew(0, OMAP_DMA_CICR(ch)); - /* Make sure the DMA transfer is stopped. */ - omap_writew(0, OMAP_DMA_CCR(ch)); -} - -int omap_dma_in_1510_mode(void) -{ - return enable_1510_mode; -} - -/* - * lch_queue DMA will start right after lch_head one is finished. - * For this DMA link to start, you still need to start (see omap_start_dma) - * the first one. That will fire up the entire queue. - */ -void omap_dma_link_lch (int lch_head, int lch_queue) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); - BUG(); - return; - } - - if ((dma_chan[lch_head].dev_id == -1) || - (dma_chan[lch_queue].dev_id == -1)) { - printk(KERN_ERR "omap_dma: trying to link non requested channels\n"); - dump_stack(); - } - - dma_chan[lch_head].next_lch = lch_queue; -} - -/* - * Once the DMA queue is stopped, we can destroy it. - */ -void omap_dma_unlink_lch (int lch_head, int lch_queue) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); - BUG(); - return; - } - - if (dma_chan[lch_head].next_lch != lch_queue || - dma_chan[lch_head].next_lch == -1) { - printk(KERN_ERR "omap_dma: trying to unlink non linked channels\n"); - dump_stack(); - } - - - if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) || - (dma_chan[lch_head].flags & OMAP_DMA_ACTIVE)) { - printk(KERN_ERR "omap_dma: You need to stop the DMA channels before unlinking\n"); - dump_stack(); - } - - dma_chan[lch_head].next_lch = -1; -} - - -static struct lcd_dma_info { - spinlock_t lock; - int reserved; - void (* callback)(u16 status, void *data); - void *cb_data; - - int active; - unsigned long addr, size; - int rotate, data_type, xres, yres; - int vxres; - int mirror; - int xscale, yscale; - int ext_ctrl; - int src_port; - int single_transfer; -} lcd_dma; - -void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, - int data_type) -{ - lcd_dma.addr = addr; - lcd_dma.data_type = data_type; - lcd_dma.xres = fb_xres; - lcd_dma.yres = fb_yres; -} - -void omap_set_lcd_dma_src_port(int port) -{ - lcd_dma.src_port = port; -} - -void omap_set_lcd_dma_ext_controller(int external) -{ - lcd_dma.ext_ctrl = external; -} - -void omap_set_lcd_dma_single_transfer(int single) -{ - lcd_dma.single_transfer = single; -} - - -void omap_set_lcd_dma_b1_rotation(int rotate) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); - BUG(); - return; - } - lcd_dma.rotate = rotate; -} - -void omap_set_lcd_dma_b1_mirror(int mirror) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n"); - BUG(); - } - lcd_dma.mirror = mirror; -} - -void omap_set_lcd_dma_b1_vxres(unsigned long vxres) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA virtual resulotion is not supported " - "in 1510 mode\n"); - BUG(); - } - lcd_dma.vxres = vxres; -} - -void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) -{ - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA scale is not supported in 1510 mode\n"); - BUG(); - } - lcd_dma.xscale = xscale; - lcd_dma.yscale = yscale; -} - -static void set_b1_regs(void) -{ - unsigned long top, bottom; - int es; - u16 w; - unsigned long en, fn; - long ei, fi; - unsigned long vxres; - unsigned int xscale, yscale; - - switch (lcd_dma.data_type) { - case OMAP_DMA_DATA_TYPE_S8: - es = 1; - break; - case OMAP_DMA_DATA_TYPE_S16: - es = 2; - break; - case OMAP_DMA_DATA_TYPE_S32: - es = 4; - break; - default: - BUG(); - return; - } - - vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres; - xscale = lcd_dma.xscale ? lcd_dma.xscale : 1; - yscale = lcd_dma.yscale ? lcd_dma.yscale : 1; - BUG_ON(vxres < lcd_dma.xres); -#define PIXADDR(x,y) (lcd_dma.addr + ((y) * vxres * yscale + (x) * xscale) * es) -#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1) - switch (lcd_dma.rotate) { - case 0: - if (!lcd_dma.mirror) { - top = PIXADDR(0, 0); - bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); - /* 1510 DMA requires the bottom address to be 2 more - * than the actual last memory access location. */ - if (omap_dma_in_1510_mode() && - lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) - bottom += 2; - ei = PIXSTEP(0, 0, 1, 0); - fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1); - } else { - top = PIXADDR(lcd_dma.xres - 1, 0); - bottom = PIXADDR(0, lcd_dma.yres - 1); - ei = PIXSTEP(1, 0, 0, 0); - fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1); - } - en = lcd_dma.xres; - fn = lcd_dma.yres; - break; - case 90: - if (!lcd_dma.mirror) { - top = PIXADDR(0, lcd_dma.yres - 1); - bottom = PIXADDR(lcd_dma.xres - 1, 0); - ei = PIXSTEP(0, 1, 0, 0); - fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1); - } else { - top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); - bottom = PIXADDR(0, 0); - ei = PIXSTEP(0, 1, 0, 0); - fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1); - } - en = lcd_dma.yres; - fn = lcd_dma.xres; - break; - case 180: - if (!lcd_dma.mirror) { - top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); - bottom = PIXADDR(0, 0); - ei = PIXSTEP(1, 0, 0, 0); - fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0); - } else { - top = PIXADDR(0, lcd_dma.yres - 1); - bottom = PIXADDR(lcd_dma.xres - 1, 0); - ei = PIXSTEP(0, 0, 1, 0); - fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0); - } - en = lcd_dma.xres; - fn = lcd_dma.yres; - break; - case 270: - if (!lcd_dma.mirror) { - top = PIXADDR(lcd_dma.xres - 1, 0); - bottom = PIXADDR(0, lcd_dma.yres - 1); - ei = PIXSTEP(0, 0, 0, 1); - fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0); - } else { - top = PIXADDR(0, 0); - bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); - ei = PIXSTEP(0, 0, 0, 1); - fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0); - } - en = lcd_dma.yres; - fn = lcd_dma.xres; - break; - default: - BUG(); - return; /* Supress warning about uninitialized vars */ - } - - if (omap_dma_in_1510_mode()) { - omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U); - omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L); - omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U); - omap_writew(bottom, OMAP1510_DMA_LCD_BOT_F1_L); - - return; - } - - /* 1610 regs */ - omap_writew(top >> 16, OMAP1610_DMA_LCD_TOP_B1_U); - omap_writew(top, OMAP1610_DMA_LCD_TOP_B1_L); - omap_writew(bottom >> 16, OMAP1610_DMA_LCD_BOT_B1_U); - omap_writew(bottom, OMAP1610_DMA_LCD_BOT_B1_L); - - omap_writew(en, OMAP1610_DMA_LCD_SRC_EN_B1); - omap_writew(fn, OMAP1610_DMA_LCD_SRC_FN_B1); - - w = omap_readw(OMAP1610_DMA_LCD_CSDP); - w &= ~0x03; - w |= lcd_dma.data_type; - omap_writew(w, OMAP1610_DMA_LCD_CSDP); - - w = omap_readw(OMAP1610_DMA_LCD_CTRL); - /* Always set the source port as SDRAM for now*/ - w &= ~(0x03 << 6); - if (lcd_dma.ext_ctrl) - w |= 1 << 8; - else - w &= ~(1 << 8); - if (lcd_dma.callback != NULL) - w |= 1 << 1; /* Block interrupt enable */ - else - w &= ~(1 << 1); - omap_writew(w, OMAP1610_DMA_LCD_CTRL); - - if (!(lcd_dma.rotate || lcd_dma.mirror || - lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale)) - return; - - w = omap_readw(OMAP1610_DMA_LCD_CCR); - /* Set the double-indexed addressing mode */ - w |= (0x03 << 12); - omap_writew(w, OMAP1610_DMA_LCD_CCR); - - omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1); - omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U); - omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L); -} - -static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - u16 w; - - w = omap_readw(OMAP1610_DMA_LCD_CTRL); - if (unlikely(!(w & (1 << 3)))) { - printk(KERN_WARNING "Spurious LCD DMA IRQ\n"); - return IRQ_NONE; - } - /* Ack the IRQ */ - w |= (1 << 3); - omap_writew(w, OMAP1610_DMA_LCD_CTRL); - lcd_dma.active = 0; - if (lcd_dma.callback != NULL) - lcd_dma.callback(w, lcd_dma.cb_data); - - return IRQ_HANDLED; -} - -int omap_request_lcd_dma(void (* callback)(u16 status, void *data), - void *data) -{ - spin_lock_irq(&lcd_dma.lock); - if (lcd_dma.reserved) { - spin_unlock_irq(&lcd_dma.lock); - printk(KERN_ERR "LCD DMA channel already reserved\n"); - BUG(); - return -EBUSY; - } - lcd_dma.reserved = 1; - spin_unlock_irq(&lcd_dma.lock); - lcd_dma.callback = callback; - lcd_dma.cb_data = data; - lcd_dma.active = 0; - lcd_dma.single_transfer = 0; - lcd_dma.rotate = 0; - lcd_dma.vxres = 0; - lcd_dma.mirror = 0; - lcd_dma.xscale = 0; - lcd_dma.yscale = 0; - lcd_dma.ext_ctrl = 0; - lcd_dma.src_port = 0; - - return 0; -} - -void omap_free_lcd_dma(void) -{ - spin_lock(&lcd_dma.lock); - if (!lcd_dma.reserved) { - spin_unlock(&lcd_dma.lock); - printk(KERN_ERR "LCD DMA is not reserved\n"); - BUG(); - return; - } - if (!enable_1510_mode) - omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR); - lcd_dma.reserved = 0; - spin_unlock(&lcd_dma.lock); -} - -void omap_enable_lcd_dma(void) -{ - u16 w; - - /* Set the Enable bit only if an external controller is - * connected. Otherwise the OMAP internal controller will - * start the transfer when it gets enabled. - */ - if (enable_1510_mode || !lcd_dma.ext_ctrl) - return; - w = omap_readw(OMAP1610_DMA_LCD_CCR); - w |= 1 << 7; - omap_writew(w, OMAP1610_DMA_LCD_CCR); - lcd_dma.active = 1; -} - -void omap_setup_lcd_dma(void) -{ - BUG_ON(lcd_dma.active); - if (!enable_1510_mode) { - /* Set some reasonable defaults */ - omap_writew(0x5440, OMAP1610_DMA_LCD_CCR); - omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP); - omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL); - } - set_b1_regs(); - if (!enable_1510_mode) { - u16 w; - - w = omap_readw(OMAP1610_DMA_LCD_CCR); - /* If DMA was already active set the end_prog bit to have - * the programmed register set loaded into the active - * register set. - */ - w |= 1 << 11; /* End_prog */ - if (!lcd_dma.single_transfer) - w |= (3 << 8); /* Auto_init, repeat */ - omap_writew(w, OMAP1610_DMA_LCD_CCR); - } -} - -void omap_stop_lcd_dma(void) -{ - lcd_dma.active = 0; - if (!enable_1510_mode && lcd_dma.ext_ctrl) - omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~(1 << 7), - OMAP1610_DMA_LCD_CCR); -} - -/* - * Clears any DMA state so the DMA engine is ready to restart with new buffers - * through omap_start_dma(). Any buffers in flight are discarded. - */ -void omap_clear_dma(int lch) -{ - unsigned long flags; - int status; - - local_irq_save(flags); - omap_writew(omap_readw(OMAP_DMA_CCR(lch)) & ~OMAP_DMA_CCR_EN, - OMAP_DMA_CCR(lch)); - status = OMAP_DMA_CSR(lch); /* clear pending interrupts */ - local_irq_restore(flags); -} - -/* - * Returns current physical source address for the given DMA channel. - * If the channel is running the caller must disable interrupts prior calling - * this function and process the returned value before re-enabling interrupt to - * prevent races with the interrupt handler. Note that in continuous mode there - * is a chance for CSSA_L register overflow inbetween the two reads resulting - * in incorrect return value. - */ -dma_addr_t omap_get_dma_src_pos(int lch) -{ - return (dma_addr_t) (OMAP_DMA_CSSA_L(lch) | - (OMAP_DMA_CSSA_U(lch) << 16)); -} - -/* - * Returns current physical destination address for the given DMA channel. - * If the channel is running the caller must disable interrupts prior calling - * this function and process the returned value before re-enabling interrupt to - * prevent races with the interrupt handler. Note that in continuous mode there - * is a chance for CDSA_L register overflow inbetween the two reads resulting - * in incorrect return value. - */ -dma_addr_t omap_get_dma_dst_pos(int lch) -{ - return (dma_addr_t) (OMAP_DMA_CDSA_L(lch) | - (OMAP_DMA_CDSA_U(lch) << 16)); -} - -static int __init omap_init_dma(void) -{ - int ch, r; - - if (cpu_is_omap1510()) { - printk(KERN_INFO "DMA support for OMAP1510 initialized\n"); - dma_chan_count = 9; - enable_1510_mode = 1; - } else if (cpu_is_omap16xx() || cpu_is_omap730()) { - printk(KERN_INFO "OMAP DMA hardware version %d\n", - omap_readw(OMAP_DMA_HW_ID)); - printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", - (omap_readw(OMAP_DMA_CAPS_0_U) << 16) | omap_readw(OMAP_DMA_CAPS_0_L), - (omap_readw(OMAP_DMA_CAPS_1_U) << 16) | omap_readw(OMAP_DMA_CAPS_1_L), - omap_readw(OMAP_DMA_CAPS_2), omap_readw(OMAP_DMA_CAPS_3), - omap_readw(OMAP_DMA_CAPS_4)); - if (!enable_1510_mode) { - u16 w; - - /* Disable OMAP 3.0/3.1 compatibility mode. */ - w = omap_readw(OMAP_DMA_GSCR); - w |= 1 << 3; - omap_writew(w, OMAP_DMA_GSCR); - dma_chan_count = 16; - } else - dma_chan_count = 9; - } else { - dma_chan_count = 0; - return 0; - } - - memset(&lcd_dma, 0, sizeof(lcd_dma)); - spin_lock_init(&lcd_dma.lock); - spin_lock_init(&dma_chan_lock); - memset(&dma_chan, 0, sizeof(dma_chan)); - - for (ch = 0; ch < dma_chan_count; ch++) { - dma_chan[ch].dev_id = -1; - dma_chan[ch].next_lch = -1; - - if (ch >= 6 && enable_1510_mode) - continue; - - /* request_irq() doesn't like dev_id (ie. ch) being zero, - * so we have to kludge around this. */ - r = request_irq(dma_irq[ch], dma_irq_handler, 0, "DMA", - (void *) (ch + 1)); - if (r != 0) { - int i; - - printk(KERN_ERR "unable to request IRQ %d for DMA (error %d)\n", - dma_irq[ch], r); - for (i = 0; i < ch; i++) - free_irq(dma_irq[i], (void *) (i + 1)); - return r; - } - } - r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, "LCD DMA", NULL); - if (r != 0) { - int i; - - printk(KERN_ERR "unable to request IRQ for LCD DMA (error %d)\n", r); - for (i = 0; i < dma_chan_count; i++) - free_irq(dma_irq[i], (void *) (i + 1)); - return r; - } - return 0; -} - -arch_initcall(omap_init_dma); - - -EXPORT_SYMBOL(omap_get_dma_src_pos); -EXPORT_SYMBOL(omap_get_dma_dst_pos); -EXPORT_SYMBOL(omap_clear_dma); -EXPORT_SYMBOL(omap_set_dma_priority); -EXPORT_SYMBOL(omap_request_dma); -EXPORT_SYMBOL(omap_free_dma); -EXPORT_SYMBOL(omap_start_dma); -EXPORT_SYMBOL(omap_stop_dma); -EXPORT_SYMBOL(omap_enable_dma_irq); -EXPORT_SYMBOL(omap_disable_dma_irq); - -EXPORT_SYMBOL(omap_set_dma_transfer_params); -EXPORT_SYMBOL(omap_set_dma_color_mode); - -EXPORT_SYMBOL(omap_set_dma_src_params); -EXPORT_SYMBOL(omap_set_dma_src_index); -EXPORT_SYMBOL(omap_set_dma_src_data_pack); -EXPORT_SYMBOL(omap_set_dma_src_burst_mode); - -EXPORT_SYMBOL(omap_set_dma_dest_params); -EXPORT_SYMBOL(omap_set_dma_dest_index); -EXPORT_SYMBOL(omap_set_dma_dest_data_pack); -EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); - -EXPORT_SYMBOL(omap_dma_link_lch); -EXPORT_SYMBOL(omap_dma_unlink_lch); - -EXPORT_SYMBOL(omap_request_lcd_dma); -EXPORT_SYMBOL(omap_free_lcd_dma); -EXPORT_SYMBOL(omap_enable_lcd_dma); -EXPORT_SYMBOL(omap_setup_lcd_dma); -EXPORT_SYMBOL(omap_stop_lcd_dma); -EXPORT_SYMBOL(omap_set_lcd_dma_b1); -EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); -EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); -EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); -EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); -EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale); -EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); - diff --git a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c deleted file mode 100644 index 9045dfd469a..00000000000 --- a/arch/arm/mach-omap/gpio.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * linux/arch/arm/mach-omap/gpio.c - * - * Support functions for OMAP GPIO - * - * Copyright (C) 2003 Nokia Corporation - * Written by Juha Yrjölä <juha.yrjola@nokia.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/config.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> - -#include <asm/hardware.h> -#include <asm/irq.h> -#include <asm/arch/irqs.h> -#include <asm/arch/gpio.h> -#include <asm/mach/irq.h> - -#include <asm/io.h> - -/* - * OMAP1510 GPIO registers - */ -#define OMAP1510_GPIO_BASE 0xfffce000 -#define OMAP1510_GPIO_DATA_INPUT 0x00 -#define OMAP1510_GPIO_DATA_OUTPUT 0x04 -#define OMAP1510_GPIO_DIR_CONTROL 0x08 -#define OMAP1510_GPIO_INT_CONTROL 0x0c -#define OMAP1510_GPIO_INT_MASK 0x10 -#define OMAP1510_GPIO_INT_STATUS 0x14 -#define OMAP1510_GPIO_PIN_CONTROL 0x18 - -#define OMAP1510_IH_GPIO_BASE 64 - -/* - * OMAP1610 specific GPIO registers - */ -#define OMAP1610_GPIO1_BASE 0xfffbe400 -#define OMAP1610_GPIO2_BASE 0xfffbec00 -#define OMAP1610_GPIO3_BASE 0xfffbb400 -#define OMAP1610_GPIO4_BASE 0xfffbbc00 -#define OMAP1610_GPIO_REVISION 0x0000 -#define OMAP1610_GPIO_SYSCONFIG 0x0010 -#define OMAP1610_GPIO_SYSSTATUS 0x0014 -#define OMAP1610_GPIO_IRQSTATUS1 0x0018 -#define OMAP1610_GPIO_IRQENABLE1 0x001c -#define OMAP1610_GPIO_DATAIN 0x002c -#define OMAP1610_GPIO_DATAOUT 0x0030 -#define OMAP1610_GPIO_DIRECTION 0x0034 -#define OMAP1610_GPIO_EDGE_CTRL1 0x0038 -#define OMAP1610_GPIO_EDGE_CTRL2 0x003c -#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c -#define OMAP1610_GPIO_CLEAR_DATAOUT 0x00b0 -#define OMAP1610_GPIO_SET_IRQENABLE1 0x00dc -#define OMAP1610_GPIO_SET_DATAOUT 0x00f0 - -/* - * OMAP730 specific GPIO registers - */ -#define OMAP730_GPIO1_BASE 0xfffbc000 -#define OMAP730_GPIO2_BASE 0xfffbc800 -#define OMAP730_GPIO3_BASE 0xfffbd000 -#define OMAP730_GPIO4_BASE 0xfffbd800 -#define OMAP730_GPIO5_BASE 0xfffbe000 -#define OMAP730_GPIO6_BASE 0xfffbe800 -#define OMAP730_GPIO_DATA_INPUT 0x00 -#define OMAP730_GPIO_DATA_OUTPUT 0x04 -#define OMAP730_GPIO_DIR_CONTROL 0x08 -#define OMAP730_GPIO_INT_CONTROL 0x0c -#define OMAP730_GPIO_INT_MASK 0x10 -#define OMAP730_GPIO_INT_STATUS 0x14 - -#define OMAP_MPUIO_MASK (~OMAP_MAX_GPIO_LINES & 0xff) - -struct gpio_bank { - u32 base; - u16 irq; - u16 virtual_irq_start; - u8 method; - u32 reserved_map; - spinlock_t lock; -}; - -#define METHOD_MPUIO 0 -#define METHOD_GPIO_1510 1 -#define METHOD_GPIO_1610 2 -#define METHOD_GPIO_730 3 - -#if defined(CONFIG_ARCH_OMAP16XX) -static struct gpio_bank gpio_bank_1610[5] = { - { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO}, - { OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 }, - { OMAP1610_GPIO2_BASE, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16, METHOD_GPIO_1610 }, - { OMAP1610_GPIO3_BASE, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32, METHOD_GPIO_1610 }, - { OMAP1610_GPIO4_BASE, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48, METHOD_GPIO_1610 }, -}; -#endif - -#ifdef CONFIG_ARCH_OMAP1510 -static struct gpio_bank gpio_bank_1510[2] = { - { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, - { OMAP1510_GPIO_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1510 } -}; -#endif - -#ifdef CONFIG_ARCH_OMAP730 -static struct gpio_bank gpio_bank_730[7] = { - { OMAP_MPUIO_BASE, INT_730_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, - { OMAP730_GPIO1_BASE, INT_730_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 }, - { OMAP730_GPIO2_BASE, INT_730_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_730 }, - { OMAP730_GPIO3_BASE, INT_730_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_730 }, - { OMAP730_GPIO4_BASE, INT_730_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_730 }, - { OMAP730_GPIO5_BASE, INT_730_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_730 }, - { OMAP730_GPIO6_BASE, INT_730_GPIO_BANK6, IH_GPIO_BASE + 160, METHOD_GPIO_730 }, -}; -#endif - -static struct gpio_bank *gpio_bank; -static int gpio_bank_count; - -static inline struct gpio_bank *get_gpio_bank(int gpio) -{ -#ifdef CONFIG_ARCH_OMAP1510 - if (cpu_is_omap1510()) { - if (OMAP_GPIO_IS_MPUIO(gpio)) - return &gpio_bank[0]; - return &gpio_bank[1]; - } -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (cpu_is_omap16xx()) { - if (OMAP_GPIO_IS_MPUIO(gpio)) - return &gpio_bank[0]; - return &gpio_bank[1 + (gpio >> 4)]; - } -#endif -#ifdef CONFIG_ARCH_OMAP730 - if (cpu_is_omap730()) { - if (OMAP_GPIO_IS_MPUIO(gpio)) - return &gpio_bank[0]; - return &gpio_bank[1 + (gpio >> 5)]; - } -#endif -} - -static inline int get_gpio_index(int gpio) -{ - if (cpu_is_omap730()) - return gpio & 0x1f; - else - return gpio & 0x0f; -} - -static inline int gpio_valid(int gpio) -{ - if (gpio < 0) - return -1; - if (OMAP_GPIO_IS_MPUIO(gpio)) { - if ((gpio & OMAP_MPUIO_MASK) > 16) - return -1; - return 0; - } -#ifdef CONFIG_ARCH_OMAP1510 - if (cpu_is_omap1510() && gpio < 16) - return 0; -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if ((cpu_is_omap16xx()) && gpio < 64) - return 0; -#endif -#ifdef CONFIG_ARCH_OMAP730 - if (cpu_is_omap730() && gpio < 192) - return 0; -#endif - return -1; -} - -static int check_gpio(int gpio) -{ - if (unlikely(gpio_valid(gpio)) < 0) { - printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio); - dump_stack(); - return -1; - } - return 0; -} - -static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) -{ - u32 reg = bank->base; - u32 l; - - switch (bank->method) { - case METHOD_MPUIO: - reg += OMAP_MPUIO_IO_CNTL; - break; - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DIR_CONTROL; - break; - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_DIRECTION; - break; - case METHOD_GPIO_730: - reg += OMAP730_GPIO_DIR_CONTROL; - break; - } - l = __raw_readl(reg); - if (is_input) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - __raw_writel(l, reg); -} - -void omap_set_gpio_direction(int gpio, int is_input) -{ - struct gpio_bank *bank; - - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); - spin_lock(&bank->lock); - _set_gpio_direction(bank, get_gpio_index(gpio), is_input); - spin_unlock(&bank->lock); -} - -static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) -{ - u32 reg = bank->base; - u32 l = 0; - - switch (bank->method) { - case METHOD_MPUIO: - reg += OMAP_MPUIO_OUTPUT; - l = __raw_readl(reg); - if (enable) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - break; - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DATA_OUTPUT; - l = __raw_readl(reg); - if (enable) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - break; - case METHOD_GPIO_1610: - if (enable) - reg += OMAP1610_GPIO_SET_DATAOUT; - else - reg += OMAP1610_GPIO_CLEAR_DATAOUT; - l = 1 << gpio; - break; - case METHOD_GPIO_730: - reg += OMAP730_GPIO_DATA_OUTPUT; - l = __raw_readl(reg); - if (enable) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - break; - default: - BUG(); - return; - } - __raw_writel(l, reg); -} - -void omap_set_gpio_dataout(int gpio, int enable) -{ - struct gpio_bank *bank; - - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); - spin_lock(&bank->lock); - _set_gpio_dataout(bank, get_gpio_index(gpio), enable); - spin_unlock(&bank->lock); -} - -int omap_get_gpio_datain(int gpio) -{ - struct gpio_bank *bank; - u32 reg; - - if (check_gpio(gpio) < 0) - return -1; - bank = get_gpio_bank(gpio); - reg = bank->base; - switch (bank->method) { - case METHOD_MPUIO: - reg += OMAP_MPUIO_INPUT_LATCH; - break; - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DATA_INPUT; - break; - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_DATAIN; - break; - case METHOD_GPIO_730: - reg += OMAP730_GPIO_DATA_INPUT; - break; - default: - BUG(); - return -1; - } - return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0; -} - -static void _set_gpio_edge_ctrl(struct gpio_bank *bank, int gpio, int edge) -{ - u32 reg = bank->base; - u32 l; - - switch (bank->method) { - case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_INT_EDGE; - l = __raw_readl(reg); - if (edge == OMAP_GPIO_RISING_EDGE) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - __raw_writel(l, reg); - break; - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_INT_CONTROL; - l = __raw_readl(reg); - if (edge == OMAP_GPIO_RISING_EDGE) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - __raw_writel(l, reg); - break; - case METHOD_GPIO_1610: - edge &= 0x03; - if (gpio & 0x08) - reg += OMAP1610_GPIO_EDGE_CTRL2; - else - reg += OMAP1610_GPIO_EDGE_CTRL1; - gpio &= 0x07; - l = __raw_readl(reg); - l &= ~(3 << (gpio << 1)); - l |= edge << (gpio << 1); - __raw_writel(l, reg); - break; - case METHOD_GPIO_730: - reg += OMAP730_GPIO_INT_CONTROL; - l = __raw_readl(reg); - if (edge == OMAP_GPIO_RISING_EDGE) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - __raw_writel(l, reg); - break; - default: - BUG(); - return; - } -} - -void omap_set_gpio_edge_ctrl(int gpio, int edge) -{ - struct gpio_bank *bank; - - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); - spin_lock(&bank->lock); - _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), edge); - spin_unlock(&bank->lock); -} - - -static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio) -{ - u32 reg = bank->base, l; - - switch (bank->method) { - case METHOD_MPUIO: - l = __raw_readl(reg + OMAP_MPUIO_GPIO_INT_EDGE); - return (l & (1 << gpio)) ? - OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE; - case METHOD_GPIO_1510: - l = __raw_readl(reg + OMAP1510_GPIO_INT_CONTROL); - return (l & (1 << gpio)) ? - OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE; - case METHOD_GPIO_1610: - if (gpio & 0x08) - reg += OMAP1610_GPIO_EDGE_CTRL2; - else - reg += OMAP1610_GPIO_EDGE_CTRL1; - return (__raw_readl(reg) >> ((gpio & 0x07) << 1)) & 0x03; - case METHOD_GPIO_730: - l = __raw_readl(reg + OMAP730_GPIO_INT_CONTROL); - return (l & (1 << gpio)) ? - OMAP_GPIO_RISING_EDGE : OMAP_GPIO_FALLING_EDGE; - default: - BUG(); - return -1; - } -} - -static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) -{ - u32 reg = bank->base; - - switch (bank->method) { - case METHOD_MPUIO: - /* MPUIO irqstatus is reset by reading the status register, - * so do nothing here */ - return; - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_INT_STATUS; - break; - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_IRQSTATUS1; - break; - case METHOD_GPIO_730: - reg += OMAP730_GPIO_INT_STATUS; - break; - default: - BUG(); - return; - } - __raw_writel(gpio_mask, reg); -} - -static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) -{ - _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio)); -} - -static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable) -{ - u32 reg = bank->base; - u32 l; - - switch (bank->method) { - case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_MASKIT; - l = __raw_readl(reg); - if (enable) - l &= ~(gpio_mask); - else - l |= gpio_mask; - break; - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_INT_MASK; - l = __raw_readl(reg); - if (enable) - l &= ~(gpio_mask); - else - l |= gpio_mask; - break; - case METHOD_GPIO_1610: - if (enable) - reg += OMAP1610_GPIO_SET_IRQENABLE1; - else - reg += OMAP1610_GPIO_CLEAR_IRQENABLE1; - l = gpio_mask; - break; - case METHOD_GPIO_730: - reg += OMAP730_GPIO_INT_MASK; - l = __raw_readl(reg); - if (enable) - l &= ~(gpio_mask); - else - l |= gpio_mask; - break; - default: - BUG(); - return; - } - __raw_writel(l, reg); -} - -static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) -{ - _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable); -} - -int omap_request_gpio(int gpio) -{ - struct gpio_bank *bank; - - if (check_gpio(gpio) < 0) - return -EINVAL; - - bank = get_gpio_bank(gpio); - spin_lock(&bank->lock); - if (unlikely(bank->reserved_map & (1 << get_gpio_index(gpio)))) { - printk(KERN_ERR "omap-gpio: GPIO %d is already reserved!\n", gpio); - dump_stack(); - spin_unlock(&bank->lock); - return -1; - } - bank->reserved_map |= (1 << get_gpio_index(gpio)); -#ifdef CONFIG_ARCH_OMAP1510 - if (bank->method == METHOD_GPIO_1510) { - u32 reg; - - /* Claim the pin for the ARM */ - reg = bank->base + OMAP1510_GPIO_PIN_CONTROL; - __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg); - } -#endif - spin_unlock(&bank->lock); - - return 0; -} - -void omap_free_gpio(int gpio) -{ - struct gpio_bank *bank; - - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); - spin_lock(&bank->lock); - if (unlikely(!(bank->reserved_map & (1 << get_gpio_index(gpio))))) { - printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio); - dump_stack(); - spin_unlock(&bank->lock); - return; - } - bank->reserved_map &= ~(1 << get_gpio_index(gpio)); - _set_gpio_direction(bank, get_gpio_index(gpio), 1); - _set_gpio_irqenable(bank, gpio, 0); - _clear_gpio_irqstatus(bank, gpio); - spin_unlock(&bank->lock); -} - -/* - * We need to unmask the GPIO bank interrupt as soon as possible to - * avoid missing GPIO interrupts for other lines in the bank. - * Then we need to mask-read-clear-unmask the triggered GPIO lines - * in the bank to avoid missing nested interrupts for a GPIO line. - * If we wait to unmask individual GPIO lines in the bank after the - * line's interrupt handler has been run, we may miss some nested - * interrupts. - */ -static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, - struct pt_regs *regs) -{ - u32 isr_reg = 0; - u32 isr; - unsigned int gpio_irq; - struct gpio_bank *bank; - - desc->chip->ack(irq); - - bank = (struct gpio_bank *) desc->data; - if (bank->method == METHOD_MPUIO) - isr_reg = bank->base + OMAP_MPUIO_GPIO_INT; -#ifdef CONFIG_ARCH_OMAP1510 - if (bank->method == METHOD_GPIO_1510) - isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS; -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (bank->method == METHOD_GPIO_1610) - isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1; -#endif -#ifdef CONFIG_ARCH_OMAP730 - if (bank->method == METHOD_GPIO_730) - isr_reg = bank->base + OMAP730_GPIO_INT_STATUS; -#endif - - isr = __raw_readl(isr_reg); - _enable_gpio_irqbank(bank, isr, 0); - _clear_gpio_irqbank(bank, isr); - _enable_gpio_irqbank(bank, isr, 1); - desc->chip->unmask(irq); - - if (unlikely(!isr)) - return; - - gpio_irq = bank->virtual_irq_start; - for (; isr != 0; isr >>= 1, gpio_irq++) { - struct irqdesc *d; - if (!(isr & 1)) - continue; - d = irq_desc + gpio_irq; - d->handle(gpio_irq, d, regs); - } -} - -static void gpio_ack_irq(unsigned int irq) -{ - unsigned int gpio = irq - IH_GPIO_BASE; - struct gpio_bank *bank = get_gpio_bank(gpio); - - _clear_gpio_irqstatus(bank, gpio); -} - -static void gpio_mask_irq(unsigned int irq) -{ - unsigned int gpio = irq - IH_GPIO_BASE; - struct gpio_bank *bank = get_gpio_bank(gpio); - - _set_gpio_irqenable(bank, gpio, 0); -} - -static void gpio_unmask_irq(unsigned int irq) -{ - unsigned int gpio = irq - IH_GPIO_BASE; - struct gpio_bank *bank = get_gpio_bank(gpio); - - if (_get_gpio_edge_ctrl(bank, get_gpio_index(gpio)) == OMAP_GPIO_NO_EDGE) { - printk(KERN_ERR "OMAP GPIO %d: trying to enable GPIO IRQ while no edge is set\n", - gpio); - _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE); - } - _set_gpio_irqenable(bank, gpio, 1); -} - -static void mpuio_ack_irq(unsigned int irq) -{ - /* The ISR is reset automatically, so do nothing here. */ -} - -static void mpuio_mask_irq(unsigned int irq) -{ - unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE); - struct gpio_bank *bank = get_gpio_bank(gpio); - - _set_gpio_irqenable(bank, gpio, 0); -} - -static void mpuio_unmask_irq(unsigned int irq) -{ - unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE); - struct gpio_bank *bank = get_gpio_bank(gpio); - - _set_gpio_irqenable(bank, gpio, 1); -} - -static struct irqchip gpio_irq_chip = { - .ack = gpio_ack_irq, - .mask = gpio_mask_irq, - .unmask = gpio_unmask_irq, -}; - -static struct irqchip mpuio_irq_chip = { - .ack = mpuio_ack_irq, - .mask = mpuio_mask_irq, - .unmask = mpuio_unmask_irq -}; - -static int initialized = 0; - -static int __init _omap_gpio_init(void) -{ - int i; - struct gpio_bank *bank; - - initialized = 1; - -#ifdef CONFIG_ARCH_OMAP1510 - if (cpu_is_omap1510()) { - printk(KERN_INFO "OMAP1510 GPIO hardware\n"); - gpio_bank_count = 2; - gpio_bank = gpio_bank_1510; - } -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (cpu_is_omap16xx()) { - int rev; - - gpio_bank_count = 5; - gpio_bank = gpio_bank_1610; - rev = omap_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION); - printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n", - (rev >> 4) & 0x0f, rev & 0x0f); - } -#endif -#ifdef CONFIG_ARCH_OMAP730 - if (cpu_is_omap730()) { - printk(KERN_INFO "OMAP730 GPIO hardware\n"); - gpio_bank_count = 7; - gpio_bank = gpio_bank_730; - } -#endif - for (i = 0; i < gpio_bank_count; i++) { - int j, gpio_count = 16; - - bank = &gpio_bank[i]; - bank->reserved_map = 0; - bank->base = IO_ADDRESS(bank->base); - spin_lock_init(&bank->lock); - if (bank->method == METHOD_MPUIO) { - omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT); - } -#ifdef CONFIG_ARCH_OMAP1510 - if (bank->method == METHOD_GPIO_1510) { - __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK); - __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS); - } -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (bank->method == METHOD_GPIO_1610) { - __raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1); - __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1); - } -#endif -#ifdef CONFIG_ARCH_OMAP730 - if (bank->method == METHOD_GPIO_730) { - __raw_writel(0xffffffff, bank->base + OMAP730_GPIO_INT_MASK); - __raw_writel(0x00000000, bank->base + OMAP730_GPIO_INT_STATUS); - - gpio_count = 32; /* 730 has 32-bit GPIOs */ - } -#endif - for (j = bank->virtual_irq_start; - j < bank->virtual_irq_start + gpio_count; j++) { - if (bank->method == METHOD_MPUIO) - set_irq_chip(j, &mpuio_irq_chip); - else - set_irq_chip(j, &gpio_irq_chip); - set_irq_handler(j, do_simple_IRQ); - set_irq_flags(j, IRQF_VALID); - } - set_irq_chained_handler(bank->irq, gpio_irq_handler); - set_irq_data(bank->irq, bank); - } - - /* Enable system clock for GPIO module. - * The CAM_CLK_CTRL *is* really the right place. */ - if (cpu_is_omap1610() || cpu_is_omap1710()) - omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL); - - return 0; -} - -/* - * This may get called early from board specific init - */ -int omap_gpio_init(void) -{ - if (!initialized) - return _omap_gpio_init(); - else - return 0; -} - -EXPORT_SYMBOL(omap_request_gpio); -EXPORT_SYMBOL(omap_free_gpio); -EXPORT_SYMBOL(omap_set_gpio_direction); -EXPORT_SYMBOL(omap_set_gpio_dataout); -EXPORT_SYMBOL(omap_get_gpio_datain); -EXPORT_SYMBOL(omap_set_gpio_edge_ctrl); - -arch_initcall(omap_gpio_init); diff --git a/arch/arm/mach-omap/mcbsp.c b/arch/arm/mach-omap/mcbsp.c deleted file mode 100644 index 7c4ad771309..00000000000 --- a/arch/arm/mach-omap/mcbsp.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * linux/arch/arm/omap/mcbsp.c - * - * Copyright (C) 2004 Nokia Corporation - * Author: Samuel Ortiz <samuel.ortiz@nokia.com> - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Multichannel mode not supported. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/wait.h> -#include <linux/completion.h> -#include <linux/interrupt.h> -#include <linux/err.h> - -#include <asm/delay.h> -#include <asm/io.h> -#include <asm/irq.h> - -#include <asm/arch/dma.h> -#include <asm/arch/mux.h> -#include <asm/arch/irqs.h> -#include <asm/arch/mcbsp.h> - -#include <asm/hardware/clock.h> - -#ifdef CONFIG_MCBSP_DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) do { } while (0) -#endif - -struct omap_mcbsp { - u32 io_base; - u8 id; - u8 free; - omap_mcbsp_word_length rx_word_length; - omap_mcbsp_word_length tx_word_length; - - /* IRQ based TX/RX */ - int rx_irq; - int tx_irq; - - /* DMA stuff */ - u8 dma_rx_sync; - short dma_rx_lch; - u8 dma_tx_sync; - short dma_tx_lch; - - /* Completion queues */ - struct completion tx_irq_completion; - struct completion rx_irq_completion; - struct completion tx_dma_completion; - struct completion rx_dma_completion; - - spinlock_t lock; -}; - -static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; -static struct clk *mcbsp_dsp_ck = 0; -static struct clk *mcbsp_api_ck = 0; - - -static void omap_mcbsp_dump_reg(u8 id) -{ - DBG("**** MCBSP%d regs ****\n", mcbsp[id].id); - DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); - DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); - DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); - DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); - DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); - DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); - DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); - DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); - DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); - DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); - DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); - DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); - DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); - DBG("***********************\n"); -} - - -static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id); - - DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2)); - - complete(&mcbsp_tx->tx_irq_completion); - return IRQ_HANDLED; -} - -static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs) -{ - struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id); - - DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2)); - - complete(&mcbsp_rx->rx_irq_completion); - return IRQ_HANDLED; -} - - -static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) -{ - struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data); - - DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2)); - - /* We can free the channels */ - omap_free_dma(mcbsp_dma_tx->dma_tx_lch); - mcbsp_dma_tx->dma_tx_lch = -1; - - complete(&mcbsp_dma_tx->tx_dma_completion); -} - -static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) -{ - struct omap_mcbsp * mcbsp_dma_rx = (struct omap_mcbsp *)(data); - - DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2)); - - /* We can free the channels */ - omap_free_dma(mcbsp_dma_rx->dma_rx_lch); - mcbsp_dma_rx->dma_rx_lch = -1; - - complete(&mcbsp_dma_rx->rx_dma_completion); -} - - -/* - * omap_mcbsp_config simply write a config to the - * appropriate McBSP. - * You either call this function or set the McBSP registers - * by yourself before calling omap_mcbsp_start(). - */ - -void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config) -{ - u32 io_base = mcbsp[id].io_base; - - DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id+1, io_base); - - /* We write the given config */ - OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); - OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1); - OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2); - OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1); - OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2); - OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1); - OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2); - OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1); - OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2); - OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1); - OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0); -} - - - -static int omap_mcbsp_check(unsigned int id) -{ - if (cpu_is_omap730()) { - if (id > OMAP_MAX_MCBSP_COUNT - 1) { - printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); - return -1; - } - return 0; - } - - if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) { - if (id > OMAP_MAX_MCBSP_COUNT) { - printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); - return -1; - } - return 0; - } - - return -1; -} - -#define EN_XORPCK 1 -#define DSP_RSTCT2 0xe1008014 - -static void omap_mcbsp_dsp_request(void) -{ - if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) { - omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)), - ARM_RSTCT1); - clk_enable(mcbsp_dsp_ck); - clk_enable(mcbsp_api_ck); - - /* enable 12MHz clock to mcbsp 1 & 3 */ - __raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK), - DSP_IDLECT2); - __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1, - DSP_RSTCT2); - } -} - -static void omap_mcbsp_dsp_free(void) -{ - /* Useless for now */ -} - - -int omap_mcbsp_request(unsigned int id) -{ - int err; - - if (omap_mcbsp_check(id) < 0) - return -EINVAL; - - /* - * On 1510, 1610 and 1710, McBSP1 and McBSP3 - * are DSP public peripherals. - */ - if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) - omap_mcbsp_dsp_request(); - - spin_lock(&mcbsp[id].lock); - if (!mcbsp[id].free) { - printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1); - spin_unlock(&mcbsp[id].lock); - return -1; - } - - mcbsp[id].free = 0; - spin_unlock(&mcbsp[id].lock); - - /* We need to get IRQs here */ - err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0, - "McBSP", - (void *) (&mcbsp[id])); - if (err != 0) { - printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n", - mcbsp[id].tx_irq, mcbsp[id].id); - return err; - } - - init_completion(&(mcbsp[id].tx_irq_completion)); - - - err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0, - "McBSP", - (void *) (&mcbsp[id])); - if (err != 0) { - printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n", - mcbsp[id].rx_irq, mcbsp[id].id); - free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); - return err; - } - - init_completion(&(mcbsp[id].rx_irq_completion)); - return 0; - -} - -void omap_mcbsp_free(unsigned int id) -{ - if (omap_mcbsp_check(id) < 0) - return; - - if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) - omap_mcbsp_dsp_free(); - - spin_lock(&mcbsp[id].lock); - if (mcbsp[id].free) { - printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1); - spin_unlock(&mcbsp[id].lock); - return; - } - - mcbsp[id].free = 1; - spin_unlock(&mcbsp[id].lock); - - /* Free IRQs */ - free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id])); - free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); -} - -/* - * Here we start the McBSP, by enabling the sample - * generator, both transmitter and receivers, - * and the frame sync. - */ -void omap_mcbsp_start(unsigned int id) -{ - u32 io_base; - u16 w; - - if (omap_mcbsp_check(id) < 0) - return; - - io_base = mcbsp[id].io_base; - - mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7); - mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7); - - /* Start the sample generator */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); - - /* Enable transmitter and receiver */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1); - - w = OMAP_MCBSP_READ(io_base, SPCR1); - OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1); - - udelay(100); - - /* Start frame sync */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); - - /* Dump McBSP Regs */ - omap_mcbsp_dump_reg(id); - -} - -void omap_mcbsp_stop(unsigned int id) -{ - u32 io_base; - u16 w; - - if (omap_mcbsp_check(id) < 0) - return; - - io_base = mcbsp[id].io_base; - - /* Reset transmitter */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); - - /* Reset receiver */ - w = OMAP_MCBSP_READ(io_base, SPCR1); - OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1)); - - /* Reset the sample rate generator */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); -} - - -/* - * IRQ based word transmission. - */ -void omap_mcbsp_xmit_word(unsigned int id, u32 word) -{ - u32 io_base; - omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length; - - if (omap_mcbsp_check(id) < 0) - return; - - io_base = mcbsp[id].io_base; - - wait_for_completion(&(mcbsp[id].tx_irq_completion)); - - if (word_length > OMAP_MCBSP_WORD_16) - OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); - OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff); -} - -u32 omap_mcbsp_recv_word(unsigned int id) -{ - u32 io_base; - u16 word_lsb, word_msb = 0; - omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length; - - if (omap_mcbsp_check(id) < 0) - return -EINVAL; - - io_base = mcbsp[id].io_base; - - wait_for_completion(&(mcbsp[id].rx_irq_completion)); - - if (word_length > OMAP_MCBSP_WORD_16) - word_msb = OMAP_MCBSP_READ(io_base, DRR2); - word_lsb = OMAP_MCBSP_READ(io_base, DRR1); - - return (word_lsb | (word_msb << 16)); -} - - -/* - * Simple DMA based buffer rx/tx routines. - * Nothing fancy, just a single buffer tx/rx through DMA. - * The DMA resources are released once the transfer is done. - * For anything fancier, you should use your own customized DMA - * routines and callbacks. - */ -int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) -{ - int dma_tx_ch; - - if (omap_mcbsp_check(id) < 0) - return -EINVAL; - - if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback, - &mcbsp[id], - &dma_tx_ch)) { - printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1); - return -EAGAIN; - } - mcbsp[id].dma_tx_lch = dma_tx_ch; - - DBG("TX DMA on channel %d\n", dma_tx_ch); - - init_completion(&(mcbsp[id].tx_dma_completion)); - - omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, - OMAP_DMA_DATA_TYPE_S16, - length >> 1, 1, - OMAP_DMA_SYNC_ELEMENT); - - omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, - OMAP_DMA_PORT_TIPB, - OMAP_DMA_AMODE_CONSTANT, - mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1); - - omap_set_dma_src_params(mcbsp[id].dma_tx_lch, - OMAP_DMA_PORT_EMIFF, - OMAP_DMA_AMODE_POST_INC, - buffer); - - omap_start_dma(mcbsp[id].dma_tx_lch); - wait_for_completion(&(mcbsp[id].tx_dma_completion)); - return 0; -} - - -int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) -{ - int dma_rx_ch; - - if (omap_mcbsp_check(id) < 0) - return -EINVAL; - - if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback, - &mcbsp[id], - &dma_rx_ch)) { - printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1); - return -EAGAIN; - } - mcbsp[id].dma_rx_lch = dma_rx_ch; - - DBG("RX DMA on channel %d\n", dma_rx_ch); - - init_completion(&(mcbsp[id].rx_dma_completion)); - - omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, - OMAP_DMA_DATA_TYPE_S16, - length >> 1, 1, - OMAP_DMA_SYNC_ELEMENT); - - omap_set_dma_src_params(mcbsp[id].dma_rx_lch, - OMAP_DMA_PORT_TIPB, - OMAP_DMA_AMODE_CONSTANT, - mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1); - - omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, - OMAP_DMA_PORT_EMIFF, - OMAP_DMA_AMODE_POST_INC, - buffer); - - omap_start_dma(mcbsp[id].dma_rx_lch); - wait_for_completion(&(mcbsp[id].rx_dma_completion)); - return 0; -} - - -/* - * SPI wrapper. - * Since SPI setup is much simpler than the generic McBSP one, - * this wrapper just need an omap_mcbsp_spi_cfg structure as an input. - * Once this is done, you can call omap_mcbsp_start(). - */ -void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg) -{ - struct omap_mcbsp_reg_cfg mcbsp_cfg; - - if (omap_mcbsp_check(id) < 0) - return; - - memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); - - /* SPI has only one frame */ - mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0)); - mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0)); - - /* Clock stop mode */ - if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY) - mcbsp_cfg.spcr1 |= (1 << 12); - else - mcbsp_cfg.spcr1 |= (3 << 11); - - /* Set clock parities */ - if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING) - mcbsp_cfg.pcr0 |= CLKRP; - else - mcbsp_cfg.pcr0 &= ~CLKRP; - - if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING) - mcbsp_cfg.pcr0 &= ~CLKXP; - else - mcbsp_cfg.pcr0 |= CLKXP; - - /* Set SCLKME to 0 and CLKSM to 1 */ - mcbsp_cfg.pcr0 &= ~SCLKME; - mcbsp_cfg.srgr2 |= CLKSM; - - /* Set FSXP */ - if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH) - mcbsp_cfg.pcr0 &= ~FSXP; - else - mcbsp_cfg.pcr0 |= FSXP; - - if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) { - mcbsp_cfg.pcr0 |= CLKXM; - mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1); - mcbsp_cfg.pcr0 |= FSXM; - mcbsp_cfg.srgr2 &= ~FSGM; - mcbsp_cfg.xcr2 |= XDATDLY(1); - mcbsp_cfg.rcr2 |= RDATDLY(1); - } - else { - mcbsp_cfg.pcr0 &= ~CLKXM; - mcbsp_cfg.srgr1 |= CLKGDV(1); - mcbsp_cfg.pcr0 &= ~FSXM; - mcbsp_cfg.xcr2 &= ~XDATDLY(3); - mcbsp_cfg.rcr2 &= ~RDATDLY(3); - } - - mcbsp_cfg.xcr2 &= ~XPHASE; - mcbsp_cfg.rcr2 &= ~RPHASE; - - omap_mcbsp_config(id, &mcbsp_cfg); -} - - -/* - * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. - * 730 has only 2 McBSP, and both of them are MPU peripherals. - */ -struct omap_mcbsp_info { - u32 virt_base; - u8 dma_rx_sync, dma_tx_sync; - u16 rx_irq, tx_irq; -}; - -#ifdef CONFIG_ARCH_OMAP730 -static const struct omap_mcbsp_info mcbsp_730[] = { - [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE), - .dma_rx_sync = OMAP_DMA_MCBSP1_RX, - .dma_tx_sync = OMAP_DMA_MCBSP1_TX, - .rx_irq = INT_730_McBSP1RX, - .tx_irq = INT_730_McBSP1TX }, - [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE), - .dma_rx_sync = OMAP_DMA_MCBSP3_RX, - .dma_tx_sync = OMAP_DMA_MCBSP3_TX, - .rx_irq = INT_730_McBSP2RX, - .tx_irq = INT_730_McBSP2TX }, -}; -#endif - -#ifdef CONFIG_ARCH_OMAP1510 -static const struct omap_mcbsp_info mcbsp_1510[] = { - [0] = { .virt_base = OMAP1510_MCBSP1_BASE, - .dma_rx_sync = OMAP_DMA_MCBSP1_RX, - .dma_tx_sync = OMAP_DMA_MCBSP1_TX, - .rx_irq = INT_McBSP1RX, - .tx_irq = INT_McBSP1TX }, - [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE), - .dma_rx_sync = OMAP_DMA_MCBSP2_RX, - .dma_tx_sync = OMAP_DMA_MCBSP2_TX, - .rx_irq = INT_1510_SPI_RX, - .tx_irq = INT_1510_SPI_TX }, - [2] = { .virt_base = OMAP1510_MCBSP3_BASE, - .dma_rx_sync = OMAP_DMA_MCBSP3_RX, - .dma_tx_sync = OMAP_DMA_MCBSP3_TX, - .rx_irq = INT_McBSP3RX, - .tx_irq = INT_McBSP3TX }, -}; -#endif - -#if defined(CONFIG_ARCH_OMAP16XX) -static const struct omap_mcbsp_info mcbsp_1610[] = { - [0] = { .virt_base = OMAP1610_MCBSP1_BASE, - .dma_rx_sync = OMAP_DMA_MCBSP1_RX, - .dma_tx_sync = OMAP_DMA_MCBSP1_TX, - .rx_irq = INT_McBSP1RX, - .tx_irq = INT_McBSP1TX }, - [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE), - .dma_rx_sync = OMAP_DMA_MCBSP2_RX, - .dma_tx_sync = OMAP_DMA_MCBSP2_TX, - .rx_irq = INT_1610_McBSP2_RX, - .tx_irq = INT_1610_McBSP2_TX }, - [2] = { .virt_base = OMAP1610_MCBSP3_BASE, - .dma_rx_sync = OMAP_DMA_MCBSP3_RX, - .dma_tx_sync = OMAP_DMA_MCBSP3_TX, - .rx_irq = INT_McBSP3RX, - .tx_irq = INT_McBSP3TX }, -}; -#endif - -static int __init omap_mcbsp_init(void) -{ - int mcbsp_count = 0, i; - static const struct omap_mcbsp_info *mcbsp_info; - - printk("Initializing OMAP McBSP system\n"); - - mcbsp_dsp_ck = clk_get(0, "dsp_ck"); - if (IS_ERR(mcbsp_dsp_ck)) { - printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); - return PTR_ERR(mcbsp_dsp_ck); - } - mcbsp_api_ck = clk_get(0, "api_ck"); - if (IS_ERR(mcbsp_dsp_ck)) { - printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n"); - return PTR_ERR(mcbsp_api_ck); - } - -#ifdef CONFIG_ARCH_OMAP730 - if (cpu_is_omap730()) { - mcbsp_info = mcbsp_730; - mcbsp_count = ARRAY_SIZE(mcbsp_730); - } -#endif -#ifdef CONFIG_ARCH_OMAP1510 - if (cpu_is_omap1510()) { - mcbsp_info = mcbsp_1510; - mcbsp_count = ARRAY_SIZE(mcbsp_1510); - } -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (cpu_is_omap1610() || cpu_is_omap1710()) { - mcbsp_info = mcbsp_1610; - mcbsp_count = ARRAY_SIZE(mcbsp_1610); - } -#endif - for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { - if (i >= mcbsp_count) { - mcbsp[i].io_base = 0; - mcbsp[i].free = 0; - continue; - } - mcbsp[i].id = i + 1; - mcbsp[i].free = 1; - mcbsp[i].dma_tx_lch = -1; - mcbsp[i].dma_rx_lch = -1; - - mcbsp[i].io_base = mcbsp_info[i].virt_base; - mcbsp[i].tx_irq = mcbsp_info[i].tx_irq; - mcbsp[i].rx_irq = mcbsp_info[i].rx_irq; - mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync; - mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync; - spin_lock_init(&mcbsp[i].lock); - } - - return 0; -} - - -arch_initcall(omap_mcbsp_init); - -EXPORT_SYMBOL(omap_mcbsp_config); -EXPORT_SYMBOL(omap_mcbsp_request); -EXPORT_SYMBOL(omap_mcbsp_free); -EXPORT_SYMBOL(omap_mcbsp_start); -EXPORT_SYMBOL(omap_mcbsp_stop); -EXPORT_SYMBOL(omap_mcbsp_xmit_word); -EXPORT_SYMBOL(omap_mcbsp_recv_word); -EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); -EXPORT_SYMBOL(omap_mcbsp_recv_buffer); -EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); diff --git a/arch/arm/mach-omap/mux.c b/arch/arm/mach-omap/mux.c deleted file mode 100644 index bcf3c6e5ecd..00000000000 --- a/arch/arm/mach-omap/mux.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * linux/arch/arm/mach-omap/mux.c - * - * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h - * - * Copyright (C) 2003 Nokia Corporation - * - * Written by Tony Lindgren <tony.lindgren@nokia.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include <linux/config.h> -#include <linux/module.h> -#include <linux/init.h> -#include <asm/system.h> -#include <asm/io.h> -#include <linux/spinlock.h> - -#define __MUX_C__ -#include <asm/arch/mux.h> - -#ifdef CONFIG_OMAP_MUX - -/* - * Sets the Omap MUX and PULL_DWN registers based on the table - */ -int __init_or_module -omap_cfg_reg(const reg_cfg_t reg_cfg) -{ - static DEFINE_SPINLOCK(mux_spin_lock); - - unsigned long flags; - reg_cfg_set *cfg; - unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0, - pull_orig = 0, pull = 0; - unsigned int mask, warn = 0; - - if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) { - printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg); - return -EINVAL; - } - - cfg = ®_cfg_table[reg_cfg]; - - /* - * We do a pretty long section here with lock on, but pin muxing - * should only happen on driver init for each driver, so it's not time - * critical. - */ - spin_lock_irqsave(&mux_spin_lock, flags); - - /* Check the mux register in question */ - if (cfg->mux_reg) { - unsigned tmp1, tmp2; - - reg_orig = omap_readl(cfg->mux_reg); - - /* The mux registers always seem to be 3 bits long */ - mask = (0x7 << cfg->mask_offset); - tmp1 = reg_orig & mask; - reg = reg_orig & ~mask; - - tmp2 = (cfg->mask << cfg->mask_offset); - reg |= tmp2; - - if (tmp1 != tmp2) - warn = 1; - - omap_writel(reg, cfg->mux_reg); - } - - /* Check for pull up or pull down selection on 1610 */ - if (!cpu_is_omap1510()) { - if (cfg->pu_pd_reg && cfg->pull_val) { - pu_pd_orig = omap_readl(cfg->pu_pd_reg); - mask = 1 << cfg->pull_bit; - - if (cfg->pu_pd_val) { - if (!(pu_pd_orig & mask)) - warn = 1; - /* Use pull up */ - pu_pd = pu_pd_orig | mask; - } else { - if (pu_pd_orig & mask) - warn = 1; - /* Use pull down */ - pu_pd = pu_pd_orig & ~mask; - } - omap_writel(pu_pd, cfg->pu_pd_reg); - } - } - - /* Check for an associated pull down register */ - if (cfg->pull_reg) { - pull_orig = omap_readl(cfg->pull_reg); - mask = 1 << cfg->pull_bit; - - if (cfg->pull_val) { - if (pull_orig & mask) - warn = 1; - /* Low bit = pull enabled */ - pull = pull_orig & ~mask; - } else { - if (!(pull_orig & mask)) - warn = 1; - /* High bit = pull disabled */ - pull = pull_orig | mask; - } - - omap_writel(pull, cfg->pull_reg); - } - - if (warn) { -#ifdef CONFIG_OMAP_MUX_WARNINGS - printk(KERN_WARNING "MUX: initialized %s\n", cfg->name); -#endif - } - -#ifdef CONFIG_OMAP_MUX_DEBUG - if (cfg->debug || warn) { - printk("MUX: Setting register %s\n", cfg->name); - printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n", - cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg); - - if (!cpu_is_omap1510()) { - if (cfg->pu_pd_reg && cfg->pull_val) { - printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n", - cfg->pu_pd_name, cfg->pu_pd_reg, - pu_pd_orig, pu_pd); - } - } - - if (cfg->pull_reg) - printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n", - cfg->pull_name, cfg->pull_reg, pull_orig, pull); - } -#endif - - spin_unlock_irqrestore(&mux_spin_lock, flags); - -#ifdef CONFIG_OMAP_MUX_ERRORS - return warn ? -ETXTBSY : 0; -#else - return 0; -#endif -} - -EXPORT_SYMBOL(omap_cfg_reg); - -#endif /* CONFIG_OMAP_MUX */ diff --git a/arch/arm/mach-omap/ocpi.c b/arch/arm/mach-omap/ocpi.c deleted file mode 100644 index c9ced134a75..00000000000 --- a/arch/arm/mach-omap/ocpi.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * linux/arch/arm/mach-omap/ocpi.c - * - * Minimal OCP bus support for omap16xx - * - * Copyright (C) 2003 - 2005 Nokia Corporation - * Written by Tony Lindgren <tony@atomide.com> - * - * Modified for clock framework by Paul Mundt <paul.mundt@nokia.com>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/version.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/err.h> - -#include <asm/io.h> -#include <asm/hardware/clock.h> -#include <asm/arch/hardware.h> - -#define OCPI_BASE 0xfffec320 -#define OCPI_FAULT (OCPI_BASE + 0x00) -#define OCPI_CMD_FAULT (OCPI_BASE + 0x04) -#define OCPI_SINT0 (OCPI_BASE + 0x08) -#define OCPI_TABORT (OCPI_BASE + 0x0c) -#define OCPI_SINT1 (OCPI_BASE + 0x10) -#define OCPI_PROT (OCPI_BASE + 0x14) -#define OCPI_SEC (OCPI_BASE + 0x18) - -/* USB OHCI OCPI access error registers */ -#define HOSTUEADDR 0xfffba0e0 -#define HOSTUESTATUS 0xfffba0e4 - -static struct clk *ocpi_ck; - -/* - * Enables device access to OMAP buses via the OCPI bridge - * FIXME: Add locking - */ -int ocpi_enable(void) -{ - unsigned int val; - - if (!cpu_is_omap16xx()) - return -ENODEV; - - /* Make sure there's clock for OCPI */ - clk_enable(ocpi_ck); - - /* Enable access for OHCI in OCPI */ - val = omap_readl(OCPI_PROT); - val &= ~0xff; - //val &= (1 << 0); /* Allow access only to EMIFS */ - omap_writel(val, OCPI_PROT); - - val = omap_readl(OCPI_SEC); - val &= ~0xff; - omap_writel(val, OCPI_SEC); - - return 0; -} -EXPORT_SYMBOL(ocpi_enable); - -static int __init omap_ocpi_init(void) -{ - if (!cpu_is_omap16xx()) - return -ENODEV; - - ocpi_ck = clk_get(NULL, "l3_ocpi_ck"); - if (IS_ERR(ocpi_ck)) - return PTR_ERR(ocpi_ck); - - clk_use(ocpi_ck); - ocpi_enable(); - printk("OMAP OCPI interconnect driver loaded\n"); - - return 0; -} - -static void __exit omap_ocpi_exit(void) -{ - /* REVISIT: Disable OCPI */ - - if (!cpu_is_omap16xx()) - return; - - clk_unuse(ocpi_ck); - clk_put(ocpi_ck); -} - -MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>"); -MODULE_DESCRIPTION("OMAP OCPI bus controller module"); -MODULE_LICENSE("GPL"); -module_init(omap_ocpi_init); -module_exit(omap_ocpi_exit); diff --git a/arch/arm/mach-omap/pm.c b/arch/arm/mach-omap/pm.c deleted file mode 100644 index 6b03ccdc1e9..00000000000 --- a/arch/arm/mach-omap/pm.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * linux/arch/arm/mach-omap/pm.c - * - * OMAP Power Management Routines - * - * Original code for the SA11x0: - * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> - * - * Modified for the PXA250 by Nicolas Pitre: - * Copyright (c) 2002 Monta Vista Software, Inc. - * - * Modified for the OMAP1510 by David Singleton: - * Copyright (c) 2002 Monta Vista Software, Inc. - * - * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/pm.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <linux/pm.h> - -#include <asm/io.h> -#include <asm/mach/time.h> -#include <asm/mach-types.h> - -#include <asm/arch/omap16xx.h> -#include <asm/arch/pm.h> -#include <asm/arch/mux.h> -#include <asm/arch/tc.h> -#include <asm/arch/tps65010.h> - -#include "clock.h" - -static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE]; -static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE]; -static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE]; -static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; - -/* - * Let's power down on idle, but only if we are really - * idle, because once we start down the path of - * going idle we continue to do idle even if we get - * a clock tick interrupt . . - */ -void omap_pm_idle(void) -{ - int (*func_ptr)(void) = 0; - unsigned int mask32 = 0; - - /* - * If the DSP is being used let's just idle the CPU, the overhead - * to wake up from Big Sleep is big, milliseconds versus micro - * seconds for wait for interrupt. - */ - - local_irq_disable(); - local_fiq_disable(); - if (need_resched()) { - local_fiq_enable(); - local_irq_enable(); - return; - } - mask32 = omap_readl(ARM_SYSST); - - /* - * Since an interrupt may set up a timer, we don't want to - * reprogram the hardware timer with interrupts enabled. - * Re-enable interrupts only after returning from idle. - */ - timer_dyn_reprogram(); - - if ((mask32 & DSP_IDLE) == 0) { - __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); - } else { - - if (cpu_is_omap1510()) { - func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND); - } else if (cpu_is_omap1610() || cpu_is_omap1710()) { - func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND); - } else if (cpu_is_omap5912()) { - func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND); - } - - func_ptr(); - } - local_fiq_enable(); - local_irq_enable(); -} - -/* - * Configuration of the wakeup event is board specific. For the - * moment we put it into this helper function. Later it may move - * to board specific files. - */ -static void omap_pm_wakeup_setup(void) -{ - /* - * Enable ARM XOR clock and release peripheral from reset by - * writing 1 to PER_EN bit in ARM_RSTCT2, this is required - * for UART configuration to use UART2 to wake up. - */ - - omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2); - omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2); - omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL); - - /* - * Turn off all interrupts except L1-2nd level cascade, - * and the L2 wakeup interrupts: keypad and UART2. - */ - - omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR); - - if (cpu_is_omap1510()) { - omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_MIR); - } - - if (cpu_is_omap16xx()) { - omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR); - - omap_writel(~0x0, OMAP_IH2_1_MIR); - omap_writel(~0x0, OMAP_IH2_2_MIR); - omap_writel(~0x0, OMAP_IH2_3_MIR); - } - - /* New IRQ agreement */ - omap_writel(1, OMAP_IH1_CONTROL); - - /* external PULL to down, bit 22 = 0 */ - omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2); -} - -void omap_pm_suspend(void) -{ - unsigned int mask32 = 0; - unsigned long arg0 = 0, arg1 = 0; - int (*func_ptr)(unsigned short, unsigned short) = 0; - unsigned short save_dsp_idlect2; - - printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev); - - if (machine_is_omap_osk()) { - /* Stop LED1 (D9) blink */ - tps65010_set_led(LED1, OFF); - } - - /* - * Step 1: turn off interrupts - */ - - local_irq_disable(); - local_fiq_disable(); - - /* - * Step 2: save registers - * - * The omap is a strange/beautiful device. The caches, memory - * and register state are preserved across power saves. - * We have to save and restore very little register state to - * idle the omap. - * - * Save interrupt, MPUI, ARM and UPLD control registers. - */ - - if (cpu_is_omap1510()) { - MPUI1510_SAVE(OMAP_IH1_MIR); - MPUI1510_SAVE(OMAP_IH2_MIR); - MPUI1510_SAVE(MPUI_CTRL); - MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI1510_SAVE(MPUI_DSP_API_CONFIG); - MPUI1510_SAVE(EMIFS_CONFIG); - MPUI1510_SAVE(EMIFF_SDRAM_CONFIG); - } else if (cpu_is_omap16xx()) { - MPUI1610_SAVE(OMAP_IH1_MIR); - MPUI1610_SAVE(OMAP_IH2_0_MIR); - MPUI1610_SAVE(OMAP_IH2_1_MIR); - MPUI1610_SAVE(OMAP_IH2_2_MIR); - MPUI1610_SAVE(OMAP_IH2_3_MIR); - MPUI1610_SAVE(MPUI_CTRL); - MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI1610_SAVE(MPUI_DSP_API_CONFIG); - MPUI1610_SAVE(EMIFS_CONFIG); - MPUI1610_SAVE(EMIFF_SDRAM_CONFIG); - } - - ARM_SAVE(ARM_CKCTL); - ARM_SAVE(ARM_IDLECT1); - ARM_SAVE(ARM_IDLECT2); - ARM_SAVE(ARM_EWUPCT); - ARM_SAVE(ARM_RSTCT1); - ARM_SAVE(ARM_RSTCT2); - ARM_SAVE(ARM_SYSST); - ULPD_SAVE(ULPD_CLOCK_CTRL); - ULPD_SAVE(ULPD_STATUS_REQ); - - /* - * Step 3: LOW_PWR signal enabling - * - * Allow the LOW_PWR signal to be visible on MPUIO5 ball. - */ - if (cpu_is_omap1510()) { - /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */ - omap_writew(omap_readw(ULPD_POWER_CTRL) | - OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL); - } else if (cpu_is_omap16xx()) { - /* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */ - omap_writew(omap_readw(ULPD_POWER_CTRL) | - OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL); - } - - /* configure LOW_PWR pin */ - omap_cfg_reg(T20_1610_LOW_PWR); - - /* - * Step 4: OMAP DSP Shutdown - */ - - /* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */ - omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE, - ARM_RSTCT1); - - /* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */ - omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG); - - /* Set EN_DSPCK = 0, stop DSP block clock */ - omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL); - - /* Stop any DSP domain clocks */ - omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2); - save_dsp_idlect2 = __raw_readw(DSP_IDLECT2); - __raw_writew(0, DSP_IDLECT2); - - /* - * Step 5: Wakeup Event Setup - */ - - omap_pm_wakeup_setup(); - - /* - * Step 6a: ARM and Traffic controller shutdown - * - * Step 6 starts here with clock and watchdog disable - */ - - /* stop clocks */ - mask32 = omap_readl(ARM_IDLECT2); - mask32 &= ~(1<<EN_WDTCK); /* bit 0 -> 0 (WDT clock) */ - mask32 |= (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */ - mask32 &= ~(1<<EN_PERCK); /* bit 2 -> 0 (MPUPER_CK clock) */ - mask32 &= ~(1<<EN_LCDCK); /* bit 3 -> 0 (LCDC clock) */ - mask32 &= ~(1<<EN_LBCK); /* bit 4 -> 0 (local bus clock) */ - mask32 |= (1<<EN_APICK); /* bit 6 -> 1 (MPUI clock) */ - mask32 &= ~(1<<EN_TIMCK); /* bit 7 -> 0 (MPU timer clock) */ - mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */ - mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */ - omap_writel(mask32, ARM_IDLECT2); - - /* disable ARM watchdog */ - omap_writel(0x00F5, OMAP_WDT_TIMER_MODE); - omap_writel(0x00A0, OMAP_WDT_TIMER_MODE); - - /* - * Step 6b: ARM and Traffic controller shutdown - * - * Step 6 continues here. Prepare jump to power management - * assembly code in internal SRAM. - * - * Since the omap_cpu_suspend routine has been copied to - * SRAM, we'll do an indirect procedure call to it and pass the - * contents of arm_idlect1 and arm_idlect2 so it can restore - * them when it wakes up and it will return. - */ - - arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1]; - arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2]; - - if (cpu_is_omap1510()) { - func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND); - } else if (cpu_is_omap1610() || cpu_is_omap1710()) { - func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND); - } else if (cpu_is_omap5912()) { - func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND); - } - - /* - * Step 6c: ARM and Traffic controller shutdown - * - * Jump to assembly code. The processor will stay there - * until wake up. - */ - - func_ptr(arg0, arg1); - - /* - * If we are here, processor is woken up! - */ - - if (cpu_is_omap1510()) { - /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */ - omap_writew(omap_readw(ULPD_POWER_CTRL) & - ~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL); - } else if (cpu_is_omap16xx()) { - /* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */ - omap_writew(omap_readw(ULPD_POWER_CTRL) & - ~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL); - } - - - /* Restore DSP clocks */ - omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2); - __raw_writew(save_dsp_idlect2, DSP_IDLECT2); - ARM_RESTORE(ARM_IDLECT2); - - /* - * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did - */ - - ARM_RESTORE(ARM_CKCTL); - ARM_RESTORE(ARM_EWUPCT); - ARM_RESTORE(ARM_RSTCT1); - ARM_RESTORE(ARM_RSTCT2); - ARM_RESTORE(ARM_SYSST); - ULPD_RESTORE(ULPD_CLOCK_CTRL); - ULPD_RESTORE(ULPD_STATUS_REQ); - - if (cpu_is_omap1510()) { - MPUI1510_RESTORE(MPUI_CTRL); - MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG); - MPUI1510_RESTORE(MPUI_DSP_API_CONFIG); - MPUI1510_RESTORE(EMIFS_CONFIG); - MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG); - MPUI1510_RESTORE(OMAP_IH1_MIR); - MPUI1510_RESTORE(OMAP_IH2_MIR); - } else if (cpu_is_omap16xx()) { - MPUI1610_RESTORE(MPUI_CTRL); - MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG); - MPUI1610_RESTORE(MPUI_DSP_API_CONFIG); - MPUI1610_RESTORE(EMIFS_CONFIG); - MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG); - - MPUI1610_RESTORE(OMAP_IH1_MIR); - MPUI1610_RESTORE(OMAP_IH2_0_MIR); - MPUI1610_RESTORE(OMAP_IH2_1_MIR); - MPUI1610_RESTORE(OMAP_IH2_2_MIR); - MPUI1610_RESTORE(OMAP_IH2_3_MIR); - } - - /* - * Reenable interrupts - */ - - local_irq_enable(); - local_fiq_enable(); - - printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev); - - if (machine_is_omap_osk()) { - /* Let LED1 (D9) blink again */ - tps65010_set_led(LED1, BLINK); - } -} - -#if defined(DEBUG) && defined(CONFIG_PROC_FS) -static int g_read_completed; - -/* - * Read system PM registers for debugging - */ -static int omap_pm_read_proc( - char *page_buffer, - char **my_first_byte, - off_t virtual_start, - int length, - int *eof, - void *data) -{ - int my_buffer_offset = 0; - char * const my_base = page_buffer; - - ARM_SAVE(ARM_CKCTL); - ARM_SAVE(ARM_IDLECT1); - ARM_SAVE(ARM_IDLECT2); - ARM_SAVE(ARM_EWUPCT); - ARM_SAVE(ARM_RSTCT1); - ARM_SAVE(ARM_RSTCT2); - ARM_SAVE(ARM_SYSST); - - ULPD_SAVE(ULPD_IT_STATUS); - ULPD_SAVE(ULPD_CLOCK_CTRL); - ULPD_SAVE(ULPD_SOFT_REQ); - ULPD_SAVE(ULPD_STATUS_REQ); - ULPD_SAVE(ULPD_DPLL_CTRL); - ULPD_SAVE(ULPD_POWER_CTRL); - - if (cpu_is_omap1510()) { - MPUI1510_SAVE(MPUI_CTRL); - MPUI1510_SAVE(MPUI_DSP_STATUS); - MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI1510_SAVE(MPUI_DSP_API_CONFIG); - MPUI1510_SAVE(EMIFF_SDRAM_CONFIG); - MPUI1510_SAVE(EMIFS_CONFIG); - } else if (cpu_is_omap16xx()) { - MPUI1610_SAVE(MPUI_CTRL); - MPUI1610_SAVE(MPUI_DSP_STATUS); - MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI1610_SAVE(MPUI_DSP_API_CONFIG); - MPUI1610_SAVE(EMIFF_SDRAM_CONFIG); - MPUI1610_SAVE(EMIFS_CONFIG); - } - - if (virtual_start == 0) { - g_read_completed = 0; - - my_buffer_offset += sprintf(my_base + my_buffer_offset, - "ARM_CKCTL_REG: 0x%-8x \n" - "ARM_IDLECT1_REG: 0x%-8x \n" - "ARM_IDLECT2_REG: 0x%-8x \n" - "ARM_EWUPCT_REG: 0x%-8x \n" - "ARM_RSTCT1_REG: 0x%-8x \n" - "ARM_RSTCT2_REG: 0x%-8x \n" - "ARM_SYSST_REG: 0x%-8x \n" - "ULPD_IT_STATUS_REG: 0x%-4x \n" - "ULPD_CLOCK_CTRL_REG: 0x%-4x \n" - "ULPD_SOFT_REQ_REG: 0x%-4x \n" - "ULPD_DPLL_CTRL_REG: 0x%-4x \n" - "ULPD_STATUS_REQ_REG: 0x%-4x \n" - "ULPD_POWER_CTRL_REG: 0x%-4x \n", - ARM_SHOW(ARM_CKCTL), - ARM_SHOW(ARM_IDLECT1), - ARM_SHOW(ARM_IDLECT2), - ARM_SHOW(ARM_EWUPCT), - ARM_SHOW(ARM_RSTCT1), - ARM_SHOW(ARM_RSTCT2), - ARM_SHOW(ARM_SYSST), - ULPD_SHOW(ULPD_IT_STATUS), - ULPD_SHOW(ULPD_CLOCK_CTRL), - ULPD_SHOW(ULPD_SOFT_REQ), - ULPD_SHOW(ULPD_DPLL_CTRL), - ULPD_SHOW(ULPD_STATUS_REQ), - ULPD_SHOW(ULPD_POWER_CTRL)); - - if (cpu_is_omap1510()) { - my_buffer_offset += sprintf(my_base + my_buffer_offset, - "MPUI1510_CTRL_REG 0x%-8x \n" - "MPUI1510_DSP_STATUS_REG: 0x%-8x \n" - "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n" - "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n" - "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n" - "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n", - MPUI1510_SHOW(MPUI_CTRL), - MPUI1510_SHOW(MPUI_DSP_STATUS), - MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG), - MPUI1510_SHOW(MPUI_DSP_API_CONFIG), - MPUI1510_SHOW(EMIFF_SDRAM_CONFIG), - MPUI1510_SHOW(EMIFS_CONFIG)); - } else if (cpu_is_omap16xx()) { - my_buffer_offset += sprintf(my_base + my_buffer_offset, - "MPUI1610_CTRL_REG 0x%-8x \n" - "MPUI1610_DSP_STATUS_REG: 0x%-8x \n" - "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n" - "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n" - "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n" - "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n", - MPUI1610_SHOW(MPUI_CTRL), - MPUI1610_SHOW(MPUI_DSP_STATUS), - MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG), - MPUI1610_SHOW(MPUI_DSP_API_CONFIG), - MPUI1610_SHOW(EMIFF_SDRAM_CONFIG), - MPUI1610_SHOW(EMIFS_CONFIG)); - } - - g_read_completed++; - } else if (g_read_completed >= 1) { - *eof = 1; - return 0; - } - g_read_completed++; - - *my_first_byte = page_buffer; - return my_buffer_offset; -} - -static void omap_pm_init_proc(void) -{ - struct proc_dir_entry *entry; - - entry = create_proc_read_entry("driver/omap_pm", - S_IWUSR | S_IRUGO, NULL, - omap_pm_read_proc, 0); -} - -#endif /* DEBUG && CONFIG_PROC_FS */ - -/* - * omap_pm_prepare - Do preliminary suspend work. - * @state: suspend state we're entering. - * - */ -//#include <asm/arch/hardware.h> - -static int omap_pm_prepare(suspend_state_t state) -{ - int error = 0; - - switch (state) - { - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - break; - - case PM_SUSPEND_DISK: - return -ENOTSUPP; - - default: - return -EINVAL; - } - - return error; -} - - -/* - * omap_pm_enter - Actually enter a sleep state. - * @state: State we're entering. - * - */ - -static int omap_pm_enter(suspend_state_t state) -{ - switch (state) - { - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - omap_pm_suspend(); - break; - - case PM_SUSPEND_DISK: - return -ENOTSUPP; - - default: - return -EINVAL; - } - - return 0; -} - - -/** - * omap_pm_finish - Finish up suspend sequence. - * @state: State we're coming out of. - * - * This is called after we wake back up (or if entering the sleep state - * failed). - */ - -static int omap_pm_finish(suspend_state_t state) -{ - return 0; -} - - -struct pm_ops omap_pm_ops ={ - .pm_disk_mode = 0, - .prepare = omap_pm_prepare, - .enter = omap_pm_enter, - .finish = omap_pm_finish, -}; - -static int __init omap_pm_init(void) -{ - printk("Power Management for TI OMAP.\n"); - pm_idle = omap_pm_idle; - /* - * We copy the assembler sleep/wakeup routines to SRAM. - * These routines need to be in SRAM as that's the only - * memory the MPU can see when it wakes up. - */ - -#ifdef CONFIG_ARCH_OMAP1510 - if (cpu_is_omap1510()) { - memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND, - omap1510_idle_loop_suspend, - omap1510_idle_loop_suspend_sz); - memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend, - omap1510_cpu_suspend_sz); - } else -#endif - if (cpu_is_omap1610() || cpu_is_omap1710()) { - memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND, - omap1610_idle_loop_suspend, - omap1610_idle_loop_suspend_sz); - memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend, - omap1610_cpu_suspend_sz); - } else if (cpu_is_omap5912()) { - memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND, - omap1610_idle_loop_suspend, - omap1610_idle_loop_suspend_sz); - memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend, - omap1610_cpu_suspend_sz); - } - - pm_set_ops(&omap_pm_ops); - -#if defined(DEBUG) && defined(CONFIG_PROC_FS) - omap_pm_init_proc(); -#endif - - return 0; -} -__initcall(omap_pm_init); - diff --git a/arch/arm/mach-omap/sleep.S b/arch/arm/mach-omap/sleep.S deleted file mode 100644 index 4d426d10582..00000000000 --- a/arch/arm/mach-omap/sleep.S +++ /dev/null @@ -1,314 +0,0 @@ -/* - * linux/arch/arm/mach-omap/sleep.S - * - * Low-level OMAP1510/1610 sleep/wakeUp support - * - * Initial SA1110 code: - * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> - * - * Adapted for PXA by Nicolas Pitre: - * Copyright (c) 2002 Monta Vista Software, Inc. - * - * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/config.h> -#include <linux/linkage.h> -#include <asm/assembler.h> -#include <asm/arch/io.h> -#include <asm/arch/pm.h> - - .text - -/* - * Forces OMAP into idle state - * - * omapXXXX_idle_loop_suspend() - * - * Note: This code get's copied to internal SRAM at boot. When the OMAP - * wakes up it continues execution at the point it went to sleep. - * - * Note: Because of slightly different configuration values we have - * processor specific functions here. - */ - -#ifdef CONFIG_ARCH_OMAP1510 -ENTRY(omap1510_idle_loop_suspend) - - stmfd sp!, {r0 - r12, lr} @ save registers on stack - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - @ get ARM_IDLECT2 into r2 - ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff - orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - @ get ARM_IDLECT1 into r1 - ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - orr r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - mov r5, #IDLE_WAIT_CYCLES & 0xff - orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 -l_1510: subs r5, r5, #1 - bne l_1510 -/* - * Let's wait for the next clock tick to wake us up. - */ - mov r0, #0 - mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt -/* - * omap1510_idle_loop_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. - */ - - @ restore ARM_IDLECT1 and ARM_IDLECT2 and return - @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 - strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - ldmfd sp!, {r0 - r12, pc} @ restore regs and return - -ENTRY(omap1510_idle_loop_suspend_sz) - .word . - omap1510_idle_loop_suspend -#endif /* CONFIG_ARCH_OMAP1510 */ - -#if defined(CONFIG_ARCH_OMAP16XX) -ENTRY(omap1610_idle_loop_suspend) - - stmfd sp!, {r0 - r12, lr} @ save registers on stack - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - @ get ARM_IDLECT2 into r2 - ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff - orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - @ get ARM_IDLECT1 into r1 - ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - orr r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - mov r5, #IDLE_WAIT_CYCLES & 0xff - orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 -l_1610: subs r5, r5, #1 - bne l_1610 -/* - * Let's wait for the next clock tick to wake us up. - */ - mov r0, #0 - mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt -/* - * omap1610_idle_loop_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. - */ - - @ restore ARM_IDLECT1 and ARM_IDLECT2 and return - @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 - strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - ldmfd sp!, {r0 - r12, pc} @ restore regs and return - -ENTRY(omap1610_idle_loop_suspend_sz) - .word . - omap1610_idle_loop_suspend -#endif /* CONFIG_ARCH_OMAP16XX */ - -/* - * Forces OMAP into deep sleep state - * - * omapXXXX_cpu_suspend() - * - * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed - * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1 - * in register r1. - * - * Note: This code get's copied to internal SRAM at boot. When the OMAP - * wakes up it continues execution at the point it went to sleep. - * - * Note: Because of errata work arounds we have processor specific functions - * here. They are mostly the same, but slightly different. - * - */ - -#ifdef CONFIG_ARCH_OMAP1510 -ENTRY(omap1510_cpu_suspend) - - @ save registers on stack - stmfd sp!, {r0 - r12, lr} - - @ load base address of Traffic Controller - mov r4, #TCMIF_ASM_BASE & 0xff000000 - orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000 - orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00 - - @ work around errata of OMAP1510 PDE bit for TC shut down - @ clear PDE bit - ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - bic r5, r5, #PDE_BIT & 0xff - str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ set PWD_EN bit - and r5, r5, #PWD_EN_BIT & 0xff - str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ prepare to put SDRAM into self-refresh manually - ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - orr r5, r5, #SELF_REFRESH_MODE & 0xff000000 - orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff - str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - - @ prepare to put EMIFS to Sleep - ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff - str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff - orr r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff - orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00 - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - mov r5, #IDLE_WAIT_CYCLES & 0xff - orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 -l_1510_2: - subs r5, r5, #1 - bne l_1510_2 -/* - * Let's wait for the next wake up event to wake us up. r0 can't be - * used here because r0 holds ARM_IDLECT1 - */ - mov r2, #0 - mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt -/* - * omap1510_cpu_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. - */ - strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - @ restore regs and return - ldmfd sp!, {r0 - r12, pc} - -ENTRY(omap1510_cpu_suspend_sz) - .word . - omap1510_cpu_suspend -#endif /* CONFIG_ARCH_OMAP1510 */ - -#if defined(CONFIG_ARCH_OMAP16XX) -ENTRY(omap1610_cpu_suspend) - - @ save registers on stack - stmfd sp!, {r0 - r12, lr} - - @ load base address of Traffic Controller - mov r4, #TCMIF_ASM_BASE & 0xff000000 - orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000 - orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00 - - @ prepare to put SDRAM into self-refresh manually - ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - orr r5, r5, #SELF_REFRESH_MODE & 0xff000000 - orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff - str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] - - @ prepare to put EMIFS to Sleep - ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff - str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] - - @ load base address of ARM_IDLECT1 and ARM_IDLECT2 - mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 - orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 - - @ turn off clock domains - mov r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff - orr r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00 - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ work around errata of OMAP1610/5912. Enable (!) peripheral - @ clock to let the chip go into deep sleep - ldrh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - orr r5,r5, #EN_PERCK_BIT & 0xff - strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - - @ request ARM idle - mov r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff - orr r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00 - strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - mov r5, #IDLE_WAIT_CYCLES & 0xff - orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 -l_1610_2: - subs r5, r5, #1 - bne l_1610_2 -/* - * Let's wait for the next wake up event to wake us up. r0 can't be - * used here because r0 holds ARM_IDLECT1 - */ - mov r2, #0 - mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt -/* - * omap1610_cpu_suspend()'s resume point. - * - * It will just start executing here, so we'll restore stuff from the - * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. - */ - strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] - strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] - - @ restore regs and return - ldmfd sp!, {r0 - r12, pc} - -ENTRY(omap1610_cpu_suspend_sz) - .word . - omap1610_cpu_suspend -#endif /* CONFIG_ARCH_OMAP16XX */ diff --git a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c deleted file mode 100644 index fd483ff9f8f..00000000000 --- a/arch/arm/mach-omap/usb.c +++ /dev/null @@ -1,593 +0,0 @@ -/* - * arch/arm/mach-omap/usb.c -- platform level USB initialization - * - * Copyright (C) 2004 Texas Instruments, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#undef DEBUG - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/usb_otg.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/system.h> -#include <asm/hardware.h> -#include <asm/mach-types.h> - -#include <asm/arch/mux.h> -#include <asm/arch/usb.h> -#include <asm/arch/board.h> - -/* These routines should handle the standard chip-specific modes - * for usb0/1/2 ports, covering basic mux and transceiver setup. - * - * Some board-*.c files will need to set up additional mux options, - * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. - */ - -/* TESTED ON: - * - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables - * - 5912 OSK OHCI (with usb0 standard-A), standard A-to-B cables - * - 5912 OSK UDC, with *nonstandard* A-to-A cable - * - 1510 Innovator UDC with bundled usb0 cable - * - 1510 Innovator OHCI with bundled usb1/usb2 cable - * - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS - * - 1710 custom development board using alternate pin group - * - 1710 H3 (with usb1 mini-AB) using standard Mini-B or OTG cables - */ - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_ARCH_OMAP_OTG - -static struct otg_transceiver *xceiv; - -/** - * otg_get_transceiver - find the (single) OTG transceiver driver - * - * Returns the transceiver driver, after getting a refcount to it; or - * null if there is no such transceiver. The caller is responsible for - * releasing that count. - */ -struct otg_transceiver *otg_get_transceiver(void) -{ - if (xceiv) - get_device(xceiv->dev); - return xceiv; -} -EXPORT_SYMBOL(otg_get_transceiver); - -int otg_set_transceiver(struct otg_transceiver *x) -{ - if (xceiv && x) - return -EBUSY; - xceiv = x; - return 0; -} -EXPORT_SYMBOL(otg_set_transceiver); - -#endif - -/*-------------------------------------------------------------------------*/ - -static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) -{ - u32 syscon1 = 0; - - if (nwires == 0) { - if (!cpu_is_omap15xx()) { - /* pulldown D+/D- */ - USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); - } - return 0; - } - - if (is_device) - omap_cfg_reg(W4_USB_PUEN); - - /* internal transceiver */ - if (nwires == 2) { - // omap_cfg_reg(P9_USB_DP); - // omap_cfg_reg(R8_USB_DM); - - if (cpu_is_omap15xx()) { - /* This works on 1510-Innovator */ - return 0; - } - - /* NOTES: - * - peripheral should configure VBUS detection! - * - only peripherals may use the internal D+/D- pulldowns - * - OTG support on this port not yet written - */ - - USB_TRANSCEIVER_CTRL_REG &= ~(7 << 4); - if (!is_device) - USB_TRANSCEIVER_CTRL_REG |= (3 << 1); - - return 3 << 16; - } - - /* alternate pin config, external transceiver */ - if (cpu_is_omap15xx()) { - printk(KERN_ERR "no usb0 alt pin config on 15xx\n"); - return 0; - } - - omap_cfg_reg(V6_USB0_TXD); - omap_cfg_reg(W9_USB0_TXEN); - omap_cfg_reg(W5_USB0_SE0); - - /* NOTE: SPEED and SUSP aren't configured here */ - - if (nwires != 3) - omap_cfg_reg(Y5_USB0_RCV); - if (nwires != 6) - USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; - - switch (nwires) { - case 3: - syscon1 = 2; - break; - case 4: - syscon1 = 1; - break; - case 6: - syscon1 = 3; - omap_cfg_reg(AA9_USB0_VP); - omap_cfg_reg(R9_USB0_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; - break; - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 0, nwires); - } - return syscon1 << 16; -} - -static u32 __init omap_usb1_init(unsigned nwires) -{ - u32 syscon1 = 0; - - if (nwires != 6 && !cpu_is_omap15xx()) - USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; - if (nwires == 0) - return 0; - - /* external transceiver */ - omap_cfg_reg(USB1_TXD); - omap_cfg_reg(USB1_TXEN); - if (cpu_is_omap15xx()) { - omap_cfg_reg(USB1_SEO); - omap_cfg_reg(USB1_SPEED); - // SUSP - } else if (cpu_is_omap1610() || cpu_is_omap5912()) { - omap_cfg_reg(W13_1610_USB1_SE0); - omap_cfg_reg(R13_1610_USB1_SPEED); - // SUSP - } else if (cpu_is_omap1710()) { - omap_cfg_reg(R13_1710_USB1_SE0); - // SUSP - } else { - pr_debug("usb unrecognized\n"); - } - if (nwires != 3) - omap_cfg_reg(USB1_RCV); - - switch (nwires) { - case 3: - syscon1 = 2; - break; - case 4: - syscon1 = 1; - break; - case 6: - syscon1 = 3; - omap_cfg_reg(USB1_VP); - omap_cfg_reg(USB1_VM); - if (!cpu_is_omap15xx()) - USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; - break; - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 1, nwires); - } - return syscon1 << 20; -} - -static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) -{ - u32 syscon1 = 0; - - /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */ - if (alt_pingroup || nwires == 0) - return 0; - if (nwires != 6 && !cpu_is_omap15xx()) - USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; - - /* external transceiver */ - if (cpu_is_omap15xx()) { - omap_cfg_reg(USB2_TXD); - omap_cfg_reg(USB2_TXEN); - omap_cfg_reg(USB2_SEO); - if (nwires != 3) - omap_cfg_reg(USB2_RCV); - /* there is no USB2_SPEED */ - } else if (cpu_is_omap16xx()) { - omap_cfg_reg(V6_USB2_TXD); - omap_cfg_reg(W9_USB2_TXEN); - omap_cfg_reg(W5_USB2_SE0); - if (nwires != 3) - omap_cfg_reg(Y5_USB2_RCV); - // FIXME omap_cfg_reg(USB2_SPEED); - } else { - pr_debug("usb unrecognized\n"); - } - // omap_cfg_reg(USB2_SUSP); - - switch (nwires) { - case 3: - syscon1 = 2; - break; - case 4: - syscon1 = 1; - break; - case 6: - syscon1 = 3; - if (cpu_is_omap15xx()) { - omap_cfg_reg(USB2_VP); - omap_cfg_reg(USB2_VM); - } else { - omap_cfg_reg(AA9_USB2_VP); - omap_cfg_reg(R9_USB2_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; - } - break; - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 2, nwires); - } - return syscon1 << 24; -} - -/*-------------------------------------------------------------------------*/ - -#if defined(CONFIG_USB_GADGET_OMAP) || \ - defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) || \ - (defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG)) -static void usb_release(struct device *dev) -{ - /* normally not freed */ -} -#endif - -#ifdef CONFIG_USB_GADGET_OMAP - -static struct resource udc_resources[] = { - /* order is significant! */ - { /* registers */ - .start = UDC_BASE, - .end = UDC_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, { /* general IRQ */ - .start = IH2_BASE + 20, - .flags = IORESOURCE_IRQ, - }, { /* PIO IRQ */ - .start = IH2_BASE + 30, - .flags = IORESOURCE_IRQ, - }, { /* SOF IRQ */ - .start = IH2_BASE + 29, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 udc_dmamask = ~(u32)0; - -static struct platform_device udc_device = { - .name = "omap_udc", - .id = -1, - .dev = { - .release = usb_release, - .dma_mask = &udc_dmamask, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(udc_resources), - .resource = udc_resources, -}; - -#endif - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - -/* The dmamask must be set for OHCI to work */ -static u64 ohci_dmamask = ~(u32)0; - -static struct resource ohci_resources[] = { - { - .start = OMAP_OHCI_BASE, - .end = OMAP_OHCI_BASE + 4096, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_USB_HHC_1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device ohci_device = { - .name = "ohci", - .id = -1, - .dev = { - .release = usb_release, - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(ohci_resources), - .resource = ohci_resources, -}; - -#endif - -#if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG) - -static struct resource otg_resources[] = { - /* order is significant! */ - { - .start = OTG_BASE, - .end = OTG_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, { - .start = IH2_BASE + 8, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device otg_device = { - .name = "omap_otg", - .id = -1, - .dev = { - .release = usb_release, - }, - .num_resources = ARRAY_SIZE(otg_resources), - .resource = otg_resources, -}; - -#endif - -/*-------------------------------------------------------------------------*/ - -#define ULPD_CLOCK_CTRL_REG __REG16(ULPD_CLOCK_CTRL) -#define ULPD_SOFT_REQ_REG __REG16(ULPD_SOFT_REQ) - - -// FIXME correct answer depends on hmc_mode, -// as does any nonzero value for config->otg port number -#ifdef CONFIG_USB_GADGET_OMAP -#define is_usb0_device(config) 1 -#else -#define is_usb0_device(config) 0 -#endif - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_ARCH_OMAP_OTG - -void __init -omap_otg_init(struct omap_usb_config *config) -{ - u32 syscon = OTG_SYSCON_1_REG & 0xffff; - int status; - int alt_pingroup = 0; - - /* NOTE: no bus or clock setup (yet?) */ - - syscon = OTG_SYSCON_1_REG & 0xffff; - if (!(syscon & OTG_RESET_DONE)) - pr_debug("USB resets not complete?\n"); - - // OTG_IRQ_EN_REG = 0; - - /* pin muxing and transceiver pinouts */ - if (config->pins[0] > 2) /* alt pingroup 2 */ - alt_pingroup = 1; - syscon |= omap_usb0_init(config->pins[0], is_usb0_device(config)); - syscon |= omap_usb1_init(config->pins[1]); - syscon |= omap_usb2_init(config->pins[2], alt_pingroup); - pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon); - OTG_SYSCON_1_REG = syscon; - - syscon = config->hmc_mode; - syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */; -#ifdef CONFIG_USB_OTG - if (config->otg) - syscon |= OTG_EN; -#endif - pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); - pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); - OTG_SYSCON_2_REG = syscon; - - printk("USB: hmc %d", config->hmc_mode); - if (alt_pingroup) - printk(", usb2 alt %d wires", config->pins[2]); - else if (config->pins[0]) - printk(", usb0 %d wires%s", config->pins[0], - is_usb0_device(config) ? " (dev)" : ""); - if (config->pins[1]) - printk(", usb1 %d wires", config->pins[1]); - if (!alt_pingroup && config->pins[2]) - printk(", usb2 %d wires", config->pins[2]); - if (config->otg) - printk(", Mini-AB on usb%d", config->otg - 1); - printk("\n"); - - /* leave USB clocks/controllers off until needed */ - ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; - ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; - ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; - syscon = OTG_SYSCON_1_REG; - syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; - -#ifdef CONFIG_USB_GADGET_OMAP - if (config->otg || config->register_dev) { - syscon &= ~DEV_IDLE_EN; - udc_device.dev.platform_data = config; - /* FIXME patch IRQ numbers for omap730 */ - status = platform_device_register(&udc_device); - if (status) - pr_debug("can't register UDC device, %d\n", status); - } -#endif - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - if (config->otg || config->register_host) { - syscon &= ~HST_IDLE_EN; - ohci_device.dev.platform_data = config; - if (cpu_is_omap730()) - ohci_resources[1].start = INT_730_USB_HHC_1; - status = platform_device_register(&ohci_device); - if (status) - pr_debug("can't register OHCI device, %d\n", status); - } -#endif - -#ifdef CONFIG_USB_OTG - if (config->otg) { - syscon &= ~OTG_IDLE_EN; - otg_device.dev.platform_data = config; - if (cpu_is_omap730()) - otg_resources[1].start = INT_730_USB_OTG; - status = platform_device_register(&otg_device); - if (status) - pr_debug("can't register OTG device, %d\n", status); - } -#endif - pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon); - OTG_SYSCON_1_REG = syscon; - - status = 0; -} - -#else -static inline void omap_otg_init(struct omap_usb_config *config) {} -#endif - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_ARCH_OMAP1510 - -#define ULPD_DPLL_CTRL_REG __REG16(ULPD_DPLL_CTRL) -#define DPLL_IOB (1 << 13) -#define DPLL_PLL_ENABLE (1 << 4) -#define DPLL_LOCK (1 << 0) - -#define ULPD_APLL_CTRL_REG __REG16(ULPD_APLL_CTRL) -#define APLL_NDPLL_SWITCH (1 << 0) - - -static void __init omap_1510_usb_init(struct omap_usb_config *config) -{ - int status; - unsigned int val; - - omap_usb0_init(config->pins[0], is_usb0_device(config)); - omap_usb1_init(config->pins[1]); - omap_usb2_init(config->pins[2], 0); - - val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1); - val |= (config->hmc_mode << 1); - omap_writel(val, MOD_CONF_CTRL_0); - - printk("USB: hmc %d", config->hmc_mode); - if (config->pins[0]) - printk(", usb0 %d wires%s", config->pins[0], - is_usb0_device(config) ? " (dev)" : ""); - if (config->pins[1]) - printk(", usb1 %d wires", config->pins[1]); - if (config->pins[2]) - printk(", usb2 %d wires", config->pins[2]); - printk("\n"); - - /* use DPLL for 48 MHz function clock */ - pr_debug("APLL %04x DPLL %04x REQ %04x\n", ULPD_APLL_CTRL_REG, - ULPD_DPLL_CTRL_REG, ULPD_SOFT_REQ_REG); - ULPD_APLL_CTRL_REG &= ~APLL_NDPLL_SWITCH; - ULPD_DPLL_CTRL_REG |= DPLL_IOB | DPLL_PLL_ENABLE; - ULPD_SOFT_REQ_REG |= SOFT_UDC_REQ | SOFT_DPLL_REQ; - while (!(ULPD_DPLL_CTRL_REG & DPLL_LOCK)) - cpu_relax(); - -#ifdef CONFIG_USB_GADGET_OMAP - if (config->register_dev) { - udc_device.dev.platform_data = config; - status = platform_device_register(&udc_device); - if (status) - pr_debug("can't register UDC device, %d\n", status); - /* udc driver gates 48MHz by D+ pullup */ - } -#endif - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - if (config->register_host) { - ohci_device.dev.platform_data = config; - status = platform_device_register(&ohci_device); - if (status) - pr_debug("can't register OHCI device, %d\n", status); - /* hcd explicitly gates 48MHz */ - } -#endif -} - -#else -static inline void omap_1510_usb_init(struct omap_usb_config *config) {} -#endif - -/*-------------------------------------------------------------------------*/ - -static struct omap_usb_config platform_data; - -static int __init -omap_usb_init(void) -{ - const struct omap_usb_config *config; - - config = omap_get_config(OMAP_TAG_USB, struct omap_usb_config); - if (config == NULL) { - printk(KERN_ERR "USB: No board-specific " - "platform config found\n"); - return -ENODEV; - } - platform_data = *config; - - if (cpu_is_omap730() || cpu_is_omap16xx()) - omap_otg_init(&platform_data); - else if (cpu_is_omap15xx()) - omap_1510_usb_init(&platform_data); - else { - printk(KERN_ERR "USB: No init for your chip yet\n"); - return -ENODEV; - } - return 0; -} - -subsys_initcall(omap_usb_init); |